Annotation of embedaddon/php/ext/soap/php_encoding.c, revision 1.1.1.1
1.1 misho 1: /*
2: +----------------------------------------------------------------------+
3: | PHP Version 5 |
4: +----------------------------------------------------------------------+
5: | Copyright (c) 1997-2012 The PHP Group |
6: +----------------------------------------------------------------------+
7: | This source file is subject to version 3.01 of the PHP license, |
8: | that is bundled with this package in the file LICENSE, and is |
9: | available through the world-wide-web at the following url: |
10: | http://www.php.net/license/3_01.txt |
11: | If you did not receive a copy of the PHP license and are unable to |
12: | obtain it through the world-wide-web, please send a note to |
13: | license@php.net so we can mail you a copy immediately. |
14: +----------------------------------------------------------------------+
15: | Authors: Brad Lafountain <rodif_bl@yahoo.com> |
16: | Shane Caraveo <shane@caraveo.com> |
17: | Dmitry Stogov <dmitry@zend.com> |
18: +----------------------------------------------------------------------+
19: */
20: /* $Id: php_encoding.c 321634 2012-01-01 13:15:04Z felipe $ */
21:
22: #include <time.h>
23:
24: #include "php_soap.h"
25: #include "ext/libxml/php_libxml.h"
26: #include "ext/standard/base64.h"
27: #include <libxml/parserInternals.h>
28: #include "zend_strtod.h"
29: #include "zend_interfaces.h"
30:
31: /* zval type decode */
32: static zval *to_zval_double(encodeTypePtr type, xmlNodePtr data);
33: static zval *to_zval_long(encodeTypePtr type, xmlNodePtr data);
34: static zval *to_zval_bool(encodeTypePtr type, xmlNodePtr data);
35: static zval *to_zval_string(encodeTypePtr type, xmlNodePtr data);
36: static zval *to_zval_stringr(encodeTypePtr type, xmlNodePtr data);
37: static zval *to_zval_stringc(encodeTypePtr type, xmlNodePtr data);
38: static zval *to_zval_map(encodeTypePtr type, xmlNodePtr data);
39: static zval *to_zval_null(encodeTypePtr type, xmlNodePtr data);
40: static zval *to_zval_base64(encodeTypePtr type, xmlNodePtr data);
41: static zval *to_zval_hexbin(encodeTypePtr type, xmlNodePtr data);
42:
43: static xmlNodePtr to_xml_long(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
44: static xmlNodePtr to_xml_double(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
45: static xmlNodePtr to_xml_bool(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
46:
47: /* String encode */
48: static xmlNodePtr to_xml_string(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
49: static xmlNodePtr to_xml_base64(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
50: static xmlNodePtr to_xml_hexbin(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
51:
52: /* Null encode */
53: static xmlNodePtr to_xml_null(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
54:
55: /* Array encode */
56: static xmlNodePtr guess_array_map(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
57: static xmlNodePtr to_xml_map(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
58:
59: static xmlNodePtr to_xml_list(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent);
60: static xmlNodePtr to_xml_list1(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent);
61:
62: /* Datetime encode/decode */
63: static xmlNodePtr to_xml_datetime_ex(encodeTypePtr type, zval *data, char *format, int style, xmlNodePtr parent);
64: static xmlNodePtr to_xml_datetime(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
65: static xmlNodePtr to_xml_time(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
66: static xmlNodePtr to_xml_date(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
67: static xmlNodePtr to_xml_gyearmonth(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
68: static xmlNodePtr to_xml_gyear(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
69: static xmlNodePtr to_xml_gmonthday(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
70: static xmlNodePtr to_xml_gday(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
71: static xmlNodePtr to_xml_gmonth(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
72: static xmlNodePtr to_xml_duration(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
73:
74: static zval *to_zval_object(encodeTypePtr type, xmlNodePtr data);
75: static zval *to_zval_array(encodeTypePtr type, xmlNodePtr data);
76:
77: static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
78: static xmlNodePtr to_xml_array(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
79:
80: static zval *to_zval_any(encodeTypePtr type, xmlNodePtr data);
81: static xmlNodePtr to_xml_any(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
82:
83: /* Try and guess for non-wsdl clients and servers */
84: static zval *guess_zval_convert(encodeTypePtr type, xmlNodePtr data);
85: static xmlNodePtr guess_xml_convert(encodeTypePtr type, zval *data, int style, xmlNodePtr parent);
86:
87: static int is_map(zval *array);
88: static encodePtr get_array_type(xmlNodePtr node, zval *array, smart_str *out_type TSRMLS_DC);
89:
90: static xmlNodePtr check_and_resolve_href(xmlNodePtr data);
91:
92: static void set_ns_prop(xmlNodePtr node, char *ns, char *name, char *val);
93: static void set_xsi_nil(xmlNodePtr node);
94: static void set_xsi_type(xmlNodePtr node, char *type);
95:
96: static void get_type_str(xmlNodePtr node, const char* ns, const char* type, smart_str* ret);
97: static void set_ns_and_type_ex(xmlNodePtr node, char *ns, char *type);
98:
99: static void set_ns_and_type(xmlNodePtr node, encodeTypePtr type);
100:
101: #define FIND_XML_NULL(xml,zval) \
102: { \
103: xmlAttrPtr null; \
104: if (!xml) { \
105: ZVAL_NULL(zval); \
106: return zval; \
107: } \
108: if (xml->properties) { \
109: null = get_attribute(xml->properties, "nil"); \
110: if (null) { \
111: ZVAL_NULL(zval); \
112: return zval; \
113: } \
114: } \
115: }
116:
117: #define CHECK_XML_NULL(xml) \
118: { \
119: xmlAttrPtr null; \
120: if (!xml) { \
121: zval *ret; \
122: ALLOC_INIT_ZVAL(ret); \
123: ZVAL_NULL(ret); \
124: return ret; \
125: } \
126: if (xml->properties) { \
127: null = get_attribute(xml->properties, "nil"); \
128: if (null) { \
129: zval *ret; \
130: ALLOC_INIT_ZVAL(ret); \
131: ZVAL_NULL(ret); \
132: return ret; \
133: } \
134: } \
135: }
136:
137: #define FIND_ZVAL_NULL(zval, xml, style) \
138: { \
139: if (!zval || Z_TYPE_P(zval) == IS_NULL) { \
140: if (style == SOAP_ENCODED) {\
141: set_xsi_nil(xml); \
142: } \
143: return xml; \
144: } \
145: }
146:
147: encode defaultEncoding[] = {
148: {{UNKNOWN_TYPE, NULL, NULL, NULL}, guess_zval_convert, guess_xml_convert},
149:
150: {{IS_NULL, "nil", XSI_NAMESPACE, NULL}, to_zval_null, to_xml_null},
151: {{IS_STRING, XSD_STRING_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_string},
152: {{IS_LONG, XSD_INT_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
153: {{IS_DOUBLE, XSD_FLOAT_STRING, XSD_NAMESPACE, NULL}, to_zval_double, to_xml_double},
154: {{IS_BOOL, XSD_BOOLEAN_STRING, XSD_NAMESPACE, NULL}, to_zval_bool, to_xml_bool},
155: {{IS_CONSTANT, XSD_STRING_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_string},
156: {{IS_ARRAY, SOAP_ENC_ARRAY_STRING, SOAP_1_1_ENC_NAMESPACE, NULL}, to_zval_array, guess_array_map},
157: {{IS_CONSTANT_ARRAY, SOAP_ENC_ARRAY_STRING, SOAP_1_1_ENC_NAMESPACE, NULL}, to_zval_array, to_xml_array},
158: {{IS_OBJECT, SOAP_ENC_OBJECT_STRING, SOAP_1_1_ENC_NAMESPACE, NULL}, to_zval_object, to_xml_object},
159: {{IS_ARRAY, SOAP_ENC_ARRAY_STRING, SOAP_1_2_ENC_NAMESPACE, NULL}, to_zval_array, guess_array_map},
160: {{IS_CONSTANT_ARRAY, SOAP_ENC_ARRAY_STRING, SOAP_1_2_ENC_NAMESPACE, NULL}, to_zval_array, to_xml_array},
161: {{IS_OBJECT, SOAP_ENC_OBJECT_STRING, SOAP_1_2_ENC_NAMESPACE, NULL}, to_zval_object, to_xml_object},
162:
163: {{XSD_STRING, XSD_STRING_STRING, XSD_NAMESPACE, NULL}, to_zval_string, to_xml_string},
164: {{XSD_BOOLEAN, XSD_BOOLEAN_STRING, XSD_NAMESPACE, NULL}, to_zval_bool, to_xml_bool},
165: {{XSD_DECIMAL, XSD_DECIMAL_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
166: {{XSD_FLOAT, XSD_FLOAT_STRING, XSD_NAMESPACE, NULL}, to_zval_double, to_xml_double},
167: {{XSD_DOUBLE, XSD_DOUBLE_STRING, XSD_NAMESPACE, NULL}, to_zval_double, to_xml_double},
168:
169: {{XSD_DATETIME, XSD_DATETIME_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_datetime},
170: {{XSD_TIME, XSD_TIME_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_time},
171: {{XSD_DATE, XSD_DATE_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_date},
172: {{XSD_GYEARMONTH, XSD_GYEARMONTH_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_gyearmonth},
173: {{XSD_GYEAR, XSD_GYEAR_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_gyear},
174: {{XSD_GMONTHDAY, XSD_GMONTHDAY_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_gmonthday},
175: {{XSD_GDAY, XSD_GDAY_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_gday},
176: {{XSD_GMONTH, XSD_GMONTH_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_gmonth},
177: {{XSD_DURATION, XSD_DURATION_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_duration},
178:
179: {{XSD_HEXBINARY, XSD_HEXBINARY_STRING, XSD_NAMESPACE, NULL}, to_zval_hexbin, to_xml_hexbin},
180: {{XSD_BASE64BINARY, XSD_BASE64BINARY_STRING, XSD_NAMESPACE, NULL}, to_zval_base64, to_xml_base64},
181:
182: {{XSD_LONG, XSD_LONG_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
183: {{XSD_INT, XSD_INT_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
184: {{XSD_SHORT, XSD_SHORT_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
185: {{XSD_BYTE, XSD_BYTE_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
186: {{XSD_NONPOSITIVEINTEGER, XSD_NONPOSITIVEINTEGER_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
187: {{XSD_POSITIVEINTEGER, XSD_POSITIVEINTEGER_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
188: {{XSD_NONNEGATIVEINTEGER, XSD_NONNEGATIVEINTEGER_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
189: {{XSD_NEGATIVEINTEGER, XSD_NEGATIVEINTEGER_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
190: {{XSD_UNSIGNEDBYTE, XSD_UNSIGNEDBYTE_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
191: {{XSD_UNSIGNEDSHORT, XSD_UNSIGNEDSHORT_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
192: {{XSD_UNSIGNEDINT, XSD_UNSIGNEDINT_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
193: {{XSD_UNSIGNEDLONG, XSD_UNSIGNEDLONG_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
194: {{XSD_INTEGER, XSD_INTEGER_STRING, XSD_NAMESPACE, NULL}, to_zval_long, to_xml_long},
195:
196: {{XSD_ANYTYPE, XSD_ANYTYPE_STRING, XSD_NAMESPACE, NULL}, guess_zval_convert, guess_xml_convert},
197: {{XSD_UR_TYPE, XSD_UR_TYPE_STRING, XSD_NAMESPACE, NULL}, guess_zval_convert, guess_xml_convert},
198: {{XSD_ANYURI, XSD_ANYURI_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
199: {{XSD_QNAME, XSD_QNAME_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
200: {{XSD_NOTATION, XSD_NOTATION_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
201: {{XSD_NORMALIZEDSTRING, XSD_NORMALIZEDSTRING_STRING, XSD_NAMESPACE, NULL}, to_zval_stringr, to_xml_string},
202: {{XSD_TOKEN, XSD_TOKEN_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
203: {{XSD_LANGUAGE, XSD_LANGUAGE_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
204: {{XSD_NMTOKEN, XSD_NMTOKEN_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
205: {{XSD_NMTOKENS, XSD_NMTOKENS_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_list1},
206: {{XSD_NAME, XSD_NAME_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
207: {{XSD_NCNAME, XSD_NCNAME_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
208: {{XSD_ID, XSD_ID_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
209: {{XSD_IDREF, XSD_IDREF_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
210: {{XSD_IDREFS, XSD_IDREFS_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_list1},
211: {{XSD_ENTITY, XSD_ENTITY_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
212: {{XSD_ENTITIES, XSD_ENTITIES_STRING, XSD_NAMESPACE, NULL}, to_zval_stringc, to_xml_list1},
213:
214: {{APACHE_MAP, APACHE_MAP_STRING, APACHE_NAMESPACE, NULL}, to_zval_map, to_xml_map},
215:
216: {{SOAP_ENC_OBJECT, SOAP_ENC_OBJECT_STRING, SOAP_1_1_ENC_NAMESPACE, NULL}, to_zval_object, to_xml_object},
217: {{SOAP_ENC_ARRAY, SOAP_ENC_ARRAY_STRING, SOAP_1_1_ENC_NAMESPACE, NULL}, to_zval_array, to_xml_array},
218: {{SOAP_ENC_OBJECT, SOAP_ENC_OBJECT_STRING, SOAP_1_2_ENC_NAMESPACE, NULL}, to_zval_object, to_xml_object},
219: {{SOAP_ENC_ARRAY, SOAP_ENC_ARRAY_STRING, SOAP_1_2_ENC_NAMESPACE, NULL}, to_zval_array, to_xml_array},
220:
221: /* support some of the 1999 data types */
222: {{XSD_STRING, XSD_STRING_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_string, to_xml_string},
223: {{XSD_BOOLEAN, XSD_BOOLEAN_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_bool, to_xml_bool},
224: {{XSD_DECIMAL, XSD_DECIMAL_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
225: {{XSD_FLOAT, XSD_FLOAT_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_double, to_xml_double},
226: {{XSD_DOUBLE, XSD_DOUBLE_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_double, to_xml_double},
227:
228: {{XSD_LONG, XSD_LONG_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_long, to_xml_long},
229: {{XSD_INT, XSD_INT_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_long, to_xml_long},
230: {{XSD_SHORT, XSD_SHORT_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_long, to_xml_long},
231: {{XSD_BYTE, XSD_BYTE_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_long, to_xml_long},
232: {{XSD_1999_TIMEINSTANT, XSD_1999_TIMEINSTANT_STRING, XSD_1999_NAMESPACE, NULL}, to_zval_stringc, to_xml_string},
233:
234: {{XSD_ANYXML, "<anyXML>", "<anyXML>", NULL}, to_zval_any, to_xml_any},
235:
236: {{END_KNOWN_TYPES, NULL, NULL, NULL}, guess_zval_convert, guess_xml_convert}
237: };
238:
239: int numDefaultEncodings = sizeof(defaultEncoding)/sizeof(encode);
240:
241:
242: void whiteSpace_replace(xmlChar* str)
243: {
244: while (*str != '\0') {
245: if (*str == '\x9' || *str == '\xA' || *str == '\xD') {
246: *str = ' ';
247: }
248: str++;
249: }
250: }
251:
252: void whiteSpace_collapse(xmlChar* str)
253: {
254: xmlChar *pos;
255: xmlChar old;
256:
257: pos = str;
258: whiteSpace_replace(str);
259: while (*str == ' ') {
260: str++;
261: }
262: old = '\0';
263: while (*str != '\0') {
264: if (*str != ' ' || old != ' ') {
265: *pos = *str;
266: pos++;
267: }
268: old = *str;
269: str++;
270: }
271: if (old == ' ') {
272: --pos;
273: }
274: *pos = '\0';
275: }
276:
277: static encodePtr find_encoder_by_type_name(sdlPtr sdl, const char *type)
278: {
279: if (sdl && sdl->encoders) {
280: HashPosition pos;
281: encodePtr *enc;
282:
283: for (zend_hash_internal_pointer_reset_ex(sdl->encoders, &pos);
284: zend_hash_get_current_data_ex(sdl->encoders, (void **) &enc, &pos) == SUCCESS;
285: zend_hash_move_forward_ex(sdl->encoders, &pos)) {
286: if (strcmp((*enc)->details.type_str, type) == 0) {
287: return *enc;
288: }
289: }
290: }
291: return NULL;
292: }
293:
294: static zend_bool soap_check_zval_ref(zval *data, xmlNodePtr node TSRMLS_DC) {
295: xmlNodePtr *node_ptr;
296:
297: if (SOAP_GLOBAL(ref_map)) {
298: if (Z_TYPE_P(data) == IS_OBJECT) {
299: data = (zval*)zend_objects_get_address(data TSRMLS_CC);
300: }
301: if (zend_hash_index_find(SOAP_GLOBAL(ref_map), (ulong)data, (void**)&node_ptr) == SUCCESS) {
302: xmlAttrPtr attr = (*node_ptr)->properties;
303: char *id;
304: smart_str prefix = {0};
305:
306: if (*node_ptr == node) {
307: return 0;
308: }
309: xmlNodeSetName(node, (*node_ptr)->name);
310: xmlSetNs(node, (*node_ptr)->ns);
311: if (SOAP_GLOBAL(soap_version) == SOAP_1_1) {
312: while (1) {
313: attr = get_attribute(attr, "id");
314: if (attr == NULL || attr->ns == NULL) {
315: break;
316: }
317: attr = attr->next;
318: }
319: if (attr) {
320: id = (char*)attr->children->content;
321: smart_str_appendc(&prefix, '#');
322: smart_str_appends(&prefix, id);
323: smart_str_0(&prefix);
324: id = prefix.c;
325: } else {
326: SOAP_GLOBAL(cur_uniq_ref)++;
327: smart_str_appendl(&prefix, "#ref", 4);
328: smart_str_append_long(&prefix, SOAP_GLOBAL(cur_uniq_ref));
329: smart_str_0(&prefix);
330: id = prefix.c;
331: xmlSetProp((*node_ptr), BAD_CAST("id"), BAD_CAST(id+1));
332: }
333: xmlSetProp(node, BAD_CAST("href"), BAD_CAST(id));
334: } else {
335: attr = get_attribute_ex(attr, "id", SOAP_1_2_ENC_NAMESPACE);
336: if (attr) {
337: id = (char*)attr->children->content;
338: smart_str_appendc(&prefix, '#');
339: smart_str_appends(&prefix, id);
340: smart_str_0(&prefix);
341: id = prefix.c;
342: } else {
343: SOAP_GLOBAL(cur_uniq_ref)++;
344: smart_str_appendl(&prefix, "#ref", 4);
345: smart_str_append_long(&prefix, SOAP_GLOBAL(cur_uniq_ref));
346: smart_str_0(&prefix);
347: id = prefix.c;
348: set_ns_prop((*node_ptr), SOAP_1_2_ENC_NAMESPACE, "id", id+1);
349: }
350: set_ns_prop(node, SOAP_1_2_ENC_NAMESPACE, "ref", id);
351: }
352: smart_str_free(&prefix);
353: return 1;
354: } else {
355: zend_hash_index_update(SOAP_GLOBAL(ref_map), (ulong)data, (void**)&node, sizeof(xmlNodePtr), NULL);
356: }
357: }
358: return 0;
359: }
360:
361: static zval* soap_find_xml_ref(xmlNodePtr node TSRMLS_DC)
362: {
363: zval **data_ptr;
364:
365: if (SOAP_GLOBAL(ref_map) &&
366: zend_hash_index_find(SOAP_GLOBAL(ref_map), (ulong)node, (void**)&data_ptr) == SUCCESS) {
367: Z_SET_ISREF_PP(data_ptr);
368: Z_ADDREF_PP(data_ptr);
369: return *data_ptr;
370: }
371: return NULL;
372: }
373:
374: static zend_bool soap_check_xml_ref(zval **data, xmlNodePtr node TSRMLS_DC)
375: {
376: zval **data_ptr;
377:
378: if (SOAP_GLOBAL(ref_map)) {
379: if (zend_hash_index_find(SOAP_GLOBAL(ref_map), (ulong)node, (void**)&data_ptr) == SUCCESS) {
380: if (*data != *data_ptr) {
381: zval_ptr_dtor(data);
382: *data = *data_ptr;
383: Z_SET_ISREF_PP(data);
384: Z_ADDREF_PP(data);
385: return 1;
386: }
387: } else {
388: zend_hash_index_update(SOAP_GLOBAL(ref_map), (ulong)node, (void**)data, sizeof(zval*), NULL);
389: }
390: }
391: return 0;
392: }
393:
394: static xmlNodePtr master_to_xml_int(encodePtr encode, zval *data, int style, xmlNodePtr parent, int check_class_map)
395: {
396: xmlNodePtr node = NULL;
397: int add_type = 0;
398: TSRMLS_FETCH();
399:
400: /* Special handling of class SoapVar */
401: if (data &&
402: Z_TYPE_P(data) == IS_OBJECT &&
403: Z_OBJCE_P(data) == soap_var_class_entry) {
404: zval **ztype, **zdata, **zns, **zstype, **zname, **znamens;
405: encodePtr enc = NULL;
406: HashTable *ht = Z_OBJPROP_P(data);
407:
408: if (zend_hash_find(ht, "enc_type", sizeof("enc_type"), (void **)&ztype) == FAILURE) {
409: soap_error0(E_ERROR, "Encoding: SoapVar has no 'enc_type' property");
410: }
411:
412: if (zend_hash_find(ht, "enc_stype", sizeof("enc_stype"), (void **)&zstype) == SUCCESS) {
413: if (zend_hash_find(ht, "enc_ns", sizeof("enc_ns"), (void **)&zns) == SUCCESS) {
414: enc = get_encoder(SOAP_GLOBAL(sdl), Z_STRVAL_PP(zns), Z_STRVAL_PP(zstype));
415: } else {
416: zns = NULL;
417: enc = get_encoder_ex(SOAP_GLOBAL(sdl), Z_STRVAL_PP(zstype), Z_STRLEN_PP(zstype));
418: }
419: if (enc == NULL && SOAP_GLOBAL(typemap)) {
420: encodePtr *new_enc;
421: smart_str nscat = {0};
422:
423: if (zns != NULL) {
424: smart_str_appendl(&nscat, Z_STRVAL_PP(zns), Z_STRLEN_PP(zns));
425: smart_str_appendc(&nscat, ':');
426: }
427: smart_str_appendl(&nscat, Z_STRVAL_PP(zstype), Z_STRLEN_PP(zstype));
428: smart_str_0(&nscat);
429: if (zend_hash_find(SOAP_GLOBAL(typemap), nscat.c, nscat.len + 1, (void**)&new_enc) == SUCCESS) {
430: enc = *new_enc;
431: }
432: smart_str_free(&nscat);
433: }
434: }
435: if (enc == NULL) {
436: enc = get_conversion(Z_LVAL_P(*ztype));
437: }
438: if (enc == NULL) {
439: enc = encode;
440: }
441:
442: if (zend_hash_find(ht, "enc_value", sizeof("enc_value"), (void **)&zdata) == FAILURE) {
443: node = master_to_xml(enc, NULL, style, parent);
444: } else {
445: node = master_to_xml(enc, *zdata, style, parent);
446: }
447:
448: if (style == SOAP_ENCODED || (SOAP_GLOBAL(sdl) && encode != enc)) {
449: if (zend_hash_find(ht, "enc_stype", sizeof("enc_stype"), (void **)&zstype) == SUCCESS) {
450: if (zend_hash_find(ht, "enc_ns", sizeof("enc_ns"), (void **)&zns) == SUCCESS) {
451: set_ns_and_type_ex(node, Z_STRVAL_PP(zns), Z_STRVAL_PP(zstype));
452: } else {
453: set_ns_and_type_ex(node, NULL, Z_STRVAL_PP(zstype));
454: }
455: }
456: }
457:
458: if (zend_hash_find(ht, "enc_name", sizeof("enc_name"), (void **)&zname) == SUCCESS) {
459: xmlNodeSetName(node, BAD_CAST(Z_STRVAL_PP(zname)));
460: }
461: if (zend_hash_find(ht, "enc_namens", sizeof("enc_namens"), (void **)&znamens) == SUCCESS) {
462: xmlNsPtr nsp = encode_add_ns(node, Z_STRVAL_PP(znamens));
463: xmlSetNs(node, nsp);
464: }
465: } else {
466: if (check_class_map && SOAP_GLOBAL(class_map) && data &&
467: Z_TYPE_P(data) == IS_OBJECT &&
468: !Z_OBJPROP_P(data)->nApplyCount) {
469: zend_class_entry *ce = Z_OBJCE_P(data);
470: HashPosition pos;
471: zval **tmp;
472: char *type_name = NULL;
473: uint type_len;
474: ulong idx;
475:
476: for (zend_hash_internal_pointer_reset_ex(SOAP_GLOBAL(class_map), &pos);
477: zend_hash_get_current_data_ex(SOAP_GLOBAL(class_map), (void **) &tmp, &pos) == SUCCESS;
478: zend_hash_move_forward_ex(SOAP_GLOBAL(class_map), &pos)) {
479: if (Z_TYPE_PP(tmp) == IS_STRING &&
480: ce->name_length == Z_STRLEN_PP(tmp) &&
481: zend_binary_strncasecmp(ce->name, ce->name_length, Z_STRVAL_PP(tmp), ce->name_length, ce->name_length) == 0 &&
482: zend_hash_get_current_key_ex(SOAP_GLOBAL(class_map), &type_name, &type_len, &idx, 0, &pos) == HASH_KEY_IS_STRING) {
483:
484: /* TODO: namespace isn't stored */
485: encodePtr enc = NULL;
486: if (SOAP_GLOBAL(sdl)) {
487: enc = get_encoder(SOAP_GLOBAL(sdl), SOAP_GLOBAL(sdl)->target_ns, type_name);
488: if (!enc) {
489: enc = find_encoder_by_type_name(SOAP_GLOBAL(sdl), type_name);
490: }
491: }
492: if (enc) {
493: if (encode != enc && style == SOAP_LITERAL) {
494: add_type = 1;
495: }
496: encode = enc;
497: }
498: break;
499: }
500: }
501: }
502:
503: if (encode == NULL) {
504: encode = get_conversion(UNKNOWN_TYPE);
505: }
506: if (SOAP_GLOBAL(typemap) && encode->details.type_str) {
507: smart_str nscat = {0};
508: encodePtr *new_enc;
509:
510: if (encode->details.ns) {
511: smart_str_appends(&nscat, encode->details.ns);
512: smart_str_appendc(&nscat, ':');
513: }
514: smart_str_appends(&nscat, encode->details.type_str);
515: smart_str_0(&nscat);
516: if (zend_hash_find(SOAP_GLOBAL(typemap), nscat.c, nscat.len + 1, (void**)&new_enc) == SUCCESS) {
517: encode = *new_enc;
518: }
519: smart_str_free(&nscat);
520: }
521: if (encode->to_xml) {
522: node = encode->to_xml(&encode->details, data, style, parent);
523: if (add_type) {
524: set_ns_and_type(node, &encode->details);
525: }
526: }
527: }
528: return node;
529: }
530:
531: xmlNodePtr master_to_xml(encodePtr encode, zval *data, int style, xmlNodePtr parent)
532: {
533: return master_to_xml_int(encode, data, style, parent, 1);
534: }
535:
536: static zval *master_to_zval_int(encodePtr encode, xmlNodePtr data)
537: {
538: zval *ret = NULL;
539: TSRMLS_FETCH();
540:
541: if (SOAP_GLOBAL(typemap)) {
542: if (encode->details.type_str) {
543: smart_str nscat = {0};
544: encodePtr *new_enc;
545:
546: if (encode->details.ns) {
547: smart_str_appends(&nscat, encode->details.ns);
548: smart_str_appendc(&nscat, ':');
549: }
550: smart_str_appends(&nscat, encode->details.type_str);
551: smart_str_0(&nscat);
552: if (zend_hash_find(SOAP_GLOBAL(typemap), nscat.c, nscat.len + 1, (void**)&new_enc) == SUCCESS) {
553: encode = *new_enc;
554: }
555: smart_str_free(&nscat);
556: } else {
557: xmlAttrPtr type_attr = get_attribute_ex(data->properties,"type", XSI_NAMESPACE);
558:
559: if (type_attr != NULL) {
560: encodePtr *new_enc;
561: xmlNsPtr nsptr;
562: char *ns, *cptype;
563: smart_str nscat = {0};
564:
565: parse_namespace(type_attr->children->content, &cptype, &ns);
566: nsptr = xmlSearchNs(data->doc, data, BAD_CAST(ns));
567: if (nsptr != NULL) {
568: smart_str_appends(&nscat, (char*)nsptr->href);
569: smart_str_appendc(&nscat, ':');
570: }
571: smart_str_appends(&nscat, cptype);
572: smart_str_0(&nscat);
573: efree(cptype);
574: if (ns) {efree(ns);}
575: if (zend_hash_find(SOAP_GLOBAL(typemap), nscat.c, nscat.len + 1, (void**)&new_enc) == SUCCESS) {
576: encode = *new_enc;
577: }
578: smart_str_free(&nscat);
579: }
580: }
581: }
582: if (encode->to_zval) {
583: ret = encode->to_zval(&encode->details, data);
584: }
585: return ret;
586: }
587:
588: zval *master_to_zval(encodePtr encode, xmlNodePtr data)
589: {
590: TSRMLS_FETCH();
591: data = check_and_resolve_href(data);
592:
593: if (encode == NULL) {
594: encode = get_conversion(UNKNOWN_TYPE);
595: } else {
596: /* Use xsi:type if it is defined */
597: xmlAttrPtr type_attr = get_attribute_ex(data->properties,"type", XSI_NAMESPACE);
598:
599: if (type_attr != NULL) {
600: encodePtr enc = get_encoder_from_prefix(SOAP_GLOBAL(sdl), data, type_attr->children->content);
601:
602: if (enc != NULL && enc != encode) {
603: encodePtr tmp = enc;
604: while (tmp &&
605: tmp->details.sdl_type != NULL &&
606: tmp->details.sdl_type->kind != XSD_TYPEKIND_COMPLEX) {
607: if (enc == tmp->details.sdl_type->encode ||
608: tmp == tmp->details.sdl_type->encode) {
609: enc = NULL;
610: break;
611: }
612: tmp = tmp->details.sdl_type->encode;
613: }
614: if (enc != NULL) {
615: encode = enc;
616: }
617: }
618: }
619: }
620: return master_to_zval_int(encode, data);
621: }
622:
623: xmlNodePtr to_xml_user(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
624: {
625: xmlNodePtr ret = NULL;
626: zval *return_value;
627: TSRMLS_FETCH();
628:
629: if (type && type->map && type->map->to_xml) {
630: MAKE_STD_ZVAL(return_value);
631:
632: if (call_user_function(EG(function_table), NULL, type->map->to_xml, return_value, 1, &data TSRMLS_CC) == FAILURE) {
633: soap_error0(E_ERROR, "Encoding: Error calling to_xml callback");
634: }
635: if (Z_TYPE_P(return_value) == IS_STRING) {
636: xmlDocPtr doc = soap_xmlParseMemory(Z_STRVAL_P(return_value), Z_STRLEN_P(return_value));
637: if (doc && doc->children) {
638: ret = xmlDocCopyNode(doc->children, parent->doc, 1);
639: }
640: xmlFreeDoc(doc);
641: }
642:
643: zval_ptr_dtor(&return_value);
644: }
645: if (!ret) {
646: ret = xmlNewNode(NULL, BAD_CAST("BOGUS"));
647: }
648: xmlAddChild(parent, ret);
649: if (style == SOAP_ENCODED) {
650: set_ns_and_type(ret, type);
651: }
652: return ret;
653: }
654:
655: zval *to_zval_user(encodeTypePtr type, xmlNodePtr node)
656: {
657: zval *return_value;
658: TSRMLS_FETCH();
659:
660: if (type && type->map && type->map->to_zval) {
661: xmlBufferPtr buf;
662: zval *data;
663: xmlNodePtr copy;
664:
665: copy = xmlCopyNode(node, 1);
666: buf = xmlBufferCreate();
667: xmlNodeDump(buf, NULL, copy, 0, 0);
668: MAKE_STD_ZVAL(data);
669: ZVAL_STRING(data, (char*)xmlBufferContent(buf), 1);
670: xmlBufferFree(buf);
671: xmlFreeNode(copy);
672:
673: ALLOC_INIT_ZVAL(return_value);
674:
675: if (call_user_function(EG(function_table), NULL, type->map->to_zval, return_value, 1, &data TSRMLS_CC) == FAILURE) {
676: soap_error0(E_ERROR, "Encoding: Error calling from_xml callback");
677: }
678: zval_ptr_dtor(&data);
679: } else {
680: ALLOC_INIT_ZVAL(return_value);
681: }
682: return return_value;
683: }
684:
685: /* TODO: get rid of "bogus".. ither by passing in the already created xmlnode or passing in the node name */
686: /* String encode/decode */
687: static zval *to_zval_string(encodeTypePtr type, xmlNodePtr data)
688: {
689: zval *ret;
690: MAKE_STD_ZVAL(ret);
691: FIND_XML_NULL(data, ret);
692: if (data && data->children) {
693: if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
694: TSRMLS_FETCH();
695:
696: if (SOAP_GLOBAL(encoding) != NULL) {
697: xmlBufferPtr in = xmlBufferCreateStatic(data->children->content, xmlStrlen(data->children->content));
698: xmlBufferPtr out = xmlBufferCreate();
699: int n = xmlCharEncOutFunc(SOAP_GLOBAL(encoding), out, in);
700:
701: if (n >= 0) {
702: ZVAL_STRING(ret, (char*)xmlBufferContent(out), 1);
703: } else {
704: ZVAL_STRING(ret, (char*)data->children->content, 1);
705: }
706: xmlBufferFree(out);
707: xmlBufferFree(in);
708: } else {
709: ZVAL_STRING(ret, (char*)data->children->content, 1);
710: }
711: } else if (data->children->type == XML_CDATA_SECTION_NODE && data->children->next == NULL) {
712: ZVAL_STRING(ret, (char*)data->children->content, 1);
713: } else {
714: soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
715: }
716: } else {
717: ZVAL_EMPTY_STRING(ret);
718: }
719: return ret;
720: }
721:
722: static zval *to_zval_stringr(encodeTypePtr type, xmlNodePtr data)
723: {
724: zval *ret;
725: MAKE_STD_ZVAL(ret);
726: FIND_XML_NULL(data, ret);
727: if (data && data->children) {
728: if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
729: TSRMLS_FETCH();
730:
731: whiteSpace_replace(data->children->content);
732: if (SOAP_GLOBAL(encoding) != NULL) {
733: xmlBufferPtr in = xmlBufferCreateStatic(data->children->content, xmlStrlen(data->children->content));
734: xmlBufferPtr out = xmlBufferCreate();
735: int n = xmlCharEncOutFunc(SOAP_GLOBAL(encoding), out, in);
736:
737: if (n >= 0) {
738: ZVAL_STRING(ret, (char*)xmlBufferContent(out), 1);
739: } else {
740: ZVAL_STRING(ret, (char*)data->children->content, 1);
741: }
742: xmlBufferFree(out);
743: xmlBufferFree(in);
744: } else {
745: ZVAL_STRING(ret, (char*)data->children->content, 1);
746: }
747: } else if (data->children->type == XML_CDATA_SECTION_NODE && data->children->next == NULL) {
748: ZVAL_STRING(ret, (char*)data->children->content, 1);
749: } else {
750: soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
751: }
752: } else {
753: ZVAL_EMPTY_STRING(ret);
754: }
755: return ret;
756: }
757:
758: static zval *to_zval_stringc(encodeTypePtr type, xmlNodePtr data)
759: {
760: zval *ret;
761: MAKE_STD_ZVAL(ret);
762: FIND_XML_NULL(data, ret);
763: if (data && data->children) {
764: if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
765: TSRMLS_FETCH();
766:
767: whiteSpace_collapse(data->children->content);
768: if (SOAP_GLOBAL(encoding) != NULL) {
769: xmlBufferPtr in = xmlBufferCreateStatic(data->children->content, xmlStrlen(data->children->content));
770: xmlBufferPtr out = xmlBufferCreate();
771: int n = xmlCharEncOutFunc(SOAP_GLOBAL(encoding), out, in);
772:
773: if (n >= 0) {
774: ZVAL_STRING(ret, (char*)xmlBufferContent(out), 1);
775: } else {
776: ZVAL_STRING(ret, (char*)data->children->content, 1);
777: }
778: xmlBufferFree(out);
779: xmlBufferFree(in);
780: } else {
781: ZVAL_STRING(ret, (char*)data->children->content, 1);
782: }
783: } else if (data->children->type == XML_CDATA_SECTION_NODE && data->children->next == NULL) {
784: ZVAL_STRING(ret, (char*)data->children->content, 1);
785: } else {
786: soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
787: }
788: } else {
789: ZVAL_EMPTY_STRING(ret);
790: }
791: return ret;
792: }
793:
794: static zval *to_zval_base64(encodeTypePtr type, xmlNodePtr data)
795: {
796: zval *ret;
797: char *str;
798: int str_len;
799:
800: MAKE_STD_ZVAL(ret);
801: FIND_XML_NULL(data, ret);
802: if (data && data->children) {
803: if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
804: whiteSpace_collapse(data->children->content);
805: str = (char*)php_base64_decode(data->children->content, strlen((char*)data->children->content), &str_len);
806: if (!str) {
807: soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
808: }
809: ZVAL_STRINGL(ret, str, str_len, 0);
810: } else if (data->children->type == XML_CDATA_SECTION_NODE && data->children->next == NULL) {
811: str = (char*)php_base64_decode(data->children->content, strlen((char*)data->children->content), &str_len);
812: if (!str) {
813: soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
814: }
815: ZVAL_STRINGL(ret, str, str_len, 0);
816: } else {
817: soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
818: }
819: } else {
820: ZVAL_EMPTY_STRING(ret);
821: }
822: return ret;
823: }
824:
825: static zval *to_zval_hexbin(encodeTypePtr type, xmlNodePtr data)
826: {
827: zval *ret;
828: unsigned char *str;
829: int str_len, i, j;
830: unsigned char c;
831:
832: MAKE_STD_ZVAL(ret);
833: FIND_XML_NULL(data, ret);
834: if (data && data->children) {
835: if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
836: whiteSpace_collapse(data->children->content);
837: } else if (data->children->type != XML_CDATA_SECTION_NODE || data->children->next != NULL) {
838: soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
839: return ret;
840: }
841: str_len = strlen((char*)data->children->content) / 2;
842: str = emalloc(str_len+1);
843: for (i = j = 0; i < str_len; i++) {
844: c = data->children->content[j++];
845: if (c >= '0' && c <= '9') {
846: str[i] = (c - '0') << 4;
847: } else if (c >= 'a' && c <= 'f') {
848: str[i] = (c - 'a' + 10) << 4;
849: } else if (c >= 'A' && c <= 'F') {
850: str[i] = (c - 'A' + 10) << 4;
851: } else {
852: soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
853: }
854: c = data->children->content[j++];
855: if (c >= '0' && c <= '9') {
856: str[i] |= c - '0';
857: } else if (c >= 'a' && c <= 'f') {
858: str[i] |= c - 'a' + 10;
859: } else if (c >= 'A' && c <= 'F') {
860: str[i] |= c - 'A' + 10;
861: } else {
862: soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
863: }
864: }
865: str[str_len] = '\0';
866: ZVAL_STRINGL(ret, (char*)str, str_len, 0);
867: } else {
868: ZVAL_EMPTY_STRING(ret);
869: }
870: return ret;
871: }
872:
873: static xmlNodePtr to_xml_string(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
874: {
875: xmlNodePtr ret, text;
876: char *str;
877: int new_len;
878: TSRMLS_FETCH();
879:
880: ret = xmlNewNode(NULL, BAD_CAST("BOGUS"));
881: xmlAddChild(parent, ret);
882: FIND_ZVAL_NULL(data, ret, style);
883:
884: if (Z_TYPE_P(data) == IS_STRING) {
885: str = estrndup(Z_STRVAL_P(data), Z_STRLEN_P(data));
886: new_len = Z_STRLEN_P(data);
887: } else {
888: zval tmp = *data;
889:
890: zval_copy_ctor(&tmp);
891: convert_to_string(&tmp);
892: str = estrndup(Z_STRVAL(tmp), Z_STRLEN(tmp));
893: new_len = Z_STRLEN(tmp);
894: zval_dtor(&tmp);
895: }
896:
897: if (SOAP_GLOBAL(encoding) != NULL) {
898: xmlBufferPtr in = xmlBufferCreateStatic(str, new_len);
899: xmlBufferPtr out = xmlBufferCreate();
900: int n = xmlCharEncInFunc(SOAP_GLOBAL(encoding), out, in);
901:
902: if (n >= 0) {
903: efree(str);
904: str = estrdup((char*)xmlBufferContent(out));
905: new_len = n;
906: }
907: xmlBufferFree(out);
908: xmlBufferFree(in);
909: }
910:
911: if (!php_libxml_xmlCheckUTF8(BAD_CAST(str))) {
912: char *err = emalloc(new_len + 8);
913: char c;
914: int i;
915:
916: memcpy(err, str, new_len+1);
917: for (i = 0; (c = err[i++]);) {
918: if ((c & 0x80) == 0) {
919: } else if ((c & 0xe0) == 0xc0) {
920: if ((err[i] & 0xc0) != 0x80) {
921: break;
922: }
923: i++;
924: } else if ((c & 0xf0) == 0xe0) {
925: if ((err[i] & 0xc0) != 0x80 || (err[i+1] & 0xc0) != 0x80) {
926: break;
927: }
928: i += 2;
929: } else if ((c & 0xf8) == 0xf0) {
930: if ((err[i] & 0xc0) != 0x80 || (err[i+1] & 0xc0) != 0x80 || (err[i+2] & 0xc0) != 0x80) {
931: break;
932: }
933: i += 3;
934: } else {
935: break;
936: }
937: }
938: if (c) {
939: err[i-1] = '\\';
940: err[i++] = 'x';
941: err[i++] = ((unsigned char)c >> 4) + ((((unsigned char)c >> 4) > 9) ? ('a' - 10) : '0');
942: err[i++] = (c & 15) + (((c & 15) > 9) ? ('a' - 10) : '0');
943: err[i++] = '.';
944: err[i++] = '.';
945: err[i++] = '.';
946: err[i++] = 0;
947: }
948:
949: soap_error1(E_ERROR, "Encoding: string '%s' is not a valid utf-8 string", err);
950: }
951:
952: text = xmlNewTextLen(BAD_CAST(str), new_len);
953: xmlAddChild(ret, text);
954: efree(str);
955:
956: if (style == SOAP_ENCODED) {
957: set_ns_and_type(ret, type);
958: }
959: return ret;
960: }
961:
962: static xmlNodePtr to_xml_base64(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
963: {
964: xmlNodePtr ret, text;
965: unsigned char *str;
966: int str_len;
967:
968: ret = xmlNewNode(NULL, BAD_CAST("BOGUS"));
969: xmlAddChild(parent, ret);
970: FIND_ZVAL_NULL(data, ret, style);
971:
972: if (Z_TYPE_P(data) == IS_STRING) {
973: str = php_base64_encode((unsigned char*)Z_STRVAL_P(data), Z_STRLEN_P(data), &str_len);
974: text = xmlNewTextLen(str, str_len);
975: xmlAddChild(ret, text);
976: efree(str);
977: } else {
978: zval tmp = *data;
979:
980: zval_copy_ctor(&tmp);
981: convert_to_string(&tmp);
982: str = php_base64_encode((unsigned char*)Z_STRVAL(tmp), Z_STRLEN(tmp), &str_len);
983: text = xmlNewTextLen(str, str_len);
984: xmlAddChild(ret, text);
985: efree(str);
986: zval_dtor(&tmp);
987: }
988:
989: if (style == SOAP_ENCODED) {
990: set_ns_and_type(ret, type);
991: }
992: return ret;
993: }
994:
995: static xmlNodePtr to_xml_hexbin(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
996: {
997: static char hexconvtab[] = "0123456789ABCDEF";
998: xmlNodePtr ret, text;
999: unsigned char *str;
1000: zval tmp;
1001: int i, j;
1002:
1003: ret = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1004: xmlAddChild(parent, ret);
1005: FIND_ZVAL_NULL(data, ret, style);
1006:
1007: if (Z_TYPE_P(data) != IS_STRING) {
1008: tmp = *data;
1009: zval_copy_ctor(&tmp);
1010: convert_to_string(&tmp);
1011: data = &tmp;
1012: }
1013: str = (unsigned char *) safe_emalloc(Z_STRLEN_P(data) * 2, sizeof(char), 1);
1014:
1015: for (i = j = 0; i < Z_STRLEN_P(data); i++) {
1016: str[j++] = hexconvtab[((unsigned char)Z_STRVAL_P(data)[i]) >> 4];
1017: str[j++] = hexconvtab[((unsigned char)Z_STRVAL_P(data)[i]) & 15];
1018: }
1019: str[j] = '\0';
1020:
1021: text = xmlNewTextLen(str, Z_STRLEN_P(data) * 2 * sizeof(char));
1022: xmlAddChild(ret, text);
1023: efree(str);
1024: if (data == &tmp) {
1025: zval_dtor(&tmp);
1026: }
1027:
1028: if (style == SOAP_ENCODED) {
1029: set_ns_and_type(ret, type);
1030: }
1031: return ret;
1032: }
1033:
1034: static zval *to_zval_double(encodeTypePtr type, xmlNodePtr data)
1035: {
1036: zval *ret;
1037: MAKE_STD_ZVAL(ret);
1038: FIND_XML_NULL(data, ret);
1039:
1040: if (data && data->children) {
1041: if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
1042: long lval;
1043: double dval;
1044:
1045: whiteSpace_collapse(data->children->content);
1046: switch (is_numeric_string((char*)data->children->content, strlen((char*)data->children->content), &lval, &dval, 0)) {
1047: case IS_LONG:
1048: Z_TYPE_P(ret) = IS_DOUBLE;
1049: Z_DVAL_P(ret) = lval;
1050: break;
1051: case IS_DOUBLE:
1052: Z_TYPE_P(ret) = IS_DOUBLE;
1053: Z_DVAL_P(ret) = dval;
1054: break;
1055: default:
1056: if (strncasecmp((char*)data->children->content, "NaN", sizeof("NaN")-1) == 0) {
1057: ZVAL_DOUBLE(ret, php_get_nan());
1058: } else if (strncasecmp((char*)data->children->content, "INF", sizeof("INF")-1) == 0) {
1059: ZVAL_DOUBLE(ret, php_get_inf());
1060: } else if (strncasecmp((char*)data->children->content, "-INF", sizeof("-INF")-1) == 0) {
1061: ZVAL_DOUBLE(ret, -php_get_inf());
1062: } else {
1063: soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
1064: }
1065: }
1066: } else {
1067: soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
1068: }
1069: } else {
1070: ZVAL_NULL(ret);
1071: }
1072: return ret;
1073: }
1074:
1075: static zval *to_zval_long(encodeTypePtr type, xmlNodePtr data)
1076: {
1077: zval *ret;
1078: MAKE_STD_ZVAL(ret);
1079: FIND_XML_NULL(data, ret);
1080:
1081: if (data && data->children) {
1082: if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
1083: long lval;
1084: double dval;
1085:
1086: whiteSpace_collapse(data->children->content);
1087: errno = 0;
1088:
1089: switch ((Z_TYPE_P(ret) = is_numeric_string((char*)data->children->content, strlen((char*)data->children->content), &lval, &dval, 0))) {
1090: case IS_LONG:
1091: Z_LVAL_P(ret) = lval;
1092: break;
1093: case IS_DOUBLE:
1094: Z_DVAL_P(ret) = dval;
1095: break;
1096: default:
1097: soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
1098: }
1099: } else {
1100: soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
1101: }
1102: } else {
1103: ZVAL_NULL(ret);
1104: }
1105: return ret;
1106: }
1107:
1108: static xmlNodePtr to_xml_long(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
1109: {
1110: xmlNodePtr ret;
1111:
1112: ret = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1113: xmlAddChild(parent, ret);
1114: FIND_ZVAL_NULL(data, ret, style);
1115:
1116: if (Z_TYPE_P(data) == IS_DOUBLE) {
1117: char s[256];
1118:
1119: snprintf(s, sizeof(s), "%0.0F",floor(Z_DVAL_P(data)));
1120: xmlNodeSetContent(ret, BAD_CAST(s));
1121: } else {
1122: zval tmp = *data;
1123:
1124: zval_copy_ctor(&tmp);
1125: if (Z_TYPE(tmp) != IS_LONG) {
1126: convert_to_long(&tmp);
1127: }
1128: convert_to_string(&tmp);
1129: xmlNodeSetContentLen(ret, BAD_CAST(Z_STRVAL(tmp)), Z_STRLEN(tmp));
1130: zval_dtor(&tmp);
1131: }
1132:
1133: if (style == SOAP_ENCODED) {
1134: set_ns_and_type(ret, type);
1135: }
1136: return ret;
1137: }
1138:
1139: static xmlNodePtr to_xml_double(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
1140: {
1141: xmlNodePtr ret;
1142: zval tmp;
1143: char *str;
1144: TSRMLS_FETCH();
1145:
1146: ret = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1147: xmlAddChild(parent, ret);
1148: FIND_ZVAL_NULL(data, ret, style);
1149:
1150: tmp = *data;
1151: if (Z_TYPE(tmp) != IS_DOUBLE) {
1152: zval_copy_ctor(&tmp);
1153: convert_to_double(&tmp);
1154: }
1155:
1156: str = (char *) safe_emalloc(EG(precision), 1, MAX_LENGTH_OF_DOUBLE + 1);
1157: php_gcvt(Z_DVAL(tmp), EG(precision), '.', 'E', str);
1158: xmlNodeSetContentLen(ret, BAD_CAST(str), strlen(str));
1159: efree(str);
1160:
1161: if (style == SOAP_ENCODED) {
1162: set_ns_and_type(ret, type);
1163: }
1164: return ret;
1165: }
1166:
1167: static zval *to_zval_bool(encodeTypePtr type, xmlNodePtr data)
1168: {
1169: zval *ret;
1170: MAKE_STD_ZVAL(ret);
1171: FIND_XML_NULL(data, ret);
1172:
1173: if (data && data->children) {
1174: if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
1175: whiteSpace_collapse(data->children->content);
1176: if (stricmp((char*)data->children->content, "true") == 0 ||
1177: stricmp((char*)data->children->content, "t") == 0 ||
1178: strcmp((char*)data->children->content, "1") == 0) {
1179: ZVAL_BOOL(ret, 1);
1180: } else if (stricmp((char*)data->children->content, "false") == 0 ||
1181: stricmp((char*)data->children->content, "f") == 0 ||
1182: strcmp((char*)data->children->content, "0") == 0) {
1183: ZVAL_BOOL(ret, 0);
1184: } else {
1185: ZVAL_STRING(ret, (char*)data->children->content, 1);
1186: convert_to_boolean(ret);
1187: }
1188: } else {
1189: soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
1190: }
1191: } else {
1192: ZVAL_NULL(ret);
1193: }
1194: return ret;
1195: }
1196:
1197: static xmlNodePtr to_xml_bool(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
1198: {
1199: xmlNodePtr ret;
1200:
1201: ret = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1202: xmlAddChild(parent, ret);
1203: FIND_ZVAL_NULL(data, ret, style);
1204:
1205: if (zend_is_true(data)) {
1206: xmlNodeSetContent(ret, BAD_CAST("true"));
1207: } else {
1208: xmlNodeSetContent(ret, BAD_CAST("false"));
1209: }
1210:
1211: if (style == SOAP_ENCODED) {
1212: set_ns_and_type(ret, type);
1213: }
1214: return ret;
1215: }
1216:
1217: /* Null encode/decode */
1218: static zval *to_zval_null(encodeTypePtr type, xmlNodePtr data)
1219: {
1220: zval *ret;
1221: MAKE_STD_ZVAL(ret);
1222: ZVAL_NULL(ret);
1223: return ret;
1224: }
1225:
1226: static xmlNodePtr to_xml_null(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
1227: {
1228: xmlNodePtr ret;
1229:
1230: ret = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1231: xmlAddChild(parent, ret);
1232: if (style == SOAP_ENCODED) {
1233: set_xsi_nil(ret);
1234: }
1235: return ret;
1236: }
1237:
1238: static void set_zval_property(zval* object, char* name, zval* val TSRMLS_DC)
1239: {
1240: zend_class_entry *old_scope;
1241:
1242: old_scope = EG(scope);
1243: EG(scope) = Z_OBJCE_P(object);
1244: #ifdef ZEND_ENGINE_2
1245: Z_DELREF_P(val);
1246: #endif
1247: add_property_zval(object, name, val);
1248: EG(scope) = old_scope;
1249: }
1250:
1251: static zval* get_zval_property(zval* object, char* name TSRMLS_DC)
1252: {
1253: if (Z_TYPE_P(object) == IS_OBJECT) {
1254: zval member;
1255: zval *data;
1256: zend_class_entry *old_scope;
1257:
1258: INIT_PZVAL(&member);
1259: ZVAL_STRING(&member, name, 0);
1260: old_scope = EG(scope);
1261: EG(scope) = Z_OBJCE_P(object);
1262: data = Z_OBJ_HT_P(object)->read_property(object, &member, BP_VAR_IS TSRMLS_CC);
1263: if (data == EG(uninitialized_zval_ptr)) {
1264: /* Hack for bug #32455 */
1265: zend_property_info *property_info;
1266:
1267: property_info = zend_get_property_info(Z_OBJCE_P(object), &member, 1 TSRMLS_CC);
1268: EG(scope) = old_scope;
1269: if (property_info && zend_hash_quick_exists(Z_OBJPROP_P(object), property_info->name, property_info->name_length+1, property_info->h)) {
1270: return data;
1271: }
1272: return NULL;
1273: }
1274: EG(scope) = old_scope;
1275: return data;
1276: } else if (Z_TYPE_P(object) == IS_ARRAY) {
1277: zval **data_ptr;
1278:
1279: if (zend_hash_find(Z_ARRVAL_P(object), name, strlen(name)+1, (void**)&data_ptr) == SUCCESS) {
1280: return *data_ptr;
1281: }
1282: }
1283: return NULL;
1284: }
1285:
1286: static void unset_zval_property(zval* object, char* name TSRMLS_DC)
1287: {
1288: if (Z_TYPE_P(object) == IS_OBJECT) {
1289: zval member;
1290: zend_class_entry *old_scope;
1291:
1292: INIT_PZVAL(&member);
1293: ZVAL_STRING(&member, name, 0);
1294: old_scope = EG(scope);
1295: EG(scope) = Z_OBJCE_P(object);
1296: Z_OBJ_HT_P(object)->unset_property(object, &member TSRMLS_CC);
1297: EG(scope) = old_scope;
1298: } else if (Z_TYPE_P(object) == IS_ARRAY) {
1299: zend_hash_del(Z_ARRVAL_P(object), name, strlen(name)+1);
1300: }
1301: }
1302:
1303: static void model_to_zval_any(zval *ret, xmlNodePtr node TSRMLS_DC)
1304: {
1305: zval* any = NULL;
1306: char* name = NULL;
1307:
1308: while (node != NULL) {
1309: if (get_zval_property(ret, (char*)node->name TSRMLS_CC) == NULL) {
1310: zval* val = master_to_zval(get_conversion(XSD_ANYXML), node);
1311:
1312: if (any && Z_TYPE_P(any) != IS_ARRAY) {
1313: /* Convert into array */
1314: zval *arr;
1315:
1316: MAKE_STD_ZVAL(arr);
1317: array_init(arr);
1318: if (name) {
1319: add_assoc_zval(arr, name, any);
1320: } else {
1321: add_next_index_zval(arr, any);
1322: }
1323: any = arr;
1324: }
1325:
1326: if (Z_TYPE_P(val) == IS_STRING && *Z_STRVAL_P(val) == '<') {
1327: name = NULL;
1328: while (node->next != NULL) {
1329: zval* val2 = master_to_zval(get_conversion(XSD_ANYXML), node->next);
1330: if (Z_TYPE_P(val2) != IS_STRING || *Z_STRVAL_P(val) != '<') {
1331: break;
1332: }
1333: add_string_to_string(val, val, val2);
1334: zval_ptr_dtor(&val2);
1335: node = node->next;
1336: }
1337: } else {
1338: name = (char*)node->name;
1339: }
1340:
1341: if (any == NULL) {
1342: if (name) {
1343: /* Convert into array */
1344: zval *arr;
1345:
1346: MAKE_STD_ZVAL(arr);
1347: array_init(arr);
1348: add_assoc_zval(arr, name, val);
1349: any = arr;
1350: name = NULL;
1351: } else {
1352: any = val;
1353: }
1354: } else {
1355: /* Add array element */
1356: if (name) {
1357: zval **el;
1358: if (zend_hash_find(Z_ARRVAL_P(any), name, strlen(name)+1, (void**)&el) == SUCCESS) {
1359: if (Z_TYPE_PP(el) != IS_ARRAY) {
1360: /* Convert into array */
1361: zval *arr;
1362:
1363: MAKE_STD_ZVAL(arr);
1364: array_init(arr);
1365: add_next_index_zval(arr, *el);
1366: *el = arr;
1367: }
1368: add_next_index_zval(*el, val);
1369: } else {
1370: add_assoc_zval(any, name, val);
1371: }
1372: } else {
1373: add_next_index_zval(any, val);
1374: }
1375: name = NULL;
1376: }
1377: }
1378: node = node->next;
1379: }
1380: if (any) {
1381: set_zval_property(ret, name ? name : "any", any TSRMLS_CC);
1382: }
1383: }
1384:
1385: static void model_to_zval_object(zval *ret, sdlContentModelPtr model, xmlNodePtr data, sdlPtr sdl TSRMLS_DC)
1386: {
1387: switch (model->kind) {
1388: case XSD_CONTENT_ELEMENT:
1389: if (model->u.element->name) {
1390: xmlNodePtr node = get_node(data->children, model->u.element->name);
1391:
1392: if (node) {
1393: zval *val;
1394: xmlNodePtr r_node;
1395:
1396: r_node = check_and_resolve_href(node);
1397: if (r_node && r_node->children && r_node->children->content) {
1398: if (model->u.element->fixed && strcmp(model->u.element->fixed, (char*)r_node->children->content) != 0) {
1399: soap_error3(E_ERROR, "Encoding: Element '%s' has fixed value '%s' (value '%s' is not allowed)", model->u.element->name, model->u.element->fixed, r_node->children->content);
1400: }
1401: val = master_to_zval(model->u.element->encode, r_node);
1402: } else if (model->u.element->fixed) {
1403: xmlNodePtr dummy = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1404: xmlNodeSetContent(dummy, BAD_CAST(model->u.element->fixed));
1405: val = master_to_zval(model->u.element->encode, dummy);
1406: xmlFreeNode(dummy);
1407: } else if (model->u.element->def && !model->u.element->nillable) {
1408: xmlNodePtr dummy = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1409: xmlNodeSetContent(dummy, BAD_CAST(model->u.element->def));
1410: val = master_to_zval(model->u.element->encode, dummy);
1411: xmlFreeNode(dummy);
1412: } else {
1413: val = master_to_zval(model->u.element->encode, r_node);
1414: }
1415: if ((node = get_node(node->next, model->u.element->name)) != NULL) {
1416: zval *array;
1417:
1418: MAKE_STD_ZVAL(array);
1419: array_init(array);
1420: add_next_index_zval(array, val);
1421: do {
1422: if (node && node->children && node->children->content) {
1423: if (model->u.element->fixed && strcmp(model->u.element->fixed, (char*)node->children->content) != 0) {
1424: soap_error3(E_ERROR, "Encoding: Element '%s' has fixed value '%s' (value '%s' is not allowed)", model->u.element->name, model->u.element->fixed, node->children->content);
1425: }
1426: val = master_to_zval(model->u.element->encode, node);
1427: } else if (model->u.element->fixed) {
1428: xmlNodePtr dummy = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1429: xmlNodeSetContent(dummy, BAD_CAST(model->u.element->fixed));
1430: val = master_to_zval(model->u.element->encode, dummy);
1431: xmlFreeNode(dummy);
1432: } else if (model->u.element->def && !model->u.element->nillable) {
1433: xmlNodePtr dummy = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1434: xmlNodeSetContent(dummy, BAD_CAST(model->u.element->def));
1435: val = master_to_zval(model->u.element->encode, dummy);
1436: xmlFreeNode(dummy);
1437: } else {
1438: val = master_to_zval(model->u.element->encode, node);
1439: }
1440: add_next_index_zval(array, val);
1441: } while ((node = get_node(node->next, model->u.element->name)) != NULL);
1442: val = array;
1443: } else if ((Z_TYPE_P(val) != IS_NULL || !model->u.element->nillable) &&
1444: (SOAP_GLOBAL(features) & SOAP_SINGLE_ELEMENT_ARRAYS) &&
1445: (model->max_occurs == -1 || model->max_occurs > 1)) {
1446: zval *array;
1447:
1448: MAKE_STD_ZVAL(array);
1449: array_init(array);
1450: add_next_index_zval(array, val);
1451: val = array;
1452: }
1453: set_zval_property(ret, model->u.element->name, val TSRMLS_CC);
1454: }
1455: }
1456: break;
1457: case XSD_CONTENT_ALL:
1458: case XSD_CONTENT_SEQUENCE:
1459: case XSD_CONTENT_CHOICE: {
1460: sdlContentModelPtr *tmp;
1461: HashPosition pos;
1462: sdlContentModelPtr any = NULL;
1463:
1464: zend_hash_internal_pointer_reset_ex(model->u.content, &pos);
1465: while (zend_hash_get_current_data_ex(model->u.content, (void**)&tmp, &pos) == SUCCESS) {
1466: if ((*tmp)->kind == XSD_CONTENT_ANY) {
1467: any = *tmp;
1468: } else {
1469: model_to_zval_object(ret, *tmp, data, sdl TSRMLS_CC);
1470: }
1471: zend_hash_move_forward_ex(model->u.content, &pos);
1472: }
1473: if (any) {
1474: model_to_zval_any(ret, data->children TSRMLS_CC);
1475: }
1476: break;
1477: }
1478: case XSD_CONTENT_GROUP:
1479: model_to_zval_object(ret, model->u.group->model, data, sdl TSRMLS_CC);
1480: break;
1481: default:
1482: break;
1483: }
1484: }
1485:
1486: /* Struct encode/decode */
1487: static zval *to_zval_object_ex(encodeTypePtr type, xmlNodePtr data, zend_class_entry *pce)
1488: {
1489: zval *ret;
1490: xmlNodePtr trav;
1491: sdlPtr sdl;
1492: sdlTypePtr sdlType = type->sdl_type;
1493: zend_class_entry *ce = ZEND_STANDARD_CLASS_DEF_PTR;
1494: zval *redo_any = NULL;
1495: TSRMLS_FETCH();
1496:
1497: if (pce) {
1498: ce = pce;
1499: } else if (SOAP_GLOBAL(class_map) && type->type_str) {
1500: zval **classname;
1501: zend_class_entry *tmp;
1502:
1503: if (zend_hash_find(SOAP_GLOBAL(class_map), type->type_str, strlen(type->type_str)+1, (void**)&classname) == SUCCESS &&
1504: Z_TYPE_PP(classname) == IS_STRING &&
1505: (tmp = zend_fetch_class(Z_STRVAL_PP(classname), Z_STRLEN_PP(classname), ZEND_FETCH_CLASS_AUTO TSRMLS_CC)) != NULL) {
1506: ce = tmp;
1507: }
1508: }
1509: sdl = SOAP_GLOBAL(sdl);
1510: if (sdlType) {
1511: if (sdlType->kind == XSD_TYPEKIND_RESTRICTION &&
1512: sdlType->encode && type != &sdlType->encode->details) {
1513: encodePtr enc;
1514:
1515: enc = sdlType->encode;
1516: while (enc && enc->details.sdl_type &&
1517: enc->details.sdl_type->kind != XSD_TYPEKIND_SIMPLE &&
1518: enc->details.sdl_type->kind != XSD_TYPEKIND_LIST &&
1519: enc->details.sdl_type->kind != XSD_TYPEKIND_UNION) {
1520: enc = enc->details.sdl_type->encode;
1521: }
1522: if (enc) {
1523: zval *base;
1524:
1525: ALLOC_INIT_ZVAL(ret);
1526: if (soap_check_xml_ref(&ret, data TSRMLS_CC)) {
1527: return ret;
1528: }
1529:
1530: object_init_ex(ret, ce);
1531: base = master_to_zval_int(enc, data);
1532: set_zval_property(ret, "_", base TSRMLS_CC);
1533: } else {
1534: ALLOC_INIT_ZVAL(ret);
1535: FIND_XML_NULL(data, ret);
1536: if (soap_check_xml_ref(&ret, data TSRMLS_CC)) {
1537: return ret;
1538: }
1539: object_init_ex(ret, ce);
1540: }
1541: } else if (sdlType->kind == XSD_TYPEKIND_EXTENSION &&
1542: sdlType->encode &&
1543: type != &sdlType->encode->details) {
1544: if (sdlType->encode->details.sdl_type &&
1545: sdlType->encode->details.sdl_type->kind != XSD_TYPEKIND_SIMPLE &&
1546: sdlType->encode->details.sdl_type->kind != XSD_TYPEKIND_LIST &&
1547: sdlType->encode->details.sdl_type->kind != XSD_TYPEKIND_UNION) {
1548:
1549: CHECK_XML_NULL(data);
1550: if ((ret = soap_find_xml_ref(data TSRMLS_CC)) != NULL) {
1551: return ret;
1552: }
1553:
1554: if (ce != ZEND_STANDARD_CLASS_DEF_PTR &&
1555: sdlType->encode->to_zval == sdl_guess_convert_zval &&
1556: sdlType->encode->details.sdl_type != NULL &&
1557: (sdlType->encode->details.sdl_type->kind == XSD_TYPEKIND_COMPLEX ||
1558: sdlType->encode->details.sdl_type->kind == XSD_TYPEKIND_RESTRICTION ||
1559: sdlType->encode->details.sdl_type->kind == XSD_TYPEKIND_EXTENSION) &&
1560: (sdlType->encode->details.sdl_type->encode == NULL ||
1561: (sdlType->encode->details.sdl_type->encode->details.type != IS_ARRAY &&
1562: sdlType->encode->details.sdl_type->encode->details.type != SOAP_ENC_ARRAY))) {
1563: ret = to_zval_object_ex(&sdlType->encode->details, data, ce);
1564: } else {
1565: ret = master_to_zval_int(sdlType->encode, data);
1566: }
1567: if (soap_check_xml_ref(&ret, data TSRMLS_CC)) {
1568: return ret;
1569: }
1570: redo_any = get_zval_property(ret, "any" TSRMLS_CC);
1571: if (Z_TYPE_P(ret) == IS_OBJECT && ce != ZEND_STANDARD_CLASS_DEF_PTR) {
1572: zend_object *zobj = zend_objects_get_address(ret TSRMLS_CC);
1573: zobj->ce = ce;
1574: }
1575: } else {
1576: zval *base;
1577:
1578: ALLOC_INIT_ZVAL(ret);
1579: if (soap_check_xml_ref(&ret, data TSRMLS_CC)) {
1580: return ret;
1581: }
1582:
1583: object_init_ex(ret, ce);
1584: base = master_to_zval_int(sdlType->encode, data);
1585: set_zval_property(ret, "_", base TSRMLS_CC);
1586: }
1587: } else {
1588: ALLOC_INIT_ZVAL(ret);
1589: FIND_XML_NULL(data, ret);
1590: if (soap_check_xml_ref(&ret, data TSRMLS_CC)) {
1591: return ret;
1592: }
1593: object_init_ex(ret, ce);
1594: }
1595: if (sdlType->model) {
1596: if (redo_any) {
1597: Z_ADDREF_P(redo_any);
1598: unset_zval_property(ret, "any" TSRMLS_CC);
1599: }
1600: model_to_zval_object(ret, sdlType->model, data, sdl TSRMLS_CC);
1601: if (redo_any) {
1602: zval *tmp = get_zval_property(ret, "any" TSRMLS_CC);
1603:
1604: if (tmp == NULL) {
1605: model_to_zval_any(ret, data->children TSRMLS_CC);
1606: } else if (Z_REFCOUNT_P(tmp) == 0) {
1607: zval_dtor(tmp);
1608: efree(tmp);
1609: }
1610: zval_ptr_dtor(&redo_any);
1611: }
1612: }
1613: if (sdlType->attributes) {
1614: sdlAttributePtr *attr;
1615: HashPosition pos;
1616:
1617: zend_hash_internal_pointer_reset_ex(sdlType->attributes, &pos);
1618: while (zend_hash_get_current_data_ex(sdlType->attributes, (void**)&attr, &pos) == SUCCESS) {
1619: if ((*attr)->name) {
1620: xmlAttrPtr val = get_attribute(data->properties, (*attr)->name);
1621: char *str_val = NULL;
1622:
1623: if (val && val->children && val->children->content) {
1624: str_val = (char*)val->children->content;
1625: if ((*attr)->fixed && strcmp((*attr)->fixed, str_val) != 0) {
1626: soap_error3(E_ERROR, "Encoding: Attribute '%s' has fixed value '%s' (value '%s' is not allowed)", (*attr)->name, (*attr)->fixed, str_val);
1627: }
1628: } else if ((*attr)->fixed) {
1629: str_val = (*attr)->fixed;
1630: } else if ((*attr)->def) {
1631: str_val = (*attr)->def;
1632: }
1633: if (str_val) {
1634: xmlNodePtr dummy, text;
1635: zval *data;
1636:
1637: dummy = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1638: text = xmlNewText(BAD_CAST(str_val));
1639: xmlAddChild(dummy, text);
1640: data = master_to_zval((*attr)->encode, dummy);
1641: xmlFreeNode(dummy);
1642: set_zval_property(ret, (*attr)->name, data TSRMLS_CC);
1643: }
1644: }
1645: zend_hash_move_forward_ex(sdlType->attributes, &pos);
1646: }
1647: }
1648: } else {
1649:
1650: ALLOC_INIT_ZVAL(ret);
1651: FIND_XML_NULL(data, ret);
1652: if (soap_check_xml_ref(&ret, data TSRMLS_CC)) {
1653: return ret;
1654: }
1655:
1656: object_init_ex(ret, ce);
1657: trav = data->children;
1658:
1659: while (trav != NULL) {
1660: if (trav->type == XML_ELEMENT_NODE) {
1661: zval *tmpVal;
1662: zval *prop;
1663:
1664: tmpVal = master_to_zval(NULL, trav);
1665:
1666: prop = get_zval_property(ret, (char*)trav->name TSRMLS_CC);
1667: if (!prop) {
1668: if (!trav->next || !get_node(trav->next, (char*)trav->name)) {
1669: set_zval_property(ret, (char*)trav->name, tmpVal TSRMLS_CC);
1670: } else {
1671: zval *arr;
1672:
1673: MAKE_STD_ZVAL(arr);
1674: array_init(arr);
1675: add_next_index_zval(arr, tmpVal);
1676: set_zval_property(ret, (char*)trav->name, arr TSRMLS_CC);
1677: }
1678: } else {
1679: /* Property already exist - make array */
1680: if (Z_TYPE_P(prop) != IS_ARRAY) {
1681: /* Convert into array */
1682: zval *arr;
1683:
1684: MAKE_STD_ZVAL(arr);
1685: array_init(arr);
1686: Z_ADDREF_P(prop);
1687: add_next_index_zval(arr, prop);
1688: set_zval_property(ret, (char*)trav->name, arr TSRMLS_CC);
1689: prop = arr;
1690: }
1691: /* Add array element */
1692: add_next_index_zval(prop, tmpVal);
1693: }
1694: }
1695: trav = trav->next;
1696: }
1697: }
1698: return ret;
1699: }
1700:
1701: static zval *to_zval_object(encodeTypePtr type, xmlNodePtr data)
1702: {
1703: return to_zval_object_ex(type, data, NULL);
1704: }
1705:
1706:
1707: static int model_to_xml_object(xmlNodePtr node, sdlContentModelPtr model, zval *object, int style, int strict TSRMLS_DC)
1708: {
1709: switch (model->kind) {
1710: case XSD_CONTENT_ELEMENT: {
1711: zval *data;
1712: xmlNodePtr property;
1713: encodePtr enc;
1714:
1715: data = get_zval_property(object, model->u.element->name TSRMLS_CC);
1716: if (data &&
1717: Z_TYPE_P(data) == IS_NULL &&
1718: !model->u.element->nillable &&
1719: model->min_occurs > 0 &&
1720: !strict) {
1721: return 0;
1722: }
1723: if (data) {
1724: enc = model->u.element->encode;
1725: if ((model->max_occurs == -1 || model->max_occurs > 1) &&
1726: Z_TYPE_P(data) == IS_ARRAY &&
1727: !is_map(data)) {
1728: HashTable *ht = Z_ARRVAL_P(data);
1729: zval **val;
1730:
1731: zend_hash_internal_pointer_reset(ht);
1732: while (zend_hash_get_current_data(ht,(void**)&val) == SUCCESS) {
1733: if (Z_TYPE_PP(val) == IS_NULL && model->u.element->nillable) {
1734: property = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1735: xmlAddChild(node, property);
1736: set_xsi_nil(property);
1737: } else {
1738: property = master_to_xml(enc, *val, style, node);
1739: if (property->children && property->children->content &&
1740: model->u.element->fixed && strcmp(model->u.element->fixed, (char*)property->children->content) != 0) {
1741: soap_error3(E_ERROR, "Encoding: Element '%s' has fixed value '%s' (value '%s' is not allowed)", model->u.element->name, model->u.element->fixed, property->children->content);
1742: }
1743: }
1744: xmlNodeSetName(property, BAD_CAST(model->u.element->name));
1745: if (style == SOAP_LITERAL &&
1746: model->u.element->namens &&
1747: model->u.element->form == XSD_FORM_QUALIFIED) {
1748: xmlNsPtr nsp = encode_add_ns(property, model->u.element->namens);
1749: xmlSetNs(property, nsp);
1750: }
1751: zend_hash_move_forward(ht);
1752: }
1753: } else {
1754: if (Z_TYPE_P(data) == IS_NULL && model->u.element->nillable) {
1755: property = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1756: xmlAddChild(node, property);
1757: set_xsi_nil(property);
1758: } else if (Z_TYPE_P(data) == IS_NULL && model->min_occurs == 0) {
1759: return 1;
1760: } else {
1761: property = master_to_xml(enc, data, style, node);
1762: if (property->children && property->children->content &&
1763: model->u.element->fixed && strcmp(model->u.element->fixed, (char*)property->children->content) != 0) {
1764: soap_error3(E_ERROR, "Encoding: Element '%s' has fixed value '%s' (value '%s' is not allowed)", model->u.element->name, model->u.element->fixed, property->children->content);
1765: }
1766: }
1767: xmlNodeSetName(property, BAD_CAST(model->u.element->name));
1768: if (style == SOAP_LITERAL &&
1769: model->u.element->namens &&
1770: model->u.element->form == XSD_FORM_QUALIFIED) {
1771: xmlNsPtr nsp = encode_add_ns(property, model->u.element->namens);
1772: xmlSetNs(property, nsp);
1773: }
1774: }
1775: return 1;
1776: } else if (strict && model->u.element->nillable && model->min_occurs > 0) {
1777: property = xmlNewNode(NULL, BAD_CAST(model->u.element->name));
1778: xmlAddChild(node, property);
1779: set_xsi_nil(property);
1780: if (style == SOAP_LITERAL &&
1781: model->u.element->namens &&
1782: model->u.element->form == XSD_FORM_QUALIFIED) {
1783: xmlNsPtr nsp = encode_add_ns(property, model->u.element->namens);
1784: xmlSetNs(property, nsp);
1785: }
1786: return 1;
1787: } else if (model->min_occurs == 0) {
1788: return 2;
1789: } else {
1790: if (strict) {
1791: soap_error1(E_ERROR, "Encoding: object has no '%s' property", model->u.element->name);
1792: }
1793: return 0;
1794: }
1795: break;
1796: }
1797: case XSD_CONTENT_ANY: {
1798: zval *data;
1799: xmlNodePtr property;
1800: encodePtr enc;
1801:
1802: data = get_zval_property(object, "any" TSRMLS_CC);
1803: if (data) {
1804: enc = get_conversion(XSD_ANYXML);
1805: if ((model->max_occurs == -1 || model->max_occurs > 1) &&
1806: Z_TYPE_P(data) == IS_ARRAY &&
1807: !is_map(data)) {
1808: HashTable *ht = Z_ARRVAL_P(data);
1809: zval **val;
1810:
1811: zend_hash_internal_pointer_reset(ht);
1812: while (zend_hash_get_current_data(ht,(void**)&val) == SUCCESS) {
1813: property = master_to_xml(enc, *val, style, node);
1814: zend_hash_move_forward(ht);
1815: }
1816: } else {
1817: property = master_to_xml(enc, data, style, node);
1818: }
1819: return 1;
1820: } else if (model->min_occurs == 0) {
1821: return 2;
1822: } else {
1823: if (strict) {
1824: soap_error0(E_ERROR, "Encoding: object has no 'any' property");
1825: }
1826: return 0;
1827: }
1828: break;
1829: }
1830: case XSD_CONTENT_SEQUENCE:
1831: case XSD_CONTENT_ALL: {
1832: sdlContentModelPtr *tmp;
1833: HashPosition pos;
1834:
1835: zend_hash_internal_pointer_reset_ex(model->u.content, &pos);
1836: while (zend_hash_get_current_data_ex(model->u.content, (void**)&tmp, &pos) == SUCCESS) {
1837: if (!model_to_xml_object(node, *tmp, object, style, (*tmp)->min_occurs > 0 TSRMLS_CC)) {
1838: if ((*tmp)->min_occurs > 0) {
1839: return 0;
1840: }
1841: }
1842: zend_hash_move_forward_ex(model->u.content, &pos);
1843: }
1844: return 1;
1845: }
1846: case XSD_CONTENT_CHOICE: {
1847: sdlContentModelPtr *tmp;
1848: HashPosition pos;
1849: int ret = 0;
1850:
1851: zend_hash_internal_pointer_reset_ex(model->u.content, &pos);
1852: while (zend_hash_get_current_data_ex(model->u.content, (void**)&tmp, &pos) == SUCCESS) {
1853: int tmp_ret = model_to_xml_object(node, *tmp, object, style, 0 TSRMLS_CC);
1854: if (tmp_ret == 1) {
1855: return 1;
1856: } else if (tmp_ret != 0) {
1857: ret = 1;
1858: }
1859: zend_hash_move_forward_ex(model->u.content, &pos);
1860: }
1861: return ret;
1862: }
1863: case XSD_CONTENT_GROUP: {
1864: return model_to_xml_object(node, model->u.group->model, object, style, model->min_occurs > 0 TSRMLS_CC);
1865: }
1866: default:
1867: break;
1868: }
1869: return 1;
1870: }
1871:
1872: static sdlTypePtr model_array_element(sdlContentModelPtr model)
1873: {
1874: switch (model->kind) {
1875: case XSD_CONTENT_ELEMENT: {
1876: if (model->max_occurs == -1 || model->max_occurs > 1) {
1877: return model->u.element;
1878: } else {
1879: return NULL;
1880: }
1881: }
1882: case XSD_CONTENT_SEQUENCE:
1883: case XSD_CONTENT_ALL:
1884: case XSD_CONTENT_CHOICE: {
1885: sdlContentModelPtr *tmp;
1886: HashPosition pos;
1887:
1888: if (zend_hash_num_elements(model->u.content) != 1) {
1889: return NULL;
1890: }
1891: zend_hash_internal_pointer_reset_ex(model->u.content, &pos);
1892: zend_hash_get_current_data_ex(model->u.content, (void**)&tmp, &pos);
1893: return model_array_element(*tmp);
1894: }
1895: case XSD_CONTENT_GROUP: {
1896: return model_array_element(model->u.group->model);
1897: }
1898: default:
1899: break;
1900: }
1901: return NULL;
1902: }
1903:
1904: static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
1905: {
1906: xmlNodePtr xmlParam;
1907: HashTable *prop = NULL;
1908: int i;
1909: sdlTypePtr sdlType = type->sdl_type;
1910: TSRMLS_FETCH();
1911:
1912: if (!data || Z_TYPE_P(data) == IS_NULL) {
1913: xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1914: xmlAddChild(parent, xmlParam);
1915: if (style == SOAP_ENCODED) {
1916: set_xsi_nil(xmlParam);
1917: set_ns_and_type(xmlParam, type);
1918: }
1919: return xmlParam;
1920: }
1921:
1922: if (Z_TYPE_P(data) == IS_OBJECT) {
1923: prop = Z_OBJPROP_P(data);
1924: } else if (Z_TYPE_P(data) == IS_ARRAY) {
1925: prop = Z_ARRVAL_P(data);
1926: }
1927:
1928: if (sdlType) {
1929: if (sdlType->kind == XSD_TYPEKIND_RESTRICTION &&
1930: sdlType->encode && type != &sdlType->encode->details) {
1931: encodePtr enc;
1932:
1933: enc = sdlType->encode;
1934: while (enc && enc->details.sdl_type &&
1935: enc->details.sdl_type->kind != XSD_TYPEKIND_SIMPLE &&
1936: enc->details.sdl_type->kind != XSD_TYPEKIND_LIST &&
1937: enc->details.sdl_type->kind != XSD_TYPEKIND_UNION) {
1938: enc = enc->details.sdl_type->encode;
1939: }
1940: if (enc) {
1941: zval *tmp = get_zval_property(data, "_" TSRMLS_CC);
1942: if (tmp) {
1943: xmlParam = master_to_xml(enc, tmp, style, parent);
1944: } else if (prop == NULL) {
1945: xmlParam = master_to_xml(enc, data, style, parent);
1946: } else {
1947: xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1948: xmlAddChild(parent, xmlParam);
1949: }
1950: } else {
1951: xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1952: xmlAddChild(parent, xmlParam);
1953: }
1954: } else if (sdlType->kind == XSD_TYPEKIND_EXTENSION &&
1955: sdlType->encode && type != &sdlType->encode->details) {
1956: if (sdlType->encode->details.sdl_type &&
1957: sdlType->encode->details.sdl_type->kind != XSD_TYPEKIND_SIMPLE &&
1958: sdlType->encode->details.sdl_type->kind != XSD_TYPEKIND_LIST &&
1959: sdlType->encode->details.sdl_type->kind != XSD_TYPEKIND_UNION) {
1960:
1961: if (prop) prop->nApplyCount++;
1962: xmlParam = master_to_xml(sdlType->encode, data, style, parent);
1963: if (prop) prop->nApplyCount--;
1964: } else {
1965: zval *tmp = get_zval_property(data, "_" TSRMLS_CC);
1966:
1967: if (tmp) {
1968: xmlParam = master_to_xml(sdlType->encode, tmp, style, parent);
1969: } else if (prop == NULL) {
1970: xmlParam = master_to_xml(sdlType->encode, data, style, parent);
1971: } else {
1972: xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1973: xmlAddChild(parent, xmlParam);
1974: }
1975: }
1976: } else {
1977: xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1978: xmlAddChild(parent, xmlParam);
1979: }
1980:
1981: if (soap_check_zval_ref(data, xmlParam TSRMLS_CC)) {
1982: return xmlParam;
1983: }
1984: if (prop != NULL) {
1985: sdlTypePtr array_el;
1986:
1987: if (Z_TYPE_P(data) == IS_ARRAY &&
1988: !is_map(data) &&
1989: sdlType->attributes == NULL &&
1990: sdlType->model != NULL &&
1991: (array_el = model_array_element(sdlType->model)) != NULL) {
1992: zval **val;
1993:
1994: zend_hash_internal_pointer_reset(prop);
1995: while (zend_hash_get_current_data(prop,(void**)&val) == SUCCESS) {
1996: xmlNodePtr property;
1997: if (Z_TYPE_PP(val) == IS_NULL && array_el->nillable) {
1998: property = xmlNewNode(NULL, BAD_CAST("BOGUS"));
1999: xmlAddChild(xmlParam, property);
2000: set_xsi_nil(property);
2001: } else {
2002: property = master_to_xml(array_el->encode, *val, style, xmlParam);
2003: }
2004: xmlNodeSetName(property, BAD_CAST(array_el->name));
2005: if (style == SOAP_LITERAL &&
2006: array_el->namens &&
2007: array_el->form == XSD_FORM_QUALIFIED) {
2008: xmlNsPtr nsp = encode_add_ns(property, array_el->namens);
2009: xmlSetNs(property, nsp);
2010: }
2011: zend_hash_move_forward(prop);
2012: }
2013: } else if (sdlType->model) {
2014: model_to_xml_object(xmlParam, sdlType->model, data, style, 1 TSRMLS_CC);
2015: }
2016: if (sdlType->attributes) {
2017: sdlAttributePtr *attr;
2018: zval *zattr;
2019: HashPosition pos;
2020:
2021: zend_hash_internal_pointer_reset_ex(sdlType->attributes, &pos);
2022: while (zend_hash_get_current_data_ex(sdlType->attributes, (void**)&attr, &pos) == SUCCESS) {
2023: if ((*attr)->name) {
2024: zattr = get_zval_property(data, (*attr)->name TSRMLS_CC);
2025: if (zattr) {
2026: xmlNodePtr dummy;
2027:
2028: dummy = master_to_xml((*attr)->encode, zattr, SOAP_LITERAL, xmlParam);
2029: if (dummy->children && dummy->children->content) {
2030: if ((*attr)->fixed && strcmp((*attr)->fixed, (char*)dummy->children->content) != 0) {
2031: soap_error3(E_ERROR, "Encoding: Attribute '%s' has fixed value '%s' (value '%s' is not allowed)", (*attr)->name, (*attr)->fixed, dummy->children->content);
2032: }
2033: /* we need to handle xml: namespace specially, since it is
2034: an implicit schema. Otherwise, use form.
2035: */
2036: if ((*attr)->namens &&
2037: (!strncmp((*attr)->namens, XML_NAMESPACE, sizeof(XML_NAMESPACE)) ||
2038: (*attr)->form == XSD_FORM_QUALIFIED)) {
2039: xmlNsPtr nsp = encode_add_ns(xmlParam, (*attr)->namens);
2040:
2041: xmlSetNsProp(xmlParam, nsp, BAD_CAST((*attr)->name), dummy->children->content);
2042: } else {
2043: xmlSetProp(xmlParam, BAD_CAST((*attr)->name), dummy->children->content);
2044: }
2045: }
2046: xmlUnlinkNode(dummy);
2047: xmlFreeNode(dummy);
2048: }
2049: }
2050: zend_hash_move_forward_ex(sdlType->attributes, &pos);
2051: }
2052: }
2053: }
2054: if (style == SOAP_ENCODED) {
2055: set_ns_and_type(xmlParam, type);
2056: }
2057: } else {
2058: xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
2059: xmlAddChild(parent, xmlParam);
2060:
2061: if (soap_check_zval_ref(data, xmlParam TSRMLS_CC)) {
2062: return xmlParam;
2063: }
2064: if (prop != NULL) {
2065: i = zend_hash_num_elements(prop);
2066: zend_hash_internal_pointer_reset(prop);
2067:
2068: for (;i > 0;i--) {
2069: xmlNodePtr property;
2070: zval **zprop;
2071: char *str_key;
2072: ulong index;
2073: int key_type;
2074: unsigned int str_key_len;
2075:
2076: key_type = zend_hash_get_current_key_ex(prop, &str_key, &str_key_len, &index, FALSE, NULL);
2077: zend_hash_get_current_data(prop, (void **)&zprop);
2078:
2079: property = master_to_xml(get_conversion((*zprop)->type), (*zprop), style, xmlParam);
2080:
2081: if (key_type == HASH_KEY_IS_STRING) {
2082: char *prop_name;
2083:
2084: if (Z_TYPE_P(data) == IS_OBJECT) {
2085: char *class_name;
2086:
2087: zend_unmangle_property_name(str_key, str_key_len-1, &class_name, &prop_name);
2088: } else {
2089: prop_name = str_key;
2090: }
2091: if (prop_name) {
2092: xmlNodeSetName(property, BAD_CAST(prop_name));
2093: }
2094: }
2095: zend_hash_move_forward(prop);
2096: }
2097: }
2098: if (style == SOAP_ENCODED) {
2099: set_ns_and_type(xmlParam, type);
2100: }
2101: }
2102: return xmlParam;
2103: }
2104:
2105: /* Array encode/decode */
2106: static xmlNodePtr guess_array_map(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
2107: {
2108: encodePtr enc = NULL;
2109:
2110: if (data && Z_TYPE_P(data) == IS_ARRAY) {
2111: if (is_map(data)) {
2112: enc = get_conversion(APACHE_MAP);
2113: } else {
2114: enc = get_conversion(SOAP_ENC_ARRAY);
2115: }
2116: }
2117: if (!enc) {
2118: enc = get_conversion(IS_NULL);
2119: }
2120:
2121: return master_to_xml(enc, data, style, parent);
2122: }
2123:
2124: static int calc_dimension_12(const char* str)
2125: {
2126: int i = 0, flag = 0;
2127: while (*str != '\0' && (*str < '0' || *str > '9') && (*str != '*')) {
2128: str++;
2129: }
2130: if (*str == '*') {
2131: i++;
2132: str++;
2133: }
2134: while (*str != '\0') {
2135: if (*str >= '0' && *str <= '9') {
2136: if (flag == 0) {
2137: i++;
2138: flag = 1;
2139: }
2140: } else if (*str == '*') {
2141: soap_error0(E_ERROR, "Encoding: '*' may only be first arraySize value in list");
2142: } else {
2143: flag = 0;
2144: }
2145: str++;
2146: }
2147: return i;
2148: }
2149:
2150: static int* get_position_12(int dimension, const char* str)
2151: {
2152: int *pos;
2153: int i = -1, flag = 0;
2154:
2155: pos = safe_emalloc(sizeof(int), dimension, 0);
2156: memset(pos,0,sizeof(int)*dimension);
2157: while (*str != '\0' && (*str < '0' || *str > '9') && (*str != '*')) {
2158: str++;
2159: }
2160: if (*str == '*') {
2161: str++;
2162: i++;
2163: }
2164: while (*str != '\0') {
2165: if (*str >= '0' && *str <= '9') {
2166: if (flag == 0) {
2167: i++;
2168: flag = 1;
2169: }
2170: pos[i] = (pos[i]*10)+(*str-'0');
2171: } else if (*str == '*') {
2172: soap_error0(E_ERROR, "Encoding: '*' may only be first arraySize value in list");
2173: } else {
2174: flag = 0;
2175: }
2176: str++;
2177: }
2178: return pos;
2179: }
2180:
2181: static int calc_dimension(const char* str)
2182: {
2183: int i = 1;
2184: while (*str != ']' && *str != '\0') {
2185: if (*str == ',') {
2186: i++;
2187: }
2188: str++;
2189: }
2190: return i;
2191: }
2192:
2193: static void get_position_ex(int dimension, const char* str, int** pos)
2194: {
2195: int i = 0;
2196:
2197: memset(*pos,0,sizeof(int)*dimension);
2198: while (*str != ']' && *str != '\0' && i < dimension) {
2199: if (*str >= '0' && *str <= '9') {
2200: (*pos)[i] = ((*pos)[i]*10)+(*str-'0');
2201: } else if (*str == ',') {
2202: i++;
2203: }
2204: str++;
2205: }
2206: }
2207:
2208: static int* get_position(int dimension, const char* str)
2209: {
2210: int *pos;
2211:
2212: pos = safe_emalloc(sizeof(int), dimension, 0);
2213: get_position_ex(dimension, str, &pos);
2214: return pos;
2215: }
2216:
2217: static void add_xml_array_elements(xmlNodePtr xmlParam,
2218: sdlTypePtr type,
2219: encodePtr enc,
2220: xmlNsPtr ns,
2221: int dimension ,
2222: int* dims,
2223: zval* data,
2224: int style)
2225: {
2226: int j;
2227:
2228: if (data && Z_TYPE_P(data) == IS_ARRAY) {
2229: zend_hash_internal_pointer_reset(data->value.ht);
2230: for (j=0; j<dims[0]; j++) {
2231: zval **zdata;
2232:
2233: if (zend_hash_get_current_data(data->value.ht, (void **)&zdata) != SUCCESS) {
2234: zdata = NULL;
2235: }
2236: if (dimension == 1) {
2237: xmlNodePtr xparam;
2238:
2239: if (zdata) {
2240: if (enc == NULL) {
2241: xparam = master_to_xml(get_conversion((*zdata)->type), (*zdata), style, xmlParam);
2242: } else {
2243: xparam = master_to_xml(enc, (*zdata), style, xmlParam);
2244: }
2245: } else {
2246: xparam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
2247: xmlAddChild(xmlParam, xparam);
2248: }
2249:
2250: if (type) {
2251: xmlNodeSetName(xparam, BAD_CAST(type->name));
2252: } else if (style == SOAP_LITERAL && enc && enc->details.type_str) {
2253: xmlNodeSetName(xparam, BAD_CAST(enc->details.type_str));
2254: xmlSetNs(xparam, ns);
2255: } else {
2256: xmlNodeSetName(xparam, BAD_CAST("item"));
2257: }
2258: } else {
2259: if (zdata) {
2260: add_xml_array_elements(xmlParam, type, enc, ns, dimension-1, dims+1, *zdata, style);
2261: } else {
2262: add_xml_array_elements(xmlParam, type, enc, ns, dimension-1, dims+1, NULL, style);
2263: }
2264: }
2265: zend_hash_move_forward(data->value.ht);
2266: }
2267: } else {
2268: for (j=0; j<dims[0]; j++) {
2269: if (dimension == 1) {
2270: xmlNodePtr xparam;
2271:
2272: xparam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
2273: xmlAddChild(xmlParam, xparam);
2274: if (type) {
2275: xmlNodeSetName(xparam, BAD_CAST(type->name));
2276: } else if (style == SOAP_LITERAL && enc && enc->details.type_str) {
2277: xmlNodeSetName(xparam, BAD_CAST(enc->details.type_str));
2278: xmlSetNs(xparam, ns);
2279: } else {
2280: xmlNodeSetName(xparam, BAD_CAST("item"));
2281: }
2282: } else {
2283: add_xml_array_elements(xmlParam, type, enc, ns, dimension-1, dims+1, NULL, style);
2284: }
2285: }
2286: }
2287: }
2288:
2289: static inline int array_num_elements(HashTable* ht)
2290: {
2291: if (ht->pListTail && ht->pListTail->nKeyLength == 0) {
2292: return ht->pListTail->h-1;
2293: }
2294: return 0;
2295: }
2296:
2297: static xmlNodePtr to_xml_array(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
2298: {
2299: sdlTypePtr sdl_type = type->sdl_type;
2300: sdlTypePtr element_type = NULL;
2301: smart_str array_type = {0}, array_size = {0};
2302: int i;
2303: xmlNodePtr xmlParam;
2304: encodePtr enc = NULL;
2305: int dimension = 1;
2306: int* dims;
2307: int soap_version;
2308: zval *array_copy = NULL;
2309: TSRMLS_FETCH();
2310:
2311: soap_version = SOAP_GLOBAL(soap_version);
2312:
2313: xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
2314: xmlAddChild(parent, xmlParam);
2315:
2316: if (!data || Z_TYPE_P(data) == IS_NULL) {
2317: if (style == SOAP_ENCODED) {
2318: set_xsi_nil(xmlParam);
2319: if (SOAP_GLOBAL(features) & SOAP_USE_XSI_ARRAY_TYPE) {
2320: set_ns_and_type_ex(xmlParam, (soap_version == SOAP_1_1) ? SOAP_1_1_ENC_NAMESPACE : SOAP_1_2_ENC_NAMESPACE, "Array");
2321: } else {
2322: set_ns_and_type(xmlParam, type);
2323: }
2324: }
2325: return xmlParam;
2326: }
2327:
2328: if (Z_TYPE_P(data) == IS_OBJECT && instanceof_function(Z_OBJCE_P(data), zend_ce_traversable TSRMLS_CC)) {
2329: zend_object_iterator *iter;
2330: zend_class_entry *ce = Z_OBJCE_P(data);
2331: zval **val;
2332: char *str_key;
2333: uint str_key_len;
2334: ulong int_key;
2335: int key_type;
2336:
2337: ALLOC_ZVAL(array_copy);
2338: INIT_PZVAL(array_copy);
2339: array_init(array_copy);
2340:
2341: iter = ce->get_iterator(ce, data, 0 TSRMLS_CC);
2342:
2343: if (EG(exception)) {
2344: goto iterator_done;
2345: }
2346:
2347: if (iter->funcs->rewind) {
2348: iter->funcs->rewind(iter TSRMLS_CC);
2349: if (EG(exception)) {
2350: goto iterator_done;
2351: }
2352: }
2353:
2354: while (iter->funcs->valid(iter TSRMLS_CC) == SUCCESS) {
2355: if (EG(exception)) {
2356: goto iterator_done;
2357: }
2358:
2359: iter->funcs->get_current_data(iter, &val TSRMLS_CC);
2360: if (EG(exception)) {
2361: goto iterator_done;
2362: }
2363: if (iter->funcs->get_current_key) {
2364: key_type = iter->funcs->get_current_key(iter, &str_key, &str_key_len, &int_key TSRMLS_CC);
2365: if (EG(exception)) {
2366: goto iterator_done;
2367: }
2368: switch(key_type) {
2369: case HASH_KEY_IS_STRING:
2370: add_assoc_zval_ex(array_copy, str_key, str_key_len, *val);
2371: efree(str_key);
2372: break;
2373: case HASH_KEY_IS_LONG:
2374: add_index_zval(array_copy, int_key, *val);
2375: break;
2376: }
2377: } else {
2378: add_next_index_zval(array_copy, *val);
2379: }
2380: Z_ADDREF_PP(val);
2381:
2382: iter->funcs->move_forward(iter TSRMLS_CC);
2383: if (EG(exception)) {
2384: goto iterator_done;
2385: }
2386: }
2387: iterator_done:
2388: iter->funcs->dtor(iter TSRMLS_CC);
2389: if (EG(exception)) {
2390: zval_ptr_dtor(&array_copy);
2391: array_copy = NULL;
2392: } else {
2393: data = array_copy;
2394: }
2395: }
2396:
2397: if (Z_TYPE_P(data) == IS_ARRAY) {
2398: sdlAttributePtr *arrayType;
2399: sdlExtraAttributePtr *ext;
2400: sdlTypePtr elementType;
2401:
2402: i = zend_hash_num_elements(Z_ARRVAL_P(data));
2403:
2404: if (sdl_type &&
2405: sdl_type->attributes &&
2406: zend_hash_find(sdl_type->attributes, SOAP_1_1_ENC_NAMESPACE":arrayType",
2407: sizeof(SOAP_1_1_ENC_NAMESPACE":arrayType"),
2408: (void **)&arrayType) == SUCCESS &&
2409: (*arrayType)->extraAttributes &&
2410: zend_hash_find((*arrayType)->extraAttributes, WSDL_NAMESPACE":arrayType", sizeof(WSDL_NAMESPACE":arrayType"), (void **)&ext) == SUCCESS) {
2411:
2412: char *value, *end;
2413: zval** el;
2414:
2415: value = estrdup((*ext)->val);
2416: end = strrchr(value,'[');
2417: if (end) {
2418: *end = '\0';
2419: end++;
2420: dimension = calc_dimension(end);
2421: }
2422: if ((*ext)->ns != NULL) {
2423: enc = get_encoder(SOAP_GLOBAL(sdl), (*ext)->ns, value);
2424: get_type_str(xmlParam, (*ext)->ns, value, &array_type);
2425: } else {
2426: smart_str_appends(&array_type, value);
2427: }
2428:
2429: dims = safe_emalloc(sizeof(int), dimension, 0);
2430: dims[0] = i;
2431: el = &data;
2432: for (i = 1; i < dimension; i++) {
2433: if (el != NULL && Z_TYPE_PP(el) == IS_ARRAY &&
2434: zend_hash_num_elements(Z_ARRVAL_PP(el)) > 0) {
2435: zend_hash_internal_pointer_reset(Z_ARRVAL_PP(el));
2436: zend_hash_get_current_data(Z_ARRVAL_PP(el), (void**)&el);
2437: if (Z_TYPE_PP(el) == IS_ARRAY) {
2438: dims[i] = zend_hash_num_elements(Z_ARRVAL_PP(el));
2439: } else {
2440: dims[i] = 0;
2441: }
2442: }
2443: }
2444:
2445: smart_str_append_long(&array_size, dims[0]);
2446: for (i=1; i<dimension; i++) {
2447: smart_str_appendc(&array_size, ',');
2448: smart_str_append_long(&array_size, dims[i]);
2449: }
2450:
2451: efree(value);
2452:
2453: } else if (sdl_type &&
2454: sdl_type->attributes &&
2455: zend_hash_find(sdl_type->attributes, SOAP_1_2_ENC_NAMESPACE":itemType",
2456: sizeof(SOAP_1_2_ENC_NAMESPACE":itemType"),
2457: (void **)&arrayType) == SUCCESS &&
2458: (*arrayType)->extraAttributes &&
2459: zend_hash_find((*arrayType)->extraAttributes, WSDL_NAMESPACE":itemType", sizeof(WSDL_NAMESPACE":itemType"), (void **)&ext) == SUCCESS) {
2460: if ((*ext)->ns != NULL) {
2461: enc = get_encoder(SOAP_GLOBAL(sdl), (*ext)->ns, (*ext)->val);
2462: get_type_str(xmlParam, (*ext)->ns, (*ext)->val, &array_type);
2463: } else {
2464: smart_str_appends(&array_type, (*ext)->val);
2465: }
2466: if (zend_hash_find(sdl_type->attributes, SOAP_1_2_ENC_NAMESPACE":arraySize",
2467: sizeof(SOAP_1_2_ENC_NAMESPACE":arraySize"),
2468: (void **)&arrayType) == SUCCESS &&
2469: (*arrayType)->extraAttributes &&
2470: zend_hash_find((*arrayType)->extraAttributes, WSDL_NAMESPACE":arraySize", sizeof(WSDL_NAMESPACE":arraysize"), (void **)&ext) == SUCCESS) {
2471: dimension = calc_dimension_12((*ext)->val);
2472: dims = get_position_12(dimension, (*ext)->val);
2473: if (dims[0] == 0) {dims[0] = i;}
2474:
2475: smart_str_append_long(&array_size, dims[0]);
2476: for (i=1; i<dimension; i++) {
2477: smart_str_appendc(&array_size, ',');
2478: smart_str_append_long(&array_size, dims[i]);
2479: }
2480: } else {
2481: dims = emalloc(sizeof(int));
2482: *dims = 0;
2483: smart_str_append_long(&array_size, i);
2484: }
2485: } else if (sdl_type &&
2486: sdl_type->attributes &&
2487: zend_hash_find(sdl_type->attributes, SOAP_1_2_ENC_NAMESPACE":arraySize",
2488: sizeof(SOAP_1_2_ENC_NAMESPACE":arraySize"),
2489: (void **)&arrayType) == SUCCESS &&
2490: (*arrayType)->extraAttributes &&
2491: zend_hash_find((*arrayType)->extraAttributes, WSDL_NAMESPACE":arraySize", sizeof(WSDL_NAMESPACE":arraySize"), (void **)&ext) == SUCCESS) {
2492: dimension = calc_dimension_12((*ext)->val);
2493: dims = get_position_12(dimension, (*ext)->val);
2494: if (dims[0] == 0) {dims[0] = i;}
2495:
2496: smart_str_append_long(&array_size, dims[0]);
2497: for (i=1; i<dimension; i++) {
2498: smart_str_appendc(&array_size, ',');
2499: smart_str_append_long(&array_size, dims[i]);
2500: }
2501:
2502: if (sdl_type && sdl_type->elements &&
2503: zend_hash_num_elements(sdl_type->elements) == 1 &&
2504: (zend_hash_internal_pointer_reset(sdl_type->elements),
2505: zend_hash_get_current_data(sdl_type->elements, (void**)&elementType) == SUCCESS) &&
2506: (elementType = *(sdlTypePtr*)elementType) != NULL &&
2507: elementType->encode && elementType->encode->details.type_str) {
2508: element_type = elementType;
2509: enc = elementType->encode;
2510: get_type_str(xmlParam, elementType->encode->details.ns, elementType->encode->details.type_str, &array_type);
2511: } else {
2512: enc = get_array_type(xmlParam, data, &array_type TSRMLS_CC);
2513: }
2514: } else if (sdl_type && sdl_type->elements &&
2515: zend_hash_num_elements(sdl_type->elements) == 1 &&
2516: (zend_hash_internal_pointer_reset(sdl_type->elements),
2517: zend_hash_get_current_data(sdl_type->elements, (void**)&elementType) == SUCCESS) &&
2518: (elementType = *(sdlTypePtr*)elementType) != NULL &&
2519: elementType->encode && elementType->encode->details.type_str) {
2520:
2521: element_type = elementType;
2522: enc = elementType->encode;
2523: get_type_str(xmlParam, elementType->encode->details.ns, elementType->encode->details.type_str, &array_type);
2524:
2525: smart_str_append_long(&array_size, i);
2526:
2527: dims = safe_emalloc(sizeof(int), dimension, 0);
2528: dims[0] = i;
2529: } else {
2530:
2531: enc = get_array_type(xmlParam, data, &array_type TSRMLS_CC);
2532: smart_str_append_long(&array_size, i);
2533: dims = safe_emalloc(sizeof(int), dimension, 0);
2534: dims[0] = i;
2535: }
2536:
2537: if (style == SOAP_ENCODED) {
2538: if (soap_version == SOAP_1_1) {
2539: smart_str_0(&array_type);
2540: if (strcmp(array_type.c,"xsd:anyType") == 0) {
2541: smart_str_free(&array_type);
2542: smart_str_appendl(&array_type,"xsd:ur-type",sizeof("xsd:ur-type")-1);
2543: }
2544: smart_str_appendc(&array_type, '[');
2545: smart_str_append(&array_type, &array_size);
2546: smart_str_appendc(&array_type, ']');
2547: smart_str_0(&array_type);
2548: set_ns_prop(xmlParam, SOAP_1_1_ENC_NAMESPACE, "arrayType", array_type.c);
2549: } else {
2550: int i = 0;
2551: while (i < array_size.len) {
2552: if (array_size.c[i] == ',') {array_size.c[i] = ' ';}
2553: ++i;
2554: }
2555: smart_str_0(&array_type);
2556: smart_str_0(&array_size);
2557: set_ns_prop(xmlParam, SOAP_1_2_ENC_NAMESPACE, "itemType", array_type.c);
2558: set_ns_prop(xmlParam, SOAP_1_2_ENC_NAMESPACE, "arraySize", array_size.c);
2559: }
2560: }
2561: smart_str_free(&array_type);
2562: smart_str_free(&array_size);
2563:
2564: add_xml_array_elements(xmlParam, element_type, enc, enc?encode_add_ns(xmlParam,enc->details.ns):NULL, dimension, dims, data, style);
2565: efree(dims);
2566: }
2567: if (style == SOAP_ENCODED) {
2568: if (SOAP_GLOBAL(features) & SOAP_USE_XSI_ARRAY_TYPE) {
2569: set_ns_and_type_ex(xmlParam, (soap_version == SOAP_1_1) ? SOAP_1_1_ENC_NAMESPACE : SOAP_1_2_ENC_NAMESPACE, "Array");
2570: } else {
2571: set_ns_and_type(xmlParam, type);
2572: }
2573: }
2574:
2575: if (array_copy) {
2576: zval_ptr_dtor(&array_copy);
2577: }
2578:
2579: return xmlParam;
2580: }
2581:
2582: static zval *to_zval_array(encodeTypePtr type, xmlNodePtr data)
2583: {
2584: zval *ret;
2585: xmlNodePtr trav;
2586: encodePtr enc = NULL;
2587: int dimension = 1;
2588: int* dims = NULL;
2589: int* pos = NULL;
2590: xmlAttrPtr attr;
2591: sdlPtr sdl;
2592: sdlAttributePtr *arrayType;
2593: sdlExtraAttributePtr *ext;
2594: sdlTypePtr elementType;
2595:
2596: TSRMLS_FETCH();
2597:
2598: MAKE_STD_ZVAL(ret);
2599: FIND_XML_NULL(data, ret);
2600: sdl = SOAP_GLOBAL(sdl);
2601:
2602: if (data &&
2603: (attr = get_attribute(data->properties,"arrayType")) &&
2604: attr->children && attr->children->content) {
2605: char *type, *end, *ns;
2606: xmlNsPtr nsptr;
2607:
2608: parse_namespace(attr->children->content, &type, &ns);
2609: nsptr = xmlSearchNs(attr->doc, attr->parent, BAD_CAST(ns));
2610:
2611: end = strrchr(type,'[');
2612: if (end) {
2613: *end = '\0';
2614: dimension = calc_dimension(end+1);
2615: dims = get_position(dimension, end+1);
2616: }
2617: if (nsptr != NULL) {
2618: enc = get_encoder(SOAP_GLOBAL(sdl), (char*)nsptr->href, type);
2619: }
2620: efree(type);
2621: if (ns) {efree(ns);}
2622:
2623: } else if ((attr = get_attribute(data->properties,"itemType")) &&
2624: attr->children &&
2625: attr->children->content) {
2626: char *type, *ns;
2627: xmlNsPtr nsptr;
2628:
2629: parse_namespace(attr->children->content, &type, &ns);
2630: nsptr = xmlSearchNs(attr->doc, attr->parent, BAD_CAST(ns));
2631: if (nsptr != NULL) {
2632: enc = get_encoder(SOAP_GLOBAL(sdl), (char*)nsptr->href, type);
2633: }
2634: efree(type);
2635: if (ns) {efree(ns);}
2636:
2637: if ((attr = get_attribute(data->properties,"arraySize")) &&
2638: attr->children && attr->children->content) {
2639: dimension = calc_dimension_12((char*)attr->children->content);
2640: dims = get_position_12(dimension, (char*)attr->children->content);
2641: } else {
2642: dims = emalloc(sizeof(int));
2643: *dims = 0;
2644: }
2645:
2646: } else if ((attr = get_attribute(data->properties,"arraySize")) &&
2647: attr->children && attr->children->content) {
2648:
2649: dimension = calc_dimension_12((char*)attr->children->content);
2650: dims = get_position_12(dimension, (char*)attr->children->content);
2651:
2652: } else if (type->sdl_type != NULL &&
2653: type->sdl_type->attributes != NULL &&
2654: zend_hash_find(type->sdl_type->attributes, SOAP_1_1_ENC_NAMESPACE":arrayType",
2655: sizeof(SOAP_1_1_ENC_NAMESPACE":arrayType"),
2656: (void **)&arrayType) == SUCCESS &&
2657: (*arrayType)->extraAttributes &&
2658: zend_hash_find((*arrayType)->extraAttributes, WSDL_NAMESPACE":arrayType", sizeof(WSDL_NAMESPACE":arrayType"), (void **)&ext) == SUCCESS) {
2659: char *type, *end;
2660:
2661: type = estrdup((*ext)->val);
2662: end = strrchr(type,'[');
2663: if (end) {
2664: *end = '\0';
2665: }
2666: if ((*ext)->ns != NULL) {
2667: enc = get_encoder(SOAP_GLOBAL(sdl), (*ext)->ns, type);
2668: }
2669: efree(type);
2670:
2671: dims = emalloc(sizeof(int));
2672: *dims = 0;
2673:
2674: } else if (type->sdl_type != NULL &&
2675: type->sdl_type->attributes != NULL &&
2676: zend_hash_find(type->sdl_type->attributes, SOAP_1_2_ENC_NAMESPACE":itemType",
2677: sizeof(SOAP_1_2_ENC_NAMESPACE":itemType"),
2678: (void **)&arrayType) == SUCCESS &&
2679: (*arrayType)->extraAttributes &&
2680: zend_hash_find((*arrayType)->extraAttributes, WSDL_NAMESPACE":itemType", sizeof(WSDL_NAMESPACE":itemType"), (void **)&ext) == SUCCESS) {
2681:
2682: if ((*ext)->ns != NULL) {
2683: enc = get_encoder(SOAP_GLOBAL(sdl), (*ext)->ns, (*ext)->val);
2684: }
2685:
2686: if (zend_hash_find(type->sdl_type->attributes, SOAP_1_2_ENC_NAMESPACE":arraySize",
2687: sizeof(SOAP_1_2_ENC_NAMESPACE":arraySize"),
2688: (void **)&arrayType) == SUCCESS &&
2689: (*arrayType)->extraAttributes &&
2690: zend_hash_find((*arrayType)->extraAttributes, WSDL_NAMESPACE":arraySize", sizeof(WSDL_NAMESPACE":arraysize"), (void **)&ext) == SUCCESS) {
2691: dimension = calc_dimension_12((*ext)->val);
2692: dims = get_position_12(dimension, (*ext)->val);
2693: } else {
2694: dims = emalloc(sizeof(int));
2695: *dims = 0;
2696: }
2697: } else if (type->sdl_type != NULL &&
2698: type->sdl_type->attributes != NULL &&
2699: zend_hash_find(type->sdl_type->attributes, SOAP_1_2_ENC_NAMESPACE":arraySize",
2700: sizeof(SOAP_1_2_ENC_NAMESPACE":arraySize"),
2701: (void **)&arrayType) == SUCCESS &&
2702: (*arrayType)->extraAttributes &&
2703: zend_hash_find((*arrayType)->extraAttributes, WSDL_NAMESPACE":arraySize", sizeof(WSDL_NAMESPACE":arraysize"), (void **)&ext) == SUCCESS) {
2704:
2705: dimension = calc_dimension_12((*ext)->val);
2706: dims = get_position_12(dimension, (*ext)->val);
2707: if (type->sdl_type && type->sdl_type->elements &&
2708: zend_hash_num_elements(type->sdl_type->elements) == 1 &&
2709: (zend_hash_internal_pointer_reset(type->sdl_type->elements),
2710: zend_hash_get_current_data(type->sdl_type->elements, (void**)&elementType) == SUCCESS) &&
2711: (elementType = *(sdlTypePtr*)elementType) != NULL &&
2712: elementType->encode) {
2713: enc = elementType->encode;
2714: }
2715: } else if (type->sdl_type && type->sdl_type->elements &&
2716: zend_hash_num_elements(type->sdl_type->elements) == 1 &&
2717: (zend_hash_internal_pointer_reset(type->sdl_type->elements),
2718: zend_hash_get_current_data(type->sdl_type->elements, (void**)&elementType) == SUCCESS) &&
2719: (elementType = *(sdlTypePtr*)elementType) != NULL &&
2720: elementType->encode) {
2721: enc = elementType->encode;
2722: }
2723: if (dims == NULL) {
2724: dimension = 1;
2725: dims = emalloc(sizeof(int));
2726: *dims = 0;
2727: }
2728: pos = safe_emalloc(sizeof(int), dimension, 0);
2729: memset(pos,0,sizeof(int)*dimension);
2730: if (data &&
2731: (attr = get_attribute(data->properties,"offset")) &&
2732: attr->children && attr->children->content) {
2733: char* tmp = strrchr((char*)attr->children->content,'[');
2734:
2735: if (tmp == NULL) {
2736: tmp = (char*)attr->children->content;
2737: }
2738: get_position_ex(dimension, tmp, &pos);
2739: }
2740:
2741: array_init(ret);
2742: trav = data->children;
2743: while (trav) {
2744: if (trav->type == XML_ELEMENT_NODE) {
2745: int i;
2746: zval *tmpVal, *ar;
2747: xmlAttrPtr position = get_attribute(trav->properties,"position");
2748:
2749: tmpVal = master_to_zval(enc, trav);
2750: if (position != NULL && position->children && position->children->content) {
2751: char* tmp = strrchr((char*)position->children->content, '[');
2752: if (tmp == NULL) {
2753: tmp = (char*)position->children->content;
2754: }
2755: get_position_ex(dimension, tmp, &pos);
2756: }
2757:
2758: /* Get/Create intermediate arrays for multidimensional arrays */
2759: i = 0;
2760: ar = ret;
2761: while (i < dimension-1) {
2762: zval** ar2;
2763: if (zend_hash_index_find(Z_ARRVAL_P(ar), pos[i], (void**)&ar2) == SUCCESS) {
2764: ar = *ar2;
2765: } else {
2766: zval *tmpAr;
2767: MAKE_STD_ZVAL(tmpAr);
2768: array_init(tmpAr);
2769: zend_hash_index_update(Z_ARRVAL_P(ar), pos[i], &tmpAr, sizeof(zval*), (void**)&ar2);
2770: ar = *ar2;
2771: }
2772: i++;
2773: }
2774: zend_hash_index_update(Z_ARRVAL_P(ar), pos[i], &tmpVal, sizeof(zval *), NULL);
2775:
2776: /* Increment position */
2777: i = dimension;
2778: while (i > 0) {
2779: i--;
2780: pos[i]++;
2781: if (pos[i] >= dims[i]) {
2782: if (i > 0) {
2783: pos[i] = 0;
2784: } else {
2785: /* TODO: Array index overflow */
2786: }
2787: } else {
2788: break;
2789: }
2790: }
2791: }
2792: trav = trav->next;
2793: }
2794: efree(dims);
2795: efree(pos);
2796: return ret;
2797: }
2798:
2799: /* Map encode/decode */
2800: static xmlNodePtr to_xml_map(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
2801: {
2802: xmlNodePtr xmlParam;
2803: int i;
2804:
2805: xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
2806: xmlAddChild(parent, xmlParam);
2807: FIND_ZVAL_NULL(data, xmlParam, style);
2808:
2809: if (Z_TYPE_P(data) == IS_ARRAY) {
2810: i = zend_hash_num_elements(Z_ARRVAL_P(data));
2811: zend_hash_internal_pointer_reset(data->value.ht);
2812: for (;i > 0;i--) {
2813: xmlNodePtr xparam, item;
2814: xmlNodePtr key;
2815: zval **temp_data;
2816: char *key_val;
2817: ulong int_val;
2818:
2819: zend_hash_get_current_data(data->value.ht, (void **)&temp_data);
2820: item = xmlNewNode(NULL, BAD_CAST("item"));
2821: xmlAddChild(xmlParam, item);
2822: key = xmlNewNode(NULL, BAD_CAST("key"));
2823: xmlAddChild(item,key);
2824: if (zend_hash_get_current_key(data->value.ht, &key_val, &int_val, FALSE) == HASH_KEY_IS_STRING) {
2825: if (style == SOAP_ENCODED) {
2826: set_xsi_type(key, "xsd:string");
2827: }
2828: xmlNodeSetContent(key, BAD_CAST(key_val));
2829: } else {
2830: smart_str tmp = {0};
2831: smart_str_append_long(&tmp, int_val);
2832: smart_str_0(&tmp);
2833:
2834: if (style == SOAP_ENCODED) {
2835: set_xsi_type(key, "xsd:int");
2836: }
2837: xmlNodeSetContentLen(key, BAD_CAST(tmp.c), tmp.len);
2838:
2839: smart_str_free(&tmp);
2840: }
2841:
2842: xparam = master_to_xml(get_conversion((*temp_data)->type), (*temp_data), style, item);
2843: xmlNodeSetName(xparam, BAD_CAST("value"));
2844:
2845: zend_hash_move_forward(data->value.ht);
2846: }
2847: }
2848: if (style == SOAP_ENCODED) {
2849: set_ns_and_type(xmlParam, type);
2850: }
2851:
2852: return xmlParam;
2853: }
2854:
2855: static zval *to_zval_map(encodeTypePtr type, xmlNodePtr data)
2856: {
2857: zval *ret, *key, *value;
2858: xmlNodePtr trav, item, xmlKey, xmlValue;
2859:
2860: MAKE_STD_ZVAL(ret);
2861: FIND_XML_NULL(data, ret);
2862:
2863: if (data && data->children) {
2864: array_init(ret);
2865: trav = data->children;
2866:
2867: trav = data->children;
2868: FOREACHNODE(trav, "item", item) {
2869: xmlKey = get_node(item->children, "key");
2870: if (!xmlKey) {
2871: soap_error0(E_ERROR, "Encoding: Can't decode apache map, missing key");
2872: }
2873:
2874: xmlValue = get_node(item->children, "value");
2875: if (!xmlKey) {
2876: soap_error0(E_ERROR, "Encoding: Can't decode apache map, missing value");
2877: }
2878:
2879: key = master_to_zval(NULL, xmlKey);
2880: value = master_to_zval(NULL, xmlValue);
2881:
2882: if (Z_TYPE_P(key) == IS_STRING) {
2883: zend_symtable_update(Z_ARRVAL_P(ret), Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &value, sizeof(zval *), NULL);
2884: } else if (Z_TYPE_P(key) == IS_LONG) {
2885: zend_hash_index_update(Z_ARRVAL_P(ret), Z_LVAL_P(key), &value, sizeof(zval *), NULL);
2886: } else {
2887: soap_error0(E_ERROR, "Encoding: Can't decode apache map, only Strings or Longs are allowd as keys");
2888: }
2889: zval_ptr_dtor(&key);
2890: }
2891: ENDFOREACH(trav);
2892: } else {
2893: ZVAL_NULL(ret);
2894: }
2895: return ret;
2896: }
2897:
2898: /* Unknown encode/decode */
2899: static xmlNodePtr guess_xml_convert(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
2900: {
2901: encodePtr enc;
2902: xmlNodePtr ret;
2903:
2904: if (data) {
2905: enc = get_conversion(data->type);
2906: } else {
2907: enc = get_conversion(IS_NULL);
2908: }
2909: ret = master_to_xml_int(enc, data, style, parent, 0);
2910: /*
2911: if (style == SOAP_LITERAL && SOAP_GLOBAL(sdl)) {
2912: set_ns_and_type(ret, &enc->details);
2913: }
2914: */
2915: return ret;
2916: }
2917:
2918: static zval *guess_zval_convert(encodeTypePtr type, xmlNodePtr data)
2919: {
2920: encodePtr enc = NULL;
2921: xmlAttrPtr tmpattr;
2922: xmlChar *type_name = NULL;
2923: zval *ret;
2924: TSRMLS_FETCH();
2925:
2926: data = check_and_resolve_href(data);
2927:
2928: if (data == NULL) {
2929: enc = get_conversion(IS_NULL);
2930: } else if (data->properties && get_attribute_ex(data->properties, "nil", XSI_NAMESPACE)) {
2931: enc = get_conversion(IS_NULL);
2932: } else {
2933: tmpattr = get_attribute_ex(data->properties,"type", XSI_NAMESPACE);
2934: if (tmpattr != NULL) {
2935: type_name = tmpattr->children->content;
2936: enc = get_encoder_from_prefix(SOAP_GLOBAL(sdl), data, tmpattr->children->content);
2937: if (enc && type == &enc->details) {
2938: enc = NULL;
2939: }
2940: if (enc != NULL) {
2941: encodePtr tmp = enc;
2942: while (tmp &&
2943: tmp->details.sdl_type != NULL &&
2944: tmp->details.sdl_type->kind != XSD_TYPEKIND_COMPLEX) {
2945: if (enc == tmp->details.sdl_type->encode ||
2946: tmp == tmp->details.sdl_type->encode) {
2947: enc = NULL;
2948: break;
2949: }
2950: tmp = tmp->details.sdl_type->encode;
2951: }
2952: }
2953: }
2954:
2955: if (enc == NULL) {
2956: /* Didn't have a type, totally guess here */
2957: /* Logic: has children = IS_OBJECT else IS_STRING */
2958: xmlNodePtr trav;
2959:
2960: if (get_attribute(data->properties, "arrayType") ||
2961: get_attribute(data->properties, "itemType") ||
2962: get_attribute(data->properties, "arraySize")) {
2963: enc = get_conversion(SOAP_ENC_ARRAY);
2964: } else {
2965: enc = get_conversion(XSD_STRING);
2966: trav = data->children;
2967: while (trav != NULL) {
2968: if (trav->type == XML_ELEMENT_NODE) {
2969: enc = get_conversion(SOAP_ENC_OBJECT);
2970: break;
2971: }
2972: trav = trav->next;
2973: }
2974: }
2975: }
2976: }
2977: ret = master_to_zval_int(enc, data);
2978: if (SOAP_GLOBAL(sdl) && type_name && enc->details.sdl_type) {
2979: zval* soapvar;
2980: char *ns, *cptype;
2981: xmlNsPtr nsptr;
2982:
2983: MAKE_STD_ZVAL(soapvar);
2984: object_init_ex(soapvar, soap_var_class_entry);
2985: add_property_long(soapvar, "enc_type", enc->details.type);
2986: #ifdef ZEND_ENGINE_2
2987: Z_DELREF_P(ret);
2988: #endif
2989: add_property_zval(soapvar, "enc_value", ret);
2990: parse_namespace(type_name, &cptype, &ns);
2991: nsptr = xmlSearchNs(data->doc, data, BAD_CAST(ns));
2992: add_property_string(soapvar, "enc_stype", cptype, 1);
2993: if (nsptr) {
2994: add_property_string(soapvar, "enc_ns", (char*)nsptr->href, 1);
2995: }
2996: efree(cptype);
2997: if (ns) {efree(ns);}
2998: ret = soapvar;
2999: }
3000: return ret;
3001: }
3002:
3003: /* Time encode/decode */
3004: static xmlNodePtr to_xml_datetime_ex(encodeTypePtr type, zval *data, char *format, int style, xmlNodePtr parent)
3005: {
3006: /* logic hacked from ext/standard/datetime.c */
3007: struct tm *ta, tmbuf;
3008: time_t timestamp;
3009: int max_reallocs = 5;
3010: size_t buf_len=64, real_len;
3011: char *buf;
3012: char tzbuf[8];
3013:
3014: xmlNodePtr xmlParam;
3015:
3016: xmlParam = xmlNewNode(NULL, BAD_CAST("BOGUS"));
3017: xmlAddChild(parent, xmlParam);
3018: FIND_ZVAL_NULL(data, xmlParam, style);
3019:
3020: if (Z_TYPE_P(data) == IS_LONG) {
3021: timestamp = Z_LVAL_P(data);
3022: ta = php_localtime_r(×tamp, &tmbuf);
3023: /*ta = php_gmtime_r(×tamp, &tmbuf);*/
3024: if (!ta) {
3025: soap_error1(E_ERROR, "Encoding: Invalid timestamp %ld", Z_LVAL_P(data));
3026: }
3027:
3028: buf = (char *) emalloc(buf_len);
3029: while ((real_len = strftime(buf, buf_len, format, ta)) == buf_len || real_len == 0) {
3030: buf_len *= 2;
3031: buf = (char *) erealloc(buf, buf_len);
3032: if (!--max_reallocs) break;
3033: }
3034:
3035: /* Time zone support */
3036: #ifdef HAVE_TM_GMTOFF
3037: snprintf(tzbuf, sizeof(tzbuf), "%c%02d:%02d", (ta->tm_gmtoff < 0) ? '-' : '+', abs(ta->tm_gmtoff / 3600), abs( (ta->tm_gmtoff % 3600) / 60 ));
3038: #else
3039: # if defined(__CYGWIN__) || defined(NETWARE)
3040: snprintf(tzbuf, sizeof(tzbuf), "%c%02d:%02d", ((ta->tm_isdst ? _timezone - 3600:_timezone)>0)?'-':'+', abs((ta->tm_isdst ? _timezone - 3600 : _timezone) / 3600), abs(((ta->tm_isdst ? _timezone - 3600 : _timezone) % 3600) / 60));
3041: # else
3042: snprintf(tzbuf, sizeof(tzbuf), "%c%02d:%02d", ((ta->tm_isdst ? timezone - 3600:timezone)>0)?'-':'+', abs((ta->tm_isdst ? timezone - 3600 : timezone) / 3600), abs(((ta->tm_isdst ? timezone - 3600 : timezone) % 3600) / 60));
3043: # endif
3044: #endif
3045: if (strcmp(tzbuf,"+00:00") == 0) {
3046: strcpy(tzbuf,"Z");
3047: real_len++;
3048: } else {
3049: real_len += 6;
3050: }
3051: if (real_len >= buf_len) {
3052: buf = (char *) erealloc(buf, real_len+1);
3053: }
3054: strcat(buf, tzbuf);
3055:
3056: xmlNodeSetContent(xmlParam, BAD_CAST(buf));
3057: efree(buf);
3058: } else if (Z_TYPE_P(data) == IS_STRING) {
3059: xmlNodeSetContentLen(xmlParam, BAD_CAST(Z_STRVAL_P(data)), Z_STRLEN_P(data));
3060: }
3061:
3062: if (style == SOAP_ENCODED) {
3063: set_ns_and_type(xmlParam, type);
3064: }
3065: return xmlParam;
3066: }
3067:
3068: static xmlNodePtr to_xml_duration(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
3069: {
3070: /* TODO: '-'?P([0-9]+Y)?([0-9]+M)?([0-9]+D)?T([0-9]+H)?([0-9]+M)?([0-9]+S)? */
3071: return to_xml_string(type, data, style, parent);
3072: }
3073:
3074: static xmlNodePtr to_xml_datetime(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
3075: {
3076: return to_xml_datetime_ex(type, data, "%Y-%m-%dT%H:%M:%S", style, parent);
3077: }
3078:
3079: static xmlNodePtr to_xml_time(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
3080: {
3081: /* TODO: microsecconds */
3082: return to_xml_datetime_ex(type, data, "%H:%M:%S", style, parent);
3083: }
3084:
3085: static xmlNodePtr to_xml_date(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
3086: {
3087: return to_xml_datetime_ex(type, data, "%Y-%m-%d", style, parent);
3088: }
3089:
3090: static xmlNodePtr to_xml_gyearmonth(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
3091: {
3092: return to_xml_datetime_ex(type, data, "%Y-%m", style, parent);
3093: }
3094:
3095: static xmlNodePtr to_xml_gyear(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
3096: {
3097: return to_xml_datetime_ex(type, data, "%Y", style, parent);
3098: }
3099:
3100: static xmlNodePtr to_xml_gmonthday(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
3101: {
3102: return to_xml_datetime_ex(type, data, "--%m-%d", style, parent);
3103: }
3104:
3105: static xmlNodePtr to_xml_gday(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
3106: {
3107: return to_xml_datetime_ex(type, data, "---%d", style, parent);
3108: }
3109:
3110: static xmlNodePtr to_xml_gmonth(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
3111: {
3112: return to_xml_datetime_ex(type, data, "--%m--", style, parent);
3113: }
3114:
3115: static zval* to_zval_list(encodeTypePtr enc, xmlNodePtr data) {
3116: /*FIXME*/
3117: return to_zval_stringc(enc, data);
3118: }
3119:
3120: static xmlNodePtr to_xml_list(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent) {
3121: xmlNodePtr ret;
3122: encodePtr list_enc = NULL;
3123:
3124: if (enc->sdl_type && enc->sdl_type->kind == XSD_TYPEKIND_LIST && enc->sdl_type->elements) {
3125: sdlTypePtr *type;
3126:
3127: zend_hash_internal_pointer_reset(enc->sdl_type->elements);
3128: if (zend_hash_get_current_data(enc->sdl_type->elements, (void**)&type) == SUCCESS) {
3129: list_enc = (*type)->encode;
3130: }
3131: }
3132:
3133: ret = xmlNewNode(NULL, BAD_CAST("BOGUS"));
3134: xmlAddChild(parent, ret);
3135: FIND_ZVAL_NULL(data, ret, style);
3136: if (Z_TYPE_P(data) == IS_ARRAY) {
3137: zval **tmp;
3138: smart_str list = {0};
3139: HashTable *ht = Z_ARRVAL_P(data);
3140:
3141: zend_hash_internal_pointer_reset(ht);
3142: while (zend_hash_get_current_data(ht, (void**)&tmp) == SUCCESS) {
3143: xmlNodePtr dummy = master_to_xml(list_enc, *tmp, SOAP_LITERAL, ret);
3144: if (dummy && dummy->children && dummy->children->content) {
3145: if (list.len != 0) {
3146: smart_str_appendc(&list, ' ');
3147: }
3148: smart_str_appends(&list, (char*)dummy->children->content);
3149: } else {
3150: soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
3151: }
3152: xmlUnlinkNode(dummy);
3153: xmlFreeNode(dummy);
3154: zend_hash_move_forward(ht);
3155: }
3156: smart_str_0(&list);
3157: xmlNodeSetContentLen(ret, BAD_CAST(list.c), list.len);
3158: smart_str_free(&list);
3159: } else {
3160: zval tmp = *data;
3161: char *str, *start, *next;
3162: smart_str list = {0};
3163:
3164: if (Z_TYPE_P(data) != IS_STRING) {
3165: zval_copy_ctor(&tmp);
3166: convert_to_string(&tmp);
3167: data = &tmp;
3168: }
3169: str = estrndup(Z_STRVAL_P(data), Z_STRLEN_P(data));
3170: whiteSpace_collapse(BAD_CAST(str));
3171: start = str;
3172: while (start != NULL && *start != '\0') {
3173: xmlNodePtr dummy;
3174: zval dummy_zval;
3175:
3176: next = strchr(start,' ');
3177: if (next != NULL) {
3178: *next = '\0';
3179: next++;
3180: }
3181: ZVAL_STRING(&dummy_zval, start, 0);
3182: dummy = master_to_xml(list_enc, &dummy_zval, SOAP_LITERAL, ret);
3183: if (dummy && dummy->children && dummy->children->content) {
3184: if (list.len != 0) {
3185: smart_str_appendc(&list, ' ');
3186: }
3187: smart_str_appends(&list, (char*)dummy->children->content);
3188: } else {
3189: soap_error0(E_ERROR, "Encoding: Violation of encoding rules");
3190: }
3191: xmlUnlinkNode(dummy);
3192: xmlFreeNode(dummy);
3193:
3194: start = next;
3195: }
3196: smart_str_0(&list);
3197: xmlNodeSetContentLen(ret, BAD_CAST(list.c), list.len);
3198: smart_str_free(&list);
3199: efree(str);
3200: if (data == &tmp) {zval_dtor(&tmp);}
3201: }
3202: return ret;
3203: }
3204:
3205: static xmlNodePtr to_xml_list1(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent) {
3206: /*FIXME: minLength=1 */
3207: return to_xml_list(enc,data,style, parent);
3208: }
3209:
3210: static zval* to_zval_union(encodeTypePtr enc, xmlNodePtr data) {
3211: /*FIXME*/
3212: return to_zval_list(enc, data);
3213: }
3214:
3215: static xmlNodePtr to_xml_union(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent) {
3216: /*FIXME*/
3217: return to_xml_list(enc,data,style, parent);
3218: }
3219:
3220: static zval *to_zval_any(encodeTypePtr type, xmlNodePtr data)
3221: {
3222: xmlBufferPtr buf;
3223: zval *ret;
3224: TSRMLS_FETCH();
3225:
3226: if (SOAP_GLOBAL(sdl) && SOAP_GLOBAL(sdl)->elements && data->name) {
3227: smart_str nscat = {0};
3228: sdlTypePtr *sdl_type;
3229:
3230: if (data->ns && data->ns->href) {
3231: smart_str_appends(&nscat, (char*)data->ns->href);
3232: smart_str_appendc(&nscat, ':');
3233: }
3234: smart_str_appends(&nscat, (char*)data->name);
3235: smart_str_0(&nscat);
3236:
3237: if (zend_hash_find(SOAP_GLOBAL(sdl)->elements, nscat.c, nscat.len+1, (void **)&sdl_type) == SUCCESS &&
3238: (*sdl_type)->encode) {
3239: smart_str_free(&nscat);
3240: return master_to_zval_int((*sdl_type)->encode, data);
3241: }
3242: smart_str_free(&nscat);
3243: }
3244:
3245: buf = xmlBufferCreate();
3246: xmlNodeDump(buf, NULL, data, 0, 0);
3247: MAKE_STD_ZVAL(ret);
3248: ZVAL_STRING(ret, (char*)xmlBufferContent(buf), 1);
3249: xmlBufferFree(buf);
3250: return ret;
3251: }
3252:
3253: static xmlNodePtr to_xml_any(encodeTypePtr type, zval *data, int style, xmlNodePtr parent)
3254: {
3255: xmlNodePtr ret = NULL;
3256:
3257: if (Z_TYPE_P(data) == IS_ARRAY) {
3258: HashPosition pos;
3259: zval **el;
3260: encodePtr enc = get_conversion(XSD_ANYXML);
3261: char *name;
3262: uint name_len;
3263: ulong idx;
3264:
3265: for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(data), &pos);
3266: zend_hash_get_current_data_ex(Z_ARRVAL_P(data), (void **) &el, &pos) == SUCCESS;
3267: zend_hash_move_forward_ex(Z_ARRVAL_P(data), &pos)) {
3268: ret = master_to_xml(enc, *el, style, parent);
3269: if (ret &&
3270: ret->name != xmlStringTextNoenc &&
3271: zend_hash_get_current_key_ex(Z_ARRVAL_P(data), &name, &name_len, &idx, 0, &pos) == HASH_KEY_IS_STRING) {
3272: xmlNodeSetName(ret, BAD_CAST(name));
3273: }
3274: }
3275: return ret;
3276: }
3277: if (Z_TYPE_P(data) == IS_STRING) {
3278: ret = xmlNewTextLen(BAD_CAST(Z_STRVAL_P(data)), Z_STRLEN_P(data));
3279: } else {
3280: zval tmp = *data;
3281:
3282: zval_copy_ctor(&tmp);
3283: convert_to_string(&tmp);
3284: ret = xmlNewTextLen(BAD_CAST(Z_STRVAL(tmp)), Z_STRLEN(tmp));
3285: zval_dtor(&tmp);
3286: }
3287:
3288: ret->name = xmlStringTextNoenc;
3289: ret->parent = parent;
3290: ret->doc = parent->doc;
3291: ret->prev = parent->last;
3292: ret->next = NULL;
3293: if (parent->last) {
3294: parent->last->next = ret;
3295: } else {
3296: parent->children = ret;
3297: }
3298: parent->last = ret;
3299:
3300: return ret;
3301: }
3302:
3303: zval *sdl_guess_convert_zval(encodeTypePtr enc, xmlNodePtr data)
3304: {
3305: sdlTypePtr type;
3306:
3307: type = enc->sdl_type;
3308: if (type == NULL) {
3309: return guess_zval_convert(enc, data);
3310: }
3311: /*FIXME: restriction support
3312: if (type && type->restrictions &&
3313: data && data->children && data->children->content) {
3314: if (type->restrictions->whiteSpace && type->restrictions->whiteSpace->value) {
3315: if (strcmp(type->restrictions->whiteSpace->value,"replace") == 0) {
3316: whiteSpace_replace(data->children->content);
3317: } else if (strcmp(type->restrictions->whiteSpace->value,"collapse") == 0) {
3318: whiteSpace_collapse(data->children->content);
3319: }
3320: }
3321: if (type->restrictions->enumeration) {
3322: if (!zend_hash_exists(type->restrictions->enumeration,data->children->content,strlen(data->children->content)+1)) {
3323: soap_error1(E_WARNING, "Encoding: Restriction: invalid enumeration value \"%s\"", data->children->content);
3324: }
3325: }
3326: if (type->restrictions->minLength &&
3327: strlen(data->children->content) < type->restrictions->minLength->value) {
3328: soap_error0(E_WARNING, "Encoding: Restriction: length less than 'minLength'");
3329: }
3330: if (type->restrictions->maxLength &&
3331: strlen(data->children->content) > type->restrictions->maxLength->value) {
3332: soap_error0(E_WARNING, "Encoding: Restriction: length greater than 'maxLength'");
3333: }
3334: if (type->restrictions->length &&
3335: strlen(data->children->content) != type->restrictions->length->value) {
3336: soap_error0(E_WARNING, "Encoding: Restriction: length is not equal to 'length'");
3337: }
3338: }
3339: */
3340: switch (type->kind) {
3341: case XSD_TYPEKIND_SIMPLE:
3342: if (type->encode && enc != &type->encode->details) {
3343: return master_to_zval_int(type->encode, data);
3344: } else {
3345: return guess_zval_convert(enc, data);
3346: }
3347: break;
3348: case XSD_TYPEKIND_LIST:
3349: return to_zval_list(enc, data);
3350: case XSD_TYPEKIND_UNION:
3351: return to_zval_union(enc, data);
3352: case XSD_TYPEKIND_COMPLEX:
3353: case XSD_TYPEKIND_RESTRICTION:
3354: case XSD_TYPEKIND_EXTENSION:
3355: if (type->encode &&
3356: (type->encode->details.type == IS_ARRAY ||
3357: type->encode->details.type == SOAP_ENC_ARRAY)) {
3358: return to_zval_array(enc, data);
3359: }
3360: return to_zval_object(enc, data);
3361: default:
3362: soap_error0(E_ERROR, "Encoding: Internal Error");
3363: return guess_zval_convert(enc, data);
3364: }
3365: }
3366:
3367: xmlNodePtr sdl_guess_convert_xml(encodeTypePtr enc, zval *data, int style, xmlNodePtr parent)
3368: {
3369: sdlTypePtr type;
3370: xmlNodePtr ret = NULL;
3371:
3372: type = enc->sdl_type;
3373:
3374: if (type == NULL) {
3375: ret = guess_xml_convert(enc, data, style, parent);
3376: if (style == SOAP_ENCODED) {
3377: set_ns_and_type(ret, enc);
3378: }
3379: return ret;
3380: }
3381: /*FIXME: restriction support
3382: if (type) {
3383: if (type->restrictions && Z_TYPE_P(data) == IS_STRING) {
3384: if (type->restrictions->enumeration) {
3385: if (!zend_hash_exists(type->restrictions->enumeration,Z_STRVAL_P(data),Z_STRLEN_P(data)+1)) {
3386: soap_error1(E_WARNING, "Encoding: Restriction: invalid enumeration value \"%s\".", Z_STRVAL_P(data));
3387: }
3388: }
3389: if (type->restrictions->minLength &&
3390: Z_STRLEN_P(data) < type->restrictions->minLength->value) {
3391: soap_error0(E_WARNING, "Encoding: Restriction: length less than 'minLength'");
3392: }
3393: if (type->restrictions->maxLength &&
3394: Z_STRLEN_P(data) > type->restrictions->maxLength->value) {
3395: soap_error0(E_WARNING, "Encoding: Restriction: length greater than 'maxLength'");
3396: }
3397: if (type->restrictions->length &&
3398: Z_STRLEN_P(data) != type->restrictions->length->value) {
3399: soap_error0(E_WARNING, "Encoding: Restriction: length is not equal to 'length'");
3400: }
3401: }
3402: }
3403: */
3404: switch(type->kind) {
3405: case XSD_TYPEKIND_SIMPLE:
3406: if (type->encode && enc != &type->encode->details) {
3407: ret = master_to_xml(type->encode, data, style, parent);
3408: } else {
3409: ret = guess_xml_convert(enc, data, style, parent);
3410: }
3411: break;
3412: case XSD_TYPEKIND_LIST:
3413: ret = to_xml_list(enc, data, style, parent);
3414: break;
3415: case XSD_TYPEKIND_UNION:
3416: ret = to_xml_union(enc, data, style, parent);
3417: break;
3418: case XSD_TYPEKIND_COMPLEX:
3419: case XSD_TYPEKIND_RESTRICTION:
3420: case XSD_TYPEKIND_EXTENSION:
3421: if (type->encode &&
3422: (type->encode->details.type == IS_ARRAY ||
3423: type->encode->details.type == SOAP_ENC_ARRAY)) {
3424: return to_xml_array(enc, data, style, parent);
3425: } else {
3426: return to_xml_object(enc, data, style, parent);
3427: }
3428: break;
3429: default:
3430: soap_error0(E_ERROR, "Encoding: Internal Error");
3431: break;
3432: }
3433: if (style == SOAP_ENCODED) {
3434: set_ns_and_type(ret, enc);
3435: }
3436: return ret;
3437: }
3438:
3439: static xmlNodePtr check_and_resolve_href(xmlNodePtr data)
3440: {
3441: if (data && data->properties) {
3442: xmlAttrPtr href;
3443:
3444: href = data->properties;
3445: while (1) {
3446: href = get_attribute(href, "href");
3447: if (href == NULL || href->ns == NULL) {break;}
3448: href = href->next;
3449: }
3450: if (href) {
3451: /* Internal href try and find node */
3452: if (href->children->content[0] == '#') {
3453: xmlNodePtr ret = get_node_with_attribute_recursive(data->doc->children, NULL, "id", (char*)&href->children->content[1]);
3454: if (!ret) {
3455: soap_error1(E_ERROR, "Encoding: Unresolved reference '%s'", href->children->content);
3456: }
3457: return ret;
3458: } else {
3459: /* TODO: External href....? */
3460: soap_error1(E_ERROR, "Encoding: External reference '%s'", href->children->content);
3461: }
3462: }
3463: /* SOAP 1.2 enc:id enc:ref */
3464: href = get_attribute_ex(data->properties, "ref", SOAP_1_2_ENC_NAMESPACE);
3465: if (href) {
3466: xmlChar* id;
3467: xmlNodePtr ret;
3468:
3469: if (href->children->content[0] == '#') {
3470: id = href->children->content+1;
3471: } else {
3472: id = href->children->content;
3473: }
3474: ret = get_node_with_attribute_recursive_ex(data->doc->children, NULL, NULL, "id", (char*)id, SOAP_1_2_ENC_NAMESPACE);
3475: if (!ret) {
3476: soap_error1(E_ERROR, "Encoding: Unresolved reference '%s'", href->children->content);
3477: } else if (ret == data) {
3478: soap_error1(E_ERROR, "Encoding: Violation of id and ref information items '%s'", href->children->content);
3479: }
3480: return ret;
3481: }
3482: }
3483: return data;
3484: }
3485:
3486: static void set_ns_and_type(xmlNodePtr node, encodeTypePtr type)
3487: {
3488: set_ns_and_type_ex(node, type->ns, type->type_str);
3489: }
3490:
3491: static void set_ns_and_type_ex(xmlNodePtr node, char *ns, char *type)
3492: {
3493: smart_str nstype = {0};
3494: get_type_str(node, ns, type, &nstype);
3495: set_xsi_type(node, nstype.c);
3496: smart_str_free(&nstype);
3497: }
3498:
3499: static xmlNsPtr xmlSearchNsPrefixByHref(xmlDocPtr doc, xmlNodePtr node, const xmlChar * href)
3500: {
3501: xmlNsPtr cur;
3502: xmlNodePtr orig = node;
3503:
3504: while (node) {
3505: if (node->type == XML_ENTITY_REF_NODE ||
3506: node->type == XML_ENTITY_NODE ||
3507: node->type == XML_ENTITY_DECL) {
3508: return NULL;
3509: }
3510: if (node->type == XML_ELEMENT_NODE) {
3511: cur = node->nsDef;
3512: while (cur != NULL) {
3513: if (cur->prefix && cur->href && xmlStrEqual(cur->href, href)) {
3514: if (xmlSearchNs(doc, node, cur->prefix) == cur) {
3515: return cur;
3516: }
3517: }
3518: cur = cur->next;
3519: }
3520: if (orig != node) {
3521: cur = node->ns;
3522: if (cur != NULL) {
3523: if (cur->prefix && cur->href && xmlStrEqual(cur->href, href)) {
3524: if (xmlSearchNs(doc, node, cur->prefix) == cur) {
3525: return cur;
3526: }
3527: }
3528: }
3529: }
3530: }
3531: node = node->parent;
3532: }
3533: return NULL;
3534: }
3535:
3536: xmlNsPtr encode_add_ns(xmlNodePtr node, const char* ns)
3537: {
3538: xmlNsPtr xmlns;
3539:
3540: if (ns == NULL) {
3541: return NULL;
3542: }
3543:
3544: xmlns = xmlSearchNsByHref(node->doc, node, BAD_CAST(ns));
3545: if (xmlns != NULL && xmlns->prefix == NULL) {
3546: xmlns = xmlSearchNsPrefixByHref(node->doc, node, BAD_CAST(ns));
3547: }
3548: if (xmlns == NULL) {
3549: xmlChar* prefix;
3550: TSRMLS_FETCH();
3551:
3552: if (zend_hash_find(&SOAP_GLOBAL(defEncNs), (char*)ns, strlen(ns) + 1, (void **)&prefix) == SUCCESS) {
3553: xmlns = xmlNewNs(node->doc->children, BAD_CAST(ns), prefix);
3554: } else {
3555: smart_str prefix = {0};
3556: int num = ++SOAP_GLOBAL(cur_uniq_ns);
3557:
3558: while (1) {
3559: smart_str_appendl(&prefix, "ns", 2);
3560: smart_str_append_long(&prefix, num);
3561: smart_str_0(&prefix);
3562: if (xmlSearchNs(node->doc, node, BAD_CAST(prefix.c)) == NULL) {
3563: break;
3564: }
3565: smart_str_free(&prefix);
3566: prefix.c = NULL;
3567: prefix.len = 0;
3568: num = ++SOAP_GLOBAL(cur_uniq_ns);
3569: }
3570:
3571: xmlns = xmlNewNs(node->doc->children, BAD_CAST(ns), BAD_CAST(prefix.c));
3572: smart_str_free(&prefix);
3573: }
3574: }
3575: return xmlns;
3576: }
3577:
3578: static void set_ns_prop(xmlNodePtr node, char *ns, char *name, char *val)
3579: {
3580: xmlSetNsProp(node, encode_add_ns(node, ns), BAD_CAST(name), BAD_CAST(val));
3581: }
3582:
3583: static void set_xsi_nil(xmlNodePtr node)
3584: {
3585: set_ns_prop(node, XSI_NAMESPACE, "nil", "true");
3586: }
3587:
3588: static void set_xsi_type(xmlNodePtr node, char *type)
3589: {
3590: set_ns_prop(node, XSI_NAMESPACE, "type", type);
3591: }
3592:
3593: void encode_reset_ns()
3594: {
3595: TSRMLS_FETCH();
3596: SOAP_GLOBAL(cur_uniq_ns) = 0;
3597: SOAP_GLOBAL(cur_uniq_ref) = 0;
3598: if (SOAP_GLOBAL(ref_map)) {
3599: zend_hash_destroy(SOAP_GLOBAL(ref_map));
3600: } else {
3601: SOAP_GLOBAL(ref_map) = emalloc(sizeof(HashTable));
3602: }
3603: zend_hash_init(SOAP_GLOBAL(ref_map), 0, NULL, NULL, 0);
3604: }
3605:
3606: void encode_finish()
3607: {
3608: TSRMLS_FETCH();
3609: SOAP_GLOBAL(cur_uniq_ns) = 0;
3610: SOAP_GLOBAL(cur_uniq_ref) = 0;
3611: if (SOAP_GLOBAL(ref_map)) {
3612: zend_hash_destroy(SOAP_GLOBAL(ref_map));
3613: efree(SOAP_GLOBAL(ref_map));
3614: SOAP_GLOBAL(ref_map) = NULL;
3615: }
3616: }
3617:
3618: encodePtr get_conversion(int encode)
3619: {
3620: encodePtr *enc = NULL;
3621: TSRMLS_FETCH();
3622:
3623: if (zend_hash_index_find(&SOAP_GLOBAL(defEncIndex), encode, (void **)&enc) == FAILURE) {
3624: soap_error0(E_ERROR, "Encoding: Cannot find encoding");
3625: return NULL;
3626: } else {
3627: return *enc;
3628: }
3629: }
3630:
3631: static int is_map(zval *array)
3632: {
3633: int i, count = zend_hash_num_elements(Z_ARRVAL_P(array));
3634:
3635: zend_hash_internal_pointer_reset(Z_ARRVAL_P(array));
3636: for (i = 0; i < count; i++) {
3637: char *str_index;
3638: ulong num_index;
3639:
3640: if (zend_hash_get_current_key(Z_ARRVAL_P(array), &str_index, &num_index, 0) == HASH_KEY_IS_STRING ||
3641: num_index != i) {
3642: return TRUE;
3643: }
3644: zend_hash_move_forward(Z_ARRVAL_P(array));
3645: }
3646: return FALSE;
3647: }
3648:
3649: static encodePtr get_array_type(xmlNodePtr node, zval *array, smart_str *type TSRMLS_DC)
3650: {
3651: HashTable *ht;
3652: int i, count, cur_type, prev_type, different;
3653: zval **tmp;
3654: char *prev_stype = NULL, *cur_stype = NULL, *prev_ns = NULL, *cur_ns = NULL;
3655:
3656: if (!array || Z_TYPE_P(array) != IS_ARRAY) {
3657: smart_str_appendl(type, "xsd:anyType", sizeof("xsd:anyType")-1);
3658: return get_conversion(XSD_ANYTYPE);
3659: }
3660:
3661: different = FALSE;
3662: cur_type = prev_type = 0;
3663: ht = HASH_OF(array);
3664: count = zend_hash_num_elements(ht);
3665:
3666: zend_hash_internal_pointer_reset(ht);
3667: for (i = 0;i < count;i++) {
3668: zend_hash_get_current_data(ht, (void **)&tmp);
3669:
3670: if (Z_TYPE_PP(tmp) == IS_OBJECT &&
3671: Z_OBJCE_PP(tmp) == soap_var_class_entry) {
3672: zval **ztype;
3673:
3674: if (zend_hash_find(Z_OBJPROP_PP(tmp), "enc_type", sizeof("enc_type"), (void **)&ztype) == FAILURE) {
3675: soap_error0(E_ERROR, "Encoding: SoapVar has no 'enc_type' property");
3676: }
3677: cur_type = Z_LVAL_PP(ztype);
3678:
3679: if (zend_hash_find(Z_OBJPROP_PP(tmp), "enc_stype", sizeof("enc_stype"), (void **)&ztype) == SUCCESS) {
3680: cur_stype = Z_STRVAL_PP(ztype);
3681: } else {
3682: cur_stype = NULL;
3683: }
3684:
3685: if (zend_hash_find(Z_OBJPROP_PP(tmp), "enc_ns", sizeof("enc_ns"), (void **)&ztype) == SUCCESS) {
3686: cur_ns = Z_STRVAL_PP(ztype);
3687: } else {
3688: cur_ns = NULL;
3689: }
3690:
3691: } else if (Z_TYPE_PP(tmp) == IS_ARRAY && is_map(*tmp)) {
3692: cur_type = APACHE_MAP;
3693: cur_stype = NULL;
3694: cur_ns = NULL;
3695: } else {
3696: cur_type = Z_TYPE_PP(tmp);
3697: cur_stype = NULL;
3698: cur_ns = NULL;
3699: }
3700:
3701: if (i > 0) {
3702: if ((cur_type != prev_type) ||
3703: (cur_stype != NULL && prev_stype != NULL && strcmp(cur_stype,prev_stype) != 0) ||
3704: (cur_stype == NULL && cur_stype != prev_stype) ||
3705: (cur_ns != NULL && prev_ns != NULL && strcmp(cur_ns,prev_ns) != 0) ||
3706: (cur_ns == NULL && cur_ns != prev_ns)) {
3707: different = TRUE;
3708: break;
3709: }
3710: }
3711:
3712: prev_type = cur_type;
3713: prev_stype = cur_stype;
3714: prev_ns = cur_ns;
3715: zend_hash_move_forward(ht);
3716: }
3717:
3718: if (different || count == 0) {
3719: smart_str_appendl(type, "xsd:anyType", sizeof("xsd:anyType")-1);
3720: return get_conversion(XSD_ANYTYPE);
3721: } else {
3722: encodePtr enc;
3723:
3724: if (cur_stype != NULL) {
3725: smart_str array_type = {0};
3726:
3727: if (cur_ns) {
3728: xmlNsPtr ns = encode_add_ns(node,cur_ns);
3729:
3730: smart_str_appends(type, (char*)ns->prefix);
3731: smart_str_appendc(type, ':');
3732: smart_str_appends(&array_type, cur_ns);
3733: smart_str_appendc(&array_type, ':');
3734: }
3735: smart_str_appends(type, cur_stype);
3736: smart_str_0(type);
3737: smart_str_appends(&array_type, cur_stype);
3738: smart_str_0(&array_type);
3739:
3740: enc = get_encoder_ex(SOAP_GLOBAL(sdl), array_type.c, array_type.len);
3741: smart_str_free(&array_type);
3742: return enc;
3743: } else {
3744: enc = get_conversion(cur_type);
3745: get_type_str(node, enc->details.ns, enc->details.type_str, type);
3746: return enc;
3747: }
3748: }
3749: }
3750:
3751: static void get_type_str(xmlNodePtr node, const char* ns, const char* type, smart_str* ret)
3752: {
3753: TSRMLS_FETCH();
3754:
3755: if (ns) {
3756: xmlNsPtr xmlns;
3757: if (SOAP_GLOBAL(soap_version) == SOAP_1_2 &&
3758: strcmp(ns,SOAP_1_1_ENC_NAMESPACE) == 0) {
3759: ns = SOAP_1_2_ENC_NAMESPACE;
3760: } else if (SOAP_GLOBAL(soap_version) == SOAP_1_1 &&
3761: strcmp(ns,SOAP_1_2_ENC_NAMESPACE) == 0) {
3762: ns = SOAP_1_1_ENC_NAMESPACE;
3763: }
3764: xmlns = encode_add_ns(node,ns);
3765: smart_str_appends(ret, (char*)xmlns->prefix);
3766: smart_str_appendc(ret, ':');
3767: }
3768: smart_str_appendl(ret, type, strlen(type));
3769: smart_str_0(ret);
3770: }
3771:
3772: static void delete_mapping(void *data)
3773: {
3774: soapMappingPtr map = (soapMappingPtr)data;
3775:
3776: if (map->to_xml) {
3777: zval_ptr_dtor(&map->to_xml);
3778: }
3779: if (map->to_zval) {
3780: zval_ptr_dtor(&map->to_zval);
3781: }
3782: efree(map);
3783: }
3784:
3785: void delete_encoder(void *encode)
3786: {
3787: encodePtr t = *((encodePtr*)encode);
3788: if (t->details.ns) {
3789: efree(t->details.ns);
3790: }
3791: if (t->details.type_str) {
3792: efree(t->details.type_str);
3793: }
3794: if (t->details.map) {
3795: delete_mapping(t->details.map);
3796: }
3797: efree(t);
3798: }
3799:
3800: void delete_encoder_persistent(void *encode)
3801: {
3802: encodePtr t = *((encodePtr*)encode);
3803: if (t->details.ns) {
3804: free(t->details.ns);
3805: }
3806: if (t->details.type_str) {
3807: free(t->details.type_str);
3808: }
3809: /* we should never have mapping in persistent encoder */
3810: assert(t->details.map == NULL);
3811: free(t);
3812: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>