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

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

Update OGC API - Processes documentation and implementation, providing a browsable User Interface to Processes.

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