1 /*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Authors: Brad Lafountain <rodif_bl@yahoo.com> |
14 | Shane Caraveo <shane@caraveo.com> |
15 | Dmitry Stogov <dmitry@php.net> |
16 +----------------------------------------------------------------------+
17 */
18
19 #include "php_soap.h"
20 #include "ext/libxml/php_libxml.h"
21 #include "libxml/uri.h"
22
23 #include "zend_virtual_cwd.h"
24 #include "main/php_open_temporary_file.h"
25
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29
30 #ifndef O_BINARY
31 # define O_BINARY 0
32 #endif
33
34 static void delete_fault(zval *zv);
35 static void delete_fault_persistent(zval *zv);
36 static void delete_binding(zval *zv);
37 static void delete_binding_persistent(zval *zv);
38 static void delete_function(zval *zv);
39 static void delete_function_persistent(zval *zv);
40 static void delete_parameter(zval *zv);
41 static void delete_parameter_persistent(zval *zv);
42 static void delete_header(zval *header);
43 static void delete_header_int(sdlSoapBindingFunctionHeaderPtr hdr);
44 static void delete_header_persistent(zval *zv);
45 static void delete_document(zval *zv);
46
get_encoder_from_prefix(sdlPtr sdl,xmlNodePtr node,const xmlChar * type)47 encodePtr get_encoder_from_prefix(sdlPtr sdl, xmlNodePtr node, const xmlChar *type)
48 {
49 encodePtr enc = NULL;
50 xmlNsPtr nsptr;
51 const char *cptype;
52 char *ns;
53
54 parse_namespace(type, &cptype, &ns);
55 nsptr = xmlSearchNs(node->doc, node, BAD_CAST(ns));
56 if (nsptr != NULL) {
57 enc = get_encoder(sdl, (char*)nsptr->href, cptype);
58 if (enc == NULL) {
59 enc = get_encoder_ex(sdl, cptype, strlen(cptype));
60 }
61 } else {
62 enc = get_encoder_ex(sdl, (char*)type, xmlStrlen(type));
63 }
64 if (ns) {efree(ns);}
65 return enc;
66 }
67
get_element(sdlPtr sdl,xmlNodePtr node,const xmlChar * type)68 static sdlTypePtr get_element(sdlPtr sdl, xmlNodePtr node, const xmlChar *type)
69 {
70 sdlTypePtr ret = NULL;
71
72 if (sdl->elements) {
73 xmlNsPtr nsptr;
74 const char *cptype;
75 char *ns;
76 sdlTypePtr sdl_type;
77
78 parse_namespace(type, &cptype, &ns);
79 nsptr = xmlSearchNs(node->doc, node, BAD_CAST(ns));
80 if (nsptr != NULL) {
81 size_t ns_len = xmlStrlen(nsptr->href);
82 size_t type_len = strlen(cptype);
83 size_t len = ns_len + type_len + 1;
84 char *nscat = emalloc(len + 1);
85
86 memcpy(nscat, nsptr->href, ns_len);
87 nscat[ns_len] = ':';
88 memcpy(nscat+ns_len+1, cptype, type_len);
89 nscat[len] = '\0';
90
91 if ((sdl_type = zend_hash_str_find_ptr(sdl->elements, nscat, len)) != NULL) {
92 ret = sdl_type;
93 } else if ((sdl_type = zend_hash_str_find_ptr(sdl->elements, (char*)type, type_len)) != NULL) {
94 ret = sdl_type;
95 }
96 efree(nscat);
97 } else {
98 if ((sdl_type = zend_hash_str_find_ptr(sdl->elements, (char*)type, xmlStrlen(type))) != NULL) {
99 ret = sdl_type;
100 }
101 }
102
103 if (ns) {efree(ns);}
104 }
105 return ret;
106 }
107
get_encoder(sdlPtr sdl,const char * ns,const char * type)108 encodePtr get_encoder(sdlPtr sdl, const char *ns, const char *type)
109 {
110 encodePtr enc = NULL;
111 char *nscat;
112 size_t ns_len = ns ? strlen(ns) : 0;
113 size_t type_len = strlen(type);
114 size_t len = ns_len + type_len + 1;
115
116 nscat = emalloc(len + 1);
117 if (ns) {
118 memcpy(nscat, ns, ns_len);
119 }
120 nscat[ns_len] = ':';
121 memcpy(nscat+ns_len+1, type, type_len);
122 nscat[len] = '\0';
123
124 enc = get_encoder_ex(sdl, nscat, len);
125
126 if (enc == NULL &&
127 ((ns_len == sizeof(SOAP_1_1_ENC_NAMESPACE)-1 &&
128 memcmp(ns, SOAP_1_1_ENC_NAMESPACE, sizeof(SOAP_1_1_ENC_NAMESPACE)-1) == 0) ||
129 (ns_len == sizeof(SOAP_1_2_ENC_NAMESPACE)-1 &&
130 memcmp(ns, SOAP_1_2_ENC_NAMESPACE, sizeof(SOAP_1_2_ENC_NAMESPACE)-1) == 0))) {
131 char *enc_nscat;
132 size_t enc_ns_len;
133 size_t enc_len;
134
135 enc_ns_len = sizeof(XSD_NAMESPACE)-1;
136 enc_len = enc_ns_len + type_len + 1;
137 enc_nscat = emalloc(enc_len + 1);
138 memcpy(enc_nscat, XSD_NAMESPACE, sizeof(XSD_NAMESPACE)-1);
139 enc_nscat[enc_ns_len] = ':';
140 memcpy(enc_nscat+enc_ns_len+1, type, type_len);
141 enc_nscat[enc_len] = '\0';
142
143 enc = get_encoder_ex(NULL, enc_nscat, enc_len);
144 efree(enc_nscat);
145 if (enc && sdl) {
146 encodePtr new_enc = pemalloc(sizeof(encode), sdl->is_persistent);
147 memcpy(new_enc, enc, sizeof(encode));
148 if (sdl->is_persistent) {
149 new_enc->details.ns = zend_strndup(ns, ns_len);
150 new_enc->details.type_str = strdup(new_enc->details.type_str);
151 } else {
152 new_enc->details.ns = estrndup(ns, ns_len);
153 new_enc->details.type_str = estrdup(new_enc->details.type_str);
154 }
155 if (new_enc->details.clark_notation) {
156 /* If it was persistent or becomes persistent, we must dup. Otherwise we can copy. */
157 bool was_persistent = GC_FLAGS(new_enc->details.clark_notation) & IS_STR_PERSISTENT;
158 if (was_persistent || sdl->is_persistent) {
159 new_enc->details.clark_notation = zend_string_dup(new_enc->details.clark_notation, sdl->is_persistent);
160 } else {
161 zend_string_addref(new_enc->details.clark_notation);
162 }
163 }
164 if (sdl->encoders == NULL) {
165 sdl->encoders = pemalloc(sizeof(HashTable), sdl->is_persistent);
166 zend_hash_init(sdl->encoders, 0, NULL, sdl->is_persistent ? delete_encoder_persistent : delete_encoder, sdl->is_persistent);
167 }
168 zend_hash_str_update_ptr(sdl->encoders, nscat, len, new_enc);
169 enc = new_enc;
170 }
171 }
172 efree(nscat);
173 return enc;
174 }
175
get_encoder_ex(sdlPtr sdl,const char * nscat,size_t len)176 encodePtr get_encoder_ex(sdlPtr sdl, const char *nscat, size_t len)
177 {
178 encodePtr enc;
179
180 if ((enc = zend_hash_str_find_ptr(&SOAP_GLOBAL(defEnc), nscat, len)) != NULL) {
181 return enc;
182 } else if (sdl && sdl->encoders && (enc = zend_hash_str_find_ptr(sdl->encoders, nscat, len)) != NULL) {
183 return enc;
184 }
185 return NULL;
186 }
187
is_wsdl_element(xmlNodePtr node)188 static int is_wsdl_element(xmlNodePtr node)
189 {
190 if (node->ns && strcmp((char*)node->ns->href, WSDL_NAMESPACE) != 0) {
191 xmlAttrPtr attr;
192 if ((attr = get_attribute_ex(node->properties, "required", WSDL_NAMESPACE)) != NULL &&
193 attr->children && attr->children->content &&
194 (strcmp((char*)attr->children->content, "1") == 0 ||
195 strcmp((char*)attr->children->content, "true") == 0)) {
196 soap_error1(E_ERROR, "Parsing WSDL: Unknown required WSDL extension '%s'", node->ns->href);
197 }
198 return 0;
199 }
200 return 1;
201 }
202
sdl_set_uri_credentials(sdlCtx * ctx,char * uri)203 void sdl_set_uri_credentials(sdlCtx *ctx, char *uri)
204 {
205 char *s;
206 size_t l1, l2;
207 zval context;
208 zval *header = NULL;
209
210 /* check if we load xsd from the same server */
211 s = strstr(ctx->sdl->source, "://");
212 if (!s) return;
213 s = strchr(s+3, '/');
214 l1 = s ? (size_t)(s - ctx->sdl->source) : strlen(ctx->sdl->source);
215 s = strstr((char*)uri, "://");
216 if (!s) return;
217 s = strchr(s+3, '/');
218 l2 = s ? (size_t)(s - (char*)uri) : strlen((char*)uri);
219 if (l1 != l2) {
220 /* check for http://...:80/ */
221 if (l1 > 11 &&
222 ctx->sdl->source[4] == ':' &&
223 ctx->sdl->source[l1-3] == ':' &&
224 ctx->sdl->source[l1-2] == '8' &&
225 ctx->sdl->source[l1-1] == '0') {
226 l1 -= 3;
227 }
228 if (l2 > 11 &&
229 uri[4] == ':' &&
230 uri[l2-3] == ':' &&
231 uri[l2-2] == '8' &&
232 uri[l2-1] == '0') {
233 l2 -= 3;
234 }
235 /* check for https://...:443/ */
236 if (l1 > 13 &&
237 ctx->sdl->source[4] == 's' &&
238 ctx->sdl->source[l1-4] == ':' &&
239 ctx->sdl->source[l1-3] == '4' &&
240 ctx->sdl->source[l1-2] == '4' &&
241 ctx->sdl->source[l1-1] == '3') {
242 l1 -= 4;
243 }
244 if (l2 > 13 &&
245 uri[4] == 's' &&
246 uri[l2-4] == ':' &&
247 uri[l2-3] == '4' &&
248 uri[l2-2] == '4' &&
249 uri[l2-1] == '3') {
250 l2 -= 4;
251 }
252 }
253 if (l1 != l2 || memcmp(ctx->sdl->source, uri, l1) != 0) {
254 /* another server. clear authentication credentals */
255 php_libxml_switch_context(NULL, &context);
256 php_libxml_switch_context(&context, NULL);
257 if (Z_TYPE(context) != IS_UNDEF) {
258 zval *context_ptr = &context;
259 ctx->context = php_stream_context_from_zval(context_ptr, 1);
260
261 if (ctx->context &&
262 (header = php_stream_context_get_option(ctx->context, "http", "header")) != NULL &&
263 Z_TYPE_P(header) == IS_STRING) {
264 /* TODO: should support header as an array, but this code path is untested */
265 s = strstr(Z_STRVAL_P(header), "Authorization: Basic");
266 if (s && (s == Z_STRVAL_P(header) || *(s-1) == '\n' || *(s-1) == '\r')) {
267 char *rest = strstr(s, "\r\n");
268 if (rest) {
269 zval new_header;
270
271 rest += 2;
272 ZVAL_NEW_STR(&new_header, zend_string_alloc(Z_STRLEN_P(header) - (rest - s), 0));
273 memcpy(Z_STRVAL(new_header), Z_STRVAL_P(header), s - Z_STRVAL_P(header));
274 memcpy(Z_STRVAL(new_header) + (s - Z_STRVAL_P(header)), rest, Z_STRLEN_P(header) - (rest - Z_STRVAL_P(header)) + 1);
275 ZVAL_COPY(&ctx->old_header, header);
276 php_stream_context_set_option(ctx->context, "http", "header", &new_header);
277 zval_ptr_dtor(&new_header);
278 }
279 }
280 }
281 }
282 }
283 }
284
sdl_restore_uri_credentials(sdlCtx * ctx)285 void sdl_restore_uri_credentials(sdlCtx *ctx)
286 {
287 if (Z_TYPE(ctx->old_header) != IS_UNDEF) {
288 php_stream_context_set_option(ctx->context, "http", "header", &ctx->old_header);
289 zval_ptr_dtor(&ctx->old_header);
290 ZVAL_UNDEF(&ctx->old_header);
291 }
292 ctx->context = NULL;
293 }
294
295 #define SAFE_STR(a) ((a)?((const char *)a):"")
296
load_wsdl_ex(zval * this_ptr,char * struri,sdlCtx * ctx,bool include)297 static void load_wsdl_ex(zval *this_ptr, char *struri, sdlCtx *ctx, bool include)
298 {
299 sdlPtr tmpsdl = ctx->sdl;
300 xmlDocPtr wsdl;
301 xmlNodePtr root, definitions, trav;
302
303 if (zend_hash_str_exists(&ctx->docs, struri, strlen(struri))) {
304 return;
305 }
306
307 sdl_set_uri_credentials(ctx, struri);
308 wsdl = soap_xmlParseFile(struri);
309 sdl_restore_uri_credentials(ctx);
310
311 if (!wsdl) {
312 const xmlError *xmlErrorPtr = xmlGetLastError();
313
314 if (xmlErrorPtr) {
315 soap_error2(E_ERROR, "Parsing WSDL: Couldn't load from '%s' : %s", struri, xmlErrorPtr->message);
316 } else {
317 soap_error1(E_ERROR, "Parsing WSDL: Couldn't load from '%s'", struri);
318 }
319 }
320
321 zend_hash_str_add_ptr(&ctx->docs, struri, strlen(struri), wsdl);
322
323 root = wsdl->children;
324 definitions = get_node_ex(root, "definitions", WSDL_NAMESPACE);
325 if (!definitions) {
326 if (include) {
327 xmlNodePtr schema = get_node_ex(root, "schema", XSD_NAMESPACE);
328 if (schema) {
329 load_schema(ctx, schema);
330 return;
331 }
332 }
333 soap_error1(E_ERROR, "Parsing WSDL: Couldn't find <definitions> in '%s'", struri);
334 }
335
336 if (!include) {
337 xmlAttrPtr targetNamespace = get_attribute(definitions->properties, "targetNamespace");
338 if (targetNamespace) {
339 tmpsdl->target_ns = estrdup((char*)targetNamespace->children->content);
340 }
341 }
342
343 trav = definitions->children;
344 while (trav != NULL) {
345 if (!is_wsdl_element(trav)) {
346 trav = trav->next;
347 continue;
348 }
349 if (node_is_equal(trav,"types")) {
350 /* TODO: Only one "types" is allowed */
351 xmlNodePtr trav2 = trav->children;
352
353 while (trav2 != NULL) {
354 if (node_is_equal_ex(trav2, "schema", XSD_NAMESPACE)) {
355 load_schema(ctx, trav2);
356 } else if (is_wsdl_element(trav2) && !node_is_equal(trav2,"documentation")) {
357 soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", SAFE_STR(trav2->name));
358 }
359 trav2 = trav2->next;
360 }
361 } else if (node_is_equal(trav,"import")) {
362 /* TODO: namespace ??? */
363 xmlAttrPtr tmp = get_attribute(trav->properties, "location");
364 if (tmp) {
365 xmlChar *uri = schema_location_construct_uri(tmp);
366 load_wsdl_ex(this_ptr, (char*)uri, ctx, true);
367 xmlFree(uri);
368 }
369
370 } else if (node_is_equal(trav,"message")) {
371 xmlAttrPtr name = get_attribute(trav->properties, "name");
372 if (name && name->children && name->children->content) {
373 if (zend_hash_str_add_ptr(&ctx->messages, (char*)name->children->content, xmlStrlen(name->children->content), trav) == NULL) {
374 soap_error1(E_ERROR, "Parsing WSDL: <message> '%s' already defined", name->children->content);
375 }
376 } else {
377 soap_error0(E_ERROR, "Parsing WSDL: <message> has no name attribute");
378 }
379
380 } else if (node_is_equal(trav,"portType")) {
381 xmlAttrPtr name = get_attribute(trav->properties, "name");
382 if (name && name->children && name->children->content) {
383 if (zend_hash_str_add_ptr(&ctx->portTypes, (char*)name->children->content, xmlStrlen(name->children->content), trav) == NULL) {
384 soap_error1(E_ERROR, "Parsing WSDL: <portType> '%s' already defined", name->children->content);
385 }
386 } else {
387 soap_error0(E_ERROR, "Parsing WSDL: <portType> has no name attribute");
388 }
389
390 } else if (node_is_equal(trav,"binding")) {
391 xmlAttrPtr name = get_attribute(trav->properties, "name");
392 if (name && name->children && name->children->content) {
393 if (zend_hash_str_add_ptr(&ctx->bindings, (char*)name->children->content, xmlStrlen(name->children->content), trav) == NULL) {
394 soap_error1(E_ERROR, "Parsing WSDL: <binding> '%s' already defined", name->children->content);
395 }
396 } else {
397 soap_error0(E_ERROR, "Parsing WSDL: <binding> has no name attribute");
398 }
399
400 } else if (node_is_equal(trav,"service")) {
401 xmlAttrPtr name = get_attribute(trav->properties, "name");
402 if (name && name->children && name->children->content) {
403 if (zend_hash_str_add_ptr(&ctx->services, (char*)name->children->content, xmlStrlen(name->children->content), trav) == NULL) {
404 soap_error1(E_ERROR, "Parsing WSDL: <service> '%s' already defined", name->children->content);
405 }
406 } else {
407 soap_error0(E_ERROR, "Parsing WSDL: <service> has no name attribute");
408 }
409 } else if (!node_is_equal(trav,"documentation")) {
410 soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", SAFE_STR(trav->name));
411 }
412 trav = trav->next;
413 }
414 }
415
wsdl_soap_binding_header(sdlCtx * ctx,xmlNodePtr header,char * wsdl_soap_namespace,int fault)416 static sdlSoapBindingFunctionHeaderPtr wsdl_soap_binding_header(sdlCtx* ctx, xmlNodePtr header, char* wsdl_soap_namespace, int fault)
417 {
418 xmlAttrPtr tmp;
419 xmlNodePtr message, part;
420 char *ctype;
421 sdlSoapBindingFunctionHeaderPtr h;
422
423 tmp = get_attribute(header->properties, "message");
424 if (!tmp) {
425 soap_error0(E_ERROR, "Parsing WSDL: Missing message attribute for <header>");
426 }
427
428 ctype = strrchr((char*)tmp->children->content,':');
429 if (ctype == NULL) {
430 ctype = (char*)tmp->children->content;
431 } else {
432 ++ctype;
433 }
434 if ((message = zend_hash_str_find_ptr(&ctx->messages, ctype, strlen(ctype))) == NULL) {
435 soap_error1(E_ERROR, "Parsing WSDL: Missing <message> with name '%s'", tmp->children->content);
436 }
437
438 tmp = get_attribute(header->properties, "part");
439 if (!tmp) {
440 soap_error0(E_ERROR, "Parsing WSDL: Missing part attribute for <header>");
441 }
442 part = get_node_with_attribute_ex(message->children, "part", WSDL_NAMESPACE, "name", (char*)tmp->children->content, NULL);
443 if (!part) {
444 soap_error1(E_ERROR, "Parsing WSDL: Missing part '%s' in <message>", tmp->children->content);
445 }
446
447 h = emalloc(sizeof(sdlSoapBindingFunctionHeader));
448 memset(h, 0, sizeof(sdlSoapBindingFunctionHeader));
449 h->name = estrdup((char*)tmp->children->content);
450
451 tmp = get_attribute(header->properties, "use");
452 if (tmp && !strncmp((char*)tmp->children->content, "encoded", sizeof("encoded"))) {
453 h->use = SOAP_ENCODED;
454 } else {
455 h->use = SOAP_LITERAL;
456 }
457
458 tmp = get_attribute(header->properties, "namespace");
459 if (tmp) {
460 h->ns = estrdup((char*)tmp->children->content);
461 }
462
463 if (h->use == SOAP_ENCODED) {
464 tmp = get_attribute(header->properties, "encodingStyle");
465 if (tmp) {
466 if (strncmp((char*)tmp->children->content, SOAP_1_1_ENC_NAMESPACE, sizeof(SOAP_1_1_ENC_NAMESPACE)) == 0) {
467 h->encodingStyle = SOAP_ENCODING_1_1;
468 } else if (strncmp((char*)tmp->children->content, SOAP_1_2_ENC_NAMESPACE, sizeof(SOAP_1_2_ENC_NAMESPACE)) == 0) {
469 h->encodingStyle = SOAP_ENCODING_1_2;
470 } else {
471 soap_error1(E_ERROR, "Parsing WSDL: Unknown encodingStyle '%s'", tmp->children->content);
472 }
473 } else {
474 soap_error0(E_ERROR, "Parsing WSDL: Unspecified encodingStyle");
475 }
476 }
477
478 tmp = get_attribute(part->properties, "type");
479 if (tmp != NULL) {
480 h->encode = get_encoder_from_prefix(ctx->sdl, part, tmp->children->content);
481 } else {
482 tmp = get_attribute(part->properties, "element");
483 if (tmp != NULL) {
484 h->element = get_element(ctx->sdl, part, tmp->children->content);
485 if (h->element) {
486 h->encode = h->element->encode;
487 if (!h->ns && h->element->namens) {
488 h->ns = estrdup(h->element->namens);
489 }
490 if (h->element->name) {
491 efree(h->name);
492 h->name = estrdup(h->element->name);
493 }
494 }
495 }
496 }
497 if (!fault) {
498 xmlNodePtr trav = header->children;
499 while (trav != NULL) {
500 if (node_is_equal_ex(trav, "headerfault", wsdl_soap_namespace)) {
501 sdlSoapBindingFunctionHeaderPtr hf = wsdl_soap_binding_header(ctx, trav, wsdl_soap_namespace, 1);
502 smart_str key = {0};
503
504 if (h->headerfaults == NULL) {
505 h->headerfaults = emalloc(sizeof(HashTable));
506 zend_hash_init(h->headerfaults, 0, NULL, delete_header, 0);
507 }
508
509 if (hf->ns) {
510 smart_str_appends(&key,hf->ns);
511 smart_str_appendc(&key,':');
512 }
513 smart_str_appends(&key,hf->name);
514 smart_str_0(&key);
515 if (zend_hash_add_ptr(h->headerfaults, key.s, hf) == NULL) {
516 delete_header_int(hf);
517 }
518 smart_str_free(&key);
519 } else if (is_wsdl_element(trav) && !node_is_equal(trav,"documentation")) {
520 soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", SAFE_STR(trav->name));
521 }
522 trav = trav->next;
523 }
524 }
525 return h;
526 }
527
wsdl_soap_binding_body(sdlCtx * ctx,xmlNodePtr node,char * wsdl_soap_namespace,sdlSoapBindingFunctionBody * binding,HashTable * params)528 static void wsdl_soap_binding_body(sdlCtx* ctx, xmlNodePtr node, char* wsdl_soap_namespace, sdlSoapBindingFunctionBody *binding, HashTable* params)
529 {
530 xmlNodePtr trav;
531
532 trav = node->children;
533 while (trav != NULL) {
534 if (node_is_equal_ex(trav, "body", wsdl_soap_namespace)) {
535 xmlNodePtr body = trav;
536
537 xmlAttrPtr useAttribute = get_attribute(body->properties, "use");
538 if (useAttribute && !strncmp((char*)useAttribute->children->content, "literal", sizeof("literal"))) {
539 binding->use = SOAP_LITERAL;
540 } else {
541 binding->use = SOAP_ENCODED;
542 }
543
544 xmlAttrPtr namespaceAttribute = get_attribute(body->properties, "namespace");
545 if (namespaceAttribute) {
546 binding->ns = estrdup((char*)namespaceAttribute->children->content);
547 }
548
549 xmlAttrPtr partsAttribute = get_attribute(body->properties, "parts");
550 if (partsAttribute) {
551 HashTable ht;
552 char *parts = (char*)partsAttribute->children->content;
553
554 /* Delete all parts those are not in the "parts" attribute */
555 zend_hash_init(&ht, 0, NULL, delete_parameter, 0);
556 while (*parts) {
557 sdlParamPtr param;
558 bool found = false;
559 char *end;
560
561 while (*parts == ' ') ++parts;
562 if (*parts == '\0') break;
563 end = strchr(parts, ' ');
564 if (end) *end = '\0';
565 ZEND_HASH_FOREACH_PTR(params, param) {
566 if (param->paramName && strcmp(parts, param->paramName) == 0) {
567 sdlParamPtr x_param;
568 x_param = emalloc(sizeof(sdlParam));
569 *x_param = *param;
570 param->paramName = NULL;
571 zend_hash_next_index_insert_ptr(&ht, x_param);
572 found = true;
573 break;
574 }
575 } ZEND_HASH_FOREACH_END();
576 if (!found) {
577 soap_error1(E_ERROR, "Parsing WSDL: Missing part '%s' in <message>", parts);
578 }
579 parts += strlen(parts);
580 if (end) *end = ' ';
581 }
582 zend_hash_destroy(params);
583 *params = ht;
584 }
585
586 if (binding->use == SOAP_ENCODED) {
587 xmlAttrPtr encodingStyleAttribute = get_attribute(body->properties, "encodingStyle");
588 if (encodingStyleAttribute) {
589 if (strncmp((char*)encodingStyleAttribute->children->content, SOAP_1_1_ENC_NAMESPACE, sizeof(SOAP_1_1_ENC_NAMESPACE)) == 0) {
590 binding->encodingStyle = SOAP_ENCODING_1_1;
591 } else if (strncmp((char*)encodingStyleAttribute->children->content, SOAP_1_2_ENC_NAMESPACE, sizeof(SOAP_1_2_ENC_NAMESPACE)) == 0) {
592 binding->encodingStyle = SOAP_ENCODING_1_2;
593 } else {
594 soap_error1(E_ERROR, "Parsing WSDL: Unknown encodingStyle '%s'", encodingStyleAttribute->children->content);
595 }
596 } else {
597 soap_error0(E_ERROR, "Parsing WSDL: Unspecified encodingStyle");
598 }
599 }
600 } else if (node_is_equal_ex(trav, "header", wsdl_soap_namespace)) {
601 sdlSoapBindingFunctionHeaderPtr h = wsdl_soap_binding_header(ctx, trav, wsdl_soap_namespace, 0);
602 smart_str key = {0};
603
604 if (binding->headers == NULL) {
605 binding->headers = emalloc(sizeof(HashTable));
606 zend_hash_init(binding->headers, 0, NULL, delete_header, 0);
607 }
608
609 if (h->ns) {
610 smart_str_appends(&key,h->ns);
611 smart_str_appendc(&key,':');
612 }
613 smart_str_appends(&key,h->name);
614 smart_str_0(&key);
615 if (zend_hash_add_ptr(binding->headers, key.s, h) == NULL) {
616 delete_header_int(h);
617 }
618 smart_str_free(&key);
619 } else if (is_wsdl_element(trav) && !node_is_equal(trav,"documentation")) {
620 soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", SAFE_STR(trav->name));
621 }
622 trav = trav->next;
623 }
624 }
625
wsdl_message(const sdlCtx * ctx,const xmlChar * message_name)626 static HashTable* wsdl_message(const sdlCtx *ctx, const xmlChar* message_name)
627 {
628 HashTable* parameters = NULL;
629
630 const char *ctype = strrchr((const char*)message_name,':');
631 if (ctype == NULL) {
632 ctype = (const char*)message_name;
633 } else {
634 ++ctype;
635 }
636
637 xmlNodePtr message = zend_hash_str_find_ptr(&ctx->messages, ctype, strlen(ctype));
638 if (message == NULL) {
639 soap_error1(E_ERROR, "Parsing WSDL: Missing <message> with name '%s'", (const char*)message_name);
640 }
641
642 parameters = emalloc(sizeof(HashTable));
643 zend_hash_init(parameters, 0, NULL, delete_parameter, 0);
644
645 xmlNodePtr trav = message->children;
646 while (trav != NULL) {
647 xmlAttrPtr type, name;
648 sdlParamPtr param;
649
650 if (trav->ns != NULL && strcmp((char*)trav->ns->href, WSDL_NAMESPACE) != 0) {
651 soap_error1(E_ERROR, "Parsing WSDL: Unexpected extensibility element <%s>", SAFE_STR(trav->name));
652 }
653 if (node_is_equal(trav,"documentation")) {
654 trav = trav->next;
655 continue;
656 }
657 if (!node_is_equal(trav,"part")) {
658 soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", SAFE_STR(trav->name));
659 }
660 xmlNodePtr part = trav;
661 param = emalloc(sizeof(sdlParam));
662 memset(param,0,sizeof(sdlParam));
663 param->order = 0;
664
665 name = get_attribute(part->properties, "name");
666 if (name == NULL) {
667 soap_error1(E_ERROR, "Parsing WSDL: No name associated with <part> '%s'", SAFE_STR(message->name));
668 }
669
670 param->paramName = estrdup((char*)name->children->content);
671
672 type = get_attribute(part->properties, "type");
673 if (type != NULL) {
674 param->encode = get_encoder_from_prefix(ctx->sdl, part, type->children->content);
675 } else {
676 xmlAttrPtr element = get_attribute(part->properties, "element");
677 if (element != NULL) {
678 param->element = get_element(ctx->sdl, part, element->children->content);
679 if (param->element) {
680 param->encode = param->element->encode;
681 }
682 }
683 }
684
685 zend_hash_next_index_insert_ptr(parameters, param);
686
687 trav = trav->next;
688 }
689 return parameters;
690 }
691
load_wsdl(zval * this_ptr,char * struri)692 static sdlPtr load_wsdl(zval *this_ptr, char *struri)
693 {
694 sdlCtx ctx = {0};
695
696 ctx.sdl = emalloc(sizeof(sdl));
697 memset(ctx.sdl, 0, sizeof(sdl));
698 ctx.sdl->source = estrdup(struri);
699 zend_hash_init(&ctx.sdl->functions, 0, NULL, delete_function, 0);
700
701 zend_hash_init(&ctx.docs, 0, NULL, delete_document, 0);
702 zend_hash_init(&ctx.messages, 0, NULL, NULL, 0);
703 zend_hash_init(&ctx.bindings, 0, NULL, NULL, 0);
704 zend_hash_init(&ctx.portTypes, 0, NULL, NULL, 0);
705 zend_hash_init(&ctx.services, 0, NULL, NULL, 0);
706
707 zend_try {
708 load_wsdl_ex(this_ptr, struri, &ctx, false);
709 schema_pass2(&ctx);
710
711 uint32_t n = zend_hash_num_elements(&ctx.services);
712 if (n == 0) {
713 soap_error0(E_ERROR, "Parsing WSDL: Couldn't bind to service");
714 }
715
716 zend_hash_internal_pointer_reset(&ctx.services);
717 for (uint32_t i = 0; i < n; i++) {
718 xmlNodePtr service, tmp;
719 xmlNodePtr trav, port;
720 bool has_soap_port = false;
721
722 service = tmp = zend_hash_get_current_data_ptr(&ctx.services);
723
724 trav = service->children;
725 while (trav != NULL) {
726 xmlAttrPtr type, name, bindingAttr, location;
727 xmlNodePtr portType, operation;
728 xmlNodePtr address, binding, trav2;
729 char *ctype;
730 sdlBindingPtr tmpbinding;
731 char *wsdl_soap_namespace = NULL;
732
733 if (!is_wsdl_element(trav) || node_is_equal(trav,"documentation")) {
734 trav = trav->next;
735 continue;
736 }
737 if (!node_is_equal(trav,"port")) {
738 soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", SAFE_STR(trav->name));
739 }
740
741 port = trav;
742
743 tmpbinding = emalloc(sizeof(sdlBinding));
744 memset(tmpbinding, 0, sizeof(sdlBinding));
745
746 bindingAttr = get_attribute(port->properties, "binding");
747 if (bindingAttr == NULL) {
748 soap_error0(E_ERROR, "Parsing WSDL: No binding associated with <port>");
749 }
750
751 /* find address and figure out binding type */
752 address = NULL;
753 trav2 = port->children;
754 while (trav2 != NULL) {
755 if (node_is_equal(trav2,"address") && trav2->ns) {
756 if (!strncmp((char*)trav2->ns->href, WSDL_SOAP11_NAMESPACE, sizeof(WSDL_SOAP11_NAMESPACE))) {
757 address = trav2;
758 wsdl_soap_namespace = WSDL_SOAP11_NAMESPACE;
759 tmpbinding->bindingType = BINDING_SOAP;
760 } else if (!strncmp((char*)trav2->ns->href, WSDL_SOAP12_NAMESPACE, sizeof(WSDL_SOAP12_NAMESPACE))) {
761 address = trav2;
762 wsdl_soap_namespace = WSDL_SOAP12_NAMESPACE;
763 tmpbinding->bindingType = BINDING_SOAP;
764 } else if (!strncmp((char*)trav2->ns->href, RPC_SOAP12_NAMESPACE, sizeof(RPC_SOAP12_NAMESPACE))) {
765 address = trav2;
766 wsdl_soap_namespace = RPC_SOAP12_NAMESPACE;
767 tmpbinding->bindingType = BINDING_SOAP;
768 } else if (!strncmp((char*)trav2->ns->href, WSDL_HTTP11_NAMESPACE, sizeof(WSDL_HTTP11_NAMESPACE))) {
769 address = trav2;
770 tmpbinding->bindingType = BINDING_HTTP;
771 } else if (!strncmp((char*)trav2->ns->href, WSDL_HTTP12_NAMESPACE, sizeof(WSDL_HTTP12_NAMESPACE))) {
772 address = trav2;
773 tmpbinding->bindingType = BINDING_HTTP;
774 }
775 }
776 if (trav2 != address && is_wsdl_element(trav2) && !node_is_equal(trav2,"documentation")) {
777 soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", SAFE_STR(trav2->name));
778 }
779 trav2 = trav2->next;
780 }
781 if (!address || tmpbinding->bindingType == BINDING_HTTP) {
782 if (has_soap_port || trav->next || i < n-1) {
783 efree(tmpbinding);
784 trav = trav->next;
785 continue;
786 } else if (!address) {
787 soap_error0(E_ERROR, "Parsing WSDL: No address associated with <port>");
788 }
789 }
790 has_soap_port = true;
791
792 location = get_attribute(address->properties, "location");
793 if (!location) {
794 soap_error0(E_ERROR, "Parsing WSDL: No location associated with <port>");
795 }
796
797 tmpbinding->location = estrdup((char*)location->children->content);
798
799 ctype = strrchr((char*)bindingAttr->children->content,':');
800 if (ctype == NULL) {
801 ctype = (char*)bindingAttr->children->content;
802 } else {
803 ++ctype;
804 }
805 if ((tmp = zend_hash_str_find_ptr(&ctx.bindings, ctype, strlen(ctype))) == NULL) {
806 soap_error1(E_ERROR, "Parsing WSDL: No <binding> element with name '%s'", ctype);
807 }
808 binding = tmp;
809
810 if (tmpbinding->bindingType == BINDING_SOAP) {
811 sdlSoapBindingPtr soapBinding;
812 xmlNodePtr soapBindingNode;
813
814 soapBinding = emalloc(sizeof(sdlSoapBinding));
815 memset(soapBinding, 0, sizeof(sdlSoapBinding));
816 soapBinding->style = SOAP_DOCUMENT;
817
818 soapBindingNode = get_node_ex(binding->children, "binding", wsdl_soap_namespace);
819 if (soapBindingNode) {
820 xmlAttrPtr styleAttribute = get_attribute(soapBindingNode->properties, "style");
821 if (styleAttribute && !strncmp((char*)styleAttribute->children->content, "rpc", sizeof("rpc"))) {
822 soapBinding->style = SOAP_RPC;
823 }
824
825 xmlAttrPtr transportAttribute = get_attribute(soapBindingNode->properties, "transport");
826 if (transportAttribute) {
827 if (strncmp((char*)transportAttribute->children->content, WSDL_HTTP_TRANSPORT, sizeof(WSDL_HTTP_TRANSPORT)) == 0) {
828 soapBinding->transport = SOAP_TRANSPORT_HTTP;
829 } else {
830 /* try the next binding */
831 efree(soapBinding);
832 efree(tmpbinding->location);
833 efree(tmpbinding);
834 trav = trav->next;
835 continue;
836 }
837 }
838 }
839 tmpbinding->bindingAttributes = (void *)soapBinding;
840 }
841
842 name = get_attribute(binding->properties, "name");
843 if (name == NULL) {
844 soap_error0(E_ERROR, "Parsing WSDL: Missing 'name' attribute for <binding>");
845 }
846 tmpbinding->name = estrdup((char*)name->children->content);
847
848 type = get_attribute(binding->properties, "type");
849 if (type == NULL) {
850 soap_error0(E_ERROR, "Parsing WSDL: Missing 'type' attribute for <binding>");
851 }
852
853 ctype = strchr((char*)type->children->content,':');
854 if (ctype == NULL) {
855 ctype = (char*)type->children->content;
856 } else {
857 ++ctype;
858 }
859 if ((tmp = zend_hash_str_find_ptr(&ctx.portTypes, ctype, strlen(ctype))) == NULL) {
860 soap_error1(E_ERROR, "Parsing WSDL: Missing <portType> with name '%s'", name->children->content);
861 }
862 portType = tmp;
863
864 trav2 = binding->children;
865 while (trav2 != NULL) {
866 sdlFunctionPtr function;
867 xmlNodePtr input, output, fault, portTypeOperation, trav3;
868 xmlAttrPtr op_name, paramOrder;
869
870 if ((tmpbinding->bindingType == BINDING_SOAP &&
871 node_is_equal_ex(trav2, "binding", wsdl_soap_namespace)) ||
872 !is_wsdl_element(trav2) ||
873 node_is_equal(trav2,"documentation")) {
874 trav2 = trav2->next;
875 continue;
876 }
877 if (!node_is_equal(trav2,"operation")) {
878 soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", SAFE_STR(trav2->name));
879 }
880
881 operation = trav2;
882
883 op_name = get_attribute(operation->properties, "name");
884 if (op_name == NULL) {
885 soap_error0(E_ERROR, "Parsing WSDL: Missing 'name' attribute for <operation>");
886 }
887
888 trav3 = operation->children;
889 while (trav3 != NULL) {
890 if (tmpbinding->bindingType == BINDING_SOAP &&
891 node_is_equal_ex(trav3, "operation", wsdl_soap_namespace)) {
892 } else if (is_wsdl_element(trav3) &&
893 !node_is_equal(trav3,"input") &&
894 !node_is_equal(trav3,"output") &&
895 !node_is_equal(trav3,"fault") &&
896 !node_is_equal(trav3,"documentation")) {
897 soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", SAFE_STR(trav3->name));
898 }
899 trav3 = trav3->next;
900 }
901
902 portTypeOperation = get_node_with_attribute_ex(portType->children, "operation", WSDL_NAMESPACE, "name", (char*)op_name->children->content, NULL);
903 if (portTypeOperation == NULL) {
904 soap_error1(E_ERROR, "Parsing WSDL: Missing <portType>/<operation> with name '%s'", op_name->children->content);
905 }
906
907 function = emalloc(sizeof(sdlFunction));
908 memset(function, 0, sizeof(sdlFunction));
909 function->functionName = estrdup((char*)op_name->children->content);
910
911 if (tmpbinding->bindingType == BINDING_SOAP) {
912 sdlSoapBindingFunctionPtr soapFunctionBinding;
913 sdlSoapBindingPtr soapBinding;
914 xmlNodePtr soapOperation;
915
916 soapFunctionBinding = emalloc(sizeof(sdlSoapBindingFunction));
917 memset(soapFunctionBinding, 0, sizeof(sdlSoapBindingFunction));
918 soapBinding = (sdlSoapBindingPtr)tmpbinding->bindingAttributes;
919 soapFunctionBinding->style = soapBinding->style;
920
921 soapOperation = get_node_ex(operation->children, "operation", wsdl_soap_namespace);
922 if (soapOperation) {
923 xmlAttrPtr soapActionAttribute = get_attribute(soapOperation->properties, "soapAction");
924 if (soapActionAttribute) {
925 soapFunctionBinding->soapAction = estrdup((char*)soapActionAttribute->children->content);
926 }
927
928 xmlAttrPtr styleAttribute = get_attribute(soapOperation->properties, "style");
929 if (styleAttribute) {
930 if (!strncmp((char*)styleAttribute->children->content, "rpc", sizeof("rpc"))) {
931 soapFunctionBinding->style = SOAP_RPC;
932 } else {
933 soapFunctionBinding->style = SOAP_DOCUMENT;
934 }
935 } else {
936 soapFunctionBinding->style = soapBinding->style;
937 }
938 }
939
940 function->bindingAttributes = (void *)soapFunctionBinding;
941 }
942
943 input = get_node_ex(portTypeOperation->children, "input", WSDL_NAMESPACE);
944 if (input != NULL) {
945 xmlAttrPtr message;
946
947 message = get_attribute(input->properties, "message");
948 if (message == NULL) {
949 soap_error1(E_ERROR, "Parsing WSDL: Missing name for <input> of '%s'", op_name->children->content);
950 }
951 function->requestParameters = wsdl_message(&ctx, message->children->content);
952
953 /* FIXME
954 xmlAttrPtr name = get_attribute(input->properties, "name");
955 if (name != NULL) {
956 function->requestName = estrdup(name->children->content);
957 } else {
958 */
959 {
960 function->requestName = estrdup(function->functionName);
961 }
962
963 if (tmpbinding->bindingType == BINDING_SOAP) {
964 input = get_node_ex(operation->children, "input", WSDL_NAMESPACE);
965 if (input != NULL) {
966 sdlSoapBindingFunctionPtr soapFunctionBinding = function->bindingAttributes;
967 wsdl_soap_binding_body(&ctx, input, wsdl_soap_namespace, &soapFunctionBinding->input, function->requestParameters);
968 }
969 }
970 }
971
972 output = get_node_ex(portTypeOperation->children, "output", WSDL_NAMESPACE);
973 if (output != NULL) {
974 xmlAttrPtr message;
975
976 message = get_attribute(output->properties, "message");
977 if (message == NULL) {
978 soap_error1(E_ERROR, "Parsing WSDL: Missing name for <output> of '%s'", op_name->children->content);
979 }
980 function->responseParameters = wsdl_message(&ctx, message->children->content);
981
982 /* FIXME
983 xmlAttrPtr name = get_attribute(output->properties, "name");
984 if (name != NULL) {
985 function->responseName = estrdup(name->children->content);
986 } else if (input == NULL) {
987 function->responseName = estrdup(function->functionName);
988 } else {
989 */
990 {
991 size_t len = strlen(function->functionName);
992 function->responseName = emalloc(len + sizeof("Response"));
993 memcpy(function->responseName, function->functionName, len);
994 memcpy(function->responseName+len, "Response", sizeof("Response"));
995 }
996
997 if (tmpbinding->bindingType == BINDING_SOAP) {
998 output = get_node_ex(operation->children, "output", WSDL_NAMESPACE);
999 if (output != NULL) {
1000 sdlSoapBindingFunctionPtr soapFunctionBinding = function->bindingAttributes;
1001 wsdl_soap_binding_body(&ctx, output, wsdl_soap_namespace, &soapFunctionBinding->output, function->responseParameters);
1002 }
1003 }
1004 }
1005
1006 paramOrder = get_attribute(portTypeOperation->properties, "parameterOrder");
1007 if (paramOrder) {
1008 /* FIXME: */
1009 }
1010
1011 fault = portTypeOperation->children;
1012 while (fault != NULL) {
1013 if (node_is_equal_ex(fault, "fault", WSDL_NAMESPACE)) {
1014 xmlAttrPtr message;
1015 sdlFaultPtr f;
1016
1017 xmlAttrPtr faultNameAttribute = get_attribute(fault->properties, "name");
1018 if (faultNameAttribute == NULL) {
1019 soap_error1(E_ERROR, "Parsing WSDL: Missing name for <fault> of '%s'", op_name->children->content);
1020 }
1021 message = get_attribute(fault->properties, "message");
1022 if (message == NULL) {
1023 soap_error1(E_ERROR, "Parsing WSDL: Missing name for <output> of '%s'", op_name->children->content);
1024 }
1025
1026 f = emalloc(sizeof(sdlFault));
1027 memset(f, 0, sizeof(sdlFault));
1028
1029 f->name = estrdup((char*)faultNameAttribute->children->content);
1030 f->details = wsdl_message(&ctx, message->children->content);
1031 if (f->details == NULL || zend_hash_num_elements(f->details) > 1) {
1032 soap_error1(E_ERROR, "Parsing WSDL: The fault message '%s' must have a single part", message->children->content);
1033 }
1034
1035 if (tmpbinding->bindingType == BINDING_SOAP) {
1036 xmlNodePtr soapFault = get_node_with_attribute_ex(operation->children, "fault", WSDL_NAMESPACE, "name", f->name, NULL);
1037 if (soapFault != NULL) {
1038 xmlNodePtr faultNodes = soapFault->children;
1039 while (faultNodes != NULL) {
1040 if (node_is_equal_ex(faultNodes, "fault", wsdl_soap_namespace)) {
1041 sdlSoapBindingFunctionFaultPtr faultBinding;
1042
1043 faultBinding = f->bindingAttributes = emalloc(sizeof(sdlSoapBindingFunctionFault));
1044 memset(f->bindingAttributes, 0, sizeof(sdlSoapBindingFunctionFault));
1045
1046 xmlAttrPtr faultUseAttribute = get_attribute(faultNodes->properties, "use");
1047 if (faultUseAttribute && !strncmp((char*)faultUseAttribute->children->content, "encoded", sizeof("encoded"))) {
1048 faultBinding->use = SOAP_ENCODED;
1049 } else {
1050 faultBinding->use = SOAP_LITERAL;
1051 }
1052
1053 xmlAttrPtr faultNamespaceAttribute = get_attribute(faultNodes->properties, "namespace");
1054 if (faultNamespaceAttribute) {
1055 faultBinding->ns = estrdup((char*)faultNamespaceAttribute->children->content);
1056 }
1057
1058 if (faultBinding->use == SOAP_ENCODED) {
1059 xmlAttrPtr faultEncodingStyleAttribute = get_attribute(faultNodes->properties, "encodingStyle");
1060 if (faultEncodingStyleAttribute) {
1061 if (strncmp((char*)faultEncodingStyleAttribute->children->content, SOAP_1_1_ENC_NAMESPACE, sizeof(SOAP_1_1_ENC_NAMESPACE)) == 0) {
1062 faultBinding->encodingStyle = SOAP_ENCODING_1_1;
1063 } else if (strncmp((char*)faultEncodingStyleAttribute->children->content, SOAP_1_2_ENC_NAMESPACE, sizeof(SOAP_1_2_ENC_NAMESPACE)) == 0) {
1064 faultBinding->encodingStyle = SOAP_ENCODING_1_2;
1065 } else {
1066 soap_error1(E_ERROR, "Parsing WSDL: Unknown encodingStyle '%s'", faultEncodingStyleAttribute->children->content);
1067 }
1068 } else {
1069 soap_error0(E_ERROR, "Parsing WSDL: Unspecified encodingStyle");
1070 }
1071 }
1072 } else if (is_wsdl_element(faultNodes) && !node_is_equal(faultNodes,"documentation")) {
1073 soap_error1(E_ERROR, "Parsing WSDL: Unexpected WSDL element <%s>", SAFE_STR(faultNodes->name));
1074 }
1075 faultNodes = faultNodes->next;
1076 }
1077 }
1078 }
1079 if (function->faults == NULL) {
1080 function->faults = emalloc(sizeof(HashTable));
1081 zend_hash_init(function->faults, 0, NULL, delete_fault, 0);
1082 }
1083 if (zend_hash_str_add_ptr(function->faults, f->name, strlen(f->name), f) == NULL) {
1084 soap_error2(E_ERROR, "Parsing WSDL: <fault> with name '%s' already defined in '%s'", f->name, op_name->children->content);
1085 }
1086 }
1087 fault = fault->next;
1088 }
1089
1090 function->binding = tmpbinding;
1091
1092 {
1093 size_t function_name_len = strlen(function->functionName);
1094 char *lc_function_name = zend_str_tolower_dup(function->functionName, function_name_len);
1095
1096 if (zend_hash_str_add_ptr(&ctx.sdl->functions, lc_function_name, function_name_len, function) == NULL) {
1097 zend_hash_next_index_insert_ptr(&ctx.sdl->functions, function);
1098 }
1099 efree(lc_function_name);
1100
1101 if (function->requestName != NULL && strcmp(function->requestName,function->functionName) != 0) {
1102 if (ctx.sdl->requests == NULL) {
1103 ctx.sdl->requests = emalloc(sizeof(HashTable));
1104 zend_hash_init(ctx.sdl->requests, 0, NULL, NULL, 0);
1105 }
1106
1107 size_t request_name_len = strlen(function->requestName);
1108 char *lc_request_name = zend_str_tolower_dup(function->requestName, request_name_len);
1109 zend_hash_str_add_ptr(ctx.sdl->requests, lc_request_name, request_name_len, function);
1110 efree(lc_request_name);
1111 }
1112 }
1113 trav2 = trav2->next;
1114 }
1115
1116 if (!ctx.sdl->bindings) {
1117 ctx.sdl->bindings = emalloc(sizeof(HashTable));
1118 zend_hash_init(ctx.sdl->bindings, 0, NULL, delete_binding, 0);
1119 }
1120
1121 if (!zend_hash_str_add_ptr(ctx.sdl->bindings, tmpbinding->name, strlen(tmpbinding->name), tmpbinding)) {
1122 zend_hash_next_index_insert_ptr(ctx.sdl->bindings, tmpbinding);
1123 }
1124 trav= trav->next;
1125 }
1126
1127 zend_hash_move_forward(&ctx.services);
1128 }
1129
1130 if (ctx.sdl->bindings == NULL || ctx.sdl->bindings->nNumOfElements == 0) {
1131 soap_error0(E_ERROR, "Parsing WSDL: Could not find any usable binding services in WSDL.");
1132 }
1133
1134 } zend_catch {
1135 /* Avoid persistent memory leak. */
1136 zend_hash_destroy(&ctx.docs);
1137 zend_bailout();
1138 } zend_end_try();
1139
1140 zend_hash_destroy(&ctx.messages);
1141 zend_hash_destroy(&ctx.bindings);
1142 zend_hash_destroy(&ctx.portTypes);
1143 zend_hash_destroy(&ctx.services);
1144 zend_hash_destroy(&ctx.docs);
1145
1146 return ctx.sdl;
1147 }
1148
1149 #define WSDL_CACHE_VERSION 0x10
1150
1151 #define WSDL_CACHE_GET(ret,type,buf) memcpy(&ret,*buf,sizeof(type)); *buf += sizeof(type);
1152 #define WSDL_CACHE_GET_INT(ret,buf) ret = ((unsigned char)(*buf)[0])|((unsigned char)(*buf)[1]<<8)|((unsigned char)(*buf)[2]<<16)|((unsigned)(*buf)[3]<<24); *buf += 4;
1153 #define WSDL_CACHE_GET_1(ret,type,buf) ret = (type)(**buf); (*buf)++;
1154 #define WSDL_CACHE_GET_N(ret,n,buf) memcpy(ret,*buf,n); *buf += n;
1155 #define WSDL_CACHE_SKIP(n,buf) *buf += n;
1156
1157 #define WSDL_CACHE_PUT_INT(val,buf) smart_str_appendc(buf,(char)(val & 0xff)); \
1158 smart_str_appendc(buf,(char)((val >> 8) & 0xff)); \
1159 smart_str_appendc(buf,(char)((val >> 16) & 0xff)); \
1160 smart_str_appendc(buf,(char)((val >> 24) & 0xff));
1161 #define WSDL_CACHE_PUT_1(val,buf) smart_str_appendc(buf,val);
1162 #define WSDL_CACHE_PUT_N(val,n,buf) smart_str_appendl(buf,val,n);
1163
1164 #define WSDL_NO_STRING_MARKER 0x7fffffff
1165
sdl_deserialize_string(char ** in)1166 static char* sdl_deserialize_string(char **in)
1167 {
1168 char *s;
1169 size_t len;
1170
1171 WSDL_CACHE_GET_INT(len, in);
1172 if (len == WSDL_NO_STRING_MARKER) {
1173 return NULL;
1174 } else {
1175 s = emalloc(len+1);
1176 WSDL_CACHE_GET_N(s, len, in);
1177 s[len] = '\0';
1178 return s;
1179 }
1180 }
1181
sdl_deserialize_key(HashTable * ht,void * data,char ** in)1182 static void sdl_deserialize_key(HashTable* ht, void* data, char **in)
1183 {
1184 size_t len;
1185
1186 WSDL_CACHE_GET_INT(len, in);
1187 if (len == WSDL_NO_STRING_MARKER) {
1188 zend_hash_next_index_insert_ptr(ht, data);
1189 } else {
1190 zend_hash_str_add_ptr(ht, *in, len, data);
1191 WSDL_CACHE_SKIP(len, in);
1192 }
1193 }
1194
sdl_deserialize_attribute(sdlAttributePtr attr,encodePtr * encoders,char ** in)1195 static void sdl_deserialize_attribute(sdlAttributePtr attr, encodePtr *encoders, char **in)
1196 {
1197 size_t i;
1198
1199 attr->name = sdl_deserialize_string(in);
1200 attr->namens = sdl_deserialize_string(in);
1201 attr->ref = sdl_deserialize_string(in);
1202 attr->def = sdl_deserialize_string(in);
1203 attr->fixed = sdl_deserialize_string(in);
1204 WSDL_CACHE_GET_1(attr->form, sdlForm, in);
1205 WSDL_CACHE_GET_1(attr->use, sdlUse, in);
1206 WSDL_CACHE_GET_INT(i, in);
1207 attr->encode = encoders[i];
1208 WSDL_CACHE_GET_INT(i, in);
1209 if (i > 0) {
1210 attr->extraAttributes = emalloc(sizeof(HashTable));
1211 zend_hash_init(attr->extraAttributes, i, NULL, delete_extra_attribute, 0);
1212 while (i > 0) {
1213 sdlExtraAttributePtr x = emalloc(sizeof(sdlExtraAttribute));
1214 sdl_deserialize_key(attr->extraAttributes, x, in);
1215 x->ns = sdl_deserialize_string(in);
1216 x->val = sdl_deserialize_string(in);
1217 --i;
1218 }
1219 }
1220 }
1221
sdl_deserialize_resriction_int(char ** in)1222 static sdlRestrictionIntPtr sdl_deserialize_resriction_int(char **in)
1223 {
1224 if (**in == 1) {
1225 sdlRestrictionIntPtr x = emalloc(sizeof(sdlRestrictionInt));
1226 WSDL_CACHE_SKIP(1, in);
1227 WSDL_CACHE_GET_INT(x->value, in);
1228 WSDL_CACHE_GET_1(x->fixed, char, in);
1229 return x;
1230 } else {
1231 WSDL_CACHE_SKIP(1, in);
1232 return NULL;
1233 }
1234 }
1235
sdl_deserialize_resriction_char(char ** in)1236 static sdlRestrictionCharPtr sdl_deserialize_resriction_char(char **in)
1237 {
1238 if (**in == 1) {
1239 sdlRestrictionCharPtr x = emalloc(sizeof(sdlRestrictionChar));
1240 WSDL_CACHE_SKIP(1, in);
1241 x->value = sdl_deserialize_string(in);
1242 WSDL_CACHE_GET_1(x->fixed, char, in);
1243 return x;
1244 } else {
1245 WSDL_CACHE_SKIP(1, in);
1246 return NULL;
1247 }
1248 }
1249
sdl_deserialize_model(sdlTypePtr * types,sdlTypePtr * elements,char ** in)1250 static sdlContentModelPtr sdl_deserialize_model(sdlTypePtr *types, sdlTypePtr *elements, char **in)
1251 {
1252 size_t i;
1253 sdlContentModelPtr model = emalloc(sizeof(sdlContentModel));
1254
1255 WSDL_CACHE_GET_1(model->kind, sdlContentKind, in);
1256 WSDL_CACHE_GET_INT(model->min_occurs, in);
1257 WSDL_CACHE_GET_INT(model->max_occurs, in);
1258 switch (model->kind) {
1259 case XSD_CONTENT_ELEMENT:
1260 WSDL_CACHE_GET_INT(i, in);
1261 model->u.element = elements[i];
1262 break;
1263 case XSD_CONTENT_SEQUENCE:
1264 case XSD_CONTENT_ALL:
1265 case XSD_CONTENT_CHOICE:
1266 WSDL_CACHE_GET_INT(i, in);
1267 model->u.content = emalloc(sizeof(HashTable));
1268 zend_hash_init(model->u.content, i, NULL, delete_model, 0);
1269 while (i > 0) {
1270 sdlContentModelPtr x = sdl_deserialize_model(types, elements, in);
1271 zend_hash_next_index_insert_ptr(model->u.content, x);
1272 i--;
1273 }
1274 break;
1275 case XSD_CONTENT_GROUP_REF:
1276 model->u.group_ref = sdl_deserialize_string(in);
1277 break;
1278 case XSD_CONTENT_GROUP:
1279 WSDL_CACHE_GET_INT(i, in);
1280 model->u.group = types[i];
1281 break;
1282 default:
1283 break;
1284 }
1285 return model;
1286 }
1287
sdl_deserialize_type(sdlTypePtr type,sdlTypePtr * types,encodePtr * encoders,char ** in)1288 static void sdl_deserialize_type(sdlTypePtr type, sdlTypePtr *types, encodePtr *encoders, char **in)
1289 {
1290 size_t i;
1291 sdlTypePtr *elements = NULL;
1292
1293 WSDL_CACHE_GET_1(type->kind, sdlTypeKind, in);
1294 type->name = sdl_deserialize_string(in);
1295 type->namens = sdl_deserialize_string(in);
1296 type->def = sdl_deserialize_string(in);
1297 type->fixed = sdl_deserialize_string(in);
1298 type->ref = sdl_deserialize_string(in);
1299 WSDL_CACHE_GET_1(type->nillable, char, in);
1300 WSDL_CACHE_GET_1(type->form, sdlForm, in);
1301
1302 WSDL_CACHE_GET_INT(i, in);
1303 type->encode = encoders[i];
1304
1305 if (**in == 1) {
1306 WSDL_CACHE_SKIP(1, in);
1307 type->restrictions = emalloc(sizeof(sdlRestrictions));
1308 /*memset(type->restrictions, 0, sizeof(sdlRestrictions));*/
1309 type->restrictions->minExclusive = sdl_deserialize_resriction_int(in);
1310 type->restrictions->minInclusive = sdl_deserialize_resriction_int(in);
1311 type->restrictions->maxExclusive = sdl_deserialize_resriction_int(in);
1312 type->restrictions->maxInclusive = sdl_deserialize_resriction_int(in);
1313 type->restrictions->totalDigits = sdl_deserialize_resriction_int(in);
1314 type->restrictions->fractionDigits = sdl_deserialize_resriction_int(in);
1315 type->restrictions->length = sdl_deserialize_resriction_int(in);
1316 type->restrictions->minLength = sdl_deserialize_resriction_int(in);
1317 type->restrictions->maxLength = sdl_deserialize_resriction_int(in);
1318 type->restrictions->whiteSpace = sdl_deserialize_resriction_char(in);
1319 type->restrictions->pattern = sdl_deserialize_resriction_char(in);
1320 WSDL_CACHE_GET_INT(i, in);
1321 if (i > 0) {
1322 type->restrictions->enumeration = emalloc(sizeof(HashTable));
1323 zend_hash_init(type->restrictions->enumeration, i, NULL, delete_restriction_var_char, 0);
1324 while (i > 0) {
1325 sdlRestrictionCharPtr x = sdl_deserialize_resriction_char(in);
1326 sdl_deserialize_key(type->restrictions->enumeration, x, in);
1327 --i;
1328 }
1329 } else {
1330 type->restrictions->enumeration = NULL;
1331 }
1332 } else {
1333 WSDL_CACHE_SKIP(1, in);
1334 }
1335
1336 WSDL_CACHE_GET_INT(i, in);
1337 if (i > 0) {
1338 elements = safe_emalloc((i+1), sizeof(sdlTypePtr), 0);
1339 elements[0] = NULL;
1340 type->elements = emalloc(sizeof(HashTable));
1341 zend_hash_init(type->elements, i, NULL, delete_type, 0);
1342 while (i > 0) {
1343 sdlTypePtr t = emalloc(sizeof(sdlType));
1344 memset(t, 0, sizeof(sdlType));
1345 sdl_deserialize_key(type->elements, t, in);
1346 sdl_deserialize_type(t, types, encoders, in);
1347 elements[i] = t;
1348 --i;
1349 }
1350 }
1351
1352 WSDL_CACHE_GET_INT(i, in);
1353 if (i > 0) {
1354 type->attributes = emalloc(sizeof(HashTable));
1355 zend_hash_init(type->attributes, i, NULL, delete_attribute, 0);
1356 while (i > 0) {
1357 sdlAttributePtr attr = emalloc(sizeof(sdlAttribute));
1358 memset(attr, 0, sizeof(sdlAttribute));
1359 sdl_deserialize_key(type->attributes, attr, in);
1360 sdl_deserialize_attribute(attr, encoders, in);
1361 --i;
1362 }
1363 }
1364
1365 if (**in != 0) {
1366 WSDL_CACHE_SKIP(1, in);
1367 type->model = sdl_deserialize_model(types, elements, in);
1368 } else {
1369 WSDL_CACHE_SKIP(1, in);
1370 }
1371 if (elements != NULL) {
1372 efree(elements);
1373 }
1374 }
1375
sdl_deserialize_encoder(encodePtr enc,sdlTypePtr * types,char ** in)1376 static void sdl_deserialize_encoder(encodePtr enc, sdlTypePtr *types, char **in)
1377 {
1378 size_t i;
1379
1380 WSDL_CACHE_GET_INT(enc->details.type, in);
1381 enc->details.type_str = sdl_deserialize_string(in);
1382 enc->details.ns = sdl_deserialize_string(in);
1383 if (enc->details.ns) {
1384 enc->details.clark_notation = zend_strpprintf(0, "{%s}%s", enc->details.ns, enc->details.type_str);
1385 }
1386 WSDL_CACHE_GET_INT(i, in);
1387 enc->details.sdl_type = types[i];
1388 enc->to_xml = sdl_guess_convert_xml;
1389 enc->to_zval = sdl_guess_convert_zval;
1390
1391 if (enc->details.sdl_type == NULL) {
1392 size_t ns_len = strlen(enc->details.ns);
1393 size_t type_len = strlen(enc->details.type_str);
1394
1395 if (((ns_len == sizeof(SOAP_1_1_ENC_NAMESPACE)-1 &&
1396 memcmp(enc->details.ns, SOAP_1_1_ENC_NAMESPACE, sizeof(SOAP_1_1_ENC_NAMESPACE)-1) == 0) ||
1397 (ns_len == sizeof(SOAP_1_2_ENC_NAMESPACE)-1 &&
1398 memcmp(enc->details.ns, SOAP_1_2_ENC_NAMESPACE, sizeof(SOAP_1_2_ENC_NAMESPACE)-1) == 0))) {
1399 char *enc_nscat;
1400 size_t enc_ns_len;
1401 size_t enc_len;
1402 encodePtr real_enc;
1403
1404 enc_ns_len = sizeof(XSD_NAMESPACE)-1;
1405 enc_len = enc_ns_len + type_len + 1;
1406 enc_nscat = emalloc(enc_len + 1);
1407 memcpy(enc_nscat, XSD_NAMESPACE, sizeof(XSD_NAMESPACE)-1);
1408 enc_nscat[enc_ns_len] = ':';
1409 memcpy(enc_nscat+enc_ns_len+1, enc->details.type_str, type_len);
1410 enc_nscat[enc_len] = '\0';
1411
1412 real_enc = get_encoder_ex(NULL, enc_nscat, enc_len);
1413 efree(enc_nscat);
1414 if (real_enc) {
1415 enc->to_zval = real_enc->to_zval;
1416 enc->to_xml = real_enc->to_xml;
1417 }
1418 }
1419 }
1420 }
1421
sdl_deserialize_soap_body(sdlSoapBindingFunctionBodyPtr body,encodePtr * encoders,sdlTypePtr * types,char ** in)1422 static void sdl_deserialize_soap_body(sdlSoapBindingFunctionBodyPtr body, encodePtr *encoders, sdlTypePtr *types, char **in)
1423 {
1424 size_t i, n;
1425
1426 WSDL_CACHE_GET_1(body->use, sdlEncodingUse, in);
1427 if (body->use == SOAP_ENCODED) {
1428 WSDL_CACHE_GET_1(body->encodingStyle, sdlRpcEncodingStyle, in);
1429 } else {
1430 body->encodingStyle = SOAP_ENCODING_DEFAULT;
1431 }
1432 body->ns = sdl_deserialize_string(in);
1433 WSDL_CACHE_GET_INT(i, in);
1434 if (i > 0) {
1435 body->headers = emalloc(sizeof(HashTable));
1436 zend_hash_init(body->headers, i, NULL, delete_header, 0);
1437 while (i > 0) {
1438 sdlSoapBindingFunctionHeaderPtr tmp = emalloc(sizeof(sdlSoapBindingFunctionHeader));
1439 memset(tmp, 0, sizeof(sdlSoapBindingFunctionHeader));
1440 sdl_deserialize_key(body->headers, tmp, in);
1441 WSDL_CACHE_GET_1(tmp->use, sdlEncodingUse, in);
1442 if (tmp->use == SOAP_ENCODED) {
1443 WSDL_CACHE_GET_1(tmp->encodingStyle, sdlRpcEncodingStyle, in);
1444 } else {
1445 tmp->encodingStyle = SOAP_ENCODING_DEFAULT;
1446 }
1447 tmp->name = sdl_deserialize_string(in);
1448 tmp->ns = sdl_deserialize_string(in);
1449 WSDL_CACHE_GET_INT(n, in);
1450 tmp->encode = encoders[n];
1451 WSDL_CACHE_GET_INT(n, in);
1452 tmp->element = types[n];
1453 --i;
1454
1455 size_t j;
1456 WSDL_CACHE_GET_INT(j, in);
1457 if (j > 0) {
1458 tmp->headerfaults = emalloc(sizeof(HashTable));
1459 zend_hash_init(tmp->headerfaults, j, NULL, delete_header, 0);
1460 while (j > 0) {
1461 sdlSoapBindingFunctionHeaderPtr tmp2 = emalloc(sizeof(sdlSoapBindingFunctionHeader));
1462 memset(tmp2, 0, sizeof(sdlSoapBindingFunctionHeader));
1463 sdl_deserialize_key(tmp->headerfaults, tmp2, in);
1464 WSDL_CACHE_GET_1(tmp2->use, sdlEncodingUse, in);
1465 if (tmp2->use == SOAP_ENCODED) {
1466 WSDL_CACHE_GET_1(tmp2->encodingStyle, sdlRpcEncodingStyle, in);
1467 } else {
1468 tmp2->encodingStyle = SOAP_ENCODING_DEFAULT;
1469 }
1470 tmp2->name = sdl_deserialize_string(in);
1471 tmp2->ns = sdl_deserialize_string(in);
1472
1473 WSDL_CACHE_GET_INT(n, in);
1474 tmp2->encode = encoders[n];
1475 WSDL_CACHE_GET_INT(n, in);
1476 tmp2->element = types[n];
1477 --j;
1478 }
1479 }
1480 }
1481 }
1482 }
1483
sdl_deserialize_parameters(encodePtr * encoders,sdlTypePtr * types,char ** in)1484 static HashTable* sdl_deserialize_parameters(encodePtr *encoders, sdlTypePtr *types, char **in)
1485 {
1486 size_t i, n;
1487 HashTable *ht;
1488
1489 WSDL_CACHE_GET_INT(i, in);
1490 if (i == 0) {return NULL;}
1491 ht = emalloc(sizeof(HashTable));
1492 zend_hash_init(ht, i, NULL, delete_parameter, 0);
1493 while (i > 0) {
1494 sdlParamPtr param = emalloc(sizeof(sdlParam));
1495 sdl_deserialize_key(ht, param, in);
1496 param->paramName = sdl_deserialize_string(in);
1497 WSDL_CACHE_GET_INT(param->order, in);
1498 WSDL_CACHE_GET_INT(n, in);
1499 param->encode = encoders[n];
1500 WSDL_CACHE_GET_INT(n, in);
1501 param->element = types[n];
1502 --i;
1503 }
1504 return ht;
1505 }
1506
get_sdl_from_cache(const char * fn,const char * uri,size_t uri_len,time_t t,time_t * cached)1507 static sdlPtr get_sdl_from_cache(const char *fn, const char *uri, size_t uri_len, time_t t, time_t *cached)
1508 {
1509 sdlPtr sdl;
1510 time_t old_t;
1511 int i, num_groups, num_types, num_elements, num_encoders, num_bindings, num_func;
1512 sdlFunctionPtr *functions = NULL;
1513 sdlBindingPtr *bindings;
1514 sdlTypePtr *types;
1515 encodePtr *encoders;
1516 const encode *enc;
1517
1518 int f;
1519 struct stat st;
1520 char *in, *buf;
1521
1522 f = open(fn, O_RDONLY|O_BINARY);
1523 if (f < 0) {
1524 return NULL;
1525 }
1526 if (fstat(f, &st) != 0) {
1527 close(f);
1528 return NULL;
1529 }
1530 buf = in = emalloc(st.st_size);
1531 if (read(f, in, st.st_size) != st.st_size) {
1532 close(f);
1533 efree(in);
1534 return NULL;
1535 }
1536 close(f);
1537
1538 if (strncmp(in,"wsdl",4) != 0 || in[4] != WSDL_CACHE_VERSION || in[5] != '\0') {
1539 unlink(fn);
1540 efree(buf);
1541 return NULL;
1542 }
1543 in += 6;
1544
1545 WSDL_CACHE_GET(old_t, time_t, &in);
1546 if (old_t < t) {
1547 unlink(fn);
1548 efree(buf);
1549 return NULL;
1550 }
1551 *cached = old_t;
1552
1553 WSDL_CACHE_GET_INT(i, &in);
1554 if (i != uri_len || strncmp(in, uri, i) != 0) {
1555 unlink(fn);
1556 efree(buf);
1557 return NULL;
1558 }
1559 WSDL_CACHE_SKIP(i, &in);
1560
1561 sdl = emalloc(sizeof(*sdl));
1562 memset(sdl, 0, sizeof(*sdl));
1563
1564 sdl->source = sdl_deserialize_string(&in);
1565 sdl->target_ns = sdl_deserialize_string(&in);
1566
1567 WSDL_CACHE_GET_INT(num_groups, &in);
1568 WSDL_CACHE_GET_INT(num_types, &in);
1569 WSDL_CACHE_GET_INT(num_elements, &in);
1570 WSDL_CACHE_GET_INT(num_encoders, &in);
1571
1572 i = num_groups+num_types+num_elements;
1573 types = safe_emalloc((i+1), sizeof(sdlTypePtr), 0);
1574 types[0] = NULL;
1575 while (i > 0) {
1576 types[i] = emalloc(sizeof(sdlType));
1577 memset(types[i], 0, sizeof(sdlType));
1578 i--;
1579 }
1580
1581 i = num_encoders;
1582 enc = defaultEncoding;
1583 while (enc->details.type != END_KNOWN_TYPES) {
1584 i++; enc++;
1585 }
1586 encoders = safe_emalloc((i+1), sizeof(encodePtr), 0);
1587 i = num_encoders;
1588 encoders[0] = NULL;
1589 while (i > 0) {
1590 encoders[i] = emalloc(sizeof(encode));
1591 memset(encoders[i], 0, sizeof(encode));
1592 i--;
1593 }
1594 i = num_encoders;
1595 enc = defaultEncoding;
1596 while (enc->details.type != END_KNOWN_TYPES) {
1597 encoders[++i] = (encodePtr)enc++;
1598 }
1599
1600 i = 1;
1601 if (num_groups > 0) {
1602 sdl->groups = emalloc(sizeof(HashTable));
1603 zend_hash_init(sdl->groups, num_groups, NULL, delete_type, 0);
1604 while (i < num_groups+1) {
1605 sdl_deserialize_key(sdl->groups, types[i], &in);
1606 sdl_deserialize_type(types[i], types, encoders, &in);
1607 i++;
1608 }
1609 }
1610
1611 if (num_types > 0) {
1612 sdl->types = emalloc(sizeof(HashTable));
1613 zend_hash_init(sdl->types, num_types, NULL, delete_type, 0);
1614 while (i < num_groups+num_types+1) {
1615 sdl_deserialize_key(sdl->types, types[i], &in);
1616 sdl_deserialize_type(types[i], types, encoders, &in);
1617 i++;
1618 }
1619 }
1620
1621 if (num_elements > 0) {
1622 sdl->elements = emalloc(sizeof(HashTable));
1623 zend_hash_init(sdl->elements, num_elements, NULL, delete_type, 0);
1624 while (i < num_groups+num_types+num_elements+1) {
1625 sdl_deserialize_key(sdl->elements, types[i], &in);
1626 sdl_deserialize_type(types[i], types, encoders, &in);
1627 i++;
1628 }
1629 }
1630
1631 i = 1;
1632 if (num_encoders > 0) {
1633 sdl->encoders = emalloc(sizeof(HashTable));
1634 zend_hash_init(sdl->encoders, num_encoders, NULL, delete_encoder, 0);
1635 while (i < num_encoders+1) {
1636 sdl_deserialize_key(sdl->encoders, encoders[i], &in);
1637 sdl_deserialize_encoder(encoders[i], types, &in);
1638 i++;
1639 }
1640 }
1641
1642 /* deserialize bindings */
1643 WSDL_CACHE_GET_INT(num_bindings, &in);
1644 bindings = safe_emalloc(num_bindings, sizeof(sdlBindingPtr), 0);
1645 if (num_bindings > 0) {
1646 sdl->bindings = emalloc(sizeof(HashTable));
1647 zend_hash_init(sdl->bindings, num_bindings, NULL, delete_binding, 0);
1648 for (i = 0; i < num_bindings; i++) {
1649 sdlBindingPtr binding = emalloc(sizeof(sdlBinding));
1650 memset(binding, 0, sizeof(sdlBinding));
1651 sdl_deserialize_key(sdl->bindings, binding, &in);
1652 binding->name = sdl_deserialize_string(&in);
1653 binding->location = sdl_deserialize_string(&in);
1654 WSDL_CACHE_GET_1(binding->bindingType,sdlBindingType,&in);
1655 if (binding->bindingType == BINDING_SOAP && *in != 0) {
1656 sdlSoapBindingPtr soap_binding = binding->bindingAttributes = emalloc(sizeof(sdlSoapBinding));
1657 WSDL_CACHE_GET_1(soap_binding->style,sdlEncodingStyle,&in);
1658 WSDL_CACHE_GET_1(soap_binding->transport,sdlTransport,&in);
1659 } else {
1660 WSDL_CACHE_SKIP(1,&in);
1661 }
1662 bindings[i] = binding;
1663 }
1664 }
1665
1666 /* deserialize functions */
1667 WSDL_CACHE_GET_INT(num_func, &in);
1668 zend_hash_init(&sdl->functions, num_func, NULL, delete_function, 0);
1669 if (num_func > 0) {
1670 functions = safe_emalloc(num_func, sizeof(sdlFunctionPtr), 0);
1671 for (i = 0; i < num_func; i++) {
1672 int binding_num, num_faults;
1673 sdlFunctionPtr func = emalloc(sizeof(sdlFunction));
1674 sdl_deserialize_key(&sdl->functions, func, &in);
1675 func->functionName = sdl_deserialize_string(&in);
1676 func->requestName = sdl_deserialize_string(&in);
1677 func->responseName = sdl_deserialize_string(&in);
1678
1679 WSDL_CACHE_GET_INT(binding_num, &in);
1680 if (binding_num == 0) {
1681 func->binding = NULL;
1682 } else {
1683 func->binding = bindings[binding_num-1];
1684 }
1685 if (func->binding && func->binding->bindingType == BINDING_SOAP && *in != 0) {
1686 sdlSoapBindingFunctionPtr binding = func->bindingAttributes = emalloc(sizeof(sdlSoapBindingFunction));
1687 memset(binding, 0, sizeof(sdlSoapBindingFunction));
1688 WSDL_CACHE_GET_1(binding->style,sdlEncodingStyle,&in);
1689 binding->soapAction = sdl_deserialize_string(&in);
1690 sdl_deserialize_soap_body(&binding->input, encoders, types, &in);
1691 sdl_deserialize_soap_body(&binding->output, encoders, types, &in);
1692 } else {
1693 WSDL_CACHE_SKIP(1, &in);
1694 func->bindingAttributes = NULL;
1695 }
1696
1697 func->requestParameters = sdl_deserialize_parameters(encoders, types, &in);
1698 func->responseParameters = sdl_deserialize_parameters(encoders, types, &in);
1699
1700 WSDL_CACHE_GET_INT(num_faults, &in);
1701 if (num_faults > 0) {
1702 int j;
1703
1704 func->faults = emalloc(sizeof(HashTable));
1705 zend_hash_init(func->faults, num_faults, NULL, delete_fault, 0);
1706
1707 for (j = 0; j < num_faults; j++) {
1708 sdlFaultPtr fault = emalloc(sizeof(sdlFault));
1709
1710 sdl_deserialize_key(func->faults, fault, &in);
1711 fault->name =sdl_deserialize_string(&in);
1712 fault->details =sdl_deserialize_parameters(encoders, types, &in);
1713 if (*in != 0) {
1714 sdlSoapBindingFunctionFaultPtr binding = fault->bindingAttributes = emalloc(sizeof(sdlSoapBindingFunctionFault));
1715 memset(binding, 0, sizeof(sdlSoapBindingFunctionFault));
1716 WSDL_CACHE_GET_1(binding->use,sdlEncodingUse,&in);
1717 if (binding->use == SOAP_ENCODED) {
1718 WSDL_CACHE_GET_1(binding->encodingStyle, sdlRpcEncodingStyle, &in);
1719 } else {
1720 binding->encodingStyle = SOAP_ENCODING_DEFAULT;
1721 }
1722 binding->ns = sdl_deserialize_string(&in);
1723 } else {
1724 WSDL_CACHE_SKIP(1, &in);
1725 fault->bindingAttributes = NULL;
1726 }
1727 }
1728 } else {
1729 func->faults = NULL;
1730 }
1731 functions[i] = func;
1732 }
1733 }
1734
1735 /* deserialize requests */
1736 WSDL_CACHE_GET_INT(i, &in);
1737 if (i > 0) {
1738 sdl->requests = emalloc(sizeof(HashTable));
1739 zend_hash_init(sdl->requests, i, NULL, NULL, 0);
1740 while (i > 0) {
1741 int function_num;
1742
1743 WSDL_CACHE_GET_INT(function_num, &in);
1744 sdl_deserialize_key(sdl->requests, functions[function_num-1], &in);
1745 i--;
1746 }
1747 }
1748
1749 if (functions) {
1750 efree(functions);
1751 }
1752 efree(bindings);
1753 efree(encoders);
1754 efree(types);
1755 efree(buf);
1756 return sdl;
1757 }
1758
sdl_serialize_string(const char * str,smart_str * out)1759 static void sdl_serialize_string(const char *str, smart_str *out)
1760 {
1761 if (str) {
1762 size_t i = strlen(str);
1763 WSDL_CACHE_PUT_INT(i, out);
1764 if (i > 0) {
1765 WSDL_CACHE_PUT_N(str, i, out);
1766 }
1767 } else {
1768 WSDL_CACHE_PUT_INT(WSDL_NO_STRING_MARKER, out);
1769 }
1770 }
1771
1772 // TODO: refactor it
sdl_serialize_key(const zend_string * key,smart_str * out)1773 static void sdl_serialize_key(const zend_string *key, smart_str *out)
1774 {
1775 if (key) {
1776 WSDL_CACHE_PUT_INT(ZSTR_LEN(key), out);
1777 WSDL_CACHE_PUT_N(ZSTR_VAL(key), ZSTR_LEN(key), out);
1778 } else {
1779 WSDL_CACHE_PUT_INT(WSDL_NO_STRING_MARKER, out);
1780 }
1781 }
1782
sdl_serialize_encoder_ref(const encodePtr enc,const HashTable * tmp_encoders,smart_str * out)1783 static void sdl_serialize_encoder_ref(const encodePtr enc, const HashTable *tmp_encoders, smart_str *out) {
1784 if (enc) {
1785 zval *encoder_num;
1786 if ((encoder_num = zend_hash_str_find(tmp_encoders, (const char*)&enc, sizeof(enc))) != 0) {
1787 WSDL_CACHE_PUT_INT(Z_LVAL_P(encoder_num), out);
1788 } else {
1789 WSDL_CACHE_PUT_INT(0, out);
1790 }
1791 } else {
1792 WSDL_CACHE_PUT_INT(0, out);
1793 }
1794 }
1795
sdl_serialize_type_ref(const sdlTypePtr type,const HashTable * tmp_types,smart_str * out)1796 static void sdl_serialize_type_ref(const sdlTypePtr type, const HashTable *tmp_types, smart_str *out) {
1797 if (type) {
1798 zval *type_num;
1799 if ((type_num = zend_hash_str_find(tmp_types, (const char*)&type, sizeof(type))) != NULL) {
1800 WSDL_CACHE_PUT_INT(Z_LVAL_P(type_num), out);
1801 } else {
1802 WSDL_CACHE_PUT_INT(0, out);
1803 }
1804 } else {
1805 WSDL_CACHE_PUT_INT(0,out);
1806 }
1807 }
1808
sdl_serialize_attribute(const sdlAttributePtr attr,const HashTable * tmp_encoders,smart_str * out)1809 static void sdl_serialize_attribute(const sdlAttributePtr attr, const HashTable *tmp_encoders, smart_str *out)
1810 {
1811 size_t i;
1812
1813 sdl_serialize_string(attr->name, out);
1814 sdl_serialize_string(attr->namens, out);
1815 sdl_serialize_string(attr->ref, out);
1816 sdl_serialize_string(attr->def, out);
1817 sdl_serialize_string(attr->fixed, out);
1818 WSDL_CACHE_PUT_1(attr->form, out);
1819 WSDL_CACHE_PUT_1(attr->use, out);
1820 sdl_serialize_encoder_ref(attr->encode, tmp_encoders, out);
1821 if (attr->extraAttributes) {
1822 i = zend_hash_num_elements(attr->extraAttributes);
1823 } else {
1824 i = 0;
1825 }
1826 WSDL_CACHE_PUT_INT(i, out);
1827 if (i > 0) {
1828 sdlExtraAttributePtr tmp;
1829 const zend_string *key;
1830
1831 ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(attr->extraAttributes, key, tmp) {
1832 sdl_serialize_key(key, out);
1833 sdl_serialize_string(tmp->ns, out);
1834 sdl_serialize_string(tmp->val, out);
1835 } ZEND_HASH_FOREACH_END();
1836 }
1837 }
1838
sdl_serialize_model(const sdlContentModelPtr model,const HashTable * tmp_types,const HashTable * tmp_elements,smart_str * out)1839 static void sdl_serialize_model(const sdlContentModelPtr model, const HashTable *tmp_types, const HashTable *tmp_elements, smart_str *out)
1840 {
1841 WSDL_CACHE_PUT_1(model->kind, out);
1842 WSDL_CACHE_PUT_INT(model->min_occurs, out);
1843 WSDL_CACHE_PUT_INT(model->max_occurs, out);
1844 switch (model->kind) {
1845 case XSD_CONTENT_ELEMENT:
1846 sdl_serialize_type_ref(model->u.element, tmp_elements, out);
1847 break;
1848 case XSD_CONTENT_SEQUENCE:
1849 case XSD_CONTENT_ALL:
1850 case XSD_CONTENT_CHOICE: {
1851 sdlContentModelPtr tmp;
1852 size_t i = zend_hash_num_elements(model->u.content);
1853
1854 WSDL_CACHE_PUT_INT(i, out);
1855 ZEND_HASH_FOREACH_PTR(model->u.content, tmp) {
1856 sdl_serialize_model(tmp, tmp_types, tmp_elements, out);
1857 } ZEND_HASH_FOREACH_END();
1858 }
1859 break;
1860 case XSD_CONTENT_GROUP_REF:
1861 sdl_serialize_string(model->u.group_ref,out);
1862 break;
1863 case XSD_CONTENT_GROUP:
1864 sdl_serialize_type_ref(model->u.group, tmp_types, out);
1865 break;
1866 default:
1867 break;
1868 }
1869 }
1870
sdl_serialize_resriction_int(const sdlRestrictionIntPtr x,smart_str * out)1871 static void sdl_serialize_resriction_int(const sdlRestrictionIntPtr x, smart_str *out)
1872 {
1873 if (x) {
1874 WSDL_CACHE_PUT_1(1, out);
1875 WSDL_CACHE_PUT_INT(x->value, out);
1876 WSDL_CACHE_PUT_1(x->fixed, out);
1877 } else {
1878 WSDL_CACHE_PUT_1(0, out);
1879 }
1880 }
1881
sdl_serialize_resriction_char(const sdlRestrictionCharPtr x,smart_str * out)1882 static void sdl_serialize_resriction_char(const sdlRestrictionCharPtr x, smart_str *out)
1883 {
1884 if (x) {
1885 WSDL_CACHE_PUT_1(1, out);
1886 sdl_serialize_string(x->value, out);
1887 WSDL_CACHE_PUT_1(x->fixed, out);
1888 } else {
1889 WSDL_CACHE_PUT_1(0, out);
1890 }
1891 }
1892
sdl_serialize_type(const sdlTypePtr type,const HashTable * tmp_encoders,const HashTable * tmp_types,smart_str * out)1893 static void sdl_serialize_type(const sdlTypePtr type, const HashTable *tmp_encoders, const HashTable *tmp_types, smart_str *out)
1894 {
1895 size_t i;
1896 HashTable *tmp_elements = NULL;
1897
1898 WSDL_CACHE_PUT_1(type->kind, out);
1899 sdl_serialize_string(type->name, out);
1900 sdl_serialize_string(type->namens, out);
1901 sdl_serialize_string(type->def, out);
1902 sdl_serialize_string(type->fixed, out);
1903 sdl_serialize_string(type->ref, out);
1904 WSDL_CACHE_PUT_1(type->nillable, out);
1905 WSDL_CACHE_PUT_1(type->form, out);
1906 sdl_serialize_encoder_ref(type->encode, tmp_encoders, out);
1907
1908 if (type->restrictions) {
1909 WSDL_CACHE_PUT_1(1, out);
1910 sdl_serialize_resriction_int(type->restrictions->minExclusive,out);
1911 sdl_serialize_resriction_int(type->restrictions->minInclusive,out);
1912 sdl_serialize_resriction_int(type->restrictions->maxExclusive,out);
1913 sdl_serialize_resriction_int(type->restrictions->maxInclusive,out);
1914 sdl_serialize_resriction_int(type->restrictions->totalDigits,out);
1915 sdl_serialize_resriction_int(type->restrictions->fractionDigits,out);
1916 sdl_serialize_resriction_int(type->restrictions->length,out);
1917 sdl_serialize_resriction_int(type->restrictions->minLength,out);
1918 sdl_serialize_resriction_int(type->restrictions->maxLength,out);
1919 sdl_serialize_resriction_char(type->restrictions->whiteSpace,out);
1920 sdl_serialize_resriction_char(type->restrictions->pattern,out);
1921 if (type->restrictions->enumeration) {
1922 i = zend_hash_num_elements(type->restrictions->enumeration);
1923 } else {
1924 i = 0;
1925 }
1926 WSDL_CACHE_PUT_INT(i, out);
1927 if (i > 0) {
1928 sdlRestrictionCharPtr tmp;
1929 const zend_string *key;
1930
1931 ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(type->restrictions->enumeration, key, tmp) {
1932 sdl_serialize_resriction_char(tmp, out);
1933 sdl_serialize_key(key, out);
1934 } ZEND_HASH_FOREACH_END();
1935 }
1936 } else {
1937 WSDL_CACHE_PUT_1(0, out);
1938 }
1939 if (type->elements) {
1940 i = zend_hash_num_elements(type->elements);
1941 } else {
1942 i = 0;
1943 }
1944 WSDL_CACHE_PUT_INT(i, out);
1945 if (i > 0) {
1946 sdlTypePtr tmp;
1947 const zend_string *key;
1948 zval zv;
1949
1950 tmp_elements = emalloc(sizeof(HashTable));
1951 zend_hash_init(tmp_elements, i, NULL, NULL, 0);
1952
1953 ZEND_HASH_FOREACH_STR_KEY_PTR(type->elements, key, tmp) {
1954 sdl_serialize_key(key, out);
1955 sdl_serialize_type(tmp, tmp_encoders, tmp_types, out);
1956 ZVAL_LONG(&zv, i);
1957 zend_hash_str_add(tmp_elements, (char*)&tmp, sizeof(tmp), &zv);
1958 i--;
1959 } ZEND_HASH_FOREACH_END();
1960 }
1961
1962 if (type->attributes) {
1963 i = zend_hash_num_elements(type->attributes);
1964 } else {
1965 i = 0;
1966 }
1967 WSDL_CACHE_PUT_INT(i, out);
1968 if (i > 0) {
1969 sdlAttributePtr tmp;
1970 const zend_string *key;
1971
1972 ZEND_HASH_FOREACH_STR_KEY_PTR(type->attributes, key, tmp) {
1973 sdl_serialize_key(key, out);
1974 sdl_serialize_attribute(tmp, tmp_encoders, out);
1975 } ZEND_HASH_FOREACH_END();
1976 }
1977 if (type->model) {
1978 WSDL_CACHE_PUT_1(1, out);
1979 sdl_serialize_model(type->model, tmp_types, tmp_elements, out);
1980 } else {
1981 WSDL_CACHE_PUT_1(0, out);
1982 }
1983 if (tmp_elements != NULL) {
1984 zend_hash_destroy(tmp_elements);
1985 efree(tmp_elements);
1986 }
1987 }
1988
sdl_serialize_encoder(const encodePtr enc,const HashTable * tmp_types,smart_str * out)1989 static void sdl_serialize_encoder(const encodePtr enc, const HashTable *tmp_types, smart_str *out)
1990 {
1991 WSDL_CACHE_PUT_INT(enc->details.type, out);
1992 sdl_serialize_string(enc->details.type_str, out);
1993 sdl_serialize_string(enc->details.ns, out);
1994 sdl_serialize_type_ref(enc->details.sdl_type, tmp_types, out);
1995 }
1996
sdl_serialize_parameters(const HashTable * ht,const HashTable * tmp_encoders,const HashTable * tmp_types,smart_str * out)1997 static void sdl_serialize_parameters(const HashTable *ht, const HashTable *tmp_encoders, const HashTable *tmp_types, smart_str *out)
1998 {
1999 size_t i;
2000
2001 if (ht) {
2002 i = zend_hash_num_elements(ht);
2003 } else {
2004 i = 0;
2005 }
2006 WSDL_CACHE_PUT_INT(i, out);
2007 if (i > 0) {
2008 sdlParamPtr tmp;
2009 const zend_string *key;
2010
2011 ZEND_HASH_FOREACH_STR_KEY_PTR(ht, key, tmp) {
2012 sdl_serialize_key(key, out);
2013 sdl_serialize_string(tmp->paramName, out);
2014 WSDL_CACHE_PUT_INT(tmp->order, out);
2015 sdl_serialize_encoder_ref(tmp->encode, tmp_encoders, out);
2016 sdl_serialize_type_ref(tmp->element, tmp_types, out);
2017 } ZEND_HASH_FOREACH_END();
2018 }
2019 }
2020
sdl_serialize_soap_body(const sdlSoapBindingFunctionBodyPtr body,const HashTable * tmp_encoders,const HashTable * tmp_types,smart_str * out)2021 static void sdl_serialize_soap_body(const sdlSoapBindingFunctionBodyPtr body, const HashTable *tmp_encoders, const HashTable *tmp_types, smart_str *out)
2022 {
2023 size_t i, j;
2024
2025 WSDL_CACHE_PUT_1(body->use, out);
2026 if (body->use == SOAP_ENCODED) {
2027 WSDL_CACHE_PUT_1(body->encodingStyle, out);
2028 }
2029 sdl_serialize_string(body->ns, out);
2030 if (body->headers) {
2031 i = zend_hash_num_elements(body->headers);
2032 } else {
2033 i = 0;
2034 }
2035 WSDL_CACHE_PUT_INT(i, out);
2036 if (i > 0) {
2037 sdlSoapBindingFunctionHeaderPtr tmp;
2038 const zend_string *key;
2039
2040 ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(body->headers, key, tmp) {
2041 sdl_serialize_key(key, out);
2042 WSDL_CACHE_PUT_1(tmp->use, out);
2043 if (tmp->use == SOAP_ENCODED) {
2044 WSDL_CACHE_PUT_1(tmp->encodingStyle, out);
2045 }
2046 sdl_serialize_string(tmp->name, out);
2047 sdl_serialize_string(tmp->ns, out);
2048 sdl_serialize_encoder_ref(tmp->encode, tmp_encoders, out);
2049 sdl_serialize_type_ref(tmp->element, tmp_types, out);
2050 if (tmp->headerfaults) {
2051 j = zend_hash_num_elements(tmp->headerfaults);
2052 } else {
2053 j = 0;
2054 }
2055 WSDL_CACHE_PUT_INT(j, out);
2056 if (j > 0) {
2057 sdlSoapBindingFunctionHeaderPtr tmp2;
2058 const zend_string *key_inner;
2059
2060 ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(body->headers, key_inner, tmp2) {
2061 sdl_serialize_key(key_inner, out);
2062 WSDL_CACHE_PUT_1(tmp2->use, out);
2063 if (tmp2->use == SOAP_ENCODED) {
2064 WSDL_CACHE_PUT_1(tmp2->encodingStyle, out);
2065 }
2066 sdl_serialize_string(tmp2->name, out);
2067 sdl_serialize_string(tmp2->ns, out);
2068 sdl_serialize_encoder_ref(tmp2->encode, tmp_encoders, out);
2069 sdl_serialize_type_ref(tmp2->element, tmp_types, out);
2070 } ZEND_HASH_FOREACH_END();
2071 }
2072 } ZEND_HASH_FOREACH_END();
2073 }
2074 }
2075
add_sdl_to_cache(const char * fn,const char * uri,time_t t,sdlPtr sdl)2076 static void add_sdl_to_cache(const char *fn, const char *uri, time_t t, sdlPtr sdl)
2077 {
2078 smart_str buf = {0};
2079 smart_str *out = &buf;
2080 int i;
2081 int type_num = 1;
2082 int encoder_num = 1;
2083 int f;
2084 const encode *enc;
2085 HashTable tmp_types;
2086 HashTable tmp_encoders;
2087 HashTable tmp_bindings;
2088 HashTable tmp_functions;
2089
2090 /* To avoid race conditions, we first create a temporary file and then rename it atomically
2091 * at the end of the function. (see bug #66150) */
2092 zend_string *temp_file_path;
2093 f = php_open_temporary_fd_ex(SOAP_GLOBAL(cache_dir), "tmp.wsdl.", &temp_file_path, PHP_TMP_FILE_SILENT);
2094
2095 if (f < 0) {return;}
2096
2097 zend_hash_init(&tmp_types, 0, NULL, NULL, 0);
2098 zend_hash_init(&tmp_encoders, 0, NULL, NULL, 0);
2099 zend_hash_init(&tmp_bindings, 0, NULL, NULL, 0);
2100 zend_hash_init(&tmp_functions, 0, NULL, NULL, 0);
2101
2102 WSDL_CACHE_PUT_N("wsdl", 4, out);
2103 WSDL_CACHE_PUT_1(WSDL_CACHE_VERSION,out);
2104 WSDL_CACHE_PUT_1(0,out);
2105 WSDL_CACHE_PUT_N((char*)&t, sizeof(t), out);
2106
2107 sdl_serialize_string(uri, out);
2108 sdl_serialize_string(sdl->source, out);
2109 sdl_serialize_string(sdl->target_ns, out);
2110
2111 if (sdl->groups) {
2112 i = zend_hash_num_elements(sdl->groups);
2113 } else {
2114 i = 0;
2115 }
2116 WSDL_CACHE_PUT_INT(i, out);
2117 if (i > 0) {
2118 sdlTypePtr tmp;
2119 zval zv;
2120
2121 ZEND_HASH_MAP_FOREACH_PTR(sdl->groups, tmp) {
2122 ZVAL_LONG(&zv, type_num);
2123 zend_hash_str_add(&tmp_types, (char*)&tmp, sizeof(tmp), &zv);
2124 ++type_num;
2125 } ZEND_HASH_FOREACH_END();
2126 }
2127
2128 if (sdl->types) {
2129 i = zend_hash_num_elements(sdl->types);
2130 } else {
2131 i = 0;
2132 }
2133 WSDL_CACHE_PUT_INT(i, out);
2134 if (i > 0) {
2135 sdlTypePtr tmp;
2136 zval zv;
2137
2138 ZEND_HASH_FOREACH_PTR(sdl->types, tmp) {
2139 ZVAL_LONG(&zv, type_num);
2140 zend_hash_str_add(&tmp_types, (char*)&tmp, sizeof(tmp), &zv);
2141 ++type_num;
2142 } ZEND_HASH_FOREACH_END();
2143 }
2144
2145 if (sdl->elements) {
2146 i = zend_hash_num_elements(sdl->elements);
2147 } else {
2148 i = 0;
2149 }
2150 WSDL_CACHE_PUT_INT(i, out);
2151 if (i > 0) {
2152 sdlTypePtr tmp;
2153 zval zv;
2154
2155 ZEND_HASH_MAP_FOREACH_PTR(sdl->elements, tmp) {
2156 ZVAL_LONG(&zv, type_num);
2157 zend_hash_str_add(&tmp_types, (char*)&tmp, sizeof(tmp), &zv);
2158 ++type_num;
2159 } ZEND_HASH_FOREACH_END();
2160 }
2161
2162 if (sdl->encoders) {
2163 i = zend_hash_num_elements(sdl->encoders);
2164 } else {
2165 i = 0;
2166 }
2167 WSDL_CACHE_PUT_INT(i, out);
2168 if (i > 0) {
2169 encodePtr tmp;
2170 zval zv;
2171
2172 ZEND_HASH_FOREACH_PTR(sdl->encoders, tmp) {
2173 ZVAL_LONG(&zv, encoder_num);
2174 zend_hash_str_add(&tmp_encoders, (char*)&tmp, sizeof(tmp), &zv);
2175 ++encoder_num;
2176 } ZEND_HASH_FOREACH_END();
2177 }
2178 enc = defaultEncoding;
2179 while (enc->details.type != END_KNOWN_TYPES) {
2180 zval zv;
2181
2182 ZVAL_LONG(&zv, encoder_num);
2183 zend_hash_str_add(&tmp_encoders, (char*)&enc, sizeof(encodePtr), &zv);
2184 enc++;
2185 ++encoder_num;
2186 }
2187
2188 if (sdl->groups) {
2189 sdlTypePtr tmp;
2190 const zend_string *key;
2191
2192 ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(sdl->groups, key, tmp) {
2193 sdl_serialize_key(key, out);
2194 sdl_serialize_type(tmp, &tmp_encoders, &tmp_types, out);
2195 } ZEND_HASH_FOREACH_END();
2196 }
2197
2198 if (sdl->types) {
2199 sdlTypePtr tmp;
2200 const zend_string *key;
2201
2202 ZEND_HASH_FOREACH_STR_KEY_PTR(sdl->types, key, tmp) {
2203 sdl_serialize_key(key, out);
2204 sdl_serialize_type(tmp, &tmp_encoders, &tmp_types, out);
2205 } ZEND_HASH_FOREACH_END();
2206 }
2207
2208 if (sdl->elements) {
2209 sdlTypePtr tmp;
2210 const zend_string *key;
2211
2212 ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(sdl->elements, key, tmp) {
2213 sdl_serialize_key(key, out);
2214 sdl_serialize_type(tmp, &tmp_encoders, &tmp_types, out);
2215 } ZEND_HASH_FOREACH_END();
2216 }
2217
2218 if (sdl->encoders) {
2219 encodePtr tmp;
2220 const zend_string *key;
2221
2222 ZEND_HASH_FOREACH_STR_KEY_PTR(sdl->encoders, key, tmp) {
2223 sdl_serialize_key(key, out);
2224 sdl_serialize_encoder(tmp, &tmp_types, out);
2225 } ZEND_HASH_FOREACH_END();
2226 }
2227
2228 /* serialize bindings */
2229 if (sdl->bindings) {
2230 i = zend_hash_num_elements(sdl->bindings);
2231 } else {
2232 i = 0;
2233 }
2234 WSDL_CACHE_PUT_INT(i, out);
2235 if (i > 0) {
2236 sdlBindingPtr tmp;
2237 int binding_num = 1;
2238 zval zv;
2239 const zend_string *key;
2240
2241 ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(sdl->bindings, key, tmp) {
2242 sdl_serialize_key(key, out);
2243 sdl_serialize_string(tmp->name, out);
2244 sdl_serialize_string(tmp->location, out);
2245 WSDL_CACHE_PUT_1(tmp->bindingType,out);
2246 if (tmp->bindingType == BINDING_SOAP && tmp->bindingAttributes != NULL) {
2247 sdlSoapBindingPtr binding = (sdlSoapBindingPtr)tmp->bindingAttributes;
2248 WSDL_CACHE_PUT_1(binding->style, out);
2249 WSDL_CACHE_PUT_1(binding->transport, out);
2250 } else {
2251 WSDL_CACHE_PUT_1(0,out);
2252 }
2253
2254 ZVAL_LONG(&zv, binding_num);
2255 zend_hash_str_add(&tmp_bindings, (char*)&tmp, sizeof(tmp), &zv);
2256 binding_num++;
2257 } ZEND_HASH_FOREACH_END();
2258 }
2259
2260 /* serialize functions */
2261 i = zend_hash_num_elements(&sdl->functions);
2262 WSDL_CACHE_PUT_INT(i, out);
2263 if (i > 0) {
2264 sdlFunctionPtr tmp;
2265 zval *binding_num, zv;
2266 int function_num = 1;
2267 const zend_string *key;
2268
2269 ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&sdl->functions, key, tmp) {
2270 sdl_serialize_key(key, out);
2271 sdl_serialize_string(tmp->functionName, out);
2272 sdl_serialize_string(tmp->requestName, out);
2273 sdl_serialize_string(tmp->responseName, out);
2274
2275 if (tmp->binding) {
2276 binding_num = zend_hash_str_find(&tmp_bindings,(char*)&tmp->binding, sizeof(tmp->binding));
2277 if (binding_num) {
2278 WSDL_CACHE_PUT_INT(Z_LVAL_P(binding_num), out);
2279 if (Z_LVAL_P(binding_num) >= 0) {
2280 if (tmp->binding->bindingType == BINDING_SOAP && tmp->bindingAttributes != NULL) {
2281 sdlSoapBindingFunctionPtr binding = (sdlSoapBindingFunctionPtr)tmp->bindingAttributes;
2282 WSDL_CACHE_PUT_1(binding->style, out);
2283 sdl_serialize_string(binding->soapAction, out);
2284 sdl_serialize_soap_body(&binding->input, &tmp_encoders, &tmp_types, out);
2285 sdl_serialize_soap_body(&binding->output, &tmp_encoders, &tmp_types, out);
2286 } else {
2287 WSDL_CACHE_PUT_1(0,out);
2288 }
2289 }
2290 }
2291 }
2292 sdl_serialize_parameters(tmp->requestParameters, &tmp_encoders, &tmp_types, out);
2293 sdl_serialize_parameters(tmp->responseParameters, &tmp_encoders, &tmp_types, out);
2294
2295 if (tmp->faults) {
2296 sdlFaultPtr fault;
2297 const zend_string *key_inner;
2298
2299 WSDL_CACHE_PUT_INT(zend_hash_num_elements(tmp->faults), out);
2300
2301 ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(tmp->faults, key_inner, fault) {
2302 sdl_serialize_key(key_inner, out);
2303 sdl_serialize_string(fault->name, out);
2304 sdl_serialize_parameters(fault->details, &tmp_encoders, &tmp_types, out);
2305 if (tmp->binding->bindingType == BINDING_SOAP && fault->bindingAttributes != NULL) {
2306 sdlSoapBindingFunctionFaultPtr binding = (sdlSoapBindingFunctionFaultPtr)fault->bindingAttributes;
2307 WSDL_CACHE_PUT_1(binding->use, out);
2308 if (binding->use == SOAP_ENCODED) {
2309 WSDL_CACHE_PUT_1(binding->encodingStyle, out);
2310 }
2311 sdl_serialize_string(binding->ns, out);
2312 } else {
2313 WSDL_CACHE_PUT_1(0, out);
2314 }
2315 } ZEND_HASH_FOREACH_END();
2316 } else {
2317 WSDL_CACHE_PUT_INT(0, out);
2318 }
2319
2320 ZVAL_LONG(&zv, function_num);
2321 zend_hash_str_add(&tmp_functions, (char*)&tmp, sizeof(tmp), &zv);
2322 function_num++;
2323 } ZEND_HASH_FOREACH_END();
2324 }
2325
2326 /* serialize requests */
2327 if (sdl->requests) {
2328 i = zend_hash_num_elements(sdl->requests);
2329 } else {
2330 i = 0;
2331 }
2332 WSDL_CACHE_PUT_INT(i, out);
2333 if (i > 0) {
2334 sdlFunctionPtr tmp;
2335 zval *function_num;
2336 const zend_string *key;
2337
2338 ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(sdl->requests, key, tmp) {
2339 function_num = zend_hash_str_find(&tmp_functions, (char*)&tmp, sizeof(tmp));
2340 WSDL_CACHE_PUT_INT(Z_LVAL_P(function_num), out);
2341 sdl_serialize_key(key, out);
2342 } ZEND_HASH_FOREACH_END();
2343 }
2344
2345 bool valid_file = write(f, ZSTR_VAL(buf.s), ZSTR_LEN(buf.s)) == ZSTR_LEN(buf.s);
2346 close(f);
2347
2348 /* Make sure that incomplete files (e.g. due to disk space issues, see bug #66150) are not utilised. */
2349 if (valid_file) {
2350 /* This is allowed to fail, this means that another process was raced to create the file. */
2351 if (VCWD_RENAME(ZSTR_VAL(temp_file_path), fn) < 0) {
2352 VCWD_UNLINK(ZSTR_VAL(temp_file_path));
2353 }
2354 }
2355
2356 smart_str_free(&buf);
2357 zend_hash_destroy(&tmp_functions);
2358 zend_hash_destroy(&tmp_bindings);
2359 zend_hash_destroy(&tmp_encoders);
2360 zend_hash_destroy(&tmp_types);
2361 zend_string_release_ex(temp_file_path, false);
2362 }
2363
2364
make_persistent_restriction_int(void * data)2365 static void make_persistent_restriction_int(void *data)
2366 {
2367 sdlRestrictionIntPtr *rest = (sdlRestrictionIntPtr *)data;
2368 sdlRestrictionIntPtr prest = NULL;
2369
2370 prest = malloc(sizeof(sdlRestrictionInt));
2371 *prest = **rest;
2372 *rest = prest;
2373 }
2374
2375
make_persistent_restriction_char_int(sdlRestrictionCharPtr * rest)2376 static void make_persistent_restriction_char_int(sdlRestrictionCharPtr *rest)
2377 {
2378 sdlRestrictionCharPtr prest = NULL;
2379
2380 prest = malloc(sizeof(sdlRestrictionChar));
2381 memset(prest, 0, sizeof(sdlRestrictionChar));
2382 prest->value = strdup((*rest)->value);
2383 prest->fixed = (*rest)->fixed;
2384 *rest = prest;
2385 }
2386
2387
make_persistent_sdl_type_ref(sdlTypePtr * type,HashTable * ptr_map,HashTable * bp_types)2388 static void make_persistent_sdl_type_ref(sdlTypePtr *type, HashTable *ptr_map, HashTable *bp_types)
2389 {
2390 sdlTypePtr tmp;
2391
2392 if ((tmp = zend_hash_str_find_ptr(ptr_map, (char *)type, sizeof(sdlTypePtr))) != NULL) {
2393 *type = tmp;
2394 } else {
2395 zend_hash_next_index_insert_ptr(bp_types, *type);
2396 }
2397 }
2398
2399
make_persistent_sdl_encoder_ref(encodePtr * enc,HashTable * ptr_map,HashTable * bp_encoders)2400 static void make_persistent_sdl_encoder_ref(encodePtr *enc, HashTable *ptr_map, HashTable *bp_encoders)
2401 {
2402 encodePtr tmp;
2403
2404 /* do not process defaultEncoding's here */
2405 if ((*enc) >= defaultEncoding && (*enc) < defaultEncoding + numDefaultEncodings) {
2406 return;
2407 }
2408
2409 if ((tmp = zend_hash_str_find_ptr(ptr_map, (char *)enc, sizeof(encodePtr))) != NULL) {
2410 *enc = tmp;
2411 } else {
2412 zend_hash_next_index_insert_ptr(bp_encoders, enc);
2413 }
2414 }
2415
2416
make_persistent_sdl_function_headers(HashTable * headers,HashTable * ptr_map)2417 static HashTable* make_persistent_sdl_function_headers(HashTable *headers, HashTable *ptr_map)
2418 {
2419 HashTable *pheaders;
2420 sdlSoapBindingFunctionHeaderPtr tmp, pheader;
2421 encodePtr penc;
2422 sdlTypePtr ptype;
2423 zend_string *key;
2424
2425 pheaders = malloc(sizeof(HashTable));
2426 zend_hash_init(pheaders, zend_hash_num_elements(headers), NULL, delete_header_persistent, 1);
2427
2428 ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(headers, key, tmp) {
2429 pheader = malloc(sizeof(sdlSoapBindingFunctionHeader));
2430 memset(pheader, 0, sizeof(sdlSoapBindingFunctionHeader));
2431 *pheader = *tmp;
2432
2433 if (pheader->name) {
2434 pheader->name = strdup(pheader->name);
2435 }
2436 if (pheader->ns) {
2437 pheader->ns = strdup(pheader->ns);
2438 }
2439
2440 if (pheader->encode && pheader->encode->details.sdl_type) {
2441 if ((penc = zend_hash_str_find_ptr(ptr_map, (char*)&pheader->encode, sizeof(encodePtr))) == NULL) {
2442 assert(0);
2443 }
2444 pheader->encode = penc;
2445 }
2446 if (pheader->element) {
2447 if ((ptype = zend_hash_str_find_ptr(ptr_map, (char*)&pheader->element, sizeof(sdlTypePtr))) == NULL) {
2448 assert(0);
2449 }
2450 pheader->element = ptype;
2451 }
2452
2453 if (pheader->headerfaults) {
2454 pheader->headerfaults = make_persistent_sdl_function_headers(pheader->headerfaults, ptr_map);
2455 }
2456
2457 if (key) {
2458 /* We have to duplicate key emalloc->malloc */
2459 zend_hash_str_add_ptr(pheaders, ZSTR_VAL(key), ZSTR_LEN(key), pheader);
2460 } else {
2461 zend_hash_next_index_insert_ptr(pheaders, pheader);
2462 }
2463 } ZEND_HASH_FOREACH_END();
2464
2465 return pheaders;
2466 }
2467
2468
make_persistent_sdl_soap_body(sdlSoapBindingFunctionBodyPtr body,HashTable * ptr_map)2469 static void make_persistent_sdl_soap_body(sdlSoapBindingFunctionBodyPtr body, HashTable *ptr_map)
2470 {
2471 if (body->ns) {
2472 body->ns = strdup(body->ns);
2473 }
2474
2475 if (body->headers) {
2476 body->headers = make_persistent_sdl_function_headers(body->headers, ptr_map);
2477 }
2478 }
2479
2480
make_persistent_sdl_parameters(HashTable * params,HashTable * ptr_map)2481 static HashTable* make_persistent_sdl_parameters(HashTable *params, HashTable *ptr_map)
2482 {
2483 HashTable *pparams;
2484 sdlParamPtr tmp, pparam;
2485 sdlTypePtr ptype;
2486 encodePtr penc;
2487 zend_string *key;
2488
2489 pparams = malloc(sizeof(HashTable));
2490 zend_hash_init(pparams, zend_hash_num_elements(params), NULL, delete_parameter_persistent, 1);
2491
2492 ZEND_HASH_FOREACH_STR_KEY_PTR(params, key, tmp) {
2493 pparam = malloc(sizeof(sdlParam));
2494 memset(pparam, 0, sizeof(sdlParam));
2495 *pparam = *tmp;
2496
2497 if (pparam->paramName) {
2498 pparam->paramName = strdup(pparam->paramName);
2499 }
2500
2501 if (pparam->encode && pparam->encode->details.sdl_type) {
2502 if ((penc = zend_hash_str_find_ptr(ptr_map, (char*)&pparam->encode, sizeof(encodePtr))) == NULL) {
2503 assert(0);
2504 }
2505 pparam->encode = penc;
2506 }
2507 if (pparam->element) {
2508 if ((ptype = zend_hash_str_find_ptr(ptr_map, (char*)&pparam->element, sizeof(sdlTypePtr))) == NULL) {
2509 assert(0);
2510 }
2511 pparam->element = ptype;
2512 }
2513
2514 if (key) {
2515 /* We have to duplicate key emalloc->malloc */
2516 zend_hash_str_add_ptr(pparams, ZSTR_VAL(key), ZSTR_LEN(key), pparam);
2517 } else {
2518 zend_hash_next_index_insert_ptr(pparams, pparam);
2519 }
2520 } ZEND_HASH_FOREACH_END();
2521
2522 return pparams;
2523 }
2524
make_persistent_sdl_function_faults(sdlFunctionPtr func,HashTable * faults,HashTable * ptr_map)2525 static HashTable* make_persistent_sdl_function_faults(sdlFunctionPtr func, HashTable *faults, HashTable *ptr_map)
2526 {
2527 HashTable *pfaults;
2528 sdlFaultPtr tmp, pfault;
2529 zend_string *key;
2530
2531 pfaults = malloc(sizeof(HashTable));
2532 zend_hash_init(pfaults, zend_hash_num_elements(faults), NULL, delete_fault_persistent, 1);
2533
2534 ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(faults, key, tmp) {
2535 pfault = malloc(sizeof(sdlFault));
2536 memset(pfault, 0, sizeof(sdlFault));
2537 *pfault = *tmp;
2538
2539 if (pfault->name) {
2540 pfault->name = strdup(pfault->name);
2541 }
2542 if (pfault->details) {
2543 pfault->details = make_persistent_sdl_parameters(pfault->details, ptr_map);
2544 }
2545
2546 if (func->binding->bindingType == BINDING_SOAP && pfault->bindingAttributes) {
2547 sdlSoapBindingFunctionFaultPtr soap_binding;
2548
2549 soap_binding = malloc(sizeof(sdlSoapBindingFunctionFault));
2550 memset(soap_binding, 0, sizeof(sdlSoapBindingFunctionFault));
2551 *soap_binding = *(sdlSoapBindingFunctionFaultPtr)pfault->bindingAttributes;
2552 if (soap_binding->ns) {
2553 soap_binding->ns = strdup(soap_binding->ns);
2554 }
2555 pfault->bindingAttributes = soap_binding;
2556 }
2557
2558 if (key) {
2559 /* We have to duplicate key emalloc->malloc */
2560 zend_hash_str_add_ptr(pfaults, ZSTR_VAL(key), ZSTR_LEN(key), pfault);
2561 } else {
2562 zend_hash_next_index_insert_ptr(pfaults, pfault);
2563 }
2564
2565 } ZEND_HASH_FOREACH_END();
2566
2567 return pfaults;
2568 }
2569
2570
make_persistent_sdl_attribute(sdlAttributePtr attr,HashTable * ptr_map,HashTable * bp_types,HashTable * bp_encoders)2571 static sdlAttributePtr make_persistent_sdl_attribute(sdlAttributePtr attr, HashTable *ptr_map, HashTable *bp_types, HashTable *bp_encoders)
2572 {
2573 sdlAttributePtr pattr;
2574 zend_string *key;
2575
2576 pattr = malloc(sizeof(sdlAttribute));
2577 memset(pattr, 0, sizeof(sdlAttribute));
2578
2579 *pattr = *attr;
2580
2581 if (pattr->name) {
2582 pattr->name = strdup(pattr->name);
2583 }
2584 if (pattr->namens) {
2585 pattr->namens = strdup(pattr->namens);
2586 }
2587 if (pattr->ref) {
2588 pattr->ref = strdup(pattr->ref);
2589 }
2590 if (pattr->def) {
2591 pattr->def = strdup(pattr->def);
2592 }
2593 if (pattr->fixed) {
2594 pattr->fixed = strdup(pattr->fixed);
2595 }
2596
2597 /* we do not want to process defaultEncoding's here */
2598 if (pattr->encode) {
2599 make_persistent_sdl_encoder_ref(&pattr->encode, ptr_map, bp_encoders);
2600 }
2601
2602 if (pattr->extraAttributes) {
2603 sdlExtraAttributePtr tmp, pextra;
2604
2605 pattr->extraAttributes = malloc(sizeof(HashTable));
2606 zend_hash_init(pattr->extraAttributes, zend_hash_num_elements(attr->extraAttributes), NULL, delete_extra_attribute_persistent, 1);
2607
2608 ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(attr->extraAttributes, key, tmp) {
2609 if (key) {
2610 pextra = malloc(sizeof(sdlExtraAttribute));
2611 memset(pextra, 0, sizeof(sdlExtraAttribute));
2612
2613 if (tmp->ns) {
2614 pextra->ns = strdup(tmp->ns);
2615 }
2616 if (tmp->val) {
2617 pextra->val = strdup(tmp->val);
2618 }
2619
2620 /* We have to duplicate key emalloc->malloc */
2621 zend_hash_str_add_ptr(pattr->extraAttributes, ZSTR_VAL(key), ZSTR_LEN(key), pextra);
2622 }
2623 } ZEND_HASH_FOREACH_END();
2624 }
2625
2626 return pattr;
2627 }
2628
2629
make_persistent_sdl_model(sdlContentModelPtr model,HashTable * ptr_map,HashTable * bp_types,HashTable * bp_encoders)2630 static sdlContentModelPtr make_persistent_sdl_model(sdlContentModelPtr model, HashTable *ptr_map, HashTable *bp_types, HashTable *bp_encoders)
2631 {
2632 sdlContentModelPtr pmodel;
2633 sdlContentModelPtr tmp, pcontent;
2634
2635 pmodel = malloc(sizeof(sdlContentModel));
2636 memset(pmodel, 0, sizeof(sdlContentModel));
2637 *pmodel = *model;
2638
2639 switch (pmodel->kind) {
2640 case XSD_CONTENT_ELEMENT:
2641 if (pmodel->u.element) {
2642 make_persistent_sdl_type_ref(&pmodel->u.element, ptr_map, bp_types);
2643 }
2644 break;
2645
2646 case XSD_CONTENT_SEQUENCE:
2647 case XSD_CONTENT_ALL:
2648 case XSD_CONTENT_CHOICE:
2649 pmodel->u.content = malloc(sizeof(HashTable));
2650 zend_hash_init(pmodel->u.content, zend_hash_num_elements(model->u.content), NULL, delete_model_persistent, 1);
2651
2652 ZEND_HASH_FOREACH_PTR(model->u.content, tmp) {
2653 pcontent = make_persistent_sdl_model(tmp, ptr_map, bp_types, bp_encoders);
2654 zend_hash_next_index_insert_ptr(pmodel->u.content, pcontent);
2655 } ZEND_HASH_FOREACH_END();
2656 break;
2657
2658 case XSD_CONTENT_GROUP_REF:
2659 if (pmodel->u.group_ref) {
2660 pmodel->u.group_ref = strdup(pmodel->u.group_ref);
2661 }
2662 break;
2663
2664 case XSD_CONTENT_GROUP:
2665 if (pmodel->u.group) {
2666 make_persistent_sdl_type_ref(&pmodel->u.group, ptr_map, bp_types);
2667 }
2668 break;
2669
2670 default:
2671 break;
2672 }
2673
2674 return pmodel;
2675 }
2676
2677
make_persistent_sdl_type(sdlTypePtr type,HashTable * ptr_map,HashTable * bp_types,HashTable * bp_encoders)2678 static sdlTypePtr make_persistent_sdl_type(sdlTypePtr type, HashTable *ptr_map, HashTable *bp_types, HashTable *bp_encoders)
2679 {
2680 zend_string *key;
2681 sdlTypePtr ptype = NULL;
2682
2683 ptype = malloc(sizeof(sdlType));
2684 memset(ptype, 0, sizeof(sdlType));
2685
2686 *ptype = *type;
2687
2688 if (ptype->name) {
2689 ptype->name = strdup(ptype->name);
2690 }
2691 if (ptype->namens) {
2692 ptype->namens = strdup(ptype->namens);
2693 }
2694 if (ptype->def) {
2695 ptype->def = strdup(ptype->def);
2696 }
2697 if (ptype->fixed) {
2698 ptype->fixed = strdup(ptype->fixed);
2699 }
2700 if (ptype->ref) {
2701 ptype->ref = strdup(ptype->ref);
2702 }
2703
2704 /* we do not want to process defaultEncoding's here */
2705 if (ptype->encode) {
2706 make_persistent_sdl_encoder_ref(&ptype->encode, ptr_map, bp_encoders);
2707 }
2708
2709 if (ptype->restrictions) {
2710 ptype->restrictions = malloc(sizeof(sdlRestrictions));
2711 memset(ptype->restrictions, 0, sizeof(sdlRestrictions));
2712 *ptype->restrictions = *type->restrictions;
2713
2714 if (ptype->restrictions->minExclusive) {
2715 make_persistent_restriction_int(&ptype->restrictions->minExclusive);
2716 }
2717 if (ptype->restrictions->maxExclusive) {
2718 make_persistent_restriction_int(&ptype->restrictions->maxExclusive);
2719 }
2720 if (ptype->restrictions->minInclusive) {
2721 make_persistent_restriction_int(&ptype->restrictions->minInclusive);
2722 }
2723 if (ptype->restrictions->maxInclusive) {
2724 make_persistent_restriction_int(&ptype->restrictions->maxInclusive);
2725 }
2726 if (ptype->restrictions->totalDigits) {
2727 make_persistent_restriction_int(&ptype->restrictions->totalDigits);
2728 }
2729 if (ptype->restrictions->fractionDigits) {
2730 make_persistent_restriction_int(&ptype->restrictions->fractionDigits);
2731 }
2732 if (ptype->restrictions->length) {
2733 make_persistent_restriction_int(&ptype->restrictions->length);
2734 }
2735 if (ptype->restrictions->minLength) {
2736 make_persistent_restriction_int(&ptype->restrictions->minLength);
2737 }
2738 if (ptype->restrictions->maxLength) {
2739 make_persistent_restriction_int(&ptype->restrictions->maxLength);
2740 }
2741 if (ptype->restrictions->whiteSpace) {
2742 make_persistent_restriction_char_int(&ptype->restrictions->whiteSpace);
2743 }
2744 if (ptype->restrictions->pattern) {
2745 make_persistent_restriction_char_int(&ptype->restrictions->pattern);
2746 }
2747
2748 if (type->restrictions->enumeration) {
2749 sdlRestrictionCharPtr tmp, penum;
2750 ptype->restrictions->enumeration = malloc(sizeof(HashTable));
2751 zend_hash_init(ptype->restrictions->enumeration, zend_hash_num_elements(type->restrictions->enumeration), NULL, delete_restriction_var_char_persistent, 1);
2752 ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(type->restrictions->enumeration, key, tmp) {
2753 penum = tmp;
2754 make_persistent_restriction_char_int(&penum);
2755 /* We have to duplicate key emalloc->malloc */
2756 zend_hash_str_add_ptr(ptype->restrictions->enumeration, ZSTR_VAL(key), ZSTR_LEN(key), penum);
2757 } ZEND_HASH_FOREACH_END();
2758 }
2759 }
2760
2761 if (ptype->elements) {
2762 sdlTypePtr tmp, pelem;
2763
2764 ptype->elements = malloc(sizeof(HashTable));
2765 zend_hash_init(ptype->elements, zend_hash_num_elements(type->elements), NULL, delete_type_persistent, 1);
2766
2767 ZEND_HASH_FOREACH_STR_KEY_PTR(type->elements, key, tmp) {
2768 pelem = make_persistent_sdl_type(tmp, ptr_map, bp_types, bp_encoders);
2769 if (key) {
2770 /* We have to duplicate key emalloc->malloc */
2771 zend_hash_str_add_ptr(ptype->elements, ZSTR_VAL(key), ZSTR_LEN(key), pelem);
2772 } else {
2773 zend_hash_next_index_insert_ptr(ptype->elements, pelem);
2774 }
2775 zend_hash_str_add_ptr(ptr_map, (char*)&tmp, sizeof(tmp), pelem);
2776 } ZEND_HASH_FOREACH_END();
2777 }
2778
2779 if (ptype->attributes) {
2780 sdlAttributePtr tmp, pattr;
2781
2782 ptype->attributes = malloc(sizeof(HashTable));
2783 zend_hash_init(ptype->attributes, zend_hash_num_elements(type->attributes), NULL, delete_attribute_persistent, 1);
2784
2785 ZEND_HASH_FOREACH_STR_KEY_PTR(type->attributes, key, tmp) {
2786 pattr = make_persistent_sdl_attribute(tmp, ptr_map, bp_types, bp_encoders);
2787 if (key) {
2788 /* We have to duplicate key emalloc->malloc */
2789 zend_hash_str_add_ptr(ptype->attributes, ZSTR_VAL(key), ZSTR_LEN(key), pattr);
2790 } else {
2791 zend_hash_next_index_insert_ptr(ptype->attributes, pattr);
2792 }
2793 } ZEND_HASH_FOREACH_END();
2794 }
2795
2796 if (type->model) {
2797 ptype->model = make_persistent_sdl_model(ptype->model, ptr_map, bp_types, bp_encoders);
2798 }
2799
2800 return ptype;
2801 }
2802
make_persistent_sdl_encoder(encodePtr enc,HashTable * ptr_map,HashTable * bp_types,HashTable * bp_encoders)2803 static encodePtr make_persistent_sdl_encoder(encodePtr enc, HashTable *ptr_map, HashTable *bp_types, HashTable *bp_encoders)
2804 {
2805 encodePtr penc = NULL;
2806
2807 penc = malloc(sizeof(encode));
2808 memset(penc, 0, sizeof(encode));
2809
2810 *penc = *enc;
2811
2812 if (penc->details.type_str) {
2813 penc->details.type_str = strdup(penc->details.type_str);
2814 }
2815 if (penc->details.ns) {
2816 penc->details.ns = strdup(penc->details.ns);
2817 penc->details.clark_notation = zend_string_dup(penc->details.clark_notation, 1);
2818 }
2819
2820 if (penc->details.sdl_type) {
2821 make_persistent_sdl_type_ref(&penc->details.sdl_type, ptr_map, bp_types);
2822 }
2823
2824 return penc;
2825 }
2826
make_persistent_sdl_binding(sdlBindingPtr bind,HashTable * ptr_map)2827 static sdlBindingPtr make_persistent_sdl_binding(sdlBindingPtr bind, HashTable *ptr_map)
2828 {
2829 sdlBindingPtr pbind = NULL;
2830
2831 pbind = malloc(sizeof(sdlBinding));
2832 memset(pbind, 0, sizeof(sdlBinding));
2833
2834 *pbind = *bind;
2835
2836 if (pbind->name) {
2837 pbind->name = strdup(pbind->name);
2838 }
2839 if (pbind->location) {
2840 pbind->location = strdup(pbind->location);
2841 }
2842
2843 if (pbind->bindingType == BINDING_SOAP && pbind->bindingAttributes) {
2844 sdlSoapBindingPtr soap_binding;
2845
2846 soap_binding = malloc(sizeof(sdlSoapBinding));
2847 memset(soap_binding, 0, sizeof(sdlSoapBinding));
2848 *soap_binding = *(sdlSoapBindingPtr)pbind->bindingAttributes;
2849 pbind->bindingAttributes = soap_binding;
2850 }
2851
2852 return pbind;
2853 }
2854
make_persistent_sdl_function(sdlFunctionPtr func,HashTable * ptr_map)2855 static sdlFunctionPtr make_persistent_sdl_function(sdlFunctionPtr func, HashTable *ptr_map)
2856 {
2857 sdlFunctionPtr pfunc = NULL;
2858
2859 pfunc = malloc(sizeof(sdlFunction));
2860 memset(pfunc, 0, sizeof(sdlFunction));
2861
2862 *pfunc = *func;
2863
2864 if (pfunc->functionName) {
2865 pfunc->functionName = strdup(pfunc->functionName);
2866 }
2867 if (pfunc->requestName) {
2868 pfunc->requestName = strdup(pfunc->requestName);
2869 }
2870 if (pfunc->responseName) {
2871 pfunc->responseName = strdup(pfunc->responseName);
2872 }
2873
2874 if (pfunc->binding) {
2875 sdlBindingPtr tmp;
2876
2877 if ((tmp = zend_hash_str_find_ptr(ptr_map, (char*)&pfunc->binding, sizeof(pfunc->binding))) == NULL) {
2878 assert(0);
2879 }
2880 pfunc->binding = tmp;
2881
2882 if (pfunc->binding->bindingType == BINDING_SOAP && pfunc->bindingAttributes) {
2883 sdlSoapBindingFunctionPtr soap_binding;
2884
2885 soap_binding = malloc(sizeof(sdlSoapBindingFunction));
2886 memset(soap_binding, 0, sizeof(sdlSoapBindingFunction));
2887 *soap_binding = *(sdlSoapBindingFunctionPtr)pfunc->bindingAttributes;
2888 if (soap_binding->soapAction) {
2889 soap_binding->soapAction = strdup(soap_binding->soapAction);
2890 }
2891 make_persistent_sdl_soap_body(&soap_binding->input, ptr_map);
2892 make_persistent_sdl_soap_body(&soap_binding->output, ptr_map);
2893 pfunc->bindingAttributes = soap_binding;
2894 }
2895
2896 if (pfunc->requestParameters) {
2897 pfunc->requestParameters = make_persistent_sdl_parameters(pfunc->requestParameters, ptr_map);
2898 }
2899 if (pfunc->responseParameters) {
2900 pfunc->responseParameters = make_persistent_sdl_parameters(pfunc->responseParameters, ptr_map);
2901 }
2902 if (pfunc->faults) {
2903 pfunc->faults = make_persistent_sdl_function_faults(pfunc, pfunc->faults, ptr_map);
2904 }
2905 }
2906
2907 return pfunc;
2908 }
2909
make_persistent_sdl(sdlPtr sdl)2910 static sdlPtr make_persistent_sdl(sdlPtr sdl)
2911 {
2912 sdlPtr psdl = NULL;
2913 HashTable ptr_map;
2914 HashTable bp_types, bp_encoders;
2915 zend_string *key;
2916
2917 zend_hash_init(&bp_types, 0, NULL, NULL, 0);
2918 zend_hash_init(&bp_encoders, 0, NULL, NULL, 0);
2919 zend_hash_init(&ptr_map, 0, NULL, NULL, 0);
2920
2921 psdl = malloc(sizeof(*sdl));
2922 memset(psdl, 0, sizeof(*sdl));
2923
2924 if (sdl->source) {
2925 psdl->source = strdup(sdl->source);
2926 }
2927 if (sdl->target_ns) {
2928 psdl->target_ns = strdup(sdl->target_ns);
2929 }
2930
2931 if (sdl->groups) {
2932 sdlTypePtr tmp;
2933 sdlTypePtr ptype;
2934
2935 psdl->groups = malloc(sizeof(HashTable));
2936 zend_hash_init(psdl->groups, zend_hash_num_elements(sdl->groups), NULL, delete_type_persistent, 1);
2937
2938 ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(sdl->groups, key, tmp) {
2939 ptype = make_persistent_sdl_type(tmp, &ptr_map, &bp_types, &bp_encoders);
2940 if (key) {
2941 /* We have to duplicate key emalloc->malloc */
2942 zend_hash_str_add_ptr(psdl->groups, ZSTR_VAL(key), ZSTR_LEN(key), ptype);
2943 } else {
2944 zend_hash_next_index_insert_ptr(psdl->groups, ptype);
2945 }
2946 zend_hash_str_add_ptr(&ptr_map, (char*)&tmp, sizeof(tmp), ptype);
2947 } ZEND_HASH_FOREACH_END();
2948 }
2949
2950 if (sdl->types) {
2951 sdlTypePtr tmp;
2952 sdlTypePtr ptype;
2953
2954 psdl->types = malloc(sizeof(HashTable));
2955 zend_hash_init(psdl->types, zend_hash_num_elements(sdl->types), NULL, delete_type_persistent, 1);
2956
2957 ZEND_HASH_FOREACH_STR_KEY_PTR(sdl->types, key, tmp) {
2958 ptype = make_persistent_sdl_type(tmp, &ptr_map, &bp_types, &bp_encoders);
2959 if (key) {
2960 /* We have to duplicate key emalloc->malloc */
2961 zend_hash_str_add_ptr(psdl->types, ZSTR_VAL(key), ZSTR_LEN(key), ptype);
2962 } else {
2963 zend_hash_next_index_insert_ptr(psdl->types, ptype);
2964 }
2965 zend_hash_str_add_ptr(&ptr_map, (char*)&tmp, sizeof(tmp), ptype);
2966 } ZEND_HASH_FOREACH_END();
2967 }
2968
2969 if (sdl->elements) {
2970 sdlTypePtr tmp;
2971 sdlTypePtr ptype;
2972
2973 psdl->elements = malloc(sizeof(HashTable));
2974 zend_hash_init(psdl->elements, zend_hash_num_elements(sdl->elements), NULL, delete_type_persistent, 1);
2975
2976 ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(sdl->elements, key, tmp) {
2977 ptype = make_persistent_sdl_type(tmp, &ptr_map, &bp_types, &bp_encoders);
2978 if (key) {
2979 /* We have to duplicate key emalloc->malloc */
2980 zend_hash_str_add_ptr(psdl->elements, ZSTR_VAL(key), ZSTR_LEN(key), ptype);
2981 } else {
2982 zend_hash_next_index_insert_ptr(psdl->elements, ptype);
2983 }
2984 zend_hash_str_add_ptr(&ptr_map, (char*)&tmp, sizeof(tmp), ptype);
2985 } ZEND_HASH_FOREACH_END();
2986 }
2987
2988 if (sdl->encoders) {
2989 encodePtr tmp;
2990 encodePtr penc;
2991
2992 psdl->encoders = malloc(sizeof(HashTable));
2993 zend_hash_init(psdl->encoders, zend_hash_num_elements(sdl->encoders), NULL, delete_encoder_persistent, 1);
2994
2995 ZEND_HASH_FOREACH_STR_KEY_PTR(sdl->encoders, key, tmp) {
2996 penc = make_persistent_sdl_encoder(tmp, &ptr_map, &bp_types, &bp_encoders);
2997 if (key) {
2998 /* We have to duplicate key emalloc->malloc */
2999 zend_hash_str_add_ptr(psdl->encoders, ZSTR_VAL(key), ZSTR_LEN(key), penc);
3000 } else {
3001 zend_hash_next_index_insert_ptr(psdl->encoders, penc);
3002 }
3003 zend_hash_str_add_ptr(&ptr_map, (char*)&tmp, sizeof(tmp), penc);
3004 } ZEND_HASH_FOREACH_END();
3005 }
3006
3007 /* do backpatching here */
3008 if (zend_hash_num_elements(&bp_types)) {
3009 sdlTypePtr *tmp, ptype = NULL;
3010
3011 ZEND_HASH_FOREACH_PTR(&bp_types, tmp) {
3012 if ((ptype = zend_hash_str_find_ptr(&ptr_map, (char*)tmp, sizeof(*tmp))) == NULL) {
3013 assert(0);
3014 }
3015 *tmp = ptype;
3016 } ZEND_HASH_FOREACH_END();
3017 }
3018 if (zend_hash_num_elements(&bp_encoders)) {
3019 encodePtr *tmp, penc = NULL;
3020
3021 ZEND_HASH_FOREACH_PTR(&bp_encoders, tmp) {
3022 if ((penc = zend_hash_str_find_ptr(&ptr_map, (char*)tmp, sizeof(*tmp))) == NULL) {
3023 assert(0);
3024 }
3025 *tmp = penc;
3026 } ZEND_HASH_FOREACH_END();
3027 }
3028
3029
3030 if (sdl->bindings) {
3031 sdlBindingPtr tmp;
3032 sdlBindingPtr pbind;
3033
3034 psdl->bindings = malloc(sizeof(HashTable));
3035 zend_hash_init(psdl->bindings, zend_hash_num_elements(sdl->bindings), NULL, delete_binding_persistent, 1);
3036
3037 ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(sdl->bindings, key, tmp) {
3038 pbind = make_persistent_sdl_binding(tmp, &ptr_map);
3039 if (key) {
3040 /* We have to duplicate key emalloc->malloc */
3041 zend_hash_str_add_ptr(psdl->bindings, ZSTR_VAL(key), ZSTR_LEN(key), pbind);
3042 } else {
3043 zend_hash_next_index_insert_ptr(psdl->bindings, pbind);
3044 }
3045 zend_hash_str_add_ptr(&ptr_map, (char*)&tmp, sizeof(tmp), pbind);
3046 } ZEND_HASH_FOREACH_END();
3047 }
3048
3049 zend_hash_init(&psdl->functions, zend_hash_num_elements(&sdl->functions), NULL, delete_function_persistent, 1);
3050 if (zend_hash_num_elements(&sdl->functions)) {
3051 sdlFunctionPtr tmp;
3052 sdlFunctionPtr pfunc;
3053
3054 ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(&sdl->functions, key, tmp) {
3055 pfunc = make_persistent_sdl_function(tmp, &ptr_map);
3056 if (key) {
3057 /* We have to duplicate key emalloc->malloc */
3058 zend_hash_str_add_ptr(&psdl->functions, ZSTR_VAL(key), ZSTR_LEN(key), pfunc);
3059 } else {
3060 zend_hash_next_index_insert_ptr(&psdl->functions, pfunc);
3061 }
3062 zend_hash_str_add_ptr(&ptr_map, (char*)&tmp, sizeof(tmp), pfunc);
3063 } ZEND_HASH_FOREACH_END();
3064 }
3065
3066 if (sdl->requests) {
3067 zval *zv;
3068 sdlFunctionPtr tmp;
3069 sdlFunctionPtr preq;
3070
3071 psdl->requests = malloc(sizeof(HashTable));
3072 zend_hash_init(psdl->requests, zend_hash_num_elements(sdl->requests), NULL, NULL, 1);
3073
3074 ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(sdl->requests, key, zv) {
3075 tmp = Z_PTR_P(zv);
3076 if ((preq = zend_hash_str_find_ptr(&ptr_map, (char*)&tmp, sizeof(tmp))) == NULL) {
3077 assert(0);
3078 }
3079 Z_PTR_P(zv) = preq;
3080 if (key) {
3081 /* We have to duplicate key emalloc->malloc */
3082 zend_hash_str_add_ptr(psdl->requests, ZSTR_VAL(key), ZSTR_LEN(key), preq);
3083 }
3084 } ZEND_HASH_FOREACH_END();
3085 }
3086
3087 zend_hash_destroy(&ptr_map);
3088 zend_hash_destroy(&bp_encoders);
3089 zend_hash_destroy(&bp_types);
3090
3091 return psdl;
3092 }
3093
3094 typedef struct _sdl_cache_bucket {
3095 sdlPtr sdl;
3096 time_t time;
3097 } sdl_cache_bucket;
3098
delete_psdl_int(sdl_cache_bucket * p)3099 static void delete_psdl_int(sdl_cache_bucket *p)
3100 {
3101 sdlPtr tmp = p->sdl;
3102
3103 zend_hash_destroy(&tmp->functions);
3104 if (tmp->source) {
3105 free(tmp->source);
3106 }
3107 if (tmp->target_ns) {
3108 free(tmp->target_ns);
3109 }
3110 if (tmp->elements) {
3111 zend_hash_destroy(tmp->elements);
3112 free(tmp->elements);
3113 }
3114 if (tmp->encoders) {
3115 zend_hash_destroy(tmp->encoders);
3116 free(tmp->encoders);
3117 }
3118 if (tmp->types) {
3119 zend_hash_destroy(tmp->types);
3120 free(tmp->types);
3121 }
3122 if (tmp->groups) {
3123 zend_hash_destroy(tmp->groups);
3124 free(tmp->groups);
3125 }
3126 if (tmp->bindings) {
3127 zend_hash_destroy(tmp->bindings);
3128 free(tmp->bindings);
3129 }
3130 if (tmp->requests) {
3131 zend_hash_destroy(tmp->requests);
3132 free(tmp->requests);
3133 }
3134 free(tmp);
3135 }
3136
delete_psdl(zval * zv)3137 static void delete_psdl(zval *zv)
3138 {
3139 delete_psdl_int(Z_PTR_P(zv));
3140 free(Z_PTR_P(zv));
3141 }
3142
get_sdl(zval * this_ptr,char * uri,zend_long cache_wsdl)3143 sdlPtr get_sdl(zval *this_ptr, char *uri, zend_long cache_wsdl)
3144 {
3145 char fn[MAXPATHLEN];
3146 sdlPtr sdl = NULL;
3147 char* old_error_code = SOAP_GLOBAL(error_code);
3148 size_t uri_len = 0;
3149 php_stream_context *context=NULL;
3150 zval *tmp, orig_context, new_context;
3151 smart_str headers = {0};
3152 char* key = NULL;
3153 time_t t = time(0);
3154 bool has_proxy_authorization = 0;
3155 bool has_authorization = 0;
3156
3157 ZVAL_UNDEF(&orig_context);
3158 ZVAL_UNDEF(&new_context);
3159 if (strchr(uri,':') != NULL || IS_ABSOLUTE_PATH(uri, uri_len)) {
3160 uri_len = strlen(uri);
3161 } else if (VCWD_REALPATH(uri, fn) == NULL) {
3162 cache_wsdl = WSDL_CACHE_NONE;
3163 } else {
3164 uri = fn;
3165 uri_len = strlen(uri);
3166 }
3167
3168 if ((cache_wsdl & WSDL_CACHE_MEMORY) && SOAP_GLOBAL(mem_cache)) {
3169 sdl_cache_bucket *p;
3170
3171 if (NULL != (p = zend_hash_str_find_ptr(SOAP_GLOBAL(mem_cache), uri, uri_len))) {
3172 if (p->time < t - SOAP_GLOBAL(cache_ttl)) {
3173 /* in-memory cache entry is expired */
3174 zend_hash_str_del(&EG(persistent_list), uri, uri_len);
3175 } else {
3176 return p->sdl;
3177 }
3178 }
3179 }
3180
3181 if ((cache_wsdl & WSDL_CACHE_DISK) && (uri_len < MAXPATHLEN)) {
3182 time_t t = time(0);
3183 char md5str[33];
3184 PHP_MD5_CTX md5_context;
3185 unsigned char digest[16];
3186 size_t len = strlen(SOAP_GLOBAL(cache_dir));
3187 time_t cached;
3188 char *user = php_get_current_user();
3189 size_t user_len = user ? strlen(user) + 1 : 0;
3190
3191 md5str[0] = '\0';
3192 PHP_MD5Init(&md5_context);
3193 PHP_MD5Update(&md5_context, (unsigned char*)uri, uri_len);
3194 PHP_MD5Final(digest, &md5_context);
3195 make_digest(md5str, digest);
3196 key = emalloc(len+sizeof("/wsdl-")-1+user_len+2+sizeof(md5str));
3197 memcpy(key,SOAP_GLOBAL(cache_dir),len);
3198 memcpy(key+len,"/wsdl-",sizeof("/wsdl-")-1);
3199 len += sizeof("/wsdl-")-1;
3200 if (user_len) {
3201 memcpy(key+len, user, user_len-1);
3202 len += user_len-1;
3203 key[len++] = '-';
3204 }
3205 if (WSDL_CACHE_VERSION <= 0x9f) {
3206 key[len++] = (WSDL_CACHE_VERSION >> 8) + '0';
3207 } else {
3208 key[len++] = (WSDL_CACHE_VERSION >> 8) - 10 + 'a';
3209 }
3210 if ((WSDL_CACHE_VERSION & 0xf) <= 0x9) {
3211 key[len++] = (WSDL_CACHE_VERSION & 0xf) + '0';
3212 } else {
3213 key[len++] = (WSDL_CACHE_VERSION & 0xf) - 10 + 'a';
3214 }
3215 memcpy(key+len,md5str,sizeof(md5str));
3216
3217 if ((sdl = get_sdl_from_cache(key, uri, uri_len, t-SOAP_GLOBAL(cache_ttl), &cached)) != NULL) {
3218 t = cached;
3219 efree(key);
3220 goto cache_in_memory;
3221 }
3222 }
3223
3224 if (instanceof_function(Z_OBJCE_P(this_ptr), soap_class_entry)) {
3225 tmp = Z_CLIENT_STREAM_CONTEXT_P(this_ptr);
3226 if (Z_TYPE_P(tmp) == IS_RESOURCE) {
3227 context = php_stream_context_from_zval(tmp, 0);
3228 /* Share a reference with new_context down below.
3229 * For new contexts, the reference is only in new_context so that doesn't need extra refcounting. */
3230 GC_ADDREF(context->res);
3231 }
3232
3233 tmp = Z_CLIENT_USER_AGENT_P(this_ptr);
3234 if (Z_TYPE_P(tmp) == IS_STRING && Z_STRLEN_P(tmp) > 0) {
3235 smart_str_appends(&headers, "User-Agent: ");
3236 smart_str_appends(&headers, Z_STRVAL_P(tmp));
3237 smart_str_appends(&headers, "\r\n");
3238 }
3239
3240 zval *proxy_host = Z_CLIENT_PROXY_HOST_P(this_ptr);
3241 zval *proxy_port = Z_CLIENT_PROXY_PORT_P(this_ptr);
3242 if (Z_TYPE_P(proxy_host) == IS_STRING && Z_TYPE_P(proxy_port) == IS_LONG) {
3243 zval str_proxy;
3244 smart_str proxy = {0};
3245 smart_str_appends(&proxy,"tcp://");
3246 smart_str_appends(&proxy,Z_STRVAL_P(proxy_host));
3247 smart_str_appends(&proxy,":");
3248 smart_str_append_long(&proxy,Z_LVAL_P(proxy_port));
3249 ZVAL_STR(&str_proxy, smart_str_extract(&proxy));
3250
3251 if (!context) {
3252 context = php_stream_context_alloc();
3253 }
3254 php_stream_context_set_option(context, "http", "proxy", &str_proxy);
3255 zval_ptr_dtor(&str_proxy);
3256
3257 if (uri_len < sizeof("https://")-1 ||
3258 strncasecmp(uri, "https://", sizeof("https://")-1) != 0) {
3259 ZVAL_TRUE(&str_proxy);
3260 php_stream_context_set_option(context, "http", "request_fulluri", &str_proxy);
3261 }
3262
3263 has_proxy_authorization = proxy_authentication(this_ptr, &headers);
3264 }
3265
3266 has_authorization = basic_authentication(this_ptr, &headers);
3267 }
3268
3269 if (!context) {
3270 context = php_stream_context_alloc();
3271 }
3272
3273 /* Use HTTP/1.1 with "Connection: close" by default */
3274 if ((tmp = php_stream_context_get_option(context, "http", "protocol_version")) == NULL) {
3275 zval http_version;
3276
3277 ZVAL_DOUBLE(&http_version, 1.1);
3278 php_stream_context_set_option(context, "http", "protocol_version", &http_version);
3279 smart_str_appendl(&headers, "Connection: close\r\n", sizeof("Connection: close\r\n")-1);
3280 }
3281
3282 if (headers.s && ZSTR_LEN(headers.s) > 0) {
3283 zval str_headers;
3284
3285 if (!context) {
3286 context = php_stream_context_alloc();
3287 } else {
3288 http_context_headers(context, has_authorization, has_proxy_authorization, 0, &headers);
3289 }
3290
3291 ZVAL_STR(&str_headers, smart_str_extract(&headers));
3292 php_stream_context_set_option(context, "http", "header", &str_headers);
3293 zval_ptr_dtor(&str_headers);
3294 }
3295
3296 if (context) {
3297 ZVAL_RES(&new_context, context->res);
3298 php_libxml_switch_context(&new_context, &orig_context);
3299 }
3300
3301 SOAP_GLOBAL(error_code) = "WSDL";
3302
3303 sdl = load_wsdl(this_ptr, uri);
3304 if (sdl) {
3305 sdl->is_persistent = 0;
3306 }
3307
3308 SOAP_GLOBAL(error_code) = old_error_code;
3309
3310 if (context) {
3311 php_libxml_switch_context(&orig_context, NULL);
3312 zval_ptr_dtor(&new_context);
3313 }
3314
3315 if ((cache_wsdl & WSDL_CACHE_DISK) && key) {
3316 if (sdl) {
3317 add_sdl_to_cache(key, uri, t, sdl);
3318 }
3319 efree(key);
3320 }
3321
3322 cache_in_memory:
3323 if (cache_wsdl & WSDL_CACHE_MEMORY) {
3324 if (sdl) {
3325 sdlPtr psdl;
3326 sdl_cache_bucket p;
3327
3328 if (SOAP_GLOBAL(mem_cache) == NULL) {
3329 SOAP_GLOBAL(mem_cache) = malloc(sizeof(HashTable));
3330 zend_hash_init(SOAP_GLOBAL(mem_cache), 0, NULL, delete_psdl, 1);
3331 } else if (SOAP_GLOBAL(cache_limit) > 0 &&
3332 SOAP_GLOBAL(cache_limit) <= (zend_long)zend_hash_num_elements(SOAP_GLOBAL(mem_cache))) {
3333 /* in-memory cache overflow */
3334 sdl_cache_bucket *q;
3335 time_t latest = t;
3336 zend_string *latest_key = NULL, *key;
3337
3338 ZEND_HASH_MAP_FOREACH_STR_KEY_PTR(SOAP_GLOBAL(mem_cache), key, q) {
3339 if (q->time < latest) {
3340 latest = q->time;
3341 latest_key = key;
3342 }
3343 } ZEND_HASH_FOREACH_END();
3344 if (latest_key) {
3345 zend_hash_del(SOAP_GLOBAL(mem_cache), latest_key);
3346 } else {
3347 return sdl;
3348 }
3349 }
3350
3351 psdl = make_persistent_sdl(sdl);
3352 psdl->is_persistent = 1;
3353 p.time = t;
3354 p.sdl = psdl;
3355
3356 zend_hash_str_update_mem(SOAP_GLOBAL(mem_cache), uri,
3357 uri_len, &p, sizeof(sdl_cache_bucket));
3358 /* remove non-persitent sdl structure */
3359 delete_sdl_impl(sdl);
3360 /* and replace it with persistent one */
3361 sdl = psdl;
3362 }
3363 }
3364
3365 return sdl;
3366 }
3367
3368 /* Deletes */
delete_sdl_impl(void * handle)3369 void delete_sdl_impl(void *handle)
3370 {
3371 sdlPtr tmp = (sdlPtr)handle;
3372
3373 zend_hash_destroy(&tmp->functions);
3374 if (tmp->source) {
3375 efree(tmp->source);
3376 }
3377 if (tmp->target_ns) {
3378 efree(tmp->target_ns);
3379 }
3380 if (tmp->elements) {
3381 zend_hash_destroy(tmp->elements);
3382 efree(tmp->elements);
3383 }
3384 if (tmp->encoders) {
3385 zend_hash_destroy(tmp->encoders);
3386 efree(tmp->encoders);
3387 }
3388 if (tmp->types) {
3389 zend_hash_destroy(tmp->types);
3390 efree(tmp->types);
3391 }
3392 if (tmp->groups) {
3393 zend_hash_destroy(tmp->groups);
3394 efree(tmp->groups);
3395 }
3396 if (tmp->bindings) {
3397 zend_hash_destroy(tmp->bindings);
3398 efree(tmp->bindings);
3399 }
3400 if (tmp->requests) {
3401 zend_hash_destroy(tmp->requests);
3402 efree(tmp->requests);
3403 }
3404 efree(tmp);
3405 }
3406
delete_sdl(sdl * handle)3407 void delete_sdl(sdl *handle)
3408 {
3409 if (!handle->is_persistent) {
3410 delete_sdl_impl(handle);
3411 }
3412 }
3413
delete_binding_ex(zval * zv,bool persistent)3414 static void delete_binding_ex(zval *zv, bool persistent)
3415 {
3416 sdlBindingPtr binding = Z_PTR_P(zv);
3417
3418 if (binding->location) {
3419 pefree(binding->location, persistent);
3420 }
3421 if (binding->name) {
3422 pefree(binding->name, persistent);
3423 }
3424
3425 if (binding->bindingType == BINDING_SOAP) {
3426 sdlSoapBindingPtr soapBind = binding->bindingAttributes;
3427 if (soapBind) {
3428 pefree(soapBind, persistent);
3429 }
3430 }
3431 pefree(binding, persistent);
3432 }
3433
delete_binding(zval * zv)3434 static void delete_binding(zval *zv)
3435 {
3436 delete_binding_ex(zv, false);
3437 }
3438
delete_binding_persistent(zval * zv)3439 static void delete_binding_persistent(zval *zv)
3440 {
3441 delete_binding_ex(zv, true);
3442 }
3443
delete_sdl_soap_binding_function_body(sdlSoapBindingFunctionBody body,bool persistent)3444 static void delete_sdl_soap_binding_function_body(sdlSoapBindingFunctionBody body, bool persistent)
3445 {
3446 if (body.ns) {
3447 pefree(body.ns, persistent);
3448 }
3449 if (body.headers) {
3450 zend_hash_destroy(body.headers);
3451 pefree(body.headers, persistent);
3452 }
3453 }
3454
delete_function_ex(zval * zv,bool persistent)3455 static void delete_function_ex(zval *zv, bool persistent)
3456 {
3457 sdlFunctionPtr function = Z_PTR_P(zv);
3458
3459 if (function->functionName) {
3460 pefree(function->functionName, persistent);
3461 }
3462 if (function->requestName) {
3463 pefree(function->requestName, persistent);
3464 }
3465 if (function->responseName) {
3466 pefree(function->responseName, persistent);
3467 }
3468 if (function->requestParameters) {
3469 zend_hash_destroy(function->requestParameters);
3470 pefree(function->requestParameters, persistent);
3471 }
3472 if (function->responseParameters) {
3473 zend_hash_destroy(function->responseParameters);
3474 pefree(function->responseParameters, persistent);
3475 }
3476 if (function->faults) {
3477 zend_hash_destroy(function->faults);
3478 pefree(function->faults, persistent);
3479 }
3480
3481 if (function->bindingAttributes &&
3482 function->binding && function->binding->bindingType == BINDING_SOAP) {
3483 sdlSoapBindingFunctionPtr soapFunction = function->bindingAttributes;
3484 if (soapFunction->soapAction) {
3485 pefree(soapFunction->soapAction, persistent);
3486 }
3487 delete_sdl_soap_binding_function_body(soapFunction->input, persistent);
3488 delete_sdl_soap_binding_function_body(soapFunction->output, persistent);
3489 pefree(soapFunction, persistent);
3490 }
3491 pefree(function, persistent);
3492 }
3493
delete_function(zval * zv)3494 static void delete_function(zval *zv)
3495 {
3496 delete_function_ex(zv, false);
3497 }
3498
delete_function_persistent(zval * zv)3499 static void delete_function_persistent(zval *zv)
3500 {
3501 delete_function_ex(zv, true);
3502 }
3503
delete_parameter_ex(zval * zv,bool persistent)3504 static void delete_parameter_ex(zval *zv, bool persistent)
3505 {
3506 sdlParamPtr param = Z_PTR_P(zv);
3507 if (param->paramName) {
3508 pefree(param->paramName, persistent);
3509 }
3510 pefree(param, persistent);
3511 }
3512
delete_parameter(zval * zv)3513 static void delete_parameter(zval *zv)
3514 {
3515 delete_parameter_ex(zv, false);
3516 }
3517
delete_parameter_persistent(zval * zv)3518 static void delete_parameter_persistent(zval *zv)
3519 {
3520 delete_parameter_ex(zv, true);
3521 }
3522
delete_header_int_ex(sdlSoapBindingFunctionHeaderPtr hdr,bool persistent)3523 static void delete_header_int_ex(sdlSoapBindingFunctionHeaderPtr hdr, bool persistent)
3524 {
3525 if (hdr->name) {
3526 pefree(hdr->name, persistent);
3527 }
3528 if (hdr->ns) {
3529 pefree(hdr->ns, persistent);
3530 }
3531 if (hdr->headerfaults) {
3532 zend_hash_destroy(hdr->headerfaults);
3533 pefree(hdr->headerfaults, persistent);
3534 }
3535 pefree(hdr, persistent);
3536 }
3537
delete_header_int(sdlSoapBindingFunctionHeaderPtr hdr)3538 static void delete_header_int(sdlSoapBindingFunctionHeaderPtr hdr)
3539 {
3540 delete_header_int_ex(hdr, false);
3541 }
3542
delete_header(zval * zv)3543 static void delete_header(zval *zv)
3544 {
3545 sdlSoapBindingFunctionHeaderPtr hdr = Z_PTR_P(zv);
3546 delete_header_int_ex(hdr, false);
3547 }
3548
delete_header_persistent(zval * zv)3549 static void delete_header_persistent(zval *zv)
3550 {
3551 sdlSoapBindingFunctionHeaderPtr hdr = Z_PTR_P(zv);
3552 delete_header_int_ex(hdr, true);
3553 }
3554
delete_fault_ex(zval * zv,bool persistent)3555 static void delete_fault_ex(zval *zv, bool persistent)
3556 {
3557 sdlFaultPtr fault = Z_PTR_P(zv);
3558 if (fault->name) {
3559 pefree(fault->name, persistent);
3560 }
3561 if (fault->details) {
3562 zend_hash_destroy(fault->details);
3563 pefree(fault->details, persistent);
3564 }
3565 if (fault->bindingAttributes) {
3566 sdlSoapBindingFunctionFaultPtr binding = (sdlSoapBindingFunctionFaultPtr)fault->bindingAttributes;
3567
3568 if (binding->ns) {
3569 pefree(binding->ns, persistent);
3570 }
3571 pefree(fault->bindingAttributes, persistent);
3572 }
3573 pefree(fault, persistent);
3574 }
3575
delete_fault(zval * zv)3576 static void delete_fault(zval *zv)
3577 {
3578 delete_fault_ex(zv, false);
3579 }
3580
delete_fault_persistent(zval * zv)3581 static void delete_fault_persistent(zval *zv)
3582 {
3583 delete_fault_ex(zv, true);
3584 }
3585
delete_document(zval * zv)3586 static void delete_document(zval *zv)
3587 {
3588 xmlDocPtr doc = Z_PTR_P(zv);
3589 xmlFreeDoc(doc);
3590 }
3591