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

Last change on this file since 651 was 651, checked in by david, 7 years ago

Bug Fix linux compilation

  • 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      lpid=atoi(tmpm2->value);
1518      tmpm2=getMap(tmp_maps->content,"tmpUrl");
1519      if(tmpm1!=NULL && tmpm2!=NULL){
1520        if( strncasecmp( tmpm2->value, "http://", 7) == 0 ||
1521            strncasecmp( tmpm2->value, "https://", 8 ) == 0 ){
1522          sprintf(url,"%s/%s_%i.xml",tmpm2->value,service,lpid);
1523        }else
1524          sprintf(url,"%s/%s/%s_%i.xml",tmpm1->value,tmpm2->value,service,lpid);
1525      }
1526    }
1527    if(tmpm1!=NULL){
1528      sprintf(tmp,"%s",tmpm1->value);
1529    }
1530    int lpid;
1531    tmpm1=getMapFromMaps(m,"lenv","usid");
1532    lpid=atoi(tmpm1->value);
1533    tmpm1=getMapFromMaps(m,"main","TmpPath");
1534    sprintf(stored_path,"%s/%s_%i.xml",tmpm1->value,service,lpid);
1535  }
1536
1537  xmlNewProp(n,BAD_CAST "serviceInstance",BAD_CAST tmp);
1538  map* test=getMap(request,"storeExecuteResponse");
1539  bool hasStoredExecuteResponse=false;
1540  if(test!=NULL && strcasecmp(test->value,"true")==0){
1541    xmlNewProp(n,BAD_CAST "statusLocation",BAD_CAST url);
1542    hasStoredExecuteResponse=true;
1543  }
1544
1545  nc = xmlNewNode(ns, BAD_CAST "Process");
1546  map* tmp2=getMap(serv->content,"processVersion");
1547  if(tmp2!=NULL)
1548    xmlNewNsProp(nc,ns,BAD_CAST "processVersion",BAD_CAST tmp2->value);
1549 
1550  map* tmpI=getMapFromMaps(m,"lenv","oIdentifier");
1551  printDescription(nc,ns_ows,tmpI->value,serv->content,0);
1552
1553  xmlAddChild(n,nc);
1554
1555  nc = xmlNewNode(ns, BAD_CAST "Status");
1556  const struct tm *tm;
1557  size_t len;
1558  time_t now;
1559  char *tmp1;
1560  map *tmpStatus;
1561 
1562  now = time ( NULL );
1563  tm = localtime ( &now );
1564
1565  tmp1 = (char*)malloc((TIME_SIZE+1)*sizeof(char));
1566
1567  len = strftime ( tmp1, TIME_SIZE, "%Y-%m-%dT%I:%M:%SZ", tm );
1568
1569  xmlNewProp(nc,BAD_CAST "creationTime",BAD_CAST tmp1);
1570
1571  char sMsg[2048];
1572  switch(status){
1573  case SERVICE_SUCCEEDED:
1574    nc1 = xmlNewNode(ns, BAD_CAST "ProcessSucceeded");
1575    sprintf(sMsg,_("The service \"%s\" ran successfully."),serv->name);
1576    nc3=xmlNewText(BAD_CAST sMsg);
1577    xmlAddChild(nc1,nc3);
1578    break;
1579  case SERVICE_STARTED:
1580    nc1 = xmlNewNode(ns, BAD_CAST "ProcessStarted");
1581    tmpStatus=getMapFromMaps(m,"lenv","status");
1582    xmlNewProp(nc1,BAD_CAST "percentCompleted",BAD_CAST tmpStatus->value);
1583    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);
1584    nc3=xmlNewText(BAD_CAST sMsg);
1585    xmlAddChild(nc1,nc3);
1586    break;
1587  case SERVICE_ACCEPTED:
1588    nc1 = xmlNewNode(ns, BAD_CAST "ProcessAccepted");
1589    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);
1590    nc3=xmlNewText(BAD_CAST sMsg);
1591    xmlAddChild(nc1,nc3);
1592    break;
1593  case SERVICE_FAILED:
1594    nc1 = xmlNewNode(ns, BAD_CAST "ProcessFailed");
1595    map *errorMap;
1596    map *te;
1597    te=getMapFromMaps(m,"lenv","code");
1598    if(te!=NULL)
1599      errorMap=createMap("code",te->value);
1600    else
1601      errorMap=createMap("code","NoApplicableCode");
1602    te=getMapFromMaps(m,"lenv","message");
1603    if(te!=NULL)
1604      addToMap(errorMap,"text",_ss(te->value));
1605    else
1606      addToMap(errorMap,"text",_("No more information available"));
1607    nc3=createExceptionReportNode(m,errorMap,0);
1608    freeMap(&errorMap);
1609    free(errorMap);
1610    xmlAddChild(nc1,nc3);
1611    break;
1612  default :
1613    printf(_("error code not know : %i\n"),status);
1614    //exit(1);
1615    break;
1616  }
1617  xmlAddChild(nc,nc1);
1618  xmlAddChild(n,nc);
1619  free(tmp1);
1620
1621#ifdef DEBUG
1622  fprintf(stderr,"printProcessResponse 1 161\n");
1623#endif
1624
1625  map* lineage=getMap(request,"lineage");
1626  if(lineage!=NULL && strcasecmp(lineage->value,"true")==0){
1627    nc = xmlNewNode(ns, BAD_CAST "DataInputs");
1628    maps* mcursor=inputs;
1629    elements* scursor=NULL;
1630    while(mcursor!=NULL /*&& scursor!=NULL*/){
1631      scursor=getElements(serv->inputs,mcursor->name);
1632      printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Input");
1633      mcursor=mcursor->next;
1634    }
1635    xmlAddChild(n,nc);
1636   
1637#ifdef DEBUG
1638    fprintf(stderr,"printProcessResponse 1 177\n");
1639#endif
1640
1641    nc = xmlNewNode(ns, BAD_CAST "OutputDefinitions");
1642    mcursor=outputs;
1643    scursor=NULL;
1644    while(mcursor!=NULL){
1645      scursor=getElements(serv->outputs,mcursor->name);
1646      printOutputDefinitions(doc,nc,ns,ns_ows,scursor,mcursor,"Output");
1647      mcursor=mcursor->next;
1648    }
1649    xmlAddChild(n,nc);
1650  }
1651#ifdef DEBUG
1652  fprintf(stderr,"printProcessResponse 1 190\n");
1653#endif
1654
1655  /**
1656   * Display the process output only when requested !
1657   */
1658  if(status==SERVICE_SUCCEEDED){
1659    nc = xmlNewNode(ns, BAD_CAST "ProcessOutputs");
1660    maps* mcursor=outputs;
1661    elements* scursor=serv->outputs;
1662    map* testResponse=getMap(request,"RawDataOutput");
1663    if(testResponse==NULL)
1664      testResponse=getMap(request,"ResponseDocument");
1665    while(mcursor!=NULL){
1666      map* tmp0=getMap(mcursor->content,"inRequest");
1667      scursor=getElements(serv->outputs,mcursor->name);
1668      if(scursor!=NULL){
1669        if(testResponse==NULL || tmp0==NULL)
1670          printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Output");
1671        else
1672          if(tmp0!=NULL && strncmp(tmp0->value,"true",4)==0)
1673            printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Output");
1674      }else
1675        /**
1676         * In case there was no definition found in the ZCFG file but
1677         * present in the service code
1678         */
1679        printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Output");
1680      mcursor=mcursor->next;
1681    }
1682    xmlAddChild(n,nc);
1683  }
1684
1685  if(hasStoredExecuteResponse==true && status!=SERVICE_STARTED){
1686    semid lid=getShmLockId(m,1);
1687    if(lid<0){
1688      /* If the lock failed */
1689      errorException(m,_("Lock failed."),"InternalError",NULL);
1690      xmlFreeDoc(doc);
1691      xmlCleanupParser();
1692      zooXmlCleanupNs();
1693      return;
1694    }
1695    else{
1696#ifdef DEBUG
1697      fprintf(stderr,"LOCK %s %d !\n",__FILE__,__LINE__);
1698#endif
1699      lockShm(lid);
1700      /* We need to write the ExecuteResponse Document somewhere */
1701      FILE* output=fopen(stored_path,"w");
1702      if(output==NULL){
1703        /* If the file cannot be created return an ExceptionReport */
1704        char tmpMsg[1024];
1705        sprintf(tmpMsg,_("Unable to create the file \"%s\" for storing the ExecuteResponse."),stored_path);
1706
1707        errorException(m,tmpMsg,"InternalError",NULL);
1708        xmlFreeDoc(doc);
1709        xmlCleanupParser();
1710        zooXmlCleanupNs();
1711        unlockShm(lid);
1712        return;
1713      }
1714      xmlChar *xmlbuff;
1715      int buffersize;
1716      xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, "UTF-8", 1);
1717      fwrite(xmlbuff,1,xmlStrlen(xmlbuff)*sizeof(char),output);
1718      xmlFree(xmlbuff);
1719      fclose(output);
1720#ifdef DEBUG
1721      fprintf(stderr,"UNLOCK %s %d !\n",__FILE__,__LINE__);
1722#endif
1723      unlockShm(lid);
1724      map* test1=getMap(request,"status");
1725      if(test1==NULL || strcasecmp(test1->value,"true")!=0){
1726        removeShmLock(m,1);
1727      }
1728    }
1729  }
1730  printDocument(m,doc,pid);
1731
1732  xmlCleanupParser();
1733  zooXmlCleanupNs();
1734}
1735
1736/**
1737 * Print a XML document.
1738 *
1739 * @param m the conf maps containing the main.cfg settings
1740 * @param doc the XML document
1741 * @param pid the process identifier linked to a service
1742 */
1743void printDocument(maps* m, xmlDocPtr doc,int pid){
1744  char *encoding=getEncoding(m);
1745  if(pid==getpid()){
1746    printHeaders(m);
1747    printf("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding);
1748  }
1749  fflush(stdout);
1750  xmlChar *xmlbuff;
1751  int buffersize;
1752  /*
1753   * Dump the document to a buffer and print it on stdout
1754   * for demonstration purposes.
1755   */
1756  xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);
1757  printf("%s",xmlbuff);
1758  fflush(stdout);
1759  /*
1760   * Free associated memory.
1761   */
1762  xmlFree(xmlbuff);
1763  xmlFreeDoc(doc);
1764  xmlCleanupParser();
1765  zooXmlCleanupNs();
1766}
1767
1768/**
1769 * Print a XML document.
1770 *
1771 * @param doc the XML document (unused)
1772 * @param nc the XML node to add the output definition
1773 * @param ns_wps the wps XML namespace
1774 * @param ns_ows the ows XML namespace
1775 * @param e the output elements
1776 * @param m the conf maps containing the main.cfg settings
1777 * @param type the type (unused)
1778 */
1779void printOutputDefinitions(xmlDocPtr doc,xmlNodePtr nc,xmlNsPtr ns_wps,xmlNsPtr ns_ows,elements* e,maps* m,const char* type){
1780  xmlNodePtr nc1;
1781  nc1=xmlNewNode(ns_wps, BAD_CAST type);
1782  map *tmp=NULL; 
1783  if(e!=NULL && e->defaults!=NULL)
1784    tmp=e->defaults->content;
1785  else{
1786    /*
1787    dumpElements(e);
1788    */
1789    return;
1790  }
1791  while(tmp!=NULL){
1792    if(strncasecmp(tmp->name,"MIMETYPE",strlen(tmp->name))==0
1793       || strncasecmp(tmp->name,"ENCODING",strlen(tmp->name))==0
1794       || strncasecmp(tmp->name,"SCHEMA",strlen(tmp->name))==0
1795       || strncasecmp(tmp->name,"UOM",strlen(tmp->name))==0)
1796    xmlNewProp(nc1,BAD_CAST tmp->name,BAD_CAST tmp->value);
1797    tmp=tmp->next;
1798  }
1799  tmp=getMap(e->defaults->content,"asReference");
1800  if(tmp==NULL)
1801    xmlNewProp(nc1,BAD_CAST "asReference",BAD_CAST "false");
1802
1803  tmp=e->content;
1804
1805  printDescription(nc1,ns_ows,m->name,e->content,0);
1806
1807  xmlAddChild(nc,nc1);
1808
1809}
1810
1811/**
1812 * Generate XML nodes describing inputs or outputs metadata.
1813 *
1814 * @param doc the XML document
1815 * @param nc the XML node to add the definition
1816 * @param ns_wps the wps namespace
1817 * @param ns_ows the ows namespace
1818 * @param ns_xlink the xlink namespace
1819 * @param e the output elements
1820 * @param m the conf maps containing the main.cfg settings
1821 * @param type the type
1822 */
1823void printIOType(xmlDocPtr doc,xmlNodePtr nc,xmlNsPtr ns_wps,xmlNsPtr ns_ows,xmlNsPtr ns_xlink,elements* e,maps* m,const char* type){
1824
1825  xmlNodePtr nc1,nc2,nc3;
1826  nc1=xmlNewNode(ns_wps, BAD_CAST type);
1827  map *tmp=NULL;
1828  if(e!=NULL)
1829    tmp=e->content;
1830  else
1831    tmp=m->content;
1832
1833  nc2=xmlNewNode(ns_ows, BAD_CAST "Identifier");
1834  if(e!=NULL)
1835    nc3=xmlNewText(BAD_CAST e->name);
1836  else
1837    nc3=xmlNewText(BAD_CAST m->name);
1838
1839  xmlAddChild(nc2,nc3);
1840  xmlAddChild(nc1,nc2);
1841  xmlAddChild(nc,nc1);
1842  if(e!=NULL)
1843    tmp=getMap(e->content,"Title");
1844  else
1845    tmp=getMap(m->content,"Title");
1846 
1847  if(tmp!=NULL){
1848    nc2=xmlNewNode(ns_ows, BAD_CAST tmp->name);
1849    nc3=xmlNewText(BAD_CAST _ss(tmp->value));
1850    xmlAddChild(nc2,nc3); 
1851    xmlAddChild(nc1,nc2);
1852  }
1853
1854  if(e!=NULL)
1855    tmp=getMap(e->content,"Abstract");
1856  else
1857    tmp=getMap(m->content,"Abstract");
1858
1859  if(tmp!=NULL){
1860    nc2=xmlNewNode(ns_ows, BAD_CAST tmp->name);
1861    nc3=xmlNewText(BAD_CAST _ss(tmp->value));
1862    xmlAddChild(nc2,nc3); 
1863    xmlAddChild(nc1,nc2);
1864    xmlAddChild(nc,nc1);
1865  }
1866
1867  /**
1868   * IO type Reference or full Data ?
1869   */
1870  map *tmpMap=getMap(m->content,"Reference");
1871  if(tmpMap==NULL){
1872    nc2=xmlNewNode(ns_wps, BAD_CAST "Data");
1873    if(e!=NULL){
1874      if(strncasecmp(e->format,"LiteralOutput",strlen(e->format))==0)
1875        nc3=xmlNewNode(ns_wps, BAD_CAST "LiteralData");
1876      else
1877        if(strncasecmp(e->format,"ComplexOutput",strlen(e->format))==0)
1878          nc3=xmlNewNode(ns_wps, BAD_CAST "ComplexData");
1879        else if(strncasecmp(e->format,"BoundingBoxOutput",strlen(e->format))==0)
1880          nc3=xmlNewNode(ns_wps, BAD_CAST "BoundingBoxData");
1881        else
1882          nc3=xmlNewNode(ns_wps, BAD_CAST e->format);
1883    }
1884    else {
1885      map* tmpV=getMapFromMaps(m,"format","value");
1886      if(tmpV!=NULL)
1887        nc3=xmlNewNode(ns_wps, BAD_CAST tmpV->value);
1888      else
1889        nc3=xmlNewNode(ns_wps, BAD_CAST "LiteralData");
1890    } 
1891    tmp=m->content;
1892
1893    while(tmp!=NULL){
1894      if(strcasecmp(tmp->name,"mimeType")==0 ||
1895         strcasecmp(tmp->name,"encoding")==0 ||
1896         strcasecmp(tmp->name,"schema")==0 ||
1897         strcasecmp(tmp->name,"datatype")==0 ||
1898         strcasecmp(tmp->name,"uom")==0) {
1899
1900        xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST tmp->value);
1901      }
1902      tmp=tmp->next;
1903      xmlAddChild(nc2,nc3);
1904    }
1905    if(e!=NULL && e->format!=NULL && strcasecmp(e->format,"BoundingBoxData")==0) {
1906      map* bb=getMap(m->content,"value");
1907      if(bb!=NULL) {
1908        map* tmpRes=parseBoundingBox(bb->value);
1909        printBoundingBox(ns_ows,nc3,tmpRes);
1910        freeMap(&tmpRes);
1911        free(tmpRes);
1912      }
1913    }
1914    else {
1915      if(e!=NULL)
1916        tmp=getMap(e->defaults->content,"mimeType");
1917      else
1918        tmp=NULL;
1919       
1920      map* tmp1=getMap(m->content,"encoding");
1921      map* tmp2=getMap(m->content,"mimeType");
1922      map* tmp3=getMap(m->content,"value");
1923      int hasValue=1;
1924      if(tmp3==NULL){
1925        tmp3=createMap("value","");
1926        hasValue=-1;
1927      }
1928
1929      if( ( tmp1 != NULL && strncmp(tmp1->value,"base64",6) == 0 )     // if encoding is base64
1930          ||                                                           // or if
1931          ( tmp2 != NULL && ( strstr(tmp2->value,"text") == NULL       //  mime type is not text
1932                              &&                                       //  nor
1933                              strstr(tmp2->value,"xml") == NULL        //  xml
1934                              &&                                       // nor
1935                              strstr(tmp2->value,"javascript") == NULL // javascript
1936                              &&
1937                              strstr(tmp2->value,"json") == NULL
1938                              &&
1939                              strstr(tmp2->value,"ecmascript") == NULL
1940                              &&
1941                              // include for backwards compatibility,
1942                              // although correct mime type is ...kml+xml:
1943                              strstr(tmp2->value,"google-earth.kml") == NULL                                                    )
1944            )
1945          ) {                                                    // then       
1946        map* rs=getMap(m->content,"size");                       // obtain size
1947        bool isSized=true;
1948        if(rs==NULL){
1949          char tmp1[1024];
1950          sprintf(tmp1,"%ld",strlen(tmp3->value));
1951          rs=createMap("size",tmp1);
1952          isSized=false;
1953        }
1954         
1955        xmlAddChild(nc3,xmlNewText(BAD_CAST base64(tmp3->value, atoi(rs->value))));  // base 64 encode in XML
1956               
1957        if(tmp1==NULL || (tmp1!=NULL && strncmp(tmp1->value,"base64",6)!=0)) {
1958          xmlAttrPtr ap = xmlHasProp(nc3, BAD_CAST "encoding");
1959          if (ap != NULL) {
1960            xmlRemoveProp(ap);
1961          }                     
1962          xmlNewProp(nc3,BAD_CAST "encoding",BAD_CAST "base64");
1963        }
1964               
1965        if(!isSized){
1966          freeMap(&rs);
1967          free(rs);
1968        }
1969      }
1970      else if (tmp2!=NULL) {                                 // else (text-based format)
1971        if(strstr(tmp2->value, "javascript") != NULL ||      //    if javascript put code in CDATA block
1972           strstr(tmp2->value, "json") != NULL ||            //    (will not be parsed by XML reader)
1973           strstr(tmp2->value, "ecmascript") != NULL
1974           ) {
1975          xmlAddChild(nc3,xmlNewCDataBlock(doc,BAD_CAST tmp3->value,strlen(tmp3->value)));
1976        }   
1977        else {                                                     // else
1978          if (strstr(tmp2->value, "xml") != NULL ||                 // if XML-based format
1979              // include for backwards compatibility,
1980              // although correct mime type is ...kml+xml:                 
1981              strstr(tmp2->value, "google-earth.kml") != NULL
1982              ) { 
1983                         
1984            int li=zooXmlAddDoc(tmp3->value);
1985            xmlDocPtr doc = iDocs[li];
1986            xmlNodePtr ir = xmlDocGetRootElement(doc);
1987            xmlAddChild(nc3,ir);
1988          }
1989          else                                                     // else     
1990            xmlAddChild(nc3,xmlNewText(BAD_CAST tmp3->value));    //   add text node
1991        }
1992        xmlAddChild(nc2,nc3);
1993      }
1994      else {
1995        xmlAddChild(nc3,xmlNewText(BAD_CAST tmp3->value));
1996      }
1997         
1998      if(hasValue<0) {
1999        freeMap(&tmp3);
2000        free(tmp3);
2001      }
2002    }
2003  }
2004  else { // Reference
2005    tmpMap=getMap(m->content,"Reference");
2006    nc3=nc2=xmlNewNode(ns_wps, BAD_CAST "Reference");
2007    if(strcasecmp(type,"Output")==0)
2008      xmlNewProp(nc3,BAD_CAST "href",BAD_CAST tmpMap->value);
2009    else
2010      xmlNewNsProp(nc3,ns_xlink,BAD_CAST "href",BAD_CAST tmpMap->value);
2011   
2012    tmp=m->content;
2013    while(tmp!=NULL) {
2014      if(strcasecmp(tmp->name,"mimeType")==0 ||
2015         strcasecmp(tmp->name,"encoding")==0 ||
2016         strcasecmp(tmp->name,"schema")==0 ||
2017         strcasecmp(tmp->name,"datatype")==0 ||
2018         strcasecmp(tmp->name,"uom")==0){
2019
2020        if(strcasecmp(tmp->name,"datatype")==0)
2021          xmlNewProp(nc3,BAD_CAST "mimeType",BAD_CAST "text/plain");
2022        else
2023          xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST tmp->value);
2024      }
2025      tmp=tmp->next;
2026      xmlAddChild(nc2,nc3);
2027    }
2028  }
2029  xmlAddChild(nc1,nc2);
2030  xmlAddChild(nc,nc1);
2031}
2032
2033/**
2034 * Create XML node with basic ows metadata informations (Identifier,Title,Abstract)
2035 *
2036 * @param root the root XML node to add the description
2037 * @param ns_ows the ows XML namespace
2038 * @param identifier the identifier to use
2039 * @param amap the map containing the ows metadata informations
2040 */
2041void printDescription(xmlNodePtr root,xmlNsPtr ns_ows,const char* identifier,map* amap,int vid=0){
2042  xmlNodePtr nc2;
2043  if(vid==0){
2044    nc2 = xmlNewNode(ns_ows, BAD_CAST "Identifier");
2045    xmlAddChild(nc2,xmlNewText(BAD_CAST identifier));
2046    xmlAddChild(root,nc2);
2047  }
2048  map* tmp=amap;
2049  const char *tmp2[2];
2050  tmp2[0]="Title";
2051  tmp2[1]="Abstract";
2052  int j=0;
2053  for(j=0;j<2;j++){
2054    map* tmp1=getMap(tmp,tmp2[j]);
2055    if(tmp1!=NULL){
2056      nc2 = xmlNewNode(ns_ows, BAD_CAST tmp2[j]);
2057      xmlAddChild(nc2,xmlNewText(BAD_CAST _ss(tmp1->value)));
2058      xmlAddChild(root,nc2);
2059    }
2060  }
2061  if(vid==1){
2062    nc2 = xmlNewNode(ns_ows, BAD_CAST "Identifier");
2063    xmlAddChild(nc2,xmlNewText(BAD_CAST identifier));
2064    xmlAddChild(root,nc2);
2065  }
2066}
2067
2068/**
2069 * Print an OWS ExceptionReport Document and HTTP headers (when required)
2070 * depending on the code.
2071 * Set hasPrinted value to true in the [lenv] section.
2072 *
2073 * @param m the maps containing the settings of the main.cfg file
2074 * @param s the map containing the text,code,locator keys
2075 */
2076void printExceptionReportResponse(maps* m,map* s){
2077  if(getMapFromMaps(m,"lenv","hasPrinted")!=NULL)
2078    return;
2079  int buffersize;
2080  xmlDocPtr doc;
2081  xmlChar *xmlbuff;
2082  xmlNodePtr n;
2083
2084  zooXmlCleanupNs();
2085  doc = xmlNewDoc(BAD_CAST "1.0");
2086  maps* tmpMap=getMaps(m,"main");
2087  char *encoding=getEncoding(tmpMap);
2088  const char *exceptionCode;
2089 
2090  map* tmp=getMap(s,"code");
2091  if(tmp!=NULL){
2092    if(strcmp(tmp->value,"OperationNotSupported")==0 ||
2093       strcmp(tmp->value,"NoApplicableCode")==0)
2094      exceptionCode="501 Not Implemented";
2095    else
2096      if(strcmp(tmp->value,"MissingParameterValue")==0 ||
2097         strcmp(tmp->value,"InvalidUpdateSequence")==0 ||
2098         strcmp(tmp->value,"OptionNotSupported")==0 ||
2099         strcmp(tmp->value,"VersionNegotiationFailed")==0 ||
2100         strcmp(tmp->value,"InvalidParameterValue")==0)
2101        exceptionCode="400 Bad request";
2102      else
2103        exceptionCode="501 Internal Server Error";
2104  }
2105  else
2106    exceptionCode="501 Internal Server Error";
2107
2108  if(m!=NULL){
2109    map *tmpSid=getMapFromMaps(m,"lenv","sid");
2110    if(tmpSid!=NULL){
2111      if( getpid()==atoi(tmpSid->value) ){
2112        printHeaders(m);
2113        printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode);
2114      }
2115    }
2116    else{
2117      printHeaders(m);
2118      printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode);
2119    }
2120  }else{
2121    printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode);
2122  }
2123  n=createExceptionReportNode(m,s,1);
2124  xmlDocSetRootElement(doc, n);
2125  xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);
2126  printf("%s",xmlbuff);
2127  fflush(stdout);
2128  xmlFreeDoc(doc);
2129  xmlFree(xmlbuff);
2130  xmlCleanupParser();
2131  zooXmlCleanupNs();
2132  if(m!=NULL)
2133    setMapInMaps(m,"lenv","hasPrinted","true");
2134}
2135
2136/**
2137 * Create an OWS ExceptionReport Node.
2138 *
2139 * @param m the conf maps
2140 * @param s the map containing the text,code,locator keys
2141 * @param use_ns (0/1) choose if you want to generate an ExceptionReport or
2142 *  ows:ExceptionReport node respectively
2143 * @return the ExceptionReport/ows:ExceptionReport node
2144 */
2145xmlNodePtr createExceptionReportNode(maps* m,map* s,int use_ns){
2146 
2147  xmlNsPtr ns,ns_xsi;
2148  xmlNodePtr n,nc,nc1;
2149
2150  int nsid=zooXmlAddNs(NULL,"http://www.opengis.net/ows","ows");
2151  ns=usedNs[nsid];
2152  if(use_ns==0){
2153    ns=NULL;
2154  }
2155  n = xmlNewNode(ns, BAD_CAST "ExceptionReport");
2156  if(use_ns==1){
2157    xmlNewNs(n,BAD_CAST "http://www.opengis.net/ows/1.1",BAD_CAST"ows");
2158    int xsiId=zooXmlAddNs(n,"http://www.w3.org/2001/XMLSchema-instance","xsi");
2159    ns_xsi=usedNs[xsiId];
2160    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");
2161  }
2162
2163
2164  addLangAttr(n,m);
2165  xmlNewProp(n,BAD_CAST "version",BAD_CAST "1.1.0");
2166 
2167  int length=1;
2168  int cnt=0;
2169  map* len=getMap(s,"length");
2170  if(len!=NULL)
2171    length=atoi(len->value);
2172  for(cnt=0;cnt<length;cnt++){
2173    nc = xmlNewNode(ns, BAD_CAST "Exception");
2174   
2175    map* tmp=getMapArray(s,"code",cnt);
2176    if(tmp==NULL)
2177      tmp=getMap(s,"code");
2178    if(tmp!=NULL)
2179      xmlNewProp(nc,BAD_CAST "exceptionCode",BAD_CAST tmp->value);
2180    else
2181      xmlNewProp(nc,BAD_CAST "exceptionCode",BAD_CAST "NoApplicableCode");
2182   
2183    tmp=getMapArray(s,"locator",cnt);
2184    if(tmp==NULL)
2185      tmp=getMap(s,"locator");
2186    if(tmp!=NULL && strcasecmp(tmp->value,"NULL")!=0)
2187      xmlNewProp(nc,BAD_CAST "locator",BAD_CAST tmp->value);
2188
2189    tmp=getMapArray(s,"text",cnt);
2190    nc1 = xmlNewNode(ns, BAD_CAST "ExceptionText");
2191    if(tmp!=NULL){
2192      xmlNodePtr txt=xmlNewText(BAD_CAST tmp->value);
2193      xmlAddChild(nc1,txt);
2194    }
2195    else{
2196      xmlNodeSetContent(nc1, BAD_CAST _("No debug message available"));
2197    }
2198    xmlAddChild(nc,nc1);
2199    xmlAddChild(n,nc);
2200  }
2201  return n;
2202}
2203
2204/**
2205 * Print an OWS ExceptionReport.
2206 *
2207 * @param m the conf maps
2208 * @param message the error message
2209 * @param errorcode the error code
2210 * @param locator the potential locator
2211 */
2212int errorException(maps *m, const char *message, const char *errorcode, const char *locator) 
2213{
2214  map* errormap = createMap("text", message);
2215  addToMap(errormap,"code", errorcode);
2216  if(locator!=NULL)
2217    addToMap(errormap,"locator", locator);
2218  else
2219    addToMap(errormap,"locator", "NULL");
2220  printExceptionReportResponse(m,errormap);
2221  freeMap(&errormap);
2222  free(errormap);
2223  return -1;
2224}
2225
2226/**
2227 * Generate the output response (RawDataOutput or ResponseDocument)
2228 *
2229 * @param s the service structure containing the metadata informations
2230 * @param request_inputs the inputs provided to the service for execution
2231 * @param request_outputs the outputs updated by the service execution
2232 * @param request_inputs1 the map containing the HTTP request
2233 * @param cpid the process identifier attached to a service execution
2234 * @param m the conf maps containing the main.cfg settings
2235 * @param res the value returned by the service execution
2236 */
2237void outputResponse(service* s,maps* request_inputs,maps* request_outputs,
2238                    map* request_inputs1,int cpid,maps* m,int res){
2239#ifdef DEBUG
2240  dumpMaps(request_inputs);
2241  dumpMaps(request_outputs);
2242  fprintf(stderr,"printProcessResponse\n");
2243#endif
2244  map* toto=getMap(request_inputs1,"RawDataOutput");
2245  int asRaw=0;
2246  if(toto!=NULL)
2247    asRaw=1;
2248 
2249  maps* tmpSess=getMaps(m,"senv");
2250  if(tmpSess!=NULL){
2251    map *_tmp=getMapFromMaps(m,"lenv","cookie");
2252    char* sessId=NULL;
2253    if(_tmp!=NULL){
2254      printf("Set-Cookie: %s; HttpOnly\r\n",_tmp->value);
2255      printf("P3P: CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"\r\n");
2256      char session_file_path[100];
2257      char *tmp1=strtok(_tmp->value,";");
2258      if(tmp1!=NULL)
2259        sprintf(session_file_path,"%s",strstr(tmp1,"=")+1);
2260      else
2261        sprintf(session_file_path,"%s",strstr(_tmp->value,"=")+1);
2262      sessId=strdup(session_file_path);
2263    }else{
2264      maps* t=getMaps(m,"senv");
2265      map*p=t->content;
2266      while(p!=NULL){
2267        if(strstr(p->name,"ID")!=NULL){
2268          sessId=strdup(p->value);
2269          break;
2270        }
2271        p=p->next;
2272      }
2273    }
2274    char session_file_path[1024];
2275    map *tmpPath=getMapFromMaps(m,"main","sessPath");
2276    if(tmpPath==NULL)
2277      tmpPath=getMapFromMaps(m,"main","tmpPath");
2278    sprintf(session_file_path,"%s/sess_%s.cfg",tmpPath->value,sessId);
2279    FILE* teste=fopen(session_file_path,"w");
2280    if(teste==NULL){
2281      char tmpMsg[1024];
2282      sprintf(tmpMsg,_("Unable to create the file \"%s\" for storing the session maps."),session_file_path);
2283      errorException(m,tmpMsg,"InternalError",NULL);
2284
2285      return;
2286    }
2287    else{
2288      fclose(teste);
2289      dumpMapsToFile(tmpSess,session_file_path);
2290    }
2291  }
2292 
2293  if(res==SERVICE_FAILED){
2294    map *lenv;
2295    lenv=getMapFromMaps(m,"lenv","message");
2296    char *tmp0;
2297    if(lenv!=NULL){
2298      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));
2299      sprintf(tmp0,_("Unable to run the Service. The message returned back by the Service was the following: %s"),lenv->value);
2300    }
2301    else{
2302      tmp0=(char*)malloc((strlen(_("Unable to run the Service. No more information was returned back by the Service."))+1)*sizeof(char));
2303      sprintf(tmp0,"%s",_("Unable to run the Service. No more information was returned back by the Service."));
2304    }
2305    errorException(m,tmp0,"InternalError",NULL);
2306    free(tmp0);
2307    return;
2308  }
2309
2310
2311  map *tmp1=getMapFromMaps(m,"main","tmpPath");
2312  if(asRaw==0){
2313#ifdef DEBUG
2314    fprintf(stderr,"REQUEST_OUTPUTS FINAL\n");
2315    dumpMaps(request_outputs);
2316#endif
2317    maps* tmpI=request_outputs;
2318
2319    while(tmpI!=NULL){
2320#ifdef USE_MS
2321      map* testMap=getMap(tmpI->content,"useMapserver");       
2322#endif
2323      map *gfile=getMap(tmpI->content,"generated_file");
2324      char *file_name;
2325      if(gfile!=NULL){
2326        gfile=getMap(tmpI->content,"expected_generated_file");
2327        if(gfile==NULL){
2328          gfile=getMap(tmpI->content,"generated_file");
2329        }
2330        readGeneratedFile(m,tmpI->content,gfile->value);           
2331        file_name=(char*)malloc((strlen(gfile->value)+strlen(tmp1->value)+1)*sizeof(char));
2332        for(int i=0;i<strlen(gfile->value);i++)
2333          file_name[i]=gfile->value[i+strlen(tmp1->value)];
2334      }
2335
2336      toto=getMap(tmpI->content,"asReference");
2337#ifdef USE_MS
2338      if(toto!=NULL && strcasecmp(toto->value,"true")==0 && testMap==NULL)
2339#else
2340      if(toto!=NULL && strcasecmp(toto->value,"true")==0)
2341#endif
2342        {
2343          elements* in=getElements(s->outputs,tmpI->name);
2344          char *format=NULL;
2345          if(in!=NULL){
2346            format=strdup(in->format);
2347          }else
2348            format=strdup("LiteralData");
2349          if(strcasecmp(format,"BoundingBoxData")==0){
2350            addToMap(tmpI->content,"extension","xml");
2351            addToMap(tmpI->content,"mimeType","text/xml");
2352            addToMap(tmpI->content,"encoding","UTF-8");
2353            addToMap(tmpI->content,"schema","http://schemas.opengis.net/ows/1.1.0/owsCommon.xsd");
2354          }
2355
2356          if(gfile==NULL){
2357            map *ext=getMap(tmpI->content,"extension");
2358            char *file_path;
2359            char file_ext[32];
2360
2361            if( ext != NULL && ext->value != NULL) {
2362              strncpy(file_ext, ext->value, 32);
2363            }
2364            else {
2365              // Obtain default file extension (see mimetypes.h).             
2366              // If the MIME type is not recognized, txt is used as the default extension
2367              map* mtype=getMap(tmpI->content,"mimeType");
2368              getFileExtension(mtype != NULL ? mtype->value : NULL, file_ext, 32);
2369            }
2370               
2371            file_name=(char*)malloc((strlen(s->name)+strlen(file_ext)+strlen(tmpI->name)+1024)*sizeof(char));
2372            int cpid0=cpid+time(NULL);     
2373            sprintf(file_name,"%s_%s_%i.%s",s->name,tmpI->name,cpid0,file_ext);
2374            file_path=(char*)malloc((strlen(tmp1->value)+strlen(file_name)+2)*sizeof(char));
2375            sprintf(file_path,"%s/%s",tmp1->value,file_name);
2376   
2377                FILE *ofile=fopen(file_path,"wb");
2378            if(ofile==NULL){
2379              char tmpMsg[1024];
2380              sprintf(tmpMsg,_("Unable to create the file \"%s\" for storing the %s final result."),file_name,tmpI->name);
2381              errorException(m,tmpMsg,"InternalError",NULL);
2382              free(file_name);
2383              free(file_path);
2384              return;
2385            }
2386            free(file_path);
2387
2388            toto=getMap(tmpI->content,"value");
2389            if(strcasecmp(format,"BoundingBoxData")!=0){
2390              map* size=getMap(tmpI->content,"size");
2391              if(size!=NULL && toto!=NULL)
2392                fwrite(toto->value,1,(atoi(size->value))*sizeof(char),ofile);
2393              else
2394                if(toto!=NULL && toto->value!=NULL)
2395                  fwrite(toto->value,1,strlen(toto->value)*sizeof(char),ofile);
2396            }else{
2397              printBoundingBoxDocument(m,tmpI,ofile);
2398            }
2399            fclose(ofile);
2400
2401          }
2402          map *tmp2=getMapFromMaps(m,"main","tmpUrl");
2403          map *tmp3=getMapFromMaps(m,"main","serverAddress");
2404          char *file_url;
2405          if(strncasecmp(tmp2->value,"http://",7)==0 ||
2406             strncasecmp(tmp2->value,"https://",8)==0){
2407            file_url=(char*)malloc((strlen(tmp2->value)+strlen(file_name)+2)*sizeof(char));
2408            sprintf(file_url,"%s/%s",tmp2->value,file_name);
2409          }else{
2410            file_url=(char*)malloc((strlen(tmp3->value)+strlen(tmp2->value)+strlen(file_name)+3)*sizeof(char));
2411            sprintf(file_url,"%s/%s/%s",tmp3->value,tmp2->value,file_name);
2412          }
2413          addToMap(tmpI->content,"Reference",file_url);
2414          free(format);
2415          free(file_name);
2416          free(file_url);       
2417         
2418        }
2419#ifdef USE_MS
2420      else{
2421        if(testMap!=NULL){
2422          setReferenceUrl(m,tmpI);
2423        }
2424      }
2425#endif
2426      tmpI=tmpI->next;
2427    }
2428    map *r_inputs=getMap(s->content,"serviceProvider");
2429#ifdef DEBUG
2430    fprintf(stderr,"SERVICE : %s\n",r_inputs->value);
2431    dumpMaps(m);
2432#endif
2433    printProcessResponse(m,request_inputs1,cpid,
2434                //       s,r_inputs->value,res,
2435                         s, s->name,res,  // replace serviceProvider with serviceName in stored response file name
2436                         request_inputs,
2437                         request_outputs);
2438  }
2439  else{
2440    /**
2441     * We get the requested output or fallback to the first one if the
2442     * requested one is not present in the resulting outputs maps.
2443     */
2444    maps* tmpI=NULL;
2445    map* tmpIV=getMap(request_inputs1,"RawDataOutput");
2446    if(tmpIV!=NULL){
2447      tmpI=getMaps(request_outputs,tmpIV->value);
2448    }
2449    if(tmpI==NULL)
2450      tmpI=request_outputs;
2451    elements* e=getElements(s->outputs,tmpI->name);
2452    if(e!=NULL && strcasecmp(e->format,"BoundingBoxData")==0){
2453      printBoundingBoxDocument(m,tmpI,NULL);
2454    }else{
2455      map *gfile=getMap(tmpI->content,"generated_file");
2456      if(gfile!=NULL){
2457        gfile=getMap(tmpI->content,"expected_generated_file");
2458        if(gfile==NULL){
2459          gfile=getMap(tmpI->content,"generated_file");
2460        }
2461        readGeneratedFile(m,tmpI->content,gfile->value);
2462      }
2463      toto=getMap(tmpI->content,"value");
2464      if(toto==NULL){
2465        char tmpMsg[1024];
2466        sprintf(tmpMsg,_("Wrong RawDataOutput parameter: unable to fetch any result for the given parameter name: \"%s\"."),tmpI->name);
2467        errorException(m,tmpMsg,"InvalidParameterValue","RawDataOutput");
2468        return;
2469      }
2470      map* fname=getMapFromMaps(tmpI,tmpI->name,"filename");
2471      if(fname!=NULL)
2472        printf("Content-Disposition: attachment; filename=\"%s\"\r\n",fname->value);
2473      map* rs=getMapFromMaps(tmpI,tmpI->name,"size");
2474      if(rs!=NULL)
2475        printf("Content-Length: %s\r\n",rs->value);
2476      printHeaders(m);
2477      char mime[1024];
2478      map* mi=getMap(tmpI->content,"mimeType");
2479#ifdef DEBUG
2480      fprintf(stderr,"SERVICE OUTPUTS\n");
2481      dumpMaps(request_outputs);
2482      fprintf(stderr,"SERVICE OUTPUTS\n");
2483#endif
2484      map* en=getMap(tmpI->content,"encoding");
2485      if(mi!=NULL && en!=NULL)
2486        sprintf(mime,
2487                "Content-Type: %s; charset=%s\r\nStatus: 200 OK\r\n\r\n",
2488                mi->value,en->value);
2489      else
2490        if(mi!=NULL)
2491          sprintf(mime,
2492                  "Content-Type: %s; charset=UTF-8\r\nStatus: 200 OK\r\n\r\n",
2493                  mi->value);
2494        else
2495          sprintf(mime,"Content-Type: text/plain; charset=utf-8\r\nStatus: 200 OK\r\n\r\n");
2496      printf("%s",mime);
2497      if(rs!=NULL)
2498        fwrite(toto->value,1,atoi(rs->value),stdout);
2499      else
2500        fwrite(toto->value,1,strlen(toto->value),stdout);
2501#ifdef DEBUG
2502      dumpMap(toto);
2503#endif
2504    }
2505  }
2506}
2507
2508/**
2509 * Create required XML nodes for boundingbox and update the current XML node
2510 *
2511 * @param ns_ows the ows XML namespace
2512 * @param n the XML node to update
2513 * @param boundingbox the map containing the boundingbox definition
2514 */
2515void printBoundingBox(xmlNsPtr ns_ows,xmlNodePtr n,map* boundingbox){
2516
2517  xmlNodePtr lw=NULL,uc=NULL;
2518
2519  map* tmp=getMap(boundingbox,"value");
2520
2521  tmp=getMap(boundingbox,"lowerCorner");
2522  if(tmp!=NULL){
2523    lw=xmlNewNode(ns_ows,BAD_CAST "LowerCorner");
2524    xmlAddChild(lw,xmlNewText(BAD_CAST tmp->value));
2525  }
2526
2527  tmp=getMap(boundingbox,"upperCorner");
2528  if(tmp!=NULL){
2529    uc=xmlNewNode(ns_ows,BAD_CAST "UpperCorner");
2530    xmlAddChild(uc,xmlNewText(BAD_CAST tmp->value));
2531  }
2532
2533  tmp=getMap(boundingbox,"crs");
2534  if(tmp!=NULL)
2535    xmlNewProp(n,BAD_CAST "crs",BAD_CAST tmp->value);
2536
2537  tmp=getMap(boundingbox,"dimensions");
2538  if(tmp!=NULL)
2539    xmlNewProp(n,BAD_CAST "dimensions",BAD_CAST tmp->value);
2540
2541  xmlAddChild(n,lw);
2542  xmlAddChild(n,uc);
2543
2544}
2545
2546/**
2547 * Parse a BoundingBox string
2548 *
2549 * [OGC 06-121r3](http://portal.opengeospatial.org/files/?artifact_id=20040):
2550 *  10.2 Bounding box
2551 *
2552 *
2553 * Value is provided as : lowerCorner,upperCorner,crs,dimension
2554 * Exemple : 189000,834000,285000,962000,urn:ogc:def:crs:OGC:1.3:CRS84
2555 *
2556 * A map to store boundingbox informations should contain:
2557 *  - lowerCorner : double,double (minimum within this bounding box)
2558 *  - upperCorner : double,double (maximum within this bounding box)
2559 *  - crs : URI (Reference to definition of the CRS)
2560 *  - dimensions : int
2561 *
2562 * Note : support only 2D bounding box.
2563 *
2564 * @param value the char* containing the KVP bouding box
2565 * @return a map containing all the bounding box keys
2566 */
2567map* parseBoundingBox(const char* value){
2568  map *res=NULL;
2569  if(value!=NULL){
2570    char *cv,*cvp;
2571    cv=strtok_r((char*) value,",",&cvp);
2572    int cnt=0;
2573    int icnt=0;
2574    char *currentValue=NULL;
2575    while(cv){
2576      if(cnt<2)
2577        if(currentValue!=NULL){
2578          char *finalValue=(char*)malloc((strlen(currentValue)+strlen(cv)+1)*sizeof(char));
2579          sprintf(finalValue,"%s%s",currentValue,cv);
2580          switch(cnt){
2581          case 0:
2582            res=createMap("lowerCorner",finalValue);
2583            break;
2584          case 1:
2585            addToMap(res,"upperCorner",finalValue);
2586            icnt=-1;
2587            break;
2588          }
2589          cnt++;
2590          free(currentValue);
2591          currentValue=NULL;
2592          free(finalValue);
2593        }
2594        else{
2595          currentValue=(char*)malloc((strlen(cv)+2)*sizeof(char));
2596          sprintf(currentValue,"%s ",cv);
2597        }
2598      else
2599        if(cnt==2){
2600          addToMap(res,"crs",cv);
2601          cnt++;
2602        }
2603        else
2604          addToMap(res,"dimensions",cv);
2605      icnt++;
2606      cv=strtok_r(NULL,",",&cvp);
2607    }
2608  }
2609  return res;
2610}
2611
2612/**
2613 * Print an ows:BoundingBox XML document
2614 *
2615 * @param m the maps containing the settings of the main.cfg file
2616 * @param boundingbox the maps containing the boundingbox definition
2617 * @param file the file to print the BoundingBox (if NULL then print on stdout)
2618 * @see parseBoundingBox, printBoundingBox
2619 */
2620void printBoundingBoxDocument(maps* m,maps* boundingbox,FILE* file){
2621  if(file==NULL)
2622    rewind(stdout);
2623  xmlNodePtr n;
2624  xmlDocPtr doc;
2625  xmlNsPtr ns_ows,ns_xsi;
2626  xmlChar *xmlbuff;
2627  int buffersize;
2628  char *encoding=getEncoding(m);
2629  map *tmp;
2630  if(file==NULL){
2631    int pid=0;
2632    tmp=getMapFromMaps(m,"lenv","sid");
2633    if(tmp!=NULL)
2634      pid=atoi(tmp->value);
2635    if(pid==getpid()){
2636      printf("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding);
2637    }
2638    fflush(stdout);
2639  }
2640
2641  doc = xmlNewDoc(BAD_CAST "1.0");
2642  int owsId=zooXmlAddNs(NULL,"http://www.opengis.net/ows/1.1","ows");
2643  ns_ows=usedNs[owsId];
2644  n = xmlNewNode(ns_ows, BAD_CAST "BoundingBox");
2645  xmlNewNs(n,BAD_CAST "http://www.opengis.net/ows/1.1",BAD_CAST "ows");
2646  int xsiId=zooXmlAddNs(n,"http://www.w3.org/2001/XMLSchema-instance","xsi");
2647  ns_xsi=usedNs[xsiId];
2648  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");
2649  map *tmp1=getMap(boundingbox->content,"value");
2650  tmp=parseBoundingBox(tmp1->value);
2651  printBoundingBox(ns_ows,n,tmp);
2652  xmlDocSetRootElement(doc, n);
2653
2654  xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);
2655  if(file==NULL)
2656    printf("%s",xmlbuff);
2657  else{
2658    fprintf(file,"%s",xmlbuff);
2659  }
2660
2661  if(tmp!=NULL){
2662    freeMap(&tmp);
2663    free(tmp);
2664  }
2665  xmlFree(xmlbuff);
2666  xmlFreeDoc(doc);
2667  xmlCleanupParser();
2668  zooXmlCleanupNs();
2669 
2670}
2671
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