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