source: trunk/zoo-project/zoo-kernel/zoo_loader.c @ 331

Revision 331, 9.6 KB checked in by djay, 3 years ago (diff)

Add the multi-part request support.

Line 
1/**
2 * Author : Gérald FENOY
3 *
4 *  Copyright 2008-2011 GeoLabs SARL. All rights reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25#define MALLOC_CHECK_ 0
26#define MALLOC_CHECK 0
27
28#ifdef WIN32
29#include "windows.h"
30#endif
31/**
32 * Specific includes
33 */
34#include "fcgio.h"
35#include "fcgi_config.h"
36#include "fcgi_stdio.h"
37#include <sys/types.h>
38#include <unistd.h>
39#include "service_internal.h"
40
41extern "C" {
42#include "cgic.h"
43#include <libxml/tree.h>
44#include <libxml/xmlmemory.h>
45#include <libxml/parser.h>
46#include <libxml/xpath.h>
47#include <libxml/xpathInternals.h>
48}
49
50#include "service_internal.h"
51
52xmlXPathObjectPtr extractFromDoc(xmlDocPtr,const char*);
53int runRequest(map*);
54
55using namespace std;
56
57#define TRUE 1
58#define FALSE -1
59
60int cgiMain(){
61  /**
62   * We'll use cgiOut as the default output (stdout) to produce plain text
63   * response.
64   */
65  dup2(fileno(cgiOut),fileno(stdout));
66#ifdef DEBUG
67  fprintf(cgiOut,"Content-Type: text/plain; charset=utf-8\r\nStatus: 200 OK\r\n\r\n");
68  fprintf(cgiOut,"Welcome on ZOO verbose debuging mode \r\n\r\n");
69  fflush(cgiOut);
70#endif
71 
72#ifdef DEBUG
73  fprintf (stderr, "Addr:%s\n", cgiRemoteAddr); 
74  fprintf (stderr, "RequestMethod: (%s) %d %d\n", cgiRequestMethod,strncasecmp(cgiRequestMethod,"post",4),strncmp(cgiContentType,"text/xml",8)==0 || strncasecmp(cgiRequestMethod,"post",4)==0); 
75  fprintf (stderr, "Request: %s\n", cgiQueryString);
76#endif
77
78  char *strQuery=strdup(cgiQueryString);
79  map* tmpMap=NULL;
80
81  if(strncmp(cgiContentType,"text/xml",8)==0 || 
82     strncasecmp(cgiRequestMethod,"post",4)==0){
83    if(cgiContentLength==NULL){
84       cgiContentLength=0;
85       char *buffer=new char[2];
86       char *res=NULL;
87       int r=0;
88       while(r=fread(buffer,sizeof(char),1,cgiIn)){
89         cgiContentLength+=r;
90         if(res==NULL){
91           res=(char*)malloc(1*sizeof(char));
92           sprintf(res,"%s",buffer);
93         }
94         else{
95           res=(char*)realloc(res,(cgiContentLength+1)*sizeof(char));
96           char *tmp=strdup(res);
97           sprintf(res,"%s%s",tmp,buffer);
98           free(tmp);
99         }
100       }
101       if(res==NULL){
102         return errorException(NULL,"ZOO-Kernel failed to process your request cause the request was emtpty.","InternalError");
103       }else
104         tmpMap=createMap("request",res);
105    }else{
106      char *buffer=new char[cgiContentLength+1];
107      if(fread(buffer,sizeof(char),cgiContentLength,cgiIn)){
108        buffer[cgiContentLength]=0;
109        tmpMap=createMap("request",buffer);
110        fprintf(stderr,"%s\n",tmpMap->value);
111      }else{
112        buffer[0]=0;
113        char **array, **arrayStep;
114        if (cgiFormEntries(&array) != cgiFormSuccess) {
115          return 1;
116        }
117        arrayStep = array;
118        while (*arrayStep) {
119          char *ivalue=new char[cgiContentLength];
120          cgiFormStringNoNewlines(*arrayStep, ivalue, cgiContentLength);
121          char* tmpValueFinal=(char*) malloc((strlen(*arrayStep)+strlen(ivalue)+1)*sizeof(char));
122          sprintf(tmpValueFinal,"%s=%s",*arrayStep,ivalue);
123          if(strlen(buffer)==0){
124            sprintf(buffer,"%s",tmpValueFinal);
125          }else{
126            char *tmp=strdup(buffer);
127            sprintf(buffer,"%s&%s",tmp,tmpValueFinal);
128            free(tmp);
129          }
130         
131          sprintf(tmpValueFinal,"%s=%s",*arrayStep,ivalue);
132          free(tmpValueFinal);
133#ifdef DEBUG
134          fprintf(stderr,"(( \n %s \n %s \n ))",*arrayStep,ivalue);
135#endif
136          delete[]ivalue;
137          arrayStep++;
138        }
139        tmpMap=createMap("request",buffer);
140      }
141      delete[]buffer;
142    }
143  }
144  else{
145    dumpMap(tmpMap);
146    char **array, **arrayStep;
147    if (cgiFormEntries(&array) != cgiFormSuccess) {
148      return 1;
149    }
150    arrayStep = array;
151    while (*arrayStep) {
152      char *value=new char[cgiContentLength];
153      cgiFormStringNoNewlines(*arrayStep, value, cgiContentLength);
154#ifdef DEBUG
155      fprintf(stderr,"(( \n %s \n %s \n ))",*arrayStep,value);
156#endif
157      if(tmpMap!=NULL)
158        addToMap(tmpMap,*arrayStep,value);
159      else
160        tmpMap=createMap(*arrayStep,value);
161      arrayStep++;
162      delete[]value;
163    }
164    cgiStringArrayFree(array);
165  }
166
167  /**
168   * In case that the POST method was used, then check if params came in XML
169   * format else try to use the attribute "request" which should be the only
170   * one.
171   */
172  if(strncasecmp(cgiRequestMethod,"post",4)==0 || 
173     (count(tmpMap)==1 && strncmp(tmpMap->value,"<",1)==0)){
174    /**
175     * First include the MetaPath and the ServiceProvider default parameters
176     * (which should be always available in GET params so in cgiQueryString)
177     */
178    char *str1;
179    str1=cgiQueryString;
180    /**
181     * Store the original XML request in xrequest map
182     */
183    map* t1=getMap(tmpMap,"request");
184    if(t1!=NULL && strncasecmp(t1->value,"<",1)==0){
185      addToMap(tmpMap,"xrequest",t1->value);
186      xmlInitParser();
187      xmlDocPtr doc = xmlParseMemory(t1->value,cgiContentLength);
188
189
190      {
191        xmlXPathObjectPtr reqptr=extractFromDoc(doc,"/*[local-name()='Envelope']/*[local-name()='Body']/*");
192        if(reqptr!=NULL){
193          xmlNodeSet* req=reqptr->nodesetval;
194          if(req!=NULL && req->nodeNr==1){
195            addToMap(tmpMap,"soap","true");
196            int k=0;
197            for(k;k < req->nodeNr;k++){
198              xmlNsPtr ns=xmlNewNs(req->nodeTab[k],BAD_CAST "http://www.w3.org/2001/XMLSchema-instance",BAD_CAST "xsi");
199              xmlDocSetRootElement(doc, req->nodeTab[k]);
200              xmlChar *xmlbuff;
201              int buffersize;
202              xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, "utf-8", 1);
203              addToMap(tmpMap,"xrequest",(char*)xmlbuff);
204              char *tmp=(char*)xmlbuff;
205              fprintf(stderr,"%s\n",tmp);
206              xmlFree(xmlbuff);
207            }
208          }
209        }
210      }
211
212      xmlNodePtr cur = xmlDocGetRootElement(doc);
213      char *tval;
214      tval=NULL;
215      tval = (char*) xmlGetProp(cur,BAD_CAST "service");
216      if(tval!=NULL)
217        addToMap(tmpMap,"service",tval);
218      tval=NULL;
219      tval = (char*) xmlGetProp(cur,BAD_CAST "language");
220      if(tval!=NULL)
221        addToMap(tmpMap,"language",tval);
222      const char* requests[3]={"GetCapabilities","DescribeProcess","Execute"};
223      for(int j=0;j<3;j++){
224        char tt[128];
225        sprintf(tt,"/*[local-name()='%s']",requests[j]);
226        xmlXPathObjectPtr reqptr=extractFromDoc(doc,tt);
227        if(reqptr!=NULL){
228          xmlNodeSet* req=reqptr->nodesetval;
229#ifdef DEBUG
230          fprintf(stderr,"%i",req->nodeNr);
231#endif
232          if(req!=NULL && req->nodeNr==1){
233            t1->value=strdup(requests[j]);
234            j=2;
235          }
236          xmlXPathFreeObject(reqptr);
237        }
238        //xmlFree(req);
239      }
240      if(strncasecmp(t1->value,"GetCapabilities",15)==0){
241        xmlXPathObjectPtr versptr=extractFromDoc(doc,"/*/*/*[local-name()='Version']");
242        xmlNodeSet* vers=versptr->nodesetval;
243        xmlChar* content=xmlNodeListGetString(doc, vers->nodeTab[0]->xmlChildrenNode,1);
244        addToMap(tmpMap,"version",(char*)content);
245        xmlXPathFreeObject(versptr);
246        //xmlFree(vers);
247        xmlFree(content);
248      }else{
249        tval=NULL;
250        tval = (char*) xmlGetProp(cur,BAD_CAST "version");
251        if(tval!=NULL)
252          addToMap(tmpMap,"version",tval);
253        xmlFree(tval);
254        tval = (char*) xmlGetProp(cur,BAD_CAST "language");
255        if(tval!=NULL)
256          addToMap(tmpMap,"language",tval);
257        xmlXPathObjectPtr idptr=extractFromDoc(doc,"/*/*[local-name()='Identifier']");
258        if(idptr!=NULL){
259          xmlNodeSet* id=idptr->nodesetval;
260          if(id!=NULL){
261            char* identifiers=NULL;
262            identifiers=(char*)calloc(cgiContentLength,sizeof(char));
263            identifiers[0]=0;
264            for(int k=0;k<id->nodeNr;k++){
265              xmlChar* content=xmlNodeListGetString(doc, id->nodeTab[k]->xmlChildrenNode,1);
266              if(strlen(identifiers)>0){
267                char *tmp=strdup(identifiers);
268                snprintf(identifiers,strlen(tmp)+xmlStrlen(content)+2,"%s,%s",tmp,content);
269                free(tmp);
270              }
271              else{
272                snprintf(identifiers,xmlStrlen(content)+1,"%s",content);
273              }
274              xmlFree(content);
275            }
276            xmlXPathFreeObject(idptr);
277            addToMap(tmpMap,"Identifier",identifiers);
278            free(identifiers);
279          }
280        }
281        //xmlFree(id);
282      }
283      xmlFree(tval);
284      xmlFreeDoc(doc);
285      xmlCleanupParser();
286    }else{
287      freeMap(&tmpMap);
288      free(tmpMap);
289      tmpMap=createMap("not_valid","true");
290    }
291
292    char *token,*saveptr;
293    token=strtok_r(cgiQueryString,"&",&saveptr);
294    while(token!=NULL){
295      char *token1,*saveptr1;
296      char *name=NULL;
297      char *value=NULL;
298      token1=strtok_r(token,"=",&saveptr1);
299      while(token1!=NULL){
300        if(name==NULL)
301          name=strdup(token1);
302        else
303          value=strdup(token1);
304        token1=strtok_r(NULL,"=",&saveptr1);
305      }
306      addToMap(tmpMap,name,value);
307      free(name);
308      free(value);
309      name=NULL;
310      value=NULL;
311      token=strtok_r(NULL,"&",&saveptr);
312    }
313   
314  }
315
316
317  if(strncasecmp(cgiContentType,"multipart/form-data",19)==0){
318      map* tmp=getMap(tmpMap,"dataInputs");
319      if(tmp!=NULL){
320        addToMap(tmpMap,"dataInputs",strstr(strQuery,"dataInputs=")+11);
321      }
322    }
323
324  runRequest(tmpMap);
325
326  /**
327   * Required but can't be made after executing a process using POST requests.
328   */
329  if(strncasecmp(cgiRequestMethod,"post",4)!=0 && count(tmpMap)!=1 && tmpMap!=NULL){
330    freeMap(&tmpMap);
331    free(tmpMap);
332  }
333  return 0;
334
335}
Note: See TracBrowser for help on using the repository browser.