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

Last change on this file since 820 was 820, checked in by djay, 4 years ago

Fix issue with nested inputs initialization. Fix issue when returning nested outputs. Fix issue with ulinet.c for building the ZOO-Kernel (thanks to Niroshan Sanjaya and Julien Abt for reporting the issue).

  • 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    elements* e=getElements(s->outputs,tmpI->name);
2618    if(e!=NULL && strcasecmp(e->format,"BoundingBoxData")==0){
2619      printBoundingBoxDocument(m,tmpI,NULL);
2620    }else{
2621      map *gfile=getMap(tmpI->content,"generated_file");
2622      if(gfile!=NULL){
2623        gfile=getMap(tmpI->content,"expected_generated_file");
2624        if(gfile==NULL){
2625          gfile=getMap(tmpI->content,"generated_file");
2626        }
2627        readGeneratedFile(m,tmpI->content,gfile->value);
2628      }
2629      toto=getMap(tmpI->content,"value");
2630      if(toto==NULL){
2631        char tmpMsg[1024];
2632        sprintf(tmpMsg,_("Wrong RawDataOutput parameter: unable to fetch any result for the given parameter name: \"%s\"."),tmpI->name);
2633        errorException(m,tmpMsg,"InvalidParameterValue","RawDataOutput");
2634        return;
2635      }
2636      map* fname=getMapFromMaps(tmpI,tmpI->name,"filename");
2637      if(fname!=NULL)
2638        printf("Content-Disposition: attachment; filename=\"%s\"\r\n",fname->value);
2639      map* rs=getMapFromMaps(tmpI,tmpI->name,"size");
2640      if(rs!=NULL)
2641        printf("Content-Length: %s\r\n",rs->value);
2642      printHeaders(m);
2643      char mime[1024];
2644      map* mi=getMap(tmpI->content,"mimeType");
2645#ifdef DEBUG
2646      fprintf(stderr,"SERVICE OUTPUTS\n");
2647      dumpMaps(request_outputs);
2648      fprintf(stderr,"SERVICE OUTPUTS\n");
2649#endif
2650      map* en=getMap(tmpI->content,"encoding");
2651      if(mi!=NULL && en!=NULL)
2652        sprintf(mime,
2653                "Content-Type: %s; charset=%s\r\nStatus: 200 OK\r\n\r\n",
2654                mi->value,en->value);
2655      else
2656        if(mi!=NULL)
2657          sprintf(mime,
2658                  "Content-Type: %s; charset=UTF-8\r\nStatus: 200 OK\r\n\r\n",
2659                  mi->value);
2660        else
2661          sprintf(mime,"Content-Type: text/plain; charset=utf-8\r\nStatus: 200 OK\r\n\r\n");
2662      printf("%s",mime);
2663      if(rs!=NULL)
2664        fwrite(toto->value,1,atoi(rs->value),stdout);
2665      else
2666        fwrite(toto->value,1,strlen(toto->value),stdout);
2667#ifdef DEBUG
2668      dumpMap(toto);
2669#endif
2670    }
2671  }
2672}
2673
2674/**
2675 * Create required XML nodes for boundingbox and update the current XML node
2676 *
2677 * @param ns_ows the ows XML namespace
2678 * @param n the XML node to update
2679 * @param boundingbox the map containing the boundingbox definition
2680 */
2681void printBoundingBox(xmlNsPtr ns_ows,xmlNodePtr n,map* boundingbox){
2682
2683  xmlNodePtr lw=NULL,uc=NULL;
2684
2685  map* tmp=getMap(boundingbox,"value");
2686
2687  tmp=getMap(boundingbox,"lowerCorner");
2688  if(tmp!=NULL){
2689    lw=xmlNewNode(ns_ows,BAD_CAST "LowerCorner");
2690    xmlAddChild(lw,xmlNewText(BAD_CAST tmp->value));
2691  }
2692
2693  tmp=getMap(boundingbox,"upperCorner");
2694  if(tmp!=NULL){
2695    uc=xmlNewNode(ns_ows,BAD_CAST "UpperCorner");
2696    xmlAddChild(uc,xmlNewText(BAD_CAST tmp->value));
2697  }
2698
2699  tmp=getMap(boundingbox,"crs");
2700  if(tmp!=NULL)
2701    xmlNewProp(n,BAD_CAST "crs",BAD_CAST tmp->value);
2702
2703  tmp=getMap(boundingbox,"dimensions");
2704  if(tmp!=NULL)
2705    xmlNewProp(n,BAD_CAST "dimensions",BAD_CAST tmp->value);
2706
2707  xmlAddChild(n,lw);
2708  xmlAddChild(n,uc);
2709
2710}
2711
2712/**
2713 * Parse a BoundingBox string
2714 *
2715 * [OGC 06-121r3](http://portal.opengeospatial.org/files/?artifact_id=20040):
2716 *  10.2 Bounding box
2717 *
2718 *
2719 * Value is provided as : lowerCorner,upperCorner,crs,dimension
2720 * Exemple : 189000,834000,285000,962000,urn:ogc:def:crs:OGC:1.3:CRS84
2721 *
2722 * A map to store boundingbox information should contain:
2723 *  - lowerCorner : double,double (minimum within this bounding box)
2724 *  - upperCorner : double,double (maximum within this bounding box)
2725 *  - crs : URI (Reference to definition of the CRS)
2726 *  - dimensions : int
2727 *
2728 * Note : support only 2D bounding box.
2729 *
2730 * @param value the char* containing the KVP bouding box
2731 * @return a map containing all the bounding box keys
2732 */
2733map* parseBoundingBox(const char* value){
2734  map *res=NULL;
2735  if(value!=NULL){
2736    char *cv,*cvp;
2737    cv=strtok_r((char*) value,",",&cvp);
2738    int cnt=0;
2739    int icnt=0;
2740    char *currentValue=NULL;
2741    while(cv){
2742      if(cnt<2)
2743        if(currentValue!=NULL){
2744          char *finalValue=(char*)malloc((strlen(currentValue)+strlen(cv)+1)*sizeof(char));
2745          sprintf(finalValue,"%s%s",currentValue,cv);
2746          switch(cnt){
2747          case 0:
2748            res=createMap("lowerCorner",finalValue);
2749            break;
2750          case 1:
2751            addToMap(res,"upperCorner",finalValue);
2752            icnt=-1;
2753            break;
2754          }
2755          cnt++;
2756          free(currentValue);
2757          currentValue=NULL;
2758          free(finalValue);
2759        }
2760        else{
2761          currentValue=(char*)malloc((strlen(cv)+2)*sizeof(char));
2762          sprintf(currentValue,"%s ",cv);
2763        }
2764      else
2765        if(cnt==2){
2766          addToMap(res,"crs",cv);
2767          cnt++;
2768        }
2769        else
2770          addToMap(res,"dimensions",cv);
2771      icnt++;
2772      cv=strtok_r(NULL,",",&cvp);
2773    }
2774  }
2775  return res;
2776}
2777
2778/**
2779 * Print an ows:BoundingBox XML document
2780 *
2781 * @param m the maps containing the settings of the main.cfg file
2782 * @param boundingbox the maps containing the boundingbox definition
2783 * @param file the file to print the BoundingBox (if NULL then print on stdout)
2784 * @see parseBoundingBox, printBoundingBox
2785 */
2786void printBoundingBoxDocument(maps* m,maps* boundingbox,FILE* file){
2787  if(file==NULL)
2788    rewind(stdout);
2789  xmlNodePtr n;
2790  xmlDocPtr doc;
2791  xmlNsPtr ns_ows,ns_xsi;
2792  xmlChar *xmlbuff;
2793  int buffersize;
2794  char *encoding=getEncoding(m);
2795  map *tmp;
2796  if(file==NULL){
2797    int pid=0;
2798    tmp=getMapFromMaps(m,"lenv","sid");
2799    if(tmp!=NULL)
2800      pid=atoi(tmp->value);
2801    if(pid==getpid()){
2802      printf("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding);
2803    }
2804    fflush(stdout);
2805  }
2806
2807  doc = xmlNewDoc(BAD_CAST "1.0");
2808  int owsId=zooXmlAddNs(NULL,"http://www.opengis.net/ows/1.1","ows");
2809  ns_ows=usedNs[owsId];
2810  n = xmlNewNode(ns_ows, BAD_CAST "BoundingBox");
2811  xmlNewNs(n,BAD_CAST "http://www.opengis.net/ows/1.1",BAD_CAST "ows");
2812  int xsiId=zooXmlAddNs(n,"http://www.w3.org/2001/XMLSchema-instance","xsi");
2813  ns_xsi=usedNs[xsiId];
2814  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");
2815  map *tmp1=getMap(boundingbox->content,"value");
2816  tmp=parseBoundingBox(tmp1->value);
2817  printBoundingBox(ns_ows,n,tmp);
2818  xmlDocSetRootElement(doc, n);
2819
2820  xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);
2821  if(file==NULL)
2822    printf("%s",xmlbuff);
2823  else{
2824    fprintf(file,"%s",xmlbuff);
2825  }
2826
2827  if(tmp!=NULL){
2828    freeMap(&tmp);
2829    free(tmp);
2830  }
2831  xmlFree(xmlbuff);
2832  xmlFreeDoc(doc);
2833  xmlCleanupParser();
2834  zooXmlCleanupNs();
2835 
2836}
2837
2838/**
2839 * Print a StatusInfo XML document.
2840 * a statusInfo map should contain the following keys:
2841 *  * JobID corresponding to usid key from the lenv section
2842 *  * Status the current state (Succeeded,Failed,Accepted,Running)
2843 *  * PercentCompleted (optional) the percent completed
2844 *  * Message (optional) any messages the service may wish to share
2845 *
2846 * @param conf the maps containing the settings of the main.cfg file
2847 * @param statusInfo the map containing the statusInfo definition
2848 * @param req the WPS requests (GetResult, GetStatus or Dismiss)
2849 */
2850void printStatusInfo(maps* conf,map* statusInfo,char* req){
2851  rewind(stdout);
2852  xmlNodePtr n,n1;
2853  xmlDocPtr doc;
2854  xmlNsPtr ns;
2855  xmlChar *xmlbuff;
2856  int buffersize;
2857  char *encoding=getEncoding(conf);
2858  map *tmp;
2859  int pid=0;
2860  printf("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding);
2861
2862  map* version=getMapFromMaps(conf,"main","rversion");
2863  int vid=getVersionId(version->value);
2864
2865  doc = xmlNewDoc(BAD_CAST "1.0");
2866  n1=printWPSHeader(doc,conf,req,"StatusInfo",version->value,1);
2867
2868  map* val=getMap(statusInfo,"JobID");
2869  int wpsId=zooXmlAddNs(NULL,schemas[vid][2],"wps");
2870  ns=usedNs[wpsId];
2871  n = xmlNewNode(ns, BAD_CAST "JobID");
2872  xmlAddChild(n,xmlNewText(BAD_CAST val->value));
2873
2874  xmlAddChild(n1,n);
2875
2876  val=getMap(statusInfo,"Status");
2877  n = xmlNewNode(ns, BAD_CAST "Status");
2878  xmlAddChild(n,xmlNewText(BAD_CAST val->value));
2879
2880  xmlAddChild(n1,n);
2881
2882  if(strncasecmp(val->value,"Failed",6)!=0 &&
2883     strncasecmp(val->value,"Succeeded",9)!=0){
2884    val=getMap(statusInfo,"PercentCompleted");
2885    if(val!=NULL){
2886      n = xmlNewNode(ns, BAD_CAST "PercentCompleted");
2887      xmlAddChild(n,xmlNewText(BAD_CAST val->value));
2888      xmlAddChild(n1,n);
2889    }
2890
2891    val=getMap(statusInfo,"Message");
2892    if(val!=NULL){   
2893      xmlAddChild(n1,xmlNewComment(BAD_CAST val->value));
2894    }
2895  }
2896  xmlDocSetRootElement(doc, n1);
2897
2898  xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);
2899  printf("%s",xmlbuff);
2900
2901  xmlFree(xmlbuff);
2902  xmlFreeDoc(doc);
2903  xmlCleanupParser();
2904  zooXmlCleanupNs();
2905 
2906}
2907
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