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