source: trunk/zoo-kernel/zoo_service_loader.c @ 92

Last change on this file since 92 was 92, checked in by djay, 14 years ago

Give ZOO-Services capabilities to return a Cookie to the client and to store persistent informations, using senv maps in main_conf, on the server side. Bug fix in addDefaultValues.

File size: 50.5 KB
Line 
1/**
2 * Author : Gérald FENOY
3 *
4 *  Copyright 2008-2011 GeoLabs SARL. All rights reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25#define length(x) (sizeof(x) / sizeof(x[0]))
26
27extern "C" int yylex();
28extern "C" int crlex();
29
30extern "C" {
31#include <libxml/tree.h>
32#include <libxml/xmlmemory.h>
33#include <libxml/parser.h>
34#include <libxml/xpath.h>
35#include <libxml/xpathInternals.h>
36}
37
38#include "cgic.h"
39#include "ulinet.h"
40
41#include <libintl.h>
42#include <locale.h>
43#include <string.h>
44
45#include "service.h"
46
47#include "service_internal.h"
48
49#ifdef USE_PYTHON
50#include "service_internal_python.h"
51#endif
52
53#ifdef USE_JAVA
54#include "service_internal_java.h"
55#endif
56
57#ifdef USE_PHP
58#include "service_internal_php.h"
59#endif
60
61#ifdef USE_JS
62#include "service_internal_js.h"
63#endif
64
65#ifdef USE_PERL
66#include "service_internal_perl.h"
67#endif
68
69
70
71#include <dirent.h>
72#include <signal.h>
73#include <unistd.h>
74#ifndef WIN32
75#include <dlfcn.h>
76#include <libgen.h>
77#else
78#include <windows.h>
79#include <direct.h>
80#endif
81#include <fcntl.h>
82#include <time.h>
83#include <stdarg.h>
84
85#define _(String) dgettext ("zoo-kernel",String)
86
87
88void *translateChar(char* str,char toReplace,char toReplaceBy){
89  int i=0,len=strlen(str);
90  for(i=0;i<len;i++){
91    if(str[i]==toReplace)
92      str[i]=toReplaceBy;
93  }
94}
95
96xmlXPathObjectPtr extractFromDoc(xmlDocPtr doc,char* search){
97  xmlXPathContextPtr xpathCtx;
98  xmlXPathObjectPtr xpathObj;
99  xpathCtx = xmlXPathNewContext(doc);
100  xpathObj = xmlXPathEvalExpression(BAD_CAST search,xpathCtx);
101  xmlXPathFreeContext(xpathCtx);
102  return xpathObj;
103}
104
105void sig_handler(int sig){
106  char tmp[100];
107  char *ssig;
108  switch(sig){
109  case SIGSEGV:
110    ssig="SIGSEGV";
111    break;
112  case SIGTERM:
113    ssig="SIGTERM";
114    break;
115  case SIGINT:
116    ssig="SIGINT";
117    break;
118  case SIGILL:
119    ssig="SIGILL";
120    break;
121  case SIGFPE:
122    ssig="SIGFPE";
123    break;
124  case SIGABRT:
125    ssig="SIGABRT";
126    break;
127  default:
128    ssig="UNKNOWN";
129    break;
130  }
131  sprintf(tmp,_("ZOO Kernel failed to process your request receiving signal %d = %s"),sig,ssig);
132  errorException(NULL, tmp, "InternalError");
133#ifdef DEBUG
134  fprintf(stderr,"Not this time!\n");
135#endif
136  exit(0);
137}
138
139void *loadServiceAndRun(maps **myMap,service* s1,map* request_inputs,maps **inputs,maps** ioutputs,int* eres){
140  char tmps1[1024];
141  char ntmp[1024];
142  maps *m=*myMap;
143  maps *request_output_real_format=*ioutputs;
144  maps *request_input_real_format=*inputs;
145  /**
146   * Extract serviceType to know what kind of service should be loaded
147   */
148  map* r_inputs=NULL;
149#ifndef WIN32
150  getcwd(ntmp,1024);
151#else
152  _getcwd(ntmp,1024);
153#endif
154  r_inputs=getMap(s1->content,"serviceType");
155#ifdef DEBUG
156  fprintf(stderr,"LOAD A %s SERVICE PROVIDER \n",r_inputs->value);
157  fflush(stderr);
158#endif
159  if(strncasecmp(r_inputs->value,"C",1)==0){
160    r_inputs=getMap(request_inputs,"metapath");
161    if(r_inputs!=NULL)
162      sprintf(tmps1,"%s/%s",ntmp,r_inputs->value);
163    else
164      sprintf(tmps1,"%s/",ntmp);
165    char *altPath=strdup(tmps1);
166    r_inputs=getMap(s1->content,"ServiceProvider");
167    sprintf(tmps1,"%s/%s",altPath,r_inputs->value);
168    free(altPath);
169#ifdef DEBUG
170    fprintf(stderr,"Trying to load %s\n",tmps1);
171#endif
172#ifdef WIN32
173    HINSTANCE so = LoadLibraryEx(tmps1,NULL,LOAD_WITH_ALTERED_SEARCH_PATH);
174#else
175    void* so = dlopen(tmps1, RTLD_LAZY);
176#endif
177#ifdef DEBUG
178#ifdef WIN32
179    DWORD errstr;
180    errstr = GetLastError();
181    fprintf(stderr,"%s loaded (%d) \n",tmps1,errstr);
182#else
183    char *errstr;
184    errstr = dlerror();
185#endif
186#endif
187
188    if( so != NULL ) {
189#ifdef DEBUG
190      fprintf(stderr,"Library loaded %s \n",errstr);
191      fprintf(stderr,"Service Shared Object = %s\n",r_inputs->value);
192#endif
193      r_inputs=getMap(s1->content,"serviceType");
194#ifdef DEBUG
195      dumpMap(r_inputs);
196      fprintf(stderr,"%s\n",r_inputs->value);
197      fflush(stderr);
198#endif
199      if(strncasecmp(r_inputs->value,"C-FORTRAN",9)==0){
200#ifdef WIN32
201        //Strange return value needed here !
202        return 1;
203#endif
204        r_inputs=getMap(request_inputs,"Identifier");
205        char fname[1024];
206        sprintf(fname,"%s_",r_inputs->value);
207#ifdef DEBUG
208        fprintf(stderr,"Try to load function %s\n",fname);
209#endif
210#ifdef WIN32
211        typedef int (CALLBACK* execute_t)(char***,char***,char***);
212        execute_t execute=(execute_t)GetProcAddress(so,fname);
213#else
214        typedef int (*execute_t)(char***,char***,char***);
215        execute_t execute=(execute_t)dlsym(so,fname);
216#endif
217#ifdef DEBUG
218#ifdef WIN32
219        errstr = GetLastError();
220#else
221        errstr = dlerror();
222#endif
223        fprintf(stderr,"Function loaded %s\n",errstr);
224#endif 
225
226        char main_conf[10][30][1024];
227        char inputs[10][30][1024];
228        char outputs[10][30][1024];
229        for(int i=0;i<10;i++){
230          for(int j=0;j<30;j++){
231            memset(main_conf[i][j],0,1024);
232            memset(inputs[i][j],0,1024);
233            memset(outputs[i][j],0,1024);
234          }
235        }
236        mapsToCharXXX(m,(char***)main_conf);
237        mapsToCharXXX(request_input_real_format,(char***)inputs);
238        mapsToCharXXX(request_output_real_format,(char***)outputs);
239        *eres=execute((char***)&main_conf[0],(char***)&inputs[0],(char***)&outputs[0]);
240#ifdef DEBUG
241        fprintf(stderr,"Function run successfully \n");
242#endif
243        charxxxToMaps((char***)&outputs[0],&request_output_real_format);
244      }else{
245#ifdef DEBUG
246#ifdef WIN32
247        errstr = GetLastError();
248        fprintf(stderr,"Function %s failed to load because of %d\n",r_inputs->value,errstr);
249#endif
250#endif
251        r_inputs=getMap(request_inputs,"Identifier");
252#ifdef DEBUG
253        fprintf(stderr,"Try to load function %s\n",r_inputs->value);
254#endif
255        typedef int (*execute_t)(maps**,maps**,maps**);
256#ifdef WIN32
257        execute_t execute=(execute_t)GetProcAddress(so,r_inputs->value); 
258#else
259        execute_t execute=(execute_t)dlsym(so,r_inputs->value);
260#endif
261
262#ifdef DEBUG
263#ifdef WIN32
264        errstr = GetLastError();
265#else
266        errstr = dlerror();
267#endif
268        fprintf(stderr,"Function loaded %s\n",errstr);
269#endif 
270
271#ifdef DEBUG
272        fprintf(stderr,"Now run the function \n");
273        fflush(stderr);
274#endif
275        *eres=execute(&m,&request_input_real_format,&request_output_real_format);
276#ifdef DEBUG
277        fprintf(stderr,"Function loaded and returned %d\n",eres);
278        fflush(stderr);
279#endif
280      }
281      dlclose(so);
282    } else {
283      /**
284       * Unable to load the specified shared library
285       */
286      char tmps[1024];
287#ifdef WIN32
288      DWORD errstr = GetLastError();
289#else
290      char* errstr = dlerror();
291#endif
292      sprintf(tmps,_("C Library can't be loaded %s \n"),errstr);
293      map* tmps1=createMap("text",tmps);
294      printExceptionReportResponse(m,tmps1);
295      *eres=-1;
296    }
297  }
298  else
299#ifdef USE_PYTHON
300    if(strncasecmp(r_inputs->value,"PYTHON",6)==0){
301      *eres=zoo_python_support(&m,request_inputs,s1,&request_input_real_format,&request_output_real_format);
302    }
303    else
304#endif
305       
306#ifdef USE_JAVA
307      if(strncasecmp(r_inputs->value,"JAVA",4)==0){
308        *eres=zoo_java_support(&m,request_inputs,s1,&request_input_real_format,&request_output_real_format);
309      }
310      else
311#endif
312
313#ifdef USE_PHP
314        if(strncasecmp(r_inputs->value,"PHP",3)==0){
315          *eres=zoo_php_support(&m,request_inputs,s1,&request_input_real_format,&request_output_real_format);
316        }
317        else
318#endif
319           
320           
321#ifdef USE_PERL
322          if(strncasecmp(r_inputs->value,"PERL",4)==0){
323            *eres=zoo_perl_support(&m,request_inputs,s1,&request_input_real_format,&request_output_real_format);
324          }
325          else
326#endif
327
328#ifdef USE_JS
329            if(strncasecmp(r_inputs->value,"JS",2)==0){
330              *eres=zoo_js_support(&m,request_inputs,s1,&request_input_real_format,&request_output_real_format);
331            }
332            else
333#endif
334              {
335                char tmpv[1024];
336                sprintf(tmpv,_("Programming Language (%s) set in ZCFG file is not currently supported by ZOO Kernel.\n"),r_inputs->value);
337                map* tmps=createMap("text",tmpv);
338                printExceptionReportResponse(m,tmps);
339                *eres=-1;
340              }
341  *myMap=m;
342  *ioutputs=request_output_real_format;
343}
344
345int runRequest(map* request_inputs)
346{
347
348#ifndef USE_GDB
349  (void) signal(SIGSEGV,sig_handler);
350  (void) signal(SIGTERM,sig_handler);
351  (void) signal(SIGINT,sig_handler);
352  (void) signal(SIGILL,sig_handler);
353  (void) signal(SIGFPE,sig_handler);
354  (void) signal(SIGABRT,sig_handler);
355#endif
356
357  map* r_inputs=NULL,*tmps=NULL;
358  maps* m=NULL;
359  int argc=count(request_inputs);
360
361  char* REQUEST=NULL;
362  /**
363   * Parsing service specfic configuration file
364   */
365  m=(maps*)calloc(1,MAPS_SIZE);
366  if(m == NULL){
367    return errorException(m, _("Unable to allocate memory."), "InternalError");
368  }
369  char ntmp[1024];
370#ifndef WIN32
371  getcwd(ntmp,1024);
372#else
373  _getcwd(ntmp,1024);
374#endif
375  r_inputs=getMap(request_inputs,"metapath");
376  if(r_inputs==NULL){
377    if(request_inputs==NULL)
378      request_inputs=createMap("metapath","");
379    else
380      addToMap(request_inputs,"metapath","");
381#ifdef DEBUG
382    fprintf(stderr,"ADD METAPATH\n");
383    dumpMap(request_inputs);
384#endif
385    r_inputs=getMap(request_inputs,"metapath");
386  }
387  char conf_file[10240];
388  snprintf(conf_file,10240,"%s/%s/main.cfg",ntmp,r_inputs->value);
389  conf_read(conf_file,m);
390#ifdef DEBUG
391  fprintf(stderr, "***** BEGIN MAPS\n"); 
392  dumpMaps(m);
393  fprintf(stderr, "***** END MAPS\n");
394#endif
395
396  bindtextdomain ("zoo-kernel","/usr/share/locale/");
397  bindtextdomain ("zoo-services","/usr/share/locale/");
398 
399  if((r_inputs=getMap(request_inputs,"language"))!=NULL){
400    char *tmp=strdup(r_inputs->value);
401    translateChar(tmp,'-','_');
402    setlocale (LC_ALL, tmp);
403    free(tmp);
404    setMapInMaps(m,"main","language",r_inputs->value);
405  }
406  else{
407    setlocale (LC_ALL, "en_US");
408    setMapInMaps(m,"main","language","en-US");
409  }
410  setlocale (LC_NUMERIC, "en_US");
411  bind_textdomain_codeset("zoo-kernel","UTF-8");
412  textdomain("zoo-kernel");
413  bind_textdomain_codeset("zoo-services","UTF-8");
414  textdomain("zoo-services");
415
416
417  /**
418   * Check for minimum inputs
419   */
420  r_inputs=getMap(request_inputs,"Request");
421  if(request_inputs==NULL || r_inputs==NULL){ 
422    errorException(m, _("Parameter <request> was not specified"),"MissingParameterValue");
423    freeMaps(&m);
424    free(m);
425    freeMap(&request_inputs);
426    free(request_inputs);
427    free(REQUEST);
428    return 1;
429  }
430  else{
431    REQUEST=strdup(r_inputs->value);
432    if(strncasecmp(r_inputs->value,"GetCapabilities",15)!=0
433       && strncasecmp(r_inputs->value,"DescribeProcess",15)!=0
434       && strncasecmp(r_inputs->value,"Execute",7)!=0){ 
435      errorException(m, _("Unenderstood <request> value. Please check that it was set to GetCapabilities, DescribeProcess or Execute."), "InvalidParameterValue");
436      freeMaps(&m);
437      free(m);
438      free(REQUEST);
439      return 1;
440    }
441  }
442  r_inputs=NULL;
443  r_inputs=getMap(request_inputs,"Service");
444  if(r_inputs==NULLMAP){
445    errorException(m, _("Parameter <service> was not specified"),"MissingParameterValue");
446    freeMaps(&m);
447    free(m);
448    free(REQUEST);
449    return 1;
450  }
451  if(strncasecmp(REQUEST,"GetCapabilities",15)!=0){
452    r_inputs=getMap(request_inputs,"Version");
453    if(r_inputs==NULL){ 
454      errorException(m, _("Parameter <version> was not specified"),"MissingParameterValue");
455      freeMaps(&m);
456      free(m);
457      free(REQUEST);
458      return 1;
459    }
460  }
461
462  r_inputs=getMap(request_inputs,"serviceprovider");
463  if(r_inputs==NULL){
464    addToMap(request_inputs,"serviceprovider","");
465  }
466
467  map* outputs=NULL;
468  maps* request_output_real_format=NULL;
469  map* tmpm=getMapFromMaps(m,"main","serverAddress");
470  if(tmpm!=NULL)
471    SERVICE_URL=strdup(tmpm->value);
472  else
473    SERVICE_URL=strdup(DEFAULT_SERVICE_URL);
474
475  service* s[100];
476  service* s1;
477  int scount=0;
478
479#ifdef DEBUG
480  dumpMap(r_inputs);
481#endif
482  char conf_dir[1024];
483  int t;
484  char tmps1[1024];
485
486  r_inputs=NULL;
487  r_inputs=getMap(request_inputs,"metapath");
488  if(r_inputs!=NULL)
489    snprintf(conf_dir,1024,"%s/%s",ntmp,r_inputs->value);
490  else
491    snprintf(conf_dir,1024,"%s",ntmp);
492
493  if(strncasecmp(REQUEST,"GetCapabilities",15)==0){
494    int i=0;
495    struct dirent *dp;
496#ifdef DEBUG
497    dumpMap(r_inputs);
498#endif
499    DIR *dirp = opendir(conf_dir);
500    if(dirp==NULL){
501      return errorException(m, _("The specified path doesn't exist."),"InvalidParameterValue");
502    }
503    xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0");
504    r_inputs=NULL;
505    r_inputs=getMap(request_inputs,"ServiceProvider");
506    xmlNodePtr n;
507    //dumpMap(request_inputs);
508    if(r_inputs!=NULL)
509      n = printGetCapabilitiesHeader(doc,r_inputs->value,m);
510    else
511      n = printGetCapabilitiesHeader(doc,"",m);
512    /**
513     * Strange, here we need to close stdout to ensure that no uneeded
514     * char will be printed (parser issue ?)
515     */
516    int saved_stdout = dup(fileno(stdout));
517    dup2(fileno(stderr),fileno(stdout));
518    while ((dp = readdir(dirp)) != NULL)
519      if(strstr(dp->d_name,".zcfg")!=0){
520        memset(tmps1,0,1024);
521        snprintf(tmps1,1024,"%s/%s",conf_dir,dp->d_name);
522        s1=(service*)calloc(1,SERVICE_SIZE);
523        if(s1 == NULL){ 
524          return errorException(m, _("Unable to allocate memory."),"InternalError");
525        }
526#ifdef DEBUG
527        fprintf(stderr,"#################\n%s\n#################\n",tmps1);
528#endif
529        t=getServiceFromFile(tmps1,&s1);
530#ifdef DEBUG
531        dumpService(s1);
532        fflush(stdout);
533        fflush(stderr);
534#endif
535        printGetCapabilitiesForProcess(m,n,s1);
536        freeService(&s1);
537        free(s1);
538        scount++;
539      }
540    (void)closedir(dirp);
541    fflush(stdout);
542    dup2(saved_stdout,fileno(stdout));
543    printDocument(m,doc,getpid());
544    freeMaps(&m);
545    free(m);
546    free(REQUEST);
547    free(SERVICE_URL);
548    fflush(stdout);
549    return 0;
550  }
551  else{
552    r_inputs=getMap(request_inputs,"Identifier");
553    if(r_inputs==NULL 
554       || strlen(r_inputs->name)==0 || strlen(r_inputs->value)==0){ 
555      errorException(m, _("Mandatory <identifier> was not specified"),"MissingParameterValue");
556      freeMaps(&m);
557      free(m);
558      free(REQUEST);
559      free(SERVICE_URL);
560      return 0;
561    }
562
563    struct dirent *dp;
564    DIR *dirp = opendir(conf_dir);
565    if(dirp==NULL){
566      errorException(m, _("The specified path path doesn't exist."),"InvalidParameterValue");
567      freeMaps(&m);
568      free(m);
569      free(REQUEST);
570      free(SERVICE_URL);
571      return 0;
572    }
573    if(strncasecmp(REQUEST,"DescribeProcess",15)==0){
574      /**
575       * Loop over Identifier list
576       */
577      xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0");
578      r_inputs=NULL;
579      r_inputs=getMap(request_inputs,"ServiceProvider");
580
581      xmlNodePtr n;
582      if(r_inputs!=NULL)
583        n = printDescribeProcessHeader(doc,r_inputs->value,m);
584      else
585        n = printDescribeProcessHeader(doc,"",m);
586
587      r_inputs=getMap(request_inputs,"Identifier");
588      char *tmps=strtok(r_inputs->value,",");
589     
590      char buff[256];
591      char buff1[1024];
592      int i=0;
593      int j=0;
594      int end=-1;
595      int saved_stdout = dup(fileno(stdout));
596      dup2(fileno(stderr),fileno(stdout));
597      while(tmps){
598        memset(buff,0,256);
599        snprintf(buff,256,"%s.zcfg",tmps);
600        memset(buff1,0,1024);
601#ifdef DEBUG
602        fprintf(stderr,"\n#######%s\n########\n",buff1);
603#endif
604        while ((dp = readdir(dirp)) != NULL)
605          if(strcmp(dp->d_name,buff)==0){
606            memset(buff1,0,1024);
607            snprintf(buff1,1024,"%s/%s",conf_dir,dp->d_name);
608            //s1=(service*)malloc(sizeof(service*));
609            s1=(service*)calloc(1,SERVICE_SIZE);
610            if(s1 == NULL){
611              return errorException(m, _("Unable to allocate memory."),"InternalError");
612            }
613#ifdef DEBUG
614            fprintf(stderr,"#################\n%s\n#################\n",buff1);
615#endif
616            t=getServiceFromFile(buff1,&s1);
617#ifdef DEBUG
618            dumpService(s1);
619#endif
620            printDescribeProcessForProcess(m,n,s1,1);
621            freeService(&s1);
622            free(s1);
623            scount++;
624          }
625        rewinddir(dirp);
626        tmps=strtok(NULL,",");
627      }
628      closedir(dirp);
629      fflush(stdout);
630      dup2(saved_stdout,fileno(stdout));
631      printDocument(m,doc,getpid());
632      freeMaps(&m);
633      free(m);
634      free(REQUEST);
635      free(SERVICE_URL);
636      fflush(stdout);
637      //xmlFree(n);
638#ifndef LINUX_FREE_ISSUE
639      if(s1)
640        free(s1);
641#endif
642      return 0;
643    }
644    else
645      if(strncasecmp(REQUEST,"Execute",strlen(REQUEST))!=0){
646        errorException(m, _("Unenderstood <request> value. Please check that it was set to GetCapabilities, DescribeProcess or Execute."), "InvalidParameterValue");
647#ifdef DEBUG
648        fprintf(stderr,"No request found %s",REQUEST);
649#endif 
650        closedir(dirp);
651        free(s);
652        return 0;
653      }
654    closedir(dirp);
655  }
656 
657  s1=NULL;
658  s1=(service*)calloc(1,SERVICE_SIZE);
659  if(s1 == NULL){
660    freeMaps(&m);
661    free(m);
662    free(REQUEST);
663    free(SERVICE_URL);
664    return errorException(m, _("Unable to allocate memory."),"InternalError");
665  }
666  r_inputs=getMap(request_inputs,"MetaPath");
667  if(r_inputs!=NULL)
668    snprintf(tmps1,1024,"%s/%s",ntmp,r_inputs->value);
669  else
670    snprintf(tmps1,1024,"%s/",ntmp);
671  r_inputs=getMap(request_inputs,"Identifier");
672  char *ttmp=strdup(tmps1);
673  snprintf(tmps1,1024,"%s/%s.zcfg",ttmp,r_inputs->value);
674  free(ttmp);
675#ifdef DEBUG
676  fprintf(stderr,"Trying to load %s\n", tmps1);
677#endif
678  int saved_stdout = dup(fileno(stdout));
679  dup2(fileno(stderr),fileno(stdout));
680  t=getServiceFromFile(tmps1,&s1);
681  fflush(stdout);
682  dup2(saved_stdout,fileno(stdout));
683  if(t<0){
684    char tmpMsg[2048+strlen(r_inputs->value)];
685    sprintf(tmpMsg,_("The value for <indetifier> seems to be wrong (%s). Please, ensure that the process exist using the GetCapabilities request."),r_inputs->value);
686    errorException(m, tmpMsg, "InvalidParameterValue");
687    freeService(&s1);
688    free(s1);
689    freeMaps(&m);
690    free(m);
691    free(REQUEST);
692    free(SERVICE_URL);
693    return 0;
694  }
695  close(saved_stdout);
696
697#ifdef DEBUG
698  dumpService(s1);
699#endif
700  map* inputs=NULL;
701  elements* c_inputs=s1->inputs;
702  int j;
703 
704  /**
705   * Create the input maps data structure
706   */
707  int i=0;
708  HINTERNET hInternet;
709  HINTERNET res;
710  hInternet=InternetOpen(
711#ifndef WIN32
712                         (LPCTSTR)
713#endif
714                         "ZooWPSClient\0",
715                         INTERNET_OPEN_TYPE_PRECONFIG,
716                         NULL,NULL, 0);
717
718#ifndef WIN32
719  if(!CHECK_INET_HANDLE(hInternet))
720    fprintf(stderr,"WARNING : hInternet handle failed to initialize");
721#endif
722  maps* request_input_real_format=NULL;
723  maps* tmpmaps = request_input_real_format;
724  map* postRequest=NULL;
725  postRequest=getMap(request_inputs,"xrequest");
726  if(postRequest==NULLMAP){
727    /**
728     * Parsing outputs provided as KVP
729     */
730    r_inputs=NULL;
731#ifdef DEBUG
732    fprintf(stderr,"OUTPUT Parsing ... \n");
733#endif
734    r_inputs=getMap(request_inputs,"ResponseDocument"); 
735    if(r_inputs==NULL) r_inputs=getMap(request_inputs,"RawDataOutput");
736   
737#ifdef DEBUG
738    fprintf(stderr,"OUTPUT Parsing ... \n");
739#endif
740    if(r_inputs!=NULL){
741#ifdef DEBUG
742      fprintf(stderr,"OUTPUT Parsing start now ... \n");
743#endif
744      char current_output_as_string[10240];
745      char cursor_output[10240];
746      char *cotmp=strdup(r_inputs->value);
747      snprintf(cursor_output,10240,"%s",cotmp);
748      free(cotmp);
749      j=0;
750      map* request_kvp_outputs=NULL;
751       
752      /**
753       * Put each Output into the outputs_as_text array
754       */
755      char * pToken;
756      maps* tmp_output=NULL;
757#ifdef DEBUG
758      fprintf(stderr,"OUTPUT [%s]\n",cursor_output);
759#endif
760      pToken=strtok(cursor_output,";");
761      char** outputs_as_text=(char**)calloc(128,sizeof(char*));
762      if(outputs_as_text == NULL) {
763        return errorException(m, _("Unable to allocate memory"), "InternalError");
764      }
765      i=0;
766      while(pToken!=NULL){
767#ifdef DEBUG
768        fprintf(stderr,"***%s***\n",pToken);
769        fflush(stderr);
770        fprintf(stderr,"***%s***\n",pToken);
771#endif
772        outputs_as_text[i]=(char*)calloc(strlen(pToken)+1,sizeof(char));
773        if(outputs_as_text[i] == NULL) {
774          return errorException(m, _("Unable to allocate memory"), "InternalError");
775        }
776        snprintf(outputs_as_text[i],strlen(pToken)+1,"%s",pToken);
777        pToken = strtok(NULL,";");
778        i++;
779      }
780      for(j=0;j<i;j++){
781        char *tmp=strdup(outputs_as_text[j]);
782        free(outputs_as_text[j]);
783        char *tmpc;
784        tmpc=strtok(tmp,"@");
785        int k=0;
786        while(tmpc!=NULL){
787          if(k==0){
788            if(tmp_output==NULL){
789              tmp_output=(maps*)calloc(1,MAPS_SIZE);
790              if(tmp_output == NULL){
791                return errorException(m, _("Unable to allocate memory."), "InternalError");
792              }
793              tmp_output->name=strdup(tmpc);
794              tmp_output->content=NULL;
795              tmp_output->next=NULL;
796            }
797          }
798          else{
799            char *tmpv=strstr(tmpc,"=");
800            char tmpn[256];
801            memset(tmpn,0,256);
802            strncpy(tmpn,tmpc,(strlen(tmpc)-strlen(tmpv))*sizeof(char));
803            tmpn[strlen(tmpc)-strlen(tmpv)]=0;
804#ifdef DEBUG
805            fprintf(stderr,"OUTPUT DEF [%s]=[%s]\n",tmpn,tmpv+1);
806#endif
807            if(tmp_output->content==NULL){
808              tmp_output->content=createMap(tmpn,tmpv+1);
809              tmp_output->content->next=NULL;
810            }
811            else
812              addToMap(tmp_output->content,tmpn,tmpv+1);
813          }
814          k++;
815#ifdef DEBUG
816          fprintf(stderr,"***%s***\n",tmpc);
817#endif
818          tmpc=strtok(NULL,"@");
819        }
820        if(request_output_real_format==NULL)
821          request_output_real_format=dupMaps(&tmp_output);
822        else
823          addMapsToMaps(&request_output_real_format,tmp_output);
824        freeMaps(&tmp_output);
825        free(tmp_output);
826        tmp_output=NULL;
827#ifdef DEBUG
828        dumpMaps(tmp_output);
829        fflush(stderr);
830#endif
831        //tmp_output=tmp_output->next;
832        free(tmp);
833      }
834      free(outputs_as_text);
835    }
836
837
838    /**
839     * Parsing inputs provided as KVP
840     */
841    r_inputs=getMap(request_inputs,"DataInputs");
842#ifdef DEBUG
843    fprintf(stderr,"DATA INPUTS [%s]\n",r_inputs->value);
844#endif
845    char current_input_as_string[40960];
846    char cursor_input[40960];
847    if(r_inputs!=NULL)
848      snprintf(cursor_input,40960,"%s",r_inputs->value);
849    else{
850      errorException(m, _("Parameter <DataInputs> was not specified"),"MissingParameterValue");
851      freeMaps(&m);
852      free(m);
853      free(REQUEST);
854      free(SERVICE_URL);
855      InternetCloseHandle(hInternet);
856      freeService(&s1);
857      free(s1);
858      return 0;
859    }
860    j=0;
861    map* request_kvp_inputs=NULL;
862 
863    /**
864     * Put each DataInputs into the inputs_as_text array
865     */
866    char * pToken;
867    pToken=strtok(cursor_input,";");
868    char** inputs_as_text=(char**)calloc(100,sizeof(char*));
869    if(inputs_as_text == NULL){
870      return errorException(m, _("Unable to allocate memory."), "InternalError");
871    }
872    i=0;
873    while(pToken!=NULL){
874#ifdef DEBUG
875      fprintf(stderr,"***%s***\n",pToken);
876#endif
877      fflush(stderr);
878#ifdef DEBUG
879      fprintf(stderr,"***%s***\n",pToken);
880#endif
881      inputs_as_text[i]=(char*)calloc(strlen(pToken)+1,sizeof(char));
882      snprintf(inputs_as_text[i],strlen(pToken)+1,"%s",pToken);
883      if(inputs_as_text[i] == NULL){
884        return errorException(m, _("Unable to allocate memory."), "InternalError");
885      }
886      pToken = strtok(NULL,";");
887      i++;
888    }
889
890    for(j=0;j<i;j++){
891      char *tmp=strdup(inputs_as_text[j]);
892      free(inputs_as_text[j]);
893      char *tmpc;
894      tmpc=strtok(tmp,"@");
895      while(tmpc!=NULL){
896#ifdef DEBUG
897        fprintf(stderr,"***\n***%s***\n",tmpc);
898#endif
899        char *tmpv=strstr(tmpc,"=");
900        char tmpn[256];
901        memset(tmpn,0,256);
902        strncpy(tmpn,tmpc,(strlen(tmpc)-strlen(tmpv))*sizeof(char));
903        tmpn[strlen(tmpc)-strlen(tmpv)]=0;
904        int cnt=0;
905#ifdef DEBUG
906        fprintf(stderr,"***\n*** %s = %s ***\n",tmpn,tmpv+1);
907#endif
908        if(tmpmaps==NULL){
909          tmpmaps=(maps*)calloc(1,MAPS_SIZE);
910          if(tmpmaps == NULL){
911            return errorException(m, _("Unable to allocate memory."), "InternalError");
912          }
913          tmpmaps->name=strdup(tmpn);
914          tmpmaps->content=createMap("value",tmpv+1);
915          tmpmaps->next=NULL;
916        }
917        tmpc=strtok(NULL,"@");
918        while(tmpc!=NULL){
919#ifdef DEBUG
920          fprintf(stderr,"*** KVP NON URL-ENCODED \n***%s***\n",tmpc);
921#endif
922          char *tmpv1=strstr(tmpc,"=");
923#ifdef DEBUG
924          fprintf(stderr,"*** VALUE NON URL-ENCODED \n***%s***\n",tmpv1+1);
925#endif
926          char tmpn1[1024];
927          memset(tmpn1,0,1024);
928          strncpy(tmpn1,tmpc,strlen(tmpc)-strlen(tmpv1));
929          tmpn1[strlen(tmpc)-strlen(tmpv1)]=0;
930#ifdef DEBUG
931          fprintf(stderr,"*** NAME NON URL-ENCODED \n***%s***\n",tmpn1);
932          fprintf(stderr,"*** VALUE NON URL-ENCODED \n***%s***\n",tmpv1+1);
933#endif
934          if(strcmp(tmpn1,"xlink:href")!=0)
935            addToMap(tmpmaps->content,tmpn1,tmpv1+1);
936          else{
937#ifdef DEBUG
938            fprintf(stderr,"REQUIRE TO DOWNLOAD A FILE FROM A SERVER : url(%s)\n",tmpv1+1);
939#endif
940#ifndef WIN32
941            if(CHECK_INET_HANDLE(hInternet))
942#endif
943              {
944                res=InternetOpenUrl(hInternet,tmpv1+1,NULL,0,
945                                    INTERNET_FLAG_NO_CACHE_WRITE,0);
946#ifdef DEBUG
947                fprintf(stderr,"(%s) content-length : %d,,res.nDataAlloc %d \n",
948                        tmpv1+1,res.nDataAlloc,res.nDataLen);
949#endif
950                char* tmpContent=(char*)calloc((res.nDataLen+1),sizeof(char));
951                if(tmpContent == NULL){
952                  return errorException(m, _("Unable to allocate memory."), "InternalError");
953                }
954                size_t dwRead;
955                InternetReadFile(res, (LPVOID)tmpContent,res.nDataLen, &dwRead);
956                map* tmpMap=getMap(tmpmaps->content,"value");
957                if(tmpMap!=NULL){
958                  free(tmpMap->value);
959                  tmpMap->value=(char*)malloc((res.nDataLen+1)*sizeof(char));
960                  memmove(tmpMap->value,tmpContent,(res.nDataLen)*sizeof(char));
961                  tmpMap->value[res.nDataLen]=0;
962                  if(strlen(tmpContent)!=res.nDataLen){
963                    char tmp[256];
964                    sprintf(tmp,"%d",res.nDataLen*sizeof(char));
965                    addToMap(tmpmaps->content,"size",tmp);
966                  }
967                }
968                free(tmpContent);
969              }
970            addToMap(tmpmaps->content,tmpn1,tmpv1+1);
971            addToMap(tmpmaps->content,"Reference",tmpv1+1);
972          }
973          tmpc=strtok(NULL,"@");
974        }
975#ifdef DEBUG
976        dumpMaps(tmpmaps);
977        fflush(stderr);
978#endif
979        if(request_input_real_format==NULL)
980          request_input_real_format=dupMaps(&tmpmaps);
981        else
982          addMapsToMaps(&request_input_real_format,tmpmaps);
983        freeMaps(&tmpmaps);
984        free(tmpmaps);
985        tmpmaps=NULL;
986        free(tmp);
987      }
988    }
989    free(inputs_as_text);
990  }
991  else {
992    /**
993     * Parse XML request
994     */ 
995    xmlInitParser();
996#ifdef DEBUG
997    fflush(stderr);
998    fprintf(stderr,"BEFORE %s\n",postRequest->value);
999    fflush(stderr);
1000#endif
1001    xmlDocPtr doc =
1002      xmlParseMemory(postRequest->value,cgiContentLength);
1003#ifdef DEBUG
1004    fprintf(stderr,"AFTER\n");
1005    fflush(stderr);
1006#endif
1007    xmlNodePtr cur = xmlDocGetRootElement(doc);
1008    /**
1009     * Parse every Input in DataInputs node.
1010     */
1011    maps* tempMaps=NULL;
1012    xmlXPathObjectPtr tmpsptr=extractFromDoc(doc,"/*/*/*[local-name()='Input']");
1013    xmlNodeSet* tmps=tmpsptr->nodesetval;
1014#ifdef DEBUG
1015    fprintf(stderr,"*****%d*****\n",tmps->nodeNr);
1016#endif
1017    for(int k=0;k<tmps->nodeNr;k++){
1018      maps *tmpmaps=NULL;
1019      xmlNodePtr cur=tmps->nodeTab[k];
1020      if(tmps->nodeTab[k]->type == XML_ELEMENT_NODE) {
1021        /**
1022         * A specific Input node.
1023         */
1024#ifdef DEBUG
1025        fprintf(stderr, "= element 0 node \"%s\"\n", cur->name);
1026#endif
1027        xmlNodePtr cur2=cur->children;
1028        while(cur2!=NULL){
1029          while(cur2!=NULL && cur2->type!=XML_ELEMENT_NODE)
1030            cur2=cur2->next;
1031          if(cur2==NULL)
1032            break;
1033          /**
1034           * Indentifier
1035           */
1036          if(xmlStrncasecmp(cur2->name,BAD_CAST "Identifier",xmlStrlen(cur2->name))==0){
1037            xmlChar *val= xmlNodeListGetString(doc,cur2->xmlChildrenNode,1);
1038            if(tmpmaps==NULL){
1039              tmpmaps=(maps*)calloc(1,MAPS_SIZE);
1040              if(tmpmaps == NULL){
1041                return errorException(m, _("Unable to allocate memory."), "InternalError");
1042              }
1043              tmpmaps->name=strdup((char*)val);
1044              tmpmaps->content=NULL;
1045              tmpmaps->next=NULL;
1046            }
1047            xmlFree(val);
1048          }
1049          /**
1050           * Title, Asbtract
1051           */
1052          if(xmlStrncasecmp(cur2->name,BAD_CAST "Title",xmlStrlen(cur2->name))==0 ||
1053             xmlStrncasecmp(cur2->name,BAD_CAST "Abstract",xmlStrlen(cur2->name))==0){
1054            xmlChar *val=
1055              xmlNodeListGetString(doc,cur2->xmlChildrenNode,1);
1056            if(tmpmaps==NULL){
1057              tmpmaps=(maps*)calloc(1,MAPS_SIZE);
1058              if(tmpmaps == NULL){
1059                return errorException(m, _("Unable to allocate memory."), "InternalError");
1060              }
1061              tmpmaps->name="missingIndetifier";
1062              tmpmaps->content=createMap((char*)cur2->name,(char*)val);
1063              tmpmaps->next=NULL;
1064            }
1065            else{
1066              if(tmpmaps->content!=NULL)
1067                addToMap(tmpmaps->content,
1068                         (char*)cur2->name,(char*)val);
1069              else
1070                tmpmaps->content=
1071                  createMap((char*)cur2->name,(char*)val);
1072            }
1073#ifdef DEBUG
1074            dumpMaps(tmpmaps);
1075#endif
1076            xmlFree(val);
1077          }
1078          /**
1079           * InputDataFormChoice (Reference or Data ?)
1080           */
1081          if(xmlStrcasecmp(cur2->name,BAD_CAST "Reference")==0){
1082            /**
1083             * Get every attribute from a Reference node
1084             * mimeType, encoding, schema, href, method
1085             * Header and Body gesture should be added here
1086             */
1087#ifdef DEBUG
1088            fprintf(stderr,"REFERENCE\n");
1089#endif
1090            map* referenceMap=NULL;
1091            char *refs[5];
1092            refs[0]="mimeType";
1093            refs[1]="encoding";
1094            refs[2]="schema";
1095            refs[3]="method";
1096            refs[4]="href";
1097            char*url;
1098            for(int l=0;l<5;l++){
1099#ifdef DEBUG
1100              fprintf(stderr,"*** %s ***",refs[l]);
1101#endif
1102              xmlChar *val=xmlGetProp(cur2,BAD_CAST refs[l]);
1103              if(val!=NULL && xmlStrlen(val)>0){
1104                if(tmpmaps->content!=NULL)
1105                  addToMap(tmpmaps->content,refs[l],(char*)val);
1106                else
1107                  tmpmaps->content=createMap(refs[l],(char*)val);
1108                map* ltmp=getMap(tmpmaps->content,"method");
1109                if(l==4){
1110                  if(!(ltmp!=NULL && strcmp(ltmp->value,"POST")==0)
1111                     && CHECK_INET_HANDLE(hInternet)){
1112                    res=InternetOpenUrl(hInternet,(char*)val,NULL,0,
1113                                        INTERNET_FLAG_NO_CACHE_WRITE,0);
1114                    char* tmpContent=
1115                      (char*)calloc((res.nDataLen+1),sizeof(char));
1116                    if(tmpContent == NULL){
1117                      return errorException(m, _("Unable to allocate memory."), "InternalError");
1118                    }
1119                    size_t dwRead;
1120                    InternetReadFile(res, (LPVOID)tmpContent,
1121                                     res.nDataLen, &dwRead);
1122                    tmpContent[res.nDataLen]=0;
1123                    addToMap(tmpmaps->content,"value",tmpContent);
1124                  }
1125                }
1126              }
1127#ifdef DEBUG
1128              fprintf(stderr,"%s\n",val);
1129#endif
1130              xmlFree(val);
1131            }
1132#ifdef POST_DEBUG
1133            fprintf(stderr,"Parse Header and Body from Reference \n");
1134#endif
1135            xmlNodePtr cur3=cur2->children;
1136            hInternet.header=NULL;
1137            while(cur3){
1138              if(xmlStrcasecmp(cur3->name,BAD_CAST "Header")==0 ){
1139                xmlNodePtr cur4=cur3;
1140                char *tmp=new char[cgiContentLength];
1141                char *ha[2];
1142                ha[0]="key";
1143                ha[1]="value";
1144                int hai;
1145                char *has;
1146                char *key;
1147                for(hai=0;hai<2;hai++){
1148                  xmlChar *val=xmlGetProp(cur3,BAD_CAST ha[hai]);
1149#ifdef POST_DEBUG
1150                  fprintf(stderr,"%s = %s\n",ha[hai],(char*)val);
1151#endif
1152                  if(hai==0){
1153                    key=(char*)calloc((1+strlen((char*)val)),sizeof(char));
1154                    snprintf(key,1+strlen((char*)val),"%s",(char*)val);
1155                  }else{
1156                    has=(char*)calloc((3+strlen((char*)val)+strlen(key)),sizeof(char));
1157                    if(has == NULL){
1158                      return errorException(m, _("Unable to allocate memory."), "InternalError");
1159                    }
1160                    snprintf(has,(3+strlen((char*)val)+strlen(key)),"%s: %s",key,(char*)val);
1161#ifdef POST_DEBUG
1162                    fprintf(stderr,"%s\n",has);
1163#endif
1164                  }
1165                }
1166                hInternet.header=curl_slist_append(hInternet.header, has);
1167                //free(has);
1168              }
1169              else{
1170#ifdef POST_DEBUG
1171                fprintf(stderr,"Try to fetch the body part of the request ...\n");
1172#endif
1173                if(xmlStrcasecmp(cur3->name,BAD_CAST "Body")==0 ){
1174#ifdef POST_DEBUG
1175                  fprintf(stderr,"Body part found !!!\n",(char*)cur3->content);
1176#endif
1177                  char *tmp=new char[cgiContentLength];
1178                  memset(tmp,0,cgiContentLength);
1179                  xmlNodePtr cur4=cur3->children;
1180                  while(cur4!=NULL){
1181                    xmlDocPtr bdoc = xmlNewDoc(BAD_CAST "1.0");
1182                    bdoc->encoding = xmlCharStrdup ("UTF-8");
1183                    xmlDocSetRootElement(bdoc,cur4);
1184                    xmlChar* btmps;
1185                    int bsize;
1186                    xmlDocDumpMemory(bdoc,&btmps,&bsize);
1187#ifdef POST_DEBUG
1188                    fprintf(stderr,"Body part found !!! %s %s\n",tmp,(char*)btmps);
1189#endif
1190                    if(btmps!=NULL)
1191                      sprintf(tmp,"%s",(char*)btmps);
1192                    xmlFreeDoc(bdoc);
1193                    cur4=cur4->next;
1194                  }
1195                  map *btmp=getMap(tmpmaps->content,"href");
1196                  if(btmp!=NULL){
1197#ifdef POST_DEBUG
1198                    fprintf(stderr,"%s %s\n",btmp->value,tmp);
1199                    curl_easy_setopt(hInternet.handle, CURLOPT_VERBOSE, 1);
1200#endif
1201                    res=InternetOpenUrl(hInternet,btmp->value,tmp,strlen(tmp),
1202                                        INTERNET_FLAG_NO_CACHE_WRITE,0);
1203                    char* tmpContent = (char*)calloc((res.nDataLen+1),sizeof(char));
1204                    if(tmpContent == NULL){
1205                      return errorException(m, _("Unable to allocate memory."), "InternalError");
1206                    }
1207                    size_t dwRead;
1208                    InternetReadFile(res, (LPVOID)tmpContent,
1209                                     res.nDataLen, &dwRead);
1210                    tmpContent[res.nDataLen]=0;
1211                    if(hInternet.header!=NULL)
1212                      curl_slist_free_all(hInternet.header);
1213                    addToMap(tmpmaps->content,"value",tmpContent);
1214#ifdef POST_DEBUG
1215                    fprintf(stderr,"DL CONTENT : (%s)\n",tmpContent);
1216#endif
1217                  }
1218                }
1219                else
1220                  if(xmlStrcasecmp(cur3->name,BAD_CAST "BodyReference")==0 ){
1221                    xmlChar *val=xmlGetProp(cur3,BAD_CAST "href");
1222                    HINTERNET bInternet,res1;
1223                    bInternet=InternetOpen(
1224#ifndef WIN32
1225                                           (LPCTSTR)
1226#endif
1227                                           "ZooWPSClient\0",
1228                                           INTERNET_OPEN_TYPE_PRECONFIG,
1229                                           NULL,NULL, 0);
1230                    if(!CHECK_INET_HANDLE(bInternet))
1231                      fprintf(stderr,"WARNING : hInternet handle failed to initialize");
1232#ifdef POST_DEBUG
1233                    curl_easy_setopt(bInternet.handle, CURLOPT_VERBOSE, 1);
1234#endif
1235                    res1=InternetOpenUrl(bInternet,(char*)val,NULL,0,
1236                                         INTERNET_FLAG_NO_CACHE_WRITE,0);
1237                    char* tmp=
1238                      (char*)calloc((res1.nDataLen+1),sizeof(char));
1239                    if(tmp == NULL){
1240                      return errorException(m, _("Unable to allocate memory."), "InternalError");
1241                    }
1242                    size_t bRead;
1243                    InternetReadFile(res1, (LPVOID)tmp,
1244                                     res1.nDataLen, &bRead);
1245                    tmp[res1.nDataLen]=0;
1246                    InternetCloseHandle(bInternet);
1247                    map *btmp=getMap(tmpmaps->content,"href");
1248                    if(btmp!=NULL){
1249#ifdef POST_DEBUG
1250                      fprintf(stderr,"%s %s\n",btmp->value,tmp);
1251                      curl_easy_setopt(hInternet.handle, CURLOPT_VERBOSE, 1);
1252#endif
1253                      res=InternetOpenUrl(hInternet,btmp->value,tmp,
1254                                          strlen(tmp),
1255                                          INTERNET_FLAG_NO_CACHE_WRITE,0);
1256                      char* tmpContent = (char*)calloc((res.nDataLen+1),sizeof(char));
1257                      if(tmpContent == NULL){
1258                        return errorException(m, _("Unable to allocate memory."), "InternalError");
1259                      }
1260                      size_t dwRead;
1261                      InternetReadFile(res, (LPVOID)tmpContent,
1262                                       res.nDataLen, &dwRead);
1263                      tmpContent[res.nDataLen]=0;
1264                      if(hInternet.header!=NULL)
1265                        curl_slist_free_all(hInternet.header);
1266                      addToMap(tmpmaps->content,"value",tmpContent);
1267#ifdef POST_DEBUG
1268                      fprintf(stderr,"DL CONTENT : (%s)\n",tmpContent);
1269#endif
1270                    }
1271                  }
1272              }
1273              cur3=cur3->next;
1274            }
1275#ifdef POST_DEBUG
1276            fprintf(stderr,"Header and Body was parsed from Reference \n");
1277#endif
1278#ifdef DEBUG
1279            dumpMap(tmpmaps->content);
1280            fprintf(stderr, "= element 2 node \"%s\" = (%s)\n", 
1281                    cur2->name,cur2->content);
1282#endif
1283          }
1284          else if(xmlStrcasecmp(cur2->name,BAD_CAST "Data")==0){
1285#ifdef DEBUG
1286            fprintf(stderr,"DATA\n");
1287#endif
1288            xmlNodePtr cur4=cur2->children;
1289            while(cur4!=NULL){
1290              while(cur4!=NULL &&cur4->type!=XML_ELEMENT_NODE)
1291                cur4=cur4->next;
1292              if(cur4==NULL)
1293                break;
1294              if(xmlStrcasecmp(cur4->name, BAD_CAST "LiteralData")==0){
1295                /**
1296                 * Get every attribute from a LiteralData node
1297                 * dataType , uom
1298                 */
1299                char *lits[2];
1300                lits[0]="dataType";
1301                lits[1]="uom";
1302                for(int l=0;l<2;l++){
1303#ifdef DEBUG
1304                  fprintf(stderr,"*** LiteralData %s ***",lits[l]);
1305#endif
1306                  xmlChar *val=xmlGetProp(cur4,BAD_CAST lits[l]);
1307                  if(val!=NULL && strlen((char*)val)>0){
1308                    if(tmpmaps->content!=NULL)
1309                      addToMap(tmpmaps->content,lits[l],(char*)val);
1310                    else
1311                      tmpmaps->content=createMap(lits[l],(char*)val);
1312                  }
1313#ifdef DEBUG
1314                  fprintf(stderr,"%s\n",val);
1315#endif
1316                  xmlFree(val);
1317                }
1318              }
1319              else if(xmlStrcasecmp(cur4->name, BAD_CAST "ComplexData")==0){
1320                /**
1321                 * Get every attribute from a Reference node
1322                 * mimeType, encoding, schema
1323                 */
1324                char *coms[3];
1325                coms[0]="mimeType";
1326                coms[1]="encoding";
1327                coms[2]="schema";
1328                for(int l=0;l<3;l++){
1329#ifdef DEBUG
1330                  fprintf(stderr,"*** ComplexData %s ***",coms[l]);
1331#endif
1332                  xmlChar *val=xmlGetProp(cur4,BAD_CAST coms[l]);
1333                  if(val!=NULL && strlen((char*)val)>0){
1334                    if(tmpmaps->content!=NULL)
1335                      addToMap(tmpmaps->content,coms[l],(char*)val);
1336                    else
1337                      tmpmaps->content=createMap(coms[l],(char*)val);
1338                  }
1339#ifdef DEBUG
1340                  fprintf(stderr,"%s\n",val);
1341#endif
1342                  xmlFree(val);
1343                }
1344              }
1345              xmlChar* mv=xmlNodeListGetString(doc,cur4->xmlChildrenNode,1);
1346              if(mv==NULL){
1347                xmlDocPtr doc1=xmlNewDoc(BAD_CAST "1.0");
1348                int buffersize;
1349                xmlDocSetRootElement(doc1,cur4->xmlChildrenNode);
1350                xmlDocDumpFormatMemoryEnc(doc1, &mv, &buffersize, "utf-8", 1);
1351                char size[1024];
1352                sprintf(size,"%d",buffersize);
1353                addToMap(tmpmaps->content,"size",size);
1354              }
1355              addToMap(tmpmaps->content,"value",(char*)mv);
1356              xmlFree(mv);
1357              cur4=cur4->next;
1358            }
1359          }
1360#ifdef DEBUG
1361          fprintf(stderr,"cur2 next \n");
1362          fflush(stderr);
1363#endif
1364          cur2=cur2->next;
1365        }
1366#ifdef DEBUG
1367        fprintf(stderr,"ADD MAPS TO REQUEST MAPS !\n");
1368        fflush(stderr);
1369#endif
1370        addMapsToMaps(&request_input_real_format,tmpmaps);
1371       
1372#ifdef DEBUG
1373        fprintf(stderr,"******TMPMAPS*****\n");
1374        dumpMaps(tmpmaps);
1375        fprintf(stderr,"******REQUESTMAPS*****\n");
1376        dumpMaps(request_input_real_format);
1377#endif
1378        freeMaps(&tmpmaps);
1379        free(tmpmaps);
1380        tmpmaps=NULL;         
1381      }
1382#ifdef DEBUG
1383      dumpMaps(tmpmaps); 
1384#endif
1385    }
1386#ifdef DEBUG
1387    fprintf(stderr,"Search for response document node\n");
1388#endif
1389    xmlXPathFreeObject(tmpsptr);
1390    //xmlFree(tmps);
1391    tmpsptr=extractFromDoc(doc,"/*/*/*[local-name()='ResponseDocument']");
1392    tmps=tmpsptr->nodesetval;
1393#ifdef DEBUG
1394    fprintf(stderr,"*****%d*****\n",tmps->nodeNr);
1395#endif
1396    for(int k=0;k<tmps->nodeNr;k++){
1397      addToMap(request_inputs,"ResponseDocument","");
1398      request_output_real_format;
1399      maps *tmpmaps=NULL;
1400      xmlNodePtr cur=tmps->nodeTab[k];
1401      if(cur->type == XML_ELEMENT_NODE) {
1402        /**
1403         * A specific responseDocument node.
1404         */
1405        if(tmpmaps==NULL){
1406          tmpmaps=(maps*)calloc(1,MAPS_SIZE);
1407          if(tmpmaps == NULL){
1408            return errorException(m, _("Unable to allocate memory."), "InternalError");
1409          }
1410          tmpmaps->name="unknownIdentifier";
1411          tmpmaps->next=NULL;
1412        }
1413        /**
1414         * Get every attribute from a LiteralData node
1415         * storeExecuteResponse, lineage, status
1416         */
1417        char *ress[3];
1418        ress[0]="storeExecuteResponse";
1419        ress[1]="lineage";
1420        ress[2]="status";
1421        xmlChar *val;
1422        for(int l=0;l<3;l++){
1423#ifdef DEBUG
1424          fprintf(stderr,"*** %s ***\t",ress[l]);
1425#endif
1426          val=xmlGetProp(cur,BAD_CAST ress[l]);
1427          if(val!=NULL && strlen((char*)val)>0){
1428            if(tmpmaps->content!=NULL)
1429              addToMap(tmpmaps->content,ress[l],(char*)val);
1430            else
1431              tmpmaps->content=createMap(ress[l],(char*)val);
1432            addToMap(request_inputs,ress[l],(char*)val);
1433          }
1434#ifdef DEBUG
1435          fprintf(stderr,"%s\n",val);
1436#endif
1437          xmlFree(val);
1438        }
1439        xmlNodePtr cur1=cur->children;
1440        while(cur1){
1441          if(xmlStrncasecmp(cur1->name,BAD_CAST "Output",xmlStrlen(cur1->name))==0){
1442            /**
1443             * Get every attribute from a Output node
1444             * mimeType, encoding, schema, uom, asReference
1445             */
1446            char *outs[5];
1447            outs[0]="mimeType";
1448            outs[1]="encoding";
1449            outs[2]="schema";
1450            outs[3]="uom";
1451            outs[4]="asReference";
1452            for(int l=0;l<5;l++){
1453#ifdef DEBUG
1454              fprintf(stderr,"*** %s ***\t",outs[l]);
1455#endif
1456              val=xmlGetProp(cur1,BAD_CAST outs[l]);
1457              if(val!=NULL && strlen((char*)val)>0){
1458                if(tmpmaps->content!=NULL)
1459                  addToMap(tmpmaps->content,outs[l],(char*)val);
1460                else
1461                  tmpmaps->content=createMap(outs[l],(char*)val);
1462              }
1463#ifdef DEBUG
1464              fprintf(stderr,"%s\n",val);
1465#endif
1466              xmlFree(val);
1467            }
1468           
1469            xmlNodePtr cur2=cur1->children;
1470            while(cur2){
1471              /**
1472               * Indentifier
1473               */
1474              if(xmlStrncasecmp(cur2->name,BAD_CAST "Identifier",xmlStrlen(cur2->name))==0){
1475                xmlChar *val=
1476                  xmlNodeListGetString(doc,cur2->xmlChildrenNode,1);
1477                if(tmpmaps==NULL){
1478                  tmpmaps=(maps*)calloc(1,MAPS_SIZE);
1479                  if(tmpmaps == NULL){
1480                    return errorException(m, _("Unable to allocate memory."), "InternalError");
1481                  }
1482                  tmpmaps->name=strdup((char*)val);
1483                  tmpmaps->content=NULL;
1484                  tmpmaps->next=NULL;
1485                }
1486                else
1487                  tmpmaps->name=strdup((char*)val);;
1488                xmlFree(val);
1489              }
1490              /**
1491               * Title, Asbtract
1492               */
1493              if(xmlStrncasecmp(cur2->name,BAD_CAST "Title",xmlStrlen(cur2->name))==0 ||
1494                 xmlStrncasecmp(cur2->name,BAD_CAST "Abstract",xmlStrlen(cur2->name))==0){
1495                xmlChar *val=
1496                  xmlNodeListGetString(doc,cur2->xmlChildrenNode,1);
1497                if(tmpmaps==NULL){
1498                  tmpmaps=(maps*)calloc(1,MAPS_SIZE);
1499                  if(tmpmaps == NULL){
1500                    return errorException(m, _("Unable to allocate memory."), "InternalError");
1501                  }
1502                  tmpmaps->name="missingIndetifier";
1503                  tmpmaps->content=createMap((char*)cur2->name,(char*)val);
1504                  tmpmaps->next=NULL;
1505                }
1506                else{
1507                  if(tmpmaps->content!=NULL)
1508                    addToMap(tmpmaps->content,
1509                             (char*)cur2->name,(char*)val);
1510                  else
1511                    tmpmaps->content=
1512                      createMap((char*)cur2->name,(char*)val);
1513                }
1514                xmlFree(val);
1515              }
1516              cur2=cur2->next;
1517            }
1518          }
1519          cur1=cur1->next;
1520        }
1521      }
1522      //xmlFree(cur);
1523      if(request_output_real_format==NULL)
1524        request_output_real_format=tmpmaps;
1525      else
1526        addMapsToMaps(&request_output_real_format,tmpmaps);
1527#ifdef DEBUG
1528      dumpMaps(tmpmaps);
1529#endif
1530    }
1531    xmlXPathFreeObject(tmpsptr);
1532    //xmlFree(tmps);
1533    tmpsptr=extractFromDoc(doc,"/*/*/*[local-name()='RawDataOutput']");
1534    tmps=tmpsptr->nodesetval;
1535#ifdef DEBUG
1536    fprintf(stderr,"*****%d*****\n",tmps->nodeNr);
1537#endif
1538    for(int k=0;k<tmps->nodeNr;k++){
1539      addToMap(request_inputs,"RawDataOutput","");
1540      xmlNodePtr cur1=tmps->nodeTab[k];
1541      xmlChar *val;
1542      /**
1543       * Get every attribute from a Output node
1544       * mimeType, encoding, schema, uom, asReference
1545       */
1546      char *outs[4];
1547      outs[0]="mimeType";
1548      outs[1]="encoding";
1549      outs[2]="schema";
1550      outs[3]="uom";
1551      for(int l=0;l<4;l++){
1552#ifdef DEBUG
1553        fprintf(stderr,"*** %s ***\t",outs[l]);
1554#endif
1555        val=xmlGetProp(cur1,BAD_CAST outs[l]);
1556        if(val!=NULL && strlen((char*)val)>0){
1557          if(tmpmaps==NULL){
1558            tmpmaps=(maps*)calloc(1,MAPS_SIZE);
1559            if(tmpmaps == NULL){
1560              return errorException(m, _("Unable to allocate memory."), "InternalError");
1561            }
1562            tmpmaps->name="unknownIdentifier";
1563            tmpmaps->content=createMap(outs[l],(char*)val);
1564            tmpmaps->next=NULL;
1565          }
1566          else
1567            addToMap(tmpmaps->content,outs[l],(char*)val);
1568        }
1569#ifdef DEBUG
1570        fprintf(stderr,"%s\n",val);
1571#endif
1572        xmlFree(val);
1573      }
1574           
1575      xmlNodePtr cur2=cur1->children;
1576      while(cur2){
1577        /**
1578         * Indentifier
1579         */
1580        if(xmlStrncasecmp(cur2->name,BAD_CAST "Identifier",xmlStrlen(cur2->name))==0){
1581          val=
1582            xmlNodeListGetString(doc,cur2->xmlChildrenNode,1);
1583          if(tmpmaps==NULL){
1584            tmpmaps=(maps*)calloc(1,MAPS_SIZE);
1585            if(tmpmaps == NULL){
1586              return errorException(m, _("Unable to allocate memory."), "InternalError");
1587            }
1588            tmpmaps->name=strdup((char*)val);
1589            tmpmaps->content=NULL;
1590            tmpmaps->next=NULL;
1591          }
1592          else
1593            tmpmaps->name=strdup((char*)val);;
1594          xmlFree(val);
1595        }
1596        cur2=cur2->next;
1597      }
1598      if(request_output_real_format==NULL)
1599        request_output_real_format=tmpmaps;
1600      else
1601        addMapsToMaps(&request_output_real_format,tmpmaps);
1602#ifdef DEBUG
1603      dumpMaps(tmpmaps);
1604#endif
1605    }
1606    xmlXPathFreeObject(tmpsptr);
1607    //xmlFree(tmps);
1608    xmlCleanupParser();
1609  }
1610
1611  //if(CHECK_INET_HANDLE(hInternet))
1612  InternetCloseHandle(hInternet);
1613
1614#ifdef DEBUG
1615  fprintf(stderr,"\n%i\n",i);
1616  dumpMaps(request_input_real_format);
1617  dumpMaps(request_output_real_format);
1618  dumpMap(request_inputs);
1619#endif
1620
1621  /**
1622   * Ensure that each requested arguments are present in the request
1623   * DataInputs and ResponseDocument / RawDataOutput
1624   */
1625  char *dfv=addDefaultValues(&request_input_real_format,s1->inputs,m,0);
1626  if(strcmp(dfv,"")!=0){
1627    char tmps[1024];
1628    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);
1629    map* tmpe=createMap("text",tmps);
1630    addToMap(tmpe,"code","MissingParameterValue");
1631    printExceptionReportResponse(m,tmpe);
1632    freeService(&s1);
1633    free(s1);
1634    freeMap(&tmpe);
1635    free(tmpe);
1636    freeMaps(&m);
1637    free(m);
1638    free(REQUEST);
1639    free(SERVICE_URL);
1640    freeMaps(&request_input_real_format);
1641    free(request_input_real_format);
1642    freeMaps(&request_output_real_format);
1643    free(request_output_real_format);
1644    freeMaps(&tmpmaps);
1645    free(tmpmaps);
1646    return 1;
1647  }
1648  addDefaultValues(&request_output_real_format,s1->outputs,m,1);
1649
1650  ensureDecodedBase64(&request_input_real_format);
1651
1652#ifdef DEBUG
1653  fprintf(stderr,"REQUEST_INPUTS\n");
1654  dumpMaps(request_input_real_format);
1655  fprintf(stderr,"REQUEST_OUTPUTS\n");
1656  dumpMaps(request_output_real_format);
1657#endif
1658
1659  maps* curs=getMaps(m,"env");
1660  if(curs!=NULL){
1661    map* mapcs=curs->content;
1662    while(mapcs!=NULLMAP){
1663#ifndef WIN32
1664      setenv(mapcs->name,mapcs->value,1);
1665#else
1666#ifdef DEBUG
1667      fprintf(stderr,"[ZOO: setenv (%s=%s)]\n",mapcs->name,mapcs->value);
1668#endif
1669      if(mapcs->value[strlen(mapcs->value)-2]=='\r'){
1670#ifdef DEBUG
1671        fprintf(stderr,"[ZOO: Env var finish with \r]\n");
1672#endif
1673        mapcs->value[strlen(mapcs->value)-1]=0;
1674      }
1675#ifdef DEBUG
1676      fflush(stderr);
1677      fprintf(stderr,"setting variable... %s\n",
1678#endif
1679              SetEnvironmentVariable(mapcs->name,mapcs->value)
1680#ifdef DEBUG
1681              ? "OK" : "FAILED");
1682#else
1683      ;
1684#endif
1685#ifdef DEBUG
1686      fflush(stderr);
1687#endif
1688#endif
1689#ifdef DEBUG
1690      fprintf(stderr,"[ZOO: setenv (%s=%s)]\n",mapcs->name,mapcs->value);
1691      fflush(stderr);
1692#endif
1693      mapcs=mapcs->next;
1694    }
1695  }
1696 
1697#ifdef DEBUG
1698  dumpMap(request_inputs);
1699#endif
1700
1701  /**
1702   * Need to check if we need to fork to load a status enabled
1703   */
1704  r_inputs=NULL;
1705  map* store=getMap(request_inputs,"storeExecuteResponse");
1706  map* status=getMap(request_inputs,"status");
1707  /**
1708   * 05-007r7 WPS 1.0.0 page 57 :
1709   * 'If status="true" and storeExecuteResponse is "false" then the service
1710   * shall raise an exception.'
1711   */
1712  if(status!=NULL && strcmp(status->value,"true")==0 && 
1713     store!=NULL && strcmp(store->value,"false")==0){
1714    errorException(m, _("Status cannot be set to true with storeExecuteResponse to false. Please, modify your request parameters."), "InvalidParameterValue");
1715    freeService(&s1);
1716    free(s1);
1717    freeMaps(&m);
1718    free(m);
1719   
1720    freeMaps(&request_input_real_format);
1721    free(request_input_real_format);
1722   
1723    freeMaps(&request_output_real_format);
1724    free(request_output_real_format);
1725   
1726    free(REQUEST);
1727    free(SERVICE_URL);
1728    return 1;
1729  }
1730  r_inputs=getMap(request_inputs,"storeExecuteResponse");
1731  int eres=SERVICE_STARTED;
1732  int cpid=getpid();
1733 
1734  maps *_tmpMaps=(maps*)malloc(MAPS_SIZE);
1735  _tmpMaps->name=strdup("lenv");
1736  char tmpBuff[100];
1737  sprintf(tmpBuff,"%i",cpid);
1738  _tmpMaps->content=createMap("sid",tmpBuff);
1739  _tmpMaps->next=NULL;
1740  addToMap(_tmpMaps->content,"status","0");
1741  if(cgiCookie!=NULL && strlen(cgiCookie)>0){
1742    addToMap(_tmpMaps->content,"sessid",strstr(cgiCookie,"=")+1);
1743    char session_file_path[1024];
1744    map *tmpPath=getMapFromMaps(m,"main","sessPath");
1745    if(tmpPath==NULL)
1746      tmpPath=getMapFromMaps(m,"main","tmpPath");
1747    sprintf(session_file_path,"%s/sess_%s.cfg",tmpPath->value,strstr(cgiCookie,"=")+1);
1748    maps *tmpSess=(maps*)calloc(1,MAPS_SIZE);
1749    struct stat file_status;
1750    int istat = stat(session_file_path, &file_status);
1751    if(istat==0){
1752      conf_read(session_file_path,tmpSess);
1753      dumpMaps(tmpSess);
1754      addMapsToMaps(&m,tmpSess);
1755      freeMaps(&tmpSess);
1756    }
1757    free(tmpSess);
1758  }
1759  addMapsToMaps(&m,_tmpMaps);
1760  freeMaps(&_tmpMaps);
1761  free(_tmpMaps);
1762
1763#ifdef DEBUG
1764  dumpMap(request_inputs);
1765#endif
1766
1767  if(status!=NULL)
1768    if(strcasecmp(status->value,"false")==0)
1769      status=NULL;
1770  if(status==NULLMAP){
1771    loadServiceAndRun(&m,s1,request_inputs,&request_input_real_format,&request_output_real_format,&eres);
1772  }
1773  else{
1774    pid_t   pid;
1775#ifdef DEBUG
1776    fprintf(stderr,"\nPID : %d\n",cpid);
1777#endif
1778
1779#ifndef WIN32
1780    pid = fork ();
1781#else
1782    pid = 0;
1783#endif
1784    if (pid > 0) {
1785      /**
1786       * dady :
1787       * set status to SERVICE_ACCEPTED
1788       */
1789#ifdef DEBUG
1790      fprintf(stderr,"father pid continue (origin %d) %d ...\n",cpid,getpid());
1791#endif
1792      eres=SERVICE_ACCEPTED;
1793    }else if (pid == 0) {
1794      /**
1795       * son : have to close the stdout, stdin and stderr to let the parent
1796       * process answer to http client.
1797       */
1798      r_inputs=getMapFromMaps(m,"main","tmpPath");
1799      map* r_inputs1=getMap(s1->content,"ServiceProvider");
1800      char* fbkp=(char*)malloc((strlen(r_inputs->value)+strlen(r_inputs1->value)+100)*sizeof(char));
1801      sprintf(fbkp,"%s/%s_%d.xml",r_inputs->value,r_inputs1->value,cpid);
1802      char* flog=(char*)malloc((strlen(r_inputs->value)+strlen(r_inputs1->value)+100)*sizeof(char));
1803      sprintf(flog,"%s/%s_%d_error.log",r_inputs->value,r_inputs1->value,cpid);
1804#ifdef DEBUG
1805      fprintf(stderr,"RUN IN BACKGROUND MODE \n");
1806      fprintf(stderr,"son pid continue (origin %d) %d ...\n",cpid,getpid());
1807      fprintf(stderr,"\nFILE TO STORE DATA %s\n",r_inputs->value);
1808#endif
1809      freopen(fbkp , "w+", stdout);
1810      fclose(stdin);
1811      freopen(flog,"w+",stderr);
1812      free(fbkp);
1813      free(flog);
1814      /**
1815       * set status to SERVICE_STARTED and flush stdout to ensure full
1816       * content was outputed (the file used to store the ResponseDocument).
1817       * The rewind stdout to restart writing from the bgining of the file,
1818       * this way the data will be updated at the end of the process run.
1819       */
1820      updateStatus(m);
1821      printProcessResponse(m,request_inputs,cpid,
1822                            s1,r_inputs1->value,SERVICE_STARTED,
1823                            request_input_real_format,
1824                            request_output_real_format);
1825      fflush(stdout);
1826      rewind(stdout);
1827
1828      loadServiceAndRun(&m,s1,request_inputs,&request_input_real_format,&request_output_real_format,&eres);
1829
1830    } else {
1831      /**
1832       * error server don't accept the process need to output a valid
1833       * error response here !!!
1834       */
1835      eres=-1;
1836      errorException(m, _("Unable to run the child process properly"), "InternalError");
1837    }
1838       
1839  }
1840
1841#ifdef DEBUG
1842  dumpMaps(request_output_real_format);
1843  fprintf(stderr,"Function loaded and returned %d\n",eres);
1844  fflush(stderr);
1845#endif
1846  if(eres!=-1)
1847    outputResponse(s1,request_input_real_format,
1848                   request_output_real_format,request_inputs,
1849                   cpid,m,eres);
1850
1851  if(((int)getpid())!=cpid){
1852    fclose(stdout);
1853    fclose(stderr);
1854    unhandleStatus(m);
1855  }
1856
1857  freeService(&s1);
1858  free(s1);
1859  freeMaps(&m);
1860  free(m);
1861 
1862  freeMaps(&request_input_real_format);
1863  free(request_input_real_format);
1864 
1865  freeMaps(&request_output_real_format);
1866  free(request_output_real_format);
1867 
1868  free(REQUEST);
1869  free(SERVICE_URL);
1870#ifdef DEBUG
1871  fprintf(stderr,"Processed response \n");
1872  fflush(stdout);
1873  fflush(stderr);
1874#endif
1875
1876  return 0;
1877}
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