OdXml.Mod 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057
  1. MODULE OdXml; (* System.Free DAVXml ~ DAVXml.Do DAVXml.File System.OpenKernelLog *)
  2. (* Create XML structures for DeltaV methods. *)
  3. IMPORT XML, XMLObjects, Streams, Files,
  4. XMLScanner, XMLParser, Strings, WebHTTP, OdUtil, KernelLog;
  5. CONST
  6. UpdateVersionTag * = "/version."; (* for allowing to send just a version number with DCT.Update. *)
  7. (***********************************************************************************)
  8. (* TYPE *)
  9. (***********************************************************************************)
  10. TYPE
  11. (* Take string and split it in segments delimited by a tag character. *)
  12. StringSplitter* =OBJECT
  13. VAR s: POINTER TO ARRAY OF CHAR; pos: LONGINT; done: BOOLEAN;
  14. PROCEDURE &Init*(CONST s: ARRAY OF CHAR);
  15. BEGIN
  16. IF s = "" THEN
  17. done := TRUE; (* In case of caller not testing for empty string. *)
  18. ELSE
  19. NEW(SELF.s, Strings.Length(s)+1); COPY(s, SELF.s^); pos := 0; done := FALSE;
  20. END;
  21. END Init;
  22. PROCEDURE Next*(tag: CHAR; VAR segment: ARRAY OF CHAR): BOOLEAN;
  23. VAR start: LONGINT;
  24. BEGIN
  25. IF done THEN segment[0] := 0X; RETURN FALSE; END;
  26. start := pos;
  27. LOOP
  28. IF s[pos] = 0X THEN segment[pos-start] := 0X; done := TRUE; RETURN TRUE;
  29. ELSIF s[pos] = tag THEN segment[pos-start] := 0X; INC(pos); RETURN TRUE;
  30. ELSE segment[pos-start] := s[pos]; INC(pos); END;
  31. END;
  32. END Next;
  33. END StringSplitter;
  34. (** NEW(doc, "D:merge", "D:source", "D:href", "http://svn.edgarschwarz.de/.....") *)
  35. Attr3Val1Req* =OBJECT(XML.Document);
  36. PROCEDURE &InitA3V1*(CONST a1, a2, a3, v1: ARRAY OF CHAR); (* http://<host>/>url> *)
  37. VAR el1, el2, el3: XML.Element; ac1: XML.ArrayChars;
  38. BEGIN Init();
  39. SELF.AddContent(xmlDecl);
  40. NEW(el1); el1.SetName(a1); el1.SetAttributeValue("xmlns:D", "DAV:"); SELF.AddContent(el1);
  41. NEW(el2); el2.SetName(a2); el1.AddContent(el2);
  42. NEW(el3); el3.SetName(a3); el2.AddContent(el3);
  43. NEW(ac1); ac1.SetStr(v1); el3.AddContent(ac1);
  44. END InitA3V1;
  45. END Attr3Val1Req;
  46. (** NEW(doc, "D:merge", "D:source", "D:href", "http://svn.edgarschwarz.de/.....") *)
  47. MergeSvnReq* =OBJECT(XML.Document);
  48. PROCEDURE &InitMergeSvnReq*(CONST a1, a2, a3, v1: ARRAY OF CHAR); (* http://<host>/>url> *)
  49. VAR el1, el2, el3: XML.Element; ac1: XML.ArrayChars;
  50. BEGIN Init();
  51. SELF.AddContent(xmlDecl);
  52. NEW(el1); el1.SetName(a1); el1.SetAttributeValue("xmlns:D", "DAV:"); SELF.AddContent(el1);
  53. NEW(el2); el2.SetName(a2); el1.AddContent(el2);
  54. NEW(el3); el3.SetName(a3); el2.AddContent(el3);
  55. NEW(ac1); ac1.SetStr(v1); el3.AddContent(ac1);
  56. (* more stuff *)
  57. NEW(el2); el2.SetName("D:no-auto-merge"); el1.AddContent(el2);
  58. NEW(el2); el2.SetName("D:no-checkout"); el1.AddContent(el2);
  59. NEW(el2); el2.SetName("D:prop"); el1.AddContent(el2);
  60. NEW(el3); el3.SetName("D:checked-in"); el2.AddContent(el3);
  61. NEW(el3); el3.SetName("D:version-name"); el2.AddContent(el3);
  62. NEW(el3); el3.SetName("D:resourcety"); el2.AddContent(el3);
  63. NEW(el3); el3.SetName("D:creationdate"); el2.AddContent(el3);
  64. NEW(el3); el3.SetName("D:creator-displayname"); el2.AddContent(el3);
  65. END InitMergeSvnReq;
  66. END MergeSvnReq;
  67. (* XML request and response objects *)
  68. ErrorRes* =OBJECT(XML.Document);
  69. PROCEDURE &Init1*(CONST error: ARRAY OF CHAR);
  70. VAR err : XML.Element;
  71. BEGIN Init();
  72. SELF.AddContent(xmlDecl);
  73. NEW(err); err.SetName("D:error"); err.SetAttributeValue("xmlns:D", "DAV:"); SELF.AddContent(err);
  74. err.AddContent(NameContent(error));
  75. END Init1;
  76. END ErrorRes;
  77. BaselineControlReq* =OBJECT(XML.Document);
  78. PROCEDURE &Init1*(CONST host, baseline: ARRAY OF CHAR);
  79. VAR bc, b, h: XML.Element; ac: XML.ArrayChars; acStr: ARRAY 128 OF CHAR;
  80. BEGIN Init();
  81. SELF.AddContent(xmlDecl);
  82. (* baseline-control *)
  83. NEW(bc); bc.SetName("D:baseline-control"); bc.SetAttributeValue("xmlns:D", "DAV:"); SELF.AddContent(bc);
  84. (* baseline-control.baseline *)
  85. NEW(b); b.SetName("D:baseline"); bc.AddContent(b);
  86. (* baseline-control.baseline.href *)
  87. NEW(h); h.SetName("D:href"); b.AddContent(h);
  88. acStr := "http://"; Strings.Append(acStr, host); Strings.Append(acStr, baseline);
  89. NEW(ac); ac.SetStr(acStr); h.AddContent(ac);
  90. END Init1;
  91. END BaselineControlReq;
  92. (* Baseline URL is given in request header. *)
  93. BaselineReportReq* =OBJECT(XML.Document);
  94. PROCEDURE &Init*;
  95. VAR br: XML.Element;
  96. BEGIN Init^();
  97. SELF.AddContent(xmlDecl);
  98. (* baseline-report *)
  99. NEW(br); br.SetName("D:baseline-report"); br.SetAttributeValue("xmlns:D", "DAV:"); SELF.AddContent(br);
  100. END Init;
  101. END BaselineReportReq;
  102. (* configuration-report response. Modeled after version-tree. *)
  103. ConfigurationReportRes* =OBJECT(XML.Document);
  104. VAR conf: ARRAY 128 OF CHAR;
  105. hostPrefix: ARRAY 64 OF CHAR;
  106. PROCEDURE &Init1*(CONST hostName, conf: ARRAY OF CHAR);
  107. VAR ms: XML.Element;
  108. BEGIN (*Init^(); *) Init(); (*???*)
  109. hostPrefix := "http://"; Strings.Append(hostPrefix, hostName);
  110. COPY(conf, SELF.conf); SELF.AddContent(xmlDecl);
  111. NEW(ms); ms.SetName("D:multistatus"); ms.SetAttributeValue("xmlns:D", "DAV:"); SELF.AddContent(ms);
  112. END Init1;
  113. (* Info on VCR together with it's current state. *)
  114. PROCEDURE addVcrState*(CONST host: ARRAY OF CHAR; VAR ms: XML.Element; CONST res, hist : ARRAY OF CHAR; VAR state: ARRAY OF CHAR);
  115. VAR r, h, ps, v, vs, s: XML.Element; ac: XML.ArrayChars; acStr: ARRAY 128 OF CHAR; statusStr: ARRAY 64 OF CHAR;
  116. BEGIN
  117. NEW(r); r.SetName("D:response"); ms.AddContent(r);
  118. (* response.href *)
  119. NEW(h); h.SetName("D:href"); r.AddContent(h);
  120. COPY(hostPrefix, acStr); Strings.Append(acStr, conf); Strings.Append(acStr, '/'); Strings.Append(acStr, res);
  121. NEW(ac); ac.SetStr(acStr); h.AddContent(ac);
  122. (* response.propstat *)
  123. NEW(ps); ps.SetName("D:propstat"); r.AddContent(ps);
  124. (* response.propstat.version *)
  125. NEW(v); v.SetName("D:version"); ps.AddContent(v);
  126. acStr := "http://"; Strings.Append(acStr, host); Strings.Append(acStr, hist);
  127. NEW(ac); ac.SetStr(acStr); v.AddContent(ac);
  128. (* response.propstat.vcrstatus *)
  129. NEW(vs); vs.SetName("D:vcr-status"); ps.AddContent(vs);
  130. IF state = "frozen" THEN COPY("checked-in", state); ELSIF state = "thawed" THEN COPY("checked-out", state); END;
  131. NEW(ac); ac.SetStr(state); vs.AddContent(ac);
  132. (* response.propstat.status*)
  133. NEW(s); s.SetName("D:status"); ps.AddContent(s);
  134. NEW(ac); statusStr := "HTTP/1.1 200 OK"; ac.SetStr(statusStr); s.AddContent(ac);
  135. END addVcrState;
  136. END ConfigurationReportRes;
  137. (* baseline-report response. Like configuration-report response without state. *)
  138. BaselineReportRes* =OBJECT(ConfigurationReportRes);
  139. (* Collect info on VCR. *)
  140. PROCEDURE addVcr*(CONST host: ARRAY OF CHAR; VAR ms: XML.Element; CONST res, hist: ARRAY OF CHAR);
  141. VAR r, h, ps, v, s : XML.Element; ac: XML.ArrayChars; acStr: ARRAY 128 OF CHAR; statusStr: ARRAY 64 OF CHAR;
  142. BEGIN
  143. NEW(r); r.SetName("D:response"); ms.AddContent(r);
  144. (* response.href *)
  145. NEW(h); h.SetName("D:href"); r.AddContent(h);
  146. acStr := "http://"; Strings.Append(acStr, host); Strings.Append(acStr, conf); Strings.Append(acStr, '/'); Strings.Append(acStr, res);
  147. NEW(ac); ac.SetStr(acStr); h.AddContent(ac);
  148. (* response.propstat *)
  149. NEW(ps); ps.SetName("D:propstat"); r.AddContent(ps);
  150. (* response.propstat.version *)
  151. NEW(v); v.SetName("D:version"); ps.AddContent(v);
  152. acStr := "http://"; Strings.Append(acStr, host); Strings.Append(acStr, hist);
  153. NEW(ac); ac.SetStr(acStr); v.AddContent(ac);
  154. (* response.propstat.status*)
  155. NEW(s); s.SetName("D:status"); ps.AddContent(s);
  156. NEW(ac); statusStr := "HTTP/1.1 200 OK"; ac.SetStr(statusStr); s.AddContent(ac);
  157. END addVcr;
  158. END BaselineReportRes;
  159. (* Checkout with activity
  160. <?xml version="1.0" encoding="utf-8" ?>
  161. <D:checkout xmlns:D="DAV:">
  162. <D:activity-set>
  163. <D:href>http://repo.webdav.org/act/fix-bug-23</D:href>
  164. </D:activity-set>
  165. </D:checkout>
  166. *)
  167. CheckoutReq* =OBJECT(XML.Document);
  168. PROCEDURE &Init1*(CONST host, activity: ARRAY OF CHAR); (* http://<host>/>url> *)
  169. VAR co, as, h: XML.Element; ac: XML.ArrayChars;
  170. BEGIN Init();
  171. SELF.AddContent(xmlDecl);
  172. (* checkout *)
  173. NEW(co); co.SetName("D:checkout"); co.SetAttributeValue("xmlns:D", "DAV:"); SELF.AddContent(co);
  174. (* checkout.activity-set *)
  175. NEW(as); as.SetName("D:activity-set"); co.AddContent(as);
  176. (* checkout.activity-set.href *)
  177. NEW(h); h.SetName("D:href"); as.AddContent(h);
  178. (* checkout.activity-set.href := activity; *)
  179. NEW(ac); ac.SetStr(activity); h.AddContent(ac);
  180. END Init1;
  181. END CheckoutReq;
  182. (* compare-baseline report response. Similar to configuration-report response.
  183. TODO: own sections for added, delete, ...
  184. compare-baseline-report
  185. (added|deleted)-version
  186. href <resource>
  187. changed-version
  188. href <from>
  189. href <to>
  190. *)
  191. CompareBaselineReportRes* =OBJECT(ConfigurationReportRes);
  192. VAR type * : ARRAY 16 OF CHAR;
  193. (* Scheint nicht zu tun. Compiler meckert.
  194. (* Override ConfigurationReportRes. *)
  195. PROCEDURE &Init1*(hostName, conf: ARRAY OF CHAR);
  196. VAR root: XML.Element;
  197. BEGIN Init();
  198. COPY(hostName, SELF.hostName);
  199. COPY(conf, SELF.conf); SELF.AddContent(xmlDecl);
  200. NEW(root); root.SetName("D:compare-baseline-report"); root.SetAttributeValue("xmlns:D", "DAV:");
  201. SELF.AddContent(root);
  202. END Init1;
  203. *)
  204. (* Collect info on VCR. ms = multistatus*)
  205. PROCEDURE addVcrType*(VAR ms: XML.Element; CONST type, from, to: ARRAY OF CHAR);
  206. CONST Hist = "/hist/";
  207. VAR typeEl, hrefEl: XML.Element; ac: XML.ArrayChars; acStr: ARRAY 128 OF CHAR;
  208. typeStr: ARRAY 32 OF CHAR;
  209. BEGIN
  210. (* <type>-version *)
  211. COPY("D:", typeStr); Strings.Append(typeStr, type); Strings.Append(typeStr, "-version");
  212. NEW(typeEl); typeEl.SetName(typeStr); ms.AddContent(typeEl);
  213. IF type = "changed" THEN (* from *)
  214. (* <type>-version.href *)
  215. NEW(hrefEl); hrefEl.SetName("D:href"); typeEl.AddContent(hrefEl);
  216. COPY(hostPrefix, acStr); Strings.Append(acStr, Hist); Strings.Append(acStr, from);
  217. NEW(ac); ac.SetStr(acStr); hrefEl.AddContent(ac);
  218. END;
  219. IF (type = "changed") OR (type = "added") OR (type = "deleted") THEN
  220. NEW(hrefEl); hrefEl.SetName("D:href"); typeEl.AddContent(hrefEl);
  221. COPY(hostPrefix, acStr); Strings.Append(acStr, Hist); Strings.Append(acStr, to);
  222. NEW(ac); ac.SetStr(acStr); hrefEl.AddContent(ac);
  223. ELSE
  224. HALT(99);
  225. END;
  226. END addVcrType;
  227. END CompareBaselineReportRes;
  228. VersionTreeRes* =OBJECT(XML.Document);
  229. VAR hist: ARRAY 128 OF CHAR;
  230. PROCEDURE &Init1*(CONST hist: ARRAY OF CHAR);
  231. VAR ms: XML.Element;
  232. BEGIN (*Init^(); *) Init(); (*???*)
  233. COPY(hist, SELF.hist); SELF.AddContent(xmlDecl);
  234. NEW(ms); ms.SetName("D:multistatus"); ms.SetAttributeValue("xmlns:D", "DAV:"); SELF.AddContent(ms);
  235. END Init1;
  236. PROCEDURE addVersion*(CONST host, ver: ARRAY OF CHAR; CONST author, date, logText: ARRAY OF CHAR);
  237. CONST Hist = "/hist/";
  238. VAR root, r, h, ps, p, s, e: XML.Element; ac: XML.ArrayChars; acStr: ARRAY 128 OF CHAR; statusStr: ARRAY 64 OF CHAR;
  239. BEGIN root := SELF.GetRoot();
  240. NEW(r); r.SetName("D:response"); root.AddContent(r);
  241. (* response.href *)
  242. NEW(h); h.SetName("D:href"); r.AddContent(h);
  243. acStr := "http://"; Strings.Append(acStr, host); Strings.Append(acStr, Hist);
  244. Strings.Append(acStr, hist);
  245. Strings.Append(acStr, '.'); Strings.Append(acStr, ver);
  246. NEW(ac); ac.SetStr(acStr); h.AddContent(ac);
  247. (* response.propstat *)
  248. NEW(ps); ps.SetName("D:propstat"); r.AddContent(ps);
  249. (* response.propstat.prop *)
  250. NEW(p); p.SetName("D:prop"); ps.AddContent(p);
  251. (* response.propstat.prop.(version-name|creator-displayname|version-time|comment) *)
  252. NEW(e); e.SetName("D:version-name"); p.AddContent(e);
  253. NEW(ac); ac.SetStr(ver); e.AddContent(ac);
  254. NEW(e); e.SetName("D:creator-displayname"); p.AddContent(e);
  255. NEW(ac); ac.SetStr(author); e.AddContent(ac);
  256. NEW(e); e.SetName("D:version-time"); p.AddContent(e);
  257. NEW(ac); ac.SetStr(date); e.AddContent(ac);
  258. NEW(e); e.SetName("D:comment"); p.AddContent(e);
  259. NEW(ac); ac.SetStr(logText); e.AddContent(ac);
  260. (* response.propstat.status*)
  261. NEW(s); s.SetName("D:status"); ps.AddContent(s);
  262. NEW(ac); statusStr := "HTTP/1.1 200 OK"; ac.SetStr(statusStr); s.AddContent(ac);
  263. END addVersion;
  264. END VersionTreeRes;
  265. PropfindRes* =OBJECT(XML.Document);
  266. VAR url: ARRAY 128 OF CHAR;
  267. PROCEDURE &Init1*(CONST url: ARRAY OF CHAR);
  268. VAR ms: XML.Element;
  269. BEGIN (* Init^(); *) Init(); (*???*)
  270. COPY(url, SELF.url); SELF.AddContent(xmlDecl);
  271. NEW(ms); ms.SetName("D:multistatus"); ms.SetAttributeValue("xmlns:D", "DAV:"); SELF.AddContent(ms);
  272. END Init1;
  273. PROCEDURE addVersion*(CONST ver, author, date, logText, state, dateTime: ARRAY OF CHAR; length: LONGINT);
  274. VAR root, r, h, ps, p, s, e: XML.Element; ac: XML.ArrayChars; acStr: ARRAY 128 OF CHAR; statusStr: ARRAY 64 OF CHAR;
  275. lengthStr: ARRAY 16 OF CHAR;
  276. BEGIN root := SELF.GetRoot();
  277. NEW(r); r.SetName("D:response"); root.AddContent(r);
  278. (* response.href *)
  279. NEW(h); h.SetName("D:href"); r.AddContent(h);
  280. COPY(url, acStr);
  281. NEW(ac); ac.SetStr(acStr); h.AddContent(ac);
  282. (* response.propstat *)
  283. NEW(ps); ps.SetName("D:propstat"); r.AddContent(ps);
  284. (* response.propstat.prop *)
  285. NEW(p); p.SetName("D:prop"); ps.AddContent(p);
  286. (* response.propstat.prop.(version-name|creator-displayname|version-time|comment) *)
  287. NEW(e); e.SetName("D:version-name"); p.AddContent(e);
  288. NEW(ac); ac.SetStr(ver); e.AddContent(ac);
  289. NEW(e); e.SetName("D:creator-displayname"); p.AddContent(e);
  290. NEW(ac); ac.SetStr(author); e.AddContent(ac);
  291. NEW(e); e.SetName("D:version-time"); p.AddContent(e);
  292. NEW(ac); ac.SetStr(date); e.AddContent(ac);
  293. NEW(e); e.SetName("D:comment"); p.AddContent(e);
  294. NEW(ac); ac.SetStr(logText); e.AddContent(ac);
  295. IF (state = "frozen") OR (state = "thawed") THEN
  296. IF state = "frozen" THEN
  297. NEW(e); e.SetName("D:checked-in"); p.AddContent(e);
  298. ELSIF state = "thawed" THEN
  299. NEW(e); e.SetName("D:checked-out"); p.AddContent(e);
  300. END;
  301. NEW(ac); COPY(url, acStr); Strings.Append(acStr, "."); Strings.Append(acStr, ver);
  302. ac.SetStr(acStr); e.AddContent(ac);
  303. END;
  304. (* response.propstat.prop.(getlastmodified|getcontentlength) *)
  305. NEW(e); e.SetName("D:getcontentlength"); p.AddContent(e);
  306. NEW(ac); Strings.IntToStr(length, lengthStr); ac.SetStr(lengthStr); e.AddContent(ac);
  307. NEW(e); e.SetName("D:getlastmodified"); p.AddContent(e);
  308. NEW(ac); ac.SetStr(dateTime); e.AddContent(ac);
  309. (* response.propstat.status*)
  310. NEW(s); s.SetName("D:status"); ps.AddContent(s);
  311. NEW(ac); statusStr := "HTTP/1.1 200 OK"; ac.SetStr(statusStr); s.AddContent(ac);
  312. END addVersion;
  313. END PropfindRes;
  314. PropfindCollectionRes* =OBJECT(XML.Document);
  315. VAR collection: ARRAY 128 OF CHAR;
  316. OKPs, notFoundPs, OKP, notFoundP, response: XML.Element;
  317. PROCEDURE &Init1*(CONST collection: ARRAY OF CHAR);
  318. VAR ms: XML.Element;
  319. BEGIN (* Init^(); *) Init(); (*???*)
  320. COPY(collection, SELF.collection); SELF.AddContent(xmlDecl);
  321. NEW(ms); ms.SetName("D:multistatus"); ms.SetAttributeValue("xmlns:D", "DAV:"); SELF.AddContent(ms);
  322. END Init1;
  323. (* Create a new response element with a href. This reponse element will be use by the following addOK,
  324. addNotFound, ... *)
  325. PROCEDURE addResponse * (CONST href: ARRAY OF CHAR);
  326. VAR multistatus, h: XML.Element; ac: XML.ArrayChars; acStr: ARRAY 128 OF CHAR;
  327. BEGIN
  328. multistatus := SELF.GetRoot();
  329. NEW(response); response.SetName("D:response"); multistatus.AddContent(response);
  330. (* response.href *)
  331. NEW(h); h.SetName("D:href"); response.AddContent(h);
  332. COPY(href, acStr);
  333. NEW(ac); ac.SetStr(acStr); h.AddContent(ac);
  334. OKPs := NIL; notFoundPs := NIL; OKP := NIL; notFoundP := NIL;
  335. END addResponse;
  336. (* Create a propstat with a OK status. Use the prop to add the following simple properties. *)
  337. PROCEDURE addOK * (name: ARRAY OF CHAR; CONST value: ARRAY OF CHAR);
  338. VAR status, propEl: XML.Element; ac: XML.ArrayChars; acStr: ARRAY 128 OF CHAR;
  339. BEGIN
  340. IF OKPs = NIL THEN (* Create propstat for successful properties. *)
  341. (* response.propstat *)
  342. NEW(OKPs); OKPs.SetName("D:propstat"); response.AddContent(OKPs);
  343. (* response.propstat.prop *)
  344. NEW(OKP); OKP.SetName("D:prop"); OKPs.AddContent(OKP);
  345. (* response.propstat.status *)
  346. NEW(status); status.SetName("D:status"); OKPs.AddContent(status);
  347. NEW(ac); acStr := "HTTP/1.1 200 OK"; ac.SetStr(acStr); status.AddContent(ac);
  348. END;
  349. IF Strings.Pos("DAV:", name) = 0 THEN Strings.Delete(name, 1, 2); END;
  350. NEW(propEl); propEl.SetName(name); OKP.AddContent(propEl);
  351. IF value # "" THEN
  352. NEW(ac); ac.SetStr(value); propEl.AddContent(ac);
  353. END;
  354. END addOK;
  355. PROCEDURE addResourceType * (CONST type: ARRAY OF CHAR);
  356. VAR coll, status, propEl: XML.Element; ac: XML.ArrayChars; acStr: ARRAY 128 OF CHAR;
  357. BEGIN
  358. IF OKPs = NIL THEN (* Create propstat for successful properties. *)
  359. (* response.propstat *)
  360. NEW(OKPs); OKPs.SetName("D:propstat"); response.AddContent(OKPs);
  361. (* response.propstat.prop *)
  362. NEW(OKP); OKP.SetName("D:prop"); OKPs.AddContent(OKP);
  363. (* response.propstat.status *)
  364. NEW(status); status.SetName("D:status"); OKPs.AddContent(status);
  365. NEW(ac); acStr := "HTTP/1.1 200 OK"; ac.SetStr(acStr); status.AddContent(ac);
  366. END;
  367. NEW(propEl); propEl.SetName("D:resourcetype"); OKP.AddContent(propEl);
  368. IF type = "collection" THEN
  369. (* <resourcetype> <collection/> </resourcetype> *)
  370. NEW(coll); coll.SetName("D:collection"); propEl.AddContent(coll);
  371. END;
  372. END addResourceType;
  373. (* Create a propstat with a OK status. Use the prop to add the following simple properties. *)
  374. PROCEDURE addNotFound * (name: ARRAY OF CHAR);
  375. VAR status, propEl: XML.Element; ac: XML.ArrayChars; acStr: ARRAY 128 OF CHAR;
  376. BEGIN
  377. IF notFoundPs = NIL THEN (* Create propstat for NotFound properties. *)
  378. (* response.propstat *)
  379. NEW(notFoundPs); notFoundPs.SetName("D:propstat"); response.AddContent(notFoundPs);
  380. (* response.propstat.prop *)
  381. NEW(notFoundP); notFoundP.SetName("D:prop"); notFoundPs.AddContent(notFoundP);
  382. (* response.propstat.status *)
  383. NEW(status); status.SetName("D:status"); notFoundPs.AddContent(status);
  384. NEW(ac); acStr := "HTTP/1.1 404 Not Found"; ac.SetStr(acStr); status.AddContent(ac);
  385. END;
  386. IF Strings.Pos("DAV:", name) = 0 THEN Strings.Delete(name, 1, 2); END;
  387. NEW(propEl); propEl.SetName(name); notFoundP.AddContent(propEl);
  388. END addNotFound;
  389. PROCEDURE addConfiguration*(CONST name, version, state: ARRAY OF CHAR);
  390. VAR multistatus, r, h, ps, p, s, e: XML.Element; ac: XML.ArrayChars;
  391. acStr: ARRAY 128 OF CHAR; statusStr: ARRAY 64 OF CHAR;
  392. BEGIN multistatus := SELF.GetRoot();
  393. NEW(r); r.SetName("D:response"); multistatus.AddContent(r);
  394. (* response.href *)
  395. NEW(h); h.SetName("D:href"); r.AddContent(h);
  396. COPY(name, acStr);
  397. NEW(ac); ac.SetStr(acStr); h.AddContent(ac);
  398. (* response.propstat *)
  399. NEW(ps); ps.SetName("D:propstat"); r.AddContent(ps);
  400. (* response.propstat.prop *)
  401. NEW(p); p.SetName("D:prop"); ps.AddContent(p);
  402. (* response.propstat.prop.version *)
  403. NEW(e); e.SetName("D:version"); p.AddContent(e);
  404. NEW(ac); ac.SetStr(version); e.AddContent(ac);
  405. (* response.propstat.prop.state *)
  406. NEW(e); e.SetName("D:state"); p.AddContent(e);
  407. NEW(ac); ac.SetStr(state); e.AddContent(ac);
  408. (* response.propstat.prop.resourcetype *)
  409. NEW(e); e.SetName("D:resourcetype"); p.AddContent(e);
  410. NEW(ac); acStr := "collection"; ac.SetStr(acStr); e.AddContent(ac);
  411. (* response.propstat.status *)
  412. NEW(s); s.SetName("D:status"); ps.AddContent(s);
  413. NEW(ac); statusStr := "HTTP/1.1 200 OK"; ac.SetStr(statusStr); s.AddContent(ac);
  414. END addConfiguration;
  415. (** Add information for a collection member
  416. <D:multistatus xmlns="DAV:">
  417. <D:response>
  418. <D:href>http://127.0.0.1/bl0/bl1</href>
  419. <D:propstat>
  420. <D:prop>
  421. <D:getcontentlength>0</getcontentlength>
  422. <D:getlastmodified>04.Jun.2003 16:38:12</D:getlastmodified>
  423. <D:getlastmodified>Tue, 11 Mar 2003 14:16:03 GMT</D:getlastmodified>
  424. <D:displayname>bl1<Displayname>
  425. <D:resourcetype>
  426. <D:collection />
  427. </D:resourcetype>
  428. <D:resourcetype /> for files.
  429. </D:prop>
  430. <D:status>HTTP/1.1 200 OK</D:status>
  431. </D:propstat>
  432. </D:response>
  433. *)
  434. PROCEDURE addMember*(CONST name, type, dateTime: ARRAY OF CHAR; length: LONGINT);
  435. VAR root, r, h, ps, p, s, rt, e: XML.Element; ac: XML.ArrayChars;
  436. acStr: ARRAY 128 OF CHAR; statusStr: ARRAY 64 OF CHAR; lengthStr: ARRAY 16 OF CHAR;
  437. BEGIN root := SELF.GetRoot();
  438. NEW(r); r.SetName("D:response"); root.AddContent(r);
  439. (* response.href *)
  440. NEW(h); h.SetName("D:href"); r.AddContent(h);
  441. COPY(name, acStr);
  442. NEW(ac); ac.SetStr(acStr); h.AddContent(ac);
  443. (* response.propstat *)
  444. NEW(ps); ps.SetName("D:propstat"); r.AddContent(ps);
  445. (* response.propstat.prop *)
  446. NEW(p); p.SetName("D:prop"); ps.AddContent(p);
  447. (* response.propstat.prop.(getlastmodified|getcontentlength) *)
  448. NEW(e); e.SetName("D:getcontentlength"); p.AddContent(e);
  449. NEW(ac); Strings.IntToStr(length, lengthStr); ac.SetStr(lengthStr); e.AddContent(ac);
  450. NEW(e); e.SetName("D:getlastmodified"); p.AddContent(e);
  451. NEW(ac); ac.SetStr(dateTime); e.AddContent(ac);
  452. (* response.propstat.prop.displayname *)
  453. NEW(e); e.SetName("D:displayname"); p.AddContent(e);
  454. Files.SplitPath(name, acStr, statusStr);
  455. NEW(ac); ac.SetStr(statusStr); e.AddContent(ac);
  456. (* response.propstat.prop.resourcetype *)
  457. NEW(rt); rt.SetName("D:resourcetype"); p.AddContent(rt);
  458. IF type = "collection" THEN
  459. (* <resourcetype> <collection/> </resourcetype> *)
  460. NEW(e); e.SetName("D:collection"); rt.AddContent(e);
  461. END;
  462. (* response.propstat.status*)
  463. NEW(s); s.SetName("D:status"); ps.AddContent(s);
  464. NEW(ac); statusStr := "HTTP/1.1 200 OK"; ac.SetStr(statusStr); s.AddContent(ac);
  465. END addMember;
  466. END PropfindCollectionRes;
  467. (** Scanner and Parser which have my error procedure which doesn't HALT(99) *)
  468. Scanner * = OBJECT (XMLScanner.Scanner)
  469. PROCEDURE &Init*(fr: Streams.Reader);
  470. BEGIN
  471. Init^(fr);
  472. reportError := XMLReportError;
  473. END Init;
  474. END Scanner;
  475. Parser * = OBJECT (XMLParser.Parser)
  476. PROCEDURE &Init*(s: XMLScanner.Scanner);
  477. BEGIN
  478. Init^(s);
  479. reportError := XMLReportError;
  480. END Init;
  481. END Parser;
  482. (***********************************************************************************)
  483. (* VAR *)
  484. (***********************************************************************************)
  485. VAR
  486. xmlDecl: XML.XMLDecl;
  487. TYPE
  488. OdXml* = OBJECT
  489. VAR
  490. showTree* : PROCEDURE (doc: XML.Document);
  491. logW: Streams.Writer;
  492. xmlns* : WebHTTP.AdditionalField; (* collect XML namespaces. *)
  493. PROCEDURE &Init*;
  494. BEGIN
  495. showTree := NIL;
  496. xmlns := NIL;
  497. NEW(logW, KernelLog.Send, 512);
  498. END Init;
  499. (***********************************************************************************)
  500. (* PROCEDURE *)
  501. (***********************************************************************************)
  502. PROCEDURE ShowDAVError * (doc: XML.Document): BOOLEAN;
  503. VAR
  504. el, child: XML.Element; elName, msg: OdUtil.Line;
  505. BEGIN
  506. el := doc.GetRoot();
  507. elName := AbsXmlName(el.GetName());
  508. IF elName = "DAV:error" THEN
  509. child := GetFirstChild(el);
  510. IF child # NIL THEN (* regular error code *)
  511. msg := AbsXmlName(child.GetName());
  512. ELSE (* My server at the moment. *)
  513. GetCharData(el, msg);
  514. END;
  515. OdUtil.Msg2("DAV:error =", msg);
  516. RETURN TRUE;
  517. END;
  518. RETURN FALSE;
  519. END ShowDAVError;
  520. PROCEDURE IsDAVError * (doc: XML.Document; VAR name: ARRAY OF CHAR): BOOLEAN;
  521. VAR
  522. el, child: XML.Element; elName, line: OdUtil.Line;
  523. BEGIN
  524. el := doc.GetRoot();
  525. elName := AbsXmlName(el.GetName());
  526. IF elName = "DAV:error" THEN
  527. child := GetFirstChild(el);
  528. IF child # NIL THEN (* regular error code *)
  529. line := AbsXmlName(child.GetName());
  530. COPY(line, name);
  531. ELSE (* My server at the moment. *)
  532. GetCharData(el, name);
  533. END;
  534. RETURN TRUE;
  535. END;
  536. RETURN FALSE;
  537. END IsDAVError;
  538. (* don't write anything. Just for counting what's written to a writer. *)
  539. (*PROCEDURE Dev0(VAR buf: ARRAY OF CHAR; ofs, len: LONGINT; propagate: BOOLEAN; VAR res: WORD);
  540. BEGIN END Dev0;*)
  541. PROCEDURE Dev0(CONST buf: ARRAY OF CHAR; ofs, len: LONGINT; propagate: BOOLEAN; VAR res: WORD);
  542. BEGIN END Dev0;
  543. (* Find size of an XML object which must be written. *)
  544. PROCEDURE XmlSize*(doc: XML.Document): LONGINT;
  545. VAR counter: Streams.Writer;
  546. BEGIN
  547. Streams.OpenWriter(counter, Dev0); doc.Write(counter, NIL, 0); counter.Update();
  548. RETURN counter.sent;
  549. END XmlSize;
  550. (** Collect XML namespaces from an element. No nested scopes. So hope that no namespace is redefined in
  551. a XML body. *)
  552. PROCEDURE GetXmlns * (el: XML.Element);
  553. VAR
  554. a: ANY; name, value: XML.String;
  555. attributes: XMLObjects.Enumerator; attr: XML.Attribute;
  556. tag, ns: ARRAY 32 OF CHAR;
  557. BEGIN
  558. attributes := el.GetAttributes();
  559. WHILE attributes.HasMoreElements() DO
  560. a := attributes.GetNext();
  561. attr := a(XML.Attribute);
  562. name := attr.GetName(); value := attr.GetValue();
  563. IF Strings.Pos("xmlns:", name^) = 0 THEN
  564. Files.SplitName(name^, tag, ns);
  565. WebHTTP.SetAdditionalFieldValue(xmlns, ns, value^);
  566. (* OdUtil.Msg3(name^, "=", value^); *)
  567. END;
  568. END;
  569. END GetXmlns;
  570. (** Expand an xmlns for an XML String. *)
  571. PROCEDURE AbsXmlName * (rawName: XML.String):OdUtil.Line;
  572. BEGIN
  573. RETURN AbsName(rawName^);
  574. END AbsXmlName;
  575. (** Expand an xmlns. *)
  576. PROCEDURE AbsName * (CONST rawName: ARRAY OF CHAR):OdUtil.Line;
  577. VAR absName, absSpace, nameSpace, name: OdUtil.Line; colonPos: SIZE;
  578. BEGIN
  579. colonPos := Strings.Pos(":", rawName);
  580. IF colonPos > -1 THEN
  581. Files.SplitName(rawName, nameSpace, name);
  582. IF nameSpace = "D" THEN (* Defaultnamespace. *)
  583. Strings.Concat("DAV:", name, absName);
  584. ELSIF WebHTTP.GetAdditionalFieldValue(xmlns, nameSpace, absSpace) THEN
  585. Strings.Concat(absSpace, name, absName);
  586. ELSE
  587. COPY(rawName, absName);
  588. END;
  589. ELSE (* Default *)
  590. Files.JoinName("DAV", rawName, absName);
  591. END;
  592. RETURN absName;
  593. END AbsName;
  594. (* Dummy because compiler doesn't like IF AbsName(s) = "DAV:jkjk" *)
  595. PROCEDURE EqualName * (name: XML.String; CONST absName: ARRAY OF CHAR): BOOLEAN;
  596. VAR line: OdUtil.Line;
  597. BEGIN
  598. line := AbsName(name^);
  599. (*KernelLog.Enter;KernelLog.String(name);KernelLog.String(",");KernelLog.String(line);
  600. KernelLog.String(",");KernelLog.String(absName);KernelLog.Exit;*)
  601. RETURN line = absName;
  602. END EqualName;
  603. (* Just for the relevant cases in the moment. *)
  604. (** Write an XML document or element e.g. in case of unexpected elements to the log device set in KernelLog. *)
  605. PROCEDURE LogDoc * (CONST info: ARRAY OF CHAR; doc: XML.Document);
  606. BEGIN
  607. logW.String(info); logW.Ln;
  608. doc.Write(logW, NIL, 0);
  609. logW.Update();
  610. END LogDoc;
  611. PROCEDURE LogEl * (CONST info: ARRAY OF CHAR; el: XML.Element);
  612. BEGIN
  613. logW.String(info); logW.Ln;
  614. el.Write(logW, NIL, 0);
  615. logW.Update();
  616. END LogEl;
  617. (* Get first child element. Would be nice to have that in XML.Mod. *)
  618. PROCEDURE GetFirstChild * (parent: XML.Element): XML.Element;
  619. VAR enum: XMLObjects.Enumerator; p: ANY;
  620. BEGIN
  621. enum := parent.GetContents();
  622. p := enum.GetNext();
  623. IF p IS XML.Element THEN
  624. RETURN p(XML.Element);
  625. ELSE
  626. RETURN NIL;
  627. END;
  628. END GetFirstChild;
  629. (* Find an element with a certain type(name) *)
  630. PROCEDURE FindElement*(parent: XML.Element; CONST type: ARRAY OF CHAR): XML.Element;
  631. VAR enum: XMLObjects.Enumerator; p: ANY; e: XML.Element; s: XML.String; l: OdUtil.Line;
  632. BEGIN
  633. (*KernelLog.Enter; KernelLog.String(type); KernelLog.Exit; System.OpenKernelLog *)
  634. enum := parent.GetContents();
  635. WHILE enum.HasMoreElements() DO
  636. p := enum.GetNext();
  637. IF p IS XML.Element THEN
  638. e := p(XML.Element); s := e.GetName();
  639. IF s # NIL THEN
  640. l := AbsName(s^);
  641. IF l = type THEN RETURN e; END
  642. END;
  643. END
  644. END;
  645. RETURN NIL
  646. END FindElement;
  647. (* Find an element in an element tree by a dot seperated string. *)
  648. PROCEDURE SplitElement*(parent: XML.Element; CONST path: ARRAY OF CHAR): XML.Element;
  649. VAR splitter: StringSplitter; child: XML.Element; name: ARRAY 64 OF CHAR;
  650. BEGIN
  651. NEW(splitter, path); child := NIL;
  652. WHILE splitter.Next('.', name) DO
  653. child := FindElement(parent, name);
  654. IF child = NIL THEN RETURN NIL; END; (* Error *)
  655. parent := child;
  656. END;
  657. RETURN child;
  658. END SplitElement;
  659. PROCEDURE ConfigurationReportReq*(): XML.Document;
  660. (* es feature *)
  661. VAR doc: XML.Document; cr: XML.Element;
  662. BEGIN
  663. NEW(doc); doc.AddContent(xmlDecl);
  664. NEW(cr); cr.SetName("D:configuration-report"); cr.SetAttributeValue("xmlns:D", "DAV:"); doc.AddContent(cr);
  665. RETURN doc;
  666. END ConfigurationReportReq;
  667. (* update version href *)
  668. PROCEDURE UpdateReq*(CONST host, ver: ARRAY OF CHAR): XML.Document;
  669. CONST PLog = FALSE;
  670. VAR doc: XML.Document; vc,v,h: XML.Element;
  671. name: ARRAY 128 OF CHAR; versionNumber: LONGINT;
  672. BEGIN
  673. NEW(doc); doc.AddContent(xmlDecl);
  674. NEW(vc); vc.SetName("D:update"); vc.SetAttributeValue("xmlns:D", "DAV:"); doc.AddContent(vc);
  675. NEW(v); v.SetName("D:version"); vc.AddContent(v);
  676. NEW(h); h.SetName("D:href"); v.AddContent(h);
  677. name := "http://"; Strings.Append(name, host);
  678. Strings.StrToInt(ver, versionNumber);
  679. IF versionNumber > 0 THEN
  680. (* A version number is given. *)
  681. Strings.Append(name, UpdateVersionTag);
  682. END;
  683. Strings.Append(name, ver);
  684. IF PLog THEN OdUtil.Msg2("DAVXml.UpdateReq", ver); END;
  685. h.AddContent(ArrayChars(name));
  686. RETURN doc;
  687. END UpdateReq;
  688. (* version-tree prop (version-name creator-displayname version-time comment) *)
  689. PROCEDURE VersionTreeReq*(): XML.Document;
  690. VAR
  691. doc: XML.Document; vt, p, e: XML.Element;
  692. BEGIN
  693. NEW(doc); doc.AddContent(xmlDecl);
  694. NEW(vt); vt.SetName("D:version-tree"); vt.SetAttributeValue("xmlns:D", "DAV:"); doc.AddContent(vt);
  695. NEW(p); p.SetName("D:prop"); vt.AddContent(p);
  696. NEW(e); e.SetName("D:version-name"); p.AddContent(e);
  697. NEW(e); e.SetName("D:creator-displayname"); p.AddContent(e);
  698. NEW(e); e.SetName("D:version-time"); p.AddContent(e);
  699. NEW(e); e.SetName("D:comment"); p.AddContent(e);
  700. RETURN doc;
  701. END VersionTreeReq;
  702. (* propertyupdate (set 1{prop <propname> 1{href} } | remove 1{ prop <propname> href } *)
  703. (* Only works for 'set hrefproperties' at the moment. *)
  704. PROCEDURE ProppatchReq*(CONST modeName: ARRAY OF CHAR; props: WebHTTP.AdditionalField): XML.Document;
  705. VAR doc: XML.Document; pu(*propertyupdate*), prop, mode, e : XML.Element;
  706. ac: XML.ArrayChars; modePropName, key, attrKey, attrVal: ARRAY 128 OF CHAR;
  707. pos: SIZE; nameVal: StringSplitter;
  708. BEGIN
  709. NEW(doc); doc.AddContent(xmlDecl);
  710. (* propertyupdate *)
  711. NEW(pu); pu.SetName("D:propertyupdate"); pu.SetAttributeValue("xmlns:D", "DAV:");
  712. pu.SetAttributeValue("xmlns:SVN", "http://subversion.tigris.org/xmlns/svn/");
  713. doc.AddContent(pu);
  714. (* pu.set/remove *)
  715. Strings.Concat("D:", modeName, modePropName);
  716. NEW(mode); mode.SetName(modePropName); pu.AddContent(mode);
  717. (* pu.<mode>.prop *)
  718. NEW(prop); prop.SetName("D:prop"); mode.AddContent(prop);
  719. WHILE props # NIL DO
  720. (* pu.set.prop.<propname> *)
  721. pos := Strings.Pos(" ", props.key); (* Assume an attribute is following. *)
  722. IF pos > -1 THEN
  723. Strings.Copy(props.key, 0, pos, key);
  724. ELSE
  725. COPY(props.key, key);
  726. END;
  727. NEW(e); e.SetName(key); prop.AddContent(e);
  728. IF pos > -1 THEN
  729. Strings.Delete(props.key, 0, pos+1);
  730. NEW(nameVal, props.key);
  731. IF nameVal.Next("=", attrKey) THEN
  732. IF nameVal.Next("=", attrVal) THEN
  733. e.SetAttributeValue(attrKey, attrVal);
  734. END;
  735. END;
  736. pos := Strings.Pos("=", props.key);
  737. END;
  738. IF modeName = "set" THEN
  739. (* pu.set.prop.<propname>.<value> *)
  740. NEW(ac); ac.SetStr(props.value); e.AddContent(ac);
  741. END;
  742. props := props.next;
  743. END;
  744. RETURN doc;
  745. END ProppatchReq;
  746. (* propfind (propname | allprop | prop ( { <propname> } )*)
  747. PROCEDURE PropfindReq * (props: WebHTTP.AdditionalField): XML.Document;
  748. VAR doc: XML.Document; propfind, prop, el: XML.Element;
  749. BEGIN
  750. prop := NIL;
  751. NEW(doc);
  752. doc.AddContent(xmlDecl);
  753. NEW(propfind);
  754. propfind.SetName("D:propfind");
  755. propfind.SetAttributeValue("xmlns:D", "DAV:");
  756. propfind.SetAttributeValue("xmlns:D2", "http://subversion.tigris.org/xmlns/dav/");
  757. doc.AddContent(propfind);
  758. WHILE props # NIL DO
  759. IF props.key = "D:propname" THEN
  760. NEW(prop); prop.SetName("D:propname"); propfind.AddContent(prop);
  761. RETURN doc;
  762. ELSIF props.key = "D:allprop" THEN
  763. NEW(prop); prop.SetName("D:allprop"); propfind.AddContent(prop);
  764. RETURN doc;
  765. ELSE
  766. IF prop = NIL THEN
  767. NEW(prop); prop.SetName("D:prop"); propfind.AddContent(prop);
  768. END;
  769. NEW(el); el.SetName(props.key); prop.AddContent(el);
  770. END;
  771. props := props.next;
  772. END;
  773. RETURN doc;
  774. END PropfindReq;
  775. (* checkin prop (creator-displayname comment) *)
  776. PROCEDURE CheckinReq*(CONST author, desc: ARRAY OF CHAR): XML.Document;
  777. VAR doc: XML.Document; vt, p, e: XML.Element;
  778. ac: XML.ArrayChars;
  779. BEGIN
  780. NEW(doc); doc.AddContent(xmlDecl);
  781. NEW(vt); vt.SetName("D:checkin"); vt.SetAttributeValue("xmlns:D", "DAV:"); doc.AddContent(vt);
  782. NEW(p); p.SetName("D:prop"); vt.AddContent(p);
  783. (* Author *) NEW(e);
  784. NEW(ac); ac.SetStr(author); e.AddContent(ac);
  785. e.SetName("D:creator-displayname"); p.AddContent(e);
  786. (* Description *) NEW(e);
  787. NEW(ac); ac.SetStr(desc); e.AddContent(ac);
  788. e.SetName("D:comment"); p.AddContent(e);
  789. RETURN doc;
  790. END CheckinReq;
  791. (* version-control prop (creator-displayname comment) *)
  792. PROCEDURE VersionControlCreateReq*(CONST author, desc: ARRAY OF CHAR): XML.Document;
  793. BEGIN
  794. RETURN FreezeReq("version-control", author, desc);
  795. END VersionControlCreateReq;
  796. (* <method> prop (creator-displayname comment) *)
  797. PROCEDURE FreezeReq*(CONST method, author, desc: ARRAY OF CHAR): XML.Document;
  798. VAR doc: XML.Document; root, p, e: XML.Element;
  799. ac: XML.ArrayChars;
  800. BEGIN
  801. NEW(doc); doc.AddContent(xmlDecl);
  802. NEW(root); root.SetName(method); root.SetAttributeValue("xmlns:D", "DAV:"); doc.AddContent(root);
  803. NEW(p); p.SetName("D:prop"); root.AddContent(p);
  804. (* Author *) NEW(e);
  805. NEW(ac); ac.SetStr(author); e.AddContent(ac);
  806. e.SetName("D:creator-displayname"); p.AddContent(e);
  807. (* Description *) NEW(e);
  808. NEW(ac); ac.SetStr(desc); e.AddContent(ac);
  809. e.SetName("D:comment"); p.AddContent(e);
  810. RETURN doc;
  811. END FreezeReq;
  812. (* <method> version href *)
  813. PROCEDURE SelectReq*(CONST method, host, ver: ARRAY OF CHAR): XML.Document;
  814. VAR doc: XML.Document; vc,v,h: XML.Element;
  815. name: ARRAY 512 OF CHAR;
  816. BEGIN
  817. NEW(doc); doc.AddContent(xmlDecl);
  818. NEW(vc); vc.SetName(method); vc.SetAttributeValue("xmlns:D", "DAV:"); doc.AddContent(vc);
  819. NEW(v); v.SetName("D:version"); vc.AddContent(v);
  820. NEW(h); h.SetName("D:href"); v.AddContent(h);
  821. name := "http://"; Strings.Append(name, host); Strings.Append(name, ver);
  822. h.AddContent(ArrayChars(name));
  823. RETURN doc;
  824. END SelectReq;
  825. (* <label> href *)
  826. PROCEDURE Href1Req*(CONST label, href: ARRAY OF CHAR): XML.Document;
  827. VAR doc: XML.Document; label0, href1: XML.Element;
  828. BEGIN
  829. NEW(doc); doc.AddContent(xmlDecl);
  830. (* label = version-tree, compare-baseline, ... *)
  831. NEW(label0); label0.SetName(label);
  832. label0.SetAttributeValue("xmlns:D", "DAV:");
  833. doc.AddContent(label0);
  834. (* href *)
  835. NEW(href1); href1.SetName("D:href");
  836. label0.AddContent(href1);
  837. href1.AddContent(ArrayChars(href));
  838. RETURN doc;
  839. END Href1Req;
  840. PROCEDURE GetVersionControlHref*(doc: XML.Document; VAR charData: ARRAY OF CHAR);
  841. VAR e: XML.Element;
  842. BEGIN
  843. e := FindElement(doc.GetRoot(), "DAV:version");
  844. e := FindElement(e, "DAV:href");
  845. GetCharData(e, charData);
  846. END GetVersionControlHref;
  847. (* update, version, href: versionName*)
  848. PROCEDURE GetUpdateVersionName*(doc: XML.Document; VAR versionName: ARRAY OF CHAR);
  849. VAR
  850. e: XML.Element; versionResource: ARRAY 256 OF CHAR; i, dotPos: LONGINT;
  851. host, path: ARRAY 256 OF CHAR; port: LONGINT;
  852. BEGIN
  853. e := FindElement(doc.GetRoot(), "DAV:version");
  854. IF e # NIL THEN
  855. e := FindElement(e, "DAV:href");
  856. IF e # NIL THEN
  857. GetCharData(e, versionResource);
  858. IF WebHTTP.SplitHTTPAdr(versionResource, host, path, port) THEN END;
  859. IF Strings.Pos("/hist/", path) = 0 THEN
  860. Strings.Delete(path, 0, 6);
  861. ELSE (* Expect "/version.<n>" *)
  862. Strings.Delete(path, 0, 1);
  863. END;
  864. dotPos := -1;
  865. (* Split <version history>.<version number> *)
  866. FOR i := 0 TO Strings.Length(path) -1 DO
  867. IF path[i] = '.' THEN dotPos := i; END;
  868. END;
  869. (* Copy versionName (number) *)
  870. FOR i := dotPos+1 TO Strings.Length(path) DO
  871. (* Also copies trailing 0X *)
  872. versionName[i - (dotPos+1)] := path[i];
  873. END;
  874. END;
  875. END;
  876. END GetUpdateVersionName;
  877. (* checkin.prop.(creator-displayname, comment) *)
  878. PROCEDURE GetAuthorDesc*(doc: XML.Document; VAR author, desc: ARRAY OF CHAR);
  879. VAR e0, e1: XML.Element;
  880. BEGIN
  881. e0 := FindElement(doc.GetRoot(), "DAV:prop");
  882. IF e0 # NIL THEN
  883. e1 := FindElement(e0, "DAV:creator-displayname");
  884. IF e1 # NIL THEN GetCharData(e1, author); ELSE author[0] := 0X; END;
  885. e1 := FindElement(e0, "DAV:comment");
  886. IF e1 # NIL THEN GetCharData(e1, desc); ELSE desc[0] := 0X; END;
  887. ELSE
  888. author[0] := 0X; desc[0] := 0X;
  889. END;
  890. END GetAuthorDesc;
  891. PROCEDURE File*; (* System.Free DAVXml ~ DAVXml.Do DAVXml.File System.OpenKernelLog *)
  892. VAR f: Files.File; fr: Files.Reader; scanner: XMLScanner.Scanner; parser: XMLParser.Parser; xmlDoc: XML.Document;
  893. w: Streams.Writer; name: ARRAY 128 OF CHAR;
  894. BEGIN
  895. f := Files.Old("VersionControl.XML");
  896. NEW(fr, f, 0);
  897. IF f # NIL THEN
  898. KernelLog.Enter; KernelLog.String("File found"); KernelLog.Exit;
  899. NEW(scanner, fr); NEW(parser, scanner); xmlDoc := parser.Parse();
  900. Streams.OpenWriter(w, KernelLog.Send); (* gibt das Zeugs im Kernel Log aus *)
  901. xmlDoc.Write(w, NIL, 0); w.Update();
  902. GetVersionControlHref(xmlDoc, name);
  903. w.String(name); w.Update();
  904. ELSE
  905. xmlDoc := NIL
  906. END
  907. END File;
  908. END OdXml;
  909. (* Like in XMLScanner and XMLParser but doesn't HALT(99) *)
  910. PROCEDURE XMLReportError(pos, line, row: LONGINT; CONST msg: ARRAY OF CHAR);
  911. BEGIN
  912. KernelLog.Enter; KernelLog.Char(CHR(9H)); KernelLog.Char(CHR(9H)); KernelLog.String("pos "); KernelLog.Int(pos, 6);
  913. KernelLog.String(", line "); KernelLog.Int(line, 0); KernelLog.String(", row "); KernelLog.Int(row, 0);
  914. KernelLog.String(" "); KernelLog.String(msg); KernelLog.Exit;
  915. END XMLReportError;
  916. PROCEDURE NameContent(CONST name: ARRAY OF CHAR): XML.NameContent;
  917. VAR nameContent: XML.NameContent;
  918. BEGIN
  919. NEW(nameContent); nameContent.SetName(name);
  920. RETURN nameContent;
  921. END NameContent;
  922. PROCEDURE XmlDecl(CONST version, encoding: ARRAY OF CHAR): XML.XMLDecl;
  923. VAR xmlDecl: XML.XMLDecl;
  924. BEGIN
  925. NEW(xmlDecl); xmlDecl.SetVersion(version); xmlDecl.SetEncoding(encoding); xmlDecl.SetStandalone(TRUE);
  926. RETURN xmlDecl;
  927. END XmlDecl;
  928. (* Get character data of an element. *)
  929. PROCEDURE GetCharData*(parent: XML.Element; VAR charData: ARRAY OF CHAR);
  930. VAR enum: XMLObjects.Enumerator; p: ANY; cd: XML.ArrayChars; s: XML.String; i: INTEGER;
  931. BEGIN
  932. charData[0] := 0X;
  933. IF parent # NIL THEN
  934. enum := parent.GetContents();
  935. WHILE enum.HasMoreElements() DO
  936. p := enum.GetNext();
  937. IF p IS XML.ArrayChars THEN
  938. cd := p(XML.ArrayChars); s := cd.GetStr();
  939. IF s # NIL THEN Strings.Append(charData, s^); END;
  940. IF charData[0] = 0DX THEN i := 0; REPEAT INC(i); charData[i-1] := charData[i]; UNTIL charData[i] = 0X; END;
  941. ELSE
  942. COPY("XML element isn't XML.ArrayChars", charData);
  943. END;
  944. END;
  945. ELSE
  946. COPY("DAVXML.GetCharData: parent was NIL", charData);
  947. END;
  948. END GetCharData;
  949. (* Get character data string of an element. *)
  950. PROCEDURE GetCharString*(parent: XML.Element): Strings.String;
  951. VAR enum: XMLObjects.Enumerator; p: ANY; cd: XML.ArrayChars;
  952. BEGIN
  953. IF parent # NIL THEN
  954. enum := parent.GetContents();
  955. WHILE enum.HasMoreElements() DO
  956. p := enum.GetNext();
  957. IF p IS XML.ArrayChars THEN
  958. cd := p(XML.ArrayChars);
  959. RETURN cd.GetStr();
  960. ELSE
  961. (*Strings.NewString("Error: XML element isn't XML.ArrayChars");*)
  962. END;
  963. END;
  964. ELSE
  965. (*Strings.NewStringCOPY("DAVXML.GetCharData: parent was NIL", charData);*)
  966. END;
  967. RETURN NIL;
  968. END GetCharString;
  969. PROCEDURE ArrayChars(CONST str: ARRAY OF CHAR): XML.ArrayChars;
  970. VAR arrayChars: XML.ArrayChars;
  971. BEGIN
  972. NEW(arrayChars); arrayChars.SetStr(str);
  973. RETURN arrayChars;
  974. END ArrayChars;
  975. BEGIN
  976. xmlDecl := XmlDecl("1.0", "UTF-8"); (* Standard header *)
  977. END OdXml.