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

Last change on this file since 673 was 673, checked in by djay, 10 years ago

Fixes in configure.ac. Fix in registry creation. Fixes for Data node for WPS version 2.0.0.

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