source: trunk/zoo-project/zoo-kernel/service_internal.c @ 467

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

Various fixes for tickets #93, #94, #95, #95, #96.

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc
File size: 80.1 KB
Line 
1/**
2 * Author : Gérald FENOY
3 *
4 * Copyright (c) 2009-2013 GeoLabs SARL
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#include "service_internal.h"
26#ifdef USE_MS
27#include "service_internal_ms.h"
28#endif
29
30#ifndef TRUE
31#define TRUE 1
32#endif
33#ifndef FALSE
34#define FALSE -1
35#endif
36
37void printHeaders(maps* m){
38  maps *_tmp=getMaps(m,"headers");
39  if(_tmp!=NULL){
40    map* _tmp1=_tmp->content;
41    while(_tmp1!=NULL){
42      printf("%s: %s\r\n",_tmp1->name,_tmp1->value);
43      _tmp1=_tmp1->next;
44    }
45  }
46}
47
48void addLangAttr(xmlNodePtr n,maps *m){
49  map *tmpLmap=getMapFromMaps(m,"main","language");
50  if(tmpLmap!=NULL)
51    xmlNewProp(n,BAD_CAST "xml:lang",BAD_CAST tmpLmap->value);
52  else
53    xmlNewProp(n,BAD_CAST "xml:lang",BAD_CAST "en-US");
54}
55
56/* Converts a hex character to its integer value */
57char from_hex(char ch) {
58  return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
59}
60
61/* Converts an integer value to its hex character*/
62char to_hex(char code) {
63  static char hex[] = "0123456789abcdef";
64  return hex[code & 15];
65}
66
67#ifdef WIN32
68
69#include <windows.h>
70#include <stdio.h>
71#include <conio.h>
72#include <tchar.h>
73
74#define SHMEMSIZE 4096
75
76static LPVOID lpvMemG = NULL;      // pointer to shared memory
77static HANDLE hMapObjectG = NULL;  // handle to file mapping
78
79void updateStatus(maps *conf){
80  LPWSTR lpszTmp;
81  BOOL fInit;
82  char *final_string=NULL;
83  char *s=NULL;
84  map *tmpMap1;
85  map *tmpMap=getMapFromMaps(conf,"lenv","sid");
86  if(hMapObjectG==NULL)
87    hMapObjectG = CreateFileMapping( 
88                                    INVALID_HANDLE_VALUE,   // use paging file
89                                    NULL,                   // default security attributes
90                                    PAGE_READWRITE,         // read/write access
91                                    0,                      // size: high 32-bits
92                                    SHMEMSIZE,              // size: low 32-bits
93                                    TEXT(tmpMap->value));   // name of map object
94  if (hMapObjectG == NULL){
95    fprintf(stderr,"Unable to create share memory segment %s !! \n",tmpMap->value);
96    return ;
97  }
98  fInit = (GetLastError() != ERROR_ALREADY_EXISTS); 
99  if(lpvMemG==NULL)
100    lpvMemG = MapViewOfFile( 
101                            hMapObjectG,     // object to map view of
102                            FILE_MAP_WRITE, // read/write access
103                            0,              // high offset:  map from
104                            0,              // low offset:   beginning
105                            0);             // default: map entire file
106  if (lpvMemG == NULL){
107    fprintf(stderr,"Unable to create or access the shared memory segment %s !! \n",tmpMap->value);
108    return ;
109  } 
110  memset(lpvMemG, '\0', SHMEMSIZE);
111  tmpMap=getMapFromMaps(conf,"lenv","status");
112  tmpMap1=NULL;
113  tmpMap1=getMapFromMaps(conf,"lenv","message");
114  lpszTmp = (LPWSTR) lpvMemG;
115  final_string=(char*)malloc((strlen(tmpMap1->value)+strlen(tmpMap->value)+2)*sizeof(char));
116  sprintf(final_string,"%s|%s",tmpMap->value,tmpMap1->value);
117  for(s=final_string;*s!='\0';*s++){
118    *lpszTmp++ = *s;
119  }
120  *lpszTmp++ = '\0';
121  free(final_string);
122}
123
124char* getStatus(int pid){
125  char *lpszBuf=(char*) malloc(SHMEMSIZE*sizeof(char));
126  int i=0;
127  LPWSTR lpszTmp=NULL;
128  LPVOID lpvMem = NULL;
129  HANDLE hMapObject = NULL;
130  BOOL fIgnore,fInit;
131  char tmp[100];
132  sprintf(tmp,"%i",pid);
133  if(hMapObject==NULL)
134    hMapObject = CreateFileMapping( 
135                                   INVALID_HANDLE_VALUE,   // use paging file
136                                   NULL,                   // default security attributes
137                                   PAGE_READWRITE,         // read/write access
138                                   0,                      // size: high 32-bits
139                                   4096,                   // size: low 32-bits
140                                   TEXT(tmp));   // name of map object
141  if (hMapObject == NULL) 
142    return FALSE;
143  if((GetLastError() != ERROR_ALREADY_EXISTS)){
144    fIgnore = UnmapViewOfFile(lpvMem); 
145    fIgnore = CloseHandle(hMapObject);
146    return "-1";
147  }
148  fInit=TRUE;
149  if(lpvMem==NULL)
150    lpvMem = MapViewOfFile( 
151                           hMapObject,     // object to map view of
152                           FILE_MAP_READ,  // read/write access
153                           0,              // high offset:  map from
154                           0,              // low offset:   beginning
155                           0);             // default: map entire file
156  if (lpvMem == NULL) 
157    return "-1"; 
158  lpszTmp = (LPWSTR) lpvMem;
159  while (*lpszTmp){
160    lpszBuf[i] = (char)*lpszTmp;
161    *lpszTmp++; 
162    lpszBuf[i+1] = '\0'; 
163    i++;
164  }
165  fprintf(stderr,"READING STRING S %s\n",lpszBuf);
166  return (char*)lpszBuf;
167}
168
169void unhandleStatus(maps *conf){
170  BOOL fIgnore;
171  fIgnore = UnmapViewOfFile(lpvMemG); 
172  fIgnore = CloseHandle(hMapObjectG);
173}
174#else
175
176void unhandleStatus(maps *conf){
177  int shmid,i;
178  key_t key;
179  void *shm;
180  struct shmid_ds shmids;
181  char *s,*s1;
182  map *tmpMap=getMapFromMaps(conf,"lenv","sid");
183  if(tmpMap!=NULL){
184    key=atoi(tmpMap->value);
185    if ((shmid = shmget(key, SHMSZ, IPC_CREAT | 0666)) < 0) {
186#ifdef DEBUG
187      fprintf(stderr,"shmget failed to update value\n");
188#endif
189    }else{
190      if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
191#ifdef DEBUG
192        fprintf(stderr,"shmat failed to update value\n");
193#endif
194      }else{
195        shmdt(shm);
196        shmctl(shmid,IPC_RMID,&shmids);
197      }
198    }
199  }
200}
201
202void updateStatus(maps *conf){
203  int shmid,i;
204  key_t key;
205  char *shm,*s,*s1;
206  map *tmpMap=NULL;
207  tmpMap=getMapFromMaps(conf,"lenv","sid");
208  if(tmpMap!=NULL){
209    key=atoi(tmpMap->value);
210    if ((shmid = shmget(key, SHMSZ, IPC_CREAT | 0666)) < 0) {
211#ifdef DEBUG
212      fprintf(stderr,"shmget failed to create new Shared memory segment\n");
213#endif
214    }else{
215      if ((shm = (char*) shmat(shmid, NULL, 0)) == (char *) -1) {
216#ifdef DEBUG
217        fprintf(stderr,"shmat failed to update value\n");
218#endif
219      }
220      else{
221        tmpMap=getMapFromMaps(conf,"lenv","status");
222        s1=shm;
223        for(s=tmpMap->value;*s!=NULL && *s!=0;s++){
224          *s1++=*s;
225        }
226        *s1++='|';
227        tmpMap=getMapFromMaps(conf,"lenv","message");
228        if(tmpMap!=NULL)
229          for(s=tmpMap->value;*s!=NULL && *s!=0;s++){
230            *s1++=*s;
231        }
232        *s1=NULL;
233        shmdt((void *)shm);
234      }
235    }
236  }
237}
238
239char* getStatus(int pid){
240  int shmid,i;
241  key_t key;
242  void *shm;
243  char *s;
244  key=pid;
245  if ((shmid = shmget(key, SHMSZ, 0666)) < 0) {
246#ifdef DEBUG
247    fprintf(stderr,"shmget failed in getStatus\n");
248#endif
249  }else{
250    if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
251#ifdef DEBUG
252      fprintf(stderr,"shmat failed in getStatus\n");
253#endif
254    }else{
255      return (char*)shm;
256    }
257  }
258  return "-1";
259}
260
261#endif
262
263#ifdef USE_JS
264
265JSBool
266JSUpdateStatus(JSContext *cx, uintN argc, jsval *argv1)
267{
268  jsval *argv = JS_ARGV(cx,argv1);
269  JS_MaybeGC(cx);
270  char *sid;
271  int istatus=0;
272  char *status=NULL;
273  maps *conf;
274  int i=0;
275  if(argc>2){
276#ifdef JS_DEBUG
277    fprintf(stderr,"Number of arguments used to call the function : %i",argc);
278#endif
279    return JS_FALSE;
280  }
281  conf=mapsFromJSObject(cx,argv[0]);
282  if(JS_ValueToInt32(cx,argv[1],&istatus)==JS_TRUE){
283    char tmpStatus[4];
284    sprintf(tmpStatus,"%i",istatus);
285    tmpStatus[3]=0;
286    status=strdup(tmpStatus);
287  }
288  if(getMapFromMaps(conf,"lenv","status")!=NULL){
289    if(status!=NULL){
290      setMapInMaps(conf,"lenv","status",status);
291      free(status);
292    }
293    else
294      setMapInMaps(conf,"lenv","status","15");
295    updateStatus(conf);
296  }
297  freeMaps(&conf);
298  free(conf);
299  JS_MaybeGC(cx);
300  return JS_TRUE;
301}
302
303#endif
304
305
306
307/* Returns a url-encoded version of str */
308/* IMPORTANT: be sure to free() the returned string after use */
309char *url_encode(char *str) {
310  char *pstr = str, *buf = (char*) malloc(strlen(str) * 3 + 1), *pbuf = buf;
311  while (*pstr) {
312    if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~') 
313      *pbuf++ = *pstr;
314    else if (*pstr == ' ') 
315      *pbuf++ = '+';
316    else 
317      *pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4), *pbuf++ = to_hex(*pstr & 15);
318    pstr++;
319  }
320  *pbuf = '\0';
321  return buf;
322}
323
324/* Returns a url-decoded version of str */
325/* IMPORTANT: be sure to free() the returned string after use */
326char *url_decode(char *str) {
327  char *pstr = str, *buf = (char*) malloc(strlen(str) + 1), *pbuf = buf;
328  while (*pstr) {
329    if (*pstr == '%') {
330      if (pstr[1] && pstr[2]) {
331        *pbuf++ = from_hex(pstr[1]) << 4 | from_hex(pstr[2]);
332        pstr += 2;
333      }
334    } else if (*pstr == '+') { 
335      *pbuf++ = ' ';
336    } else {
337      *pbuf++ = *pstr;
338    }
339    pstr++;
340  }
341  *pbuf = '\0';
342  return buf;
343}
344
345char *zCapitalize1(char *tmp){
346        char *res=strdup(tmp);
347        if(res[0]>=97 && res[0]<=122)
348                res[0]-=32;
349        return res;
350}
351
352char *zCapitalize(char *tmp){
353  int i=0;
354  char *res=strdup(tmp);
355  for(i=0;i<strlen(res);i++)
356    if(res[i]>=97 && res[i]<=122)
357      res[i]-=32;
358  return res;
359}
360
361
362int zooXmlSearchForNs(const char* name){
363  int i;
364  int res=-1;
365  for(i=0;i<nbNs;i++)
366    if(strncasecmp(name,nsName[i],strlen(nsName[i]))==0){
367      res=i;
368      break;
369    }
370  return res;
371}
372
373int zooXmlAddNs(xmlNodePtr nr,const char* url,const char* name){
374#ifdef DEBUG
375  fprintf(stderr,"zooXmlAddNs %d \n",nbNs);
376#endif
377  int currId=-1;
378  int currNode=-1;
379  if(nbNs==0){
380    nbNs++;
381    currId=0;
382    nsName[currId]=strdup(name);
383    usedNs[currId]=xmlNewNs(nr,BAD_CAST url,BAD_CAST name);
384  }else{
385    currId=zooXmlSearchForNs(name);
386    if(currId<0){
387      nbNs++;
388      currId=nbNs-1;
389      nsName[currId]=strdup(name);
390      usedNs[currId]=xmlNewNs(nr,BAD_CAST url,BAD_CAST name);
391    }
392  }
393  return currId;
394}
395
396void zooXmlCleanupNs(){
397  int j;
398#ifdef DEBUG
399  fprintf(stderr,"zooXmlCleanup %d\n",nbNs);
400#endif
401  for(j=nbNs-1;j>=0;j--){
402#ifdef DEBUG
403    fprintf(stderr,"zooXmlCleanup %d\n",j);
404#endif
405    if(j==0)
406      xmlFreeNs(usedNs[j]);
407    free(nsName[j]);
408    nbNs--;
409  }
410  nbNs=0;
411}
412
413xmlNodePtr soapEnvelope(maps* conf,xmlNodePtr n){
414  map* soap=getMapFromMaps(conf,"main","isSoap");
415  if(soap!=NULL && strcasecmp(soap->value,"true")==0){
416    int lNbNs=nbNs;
417    nsName[lNbNs]=strdup("soap");
418    usedNs[lNbNs]=xmlNewNs(NULL,BAD_CAST "http://www.w3.org/2003/05/soap-envelope",BAD_CAST "soap");
419    nbNs++;
420    xmlNodePtr nr = xmlNewNode(usedNs[lNbNs], BAD_CAST "Envelope");
421    nsName[nbNs]=strdup("soap");
422    usedNs[nbNs]=xmlNewNs(nr,BAD_CAST "http://www.w3.org/2003/05/soap-envelope",BAD_CAST "soap");
423    nbNs++;
424    nsName[nbNs]=strdup("xsi");
425    usedNs[nbNs]=xmlNewNs(nr,BAD_CAST "http://www.w3.org/2001/XMLSchema-instance",BAD_CAST "xsi");
426    nbNs++;
427    xmlNsPtr ns_xsi=usedNs[nbNs-1];
428    xmlNewNsProp(nr,ns_xsi,BAD_CAST "schemaLocation",BAD_CAST "http://www.w3.org/2003/05/soap-envelope http://www.w3.org/2003/05/soap-envelope");
429    xmlNodePtr nr1 = xmlNewNode(usedNs[lNbNs], BAD_CAST "Body");
430    xmlAddChild(nr1,n);
431    xmlAddChild(nr,nr1);
432    return nr;
433  }else
434    return n;
435}
436
437xmlNodePtr printGetCapabilitiesHeader(xmlDocPtr doc,const char* service,maps* m){
438
439  xmlNsPtr ns,ns_ows,ns_xlink,ns_xsi;
440  xmlNodePtr n,nc,nc1,nc2,nc3,nc4,nc5,nc6,pseudor;
441  xmlChar *xmlbuff;
442  int buffersize;
443  /**
444   * Create the document and its temporary root.
445   */
446  int wpsId=zooXmlAddNs(NULL,"http://www.opengis.net/wps/1.0.0","wps");
447  ns=usedNs[wpsId];
448  maps* toto1=getMaps(m,"main");
449
450  n = xmlNewNode(ns, BAD_CAST "Capabilities");
451  int owsId=zooXmlAddNs(n,"http://www.opengis.net/ows/1.1","ows");
452  ns_ows=usedNs[owsId];
453  xmlNewNs(n,BAD_CAST "http://www.opengis.net/wps/1.0.0",BAD_CAST "wps");
454  int xsiId=zooXmlAddNs(n,"http://www.w3.org/2001/XMLSchema-instance","xsi");
455  ns_xsi=usedNs[xsiId];
456  int xlinkId=zooXmlAddNs(n,"http://www.w3.org/1999/xlink","xlink");
457  ns_xlink=usedNs[xlinkId];
458  xmlNewNsProp(n,ns_xsi,BAD_CAST "schemaLocation",BAD_CAST "http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsGetCapabilities_response.xsd"); 
459  xmlNewProp(n,BAD_CAST "service",BAD_CAST "WPS");
460  addLangAttr(n,m);
461 
462  if(toto1!=NULL){
463    map* tmp=getMap(toto1->content,"version");
464    if(tmp!=NULL){
465      xmlNewProp(n,BAD_CAST "version",BAD_CAST tmp->value);
466    }
467    else
468      xmlNewProp(n,BAD_CAST "version",BAD_CAST "1.0.0");
469  }
470  else
471    xmlNewProp(n,BAD_CAST "version",BAD_CAST "1.0.0");
472
473  char tmp[256];
474 
475  nc = xmlNewNode(ns_ows, BAD_CAST "ServiceIdentification");
476  maps* tmp4=getMaps(m,"identification");
477  if(tmp4!=NULL){
478    map* tmp2=tmp4->content;
479    char *orderedFields[5];
480    orderedFields[0]="Title";
481    orderedFields[1]="Abstract";
482    orderedFields[2]="Keywords";
483    orderedFields[3]="Fees";
484    orderedFields[4]="AccessConstraints";
485    int oI=0;
486    for(oI=0;oI<5;oI++)
487      if((tmp2=getMap(tmp4->content,orderedFields[oI]))!=NULL){
488        if(strcasecmp(tmp2->name,"abstract")==0 ||
489           strcasecmp(tmp2->name,"title")==0 ||
490           strcasecmp(tmp2->name,"accessConstraints")==0 ||
491           strcasecmp(tmp2->name,"fees")==0){
492          tmp2->name[0]=toupper(tmp2->name[0]);
493          nc1 = xmlNewNode(ns_ows, BAD_CAST tmp2->name);
494          xmlAddChild(nc1,xmlNewText(BAD_CAST tmp2->value));
495          xmlAddChild(nc,nc1);
496        }
497        else
498          if(strcmp(tmp2->name,"keywords")==0){
499            nc1 = xmlNewNode(ns_ows, BAD_CAST "Keywords");
500            char *toto=tmp2->value;
501            char buff[256];
502            int i=0;
503            int j=0;
504            while(toto[i]){
505              if(toto[i]!=',' && toto[i]!=0){
506                buff[j]=toto[i];
507                buff[j+1]=0;
508                j++;
509              }
510              else{
511                nc2 = xmlNewNode(ns_ows, BAD_CAST "Keyword");
512                xmlAddChild(nc2,xmlNewText(BAD_CAST buff));           
513                xmlAddChild(nc1,nc2);
514                j=0;
515              }
516              i++;
517            }
518            if(strlen(buff)>0){
519              nc2 = xmlNewNode(ns_ows, BAD_CAST "Keyword");
520              xmlAddChild(nc2,xmlNewText(BAD_CAST buff));             
521              xmlAddChild(nc1,nc2);
522            }
523            xmlAddChild(nc,nc1);
524            nc2 = xmlNewNode(ns_ows, BAD_CAST "ServiceType");
525            xmlAddChild(nc2,xmlNewText(BAD_CAST "WPS"));
526            xmlAddChild(nc,nc2);
527            nc2 = xmlNewNode(ns_ows, BAD_CAST "ServiceTypeVersion");
528            xmlAddChild(nc2,xmlNewText(BAD_CAST "1.0.0"));
529            xmlAddChild(nc,nc2);         
530          }
531        tmp2=tmp2->next;
532      }
533  }
534  else{
535    fprintf(stderr,"TMP4 NOT FOUND !!");
536    return NULL;
537  }
538  xmlAddChild(n,nc);
539
540  nc = xmlNewNode(ns_ows, BAD_CAST "ServiceProvider");
541  nc3 = xmlNewNode(ns_ows, BAD_CAST "ServiceContact");
542  nc4 = xmlNewNode(ns_ows, BAD_CAST "ContactInfo");
543  nc5 = xmlNewNode(ns_ows, BAD_CAST "Phone");
544  nc6 = xmlNewNode(ns_ows, BAD_CAST "Address");
545  tmp4=getMaps(m,"provider");
546  if(tmp4!=NULL){
547    map* tmp2=tmp4->content;
548    char *tmpAddress[6];
549    tmpAddress[0]="addressDeliveryPoint";
550    tmpAddress[1]="addressCity";
551    tmpAddress[2]="addressAdministrativeArea";
552    tmpAddress[3]="addressPostalCode";
553    tmpAddress[4]="addressCountry";
554    tmpAddress[5]="addressElectronicMailAddress";
555    char *tmpPhone[2];
556    tmpPhone[0]="phoneVoice";
557    tmpPhone[1]="phoneFacsimile";
558    char *orderedFields[12];
559    orderedFields[0]="providerName";
560    orderedFields[1]="providerSite";
561    orderedFields[2]="individualName";
562    orderedFields[3]="positionName";
563    orderedFields[4]=tmpPhone[0];
564    orderedFields[5]=tmpPhone[1];
565    orderedFields[6]=tmpAddress[0];
566    orderedFields[7]=tmpAddress[1];
567    orderedFields[8]=tmpAddress[2];
568    orderedFields[9]=tmpAddress[3];
569    orderedFields[10]=tmpAddress[4];
570    orderedFields[11]=tmpAddress[5];
571    int oI=0;
572    for(oI=0;oI<12;oI++)
573      if((tmp2=getMap(tmp4->content,orderedFields[oI]))!=NULL){
574        if(strcmp(tmp2->name,"keywords")!=0 &&
575           strcmp(tmp2->name,"serverAddress")!=0 &&
576           strcmp(tmp2->name,"lang")!=0){
577          tmp2->name[0]=toupper(tmp2->name[0]);
578          if(strcmp(tmp2->name,"ProviderName")==0){
579            nc1 = xmlNewNode(ns_ows, BAD_CAST tmp2->name);
580            xmlAddChild(nc1,xmlNewText(BAD_CAST tmp2->value));
581            xmlAddChild(nc,nc1);
582          }
583          else{
584            if(strcmp(tmp2->name,"ProviderSite")==0){
585              nc1 = xmlNewNode(ns_ows, BAD_CAST tmp2->name);
586              xmlNewNsProp(nc1,ns_xlink,BAD_CAST "href",BAD_CAST tmp2->value);
587              xmlAddChild(nc,nc1);
588            } 
589            else 
590              if(strcmp(tmp2->name,"IndividualName")==0 || 
591                 strcmp(tmp2->name,"PositionName")==0){
592                nc1 = xmlNewNode(ns_ows, BAD_CAST tmp2->name);
593                xmlAddChild(nc1,xmlNewText(BAD_CAST tmp2->value));
594                xmlAddChild(nc3,nc1);
595              } 
596              else 
597                if(strncmp(tmp2->name,"Phone",5)==0){
598                  int j;
599                  for(j=0;j<2;j++)
600                    if(strcasecmp(tmp2->name,tmpPhone[j])==0){
601                      char *toto=NULL;
602                      char *toto1=tmp2->name;
603                      toto=strstr(toto1,"Phone");
604                      nc1 = xmlNewNode(ns_ows, BAD_CAST toto1+5);
605                      xmlAddChild(nc1,xmlNewText(BAD_CAST tmp2->value));
606                      xmlAddChild(nc5,nc1);
607                    }
608                }
609                else 
610                  if(strncmp(tmp2->name,"Address",7)==0){
611                    int j;
612                    for(j=0;j<6;j++)
613                      if(strcasecmp(tmp2->name,tmpAddress[j])==0){
614                        char *toto=NULL;
615                        char *toto1=tmp2->name;
616                        toto=strstr(toto1,"Address");
617                        nc1 = xmlNewNode(ns_ows, BAD_CAST toto1+7);
618                        xmlAddChild(nc1,xmlNewText(BAD_CAST tmp2->value));
619                        xmlAddChild(nc6,nc1);
620                      }
621                  }
622          }
623        }
624        else
625          if(strcmp(tmp2->name,"keywords")==0){
626            nc1 = xmlNewNode(ns_ows, BAD_CAST "Keywords");
627            char *toto=tmp2->value;
628            char buff[256];
629            int i=0;
630            int j=0;
631            while(toto[i]){
632              if(toto[i]!=',' && toto[i]!=0){
633                buff[j]=toto[i];
634                buff[j+1]=0;
635                j++;
636              }
637              else{
638                nc2 = xmlNewNode(ns_ows, BAD_CAST "Keyword");
639                xmlAddChild(nc2,xmlNewText(BAD_CAST buff));           
640                xmlAddChild(nc1,nc2);
641                j=0;
642              }
643              i++;
644            }
645            if(strlen(buff)>0){
646              nc2 = xmlNewNode(ns_ows, BAD_CAST "Keyword");
647              xmlAddChild(nc2,xmlNewText(BAD_CAST buff));             
648              xmlAddChild(nc1,nc2);
649            }
650            xmlAddChild(nc,nc1);
651          }
652        tmp2=tmp2->next;
653      }
654  }
655  else{
656    fprintf(stderr,"TMP4 NOT FOUND !!");
657  }
658  xmlAddChild(nc4,nc5);
659  xmlAddChild(nc4,nc6);
660  xmlAddChild(nc3,nc4);
661  xmlAddChild(nc,nc3);
662  xmlAddChild(n,nc);
663
664
665  nc = xmlNewNode(ns_ows, BAD_CAST "OperationsMetadata");
666  char *tmp2[3];
667  tmp2[0]=strdup("GetCapabilities");
668  tmp2[1]=strdup("DescribeProcess");
669  tmp2[2]=strdup("Execute");
670  int j=0;
671
672  if(toto1!=NULL){
673    map* tmp=getMap(toto1->content,"serverAddress");
674    if(tmp!=NULL){
675      SERVICE_URL = strdup(tmp->value);
676    }
677    else
678      SERVICE_URL = strdup("not_found");
679  }
680  else
681    SERVICE_URL = strdup("not_found");
682
683  for(j=0;j<3;j++){
684    nc1 = xmlNewNode(ns_ows, BAD_CAST "Operation");
685    xmlNewProp(nc1,BAD_CAST "name",BAD_CAST tmp2[j]);
686    nc2 = xmlNewNode(ns_ows, BAD_CAST "DCP");
687    nc3 = xmlNewNode(ns_ows, BAD_CAST "HTTP");
688    nc4 = xmlNewNode(ns_ows, BAD_CAST "Get");
689    sprintf(tmp,"%s/%s",SERVICE_URL,service);
690    xmlNewNsProp(nc4,ns_xlink,BAD_CAST "href",BAD_CAST tmp);
691    xmlAddChild(nc3,nc4);
692    if(j>0){
693      nc4 = xmlNewNode(ns_ows, BAD_CAST "Post");
694      xmlNewNsProp(nc4,ns_xlink,BAD_CAST "href",BAD_CAST tmp);
695      xmlAddChild(nc3,nc4);
696    }
697    xmlAddChild(nc2,nc3);
698    xmlAddChild(nc1,nc2);   
699    xmlAddChild(nc,nc1);   
700  }
701  for(j=2;j>=0;j--)
702    free(tmp2[j]);
703  xmlAddChild(n,nc);
704
705  nc = xmlNewNode(ns, BAD_CAST "ProcessOfferings");
706  xmlAddChild(n,nc);
707
708  nc1 = xmlNewNode(ns, BAD_CAST "Languages");
709  nc2 = xmlNewNode(ns, BAD_CAST "Default");
710  nc3 = xmlNewNode(ns, BAD_CAST "Supported");
711 
712  toto1=getMaps(m,"main");
713  if(toto1!=NULL){
714    map* tmp1=getMap(toto1->content,"lang");
715    char *toto=tmp1->value;
716    char buff[256];
717    int i=0;
718    int j=0;
719    int dcount=0;
720    while(toto[i]){
721      if(toto[i]!=',' && toto[i]!=0){
722        buff[j]=toto[i];
723        buff[j+1]=0;
724        j++;
725      }
726      else{
727        nc4 = xmlNewNode(ns_ows, BAD_CAST "Language");
728        xmlAddChild(nc4,xmlNewText(BAD_CAST buff));
729        if(dcount==0){
730          xmlAddChild(nc2,nc4);
731          xmlAddChild(nc1,nc2);
732          dcount++;
733        }
734        nc4 = xmlNewNode(ns_ows, BAD_CAST "Language");
735        xmlAddChild(nc4,xmlNewText(BAD_CAST buff));
736        xmlAddChild(nc3,nc4);
737        j=0;
738        buff[j]=0;
739      }
740      i++;
741    }
742    if(strlen(buff)>0){
743      nc4 = xmlNewNode(ns_ows, BAD_CAST "Language");
744      xmlAddChild(nc4,xmlNewText(BAD_CAST buff));             
745      xmlAddChild(nc3,nc4);
746    }
747  }
748  xmlAddChild(nc1,nc3);
749  xmlAddChild(n,nc1);
750 
751  xmlNodePtr fn=soapEnvelope(m,n);
752  xmlDocSetRootElement(doc, fn);
753  //xmlFreeNs(ns);
754  free(SERVICE_URL);
755  return nc;
756}
757
758void printGetCapabilitiesForProcess(maps* m,xmlNodePtr nc,service* serv){
759  xmlNsPtr ns,ns_ows,ns_xlink;
760  xmlNodePtr nr,n,nc1,nc2,nc3,nc4,nc5,nc6,pseudor;
761  /**
762   * Initialize or get existing namspaces
763   */
764  int wpsId=zooXmlAddNs(NULL,"http://www.opengis.net/wps/1.0.0","wps");
765  ns=usedNs[wpsId];
766  int owsId=zooXmlAddNs(NULL,"http://www.opengis.net/ows/1.1","ows");
767  ns_ows=usedNs[owsId];
768  int xlinkId=zooXmlAddNs(n,"http://www.w3.org/1999/xlink","xlink");
769  ns_xlink=usedNs[xlinkId];
770
771  int cursor=0;
772  map* tmp1;
773  if(serv->content!=NULL){
774    nc1 = xmlNewNode(ns, BAD_CAST "Process");
775    tmp1=getMap(serv->content,"processVersion");
776    if(tmp1!=NULL)
777      xmlNewNsProp(nc1,ns,BAD_CAST "processVersion",BAD_CAST tmp1->value);
778    printDescription(nc1,ns_ows,serv->name,serv->content);
779    tmp1=serv->metadata;
780    while(tmp1!=NULL){
781      nc2 = xmlNewNode(ns_ows, BAD_CAST "Metadata");
782      xmlNewNsProp(nc2,ns_xlink,BAD_CAST tmp1->name,BAD_CAST tmp1->value);
783      xmlAddChild(nc1,nc2);
784      tmp1=tmp1->next;
785    }
786    xmlAddChild(nc,nc1);
787  }
788}
789
790xmlNodePtr printDescribeProcessHeader(xmlDocPtr doc,const char* service,maps* m){
791
792  xmlNsPtr ns,ns_ows,ns_xlink,ns_xsi;
793  xmlNodePtr n,nr;
794  xmlChar *xmlbuff;
795  int buffersize;
796
797  int wpsId=zooXmlAddNs(NULL,"http://schemas.opengis.net/wps/1.0.0","wps");
798  ns=usedNs[wpsId];
799  n = xmlNewNode(ns, BAD_CAST "ProcessDescriptions");
800  int owsId=zooXmlAddNs(n,"http://www.opengis.net/ows/1.1","ows");
801  ns_ows=usedNs[owsId];
802  xmlNewNs(n,BAD_CAST "http://www.opengis.net/wps/1.0.0",BAD_CAST "wps");
803  zooXmlAddNs(n,"http://www.w3.org/1999/xlink","xlink");
804  int xsiId=zooXmlAddNs(n,"http://www.w3.org/2001/XMLSchema-instance","xsi");
805  ns_xsi=usedNs[xsiId];
806 
807  xmlNewNsProp(n,ns_xsi,BAD_CAST "schemaLocation",BAD_CAST "http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsDescribeProcess_response.xsd");
808  xmlNewProp(n,BAD_CAST "service",BAD_CAST "WPS");
809  xmlNewProp(n,BAD_CAST "version",BAD_CAST "1.0.0");
810  addLangAttr(n,m);
811
812  xmlNodePtr fn=soapEnvelope(m,n);
813  xmlDocSetRootElement(doc, fn);
814
815  return n;
816}
817
818void printDescribeProcessForProcess(maps* m,xmlNodePtr nc,service* serv,int sc){
819  xmlNsPtr ns,ns_ows,ns_xlink,ns_xsi;
820  xmlNodePtr nr,n,nc1,nc2,nc3,nc4,nc5,nc6,pseudor;
821
822  char tmp[256];
823  n=nc;
824 
825  int wpsId=zooXmlAddNs(NULL,"http://schemas.opengis.net/wps/1.0.0","wps");
826  ns=usedNs[wpsId];
827  int owsId=zooXmlAddNs(NULL,"http://www.opengis.net/ows/1.1","ows");
828  ns_ows=usedNs[owsId];
829  int xlinkId=zooXmlAddNs(NULL,"http://www.w3.org/1999/xlink","xlink");
830  ns_xlink=usedNs[xlinkId];
831
832  nc = xmlNewNode(NULL, BAD_CAST "ProcessDescription");
833  char *tmp4[3];
834  tmp4[0]="processVersion";
835  tmp4[1]="storeSupported";
836  tmp4[2]="statusSupported";
837  int j=0;
838  map* tmp1=NULL;
839  for(j=0;j<3;j++){
840    tmp1=getMap(serv->content,tmp4[j]);
841    if(tmp1!=NULL){
842      if(j==0)
843        xmlNewNsProp(nc,ns,BAD_CAST "processVersion",BAD_CAST tmp1->value);     
844      else
845        xmlNewProp(nc,BAD_CAST tmp4[j],BAD_CAST tmp1->value);     
846    }
847    else{
848      if(j>0)
849        xmlNewProp(nc,BAD_CAST tmp4[j],BAD_CAST "false");     
850    }
851  }
852 
853  printDescription(nc,ns_ows,serv->name,serv->content);
854
855  tmp1=serv->metadata;
856  while(tmp1!=NULL){
857    nc1 = xmlNewNode(ns_ows, BAD_CAST "Metadata");
858    xmlNewNsProp(nc1,ns_xlink,BAD_CAST tmp1->name,BAD_CAST tmp1->value);
859    xmlAddChild(nc,nc1);
860    tmp1=tmp1->next;
861  }
862
863  tmp1=getMap(serv->content,"Profile");
864  if(tmp1!=NULL){
865    nc1 = xmlNewNode(ns, BAD_CAST "Profile");
866    xmlAddChild(nc1,xmlNewText(BAD_CAST tmp1->value));
867    xmlAddChild(nc,nc1);
868  }
869
870  nc1 = xmlNewNode(NULL, BAD_CAST "DataInputs");
871  elements* e=serv->inputs;
872  printFullDescription(e,"Input",ns_ows,nc1);
873  xmlAddChild(nc,nc1);
874
875  nc1 = xmlNewNode(NULL, BAD_CAST "ProcessOutputs");
876  e=serv->outputs;
877  printFullDescription(e,"Output",ns_ows,nc1);
878  xmlAddChild(nc,nc1);
879
880  xmlAddChild(n,nc);
881
882}
883
884void printFullDescription(elements *elem,const char* type,xmlNsPtr ns_ows,xmlNodePtr nc1){
885  char *orderedFields[13];
886  orderedFields[0]="mimeType";
887  orderedFields[1]="encoding";
888  orderedFields[2]="schema";
889  orderedFields[3]="dataType";
890  orderedFields[4]="uom";
891  orderedFields[5]="CRS";
892  orderedFields[6]="value";
893  orderedFields[7]="AllowedValues";
894  orderedFields[8]="range";
895  orderedFields[9]="rangeMin";
896  orderedFields[10]="rangeMax";
897  orderedFields[11]="rangeClosure";
898  orderedFields[12]="rangeSpace";
899
900  xmlNodePtr nc2,nc3,nc4,nc5,nc6,nc7,nc8;
901  elements* e=elem;
902  map* tmp1=NULL;
903  while(e!=NULL){
904    int default1=0;
905    int isAnyValue=1;
906    nc2 = xmlNewNode(NULL, BAD_CAST type);
907    tmp1=getMap(e->content,"minOccurs");
908    if(tmp1){
909      xmlNewProp(nc2,BAD_CAST tmp1->name,BAD_CAST tmp1->value);
910    }
911    tmp1=getMap(e->content,"maxOccurs");
912    if(tmp1){
913      xmlNewProp(nc2,BAD_CAST tmp1->name,BAD_CAST tmp1->value);
914    }
915
916    printDescription(nc2,ns_ows,e->name,e->content);
917
918    if(strncmp(type,"Output",6)==0){
919      if(strncasecmp(e->format,"LITERALDATA",strlen(e->format))==0)
920        nc3 = xmlNewNode(NULL, BAD_CAST "LiteralOutput");
921      else if(strncasecmp(e->format,"COMPLEXDATA",strlen(e->format))==0)
922        nc3 = xmlNewNode(NULL, BAD_CAST "ComplexOutput");
923      else if(strncasecmp(e->format,"BOUNDINGBOXDATA",strlen(e->format))==0)
924        nc3 = xmlNewNode(NULL, BAD_CAST "BoundingBoxOutput");
925      else
926        nc3 = xmlNewNode(NULL, BAD_CAST e->format);
927    }else{
928      if(strncasecmp(e->format,"LITERALDATA",strlen(e->format))==0){
929        nc3 = xmlNewNode(NULL, BAD_CAST "LiteralData");
930      }
931      else if(strncasecmp(e->format,"COMPLEXDATA",strlen(e->format))==0)
932        nc3 = xmlNewNode(NULL, BAD_CAST "ComplexData");
933      else if(strncasecmp(e->format,"BOUNDINGBOXDATA",strlen(e->format))==0)
934        nc3 = xmlNewNode(NULL, BAD_CAST "BoundingBoxData");
935      else
936        nc3 = xmlNewNode(NULL, BAD_CAST e->format);
937    }
938    iotype* _tmp0=NULL;
939    iotype* _tmp=e->defaults;
940    int datatype=0;
941    bool hasDefault=false;
942    bool hasUOM=false;
943    if(_tmp!=NULL){
944      if(strcmp(e->format,"LiteralOutput")==0 ||
945         strcmp(e->format,"LiteralData")==0){
946        datatype=1;
947        nc4 = xmlNewNode(NULL, BAD_CAST "UOMs");
948        nc5 = xmlNewNode(NULL, BAD_CAST "Default");
949      }
950      else if(strcmp(e->format,"BoundingBoxOutput")==0 ||
951              strcmp(e->format,"BoundingBoxData")==0){
952        datatype=2;
953        //nc4 = xmlNewNode(NULL, BAD_CAST "BoundingBoxOutput");
954        nc5 = xmlNewNode(NULL, BAD_CAST "Default");
955      }
956      else{
957        nc4 = xmlNewNode(NULL, BAD_CAST "Default");
958        nc5 = xmlNewNode(NULL, BAD_CAST "Format");
959      }
960     
961      tmp1=_tmp->content;
962      int avcnt=0;
963      int dcnt=0;
964      int oI=0;
965      for(oI=0;oI<13;oI++)
966        if((tmp1=getMap(_tmp->content,orderedFields[oI]))!=NULL){
967          //while(tmp1!=NULL){
968#ifdef DEBUG
969          printf("DATATYPE DEFAULT ? %s\n",tmp1->name);
970#endif
971          if(strncasecmp(tmp1->name,"DataType",8)==0){
972            nc6 = xmlNewNode(ns_ows, BAD_CAST "DataType");
973            xmlAddChild(nc6,xmlNewText(BAD_CAST tmp1->value));
974            char tmp[1024];
975            sprintf(tmp,"http://www.w3.org/TR/xmlschema-2/#%s",tmp1->value);
976            xmlNewNsProp(nc6,ns_ows,BAD_CAST "reference",BAD_CAST tmp);
977            xmlAddChild(nc3,nc6);
978            tmp1=tmp1->next;
979            datatype=1;
980            continue;
981          }
982          if(strcmp(tmp1->name,"asReference")!=0 &&
983             strncasecmp(tmp1->name,"DataType",8)!=0 &&
984             strcasecmp(tmp1->name,"extension")!=0 &&
985             strcasecmp(tmp1->name,"value")!=0 &&
986             strncasecmp(tmp1->name,"AllowedValues",13)!=0&&
987             strncasecmp(tmp1->name,"range",5)!=0){
988            if(datatype!=1){
989              char *tmp2=zCapitalize1(tmp1->name);
990              nc6 = xmlNewNode(NULL, BAD_CAST tmp2);
991              free(tmp2);
992            }
993            else{
994              char *tmp2=zCapitalize(tmp1->name);
995              nc6 = xmlNewNode(ns_ows, BAD_CAST tmp2);
996              free(tmp2);
997            }
998            xmlAddChild(nc6,xmlNewText(BAD_CAST tmp1->value));
999            xmlAddChild(nc5,nc6);
1000            hasUOM=true;
1001          }else 
1002            if(strncmp(type,"Input",5)==0){
1003
1004              if(strcmp(tmp1->name,"value")==0){
1005                nc7 = xmlNewNode(NULL, BAD_CAST "DefaultValue");
1006                xmlAddChild(nc7,xmlNewText(BAD_CAST tmp1->value));
1007                default1=1;
1008                hasDefault=true;
1009              }
1010              if(strncasecmp(tmp1->name,"AllowedValues",13)==0){
1011                nc6 = xmlNewNode(ns_ows, BAD_CAST "AllowedValues");
1012                char *token,*saveptr1;
1013                token=strtok_r(tmp1->value,",",&saveptr1);
1014                while(token!=NULL){
1015                  nc7 = xmlNewNode(ns_ows, BAD_CAST "Value");
1016                  char *tmps=strdup(token);
1017                  tmps[strlen(tmps)]=0;
1018                  xmlAddChild(nc7,xmlNewText(BAD_CAST tmps));
1019                  xmlAddChild(nc6,nc7);
1020                  token=strtok_r(NULL,",",&saveptr1);
1021                }
1022                if(getMap(_tmp->content,"range")!=NULL ||
1023                   getMap(_tmp->content,"rangeMin")!=NULL ||
1024                   getMap(_tmp->content,"rangeMax")!=NULL ||
1025                   getMap(_tmp->content,"rangeClosure")!=NULL )
1026                  goto doRange;
1027                xmlAddChild(nc3,nc6);
1028                isAnyValue=-1;
1029              }
1030              if(strncasecmp(tmp1->name,"range",5)==0){
1031                if(isAnyValue==1){
1032                  nc6 = xmlNewNode(ns_ows, BAD_CAST "AllowedValues");
1033                doRange:
1034                 
1035                  /**
1036                   * Range: Table 46 OGC Web Services Common Standard
1037                   */
1038                  nc8 = xmlNewNode(ns_ows, BAD_CAST "Range");
1039
1040                  map* tmp0=getMap(tmp1,"range");
1041                  if(tmp0!=NULL){
1042                    char* pToken;
1043                    char* orig=zStrdup(tmp0->value);
1044                    /**
1045                     * RangeClosure: Table 47 OGC Web Services Common Standard
1046                     */
1047                    char *tmp="closed";
1048                    if(orig[0]=='[' && orig[strlen(orig)-1]=='[')
1049                      tmp="closed-open";
1050                    else
1051                      if(orig[0]==']' && orig[strlen(orig)-1]==']')
1052                        tmp="open-closed";
1053                      else
1054                        if(orig[0]==']' && orig[strlen(orig)-1]=='[')
1055                          tmp="open";
1056                    xmlNewNsProp(nc8,ns_ows,BAD_CAST "rangeClosure",BAD_CAST tmp);
1057                    pToken=strtok(orig,",");
1058                    int nci0=0;
1059                    while(pToken!=NULL){
1060                      char *tmpStr=(char*) malloc((strlen(pToken))*sizeof(char));
1061                      if(nci0==0){
1062                        nc7 = xmlNewNode(ns_ows, BAD_CAST "MinimumValue");
1063                        int nci=1;
1064                        for(nci=1;nci<strlen(pToken);nci++){
1065                          tmpStr[nci-1]=pToken[nci];
1066                        }
1067                      }else{
1068                        nc7 = xmlNewNode(ns_ows, BAD_CAST "MaximumValue");
1069                        int nci=0;
1070                        for(nci=0;nci<strlen(pToken)-1;nci++){
1071                          tmpStr[nci]=pToken[nci];
1072                        }
1073                      }
1074                      xmlAddChild(nc7,xmlNewText(BAD_CAST tmpStr));
1075                      xmlAddChild(nc8,nc7);
1076                      nci0++;
1077                      pToken = strtok(NULL,",");
1078                    }               
1079                    if(getMap(tmp1,"rangeSpacing")==NULL){
1080                      nc7 = xmlNewNode(ns_ows, BAD_CAST "Spacing");
1081                      xmlAddChild(nc7,xmlNewText(BAD_CAST "1"));
1082                      xmlAddChild(nc8,nc7);
1083                    }
1084                  }else{
1085
1086                  tmp0=getMap(tmp1,"rangeMin");
1087                  if(tmp0!=NULL){
1088                    nc7 = xmlNewNode(ns_ows, BAD_CAST "MinimumValue");
1089                    xmlAddChild(nc7,xmlNewText(BAD_CAST tmp0->value));
1090                    xmlAddChild(nc8,nc7);
1091                  }else{
1092                    nc7 = xmlNewNode(ns_ows, BAD_CAST "MinimumValue");
1093                    xmlAddChild(nc8,nc7);
1094                  }
1095                  tmp0=getMap(tmp1,"rangeMax");
1096                  if(tmp0!=NULL){
1097                    nc7 = xmlNewNode(ns_ows, BAD_CAST "MaximumValue");
1098                    xmlAddChild(nc7,xmlNewText(BAD_CAST tmp0->value));
1099                    xmlAddChild(nc8,nc7);
1100                  }else{
1101                    nc7 = xmlNewNode(ns_ows, BAD_CAST "MaximumValue");
1102                    xmlAddChild(nc8,nc7);
1103                  }
1104                  tmp0=getMap(tmp1,"rangeSpacing");
1105                  if(tmp0!=NULL){
1106                    nc7 = xmlNewNode(ns_ows, BAD_CAST "Spacing");
1107                    xmlAddChild(nc7,xmlNewText(BAD_CAST tmp0->value));
1108                    xmlAddChild(nc8,nc7);
1109                  }
1110                  tmp0=getMap(tmp1,"rangeClosure");
1111                  if(tmp0!=NULL){
1112                    char *tmp="closed";
1113                    if(strcasecmp(tmp0->value,"co")==0)
1114                      tmp="closed-open";
1115                    else
1116                      if(strcasecmp(tmp0->value,"oc")==0)
1117                        tmp="open-closed";
1118                      else
1119                        if(strcasecmp(tmp0->value,"o")==0)
1120                          tmp="open";
1121                    xmlNewNsProp(nc8,ns_ows,BAD_CAST "rangeClosure",BAD_CAST tmp);
1122                  }else
1123                    xmlNewNsProp(nc8,ns_ows,BAD_CAST "rangeClosure",BAD_CAST "closed");
1124                  }
1125                  if(_tmp0==NULL){
1126                    xmlAddChild(nc6,nc8);
1127                    _tmp0=e->supported;
1128                    tmp1=_tmp0->content;
1129                    goto doRange;
1130                  }else{
1131                    _tmp0=_tmp0->next;
1132                    if(_tmp0!=NULL){
1133                      xmlAddChild(nc6,nc8);
1134                      tmp1=_tmp0->content;
1135                      goto doRange;
1136                    }
1137                 
1138                  }
1139                  xmlAddChild(nc6,nc8);
1140                  xmlAddChild(nc3,nc6);
1141                  isAnyValue=-1;
1142                }
1143              }
1144            }
1145          tmp1=tmp1->next;
1146          if(datatype!=2){
1147            if(hasUOM==true){
1148              xmlAddChild(nc4,nc5);
1149              xmlAddChild(nc3,nc4);
1150            }
1151          }else{
1152            xmlAddChild(nc3,nc5);
1153          }
1154          if(strncmp(type,"Input",5)==0){
1155            if(datatype==1 && isAnyValue==1 && default1>0){
1156              xmlAddChild(nc3,nc7);
1157            }
1158          }
1159         
1160        }
1161      if(strncmp(type,"Input",5)==0){
1162        if(datatype==1 && isAnyValue==1 && avcnt==0){
1163          xmlAddChild(nc3,xmlNewNode(ns_ows, BAD_CAST "AnyValue"));
1164          hasDefault=true;
1165          avcnt++;
1166        }
1167      }
1168     
1169      map* metadata=e->metadata;
1170      xmlNodePtr n;
1171      int xlinkId=zooXmlAddNs(n,"http://www.w3.org/1999/xlink","xlink");
1172      xmlNsPtr ns_xlink=usedNs[xlinkId];
1173
1174      while(metadata!=NULL){
1175        nc6=xmlNewNode(ns_ows, BAD_CAST "MetaData");
1176        xmlNewNsProp(nc6,ns_xlink,BAD_CAST metadata->name,BAD_CAST metadata->value);
1177        xmlAddChild(nc2,nc6);
1178        metadata=metadata->next;
1179      }
1180    }
1181
1182    _tmp=e->supported;
1183    if(_tmp==NULL && (getMap(e->defaults->content,"uom")!=NULL || datatype!=1))
1184      _tmp=e->defaults;
1185
1186    int hasSupported=-1;
1187    while(_tmp!=NULL){
1188      if(hasSupported<0){
1189        if(datatype==0){
1190          nc4 = xmlNewNode(NULL, BAD_CAST "Supported");
1191          nc5 = xmlNewNode(NULL, BAD_CAST "Format");
1192        }
1193        else
1194          nc5 = xmlNewNode(NULL, BAD_CAST "Supported");
1195        hasSupported=0;
1196      }else
1197        if(datatype==0)
1198          nc5 = xmlNewNode(NULL, BAD_CAST "Format");
1199      tmp1=_tmp->content;
1200      int oI=0;
1201      for(oI=0;oI<6;oI++)
1202        if((tmp1=getMap(_tmp->content,orderedFields[oI]))!=NULL){
1203#ifdef DEBUG
1204          printf("DATATYPE SUPPORTED ? %s\n",tmp1->name);
1205#endif
1206          if(strcmp(tmp1->name,"asReference")!=0 && 
1207             strcmp(tmp1->name,"DataType")!=0 &&
1208             strcasecmp(tmp1->name,"extension")!=0){
1209            if(datatype!=1){
1210              char *tmp2=zCapitalize1(tmp1->name);
1211              nc6 = xmlNewNode(NULL, BAD_CAST tmp2);
1212              free(tmp2);
1213            }
1214            else{
1215              char *tmp2=zCapitalize(tmp1->name);
1216              nc6 = xmlNewNode(ns_ows, BAD_CAST tmp2);
1217              free(tmp2);
1218            }
1219            if(datatype==2){
1220              char *tmpv,*tmps;
1221              tmps=strtok_r(tmp1->value,",",&tmpv);
1222              while(tmps){
1223                xmlAddChild(nc6,xmlNewText(BAD_CAST tmps));
1224                xmlAddChild(nc5,nc6);
1225                tmps=strtok_r(NULL,",",&tmpv);
1226                if(tmps){
1227                  char *tmp2=zCapitalize1(tmp1->name);
1228                  nc6 = xmlNewNode(NULL, BAD_CAST tmp2);
1229                  free(tmp2);
1230                }
1231              }
1232            }
1233            else{
1234              xmlAddChild(nc6,xmlNewText(BAD_CAST tmp1->value));
1235              xmlAddChild(nc5,nc6);
1236            }
1237          }
1238          tmp1=tmp1->next;
1239        }
1240      if(hasSupported<=0){
1241        if(datatype!=2){
1242          xmlAddChild(nc4,nc5);
1243          xmlAddChild(nc3,nc4);
1244        }else
1245          xmlAddChild(nc3,nc5);
1246        hasSupported=1;
1247      }
1248      else
1249        if(datatype!=2){
1250          xmlAddChild(nc4,nc5);
1251        }
1252        else
1253          xmlAddChild(nc3,nc5);
1254      _tmp=_tmp->next;
1255    }
1256    xmlAddChild(nc2,nc3);
1257   
1258    if(datatype!=2 && hasUOM==true){
1259      xmlAddChild(nc3,nc4);
1260      xmlAddChild(nc2,nc3);
1261    }/*else if(datatype!=2){
1262      if(hasDefault!=true && strncmp(type,"Input",5)==0 && isAnyValue==1)
1263        xmlAddChild(nc3,xmlNewNode(ns_ows, BAD_CAST "AnyValue"));
1264        }*/
1265   
1266    xmlAddChild(nc1,nc2);
1267   
1268    e=e->next;
1269  }
1270}
1271
1272void printProcessResponse(maps* m,map* request, int pid,service* serv,const char* service,int status,maps* inputs,maps* outputs){
1273  xmlNsPtr ns,ns1,ns_ows,ns_xlink,ns_xsi;
1274  xmlNodePtr nr,n,nc,nc1,nc2,nc3,pseudor;
1275  xmlDocPtr doc;
1276  xmlChar *xmlbuff;
1277  int buffersize;
1278  time_t time1; 
1279  time(&time1);
1280  nr=NULL;
1281  /**
1282   * Create the document and its temporary root.
1283   */
1284  doc = xmlNewDoc(BAD_CAST "1.0");
1285  int wpsId=zooXmlAddNs(NULL,"http://www.opengis.net/wps/1.0.0","wps");
1286  ns=usedNs[wpsId];
1287
1288  n = xmlNewNode(ns, BAD_CAST "ExecuteResponse");
1289  xmlNewNs(n,BAD_CAST "http://www.opengis.net/wps/1.0.0",BAD_CAST "wps");
1290  int owsId=zooXmlAddNs(n,"http://www.opengis.net/ows/1.1","ows");
1291  ns_ows=usedNs[owsId];
1292  int xlinkId=zooXmlAddNs(n,"http://www.w3.org/1999/xlink","xlink");
1293  ns_xlink=usedNs[xlinkId];
1294  int xsiId=zooXmlAddNs(n,"http://www.w3.org/2001/XMLSchema-instance","xsi");
1295  ns_xsi=usedNs[xsiId];
1296 
1297  xmlNewNsProp(n,ns_xsi,BAD_CAST "schemaLocation",BAD_CAST "http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsExecute_response.xsd");
1298 
1299  xmlNewProp(n,BAD_CAST "service",BAD_CAST "WPS");
1300  xmlNewProp(n,BAD_CAST "version",BAD_CAST "1.0.0");
1301  addLangAttr(n,m);
1302
1303  char tmp[256];
1304  char url[1024];
1305  char stored_path[1024];
1306  memset(tmp,0,256);
1307  memset(url,0,1024);
1308  memset(stored_path,0,1024);
1309  maps* tmp_maps=getMaps(m,"main");
1310  if(tmp_maps!=NULL){
1311    map* tmpm1=getMap(tmp_maps->content,"serverAddress");
1312    /**
1313     * Check if the ZOO Service GetStatus is available in the local directory.
1314     * If yes, then it uses a reference to an URL which the client can access
1315     * to get information on the status of a running Service (using the
1316     * percentCompleted attribute).
1317     * Else fallback to the initial method using the xml file to write in ...
1318     */
1319    char ntmp[1024];
1320#ifndef WIN32
1321    getcwd(ntmp,1024);
1322#else
1323    _getcwd(ntmp,1024);
1324#endif
1325    struct stat myFileInfo;
1326    int statRes;
1327    char file_path[1024];
1328    sprintf(file_path,"%s/GetStatus.zcfg",ntmp);
1329    statRes=stat(file_path,&myFileInfo);
1330    if(statRes==0){
1331      char currentSid[128];
1332      map* tmpm=getMap(tmp_maps->content,"rewriteUrl");
1333      map *tmp_lenv=NULL;
1334      tmp_lenv=getMapFromMaps(m,"lenv","sid");
1335      if(tmp_lenv==NULL)
1336        sprintf(currentSid,"%i",pid);
1337      else
1338        sprintf(currentSid,"%s",tmp_lenv->value);
1339      if(tmpm==NULL || strcasecmp(tmpm->value,"false")==0){
1340        sprintf(url,"%s?request=Execute&service=WPS&version=1.0.0&Identifier=GetStatus&DataInputs=sid=%s&RawDataOutput=Result",tmpm1->value,currentSid);
1341      }else{
1342        if(strlen(tmpm->value)>0)
1343          if(strcasecmp(tmpm->value,"true")!=0)
1344            sprintf(url,"%s/%s/GetStatus/%s",tmpm1->value,tmpm->value,currentSid);
1345          else
1346            sprintf(url,"%s/GetStatus/%s",tmpm1->value,currentSid);
1347        else
1348          sprintf(url,"%s/?request=Execute&service=WPS&version=1.0.0&Identifier=GetStatus&DataInputs=sid=%s&RawDataOutput=Result",tmpm1->value,currentSid);
1349      }
1350    }else{
1351      map* tmpm2=getMap(tmp_maps->content,"tmpUrl");
1352      if(tmpm1!=NULL && tmpm2!=NULL){
1353        if( strncasecmp( tmpm2->value, "http://", 7) == 0 ||
1354            strncasecmp( tmpm2->value, "https://", 8 ) == 0 ){
1355          sprintf(url,"%s/%s_%i.xml",tmpm2->value,service,pid);
1356        }else
1357          sprintf(url,"%s/%s/%s_%i.xml",tmpm1->value,tmpm2->value,service,pid);
1358      }
1359    }
1360    if(tmpm1!=NULL)
1361      sprintf(tmp,"%s",tmpm1->value);
1362    tmpm1=getMapFromMaps(m,"main","TmpPath");
1363    sprintf(stored_path,"%s/%s_%i.xml",tmpm1->value,service,pid);
1364  }
1365
1366
1367
1368  xmlNewProp(n,BAD_CAST "serviceInstance",BAD_CAST tmp);
1369  map* test=getMap(request,"storeExecuteResponse");
1370  bool hasStoredExecuteResponse=false;
1371  if(test!=NULL && strcasecmp(test->value,"true")==0){
1372    xmlNewProp(n,BAD_CAST "statusLocation",BAD_CAST url);
1373    hasStoredExecuteResponse=true;
1374  }
1375
1376  nc = xmlNewNode(ns, BAD_CAST "Process");
1377  map* tmp2=getMap(serv->content,"processVersion");
1378  if(tmp2!=NULL)
1379    xmlNewNsProp(nc,ns,BAD_CAST "processVersion",BAD_CAST tmp2->value);
1380 
1381  printDescription(nc,ns_ows,serv->name,serv->content);
1382
1383  xmlAddChild(n,nc);
1384
1385  nc = xmlNewNode(ns, BAD_CAST "Status");
1386  const struct tm *tm;
1387  size_t len;
1388  time_t now;
1389  char *tmp1;
1390  map *tmpStatus;
1391 
1392  now = time ( NULL );
1393  tm = localtime ( &now );
1394
1395  tmp1 = (char*)malloc((TIME_SIZE+1)*sizeof(char));
1396
1397  len = strftime ( tmp1, TIME_SIZE, "%Y-%m-%dT%I:%M:%SZ", tm );
1398
1399  xmlNewProp(nc,BAD_CAST "creationTime",BAD_CAST tmp1);
1400
1401  char sMsg[2048];
1402  switch(status){
1403  case SERVICE_SUCCEEDED:
1404    nc1 = xmlNewNode(ns, BAD_CAST "ProcessSucceeded");
1405    sprintf(sMsg,_("Service \"%s\" run successfully."),serv->name);
1406    nc3=xmlNewText(BAD_CAST sMsg);
1407    xmlAddChild(nc1,nc3);
1408    break;
1409  case SERVICE_STARTED:
1410    nc1 = xmlNewNode(ns, BAD_CAST "ProcessStarted");
1411    tmpStatus=getMapFromMaps(m,"lenv","status");
1412    xmlNewProp(nc1,BAD_CAST "percentCompleted",BAD_CAST tmpStatus->value);
1413    sprintf(sMsg,_("ZOO Service \"%s\" is currently running. Please, reload this document to get the up-to-date status of the Service."),serv->name);
1414    nc3=xmlNewText(BAD_CAST sMsg);
1415    xmlAddChild(nc1,nc3);
1416    break;
1417  case SERVICE_ACCEPTED:
1418    nc1 = xmlNewNode(ns, BAD_CAST "ProcessAccepted");
1419    sprintf(sMsg,_("Service \"%s\" was accepted by the ZOO Kernel and it run as a background task. Please consult the statusLocation attribtue providen in this document to get the up-to-date document."),serv->name);
1420    nc3=xmlNewText(BAD_CAST sMsg);
1421    xmlAddChild(nc1,nc3);
1422    break;
1423  case SERVICE_FAILED:
1424    nc1 = xmlNewNode(ns, BAD_CAST "ProcessFailed");
1425    map *errorMap;
1426    map *te;
1427    te=getMapFromMaps(m,"lenv","code");
1428    if(te!=NULL)
1429      errorMap=createMap("code",te->value);
1430    else
1431      errorMap=createMap("code","NoApplicableCode");
1432    te=getMapFromMaps(m,"lenv","message");
1433    if(te!=NULL)
1434      addToMap(errorMap,"text",_ss(te->value));
1435    else
1436      addToMap(errorMap,"text",_("No more information available"));
1437    nc3=createExceptionReportNode(m,errorMap,0);
1438    freeMap(&errorMap);
1439    free(errorMap);
1440    xmlAddChild(nc1,nc3);
1441    break;
1442  default :
1443    printf(_("error code not know : %i\n"),status);
1444    //exit(1);
1445    break;
1446  }
1447  xmlAddChild(nc,nc1);
1448  xmlAddChild(n,nc);
1449  free(tmp1);
1450
1451#ifdef DEBUG
1452  fprintf(stderr,"printProcessResponse 1 161\n");
1453#endif
1454
1455  map* lineage=getMap(request,"lineage");
1456  if(lineage!=NULL && strcasecmp(lineage->value,"true")==0){
1457    nc = xmlNewNode(ns, BAD_CAST "DataInputs");
1458    int i;
1459    maps* mcursor=inputs;
1460    elements* scursor=NULL;
1461    while(mcursor!=NULL /*&& scursor!=NULL*/){
1462      scursor=getElements(serv->inputs,mcursor->name);
1463      printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Input");
1464      mcursor=mcursor->next;
1465    }
1466    xmlAddChild(n,nc);
1467   
1468#ifdef DEBUG
1469    fprintf(stderr,"printProcessResponse 1 177\n");
1470#endif
1471
1472    nc = xmlNewNode(ns, BAD_CAST "OutputDefinitions");
1473    mcursor=outputs;
1474    scursor=NULL;
1475    while(mcursor!=NULL){
1476      scursor=getElements(serv->outputs,mcursor->name);
1477      printOutputDefinitions1(doc,nc,ns,ns_ows,scursor,mcursor,"Output");
1478      mcursor=mcursor->next;
1479    }
1480    xmlAddChild(n,nc);
1481  }
1482#ifdef DEBUG
1483  fprintf(stderr,"printProcessResponse 1 190\n");
1484#endif
1485
1486  /**
1487   * Display the process output only when requested !
1488   */
1489  if(status==SERVICE_SUCCEEDED){
1490    nc = xmlNewNode(ns, BAD_CAST "ProcessOutputs");
1491    maps* mcursor=outputs;
1492    elements* scursor=serv->outputs;
1493    map* testResponse=getMap(request,"RawDataOutput");
1494    if(testResponse==NULL)
1495      testResponse=getMap(request,"ResponseDocument");
1496    while(mcursor!=NULL){
1497      map* tmp0=getMap(mcursor->content,"inRequest");
1498      scursor=getElements(serv->outputs,mcursor->name);
1499      if(scursor!=NULL){
1500        if(testResponse==NULL || tmp0==NULL)
1501          printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Output");
1502        else
1503          if(tmp0!=NULL && strncmp(tmp0->value,"true",4)==0)
1504            printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Output");
1505      }else
1506        /**
1507         * In case there was no definition found in the ZCFG file but
1508         * present in the service code
1509         */
1510        printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Output");
1511      mcursor=mcursor->next;
1512    }
1513    xmlAddChild(n,nc);
1514  }
1515
1516#ifdef DEBUG
1517  fprintf(stderr,"printProcessResponse 1 202\n");
1518#endif
1519  nr=soapEnvelope(m,n);
1520  xmlDocSetRootElement(doc, nr);
1521
1522  if(hasStoredExecuteResponse==true){
1523    /* We need to write the ExecuteResponse Document somewhere */
1524    FILE* output=fopen(stored_path,"w");
1525    if(output==NULL){
1526      /* If the file cannot be created return an ExceptionReport */
1527      char tmpMsg[1024];
1528      sprintf(tmpMsg,_("Unable to create the file : \"%s\" for storing the ExecuteResponse."),stored_path);
1529      map * errormap = createMap("text",tmpMsg);
1530      addToMap(errormap,"code", "InternalError");
1531      printExceptionReportResponse(m,errormap);
1532      freeMap(&errormap);
1533      free(errormap);
1534      xmlCleanupParser();
1535      zooXmlCleanupNs();
1536      return;
1537    }
1538    xmlChar *xmlbuff;
1539    int buffersize;
1540    xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, "UTF-8", 1);
1541    fwrite(xmlbuff,1,xmlStrlen(xmlbuff)*sizeof(char),output);
1542    xmlFree(xmlbuff);
1543    fclose(output);
1544  }
1545  printDocument(m,doc,pid);
1546
1547  xmlCleanupParser();
1548  zooXmlCleanupNs();
1549}
1550
1551
1552void printDocument(maps* m, xmlDocPtr doc,int pid){
1553  char *encoding=getEncoding(m);
1554  if(pid==getpid()){
1555    printHeaders(m);
1556    printf("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding);
1557  }
1558  fflush(stdout);
1559  xmlChar *xmlbuff;
1560  int buffersize;
1561  /*
1562   * Dump the document to a buffer and print it on stdout
1563   * for demonstration purposes.
1564   */
1565  xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);
1566  printf("%s",xmlbuff);
1567  fflush(stdout);
1568  /*
1569   * Free associated memory.
1570   */
1571  xmlFree(xmlbuff);
1572  xmlFreeDoc(doc);
1573  xmlCleanupParser();
1574  zooXmlCleanupNs();
1575}
1576
1577void printOutputDefinitions1(xmlDocPtr doc,xmlNodePtr nc,xmlNsPtr ns_wps,xmlNsPtr ns_ows,elements* e,maps* m,const char* type){
1578  xmlNodePtr nc1;
1579  nc1=xmlNewNode(ns_wps, BAD_CAST type);
1580  map *tmp=NULL; 
1581  if(e!=NULL && e->defaults!=NULL)
1582    tmp=e->defaults->content;
1583  else{
1584    /*
1585    dumpElements(e);
1586    */
1587    return;
1588  }
1589  while(tmp!=NULL){
1590    if(strncasecmp(tmp->name,"MIMETYPE",strlen(tmp->name))==0
1591       || strncasecmp(tmp->name,"ENCODING",strlen(tmp->name))==0
1592       || strncasecmp(tmp->name,"SCHEMA",strlen(tmp->name))==0
1593       || strncasecmp(tmp->name,"UOM",strlen(tmp->name))==0)
1594    xmlNewProp(nc1,BAD_CAST tmp->name,BAD_CAST tmp->value);
1595    tmp=tmp->next;
1596  }
1597  tmp=getMap(e->defaults->content,"asReference");
1598  if(tmp==NULL)
1599    xmlNewProp(nc1,BAD_CAST "asReference",BAD_CAST "false");
1600
1601  tmp=e->content;
1602
1603  printDescription(nc1,ns_ows,m->name,e->content);
1604
1605  xmlAddChild(nc,nc1);
1606
1607}
1608
1609void printOutputDefinitions(xmlDocPtr doc,xmlNodePtr nc,xmlNsPtr ns_wps,xmlNsPtr ns_ows,elements* e,map* m,const char* type){
1610  xmlNodePtr nc1,nc2,nc3;
1611  nc1=xmlNewNode(ns_wps, BAD_CAST type);
1612  map *tmp=NULL; 
1613  if(e!=NULL && e->defaults!=NULL)
1614    tmp=e->defaults->content;
1615  else{
1616    /*
1617    dumpElements(e);
1618    */
1619    return;
1620  }
1621  while(tmp!=NULL){
1622    xmlNewProp(nc1,BAD_CAST tmp->name,BAD_CAST tmp->value);
1623    tmp=tmp->next;
1624  }
1625  tmp=getMap(e->defaults->content,"asReference");
1626  if(tmp==NULL)
1627    xmlNewProp(nc1,BAD_CAST "asReference",BAD_CAST "false");
1628
1629  tmp=e->content;
1630
1631  printDescription(nc1,ns_ows,m->name,e->content);
1632
1633  xmlAddChild(nc,nc1);
1634
1635}
1636
1637void printIOType(xmlDocPtr doc,xmlNodePtr nc,xmlNsPtr ns_wps,xmlNsPtr ns_ows,xmlNsPtr ns_xlink,elements* e,maps* m,const char* type){
1638  xmlNodePtr nc1,nc2,nc3;
1639  nc1=xmlNewNode(ns_wps, BAD_CAST type);
1640  map *tmp=NULL;
1641  if(e!=NULL)
1642    tmp=e->content;
1643  else
1644    tmp=m->content;
1645#ifdef DEBUG
1646  dumpMap(tmp);
1647  dumpElements(e);
1648#endif
1649  nc2=xmlNewNode(ns_ows, BAD_CAST "Identifier");
1650  if(e!=NULL)
1651    nc3=xmlNewText(BAD_CAST e->name);
1652  else
1653    nc3=xmlNewText(BAD_CAST m->name);
1654  xmlAddChild(nc2,nc3);
1655  xmlAddChild(nc1,nc2);
1656  xmlAddChild(nc,nc1);
1657  // Extract Title required to be first element in the ZCFG file !
1658  bool isTitle=TRUE;
1659  if(e!=NULL)
1660    tmp=getMap(e->content,"Title");
1661  else
1662    tmp=getMap(m->content,"Title");
1663 
1664  if(tmp!=NULL){
1665    nc2=xmlNewNode(ns_ows, BAD_CAST tmp->name);
1666    nc3=xmlNewText(BAD_CAST _ss(tmp->value));
1667    xmlAddChild(nc2,nc3); 
1668    xmlAddChild(nc1,nc2);
1669  }
1670
1671  if(e!=NULL)
1672    tmp=getMap(e->content,"Abstract");
1673  else
1674    tmp=getMap(m->content,"Abstract");
1675  if(tmp!=NULL){
1676    nc2=xmlNewNode(ns_ows, BAD_CAST tmp->name);
1677    nc3=xmlNewText(BAD_CAST _ss(tmp->value));
1678    xmlAddChild(nc2,nc3); 
1679    xmlAddChild(nc1,nc2);
1680    xmlAddChild(nc,nc1);
1681  }
1682
1683  /**
1684   * IO type Reference or full Data ?
1685   */
1686#ifdef DEBUG
1687  fprintf(stderr,"FORMAT %s %s\n",e->format,e->format);
1688#endif
1689  map *tmpMap=getMap(m->content,"Reference");
1690  if(tmpMap==NULL){
1691    nc2=xmlNewNode(ns_wps, BAD_CAST "Data");
1692    if(e!=NULL){
1693      if(strncasecmp(e->format,"LiteralOutput",strlen(e->format))==0)
1694        nc3=xmlNewNode(ns_wps, BAD_CAST "LiteralData");
1695      else
1696        if(strncasecmp(e->format,"ComplexOutput",strlen(e->format))==0)
1697          nc3=xmlNewNode(ns_wps, BAD_CAST "ComplexData");
1698        else if(strncasecmp(e->format,"BoundingBoxOutput",strlen(e->format))==0)
1699          nc3=xmlNewNode(ns_wps, BAD_CAST "BoundingBoxData");
1700        else
1701          nc3=xmlNewNode(ns_wps, BAD_CAST e->format);
1702    }
1703    else{
1704      map* tmpV=getMapFromMaps(m,"format","value");
1705      if(tmpV!=NULL)
1706        nc3=xmlNewNode(ns_wps, BAD_CAST tmpV->value);
1707      else
1708        nc3=xmlNewNode(ns_wps, BAD_CAST "LitteralData");
1709    } 
1710    tmp=m->content;
1711#ifdef USE_MS
1712    map* testMap=getMap(tmp,"requestedMimeType");
1713#endif
1714    while(tmp!=NULL){
1715      if(strcasecmp(tmp->name,"mimeType")==0 ||
1716         strcasecmp(tmp->name,"encoding")==0 ||
1717         strcasecmp(tmp->name,"schema")==0 ||
1718         strcasecmp(tmp->name,"datatype")==0 ||
1719         strcasecmp(tmp->name,"uom")==0)
1720#ifdef USE_MS
1721        if(testMap==NULL || (testMap!=NULL && strncasecmp(testMap->value,"text/xml",8)==0)){
1722#endif
1723        xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST tmp->value);
1724#ifdef USE_MS
1725        }
1726      else
1727        if(strcasecmp(tmp->name,"mimeType")==0)
1728          if(testMap!=NULL)
1729            xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST testMap->value);
1730          else 
1731            xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST tmp->value);
1732#endif
1733      tmp=tmp->next;
1734      xmlAddChild(nc2,nc3);
1735    }
1736    if(e!=NULL && e->format!=NULL && strcasecmp(e->format,"BoundingBoxData")==0){
1737      map* bb=getMap(m->content,"value");
1738      if(bb!=NULL){
1739        map* tmpRes=parseBoundingBox(bb->value);
1740        printBoundingBox(ns_ows,nc3,tmpRes);
1741        freeMap(&tmpRes);
1742        free(tmpRes);
1743      }
1744    }else{
1745      if(e!=NULL)
1746        tmp=getMap(e->defaults->content,"mimeType");
1747      else
1748        tmp=NULL;
1749#ifdef USE_MS
1750      /**
1751       * In case of OGC WebServices output use, as the data was requested
1752       * with asReference=false we have to download the resulting OWS request
1753       * stored in the Reference map value.
1754       */
1755      map* testMap=getMap(m->content,"requestedMimeType");
1756      if(testMap!=NULL){
1757        HINTERNET hInternet;
1758        hInternet=InternetOpen(
1759#ifndef WIN32
1760                               (LPCTSTR)
1761#endif
1762                               "ZooWPSClient\0",
1763                               INTERNET_OPEN_TYPE_PRECONFIG,
1764                               NULL,NULL, 0);
1765        testMap=getMap(m->content,"Reference");
1766        loadRemoteFile(m,m->content,hInternet,testMap->value);
1767        InternetCloseHandle(hInternet);
1768      }
1769#endif
1770      map* tmp1=getMap(m->content,"encoding");
1771      map* tmp2=getMap(m->content,"mimeType");
1772      map* tmp3=getMap(m->content,"value");
1773      int hasValue=1;
1774      if(tmp3==NULL){
1775        tmp3=createMap("value","");
1776        hasValue=-1;
1777      }
1778      if((tmp1!=NULL && strncmp(tmp1->value,"base64",6)==0)
1779         || (tmp2!=NULL && (strncmp(tmp2->value,"image/",6)==0 ||
1780                            (strncmp(tmp2->value,"application/",12)==0) &&
1781                            strncmp(tmp2->value,"application/json",16)!=0&&
1782                            strncmp(tmp2->value,"application/x-javascript",24)!=0&&
1783                            strncmp(tmp2->value,"application/vnd.google-earth.kml",32)!=0)
1784             )) {
1785        map* rs=getMap(m->content,"size");
1786        bool isSized=true;
1787        if(rs==NULL){
1788          char tmp1[1024];
1789          sprintf(tmp1,"%d",strlen(tmp3->value));
1790          rs=createMap("size",tmp1);
1791          isSized=false;
1792        }
1793
1794        xmlAddChild(nc3,xmlNewText(BAD_CAST base64(tmp3->value, atoi(rs->value))));
1795        if(!isSized){
1796          freeMap(&rs);
1797          free(rs);
1798        }
1799      }
1800      else if(tmp2!=NULL){
1801        if(strncmp(tmp2->value,"text/js",7)==0 ||
1802           strncmp(tmp2->value,"application/json",16)==0)
1803          xmlAddChild(nc3,xmlNewCDataBlock(doc,BAD_CAST tmp3->value,strlen(tmp3->value)));
1804        else{
1805          if(strncmp(tmp2->value,"text/xml",8)==0 ||
1806             strncmp(tmp2->value,"application/vnd.google-earth.kml",32)==0){
1807            xmlDocPtr doc =
1808              xmlParseMemory(tmp3->value,strlen(tmp3->value));
1809            xmlNodePtr ir = xmlDocGetRootElement(doc);
1810            xmlAddChild(nc3,ir);
1811          }
1812          else
1813            xmlAddChild(nc3,xmlNewText(BAD_CAST tmp3->value));
1814        }
1815        xmlAddChild(nc2,nc3);
1816      }
1817      else{
1818        xmlAddChild(nc3,xmlNewText(BAD_CAST tmp3->value));
1819      }
1820      if(hasValue<0){
1821        freeMap(&tmp3);
1822        free(tmp3);
1823      }
1824    }
1825  }
1826  else{
1827    tmpMap=getMap(m->content,"Reference");
1828    nc3=nc2=xmlNewNode(ns_wps, BAD_CAST "Reference");
1829    if(strcasecmp(type,"Output")==0)
1830      xmlNewProp(nc3,BAD_CAST "href",BAD_CAST tmpMap->value);
1831    else
1832      xmlNewNsProp(nc3,ns_xlink,BAD_CAST "href",BAD_CAST tmpMap->value);
1833    tmp=m->content;
1834#ifdef USE_MS
1835    map* testMap=getMap(tmp,"requestedMimeType");
1836#endif
1837    while(tmp!=NULL){
1838      if(strcasecmp(tmp->name,"mimeType")==0 ||
1839         strcasecmp(tmp->name,"encoding")==0 ||
1840         strcasecmp(tmp->name,"schema")==0 ||
1841         strcasecmp(tmp->name,"datatype")==0 ||
1842         strcasecmp(tmp->name,"uom")==0)
1843#ifdef USE_MS
1844        if(testMap!=NULL  && strncasecmp(testMap->value,"text/xml",8)!=0){
1845          if(strcasecmp(tmp->name,"mimeType")==0)
1846            xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST testMap->value);
1847        }
1848        else
1849#endif
1850        xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST tmp->value);
1851      tmp=tmp->next;
1852      xmlAddChild(nc2,nc3);
1853    }
1854  }
1855  xmlAddChild(nc1,nc2);
1856  xmlAddChild(nc,nc1);
1857
1858}
1859
1860void printDescription(xmlNodePtr root,xmlNsPtr ns_ows,const char* identifier,map* amap){
1861  xmlNodePtr nc2 = xmlNewNode(ns_ows, BAD_CAST "Identifier");
1862  xmlAddChild(nc2,xmlNewText(BAD_CAST identifier));
1863  xmlAddChild(root,nc2);
1864  map* tmp=amap;
1865  char *tmp2[2];
1866  tmp2[0]="Title";
1867  tmp2[1]="Abstract";
1868  int j=0;
1869  for(j=0;j<2;j++){
1870    map* tmp1=getMap(tmp,tmp2[j]);
1871    if(tmp1!=NULL){
1872      nc2 = xmlNewNode(ns_ows, BAD_CAST tmp2[j]);
1873      xmlAddChild(nc2,xmlNewText(BAD_CAST _ss(tmp1->value)));
1874      xmlAddChild(root,nc2);
1875    }
1876  }
1877}
1878
1879char* getEncoding(maps* m){
1880  if(m!=NULL){
1881    map* tmp=getMap(m->content,"encoding");
1882    if(tmp!=NULL){
1883      return tmp->value;
1884    }
1885    else
1886      return "UTF-8";
1887  }
1888  else
1889    return "UTF-8"; 
1890}
1891
1892char* getVersion(maps* m){
1893  if(m!=NULL){
1894    map* tmp=getMap(m->content,"version");
1895    if(tmp!=NULL){
1896      return tmp->value;
1897    }
1898    else
1899      return "1.0.0";
1900  }
1901  else
1902    return "1.0.0";
1903}
1904
1905void printExceptionReportResponse(maps* m,map* s){
1906  int buffersize;
1907  xmlDocPtr doc;
1908  xmlChar *xmlbuff;
1909  xmlNodePtr n;
1910
1911  doc = xmlNewDoc(BAD_CAST "1.0");
1912  maps* tmpMap=getMaps(m,"main");
1913  char *encoding=getEncoding(tmpMap);
1914  char *exceptionCode;
1915 
1916  map* tmp=getMap(s,"code");
1917  if(tmp!=NULL){
1918    if(strcmp(tmp->value,"OperationNotSupported")==0)
1919      exceptionCode="501 Not Implemented";
1920    else
1921      if(strcmp(tmp->value,"MissingParameterValue")==0 ||
1922         strcmp(tmp->value,"InvalidUpdateSequence")==0 ||
1923         strcmp(tmp->value,"OptionNotSupported")==0 ||
1924         strcmp(tmp->value,"VersionNegotiationFailed")==0 ||
1925         strcmp(tmp->value,"InvalidParameterValue")==0)
1926        exceptionCode="400 Bad request";
1927      else
1928        if(strcmp(tmp->value,"NoApplicableCode")==0)
1929          exceptionCode="501 Internal Server Error";
1930        else
1931          exceptionCode="501 Internal Server Error";
1932  }
1933  else
1934    exceptionCode="501 Internal Server Error";
1935
1936  if(m!=NULL){
1937    map *tmpSid=getMapFromMaps(m,"lenv","sid");
1938    if(tmpSid!=NULL){
1939      if( getpid()==atoi(tmpSid->value) ){
1940        printHeaders(m);
1941        printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode);
1942      }
1943    }
1944    else{
1945      printHeaders(m);
1946      printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode);
1947    }
1948  }else{
1949    printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode);
1950  }
1951  n=createExceptionReportNode(m,s,1);
1952  xmlDocSetRootElement(doc, n);
1953  xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);
1954  printf("%s",xmlbuff);
1955  fflush(stdout);
1956  xmlFreeDoc(doc);
1957  xmlFree(xmlbuff);
1958  xmlCleanupParser();
1959  zooXmlCleanupNs();
1960}
1961
1962xmlNodePtr createExceptionReportNode(maps* m,map* s,int use_ns){
1963 
1964  int buffersize;
1965  xmlChar *xmlbuff;
1966  xmlNsPtr ns,ns_ows,ns_xlink,ns_xsi;
1967  xmlNodePtr n,nc,nc1,nc2;
1968
1969  maps* tmpMap=getMaps(m,"main");
1970
1971  int nsid=zooXmlAddNs(NULL,"http://www.opengis.net/ows/1.1","ows");
1972  ns=usedNs[nsid];
1973  n = xmlNewNode(ns, BAD_CAST "ExceptionReport");
1974
1975  if(use_ns==1){
1976    ns_ows=xmlNewNs(n,BAD_CAST "http://www.opengis.net/ows/1.1",BAD_CAST "ows");
1977    int xsiId=zooXmlAddNs(n,"http://www.w3.org/2001/XMLSchema-instance","xsi");
1978    ns_xsi=usedNs[xsiId];
1979    int xlinkId=zooXmlAddNs(n,"http://www.w3.org/1999/xlink","xlink");
1980    ns_xlink=usedNs[xlinkId];
1981    xmlNewNsProp(n,ns_xsi,BAD_CAST "schemaLocation",BAD_CAST "http://www.opengis.net/ows/1.1 http://schemas.opengis.net/ows/1.1.0/owsExceptionReport.xsd");
1982  }
1983  addLangAttr(n,m);
1984  xmlNewProp(n,BAD_CAST "version",BAD_CAST "1.1.0");
1985 
1986  nc = xmlNewNode(ns, BAD_CAST "Exception");
1987
1988  map* tmp=getMap(s,"code");
1989  if(tmp!=NULL)
1990    xmlNewProp(nc,BAD_CAST "exceptionCode",BAD_CAST tmp->value);
1991  else
1992    xmlNewProp(nc,BAD_CAST "exceptionCode",BAD_CAST "NoApplicableCode");
1993
1994  tmp=getMap(s,"locator");
1995  if(tmp!=NULL && strcasecmp(tmp->value,"NULL")!=0)
1996    xmlNewProp(nc,BAD_CAST "locator",BAD_CAST tmp->value);
1997
1998
1999  tmp=getMap(s,"text");
2000  nc1 = xmlNewNode(ns, BAD_CAST "ExceptionText");
2001  nc2=NULL;
2002  if(tmp!=NULL){
2003    xmlNodeSetContent(nc1, BAD_CAST tmp->value);
2004  }
2005  else{
2006    xmlNodeSetContent(nc1, BAD_CAST _("No debug message available"));
2007  }
2008  xmlAddChild(nc,nc1);
2009  xmlAddChild(n,nc);
2010  return n;
2011}
2012
2013
2014void outputResponse(service* s,maps* request_inputs,maps* request_outputs,
2015                    map* request_inputs1,int cpid,maps* m,int res){
2016#ifdef DEBUG
2017  dumpMaps(request_inputs);
2018  dumpMaps(request_outputs);
2019  fprintf(stderr,"printProcessResponse\n");
2020#endif
2021  map* toto=getMap(request_inputs1,"RawDataOutput");
2022  int asRaw=0;
2023  if(toto!=NULL)
2024    asRaw=1;
2025 
2026  maps* tmpSess=getMaps(m,"senv");
2027  if(tmpSess!=NULL){
2028    map *_tmp=getMapFromMaps(m,"lenv","cookie");
2029    char* sessId;
2030    if(_tmp!=NULL){
2031      printf("Set-Cookie: %s; HttpOnly\r\n",_tmp->value);
2032      printf("P3P: CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"\r\n");
2033      char session_file_path[100];
2034      char *tmp1=strtok(_tmp->value,";");
2035      if(tmp1!=NULL)
2036        sprintf(session_file_path,"%s",strstr(tmp1,"=")+1);
2037      else
2038        sprintf(session_file_path,"%s",strstr(_tmp->value,"=")+1);
2039      sessId=strdup(session_file_path);
2040    }else{
2041      maps* t=getMaps(m,"senv");
2042      map*p=t->content;
2043      while(p!=NULL){
2044        if(strstr(p->name,"ID")!=NULL){
2045          sessId=strdup(p->value);
2046          break;
2047        }
2048        p=p->next;
2049      }
2050    }
2051    char session_file_path[1024];
2052    map *tmpPath=getMapFromMaps(m,"main","sessPath");
2053    if(tmpPath==NULL)
2054      tmpPath=getMapFromMaps(m,"main","tmpPath");
2055    sprintf(session_file_path,"%s/sess_%s.cfg",tmpPath->value,sessId);
2056    FILE* teste=fopen(session_file_path,"w");
2057    if(teste==NULL){
2058      char tmpMsg[1024];
2059      sprintf(tmpMsg,_("Unable to create the file : \"%s\" for storing the session maps."),session_file_path);
2060      map * errormap = createMap("text",tmpMsg);
2061      addToMap(errormap,"code", "InternalError");
2062     
2063      printExceptionReportResponse(m,errormap);
2064      freeMap(&errormap);
2065      free(errormap);
2066      return;
2067    }
2068    else{
2069      fclose(teste);
2070      dumpMapsToFile(tmpSess,session_file_path);
2071    }
2072  }
2073 
2074  if(res==SERVICE_FAILED){
2075    map * errormap;
2076    map *lenv;
2077    lenv=getMapFromMaps(m,"lenv","message");
2078    char *tmp0;
2079    if(lenv!=NULL){
2080      tmp0=(char*)malloc((strlen(lenv->value)+strlen(_("Unable to run the Service. The message returned back by the Service was the following: "))+1)*sizeof(char));
2081      sprintf(tmp0,_("Unable to run the Service. The message returned back by the Service was the following: %s"),lenv->value);
2082    }
2083    else{
2084      tmp0=(char*)malloc((strlen(_("Unable to run the Service. No more information was returned back by the Service."))+1)*sizeof(char));
2085      sprintf(tmp0,_("Unable to run the Service. No more information was returned back by the Service."));
2086    }
2087    errormap = createMap("text",tmp0);
2088    free(tmp0);
2089    addToMap(errormap,"code", "InternalError");
2090    printExceptionReportResponse(m,errormap);
2091    freeMap(&errormap);
2092    free(errormap);
2093    return;
2094  }
2095
2096  if(asRaw==0){
2097#ifdef DEBUG
2098    fprintf(stderr,"REQUEST_OUTPUTS FINAL\n");
2099    dumpMaps(request_outputs);
2100#endif
2101    maps* tmpI=request_outputs;
2102    while(tmpI!=NULL){
2103#ifdef USE_MS
2104      map* testMap=getMap(tmpI->content,"useMapserver");       
2105#endif
2106      toto=getMap(tmpI->content,"asReference");
2107#ifdef USE_MS
2108      if(toto!=NULL && strcasecmp(toto->value,"true")==0 && testMap==NULL)
2109#else
2110      if(toto!=NULL && strcasecmp(toto->value,"true")==0)
2111#endif
2112        {
2113        elements* in=getElements(s->outputs,tmpI->name);
2114        char *format=NULL;
2115        if(in!=NULL){
2116          format=strdup(in->format);
2117        }else
2118          format=strdup("LiteralData");
2119        if(strcasecmp(format,"BoundingBoxData")==0){
2120          addToMap(tmpI->content,"extension","xml");
2121          addToMap(tmpI->content,"mimeType","text/xml");
2122          addToMap(tmpI->content,"encoding","UTF-8");
2123          addToMap(tmpI->content,"schema","http://schemas.opengis.net/ows/1.1.0/owsCommon.xsd");
2124        }
2125        map *ext=getMap(tmpI->content,"extension");
2126        map *tmp1=getMapFromMaps(m,"main","tmpPath");
2127        char *file_name,*file_path;
2128        bool hasExt=true;
2129        if(ext==NULL){
2130          // We can fallback to a default list of supported formats using
2131          // mimeType information if present here. Maybe we can add more formats
2132          // here.
2133          // If mimeType was not found, we then set txt as the default extension
2134          map* mtype=getMap(tmpI->content,"mimeType");
2135          if(mtype!=NULL){
2136            if(strcasecmp(mtype->value,"text/xml")==0)
2137              ext=createMap("extension","xml");
2138            else if(strcasecmp(mtype->value,"application/json")==0)
2139              ext=createMap("extension","js");
2140            else if(strncmp(mtype->value,"application/vnd.google-earth.kml",32)==0)
2141              ext=createMap("extension","kml");
2142            else if(strncmp(mtype->value,"image/",6)==0)
2143              ext=createMap("extension",strstr(mtype->value,"/")+1);
2144            else
2145              ext=createMap("extension","txt");
2146          }
2147          else
2148            ext=createMap("extension","txt");
2149          hasExt=false;
2150        }
2151        file_name=(char*)malloc((strlen(s->name)+strlen(ext->value)+strlen(tmpI->name)+1024)*sizeof(char));
2152        int cpid0=cpid+time(NULL);
2153        sprintf(file_name,"%s_%s_%i.%s",s->name,tmpI->name,cpid0,ext->value);
2154        file_path=(char*)malloc((strlen(tmp1->value)+strlen(file_name)+2)*sizeof(char));
2155        sprintf(file_path,"%s/%s",tmp1->value,file_name);
2156        FILE *ofile=fopen(file_path,"wb");
2157        if(ofile==NULL){
2158          char tmpMsg[1024];
2159          sprintf(tmpMsg,_("Unable to create the file : \"%s\" for storing the %s final result."),file_name,tmpI->name);
2160          map * errormap = createMap("text",tmpMsg);
2161          addToMap(errormap,"code", "InternalError");
2162          printExceptionReportResponse(m,errormap);
2163          freeMap(&errormap);
2164          free(errormap);
2165          free(file_name);
2166          free(file_path);
2167          return;
2168        }
2169        free(file_path);
2170        map *tmp2=getMapFromMaps(m,"main","tmpUrl");
2171        map *tmp3=getMapFromMaps(m,"main","serverAddress");
2172        char *file_url;
2173        if(strncasecmp(tmp2->value,"http://",7)==0 ||
2174           strncasecmp(tmp2->value,"https://",8)==0){
2175          file_url=(char*)malloc((strlen(tmp2->value)+strlen(file_name)+2)*sizeof(char));
2176          sprintf(file_url,"%s/%s",tmp2->value,file_name);
2177        }else{
2178          file_url=(char*)malloc((strlen(tmp3->value)+strlen(tmp2->value)+strlen(file_name)+3)*sizeof(char));
2179          sprintf(file_url,"%s/%s/%s",tmp3->value,tmp2->value,file_name);
2180        }
2181        addToMap(tmpI->content,"Reference",file_url);
2182        if(!hasExt){
2183          freeMap(&ext);
2184          free(ext);
2185        }
2186        toto=getMap(tmpI->content,"value");
2187        if(strcasecmp(format,"BoundingBoxData")!=0){
2188          map* size=getMap(tmpI->content,"size");
2189          if(size!=NULL && toto!=NULL)
2190            fwrite(toto->value,1,atoi(size->value)*sizeof(char),ofile);
2191          else
2192            if(toto!=NULL && toto->value!=NULL)
2193              fwrite(toto->value,1,strlen(toto->value)*sizeof(char),ofile);
2194        }else{
2195          printBoundingBoxDocument(m,tmpI,ofile);
2196        }
2197        free(format);
2198        fclose(ofile);
2199        free(file_name);
2200        free(file_url); 
2201      }
2202#ifdef USE_MS
2203      else{
2204        if(testMap!=NULL){
2205          setReferenceUrl(m,tmpI);
2206        }
2207      }
2208#endif
2209      tmpI=tmpI->next;
2210    }
2211    map *r_inputs=getMap(s->content,"serviceProvider");
2212#ifdef DEBUG
2213    fprintf(stderr,"SERVICE : %s\n",r_inputs->value);
2214    dumpMaps(m);
2215#endif
2216    printProcessResponse(m,request_inputs1,cpid,
2217                         s,r_inputs->value,res,
2218                         request_inputs,
2219                         request_outputs);
2220    }
2221    else{
2222      /**
2223       * We get the requested output or fallback to the first one if the
2224       * requested one is not present in the resulting outputs maps.
2225       */
2226      maps* tmpI=NULL;
2227      map* tmpIV=getMap(request_inputs1,"RawDataOutput");
2228      if(tmpIV!=NULL){
2229        tmpI=getMaps(request_outputs,tmpIV->value);
2230      }
2231      if(tmpI==NULL)
2232        tmpI=request_outputs;
2233      elements* e=getElements(s->outputs,tmpI->name);
2234      if(e!=NULL && strcasecmp(e->format,"BoundingBoxData")==0){
2235        printBoundingBoxDocument(m,tmpI,NULL);
2236      }else{
2237        toto=getMap(tmpI->content,"value");
2238        if(toto==NULL){
2239          char tmpMsg[1024];
2240          sprintf(tmpMsg,_("Wrong RawDataOutput parameter, unable to fetch any result for the name your provided : \"%s\"."),tmpI->name);
2241          map * errormap = createMap("text",tmpMsg);
2242          addToMap(errormap,"code", "InvalidParameterValue");
2243          printExceptionReportResponse(m,errormap);
2244          freeMap(&errormap);
2245          free(errormap);
2246          return;
2247        }
2248        map* fname=getMapFromMaps(tmpI,tmpI->name,"filename");
2249        if(fname!=NULL)
2250          printf("Content-Disposition: attachment; filename=\"%s\"\r\n",fname->value);
2251        map* rs=getMapFromMaps(tmpI,tmpI->name,"size");
2252        if(rs!=NULL)
2253          printf("Content-Length: %s\r\n",rs->value);
2254        printHeaders(m);
2255        char mime[1024];
2256        map* mi=getMap(tmpI->content,"mimeType");
2257#ifdef DEBUG
2258        fprintf(stderr,"SERVICE OUTPUTS\n");
2259        dumpMaps(request_outputs);
2260        fprintf(stderr,"SERVICE OUTPUTS\n");
2261#endif
2262        map* en=getMap(tmpI->content,"encoding");
2263        if(mi!=NULL && en!=NULL)
2264          sprintf(mime,
2265                  "Content-Type: %s; charset=%s\r\nStatus: 200 OK\r\n\r\n",
2266                  mi->value,en->value);
2267        else
2268          if(mi!=NULL)
2269            sprintf(mime,
2270                    "Content-Type: %s; charset=UTF-8\r\nStatus: 200 OK\r\n\r\n",
2271                    mi->value);
2272          else
2273            sprintf(mime,"Content-Type: text/plain; charset=utf-8\r\nStatus: 200 OK\r\n\r\n");
2274        printf("%s",mime);
2275        if(rs!=NULL)
2276          fwrite(toto->value,1,atoi(rs->value),stdout);
2277        else
2278          fwrite(toto->value,1,strlen(toto->value),stdout);
2279#ifdef DEBUG
2280        dumpMap(toto);
2281#endif
2282      }
2283    }
2284}
2285
2286char *base64(const char *input, int length)
2287{
2288  BIO *bmem, *b64;
2289  BUF_MEM *bptr;
2290
2291  b64 = BIO_new(BIO_f_base64());
2292  BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
2293  bmem = BIO_new(BIO_s_mem());
2294  b64 = BIO_push(b64, bmem);
2295  BIO_write(b64, input, length);
2296  BIO_flush(b64);
2297  BIO_get_mem_ptr(b64, &bptr);
2298
2299  char *buff = (char *)malloc((bptr->length)*sizeof(char));
2300  memcpy(buff, bptr->data, bptr->length-1);
2301  buff[bptr->length-1] = 0;
2302
2303  BIO_free_all(b64);
2304
2305  return buff;
2306}
2307
2308char *base64d(const char *input, int length,int* red)
2309{
2310  BIO *b64, *bmem;
2311
2312  char *buffer = (char *)malloc(length);
2313  if(buffer){
2314    memset(buffer, 0, length);
2315    b64 = BIO_new(BIO_f_base64());
2316    if(b64){
2317      bmem = BIO_new_mem_buf((unsigned char*)input,length);
2318      bmem = BIO_push(b64, bmem);
2319      *red=BIO_read(bmem, buffer, length);
2320      buffer[length-1]=0;
2321      BIO_free_all(bmem);
2322    }
2323  }
2324  return buffer;
2325}
2326
2327void ensureDecodedBase64(maps **in){
2328  maps* cursor=*in;
2329  while(cursor!=NULL){
2330    map *tmp=getMap(cursor->content,"encoding");
2331    if(tmp!=NULL && strncasecmp(tmp->value,"base64",6)==0){
2332      tmp=getMap(cursor->content,"value");
2333      addToMap(cursor->content,"base64_value",tmp->value);
2334      int size=0;
2335      char *s=strdup(tmp->value);
2336      free(tmp->value);
2337      tmp->value=base64d(s,strlen(s),&size);
2338      free(s);
2339      char sizes[1024];
2340      sprintf(sizes,"%d",size);
2341      addToMap(cursor->content,"size",sizes);
2342    }
2343    cursor=cursor->next;
2344  }
2345}
2346
2347char* addDefaultValues(maps** out,elements* in,maps* m,int type){
2348  elements* tmpInputs=in;
2349  maps* out1=*out;
2350  if(type==1){
2351    while(out1!=NULL){
2352      if(getElements(in,out1->name)==NULL)
2353        return out1->name;
2354      out1=out1->next;
2355    }
2356    out1=*out;
2357  }
2358  while(tmpInputs!=NULL){
2359    maps *tmpMaps=getMaps(out1,tmpInputs->name);
2360    if(tmpMaps==NULL){
2361      maps* tmpMaps2=(maps*)malloc(MAPS_SIZE);
2362      tmpMaps2->name=strdup(tmpInputs->name);
2363      tmpMaps2->content=NULL;
2364      tmpMaps2->next=NULL;
2365     
2366      if(type==0){
2367        map* tmpMapMinO=getMap(tmpInputs->content,"minOccurs");
2368        if(tmpMapMinO!=NULL)
2369          if(atoi(tmpMapMinO->value)>=1){
2370            freeMaps(&tmpMaps2);
2371            free(tmpMaps2);
2372            return tmpInputs->name;
2373          }
2374          else{
2375            if(tmpMaps2->content==NULL)
2376              tmpMaps2->content=createMap("minOccurs",tmpMapMinO->value);
2377            else
2378              addToMap(tmpMaps2->content,"minOccurs",tmpMapMinO->value);
2379          }
2380        map* tmpMaxO=getMap(tmpInputs->content,"maxOccurs");
2381        if(tmpMaxO!=NULL)
2382          if(tmpMaps2->content==NULL)
2383            tmpMaps2->content=createMap("maxOccurs",tmpMaxO->value);
2384          else
2385            addToMap(tmpMaps2->content,"maxOccurs",tmpMaxO->value);
2386      }
2387
2388      iotype* tmpIoType=tmpInputs->defaults;
2389      if(tmpIoType!=NULL){
2390        map* tmpm=tmpIoType->content;
2391        while(tmpm!=NULL){
2392          if(tmpMaps2->content==NULL)
2393            tmpMaps2->content=createMap(tmpm->name,tmpm->value);
2394          else
2395            addToMap(tmpMaps2->content,tmpm->name,tmpm->value);
2396          tmpm=tmpm->next;
2397        }
2398      }
2399      addToMap(tmpMaps2->content,"inRequest","false");
2400      if(type==0){
2401        map *tmpMap=getMap(tmpMaps2->content,"value");
2402        if(tmpMap==NULL)
2403          addToMap(tmpMaps2->content,"value","NULL");
2404      }
2405      if(out1==NULL){
2406        *out=dupMaps(&tmpMaps2);
2407        out1=*out;
2408      }
2409      else
2410        addMapsToMaps(&out1,tmpMaps2);
2411      freeMap(&tmpMaps2->content);
2412      free(tmpMaps2->content);
2413      tmpMaps2->content=NULL;
2414      freeMaps(&tmpMaps2);
2415      free(tmpMaps2);
2416      tmpMaps2=NULL;
2417    }
2418    else{
2419      iotype* tmpIoType=getIoTypeFromElement(tmpInputs,tmpInputs->name,
2420                                             tmpMaps->content);
2421      if(type==0) {
2422        /**
2423         * In case of an Input maps, then add the minOccurs and maxOccurs to the
2424         * content map.
2425         */
2426        map* tmpMap1=getMap(tmpInputs->content,"minOccurs");
2427        if(tmpMap1!=NULL){
2428          if(tmpMaps->content==NULL)
2429            tmpMaps->content=createMap("minOccurs",tmpMap1->value);
2430          else
2431            addToMap(tmpMaps->content,"minOccurs",tmpMap1->value);
2432        }
2433        map* tmpMaxO=getMap(tmpInputs->content,"maxOccurs");
2434        if(tmpMaxO!=NULL){
2435          if(tmpMaps->content==NULL)
2436            tmpMaps->content=createMap("maxOccurs",tmpMap1->value);
2437          else
2438            addToMap(tmpMaps->content,"maxOccurs",tmpMap1->value);
2439        }
2440        /**
2441         * Parsing BoundingBoxData, fill the following map and then add it to
2442         * the content map of the Input maps:
2443         * lowerCorner, upperCorner, srs and dimensions
2444         * cf. parseBoundingBox
2445         */
2446        if(strcasecmp(tmpInputs->format,"BoundingBoxData")==0){
2447          maps* tmpI=getMaps(*out,tmpInputs->name);
2448          if(tmpI!=NULL){
2449            map* tmpV=getMap(tmpI->content,"value");
2450            if(tmpV!=NULL){
2451              char *tmpVS=strdup(tmpV->value);
2452              map* tmp=parseBoundingBox(tmpVS);
2453              free(tmpVS);
2454              map* tmpC=tmp;
2455              while(tmpC!=NULL){
2456                addToMap(tmpMaps->content,tmpC->name,tmpC->value);
2457                tmpC=tmpC->next;
2458              }
2459              freeMap(&tmp);
2460              free(tmp);
2461            }
2462          }
2463        }
2464      }
2465
2466      if(tmpIoType!=NULL){
2467        map* tmpContent=tmpIoType->content;
2468        map* cval=NULL;
2469        int hasPassed=-1;
2470        while(tmpContent!=NULL){
2471          if((cval=getMap(tmpMaps->content,tmpContent->name))==NULL){
2472#ifdef DEBUG
2473            fprintf(stderr,"addDefaultValues %s => %s\n",tmpContent->name,tmpContent->value);
2474#endif
2475            if(tmpMaps->content==NULL)
2476              tmpMaps->content=createMap(tmpContent->name,tmpContent->value);
2477            else
2478              addToMap(tmpMaps->content,tmpContent->name,tmpContent->value);
2479           
2480            if(hasPassed<0 && type==0 && getMap(tmpMaps->content,"isArray")!=NULL){
2481              map* length=getMap(tmpMaps->content,"length");
2482              int i;
2483              char *tcn=strdup(tmpContent->name);
2484              for(i=1;i<atoi(length->value);i++){
2485#ifdef DEBUG
2486                dumpMap(tmpMaps->content);
2487                fprintf(stderr,"addDefaultValues %s_%d => %s\n",tcn,i,tmpContent->value);
2488#endif
2489                int len=strlen((char*) tcn);
2490                char *tmp1=(char *)malloc((len+10)*sizeof(char));
2491                sprintf(tmp1,"%s_%d",tcn,i);
2492#ifdef DEBUG
2493                fprintf(stderr,"addDefaultValues %s => %s\n",tmp1,tmpContent->value);
2494#endif
2495                addToMap(tmpMaps->content,tmp1,tmpContent->value);
2496                free(tmp1);
2497                hasPassed=1;
2498              }
2499              free(tcn);
2500            }
2501          }
2502          tmpContent=tmpContent->next;
2503        }
2504#ifdef USE_MS
2505        /**
2506         * check for useMapServer presence
2507         */
2508        map* tmpCheck=getMap(tmpIoType->content,"useMapServer");
2509        if(tmpCheck!=NULL){
2510          // Get the default value
2511          tmpIoType=getIoTypeFromElement(tmpInputs,tmpInputs->name,NULL);
2512          tmpCheck=getMap(tmpMaps->content,"mimeType");
2513          addToMap(tmpMaps->content,"requestedMimeType",tmpCheck->value);
2514          map* cursor=tmpIoType->content;
2515          while(cursor!=NULL){
2516            addToMap(tmpMaps->content,cursor->name,cursor->value);
2517            cursor=cursor->next;
2518          }
2519         
2520          cursor=tmpInputs->content;
2521          while(cursor!=NULL){
2522            if(strcasecmp(cursor->name,"Title")==0 ||
2523               strcasecmp(cursor->name,"Abstract")==0)
2524              addToMap(tmpMaps->content,cursor->name,cursor->value);
2525           cursor=cursor->next;
2526          }
2527        }
2528#endif
2529      }
2530      if(tmpMaps->content==NULL)
2531        tmpMaps->content=createMap("inRequest","true");
2532      else
2533        addToMap(tmpMaps->content,"inRequest","true");
2534
2535    }
2536    tmpInputs=tmpInputs->next;
2537  }
2538  return "";
2539}
2540
2541/**
2542 * parseBoundingBox : parse a BoundingBox string
2543 *
2544 * OGC 06-121r3 : 10.2 Bounding box
2545 *
2546 * value is provided as : lowerCorner,upperCorner,crs,dimension
2547 * exemple : 189000,834000,285000,962000,urn:ogc:def:crs:OGC:1.3:CRS84
2548 *
2549 * Need to create a map to store boundingbox informations :
2550 *  - lowerCorner : double,double (minimum within this bounding box)
2551 *  - upperCorner : double,double (maximum within this bounding box)
2552 *  - crs : URI (Reference to definition of the CRS)
2553 *  - dimensions : int
2554 *
2555 * Note : support only 2D bounding box.
2556 */
2557map* parseBoundingBox(const char* value){
2558  map *res=NULL;
2559  if(value!=NULL){
2560    char *cv,*cvp;
2561    cv=strtok_r((char*) value,",",&cvp);
2562    int cnt=0;
2563    int icnt=0;
2564    char *currentValue=NULL;
2565    while(cv){
2566      if(cnt<2)
2567        if(currentValue!=NULL){
2568          char *finalValue=(char*)malloc((strlen(currentValue)+strlen(cv)+1)*sizeof(char));
2569          sprintf(finalValue,"%s%s",currentValue,cv);
2570          switch(cnt){
2571          case 0:
2572            res=createMap("lowerCorner",finalValue);
2573            break;
2574          case 1:
2575            addToMap(res,"upperCorner",finalValue);
2576            icnt=-1;
2577            break;
2578          }
2579          cnt++;
2580          free(currentValue);
2581          currentValue=NULL;
2582          free(finalValue);
2583        }
2584        else{
2585          currentValue=(char*)malloc((strlen(cv)+2)*sizeof(char));
2586          sprintf(currentValue,"%s ",cv);
2587        }
2588      else
2589        if(cnt==2){
2590          addToMap(res,"crs",cv);
2591          cnt++;
2592        }
2593        else
2594          addToMap(res,"dimensions",cv);
2595      icnt++;
2596      cv=strtok_r(NULL,",",&cvp);
2597    }
2598  }
2599  return res;
2600}
2601
2602/**
2603 * printBoundingBox : fill a BoundingBox node (ows:BoundingBox or
2604 * wps:BoundingBoxData). Set crs and dimensions attributes, add
2605 * Lower/UpperCorner nodes to a pre-existing XML node.
2606 */
2607void printBoundingBox(xmlNsPtr ns_ows,xmlNodePtr n,map* boundingbox){
2608
2609  xmlNodePtr bb,lw,uc;
2610
2611  map* tmp=getMap(boundingbox,"value");
2612
2613  tmp=getMap(boundingbox,"lowerCorner");
2614  if(tmp!=NULL){
2615    lw=xmlNewNode(ns_ows,BAD_CAST "LowerCorner");
2616    xmlAddChild(lw,xmlNewText(BAD_CAST tmp->value));
2617  }
2618
2619  tmp=getMap(boundingbox,"upperCorner");
2620  if(tmp!=NULL){
2621    uc=xmlNewNode(ns_ows,BAD_CAST "UpperCorner");
2622    xmlAddChild(uc,xmlNewText(BAD_CAST tmp->value));
2623  }
2624
2625  tmp=getMap(boundingbox,"crs");
2626  if(tmp!=NULL)
2627    xmlNewProp(n,BAD_CAST "crs",BAD_CAST tmp->value);
2628
2629  tmp=getMap(boundingbox,"dimensions");
2630  if(tmp!=NULL)
2631    xmlNewProp(n,BAD_CAST "dimensions",BAD_CAST tmp->value);
2632
2633  xmlAddChild(n,lw);
2634  xmlAddChild(n,uc);
2635
2636}
2637
2638void printBoundingBoxDocument(maps* m,maps* boundingbox,FILE* file){
2639  if(file==NULL)
2640    rewind(stdout);
2641  xmlNodePtr n;
2642  xmlDocPtr doc;
2643  xmlNsPtr ns_ows,ns_xsi;
2644  xmlChar *xmlbuff;
2645  int buffersize;
2646  char *encoding=getEncoding(m);
2647  map *tmp;
2648  if(file==NULL){
2649    int pid=0;
2650    tmp=getMapFromMaps(m,"lenv","sid");
2651    if(tmp!=NULL)
2652      pid=atoi(tmp->value);
2653    if(pid==getpid()){
2654      printf("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding);
2655    }
2656    fflush(stdout);
2657  }
2658
2659  doc = xmlNewDoc(BAD_CAST "1.0");
2660  int owsId=zooXmlAddNs(NULL,"http://www.opengis.net/ows/1.1","ows");
2661  ns_ows=usedNs[owsId];
2662  n = xmlNewNode(ns_ows, BAD_CAST "BoundingBox");
2663  xmlNewNs(n,BAD_CAST "http://www.opengis.net/ows/1.1",BAD_CAST "ows");
2664  int xsiId=zooXmlAddNs(n,"http://www.w3.org/2001/XMLSchema-instance","xsi");
2665  ns_xsi=usedNs[xsiId];
2666  xmlNewNsProp(n,ns_xsi,BAD_CAST "schemaLocation",BAD_CAST "http://www.opengis.net/ows/1.1 http://schemas.opengis.net/ows/1.1.0/owsCommon.xsd");
2667  map *tmp1=getMap(boundingbox->content,"value");
2668  tmp=parseBoundingBox(tmp1->value);
2669  printBoundingBox(ns_ows,n,tmp);
2670  xmlDocSetRootElement(doc, n);
2671
2672  xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);
2673  if(file==NULL)
2674    printf("%s",xmlbuff);
2675  else{
2676    fprintf(file,"%s",xmlbuff);
2677  }
2678
2679  if(tmp!=NULL){
2680    freeMap(&tmp);
2681    free(tmp);
2682  }
2683  xmlFree(xmlbuff);
2684  xmlFreeDoc(doc);
2685  xmlCleanupParser();
2686  zooXmlCleanupNs();
2687 
2688}
2689
2690
2691char* getMd5(char* url){
2692  EVP_MD_CTX md5ctx;
2693  char* fresult=(char*)malloc((EVP_MAX_MD_SIZE+1)*sizeof(char));
2694  unsigned char result[EVP_MAX_MD_SIZE];
2695  unsigned int len;
2696  EVP_DigestInit(&md5ctx, EVP_md5());
2697  EVP_DigestUpdate(&md5ctx, url, strlen(url));
2698  EVP_DigestFinal_ex(&md5ctx,result,&len);
2699  EVP_MD_CTX_cleanup(&md5ctx);
2700  int i;
2701  for(i = 0; i < len; i++){
2702    if(i>0){
2703      char *tmp=strdup(fresult);
2704      sprintf(fresult,"%s%02x", tmp,result[i]);
2705      free(tmp);
2706    }
2707    else
2708      sprintf(fresult,"%02x",result[i]);
2709  }
2710  return fresult;
2711}
2712
2713/**
2714 * Cache a file for a given request
2715 */
2716void addToCache(maps* conf,char* request,char* content,char* mimeType,int length){
2717  map* tmp=getMapFromMaps(conf,"main","cacheDir");
2718  if(tmp!=NULL){
2719    char* md5str=getMd5(request);
2720    char* fname=(char*)malloc(sizeof(char)*(strlen(tmp->value)+strlen(md5str)+6));
2721    sprintf(fname,"%s/%s.zca",tmp->value,md5str);
2722#ifdef DEBUG
2723    fprintf(stderr,"Cache list : %s\n",fname);
2724    fflush(stderr);
2725#endif
2726    FILE* fo=fopen(fname,"w+");
2727    fwrite(content,sizeof(char),length,fo);
2728    fclose(fo);
2729
2730    sprintf(fname,"%s/%s.zcm",tmp->value,md5str);
2731    fo=fopen(fname,"w+");
2732#ifdef DEBUG
2733    fprintf(stderr,"MIMETYPE: %s\n",mimeType);
2734#endif
2735    fwrite(mimeType,sizeof(char),strlen(mimeType),fo);
2736    fclose(fo);
2737
2738    free(md5str);
2739    free(fname);
2740  }
2741}
2742
2743char* isInCache(maps* conf,char* request){
2744  map* tmpM=getMapFromMaps(conf,"main","cacheDir");
2745  if(tmpM!=NULL){
2746    char* md5str=getMd5(request);
2747#ifdef DEBUG
2748    fprintf(stderr,"MD5STR : (%s)\n\n",md5str);
2749#endif
2750    char* fname=(char*)malloc(sizeof(char)*(strlen(tmpM->value)+strlen(md5str)+6));
2751    sprintf(fname,"%s/%s.zca",tmpM->value,md5str);
2752    struct stat f_status;
2753    int s=stat(fname, &f_status);
2754    if(s==0 && f_status.st_size>0){
2755      free(md5str);
2756      return fname;
2757    }
2758    free(md5str);
2759    free(fname);
2760  }
2761  return NULL;
2762}
2763
2764/**
2765 * loadRemoteFile:
2766 * Try to load file from cache or download a remote file if not in cache
2767 */
2768int loadRemoteFile(maps* m,map* content,HINTERNET hInternet,char *url){
2769  HINTERNET res;
2770  char* fcontent;
2771  char* cached=isInCache(m,url);
2772  char *mimeType=NULL;
2773  int fsize;
2774  int hasF=-1;
2775  if(cached!=NULL){
2776    struct stat f_status;
2777    int s=stat(cached, &f_status);
2778    if(s==0){
2779      fcontent=(char*)malloc(sizeof(char)*(f_status.st_size+1));
2780      FILE* f=fopen(cached,"rb");
2781      int len=fread(fcontent,f_status.st_size,1,f);
2782      fsize=f_status.st_size;
2783      fcontent[fsize]=0;
2784      fclose(f);
2785    }
2786    cached[strlen(cached)-1]='m';
2787    s=stat(cached, &f_status);
2788    if(s==0){
2789      mimeType=(char*)malloc(sizeof(char)*(f_status.st_size+1));
2790      FILE* f=fopen(cached,"rb");
2791      int len=fread(mimeType,f_status.st_size,1,f);
2792      mimeType[f_status.st_size]=0;
2793      fclose(f);
2794    }
2795  }else{
2796    res=InternetOpenUrl(hInternet,url,NULL,0,INTERNET_FLAG_NO_CACHE_WRITE,0);
2797    fcontent=(char*)malloc((res.nDataLen+1)*sizeof(char));
2798    if(fcontent == NULL){
2799      return errorException(m, _("Unable to allocate memory."), "InternalError",NULL);
2800    }
2801    size_t dwRead;
2802    InternetReadFile(res, (LPVOID)fcontent, res.nDataLen, &dwRead);
2803    fcontent[res.nDataLen]=0;
2804    fsize=res.nDataLen;
2805    mimeType=(char*)res.mimeType;
2806  }
2807  if(fsize==0){
2808    return errorException(m, _("Unable to download the file."), "InternalError",NULL);
2809  }
2810
2811  if(mimeType!=NULL){
2812    addToMap(content,"fmimeType",mimeType);
2813  }
2814
2815  map* tmpMap=getMapOrFill(content,"value","");
2816   
2817  free(tmpMap->value);
2818  tmpMap->value=(char*)malloc((fsize+1)*sizeof(char));
2819  if(tmpMap->value==NULL)
2820    fprintf(stderr,"Unable to allocate memory!\n");
2821  //snprintf(tmpMap->value,(fsize+1)*sizeof(char),fcontent);
2822  memcpy(tmpMap->value,fcontent,(fsize+1)*sizeof(char));
2823 
2824  char ltmp1[256];
2825  sprintf(ltmp1,"%d",fsize);
2826  addToMap(content,"size",ltmp1);
2827  if(cached==NULL)
2828    addToCache(m,url,fcontent,mimeType,fsize);
2829  else{
2830    free(fcontent);
2831    free(mimeType);
2832    free(cached);
2833  }
2834  return 0;
2835}
2836
2837int errorException(maps *m, const char *message, const char *errorcode, const char *locator) 
2838{
2839  map* errormap = createMap("text", message);
2840  addToMap(errormap,"code", errorcode);
2841  if(locator!=NULL)
2842    addToMap(errormap,"locator", locator);
2843  else
2844    addToMap(errormap,"locator", "NULL");
2845  printExceptionReportResponse(m,errormap);
2846  freeMap(&errormap);
2847  free(errormap);
2848  return -1;
2849}
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