This source file includes following definitions.
- ZEND_GET_MODULE
- destroy_server_data
- xmlrpc_server_destructor
- PHP_MINIT_FUNCTION
- PHP_MINFO_FUNCTION
- add_long
- add_double
- add_string
- add_stringl
- add_zval
- set_output_options
- determine_vector_type
- PHP_to_XMLRPC_worker
- PHP_to_XMLRPC
- XMLRPC_to_PHP
- PHP_FUNCTION
- PHP_FUNCTION
- decode_request_worker
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- php_xmlrpc_callback
- php_xmlrpc_introspection_callback
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- get_type_str_mapping
- xmlrpc_type_as_str
- xmlrpc_str_as_type
- xmlrpc_str_as_vector_type
- set_zval_xmlrpc_type
- get_zval_xmlrpc_type
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64 #ifdef HAVE_CONFIG_H
65 #include "config.h"
66 #endif
67
68 #include "php.h"
69 #include "ext/standard/info.h"
70 #include "ext/standard/php_string.h"
71 #include "ext/date/php_date.h"
72 #include "php_ini.h"
73 #include "php_xmlrpc.h"
74 #include "xmlrpc.h"
75
76 #define PHP_EXT_VERSION "0.51"
77
78 static int le_xmlrpc_server;
79
80
81 ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlrpc_encode, 0, 0, 1)
82 ZEND_ARG_INFO(0, value)
83 ZEND_END_ARG_INFO()
84
85 ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlrpc_decode, 0, 0, 1)
86 ZEND_ARG_INFO(0, value)
87 ZEND_ARG_INFO(0, encoding)
88 ZEND_END_ARG_INFO()
89
90 ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlrpc_decode_request, 0, 0, 2)
91 ZEND_ARG_INFO(0, xml)
92 ZEND_ARG_INFO(1, method)
93 ZEND_ARG_INFO(0, encoding)
94 ZEND_END_ARG_INFO()
95
96 ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlrpc_encode_request, 0, 0, 2)
97 ZEND_ARG_INFO(0, method)
98 ZEND_ARG_INFO(0, params)
99 ZEND_ARG_INFO(0, output_options)
100 ZEND_END_ARG_INFO()
101
102 ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlrpc_set_type, 0, 0, 2)
103 ZEND_ARG_INFO(1, value)
104 ZEND_ARG_INFO(0, type)
105 ZEND_END_ARG_INFO()
106
107 ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlrpc_is_fault, 0, 0, 1)
108 ZEND_ARG_INFO(0, arg)
109 ZEND_END_ARG_INFO()
110
111 ZEND_BEGIN_ARG_INFO(arginfo_xmlrpc_server_create, 0)
112 ZEND_END_ARG_INFO()
113
114 ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlrpc_server_destroy, 0, 0, 1)
115 ZEND_ARG_INFO(0, server)
116 ZEND_END_ARG_INFO()
117
118 ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlrpc_server_register_method, 0, 0, 3)
119 ZEND_ARG_INFO(0, server)
120 ZEND_ARG_INFO(0, method_name)
121 ZEND_ARG_INFO(0, function)
122 ZEND_END_ARG_INFO()
123
124 ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlrpc_server_call_method, 0, 0, 3)
125 ZEND_ARG_INFO(0, server)
126 ZEND_ARG_INFO(0, xml)
127 ZEND_ARG_INFO(0, user_data)
128 ZEND_ARG_INFO(0, output_options)
129 ZEND_END_ARG_INFO()
130
131 ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlrpc_parse_method_descriptions, 0, 0, 1)
132 ZEND_ARG_INFO(0, xml)
133 ZEND_END_ARG_INFO()
134
135 ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlrpc_server_add_introspection_data, 0, 0, 2)
136 ZEND_ARG_INFO(0, server)
137 ZEND_ARG_INFO(0, desc)
138 ZEND_END_ARG_INFO()
139
140 ZEND_BEGIN_ARG_INFO_EX(arginfo_xmlrpc_server_register_introspection_callback, 0, 0, 2)
141 ZEND_ARG_INFO(0, server)
142 ZEND_ARG_INFO(0, function)
143 ZEND_END_ARG_INFO()
144
145
146 const zend_function_entry xmlrpc_functions[] = {
147 PHP_FE(xmlrpc_encode, arginfo_xmlrpc_encode)
148 PHP_FE(xmlrpc_decode, arginfo_xmlrpc_decode)
149 PHP_FE(xmlrpc_decode_request, arginfo_xmlrpc_decode_request)
150 PHP_FE(xmlrpc_encode_request, arginfo_xmlrpc_encode_request)
151 PHP_FE(xmlrpc_get_type, arginfo_xmlrpc_encode)
152 PHP_FE(xmlrpc_set_type, arginfo_xmlrpc_set_type)
153 PHP_FE(xmlrpc_is_fault, arginfo_xmlrpc_is_fault)
154 PHP_FE(xmlrpc_server_create, arginfo_xmlrpc_server_create)
155 PHP_FE(xmlrpc_server_destroy, arginfo_xmlrpc_server_destroy)
156 PHP_FE(xmlrpc_server_register_method, arginfo_xmlrpc_server_register_method)
157 PHP_FE(xmlrpc_server_call_method, arginfo_xmlrpc_server_call_method)
158 PHP_FE(xmlrpc_parse_method_descriptions, arginfo_xmlrpc_parse_method_descriptions)
159 PHP_FE(xmlrpc_server_add_introspection_data, arginfo_xmlrpc_server_add_introspection_data)
160 PHP_FE(xmlrpc_server_register_introspection_callback, arginfo_xmlrpc_server_register_introspection_callback)
161 PHP_FE_END
162 };
163
164 zend_module_entry xmlrpc_module_entry = {
165 STANDARD_MODULE_HEADER,
166 "xmlrpc",
167 xmlrpc_functions,
168 PHP_MINIT(xmlrpc),
169 NULL,
170 NULL,
171 NULL,
172 PHP_MINFO(xmlrpc),
173 PHP_EXT_VERSION,
174 STANDARD_MODULE_PROPERTIES
175 };
176
177 #ifdef COMPILE_DL_XMLRPC
178 ZEND_GET_MODULE(xmlrpc)
179 #endif
180
181
182
183
184
185
186 typedef struct _xmlrpc_server_data {
187 zval* method_map;
188 zval* introspection_map;
189 XMLRPC_SERVER server_ptr;
190 } xmlrpc_server_data;
191
192
193
194 typedef struct _php_output_options {
195 int b_php_out;
196 int b_auto_version;
197 STRUCT_XMLRPC_REQUEST_OUTPUT_OPTIONS xmlrpc_out;
198 } php_output_options;
199
200
201 typedef struct _xmlrpc_callback_data {
202 zval* xmlrpc_method;
203 zval* php_function;
204 zval* caller_params;
205 zval* return_data;
206 xmlrpc_server_data* server;
207 char php_executed;
208 } xmlrpc_callback_data;
209
210
211 #define OUTPUT_TYPE_KEY "output_type"
212 #define OUTPUT_TYPE_KEY_LEN (sizeof(OUTPUT_TYPE_KEY) - 1)
213 #define OUTPUT_TYPE_VALUE_PHP "php"
214 #define OUTPUT_TYPE_VALUE_XML "xml"
215
216 #define VERBOSITY_KEY "verbosity"
217 #define VERBOSITY_KEY_LEN (sizeof(VERBOSITY_KEY) - 1)
218 #define VERBOSITY_VALUE_NO_WHITE_SPACE "no_white_space"
219 #define VERBOSITY_VALUE_NEWLINES_ONLY "newlines_only"
220 #define VERBOSITY_VALUE_PRETTY "pretty"
221
222 #define ESCAPING_KEY "escaping"
223 #define ESCAPING_KEY_LEN (sizeof(ESCAPING_KEY) - 1)
224 #define ESCAPING_VALUE_CDATA "cdata"
225 #define ESCAPING_VALUE_NON_ASCII "non-ascii"
226 #define ESCAPING_VALUE_NON_PRINT "non-print"
227 #define ESCAPING_VALUE_MARKUP "markup"
228
229 #define VERSION_KEY "version"
230 #define VERSION_KEY_LEN (sizeof(VERSION_KEY) - 1)
231 #define VERSION_VALUE_SIMPLE "simple"
232 #define VERSION_VALUE_XMLRPC "xmlrpc"
233 #define VERSION_VALUE_SOAP11 "soap 1.1"
234 #define VERSION_VALUE_AUTO "auto"
235
236 #define ENCODING_KEY "encoding"
237 #define ENCODING_KEY_LEN (sizeof(ENCODING_KEY) - 1)
238 #define ENCODING_DEFAULT "iso-8859-1"
239
240
241 #define OBJECT_TYPE_ATTR "xmlrpc_type"
242 #define OBJECT_VALUE_ATTR "scalar"
243 #define OBJECT_VALUE_TS_ATTR "timestamp"
244
245
246 #define FAULT_CODE "faultCode"
247 #define FAULT_CODE_LEN (sizeof(FAULT_CODE) - 1)
248 #define FAULT_STRING "faultString"
249 #define FAULT_STRING_LEN (sizeof(FAULT_STRING) - 1)
250
251
252
253
254 XMLRPC_VALUE_TYPE get_zval_xmlrpc_type(zval* value, zval** newvalue);
255 static void php_xmlrpc_introspection_callback(XMLRPC_SERVER server, void* data);
256 int sset_zval_xmlrpc_type(zval* value, XMLRPC_VALUE_TYPE type);
257 zval* decode_request_worker(char *xml_in, int xml_in_len, char *encoding_in, zval* method_name_out);
258 const char* xmlrpc_type_as_str(XMLRPC_VALUE_TYPE type, XMLRPC_VECTOR_TYPE vtype);
259 XMLRPC_VALUE_TYPE xmlrpc_str_as_type(const char* str);
260 XMLRPC_VECTOR_TYPE xmlrpc_str_as_vector_type(const char* str);
261 int set_zval_xmlrpc_type(zval* value, XMLRPC_VALUE_TYPE type);
262
263
264
265
266
267 static void destroy_server_data(xmlrpc_server_data *server TSRMLS_DC)
268 {
269 if (server) {
270 XMLRPC_ServerDestroy(server->server_ptr);
271
272 zval_dtor(server->method_map);
273 FREE_ZVAL(server->method_map);
274
275 zval_dtor(server->introspection_map);
276 FREE_ZVAL(server->introspection_map);
277
278 efree(server);
279 }
280 }
281
282
283
284 static void xmlrpc_server_destructor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
285 {
286 if (rsrc && rsrc->ptr) {
287 destroy_server_data((xmlrpc_server_data*) rsrc->ptr TSRMLS_CC);
288 }
289 }
290
291
292 PHP_MINIT_FUNCTION(xmlrpc)
293 {
294 le_xmlrpc_server = zend_register_list_destructors_ex(xmlrpc_server_destructor, NULL, "xmlrpc server", module_number);
295
296 return SUCCESS;
297 }
298
299
300 PHP_MINFO_FUNCTION(xmlrpc)
301 {
302 php_info_print_table_start();
303 php_info_print_table_row(2, "core library version", XMLRPC_GetVersionString());
304 php_info_print_table_row(2, "php extension version", PHP_EXT_VERSION);
305 php_info_print_table_row(2, "author", "Dan Libby");
306 php_info_print_table_row(2, "homepage", "http://xmlrpc-epi.sourceforge.net");
307 php_info_print_table_row(2, "open sourced by", "Epinions.com");
308 php_info_print_table_end();
309 }
310
311
312
313
314
315
316
317
318 #if 0
319 static int add_long(zval* list, char* id, int num) {
320 if(id) return add_assoc_long(list, id, num);
321 else return add_next_index_long(list, num);
322 }
323
324 static int add_double(zval* list, char* id, double num) {
325 if(id) return add_assoc_double(list, id, num);
326 else return add_next_index_double(list, num);
327 }
328
329 static int add_string(zval* list, char* id, char* string, int duplicate) {
330 if(id) return add_assoc_string(list, id, string, duplicate);
331 else return add_next_index_string(list, string, duplicate);
332 }
333
334 static int add_stringl(zval* list, char* id, char* string, uint length, int duplicate) {
335 if(id) return add_assoc_stringl(list, id, string, length, duplicate);
336 else return add_next_index_stringl(list, string, length, duplicate);
337 }
338
339 #endif
340
341 static int add_zval(zval* list, const char* id, zval** val)
342 {
343 if (list && val) {
344 if (id) {
345 int id_len = strlen(id);
346 if (!(id_len > 1 && id[0] == '0') && is_numeric_string((char *)id, id_len, NULL, NULL, 0) == IS_LONG) {
347 long index = strtol(id, NULL, 0);
348 return zend_hash_index_update(Z_ARRVAL_P(list), index, (void *) val, sizeof(zval **), NULL);
349 } else {
350 return zend_hash_update(Z_ARRVAL_P(list), (char*) id, strlen(id) + 1, (void *) val, sizeof(zval **), NULL);
351 }
352 } else {
353 return zend_hash_next_index_insert(Z_ARRVAL_P(list), (void *) val, sizeof(zval **), NULL);
354 }
355 }
356
357 return 0;
358 }
359
360 #define my_zend_hash_get_current_key(ht, my_key, num_index) zend_hash_get_current_key(ht, my_key, num_index, 0)
361
362
363
364
365
366
367
368
369 static void set_output_options(php_output_options* options, zval* output_opts)
370 {
371 if (options) {
372
373
374 options->b_php_out = 0;
375 options->b_auto_version = 1;
376 options->xmlrpc_out.version = xmlrpc_version_1_0;
377 options->xmlrpc_out.xml_elem_opts.encoding = ENCODING_DEFAULT;
378 options->xmlrpc_out.xml_elem_opts.verbosity = xml_elem_pretty;
379 options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_markup_escaping | xml_elem_non_ascii_escaping | xml_elem_non_print_escaping;
380
381 if (output_opts && Z_TYPE_P(output_opts) == IS_ARRAY) {
382 zval** val;
383
384
385 if (zend_hash_find(Z_ARRVAL_P(output_opts), OUTPUT_TYPE_KEY, OUTPUT_TYPE_KEY_LEN + 1, (void**) &val) == SUCCESS) {
386 if (Z_TYPE_PP(val) == IS_STRING) {
387 if (!strcmp(Z_STRVAL_PP(val), OUTPUT_TYPE_VALUE_PHP)) {
388 options->b_php_out = 1;
389 } else if (!strcmp(Z_STRVAL_PP(val), OUTPUT_TYPE_VALUE_XML)) {
390 options->b_php_out = 0;
391 }
392 }
393 }
394
395
396 if (zend_hash_find(Z_ARRVAL_P(output_opts), VERBOSITY_KEY, VERBOSITY_KEY_LEN + 1, (void**) &val) == SUCCESS) {
397 if (Z_TYPE_PP(val) == IS_STRING) {
398 if (!strcmp(Z_STRVAL_PP(val), VERBOSITY_VALUE_NO_WHITE_SPACE)) {
399 options->xmlrpc_out.xml_elem_opts.verbosity = xml_elem_no_white_space;
400 } else if (!strcmp(Z_STRVAL_PP(val), VERBOSITY_VALUE_NEWLINES_ONLY)) {
401 options->xmlrpc_out.xml_elem_opts.verbosity = xml_elem_newlines_only;
402 } else if (!strcmp(Z_STRVAL_PP(val), VERBOSITY_VALUE_PRETTY)) {
403 options->xmlrpc_out.xml_elem_opts.verbosity = xml_elem_pretty;
404 }
405 }
406 }
407
408
409 if (zend_hash_find(Z_ARRVAL_P(output_opts), VERSION_KEY, VERSION_KEY_LEN + 1, (void**) &val) == SUCCESS) {
410 if (Z_TYPE_PP(val) == IS_STRING) {
411 options->b_auto_version = 0;
412 if (!strcmp(Z_STRVAL_PP(val), VERSION_VALUE_XMLRPC)) {
413 options->xmlrpc_out.version = xmlrpc_version_1_0;
414 } else if (!strcmp(Z_STRVAL_PP(val), VERSION_VALUE_SIMPLE)) {
415 options->xmlrpc_out.version = xmlrpc_version_simple;
416 } else if (!strcmp((*val)->value.str.val, VERSION_VALUE_SOAP11)) {
417 options->xmlrpc_out.version = xmlrpc_version_soap_1_1;
418 } else {
419 options->b_auto_version = 1;
420 }
421 }
422 }
423
424
425 if (zend_hash_find(Z_ARRVAL_P(output_opts), ENCODING_KEY, ENCODING_KEY_LEN + 1, (void**)&val) == SUCCESS) {
426 if (Z_TYPE_PP(val) == IS_STRING) {
427 options->xmlrpc_out.xml_elem_opts.encoding = estrdup(Z_STRVAL_PP(val));
428 }
429 }
430
431
432 if (zend_hash_find(Z_ARRVAL_P(output_opts), ESCAPING_KEY, ESCAPING_KEY_LEN + 1, (void**)&val) == SUCCESS) {
433
434 if (Z_TYPE_PP(val) == IS_ARRAY) {
435 zval** iter_val;
436
437 zend_hash_internal_pointer_reset(Z_ARRVAL_PP(val));
438 options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_no_escaping;
439
440 while (1) {
441 if (zend_hash_get_current_data(Z_ARRVAL_PP(val), (void**)&iter_val) == SUCCESS) {
442 if (Z_TYPE_PP(iter_val) == IS_STRING && Z_STRVAL_PP(iter_val)) {
443 if (!strcmp(Z_STRVAL_PP(iter_val), ESCAPING_VALUE_CDATA)) {
444 options->xmlrpc_out.xml_elem_opts.escaping |= xml_elem_cdata_escaping;
445 } else if (!strcmp(Z_STRVAL_PP(iter_val), ESCAPING_VALUE_NON_ASCII)) {
446 options->xmlrpc_out.xml_elem_opts.escaping |= xml_elem_non_ascii_escaping;
447 } else if (!strcmp(Z_STRVAL_PP(iter_val), ESCAPING_VALUE_NON_PRINT)) {
448 options->xmlrpc_out.xml_elem_opts.escaping |= xml_elem_non_print_escaping;
449 } else if (!strcmp(Z_STRVAL_PP(iter_val), ESCAPING_VALUE_MARKUP)) {
450 options->xmlrpc_out.xml_elem_opts.escaping |= xml_elem_markup_escaping;
451 }
452 }
453 } else {
454 break;
455 }
456 zend_hash_move_forward(Z_ARRVAL_PP(val));
457 }
458
459 } else if (Z_TYPE_PP(val) == IS_STRING) {
460 if (!strcmp(Z_STRVAL_PP(val), ESCAPING_VALUE_CDATA)) {
461 options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_cdata_escaping;
462 } else if (!strcmp(Z_STRVAL_PP(val), ESCAPING_VALUE_NON_ASCII)) {
463 options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_non_ascii_escaping;
464 } else if (!strcmp(Z_STRVAL_PP(val), ESCAPING_VALUE_NON_PRINT)) {
465 options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_non_print_escaping;
466 } else if (!strcmp(Z_STRVAL_PP(val), ESCAPING_VALUE_MARKUP)) {
467 options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_markup_escaping;
468 }
469 }
470 }
471 }
472 }
473 }
474
475
476
477
478
479
480
481
482
483
484
485 static XMLRPC_VECTOR_TYPE determine_vector_type (HashTable *ht)
486 {
487 int bArray = 0, bStruct = 0, bMixed = 0;
488 unsigned long num_index, last_num = 0;
489 char* my_key;
490
491 zend_hash_internal_pointer_reset(ht);
492 while (1) {
493 int res = my_zend_hash_get_current_key(ht, &my_key, &num_index);
494
495 if (res == HASH_KEY_IS_LONG) {
496 if (bStruct) {
497 bMixed = 1;
498 break;
499 } else if (last_num > 0 && last_num != num_index-1) {
500 bStruct = 1;
501 break;
502 }
503 bArray = 1;
504 last_num = num_index;
505 } else if (res == HASH_KEY_NON_EXISTENT) {
506 break;
507 } else if (res == HASH_KEY_IS_STRING) {
508 if (bArray) {
509 bMixed = 1;
510 break;
511 }
512 bStruct = 1;
513 }
514 zend_hash_move_forward(ht);
515 }
516 return bMixed ? xmlrpc_vector_mixed : (bStruct ? xmlrpc_vector_struct : xmlrpc_vector_array);
517 }
518
519
520 static XMLRPC_VALUE PHP_to_XMLRPC_worker (const char* key, zval* in_val, int depth TSRMLS_DC)
521 {
522 XMLRPC_VALUE xReturn = NULL;
523
524 if (in_val) {
525 zval* val = NULL;
526 XMLRPC_VALUE_TYPE type = get_zval_xmlrpc_type(in_val, &val);
527
528 if (val) {
529 switch (type) {
530 case xmlrpc_base64:
531 if (Z_TYPE_P(val) == IS_NULL) {
532 xReturn = XMLRPC_CreateValueEmpty();
533 XMLRPC_SetValueID(xReturn, key, 0);
534 } else {
535 if (Z_TYPE_P(val) != IS_STRING) {
536 zval *newvalue;
537 ALLOC_INIT_ZVAL(newvalue);
538 MAKE_COPY_ZVAL(&val, newvalue);
539 convert_to_string(newvalue);
540 xReturn = XMLRPC_CreateValueBase64(key, Z_STRVAL_P(newvalue), Z_STRLEN_P(newvalue));
541 zval_ptr_dtor(&newvalue);
542 } else {
543 xReturn = XMLRPC_CreateValueBase64(key, Z_STRVAL_P(val), Z_STRLEN_P(val));
544 }
545 }
546 break;
547 case xmlrpc_datetime:
548 convert_to_string(val);
549 xReturn = XMLRPC_CreateValueDateTime_ISO8601(key, Z_STRVAL_P(val));
550 break;
551 case xmlrpc_boolean:
552 convert_to_boolean(val);
553 xReturn = XMLRPC_CreateValueBoolean(key, Z_LVAL_P(val));
554 break;
555 case xmlrpc_int:
556 convert_to_long(val);
557 xReturn = XMLRPC_CreateValueInt(key, Z_LVAL_P(val));
558 break;
559 case xmlrpc_double:
560 convert_to_double(val);
561 xReturn = XMLRPC_CreateValueDouble(key, Z_DVAL_P(val));
562 break;
563 case xmlrpc_string:
564 convert_to_string(val);
565 xReturn = XMLRPC_CreateValueString(key, Z_STRVAL_P(val), Z_STRLEN_P(val));
566 break;
567 case xmlrpc_vector:
568 {
569 unsigned long num_index;
570 zval** pIter;
571 char* my_key;
572 HashTable *ht = NULL;
573 zval *val_arr;
574 XMLRPC_VECTOR_TYPE vtype;
575
576 ht = HASH_OF(val);
577 if (ht && ht->nApplyCount > 1) {
578 php_error_docref(NULL TSRMLS_CC, E_ERROR, "XML-RPC doesn't support circular references");
579 return NULL;
580 }
581
582 MAKE_STD_ZVAL(val_arr);
583 MAKE_COPY_ZVAL(&val, val_arr);
584 convert_to_array(val_arr);
585
586 vtype = determine_vector_type(Z_ARRVAL_P(val_arr));
587 xReturn = XMLRPC_CreateVector(key, vtype);
588
589 zend_hash_internal_pointer_reset(Z_ARRVAL_P(val_arr));
590 while(zend_hash_get_current_data(Z_ARRVAL_P(val_arr), (void**)&pIter) == SUCCESS) {
591 int res = my_zend_hash_get_current_key(Z_ARRVAL_P(val_arr), &my_key, &num_index);
592
593 switch (res) {
594 case HASH_KEY_NON_EXISTENT:
595 break;
596 case HASH_KEY_IS_STRING:
597 case HASH_KEY_IS_LONG:
598 ht = HASH_OF(*pIter);
599 if (ht) {
600 ht->nApplyCount++;
601 }
602 if (res == HASH_KEY_IS_LONG) {
603 char *num_str = NULL;
604
605 if (vtype != xmlrpc_vector_array) {
606 spprintf(&num_str, 0, "%ld", num_index);
607 }
608 XMLRPC_AddValueToVector(xReturn, PHP_to_XMLRPC_worker(num_str, *pIter, depth++ TSRMLS_CC));
609 if (num_str) {
610 efree(num_str);
611 }
612 } else {
613 XMLRPC_AddValueToVector(xReturn, PHP_to_XMLRPC_worker(my_key, *pIter, depth++ TSRMLS_CC));
614 }
615 if (ht) {
616 ht->nApplyCount--;
617 }
618 break;
619 }
620 zend_hash_move_forward(Z_ARRVAL_P(val_arr));
621 }
622 zval_ptr_dtor(&val_arr);
623 }
624 break;
625 default:
626 break;
627 }
628 }
629 }
630 return xReturn;
631 }
632
633 static XMLRPC_VALUE PHP_to_XMLRPC(zval* root_val TSRMLS_DC)
634 {
635 return PHP_to_XMLRPC_worker(NULL, root_val, 0 TSRMLS_CC);
636 }
637
638
639 static zval* XMLRPC_to_PHP(XMLRPC_VALUE el)
640 {
641 zval* elem = NULL;
642 const char* pStr;
643
644 if (el) {
645 XMLRPC_VALUE_TYPE type = XMLRPC_GetValueType(el);
646
647 MAKE_STD_ZVAL(elem);
648
649 switch(type) {
650 case xmlrpc_empty:
651 Z_TYPE_P(elem) = IS_NULL;
652 break;
653 case xmlrpc_string:
654 pStr = XMLRPC_GetValueString(el);
655 if (pStr) {
656 Z_STRLEN_P(elem) = XMLRPC_GetValueStringLen(el);
657 Z_STRVAL_P(elem) = estrndup(pStr, Z_STRLEN_P(elem));
658 Z_TYPE_P(elem) = IS_STRING;
659 }
660 break;
661 case xmlrpc_int:
662 Z_LVAL_P(elem) = XMLRPC_GetValueInt(el);
663 Z_TYPE_P(elem) = IS_LONG;
664 break;
665 case xmlrpc_boolean:
666 Z_LVAL_P(elem) = XMLRPC_GetValueBoolean(el);
667 Z_TYPE_P(elem) = IS_BOOL;
668 break;
669 case xmlrpc_double:
670 Z_DVAL_P(elem) = XMLRPC_GetValueDouble(el);
671 Z_TYPE_P(elem) = IS_DOUBLE;
672 break;
673 case xmlrpc_datetime:
674 Z_STRLEN_P(elem) = XMLRPC_GetValueStringLen(el);
675 Z_STRVAL_P(elem) = estrndup(XMLRPC_GetValueDateTime_ISO8601(el), Z_STRLEN_P(elem));
676 Z_TYPE_P(elem) = IS_STRING;
677 break;
678 case xmlrpc_base64:
679 pStr = XMLRPC_GetValueBase64(el);
680 if (pStr) {
681 Z_STRLEN_P(elem) = XMLRPC_GetValueStringLen(el);
682 Z_STRVAL_P(elem) = estrndup(pStr, Z_STRLEN_P(elem));
683 Z_TYPE_P(elem) = IS_STRING;
684 }
685 break;
686 case xmlrpc_vector:
687 array_init(elem);
688 {
689 XMLRPC_VALUE xIter = XMLRPC_VectorRewind(el);
690
691 while( xIter ) {
692 zval *val = XMLRPC_to_PHP(xIter);
693 if (val) {
694 add_zval(elem, XMLRPC_GetValueID(xIter), &val);
695 }
696 xIter = XMLRPC_VectorNext(el);
697 }
698 }
699 break;
700 default:
701 break;
702 }
703 set_zval_xmlrpc_type(elem, type);
704 }
705 return elem;
706 }
707
708
709
710 PHP_FUNCTION(xmlrpc_encode_request)
711 {
712 XMLRPC_REQUEST xRequest = NULL;
713 char *outBuf;
714 zval *vals, *out_opts = NULL;
715 char *method = NULL;
716 int method_len;
717 php_output_options out;
718
719 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s!z|a", &method, &method_len, &vals, &out_opts) == FAILURE) {
720 return;
721 }
722
723 set_output_options(&out, out_opts ? out_opts : 0);
724
725 if (return_value_used) {
726 xRequest = XMLRPC_RequestNew();
727
728 if (xRequest) {
729 XMLRPC_RequestSetOutputOptions(xRequest, &out.xmlrpc_out);
730 if (method == NULL) {
731 XMLRPC_RequestSetRequestType(xRequest, xmlrpc_request_response);
732 } else {
733 XMLRPC_RequestSetMethodName(xRequest, method);
734 XMLRPC_RequestSetRequestType(xRequest, xmlrpc_request_call);
735 }
736 if (Z_TYPE_P(vals) != IS_NULL) {
737 XMLRPC_RequestSetData(xRequest, PHP_to_XMLRPC(vals TSRMLS_CC));
738 }
739
740 outBuf = XMLRPC_REQUEST_ToXML(xRequest, 0);
741 if (outBuf) {
742 RETVAL_STRING(outBuf, 1);
743 free(outBuf);
744 }
745 XMLRPC_RequestFree(xRequest, 1);
746 }
747 }
748
749 if (strcmp(out.xmlrpc_out.xml_elem_opts.encoding, ENCODING_DEFAULT) != 0) {
750 efree((char *)out.xmlrpc_out.xml_elem_opts.encoding);
751 }
752 }
753
754
755
756
757 PHP_FUNCTION(xmlrpc_encode)
758 {
759 XMLRPC_VALUE xOut = NULL;
760 zval **arg1;
761 char *outBuf;
762
763 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &arg1) == FAILURE) {
764 return;
765 }
766
767 if (return_value_used) {
768
769 xOut = PHP_to_XMLRPC(*arg1 TSRMLS_CC);
770
771
772 outBuf = XMLRPC_VALUE_ToXML(xOut, 0);
773
774 if (xOut) {
775 if (outBuf) {
776 RETVAL_STRING(outBuf, 1);
777 free(outBuf);
778 }
779
780 XMLRPC_CleanupValue(xOut);
781 }
782 }
783 }
784
785
786 zval* decode_request_worker(char *xml_in, int xml_in_len, char *encoding_in, zval* method_name_out)
787 {
788 zval* retval = NULL;
789 XMLRPC_REQUEST response;
790 STRUCT_XMLRPC_REQUEST_INPUT_OPTIONS opts = {{0}};
791 const char *method_name;
792 opts.xml_elem_opts.encoding = encoding_in ? utf8_get_encoding_id_from_string(encoding_in) : ENCODING_DEFAULT;
793
794
795 response = XMLRPC_REQUEST_FromXML(xml_in, xml_in_len, &opts);
796 if (response) {
797
798 retval = XMLRPC_to_PHP(XMLRPC_RequestGetData(response));
799
800 if (XMLRPC_RequestGetRequestType(response) == xmlrpc_request_call) {
801 if (method_name_out) {
802 method_name = XMLRPC_RequestGetMethodName(response);
803 if (method_name) {
804 zval_dtor(method_name_out);
805 Z_TYPE_P(method_name_out) = IS_STRING;
806 Z_STRVAL_P(method_name_out) = estrdup(method_name);
807 Z_STRLEN_P(method_name_out) = strlen(Z_STRVAL_P(method_name_out));
808 } else if (retval) {
809 zval_ptr_dtor(&retval);
810 retval = NULL;
811 }
812 }
813 }
814
815
816 XMLRPC_RequestFree(response, 1);
817 }
818 return retval;
819 }
820
821
822
823
824 PHP_FUNCTION(xmlrpc_decode_request)
825 {
826 char *xml, *encoding = NULL;
827 zval **method;
828 int xml_len, encoding_len = 0;
829
830 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sZ|s", &xml, &xml_len, &method, &encoding, &encoding_len) == FAILURE) {
831 return;
832 }
833
834
835 if (return_value_used) {
836 zval* retval = decode_request_worker(xml, xml_len, encoding_len ? encoding : NULL, *method);
837 if (retval) {
838 *return_value = *retval;
839 FREE_ZVAL(retval);
840 }
841 }
842 }
843
844
845
846
847 PHP_FUNCTION(xmlrpc_decode)
848 {
849 char *arg1, *arg2 = NULL;
850 int arg1_len, arg2_len = 0;
851
852 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &arg1, &arg1_len, &arg2, &arg2_len) == FAILURE) {
853 return;
854 }
855
856 if (return_value_used) {
857 zval* retval = decode_request_worker(arg1, arg1_len, arg2_len ? arg2 : NULL, NULL);
858 if (retval) {
859 *return_value = *retval;
860 FREE_ZVAL(retval);
861 }
862 }
863 }
864
865
866
867
868
869
870
871
872 PHP_FUNCTION(xmlrpc_server_create)
873 {
874 if (zend_parse_parameters_none() == FAILURE) {
875 return;
876 }
877
878 if (return_value_used) {
879 zval *method_map, *introspection_map;
880 xmlrpc_server_data *server = emalloc(sizeof(xmlrpc_server_data));
881 MAKE_STD_ZVAL(method_map);
882 MAKE_STD_ZVAL(introspection_map);
883
884 array_init(method_map);
885 array_init(introspection_map);
886
887
888 server->method_map = method_map;
889 server->introspection_map = introspection_map;
890 server->server_ptr = XMLRPC_ServerCreate();
891
892 XMLRPC_ServerRegisterIntrospectionCallback(server->server_ptr, php_xmlrpc_introspection_callback);
893
894
895 ZEND_REGISTER_RESOURCE(return_value,server, le_xmlrpc_server);
896 }
897 }
898
899
900
901
902 PHP_FUNCTION(xmlrpc_server_destroy)
903 {
904 zval *arg1;
905 int bSuccess = FAILURE, type;
906 xmlrpc_server_data *server;
907
908 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &arg1) == FAILURE) {
909 return;
910 }
911
912 server = zend_list_find(Z_LVAL_P(arg1), &type);
913
914 if (server && type == le_xmlrpc_server) {
915 bSuccess = zend_list_delete(Z_LVAL_P(arg1));
916
917
918
919
920 }
921 RETVAL_LONG(bSuccess == SUCCESS);
922 }
923
924
925
926
927
928 static XMLRPC_VALUE php_xmlrpc_callback(XMLRPC_SERVER server, XMLRPC_REQUEST xRequest, void* data)
929 {
930 xmlrpc_callback_data* pData = (xmlrpc_callback_data*)data;
931 zval** php_function;
932 zval* xmlrpc_params;
933 zval* callback_params[3];
934 TSRMLS_FETCH();
935
936 zval_dtor(pData->xmlrpc_method);
937 zval_dtor(pData->return_data);
938
939
940 ZVAL_STRING(pData->xmlrpc_method, XMLRPC_RequestGetMethodName(xRequest), 1);
941 xmlrpc_params = XMLRPC_to_PHP(XMLRPC_RequestGetData(xRequest));
942
943
944 if(zend_hash_find(Z_ARRVAL_P(pData->server->method_map),
945 Z_STRVAL_P(pData->xmlrpc_method),
946 Z_STRLEN_P(pData->xmlrpc_method) + 1,
947 (void**)&php_function) == SUCCESS) {
948
949 pData->php_function = *php_function;
950 }
951
952
953 callback_params[0] = pData->xmlrpc_method;
954 callback_params[1] = xmlrpc_params;
955 callback_params[2] = pData->caller_params;
956
957
958
959
960 call_user_function(CG(function_table), NULL, pData->php_function, pData->return_data, 3, callback_params TSRMLS_CC);
961
962 pData->php_executed = 1;
963
964 zval_ptr_dtor(&xmlrpc_params);
965
966 return PHP_to_XMLRPC(pData->return_data TSRMLS_CC);
967 }
968
969
970
971
972
973 static void php_xmlrpc_introspection_callback(XMLRPC_SERVER server, void* data)
974 {
975 zval retval, **php_function;
976 zval *callback_params[1];
977 char *php_function_name;
978 xmlrpc_callback_data* pData = (xmlrpc_callback_data*)data;
979 TSRMLS_FETCH();
980
981
982 callback_params[0] = pData->caller_params;
983
984
985 zend_hash_internal_pointer_reset(Z_ARRVAL_P(pData->server->introspection_map));
986 while (1) {
987 if (zend_hash_get_current_data(Z_ARRVAL_P(pData->server->introspection_map), (void**)&php_function) == SUCCESS) {
988 if (zend_is_callable(*php_function, 0, &php_function_name TSRMLS_CC)) {
989
990 if (call_user_function(CG(function_table), NULL, *php_function, &retval, 1, callback_params TSRMLS_CC) == SUCCESS) {
991 XMLRPC_VALUE xData;
992 STRUCT_XMLRPC_ERROR err = {0};
993
994
995 convert_to_string(&retval);
996
997 xData = XMLRPC_IntrospectionCreateDescription(Z_STRVAL(retval), &err);
998
999 if (xData) {
1000 if (!XMLRPC_ServerAddIntrospectionData(server, xData)) {
1001 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to add introspection data returned from %s(), improper element structure", php_function_name);
1002 }
1003 XMLRPC_CleanupValue(xData);
1004 } else {
1005
1006 if (err.xml_elem_error.parser_code) {
1007 php_error_docref(NULL TSRMLS_CC, E_WARNING, "xml parse error: [line %ld, column %ld, message: %s] Unable to add introspection data returned from %s()",
1008 err.xml_elem_error.column, err.xml_elem_error.line, err.xml_elem_error.parser_error, php_function_name);
1009 } else {
1010 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to add introspection data returned from %s()", php_function_name);
1011 }
1012 }
1013 zval_dtor(&retval);
1014 } else {
1015
1016 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error calling user introspection callback: %s()", php_function_name);
1017 }
1018 } else {
1019 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid callback '%s' passed", php_function_name);
1020 }
1021 efree(php_function_name);
1022 } else {
1023 break;
1024 }
1025 zend_hash_move_forward(Z_ARRVAL_P(pData->server->introspection_map));
1026 }
1027
1028
1029 zend_hash_clean(Z_ARRVAL_P(pData->server->introspection_map));
1030 }
1031
1032
1033
1034
1035 PHP_FUNCTION(xmlrpc_server_register_method)
1036 {
1037 char *method_key;
1038 int method_key_len;
1039 zval *handle, *method_name_save, **method_name;
1040 int type;
1041 xmlrpc_server_data* server;
1042
1043 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsZ", &handle, &method_key, &method_key_len, &method_name) == FAILURE) {
1044 return;
1045 }
1046
1047 server = zend_list_find(Z_LVAL_P(handle), &type);
1048
1049 if (type == le_xmlrpc_server) {
1050
1051
1052
1053 if (XMLRPC_ServerRegisterMethod(server->server_ptr, method_key, php_xmlrpc_callback)) {
1054
1055 ALLOC_ZVAL(method_name_save);
1056 MAKE_COPY_ZVAL(method_name, method_name_save);
1057
1058
1059 add_zval(server->method_map, method_key, &method_name_save);
1060
1061 RETURN_BOOL(1);
1062 }
1063 }
1064 RETURN_BOOL(0);
1065 }
1066
1067
1068
1069
1070 PHP_FUNCTION(xmlrpc_server_register_introspection_callback)
1071 {
1072 zval **method_name, *handle, *method_name_save;
1073 int type;
1074 xmlrpc_server_data* server;
1075
1076 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rZ", &handle, &method_name) == FAILURE) {
1077 return;
1078 }
1079
1080 server = zend_list_find(Z_LVAL_P(handle), &type);
1081
1082 if (type == le_xmlrpc_server) {
1083
1084 ALLOC_ZVAL(method_name_save);
1085 MAKE_COPY_ZVAL(method_name, method_name_save);
1086
1087
1088 add_zval(server->introspection_map, NULL, &method_name_save);
1089
1090 RETURN_BOOL(1);
1091 }
1092 RETURN_BOOL(0);
1093 }
1094
1095
1096
1097
1098
1099
1100 PHP_FUNCTION(xmlrpc_server_call_method)
1101 {
1102 xmlrpc_callback_data data = {0};
1103 XMLRPC_REQUEST xRequest;
1104 STRUCT_XMLRPC_REQUEST_INPUT_OPTIONS input_opts;
1105 xmlrpc_server_data* server;
1106 zval **caller_params, *handle, *output_opts = NULL;
1107 char *rawxml;
1108 int rawxml_len, type;
1109 php_output_options out;
1110 int argc =ZEND_NUM_ARGS();
1111
1112 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsZ|a", &handle, &rawxml, &rawxml_len, &caller_params, &output_opts) != SUCCESS) {
1113 return;
1114 }
1115
1116 if (argc == 3) {
1117 set_output_options(&out, NULL);
1118 } else {
1119 set_output_options(&out, output_opts);
1120 }
1121
1122 server = zend_list_find(Z_LVAL_P(handle), &type);
1123
1124 if (type == le_xmlrpc_server) {
1125
1126 input_opts.xml_elem_opts.encoding = utf8_get_encoding_id_from_string(out.xmlrpc_out.xml_elem_opts.encoding);
1127
1128
1129 xRequest = XMLRPC_REQUEST_FromXML(rawxml, rawxml_len, &input_opts);
1130
1131 if (xRequest) {
1132 const char* methodname = XMLRPC_RequestGetMethodName(xRequest);
1133 XMLRPC_VALUE xAnswer = NULL;
1134 MAKE_STD_ZVAL(data.xmlrpc_method);
1135 MAKE_STD_ZVAL(data.return_data);
1136 Z_TYPE_P(data.return_data) = IS_NULL;
1137 Z_TYPE_P(data.xmlrpc_method) = IS_NULL;
1138
1139
1140 data.caller_params = *caller_params;
1141 data.php_executed = 0;
1142 data.server = server;
1143
1144
1145
1146
1147
1148 xAnswer = XMLRPC_ServerCallMethod(server->server_ptr, xRequest, &data);
1149 if (xAnswer && out.b_php_out) {
1150 zval_dtor(data.return_data);
1151 FREE_ZVAL(data.return_data);
1152 data.return_data = XMLRPC_to_PHP(xAnswer);
1153 } else if (data.php_executed && !out.b_php_out && !xAnswer) {
1154 xAnswer = PHP_to_XMLRPC(data.return_data TSRMLS_CC);
1155 }
1156
1157
1158 if (!out.b_php_out) {
1159 XMLRPC_REQUEST xResponse = XMLRPC_RequestNew();
1160 if (xResponse) {
1161 char *outBuf = 0;
1162 int buf_len = 0;
1163
1164
1165 if (out.b_auto_version) {
1166 XMLRPC_REQUEST_OUTPUT_OPTIONS opts = XMLRPC_RequestGetOutputOptions(xRequest);
1167 if (opts) {
1168 out.xmlrpc_out.version = opts->version;
1169 }
1170 }
1171
1172 XMLRPC_RequestSetOutputOptions(xResponse, &out.xmlrpc_out);
1173 XMLRPC_RequestSetRequestType(xResponse, xmlrpc_request_response);
1174 XMLRPC_RequestSetData(xResponse, xAnswer);
1175 XMLRPC_RequestSetMethodName(xResponse, methodname);
1176
1177
1178 outBuf = XMLRPC_REQUEST_ToXML(xResponse, &buf_len);
1179 if (outBuf) {
1180 RETVAL_STRINGL(outBuf, buf_len, 1);
1181 free(outBuf);
1182 }
1183
1184 XMLRPC_RequestFree(xResponse, 0);
1185 }
1186 } else {
1187 *return_value = *data.return_data;
1188 zval_copy_ctor(return_value);
1189 }
1190
1191
1192 zval_ptr_dtor(&data.xmlrpc_method);
1193
1194 zval_dtor(data.return_data);
1195 FREE_ZVAL(data.return_data);
1196
1197 if (xAnswer) {
1198 XMLRPC_CleanupValue(xAnswer);
1199 }
1200
1201 XMLRPC_RequestFree(xRequest, 1);
1202 }
1203 }
1204 }
1205
1206
1207
1208
1209 PHP_FUNCTION(xmlrpc_server_add_introspection_data)
1210 {
1211 zval *handle, *desc;
1212 int type;
1213 xmlrpc_server_data* server;
1214
1215 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ra", &handle, &desc) == FAILURE) {
1216 return;
1217 }
1218
1219 server = zend_list_find(Z_LVAL_P(handle), &type);
1220
1221 if (type == le_xmlrpc_server) {
1222 XMLRPC_VALUE xDesc = PHP_to_XMLRPC(desc TSRMLS_CC);
1223 if (xDesc) {
1224 int retval = XMLRPC_ServerAddIntrospectionData(server->server_ptr, xDesc);
1225 XMLRPC_CleanupValue(xDesc);
1226 RETURN_LONG(retval);
1227 }
1228 }
1229 RETURN_LONG(0);
1230 }
1231
1232
1233
1234
1235 PHP_FUNCTION(xmlrpc_parse_method_descriptions)
1236 {
1237 zval *retval;
1238 char *arg1;
1239 int arg1_len;
1240
1241 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg1, &arg1_len) == FAILURE) {
1242 return;
1243 }
1244
1245 if (return_value_used) {
1246 STRUCT_XMLRPC_ERROR err = {0};
1247 XMLRPC_VALUE xVal = XMLRPC_IntrospectionCreateDescription(arg1, &err);
1248 if (xVal) {
1249 retval = XMLRPC_to_PHP(xVal);
1250
1251 if (retval) {
1252 RETVAL_ZVAL(retval, 1, 1);
1253 }
1254
1255 XMLRPC_CleanupValue(xVal);
1256 } else {
1257
1258 if (err.xml_elem_error.parser_code) {
1259 php_error_docref(NULL TSRMLS_CC, E_WARNING, "xml parse error: [line %ld, column %ld, message: %s] Unable to create introspection data",
1260 err.xml_elem_error.column, err.xml_elem_error.line, err.xml_elem_error.parser_error);
1261 } else {
1262 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid xml structure. Unable to create introspection data");
1263 }
1264
1265 php_error_docref(NULL TSRMLS_CC, E_WARNING, "xml parse error. no method description created");
1266 }
1267 }
1268 }
1269
1270
1271
1272
1273
1274
1275 #define XMLRPC_TYPE_COUNT 9
1276 #define XMLRPC_VECTOR_TYPE_COUNT 4
1277 #define TYPE_STR_MAP_SIZE (XMLRPC_TYPE_COUNT + XMLRPC_VECTOR_TYPE_COUNT)
1278
1279
1280 static const char** get_type_str_mapping(void)
1281 {
1282 static const char* str_mapping[TYPE_STR_MAP_SIZE];
1283 static int first = 1;
1284 if (first) {
1285
1286 str_mapping[xmlrpc_none] = "none";
1287 str_mapping[xmlrpc_empty] = "empty";
1288 str_mapping[xmlrpc_base64] = "base64";
1289 str_mapping[xmlrpc_boolean] = "boolean";
1290 str_mapping[xmlrpc_datetime] = "datetime";
1291 str_mapping[xmlrpc_double] = "double";
1292 str_mapping[xmlrpc_int] = "int";
1293 str_mapping[xmlrpc_string] = "string";
1294 str_mapping[xmlrpc_vector] = "vector";
1295 str_mapping[XMLRPC_TYPE_COUNT + xmlrpc_vector_none] = "none";
1296 str_mapping[XMLRPC_TYPE_COUNT + xmlrpc_vector_array] = "array";
1297 str_mapping[XMLRPC_TYPE_COUNT + xmlrpc_vector_mixed] = "mixed";
1298 str_mapping[XMLRPC_TYPE_COUNT + xmlrpc_vector_struct] = "struct";
1299 first = 0;
1300 }
1301 return (const char**)str_mapping;
1302 }
1303
1304
1305
1306 const char* xmlrpc_type_as_str(XMLRPC_VALUE_TYPE type, XMLRPC_VECTOR_TYPE vtype)
1307 {
1308 const char** str_mapping = get_type_str_mapping();
1309
1310 if (vtype == xmlrpc_vector_none) {
1311 return str_mapping[type];
1312 } else {
1313 return str_mapping[XMLRPC_TYPE_COUNT + vtype];
1314 }
1315 }
1316
1317
1318
1319 XMLRPC_VALUE_TYPE xmlrpc_str_as_type(const char* str)
1320 {
1321 const char** str_mapping = get_type_str_mapping();
1322 int i;
1323
1324 if (str) {
1325 for (i = 0; i < XMLRPC_TYPE_COUNT; i++) {
1326 if (!strcmp(str_mapping[i], str)) {
1327 return (XMLRPC_VALUE_TYPE) i;
1328 }
1329 }
1330 }
1331 return xmlrpc_none;
1332 }
1333
1334
1335
1336 XMLRPC_VECTOR_TYPE xmlrpc_str_as_vector_type(const char* str)
1337 {
1338 const char** str_mapping = get_type_str_mapping();
1339 int i;
1340
1341 if (str) {
1342 for (i = XMLRPC_TYPE_COUNT; i < TYPE_STR_MAP_SIZE; i++) {
1343 if (!strcmp(str_mapping[i], str)) {
1344 return (XMLRPC_VECTOR_TYPE) (i - XMLRPC_TYPE_COUNT);
1345 }
1346 }
1347 }
1348 return xmlrpc_none;
1349 }
1350
1351
1352
1353
1354
1355
1356 int set_zval_xmlrpc_type(zval* value, XMLRPC_VALUE_TYPE newtype)
1357 {
1358 int bSuccess = FAILURE;
1359 TSRMLS_FETCH();
1360
1361
1362
1363
1364 if (Z_TYPE_P(value) == IS_STRING) {
1365 if (newtype == xmlrpc_base64 || newtype == xmlrpc_datetime) {
1366 const char* typestr = xmlrpc_type_as_str(newtype, xmlrpc_vector_none);
1367 zval* type;
1368
1369 MAKE_STD_ZVAL(type);
1370
1371 Z_TYPE_P(type) = IS_STRING;
1372 Z_STRVAL_P(type) = estrdup(typestr);
1373 Z_STRLEN_P(type) = strlen(typestr);
1374
1375 if (newtype == xmlrpc_datetime) {
1376 XMLRPC_VALUE v = XMLRPC_CreateValueDateTime_ISO8601(NULL, value->value.str.val);
1377 if (v) {
1378 time_t timestamp = (time_t) php_parse_date((char *)XMLRPC_GetValueDateTime_ISO8601(v), NULL);
1379 if (timestamp != -1) {
1380 zval* ztimestamp;
1381
1382 MAKE_STD_ZVAL(ztimestamp);
1383
1384 ztimestamp->type = IS_LONG;
1385 ztimestamp->value.lval = timestamp;
1386
1387 convert_to_object(value);
1388 if (SUCCESS == zend_hash_update(Z_OBJPROP_P(value), OBJECT_TYPE_ATTR, sizeof(OBJECT_TYPE_ATTR), (void *) &type, sizeof(zval *), NULL)) {
1389 bSuccess = zend_hash_update(Z_OBJPROP_P(value), OBJECT_VALUE_TS_ATTR, sizeof(OBJECT_VALUE_TS_ATTR), (void *) &ztimestamp, sizeof(zval *), NULL);
1390 }
1391 } else {
1392 zval_ptr_dtor(&type);
1393 }
1394 XMLRPC_CleanupValue(v);
1395 } else {
1396 zval_ptr_dtor(&type);
1397 }
1398 } else {
1399 convert_to_object(value);
1400 bSuccess = zend_hash_update(Z_OBJPROP_P(value), OBJECT_TYPE_ATTR, sizeof(OBJECT_TYPE_ATTR), (void *) &type, sizeof(zval *), NULL);
1401 }
1402 }
1403 }
1404
1405 return bSuccess;
1406 }
1407
1408
1409
1410 XMLRPC_VALUE_TYPE get_zval_xmlrpc_type(zval* value, zval** newvalue)
1411 {
1412 XMLRPC_VALUE_TYPE type = xmlrpc_none;
1413 TSRMLS_FETCH();
1414
1415 if (value) {
1416 switch (Z_TYPE_P(value)) {
1417 case IS_NULL:
1418 type = xmlrpc_base64;
1419 break;
1420 #ifndef BOOL_AS_LONG
1421
1422
1423 case IS_BOOL:
1424 type = xmlrpc_boolean;
1425 break;
1426 #else
1427 case IS_BOOL:
1428 #endif
1429 case IS_LONG:
1430 case IS_RESOURCE:
1431 type = xmlrpc_int;
1432 break;
1433 case IS_DOUBLE:
1434 type = xmlrpc_double;
1435 break;
1436 case IS_CONSTANT:
1437 type = xmlrpc_string;
1438 break;
1439 case IS_STRING:
1440 type = xmlrpc_string;
1441 break;
1442 case IS_ARRAY:
1443 type = xmlrpc_vector;
1444 break;
1445 case IS_OBJECT:
1446 {
1447 zval** attr;
1448 type = xmlrpc_vector;
1449
1450 if (zend_hash_find(Z_OBJPROP_P(value), OBJECT_TYPE_ATTR, sizeof(OBJECT_TYPE_ATTR), (void**) &attr) == SUCCESS) {
1451 if (Z_TYPE_PP(attr) == IS_STRING) {
1452 type = xmlrpc_str_as_type(Z_STRVAL_PP(attr));
1453 }
1454 }
1455 break;
1456 }
1457 }
1458
1459
1460 if (newvalue) {
1461 zval** val;
1462
1463 if ((type == xmlrpc_base64 && Z_TYPE_P(value) == IS_OBJECT) || type == xmlrpc_datetime) {
1464 if (zend_hash_find(Z_OBJPROP_P(value), OBJECT_VALUE_ATTR, sizeof(OBJECT_VALUE_ATTR), (void**) &val) == SUCCESS) {
1465 *newvalue = *val;
1466 }
1467 } else {
1468 *newvalue = value;
1469 }
1470 }
1471 }
1472
1473 return type;
1474 }
1475
1476
1477
1478
1479 PHP_FUNCTION(xmlrpc_set_type)
1480 {
1481 zval **arg;
1482 char *type;
1483 int type_len;
1484 XMLRPC_VALUE_TYPE vtype;
1485
1486 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zs", &arg, &type, &type_len) == FAILURE) {
1487 return;
1488 }
1489
1490 vtype = xmlrpc_str_as_type(type);
1491 if (vtype != xmlrpc_none) {
1492 if (set_zval_xmlrpc_type(*arg, vtype) == SUCCESS) {
1493 RETURN_TRUE;
1494 }
1495 } else {
1496 zend_error(E_WARNING,"invalid type '%s' passed to xmlrpc_set_type()", type);
1497 }
1498 RETURN_FALSE;
1499 }
1500
1501
1502
1503
1504 PHP_FUNCTION(xmlrpc_get_type)
1505 {
1506 zval **arg;
1507 XMLRPC_VALUE_TYPE type;
1508 XMLRPC_VECTOR_TYPE vtype = xmlrpc_vector_none;
1509
1510 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &arg) == FAILURE) {
1511 return;
1512 }
1513
1514 type = get_zval_xmlrpc_type(*arg, 0);
1515 if (type == xmlrpc_vector) {
1516 vtype = determine_vector_type((Z_TYPE_PP(arg) == IS_OBJECT) ? Z_OBJPROP_PP(arg) : Z_ARRVAL_PP(arg));
1517 }
1518
1519 RETURN_STRING((char*) xmlrpc_type_as_str(type, vtype), 1);
1520 }
1521
1522
1523
1524
1525 PHP_FUNCTION(xmlrpc_is_fault)
1526 {
1527 zval *arg, **val;
1528
1529 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &arg) == FAILURE) {
1530 return;
1531 }
1532
1533
1534
1535
1536
1537
1538
1539 if (zend_hash_find(Z_ARRVAL_P(arg), FAULT_CODE, FAULT_CODE_LEN + 1, (void**) &val) == SUCCESS &&
1540 zend_hash_find(Z_ARRVAL_P(arg), FAULT_STRING, FAULT_STRING_LEN + 1, (void**) &val) == SUCCESS) {
1541 RETURN_TRUE;
1542 }
1543
1544 RETURN_FALSE;
1545 }
1546
1547
1548
1549
1550
1551
1552
1553
1554