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

Last change on this file since 674 was 673, checked in by djay, 9 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