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

Last change on this file since 851 was 851, checked in by djay, 7 years ago

Invoke callback asynchronously. Still the ZOO-Kernel has still to wait for every requests to finish before stoping its execution.

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