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

Last change on this file since 459 was 459, checked in by djay, 6 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