Index: trunk/zoo-project/zoo-kernel/response_print.c
===================================================================
--- trunk/zoo-project/zoo-kernel/response_print.c	(revision 641)
+++ trunk/zoo-project/zoo-kernel/response_print.c	(revision 641)
@@ -0,0 +1,2670 @@
+/*
+ * Author : Gérald FENOY
+ *
+ * Copyright (c) 2009-2015 GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "response_print.h"
+#include "request_parser.h"
+#include "server_internal.h"
+#ifdef USE_MS
+#include "service_internal_ms.h"
+#else
+#include "cpl_vsi.h"
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE -1
+#endif
+
+#ifndef WIN32
+#include <dlfcn.h>
+#endif
+
+#define ERROR_MSG_MAX_LENGTH 1024
+
+#include "mimetypes.h"
+
+
+/**
+ * Add prefix to the service name.
+ * 
+ * @param conf the conf maps containing the main.cfg settings
+ * @param level the map containing the level information
+ * @param serv the service structure created from the zcfg file
+ */
+void addPrefix(maps* conf,map* level,service* serv){
+  if(level!=NULL){
+    char key[25];
+    char* prefix=NULL;
+    int clevel=atoi(level->value);
+    int cl=0;
+    for(cl=0;cl<clevel;cl++){
+      sprintf(key,"sprefix_%d",cl);
+      map* tmp2=getMapFromMaps(conf,"lenv",key);
+      if(tmp2!=NULL){
+	if(prefix==NULL)
+	  prefix=zStrdup(tmp2->value);
+	else{
+	  int plen=strlen(prefix);
+	  prefix=(char*)realloc(prefix,(plen+strlen(tmp2->value)+2)*sizeof(char));
+	  memcpy(prefix+plen,tmp2->value,strlen(tmp2->value)*sizeof(char));
+	  prefix[plen+strlen(tmp2->value)]=0;
+	}
+      }
+    }
+    if(prefix!=NULL){
+      char* tmp0=strdup(serv->name);
+      free(serv->name);
+      serv->name=(char*)malloc((strlen(prefix)+strlen(tmp0)+1)*sizeof(char));
+      sprintf(serv->name,"%s%s",prefix,tmp0);
+      free(tmp0);
+      free(prefix);
+      prefix=NULL;
+    }
+  }
+}
+
+/**
+ * Print the HTTP headers based on a map.
+ * 
+ * @param m the map containing the headers informations
+ */
+void printHeaders(maps* m){
+  maps *_tmp=getMaps(m,"headers");
+  if(_tmp!=NULL){
+    map* _tmp1=_tmp->content;
+    while(_tmp1!=NULL){
+      printf("%s: %s\r\n",_tmp1->name,_tmp1->value);
+      _tmp1=_tmp1->next;
+    }
+  }
+}
+
+/**
+ * Add a land attribute to a XML node
+ *
+ * @param n the XML node to add the attribute
+ * @param m the map containing the language key to add as xml:lang
+ */
+void addLangAttr(xmlNodePtr n,maps *m){
+  map *tmpLmap=getMapFromMaps(m,"main","language");
+  if(tmpLmap!=NULL)
+    xmlNewProp(n,BAD_CAST "xml:lang",BAD_CAST tmpLmap->value);
+  else
+    xmlNewProp(n,BAD_CAST "xml:lang",BAD_CAST "en-US");
+}
+
+/**
+ * Replace the first letter by its upper case version in a new char array
+ *
+ * @param tmp the char*
+ * @return a new char* with first letter in upper case
+ * @warning be sure to free() the returned string after use
+ */
+char *zCapitalize1(char *tmp){
+  char *res=zStrdup(tmp);
+  if(res[0]>=97 && res[0]<=122)
+    res[0]-=32;
+  return res;
+}
+
+/**
+ * Replace all letters by their upper case version in a new char array
+ *
+ * @param tmp the char*
+ * @return a new char* with first letter in upper case
+ * @warning be sure to free() the returned string after use
+ */
+char *zCapitalize(char *tmp){
+  int i=0;
+  char *res=zStrdup(tmp);
+  for(i=0;i<strlen(res);i++)
+    if(res[i]>=97 && res[i]<=122)
+      res[i]-=32;
+  return res;
+}
+
+/**
+ * Search for an existing XML namespace in usedNS.
+ * 
+ * @param name the name of the XML namespace to search
+ * @return the index of the XML namespace found or -1 if not found.
+ */
+int zooXmlSearchForNs(const char* name){
+  int i;
+  int res=-1;
+  for(i=0;i<nbNs;i++)
+    if(strncasecmp(name,nsName[i],strlen(nsName[i]))==0){
+      res=i;
+      break;
+    }
+  return res;
+}
+
+/**
+ * Add an XML namespace to the usedNS if it was not already used.
+ * 
+ * @param nr the xmlNodePtr to attach the XML namspace (can be NULL)
+ * @param url the url of the XML namespace to add
+ * @param name the name of the XML namespace to add
+ * @return the index of the XML namespace added.
+ */
+int zooXmlAddNs(xmlNodePtr nr,const char* url,const char* name){
+#ifdef DEBUG
+  fprintf(stderr,"zooXmlAddNs %d %s \n",nbNs,name);
+#endif
+  int currId=-1;
+  if(nbNs==0){
+    nbNs++;
+    currId=0;
+    nsName[currId]=strdup(name);
+    usedNs[currId]=xmlNewNs(nr,BAD_CAST url,BAD_CAST name);
+  }else{
+    currId=zooXmlSearchForNs(name);
+    if(currId<0){
+      nbNs++;
+      currId=nbNs-1;
+      nsName[currId]=strdup(name);
+      usedNs[currId]=xmlNewNs(nr,BAD_CAST url,BAD_CAST name);
+    }
+  }
+  return currId;
+}
+
+/**
+ * Free allocated memory to store used XML namespace.
+ */
+void zooXmlCleanupNs(){
+  int j;
+#ifdef DEBUG
+  fprintf(stderr,"zooXmlCleanup %d\n",nbNs);
+#endif
+  for(j=nbNs-1;j>=0;j--){
+#ifdef DEBUG
+    fprintf(stderr,"zooXmlCleanup %d\n",j);
+#endif
+    if(j==0)
+      xmlFreeNs(usedNs[j]);
+    free(nsName[j]);
+    nbNs--;
+  }
+  nbNs=0;
+}
+
+/**
+ * Add a XML document to the iDocs.
+ * 
+ * @param value the string containing the XML document
+ * @return the index of the XML document added.
+ */
+int zooXmlAddDoc(const char* value){
+  int currId=0;
+  nbDocs++;
+  currId=nbDocs-1;
+  iDocs[currId]=xmlParseMemory(value,strlen(value));
+  return currId;
+}
+
+/**
+ * Free allocated memort to store XML documents
+ */
+void zooXmlCleanupDocs(){
+  int j;
+  for(j=nbDocs-1;j>=0;j--){
+    xmlFreeDoc(iDocs[j]);
+  }
+  nbDocs=0;
+}
+
+/**
+ * Generate a SOAP Envelope node when required (if the isSoap key of the [main]
+ * section is set to true).
+ * 
+ * @param conf the conf maps containing the main.cfg settings
+ * @param n the node used as children of the generated soap:Envelope
+ * @return the generated soap:Envelope (if isSoap=true) or the input node n 
+ *  (when isSoap=false)
+ */
+xmlNodePtr soapEnvelope(maps* conf,xmlNodePtr n){
+  map* soap=getMapFromMaps(conf,"main","isSoap");
+  if(soap!=NULL && strcasecmp(soap->value,"true")==0){
+    int lNbNs=nbNs;
+    nsName[lNbNs]=strdup("soap");
+    usedNs[lNbNs]=xmlNewNs(NULL,BAD_CAST "http://www.w3.org/2003/05/soap-envelope",BAD_CAST "soap");
+    nbNs++;
+    xmlNodePtr nr = xmlNewNode(usedNs[lNbNs], BAD_CAST "Envelope");
+    nsName[nbNs]=strdup("soap");
+    usedNs[nbNs]=xmlNewNs(nr,BAD_CAST "http://www.w3.org/2003/05/soap-envelope",BAD_CAST "soap");
+    nbNs++;
+    nsName[nbNs]=strdup("xsi");
+    usedNs[nbNs]=xmlNewNs(nr,BAD_CAST "http://www.w3.org/2001/XMLSchema-instance",BAD_CAST "xsi");
+    nbNs++;
+    xmlNsPtr ns_xsi=usedNs[nbNs-1];
+    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");
+    xmlNodePtr nr1 = xmlNewNode(usedNs[lNbNs], BAD_CAST "Body");
+    xmlAddChild(nr1,n);
+    xmlAddChild(nr,nr1);
+    return nr;
+  }else
+    return n;
+}
+
+/**
+ * Generate a WPS header.
+ * 
+ * @param doc the document to add the header
+ * @param m the conf maps containing the main.cfg settings
+ * @param req the request type (GetCapabilities,DescribeProcess,Execute)
+ * @param rname the root node name
+ * @return the generated wps:rname xmlNodePtr (can be wps: Capabilities, 
+ *  wps:ProcessDescriptions,wps:ExecuteResponse)
+ */
+xmlNodePtr printWPSHeader(xmlDocPtr doc,maps* m,const char* req,const char* rname,const char* version,int reqId){
+
+  xmlNsPtr ns,ns_xsi;
+  xmlNodePtr n;
+
+  int vid=getVersionId(version);
+
+  int wpsId=zooXmlAddNs(NULL,schemas[vid][2],"wps");
+  ns=usedNs[wpsId];
+  n = xmlNewNode(ns, BAD_CAST rname);
+  zooXmlAddNs(n,schemas[vid][1],"ows");
+  xmlNewNs(n,BAD_CAST schemas[vid][2],BAD_CAST "wps");
+  zooXmlAddNs(n,"http://www.w3.org/1999/xlink","xlink");
+  int xsiId=zooXmlAddNs(n,"http://www.w3.org/2001/XMLSchema-instance","xsi");
+  ns_xsi=usedNs[xsiId];
+  char *tmp=(char*) malloc((86+strlen(req)+1)*sizeof(char));
+  sprintf(tmp,schemas[vid][4],schemas[vid][2],schemas[vid][3],req);
+  xmlNewNsProp(n,ns_xsi,BAD_CAST "schemaLocation",BAD_CAST tmp);
+  free(tmp);
+  if(vid==0 || reqId==0){
+    xmlNewProp(n,BAD_CAST "service",BAD_CAST "WPS");
+    xmlNewProp(n,BAD_CAST "version",BAD_CAST schemas[vid][0]);
+  }
+  if(vid==0)
+    addLangAttr(n,m);
+  xmlNodePtr fn=soapEnvelope(m,n);
+  xmlDocSetRootElement(doc, fn);
+  return n;
+}
+
+void addLanguageNodes(maps* conf,xmlNodePtr n,xmlNsPtr ns,xmlNsPtr ns_ows){
+  xmlNodePtr nc1,nc2,nc3,nc4;
+  map* version=getMapFromMaps(conf,"main","rversion");
+  int vid=getVersionId(version->value);
+  if(vid==1)
+    nc1 = xmlNewNode(ns_ows, BAD_CAST "Languages");
+  else{
+    nc1 = xmlNewNode(ns, BAD_CAST "Languages");
+    nc2 = xmlNewNode(ns, BAD_CAST "Default");
+    nc3 = xmlNewNode(ns, BAD_CAST "Supported");
+  }
+
+  maps* tmp=getMaps(conf,"main");
+  if(tmp!=NULL){
+    map* tmp1=getMap(tmp->content,"lang");
+    char *toto=tmp1->value;
+    char buff[256];
+    int i=0;
+    int j=0;
+    int dcount=0;
+    while(toto[i]){
+      if(toto[i]!=',' && toto[i]!=0){
+	buff[j]=toto[i];
+	buff[j+1]=0;
+	j++;
+      }
+      else{
+	nc4 = xmlNewNode(ns_ows, BAD_CAST "Language");
+	xmlAddChild(nc4,xmlNewText(BAD_CAST buff));
+	if(dcount==0){
+	  if(vid==0){
+	    xmlAddChild(nc2,nc4);
+	    xmlAddChild(nc1,nc2);
+	  }
+	  dcount++;
+	}
+	nc4 = xmlNewNode(ns_ows, BAD_CAST "Language");
+	xmlAddChild(nc4,xmlNewText(BAD_CAST buff));
+	if(vid==0)
+	  xmlAddChild(nc3,nc4);
+	else
+	  xmlAddChild(nc1,nc4);
+	j=0;
+	buff[j]=0;
+      }
+      i++;
+    }
+    if(strlen(buff)>0){
+      nc4 = xmlNewNode(ns_ows, BAD_CAST "Language");
+      xmlAddChild(nc4,xmlNewText(BAD_CAST buff));	      
+	if(vid==0)
+	  xmlAddChild(nc3,nc4);
+	else
+	  xmlAddChild(nc1,nc4);
+    }
+  }
+  if(vid==0)
+    xmlAddChild(nc1,nc3);
+  xmlAddChild(n,nc1);
+}
+
+/**
+ * Generate a Capabilities header.
+ * 
+ * @param doc the document to add the header
+ * @param m the conf maps containing the main.cfg settings
+ * @return the generated wps:ProcessOfferings xmlNodePtr 
+ */
+xmlNodePtr printGetCapabilitiesHeader(xmlDocPtr doc,maps* m,const char* version="1.0.0"){
+
+  xmlNsPtr ns,ns_ows,ns_xlink;
+  xmlNodePtr n,nc,nc1,nc2,nc3,nc4,nc5,nc6;
+  n = printWPSHeader(doc,m,"GetCapabilities","Capabilities",version,0);
+  maps* toto1=getMaps(m,"main");
+  char tmp[256];
+  map* v=getMapFromMaps(m,"main","rversion");
+  int vid=getVersionId(v->value);
+
+  int wpsId=zooXmlAddNs(NULL,schemas[vid][2],"wps");
+  ns=usedNs[wpsId];
+  int xlinkId=zooXmlAddNs(NULL,"http://www.w3.org/1999/xlink","xlink");
+  ns_xlink=usedNs[xlinkId];
+  int owsId=zooXmlAddNs(NULL,schemas[vid][1],"ows");
+  ns_ows=usedNs[owsId];
+
+  nc = xmlNewNode(ns_ows, BAD_CAST "ServiceIdentification");
+  maps* tmp4=getMaps(m,"identification");
+  if(tmp4!=NULL){
+    map* tmp2=tmp4->content;
+    const char *orderedFields[5];
+    orderedFields[0]="Title";
+    orderedFields[1]="Abstract";
+    orderedFields[2]="Keywords";
+    orderedFields[3]="Fees";
+    orderedFields[4]="AccessConstraints";
+    int oI=0;
+    for(oI=0;oI<5;oI++)
+      if((tmp2=getMap(tmp4->content,orderedFields[oI]))!=NULL){
+	if(strcasecmp(tmp2->name,"abstract")==0 ||
+	   strcasecmp(tmp2->name,"title")==0 ||
+	   strcasecmp(tmp2->name,"accessConstraints")==0 ||
+	   strcasecmp(tmp2->name,"fees")==0){
+	  tmp2->name[0]=toupper(tmp2->name[0]);
+	  nc1 = xmlNewNode(ns_ows, BAD_CAST tmp2->name);
+	  xmlAddChild(nc1,xmlNewText(BAD_CAST tmp2->value));
+	  xmlAddChild(nc,nc1);
+	}
+	else
+	  if(strcmp(tmp2->name,"keywords")==0){
+	    nc1 = xmlNewNode(ns_ows, BAD_CAST "Keywords");
+	    char *toto=tmp2->value;
+	    char buff[256];
+	    int i=0;
+	    int j=0;
+	    while(toto[i]){
+	      if(toto[i]!=',' && toto[i]!=0){
+		buff[j]=toto[i];
+		buff[j+1]=0;
+		j++;
+	      }
+	      else{
+		nc2 = xmlNewNode(ns_ows, BAD_CAST "Keyword");
+		xmlAddChild(nc2,xmlNewText(BAD_CAST buff));	      
+		xmlAddChild(nc1,nc2);
+		j=0;
+	      }
+	      i++;
+	    }
+	    if(strlen(buff)>0){
+	      nc2 = xmlNewNode(ns_ows, BAD_CAST "Keyword");
+	      xmlAddChild(nc2,xmlNewText(BAD_CAST buff));	      
+	      xmlAddChild(nc1,nc2);
+	    }
+	    xmlAddChild(nc,nc1);
+	    nc2 = xmlNewNode(ns_ows, BAD_CAST "ServiceType");
+	    xmlAddChild(nc2,xmlNewText(BAD_CAST "WPS"));
+	    xmlAddChild(nc,nc2);
+	    nc2 = xmlNewNode(ns_ows, BAD_CAST "ServiceTypeVersion");
+	    dumpMaps(m);
+	    map* tmpv=getMapFromMaps(m,"main","rversion");
+	    xmlAddChild(nc2,xmlNewText(BAD_CAST tmpv->value));
+	    xmlAddChild(nc,nc2);
+	  }
+	tmp2=tmp2->next;
+      }
+  }
+  else{
+    fprintf(stderr,"TMP4 NOT FOUND !!");
+    return NULL;
+  }
+  xmlAddChild(n,nc);
+
+  nc = xmlNewNode(ns_ows, BAD_CAST "ServiceProvider");
+  nc3 = xmlNewNode(ns_ows, BAD_CAST "ServiceContact");
+  nc4 = xmlNewNode(ns_ows, BAD_CAST "ContactInfo");
+  nc5 = xmlNewNode(ns_ows, BAD_CAST "Phone");
+  nc6 = xmlNewNode(ns_ows, BAD_CAST "Address");
+  tmp4=getMaps(m,"provider");
+  if(tmp4!=NULL){
+    map* tmp2=tmp4->content;
+    const char *tmpAddress[6];
+    tmpAddress[0]="addressDeliveryPoint";
+    tmpAddress[1]="addressCity";
+    tmpAddress[2]="addressAdministrativeArea";
+    tmpAddress[3]="addressPostalCode";
+    tmpAddress[4]="addressCountry";
+    tmpAddress[5]="addressElectronicMailAddress";
+    const char *tmpPhone[2];
+    tmpPhone[0]="phoneVoice";
+    tmpPhone[1]="phoneFacsimile";
+    const char *orderedFields[12];
+    orderedFields[0]="providerName";
+    orderedFields[1]="providerSite";
+    orderedFields[2]="individualName";
+    orderedFields[3]="positionName";
+    orderedFields[4]=tmpPhone[0];
+    orderedFields[5]=tmpPhone[1];
+    orderedFields[6]=tmpAddress[0];
+    orderedFields[7]=tmpAddress[1];
+    orderedFields[8]=tmpAddress[2];
+    orderedFields[9]=tmpAddress[3];
+    orderedFields[10]=tmpAddress[4];
+    orderedFields[11]=tmpAddress[5];
+    int oI=0;
+    for(oI=0;oI<12;oI++)
+      if((tmp2=getMap(tmp4->content,orderedFields[oI]))!=NULL){
+	if(strcmp(tmp2->name,"keywords")!=0 &&
+	   strcmp(tmp2->name,"serverAddress")!=0 &&
+	   strcmp(tmp2->name,"lang")!=0){
+	  tmp2->name[0]=toupper(tmp2->name[0]);
+	  if(strcmp(tmp2->name,"ProviderName")==0){
+	    nc1 = xmlNewNode(ns_ows, BAD_CAST tmp2->name);
+	    xmlAddChild(nc1,xmlNewText(BAD_CAST tmp2->value));
+	    xmlAddChild(nc,nc1);
+	  }
+	  else{
+	    if(strcmp(tmp2->name,"ProviderSite")==0){
+	      nc1 = xmlNewNode(ns_ows, BAD_CAST tmp2->name);
+	      xmlNewNsProp(nc1,ns_xlink,BAD_CAST "href",BAD_CAST tmp2->value);
+	      xmlAddChild(nc,nc1);
+	    } 
+	    else  
+	      if(strcmp(tmp2->name,"IndividualName")==0 || 
+		 strcmp(tmp2->name,"PositionName")==0){
+		nc1 = xmlNewNode(ns_ows, BAD_CAST tmp2->name);
+		xmlAddChild(nc1,xmlNewText(BAD_CAST tmp2->value));
+		xmlAddChild(nc3,nc1);
+	      } 
+	      else 
+		if(strncmp(tmp2->name,"Phone",5)==0){
+		  int j;
+		  for(j=0;j<2;j++)
+		    if(strcasecmp(tmp2->name,tmpPhone[j])==0){
+		      char *tmp4=tmp2->name;
+		      nc1 = xmlNewNode(ns_ows, BAD_CAST tmp4+5);
+		      xmlAddChild(nc1,xmlNewText(BAD_CAST tmp2->value));
+		      xmlAddChild(nc5,nc1);
+		    }
+		}
+		else 
+		  if(strncmp(tmp2->name,"Address",7)==0){
+		    int j;
+		    for(j=0;j<6;j++)
+		      if(strcasecmp(tmp2->name,tmpAddress[j])==0){
+			char *tmp4=tmp2->name;
+			nc1 = xmlNewNode(ns_ows, BAD_CAST tmp4+7);
+			xmlAddChild(nc1,xmlNewText(BAD_CAST tmp2->value));
+			xmlAddChild(nc6,nc1);
+		      }
+		  }
+	  }
+	}
+	else
+	  if(strcmp(tmp2->name,"keywords")==0){
+	    nc1 = xmlNewNode(ns_ows, BAD_CAST "Keywords");
+	    char *toto=tmp2->value;
+	    char buff[256];
+	    int i=0;
+	    int j=0;
+	    while(toto[i]){
+	      if(toto[i]!=',' && toto[i]!=0){
+		buff[j]=toto[i];
+		buff[j+1]=0;
+		j++;
+	      }
+	      else{
+		nc2 = xmlNewNode(ns_ows, BAD_CAST "Keyword");
+		xmlAddChild(nc2,xmlNewText(BAD_CAST buff));	      
+		xmlAddChild(nc1,nc2);
+		j=0;
+	      }
+	      i++;
+	    }
+	    if(strlen(buff)>0){
+	      nc2 = xmlNewNode(ns_ows, BAD_CAST "Keyword");
+	      xmlAddChild(nc2,xmlNewText(BAD_CAST buff));	      
+	      xmlAddChild(nc1,nc2);
+	    }
+	    xmlAddChild(nc,nc1);
+	  }
+	tmp2=tmp2->next;
+      }
+  }
+  else{
+    fprintf(stderr,"TMP4 NOT FOUND !!");
+  }
+  xmlAddChild(nc4,nc5);
+  xmlAddChild(nc4,nc6);
+  xmlAddChild(nc3,nc4);
+  xmlAddChild(nc,nc3);
+  xmlAddChild(n,nc);
+
+
+  nc = xmlNewNode(ns_ows, BAD_CAST "OperationsMetadata");
+
+  int j=0;
+
+  if(toto1!=NULL){
+    map* tmp=getMap(toto1->content,"serverAddress");
+    if(tmp!=NULL){
+      SERVICE_URL = strdup(tmp->value);
+    }
+    else
+      SERVICE_URL = strdup("not_defined");
+  }
+  else
+    SERVICE_URL = strdup("not_defined");
+
+  for(j=0;j<nbSupportedRequests;j++){
+    if(requests[vid][j]==NULL)
+      break;
+    else{
+      nc1 = xmlNewNode(ns_ows, BAD_CAST "Operation");
+      xmlNewProp(nc1,BAD_CAST "name",BAD_CAST requests[vid][j]);
+      nc2 = xmlNewNode(ns_ows, BAD_CAST "DCP");
+      nc3 = xmlNewNode(ns_ows, BAD_CAST "HTTP");
+      if(vid!=1 || j!=2){
+	nc4 = xmlNewNode(ns_ows, BAD_CAST "Get");
+	xmlNewNsProp(nc4,ns_xlink,BAD_CAST "href",BAD_CAST SERVICE_URL);
+	xmlAddChild(nc3,nc4);
+      }
+      nc4 = xmlNewNode(ns_ows, BAD_CAST "Post");
+      xmlNewNsProp(nc4,ns_xlink,BAD_CAST "href",BAD_CAST SERVICE_URL);
+      xmlAddChild(nc3,nc4);
+      xmlAddChild(nc2,nc3);
+      xmlAddChild(nc1,nc2);
+      xmlAddChild(nc,nc1);
+    }
+  }
+  xmlAddChild(n,nc);
+
+  if(vid==1)
+    addLanguageNodes(m,n,ns,ns_ows);
+  free(SERVICE_URL);
+
+  nc = xmlNewNode(ns, BAD_CAST root_nodes[vid][0]);
+  xmlAddChild(n,nc);
+
+  if(vid==0)
+    addLanguageNodes(m,n,ns,ns_ows);
+
+  return nc;
+}
+
+/**
+ * Generate a wps:Process node for a servie and add it to a given node.
+ * 
+ * @param m the conf maps containing the main.cfg settings
+ * @param registry the profile registry if any
+ * @param nc the XML node to add the Process node
+ * @param serv the service structure created from the zcfg file
+ * @return the generated wps:ProcessOfferings xmlNodePtr 
+ */
+void printGetCapabilitiesForProcess(maps* m,xmlNodePtr nc,service* serv){
+  xmlNsPtr ns,ns_ows,ns_xml,ns_xlink;
+  xmlNodePtr n=NULL,nc1,nc2;
+  map* version=getMapFromMaps(m,"main","rversion");
+  int vid=getVersionId(version->value);
+  // Initialize or get existing namespaces
+  int wpsId=zooXmlAddNs(NULL,schemas[vid][2],"wps");
+  ns=usedNs[wpsId];
+  int owsId=zooXmlAddNs(NULL,schemas[vid][1],"ows");
+  ns_ows=usedNs[owsId];
+  int xmlId=zooXmlAddNs(NULL,"http://www.w3.org/XML/1998/namespace","xml");
+  ns_xml=usedNs[xmlId];
+  int xlinkId=zooXmlAddNs(n,"http://www.w3.org/1999/xlink","xlink");
+  ns_xlink=usedNs[xlinkId];
+  map* tmp1;
+  if(serv->content!=NULL){
+    nc1 = xmlNewNode(ns, BAD_CAST capabilities[vid][0]);
+    int i=1;
+    int limit=3;
+    if(vid==1){
+      ns=NULL;
+      limit=7;
+    }
+    for(;i<limit;i+=2){
+      if(capabilities[vid][i]==NULL)
+	break;
+      else{
+	tmp1=getMap(serv->content,capabilities[vid][i]);
+	if(tmp1!=NULL){
+	  if(vid==1 && i==1 && strlen(tmp1->value)<5){
+	    char *val=(char*)malloc((strlen(tmp1->value)+5)*sizeof(char));
+	    sprintf(val,"%s.0.0",tmp1->value);
+	    xmlNewNsProp(nc1,ns,BAD_CAST capabilities[vid][i],BAD_CAST val);
+	    free(val);
+	  }
+	  else
+	    xmlNewNsProp(nc1,ns,BAD_CAST capabilities[vid][i],BAD_CAST tmp1->value);
+	}
+	else
+	  xmlNewNsProp(nc1,ns,BAD_CAST capabilities[vid][i],BAD_CAST capabilities[vid][i+1]);
+      }
+    }
+    map* tmp3=getMapFromMaps(m,"lenv","level");
+    addPrefix(m,tmp3,serv);
+    printDescription(nc1,ns_ows,serv->name,serv->content,vid);
+    tmp1=serv->metadata;
+    while(tmp1!=NULL){
+      nc2 = xmlNewNode(ns_ows, BAD_CAST "Metadata");
+      xmlNewNsProp(nc2,ns_xlink,BAD_CAST tmp1->name,BAD_CAST tmp1->value);
+      xmlAddChild(nc1,nc2);
+      tmp1=tmp1->next;
+    }
+
+    xmlAddChild(nc,nc1);
+  }
+}
+
+void attachAttributes(xmlNodePtr n,xmlNsPtr ns,map* content,int vid){
+  xmlNodePtr nc1;
+  int limit=(vid==1?7:3);
+  for(int i=1;i<limit;i+=2){
+    map* tmp1=getMap(content,capabilities[vid][i]);
+    if(tmp1!=NULL){
+      if(vid==1 && i==1 && strlen(tmp1->value)<5){
+	char *val=(char*)malloc((strlen(tmp1->value)+5)*sizeof(char));
+	sprintf(val,"%s.0.0",tmp1->value);
+	xmlNewNsProp(nc1,ns,BAD_CAST capabilities[vid][i],BAD_CAST val);
+	free(val);
+      }
+      else
+	xmlNewNsProp(nc1,ns,BAD_CAST capabilities[vid][i],BAD_CAST tmp1->value);
+    }
+    else
+      xmlNewNsProp(nc1,ns,BAD_CAST capabilities[vid][i],BAD_CAST capabilities[vid][i+1]);
+  }
+}
+
+/**
+ * Generate a ProcessDescription node for a servie and add it to a given node.
+ * 
+ * @param m the conf maps containing the main.cfg settings
+ * @param nc the XML node to add the Process node
+ * @param serv the servive structure created from the zcfg file
+ * @return the generated wps:ProcessOfferings xmlNodePtr 
+ */
+void printDescribeProcessForProcess(maps* m,xmlNodePtr nc,service* serv){
+  xmlNsPtr ns,ns_ows,ns_xlink;
+  xmlNodePtr n,nc1,nc2;
+  map* version=getMapFromMaps(m,"main","rversion");
+  int vid=getVersionId(version->value);
+
+  n=nc;
+  
+  int wpsId=zooXmlAddNs(NULL,schemas[vid][3],"wps");
+  ns=usedNs[wpsId];
+  int owsId=zooXmlAddNs(NULL,schemas[vid][1],"ows");
+  ns_ows=usedNs[owsId];
+  int xlinkId=zooXmlAddNs(NULL,"http://www.w3.org/1999/xlink","xlink");
+  ns_xlink=usedNs[xlinkId];
+  map* tmp1=NULL;
+
+  if(vid==0){
+    nc = xmlNewNode(NULL, BAD_CAST "ProcessDescription");
+    attachAttributes(nc,ns,serv->content,vid);
+  }
+  else{
+    nc2 = xmlNewNode(ns, BAD_CAST "ProcessOffering");
+    attachAttributes(nc2,NULL,serv->content,vid);
+    nc = xmlNewNode(ns, BAD_CAST "Process");
+  }
+  /*
+  const char *tmp4[3];
+  tmp4[0]="processVersion";
+  tmp4[1]="storeSupported";
+  tmp4[2]="statusSupported";
+  int j=0;
+  for(j=0;j<3;j++){
+    tmp1=getMap(serv->content,tmp4[j]);
+    if(tmp1!=NULL){
+      if(j==0)
+	xmlNewNsProp(nc,ns,BAD_CAST "processVersion",BAD_CAST tmp1->value);      
+      else
+	xmlNewProp(nc,BAD_CAST tmp4[j],BAD_CAST tmp1->value);      
+    }
+    else{
+      if(j>0)
+	xmlNewProp(nc,BAD_CAST tmp4[j],BAD_CAST "true");
+      else
+	xmlNewNsProp(nc,ns,BAD_CAST "processVersion",BAD_CAST "1");
+    }
+  }
+  */
+  
+  tmp1=getMapFromMaps(m,"lenv","level");
+  addPrefix(m,tmp1,serv);
+  printDescription(nc,ns_ows,serv->name,serv->content,vid);
+
+  tmp1=serv->metadata;
+  while(tmp1!=NULL){
+    nc1 = xmlNewNode(ns_ows, BAD_CAST "Metadata");
+    xmlNewNsProp(nc1,ns_xlink,BAD_CAST tmp1->name,BAD_CAST tmp1->value);
+    xmlAddChild(nc,nc1);
+    tmp1=tmp1->next;
+  }
+
+  tmp1=getMap(serv->content,"Profile");
+  if(tmp1!=NULL && vid==0){
+    nc1 = xmlNewNode(ns, BAD_CAST "Profile");
+    xmlAddChild(nc1,xmlNewText(BAD_CAST tmp1->value));
+    xmlAddChild(nc,nc1);
+  }
+
+  if(serv->inputs!=NULL){
+    elements* e=serv->inputs;
+    if(vid==0){
+      nc1 = xmlNewNode(NULL, BAD_CAST "DataInputs");
+      printFullDescription(1,e,"Input",ns,ns_ows,nc1,vid);
+      xmlAddChild(nc,nc1);
+    }
+    else{
+      printFullDescription(1,e,"wps:Input",ns,ns_ows,nc,vid);
+    }
+  }
+
+  elements* e=serv->outputs;
+  if(vid==0){
+    nc1 = xmlNewNode(NULL, BAD_CAST "ProcessOutputs");
+    printFullDescription(0,e,"Output",ns,ns_ows,nc1,vid);
+    xmlAddChild(nc,nc1);
+  }
+  else{
+    printFullDescription(0,e,"wps:Output",ns,ns_ows,nc,vid);
+  }
+  if(vid==0)
+    xmlAddChild(n,nc);
+  else{
+    xmlAddChild(nc2,nc);
+    xmlAddChild(n,nc2);
+  }
+
+}
+
+/**
+ * Generate the required XML tree for the detailled metadata informations of 
+ * inputs or outputs
+ *
+ * @param in 1 in case of inputs, 0 for outputs
+ * @param elem the elements structure containing the metadata informations
+ * @param type the name ("Input" or "Output") of the XML node to create
+ * @param ns_ows the ows XML namespace
+ * @param nc1 the XML node to use to add the created tree
+ */
+void printFullDescription(int in,elements *elem,const char* type,xmlNsPtr ns,xmlNsPtr ns_ows,xmlNodePtr nc1,int vid){
+  xmlNsPtr ns1=NULL;
+  if(vid==1)
+    ns1=ns;
+  const char *orderedFields[13];
+  orderedFields[0]="mimeType";
+  orderedFields[1]="encoding";
+  orderedFields[2]="schema";
+  orderedFields[3]="dataType";
+  orderedFields[4]="uom";
+  orderedFields[5]="CRS";
+  orderedFields[6]="value";
+  orderedFields[7]="AllowedValues";
+  orderedFields[8]="range";
+  orderedFields[9]="rangeMin";
+  orderedFields[10]="rangeMax";
+  orderedFields[11]="rangeClosure";
+  orderedFields[12]="rangeSpace";
+
+  xmlNodePtr nc2,nc3,nc4,nc5,nc6,nc7,nc8,nc9;
+  elements* e=elem;
+  nc9=NULL;
+  map* tmp1=NULL;
+  while(e!=NULL){
+    int default1=0;
+    int isAnyValue=1;
+    nc2 = xmlNewNode(NULL, BAD_CAST type);
+    if(strncmp(type,"Input",5)==0){
+      tmp1=getMap(e->content,"minOccurs");
+      if(tmp1!=NULL){
+	xmlNewProp(nc2,BAD_CAST tmp1->name,BAD_CAST tmp1->value);
+      }else
+	xmlNewProp(nc2,BAD_CAST "minOccurs",BAD_CAST "0");
+      tmp1=getMap(e->content,"maxOccurs");
+      if(tmp1!=NULL){
+	if(strcasecmp(tmp1->value,"unbounded")!=0)
+	  xmlNewProp(nc2,BAD_CAST tmp1->name,BAD_CAST tmp1->value);
+	else
+	  xmlNewProp(nc2,BAD_CAST "maxOccurs",BAD_CAST "1000");
+      }else
+	xmlNewProp(nc2,BAD_CAST "maxOccurs",BAD_CAST "1");
+      if((tmp1=getMap(e->content,"maximumMegabytes"))!=NULL){
+	xmlNewProp(nc2,BAD_CAST "maximumMegabytes",BAD_CAST tmp1->value);
+      }
+    }
+
+    printDescription(nc2,ns_ows,e->name,e->content,vid);
+
+    /**
+     * Build the (Literal/Complex/BoundingBox)Data node
+     */
+    if(strncmp(type,"Output",6)==0){
+      if(strncasecmp(e->format,"LITERALDATA",strlen(e->format))==0)
+	nc3 = xmlNewNode(ns1, BAD_CAST "LiteralOutput");
+      else if(strncasecmp(e->format,"COMPLEXDATA",strlen(e->format))==0)
+	nc3 = xmlNewNode(ns1, BAD_CAST "ComplexOutput");
+      else if(strncasecmp(e->format,"BOUNDINGBOXDATA",strlen(e->format))==0)
+	nc3 = xmlNewNode(ns1, BAD_CAST "BoundingBoxOutput");
+      else
+	nc3 = xmlNewNode(ns1, BAD_CAST e->format);
+    }else{
+      if(strncasecmp(e->format,"LITERALDATA",strlen(e->format))==0 ||
+	 strncasecmp(e->format,"LITERALOUTPUT",strlen(e->format))==0){
+	nc3 = xmlNewNode(ns1, BAD_CAST "LiteralData");
+      }
+      else if(strncasecmp(e->format,"COMPLEXDATA",strlen(e->format))==0)
+	nc3 = xmlNewNode(ns1, BAD_CAST "ComplexData");
+      else if(strncasecmp(e->format,"BOUNDINGBOXDATA",strlen(e->format))==0)
+	nc3 = xmlNewNode(ns1, BAD_CAST "BoundingBoxData");
+      else
+	nc3 = xmlNewNode(ns1, BAD_CAST e->format);
+    }
+
+    iotype* _tmp0=NULL;
+    iotype* _tmp=e->defaults;
+    int datatype=0;
+    bool hasUOM=false;
+    bool hasUOM1=false;
+    if(_tmp!=NULL){
+      if(strcmp(e->format,"LiteralOutput")==0 ||
+	 strcmp(e->format,"LiteralData")==0){
+     	datatype=1;
+	if(vid==1){
+	  nc4 = xmlNewNode(ns1, BAD_CAST "Format");
+	  xmlNewProp(nc4,BAD_CAST "mimeType",BAD_CAST "text/plain");
+	  xmlNewProp(nc4,BAD_CAST "default",BAD_CAST "true");
+	  xmlAddChild(nc3,nc4);
+	  nc5 = xmlNewNode(NULL, BAD_CAST "LiteralDataDomain");
+	  xmlNewProp(nc5,BAD_CAST "default",BAD_CAST "true");
+	}
+	else{
+	  nc4 = xmlNewNode(NULL, BAD_CAST "UOMs");
+	  nc5 = xmlNewNode(NULL, BAD_CAST "Default");
+	}
+      }
+      else if(strcmp(e->format,"BoundingBoxOutput")==0 ||
+	      strcmp(e->format,"BoundingBoxData")==0){
+	datatype=2;
+	nc5 = xmlNewNode(NULL, BAD_CAST "Default");
+      }
+      else{
+	if(vid==0)
+	  nc4 = xmlNewNode(NULL, BAD_CAST "Default");
+	nc5 = xmlNewNode(ns1, BAD_CAST "Format");
+	if(vid==1){
+	  xmlNewProp(nc5,BAD_CAST "default",BAD_CAST "true");
+	  int oI=0;
+	  for(oI=0;oI<3;oI++)
+	    if((tmp1=getMap(_tmp->content,orderedFields[oI]))!=NULL){
+	      xmlNewProp(nc5,BAD_CAST orderedFields[oI],BAD_CAST tmp1->value);
+	    }
+	}
+      }
+      
+      tmp1=_tmp->content;
+
+      if(vid==0)
+	if((tmp1=getMap(_tmp->content,"DataType"))!=NULL){
+	  nc8 = xmlNewNode(ns_ows, BAD_CAST "DataType");
+	  xmlAddChild(nc8,xmlNewText(BAD_CAST tmp1->value));
+	  char tmp[1024];
+	  sprintf(tmp,"http://www.w3.org/TR/xmlschema-2/#%s",tmp1->value);
+	  xmlNewNsProp(nc8,ns_ows,BAD_CAST "reference",BAD_CAST tmp);
+	  if(vid==0)
+	    xmlAddChild(nc3,nc8);
+	  else
+	    xmlAddChild(nc5,nc8);
+	  datatype=1;
+	}
+
+      bool isInput=false;
+      if(strncmp(type,"Input",5)==0 || strncmp(type,"wps:Input",9)==0){
+	isInput=true;
+	if((tmp1=getMap(_tmp->content,"AllowedValues"))!=NULL){
+	  nc6 = xmlNewNode(ns_ows, BAD_CAST "AllowedValues");
+	  char *token,*saveptr1;
+	  token=strtok_r(tmp1->value,",",&saveptr1);
+	  while(token!=NULL){
+	    nc7 = xmlNewNode(ns_ows, BAD_CAST "Value");
+	    char *tmps=strdup(token);
+	    tmps[strlen(tmps)]=0;
+	    xmlAddChild(nc7,xmlNewText(BAD_CAST tmps));
+	    free(tmps);
+	    xmlAddChild(nc6,nc7);
+	    token=strtok_r(NULL,",",&saveptr1);
+	  }
+	  if(getMap(_tmp->content,"range")!=NULL ||
+	     getMap(_tmp->content,"rangeMin")!=NULL ||
+	     getMap(_tmp->content,"rangeMax")!=NULL ||
+	     getMap(_tmp->content,"rangeClosure")!=NULL )
+	    goto doRange;
+	  if(vid==0)
+	    xmlAddChild(nc3,nc6);
+	  else
+	    xmlAddChild(nc5,nc6);
+	  isAnyValue=-1;
+	}
+
+        tmp1=getMap(_tmp->content,"range");
+	if(tmp1==NULL)
+	  tmp1=getMap(_tmp->content,"rangeMin");
+	if(tmp1==NULL)
+	  tmp1=getMap(_tmp->content,"rangeMax");
+	
+	if(tmp1!=NULL && isAnyValue==1){
+	  nc6 = xmlNewNode(ns_ows, BAD_CAST "AllowedValues");
+	doRange:
+	  
+	  /**
+	   * Range: Table 46 OGC Web Services Common Standard
+	   */
+	  nc8 = xmlNewNode(ns_ows, BAD_CAST "Range");
+	  
+	  map* tmp0=getMap(tmp1,"range");
+	  if(tmp0!=NULL){
+	    char* pToken;
+	    char* orig=zStrdup(tmp0->value);
+	    /**
+	     * RangeClosure: Table 47 OGC Web Services Common Standard
+	     */
+	    const char *tmp="closed";
+	    if(orig[0]=='[' && orig[strlen(orig)-1]=='[')
+	      tmp="closed-open";
+	    else
+	      if(orig[0]==']' && orig[strlen(orig)-1]==']')
+		tmp="open-closed";
+	      else
+		if(orig[0]==']' && orig[strlen(orig)-1]=='[')
+		  tmp="open";
+	    xmlNewNsProp(nc8,ns_ows,BAD_CAST "rangeClosure",BAD_CAST tmp);
+	    pToken=strtok(orig,",");
+	    int nci0=0;
+	    while(pToken!=NULL){
+	      char *tmpStr=(char*) malloc((strlen(pToken))*sizeof(char));
+	      if(nci0==0){
+		nc7 = xmlNewNode(ns_ows, BAD_CAST "MinimumValue");
+		strncpy( tmpStr, pToken+1, strlen(pToken)-1 );
+		tmpStr[strlen(pToken)-1] = '\0';
+	      }else{
+		nc7 = xmlNewNode(ns_ows, BAD_CAST "MaximumValue");
+		const char* bkt;
+		if ( ( bkt = strchr(pToken, '[') ) != NULL || ( bkt = strchr(pToken, ']') ) != NULL ){
+		  strncpy( tmpStr, pToken, bkt - pToken );
+		  tmpStr[bkt - pToken] = '\0';
+		}
+	      }
+	      xmlAddChild(nc7,xmlNewText(BAD_CAST tmpStr));
+	      free(tmpStr);
+	      xmlAddChild(nc8,nc7);
+	      nci0++;
+	      pToken = strtok(NULL,",");
+	    }		    
+	    if(getMap(tmp1,"rangeSpacing")==NULL){
+	      nc7 = xmlNewNode(ns_ows, BAD_CAST "Spacing");
+	      xmlAddChild(nc7,xmlNewText(BAD_CAST "1"));
+	      xmlAddChild(nc8,nc7);
+	    }
+	    free(orig);
+	  }else{
+	    
+	    tmp0=getMap(tmp1,"rangeMin");
+	    if(tmp0!=NULL){
+	      nc7 = xmlNewNode(ns_ows, BAD_CAST "MinimumValue");
+	      xmlAddChild(nc7,xmlNewText(BAD_CAST tmp0->value));
+	      xmlAddChild(nc8,nc7);
+	    }else{
+	      nc7 = xmlNewNode(ns_ows, BAD_CAST "MinimumValue");
+	      xmlAddChild(nc8,nc7);
+	    }
+	    tmp0=getMap(tmp1,"rangeMax");
+	    if(tmp0!=NULL){
+	      nc7 = xmlNewNode(ns_ows, BAD_CAST "MaximumValue");
+	      xmlAddChild(nc7,xmlNewText(BAD_CAST tmp0->value));
+	      xmlAddChild(nc8,nc7);
+	    }else{
+	      nc7 = xmlNewNode(ns_ows, BAD_CAST "MaximumValue");
+	      xmlAddChild(nc8,nc7);
+	    }
+	    tmp0=getMap(tmp1,"rangeSpacing");
+	    if(tmp0!=NULL){
+	      nc7 = xmlNewNode(ns_ows, BAD_CAST "Spacing");
+	      xmlAddChild(nc7,xmlNewText(BAD_CAST tmp0->value));
+	      xmlAddChild(nc8,nc7);
+	    }
+	    tmp0=getMap(tmp1,"rangeClosure");
+	    if(tmp0!=NULL){
+	      const char *tmp="closed";
+	      if(strcasecmp(tmp0->value,"co")==0)
+		tmp="closed-open";
+	      else
+		if(strcasecmp(tmp0->value,"oc")==0)
+		  tmp="open-closed";
+		else
+		  if(strcasecmp(tmp0->value,"o")==0)
+		    tmp="open";
+	      xmlNewNsProp(nc8,ns_ows,BAD_CAST "rangeClosure",BAD_CAST tmp);
+	    }else
+	      xmlNewNsProp(nc8,ns_ows,BAD_CAST "rangeClosure",BAD_CAST "closed");
+	  }
+	  if(_tmp0==NULL){
+	    xmlAddChild(nc6,nc8);
+	    _tmp0=e->supported;
+	    if(_tmp0!=NULL &&
+	       (getMap(_tmp0->content,"range")!=NULL ||
+		getMap(_tmp0->content,"rangeMin")!=NULL ||
+		getMap(_tmp0->content,"rangeMax")!=NULL ||
+		getMap(_tmp0->content,"rangeClosure")!=NULL )){
+	      tmp1=_tmp0->content;
+	      goto doRange;
+	    }
+	  }else{
+	    _tmp0=_tmp0->next;
+	    if(_tmp0!=NULL){
+	      xmlAddChild(nc6,nc8);
+	      if(getMap(_tmp0->content,"range")!=NULL ||
+		 getMap(_tmp0->content,"rangeMin")!=NULL ||
+		 getMap(_tmp0->content,"rangeMax")!=NULL ||
+		 getMap(_tmp0->content,"rangeClosure")!=NULL ){
+		tmp1=_tmp0->content;
+		goto doRange;
+	      }
+	    }
+	  }
+	  xmlAddChild(nc6,nc8);
+	  if(vid==0)
+	    xmlAddChild(nc3,nc6);
+	  else
+	    xmlAddChild(nc5,nc6);
+	  isAnyValue=-1;
+	}
+	
+      }
+      
+      int oI=0;
+      /*if(vid==0)*/ {
+	for(oI=0;oI<13;oI++)
+	  if((tmp1=getMap(_tmp->content,orderedFields[oI]))!=NULL){
+#ifdef DEBUG
+	    printf("DATATYPE DEFAULT ? %s\n",tmp1->name);
+#endif
+	    if(strcmp(tmp1->name,"asReference")!=0 &&
+	       strncasecmp(tmp1->name,"DataType",8)!=0 &&
+	       strcasecmp(tmp1->name,"extension")!=0 &&
+	       strcasecmp(tmp1->name,"value")!=0 &&
+	       strcasecmp(tmp1->name,"AllowedValues")!=0 &&
+	       strncasecmp(tmp1->name,"range",5)!=0){
+	      if(datatype!=1){
+		char *tmp2=zCapitalize1(tmp1->name);
+		nc9 = xmlNewNode(NULL, BAD_CAST tmp2);
+		free(tmp2);
+	      }
+	      else{
+		char *tmp2=zCapitalize(tmp1->name);
+		nc9 = xmlNewNode(ns_ows, BAD_CAST tmp2);
+		free(tmp2);
+	      }
+	      xmlAddChild(nc9,xmlNewText(BAD_CAST tmp1->value));
+	      if(vid==0 || oI>=3){
+		if(vid==0 || oI!=4)
+		  xmlAddChild(nc5,nc9);
+		if(oI==4 && vid==1){
+		  xmlNewProp(nc9,BAD_CAST "default",BAD_CAST "true");
+		}
+	      }
+	      else
+		xmlFree(nc9);
+	      if(strcasecmp(tmp1->name,"uom")==0)
+		hasUOM1=true;
+	      hasUOM=true;
+	    }else 	  
+	      tmp1=tmp1->next;
+	  }
+      }
+    
+      if(datatype!=2){
+	if(hasUOM==true){
+	  if(vid==0){
+	    xmlAddChild(nc4,nc5);
+	    xmlAddChild(nc3,nc4);
+	  }
+	  else{
+	    xmlAddChild(nc3,nc5);
+	  }
+	}else{
+	  if(hasUOM1==false && vid==0){
+	    xmlFreeNode(nc5);
+	    if(datatype==1)
+	      xmlFreeNode(nc4);
+	  }
+	  else
+	    xmlAddChild(nc3,nc5);
+	}
+      }else{
+	xmlAddChild(nc3,nc5);
+      }
+      
+      if(datatype!=1 && default1<0){
+	xmlFreeNode(nc5);
+	if(datatype!=2)
+	  xmlFreeNode(nc4);
+      }
+
+
+      if((isInput || vid==1) && datatype==1 &&
+	 getMap(_tmp->content,"AllowedValues")==NULL &&
+	 getMap(_tmp->content,"range")==NULL &&
+	 getMap(_tmp->content,"rangeMin")==NULL &&
+	 getMap(_tmp->content,"rangeMax")==NULL &&
+	 getMap(_tmp->content,"rangeClosure")==NULL ){
+	tmp1=getMap(_tmp->content,"dataType");
+	// We were tempted to define default value for boolean as {true,false}
+	if(tmp1!=NULL && strcasecmp(tmp1->value,"boolean")==0){
+	  nc6 = xmlNewNode(ns_ows, BAD_CAST "AllowedValues");
+	  nc7 = xmlNewNode(ns_ows, BAD_CAST "Value");
+	  xmlAddChild(nc7,xmlNewText(BAD_CAST "true"));
+	  xmlAddChild(nc6,nc7);
+	  nc7 = xmlNewNode(ns_ows, BAD_CAST "Value");
+	  xmlAddChild(nc7,xmlNewText(BAD_CAST "false"));
+	  xmlAddChild(nc6,nc7);
+	  if(vid==0)
+	    xmlAddChild(nc3,nc6);
+	  else
+	    xmlAddChild(nc5,nc6);
+	}
+	else
+	if(vid==0)
+	  xmlAddChild(nc3,xmlNewNode(ns_ows, BAD_CAST "AnyValue"));
+	else
+	  xmlAddChild(nc5,xmlNewNode(ns_ows, BAD_CAST "AnyValue"));
+      }
+
+      if(vid==1){
+	if((tmp1=getMap(_tmp->content,"DataType"))!=NULL){
+	  nc8 = xmlNewNode(ns_ows, BAD_CAST "DataType");
+	  xmlAddChild(nc8,xmlNewText(BAD_CAST tmp1->value));
+	  char tmp[1024];
+	  sprintf(tmp,"http://www.w3.org/TR/xmlschema-2/#%s",tmp1->value);
+	  xmlNewNsProp(nc8,ns_ows,BAD_CAST "reference",BAD_CAST tmp);
+	  if(vid==0)
+	    xmlAddChild(nc3,nc8);
+	  else
+	    xmlAddChild(nc5,nc8);
+	  datatype=1;
+	}
+	if(hasUOM==true){
+	  tmp1=getMap(_tmp->content,"uom");
+	  if(tmp1!=NULL){
+	    char *tmp2=zCapitalize(tmp1->name);
+	    nc9 = xmlNewNode(ns_ows, BAD_CAST tmp2);
+	    free(tmp2);
+	    //xmlNewProp(nc9, BAD_CAST "default", BAD_CAST "true");
+	    xmlAddChild(nc9,xmlNewText(BAD_CAST tmp1->value));
+	    xmlAddChild(nc5,nc9);
+	    /*struct iotype * _ltmp=e->supported;
+	    while(_ltmp!=NULL){
+	      tmp1=getMap(_ltmp->content,"uom");
+	      if(tmp1!=NULL){
+		char *tmp2=zCapitalize(tmp1->name);
+		nc9 = xmlNewNode(ns_ows, BAD_CAST tmp2);
+		free(tmp2);
+		xmlAddChild(nc9,xmlNewText(BAD_CAST tmp1->value));
+		xmlAddChild(nc5,nc9);
+	      }
+	      _ltmp=_ltmp->next;
+	      }*/
+	    
+	  }
+	}
+	if(e->defaults!=NULL && (tmp1=getMap(e->defaults->content,"value"))!=NULL){
+	  nc7 = xmlNewNode(ns_ows, BAD_CAST "DefaultValue");
+	  xmlAddChild(nc7,xmlNewText(BAD_CAST tmp1->value));
+	  xmlAddChild(nc5,nc7);
+	}
+      }
+
+      map* metadata=e->metadata;
+      xmlNodePtr n=NULL;
+      int xlinkId=zooXmlAddNs(n,"http://www.w3.org/1999/xlink","xlink");
+      xmlNsPtr ns_xlink=usedNs[xlinkId];
+
+      while(metadata!=NULL){
+	nc6=xmlNewNode(ns_ows, BAD_CAST "Metadata");
+	xmlNewNsProp(nc6,ns_xlink,BAD_CAST metadata->name,BAD_CAST metadata->value);
+	xmlAddChild(nc2,nc6);
+	metadata=metadata->next;
+      }
+
+    }
+
+    _tmp=e->supported;
+    if(_tmp==NULL && datatype!=1)
+      _tmp=e->defaults;
+
+    int hasSupported=-1;
+
+    while(_tmp!=NULL){
+      if(hasSupported<0){
+	if(datatype==0){
+	  if(vid==0)
+	    nc4 = xmlNewNode(NULL, BAD_CAST "Supported");
+	  nc5 = xmlNewNode(ns1, BAD_CAST "Format");
+	  if(vid==1){
+	    int oI=0;
+	    for(oI=0;oI<3;oI++)
+	      if((tmp1=getMap(_tmp->content,orderedFields[oI]))!=NULL){
+		xmlNewProp(nc5,BAD_CAST orderedFields[oI],BAD_CAST tmp1->value);
+	      }
+	  }
+	}
+	else
+	  if(vid==0)
+	    nc5 = xmlNewNode(NULL, BAD_CAST "Supported");
+	hasSupported=0;
+      }else
+	if(datatype==0){
+	  nc5 = xmlNewNode(ns1, BAD_CAST "Format");
+	  if(vid==1){
+	    int oI=0;
+	    for(oI=0;oI<3;oI++)
+	      if((tmp1=getMap(_tmp->content,orderedFields[oI]))!=NULL){
+		xmlNewProp(nc5,BAD_CAST orderedFields[oI],BAD_CAST tmp1->value);
+	      }
+	  }
+	}
+      tmp1=_tmp->content;
+      int oI=0;
+      for(oI=0;oI<6;oI++)
+	if((tmp1=getMap(_tmp->content,orderedFields[oI]))!=NULL){
+#ifdef DEBUG
+	  printf("DATATYPE SUPPORTED ? %s\n",tmp1->name);
+#endif
+	  if(strcmp(tmp1->name,"asReference")!=0 && 
+	     strcmp(tmp1->name,"value")!=0 && 
+	     strcmp(tmp1->name,"DataType")!=0 &&
+	     strcasecmp(tmp1->name,"extension")!=0){
+	    if(datatype!=1){
+	      char *tmp2=zCapitalize1(tmp1->name);
+	      nc6 = xmlNewNode(NULL, BAD_CAST tmp2);
+	      free(tmp2);
+	    }
+	    else{
+	      char *tmp2=zCapitalize(tmp1->name);
+	      nc6 = xmlNewNode(ns_ows, BAD_CAST tmp2);
+	      free(tmp2);
+	    }
+	    if(datatype==2){
+	      char *tmpv,*tmps;
+	      tmps=strtok_r(tmp1->value,",",&tmpv);
+	      while(tmps){
+		xmlAddChild(nc6,xmlNewText(BAD_CAST tmps));
+		tmps=strtok_r(NULL,",",&tmpv);
+		if(tmps){
+		  char *tmp2=zCapitalize1(tmp1->name);
+		  nc6 = xmlNewNode(NULL, BAD_CAST tmp2);
+		  free(tmp2);
+		}
+	      }
+	    }
+	    else{
+	      xmlAddChild(nc6,xmlNewText(BAD_CAST tmp1->value));
+	    }
+	    if(vid==0 || oI>=3){
+	      if(vid==0 || oI!=4)
+		xmlAddChild(nc5,nc6);
+	      else
+		xmlFree(nc6);
+	    }
+	    else
+	      xmlFree(nc6);
+	  }
+	  tmp1=tmp1->next;
+	}
+      if(hasSupported<=0){
+	if(datatype==0){
+	  if(vid==0){
+	    xmlAddChild(nc4,nc5);
+	    xmlAddChild(nc3,nc4);
+	  }
+	  else{
+	    xmlAddChild(nc3,nc5);
+	  }
+
+	}else{
+	  if(datatype!=1)
+	    xmlAddChild(nc3,nc5);
+	}
+	hasSupported=1;
+      }
+      else
+	if(datatype==0){
+	  if(vid==0){
+	    xmlAddChild(nc4,nc5);
+	    xmlAddChild(nc3,nc4);
+	  }
+	  else{
+	    xmlAddChild(nc3,nc5);
+	  }
+	}
+	else
+	  if(datatype!=1)
+	    xmlAddChild(nc3,nc5);
+
+      _tmp=_tmp->next;
+    }
+
+    if(hasSupported==0){
+      if(datatype==0 && vid!=0)
+	xmlFreeNode(nc4);
+      xmlFreeNode(nc5);
+    }
+
+    _tmp=e->defaults;
+    if(datatype==1 && hasUOM1==true){
+      if(vid==0){
+	xmlAddChild(nc4,nc5);
+	xmlAddChild(nc3,nc4);
+      }
+      else{
+	xmlAddChild(nc3,nc5);
+      }
+    }
+
+    if(vid==0 && _tmp!=NULL && (tmp1=getMap(_tmp->content,"value"))!=NULL){
+      nc7 = xmlNewNode(NULL, BAD_CAST "DefaultValue");
+      xmlAddChild(nc7,xmlNewText(BAD_CAST tmp1->value));
+      xmlAddChild(nc3,nc7);
+    }
+    
+    xmlAddChild(nc2,nc3);
+    
+    xmlAddChild(nc1,nc2);
+    
+    e=e->next;
+  }
+}
+
+/**
+ * Generate a wps:Execute XML document.
+ * 
+ * @param m the conf maps containing the main.cfg settings
+ * @param request the map representing the HTTP request
+ * @param pid the process identifier linked to a service
+ * @param serv the serv structure created from the zcfg file
+ * @param service the service name
+ * @param status the status returned by the service
+ * @param inputs the inputs provided
+ * @param outputs the outputs generated by the service
+ */
+void printProcessResponse(maps* m,map* request, int pid,service* serv,const char* service,int status,maps* inputs,maps* outputs){
+  xmlNsPtr ns,ns_ows,ns_xlink;
+  xmlNodePtr nr,n,nc,nc1=NULL,nc3;
+  xmlDocPtr doc;
+  time_t time1;  
+  time(&time1);
+  nr=NULL;
+
+  doc = xmlNewDoc(BAD_CAST "1.0");
+  map* version=getMap(request,"version");
+  n = printWPSHeader(doc,m,"Execute","ExecuteResponse",(version!=NULL?version->value:"1.0.0"),2);
+  int wpsId=zooXmlAddNs(NULL,"http://www.opengis.net/wps/1.0.0","wps");
+  ns=usedNs[wpsId];
+  int owsId=zooXmlAddNs(NULL,"http://www.opengis.net/ows/1.1","ows");
+  ns_ows=usedNs[owsId];
+  int xlinkId=zooXmlAddNs(NULL,"http://www.w3.org/1999/xlink","xlink");
+  ns_xlink=usedNs[xlinkId];
+
+  char tmp[256];
+  char url[1024];
+  char stored_path[1024];
+  memset(tmp,0,256);
+  memset(url,0,1024);
+  memset(stored_path,0,1024);
+  maps* tmp_maps=getMaps(m,"main");
+  if(tmp_maps!=NULL){
+    map* tmpm1=getMap(tmp_maps->content,"serverAddress");
+    /**
+     * Check if the ZOO Service GetStatus is available in the local directory.
+     * If yes, then it uses a reference to an URL which the client can access
+     * to get information on the status of a running Service (using the 
+     * percentCompleted attribute). 
+     * Else fallback to the initial method using the xml file to write in ...
+     */
+    char ntmp[1024];
+#ifndef WIN32
+    getcwd(ntmp,1024);
+#else
+    _getcwd(ntmp,1024);
+#endif
+    struct stat myFileInfo;
+    int statRes;
+    char file_path[1024];
+    sprintf(file_path,"%s/GetStatus.zcfg",ntmp);
+    statRes=stat(file_path,&myFileInfo);
+    if(statRes==0){
+      char currentSid[128];
+      map* tmpm=getMap(tmp_maps->content,"rewriteUrl");
+      map *tmp_lenv=NULL;
+      tmp_lenv=getMapFromMaps(m,"lenv","usid");
+      if(tmp_lenv==NULL)
+	sprintf(currentSid,"%i",pid);
+      else
+	sprintf(currentSid,"%s",tmp_lenv->value);
+      if(tmpm==NULL || strcasecmp(tmpm->value,"false")==0){
+	sprintf(url,"%s?request=Execute&service=WPS&version=1.0.0&Identifier=GetStatus&DataInputs=sid=%s&RawDataOutput=Result",tmpm1->value,currentSid);
+      }else{
+	if(strlen(tmpm->value)>0)
+	  if(strcasecmp(tmpm->value,"true")!=0)
+	    sprintf(url,"%s/%s/GetStatus/%s",tmpm1->value,tmpm->value,currentSid);
+	  else
+	    sprintf(url,"%s/GetStatus/%s",tmpm1->value,currentSid);
+	else
+	  sprintf(url,"%s/?request=Execute&service=WPS&version=1.0.0&Identifier=GetStatus&DataInputs=sid=%s&RawDataOutput=Result",tmpm1->value,currentSid);
+	fprintf(stderr,"%s %d\n",__FILE__,__LINE__);
+      }
+    }else{
+      int lpid;
+      map* tmpm2=getMapFromMaps(m,"lenv","usid");
+      lpid=atoi(tmpm2->value);
+      tmpm2=getMap(tmp_maps->content,"tmpUrl");
+      if(tmpm1!=NULL && tmpm2!=NULL){
+	if( strncasecmp( tmpm2->value, "http://", 7) == 0 ||
+	    strncasecmp( tmpm2->value, "https://", 8 ) == 0 ){
+	  sprintf(url,"%s/%s_%i.xml",tmpm2->value,service,lpid);
+	}else
+	  sprintf(url,"%s/%s/%s_%i.xml",tmpm1->value,tmpm2->value,service,lpid);
+      }
+    }
+    if(tmpm1!=NULL){
+      sprintf(tmp,"%s",tmpm1->value);
+    }
+    int lpid;
+    tmpm1=getMapFromMaps(m,"lenv","usid");
+    lpid=atoi(tmpm1->value);
+    tmpm1=getMapFromMaps(m,"main","TmpPath");
+    sprintf(stored_path,"%s/%s_%i.xml",tmpm1->value,service,lpid);
+  }
+
+  xmlNewProp(n,BAD_CAST "serviceInstance",BAD_CAST tmp);
+  map* test=getMap(request,"storeExecuteResponse");
+  bool hasStoredExecuteResponse=false;
+  if(test!=NULL && strcasecmp(test->value,"true")==0){
+    xmlNewProp(n,BAD_CAST "statusLocation",BAD_CAST url);
+    hasStoredExecuteResponse=true;
+  }
+
+  nc = xmlNewNode(ns, BAD_CAST "Process");
+  map* tmp2=getMap(serv->content,"processVersion");
+  if(tmp2!=NULL)
+    xmlNewNsProp(nc,ns,BAD_CAST "processVersion",BAD_CAST tmp2->value);
+  
+  map* tmpI=getMapFromMaps(m,"lenv","oIdentifier");
+  printDescription(nc,ns_ows,tmpI->value,serv->content,0);
+
+  xmlAddChild(n,nc);
+
+  nc = xmlNewNode(ns, BAD_CAST "Status");
+  const struct tm *tm;
+  size_t len;
+  time_t now;
+  char *tmp1;
+  map *tmpStatus;
+  
+  now = time ( NULL );
+  tm = localtime ( &now );
+
+  tmp1 = (char*)malloc((TIME_SIZE+1)*sizeof(char));
+
+  len = strftime ( tmp1, TIME_SIZE, "%Y-%m-%dT%I:%M:%SZ", tm );
+
+  xmlNewProp(nc,BAD_CAST "creationTime",BAD_CAST tmp1);
+
+  char sMsg[2048];
+  switch(status){
+  case SERVICE_SUCCEEDED:
+    nc1 = xmlNewNode(ns, BAD_CAST "ProcessSucceeded");
+    sprintf(sMsg,_("The service \"%s\" ran successfully."),serv->name);
+    nc3=xmlNewText(BAD_CAST sMsg);
+    xmlAddChild(nc1,nc3);
+    break;
+  case SERVICE_STARTED:
+    nc1 = xmlNewNode(ns, BAD_CAST "ProcessStarted");
+    tmpStatus=getMapFromMaps(m,"lenv","status");
+    xmlNewProp(nc1,BAD_CAST "percentCompleted",BAD_CAST tmpStatus->value);
+    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);
+    nc3=xmlNewText(BAD_CAST sMsg);
+    xmlAddChild(nc1,nc3);
+    break;
+  case SERVICE_ACCEPTED:
+    nc1 = xmlNewNode(ns, BAD_CAST "ProcessAccepted");
+    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);
+    nc3=xmlNewText(BAD_CAST sMsg);
+    xmlAddChild(nc1,nc3);
+    break;
+  case SERVICE_FAILED:
+    nc1 = xmlNewNode(ns, BAD_CAST "ProcessFailed");
+    map *errorMap;
+    map *te;
+    te=getMapFromMaps(m,"lenv","code");
+    if(te!=NULL)
+      errorMap=createMap("code",te->value);
+    else
+      errorMap=createMap("code","NoApplicableCode");
+    te=getMapFromMaps(m,"lenv","message");
+    if(te!=NULL)
+      addToMap(errorMap,"text",_ss(te->value));
+    else
+      addToMap(errorMap,"text",_("No more information available"));
+    nc3=createExceptionReportNode(m,errorMap,0);
+    freeMap(&errorMap);
+    free(errorMap);
+    xmlAddChild(nc1,nc3);
+    break;
+  default :
+    printf(_("error code not know : %i\n"),status);
+    //exit(1);
+    break;
+  }
+  xmlAddChild(nc,nc1);
+  xmlAddChild(n,nc);
+  free(tmp1);
+
+#ifdef DEBUG
+  fprintf(stderr,"printProcessResponse 1 161\n");
+#endif
+
+  map* lineage=getMap(request,"lineage");
+  if(lineage!=NULL && strcasecmp(lineage->value,"true")==0){
+    nc = xmlNewNode(ns, BAD_CAST "DataInputs");
+    maps* mcursor=inputs;
+    elements* scursor=NULL;
+    while(mcursor!=NULL /*&& scursor!=NULL*/){
+      scursor=getElements(serv->inputs,mcursor->name);
+      printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Input");
+      mcursor=mcursor->next;
+    }
+    xmlAddChild(n,nc);
+    
+#ifdef DEBUG
+    fprintf(stderr,"printProcessResponse 1 177\n");
+#endif
+
+    nc = xmlNewNode(ns, BAD_CAST "OutputDefinitions");
+    mcursor=outputs;
+    scursor=NULL;
+    while(mcursor!=NULL){
+      scursor=getElements(serv->outputs,mcursor->name);
+      printOutputDefinitions(doc,nc,ns,ns_ows,scursor,mcursor,"Output");
+      mcursor=mcursor->next;
+    }
+    xmlAddChild(n,nc);
+  }
+#ifdef DEBUG
+  fprintf(stderr,"printProcessResponse 1 190\n");
+#endif
+
+  /**
+   * Display the process output only when requested !
+   */
+  if(status==SERVICE_SUCCEEDED){
+    nc = xmlNewNode(ns, BAD_CAST "ProcessOutputs");
+    maps* mcursor=outputs;
+    elements* scursor=serv->outputs;
+    map* testResponse=getMap(request,"RawDataOutput");
+    if(testResponse==NULL)
+      testResponse=getMap(request,"ResponseDocument");
+    while(mcursor!=NULL){
+      map* tmp0=getMap(mcursor->content,"inRequest");
+      scursor=getElements(serv->outputs,mcursor->name);
+      if(scursor!=NULL){
+	if(testResponse==NULL || tmp0==NULL)
+	  printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Output");
+	else
+	  if(tmp0!=NULL && strncmp(tmp0->value,"true",4)==0)
+	    printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Output");
+      }else
+	/**
+	 * In case there was no definition found in the ZCFG file but 
+	 * present in the service code
+	 */
+	printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Output");
+      mcursor=mcursor->next;
+    }
+    xmlAddChild(n,nc);
+  }
+
+  if(hasStoredExecuteResponse==true && status!=SERVICE_STARTED){
+    semid lid=getShmLockId(m,1);
+    if(lid<0){
+      /* If the lock failed */
+      errorException(m,_("Lock failed."),"InternalError",NULL);
+      xmlFreeDoc(doc);
+      xmlCleanupParser();
+      zooXmlCleanupNs();
+      return;
+    }
+    else{
+#ifdef DEBUG
+      fprintf(stderr,"LOCK %s %d !\n",__FILE__,__LINE__);
+#endif
+      lockShm(lid);
+      /* We need to write the ExecuteResponse Document somewhere */
+      FILE* output=fopen(stored_path,"w");
+      if(output==NULL){
+	/* If the file cannot be created return an ExceptionReport */
+	char tmpMsg[1024];
+	sprintf(tmpMsg,_("Unable to create the file \"%s\" for storing the ExecuteResponse."),stored_path);
+
+	errorException(m,tmpMsg,"InternalError",NULL);
+	xmlFreeDoc(doc);
+	xmlCleanupParser();
+	zooXmlCleanupNs();
+	unlockShm(lid);
+	return;
+      }
+      xmlChar *xmlbuff;
+      int buffersize;
+      xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, "UTF-8", 1);
+      fwrite(xmlbuff,1,xmlStrlen(xmlbuff)*sizeof(char),output);
+      xmlFree(xmlbuff);
+      fclose(output);
+#ifdef DEBUG
+      fprintf(stderr,"UNLOCK %s %d !\n",__FILE__,__LINE__);
+#endif
+      unlockShm(lid);
+      map* test1=getMap(request,"status");
+      if(test1==NULL || strcasecmp(test1->value,"true")!=0){
+	removeShmLock(m,1);
+      }
+    }
+  }
+  printDocument(m,doc,pid);
+
+  xmlCleanupParser();
+  zooXmlCleanupNs();
+}
+
+/**
+ * Print a XML document.
+ * 
+ * @param m the conf maps containing the main.cfg settings
+ * @param doc the XML document
+ * @param pid the process identifier linked to a service
+ */
+void printDocument(maps* m, xmlDocPtr doc,int pid){
+  char *encoding=getEncoding(m);
+  if(pid==getpid()){
+    printHeaders(m);
+    printf("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding);
+  }
+  fflush(stdout);
+  xmlChar *xmlbuff;
+  int buffersize;
+  /*
+   * Dump the document to a buffer and print it on stdout
+   * for demonstration purposes.
+   */
+  xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);
+  printf("%s",xmlbuff);
+  fflush(stdout);
+  /*
+   * Free associated memory.
+   */
+  xmlFree(xmlbuff);
+  xmlFreeDoc(doc);
+  xmlCleanupParser();
+  zooXmlCleanupNs();
+}
+
+/**
+ * Print a XML document.
+ * 
+ * @param doc the XML document (unused)
+ * @param nc the XML node to add the output definition
+ * @param ns_wps the wps XML namespace
+ * @param ns_ows the ows XML namespace
+ * @param e the output elements 
+ * @param m the conf maps containing the main.cfg settings
+ * @param type the type (unused)
+ */
+void printOutputDefinitions(xmlDocPtr doc,xmlNodePtr nc,xmlNsPtr ns_wps,xmlNsPtr ns_ows,elements* e,maps* m,const char* type){
+  xmlNodePtr nc1;
+  nc1=xmlNewNode(ns_wps, BAD_CAST type);
+  map *tmp=NULL;  
+  if(e!=NULL && e->defaults!=NULL)
+    tmp=e->defaults->content;
+  else{
+    /*
+    dumpElements(e);
+    */
+    return;
+  }
+  while(tmp!=NULL){
+    if(strncasecmp(tmp->name,"MIMETYPE",strlen(tmp->name))==0
+       || strncasecmp(tmp->name,"ENCODING",strlen(tmp->name))==0
+       || strncasecmp(tmp->name,"SCHEMA",strlen(tmp->name))==0
+       || strncasecmp(tmp->name,"UOM",strlen(tmp->name))==0)
+    xmlNewProp(nc1,BAD_CAST tmp->name,BAD_CAST tmp->value);
+    tmp=tmp->next;
+  }
+  tmp=getMap(e->defaults->content,"asReference");
+  if(tmp==NULL)
+    xmlNewProp(nc1,BAD_CAST "asReference",BAD_CAST "false");
+
+  tmp=e->content;
+
+  printDescription(nc1,ns_ows,m->name,e->content,0);
+
+  xmlAddChild(nc,nc1);
+
+}
+
+/**
+ * Generate XML nodes describing inputs or outputs metadata.
+ * 
+ * @param doc the XML document 
+ * @param nc the XML node to add the definition
+ * @param ns_wps the wps namespace
+ * @param ns_ows the ows namespace
+ * @param ns_xlink the xlink namespace
+ * @param e the output elements 
+ * @param m the conf maps containing the main.cfg settings
+ * @param type the type
+ */
+void printIOType(xmlDocPtr doc,xmlNodePtr nc,xmlNsPtr ns_wps,xmlNsPtr ns_ows,xmlNsPtr ns_xlink,elements* e,maps* m,const char* type){
+
+  xmlNodePtr nc1,nc2,nc3;
+  nc1=xmlNewNode(ns_wps, BAD_CAST type);
+  map *tmp=NULL;
+  if(e!=NULL)
+    tmp=e->content;
+  else
+    tmp=m->content;
+
+  nc2=xmlNewNode(ns_ows, BAD_CAST "Identifier");
+  if(e!=NULL)
+    nc3=xmlNewText(BAD_CAST e->name);
+  else
+    nc3=xmlNewText(BAD_CAST m->name);
+
+  xmlAddChild(nc2,nc3);
+  xmlAddChild(nc1,nc2);
+  xmlAddChild(nc,nc1);
+  if(e!=NULL)
+    tmp=getMap(e->content,"Title");
+  else
+    tmp=getMap(m->content,"Title");
+  
+  if(tmp!=NULL){
+    nc2=xmlNewNode(ns_ows, BAD_CAST tmp->name);
+    nc3=xmlNewText(BAD_CAST _ss(tmp->value));
+    xmlAddChild(nc2,nc3);  
+    xmlAddChild(nc1,nc2);
+  }
+
+  if(e!=NULL)
+    tmp=getMap(e->content,"Abstract");
+  else
+    tmp=getMap(m->content,"Abstract");
+
+  if(tmp!=NULL){
+    nc2=xmlNewNode(ns_ows, BAD_CAST tmp->name);
+    nc3=xmlNewText(BAD_CAST _ss(tmp->value));
+    xmlAddChild(nc2,nc3);  
+    xmlAddChild(nc1,nc2);
+    xmlAddChild(nc,nc1);
+  }
+
+  /**
+   * IO type Reference or full Data ?
+   */
+  map *tmpMap=getMap(m->content,"Reference");
+  if(tmpMap==NULL){
+    nc2=xmlNewNode(ns_wps, BAD_CAST "Data");
+    if(e!=NULL){
+      if(strncasecmp(e->format,"LiteralOutput",strlen(e->format))==0)
+	nc3=xmlNewNode(ns_wps, BAD_CAST "LiteralData");
+      else
+        if(strncasecmp(e->format,"ComplexOutput",strlen(e->format))==0)
+	  nc3=xmlNewNode(ns_wps, BAD_CAST "ComplexData");
+	else if(strncasecmp(e->format,"BoundingBoxOutput",strlen(e->format))==0)
+	  nc3=xmlNewNode(ns_wps, BAD_CAST "BoundingBoxData");
+	else
+	  nc3=xmlNewNode(ns_wps, BAD_CAST e->format);
+    }
+    else {
+      map* tmpV=getMapFromMaps(m,"format","value");
+      if(tmpV!=NULL)
+	nc3=xmlNewNode(ns_wps, BAD_CAST tmpV->value);
+      else
+	nc3=xmlNewNode(ns_wps, BAD_CAST "LiteralData");
+    } 
+    tmp=m->content;
+
+    while(tmp!=NULL){
+      if(strcasecmp(tmp->name,"mimeType")==0 ||
+	 strcasecmp(tmp->name,"encoding")==0 ||
+	 strcasecmp(tmp->name,"schema")==0 ||
+	 strcasecmp(tmp->name,"datatype")==0 ||
+	 strcasecmp(tmp->name,"uom")==0) {
+
+	xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST tmp->value);
+      }
+      tmp=tmp->next;
+      xmlAddChild(nc2,nc3);
+    }
+    if(e!=NULL && e->format!=NULL && strcasecmp(e->format,"BoundingBoxData")==0) {
+      map* bb=getMap(m->content,"value");
+      if(bb!=NULL) {
+	map* tmpRes=parseBoundingBox(bb->value);
+	printBoundingBox(ns_ows,nc3,tmpRes);
+	freeMap(&tmpRes);
+	free(tmpRes);
+      }
+    }
+    else {
+      if(e!=NULL)
+	tmp=getMap(e->defaults->content,"mimeType");
+      else
+	tmp=NULL;
+	
+      map* tmp1=getMap(m->content,"encoding");
+      map* tmp2=getMap(m->content,"mimeType");
+      map* tmp3=getMap(m->content,"value");
+      int hasValue=1;
+      if(tmp3==NULL){
+	tmp3=createMap("value","");
+	hasValue=-1;
+      }
+
+      if( ( tmp1 != NULL && strncmp(tmp1->value,"base64",6) == 0 )     // if encoding is base64
+	  || 	                                                       // or if 
+	  ( tmp2 != NULL && ( strstr(tmp2->value,"text") == NULL       //  mime type is not text 
+			      &&                                       //  nor 
+			      strstr(tmp2->value,"xml") == NULL        //  xml
+			      &&                                       // nor
+			      strstr(tmp2->value,"javascript") == NULL // javascript
+			      &&
+			      strstr(tmp2->value,"json") == NULL
+			      &&
+			      strstr(tmp2->value,"ecmascript") == NULL
+			      &&
+			      // include for backwards compatibility,
+			      // although correct mime type is ...kml+xml:
+			      strstr(tmp2->value,"google-earth.kml") == NULL							)
+	    )
+	  ) { 	                                                 // then	
+	map* rs=getMap(m->content,"size");                       // obtain size
+	bool isSized=true;
+	if(rs==NULL){
+	  char tmp1[1024];
+	  sprintf(tmp1,"%ld",strlen(tmp3->value));
+	  rs=createMap("size",tmp1);
+	  isSized=false;
+	}
+	 
+	xmlAddChild(nc3,xmlNewText(BAD_CAST base64(tmp3->value, atoi(rs->value))));  // base 64 encode in XML
+		
+	if(tmp1==NULL || (tmp1!=NULL && strncmp(tmp1->value,"base64",6)!=0)) {
+	  xmlAttrPtr ap = xmlHasProp(nc3, BAD_CAST "encoding");
+	  if (ap != NULL) {
+	    xmlRemoveProp(ap);
+	  }			
+	  xmlNewProp(nc3,BAD_CAST "encoding",BAD_CAST "base64");
+	}
+		
+	if(!isSized){
+	  freeMap(&rs);
+	  free(rs);
+	}
+      }
+      else if (tmp2!=NULL) {                                 // else (text-based format) 
+	if(strstr(tmp2->value, "javascript") != NULL ||      //    if javascript put code in CDATA block 
+	   strstr(tmp2->value, "json") != NULL ||            //    (will not be parsed by XML reader) 
+	   strstr(tmp2->value, "ecmascript") != NULL
+	   ) {
+	  xmlAddChild(nc3,xmlNewCDataBlock(doc,BAD_CAST tmp3->value,strlen(tmp3->value)));
+	}   
+	else {                                                     // else
+	  if (strstr(tmp2->value, "xml") != NULL ||                 // if XML-based format
+	      // include for backwards compatibility,
+	      // although correct mime type is ...kml+xml:		   
+	      strstr(tmp2->value, "google-earth.kml") != NULL
+	      ) { 
+			  
+	    int li=zooXmlAddDoc(tmp3->value);
+	    xmlDocPtr doc = iDocs[li];
+	    xmlNodePtr ir = xmlDocGetRootElement(doc);
+	    xmlAddChild(nc3,ir);
+	  }
+	  else                                                     // else	
+	    xmlAddChild(nc3,xmlNewText(BAD_CAST tmp3->value));    //   add text node
+	}
+	xmlAddChild(nc2,nc3);
+      }
+      else {
+	xmlAddChild(nc3,xmlNewText(BAD_CAST tmp3->value));
+      }
+	  
+      if(hasValue<0) {
+	freeMap(&tmp3);
+	free(tmp3);
+      }
+    }
+  }
+  else { // Reference
+    tmpMap=getMap(m->content,"Reference");
+    nc3=nc2=xmlNewNode(ns_wps, BAD_CAST "Reference");
+    if(strcasecmp(type,"Output")==0)
+      xmlNewProp(nc3,BAD_CAST "href",BAD_CAST tmpMap->value);
+    else
+      xmlNewNsProp(nc3,ns_xlink,BAD_CAST "href",BAD_CAST tmpMap->value);
+    
+    tmp=m->content;
+    while(tmp!=NULL) {
+      if(strcasecmp(tmp->name,"mimeType")==0 ||
+	 strcasecmp(tmp->name,"encoding")==0 ||
+	 strcasecmp(tmp->name,"schema")==0 ||
+	 strcasecmp(tmp->name,"datatype")==0 ||
+	 strcasecmp(tmp->name,"uom")==0){
+
+	if(strcasecmp(tmp->name,"datatype")==0)
+	  xmlNewProp(nc3,BAD_CAST "mimeType",BAD_CAST "text/plain");
+	else
+	  xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST tmp->value);
+      }
+      tmp=tmp->next;
+      xmlAddChild(nc2,nc3);
+    }
+  }
+  xmlAddChild(nc1,nc2);
+  xmlAddChild(nc,nc1);
+}
+
+/**
+ * Create XML node with basic ows metadata informations (Identifier,Title,Abstract)
+ *
+ * @param root the root XML node to add the description
+ * @param ns_ows the ows XML namespace
+ * @param identifier the identifier to use
+ * @param amap the map containing the ows metadata informations 
+ */
+void printDescription(xmlNodePtr root,xmlNsPtr ns_ows,const char* identifier,map* amap,int vid=0){
+  xmlNodePtr nc2;
+  if(vid==0){
+    nc2 = xmlNewNode(ns_ows, BAD_CAST "Identifier");
+    xmlAddChild(nc2,xmlNewText(BAD_CAST identifier));
+    xmlAddChild(root,nc2);
+  }
+  map* tmp=amap;
+  const char *tmp2[2];
+  tmp2[0]="Title";
+  tmp2[1]="Abstract";
+  int j=0;
+  for(j=0;j<2;j++){
+    map* tmp1=getMap(tmp,tmp2[j]);
+    if(tmp1!=NULL){
+      nc2 = xmlNewNode(ns_ows, BAD_CAST tmp2[j]);
+      xmlAddChild(nc2,xmlNewText(BAD_CAST _ss(tmp1->value)));
+      xmlAddChild(root,nc2);
+    }
+  }
+  if(vid==1){
+    nc2 = xmlNewNode(ns_ows, BAD_CAST "Identifier");
+    xmlAddChild(nc2,xmlNewText(BAD_CAST identifier));
+    xmlAddChild(root,nc2);
+  }
+}
+
+/**
+ * Print an OWS ExceptionReport Document and HTTP headers (when required) 
+ * depending on the code.
+ * Set hasPrinted value to true in the [lenv] section.
+ * 
+ * @param m the maps containing the settings of the main.cfg file
+ * @param s the map containing the text,code,locator keys
+ */
+void printExceptionReportResponse(maps* m,map* s){
+  if(getMapFromMaps(m,"lenv","hasPrinted")!=NULL)
+    return;
+  int buffersize;
+  xmlDocPtr doc;
+  xmlChar *xmlbuff;
+  xmlNodePtr n;
+
+  zooXmlCleanupNs();
+  doc = xmlNewDoc(BAD_CAST "1.0");
+  maps* tmpMap=getMaps(m,"main");
+  char *encoding=getEncoding(tmpMap);
+  const char *exceptionCode;
+  
+  map* tmp=getMap(s,"code");
+  if(tmp!=NULL){
+    if(strcmp(tmp->value,"OperationNotSupported")==0 ||
+       strcmp(tmp->value,"NoApplicableCode")==0)
+      exceptionCode="501 Not Implemented";
+    else
+      if(strcmp(tmp->value,"MissingParameterValue")==0 ||
+	 strcmp(tmp->value,"InvalidUpdateSequence")==0 ||
+	 strcmp(tmp->value,"OptionNotSupported")==0 ||
+	 strcmp(tmp->value,"VersionNegotiationFailed")==0 ||
+	 strcmp(tmp->value,"InvalidParameterValue")==0)
+	exceptionCode="400 Bad request";
+      else
+	exceptionCode="501 Internal Server Error";
+  }
+  else
+    exceptionCode="501 Internal Server Error";
+
+  if(m!=NULL){
+    map *tmpSid=getMapFromMaps(m,"lenv","sid");
+    if(tmpSid!=NULL){
+      if( getpid()==atoi(tmpSid->value) ){
+	printHeaders(m);
+	printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode);
+      }
+    }
+    else{
+      printHeaders(m);
+      printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode);
+    }
+  }else{
+    printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode);
+  }
+  n=createExceptionReportNode(m,s,1);
+  xmlDocSetRootElement(doc, n);
+  xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);
+  printf("%s",xmlbuff);
+  fflush(stdout);
+  xmlFreeDoc(doc);
+  xmlFree(xmlbuff);
+  xmlCleanupParser();
+  zooXmlCleanupNs();
+  if(m!=NULL)
+    setMapInMaps(m,"lenv","hasPrinted","true");
+}
+
+/**
+ * Create an OWS ExceptionReport Node.
+ * 
+ * @param m the conf maps
+ * @param s the map containing the text,code,locator keys
+ * @param use_ns (0/1) choose if you want to generate an ExceptionReport or 
+ *  ows:ExceptionReport node respectively
+ * @return the ExceptionReport/ows:ExceptionReport node
+ */
+xmlNodePtr createExceptionReportNode(maps* m,map* s,int use_ns){
+  
+  xmlNsPtr ns,ns_xsi;
+  xmlNodePtr n,nc,nc1;
+
+  int nsid=zooXmlAddNs(NULL,"http://www.opengis.net/ows","ows");
+  ns=usedNs[nsid];
+  if(use_ns==0){
+    ns=NULL;
+  }
+  n = xmlNewNode(ns, BAD_CAST "ExceptionReport");
+  if(use_ns==1){
+    xmlNewNs(n,BAD_CAST "http://www.opengis.net/ows/1.1",BAD_CAST"ows");
+    int xsiId=zooXmlAddNs(n,"http://www.w3.org/2001/XMLSchema-instance","xsi");
+    ns_xsi=usedNs[xsiId];
+    xmlNewNsProp(n,ns_xsi,BAD_CAST "schemaLocation",BAD_CAST "http://www.opengis.net/ows/1.1 http://schemas.opengis.net/ows/1.1.0/owsExceptionReport.xsd");
+  }
+
+
+  addLangAttr(n,m);
+  xmlNewProp(n,BAD_CAST "version",BAD_CAST "1.1.0");
+  
+  int length=1;
+  int cnt=0;
+  map* len=getMap(s,"length");
+  if(len!=NULL)
+    length=atoi(len->value);
+  for(cnt=0;cnt<length;cnt++){
+    nc = xmlNewNode(ns, BAD_CAST "Exception");
+    
+    map* tmp=getMapArray(s,"code",cnt);
+    if(tmp==NULL)
+      tmp=getMap(s,"code");
+    if(tmp!=NULL)
+      xmlNewProp(nc,BAD_CAST "exceptionCode",BAD_CAST tmp->value);
+    else
+      xmlNewProp(nc,BAD_CAST "exceptionCode",BAD_CAST "NoApplicableCode");
+    
+    tmp=getMapArray(s,"locator",cnt);
+    if(tmp==NULL)
+      tmp=getMap(s,"locator");
+    if(tmp!=NULL && strcasecmp(tmp->value,"NULL")!=0)
+      xmlNewProp(nc,BAD_CAST "locator",BAD_CAST tmp->value);
+
+    tmp=getMapArray(s,"text",cnt);
+    nc1 = xmlNewNode(ns, BAD_CAST "ExceptionText");
+    if(tmp!=NULL){
+      xmlNodePtr txt=xmlNewText(BAD_CAST tmp->value);
+      xmlAddChild(nc1,txt);
+    }
+    else{
+      xmlNodeSetContent(nc1, BAD_CAST _("No debug message available"));
+    }
+    xmlAddChild(nc,nc1);
+    xmlAddChild(n,nc);
+  }
+  return n;
+}
+
+/**
+ * Print an OWS ExceptionReport.
+ * 
+ * @param m the conf maps
+ * @param message the error message 
+ * @param errorcode the error code
+ * @param locator the potential locator
+ */
+int errorException(maps *m, const char *message, const char *errorcode, const char *locator) 
+{
+  map* errormap = createMap("text", message);
+  addToMap(errormap,"code", errorcode);
+  if(locator!=NULL)
+    addToMap(errormap,"locator", locator);
+  else
+    addToMap(errormap,"locator", "NULL");
+  printExceptionReportResponse(m,errormap);
+  freeMap(&errormap);
+  free(errormap);
+  return -1;
+}
+
+/**
+ * Generate the output response (RawDataOutput or ResponseDocument)
+ *
+ * @param s the service structure containing the metadata informations
+ * @param request_inputs the inputs provided to the service for execution
+ * @param request_outputs the outputs updated by the service execution
+ * @param request_inputs1 the map containing the HTTP request
+ * @param cpid the process identifier attached to a service execution
+ * @param m the conf maps containing the main.cfg settings
+ * @param res the value returned by the service execution
+ */
+void outputResponse(service* s,maps* request_inputs,maps* request_outputs,
+		    map* request_inputs1,int cpid,maps* m,int res){
+#ifdef DEBUG
+  dumpMaps(request_inputs);
+  dumpMaps(request_outputs);
+  fprintf(stderr,"printProcessResponse\n");
+#endif
+  map* toto=getMap(request_inputs1,"RawDataOutput");
+  int asRaw=0;
+  if(toto!=NULL)
+    asRaw=1;
+  
+  maps* tmpSess=getMaps(m,"senv");
+  if(tmpSess!=NULL){
+    map *_tmp=getMapFromMaps(m,"lenv","cookie");
+    char* sessId=NULL;
+    if(_tmp!=NULL){
+      printf("Set-Cookie: %s; HttpOnly\r\n",_tmp->value);
+      printf("P3P: CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"\r\n");
+      char session_file_path[100];
+      char *tmp1=strtok(_tmp->value,";");
+      if(tmp1!=NULL)
+	sprintf(session_file_path,"%s",strstr(tmp1,"=")+1);
+      else
+	sprintf(session_file_path,"%s",strstr(_tmp->value,"=")+1);
+      sessId=strdup(session_file_path);
+    }else{
+      maps* t=getMaps(m,"senv");
+      map*p=t->content;
+      while(p!=NULL){
+	if(strstr(p->name,"ID")!=NULL){
+	  sessId=strdup(p->value);
+	  break;
+	}
+	p=p->next;
+      }
+    }
+    char session_file_path[1024];
+    map *tmpPath=getMapFromMaps(m,"main","sessPath");
+    if(tmpPath==NULL)
+      tmpPath=getMapFromMaps(m,"main","tmpPath");
+    sprintf(session_file_path,"%s/sess_%s.cfg",tmpPath->value,sessId);
+    FILE* teste=fopen(session_file_path,"w");
+    if(teste==NULL){
+      char tmpMsg[1024];
+      sprintf(tmpMsg,_("Unable to create the file \"%s\" for storing the session maps."),session_file_path);
+      errorException(m,tmpMsg,"InternalError",NULL);
+
+      return;
+    }
+    else{
+      fclose(teste);
+      dumpMapsToFile(tmpSess,session_file_path);
+    }
+  }
+  
+  if(res==SERVICE_FAILED){
+    map *lenv;
+    lenv=getMapFromMaps(m,"lenv","message");
+    char *tmp0;
+    if(lenv!=NULL){
+      tmp0=(char*)malloc((strlen(lenv->value)+strlen(_("Unable to run the Service. The message returned back by the Service was the following: "))+1)*sizeof(char));
+      sprintf(tmp0,_("Unable to run the Service. The message returned back by the Service was the following: %s"),lenv->value);
+    }
+    else{
+      tmp0=(char*)malloc((strlen(_("Unable to run the Service. No more information was returned back by the Service."))+1)*sizeof(char));
+      sprintf(tmp0,"%s",_("Unable to run the Service. No more information was returned back by the Service."));
+    }
+    errorException(m,tmp0,"InternalError",NULL);
+    free(tmp0);
+    return;
+  }
+
+
+  map *tmp1=getMapFromMaps(m,"main","tmpPath");
+  if(asRaw==0){
+#ifdef DEBUG
+    fprintf(stderr,"REQUEST_OUTPUTS FINAL\n");
+    dumpMaps(request_outputs);
+#endif
+    maps* tmpI=request_outputs;
+
+    while(tmpI!=NULL){
+#ifdef USE_MS
+      map* testMap=getMap(tmpI->content,"useMapserver");	
+#endif
+      map *gfile=getMap(tmpI->content,"generated_file");
+      char *file_name;
+      if(gfile!=NULL){
+	gfile=getMap(tmpI->content,"expected_generated_file");
+	if(gfile==NULL){
+	  gfile=getMap(tmpI->content,"generated_file");
+	}
+	readGeneratedFile(m,tmpI->content,gfile->value);	    
+	file_name=(char*)malloc((strlen(gfile->value)+strlen(tmp1->value)+1)*sizeof(char));
+	for(int i=0;i<strlen(gfile->value);i++)
+	  file_name[i]=gfile->value[i+strlen(tmp1->value)];
+      }
+
+      toto=getMap(tmpI->content,"asReference");
+#ifdef USE_MS
+      if(toto!=NULL && strcasecmp(toto->value,"true")==0 && testMap==NULL)
+#else
+      if(toto!=NULL && strcasecmp(toto->value,"true")==0)
+#endif
+	{
+	  elements* in=getElements(s->outputs,tmpI->name);
+	  char *format=NULL;
+	  if(in!=NULL){
+	    format=strdup(in->format);
+	  }else
+	    format=strdup("LiteralData");
+	  if(strcasecmp(format,"BoundingBoxData")==0){
+	    addToMap(tmpI->content,"extension","xml");
+	    addToMap(tmpI->content,"mimeType","text/xml");
+	    addToMap(tmpI->content,"encoding","UTF-8");
+	    addToMap(tmpI->content,"schema","http://schemas.opengis.net/ows/1.1.0/owsCommon.xsd");
+	  }
+
+	  if(gfile==NULL){
+	    map *ext=getMap(tmpI->content,"extension");
+	    char *file_path;
+	    char file_ext[32];
+
+	    if( ext != NULL && ext->value != NULL) {
+	      strncpy(file_ext, ext->value, 32);
+	    }
+	    else {
+	      // Obtain default file extension (see mimetypes.h).	      
+	      // If the MIME type is not recognized, txt is used as the default extension
+	      map* mtype=getMap(tmpI->content,"mimeType");
+	      getFileExtension(mtype != NULL ? mtype->value : NULL, file_ext, 32);
+	    }
+		
+	    file_name=(char*)malloc((strlen(s->name)+strlen(file_ext)+strlen(tmpI->name)+1024)*sizeof(char));
+	    int cpid0=cpid+time(NULL);	    
+	    sprintf(file_name,"%s_%s_%i.%s",s->name,tmpI->name,cpid0,file_ext);
+	    file_path=(char*)malloc((strlen(tmp1->value)+strlen(file_name)+2)*sizeof(char));
+	    sprintf(file_path,"%s/%s",tmp1->value,file_name);
+    
+		FILE *ofile=fopen(file_path,"wb");
+	    if(ofile==NULL){
+	      char tmpMsg[1024];
+	      sprintf(tmpMsg,_("Unable to create the file \"%s\" for storing the %s final result."),file_name,tmpI->name);
+	      errorException(m,tmpMsg,"InternalError",NULL);
+	      free(file_name);
+	      free(file_path);
+	      return;
+	    }
+	    free(file_path);
+
+	    toto=getMap(tmpI->content,"value");
+	    if(strcasecmp(format,"BoundingBoxData")!=0){
+	      map* size=getMap(tmpI->content,"size");
+	      if(size!=NULL && toto!=NULL)
+		fwrite(toto->value,1,(atoi(size->value))*sizeof(char),ofile);
+	      else
+		if(toto!=NULL && toto->value!=NULL)
+		  fwrite(toto->value,1,strlen(toto->value)*sizeof(char),ofile);
+	    }else{
+	      printBoundingBoxDocument(m,tmpI,ofile);
+	    }
+	    fclose(ofile);
+
+	  }
+	  map *tmp2=getMapFromMaps(m,"main","tmpUrl");
+	  map *tmp3=getMapFromMaps(m,"main","serverAddress");
+	  char *file_url;
+	  if(strncasecmp(tmp2->value,"http://",7)==0 ||
+	     strncasecmp(tmp2->value,"https://",8)==0){
+	    file_url=(char*)malloc((strlen(tmp2->value)+strlen(file_name)+2)*sizeof(char));
+	    sprintf(file_url,"%s/%s",tmp2->value,file_name);
+	  }else{
+	    file_url=(char*)malloc((strlen(tmp3->value)+strlen(tmp2->value)+strlen(file_name)+3)*sizeof(char));
+	    sprintf(file_url,"%s/%s/%s",tmp3->value,tmp2->value,file_name);
+	  }
+	  addToMap(tmpI->content,"Reference",file_url);
+	  free(format);
+	  free(file_name);
+	  free(file_url);	
+	  
+	}
+#ifdef USE_MS
+      else{
+	if(testMap!=NULL){
+	  setReferenceUrl(m,tmpI);
+	}
+      }
+#endif
+      tmpI=tmpI->next;
+    }
+    map *r_inputs=getMap(s->content,"serviceProvider");
+#ifdef DEBUG
+    fprintf(stderr,"SERVICE : %s\n",r_inputs->value);
+    dumpMaps(m);
+#endif
+    printProcessResponse(m,request_inputs1,cpid,
+		//	 s,r_inputs->value,res,
+			 s, s->name,res,  // replace serviceProvider with serviceName in stored response file name
+			 request_inputs,
+			 request_outputs);
+  }
+  else{
+    /**
+     * We get the requested output or fallback to the first one if the 
+     * requested one is not present in the resulting outputs maps.
+     */
+    maps* tmpI=NULL;
+    map* tmpIV=getMap(request_inputs1,"RawDataOutput");
+    if(tmpIV!=NULL){
+      tmpI=getMaps(request_outputs,tmpIV->value);
+    }
+    if(tmpI==NULL)
+      tmpI=request_outputs;
+    elements* e=getElements(s->outputs,tmpI->name);
+    if(e!=NULL && strcasecmp(e->format,"BoundingBoxData")==0){
+      printBoundingBoxDocument(m,tmpI,NULL);
+    }else{
+      map *gfile=getMap(tmpI->content,"generated_file");
+      if(gfile!=NULL){
+	gfile=getMap(tmpI->content,"expected_generated_file");
+	if(gfile==NULL){
+	  gfile=getMap(tmpI->content,"generated_file");
+	}
+	readGeneratedFile(m,tmpI->content,gfile->value);
+      }
+      toto=getMap(tmpI->content,"value");
+      if(toto==NULL){
+	char tmpMsg[1024];
+	sprintf(tmpMsg,_("Wrong RawDataOutput parameter: unable to fetch any result for the given parameter name: \"%s\"."),tmpI->name);
+	errorException(m,tmpMsg,"InvalidParameterValue","RawDataOutput");
+	return;
+      }
+      map* fname=getMapFromMaps(tmpI,tmpI->name,"filename");
+      if(fname!=NULL)
+	printf("Content-Disposition: attachment; filename=\"%s\"\r\n",fname->value);
+      map* rs=getMapFromMaps(tmpI,tmpI->name,"size");
+      if(rs!=NULL)
+	printf("Content-Length: %s\r\n",rs->value);
+      printHeaders(m);
+      char mime[1024];
+      map* mi=getMap(tmpI->content,"mimeType");
+#ifdef DEBUG
+      fprintf(stderr,"SERVICE OUTPUTS\n");
+      dumpMaps(request_outputs);
+      fprintf(stderr,"SERVICE OUTPUTS\n");
+#endif
+      map* en=getMap(tmpI->content,"encoding");
+      if(mi!=NULL && en!=NULL)
+	sprintf(mime,
+		"Content-Type: %s; charset=%s\r\nStatus: 200 OK\r\n\r\n",
+		mi->value,en->value);
+      else
+	if(mi!=NULL)
+	  sprintf(mime,
+		  "Content-Type: %s; charset=UTF-8\r\nStatus: 200 OK\r\n\r\n",
+		  mi->value);
+	else
+	  sprintf(mime,"Content-Type: text/plain; charset=utf-8\r\nStatus: 200 OK\r\n\r\n");
+      printf("%s",mime);
+      if(rs!=NULL)
+	fwrite(toto->value,1,atoi(rs->value),stdout);
+      else
+	fwrite(toto->value,1,strlen(toto->value),stdout);
+#ifdef DEBUG
+      dumpMap(toto);
+#endif
+    }
+  }
+}
+
+/**
+ * Create required XML nodes for boundingbox and update the current XML node
+ *
+ * @param ns_ows the ows XML namespace
+ * @param n the XML node to update
+ * @param boundingbox the map containing the boundingbox definition
+ */
+void printBoundingBox(xmlNsPtr ns_ows,xmlNodePtr n,map* boundingbox){
+
+  xmlNodePtr lw=NULL,uc=NULL;
+
+  map* tmp=getMap(boundingbox,"value");
+
+  tmp=getMap(boundingbox,"lowerCorner");
+  if(tmp!=NULL){
+    lw=xmlNewNode(ns_ows,BAD_CAST "LowerCorner");
+    xmlAddChild(lw,xmlNewText(BAD_CAST tmp->value));
+  }
+
+  tmp=getMap(boundingbox,"upperCorner");
+  if(tmp!=NULL){
+    uc=xmlNewNode(ns_ows,BAD_CAST "UpperCorner");
+    xmlAddChild(uc,xmlNewText(BAD_CAST tmp->value));
+  }
+
+  tmp=getMap(boundingbox,"crs");
+  if(tmp!=NULL)
+    xmlNewProp(n,BAD_CAST "crs",BAD_CAST tmp->value);
+
+  tmp=getMap(boundingbox,"dimensions");
+  if(tmp!=NULL)
+    xmlNewProp(n,BAD_CAST "dimensions",BAD_CAST tmp->value);
+
+  xmlAddChild(n,lw);
+  xmlAddChild(n,uc);
+
+}
+
+/**
+ * Parse a BoundingBox string
+ *
+ * [OGC 06-121r3](http://portal.opengeospatial.org/files/?artifact_id=20040):
+ *  10.2 Bounding box
+ * 
+ *
+ * Value is provided as : lowerCorner,upperCorner,crs,dimension
+ * Exemple : 189000,834000,285000,962000,urn:ogc:def:crs:OGC:1.3:CRS84
+ *
+ * A map to store boundingbox informations should contain:
+ *  - lowerCorner : double,double (minimum within this bounding box)
+ *  - upperCorner : double,double (maximum within this bounding box)
+ *  - crs : URI (Reference to definition of the CRS)
+ *  - dimensions : int 
+ * 
+ * Note : support only 2D bounding box.
+ *
+ * @param value the char* containing the KVP bouding box
+ * @return a map containing all the bounding box keys
+ */
+map* parseBoundingBox(const char* value){
+  map *res=NULL;
+  if(value!=NULL){
+    char *cv,*cvp;
+    cv=strtok_r((char*) value,",",&cvp);
+    int cnt=0;
+    int icnt=0;
+    char *currentValue=NULL;
+    while(cv){
+      if(cnt<2)
+	if(currentValue!=NULL){
+	  char *finalValue=(char*)malloc((strlen(currentValue)+strlen(cv)+1)*sizeof(char));
+	  sprintf(finalValue,"%s%s",currentValue,cv);
+	  switch(cnt){
+	  case 0:
+	    res=createMap("lowerCorner",finalValue);
+	    break;
+	  case 1:
+	    addToMap(res,"upperCorner",finalValue);
+	    icnt=-1;
+	    break;
+	  }
+	  cnt++;
+	  free(currentValue);
+	  currentValue=NULL;
+	  free(finalValue);
+	}
+	else{
+	  currentValue=(char*)malloc((strlen(cv)+2)*sizeof(char));
+	  sprintf(currentValue,"%s ",cv);
+	}
+      else
+	if(cnt==2){
+	  addToMap(res,"crs",cv);
+	  cnt++;
+	}
+	else
+	  addToMap(res,"dimensions",cv);
+      icnt++;
+      cv=strtok_r(NULL,",",&cvp);
+    }
+  }
+  return res;
+}
+
+/**
+ * Print an ows:BoundingBox XML document
+ *
+ * @param m the maps containing the settings of the main.cfg file
+ * @param boundingbox the maps containing the boundingbox definition
+ * @param file the file to print the BoundingBox (if NULL then print on stdout)
+ * @see parseBoundingBox, printBoundingBox
+ */
+void printBoundingBoxDocument(maps* m,maps* boundingbox,FILE* file){
+  if(file==NULL)
+    rewind(stdout);
+  xmlNodePtr n;
+  xmlDocPtr doc;
+  xmlNsPtr ns_ows,ns_xsi;
+  xmlChar *xmlbuff;
+  int buffersize;
+  char *encoding=getEncoding(m);
+  map *tmp;
+  if(file==NULL){
+    int pid=0;
+    tmp=getMapFromMaps(m,"lenv","sid");
+    if(tmp!=NULL)
+      pid=atoi(tmp->value);
+    if(pid==getpid()){
+      printf("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding);
+    }
+    fflush(stdout);
+  }
+
+  doc = xmlNewDoc(BAD_CAST "1.0");
+  int owsId=zooXmlAddNs(NULL,"http://www.opengis.net/ows/1.1","ows");
+  ns_ows=usedNs[owsId];
+  n = xmlNewNode(ns_ows, BAD_CAST "BoundingBox");
+  xmlNewNs(n,BAD_CAST "http://www.opengis.net/ows/1.1",BAD_CAST "ows");
+  int xsiId=zooXmlAddNs(n,"http://www.w3.org/2001/XMLSchema-instance","xsi");
+  ns_xsi=usedNs[xsiId];
+  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");
+  map *tmp1=getMap(boundingbox->content,"value");
+  tmp=parseBoundingBox(tmp1->value);
+  printBoundingBox(ns_ows,n,tmp);
+  xmlDocSetRootElement(doc, n);
+
+  xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);
+  if(file==NULL)
+    printf("%s",xmlbuff);
+  else{
+    fprintf(file,"%s",xmlbuff);
+  }
+
+  if(tmp!=NULL){
+    freeMap(&tmp);
+    free(tmp);
+  }
+  xmlFree(xmlbuff);
+  xmlFreeDoc(doc);
+  xmlCleanupParser();
+  zooXmlCleanupNs();
+  
+}
+
Index: trunk/zoo-project/zoo-kernel/response_print.h
===================================================================
--- trunk/zoo-project/zoo-kernel/response_print.h	(revision 641)
+++ trunk/zoo-project/zoo-kernel/response_print.h	(revision 641)
@@ -0,0 +1,217 @@
+/*
+ * Author : Gérald FENOY
+ *
+ * Copyright (c) 2009-2013 GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef ZOO_RESPONSE_PRINT_H
+#define ZOO_RESPONSE_PRINT_H 1
+
+#pragma once 
+
+/**
+ * The default service url (overriden by serverAddress)
+ */
+#define DEFAULT_SERVICE_URL "http://www.zoo-project.org/"
+/**
+ * The time size
+ */
+#define TIME_SIZE 40
+
+#include <libintl.h>
+#include <locale.h>
+/**
+ * ZOO-Kernel internal messages translation function
+ */
+#define _(String) dgettext ("zoo-kernel",String)
+/**
+ * ZOO-Services messages translation function
+ */
+#define _ss(String) dgettext ("zoo-services",String)
+
+/**
+ * ZOO-Kernel was unable to create a lock
+ */
+#define ZOO_LOCK_CREATE_FAILED -4
+/**
+ * ZOO-Kernel was unable to acquire a lock
+ */
+#define ZOO_LOCK_ACQUIRE_FAILED -5
+/**
+ * ZOO-Kernel was unable to release a lock
+ */
+#define ZOO_LOCK_RELEASE_FAILED -6
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include "cgic.h"
+#ifndef WIN32
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/sem.h>
+#else
+#include <direct.h>
+#endif
+#include <stdio.h>
+#include <time.h>
+#include <ctype.h>
+#ifdef WIN32
+#ifndef USE_RUBY
+#include <unistd.h>
+#endif
+#endif
+#ifndef WIN32
+#include <xlocale.h>
+#endif
+#include "ulinet.h"
+
+#include "service.h"
+#include <openssl/sha.h>
+#include <openssl/md5.h>
+#include <openssl/hmac.h>
+#include <openssl/evp.h>
+#include <openssl/bio.h>
+#include <openssl/buffer.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <libxml/parser.h>
+#include <libxml/xpath.h>
+
+  /**
+   * Maximum number of XML namespaces
+   */
+#define ZOO_NS_MAX 10
+  /**
+   * Maximum number of XML docs
+   */
+#define ZOO_DOC_MAX 20
+
+  /**
+   * Global char* to store the serverAddress value of the [main] section
+   */
+  static char* SERVICE_URL;
+
+  /**
+   * Array of xmlNsPtr storing all used XML namespace
+   */
+  static xmlNsPtr usedNs[ZOO_NS_MAX];
+  /**
+   * Array storing names of the used XML namespace
+   */
+  static char* nsName[ZOO_NS_MAX];
+  /**
+   * Number of XML namespaces
+   */
+  static int nbNs=0;
+  /**
+   * Array of xmlDocPtr storing XML docs
+   */
+  static xmlDocPtr iDocs[ZOO_DOC_MAX];
+  /**
+   * Number of XML docs
+   */
+  static int nbDocs=0;
+
+  /**
+   * Definitions of schemas depending on the WPS version
+   */
+  static const char* schemas[2][5]={
+    {"1.0.0","http://www.opengis.net/ows/1.1","http://www.opengis.net/wps/1.0.0","http://schemas.opengis.net/wps/1.0.0","%s %s/wps%s_response.xsd"},
+    {"2.0.0","http://www.opengis.net/ows/2.0","http://www.opengis.net/wps/2.0","http://schemas.opengis.net/wps/2.0","%s %s/wps%s.xsd"},
+  };
+  /**
+   * Definitions of support requests (depending on the WPS version)
+   */
+  static int nbSupportedRequests=7;
+  /**
+   * Definitions of requests depending on the WPS version
+   */
+  static const char* requests[2][7]={
+    {"GetCapabilities","DescribeProcess","Execute",NULL},
+    {"GetCapabilities","DescribeProcess","Execute","GetStatus","GetResult","Dismiss",NULL},
+  };
+  /**
+   * Definitions of root node for response depending on the request and the WPS version
+   */
+  static const char* root_nodes[2][6]={
+    {"ProcessOfferings","ProcessDescriptions",NULL},
+    {"Contents","ProcessOfferings",NULL}
+  };
+
+  /**
+   * Name and corresponding attributes depending on the WPS version
+   */
+  static const char* capabilities[2][7]={
+    {
+      "Process",
+      "processVersion","1",
+      "storeSupported","true",
+      "statusSupported","true"
+    },
+    {
+      "ProcessSummary",
+      "processVersion","1.0.0",
+      "jobControlOptions","sync-execute async-execute dismiss",
+      "outputTransmission","value reference"
+    }
+  };
+
+  void addLangAttr(xmlNodePtr,maps*);
+
+  void printHeaders(maps*);
+
+  int zooXmlSearchForNs(const char*);
+  int zooXmlAddNs(xmlNodePtr,const char*,const char*);
+  void zooXmlCleanupNs();
+
+  int zooXmlAddDoc(xmlNodePtr,const char*,const char*);
+  void zooXmlCleanupDocs();
+  
+  void printExceptionReportResponse(maps*,map*);
+  xmlNodePtr createExceptionReportNode(maps*,map*,int);
+  void printProcessResponse(maps*,map*,int,service*,const char*,int,maps*,maps*);
+  xmlNodePtr printWPSHeader(xmlDocPtr,maps*,const char*,const char*,const char*,int);
+  xmlNodePtr printGetCapabilitiesHeader(xmlDocPtr,maps*,const char*);
+  void printGetCapabilitiesForProcess(maps*,xmlNodePtr,service*);
+  void printDescribeProcessForProcess(maps*,xmlNodePtr,service*);
+  void printFullDescription(int,elements*,const char*,xmlNsPtr,xmlNsPtr,xmlNodePtr,int);
+  void printDocument(maps*,xmlDocPtr,int);
+  void printDescription(xmlNodePtr,xmlNsPtr,const char*,map*,int);
+  void printIOType(xmlDocPtr,xmlNodePtr,xmlNsPtr,xmlNsPtr,xmlNsPtr,elements*,maps*,const char*);
+  map* parseBoundingBox(const char*);
+  void printBoundingBox(xmlNsPtr,xmlNodePtr,map*);
+  void printBoundingBoxDocument(maps*,maps*,FILE*);
+  void printOutputDefinitions(xmlDocPtr,xmlNodePtr,xmlNsPtr,xmlNsPtr,elements*,maps*,const char*);
+
+  void outputResponse(service*,maps*,maps*,map*,int,maps*,int);
+
+  int errorException(maps *, const char *, const char *, const char*);
+
+  xmlNodePtr soapEnvelope(maps*,xmlNodePtr);
+  int checkForSoapEnvelope(xmlDocPtr);
+  
+#ifdef __cplusplus
+}
+#endif
+
+#endif
