/* wsdl2h.cpp WSDL parser, translator, and generator (of the gSOAP header file format) -------------------------------------------------------------------------------- gSOAP XML Web services tools Copyright (C) 2000-2016, Robert van Engelen, Genivia Inc. All Rights Reserved. This software is released under one of the following licenses: GPL or Genivia's license for commercial use. -------------------------------------------------------------------------------- GPL license. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Author contact information: engelen@genivia.com / engelen@acm.org -------------------------------------------------------------------------------- A commercial use license is available from Genivia, Inc., contact@genivia.com -------------------------------------------------------------------------------- Build: soapcpp2 -ipwsdl wsdl.h g++ -o wsdl2h wsdl2h.cpp types.cpp service.cpp wsdl.cpp schema.cpp wsdlC.cpp stdsoap2.cpp TODO: Resolve relative versus absolute import paths for reading imported WSDL/schema (use URL local addresses) Do not generate abstract complexTypes, but include defs in derived types Handle simpleType derivation from base64 */ #include "includes.h" #include "types.h" #include "service.h" #ifndef WSDL2H_IMPORT_PATH #define WSDL2H_IMPORT_PATH (NULL) #endif #ifndef WSDL_TYPEMAP_FILE #define WSDL_TYPEMAP_FILE "typemap.dat" #endif static void init(); static void options(int argc, char **argv); int _flag = 0, aflag = 0, bflag = 0, cflag = 0, c11flag = 0, dflag = 0, eflag = 0, fflag = 0, gflag = 0, iflag = 0, jflag = 0, kflag = 0, mflag = 0, Mflag = 0, pflag = 0, Pflag = 0, Rflag = 0, sflag = 0, uflag = 0, Uflag = 0, vflag = 0, wflag = 0, Wflag = 0, xflag = 0, yflag = 0, zflag = 0; int openfiles = 0; int infiles = 0; char *infile[MAXINFILES], *outfile = NULL, *proxy_host = NULL, *proxy_userid = NULL, *proxy_passwd = NULL, *auth_userid = NULL, *auth_passwd = NULL; const char *mapfile = WSDL_TYPEMAP_FILE, *import_path = WSDL2H_IMPORT_PATH, *cwd_path = NULL, *cppnamespace = NULL; int proxy_port = 8080; FILE *stream = stdout; SetOfString exturis; extern struct Namespace namespaces[]; const char *service_prefix = NULL; const char *schema_prefix = "ns"; const char elementformat[] = " %-35s %-30s"; const char pointerformat[] = " %-35s *%-30s"; const char attributeformat[] = " @%-35s %-30s"; const char templateformat[] = " %s<%-23s> %-30s"; const char pointertemplateformat[] = " %s<%-22s> *%-30s"; const char templateformat_open[] = " %s<%s"; const char attrtemplateformat_open[] = " @%s<%s"; const char arrayformat[] = " %-35s *__ptr%-25s"; const char arraysizeformat[] = " %-35s __size%-24s"; const char arrayoffsetformat[] = "// %-35s __offset%-22s"; const char sizeformat[] = " $%-35s __size%-24s"; const char choiceformat[] = " $%-35s __union%-23s"; const char schemaformat[] = "//gsoap %-5s schema %s:\t%s\n"; const char serviceformat[] = "//gsoap %-4s service %s:\t%s %s\n"; const char paraformat[] = " %-35s%s%s%s"; const char anonformat[] = " %-35s%s_%s%s"; const char copyrightnotice[] = "\n** The gSOAP WSDL/Schema processor for C and C++, wsdl2h release " WSDL2H_VERSION "\n** Copyright (C) 2000-2016 Robert van Engelen, Genivia Inc.\n** All Rights Reserved. This product is provided \"as is\", without any warranty.\n** The wsdl2h tool and its generated software are released under the GPL.\n** ----------------------------------------------------------------------------\n** A commercial use license is available from Genivia Inc., contact@genivia.com\n** ----------------------------------------------------------------------------\n\n"; const char licensenotice[] = "\ --------------------------------------------------------------------------------\n\ gSOAP XML Web services tools\n\ Copyright (C) 2000-2016, Robert van Engelen, Genivia Inc. All Rights Reserved.\n\ The wsdl2h tool and its generated software are released under the GPL.\n\ This software is released under the GPL with the additional exemption that\n\ compiling, linking, and/or using OpenSSL is allowed.\n\ --------------------------------------------------------------------------------\n\ GPL license.\n\ \n\ This program is free software; you can redistribute it and/or modify it under\n\ the terms of the GNU General Public License as published by the Free Software\n\ Foundation; either version 2 of the License, or (at your option) any later\n\ version.\n\ \n\ This program is distributed in the hope that it will be useful, but WITHOUT ANY\n\ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A\n\ PARTICULAR PURPOSE. See the GNU General Public License for more details.\n\ \n\ You should have received a copy of the GNU General Public License along with\n\ this program; if not, write to the Free Software Foundation, Inc., 59 Temple\n\ Place, Suite 330, Boston, MA 02111-1307 USA\n\ \n\ Author contact information:\n\ engelen@genivia.com / engelen@acm.org\n\ \n\ This program is released under the GPL with the additional exemption that\n\ compiling, linking, and/or using OpenSSL is allowed.\n\ --------------------------------------------------------------------------------\n\ A commercial-use license is available from Genivia, Inc., contact@genivia.com\n\ --------------------------------------------------------------------------------\n"; int main(int argc, char **argv) { fprintf(stderr, "%s", copyrightnotice); options(argc, argv); init(); if (cppnamespace) fprintf(stream, "namespace %s {\n", cppnamespace); Definitions def; wsdl__definitions definitions; definitions.read(infiles, infile); if (definitions.error()) { definitions.print_fault(); exit(1); } definitions.traverse(); def.compile(definitions); if (outfile) { fclose(stream); fprintf(stderr, "\nTo finalize code generation, execute:\n> soapcpp2 %s\n", outfile); if (!cflag) fprintf(stderr, "Or to generate C++ proxy and service classes:\n> soapcpp2 -j %s\n", outfile); fprintf(stderr, "\n"); } return 0; } //////////////////////////////////////////////////////////////////////////////// // // Initialization // //////////////////////////////////////////////////////////////////////////////// static void init() { struct Namespace *p = namespaces; if (p) { for (; p->id; p++) { if (p->in && *p->in) exturis.insert(p->in); if (p->ns && *p->ns) exturis.insert(p->ns); } } } //////////////////////////////////////////////////////////////////////////////// // // Parse command line options // //////////////////////////////////////////////////////////////////////////////// static void options(int argc, char **argv) { int i; infiles = 0; openfiles = 0; for (i = 1; i < argc; i++) { char *a = argv[i]; if (*a == '-' #ifdef WIN32 || *a == '/' #endif ) { int g = 1; while (g && *++a) { switch (*a) { case '_': _flag = 1; break; case 'a': aflag = 1; break; case 'b': bflag = 1; break; case 'c': if (a[1] == '+' && a[2] == '+') { a += 2; if (a[1] == '1' && a[2] == '1') { a += 2; c11flag = 1; } cflag = 0; } else { cflag = 1; if (cppnamespace) fprintf(stderr, "wsdl2h: Options -c and -q cannot be used together\n"); } break; case 'd': dflag = 1; break; case 'e': eflag = 1; break; case 'f': fflag = 1; break; case 'g': gflag = 1; break; case 'i': iflag = 1; break; case 'j': jflag = 1; break; case 'k': kflag = 1; break; case 'I': a++; g = 0; if (*a) import_path = a; else if (i < argc && argv[++i]) import_path = argv[i]; else fprintf(stderr, "wsdl2h: Option -I requires a path argument\n"); break; case 'l': fprintf(stderr, "%s", licensenotice); exit(0); break; case 'm': mflag = 1; break; case 'M': Mflag = 1; break; case 'n': a++; g = 0; if (*a) schema_prefix = a; else if (i < argc && argv[++i]) schema_prefix = argv[i]; else fprintf(stderr, "wsdl2h: Option -n requires a prefix name argument\n"); break; case 'N': a++; g = 0; if (*a) service_prefix = a; else if (i < argc && argv[++i]) service_prefix = argv[i]; else fprintf(stderr, "wsdl2h: Option -N requires a prefix name argument\n"); break; case 'o': a++; g = 0; if (*a) outfile = a; else if (i < argc && argv[++i]) outfile = argv[i]; else fprintf(stderr, "wsdl2h: Option -o requires an output file argument\n"); break; case 'p': pflag = 1; break; case 'P': Pflag = 1; break; case 'q': a++; g = 0; if (*a) cppnamespace = a; else if (i < argc && argv[++i]) cppnamespace = argv[i]; else fprintf(stderr, "wsdl2h: Option -q requires a C++ namespace name argument\n"); if (cflag) fprintf(stderr, "wsdl2h: Options -c and -q cannot be used together\n"); break; case 'r': a++; g = 0; if (*a) proxy_host = a; else if (i < argc && argv[++i]) proxy_host = argv[i]; else fprintf(stderr, "wsdl2h: Option -r requires proxy host:port:userid:passwd or :userid:passwd authentication argument\n"); if (proxy_host) { size_t l = strlen(proxy_host); char *s = (char*)emalloc(l + 1); soap_strcpy(s, l + 2, proxy_host); proxy_host = s; s = strchr(proxy_host, ':'); if (s) { *s = '\0'; if (*proxy_host) { proxy_port = soap_strtol(s + 1, &s, 10); if (s && *s == ':') { *s = '\0'; proxy_userid = s + 1; s = strchr(proxy_userid, ':'); if (s && *s == ':') { *s = '\0'; proxy_passwd = s + 1; } } } else { s = proxy_host; proxy_host = NULL; auth_userid = s + 1; s = strchr(auth_userid, ':'); if (s && *s == ':') { *s = '\0'; auth_passwd = s + 1; } } } } break; case 'R': Rflag = 1; break; case 's': sflag = 1; break; case 't': a++; g = 0; if (*a) mapfile = a; else if (i < argc && argv[++i]) mapfile = argv[i]; else fprintf(stderr, "wsdl2h: Option -t requires a type map file argument\n"); break; case 'U': Uflag = 1; break; case 'u': uflag = 1; break; case 'v': vflag = 1; break; case 'w': wflag = 1; break; case 'W': Wflag = 1; break; case 'x': xflag = 1; break; case 'y': yflag = 1; break; case 'z': a++; g = 0; if (*a) zflag = soap_strtol(a, NULL, 10); else if (i < argc && argv[++i]) zflag = soap_strtol(argv[i], NULL, 10); else zflag = 1; break; case '?': case 'h': fprintf(stderr, "Usage: wsdl2h [-a] [-b] [-c|-c++|-c++11] [-d] [-e] [-f] [-g] [-h] [-I path] [-i] [-j] [-k] [-l] [-m] [-M] [-N name] [-n name] [-P|-p] [-q name] [-R] [-r proxyhost[:port[:uid:pwd]]] [-r:userid:passwd] [-s] [-t typemapfile] [-U] [-u] [-v] [-w] [-W] [-x] [-y] [-z#] [-_] [-o outfile.h] infile.wsdl infile.xsd http://www... ...\n\n"); fprintf(stderr, "\ -a generate indexed struct names for local elements with anonymous types\n\ -b bi-directional operations (duplex ops) added to serve one-way responses\n\ -c generate C source code\n\ -c++ generate C++ source code (default)\n\ -c++11 generate C++11 source code\n\ -d use DOM to populate xs:any, xs:anyType, and xs:anyAttribute\n\ -e don't qualify enum names\n\ -f generate flat C++ class hierarchy\n\ -g generate global top-level element declarations\n\ -h display help info\n\ -Ipath use path to find files\n\ -i don't import (advanced option)\n\ -j don't generate SOAP_ENV__Header and SOAP_ENV__Detail definitions\n\ -k don't generate SOAP_ENV__Header mustUnderstand qualifiers\n\ -l display license information\n\ -m use xsd.h module to import primitive types\n\ -M suppress error \"must understand element with wsdl:required='true'\"\n\ -Nname use name for service prefixes to produce a service for each binding\n\ -nname use name as the base namespace prefix instead of 'ns'\n\ -ofile output to file\n\ -P don't create polymorphic types inherited from xsd__anyType\n\ -p create polymorphic types inherited from base xsd__anyType\n\ -qname use name for the C++ namespace of all declarations\n\ -R generate REST operations for REST bindings in the WSDL\n\ -rhost[:port[:uid:pwd]]\n\ connect via proxy host, port, and proxy credentials\n\ -r:uid:pwd\n\ connect with authentication credentials (digest auth requires SSL)\n\ -s don't generate STL code (no std::string and no std::vector)\n\ -tfile use type map file instead of the default file typemap.dat\n\ -U allow UTF8-encoded Unicode C/C++ identifiers when mapping XML tag names\n\ -u don't generate unions\n\ -v verbose output\n\ -W suppress warnings\n\ -w always wrap response parameters in a response struct (<=1.1.4 behavior)\n\ -x don't generate _XML any/anyAttribute extensibility elements\n\ -y generate typedef synonyms for structs and enums\n\ -z1 compatibility with 2.7.6e: generate pointer-based arrays\n\ -z2 compatibility with 2.7.7 to 2.7.15: qualify element/attribute references\n\ -z3 compatibility with 2.7.16 to 2.8.7: qualify element/attribute references\n\ -z4 compatibility up to 2.8.11: don't generate union structs in std::vector\n\ -z5 compatibility up to 2.8.15\n\ -z6 compatibility up to 2.8.17\n\ -_ don't generate _USCORE (replace with UNICODE _x005f)\n\ infile.wsdl infile.xsd http://www... list of input sources (if none: use stdin)\n\ \n"); exit(0); default: fprintf(stderr, "wsdl2h: Unknown option %s\n", a); exit(1); } } } else { infile[infiles++] = argv[i]; if (infiles >= MAXINFILES) { fprintf(stderr, "wsdl2h: too many files\n"); exit(1); } } } if (infiles) { if (!outfile) { if (strncmp(infile[0], "http://", 7) && strncmp(infile[0], "https://", 8)) { const char *s = strrchr(infile[0], '.'); if (s && (!soap_tag_cmp(s, ".wsdl") || !soap_tag_cmp(s, ".gwsdl") || !soap_tag_cmp(s, ".xsd"))) { outfile = estrdup(infile[0]); outfile[s - infile[0] + 1] = 'h'; outfile[s - infile[0] + 2] = '\0'; } else { size_t l = strlen(infile[0]); outfile = (char*)emalloc(l + 3); soap_strcpy(outfile, l + 3, infile[0]); soap_strcpy(outfile + l, 3, ".h"); } } } if (outfile) { stream = fopen(outfile, "w"); if (!stream) { fprintf(stderr, "Cannot write to %s\n", outfile); exit(1); } fprintf(stderr, "Saving %s\n\n", outfile); } } } //////////////////////////////////////////////////////////////////////////////// // // Namespaces // //////////////////////////////////////////////////////////////////////////////// struct Namespace namespaces[] = { {"SOAP-ENV", "http://schemas.xmlsoap.org/soap/envelope/", "http://www.w3.org/*/soap-envelope"}, {"SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/", "http://www.w3.org/*/soap-encoding"}, {"xsi", "http://www.w3.org/2001/XMLSchema-instance"}, {"xsd", "-"}, // http://www.w3.org/2001/XMLSchema"}, // don't use this, it might conflict with xs {"xml", "http://www.w3.org/XML/1998/namespace"}, {"xs", "http://www.w3.org/2001/XMLSchema", "http://www.w3.org/*/XMLSchema" }, {"vc", "http://www.w3.org/2007/XMLSchema-versioning" }, {"http", "http://schemas.xmlsoap.org/wsdl/http/"}, {"soap", "http://schemas.xmlsoap.org/wsdl/soap/", "http://schemas.xmlsoap.org/wsdl/soap*/"}, {"mime", "http://schemas.xmlsoap.org/wsdl/mime/"}, {"xmime", "http://www.w3.org/2005/05/xmlmime"}, {"dime", "http://schemas.xmlsoap.org/ws/2002/04/dime/wsdl/", "http://schemas.xmlsoap.org/ws/*/dime/wsdl/"}, {"wsdl", "http://schemas.xmlsoap.org/wsdl/", "http://www.w3.org/ns/wsdl"}, {"wsdli", "http://www.w3.org/ns/wsdl-instance"}, {"wsdlx", "http://www.w3.org/ns/wsdl-extensions"}, {"wsoap", "http://www.w3.org/ns/wsdl/soap"}, {"whttp", "http://www.w3.org/ns/wsdl/http"}, {"wrpc", "http://www.w3.org/ns/wsdl/rpc"}, {"wsaw", "http://www.w3.org/2006/05/addressing/wsdl"}, {"gwsdl", "http://www.gridforum.org/namespaces/2003/03/gridWSDLExtensions"}, {"wsa_", "http://www.w3.org/2005/08/addressing"}, {"wsam", "http://www.w3.org/2007/05/addressing/metadata"}, {"wsrmp", "http://docs.oasis-open.org/ws-rx/wsrm/200702", "http://docs.oasis-open.org/ws-rx/wsrm/*"}, {"wsrmp5", "http://schemas.xmlsoap.org/ws/2005/02/rm/policy"}, {"sp", "http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702", "http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"}, {"wsp_", "http://www.w3.org/ns/ws-policy", "http://schemas.xmlsoap.org/ws/2004/09/policy"}, {"wst_", "http://docs.oasis-open.org/ws-sx/ws-trust/200512"}, {"wsu_", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"}, {"plnk","http://docs.oasis-open.org/wsbpel/2.0/plnktype"}, {"vprop","http://docs.oasis-open.org/wsbpel/2.0/varprop"}, #ifdef WITH_BPEL {"bpel","http://docs.oasis-open.org/wsbpel/2.0/process/executable"}, {"sref","http://docs.oasis-open.org/wsbpel/2.0/serviceref"}, #endif {NULL, NULL} };