xmlrpc.h

Go to the documentation of this file.
00001 
00002  //
00003  // XMLStorage XML-RPC extension
00004  //
00005  // Copyright (c) 2009, 2014 Martin Fuchs <martin-fuchs@gmx.net>
00006  //
00007 
00008 
00009 /*
00010 
00011   All rights reserved.
00012 
00013   Redistribution and use in source and binary forms, with or without
00014   modification, are permitted provided that the following conditions are met:
00015 
00016   * Redistributions of source code must retain the above copyright
00017     notice, this list of conditions and the following disclaimer.
00018   * Redistributions in binary form must reproduce the above copyright
00019     notice, this list of conditions and the following disclaimer in
00020     the documentation and/or other materials provided with the
00021     distribution.
00022 
00023   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00024   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00025   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00026   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00027   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00028   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00029   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00030   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00031   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00032   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033   POSSIBILITY OF SUCH DAMAGE.
00034 
00035 */
00036 
00037 #pragma once
00038 
00039 #ifndef __XMLRPC_H
00040 
00041 
00042 #if _MSC_VER>=1400 // VS2005 or higher
00043 // define _CRT_SECURE_CPP_OVERLOAD_... before including any system header file to be compatible to xmlstorage.h
00044 #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES         1
00045 #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES_COUNT   1
00046 #define _CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES           1
00047 #else
00048 #endif
00049 
00050 #ifndef _MSC_VER
00051 #define _strnicmp strncasecmp
00052 #endif
00053 
00054 #ifdef _WIN32
00055 #include <winsock2.h>
00056 #include <ws2tcpip.h>   // getaddrinfo()
00057 #pragma comment(lib, "ws2_32")
00058 #else
00059 #include <netdb.h>
00060 #include <errno.h>
00061 #endif
00062 
00063 #include <xmlstorage.h> // define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES before including any other system header file
00064 using namespace XMLStorage;
00065 
00066 #ifndef __STDC_WANT_SECURE_LIB__
00067 #define sscanf_s sscanf // beware: format strings for sscanf_s() and sscanf() are only identically, if no string buffers are used to return strings!
00068 #endif
00069 
00070 using namespace std;
00071 
00072 #include <assert.h>
00073 
00074 
00075 namespace XMLRPC {
00076 
00077 
00078 struct Exception : public exception
00079 {
00080     Exception(const char* msg, int code=0)
00081      :  _msg(msg),
00082         _code(code)
00083     {
00084     }
00085 
00086     ~Exception() throw()
00087     {
00088     }
00089 
00090     const char* what() const throw()
00091     {
00092         return _msg.c_str();
00093     }
00094 
00095 protected:
00096     string  _msg;
00097     int _code;
00098 
00099     Exception(int code=0)
00100      :  _code(code)
00101     {
00102     }
00103 };
00104 
00105 
00106 #ifdef _WIN32
00107 
00108  // Exception for Windows errors
00109 struct WE : public Exception
00110 {
00111     WE(DWORD code)
00112      :  Exception(code)
00113     {
00114         LPSTR buffer;
00115 
00116         if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
00117             0, code, MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT), (LPSTR)&buffer, 0, NULL)) {
00118             _msg = buffer;
00119             LocalFree(buffer);
00120         } else {
00121             char b[64];
00122             sprintf(b, "unknown error 0x%08X", (unsigned)code);
00123             _msg = b;
00124         }
00125     }
00126 };
00127 
00128  // Exception for the last operating system error code
00129 struct LWE : public WE
00130 {
00131     LWE()
00132      : WE(GetLastError())
00133     {
00134     }
00135 };
00136 
00137  // WINSOCK exception
00138 struct LWSE : public WE
00139 {
00140     LWSE()
00141      : WE(WSAGetLastError())
00142     {
00143     }
00144 };
00145 
00146 #else
00147 
00148  // operating system error exception
00149 struct LWSE : public Exception
00150 {
00151     LWSE()
00152      :  Exception(errno)
00153     {
00154         _msg = strerror(_code);
00155     }
00156 };
00157 
00158 #endif // _WIN32
00159 
00160 
00161  // ISO 8601 conforming date
00162 struct ISODate
00163 {
00164     ISODate();  // initialized with current date+time
00165     ISODate(const char* s);
00166 
00167     string  str() const;
00168     long    diff(const ISODate& other) const;
00169 
00170     int _year;
00171     int _month;
00172     int _day;
00173 
00174     int _hour;
00175     int _minute;
00176     int _second;
00177 };
00178 
00179 extern char* base64_encode(const void* buf, size_t size);
00180 extern void* base64_decode(const char* s, size_t& data_len);
00181 
00182  // BASE64 encoded binary
00183 struct Binary
00184 {
00185     Binary(const void* buffer, size_t len);
00186     Binary(const char* base64);
00187     Binary(const Binary& other);
00188     ~Binary() {free(_buffer);}
00189 
00190     string str() const;
00191 
00192     void* _buffer;
00193     size_t  _len;
00194 };
00195 
00196 
00197 struct XMLRPCArray : public list<string>
00198 {
00199     XMLRPCArray() {}
00200     XMLRPCArray(const_XMLPos pos);
00201 };
00202 
00203 struct XMLRPCStruct : public map<string, string>
00204 {
00205     XMLRPCStruct() {}
00206     XMLRPCStruct(const XMLNode& node);
00207 };
00208 
00209 
00210  // Exception for failures received from the server
00211 struct XMLRPCFault : public Exception
00212 {
00213     XMLRPCFault(int faultCode, const string& faultString)
00214      :  Exception(faultCode)
00215     {
00216         ostringstream buffer;
00217 
00218         buffer << "XMLRPCFault " << _code << ": " << faultString;
00219 
00220         _msg = buffer.str();
00221     }
00222 };
00223 
00224 
00225 enum XMLRPC_TYPE
00226 {
00227     XRT_VOID,
00228     XRT_INT, XRT_DOUBLE, XRT_BOOLEAN, XRT_STRING,
00229     XRT_DATE, XRT_BINARY, XRT_ARRAY, XRT_STRUCT
00230 };
00231 
00232 typedef list<XMLRPC_TYPE> TypeList;
00233 
00234 
00235 struct XMLRPCParser
00236 {
00237     XMLRPCParser(const string& xml_str, const string& keyword);
00238 
00239     string  get_any();
00240     int     get_int();
00241     double  get_double();
00242     bool    get_bool();
00243     string  get_string();
00244     ISODate get_date();
00245     Binary  get_binary();
00246     XMLRPCArray get_array();
00247     XMLRPCStruct get_struct();
00248 
00249     bool    more_parameters() const;
00250     XMLRPC_TYPE get_next_type() const;
00251     size_t  get_parameter_types(TypeList& types) const;
00252 
00253 protected:
00254     XMLDoc  _doc;
00255     XMLPos  _pos;
00256     int     _value_cnt;
00257 
00258 private:
00259     bool    next_parameter();
00260 
00261     static XMLRPC_TYPE get_param_type(const XMLNode* pNode);
00262 };
00263 
00264  // read single values from the XML data
00265 struct XMLRPCValue
00266 {
00267     static string   get_any(const_XMLPos pos);
00268     static int      get_int(const_XMLPos pos);
00269     static double   get_double(const_XMLPos pos);
00270     static bool     get_bool(const_XMLPos pos);
00271     static string   get_string(const_XMLPos pos);
00272     static ISODate  get_date(const_XMLPos pos);
00273     static Binary   get_binary(const_XMLPos pos);
00274     static XMLRPCArray get_array(const_XMLPos pos);
00275     static XMLRPCStruct get_struct(const_XMLPos pos);
00276 };
00277 
00278 
00279  // decode the response received from the server
00280 struct XMLRPCResult : public XMLRPCParser
00281 {
00282     XMLRPCResult(const string& xml_str);
00283 
00284     string  _fault;
00285 };
00286 
00287 
00288 struct XMLRPCWriter
00289 {
00290     XMLRPCWriter() : _writer(_buffer, PRETTY_PLAIN), _params(0) {}
00291 
00292     string  flush();
00293 
00294 protected:
00295     void    write_string_param(const string& value);
00296     void    write_param(const string& type, const string& value);
00297     void    write_param(const XMLRPCArray& arr);
00298     void    write_param(const XMLRPCStruct& str);
00299     void    write_struct(const XMLRPCStruct& str, const string& keyword);
00300 
00301     ostringstream _buffer;
00302     XMLWriter   _writer;
00303     int _params;
00304 };
00305 
00306 
00307  // XMLRPCCall is used for calling a XML-RPC function from the client.
00308 struct XMLRPCCall : public XMLRPCWriter
00309 {
00310     XMLRPCCall(const char* name);
00311 
00312     XMLRPCCall& operator%(int i4)                   {write_param("i4", XMLInt(i4));                 return *this;}
00313     XMLRPCCall& operator%(double d)                 {write_param("double", XMLDouble(d));           return *this;}
00314     XMLRPCCall& operator%(bool b)                   {write_param("boolean", b? "1": "0");           return *this;}
00315     XMLRPCCall& operator%(const string& s)          {write_string_param(s);                         return *this;}
00316     XMLRPCCall& operator%(const char* s)            {write_string_param(s);                         return *this;}
00317     XMLRPCCall& operator%(const ISODate& date)      {write_param("dateTime.iso8601", date.str());   return *this;}
00318     XMLRPCCall& operator%(const Binary& bin)        {write_param("base64", bin.str());              return *this;}
00319     XMLRPCCall& operator%(const XMLRPCArray& arr)   {write_param(arr);}
00320     XMLRPCCall& operator%(const XMLRPCStruct& str)  {write_param(str);}
00321 
00322 private:
00323     void    init(const char* name);
00324 };
00325 
00326 
00327  // Decoding a request received from the client
00328 struct XMLRPCRequest : public XMLRPCParser
00329 {
00330     XMLRPCRequest(const string& xml_str);
00331 
00332     string  _method_name;
00333 };
00334 
00335  // XMLRPCResponse is used for creating a answer for a XML-RPC request in the server.
00336 struct XMLRPCResponse : public XMLRPCWriter
00337 {
00338     XMLRPCResponse()
00339     {
00340         init();
00341     }
00342 
00343     void    set_int(int i4)                     {write_param("i4", XMLInt(i4));}
00344     void    set_double(double d)                {write_param("double", XMLDouble(d));}
00345     void    set_bool(bool b)                    {write_param("boolean", b? "1": "0");}
00346     void    set_string(const string& s)         {write_string_param(s);}
00347     void    set_string(const char* s)           {write_string_param(s);}
00348     void    set_date(const ISODate& date)       {write_param("dateTime.iso8601", date.str());}
00349     void    set_binary(const Binary& bin)       {write_param("base64", bin.str());}
00350     void    set_array(const XMLRPCArray& arr)   {write_param(arr);}
00351     void    set_struct(const XMLRPCStruct& str) {write_param(str);}
00352 
00353     void    set_failure(int code, const string& message);
00354 
00355 private:
00356     void    init();
00357 };
00358 
00359 
00360 } // namespace XMLRPC
00361 
00362 
00363 #define __XMLRPC_H
00364 #endif