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