Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

xmlrpc.c

Go to the documentation of this file.
00001 /* ==================================================================== 
00002  * The Kannel Software License, Version 1.0 
00003  * 
00004  * Copyright (c) 2001-2008 Kannel Group  
00005  * Copyright (c) 1998-2001 WapIT Ltd.   
00006  * All rights reserved. 
00007  * 
00008  * Redistribution and use in source and binary forms, with or without 
00009  * modification, are permitted provided that the following conditions 
00010  * are met: 
00011  * 
00012  * 1. Redistributions of source code must retain the above copyright 
00013  *    notice, this list of conditions and the following disclaimer. 
00014  * 
00015  * 2. Redistributions in binary form must reproduce the above copyright 
00016  *    notice, this list of conditions and the following disclaimer in 
00017  *    the documentation and/or other materials provided with the 
00018  *    distribution. 
00019  * 
00020  * 3. The end-user documentation included with the redistribution, 
00021  *    if any, must include the following acknowledgment: 
00022  *       "This product includes software developed by the 
00023  *        Kannel Group (http://www.kannel.org/)." 
00024  *    Alternately, this acknowledgment may appear in the software itself, 
00025  *    if and wherever such third-party acknowledgments normally appear. 
00026  * 
00027  * 4. The names "Kannel" and "Kannel Group" must not be used to 
00028  *    endorse or promote products derived from this software without 
00029  *    prior written permission. For written permission, please  
00030  *    contact org@kannel.org. 
00031  * 
00032  * 5. Products derived from this software may not be called "Kannel", 
00033  *    nor may "Kannel" appear in their name, without prior written 
00034  *    permission of the Kannel Group. 
00035  * 
00036  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
00037  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
00038  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00039  * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS 
00040  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,  
00041  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
00042  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
00043  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
00044  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
00045  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  
00046  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00047  * ==================================================================== 
00048  * 
00049  * This software consists of voluntary contributions made by many 
00050  * individuals on behalf of the Kannel Group.  For more information on  
00051  * the Kannel Group, please see <http://www.kannel.org/>. 
00052  * 
00053  * Portions of this software are based upon software originally written at  
00054  * WapIT Ltd., Helsinki, Finland for the Kannel project.  
00055  */ 
00056 
00057 /*
00058  * gwlib/xmlrpc.c: functions to handle XML-RPC structure - building and parsing
00059  *
00060  * XML-RPC is HTTP-based XML defination to handle remote procedure calls,
00061  * and is defined at http://www.xml-rpc.org
00062  *
00063  * Kalle Marjola 2001 for project Kannel
00064  * Stipe Tolj <stolj@wapme.de>
00065  * Robert Gaach <robert.galach@my.tenbit.pl> 
00066  */
00067  
00068 #include <libxml/xmlmemory.h>
00069 #include <libxml/tree.h>
00070 #include <libxml/debugXML.h>
00071 #include <libxml/encoding.h>
00072 
00073 #include "gwlib/gwlib.h"
00074 #include "gwlib/xmlrpc.h"
00075 
00076 #define XR_ENABLE_EMPTY_STRING_VALUES
00077 
00078 #define OPTIMAL_STRUCT_SIZE 7
00079 
00080 typedef struct xmlrpc_methodresponse XMLRPCMethodResponse;
00081 typedef struct xmlrpc_member XMLRPCMember;
00082 typedef struct xmlrpc_methodcall XMLRPCMethodCall;
00083 typedef struct xmlrpc_fault XMLRPCFault;
00084 
00085 typedef struct xmlrpc_table_t xmlrpc_table_t;
00086 typedef struct xmlrpc_2table_t xmlrpc_2table_t;
00087 
00088 
00089 struct xmlrpc_methodcall {
00090     Octstr *method_name;
00091     List *params;         /* List of XMLRPCValues */
00092 };
00093 
00094 struct xmlrpc_methodresponse {
00095     XMLRPCValue *param;         /* Param value */
00096     XMLRPCFault *fault;         /* ..or this */
00097 };
00098 
00099 struct xmlrpc_fault {
00100     long f_code;                /* Fault code */
00101     Octstr *f_string;           /* and description */
00102 };
00103 
00104 struct xmlrpc_document {
00105     int d_type;           /* enum here */
00106     int parse_status;     /* enum here */
00107     Octstr *parse_error;  /* error string in case of parsing error */
00108     XMLRPCMethodCall *methodcall;
00109     XMLRPCMethodResponse *methodresponse;
00110 };
00111 
00112 struct xmlrpc_value {
00113     int v_type;         /* enum here */
00114     XMLRPCScalar *v_scalar;
00115     List *v_array;     /* List of XMLRPCValues */
00116     Dict *v_struct;    /* Dict of XMLRPCValues */
00117 };
00118 
00119 struct xmlrpc_member {  /* member of struct */
00120     Octstr *name;
00121     XMLRPCValue *value;
00122 };
00123 
00124 struct xmlrpc_scalar {
00125     int s_type;         /* enum here */
00126     Octstr *s_str;
00127     long s_int;
00128     int s_bool;
00129     double s_double;
00130     Octstr *s_date;
00131     Octstr *s_base64;
00132 };
00133 
00134 struct xmlrpc_table_t {
00135     char *name;
00136 };
00137 
00138 struct xmlrpc_2table_t {
00139     char *name;
00140     int s_type; /* enum here */
00141 };
00142 
00143 static xmlrpc_table_t methodcall_elements[] = {
00144     { "METHODNAME" },
00145     { "PARAMS" }
00146 };
00147 
00148 static xmlrpc_table_t methodresponse_elements[] = {
00149     { "FAULT" },
00150     { "PARAMS" }
00151 };
00152 
00153 static xmlrpc_table_t params_elements[] = {
00154     { "PARAM" }
00155 };
00156 
00157 static xmlrpc_table_t param_elements[] = {
00158     { "VALUE" }
00159 };
00160 
00161 static xmlrpc_2table_t value_elements[] = {
00162     { "I4", xr_int },
00163     { "INT", xr_int },
00164     { "BOOLEAN", xr_bool },
00165     { "STRING", xr_string },
00166     { "DOUBLE", xr_double },
00167     { "DATETIME.ISO8601", xr_date },
00168     { "BASE64", xr_base64 },
00169     { "STRUCT", xr_struct },
00170     { "ARRAY", xr_array }
00171 };
00172 
00173 static xmlrpc_table_t struct_elements[] = {
00174     { "MEMBER" }
00175 };
00176 
00177 static xmlrpc_table_t member_elements[] = {
00178     { "NAME" },
00179     { "VALUE" }
00180 };
00181 
00182 static xmlrpc_table_t array_elements[] = {
00183     { "DATA" }
00184 };
00185 
00186 static xmlrpc_table_t data_elements[] = {
00187     { "VALUE" }
00188 };
00189 
00190 static xmlrpc_table_t fault_elements[] = {
00191     { "VALUE" }
00192 };
00193 
00194 #define NUMBER_OF_METHODCALL_ELEMENTS \
00195     sizeof(methodcall_elements)/sizeof(methodcall_elements[0])
00196 #define NUMBER_OF_METHODRESPONSE_ELEMENTS \
00197     sizeof(methodresponse_elements)/sizeof(methodresponse_elements[0])
00198 #define NUMBER_OF_PARAMS_ELEMENTS \
00199     sizeof(params_elements)/sizeof(params_elements[0])
00200 #define NUMBER_OF_PARAM_ELEMENTS \
00201     sizeof(param_elements)/sizeof(param_elements[0])
00202 #define NUMBER_OF_VALUE_ELEMENTS \
00203     sizeof(value_elements)/sizeof(value_elements[0])
00204 #define NUMBER_OF_STRUCT_ELEMENTS \
00205     sizeof(struct_elements)/sizeof(struct_elements[0])
00206 #define NUMBER_OF_MEMBER_ELEMENTS \
00207     sizeof(member_elements)/sizeof(member_elements[0])
00208 #define NUMBER_OF_ARRAY_ELEMENTS \
00209     sizeof(array_elements)/sizeof(array_elements[0])
00210 #define NUMBER_OF_DATA_ELEMENTS \
00211     sizeof(data_elements)/sizeof(data_elements[0])
00212 #define NUMBER_OF_FAULT_ELEMENTS \
00213     sizeof(fault_elements)/sizeof(fault_elements[0])
00214 
00215 
00216 /* --------------------------------------
00217  * internal parser function declarations
00218  */
00219  
00220 static int parse_document(xmlDocPtr document, XMLRPCDocument *xrdoc);
00221 static int parse_methodcall(xmlDocPtr doc, xmlNodePtr node, 
00222                 XMLRPCDocument *xrdoc, XMLRPCMethodCall *methodcall);
00223 static int parse_methodcall_element(xmlDocPtr doc, xmlNodePtr node, 
00224                 XMLRPCDocument *xrdoc, XMLRPCMethodCall *methodcall);
00225 static int parse_methodresponse(xmlDocPtr doc, xmlNodePtr node, 
00226                 XMLRPCDocument *xrdoc, XMLRPCMethodResponse *methodresponse, 
00227                 int* n);
00228 static int parse_methodresponse_element(xmlDocPtr doc, xmlNodePtr node, 
00229                 XMLRPCDocument *xrdoc, XMLRPCMethodResponse *methodresponse);
00230 static int parse_params(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc, 
00231                 List *params);
00232 static int parse_params_element(xmlDocPtr doc, xmlNodePtr node, 
00233                 XMLRPCDocument *xrdoc, List *params);
00234 static int parse_param(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc, 
00235                 List *params, int *n);
00236 static int parse_param_element(xmlDocPtr doc, xmlNodePtr node, 
00237                 XMLRPCDocument *xrdoc, List *params);
00238 static int parse_value(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc, 
00239                 XMLRPCValue *value);
00240 static int parse_value_element(xmlDocPtr doc, xmlNodePtr node, 
00241                 XMLRPCDocument *xrdoc, XMLRPCValue *xrvalue);
00242 static int parse_struct(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc, 
00243                 Dict *members);
00244 static int parse_struct_element(xmlDocPtr doc, xmlNodePtr node, 
00245                 XMLRPCDocument *xrdoc, Dict *members);
00246 static int parse_member(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc, 
00247                 XMLRPCMember *member);
00248 static int parse_member_element(xmlDocPtr doc, xmlNodePtr node, 
00249                 XMLRPCDocument *xrdoc, XMLRPCMember *member);
00250 static int parse_array(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc, 
00251                 List *elements);
00252 static int parse_array_element(xmlDocPtr doc, xmlNodePtr node, 
00253                 XMLRPCDocument *xrdoc, List *elements);
00254 static int parse_data(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc, 
00255                 List *elements);
00256 static int parse_data_element(xmlDocPtr doc, xmlNodePtr node, 
00257                 XMLRPCDocument *xrdoc, List *elements);
00258 static int parse_fault(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc, 
00259                 XMLRPCFault *fault);
00260 static int parse_fault_element(xmlDocPtr doc, xmlNodePtr node, 
00261                 XMLRPCDocument *xrdoc, XMLRPCFault *fault);
00262 
00263 
00264 /*-------------------------------------
00265  * MethodCall
00266  */
00267 
00268 static XMLRPCMethodCall *xmlrpc_call_create(Octstr *name)
00269 {
00270     XMLRPCMethodCall *nmsg = gw_malloc(sizeof(XMLRPCMethodCall));
00271 
00272     nmsg->method_name = octstr_duplicate(name);
00273     nmsg->params = gwlist_create();
00274     
00275     return nmsg;
00276 }
00277 
00278 static void xmlrpc_call_destroy(XMLRPCMethodCall *call)
00279 {
00280     if (call == NULL)
00281         return;
00282 
00283     octstr_destroy(call->method_name);
00284     gwlist_destroy(call->params, xmlrpc_value_destroy_item);
00285 
00286     gw_free(call);
00287 }
00288 
00289 static Octstr *xmlrpc_call_get_name(XMLRPCMethodCall *call)
00290 {
00291     return call->method_name;
00292 }
00293 
00294 static int xmlrpc_call_add_param(XMLRPCMethodCall *method, XMLRPCValue *value)
00295 {
00296     if (method == NULL || value == NULL)
00297         return -1;
00298 
00299     gwlist_produce(method->params, value);
00300     return 0;
00301 }
00302 
00303 static Octstr *xmlrpc_call_print(XMLRPCMethodCall *call, int level)
00304 {
00305     Octstr *body, *os_value;
00306     XMLRPCValue *val;
00307     long i;
00308 
00309     if (call == NULL || call->method_name == NULL)
00310         return NULL;
00311 
00312     body = octstr_format("%*s<methodCall>\n"
00313                          "%*s<methodName>%S</methodName>\n",
00314                          level, "", level + 2, "", call->method_name);
00315 
00316     gwlist_lock(call->params);
00317     if (gwlist_len(call->params) > 0) {
00318         octstr_format_append(body, "%*s<params>\n", level + 2, "");
00319         for (i = 0; i < gwlist_len(call->params); i++) {
00320             val = gwlist_get(call->params, i);
00321             os_value = xmlrpc_value_print(val, level + 6);
00322 
00323             if (os_value == NULL) {
00324                 error(0, "XMLRPC: Could not print method call, param %ld malformed", i);
00325                 octstr_destroy(body);
00326                 return NULL;
00327             }
00328             octstr_format_append(body, "%*s<param>\n%S%*s</param>\n", 
00329                                  level + 4, "", os_value, level + 4, "");
00330             octstr_destroy(os_value);
00331         }
00332         octstr_format_append(body, "%*s</params>\n", level + 2, "");
00333     }
00334     gwlist_unlock(call->params);
00335     octstr_format_append(body, "%*s</methodCall>\n", level, "");
00336 
00337     return body;
00338 }
00339 
00340 
00341 /*-------------------------------------
00342  * XMLRPCFault
00343  */
00344 
00345 static XMLRPCFault *xmlrpc_fault_create(long fcode, Octstr *fstring)
00346 {
00347     XMLRPCFault *fault = gw_malloc(sizeof(XMLRPCFault));
00348     
00349     fault->f_code = fcode;
00350     fault->f_string = octstr_duplicate(fstring);
00351     
00352     return fault;
00353 }
00354 
00355 static void xmlrpc_fault_destroy(XMLRPCFault *fault)
00356 {
00357     if (fault == NULL) return;
00358     
00359     octstr_destroy(fault->f_string);
00360     gw_free(fault);
00361 }
00362 
00363 static long xmlrpc_fault_get_code(XMLRPCFault *fault)
00364 {
00365     if (fault == NULL) return -1;
00366     
00367     return fault->f_code;
00368 }
00369 
00370 static Octstr *xmlrpc_fault_get_string(XMLRPCFault *fault)
00371 {
00372     if (fault == NULL) return NULL;
00373     
00374     return fault->f_string;
00375 }
00376 
00377 static Octstr *xmlrpc_fault_print(XMLRPCFault *fault, int level)
00378 {
00379     Octstr *os;
00380     
00381     if (fault == NULL) return NULL;
00382     
00383     os = octstr_format("%*s<fault>\n%*s<value>\n"
00384                          "%*s<struct>\n"
00385                            "%*s<member>\n"
00386                              "%*s<name>faultCode</name>\n"
00387                              "%*s<value><int>%ld</int></value>\n"
00388                            "%*s</member>\n"
00389                            "%*s<member>\n"
00390                              "%*s<name>faultString</name>\n"
00391                              "%*s<value><string>%S</string></value>\n"
00392                            "%*s</member>\n"
00393                            "%*s</struct>\n"
00394                        "%*s</value>\n%*s</fault>\n",
00395                        level, "", level+2, "", level+4, "", level+6, "", 
00396                        level+8, "", level+8, "",
00397                        fault->f_code,
00398                        level+6, "", level+6, "", level+8, "", level+8, "",
00399                        (fault->f_string == NULL ? octstr_imm("/") : fault->f_string),
00400                        level+6, "", level+4, "", level+2, "", level, "");
00401 
00402     return os;
00403 }
00404 
00405 
00406 /*-------------------------------------
00407  * MethodResponse
00408  */
00409 
00410 
00411 static XMLRPCMethodResponse *xmlrpc_response_create(void)
00412 {
00413     XMLRPCMethodResponse *nmsg = gw_malloc(sizeof(XMLRPCMethodResponse));
00414 
00415     nmsg->param = NULL;
00416     nmsg->fault = NULL;
00417     
00418     return nmsg;
00419 }
00420 
00421 static void xmlrpc_response_destroy(XMLRPCMethodResponse *response)
00422 {
00423     if (response == NULL)
00424         return;
00425 
00426     xmlrpc_value_destroy(response->param);
00427     xmlrpc_fault_destroy(response->fault);
00428 
00429     gw_free(response);
00430 }
00431 
00432 static int xmlrpc_response_add_param(XMLRPCMethodResponse *response, XMLRPCValue *value)
00433 {
00434     if (response == NULL || value == NULL)
00435         return -1;
00436 
00437     if (response->param != NULL) {
00438         error(0, "XMLRPC: Method Response may contain only one param.");
00439         return -1;
00440     }
00441     if (response->fault != NULL) {
00442         error(0, "XMLRPC: Fault Response may not contain any param.");
00443         return -1;
00444     }
00445     
00446     response->param = value;
00447     return 0;
00448 }
00449 
00450 static int xmlrpc_response_is_fault(XMLRPCMethodResponse *response)
00451 {
00452     if (response == NULL || response->fault == NULL)
00453         return 0;
00454     
00455     return 1;
00456 }
00457 
00458 static long xmlrpc_response_get_faultcode(XMLRPCMethodResponse *faultresponse)
00459 {
00460     if (! xmlrpc_response_is_fault(faultresponse)) {
00461         error(0, "XMLRPC response is not fault response.");
00462         return -1;
00463     }
00464     
00465     return xmlrpc_fault_get_code(faultresponse->fault);
00466 }
00467 
00468 static Octstr *xmlrpc_response_get_faultstring(XMLRPCMethodResponse *faultresponse)
00469 {
00470     if (! xmlrpc_response_is_fault(faultresponse)) {
00471         error(0, "XMLRPC response is not fault response.");
00472         return NULL;
00473     }
00474     
00475     return xmlrpc_fault_get_string(faultresponse->fault);
00476 }
00477 
00478 
00479 static Octstr *xmlrpc_response_print(XMLRPCMethodResponse *response, int level)
00480 {
00481     Octstr *body = NULL, *os_value = NULL;
00482 
00483     if (response->fault == NULL && response->param != NULL) {
00484         os_value = xmlrpc_value_print(response->param, level + 6);
00485 
00486         body = octstr_format("%*s<methodResponse>\n"
00487                              "%*s<params>\n%*s<param>\n"
00488                              "%S"
00489                              "%*s</param>\n%*s</params>\n"
00490                              "%*s</methodResponse>\n",
00491                              level, "", level+2, "", level+4, "", os_value, 
00492                              level+4, "", level+2, "", level, "");
00493     } 
00494     else if (response->fault != NULL && response->param == NULL) {
00495         os_value = xmlrpc_fault_print(response->fault, level + 2);
00496 
00497         body = octstr_format("%*s<methodResponse>\n"
00498                              "%S"
00499                              "%*s</methodResponse>\n",
00500                              level, "", os_value, level, "");
00501     }
00502     
00503     octstr_destroy(os_value);
00504     return body;
00505 }
00506 
00507 
00508 /*-------------------------------------
00509  * Document
00510  */
00511 
00512 XMLRPCDocument *xmlrpc_doc_create(void)
00513 {
00514     XMLRPCDocument *xrdoc = gw_malloc(sizeof(XMLRPCDocument));
00515     
00516     xrdoc->d_type = xr_undefined;
00517     xrdoc->parse_status = XMLRPC_COMPILE_OK;
00518     xrdoc->parse_error = NULL;
00519     xrdoc->methodcall = NULL;
00520     xrdoc->methodresponse = NULL;
00521     
00522     return xrdoc;
00523 }
00524 
00525 XMLRPCDocument *xmlrpc_doc_create_call(Octstr *name)
00526 {
00527     XMLRPCDocument *xrdoc;
00528     
00529     xrdoc = xmlrpc_doc_create();
00530     xrdoc->d_type = xr_methodcall;
00531     xrdoc->methodcall = xmlrpc_call_create(name);
00532     
00533     return xrdoc;
00534 }
00535 
00536 XMLRPCDocument *xmlrpc_doc_create_response(void)
00537 {
00538     XMLRPCDocument *xrdoc;
00539     
00540     xrdoc = xmlrpc_doc_create();
00541     xrdoc->d_type = xr_methodresponse;
00542     xrdoc->methodresponse = xmlrpc_response_create();
00543     
00544     return xrdoc;
00545 }
00546 
00547 XMLRPCDocument *xmlrpc_doc_create_faultresponse(long faultcode, Octstr *faultstring)
00548 {
00549     XMLRPCDocument *xrdoc;
00550     XMLRPCMethodResponse *response;
00551     
00552     xrdoc = xmlrpc_doc_create_response();
00553 
00554     response = xrdoc->methodresponse;
00555     response->fault = xmlrpc_fault_create(faultcode, faultstring);
00556 
00557     return xrdoc;
00558 }
00559 
00560 XMLRPCDocument *xmlrpc_doc_parse(Octstr *post_body, int d_type)
00561 {
00562     XMLRPCDocument *xrdoc = xmlrpc_doc_create();
00563     xmlDocPtr pDoc;
00564     size_t size;
00565     char *body;
00566 
00567     if (post_body == NULL) {
00568         xrdoc->parse_status = XMLRPC_XMLPARSE_FAILED;
00569         xrdoc->parse_error = octstr_create("XMLRPC: (null) XML document given.");
00570         return xrdoc;
00571     }    
00572     xrdoc->d_type = d_type;
00573     
00574     octstr_strip_blanks(post_body);
00575     octstr_shrink_blanks(post_body);
00576     size = octstr_len(post_body);
00577     body = octstr_get_cstr(post_body);
00578 
00579     /* parse XML document to a XML tree */
00580     pDoc = xmlParseMemory(body, size);
00581     if (!pDoc) {
00582         xrdoc->parse_status = XMLRPC_XMLPARSE_FAILED;
00583         xrdoc->parse_error = octstr_create("XMLRPC: not valid XML document given.");
00584         return xrdoc;
00585     }
00586     parse_document(pDoc, xrdoc);
00587     xmlFreeDoc(pDoc);
00588     
00589     return xrdoc;
00590 }
00591 
00592 /* Destroy XMLRPCDocument object */
00593 void xmlrpc_doc_destroy(XMLRPCDocument *xrdoc, int d_type)
00594 {
00595     if (xrdoc == NULL) 
00596         return;
00597     
00598     if (xrdoc->d_type != d_type)
00599         warning(0, "Destroying document with different type then given.");
00600     
00601     xmlrpc_call_destroy(xrdoc->methodcall);
00602     xmlrpc_response_destroy(xrdoc->methodresponse);
00603     octstr_destroy(xrdoc->parse_error);
00604     
00605     gw_free(xrdoc);
00606 }
00607 
00608 /* Add given <value> param to XMLRPCDocument object. 
00609  * Return 0 if ok or -1 if something wrong (e.g. xrdoc is null or faultresponse)
00610  */
00611 int xmlrpc_doc_add_value(XMLRPCDocument *xrdoc, int d_type, XMLRPCValue *value)
00612 {
00613     if (xrdoc == NULL) 
00614         return -1;
00615 
00616     if (xrdoc->d_type != d_type && d_type != xr_undefined) {
00617         error(0, "Wrong xmlrpc document type. Param not added.");
00618         return -1;
00619     }
00620     if (xrdoc->d_type == xr_methodresponse) {
00621         if (xmlrpc_response_add_param(xrdoc->methodresponse, value) < 0) 
00622             return -1;
00623     } 
00624     else if (xrdoc->d_type == xr_methodcall) {
00625         if (xmlrpc_call_add_param(xrdoc->methodcall, value) < 0) 
00626             return -1;
00627     }
00628     else {
00629         error(0, "Unknown xmlrpc document type. Param not added.");
00630         return -1;
00631     }
00632     return 0;
00633 }
00634 
00635 /* Add a scalar param to MethodCall/MethodResponse. 
00636  * Return 0 if ok or -1 if something wrong (e.g. xrdoc is null or faultresponse)
00637  */
00638 int xmlrpc_doc_add_scalar(XMLRPCDocument *xrdoc, int d_type, int type, void *arg)
00639 {
00640     XMLRPCValue *param;
00641     
00642     param = xmlrpc_create_scalar_value(type, arg);
00643     if (xmlrpc_doc_add_value(xrdoc, d_type, param) < 0) {
00644         xmlrpc_value_destroy(param);
00645         return -1;
00646     }
00647     return 0;
00648 }
00649 
00650 
00651 /* Create Octstr (text/xml string) out of given XMLRPCDocument. Caller
00652  * must free returned Octstr */
00653 Octstr *xmlrpc_doc_print(XMLRPCDocument *xrdoc, int d_type, int level)
00654 {
00655     Octstr *body = NULL, *pref = NULL;
00656 
00657     if (xrdoc == NULL) 
00658         return NULL;
00659 
00660     if (xrdoc->d_type != d_type) {
00661         error(0, "Wrong xmlrpc document type.");
00662         return NULL;
00663     }
00664     if (xrdoc->d_type == xr_methodresponse) {
00665         body = xmlrpc_response_print(xrdoc->methodresponse, level);
00666     } 
00667     else if (xrdoc->d_type == xr_methodcall) {
00668         body = xmlrpc_call_print(xrdoc->methodcall, level);
00669     }
00670     else {
00671         error(0, "Unknown xmlrpc document type.");
00672     }
00673 
00674     if (body != NULL) {
00675         pref = octstr_format("%*s<?xml version=\"1.0\"?>\n", level, "");
00676         octstr_insert(body, pref, 0);
00677         octstr_destroy(pref);
00678     }
00679     return body;
00680 }
00681 
00682 /* Send XMLRPCDocument to given URL with given Headers. 
00683  * Return 0 if all went fine, -1 if failure. As user reference, uses *void
00684  */
00685 int xmlrpc_doc_send(XMLRPCDocument *xrdoc, int d_type, HTTPCaller *http_ref,
00686                     Octstr *url, List *headers, void *ref)
00687 {
00688     Octstr *body;
00689     if (http_ref == NULL || xrdoc == NULL)
00690         return -1;
00691     
00692     if (xrdoc->d_type != d_type) {
00693         error(0, "Wrong xmlrpc document type.");
00694         return -1;
00695     }
00696     
00697     if (headers == NULL)
00698         headers = gwlist_create();
00699     
00700     http_header_remove_all(headers, "Content-Type");
00701     http_header_add(headers, "Content-Type", "text/xml");
00702 
00703     /* 
00704      * XML-RPC specs say we at least need Host and User-Agent 
00705      * HTTP headers to be defined.
00706      * These are set anyway within gwlib/http.c:build_request()
00707      */
00708     body = xmlrpc_doc_print(xrdoc, d_type, 0);
00709 
00710     http_start_request(http_ref, HTTP_METHOD_POST, 
00711                        url, headers, body, 0, ref, NULL);
00712     
00713     octstr_destroy(body);
00714     /* XXX: should headers be destroyed here? */
00715     /*http_destroy_headers(headers); */
00716     return 0;
00717 }
00718 
00719 
00720 /*-------------------------------------
00721  * XMLRPCValue
00722  */
00723 
00724 
00725 /* Create new value. Set type of it to xr_undefined, so it must be
00726  * set laterwards to correct one
00727  */
00728 XMLRPCValue *xmlrpc_value_create(void)
00729 {
00730     XMLRPCValue *val = gw_malloc(sizeof(XMLRPCValue));
00731 
00732     val->v_type = xr_undefined;
00733     val->v_scalar = NULL;
00734     val->v_array = NULL;
00735     val->v_struct = NULL;
00736     return val;
00737 }
00738 
00739 /* Destroy value with its information, recursively if need to */
00740 void xmlrpc_value_destroy(XMLRPCValue *val)
00741 {
00742     if (val == NULL)
00743         return;
00744 
00745     switch(val->v_type) {
00746         case xr_scalar:
00747             xmlrpc_scalar_destroy(val->v_scalar);
00748             break;
00749         case xr_array:
00750             gwlist_destroy(val->v_array, xmlrpc_value_destroy_item);
00751             break;
00752         case xr_struct:
00753             dict_destroy(val->v_struct);
00754             break;
00755     }
00756     gw_free(val);
00757 }
00758 
00759 /* wrapper to destroy to be used with list */
00760 void xmlrpc_value_destroy_item(void *val)
00761 {
00762     xmlrpc_value_destroy(val);
00763 }
00764 
00765 int xmlrpc_value_set_type(XMLRPCValue *val, int v_type)
00766 {
00767     if (val == NULL)
00768         return -1;
00769 
00770     switch(v_type) {
00771         case xr_scalar:
00772         case xr_array:
00773         case xr_struct:
00774             val->v_type = v_type;
00775             break;
00776         default:
00777             error(0, "XMLRPC: value type not supported.");
00778             return -1;
00779     }
00780     
00781     return 0;
00782 }
00783 
00784 int xmlrpc_value_set_content(XMLRPCValue *val, void *content)
00785 {
00786     if (val == NULL)
00787         return -1;
00788 
00789     switch(val->v_type) {
00790         case xr_scalar:
00791             val->v_scalar = (XMLRPCScalar *)content;
00792             break;
00793         case xr_array:
00794             val->v_array  = (List *)content;
00795             break;
00796         case xr_struct:
00797             val->v_struct = (Dict *)content;
00798             break;
00799         default:
00800             error(0, "XMLRPC: value type not supported.");
00801             return -1;
00802     }
00803     
00804     return 0;
00805 }
00806 
00807 int xmlrpc_value_get_type(XMLRPCValue *val)
00808 {
00809     if (val == NULL)
00810         return -1;
00811         
00812     return val->v_type;
00813 }
00814 
00815 int xmlrpc_value_get_type_smart(XMLRPCValue *val)
00816 {
00817     int type = xmlrpc_value_get_type(val);
00818     if (type == xr_scalar) 
00819         return xmlrpc_get_scalar_value_type(val);
00820 
00821     return type;
00822 }
00823 
00824 void *xmlrpc_value_get_content(XMLRPCValue *val)
00825 {
00826     if (val == NULL)
00827         return NULL;
00828         
00829     switch(val->v_type) {
00830         case xr_scalar:
00831             return val->v_scalar;
00832         case xr_array:
00833             return val->v_array;
00834         case xr_struct:
00835             return val->v_struct;
00836         default:
00837             error(0, "XMLRPC: value type not supported.");
00838             return NULL;
00839     }
00840 }
00841 
00842 Octstr *xmlrpc_value_print(XMLRPCValue *val, int level)
00843 {
00844     Octstr *body = NULL, *os = NULL;
00845 
00846     if (val == NULL)
00847         return NULL;
00848     
00849     switch(val->v_type) {
00850         case xr_scalar:
00851             os = xmlrpc_scalar_print(val->v_scalar, level+2);
00852            break;
00853         case xr_struct:
00854             os = xmlrpc_print_struct(val->v_struct, level+2);
00855             break;
00856         case xr_array:
00857             os = xmlrpc_print_array(val->v_array, level+2);
00858             break;
00859         default:
00860             return NULL;
00861     }
00862 
00863     if (os != NULL) {
00864         body = octstr_format("%*s<value>\n%S%*s</value>\n",
00865                              level, "", os, level, "");
00866         octstr_destroy(os);
00867     }
00868     
00869     return body;
00870 }
00871 
00872 
00873 /*-------------------------------------
00874  * XMLRPCScalar
00875  */
00876 
00877 
00878 /* Create new scalar of given type with given argument */
00879 XMLRPCScalar *xmlrpc_scalar_create(int type, void *arg)
00880 {
00881     XMLRPCScalar *scalar = gw_malloc(sizeof(XMLRPCScalar));
00882 
00883     scalar->s_type = type;
00884     scalar->s_int = 0;
00885     scalar->s_bool = 0;
00886     scalar->s_double = 0.0;
00887     scalar->s_str = NULL;
00888     scalar->s_date = NULL;
00889     scalar->s_base64 = NULL;
00890     
00891     if (arg == NULL) {
00892 #ifdef XR_ENABLE_EMPTY_STRING_VALUES
00893         if (scalar->s_type != xr_string) {
00894 #endif
00895             error(0,"XML-RPC: scalar value may not be null!");
00896             xmlrpc_scalar_destroy(scalar);
00897             return NULL;
00898 #ifdef XR_ENABLE_EMPTY_STRING_VALUES
00899         }
00900 #endif
00901     }
00902     switch (type) {
00903         case xr_int:
00904             if (arg != NULL) 
00905                 scalar->s_int = *(long*)arg;
00906             break;
00907         case xr_bool:
00908             if (arg != NULL) 
00909                 scalar->s_bool = *(int*)arg;
00910             break;
00911         case xr_double:
00912             if (arg != NULL) 
00913                 scalar->s_double = *(double*)arg;
00914             break;
00915         case xr_string:
00916             scalar->s_str = octstr_duplicate((Octstr *)arg);
00917             break;
00918         case xr_date:
00919             scalar->s_date = octstr_duplicate((Octstr *)arg);
00920             break;
00921         case xr_base64:
00922             scalar->s_base64 = octstr_duplicate((Octstr *)arg);
00923             break;
00924         default:
00925             error(0,"XML-RPC: scalar type not supported!");
00926             xmlrpc_scalar_destroy(scalar);
00927             return NULL;
00928     }
00929     return scalar;
00930 }
00931 
00932 
00933 /* Destroy scalar */
00934 void xmlrpc_scalar_destroy(XMLRPCScalar *scalar)
00935 {
00936     if (scalar == NULL)
00937         return;
00938 
00939     octstr_destroy(scalar->s_str);
00940     octstr_destroy(scalar->s_date);
00941     octstr_destroy(scalar->s_base64);
00942     
00943     gw_free(scalar);
00944 }
00945 
00946 int xmlrpc_scalar_get_type(XMLRPCScalar *scalar)
00947 {
00948     if (scalar == NULL)
00949         return -1;
00950     return scalar->s_type;
00951 }
00952 
00953 void *xmlrpc_scalar_get_content(XMLRPCScalar *scalar, int s_type)
00954 {
00955     if (scalar == NULL)
00956         return NULL;
00957     if (scalar->s_type != s_type) {
00958         error(0, "XMLRPC: Scalar content request with bogus type");
00959         return NULL;
00960     }
00961     switch (scalar->s_type) {
00962         case xr_int:     return &(scalar->s_int);
00963         case xr_bool:    return &(scalar->s_bool);
00964         case xr_double:  return &(scalar->s_double);
00965         case xr_string:  return scalar->s_str;
00966         case xr_date:    return scalar->s_date;
00967         case xr_base64:  return scalar->s_base64;
00968         default:
00969             error(0,"XML-RPC: scalar type not supported!");
00970             return NULL;
00971     }
00972 }
00973 
00974 Octstr *xmlrpc_scalar_print(XMLRPCScalar *scalar, int level)
00975 {
00976     Octstr *os = NULL;
00977     
00978     if (scalar == NULL)
00979         return NULL;
00980 
00981     switch (scalar->s_type) {
00982         case xr_int:
00983             os = octstr_format("%*s<int>%ld</int>\n", 
00984                                level, "", scalar->s_int);
00985             break;
00986         case xr_bool:
00987             os = octstr_format("%*s<bool>%d</bool>\n", 
00988                                level, "", scalar->s_bool);
00989             break;
00990         case xr_double:
00991             os = octstr_format("%*s<double>%d</double>\n", 
00992                                  level, "", scalar->s_double);
00993             break;
00994         case xr_string:
00995             if (scalar->s_str == NULL) {
00996 #ifdef XR_ENABLE_EMPTY_STRING_VALUES
00997                 os = octstr_format("%*s<string></string>\n", 
00998                                    level, "");
00999 #endif
01000             } else {
01001                 Octstr *tmp = octstr_duplicate(scalar->s_str);
01002                 octstr_convert_to_html_entities(tmp);
01003                 os = octstr_format("%*s<string>%S</string>\n", 
01004                                    level, "", tmp);
01005                 octstr_destroy(tmp);
01006             }
01007             break;
01008         case xr_date:
01009             os = octstr_format("%*s<datetime.iso8601>%S</datetime.iso8601>\n", 
01010                                level, "", scalar->s_date);
01011             break;
01012         case xr_base64:
01013             os = octstr_format("%*s<base64>%S</base64>\n", 
01014                                level, "", scalar->s_base64);
01015             break;
01016     }
01017     return os;    
01018 }
01019 
01020 
01021 /*-------------------------------------
01022  * XMLRPCMember - internal functions
01023  */
01024 
01025 /* Create new member with undefined name and value */
01026 static XMLRPCMember *xmlrpc_member_create(void)
01027 {
01028     XMLRPCMember *member = gw_malloc(sizeof(XMLRPCMember));
01029 
01030     member->name = NULL;
01031     member->value = NULL;
01032 
01033     return member;
01034 }
01035 
01036 /* Destroy member and if destroy_value != 0 destroy its content */
01037 static void xmlrpc_member_destroy(XMLRPCMember *member, int destroy_value)
01038 {
01039     if (member == NULL)
01040         return;
01041 
01042     octstr_destroy(member->name);
01043     if (destroy_value == 1)
01044         xmlrpc_value_destroy(member->value);
01045 
01046     gw_free(member);
01047 }
01048 
01049 
01050 
01051 /*-------------------------------------------------
01052  * Utilities to make things easier
01053  */
01054 
01055 Octstr *xmlrpc_get_call_name(XMLRPCDocument *call)
01056 {
01057     if (call == NULL || call->methodcall == NULL)
01058         return NULL;
01059     return xmlrpc_call_get_name(call->methodcall);
01060 }
01061 
01062 /*** PARAMS HANDLING ***/
01063 int xmlrpc_count_params(XMLRPCDocument *xrdoc)
01064 {
01065     if (xrdoc == NULL)
01066         return -1;
01067     if (xrdoc->d_type == xr_methodcall && xrdoc->methodcall != NULL)
01068         return gwlist_len(xrdoc->methodcall->params);
01069     else if (xrdoc->d_type == xr_methodresponse && xrdoc->methodresponse != NULL)
01070         return (xrdoc->methodresponse->param != NULL ? 1 : 0);
01071     
01072     return -1;
01073 }
01074 
01075 XMLRPCValue *xmlrpc_get_param(XMLRPCDocument *xrdoc, int i)
01076 {
01077     if (xrdoc == NULL)
01078         return NULL;
01079     if (xrdoc->d_type == xr_methodcall && xrdoc->methodcall != NULL) 
01080         return gwlist_len(xrdoc->methodcall->params) > i ? gwlist_get(xrdoc->methodcall->params, i) : NULL;
01081     else if (xrdoc->d_type == xr_methodresponse && xrdoc->methodresponse != NULL
01082              && i == 0)
01083         return xrdoc->methodresponse->param;
01084     
01085     return NULL;
01086 }
01087 
01088 int xmlrpc_get_type_param(XMLRPCDocument *xrdoc, int i)
01089 {
01090     XMLRPCValue *param = xmlrpc_get_param(xrdoc, i);
01091     
01092     return xmlrpc_value_get_type(param);
01093 }
01094 
01095 void *xmlrpc_get_content_param(XMLRPCDocument *xrdoc, int i)
01096 {
01097     XMLRPCValue *param = xmlrpc_get_param(xrdoc, i);
01098     
01099     return xmlrpc_value_get_content(param);
01100 }
01101 
01102 /*** STRUCT VALUE HANDLING ***/
01103 XMLRPCValue *xmlrpc_create_struct_value(int count_members)
01104 {
01105     XMLRPCValue *value = xmlrpc_value_create();
01106     int len = (count_members > 0 ? count_members : OPTIMAL_STRUCT_SIZE);
01107     value->v_type = xr_struct;
01108     value->v_struct = dict_create(len, xmlrpc_value_destroy_item);
01109 
01110     return value;
01111 }
01112 
01113 long xmlrpc_count_members(XMLRPCValue *xrstruct)
01114 {
01115     if (xrstruct == NULL || xrstruct->v_type != xr_struct)
01116         return -1;
01117     return dict_key_count(xrstruct->v_struct);
01118 }
01119 
01120 int xmlrpc_add_member(XMLRPCValue *xrstruct, Octstr *name, XMLRPCValue *value)
01121 {
01122     if (xrstruct == NULL || xrstruct->v_type != xr_struct 
01123         || name == NULL || value == NULL)
01124         return -1;
01125     
01126     return dict_put_once(xrstruct->v_struct, name, value);
01127 }
01128 
01129 int xmlrpc_add_member_scalar(XMLRPCValue *xrstruct, Octstr *name, int type, void *arg)
01130 {
01131     XMLRPCValue *value = xmlrpc_create_scalar_value(type, arg);
01132     int status;
01133     
01134     status = xmlrpc_add_member(xrstruct, name, value);
01135     if (status < 0)
01136         xmlrpc_value_destroy(value);
01137         
01138     return status;
01139 }
01140 
01141 XMLRPCValue *xmlrpc_get_member(XMLRPCValue *xrstruct, Octstr *name)
01142 {
01143     if (xrstruct == NULL || xrstruct->v_type != xr_struct || name == NULL)
01144         return NULL;
01145     
01146     return dict_get(xrstruct->v_struct, name);
01147 }
01148 
01149 int xmlrpc_get_member_type(XMLRPCValue *xrstruct, Octstr *name)
01150 {
01151     XMLRPCValue *value = xmlrpc_get_member(xrstruct, name);
01152     
01153     return xmlrpc_value_get_type(value);
01154 }
01155 
01156 void *xmlrpc_get_member_content(XMLRPCValue *xrstruct, Octstr *name)
01157 {
01158     XMLRPCValue *value = xmlrpc_get_member(xrstruct, name);
01159     
01160     return xmlrpc_value_get_content(value);
01161 }
01162 
01163 Octstr *xmlrpc_print_struct(Dict *v_struct,  int level)
01164 {
01165     Octstr *body, *os_val, *key;
01166     List *keys;
01167     XMLRPCValue *member_val;
01168 
01169     if (v_struct == NULL || dict_key_count(v_struct) == 0)
01170         return NULL;
01171     
01172     keys = dict_keys(v_struct);
01173     body = octstr_format("%*s<struct>\n", level, "");
01174 
01175     while ((key = gwlist_consume(keys)) != NULL) {
01176         member_val = dict_get(v_struct, key);
01177         os_val = xmlrpc_value_print(member_val, level+4);
01178         if (os_val == NULL) {
01179             gwlist_destroy(keys, octstr_destroy_item);
01180             octstr_destroy(key);
01181             octstr_destroy(body);
01182             return NULL;
01183         }
01184         octstr_format_append(body, "%*s<member>\n"
01185                                      "%*s<name>%S</name>\n%S"
01186                                    "%*s</member>\n",
01187                                    level+2, "", level+4, "",
01188                                    key, os_val,
01189                                    level+2, "");
01190         octstr_destroy(key);
01191         octstr_destroy(os_val);
01192     }
01193     gwlist_destroy(keys, octstr_destroy_item);
01194     octstr_format_append(body, "%*s</struct>\n", level, "");
01195     
01196     return body;
01197 }
01198 
01199 /*** ARRAY VALUE HANDLING ***/
01200 XMLRPCValue *xmlrpc_create_array_value(void)
01201 {
01202     XMLRPCValue *value = xmlrpc_value_create();
01203     value->v_type = xr_array;
01204     value->v_array = gwlist_create();
01205 
01206     return value;
01207 }
01208 
01209 int xmlrpc_count_elements(XMLRPCValue *xrarray)
01210 {
01211     if (xrarray == NULL || xrarray->v_type != xr_array)
01212         return -1;
01213     
01214     return  gwlist_len(xrarray->v_array);
01215 }
01216 
01217 int xmlrpc_add_element(XMLRPCValue *xrarray, XMLRPCValue *value)
01218 {
01219     if (xrarray == NULL || xrarray->v_type != xr_array || value == NULL)
01220         return -1;
01221     
01222     gwlist_produce(xrarray->v_array, value);
01223     return 1;
01224 }
01225 
01226 int xmlrpc_add_element_scalar(XMLRPCValue *xrarray, int type, void *arg)
01227 {
01228     XMLRPCValue *value = xmlrpc_create_scalar_value(type, arg);
01229     int status;
01230     
01231     status = xmlrpc_add_element(xrarray, value);
01232     if (status < 0)
01233         xmlrpc_value_destroy(value);
01234         
01235     return status;
01236 }
01237 
01238 XMLRPCValue *xmlrpc_get_element(XMLRPCValue *xrarray, int i)
01239 {
01240     if (xrarray == NULL || xrarray->v_type != xr_array || i < 0)
01241         return NULL;
01242     
01243     return gwlist_get(xrarray->v_array, i);
01244 }
01245 
01246 int xmlrpc_get_element_type(XMLRPCValue *xrarray, int i)
01247 {
01248     XMLRPCValue *value = xmlrpc_get_element(xrarray, i);
01249     
01250     return xmlrpc_value_get_type(value);
01251 }
01252 
01253 void *xmlrpc_get_element_content(XMLRPCValue *xrarray, int i)
01254 {
01255     XMLRPCValue *value = xmlrpc_get_element(xrarray, i);
01256     
01257     return xmlrpc_value_get_content(value);
01258 }
01259 
01260 Octstr *xmlrpc_print_array(List *v_array,  int level)
01261 {
01262     Octstr *body, *os_element;
01263     XMLRPCValue *element = NULL;
01264     int i;
01265     
01266     if (v_array == NULL)
01267         return NULL;
01268     
01269     body = octstr_format("%*s<array>\n%*s<data>\n", level, "", level+2, "");
01270 
01271     for(i = 0; i < gwlist_len(v_array); i++) {
01272         element = gwlist_get(v_array, i);
01273         os_element = xmlrpc_value_print(element, level+4);
01274         if (os_element == NULL) {
01275             octstr_destroy(body);
01276             return NULL;
01277         }
01278         
01279         octstr_append(body, os_element);
01280         octstr_destroy(os_element);
01281     }
01282     octstr_format_append(body, "%*s</data>\n%*s</array>\n", 
01283                          level+2, "", level, "");
01284     
01285     return body;
01286 }
01287 
01288 
01289 /*** SCALAR VALUE HANDLING ***/
01290 XMLRPCValue *xmlrpc_create_scalar_value(int type, void *arg)
01291 {
01292     XMLRPCValue *value = xmlrpc_value_create();
01293     value->v_type = xr_scalar;
01294     value->v_scalar = xmlrpc_scalar_create(type, arg);
01295 
01296     return value;
01297 }
01298 
01299 XMLRPCValue *xmlrpc_create_double_value(double val)
01300 {
01301     return xmlrpc_create_scalar_value(xr_double, &val);
01302 }
01303 
01304 XMLRPCValue *xmlrpc_create_int_value(long val)
01305 {
01306     return xmlrpc_create_scalar_value(xr_int, &val);
01307 }
01308 
01309 XMLRPCValue *xmlrpc_create_string_value(Octstr *val)
01310 {
01311     return xmlrpc_create_scalar_value(xr_string, val);
01312 }
01313 
01314 
01315 /*** FAULT HANDLING ***/
01316 int xmlrpc_is_fault(XMLRPCDocument *response)
01317 {
01318     if (response == NULL || response->d_type != xr_methodresponse)
01319         return 0;
01320     
01321     return xmlrpc_response_is_fault(response->methodresponse);
01322 }
01323 
01324 long xmlrpc_get_faultcode(XMLRPCDocument *faultresponse)
01325 {
01326     if (! xmlrpc_is_fault(faultresponse)) {
01327         error(0, "XMLRPC object is not fault response.");
01328         return -1;
01329     }
01330     
01331     return xmlrpc_response_get_faultcode(faultresponse->methodresponse);
01332 }
01333 
01334 Octstr *xmlrpc_get_faultstring(XMLRPCDocument *faultresponse)
01335 {
01336     if (! xmlrpc_is_fault(faultresponse)) {
01337         error(0, "XMLRPC object is not fault response.");
01338         return NULL;
01339     }
01340     
01341     return xmlrpc_response_get_faultstring(faultresponse->methodresponse);
01342 }
01343 
01344 
01345 /*** PARSE STATUS HANDLING***/
01346 
01347 int xmlrpc_parse_status(XMLRPCDocument *xrdoc)
01348 {
01349     if (xrdoc == NULL)
01350         return -1;
01351 
01352     return xrdoc->parse_status;
01353 }
01354 
01355 Octstr *xmlrpc_parse_error(XMLRPCDocument *xrdoc) 
01356 {
01357     if (xrdoc == NULL)
01358         return NULL;
01359     
01360     return octstr_duplicate(xrdoc->parse_error);
01361 }
01362 
01363 
01364 /*-------------------------------------------------
01365  * Internal parser functions
01366  */
01367 
01368 static int parse_document(xmlDocPtr document, XMLRPCDocument *xrdoc)
01369 {
01370     xmlNodePtr node;
01371     Octstr *name;
01372     int n = 0, status = 0;
01373     
01374     node = xmlDocGetRootElement(document);
01375 
01376     /*
01377      * check if this is at least a valid root element
01378      */
01379     if (node == NULL || node->name == NULL) {
01380         error(0, "XMLRPC: XML document - not valid root node!");
01381         xrdoc->parse_status = XMLRPC_XMLPARSE_FAILED;
01382         xrdoc->parse_error = octstr_format("XML-RPC compiler: bad XML");
01383         return -1;
01384     }
01385     
01386     name = octstr_create(node->name);
01387     if (octstr_len(name) == 0) {
01388         octstr_destroy(name);
01389         return -1;
01390     }
01391     if ((xrdoc->d_type == xr_methodcall || xrdoc->d_type == xr_undefined)
01392         && octstr_case_compare(name, octstr_imm("METHODCALL")) == 0) {
01393         
01394         xrdoc->d_type = xr_methodcall;
01395         xrdoc->methodcall = xmlrpc_call_create(NULL);
01396         octstr_destroy(name);
01397         
01398         status = parse_methodcall(document, node->xmlChildrenNode, xrdoc, xrdoc->methodcall);
01399         if (status < 0) {
01400             xmlrpc_call_destroy(xrdoc->methodcall);
01401             xrdoc->methodcall = NULL;
01402             if (xrdoc->parse_status == XMLRPC_COMPILE_OK) {
01403                 xrdoc->parse_status = XMLRPC_XMLPARSE_FAILED;
01404                 xrdoc->parse_error = octstr_format("XML-RPC compiler: bad XML");
01405             }
01406         } 
01407         else if ((xrdoc->methodcall->method_name) == NULL) {
01408             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
01409             xrdoc->parse_error = octstr_format("XML-RPC compiler: <methodName> tag expected!");
01410             status = -1;
01411         }
01412         return status;
01413     } else if ((xrdoc->d_type == xr_methodresponse || xrdoc->d_type == xr_undefined)
01414                && octstr_case_compare(name, octstr_imm("METHODRESPONSE")) == 0) {
01415         
01416         xrdoc->d_type = xr_methodresponse;
01417         xrdoc->methodresponse = xmlrpc_response_create();
01418         octstr_destroy(name);
01419         
01420         status = parse_methodresponse(document, node->xmlChildrenNode, 
01421                                       xrdoc, xrdoc->methodresponse, &n);
01422         if (status < 0) {
01423             xmlrpc_response_destroy(xrdoc->methodresponse);
01424             xrdoc->methodresponse = NULL;
01425         }
01426         return status;
01427     } else {
01428         xrdoc->parse_status = XMLRPC_PARSING_FAILED;
01429         xrdoc->parse_error = octstr_format("XML-RPC compiler: wrong root element <%s>, "
01430                                            "<%s> expected!", 
01431                                            octstr_get_cstr(name), 
01432                                            (xrdoc->d_type == xr_methodcall ? 
01433                                                "methodCall" : "methodResponse"));
01434         octstr_destroy(name);
01435         return -1;
01436     }
01437 }
01438 
01439 static int parse_methodcall(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc,
01440                             XMLRPCMethodCall *methodcall)
01441 {
01442     int status = 0;
01443   
01444     /* call for the parser function of the node type. */
01445     switch (node->type) {
01446 
01447         case XML_ELEMENT_NODE:
01448             
01449             status = parse_methodcall_element(doc, node, xrdoc, methodcall);
01450             break;
01451 
01452         case XML_TEXT_NODE:
01453         case XML_COMMENT_NODE:
01454         case XML_PI_NODE:
01455             /* Text nodes, comments and PIs are ignored. */
01456             break;
01457            /*
01458             * XML has also many other node types, these are not needed with 
01459             * XML-RPC. Therefore they are assumed to be an error.
01460             */
01461         default:
01462             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
01463             xrdoc->parse_error = octstr_format("XML-RPC compiler: unknown XML node "
01464                                                "in the XML-RPC source.");
01465             return -1;
01466             break;
01467     }
01468 
01469     if (node->next != NULL)
01470         return parse_methodcall(doc, node->next, xrdoc, methodcall);
01471         
01472     return status;
01473 }
01474 
01475 static int parse_methodcall_element(xmlDocPtr doc, xmlNodePtr node, 
01476                                     XMLRPCDocument *xrdoc, XMLRPCMethodCall *methodcall)
01477 {
01478     Octstr *name;
01479     xmlChar *content_buff;
01480     size_t i;
01481 
01482     /*
01483      * check if the element is allowed at this level 
01484      */
01485     if (node->name == NULL) {
01486         error(0, "XMLRPC: XML methodcall element nodes without name!");
01487         xrdoc->parse_status = XMLRPC_XMLPARSE_FAILED;
01488         xrdoc->parse_error = octstr_format("XML-RPC compiler: bad XML");
01489         return -1;
01490     }
01491 
01492     name = octstr_create(node->name);
01493     if (octstr_len(name) == 0) {
01494         octstr_destroy(name);
01495         return -1;
01496     }
01497 
01498     i = 0;
01499     while (i < NUMBER_OF_METHODCALL_ELEMENTS) {
01500         if (octstr_case_compare(name, octstr_imm(methodcall_elements[i].name)) == 0)
01501             break;
01502         ++i;
01503     }
01504     if (i == NUMBER_OF_METHODCALL_ELEMENTS) {
01505         xrdoc->parse_status = XMLRPC_PARSING_FAILED;
01506         xrdoc->parse_error = octstr_format("XML-RPC compiler: unknown tag '%s' in XML source "
01507                                            "at level <methodCall>", octstr_get_cstr(name));
01508         octstr_destroy(name);
01509         return -1;
01510     } 
01511     octstr_destroy(name);
01512 
01513     /* 
01514      * now check which type it is and process 
01515      *
01516      * valid tags at this level are:
01517      *   methodName [0]
01518      *   params     [1]
01519      */
01520     if (i == 0) {
01521         /* this has been the <methodName> tag */
01522         if (methodcall->method_name == NULL) {
01523             /*only one <methodName> tag allowed*/
01524             content_buff = xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
01525             if (content_buff != NULL) {
01526                 methodcall->method_name = octstr_create(content_buff);
01527                 xmlFree(content_buff);
01528             } else {
01529                 xrdoc->parse_status = XMLRPC_PARSING_FAILED;
01530                 xrdoc->parse_error = octstr_format("XML-RPC compiler: empty tag <methodName> in XML source "
01531                                            "at level <methodCall>");
01532                 return -1;
01533             }
01534         } else {
01535             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
01536             xrdoc->parse_error = octstr_format("XML-RPC compiler: duplicated tag <methodName> in XML source "
01537                                                "at level <methodCall>");
01538             octstr_destroy(name);
01539             return -1;
01540         }
01541     } else {
01542         /* 
01543          * ok, this has to be an <params> tag, otherwise we would 
01544          * have returned previosly
01545          */
01546         return parse_params(doc, node->xmlChildrenNode, xrdoc, methodcall->params);
01547     }
01548     return 0;
01549 } 
01550 
01551 static int parse_methodresponse(xmlDocPtr doc, xmlNodePtr node, 
01552                             XMLRPCDocument *xrdoc, XMLRPCMethodResponse *methodresponse, int* n)
01553 {
01554     int status = 0;
01555   
01556     /* call for the parser function of the node type. */
01557     switch (node->type) {
01558 
01559         case XML_ELEMENT_NODE:
01560             if (*n > 0) {
01561                 xrdoc->parse_status = XMLRPC_PARSING_FAILED;
01562                 xrdoc->parse_error = octstr_format("XML-RPC compiler: unexpected XML node <%s> "
01563                                                    "in the XML-RPC source.", node->name);
01564                 return -1;
01565             }
01566             status = parse_methodresponse_element(doc, node, xrdoc, methodresponse);
01567             (*n)++;
01568             break;
01569 
01570         case XML_TEXT_NODE:
01571         case XML_COMMENT_NODE:
01572         case XML_PI_NODE:
01573             /* Text nodes, comments and PIs are ignored. */
01574             break;
01575            /*
01576             * XML has also many other node types, these are not needed with 
01577             * XML-RPC. Therefore they are assumed to be an error.
01578             */
01579         default:
01580             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
01581             xrdoc->parse_error = octstr_format("XML-RPC compiler: unknown XML node "
01582                                                "in the XML-RPC source.");
01583             return -1;
01584             break;
01585     }
01586 
01587     if (node->next != NULL) {
01588         if (parse_methodresponse(doc, node->next, xrdoc, methodresponse, n) == -1) {
01589             return -1;
01590         }
01591     }
01592 
01593     return status;
01594 }
01595 
01596 static int parse_methodresponse_element(xmlDocPtr doc, xmlNodePtr node, 
01597                                     XMLRPCDocument *xrdoc, XMLRPCMethodResponse *methodresponse)
01598 {
01599     Octstr *name;
01600     size_t i;
01601     int status;
01602 
01603     /*
01604      * check if the element is allowed at this level 
01605      */
01606     if (node->name == NULL) {
01607         error(0, "XMLRPC: XML methodResponse element nodes without name!");
01608         xrdoc->parse_status = XMLRPC_XMLPARSE_FAILED;
01609         xrdoc->parse_error = octstr_format("XML-RPC compiler: bad XML");
01610         return -1;
01611     }
01612 
01613     name = octstr_create(node->name);
01614     if (octstr_len(name) == 0) {
01615         octstr_destroy(name);
01616         return -1;
01617     }
01618 
01619     i = 0;
01620     while (i < NUMBER_OF_METHODRESPONSE_ELEMENTS) {
01621         if (octstr_case_compare(name, octstr_imm(methodresponse_elements[i].name)) == 0)
01622             break;
01623         ++i;
01624     }
01625     if (i == NUMBER_OF_METHODRESPONSE_ELEMENTS) {
01626         xrdoc->parse_status = XMLRPC_PARSING_FAILED;
01627         xrdoc->parse_error = octstr_format("XML-RPC compiler: unknown tag '%s' in XML source "
01628                                            "at level <methodResponse>", octstr_get_cstr(name));
01629         octstr_destroy(name);
01630         return -1;
01631     } 
01632     octstr_destroy(name);
01633 
01634     /* 
01635      * now check which type it is and process 
01636      *
01637      * valid tags at this level are:
01638      *   fault  [0]
01639      *   params [1]
01640      */
01641     if (i == 0) {
01642         /* this has been the <fault> tag */
01643         methodresponse->fault = xmlrpc_fault_create(0, NULL);
01644         return parse_fault(doc, node->xmlChildrenNode, xrdoc, methodresponse->fault);
01645     } else {
01646         /* 
01647          * ok, this has to be an <params> tag, otherwise we would 
01648          * have returned previosly
01649          */
01650         List *params = gwlist_create();;
01651         status = parse_params(doc, node->xmlChildrenNode, xrdoc, params);
01652         if (status < 0) return -1;
01653         if (gwlist_len(params) != 1) {
01654             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
01655             xrdoc->parse_error = octstr_format("XML-RPC compiler:wrong number of params "
01656                                                "at level <methodResponse>");
01657             gwlist_destroy(params, xmlrpc_value_destroy_item);
01658             return -1;
01659         }
01660         methodresponse->param = gwlist_consume(params);
01661         gwlist_destroy(params, xmlrpc_value_destroy_item);
01662         return status;
01663     }
01664 
01665 }
01666 
01667 static int parse_params(xmlDocPtr doc, xmlNodePtr node, 
01668                         XMLRPCDocument *xrdoc, List *params)
01669 {
01670     int status = 0;
01671   
01672     /* call for the parser function of the node type. */
01673     switch (node->type) {
01674 
01675         case XML_ELEMENT_NODE:
01676             status = parse_params_element(doc, node, xrdoc, params);
01677             break;
01678 
01679         case XML_TEXT_NODE:
01680         case XML_COMMENT_NODE:
01681         case XML_PI_NODE:
01682             /* Text nodes, comments and PIs are ignored. */
01683             break;
01684            /*
01685             * XML has also many other node types, these are not needed with 
01686             * XML-RPC. Therefore they are assumed to be an error.
01687             */
01688         default:
01689             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
01690             xrdoc->parse_error = octstr_format("XML-RPC compiler: unknown XML node in XML-RPC source.");
01691             return -1;
01692             break;
01693     }
01694 
01695     if (node->next != NULL)
01696            if (parse_params(doc, node->next, xrdoc, params) == -1)
01697             return -1;
01698 
01699     return status;
01700 }
01701 
01702 static int parse_params_element(xmlDocPtr doc, xmlNodePtr node, 
01703                                 XMLRPCDocument *xrdoc, List *params)
01704 {
01705     Octstr *name;
01706     size_t i;
01707     int n = 0;
01708 
01709     /*
01710      * check if the element is allowed at this level
01711      * within <params> we only have one or more <param>
01712      */
01713     if (node->name == NULL) {
01714         error(0, "XMLRPC: XML params element nodes without name!");
01715         xrdoc->parse_status = XMLRPC_XMLPARSE_FAILED;
01716         xrdoc->parse_error = octstr_format("XML-RPC compiler: bad XML");
01717         return -1;
01718     }
01719     
01720     name = octstr_create(node->name);
01721     if (octstr_len(name) == 0) {
01722         octstr_destroy(name);
01723         return -1;
01724     }
01725 
01726     i = 0;
01727     while (i < NUMBER_OF_PARAMS_ELEMENTS) {
01728         if (octstr_case_compare(name, octstr_imm(params_elements[i].name)) == 0)
01729             break;
01730         ++i;
01731     }
01732     if (i == NUMBER_OF_PARAMS_ELEMENTS) {
01733         xrdoc->parse_status = XMLRPC_PARSING_FAILED;
01734         xrdoc->parse_error = octstr_format("XML-RPC compiler: unknown tag '%s' "
01735                                            "in XML source at level <params>", 
01736                                            octstr_get_cstr(name));
01737         octstr_destroy(name);
01738         return -1;
01739     } 
01740     octstr_destroy(name);
01741 
01742     /* 
01743      * now check which type it is and process 
01744      *
01745      * valid tags at this level are:
01746      *   param [0]
01747      */
01748     if (i == 0) {
01749         /* this has been a <param> tag */
01750         if (parse_param(doc, node->xmlChildrenNode, xrdoc, params, &n) == -1)
01751             return -1;
01752     } else {
01753         /* we should never be here */
01754         xrdoc->parse_status = XMLRPC_PARSING_FAILED;
01755         xrdoc->parse_error = octstr_format("XML-RPC compiler: bogus parsing exception in parse_params!");
01756         return -1;
01757     }
01758     return 0;
01759 }
01760 
01761 static int parse_param(xmlDocPtr doc, xmlNodePtr node, 
01762                        XMLRPCDocument *xrdoc, List *params, int *n)
01763 {
01764     int status = 0;
01765   
01766     /* call for the parser function of the node type. */
01767     switch (node->type) {
01768 
01769         case XML_ELEMENT_NODE:
01770 
01771             /* a <param> can only have one value element type */
01772             if ((*n) > 0) {
01773                 xrdoc->parse_status = XMLRPC_PARSING_FAILED;
01774                 xrdoc->parse_error = octstr_format("XML-RPC compiler: param may only have one value!");
01775                 return -1;
01776             }
01777 
01778             status = parse_param_element(doc, node, xrdoc, params);
01779             (*n)++;
01780             break;
01781 
01782         case XML_TEXT_NODE:
01783         case XML_COMMENT_NODE:
01784         case XML_PI_NODE:
01785             /* Text nodes, comments and PIs are ignored. */
01786             break;
01787            /*
01788             * XML has also many other node types, these are not needed with 
01789             * XML-RPC. Therefore they are assumed to be an error.
01790             */
01791         default:
01792             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
01793             xrdoc->parse_error = octstr_format("XML-RPC compiler: Unknown XML node in the XML-RPC source.");
01794             return -1;
01795             break;
01796     }
01797    
01798     if (node->next != NULL)
01799         if (parse_param(doc, node->next, xrdoc, params, n) == -1)
01800             return -1;
01801 
01802     return status;
01803 }
01804 
01805 static int parse_param_element(xmlDocPtr doc, xmlNodePtr node, 
01806                                XMLRPCDocument *xrdoc, List *params)
01807 {
01808     Octstr *name;
01809     size_t i;
01810     XMLRPCValue *value;
01811 
01812     /*
01813      * check if the element is allowed at this level 
01814      */
01815     if (node->name == NULL) {
01816         error(0, "XMLRPC: XML param element nodes without name!");
01817         xrdoc->parse_status = XMLRPC_XMLPARSE_FAILED;
01818         xrdoc->parse_error = octstr_format("XML-RPC compiler: bad XML");
01819         return -1;
01820     }
01821 
01822     name = octstr_create(node->name);
01823     if (octstr_len(name) == 0) {
01824         octstr_destroy(name);
01825         return -1;
01826     }
01827 
01828     i = 0;
01829     while (i < NUMBER_OF_PARAM_ELEMENTS) {
01830         if (octstr_case_compare(name, octstr_imm(param_elements[i].name)) == 0)
01831             break;
01832         ++i;
01833     }
01834     if (i == NUMBER_OF_PARAM_ELEMENTS) {
01835         xrdoc->parse_status = XMLRPC_PARSING_FAILED;
01836         xrdoc->parse_error = octstr_format("XML-RPC compiler: unknown tag '%s' "
01837                                            "in XML source at level <param>", 
01838                                            octstr_get_cstr(name));
01839         octstr_destroy(name);
01840         return -1;
01841     } 
01842     octstr_destroy(name);
01843 
01844     /* 
01845      * now check which type it is and process 
01846      *
01847      * valid tags at this level are:
01848      *   value [0]
01849      */
01850     if (i == 0) {
01851         /* this has been a <param> tag */
01852         value = xmlrpc_value_create();
01853         if (parse_value(doc, node->xmlChildrenNode, xrdoc, value) == -1) {
01854             xmlrpc_value_destroy(value);
01855             return -1;
01856         }
01857         gwlist_append(params, value);
01858     } else {
01859         /* we should never be here */
01860         xrdoc->parse_status = XMLRPC_PARSING_FAILED;
01861         xrdoc->parse_error = octstr_format("XML-RPC compiler: bogus parsing exception in parse_param!");
01862         return -1;
01863     }
01864     return 0;
01865 }
01866 
01867 static int parse_value(xmlDocPtr doc, xmlNodePtr node, 
01868                        XMLRPCDocument *xrdoc, XMLRPCValue *value)
01869 {
01870     int status = 0;
01871   
01872     /* call for the parser function of the node type. */
01873     switch (node->type) {
01874 
01875         case XML_ELEMENT_NODE:
01876             status = parse_value_element(doc, node, xrdoc, value);
01877             break;
01878 
01879         case XML_TEXT_NODE:
01880         case XML_COMMENT_NODE:
01881         case XML_PI_NODE:
01882             /* Text nodes, comments and PIs are ignored. */
01883             break;
01884            /*
01885             * XML has also many other node types, these are not needed with 
01886             * XML-RPC. Therefore they are assumed to be an error.
01887             */
01888         default:
01889             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
01890             xrdoc->parse_error = octstr_format("XML-RPC compiler: Unknown XML node in the XML-RPC source.");
01891             return -1;
01892             break;
01893     }
01894 
01895     if (node->next != NULL)
01896         if (parse_value(doc, node->next, xrdoc, value) == -1)
01897             return -1;
01898 
01899     return status;
01900 }
01901 
01902 static int parse_value_element(xmlDocPtr doc, xmlNodePtr node, 
01903                                XMLRPCDocument *xrdoc, XMLRPCValue *xrvalue)
01904 {
01905     Octstr *name;
01906     Octstr *value = NULL;
01907     xmlChar *content_buff;
01908     long lval = 0;
01909     double dval = 0.0;
01910     size_t i;
01911 
01912     /*
01913      * check if the element is allowed at this level 
01914      */
01915     if (node->name == NULL) {
01916         error(0, "XMLRPC: XML value element nodes without name!");
01917         xrdoc->parse_status = XMLRPC_XMLPARSE_FAILED;
01918         xrdoc->parse_error = octstr_format("XML-RPC compiler: bad XML");
01919         return -1;
01920     }
01921 
01922     name = octstr_create(node->name);
01923     if (octstr_len(name) == 0) {
01924         octstr_destroy(name);
01925         return -1;
01926     }
01927 
01928     i = 0;
01929     while (i < NUMBER_OF_VALUE_ELEMENTS) {
01930         if (octstr_case_compare(name, octstr_imm(value_elements[i].name)) == 0)
01931             break;
01932         ++i;
01933     }
01934     if (i == NUMBER_OF_VALUE_ELEMENTS) {
01935         xrdoc->parse_status = XMLRPC_PARSING_FAILED;
01936         xrdoc->parse_error = octstr_format("XML-RPC compiler: unknown tag '%s' "
01937                                            "in XML source at level <value>", 
01938                                            octstr_get_cstr(name));
01939         octstr_destroy(name);
01940         return -1;
01941     } 
01942     octstr_destroy(name);
01943 
01944 
01945     content_buff = xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
01946     if (content_buff != NULL) {
01947         value = octstr_create(content_buff);
01948         xmlFree(content_buff);
01949     }
01950 
01951     /* 
01952      * now check which type it is and process 
01953      *
01954      * valid tags at this level are:
01955      *   i4, int
01956      *   boolean
01957      *   string
01958      *   double
01959      *   dateTime.iso8601
01960      *   base64
01961      *   struct
01962      *   array
01963      */
01964     switch (value_elements[i].s_type) {
01965         /*
01966          * scalar types
01967          */
01968         case xr_int:   case xr_bool:
01969         case xr_double:
01970         case xr_date:  case xr_base64:
01971 #ifndef XR_ENABLE_EMPTY_STRING_VALUES
01972         case xr_string:
01973 #endif
01974             if (value == NULL) {
01975                 xrdoc->parse_status = XMLRPC_PARSING_FAILED;
01976                 xrdoc->parse_error = octstr_format("XML-RPC compiler: no value for '%s'", 
01977                                            node->name);
01978                 return -1;
01979             }
01980             break;
01981     }
01982 
01983     switch (value_elements[i].s_type) {
01984         
01985         /*
01986          * scalar types
01987          */
01988         case xr_int:
01989             if (value != NULL && octstr_parse_long(&lval, value, 0, 10) < 0) {
01990                 xrdoc->parse_status = XMLRPC_PARSING_FAILED;
01991                 xrdoc->parse_error = octstr_format("XML-RPC compiler: could not parse int value '%s'", 
01992                                                    octstr_get_cstr(value));
01993                 octstr_destroy(value);
01994                 return -1;
01995             }
01996             xrvalue->v_type = xr_scalar;
01997             xrvalue->v_scalar = xmlrpc_scalar_create(xr_int, (void *) &lval);
01998             break;
01999         
02000         case xr_bool:
02001             if (value != NULL && octstr_parse_long(&lval, value, 0, 10) < 0) {
02002                 xrdoc->parse_status = XMLRPC_PARSING_FAILED;
02003                 xrdoc->parse_error = octstr_format("XML-RPC compiler: could not parse boolean value '%s'", 
02004                                                    octstr_get_cstr(value));
02005                 octstr_destroy(value);
02006                 return -1;
02007             }
02008             xrvalue->v_type = xr_scalar;
02009             xrvalue->v_scalar = xmlrpc_scalar_create(xr_bool, (void *) &lval);
02010             break;
02011 
02012         case xr_double:
02013             if (value != NULL && octstr_parse_double(&dval, value, 0) < 0) {
02014                 xrdoc->parse_status = XMLRPC_PARSING_FAILED;
02015                 xrdoc->parse_error = octstr_format("XML-RPC compiler: could not parse double value '%s'", 
02016                                                    octstr_get_cstr(value));
02017                 octstr_destroy(value);
02018                 return -1;
02019             }
02020             xrvalue->v_type = xr_scalar;
02021             xrvalue->v_scalar = xmlrpc_scalar_create(xr_double, (void *) &dval);
02022             break;
02023 
02024         case xr_string:
02025             xrvalue->v_type = xr_scalar;
02026             xrvalue->v_scalar = xmlrpc_scalar_create(xr_string, (void *) value);
02027             break;
02028 
02029         case xr_date:
02030             xrvalue->v_type = xr_scalar;
02031             xrvalue->v_scalar = xmlrpc_scalar_create(xr_date, (void *) value);
02032             break;
02033 
02034         case xr_base64:
02035             xrvalue->v_type = xr_scalar;
02036             xrvalue->v_scalar = xmlrpc_scalar_create(xr_base64, (void *) value);
02037             break;
02038 
02039         case xr_struct:
02040             xrvalue->v_type = xr_struct;
02041             xrvalue->v_struct = dict_create(OPTIMAL_STRUCT_SIZE, xmlrpc_value_destroy_item);
02042 
02043             if (parse_struct(doc, node->xmlChildrenNode, xrdoc, xrvalue->v_struct) == -1) {
02044                 octstr_destroy(value);
02045                 return -1;
02046             }
02047             break;
02048 
02049         case xr_array:
02050             xrvalue->v_type = xr_array;
02051             xrvalue->v_array = gwlist_create();
02052 
02053             if (parse_array(doc, node->xmlChildrenNode, xrdoc, xrvalue->v_array) == -1) {
02054                 xrdoc->parse_status = XMLRPC_PARSING_FAILED; 
02055                 xrdoc->parse_error = octstr_format("XML-RPC compiler: could not parse array"); 
02056                 octstr_destroy(value);
02057                 return -1;
02058             }
02059             break;
02060 
02061         default:
02062             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
02063             xrdoc->parse_error = octstr_format("XML-RPC compiler: bogus parsing exception in parse_value!");
02064             return -1;
02065     }
02066 
02067     octstr_destroy(value);
02068     return 0;
02069 }
02070 
02071 static int parse_struct(xmlDocPtr doc, xmlNodePtr node, 
02072                         XMLRPCDocument *xrdoc, Dict *members)
02073 {
02074     int status = 0;
02075   
02076     /* call for the parser function of the node type. */
02077     switch (node->type) {
02078 
02079         case XML_ELEMENT_NODE:
02080             status = parse_struct_element(doc, node, xrdoc, members);
02081             break;
02082 
02083         case XML_TEXT_NODE:
02084         case XML_COMMENT_NODE:
02085         case XML_PI_NODE:
02086             /* Text nodes, comments and PIs are ignored. */
02087             break;
02088            /*
02089             * XML has also many other node types, these are not needed with 
02090             * XML-RPC. Therefore they are assumed to be an error.
02091             */
02092         default:
02093             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
02094             xrdoc->parse_error = octstr_format("XML-RPC compiler: Unknown XML node in the XML-RPC source.");
02095             return -1;
02096             break;
02097     }
02098 
02099     if (node->next != NULL)
02100            if (parse_struct(doc, node->next, xrdoc, members) == -1)
02101             return -1;
02102 
02103     return status;
02104 }
02105 
02106 static int parse_struct_element(xmlDocPtr doc, xmlNodePtr node, 
02107                                 XMLRPCDocument *xrdoc, Dict *members)
02108 {
02109     Octstr *name;
02110     size_t i;
02111     XMLRPCMember *member;
02112 
02113     /*
02114      * check if the element is allowed at this level 
02115      */
02116     if (node->name == NULL) {
02117         error(0, "XMLRPC: XML struct element nodes without name!");
02118         xrdoc->parse_status = XMLRPC_XMLPARSE_FAILED;
02119         xrdoc->parse_error = octstr_format("XML-RPC compiler: bad XML");
02120         return -1;
02121     }
02122     
02123     name = octstr_create(node->name);
02124     if (octstr_len(name) == 0) {
02125         octstr_destroy(name);
02126         return -1;
02127     }
02128 
02129     i = 0;
02130     while (i < NUMBER_OF_STRUCT_ELEMENTS) {
02131         if (octstr_case_compare(name, octstr_imm(struct_elements[i].name)) == 0)
02132             break;
02133         ++i;
02134     }
02135     if (i == NUMBER_OF_STRUCT_ELEMENTS) {
02136         xrdoc->parse_status = XMLRPC_PARSING_FAILED;
02137         xrdoc->parse_error = octstr_format("XML-RPC compiler: unknown tag '%s' "
02138                                            "in XML source at level <struct>", 
02139                                            octstr_get_cstr(name));
02140         octstr_destroy(name);
02141         return -1;
02142     } 
02143     octstr_destroy(name);
02144 
02145     /* 
02146      * now check which type it is and process 
02147      *
02148      * valid tags at this level are:
02149      *   member [0]
02150      */
02151     if (i == 0) {
02152         /* this has been a <member> tag */
02153         member = xmlrpc_member_create();
02154         if (parse_member(doc, node->xmlChildrenNode, xrdoc, member) == -1) {
02155             xmlrpc_member_destroy(member, 1);
02156             return -1;
02157         }
02158         if (! dict_put_once(members, member->name, member->value)) {
02159             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
02160             xrdoc->parse_error = octstr_format("XML-RPC compiler: at least two members have same name.");
02161             xmlrpc_member_destroy(member, 1);
02162             return -1;
02163         }
02164         xmlrpc_member_destroy(member, 0);
02165     } else {
02166         /* we should never be here */
02167         xrdoc->parse_status = XMLRPC_PARSING_FAILED;
02168         xrdoc->parse_error = octstr_format("XML-RPC compiler: bogus parsing exception in parse_struct!");
02169         return -1;
02170     }
02171     return 0;
02172 }
02173 
02174 static int parse_member(xmlDocPtr doc, xmlNodePtr node, 
02175                         XMLRPCDocument *xrdoc, XMLRPCMember *member)
02176 {
02177     int status = 0;
02178   
02179     /* call for the parser function of the node type. */
02180     switch (node->type) {
02181 
02182         case XML_ELEMENT_NODE:
02183             status = parse_member_element(doc, node, xrdoc, member);
02184             break;
02185 
02186         case XML_TEXT_NODE:
02187         case XML_COMMENT_NODE:
02188         case XML_PI_NODE:
02189             /* Text nodes, comments and PIs are ignored. */
02190             break;
02191            /*
02192             * XML has also many other node types, these are not needed with 
02193             * XML-RPC. Therefore they are assumed to be an error.
02194             */
02195         default:
02196             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
02197             xrdoc->parse_error = octstr_format("XML-RPC compiler: Unknown XML node in the XML-RPC source.");
02198             return -1;
02199             break;
02200     }
02201 
02202     if (node->next != NULL)
02203            if (parse_member(doc, node->next, xrdoc, member) == -1)
02204             return -1;
02205 
02206     return status;
02207 }
02208 
02209 static int parse_member_element(xmlDocPtr doc, xmlNodePtr node, 
02210                                 XMLRPCDocument *xrdoc, XMLRPCMember *member)
02211 {
02212     Octstr *name;
02213     xmlChar *content_buff;
02214     size_t i;
02215 
02216     /*
02217      * check if the element is allowed at this level 
02218      */
02219     if (node->name == NULL) {
02220         error(0, "XMLRPC: XML member element nodes without name!");
02221         xrdoc->parse_status = XMLRPC_XMLPARSE_FAILED;
02222         xrdoc->parse_error = octstr_format("XML-RPC compiler: bad XML");
02223         return -1;
02224     }
02225 
02226     name = octstr_create(node->name);
02227     if (octstr_len(name) == 0) {
02228         octstr_destroy(name);
02229         return -1;
02230     }
02231 
02232     i = 0;
02233     while (i < NUMBER_OF_MEMBER_ELEMENTS) {
02234         if (octstr_case_compare(name, octstr_imm(member_elements[i].name)) == 0)
02235             break;
02236         ++i;
02237     }
02238     if (i == NUMBER_OF_MEMBER_ELEMENTS) {
02239         xrdoc->parse_status = XMLRPC_PARSING_FAILED;
02240         xrdoc->parse_error = octstr_format("XML-RPC compiler: unknown tag '%s' "
02241                                            "in XML source at level <member>", 
02242                                            octstr_get_cstr(name));
02243         octstr_destroy(name);
02244         return -1;
02245     } 
02246     octstr_destroy(name);
02247 
02248     /* 
02249      * now check which type it is and process 
02250      *
02251      * valid tags at this level are:
02252      *   name [0]
02253      *   value [1]
02254      */
02255     if (i == 0) {
02256         /* this has been a <name> tag */
02257         if (member->name != NULL) {
02258             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
02259             xrdoc->parse_error = octstr_format("XML-RPC compiler: duplicated tag '<name>' "
02260                                                "in XML source at level <member>");
02261             return -1;
02262         }
02263         content_buff = xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
02264         if (content_buff != NULL) {
02265             member->name = octstr_create(content_buff);
02266             xmlFree(content_buff);
02267         } else {
02268             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
02269             xrdoc->parse_error = octstr_format("XML-RPC compiler: empty tag <name> in XML source "
02270                                           "at level <member>");
02271             return -1;
02272         }
02273     } else {
02274         member->value = xmlrpc_value_create();
02275         if (parse_value(doc, node->xmlChildrenNode, xrdoc, member->value) == -1) {
02276             xmlrpc_value_destroy(member->value);
02277             member->value = NULL;
02278             return -1;    
02279         }
02280     }
02281     return 0;
02282 }
02283 
02284 static int parse_array(xmlDocPtr doc, xmlNodePtr node, 
02285                         XMLRPCDocument *xrdoc, List *elements)
02286 {
02287     int status = 0;
02288   
02289     /* call for the parser function of the node type. */
02290     switch (node->type) {
02291 
02292         case XML_ELEMENT_NODE:
02293             status = parse_array_element(doc, node, xrdoc, elements);
02294             break;
02295 
02296         case XML_TEXT_NODE:
02297         case XML_COMMENT_NODE:
02298         case XML_PI_NODE:
02299             /* Text nodes, comments and PIs are ignored. */
02300             break;
02301            /*
02302             * XML has also many other node types, these are not needed with 
02303             * XML-RPC. Therefore they are assumed to be an error.
02304             */
02305         default:
02306             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
02307             xrdoc->parse_error = octstr_format("XML-RPC compiler: Unknown XML node in the XML-RPC source.");
02308             return -1;
02309             break;
02310     }
02311 
02312     if (node->next != NULL)
02313            if (parse_array(doc, node->next, xrdoc, elements) == -1)
02314             return -1;
02315 
02316     return status;
02317 }
02318 
02319 static int parse_array_element(xmlDocPtr doc, xmlNodePtr node, 
02320                                 XMLRPCDocument *xrdoc, List *elements)
02321 {
02322     Octstr *name;
02323     size_t i;
02324 
02325     /*
02326      * check if the element is allowed at this level 
02327      */
02328     if (node->name == NULL) {
02329         error(0, "XMLRPC: XML array element nodes without name!");
02330         xrdoc->parse_status = XMLRPC_XMLPARSE_FAILED;
02331         xrdoc->parse_error = octstr_format("XML-RPC compiler: bad XML");
02332         return -1;
02333     }
02334 
02335     name = octstr_create(node->name);
02336     if (octstr_len(name) == 0) {
02337         octstr_destroy(name);
02338         return -1;
02339     }
02340 
02341     i = 0;
02342     while (i < NUMBER_OF_ARRAY_ELEMENTS) {
02343         if (octstr_case_compare(name, octstr_imm(array_elements[i].name)) == 0)
02344             break;
02345         ++i;
02346     }
02347     if (i == NUMBER_OF_ARRAY_ELEMENTS) {
02348         xrdoc->parse_status = XMLRPC_PARSING_FAILED;
02349         xrdoc->parse_error = octstr_format("XML-RPC compiler: unknown tag '%s' "
02350                                            "in XML source at level <array>", 
02351                                            octstr_get_cstr(name));
02352         octstr_destroy(name);
02353         return -1;
02354     } 
02355     octstr_destroy(name);
02356 
02357     /* 
02358      * now check which type it is and process 
02359      *
02360      * valid tags at this level are:
02361      *   data [0]
02362      */
02363     if (i == 0) {
02364         /* this has been a <data> tag */
02365         if (parse_data(doc, node->xmlChildrenNode, xrdoc, elements) == -1)
02366             return -1;
02367             
02368     } else {
02369         /* we should never be here */
02370         xrdoc->parse_status = XMLRPC_PARSING_FAILED;
02371         xrdoc->parse_error = octstr_format("XML-RPC compiler: bogus parsing exception in parse_array!");
02372         return -1;
02373     }
02374     return 0;
02375 }
02376 
02377 static int parse_data(xmlDocPtr doc, xmlNodePtr node, 
02378                       XMLRPCDocument *xrdoc, List *elements)
02379 {
02380     int status = 0;
02381   
02382     /* call for the parser function of the node type. */
02383     switch (node->type) {
02384 
02385         case XML_ELEMENT_NODE:
02386             status = parse_data_element(doc, node, xrdoc, elements);
02387             break;
02388 
02389         case XML_TEXT_NODE:
02390         case XML_COMMENT_NODE:
02391         case XML_PI_NODE:
02392             /* Text nodes, comments and PIs are ignored. */
02393             break;
02394            /*
02395             * XML has also many other node types, these are not needed with 
02396             * XML-RPC. Therefore they are assumed to be an error.
02397             */
02398         default:
02399             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
02400             xrdoc->parse_error = octstr_format("XML-RPC compiler: Unknown XML node in the XML-RPC source.");
02401             return -1;
02402             break;
02403     }
02404 
02405     if (node->next != NULL)
02406            if (parse_data(doc, node->next, xrdoc, elements) == -1)
02407             return -1;
02408 
02409     return status;
02410 }
02411 
02412 static int parse_data_element(xmlDocPtr doc, xmlNodePtr node, 
02413                               XMLRPCDocument *xrdoc, List *elements)
02414 {
02415     Octstr *name;
02416     XMLRPCValue *value;
02417     size_t i;
02418 
02419     /*
02420      * check if the element is allowed at this level 
02421      */
02422     if (node->name == NULL) {
02423         error(0, "XMLRPC: XML data element nodes without name!");
02424         xrdoc->parse_status = XMLRPC_XMLPARSE_FAILED;
02425         xrdoc->parse_error = octstr_format("XML-RPC compiler: bad XML");
02426         return -1;
02427     }
02428 
02429     name = octstr_create(node->name);
02430     if (octstr_len(name) == 0) {
02431         octstr_destroy(name);
02432         return -1;
02433     }
02434 
02435     i = 0;
02436     while (i < NUMBER_OF_DATA_ELEMENTS) {
02437         if (octstr_case_compare(name, octstr_imm(data_elements[i].name)) == 0)
02438             break;
02439         ++i;
02440     }
02441     if (i == NUMBER_OF_DATA_ELEMENTS) {
02442         xrdoc->parse_status = XMLRPC_PARSING_FAILED;
02443         xrdoc->parse_error = octstr_format("XML-RPC compiler: unknown tag '%s' "
02444                                            "in XML source at level <data>", 
02445                                            octstr_get_cstr(name));
02446         octstr_destroy(name);
02447         return -1;
02448     } 
02449     octstr_destroy(name);
02450 
02451     /* 
02452      * now check which type it is and process 
02453      *
02454      * valid tags at this level are:
02455      *  value [0]
02456      */
02457     if (i == 0) {
02458         /* this has been a <value> tag */
02459         value = xmlrpc_value_create();
02460         if (parse_value(doc, node->xmlChildrenNode, xrdoc, value) == -1) {
02461             xmlrpc_value_destroy(value);
02462             return -1;
02463         }
02464         gwlist_append(elements, value);
02465             
02466     } else {
02467         /* we should never be here */
02468         xrdoc->parse_status = XMLRPC_PARSING_FAILED;
02469         xrdoc->parse_error = octstr_format("XML-RPC compiler: bogus parsing exception in parse_array!");
02470         return -1;
02471     }
02472     return 0;
02473 }
02474 
02475 static int parse_fault(xmlDocPtr doc, xmlNodePtr node, 
02476                        XMLRPCDocument *xrdoc, XMLRPCFault *fault)
02477 {
02478     int status = 0;
02479   
02480     /* call for the parser function of the node type. */
02481     switch (node->type) {
02482 
02483         case XML_ELEMENT_NODE:
02484             status = parse_fault_element(doc, node, xrdoc, fault);
02485             break;
02486 
02487         case XML_TEXT_NODE:
02488         case XML_COMMENT_NODE:
02489         case XML_PI_NODE:
02490             /* Text nodes, comments and PIs are ignored. */
02491             break;
02492            /*
02493             * XML has also many other node types, these are not needed with 
02494             * XML-RPC. Therefore they are assumed to be an error.
02495             */
02496         default:
02497             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
02498             xrdoc->parse_error = octstr_format("XML-RPC compiler: Unknown XML node in the XML-RPC source.");
02499             return -1;
02500             break;
02501     }
02502 
02503     if (node->next != NULL)
02504            if (parse_fault(doc, node->next, xrdoc, fault) == -1)
02505             return -1;
02506 
02507     return status;
02508 }
02509 
02510 static int parse_fault_element(xmlDocPtr doc, xmlNodePtr node, 
02511                                XMLRPCDocument *xrdoc, XMLRPCFault *fault)
02512 {
02513     Octstr *name; 
02514     XMLRPCValue *value, *v_code, *v_string;
02515     size_t i;
02516 
02517     /*
02518      * check if the element is allowed at this level 
02519      */
02520     if (node->name == NULL) {
02521         error(0, "XMLRPC: XML fault element nodes without name!");
02522         xrdoc->parse_status = XMLRPC_XMLPARSE_FAILED;
02523         xrdoc->parse_error = octstr_format("XML-RPC compiler: bad XML");
02524         return -1;
02525     }
02526 
02527     name = octstr_create(node->name);
02528     if (octstr_len(name) == 0) {
02529         octstr_destroy(name);
02530         return -1;
02531     }
02532 
02533     i = 0;
02534     while (i < NUMBER_OF_FAULT_ELEMENTS) {
02535         if (octstr_case_compare(name, octstr_imm(fault_elements[i].name)) == 0)
02536             break;
02537         ++i;
02538     }
02539     if (i == NUMBER_OF_FAULT_ELEMENTS) {
02540         xrdoc->parse_status = XMLRPC_PARSING_FAILED;
02541         xrdoc->parse_error = octstr_format("XML-RPC compiler: unknown tag '%s' "
02542                                            "in XML source at level <fault>", 
02543                                            octstr_get_cstr(name));
02544         octstr_destroy(name);
02545         return -1;
02546     } 
02547     octstr_destroy(name);
02548 
02549     /* 
02550      * now check which type it is and process 
02551      *
02552      * valid tags at this level are:
02553      *   value [0]
02554      */
02555     if (i == 0) {
02556         /* this has been a <value> tag */
02557         value = xmlrpc_value_create();
02558         if (parse_value(doc, node->xmlChildrenNode, xrdoc, value) == -1) {
02559             xmlrpc_value_destroy(value);
02560             return -1;    
02561         }
02562         /* must be :
02563          *     <struct>
02564          *         <member>
02565          *             <name>faultCode</name>
02566          *             <value><int> ... </int></value>
02567          *         </member>
02568          *         <member>
02569          *             <name>faultString</name>
02570          *             <value><string> ... </string></value>
02571          *         </member>
02572          *     </struct> 
02573          */
02574         if (xmlrpc_value_get_type(value) != xr_struct ||
02575             (v_code = xmlrpc_get_member(value, octstr_imm("faultCode"))) == NULL ||
02576             xmlrpc_value_get_type_smart(v_code) != xr_int ||
02577             (v_string = xmlrpc_get_member(value, octstr_imm("faultString"))) == NULL ||
02578             xmlrpc_value_get_type_smart(v_string) != xr_string ||
02579             xmlrpc_count_members(value) != 2) {
02580             
02581             xrdoc->parse_status = XMLRPC_PARSING_FAILED;
02582             xrdoc->parse_error = octstr_format("XML-RPC compiler: bogus value "
02583                                                "in XML source at level <fault>");
02584             xmlrpc_value_destroy(value);
02585             return -1;
02586         }
02587         
02588         fault->f_code = xmlrpc_scalar_get_int((XMLRPCScalar *) xmlrpc_value_get_content(v_code));
02589         fault->f_string = xmlrpc_scalar_get_string((XMLRPCScalar *) xmlrpc_value_get_content(v_string));
02590         
02591         xmlrpc_value_destroy(value);
02592     } else {
02593         xrdoc->parse_status = XMLRPC_PARSING_FAILED;
02594         xrdoc->parse_error = octstr_format("XML-RPC compiler: duplicated tag '<name>' "
02595                                            "in XML source at level <member>");
02596         return -1;
02597     }
02598     return 0;
02599 }
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.