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

Last change on this file since 902 was 902, checked in by djay, 6 years ago

Make Callback and HPC support independent.

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