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

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

Better concurrency gesture for asynchronous requests, add db backend support for status informations.

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