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

Last change on this file was 967, checked in by djay, 10 months ago

Add support for the two inputs / outputs syntaxes discussed in SWG in both the ZOO-Kernel and the HTML basic UI. Update documentation, add a section for the ZOO-API in Python language section. Rename variables in service.c to ease readabiliy.

  • Property svn:keywords set to Id
File size: 97.1 KB
Line 
1/*
2 * Author : Gérald FENOY
3 *
4 * Copyright (c) 2009-2020 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#include "service_json.h"
44
45/**
46 * Add prefix to the service name.
47 *
48 * @param pmsConf the conf maps containing the main.cfg settings
49 * @param pmLevel the map containing the level information
50 * @param psService the service structure created from the zcfg file
51 */
52void addPrefix(maps* pmsConf,map* pmLevel,service* psService){
53  if(pmLevel!=NULL){
54    char acKey[25];
55    char* pcaPrefix=NULL;
56    int iClevel=atoi(pmLevel->value);
57    int iCl=0;
58    for(iCl=0;iCl<iClevel;iCl++){
59      sprintf(acKey,"sprefix_%d",iCl);
60      map* tmp2=getMapFromMaps(pmsConf,"lenv",acKey);
61      if(tmp2!=NULL){
62        if(pcaPrefix==NULL)
63          pcaPrefix=zStrdup(tmp2->value);
64        else{
65          int plen=strlen(pcaPrefix);
66          pcaPrefix=(char*)realloc(pcaPrefix,(plen+strlen(tmp2->value)+2)*sizeof(char));
67          memcpy(pcaPrefix+plen,tmp2->value,strlen(tmp2->value)*sizeof(char));
68          pcaPrefix[plen+strlen(tmp2->value)]=0;
69        }
70      }
71    }
72    if(pcaPrefix!=NULL){
73      char* pcaTmp=zStrdup(psService->name);
74      free(psService->name);
75      psService->name=(char*)malloc((strlen(pcaPrefix)+strlen(pcaTmp)+1)*sizeof(char));
76      sprintf(psService->name,"%s%s",pcaPrefix,pcaTmp);
77      free(pcaTmp);
78      free(pcaPrefix);
79      pcaPrefix=NULL;
80    }
81  }
82}
83
84/**
85 * Print the HTTP headers based on a map.
86 *
87 * @param pmsConf the map containing the headers information
88 */
89void printHeaders(maps* pmsConf){
90  maps *pmsTmp=getMaps(pmsConf,"headers");
91  if(pmsTmp!=NULL){
92    map* pmTmp=pmsTmp->content;
93    while(pmTmp!=NULL){
94      printf("%s: %s\r\n",pmTmp->name,pmTmp->value);
95      pmTmp=pmTmp->next;
96    }
97  }
98  printSessionHeaders(pmsConf);
99}
100
101/**
102 * Print the Set-Cookie header if necessary (conf["lenv"]["cookie"]) and save
103 * the session file.
104 *
105 * The session file (sess_<SESSID>_.cfg where <SESSID> is the cookie value) is
106 * stored in the conf["main"]["tmpPath"] directory.
107 * @param pmsConf the main configuration map
108 */
109void printSessionHeaders(maps* pmsConf){
110  maps* pmsSess=getMaps(pmsConf,"senv");
111  if(pmsSess!=NULL){
112    map *pmTmp=getMapFromMaps(pmsConf,"lenv","cookie");
113    char* sessId=NULL;
114    if(pmTmp!=NULL){
115      printf("Set-Cookie: %s; HttpOnly\r\n",pmTmp->value);
116      map *pmTmp1=getMapFromMaps(pmsConf,"senv","ecookie_length");
117      if(pmTmp1!=NULL){
118        int len=atoi(pmTmp1->value);
119        int cnt=0;
120        for(cnt=0;cnt<len;cnt++){
121          map* pmTmp2=getMapArray(pmsSess->content,"ecookie",cnt);
122          if(pmTmp2!=NULL)
123            printf("Set-Cookie: %s; HttpOnly\r\n",pmTmp2->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(pmTmp->value,";");
129      if(tmp1!=NULL)
130        sprintf(session_file_path,"%s",strstr(tmp1,"=")+1);
131      else
132        sprintf(session_file_path,"%s",strstr(pmTmp->value,"=")+1);
133      sessId=zStrdup(session_file_path);
134    }else{
135      maps* t=getMaps(pmsConf,"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(pmsConf,"main","sessPath");
147    if(tmpPath==NULL)
148      tmpPath=getMapFromMaps(pmsConf,"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(pmsConf,tmpMsg,"InternalError",NULL);
155      return;
156    }
157    else{
158      fclose(teste);
159      dumpMapsToFile(pmsSess,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 * Produce the status string used in HTTP headers.
2538 *
2539 * @param pmConf the maps containing the settings of the main.cfg file
2540 * @param pmCode the map containing the error code (or a map array of the same keys)
2541 */
2542const char* produceStatusString(maps* pmConf,map* pmCode){
2543  if(pmCode!=NULL){
2544    int iI=0;
2545    for(iI=0;iI<3;iI++){
2546      int iJ=0;
2547      for(iJ=0;;iJ++){
2548        if(aapccStatusCodes[iI][iJ]==NULL)
2549          break;
2550        else{
2551          if(strcmp(aapccStatusCodes[iI][iJ],pmCode->value)==0)
2552            return aapccStatusCodes[iI][0];
2553        }
2554      }
2555    }
2556  }
2557  else{
2558    return aapccStatusCodes[3][0];
2559  }
2560}
2561
2562/**
2563 * Print an OWS ExceptionReport Document and HTTP headers (when required)
2564 * depending on the code.
2565 * Set hasPrinted value to true in the [lenv] section.
2566 *
2567 * @param m the maps containing the settings of the main.cfg file
2568 * @param s the map containing the text,code,locator keys (or a map array of the same keys)
2569 */
2570void _printExceptionReportResponse(maps* m,map* s){
2571  int buffersize;
2572  xmlDocPtr doc;
2573  xmlChar *xmlbuff;
2574  xmlNodePtr n;
2575
2576  zooXmlCleanupNs();
2577  doc = xmlNewDoc(BAD_CAST "1.0");
2578  maps* tmpMap=getMaps(m,"main");
2579  char *encoding=getEncoding(tmpMap);
2580  const char *exceptionCode;
2581 
2582  map* tmp=getMap(s,"code");
2583  exceptionCode=produceStatusString(m,tmp);
2584  tmp=getMapFromMaps(m,"lenv","status_code");
2585  if(tmp!=NULL)
2586    exceptionCode=tmp->value;
2587  if(m!=NULL){
2588    map *tmpSid=getMapFromMaps(m,"lenv","sid");
2589    if(tmpSid!=NULL){
2590      if( getpid()==atoi(tmpSid->value) ){
2591        printHeaders(m);
2592        printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode);
2593      }
2594    }
2595    else{
2596      printHeaders(m);
2597      printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode);
2598    }
2599  }else{
2600    printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode);
2601  }
2602  n=createExceptionReportNode(m,s,1);
2603  xmlDocSetRootElement(doc, n);
2604  xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);
2605  printf("%s",xmlbuff);
2606  fflush(stdout);
2607  xmlFreeDoc(doc);
2608  xmlFree(xmlbuff);
2609  xmlCleanupParser();
2610  zooXmlCleanupNs();
2611  if(m!=NULL)
2612    setMapInMaps(m,"lenv","hasPrinted","true"); 
2613}
2614
2615/**
2616 * Print an OWS ExceptionReport or exception.yaml Document and HTTP headers
2617 * (when required) depending on the code.
2618 *
2619 * @param pmsConf the maps containing the settings of the main.cfg file
2620 * @param psService the service
2621 */
2622void printExceptionReportResponse(maps* pmsConf,map* psService){
2623  if(getMapFromMaps(pmsConf,"lenv","hasPrinted")!=NULL)
2624    return;
2625  map* pmExecutionType=getMapFromMaps(pmsConf,"main","executionType");
2626  if(pmExecutionType!=NULL && strncasecmp(pmExecutionType->value,"xml",3)==0)
2627    _printExceptionReportResponse(pmsConf,psService);
2628  else
2629    printExceptionReportResponseJ(pmsConf,psService);
2630}
2631
2632/**
2633 * Create an OWS ExceptionReport Node.
2634 *
2635 * @param m the conf maps
2636 * @param s the map containing the text,code,locator keys
2637 * @param use_ns (0/1) choose if you want to generate an ExceptionReport or
2638 *  ows:ExceptionReport node respectively
2639 * @return the ExceptionReport/ows:ExceptionReport node
2640 */
2641xmlNodePtr createExceptionReportNode(maps* m,map* s,int use_ns){
2642 
2643  xmlNsPtr ns,ns_xsi;
2644  xmlNodePtr n,nc,nc1;
2645
2646  int nsid=zooXmlAddNs(NULL,"http://www.opengis.net/ows","ows");
2647  ns=usedNs[nsid];
2648  if(use_ns==0){
2649    ns=NULL;
2650  }
2651  n = xmlNewNode(ns, BAD_CAST "ExceptionReport");
2652  map* version=getMapFromMaps(m,"main","rversion");
2653  int vid=-1;
2654  if(version!=NULL)
2655    vid=getVersionId(version->value);
2656  if(vid<0)
2657    vid=0;
2658  if(use_ns==1){
2659    xmlNewNs(n,BAD_CAST schemas[vid][1],BAD_CAST"ows");
2660    int xsiId=zooXmlAddNs(n,"http://www.w3.org/2001/XMLSchema-instance","xsi");
2661    ns_xsi=usedNs[xsiId];
2662    char tmp[1024];
2663    sprintf(tmp,"%s %s",schemas[vid][1],schemas[vid][5]);
2664    xmlNewNsProp(n,ns_xsi,BAD_CAST "schemaLocation",BAD_CAST tmp);
2665  }
2666
2667
2668  addLangAttr(n,m);
2669  xmlNewProp(n,BAD_CAST "version",BAD_CAST schemas[vid][6]);
2670 
2671  int length=1;
2672  int cnt=0;
2673  map* len=getMap(s,"length");
2674  if(len!=NULL)
2675    length=atoi(len->value);
2676  for(cnt=0;cnt<length;cnt++){
2677    nc = xmlNewNode(ns, BAD_CAST "Exception");
2678   
2679    map* tmp=getMapArray(s,"code",cnt);
2680    if(tmp==NULL)
2681      tmp=getMap(s,"code");
2682    if(tmp!=NULL)
2683      xmlNewProp(nc,BAD_CAST "exceptionCode",BAD_CAST tmp->value);
2684    else
2685      xmlNewProp(nc,BAD_CAST "exceptionCode",BAD_CAST "NoApplicableCode");
2686   
2687    tmp=getMapArray(s,"locator",cnt);
2688    if(tmp==NULL)
2689      tmp=getMap(s,"locator");
2690    if(tmp!=NULL && strcasecmp(tmp->value,"NULL")!=0)
2691      xmlNewProp(nc,BAD_CAST "locator",BAD_CAST tmp->value);
2692
2693    tmp=getMapArray(s,"text",cnt);
2694    if(tmp==NULL)
2695      tmp=getMapArray(s,"message",cnt);
2696    nc1 = xmlNewNode(ns, BAD_CAST "ExceptionText");
2697    if(tmp!=NULL){
2698      xmlNodePtr txt=xmlNewText(BAD_CAST tmp->value);
2699      xmlAddChild(nc1,txt);
2700      if(cnt==0)
2701        setMapInMaps(m,"lenv","message",tmp->value);
2702    }
2703    else{
2704      xmlNodeSetContent(nc1, BAD_CAST _("No debug message available"));
2705    }
2706    xmlAddChild(nc,nc1);
2707    xmlAddChild(n,nc);
2708  }
2709  return n;
2710}
2711
2712/**
2713 * Print an OWS ExceptionReport.
2714 *
2715 * @param m the conf maps
2716 * @param message the error message
2717 * @param errorcode the error code
2718 * @param locator the potential locator
2719 */
2720int errorException(maps *m, const char *message, const char *errorcode, const char *locator) 
2721{
2722  map* pmExectionType=getMapFromMaps(m,"main","executionType");
2723  map* errormap = createMap("text", message);
2724  addToMap(errormap,"code", errorcode);
2725  if(locator!=NULL)
2726    addToMap(errormap,"locator", locator);
2727  else
2728    addToMap(errormap,"locator", "NULL");
2729  if(pmExectionType!=NULL && strncasecmp(pmExectionType->value,"xml",3)==0)
2730    printExceptionReportResponse(m,errormap);
2731  else{
2732    printExceptionReportResponseJ(m,errormap);
2733    setMapInMaps(m,"lenv","no-headers","true");
2734  }
2735  freeMap(&errormap);
2736  free(errormap);
2737  return -1;
2738}
2739
2740/**
2741 * Produce a copy file and the corresponding url in case it is required
2742 * Please, free the returned ressource while used
2743 *
2744 * @param pmConf maps* pointing to the main configuration file
2745 */
2746char* produceFileUrl(service* psService,maps* pmsConf,maps* pmsOutputs,const char* pccFormat, int itn){
2747  // Create file for reference data if not existing
2748  map *pmGFile=getMap(pmsOutputs->content,"generated_file");
2749  map *pmTmpPath=getMapFromMaps(pmsConf,"main","tmpPath");
2750  map *pmTmpUrl=getMapFromMaps(pmsConf,"main","tmpUrl");
2751  char *pcaFileName=NULL;
2752  char *pcaFilePath=NULL;
2753  char *pcaFileUrl=NULL;
2754  if(pmGFile!=NULL){
2755    pmGFile=getMap(pmsOutputs->content,"expected_generated_file");
2756    if(pmGFile==NULL){
2757      pmGFile=getMap(pmsOutputs->content,"generated_file");
2758    }
2759    if(strstr(pmGFile->value,pmTmpPath->value)!=NULL)
2760      pcaFileName=zStrdup(strstr(pmGFile->value,pmTmpPath->value)+strlen(pmTmpPath->value));
2761  }
2762  // Create file for reference data
2763  map *pmUsid=getMapFromMaps(pmsConf,"lenv","usid");
2764  map *pmExt=getMap(pmsOutputs->content,"extension");
2765  if(pmGFile==NULL){
2766    char acFileExt[32];     
2767    if( pmExt != NULL && pmExt->value != NULL) {
2768      strncpy(acFileExt, pmExt->value, 32);
2769    }
2770    else {
2771      // Obtain default file extension (see mimetypes.h).             
2772      // If the MIME type is not recognized, txt is used as the default extension
2773      map* pmType=getMap(pmsOutputs->content,"mimeType");
2774      getFileExtension(pmType != NULL ? pmType->value : NULL, acFileExt, 32);
2775    }
2776    if(pcaFileName!=NULL)
2777      free(pcaFileName);
2778             
2779    pcaFileName=(char*)malloc((strlen(psService->name)+strlen(pmUsid->value)+strlen(acFileExt)+strlen(pmsOutputs->name)+45)*sizeof(char));
2780    sprintf(pcaFileName,"ZOO_DATA_%s_%s_%s_%d.%s",psService->name,pmsOutputs->name,pmUsid->value,itn,acFileExt);
2781
2782    pcaFilePath=(char*)malloc((strlen(pmTmpPath->value)+strlen(pcaFileName)+2)*sizeof(char));
2783    sprintf(pcaFilePath,"%s/%s",pmTmpPath->value,pcaFileName);
2784  }else{
2785    pcaFilePath=(char*)malloc((strlen(pmGFile->value)+1)*sizeof(char));
2786    sprintf(pcaFilePath,"%s",pmGFile->value);
2787  }
2788 
2789  pcaFileUrl=(char*)malloc((strlen(pmTmpUrl->value)+
2790                          strlen(pcaFileName)+2)*sizeof(char));
2791  sprintf(pcaFileUrl,"%s/%s",pmTmpUrl->value,pcaFileName);
2792
2793  if(pmGFile==NULL) {
2794    FILE *pfOfile=fopen(pcaFilePath,"wb");
2795    if(pfOfile==NULL){
2796      char acTmpMsg[1024];
2797      sprintf(acTmpMsg,
2798              _("Unable to create the file \"%s\" for storing the %s final result."),
2799              pcaFileName,pmsOutputs->name);
2800      map* pmError=createMap("code","InternalError");
2801      addToMap(pmError,"message",acTmpMsg);
2802      printExceptionReportResponseJ(pmsConf,pmError);
2803      free(pcaFileName);
2804      free(pcaFilePath);
2805      return NULL;
2806    }
2807
2808    map* pmValue=getMap(pmsOutputs->content,"value");
2809    if(pmValue==NULL){
2810      char acTmpMsg[1024];
2811      sprintf(acTmpMsg,
2812              _("No value found for the requested output %s."),
2813              pmsOutputs->name);
2814      map* pmError=createMap("code","InternalError");
2815      addToMap(pmError,"message",acTmpMsg);
2816      printExceptionReportResponseJ(pmsConf,pmError);
2817      fclose(pfOfile);
2818      free(pcaFileName);
2819      free(pcaFilePath);
2820      return NULL;
2821    }
2822    if(pccFormat==NULL || strcasecmp(pccFormat,"BoundingBoxData")!=0){
2823      map* size=getMap(pmsOutputs->content,"size");
2824      if(size!=NULL && pmValue!=NULL)
2825        fwrite(pmValue->value,1,(atoi(size->value))*sizeof(char),pfOfile);
2826      else
2827        if(pmValue!=NULL && pmValue->value!=NULL)
2828          fwrite(pmValue->value,1,
2829                 strlen(pmValue->value)*sizeof(char),pfOfile);
2830    }else
2831      printBoundingBoxDocument(pmsConf,pmsOutputs,pfOfile);
2832    fclose(pfOfile);
2833  }
2834  free(pcaFileName);
2835  free(pcaFilePath);
2836  return pcaFileUrl;
2837}
2838
2839/**
2840 * Generate the output response (RawDataOutput or ResponseDocument)
2841 *
2842 * @param s the service structure containing the metadata information
2843 * @param request_inputs the inputs provided to the service for execution
2844 * @param request_outputs the outputs updated by the service execution
2845 * @param request_inputs1 the map containing the HTTP request
2846 * @param cpid the process identifier attached to a service execution
2847 * @param m the conf maps containing the main.cfg settings
2848 * @param res the value returned by the service execution
2849 */
2850void outputResponse(service* s,maps* request_inputs,maps* request_outputs,
2851                    map* request_inputs1,int cpid,maps* m,int res){
2852#ifdef DEBUG
2853  dumpMaps(request_inputs);
2854  dumpMaps(request_outputs);
2855  fprintf(stderr,"printProcessResponse\n");
2856#endif 
2857  map* pmRawData=getMap(request_inputs1,"RawDataOutput");
2858  int asRaw=0;
2859  if(pmRawData!=NULL)
2860    asRaw=1;
2861  map* version=getMapFromMaps(m,"main","rversion");
2862  int vid=getVersionId(version->value);
2863  printSessionHeaders(m);
2864  if(res==SERVICE_FAILED){
2865    char* tmp0=produceErrorMessage(m);
2866    errorException(m,tmp0,"InternalError",NULL);
2867    free(tmp0);
2868    return;
2869  }
2870
2871  if(res==SERVICE_ACCEPTED && vid==1){
2872    map* statusInfo=createMap("Status","Accepted");
2873    map *usid=getMapFromMaps(m,"lenv","usid");
2874    addToMap(statusInfo,"JobID",usid->value);
2875    printStatusInfo(m,statusInfo,(char*)"Execute");
2876    freeMap(&statusInfo);
2877    free(statusInfo);
2878    return;
2879  }
2880
2881  if(res!=SERVICE_SUCCEEDED){     
2882    printProcessResponse(m,request_inputs1,cpid,
2883                         s, s->name,res,  // replace serviceProvider with serviceName in stored response file name
2884                         request_inputs,
2885                         request_outputs);
2886    return;
2887  }
2888     
2889  map *tmp1=getMapFromMaps(m,"main","tmpPath");
2890  if(asRaw==0){
2891#ifdef DEBUG
2892    fprintf(stderr,"REQUEST_OUTPUTS FINAL\n");
2893    dumpMaps(request_outputs);
2894#endif
2895    maps* tmpI=request_outputs;
2896    maps* stmpI=NULL;
2897    map* usid=getMapFromMaps(m,"lenv","usid");
2898    int itn=0;
2899    int error=-1;
2900  NESTED0:
2901    while(tmpI!=NULL){
2902      if(tmpI->child!=NULL){
2903        stmpI=tmpI;
2904        tmpI=tmpI->child;
2905      }
2906#ifdef USE_MS
2907      map* testMap=getMap(tmpI->content,"useMapserver");       
2908#endif
2909      /*map *gfile=getMap(tmpI->content,"generated_file");
2910      char *file_name=NULL;       
2911      if(gfile!=NULL){
2912        gfile=getMap(tmpI->content,"expected_generated_file");
2913        if(gfile==NULL){
2914          gfile=getMap(tmpI->content,"generated_file");
2915        }
2916        readGeneratedFile(m,tmpI->content,gfile->value);
2917        file_name=zStrdup((gfile->value)+strlen(tmp1->value));
2918        }*/
2919      char *pcaFileUrl=NULL;
2920      pmRawData=getMap(tmpI->content,"asReference");
2921#ifdef USE_MS
2922      map* geodatatype=getMap(tmpI->content,"geodatatype");
2923      if(pmRawData!=NULL && strcasecmp(pmRawData->value,"true")==0 &&
2924         (testMap==NULL ||
2925          strncasecmp(testMap->value,"true",4)!=0 ||
2926          (geodatatype!=NULL && strcasecmp(geodatatype->value,"other")==0) ) ) 
2927#else
2928        if(pmRawData!=NULL && strcasecmp(pmRawData->value,"true")==0)
2929#endif
2930          {             
2931            elements* in=getElements(s->outputs,tmpI->name);
2932            if(in==NULL && s->outputs->child!=NULL){
2933              in=getElements(s->outputs->child,tmpI->name);
2934            }
2935            char *format=NULL;
2936            if(in!=NULL && in->format!=NULL){
2937              format=in->format;
2938            }else
2939              format=(char*)"LiteralData";
2940            if(format!=NULL && strcasecmp(format,"BoundingBoxData")==0){
2941              addToMap(tmpI->content,"extension","xml");
2942              addToMap(tmpI->content,"mimeType","text/xml");
2943              addToMap(tmpI->content,"encoding","UTF-8");
2944              addToMap(tmpI->content,"schema","http://schemas.opengis.net/ows/1.1.0/owsCommon.xsd");
2945            }
2946            pcaFileUrl=produceFileUrl(s,m,tmpI,format,itn);
2947            itn++;
2948            if(pcaFileUrl==NULL)
2949              return;
2950            addToMap(tmpI->content,"Reference",pcaFileUrl);
2951          }
2952#ifdef USE_MS
2953        else{
2954          if(testMap!=NULL){
2955            map* nbFeatures;
2956            setMapInMaps(m,"lenv","state","out");
2957            setReferenceUrl(m,tmpI);
2958            nbFeatures=getMap(tmpI->content,"nb_features");
2959            geodatatype=getMap(tmpI->content,"geodatatype");
2960            if((nbFeatures!=NULL && atoi(nbFeatures->value)==0) ||
2961               (geodatatype!=NULL && strcasecmp(geodatatype->value,"other")==0)){
2962              error=1;
2963              res=SERVICE_FAILED;
2964            }
2965          }
2966        }
2967#endif 
2968      if(pcaFileUrl!=NULL){
2969        free(pcaFileUrl);
2970        pcaFileUrl=NULL;
2971      }
2972      tmpI=tmpI->next;
2973    }
2974    if(stmpI!=NULL){
2975      tmpI=stmpI->next;
2976      stmpI=NULL;
2977      if(tmpI!=NULL)
2978        goto NESTED0;
2979    }   
2980#ifdef DEBUG
2981    fprintf(stderr,"SERVICE : %s\n",s->name);
2982    dumpMaps(m);
2983#endif 
2984    if(error<0)
2985      printProcessResponse(m,request_inputs1,cpid,
2986                           s, s->name,res,  // replace serviceProvider with serviceName in stored response file name
2987                           request_inputs,
2988                           request_outputs);
2989    else{
2990      maps* tmpMaps=getMaps(m,"lenv");
2991#ifdef USE_CALLBACK
2992      invokeCallback(m,NULL,NULL,7,0);
2993#endif
2994      printExceptionReportResponse(m,tmpMaps->content);
2995    }
2996  }
2997  else{
2998    /**
2999     * We get the requested output or fallback to the first one if the
3000     * requested one is not present in the resulting outputs maps.
3001     */
3002    maps* tmpI=NULL;
3003    map* tmpIV=getMap(request_inputs1,"RawDataOutput");
3004    if(tmpIV!=NULL){
3005      tmpI=getMaps(request_outputs,tmpIV->value);         
3006    }
3007    if(tmpI==NULL)
3008      tmpI=request_outputs;
3009
3010    elements* e=getElements(s->outputs,tmpI->name);
3011    if(e!=NULL && strcasecmp(e->format,"BoundingBoxData")==0){
3012      printBoundingBoxDocument(m,tmpI,NULL);
3013    }else{
3014      printRawdataOutput(m,tmpI);
3015    }
3016  }
3017}
3018
3019/**
3020 * Print one outputs as raw
3021 *
3022 * @param conf the main configuration maps
3023 * @param outputs the output to be print as raw
3024 */
3025void* printRawdataOutput(maps* conf,maps* outputs){
3026  map *gfile=getMap(outputs->content,"generated_file");
3027  if(gfile!=NULL){
3028    gfile=getMap(outputs->content,"expected_generated_file");
3029    if(gfile==NULL){
3030      gfile=getMap(outputs->content,"generated_file");
3031    }
3032    readGeneratedFile(conf,outputs->content,gfile->value);
3033  }
3034  map* toto=getMap(outputs->content,"value");
3035  if(toto==NULL){
3036    char tmpMsg[1024];
3037    sprintf(tmpMsg,_("Wrong RawDataOutput parameter: unable to fetch any result for the given parameter name: \"%s\"."),outputs->name);
3038    map* pmExecutionType=getMapFromMaps(conf,"main","executionType");
3039    if(pmExecutionType!=NULL && strncasecmp(pmExecutionType->value,"xml",3)==0)
3040      errorException(conf,tmpMsg,"InvalidParameterValue","RawDataOutput");
3041    else{
3042      setMapInMaps(conf,"lenv","error","true");
3043      setMapInMaps(conf,"lenv","code","InvalidParameterValue");
3044      setMapInMaps(conf,"lenv","message",tmpMsg);
3045    }
3046    return NULL;
3047  }
3048  map* fname=getMapFromMaps(outputs,outputs->name,"filename");           
3049  if(fname!=NULL)
3050    printf("Content-Disposition: attachment; filename=\"%s\"\r\n",fname->value);
3051  map* rs=getMapFromMaps(outputs,outputs->name,"size");
3052  if(rs!=NULL)
3053    printf("Content-Length: %s\r\n",rs->value);
3054  char mime[1024];
3055  map* mi=getMap(outputs->content,"mimeType");
3056  map* en=getMap(outputs->content,"encoding");
3057  if(mi!=NULL && en!=NULL)
3058    sprintf(mime,
3059            "Content-Type: %s; charset=%s\r\nStatus: 200 OK\r\n\r\n",
3060            mi->value,en->value);
3061  else
3062    if(mi!=NULL)
3063      sprintf(mime,
3064              "Content-Type: %s; charset=UTF-8\r\nStatus: 200 OK\r\n\r\n",
3065              mi->value);
3066    else
3067      sprintf(mime,"Content-Type: text/plain; charset=utf-8\r\nStatus: 200 OK\r\n\r\n");
3068  printf("%s",mime);
3069  if(rs!=NULL)
3070    fwrite(toto->value,1,atoi(rs->value),stdout);
3071  else
3072    fwrite(toto->value,1,strlen(toto->value),stdout);   
3073}
3074
3075/**
3076 * Create required XML nodes for boundingbox and update the current XML node
3077 *
3078 * @param ns_ows the ows XML namespace
3079 * @param n the XML node to update
3080 * @param boundingbox the map containing the boundingbox definition
3081 */
3082void printBoundingBox(xmlNsPtr ns_ows,xmlNodePtr n,map* boundingbox){
3083
3084  xmlNodePtr lw=NULL,uc=NULL;
3085
3086  map* tmp=getMap(boundingbox,"value");
3087
3088  tmp=getMap(boundingbox,"lowerCorner");
3089  if(tmp!=NULL){
3090    lw=xmlNewNode(ns_ows,BAD_CAST "LowerCorner");
3091    xmlAddChild(lw,xmlNewText(BAD_CAST tmp->value));
3092  }
3093
3094  tmp=getMap(boundingbox,"upperCorner");
3095  if(tmp!=NULL){
3096    uc=xmlNewNode(ns_ows,BAD_CAST "UpperCorner");
3097    xmlAddChild(uc,xmlNewText(BAD_CAST tmp->value));
3098  }
3099
3100  tmp=getMap(boundingbox,"crs");
3101  if(tmp!=NULL)
3102    xmlNewProp(n,BAD_CAST "crs",BAD_CAST tmp->value);
3103
3104  tmp=getMap(boundingbox,"dimensions");
3105  if(tmp!=NULL)
3106    xmlNewProp(n,BAD_CAST "dimensions",BAD_CAST tmp->value);
3107
3108  xmlAddChild(n,lw);
3109  xmlAddChild(n,uc);
3110
3111}
3112
3113/**
3114 * Parse a BoundingBox string
3115 *
3116 * [OGC 06-121r3](http://portal.opengeospatial.org/files/?artifact_id=20040):
3117 *  10.2 Bounding box
3118 *
3119 *
3120 * Value is provided as : lowerCorner,upperCorner,crs,dimension
3121 * Exemple : 189000,834000,285000,962000,urn:ogc:def:crs:OGC:1.3:CRS84
3122 *
3123 * A map to store boundingbox information should contain:
3124 *  - lowerCorner : double,double (minimum within this bounding box)
3125 *  - upperCorner : double,double (maximum within this bounding box)
3126 *  - crs : URI (Reference to definition of the CRS)
3127 *  - dimensions : int
3128 *
3129 * Note : support only 2D bounding box.
3130 *
3131 * @param value the char* containing the KVP bouding box
3132 * @return a map containing all the bounding box keys
3133 */
3134map* parseBoundingBox(const char* value){
3135  map *res=NULL;
3136  if(value!=NULL){
3137    char *cv,*cvp;
3138    cv=strtok_r((char*) value,",",&cvp);
3139    int cnt=0;
3140    int icnt=0;
3141    char *currentValue=NULL;
3142    while(cv){
3143      if(cnt<2)
3144        if(currentValue!=NULL){
3145          char *finalValue=(char*)malloc((strlen(currentValue)+strlen(cv)+1)*sizeof(char));
3146          sprintf(finalValue,"%s%s",currentValue,cv);
3147          switch(cnt){
3148          case 0:
3149            res=createMap("lowerCorner",finalValue);
3150            break;
3151          case 1:
3152            addToMap(res,"upperCorner",finalValue);
3153            icnt=-1;
3154            break;
3155          }
3156          cnt++;
3157          free(currentValue);
3158          currentValue=NULL;
3159          free(finalValue);
3160        }
3161        else{
3162          currentValue=(char*)malloc((strlen(cv)+2)*sizeof(char));
3163          sprintf(currentValue,"%s ",cv);
3164        }
3165      else
3166        if(cnt==2){
3167          addToMap(res,"crs",cv);
3168          cnt++;
3169        }
3170        else
3171          addToMap(res,"dimensions",cv);
3172      icnt++;
3173      cv=strtok_r(NULL,",",&cvp);
3174    }
3175  }
3176  return res;
3177}
3178
3179/**
3180 * Print an ows:BoundingBox XML document
3181 *
3182 * @param m the maps containing the settings of the main.cfg file
3183 * @param boundingbox the maps containing the boundingbox definition
3184 * @param file the file to print the BoundingBox (if NULL then print on stdout)
3185 * @see parseBoundingBox, printBoundingBox
3186 */
3187void printBoundingBoxDocument(maps* m,maps* boundingbox,FILE* file){
3188  if(file==NULL)
3189    rewind(stdout);
3190  xmlNodePtr n;
3191  xmlDocPtr doc;
3192  xmlNsPtr ns_ows,ns_xsi;
3193  xmlChar *xmlbuff;
3194  int buffersize;
3195  char *encoding=getEncoding(m);
3196  map *tmp;
3197  if(file==NULL){
3198    int pid=0;
3199    tmp=getMapFromMaps(m,"lenv","sid");
3200    if(tmp!=NULL)
3201      pid=atoi(tmp->value);
3202    if(pid==getpid()){
3203      printf("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding);
3204    }
3205    fflush(stdout);
3206  }
3207
3208  doc = xmlNewDoc(BAD_CAST "1.0");
3209  int owsId=zooXmlAddNs(NULL,"http://www.opengis.net/ows/1.1","ows");
3210  ns_ows=usedNs[owsId];
3211  n = xmlNewNode(ns_ows, BAD_CAST "BoundingBox");
3212  xmlNewNs(n,BAD_CAST "http://www.opengis.net/ows/1.1",BAD_CAST "ows");
3213  int xsiId=zooXmlAddNs(n,"http://www.w3.org/2001/XMLSchema-instance","xsi");
3214  ns_xsi=usedNs[xsiId];
3215  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");
3216  map *tmp1=getMap(boundingbox->content,"value");
3217  tmp=parseBoundingBox(tmp1->value);
3218  printBoundingBox(ns_ows,n,tmp);
3219  xmlDocSetRootElement(doc, n);
3220
3221  xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);
3222  if(file==NULL)
3223    printf("%s",xmlbuff);
3224  else{
3225    fprintf(file,"%s",xmlbuff);
3226  }
3227
3228  if(tmp!=NULL){
3229    freeMap(&tmp);
3230    free(tmp);
3231  }
3232  xmlFree(xmlbuff);
3233  xmlFreeDoc(doc);
3234  xmlCleanupParser();
3235  zooXmlCleanupNs();
3236 
3237}
3238
3239/**
3240 * Print a StatusInfo XML document.
3241 * a statusInfo map should contain the following keys:
3242 *  * JobID corresponding to usid key from the lenv section
3243 *  * Status the current state (Succeeded,Failed,Accepted,Running)
3244 *  * PercentCompleted (optional) the percent completed
3245 *  * Message (optional) any messages the service may wish to share
3246 *
3247 * @param conf the maps containing the settings of the main.cfg file
3248 * @param statusInfo the map containing the statusInfo definition
3249 * @param req the WPS requests (GetResult, GetStatus or Dismiss)
3250 */
3251void printStatusInfo(maps* conf,map* statusInfo,char* req){
3252  rewind(stdout);
3253  xmlNodePtr n,n1;
3254  xmlDocPtr doc;
3255  xmlNsPtr ns;
3256  xmlChar *xmlbuff;
3257  int buffersize;
3258  char *encoding=getEncoding(conf);
3259  map *tmp;
3260  int pid=0;
3261  printf("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding);
3262
3263  map* version=getMapFromMaps(conf,"main","rversion");
3264  int vid=getVersionId(version->value);
3265
3266  doc = xmlNewDoc(BAD_CAST "1.0");
3267  n1=printWPSHeader(doc,conf,req,"StatusInfo",version->value,1);
3268
3269  map* val=getMap(statusInfo,"JobID");
3270  int wpsId=zooXmlAddNs(NULL,schemas[vid][2],"wps");
3271  ns=usedNs[wpsId];
3272  n = xmlNewNode(ns, BAD_CAST "JobID");
3273  xmlAddChild(n,xmlNewText(BAD_CAST val->value));
3274
3275  xmlAddChild(n1,n);
3276
3277  val=getMap(statusInfo,"Status");
3278  n = xmlNewNode(ns, BAD_CAST "Status");
3279  xmlAddChild(n,xmlNewText(BAD_CAST val->value));
3280
3281  xmlAddChild(n1,n);
3282
3283  if(strncasecmp(val->value,"Failed",6)!=0 &&
3284     strncasecmp(val->value,"Succeeded",9)!=0){
3285    val=getMap(statusInfo,"PercentCompleted");
3286    if(val!=NULL){
3287      n = xmlNewNode(ns, BAD_CAST "PercentCompleted");
3288      xmlAddChild(n,xmlNewText(BAD_CAST val->value));
3289      xmlAddChild(n1,n);
3290    }
3291
3292    val=getMap(statusInfo,"Message");
3293    if(val!=NULL){   
3294      xmlAddChild(n1,xmlNewComment(BAD_CAST val->value));
3295    }
3296  }
3297  xmlDocSetRootElement(doc, n1);
3298
3299  xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);
3300  printf("%s",xmlbuff);
3301
3302  xmlFree(xmlbuff);
3303  xmlFreeDoc(doc);
3304  xmlCleanupParser();
3305  zooXmlCleanupNs();
3306 
3307}
3308
Note: See TracBrowser for help on using the repository browser.

Search

Context Navigation

ZOO Sponsors

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

Become a sponsor !

Knowledge partners

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

Become a knowledge partner

Related links

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