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

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

Fix the issue with JavaScript? support and GDAL profile service

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