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

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

Fixes for supporting properly the memory=protect which force the ZOO-Kernel to not store any downloaded files in memory. Add footer to the HPC support. Fix the autotools to build service_json and sshapi only when required so, when HPC support is activated, this also avoid adding too much dependencies at compilation time. Store md5 of the downloaded files to avoid uploading on HPC server the same file more than once, in case the md5 correspond.

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