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

Last change on this file since 926 was 926, checked in by djay, 3 years ago

Fix issue with version parameter for GetCapabilities?, issue with DescribeProcess? (version 2.0.0) and fix to build on MacOS

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