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