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

Last change on this file since 943 was 943, checked in by knut, 14 months ago

Fix problem with the parsing of system environment variables (Windows version). Need to verify that problem does not pertain to non-Windows versions also.

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

Search

ZOO Sponsors

http://www.zoo-project.org/trac/chrome/site/img/geolabs-logo.pnghttp://www.zoo-project.org/trac/chrome/site/img/neogeo-logo.png http://www.zoo-project.org/trac/chrome/site/img/apptech-logo.png http://www.zoo-project.org/trac/chrome/site/img/3liz-logo.png http://www.zoo-project.org/trac/chrome/site/img/gateway-logo.png

Become a sponsor !

Knowledge partners

http://www.zoo-project.org/trac/chrome/site/img/ocu-logo.png http://www.zoo-project.org/trac/chrome/site/img/gucas-logo.png http://www.zoo-project.org/trac/chrome/site/img/polimi-logo.png http://www.zoo-project.org/trac/chrome/site/img/fem-logo.png http://www.zoo-project.org/trac/chrome/site/img/supsi-logo.png http://www.zoo-project.org/trac/chrome/site/img/cumtb-logo.png

Become a knowledge partner

Related links

http://zoo-project.org/img/ogclogo.png http://zoo-project.org/img/osgeologo.png