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

Last change on this file since 862 was 862, checked in by djay, 6 years ago

Add the capability to publish heatmap or any templated mapfile using the epecific msInclude and msLayer keys for an output. For MapServer? published output, define 4096 as the default maxsize and use pixel width or height for raster files. use the correct MapServer? imagemode depending on GDALGetRasterDataType (MS_IMAGEMODE_BYTE for GDT_Byte, MS_IMAGEMODE_INT16 for GDT_Int16 and MS_IMAGEMODE_FLOAT32 for GDT_Float32). Create a text file (.maps) listing every mapfiles created for a MapServer? published output (or inputs) using saveMapNames function. Fixes in ulinet, use uuid for naming temporary files. Add dialect input to the ogr2ogr service. Use the .maps file for removing a file from the DeleteData? service

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