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

Last change on this file since 888 was 888, checked in by djay, 5 years ago

Add support for output style definition depending on geometry type (msStylePoly, msStylePoint, msStrylLine). Upload shared data in remote_persitent_data_path rather than remote_data_path (used for not shared data). In case output data should be published and the data is empty (nb_pixels or nb_features is set to 0) then, the ZOO-Kernel returns an ExceptionReport? with an Exception for every output.

  • Property svn:keywords set to Id
File size: 93.4 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=strdup(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]=strdup(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]=strdup(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]=strdup("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]=strdup("soap");
262    usedNs[nbNs]=xmlNewNs(nr,BAD_CAST "http://www.w3.org/2003/05/soap-envelope",BAD_CAST "soap");
263    nbNs++;
264    nsName[nbNs]=strdup("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 = strdup(tmp->value);
597    }
598    else
599      SERVICE_URL = strdup("not_defined");
600  }
601  else
602    SERVICE_URL = strdup("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=strdup(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=strdup(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
2030  if(vid==0 && 
2031     hasStoredExecuteResponse==true 
2032     && status!=SERVICE_STARTED
2033#ifndef WIN32
2034     && status!=SERVICE_ACCEPTED
2035#endif
2036     ){
2037#ifndef RELY_ON_DB
2038    semid lid=acquireLock(m);//,1);
2039    if(lid<0){
2040      /* If the lock failed */
2041      errorException(m,_("Lock failed."),"InternalError",NULL);
2042      xmlFreeDoc(doc);
2043      xmlCleanupParser();
2044      zooXmlCleanupNs();
2045      return;
2046    }
2047    else{
2048#endif
2049      /* We need to write the ExecuteResponse Document somewhere */
2050      FILE* output=fopen(stored_path,"w");
2051      if(output==NULL){
2052        /* If the file cannot be created return an ExceptionReport */
2053        char tmpMsg[1024];
2054        sprintf(tmpMsg,_("Unable to create the file \"%s\" for storing the ExecuteResponse."),stored_path);
2055
2056        errorException(m,tmpMsg,"InternalError",NULL);
2057        xmlFreeDoc(doc);
2058        xmlCleanupParser();
2059        zooXmlCleanupNs();
2060#ifndef RELY_ON_DB
2061        unlockShm(lid);
2062#endif
2063        return;
2064      }
2065      xmlChar *xmlbuff;
2066      int buffersize;
2067      xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, "UTF-8", 1);
2068      fwrite(xmlbuff,1,xmlStrlen(xmlbuff)*sizeof(char),output);
2069      xmlFree(xmlbuff);
2070      fclose(output);
2071#ifndef RELY_ON_DB
2072#ifdef DEBUG
2073      fprintf(stderr,"UNLOCK %s %d !\n",__FILE__,__LINE__);
2074#endif
2075      unlockShm(lid);
2076      map* v=getMapFromMaps(m,"lenv","sid");
2077      // Remove the lock when running as a normal task
2078      if(getpid()==atoi(v->value)){
2079        removeShmLock (m, 1);
2080      }
2081    }
2082#endif
2083  }
2084
2085  printDocument(m,doc,pid);
2086
2087  xmlCleanupParser();
2088  zooXmlCleanupNs();
2089}
2090
2091/**
2092 * Print a XML document.
2093 *
2094 * @param m the conf maps containing the main.cfg settings
2095 * @param doc the XML document
2096 * @param pid the process identifier linked to a service
2097 */
2098void printDocument(maps* m, xmlDocPtr doc,int pid){
2099  char *encoding=getEncoding(m);
2100  if(pid==getpid()){
2101    printHeaders(m);
2102    printf("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding);
2103  }
2104  fflush(stdout);
2105  xmlChar *xmlbuff;
2106  int buffersize;
2107  /*
2108   * Dump the document to a buffer and print it on stdout
2109   * for demonstration purposes.
2110   */
2111  xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);
2112  printf("%s",xmlbuff);
2113  fflush(stdout);
2114  /*
2115   * Free associated memory.
2116   */
2117  xmlFree(xmlbuff);
2118  xmlFreeDoc(doc);
2119  xmlCleanupParser();
2120  zooXmlCleanupNs();
2121}
2122
2123/**
2124 * Print a XML document.
2125 *
2126 * @param doc the XML document (unused)
2127 * @param nc the XML node to add the output definition
2128 * @param ns_wps the wps XML namespace
2129 * @param ns_ows the ows XML namespace
2130 * @param e the output elements
2131 * @param m the conf maps containing the main.cfg settings
2132 * @param type the type (unused)
2133 */
2134void printOutputDefinitions(xmlDocPtr doc,xmlNodePtr nc,xmlNsPtr ns_wps,xmlNsPtr ns_ows,elements* e,maps* m,const char* type){
2135  xmlNodePtr nc1;
2136  nc1=xmlNewNode(ns_wps, BAD_CAST type);
2137  map *tmp=NULL; 
2138  if(e!=NULL && e->defaults!=NULL)
2139    tmp=e->defaults->content;
2140  else{
2141    /*
2142      dumpElements(e);
2143    */
2144    return;
2145  }
2146  while(tmp!=NULL){
2147    if(strncasecmp(tmp->name,"MIMETYPE",strlen(tmp->name))==0
2148       || strncasecmp(tmp->name,"ENCODING",strlen(tmp->name))==0
2149       || strncasecmp(tmp->name,"SCHEMA",strlen(tmp->name))==0
2150       || strncasecmp(tmp->name,"UOM",strlen(tmp->name))==0)
2151      xmlNewProp(nc1,BAD_CAST tmp->name,BAD_CAST tmp->value);
2152    tmp=tmp->next;
2153  }
2154  tmp=getMap(e->defaults->content,"asReference");
2155  if(tmp==NULL)
2156    xmlNewProp(nc1,BAD_CAST "asReference",BAD_CAST "false");
2157
2158  tmp=e->content;
2159
2160  printDescription(nc1,ns_ows,m->name,e->content,0);
2161
2162  xmlAddChild(nc,nc1);
2163
2164}
2165
2166/**
2167 * Generate XML nodes describing inputs or outputs metadata.
2168 *
2169 * @param doc the XML document
2170 * @param nc the XML node to add the definition
2171 * @param ns_wps the wps namespace
2172 * @param ns_ows the ows namespace
2173 * @param ns_xlink the xlink namespace
2174 * @param e the output elements
2175 * @param m the conf maps containing the main.cfg settings
2176 * @param type the type
2177 */
2178void printIOType(xmlDocPtr doc,xmlNodePtr nc,xmlNsPtr ns_wps,xmlNsPtr ns_ows,xmlNsPtr ns_xlink,elements* e,maps* m,const char* type,int vid){
2179
2180  xmlNodePtr nc1,nc2,nc3;
2181  nc1=xmlNewNode(ns_wps, BAD_CAST type);
2182  map *tmp=NULL;
2183  if(e!=NULL)
2184    tmp=e->content;
2185  else
2186    tmp=m->content;
2187
2188  if(vid==0){
2189    nc2=xmlNewNode(ns_ows, BAD_CAST "Identifier");
2190    if(e!=NULL)
2191      nc3=xmlNewText(BAD_CAST e->name);
2192    else
2193      nc3=xmlNewText(BAD_CAST m->name);
2194   
2195    xmlAddChild(nc2,nc3);
2196    xmlAddChild(nc1,nc2);
2197 
2198    xmlAddChild(nc,nc1);
2199
2200    if(e!=NULL)
2201      tmp=getMap(e->content,"Title");
2202    else
2203      tmp=getMap(m->content,"Title");
2204   
2205    if(tmp!=NULL){
2206      nc2=xmlNewNode(ns_ows, BAD_CAST tmp->name);
2207      nc3=xmlNewText(BAD_CAST _ss(tmp->value));
2208      xmlAddChild(nc2,nc3); 
2209      xmlAddChild(nc1,nc2);
2210    }
2211
2212    if(e!=NULL)
2213      tmp=getMap(e->content,"Abstract");
2214    else
2215      tmp=getMap(m->content,"Abstract");
2216
2217    if(tmp!=NULL){
2218      nc2=xmlNewNode(ns_ows, BAD_CAST tmp->name);
2219      nc3=xmlNewText(BAD_CAST _ss(tmp->value));
2220      xmlAddChild(nc2,nc3); 
2221      xmlAddChild(nc1,nc2);
2222      xmlAddChild(nc,nc1);
2223    }
2224  }else{
2225    xmlNewProp(nc1,BAD_CAST "id",BAD_CAST (e!=NULL?e->name:m->name));
2226  }
2227
2228  // IO type nested outputs
2229  if(m->child!=NULL){
2230    maps* curs=m->child;
2231    elements* ecurs=getElements(e,(e!=NULL?e->name:m->name));
2232    ecurs=ecurs->child;
2233    while(curs!=NULL/* && ecurs!=NULL*/){
2234      ecurs=getElements(ecurs,(curs->name));
2235      map* inRequest=getMap(curs->content,"inRequest");
2236      if(inRequest!=NULL && strncasecmp(inRequest->value,"true",4)==0)
2237        printIOType(doc,nc1,ns_wps,ns_ows,ns_xlink,ecurs,curs,type,vid);
2238      curs=curs->next;
2239      ecurs=getElements(e,(e!=NULL?e->name:m->name));
2240      ecurs=ecurs->child;
2241    }
2242  }
2243  else{
2244    map *tmpMap=getMap(m->content,"Reference");
2245    if(tmpMap==NULL){
2246      nc2=xmlNewNode(ns_wps, BAD_CAST "Data");
2247      if(e!=NULL && e->format!=NULL){
2248        if(strncasecmp(e->format,"LiteralOutput",strlen(e->format))==0)
2249          nc3=xmlNewNode(ns_wps, BAD_CAST "LiteralData");
2250        else
2251          if(strncasecmp(e->format,"ComplexOutput",strlen(e->format))==0)
2252            nc3=xmlNewNode(ns_wps, BAD_CAST "ComplexData");
2253          else if(strncasecmp(e->format,"BoundingBoxOutput",strlen(e->format))==0)
2254            nc3=xmlNewNode(ns_wps, BAD_CAST "BoundingBoxData");
2255          else
2256            nc3=xmlNewNode(ns_wps, BAD_CAST e->format);
2257      }
2258      else {
2259        map* tmpV=getMapFromMaps(m,"format","value");
2260        if(tmpV!=NULL)
2261          nc3=xmlNewNode(ns_wps, BAD_CAST tmpV->value);
2262        else
2263          nc3=xmlNewNode(ns_wps, BAD_CAST "LiteralData");
2264      } 
2265      tmp=m->content;
2266     
2267      while(tmp!=NULL){
2268        if(strcasecmp(tmp->name,"mimeType")==0 ||
2269           strcasecmp(tmp->name,"encoding")==0 ||
2270           strcasecmp(tmp->name,"schema")==0 ||
2271           strcasecmp(tmp->name,"datatype")==0 ||
2272           strcasecmp(tmp->name,"uom")==0) {
2273         
2274          if(vid==0)
2275            xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST tmp->value);
2276          else{
2277            if(strcasecmp(tmp->name,"datatype")==0)
2278              xmlNewProp(nc2,BAD_CAST "mimeType",BAD_CAST "text/plain");
2279            else
2280              if(strcasecmp(tmp->name,"uom")!=0)
2281                xmlNewProp(nc2,BAD_CAST tmp->name,BAD_CAST tmp->value);
2282          }
2283        }
2284        if(vid==0)
2285          xmlAddChild(nc2,nc3);
2286        tmp=tmp->next;
2287      }
2288      if(e!=NULL && e->format!=NULL && strcasecmp(e->format,"BoundingBoxData")==0) {
2289        map* bb=getMap(m->content,"value");
2290        if(bb!=NULL) {
2291          map* tmpRes=parseBoundingBox(bb->value);
2292          printBoundingBox(ns_ows,nc3,tmpRes);
2293          freeMap(&tmpRes);
2294          free(tmpRes);
2295        }
2296      }
2297      else {
2298        if(e!=NULL)
2299          tmp=getMap(e->defaults->content,"mimeType");
2300        else
2301          tmp=NULL;
2302       
2303        map* tmp1=getMap(m->content,"encoding");
2304        map* tmp2=getMap(m->content,"mimeType");
2305        map* tmp3=getMap(m->content,"value");
2306        int hasValue=1;
2307        if(tmp3==NULL){
2308          tmp3=createMap("value","");
2309          hasValue=-1;
2310        }
2311       
2312        if( ( tmp1 != NULL && strncmp(tmp1->value,"base64",6) == 0 )     // if encoding is base64
2313            ||                                                         // or if
2314            ( tmp2 != NULL && ( strstr(tmp2->value,"text") == NULL       //  mime type is not text
2315                                &&                                       //  nor
2316                                strstr(tmp2->value,"xml") == NULL        //  xml
2317                                &&                                       // nor
2318                                strstr(tmp2->value,"javascript") == NULL // javascript
2319                                &&
2320                                strstr(tmp2->value,"json") == NULL
2321                                &&
2322                                strstr(tmp2->value,"ecmascript") == NULL
2323                                &&
2324                                // include for backwards compatibility,
2325                                // although correct mime type is ...kml+xml:
2326                                strstr(tmp2->value,"google-earth.kml") == NULL                                                  )
2327              )
2328            ) {                                                          // then       
2329          map* rs=getMap(m->content,"size");                       // obtain size
2330          bool isSized=true;
2331          if(rs==NULL){
2332            char tmp1[1024];
2333            sprintf(tmp1,"%ld",strlen(tmp3->value));
2334            rs=createMap("size",tmp1);
2335            isSized=false;
2336          }
2337         
2338          xmlAddChild((vid==0?nc3:nc2),xmlNewText(BAD_CAST base64(tmp3->value, atoi(rs->value))));  // base 64 encode in XML
2339         
2340          if(tmp1==NULL || (tmp1!=NULL && strncmp(tmp1->value,"base64",6)!=0)) {
2341            xmlAttrPtr ap = xmlHasProp((vid==0?nc3:nc2), BAD_CAST "encoding");
2342            if (ap != NULL) {
2343              xmlRemoveProp(ap);
2344            }                   
2345            xmlNewProp((vid==0?nc3:nc2),BAD_CAST "encoding",BAD_CAST "base64");
2346          }
2347         
2348          if(!isSized){
2349            freeMap(&rs);
2350            free(rs);
2351          }
2352        }
2353        else if (tmp2!=NULL) {                                 // else (text-based format)
2354          if(strstr(tmp2->value, "javascript") != NULL ||      //    if javascript put code in CDATA block
2355             strstr(tmp2->value, "json") != NULL ||            //    (will not be parsed by XML reader)
2356             strstr(tmp2->value, "ecmascript") != NULL
2357             ) {
2358            xmlAddChild((vid==0?nc3:nc2),xmlNewCDataBlock(doc,BAD_CAST tmp3->value,strlen(tmp3->value)));
2359          }   
2360          else {                                                     // else
2361            if (strstr(tmp2->value, "xml") != NULL ||                 // if XML-based format
2362                // include for backwards compatibility,
2363                // although correct mime type is ...kml+xml:               
2364                strstr(tmp2->value, "google-earth.kml") != NULL
2365                ) { 
2366             
2367              int li=zooXmlAddDoc(tmp3->value);
2368              xmlDocPtr doc = iDocs[li];
2369              xmlNodePtr ir = xmlDocGetRootElement(doc);
2370              xmlAddChild((vid==0?nc3:nc2),ir);
2371            }
2372            else                                                     // else   
2373              xmlAddChild((vid==0?nc3:nc2),xmlNewText(BAD_CAST tmp3->value));    //   add text node
2374          }
2375          xmlAddChild(nc2,nc3);
2376        }
2377        else {
2378          xmlAddChild((vid==0?nc3:nc2),xmlNewText(BAD_CAST tmp3->value));
2379        }
2380       
2381        if(hasValue<0) {
2382          freeMap(&tmp3);
2383          free(tmp3);
2384        }
2385      }
2386    }
2387    else { // Reference
2388      tmpMap=getMap(m->content,"Reference");
2389      nc3=nc2=xmlNewNode(ns_wps, BAD_CAST "Reference");
2390      /* Special case to avoid failing to validate against the WPS 2.0 schema */
2391      if(strcasecmp(type,"Output")==0 && vid==0)
2392        xmlNewProp(nc3,BAD_CAST "href",BAD_CAST tmpMap->value);
2393      else
2394        xmlNewNsProp(nc3,ns_xlink,BAD_CAST "href",BAD_CAST tmpMap->value);
2395     
2396      tmp=m->content;
2397      while(tmp!=NULL) {
2398        if(strcasecmp(tmp->name,"mimeType")==0 ||
2399           strcasecmp(tmp->name,"encoding")==0 ||
2400           strcasecmp(tmp->name,"schema")==0 ||
2401           strcasecmp(tmp->name,"datatype")==0 ||
2402           strcasecmp(tmp->name,"uom")==0){
2403         
2404          if(strcasecmp(tmp->name,"datatype")==0)
2405            xmlNewProp(nc3,BAD_CAST "mimeType",BAD_CAST "text/plain");
2406          else
2407            xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST tmp->value);
2408        }
2409        tmp=tmp->next;
2410        xmlAddChild(nc2,nc3);
2411      }
2412    }
2413    xmlAddChild(nc1,nc2);
2414  }
2415  xmlAddChild(nc,nc1);
2416}
2417
2418/**
2419 * Create XML node with basic ows metadata information (Identifier,Title,Abstract)
2420 *
2421 * @param root the root XML node to add the description
2422 * @param ns_ows the ows XML namespace
2423 * @param identifier the identifier to use
2424 * @param amap the map containing the ows metadata information
2425 */
2426void printDescription(xmlNodePtr root,xmlNsPtr ns_ows,const char* identifier,map* amap,int vid=0){
2427  xmlNodePtr nc2;
2428  if(vid==0){
2429    nc2 = xmlNewNode(ns_ows, BAD_CAST "Identifier");
2430    xmlAddChild(nc2,xmlNewText(BAD_CAST identifier));
2431    xmlAddChild(root,nc2);
2432  }
2433  map* tmp=amap;
2434  const char *tmp2[2];
2435  tmp2[0]="Title";
2436  tmp2[1]="Abstract";
2437  int j=0;
2438  for(j=0;j<2;j++){
2439    map* tmp1=getMap(tmp,tmp2[j]);
2440    if(tmp1!=NULL){
2441      nc2 = xmlNewNode(ns_ows, BAD_CAST tmp2[j]);
2442      xmlAddChild(nc2,xmlNewText(BAD_CAST _ss(tmp1->value)));
2443      xmlAddChild(root,nc2);
2444    }
2445  }
2446  if(vid==1){
2447    nc2 = xmlNewNode(ns_ows, BAD_CAST "Identifier");
2448    xmlAddChild(nc2,xmlNewText(BAD_CAST identifier));
2449    xmlAddChild(root,nc2);
2450  }
2451}
2452
2453/**
2454 * Print an OWS ExceptionReport Document and HTTP headers (when required)
2455 * depending on the code.
2456 * Set hasPrinted value to true in the [lenv] section.
2457 *
2458 * @param m the maps containing the settings of the main.cfg file
2459 * @param s the map containing the text,code,locator keys (or a map array of the same keys)
2460 */
2461void printExceptionReportResponse(maps* m,map* s){
2462  if(getMapFromMaps(m,"lenv","hasPrinted")!=NULL)
2463    return;
2464  int buffersize;
2465  xmlDocPtr doc;
2466  xmlChar *xmlbuff;
2467  xmlNodePtr n;
2468
2469  zooXmlCleanupNs();
2470  doc = xmlNewDoc(BAD_CAST "1.0");
2471  maps* tmpMap=getMaps(m,"main");
2472  char *encoding=getEncoding(tmpMap);
2473  const char *exceptionCode;
2474 
2475  map* tmp=getMap(s,"code");
2476  if(tmp!=NULL){
2477    if(strcmp(tmp->value,"OperationNotSupported")==0 ||
2478       strcmp(tmp->value,"NoApplicableCode")==0)
2479      exceptionCode="501 Not Implemented";
2480    else
2481      if(strcmp(tmp->value,"MissingParameterValue")==0 ||
2482         strcmp(tmp->value,"InvalidUpdateSequence")==0 ||
2483         strcmp(tmp->value,"OptionNotSupported")==0 ||
2484         strcmp(tmp->value,"VersionNegotiationFailed")==0 ||
2485         strcmp(tmp->value,"InvalidParameterValue")==0)
2486        exceptionCode="400 Bad request";
2487      else
2488        exceptionCode="501 Internal Server Error";
2489  }
2490  else
2491    exceptionCode="501 Internal Server Error";
2492  tmp=getMapFromMaps(m,"lenv","status_code");
2493  if(tmp!=NULL)
2494    exceptionCode=tmp->value;
2495  if(m!=NULL){
2496    map *tmpSid=getMapFromMaps(m,"lenv","sid");
2497    if(tmpSid!=NULL){
2498      if( getpid()==atoi(tmpSid->value) ){
2499        printHeaders(m);
2500        printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode);
2501      }
2502    }
2503    else{
2504      printHeaders(m);
2505      printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode);
2506    }
2507  }else{
2508    printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode);
2509  }
2510  n=createExceptionReportNode(m,s,1);
2511  xmlDocSetRootElement(doc, n);
2512  xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);
2513  printf("%s",xmlbuff);
2514  fflush(stdout);
2515  xmlFreeDoc(doc);
2516  xmlFree(xmlbuff);
2517  xmlCleanupParser();
2518  zooXmlCleanupNs();
2519  if(m!=NULL)
2520    setMapInMaps(m,"lenv","hasPrinted","true");
2521}
2522
2523/**
2524 * Create an OWS ExceptionReport Node.
2525 *
2526 * @param m the conf maps
2527 * @param s the map containing the text,code,locator keys
2528 * @param use_ns (0/1) choose if you want to generate an ExceptionReport or
2529 *  ows:ExceptionReport node respectively
2530 * @return the ExceptionReport/ows:ExceptionReport node
2531 */
2532xmlNodePtr createExceptionReportNode(maps* m,map* s,int use_ns){
2533 
2534  xmlNsPtr ns,ns_xsi;
2535  xmlNodePtr n,nc,nc1;
2536
2537  int nsid=zooXmlAddNs(NULL,"http://www.opengis.net/ows","ows");
2538  ns=usedNs[nsid];
2539  if(use_ns==0){
2540    ns=NULL;
2541  }
2542  n = xmlNewNode(ns, BAD_CAST "ExceptionReport");
2543  map* version=getMapFromMaps(m,"main","rversion");
2544  int vid=-1;
2545  if(version!=NULL)
2546    vid=getVersionId(version->value);
2547  if(vid<0)
2548    vid=0;
2549  if(use_ns==1){
2550    xmlNewNs(n,BAD_CAST schemas[vid][1],BAD_CAST"ows");
2551    int xsiId=zooXmlAddNs(n,"http://www.w3.org/2001/XMLSchema-instance","xsi");
2552    ns_xsi=usedNs[xsiId];
2553    char tmp[1024];
2554    sprintf(tmp,"%s %s",schemas[vid][1],schemas[vid][5]);
2555    xmlNewNsProp(n,ns_xsi,BAD_CAST "schemaLocation",BAD_CAST tmp);
2556  }
2557
2558
2559  addLangAttr(n,m);
2560  xmlNewProp(n,BAD_CAST "version",BAD_CAST schemas[vid][6]);
2561 
2562  int length=1;
2563  int cnt=0;
2564  map* len=getMap(s,"length");
2565  if(len!=NULL)
2566    length=atoi(len->value);
2567  for(cnt=0;cnt<length;cnt++){
2568    nc = xmlNewNode(ns, BAD_CAST "Exception");
2569   
2570    map* tmp=getMapArray(s,"code",cnt);
2571    if(tmp==NULL)
2572      tmp=getMap(s,"code");
2573    if(tmp!=NULL)
2574      xmlNewProp(nc,BAD_CAST "exceptionCode",BAD_CAST tmp->value);
2575    else
2576      xmlNewProp(nc,BAD_CAST "exceptionCode",BAD_CAST "NoApplicableCode");
2577   
2578    tmp=getMapArray(s,"locator",cnt);
2579    if(tmp==NULL)
2580      tmp=getMap(s,"locator");
2581    if(tmp!=NULL && strcasecmp(tmp->value,"NULL")!=0)
2582      xmlNewProp(nc,BAD_CAST "locator",BAD_CAST tmp->value);
2583
2584    tmp=getMapArray(s,"text",cnt);
2585    if(tmp==NULL)
2586      tmp=getMapArray(s,"message",cnt);
2587    nc1 = xmlNewNode(ns, BAD_CAST "ExceptionText");
2588    if(tmp!=NULL){
2589      xmlNodePtr txt=xmlNewText(BAD_CAST tmp->value);
2590      xmlAddChild(nc1,txt);
2591      if(cnt==0)
2592        setMapInMaps(m,"lenv","message",tmp->value);
2593    }
2594    else{
2595      xmlNodeSetContent(nc1, BAD_CAST _("No debug message available"));
2596    }
2597    xmlAddChild(nc,nc1);
2598    xmlAddChild(n,nc);
2599  }
2600  return n;
2601}
2602
2603/**
2604 * Print an OWS ExceptionReport.
2605 *
2606 * @param m the conf maps
2607 * @param message the error message
2608 * @param errorcode the error code
2609 * @param locator the potential locator
2610 */
2611int errorException(maps *m, const char *message, const char *errorcode, const char *locator) 
2612{
2613  map* errormap = createMap("text", message);
2614  addToMap(errormap,"code", errorcode);
2615  if(locator!=NULL)
2616    addToMap(errormap,"locator", locator);
2617  else
2618    addToMap(errormap,"locator", "NULL");
2619  printExceptionReportResponse(m,errormap);
2620  freeMap(&errormap);
2621  free(errormap);
2622  return -1;
2623}
2624
2625/**
2626 * Generate the output response (RawDataOutput or ResponseDocument)
2627 *
2628 * @param s the service structure containing the metadata information
2629 * @param request_inputs the inputs provided to the service for execution
2630 * @param request_outputs the outputs updated by the service execution
2631 * @param request_inputs1 the map containing the HTTP request
2632 * @param cpid the process identifier attached to a service execution
2633 * @param m the conf maps containing the main.cfg settings
2634 * @param res the value returned by the service execution
2635 */
2636void outputResponse(service* s,maps* request_inputs,maps* request_outputs,
2637                    map* request_inputs1,int cpid,maps* m,int res){
2638#ifdef DEBUG
2639  dumpMaps(request_inputs);
2640  dumpMaps(request_outputs);
2641  fprintf(stderr,"printProcessResponse\n");
2642#endif
2643  map* toto=getMap(request_inputs1,"RawDataOutput");
2644  int asRaw=0;
2645  if(toto!=NULL)
2646    asRaw=1;
2647  map* version=getMapFromMaps(m,"main","rversion");
2648  int vid=getVersionId(version->value);
2649  maps* tmpSess=getMaps(m,"senv");
2650  if(tmpSess!=NULL){
2651    map *_tmp=getMapFromMaps(m,"lenv","cookie");
2652    maps *tmps=getMaps(m,"senv");
2653    char* sessId=NULL;
2654    if(_tmp!=NULL){
2655      printf("Set-Cookie: %s; HttpOnly\r\n",_tmp->value);
2656      map *_tmp1=getMapFromMaps(m,"senv","ecookie_length");
2657      if(_tmp1!=NULL){
2658        int len=atoi(_tmp1->value);
2659        int cnt=0;
2660        for(cnt=0;cnt<len;cnt++){
2661          map* _tmp2=getMapArray(tmps->content,"ecookie",cnt);
2662          if(_tmp2!=NULL)
2663            printf("Set-Cookie: %s; HttpOnly\r\n",_tmp2->value);
2664        }
2665      }
2666      printf("P3P: CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"\r\n");
2667      char session_file_path[100];
2668      char *tmp1=strtok(_tmp->value,";");
2669      if(tmp1!=NULL)
2670        sprintf(session_file_path,"%s",strstr(tmp1,"=")+1);
2671      else
2672        sprintf(session_file_path,"%s",strstr(_tmp->value,"=")+1);
2673      sessId=strdup(session_file_path);
2674    }else{
2675      maps* t=getMaps(m,"senv");
2676      map*p=t->content;
2677      while(p!=NULL){
2678        if(strstr(p->name,"ID")!=NULL){
2679          sessId=strdup(p->value);
2680          break;
2681        }
2682        p=p->next;
2683      }
2684    }
2685    char session_file_path[1024];
2686    map *tmpPath=getMapFromMaps(m,"main","sessPath");
2687    if(tmpPath==NULL)
2688      tmpPath=getMapFromMaps(m,"main","tmpPath");
2689    sprintf(session_file_path,"%s/sess_%s.cfg",tmpPath->value,sessId);
2690    FILE* teste=fopen(session_file_path,"w");
2691    if(teste==NULL){
2692      char tmpMsg[1024];
2693      sprintf(tmpMsg,_("Unable to create the file \"%s\" for storing the session maps."),session_file_path);
2694      errorException(m,tmpMsg,"InternalError",NULL);
2695      return;
2696    }
2697    else{
2698      fclose(teste);
2699      dumpMapsToFile(tmpSess,session_file_path,1);
2700    }
2701  }
2702  if(res==SERVICE_FAILED){
2703    map *lenv;
2704    lenv=getMapFromMaps(m,"lenv","message");
2705    char *tmp0;
2706    if(lenv!=NULL){
2707      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));
2708      sprintf(tmp0,_("Unable to run the Service. The message returned back by the Service was the following: %s"),lenv->value);
2709    }
2710    else{
2711      tmp0=(char*)malloc((strlen(_("Unable to run the Service. No more information was returned back by the Service."))+1)*sizeof(char));
2712      sprintf(tmp0,"%s",_("Unable to run the Service. No more information was returned back by the Service."));
2713    }
2714    errorException(m,tmp0,"InternalError",NULL);
2715    free(tmp0);
2716    return;
2717  }
2718
2719  if(res==SERVICE_ACCEPTED && vid==1){
2720    map* statusInfo=createMap("Status","Accepted");
2721    map *usid=getMapFromMaps(m,"lenv","usid");
2722    addToMap(statusInfo,"JobID",usid->value);
2723    printStatusInfo(m,statusInfo,(char*)"Execute");
2724    freeMap(&statusInfo);
2725    free(statusInfo);
2726    return;
2727  }
2728
2729  if(res!=SERVICE_SUCCEEDED){
2730    printProcessResponse(m,request_inputs1,cpid,
2731                         s, s->name,res,  // replace serviceProvider with serviceName in stored response file name
2732                         request_inputs,
2733                         request_outputs);
2734    return;
2735  }
2736   
2737       
2738  map *tmp1=getMapFromMaps(m,"main","tmpPath");
2739  if(asRaw==0){
2740#ifdef DEBUG
2741    fprintf(stderr,"REQUEST_OUTPUTS FINAL\n");
2742    dumpMaps(request_outputs);
2743#endif
2744    maps* tmpI=request_outputs;
2745    maps* stmpI=NULL;
2746    map* usid=getMapFromMaps(m,"lenv","usid");
2747    int itn=0;
2748    int error=-1;
2749  NESTED0:
2750    while(tmpI!=NULL){
2751      if(tmpI->child!=NULL){
2752        stmpI=tmpI;
2753        tmpI=tmpI->child;
2754      }
2755#ifdef USE_MS
2756      map* testMap=getMap(tmpI->content,"useMapserver");       
2757#endif
2758      map *gfile=getMap(tmpI->content,"generated_file");
2759      char *file_name=NULL;
2760      if(gfile!=NULL){
2761        gfile=getMap(tmpI->content,"expected_generated_file");
2762        if(gfile==NULL){
2763          gfile=getMap(tmpI->content,"generated_file");
2764        }
2765        readGeneratedFile(m,tmpI->content,gfile->value);
2766        file_name=zStrdup((gfile->value)+strlen(tmp1->value));
2767      }
2768      toto=getMap(tmpI->content,"asReference");
2769#ifdef USE_MS
2770      map* geodatatype=getMap(tmpI->content,"geodatatype");
2771      if(toto!=NULL && strcasecmp(toto->value,"true")==0 &&
2772         (testMap==NULL ||
2773          strncasecmp(testMap->value,"true",4)!=0 ||
2774          (geodatatype!=NULL && strcasecmp(geodatatype->value,"other")==0) ) ) 
2775#else
2776        if(toto!=NULL && strcasecmp(toto->value,"true")==0)
2777#endif
2778          {
2779            elements* in=getElements(s->outputs,tmpI->name);
2780            if(in==NULL && s->outputs->child!=NULL){
2781              in=getElements(s->outputs->child,tmpI->name);
2782            }
2783            char *format=NULL;
2784            if(in!=NULL && in->format!=NULL){
2785              format=in->format;
2786            }else
2787              format=(char*)"LiteralData";
2788            if(format!=NULL && strcasecmp(format,"BoundingBoxData")==0){
2789              addToMap(tmpI->content,"extension","xml");
2790              addToMap(tmpI->content,"mimeType","text/xml");
2791              addToMap(tmpI->content,"encoding","UTF-8");
2792              addToMap(tmpI->content,"schema","http://schemas.opengis.net/ows/1.1.0/owsCommon.xsd");
2793            }
2794
2795            char *file_path=NULL;
2796            if(gfile==NULL) {
2797              map *ext=getMap(tmpI->content,"extension");
2798              char file_ext[32];
2799           
2800              if( ext != NULL && ext->value != NULL) {
2801                strncpy(file_ext, ext->value, 32);
2802              }
2803              else {
2804                // Obtain default file extension (see mimetypes.h).           
2805                // If the MIME type is not recognized, txt is used as the default extension
2806                map* mtype=getMap(tmpI->content,"mimeType");
2807                getFileExtension(mtype != NULL ? mtype->value : NULL, file_ext, 32);
2808              }
2809              if(file_name!=NULL)
2810                free(file_name);
2811              file_name=(char*)malloc((strlen(s->name)+strlen(usid->value)+strlen(file_ext)+strlen(tmpI->name)+45)*sizeof(char));
2812              sprintf(file_name,"ZOO_DATA_%s_%s_%s_%d.%s",s->name,tmpI->name,usid->value,itn,file_ext);
2813              itn++;
2814              file_path=(char*)malloc((strlen(tmp1->value)+strlen(file_name)+2)*sizeof(char));
2815              sprintf(file_path,"%s/%s",tmp1->value,file_name);
2816
2817              FILE *ofile=fopen(file_path,"wb");
2818              if(ofile==NULL){
2819                char tmpMsg[1024];
2820                sprintf(tmpMsg,_("Unable to create the file \"%s\" for storing the %s final result."),file_name,tmpI->name);
2821                errorException(m,tmpMsg,"InternalError",NULL);
2822                free(file_name);
2823                free(file_path);
2824                return;
2825              }
2826
2827              toto=getMap(tmpI->content,"value");
2828              if(toto==NULL){
2829                char tmpMsg[1024];
2830                sprintf(tmpMsg,_("No value found for the requested output %s."),tmpI->name);
2831                errorException(m,tmpMsg,"InternalError",NULL);
2832                fclose(ofile);
2833                free(file_name);
2834                free(file_path);
2835                return;
2836              }
2837              if(strcasecmp(format,"BoundingBoxData")!=0){
2838                map* size=getMap(tmpI->content,"size");
2839                if(size!=NULL && toto!=NULL)
2840                  fwrite(toto->value,1,(atoi(size->value))*sizeof(char),ofile);
2841                else
2842                  if(toto!=NULL && toto->value!=NULL)
2843                    fwrite(toto->value,1,strlen(toto->value)*sizeof(char),ofile);
2844              }else{
2845                printBoundingBoxDocument(m,tmpI,ofile);
2846              }
2847              fclose(ofile);
2848            }
2849
2850            map *tmp2=getMapFromMaps(m,"main","tmpUrl");
2851            map *tmp3=getMapFromMaps(m,"main","serverAddress");
2852            char *file_url=NULL;
2853            if(strncasecmp(tmp2->value,"http://",7)==0 ||
2854               strncasecmp(tmp2->value,"https://",8)==0){
2855              file_url=(char*)malloc((strlen(tmp2->value)+strlen(file_name)+2)*sizeof(char));
2856              sprintf(file_url,"%s/%s",tmp2->value,file_name);
2857            }else{
2858              file_url=(char*)malloc((strlen(tmp3->value)+strlen(tmp2->value)+strlen(file_name)+3)*sizeof(char));
2859              sprintf(file_url,"%s/%s/%s",tmp3->value,tmp2->value,file_name);
2860            }
2861            addToMap(tmpI->content,"Reference",file_url);
2862            if(file_name!=NULL)
2863              free(file_name);
2864            if(file_url!=NULL)
2865              free(file_url);
2866            file_name=NULL;
2867          }
2868#ifdef USE_MS
2869        else{
2870          if(testMap!=NULL){
2871            map* nbFeatures;
2872            setMapInMaps(m,"lenv","state","out");
2873            setReferenceUrl(m,tmpI);
2874            nbFeatures=getMap(tmpI->content,"nb_features");
2875            geodatatype=getMap(tmpI->content,"geodatatype");
2876            if((nbFeatures!=NULL && atoi(nbFeatures->value)==0) ||
2877               (geodatatype!=NULL && strcasecmp(geodatatype->value,"other")==0))
2878              error=1;
2879              res=SERVICE_FAILED;
2880          }
2881        }
2882#endif
2883      if(file_name!=NULL){
2884        free(file_name);
2885        file_name=NULL;
2886      }
2887      tmpI=tmpI->next;
2888    }
2889    if(stmpI!=NULL){
2890      tmpI=stmpI->next;
2891      stmpI=NULL;
2892      if(tmpI!=NULL)
2893        goto NESTED0;
2894    }   
2895#ifdef DEBUG
2896    fprintf(stderr,"SERVICE : %s\n",s->name);
2897    dumpMaps(m);
2898#endif
2899    if(error<0)
2900      printProcessResponse(m,request_inputs1,cpid,
2901                           s, s->name,res,  // replace serviceProvider with serviceName in stored response file name
2902                           request_inputs,
2903                           request_outputs);
2904    else{
2905      maps* tmpMaps=getMaps(m,"lenv");
2906      dumpMap(tmpMaps->content);
2907#ifdef USE_HPC
2908      invokeCallback(m,NULL,NULL,7,0);
2909#endif
2910      printExceptionReportResponse(m,tmpMaps->content);
2911    }
2912  }
2913  else{
2914    /**
2915     * We get the requested output or fallback to the first one if the
2916     * requested one is not present in the resulting outputs maps.
2917     */
2918    maps* tmpI=NULL;
2919    map* tmpIV=getMap(request_inputs1,"RawDataOutput");
2920    if(tmpIV!=NULL){
2921      tmpI=getMaps(request_outputs,tmpIV->value);
2922    }
2923    if(tmpI==NULL)
2924      tmpI=request_outputs;
2925    elements* e=getElements(s->outputs,tmpI->name);
2926    if(e!=NULL && strcasecmp(e->format,"BoundingBoxData")==0){
2927      printBoundingBoxDocument(m,tmpI,NULL);
2928    }else{
2929      map *gfile=getMap(tmpI->content,"generated_file");
2930      if(gfile!=NULL){
2931        gfile=getMap(tmpI->content,"expected_generated_file");
2932        if(gfile==NULL){
2933          gfile=getMap(tmpI->content,"generated_file");
2934        }
2935        readGeneratedFile(m,tmpI->content,gfile->value);
2936      }
2937      toto=getMap(tmpI->content,"value");
2938      if(toto==NULL){
2939        char tmpMsg[1024];
2940        sprintf(tmpMsg,_("Wrong RawDataOutput parameter: unable to fetch any result for the given parameter name: \"%s\"."),tmpI->name);
2941        errorException(m,tmpMsg,"InvalidParameterValue","RawDataOutput");
2942        return;
2943      }
2944      map* fname=getMapFromMaps(tmpI,tmpI->name,"filename");
2945      if(fname!=NULL)
2946        printf("Content-Disposition: attachment; filename=\"%s\"\r\n",fname->value);
2947      map* rs=getMapFromMaps(tmpI,tmpI->name,"size");
2948      if(rs!=NULL)
2949        printf("Content-Length: %s\r\n",rs->value);
2950      printHeaders(m);
2951      char mime[1024];
2952      map* mi=getMap(tmpI->content,"mimeType");
2953#ifdef DEBUG
2954      fprintf(stderr,"SERVICE OUTPUTS\n");
2955      dumpMaps(request_outputs);
2956      fprintf(stderr,"SERVICE OUTPUTS\n");
2957#endif
2958      map* en=getMap(tmpI->content,"encoding");
2959      if(mi!=NULL && en!=NULL)
2960        sprintf(mime,
2961                "Content-Type: %s; charset=%s\r\nStatus: 200 OK\r\n\r\n",
2962                mi->value,en->value);
2963      else
2964        if(mi!=NULL)
2965          sprintf(mime,
2966                  "Content-Type: %s; charset=UTF-8\r\nStatus: 200 OK\r\n\r\n",
2967                  mi->value);
2968        else
2969          sprintf(mime,"Content-Type: text/plain; charset=utf-8\r\nStatus: 200 OK\r\n\r\n");
2970      printf("%s",mime);
2971      if(rs!=NULL)
2972        fwrite(toto->value,1,atoi(rs->value),stdout);
2973      else
2974        fwrite(toto->value,1,strlen(toto->value),stdout);
2975#ifdef DEBUG
2976      dumpMap(toto);
2977#endif
2978    }
2979  }
2980}
2981
2982/**
2983 * Create required XML nodes for boundingbox and update the current XML node
2984 *
2985 * @param ns_ows the ows XML namespace
2986 * @param n the XML node to update
2987 * @param boundingbox the map containing the boundingbox definition
2988 */
2989void printBoundingBox(xmlNsPtr ns_ows,xmlNodePtr n,map* boundingbox){
2990
2991  xmlNodePtr lw=NULL,uc=NULL;
2992
2993  map* tmp=getMap(boundingbox,"value");
2994
2995  tmp=getMap(boundingbox,"lowerCorner");
2996  if(tmp!=NULL){
2997    lw=xmlNewNode(ns_ows,BAD_CAST "LowerCorner");
2998    xmlAddChild(lw,xmlNewText(BAD_CAST tmp->value));
2999  }
3000
3001  tmp=getMap(boundingbox,"upperCorner");
3002  if(tmp!=NULL){
3003    uc=xmlNewNode(ns_ows,BAD_CAST "UpperCorner");
3004    xmlAddChild(uc,xmlNewText(BAD_CAST tmp->value));
3005  }
3006
3007  tmp=getMap(boundingbox,"crs");
3008  if(tmp!=NULL)
3009    xmlNewProp(n,BAD_CAST "crs",BAD_CAST tmp->value);
3010
3011  tmp=getMap(boundingbox,"dimensions");
3012  if(tmp!=NULL)
3013    xmlNewProp(n,BAD_CAST "dimensions",BAD_CAST tmp->value);
3014
3015  xmlAddChild(n,lw);
3016  xmlAddChild(n,uc);
3017
3018}
3019
3020/**
3021 * Parse a BoundingBox string
3022 *
3023 * [OGC 06-121r3](http://portal.opengeospatial.org/files/?artifact_id=20040):
3024 *  10.2 Bounding box
3025 *
3026 *
3027 * Value is provided as : lowerCorner,upperCorner,crs,dimension
3028 * Exemple : 189000,834000,285000,962000,urn:ogc:def:crs:OGC:1.3:CRS84
3029 *
3030 * A map to store boundingbox information should contain:
3031 *  - lowerCorner : double,double (minimum within this bounding box)
3032 *  - upperCorner : double,double (maximum within this bounding box)
3033 *  - crs : URI (Reference to definition of the CRS)
3034 *  - dimensions : int
3035 *
3036 * Note : support only 2D bounding box.
3037 *
3038 * @param value the char* containing the KVP bouding box
3039 * @return a map containing all the bounding box keys
3040 */
3041map* parseBoundingBox(const char* value){
3042  map *res=NULL;
3043  if(value!=NULL){
3044    char *cv,*cvp;
3045    cv=strtok_r((char*) value,",",&cvp);
3046    int cnt=0;
3047    int icnt=0;
3048    char *currentValue=NULL;
3049    while(cv){
3050      if(cnt<2)
3051        if(currentValue!=NULL){
3052          char *finalValue=(char*)malloc((strlen(currentValue)+strlen(cv)+1)*sizeof(char));
3053          sprintf(finalValue,"%s%s",currentValue,cv);
3054          switch(cnt){
3055          case 0:
3056            res=createMap("lowerCorner",finalValue);
3057            break;
3058          case 1:
3059            addToMap(res,"upperCorner",finalValue);
3060            icnt=-1;
3061            break;
3062          }
3063          cnt++;
3064          free(currentValue);
3065          currentValue=NULL;
3066          free(finalValue);
3067        }
3068        else{
3069          currentValue=(char*)malloc((strlen(cv)+2)*sizeof(char));
3070          sprintf(currentValue,"%s ",cv);
3071        }
3072      else
3073        if(cnt==2){
3074          addToMap(res,"crs",cv);
3075          cnt++;
3076        }
3077        else
3078          addToMap(res,"dimensions",cv);
3079      icnt++;
3080      cv=strtok_r(NULL,",",&cvp);
3081    }
3082  }
3083  return res;
3084}
3085
3086/**
3087 * Print an ows:BoundingBox XML document
3088 *
3089 * @param m the maps containing the settings of the main.cfg file
3090 * @param boundingbox the maps containing the boundingbox definition
3091 * @param file the file to print the BoundingBox (if NULL then print on stdout)
3092 * @see parseBoundingBox, printBoundingBox
3093 */
3094void printBoundingBoxDocument(maps* m,maps* boundingbox,FILE* file){
3095  if(file==NULL)
3096    rewind(stdout);
3097  xmlNodePtr n;
3098  xmlDocPtr doc;
3099  xmlNsPtr ns_ows,ns_xsi;
3100  xmlChar *xmlbuff;
3101  int buffersize;
3102  char *encoding=getEncoding(m);
3103  map *tmp;
3104  if(file==NULL){
3105    int pid=0;
3106    tmp=getMapFromMaps(m,"lenv","sid");
3107    if(tmp!=NULL)
3108      pid=atoi(tmp->value);
3109    if(pid==getpid()){
3110      printf("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding);
3111    }
3112    fflush(stdout);
3113  }
3114
3115  doc = xmlNewDoc(BAD_CAST "1.0");
3116  int owsId=zooXmlAddNs(NULL,"http://www.opengis.net/ows/1.1","ows");
3117  ns_ows=usedNs[owsId];
3118  n = xmlNewNode(ns_ows, BAD_CAST "BoundingBox");
3119  xmlNewNs(n,BAD_CAST "http://www.opengis.net/ows/1.1",BAD_CAST "ows");
3120  int xsiId=zooXmlAddNs(n,"http://www.w3.org/2001/XMLSchema-instance","xsi");
3121  ns_xsi=usedNs[xsiId];
3122  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");
3123  map *tmp1=getMap(boundingbox->content,"value");
3124  tmp=parseBoundingBox(tmp1->value);
3125  printBoundingBox(ns_ows,n,tmp);
3126  xmlDocSetRootElement(doc, n);
3127
3128  xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);
3129  if(file==NULL)
3130    printf("%s",xmlbuff);
3131  else{
3132    fprintf(file,"%s",xmlbuff);
3133  }
3134
3135  if(tmp!=NULL){
3136    freeMap(&tmp);
3137    free(tmp);
3138  }
3139  xmlFree(xmlbuff);
3140  xmlFreeDoc(doc);
3141  xmlCleanupParser();
3142  zooXmlCleanupNs();
3143 
3144}
3145
3146/**
3147 * Print a StatusInfo XML document.
3148 * a statusInfo map should contain the following keys:
3149 *  * JobID corresponding to usid key from the lenv section
3150 *  * Status the current state (Succeeded,Failed,Accepted,Running)
3151 *  * PercentCompleted (optional) the percent completed
3152 *  * Message (optional) any messages the service may wish to share
3153 *
3154 * @param conf the maps containing the settings of the main.cfg file
3155 * @param statusInfo the map containing the statusInfo definition
3156 * @param req the WPS requests (GetResult, GetStatus or Dismiss)
3157 */
3158void printStatusInfo(maps* conf,map* statusInfo,char* req){
3159  rewind(stdout);
3160  xmlNodePtr n,n1;
3161  xmlDocPtr doc;
3162  xmlNsPtr ns;
3163  xmlChar *xmlbuff;
3164  int buffersize;
3165  char *encoding=getEncoding(conf);
3166  map *tmp;
3167  int pid=0;
3168  printf("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding);
3169
3170  map* version=getMapFromMaps(conf,"main","rversion");
3171  int vid=getVersionId(version->value);
3172
3173  doc = xmlNewDoc(BAD_CAST "1.0");
3174  n1=printWPSHeader(doc,conf,req,"StatusInfo",version->value,1);
3175
3176  map* val=getMap(statusInfo,"JobID");
3177  int wpsId=zooXmlAddNs(NULL,schemas[vid][2],"wps");
3178  ns=usedNs[wpsId];
3179  n = xmlNewNode(ns, BAD_CAST "JobID");
3180  xmlAddChild(n,xmlNewText(BAD_CAST val->value));
3181
3182  xmlAddChild(n1,n);
3183
3184  val=getMap(statusInfo,"Status");
3185  n = xmlNewNode(ns, BAD_CAST "Status");
3186  xmlAddChild(n,xmlNewText(BAD_CAST val->value));
3187
3188  xmlAddChild(n1,n);
3189
3190  if(strncasecmp(val->value,"Failed",6)!=0 &&
3191     strncasecmp(val->value,"Succeeded",9)!=0){
3192    val=getMap(statusInfo,"PercentCompleted");
3193    if(val!=NULL){
3194      n = xmlNewNode(ns, BAD_CAST "PercentCompleted");
3195      xmlAddChild(n,xmlNewText(BAD_CAST val->value));
3196      xmlAddChild(n1,n);
3197    }
3198
3199    val=getMap(statusInfo,"Message");
3200    if(val!=NULL){   
3201      xmlAddChild(n1,xmlNewComment(BAD_CAST val->value));
3202    }
3203  }
3204  xmlDocSetRootElement(doc, n1);
3205
3206  xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);
3207  printf("%s",xmlbuff);
3208
3209  xmlFree(xmlbuff);
3210  xmlFreeDoc(doc);
3211  xmlCleanupParser();
3212  zooXmlCleanupNs();
3213 
3214}
3215
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