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