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

Last change on this file since 921 was 921, checked in by djay, 5 years ago

Fix issue building with gcc 7.3.0

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

Search

ZOO Sponsors

http://www.zoo-project.org/trac/chrome/site/img/geolabs-logo.pnghttp://www.zoo-project.org/trac/chrome/site/img/neogeo-logo.png http://www.zoo-project.org/trac/chrome/site/img/apptech-logo.png http://www.zoo-project.org/trac/chrome/site/img/3liz-logo.png http://www.zoo-project.org/trac/chrome/site/img/gateway-logo.png

Become a sponsor !

Knowledge partners

http://www.zoo-project.org/trac/chrome/site/img/ocu-logo.png http://www.zoo-project.org/trac/chrome/site/img/gucas-logo.png http://www.zoo-project.org/trac/chrome/site/img/polimi-logo.png http://www.zoo-project.org/trac/chrome/site/img/fem-logo.png http://www.zoo-project.org/trac/chrome/site/img/supsi-logo.png http://www.zoo-project.org/trac/chrome/site/img/cumtb-logo.png

Become a knowledge partner

Related links

http://zoo-project.org/img/ogclogo.png http://zoo-project.org/img/osgeologo.png