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