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