Skip to content

Commit 9859d83

Browse files
committed
Implement request #61105: Support Soap 1.2 SoapFault Reason Text lang attribute
This is on the border line of a bugfix and a new feature. Anyway, this is necessary to fix compatibility with .NET clients. Closes GH-18701.
1 parent ed2bebd commit 9859d83

36 files changed

+205
-118
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,8 @@ PHP NEWS
202202
. Fixed bug #70951 (Segmentation fault on invalid WSDL cache). (nielsdos)
203203
. Implement request #55503 (Extend __getTypes to support enumerations).
204204
(nielsdos, datibbaw)
205+
. Implement request #61105 (Support Soap 1.2 SoapFault Reason Text lang
206+
attribute). (nielsdos)
205207

206208
- Sockets:
207209
. Added IPPROTO_ICMP/IPPROTO_ICMPV6 to create raw socket for ICMP usage.

UPGRADING

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,11 @@ PHP 8.5 UPGRADE NOTES
204204

205205
- SOAP:
206206
. Enumeration cases are now dumped in __getTypes().
207+
. Implemented request #61105:
208+
support for Soap 1.2 Reason Text xml:lang attribute.
209+
The signature of SoapFault::__construct() and SoapServer::fault() therefore
210+
now have an optional $lang parameter.
211+
This support solves compatibility with .NET SOAP clients.
207212

208213
- XSL:
209214
. The $namespace argument of XSLTProcessor::getParameter(),

ext/soap/php_http.c

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@ int make_http_soap_request(zval *this_ptr,
455455
if (request != buf) {
456456
zend_string_release_ex(request, 0);
457457
}
458-
add_soap_fault(this_ptr, "HTTP", "Unable to parse URL", NULL, NULL);
458+
add_soap_fault(this_ptr, "HTTP", "Unable to parse URL", NULL, NULL, SOAP_GLOBAL(lang_en));
459459
smart_str_free(&soap_headers_z);
460460
efree(http_msg);
461461
return FALSE;
@@ -469,7 +469,7 @@ int make_http_soap_request(zval *this_ptr,
469469
if (request != buf) {
470470
zend_string_release_ex(request, 0);
471471
}
472-
add_soap_fault(this_ptr, "HTTP", "Unknown protocol. Only http and https are allowed.", NULL, NULL);
472+
add_soap_fault(this_ptr, "HTTP", "Unknown protocol. Only http and https are allowed.", NULL, NULL, SOAP_GLOBAL(lang_en));
473473
smart_str_free(&soap_headers_z);
474474
efree(http_msg);
475475
return FALSE;
@@ -482,7 +482,7 @@ int make_http_soap_request(zval *this_ptr,
482482
if (request != buf) {
483483
zend_string_release_ex(request, 0);
484484
}
485-
add_soap_fault(this_ptr, "HTTP", "SSL support is not available in this build", NULL, NULL);
485+
add_soap_fault(this_ptr, "HTTP", "SSL support is not available in this build", NULL, NULL, SOAP_GLOBAL(lang_en));
486486
PG(allow_url_fopen) = old_allow_url_fopen;
487487
smart_str_free(&soap_headers_z);
488488
efree(http_msg);
@@ -537,7 +537,7 @@ int make_http_soap_request(zval *this_ptr,
537537
if (request != buf) {
538538
zend_string_release_ex(request, 0);
539539
}
540-
add_soap_fault(this_ptr, "HTTP", "Could not connect to host", NULL, NULL);
540+
add_soap_fault(this_ptr, "HTTP", "Could not connect to host", NULL, NULL, SOAP_GLOBAL(lang_en));
541541
PG(allow_url_fopen) = old_allow_url_fopen;
542542
smart_str_free(&soap_headers_z);
543543
efree(http_msg);
@@ -908,14 +908,14 @@ int make_http_soap_request(zval *this_ptr,
908908
convert_to_null(Z_CLIENT_HTTPURL_P(this_ptr));
909909
convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr));
910910
convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr));
911-
add_soap_fault(this_ptr, "HTTP", "Failed Sending HTTP SOAP request", NULL, NULL);
911+
add_soap_fault(this_ptr, "HTTP", "Failed Sending HTTP SOAP request", NULL, NULL, SOAP_GLOBAL(lang_en));
912912
smart_str_free(&soap_headers_z);
913913
efree(http_msg);
914914
return FALSE;
915915
}
916916
smart_str_free(&soap_headers);
917917
} else {
918-
add_soap_fault(this_ptr, "HTTP", "Failed to create stream??", NULL, NULL);
918+
add_soap_fault(this_ptr, "HTTP", "Failed to create stream??", NULL, NULL, SOAP_GLOBAL(lang_en));
919919
smart_str_free(&soap_headers_z);
920920
efree(http_msg);
921921
return FALSE;
@@ -932,7 +932,7 @@ int make_http_soap_request(zval *this_ptr,
932932
php_stream_close(stream);
933933
convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr));
934934
convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr));
935-
add_soap_fault(this_ptr, "HTTP", "Error Fetching http headers", NULL, NULL);
935+
add_soap_fault(this_ptr, "HTTP", "Error Fetching http headers", NULL, NULL, SOAP_GLOBAL(lang_en));
936936
smart_str_free(&soap_headers_z);
937937
efree(http_msg);
938938
return FALSE;
@@ -1121,7 +1121,7 @@ int make_http_soap_request(zval *this_ptr,
11211121
zend_string_release_ex(http_headers, 0);
11221122
convert_to_null(Z_CLIENT_HTTPSOCKET_P(this_ptr));
11231123
convert_to_null(Z_CLIENT_USE_PROXY_P(this_ptr));
1124-
add_soap_fault(this_ptr, "HTTP", "Error Fetching http body, No Content-Length, connection closed or chunked data", NULL, NULL);
1124+
add_soap_fault(this_ptr, "HTTP", "Error Fetching http body, No Content-Length, connection closed or chunked data", NULL, NULL, SOAP_GLOBAL(lang_en));
11251125
if (http_msg) {
11261126
efree(http_msg);
11271127
}
@@ -1180,7 +1180,7 @@ int make_http_soap_request(zval *this_ptr,
11801180
phpurl = new_url;
11811181

11821182
if (--redirect_max < 1) {
1183-
add_soap_fault(this_ptr, "HTTP", "Redirection limit reached, aborting", NULL, NULL);
1183+
add_soap_fault(this_ptr, "HTTP", "Redirection limit reached, aborting", NULL, NULL, SOAP_GLOBAL(lang_en));
11841184
smart_str_free(&soap_headers_z);
11851185
efree(http_msg);
11861186
return FALSE;
@@ -1318,7 +1318,7 @@ int make_http_soap_request(zval *this_ptr,
13181318
if (http_msg) {
13191319
efree(http_msg);
13201320
}
1321-
add_soap_fault(this_ptr, "HTTP", "Unknown Content-Encoding", NULL, NULL);
1321+
add_soap_fault(this_ptr, "HTTP", "Unknown Content-Encoding", NULL, NULL, SOAP_GLOBAL(lang_en));
13221322
return FALSE;
13231323
}
13241324
if (call_user_function(CG(function_table), (zval*)NULL, &func, &retval, 1, params) == SUCCESS &&
@@ -1334,7 +1334,7 @@ int make_http_soap_request(zval *this_ptr,
13341334
efree(content_encoding);
13351335
zend_string_release_ex(http_headers, 0);
13361336
zend_string_release_ex(http_body, 0);
1337-
add_soap_fault(this_ptr, "HTTP", "Can't uncompress compressed response", NULL, NULL);
1337+
add_soap_fault(this_ptr, "HTTP", "Can't uncompress compressed response", NULL, NULL, SOAP_GLOBAL(lang_en));
13381338
if (http_msg) {
13391339
efree(http_msg);
13401340
}
@@ -1368,7 +1368,7 @@ int make_http_soap_request(zval *this_ptr,
13681368
if (error) {
13691369
zval_ptr_dtor(return_value);
13701370
ZVAL_UNDEF(return_value);
1371-
add_soap_fault(this_ptr, "HTTP", http_msg, NULL, NULL);
1371+
add_soap_fault(this_ptr, "HTTP", http_msg, NULL, NULL, SOAP_GLOBAL(lang_en));
13721372
efree(http_msg);
13731373
return FALSE;
13741374
}

ext/soap/php_packet_soap.c

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,11 @@ bool parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctio
4040
response = soap_xmlParseMemory(buffer, buffer_size);
4141

4242
if (!response) {
43-
add_soap_fault(this_ptr, "Client", "looks like we got no XML document", NULL, NULL);
43+
add_soap_fault(this_ptr, "Client", "looks like we got no XML document", NULL, NULL, SOAP_GLOBAL(lang_en));
4444
return false;
4545
}
4646
if (xmlGetIntSubset(response) != NULL) {
47-
add_soap_fault(this_ptr, "Client", "DTD are not supported by SOAP", NULL, NULL);
47+
add_soap_fault(this_ptr, "Client", "DTD are not supported by SOAP", NULL, NULL, SOAP_GLOBAL(lang_en));
4848
xmlFreeDoc(response);
4949
return false;
5050
}
@@ -63,32 +63,32 @@ bool parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctio
6363
envelope_ns = SOAP_1_2_ENV_NAMESPACE;
6464
soap_version = SOAP_1_2;
6565
} else {
66-
add_soap_fault(this_ptr, "VersionMismatch", "Wrong Version", NULL, NULL);
66+
add_soap_fault(this_ptr, "VersionMismatch", "Wrong Version", NULL, NULL, SOAP_GLOBAL(lang_en));
6767
xmlFreeDoc(response);
6868
return false;
6969
}
7070
}
7171
trav = trav->next;
7272
}
7373
if (env == NULL) {
74-
add_soap_fault(this_ptr, "Client", "looks like we got XML without \"Envelope\" element", NULL, NULL);
74+
add_soap_fault(this_ptr, "Client", "looks like we got XML without \"Envelope\" element", NULL, NULL, SOAP_GLOBAL(lang_en));
7575
xmlFreeDoc(response);
7676
return false;
7777
}
7878

7979
attr = env->properties;
8080
while (attr != NULL) {
8181
if (attr->ns == NULL) {
82-
add_soap_fault(this_ptr, "Client", "A SOAP Envelope element cannot have non Namespace qualified attributes", NULL, NULL);
82+
add_soap_fault(this_ptr, "Client", "A SOAP Envelope element cannot have non Namespace qualified attributes", NULL, NULL, SOAP_GLOBAL(lang_en));
8383
xmlFreeDoc(response);
8484
return false;
8585
} else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) {
8686
if (soap_version == SOAP_1_2) {
87-
add_soap_fault(this_ptr, "Client", "encodingStyle cannot be specified on the Envelope", NULL, NULL);
87+
add_soap_fault(this_ptr, "Client", "encodingStyle cannot be specified on the Envelope", NULL, NULL, SOAP_GLOBAL(lang_en));
8888
xmlFreeDoc(response);
8989
return false;
9090
} else if (strcmp((char*)attr->children->content, SOAP_1_1_ENC_NAMESPACE) != 0) {
91-
add_soap_fault(this_ptr, "Client", "Unknown data encoding style", NULL, NULL);
91+
add_soap_fault(this_ptr, "Client", "Unknown data encoding style", NULL, NULL, SOAP_GLOBAL(lang_en));
9292
xmlFreeDoc(response);
9393
return false;
9494
}
@@ -120,33 +120,33 @@ bool parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctio
120120
trav = trav->next;
121121
}
122122
if (body == NULL) {
123-
add_soap_fault(this_ptr, "Client", "Body must be present in a SOAP envelope", NULL, NULL);
123+
add_soap_fault(this_ptr, "Client", "Body must be present in a SOAP envelope", NULL, NULL, SOAP_GLOBAL(lang_en));
124124
xmlFreeDoc(response);
125125
return false;
126126
}
127127
attr = body->properties;
128128
while (attr != NULL) {
129129
if (attr->ns == NULL) {
130130
if (soap_version == SOAP_1_2) {
131-
add_soap_fault(this_ptr, "Client", "A SOAP Body element cannot have non Namespace qualified attributes", NULL, NULL);
131+
add_soap_fault(this_ptr, "Client", "A SOAP Body element cannot have non Namespace qualified attributes", NULL, NULL, SOAP_GLOBAL(lang_en));
132132
xmlFreeDoc(response);
133133
return false;
134134
}
135135
} else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) {
136136
if (soap_version == SOAP_1_2) {
137-
add_soap_fault(this_ptr, "Client", "encodingStyle cannot be specified on the Body", NULL, NULL);
137+
add_soap_fault(this_ptr, "Client", "encodingStyle cannot be specified on the Body", NULL, NULL, SOAP_GLOBAL(lang_en));
138138
xmlFreeDoc(response);
139139
return false;
140140
} else if (strcmp((char*)attr->children->content, SOAP_1_1_ENC_NAMESPACE) != 0) {
141-
add_soap_fault(this_ptr, "Client", "Unknown data encoding style", NULL, NULL);
141+
add_soap_fault(this_ptr, "Client", "Unknown data encoding style", NULL, NULL, SOAP_GLOBAL(lang_en));
142142
xmlFreeDoc(response);
143143
return false;
144144
}
145145
}
146146
attr = attr->next;
147147
}
148148
if (trav != NULL && soap_version == SOAP_1_2) {
149-
add_soap_fault(this_ptr, "Client", "A SOAP 1.2 envelope can contain only Header and Body", NULL, NULL);
149+
add_soap_fault(this_ptr, "Client", "A SOAP 1.2 envelope can contain only Header and Body", NULL, NULL, SOAP_GLOBAL(lang_en));
150150
xmlFreeDoc(response);
151151
return false;
152152
}
@@ -155,16 +155,16 @@ bool parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctio
155155
attr = head->properties;
156156
while (attr != NULL) {
157157
if (attr->ns == NULL) {
158-
add_soap_fault(this_ptr, "Client", "A SOAP Header element cannot have non Namespace qualified attributes", NULL, NULL);
158+
add_soap_fault(this_ptr, "Client", "A SOAP Header element cannot have non Namespace qualified attributes", NULL, NULL, SOAP_GLOBAL(lang_en));
159159
xmlFreeDoc(response);
160160
return false;
161161
} else if (attr_is_equal_ex(attr,"encodingStyle",SOAP_1_2_ENV_NAMESPACE)) {
162162
if (soap_version == SOAP_1_2) {
163-
add_soap_fault(this_ptr, "Client", "encodingStyle cannot be specified on the Header", NULL, NULL);
163+
add_soap_fault(this_ptr, "Client", "encodingStyle cannot be specified on the Header", NULL, NULL, SOAP_GLOBAL(lang_en));
164164
xmlFreeDoc(response);
165165
return false;
166166
} else if (strcmp((char*)attr->children->content, SOAP_1_1_ENC_NAMESPACE) != 0) {
167-
add_soap_fault(this_ptr, "Client", "Unknown data encoding style", NULL, NULL);
167+
add_soap_fault(this_ptr, "Client", "Unknown data encoding style", NULL, NULL, SOAP_GLOBAL(lang_en));
168168
xmlFreeDoc(response);
169169
return false;
170170
}
@@ -177,6 +177,7 @@ bool parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctio
177177
fault = get_node_ex(body->children,"Fault",envelope_ns);
178178
if (fault != NULL) {
179179
char *faultcode = NULL;
180+
zend_string *lang = ZSTR_EMPTY_ALLOC();
180181
zend_string *faultstring = NULL, *faultactor = NULL;
181182
zval details;
182183
xmlNodePtr tmp;
@@ -219,13 +220,19 @@ bool parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctio
219220

220221
tmp = get_node(fault->children,"Reason");
221222
if (tmp != NULL && tmp->children != NULL) {
222-
/* TODO: lang attribute */
223223
tmp = get_node(tmp->children,"Text");
224224
if (tmp != NULL && tmp->children != NULL) {
225225
zval zv;
226226
master_to_zval(&zv, get_conversion(IS_STRING), tmp);
227227
convert_to_string(&zv)
228228
faultstring = Z_STR(zv);
229+
230+
/* xml:lang is required by SOAP 1.2, but for BC reasons we allow it to be missing */
231+
xmlAttrPtr lang_attr = get_attribute_ex(tmp->properties, "lang", (const char *) XML_XML_NAMESPACE);
232+
if (lang_attr != NULL && lang_attr->children != NULL) {
233+
const char *lang_str = (const char *) lang_attr->children->content;
234+
lang = zend_string_init(lang_str, strlen(lang_str), false);
235+
}
229236
}
230237
}
231238

@@ -234,13 +241,14 @@ bool parse_packet_soap(zval *this_ptr, char *buffer, int buffer_size, sdlFunctio
234241
master_to_zval(&details, NULL, tmp);
235242
}
236243
}
237-
add_soap_fault(this_ptr, faultcode, faultstring ? ZSTR_VAL(faultstring) : NULL, faultactor ? ZSTR_VAL(faultactor) : NULL, &details);
244+
add_soap_fault(this_ptr, faultcode, faultstring ? ZSTR_VAL(faultstring) : NULL, faultactor ? ZSTR_VAL(faultactor) : NULL, &details, lang);
238245
if (faultstring) {
239246
zend_string_release_ex(faultstring, 0);
240247
}
241248
if (faultactor) {
242249
zend_string_release_ex(faultactor, 0);
243250
}
251+
zend_string_release_ex(lang, false);
244252
if (Z_REFCOUNTED(details)) {
245253
Z_DELREF(details);
246254
}

ext/soap/php_soap.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ ZEND_BEGIN_MODULE_GLOBALS(soap)
170170
HashTable wsdl_cache;
171171
int cur_uniq_ref;
172172
HashTable *ref_map;
173+
zend_string *lang_en;
173174
ZEND_END_MODULE_GLOBALS(soap)
174175

175176
#ifdef ZTS
@@ -194,7 +195,7 @@ extern zend_class_entry* soap_sdl_class_entry;
194195

195196
extern HashTable php_soap_defEncNs, php_soap_defEnc, php_soap_defEncIndex;
196197

197-
void add_soap_fault(zval *obj, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail);
198+
void add_soap_fault(zval *obj, char *fault_code, char *fault_string, char *fault_actor, zval *fault_detail, zend_string *lang);
198199

199200
#define soap_error0(severity, format) \
200201
php_error(severity, "SOAP-ERROR: " format)

0 commit comments

Comments
 (0)