xmlrpc.c
上传用户:gzpyjq
上传日期:2013-01-31
资源大小:1852k
文件大小:32k
源码类别:

手机WAP编程

开发平台:

WINDOWS

  1. /*
  2.  * gwlib/xmlrpc.c: functions to handle XML-RPC structure - building and parsing
  3.  *
  4.  * XML-RPC is HTTP-based XML defination to handle remote procedure calls,
  5.  * and is defined at http://www.xml-rpc.org
  6.  *
  7.  * Kalle Marjola 2001 for project Kannel
  8.  * Stipe Tolj <tolj@wapme-systems.de>
  9.  */
  10. #include <libxml/xmlmemory.h>
  11. #include <libxml/tree.h>
  12. #include <libxml/debugXML.h>
  13. #include <libxml/encoding.h>
  14. #include "gwlib/gwlib.h"
  15. #include "gwlib/xmlrpc.h"
  16. struct xmlrpc_methodcall {
  17.     Octstr *method_name;
  18.     List *params;         /* List of XMLRPCValues */
  19.     int parse_status;     /* enum here */
  20.     Octstr *parse_error;  /* error string in case of parsing error */
  21. };
  22. struct xmlrpc_methodresponse {
  23.     XMLRPCValue *param; /* either this... */
  24.     XMLRPCValue *fault;  /* ..or this */
  25. };
  26. struct xmlrpc_value {
  27.     int v_type; /* enum here */
  28.     XMLRPCScalar *v_scalar;
  29.     List *v_array;     /* List of XMLRPCValues */
  30.     List *v_struct;    /* List of XMLRPMembers */
  31. };
  32. struct xmlrpc_member { /* member of struct */
  33.     Octstr *name;
  34.     XMLRPCValue *value;
  35. };
  36. struct xmlrpc_scalar {
  37.     int s_type; /* enum here */
  38.     Octstr *s_str;
  39.     long s_int;
  40.     int s_bool;
  41.     double s_double;
  42.     Octstr *s_date;
  43.     Octstr *s_base64;
  44. };
  45. struct xmlrpc_table_t {
  46.     char *name;
  47. };
  48. struct xmlrpc_2table_t {
  49.     char *name;
  50.     int s_type; /* enum here */
  51. };
  52. static xmlrpc_table_t methodcall_elements[] = {
  53.     { "METHODNAME" },
  54.     { "PARAMS" }
  55. };
  56. static xmlrpc_table_t params_elements[] = {
  57.     { "PARAM" }
  58. };
  59. static xmlrpc_table_t param_elements[] = {
  60.     { "VALUE" }
  61. };
  62. static xmlrpc_2table_t value_elements[] = {
  63.     { "I4", xr_int },
  64.     { "INT", xr_int },
  65.     { "BOOLEAN", xr_bool },
  66.     { "STRING", xr_string },
  67.     { "DOUBLE", xr_double },
  68.     { "DATETIME.ISO8601", xr_date },
  69.     { "BASE64", xr_base64 },
  70.     { "STRUCT", xr_struct },
  71.     { "ARRAY", xr_array }
  72. };
  73. static xmlrpc_table_t struct_elements[] = {
  74.     { "MEMBER" }
  75. };
  76. static xmlrpc_table_t member_elements[] = {
  77.     { "NAME" },
  78.     { "VALUE" }
  79. };
  80. #define NUMBER_OF_METHODCALL_ELEMENTS 
  81.     sizeof(methodcall_elements)/sizeof(methodcall_elements[0])
  82. #define NUMBER_OF_PARAMS_ELEMENTS 
  83.     sizeof(params_elements)/sizeof(params_elements[0])
  84. #define NUMBER_OF_PARAM_ELEMENTS 
  85.     sizeof(param_elements)/sizeof(param_elements[0])
  86. #define NUMBER_OF_VALUE_ELEMENTS 
  87.     sizeof(value_elements)/sizeof(value_elements[0])
  88. #define NUMBER_OF_STRUCT_ELEMENTS 
  89.     sizeof(struct_elements)/sizeof(struct_elements[0])
  90. #define NUMBER_OF_MEMBER_ELEMENTS 
  91.     sizeof(member_elements)/sizeof(member_elements[0])
  92. static int parse_document(xmlDocPtr document, XMLRPCMethodCall **msg);
  93. static int parse_methodcall(xmlDocPtr doc, xmlNodePtr node, 
  94.                             XMLRPCMethodCall **msg);
  95. static int parse_methodcall_element(xmlDocPtr doc, xmlNodePtr node, 
  96.                                     XMLRPCMethodCall **msg);
  97. static int parse_params(xmlDocPtr doc, xmlNodePtr node, 
  98.                         XMLRPCMethodCall **msg);
  99. static int parse_params_element(xmlDocPtr doc, xmlNodePtr node, 
  100.                                 XMLRPCMethodCall **msg);
  101. static int parse_param(xmlDocPtr doc, xmlNodePtr node, 
  102.                        XMLRPCMethodCall **msg, int *n);
  103. static int parse_param_element(xmlDocPtr doc, xmlNodePtr node, 
  104.                                XMLRPCMethodCall **msg);
  105. static int parse_value(xmlDocPtr doc, xmlNodePtr node, 
  106.                        XMLRPCMethodCall **msg);
  107. static int parse_value_element(xmlDocPtr doc, xmlNodePtr node, 
  108.                                XMLRPCMethodCall **msg);
  109. /*-------------------------------------
  110.  * MethodCall
  111.  */
  112. XMLRPCMethodCall *xmlrpc_call_create(Octstr *name)
  113. {
  114.     XMLRPCMethodCall *nmsg = gw_malloc(sizeof(XMLRPCMethodCall));
  115.     nmsg->method_name = octstr_duplicate(name);
  116.     nmsg->params = list_create();
  117.     nmsg->parse_status = XMLRPC_COMPILE_OK;
  118.     nmsg->parse_error = NULL;
  119.     
  120.     return nmsg;
  121. }
  122. XMLRPCMethodCall *xmlrpc_call_parse(Octstr *post_body)
  123. {
  124.     XMLRPCMethodCall *msg = gw_malloc(sizeof(XMLRPCMethodCall));
  125.     xmlDocPtr pDoc;
  126.     size_t size;
  127.     char *body;
  128.     int ret;
  129.     msg->method_name = octstr_create("");
  130.     msg->params = list_create();
  131.     msg->parse_status = XMLRPC_COMPILE_OK;
  132.     msg->parse_error = NULL;
  133.     octstr_strip_blanks(post_body);
  134.     octstr_shrink_blanks(post_body);
  135.     size = octstr_len(post_body);
  136.     body = octstr_get_cstr(post_body);
  137.     /* parse XML document to a XML tree */
  138.     pDoc = xmlParseMemory(body, size);
  139.     ret = parse_document(pDoc, &msg);
  140.     xmlFreeDoc(pDoc);
  141.     return msg;
  142. }
  143. void xmlrpc_call_destroy(XMLRPCMethodCall *call)
  144. {
  145.     if (call == NULL)
  146. return;
  147.     octstr_destroy(call->method_name);
  148.     list_destroy(call->params, xmlrpc_value_destroy_item);
  149.     if (call->parse_error != NULL)
  150.         octstr_destroy(call->parse_error);
  151.     gw_free(call);
  152. }
  153. int xmlrpc_call_add_scalar(XMLRPCMethodCall *method, int type, void *arg)
  154. {
  155.     XMLRPCValue *nval;
  156.     if (method == NULL)
  157.         return -1;
  158.     nval = xmlrpc_create_scalar_value(type, arg);
  159.     list_produce(method->params, nval);
  160.     return 0;
  161. }
  162. int xmlrpc_call_add_value(XMLRPCMethodCall *method, XMLRPCValue *value)
  163. {
  164.     if (method == NULL || value == NULL)
  165. return -1;
  166.     list_produce(method->params, value);
  167.     return 0;
  168. }
  169. Octstr *xmlrpc_call_octstr(XMLRPCMethodCall *call)
  170. {
  171.     Octstr *body;
  172.     XMLRPCValue *val;
  173.     long i;
  174.     
  175.     body = octstr_format("<?xml version="1.0"?>n<methodCall>n"
  176.              "  <methodName>%S</methodName>n"
  177.              "  <params>", call->method_name);
  178.     list_lock(call->params);
  179.     for (i = 0; i < list_len(call->params); i++) {
  180.         val = list_get(call->params, i);
  181.         octstr_format_append(body, "n    <param>n"
  182.                              "n      ");
  183.         xmlrpc_value_print(val, body);
  184.         octstr_format_append(body, "n    </param>n");
  185.         
  186.     }
  187.     list_unlock(call->params);
  188.     
  189.     octstr_format_append(body, "  </params>n"
  190.              "</methodCall>n");
  191.     return body;
  192. }
  193. int xmlrpc_call_send(XMLRPCMethodCall *call, HTTPCaller *http_ref,
  194.      Octstr *url, List *headers, void *ref)
  195. {
  196.     Octstr *body;
  197.     if (http_ref == NULL || call == NULL)
  198. return -1;
  199.     
  200.     if (headers == NULL)
  201. headers = list_create();
  202.     
  203.     http_header_add(headers, "Content-Type", "text/xml");
  204.     /* 
  205.      * XML-RPC specs say we at least need Host and User-Agent 
  206.      * HTTP headers to be defined.
  207.      * These are set anyway within gwlib/http.c:build_request()
  208.      */
  209.     body = xmlrpc_call_octstr(call);
  210.     http_start_request(http_ref, HTTP_METHOD_GET, 
  211.                        url, headers, body, 0, ref, NULL);
  212.     
  213.     octstr_destroy(body);
  214.     http_destroy_headers(headers);
  215.     return 0;
  216. }
  217. /*-------------------------------------
  218.  * MethodResponse
  219.  */
  220. XMLRPCMethodResponse *xmlrpc_response_create(XMLRPCValue *param)
  221. {
  222.     XMLRPCMethodResponse *nmsg = gw_malloc(sizeof(XMLRPCMethodResponse));
  223.     nmsg->param = param;
  224.     nmsg->fault = NULL;
  225.     
  226.     return nmsg;
  227. }
  228. void xmlrpc_response_destroy(XMLRPCMethodResponse *response)
  229. {
  230.     if (response == NULL)
  231. return;
  232.     xmlrpc_value_destroy(response->param);
  233.     xmlrpc_value_destroy(response->fault);
  234.     gw_free(response);
  235. }
  236. /* Create new value. Set type of it to undefined, so it must be
  237.  * set laterwards to correct one
  238.  */
  239. XMLRPCValue *xmlrpc_value_create(void)
  240. {
  241.     XMLRPCValue *val = gw_malloc(sizeof(XMLRPCValue));
  242.     val->v_type = xr_undefined;
  243.     val->v_scalar = NULL;
  244.     val->v_array = NULL;
  245.     val->v_struct = NULL;
  246.     return val;
  247. }
  248. /* Destroy value with its information, recursively if need to */
  249. void xmlrpc_value_destroy(XMLRPCValue *val)
  250. {
  251.     if (val == NULL)
  252. return;
  253.     switch(val->v_type) {
  254.     case xr_scalar:
  255. xmlrpc_scalar_destroy(val->v_scalar);
  256. break;
  257.     case xr_array:
  258. list_destroy(val->v_array, xmlrpc_value_destroy_item);
  259. break;
  260.     case xr_struct:
  261. list_destroy(val->v_struct, xmlrpc_member_destroy_item);
  262. break;
  263.     }
  264.     gw_free(val);
  265. }
  266. /* wrapper to destroy to be used with list */
  267. void xmlrpc_value_destroy_item(void *val)
  268. {
  269.     xmlrpc_value_destroy(val);
  270. }
  271. void xmlrpc_value_print(XMLRPCValue *val, Octstr *os)
  272. {
  273.     if (val->v_type != xr_scalar)
  274. return;
  275.     octstr_format_append(os, "<value>");
  276.     xmlrpc_scalar_print(val->v_scalar, os);
  277.     octstr_format_append(os, "</value>");
  278. }
  279. /* Create new member with undefined value */
  280. XMLRPCMember *xmlrpc_member_create(Octstr *name)
  281. {
  282.     XMLRPCMember *member = gw_malloc(sizeof(XMLRPCMember));
  283.     gw_assert(name);
  284.     member->name = octstr_duplicate(name);
  285.     member->value = xmlrpc_value_create();
  286.     return member;
  287. }
  288. /* Destroy member and its contents */
  289. void xmlrpc_member_destroy(XMLRPCMember *member)
  290. {
  291.     if (member == NULL)
  292. return;
  293.     xmlrpc_value_destroy(member->value);
  294.     octstr_destroy(member->name);
  295.     gw_free(member);
  296. }
  297. void xmlrpc_member_destroy_item(void *member)
  298. {
  299.     xmlrpc_member_destroy(member);
  300. }
  301. /* Create new scalar of given type with given argument */
  302. XMLRPCScalar *xmlrpc_scalar_create(int type, void *arg)
  303. {
  304.     XMLRPCScalar *scalar = gw_malloc(sizeof(XMLRPCScalar));
  305.     scalar->s_type = type;
  306.     scalar->s_int = 0;
  307.     scalar->s_bool = 0;
  308.     scalar->s_double = 0;
  309.     scalar->s_str = NULL;
  310.     scalar->s_date = NULL;
  311.     scalar->s_base64 = NULL;
  312.     
  313.     switch (type) {
  314.         case xr_int:
  315.             scalar->s_int = (long)arg;
  316.             break;
  317.         case xr_bool:
  318.             scalar->s_bool = (int)arg;
  319.             break;
  320.         case xr_string:
  321.             scalar->s_str = octstr_duplicate((Octstr *)arg);
  322.             break;
  323.         case xr_date:
  324.             scalar->s_date = octstr_duplicate((Octstr *)arg);
  325.             break;
  326.         case xr_base64:
  327.             scalar->s_base64 = octstr_duplicate((Octstr *)arg);
  328.             break;
  329.         default:
  330.             panic(0,"XML-RPC: scalar type not supported!");
  331.             break;
  332.     }
  333.     return scalar;
  334. }
  335. XMLRPCScalar *xmlrpc_scalar_create_double(int type, double val)
  336. {
  337.     XMLRPCScalar *scalar = gw_malloc(sizeof(XMLRPCScalar));
  338.     scalar->s_type = type;
  339.     scalar->s_int = 0;
  340.     scalar->s_bool = 0;
  341.     scalar->s_double = 0;
  342.     scalar->s_str = NULL;
  343.     scalar->s_date = NULL;
  344.     scalar->s_base64 = NULL;
  345.     
  346.     switch (type) {
  347.         case xr_double:
  348.             scalar->s_double = val;
  349.             break;
  350.         default:
  351.             panic(0,"XML-RPC: scalar type not supported!");
  352.             break;
  353.     }
  354.     return scalar;
  355. }
  356. /* Destroy scalar */
  357. void xmlrpc_scalar_destroy(XMLRPCScalar *scalar)
  358. {
  359.     if (scalar == NULL)
  360. return;
  361.     octstr_destroy(scalar->s_str);
  362.     octstr_destroy(scalar->s_date);
  363.     octstr_destroy(scalar->s_base64);
  364.     
  365.     gw_free(scalar);
  366. }
  367. void xmlrpc_scalar_print(XMLRPCScalar *scalar, Octstr *os)
  368. {
  369.     switch (scalar->s_type) {
  370.         case xr_int:
  371.             octstr_format_append(os, "<int>%d</int>", scalar->s_int);
  372.             break;
  373.         case xr_bool:
  374.             octstr_format_append(os, "<bool>%d</bool>", scalar->s_bool);
  375.             break;
  376.         case xr_string:
  377.             octstr_format_append(os, "<string>%S</string>", scalar->s_str);
  378.             break;
  379.         case xr_double:
  380.             octstr_format_append(os, "<double>%d</double>", scalar->s_double);
  381.             break;
  382.         case xr_date:
  383.             octstr_format_append(os, "<date>%S</date>", scalar->s_date);
  384.             break;
  385.         case xr_base64:
  386.             octstr_format_append(os, "<base64>%S</base64>", scalar->s_base64);
  387.             break;
  388.     }
  389. }
  390. /*-------------------------------------------------
  391.  * Utilities to make things easier
  392.  */
  393. /* create scalar value from given arguments
  394.  * XXX: Should this take different kind of arguments?
  395.  */
  396. XMLRPCValue *xmlrpc_create_scalar_value(int type, void *arg)
  397. {
  398.     XMLRPCValue *value = xmlrpc_value_create();
  399.     value->v_type = xr_scalar;
  400.     value->v_scalar = xmlrpc_scalar_create(type, arg);
  401.     return value;
  402. }
  403. XMLRPCValue *xmlrpc_create_scalar_value_double(int type, double val)
  404. {
  405.     XMLRPCValue *value = xmlrpc_value_create();
  406.     value->v_type = xr_scalar;
  407.     value->v_scalar = xmlrpc_scalar_create_double(type, val);
  408.     return value;
  409. }
  410. XMLRPCValue *xmlrpc_create_struct_value(int type, void *arg)
  411. {
  412.     XMLRPCValue *value = xmlrpc_value_create();
  413.     value->v_type = xr_struct;
  414.     value->v_struct = list_create();
  415.     return value;
  416. }
  417. int xmlrpc_parse_status(XMLRPCMethodCall *call)
  418. {
  419.     if (call == NULL)
  420.    return -1;
  421.     return call->parse_status;
  422. }
  423. Octstr *xmlrpc_parse_error(XMLRPCMethodCall *call) 
  424. {
  425.     if (call == NULL)
  426.         return NULL;
  427.     
  428.     return call->parse_error;
  429. }
  430. Octstr *xmlrpc_get_method_name(XMLRPCMethodCall *call)
  431. {
  432.     if (call == NULL)
  433.         return NULL;
  434.     return call->method_name;
  435. }
  436. int xmlrpc_call_len(XMLRPCMethodCall *call)
  437. {
  438.     if (call == NULL)
  439.         return 0;
  440.     return list_len(call->params);
  441. }
  442. int xmlrpc_get_type(XMLRPCMethodCall *call, int pos)
  443. {
  444.     XMLRPCValue *var;
  445.     if (call == NULL)
  446.         return -1;
  447.     var = list_get(call->params, pos);
  448.     return var->v_type;
  449. }
  450. /*-------------------------------------------------
  451.  * Internal parser functions
  452.  */
  453. static int parse_member_element(xmlDocPtr doc, xmlNodePtr node, 
  454.                                 XMLRPCMethodCall **msg)
  455. {
  456.     Octstr *name;
  457.     size_t i;
  458.     /*
  459.      * check if the element is allowed at this level 
  460.      */
  461.     name = octstr_create(node->name);
  462.     if (octstr_len(name) == 0) {
  463.         octstr_destroy(name);
  464.         return -1;
  465.     }
  466.     i = 0;
  467.     while (i < NUMBER_OF_MEMBER_ELEMENTS) {
  468.         if (octstr_case_compare(name, octstr_imm(member_elements[i].name)) == 0)
  469.             break;
  470.         ++i;
  471.     }
  472.     if (i == NUMBER_OF_MEMBER_ELEMENTS) {
  473.         (*msg)->parse_status = XMLRPC_PARSING_FAILED;
  474.         (*msg)->parse_error = octstr_format("XML-RPC compiler: unknown tag '%s' "
  475.                                             "in XML source at level <member>", 
  476.                                             octstr_get_cstr(name));
  477.         octstr_destroy(name);
  478.         return -1;
  479.     } 
  480.     octstr_destroy(name);
  481.     /* 
  482.      * now check which type it is and process 
  483.      *
  484.      * valid tags at this level are:
  485.      *   name [0]
  486.      *   value [1]
  487.      */
  488.     if (i == 0) {
  489.         /* this has been a <member> tag */
  490.         //if (parse_name(doc, node->xmlChildrenNode, msg) == -1)
  491.         //    return -1;
  492.     } else {
  493.         /* we should never be here */
  494.         (*msg)->parse_status = XMLRPC_PARSING_FAILED;
  495.         (*msg)->parse_error = octstr_format("XML-RPC compiler: bogus parsing exception in parse_member!");
  496.         return -1;
  497.     }
  498.     return 0;
  499. }
  500. static int parse_member(xmlDocPtr doc, xmlNodePtr node, 
  501.                         XMLRPCMethodCall **msg)
  502. {
  503.     int status = 0;
  504.   
  505.     /* call for the parser function of the node type. */
  506.     switch (node->type) {
  507.         case XML_ELEMENT_NODE:
  508.             status = parse_member_element(doc, node, msg);
  509.             break;
  510.         case XML_TEXT_NODE:
  511.         case XML_COMMENT_NODE:
  512.         case XML_PI_NODE:
  513.             /* Text nodes, comments and PIs are ignored. */
  514.             break;
  515.    /*
  516.     * XML has also many other node types, these are not needed with 
  517.     * XML-RPC. Therefore they are assumed to be an error.
  518.     */
  519.         default:
  520.             (*msg)->parse_status = XMLRPC_PARSING_FAILED;
  521.             (*msg)->parse_error = octstr_format("XML-RPC compiler: Unknown XML node in the XML-RPC source.");
  522.             return -1;
  523.             break;
  524.     }
  525.     if (node->next != NULL)
  526.    if (parse_member(doc, node->next, msg) == -1)
  527.             return -1;
  528.     return status;
  529. }
  530. static int parse_struct_element(xmlDocPtr doc, xmlNodePtr node, 
  531.                                 XMLRPCMethodCall **msg)
  532. {
  533.     Octstr *name;
  534.     size_t i;
  535.     /*
  536.      * check if the element is allowed at this level 
  537.      */
  538.     name = octstr_create(node->name);
  539.     if (octstr_len(name) == 0) {
  540.         octstr_destroy(name);
  541.         return -1;
  542.     }
  543.     i = 0;
  544.     while (i < NUMBER_OF_STRUCT_ELEMENTS) {
  545.         if (octstr_case_compare(name, octstr_imm(struct_elements[i].name)) == 0)
  546.             break;
  547.         ++i;
  548.     }
  549.     if (i == NUMBER_OF_STRUCT_ELEMENTS) {
  550.         (*msg)->parse_status = XMLRPC_PARSING_FAILED;
  551.         (*msg)->parse_error = octstr_format("XML-RPC compiler: unknown tag '%s' "
  552.                                             "in XML source at level <struct>", 
  553.                                             octstr_get_cstr(name));
  554.         octstr_destroy(name);
  555.         return -1;
  556.     } 
  557.     octstr_destroy(name);
  558.     /* 
  559.      * now check which type it is and process 
  560.      *
  561.      * valid tags at this level are:
  562.      *   member [0]
  563.      */
  564.     if (i == 0) {
  565.         /* this has been a <member> tag */
  566.         if (parse_member(doc, node->xmlChildrenNode, msg) == -1)
  567.             return -1;
  568.     } else {
  569.         /* we should never be here */
  570.         (*msg)->parse_status = XMLRPC_PARSING_FAILED;
  571.         (*msg)->parse_error = octstr_format("XML-RPC compiler: bogus parsing exception in parse_struct!");
  572.         return -1;
  573.     }
  574.     return 0;
  575. }
  576. static int parse_struct(xmlDocPtr doc, xmlNodePtr node, 
  577.                         XMLRPCMethodCall **msg)
  578. {
  579.     int status = 0;
  580.   
  581.     /* call for the parser function of the node type. */
  582.     switch (node->type) {
  583.         case XML_ELEMENT_NODE:
  584.             status = parse_struct_element(doc, node, msg);
  585.             break;
  586.         case XML_TEXT_NODE:
  587.         case XML_COMMENT_NODE:
  588.         case XML_PI_NODE:
  589.             /* Text nodes, comments and PIs are ignored. */
  590.             break;
  591.    /*
  592.     * XML has also many other node types, these are not needed with 
  593.     * XML-RPC. Therefore they are assumed to be an error.
  594.     */
  595.         default:
  596.             (*msg)->parse_status = XMLRPC_PARSING_FAILED;
  597.             (*msg)->parse_error = octstr_format("XML-RPC compiler: Unknown XML node in the XML-RPC source.");
  598.             return -1;
  599.             break;
  600.     }
  601.     if (node->next != NULL)
  602.    if (parse_struct(doc, node->next, msg) == -1)
  603.             return -1;
  604.     return status;
  605. }
  606. static int parse_value_element(xmlDocPtr doc, xmlNodePtr node, 
  607.                                XMLRPCMethodCall **msg)
  608. {
  609.     Octstr *name;
  610.     Octstr *value;
  611.     long lval = 0;
  612.     size_t i;
  613.     /*
  614.      * check if the element is allowed at this level 
  615.      */
  616.     name = octstr_create(node->name);
  617.     if (octstr_len(name) == 0) {
  618.         octstr_destroy(name);
  619.         return -1;
  620.     }
  621.     i = 0;
  622.     while (i < NUMBER_OF_VALUE_ELEMENTS) {
  623.         if (octstr_case_compare(name, octstr_imm(value_elements[i].name)) == 0)
  624.             break;
  625.         ++i;
  626.     }
  627.     if (i == NUMBER_OF_VALUE_ELEMENTS) {
  628.         (*msg)->parse_status = XMLRPC_PARSING_FAILED;
  629.         (*msg)->parse_error = octstr_format("XML-RPC compiler: unknown tag '%s' "
  630.                                             "in XML source at level <value>", 
  631.                                             octstr_get_cstr(name));
  632.         octstr_destroy(name);
  633.         return -1;
  634.     } 
  635.     octstr_destroy(name);
  636.     value = octstr_create(xmlNodeListGetString(doc, node->xmlChildrenNode, 1));
  637.     if (value == NULL) {
  638.         (*msg)->parse_status = XMLRPC_PARSING_FAILED;
  639.         (*msg)->parse_error = octstr_format("XML-RPC compiler: no value for '%s'", 
  640.                                             node->name);
  641.         return -1;
  642.     }
  643.     /* 
  644.      * now check which type it is and process 
  645.      *
  646.      * valid tags at this level are:
  647.      *   i4, int
  648.      *   boolean
  649.      *   string
  650.      *   double
  651.      *   dateTime.iso8601
  652.      *   base64
  653.      *   struct
  654.      *   array
  655.      */
  656.     switch (value_elements[i].s_type) {
  657.         
  658.         /*
  659.          * scalar types
  660.          */
  661.         case xr_int:
  662.             if (octstr_parse_long(&lval, value, 0, 10) < 0) {
  663.                 (*msg)->parse_status = XMLRPC_PARSING_FAILED;
  664.                 (*msg)->parse_error = octstr_format("XML-RPC compiler: could not parse int value '%s'", 
  665.                                                     octstr_get_cstr(value));
  666.                 return -1;
  667.             }
  668.             //xmlrpc_call_add_int((*msg), lval);
  669.             xmlrpc_call_add_scalar((*msg), xr_int, (void *) lval);
  670.             debug("", 0, "XML-RPC: added int %ld", lval);
  671.             break;
  672.         
  673.         case xr_bool:
  674.             if (octstr_parse_long(&lval, value, 0, 10) < 0) {
  675.                 (*msg)->parse_status = XMLRPC_PARSING_FAILED;
  676.                 (*msg)->parse_error = octstr_format("XML-RPC compiler: could not parse boolean value '%s'", 
  677.                                                     octstr_get_cstr(value));
  678.                 return -1;
  679.             }
  680.             //xmlrpc_call_add_bool((*msg), (int) lval);
  681.             xmlrpc_call_add_scalar((*msg), xr_bool, (void *) lval);
  682.             debug("", 0, "XML-RPC: added boolean %d", (int) lval);
  683.             break;
  684.         case xr_string:
  685.             //xmlrpc_call_add_string((*msg), value);
  686.             xmlrpc_call_add_scalar((*msg), xr_string, (void *) value);
  687.             debug("", 0, "XML-RPC: added string %s", octstr_get_cstr(value));
  688.             break;
  689.         case xr_date:
  690.             //xmlrpc_call_add_date((*msg), value);
  691.             xmlrpc_call_add_scalar((*msg), xr_date, (void *) value);
  692.             debug("", 0, "XML-RPC: added date %s", octstr_get_cstr(value));
  693.             break;
  694.         case xr_base64:
  695.             //xmlrpc_call_add_base64((*msg), value);
  696.             xmlrpc_call_add_scalar((*msg), xr_base64, (void *) value);
  697.             debug("", 0, "XML-RPC: added base64 %s", octstr_get_cstr(value));
  698.             break;
  699.         case xr_struct:
  700.             if (parse_struct(doc, node->xmlChildrenNode, msg) == -1) {
  701.                 debug("", 0, "%s", octstr_get_cstr((*msg)->parse_error));
  702.                 //(*msg)->parse_status = XMLRPC_PARSING_FAILED;
  703.                 //(*msg)->parse_error = octstr_format("XML-RPC compiler: could not parse struct"); 
  704.                 return -1;
  705.             }
  706.             //debug("", 0, "XML-RPC: added struct %s", octstr_get_cstr(value));
  707.             break;
  708.         case xr_double:
  709.         default:
  710.             (*msg)->parse_status = XMLRPC_PARSING_FAILED;
  711.             (*msg)->parse_error = octstr_format("XML-RPC compiler: bogus parsing exception in parse_value!");
  712.             return -1;
  713.             break;
  714.     }
  715.     octstr_destroy(value);
  716.     return 0;
  717. }
  718. static int parse_value(xmlDocPtr doc, xmlNodePtr node, 
  719.                        XMLRPCMethodCall **msg)
  720. {
  721.     int status = 0;
  722.   
  723.     /* call for the parser function of the node type. */
  724.     switch (node->type) {
  725.         case XML_ELEMENT_NODE:
  726.             status = parse_value_element(doc, node, msg);
  727.             break;
  728.         case XML_TEXT_NODE:
  729.         case XML_COMMENT_NODE:
  730.         case XML_PI_NODE:
  731.             /* Text nodes, comments and PIs are ignored. */
  732.             break;
  733.    /*
  734.     * XML has also many other node types, these are not needed with 
  735.     * XML-RPC. Therefore they are assumed to be an error.
  736.     */
  737.         default:
  738.             (*msg)->parse_status = XMLRPC_PARSING_FAILED;
  739.             (*msg)->parse_error = octstr_format("XML-RPC compiler: Unknown XML node in the XML-RPC source.");
  740.             return -1;
  741.             break;
  742.     }
  743.     if (node->next != NULL)
  744.    if (parse_value(doc, node->next, msg) == -1)
  745.             return -1;
  746.     return status;
  747. }
  748. static int parse_param_element(xmlDocPtr doc, xmlNodePtr node, 
  749.                                XMLRPCMethodCall **msg)
  750. {
  751.     Octstr *name;
  752.     size_t i;
  753.     /*
  754.      * check if the element is allowed at this level 
  755.      */
  756.     name = octstr_create(node->name);
  757.     if (octstr_len(name) == 0) {
  758.         octstr_destroy(name);
  759.         return -1;
  760.     }
  761.     i = 0;
  762.     while (i < NUMBER_OF_PARAM_ELEMENTS) {
  763.         if (octstr_case_compare(name, octstr_imm(param_elements[i].name)) == 0)
  764.             break;
  765.         ++i;
  766.     }
  767.     if (i == NUMBER_OF_PARAM_ELEMENTS) {
  768.         (*msg)->parse_status = XMLRPC_PARSING_FAILED;
  769.         (*msg)->parse_error = octstr_format("XML-RPC compiler: unknown tag '%s' "
  770.                                             "in XML source at level <param>", 
  771.                                             octstr_get_cstr(name));
  772.         octstr_destroy(name);
  773.         return -1;
  774.     } 
  775.     octstr_destroy(name);
  776.     /* 
  777.      * now check which type it is and process 
  778.      *
  779.      * valid tags at this level are:
  780.      *   value [0]
  781.      */
  782.     if (i == 0) {
  783.         /* this has been a <param> tag */
  784.         if (parse_value(doc, node->xmlChildrenNode, msg) == -1)
  785.             return -1;
  786.     } else {
  787.         /* we should never be here */
  788.         (*msg)->parse_status = XMLRPC_PARSING_FAILED;
  789.         (*msg)->parse_error = octstr_format("XML-RPC compiler: bogus parsing exception in parse_param!");
  790.         return -1;
  791.     }
  792.     return 0;
  793. }
  794. static int parse_param(xmlDocPtr doc, xmlNodePtr node, 
  795.                        XMLRPCMethodCall **msg, int *n)
  796. {
  797.     int status = 0;
  798.   
  799.     /* call for the parser function of the node type. */
  800.     switch (node->type) {
  801.         case XML_ELEMENT_NODE:
  802.             /* a <param> can only have one value element type */
  803.             if ((*n) > 0) {
  804.                 (*msg)->parse_status = XMLRPC_PARSING_FAILED;
  805.                 (*msg)->parse_error = octstr_format("XML-RPC compiler: param may only have one value!");
  806.                 return -1;
  807.             }
  808.             status = parse_param_element(doc, node, msg);
  809.             (*n)++;
  810.             break;
  811.         case XML_TEXT_NODE:
  812.         case XML_COMMENT_NODE:
  813.         case XML_PI_NODE:
  814.             /* Text nodes, comments and PIs are ignored. */
  815.             break;
  816.    /*
  817.     * XML has also many other node types, these are not needed with 
  818.     * XML-RPC. Therefore they are assumed to be an error.
  819.     */
  820.         default:
  821.             (*msg)->parse_status = XMLRPC_PARSING_FAILED;
  822.             (*msg)->parse_error = octstr_format("XML-RPC compiler: Unknown XML node in the XML-RPC source.");
  823.             return -1;
  824.             break;
  825.     }
  826.    
  827.     if (node->next != NULL)
  828.    if (parse_param(doc, node->next, msg, n) == -1)
  829.             return -1;
  830.     return status;
  831. }
  832. static int parse_params_element(xmlDocPtr doc, xmlNodePtr node, 
  833.                                 XMLRPCMethodCall **msg)
  834. {
  835.     Octstr *name;
  836.     size_t i;
  837.     int n = 0;
  838.     /*
  839.      * check if the element is allowed at this level
  840.      * within <params> we only have one or more <param>
  841.      */
  842.     name = octstr_create(node->name);
  843.     if (octstr_len(name) == 0) {
  844.         octstr_destroy(name);
  845.         return -1;
  846.     }
  847.     i = 0;
  848.     while (i < NUMBER_OF_PARAMS_ELEMENTS) {
  849.         if (octstr_case_compare(name, octstr_imm(params_elements[i].name)) == 0)
  850.             break;
  851.         ++i;
  852.     }
  853.     if (i == NUMBER_OF_PARAMS_ELEMENTS) {
  854.         (*msg)->parse_status = XMLRPC_PARSING_FAILED;
  855.         (*msg)->parse_error = octstr_format("XML-RPC compiler: unknown tag '%s' "
  856.                                             "in XML source at level <params>", 
  857.                                             octstr_get_cstr(name));
  858.         octstr_destroy(name);
  859.         return -1;
  860.     } 
  861.     octstr_destroy(name);
  862.     /* 
  863.      * now check which type it is and process 
  864.      *
  865.      * valid tags at this level are:
  866.      *   param [0]
  867.      */
  868.     if (i == 0) {
  869.         /* this has been a <param> tag */
  870.         if (parse_param(doc, node->xmlChildrenNode, msg, &n) == -1)
  871.             return -1;
  872.     } else {
  873.         /* we should never be here */
  874.         (*msg)->parse_status = XMLRPC_PARSING_FAILED;
  875.         (*msg)->parse_error = octstr_format("XML-RPC compiler: bogus parsing exception in parse_params!");
  876.         return -1;
  877.     }
  878.     return 0;
  879. }
  880. static int parse_params(xmlDocPtr doc, xmlNodePtr node, 
  881.                         XMLRPCMethodCall **msg)
  882. {
  883.     int status = 0;
  884.   
  885.     /* call for the parser function of the node type. */
  886.     switch (node->type) {
  887.         case XML_ELEMENT_NODE:
  888.             status = parse_params_element(doc, node, msg);
  889.             break;
  890.         case XML_TEXT_NODE:
  891.         case XML_COMMENT_NODE:
  892.         case XML_PI_NODE:
  893.             /* Text nodes, comments and PIs are ignored. */
  894.             break;
  895.    /*
  896.     * XML has also many other node types, these are not needed with 
  897.     * XML-RPC. Therefore they are assumed to be an error.
  898.     */
  899.         default:
  900.             (*msg)->parse_status = XMLRPC_PARSING_FAILED;
  901.             (*msg)->parse_error = octstr_format("XML-RPC compiler: unknown XML node in XML-RPC source.");
  902.             return -1;
  903.             break;
  904.     }
  905.     if (node->next != NULL)
  906.    if (parse_params(doc, node->next, msg) == -1)
  907.             return -1;
  908.     return status;
  909. }
  910. static int parse_methodcall_element(xmlDocPtr doc, xmlNodePtr node, 
  911.                                     XMLRPCMethodCall **msg)
  912. {
  913.     Octstr *name;
  914.     Octstr *value;
  915.     size_t i;
  916.     /*
  917.      * check if the element is allowed at this level 
  918.      */
  919.     name = octstr_create(node->name);
  920.     if (octstr_len(name) == 0) {
  921.         octstr_destroy(name);
  922.         return -1;
  923.     }
  924.     i = 0;
  925.     while (i < NUMBER_OF_METHODCALL_ELEMENTS) {
  926.         if (octstr_case_compare(name, octstr_imm(methodcall_elements[i].name)) == 0)
  927.             break;
  928.         ++i;
  929.     }
  930.     if (i == NUMBER_OF_METHODCALL_ELEMENTS) {
  931.         (*msg)->parse_status = XMLRPC_PARSING_FAILED;
  932.         (*msg)->parse_error = octstr_format("XML-RPC compiler: unknown tag '%s' in XML source "
  933.                                             "at level <methodCall>", octstr_get_cstr(name));
  934.         octstr_destroy(name);
  935.         return -1;
  936.     } 
  937.     octstr_destroy(name);
  938.     /* 
  939.      * now check which type it is and process 
  940.      *
  941.      * valid tags at this level are:
  942.      *   methodCall [0]
  943.      *   params     [1]
  944.      */
  945.     if (i == 0) {
  946.         /* this has been the <methodName> tag */
  947.         value = octstr_create(xmlNodeListGetString(doc, node->xmlChildrenNode, 1));
  948.                 
  949.         /* destroy current msg->method_name and redefine */
  950.         octstr_destroy((*msg)->method_name);
  951.         (*msg)->method_name = octstr_duplicate(value);
  952.         octstr_destroy(value);
  953.     } else {
  954.         /* 
  955.          * ok, this has to be an <params> tag, otherwise we would 
  956.          * have returned previosly
  957.          */
  958.         if (parse_params(doc, node->xmlChildrenNode, msg) == -1)
  959.             return -1;
  960.     }
  961.     return 0;
  962. }
  963. static int parse_methodcall(xmlDocPtr doc, xmlNodePtr node, 
  964.                             XMLRPCMethodCall **msg)
  965. {
  966.     int status = 0;
  967.   
  968.     /* call for the parser function of the node type. */
  969.     switch (node->type) {
  970.         case XML_ELEMENT_NODE:
  971.             status = parse_methodcall_element(doc, node, msg);
  972.             break;
  973.         case XML_TEXT_NODE:
  974.         case XML_COMMENT_NODE:
  975.         case XML_PI_NODE:
  976.             /* Text nodes, comments and PIs are ignored. */
  977.             break;
  978.    /*
  979.     * XML has also many other node types, these are not needed with 
  980.     * XML-RPC. Therefore they are assumed to be an error.
  981.     */
  982.         default:
  983.             (*msg)->parse_status = XMLRPC_PARSING_FAILED;
  984.             (*msg)->parse_error = octstr_format("XML-RPC compiler: unknown XML node "
  985.                                                 "in the XML-RPC source.");
  986.             return -1;
  987.             break;
  988.     }
  989.     if (node->next != NULL)
  990.    if (parse_methodcall(doc, node->next, msg) == -1)
  991.             return -1;
  992.     return status;
  993. }
  994. static int parse_document(xmlDocPtr document, XMLRPCMethodCall **msg)
  995. {
  996.     xmlNodePtr node;
  997.     Octstr *name;
  998.     node = xmlDocGetRootElement(document);
  999.     /*
  1000.      * check if this is at least a valid root element
  1001.      */
  1002.     name = octstr_create(node->name);
  1003.     if (octstr_len(name) == 0) {
  1004.         octstr_destroy(name);
  1005.         return -1;
  1006.     }
  1007.     if (octstr_case_compare(name, octstr_imm("METHODCALL")) != 0) {
  1008.         (*msg)->parse_status = XMLRPC_PARSING_FAILED;
  1009.         (*msg)->parse_error = octstr_format("XML-RPC compiler: wrong root element <%s>, "
  1010.                                             "<methodCall> expected!", 
  1011.                                             octstr_get_cstr(name));
  1012.         octstr_destroy(name);
  1013.         return -1;
  1014.     }
  1015.     octstr_destroy(name);
  1016.     return parse_methodcall(document, node->xmlChildrenNode, msg);
  1017. }