1 /******************************************************************
2  *  $Id: wsdl2c.c,v 1.9 2005/05/27 19:28:16 snowdrop Exp $
3  *
4  * CSOAP Project:  A SOAP client/server library in C
5  * Copyright (C) 2003  Ferhat Ayaz
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA  02111-1307, USA.
21  *
22  * Email: ayaz@jprogrammer.net
23  */
24 #include <libxml/xpath.h>
25 #include <xsd2c/xsd2c.h>
26 #include <xsd2c/util.h> /* parseNS */
27 #include <xsd2c/formatter.h> /* formatter sax serializer */
28 #include <xsd2c/obj.h> /* formatter sax serializer */
29 #include <string.h>
30 
31 #define _DESERIALIZER_DISABLE_
32 #include "CallList.h"
33 
34 /* ------------- Just for test --------------------------------- */
35 
36 int Writer_Tab = 0;
37 int Writer_Ret = 0;
38 
Writer_StartElement(const char * element_name,int attr_count,char ** keys,char ** values,void * userData)39 void Writer_StartElement(const char* element_name, int attr_count, char **keys, char **values, void* userData)
40 {
41   int i, j;
42   if (Writer_Ret) printf("\n");
43   for (j=0;j<Writer_Tab;j++) printf("\t");
44   printf("<%s", element_name);
45   for (i=0;i<attr_count;i++)
46   {
47     printf(" %s = \"%s\"", keys[i], values[i]);
48   }
49   printf(">");
50   Writer_Tab++;
51   Writer_Ret = 1;
52 }
53 
Writer_Characters(const char * element_name,const char * chars,void * userData)54 void Writer_Characters(const char* element_name, const char* chars, void* userData)
55 {
56   printf("%s", chars!=NULL?chars:"null");
57 }
58 
Writer_EndElement(const char * element_name,void * userData)59 void Writer_EndElement(const char* element_name, void* userData)
60 {
61   int j;
62   Writer_Tab--;
63   if (!Writer_Ret)
64     for (j=0;j<Writer_Tab;j++) printf("\t");
65   printf("</%s>\n", element_name);
66   Writer_Ret = 0;
67 }
68 
69 /* ------------------------------------------------------------- */
70 
71 struct CallList* callList = NULL;
72 char soap_prefix[50];
73 char wsdl_prefix[50];
74 char target_ns[150];
75 char target_prefix[50];
76 
xpath_eval(xmlDocPtr doc,const char * xpath)77 xmlXPathObjectPtr xpath_eval(xmlDocPtr doc, const char *xpath)
78 {
79   xmlXPathContextPtr context;
80   xmlXPathObjectPtr result;
81   xmlNodePtr node;
82   xmlNsPtr default_ns;
83 
84   node = xmlDocGetRootElement(doc);
85   if (node == NULL) {
86     fprintf(stderr,"empty document\n");
87     return NULL;
88   }
89 
90 
91   context = xmlXPathNewContext(doc);
92 
93   context->namespaces = xmlGetNsList(doc, node);
94   context->nsNr = 0;
95   if (context->namespaces != NULL) {
96      while (context->namespaces[context->nsNr] != NULL) {
97 /*      fprintf(stdout, "NS: '%s' - '%s'\n", context->namespaces[context->nsNr]->href,
98   context->namespaces[context->nsNr]->prefix); */
99       context->nsNr++;
100      }
101   }
102 
103   /* search default namespace */
104   default_ns = xmlSearchNs(doc, node, NULL);
105   if (default_ns != NULL && default_ns->href != NULL) {
106     fprintf(stdout, "Register default namespace '%s'\n", (const char*)default_ns->href);
107     /* default_ns : "http://schemas.xmlsoap.org/wsdl/" */
108     xmlXPathRegisterNs(context, "wsdl", default_ns->href );
109   }
110 
111 
112   printf("XPath: '%s'\n", xpath);
113   result = xmlXPathEvalExpression((xmlChar*)xpath, context);
114   if (result == NULL) {
115     fprintf(stderr, "ERROR: XPath error!\n");
116     return NULL;
117   }
118 
119   if(xmlXPathNodeSetIsEmpty(result->nodesetval)){
120     /* no result */
121     printf("XPath result is empty\n");
122     return NULL;
123   }
124 
125   xmlXPathFreeContext(context);
126   return result;
127 }
128 
findPortType(xmlDocPtr doc,const char * name)129 xmlNodePtr findPortType(xmlDocPtr doc, const char *name)
130 {
131   xmlNodePtr root;
132   xmlNodePtr cur;
133   xmlChar *attr_name;
134 
135   root = xmlDocGetRootElement(doc);
136   if (root == NULL) {
137     fprintf(stderr, "Empty document!\n");
138     return NULL;
139   }
140 
141   cur = root->xmlChildrenNode;
142 
143   while (cur != NULL) {
144 
145     if (cur->type != XML_ELEMENT_NODE) {
146       cur = cur->next;
147       continue;
148     }
149 
150     if (xmlStrcmp(cur->name, (const xmlChar*)"portType")) {
151       cur = cur->next;
152       continue;
153     }
154 
155     attr_name = xmlGetProp(cur, "name");
156     if (attr_name == NULL) {
157       cur = cur->next;
158       continue;
159     }
160 
161     if (!xmlStrcmp(attr_name, (const xmlChar*)name)) {
162       /*xmlFree(attr_name);*/
163       return cur;
164     }
165 
166     /*xmlFree(attr_name);*/
167     cur = cur->next;
168   }
169 
170   return NULL;
171 }
172 
173 
findMessage(xmlDocPtr doc,const char * name)174 xmlNodePtr findMessage(xmlDocPtr doc, const char *name)
175 {
176   xmlNodePtr root;
177   xmlNodePtr cur;
178   xmlChar *attr_name;
179 
180   root = xmlDocGetRootElement(doc);
181   if (root == NULL) {
182     fprintf(stderr, "Empty document!\n");
183     return NULL;
184   }
185 
186   cur = root->xmlChildrenNode;
187 
188   while (cur != NULL) {
189 
190     if (cur->type != XML_ELEMENT_NODE) {
191       cur = cur->next;
192       continue;
193     }
194 
195     if (xmlStrcmp(cur->name, (const xmlChar*)"message")) {
196       cur = cur->next;
197       continue;
198     }
199 
200     attr_name = xmlGetProp(cur, "name");
201     if (attr_name == NULL) {
202       cur = cur->next;
203       continue;
204     }
205 
206     if (!xmlStrcmp(attr_name, (const xmlChar*)name)) {
207       /*xmlFree(attr_name);*/
208       return cur;
209     }
210 
211     /*xmlFree(attr_name);*/
212     cur = cur->next;
213   }
214 
215   return NULL;
216 }
217 
218 
findSubNode(xmlNodePtr root,const char * element_name)219 xmlNodePtr findSubNode(xmlNodePtr root, const char *element_name)
220 {
221   xmlNodePtr cur;
222 
223   cur = root->xmlChildrenNode;
224 
225   while (cur != NULL) {
226 
227     if (cur->type != XML_ELEMENT_NODE) {
228       cur = cur->next;
229       continue;
230     }
231 
232     if (!xmlStrcmp(cur->name, (const xmlChar*)element_name)) {
233       return cur;
234     }
235 
236     cur = cur->next;
237   }
238 
239   return NULL;
240 }
241 
242 
handleInputParameters(xmlDocPtr doc,const char * name,struct CallFunc * func)243 void handleInputParameters(xmlDocPtr doc, const char *name, struct CallFunc *func)
244 {
245   char ns[10];
246   char message_name[255];
247   xmlNodePtr node;
248   xmlNodePtr cur;
249   struct CallVar *var;
250   xmlChar *var_name, *var_type;
251 
252   parseNS(name, ns, message_name); /* check why to pase ns? */
253 
254   node = findMessage(doc, message_name);
255   if (node == NULL) {
256     fprintf(stderr, "ERROR: Can not find message '%s'\n", message_name);
257     return;
258   }
259 
260   cur = node->xmlChildrenNode;
261   while (cur != NULL) {
262 
263     if (cur->type != XML_ELEMENT_NODE) {
264       cur = cur->next;
265       continue;
266     }
267 
268     if (xmlStrcmp(cur->name, (const xmlChar*)"part")) {
269       cur = cur->next;
270       continue;
271     }
272 
273     var_name = xmlGetProp(cur, "name");
274     if (var_name == NULL) {
275       fprintf(stderr, "ERROR: Found <part> without attrbute 'name'! (message:'%s')\n",
276         message_name);
277       cur = cur->next;
278       continue;
279     }
280 
281     var_type = xmlGetProp(cur, "type");
282     if (var_type == NULL) {
283       var_type = xmlGetProp(cur, "element");
284     }
285 
286     if (var_type == NULL) {
287       fprintf(stderr, "ERROR: Found <part> without attrbute 'type' or 'element'! (message:'%s')\n",
288         message_name);
289       /*xmlFree(var_name);*/
290       cur = cur->next;
291       continue;
292     }
293 
294     var = CallVar_Create();
295     CallVar_Set_name(var, (const char*)var_name);
296     CallVar_Set_type(var, (const char*)var_type);
297     CallFunc_Add_in(func, var);
298 
299     fprintf(stdout, "\t\t(%s,%s)\n", trXSD2C((const char*)var_type), (const char*)var_name);
300 
301     /*xmlFree(var_name);
302     xmlFree(var_type);*/
303 
304     cur = cur->next;
305   }
306 
307 }
308 
handleOutputParameters(xmlDocPtr doc,const char * name,struct CallFunc * func)309 void handleOutputParameters(xmlDocPtr doc, const char *name, struct CallFunc *func)
310 {
311   char ns[10];
312   char message_name[255];
313   xmlNodePtr node;
314   xmlNodePtr cur;
315   struct CallVar *var;
316   xmlChar *var_name, *var_type;
317 
318   parseNS(name, ns, message_name); /* check why to pase ns? */
319 
320   node = findMessage(doc, message_name);
321   if (node == NULL) {
322     fprintf(stderr, "ERROR: Can not find message '%s'\n", message_name);
323     return;
324   }
325 
326   cur = node->xmlChildrenNode;
327   while (cur != NULL) {
328 
329     if (cur->type != XML_ELEMENT_NODE) {
330       cur = cur->next;
331       continue;
332     }
333 
334     if (xmlStrcmp(cur->name, (const xmlChar*)"part")) {
335       cur = cur->next;
336       continue;
337     }
338 
339     var_name = xmlGetProp(cur, "name");
340     if (var_name == NULL) {
341       fprintf(stderr, "ERROR: Found <part> without attrbute 'name'! (message:'%s')\n",
342         message_name);
343       cur = cur->next;
344       continue;
345     }
346 
347     var_type = xmlGetProp(cur, "type");
348     if (var_type == NULL) {
349       var_type = xmlGetProp(cur, "element");
350     }
351 
352     if (var_type == NULL) {
353       fprintf(stderr, "ERROR: Found <part> without attrbute 'type' or 'element'! (message:'%s')\n",
354         message_name);
355       /*xmlFree(var_name);*/
356       cur = cur->next;
357       continue;
358     }
359 
360     var = CallVar_Create();
361     CallVar_Set_name(var, (const char*)var_name);
362     CallVar_Set_type(var, (const char*)var_type);
363     CallFunc_Set_out(func, var);
364 
365     fprintf(stdout, "\t\t(%s,%s)\n", trXSD2C((const char*)var_type), (const char*)var_name);
366 
367     /*xmlFree(var_name);
368     xmlFree(var_type);*/
369 
370     cur = cur->next;
371 
372     break; /* only one return parameter */
373   }
374 
375 }
376 
handlePortType(xmlDocPtr doc,const char * name)377 void handlePortType(xmlDocPtr doc, const char *name)
378 {
379   xmlNodePtr node;
380   xmlNodePtr input;
381   xmlNodePtr output;
382   xmlNodePtr cur;
383   xmlChar *attr_name;
384   xmlChar *message;
385   struct CallFunc *func;
386   char opname[255];
387 
388   node = findPortType(doc, name);
389   if (node == NULL) {
390     fprintf(stderr, "PortType '%s' not found!\n", name);
391     return;
392   }
393 
394   cur = node->xmlChildrenNode;
395   while (cur != NULL) {
396 
397     if (cur->type != XML_ELEMENT_NODE) {
398       cur = cur->next;
399       continue;
400     }
401 
402     if (xmlStrcmp(cur->name, (const xmlChar*)"operation")) {
403       cur = cur->next;
404       continue;
405     }
406 
407     attr_name = xmlGetProp(cur, "name");
408     if (attr_name == NULL) {
409       cur = cur->next;
410       continue;
411     }
412 
413     strcpy(opname, (const char*)attr_name);
414     /*xmlFree(attr_name);*/
415 
416     func = CallFunc_Create();
417     CallList_Add_operation(callList, func);
418 
419     CallFunc_Set_name(func, opname);
420     fprintf(stdout, "Operation -> '%s'\n", opname);
421 
422     /* handle input */
423     input = findSubNode(cur, "input");
424     if (input == NULL) {
425       fprintf(stderr, "WARNING: No input for operation '%'\n", opname);
426       cur = cur->next;
427       continue;
428     }
429 
430     message = xmlGetProp(input, "message");
431     if (message == NULL) {
432       fprintf(stderr, "ERROR: No message attribute for input operation '%s'\n", opname);
433       cur = cur->next;
434       continue;
435     }
436 
437     fprintf(stdout, "\tinput  = '%s'\n", (const char*)message);
438 
439     handleInputParameters(doc, (const char*)message, func);
440 
441     /*xmlFree(message);*/
442 
443     /* handle output */
444     output = findSubNode(cur, "output");
445     if (output == NULL) { /* one way operation is ok */
446       cur = cur->next;
447       continue;
448     }
449 
450     message = xmlGetProp(output, "message");
451     if (message == NULL) {
452       fprintf(stderr, "ERROR: No message attribute for output operation '%s'\n", opname);
453       cur = cur->next;
454       continue;
455     }
456 
457     fprintf(stdout, "\toutput = '%s'\n", (const char*)message);
458     /*xmlFree(message);*/
459 
460     handleOutputParameters(doc, (const char*)message, func);
461     cur = cur->next;
462   }
463 
464 }
465 
handleBinding(xmlDocPtr doc,const char * type)466 void handleBinding(xmlDocPtr doc, const char *type)
467 {
468 
469   int i;
470   xmlChar *name;
471   xmlChar *btype;
472   xmlNodeSetPtr nodeset;
473   xmlXPathObjectPtr xpathObj;
474   char query[255];
475   char port_name[255], port_ns[10];
476   char binding_type[255], binding_ns[10];
477 
478   parseNS(type, binding_ns, binding_type);
479 
480   /* Set xpath  query */
481   if (wsdl_prefix[0])
482     sprintf(query, "//%s:definitions/%s:binding[@name=\"%s\"]", wsdl_prefix, wsdl_prefix, binding_type);
483   else
484     sprintf(query, "//definitions/binding[@name=\"%s\"]", binding_type);
485 
486   /* Find Bindings */
487   xpathObj = xpath_eval(doc, query);
488 
489   if (xpathObj == NULL) {
490     fprintf(stderr, "No Soap Binding found!\n");
491     return;
492   }
493 
494   /* Check if found nodes */
495   nodeset = xpathObj->nodesetval;
496   if (nodeset == NULL) {
497     fprintf(stderr, "No Soap Binding found! nodeset empty!\n");
498     return;
499   }
500 
501   /* Iterate all soap services */
502   for (i=0;i < nodeset->nodeNr; i++) {
503 
504     name = xmlGetProp(nodeset->nodeTab[i], "name");
505 
506     if (name == NULL) {
507       fprintf(stderr, "WARNING: no attribute name found!\n");
508     } else {
509       fprintf(stdout, "Found Binding -> (name: '%s')\n",
510         (const char*)name);
511     }
512 
513     btype = xmlGetProp(nodeset->nodeTab[i], "type");
514 
515     if (btype == NULL) {
516       fprintf(stderr, "WARNING: no attribute type found!\n");
517     } else {
518       parseNS(btype, port_ns, port_name);
519       handlePortType(doc, port_name);
520     }
521 
522 /*    if (name != NULL) xmlFree(name);
523     if (btype != NULL) xmlFree(btype);  */
524   }
525 
526 }
527 
wsdlParse(xmlDocPtr doc)528 void wsdlParse(xmlDocPtr doc)
529 {
530   int i;
531   xmlChar *name, *binding;
532   xmlNodeSetPtr nodeset;
533   xmlXPathObjectPtr xpathObj;
534   char query[255];
535 
536   if (wsdl_prefix[0])
537     sprintf(query, "//%s:definitions/%s:service/%s:port[%s:address]",  wsdl_prefix, wsdl_prefix, wsdl_prefix, soap_prefix);
538   else
539     sprintf(query, "//definitions/service/port[%s:address]", soap_prefix);
540 
541 
542   /* Find Soap Service */
543   xpathObj = xpath_eval(doc, query);
544 
545   if (xpathObj == NULL) {
546     fprintf(stderr, "No Soap Service  found!\n");
547     return;
548   }
549 
550   /* Check if found nodes */
551   nodeset = xpathObj->nodesetval;
552   if (nodeset == NULL) {
553     fprintf(stderr, "No Soap Service  found! nodeset empty!\n");
554     return;
555   }
556 
557   /* Iterate all soap services */
558   for (i=0;i < nodeset->nodeNr; i++) {
559 
560     name = xmlGetProp(nodeset->nodeTab[i], "name");
561     binding = xmlGetProp(nodeset->nodeTab[i], "binding");
562 
563     if (name == NULL) {
564       fprintf(stderr, "WARNING: no attribute type found!\n");
565     } if (binding == NULL) {
566       fprintf(stderr, "WARNING: no attribute binding found!\n");
567     } else {
568       fprintf(stdout, "Found SOAP port -> (type: '%s') (binding: '%s')\n",
569         (const char*)name, (const char*)binding);
570     }
571 
572     handleBinding(doc, binding);
573 
574 /*    if (name != NULL) xmlFree(name);
575     if (binding != NULL) xmlFree(binding);*/
576   }
577 
578 
579 }
580 
581 
582 static
583 void usage(const char* execname);
584 
main(int argc,char * argv[])585 int main(int argc, char *argv[])
586 {
587   xmlDocPtr doc;
588   xmlNodePtr cur;
589   xmlNodePtr node;
590   xmlNodePtr xsdRoot;
591   xmlNsPtr default_ns;
592   xmlNsPtr soap_ns;
593   xmlNsPtr wsdl_ns;
594   xmlNsPtr tar_ns;
595   xmlChar *tar_ns_str;
596 
597   int i;
598   char outDir[1054];
599   char fname[255];
600 
601   if (argc < 2) {
602     usage(argv[0]);
603     return 1;
604   }
605 
606 
607 
608  strcpy(outDir, ".");
609 
610   for (i=1;i<argc;i++)
611   {
612     if (!strcmp(argv[i], "-d"))
613       if (i==argc-1) usage(argv[0]);
614       else strcpy(outDir, argv[++i]);
615     else if (!strcmp(argv[i], "-S"))
616       formatter_generate_sax_serializer = 1;
617     else strcpy(fname, argv[i]);
618   }
619 
620 
621   xsdRoot = wsdlLoadFile(fname);
622 
623   if (xsdRoot == NULL )
624   {
625     fprintf(stderr,"No Schema data found\n");
626     doc = xmlParseFile(fname);
627     if (doc == NULL)
628     {
629 	    fprintf(stderr,"Can not parse document\n");
630 	    return 1;
631     }
632   }
633   else
634   {
635 	  doc = xsdRoot->doc;
636   }
637 
638 
639   node = xmlDocGetRootElement(doc);
640   if (node == NULL) {
641     fprintf(stderr,"empty document\n");
642     xmlFreeDoc(doc);
643     return 1;
644   }
645 
646   /* Search for wsdl soap namespace
647     http://schemas.xmlsoap.org/wsdl/soap/
648   */
649   soap_ns = xmlSearchNsByHref(doc, node, "http://schemas.xmlsoap.org/wsdl/soap/");
650   if (soap_ns == NULL) {
651     soap_ns = xmlSearchNsByHref(doc, node, "http://schemas.xmlsoap.org/wsdl/soap");
652   }
653 
654   if (soap_ns != NULL && soap_ns->prefix != NULL) {
655       fprintf(stdout, "Wsdl SOAP prefix: '%s'\n", soap_ns->prefix);
656       strcpy(soap_prefix, soap_ns->prefix);
657   } else {
658     fprintf(stderr,"Namespace 'http://schemas.xmlsoap.org/wsdl/soap/' expected\n");
659     xmlFreeDoc(doc);
660     return 1;
661   }
662 
663 
664   /* Search for wsdl namespace
665     http://schemas.xmlsoap.org/wsdl/
666   */
667   wsdl_ns = xmlSearchNsByHref(doc, node, "http://schemas.xmlsoap.org/wsdl/");
668   if (wsdl_ns == NULL) {
669     wsdl_ns = xmlSearchNsByHref(doc, node, "http://schemas.xmlsoap.org/wsdl");
670   }
671 
672 
673   if (wsdl_ns != NULL && wsdl_ns->prefix != NULL) {
674       fprintf(stdout, "Wsdl prefix: '%s'\n", wsdl_ns->prefix);
675       strcpy(wsdl_prefix, wsdl_ns->prefix);
676   } else {
677     /* search default namespace */
678     default_ns = xmlSearchNs(doc, node, NULL);
679     if (default_ns == NULL || ( default_ns != NULL && default_ns->href == NULL)) {
680       fprintf(stdout, "Adding default namespace 'http://schemas.xmlsoap.org/wsdl/'\n");
681       xmlNewDocProp(doc,  "xmlns", "http://schemas.xmlsoap.org/wsdl/");
682     }
683 
684     /*strcpy(wsdl_prefix, "wsdl");*/
685     wsdl_prefix[0] = '\0';
686   }
687 
688 
689 
690   /* search targetNamespace */
691   tar_ns_str = xmlGetProp(node, "targetNamespace");
692   if (tar_ns_str) {
693     strcpy(target_ns, tar_ns_str);
694     /* Search for target namespace
695     */
696     tar_ns = xmlSearchNsByHref(doc, node, target_ns);
697     if (tar_ns && tar_ns->prefix) {
698       strcpy(target_prefix, tar_ns->prefix);
699       printf("Target namespace: %s\nTarget NS Prefix: %s\n",
700         target_ns, target_prefix);
701     } else {
702       target_prefix[0] = '\0';
703     }
704     /*xmlFree*/
705   } else {
706     target_ns[0] = '\0';
707     target_prefix[0] = '\0';
708   }
709 
710 
711   xsdRoot = xsdRoot?xsdRoot:node;
712 	while (xsdRoot) {
713 
714 	  if (xsdRoot->type != XML_ELEMENT_NODE) {
715 	     xsdRoot  = xsdRoot->next;
716 	     continue;
717 	  }
718 
719     if (!xsdInitTrModule(xsdRoot))
720       return 1;
721 
722     if (!xsdInitObjModule(xsdRoot))
723       return 1;
724 
725 
726 	  printf("Calling xsd engine\n");
727     if (xsdEngineRun(xsdRoot, outDir)) {
728      fprintf(stderr, "xsd2c engine error\n");
729     	return 1;
730     }
731     xsdRoot  = xsdRoot->next;
732   }
733   callList = CallList_Create();
734   wsdlParse(doc);
735 
736 /*  CallList_Sax_Serialize(callList, "CallList",
737     Writer_StartElement,
738     Writer_Characters,
739     Writer_EndElement, 0);
740 */
741   codeWriteStubHeader(callList, "test_stub.h");
742 
743   CallList_Free(callList);
744 
745   trFreeModule();
746   objFreeModule();
747 
748   xmlFreeDoc(doc);
749   return 0;
750 }
751 
752 
753 
754 static
usage(const char * execname)755 void usage(const char* execname)
756 {
757 	fprintf(stderr, "usage: %s -d dest <wsdl file>\n", execname);
758 }
759 
760