📄 xmlrpc.c
字号:
/* ==================================================================== * The Kannel Software License, Version 1.0 * * Copyright (c) 2001-2004 Kannel Group * Copyright (c) 1998-2001 WapIT Ltd. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Kannel Group (http://www.kannel.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Kannel" and "Kannel Group" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please * contact org@kannel.org. * * 5. Products derived from this software may not be called "Kannel", * nor may "Kannel" appear in their name, without prior written * permission of the Kannel Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Kannel Group. For more information on * the Kannel Group, please see <http://www.kannel.org/>. * * Portions of this software are based upon software originally written at * WapIT Ltd., Helsinki, Finland for the Kannel project. */ /* * gwlib/xmlrpc.c: functions to handle XML-RPC structure - building and parsing * * XML-RPC is HTTP-based XML defination to handle remote procedure calls, * and is defined at http://www.xml-rpc.org * * Kalle Marjola 2001 for project Kannel * Stipe Tolj <tolj@wapme-systems.de> * Robert Ga砤ch <robert.galach@my.tenbit.pl> */ #include <libxml/xmlmemory.h>#include <libxml/tree.h>#include <libxml/debugXML.h>#include <libxml/encoding.h>#include "gwlib/gwlib.h"#include "gwlib/xmlrpc.h"#define XR_ENABLE_EMPTY_STRING_VALUES#define OPTIMAL_STRUCT_SIZE 7typedef struct xmlrpc_methodresponse XMLRPCMethodResponse;typedef struct xmlrpc_member XMLRPCMember;typedef struct xmlrpc_methodcall XMLRPCMethodCall;typedef struct xmlrpc_fault XMLRPCFault;typedef struct xmlrpc_table_t xmlrpc_table_t;typedef struct xmlrpc_2table_t xmlrpc_2table_t;struct xmlrpc_methodcall { Octstr *method_name; List *params; /* List of XMLRPCValues */};struct xmlrpc_methodresponse { XMLRPCValue *param; /* Param value */ XMLRPCFault *fault; /* ..or this */};struct xmlrpc_fault { long f_code; /* Fault code */ Octstr *f_string; /* and description */};struct xmlrpc_document { int d_type; /* enum here */ int parse_status; /* enum here */ Octstr *parse_error; /* error string in case of parsing error */ XMLRPCMethodCall *methodcall; XMLRPCMethodResponse *methodresponse;};struct xmlrpc_value { int v_type; /* enum here */ XMLRPCScalar *v_scalar; List *v_array; /* List of XMLRPCValues */ Dict *v_struct; /* Dict of XMLRPCValues */};struct xmlrpc_member { /* member of struct */ Octstr *name; XMLRPCValue *value;};struct xmlrpc_scalar { int s_type; /* enum here */ Octstr *s_str; long s_int; int s_bool; double s_double; Octstr *s_date; Octstr *s_base64;};struct xmlrpc_table_t { char *name;};struct xmlrpc_2table_t { char *name; int s_type; /* enum here */};static xmlrpc_table_t methodcall_elements[] = { { "METHODNAME" }, { "PARAMS" }};static xmlrpc_table_t methodresponse_elements[] = { { "FAULT" }, { "PARAMS" }};static xmlrpc_table_t params_elements[] = { { "PARAM" }};static xmlrpc_table_t param_elements[] = { { "VALUE" }};static xmlrpc_2table_t value_elements[] = { { "I4", xr_int }, { "INT", xr_int }, { "BOOLEAN", xr_bool }, { "STRING", xr_string }, { "DOUBLE", xr_double }, { "DATETIME.ISO8601", xr_date }, { "BASE64", xr_base64 }, { "STRUCT", xr_struct }, { "ARRAY", xr_array }};static xmlrpc_table_t struct_elements[] = { { "MEMBER" }};static xmlrpc_table_t member_elements[] = { { "NAME" }, { "VALUE" }};static xmlrpc_table_t array_elements[] = { { "DATA" }};static xmlrpc_table_t data_elements[] = { { "VALUE" }};static xmlrpc_table_t fault_elements[] = { { "VALUE" }};#define NUMBER_OF_METHODCALL_ELEMENTS \ sizeof(methodcall_elements)/sizeof(methodcall_elements[0])#define NUMBER_OF_METHODRESPONSE_ELEMENTS \ sizeof(methodresponse_elements)/sizeof(methodresponse_elements[0])#define NUMBER_OF_PARAMS_ELEMENTS \ sizeof(params_elements)/sizeof(params_elements[0])#define NUMBER_OF_PARAM_ELEMENTS \ sizeof(param_elements)/sizeof(param_elements[0])#define NUMBER_OF_VALUE_ELEMENTS \ sizeof(value_elements)/sizeof(value_elements[0])#define NUMBER_OF_STRUCT_ELEMENTS \ sizeof(struct_elements)/sizeof(struct_elements[0])#define NUMBER_OF_MEMBER_ELEMENTS \ sizeof(member_elements)/sizeof(member_elements[0])#define NUMBER_OF_ARRAY_ELEMENTS \ sizeof(array_elements)/sizeof(array_elements[0])#define NUMBER_OF_DATA_ELEMENTS \ sizeof(data_elements)/sizeof(data_elements[0])#define NUMBER_OF_FAULT_ELEMENTS \ sizeof(fault_elements)/sizeof(fault_elements[0])/* -------------------------------------- * internal parser function declarations */ static int parse_document(xmlDocPtr document, XMLRPCDocument *xrdoc);static int parse_methodcall(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc, XMLRPCMethodCall *methodcall);static int parse_methodcall_element(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc, XMLRPCMethodCall *methodcall);static int parse_methodresponse(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc, XMLRPCMethodResponse *methodresponse, int* n);static int parse_methodresponse_element(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc, XMLRPCMethodResponse *methodresponse);static int parse_params(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc, List *params);static int parse_params_element(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc, List *params);static int parse_param(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc, List *params, int *n);static int parse_param_element(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc, List *params);static int parse_value(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc, XMLRPCValue *value);static int parse_value_element(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc, XMLRPCValue *xrvalue);static int parse_struct(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc, Dict *members);static int parse_struct_element(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc, Dict *members);static int parse_member(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc, XMLRPCMember *member);static int parse_member_element(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc, XMLRPCMember *member);static int parse_array(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc, List *elements);static int parse_array_element(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc, List *elements);static int parse_data(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc, List *elements);static int parse_data_element(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc, List *elements);static int parse_fault(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc, XMLRPCFault *fault);static int parse_fault_element(xmlDocPtr doc, xmlNodePtr node, XMLRPCDocument *xrdoc, XMLRPCFault *fault);/*------------------------------------- * MethodCall */static XMLRPCMethodCall *xmlrpc_call_create(Octstr *name){ XMLRPCMethodCall *nmsg = gw_malloc(sizeof(XMLRPCMethodCall)); nmsg->method_name = octstr_duplicate(name); nmsg->params = list_create(); return nmsg;}static void xmlrpc_call_destroy(XMLRPCMethodCall *call){ if (call == NULL) return; octstr_destroy(call->method_name); list_destroy(call->params, xmlrpc_value_destroy_item); gw_free(call);}static Octstr *xmlrpc_call_get_name(XMLRPCMethodCall *call){ return call->method_name;}static int xmlrpc_call_add_param(XMLRPCMethodCall *method, XMLRPCValue *value){ if (method == NULL || value == NULL) return -1; list_produce(method->params, value); return 0;}static Octstr *xmlrpc_call_print(XMLRPCMethodCall *call, int level){ Octstr *body, *os_value; XMLRPCValue *val; long i; if (call == NULL || call->method_name == NULL) return NULL; body = octstr_format("%*s<methodCall>\n" "%*s<methodName>%S</methodName>\n", level, "", level + 2, "", call->method_name); list_lock(call->params); if (list_len(call->params) > 0) { octstr_format_append(body, "%*s<params>\n", level + 2, ""); for (i = 0; i < list_len(call->params); i++) { val = list_get(call->params, i); os_value = xmlrpc_value_print(val, level + 6); if (os_value == NULL) { error(0, "XMLRPC: Could not print method call, param %ld malformed", i); octstr_destroy(body); return NULL; } octstr_format_append(body, "%*s<param>\n%S%*s</param>\n", level + 4, "", os_value, level + 4, ""); octstr_destroy(os_value); } octstr_format_append(body, "%*s</params>\n", level + 2, ""); } list_unlock(call->params); octstr_format_append(body, "%*s</methodCall>\n", level, ""); return body;}/*------------------------------------- * XMLRPCFault */static XMLRPCFault *xmlrpc_fault_create(long fcode, Octstr *fstring){ XMLRPCFault *fault = gw_malloc(sizeof(XMLRPCFault)); fault->f_code = fcode; fault->f_string = octstr_duplicate(fstring); return fault;}static void xmlrpc_fault_destroy(XMLRPCFault *fault){ if (fault == NULL) return; octstr_destroy(fault->f_string); gw_free(fault);}static long xmlrpc_fault_get_code(XMLRPCFault *fault){ if (fault == NULL) return -1; return fault->f_code;}static Octstr *xmlrpc_fault_get_string(XMLRPCFault *fault){ if (fault == NULL) return NULL; return fault->f_string;}static Octstr *xmlrpc_fault_print(XMLRPCFault *fault, int level){ Octstr *os; if (fault == NULL) return NULL; os = octstr_format("%*s<fault>\n%*s<value>\n" "%*s<struct>\n" "%*s<member>\n" "%*s<name>faultCode</name>\n" "%*s<value><int>%ld</int></value>\n" "%*s</member>\n" "%*s<member>\n" "%*s<name>faultString</name>\n" "%*s<value><string>%S</string></value>\n" "%*s</member>\n" "%*s</struct>\n" "%*s</value>\n%*s</fault>\n", level, "", level+2, "", level+4, "", level+6, "", level+8, "", level+8, "", fault->f_code, level+6, "", level+6, "", level+8, "", level+8, "", (fault->f_string == NULL ? octstr_imm("/") : fault->f_string), level+6, "", level+4, "", level+2, "", level, ""); return os;}/*------------------------------------- * MethodResponse */static XMLRPCMethodResponse *xmlrpc_response_create(void){ XMLRPCMethodResponse *nmsg = gw_malloc(sizeof(XMLRPCMethodResponse)); nmsg->param = NULL; nmsg->fault = NULL; return nmsg;}static void xmlrpc_response_destroy(XMLRPCMethodResponse *response){ if (response == NULL) return; xmlrpc_value_destroy(response->param); xmlrpc_fault_destroy(response->fault); gw_free(response);}static int xmlrpc_response_add_param(XMLRPCMethodResponse *response, XMLRPCValue *value){ if (response == NULL || value == NULL) return -1; if (response->param != NULL) { error(0, "XMLRPC: Method Response may contain only one param."); return -1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -