source: trunk/zoo-project/zoo-kernel/response_print.c @ 654

Last change on this file since 654 was 654, checked in by djay, 9 years ago

Initial support for WPS 2.0.0 including the Dismiss extension.

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