diff options
author | Dmitry Stogov <dmitry@php.net> | 2004-01-26 09:51:07 +0000 |
---|---|---|
committer | Dmitry Stogov <dmitry@php.net> | 2004-01-26 09:51:07 +0000 |
commit | e3cfa02b4e7b26cd153783109533ed75b943d57d (patch) | |
tree | 3a304b3ecbbc7b02fda6a5e3788e0db52f79aa96 /ext/soap/php_encoding.c | |
parent | 7e6b108a96919e88e7f62d3a3a3d1904ca191546 (diff) | |
download | php-git-e3cfa02b4e7b26cd153783109533ed75b943d57d.tar.gz |
XML Schema support (decoding of xsi:nil with attributes)
Source Cleanup
Diffstat (limited to 'ext/soap/php_encoding.c')
-rw-r--r-- | ext/soap/php_encoding.c | 294 |
1 files changed, 269 insertions, 25 deletions
diff --git a/ext/soap/php_encoding.c b/ext/soap/php_encoding.c index 324594f786..16f3b8ca81 100644 --- a/ext/soap/php_encoding.c +++ b/ext/soap/php_encoding.c @@ -41,12 +41,50 @@ static xmlNodePtr to_xml_gday(encodeTypePtr type, zval *data, int style); static xmlNodePtr to_xml_gmonth(encodeTypePtr type, zval *data, int style); static xmlNodePtr to_xml_duration(encodeTypePtr type, zval *data, int style); +static zval *to_zval_object(encodeTypePtr type, xmlNodePtr data); +static zval *to_zval_array(encodeTypePtr type, xmlNodePtr data); + +static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style); +static xmlNodePtr to_xml_array(encodeTypePtr type, zval *data, int style); + +/* Try and guess for non-wsdl clients and servers */ +static zval *guess_zval_convert(encodeTypePtr type, xmlNodePtr data); +static xmlNodePtr guess_xml_convert(encodeTypePtr type, zval *data, int style); + static int is_map(zval *array); static void get_array_type(xmlNodePtr node, zval *array, smart_str *out_type TSRMLS_DC); static void get_type_str(xmlNodePtr node, const char* ns, const char* type, smart_str* ret); static void set_ns_and_type_ex(xmlNodePtr node, char *ns, char *type); +static void set_ns_and_type(xmlNodePtr node, encodeTypePtr type); + +#define FIND_XML_NULL(xml,zval) \ + { \ + xmlAttrPtr null; \ + if (!xml) { \ + ZVAL_NULL(zval); \ + return zval; \ + } \ + if (xml->properties) { \ + null = get_attribute(xml->properties, "nil"); \ + if (null) { \ + ZVAL_NULL(zval); \ + return zval; \ + } \ + } \ + } + +#define FIND_ZVAL_NULL(zval, xml, style) \ +{ \ + if (!zval || Z_TYPE_P(zval) == IS_NULL) { \ + if (style == SOAP_ENCODED) {\ + xmlSetProp(xml, "xsi:nil", "1"); \ + }\ + return xml; \ + } \ +} + encode defaultEncoding[] = { {{UNKNOWN_TYPE, NULL, NULL, NULL}, guess_zval_convert, guess_xml_convert}, @@ -653,10 +691,7 @@ static zval *to_zval_null(encodeTypePtr type, xmlNodePtr data) static xmlNodePtr to_xml_null(encodeTypePtr type, zval *data, int style) { - xmlNodePtr ret; - - ret = xmlNewNode(NULL, "BOGUS"); - FIND_ZVAL_NULL(data, ret, style); + xmlNodePtr ret = xmlNewNode(NULL, "BOGUS"); if (style == SOAP_ENCODED) { xmlSetProp(ret, "xsi:nil", "1"); @@ -727,7 +762,7 @@ static void model_to_zval_object(zval *ret, sdlContentModelPtr model, xmlNodePtr } /* Struct encode/decode */ -zval *to_zval_object(encodeTypePtr type, xmlNodePtr data) +static zval *to_zval_object(encodeTypePtr type, xmlNodePtr data) { zval *ret; xmlNodePtr trav; @@ -752,7 +787,6 @@ zval *to_zval_object(encodeTypePtr type, xmlNodePtr data) zval *base; MAKE_STD_ZVAL(ret); - FIND_XML_NULL(data, ret); object_init(ret); base = master_to_zval(enc, data); @@ -778,7 +812,6 @@ zval *to_zval_object(encodeTypePtr type, xmlNodePtr data) zval *base; MAKE_STD_ZVAL(ret); - FIND_XML_NULL(data, ret); object_init(ret); base = master_to_zval(sdlType->encode, data); @@ -919,7 +952,7 @@ static int model_to_xml_object(xmlNodePtr node, sdlContentModelPtr model, HashTa return 1; } -xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style) +static xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style) { xmlNodePtr xmlParam; HashTable *prop; @@ -1076,9 +1109,9 @@ xmlNodePtr to_xml_object(encodeTypePtr type, zval *data, int style) xmlAddChild(xmlParam, property); zend_hash_move_forward(prop); } - if (style == SOAP_ENCODED) { - set_ns_and_type(xmlParam, type); - } + } + if (style == SOAP_ENCODED) { + set_ns_and_type(xmlParam, type); } } return xmlParam; @@ -1275,7 +1308,7 @@ static inline int array_num_elements(HashTable* ht) return 0; } -xmlNodePtr to_xml_array(encodeTypePtr type, zval *data, int style) +static xmlNodePtr to_xml_array(encodeTypePtr type, zval *data, int style) { sdlTypePtr sdl_type = type->sdl_type; smart_str array_type = {0}, array_size = {0}; @@ -1474,14 +1507,14 @@ xmlNodePtr to_xml_array(encodeTypePtr type, zval *data, int style) add_xml_array_elements(xmlParam, sdl_type, enc, dimension, dims, data, style); efree(dims); - if (style == SOAP_ENCODED) { - set_ns_and_type(xmlParam, type); - } + } + if (style == SOAP_ENCODED) { + set_ns_and_type(xmlParam, type); } return xmlParam; } -zval *to_zval_array(encodeTypePtr type, xmlNodePtr data) +static zval *to_zval_array(encodeTypePtr type, xmlNodePtr data) { zval *ret; xmlNodePtr trav; @@ -1728,7 +1761,7 @@ static xmlNodePtr to_xml_map(encodeTypePtr type, zval *data, int style) if (Z_TYPE_P(data) == IS_ARRAY) { i = zend_hash_num_elements(Z_ARRVAL_P(data)); /* TODO: Register namespace...??? */ - xmlSetProp(xmlParam, "xmlns:apache", "http://xml.apache.org/xml-soap"); +// xmlSetProp(xmlParam, APACHE_NS_PREFIX, APACHE_NAMESPACE); zend_hash_internal_pointer_reset(data->value.ht); for (;i > 0;i--) { xmlNodePtr xparam, item; @@ -1771,9 +1804,9 @@ static xmlNodePtr to_xml_map(encodeTypePtr type, zval *data, int style) } zend_hash_move_forward(data->value.ht); } - if (style == SOAP_ENCODED) { - set_ns_and_type(xmlParam, type); - } + } + if (style == SOAP_ENCODED) { + set_ns_and_type(xmlParam, type); } return xmlParam; @@ -1816,6 +1849,7 @@ static zval *to_zval_map(encodeTypePtr type, xmlNodePtr data) } else { php_error(E_ERROR, "Error encoding apache map, only Strings or Longs are allowd as keys"); } + zval_ptr_dtor(&key); } ENDFOREACH(trav); } else { @@ -1825,7 +1859,7 @@ static zval *to_zval_map(encodeTypePtr type, xmlNodePtr data) } /* Unknown encode/decode */ -xmlNodePtr guess_xml_convert(encodeTypePtr type, zval *data, int style) +static xmlNodePtr guess_xml_convert(encodeTypePtr type, zval *data, int style) { encodePtr enc; TSRMLS_FETCH(); @@ -1838,7 +1872,7 @@ xmlNodePtr guess_xml_convert(encodeTypePtr type, zval *data, int style) return master_to_xml(enc, data, style); } -zval *guess_zval_convert(encodeTypePtr type, xmlNodePtr data) +static zval *guess_zval_convert(encodeTypePtr type, xmlNodePtr data) { encodePtr enc = NULL; xmlAttrPtr tmpattr; @@ -1941,8 +1975,6 @@ static xmlNodePtr to_xml_datetime_ex(encodeTypePtr type, zval *data, char *forma strcpy(buf, Z_STRVAL_P(data)); xmlNodeSetContentLen(xmlParam, buf, Z_STRLEN_P(data)); - } else { - xmlSetProp(xmlParam, "xsi:nil", "1"); } if (style == SOAP_ENCODED) { @@ -1998,7 +2030,185 @@ static xmlNodePtr to_xml_gmonth(encodeTypePtr type, zval *data, int style) return to_xml_datetime_ex(type, data, "--%m--", style); } -void set_ns_and_type(xmlNodePtr node, encodeTypePtr type) +static zval* to_zval_list(encodeTypePtr enc, xmlNodePtr data) { + /*FIXME*/ + return to_zval_stringc(enc, data); +} + +static xmlNodePtr to_xml_list(encodeTypePtr enc, zval *data, int style) { + xmlNodePtr ret; + + ret = xmlNewNode(NULL, "BOGUS"); + FIND_ZVAL_NULL(data, ret, style); + if (Z_TYPE_P(data) == IS_ARRAY) { + zval **tmp; + smart_str list = {0}; + HashTable *ht = Z_ARRVAL_P(data); + + zend_hash_internal_pointer_reset(ht); + while (zend_hash_get_current_data(ht, (void**)&tmp) == SUCCESS) { + if (list.len != 0) { + smart_str_appendc(&list, ' '); + } + if (Z_TYPE_PP(tmp) == IS_STRING) { + smart_str_appendl(&list, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp)); + } else { + zval copy = **tmp; + zval_copy_ctor(©); + convert_to_string(©); + smart_str_appendl(&list, Z_STRVAL(copy), Z_STRLEN(copy)); + zval_dtor(©); + } + zend_hash_move_forward(ht); + } + smart_str_0(&list); + xmlNodeSetContentLen(ret, list.c, list.len); + smart_str_free(&list); + } else if (Z_TYPE_P(data) == IS_STRING) { + xmlNodeSetContentLen(ret, Z_STRVAL_P(data), Z_STRLEN_P(data)); + } else { + zval tmp = *data; + + zval_copy_ctor(&tmp); + convert_to_string(&tmp); + xmlNodeSetContentLen(ret, Z_STRVAL(tmp), Z_STRLEN(tmp)); + zval_dtor(&tmp); + } + return ret; +} + +static zval* to_zval_union(encodeTypePtr enc, xmlNodePtr data) { + /*FIXME*/ + return to_zval_list(enc, data); +} + +static xmlNodePtr to_xml_union(encodeTypePtr enc, zval *data, int style) { + /*FIXME*/ + return to_xml_list(enc,data,style); +} + +zval *sdl_guess_convert_zval(encodeTypePtr enc, xmlNodePtr data) +{ + sdlTypePtr type; + + type = enc->sdl_type; + + if (type && type->restrictions && + data && data->children && data->children->content) { + if (type->restrictions->whiteSpace && type->restrictions->whiteSpace->value) { + if (strcmp(type->restrictions->whiteSpace->value,"replace") == 0) { + whiteSpace_replace(data->children->content); + } else if (strcmp(type->restrictions->whiteSpace->value,"collapse") == 0) { + whiteSpace_collapse(data->children->content); + } + } + if (type->restrictions->enumeration) { + if (!zend_hash_exists(type->restrictions->enumeration,data->children->content,strlen(data->children->content)+1)) { + php_error(E_WARNING,"Restriction: invalid enumeration value \"%s\"",data->children->content); + } + } + if (type->restrictions->minLength && + strlen(data->children->content) < type->restrictions->minLength->value) { + php_error(E_WARNING,"Restriction: length less then 'minLength'"); + } + if (type->restrictions->maxLength && + strlen(data->children->content) > type->restrictions->maxLength->value) { + php_error(E_WARNING,"Restriction: length greater then 'maxLength'"); + } + if (type->restrictions->length && + strlen(data->children->content) != type->restrictions->length->value) { + php_error(E_WARNING,"Restriction: length is not equal to 'length'"); + } + } + switch (type->kind) { + case XSD_TYPEKIND_SIMPLE: + if (type->encode && enc != &type->encode->details) { + return master_to_zval(type->encode, data); + } + break; + case XSD_TYPEKIND_LIST: + return to_zval_list(enc, data); + case XSD_TYPEKIND_UNION: + return to_zval_union(enc, data); + case XSD_TYPEKIND_COMPLEX: + case XSD_TYPEKIND_RESTRICTION: + case XSD_TYPEKIND_EXTENSION: + if (type->encode && + (type->encode->details.type == IS_ARRAY || + type->encode->details.type == SOAP_ENC_ARRAY)) { + return to_zval_array(enc, data); + } + return to_zval_object(enc, data); + default: + break; + } + return guess_zval_convert(enc, data); +} + +xmlNodePtr sdl_guess_convert_xml(encodeTypePtr enc, zval *data, int style) +{ + sdlTypePtr type; + xmlNodePtr ret = NULL; + + type = enc->sdl_type; + + if (type) { + if (type->restrictions && Z_TYPE_P(data) == IS_STRING) { + if (type->restrictions->enumeration) { + if (!zend_hash_exists(type->restrictions->enumeration,Z_STRVAL_P(data),Z_STRLEN_P(data)+1)) { + php_error(E_WARNING,"Restriction: invalid enumeration value \"%s\".",Z_STRVAL_P(data)); + } + } + if (type->restrictions->minLength && + Z_STRLEN_P(data) < type->restrictions->minLength->value) { + php_error(E_WARNING,"Restriction: length less then 'minLength'"); + } + if (type->restrictions->maxLength && + Z_STRLEN_P(data) > type->restrictions->maxLength->value) { + php_error(E_WARNING,"Restriction: length greater then 'maxLength'"); + } + if (type->restrictions->length && + Z_STRLEN_P(data) != type->restrictions->length->value) { + php_error(E_WARNING,"Restriction: length is not equal to 'length'"); + } + } + } + switch(type->kind) { + case XSD_TYPEKIND_SIMPLE: + if (type->encode && enc != &type->encode->details) { + ret = master_to_xml(type->encode, data, style); + } + break; + case XSD_TYPEKIND_LIST: + ret = to_xml_list(enc, data, style); + break; + case XSD_TYPEKIND_UNION: + ret = to_xml_union(enc, data, style); + break; + case XSD_TYPEKIND_COMPLEX: + case XSD_TYPEKIND_RESTRICTION: + case XSD_TYPEKIND_EXTENSION: + if (type->encode && + (type->encode->details.type == IS_ARRAY || + type->encode->details.type == SOAP_ENC_ARRAY)) { + ret = to_xml_array(enc, data, style); + } else { + ret = to_xml_object(enc, data, style); + } + break; + default: + break; + } + if (ret == NULL) { + ret = guess_xml_convert(enc, data, style); + } + if (style == SOAP_ENCODED) { + set_ns_and_type(ret, enc); + } + return ret; +} + +static void set_ns_and_type(xmlNodePtr node, encodeTypePtr type) { set_ns_and_type_ex(node, type->ns, type->type_str); } @@ -2252,6 +2462,40 @@ smart_str *build_soap_action(zval *this_ptr, char *soapaction) return tmp; } +static void delete_mapping(void *data) +{ + soapMappingPtr map = (soapMappingPtr)data; + + if (map->ns) { + efree(map->ns); + } + if (map->ctype) { + efree(map->ctype); + } + + if (map->type == SOAP_MAP_FUNCTION) { + if (map->map_functions.to_xml_before) { + zval_ptr_dtor(&map->map_functions.to_xml_before); + } + if (map->map_functions.to_xml) { + zval_ptr_dtor(&map->map_functions.to_xml); + } + if (map->map_functions.to_xml_after) { + zval_ptr_dtor(&map->map_functions.to_xml_after); + } + if (map->map_functions.to_zval_before) { + zval_ptr_dtor(&map->map_functions.to_zval_before); + } + if (map->map_functions.to_zval) { + zval_ptr_dtor(&map->map_functions.to_zval); + } + if (map->map_functions.to_zval_after) { + zval_ptr_dtor(&map->map_functions.to_zval_after); + } + } + efree(map); +} + void delete_encoder(void *encode) { encodePtr t = *((encodePtr*)encode); |