source: branches/PublicaMundi_David_integration_01-devel/zoo-project/zoo-kernel/response_print.c @ 741

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

Search

Context Navigation

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