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

Last change on this file since 896 was 896, checked in by knut, 5 years ago

Added some recent changes from trunk (r889), including some new utility functions and exception handling and new (conditional) definition of type bool. Added some new logic concerning Python and Mono environment and search paths. Fixed problem with Mono updateStatus function. Changed response_print.h to #include locale.h unconditionally and xlocale.h conditionally; xlocale.h is non-standard and can probably be dropped.

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