source: trunk/zoo-project/zoo-kernel/zoo_service_loader.c @ 459

Last change on this file since 459 was 459, checked in by djay, 10 years ago

Initial introduction of Value and Range in AllowedValues?, update zcfg documentation. Return valid Status code when returning ExceptionRepport?.

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc
File size: 67.4 KB
Line 
1/**
2 * Author : Gérald FENOY
3 *
4 *  Copyright 2008-2013 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 length(x) (sizeof(x) / sizeof(x[0]))
26
27extern "C" int yylex();
28extern "C" int crlex();
29
30#include "cgic.h"
31
32extern "C" {
33#include <libxml/tree.h>
34#include <libxml/xmlmemory.h>
35#include <libxml/parser.h>
36#include <libxml/xpath.h>
37#include <libxml/xpathInternals.h>
38}
39
40#include "ulinet.h"
41
42#include <libintl.h>
43#include <locale.h>
44#include <string.h>
45
46#include "service.h"
47
48#include "service_internal.h"
49
50#ifdef USE_PYTHON
51#include "service_internal_python.h"
52#endif
53
54#ifdef USE_JAVA
55#include "service_internal_java.h"
56#endif
57
58#ifdef USE_PHP
59#include "service_internal_php.h"
60#endif
61
62#ifdef USE_JS
63#include "service_internal_js.h"
64#endif
65
66#ifdef USE_RUBY
67#include "service_internal_ruby.h"
68#endif
69
70#ifdef USE_PERL
71#include "service_internal_perl.h"
72#endif
73
74#include <dirent.h>
75#include <signal.h>
76#include <unistd.h>
77#ifndef WIN32
78#include <dlfcn.h>
79#include <libgen.h>
80#else
81#include <windows.h>
82#include <direct.h>
83#include <sys/types.h>
84#include <sys/stat.h>
85#include <unistd.h>
86#define pid_t int;
87#endif
88#include <fcntl.h>
89#include <time.h>
90#include <stdarg.h>
91
92#ifdef WIN32
93extern "C" {
94  __declspec(dllexport) char *strcasestr(char const *a, char const *b)
95#ifndef USE_MS
96 { 
97  char *x=_zStrdup(a); 
98  char *y=_zStrdup(b); 
99 
100  x=_strlwr(x); 
101  y=_strlwr(y); 
102  char *pos = strstr(x, y); 
103  char *ret = pos == NULL ? NULL : (char *)(a + (pos-x)); 
104  free(x); 
105  free(y); 
106  return ret; 
107 };
108#else
109  ;
110#endif
111}
112#endif
113
114#define _(String) dgettext ("zoo-kernel",String)
115#define __(String) dgettext ("zoo-service",String)
116
117
118void translateChar(char* str,char toReplace,char toReplaceBy){
119  int i=0,len=strlen(str);
120  for(i=0;i<len;i++){
121    if(str[i]==toReplace)
122      str[i]=toReplaceBy;
123  }
124}
125
126/**
127 * Create (or append to) an array valued maps
128 * value = "["",""]"
129 */
130int appendMapsToMaps(maps* m,maps* mo,maps* mi,elements* elem){
131  maps* tmpMaps=getMaps(mo,mi->name);
132  map* tmap=getMapType(tmpMaps->content);
133  elements* el=getElements(elem,mi->name);
134  int hasEl=1;
135  if(el==NULL)
136    hasEl=-1;
137  if(tmap==NULL){
138    if(hasEl>0)
139      tmap=getMapType(el->defaults->content);     
140  }
141
142  map* testMap=NULL;
143  if(hasEl>0){
144    testMap=getMap(el->content,"maxOccurs");
145  }else{
146    testMap=createMap("maxOccurs","unbounded");
147  }
148
149  if(testMap!=NULL){
150    if(strncasecmp(testMap->value,"unbounded",9)!=0 && atoi(testMap->value)>1){
151      if(addMapsArrayToMaps(&mo,mi,tmap->name)<0){
152        char emsg[1024];
153        sprintf(emsg,_("You set maximum occurences for <%s> as %i but you tried to use it more than the limit you set. Please correct your ZCFG file or your request."),mi->name,atoi(testMap->value));
154        errorException(m,emsg,"InternalError",NULL);
155        return -1;
156      }
157    }else{
158      if(strncasecmp(testMap->value,"unbounded",9)==0){
159        if(hasEl<0){
160          freeMap(&testMap);
161          free(testMap);
162        }
163        if(addMapsArrayToMaps(&mo,mi,tmap->name)<0){
164          char emsg[1024];
165          map* tmpMap=getMap(mi->content,"length");
166          sprintf(emsg,_("ZOO-Kernel was unable to load your data for %s position %s."),mi->name,tmpMap->value);
167          errorException(m,emsg,"InternalError",NULL);
168          return -1;
169        }
170      }
171      else{
172        char emsg[1024];
173        sprintf(emsg,_("You set maximum occurences for <%s> to one but you tried to use it more than once. Please correct your ZCFG file or your request."),mi->name);
174        errorException(m,emsg,"InternalError",NULL);
175        return -1;
176      }
177    }
178  }
179  return 0;
180}
181
182xmlXPathObjectPtr extractFromDoc(xmlDocPtr doc,const char* search){
183  xmlXPathContextPtr xpathCtx;
184  xmlXPathObjectPtr xpathObj;
185  xpathCtx = xmlXPathNewContext(doc);
186  xpathObj = xmlXPathEvalExpression(BAD_CAST search,xpathCtx);
187  xmlXPathFreeContext(xpathCtx);
188  return xpathObj;
189}
190
191void donothing(int sig){
192  fprintf(stderr,"Signal %d after the ZOO-Kernel returned result !\n",sig);
193  exit(0);
194}
195
196void sig_handler(int sig){
197  char tmp[100];
198  const char *ssig;
199  switch(sig){
200  case SIGSEGV:
201    ssig="SIGSEGV";
202    break;
203  case SIGTERM:
204    ssig="SIGTERM";
205    break;
206  case SIGINT:
207    ssig="SIGINT";
208    break;
209  case SIGILL:
210    ssig="SIGILL";
211    break;
212  case SIGFPE:
213    ssig="SIGFPE";
214    break;
215  case SIGABRT:
216    ssig="SIGABRT";
217    break;
218  default:
219    ssig="UNKNOWN";
220    break;
221  }
222  sprintf(tmp,_("ZOO Kernel failed to process your request receiving signal %d = %s"),sig,ssig);
223  errorException(NULL, tmp, "InternalError",NULL);
224#ifdef DEBUG
225  fprintf(stderr,"Not this time!\n");
226#endif
227  exit(0);
228}
229
230void loadServiceAndRun(maps **myMap,service* s1,map* request_inputs,maps **inputs,maps** ioutputs,int* eres){
231  char tmps1[1024];
232  char ntmp[1024];
233  maps *m=*myMap;
234  maps *request_output_real_format=*ioutputs;
235  maps *request_input_real_format=*inputs;
236  /**
237   * Extract serviceType to know what kind of service should be loaded
238   */
239  map* r_inputs=NULL;
240#ifndef WIN32
241  char* pntmp=getcwd(ntmp,1024);
242#else
243  _getcwd(ntmp,1024);
244#endif
245  r_inputs=getMap(s1->content,"serviceType");
246#ifdef DEBUG
247  fprintf(stderr,"LOAD A %s SERVICE PROVIDER \n",r_inputs->value);
248  fflush(stderr);
249#endif
250  if(strlen(r_inputs->value)==1 && strncasecmp(r_inputs->value,"C",1)==0){
251    r_inputs=getMap(request_inputs,"metapath");
252    if(r_inputs!=NULL)
253      sprintf(tmps1,"%s/%s",ntmp,r_inputs->value);
254    else
255      sprintf(tmps1,"%s/",ntmp);
256    char *altPath=zStrdup(tmps1);
257    r_inputs=getMap(s1->content,"ServiceProvider");
258    sprintf(tmps1,"%s/%s",altPath,r_inputs->value);
259    free(altPath);
260#ifdef DEBUG
261    fprintf(stderr,"Trying to load %s\n",tmps1);
262#endif
263#ifdef WIN32
264    HINSTANCE so = LoadLibraryEx(tmps1,NULL,LOAD_WITH_ALTERED_SEARCH_PATH);
265#else
266    void* so = dlopen(tmps1, RTLD_LAZY);
267#endif
268#ifdef DEBUG
269#ifdef WIN32
270    DWORD errstr;
271    errstr = GetLastError();
272    fprintf(stderr,"%s loaded (%d) \n",tmps1,errstr);
273#else
274    char *errstr;
275    errstr = dlerror();
276#endif
277#endif
278    if( so != NULL ) {
279#ifdef DEBUG
280      fprintf(stderr,"Library loaded %s \n",errstr);
281      fprintf(stderr,"Service Shared Object = %s\n",r_inputs->value);
282#endif
283      r_inputs=getMap(s1->content,"serviceType");
284#ifdef DEBUG
285      dumpMap(r_inputs);
286      fprintf(stderr,"%s\n",r_inputs->value);
287      fflush(stderr);
288#endif
289      if(strncasecmp(r_inputs->value,"C-FORTRAN",9)==0){
290        r_inputs=getMap(request_inputs,"Identifier");
291        char fname[1024];
292        sprintf(fname,"%s_",r_inputs->value);
293#ifdef DEBUG
294        fprintf(stderr,"Try to load function %s\n",fname);
295#endif
296#ifdef WIN32
297        typedef int (CALLBACK* execute_t)(char***,char***,char***);
298        execute_t execute=(execute_t)GetProcAddress(so,fname);
299#else
300        typedef int (*execute_t)(char***,char***,char***);
301        execute_t execute=(execute_t)dlsym(so,fname);
302#endif
303#ifdef DEBUG
304#ifdef WIN32
305        errstr = GetLastError();
306#else
307        errstr = dlerror();
308#endif
309        fprintf(stderr,"Function loaded %s\n",errstr);
310#endif 
311
312        char main_conf[10][30][1024];
313        char inputs[10][30][1024];
314        char outputs[10][30][1024];
315        for(int i=0;i<10;i++){
316          for(int j=0;j<30;j++){
317            memset(main_conf[i][j],0,1024);
318            memset(inputs[i][j],0,1024);
319            memset(outputs[i][j],0,1024);
320          }
321        }
322        mapsToCharXXX(m,(char***)main_conf);
323        mapsToCharXXX(request_input_real_format,(char***)inputs);
324        mapsToCharXXX(request_output_real_format,(char***)outputs);
325        *eres=execute((char***)&main_conf[0],(char***)&inputs[0],(char***)&outputs[0]);
326#ifdef DEBUG
327        fprintf(stderr,"Function run successfully \n");
328#endif
329        charxxxToMaps((char***)&outputs[0],&request_output_real_format);
330      }else{
331#ifdef DEBUG
332#ifdef WIN32
333        errstr = GetLastError();
334        fprintf(stderr,"Function %s failed to load because of %d\n",r_inputs->value,errstr);
335#endif
336#endif
337        r_inputs=getMap(request_inputs,"Identifier");
338#ifdef DEBUG
339        fprintf(stderr,"Try to load function %s\n",r_inputs->value);
340#endif
341        typedef int (*execute_t)(maps**,maps**,maps**);
342#ifdef WIN32
343        execute_t execute=(execute_t)GetProcAddress(so,r_inputs->value); 
344#else
345        execute_t execute=(execute_t)dlsym(so,r_inputs->value);
346#endif
347
348#ifdef DEBUG
349#ifdef WIN32
350        errstr = GetLastError();
351#else
352        errstr = dlerror();
353#endif
354        fprintf(stderr,"Function loaded %s\n",errstr);
355#endif 
356
357#ifdef DEBUG
358        fprintf(stderr,"Now run the function \n");
359        fflush(stderr);
360#endif
361        *eres=execute(&m,&request_input_real_format,&request_output_real_format);
362#ifdef DEBUG
363        fprintf(stderr,"Function loaded and returned %d\n",eres);
364        fflush(stderr);
365#endif
366      }
367#ifdef WIN32
368      *ioutputs=dupMaps(&request_output_real_format);
369      FreeLibrary(so);
370#else
371      dlclose(so);
372#endif
373    } else {
374      /**
375       * Unable to load the specified shared library
376       */
377      char tmps[1024];
378#ifdef WIN32
379      DWORD errstr = GetLastError();
380#else
381      char* errstr = dlerror();
382#endif
383      sprintf(tmps,_("C Library can't be loaded %s"),errstr);
384      map* tmps1=createMap("text",tmps);
385      printExceptionReportResponse(m,tmps1);
386      *eres=-1;
387    }
388  }
389  else
390#ifdef USE_PYTHON
391    if(strncasecmp(r_inputs->value,"PYTHON",6)==0){
392      *eres=zoo_python_support(&m,request_inputs,s1,&request_input_real_format,&request_output_real_format);
393    }
394    else
395#endif
396       
397#ifdef USE_JAVA
398      if(strncasecmp(r_inputs->value,"JAVA",4)==0){
399        *eres=zoo_java_support(&m,request_inputs,s1,&request_input_real_format,&request_output_real_format);
400      }
401      else
402#endif
403
404#ifdef USE_PHP
405        if(strncasecmp(r_inputs->value,"PHP",3)==0){
406          *eres=zoo_php_support(&m,request_inputs,s1,&request_input_real_format,&request_output_real_format);
407        }
408        else
409#endif
410           
411           
412#ifdef USE_PERL
413          if(strncasecmp(r_inputs->value,"PERL",4)==0){
414            *eres=zoo_perl_support(&m,request_inputs,s1,&request_input_real_format,&request_output_real_format);
415          }
416          else
417#endif
418
419#ifdef USE_JS
420            if(strncasecmp(r_inputs->value,"JS",2)==0){
421              *eres=zoo_js_support(&m,request_inputs,s1,&request_input_real_format,&request_output_real_format);
422            }
423            else
424#endif
425
426#ifdef USE_RUBY
427          if(strncasecmp(r_inputs->value,"Ruby",4)==0){
428            *eres=zoo_ruby_support(&m,request_inputs,s1,&request_input_real_format,&request_output_real_format);
429          }
430          else
431#endif
432
433              {
434                char tmpv[1024];
435                sprintf(tmpv,_("Programming Language (%s) set in ZCFG file is not currently supported by ZOO Kernel.\n"),r_inputs->value);
436                map* tmps=createMap("text",tmpv);
437                printExceptionReportResponse(m,tmps);
438                *eres=-1;
439              }
440  *myMap=m;
441  *ioutputs=request_output_real_format;
442}
443
444
445#ifdef WIN32
446/**
447 * createProcess function: create a new process after setting some env variables
448 */
449void createProcess(maps* m,map* request_inputs,service* s1,char* opts,int cpid, maps* inputs,maps* outputs){
450  STARTUPINFO si;
451  PROCESS_INFORMATION pi;
452  ZeroMemory( &si, sizeof(si) );
453  si.cb = sizeof(si);
454  ZeroMemory( &pi, sizeof(pi) );
455  char *tmp=(char *)malloc((1024+cgiContentLength)*sizeof(char));
456  char *tmpq=(char *)malloc((1024+cgiContentLength)*sizeof(char));
457  map *req=getMap(request_inputs,"request");
458  map *id=getMap(request_inputs,"identifier");
459  map *di=getMap(request_inputs,"DataInputs");
460
461  char *dataInputsKVP=getMapsAsKVP(inputs,cgiContentLength,0);
462  char *dataOutputsKVP=getMapsAsKVP(outputs,cgiContentLength,1);
463#ifdef DEBUG
464  fprintf(stderr,"DATAINPUTSKVP %s\n",dataInputsKVP);
465  fprintf(stderr,"DATAOUTPUTSKVP %s\n",dataOutputsKVP);
466#endif
467  map *sid=getMapFromMaps(m,"lenv","sid");
468  map* r_inputs=getMapFromMaps(m,"main","tmpPath");
469  map* r_inputs1=getMap(request_inputs,"metapath");
470  int hasIn=-1;
471  if(r_inputs1==NULL){
472    r_inputs1=createMap("metapath","");
473    hasIn=1;
474  }
475  map* r_inputs2=getMap(request_inputs,"ResponseDocument");
476  if(r_inputs2==NULL)
477    r_inputs2=getMap(request_inputs,"RawDataOutput");
478  map *tmpPath=getMapFromMaps(m,"lenv","cwd");
479
480  map *tmpReq=getMap(request_inputs,"xrequest");
481  if(r_inputs2!=NULL){
482    sprintf(tmp,"\"metapath=%s&request=%s&service=WPS&version=1.0.0&Identifier=%s&DataInputs=%s&%s=%s&cgiSid=%s\"",r_inputs1->value,req->value,id->value,dataInputsKVP,r_inputs2->name,dataOutputsKVP,sid->value);
483    sprintf(tmpq,"metapath=%s&request=%s&service=WPS&version=1.0.0&Identifier=%s&DataInputs=%s&%s=%s",r_inputs1->value,req->value,id->value,dataInputsKVP,r_inputs2->name,dataOutputsKVP);
484  }
485  else{
486    sprintf(tmp,"\"metapath=%s&request=%s&service=WPS&version=1.0.0&Identifier=%s&DataInputs=%s&cgiSid=%s\"",r_inputs1->value,req->value,id->value,dataInputsKVP,sid->value);
487    sprintf(tmpq,"metapath=%s&request=%s&service=WPS&version=1.0.0&Identifier=%s&DataInputs=%s",r_inputs1->value,req->value,id->value,dataInputsKVP,sid->value);
488  }
489 
490  if(hasIn>0){
491    freeMap(&r_inputs1);
492    free(r_inputs1);
493  }
494  char *tmp1=zStrdup(tmp);
495  sprintf(tmp,"\"zoo_loader.cgi\" %s \"%s\"",tmp1,sid->value);
496 
497  free(dataInputsKVP);
498  free(dataOutputsKVP);
499#ifdef DEBUG
500  fprintf(stderr,"REQUEST IS : %s \n",tmp);
501#endif
502  SetEnvironmentVariable("CGISID",TEXT(sid->value));
503  SetEnvironmentVariable("QUERY_STRING",TEXT(tmpq));
504  char clen[1000];
505  sprintf(clen,"%d",strlen(tmpq));
506  SetEnvironmentVariable("CONTENT_LENGTH",TEXT(clen));
507 
508  if( !CreateProcess( NULL,             // No module name (use command line)
509                      TEXT(tmp),        // Command line
510                      NULL,             // Process handle not inheritable
511                      NULL,             // Thread handle not inheritable
512                      FALSE,            // Set handle inheritance to FALSE
513                      CREATE_NO_WINDOW, // Apache won't wait until the end
514                      NULL,             // Use parent's environment block
515                      NULL,             // Use parent's starting directory
516                      &si,              // Pointer to STARTUPINFO struct
517                      &pi )             // Pointer to PROCESS_INFORMATION struct
518      ) 
519    { 
520#ifdef DEBUG
521      fprintf( stderr, "CreateProcess failed (%d).\n", GetLastError() );
522#endif
523      return ;
524    }else{
525#ifdef DEBUG
526    fprintf( stderr, "CreateProcess successfull (%d).\n\n\n\n", GetLastError() );
527#endif
528  }
529  CloseHandle( pi.hProcess );
530  CloseHandle( pi.hThread );
531#ifdef DEBUG
532  fprintf(stderr,"CreateProcess finished !\n");
533#endif
534}
535#endif
536
537int runRequest(map* request_inputs)
538{
539
540#ifndef USE_GDB
541  (void) signal(SIGSEGV,sig_handler);
542  (void) signal(SIGTERM,sig_handler);
543  (void) signal(SIGINT,sig_handler);
544  (void) signal(SIGILL,sig_handler);
545  (void) signal(SIGFPE,sig_handler);
546  (void) signal(SIGABRT,sig_handler);
547#endif
548
549  map* r_inputs=NULL;
550  maps* m=NULL;
551
552  char* REQUEST=NULL;
553  /**
554   * Parsing service specfic configuration file
555   */
556  m=(maps*)malloc(MAPS_SIZE);
557  if(m == NULL){
558    return errorException(m, _("Unable to allocate memory."), "InternalError",NULL);
559  }
560  char ntmp[1024];
561#ifndef WIN32
562  char *pntmp=getcwd(ntmp,1024);
563#else
564  _getcwd(ntmp,1024);
565#endif
566  r_inputs=getMapOrFill(request_inputs,"metapath","");
567
568
569  char conf_file[10240];
570  snprintf(conf_file,10240,"%s/%s/main.cfg",ntmp,r_inputs->value);
571  if(conf_read(conf_file,m)==2){
572    errorException(NULL, _("Unable to load the main.cfg file."),"InternalError",NULL);
573    free(m);
574    return 1;
575  }
576#ifdef DEBUG
577  fprintf(stderr, "***** BEGIN MAPS\n"); 
578  dumpMaps(m);
579  fprintf(stderr, "***** END MAPS\n");
580#endif
581
582  map *getPath=getMapFromMaps(m,"main","gettextPath");
583  if(getPath!=NULL){
584    bindtextdomain ("zoo-kernel",getPath->value);
585    bindtextdomain ("zoo-services",getPath->value);   
586  }else{
587    bindtextdomain ("zoo-kernel","/usr/share/locale/");
588    bindtextdomain ("zoo-services","/usr/share/locale/");
589  }
590
591
592  /**
593   * Manage our own error log file (usefull to separate standard apache debug
594   * messages from the ZOO-Kernel ones but also for IIS users to avoid wrong
595   * headers messages returned by the CGI due to wrong redirection of stderr)
596   */
597  FILE * fstde=NULL;
598  map* fstdem=getMapFromMaps(m,"main","logPath");
599  if(fstdem!=NULL)
600    fstde = freopen(fstdem->value, "a+", stderr) ;
601
602  r_inputs=getMap(request_inputs,"language");
603  if(r_inputs==NULL)
604    r_inputs=getMapFromMaps(m,"main","language");
605  if(r_inputs!=NULL){
606    char *tmp=zStrdup(r_inputs->value);
607    setMapInMaps(m,"main","language",tmp);
608    translateChar(tmp,'-','_');
609    setlocale (LC_ALL, tmp);
610#ifndef WIN32
611    setenv("LC_ALL",tmp,1);
612#else
613    char tmp1[12];
614    sprintf(tmp1,"LC_ALL=%s",tmp);
615    putenv(tmp1);
616#endif
617    free(tmp);
618  }
619  else{
620    setlocale (LC_ALL, "en_US");
621#ifndef WIN32
622    setenv("LC_ALL","en_US",1);
623#else
624    char tmp1[12];
625    sprintf(tmp1,"LC_ALL=en_US");
626    putenv(tmp1);
627#endif
628    setMapInMaps(m,"main","language","en-US");
629  }
630  setlocale (LC_NUMERIC, "en_US");
631  bind_textdomain_codeset("zoo-kernel","UTF-8");
632  textdomain("zoo-kernel");
633  bind_textdomain_codeset("zoo-services","UTF-8");
634  textdomain("zoo-services");
635
636  map* lsoap=getMap(request_inputs,"soap");
637  if(lsoap!=NULL && strcasecmp(lsoap->value,"true")==0)
638    setMapInMaps(m,"main","isSoap","true");
639  else
640    setMapInMaps(m,"main","isSoap","false");
641
642  if(strlen(cgiServerName)>0){
643    char tmpUrl[1024];
644    sprintf(tmpUrl,"http://%s%s",cgiServerName,cgiScriptName);
645#ifdef DEBUG
646    fprintf(stderr,"*** %s ***\n",tmpUrl);
647#endif
648    setMapInMaps(m,"main","serverAddress",tmpUrl);
649  }
650
651  /**
652   * Check for minimum inputs
653   */
654  r_inputs=getMap(request_inputs,"Request");
655  if(request_inputs==NULL || r_inputs==NULL){ 
656    errorException(m, _("Parameter <request> was not specified"),"MissingParameterValue","request");
657    freeMaps(&m);
658    free(m);
659    return 1;
660  }
661  else{
662    REQUEST=zStrdup(r_inputs->value);
663    if(strncasecmp(r_inputs->value,"GetCapabilities",15)!=0
664       && strncasecmp(r_inputs->value,"DescribeProcess",15)!=0
665       && strncasecmp(r_inputs->value,"Execute",7)!=0){ 
666      errorException(m, _("Unenderstood <request> value. Please check that it was set to GetCapabilities, DescribeProcess or Execute."), "InvalidParameterValue","request");
667      freeMaps(&m);
668      free(m);
669      free(REQUEST);
670      return 1;
671    }
672  }
673  r_inputs=NULL;
674  r_inputs=getMap(request_inputs,"Service");
675  if(r_inputs==NULLMAP){
676    errorException(m, _("Parameter <service> was not specified"),"MissingParameterValue","service");
677    freeMaps(&m);
678    free(m);
679    free(REQUEST);
680    return 1;
681  }else{
682    if(strcasecmp(r_inputs->value,"WPS")!=0){
683      errorException(m, _("Unenderstood <service> value, WPS is the only acceptable value."), "InvalidParameterValue","service");
684      freeMaps(&m);
685      free(m);
686      free(REQUEST);
687      return 1;
688    }
689  }
690  if(strncasecmp(REQUEST,"GetCapabilities",15)!=0){
691    r_inputs=getMap(request_inputs,"Version");
692    if(r_inputs==NULL){ 
693      errorException(m, _("Parameter <version> was not specified"),"MissingParameterValue","version");
694      freeMaps(&m);
695      free(m);
696      free(REQUEST);
697      return 1;
698    }else{
699      if(strcasecmp(r_inputs->value,"1.0.0")!=0){
700        errorException(m, _("Unenderstood <version> value, 1.0.0 is the only acceptable value."), "InvalidParameterValue","service");
701        freeMaps(&m);
702        free(m);
703        free(REQUEST);
704        return 1;
705      }
706    } 
707  }
708
709  r_inputs=getMap(request_inputs,"serviceprovider");
710  if(r_inputs==NULL){
711    addToMap(request_inputs,"serviceprovider","");
712  }
713
714  maps* request_output_real_format=NULL;
715  map* tmpm=getMapFromMaps(m,"main","serverAddress");
716  if(tmpm!=NULL)
717    SERVICE_URL=zStrdup(tmpm->value);
718  else
719    SERVICE_URL=zStrdup(DEFAULT_SERVICE_URL);
720
721  service* s1;
722  int scount=0;
723#ifdef DEBUG
724  dumpMap(r_inputs);
725#endif
726  char conf_dir[1024];
727  int t;
728  char tmps1[1024];
729
730  r_inputs=NULL;
731  r_inputs=getMap(request_inputs,"metapath");
732  if(r_inputs!=NULL)
733    snprintf(conf_dir,1024,"%s/%s",ntmp,r_inputs->value);
734  else
735    snprintf(conf_dir,1024,"%s",ntmp);
736
737  if(strncasecmp(REQUEST,"GetCapabilities",15)==0){
738    struct dirent *dp;
739#ifdef DEBUG
740    dumpMap(r_inputs);
741#endif
742    DIR *dirp = opendir(conf_dir);
743    if(dirp==NULL){
744      return errorException(m, _("The specified path doesn't exist."),"InvalidParameterValue","metapath");
745    }
746    xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0");
747    r_inputs=NULL;
748    r_inputs=getMap(request_inputs,"ServiceProvider");
749    xmlNodePtr n;
750    if(r_inputs!=NULL)
751      n = printGetCapabilitiesHeader(doc,r_inputs->value,m);
752    else
753      n = printGetCapabilitiesHeader(doc,"",m);
754    /**
755     * Here we need to close stdout to ensure that not supported chars
756     * has been found in the zcfg and then printed on stdout
757     */
758    int saved_stdout = dup(fileno(stdout));
759    dup2(fileno(stderr),fileno(stdout));
760    while ((dp = readdir(dirp)) != NULL)
761      if(strstr(dp->d_name,".zcfg")!=0){
762        memset(tmps1,0,1024);
763        snprintf(tmps1,1024,"%s/%s",conf_dir,dp->d_name);
764        s1=(service*)malloc(SERVICE_SIZE);
765        if(s1 == NULL){ 
766          return errorException(m, _("Unable to allocate memory."),"InternalError",NULL);
767        }
768#ifdef DEBUG
769        fprintf(stderr,"#################\n%s\n#################\n",tmps1);
770#endif
771        t=getServiceFromFile(tmps1,&s1);
772#ifdef DEBUG
773        dumpService(s1);
774        fflush(stdout);
775        fflush(stderr);
776#endif
777        printGetCapabilitiesForProcess(m,n,s1);
778        freeService(&s1);
779        free(s1);
780        scount++;
781      }
782    (void)closedir(dirp);
783    fflush(stdout);
784    dup2(saved_stdout,fileno(stdout));
785    printDocument(m,doc,getpid());
786    freeMaps(&m);
787    free(m);
788    free(REQUEST);
789    free(SERVICE_URL);
790    fflush(stdout);
791    return 0;
792  }
793  else{
794    r_inputs=getMap(request_inputs,"Identifier");
795    if(r_inputs==NULL 
796       || strlen(r_inputs->name)==0 || strlen(r_inputs->value)==0){ 
797      errorException(m, _("Mandatory <identifier> was not specified"),"MissingParameterValue","identifier");
798      freeMaps(&m);
799      free(m);
800      free(REQUEST);
801      free(SERVICE_URL);
802      return 0;
803    }
804
805    struct dirent *dp;
806    DIR *dirp = opendir(conf_dir);
807    if(dirp==NULL){
808      errorException(m, _("The specified path path doesn't exist."),"InvalidParameterValue",conf_dir);
809      freeMaps(&m);
810      free(m);
811      free(REQUEST);
812      free(SERVICE_URL);
813      return 0;
814    }
815    if(strncasecmp(REQUEST,"DescribeProcess",15)==0){
816      /**
817       * Loop over Identifier list
818       */
819      xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0");
820      r_inputs=NULL;
821      r_inputs=getMap(request_inputs,"ServiceProvider");
822
823      xmlNodePtr n;
824      if(r_inputs!=NULL)
825        n = printDescribeProcessHeader(doc,r_inputs->value,m);
826      else
827        n = printDescribeProcessHeader(doc,"",m);
828
829      r_inputs=getMap(request_inputs,"Identifier");
830      char *tmps=strtok(r_inputs->value,",");
831     
832      char buff[256];
833      char buff1[1024];
834      int saved_stdout = dup(fileno(stdout));
835      dup2(fileno(stderr),fileno(stdout));
836      while(tmps){
837        memset(buff,0,256);
838        snprintf(buff,256,"%s.zcfg",tmps);
839        memset(buff1,0,1024);
840#ifdef DEBUG
841        printf("\n#######%s\n########\n",buff1);
842#endif
843        while ((dp = readdir(dirp)) != NULL)
844          if((strcasecmp("all.zcfg",buff)==0 && strstr(dp->d_name,".zcfg")>0)
845             || strcasecmp(dp->d_name,buff)==0){
846            memset(buff1,0,1024);
847            snprintf(buff1,1024,"%s/%s",conf_dir,dp->d_name);
848            s1=(service*)malloc(SERVICE_SIZE);
849            if(s1 == NULL){
850              dup2(saved_stdout,fileno(stdout));
851              return errorException(m, _("Unable to allocate memory."),"InternalError",NULL);
852            }
853#ifdef DEBUG
854            printf("#################\n%s\n#################\n",buff1);
855#endif
856            t=getServiceFromFile(buff1,&s1);
857#ifdef DEBUG
858            dumpService(s1);
859#endif
860            printDescribeProcessForProcess(m,n,s1,1);
861            freeService(&s1);
862            free(s1);
863            scount++;
864          }
865        rewinddir(dirp);
866        tmps=strtok(NULL,",");
867      }
868      closedir(dirp);
869      fflush(stdout);
870      dup2(saved_stdout,fileno(stdout));
871      printDocument(m,doc,getpid());
872      freeMaps(&m);
873      free(m);
874      free(REQUEST);
875      free(SERVICE_URL);
876      fflush(stdout);
877      return 0;
878    }
879    else
880      if(strncasecmp(REQUEST,"Execute",strlen(REQUEST))!=0){
881        errorException(m, _("Unenderstood <request> value. Please check that it was set to GetCapabilities, DescribeProcess or Execute."), "InvalidParameterValue","request");
882#ifdef DEBUG
883        fprintf(stderr,"No request found %s",REQUEST);
884#endif 
885        closedir(dirp);
886        freeMaps(&m);
887        free(m);
888        free(REQUEST);
889        free(SERVICE_URL);
890        fflush(stdout);
891        return 0;
892      }
893    closedir(dirp);
894  }
895 
896  s1=NULL;
897  s1=(service*)malloc(SERVICE_SIZE);
898  if(s1 == NULL){
899    freeMaps(&m);
900    free(m);
901    free(REQUEST);
902    free(SERVICE_URL);
903    return errorException(m, _("Unable to allocate memory."),"InternalError",NULL);
904  }
905  r_inputs=getMap(request_inputs,"MetaPath");
906  if(r_inputs!=NULL)
907    snprintf(tmps1,1024,"%s/%s",ntmp,r_inputs->value);
908  else
909    snprintf(tmps1,1024,"%s/",ntmp);
910  r_inputs=getMap(request_inputs,"Identifier");
911  char *ttmp=zStrdup(tmps1);
912  snprintf(tmps1,1024,"%s/%s.zcfg",ttmp,r_inputs->value);
913  free(ttmp);
914#ifdef DEBUG
915  fprintf(stderr,"Trying to load %s\n", tmps1);
916#endif
917  int saved_stdout = dup(fileno(stdout));
918  dup2(fileno(stderr),fileno(stdout));
919  t=getServiceFromFile(tmps1,&s1);
920  fflush(stdout);
921  dup2(saved_stdout,fileno(stdout));
922  if(t<0){
923    char *tmpMsg=(char*)malloc(2048+strlen(r_inputs->value));
924   
925    sprintf(tmpMsg,_("The value for <indetifier> seems to be wrong (%s). Please, ensure that the process exist using the GetCapabilities request."),r_inputs->value);
926    errorException(m, tmpMsg, "InvalidParameterValue","identifier");
927    free(tmpMsg);
928    free(s1);
929    freeMaps(&m);
930    free(m);
931    free(REQUEST);
932    free(SERVICE_URL);
933    return 0;
934  }
935  close(saved_stdout);
936
937#ifdef DEBUG
938  dumpService(s1);
939#endif
940  int j;
941 
942
943  /**
944   * Create the input and output maps data structure
945   */
946  int i=0;
947  HINTERNET hInternet;
948  HINTERNET res;
949  hInternet=InternetOpen(
950#ifndef WIN32
951                         (LPCTSTR)
952#endif
953                         "ZooWPSClient\0",
954                         INTERNET_OPEN_TYPE_PRECONFIG,
955                         NULL,NULL, 0);
956
957#ifndef WIN32
958  if(!CHECK_INET_HANDLE(hInternet))
959    fprintf(stderr,"WARNING : hInternet handle failed to initialize");
960#endif
961  maps* request_input_real_format=NULL;
962  maps* tmpmaps = request_input_real_format;
963  map* postRequest=NULL;
964  postRequest=getMap(request_inputs,"xrequest");
965  if(postRequest==NULLMAP){
966    /**
967     * Parsing outputs provided as KVP
968     */
969    r_inputs=NULL;
970#ifdef DEBUG
971    fprintf(stderr,"OUTPUT Parsing ... \n");
972#endif
973    r_inputs=getMap(request_inputs,"ResponseDocument"); 
974    if(r_inputs==NULL) r_inputs=getMap(request_inputs,"RawDataOutput");
975   
976#ifdef DEBUG
977    fprintf(stderr,"OUTPUT Parsing ... \n");
978#endif
979    if(r_inputs!=NULL){
980#ifdef DEBUG
981      fprintf(stderr,"OUTPUT Parsing start now ... \n");
982#endif
983      char cursor_output[10240];
984      char *cotmp=zStrdup(r_inputs->value);
985      snprintf(cursor_output,10240,"%s",cotmp);
986      free(cotmp);
987      j=0;
988       
989      /**
990       * Put each Output into the outputs_as_text array
991       */
992      char * pToken;
993      maps* tmp_output=NULL;
994#ifdef DEBUG
995      fprintf(stderr,"OUTPUT [%s]\n",cursor_output);
996#endif
997      pToken=strtok(cursor_output,";");
998      char** outputs_as_text=(char**)malloc(128*sizeof(char*));
999      if(outputs_as_text == NULL) {
1000        return errorException(m, _("Unable to allocate memory"), "InternalError",NULL);
1001      }
1002      i=0;
1003      while(pToken!=NULL){
1004#ifdef DEBUG
1005        fprintf(stderr,"***%s***\n",pToken);
1006        fflush(stderr);
1007        fprintf(stderr,"***%s***\n",pToken);
1008#endif
1009        outputs_as_text[i]=(char*)malloc((strlen(pToken)+1)*sizeof(char));
1010        if(outputs_as_text[i] == NULL) {
1011          return errorException(m, _("Unable to allocate memory"), "InternalError",NULL);
1012        }
1013        snprintf(outputs_as_text[i],strlen(pToken)+1,"%s",pToken);
1014        pToken = strtok(NULL,";");
1015        i++;
1016      }
1017      for(j=0;j<i;j++){
1018        char *tmp=zStrdup(outputs_as_text[j]);
1019        free(outputs_as_text[j]);
1020        char *tmpc;
1021        tmpc=strtok(tmp,"@");
1022        int k=0;
1023        while(tmpc!=NULL){
1024          if(k==0){
1025            if(tmp_output==NULL){
1026              tmp_output=(maps*)malloc(MAPS_SIZE);
1027              if(tmp_output == NULL){
1028                return errorException(m, _("Unable to allocate memory."), "InternalError",NULL);
1029              }
1030              tmp_output->name=zStrdup(tmpc);
1031              tmp_output->content=NULL;
1032              tmp_output->next=NULL;
1033            }
1034          }
1035          else{
1036            char *tmpv=strstr(tmpc,"=");
1037            char tmpn[256];
1038            memset(tmpn,0,256);
1039            strncpy(tmpn,tmpc,(strlen(tmpc)-strlen(tmpv))*sizeof(char));
1040            tmpn[strlen(tmpc)-strlen(tmpv)]=0;
1041#ifdef DEBUG
1042            fprintf(stderr,"OUTPUT DEF [%s]=[%s]\n",tmpn,tmpv+1);
1043#endif
1044            if(tmp_output->content==NULL){
1045              tmp_output->content=createMap(tmpn,tmpv+1);
1046              tmp_output->content->next=NULL;
1047            }
1048            else
1049              addToMap(tmp_output->content,tmpn,tmpv+1);
1050          }
1051          k++;
1052#ifdef DEBUG
1053          fprintf(stderr,"***%s***\n",tmpc);
1054#endif
1055          tmpc=strtok(NULL,"@");
1056        }
1057        if(request_output_real_format==NULL)
1058          request_output_real_format=dupMaps(&tmp_output);
1059        else
1060          addMapsToMaps(&request_output_real_format,tmp_output);
1061        freeMaps(&tmp_output);
1062        free(tmp_output);
1063        tmp_output=NULL;
1064#ifdef DEBUG
1065        dumpMaps(tmp_output);
1066        fflush(stderr);
1067#endif
1068        free(tmp);
1069      }
1070      free(outputs_as_text);
1071    }
1072
1073
1074    /**
1075     * Parsing inputs provided as KVP
1076     */
1077    r_inputs=getMap(request_inputs,"DataInputs");
1078#ifdef DEBUG
1079    fprintf(stderr,"DATA INPUTS [%s]\n",r_inputs->value);
1080#endif
1081    char cursor_input[40960];
1082    if(r_inputs!=NULL)
1083      snprintf(cursor_input,40960,"%s",r_inputs->value);
1084    else{
1085      errorException(m, _("Parameter <DataInputs> was not specified"),"MissingParameterValue","DataInputs");
1086      freeMaps(&m);
1087      free(m);
1088      free(REQUEST);
1089      free(SERVICE_URL);
1090      InternetCloseHandle(hInternet);
1091      freeService(&s1);
1092      free(s1);
1093      return 0;
1094    }
1095    j=0;
1096 
1097    /**
1098     * Put each DataInputs into the inputs_as_text array
1099     */
1100    char *tmp1=zStrdup(cursor_input);
1101    char * pToken;
1102    pToken=strtok(cursor_input,";");
1103    if(pToken!=NULL && strncasecmp(pToken,tmp1,strlen(tmp1))==0){
1104      char* tmp2=url_decode(tmp1);
1105      snprintf(cursor_input,(strlen(tmp2)+1)*sizeof(char),"%s",tmp2);
1106      free(tmp2);
1107      pToken=strtok(cursor_input,";");
1108    }
1109    free(tmp1);
1110
1111    char** inputs_as_text=(char**)malloc(100*sizeof(char*));
1112    if(inputs_as_text == NULL){
1113      return errorException(m, _("Unable to allocate memory."), "InternalError",NULL);
1114    }
1115    i=0;
1116    while(pToken!=NULL){
1117#ifdef DEBUG
1118      fprintf(stderr,"***%s***\n",pToken);
1119#endif
1120      fflush(stderr);
1121#ifdef DEBUG
1122      fprintf(stderr,"***%s***\n",pToken);
1123#endif
1124      inputs_as_text[i]=(char*)malloc((strlen(pToken)+1)*sizeof(char));
1125      snprintf(inputs_as_text[i],strlen(pToken)+1,"%s",pToken);
1126      if(inputs_as_text[i] == NULL){
1127        return errorException(m, _("Unable to allocate memory."), "InternalError",NULL);
1128      }
1129      pToken = strtok(NULL,";");
1130      i++;
1131    }
1132
1133    for(j=0;j<i;j++){
1134      char *tmp=zStrdup(inputs_as_text[j]);
1135      free(inputs_as_text[j]);
1136      char *tmpc;
1137      tmpc=strtok(tmp,"@");
1138      while(tmpc!=NULL){
1139#ifdef DEBUG
1140        fprintf(stderr,"***\n***%s***\n",tmpc);
1141#endif
1142        char *tmpv=strstr(tmpc,"=");
1143        char tmpn[256];
1144        memset(tmpn,0,256);
1145        if(tmpv!=NULL){
1146          strncpy(tmpn,tmpc,(strlen(tmpc)-strlen(tmpv))*sizeof(char));
1147          tmpn[strlen(tmpc)-strlen(tmpv)]=0;
1148        }
1149        else{
1150          strncpy(tmpn,tmpc,strlen(tmpc)*sizeof(char));
1151          tmpn[strlen(tmpc)]=0;
1152        }
1153#ifdef DEBUG
1154        fprintf(stderr,"***\n*** %s = %s ***\n",tmpn,tmpv+1);
1155#endif
1156        if(tmpmaps==NULL){
1157          tmpmaps=(maps*)malloc(MAPS_SIZE);
1158          if(tmpmaps == NULL){
1159            return errorException(m, _("Unable to allocate memory."), "InternalError",NULL);
1160          }
1161          tmpmaps->name=zStrdup(tmpn);
1162          if(tmpv!=NULL){
1163            char *tmpvf=url_decode(tmpv+1);
1164            tmpmaps->content=createMap("value",tmpvf);
1165            free(tmpvf);
1166          }
1167          else
1168            tmpmaps->content=createMap("value","Reference");
1169          tmpmaps->next=NULL;
1170        }
1171        tmpc=strtok(NULL,"@");
1172        while(tmpc!=NULL){
1173#ifdef DEBUG
1174          fprintf(stderr,"*** KVP NON URL-ENCODED \n***%s***\n",tmpc);
1175#endif
1176          char *tmpv1=strstr(tmpc,"=");
1177#ifdef DEBUG
1178          fprintf(stderr,"*** VALUE NON URL-ENCODED \n***%s***\n",tmpv1+1);
1179#endif
1180          char tmpn1[1024];
1181          memset(tmpn1,0,1024);
1182          if(tmpv1!=NULL){
1183            strncpy(tmpn1,tmpc,strlen(tmpc)-strlen(tmpv1));
1184            tmpn1[strlen(tmpc)-strlen(tmpv1)]=0;
1185            addToMap(tmpmaps->content,tmpn1,tmpv1+1);
1186          }
1187          else{
1188            strncpy(tmpn1,tmpc,strlen(tmpc));
1189            tmpn1[strlen(tmpc)]=0;
1190            map* lmap=getLastMap(tmpmaps->content);
1191            char *tmpValue=(char*)malloc((strlen(tmpv)+strlen(tmpc)+1)*sizeof(char));
1192            sprintf(tmpValue,"%s@%s",tmpv+1,tmpc);
1193            free(lmap->value);
1194            lmap->value=zStrdup(tmpValue);
1195            free(tmpValue);
1196            tmpc=strtok(NULL,"@");
1197            continue;
1198          }
1199#ifdef DEBUG
1200          fprintf(stderr,"*** NAME NON URL-ENCODED \n***%s***\n",tmpn1);
1201          fprintf(stderr,"*** VALUE NON URL-ENCODED \n***%s***\n",tmpv1+1);
1202#endif
1203          if(strcmp(tmpn1,"xlink:href")!=0)
1204            addToMap(tmpmaps->content,tmpn1,tmpv1+1);
1205          else
1206            if(tmpv1!=NULL){
1207              char *tmpx2=url_decode(tmpv1+1);
1208              if(strncasecmp(tmpx2,"http://",7)!=0 &&
1209                 strncasecmp(tmpx2,"ftp://",6)!=0 &&
1210                 strncasecmp(tmpx2,"https://",8)!=0){
1211                char emsg[1024];
1212                sprintf(emsg,_("Unable to find a valid protocol to download the remote file %s"),tmpv1+1);
1213                errorException(m,emsg,"InternalError",NULL);
1214                freeMaps(&m);
1215                free(m);
1216                free(REQUEST);
1217                free(SERVICE_URL);
1218                InternetCloseHandle(hInternet);
1219                freeService(&s1);
1220                free(s1);
1221                return 0;
1222              }
1223#ifdef DEBUG
1224              fprintf(stderr,"REQUIRE TO DOWNLOAD A FILE FROM A SERVER : url(%s)\n",tmpv1+1);
1225#endif
1226              addToMap(tmpmaps->content,tmpn1,tmpx2);
1227             
1228#ifndef WIN32
1229              if(CHECK_INET_HANDLE(hInternet))
1230#endif
1231                {
1232                  if(loadRemoteFile(m,tmpmaps->content,hInternet,tmpx2)<0){
1233                    freeMaps(&m);
1234                    free(m);
1235                    free(REQUEST);
1236                    free(SERVICE_URL);
1237                    InternetCloseHandle(hInternet);
1238                    freeService(&s1);
1239                    free(s1);
1240                    return 0;
1241                  }
1242                }
1243              free(tmpx2);
1244              addToMap(tmpmaps->content,"Reference",tmpv1+1);
1245            }
1246          tmpc=strtok(NULL,"@");
1247        }
1248#ifdef DEBUG
1249        dumpMaps(tmpmaps);
1250        fflush(stderr);
1251#endif
1252        if(request_input_real_format==NULL)
1253          request_input_real_format=dupMaps(&tmpmaps);
1254        else{
1255          maps* testPresence=getMaps(request_input_real_format,tmpmaps->name);
1256          if(testPresence!=NULL){
1257            elements* elem=getElements(s1->inputs,tmpmaps->name);
1258            if(elem!=NULL){
1259              if(appendMapsToMaps(m,request_input_real_format,tmpmaps,elem)<0){
1260                freeMaps(&m);
1261                free(m);
1262                free(REQUEST);
1263                free(SERVICE_URL);
1264                InternetCloseHandle(hInternet);
1265                freeService(&s1);
1266                free(s1);
1267                return 0;
1268              }
1269            }
1270          }
1271          else
1272            addMapsToMaps(&request_input_real_format,tmpmaps);
1273        }
1274        freeMaps(&tmpmaps);
1275        free(tmpmaps);
1276        tmpmaps=NULL;
1277        free(tmp);
1278      }
1279    }
1280    free(inputs_as_text);
1281  }
1282  else {
1283    /**
1284     * Parse XML request
1285     */ 
1286    xmlInitParser();
1287#ifdef DEBUG
1288    fflush(stderr);
1289    fprintf(stderr,"BEFORE %s\n",postRequest->value);
1290    fflush(stderr);
1291#endif
1292    xmlDocPtr doc =
1293      xmlParseMemory(postRequest->value,cgiContentLength);
1294#ifdef DEBUG
1295    fprintf(stderr,"AFTER\n");
1296    fflush(stderr);
1297#endif
1298    /**
1299     * Parse every Input in DataInputs node.
1300     */
1301    xmlXPathObjectPtr tmpsptr=extractFromDoc(doc,"/*/*/*[local-name()='Input']");
1302    xmlNodeSet* tmps=tmpsptr->nodesetval;
1303#ifdef DEBUG
1304    fprintf(stderr,"*****%d*****\n",tmps->nodeNr);
1305#endif
1306    for(int k=0;k<tmps->nodeNr;k++){
1307      maps *tmpmaps=NULL;
1308      xmlNodePtr cur=tmps->nodeTab[k];
1309      if(tmps->nodeTab[k]->type == XML_ELEMENT_NODE) {
1310        /**
1311         * A specific Input node.
1312         */
1313#ifdef DEBUG
1314        fprintf(stderr, "= element 0 node \"%s\"\n", cur->name);
1315#endif
1316        xmlNodePtr cur2=cur->children;
1317        while(cur2!=NULL){
1318          while(cur2!=NULL && cur2->type!=XML_ELEMENT_NODE)
1319            cur2=cur2->next;
1320          if(cur2==NULL)
1321            break;
1322          /**
1323           * Indentifier
1324           */
1325          if(xmlStrncasecmp(cur2->name,BAD_CAST "Identifier",xmlStrlen(cur2->name))==0){
1326            xmlChar *val= xmlNodeListGetString(doc,cur2->xmlChildrenNode,1);
1327            if(tmpmaps==NULL){
1328              tmpmaps=(maps*)malloc(MAPS_SIZE);
1329              if(tmpmaps == NULL){
1330                return errorException(m, _("Unable to allocate memory."), "InternalError",NULL);
1331              }
1332              tmpmaps->name=zStrdup((char*)val);
1333              tmpmaps->content=NULL;
1334              tmpmaps->next=NULL;
1335            }
1336            xmlFree(val);
1337          }
1338          /**
1339           * Title, Asbtract
1340           */
1341          if(xmlStrncasecmp(cur2->name,BAD_CAST "Title",xmlStrlen(cur2->name))==0 ||
1342             xmlStrncasecmp(cur2->name,BAD_CAST "Abstract",xmlStrlen(cur2->name))==0){
1343            xmlChar *val=
1344              xmlNodeListGetString(doc,cur2->xmlChildrenNode,1);
1345            if(tmpmaps==NULL){
1346              tmpmaps=(maps*)malloc(MAPS_SIZE);
1347              if(tmpmaps == NULL){
1348                return errorException(m, _("Unable to allocate memory."), "InternalError",NULL);
1349              }
1350              tmpmaps->name=zStrdup("missingIndetifier");
1351              tmpmaps->content=createMap((char*)cur2->name,(char*)val);
1352              tmpmaps->next=NULL;
1353            }
1354            else{
1355              if(tmpmaps->content!=NULL)
1356                addToMap(tmpmaps->content,
1357                         (char*)cur2->name,(char*)val);
1358              else
1359                tmpmaps->content=
1360                  createMap((char*)cur2->name,(char*)val);
1361            }
1362#ifdef DEBUG
1363            dumpMaps(tmpmaps);
1364#endif
1365            xmlFree(val);
1366          }
1367          /**
1368           * InputDataFormChoice (Reference or Data ?)
1369           */
1370          if(xmlStrcasecmp(cur2->name,BAD_CAST "Reference")==0){
1371            /**
1372             * Get every attribute from a Reference node
1373             * mimeType, encoding, schema, href, method
1374             * Header and Body gesture should be added here
1375             */
1376#ifdef DEBUG
1377            fprintf(stderr,"REFERENCE\n");
1378#endif
1379            const char *refs[5]={"mimeType","encoding","schema","method","href"};
1380            for(int l=0;l<5;l++){
1381#ifdef DEBUG
1382              fprintf(stderr,"*** %s ***",refs[l]);
1383#endif
1384              xmlChar *val=xmlGetProp(cur2,BAD_CAST refs[l]);
1385              if(val!=NULL && xmlStrlen(val)>0){
1386                if(tmpmaps->content!=NULL)
1387                  addToMap(tmpmaps->content,refs[l],(char*)val);
1388                else
1389                  tmpmaps->content=createMap(refs[l],(char*)val);
1390                map* ltmp=getMap(tmpmaps->content,"method");
1391                if(l==4){
1392                  if(!(ltmp!=NULL && strncmp(ltmp->value,"POST",4)==0)
1393                     && CHECK_INET_HANDLE(hInternet)){
1394                    if(loadRemoteFile(m,tmpmaps->content,hInternet,(char*)val)!=0){
1395                      freeMaps(&m);
1396                      free(m);
1397                      free(REQUEST);
1398                      free(SERVICE_URL);
1399                      InternetCloseHandle(hInternet);
1400                      freeService(&s1);
1401                      free(s1);
1402                      return 0;
1403                    }
1404                  }
1405                }
1406              }
1407#ifdef DEBUG
1408              fprintf(stderr,"%s\n",val);
1409#endif
1410              xmlFree(val);
1411            }
1412#ifdef POST_DEBUG
1413            fprintf(stderr,"Parse Header and Body from Reference \n");
1414#endif
1415            xmlNodePtr cur3=cur2->children;
1416            HINTERNET hInternetP;
1417            hInternetP=InternetOpen(
1418#ifndef WIN32
1419                                   (LPCTSTR)
1420#endif
1421                                   "ZooWPSClient\0",
1422                                   INTERNET_OPEN_TYPE_PRECONFIG,
1423                                   NULL,NULL, 0);
1424            hInternetP.header=NULL;
1425            while(cur3){
1426              while(cur3!=NULL && cur3->type!=XML_ELEMENT_NODE)
1427                cur2=cur3->next;
1428              if(xmlStrcasecmp(cur3->name,BAD_CAST "Header")==0 ){
1429                const char *ha[2];
1430                ha[0]="key";
1431                ha[1]="value";
1432                int hai;
1433                char *has;
1434                char *key;
1435                for(hai=0;hai<2;hai++){
1436                  xmlChar *val=xmlGetProp(cur3,BAD_CAST ha[hai]);
1437#ifdef POST_DEBUG
1438                  fprintf(stderr,"%s = %s\n",ha[hai],(char*)val);
1439#endif
1440                  if(hai==0){
1441                    key=(char*)malloc((1+strlen((char*)val))*sizeof(char));
1442                    snprintf(key,1+strlen((char*)val),"%s",(char*)val);
1443                  }else{
1444                    has=(char*)malloc((3+strlen((char*)val)+strlen(key))*sizeof(char));
1445                    if(has == NULL){
1446                      return errorException(m, _("Unable to allocate memory."), "InternalError",NULL);
1447                    }
1448                    snprintf(has,(3+strlen((char*)val)+strlen(key)),"%s: %s",key,(char*)val);
1449#ifdef POST_DEBUG
1450                    fprintf(stderr,"%s\n",has);
1451#endif
1452                  }
1453                }
1454                hInternetP.header=curl_slist_append(hInternetP.header, has);
1455                if(has!=NULL)
1456                  free(has);
1457              }
1458              else{
1459#ifdef POST_DEBUG
1460                fprintf(stderr,"Try to fetch the body part of the request ...\n");
1461#endif
1462                if(xmlStrcasecmp(cur3->name,BAD_CAST "Body")==0 ){
1463#ifdef POST_DEBUG
1464                  fprintf(stderr,"Body part found !!!\n",(char*)cur3->content);
1465#endif
1466                  char *tmp=new char[cgiContentLength];
1467                  memset(tmp,0,cgiContentLength);
1468                  xmlNodePtr cur4=cur3->children;
1469                  while(cur4!=NULL){
1470                    while(cur4->type!=XML_ELEMENT_NODE)
1471                      cur4=cur4->next;
1472                    xmlDocPtr bdoc = xmlNewDoc(BAD_CAST "1.0");
1473                    bdoc->encoding = xmlCharStrdup ("UTF-8");
1474                    xmlDocSetRootElement(bdoc,cur4);
1475                    xmlChar* btmps;
1476                    int bsize;
1477                    xmlDocDumpMemory(bdoc,&btmps,&bsize);
1478#ifdef POST_DEBUG
1479                    fprintf(stderr,"Body part found !!! %s %s\n",tmp,(char*)btmps);
1480#endif
1481                    if(btmps!=NULL)
1482                      sprintf(tmp,"%s",(char*)btmps);
1483                    xmlFreeDoc(bdoc);
1484                    cur4=cur4->next;
1485                  }
1486                  map *btmp=getMap(tmpmaps->content,"href");
1487                  if(btmp!=NULL){
1488#ifdef POST_DEBUG
1489                    fprintf(stderr,"%s %s\n",btmp->value,tmp);
1490                    curl_easy_setopt(hInternetP.handle, CURLOPT_VERBOSE, 1);
1491#endif
1492                    res=InternetOpenUrl(hInternetP,btmp->value,tmp,strlen(tmp),
1493                                        INTERNET_FLAG_NO_CACHE_WRITE,0);
1494                    char* tmpContent = (char*)malloc((res.nDataLen+1)*sizeof(char));
1495                    if(tmpContent == NULL){
1496                      return errorException(m, _("Unable to allocate memory."), "InternalError",NULL);
1497                    }
1498                    size_t dwRead;
1499                    InternetReadFile(res, (LPVOID)tmpContent,
1500                                     res.nDataLen, &dwRead);
1501                    tmpContent[res.nDataLen]=0;
1502                    if(hInternetP.header!=NULL)
1503                      curl_slist_free_all(hInternetP.header);
1504                    addToMap(tmpmaps->content,"value",tmpContent);
1505#ifdef POST_DEBUG
1506                    fprintf(stderr,"DL CONTENT : (%s)\n",tmpContent);
1507#endif
1508                  }
1509                }
1510                else
1511                  if(xmlStrcasecmp(cur3->name,BAD_CAST "BodyReference")==0 ){
1512                    xmlChar *val=xmlGetProp(cur3,BAD_CAST "href");
1513                    HINTERNET bInternet,res1;
1514                    bInternet=InternetOpen(
1515#ifndef WIN32
1516                                           (LPCTSTR)
1517#endif
1518                                           "ZooWPSClient\0",
1519                                           INTERNET_OPEN_TYPE_PRECONFIG,
1520                                           NULL,NULL, 0);
1521                    if(!CHECK_INET_HANDLE(bInternet))
1522                      fprintf(stderr,"WARNING : hInternet handle failed to initialize");
1523#ifdef POST_DEBUG
1524                    curl_easy_setopt(bInternet.handle, CURLOPT_VERBOSE, 1);
1525#endif
1526                    res1=InternetOpenUrl(bInternet,(char*)val,NULL,0,
1527                                         INTERNET_FLAG_NO_CACHE_WRITE,0);
1528                    char* tmp=
1529                      (char*)malloc((res1.nDataLen+1)*sizeof(char));
1530                    if(tmp == NULL){
1531                      return errorException(m, _("Unable to allocate memory."), "InternalError",NULL);
1532                    }
1533                    size_t bRead;
1534                    InternetReadFile(res1, (LPVOID)tmp,
1535                                     res1.nDataLen, &bRead);
1536                    tmp[res1.nDataLen]=0;
1537                    InternetCloseHandle(bInternet);
1538                    map *btmp=getMap(tmpmaps->content,"href");
1539                    if(btmp!=NULL){
1540#ifdef POST_DEBUG
1541                      fprintf(stderr,"%s %s\n",btmp->value,tmp);
1542                      curl_easy_setopt(hInternetP.handle, CURLOPT_VERBOSE, 1);
1543#endif
1544                      res=InternetOpenUrl(hInternetP,btmp->value,tmp,
1545                                          strlen(tmp),
1546                                          INTERNET_FLAG_NO_CACHE_WRITE,0);
1547                      char* tmpContent = (char*)malloc((res.nDataLen+1)*sizeof(char));
1548                      if(tmpContent == NULL){
1549                        return errorException(m, _("Unable to allocate memory."), "InternalError",NULL);
1550                      }
1551                      size_t dwRead;
1552                      InternetReadFile(res, (LPVOID)tmpContent,
1553                                       res.nDataLen, &dwRead);
1554                      tmpContent[res.nDataLen]=0;
1555                      if(hInternetP.header!=NULL)
1556                        curl_slist_free_all(hInternetP.header);
1557                      addToMap(tmpmaps->content,"value",tmpContent);
1558#ifdef POST_DEBUG
1559                      fprintf(stderr,"DL CONTENT : (%s)\n",tmpContent);
1560#endif
1561                    }
1562                  }
1563              }
1564              cur3=cur3->next;
1565            }
1566            InternetCloseHandle(hInternetP);
1567#ifdef POST_DEBUG
1568            fprintf(stderr,"Header and Body was parsed from Reference \n");
1569#endif
1570#ifdef DEBUG
1571            dumpMap(tmpmaps->content);
1572            fprintf(stderr, "= element 2 node \"%s\" = (%s)\n", 
1573                    cur2->name,cur2->content);
1574#endif
1575          }
1576          else if(xmlStrcasecmp(cur2->name,BAD_CAST "Data")==0){
1577#ifdef DEBUG
1578            fprintf(stderr,"DATA\n");
1579#endif
1580            xmlNodePtr cur4=cur2->children;
1581            while(cur4!=NULL){
1582              while(cur4!=NULL &&cur4->type!=XML_ELEMENT_NODE)
1583                cur4=cur4->next;
1584              if(cur4==NULL)
1585                break;
1586              if(xmlStrcasecmp(cur4->name, BAD_CAST "LiteralData")==0){
1587                /**
1588                 * Get every attribute from a LiteralData node
1589                 * dataType , uom
1590                 */
1591                char *list[2];
1592                list[0]=zStrdup("dataType");
1593                list[1]=zStrdup("uom");
1594                for(int l=0;l<2;l++){
1595#ifdef DEBUG
1596                  fprintf(stderr,"*** LiteralData %s ***",list[l]);
1597#endif
1598                  xmlChar *val=xmlGetProp(cur4,BAD_CAST list[l]);
1599                  if(val!=NULL && strlen((char*)val)>0){
1600                    if(tmpmaps->content!=NULL)
1601                      addToMap(tmpmaps->content,list[l],(char*)val);
1602                    else
1603                      tmpmaps->content=createMap(list[l],(char*)val);
1604#ifdef DEBUG
1605                    fprintf(stderr,"%s\n",val);
1606#endif
1607                  }
1608                  xmlFree(val);
1609                  free(list[l]);                 
1610                }
1611              }
1612              else if(xmlStrcasecmp(cur4->name, BAD_CAST "ComplexData")==0){
1613                /**
1614                 * Get every attribute from a Reference node
1615                 * mimeType, encoding, schema
1616                 */
1617                const char *coms[3]={"mimeType","encoding","schema"};
1618                for(int l=0;l<3;l++){
1619#ifdef DEBUG
1620                  fprintf(stderr,"*** ComplexData %s ***\n",coms[l]);
1621#endif
1622                  xmlChar *val=xmlGetProp(cur4,BAD_CAST coms[l]);
1623                  if(val!=NULL && strlen((char*)val)>0){
1624                    if(tmpmaps->content!=NULL)
1625                      addToMap(tmpmaps->content,coms[l],(char*)val);
1626                    else
1627                      tmpmaps->content=createMap(coms[l],(char*)val);
1628#ifdef DEBUG
1629                    fprintf(stderr,"%s\n",val);
1630#endif
1631                  }
1632                  xmlFree(val);
1633                }
1634              }
1635
1636              map* test=getMap(tmpmaps->content,"encoding");
1637              if(test==NULL){
1638                if(tmpmaps->content!=NULL)
1639                  addToMap(tmpmaps->content,"encoding","utf-8");
1640                else
1641                  tmpmaps->content=createMap("encoding","utf-8");
1642                test=getMap(tmpmaps->content,"encoding");
1643              }
1644
1645              if(strcasecmp(test->value,"base64")!=0){
1646                xmlChar* mv=xmlNodeListGetString(doc,cur4->xmlChildrenNode,1);
1647                map* ltmp=getMap(tmpmaps->content,"mimeType");
1648                if(mv==NULL || 
1649                   (xmlStrcasecmp(cur4->name, BAD_CAST "ComplexData")==0 &&
1650                    (ltmp==NULL || strncasecmp(ltmp->value,"text/xml",8)==0) )){
1651                  xmlDocPtr doc1=xmlNewDoc(BAD_CAST "1.0");
1652                  int buffersize;
1653                  xmlNodePtr cur5=cur4->children;
1654                  while(cur5!=NULL &&cur5->type!=XML_ELEMENT_NODE)
1655                    cur5=cur5->next;
1656                  xmlDocSetRootElement(doc1,cur5);
1657                  xmlDocDumpFormatMemoryEnc(doc1, &mv, &buffersize, "utf-8", 1);
1658                  char size[1024];
1659                  sprintf(size,"%d",buffersize);
1660                  addToMap(tmpmaps->content,"size",size);
1661                }
1662                addToMap(tmpmaps->content,"value",(char*)mv);
1663                xmlFree(mv);
1664              }else{
1665                xmlChar* tmp=xmlNodeListGetRawString(doc,cur4->xmlChildrenNode,0);
1666                addToMap(tmpmaps->content,"value",(char*)tmp);
1667                map* tmpv=getMap(tmpmaps->content,"value");
1668                char *res=NULL;
1669                char *curs=tmpv->value;
1670                for(int i=0;i<=strlen(tmpv->value)/64;i++) {
1671                  if(res==NULL)
1672                    res=(char*)malloc(67*sizeof(char));
1673                  else
1674                    res=(char*)realloc(res,(((i+1)*65)+i)*sizeof(char));
1675                  int csize=i*65;
1676                  strncpy(res + csize,curs,64);
1677                  if(i==xmlStrlen(tmp)/64)
1678                    strcat(res,"\n\0");
1679                  else{
1680                    strncpy(res + (((i+1)*64)+i),"\n\0",2);
1681                    curs+=64;
1682                  }
1683                }
1684                free(tmpv->value);
1685                tmpv->value=zStrdup(res);
1686                free(res);
1687                xmlFree(tmp);
1688              }
1689              cur4=cur4->next;
1690            }
1691          }
1692#ifdef DEBUG
1693          fprintf(stderr,"cur2 next \n");
1694          fflush(stderr);
1695#endif
1696          cur2=cur2->next;
1697        }
1698#ifdef DEBUG
1699        fprintf(stderr,"ADD MAPS TO REQUEST MAPS !\n");
1700        fflush(stderr);
1701#endif
1702
1703        {
1704          maps* testPresence=getMaps(request_input_real_format,tmpmaps->name);
1705          if(testPresence!=NULL){
1706            elements* elem=getElements(s1->inputs,tmpmaps->name);
1707            if(elem!=NULL){
1708              if(appendMapsToMaps(m,request_input_real_format,tmpmaps,elem)<0){
1709                freeMaps(&m);
1710                free(m);
1711                free(REQUEST);
1712                free(SERVICE_URL);
1713                InternetCloseHandle(hInternet);
1714                freeService(&s1);
1715                free(s1);
1716                return 0;
1717              }
1718            }
1719          }
1720          else
1721            addMapsToMaps(&request_input_real_format,tmpmaps);
1722        }
1723
1724#ifdef DEBUG
1725        fprintf(stderr,"******TMPMAPS*****\n");
1726        dumpMaps(tmpmaps);
1727        fprintf(stderr,"******REQUESTMAPS*****\n");
1728        dumpMaps(request_input_real_format);
1729#endif
1730        freeMaps(&tmpmaps);
1731        free(tmpmaps);
1732        tmpmaps=NULL;         
1733      }
1734#ifdef DEBUG
1735      dumpMaps(tmpmaps); 
1736#endif
1737    }
1738#ifdef DEBUG
1739    fprintf(stderr,"Search for response document node\n");
1740#endif
1741    xmlXPathFreeObject(tmpsptr);
1742   
1743    tmpsptr=extractFromDoc(doc,"/*/*/*[local-name()='ResponseDocument']");
1744    bool asRaw=false;
1745    tmps=tmpsptr->nodesetval;
1746    if(tmps->nodeNr==0){
1747      tmpsptr=extractFromDoc(doc,"/*/*/*[local-name()='RawDataOutput']");
1748      tmps=tmpsptr->nodesetval;
1749      asRaw=true;
1750    }
1751#ifdef DEBUG
1752    fprintf(stderr,"*****%d*****\n",tmps->nodeNr);
1753#endif
1754    for(int k=0;k<tmps->nodeNr;k++){
1755      if(asRaw==true)
1756        addToMap(request_inputs,"RawDataOutput","");
1757      else
1758        addToMap(request_inputs,"ResponseDocument","");
1759      maps *tmpmaps=NULL;
1760      xmlNodePtr cur=tmps->nodeTab[k];
1761      if(cur->type == XML_ELEMENT_NODE) {
1762        /**
1763         * A specific responseDocument node.
1764         */
1765        if(tmpmaps==NULL){
1766          tmpmaps=(maps*)malloc(MAPS_SIZE);
1767          if(tmpmaps == NULL){
1768            return errorException(m, _("Unable to allocate memory."), "InternalError",NULL);
1769          }
1770          tmpmaps->name=zStrdup("unknownIdentifier");
1771          tmpmaps->content=NULL;
1772          tmpmaps->next=NULL;
1773        }
1774        /**
1775         * Get every attribute: storeExecuteResponse, lineage, status
1776         */
1777        const char *ress[3]={"storeExecuteResponse","lineage","status"};
1778        xmlChar *val;
1779        for(int l=0;l<3;l++){
1780#ifdef DEBUG
1781          fprintf(stderr,"*** %s ***\t",ress[l]);
1782#endif
1783          val=xmlGetProp(cur,BAD_CAST ress[l]);
1784          if(val!=NULL && strlen((char*)val)>0){
1785            if(tmpmaps->content!=NULL)
1786              addToMap(tmpmaps->content,ress[l],(char*)val);
1787            else
1788              tmpmaps->content=createMap(ress[l],(char*)val);
1789            addToMap(request_inputs,ress[l],(char*)val);
1790          }
1791#ifdef DEBUG
1792          fprintf(stderr,"%s\n",val);
1793#endif
1794          xmlFree(val);
1795        }
1796        xmlNodePtr cur1=cur->children;
1797        while(cur1!=NULL && cur1->type != XML_ELEMENT_NODE)
1798          cur1=cur1->next;
1799        int cur1cnt=0;
1800        while(cur1){
1801          /**
1802           * Indentifier
1803           */
1804          if(xmlStrncasecmp(cur1->name,BAD_CAST "Identifier",xmlStrlen(cur1->name))==0){
1805            xmlChar *val=
1806              xmlNodeListGetString(doc,cur1->xmlChildrenNode,1);
1807            if(tmpmaps==NULL){
1808              tmpmaps=(maps*)malloc(MAPS_SIZE);
1809              if(tmpmaps == NULL){
1810                return errorException(m, _("Unable to allocate memory."), "InternalError",NULL);
1811              }
1812              tmpmaps->name=zStrdup((char*)val);
1813              tmpmaps->content=NULL;
1814              tmpmaps->next=NULL;
1815            }
1816            else{
1817              //free(tmpmaps->name);
1818              tmpmaps->name=zStrdup((char*)val);
1819            }
1820            if(asRaw==true)
1821              addToMap(request_inputs,"RawDataOutput",(char*)val);
1822            else{
1823              if(cur1cnt==0)
1824                addToMap(request_inputs,"ResponseDocument",(char*)val);
1825              else{
1826                map* tt=getMap(request_inputs,"ResponseDocument");
1827                char* tmp=zStrdup(tt->value);
1828                free(tt->value);
1829                tt->value=(char*)malloc((strlen(tmp)+strlen((char*)val)+1)*sizeof(char));
1830                sprintf(tt->value,"%s;%s",tmp,(char*)val);
1831                free(tmp);
1832              }
1833            }
1834            cur1cnt+=1;
1835            xmlFree(val);
1836          }
1837          /**
1838           * Title, Asbtract
1839           */
1840          else if(xmlStrncasecmp(cur1->name,BAD_CAST "Title",xmlStrlen(cur1->name))==0 ||
1841                  xmlStrncasecmp(cur1->name,BAD_CAST "Abstract",xmlStrlen(cur1->name))==0){
1842            xmlChar *val=
1843              xmlNodeListGetString(doc,cur1->xmlChildrenNode,1);
1844            if(tmpmaps==NULL){
1845              tmpmaps=(maps*)malloc(MAPS_SIZE);
1846              if(tmpmaps == NULL){
1847                return errorException(m, _("Unable to allocate memory."), "InternalError",NULL);
1848              }
1849              tmpmaps->name=zStrdup("missingIndetifier");
1850              tmpmaps->content=createMap((char*)cur1->name,(char*)val);
1851              tmpmaps->next=NULL;
1852            }
1853            else{
1854              if(tmpmaps->content!=NULL)
1855                addToMap(tmpmaps->content,(char*)cur1->name,(char*)val);
1856              else
1857                tmpmaps->content=createMap((char*)cur1->name,(char*)val);
1858            }
1859            xmlFree(val);
1860          }
1861          else if(xmlStrncasecmp(cur1->name,BAD_CAST "Output",xmlStrlen(cur1->name))==0){
1862            /**
1863             * Get every attribute from a Output node
1864             * mimeType, encoding, schema, uom, asReference
1865             */
1866            const char *outs[5]={"mimeType","encoding","schema","uom","asReference"};
1867            for(int l=0;l<5;l++){
1868#ifdef DEBUG
1869              fprintf(stderr,"*** %s ***\t",outs[l]);
1870#endif
1871              val=xmlGetProp(cur1,BAD_CAST outs[l]);
1872              if(val!=NULL && strlen((char*)val)>0){
1873                if(tmpmaps->content!=NULL)
1874                  addToMap(tmpmaps->content,outs[l],(char*)val);
1875                else
1876                  tmpmaps->content=createMap(outs[l],(char*)val);
1877              }
1878#ifdef DEBUG
1879              fprintf(stderr,"%s\n",val);
1880#endif
1881              xmlFree(val);
1882            }
1883            xmlNodePtr cur2=cur1->children;
1884            while(cur2!=NULL && cur2->type != XML_ELEMENT_NODE)
1885              cur2=cur2->next;
1886            while(cur2){
1887              /**
1888               * Indentifier
1889               */
1890              if(xmlStrncasecmp(cur2->name,BAD_CAST "Identifier",xmlStrlen(cur2->name))==0){
1891                xmlChar *val=
1892                  xmlNodeListGetString(doc,cur2->xmlChildrenNode,1);
1893                if(tmpmaps==NULL){
1894                  tmpmaps=(maps*)malloc(MAPS_SIZE);
1895                  if(tmpmaps == NULL){
1896                    return errorException(m, _("Unable to allocate memory."), "InternalError",NULL);
1897                  }
1898                  tmpmaps->name=zStrdup((char*)val);
1899                  tmpmaps->content=NULL;
1900                  tmpmaps->next=NULL;
1901                }
1902                else{
1903                  if(tmpmaps->name!=NULL)
1904                    free(tmpmaps->name);
1905                  tmpmaps->name=zStrdup((char*)val);;
1906                }
1907                xmlFree(val);
1908              }
1909              /**
1910               * Title, Asbtract
1911               */
1912              else if(xmlStrncasecmp(cur2->name,BAD_CAST "Title",xmlStrlen(cur2->name))==0 ||
1913                      xmlStrncasecmp(cur2->name,BAD_CAST "Abstract",xmlStrlen(cur2->name))==0){
1914                xmlChar *val=
1915                  xmlNodeListGetString(doc,cur2->xmlChildrenNode,1);
1916                if(tmpmaps==NULL){
1917                  tmpmaps=(maps*)malloc(MAPS_SIZE);
1918                  if(tmpmaps == NULL){
1919                    return errorException(m, _("Unable to allocate memory."), "InternalError",NULL);
1920                  }
1921                  tmpmaps->name=zStrdup("missingIndetifier");
1922                  tmpmaps->content=createMap((char*)cur2->name,(char*)val);
1923                  tmpmaps->next=NULL;
1924                }
1925                else{
1926                  if(tmpmaps->content!=NULL)
1927                    addToMap(tmpmaps->content,
1928                             (char*)cur2->name,(char*)val);
1929                  else
1930                    tmpmaps->content=
1931                      createMap((char*)cur2->name,(char*)val);
1932                }
1933                xmlFree(val);
1934              }
1935              cur2=cur2->next;
1936              while(cur2!=NULL && cur2->type != XML_ELEMENT_NODE)
1937                cur2=cur2->next;
1938            }
1939          }
1940          cur1=cur1->next;
1941          while(cur1!=NULL && cur1->type != XML_ELEMENT_NODE)
1942            cur1=cur1->next;
1943        }
1944      }
1945      if(request_output_real_format==NULL)
1946        request_output_real_format=dupMaps(&tmpmaps);
1947      else
1948        addMapsToMaps(&request_output_real_format,tmpmaps);
1949      if(tmpmaps!=NULL){
1950        freeMaps(&tmpmaps);
1951        free(tmpmaps);
1952        tmpmaps=NULL;
1953      }
1954    }
1955    xmlXPathFreeObject(tmpsptr);
1956    xmlCleanupParser();
1957  }
1958 
1959
1960  //  if(CHECK_INET_HANDLE(hInternet))
1961  InternetCloseHandle(hInternet);
1962
1963#ifdef DEBUG
1964  fprintf(stderr,"\n%d\n",__LINE__);
1965  fflush(stderr);
1966  dumpMaps(request_input_real_format);
1967  dumpMaps(request_output_real_format);
1968  dumpMap(request_inputs);
1969  fprintf(stderr,"\n%d\n",__LINE__);
1970  fflush(stderr);
1971#endif
1972
1973  /**
1974   * Ensure that each requested arguments are present in the request
1975   * DataInputs and ResponseDocument / RawDataOutput
1976   */
1977  char *dfv=addDefaultValues(&request_input_real_format,s1->inputs,m,0);
1978  char *dfv1=addDefaultValues(&request_output_real_format,s1->outputs,m,1);
1979  if(strcmp(dfv1,"")!=0 || strcmp(dfv,"")!=0){
1980    char tmps[1024];
1981    map* tmpe=createMap("code","MissingParameterValue");
1982    if(strcmp(dfv,"")!=0){
1983      snprintf(tmps,1024,_("The <%s> argument was not specified in DataInputs but defined as requested in ZOO ServicesProvider configuration file, please correct your query or the ZOO Configuration file."),dfv);
1984      addToMap(tmpe,"locator",dfv);
1985    }
1986    else if(strcmp(dfv1,"")!=0){
1987      snprintf(tmps,1024,_("The <%s> argument was specified as Output identifier but not defined in the ZOO Configuration File. Please, correct your query or the ZOO Configuration File."),dfv1);
1988      addToMap(tmpe,"locator",dfv1);
1989    }
1990    addToMap(tmpe,"text",tmps);
1991    printExceptionReportResponse(m,tmpe);
1992    freeService(&s1);
1993    free(s1);
1994    freeMap(&tmpe);
1995    free(tmpe);
1996    freeMaps(&m);
1997    free(m);
1998    free(REQUEST);
1999    free(SERVICE_URL);
2000    freeMaps(&request_input_real_format);
2001    free(request_input_real_format);
2002    freeMaps(&request_output_real_format);
2003    free(request_output_real_format);
2004    freeMaps(&tmpmaps);
2005    free(tmpmaps);
2006    return 1;
2007  }
2008  maps* tmpReqI=request_input_real_format;
2009  while(tmpReqI!=NULL){
2010    char name[1024];
2011    if(getMap(tmpReqI->content,"isFile")!=NULL){
2012      if (cgiFormFileName(tmpReqI->name, name, sizeof(name)) == cgiFormSuccess) {
2013        int BufferLen=1024;
2014        cgiFilePtr file;
2015        int targetFile;
2016        mode_t mode;
2017        char storageNameOnServer[2048];
2018        char fileNameOnServer[64];
2019        char contentType[1024];
2020        char buffer[1024];
2021        char *tmpStr=NULL;
2022        int size;
2023        int got,t;
2024        map *path=getMapFromMaps(m,"main","tmpPath");
2025        cgiFormFileSize(tmpReqI->name, &size);
2026        cgiFormFileContentType(tmpReqI->name, contentType, sizeof(contentType));
2027        if (cgiFormFileOpen(tmpReqI->name, &file) == cgiFormSuccess) {
2028          t=-1;
2029          while(1){
2030            tmpStr=strstr(name+t+1,"\\");
2031            if(NULL==tmpStr)
2032              tmpStr=strstr(name+t+1,"/");
2033            if(NULL!=tmpStr)
2034              t=(int)(tmpStr-name);
2035            else
2036              break;
2037          }
2038          strcpy(fileNameOnServer,name+t+1);
2039         
2040          sprintf(storageNameOnServer,"%s/%s",path->value,fileNameOnServer);
2041#ifdef DEBUG
2042          fprintf(stderr,"Name on server %s\n",storageNameOnServer);
2043          fprintf(stderr,"fileNameOnServer: %s\n",fileNameOnServer);
2044#endif
2045          mode=S_IRWXU|S_IRGRP|S_IROTH;
2046          targetFile = open (storageNameOnServer,O_RDWR|O_CREAT|O_TRUNC,S_IRWXU|S_IRGRP|S_IROTH);
2047          if(targetFile<0){
2048#ifdef DEBUG
2049            fprintf(stderr,"could not create the new file,%s\n",fileNameOnServer);         
2050#endif
2051          }else{
2052            while (cgiFormFileRead(file, buffer, BufferLen, &got) ==cgiFormSuccess){
2053              if(got>0)
2054                write(targetFile,buffer,got);
2055            }
2056          }
2057          addToMap(tmpReqI->content,"lref",storageNameOnServer);
2058          cgiFormFileClose(file);
2059          close(targetFile);
2060#ifdef DEBUG
2061          fprintf(stderr,"File \"%s\" has been uploaded",fileNameOnServer);
2062#endif
2063        }
2064      }
2065    }
2066    tmpReqI=tmpReqI->next;
2067  }
2068
2069  ensureDecodedBase64(&request_input_real_format);
2070
2071#ifdef DEBUG
2072  fprintf(stderr,"REQUEST_INPUTS\n");
2073  dumpMaps(request_input_real_format);
2074  fprintf(stderr,"REQUEST_OUTPUTS\n");
2075  dumpMaps(request_output_real_format);
2076#endif
2077
2078  maps* curs=getMaps(m,"env");
2079  if(curs!=NULL){
2080    map* mapcs=curs->content;
2081    while(mapcs!=NULLMAP){
2082#ifndef WIN32
2083      setenv(mapcs->name,mapcs->value,1);
2084#else
2085#ifdef DEBUG
2086      fprintf(stderr,"[ZOO: setenv (%s=%s)]\n",mapcs->name,mapcs->value);
2087#endif
2088      if(mapcs->value[strlen(mapcs->value)-2]=='\r'){
2089#ifdef DEBUG
2090        fprintf(stderr,"[ZOO: Env var finish with \r]\n");
2091#endif
2092        mapcs->value[strlen(mapcs->value)-1]=0;
2093      }
2094#ifdef DEBUG
2095      fflush(stderr);
2096      fprintf(stderr,"setting variable... %s\n",(
2097#endif
2098              SetEnvironmentVariable(mapcs->name,mapcs->value)
2099#ifdef DEBUG
2100              ==0)? "OK" : "FAILED");
2101#else
2102      ;
2103#endif
2104      char* toto=(char*)malloc((strlen(mapcs->name)+strlen(mapcs->value)+2)*sizeof(char));
2105      sprintf(toto,"%s=%s",mapcs->name,mapcs->value);
2106      putenv(toto);
2107#ifdef DEBUG
2108      fflush(stderr);
2109#endif
2110#endif
2111#ifdef DEBUG
2112      fprintf(stderr,"[ZOO: setenv (%s=%s)]\n",mapcs->name,mapcs->value);
2113      fflush(stderr);
2114#endif
2115      mapcs=mapcs->next;
2116    }
2117  }
2118 
2119#ifdef DEBUG
2120  dumpMap(request_inputs);
2121#endif
2122
2123  /**
2124   * Need to check if we need to fork to load a status enabled
2125   */
2126  r_inputs=NULL;
2127  map* store=getMap(request_inputs,"storeExecuteResponse");
2128  map* status=getMap(request_inputs,"status");
2129  /**
2130   * 05-007r7 WPS 1.0.0 page 57 :
2131   * 'If status="true" and storeExecuteResponse is "false" then the service
2132   * shall raise an exception.'
2133   */
2134  if(status!=NULL && strcmp(status->value,"true")==0 && 
2135     store!=NULL && strcmp(store->value,"false")==0){
2136    errorException(m, _("Status cannot be set to true with storeExecuteResponse to false. Please, modify your request parameters."), "InvalidParameterValue","storeExecuteResponse");
2137    freeService(&s1);
2138    free(s1);
2139    freeMaps(&m);
2140    free(m);
2141   
2142    freeMaps(&request_input_real_format);
2143    free(request_input_real_format);
2144   
2145    freeMaps(&request_output_real_format);
2146    free(request_output_real_format);
2147   
2148    free(REQUEST);
2149    free(SERVICE_URL);
2150    return 1;
2151  }
2152  r_inputs=getMap(request_inputs,"storeExecuteResponse");
2153  int eres=SERVICE_STARTED;
2154  int cpid=getpid();
2155
2156  /**
2157   * Initialize the specific [lenv] section which contains runtime variables:
2158   *
2159   *  - usid : it is an unique identification number
2160   *  - sid : it is the process idenfitication number (OS)
2161   *  - status : value between 0 and 100 to express the  completude of
2162   * the operations of the running service
2163   *  - message : is a string where you can store error messages, in case
2164   * service is failing, or o provide details on the ongoing operation.
2165   *  - cwd : is the current working directory
2166   *  - soap : is a boolean value, true if the request was contained in a SOAP
2167   * Envelop
2168   *  - sessid : string storing the session identifier (only when cookie is
2169   * used)
2170   *  - cgiSid : only defined on Window platforms (for being able to identify
2171   * the created process)
2172   *
2173   */
2174  maps *_tmpMaps=(maps*)malloc(MAPS_SIZE);
2175  _tmpMaps->name=zStrdup("lenv");
2176  char tmpBuff[100];
2177  sprintf(tmpBuff,"%i",(cpid+(int)time(NULL)));
2178  _tmpMaps->content=createMap("usid",tmpBuff);
2179  _tmpMaps->next=NULL;
2180  sprintf(tmpBuff,"%i",cpid);
2181  addToMap(_tmpMaps->content,"sid",tmpBuff);
2182  addToMap(_tmpMaps->content,"status","0");
2183  addToMap(_tmpMaps->content,"message",_("No message provided"));
2184  addToMap(_tmpMaps->content,"cwd",ntmp);
2185  map* ltmp=getMap(request_inputs,"soap");
2186  if(ltmp!=NULL)
2187    addToMap(_tmpMaps->content,"soap",ltmp->value);
2188  else
2189    addToMap(_tmpMaps->content,"soap","false");
2190  if(cgiCookie!=NULL && strlen(cgiCookie)>0){
2191    int hasValidCookie=-1;
2192    char *tcook=zStrdup(cgiCookie);
2193    char *tmp=NULL;
2194    int hasVal=-1;
2195    map* testing=getMapFromMaps(m,"main","cookiePrefix");
2196    if(testing==NULL){
2197      tmp=zStrdup("ID=");
2198    }else{
2199      tmp=(char*)malloc((strlen(testing->value)+2)*sizeof(char));
2200      sprintf(tmp,"%s=",testing->value);
2201      hasVal=1;
2202    }
2203    if(strstr(cgiCookie,";")!=NULL){
2204      char *token,*saveptr;
2205      token=strtok_r(cgiCookie,";",&saveptr);
2206      while(token!=NULL){
2207        if(strcasestr(token,tmp)!=NULL){
2208          if(tcook!=NULL)
2209            free(tcook);
2210          tcook=zStrdup(token);
2211          hasValidCookie=1;
2212        }
2213        token=strtok_r(NULL,";",&saveptr);
2214      }
2215    }else{
2216      if(strstr(cgiCookie,"=")!=NULL && strcasestr(cgiCookie,tmp)!=NULL){
2217        tcook=zStrdup(cgiCookie);
2218        hasValidCookie=1;
2219      }
2220      if(tmp!=NULL){
2221        free(tmp);
2222      }
2223    }
2224    if(hasValidCookie>0){
2225      addToMap(_tmpMaps->content,"sessid",strstr(tcook,"=")+1);
2226      char session_file_path[1024];
2227      map *tmpPath=getMapFromMaps(m,"main","sessPath");
2228      if(tmpPath==NULL)
2229        tmpPath=getMapFromMaps(m,"main","tmpPath");
2230      char *tmp1=strtok(tcook,";");
2231      if(tmp1!=NULL)
2232        sprintf(session_file_path,"%s/sess_%s.cfg",tmpPath->value,strstr(tmp1,"=")+1);
2233      else
2234        sprintf(session_file_path,"%s/sess_%s.cfg",tmpPath->value,strstr(cgiCookie,"=")+1);
2235      free(tcook);
2236      maps *tmpSess=(maps*)malloc(MAPS_SIZE);
2237      struct stat file_status;
2238      int istat = stat(session_file_path, &file_status);
2239      if(istat==0 && file_status.st_size>0){
2240        conf_read(session_file_path,tmpSess);
2241        addMapsToMaps(&m,tmpSess);
2242        freeMaps(&tmpSess);
2243        free(tmpSess);
2244      }
2245    }
2246  }
2247  addMapsToMaps(&m,_tmpMaps);
2248  freeMaps(&_tmpMaps);
2249  free(_tmpMaps);
2250
2251#ifdef DEBUG
2252  dumpMap(request_inputs);
2253#endif
2254#ifdef WIN32
2255  char *cgiSidL=NULL;
2256  if(getenv("CGISID")!=NULL)
2257    addToMap(request_inputs,"cgiSid",getenv("CGISID"));
2258  map* test1=getMap(request_inputs,"cgiSid");
2259  if(test1!=NULL){
2260    cgiSid=test1->value;
2261    addToMap(request_inputs,"storeExecuteResponse","true");
2262    addToMap(request_inputs,"status","true");
2263    setMapInMaps(m,"lenv","sid",test1->value);
2264    status=getMap(request_inputs,"status");
2265  }
2266#endif
2267  int hrstd=-1;
2268  char *fbkp,*fbkp1;
2269  FILE *f0,*f1;
2270  if(status!=NULL)
2271    if(strcasecmp(status->value,"false")==0)
2272      status=NULLMAP;
2273  if(status==NULLMAP){
2274    loadServiceAndRun(&m,s1,request_inputs,&request_input_real_format,&request_output_real_format,&eres);
2275  }
2276  else{
2277    int   pid;
2278#ifdef DEBUG
2279    fprintf(stderr,"\nPID : %d\n",cpid);
2280#endif
2281
2282#ifndef WIN32
2283    pid = fork ();
2284#else
2285    if(cgiSid==NULL){
2286      createProcess(m,request_inputs,s1,NULL,cpid,request_input_real_format,request_output_real_format);
2287      pid = cpid;
2288    }else{
2289      pid=0;
2290      cpid=atoi(cgiSid);
2291    }
2292#endif
2293    if (pid > 0) {
2294      /**
2295       * dady :
2296       * set status to SERVICE_ACCEPTED
2297       */
2298#ifdef DEBUG
2299      fprintf(stderr,"father pid continue (origin %d) %d ...\n",cpid,getpid());
2300#endif
2301      eres=SERVICE_ACCEPTED;
2302    }else if (pid == 0) {
2303      /**
2304       * son : have to close the stdout, stdin and stderr to let the parent
2305       * process answer to http client.
2306       */
2307      r_inputs=getMapFromMaps(m,"main","tmpPath");
2308      map* r_inputs1=getMap(s1->content,"ServiceProvider");
2309      fbkp=(char*)malloc((strlen(r_inputs->value)+strlen(r_inputs1->value)+1024)*sizeof(char));
2310      sprintf(fbkp,"%s/%s_%d.xml",r_inputs->value,r_inputs1->value,cpid);
2311      char* flog=(char*)malloc((strlen(r_inputs->value)+strlen(r_inputs1->value)+1024)*sizeof(char));
2312      sprintf(flog,"%s/%s_%d_error.log",r_inputs->value,r_inputs1->value,cpid);
2313#ifdef DEBUG
2314      fprintf(stderr,"RUN IN BACKGROUND MODE \n");
2315      fprintf(stderr,"son pid continue (origin %d) %d ...\n",cpid,getpid());
2316      fprintf(stderr,"\nFILE TO STORE DATA %s\n",r_inputs->value);
2317#endif
2318      freopen(flog, "w+", stderr);
2319      f0=freopen(fbkp , "w+", stdout);
2320#ifndef WIN32
2321      fclose(stdin);
2322#endif
2323      free(flog);
2324      /**
2325       * set status to SERVICE_STARTED and flush stdout to ensure full
2326       * content was outputed (the file used to store the ResponseDocument).
2327       * The rewind stdout to restart writing from the bgining of the file,
2328       * this way the data will be updated at the end of the process run.
2329       */
2330      printProcessResponse(m,request_inputs,cpid,
2331                           s1,r_inputs1->value,SERVICE_STARTED,
2332                           request_input_real_format,
2333                           request_output_real_format);
2334#ifndef WIN32
2335      fflush(stdout);
2336      rewind(stdout);
2337#else
2338#endif
2339      fbkp1=(char*)malloc((strlen(r_inputs->value)+strlen(r_inputs1->value)+1024)*sizeof(char));
2340      sprintf(fbkp1,"%s/%s_final_%d.xml",r_inputs->value,r_inputs1->value,cpid);
2341      f1=freopen(fbkp1 , "w+", stdout);
2342      loadServiceAndRun(&m,s1,request_inputs,&request_input_real_format,&request_output_real_format,&eres);
2343    } else {
2344      /**
2345       * error server don't accept the process need to output a valid
2346       * error response here !!!
2347       */
2348      eres=-1;
2349      errorException(m, _("Unable to run the child process properly"), "InternalError",NULL);
2350    }
2351  }
2352
2353#ifdef DEBUG
2354  dumpMaps(request_output_real_format);
2355#endif
2356  if(eres!=-1)
2357    outputResponse(s1,request_input_real_format,
2358                   request_output_real_format,request_inputs,
2359                   cpid,m,eres);
2360  fflush(stdout);
2361  /**
2362   * Ensure that if error occurs when freeing memory, no signal will return
2363   * an ExceptionReport document as the result was already returned to the
2364   * client.
2365   */
2366#ifndef USE_GDB
2367  (void) signal(SIGSEGV,donothing);
2368  (void) signal(SIGTERM,donothing);
2369  (void) signal(SIGINT,donothing);
2370  (void) signal(SIGILL,donothing);
2371  (void) signal(SIGFPE,donothing);
2372  (void) signal(SIGABRT,donothing);
2373#endif
2374
2375  if(((int)getpid())!=cpid || cgiSid!=NULL){
2376    fclose(stdout);
2377    fclose(stderr);
2378    unhandleStatus(m);
2379    /**
2380     * Dump back the final file fbkp1 to fbkp
2381     */
2382    fclose(f0);
2383    fclose(f1);
2384    FILE* f2=fopen(fbkp1,"rb");
2385    FILE* f3=fopen(fbkp,"wb+");
2386    free(fbkp);
2387    fseek(f2,0,SEEK_END);
2388    long flen=ftell(f2);
2389    fseek(f2,0,SEEK_SET);
2390    char *tmps1=(char*)malloc((flen+1)*sizeof(char));
2391    fread(tmps1,flen,1,f2);
2392    fwrite(tmps1,1,flen,f3);
2393    fclose(f2);
2394    fclose(f3);
2395    unlink(fbkp1);
2396    free(fbkp1);
2397  }
2398
2399  freeService(&s1);
2400  free(s1);
2401  freeMaps(&m);
2402  free(m);
2403 
2404  freeMaps(&request_input_real_format);
2405  free(request_input_real_format);
2406 
2407  freeMaps(&request_output_real_format);
2408  free(request_output_real_format);
2409 
2410  free(REQUEST);
2411  free(SERVICE_URL);
2412#ifdef DEBUG
2413  fprintf(stderr,"Processed response \n");
2414  fflush(stdout);
2415  fflush(stderr);
2416#endif
2417
2418  return 0;
2419}
2420
Note: See TracBrowser for help on using the repository browser.

Search

ZOO Sponsors

http://www.zoo-project.org/trac/chrome/site/img/geolabs-logo.pnghttp://www.zoo-project.org/trac/chrome/site/img/neogeo-logo.png http://www.zoo-project.org/trac/chrome/site/img/apptech-logo.png http://www.zoo-project.org/trac/chrome/site/img/3liz-logo.png http://www.zoo-project.org/trac/chrome/site/img/gateway-logo.png

Become a sponsor !

Knowledge partners

http://www.zoo-project.org/trac/chrome/site/img/ocu-logo.png http://www.zoo-project.org/trac/chrome/site/img/gucas-logo.png http://www.zoo-project.org/trac/chrome/site/img/polimi-logo.png http://www.zoo-project.org/trac/chrome/site/img/fem-logo.png http://www.zoo-project.org/trac/chrome/site/img/supsi-logo.png http://www.zoo-project.org/trac/chrome/site/img/cumtb-logo.png

Become a knowledge partner

Related links

http://zoo-project.org/img/ogclogo.png http://zoo-project.org/img/osgeologo.png