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