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