summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/soap/TODO6
-rw-r--r--ext/soap/php_encoding.c42
-rw-r--r--ext/soap/php_encoding.h1
-rw-r--r--ext/soap/php_schema.c412
-rw-r--r--ext/soap/php_schema.h1
-rw-r--r--ext/soap/php_sdl.c89
-rw-r--r--ext/soap/php_sdl.h13
-rw-r--r--ext/soap/soap.c10
8 files changed, 470 insertions, 104 deletions
diff --git a/ext/soap/TODO b/ext/soap/TODO
index b8a27cfd37..9eb2d0d46a 100644
--- a/ext/soap/TODO
+++ b/ext/soap/TODO
@@ -100,7 +100,7 @@ Schema
------
- <include>, <import>, <redefine>
- support for user defined simple types
- - restiction
+ ? restiction
+ base
+ enumeration
+ length (for string, anyURI, hexBinary, base64Binary and derived)
@@ -114,8 +114,8 @@ Schema
- maxInclusive (for numeric, date types)
- totalDigits (for decimal)
- fractionDigits (for decimal)
- - list ???
- - union ???
+ ? list
+ ? union
- support for user defined complex types
- simpleContent extension
+ base
diff --git a/ext/soap/php_encoding.c b/ext/soap/php_encoding.c
index 38d6114335..b4acf1001a 100644
--- a/ext/soap/php_encoding.c
+++ b/ext/soap/php_encoding.c
@@ -45,7 +45,6 @@ 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(xmlNodePtr node, encodeType type);
static void set_ns_and_type_ex(xmlNodePtr node, char *ns, char *type);
encode defaultEncoding[] = {
@@ -179,6 +178,9 @@ xmlNodePtr master_to_xml(encodePtr encode, zval *data, int style)
{
xmlNodePtr node = NULL;
+ if (encode == NULL) {
+ encode = get_conversion(UNKNOWN_TYPE);
+ }
if (encode->to_xml_before) {
data = encode->to_xml_before(encode->details, data);
}
@@ -1598,7 +1600,7 @@ static xmlNodePtr to_xml_gmonth(encodeType type, zval *data, int style)
return to_xml_datetime_ex(type, data, "--%m--", style);
}
-static void set_ns_and_type(xmlNodePtr node, encodeType type)
+void set_ns_and_type(xmlNodePtr node, encodeType type)
{
set_ns_and_type_ex(node, type.ns, type.type_str);
}
@@ -1794,21 +1796,35 @@ static void get_type_str(xmlNodePtr node, const char* ns, const char* type, smar
smart_str_appendl(ret, prefix, strlen(prefix));
smart_str_appendc(ret, ':');
} else if (node != NULL) {
- smart_str* prefix = encode_new_ns();
- smart_str xmlns = {0};
+ xmlAttrPtr attr = node->properties;
- smart_str_appendl(&xmlns, "xmlns:", 6);
- smart_str_append(&xmlns, prefix);
- smart_str_0(&xmlns);
+ while (attr != NULL) {
+ if (strncmp(attr->name,"xmlns:",sizeof("xmlns:")-1) == 0 &&
+ strcmp(attr->children->content,ns) == 0) {
+ break;
+ }
+ attr = attr->next;
+ }
+ if (attr == NULL) {
+ smart_str* prefix = encode_new_ns();
+ smart_str xmlns = {0};
- xmlSetProp(node, xmlns.c, ns);
+ smart_str_appendl(&xmlns, "xmlns:", 6);
+ smart_str_append(&xmlns, prefix);
+ smart_str_0(&xmlns);
- smart_str_append(ret, prefix);
- smart_str_appendc(ret, ':');
+ xmlSetProp(node, xmlns.c, ns);
- smart_str_free(&xmlns);
- smart_str_free(prefix);
- efree(prefix);
+ smart_str_append(ret, prefix);
+ smart_str_appendc(ret, ':');
+
+ smart_str_free(&xmlns);
+ smart_str_free(prefix);
+ efree(prefix);
+ } else {
+ smart_str_appends(ret, attr->name + sizeof("xmlns:")-1);
+ smart_str_appendc(ret, ':');
+ }
} else {
php_error(E_ERROR,"Unknown namespace '%s'",ns);
}
diff --git a/ext/soap/php_encoding.h b/ext/soap/php_encoding.h
index 85b9989893..7b30f0a1fb 100644
--- a/ext/soap/php_encoding.h
+++ b/ext/soap/php_encoding.h
@@ -198,6 +198,7 @@ xmlNodePtr guess_xml_convert(encodeType type, zval *data, int style);
void encode_reset_ns();
smart_str *encode_new_ns();
+void set_ns_and_type(xmlNodePtr node, encodeType type);
encodePtr get_conversion_ex(HashTable *encoding, int encode);
encodePtr get_conversion_from_type_ex(HashTable *encoding, xmlNodePtr node, const char *type);
diff --git a/ext/soap/php_schema.c b/ext/soap/php_schema.c
index bd42c64643..3ff2502b33 100644
--- a/ext/soap/php_schema.c
+++ b/ext/soap/php_schema.c
@@ -6,7 +6,7 @@ static int schema_sequence(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr seqType, sdlTy
static int schema_list(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr listType, sdlTypePtr cur_type);
static int schema_union(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr unionType, sdlTypePtr cur_type);
static int schema_simpleContent(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr simpCompType, sdlTypePtr cur_type);
-static int schema_restriction_simpleContent(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr restType, sdlTypePtr cur_type);
+static int schema_restriction_simpleContent(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr restType, sdlTypePtr cur_type, int simpleType);
static int schema_restriction_complexContent(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr restType, sdlTypePtr cur_type);
static int schema_extension_simpleContent(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr extType, sdlTypePtr cur_type);
static int schema_extension_complexContent(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr extType, sdlTypePtr cur_type);
@@ -123,11 +123,44 @@ static int schema_simpleType(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr simpleType,
}
name = get_attribute(simpleType->properties, "name");
- if (name != NULL) {
+ if (cur_type != NULL) {
+ /* Anonymous type inside <element> or <restriction> */
+ sdlTypePtr newType, *ptr;
+
+ newType = malloc(sizeof(sdlType));
+ memset(newType, 0, sizeof(sdlType));
+ newType->kind = XSD_TYPEKIND_SIMPLE;
+ if (name != NULL) {
+ newType->name = strdup(name->children->content);
+ newType->namens = strdup(ns->children->content);
+ } else {
+ newType->name = strdup(cur_type->name);
+ newType->namens = strdup(cur_type->namens);
+ }
+
+ zend_hash_next_index_insert(sdl->types, &newType, sizeof(sdlTypePtr), (void **)&ptr);
+
+ if (sdl->encoders == NULL) {
+ sdl->encoders = malloc(sizeof(HashTable));
+ zend_hash_init(sdl->encoders, 0, NULL, delete_encoder, 1);
+ }
+ cur_type->encode = malloc(sizeof(encode));
+ memset(cur_type->encode, 0, sizeof(encode));
+ cur_type->encode->details.ns = strdup(newType->namens);
+ cur_type->encode->details.type_str = strdup(newType->name);
+ cur_type->encode->details.sdl_type = *ptr;
+ cur_type->encode->to_xml = sdl_guess_convert_xml;
+ cur_type->encode->to_zval = sdl_guess_convert_zval;
+ zend_hash_next_index_insert(sdl->encoders, &cur_type->encode, sizeof(encodePtr), NULL);
+
+ cur_type =*ptr;
+
+ } else if (name != NULL) {
sdlTypePtr newType, *ptr;
newType = malloc(sizeof(sdlType));
memset(newType, 0, sizeof(sdlType));
+ newType->kind = XSD_TYPEKIND_SIMPLE;
newType->name = strdup(name->children->content);
newType->namens = strdup(ns->children->content);
@@ -143,17 +176,6 @@ static int schema_simpleType(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr simpleType,
cur_type = (*ptr);
create_encoder(sdl, cur_type, ns->children->content, name->children->content);
- } else if (cur_type != NULL) {
- sdlTypePtr newType, *ptr;
-
- newType = malloc(sizeof(sdlType));
- memset(newType, 0, sizeof(sdlType));
- newType->name = strdup(cur_type->name);
- newType->namens = strdup(cur_type->namens);
-
- zend_hash_next_index_insert(sdl->types, &newType, sizeof(sdlTypePtr), (void **)&ptr);
- cur_type->encode = create_encoder(sdl, *ptr, (char *)(*ptr)->namens, (char *)(*ptr)->name);
- cur_type =*ptr;
} else {
php_error(E_ERROR, "Error parsing schema (simpleType has no 'name' attribute)");
}
@@ -171,17 +193,21 @@ static int schema_simpleType(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr simpleType,
}
if (trav != NULL) {
if (node_is_equal(trav,"restriction")) {
- schema_restriction_simpleContent(sdl, tsn, trav, cur_type);
+ schema_restriction_simpleContent(sdl, tsn, trav, cur_type, 1);
trav = trav->next;
} else if (node_is_equal(trav,"list")) {
+ cur_type->kind = XSD_TYPEKIND_LIST;
schema_list(sdl, tsn, trav, cur_type);
trav = trav->next;
} else if (node_is_equal(trav,"union")) {
+ cur_type->kind = XSD_TYPEKIND_UNION;
schema_union(sdl, tsn, trav, cur_type);
trav = trav->next;
} else {
php_error(E_ERROR, "Error parsing schema (unexpected <%s> in simpleType)",trav->name);
}
+ } else {
+ php_error(E_ERROR, "Error parsing schema (expected <restriction>, <list> or <union> in simpleType)");
}
while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
trav = trav->next;
@@ -208,7 +234,30 @@ static int schema_list(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr listType, sdlTypeP
itemType = get_attribute(listType->properties, "itemType");
if (itemType != NULL) {
- /*FIXME*/
+ char *type, *ns;
+ xmlNsPtr nsptr;
+
+ parse_namespace(itemType->children->content, &type, &ns);
+ nsptr = xmlSearchNs(listType->doc, listType, ns);
+ if (nsptr != NULL) {
+ sdlTypePtr newType, *tmp;
+
+ newType = malloc(sizeof(sdlType));
+ memset(newType, 0, sizeof(sdlType));
+
+ newType->name = strdup(type);
+ newType->namens = strdup(nsptr->href);
+
+ newType->encode = get_create_encoder(sdl, newType, (char *)nsptr->href, type);
+
+ if (cur_type->elements == NULL) {
+ cur_type->elements = malloc(sizeof(HashTable));
+ zend_hash_init(cur_type->elements, 0, NULL, delete_type, 1);
+ }
+ zend_hash_next_index_insert(cur_type->elements, &newType, sizeof(sdlTypePtr), (void **)&tmp);
+ }
+ if (type) {efree(type);}
+ if (ns) {efree(ns);}
}
trav = listType->children;
@@ -223,7 +272,25 @@ static int schema_list(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr listType, sdlTypeP
trav = trav->next;
}
if (trav != NULL && node_is_equal(trav,"simpleType")) {
- /*FIXME*/
+ sdlTypePtr newType, *tmp;
+
+ if (itemType != NULL) {
+ php_error(E_ERROR, "Error parsing schema (element have both 'itemType' attribute and subtype)");
+ }
+
+ newType = malloc(sizeof(sdlType));
+ memset(newType, 0, sizeof(sdlType));
+
+ newType->name = strdup("anonymous");
+ newType->namens = strdup(tsn->children->content);
+
+ if (cur_type->elements == NULL) {
+ cur_type->elements = malloc(sizeof(HashTable));
+ zend_hash_init(cur_type->elements, 0, NULL, delete_type, 1);
+ }
+ zend_hash_next_index_insert(cur_type->elements, &newType, sizeof(sdlTypePtr), (void **)&tmp);
+
+ schema_simpleType(sdl, tsn, trav, newType);
trav = trav->next;
}
while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
@@ -246,11 +313,51 @@ static int schema_list(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr listType, sdlTypeP
static int schema_union(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr unionType, sdlTypePtr cur_type)
{
xmlNodePtr trav;
- xmlAttrPtr itemType;
+ xmlAttrPtr memberTypes;
- itemType = get_attribute(unionType->properties, "memberTypes");
- if (itemType != NULL) {
- /*FIXME*/
+ memberTypes = get_attribute(unionType->properties, "memberTypes");
+ if (memberTypes != NULL) {
+ char *str, *start, *end, *next;
+ char *type, *ns;
+ xmlNsPtr nsptr;
+
+ str = estrdup(memberTypes->children->content);
+ whiteSpace_collapse(str);
+ start = str;
+ while (start != NULL && *start != '\0') {
+ end = strchr(start,' ');
+ if (end == NULL) {
+ next = NULL;
+ } else {
+ *end = '\0';
+ next = end+1;
+ }
+
+ parse_namespace(start, &type, &ns);
+ nsptr = xmlSearchNs(unionType->doc, unionType, ns);
+ if (nsptr != NULL) {
+ sdlTypePtr newType, *tmp;
+
+ newType = malloc(sizeof(sdlType));
+ memset(newType, 0, sizeof(sdlType));
+
+ newType->name = strdup(type);
+ newType->namens = strdup(nsptr->href);
+
+ newType->encode = get_create_encoder(sdl, newType, (char *)nsptr->href, type);
+
+ if (cur_type->elements == NULL) {
+ cur_type->elements = malloc(sizeof(HashTable));
+ zend_hash_init(cur_type->elements, 0, NULL, delete_type, 1);
+ }
+ zend_hash_next_index_insert(cur_type->elements, &newType, sizeof(sdlTypePtr), (void **)&tmp);
+ }
+ if (type) {efree(type);}
+ if (ns) {efree(ns);}
+
+ start = next;
+ }
+ efree(str);
}
trav = unionType->children;
@@ -264,7 +371,26 @@ static int schema_union(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr unionType, sdlTyp
while (trav != NULL) {
if (trav->type == XML_ELEMENT_NODE) {
if (node_is_equal(trav,"simpleType")) {
- /*FIXME*/
+ sdlTypePtr newType, *tmp;
+
+ if (memberTypes != NULL) {
+ php_error(E_ERROR, "Error parsing schema (union have both 'memberTypes' attribute and subtypes)");
+ }
+
+ newType = malloc(sizeof(sdlType));
+ memset(newType, 0, sizeof(sdlType));
+
+ newType->name = strdup("anonymous");
+ newType->namens = strdup(tsn->children->content);
+
+ if (cur_type->elements == NULL) {
+ cur_type->elements = malloc(sizeof(HashTable));
+ zend_hash_init(cur_type->elements, 0, NULL, delete_type, 1);
+ }
+ zend_hash_next_index_insert(cur_type->elements, &newType, sizeof(sdlTypePtr), (void **)&tmp);
+
+ schema_simpleType(sdl, tsn, trav, newType);
+
} else {
php_error(E_ERROR, "Error parsing schema (unexpected <%s> in union)",trav->name);
}
@@ -304,7 +430,7 @@ static int schema_simpleContent(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr simpCompT
}
if (trav != NULL) {
if (node_is_equal(trav, "restriction")) {
- schema_restriction_simpleContent(sdl, tsn, trav, cur_type);
+ schema_restriction_simpleContent(sdl, tsn, trav, cur_type, 0);
trav = trav->next;
} else if (node_is_equal(trav, "extension")) {
schema_extension_simpleContent(sdl, tsn, trav, cur_type);
@@ -326,14 +452,20 @@ static int schema_simpleContent(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr simpCompT
}
/*
-<restriction
+simpleType:<restriction
+ base = QName
+ id = ID
+ {any attributes with non-schema namespace . . .}>
+ Content: (annotation?, (simpleType?, (minExclusive | minInclusive | maxExclusive | maxInclusive | totalDigits | fractionDigits | length | minLength | maxLength | enumeration | whiteSpace | pattern)*)?)
+</restriction>
+simpleContent:<restriction
base = QName
id = ID
{any attributes with non-schema namespace . . .}>
Content: (annotation?, (simpleType?, (minExclusive | minInclusive | maxExclusive | maxInclusive | totalDigits | fractionDigits | length | minLength | maxLength | enumeration | whiteSpace | pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))
</restriction>
*/
-static int schema_restriction_simpleContent(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr restType, sdlTypePtr cur_type)
+static int schema_restriction_simpleContent(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr restType, sdlTypePtr cur_type, int simpleType)
{
xmlNodePtr trav;
xmlAttrPtr base;
@@ -350,6 +482,8 @@ static int schema_restriction_simpleContent(sdlPtr sdl, xmlAttrPtr tsn, xmlNodeP
}
if (type) {efree(type);}
if (ns) {efree(ns);}
+ } else if (!simpleType) {
+ php_error(E_ERROR, "Error parsing schema (restriction has no 'base' attribute)");
}
if (cur_type->restrictions == NULL) {
@@ -411,21 +545,23 @@ static int schema_restriction_simpleContent(sdlPtr sdl, xmlAttrPtr tsn, xmlNodeP
}
trav = trav->next;
}
- while (trav != NULL) {
- if (trav->type == XML_ELEMENT_NODE) {
- if (node_is_equal(trav,"attribute")) {
- schema_attribute(sdl, tsn, trav, cur_type);
- } else if (node_is_equal(trav,"attributeGroup")) {
- schema_attributeGroupRef(sdl, tsn, trav, cur_type);
- } else if (node_is_equal(trav,"anyAttribute")) {
- /* TODO: <anyAttribute> support */
- trav = trav->next;
- break;
- } else {
- php_error(E_ERROR, "Error parsing schema (unexpected <%s> in restriction)",trav->name);
+ if (!simpleType) {
+ while (trav != NULL) {
+ if (trav->type == XML_ELEMENT_NODE) {
+ if (node_is_equal(trav,"attribute")) {
+ schema_attribute(sdl, tsn, trav, cur_type);
+ } else if (node_is_equal(trav,"attributeGroup")) {
+ schema_attributeGroupRef(sdl, tsn, trav, cur_type);
+ } else if (node_is_equal(trav,"anyAttribute")) {
+ /* TODO: <anyAttribute> support */
+ trav = trav->next;
+ break;
+ } else {
+ php_error(E_ERROR, "Error parsing schema (unexpected <%s> in restriction)",trav->name);
+ }
}
+ trav = trav->next;
}
- trav = trav->next;
}
while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
trav = trav->next;
@@ -482,11 +618,14 @@ static int schema_restriction_complexContent(sdlPtr sdl, xmlAttrPtr tsn, xmlNode
schema_group(sdl, tsn, trav, cur_type);
trav = trav->next;
} else if (node_is_equal(trav,"all")) {
+ cur_type->kind = XSD_TYPEKIND_ALL;
schema_all(sdl, tsn, trav, cur_type);
trav = trav->next;
} else if (node_is_equal(trav,"choice")) {
+ cur_type->kind = XSD_TYPEKIND_CHOICE;
schema_choice(sdl, tsn, trav, cur_type);
trav = trav->next;
+ cur_type->kind = XSD_TYPEKIND_SEQUENCE;
} else if (node_is_equal(trav,"sequence")) {
schema_sequence(sdl, tsn, trav, cur_type);
trav = trav->next;
@@ -673,12 +812,15 @@ static int schema_extension_complexContent(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePt
schema_group(sdl, tsn, trav, cur_type);
trav = trav->next;
} else if (node_is_equal(trav,"all")) {
+ cur_type->kind = XSD_TYPEKIND_ALL;
schema_all(sdl, tsn, trav, cur_type);
trav = trav->next;
} else if (node_is_equal(trav,"choice")) {
+ cur_type->kind = XSD_TYPEKIND_CHOICE;
schema_choice(sdl, tsn, trav, cur_type);
trav = trav->next;
} else if (node_is_equal(trav,"sequence")) {
+ cur_type->kind = XSD_TYPEKIND_SEQUENCE;
schema_sequence(sdl, tsn, trav, cur_type);
trav = trav->next;
}
@@ -772,20 +914,29 @@ static int schema_group(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr groupType, sdlTyp
while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
trav = trav->next;
}
- while (trav != NULL) {
- if (trav->type == XML_ELEMENT_NODE) {
- if (node_is_equal(trav,"choice")) {
- schema_choice(sdl, tsn, trav, cur_type);
- } else if (node_is_equal(trav,"sequence")) {
- schema_sequence(sdl, tsn, trav, cur_type);
- } else if (node_is_equal(trav,"all")) {
- schema_all(sdl, tsn, trav, cur_type);
- } else {
- php_error(E_ERROR, "Error parsing schema (unexpected <%s> in group)",trav->name);
- }
+ if (trav != NULL) {
+ if (node_is_equal(trav,"choice")) {
+ cur_type->kind = XSD_TYPEKIND_CHOICE;
+ schema_choice(sdl, tsn, trav, cur_type);
+ trav = trav->next;
+ } else if (node_is_equal(trav,"sequence")) {
+ cur_type->kind = XSD_TYPEKIND_SEQUENCE;
+ schema_sequence(sdl, tsn, trav, cur_type);
+ trav = trav->next;
+ } else if (node_is_equal(trav,"all")) {
+ cur_type->kind = XSD_TYPEKIND_ALL;
+ schema_all(sdl, tsn, trav, cur_type);
+ trav = trav->next;
+ } else {
+ php_error(E_ERROR, "Error parsing schema (unexpected <%s> in group)",trav->name);
}
+ }
+ while (trav != NULL && trav->type != XML_ELEMENT_NODE) {
trav = trav->next;
}
+ if (trav != NULL) {
+ php_error(E_ERROR, "Error parsing schema (unexpected <%s> in group)",trav->name);
+ }
return TRUE;
}
/*
@@ -821,12 +972,16 @@ static int schema_choice(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr choiceType, sdlT
if (node_is_equal(trav,"element")) {
schema_element(sdl, tsn, trav, cur_type);
} else if (node_is_equal(trav,"grouop")) {
+ /*FIXME*/
schema_group(sdl, tsn, trav, cur_type);
} else if (node_is_equal(trav,"choice")) {
+ /*FIXME*/
schema_choice(sdl, tsn, trav, cur_type);
} else if (node_is_equal(trav,"sequence")) {
+ /*FIXME*/
schema_sequence(sdl, tsn, trav, cur_type);
} else if (node_is_equal(trav,"any")) {
+ /*FIXME*/
schema_any(sdl, tsn, trav, cur_type);
} else {
php_error(E_ERROR, "Error parsing schema (unexpected <%s> in choice)",trav->name);
@@ -866,12 +1021,16 @@ static int schema_sequence(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr seqType, sdlTy
if (node_is_equal(trav,"element")) {
schema_element(sdl, tsn, trav, cur_type);
} else if (node_is_equal(trav,"grouop")) {
+ /*FIXME*/
schema_group(sdl, tsn, trav, cur_type);
} else if (node_is_equal(trav,"choice")) {
+ /*FIXME*/
schema_choice(sdl, tsn, trav, cur_type);
} else if (node_is_equal(trav,"sequence")) {
+ /*FIXME*/
schema_sequence(sdl, tsn, trav, cur_type);
} else if (node_is_equal(trav,"any")) {
+ /*FIXME*/
schema_any(sdl, tsn, trav, cur_type);
} else {
php_error(E_ERROR, "Error parsing schema (unexpected <%s> in sequence)",trav->name);
@@ -959,42 +1118,59 @@ static int schema_complexType(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr compType, s
}
name = get_attribute(attrs, "name");
- if (name) {
+ if (cur_type != NULL) {
+ /* Anonymous type inside <element> */
sdlTypePtr newType, *ptr;
newType = malloc(sizeof(sdlType));
memset(newType, 0, sizeof(sdlType));
- newType->name = strdup(name->children->content);
- newType->namens = strdup(ns->children->content);
-
- if (cur_type == NULL) {
- zend_hash_next_index_insert(sdl->types, &newType, sizeof(sdlTypePtr), (void **)&ptr);
+ newType->kind = XSD_TYPEKIND_COMPLEX;
+ if (name != NULL) {
+ newType->name = strdup(name->children->content);
+ newType->namens = strdup(ns->children->content);
} else {
- if (cur_type->elements == NULL) {
- cur_type->elements = malloc(sizeof(HashTable));
- zend_hash_init(cur_type->elements, 0, NULL, delete_type, 1);
- }
- zend_hash_update(cur_type->elements, newType->name, strlen(newType->name) + 1, &newType, sizeof(sdlTypePtr), (void **)&ptr);
+ newType->name = strdup(cur_type->name);
+ newType->namens = strdup(cur_type->namens);
}
- cur_type = (*ptr);
- create_encoder(sdl, cur_type, ns->children->content, name->children->content);
- if (cur_type->encode == NULL) {
- cur_type->encode = get_conversion(SOAP_ENC_OBJECT);
+ zend_hash_next_index_insert(sdl->types, &newType, sizeof(sdlTypePtr), (void **)&ptr);
+
+ if (sdl->encoders == NULL) {
+ sdl->encoders = malloc(sizeof(HashTable));
+ zend_hash_init(sdl->encoders, 0, NULL, delete_encoder, 1);
}
- } else if (cur_type != NULL) {
+ cur_type->encode = malloc(sizeof(encode));
+ memset(cur_type->encode, 0, sizeof(encode));
+ cur_type->encode->details.ns = strdup(newType->namens);
+ cur_type->encode->details.type_str = strdup(newType->name);
+ cur_type->encode->details.sdl_type = *ptr;
+ cur_type->encode->to_xml = sdl_guess_convert_xml;
+ cur_type->encode->to_zval = sdl_guess_convert_zval;
+ zend_hash_next_index_insert(sdl->encoders, &cur_type->encode, sizeof(encodePtr), NULL);
+
+ cur_type =*ptr;
+
+ } else if (name) {
sdlTypePtr newType, *ptr;
newType = malloc(sizeof(sdlType));
memset(newType, 0, sizeof(sdlType));
- newType->name = strdup(cur_type->name);
- newType->namens = strdup(cur_type->namens);
+ newType->kind = XSD_TYPEKIND_COMPLEX;
+ newType->name = strdup(name->children->content);
+ newType->namens = strdup(ns->children->content);
zend_hash_next_index_insert(sdl->types, &newType, sizeof(sdlTypePtr), (void **)&ptr);
- cur_type->encode = create_encoder(sdl, *ptr, (char *)(*ptr)->namens, (char *)(*ptr)->name);
- cur_type =*ptr;
+
+ cur_type = (*ptr);
+ create_encoder(sdl, cur_type, ns->children->content, name->children->content);
+/*
+ if (cur_type->encode == NULL) {
+ cur_type->encode = get_conversion(SOAP_ENC_OBJECT);
+ }
+*/
} else {
php_error(E_ERROR, "Error parsing schema (complexType has no 'name' attribute)");
+ return FALSE;
}
trav = compType->children;
@@ -1020,12 +1196,15 @@ static int schema_complexType(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr compType, s
schema_group(sdl, tsn, trav, cur_type);
trav = trav->next;
} else if (node_is_equal(trav,"all")) {
+ cur_type->kind = XSD_TYPEKIND_ALL;
schema_all(sdl, tsn, trav, cur_type);
trav = trav->next;
} else if (node_is_equal(trav,"choice")) {
+ cur_type->kind = XSD_TYPEKIND_CHOICE;
schema_choice(sdl, tsn, trav, cur_type);
trav = trav->next;
} else if (node_is_equal(trav,"sequence")) {
+ cur_type->kind = XSD_TYPEKIND_SEQUENCE;
schema_sequence(sdl, tsn, trav, cur_type);
trav = trav->next;
}
@@ -1078,7 +1257,7 @@ static int schema_complexType(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr compType, s
static int schema_element(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr element, sdlTypePtr cur_type)
{
xmlNodePtr trav;
- xmlAttrPtr attrs, curattr, name, ns, type;
+ xmlAttrPtr attrs, curattr, ns, name, type, ref = NULL;
attrs = element->properties;
ns = get_attribute(attrs, "targetNamespace");
@@ -1087,8 +1266,8 @@ static int schema_element(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr element, sdlTyp
}
name = get_attribute(attrs, "name");
- if (!name) {
- name = get_attribute(attrs, "ref");
+ if (name == NULL) {
+ name = ref = get_attribute(attrs, "ref");
}
if (name) {
@@ -1099,8 +1278,30 @@ static int schema_element(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr element, sdlTyp
newType = malloc(sizeof(sdlType));
memset(newType, 0, sizeof(sdlType));
- newType->name = strdup(name->children->content);
- newType->namens = strdup(tsn->children->content);
+ if (ref) {
+ smart_str nscat = {0};
+ char *type, *ns;
+ xmlNsPtr nsptr;
+
+ parse_namespace(ref->children->content, &type, &ns);
+ nsptr = xmlSearchNs(element->doc, element, ns);
+ if (nsptr != NULL) {
+ smart_str_appends(&nscat, nsptr->href);
+ smart_str_appendc(&nscat, ':');
+ newType->namens = strdup(nsptr->href);
+ }
+ smart_str_appends(&nscat, type);
+ newType->name = strdup(type);
+ smart_str_0(&nscat);
+ if (type) {efree(type);}
+ if (ns) {efree(ns);}
+ newType->ref = estrdup(nscat.c);
+ smart_str_free(&nscat);
+ } else {
+ newType->name = strdup(name->children->content);
+ newType->namens = strdup(ns->children->content);
+ }
+
newType->nillable = FALSE;
newType->min_occurs = 1;
newType->max_occurs = 1;
@@ -1122,9 +1323,6 @@ static int schema_element(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr element, sdlTyp
smart_str_0(&key);
zend_hash_update(addHash, key.c, key.len + 1, &newType, sizeof(sdlTypePtr), (void **)&tmp);
cur_type = (*tmp);
-/*
- create_encoder(sdl, cur_type, ns->children->content, name->children->content);
-*/
smart_str_free(&key);
} else {
php_error(E_ERROR, "Error parsing schema (element has no 'name' nor 'ref' attributes)");
@@ -1160,15 +1358,13 @@ static int schema_element(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr element, sdlTyp
/* type = QName */
type = get_attribute(attrs, "type");
-/*
- if (!curattr) {
- curattr = name;
- }
-*/
if (type) {
char *cptype, *str_ns;
xmlNsPtr nsptr;
+ if (ref != NULL) {
+ php_error(E_ERROR, "Error parsing schema (element have both 'ref' and 'type' attributes)");
+ }
parse_namespace(type->children->content, &cptype, &str_ns);
nsptr = xmlSearchNs(element->doc, element, str_ns);
if (nsptr != NULL) {
@@ -1190,9 +1386,19 @@ static int schema_element(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr element, sdlTyp
}
if (trav != NULL) {
if (node_is_equal(trav,"simpleType")) {
+ if (ref != NULL) {
+ php_error(E_ERROR, "Error parsing schema (element have both 'ref' attribute and subtype)");
+ } else if (type != NULL) {
+ php_error(E_ERROR, "Error parsing schema (element have both 'type' attribute and subtype)");
+ }
schema_simpleType(sdl, tsn, trav, cur_type);
trav = trav->next;
} else if (node_is_equal(trav,"complexType")) {
+ if (ref != NULL) {
+ php_error(E_ERROR, "Error parsing schema (element have both 'ref' attribute and subtype)");
+ } else if (type != NULL) {
+ php_error(E_ERROR, "Error parsing schema (element have both 'type' attribute and subtype)");
+ }
schema_complexType(sdl, tsn, trav, cur_type);
trav = trav->next;
}
@@ -1373,3 +1579,47 @@ static int schema_attributeGroupRef(sdlPtr sdl, xmlAttrPtr tsn, xmlNodePtr attrG
}
return TRUE;
}
+
+static void schema_type_fixup(sdlPtr sdl, sdlTypePtr type)
+{
+ sdlTypePtr *tmp;
+
+ if (type->ref != NULL) {
+ if (zend_hash_find(sdl->elements, type->ref, strlen(type->ref)+1, (void**)&tmp) == SUCCESS) {
+ type->encode = (*tmp)->encode;
+ /* TODO: nillable minOccurs, maxOccurs */
+ } else {
+ php_error(E_ERROR, "Error parsing schema (unresolved element 'ref' attribute)");
+ }
+ efree(type->ref);
+ type->ref = NULL;
+ }
+ if (type->elements) {
+ zend_hash_internal_pointer_reset(type->elements);
+ while (zend_hash_get_current_data(type->elements,(void**)&tmp) == SUCCESS) {
+ schema_type_fixup(sdl,*tmp);
+ zend_hash_move_forward(type->elements);
+ }
+ }
+}
+
+int schema_pass2(sdlPtr sdl)
+{
+ sdlTypePtr *type;
+
+ if (sdl->elements) {
+ zend_hash_internal_pointer_reset(sdl->elements);
+ while (zend_hash_get_current_data(sdl->elements,(void**)&type) == SUCCESS) {
+ schema_type_fixup(sdl,*type);
+ zend_hash_move_forward(sdl->elements);
+ }
+ }
+ if (sdl->types) {
+ zend_hash_internal_pointer_reset(sdl->types);
+ while (zend_hash_get_current_data(sdl->types,(void**)&type) == SUCCESS) {
+ schema_type_fixup(sdl,*type);
+ zend_hash_move_forward(sdl->types);
+ }
+ }
+ return TRUE;
+}
diff --git a/ext/soap/php_schema.h b/ext/soap/php_schema.h
index ed7a9d8e78..74994485dd 100644
--- a/ext/soap/php_schema.h
+++ b/ext/soap/php_schema.h
@@ -2,5 +2,6 @@
#define PHP_SCHEMA_H
int load_schema(sdlPtr sdl, xmlNodePtr schema);
+int schema_pass2(sdlPtr sdl);
#endif
diff --git a/ext/soap/php_sdl.c b/ext/soap/php_sdl.c
index 7f33427e8f..4d727b3e67 100644
--- a/ext/soap/php_sdl.c
+++ b/ext/soap/php_sdl.c
@@ -28,7 +28,7 @@ encodePtr get_encoder_from_prefix(sdlPtr sdl, xmlNodePtr data, const char *type)
return enc;
}
-encodePtr get_encoder_from_element(sdlPtr sdl, xmlNodePtr node, const char *type)
+static encodePtr get_encoder_from_element(sdlPtr sdl, xmlNodePtr node, const char *type)
{
encodePtr enc = NULL;
TSRMLS_FETCH();
@@ -161,6 +161,75 @@ encodePtr create_encoder(sdlPtr sdl, sdlTypePtr cur_type, const char *ns, const
return enc;
}
+static zval* to_zval_list(encodeType enc, xmlNodePtr data) {
+ zval *ret;
+ MAKE_STD_ZVAL(ret);
+ FIND_XML_NULL(data, ret);
+ if (data && data->children) {
+ if (data->children->type == XML_TEXT_NODE && data->children->next == NULL) {
+ whiteSpace_collapse(data->children->content);
+ ZVAL_STRING(ret, data->children->content, 1);
+ } else {
+ php_error(E_ERROR,"Violation of encoding rules");
+ }
+ } else {
+ ZVAL_EMPTY_STRING(ret);
+ }
+ return ret;
+}
+
+static xmlNodePtr to_xml_list(encodeType 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(&copy);
+ convert_to_string(&copy);
+ smart_str_appendl(&list, Z_STRVAL(copy), Z_STRLEN(copy));
+ zval_dtor(&copy);
+ }
+ 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(encodeType enc, xmlNodePtr data) {
+ /*FIXME*/
+ return to_zval_list(enc, data);
+}
+
+static xmlNodePtr to_xml_union(encodeType enc, zval *data, int style) {
+ /*FIXME*/
+ return to_xml_list(enc,data,style);
+}
+
zval *sdl_guess_convert_zval(encodeType enc, xmlNodePtr data)
{
sdlTypePtr type;
@@ -209,6 +278,10 @@ zval *sdl_guess_convert_zval(encodeType enc, xmlNodePtr data)
return master_to_zval(get_conversion(UNKNOWN_TYPE), data);
}
}
+ } else if (type->kind == XSD_TYPEKIND_LIST) {
+ return to_zval_list(enc, data);
+ } else if (type->kind == XSD_TYPEKIND_UNION) {
+ return to_zval_union(enc, data);
} else if (type->elements) {
return to_zval_object(enc, data);
} else {
@@ -258,12 +331,18 @@ xmlNodePtr sdl_guess_convert_xml(encodeType enc, zval *data, int style)
ret = master_to_xml(get_conversion(UNKNOWN_TYPE), data, style);
}
}
- }
- else if (type->elements) {
+ } else if (type->kind == XSD_TYPEKIND_LIST) {
+ ret = to_xml_list(enc, data, style);
+ } else if (type->kind == XSD_TYPEKIND_UNION) {
+ ret = to_xml_union(enc, data, style);
+ } else if (type->elements) {
ret = to_xml_object(enc, data, style);
} else {
ret = guess_xml_convert(enc, data, style);
}
+ if (style == SOAP_ENCODED) {
+ set_ns_and_type(ret, enc);
+ }
return ret;
}
@@ -428,6 +507,8 @@ static sdlPtr load_wsdl(char *struri)
load_wsdl_ex(struri,&ctx, 0);
+ schema_pass2(ctx.root);
+
n = zend_hash_num_elements(&ctx.services);
if (n > 0) {
zend_hash_internal_pointer_reset(&ctx.services);
@@ -688,6 +769,7 @@ static sdlPtr load_wsdl(char *struri)
sdlParamPtr param;
param = malloc(sizeof(sdlParam));
+ memset(param,0,sizeof(sdlParam));
param->order = 0;
name = get_attribute(part->properties, "name");
@@ -783,6 +865,7 @@ static sdlPtr load_wsdl(char *struri)
xmlAttrPtr element, type, name;
param = malloc(sizeof(sdlParam));
+ memset(param, 0, sizeof(sdlParam));
param->order = 0;
name = get_attribute(part->properties, "name");
diff --git a/ext/soap/php_sdl.h b/ext/soap/php_sdl.h
index 06c0a83274..ae6a90be6b 100644
--- a/ext/soap/php_sdl.h
+++ b/ext/soap/php_sdl.h
@@ -90,7 +90,19 @@ struct _sdlRestrictions {
sdlRestrictionCharPtr pattern;
};
+typedef enum _sdlTypeKind {
+ XSD_TYPEKIND_UNKNOWN,
+ XSD_TYPEKIND_SIMPLE,
+ XSD_TYPEKIND_COMPLEX,
+ XSD_TYPEKIND_LIST,
+ XSD_TYPEKIND_UNION,
+ XSD_TYPEKIND_ALL,
+ XSD_TYPEKIND_SEQUENCE,
+ XSD_TYPEKIND_CHOICE
+} sdlTypeKind;
+
struct _sdlType {
+ sdlTypeKind kind;
char *name;
char *namens;
int nillable;
@@ -100,6 +112,7 @@ struct _sdlType {
HashTable *attributes; /* array of sdlAttributePtr */
sdlRestrictionsPtr restrictions;
encodePtr encode;
+ char *ref;
};
struct _sdlParam {
diff --git a/ext/soap/soap.c b/ext/soap/soap.c
index b7b060fcd7..f69c131b77 100644
--- a/ext/soap/soap.c
+++ b/ext/soap/soap.c
@@ -1200,7 +1200,6 @@ PHP_METHOD(soapserver, handle)
zval_dtor(&function_name);
xmlFreeDoc(doc_return);
- efree(fn_name);
php_write(buf, size TSRMLS_CC);
xmlFree(buf);
@@ -1981,7 +1980,11 @@ static xmlDocPtr seralize_response_call(sdlFunctionPtr function, char *function_
}
if (function != NULL) {
- param_count = zend_hash_num_elements(function->responseParameters);
+ if (function->responseParameters) {
+ param_count = zend_hash_num_elements(function->responseParameters);
+ } else {
+ param_count = 0;
+ }
} else {
param_count = 1;
}
@@ -2219,9 +2222,8 @@ static xmlNodePtr seralize_zval(zval *val, sdlParamPtr param, char *paramName, i
if (param != NULL) {
enc = param->encode;
} else {
- enc = get_conversion(val->type);
+ enc = get_conversion(val->type);
}
-
xmlParam = master_to_xml(enc, val, style);
if (!strcmp(xmlParam->name, "BOGUS")) {
xmlNodeSetName(xmlParam, paramName);