xmlrpc.pp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941
  1. {
  2. XML-RPC server and client library
  3. Copyright (c) 2003-2004 by
  4. Areca Systems GmbH / Sebastian Guenther, [email protected]
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. }
  11. unit XMLRPC;
  12. interface
  13. uses SysUtils, Classes, fpAsync, ssockets, DOM, HTTPClient, HTTPSvlt;
  14. type
  15. EXMLRPCParser = class(Exception);
  16. TXMLRPCParams = class(TDOMElement);
  17. TXMLRPCValue = class(TDOMElement);
  18. TXMLRPCStruct = class(TXMLRPCValue);
  19. TXMLRPCArray = class(TXMLRPCValue);
  20. TXMLRPCWriter = class
  21. private
  22. Doc: TXMLDocument;
  23. protected
  24. function CreateValueEl: TXMLRPCValue;
  25. public
  26. constructor Create;
  27. destructor Destroy; override;
  28. function MakeStream: TMemoryStream;
  29. procedure WriteMethodCall(const AMethodName: DOMString;
  30. Params: TXMLRPCParams);
  31. procedure WriteResponse(Value: TXMLRPCValue);
  32. procedure WriteFaultResponse(FaultCode: LongInt;
  33. const FaultString: DOMString);
  34. function CreateParams: TXMLRPCParams;
  35. procedure AddParam(Params: TXMLRPCParams; Value: TXMLRPCValue);
  36. function CreateIntValue(i: LongInt): TXMLRPCValue;
  37. function CreateBooleanValue(b: Boolean): TXMLRPCValue;
  38. function CreateStringValue(const s: DOMString): TXMLRPCValue;
  39. function CreateDoubleValue(d: Double): TXMLRPCValue;
  40. function CreateDateTimeValue(dt: TDateTime): TXMLRPCValue;
  41. function CreateStruct: TXMLRPCStruct;
  42. procedure AddStructMember(Struct: TXMLRPCStruct; const Name: DOMString;
  43. Member: TXMLRPCValue);
  44. function CreateArray: TXMLRPCArray;
  45. procedure AddArrayElement(AArray: TXMLRPCArray; Value: TXMLRPCValue);
  46. // !!!: Missing: Binary data
  47. end;
  48. TXMLRPCPostType = (
  49. xmlrpcInvalid, // Invalid post type
  50. xmlrpcMethodCall, // Method call
  51. xmlrpcResponse, // Method call response (successfull)
  52. xmlrpcFaultResponse); // Method call response (failed)
  53. TXMLRPCParser = class
  54. private
  55. Doc: TXMLDocument;
  56. CurDataNode: TDOMNode;
  57. InArray: Boolean;
  58. procedure NextNode;
  59. procedure PrevNode;
  60. function GetValue: String;
  61. function FindStructMember(AStruct: TXMLRPCStruct;
  62. const AMemberName: String): TDOMElement;
  63. function GetStructMemberValue(MemberNode: TDOMElement): String;
  64. public
  65. constructor Create(AStream: TStream);
  66. destructor Destroy; override;
  67. function GetPostType: TXMLRPCPostType;
  68. function GetMethodName: String;
  69. procedure ResetValueCursor;
  70. // Simple values
  71. function GetNextInt: LongInt;
  72. function GetPrevInt: LongInt;
  73. function GetNextBoolean: Boolean;
  74. function GetPrevBoolean: Boolean;
  75. function GetNextString: String;
  76. function GetPrevString: String;
  77. function GetNextDouble: Double;
  78. function GetPrevDouble: Double;
  79. // !!!: Missing: DateTime, Binary data
  80. // Struct values
  81. function GetNextStruct: TXMLRPCStruct;
  82. function GetIntMember(AStruct: TXMLRPCStruct; const AName: String;
  83. ADefault: Integer): Integer;
  84. function GetBooleanMember(AStruct: TXMLRPCStruct; const AName: String;
  85. ADefault: Boolean): Boolean;
  86. function GetStringMember(AStruct: TXMLRPCStruct; const AName: String;
  87. const ADefault: String): String;
  88. function GetDoubleMember(AStruct: TXMLRPCStruct; const AName: String;
  89. ADefault: Double): Double;
  90. // Array values
  91. procedure BeginArray;
  92. procedure EndArray;
  93. end;
  94. {$ifdef NEVERTRUE}
  95. TOnXMLRPCCallCompleted = procedure(AParser: TXMLRPCParser) of object;
  96. TXMLRPCClient = class
  97. private
  98. FEventLoop: TEventLoop;
  99. FServerURL: String;
  100. FOnBeginRPC, FOnEndRPC: TNotifyEvent;
  101. RequestStream, ResponseStream: TMemoryStream;
  102. CurCallback: TOnXMLRPCCallCompleted;
  103. LocalEventLoop: TEventLoop;
  104. Connection: TCustomHttpClient;
  105. procedure MakeRequest(const AProcName: String; AArgs: array of const);
  106. procedure ProcessAnswer;
  107. procedure StreamSent(Sender: TObject);
  108. procedure DataAvailable(Sender: TObject);
  109. public
  110. constructor Create(AEventLoop: TEventLoop);
  111. procedure Call(ACallback: TOnXMLRPCCallCompleted;
  112. const AProcName: String; AArgs: array of const);
  113. procedure CallAsync(ACallback: TOnXMLRPCCallCompleted;
  114. const AProcName: String; AArgs: array of const);
  115. property EventLoop: TEventLoop read FEventLoop;
  116. property ServerURL: String read FServerURL write FServerURL;
  117. property OnBeginRPC: TNotifyEvent read FOnBeginRPC write FOnBeginRPC;
  118. property OnEndRPC: TNotifyEvent read FOnEndRPC write FOnEndRPC;
  119. end;
  120. {$endif}
  121. TCheckCallEvent = procedure(AParser: TXMLRPCParser; const APath: TStrings;
  122. var ExecCall: Boolean) of object;
  123. TExceptionEvent = procedure(e: Exception) of object;
  124. TXMLRPCServlet = class(THttpServlet)
  125. private
  126. FOnCheckCall: TCheckCallEvent;
  127. FOnException: TExceptionEvent;
  128. protected
  129. procedure DoPost(Req: THttpServletRequest; Resp: THttpServletResponse);
  130. override;
  131. public
  132. procedure Dispatch(AParser: TXMLRPCParser; AWriter: TXMLRPCWriter;
  133. APath: TStrings); virtual; abstract;
  134. property OnCheckCall: TCheckCallEvent read FOnCheckCall write FOnCheckCall;
  135. property OnException: TExceptionEvent read FOnException write FOnException;
  136. end;
  137. implementation
  138. uses XMLWrite, XMLRead;
  139. // Debugging stuff
  140. {$IFDEF XMLRPCDebug}
  141. const
  142. NodeNames: array[ELEMENT_NODE..NOTATION_NODE] of String = (
  143. 'Element',
  144. 'Attribute',
  145. 'Text',
  146. 'CDATA section',
  147. 'Entity reference',
  148. 'Entity',
  149. 'Processing instruction',
  150. 'Comment',
  151. 'Document',
  152. 'Document type',
  153. 'Document fragment',
  154. 'Notation'
  155. );
  156. procedure DumpNode(node: TDOMNode; spc: String);
  157. var
  158. i: Integer;
  159. attr: TDOMNode;
  160. begin
  161. Write(spc, NodeNames[node.NodeType]);
  162. if Copy(node.NodeName, 1, 1) <> '#' then
  163. Write(' "', node.NodeName, '"');
  164. if node.NodeValue <> '' then
  165. Write(' "', node.NodeValue, '"');
  166. if (node.Attributes <> nil) and (node.Attributes.Length > 0) then begin
  167. Write(',');
  168. for i := 0 to node.Attributes.Length - 1 do begin
  169. attr := node.Attributes.Item[i];
  170. Write(' ', attr.NodeName, ' = "', attr.NodeValue, '"');
  171. end;
  172. end;
  173. WriteLn;
  174. node := node.FirstChild;
  175. while Assigned(node) do
  176. begin
  177. DumpNode(node, spc + ' ');
  178. node := node.NextSibling;
  179. end;
  180. end;
  181. {$ENDIF}
  182. // XML-RPC Writer
  183. constructor TXMLRPCWriter.Create;
  184. begin
  185. inherited Create;
  186. Doc := TXMLDocument.Create;
  187. end;
  188. destructor TXMLRPCWriter.Destroy;
  189. begin
  190. Doc.Free;
  191. inherited Destroy;
  192. end;
  193. function TXMLRPCWriter.MakeStream: TMemoryStream;
  194. begin
  195. Result := TMemoryStream.Create;
  196. try
  197. WriteXMLFile(Doc, Result);
  198. // WriteXMLFile(Doc, THandleStream.Create(StdOutputHandle));
  199. Result.Position := 0;
  200. except
  201. on e: Exception do
  202. Result.Free;
  203. end;
  204. end;
  205. procedure TXMLRPCWriter.WriteMethodCall(const AMethodName: DOMString;
  206. Params: TXMLRPCParams);
  207. var
  208. El, El2: TDOMElement;
  209. begin
  210. El := Doc.CreateElement('methodCall');
  211. Doc.AppendChild(El);
  212. El2 := Doc.CreateElement('methodName');
  213. El.AppendChild(El2);
  214. El2.AppendChild(Doc.CreateTextNode(AMethodName));
  215. El.AppendChild(Params);
  216. end;
  217. procedure TXMLRPCWriter.WriteResponse(Value: TXMLRPCValue);
  218. var
  219. El, El2: TDOMElement;
  220. begin
  221. ASSERT(Value is TXMLRPCValue);
  222. El := Doc.CreateElement('methodResponse');
  223. Doc.AppendChild(El);
  224. El2 := Doc.CreateElement('params');
  225. El.AppendChild(El2);
  226. if not Assigned(Value) then
  227. Value := CreateBooleanValue(True);
  228. El := Doc.CreateElement('param');
  229. El2.AppendChild(El);
  230. El.AppendChild(Value);
  231. end;
  232. procedure TXMLRPCWriter.WriteFaultResponse(FaultCode: LongInt;
  233. const FaultString: DOMString);
  234. var
  235. El, El2: TDOMElement;
  236. Struct: TXMLRPCStruct;
  237. begin
  238. El := Doc.CreateElement('methodResponse');
  239. Doc.AppendChild(El);
  240. El2 := Doc.CreateElement('fault');
  241. El.AppendChild(El2);
  242. Struct := CreateStruct;
  243. AddStructMember(Struct, 'faultCode', CreateIntValue(FaultCode));
  244. AddStructMember(Struct, 'faultString', CreateStringValue(FaultString));
  245. El2.AppendChild(Struct);
  246. end;
  247. function TXMLRPCWriter.CreateParams: TXMLRPCParams;
  248. begin
  249. Result := TXMLRPCParams(Doc.CreateElement('params'));
  250. end;
  251. procedure TXMLRPCWriter.AddParam(Params: TXMLRPCParams; Value: TXMLRPCValue);
  252. var
  253. El: TDOMElement;
  254. begin
  255. ASSERT((Params is TXMLRPCParams) and (Value is TXMLRPCValue));
  256. El := Doc.CreateElement('param');
  257. Params.AppendChild(El);
  258. El.AppendChild(Value);
  259. end;
  260. function TXMLRPCWriter.CreateIntValue(i: LongInt): TXMLRPCValue;
  261. var
  262. El: TDOMElement;
  263. begin
  264. Result := CreateValueEl;
  265. El := Doc.CreateElement('int');
  266. Result.AppendChild(El);
  267. El.AppendChild(Doc.CreateTextNode(IntToStr(i)));
  268. end;
  269. function TXMLRPCWriter.CreateBooleanValue(b: Boolean): TXMLRPCValue;
  270. var
  271. El: TDOMElement;
  272. begin
  273. Result := CreateValueEl;
  274. El := Doc.CreateElement('boolean');
  275. Result.AppendChild(El);
  276. El.AppendChild(Doc.CreateTextNode(IntToStr(Ord(b))));
  277. end;
  278. function TXMLRPCWriter.CreateStringValue(const s: DOMString): TXMLRPCValue;
  279. var
  280. El: TDOMElement;
  281. begin
  282. Result := CreateValueEl;
  283. El := Doc.CreateElement('string');
  284. Result.AppendChild(El);
  285. if Length(s) > 0 then
  286. El.AppendChild(Doc.CreateTextNode(s));
  287. end;
  288. function TXMLRPCWriter.CreateDoubleValue(d: Double): TXMLRPCValue;
  289. var
  290. El: TDOMElement;
  291. begin
  292. Result := CreateValueEl;
  293. El := Doc.CreateElement('double');
  294. Result.AppendChild(El);
  295. El.AppendChild(Doc.CreateTextNode(FloatToStr(d)));
  296. end;
  297. function TXMLRPCWriter.CreateDateTimeValue(dt: TDateTime): TXMLRPCValue;
  298. var
  299. El: TDOMElement;
  300. begin
  301. Result := CreateValueEl;
  302. El := Doc.CreateElement('dateTime.iso8601');
  303. Result.AppendChild(El);
  304. El.AppendChild(Doc.CreateTextNode(FormatDateTime('ddmmyyyyThh:nn:ss', dt)));
  305. end;
  306. function TXMLRPCWriter.CreateStruct: TXMLRPCStruct;
  307. begin
  308. Result := TXMLRPCStruct(CreateValueEl);
  309. Result.AppendChild(Doc.CreateElement('struct'));
  310. end;
  311. procedure TXMLRPCWriter.AddStructMember(Struct: TXMLRPCStruct;
  312. const Name: DOMString; Member: TXMLRPCValue);
  313. var
  314. MemberEl, El: TDOMElement;
  315. begin
  316. ASSERT((Struct is TXMLRPCStruct) and (Name <> '') and
  317. (Member is TXMLRPCValue));
  318. MemberEl := Doc.CreateElement('member');
  319. Struct.FirstChild.AppendChild(MemberEl);
  320. El := Doc.CreateElement('name');
  321. MemberEl.AppendChild(El);
  322. El.AppendChild(Doc.CreateTextNode(Name));
  323. MemberEl.AppendChild(Member);
  324. end;
  325. function TXMLRPCWriter.CreateArray: TXMLRPCArray;
  326. var
  327. ArrayEl: TDOMElement;
  328. begin
  329. Result := TXMLRPCArray(CreateValueEl);
  330. ArrayEl := Doc.CreateElement('array');
  331. Result.AppendChild(ArrayEl);
  332. ArrayEl.AppendChild(Doc.CreateElement('data'));
  333. end;
  334. procedure TXMLRPCWriter.AddArrayElement(AArray: TXMLRPCArray;
  335. Value: TXMLRPCValue);
  336. begin
  337. ASSERT((AArray is TXMLRPCArray) and (Value is TXMLRPCValue));
  338. AArray.FirstChild.FirstChild.AppendChild(Value);
  339. end;
  340. function TXMLRPCWriter.CreateValueEl: TXMLRPCValue;
  341. begin
  342. Result := TXMLRPCValue(Doc.CreateElement('value'));
  343. end;
  344. // XML-RPC Parser
  345. constructor TXMLRPCParser.Create(AStream: TStream);
  346. var
  347. Node: TDOMNode;
  348. begin
  349. inherited Create;
  350. ReadXMLFile(Doc, AStream);
  351. Node := Doc.DocumentElement;
  352. {$IFDEF XMLRPCDebug}DumpNode(Node, 'Parser> ');{$ENDIF}
  353. if (Node.NodeName = 'methodCall') or (Node.NodeName = 'methodResponse') then
  354. begin
  355. Node := Node.FirstChild;
  356. while Assigned(Node) and (Node.NodeName <> 'params') do
  357. Node := Node.NextSibling;
  358. if Assigned(Node) then
  359. begin
  360. Node := Node.FirstChild;
  361. while Assigned(Node) and (Node.NodeName <> 'param') do
  362. Node := Node.NextSibling;
  363. CurDataNode := Node;
  364. end;
  365. end;
  366. end;
  367. destructor TXMLRPCParser.Destroy;
  368. begin
  369. Doc.Free;
  370. inherited Destroy;
  371. end;
  372. function TXMLRPCParser.GetPostType: TXMLRPCPostType;
  373. var
  374. Node: TDOMNode;
  375. begin
  376. Result := xmlrpcInvalid;
  377. Node := Doc.DocumentElement;
  378. if Node.NodeName = 'methodCall' then
  379. Result := xmlrpcMethodCall
  380. else if Node.NodeName = 'methodResponse' then
  381. begin
  382. Node := Node.FirstChild;
  383. while Assigned(Node) and (Node.NodeType <> ELEMENT_NODE) do
  384. Node := Node.NextSibling;
  385. if Assigned(Node) then
  386. if Node.NodeName = 'params' then
  387. Result := xmlrpcResponse
  388. else if Node.NodeName = 'fault' then
  389. Result := xmlrpcFaultResponse;
  390. end;
  391. end;
  392. function TXMLRPCParser.GetMethodName: String;
  393. var
  394. Node: TDOMNode;
  395. begin
  396. SetLength(Result, 0);
  397. Node := Doc.DocumentElement;
  398. if (not Assigned(Node)) or (Node.NodeName <> 'methodCall') then
  399. exit;
  400. Node := Node.FindNode('methodName');
  401. if not Assigned(Node) then
  402. exit;
  403. Node := Node.FirstChild;
  404. while Assigned(Node) do
  405. begin
  406. if Node.NodeType = TEXT_NODE then
  407. Result := Result + Node.NodeValue;
  408. Node := Node.NextSibling;
  409. end;
  410. end;
  411. procedure TXMLRPCParser.ResetValueCursor;
  412. begin
  413. CurDataNode := CurDataNode.ParentNode.FirstChild;
  414. {$IFDEF XMLRPCDebug}DumpNode(CurDataNode, 'ResetValueCursor> ');{$ENDIF}
  415. end;
  416. function TXMLRPCParser.GetNextInt: LongInt;
  417. begin
  418. Result := StrToInt(GetValue);
  419. NextNode;
  420. end;
  421. function TXMLRPCParser.GetPrevInt: LongInt;
  422. begin
  423. PrevNode;
  424. Result := StrToInt(GetValue);
  425. end;
  426. function TXMLRPCParser.GetNextBoolean: Boolean;
  427. begin
  428. Result := GetValue = '1';
  429. NextNode;
  430. end;
  431. function TXMLRPCParser.GetPrevBoolean: Boolean;
  432. begin
  433. PrevNode;
  434. Result := GetValue = '1';
  435. end;
  436. function TXMLRPCParser.GetNextString: String;
  437. begin
  438. Result := GetValue;
  439. NextNode;
  440. end;
  441. function TXMLRPCParser.GetPrevString: String;
  442. begin
  443. PrevNode;
  444. Result := GetValue;
  445. end;
  446. function TXMLRPCParser.GetNextDouble: Double;
  447. begin
  448. Result := StrToFloat(GetValue);
  449. NextNode;
  450. end;
  451. function TXMLRPCParser.GetPrevDouble: Double;
  452. begin
  453. PrevNode;
  454. Result := StrToFloat(GetValue);
  455. end;
  456. function TXMLRPCParser.GetNextStruct: TXMLRPCStruct;
  457. begin
  458. if Assigned(CurDataNode) and Assigned(CurDataNode.FirstChild) then
  459. begin
  460. Result := TXMLRPCStruct(CurDataNode.FirstChild);
  461. while Assigned(Result) and (Result.NodeName <> 'struct') do
  462. Result := TXMLRPCStruct(Result.NextSibling);
  463. NextNode;
  464. end else
  465. Result := nil;
  466. end;
  467. function TXMLRPCParser.GetIntMember(AStruct: TXMLRPCStruct;
  468. const AName: String; ADefault: Integer): Integer;
  469. var
  470. MemberNode: TDOMElement;
  471. begin
  472. MemberNode := FindStructMember(AStruct, AName);
  473. if Assigned(MemberNode) then
  474. Result := StrToInt(GetStructMemberValue(MemberNode))
  475. else
  476. Result := ADefault;
  477. end;
  478. function TXMLRPCParser.GetBooleanMember(AStruct: TXMLRPCStruct;
  479. const AName: String; ADefault: Boolean): Boolean;
  480. var
  481. MemberNode: TDOMElement;
  482. begin
  483. MemberNode := FindStructMember(AStruct, AName);
  484. if Assigned(MemberNode) then
  485. Result := GetStructMemberValue(MemberNode) = '1'
  486. else
  487. Result := ADefault;
  488. end;
  489. function TXMLRPCParser.GetStringMember(AStruct: TXMLRPCStruct;
  490. const AName: String; const ADefault: String): String;
  491. var
  492. MemberNode: TDOMElement;
  493. begin
  494. MemberNode := FindStructMember(AStruct, AName);
  495. if Assigned(MemberNode) then
  496. Result := GetStructMemberValue(MemberNode)
  497. else
  498. Result := ADefault;
  499. end;
  500. function TXMLRPCParser.GetDoubleMember(AStruct: TXMLRPCStruct;
  501. const AName: String; ADefault: Double): Double;
  502. var
  503. MemberNode: TDOMElement;
  504. begin
  505. MemberNode := FindStructMember(AStruct, AName);
  506. if Assigned(MemberNode) then
  507. Result := StrToFloat(GetStructMemberValue(MemberNode))
  508. else
  509. Result := ADefault;
  510. end;
  511. procedure TXMLRPCParser.BeginArray;
  512. begin
  513. if Assigned(CurDataNode) then
  514. begin
  515. CurDataNode := CurDataNode.FirstChild;
  516. while Assigned(CurDataNode) and (CurDataNode.NodeName <> 'array') do
  517. CurDataNode := CurDataNode.NextSibling;
  518. if Assigned(CurDataNode) then
  519. begin
  520. CurDataNode := CurDataNode.FirstChild;
  521. while Assigned(CurDataNode) and (CurDataNode.NodeName <> 'data') do
  522. CurDataNode := CurDataNode.NextSibling;
  523. { if Assigned(CurDataNode) then
  524. begin
  525. CurDataNodeParent := CurDataNode;
  526. CurDataNode := nil;
  527. ResetValueCursor;
  528. end;}
  529. end;
  530. //NextNode;
  531. end;
  532. end;
  533. procedure TXMLRPCParser.EndArray;
  534. begin
  535. end;
  536. procedure TXMLRPCParser.NextNode;
  537. begin
  538. repeat
  539. CurDataNode := CurDataNode.NextSibling;
  540. until (not Assigned(CurDataNode)) or (CurDataNode.NodeType = ELEMENT_NODE);
  541. end;
  542. procedure TXMLRPCParser.PrevNode;
  543. begin
  544. {$IFDEF XMLRPCDebug}DumpNode(CurDataNode, 'PrevNode before> ');{$ENDIF}
  545. if Assigned(CurDataNode.PreviousSibling) then
  546. CurDataNode := CurDataNode.PreviousSibling
  547. else
  548. CurDataNode := CurDataNode.ParentNode.LastChild;
  549. {$IFDEF XMLRPCDebug}DumpNode(CurDataNode, 'PrevNode result> ');{$ENDIF}
  550. end;
  551. function TXMLRPCParser.GetValue: String;
  552. var
  553. Node: TDOMNode;
  554. begin
  555. if not Assigned(CurDataNode) then
  556. Result := ''
  557. else
  558. begin
  559. Node := CurDataNode;
  560. if Node.NodeName <> 'value' then
  561. Node := Node.FirstChild;
  562. Node := Node.FirstChild;
  563. if Node.NodeType = TEXT_NODE then
  564. Result := Node.NodeValue
  565. else begin
  566. while Assigned(Node) and (Node.NodeType <> ELEMENT_NODE) do
  567. Node := Node.NextSibling;
  568. if Assigned(Node) then
  569. begin
  570. Node := Node.FirstChild;
  571. if Assigned(Node) and (Node.NodeType = TEXT_NODE) then
  572. Result := Node.NodeValue
  573. else
  574. Result := '';
  575. end;
  576. end;
  577. end;
  578. end;
  579. function TXMLRPCParser.FindStructMember(AStruct: TXMLRPCStruct;
  580. const AMemberName: String): TDOMElement;
  581. var
  582. Node: TDOMNode;
  583. begin
  584. Result := TDOMElement(AStruct.FirstChild);
  585. while Assigned(Result) and (Result.NodeName = 'member') do
  586. begin
  587. Node := Result.FirstChild;
  588. while Assigned(Node) do
  589. begin
  590. if Node.NodeName = 'name' then
  591. begin
  592. if Assigned(Node.FirstChild) and
  593. (CompareText(Node.FirstChild.NodeValue, AMemberName) = 0) then
  594. exit;
  595. end;
  596. Node := Node.NextSibling;
  597. end;
  598. Result := TDOMElement(Result.NextSibling);
  599. end;
  600. end;
  601. function TXMLRPCParser.GetStructMemberValue(MemberNode: TDOMElement): String;
  602. var
  603. Node, Subnode: TDOMNode;
  604. begin
  605. Node := MemberNode.FirstChild;
  606. while Assigned(Node) do
  607. begin
  608. if Node.NodeName = 'value' then
  609. begin
  610. Subnode := Node.FirstChild;
  611. if Assigned(Subnode) and (Subnode.NodeType = TEXT_NODE) then
  612. begin
  613. Result := Subnode.NodeValue;
  614. exit;
  615. end;
  616. while Assigned(Subnode) do
  617. begin
  618. if Subnode.NodeType = ELEMENT_NODE then
  619. begin
  620. if Assigned(Subnode.FirstChild) then
  621. Result := Subnode.FirstChild.NodeValue
  622. else
  623. Result := '';
  624. exit;
  625. end;
  626. Subnode := Subnode.NextSibling;
  627. end;
  628. end;
  629. Node := Node.NextSibling;
  630. end;
  631. end;
  632. {$IFDEF NEVERTRUE}
  633. // XML-RPC Client
  634. constructor TXMLRPCClient.Create(AEventLoop: TEventLoop);
  635. begin
  636. inherited Create;
  637. FEventLoop := AEventLoop;
  638. end;
  639. procedure TXMLRPCClient.Call(ACallback: TOnXMLRPCCallCompleted;
  640. const AProcName: String; AArgs: array of const);
  641. var
  642. Host: String;
  643. Port: Word;
  644. Socket: TInetSocket;
  645. begin
  646. CurCallback := ACallback;
  647. MakeRequest(AProcName, AArgs);
  648. try
  649. ResponseStream := TMemoryStream.Create;
  650. if Assigned(OnBeginRPC) then
  651. OnBeginRPC(Self);
  652. Host := 'localhost';
  653. Port := 12345;
  654. Socket := TInetSocket.Create(Host, Port);
  655. try
  656. RequestStream.Position := 0;
  657. // Socket.Write(RequestStream.Memory^, RequestStream.Size);
  658. LocalEventLoop := TEventLoop.Create;
  659. try
  660. Connection := TCustomHttpClient.Create(LocalEventLoop, Socket);
  661. try
  662. Connection.HeaderToSend := THttpRequestHeader.Create;
  663. with THttpRequestHeader(Connection.HeaderToSend) do
  664. begin
  665. Command := 'POST';
  666. URI := '/xmlrpc';
  667. UserAgent := 'Free Pascal XML-RPC';
  668. ContentType := 'text/xml';
  669. ContentLength := RequestStream.Size;
  670. end;
  671. Connection.StreamToSend := RequestStream;
  672. Connection.ReceivedHeader := THttpResponseHeader.Create;
  673. Connection.ReceivedStream := ResponseStream;
  674. Connection.OnStreamSent := @StreamSent;
  675. Connection.Send;
  676. LocalEventLoop.Run;
  677. finally
  678. if Assigned(Connection) then
  679. begin
  680. Connection.HeaderToSend.Free;
  681. Connection.ReceivedHeader.Free;
  682. end;
  683. Connection.Free;
  684. end;
  685. finally
  686. LocalEventLoop.Free;
  687. end;
  688. finally
  689. Socket.Free;
  690. end;
  691. finally
  692. FreeAndNil(RequestStream);
  693. end;
  694. // HTTPConnection.Post(ServerURL, RequestStream, ResponseStream);
  695. ProcessAnswer;
  696. end;
  697. procedure TXMLRPCClient.CallAsync(ACallback: TOnXMLRPCCallCompleted;
  698. const AProcName: String; AArgs: array of const);
  699. begin
  700. CurCallback := ACallback;
  701. MakeRequest(AProcName, AArgs);
  702. ResponseStream := TMemoryStream.Create;
  703. if Assigned(OnBeginRPC) then
  704. OnBeginRPC(Self);
  705. // CurRPCThread := TRPCThread.Create(Self);
  706. end;
  707. procedure TXMLRPCClient.MakeRequest(const AProcName: String;
  708. AArgs: array of const);
  709. var
  710. Writer: TXMLRPCWriter;
  711. Params: TXMLRPCParams;
  712. i: Integer;
  713. begin
  714. Writer := TXMLRPCWriter.Create;
  715. try
  716. Params := Writer.CreateParams;
  717. try
  718. for i := Low(AArgs) to High(AArgs) do
  719. with AArgs[i] do
  720. case VType of
  721. vtInteger: Writer.AddParam(Params, Writer.CreateIntValue(VInteger));
  722. vtBoolean: Writer.AddParam(Params, Writer.CreateBooleanValue(VBoolean));
  723. vtChar: Writer.AddParam(Params, Writer.CreateStringValue(VChar));
  724. vtExtended: Writer.AddParam(Params, Writer.CreateDoubleValue(VExtended^));
  725. vtString: Writer.AddParam(Params, Writer.CreateStringValue(VString^));
  726. vtPChar: Writer.AddParam(Params, Writer.CreateStringValue(VPChar));
  727. vtWideChar: Writer.AddParam(Params, Writer.CreateStringValue(VWideChar));
  728. vtPWideChar: Writer.AddParam(Params, Writer.CreateStringValue(VPWideChar));
  729. vtAnsiString: Writer.AddParam(Params, Writer.CreateStringValue(String(VAnsiString)));
  730. // vtCurrency: ?
  731. // vtVariant: ?
  732. vtInt64: Writer.AddParam(Params, Writer.CreateIntValue(VInt64^));
  733. else
  734. raise Exception.Create('Unsupported data type in RPC argument list');
  735. end;
  736. Writer.WriteMethodCall(AProcName, Params);
  737. RequestStream := Writer.MakeStream;
  738. except
  739. Params.Free;
  740. end;
  741. finally
  742. Writer.Free;
  743. end;
  744. end;
  745. procedure TXMLRPCClient.ProcessAnswer;
  746. var
  747. Parser: TXMLRPCParser;
  748. begin
  749. ResponseStream.Position := 0;
  750. Parser := TXMLRPCParser.Create(ResponseStream);
  751. FreeAndNil(ResponseStream);
  752. try
  753. case Parser.GetPostType of
  754. xmlrpcFaultResponse:
  755. } {raise Exception.Create(Format('%d - %s', [Parser.GetNextInt,
  756. Parser.GetNextString]));}
  757. { raise Exception.Create('Fehler bei XML-RPC-Befehlsausführung');
  758. xmlrpcResponse:
  759. if Assigned(CurCallback) then
  760. CurCallback(Parser);
  761. else
  762. raise Exception.Create('Invalid response');
  763. end;
  764. finally
  765. Parser.Free;
  766. if Assigned(OnEndRPC) then
  767. OnEndRPC(Self);
  768. end;
  769. end;
  770. procedure TXMLRPCClient.StreamSent(Sender: TObject);
  771. begin
  772. // LocalEventLoop.Break;
  773. Connection.Receive;
  774. end;
  775. procedure TXMLRPCClient.DataAvailable(Sender: TObject);
  776. begin
  777. LocalEventLoop.Break;
  778. end;
  779. }
  780. {$ENDIF NEVERTRUE}
  781. // XML-RPC Server
  782. procedure TXMLRPCServlet.DoPost(Req: THttpServletRequest;
  783. Resp: THttpServletResponse);
  784. var
  785. Parser: TXMLRPCParser;
  786. Writer: TXMLRPCWriter;
  787. Path: TStringList;
  788. LastDot, i: Integer;
  789. s, PathStr: String;
  790. AnswerStream: TStream;
  791. ExecCall: Boolean;
  792. begin
  793. Parser := TXMLRPCParser.Create(Req.InputStream);
  794. try
  795. if Parser.GetPostType <> xmlrpcMethodCall then
  796. exit;
  797. Resp.ContentType := 'text/xml';
  798. Writer := TXMLRPCWriter.Create;
  799. try
  800. try
  801. // ...Header auswerten und zum Dispatcher springen...
  802. PathStr := Parser.GetMethodName + '.';
  803. Path := TStringList.Create;
  804. try
  805. LastDot := 1;
  806. for i := 1 to Length(PathStr) do
  807. if PathStr[i] = '.' then
  808. begin
  809. Path.Add(UpperCase(Copy(PathStr, LastDot, i - LastDot)));
  810. LastDot := i + 1;
  811. end;
  812. ExecCall := True;
  813. if Assigned(OnCheckCall) then
  814. OnCheckCall(Parser, Path, ExecCall);
  815. if ExecCall then
  816. Dispatch(Parser, Writer, Path)
  817. else
  818. Writer.WriteFaultResponse(2, 'May not execute request');
  819. finally
  820. Path.Free;
  821. end;
  822. except
  823. on e: Exception do
  824. begin
  825. if Assigned(OnException) then
  826. OnException(e);
  827. Writer.WriteFaultResponse(2,
  828. 'Execution error: ' + e.ClassName + ': ' + e.Message);
  829. end;
  830. end;
  831. AnswerStream := Writer.MakeStream;
  832. try
  833. Resp.ContentLength := AnswerStream.Size;
  834. Resp.OutputStream.CopyFrom(AnswerStream, AnswerStream.Size);
  835. finally
  836. AnswerStream.Free;
  837. end;
  838. finally
  839. Writer.Free;
  840. end;
  841. finally
  842. Parser.Free;
  843. end;
  844. end;
  845. end.