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