Skip to content

Implement request #61105: Support Soap 1.2 SoapFault Reason Text lang attribute #18701

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,13 @@ PHP 8.5 UPGRADE NOTES
IntlListFormatter::WIDTH_NARROW widths.
It is supported from icu 67.

- SOAP:
. Implemented request #61105:
support for Soap 1.2 Reason Text xml:lang attribute.
The signature of SoapFault::__construct() and SoapServer::fault() therefore
now have an optional $lang parameter.
This support solves compatibility with .NET SOAP clients.

- XSL:
. The $namespace argument of XSLTProcessor::getParameter(),
XSLTProcessor::setParameter() and XSLTProcessor::removeParameter()
Expand Down
24 changes: 12 additions & 12 deletions ext/soap/php_http.c
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ int make_http_soap_request(zval *this_ptr,
if (request != buf) {
zend_string_release_ex(request, 0);
}
add_soap_fault(this_ptr, "HTTP", "Unable to parse URL", NULL, NULL);
add_soap_fault(this_ptr, "HTTP", "Unable to parse URL", NULL, NULL, SOAP_GLOBAL(lang_en));
smart_str_free(&soap_headers_z);
efree(http_msg);
return FALSE;
Expand All @@ -469,7 +469,7 @@ int make_http_soap_request(zval *this_ptr,
if (request != buf) {
zend_string_release_ex(request, 0);
}
add_soap_fault(this_ptr, "HTTP", "Unknown protocol. Only http and https are allowed.", NULL, NULL);
add_soap_fault(this_ptr, "HTTP", "Unknown protocol. Only http and https are allowed.", NULL, NULL, SOAP_GLOBAL(lang_en));
smart_str_free(&soap_headers_z);
efree(http_msg);
return FALSE;
Expand All @@ -482,7 +482,7 @@ int make_http_soap_request(zval *this_ptr,
if (request != buf) {
zend_string_release_ex(request, 0);
}
add_soap_fault(this_ptr, "HTTP", "SSL support is not available in this build", NULL, NULL);
add_soap_fault(this_ptr, "HTTP", "SSL support is not available in this build", NULL, NULL, SOAP_GLOBAL(lang_en));
PG(allow_url_fopen) = old_allow_url_fopen;
smart_str_free(&soap_headers_z);
efree(http_msg);
Expand Down Expand Up @@ -537,7 +537,7 @@ int make_http_soap_request(zval *this_ptr,
if (request != buf) {
zend_string_release_ex(request, 0);
}
add_soap_fault(this_ptr, "HTTP", "Could not connect to host", NULL, NULL);
add_soap_fault(this_ptr, "HTTP", "Could not connect to host", NULL, NULL, SOAP_GLOBAL(lang_en));
PG(allow_url_fopen) = old_allow_url_fopen;
smart_str_free(&soap_headers_z);
efree(http_msg);
Expand Down Expand Up @@ -908,14 +908,14 @@ int make_http_soap_request(zval *this_ptr,
convert_to_null(Z_CLIENT_HTTPURL_P(this_ptr));
convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr));
convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr));
add_soap_fault(this_ptr, "HTTP", "Failed Sending HTTP SOAP request", NULL, NULL);
add_soap_fault(this_ptr, "HTTP", "Failed Sending HTTP SOAP request", NULL, NULL, SOAP_GLOBAL(lang_en));
smart_str_free(&soap_headers_z);
efree(http_msg);
return FALSE;
}
smart_str_free(&soap_headers);
} else {
add_soap_fault(this_ptr, "HTTP", "Failed to create stream??", NULL, NULL);
add_soap_fault(this_ptr, "HTTP", "Failed to create stream??", NULL, NULL, SOAP_GLOBAL(lang_en));
smart_str_free(&soap_headers_z);
efree(http_msg);
return FALSE;
Expand All @@ -932,7 +932,7 @@ int make_http_soap_request(zval *this_ptr,
php_stream_close(stream);
convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr));
convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr));
add_soap_fault(this_ptr, "HTTP", "Error Fetching http headers", NULL, NULL);
add_soap_fault(this_ptr, "HTTP", "Error Fetching http headers", NULL, NULL, SOAP_GLOBAL(lang_en));
smart_str_free(&soap_headers_z);
efree(http_msg);
return FALSE;
Expand Down Expand Up @@ -1121,7 +1121,7 @@ int make_http_soap_request(zval *this_ptr,
zend_string_release_ex(http_headers, 0);
convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr));
convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr));
add_soap_fault(this_ptr, "HTTP", "Error Fetching http body, No Content-Length, connection closed or chunked data", NULL, NULL);
add_soap_fault(this_ptr, "HTTP", "Error Fetching http body, No Content-Length, connection closed or chunked data", NULL, NULL, SOAP_GLOBAL(lang_en));
if (http_msg) {
efree(http_msg);
}
Expand Down Expand Up @@ -1180,7 +1180,7 @@ int make_http_soap_request(zval *this_ptr,
phpurl = new_url;

if (--redirect_max < 1) {
add_soap_fault(this_ptr, "HTTP", "Redirection limit reached, aborting", NULL, NULL);
add_soap_fault(this_ptr, "HTTP", "Redirection limit reached, aborting", NULL, NULL, SOAP_GLOBAL(lang_en));
smart_str_free(&soap_headers_z);
efree(http_msg);
return FALSE;
Expand Down Expand Up @@ -1318,7 +1318,7 @@ int make_http_soap_request(zval *this_ptr,
if (http_msg) {
efree(http_msg);
}
add_soap_fault(this_ptr, "HTTP", "Unknown Content-Encoding", NULL, NULL);
add_soap_fault(this_ptr, "HTTP", "Unknown Content-Encoding", NULL, NULL, SOAP_GLOBAL(lang_en));
return FALSE;
}
if (call_user_function(CG(function_table), (zval*)NULL, &func, &retval, 1, params) == SUCCESS &&
Expand All @@ -1334,7 +1334,7 @@ int make_http_soap_request(zval *this_ptr,
efree(content_encoding);
zend_string_release_ex(http_headers, 0);
zend_string_release_ex(http_body, 0);
add_soap_fault(this_ptr, "HTTP", "Can't uncompress compressed response", NULL, NULL);
add_soap_fault(this_ptr, "HTTP", "Can't uncompress compressed response", NULL, NULL, SOAP_GLOBAL(lang_en));
if (http_msg) {
efree(http_msg);
}
Expand Down Expand Up @@ -1368,7 +1368,7 @@ int make_http_soap_request(zval *this_ptr,
if (error) {
zval_ptr_dtor(return_value);
ZVAL_UNDEF(return_value);
add_soap_fault(this_ptr, "HTTP", http_msg, NULL, NULL);
add_soap_fault(this_ptr, "HTTP", http_msg, NULL, NULL, SOAP_GLOBAL(lang_en));
efree(http_msg);
return FALSE;
}
Expand Down
44 changes: 27 additions & 17 deletions ext/soap/php_packet_soap.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ bool parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctio
response = soap_xmlParseMemory(buffer, buffer_size);

if (!response) {
add_soap_fault(this_ptr, "Client", "looks like we got no XML document", NULL, NULL);
add_soap_fault(this_ptr, "Client", "looks like we got no XML document", NULL, NULL, SOAP_GLOBAL(lang_en));
return false;
}
if (xmlGetIntSubset(response) != NULL) {
add_soap_fault(this_ptr, "Client", "DTD are not supported by SOAP", NULL, NULL);
add_soap_fault(this_ptr, "Client", "DTD are not supported by SOAP", NULL, NULL, SOAP_GLOBAL(lang_en));
xmlFreeDoc(response);
return false;
}
Expand All @@ -63,32 +63,32 @@ bool parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctio
envelope_ns = SOAP_1_2_ENV_NAMESPACE;
soap_version = SOAP_1_2;
} else {
add_soap_fault(this_ptr, "VersionMismatch", "Wrong Version", NULL, NULL);
add_soap_fault(this_ptr, "VersionMismatch", "Wrong Version", NULL, NULL, SOAP_GLOBAL(lang_en));
xmlFreeDoc(response);
return false;
}
}
trav = trav->next;
}
if (env == NULL) {
add_soap_fault(this_ptr, "Client", "looks like we got XML without \"Envelope\" element", NULL, NULL);
add_soap_fault(this_ptr, "Client", "looks like we got XML without \"Envelope\" element", NULL, NULL, SOAP_GLOBAL(lang_en));
xmlFreeDoc(response);
return false;
}

attr = env->properties;
while (attr != NULL) {
if (attr->ns == NULL) {
add_soap_fault(this_ptr, "Client", "A SOAP Envelope element cannot have non Namespace qualified attributes", NULL, NULL);
add_soap_fault(this_ptr, "Client", "A SOAP Envelope element cannot have non Namespace qualified attributes", NULL, NULL, SOAP_GLOBAL(lang_en));
xmlFreeDoc(response);
return false;
} else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) {
if (soap_version == SOAP_1_2) {
add_soap_fault(this_ptr, "Client", "encodingStyle cannot be specified on the Envelope", NULL, NULL);
add_soap_fault(this_ptr, "Client", "encodingStyle cannot be specified on the Envelope", NULL, NULL, SOAP_GLOBAL(lang_en));
xmlFreeDoc(response);
return false;
} else if (strcmp((char*)attr->children->content, SOAP_1_1_ENC_NAMESPACE) != 0) {
add_soap_fault(this_ptr, "Client", "Unknown data encoding style", NULL, NULL);
add_soap_fault(this_ptr, "Client", "Unknown data encoding style", NULL, NULL, SOAP_GLOBAL(lang_en));
xmlFreeDoc(response);
return false;
}
Expand Down Expand Up @@ -120,33 +120,33 @@ bool parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctio
trav = trav->next;
}
if (body == NULL) {
add_soap_fault(this_ptr, "Client", "Body must be present in a SOAP envelope", NULL, NULL);
add_soap_fault(this_ptr, "Client", "Body must be present in a SOAP envelope", NULL, NULL, SOAP_GLOBAL(lang_en));
xmlFreeDoc(response);
return false;
}
attr = body->properties;
while (attr != NULL) {
if (attr->ns == NULL) {
if (soap_version == SOAP_1_2) {
add_soap_fault(this_ptr, "Client", "A SOAP Body element cannot have non Namespace qualified attributes", NULL, NULL);
add_soap_fault(this_ptr, "Client", "A SOAP Body element cannot have non Namespace qualified attributes", NULL, NULL, SOAP_GLOBAL(lang_en));
xmlFreeDoc(response);
return false;
}
} else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) {
if (soap_version == SOAP_1_2) {
add_soap_fault(this_ptr, "Client", "encodingStyle cannot be specified on the Body", NULL, NULL);
add_soap_fault(this_ptr, "Client", "encodingStyle cannot be specified on the Body", NULL, NULL, SOAP_GLOBAL(lang_en));
xmlFreeDoc(response);
return false;
} else if (strcmp((char*)attr->children->content, SOAP_1_1_ENC_NAMESPACE) != 0) {
add_soap_fault(this_ptr, "Client", "Unknown data encoding style", NULL, NULL);
add_soap_fault(this_ptr, "Client", "Unknown data encoding style", NULL, NULL, SOAP_GLOBAL(lang_en));
xmlFreeDoc(response);
return false;
}
}
attr = attr->next;
}
if (trav != NULL && soap_version == SOAP_1_2) {
add_soap_fault(this_ptr, "Client", "A SOAP 1.2 envelope can contain only Header and Body", NULL, NULL);
add_soap_fault(this_ptr, "Client", "A SOAP 1.2 envelope can contain only Header and Body", NULL, NULL, SOAP_GLOBAL(lang_en));
xmlFreeDoc(response);
return false;
}
Expand All @@ -155,16 +155,16 @@ bool parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctio
attr = head->properties;
while (attr != NULL) {
if (attr->ns == NULL) {
add_soap_fault(this_ptr, "Client", "A SOAP Header element cannot have non Namespace qualified attributes", NULL, NULL);
add_soap_fault(this_ptr, "Client", "A SOAP Header element cannot have non Namespace qualified attributes", NULL, NULL, SOAP_GLOBAL(lang_en));
xmlFreeDoc(response);
return false;
} else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) {
if (soap_version == SOAP_1_2) {
add_soap_fault(this_ptr, "Client", "encodingStyle cannot be specified on the Header", NULL, NULL);
add_soap_fault(this_ptr, "Client", "encodingStyle cannot be specified on the Header", NULL, NULL, SOAP_GLOBAL(lang_en));
xmlFreeDoc(response);
return false;
} else if (strcmp((char*)attr->children->content, SOAP_1_1_ENC_NAMESPACE) != 0) {
add_soap_fault(this_ptr, "Client", "Unknown data encoding style", NULL, NULL);
add_soap_fault(this_ptr, "Client", "Unknown data encoding style", NULL, NULL, SOAP_GLOBAL(lang_en));
xmlFreeDoc(response);
return false;
}
Expand All @@ -177,6 +177,7 @@ bool parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctio
fault = get_node_ex(body->children,"Fault",envelope_ns);
if (fault != NULL) {
char *faultcode = NULL;
zend_string *lang = NULL;
zend_string *faultstring = NULL, *faultactor = NULL;
zval details;
xmlNodePtr tmp;
Expand Down Expand Up @@ -219,13 +220,19 @@ bool parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctio

tmp = get_node(fault->children,"Reason");
if (tmp != NULL && tmp->children != NULL) {
/* TODO: lang attribute */
tmp = get_node(tmp->children,"Text");
if (tmp != NULL && tmp->children != NULL) {
zval zv;
master_to_zval(&zv, get_conversion(IS_STRING), tmp);
convert_to_string(&zv)
faultstring = Z_STR(zv);

/* xml:lang is required by SOAP 1.2, but for BC reasons we allow it to be missing */
xmlAttrPtr lang_attr = get_attribute_ex(tmp->properties, "lang", (const char *) XML_XML_NAMESPACE);
if (lang_attr != NULL && lang_attr->children != NULL) {
const char *lang_str = (const char *) lang_attr->children->content;
lang = zend_string_init(lang_str, strlen(lang_str), false);
}
}
}

Expand All @@ -234,13 +241,16 @@ bool parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctio
master_to_zval(&details, NULL, tmp);
}
}
add_soap_fault(this_ptr, faultcode, faultstring ? ZSTR_VAL(faultstring) : NULL, faultactor ? ZSTR_VAL(faultactor) : NULL, &details);
add_soap_fault(this_ptr, faultcode, faultstring ? ZSTR_VAL(faultstring) : NULL, faultactor ? ZSTR_VAL(faultactor) : NULL, &details, lang);
if (faultstring) {
zend_string_release_ex(faultstring, 0);
}
if (faultactor) {
zend_string_release_ex(faultactor, 0);
}
if (lang) {
zend_string_release_ex(lang, false);
}
if (Z_REFCOUNTED(details)) {
Z_DELREF(details);
}
Expand Down
3 changes: 2 additions & 1 deletion ext/soap/php_soap.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ ZEND_BEGIN_MODULE_GLOBALS(soap)
HashTable wsdl_cache;
int cur_uniq_ref;
HashTable *ref_map;
zend_string *lang_en;
ZEND_END_MODULE_GLOBALS(soap)

#ifdef ZTS
Expand All @@ -195,7 +196,7 @@ extern zend_class_entry* soap_var_class_entry;
extern zend_class_entry* soap_url_class_entry;
extern zend_class_entry* soap_sdl_class_entry;

void add_soap_fault(zval *obj, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail);
void add_soap_fault(zval *obj, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail, zend_string *lang);

#define soap_error0(severity, format) \
php_error(severity, "SOAP-ERROR: " format)
Expand Down
Loading