source: branches/prototype-v0/zoo-project/zoo-kernel/response_print.c @ 822

Last change on this file since 822 was 822, checked in by djay, 7 years ago

Commit the minimal requirements for remote HPC support

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

Search

ZOO Sponsors

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

Become a sponsor !

Knowledge partners

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

Become a knowledge partner

Related links

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