source: trunk/zoo-project/zoo-kernel/response_print.c @ 908

Last change on this file since 908 was 889, checked in by knut, 6 years ago

Added some new logging functionality (function logMessage(), macros zooLog, zooLogMsg). Added utility functions setErrorMessage(), hasvalue(), and nonempty() in service.c. Added enum WPSException and arrays WPSExceptionText and WPSExceptionCode (see also function setErrorMessage). New conditional definition of type bool in service.c (to fix issue with bool). Null pointer check in function addToMap. Added missing return values and explicit type casts in some functions. Removed Windows-specific code in function dumpBackFinalFile (zoo_service_loader.c) that may cause error for async raw data output in formats other than XML.

  • Property svn:keywords set to Id
File size: 84.6 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;
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    for(;i<limit;i+=2){
670      if(capabilities[vid][i]==NULL)
671        break;
672      else{
673        tmp1=getMap(serv->content,capabilities[vid][i]);
674        if(tmp1!=NULL){
675          if(vid==1 && i==1 && strlen(tmp1->value)<5){
676            char *val=(char*)malloc((strlen(tmp1->value)+5)*sizeof(char));
677            sprintf(val,"%s.0.0",tmp1->value);
678            xmlNewNsProp(nc1,ns,BAD_CAST capabilities[vid][i],BAD_CAST val);
679            free(val);
680          }
681          else
682            xmlNewNsProp(nc1,ns,BAD_CAST capabilities[vid][i],BAD_CAST tmp1->value);
683        }
684        else
685          xmlNewNsProp(nc1,ns,BAD_CAST capabilities[vid][i],BAD_CAST capabilities[vid][i+1]);
686      }
687    }
688    map* tmp3=getMapFromMaps(m,"lenv","level");
689    addPrefix(m,tmp3,serv);
690    printDescription(nc1,ns_ows,serv->name,serv->content,vid);
691    tmp1=serv->metadata;
692    while(tmp1!=NULL){
693      nc2 = xmlNewNode(ns_ows, BAD_CAST "Metadata");
694      xmlNewNsProp(nc2,ns_xlink,BAD_CAST tmp1->name,BAD_CAST tmp1->value);
695      xmlAddChild(nc1,nc2);
696      tmp1=tmp1->next;
697    }
698
699    xmlAddChild(nc,nc1);
700  }
701}
702
703/**
704 * Attach attributes to a ProcessDescription or a ProcessOffering node.
705 *
706 * @param n the XML node to attach the attributes to
707 * @param ns the XML namespace to create the attributes
708 * @param content the servive main content created from the zcfg file
709 * @param vid the version identifier (0 for 1.0.0 and 1 for 2.0.0)
710 */
711void attachAttributes(xmlNodePtr n,xmlNsPtr ns,map* content,int vid){
712  int limit=7;
713  for(int i=1;i<limit;i+=2){
714    map* tmp1=getMap(content,capabilities[vid][i]);
715    if(tmp1!=NULL){
716      if(vid==1 && i==1 && strlen(tmp1->value)<5){
717        char *val=(char*)malloc((strlen(tmp1->value)+5)*sizeof(char));
718        sprintf(val,"%s.0.0",tmp1->value);
719        xmlNewNsProp(n,ns,BAD_CAST capabilities[vid][i],BAD_CAST val);
720        free(val);
721      }
722      else{
723        if(vid==0 && i>=2)
724          xmlNewProp(n,BAD_CAST capabilities[vid][i],BAD_CAST tmp1->value);
725        else
726          xmlNewNsProp(n,ns,BAD_CAST capabilities[vid][i],BAD_CAST tmp1->value);
727      }
728    }
729    else{
730      if(vid==0 && i>=2)
731        xmlNewProp(n,BAD_CAST capabilities[vid][i],BAD_CAST capabilities[vid][i+1]);
732      else
733        xmlNewNsProp(n,ns,BAD_CAST capabilities[vid][i],BAD_CAST capabilities[vid][i+1]);
734    }
735  }
736}
737
738/**
739 * Add the ows:Metadata nodes relative to the profile registry
740 *
741 * @param n the XML node to add the ows:Metadata
742 * @param ns_ows the ows XML namespace
743 * @param ns_xlink the ows xlink namespace
744 * @param reg the profile registry
745 * @param main_conf the map containing the main configuration content
746 * @param serv the service
747 */
748void addInheritedMetadata(xmlNodePtr n,xmlNsPtr ns_ows,xmlNsPtr ns_xlink,registry* reg,maps* main_conf,service* serv){
749  int vid=1;
750  map* tmp1=getMap(serv->content,"extend");
751  if(tmp1==NULL)
752    tmp1=getMap(serv->content,"concept");
753  if(tmp1!=NULL){
754    map* level=getMap(serv->content,"level");
755    if(level!=NULL){
756      xmlNodePtr nc1 = xmlNewNode(ns_ows, BAD_CAST "Metadata");
757      char* ckey=level->value;
758      if(strncasecmp(level->value,"profile",7)==0)
759        ckey=(char*)"generic";
760      if(strncasecmp(level->value,"generic",7)==0)
761        ckey=(char*)"concept";
762      service* inherited=getServiceFromRegistry(reg,ckey,tmp1->value);
763      if(inherited!=NULL){
764        addInheritedMetadata(n,ns_ows,ns_xlink,reg,main_conf,inherited);
765      }
766      char cschema[71];
767      sprintf(cschema,"%s%s",schemas[vid][7],ckey);
768      map* regUrl=getMapFromMaps(main_conf,"main","registryUrl");
769      map* regExt=getMapFromMaps(main_conf,"main","registryExt");
770      char* registryUrl=(char*)malloc((strlen(regUrl->value)+strlen(ckey)+
771                                       (regExt!=NULL?strlen(regExt->value)+1:0)+
772                                       strlen(tmp1->value)+2)*sizeof(char));
773      if(regExt!=NULL)
774        sprintf(registryUrl,"%s%s/%s.%s",regUrl->value,ckey,tmp1->value,regExt->value);
775      else
776        sprintf(registryUrl,"%s%s/%s",regUrl->value,ckey,tmp1->value);
777      xmlNewNsProp(nc1,ns_xlink,BAD_CAST "role",BAD_CAST cschema);
778      xmlNewNsProp(nc1,ns_xlink,BAD_CAST "href",BAD_CAST registryUrl);
779      free(registryUrl);
780      xmlAddChild(n,nc1);
781    }
782  }
783}
784
785/**
786 * Generate a ProcessDescription node for a servie and add it to a given node.
787 *
788 * @param reg the profile registry
789 * @param m the conf maps containing the main.cfg settings
790 * @param nc the XML node to add the Process node
791 * @param serv the servive structure created from the zcfg file
792 * @return the generated wps:ProcessOfferings xmlNodePtr
793 */
794void printDescribeProcessForProcess(registry *reg, maps* m,xmlNodePtr nc,service* serv){
795  xmlNsPtr ns,ns_ows,ns_xlink;
796  xmlNodePtr n,nc1;
797  xmlNodePtr nc2 = NULL;
798  map* version=getMapFromMaps(m,"main","rversion");
799  int vid=getVersionId(version->value);
800
801  n=nc;
802 
803  int wpsId=zooXmlAddNs(NULL,schemas[vid][3],"wps");
804  ns=usedNs[wpsId];
805  int owsId=zooXmlAddNs(NULL,schemas[vid][1],"ows");
806  ns_ows=usedNs[owsId];
807  int xlinkId=zooXmlAddNs(NULL,"http://www.w3.org/1999/xlink","xlink");
808  ns_xlink=usedNs[xlinkId];
809  map* tmp1=NULL;
810
811  if(vid==0){
812    nc = xmlNewNode(NULL, BAD_CAST "ProcessDescription");
813    attachAttributes(nc,ns,serv->content,vid);
814  }
815  else{
816    nc2 = xmlNewNode(ns, BAD_CAST "ProcessOffering");
817    // In case mode was defined in the ZCFG file then restrict the
818    // jobControlOptions value to this value. The dismiss is always
819    // supported whatever you can set in the ZCFG file.
820    // cf. http://docs.opengeospatial.org/is/14-065/14-065.html#47 (Table 30)
821    map* mode=getMap(serv->content,"mode");
822    if(mode!=NULL){
823      if( strncasecmp(mode->value,"sync",strlen(mode->value))==0 ||
824          strncasecmp(mode->value,"async",strlen(mode->value))==0 ){
825        char toReplace[22];
826        sprintf(toReplace,"%s-execute dismiss",mode->value);
827        addToMap(serv->content,capabilities[vid][3],toReplace);
828      }
829    }
830    attachAttributes(nc2,NULL,serv->content,vid);
831    map* level=getMap(serv->content,"level");
832    if(level!=NULL && strcasecmp(level->value,"generic")==0)
833      nc = xmlNewNode(ns, BAD_CAST "GenericProcess");
834    else
835      nc = xmlNewNode(ns, BAD_CAST "Process");
836  }
837 
838  tmp1=getMapFromMaps(m,"lenv","level");
839  addPrefix(m,tmp1,serv);
840  printDescription(nc,ns_ows,serv->name,serv->content,vid);
841
842  if(vid==0){
843    tmp1=serv->metadata;
844    while(tmp1!=NULL){
845      nc1 = xmlNewNode(ns_ows, BAD_CAST "Metadata");
846      xmlNewNsProp(nc1,ns_xlink,BAD_CAST tmp1->name,BAD_CAST tmp1->value);
847      xmlAddChild(nc,nc1);
848      tmp1=tmp1->next;
849    }
850    tmp1=getMap(serv->content,"Profile");
851    if(tmp1!=NULL && vid==0){
852      nc1 = xmlNewNode(ns, BAD_CAST "Profile");
853      xmlAddChild(nc1,xmlNewText(BAD_CAST tmp1->value));
854      xmlAddChild(nc,nc1);
855    }
856  }else{
857    addInheritedMetadata(nc,ns_ows,ns_xlink,reg,m,serv);
858  }
859
860  if(serv->inputs!=NULL){
861    elements* e=serv->inputs;
862    if(vid==0){
863      nc1 = xmlNewNode(NULL, BAD_CAST "DataInputs");
864      printFullDescription(1,e,"Input",ns,ns_ows,nc1,vid);
865      xmlAddChild(nc,nc1);
866    }
867    else{
868      printFullDescription(1,e,"wps:Input",ns,ns_ows,nc,vid);
869    }
870  }
871
872  elements* e=serv->outputs;
873  if(vid==0){
874    nc1 = xmlNewNode(NULL, BAD_CAST "ProcessOutputs");
875    printFullDescription(0,e,"Output",ns,ns_ows,nc1,vid);
876    xmlAddChild(nc,nc1);
877  }
878  else{
879    printFullDescription(0,e,"wps:Output",ns,ns_ows,nc,vid);
880  }
881  if(vid==0)
882    xmlAddChild(n,nc);
883  else if (nc2 != NULL) {         
884    xmlAddChild(nc2,nc);
885    xmlAddChild(n,nc2);
886  }
887
888}
889
890/**
891 * Generate the required XML tree for the detailled metadata information of
892 * inputs or outputs
893 *
894 * @param in 1 in case of inputs, 0 for outputs
895 * @param elem the elements structure containing the metadata information
896 * @param type the name ("Input" or "Output") of the XML node to create
897 * @param ns_ows the ows XML namespace
898 * @param ns_ows the ows XML namespace
899 * @param nc1 the XML node to use to add the created tree
900 * @param vid the WPS version id (0 for 1.0.0, 1 for 2.0.0)
901 */
902void printFullDescription(int in,elements *elem,const char* type,xmlNsPtr ns,xmlNsPtr ns_ows,xmlNodePtr nc1,int vid){
903  xmlNsPtr ns1=NULL;
904  if(vid==1)
905    ns1=ns;
906
907  xmlNodePtr nc2,nc3,nc4,nc5,nc6,nc7,nc8,nc9;
908  elements* e=elem;
909  nc9=NULL;
910  map* tmp1=NULL;
911  while(e!=NULL){
912    int default1=0;
913    int isAnyValue=1;
914    nc2 = xmlNewNode(NULL, BAD_CAST type);
915    if(strstr(type,"Input")!=NULL){
916      tmp1=getMap(e->content,"minOccurs");
917      if(tmp1!=NULL){
918        xmlNewProp(nc2,BAD_CAST tmp1->name,BAD_CAST tmp1->value);
919      }else
920        xmlNewProp(nc2,BAD_CAST "minOccurs",BAD_CAST "0");
921      tmp1=getMap(e->content,"maxOccurs");
922      if(tmp1!=NULL){
923        if(strcasecmp(tmp1->value,"unbounded")!=0)
924          xmlNewProp(nc2,BAD_CAST tmp1->name,BAD_CAST tmp1->value);
925        else
926          xmlNewProp(nc2,BAD_CAST "maxOccurs",BAD_CAST "1000");
927      }else
928        xmlNewProp(nc2,BAD_CAST "maxOccurs",BAD_CAST "1");
929      if((tmp1=getMap(e->content,"maximumMegabytes"))!=NULL){
930        xmlNewProp(nc2,BAD_CAST "maximumMegabytes",BAD_CAST tmp1->value);
931      }
932    }
933
934    printDescription(nc2,ns_ows,e->name,e->content,vid);
935
936    if(e->format!=NULL){
937      const char orderedFields[13][14]={
938        "mimeType",
939        "encoding",
940        "schema",
941        "dataType",
942        "uom",
943        "CRS",
944        "AllowedValues",
945        "range",
946        "rangeMin",
947        "rangeMax",
948        "rangeClosure",
949        "rangeSpace"
950      };
951
952      //Build the (Literal/Complex/BoundingBox)Data node
953      if(strncmp(type,"Output",6)==0){
954        if(strncasecmp(e->format,"LITERALDATA",strlen(e->format))==0)
955          nc3 = xmlNewNode(ns1, BAD_CAST "LiteralOutput");
956        else if(strncasecmp(e->format,"COMPLEXDATA",strlen(e->format))==0)
957          nc3 = xmlNewNode(ns1, BAD_CAST "ComplexOutput");
958        else if(strncasecmp(e->format,"BOUNDINGBOXDATA",strlen(e->format))==0)
959          nc3 = xmlNewNode(ns1, BAD_CAST "BoundingBoxOutput");
960        else
961          nc3 = xmlNewNode(ns1, BAD_CAST e->format);
962      }else{
963        if(strncasecmp(e->format,"LITERALDATA",strlen(e->format))==0 ||
964           strncasecmp(e->format,"LITERALOUTPUT",strlen(e->format))==0){
965          nc3 = xmlNewNode(ns1, BAD_CAST "LiteralData");
966        }
967        else if(strncasecmp(e->format,"COMPLEXDATA",strlen(e->format))==0)
968          nc3 = xmlNewNode(ns1, BAD_CAST "ComplexData");
969        else if(strncasecmp(e->format,"BOUNDINGBOXDATA",strlen(e->format))==0)
970          nc3 = xmlNewNode(ns1, BAD_CAST "BoundingBoxData");
971        else
972          nc3 = xmlNewNode(ns1, BAD_CAST e->format);
973      }
974
975      iotype* _tmp0=NULL;
976      iotype* _tmp=e->defaults;
977      int datatype=0;
978      bool hasUOM=false;
979      bool hasUOM1=false;
980      if(_tmp!=NULL){
981        if(strcmp(e->format,"LiteralOutput")==0 ||
982           strcmp(e->format,"LiteralData")==0){
983          datatype=1;
984          if(vid==1){
985            nc4 = xmlNewNode(ns1, BAD_CAST "Format");
986            xmlNewProp(nc4,BAD_CAST "mimeType",BAD_CAST "text/plain");
987            xmlNewProp(nc4,BAD_CAST "default",BAD_CAST "true");
988            xmlAddChild(nc3,nc4);
989            nc5 = xmlNewNode(NULL, BAD_CAST "LiteralDataDomain");
990            xmlNewProp(nc5,BAD_CAST "default",BAD_CAST "true");
991          }
992          else{
993            nc4 = xmlNewNode(NULL, BAD_CAST "UOMs");
994            nc5 = xmlNewNode(NULL, BAD_CAST "Default");
995          }
996        }
997        else if(strcmp(e->format,"BoundingBoxOutput")==0 ||
998                strcmp(e->format,"BoundingBoxData")==0){
999          datatype=2;
1000          nc5 = xmlNewNode(NULL, BAD_CAST "Default");
1001        }
1002        else{
1003          if(vid==0)
1004            nc4 = xmlNewNode(NULL, BAD_CAST "Default");
1005          nc5 = xmlNewNode(ns1, BAD_CAST "Format");
1006          if(vid==1){
1007            xmlNewProp(nc5,BAD_CAST "default",BAD_CAST "true");
1008            int oI=0;
1009            for(oI=0;oI<3;oI++)
1010              if((tmp1=getMap(_tmp->content,orderedFields[oI]))!=NULL){
1011                xmlNewProp(nc5,BAD_CAST orderedFields[oI],BAD_CAST tmp1->value);
1012              }
1013          }
1014        }
1015     
1016        tmp1=_tmp->content;
1017
1018        if(vid==0)
1019          if((tmp1=getMap(_tmp->content,"DataType"))!=NULL){
1020            nc8 = xmlNewNode(ns_ows, BAD_CAST "DataType");
1021            xmlAddChild(nc8,xmlNewText(BAD_CAST tmp1->value));
1022            char tmp[1024];
1023            sprintf(tmp,"http://www.w3.org/TR/xmlschema-2/#%s",tmp1->value);
1024            xmlNewNsProp(nc8,ns_ows,BAD_CAST "reference",BAD_CAST tmp);
1025            if(vid==0)
1026              xmlAddChild(nc3,nc8);
1027            else
1028              xmlAddChild(nc5,nc8);
1029            datatype=1;
1030          }
1031
1032        bool isInput=false;
1033        if(strncmp(type,"Input",5)==0 || strncmp(type,"wps:Input",9)==0){
1034          isInput=true;
1035          if((tmp1=getMap(_tmp->content,"AllowedValues"))!=NULL){
1036            nc6 = xmlNewNode(ns_ows, BAD_CAST "AllowedValues");
1037            char *token,*saveptr1;
1038            token=strtok_r(tmp1->value,",",&saveptr1);
1039            while(token!=NULL){
1040              nc7 = xmlNewNode(ns_ows, BAD_CAST "Value");
1041              char *tmps=strdup(token);
1042              tmps[strlen(tmps)]=0;
1043              xmlAddChild(nc7,xmlNewText(BAD_CAST tmps));
1044              free(tmps);
1045              xmlAddChild(nc6,nc7);
1046              token=strtok_r(NULL,",",&saveptr1);
1047            }
1048            if(getMap(_tmp->content,"range")!=NULL ||
1049               getMap(_tmp->content,"rangeMin")!=NULL ||
1050               getMap(_tmp->content,"rangeMax")!=NULL ||
1051               getMap(_tmp->content,"rangeClosure")!=NULL )
1052              goto doRange;
1053            if(vid==0)
1054              xmlAddChild(nc3,nc6);
1055            else
1056              xmlAddChild(nc5,nc6);
1057            isAnyValue=-1;
1058          }
1059
1060          tmp1=getMap(_tmp->content,"range");
1061          if(tmp1==NULL)
1062            tmp1=getMap(_tmp->content,"rangeMin");
1063          if(tmp1==NULL)
1064            tmp1=getMap(_tmp->content,"rangeMax");
1065       
1066          if(tmp1!=NULL && isAnyValue==1){
1067            nc6 = xmlNewNode(ns_ows, BAD_CAST "AllowedValues");
1068          doRange:
1069         
1070            /**
1071             * Range: Table 46 OGC Web Services Common Standard
1072             */
1073            nc8 = xmlNewNode(ns_ows, BAD_CAST "Range");
1074         
1075            map* tmp0=getMap(tmp1,"range");
1076            if(tmp0!=NULL){
1077              char* pToken;
1078              char* orig=zStrdup(tmp0->value);
1079              /**
1080               * RangeClosure: Table 47 OGC Web Services Common Standard
1081               */
1082              const char *tmp="closed";
1083              if(orig[0]=='[' && orig[strlen(orig)-1]=='[')
1084                tmp="closed-open";
1085              else
1086                if(orig[0]==']' && orig[strlen(orig)-1]==']')
1087                  tmp="open-closed";
1088                else
1089                  if(orig[0]==']' && orig[strlen(orig)-1]=='[')
1090                    tmp="open";
1091              xmlNewNsProp(nc8,ns_ows,BAD_CAST "rangeClosure",BAD_CAST tmp);
1092              pToken=strtok(orig,",");
1093              int nci0=0;
1094              while(pToken!=NULL){
1095                char *tmpStr=(char*) malloc((strlen(pToken))*sizeof(char));
1096                if(nci0==0){
1097                  nc7 = xmlNewNode(ns_ows, BAD_CAST "MinimumValue");
1098                  strncpy( tmpStr, pToken+1, strlen(pToken)-1 );
1099                  tmpStr[strlen(pToken)-1] = '\0';
1100                }else{
1101                  nc7 = xmlNewNode(ns_ows, BAD_CAST "MaximumValue");
1102                  const char* bkt;
1103                  if ( ( bkt = strchr(pToken, '[') ) != NULL || ( bkt = strchr(pToken, ']') ) != NULL ){
1104                    strncpy( tmpStr, pToken, bkt - pToken );
1105                    tmpStr[bkt - pToken] = '\0';
1106                  }
1107                }
1108                xmlAddChild(nc7,xmlNewText(BAD_CAST tmpStr));
1109                free(tmpStr);
1110                xmlAddChild(nc8,nc7);
1111                nci0++;
1112                pToken = strtok(NULL,",");
1113              }             
1114              if(getMap(tmp1,"rangeSpacing")==NULL){
1115                nc7 = xmlNewNode(ns_ows, BAD_CAST "Spacing");
1116                xmlAddChild(nc7,xmlNewText(BAD_CAST "1"));
1117                xmlAddChild(nc8,nc7);
1118              }
1119              free(orig);
1120            }else{
1121           
1122              tmp0=getMap(tmp1,"rangeMin");
1123              if(tmp0!=NULL){
1124                nc7 = xmlNewNode(ns_ows, BAD_CAST "MinimumValue");
1125                xmlAddChild(nc7,xmlNewText(BAD_CAST tmp0->value));
1126                xmlAddChild(nc8,nc7);
1127              }else{
1128                nc7 = xmlNewNode(ns_ows, BAD_CAST "MinimumValue");
1129                xmlAddChild(nc8,nc7);
1130              }
1131              tmp0=getMap(tmp1,"rangeMax");
1132              if(tmp0!=NULL){
1133                nc7 = xmlNewNode(ns_ows, BAD_CAST "MaximumValue");
1134                xmlAddChild(nc7,xmlNewText(BAD_CAST tmp0->value));
1135                xmlAddChild(nc8,nc7);
1136              }else{
1137                nc7 = xmlNewNode(ns_ows, BAD_CAST "MaximumValue");
1138                xmlAddChild(nc8,nc7);
1139              }
1140              tmp0=getMap(tmp1,"rangeSpacing");
1141              if(tmp0!=NULL){
1142                nc7 = xmlNewNode(ns_ows, BAD_CAST "Spacing");
1143                xmlAddChild(nc7,xmlNewText(BAD_CAST tmp0->value));
1144                xmlAddChild(nc8,nc7);
1145              }
1146              tmp0=getMap(tmp1,"rangeClosure");
1147              if(tmp0!=NULL){
1148                const char *tmp="closed";
1149                if(strcasecmp(tmp0->value,"co")==0)
1150                  tmp="closed-open";
1151                else
1152                  if(strcasecmp(tmp0->value,"oc")==0)
1153                    tmp="open-closed";
1154                  else
1155                    if(strcasecmp(tmp0->value,"o")==0)
1156                      tmp="open";
1157                xmlNewNsProp(nc8,ns_ows,BAD_CAST "rangeClosure",BAD_CAST tmp);
1158              }else
1159                xmlNewNsProp(nc8,ns_ows,BAD_CAST "rangeClosure",BAD_CAST "closed");
1160            }
1161            if(_tmp0==NULL){
1162              xmlAddChild(nc6,nc8);
1163              _tmp0=e->supported;
1164              if(_tmp0!=NULL &&
1165                 (getMap(_tmp0->content,"range")!=NULL ||
1166                  getMap(_tmp0->content,"rangeMin")!=NULL ||
1167                  getMap(_tmp0->content,"rangeMax")!=NULL ||
1168                  getMap(_tmp0->content,"rangeClosure")!=NULL )){
1169                tmp1=_tmp0->content;
1170                goto doRange;
1171              }
1172            }else{
1173              _tmp0=_tmp0->next;
1174              if(_tmp0!=NULL){
1175                xmlAddChild(nc6,nc8);
1176                if(getMap(_tmp0->content,"range")!=NULL ||
1177                   getMap(_tmp0->content,"rangeMin")!=NULL ||
1178                   getMap(_tmp0->content,"rangeMax")!=NULL ||
1179                   getMap(_tmp0->content,"rangeClosure")!=NULL ){
1180                  tmp1=_tmp0->content;
1181                  goto doRange;
1182                }
1183              }
1184            }
1185            xmlAddChild(nc6,nc8);
1186            if(vid==0)
1187              xmlAddChild(nc3,nc6);
1188            else
1189              xmlAddChild(nc5,nc6);
1190            isAnyValue=-1;
1191          }
1192       
1193        }
1194     
1195        int oI=0;
1196        /*if(vid==0)*/ {
1197          for(oI=0;oI<13;oI++)
1198            if((tmp1=getMap(_tmp->content,orderedFields[oI]))!=NULL){
1199#ifdef DEBUG
1200              printf("DATATYPE DEFAULT ? %s\n",tmp1->name);
1201#endif
1202              if(strcmp(tmp1->name,"asReference")!=0 &&
1203                 strncasecmp(tmp1->name,"DataType",8)!=0 &&
1204                 strcasecmp(tmp1->name,"extension")!=0 &&
1205                 strcasecmp(tmp1->name,"value")!=0 &&
1206                 strcasecmp(tmp1->name,"AllowedValues")!=0 &&
1207                 strncasecmp(tmp1->name,"range",5)!=0){
1208                if(datatype!=1){
1209                  char *tmp2=zCapitalize1(tmp1->name);
1210                  nc9 = xmlNewNode(NULL, BAD_CAST tmp2);
1211                  free(tmp2);
1212                }
1213                else{
1214                  char *tmp2=zCapitalize(tmp1->name);
1215                  nc9 = xmlNewNode(ns_ows, BAD_CAST tmp2);
1216                  free(tmp2);
1217                }
1218                xmlAddChild(nc9,xmlNewText(BAD_CAST tmp1->value));
1219                if(vid==0 || oI>=3){
1220                  if(vid==0 || oI!=4)
1221                    xmlAddChild(nc5,nc9);
1222                  if(oI==4 && vid==1){
1223                    xmlNewProp(nc9,BAD_CAST "default",BAD_CAST "true");
1224                  }
1225                }
1226                else
1227                  xmlFree(nc9);
1228                if(strcasecmp(tmp1->name,"uom")==0)
1229                  hasUOM1=true;
1230                hasUOM=true;
1231              }else       
1232                tmp1=tmp1->next;
1233            }
1234        }
1235   
1236        if(datatype!=2){
1237          if(hasUOM==true){
1238            if(vid==0){
1239              xmlAddChild(nc4,nc5);
1240              xmlAddChild(nc3,nc4);
1241            }
1242            else{
1243              xmlAddChild(nc3,nc5);
1244            }
1245          }else{
1246            if(hasUOM1==false && vid==0){
1247              xmlFreeNode(nc5);
1248              if(datatype==1)
1249                xmlFreeNode(nc4);
1250            }
1251            else
1252              xmlAddChild(nc3,nc5);
1253          }
1254        }else{
1255          xmlAddChild(nc3,nc5);
1256        }
1257     
1258        if(datatype!=1 && default1<0){
1259          xmlFreeNode(nc5);
1260          if(datatype!=2)
1261            xmlFreeNode(nc4);
1262        }
1263
1264
1265        if((isInput || vid==1) && datatype==1 &&
1266           getMap(_tmp->content,"AllowedValues")==NULL &&
1267           getMap(_tmp->content,"range")==NULL &&
1268           getMap(_tmp->content,"rangeMin")==NULL &&
1269           getMap(_tmp->content,"rangeMax")==NULL &&
1270           getMap(_tmp->content,"rangeClosure")==NULL ){
1271          tmp1=getMap(_tmp->content,"dataType");
1272          // We were tempted to define default value for boolean as {true,false}
1273          if(tmp1!=NULL && strcasecmp(tmp1->value,"boolean")==0){
1274            nc6 = xmlNewNode(ns_ows, BAD_CAST "AllowedValues");
1275            nc7 = xmlNewNode(ns_ows, BAD_CAST "Value");
1276            xmlAddChild(nc7,xmlNewText(BAD_CAST "true"));
1277            xmlAddChild(nc6,nc7);
1278            nc7 = xmlNewNode(ns_ows, BAD_CAST "Value");
1279            xmlAddChild(nc7,xmlNewText(BAD_CAST "false"));
1280            xmlAddChild(nc6,nc7);
1281            if(vid==0)
1282              xmlAddChild(nc3,nc6);
1283            else
1284              xmlAddChild(nc5,nc6);
1285          }
1286          else
1287            if(vid==0)
1288              xmlAddChild(nc3,xmlNewNode(ns_ows, BAD_CAST "AnyValue"));
1289            else
1290              xmlAddChild(nc5,xmlNewNode(ns_ows, BAD_CAST "AnyValue"));
1291        }
1292
1293        if(vid==1){
1294          if((tmp1=getMap(_tmp->content,"DataType"))!=NULL){
1295            nc8 = xmlNewNode(ns_ows, BAD_CAST "DataType");
1296            xmlAddChild(nc8,xmlNewText(BAD_CAST tmp1->value));
1297            char tmp[1024];
1298            sprintf(tmp,"http://www.w3.org/TR/xmlschema-2/#%s",tmp1->value);
1299            xmlNewNsProp(nc8,ns_ows,BAD_CAST "reference",BAD_CAST tmp);
1300            if(vid==0)
1301              xmlAddChild(nc3,nc8);
1302            else
1303              xmlAddChild(nc5,nc8);
1304            datatype=1;
1305          }
1306          if(hasUOM==true){
1307            tmp1=getMap(_tmp->content,"uom");
1308            if(tmp1!=NULL){
1309              char *tmp2=zCapitalize(tmp1->name);
1310              nc9 = xmlNewNode(ns_ows, BAD_CAST tmp2);
1311              free(tmp2);
1312              //xmlNewProp(nc9, BAD_CAST "default", BAD_CAST "true");
1313              xmlAddChild(nc9,xmlNewText(BAD_CAST tmp1->value));
1314              xmlAddChild(nc5,nc9);
1315              /*struct iotype * _ltmp=e->supported;
1316                while(_ltmp!=NULL){
1317                tmp1=getMap(_ltmp->content,"uom");
1318                if(tmp1!=NULL){
1319                char *tmp2=zCapitalize(tmp1->name);
1320                nc9 = xmlNewNode(ns_ows, BAD_CAST tmp2);
1321                free(tmp2);
1322                xmlAddChild(nc9,xmlNewText(BAD_CAST tmp1->value));
1323                xmlAddChild(nc5,nc9);
1324                }
1325                _ltmp=_ltmp->next;
1326                }*/
1327           
1328            }
1329          }
1330          if(e->defaults!=NULL && (tmp1=getMap(e->defaults->content,"value"))!=NULL){
1331            nc7 = xmlNewNode(ns_ows, BAD_CAST "DefaultValue");
1332            xmlAddChild(nc7,xmlNewText(BAD_CAST tmp1->value));
1333            xmlAddChild(nc5,nc7);
1334          }
1335        }
1336
1337        map* metadata=e->metadata;
1338        xmlNodePtr n=NULL;
1339        int xlinkId=zooXmlAddNs(n,"http://www.w3.org/1999/xlink","xlink");
1340        xmlNsPtr ns_xlink=usedNs[xlinkId];
1341
1342        while(metadata!=NULL){
1343          nc6=xmlNewNode(ns_ows, BAD_CAST "Metadata");
1344          xmlNewNsProp(nc6,ns_xlink,BAD_CAST metadata->name,BAD_CAST metadata->value);
1345          xmlAddChild(nc2,nc6);
1346          metadata=metadata->next;
1347        }
1348
1349      }
1350
1351      _tmp=e->supported;
1352      if(_tmp==NULL && datatype!=1)
1353        _tmp=e->defaults;
1354
1355      int hasSupported=-1;
1356
1357      while(_tmp!=NULL){
1358        if(hasSupported<0){
1359          if(datatype==0){
1360            if(vid==0)
1361              nc4 = xmlNewNode(NULL, BAD_CAST "Supported");
1362            nc5 = xmlNewNode(ns1, BAD_CAST "Format");
1363            if(vid==1){
1364              int oI=0;
1365              for(oI=0;oI<3;oI++)
1366                if((tmp1=getMap(_tmp->content,orderedFields[oI]))!=NULL){
1367                  xmlNewProp(nc5,BAD_CAST orderedFields[oI],BAD_CAST tmp1->value);
1368                }
1369            }
1370          }
1371          else
1372            if(vid==0)
1373              nc5 = xmlNewNode(NULL, BAD_CAST "Supported");
1374          hasSupported=0;
1375        }else
1376          if(datatype==0){
1377            nc5 = xmlNewNode(ns1, BAD_CAST "Format");
1378            if(vid==1){
1379              int oI=0;
1380              for(oI=0;oI<3;oI++)
1381                if((tmp1=getMap(_tmp->content,orderedFields[oI]))!=NULL){
1382                  xmlNewProp(nc5,BAD_CAST orderedFields[oI],BAD_CAST tmp1->value);
1383                }
1384            }
1385          }
1386        tmp1=_tmp->content;
1387        int oI=0;
1388        for(oI=0;oI<6;oI++)
1389          if((tmp1=getMap(_tmp->content,orderedFields[oI]))!=NULL){
1390#ifdef DEBUG
1391            printf("DATATYPE SUPPORTED ? %s\n",tmp1->name);
1392#endif
1393            if(strcmp(tmp1->name,"asReference")!=0 && 
1394               strcmp(tmp1->name,"value")!=0 && 
1395               strcmp(tmp1->name,"DataType")!=0 &&
1396               strcasecmp(tmp1->name,"extension")!=0){
1397              if(datatype!=1){
1398                char *tmp2=zCapitalize1(tmp1->name);
1399                nc6 = xmlNewNode(NULL, BAD_CAST tmp2);
1400                free(tmp2);
1401              }
1402              else{
1403                char *tmp2=zCapitalize(tmp1->name);
1404                nc6 = xmlNewNode(ns_ows, BAD_CAST tmp2);
1405                free(tmp2);
1406              }
1407              if(datatype==2){
1408                char *tmpv,*tmps;
1409                tmps=strtok_r(tmp1->value,",",&tmpv);
1410                while(tmps){
1411                  xmlAddChild(nc6,xmlNewText(BAD_CAST tmps));
1412                  tmps=strtok_r(NULL,",",&tmpv);
1413                  if(tmps){
1414                    char *tmp2=zCapitalize1(tmp1->name);
1415                    nc6 = xmlNewNode(NULL, BAD_CAST tmp2);
1416                    free(tmp2);
1417                  }
1418                }
1419              }
1420              else{
1421                xmlAddChild(nc6,xmlNewText(BAD_CAST tmp1->value));
1422              }
1423              if(vid==0 || oI>=3){
1424                if(vid==0 || oI!=4)
1425                  xmlAddChild(nc5,nc6);
1426                else
1427                  xmlFree(nc6);
1428              }
1429              else
1430                xmlFree(nc6);
1431            }
1432            tmp1=tmp1->next;
1433          }
1434        if(hasSupported<=0){
1435          if(datatype==0){
1436            if(vid==0){
1437              xmlAddChild(nc4,nc5);
1438              xmlAddChild(nc3,nc4);
1439            }
1440            else{
1441              xmlAddChild(nc3,nc5);
1442            }
1443
1444          }else{
1445            if(datatype!=1)
1446              xmlAddChild(nc3,nc5);
1447          }
1448          hasSupported=1;
1449        }
1450        else
1451          if(datatype==0){
1452            if(vid==0){
1453              xmlAddChild(nc4,nc5);
1454              xmlAddChild(nc3,nc4);
1455            }
1456            else{
1457              xmlAddChild(nc3,nc5);
1458            }
1459          }
1460          else
1461            if(datatype!=1)
1462              xmlAddChild(nc3,nc5);
1463
1464        _tmp=_tmp->next;
1465      }
1466
1467      if(hasSupported==0){
1468        if(datatype==0 && vid!=0)
1469          xmlFreeNode(nc4);
1470        xmlFreeNode(nc5);
1471      }
1472
1473      _tmp=e->defaults;
1474      if(datatype==1 && hasUOM1==true){
1475        if(vid==0){
1476          xmlAddChild(nc4,nc5);
1477          xmlAddChild(nc3,nc4);
1478        }
1479        else{
1480          xmlAddChild(nc3,nc5);
1481        }
1482      }
1483
1484      if(vid==0 && _tmp!=NULL && (tmp1=getMap(_tmp->content,"value"))!=NULL){
1485        nc7 = xmlNewNode(NULL, BAD_CAST "DefaultValue");
1486        xmlAddChild(nc7,xmlNewText(BAD_CAST tmp1->value));
1487        xmlAddChild(nc3,nc7);
1488      }
1489   
1490      xmlAddChild(nc2,nc3);
1491    }else{
1492      if(e->child!=NULL && vid!=0){
1493        printFullDescription(in,e->child,type,ns,ns_ows,nc2,vid);
1494      }
1495    }
1496   
1497    if(e->child!=NULL && vid==0){
1498      elements* children=dupElements(e->child);
1499      elements* cursor=children;
1500      while(cursor!=NULL){
1501        char* tmp=strdup(cursor->name);
1502        free(cursor->name);
1503        cursor->name=(char*)malloc((strlen(cursor->name)+strlen(e->name)+2)*sizeof(char));
1504        sprintf(cursor->name,"%s.%s",e->name,tmp);
1505        cursor=cursor->next;
1506      }
1507      printFullDescription(in,children,type,ns,ns_ows,nc2,vid);
1508      xmlAddChild(nc1,nc2);
1509      freeElements(&children);
1510      free(children);
1511    }else
1512      xmlAddChild(nc1,nc2);
1513   
1514    e=e->next;
1515  }
1516}
1517
1518/**
1519 * Generate a wps:Execute XML document.
1520 *
1521 * @param m the conf maps containing the main.cfg settings
1522 * @param request the map representing the HTTP request
1523 * @param pid the process identifier linked to a service
1524 * @param serv the serv structure created from the zcfg file
1525 * @param service the service name
1526 * @param status the status returned by the service
1527 * @param inputs the inputs provided
1528 * @param outputs the outputs generated by the service
1529 */
1530void printProcessResponse(maps* m,map* request, int pid,service* serv,const char* service,int status,maps* inputs,maps* outputs){
1531  xmlNsPtr ns,ns_ows,ns_xlink;
1532  xmlNodePtr nr,n,nc,nc1=NULL,nc3;
1533  xmlDocPtr doc;
1534  time_t time1; 
1535  time(&time1);
1536  nr=NULL;
1537
1538  doc = xmlNewDoc(BAD_CAST "1.0");
1539  map* version=getMapFromMaps(m,"main","rversion");
1540  int vid=getVersionId(version->value);
1541  n = printWPSHeader(doc,m,"Execute",root_nodes[vid][2],(version!=NULL?version->value:"1.0.0"),2);
1542  int wpsId=zooXmlAddNs(NULL,schemas[vid][2],"wps");
1543  ns=usedNs[wpsId];
1544  int owsId=zooXmlAddNs(NULL,schemas[vid][1],"ows");
1545  ns_ows=usedNs[owsId];
1546  int xlinkId=zooXmlAddNs(NULL,"http://www.w3.org/1999/xlink","xlink");
1547  ns_xlink=usedNs[xlinkId];
1548  bool hasStoredExecuteResponse=false;
1549  char stored_path[1024];
1550  memset(stored_path,0,1024);
1551   
1552  if(vid==0){
1553    char tmp[256];
1554    char url[1024];
1555    memset(tmp,0,256);
1556    memset(url,0,1024);
1557    maps* tmp_maps=getMaps(m,"main");
1558    if(tmp_maps!=NULL && tmp_maps->content!=NULL){
1559      map* tmpm1=getMap(tmp_maps->content,"serverAddress");
1560      /**
1561       * Check if the ZOO Service GetStatus is available in the local directory.
1562       * If yes, then it uses a reference to an URL which the client can access
1563       * to get information on the status of a running Service (using the
1564       * percentCompleted attribute).
1565       * Else fallback to the initial method using the xml file to write in ...
1566       */
1567      map* cwdMap=getMapFromMaps(m,"main","servicePath");
1568      struct stat myFileInfo;
1569      int statRes;
1570      char file_path[1024];
1571      if(cwdMap!=NULL){
1572        sprintf(file_path,"%s/GetStatus.zcfg",cwdMap->value);
1573      }else{
1574        char ntmp[1024];
1575#ifndef WIN32
1576        getcwd(ntmp,1024);
1577#else
1578        _getcwd(ntmp,1024);
1579#endif
1580        sprintf(file_path,"%s/GetStatus.zcfg",ntmp);
1581      }
1582      statRes=stat(file_path,&myFileInfo);
1583      if(statRes==0){
1584        char currentSid[128];
1585        map* tmpm=getMap(tmp_maps->content,"rewriteUrl");
1586        map *tmp_lenv=NULL;
1587        tmp_lenv=getMapFromMaps(m,"lenv","usid");
1588        if(tmp_lenv==NULL)
1589          sprintf(currentSid,"%i",pid);
1590        else
1591          sprintf(currentSid,"%s",tmp_lenv->value);
1592        if(tmpm==NULL || strcasecmp(tmpm->value,"false")==0){
1593          sprintf(url,"%s?request=Execute&service=WPS&version=1.0.0&Identifier=GetStatus&DataInputs=sid=%s&RawDataOutput=Result",tmpm1->value,currentSid);
1594        }else{
1595          if(strlen(tmpm->value)>0)
1596            if(strcasecmp(tmpm->value,"true")!=0)
1597              sprintf(url,"%s/%s/GetStatus/%s",tmpm1->value,tmpm->value,currentSid);
1598            else
1599              sprintf(url,"%s/GetStatus/%s",tmpm1->value,currentSid);
1600          else
1601            sprintf(url,"%s/?request=Execute&service=WPS&version=1.0.0&Identifier=GetStatus&DataInputs=sid=%s&RawDataOutput=Result",tmpm1->value,currentSid);
1602        }
1603      }else{
1604        int lpid;
1605        map* tmpm2=getMapFromMaps(m,"lenv","usid");
1606        map* tmpm3=getMap(tmp_maps->content,"tmpUrl");
1607        if(tmpm1!=NULL && tmpm3!=NULL){
1608          if( strncasecmp( tmpm3->value, "http://", 7) == 0 ||
1609              strncasecmp( tmpm3->value, "https://", 8 ) == 0 ){
1610            sprintf(url,"%s/%s_%s.xml",tmpm3->value,service,tmpm2->value);
1611          }else
1612            sprintf(url,"%s/%s_%s.xml",tmpm1->value,service,tmpm2->value);
1613        }
1614      }
1615      if(tmpm1!=NULL){
1616        sprintf(tmp,"%s",tmpm1->value);
1617      }
1618      int lpid;
1619      map* tmpm2=getMapFromMaps(m,"lenv","usid");
1620      tmpm1=getMapFromMaps(m,"main","TmpPath");
1621      sprintf(stored_path,"%s/%s_%s.xml",tmpm1->value,service,tmpm2->value);
1622    }
1623
1624    xmlNewProp(n,BAD_CAST "serviceInstance",BAD_CAST tmp);
1625    map* test=getMap(request,"storeExecuteResponse");
1626    if(test!=NULL && strcasecmp(test->value,"true")==0){
1627      xmlNewProp(n,BAD_CAST "statusLocation",BAD_CAST url);
1628      hasStoredExecuteResponse=true;
1629    }
1630
1631    nc = xmlNewNode(ns, BAD_CAST "Process");
1632    map* tmp2=getMap(serv->content,"processVersion");
1633    if(tmp2!=NULL)
1634      xmlNewNsProp(nc,ns,BAD_CAST "processVersion",BAD_CAST tmp2->value);
1635    else
1636      xmlNewNsProp(nc,ns,BAD_CAST "processVersion",BAD_CAST "1");
1637 
1638    map* tmpI=getMapFromMaps(m,"lenv","oIdentifier");
1639    printDescription(nc,ns_ows,tmpI->value,serv->content,0);
1640
1641    xmlAddChild(n,nc);
1642
1643    nc = xmlNewNode(ns, BAD_CAST "Status");
1644    const struct tm *tm;
1645    size_t len;
1646    time_t now;
1647    char *tmp1;
1648    map *tmpStatus;
1649 
1650    now = time ( NULL );
1651    tm = localtime ( &now );
1652
1653    tmp1 = (char*)malloc((TIME_SIZE+1)*sizeof(char));
1654
1655    len = strftime ( tmp1, TIME_SIZE, "%Y-%m-%dT%I:%M:%SZ", tm );
1656
1657    xmlNewProp(nc,BAD_CAST "creationTime",BAD_CAST tmp1);
1658
1659    char sMsg[2048];
1660    switch(status){
1661    case SERVICE_SUCCEEDED:
1662      nc1 = xmlNewNode(ns, BAD_CAST "ProcessSucceeded");
1663      sprintf(sMsg,_("The service \"%s\" ran successfully."),serv->name);
1664      nc3=xmlNewText(BAD_CAST sMsg);
1665      xmlAddChild(nc1,nc3);
1666      break;
1667    case SERVICE_STARTED:
1668      nc1 = xmlNewNode(ns, BAD_CAST "ProcessStarted");
1669      tmpStatus=getMapFromMaps(m,"lenv","status");
1670      xmlNewProp(nc1,BAD_CAST "percentCompleted",BAD_CAST tmpStatus->value);
1671      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);
1672      nc3=xmlNewText(BAD_CAST sMsg);
1673      xmlAddChild(nc1,nc3);
1674      break;
1675    case SERVICE_ACCEPTED:
1676      nc1 = xmlNewNode(ns, BAD_CAST "ProcessAccepted");
1677      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);
1678      nc3=xmlNewText(BAD_CAST sMsg);
1679      xmlAddChild(nc1,nc3);
1680      break;
1681    case SERVICE_FAILED:
1682      nc1 = xmlNewNode(ns, BAD_CAST "ProcessFailed");
1683      map *errorMap;
1684      map *te;
1685      te=getMapFromMaps(m,"lenv","code");
1686      if(te!=NULL)
1687        errorMap=createMap("code",te->value);
1688      else
1689        errorMap=createMap("code","NoApplicableCode");
1690      te=getMapFromMaps(m,"lenv","message");
1691      if(te!=NULL)
1692        addToMap(errorMap,"text",_ss(te->value));
1693      else
1694        addToMap(errorMap,"text",_("No more information available"));
1695      nc3=createExceptionReportNode(m,errorMap,0);
1696      freeMap(&errorMap);
1697      free(errorMap);
1698      xmlAddChild(nc1,nc3);
1699      break;
1700    default :
1701      printf(_("error code not know : %i\n"),status);
1702      //exit(1);
1703      break;
1704    }
1705    xmlAddChild(nc,nc1);
1706    xmlAddChild(n,nc);
1707    free(tmp1);
1708
1709#ifdef DEBUG
1710    fprintf(stderr,"printProcessResponse %d\n",__LINE__);
1711#endif
1712
1713    map* lineage=getMap(request,"lineage");
1714    if(lineage!=NULL && strcasecmp(lineage->value,"true")==0){
1715      nc = xmlNewNode(ns, BAD_CAST "DataInputs");
1716      maps* mcursor=inputs;
1717      elements* scursor=NULL;
1718      while(mcursor!=NULL /*&& scursor!=NULL*/){
1719        scursor=getElements(serv->inputs,mcursor->name);
1720        printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Input",vid);
1721        mcursor=mcursor->next;
1722      }
1723      xmlAddChild(n,nc);
1724
1725      nc = xmlNewNode(ns, BAD_CAST "OutputDefinitions");
1726      mcursor=outputs;
1727      scursor=NULL;
1728      while(mcursor!=NULL){
1729        scursor=getElements(serv->outputs,mcursor->name);
1730        printOutputDefinitions(doc,nc,ns,ns_ows,scursor,mcursor,"Output");
1731        mcursor=mcursor->next;
1732      }
1733      xmlAddChild(n,nc);
1734    }
1735  }
1736
1737  /**
1738   * Display the process output only when requested !
1739   */
1740  if(status==SERVICE_SUCCEEDED){
1741    if(vid==0){
1742      nc = xmlNewNode(ns, BAD_CAST "ProcessOutputs");
1743    }
1744    maps* mcursor=outputs;
1745    elements* scursor=serv->outputs;
1746    map* testResponse=getMap(request,"RawDataOutput");
1747    if(testResponse==NULL)
1748      testResponse=getMap(request,"ResponseDocument");
1749    while(mcursor!=NULL){
1750      map* tmp0=getMap(mcursor->content,"inRequest");
1751      scursor=getElements(serv->outputs,mcursor->name);
1752      if(scursor!=NULL){
1753        if(testResponse==NULL || tmp0==NULL){
1754          if(vid==0)
1755            printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Output",vid);
1756          else
1757            printIOType(doc,n,ns,ns_ows,ns_xlink,scursor,mcursor,"Output",vid);
1758        }
1759        else
1760
1761          if(tmp0!=NULL && strncmp(tmp0->value,"true",4)==0){
1762            if(vid==0)
1763              printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Output",vid);
1764            else
1765              printIOType(doc,n,ns,ns_ows,ns_xlink,scursor,mcursor,"Output",vid);
1766          }
1767      }else
1768        /**
1769         * In case there was no definition found in the ZCFG file but
1770         * present in the service code
1771         */
1772        if(vid==0)
1773          printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Output",vid);
1774        else
1775          printIOType(doc,n,ns,ns_ows,ns_xlink,scursor,mcursor,"Output",vid);
1776      mcursor=mcursor->next;
1777    }
1778    if(vid==0)
1779      xmlAddChild(n,nc);
1780  }
1781
1782  if(vid==0 && 
1783     hasStoredExecuteResponse==true 
1784     && status!=SERVICE_STARTED
1785#ifndef WIN32
1786     && status!=SERVICE_ACCEPTED
1787#endif
1788     ){
1789#ifndef RELY_ON_DB
1790    semid lid=acquireLock(m);//,1);
1791    if(lid<0){
1792      /* If the lock failed */
1793      errorException(m,_("Lock failed."),"InternalError",NULL);
1794      xmlFreeDoc(doc);
1795      xmlCleanupParser();
1796      zooXmlCleanupNs();
1797      return;
1798    }
1799    else{
1800#endif
1801      /* We need to write the ExecuteResponse Document somewhere */
1802      FILE* output=fopen(stored_path,"w");
1803      if(output==NULL){
1804        /* If the file cannot be created return an ExceptionReport */
1805        char tmpMsg[1024];
1806        sprintf(tmpMsg,_("Unable to create the file \"%s\" for storing the ExecuteResponse."),stored_path);
1807
1808        errorException(m,tmpMsg,"InternalError",NULL);
1809        xmlFreeDoc(doc);
1810        xmlCleanupParser();
1811        zooXmlCleanupNs();
1812#ifndef RELY_ON_DB
1813        unlockShm(lid);
1814#endif
1815        return;
1816      }
1817      xmlChar *xmlbuff;
1818      int buffersize;
1819      xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, "UTF-8", 1);
1820      fwrite(xmlbuff,1,xmlStrlen(xmlbuff)*sizeof(char),output);
1821      xmlFree(xmlbuff);
1822      fclose(output);
1823#ifndef RELY_ON_DB
1824#ifdef DEBUG
1825      fprintf(stderr,"UNLOCK %s %d !\n",__FILE__,__LINE__);
1826#endif
1827      unlockShm(lid);
1828      map* v=getMapFromMaps(m,"lenv","sid");
1829      // Remove the lock when running as a normal task
1830      if(getpid()==atoi(v->value)){
1831        removeShmLock (m, 1);
1832      }
1833    }
1834#endif
1835  }
1836  printDocument(m,doc,pid);
1837
1838  xmlCleanupParser();
1839  zooXmlCleanupNs();
1840}
1841
1842/**
1843 * Print a XML document.
1844 *
1845 * @param m the conf maps containing the main.cfg settings
1846 * @param doc the XML document
1847 * @param pid the process identifier linked to a service
1848 */
1849void printDocument(maps* m, xmlDocPtr doc,int pid){
1850  char *encoding=getEncoding(m);
1851  if(pid==getpid()){
1852    printHeaders(m);
1853    printf("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding);
1854  }
1855  fflush(stdout);
1856  xmlChar *xmlbuff;
1857  int buffersize;
1858  /*
1859   * Dump the document to a buffer and print it on stdout
1860   * for demonstration purposes.
1861   */
1862  xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);
1863  printf("%s",xmlbuff);
1864  fflush(stdout);
1865  /*
1866   * Free associated memory.
1867   */
1868  xmlFree(xmlbuff);
1869  xmlFreeDoc(doc);
1870  xmlCleanupParser();
1871  zooXmlCleanupNs();
1872}
1873
1874/**
1875 * Print a XML document.
1876 *
1877 * @param doc the XML document (unused)
1878 * @param nc the XML node to add the output definition
1879 * @param ns_wps the wps XML namespace
1880 * @param ns_ows the ows XML namespace
1881 * @param e the output elements
1882 * @param m the conf maps containing the main.cfg settings
1883 * @param type the type (unused)
1884 */
1885void printOutputDefinitions(xmlDocPtr doc,xmlNodePtr nc,xmlNsPtr ns_wps,xmlNsPtr ns_ows,elements* e,maps* m,const char* type){
1886  xmlNodePtr nc1;
1887  nc1=xmlNewNode(ns_wps, BAD_CAST type);
1888  map *tmp=NULL; 
1889  if(e!=NULL && e->defaults!=NULL)
1890    tmp=e->defaults->content;
1891  else{
1892    /*
1893    dumpElements(e);
1894    */
1895    return;
1896  }
1897  while(tmp!=NULL){
1898    if(strncasecmp(tmp->name,"MIMETYPE",strlen(tmp->name))==0
1899       || strncasecmp(tmp->name,"ENCODING",strlen(tmp->name))==0
1900       || strncasecmp(tmp->name,"SCHEMA",strlen(tmp->name))==0
1901       || strncasecmp(tmp->name,"UOM",strlen(tmp->name))==0)
1902    xmlNewProp(nc1,BAD_CAST tmp->name,BAD_CAST tmp->value);
1903    tmp=tmp->next;
1904  }
1905  tmp=getMap(e->defaults->content,"asReference");
1906  if(tmp==NULL)
1907    xmlNewProp(nc1,BAD_CAST "asReference",BAD_CAST "false");
1908
1909  tmp=e->content;
1910
1911  printDescription(nc1,ns_ows,m->name,e->content,0);
1912
1913  xmlAddChild(nc,nc1);
1914
1915}
1916
1917/**
1918 * Generate XML nodes describing inputs or outputs metadata.
1919 *
1920 * @param doc the XML document
1921 * @param nc the XML node to add the definition
1922 * @param ns_wps the wps namespace
1923 * @param ns_ows the ows namespace
1924 * @param ns_xlink the xlink namespace
1925 * @param e the output elements
1926 * @param m the conf maps containing the main.cfg settings
1927 * @param type the type
1928 */
1929void printIOType(xmlDocPtr doc,xmlNodePtr nc,xmlNsPtr ns_wps,xmlNsPtr ns_ows,xmlNsPtr ns_xlink,elements* e,maps* m,const char* type,int vid){
1930
1931  xmlNodePtr nc1,nc2,nc3;
1932  nc1=xmlNewNode(ns_wps, BAD_CAST type);
1933  map *tmp=NULL;
1934  if(e!=NULL)
1935    tmp=e->content;
1936  else
1937    tmp=m->content;
1938
1939  if(vid==0){
1940    nc2=xmlNewNode(ns_ows, BAD_CAST "Identifier");
1941    if(e!=NULL)
1942      nc3=xmlNewText(BAD_CAST e->name);
1943    else
1944      nc3=xmlNewText(BAD_CAST m->name);
1945   
1946    xmlAddChild(nc2,nc3);
1947    xmlAddChild(nc1,nc2);
1948 
1949    xmlAddChild(nc,nc1);
1950
1951    if(e!=NULL)
1952      tmp=getMap(e->content,"Title");
1953    else
1954      tmp=getMap(m->content,"Title");
1955   
1956    if(tmp!=NULL){
1957      nc2=xmlNewNode(ns_ows, BAD_CAST tmp->name);
1958      nc3=xmlNewText(BAD_CAST _ss(tmp->value));
1959      xmlAddChild(nc2,nc3); 
1960      xmlAddChild(nc1,nc2);
1961    }
1962
1963    if(e!=NULL)
1964      tmp=getMap(e->content,"Abstract");
1965    else
1966      tmp=getMap(m->content,"Abstract");
1967
1968    if(tmp!=NULL){
1969      nc2=xmlNewNode(ns_ows, BAD_CAST tmp->name);
1970      nc3=xmlNewText(BAD_CAST _ss(tmp->value));
1971      xmlAddChild(nc2,nc3); 
1972      xmlAddChild(nc1,nc2);
1973      xmlAddChild(nc,nc1);
1974    }
1975  }else{
1976    xmlNewProp(nc1,BAD_CAST "id",BAD_CAST (e!=NULL?e->name:m->name));
1977  }
1978
1979  // IO type nested outputs
1980  if(m->child!=NULL){
1981    maps* curs=m->child;
1982    elements* ecurs=getElements(e,(e!=NULL?e->name:m->name));
1983    ecurs=ecurs->child;
1984    while(curs!=NULL){
1985      ecurs=getElements(ecurs,(curs->name));
1986      map* inRequest=getMap(curs->content,"inRequest");
1987      if(inRequest!=NULL && strncasecmp(inRequest->value,"true",4)==0)
1988        printIOType(doc,nc1,ns_wps,ns_ows,ns_xlink,ecurs,curs,type,vid);
1989      curs=curs->next;
1990      ecurs=getElements(e,(e!=NULL?e->name:m->name));
1991      ecurs=ecurs->child;
1992    }
1993  }
1994  else{
1995    map *tmpMap=getMap(m->content,"Reference");
1996    if(tmpMap==NULL){
1997      nc2=xmlNewNode(ns_wps, BAD_CAST "Data");
1998      if(e!=NULL && e->format!=NULL){
1999        if(strncasecmp(e->format,"LiteralOutput",strlen(e->format))==0)
2000          nc3=xmlNewNode(ns_wps, BAD_CAST "LiteralData");
2001        else
2002          if(strncasecmp(e->format,"ComplexOutput",strlen(e->format))==0)
2003            nc3=xmlNewNode(ns_wps, BAD_CAST "ComplexData");
2004          else if(strncasecmp(e->format,"BoundingBoxOutput",strlen(e->format))==0)
2005            nc3=xmlNewNode(ns_wps, BAD_CAST "BoundingBoxData");
2006          else
2007            nc3=xmlNewNode(ns_wps, BAD_CAST e->format);
2008      }
2009      else {
2010        map* tmpV=getMapFromMaps(m,"format","value");
2011        if(tmpV!=NULL)
2012          nc3=xmlNewNode(ns_wps, BAD_CAST tmpV->value);
2013        else
2014          nc3=xmlNewNode(ns_wps, BAD_CAST "LiteralData");
2015      } 
2016      tmp=m->content;
2017     
2018      while(tmp!=NULL){
2019        if(strcasecmp(tmp->name,"mimeType")==0 ||
2020           strcasecmp(tmp->name,"encoding")==0 ||
2021           strcasecmp(tmp->name,"schema")==0 ||
2022           strcasecmp(tmp->name,"datatype")==0 ||
2023           strcasecmp(tmp->name,"uom")==0) {
2024         
2025          if(vid==0)
2026            xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST tmp->value);
2027          else{
2028            if(strcasecmp(tmp->name,"datatype")==0)
2029              xmlNewProp(nc2,BAD_CAST "mimeType",BAD_CAST "text/plain");
2030            else
2031              if(strcasecmp(tmp->name,"uom")!=0)
2032                xmlNewProp(nc2,BAD_CAST tmp->name,BAD_CAST tmp->value);
2033          }
2034        }
2035        if(vid==0)
2036          xmlAddChild(nc2,nc3);
2037        tmp=tmp->next;
2038      }
2039      if(e!=NULL && e->format!=NULL && strcasecmp(e->format,"BoundingBoxData")==0) {
2040        map* bb=getMap(m->content,"value");
2041        if(bb!=NULL) {
2042          map* tmpRes=parseBoundingBox(bb->value);
2043          printBoundingBox(ns_ows,nc3,tmpRes);
2044          freeMap(&tmpRes);
2045          free(tmpRes);
2046        }
2047      }
2048      else {
2049        if(e!=NULL)
2050          tmp=getMap(e->defaults->content,"mimeType");
2051        else
2052          tmp=NULL;
2053       
2054        map* tmp1=getMap(m->content,"encoding");
2055        map* tmp2=getMap(m->content,"mimeType");
2056        map* tmp3=getMap(m->content,"value");
2057        int hasValue=1;
2058        if(tmp3==NULL){
2059          tmp3=createMap("value","");
2060          hasValue=-1;
2061        }
2062       
2063        if( ( tmp1 != NULL && strncmp(tmp1->value,"base64",6) == 0 )     // if encoding is base64
2064            ||                                                         // or if
2065            ( tmp2 != NULL && ( strstr(tmp2->value,"text") == NULL       //  mime type is not text
2066                                &&                                       //  nor
2067                                strstr(tmp2->value,"xml") == NULL        //  xml
2068                                &&                                       // nor
2069                                strstr(tmp2->value,"javascript") == NULL // javascript
2070                                &&
2071                                strstr(tmp2->value,"json") == NULL
2072                                &&
2073                                strstr(tmp2->value,"ecmascript") == NULL
2074                                &&
2075                                // include for backwards compatibility,
2076                                // although correct mime type is ...kml+xml:
2077                                strstr(tmp2->value,"google-earth.kml") == NULL                                                  )
2078              )
2079            ) {                                                          // then       
2080          map* rs=getMap(m->content,"size");                       // obtain size
2081          bool isSized=true;
2082          if(rs==NULL){
2083            char tmp1[1024];
2084            sprintf(tmp1,"%ld",strlen(tmp3->value));
2085            rs=createMap("size",tmp1);
2086            isSized=false;
2087          }
2088         
2089          xmlAddChild((vid==0?nc3:nc2),xmlNewText(BAD_CAST base64(tmp3->value, atoi(rs->value))));  // base 64 encode in XML
2090         
2091          if(tmp1==NULL || (tmp1!=NULL && strncmp(tmp1->value,"base64",6)!=0)) {
2092            xmlAttrPtr ap = xmlHasProp((vid==0?nc3:nc2), BAD_CAST "encoding");
2093            if (ap != NULL) {
2094              xmlRemoveProp(ap);
2095            }                   
2096            xmlNewProp((vid==0?nc3:nc2),BAD_CAST "encoding",BAD_CAST "base64");
2097          }
2098         
2099          if(!isSized){
2100            freeMap(&rs);
2101            free(rs);
2102          }
2103        }
2104        else if (tmp2!=NULL) {                                 // else (text-based format)
2105          if(strstr(tmp2->value, "javascript") != NULL ||      //    if javascript put code in CDATA block
2106             strstr(tmp2->value, "json") != NULL ||            //    (will not be parsed by XML reader)
2107             strstr(tmp2->value, "ecmascript") != NULL
2108           ) {
2109            xmlAddChild((vid==0?nc3:nc2),xmlNewCDataBlock(doc,BAD_CAST tmp3->value,strlen(tmp3->value)));
2110          }   
2111          else {                                                     // else
2112            if (strstr(tmp2->value, "xml") != NULL ||                 // if XML-based format
2113                // include for backwards compatibility,
2114              // although correct mime type is ...kml+xml:                 
2115                strstr(tmp2->value, "google-earth.kml") != NULL
2116                ) { 
2117             
2118              int li=zooXmlAddDoc(tmp3->value);
2119              xmlDocPtr doc = iDocs[li];
2120              xmlNodePtr ir = xmlDocGetRootElement(doc);
2121              xmlAddChild((vid==0?nc3:nc2),ir);
2122            }
2123            else                                                     // else   
2124              xmlAddChild((vid==0?nc3:nc2),xmlNewText(BAD_CAST tmp3->value));    //   add text node
2125          }
2126          xmlAddChild(nc2,nc3);
2127        }
2128        else {
2129          xmlAddChild((vid==0?nc3:nc2),xmlNewText(BAD_CAST tmp3->value));
2130        }
2131       
2132        if(hasValue<0) {
2133          freeMap(&tmp3);
2134          free(tmp3);
2135        }
2136      }
2137    }
2138    else { // Reference
2139      tmpMap=getMap(m->content,"Reference");
2140      nc3=nc2=xmlNewNode(ns_wps, BAD_CAST "Reference");
2141      /* Special case to avoid failing to validate against the WPS 2.0 schema */
2142      if(strcasecmp(type,"Output")==0 && vid==0)
2143        xmlNewProp(nc3,BAD_CAST "href",BAD_CAST tmpMap->value);
2144      else
2145        xmlNewNsProp(nc3,ns_xlink,BAD_CAST "href",BAD_CAST tmpMap->value);
2146     
2147      tmp=m->content;
2148      while(tmp!=NULL) {
2149        if(strcasecmp(tmp->name,"mimeType")==0 ||
2150           strcasecmp(tmp->name,"encoding")==0 ||
2151           strcasecmp(tmp->name,"schema")==0 ||
2152           strcasecmp(tmp->name,"datatype")==0 ||
2153           strcasecmp(tmp->name,"uom")==0){
2154         
2155          if(strcasecmp(tmp->name,"datatype")==0)
2156            xmlNewProp(nc3,BAD_CAST "mimeType",BAD_CAST "text/plain");
2157          else
2158            xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST tmp->value);
2159        }
2160        tmp=tmp->next;
2161        xmlAddChild(nc2,nc3);
2162      }
2163    }
2164    xmlAddChild(nc1,nc2);
2165  }
2166  xmlAddChild(nc,nc1);
2167}
2168
2169/**
2170 * Create XML node with basic ows metadata information (Identifier,Title,Abstract)
2171 *
2172 * @param root the root XML node to add the description
2173 * @param ns_ows the ows XML namespace
2174 * @param identifier the identifier to use
2175 * @param amap the map containing the ows metadata information
2176 */
2177void printDescription(xmlNodePtr root,xmlNsPtr ns_ows,const char* identifier,map* amap,int vid=0){
2178  xmlNodePtr nc2;
2179  if(vid==0){
2180    nc2 = xmlNewNode(ns_ows, BAD_CAST "Identifier");
2181    xmlAddChild(nc2,xmlNewText(BAD_CAST identifier));
2182    xmlAddChild(root,nc2);
2183  }
2184  map* tmp=amap;
2185  const char *tmp2[2];
2186  tmp2[0]="Title";
2187  tmp2[1]="Abstract";
2188  int j=0;
2189  for(j=0;j<2;j++){
2190    map* tmp1=getMap(tmp,tmp2[j]);
2191    if(tmp1!=NULL){
2192      nc2 = xmlNewNode(ns_ows, BAD_CAST tmp2[j]);
2193      xmlAddChild(nc2,xmlNewText(BAD_CAST _ss(tmp1->value)));
2194      xmlAddChild(root,nc2);
2195    }
2196  }
2197  if(vid==1){
2198    nc2 = xmlNewNode(ns_ows, BAD_CAST "Identifier");
2199    xmlAddChild(nc2,xmlNewText(BAD_CAST identifier));
2200    xmlAddChild(root,nc2);
2201  }
2202}
2203
2204/**
2205 * Print an OWS ExceptionReport Document and HTTP headers (when required)
2206 * depending on the code.
2207 * Set hasPrinted value to true in the [lenv] section.
2208 *
2209 * @param m the maps containing the settings of the main.cfg file
2210 * @param s the map containing the text,code,locator keys (or a map array of the same keys)
2211 */
2212void printExceptionReportResponse(maps* m,map* s){
2213  if(getMapFromMaps(m,"lenv","hasPrinted")!=NULL)
2214    return;
2215  int buffersize;
2216  xmlDocPtr doc;
2217  xmlChar *xmlbuff;
2218  xmlNodePtr n;
2219
2220  zooXmlCleanupNs();
2221  doc = xmlNewDoc(BAD_CAST "1.0");
2222  maps* tmpMap=getMaps(m,"main");
2223  char *encoding=getEncoding(tmpMap);
2224  const char *exceptionCode;
2225 
2226  map* tmp=getMap(s,"code");
2227  if(tmp!=NULL){
2228    if(strcmp(tmp->value,"OperationNotSupported")==0 ||
2229       strcmp(tmp->value,"NoApplicableCode")==0)
2230      exceptionCode="501 Not Implemented";
2231    else
2232      if(strcmp(tmp->value,"MissingParameterValue")==0 ||
2233         strcmp(tmp->value,"InvalidUpdateSequence")==0 ||
2234         strcmp(tmp->value,"OptionNotSupported")==0 ||
2235         strcmp(tmp->value,"VersionNegotiationFailed")==0 ||
2236         strcmp(tmp->value,"InvalidParameterValue")==0)
2237        exceptionCode="400 Bad request";
2238      else
2239        exceptionCode="501 Internal Server Error";
2240  }
2241  else
2242    exceptionCode="501 Internal Server Error";
2243
2244  if(m!=NULL){
2245    map *tmpSid=getMapFromMaps(m,"lenv","sid");
2246    if(tmpSid!=NULL){
2247      if( getpid()==atoi(tmpSid->value) ){
2248        printHeaders(m);
2249        printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode);
2250      }
2251    }
2252    else{
2253      printHeaders(m);
2254      printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode);
2255    }
2256  }else{
2257    printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode);
2258  }
2259  n=createExceptionReportNode(m,s,1);
2260  xmlDocSetRootElement(doc, n);
2261  xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);
2262  printf("%s",xmlbuff);
2263  fflush(stdout);
2264  xmlFreeDoc(doc);
2265  xmlFree(xmlbuff);
2266  xmlCleanupParser();
2267  zooXmlCleanupNs();
2268  if(m!=NULL)
2269    setMapInMaps(m,"lenv","hasPrinted","true");
2270}
2271
2272/**
2273 * Create an OWS ExceptionReport Node.
2274 *
2275 * @param m the conf maps
2276 * @param s the map containing the text,code,locator keys
2277 * @param use_ns (0/1) choose if you want to generate an ExceptionReport or
2278 *  ows:ExceptionReport node respectively
2279 * @return the ExceptionReport/ows:ExceptionReport node
2280 */
2281xmlNodePtr createExceptionReportNode(maps* m,map* s,int use_ns){
2282 
2283  xmlNsPtr ns,ns_xsi;
2284  xmlNodePtr n,nc,nc1;
2285
2286  int nsid=zooXmlAddNs(NULL,"http://www.opengis.net/ows","ows");
2287  ns=usedNs[nsid];
2288  if(use_ns==0){
2289    ns=NULL;
2290  }
2291  n = xmlNewNode(ns, BAD_CAST "ExceptionReport");
2292  map* version=getMapFromMaps(m,"main","rversion");
2293  int vid=-1;
2294  if(version!=NULL)
2295    vid=getVersionId(version->value);
2296  if(vid<0)
2297    vid=0;
2298  if(use_ns==1){
2299    xmlNewNs(n,BAD_CAST schemas[vid][1],BAD_CAST"ows");
2300    int xsiId=zooXmlAddNs(n,"http://www.w3.org/2001/XMLSchema-instance","xsi");
2301    ns_xsi=usedNs[xsiId];
2302    char tmp[1024];
2303    sprintf(tmp,"%s %s",schemas[vid][1],schemas[vid][5]);
2304    xmlNewNsProp(n,ns_xsi,BAD_CAST "schemaLocation",BAD_CAST tmp);
2305  }
2306
2307
2308  addLangAttr(n,m);
2309  xmlNewProp(n,BAD_CAST "version",BAD_CAST schemas[vid][6]);
2310 
2311  int length=1;
2312  int cnt=0;
2313  map* len=getMap(s,"length");
2314  if(len!=NULL)
2315    length=atoi(len->value);
2316  for(cnt=0;cnt<length;cnt++){
2317    nc = xmlNewNode(ns, BAD_CAST "Exception");
2318   
2319    map* tmp=getMapArray(s,"code",cnt);
2320    if(tmp==NULL)
2321      tmp=getMap(s,"code");
2322    if(tmp!=NULL)
2323      xmlNewProp(nc,BAD_CAST "exceptionCode",BAD_CAST tmp->value);
2324    else
2325      xmlNewProp(nc,BAD_CAST "exceptionCode",BAD_CAST "NoApplicableCode");
2326   
2327    tmp=getMapArray(s,"locator",cnt);
2328    if(tmp==NULL)
2329      tmp=getMap(s,"locator");
2330    if(tmp!=NULL && strcasecmp(tmp->value,"NULL")!=0)
2331      xmlNewProp(nc,BAD_CAST "locator",BAD_CAST tmp->value);
2332
2333    tmp=getMapArray(s,"text",cnt);
2334    nc1 = xmlNewNode(ns, BAD_CAST "ExceptionText");
2335    if(tmp!=NULL){
2336      xmlNodePtr txt=xmlNewText(BAD_CAST tmp->value);
2337      xmlAddChild(nc1,txt);
2338    }
2339    else{
2340      xmlNodeSetContent(nc1, BAD_CAST _("No debug message available"));
2341    }
2342    xmlAddChild(nc,nc1);
2343    xmlAddChild(n,nc);
2344  }
2345  return n;
2346}
2347
2348/**
2349 * Print an OWS ExceptionReport.
2350 *
2351 * @param m the conf maps
2352 * @param message the error message
2353 * @param errorcode the error code
2354 * @param locator the potential locator
2355 */
2356int errorException(maps *m, const char *message, const char *errorcode, const char *locator) 
2357{
2358  map* errormap = createMap("text", message);
2359  addToMap(errormap,"code", errorcode);
2360  if(locator!=NULL)
2361    addToMap(errormap,"locator", locator);
2362  else
2363    addToMap(errormap,"locator", "NULL");
2364  printExceptionReportResponse(m,errormap);
2365  freeMap(&errormap);
2366  free(errormap);
2367  return -1;
2368}
2369
2370/**
2371 * Generate the output response (RawDataOutput or ResponseDocument)
2372 *
2373 * @param s the service structure containing the metadata information
2374 * @param request_inputs the inputs provided to the service for execution
2375 * @param request_outputs the outputs updated by the service execution
2376 * @param request_inputs1 the map containing the HTTP request
2377 * @param cpid the process identifier attached to a service execution
2378 * @param m the conf maps containing the main.cfg settings
2379 * @param res the value returned by the service execution
2380 */
2381void outputResponse(service* s,maps* request_inputs,maps* request_outputs,
2382                    map* request_inputs1,int cpid,maps* m,int res){
2383               
2384#ifdef DEBUG
2385  dumpMaps(request_inputs);
2386  dumpMaps(request_outputs);
2387  fprintf(stderr,"printProcessResponse\n");
2388#endif
2389  map* toto=getMap(request_inputs1,"RawDataOutput");
2390  int asRaw=0;
2391  if(toto!=NULL)
2392    asRaw=1;
2393  map* version=getMapFromMaps(m,"main","rversion");
2394  int vid=getVersionId(version->value);
2395  maps* tmpSess=getMaps(m,"senv");
2396  if(tmpSess!=NULL){
2397    map *_tmp=getMapFromMaps(m,"lenv","cookie");
2398    char* sessId=NULL;
2399    if(_tmp!=NULL){
2400      printf("Set-Cookie: %s; HttpOnly\r\n",_tmp->value);
2401      printf("P3P: CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"\r\n");
2402      char session_file_path[100];
2403      char *tmp1=strtok(_tmp->value,";");
2404      if(tmp1!=NULL)
2405        sprintf(session_file_path,"%s",strstr(tmp1,"=")+1);
2406      else
2407        sprintf(session_file_path,"%s",strstr(_tmp->value,"=")+1);
2408      sessId=strdup(session_file_path);
2409    }else{
2410      maps* t=getMaps(m,"senv");
2411      map*p=t->content;
2412      while(p!=NULL){
2413        if(strstr(p->name,"ID")!=NULL){
2414          sessId=strdup(p->value);
2415          break;
2416        }
2417        p=p->next;
2418      }
2419    }
2420    char session_file_path[1024];
2421    map *tmpPath=getMapFromMaps(m,"main","sessPath");
2422    if(tmpPath==NULL)
2423      tmpPath=getMapFromMaps(m,"main","tmpPath");
2424    sprintf(session_file_path,"%s/sess_%s.cfg",tmpPath->value,sessId);
2425    FILE* teste=fopen(session_file_path,"w");
2426    if(teste==NULL){
2427      char tmpMsg[1024];
2428      sprintf(tmpMsg,_("Unable to create the file \"%s\" for storing the session maps."),session_file_path);
2429      errorException(m,tmpMsg,"InternalError",NULL);
2430      return;
2431    }
2432    else{
2433      fclose(teste);
2434      dumpMapsToFile(tmpSess,session_file_path,1);
2435    }
2436  }
2437                 
2438  if(res==SERVICE_FAILED){
2439    map *lenv;
2440    lenv=getMapFromMaps(m,"lenv","message");
2441    char *tmp0;
2442    if(lenv!=NULL){
2443      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));
2444      sprintf(tmp0,_("Unable to run the Service. The message returned back by the Service was the following: %s"),lenv->value);
2445    }
2446    else{
2447      tmp0=(char*)malloc((strlen(_("Unable to run the Service. No more information was returned back by the Service."))+1)*sizeof(char));
2448      sprintf(tmp0,"%s",_("Unable to run the Service. No more information was returned back by the Service."));
2449    }
2450    errorException(m,tmp0,"InternalError",NULL);
2451    free(tmp0);
2452    return;
2453  }
2454
2455  if(res==SERVICE_ACCEPTED && vid==1){
2456    map* statusInfo=createMap("Status","Accepted");
2457    map *usid=getMapFromMaps(m,"lenv","usid");
2458    addToMap(statusInfo,"JobID",usid->value);
2459    printStatusInfo(m,statusInfo,(char*)"Execute");
2460    freeMap(&statusInfo);
2461    free(statusInfo);
2462    return;
2463  }
2464       
2465  map *tmp1=getMapFromMaps(m,"main","tmpPath");
2466  if(asRaw==0){
2467#ifdef DEBUG
2468    fprintf(stderr,"REQUEST_OUTPUTS FINAL\n");
2469    dumpMaps(request_outputs);
2470#endif
2471    maps* tmpI=request_outputs;
2472    maps* stmpI=NULL;
2473    map* usid=getMapFromMaps(m,"lenv","usid");
2474    int itn=0;
2475  NESTED0:
2476    while(tmpI!=NULL){
2477      if(tmpI->child!=NULL){
2478        stmpI=tmpI;
2479        tmpI=tmpI->child;
2480      }
2481#ifdef USE_MS
2482      map* testMap=getMap(tmpI->content,"useMapserver");       
2483#endif
2484      map *gfile=getMap(tmpI->content,"generated_file");
2485      char *file_name;
2486      if(gfile!=NULL){
2487        gfile=getMap(tmpI->content,"expected_generated_file");
2488        if(gfile==NULL){
2489          gfile=getMap(tmpI->content,"generated_file");
2490        }
2491        readGeneratedFile(m,tmpI->content,gfile->value);
2492        file_name=zStrdup((gfile->value)+strlen(tmp1->value));
2493      }
2494
2495      toto=getMap(tmpI->content,"asReference");
2496#ifdef USE_MS
2497      if(toto!=NULL && strcasecmp(toto->value,"true")==0 && testMap==NULL)
2498#else
2499      if(toto!=NULL && strcasecmp(toto->value,"true")==0)
2500#endif
2501        {
2502          elements* in=getElements(s->outputs,tmpI->name);
2503          if(in==NULL && s->outputs->child!=NULL){
2504            in=getElements(s->outputs->child,tmpI->name);
2505          }
2506          char *format=NULL;
2507          if(in!=NULL && in->format!=NULL){
2508            format=in->format;
2509          }else
2510            format=(char*)"LiteralData";
2511          if(format!=NULL && strcasecmp(format,"BoundingBoxData")==0){
2512            addToMap(tmpI->content,"extension","xml");
2513            addToMap(tmpI->content,"mimeType","text/xml");
2514            addToMap(tmpI->content,"encoding","UTF-8");
2515            addToMap(tmpI->content,"schema","http://schemas.opengis.net/ows/1.1.0/owsCommon.xsd");
2516          }
2517
2518          if(gfile==NULL) {
2519            map *ext=getMap(tmpI->content,"extension");
2520            char *file_path;
2521            char file_ext[32];
2522
2523            if( ext != NULL && ext->value != NULL) {
2524              strncpy(file_ext, ext->value, 32);
2525            }
2526            else {
2527              // Obtain default file extension (see mimetypes.h).             
2528              // If the MIME type is not recognized, txt is used as the default extension
2529              map* mtype=getMap(tmpI->content,"mimeType");
2530              getFileExtension(mtype != NULL ? mtype->value : NULL, file_ext, 32);
2531            }
2532
2533            file_name=(char*)malloc((strlen(s->name)+strlen(usid->value)+strlen(file_ext)+strlen(tmpI->name)+45)*sizeof(char));
2534            sprintf(file_name,"%s_%s_%s_%d.%s",s->name,tmpI->name,usid->value,itn,file_ext);
2535            itn++;
2536            file_path=(char*)malloc((strlen(tmp1->value)+strlen(file_name)+2)*sizeof(char));
2537            sprintf(file_path,"%s/%s",tmp1->value,file_name);
2538
2539            FILE *ofile=fopen(file_path,"wb");
2540            if(ofile==NULL){
2541              char tmpMsg[1024];
2542              sprintf(tmpMsg,_("Unable to create the file \"%s\" for storing the %s final result."),file_name,tmpI->name);
2543              errorException(m,tmpMsg,"InternalError",NULL);
2544              free(file_name);
2545              free(file_path);
2546              return;
2547            }
2548            free(file_path);
2549
2550            toto=getMap(tmpI->content,"value");
2551            if(strcasecmp(format,"BoundingBoxData")!=0){
2552              map* size=getMap(tmpI->content,"size");
2553              if(size!=NULL && toto!=NULL)
2554                fwrite(toto->value,1,(atoi(size->value))*sizeof(char),ofile);
2555              else
2556                if(toto!=NULL && toto->value!=NULL)
2557                  fwrite(toto->value,1,strlen(toto->value)*sizeof(char),ofile);
2558            }else{
2559              printBoundingBoxDocument(m,tmpI,ofile);
2560            }
2561            fclose(ofile);
2562
2563          }
2564
2565          map *tmp2=getMapFromMaps(m,"main","tmpUrl");
2566          map *tmp3=getMapFromMaps(m,"main","serverAddress");
2567          char *file_url;
2568          if(strncasecmp(tmp2->value,"http://",7)==0 ||
2569             strncasecmp(tmp2->value,"https://",8)==0){
2570            file_url=(char*)malloc((strlen(tmp2->value)+strlen(file_name)+2)*sizeof(char));
2571            sprintf(file_url,"%s/%s",tmp2->value,file_name);
2572          }else{
2573            file_url=(char*)malloc((strlen(tmp3->value)+strlen(tmp2->value)+strlen(file_name)+3)*sizeof(char));
2574            sprintf(file_url,"%s/%s/%s",tmp3->value,tmp2->value,file_name);
2575          }
2576          addToMap(tmpI->content,"Reference",file_url);
2577          free(file_name);
2578          free(file_url);
2579         
2580        }
2581#ifdef USE_MS
2582      else{
2583        if(testMap!=NULL){
2584          setReferenceUrl(m,tmpI);
2585        }
2586      }
2587#endif
2588      tmpI=tmpI->next;
2589    }
2590    if(stmpI!=NULL){
2591      tmpI=stmpI->next;
2592      stmpI=NULL;
2593      if(tmpI!=NULL)
2594        goto NESTED0;
2595    }
2596#ifdef DEBUG
2597    fprintf(stderr,"SERVICE : %s\n",s->name);
2598    dumpMaps(m);
2599#endif
2600    printProcessResponse(m,request_inputs1,cpid,
2601                         s, s->name,res,  // replace serviceProvider with serviceName in stored response file name
2602                         request_inputs,
2603                         request_outputs);
2604  }
2605  else{
2606    /**
2607     * We get the requested output or fallback to the first one if the
2608     * requested one is not present in the resulting outputs maps.
2609     */
2610    maps* tmpI=NULL;
2611    map* tmpIV=getMap(request_inputs1,"RawDataOutput");
2612    if(tmpIV!=NULL){
2613      tmpI=getMaps(request_outputs,tmpIV->value);         
2614    }
2615    if(tmpI==NULL)
2616      tmpI=request_outputs;
2617
2618    elements* e=getElements(s->outputs,tmpI->name);
2619    if(e!=NULL && strcasecmp(e->format,"BoundingBoxData")==0){
2620      printBoundingBoxDocument(m,tmpI,NULL);
2621    }else{
2622      map *gfile=getMap(tmpI->content,"generated_file");
2623      if(gfile!=NULL){
2624        gfile=getMap(tmpI->content,"expected_generated_file"); 
2625        if(gfile==NULL){
2626          gfile=getMap(tmpI->content,"generated_file");
2627        }
2628        readGeneratedFile(m,tmpI->content,gfile->value);
2629      }
2630      toto=getMap(tmpI->content,"value");       
2631      if(toto==NULL){
2632        char tmpMsg[1024];
2633        sprintf(tmpMsg,_("Wrong RawDataOutput parameter: unable to fetch any result for the given parameter name: \"%s\"."),tmpI->name);
2634        errorException(m,tmpMsg,"InvalidParameterValue","RawDataOutput");
2635        return;
2636      }   
2637      map* fname=getMapFromMaps(tmpI,tmpI->name,"filename");             
2638      if(fname!=NULL)
2639        printf("Content-Disposition: attachment; filename=\"%s\"\r\n",fname->value);
2640      map* rs=getMapFromMaps(tmpI,tmpI->name,"size");
2641      if(rs!=NULL)
2642        printf("Content-Length: %s\r\n",rs->value);
2643      printHeaders(m);
2644      char mime[1024];
2645      map* mi=getMap(tmpI->content,"mimeType");
2646#ifdef DEBUG
2647      fprintf(stderr,"SERVICE OUTPUTS\n");
2648      dumpMaps(request_outputs);
2649      fprintf(stderr,"SERVICE OUTPUTS\n");
2650#endif
2651      map* en=getMap(tmpI->content,"encoding");
2652      if(mi!=NULL && en!=NULL)
2653        sprintf(mime,
2654                "Content-Type: %s; charset=%s\r\nStatus: 200 OK\r\n\r\n",
2655                mi->value,en->value);
2656      else
2657        if(mi!=NULL)
2658          sprintf(mime,
2659                  "Content-Type: %s; charset=UTF-8\r\nStatus: 200 OK\r\n\r\n",
2660                  mi->value);
2661        else
2662          sprintf(mime,"Content-Type: text/plain; charset=utf-8\r\nStatus: 200 OK\r\n\r\n");
2663      printf("%s",mime);
2664      if(rs!=NULL)
2665        fwrite(toto->value,1,atoi(rs->value),stdout);
2666      else
2667        fwrite(toto->value,1,strlen(toto->value),stdout);
2668#ifdef DEBUG
2669      dumpMap(toto);
2670#endif
2671    }
2672  }
2673}
2674
2675/**
2676 * Create required XML nodes for boundingbox and update the current XML node
2677 *
2678 * @param ns_ows the ows XML namespace
2679 * @param n the XML node to update
2680 * @param boundingbox the map containing the boundingbox definition
2681 */
2682void printBoundingBox(xmlNsPtr ns_ows,xmlNodePtr n,map* boundingbox){
2683
2684  xmlNodePtr lw=NULL,uc=NULL;
2685
2686  map* tmp=getMap(boundingbox,"value");
2687
2688  tmp=getMap(boundingbox,"lowerCorner");
2689  if(tmp!=NULL){
2690    lw=xmlNewNode(ns_ows,BAD_CAST "LowerCorner");
2691    xmlAddChild(lw,xmlNewText(BAD_CAST tmp->value));
2692  }
2693
2694  tmp=getMap(boundingbox,"upperCorner");
2695  if(tmp!=NULL){
2696    uc=xmlNewNode(ns_ows,BAD_CAST "UpperCorner");
2697    xmlAddChild(uc,xmlNewText(BAD_CAST tmp->value));
2698  }
2699
2700  tmp=getMap(boundingbox,"crs");
2701  if(tmp!=NULL)
2702    xmlNewProp(n,BAD_CAST "crs",BAD_CAST tmp->value);
2703
2704  tmp=getMap(boundingbox,"dimensions");
2705  if(tmp!=NULL)
2706    xmlNewProp(n,BAD_CAST "dimensions",BAD_CAST tmp->value);
2707
2708  xmlAddChild(n,lw);
2709  xmlAddChild(n,uc);
2710
2711}
2712
2713/**
2714 * Parse a BoundingBox string
2715 *
2716 * [OGC 06-121r3](http://portal.opengeospatial.org/files/?artifact_id=20040):
2717 *  10.2 Bounding box
2718 *
2719 *
2720 * Value is provided as : lowerCorner,upperCorner,crs,dimension
2721 * Exemple : 189000,834000,285000,962000,urn:ogc:def:crs:OGC:1.3:CRS84
2722 *
2723 * A map to store boundingbox information should contain:
2724 *  - lowerCorner : double,double (minimum within this bounding box)
2725 *  - upperCorner : double,double (maximum within this bounding box)
2726 *  - crs : URI (Reference to definition of the CRS)
2727 *  - dimensions : int
2728 *
2729 * Note : support only 2D bounding box.
2730 *
2731 * @param value the char* containing the KVP bouding box
2732 * @return a map containing all the bounding box keys
2733 */
2734map* parseBoundingBox(const char* value){
2735  map *res=NULL;
2736  if(value!=NULL){
2737    char *cv,*cvp;
2738    cv=strtok_r((char*) value,",",&cvp);
2739    int cnt=0;
2740    int icnt=0;
2741    char *currentValue=NULL;
2742    while(cv){
2743      if(cnt<2)
2744        if(currentValue!=NULL){
2745          char *finalValue=(char*)malloc((strlen(currentValue)+strlen(cv)+1)*sizeof(char));
2746          sprintf(finalValue,"%s%s",currentValue,cv);
2747          switch(cnt){
2748          case 0:
2749            res=createMap("lowerCorner",finalValue);
2750            break;
2751          case 1:
2752            addToMap(res,"upperCorner",finalValue);
2753            icnt=-1;
2754            break;
2755          }
2756          cnt++;
2757          free(currentValue);
2758          currentValue=NULL;
2759          free(finalValue);
2760        }
2761        else{
2762          currentValue=(char*)malloc((strlen(cv)+2)*sizeof(char));
2763          sprintf(currentValue,"%s ",cv);
2764        }
2765      else
2766        if(cnt==2){
2767          addToMap(res,"crs",cv);
2768          cnt++;
2769        }
2770        else
2771          addToMap(res,"dimensions",cv);
2772      icnt++;
2773      cv=strtok_r(NULL,",",&cvp);
2774    }
2775  }
2776  return res;
2777}
2778
2779/**
2780 * Print an ows:BoundingBox XML document
2781 *
2782 * @param m the maps containing the settings of the main.cfg file
2783 * @param boundingbox the maps containing the boundingbox definition
2784 * @param file the file to print the BoundingBox (if NULL then print on stdout)
2785 * @see parseBoundingBox, printBoundingBox
2786 */
2787void printBoundingBoxDocument(maps* m,maps* boundingbox,FILE* file){
2788  if(file==NULL)
2789    rewind(stdout);
2790  xmlNodePtr n;
2791  xmlDocPtr doc;
2792  xmlNsPtr ns_ows,ns_xsi;
2793  xmlChar *xmlbuff;
2794  int buffersize;
2795  char *encoding=getEncoding(m);
2796  map *tmp;
2797  if(file==NULL){
2798    int pid=0;
2799    tmp=getMapFromMaps(m,"lenv","sid");
2800    if(tmp!=NULL)
2801      pid=atoi(tmp->value);
2802    if(pid==getpid()){
2803      printf("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding);
2804    }
2805    fflush(stdout);
2806  }
2807
2808  doc = xmlNewDoc(BAD_CAST "1.0");
2809  int owsId=zooXmlAddNs(NULL,"http://www.opengis.net/ows/1.1","ows");
2810  ns_ows=usedNs[owsId];
2811  n = xmlNewNode(ns_ows, BAD_CAST "BoundingBox");
2812  xmlNewNs(n,BAD_CAST "http://www.opengis.net/ows/1.1",BAD_CAST "ows");
2813  int xsiId=zooXmlAddNs(n,"http://www.w3.org/2001/XMLSchema-instance","xsi");
2814  ns_xsi=usedNs[xsiId];
2815  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");
2816  map *tmp1=getMap(boundingbox->content,"value");
2817  tmp=parseBoundingBox(tmp1->value);
2818  printBoundingBox(ns_ows,n,tmp);
2819  xmlDocSetRootElement(doc, n);
2820
2821  xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);
2822  if(file==NULL)
2823    printf("%s",xmlbuff);
2824  else{
2825    fprintf(file,"%s",xmlbuff);
2826  }
2827
2828  if(tmp!=NULL){
2829    freeMap(&tmp);
2830    free(tmp);
2831  }
2832  xmlFree(xmlbuff);
2833  xmlFreeDoc(doc);
2834  xmlCleanupParser();
2835  zooXmlCleanupNs();
2836 
2837}
2838
2839/**
2840 * Print a StatusInfo XML document.
2841 * a statusInfo map should contain the following keys:
2842 *  * JobID corresponding to usid key from the lenv section
2843 *  * Status the current state (Succeeded,Failed,Accepted,Running)
2844 *  * PercentCompleted (optional) the percent completed
2845 *  * Message (optional) any messages the service may wish to share
2846 *
2847 * @param conf the maps containing the settings of the main.cfg file
2848 * @param statusInfo the map containing the statusInfo definition
2849 * @param req the WPS requests (GetResult, GetStatus or Dismiss)
2850 */
2851void printStatusInfo(maps* conf,map* statusInfo,char* req){
2852  rewind(stdout);
2853  xmlNodePtr n,n1;
2854  xmlDocPtr doc;
2855  xmlNsPtr ns;
2856  xmlChar *xmlbuff;
2857  int buffersize;
2858  char *encoding=getEncoding(conf);
2859  map *tmp;
2860  int pid=0;
2861  printf("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding);
2862
2863  map* version=getMapFromMaps(conf,"main","rversion");
2864  int vid=getVersionId(version->value);
2865
2866  doc = xmlNewDoc(BAD_CAST "1.0");
2867  n1=printWPSHeader(doc,conf,req,"StatusInfo",version->value,1);
2868
2869  map* val=getMap(statusInfo,"JobID");
2870  int wpsId=zooXmlAddNs(NULL,schemas[vid][2],"wps");
2871  ns=usedNs[wpsId];
2872  n = xmlNewNode(ns, BAD_CAST "JobID");
2873  xmlAddChild(n,xmlNewText(BAD_CAST val->value));
2874
2875  xmlAddChild(n1,n);
2876
2877  val=getMap(statusInfo,"Status");
2878  n = xmlNewNode(ns, BAD_CAST "Status");
2879  xmlAddChild(n,xmlNewText(BAD_CAST val->value));
2880
2881  xmlAddChild(n1,n);
2882
2883  if(strncasecmp(val->value,"Failed",6)!=0 &&
2884     strncasecmp(val->value,"Succeeded",9)!=0){
2885    val=getMap(statusInfo,"PercentCompleted");
2886    if(val!=NULL){
2887      n = xmlNewNode(ns, BAD_CAST "PercentCompleted");
2888      xmlAddChild(n,xmlNewText(BAD_CAST val->value));
2889      xmlAddChild(n1,n);
2890    }
2891
2892    val=getMap(statusInfo,"Message");
2893    if(val!=NULL){   
2894      xmlAddChild(n1,xmlNewComment(BAD_CAST val->value));
2895    }
2896  }
2897  xmlDocSetRootElement(doc, n1);
2898
2899  xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);
2900  printf("%s",xmlbuff);
2901
2902  xmlFree(xmlbuff);
2903  xmlFreeDoc(doc);
2904  xmlCleanupParser();
2905  zooXmlCleanupNs();
2906 
2907}
2908
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