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