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