Annotation of embedaddon/php/ext/soap/php_encoding.c, revision 1.1
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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>