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

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

Fix issue in kvParseInput when memory!=load and handle session from the OGC API - Processes

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