Setting tag plcapi-5.3-11
[plcapi.git] / php / xmlrpc / libxmlrpc / xml_to_dandarpc.c
1 /*
2   This file is part of libXMLRPC - a C library for xml-encoded function calls.
3
4   Author: Dan Libby (dan@libby.com)
5   Epinions.com may be contacted at feedback@epinions-inc.com
6 */
7
8 /*  
9   Copyright 2000 Epinions, Inc. 
10
11   Subject to the following 3 conditions, Epinions, Inc.  permits you, free 
12   of charge, to (a) use, copy, distribute, modify, perform and display this 
13   software and associated documentation files (the "Software"), and (b) 
14   permit others to whom the Software is furnished to do so as well.  
15
16   1) The above copyright notice and this permission notice shall be included 
17   without modification in all copies or substantial portions of the 
18   Software.  
19
20   2) THE SOFTWARE IS PROVIDED "AS IS", WITHOUT ANY WARRANTY OR CONDITION OF 
21   ANY KIND, EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION ANY 
22   IMPLIED WARRANTIES OF ACCURACY, MERCHANTABILITY, FITNESS FOR A PARTICULAR 
23   PURPOSE OR NONINFRINGEMENT.  
24
25   3) IN NO EVENT SHALL EPINIONS, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, 
26   SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT 
27   OF OR IN CONNECTION WITH THE SOFTWARE (HOWEVER ARISING, INCLUDING 
28   NEGLIGENCE), EVEN IF EPINIONS, INC.  IS AWARE OF THE POSSIBILITY OF SUCH 
29   DAMAGES.    
30
31 */
32
33 #ifdef _WIN32
34 #include "xmlrpc_win32.h"
35 #endif
36 #include <string.h>
37 #include <stdlib.h>
38 #include "xml_to_dandarpc.h"
39 #include "base64.h"
40
41 /* list of tokens used in vocab */
42 #define ELEM_METHODCALL     "methodCall"
43 #define ELEM_METHODNAME     "methodName"
44 #define ELEM_METHODRESPONSE "methodResponse"
45 #define ELEM_ROOT           "simpleRPC"
46
47 #define ATTR_ARRAY          "array"
48 #define ATTR_BASE64         "base64"
49 #define ATTR_BOOLEAN        "boolean"
50 #define ATTR_DATETIME       "dateTime.iso8601"
51 #define ATTR_DOUBLE         "double"
52 #define ATTR_ID             "id"
53 #define ATTR_INT            "int"
54 #define ATTR_MIXED          "mixed"
55 #define ATTR_SCALAR         "scalar"
56 #define ATTR_STRING         "string"
57 #define ATTR_STRUCT         "struct"
58 #define ATTR_TYPE           "type"
59 #define ATTR_VECTOR         "vector"
60 #define ATTR_VERSION        "version"
61
62 #define VAL_VERSION_0_9     "0.9"
63
64
65 XMLRPC_VALUE xml_element_to_DANDARPC_REQUEST_worker(XMLRPC_REQUEST request, XMLRPC_VALUE xCurrent, xml_element* el) {
66    if(!xCurrent) {
67       xCurrent = XMLRPC_CreateValueEmpty();
68    }
69
70    if(el->name) {
71       const char* id = NULL;
72       const char* type = NULL;
73       xml_element_attr* attr_iter = Q_Head(&el->attrs);
74
75       while(attr_iter) {
76          if(!strcmp(attr_iter->key, ATTR_ID)) {
77             id = attr_iter->val;
78          }
79          if(!strcmp(attr_iter->key, ATTR_TYPE)) {
80             type = attr_iter->val;
81          }
82          attr_iter = Q_Next(&el->attrs);
83       }
84
85       if(id) {
86          XMLRPC_SetValueID_Case(xCurrent, id, 0, xmlrpc_case_exact);
87       }
88
89       if(!strcmp(el->name, ATTR_SCALAR)) {
90          if(!type || !strcmp(type, ATTR_STRING)) {
91             XMLRPC_SetValueString(xCurrent, el->text.str, el->text.len);
92          }
93          else if(!strcmp(type, ATTR_INT)) {
94             XMLRPC_SetValueInt(xCurrent, atoi(el->text.str));
95          }
96          else if(!strcmp(type, ATTR_BOOLEAN)) {
97             XMLRPC_SetValueBoolean(xCurrent, atoi(el->text.str));
98          }
99          else if(!strcmp(type, ATTR_DOUBLE)) {
100             XMLRPC_SetValueDouble(xCurrent, atof(el->text.str));
101          }
102          else if(!strcmp(type, ATTR_DATETIME)) {
103             XMLRPC_SetValueDateTime_ISO8601(xCurrent, el->text.str);
104          }
105          else if(!strcmp(type, ATTR_BASE64)) {
106             struct buffer_st buf;
107             base64_decode(&buf, el->text.str, el->text.len);
108             XMLRPC_SetValueBase64(xCurrent, buf.data, buf.offset);
109             buffer_delete(&buf);
110          }
111       }
112       else if(!strcmp(el->name, ATTR_VECTOR)) {
113          xml_element* iter = (xml_element*)Q_Head(&el->children);
114
115          if(!type || !strcmp(type, ATTR_MIXED)) {
116             XMLRPC_SetIsVector(xCurrent, xmlrpc_vector_mixed);
117          }
118          else if(!strcmp(type, ATTR_ARRAY)) {
119                                 XMLRPC_SetIsVector(xCurrent, xmlrpc_vector_array);
120          }
121          else if(!strcmp(type, ATTR_STRUCT)) {
122             XMLRPC_SetIsVector(xCurrent, xmlrpc_vector_struct);
123          }
124          while( iter ) {
125             XMLRPC_VALUE xNext = XMLRPC_CreateValueEmpty();
126             xml_element_to_DANDARPC_REQUEST_worker(request, xNext, iter);
127             XMLRPC_AddValueToVector(xCurrent, xNext);
128             iter = (xml_element*)Q_Next(&el->children);
129          }
130       }
131       else {
132          xml_element* iter = (xml_element*)Q_Head(&el->children);
133          while( iter ) {
134             xml_element_to_DANDARPC_REQUEST_worker(request, xCurrent, iter);
135             iter = (xml_element*)Q_Next(&el->children);
136          }
137
138          if(!strcmp(el->name, ELEM_METHODCALL)) {
139             if(request) {
140                XMLRPC_RequestSetRequestType(request, xmlrpc_request_call);
141             }
142          }
143          else if(!strcmp(el->name, ELEM_METHODRESPONSE)) {
144             if(request) {
145                XMLRPC_RequestSetRequestType(request, xmlrpc_request_response);
146             }
147          }
148          else if(!strcmp(el->name, ELEM_METHODNAME)) {
149             if(request) {
150                XMLRPC_RequestSetMethodName(request, el->text.str);
151             }
152          }
153       }
154    }
155    return xCurrent;
156 }
157
158 XMLRPC_VALUE xml_element_to_DANDARPC_VALUE(xml_element* el)
159 {
160    return xml_element_to_DANDARPC_REQUEST_worker(NULL, NULL, el);
161 }
162
163 XMLRPC_VALUE xml_element_to_DANDARPC_REQUEST(XMLRPC_REQUEST request, xml_element* el)
164 {
165    if(request) {
166       return XMLRPC_RequestSetData(request, xml_element_to_DANDARPC_REQUEST_worker(request, NULL, el));
167    }
168    return NULL;
169 }
170
171 xml_element* DANDARPC_to_xml_element_worker(XMLRPC_REQUEST request, XMLRPC_VALUE node) {
172 #define BUF_SIZE 512
173    xml_element* root = NULL;
174    if(node) {
175       char buf[BUF_SIZE];
176       const char* id = XMLRPC_GetValueID(node);
177       XMLRPC_VALUE_TYPE type = XMLRPC_GetValueType(node);
178       XMLRPC_REQUEST_OUTPUT_OPTIONS output = XMLRPC_RequestGetOutputOptions(request);
179       int bNoAddType = (type == xmlrpc_string && request && output && output->xml_elem_opts.verbosity == xml_elem_no_white_space);
180       xml_element* elem_val = xml_elem_new();
181       const char* pAttrType = NULL;
182
183       xml_element_attr* attr_type = bNoAddType ? NULL : malloc(sizeof(xml_element_attr));
184        
185       if(attr_type) {
186          attr_type->key = strdup(ATTR_TYPE);
187          attr_type->val = 0;
188          Q_PushTail(&elem_val->attrs, attr_type);
189       }
190
191       elem_val->name = (type == xmlrpc_vector) ? strdup(ATTR_VECTOR) : strdup(ATTR_SCALAR);
192
193       if(id && *id) {
194          xml_element_attr* attr_id = malloc(sizeof(xml_element_attr));
195          if(attr_id) {
196             attr_id->key = strdup(ATTR_ID);
197             attr_id->val = strdup(id);
198             Q_PushTail(&elem_val->attrs, attr_id);
199          }
200       }
201
202       switch(type) {
203          case xmlrpc_string:
204             pAttrType = ATTR_STRING;
205             simplestring_addn(&elem_val->text, XMLRPC_GetValueString(node), XMLRPC_GetValueStringLen(node));
206             break;
207          case xmlrpc_int:
208             pAttrType = ATTR_INT;
209             snprintf(buf, BUF_SIZE, "%i", XMLRPC_GetValueInt(node));
210             simplestring_add(&elem_val->text, buf);
211             break;
212          case xmlrpc_boolean:
213             pAttrType = ATTR_BOOLEAN;
214             snprintf(buf, BUF_SIZE, "%i", XMLRPC_GetValueBoolean(node));
215             simplestring_add(&elem_val->text, buf);
216             break;
217          case xmlrpc_double:
218             pAttrType = ATTR_DOUBLE;
219             snprintf(buf, BUF_SIZE, "%f", XMLRPC_GetValueDouble(node));
220             simplestring_add(&elem_val->text, buf);
221             break;
222          case xmlrpc_datetime:
223             pAttrType = ATTR_DATETIME;
224             simplestring_add(&elem_val->text, XMLRPC_GetValueDateTime_ISO8601(node));
225             break;
226          case xmlrpc_base64:
227             {
228                struct buffer_st buf;
229                pAttrType = ATTR_BASE64;
230                base64_encode(&buf, XMLRPC_GetValueBase64(node), XMLRPC_GetValueStringLen(node));
231                simplestring_addn(&elem_val->text, buf.data, buf.offset );
232                buffer_delete(&buf);
233             }
234             break;
235          case xmlrpc_vector:
236             {
237                XMLRPC_VECTOR_TYPE my_type = XMLRPC_GetVectorType(node);
238                XMLRPC_VALUE xIter = XMLRPC_VectorRewind(node);
239
240                switch(my_type) {
241                   case xmlrpc_vector_array:
242                      pAttrType = ATTR_ARRAY;
243                      break;
244                   case xmlrpc_vector_mixed:
245                      pAttrType = ATTR_MIXED;
246                      break;
247                   case xmlrpc_vector_struct:
248                      pAttrType = ATTR_STRUCT;
249                      break;
250                   default:
251                      break;
252                }
253
254                /* recurse through sub-elements */
255                while( xIter ) {
256                   xml_element* next_el = DANDARPC_to_xml_element_worker(request, xIter);
257                   if(next_el) {
258                      Q_PushTail(&elem_val->children, next_el);
259                   }
260                   xIter = XMLRPC_VectorNext(node);
261                }
262             }
263             break;
264          default:
265             break;
266       }
267       if(pAttrType && attr_type && !bNoAddType) {
268          attr_type->val = strdup(pAttrType);
269       }
270       root = elem_val;
271    }
272    return root;
273 }
274
275 xml_element* DANDARPC_VALUE_to_xml_element(XMLRPC_VALUE node) {
276    return DANDARPC_to_xml_element_worker(NULL, node);
277 }
278
279 xml_element* DANDARPC_REQUEST_to_xml_element(XMLRPC_REQUEST request) {
280    xml_element* wrapper = NULL;
281    xml_element* root = NULL;
282    if(request) {
283       XMLRPC_REQUEST_TYPE request_type = XMLRPC_RequestGetRequestType(request);
284       const char* pStr = NULL;
285       xml_element_attr* version = malloc(sizeof(xml_element_attr));
286       version->key = strdup(ATTR_VERSION);
287       version->val = strdup(VAL_VERSION_0_9);
288       
289       wrapper = xml_elem_new();
290
291       if(request_type == xmlrpc_request_response) {
292          pStr = ELEM_METHODRESPONSE;
293       }
294       else if(request_type == xmlrpc_request_call) {
295          pStr = ELEM_METHODCALL;
296       }
297       if(pStr) {
298          wrapper->name = strdup(pStr);
299       }
300
301       root = xml_elem_new();
302       root->name = strdup(ELEM_ROOT);
303       Q_PushTail(&root->attrs, version);
304       Q_PushTail(&root->children, wrapper);
305
306       pStr = XMLRPC_RequestGetMethodName(request);
307
308       if(pStr) {
309          xml_element* method = xml_elem_new();
310          method->name = strdup(ELEM_METHODNAME);
311          simplestring_add(&method->text, pStr);
312          Q_PushTail(&wrapper->children, method);
313       }
314       Q_PushTail(&wrapper->children, 
315                  DANDARPC_to_xml_element_worker(request, XMLRPC_RequestGetData(request)));
316    }
317    return root;
318 }
319