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

Last change on this file since 641 was 641, checked in by djay, 7 years ago

Adding missing file

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

Search

Context Navigation

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