1 /*
2  * Copyright 1999-2006 University of Chicago
3  * 
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  * 
8  * http://www.apache.org/licenses/LICENSE-2.0
9  * 
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "globus_common.h"
18
19
20 #ifndef IN_LIBXML
21 #define IN_LIBXML
22 #include "libxml/xmlerror.h"
23 #undef  IN_LIBXML
24 #else
25 #include "libxml/xmlerror.h"
26 #endif
27
28 #include <string.h>
29 #include "libxml/xmlschemas.h"
30 #include "wsdl.h"
31 #include "libxml/parserInternals.h"
32 #include "libxml/uri.h"
33
34 const CONST_NODE WSDL_DEFINITIONS_NODE = {WSDL_NS, "definitions"};
35 const CONST_NODE WSDL_TYPES_NODE       = {WSDL_NS, "types"};
36 const CONST_NODE WSDL_MESSAGE_NODE     = {WSDL_NS, "message"};
37 const CONST_NODE WSDL_PART_NODE        = {WSDL_NS, "part"};
38 const CONST_NODE WSDL_PORTTYPE_NODE    = {WSDL_NS, "portType"};
39 const CONST_NODE WSDL_OPERATION_NODE   = {WSDL_NS, "operation"};
40 const CONST_NODE WSDL_INPUT_NODE       = {WSDL_NS, "input"};
41 const CONST_NODE WSDL_OUTPUT_NODE      = {WSDL_NS, "output"};
42 const CONST_NODE WSDL_FAULT_NODE       = {WSDL_NS, "fault"};
43 const CONST_NODE WSDL_BINDING_NODE     = {WSDL_NS, "binding"};
44 const CONST_NODE WSDL_SERVICE_NODE     = {WSDL_NS, "service"};
45 const CONST_NODE WSDL_PORT_NODE        = {WSDL_NS, "port"};
46 const CONST_NODE WSDL_IMPORT_NODE      = {WSDL_NS, "import"};
47 const CONST_NODE WSDL_DOCUMENTATION_NODE
48                                        = {WSDL_NS, "documentation"};
49
50 const CONST_NODE SOAP_BINDING_NODE     = {SOAP_NS, "binding"};
51 const CONST_NODE SOAP_OPERATION_NODE   = {SOAP_NS, "operation"};
52 const CONST_NODE SOAP_BODY_NODE        = {SOAP_NS, "body"};
53 const CONST_NODE SOAP_HEADER_NODE      = {SOAP_NS, "header"};
54 const CONST_NODE SOAP_FAULT_NODE       = {SOAP_NS, "fault"};
55 const CONST_NODE SOAP_ADDRESS_NODE     = {SOAP_NS, "address"};
56
57 const CONST_NODE XSD_SCHEMA_NODE       = {XSD_NS, "schema"};
58 const CONST_NODE XSD_IMPORT_NODE       = {XSD_NS, "import"};
59
60 const CONST_NODE WSRP_RESOURCE_PROPERTIES_NODE = 
61                                          {WSRP_NS, "ResourceProperties"};
62
63 /**
64  * xmlSchemaIsBlank:
65  * @str:  a string
66  *
67  * Check if a string is ignorable
68  *
69  * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
70  */
71
72 /* copied from xmlschemas.c */
73
74 static int
75 xmlSchemaIsBlank(xmlChar * str)
76 0 {
77 0     if (str == NULL)
78 0         return (1);
79 0     while (*str != 0) {
80 0         if (!(IS_BLANK_CH(*str)))
81 0             return (0);
82 0         str++;
83     }
84 0     return (1);
85 }
86
87 #define IS_BLANK_NODE(n) \
88     (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
89
90 static
91 void
92 wsdlGenericError(wsdlParserCtxtPtr ctxt, xmlNodePtr node, int error,
93           const char *msg, const xmlChar * str1, const xmlChar * str2);
94
95 static
96 int
97 xmlCompareNodeConst(xmlNodePtr node, const CONST_NODE comp);
98
99 static
100 int
101 GetChildNode(const xmlNodePtr node, CONST_NODE child, xmlNodePtr * childNode);
102
103 static
104 const xmlChar *
105 wsdlGetProp(
106     wsdlParserCtxtPtr                   ctxt, 
107     xmlNodePtr                          node, 
108     const char *                        name);
109
110 static const xmlChar *
111 wsdlGetQNameProp(
112     wsdlParserCtxtPtr                   ctxt,
113     xmlNodePtr                          node,
114     const char *                        name,
115     const xmlChar **                    Namespace);
116
117 static void
118 wsdlErrorMemory(wsdlParserCtxtPtr ctxt,
119                 const char *extra, xmlNodePtr node);
120
121 static void
122 wsdlParserError(wsdlParserCtxtPtr ctxt, xmlNodePtr node, int error,
123                 const char *msg, const xmlChar * str1, const xmlChar * str2,
124                 const char *file, int line);
125
126 static
127 int
128 wsdlParseInternal(wsdlParserCtxtPtr     ctxt);
129
130 static void
131 wsdlCleanupDoc(wsdlParserCtxtPtr ctxt, xmlNodePtr root);
132
133 static
134 wsdlSchemaPtr
135 wsdlNewSchema(wsdlParserCtxtPtr         ctxt);
136
137 static
138 wsdlSchemaPtr
139 wsdlDoParse(wsdlParserCtxtPtr           ctxt,
140             wsdlSchemaPtr               schema,
141             xmlNodePtr                  node);
142
143 static wsdlPortPtr
144 wsdlParsePort(
145     wsdlParserCtxtPtr                   ctxt,
146     wsdlSchemaPtr                       schema,
147     xmlNodePtr                          node);
148
149 static
150 void *
151 wsdlParseSoapOperation(
152     wsdlParserCtxtPtr                   ctxt,
153     wsdlSchemaPtr                       schema,
154     xmlNodePtr                          node);
155
156 static
157 void *
158 wsdlParseSoapBindingParam(
159     wsdlParserCtxtPtr                   ctxt,
160     wsdlSchemaPtr                       schema,
161     xmlNodePtr                          node);
162
163 static
164 void
165 wsdlSoapBindingParamFree(
166     soapBindingParamPtr             param);
167
168 static
169 soapBindingPtr
170 wsdlParseSoapBinding(
171     wsdlParserCtxtPtr                   ctxt,
172     wsdlSchemaPtr                       schema,
173     xmlNodePtr                          node);
174
175 static
176 void
177 wsdlBindingOperationFaultFree(
178     wsdlBindingOperationFaultPtr        bopf);
179
180
181 static
182 void
183 wsdlBindingOperationFree(
184     wsdlBindingOperationPtr             bop);
185
186 static wsdlBindingPtr
187 wsdlParseBinding(
188     wsdlParserCtxtPtr                   ctxt,
189     wsdlSchemaPtr                       schema,
190     xmlNodePtr                          node);
191
192 static
193 void
194 wsdlFaultFree(
195     wsdlFaultPtr                        fault);
196
197 static 
198 void
199 wsdlBindingFree(
200     wsdlBindingPtr                      binding);
201
202 static 
203 void
204 wsdlBindingHEFree(
205     void *                              value,
206     xmlChar *                           name);
207
208 static
209 void
210 wsdlPortFree(
211     wsdlPortPtr                         port);
212
213 static wsdlServicePtr
214 wsdlParseService(
215     wsdlParserCtxtPtr                   ctxt,
216     wsdlSchemaPtr                       schema,
217     xmlNodePtr                          node);
218
219 static
220 void
221 wsdlServiceFree(
222     wsdlServicePtr                      service);
223
224 static
225 void
226 wsdlServiceHEFree(
227     void *                              value,
228     xmlChar *                           name);
229
230 static
231 int
232 wsdlParseTypes(wsdlParserCtxtPtr        ctxt,
233                wsdlSchemaPtr            schema,
234                xmlNodePtr               node);
235
236 static        
237 wsdlPartPtr
238 wsdlParsePart(wsdlParserCtxtPtr         ctxt,
239               wsdlSchemaPtr             schema,
240               xmlNodePtr                node);
241
242 static
243 void
244 wsdlPartFree(
245     wsdlPartPtr                         part);
246
247 static
248 wsdlMessagePtr
249 wsdlParseMessage(wsdlParserCtxtPtr      ctxt,
250                  wsdlSchemaPtr          schema,
251                  xmlNodePtr             node);
252
253 static
254 void
255 wsdlMessageFree(
256     wsdlMessagePtr                      message);
257
258 static
259 void
260 wsdlMessageHEFree(
261     void *                              value,
262     xmlChar *                           name);
263
264 static
265 wsdlParserCtxtPtr
266 wsdlParseImport(wsdlParserCtxtPtr       ctxt,
267                 wsdlSchemaPtr           schema,
268                 xmlNodePtr              node);
269
270 static
271 int
272 wsdlParseSchemaImport(wsdlParserCtxtPtr ctxt,
273                       wsdlSchemaPtr     schema,
274                       xmlNodePtr        node);
275
276 static
277 wsdlParamPtr
278 wsdlParseParam(wsdlParserCtxtPtr        ctxt,
279                wsdlSchemaPtr            schema,
280                xmlNodePtr               node);
281
282 static
283 wsdlOperationPtr
284 wsdlParseOperation(wsdlParserCtxtPtr    ctxt,
285                    wsdlSchemaPtr        schema,
286                    xmlNodePtr           node);
287
288 static
289 void
290 wsdlOperationFree(
291     wsdlOperationPtr                    op);
292
293 static
294 wsdlPortTypePtr
295 wsdlParsePortType(wsdlParserCtxtPtr     ctxt,
296                   wsdlSchemaPtr         schema,
297                   xmlNodePtr            node);
298
299 static
300 void
301 wsdlPortTypeFree(
302     wsdlPortTypePtr                     portType);
303
304 static
305 void
306 wsdlPortTypeHEFree(
307     void *                              value,
308     xmlChar *                           name);
309
310 static
311 int
312 wsdlParseTopLevel(wsdlParserCtxtPtr     ctxt,
313                   wsdlSchemaPtr         schema,
314                   xmlNodePtr            node);
315
316 static
317 int
318 wsdlParseImports(wsdlParserCtxtPtr     ctxt,
319                   wsdlSchemaPtr         schema,
320                   xmlNodePtr            node);
321
322 static
323 void
324 wsdlCreateTypesHashScanner(
325     void *                              import_payload,
326     void *                              data,
327     xmlChar *                           schema_namespace);
328
329 xmlChar *
330 globus_i_wsdl_my_strtok(
331     const char *                        str,
332     size_t                              str_length,
333     int *                               token_start_index,
334     int *                               token_end_index,
335     const char *                        delims)
336 0 {
337 0     const char *                        locator;
338 0     const char *                        start_token;
339 0     int                                 delim_count, ind, i, between_tokens, len;
340 0     char *                              new_token = NULL;
341 0     ind = 0;
342 0     i = 0;
343 0     between_tokens = 0;
344 0     delim_count = strlen(delims);
345 0     locator = str;
346     
347 0     for(i = 0; i < delim_count; ++i)
348     {
349 0         if(*locator == delims[i])
350         {
351 0             between_tokens = 1;
352         }
353     }
354
355 0     while(between_tokens && locator && ind < str_length)
356     {
357 0         for(i = 0; i < delim_count; ++i)
358         {
359 0             if(*locator == delims[i])
360             {
361 0                 break;
362             }
363         }
364
365 0         if(i == delim_count)
366         {
367 0             between_tokens = 0;
368 0             break;
369         }
370
371 0         locator++;
372 0         ind++;
373     }
374
375 0     start_token = locator;
376 0     if(token_start_index)
377     {
378 0         *token_start_index = ind;
379     }
380
381 0     while(!between_tokens && *locator && ind < str_length)
382     {
383 0         for(i = 0; i < delim_count; ++i)
384         {
385 0             if(*locator == delims[i])
386             {
387 0                 if(token_end_index)
388                 {
389 0                     *token_end_index = ind;
390                 }
391 0                 between_tokens = 1;
392 0                 break;
393             }
394         }
395
396 0         locator++;
397 0         ind++;
398     }
399
400 0     if(ind == str_length)
401     {
402 0         *token_end_index = -1;
403     }
404     else
405     {
406 0         ind--;
407     }
408
409 0     len = ind + (str - start_token);
410 0     if(len > 0)
411     {
412 0         new_token = malloc(len+1);
413 0         memcpy(new_token, start_token, len + 1);
414 0         new_token[len] = '\0';
415     }
416
417 0     return (xmlChar *) new_token;
418 }
419
420 int
421 globus_i_wsdl_split_qnames(
422     const xmlChar *                     default_namespace,
423     xmlNodePtr                          node,
424     const xmlChar *                     qname_string,
425     xsdQNamePtr *                       qnames)
426 0 {
427 0     xmlChar *                           prefix;
428 0     const xmlChar *                     rpns;
429 0     char *                              tmpstr;
430 0     char *                              newstr;
431 0     xmlChar *                           local;
432 0     int                                 start_token;
433 0     int                                 end_token;
434 0     xmlChar *                              token;
435 0     xsdQNamePtr                         qn = NULL;
436
437 0     newstr = globus_libc_strdup((const char *) qname_string);
438 0     tmpstr = newstr;
439 0     token = globus_i_wsdl_my_strtok(tmpstr, strlen(tmpstr), &start_token, &end_token, "\n\t ");
440 0     tmpstr += end_token;
441         
442 0     while(1)
443     {
444 0         xsdQNamePtr                     new_qn;
445 0         xmlNsPtr                        ns;
446
447 0         local = xmlSplitQName2(token, &prefix);
448 0         if(!prefix)
449         {
450 0             if(default_namespace)
451             {
452 0                 rpns = default_namespace;
453             }
454             else
455             {
456 0                 ns = xmlSearchNs(node->doc, node, prefix);
457 0                 rpns = (xmlChar *) ns->href;
458             }
459         }
460         else
461         {
462 0             ns = xmlSearchNs(node->doc, node, prefix);
463 0             rpns = (xmlChar *) ns->href;
464         }
465
466 0         if(!local)
467         {
468 0             local = xmlStrdup(token);
469         }
470
471 0         new_qn = xmlMalloc(sizeof(xsdQName));
472 0         memset(new_qn, 0, sizeof(xsdQName));
473
474 0         new_qn->name = local;
475 0         new_qn->Namespace = rpns;
476 0         new_qn->next = qn;
477 0         qn = new_qn;
478
479 0         free(token);
480 0         if(end_token < 0)
481         {
482 0             break;
483         }
484
485 0         token = globus_i_wsdl_my_strtok(tmpstr, strlen(tmpstr), &start_token, &end_token, "\n\t ");
486 0         tmpstr += end_token;
487 0         if(!token)
488         {
489 0             break;
490         }
491
492     }
493
494 0     *qnames = qn;
495 0     globus_free(newstr);
496 0     return 0;
497 }
498
499 void
500 xsdQNameFree(
501     xsdQNamePtr                         qname)
502 0 {
503 0     if(qname)
504     {
505 0         if(qname->next)
506         {
507 0             xsdQNameFree(qname->next);
508         }
509
510 0         xmlFree(qname);
511     }
512 }
513         
514
515 static
516 int
517 xmlCompareNodeConst(xmlNodePtr node, const CONST_NODE comp)
518 0 {
519 0     if(!node || !node->name)
520     {
521 0         return -1;
522     }
523
524 0     if(!xmlStrEqual(node->name, (const xmlChar *) comp.name))
525     {
526 0         return -1;
527     }
528
529 0     if(!node->ns)
530     {
531 0         return -1;
532     }
533
534 0     if(!xmlStrEqual(node->ns->href, (const xmlChar *) comp.ns))
535     {
536 0         return -1;
537     }
538
539 0     return 0;
540 }
541
542 static
543 int
544 GetChildNode(const xmlNodePtr node, CONST_NODE child, xmlNodePtr * childNode)
545 0 {
546 0     xmlNodePtr                          tmpNode;
547
548 0     if(!node || !node->children)
549     {
550 0         return -1;
551     }
552
553 0     tmpNode = node->children;
554 0     while(tmpNode)
555     {
556 0         if(tmpNode->type == XML_ELEMENT_NODE &&
557            !xmlCompareNodeConst(tmpNode, child))
558         {
559 0             break;
560         }
561         else
562         {
563 0             tmpNode = tmpNode->next;
564         }
565     }
566
567 0     if(!tmpNode)
568     {
569 0         return -1;
570     }
571
572 0     *childNode = tmpNode;
573 0     return 0;
574 }
575
576 static
577 const xmlChar *
578 wsdlGetProp(
579     wsdlParserCtxtPtr                   ctxt, 
580     xmlNodePtr                          node, 
581     const char *                        name)
582 0 {
583 0     xmlChar *                           val;
584 0     const xmlChar *                     ret;
585     
586 0     val = xmlGetProp(node, BAD_CAST name);
587 0     if(val == NULL)
588     {
589 0         return (NULL);
590     }
591
592 0     ret = xmlDictLookup(ctxt->dict, val, -1);
593 0     xmlFree(val);
594 0     return(ret);
595 }
596
597 static const xmlChar *
598 wsdlGetQNameProp(
599     wsdlParserCtxtPtr                   ctxt,
600     xmlNodePtr                          node,
601     const char *                        name,
602     const xmlChar **                    Namespace)
603 0 {
604 0     const xmlChar *                     val;
605 0     xmlNsPtr                            ns;
606 0     const xmlChar *                     ret;
607 0     const xmlChar *                     prefix;
608 0     int                                 len;
609
610 0     *Namespace = NULL;
611 0     val = wsdlGetProp(ctxt, node, name);
612 0     if(val == NULL)
613     {
614 0         return (NULL);
615     }
616     
617 0     ret = xmlSplitQName3(val, &len);
618 0     if(ret == NULL)
619     {
620 0         return (val);
621     }
622
623 0     ret = xmlDictLookup(ctxt->dict, ret, -1);
624 0     prefix = xmlDictLookup(ctxt->dict, val, len);
625
626 0     ns = xmlSearchNs(node->doc, node, prefix);
627 0     if(ns == NULL)
628     {
629 0         wsdlGenericError(ctxt, node, WSDL_ERR_PREFIX_UNDEFINED,
630                  "Attribute %s: the QName prefix %s is undefined\n",
631                  (const xmlChar *) name, prefix);
632     }
633     else
634     {
635 0         *Namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
636     }
637
638 0     return (ret);
639 }
640
641 /**
642  * wsdlSetParserErrors:
643  * @ctxt:  a schema validation context
644  * @err:  the error callback
645  * @warn:  the warning callback
646  * @ctx:  contextual data for the callbacks
647  *
648  * Set the callback functions used to handle errors for a validation context
649  */
650 void
651 wsdlSetParserErrors(wsdlParserCtxtPtr ctxt,
652                     wsdlErrorFunc err,
653                     wsdlWarningFunc warn, void *ctx)
654 0 {
655 0     if (ctxt == NULL)
656 0         return;
657 0     ctxt->err = err;
658 0     ctxt->warn = warn;
659 0     ctxt->userData = ctx;
660 }
661
662 /**
663  * wsdlErrorMemory:
664  * @node: a context node
665  * @extra:  extra informations
666  *
667  * Handle an out of memory condition
668  */
669 static void
670 wsdlErrorMemory(wsdlParserCtxtPtr ctxt,
671                 const char *extra, xmlNodePtr node)
672 0 {
673 0     if (ctxt != NULL)
674 0         ctxt->nberrors++;
675 0     __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
676                      extra);
677 }
678
679 /**
680  * wsdlError:
681  * @ctxt: the parsing context
682  * @node: the context node
683  * @error: the error code
684  * @msg: the error message
685  * @str1: extra data
686  * @str2: extra data
687  * 
688  * Handle a parser error
689  */
690 static void
691 wsdlGenericError(wsdlParserCtxtPtr ctxt, xmlNodePtr node, int error,
692           const char *msg, const xmlChar * str1, const xmlChar * str2)
693 0 {
694 0     xmlGenericErrorFunc channel = NULL;
695 0     xmlStructuredErrorFunc schannel = NULL;
696 0     void *data = NULL;
697
698 0     if (ctxt != NULL) {
699 0         ctxt->nberrors++;
700 0         channel = ctxt->err;
701 0         data = ctxt->userData;
702     }
703 0     __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
704                     error, XML_ERR_ERROR, NULL, 0,
705                     (const char *) str1, (const char *) str2, NULL, 0, 0,
706                     msg, str1, str2);
707 }
708
709 static void
710 wsdlParserError(wsdlParserCtxtPtr ctxt, xmlNodePtr node, int error,
711                 const char *msg, const xmlChar * str1, const xmlChar * str2,
712                 const char *file, int line)
713 0 {
714 0     xmlGenericErrorFunc channel = NULL;
715 0     xmlStructuredErrorFunc schannel = NULL;
716 0     void *data = NULL;
717
718 0     if (ctxt != NULL) {
719 0         ctxt->nberrors++;
720 0         channel = ctxt->err;
721 0         data = ctxt->userData;
722     }
723 0     __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
724                     error, XML_ERR_ERROR, file, (line != -1) ? line : 0,
725                     (const char *) str1, (const char *) str2, NULL, 0, 0,
726                     msg, str1, str2);
727 }    
728
729 wsdlParserCtxtPtr
730 wsdlNewParserCtxt(
731     const char *                        URL)
732 0 {
733 0     wsdlParserCtxtPtr                   ret;
734
735 0     if(URL == NULL)
736     {
737 0         return (NULL);
738     }
739
740 0     ret = (wsdlParserCtxtPtr) xmlMalloc(sizeof(wsdlParserCtxt));
741 0     if(ret == NULL)
742     {
743 0         wsdlErrorMemory(NULL, "allocating wsdl parser context", NULL);
744 0         return (NULL);
745     }
746
747 0     memset(ret, 0, sizeof(wsdlParserCtxt));
748 0     ret->dict = xmlDictCreate();
749 0     if(!ret->dict)
750     {
751 0         wsdlGenericError(ret, NULL, WSDL_ERR_DICT, "creating dictionary for context",
752                   NULL, NULL);
753 0         xmlFree(ret);
754 0         return (NULL);
755     }
756     
757 0     ret->url = (xmlChar *) xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
758 0     return (ret);
759 }
760
761 wsdlParserCtxtPtr
762 wsdlNewMemParserCtxt(
763     const char *                        buffer,
764     int                                 size)
765 0 {
766 0     wsdlParserCtxtPtr                   ret;
767
768 0     if((buffer == NULL) || (size <= 0))
769     {
770 0         return (NULL);
771     }
772
773 0     ret = (wsdlParserCtxtPtr) xmlMalloc(sizeof(wsdlParserCtxt));
774 0     if(ret == NULL)
775     {
776 0         wsdlErrorMemory(NULL, "allocating wsdl parser context", NULL);
777 0         return (NULL);
778     }
779 0     memset(ret, 0, sizeof(wsdlParserCtxt));
780 0     ret->buffer = (char *) buffer;
781 0     ret->size = size;
782 0     ret->dict = xmlDictCreate();
783 0     if(!ret->dict)
784     {
785 0         xmlFree(ret);
786 0         return (NULL);
787     }
788
789 0     return (ret);
790 }
791
792 wsdlParserCtxtPtr
793 wsdlNewDocParserCtxt(
794     xmlDocPtr                           doc)
795 0 {
796 0     wsdlParserCtxtPtr                   ret;
797
798 0     if(doc == NULL)
799     {
800 0         return (NULL);
801     }
802
803 0     ret = (wsdlParserCtxtPtr) xmlMalloc(sizeof(wsdlParserCtxt));
804 0     if(ret == NULL)
805     {
806 0         wsdlErrorMemory(NULL, "allocating wsdl parser context", NULL);
807 0         return (NULL);
808     }
809 0     memset(ret, 0, sizeof(wsdlParserCtxt));
810 0     ret->doc = doc;
811 0     ret->dict = xmlDictCreate();
812 0     if(!ret->dict)
813     {
814 0         xmlFree(ret);
815 0         return (NULL);
816     }
817
818 0     ret->preserve = 1;
819     
820 0     return (ret);
821 }
822
823 void
824 wsdlFreeParserCtxt(wsdlParserCtxtPtr    ctxt)
825 0 {
826 0     if(ctxt == NULL)
827     {
828 0         return;
829     }
830
831 0     if(ctxt->doc != NULL && !ctxt->preserve)
832     {
833 0         xmlFreeDoc(ctxt->doc);
834     }
835 0     xmlDictFree(ctxt->dict);
836 0     xmlFree(ctxt);
837 }
838
839 static
840 int
841 wsdlParseInternal(wsdlParserCtxtPtr     ctxt)
842 0 {
843 0     if (ctxt->url != NULL) {
844 0         ctxt->doc = xmlReadFile((const char *) ctxt->url, NULL, 
845                                 XML_PARSE_NOENT);
846 0         if (ctxt->doc == NULL) {
847 0     wsdlGenericError(ctxt, NULL,
848                      WSDL_ERR_FAILED_LOAD,
849                      "wsdlParseInternal: could not load %s\n", 
850                      ctxt->url, NULL);
851 0             return -1;
852         }
853 0     } else if (ctxt->buffer != NULL) {
854 0         ctxt->doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
855                                   XML_PARSE_NOENT);
856 0         if (ctxt->doc == NULL) {
857 0     wsdlGenericError(ctxt, NULL,
858                      WSDL_ERR_FAILED_PARSE,
859                      "wsdlParseInternal: could not parse\n",
860                      NULL, NULL);
861 0             return -1;
862         }
863 0         ctxt->doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
864 0         ctxt->url = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
865 0     } else if (ctxt->doc != NULL) {
866 0 ctxt->preserve = 1;
867     } else {
868 0 wsdlGenericError(ctxt, NULL,
869                  WSDL_ERR_NOTHING_TO_PARSE,
870                  "wsdlParseInternal: could not parse\n",
871                  NULL, NULL);
872 0         return -1;
873     }
874
875 0     return 0;
876 }
877
878 /**
879  * unashamedly copied from xmlSchemaCleanupDoc
880  */
881 static void
882 wsdlCleanupDoc(wsdlParserCtxtPtr ctxt, xmlNodePtr root)
883 0 {
884 0     xmlNodePtr delete, cur;
885
886 0     if ((ctxt == NULL) || (root == NULL)) return;
887
888     /*
889      * Remove all the blank text nodes
890      */
891 0     delete = NULL;
892 0     cur = root;
893 0     while (cur != NULL) {
894 0         if (delete != NULL) {
895 0             xmlUnlinkNode(delete);
896 0             xmlFreeNode(delete);
897 0             delete = NULL;
898         }
899 0         if (cur->type == XML_TEXT_NODE) {
900 0             if (IS_BLANK_NODE(cur)) {
901 0                 if (xmlNodeGetSpacePreserve(cur) != 1) {
902 0                     delete = cur;
903                 }
904             }
905 0         } else if ((cur->type != XML_ELEMENT_NODE) &&
906                    (cur->type != XML_CDATA_SECTION_NODE)) {
907 0             delete = cur;
908 0             goto skip_children;
909         }
910
911         /*
912          * Skip to next node
913          */
914 0         if (cur->children != NULL) {
915 0             if ((cur->children->type != XML_ENTITY_DECL) &&
916                 (cur->children->type != XML_ENTITY_REF_NODE) &&
917                 (cur->children->type != XML_ENTITY_NODE)) {
918 0                 cur = cur->children;
919 0                 continue;
920             }
921         }
922       skip_children:
923 0         if (cur->next != NULL) {
924 0             cur = cur->next;
925 0             continue;
926         }
927
928 0         do {
929 0             cur = cur->parent;
930 0             if (cur == NULL)
931 0                 break;
932 0             if (cur == root) {
933 0                 cur = NULL;
934 0                 break;
935             }
936 0             if (cur->next != NULL) {
937 0                 cur = cur->next;
938 0                 break;
939             }
940 0         } while (cur != NULL);
941     }
942 0     if (delete != NULL) {
943 0         xmlUnlinkNode(delete);
944 0         xmlFreeNode(delete);
945 0         delete = NULL;
946     }
947 }
948
949 static
950 wsdlSchemaPtr
951 wsdlNewSchema(wsdlParserCtxtPtr         ctxt)
952 0 {
953 0     wsdlSchemaPtr                       ret;
954
955 0     ret = (wsdlSchemaPtr) xmlMalloc(sizeof(wsdlSchema));
956 0     if(ret == NULL)
957     {
958 0         wsdlErrorMemory(ctxt, "allocating schema", NULL);
959 0         return (NULL);
960     }
961 0     memset(ret, 0, sizeof(wsdlSchema));
962 0     xmlDictReference(ctxt->dict);
963 0     ret->dict = ctxt->dict;
964 0     ctxt->schema = ret;
965 0     return (ret);
966 }
967     
968
969 static
970 wsdlSchemaPtr
971 wsdlDoParse(wsdlParserCtxtPtr           ctxt,
972             wsdlSchemaPtr               outer_schema,
973             xmlNodePtr                  node)
974 0 {
975 0     wsdlSchemaPtr                       schema = NULL;
976 0     xmlNodePtr                          child = NULL;
977 0     int                                 nberrors = 0;
978 0     const xmlChar *                     val = NULL;
979 0     int                                 res;
980     
981 0     if((ctxt == NULL) || (node == NULL))
982     {
983 0         return (NULL);
984     }
985
986 0     nberrors = ctxt->nberrors;
987 0     ctxt->nberrors = 0;
988
989 0     if(node->type == XML_ELEMENT_NODE &&
990        !xmlCompareNodeConst(node, WSDL_DEFINITIONS_NODE))
991     {
992 0         schema = wsdlNewSchema(ctxt);
993 0         if(schema == NULL)
994         {
995 0             return (NULL);
996         }
997
998 0         val = wsdlGetProp(ctxt, node, "targetNamespace");
999 0         if(val != NULL)
1000         {
1001 0             schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
1002         }
1003
1004 0         child = node->children;
1005 0         while(child)
1006         {
1007 0             res = wsdlParseImports(ctxt, schema, child);
1008 0             if(res != 0)
1009             {
1010 0                 return (NULL);
1011             }
1012 0             child = child->next;
1013         }
1014
1015 0         child = node->children;
1016 0         while(child)
1017         {
1018 0             res = wsdlParseTopLevel(ctxt, schema, child);
1019 0             if(res != 0)
1020             {
1021 0                 long                            lno = xmlGetLineNo(node);
1022 0                 wsdlParserError(ctxt, node,
1023                                 WSDL_ERR_NOT_WSDL,
1024                                 "Failed to parse top level element: %s",
1025                                 child->name, NULL,
1026                                 (const char *) ctxt->url, lno);
1027 0                 return (NULL);
1028             }
1029 0             child = child->next;
1030         }
1031     }
1032 0     else if(node->type == XML_ELEMENT_NODE &&
1033             !xmlCompareNodeConst(node, XSD_SCHEMA_NODE))
1034     {
1035 0         if(!outer_schema)
1036         {
1037 0             long                        lno = xmlGetLineNo(node);
1038 0             wsdlParserError(ctxt, node,
1039                             WSDL_ERR_NOT_WSDL,
1040                             "Parser failed to find a 'definitions' element"
1041                             " in the document.  A 'schema' element appears "
1042                             "to be outermost node in the document",
1043                             NULL, NULL, (const char *) ctxt->url, lno);
1044 0             return (NULL);
1045         }
1046
1047 0         res = wsdlParseTypes(ctxt, outer_schema, node->parent);
1048 0         if(res != 0)
1049         {
1050 0             long                            lno = xmlGetLineNo(node);
1051 0             wsdlParserError(ctxt, node,
1052                             WSDL_ERR_NOT_WSDL,
1053                             "Failed to parser types in schema",
1054                             NULL, NULL, (const char *) ctxt->url, lno);
1055 0             return (NULL);
1056         }
1057     }
1058     else
1059     {
1060 0         long                            lno = xmlGetLineNo(node);
1061 0         wsdlParserError(ctxt, node,
1062                         WSDL_ERR_NOT_WSDL,
1063                         "no 'definitions' element",
1064                         NULL, NULL, (const char *) ctxt->url, lno);
1065 0         return (NULL);
1066     }
1067
1068 0     if(ctxt->nberrors != 0)
1069     {
1070 0         if(schema != NULL)
1071         {
1072 0             wsdlSchemaFree(schema);
1073 0             schema = NULL;
1074         }
1075     }
1076 0     ctxt->nberrors = nberrors;
1077 #ifdef DEBUG
1078     if(schema == NULL)
1079     {
1080         xmlGenericError(xmlGenericErrorContext,
1081                         "wsdlDoParse() failed\n");
1082     }
1083 #endif
1084     
1085 0     return (schema);
1086 }
1087
1088 wsdlSchemaPtr
1089 wsdlParse(wsdlParserCtxtPtr             ctxt)
1090 0 {
1091 0     int                                 res;
1092 0     wsdlSchemaPtr                       ret = NULL;
1093 0     xmlNodePtr                          root;
1094     
1095 0     res = wsdlParseInternal(ctxt);
1096 0     if(res != 0)
1097     {
1098 0         return NULL;
1099     }
1100     
1101 0     root = xmlDocGetRootElement(ctxt->doc);
1102 0     if(root == NULL)
1103     {
1104 0         wsdlParserError(ctxt, (xmlNodePtr) ctxt->doc,
1105                         WSDL_ERR_NOROOT,
1106                         "wsdl document has no root", 
1107                         NULL, NULL, (const char *) ctxt->url, 0);
1108 0         if(!ctxt->preserve)
1109         {
1110 0             xmlFreeDoc(ctxt->doc);
1111         }
1112 0         return (NULL);
1113     }
1114
1115 0     wsdlCleanupDoc(ctxt, root);
1116
1117 0     ret = wsdlDoParse(ctxt, NULL, root);
1118 0     if(ret == NULL)
1119     {
1120 0         return (NULL);
1121     }
1122
1123 0     return (ret);
1124 }
1125
1126 wsdlSchemaPtr
1127 wsdlParseXmlSchema(wsdlParserCtxtPtr             ctxt)
1128 0 {
1129 0     xmlSchemaParserCtxtPtr              xmlschema_context = NULL;
1130 0     wsdlSchemaPtr                       schema = NULL;
1131     
1132 0     schema = wsdlNewSchema(ctxt);
1133 0     if(schema == NULL)
1134     {
1135 0         return (NULL);
1136     }
1137
1138 0     xmlschema_context = xmlSchemaNewParserCtxt((const char *) ctxt->url);
1139 0     xmlSchemaSetParserErrors(xmlschema_context, 
1140                              (xmlSchemaValidityErrorFunc) ctxt->err, 
1141                              (xmlSchemaValidityWarningFunc) ctxt->warn, 
1142                              ctxt->userData);
1143         
1144 0     schema->schemaTypes = xmlSchemaParse(xmlschema_context, NULL);
1145 0     xmlSchemaFreeParserCtxt(xmlschema_context);
1146
1147 0     return (schema);
1148 }
1149
1150 static wsdlPortPtr
1151 wsdlParsePort(
1152     wsdlParserCtxtPtr                   ctxt,
1153     wsdlSchemaPtr                       schema,
1154     xmlNodePtr                          node)
1155 0 {
1156 0     xmlNodePtr                          tmpNode;
1157 0     xmlNodePtr                          childNode;
1158 0     wsdlPortPtr                         port = NULL;
1159 0     const xmlChar *                     binding_name;
1160 0     const xmlChar *                     binding_ns;
1161
1162 0     tmpNode = node;
1163
1164 0     if((ctxt == NULL) || (schema == NULL))
1165     {
1166 0         return (NULL);
1167     }
1168     
1169 0     port = (wsdlPortPtr) xmlMalloc(sizeof(wsdlPort));
1170 0     if(!port)
1171     {
1172 0         wsdlErrorMemory(ctxt, "allocating port", NULL);
1173 0         return (NULL);
1174     }
1175 0     memset(port, 0, sizeof(wsdlPort));
1176 0     port->node = tmpNode;
1177 0     port->name = wsdlGetProp(ctxt, tmpNode, "name");
1178 0     binding_name = wsdlGetQNameProp(ctxt, tmpNode, "binding", &binding_ns);
1179 0     port->binding = wsdlFindBinding(ctxt, schema, binding_name, binding_ns);
1180 0     if(!port->binding)
1181     {
1182 0         long                            lno = xmlGetLineNo(node);
1183 0         wsdlParserError(ctxt, node,
1184                         WSDL_ERR_NO_NODE,
1185                         "reference to binding {%s}%s could not be qualified",
1186                         binding_ns, binding_name, (const char *)ctxt->url, lno);
1187 0         xmlFree(port);
1188 0         return (NULL);
1189     }
1190
1191 0     childNode = tmpNode->children;
1192
1193 0     while(childNode)
1194     {
1195 0         if(childNode &&
1196                 !xmlCompareNodeConst(childNode, WSDL_DOCUMENTATION_NODE))
1197         {
1198 0             childNode = childNode->next;
1199         }
1200 0         else if(childNode && !xmlCompareNodeConst(childNode, SOAP_ADDRESS_NODE))
1201         {
1202 0             soapAddressPtr                  soap_addr;
1203             
1204 0             port->extensionType = SOAP_BINDING;
1205 0             soap_addr = (soapAddressPtr) xmlMalloc(sizeof(soapAddress));
1206 0             if(!soap_addr)
1207             {
1208 0                 wsdlPortFree(port);
1209 0                 return (NULL);
1210             }
1211 0             memset(soap_addr, 0, sizeof(soapAddress));
1212             
1213 0             soap_addr->location = wsdlGetProp(ctxt, childNode, "location");
1214 0             if(!soap_addr->location)
1215             {
1216 0                 long                        lno = xmlGetLineNo(childNode);
1217 0                 wsdlParserError(ctxt, childNode, WSDL_ERR_SOAP_BINDING,
1218                                 "no location 'attribute' found for soap address element",
1219                                 NULL, NULL, (const char *) ctxt->url, lno);
1220 0                 wsdlPortFree(port);
1221 0                 return (NULL);
1222             }
1223
1224 0             soap_addr->node = childNode;
1225
1226 0             port->extension = (void *) soap_addr;
1227
1228 0             return (port);
1229         }
1230         else
1231         {
1232 0             long                        lno = xmlGetLineNo(childNode);
1233 0             wsdlParserError(ctxt, childNode, WSDL_ERR_SOAP_BINDING,
1234                             "unexpected child of port element",
1235                             NULL, NULL, (const char *) ctxt->url, lno);
1236 0             wsdlPortFree(port);
1237 0             return (NULL);
1238         }
1239     }
1240 0     return port;
1241 }
1242
1243 static
1244 void
1245 wsdlPortFree(
1246     wsdlPortPtr                         port)
1247 0 {
1248 0     if(port)
1249     {
1250 0         if(port->next)
1251         {
1252 0             wsdlPortFree(port->next);
1253         }
1254
1255 0         if(port->extension)
1256         {
1257 0             if(port->extensionType == SOAP_BINDING)
1258             {
1259 0                 xmlFree(port->extension);
1260             }
1261         }
1262
1263 0         xmlFree(port);
1264     }
1265 }
1266         
1267 static
1268 void *
1269 wsdlParseSoapOperation(
1270     wsdlParserCtxtPtr                   ctxt,
1271     wsdlSchemaPtr                       schema,
1272     xmlNodePtr                          node)
1273 0 {
1274 0     soapOperationPtr                    soap_op;
1275 0     const xmlChar *                     style;
1276
1277 0     soap_op = (soapOperationPtr) xmlMalloc(sizeof(soapOperation));
1278 0     if(!soap_op)
1279     {
1280 0         wsdlErrorMemory(ctxt, "allocationg soap operation", NULL);
1281 0         return (NULL);
1282     }
1283
1284 0     soap_op->soapAction = wsdlGetProp(ctxt, node, "soapAction");
1285 0     style = wsdlGetProp(ctxt, node, "style");
1286 0     if(style)
1287     {
1288 0         if(xmlStrEqual(style, (const xmlChar *) "rpc"))
1289         {
1290 0             soap_op->style = RPC_STYLE;
1291         }
1292 0         else if(xmlStrEqual(style, (const xmlChar *) "document"))
1293         {
1294 0             soap_op->style = DOCUMENT_STYLE;
1295         }
1296     }
1297
1298 0     soap_op->node = node;
1299
1300 0     return (soap_op);
1301 }
1302
1303 static
1304 void *
1305 wsdlParseSoapBindingParam(
1306     wsdlParserCtxtPtr                   ctxt,
1307     wsdlSchemaPtr                       schema,
1308     xmlNodePtr                          node)
1309 0 {
1310 0     xmlNodePtr                          tmpNode;
1311 0     soapBindingParamPtr                 soap_param;
1312
1313 0     soap_param = (soapBindingParamPtr) xmlMalloc(sizeof(soapBindingParam));
1314 0     if(!soap_param)
1315     {
1316 0         wsdlErrorMemory(ctxt, "allocating soap binding param", NULL);
1317 0         return (NULL);
1318     }
1319 0     memset(soap_param, 0, sizeof(soapBindingParam));
1320
1321 0     tmpNode = node;
1322
1323 0     while(tmpNode)
1324     {
1325 0         if(!xmlCompareNodeConst(tmpNode, SOAP_BODY_NODE))
1326         {
1327 0             soapBodyPtr                     soap_body;
1328 0             const xmlChar *                 use;
1329
1330 0             if(soap_param->body)
1331             {
1332 0                 long                    lno = xmlGetLineNo(tmpNode);
1333 0                 wsdlParserError(ctxt, tmpNode,
1334                                 WSDL_ERR_SOAP_BINDING,
1335                                 "multiple soap body elements defined",
1336                                 NULL, NULL, (const char *) ctxt->url, lno);
1337 0                 wsdlSoapBindingParamFree(soap_param);
1338 0                 return (NULL);
1339             }
1340                 
1341 0             soap_body = (soapBodyPtr) xmlMalloc(sizeof(soapBody));
1342 0             if(!soap_body)
1343             {
1344 0                 wsdlErrorMemory(ctxt, "allocating soap body", NULL);
1345 0                 return (NULL);
1346             }
1347 0             memset(soap_body, 0, sizeof(soapBody));
1348
1349 0             soap_body->encodingStyle = wsdlGetProp(ctxt, tmpNode, "encodingStyle");
1350 0             soap_body->parts = wsdlGetProp(ctxt, tmpNode, "parts");
1351 0             use = wsdlGetProp(ctxt, tmpNode, "use");
1352         
1353 0             if(use)
1354             {
1355 0                 if(xmlStrEqual(use, (const xmlChar *) "literal"))
1356                 {
1357 0                     soap_body->use = LITERAL_USE;
1358                 }
1359 0                 else if(xmlStrEqual(use, (const xmlChar *) "encoded"))
1360                 {
1361 0                     soap_body->use = ENCODED_USE;
1362                 }
1363                 else
1364                 {
1365 0                     long                        lno = xmlGetLineNo(tmpNode);
1366 0                     wsdlParserError(ctxt, tmpNode,
1367                                     WSDL_ERR_SOAP_BINDING,
1368                                     "Unknown soap body 'use' type: %s",
1369                                     use, NULL, (const char *) ctxt->url, lno);
1370 0                     xmlFree(soap_body);
1371 0                     wsdlSoapBindingParamFree(soap_param);
1372 0                     return (NULL);
1373                 }
1374             }
1375
1376 0             soap_body->Namespace = wsdlGetProp(ctxt, tmpNode, "namespace");
1377 0             soap_body->node = tmpNode;
1378         
1379 0             soap_param->body = soap_body;
1380         }
1381 0         else if(!xmlCompareNodeConst(tmpNode, SOAP_HEADER_NODE))
1382         {
1383 0             soapHeaderPtr                   soap_header;
1384 0             const xmlChar *                 use;
1385
1386 0             if(soap_param->header)
1387             {
1388 0                 long                    lno = xmlGetLineNo(tmpNode);
1389 0                 wsdlParserError(ctxt, tmpNode,
1390                                 WSDL_ERR_SOAP_BINDING,
1391                                 "multiple soap header elements defined",
1392                                 NULL, NULL, (const char *) ctxt->url, lno);
1393 0                 wsdlSoapBindingParamFree(soap_param);
1394 0                 return (NULL);
1395             }
1396                 
1397 0             soap_header = (soapHeaderPtr) xmlMalloc(sizeof(soapHeader));
1398 0             if(!soap_header)
1399             {
1400 0                 wsdlErrorMemory(ctxt, "allocating soap header", NULL);
1401 0                 return (NULL);
1402             }
1403 0             memset(soap_header, 0, sizeof(soapHeader));
1404
1405 0             soap_header->encodingStyle = wsdlGetProp(ctxt, tmpNode, "encodingStyle");
1406 0             soap_header->parts = wsdlGetProp(ctxt, tmpNode, "parts");
1407 0             use = wsdlGetProp(ctxt, tmpNode, "use");
1408         
1409 0             if(use)
1410             {
1411 0                 if(xmlStrEqual(use, (const xmlChar *) "literal"))
1412                 {
1413 0                     soap_header->use = LITERAL_USE;
1414                 }
1415 0                 else if(xmlStrEqual(use, (const xmlChar *) "encoded"))
1416                 {
1417 0                     soap_header->use = ENCODED_USE;
1418                 }
1419                 else
1420                 {
1421 0                     long                        lno = xmlGetLineNo(tmpNode);
1422 0                     wsdlParserError(ctxt, tmpNode,
1423                                     WSDL_ERR_SOAP_BINDING,
1424                                     "Unknown soap header use type: %s",
1425                                     use, NULL, (const char *) ctxt->url, lno);
1426 0                     xmlFree(soap_header);
1427 0                     wsdlSoapBindingParamFree(soap_param);
1428 0                     return (NULL);
1429                 }
1430             }
1431
1432 0             soap_header->Namespace = wsdlGetProp(ctxt, tmpNode, "namespace");
1433 0             soap_header->node = tmpNode;
1434         
1435 0             soap_param->header = soap_header;
1436         }
1437 0         else if(!xmlCompareNodeConst(tmpNode, SOAP_FAULT_NODE))
1438         {
1439 0             soapFaultPtr                soap_fault;
1440 0             const xmlChar *             use;
1441
1442 0             soap_fault = (soapFaultPtr) xmlMalloc(sizeof(soapFault));
1443 0             if(!soap_fault)
1444             {
1445 0                 wsdlErrorMemory(ctxt, "allocating soap header", NULL);
1446 0                 return (NULL);
1447             }
1448 0             memset(soap_fault, 0, sizeof(soapFault));
1449
1450 0             soap_fault->encodingStyle = wsdlGetProp(ctxt, tmpNode, "encodingStyle");
1451 0             use = wsdlGetProp(ctxt, tmpNode, "use");
1452         
1453 0             if(use)
1454             {
1455 0                 if(xmlStrEqual(use, (const xmlChar *) "literal"))
1456                 {
1457 0                     soap_fault->use = LITERAL_USE;
1458                 }
1459 0                 else if(xmlStrEqual(use, (const xmlChar *) "encoded"))
1460                 {
1461 0                     soap_fault->use = ENCODED_USE;
1462                 }
1463                 else
1464                 {
1465 0                     long                        lno = xmlGetLineNo(tmpNode);
1466 0                     wsdlParserError(ctxt, tmpNode,
1467                                     WSDL_ERR_SOAP_BINDING,
1468                                     "Unknown soap fault use type: %s",
1469                                     use, NULL, (const char *) ctxt->url, lno);
1470 0                     xmlFree(soap_fault);
1471 0                     wsdlSoapBindingParamFree(soap_param);
1472 0                     return (NULL);
1473                 }
1474             }
1475
1476 0             soap_fault->Namespace = wsdlGetProp(ctxt, tmpNode, "namespace");
1477 0             soap_fault->node = tmpNode;
1478         
1479 0             soap_param->fault = soap_fault;
1480         }
1481
1482 0         tmpNode = tmpNode->next;
1483     }
1484
1485 0     return (soap_param);
1486 }
1487
1488 static
1489 void
1490 wsdlSoapBindingParamFree(
1491     soapBindingParamPtr             param)
1492 0 {
1493 0     if(param)
1494     {
1495 0         if(param->header)
1496         {
1497 0             xmlFree(param->header);
1498         }
1499         
1500 0         if(param->body)
1501         {
1502 0             xmlFree(param->body);
1503         }
1504         
1505 0         if(param->fault)
1506         {
1507 0             xmlFree(param->fault);
1508         }
1509
1510 0         xmlFree(param);
1511     }
1512 }
1513
1514 static
1515 soapBindingPtr
1516 wsdlParseSoapBinding(
1517     wsdlParserCtxtPtr                   ctxt,
1518     wsdlSchemaPtr                       schema,
1519     xmlNodePtr                          node)
1520 0 {
1521 0     const xmlChar *                     style;
1522 0     soapBindingPtr                      sb;
1523
1524 0     sb = (soapBindingPtr) xmlMalloc(sizeof(soapBinding));
1525 0     if(!sb)
1526     {
1527 0         wsdlErrorMemory(ctxt, "allocating soap binding", NULL);
1528 0         return (NULL);
1529     }
1530 0     memset(sb, 0, sizeof(soapBinding));
1531
1532 0     style = wsdlGetProp(ctxt, node, "style");
1533 0     if(style)
1534     {
1535 0         if(xmlStrEqual(style, (const xmlChar *) "rpc"))
1536         {
1537 0             sb->style = RPC_STYLE;
1538         }
1539 0         else if(xmlStrEqual(style, (const xmlChar *) "document"))
1540         {
1541 0             sb->style = DOCUMENT_STYLE;
1542         }
1543         else
1544         {
1545 0             long                        lno = xmlGetLineNo(node);
1546 0             wsdlParserError(ctxt, node,
1547                             WSDL_ERR_SOAP_BINDING,
1548                             "Invalid style choice: %s for soap binding",
1549                             style, NULL, (const char *) ctxt->url, lno);
1550 0             xmlFree(sb);
1551 0             return (NULL);
1552
1553         }
1554     }
1555
1556 0     sb->transport = wsdlGetProp(ctxt, node, "transport");
1557 0     sb->node = node;
1558
1559 0     return (sb);
1560 }
1561
1562 static
1563 void
1564 wsdlBindingOperationFaultFree(
1565     wsdlBindingOperationFaultPtr        bopf)
1566 0 {
1567 0     if(bopf)
1568     {
1569 0         if(bopf->next)
1570         {
1571 0             wsdlBindingOperationFaultFree(bopf->next);
1572         }
1573
1574 0         if(bopf->extension)
1575         {
1576 0             if(bopf->extensionType == SOAP_BINDING)
1577             {
1578 0                 wsdlSoapBindingParamFree((soapBindingParamPtr) bopf->extension);
1579             }
1580         }
1581
1582 0         xmlFree(bopf);
1583     }
1584 }
1585
1586 static
1587 void
1588 wsdlBindingOperationFree(
1589     wsdlBindingOperationPtr             bop)
1590 0 {
1591 0     if(bop)
1592     {
1593 0         if(bop->next)
1594         {
1595 0             wsdlBindingOperationFree(bop->next);
1596         }
1597
1598 0         if(bop->input)
1599         {
1600 0             if(bop->inputType == SOAP_BINDING)
1601             {
1602 0                 wsdlSoapBindingParamFree(bop->input);
1603             }
1604         }
1605 0         if(bop->output)
1606         {
1607 0             if(bop->outputType == SOAP_BINDING)
1608             {
1609 0                 wsdlSoapBindingParamFree(bop->output);
1610             }
1611         }
1612 0         if(bop->faults)
1613         {
1614 0             wsdlBindingOperationFaultFree(bop->faults);
1615         }
1616 0         if(bop->extension)
1617         {
1618 0             if(bop->extensionType == SOAP_BINDING)
1619             {
1620 0                 xmlFree(bop->extension);
1621             }
1622         }
1623     }
1624 }
1625
1626 static wsdlBindingPtr
1627 wsdlParseBinding(
1628     wsdlParserCtxtPtr                   ctxt,
1629     wsdlSchemaPtr                       schema,
1630     xmlNodePtr                          node)
1631 0 {
1632 0     xmlNodePtr                          tmpNode;
1633 0     wsdlBindingPtr                      binding;
1634 0     const xmlChar *                     port_type_name;
1635 0     const xmlChar *                     port_type_ns;
1636 0     xmlNodePtr                          sb_node;
1637 0     xmlNodePtr                          childNode;
1638
1639 0     tmpNode = node;
1640
1641 0     if((ctxt == NULL) || (schema == NULL))
1642     {
1643 0         return (NULL);
1644     }
1645
1646 0     binding = xmlMalloc(sizeof(wsdlBinding));
1647 0     if(!binding)
1648     { 
1649 0         wsdlErrorMemory(ctxt, "allocating service", NULL);
1650 0         return (NULL);
1651     }
1652        
1653 0     memset(binding, 0, sizeof(wsdlService));
1654 0     binding->node = tmpNode;
1655 0     binding->name = wsdlGetProp(ctxt, tmpNode, "name");
1656 0     if(binding->name == NULL)
1657     {
1658 0         long                            lno = xmlGetLineNo(node);
1659 0         wsdlParserError(ctxt, node,
1660                         WSDL_ERR_NO_NODE,
1661                         "no 'name' attribute in binding element",
1662                         NULL, NULL, (const char *) ctxt->url, lno);
1663 0         wsdlBindingFree(binding);
1664 0         return (NULL);
1665     }
1666     
1667 0     port_type_name = wsdlGetQNameProp(ctxt, tmpNode, "type", &port_type_ns);
1668 0     binding->type = wsdlFindPortType(ctxt, 
1669                                      schema, port_type_name, port_type_ns);
1670 0     if(!binding->type)
1671     {
1672 0         long                            lno = xmlGetLineNo(node);
1673 0         wsdlParserError(ctxt, node,
1674                         WSDL_ERR_NO_NODE,
1675                         "no port type matching {%s}%s for binding element",
1676                         port_type_ns, port_type_name, (const char *) ctxt->url,
1677                         lno);
1678 0         wsdlBindingFree(binding);
1679 0         return (NULL);
1680     }
1681
1682 0     if(GetChildNode(tmpNode, SOAP_BINDING_NODE, &sb_node))
1683     {
1684 0         binding->extensionType = SOAP_BINDING;
1685 0         binding->extension = (void *) wsdlParseSoapBinding(ctxt, schema, sb_node);
1686     }
1687
1688 0     childNode = tmpNode->children;
1689 0     while(childNode)
1690     {
1691 0         xmlNodePtr                      opChildNode = NULL;
1692
1693 0         if(!xmlCompareNodeConst(childNode, WSDL_DOCUMENTATION_NODE))
1694         {
1695             /* Ignored for now */
1696         }
1697 0         else if(!xmlCompareNodeConst(childNode, SOAP_BINDING_NODE))
1698         {
1699             /* Already handled above */
1700         }
1701 0         else if(!xmlCompareNodeConst(childNode, WSDL_OPERATION_NODE))
1702         {
1703 0             wsdlBindingOperationPtr     bop;
1704 0             bop = xmlMalloc(sizeof(wsdlBindingOperation));
1705 0             if(!bop)
1706             {
1707 0                 wsdlErrorMemory(ctxt, "allocating binding operation", NULL);
1708 0                 wsdlBindingFree(binding);
1709 0                 return (NULL);
1710             }
1711 0             memset(bop, 0, sizeof(wsdlBindingOperation));
1712
1713 0             bop->name = wsdlGetProp(ctxt, childNode, "name");
1714 0             if(!bop->name)
1715             {
1716 0                 long                    lno = xmlGetLineNo(childNode);
1717 0                 wsdlParserError(ctxt, childNode,
1718                                 WSDL_ERR_BINDING,
1719                                 "the binding operation element does not "
1720                                 "have a 'name' attribute",
1721                                 NULL, NULL, (const char *) ctxt->url, lno);
1722 0                 wsdlBindingOperationFree(bop);
1723 0                 wsdlBindingFree(binding);
1724 0                 return (NULL);
1725             }
1726             
1727 0             opChildNode = childNode->children;
1728 0             while(opChildNode)
1729             {
1730 0                 if(!xmlCompareNodeConst(opChildNode, WSDL_INPUT_NODE))
1731                 {
1732 0                     xmlNodePtr          inputChildNode = opChildNode->children;
1733 0                     void *              soap_param;
1734
1735 0                     if(bop->input)
1736                     {
1737 0                         long            lno = xmlGetLineNo(opChildNode);
1738 0                         wsdlParserError(ctxt, opChildNode,
1739                                         WSDL_ERR_SOAP_BINDING,
1740                                         "Only 1 input element is allowed "
1741                                         "in the soap binding",
1742                                         NULL, NULL, (const char *) ctxt->url,
1743                                         lno);
1744 0                         wsdlBindingOperationFree(bop);
1745 0                         wsdlBindingFree(binding);
1746 0                         return (NULL);
1747                     }
1748
1749 0                     if(inputChildNode)
1750                     {
1751 0                         soap_param = wsdlParseSoapBindingParam(ctxt, 
1752                                                                schema, 
1753                                                                inputChildNode);
1754 0                         if(!soap_param)
1755                         {
1756 0                             wsdlBindingOperationFree(bop);
1757 0                             wsdlBindingFree(binding);
1758 0                             return (NULL);
1759                         }
1760
1761 0                         bop->inputType = SOAP_BINDING;
1762 0                         bop->input = soap_param;
1763                     }
1764                 }
1765 0                 if(!xmlCompareNodeConst(opChildNode, WSDL_OUTPUT_NODE))
1766                 {
1767 0                     xmlNodePtr          outputChildNode = opChildNode->children;
1768 0                     void *              soap_param;
1769
1770 0                     if(bop->output)
1771                     {
1772 0                         long            lno = xmlGetLineNo(opChildNode);
1773 0                         wsdlParserError(ctxt, opChildNode,
1774                                         WSDL_ERR_SOAP_BINDING,
1775                                         "Only 1 output element is allowed "
1776                                         "in the soap binding",
1777                                         NULL, NULL, (const char *) ctxt->url,
1778                                         lno);
1779 0                         wsdlBindingOperationFree(bop);
1780 0                         wsdlBindingFree(binding);
1781 0                         return (NULL);
1782                     }
1783
1784 0                     if(outputChildNode)
1785                     {
1786 0                         soap_param = wsdlParseSoapBindingParam(ctxt, 
1787                                                                schema, 
1788                                                                outputChildNode);
1789 0                         if(!soap_param)
1790                         {
1791 0                             wsdlBindingOperationFree(bop);
1792 0                             wsdlBindingFree(binding);
1793 0                             return (NULL);
1794                         }
1795
1796 0                         bop->outputType = SOAP_BINDING;
1797 0                         bop->output = soap_param;
1798                     }
1799                 }
1800 0                 if(!xmlCompareNodeConst(opChildNode, WSDL_FAULT_NODE))
1801                 {
1802 0                     xmlNodePtr          faultChildNode = opChildNode->children;
1803 0                     wsdlBindingOperationFaultPtr bopf;
1804 0                     void *              soap_param;
1805
1806 0                     bopf = (wsdlBindingOperationFaultPtr) xmlMalloc(
1807                         sizeof(wsdlBindingOperationFault));
1808 0                     if(!bopf)
1809                     {
1810 0                         wsdlErrorMemory(ctxt, "allocating binding operation fault",
1811                                          NULL);
1812 0                         wsdlBindingOperationFree(bop);
1813 0                         wsdlBindingFree(binding);
1814 0                         return (NULL);
1815                     }
1816 0                     memset(bopf, 0, sizeof(wsdlBindingOperationFault));
1817                     
1818 0                     bopf->name =  wsdlGetProp(ctxt, opChildNode, "name");
1819 0                     if(!bopf->name)
1820                     {
1821 0                         long            lno = xmlGetLineNo(opChildNode);
1822 0                         wsdlParserError(ctxt, opChildNode, 
1823                                         WSDL_ERR_SOAP_BINDING,
1824                                         "binding operation fault "
1825                                         "requires 'name' attribute",
1826                                         NULL, NULL, (const char *) ctxt->url,
1827                                         lno);
1828 0                         wsdlBindingOperationFaultFree(bopf);
1829 0                         wsdlBindingOperationFree(bop);
1830 0                         wsdlBindingFree(binding);
1831 0                         return (NULL);
1832                     }
1833
1834 0                     if(faultChildNode)
1835                     {
1836 0                         soap_param = wsdlParseSoapBindingParam(ctxt, 
1837                                                                schema, 
1838                                                                faultChildNode);
1839 0                         if(!soap_param)
1840                         {
1841 0                             wsdlBindingOperationFaultFree(bopf);
1842 0                             wsdlBindingOperationFree(bop);
1843 0                             wsdlBindingFree(binding);
1844 0                             return (NULL);
1845                         }
1846                         
1847 0                         bopf->extension = soap_param;
1848 0                         bopf->extensionType = SOAP_BINDING;
1849
1850 0                         bopf->next = bop->faults;
1851 0                         bop->faults = bopf;
1852                     }
1853                 }
1854                 else
1855                 {
1856 0                     if(!xmlCompareNodeConst(opChildNode, SOAP_OPERATION_NODE))
1857                     {
1858 0                         bop->extensionType = SOAP_BINDING;
1859 0                         bop->extension = wsdlParseSoapOperation(ctxt, 
1860                                                                 schema, 
1861                                                                 opChildNode);
1862 0                         if(!bop->extension)
1863                         {
1864 0                             wsdlBindingOperationFree(bop);
1865 0                             wsdlBindingFree(binding);
1866 0                             return (NULL);
1867                         }
1868                     }
1869                 }
1870
1871 0                 opChildNode = opChildNode->next;
1872             }
1873
1874 0             if(!binding->operations)
1875             {
1876 0                 binding->operations = bop;
1877             }
1878             else
1879             {
1880 0                 bop->next = binding->operations;
1881 0                 binding->operations = bop;
1882             }
1883         }
1884         else
1885         {
1886 0             long                        lno = xmlGetLineNo(childNode);
1887
1888 0             wsdlParserError(ctxt, node,
1889                             WSDL_ERR_NOT_WSDL,
1890                             "Parser failed to find an 'operation' element"
1891                             " in the binding definition.",
1892                             NULL, NULL, (const char *) ctxt->url, lno);
1893 0             return (NULL);
1894         }
1895
1896 0         childNode = childNode->next;
1897     }
1898
1899 0     binding->schema = schema;
1900 0     return (binding);
1901 }                
1902
1903 static 
1904 void
1905 wsdlBindingFree(
1906     wsdlBindingPtr                      binding)
1907 0 {
1908 0     if(binding)
1909     {
1910 0         if(binding->operations)
1911         {
1912 0             wsdlBindingOperationFree(binding->operations);
1913         }
1914
1915 0         if(binding->extension)
1916         {
1917 0             if(binding->extensionType == SOAP_BINDING)
1918             {
1919 0                 xmlFree(binding->extension);
1920             }
1921         }
1922     }
1923 }
1924
1925 static
1926 void
1927 wsdlBindingHEFree(
1928     void *                              value,
1929     xmlChar *                           name)
1930 0 {
1931 0     wsdlBindingFree((wsdlBindingPtr) value);
1932 }
1933
1934 static wsdlServicePtr
1935 wsdlParseService(
1936     wsdlParserCtxtPtr                   ctxt,
1937     wsdlSchemaPtr                       schema,
1938     xmlNodePtr                          node)
1939 0 {
1940 0     xmlNodePtr                          tmpNode;
1941 0     wsdlServicePtr                      service;
1942
1943 0     tmpNode = node;
1944
1945 0     if((ctxt == NULL) || (schema == NULL))
1946     {
1947 0         return (NULL);
1948     }
1949     
1950 0     service = (wsdlServicePtr) xmlMalloc(sizeof(wsdlService));
1951 0     if(service == NULL)
1952     {
1953 0         wsdlErrorMemory(ctxt, "allocating service", NULL);
1954 0         return (NULL);
1955     }
1956 0     memset(service, 0, sizeof(wsdlService));
1957 0     service->node = tmpNode;
1958 0     service->name = wsdlGetProp(ctxt, tmpNode, "name");
1959 0     if(service->name == NULL)
1960     {
1961 0         long                            lno = xmlGetLineNo(node);
1962 0         wsdlParserError(ctxt, node,
1963                         WSDL_ERR_NO_NODE,
1964                         "no 'name' attribute in service element",
1965                         NULL, NULL, (const char *) ctxt->url, lno);
1966 0         xmlFree(service);
1967 0         return (NULL);
1968     }
1969
1970 0     tmpNode = tmpNode->children;
1971 0     while(tmpNode)
1972     {
1973 0         if(tmpNode->type == XML_ELEMENT_NODE &&
1974             !xmlCompareNodeConst(tmpNode, WSDL_DOCUMENTATION_NODE))
1975         {
1976             /* Ignored for now */
1977         }
1978 0         else if(tmpNode->type == XML_ELEMENT_NODE &&
1979            !xmlCompareNodeConst(tmpNode, WSDL_PORT_NODE))
1980         {
1981 0             wsdlPortPtr                 port;
1982 0             port = wsdlParsePort(ctxt, schema, tmpNode);
1983 0             if(!port)
1984             {
1985 0                 xmlFree(service);
1986 0                 return (NULL);
1987             }
1988
1989 0             if(!service->ports)
1990             {
1991 0                 service->ports = port;
1992             }
1993             else
1994             {
1995 0                 port->next = service->ports;
1996 0                 service->ports = port;
1997             }
1998         }
1999         else
2000         {
2001 0             long                        lno = xmlGetLineNo(node);
2002 0             wsdlParserError(ctxt, node,
2003                             WSDL_ERR_NOT_WSDL,
2004                             "Parser failed to find an 'port' element"
2005                             " in the portType definition.",
2006                             NULL, NULL, (const char *) ctxt->url, lno);
2007 0             return (NULL);
2008         }
2009
2010 0         tmpNode = tmpNode->next;
2011     }
2012
2013 0     service->schema = schema;
2014 0     return (service);
2015 }
2016
2017 static
2018 void
2019 wsdlServiceFree(
2020     wsdlServicePtr                      service)
2021 0 {
2022 0     if(service)
2023     {
2024 0         if(service->ports)
2025         {
2026 0             wsdlPortFree(service->ports);
2027         }
2028         
2029 0         xmlFree(service);
2030     }
2031 }        
2032
2033 static
2034 void
2035 wsdlServiceHEFree(
2036     void *                              value,
2037     xmlChar *                           name)
2038 0 {
2039 0     wsdlServiceFree((wsdlServicePtr)value);
2040 }
2041
2042 static
2043 int
2044 wsdlParseTypes(wsdlParserCtxtPtr        ctxt,
2045                wsdlSchemaPtr            schema,
2046                xmlNodePtr               node)
2047 0 {
2048 0     xmlSchemaPtr                        xsd;
2049 0     xmlSchemaParserCtxtPtr              schemaCtxt;
2050 0     xmlDocPtr                           xsdDoc;
2051 0     xmlNsPtr                            tmp_ns;
2052 0     xmlNodePtr                          root;
2053 0     xmlNodePtr                          tnode;
2054
2055 0     tnode = node->children;
2056
2057 0     if(!xmlCompareNodeConst(tnode, WSDL_DOCUMENTATION_NODE))
2058     {
2059 0         tnode = tnode->next;
2060     }
2061
2062 0     if(xmlCompareNodeConst(tnode, XSD_SCHEMA_NODE))
2063     {
2064 0         long                            lno;
2065
2066 0         if(!xmlCompareNodeConst(node, XSD_SCHEMA_NODE))
2067         {
2068 0             tnode = node;
2069         }
2070         else
2071         {
2072 0             lno = xmlGetLineNo(node);
2073 0             wsdlParserError(ctxt, node,
2074                             WSDL_ERR_TYPES,
2075                             "expected 'schema' element but found '%s' instead",
2076                             NULL, NULL, (const char *) ctxt->url, lno);
2077 0             return (-1);
2078         }
2079     }
2080
2081 0     if(tnode)
2082     {
2083 0         xsdDoc = xmlNewDoc((const xmlChar *) "1.0");
2084 0         xsdDoc->children = tnode;
2085 0         root = xmlDocGetRootElement(xsdDoc);
2086
2087 0         if(root->nsDef)
2088         {
2089 0             tmp_ns = root->nsDef;
2090 0             while(tmp_ns->next)
2091             {
2092 0                 tmp_ns = tmp_ns->next;
2093             }
2094             
2095 0             tmp_ns->next = xmlCopyNamespaceList(node->nsDef);
2096         }
2097         else
2098         {
2099 0             root->nsDef = xmlCopyNamespaceList(node->nsDef);
2100 0             tmp_ns = root->nsDef;
2101         }
2102
2103 0         if(tmp_ns)
2104         {
2105 0             while(tmp_ns->next)
2106             {
2107 0                 tmp_ns = tmp_ns->next;
2108             }
2109
2110 0             tmp_ns->next = xmlCopyNamespaceList(
2111                 (node->parent ? node->parent->nsDef : node->nsDef));
2112         }
2113         else
2114         {
2115 0             root->nsDef = xmlCopyNamespaceList(
2116                 (node->parent ? node->parent->nsDef : node->nsDef));
2117         }
2118  
2119         /* need to add defined namespaces to types
2120          * doc from definitions and types */
2121         
2122 0         schemaCtxt = xmlSchemaNewDocParserCtxt(xsdDoc);
2123 0         if(!schemaCtxt)
2124         {
2125 0             return (-1);
2126         }
2127         
2128 0         xmlSchemaSetParserErrors(schemaCtxt, 
2129                                  (xmlSchemaValidityErrorFunc) ctxt->err, 
2130                                  (xmlSchemaValidityWarningFunc) ctxt->warn, 
2131                                  ctxt->userData);
2132         
2133 0         if(!schema->xmlSchemaImportsDecl)
2134         {
2135 0             schema->xmlSchemaImportsDecl = xmlHashCreate(10);
2136         }
2137
2138 0         xmlHashScan(schema->importsDecl, 
2139                     wsdlCreateTypesHashScanner, 
2140                     schema->xmlSchemaImportsDecl);
2141 0         xsd = xmlSchemaParse(schemaCtxt, schema->xmlSchemaImportsDecl); 
2142 0         if(!xsd) 
2143         { 
2144 0             return (-1); 
2145         } 
2146         
2147 0         xmlSchemaFreeParserCtxt(schemaCtxt);
2148 0         schema->schemaTypes = xsd;
2149     }
2150
2151 0     return (0);
2152 }
2153
2154 xmlSchemaElementPtr
2155 xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
2156                  const xmlChar * Namespace, int level);
2157
2158 xmlSchemaTypePtr
2159 xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
2160                  const xmlChar * Namespace);
2161
2162 typedef struct _wsdlFindType
2163 {
2164     const xmlChar *                     typeLocal;
2165     const xmlChar *                     typeNs;
2166     xmlSchemaTypePtr                    type;
2167 } * wsdlFindTypePtr;
2168
2169 static
2170 void
2171 wsdlFindTypeScanner(
2172     void *                              payload,
2173     void *                              data,
2174     xmlChar *                           name)
2175 0 {
2176 0     wsdlImportPtr                       import = (wsdlImportPtr) payload;
2177 0     wsdlFindTypePtr                     handle = (wsdlFindTypePtr) data;
2178
2179 0     if(!handle->type)
2180     {
2181 0         handle->type = xmlSchemaGetType(import->schema->schemaTypes, 
2182                                         handle->typeLocal, handle->typeNs);
2183     }
2184 }
2185
2186 xmlSchemaTypePtr
2187 wsdlFindType(wsdlParserCtxtPtr          ctxt,
2188              wsdlSchemaPtr              schema,
2189              const xmlChar *            typeLocal,
2190              const xmlChar *            typeNs)
2191 0 {
2192 0     xmlSchemaTypePtr                    type;
2193 0     struct _wsdlFindType                find_type;
2194
2195 0     type = xmlSchemaGetType(schema->schemaTypes, typeLocal, typeNs);
2196 0     if(type)
2197     {
2198 0         return (type);
2199     }
2200
2201 0     if(schema->importsDecl)
2202     {
2203 0         find_type.typeLocal = typeLocal;
2204 0         find_type.typeNs = typeNs;
2205 0         find_type.type = NULL;
2206 0         xmlHashScan(schema->importsDecl, wsdlFindTypeScanner, &find_type);
2207
2208 0         if(find_type.type)
2209         {
2210 0             return (find_type.type);
2211         }
2212     }
2213
2214 0     return (NULL);
2215 }
2216
2217 typedef struct _wsdlFindElement
2218 {
2219     const xmlChar *                     elementLocal;
2220     const xmlChar *                     elementNs;
2221     xmlSchemaElementPtr                 element;
2222 } * wsdlFindElementPtr;
2223
2224 static
2225 void
2226 wsdlFindElementScanner(
2227     void *                              payload,
2228     void *                              data,
2229     xmlChar *                           name)
2230 0 {
2231 0     wsdlImportPtr                       import = (wsdlImportPtr) payload;
2232 0     wsdlFindElementPtr                  handle = (wsdlFindElementPtr) data;
2233
2234 0     if(!handle->element)
2235     {
2236 0         handle->element = xmlSchemaGetElem(
2237             import->schema->schemaTypes, 
2238             handle->elementLocal, handle->elementNs, 1);
2239     }
2240 }
2241
2242 xmlSchemaElementPtr
2243 wsdlFindElement(wsdlParserCtxtPtr       ctxt,
2244                 wsdlSchemaPtr           schema,
2245                 const xmlChar *         elementLocal,
2246                 const xmlChar *         elementNs)
2247 0 {
2248 0     struct _wsdlFindElement             find_element;
2249 0     xmlSchemaElementPtr                 element;
2250
2251 0     element = xmlSchemaGetElem(schema->schemaTypes, elementLocal, elementNs, 1);
2252 0     if(element)
2253     {
2254 0         return (element);
2255     }
2256     
2257 0     if(schema->importsDecl)
2258     {
2259 0         find_element.elementLocal = elementLocal;
2260 0         find_element.elementNs = elementNs;
2261 0         find_element.element = NULL;
2262 0         xmlHashScan(schema->importsDecl, wsdlFindElementScanner, &find_element);
2263 0         if(find_element.element)
2264         {
2265 0             return (find_element.element);
2266         }
2267     }
2268
2269 0     return (NULL);
2270 }
2271
2272 wsdlMessagePtr
2273 wsdlFindMessage(
2274     wsdlParserCtxtPtr                   ctxt,
2275     wsdlSchemaPtr                       schema,
2276     const xmlChar *                     messageLocal,
2277     const xmlChar *                     messageNs)
2278 0 {
2279 0     wsdlImportPtr                       import;
2280 0     wsdlMessagePtr                      message;
2281
2282 0     message = xmlHashLookup2(schema->messagesDecl, messageLocal, messageNs);
2283 0     if(!message)
2284     {
2285 0         import = xmlHashLookup(schema->importsDecl, messageNs);
2286 0         if(!import)
2287         {
2288 0             return NULL;
2289         }
2290
2291 0         message = wsdlFindMessage(ctxt, import->schema, messageLocal, messageNs);
2292 0         if(!message)
2293         {
2294 0             return NULL;
2295         }
2296     }
2297
2298 0     return message;
2299 }
2300
2301 wsdlPortTypePtr
2302 wsdlFindPortType(
2303     wsdlParserCtxtPtr                   ctxt,
2304     wsdlSchemaPtr                       schema,
2305     const xmlChar *                     portTypeLocal,
2306     const xmlChar *                     portTypeNs)
2307 0 {
2308 0     wsdlImportPtr                       import;
2309 0     wsdlPortTypePtr                     portType;
2310
2311 0     portType = xmlHashLookup2(schema->portTypesDecl, portTypeLocal, portTypeNs);
2312 0     if(!portType)
2313     {
2314 0         import = xmlHashLookup(schema->importsDecl, portTypeNs);
2315 0         if(!import)
2316         {
2317 0             return NULL;
2318         }
2319
2320 0         portType = wsdlFindPortType(ctxt, import->schema, portTypeLocal, portTypeNs);
2321 0         if(!portType)
2322         {
2323 0             return NULL;
2324         }
2325     }
2326
2327 0     return portType;
2328 }
2329
2330 wsdlBindingPtr
2331 wsdlFindBinding(
2332     wsdlParserCtxtPtr                   ctxt,
2333     wsdlSchemaPtr                       schema,
2334     const xmlChar *                     bindingLocal,
2335     const xmlChar *                     bindingNs)
2336 0 {
2337 0     wsdlImportPtr                       import;
2338 0     wsdlBindingPtr                      binding;
2339
2340 0     binding = xmlHashLookup2(schema->bindingsDecl, bindingLocal, bindingNs);
2341 0     if(!binding)
2342     {
2343 0         import = xmlHashLookup(schema->importsDecl, bindingNs);
2344 0         if(!import)
2345         {
2346 0             return NULL;
2347         }
2348
2349 0         binding = wsdlFindBinding(ctxt, import->schema, bindingLocal, bindingNs);
2350 0         if(!binding)
2351         {
2352 0             return NULL;
2353         }
2354     }
2355
2356 0     return binding;
2357 }
2358
2359 wsdlServicePtr
2360 wsdlFindService(
2361     wsdlParserCtxtPtr                   ctxt,
2362     wsdlSchemaPtr                       schema,
2363     const xmlChar *                     serviceLocal,
2364     const xmlChar *                     serviceNs)
2365 0 {
2366 0     wsdlImportPtr                       import;
2367 0     wsdlServicePtr                      service;
2368
2369 0     service = xmlHashLookup2(schema->servicesDecl, serviceLocal, serviceNs);
2370 0     if(!service)
2371     {
2372 0         import = xmlHashLookup(schema->importsDecl, serviceNs);
2373 0         if(!import)
2374         {
2375 0             return NULL;
2376         }
2377
2378 0         service = wsdlFindService(ctxt, import->schema, serviceLocal, serviceNs);
2379 0         if(!service)
2380         {
2381 0             return NULL;
2382         }
2383     }
2384
2385 0     return service;
2386 }
2387
2388 static        
2389 wsdlPartPtr
2390 wsdlParsePart(wsdlParserCtxtPtr         ctxt,
2391               wsdlSchemaPtr             schema,
2392               xmlNodePtr                node)
2393 0 {
2394 0     wsdlPartPtr                         part;
2395 0     const xmlChar *                     typeLocal;
2396 0     const xmlChar *                     typeNs;
2397 0     const xmlChar *                     elementLocal;
2398 0     const xmlChar *                     elementNs;
2399     
2400 0     part = (wsdlPartPtr) xmlMalloc(sizeof(wsdlPart));
2401 0     if(!part)
2402     {
2403 0         wsdlErrorMemory(ctxt, "allocating part structure", node);
2404 0         return (NULL);
2405     }
2406 0     memset(part, 0, sizeof(wsdlPart));
2407
2408 0     part->name = wsdlGetProp(ctxt, node, "name");
2409
2410 0     part->node = node;
2411
2412 0     typeLocal = wsdlGetQNameProp(ctxt, node, "type", &typeNs);
2413 0     if(typeLocal)
2414     {
2415 0         part->type = wsdlFindType(ctxt, schema, typeLocal, typeNs);
2416 0         if(!part->type)
2417         {
2418 0             long                        lno = xmlGetLineNo(node);
2419 0             wsdlParserError(ctxt, node,
2420                             WSDL_ERR_PART, 
2421                             "WSDL part references invalid type: {%s}%s\n",
2422                             typeNs, typeLocal, (const char *) ctxt->url, lno);
2423 0             return (NULL);
2424         }
2425     }
2426
2427 0     elementLocal = wsdlGetQNameProp(ctxt, node, "element", &elementNs);
2428 0     if(elementLocal)
2429     {
2430 0         part->element = wsdlFindElement(ctxt, schema, elementLocal, elementNs);
2431 0         if(!part->element)
2432         {
2433 0             long                        lno = xmlGetLineNo(node);
2434             
2435 0             wsdlParserError(ctxt, node,
2436                      WSDL_ERR_PART, 
2437                      "WSDL part references invalid element: {%s}%s\n",
2438                      elementNs, elementLocal, (const char *) ctxt->url, lno);
2439 0             return (NULL);
2440         }
2441     }
2442
2443 0     part->node = node;
2444
2445 0     return (part);
2446 }
2447
2448 static
2449 void
2450 wsdlPartFree(
2451     wsdlPartPtr                         part)
2452 0 {
2453 0     if(part)
2454     {
2455 0         if(part->next)
2456         {
2457 0             wsdlPartFree(part->next);
2458         }
2459
2460 0         xmlFree(part);
2461     }
2462 }
2463
2464 static
2465 wsdlMessagePtr
2466 wsdlParseMessage(wsdlParserCtxtPtr      ctxt,
2467                  wsdlSchemaPtr          schema,
2468                  xmlNodePtr             node)
2469 0 {
2470 0     wsdlMessagePtr                      message;
2471 0     wsdlPartPtr                         part;
2472 0     xmlNodePtr                          partNode;
2473 0     const xmlChar *                     typename = NULL;
2474 0     const xmlChar *                     elemname = NULL;
2475     
2476 0     message = (wsdlMessagePtr) xmlMalloc(sizeof(wsdlMessage));
2477 0     if(!message)
2478     {
2479 0         wsdlErrorMemory(ctxt, "allocating message structure", node);
2480 0         return (NULL);
2481     }
2482 0     memset(message, 0, sizeof(wsdlMessage));
2483
2484 0     message->name = wsdlGetProp(ctxt, node, "name");
2485 0     if(!message->name)
2486     {
2487 0         long                            lno = xmlGetLineNo(node);
2488 0         wsdlParserError(ctxt, node,
2489                         WSDL_ERR_MESSAGE,
2490                         "The message element needs a 'name' attribute",
2491                         NULL, NULL, (const char *) ctxt->url, lno);
2492 0         wsdlMessageFree(message);
2493 0         return (NULL);
2494     }
2495
2496 0     message->node = node;
2497
2498 0     partNode = node->children;
2499 0     while(partNode)
2500     {
2501 0         if(!xmlCompareNodeConst(partNode, WSDL_DOCUMENTATION_NODE))
2502         {
2503             /* Ignored for now */
2504         }
2505 0         else if (!xmlCompareNodeConst(partNode, WSDL_PART_NODE))
2506         {
2507 0             part = wsdlParsePart(ctxt, schema, partNode);
2508 0             if(!part)
2509             {
2510 0                 wsdlMessageFree(message);
2511 0                 return (NULL);
2512             }
2513
2514 0             if(part->type && part->type->name)
2515             {
2516 0                 typename = xmlDictLookup(ctxt->dict, part->type->name, -1);
2517             }
2518
2519 0             if(part->element && part->element->name)
2520             {
2521 0                 elemname = xmlDictLookup(ctxt->dict, part->element->name, -1);
2522             }
2523
2524 0             if(!message->parts)
2525             {
2526 0                 message->parts = part;
2527             }
2528             else
2529             {
2530 0                 part->next = message->parts;
2531 0                 message->parts = part;
2532             }
2533         }
2534 0         else if(xmlCompareNodeConst(partNode, WSDL_PART_NODE))
2535         {
2536 0             long                        lno = xmlGetLineNo(partNode);
2537 0             wsdlParserError(ctxt, node, WSDL_ERR_MESSAGE,
2538                            "The subelement of the %s message is not a part",
2539                            partNode->name, NULL, (const char *) ctxt->url, lno);
2540 0             wsdlMessageFree(message);
2541 0             return (NULL);
2542         }
2543
2544 0         partNode = partNode->next;
2545     }
2546
2547 0     message->schema = schema;
2548 0     return (message);
2549 }
2550
2551 static
2552 void
2553 wsdlMessageFree(
2554     wsdlMessagePtr                      message)
2555 0 {
2556 0     if(message)
2557     {
2558 0         if(message->parts)
2559         {
2560 0             wsdlPartFree(message->parts);
2561         }
2562
2563 0         xmlFree(message);
2564     }
2565 }
2566
2567 static
2568 void
2569 wsdlMessageHEFree(
2570     void *                              value,
2571     xmlChar *                           name)
2572 0 {
2573 0     wsdlMessageFree((wsdlMessagePtr)value);
2574 }
2575
2576 static
2577 int
2578 wsdlParseSchemaImport(wsdlParserCtxtPtr ctxt,
2579                       wsdlSchemaPtr     schema,
2580                       xmlNodePtr        node)
2581 0 {
2582 0     const xmlChar *                     Namespace;
2583 0     const xmlChar *                     schemaLocation;
2584 0     const xmlChar *                     url = NULL;
2585 0     xmlSchemaImportPtr                  xsd_import;
2586 0     xmlSchemaParserCtxtPtr              newCtxt;
2587 0     xmlSchemaPtr                        xsd_schema = NULL;
2588     
2589
2590 0     Namespace = wsdlGetProp(ctxt, node, "location");
2591 0     schemaLocation = wsdlGetProp(ctxt, node, "schemaLocation");
2592     
2593 0     if(schemaLocation)
2594     {
2595 0         xmlChar *base = NULL;
2596 0         xmlChar *URI = NULL;
2597 0         xmlURIPtr check;
2598
2599 0         url = xmlDictLookup(ctxt->dict, (const xmlChar *) schemaLocation, -1);
2600 0         if(!url)
2601         {
2602 0             long                        lno = xmlGetLineNo(node);
2603 0             wsdlParserError(ctxt, node,
2604                             WSDL_ERR_IMPORT,
2605                             "failed to get location of xml schema import",
2606                             NULL, NULL, (const char *) ctxt->url, lno);
2607 0             return (-1);
2608         }
2609
2610 0         check = xmlParseURI((const char *) url);
2611 0         if(check == NULL)
2612         {
2613 0             long                        lno = xmlGetLineNo(node);
2614 0             wsdlParserError(
2615                 ctxt, node,
2616                 WSDL_ERR_IMPORT,
2617                 "Import schemaLocation attribute is not a URI: %s\n",
2618                 schemaLocation, NULL, (const char *) ctxt->url, lno);
2619 0             return (-1);
2620         }
2621         else
2622         {
2623 0             xmlFreeURI(check);
2624         }
2625         
2626 0         base = xmlNodeGetBase(node->doc, node);
2627 0         if(base == NULL)
2628         {
2629 0             URI = xmlBuildURI(url, node->doc->URL);
2630         }
2631         else
2632         {
2633 0             URI = xmlBuildURI(url, base);
2634 0             xmlFree(base);
2635         }
2636         
2637 0         if(URI != NULL)
2638         {
2639 0             url = xmlDictLookup(ctxt->dict, URI, -1);
2640 0             xmlFree(URI);
2641         }
2642     }
2643
2644 0     if(url)
2645     {
2646 0         newCtxt = xmlSchemaNewParserCtxt((const char *) url);
2647 0         xmlSchemaSetParserErrors(newCtxt, 
2648                                  (xmlSchemaValidityErrorFunc) ctxt->err, 
2649                                  (xmlSchemaValidityWarningFunc) ctxt->warn, 
2650                                  ctxt->userData);
2651     }
2652     else
2653     {
2654 0         long                            lno = xmlGetLineNo(node);
2655 0         wsdlParserError(
2656             ctxt, node,
2657             WSDL_ERR_IMPORT,
2658             "Could not find matching xml schema file for import: %s",
2659             url, NULL, (const char *) ctxt->url, lno);
2660 0         return (-1);
2661     }
2662
2663 0     xmlHashScan(schema->importsDecl, 
2664                 wsdlCreateTypesHashScanner, 
2665                 schema->xmlSchemaImportsDecl);
2666 0     xsd_schema = xmlSchemaParse(newCtxt, NULL);
2667 0     if(!xsd_schema)
2668     { 
2669 0         return (-1); 
2670     }
2671
2672 0     xmlSchemaFreeParserCtxt(newCtxt);
2673
2674 0     xsd_import = (xmlSchemaImportPtr) xmlMalloc(sizeof(xmlSchemaImport));
2675 0     if(xsd_import == NULL)
2676     {
2677 0         wsdlErrorMemory(ctxt, "allocating imported wsdl", NULL);
2678 0         return (-1);
2679     }
2680     
2681 0     memset(xsd_import, 0, sizeof(xmlSchemaImport));
2682 0     xsd_import->schemaLocation = xmlDictLookup(ctxt->dict, url, -1);
2683 0     xsd_import->schema = xsd_schema;
2684     
2685 0     if(!schema->xmlSchemaImportsDecl)
2686     {
2687 0         schema->xmlSchemaImportsDecl = xmlHashCreate(10);
2688     }
2689     
2690 0     if(xsd_schema->targetNamespace)
2691     {
2692 0         if(xmlHashAddEntry(
2693                schema->xmlSchemaImportsDecl, 
2694                xsd_schema->targetNamespace, 
2695                xsd_import) < 0)
2696         {
2697 0             long                        lno = xmlGetLineNo(
2698 0                 (xmlNodePtr) ctxt->doc);
2699 0             wsdlParserError(ctxt, (xmlNodePtr) ctxt->doc,
2700                             WSDL_ERR_IMPORT,
2701                             "wsdl document imports %s multiple times",
2702                             url, NULL,
2703                             (const char *) ctxt->url, lno);
2704 0             xmlSchemaFree(xsd_schema);
2705 0             xmlFree(xsd_import);
2706 0             return (-1);
2707         }
2708     }
2709     else
2710     {
2711 0         if(xmlHashAddEntry(
2712                schema->xmlSchemaImportsDecl, 
2713                schema->targetNamespace, 
2714                xsd_import) < 0)
2715         {
2716 0             long                        lno = xmlGetLineNo(
2717 0                 (xmlNodePtr) ctxt->doc);
2718 0             wsdlParserError(ctxt, (xmlNodePtr) ctxt->doc,
2719                             WSDL_ERR_IMPORT,
2720                             "wsdl document imports %s multiple times",
2721                             url, NULL,
2722                             (const char *) ctxt->url, lno);
2723 0             xmlSchemaFree(xsd_schema);
2724 0             xmlFree(xsd_import);
2725 0             return (-1);
2726         }
2727     }
2728
2729 0     return 0;
2730 }
2731
2732 static
2733 wsdlParserCtxtPtr
2734 wsdlParseImport(wsdlParserCtxtPtr       ctxt,
2735                 wsdlSchemaPtr           schema,
2736                 xmlNodePtr              node)
2737 0 {
2738 0     const xmlChar *                     Namespace;
2739 0     const xmlChar *                     location;
2740 0     const xmlChar *                     url = NULL;
2741 0     const xmlChar *                     ns = NULL;
2742 0     wsdlParserCtxtPtr                   newCtxt;
2743 0     xmlNodePtr                          root;
2744 0     int                                 res;
2745 0     wsdlImportPtr                       import = NULL;
2746     
2747 0     Namespace = wsdlGetProp(ctxt, node, "namespace");
2748 0     location = wsdlGetProp(ctxt, node, "location");
2749     
2750 0     if(location)
2751     {
2752 0         xmlChar *base = NULL;
2753 0         xmlChar *URI = NULL;
2754 0         xmlURIPtr check;
2755
2756 0         url = xmlDictLookup(ctxt->dict, (const xmlChar *) location, -1);
2757 0         if(!url)
2758         {
2759 0             long                        lno = xmlGetLineNo(node);
2760 0             wsdlParserError(ctxt, node, 
2761                             WSDL_ERR_IMPORT,
2762                             "Failed to get location of wsdl import", 
2763                             NULL, NULL, (const char *) ctxt->url, lno);
2764 0             return (NULL);
2765         }
2766
2767 0         check = xmlParseURI((const char *) url);
2768 0         if (check == NULL) {
2769 0             long                        lno = xmlGetLineNo(node);
2770 0             wsdlParserError(ctxt, node,
2771                            WSDL_ERR_IMPORT,
2772                            "Import location attribute is not an URI: %s\n",
2773                            location, NULL, (const char *) ctxt->url, lno);
2774 0             return (NULL);
2775         } else {
2776 0             xmlFreeURI(check);
2777         }
2778 0 base = xmlNodeGetBase(node->doc, node);
2779 0 if (base == NULL) {
2780 0     URI = xmlBuildURI(url, node->doc->URL);
2781 } else {
2782 0     URI = xmlBuildURI(url, base);
2783 0     xmlFree(base);
2784 }
2785 0 if (URI != NULL) {
2786 0             url = xmlDictLookup(ctxt->dict, URI, -1);
2787 0     xmlFree(URI);
2788 }
2789     }
2790
2791 0     if(url)
2792     {
2793 0         newCtxt = wsdlNewParserCtxt((const char *) url);
2794 0         xmlDictFree(newCtxt->dict);
2795 0         xmlDictReference(ctxt->dict);
2796 0         newCtxt->dict = ctxt->dict;
2797 0         newCtxt->url = xmlDictLookup(newCtxt->dict, url, -1);
2798     }
2799     else
2800     {
2801 0         long                            lno = xmlGetLineNo(node);
2802 0         wsdlParserError(ctxt, node,
2803                        WSDL_ERR_IMPORT,
2804                        "Could not find matching wsdl file for import: %s",
2805                        url, NULL, (const char *) ctxt->url, lno);
2806 0         return (NULL);
2807     }
2808
2809 0     newCtxt->enclosingCtxt = ctxt;
2810 0     if(ns)
2811     {
2812 0         newCtxt->enclosingNs = ns;
2813     }
2814     else
2815     {
2816 0         newCtxt->enclosingNs = schema->targetNamespace;
2817     }
2818
2819 0     res = wsdlParseInternal(newCtxt);
2820 0     if(res != 0)
2821     {
2822 0         return (NULL);
2823     }
2824
2825 0     root = xmlDocGetRootElement(newCtxt->doc);
2826 0     if(root == NULL)
2827     {
2828 0         long                            lno = xmlGetLineNo(
2829 0             (xmlNodePtr) newCtxt->doc);
2830 0         wsdlParserError(newCtxt, (xmlNodePtr) newCtxt->doc,
2831                         WSDL_ERR_NOROOT,
2832                         "wsdl document has no root", NULL, NULL,
2833                         (const char *) newCtxt->url, lno);
2834 0         if(!newCtxt->preserve)
2835         {
2836 0             xmlFreeDoc(newCtxt->doc);
2837         }
2838 0         return (NULL);
2839     }
2840
2841 0     wsdlCleanupDoc(newCtxt, root);
2842
2843 0     import = (wsdlImportPtr) xmlMalloc(sizeof(wsdlImport));
2844 0     if(import == NULL)
2845     {
2846 0         wsdlErrorMemory(newCtxt, "allocating imported wsdl", root);
2847 0         return (NULL);
2848     }
2849
2850 0     memset(import, 0, sizeof(wsdlImport));
2851 0     import->wsdlLocation = xmlDictLookup(ctxt->dict, url, -1);
2852 0     import->schema = wsdlDoParse(newCtxt, schema, root);
2853 0     if(!import->schema)
2854     {
2855 0         long                            lno = xmlGetLineNo(
2856 0             (xmlNodePtr) newCtxt->doc);
2857 0         wsdlParserError(newCtxt, (xmlNodePtr) newCtxt->doc,
2858                         WSDL_ERR_IMPORT,
2859                         "Could not parse types in wsdl document", 
2860                         NULL, NULL,
2861                         (const char *) newCtxt->url, lno);
2862 0         xmlFree(import);
2863 0         return (NULL);
2864     }
2865
2866 0     newCtxt->schema = import->schema;
2867
2868 0     if(!schema->importsDecl)
2869     {
2870 0         schema->importsDecl = xmlHashCreate(10);
2871     }
2872         
2873 0     if(Namespace)
2874     {
2875 0         if(xmlHashAddEntry(schema->importsDecl, Namespace, import) < 0)
2876         {
2877 0             long                            lno = xmlGetLineNo(
2878 0             (xmlNodePtr) newCtxt->doc);
2879 0             wsdlParserError(newCtxt, (xmlNodePtr) newCtxt->doc,
2880                             WSDL_ERR_IMPORT,
2881                             "wsdl document imports %s multiple times", 
2882                             import->wsdlLocation, NULL,
2883                             (const char *) newCtxt->url, lno);
2884 0             xmlFree(import);
2885 0             return (NULL);
2886         }
2887     }
2888     else
2889     {
2890 0         if(xmlHashAddEntry(schema->importsDecl, schema->targetNamespace, import) < 0)
2891         {
2892 0             long                            lno = xmlGetLineNo(
2893 0             (xmlNodePtr) newCtxt->doc);
2894 0             wsdlParserError(newCtxt, (xmlNodePtr) newCtxt->doc,
2895                             WSDL_ERR_IMPORT,
2896                             "wsdl document imports %s multiple times", 
2897                             import->wsdlLocation, NULL,
2898                             (const char *) newCtxt->url, lno);
2899 0             xmlFree(import);
2900 0             return (NULL);
2901         }
2902     }
2903
2904 0     return (newCtxt);
2905 }
2906
2907 static
2908 wsdlParamPtr
2909 wsdlParseParam(wsdlParserCtxtPtr        ctxt,
2910                wsdlSchemaPtr            schema,
2911                xmlNodePtr               node)
2912 0 {
2913 0     wsdlParamPtr                        param;
2914 0     const xmlChar *                     message_name;
2915 0     const xmlChar *                     message_ns;
2916
2917 0     param = (wsdlParamPtr) xmlMalloc(sizeof(wsdlParam));
2918 0     if(!param)
2919     {
2920 0         wsdlErrorMemory(ctxt, "allocating structure for param", node);
2921 0         return (NULL);
2922     }
2923 0     memset(param, 0, sizeof(wsdlParam));
2924     
2925 0     param->name = wsdlGetProp(ctxt, node, "name");
2926
2927 0     param->Action = wsdlGetProp(ctxt, node, "Action");
2928
2929 0     param->node = node;
2930     
2931 0     message_name = wsdlGetQNameProp(ctxt, node, "message", &message_ns);
2932 0     if(!message_name)
2933     {
2934 0         long                            lno = xmlGetLineNo(node);
2935 0         wsdlParserError(ctxt, node, WSDL_ERR_PARAM,
2936                         "no 'message' attribute found for param element",
2937                         NULL, NULL, (const char *) ctxt->url, lno);
2938 0         xmlFree(param);
2939 0         return (NULL);
2940     }
2941
2942 0     param->message = wsdlFindMessage(ctxt, schema, message_name, message_ns);
2943 0     if(!param->message)
2944     {
2945 0         long                            lno = xmlGetLineNo(node);
2946 0         wsdlParserError(ctxt, node, WSDL_ERR_PARAM,
2947                         "invalid reference to message {%s}%s in param",
2948                         message_ns, message_name, (const char *) ctxt->url,
2949                         lno);
2950 0         xmlFree(param);
2951 0         return (NULL);
2952     }
2953     
2954 0     return (param);
2955 }
2956     
2957
2958 static
2959 wsdlFaultPtr
2960 wsdlParseFault(wsdlParserCtxtPtr        ctxt,
2961                wsdlSchemaPtr            schema,
2962                xmlNodePtr               node)
2963 0 {
2964 0     wsdlFaultPtr                        fault;
2965 0     const xmlChar *                     message_ns;
2966 0     const xmlChar *                     message_name;
2967
2968 0     fault = (wsdlFaultPtr) xmlMalloc(sizeof(wsdlFault));
2969 0     if(!fault)
2970     {
2971 0         wsdlErrorMemory(ctxt, "allocating structure for param", node);
2972 0         return (NULL);
2973     }
2974 0     memset(fault, 0, sizeof(wsdlFault));
2975     
2976 0     fault->name = wsdlGetProp(ctxt, node, "name");
2977 0     if(!fault->name)
2978     {
2979 0         long                            lno = xmlGetLineNo(node);
2980 0         wsdlParserError(ctxt, node, WSDL_ERR_FAULT,
2981                         "no 'name' attribute found for fault element",
2982                         NULL, NULL, (const char *) ctxt->url, lno);
2983 0         xmlFree(fault);
2984 0         return (NULL);
2985     }
2986
2987 0     fault->node = node;
2988         
2989 0     message_name = wsdlGetQNameProp(ctxt, node, "message", &message_ns);
2990 0     if(!message_name)
2991     {
2992 0         long                            lno = xmlGetLineNo(node);
2993 0         wsdlParserError(ctxt, node, WSDL_ERR_FAULT,
2994                         "no 'message' attribute found for fault element",
2995                         NULL, NULL, (const char *) ctxt->url, lno);
2996 0         xmlFree(fault);
2997 0         return (NULL);
2998     }
2999
3000 0     fault->message = wsdlFindMessage(ctxt, schema, message_name, message_ns);
3001 0     if(!fault->message)
3002     {
3003 0         long                            lno = xmlGetLineNo(node);
3004 0         wsdlParserError(ctxt, node, WSDL_ERR_PARAM,
3005                         "invalid reference to message {%s}%s in fault",
3006                         message_ns, message_name, (const char *) ctxt->url,
3007                         lno);
3008 0         xmlFree(fault);
3009 0         return (NULL);
3010     }
3011     
3012 0     return (fault);
3013 }
3014
3015 static
3016 wsdlOperationPtr
3017 wsdlParseOperation(wsdlParserCtxtPtr    ctxt,
3018                    wsdlSchemaPtr        schema,
3019                    xmlNodePtr           node)
3020 0 {
3021 0     wsdlOperationPtr                    op;
3022 0     xmlNodePtr                          childNode;
3023
3024 0     op = (wsdlOperationPtr) xmlMalloc(sizeof(wsdlOperation));
3025 0     if(!op)
3026     {
3027 0         wsdlErrorMemory(ctxt, "allocating structure for operation", node);
3028 0         return (NULL);
3029     }
3030 0     memset(op, 0, sizeof(wsdlOperation));
3031
3032 0     op->name = wsdlGetProp(ctxt, node, "name");
3033 0     if(!op->name)
3034     {
3035 0         long                            lno = xmlGetLineNo(node);
3036 0         wsdlParserError(ctxt, node, WSDL_ERR_OP,
3037                         "operation must define a 'name' attribute",
3038                         NULL, NULL, (const char *) ctxt->url, lno);
3039         
3040 0         return (NULL);
3041     }
3042
3043 0     op->node = node;
3044
3045 0     childNode = node->children;
3046 0     while(childNode)
3047     {
3048 0         if(!xmlCompareNodeConst(childNode, WSDL_DOCUMENTATION_NODE))
3049         {
3050             /* Ignored for now */
3051         }
3052 0         else if(!xmlCompareNodeConst(childNode, WSDL_INPUT_NODE))
3053         {
3054 0             op->type = (op->output) ? SOLICIT_RESPONSE_OPERATION : ONE_WAY_OPERATION;
3055 0             op->input = wsdlParseParam(ctxt, schema, childNode);
3056 0             if(!op->input)
3057             {
3058 0                 return (NULL);
3059             }
3060         }
3061 0         else if(!xmlCompareNodeConst(childNode, WSDL_OUTPUT_NODE))
3062         {
3063 0             op->type = (op->input) ? REQUEST_RESPONSE_OPERATION : NOTIFICATION_OPERATION;
3064 0             op->output = wsdlParseParam(ctxt, schema, childNode);
3065 0             if(!op->output)
3066             {
3067 0                 return (NULL);
3068             }
3069         }
3070 0         else if(!xmlCompareNodeConst(childNode, WSDL_FAULT_NODE))
3071         {
3072 0             wsdlFaultPtr                fault = NULL;
3073 0             fault = wsdlParseFault(ctxt, schema, childNode);
3074 0             if(!fault)
3075             {
3076 0                 return (NULL);
3077             }
3078
3079 0             if(!op->faults)
3080             {
3081 0                 op->faults = fault;
3082             }
3083             else
3084             {
3085 0                 fault->next = op->faults;
3086 0                 op->faults = fault;
3087             }
3088         }
3089         else
3090         {
3091             /* unmatched operation child element */
3092 0             return (NULL);
3093         }
3094
3095 0         childNode = childNode->next;
3096     }
3097
3098 0     op->node = node;
3099     
3100 0     return (op);
3101 }
3102
3103 static
3104 void
3105 wsdlOperationFree(
3106     wsdlOperationPtr                    op)
3107 0 {
3108 0     if(op)
3109     {
3110 0         if(op->next)
3111         {
3112 0             wsdlOperationFree(op->next);
3113         }
3114 0         if(op->input)
3115         {
3116 0             xmlFree(op->input);
3117         }
3118 0         if(op->output)
3119         {
3120 0             xmlFree(op->output);
3121         }
3122 0         if(op->faults)
3123         {
3124 0             wsdlFaultFree(op->faults);
3125         }
3126
3127 0         xmlFree(op);
3128     }
3129 }
3130
3131 static
3132 void
3133 wsdlFaultFree(
3134     wsdlFaultPtr                        fault)
3135 0 {
3136 0     if(fault)
3137     {
3138 0         if(fault->next)
3139         {
3140 0             wsdlFaultFree(fault->next);
3141         }
3142         
3143 0         xmlFree(fault);
3144     }
3145 }
3146
3147 static
3148 wsdlPortTypePtr
3149 wsdlParsePortType(wsdlParserCtxtPtr     ctxt,
3150                   wsdlSchemaPtr         schema,
3151                   xmlNodePtr            node)
3152 0 {
3153 0     xmlChar *                           rp_qnames;
3154 0     xmlChar *                           impls_qnames;
3155 0     wsdlPortTypePtr                     portType;
3156 0     wsdlOperationPtr                    operation;
3157 0     xmlNodePtr                          opNode;
3158
3159 0     portType = (wsdlPortTypePtr) xmlMalloc(sizeof(wsdlPortType));
3160 0     if(!portType)
3161     {
3162 0         wsdlErrorMemory(ctxt, "allocating space for portType structure", node);
3163 0         return (NULL);
3164     }
3165 0     memset(portType, 0, sizeof(wsdlPortType));
3166     
3167 0     portType->name = wsdlGetProp(ctxt, node, "name");
3168 0     if(!portType->name)
3169     {
3170 0         long                            lno = xmlGetLineNo(node);
3171 0         wsdlParserError(ctxt, node, WSDL_ERR_PORT_TYPE,
3172                         "portType must define a 'name' attribute",
3173                         NULL, NULL, (const char *) ctxt->url, lno);
3174 0         return (NULL);
3175     }
3176
3177 0     portType->node = node;
3178
3179 0     rp_qnames = xmlGetNsProp(
3180             node,
3181             (const xmlChar *) "ResourceProperties",
3182             (const xmlChar *) WSRP_NS);
3183 0     if(rp_qnames)
3184     {
3185 0         globus_i_wsdl_split_qnames(
3186             schema->targetNamespace,
3187             node, rp_qnames, &portType->ResourceProperties);
3188     }
3189
3190 0     impls_qnames = xmlGetNsProp(
3191             node,
3192             (const xmlChar *) "implements",
3193             (const xmlChar *) GTWSDL_NS);
3194 0     if(impls_qnames)
3195     {
3196 0         globus_i_wsdl_split_qnames(
3197             schema->targetNamespace,
3198             node, 
3199             impls_qnames, &portType->implements);
3200     }
3201         
3202 0     opNode = node->children;
3203 0     while(opNode)
3204     {
3205 0         if(!xmlCompareNodeConst(opNode, WSDL_DOCUMENTATION_NODE))
3206         {
3207             /* Ignored for now */
3208         }
3209 0         else if(!xmlCompareNodeConst(opNode, WSDL_OPERATION_NODE))
3210         {
3211 0             operation = wsdlParseOperation(ctxt, schema, opNode);
3212 0             if(!operation)
3213             {
3214 0                 return (NULL);
3215             }
3216
3217 0             if(portType->operations)
3218             {
3219 0                 operation->next = portType->operations;
3220             }
3221
3222 0             portType->operations = operation;
3223         }
3224         else
3225         {
3226 0             long                        lno = xmlGetLineNo(opNode);
3227 0             wsdlParserError(ctxt, opNode, WSDL_ERR_PORT_TYPE,
3228                             "child element of 'portType' must be an operation",
3229                             NULL, NULL, (const char *) ctxt->url, lno);
3230 0             return (NULL);
3231         }
3232
3233 0         opNode = opNode->next;
3234     }
3235
3236 0     portType->schema = schema;
3237 0     return (portType);
3238 }
3239
3240 static
3241 void
3242 wsdlPortTypeFree(
3243     wsdlPortTypePtr                     portType)
3244 0 {
3245 0     if(portType)
3246     {
3247 0         if(portType->operations)
3248         {
3249 0             wsdlOperationFree(portType->operations);
3250         }
3251
3252 0         if(portType->ResourceProperties)
3253         {
3254 0             xsdQNameFree(portType->ResourceProperties);
3255         }
3256
3257 0         if(portType->implements)
3258         {
3259 0             xsdQNameFree(portType->implements);
3260         }
3261
3262 0         xmlFree(portType);
3263     }
3264 }
3265
3266 static
3267 void
3268 wsdlPortTypeHEFree(
3269     void *                              value,
3270     xmlChar *                           name)
3271 0 {
3272 0     wsdlPortTypeFree((wsdlPortTypePtr) value);
3273 }
3274
3275 static
3276 void
3277 wsdlImportHEFree(
3278     void *                              value,
3279     xmlChar *                           name)
3280 0 {
3281 0     wsdlImportPtr                       import;
3282
3283 0     import = (wsdlImportPtr) value;
3284
3285 0     if(import)
3286     {
3287 0         if(import->schema)
3288         {
3289 0             wsdlSchemaFree(import->schema);
3290         }
3291
3292 0         xmlFree(import);
3293     }
3294 }
3295
3296 void
3297 wsdlSchemaFree(
3298     wsdlSchemaPtr                       schema)
3299 0 {
3300 0     if(schema)
3301     {
3302 0         if(schema->schemaTypes)
3303         {
3304 0             xmlSchemaFree(schema->schemaTypes);
3305 /*             xmlSchemaPtr                xsd = schema->schemaTypes; */
3306 /*             while(xsd) */
3307 /*             { */
3308 /*                 xmlSchemaPtr            next_xsd = NULL; */
3309
3310 /*                 if(xsd->_private) */
3311 /*                 { */
3312 /*                     next_xsd = (xmlSchemaPtr) xsd->_private; */
3313 /*                 } */
3314                 
3315 /*                 xsd->_private = NULL; */
3316 /*                 xmlSchemaFree(xsd); */
3317
3318 /*                 xsd = next_xsd; */
3319 /*             } */
3320         }
3321
3322 0         if(schema->messagesDecl)
3323         {
3324 0             xmlHashFree(schema->messagesDecl, wsdlMessageHEFree);
3325         }
3326
3327 0         if(schema->portTypesDecl)
3328         {
3329 0             xmlHashFree(schema->portTypesDecl, wsdlPortTypeHEFree);
3330         }
3331
3332 0         if(schema->bindingsDecl)
3333         {
3334 0             xmlHashFree(schema->bindingsDecl, wsdlBindingHEFree);
3335         }
3336
3337 0         if(schema->servicesDecl)
3338         {
3339 0             xmlHashFree(schema->servicesDecl, wsdlServiceHEFree);
3340         }
3341
3342 0         if(schema->importsDecl)
3343         {
3344 0             xmlHashFree(schema->importsDecl, wsdlImportHEFree);
3345         }
3346
3347 0         if(schema->dict)
3348         {
3349 0             xmlDictFree(schema->dict);
3350         }
3351     }
3352 }
3353
3354 static
3355 int
3356 wsdlParseTopLevel(wsdlParserCtxtPtr     ctxt,
3357                   wsdlSchemaPtr         schema,
3358                   xmlNodePtr            node)
3359 0 {
3360 0     int res = 0;
3361 0     xmlNodePtr                          child;
3362     
3363 0     child = node;
3364 0     if(!xmlCompareNodeConst(child, WSDL_TYPES_NODE))
3365     {
3366 0         res = wsdlParseTypes(ctxt, schema, child);
3367     }
3368 0     else if(!xmlCompareNodeConst(child, WSDL_MESSAGE_NODE))
3369     {
3370 0         wsdlMessagePtr                  new_message;
3371 0         const xmlChar *                 tns = NULL;
3372         
3373 0         new_message = wsdlParseMessage(ctxt, schema, child);
3374 0         if(!new_message)
3375         {
3376 0             return (-1);
3377         }
3378         
3379 0         if(!schema->messagesDecl)
3380         {
3381 0             schema->messagesDecl = xmlHashCreate(10);
3382         }
3383
3384 0         if(schema->targetNamespace)
3385         {
3386 0             tns = xmlDictLookup(ctxt->dict, schema->targetNamespace, -1);
3387         }
3388 0         else if(child && child->ns && child->ns->href)
3389         {
3390 0             tns = xmlDictLookup(ctxt->dict, child->ns->href, -1);
3391         }
3392         
3393 0         xmlHashAddEntry2(
3394             schema->messagesDecl, new_message->name, tns, new_message);
3395     }
3396 0     else if(!xmlCompareNodeConst(child, WSDL_PORTTYPE_NODE))
3397     {
3398 0         wsdlPortTypePtr                 port_type;
3399 0         const xmlChar *                 tns;
3400
3401 0         port_type = wsdlParsePortType(ctxt, schema, child);
3402 0         if(!port_type)
3403         {
3404 0             return (-1);
3405         }
3406
3407 0         if(!schema->portTypesDecl)
3408         {
3409 0             schema->portTypesDecl = xmlHashCreate(10);
3410         }
3411
3412 0         tns = schema->targetNamespace;
3413 0         if(!tns)
3414         {
3415 0             if(child->ns && child->ns->href)
3416             {
3417 0                 tns = child->ns->href;
3418             }
3419         }
3420         
3421 0         xmlHashAddEntry2(
3422             schema->portTypesDecl, port_type->name, tns, port_type);
3423     }
3424 0     else if(!xmlCompareNodeConst(child, WSDL_BINDING_NODE))
3425     {
3426 0         wsdlBindingPtr                  binding;
3427 0         const xmlChar *                 tns;
3428         
3429 0         binding = wsdlParseBinding(ctxt, schema, child);
3430 0         if(!binding)
3431         {
3432 0             return (-1);
3433         }
3434
3435 0         if(!schema->bindingsDecl)
3436         {
3437 0             schema->bindingsDecl = xmlHashCreate(10);
3438         }
3439         
3440 0         tns = schema->targetNamespace;
3441 0         if(!tns)
3442         {
3443 0             if(child->ns && child->ns->href)
3444             {
3445 0                 tns = child->ns->href;
3446             }
3447         }
3448         
3449 0         xmlHashAddEntry2(schema->bindingsDecl, binding->name, tns, binding);
3450     }
3451 0     else if(!xmlCompareNodeConst(child, WSDL_SERVICE_NODE))
3452     {
3453 0         wsdlServicePtr                  service;
3454 0         const xmlChar *                 tns;
3455         
3456 0         service = wsdlParseService(ctxt, schema, child);
3457 0         if(!service)
3458         {
3459 0             return (-1);
3460         }
3461         
3462 0         if(!schema->servicesDecl)
3463         {
3464 0             schema->servicesDecl = xmlHashCreate(10);
3465         }
3466
3467 0         tns = schema->targetNamespace;
3468 0         if(!tns)
3469         {
3470 0             if(child->ns && child->ns->href)
3471             {
3472 0                 tns = child->ns->href;
3473             }
3474         }
3475         
3476 0         xmlHashAddEntry2(schema->servicesDecl, service->name, tns, service);
3477     }
3478 0     else if(!xmlCompareNodeConst(child, WSDL_IMPORT_NODE))
3479     {
3480         /* already handled */
3481     }
3482 0     else if(!xmlCompareNodeConst(child, XSD_IMPORT_NODE))
3483     {
3484         /* already handled */
3485     }
3486 0     else if(!xmlCompareNodeConst(child, WSDL_DOCUMENTATION_NODE))
3487     {
3488         /* Ignored for now */
3489     }
3490     else
3491     {
3492 0         long                            lno = xmlGetLineNo(node);
3493 0         res = -1;
3494 0         wsdlParserError(ctxt, node,
3495                         WSDL_ERR_TOPLEVEL,
3496                         "Failed to parse top level WSDL element %s",
3497                         child->name, NULL, (const char *) ctxt->url, lno);
3498     }
3499     
3500 0     return (res);
3501 }
3502
3503 static
3504 int
3505 wsdlParseImports(wsdlParserCtxtPtr     ctxt,
3506                  wsdlSchemaPtr         schema,
3507                  xmlNodePtr            node)
3508 0 {
3509 0     int res = 0;
3510 0     xmlNodePtr                          child;
3511     
3512 0     child = node;
3513 0     if(!xmlCompareNodeConst(child, WSDL_IMPORT_NODE))
3514     {
3515 0         const xmlChar *                    tns;
3516 0         wsdlParserCtxtPtr               import_ctxt;
3517 0         tns = schema->targetNamespace;
3518 0         import_ctxt = wsdlParseImport(ctxt, schema, child);
3519 0         if(!import_ctxt)
3520         {
3521 0             return (-1);
3522         }
3523 0         schema->targetNamespace = tns;
3524     }
3525 0     else if(!xmlCompareNodeConst(child, XSD_IMPORT_NODE))
3526     {
3527 0         res = wsdlParseSchemaImport(ctxt, schema, child);
3528 0         if(res != 0)
3529         {
3530 0             return (-1);
3531         }
3532     }
3533
3534 0     return (res);
3535 }
3536
3537 static
3538 void
3539 xmlSchemaCreateTypesHashScanner(
3540     void *                              import_payload,
3541     void *                              data,
3542     xmlChar *                           schema_namespace);
3543
3544 static
3545 void
3546 wsdlCreateTypesHashScanner(
3547     void *                              import_payload,
3548     void *                              data,
3549     xmlChar *                           schema_namespace)
3550 0 {
3551 0     wsdlImportPtr                       import;
3552 0     xmlHashTablePtr                     xsd_imports;
3553 0     xmlSchemaImportPtr                  xsd_import;
3554
3555 0     xsd_imports = (xmlHashTablePtr) data;
3556 0     import = (wsdlImportPtr) import_payload;
3557     
3558 0     if(import->schema->schemaTypes)
3559     {
3560 0         xsd_import = (xmlSchemaImportPtr) xmlMalloc(sizeof(xmlSchemaImport));
3561 0         if(!xsd_import)
3562         {
3563 0             wsdlErrorMemory(
3564                 NULL, "Memory allocation of schemaImport failed", NULL);
3565 0             return;
3566         }
3567
3568 0         memset(xsd_import, 0, sizeof(xmlSchemaImport));
3569
3570 0         xsd_import->schemaLocation = import->wsdlLocation;
3571 0         xsd_import->schema = import->schema->schemaTypes;
3572 0         xsd_import->preserve = 1;
3573 0 xmlHashAddEntry(
3574             xsd_imports, xsd_import->schema->targetNamespace, xsd_import);
3575 0         if(import->schema->xmlSchemaImportsDecl)
3576         {
3577 0             xmlHashScan(import->schema->xmlSchemaImportsDecl,
3578                         xmlSchemaCreateTypesHashScanner,
3579                         xsd_imports);
3580         }
3581     }
3582 }
3583
3584 static
3585 void
3586 xmlSchemaCreateTypesHashScanner(
3587     void *                              import_payload,
3588     void *                              data,
3589     xmlChar *                           schema_namespace)
3590 0 {
3591 0     xmlHashTablePtr                     xsd_imports;
3592 0     xmlSchemaImportPtr                  xsd_import;
3593 0     xmlSchemaImportPtr                  new_import;
3594
3595 0     xsd_imports = (xmlHashTablePtr) data;
3596 0     xsd_import = (xmlSchemaImportPtr) import_payload;
3597     
3598 0     new_import = (xmlSchemaImportPtr) xmlMalloc(sizeof(xmlSchemaImport));
3599 0     if(!new_import)
3600     {
3601 0         wsdlErrorMemory(
3602             NULL, "Memory allocation of schemaImport failed", NULL);
3603 0         return;
3604     }
3605
3606 0     memset(new_import, 0, sizeof(xmlSchemaImport));
3607
3608 0     new_import->schemaLocation = xsd_import->schemaLocation;
3609 0     new_import->schema = xsd_import->schema;
3610 0     new_import->preserve = 1;
3611 0     xmlHashAddEntry(xsd_imports, schema_namespace, new_import);