diff --git a/NEWS b/NEWS index c0f20b747da..6dffb0cc847 100644 --- a/NEWS +++ b/NEWS @@ -184,6 +184,8 @@ PHP NEWS - SOAP: . Fixed bug #49169 (SoapServer calls wrong function, although "SOAP action" header is correct). (nielsdos) + . Fix namespace handling of WSDL and XML schema in SOAP, + fixing at least GH-16320 and bug #68576. (nielsdos) - Sockets: . Added IPPROTO_ICMP/IPPROTO_ICMPV6 to create raw socket for ICMP usage. diff --git a/ext/soap/php_encoding.c b/ext/soap/php_encoding.c index bc8e42ef0df..c4fa7702cf4 100644 --- a/ext/soap/php_encoding.c +++ b/ext/soap/php_encoding.c @@ -104,7 +104,7 @@ static void set_ns_and_type(xmlNodePtr node, encodeTypePtr type); return zval; \ } \ if (xml->properties) { \ - null = get_attribute(xml->properties, "nil"); \ + null = get_attribute_ex(xml->properties, "nil", XSI_NAMESPACE); \ if (null) { \ ZVAL_NULL(zval); \ return zval; \ @@ -287,13 +287,7 @@ static bool soap_check_zval_ref(zval *data, xmlNodePtr node) { return 0; } if (SOAP_GLOBAL(soap_version) == SOAP_1_1) { - while (1) { - attr = get_attribute(attr, "id"); - if (attr == NULL || attr->ns == NULL) { - break; - } - attr = attr->next; - } + attr = get_attribute(attr, "id"); if (attr) { id = (char*)attr->children->content; smart_str_appendc(&prefix, '#'); @@ -1530,7 +1524,7 @@ static zval *to_zval_object_ex(zval *ret, encodeTypePtr type, xmlNodePtr data, z ZEND_HASH_FOREACH_PTR(sdlType->attributes, attr) { if (attr->name) { - xmlAttrPtr val = get_attribute(data->properties, attr->name); + xmlAttrPtr val = get_attribute_any_ns(data->properties, attr->name); char *str_val = NULL; if (val && val->children && val->children->content) { @@ -2485,6 +2479,26 @@ iterator_failed_to_get: return xmlParam; } +static xmlAttrPtr get_soap_1_1_enc_attribute(xmlAttrPtr props, const char *name) +{ + return get_attribute_ex(props, name, SOAP_1_1_ENC_NAMESPACE); +} + +static xmlAttrPtr get_soap_1_2_enc_attribute(xmlAttrPtr props, const char *name) +{ + return get_attribute_ex(props, name, SOAP_1_2_ENC_NAMESPACE); +} + +/* Be forgiving for BC */ +static xmlAttrPtr get_soap_enc_attribute(xmlAttrPtr props, const char *name) +{ + xmlAttrPtr res = get_soap_1_1_enc_attribute(props, name); + if (!res) { + res = get_soap_1_2_enc_attribute(props, name); + } + return res; +} + static zval *to_zval_array(zval *ret, encodeTypePtr type, xmlNodePtr data) { xmlNodePtr trav; @@ -2501,7 +2515,7 @@ static zval *to_zval_array(zval *ret, encodeTypePtr type, xmlNodePtr data) FIND_XML_NULL(data, ret); if (data && - (attr = get_attribute(data->properties,"arrayType")) && + (attr = get_soap_enc_attribute(data->properties,"arrayType")) && attr->children && attr->children->content) { const char *type; char *end, *ns; @@ -2521,7 +2535,7 @@ static zval *to_zval_array(zval *ret, encodeTypePtr type, xmlNodePtr data) } if (ns) {efree(ns);} - } else if ((attr = get_attribute(data->properties,"itemType")) && + } else if ((attr = get_soap_enc_attribute(data->properties,"itemType")) && attr->children && attr->children->content) { const char *type; @@ -2535,7 +2549,7 @@ static zval *to_zval_array(zval *ret, encodeTypePtr type, xmlNodePtr data) } if (ns) {efree(ns);} - if ((attr = get_attribute(data->properties,"arraySize")) && + if ((attr = get_soap_enc_attribute(data->properties,"arraySize")) && attr->children && attr->children->content) { dimension = calc_dimension_12((char*)attr->children->content); dims = get_position_12(dimension, (char*)attr->children->content); @@ -2544,7 +2558,7 @@ static zval *to_zval_array(zval *ret, encodeTypePtr type, xmlNodePtr data) *dims = 0; } - } else if ((attr = get_attribute(data->properties,"arraySize")) && + } else if ((attr = get_soap_enc_attribute(data->properties,"arraySize")) && attr->children && attr->children->content) { dimension = calc_dimension_12((char*)attr->children->content); @@ -2623,7 +2637,7 @@ static zval *to_zval_array(zval *ret, encodeTypePtr type, xmlNodePtr data) pos = safe_emalloc(sizeof(int), dimension, 0); memset(pos,0,sizeof(int)*dimension); if (data && - (attr = get_attribute(data->properties,"offset")) && + (attr = get_soap_enc_attribute(data->properties,"offset")) && attr->children && attr->children->content) { char* tmp = strrchr((char*)attr->children->content,'['); @@ -2639,7 +2653,7 @@ static zval *to_zval_array(zval *ret, encodeTypePtr type, xmlNodePtr data) if (trav->type == XML_ELEMENT_NODE) { int i; zval tmpVal, *ar; - xmlAttrPtr position = get_attribute(trav->properties,"position"); + xmlAttrPtr position = get_soap_enc_attribute(trav->properties,"position"); ZVAL_NULL(&tmpVal); master_to_zval(&tmpVal, enc, trav); @@ -2854,9 +2868,9 @@ static zval *guess_zval_convert(zval *ret, encodeTypePtr type, xmlNodePtr data) /* Logic: has children = IS_OBJECT else IS_STRING */ xmlNodePtr trav; - if (get_attribute(data->properties, "arrayType") || - get_attribute(data->properties, "itemType") || - get_attribute(data->properties, "arraySize")) { + if (get_soap_enc_attribute(data->properties, "arrayType") || + get_soap_enc_attribute(data->properties, "itemType") || + get_soap_enc_attribute(data->properties, "arraySize")) { enc = get_conversion(SOAP_ENC_ARRAY); } else { enc = get_conversion(XSD_STRING); @@ -3340,14 +3354,7 @@ xmlNodePtr sdl_guess_convert_xml(encodeTypePtr enc, zval *data, int style, xmlNo static xmlNodePtr check_and_resolve_href(xmlNodePtr data) { if (data && data->properties) { - xmlAttrPtr href; - - href = data->properties; - while (1) { - href = get_attribute(href, "href"); - if (href == NULL || href->ns == NULL) {break;} - href = href->next; - } + xmlAttrPtr href = get_attribute(data->properties, "href"); if (href) { /* Internal href try and find node */ if (href->children->content[0] == '#') { diff --git a/ext/soap/php_encoding.h b/ext/soap/php_encoding.h index 67023a81d82..ef05c9ebe78 100644 --- a/ext/soap/php_encoding.h +++ b/ext/soap/php_encoding.h @@ -35,7 +35,7 @@ #define SOAP_1_2_ENC_NAMESPACE "http://www.w3.org/2003/05/soap-encoding" #define SOAP_1_2_ENC_NS_PREFIX "enc" -#define SCHEMA_NAMESPACE "http://www.w3.org/2001/XMLSchema" +#define XSD_DRAFT_2000_NAMESPACE "http://www.w3.org/2000/10/XMLSchema" #define XSD_NAMESPACE "http://www.w3.org/2001/XMLSchema" #define XSD_NS_PREFIX "xsd" #define XSI_NAMESPACE "http://www.w3.org/2001/XMLSchema-instance" diff --git a/ext/soap/php_schema.c b/ext/soap/php_schema.c index ac4fb60cb2c..f1af0110bab 100644 --- a/ext/soap/php_schema.c +++ b/ext/soap/php_schema.c @@ -43,6 +43,17 @@ static int schema_restriction_var_char(xmlNodePtr val, sdlRestrictionCharPtr *va static void schema_type_fixup(sdlCtx *ctx, sdlTypePtr type); +static bool node_is_equal_xsd(xmlNodePtr node, const char *name) +{ + static const char *ns[] = { + XSD_NAMESPACE, + XSD_DRAFT_2000_NAMESPACE, + NULL + }; + + return node_is_equal_ex_one_of(node, name, ns); +} + static encodePtr create_encoder(sdlPtr sdl, sdlTypePtr cur_type, const xmlChar *ns, const xmlChar *type) { smart_str nscat = {0}; @@ -226,7 +237,7 @@ int load_schema(sdlCtx *ctx, xmlNodePtr schema) trav = schema->children; while (trav != NULL) { - if (node_is_equal(trav,"include")) { + if (node_is_equal_xsd(trav,"include")) { xmlAttrPtr location; location = get_attribute(trav->properties, "schemaLocation"); @@ -238,7 +249,7 @@ int load_schema(sdlCtx *ctx, xmlNodePtr schema) xmlFree(uri); } - } else if (node_is_equal(trav,"redefine")) { + } else if (node_is_equal_xsd(trav,"redefine")) { xmlAttrPtr location; location = get_attribute(trav->properties, "schemaLocation"); @@ -251,7 +262,7 @@ int load_schema(sdlCtx *ctx, xmlNodePtr schema) /* TODO: support */ } - } else if (node_is_equal(trav,"import")) { + } else if (node_is_equal_xsd(trav,"import")) { xmlAttrPtr ns, location; xmlChar *uri = NULL; @@ -270,7 +281,7 @@ int load_schema(sdlCtx *ctx, xmlNodePtr schema) } schema_load_file(ctx, ns, uri, tns, 1); if (uri != NULL) {xmlFree(uri);} - } else if (node_is_equal(trav,"annotation")) { + } else if (node_is_equal_xsd(trav,"annotation")) { /* TODO: support */ /* annotation cleanup xmlNodePtr tmp = trav; @@ -286,21 +297,21 @@ int load_schema(sdlCtx *ctx, xmlNodePtr schema) } while (trav != NULL) { - if (node_is_equal(trav,"simpleType")) { + if (node_is_equal_xsd(trav,"simpleType")) { schema_simpleType(ctx->sdl, tns, trav, NULL); - } else if (node_is_equal(trav,"complexType")) { + } else if (node_is_equal_xsd(trav,"complexType")) { schema_complexType(ctx->sdl, tns, trav, NULL); - } else if (node_is_equal(trav,"group")) { + } else if (node_is_equal_xsd(trav,"group")) { schema_group(ctx->sdl, tns, trav, NULL, NULL); - } else if (node_is_equal(trav,"attributeGroup")) { + } else if (node_is_equal_xsd(trav,"attributeGroup")) { schema_attributeGroup(ctx->sdl, tns, trav, NULL, ctx); - } else if (node_is_equal(trav,"element")) { + } else if (node_is_equal_xsd(trav,"element")) { schema_element(ctx->sdl, tns, trav, NULL, NULL); - } else if (node_is_equal(trav,"attribute")) { + } else if (node_is_equal_xsd(trav,"attribute")) { schema_attribute(ctx->sdl, tns, trav, NULL, ctx); - } else if (node_is_equal(trav,"notation")) { + } else if (node_is_equal_xsd(trav,"notation")) { /* TODO: support */ - } else if (node_is_equal(trav,"annotation")) { + } else if (node_is_equal_xsd(trav,"annotation")) { /* TODO: support */ } else { soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in schema", trav->name); @@ -391,19 +402,19 @@ static int schema_simpleType(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr simpleType, } trav = simpleType->children; - if (trav != NULL && node_is_equal(trav,"annotation")) { + if (trav != NULL && node_is_equal_xsd(trav,"annotation")) { /* TODO: support */ trav = trav->next; } if (trav != NULL) { - if (node_is_equal(trav,"restriction")) { + if (node_is_equal_xsd(trav,"restriction")) { schema_restriction_simpleContent(sdl, tns, trav, cur_type, 1); trav = trav->next; - } else if (node_is_equal(trav,"list")) { + } else if (node_is_equal_xsd(trav,"list")) { cur_type->kind = XSD_TYPEKIND_LIST; schema_list(sdl, tns, trav, cur_type); trav = trav->next; - } else if (node_is_equal(trav,"union")) { + } else if (node_is_equal_xsd(trav,"union")) { cur_type->kind = XSD_TYPEKIND_UNION; schema_union(sdl, tns, trav, cur_type); trav = trav->next; @@ -462,11 +473,11 @@ static int schema_list(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr listType, sdlTypeP } trav = listType->children; - if (trav != NULL && node_is_equal(trav,"annotation")) { + if (trav != NULL && node_is_equal_xsd(trav,"annotation")) { /* TODO: support */ trav = trav->next; } - if (trav != NULL && node_is_equal(trav,"simpleType")) { + if (trav != NULL && node_is_equal_xsd(trav,"simpleType")) { sdlTypePtr newType; if (itemType != NULL) { @@ -562,12 +573,12 @@ static int schema_union(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr unionType, sdlTyp } trav = unionType->children; - if (trav != NULL && node_is_equal(trav,"annotation")) { + if (trav != NULL && node_is_equal_xsd(trav,"annotation")) { /* TODO: support */ trav = trav->next; } while (trav != NULL) { - if (node_is_equal(trav,"simpleType")) { + if (node_is_equal_xsd(trav,"simpleType")) { sdlTypePtr newType; newType = emalloc(sizeof(sdlType)); @@ -615,16 +626,16 @@ static int schema_simpleContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr simpCompT xmlNodePtr trav; trav = simpCompType->children; - if (trav != NULL && node_is_equal(trav,"annotation")) { + if (trav != NULL && node_is_equal_xsd(trav,"annotation")) { /* TODO: support */ trav = trav->next; } if (trav != NULL) { - if (node_is_equal(trav, "restriction")) { + if (node_is_equal_xsd(trav, "restriction")) { cur_type->kind = XSD_TYPEKIND_RESTRICTION; schema_restriction_simpleContent(sdl, tns, trav, cur_type, 0); trav = trav->next; - } else if (node_is_equal(trav, "extension")) { + } else if (node_is_equal_xsd(trav, "extension")) { cur_type->kind = XSD_TYPEKIND_EXTENSION; schema_extension_simpleContent(sdl, tns, trav, cur_type); trav = trav->next; @@ -682,38 +693,38 @@ static int schema_restriction_simpleContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodeP } trav = restType->children; - if (trav != NULL && node_is_equal(trav, "annotation")) { + if (trav != NULL && node_is_equal_xsd(trav, "annotation")) { /* TODO: support */ trav = trav->next; } - if (trav != NULL && node_is_equal(trav, "simpleType")) { + if (trav != NULL && node_is_equal_xsd(trav, "simpleType")) { schema_simpleType(sdl, tns, trav, cur_type); trav = trav->next; } while (trav != NULL) { - if (node_is_equal(trav, "minExclusive")) { + if (node_is_equal_xsd(trav, "minExclusive")) { schema_restriction_var_int(trav, &cur_type->restrictions->minExclusive); - } else if (node_is_equal(trav, "minInclusive")) { + } else if (node_is_equal_xsd(trav, "minInclusive")) { schema_restriction_var_int(trav, &cur_type->restrictions->minInclusive); - } else if (node_is_equal(trav, "maxExclusive")) { + } else if (node_is_equal_xsd(trav, "maxExclusive")) { schema_restriction_var_int(trav, &cur_type->restrictions->maxExclusive); - } else if (node_is_equal(trav, "maxInclusive")) { + } else if (node_is_equal_xsd(trav, "maxInclusive")) { schema_restriction_var_int(trav, &cur_type->restrictions->maxInclusive); - } else if (node_is_equal(trav, "totalDigits")) { + } else if (node_is_equal_xsd(trav, "totalDigits")) { schema_restriction_var_int(trav, &cur_type->restrictions->totalDigits); - } else if (node_is_equal(trav, "fractionDigits")) { + } else if (node_is_equal_xsd(trav, "fractionDigits")) { schema_restriction_var_int(trav, &cur_type->restrictions->fractionDigits); - } else if (node_is_equal(trav, "length")) { + } else if (node_is_equal_xsd(trav, "length")) { schema_restriction_var_int(trav, &cur_type->restrictions->length); - } else if (node_is_equal(trav, "minLength")) { + } else if (node_is_equal_xsd(trav, "minLength")) { schema_restriction_var_int(trav, &cur_type->restrictions->minLength); - } else if (node_is_equal(trav, "maxLength")) { + } else if (node_is_equal_xsd(trav, "maxLength")) { schema_restriction_var_int(trav, &cur_type->restrictions->maxLength); - } else if (node_is_equal(trav, "whiteSpace")) { + } else if (node_is_equal_xsd(trav, "whiteSpace")) { schema_restriction_var_char(trav, &cur_type->restrictions->whiteSpace); - } else if (node_is_equal(trav, "pattern")) { + } else if (node_is_equal_xsd(trav, "pattern")) { schema_restriction_var_char(trav, &cur_type->restrictions->pattern); - } else if (node_is_equal(trav, "enumeration")) { + } else if (node_is_equal_xsd(trav, "enumeration")) { sdlRestrictionCharPtr enumval = NULL; schema_restriction_var_char(trav, &enumval); @@ -731,11 +742,11 @@ static int schema_restriction_simpleContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodeP } if (!simpleType) { while (trav != NULL) { - if (node_is_equal(trav,"attribute")) { + if (node_is_equal_xsd(trav,"attribute")) { schema_attribute(sdl, tns, trav, cur_type, NULL); - } else if (node_is_equal(trav,"attributeGroup")) { + } else if (node_is_equal_xsd(trav,"attributeGroup")) { schema_attributeGroup(sdl, tns, trav, cur_type, NULL); - } else if (node_is_equal(trav,"anyAttribute")) { + } else if (node_is_equal_xsd(trav,"anyAttribute")) { /* TODO: support */ trav = trav->next; break; @@ -782,31 +793,31 @@ static int schema_restriction_complexContent(sdlPtr sdl, xmlAttrPtr tns, xmlNode } trav = restType->children; - if (trav != NULL && node_is_equal(trav,"annotation")) { + if (trav != NULL && node_is_equal_xsd(trav,"annotation")) { /* TODO: support */ trav = trav->next; } if (trav != NULL) { - if (node_is_equal(trav,"group")) { + if (node_is_equal_xsd(trav,"group")) { schema_group(sdl, tns, trav, cur_type, NULL); trav = trav->next; - } else if (node_is_equal(trav,"all")) { + } else if (node_is_equal_xsd(trav,"all")) { schema_all(sdl, tns, trav, cur_type, NULL); trav = trav->next; - } else if (node_is_equal(trav,"choice")) { + } else if (node_is_equal_xsd(trav,"choice")) { schema_choice(sdl, tns, trav, cur_type, NULL); trav = trav->next; - } else if (node_is_equal(trav,"sequence")) { + } else if (node_is_equal_xsd(trav,"sequence")) { schema_sequence(sdl, tns, trav, cur_type, NULL); trav = trav->next; } } while (trav != NULL) { - if (node_is_equal(trav,"attribute")) { + if (node_is_equal_xsd(trav,"attribute")) { schema_attribute(sdl, tns, trav, cur_type, NULL); - } else if (node_is_equal(trav,"attributeGroup")) { + } else if (node_is_equal_xsd(trav,"attributeGroup")) { schema_attributeGroup(sdl, tns, trav, cur_type, NULL); - } else if (node_is_equal(trav,"anyAttribute")) { + } else if (node_is_equal_xsd(trav,"anyAttribute")) { /* TODO: support */ trav = trav->next; break; @@ -907,16 +918,16 @@ static int schema_extension_simpleContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr } trav = extType->children; - if (trav != NULL && node_is_equal(trav,"annotation")) { + if (trav != NULL && node_is_equal_xsd(trav,"annotation")) { /* TODO: support */ trav = trav->next; } while (trav != NULL) { - if (node_is_equal(trav,"attribute")) { + if (node_is_equal_xsd(trav,"attribute")) { schema_attribute(sdl, tns, trav, cur_type, NULL); - } else if (node_is_equal(trav,"attributeGroup")) { + } else if (node_is_equal_xsd(trav,"attributeGroup")) { schema_attributeGroup(sdl, tns, trav, cur_type, NULL); - } else if (node_is_equal(trav,"anyAttribute")) { + } else if (node_is_equal_xsd(trav,"anyAttribute")) { /* TODO: support */ trav = trav->next; break; @@ -962,31 +973,31 @@ static int schema_extension_complexContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePt } trav = extType->children; - if (trav != NULL && node_is_equal(trav,"annotation")) { + if (trav != NULL && node_is_equal_xsd(trav,"annotation")) { /* TODO: support */ trav = trav->next; } if (trav != NULL) { - if (node_is_equal(trav,"group")) { + if (node_is_equal_xsd(trav,"group")) { schema_group(sdl, tns, trav, cur_type, NULL); trav = trav->next; - } else if (node_is_equal(trav,"all")) { + } else if (node_is_equal_xsd(trav,"all")) { schema_all(sdl, tns, trav, cur_type, NULL); trav = trav->next; - } else if (node_is_equal(trav,"choice")) { + } else if (node_is_equal_xsd(trav,"choice")) { schema_choice(sdl, tns, trav, cur_type, NULL); trav = trav->next; - } else if (node_is_equal(trav,"sequence")) { + } else if (node_is_equal_xsd(trav,"sequence")) { schema_sequence(sdl, tns, trav, cur_type, NULL); trav = trav->next; } } while (trav != NULL) { - if (node_is_equal(trav,"attribute")) { + if (node_is_equal_xsd(trav,"attribute")) { schema_attribute(sdl, tns, trav, cur_type, NULL); - } else if (node_is_equal(trav,"attributeGroup")) { + } else if (node_is_equal_xsd(trav,"attributeGroup")) { schema_attributeGroup(sdl, tns, trav, cur_type, NULL); - } else if (node_is_equal(trav,"anyAttribute")) { + } else if (node_is_equal_xsd(trav,"anyAttribute")) { /* TODO: support */ trav = trav->next; break; @@ -1050,12 +1061,12 @@ static int schema_all(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr all, sdlTypePtr cur schema_min_max(all, newModel); trav = all->children; - if (trav != NULL && node_is_equal(trav,"annotation")) { + if (trav != NULL && node_is_equal_xsd(trav,"annotation")) { /* TODO: support */ trav = trav->next; } while (trav != NULL) { - if (node_is_equal(trav,"element")) { + if (node_is_equal_xsd(trav,"element")) { schema_element(sdl, tns, trav, cur_type, newModel); } else { soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in all", trav->name); @@ -1164,26 +1175,26 @@ static int schema_group(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr groupType, sdlTyp schema_min_max(groupType, newModel); trav = groupType->children; - if (trav != NULL && node_is_equal(trav,"annotation")) { + if (trav != NULL && node_is_equal_xsd(trav,"annotation")) { /* TODO: support */ trav = trav->next; } if (trav != NULL) { - if (node_is_equal(trav,"choice")) { + if (node_is_equal_xsd(trav,"choice")) { if (ref != NULL) { soap_error0(E_ERROR, "Parsing Schema: group has both 'ref' attribute and subcontent"); } newModel->kind = XSD_CONTENT_CHOICE; schema_choice(sdl, tns, trav, cur_type, newModel); trav = trav->next; - } else if (node_is_equal(trav,"sequence")) { + } else if (node_is_equal_xsd(trav,"sequence")) { if (ref != NULL) { soap_error0(E_ERROR, "Parsing Schema: group has both 'ref' attribute and subcontent"); } newModel->kind = XSD_CONTENT_SEQUENCE; schema_sequence(sdl, tns, trav, cur_type, newModel); trav = trav->next; - } else if (node_is_equal(trav,"all")) { + } else if (node_is_equal_xsd(trav,"all")) { if (ref != NULL) { soap_error0(E_ERROR, "Parsing Schema: group has both 'ref' attribute and subcontent"); } @@ -1226,20 +1237,20 @@ static int schema_choice(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr choiceType, sdlT schema_min_max(choiceType, newModel); trav = choiceType->children; - if (trav != NULL && node_is_equal(trav,"annotation")) { + if (trav != NULL && node_is_equal_xsd(trav,"annotation")) { /* TODO: support */ trav = trav->next; } while (trav != NULL) { - if (node_is_equal(trav,"element")) { + if (node_is_equal_xsd(trav,"element")) { schema_element(sdl, tns, trav, cur_type, newModel); - } else if (node_is_equal(trav,"group")) { + } else if (node_is_equal_xsd(trav,"group")) { schema_group(sdl, tns, trav, cur_type, newModel); - } else if (node_is_equal(trav,"choice")) { + } else if (node_is_equal_xsd(trav,"choice")) { schema_choice(sdl, tns, trav, cur_type, newModel); - } else if (node_is_equal(trav,"sequence")) { + } else if (node_is_equal_xsd(trav,"sequence")) { schema_sequence(sdl, tns, trav, cur_type, newModel); - } else if (node_is_equal(trav,"any")) { + } else if (node_is_equal_xsd(trav,"any")) { schema_any(sdl, tns, trav, cur_type, newModel); } else { soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in choice", trav->name); @@ -1276,20 +1287,20 @@ static int schema_sequence(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr seqType, sdlTy schema_min_max(seqType, newModel); trav = seqType->children; - if (trav != NULL && node_is_equal(trav,"annotation")) { + if (trav != NULL && node_is_equal_xsd(trav,"annotation")) { /* TODO: support */ trav = trav->next; } while (trav != NULL) { - if (node_is_equal(trav,"element")) { + if (node_is_equal_xsd(trav,"element")) { schema_element(sdl, tns, trav, cur_type, newModel); - } else if (node_is_equal(trav,"group")) { + } else if (node_is_equal_xsd(trav,"group")) { schema_group(sdl, tns, trav, cur_type, newModel); - } else if (node_is_equal(trav,"choice")) { + } else if (node_is_equal_xsd(trav,"choice")) { schema_choice(sdl, tns, trav, cur_type, newModel); - } else if (node_is_equal(trav,"sequence")) { + } else if (node_is_equal_xsd(trav,"sequence")) { schema_sequence(sdl, tns, trav, cur_type, newModel); - } else if (node_is_equal(trav,"any")) { + } else if (node_is_equal_xsd(trav,"any")) { schema_any(sdl, tns, trav, cur_type, newModel); } else { soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in sequence", trav->name); @@ -1338,16 +1349,16 @@ static int schema_complexContent(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr compCont xmlNodePtr trav; trav = compCont->children; - if (trav != NULL && node_is_equal(trav,"annotation")) { + if (trav != NULL && node_is_equal_xsd(trav,"annotation")) { /* TODO: support */ trav = trav->next; } if (trav != NULL) { - if (node_is_equal(trav, "restriction")) { + if (node_is_equal_xsd(trav, "restriction")) { cur_type->kind = XSD_TYPEKIND_RESTRICTION; schema_restriction_complexContent(sdl, tns, trav, cur_type); trav = trav->next; - } else if (node_is_equal(trav, "extension")) { + } else if (node_is_equal_xsd(trav, "extension")) { cur_type->kind = XSD_TYPEKIND_EXTENSION; schema_extension_complexContent(sdl, tns, trav, cur_type); trav = trav->next; @@ -1442,37 +1453,37 @@ static int schema_complexType(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr compType, s } trav = compType->children; - if (trav != NULL && node_is_equal(trav, "annotation")) { + if (trav != NULL && node_is_equal_xsd(trav, "annotation")) { /* TODO: support */ trav = trav->next; } if (trav != NULL) { - if (node_is_equal(trav,"simpleContent")) { + if (node_is_equal_xsd(trav,"simpleContent")) { schema_simpleContent(sdl, tns, trav, cur_type); trav = trav->next; - } else if (node_is_equal(trav,"complexContent")) { + } else if (node_is_equal_xsd(trav,"complexContent")) { schema_complexContent(sdl, tns, trav, cur_type); trav = trav->next; } else { - if (node_is_equal(trav,"group")) { + if (node_is_equal_xsd(trav,"group")) { schema_group(sdl, tns, trav, cur_type, NULL); trav = trav->next; - } else if (node_is_equal(trav,"all")) { + } else if (node_is_equal_xsd(trav,"all")) { schema_all(sdl, tns, trav, cur_type, NULL); trav = trav->next; - } else if (node_is_equal(trav,"choice")) { + } else if (node_is_equal_xsd(trav,"choice")) { schema_choice(sdl, tns, trav, cur_type, NULL); trav = trav->next; - } else if (node_is_equal(trav,"sequence")) { + } else if (node_is_equal_xsd(trav,"sequence")) { schema_sequence(sdl, tns, trav, cur_type, NULL); trav = trav->next; } while (trav != NULL) { - if (node_is_equal(trav,"attribute")) { + if (node_is_equal_xsd(trav,"attribute")) { schema_attribute(sdl, tns, trav, cur_type, NULL); - } else if (node_is_equal(trav,"attributeGroup")) { + } else if (node_is_equal_xsd(trav,"attributeGroup")) { schema_attributeGroup(sdl, tns, trav, cur_type, NULL); - } else if (node_is_equal(trav,"anyAttribute")) { + } else if (node_is_equal_xsd(trav,"anyAttribute")) { /* TODO: support */ trav = trav->next; break; @@ -1659,7 +1670,7 @@ static int schema_element(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr element, sdlTyp if (cur_type->form == XSD_FORM_DEFAULT) { xmlNodePtr parent = element->parent; while (parent) { - if (node_is_equal_ex(parent, "schema", SCHEMA_NAMESPACE)) { + if (node_is_equal_xsd(parent, "schema")) { xmlAttrPtr def; def = get_attribute(parent->properties, "elementFormDefault"); if(def == NULL || strncmp((char*)def->children->content, "qualified", sizeof("qualified"))) { @@ -1695,12 +1706,12 @@ static int schema_element(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr element, sdlTyp } trav = element->children; - if (trav != NULL && node_is_equal(trav, "annotation")) { + if (trav != NULL && node_is_equal_xsd(trav, "annotation")) { /* TODO: support */ trav = trav->next; } if (trav != NULL) { - if (node_is_equal(trav,"simpleType")) { + if (node_is_equal_xsd(trav,"simpleType")) { if (ref != NULL) { soap_error0(E_ERROR, "Parsing Schema: element has both 'ref' attribute and subtype"); } else if (type != NULL) { @@ -1708,7 +1719,7 @@ static int schema_element(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr element, sdlTyp } schema_simpleType(sdl, tns, trav, cur_type); trav = trav->next; - } else if (node_is_equal(trav,"complexType")) { + } else if (node_is_equal_xsd(trav,"complexType")) { if (ref != NULL) { soap_error0(E_ERROR, "Parsing Schema: element has both 'ref' attribute and subtype"); } else if (type != NULL) { @@ -1719,11 +1730,11 @@ static int schema_element(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr element, sdlTyp } } while (trav != NULL) { - if (node_is_equal(trav,"unique")) { + if (node_is_equal_xsd(trav,"unique")) { /* TODO: support */ - } else if (node_is_equal(trav,"key")) { + } else if (node_is_equal_xsd(trav,"key")) { /* TODO: support */ - } else if (node_is_equal(trav,"keyref")) { + } else if (node_is_equal_xsd(trav,"keyref")) { /* TODO: support */ } else { soap_error1(E_ERROR, "Parsing Schema: unexpected <%s> in element", trav->name); @@ -1844,11 +1855,11 @@ static int schema_attribute(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr attrType, sdl attr = attrType->properties; while (attr != NULL) { - if (attr_is_equal_ex(attr, "default", SCHEMA_NAMESPACE)) { + if (attr_is_equal(attr, "default")) { newAttr->def = estrdup((char*)attr->children->content); - } else if (attr_is_equal_ex(attr, "fixed", SCHEMA_NAMESPACE)) { + } else if (attr_is_equal(attr, "fixed")) { newAttr->fixed = estrdup((char*)attr->children->content); - } else if (attr_is_equal_ex(attr, "form", SCHEMA_NAMESPACE)) { + } else if (attr_is_equal(attr, "form")) { if (strncmp((char*)attr->children->content, "qualified", sizeof("qualified")) == 0) { newAttr->form = XSD_FORM_QUALIFIED; } else if (strncmp((char*)attr->children->content, "unqualified", sizeof("unqualified")) == 0) { @@ -1856,15 +1867,15 @@ static int schema_attribute(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr attrType, sdl } else { newAttr->form = XSD_FORM_DEFAULT; } - } else if (attr_is_equal_ex(attr, "id", SCHEMA_NAMESPACE)) { + } else if (attr_is_equal(attr, "id")) { /* skip */ - } else if (attr_is_equal_ex(attr, "name", SCHEMA_NAMESPACE)) { + } else if (attr_is_equal(attr, "name")) { newAttr->name = estrdup((char*)attr->children->content); - } else if (attr_is_equal_ex(attr, "ref", SCHEMA_NAMESPACE)) { + } else if (attr_is_equal(attr, "ref")) { /* already processed */ - } else if (attr_is_equal_ex(attr, "type", SCHEMA_NAMESPACE)) { + } else if (attr_is_equal(attr, "type")) { /* already processed */ - } else if (attr_is_equal_ex(attr, "use", SCHEMA_NAMESPACE)) { + } else if (attr_is_equal(attr, "use")) { if (strncmp((char*)attr->children->content, "prohibited", sizeof("prohibited")) == 0) { newAttr->use = XSD_USE_PROHIBITED; } else if (strncmp((char*)attr->children->content, "required", sizeof("required")) == 0) { @@ -1875,9 +1886,9 @@ static int schema_attribute(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr attrType, sdl newAttr->use = XSD_USE_DEFAULT; } } else { - xmlNsPtr nsPtr = attr_find_ns(attr); + xmlNsPtr nsPtr = attr->ns; - if (strncmp((char*)nsPtr->href, SCHEMA_NAMESPACE, sizeof(SCHEMA_NAMESPACE))) { + if (nsPtr && strncmp((const char*) nsPtr->href, XSD_NAMESPACE, sizeof(XSD_NAMESPACE)) != 0) { smart_str key2 = {0}; sdlExtraAttributePtr ext; xmlNsPtr nsptr; @@ -1914,7 +1925,7 @@ static int schema_attribute(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr attrType, sdl if (newAttr->form == XSD_FORM_DEFAULT) { xmlNodePtr parent = attrType->parent; while (parent) { - if (node_is_equal_ex(parent, "schema", SCHEMA_NAMESPACE)) { + if (node_is_equal_xsd(parent, "schema")) { xmlAttrPtr def; def = get_attribute(parent->properties, "attributeFormDefault"); if(def == NULL || strncmp((char*)def->children->content, "qualified", sizeof("qualified"))) { @@ -1931,12 +1942,12 @@ static int schema_attribute(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr attrType, sdl } } trav = attrType->children; - if (trav != NULL && node_is_equal(trav, "annotation")) { + if (trav != NULL && node_is_equal_xsd(trav, "annotation")) { /* TODO: support */ trav = trav->next; } if (trav != NULL) { - if (node_is_equal(trav,"simpleType")) { + if (node_is_equal_xsd(trav,"simpleType")) { sdlTypePtr dummy_type; zval zv; @@ -2039,22 +2050,22 @@ static int schema_attributeGroup(sdlPtr sdl, xmlAttrPtr tns, xmlNodePtr attrGrou } trav = attrGroup->children; - if (trav != NULL && node_is_equal(trav, "annotation")) { + if (trav != NULL && node_is_equal_xsd(trav, "annotation")) { /* TODO: support */ trav = trav->next; } while (trav != NULL) { - if (node_is_equal(trav,"attribute")) { + if (node_is_equal_xsd(trav,"attribute")) { if (ref != NULL) { soap_error0(E_ERROR, "Parsing Schema: attributeGroup has both 'ref' attribute and subattribute"); } schema_attribute(sdl, tns, trav, cur_type, NULL); - } else if (node_is_equal(trav,"attributeGroup")) { + } else if (node_is_equal_xsd(trav,"attributeGroup")) { if (ref != NULL) { soap_error0(E_ERROR, "Parsing Schema: attributeGroup has both 'ref' attribute and subattribute"); } schema_attributeGroup(sdl, tns, trav, cur_type, NULL); - } else if (node_is_equal(trav,"anyAttribute")) { + } else if (node_is_equal_xsd(trav,"anyAttribute")) { if (ref != NULL) { soap_error0(E_ERROR, "Parsing Schema: attributeGroup has both 'ref' attribute and subattribute"); } @@ -2269,7 +2280,7 @@ static void schema_type_fixup(sdlCtx *ctx, sdlTypePtr type) type->def = estrdup(tmp->def); } type->form = tmp->form; - } else if (strcmp(type->ref, SCHEMA_NAMESPACE ":schema") == 0) { + } else if (strcmp(type->ref, XSD_NAMESPACE ":schema") == 0) { type->encode = get_conversion(XSD_ANYXML); } else { soap_error1(E_ERROR, "Parsing Schema: unresolved element 'ref' attribute '%s'", type->ref); diff --git a/ext/soap/php_xml.c b/ext/soap/php_xml.c index f3b8e18f7dd..185525c048c 100644 --- a/ext/soap/php_xml.c +++ b/ext/soap/php_xml.c @@ -167,18 +167,6 @@ xmlDocPtr soap_xmlParseMemory(const void *buf, size_t buf_size) return ret; } -/* FIXME: this is wrong, attributes don't inherit the namespace of the node they're in! */ -xmlNsPtr attr_find_ns(xmlAttrPtr node) -{ - if (node->ns) { - return node->ns; - } else if (node->parent->ns) { - return node->parent->ns; - } else { - return xmlSearchNs(node->doc, node->parent, NULL); - } -} - xmlNsPtr node_find_ns(xmlNodePtr node) { if (node->ns) { @@ -190,14 +178,16 @@ xmlNsPtr node_find_ns(xmlNodePtr node) int attr_is_equal_ex(xmlAttrPtr node, const char *name, const char *ns) { - if (name == NULL || ((node->name) && strcmp((char*)node->name, name) == 0)) { + if (node->name && strcmp((const char *) node->name, name) == 0) { + xmlNsPtr nsPtr = node->ns; if (ns) { - xmlNsPtr nsPtr = attr_find_ns(node); if (nsPtr) { - return (strcmp((char*)nsPtr->href, ns) == 0); + return (strcmp((const char *) nsPtr->href, ns) == 0); } else { return FALSE; } + } else if (nsPtr) { + return FALSE; } return TRUE; } @@ -210,7 +200,7 @@ int node_is_equal_ex(xmlNodePtr node, const char *name, const char *ns) if (ns) { xmlNsPtr nsPtr = node_find_ns(node); if (nsPtr) { - return (strcmp((char*)nsPtr->href, ns) == 0); + return strcmp((const char *) nsPtr->href, ns) == 0; } else { return FALSE; } @@ -220,10 +210,41 @@ int node_is_equal_ex(xmlNodePtr node, const char *name, const char *ns) return FALSE; } +int node_is_equal_ex_one_of(xmlNodePtr node, const char *name, const char *const *namespaces) +{ + if ((node->name) && strcmp((char*)node->name, name) == 0) { + xmlNsPtr nsPtr = node_find_ns(node); + if (nsPtr) { + do { + if (strcmp((const char *) nsPtr->href, *namespaces) == 0) { + return TRUE; + } + namespaces++; + } while (*namespaces != NULL); + } + return FALSE; + } + return FALSE; +} -xmlAttrPtr get_attribute_ex(xmlAttrPtr node, const char *name, const char *ns) +xmlAttrPtr get_attribute_any_ns(xmlAttrPtr node, const char *name) { while (node!=NULL) { + if (node->name && strcmp((const char *) node->name, name) == 0) { + return node; + } + node = node->next; + } + return NULL; +} + +/* Finds an attribute by name and namespace. + * If ns is NULL, the attribute must not be in any namespace. + * If ns is not NULL, the attribute must be in the specified namespace. + */ +xmlAttrPtr get_attribute_ex(xmlAttrPtr node, const char *name, const char *ns) +{ + while (node != NULL) { if (attr_is_equal_ex(node, name, ns)) { return node; } diff --git a/ext/soap/php_xml.h b/ext/soap/php_xml.h index d46767e68ed..c967ac09d73 100644 --- a/ext/soap/php_xml.h +++ b/ext/soap/php_xml.h @@ -30,11 +30,12 @@ xmlDocPtr soap_xmlParseFile(const char *filename); xmlDocPtr soap_xmlParseMemory(const void *buf, size_t size); -xmlNsPtr attr_find_ns(xmlAttrPtr node); xmlNsPtr node_find_ns(xmlNodePtr node); int attr_is_equal_ex(xmlAttrPtr node, const char *name, const char *ns); int node_is_equal_ex(xmlNodePtr node, const char *name, const char *ns); -xmlAttrPtr get_attribute_ex(xmlAttrPtr node,const char *name, const char *ns); +int node_is_equal_ex_one_of(xmlNodePtr node, const char *name, const char *const *namespaces); +xmlAttrPtr get_attribute_any_ns(xmlAttrPtr node, const char *name); +xmlAttrPtr get_attribute_ex(xmlAttrPtr node, const char *name, const char *ns); xmlNodePtr get_node_ex(xmlNodePtr node, const char *name, const char *ns); xmlNodePtr get_node_recursive_ex(xmlNodePtr node, const char *name, const char *ns); xmlNodePtr get_node_with_attribute_ex(xmlNodePtr node, const char *name, const char *name_ns, const char *attribute, const char *value, const char *attr_ns); diff --git a/ext/soap/tests/bugs/bug27722.wsdl b/ext/soap/tests/bugs/bug27722.wsdl index 05cb4a6e8b7..880cf14aaf3 100644 --- a/ext/soap/tests/bugs/bug27722.wsdl +++ b/ext/soap/tests/bugs/bug27722.wsdl @@ -69,11 +69,11 @@ - - - - - + + + + + diff --git a/ext/soap/tests/bugs/bug27742.wsdl b/ext/soap/tests/bugs/bug27742.wsdl index 5843534a003..670ff6cd1f3 100644 --- a/ext/soap/tests/bugs/bug27742.wsdl +++ b/ext/soap/tests/bugs/bug27742.wsdl @@ -1,8 +1,8 @@ - + - + ISO 8601 pattern used to denote program durations. Year, month and day are not relevant in our context and are omitted. diff --git a/ext/soap/tests/bugs/bug29839.wsdl b/ext/soap/tests/bugs/bug29839.wsdl index 2bea2da9137..352b3d6826c 100644 --- a/ext/soap/tests/bugs/bug29839.wsdl +++ b/ext/soap/tests/bugs/bug29839.wsdl @@ -1,14 +1,14 @@ - + - + - + - + diff --git a/ext/soap/tests/bugs/bug34453.wsdl b/ext/soap/tests/bugs/bug34453.wsdl index 6b5ca48fe8c..e1ea4ade0b6 100644 --- a/ext/soap/tests/bugs/bug34453.wsdl +++ b/ext/soap/tests/bugs/bug34453.wsdl @@ -1,10 +1,10 @@ - + - + diff --git a/ext/soap/tests/bugs/bug62900.phpt b/ext/soap/tests/bugs/bug62900.phpt index c78afda5304..64e71aa5aaf 100644 --- a/ext/soap/tests/bugs/bug62900.phpt +++ b/ext/soap/tests/bugs/bug62900.phpt @@ -11,7 +11,7 @@ $wsdl_with_ns = << - + @@ -21,7 +21,7 @@ $wsdl_without_ns = << - + diff --git a/ext/soap/tests/bugs/bug68576.phpt b/ext/soap/tests/bugs/bug68576.phpt new file mode 100644 index 00000000000..ab89cd980c6 --- /dev/null +++ b/ext/soap/tests/bugs/bug68576.phpt @@ -0,0 +1,17 @@ +--TEST-- +Bug #68576 (Namespaces in schema php_schema.c) +--EXTENSIONS-- +soap +--FILE-- + WSDL_CACHE_NONE]); +} catch (SoapFault $e) { + // Should throw a SoapFault for the binding to the service, not for a schema error + echo get_class($e)."\n"; + echo $e->faultstring."\n"; +} +?> +--EXPECT-- +SoapFault +SOAP-ERROR: Parsing WSDL: Couldn't bind to service diff --git a/ext/soap/tests/bugs/bug68576.wsdl b/ext/soap/tests/bugs/bug68576.wsdl new file mode 100644 index 00000000000..7c1396c96c4 --- /dev/null +++ b/ext/soap/tests/bugs/bug68576.wsdl @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + +