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

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

Update the source code for HPC support. Automatically adding nested outputs for the HPC support (should this be available for every support?). Add capability to store the metadata in the Collection DataBase?. Addition of the zcfg2sql to import any existing ZCFG file into the Collection DB. Add the support to invoke a callback (for history purpose) in case a [callback] section contains at least one parameter defined (url). Add support to convert maps and map to JSON (for callback use only by now). Fix some memory leaks (some are still there).

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