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