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

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

Merge prototype-v0 branch in trunk

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