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