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

Last change on this file since 929 was 929, checked in by djay, 5 years ago

Fix issue with LiteralDataDomain? definition from DescribeProcess? version 2

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

Search

ZOO Sponsors

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

Become a sponsor !

Knowledge partners

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

Become a knowledge partner

Related links

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