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

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

HPC support update. Add inputs for create options in Gdal_Dem.

  • Property svn:keywords set to Id
File size: 91.9 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
2468  if(m!=NULL){
2469    map *tmpSid=getMapFromMaps(m,"lenv","sid");
2470    if(tmpSid!=NULL){
2471      if( getpid()==atoi(tmpSid->value) ){
2472        printHeaders(m);
2473        printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode);
2474      }
2475    }
2476    else{
2477      printHeaders(m);
2478      printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode);
2479    }
2480  }else{
2481    printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode);
2482  }
2483  n=createExceptionReportNode(m,s,1);
2484  xmlDocSetRootElement(doc, n);
2485  xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);
2486  printf("%s",xmlbuff);
2487  fflush(stdout);
2488  xmlFreeDoc(doc);
2489  xmlFree(xmlbuff);
2490  xmlCleanupParser();
2491  zooXmlCleanupNs();
2492  if(m!=NULL)
2493    setMapInMaps(m,"lenv","hasPrinted","true");
2494}
2495
2496/**
2497 * Create an OWS ExceptionReport Node.
2498 *
2499 * @param m the conf maps
2500 * @param s the map containing the text,code,locator keys
2501 * @param use_ns (0/1) choose if you want to generate an ExceptionReport or
2502 *  ows:ExceptionReport node respectively
2503 * @return the ExceptionReport/ows:ExceptionReport node
2504 */
2505xmlNodePtr createExceptionReportNode(maps* m,map* s,int use_ns){
2506 
2507  xmlNsPtr ns,ns_xsi;
2508  xmlNodePtr n,nc,nc1;
2509
2510  int nsid=zooXmlAddNs(NULL,"http://www.opengis.net/ows","ows");
2511  ns=usedNs[nsid];
2512  if(use_ns==0){
2513    ns=NULL;
2514  }
2515  n = xmlNewNode(ns, BAD_CAST "ExceptionReport");
2516  map* version=getMapFromMaps(m,"main","rversion");
2517  int vid=-1;
2518  if(version!=NULL)
2519    vid=getVersionId(version->value);
2520  if(vid<0)
2521    vid=0;
2522  if(use_ns==1){
2523    xmlNewNs(n,BAD_CAST schemas[vid][1],BAD_CAST"ows");
2524    int xsiId=zooXmlAddNs(n,"http://www.w3.org/2001/XMLSchema-instance","xsi");
2525    ns_xsi=usedNs[xsiId];
2526    char tmp[1024];
2527    sprintf(tmp,"%s %s",schemas[vid][1],schemas[vid][5]);
2528    xmlNewNsProp(n,ns_xsi,BAD_CAST "schemaLocation",BAD_CAST tmp);
2529  }
2530
2531
2532  addLangAttr(n,m);
2533  xmlNewProp(n,BAD_CAST "version",BAD_CAST schemas[vid][6]);
2534 
2535  int length=1;
2536  int cnt=0;
2537  map* len=getMap(s,"length");
2538  if(len!=NULL)
2539    length=atoi(len->value);
2540  for(cnt=0;cnt<length;cnt++){
2541    nc = xmlNewNode(ns, BAD_CAST "Exception");
2542   
2543    map* tmp=getMapArray(s,"code",cnt);
2544    if(tmp==NULL)
2545      tmp=getMap(s,"code");
2546    if(tmp!=NULL)
2547      xmlNewProp(nc,BAD_CAST "exceptionCode",BAD_CAST tmp->value);
2548    else
2549      xmlNewProp(nc,BAD_CAST "exceptionCode",BAD_CAST "NoApplicableCode");
2550   
2551    tmp=getMapArray(s,"locator",cnt);
2552    if(tmp==NULL)
2553      tmp=getMap(s,"locator");
2554    if(tmp!=NULL && strcasecmp(tmp->value,"NULL")!=0)
2555      xmlNewProp(nc,BAD_CAST "locator",BAD_CAST tmp->value);
2556
2557    tmp=getMapArray(s,"text",cnt);
2558    nc1 = xmlNewNode(ns, BAD_CAST "ExceptionText");
2559    if(tmp!=NULL){
2560      xmlNodePtr txt=xmlNewText(BAD_CAST tmp->value);
2561      xmlAddChild(nc1,txt);
2562    }
2563    else{
2564      xmlNodeSetContent(nc1, BAD_CAST _("No debug message available"));
2565    }
2566    xmlAddChild(nc,nc1);
2567    xmlAddChild(n,nc);
2568  }
2569  return n;
2570}
2571
2572/**
2573 * Print an OWS ExceptionReport.
2574 *
2575 * @param m the conf maps
2576 * @param message the error message
2577 * @param errorcode the error code
2578 * @param locator the potential locator
2579 */
2580int errorException(maps *m, const char *message, const char *errorcode, const char *locator) 
2581{
2582  map* errormap = createMap("text", message);
2583  addToMap(errormap,"code", errorcode);
2584  if(locator!=NULL)
2585    addToMap(errormap,"locator", locator);
2586  else
2587    addToMap(errormap,"locator", "NULL");
2588  printExceptionReportResponse(m,errormap);
2589  freeMap(&errormap);
2590  free(errormap);
2591  return -1;
2592}
2593
2594/**
2595 * Generate the output response (RawDataOutput or ResponseDocument)
2596 *
2597 * @param s the service structure containing the metadata information
2598 * @param request_inputs the inputs provided to the service for execution
2599 * @param request_outputs the outputs updated by the service execution
2600 * @param request_inputs1 the map containing the HTTP request
2601 * @param cpid the process identifier attached to a service execution
2602 * @param m the conf maps containing the main.cfg settings
2603 * @param res the value returned by the service execution
2604 */
2605void outputResponse(service* s,maps* request_inputs,maps* request_outputs,
2606                    map* request_inputs1,int cpid,maps* m,int res){
2607               
2608#ifdef DEBUG
2609  dumpMaps(request_inputs);
2610  dumpMaps(request_outputs);
2611  fprintf(stderr,"printProcessResponse\n");
2612#endif
2613  map* toto=getMap(request_inputs1,"RawDataOutput");
2614  int asRaw=0;
2615  if(toto!=NULL)
2616    asRaw=1;
2617  map* version=getMapFromMaps(m,"main","rversion");
2618  int vid=getVersionId(version->value);
2619  maps* tmpSess=getMaps(m,"senv");
2620  if(tmpSess!=NULL){
2621    map *_tmp=getMapFromMaps(m,"lenv","cookie");
2622    char* sessId=NULL;
2623    if(_tmp!=NULL){
2624      printf("Set-Cookie: %s; HttpOnly\r\n",_tmp->value);
2625      printf("P3P: CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"\r\n");
2626      char session_file_path[100];
2627      char *tmp1=strtok(_tmp->value,";");
2628      if(tmp1!=NULL)
2629        sprintf(session_file_path,"%s",strstr(tmp1,"=")+1);
2630      else
2631        sprintf(session_file_path,"%s",strstr(_tmp->value,"=")+1);
2632      sessId=strdup(session_file_path);
2633    }else{
2634      maps* t=getMaps(m,"senv");
2635      map*p=t->content;
2636      while(p!=NULL){
2637        if(strstr(p->name,"ID")!=NULL){
2638          sessId=strdup(p->value);
2639          break;
2640        }
2641        p=p->next;
2642      }
2643    }
2644    char session_file_path[1024];
2645    map *tmpPath=getMapFromMaps(m,"main","sessPath");
2646    if(tmpPath==NULL)
2647      tmpPath=getMapFromMaps(m,"main","tmpPath");
2648    sprintf(session_file_path,"%s/sess_%s.cfg",tmpPath->value,sessId);
2649    FILE* teste=fopen(session_file_path,"w");
2650    if(teste==NULL){
2651      char tmpMsg[1024];
2652      sprintf(tmpMsg,_("Unable to create the file \"%s\" for storing the session maps."),session_file_path);
2653      errorException(m,tmpMsg,"InternalError",NULL);
2654      return;
2655    }
2656    else{
2657      fclose(teste);
2658      dumpMapsToFile(tmpSess,session_file_path,1);
2659    }
2660  }
2661                 
2662  if(res==SERVICE_FAILED){
2663    map *lenv;
2664    lenv=getMapFromMaps(m,"lenv","message");
2665    char *tmp0;
2666    if(lenv!=NULL){
2667      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));
2668      sprintf(tmp0,_("Unable to run the Service. The message returned back by the Service was the following: %s"),lenv->value);
2669    }
2670    else{
2671      tmp0=(char*)malloc((strlen(_("Unable to run the Service. No more information was returned back by the Service."))+1)*sizeof(char));
2672      sprintf(tmp0,"%s",_("Unable to run the Service. No more information was returned back by the Service."));
2673    }
2674    errorException(m,tmp0,"InternalError",NULL);
2675    free(tmp0);
2676    return;
2677  }
2678
2679  if(res==SERVICE_ACCEPTED && vid==1){
2680    map* statusInfo=createMap("Status","Accepted");
2681    map *usid=getMapFromMaps(m,"lenv","usid");
2682    addToMap(statusInfo,"JobID",usid->value);
2683    printStatusInfo(m,statusInfo,(char*)"Execute");
2684    freeMap(&statusInfo);
2685    free(statusInfo);
2686    return;
2687  }
2688       
2689  map *tmp1=getMapFromMaps(m,"main","tmpPath");
2690  if(asRaw==0){
2691#ifdef DEBUG
2692    fprintf(stderr,"REQUEST_OUTPUTS FINAL\n");
2693    dumpMaps(request_outputs);
2694#endif
2695    maps* tmpI=request_outputs;
2696    maps* stmpI=NULL;
2697    map* usid=getMapFromMaps(m,"lenv","usid");
2698    int itn=0;
2699  NESTED0:
2700    while(tmpI!=NULL){
2701      if(tmpI->child!=NULL){
2702        stmpI=tmpI;
2703        tmpI=tmpI->child;
2704      }
2705#ifdef USE_MS
2706      map* testMap=getMap(tmpI->content,"useMapserver");       
2707#endif
2708      map *gfile=getMap(tmpI->content,"generated_file");
2709      char *file_name=NULL;
2710      if(gfile!=NULL){
2711        gfile=getMap(tmpI->content,"expected_generated_file");
2712        if(gfile==NULL){
2713          gfile=getMap(tmpI->content,"generated_file");
2714        }
2715        readGeneratedFile(m,tmpI->content,gfile->value);
2716        file_name=zStrdup((gfile->value)+strlen(tmp1->value));
2717      }
2718      toto=getMap(tmpI->content,"asReference");
2719#ifdef USE_MS
2720      restartNoMS:
2721      map* geodatatype=getMap(tmpI->content,"geodatatype");
2722     
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(strcasecmp(format,"BoundingBoxData")!=0){
2781              map* size=getMap(tmpI->content,"size");
2782              if(size!=NULL && toto!=NULL)
2783                fwrite(toto->value,1,(atoi(size->value))*sizeof(char),ofile);
2784              else
2785                if(toto!=NULL && toto->value!=NULL)
2786                  fwrite(toto->value,1,strlen(toto->value)*sizeof(char),ofile);
2787            }else{
2788              printBoundingBoxDocument(m,tmpI,ofile);
2789            }
2790            fclose(ofile);
2791          }
2792
2793          map *tmp2=getMapFromMaps(m,"main","tmpUrl");
2794          map *tmp3=getMapFromMaps(m,"main","serverAddress");
2795          char *file_url=NULL;
2796          if(strncasecmp(tmp2->value,"http://",7)==0 ||
2797             strncasecmp(tmp2->value,"https://",8)==0){
2798            file_url=(char*)malloc((strlen(tmp2->value)+strlen(file_name)+2)*sizeof(char));
2799            sprintf(file_url,"%s/%s",tmp2->value,file_name);
2800          }else{
2801            file_url=(char*)malloc((strlen(tmp3->value)+strlen(tmp2->value)+strlen(file_name)+3)*sizeof(char));
2802            sprintf(file_url,"%s/%s/%s",tmp3->value,tmp2->value,file_name);
2803          }
2804          addToMap(tmpI->content,"Reference",file_url);
2805          /*maps* curs=tmpI;
2806          curs=curs->next;
2807          map* test=getMap(tmpI->content,"replicateStorageNext");
2808          if(test!=NULL && strncasecmp(test->value,"true",4)==0)
2809            while(curs!=NULL){
2810              addToMap(curs->content,"storage",file_path);
2811              curs=curs->next;
2812              }
2813          if(file_path!=NULL)
2814          free(file_path);*/
2815          if(file_name!=NULL)
2816            free(file_name);
2817          if(file_url!=NULL)
2818            free(file_url);
2819          file_name=NULL;
2820        }
2821#ifdef USE_MS
2822      else{
2823        if(testMap!=NULL){
2824          setMapInMaps(m,"lenv","state","out");
2825          setReferenceUrl(m,tmpI);
2826          geodatatype=getMap(tmpI->content,"geodatatype");
2827          if(geodatatype!=NULL && strcasecmp(geodatatype->value,"other")==0)
2828            goto restartNoMS;
2829        }
2830      }
2831#endif
2832      if(file_name!=NULL){
2833        free(file_name);
2834        file_name=NULL;
2835      }
2836      tmpI=tmpI->next;
2837    }
2838    if(stmpI!=NULL){
2839      tmpI=stmpI->next;
2840      stmpI=NULL;
2841      if(tmpI!=NULL)
2842        goto NESTED0;
2843    }   
2844#ifdef DEBUG
2845    fprintf(stderr,"SERVICE : %s\n",s->name);
2846    dumpMaps(m);
2847#endif
2848    printProcessResponse(m,request_inputs1,cpid,
2849                         s, s->name,res,  // replace serviceProvider with serviceName in stored response file name
2850                         request_inputs,
2851                         request_outputs);
2852  }
2853  else{
2854    /**
2855     * We get the requested output or fallback to the first one if the
2856     * requested one is not present in the resulting outputs maps.
2857     */
2858    maps* tmpI=NULL;
2859    map* tmpIV=getMap(request_inputs1,"RawDataOutput");
2860    if(tmpIV!=NULL){
2861      tmpI=getMaps(request_outputs,tmpIV->value);
2862    }
2863    if(tmpI==NULL)
2864      tmpI=request_outputs;
2865    elements* e=getElements(s->outputs,tmpI->name);
2866    if(e!=NULL && strcasecmp(e->format,"BoundingBoxData")==0){
2867      printBoundingBoxDocument(m,tmpI,NULL);
2868    }else{
2869      map *gfile=getMap(tmpI->content,"generated_file");
2870      if(gfile!=NULL){
2871        gfile=getMap(tmpI->content,"expected_generated_file");
2872        if(gfile==NULL){
2873          gfile=getMap(tmpI->content,"generated_file");
2874        }
2875        readGeneratedFile(m,tmpI->content,gfile->value);
2876      }
2877      toto=getMap(tmpI->content,"value");
2878      if(toto==NULL){
2879        char tmpMsg[1024];
2880        sprintf(tmpMsg,_("Wrong RawDataOutput parameter: unable to fetch any result for the given parameter name: \"%s\"."),tmpI->name);
2881        errorException(m,tmpMsg,"InvalidParameterValue","RawDataOutput");
2882        return;
2883      }
2884      map* fname=getMapFromMaps(tmpI,tmpI->name,"filename");
2885      if(fname!=NULL)
2886        printf("Content-Disposition: attachment; filename=\"%s\"\r\n",fname->value);
2887      map* rs=getMapFromMaps(tmpI,tmpI->name,"size");
2888      if(rs!=NULL)
2889        printf("Content-Length: %s\r\n",rs->value);
2890      printHeaders(m);
2891      char mime[1024];
2892      map* mi=getMap(tmpI->content,"mimeType");
2893#ifdef DEBUG
2894      fprintf(stderr,"SERVICE OUTPUTS\n");
2895      dumpMaps(request_outputs);
2896      fprintf(stderr,"SERVICE OUTPUTS\n");
2897#endif
2898      map* en=getMap(tmpI->content,"encoding");
2899      if(mi!=NULL && en!=NULL)
2900        sprintf(mime,
2901                "Content-Type: %s; charset=%s\r\nStatus: 200 OK\r\n\r\n",
2902                mi->value,en->value);
2903      else
2904        if(mi!=NULL)
2905          sprintf(mime,
2906                  "Content-Type: %s; charset=UTF-8\r\nStatus: 200 OK\r\n\r\n",
2907                  mi->value);
2908        else
2909          sprintf(mime,"Content-Type: text/plain; charset=utf-8\r\nStatus: 200 OK\r\n\r\n");
2910      printf("%s",mime);
2911      if(rs!=NULL)
2912        fwrite(toto->value,1,atoi(rs->value),stdout);
2913      else
2914        fwrite(toto->value,1,strlen(toto->value),stdout);
2915#ifdef DEBUG
2916      dumpMap(toto);
2917#endif
2918    }
2919  }
2920}
2921
2922/**
2923 * Create required XML nodes for boundingbox and update the current XML node
2924 *
2925 * @param ns_ows the ows XML namespace
2926 * @param n the XML node to update
2927 * @param boundingbox the map containing the boundingbox definition
2928 */
2929void printBoundingBox(xmlNsPtr ns_ows,xmlNodePtr n,map* boundingbox){
2930
2931  xmlNodePtr lw=NULL,uc=NULL;
2932
2933  map* tmp=getMap(boundingbox,"value");
2934
2935  tmp=getMap(boundingbox,"lowerCorner");
2936  if(tmp!=NULL){
2937    lw=xmlNewNode(ns_ows,BAD_CAST "LowerCorner");
2938    xmlAddChild(lw,xmlNewText(BAD_CAST tmp->value));
2939  }
2940
2941  tmp=getMap(boundingbox,"upperCorner");
2942  if(tmp!=NULL){
2943    uc=xmlNewNode(ns_ows,BAD_CAST "UpperCorner");
2944    xmlAddChild(uc,xmlNewText(BAD_CAST tmp->value));
2945  }
2946
2947  tmp=getMap(boundingbox,"crs");
2948  if(tmp!=NULL)
2949    xmlNewProp(n,BAD_CAST "crs",BAD_CAST tmp->value);
2950
2951  tmp=getMap(boundingbox,"dimensions");
2952  if(tmp!=NULL)
2953    xmlNewProp(n,BAD_CAST "dimensions",BAD_CAST tmp->value);
2954
2955  xmlAddChild(n,lw);
2956  xmlAddChild(n,uc);
2957
2958}
2959
2960/**
2961 * Parse a BoundingBox string
2962 *
2963 * [OGC 06-121r3](http://portal.opengeospatial.org/files/?artifact_id=20040):
2964 *  10.2 Bounding box
2965 *
2966 *
2967 * Value is provided as : lowerCorner,upperCorner,crs,dimension
2968 * Exemple : 189000,834000,285000,962000,urn:ogc:def:crs:OGC:1.3:CRS84
2969 *
2970 * A map to store boundingbox information should contain:
2971 *  - lowerCorner : double,double (minimum within this bounding box)
2972 *  - upperCorner : double,double (maximum within this bounding box)
2973 *  - crs : URI (Reference to definition of the CRS)
2974 *  - dimensions : int
2975 *
2976 * Note : support only 2D bounding box.
2977 *
2978 * @param value the char* containing the KVP bouding box
2979 * @return a map containing all the bounding box keys
2980 */
2981map* parseBoundingBox(const char* value){
2982  map *res=NULL;
2983  if(value!=NULL){
2984    char *cv,*cvp;
2985    cv=strtok_r((char*) value,",",&cvp);
2986    int cnt=0;
2987    int icnt=0;
2988    char *currentValue=NULL;
2989    while(cv){
2990      if(cnt<2)
2991        if(currentValue!=NULL){
2992          char *finalValue=(char*)malloc((strlen(currentValue)+strlen(cv)+1)*sizeof(char));
2993          sprintf(finalValue,"%s%s",currentValue,cv);
2994          switch(cnt){
2995          case 0:
2996            res=createMap("lowerCorner",finalValue);
2997            break;
2998          case 1:
2999            addToMap(res,"upperCorner",finalValue);
3000            icnt=-1;
3001            break;
3002          }
3003          cnt++;
3004          free(currentValue);
3005          currentValue=NULL;
3006          free(finalValue);
3007        }
3008        else{
3009          currentValue=(char*)malloc((strlen(cv)+2)*sizeof(char));
3010          sprintf(currentValue,"%s ",cv);
3011        }
3012      else
3013        if(cnt==2){
3014          addToMap(res,"crs",cv);
3015          cnt++;
3016        }
3017        else
3018          addToMap(res,"dimensions",cv);
3019      icnt++;
3020      cv=strtok_r(NULL,",",&cvp);
3021    }
3022  }
3023  return res;
3024}
3025
3026/**
3027 * Print an ows:BoundingBox XML document
3028 *
3029 * @param m the maps containing the settings of the main.cfg file
3030 * @param boundingbox the maps containing the boundingbox definition
3031 * @param file the file to print the BoundingBox (if NULL then print on stdout)
3032 * @see parseBoundingBox, printBoundingBox
3033 */
3034void printBoundingBoxDocument(maps* m,maps* boundingbox,FILE* file){
3035  if(file==NULL)
3036    rewind(stdout);
3037  xmlNodePtr n;
3038  xmlDocPtr doc;
3039  xmlNsPtr ns_ows,ns_xsi;
3040  xmlChar *xmlbuff;
3041  int buffersize;
3042  char *encoding=getEncoding(m);
3043  map *tmp;
3044  if(file==NULL){
3045    int pid=0;
3046    tmp=getMapFromMaps(m,"lenv","sid");
3047    if(tmp!=NULL)
3048      pid=atoi(tmp->value);
3049    if(pid==getpid()){
3050      printf("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding);
3051    }
3052    fflush(stdout);
3053  }
3054
3055  doc = xmlNewDoc(BAD_CAST "1.0");
3056  int owsId=zooXmlAddNs(NULL,"http://www.opengis.net/ows/1.1","ows");
3057  ns_ows=usedNs[owsId];
3058  n = xmlNewNode(ns_ows, BAD_CAST "BoundingBox");
3059  xmlNewNs(n,BAD_CAST "http://www.opengis.net/ows/1.1",BAD_CAST "ows");
3060  int xsiId=zooXmlAddNs(n,"http://www.w3.org/2001/XMLSchema-instance","xsi");
3061  ns_xsi=usedNs[xsiId];
3062  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");
3063  map *tmp1=getMap(boundingbox->content,"value");
3064  tmp=parseBoundingBox(tmp1->value);
3065  printBoundingBox(ns_ows,n,tmp);
3066  xmlDocSetRootElement(doc, n);
3067
3068  xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);
3069  if(file==NULL)
3070    printf("%s",xmlbuff);
3071  else{
3072    fprintf(file,"%s",xmlbuff);
3073  }
3074
3075  if(tmp!=NULL){
3076    freeMap(&tmp);
3077    free(tmp);
3078  }
3079  xmlFree(xmlbuff);
3080  xmlFreeDoc(doc);
3081  xmlCleanupParser();
3082  zooXmlCleanupNs();
3083 
3084}
3085
3086/**
3087 * Print a StatusInfo XML document.
3088 * a statusInfo map should contain the following keys:
3089 *  * JobID corresponding to usid key from the lenv section
3090 *  * Status the current state (Succeeded,Failed,Accepted,Running)
3091 *  * PercentCompleted (optional) the percent completed
3092 *  * Message (optional) any messages the service may wish to share
3093 *
3094 * @param conf the maps containing the settings of the main.cfg file
3095 * @param statusInfo the map containing the statusInfo definition
3096 * @param req the WPS requests (GetResult, GetStatus or Dismiss)
3097 */
3098void printStatusInfo(maps* conf,map* statusInfo,char* req){
3099  rewind(stdout);
3100  xmlNodePtr n,n1;
3101  xmlDocPtr doc;
3102  xmlNsPtr ns;
3103  xmlChar *xmlbuff;
3104  int buffersize;
3105  char *encoding=getEncoding(conf);
3106  map *tmp;
3107  int pid=0;
3108  printf("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding);
3109
3110  map* version=getMapFromMaps(conf,"main","rversion");
3111  int vid=getVersionId(version->value);
3112
3113  doc = xmlNewDoc(BAD_CAST "1.0");
3114  n1=printWPSHeader(doc,conf,req,"StatusInfo",version->value,1);
3115
3116  map* val=getMap(statusInfo,"JobID");
3117  int wpsId=zooXmlAddNs(NULL,schemas[vid][2],"wps");
3118  ns=usedNs[wpsId];
3119  n = xmlNewNode(ns, BAD_CAST "JobID");
3120  xmlAddChild(n,xmlNewText(BAD_CAST val->value));
3121
3122  xmlAddChild(n1,n);
3123
3124  val=getMap(statusInfo,"Status");
3125  n = xmlNewNode(ns, BAD_CAST "Status");
3126  xmlAddChild(n,xmlNewText(BAD_CAST val->value));
3127
3128  xmlAddChild(n1,n);
3129
3130  if(strncasecmp(val->value,"Failed",6)!=0 &&
3131     strncasecmp(val->value,"Succeeded",9)!=0){
3132    val=getMap(statusInfo,"PercentCompleted");
3133    if(val!=NULL){
3134      n = xmlNewNode(ns, BAD_CAST "PercentCompleted");
3135      xmlAddChild(n,xmlNewText(BAD_CAST val->value));
3136      xmlAddChild(n1,n);
3137    }
3138
3139    val=getMap(statusInfo,"Message");
3140    if(val!=NULL){   
3141      xmlAddChild(n1,xmlNewComment(BAD_CAST val->value));
3142    }
3143  }
3144  xmlDocSetRootElement(doc, n1);
3145
3146  xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);
3147  printf("%s",xmlbuff);
3148
3149  xmlFree(xmlbuff);
3150  xmlFreeDoc(doc);
3151  xmlCleanupParser();
3152  zooXmlCleanupNs();
3153 
3154}
3155
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