Fixed build on MacOSX
[pwlib.git] / include / ptclib / pxmlrpc.h
blob97d206eb75f5e16d160d90ce3eda58fa5752619d
1 /*
2 * pxmlrpc.h
4 * XML/RPC support
6 * Portable Windows Library
8 * Copyright (c) 2002 Equivalence Pty. Ltd.
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.0 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
15 * Software distributed under the License is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17 * the License for the specific language governing rights and limitations
18 * under the License.
20 * The Original Code is Portable Windows Library.
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24 * Contributor(s): ______________________________________.
26 * $Log$
27 * Revision 1.20 2004/05/17 06:05:20 csoutheren
28 * Changed "make docs" to use doxygen
29 * Added new config file and main page
31 * Revision 1.19 2003/04/15 07:08:36 robertj
32 * Changed read and write from streams for base array classes so operates in
33 * the same way for both PIntArray and PArray<int> etc
35 * Revision 1.18 2003/04/15 03:00:41 robertj
36 * Added array support to XML/RPC
37 * Fixed XML/RPC parsing when lots of white space in raw XML, caused by
38 * big fix to base XML parser not returning internal data elements.
40 * Revision 1.17 2003/01/28 05:08:07 robertj
41 * Fixed copy constructor on function arguments and return value
43 * Revision 1.16 2002/12/16 06:57:15 robertj
44 * Added ability to specify certain elemets (by name) that are exempt from
45 * the indent formatting. Useful for XML/RPC where leading white space is
46 * not ignored by all servers.
47 * Improved the macros for defining RPC functions.
49 * Revision 1.15 2002/12/13 01:04:56 robertj
50 * Added copy constructor and assignment operator to XML/RPC structs
52 * Revision 1.14 2002/12/10 04:44:43 robertj
53 * Added support in PTime for ISO 8601 format.
55 * Revision 1.13 2002/12/09 04:06:18 robertj
56 * Added macros for defining multi-argument functions
58 * Revision 1.12 2002/12/04 02:09:26 robertj
59 * Changed macro name prefix to PXMLRPC
61 * Revision 1.11 2002/12/04 00:31:13 robertj
62 * Fixed GNU compatibility
64 * Revision 1.10 2002/12/04 00:15:56 robertj
65 * Large enhancement to create automatically encoding and decoding structures
66 * using macros to build a class.
68 * Revision 1.9 2002/11/06 22:47:24 robertj
69 * Fixed header comment (copyright etc)
71 * Revision 1.8 2002/10/02 08:54:34 craigs
72 * Added support for XMLRPC server
74 * Revision 1.7 2002/09/16 01:08:59 robertj
75 * Added #define so can select if #pragma interface/implementation is used on
76 * platform basis (eg MacOS) rather than compiler, thanks Robert Monaghan.
78 * Revision 1.6 2002/08/13 03:02:07 robertj
79 * Removed previous fix for memory leak, as object was already deleted.
81 * Revision 1.5 2002/08/13 01:55:00 craigs
82 * Fixed memory leak on PXMLRPCRequest class
84 * Revision 1.4 2002/08/06 01:04:03 robertj
85 * Fixed missing pragma interface/implementation
87 * Revision 1.3 2002/07/12 05:51:14 craigs
88 * Added structs to XMLRPC response types
90 * Revision 1.2 2002/03/27 00:50:44 craigs
91 * Fixed problems with parsing faults and creating structs
93 * Revision 1.1 2002/03/26 07:06:50 craigs
94 * Initial version
98 #ifndef _PXMLRPC_H
99 #define _PXMLRPC_H
101 #ifdef P_USE_PRAGMA
102 #pragma interface
103 #endif
105 #include <ptclib/pxml.h>
106 #include <ptclib/url.h>
109 class PXMLRPCBlock;
110 class PXMLRPCVariableBase;
111 class PXMLRPCStructBase;
114 /////////////////////////////////////////////////////////////////
116 class PXMLRPC : public PObject
118 PCLASSINFO(PXMLRPC, PObject);
119 public:
120 enum {
121 CannotCreateRequestXML = 100,
122 CannotParseResponseXML,
123 CannotParseRequestXML,
124 HTTPPostFailed,
125 CannotReadResponseContentBody,
126 ResponseRootNotMethodResponse,
127 ResponseEmpty,
128 ResponseUnknownFormat,
129 ParamNotValue,
130 ScalarWithoutElement,
131 ParamNotStruct,
132 MemberIncomplete,
133 MemberUnnamed,
134 FaultyFault,
135 RequestHasWrongDocumentType,
136 RequestHasNoMethodName,
137 RequestHasNoParms,
138 MethodNameIsEmpty,
139 UnknownMethod,
140 ParamNotArray,
142 UserFault = 1000,
145 PXMLRPC(
146 const PURL & url,
147 unsigned options = 0
150 void SetTimeout(const PTimeInterval & _timeout) { timeout = _timeout; }
152 BOOL MakeRequest(const PString & method);
153 BOOL MakeRequest(const PString & method, PXMLRPCBlock & response);
154 BOOL MakeRequest(PXMLRPCBlock & request, PXMLRPCBlock & response);
155 BOOL MakeRequest(const PString & method, const PXMLRPCStructBase & args, PXMLRPCStructBase & reply);
157 PString GetFaultText() const { return faultText; }
158 PINDEX GetFaultCode() const { return faultCode; }
160 static BOOL ISO8601ToPTime(const PString & iso8601, PTime & val, int tz = PTime::GMT);
161 static PString PTimeToISO8601(const PTime & val);
163 protected:
164 BOOL PerformRequest(PXMLRPCBlock & request, PXMLRPCBlock & response);
166 PURL url;
167 PINDEX faultCode;
168 PString faultText;
169 PTimeInterval timeout;
170 unsigned options;
173 /////////////////////////////////////////////////////////////////
175 class PXMLRPCBlock : public PXML
177 PCLASSINFO(PXMLRPCBlock, PXML);
178 public:
179 PXMLRPCBlock();
180 PXMLRPCBlock(const PString & method);
181 PXMLRPCBlock(const PString & method, const PXMLRPCStructBase & structData);
183 BOOL Load(const PString & str);
185 PXMLElement * GetParams();
186 PXMLElement * GetParam(PINDEX idx) const;
187 PINDEX GetParamCount() const;
189 // used when used as a response
190 PINDEX GetFaultCode() const { return faultCode; }
191 PString GetFaultText() const { return faultText; }
192 void SetFault(PINDEX code, const PString & text) { faultCode = code; faultText = text; }
193 BOOL ValidateResponse();
195 // helper functions for getting parameters
196 BOOL GetParams(PXMLRPCStructBase & data);
197 BOOL GetParam(PINDEX idx, PString & type, PString & result);
198 BOOL GetExpectedParam(PINDEX idx, const PString & expectedType, PString & value);
200 BOOL GetParam(PINDEX idx, PString & result);
201 BOOL GetParam(PINDEX idx, int & result);
202 BOOL GetParam(PINDEX idx, double & result);
203 BOOL GetParam(PINDEX idx, PTime & result, int tz = PTime::GMT);
204 BOOL GetParam(PINDEX idx, PStringToString & result);
205 BOOL GetParam(PINDEX idx, PXMLRPCStructBase & result);
206 BOOL GetParam(PINDEX idx, PStringArray & result);
207 BOOL GetParam(PINDEX idx, PArray<PStringToString> & result);
209 // static functions for parsing values
210 BOOL ParseScalar(PXMLElement * element, PString & type, PString & value);
211 BOOL ParseStruct(PXMLElement * element, PStringToString & structDict);
212 BOOL ParseStruct(PXMLElement * element, PXMLRPCStructBase & structData);
213 BOOL ParseArray(PXMLElement * element, PStringArray & array);
214 BOOL ParseArray(PXMLElement * element, PArray<PStringToString> & array);
215 BOOL ParseArray(PXMLElement * element, PXMLRPCVariableBase & array);
217 // static functions for creating values
218 static PXMLElement * CreateValueElement(PXMLElement * element);
219 static PXMLElement * CreateScalar(const PString & type, const PString & scalar);
220 static PXMLElement * CreateMember(const PString & name, PXMLElement * value);
222 static PXMLElement * CreateScalar(const PString & str);
223 static PXMLElement * CreateScalar(int value);
224 static PXMLElement * CreateScalar(double value);
225 static PXMLElement * CreateDateAndTime(const PTime & time);
226 static PXMLElement * CreateBinary(const PBYTEArray & data);
228 static PXMLElement * CreateStruct();
229 static PXMLElement * CreateStruct(const PStringToString & dict);
230 static PXMLElement * CreateStruct(const PStringToString & dict, const PString & typeStr);
231 static PXMLElement * CreateStruct(const PXMLRPCStructBase & structData);
233 static PXMLElement * CreateArray(const PStringArray & array);
234 static PXMLElement * CreateArray(const PStringArray & array, const PString & typeStr);
235 static PXMLElement * CreateArray(const PStringArray & array, const PStringArray & types);
236 static PXMLElement * CreateArray(const PArray<PStringToString> & array);
237 static PXMLElement * CreateArray(const PXMLRPCVariableBase & array);
239 // helper functions for adding parameters
240 void AddParam(PXMLElement * parm);
241 void AddParam(const PString & str);
242 void AddParam(int value);
243 void AddParam(double value);
244 void AddParam(const PTime & time);
245 void AddParam(const PXMLRPCStructBase & structData);
246 void AddBinary(const PBYTEArray & data);
247 void AddStruct(const PStringToString & dict);
248 void AddStruct(const PStringToString & dict, const PString & typeStr);
249 void AddArray(const PStringArray & array);
250 void AddArray(const PStringArray & array, const PString & typeStr);
251 void AddArray(const PStringArray & array, const PStringArray & types);
252 void AddArray(const PArray<PStringToString> & array);
254 protected:
255 PXMLElement * params;
256 PString faultText;
257 PINDEX faultCode;
261 /////////////////////////////////////////////////////////////////
263 class PXMLRPCVariableBase : public PObject {
264 PCLASSINFO(PXMLRPCVariableBase, PObject);
265 protected:
266 PXMLRPCVariableBase(const char * name, const char * type = NULL);
268 public:
269 const char * GetName() const { return name; }
270 const char * GetType() const { return type; }
272 virtual void Copy(const PXMLRPCVariableBase & other) = 0;
273 virtual PString ToString(PINDEX i) const;
274 virtual void FromString(PINDEX i, const PString & str);
275 virtual PXMLRPCStructBase * GetStruct(PINDEX i) const;
276 virtual BOOL IsArray() const;
277 virtual PINDEX GetSize() const;
278 virtual BOOL SetSize(PINDEX);
280 PString ToBase64(PAbstractArray & data) const;
281 void FromBase64(const PString & str, PAbstractArray & data);
283 protected:
284 const char * name;
285 const char * type;
287 private:
288 PXMLRPCVariableBase(const PXMLRPCVariableBase &) { }
292 class PXMLRPCArrayBase : public PXMLRPCVariableBase {
293 PCLASSINFO(PXMLRPCArrayBase, PXMLRPCVariableBase);
294 protected:
295 PXMLRPCArrayBase(PContainer & array, const char * name, const char * type);
296 PXMLRPCArrayBase & operator=(const PXMLRPCArrayBase &);
298 public:
299 virtual void PrintOn(ostream & strm) const;
300 virtual void Copy(const PXMLRPCVariableBase & other);
301 virtual BOOL IsArray() const;
302 virtual PINDEX GetSize() const;
303 virtual BOOL SetSize(PINDEX);
305 protected:
306 PContainer & array;
310 class PXMLRPCArrayObjectsBase : public PXMLRPCArrayBase {
311 PCLASSINFO(PXMLRPCArrayObjectsBase, PXMLRPCArrayBase);
312 protected:
313 PXMLRPCArrayObjectsBase(PArrayObjects & array, const char * name, const char * type);
314 PXMLRPCArrayObjectsBase & operator=(const PXMLRPCArrayObjectsBase &);
316 public:
317 virtual PString ToString(PINDEX i) const;
318 virtual void FromString(PINDEX i, const PString & str);
319 virtual BOOL SetSize(PINDEX);
321 virtual PObject * CreateObject() const = 0;
323 protected:
324 PArrayObjects & array;
328 class PXMLRPCStructBase : public PObject {
329 PCLASSINFO(PXMLRPCStructBase, PObject);
330 protected:
331 PXMLRPCStructBase();
332 PXMLRPCStructBase & operator=(const PXMLRPCStructBase &);
333 private:
334 PXMLRPCStructBase(const PXMLRPCStructBase &) { }
336 public:
337 void PrintOn(ostream & strm) const;
339 PINDEX GetNumVariables() const { return variablesByOrder.GetSize(); }
340 PXMLRPCVariableBase & GetVariable(PINDEX idx) const { return variablesByOrder[idx]; }
341 PXMLRPCVariableBase * GetVariable(const char * name) const { return variablesByName.GetAt(name); }
343 void AddVariable(PXMLRPCVariableBase * var);
344 static PXMLRPCStructBase & GetInitialiser() { return *PAssertNULL(initialiserInstance); }
346 protected:
347 void EndConstructor();
349 PList<PXMLRPCVariableBase> variablesByOrder;
350 PDictionary<PString, PXMLRPCVariableBase> variablesByName;
352 PXMLRPCStructBase * initialiserStack;
353 static PMutex initialiserMutex;
354 static PXMLRPCStructBase * initialiserInstance;
358 #define PXMLRPC_STRUCT_BEGIN(name) \
359 class name : public PXMLRPCStructBase { \
360 public: name() { EndConstructor(); } \
361 public: name(const name & other) { EndConstructor(); operator=(other); } \
362 public: name & operator=(const name & other) { PXMLRPCStructBase::operator=(other); return *this; }
364 #define PXMLRPC_VARIABLE_CLASS(base, type, variable, xmltype, init, extras) \
365 private: struct PXMLRPCVar_##variable : public PXMLRPCVariableBase { \
366 PXMLRPCVar_##variable() \
367 : PXMLRPCVariableBase(#variable, xmltype), \
368 instance(((base &)base::GetInitialiser()).variable) \
369 { init } \
370 virtual void PrintOn (ostream & s) const { s << instance; } \
371 virtual void ReadFrom(istream & s) { s >> instance; } \
372 virtual void Copy(const PXMLRPCVariableBase & other) \
373 { instance = ((PXMLRPCVar_##variable &)other).instance; } \
374 extras \
375 type & instance; \
376 } pxmlrpcvar_##variable
378 #define PXMLRPC_VARIABLE_CUSTOM(base, type, variable, xmltype, init, extras) \
379 public: type variable; \
380 PXMLRPC_VARIABLE_CLASS(base, type, variable, xmltype, init, extras)
382 #define PXMLRPC_ARRAY_CUSTOM(base, arraytype, basetype, variable, xmltype, par, extras) \
383 public: arraytype variable; \
384 private: struct PXMLRPCVar_##variable : public par { \
385 PXMLRPCVar_##variable() \
386 : par(((base &)base::GetInitialiser()).variable, #variable, xmltype), \
387 instance((arraytype &)array) \
388 { } \
389 extras \
390 arraytype & instance; \
391 } pxmlrpcvar_##variable
392 #ifdef DOCPLUSPLUS
394 #endif
397 #define PXMLRPC_STRUCT_END() \
401 #define PXMLRPC_VARIABLE(base, type, variable, xmltype) \
402 PXMLRPC_VARIABLE_CUSTOM(base, type, variable, xmltype, ;, ;)
405 #define PXMLRPC_VARIABLE_INIT(base, type, variable, xmltype, init) \
406 PXMLRPC_VARIABLE_CUSTOM(base, type, variable, xmltype, instance=init;, ;)
409 #define PXMLRPC_STRING(base, type, variable) \
410 PXMLRPC_VARIABLE(base, type, variable, "string")
413 #define PXMLRPC_STRING_INIT(base, type, variable, init) \
414 PXMLRPC_VARIABLE_INIT(base, type, variable, "string", init)
417 #define PXMLRPC_INTEGER(base, type, variable) \
418 PXMLRPC_VARIABLE(base, type, variable, "int")
421 #define PXMLRPC_INTEGER_INIT(base, type, variable, init) \
422 PXMLRPC_VARIABLE_INIT(base, type, variable, "int", init)
425 #define PXMLRPC_BOOLEAN(base, type, variable) \
426 PXMLRPC_VARIABLE(base, type, variable, "boolean")
429 #define PXMLRPC_BOOLEAN_INIT(base, type, variable, init) \
430 PXMLRPC_VARIABLE_INIT(base, type, variable, "boolean", init)
433 #define PXMLRPC_DOUBLE(base, type, variable) \
434 PXMLRPC_VARIABLE(base, type, variable, "double")
437 #define PXMLRPC_DOUBLE_INIT(base, type, variable, init) \
438 PXMLRPC_VARIABLE_INIT(base, type, variable, "double", init)
441 #define PXMLRPC_DATETIME(base, type, variable) \
442 PXMLRPC_VARIABLE_CUSTOM(base, type, variable, "dateTime.iso8601", ;, \
443 PString ToString(PINDEX) const { return instance.AsString(PTime::ShortISO8601); } )
446 #define PXMLRPC_BINARY(base, type, variable) \
447 PXMLRPC_VARIABLE_CUSTOM(base, type, variable, "base64", ;, \
448 PString ToString(PINDEX) const { return ToBase64(instance); } \
449 void FromString(PINDEX, const PString & str) { FromBase64(str, instance); } )
452 #define PXMLRPC_STRUCT(base, type, variable) \
453 PXMLRPC_VARIABLE_CUSTOM(base, type, variable, "struct", ;, \
454 PXMLRPCStructBase * GetStruct(PINDEX) const { return &instance; } )
457 #define PXMLRPC_ARRAY(base, arraytype, basetype, variable, xmltype) \
458 PXMLRPC_ARRAY_CUSTOM(base, arraytype, basetype, variable, xmltype, PXMLRPCArrayObjectsBase, \
459 PObject * CreateObject() const { return new basetype; })
462 #define PXMLRPC_ARRAY_STRING(base, arraytype, basetype, variable) \
463 PXMLRPC_ARRAY(base, arraytype, basetype, variable, "string")
465 #define PXMLRPC_ARRAY_INTEGER(base, type, variable) \
466 PXMLRPC_ARRAY_CUSTOM(base, PScalarArray<type>, type, variable, "int", PXMLRPCArrayBase, \
467 PString ToString(PINDEX i) const { return PString(instance[i]); } \
468 void FromString(PINDEX i, const PString & str) { instance[i] = (type)str.AsInteger(); })
470 #define PXMLRPC_ARRAY_DOUBLE(base, type, variable) \
471 PXMLRPC_ARRAY_CUSTOM(base, PScalarArray<type>, type, variable, "double", PXMLRPCArrayBase, \
472 PString ToString(PINDEX i) const { return psprintf("%f", instance[i]); } \
473 void FromString(PINDEX i, const PString & str) { instance[i] = (type)str.AsReal(); })
475 #define PXMLRPC_ARRAY_STRUCT(base, type, variable) \
476 PXMLRPC_ARRAY_CUSTOM(base, PArray<type>, type, variable, "struct", PXMLRPCArrayObjectsBase, \
477 PXMLRPCStructBase * GetStruct(PINDEX i) const { return &instance[i]; } \
478 PObject * CreateObject() const { return new type; })
481 #define PXMLRPC_FUNC_NOARG_NOREPLY(name) \
482 BOOL name() { return MakeRequest(#name); }
485 #define PXMLRPC_FUNC_SINGLE_ARG(name, vartype, argtype) \
486 class name##_in : public PXMLRPCStructBase { \
487 public: name##_in(const argtype & var) : variable(var) { EndConstructor(); } \
488 vartype(name##_in, argtype, variable);
491 #define PXMLRPC_FUNC_MULTI_ARGS(name) \
492 PXMLRPC_STRUCT_BEGIN(name##_in)
495 #ifdef DOCPLUSPLUS
497 #endif
498 #define PXMLRPC_FUNC_MULTI_REPLY(name) \
499 }; PXMLRPC_STRUCT_BEGIN(name##_out)
502 #ifdef DOCPLUSPLUS
504 #endif
505 #define PXMLRPC_FUNC_NO_ARGS(name) \
506 }; \
507 BOOL name(name##_out & reply) \
508 { return MakeRequest(#name, name##_in(), reply); }
511 #ifdef DOCPLUSPLUS
513 #endif
514 #define PXMLRPC_FUNC_STRUCT_ARG(name) \
515 }; \
516 class name##_in_carrier : public PXMLRPCStructBase { \
517 public: name##_in_carrier(const name##_in & var) : variable(var) { EndConstructor(); } \
518 private: struct var_class : public PXMLRPCVariableBase { \
519 var_class(const name##_in & var) \
520 : PXMLRPCVariableBase("variable", "struct"), instance(var) { } \
521 virtual void PrintOn (ostream & s) const { s << instance; } \
522 virtual PXMLRPCStructBase * GetStruct(PINDEX) const { return (PXMLRPCStructBase *)&instance; } \
523 virtual void Copy(const PXMLRPCVariableBase &) { } \
524 const name##_in & instance; \
525 } variable; \
526 }; \
527 BOOL name(const name##_in & args, name##_out & reply) \
528 { return MakeRequest(#name, name##_in_carrier(args), reply); }
531 #ifdef DOCPLUSPLUS
533 #endif
534 #define PXMLRPC_FUNC_NORM_ARGS(name) \
535 }; \
536 BOOL name(const name##_in & args, name##_out & reply) \
537 { return MakeRequest(#name, args, reply); }
541 /////////////////////////////////////////////////////////////////
544 #endif