source: branches/PublicaMundi_David-devel/zoo-project/zoo-kernel/service_internal.c @ 549

Last change on this file since 549 was 549, checked in by david, 9 years ago
  • Adding Process Management
  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc
File size: 122.0 KB
Line 
1/**
2 * Author : Gérald FENOY
3 *
4 * Copyright (c) 2009-2013 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#include "service_internal.h"
26#ifdef USE_MS
27#include "service_internal_ms.h"
28#else
29#include "cpl_vsi.h"
30#endif
31
32#ifndef TRUE
33#define TRUE 1
34#endif
35#ifndef FALSE
36#define FALSE -1
37#endif
38
39int
40isValidLang (maps * conf, const char *str)
41{
42  map *tmpMap = getMapFromMaps (conf, "main", "lang");
43  char *tmp = zStrdup (tmpMap->value);
44  char *pToken = strtok (tmp, ",");
45  int res = -1;
46  while (pToken != NULL)
47    {
48      if (strcasecmp (str, pToken) == 0)
49        {
50          res = 1;
51          break;
52        }
53      pToken = strtok (NULL, ",");
54    }
55  free (tmp);
56  return res;
57}
58
59void
60printHeaders (maps * m,FCGX_Stream *out)
61{
62  maps *_tmp = getMaps (m, "headers");
63  if (_tmp != NULL)
64    {
65      map *_tmp1 = _tmp->content;
66      while (_tmp1 != NULL)
67        {
68          FCGX_FPrintF(out,"%s: %s\r\n", _tmp1->name, _tmp1->value);
69          //printf ("%s: %s\r\n", _tmp1->name, _tmp1->value);
70          _tmp1 = _tmp1->next;
71        }
72    }
73}
74
75void
76addLangAttr (xmlNodePtr n, maps * m)
77{
78  map *tmpLmap = getMapFromMaps (m, "main", "language");
79  if (tmpLmap != NULL)
80    xmlNewProp (n, BAD_CAST "xml:lang", BAD_CAST tmpLmap->value);
81  else
82    xmlNewProp (n, BAD_CAST "xml:lang", BAD_CAST "en-US");
83}
84
85/* Converts a hex character to its integer value */
86char
87from_hex (char ch)
88{
89  return isdigit (ch) ? ch - '0' : tolower (ch) - 'a' + 10;
90}
91
92/* Converts an integer value to its hex character*/
93char
94to_hex (char code)
95{
96  static char hex[] = "0123456789abcdef";
97  return hex[code & 15];
98}
99
100#ifdef WIN32
101
102#include <windows.h>
103//#include <fcgi_stdio.h>
104#include <stdio.h>
105#include <conio.h>
106#include <tchar.h>
107
108#define SHMEMSIZE 4096
109
110static LPVOID lpvMemG = NULL;   // pointer to shared memory
111static HANDLE hMapObjectG = NULL;       // handle to file mapping
112
113int
114_updateStatus (maps * conf)
115{
116  LPWSTR lpszTmp;
117  BOOL fInit;
118  char *final_string = NULL;
119  char *s = NULL;
120  map *tmpMap1;
121  map *tmpMap = getMapFromMaps (conf, "lenv", "sid");
122  if (hMapObjectG == NULL)
123    hMapObjectG = CreateFileMapping (INVALID_HANDLE_VALUE,      // use paging file
124                                     NULL,      // default security attributes
125                                     PAGE_READWRITE,    // read/write access
126                                     0, // size: high 32-bits
127                                     SHMEMSIZE, // size: low 32-bits
128                                     TEXT (tmpMap->value));     // name of map object
129  if (hMapObjectG == NULL)
130    {
131      fprintf (stderr, "Unable to create share memory segment %s !! \n",
132               tmpMap->value);
133      return -2;
134    }
135  fInit = (GetLastError () != ERROR_ALREADY_EXISTS);
136  if (lpvMemG == NULL)
137    lpvMemG = MapViewOfFile (hMapObjectG,       // object to map view of
138                             FILE_MAP_WRITE,    // read/write access
139                             0, // high offset:  map from
140                             0, // low offset:   beginning
141                             0);        // default: map entire file
142  if (lpvMemG == NULL)
143    {
144      fprintf (stderr,
145               "Unable to create or access the shared memory segment %s !! \n",
146               tmpMap->value);
147      return -1;
148    }
149  memset (lpvMemG, '\0', SHMEMSIZE);
150  tmpMap = getMapFromMaps (conf, "lenv", "status");
151  tmpMap1 = NULL;
152  tmpMap1 = getMapFromMaps (conf, "lenv", "message");
153  lpszTmp = (LPWSTR) lpvMemG;
154  final_string =
155    (char *) malloc ((strlen (tmpMap1->value) + strlen (tmpMap->value) + 2) *
156                     sizeof (char));
157  sprintf (final_string, "%s|%s", tmpMap->value, tmpMap1->value);
158  for (s = final_string; *s != '\0'; *s++)
159    {
160      *lpszTmp++ = *s;
161    }
162  *lpszTmp++ = '\0';
163  free (final_string);
164  return 0;
165}
166
167char *
168getStatus (int pid)
169{
170  char *lpszBuf = (char *) malloc (SHMEMSIZE * sizeof (char));
171  int i = 0;
172  LPWSTR lpszTmp = NULL;
173  LPVOID lpvMem = NULL;
174  HANDLE hMapObject = NULL;
175  BOOL fIgnore, fInit;
176  char tmp[100];
177  sprintf (tmp, "%i", pid);
178  if (hMapObject == NULL)
179    hMapObject = CreateFileMapping (INVALID_HANDLE_VALUE,       // use paging file
180                                    NULL,       // default security attributes
181                                    PAGE_READWRITE,     // read/write access
182                                    0,  // size: high 32-bits
183                                    4096,       // size: low 32-bits
184                                    TEXT (tmp));        // name of map object
185  if (hMapObject == NULL)
186    return FALSE;
187  if ((GetLastError () != ERROR_ALREADY_EXISTS))
188    {
189      fIgnore = UnmapViewOfFile (lpvMem);
190      fIgnore = CloseHandle (hMapObject);
191      return "-1";
192    }
193  fInit = TRUE;
194  if (lpvMem == NULL)
195    lpvMem = MapViewOfFile (hMapObject, // object to map view of
196                            FILE_MAP_READ,      // read/write access
197                            0,  // high offset:  map from
198                            0,  // low offset:   beginning
199                            0); // default: map entire file
200  if (lpvMem == NULL)
201    return "-1";
202  lpszTmp = (LPWSTR) lpvMem;
203  while (*lpszTmp)
204    {
205      lpszBuf[i] = (char) *lpszTmp;
206      *lpszTmp++;
207      lpszBuf[i + 1] = '\0';
208      i++;
209    }
210#ifdef DEBUG
211  fprintf (stderr, "READING STRING S %s\n", lpszBuf);
212#endif
213  return (char *) lpszBuf;
214}
215
216void
217unhandleStatus (maps * conf)
218{
219  BOOL fIgnore;
220  fIgnore = UnmapViewOfFile (lpvMemG);
221  fIgnore = CloseHandle (hMapObjectG);
222}
223#else
224
225void
226unhandleStatus (maps * conf)
227{
228  int shmid;
229  key_t key;
230  void *shm;
231  struct shmid_ds shmids;
232  map *tmpMap = getMapFromMaps (conf, "lenv", "sid");
233  if (tmpMap != NULL)
234    {
235      key = atoi (tmpMap->value);
236      if ((shmid = shmget (key, SHMSZ, IPC_CREAT | 0666)) < 0)
237        {
238#ifdef DEBUG
239          fprintf (stderr, "shmget failed to update value\n");
240#endif
241        }
242      else
243        {
244          if ((shm = shmat (shmid, NULL, 0)) == (char *) -1)
245            {
246#ifdef DEBUG
247              fprintf (stderr, "shmat failed to update value\n");
248#endif
249            }
250          else
251            {
252              shmdt (shm);
253              shmctl (shmid, IPC_RMID, &shmids);
254            }
255        }
256    }
257}
258
259int
260_updateStatus (maps * conf)
261{
262  int shmid;
263  key_t key;
264  char *shm, *s, *s1;
265  map *tmpMap = NULL;
266  tmpMap = getMapFromMaps (conf, "lenv", "sid");
267  if (tmpMap != NULL)
268    {
269      key = atoi (tmpMap->value);
270      if ((shmid = shmget (key, SHMSZ, IPC_CREAT | 0666)) < 0)
271        {
272#ifdef DEBUG
273          fprintf (stderr,
274                   "shmget failed to create new Shared memory segment\n");
275#endif
276          return -2;
277        }
278      else
279        {
280          if ((shm = (char *) shmat (shmid, NULL, 0)) == (char *) -1)
281            {
282#ifdef DEBUG
283              fprintf (stderr, "shmat failed to update value\n");
284#endif
285              return -1;
286            }
287          else
288            {
289              tmpMap = getMapFromMaps (conf, "lenv", "status");
290              s1 = shm;
291              for (s = tmpMap->value; *s != NULL && *s != 0; s++)
292                {
293                  *s1++ = *s;
294                }
295              *s1++ = '|';
296              tmpMap = getMapFromMaps (conf, "lenv", "message");
297              if (tmpMap != NULL)
298                for (s = tmpMap->value; *s != NULL && *s != 0; s++)
299                  {
300                    *s1++ = *s;
301                  }
302              *s1 = NULL;
303              shmdt ((void *) shm);
304            }
305        }
306    }
307  return 0;
308}
309
310char *
311getStatus (int pid)
312{
313  int shmid;
314  key_t key;
315  void *shm;
316  key = pid;
317  if ((shmid = shmget (key, SHMSZ, 0666)) < 0)
318    {
319#ifdef DEBUG
320      fprintf (stderr, "shmget failed in getStatus\n");
321#endif
322    }
323  else
324    {
325      if ((shm = shmat (shmid, NULL, 0)) == (char *) -1)
326        {
327#ifdef DEBUG
328          fprintf (stderr, "shmat failed in getStatus\n");
329#endif
330        }
331      else
332        {
333          return (char *) shm;
334        }
335    }
336  return (char *) "-1";
337}
338
339#endif
340
341#ifdef USE_JS
342
343JSBool
344JSUpdateStatus (JSContext * cx, uintN argc, jsval * argv1)
345{
346  jsval *argv = JS_ARGV (cx, argv1);
347  JS_MaybeGC (cx);
348  int istatus = 0;
349  char *status = NULL;
350  maps *conf;
351  if (argc > 2)
352    {
353#ifdef JS_DEBUG
354      fprintf (stderr, "Number of arguments used to call the function : %i",
355               argc);
356#endif
357      return JS_FALSE;
358    }
359  conf = mapsFromJSObject (cx, argv[0]);
360  if (JS_ValueToInt32 (cx, argv[1], &istatus) == JS_TRUE)
361    {
362      char tmpStatus[4];
363      sprintf (tmpStatus, "%i", istatus);
364      tmpStatus[3] = 0;
365      status = strdup (tmpStatus);
366    }
367  if (getMapFromMaps (conf, "lenv", "status") != NULL)
368    {
369      if (status != NULL)
370        {
371          setMapInMaps (conf, "lenv", "status", status);
372          free (status);
373        }
374      else
375        setMapInMaps (conf, "lenv", "status", "15");
376      _updateStatus (conf);
377    }
378  freeMaps (&conf);
379  free (conf);
380  JS_MaybeGC (cx);
381  return JS_TRUE;
382}
383
384#endif
385
386
387
388/* Returns a url-encoded version of str */
389/* IMPORTANT: be sure to free() the returned string after use */
390char *
391url_encode (char *str)
392{
393  char *pstr = str, *buf = (char *) malloc (strlen (str) * 3 + 1), *pbuf =
394    buf;
395  while (*pstr)
396    {
397      if (isalnum (*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.'
398          || *pstr == '~')
399        *pbuf++ = *pstr;
400      else if (*pstr == ' ')
401        *pbuf++ = '+';
402      else
403        *pbuf++ = '%', *pbuf++ = to_hex (*pstr >> 4), *pbuf++ =
404          to_hex (*pstr & 15);
405      pstr++;
406    }
407  *pbuf = '\0';
408  return buf;
409}
410
411/* Returns a url-decoded version of str */
412/* IMPORTANT: be sure to free() the returned string after use */
413char *
414url_decode (char *str)
415{
416  char *pstr = str, *buf = (char *) malloc (strlen (str) + 1), *pbuf = buf;
417  while (*pstr)
418    {
419      if (*pstr == '%')
420        {
421          if (pstr[1] && pstr[2])
422            {
423              *pbuf++ = from_hex (pstr[1]) << 4 | from_hex (pstr[2]);
424              pstr += 2;
425            }
426        }
427      else if (*pstr == '+')
428        {
429          *pbuf++ = ' ';
430        }
431      else
432        {
433          *pbuf++ = *pstr;
434        }
435      pstr++;
436    }
437  *pbuf = '\0';
438  return buf;
439}
440
441char *
442zCapitalize1 (char *tmp)
443{
444  char *res = strdup (tmp);
445  if (res[0] >= 97 && res[0] <= 122)
446    res[0] -= 32;
447  return res;
448}
449
450char *
451zCapitalize (char *tmp)
452{
453  int i = 0;
454  char *res = strdup (tmp);
455  for (i = 0; i < strlen (res); i++)
456    if (res[i] >= 97 && res[i] <= 122)
457      res[i] -= 32;
458  return res;
459}
460
461
462int
463zooXmlSearchForNs (const char *name)
464{
465  int i;
466  int res = -1;
467  for (i = 0; i < nbNs; i++)
468    if (strncasecmp (name, nsName[i], strlen (nsName[i])) == 0)
469      {
470        res = i;
471        break;
472      }
473  return res;
474}
475
476int
477zooXmlAddNs (xmlNodePtr nr, const char *url, const char *name)
478{
479#ifdef DEBUG
480  fprintf (stderr, "zooXmlAddNs %d %s \n", nbNs, name);
481#endif
482  int currId = -1;
483  if (nbNs == 0)
484    {
485      nbNs++;
486      currId = 0;
487      nsName[currId] = strdup (name);
488      usedNs[currId] = xmlNewNs (nr, BAD_CAST url, BAD_CAST name);
489    }
490  else
491    {
492      currId = zooXmlSearchForNs (name);
493      if (currId < 0)
494        {
495          nbNs++;
496          currId = nbNs - 1;
497          nsName[currId] = strdup (name);
498          usedNs[currId] = xmlNewNs (nr, BAD_CAST url, BAD_CAST name);
499        }
500    }
501  return currId;
502}
503
504void
505zooXmlCleanupNs ()
506{
507  int j;
508#ifdef DEBUG
509  fprintf (stderr, "zooXmlCleanup %d\n", nbNs);
510#endif
511  for (j = nbNs - 1; j >= 0; j--)
512    {
513#ifdef DEBUG
514      fprintf (stderr, "zooXmlCleanup %d\n", j);
515#endif
516      if (j == 0)
517        xmlFreeNs (usedNs[j]);
518      free (nsName[j]);
519      nbNs--;
520    }
521  nbNs = 0;
522}
523
524
525int
526zooXmlAddDoc (const char *value)
527{
528  int currId = 0;
529  nbDocs++;
530  currId = nbDocs - 1;
531  iDocs[currId] = xmlParseMemory (value, strlen (value));
532  return currId;
533}
534
535void
536zooXmlCleanupDocs ()
537{
538  int j;
539  for (j = nbDocs - 1; j >= 0; j--)
540    {
541      xmlFreeDoc (iDocs[j]);
542    }
543  nbDocs = 0;
544}
545
546
547xmlNodePtr
548soapEnvelope (maps * conf, xmlNodePtr n)
549{
550  map *soap = getMapFromMaps (conf, "main", "isSoap");
551  if (soap != NULL && strcasecmp (soap->value, "true") == 0)
552    {
553      int lNbNs = nbNs;
554      nsName[lNbNs] = strdup ("soap");
555      usedNs[lNbNs] =
556        xmlNewNs (NULL, BAD_CAST "http://www.w3.org/2003/05/soap-envelope",
557                  BAD_CAST "soap");
558      nbNs++;
559      xmlNodePtr nr = xmlNewNode (usedNs[lNbNs], BAD_CAST "Envelope");
560      nsName[nbNs] = strdup ("soap");
561      usedNs[nbNs] =
562        xmlNewNs (nr, BAD_CAST "http://www.w3.org/2003/05/soap-envelope",
563                  BAD_CAST "soap");
564      nbNs++;
565      nsName[nbNs] = strdup ("xsi");
566      usedNs[nbNs] =
567        xmlNewNs (nr, BAD_CAST "http://www.w3.org/2001/XMLSchema-instance",
568                  BAD_CAST "xsi");
569      nbNs++;
570      xmlNsPtr ns_xsi = usedNs[nbNs - 1];
571      xmlNewNsProp (nr, ns_xsi, BAD_CAST "schemaLocation",
572                    BAD_CAST
573                    "http://www.w3.org/2003/05/soap-envelope http://www.w3.org/2003/05/soap-envelope");
574      xmlNodePtr nr1 = xmlNewNode (usedNs[lNbNs], BAD_CAST "Body");
575      xmlAddChild (nr1, n);
576      xmlAddChild (nr, nr1);
577      return nr;
578    }
579  else
580    return n;
581}
582
583xmlNodePtr
584printGetCapabilitiesHeader (xmlDocPtr doc, const char *service, maps * m)
585{
586
587  xmlNsPtr ns, ns_ows, ns_xlink, ns_xsi;
588  xmlNodePtr n, nc, nc1, nc2, nc3, nc4, nc5, nc6;
589  /**
590   * Create the document and its temporary root.
591   */
592  int wpsId = zooXmlAddNs (NULL, "http://www.opengis.net/wps/1.0.0", "wps");
593  ns = usedNs[wpsId];
594  maps *toto1 = getMaps (m, "main");
595
596  n = xmlNewNode (ns, BAD_CAST "Capabilities");
597  int owsId = zooXmlAddNs (n, "http://www.opengis.net/ows/1.1", "ows");
598  ns_ows = usedNs[owsId];
599  xmlNewNs (n, BAD_CAST "http://www.opengis.net/wps/1.0.0", BAD_CAST "wps");
600  int xsiId =
601    zooXmlAddNs (n, "http://www.w3.org/2001/XMLSchema-instance", "xsi");
602  ns_xsi = usedNs[xsiId];
603  int xlinkId = zooXmlAddNs (n, "http://www.w3.org/1999/xlink", "xlink");
604  ns_xlink = usedNs[xlinkId];
605  xmlNewNsProp (n, ns_xsi, BAD_CAST "schemaLocation",
606                BAD_CAST
607                "http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsGetCapabilities_response.xsd");
608  xmlNewProp (n, BAD_CAST "service", BAD_CAST "WPS");
609  addLangAttr (n, m);
610
611  if (toto1 != NULL)
612    {
613      map *tmp = getMap (toto1->content, "version");
614      if (tmp != NULL)
615        {
616          xmlNewProp (n, BAD_CAST "version", BAD_CAST tmp->value);
617        }
618      else
619        xmlNewProp (n, BAD_CAST "version", BAD_CAST "1.0.0");
620    }
621  else
622    xmlNewProp (n, BAD_CAST "version", BAD_CAST "1.0.0");
623
624  char tmp[256];
625
626  nc = xmlNewNode (ns_ows, BAD_CAST "ServiceIdentification");
627  maps *tmp4 = getMaps (m, "identification");
628  if (tmp4 != NULL)
629    {
630      map *tmp2 = tmp4->content;
631      const char *orderedFields[5];
632      orderedFields[0] = "Title";
633      orderedFields[1] = "Abstract";
634      orderedFields[2] = "Keywords";
635      orderedFields[3] = "Fees";
636      orderedFields[4] = "AccessConstraints";
637      int oI = 0;
638      for (oI = 0; oI < 5; oI++)
639        if ((tmp2 = getMap (tmp4->content, orderedFields[oI])) != NULL)
640          {
641            if (strcasecmp (tmp2->name, "abstract") == 0 ||
642                strcasecmp (tmp2->name, "title") == 0 ||
643                strcasecmp (tmp2->name, "accessConstraints") == 0 ||
644                strcasecmp (tmp2->name, "fees") == 0)
645              {
646                tmp2->name[0] = toupper (tmp2->name[0]);
647                nc1 = xmlNewNode (ns_ows, BAD_CAST tmp2->name);
648                xmlAddChild (nc1, xmlNewText (BAD_CAST tmp2->value));
649                xmlAddChild (nc, nc1);
650              }
651            else if (strcmp (tmp2->name, "keywords") == 0)
652              {
653                nc1 = xmlNewNode (ns_ows, BAD_CAST "Keywords");
654                char *toto = tmp2->value;
655                char buff[256];
656                int i = 0;
657                int j = 0;
658                while (toto[i])
659                  {
660                    if (toto[i] != ',' && toto[i] != 0)
661                      {
662                        buff[j] = toto[i];
663                        buff[j + 1] = 0;
664                        j++;
665                      }
666                    else
667                      {
668                        nc2 = xmlNewNode (ns_ows, BAD_CAST "Keyword");
669                        xmlAddChild (nc2, xmlNewText (BAD_CAST buff));
670                        xmlAddChild (nc1, nc2);
671                        j = 0;
672                      }
673                    i++;
674                  }
675                if (strlen (buff) > 0)
676                  {
677                    nc2 = xmlNewNode (ns_ows, BAD_CAST "Keyword");
678                    xmlAddChild (nc2, xmlNewText (BAD_CAST buff));
679                    xmlAddChild (nc1, nc2);
680                  }
681                xmlAddChild (nc, nc1);
682                nc2 = xmlNewNode (ns_ows, BAD_CAST "ServiceType");
683                xmlAddChild (nc2, xmlNewText (BAD_CAST "WPS"));
684                xmlAddChild (nc, nc2);
685                nc2 = xmlNewNode (ns_ows, BAD_CAST "ServiceTypeVersion");
686                xmlAddChild (nc2, xmlNewText (BAD_CAST "1.0.0"));
687                xmlAddChild (nc, nc2);
688              }
689            tmp2 = tmp2->next;
690          }
691    }
692  else
693    {
694      fprintf (stderr, "TMP4 NOT FOUND !!");
695      return NULL;
696    }
697  xmlAddChild (n, nc);
698
699  nc = xmlNewNode (ns_ows, BAD_CAST "ServiceProvider");
700  nc3 = xmlNewNode (ns_ows, BAD_CAST "ServiceContact");
701  nc4 = xmlNewNode (ns_ows, BAD_CAST "ContactInfo");
702  nc5 = xmlNewNode (ns_ows, BAD_CAST "Phone");
703  nc6 = xmlNewNode (ns_ows, BAD_CAST "Address");
704  tmp4 = getMaps (m, "provider");
705  if (tmp4 != NULL)
706    {
707      map *tmp2 = tmp4->content;
708      const char *tmpAddress[6];
709      tmpAddress[0] = "addressDeliveryPoint";
710      tmpAddress[1] = "addressCity";
711      tmpAddress[2] = "addressAdministrativeArea";
712      tmpAddress[3] = "addressPostalCode";
713      tmpAddress[4] = "addressCountry";
714      tmpAddress[5] = "addressElectronicMailAddress";
715      const char *tmpPhone[2];
716      tmpPhone[0] = "phoneVoice";
717      tmpPhone[1] = "phoneFacsimile";
718      const char *orderedFields[12];
719      orderedFields[0] = "providerName";
720      orderedFields[1] = "providerSite";
721      orderedFields[2] = "individualName";
722      orderedFields[3] = "positionName";
723      orderedFields[4] = tmpPhone[0];
724      orderedFields[5] = tmpPhone[1];
725      orderedFields[6] = tmpAddress[0];
726      orderedFields[7] = tmpAddress[1];
727      orderedFields[8] = tmpAddress[2];
728      orderedFields[9] = tmpAddress[3];
729      orderedFields[10] = tmpAddress[4];
730      orderedFields[11] = tmpAddress[5];
731      int oI = 0;
732      for (oI = 0; oI < 12; oI++)
733        if ((tmp2 = getMap (tmp4->content, orderedFields[oI])) != NULL)
734          {
735            if (strcmp (tmp2->name, "keywords") != 0 &&
736                strcmp (tmp2->name, "serverAddress") != 0 &&
737                strcmp (tmp2->name, "lang") != 0)
738              {
739                tmp2->name[0] = toupper (tmp2->name[0]);
740                if (strcmp (tmp2->name, "ProviderName") == 0)
741                  {
742                    nc1 = xmlNewNode (ns_ows, BAD_CAST tmp2->name);
743                    xmlAddChild (nc1, xmlNewText (BAD_CAST tmp2->value));
744                    xmlAddChild (nc, nc1);
745                  }
746                else
747                  {
748                    if (strcmp (tmp2->name, "ProviderSite") == 0)
749                      {
750                        nc1 = xmlNewNode (ns_ows, BAD_CAST tmp2->name);
751                        xmlNewNsProp (nc1, ns_xlink, BAD_CAST "href",
752                                      BAD_CAST tmp2->value);
753                        xmlAddChild (nc, nc1);
754                      }
755                    else
756                      if (strcmp (tmp2->name, "IndividualName") == 0 ||
757                          strcmp (tmp2->name, "PositionName") == 0)
758                      {
759                        nc1 = xmlNewNode (ns_ows, BAD_CAST tmp2->name);
760                        xmlAddChild (nc1, xmlNewText (BAD_CAST tmp2->value));
761                        xmlAddChild (nc3, nc1);
762                      }
763                    else if (strncmp (tmp2->name, "Phone", 5) == 0)
764                      {
765                        int j;
766                        for (j = 0; j < 2; j++)
767                          if (strcasecmp (tmp2->name, tmpPhone[j]) == 0)
768                            {
769                              char *tmp4 = tmp2->name;
770                              nc1 = xmlNewNode (ns_ows, BAD_CAST tmp4 + 5);
771                              xmlAddChild (nc1,
772                                           xmlNewText (BAD_CAST tmp2->value));
773                              xmlAddChild (nc5, nc1);
774                            }
775                      }
776                    else if (strncmp (tmp2->name, "Address", 7) == 0)
777                      {
778                        int j;
779                        for (j = 0; j < 6; j++)
780                          if (strcasecmp (tmp2->name, tmpAddress[j]) == 0)
781                            {
782                              char *tmp4 = tmp2->name;
783                              nc1 = xmlNewNode (ns_ows, BAD_CAST tmp4 + 7);
784                              xmlAddChild (nc1,
785                                           xmlNewText (BAD_CAST tmp2->value));
786                              xmlAddChild (nc6, nc1);
787                            }
788                      }
789                  }
790              }
791            else if (strcmp (tmp2->name, "keywords") == 0)
792              {
793                nc1 = xmlNewNode (ns_ows, BAD_CAST "Keywords");
794                char *toto = tmp2->value;
795                char buff[256];
796                int i = 0;
797                int j = 0;
798                while (toto[i])
799                  {
800                    if (toto[i] != ',' && toto[i] != 0)
801                      {
802                        buff[j] = toto[i];
803                        buff[j + 1] = 0;
804                        j++;
805                      }
806                    else
807                      {
808                        nc2 = xmlNewNode (ns_ows, BAD_CAST "Keyword");
809                        xmlAddChild (nc2, xmlNewText (BAD_CAST buff));
810                        xmlAddChild (nc1, nc2);
811                        j = 0;
812                      }
813                    i++;
814                  }
815                if (strlen (buff) > 0)
816                  {
817                    nc2 = xmlNewNode (ns_ows, BAD_CAST "Keyword");
818                    xmlAddChild (nc2, xmlNewText (BAD_CAST buff));
819                    xmlAddChild (nc1, nc2);
820                  }
821                xmlAddChild (nc, nc1);
822              }
823            tmp2 = tmp2->next;
824          }
825    }
826  else
827    {
828      fprintf (stderr, "TMP4 NOT FOUND !!");
829    }
830  xmlAddChild (nc4, nc5);
831  xmlAddChild (nc4, nc6);
832  xmlAddChild (nc3, nc4);
833  xmlAddChild (nc, nc3);
834  xmlAddChild (n, nc);
835
836
837  nc = xmlNewNode (ns_ows, BAD_CAST "OperationsMetadata");
838  char *tmp2[3];
839  tmp2[0] = strdup ("GetCapabilities");
840  tmp2[1] = strdup ("DescribeProcess");
841  tmp2[2] = strdup ("Execute");
842  int j = 0;
843
844  if (toto1 != NULL)
845    {
846      map *tmp = getMap (toto1->content, "serverAddress");
847      if (tmp != NULL)
848        {
849          SERVICE_URL = strdup (tmp->value);
850        }
851      else
852        SERVICE_URL = strdup ("not_found");
853    }
854  else
855    SERVICE_URL = strdup ("not_found");
856
857  for (j = 0; j < 3; j++)
858    {
859      nc1 = xmlNewNode (ns_ows, BAD_CAST "Operation");
860      xmlNewProp (nc1, BAD_CAST "name", BAD_CAST tmp2[j]);
861      nc2 = xmlNewNode (ns_ows, BAD_CAST "DCP");
862      nc3 = xmlNewNode (ns_ows, BAD_CAST "HTTP");
863      nc4 = xmlNewNode (ns_ows, BAD_CAST "Get");
864      sprintf (tmp, "%s/%s", SERVICE_URL, service);
865      xmlNewNsProp (nc4, ns_xlink, BAD_CAST "href", BAD_CAST tmp);
866      xmlAddChild (nc3, nc4);
867      if (j > 0)
868        {
869          nc4 = xmlNewNode (ns_ows, BAD_CAST "Post");
870          xmlNewNsProp (nc4, ns_xlink, BAD_CAST "href", BAD_CAST tmp);
871          xmlAddChild (nc3, nc4);
872        }
873      xmlAddChild (nc2, nc3);
874      xmlAddChild (nc1, nc2);
875      xmlAddChild (nc, nc1);
876    }
877  for (j = 2; j >= 0; j--)
878    free (tmp2[j]);
879  xmlAddChild (n, nc);
880
881  nc = xmlNewNode (ns, BAD_CAST "ProcessOfferings");
882  xmlAddChild (n, nc);
883
884  nc1 = xmlNewNode (ns, BAD_CAST "Languages");
885  nc2 = xmlNewNode (ns, BAD_CAST "Default");
886  nc3 = xmlNewNode (ns, BAD_CAST "Supported");
887
888  toto1 = getMaps (m, "main");
889  if (toto1 != NULL)
890    {
891      map *tmp1 = getMap (toto1->content, "lang");
892      char *toto = tmp1->value;
893      char buff[256];
894      int i = 0;
895      int j = 0;
896      int dcount = 0;
897      while (toto[i])
898        {
899          if (toto[i] != ',' && toto[i] != 0)
900            {
901              buff[j] = toto[i];
902              buff[j + 1] = 0;
903              j++;
904            }
905          else
906            {
907              nc4 = xmlNewNode (ns_ows, BAD_CAST "Language");
908              xmlAddChild (nc4, xmlNewText (BAD_CAST buff));
909              if (dcount == 0)
910                {
911                  xmlAddChild (nc2, nc4);
912                  xmlAddChild (nc1, nc2);
913                  dcount++;
914                }
915              nc4 = xmlNewNode (ns_ows, BAD_CAST "Language");
916              xmlAddChild (nc4, xmlNewText (BAD_CAST buff));
917              xmlAddChild (nc3, nc4);
918              j = 0;
919              buff[j] = 0;
920            }
921          i++;
922        }
923      if (strlen (buff) > 0)
924        {
925          nc4 = xmlNewNode (ns_ows, BAD_CAST "Language");
926          xmlAddChild (nc4, xmlNewText (BAD_CAST buff));
927          xmlAddChild (nc3, nc4);
928        }
929    }
930  xmlAddChild (nc1, nc3);
931  xmlAddChild (n, nc1);
932
933  xmlNodePtr fn = soapEnvelope (m, n);
934  xmlDocSetRootElement (doc, fn);
935  //xmlFreeNs(ns);
936  free (SERVICE_URL);
937  return nc;
938}
939
940void
941addPrefix (maps * conf, map * level, service * serv)
942{
943  if (level != NULL)
944    {
945      char key[25];
946      char *prefix = NULL;
947      int clevel = atoi (level->value);
948      int cl = 0;
949      for (cl = 0; cl < clevel; cl++)
950        {
951          sprintf (key, "sprefix_%d", cl);
952          map *tmp2 = getMapFromMaps (conf, "lenv", key);
953          if (tmp2 != NULL)
954            {
955              if (prefix == NULL)
956                prefix = zStrdup (tmp2->value);
957              else
958                {
959                  int plen = strlen (prefix);
960                  prefix =
961                    (char *) realloc (prefix,
962                                      (plen + strlen (tmp2->value) +
963                                       2) * sizeof (char));
964                  memcpy (prefix + plen, tmp2->value,
965                          strlen (tmp2->value) * sizeof (char));
966                  prefix[plen + strlen (tmp2->value)] = 0;
967                }
968            }
969        }
970      if (prefix != NULL)
971        {
972          char *tmp0 = strdup (serv->name);
973          free (serv->name);
974          serv->name =
975            (char *) malloc ((strlen (prefix) + strlen (tmp0) + 1) *
976                             sizeof (char));
977          sprintf (serv->name, "%s%s", prefix, tmp0);
978          free (tmp0);
979          free (prefix);
980          prefix = NULL;
981        }
982    }
983}
984
985void
986printGetCapabilitiesForProcess (maps * m, xmlNodePtr nc, service * serv)
987{
988  xmlNsPtr ns, ns_ows, ns_xlink;
989  xmlNodePtr n = NULL, nc1, nc2;
990  /**
991   * Initialize or get existing namspaces
992   */
993  int wpsId = zooXmlAddNs (NULL, "http://www.opengis.net/wps/1.0.0", "wps");
994  ns = usedNs[wpsId];
995  int owsId = zooXmlAddNs (NULL, "http://www.opengis.net/ows/1.1", "ows");
996  ns_ows = usedNs[owsId];
997  int xlinkId = zooXmlAddNs (n, "http://www.w3.org/1999/xlink", "xlink");
998  ns_xlink = usedNs[xlinkId];
999
1000  map *tmp1;
1001  if (serv->content != NULL)
1002    {
1003      nc1 = xmlNewNode (ns, BAD_CAST "Process");
1004      tmp1 = getMap (serv->content, "processVersion");
1005      if (tmp1 != NULL)
1006        xmlNewNsProp (nc1, ns, BAD_CAST "processVersion",
1007                      BAD_CAST tmp1->value);
1008      map *tmp3 = getMapFromMaps (m, "lenv", "level");
1009      addPrefix (m, tmp3, serv);
1010      printDescription (nc1, ns_ows, serv->name, serv->content);
1011      tmp1 = serv->metadata;
1012      while (tmp1 != NULL)
1013        {
1014          nc2 = xmlNewNode (ns_ows, BAD_CAST "Metadata");
1015          xmlNewNsProp (nc2, ns_xlink, BAD_CAST tmp1->name,
1016                        BAD_CAST tmp1->value);
1017          xmlAddChild (nc1, nc2);
1018          tmp1 = tmp1->next;
1019        }
1020      xmlAddChild (nc, nc1);
1021    }
1022}
1023
1024xmlNodePtr
1025printDescribeProcessHeader (xmlDocPtr doc, const char *service, maps * m)
1026{
1027
1028  xmlNsPtr ns, ns_xsi;
1029  xmlNodePtr n;
1030
1031  int wpsId =
1032    zooXmlAddNs (NULL, "http://schemas.opengis.net/wps/1.0.0", "wps");
1033  ns = usedNs[wpsId];
1034  n = xmlNewNode (ns, BAD_CAST "ProcessDescriptions");
1035  zooXmlAddNs (n, "http://www.opengis.net/ows/1.1", "ows");
1036  xmlNewNs (n, BAD_CAST "http://www.opengis.net/wps/1.0.0", BAD_CAST "wps");
1037  zooXmlAddNs (n, "http://www.w3.org/1999/xlink", "xlink");
1038  int xsiId =
1039    zooXmlAddNs (n, "http://www.w3.org/2001/XMLSchema-instance", "xsi");
1040  ns_xsi = usedNs[xsiId];
1041
1042  xmlNewNsProp (n, ns_xsi, BAD_CAST "schemaLocation",
1043                BAD_CAST
1044                "http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsDescribeProcess_response.xsd");
1045  xmlNewProp (n, BAD_CAST "service", BAD_CAST "WPS");
1046  xmlNewProp (n, BAD_CAST "version", BAD_CAST "1.0.0");
1047  addLangAttr (n, m);
1048
1049  xmlNodePtr fn = soapEnvelope (m, n);
1050  xmlDocSetRootElement (doc, fn);
1051
1052  return n;
1053}
1054
1055void
1056printDescribeProcessForProcess (maps * m, xmlNodePtr nc, service * serv)
1057{
1058  xmlNsPtr ns, ns_ows, ns_xlink;
1059  xmlNodePtr n, nc1;
1060
1061  n = nc;
1062
1063  int wpsId =
1064    zooXmlAddNs (NULL, "http://schemas.opengis.net/wps/1.0.0", "wps");
1065  ns = usedNs[wpsId];
1066  int owsId = zooXmlAddNs (NULL, "http://www.opengis.net/ows/1.1", "ows");
1067  ns_ows = usedNs[owsId];
1068  int xlinkId = zooXmlAddNs (NULL, "http://www.w3.org/1999/xlink", "xlink");
1069  ns_xlink = usedNs[xlinkId];
1070
1071  nc = xmlNewNode (NULL, BAD_CAST "ProcessDescription");
1072  const char *tmp4[3];
1073  tmp4[0] = "processVersion";
1074  tmp4[1] = "storeSupported";
1075  tmp4[2] = "statusSupported";
1076  int j = 0;
1077  map *tmp1 = NULL;
1078  for (j = 0; j < 3; j++)
1079    {
1080      tmp1 = getMap (serv->content, tmp4[j]);
1081      if (tmp1 != NULL)
1082        {
1083          if (j == 0)
1084            xmlNewNsProp (nc, ns, BAD_CAST "processVersion",
1085                          BAD_CAST tmp1->value);
1086          else
1087            xmlNewProp (nc, BAD_CAST tmp4[j], BAD_CAST tmp1->value);
1088        }
1089      else
1090        {
1091          if (j > 0)
1092            xmlNewProp (nc, BAD_CAST tmp4[j], BAD_CAST "false");
1093        }
1094    }
1095
1096  tmp1 = getMapFromMaps (m, "lenv", "level");
1097  addPrefix (m, tmp1, serv);
1098  printDescription (nc, ns_ows, serv->identifier, serv->content);
1099
1100  tmp1 = serv->metadata;
1101  while (tmp1 != NULL)
1102    {
1103      nc1 = xmlNewNode (ns_ows, BAD_CAST "Metadata");
1104      xmlNewNsProp (nc1, ns_xlink, BAD_CAST tmp1->name, BAD_CAST tmp1->value);
1105      xmlAddChild (nc, nc1);
1106      tmp1 = tmp1->next;
1107    }
1108
1109  tmp1 = getMap (serv->content, "Profile");
1110  if (tmp1 != NULL)
1111    {
1112      nc1 = xmlNewNode (ns, BAD_CAST "Profile");
1113      xmlAddChild (nc1, xmlNewText (BAD_CAST tmp1->value));
1114      xmlAddChild (nc, nc1);
1115    }
1116
1117  if (serv->inputs != NULL)
1118    {
1119      nc1 = xmlNewNode (NULL, BAD_CAST "DataInputs");
1120      elements *e = serv->inputs;
1121      printFullDescription (1, e, "Input", ns_ows, nc1);
1122      xmlAddChild (nc, nc1);
1123    }
1124
1125  nc1 = xmlNewNode (NULL, BAD_CAST "ProcessOutputs");
1126  elements *e = serv->outputs;
1127  printFullDescription (0, e, "Output", ns_ows, nc1);
1128  xmlAddChild (nc, nc1);
1129
1130  xmlAddChild (n, nc);
1131
1132}
1133
1134void
1135printFullDescription (int in, elements * elem, const char *type,
1136                      xmlNsPtr ns_ows, xmlNodePtr nc1)
1137{
1138  const char *orderedFields[13];
1139  orderedFields[0] = "mimeType";
1140  orderedFields[1] = "encoding";
1141  orderedFields[2] = "schema";
1142  orderedFields[3] = "dataType";
1143  orderedFields[4] = "uom";
1144  orderedFields[5] = "CRS";
1145  orderedFields[6] = "value";
1146  orderedFields[7] = "AllowedValues";
1147  orderedFields[8] = "range";
1148  orderedFields[9] = "rangeMin";
1149  orderedFields[10] = "rangeMax";
1150  orderedFields[11] = "rangeClosure";
1151  orderedFields[12] = "rangeSpace";
1152
1153  xmlNodePtr nc2, nc3, nc4, nc5, nc6, nc7, nc8, nc9;
1154  elements *e = elem;
1155
1156  map *tmp1 = NULL;
1157  while (e != NULL)
1158    {
1159      int default1 = 0;
1160      int isAnyValue = 1;
1161      nc2 = xmlNewNode (NULL, BAD_CAST type);
1162      if (strncmp (type, "Input", 5) == 0)
1163        {
1164          tmp1 = getMap (e->content, "minOccurs");
1165          if (tmp1 != NULL)
1166            {
1167              xmlNewProp (nc2, BAD_CAST tmp1->name, BAD_CAST tmp1->value);
1168            }
1169          else
1170            xmlNewProp (nc2, BAD_CAST "minOccurs", BAD_CAST "0");
1171          tmp1 = getMap (e->content, "maxOccurs");
1172          if (tmp1 != NULL)
1173            {
1174              if (strcasecmp (tmp1->value, "unbounded") != 0)
1175                xmlNewProp (nc2, BAD_CAST tmp1->name, BAD_CAST tmp1->value);
1176              else
1177                xmlNewProp (nc2, BAD_CAST "maxOccurs", BAD_CAST "1000");
1178            }
1179          else
1180            xmlNewProp (nc2, BAD_CAST "maxOccurs", BAD_CAST "1");
1181          if ((tmp1 = getMap (e->content, "maximumMegabytes")) != NULL)
1182            {
1183              xmlNewProp (nc2, BAD_CAST "maximumMegabytes",
1184                          BAD_CAST tmp1->value);
1185            }
1186        }
1187
1188      printDescription (nc2, ns_ows, e->name, e->content);
1189
1190    /**
1191     * Build the (Literal/Complex/BoundingBox)Data node
1192     */
1193      if (strncmp (type, "Output", 6) == 0)
1194        {
1195          if (strncasecmp (e->format, "LITERALDATA", strlen (e->format)) == 0)
1196            nc3 = xmlNewNode (NULL, BAD_CAST "LiteralOutput");
1197          else if (strncasecmp (e->format, "COMPLEXDATA", strlen (e->format))
1198                   == 0)
1199            nc3 = xmlNewNode (NULL, BAD_CAST "ComplexOutput");
1200          else
1201            if (strncasecmp (e->format, "BOUNDINGBOXDATA", strlen (e->format))
1202                == 0)
1203            nc3 = xmlNewNode (NULL, BAD_CAST "BoundingBoxOutput");
1204          else
1205            nc3 = xmlNewNode (NULL, BAD_CAST e->format);
1206        }
1207      else
1208        {
1209          if (strncasecmp (e->format, "LITERALDATA", strlen (e->format)) == 0)
1210            {
1211              nc3 = xmlNewNode (NULL, BAD_CAST "LiteralData");
1212            }
1213          else if (strncasecmp (e->format, "COMPLEXDATA", strlen (e->format))
1214                   == 0)
1215            nc3 = xmlNewNode (NULL, BAD_CAST "ComplexData");
1216          else
1217            if (strncasecmp (e->format, "BOUNDINGBOXDATA", strlen (e->format))
1218                == 0)
1219            nc3 = xmlNewNode (NULL, BAD_CAST "BoundingBoxData");
1220          else
1221            nc3 = xmlNewNode (NULL, BAD_CAST e->format);
1222        }
1223
1224      iotype *_tmp0 = NULL;
1225      iotype *_tmp = e->defaults;
1226      int datatype = 0;
1227      bool hasUOM = false;
1228      bool hasUOM1 = false;
1229      if (_tmp != NULL)
1230        {
1231          if (strcmp (e->format, "LiteralOutput") == 0 ||
1232              strcmp (e->format, "LiteralData") == 0)
1233            {
1234              datatype = 1;
1235              nc4 = xmlNewNode (NULL, BAD_CAST "UOMs");
1236              nc5 = xmlNewNode (NULL, BAD_CAST "Default");
1237            }
1238          else if (strcmp (e->format, "BoundingBoxOutput") == 0 ||
1239                   strcmp (e->format, "BoundingBoxData") == 0)
1240            {
1241              datatype = 2;
1242              nc5 = xmlNewNode (NULL, BAD_CAST "Default");
1243            }
1244          else
1245            {
1246              nc4 = xmlNewNode (NULL, BAD_CAST "Default");
1247              nc5 = xmlNewNode (NULL, BAD_CAST "Format");
1248            }
1249
1250          tmp1 = _tmp->content;
1251
1252          if ((tmp1 = getMap (_tmp->content, "DataType")) != NULL)
1253            {
1254              nc8 = xmlNewNode (ns_ows, BAD_CAST "DataType");
1255              xmlAddChild (nc8, xmlNewText (BAD_CAST tmp1->value));
1256              char tmp[1024];
1257              sprintf (tmp, "http://www.w3.org/TR/xmlschema-2/#%s",
1258                       tmp1->value);
1259              xmlNewNsProp (nc8, ns_ows, BAD_CAST "reference", BAD_CAST tmp);
1260              xmlAddChild (nc3, nc8);
1261              datatype = 1;
1262            }
1263
1264          if (strncmp (type, "Input", 5) == 0)
1265            {
1266
1267              if ((tmp1 = getMap (_tmp->content, "AllowedValues")) != NULL)
1268                {
1269                  nc6 = xmlNewNode (ns_ows, BAD_CAST "AllowedValues");
1270                  char *token, *saveptr1;
1271                  token = strtok_r (tmp1->value, ",", &saveptr1);
1272                  while (token != NULL)
1273                    {
1274                      nc7 = xmlNewNode (ns_ows, BAD_CAST "Value");
1275                      char *tmps = strdup (token);
1276                      tmps[strlen (tmps)] = 0;
1277                      xmlAddChild (nc7, xmlNewText (BAD_CAST tmps));
1278                      free (tmps);
1279                      xmlAddChild (nc6, nc7);
1280                      token = strtok_r (NULL, ",", &saveptr1);
1281                    }
1282                  if (getMap (_tmp->content, "range") != NULL ||
1283                      getMap (_tmp->content, "rangeMin") != NULL ||
1284                      getMap (_tmp->content, "rangeMax") != NULL ||
1285                      getMap (_tmp->content, "rangeClosure") != NULL)
1286                    goto doRange;
1287                  xmlAddChild (nc3, nc6);
1288                  isAnyValue = -1;
1289                }
1290
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");
1296
1297              if (tmp1 != NULL && isAnyValue == 1)
1298                {
1299                  nc6 = xmlNewNode (ns_ows, BAD_CAST "AllowedValues");
1300                doRange:
1301
1302          /**
1303           * Range: Table 46 OGC Web Services Common Standard
1304           */
1305                  nc8 = xmlNewNode (ns_ows, BAD_CAST "Range");
1306
1307                  map *tmp0 = getMap (tmp1, "range");
1308                  if (tmp0 != NULL)
1309                    {
1310                      char *pToken;
1311                      char *orig = zStrdup (tmp0->value);
1312            /**
1313             * RangeClosure: Table 47 OGC Web Services Common Standard
1314             */
1315                      const char *tmp = "closed";
1316                      if (orig[0] == '[' && orig[strlen (orig) - 1] == '[')
1317                        tmp = "closed-open";
1318                      else
1319                        if (orig[0] == ']' && orig[strlen (orig) - 1] == ']')
1320                        tmp = "open-closed";
1321                      else
1322                        if (orig[0] == ']' && orig[strlen (orig) - 1] == '[')
1323                        tmp = "open";
1324                      xmlNewNsProp (nc8, ns_ows, BAD_CAST "rangeClosure",
1325                                    BAD_CAST tmp);
1326                      pToken = strtok (orig, ",");
1327                      int nci0 = 0;
1328                      while (pToken != NULL)
1329                        {
1330                          char *tmpStr =
1331                            (char *) malloc ((strlen (pToken)) *
1332                                             sizeof (char));
1333                          if (nci0 == 0)
1334                            {
1335                              nc7 =
1336                                xmlNewNode (ns_ows, BAD_CAST "MinimumValue");
1337                              int nci = 1;
1338                              for (nci = 1; nci < strlen (pToken); nci++)
1339                                {
1340                                  tmpStr[nci - 1] = pToken[nci];
1341                                }
1342                            }
1343                          else
1344                            {
1345                              nc7 =
1346                                xmlNewNode (ns_ows, BAD_CAST "MaximumValue");
1347                              int nci = 0;
1348                              for (nci = 0; nci < strlen (pToken) - 1; nci++)
1349                                {
1350                                  tmpStr[nci] = pToken[nci];
1351                                }
1352                            }
1353                          xmlAddChild (nc7, xmlNewText (BAD_CAST tmpStr));
1354                          free (tmpStr);
1355                          xmlAddChild (nc8, nc7);
1356                          nci0++;
1357                          pToken = strtok (NULL, ",");
1358                        }
1359                      if (getMap (tmp1, "rangeSpacing") == NULL)
1360                        {
1361                          nc7 = xmlNewNode (ns_ows, BAD_CAST "Spacing");
1362                          xmlAddChild (nc7, xmlNewText (BAD_CAST "1"));
1363                          xmlAddChild (nc8, nc7);
1364                        }
1365                      free (orig);
1366                    }
1367                  else
1368                    {
1369
1370                      tmp0 = getMap (tmp1, "rangeMin");
1371                      if (tmp0 != NULL)
1372                        {
1373                          nc7 = xmlNewNode (ns_ows, BAD_CAST "MinimumValue");
1374                          xmlAddChild (nc7,
1375                                       xmlNewText (BAD_CAST tmp0->value));
1376                          xmlAddChild (nc8, nc7);
1377                        }
1378                      else
1379                        {
1380                          nc7 = xmlNewNode (ns_ows, BAD_CAST "MinimumValue");
1381                          xmlAddChild (nc8, nc7);
1382                        }
1383                      tmp0 = getMap (tmp1, "rangeMax");
1384                      if (tmp0 != NULL)
1385                        {
1386                          nc7 = xmlNewNode (ns_ows, BAD_CAST "MaximumValue");
1387                          xmlAddChild (nc7,
1388                                       xmlNewText (BAD_CAST tmp0->value));
1389                          xmlAddChild (nc8, nc7);
1390                        }
1391                      else
1392                        {
1393                          nc7 = xmlNewNode (ns_ows, BAD_CAST "MaximumValue");
1394                          xmlAddChild (nc8, nc7);
1395                        }
1396                      tmp0 = getMap (tmp1, "rangeSpacing");
1397                      if (tmp0 != NULL)
1398                        {
1399                          nc7 = xmlNewNode (ns_ows, BAD_CAST "Spacing");
1400                          xmlAddChild (nc7,
1401                                       xmlNewText (BAD_CAST tmp0->value));
1402                          xmlAddChild (nc8, nc7);
1403                        }
1404                      tmp0 = getMap (tmp1, "rangeClosure");
1405                      if (tmp0 != NULL)
1406                        {
1407                          const char *tmp = "closed";
1408                          if (strcasecmp (tmp0->value, "co") == 0)
1409                            tmp = "closed-open";
1410                          else if (strcasecmp (tmp0->value, "oc") == 0)
1411                            tmp = "open-closed";
1412                          else if (strcasecmp (tmp0->value, "o") == 0)
1413                            tmp = "open";
1414                          xmlNewNsProp (nc8, ns_ows, BAD_CAST "rangeClosure",
1415                                        BAD_CAST tmp);
1416                        }
1417                      else
1418                        xmlNewNsProp (nc8, ns_ows, BAD_CAST "rangeClosure",
1419                                      BAD_CAST "closed");
1420                    }
1421                  if (_tmp0 == NULL)
1422                    {
1423                      xmlAddChild (nc6, nc8);
1424                      _tmp0 = e->supported;
1425                      if (getMap (_tmp0->content, "range") != NULL ||
1426                          getMap (_tmp0->content, "rangeMin") != NULL ||
1427                          getMap (_tmp0->content, "rangeMax") != NULL ||
1428                          getMap (_tmp0->content, "rangeClosure") != NULL)
1429                        {
1430                          tmp1 = _tmp0->content;
1431                          goto doRange;
1432                        }
1433                    }
1434                  else
1435                    {
1436                      _tmp0 = _tmp0->next;
1437                      if (_tmp0 != NULL)
1438                        {
1439                          xmlAddChild (nc6, nc8);
1440                          if (getMap (_tmp0->content, "range") != NULL ||
1441                              getMap (_tmp0->content, "rangeMin") != NULL ||
1442                              getMap (_tmp0->content, "rangeMax") != NULL ||
1443                              getMap (_tmp0->content, "rangeClosure") != NULL)
1444                            {
1445                              tmp1 = _tmp0->content;
1446                              goto doRange;
1447                            }
1448                        }
1449                    }
1450                  xmlAddChild (nc6, nc8);
1451                  xmlAddChild (nc3, nc6);
1452                  isAnyValue = -1;
1453                }
1454
1455            }
1456
1457
1458          int oI = 0;
1459          for (oI = 0; oI < 13; oI++)
1460            if ((tmp1 = getMap (_tmp->content, orderedFields[oI])) != NULL)
1461              {
1462#ifdef DEBUG
1463                printf ("DATATYPE DEFAULT ? %s\n", tmp1->name);
1464#endif
1465                if (strcmp (tmp1->name, "asReference") != 0 &&
1466                    strncasecmp (tmp1->name, "DataType", 8) != 0 &&
1467                    strcasecmp (tmp1->name, "extension") != 0 &&
1468                    strcasecmp (tmp1->name, "value") != 0 &&
1469                    strcasecmp (tmp1->name, "AllowedValues") != 0 &&
1470                    strncasecmp (tmp1->name, "range", 5) != 0)
1471                  {
1472                    if (datatype != 1)
1473                      {
1474                        char *tmp2 = zCapitalize1 (tmp1->name);
1475                        nc9 = xmlNewNode (NULL, BAD_CAST tmp2);
1476                        free (tmp2);
1477                      }
1478                    else
1479                      {
1480                        char *tmp2 = zCapitalize (tmp1->name);
1481                        nc9 = xmlNewNode (ns_ows, BAD_CAST tmp2);
1482                        free (tmp2);
1483                      }
1484                    xmlAddChild (nc9, xmlNewText (BAD_CAST tmp1->value));
1485                    xmlAddChild (nc5, nc9);
1486                    if (strcasecmp (tmp1->name, "uom") == 0)
1487                      hasUOM1 = true;
1488                    hasUOM = true;
1489                  }
1490                else
1491
1492                  tmp1 = tmp1->next;
1493              }
1494
1495
1496          if (datatype != 2)
1497            {
1498              if (hasUOM == true)
1499                {
1500                  xmlAddChild (nc4, nc5);
1501                  xmlAddChild (nc3, nc4);
1502                }
1503              else
1504                {
1505                  if (hasUOM1 == false)
1506                    {
1507                      xmlFreeNode (nc5);
1508                      if (datatype == 1)
1509                        xmlFreeNode (nc4);
1510                    }
1511                }
1512            }
1513          else
1514            {
1515              xmlAddChild (nc3, nc5);
1516            }
1517
1518          if (datatype != 1 && default1 < 0)
1519            {
1520              xmlFreeNode (nc5);
1521              if (datatype != 2)
1522                xmlFreeNode (nc4);
1523            }
1524
1525          map *metadata = e->metadata;
1526          xmlNodePtr n = NULL;
1527          int xlinkId =
1528            zooXmlAddNs (n, "http://www.w3.org/1999/xlink", "xlink");
1529          xmlNsPtr ns_xlink = usedNs[xlinkId];
1530
1531          while (metadata != NULL)
1532            {
1533              nc6 = xmlNewNode (ns_ows, BAD_CAST "Metadata");
1534              xmlNewNsProp (nc6, ns_xlink, BAD_CAST metadata->name,
1535                            BAD_CAST metadata->value);
1536              xmlAddChild (nc2, nc6);
1537              metadata = metadata->next;
1538            }
1539
1540        }
1541
1542      _tmp = e->supported;
1543      if (_tmp == NULL && datatype != 1)
1544        _tmp = e->defaults;
1545
1546      int hasSupported = -1;
1547
1548      while (_tmp != NULL)
1549        {
1550          if (hasSupported < 0)
1551            {
1552              if (datatype == 0)
1553                {
1554                  nc4 = xmlNewNode (NULL, BAD_CAST "Supported");
1555                  nc5 = xmlNewNode (NULL, BAD_CAST "Format");
1556                }
1557              else
1558                nc5 = xmlNewNode (NULL, BAD_CAST "Supported");
1559              hasSupported = 0;
1560            }
1561          else if (datatype == 0)
1562            nc5 = xmlNewNode (NULL, BAD_CAST "Format");
1563          tmp1 = _tmp->content;
1564          int oI = 0;
1565          for (oI = 0; oI < 6; oI++)
1566            if ((tmp1 = getMap (_tmp->content, orderedFields[oI])) != NULL)
1567              {
1568#ifdef DEBUG
1569                printf ("DATATYPE SUPPORTED ? %s\n", tmp1->name);
1570#endif
1571                if (strcmp (tmp1->name, "asReference") != 0 &&
1572                    strcmp (tmp1->name, "value") != 0 &&
1573                    strcmp (tmp1->name, "DataType") != 0 &&
1574                    strcasecmp (tmp1->name, "extension") != 0)
1575                  {
1576                    if (datatype != 1)
1577                      {
1578                        char *tmp2 = zCapitalize1 (tmp1->name);
1579                        nc6 = xmlNewNode (NULL, BAD_CAST tmp2);
1580                        free (tmp2);
1581                      }
1582                    else
1583                      {
1584                        char *tmp2 = zCapitalize (tmp1->name);
1585                        nc6 = xmlNewNode (ns_ows, BAD_CAST tmp2);
1586                        free (tmp2);
1587                      }
1588                    if (datatype == 2)
1589                      {
1590                        char *tmpv, *tmps;
1591                        tmps = strtok_r (tmp1->value, ",", &tmpv);
1592                        while (tmps)
1593                          {
1594                            xmlAddChild (nc6, xmlNewText (BAD_CAST tmps));
1595                            tmps = strtok_r (NULL, ",", &tmpv);
1596                            if (tmps)
1597                              {
1598                                char *tmp2 = zCapitalize1 (tmp1->name);
1599                                nc6 = xmlNewNode (NULL, BAD_CAST tmp2);
1600                                free (tmp2);
1601                              }
1602                          }
1603                      }
1604                    else
1605                      {
1606                        xmlAddChild (nc6, xmlNewText (BAD_CAST tmp1->value));
1607                      }
1608                    xmlAddChild (nc5, nc6);
1609                  }
1610                tmp1 = tmp1->next;
1611              }
1612          if (hasSupported <= 0)
1613            {
1614              if (datatype == 0)
1615                {
1616                  xmlAddChild (nc4, nc5);
1617                  xmlAddChild (nc3, nc4);
1618                }
1619              else
1620                {
1621                  if (datatype != 1)
1622                    xmlAddChild (nc3, nc5);
1623                }
1624              hasSupported = 1;
1625            }
1626          else if (datatype == 0)
1627            {
1628              xmlAddChild (nc4, nc5);
1629              xmlAddChild (nc3, nc4);
1630            }
1631          else if (datatype != 1)
1632            xmlAddChild (nc3, nc5);
1633
1634          _tmp = _tmp->next;
1635        }
1636
1637      if (hasSupported == 0)
1638        {
1639          if (datatype == 0)
1640            xmlFreeNode (nc4);
1641          xmlFreeNode (nc5);
1642        }
1643
1644      _tmp = e->defaults;
1645      if (datatype == 1 && hasUOM1 == true)
1646        {
1647          xmlAddChild (nc4, nc5);
1648          xmlAddChild (nc3, nc4);
1649        }
1650
1651      if (in > 0 && datatype == 1 &&
1652          getMap (_tmp->content, "AllowedValues") == NULL &&
1653          getMap (_tmp->content, "range") == NULL &&
1654          getMap (_tmp->content, "rangeMin") == NULL &&
1655          getMap (_tmp->content, "rangeMax") == NULL &&
1656          getMap (_tmp->content, "rangeClosure") == NULL)
1657        {
1658          tmp1 = getMap (_tmp->content, "dataType");
1659          if (tmp1 != NULL)
1660            if (strcasecmp (tmp1->value, "boolean") == 0)
1661              {
1662                nc6 = xmlNewNode (ns_ows, BAD_CAST "AllowedValues");
1663                nc7 = xmlNewNode (ns_ows, BAD_CAST "Value");
1664                xmlAddChild (nc7, xmlNewText (BAD_CAST "true"));
1665                xmlAddChild (nc6, nc7);
1666                nc7 = xmlNewNode (ns_ows, BAD_CAST "Value");
1667                xmlAddChild (nc7, xmlNewText (BAD_CAST "false"));
1668                xmlAddChild (nc6, nc7);
1669                xmlAddChild (nc3, nc6);
1670              }
1671          xmlAddChild (nc3, xmlNewNode (ns_ows, BAD_CAST "AnyValue"));
1672        }
1673
1674      if ((tmp1 = getMap (_tmp->content, "value")) != NULL)
1675        {
1676          nc7 = xmlNewNode (NULL, BAD_CAST "DefaultValue");
1677          xmlAddChild (nc7, xmlNewText (BAD_CAST tmp1->value));
1678          xmlAddChild (nc3, nc7);
1679        }
1680
1681      xmlAddChild (nc2, nc3);
1682
1683      xmlAddChild (nc1, nc2);
1684
1685      e = e->next;
1686    }
1687}
1688
1689void
1690printProcessResponse (maps * m, map * request, int pid, service * serv,
1691                      const char *service, int status, maps * inputs,
1692                      maps * outputs, FCGX_Stream* out)
1693{
1694  xmlNsPtr ns, ns_ows, ns_xlink, ns_xsi;
1695  xmlNodePtr nr, n, nc, nc1 = NULL, nc3;
1696  xmlDocPtr doc;
1697  time_t time1;
1698  time (&time1);
1699  nr = NULL;
1700  /**
1701   * Create the document and its temporary root.
1702   */
1703  doc = xmlNewDoc (BAD_CAST "1.0");
1704  int wpsId = zooXmlAddNs (NULL, "http://www.opengis.net/wps/1.0.0", "wps");
1705  ns = usedNs[wpsId];
1706
1707  n = xmlNewNode (ns, BAD_CAST "ExecuteResponse");
1708  xmlNewNs (n, BAD_CAST "http://www.opengis.net/wps/1.0.0", BAD_CAST "wps");
1709  int owsId = zooXmlAddNs (n, "http://www.opengis.net/ows/1.1", "ows");
1710  ns_ows = usedNs[owsId];
1711  int xlinkId = zooXmlAddNs (n, "http://www.w3.org/1999/xlink", "xlink");
1712  ns_xlink = usedNs[xlinkId];
1713  int xsiId =
1714    zooXmlAddNs (n, "http://www.w3.org/2001/XMLSchema-instance", "xsi");
1715  ns_xsi = usedNs[xsiId];
1716
1717  xmlNewNsProp (n, ns_xsi, BAD_CAST "schemaLocation",
1718                BAD_CAST
1719                "http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsExecute_response.xsd");
1720
1721  xmlNewProp (n, BAD_CAST "service", BAD_CAST "WPS");
1722  xmlNewProp (n, BAD_CAST "version", BAD_CAST "1.0.0");
1723  addLangAttr (n, m);
1724
1725  char tmp[256];
1726  char url[1024];
1727  char stored_path[1024];
1728  memset (tmp, 0, 256);
1729  memset (url, 0, 1024);
1730  memset (stored_path, 0, 1024);
1731  maps *tmp_maps = getMaps (m, "main");
1732  if (tmp_maps != NULL)
1733    {
1734      map *tmpm1 = getMap (tmp_maps->content, "serverAddress");
1735    /**
1736     * Check if the ZOO Service GetStatus is available in the local directory.
1737     * If yes, then it uses a reference to an URL which the client can access
1738     * to get information on the status of a running Service (using the
1739     * percentCompleted attribute).
1740     * Else fallback to the initial method using the xml file to write in ...
1741     */
1742      char ntmp[1024];
1743#ifndef WIN32
1744      getcwd (ntmp, 1024);
1745#else
1746      _getcwd (ntmp, 1024);
1747#endif
1748      struct stat myFileInfo;
1749      int statRes;
1750      char file_path[1024];
1751      sprintf (file_path, "%s/GetStatus.zcfg", ntmp);
1752      statRes = stat (file_path, &myFileInfo);
1753      if (statRes == 0)
1754        {
1755          char currentSid[128];
1756          map *tmpm = getMap (tmp_maps->content, "rewriteUrl");
1757          map *tmp_lenv = NULL;
1758          tmp_lenv = getMapFromMaps (m, "lenv", "sid");
1759          if (tmp_lenv == NULL)
1760            sprintf (currentSid, "%i", pid);
1761          else
1762            sprintf (currentSid, "%s", tmp_lenv->value);
1763          if (tmpm == NULL || strcasecmp (tmpm->value, "false") == 0)
1764            {
1765              sprintf (url,
1766                       "%s?request=Execute&service=WPS&version=1.0.0&Identifier=GetStatus&DataInputs=sid=%s&RawDataOutput=Result",
1767                       tmpm1->value, currentSid);
1768            }
1769          else
1770            {
1771              if (strlen (tmpm->value) > 0)
1772                if (strcasecmp (tmpm->value, "true") != 0)
1773                  sprintf (url, "%s/%s/GetStatus/%s", tmpm1->value,
1774                           tmpm->value, currentSid);
1775                else
1776                  sprintf (url, "%s/GetStatus/%s", tmpm1->value, currentSid);
1777              else
1778                sprintf (url,
1779                         "%s/?request=Execute&service=WPS&version=1.0.0&Identifier=GetStatus&DataInputs=sid=%s&RawDataOutput=Result",
1780                         tmpm1->value, currentSid);
1781            }
1782        }
1783      else
1784        {
1785          map *tmpm2 = getMap (tmp_maps->content, "tmpUrl");
1786          if (tmpm1 != NULL && tmpm2 != NULL)
1787            {
1788              if (strncasecmp (tmpm2->value, "http://", 7) == 0 ||
1789                  strncasecmp (tmpm2->value, "https://", 8) == 0)
1790                {
1791                  sprintf (url, "%s/%s_%i.xml", tmpm2->value, service, pid);
1792                }
1793              else
1794                sprintf (url, "%s/%s/%s_%i.xml", tmpm1->value, tmpm2->value,
1795                         service, pid);
1796            }
1797        }
1798      if (tmpm1 != NULL)
1799        sprintf (tmp, "%s", tmpm1->value);
1800      tmpm1 = getMapFromMaps (m, "main", "TmpPath");
1801      sprintf (stored_path, "%s/%s_%i.xml", tmpm1->value, service, pid);
1802    }
1803
1804
1805
1806  xmlNewProp (n, BAD_CAST "serviceInstance", BAD_CAST tmp);
1807  map *test = getMap (request, "storeExecuteResponse");
1808  bool hasStoredExecuteResponse = false;
1809  if (test != NULL && strcasecmp (test->value, "true") == 0)
1810    {
1811      xmlNewProp (n, BAD_CAST "statusLocation", BAD_CAST url);
1812      hasStoredExecuteResponse = true;
1813    }
1814
1815  nc = xmlNewNode (ns, BAD_CAST "Process");
1816  map *tmp2 = getMap (serv->content, "processVersion");
1817  if (tmp2 != NULL)
1818    xmlNewNsProp (nc, ns, BAD_CAST "processVersion", BAD_CAST tmp2->value);
1819
1820  printDescription (nc, ns_ows, serv->name, serv->content);
1821
1822  xmlAddChild (n, nc);
1823
1824  nc = xmlNewNode (ns, BAD_CAST "Status");
1825  const struct tm *tm;
1826  size_t len;
1827  time_t now;
1828  char *tmp1;
1829  map *tmpStatus;
1830
1831  now = time (NULL);
1832  tm = localtime (&now);
1833
1834  tmp1 = (char *) malloc ((TIME_SIZE + 1) * sizeof (char));
1835
1836  len = strftime (tmp1, TIME_SIZE, "%Y-%m-%dT%I:%M:%SZ", tm);
1837
1838  xmlNewProp (nc, BAD_CAST "creationTime", BAD_CAST tmp1);
1839
1840  char sMsg[2048];
1841  switch (status)
1842    {
1843    case SERVICE_SUCCEEDED:
1844      nc1 = xmlNewNode (ns, BAD_CAST "ProcessSucceeded");
1845      sprintf (sMsg, _("Service \"%s\" run successfully."), serv->name);
1846      nc3 = xmlNewText (BAD_CAST sMsg);
1847      xmlAddChild (nc1, nc3);
1848      break;
1849    case SERVICE_STARTED:
1850      nc1 = xmlNewNode (ns, BAD_CAST "ProcessStarted");
1851      tmpStatus = getMapFromMaps (m, "lenv", "status");
1852      xmlNewProp (nc1, BAD_CAST "percentCompleted",
1853                  BAD_CAST tmpStatus->value);
1854      sprintf (sMsg,
1855               _
1856               ("ZOO Service \"%s\" is currently running. Please, reload this document to get the up-to-date status of the Service."),
1857               serv->name);
1858      nc3 = xmlNewText (BAD_CAST sMsg);
1859      xmlAddChild (nc1, nc3);
1860      break;
1861    case SERVICE_ACCEPTED:
1862      nc1 = xmlNewNode (ns, BAD_CAST "ProcessAccepted");
1863      sprintf (sMsg,
1864               _
1865               ("Service \"%s\" was accepted by the ZOO Kernel and it run as a background task. Please consult the statusLocation attribtue providen in this document to get the up-to-date document."),
1866               serv->name);
1867      nc3 = xmlNewText (BAD_CAST sMsg);
1868      xmlAddChild (nc1, nc3);
1869      break;
1870    case SERVICE_FAILED:
1871      nc1 = xmlNewNode (ns, BAD_CAST "ProcessFailed");
1872      map *errorMap;
1873      map *te;
1874      te = getMapFromMaps (m, "lenv", "code");
1875      if (te != NULL)
1876        errorMap = createMap ("code", te->value);
1877      else
1878        errorMap = createMap ("code", "NoApplicableCode");
1879      te = getMapFromMaps (m, "lenv", "message");
1880      if (te != NULL)
1881        addToMap (errorMap, "text", _ss (te->value));
1882      else
1883        addToMap (errorMap, "text", _("No more information available"));
1884      nc3 = createExceptionReportNode (m, errorMap, 0);
1885      freeMap (&errorMap);
1886      free (errorMap);
1887      xmlAddChild (nc1, nc3);
1888      break;
1889    default:
1890      printf (_("error code not know : %i\n"), status);
1891      //exit(1);
1892      break;
1893    }
1894  xmlAddChild (nc, nc1);
1895  xmlAddChild (n, nc);
1896  free (tmp1);
1897
1898#ifdef DEBUG
1899  fprintf (stderr, "printProcessResponse 1 161\n");
1900#endif
1901
1902  map *lineage = getMap (request, "lineage");
1903  if (lineage != NULL && strcasecmp (lineage->value, "true") == 0)
1904    {
1905      nc = xmlNewNode (ns, BAD_CAST "DataInputs");
1906      maps *mcursor = inputs;
1907      elements *scursor = NULL;
1908      while (mcursor != NULL /*&& scursor!=NULL */ )
1909        {
1910          scursor = getElements (serv->inputs, mcursor->name);
1911          printIOType (doc, nc, ns, ns_ows, ns_xlink, scursor, mcursor,
1912                       "Input");
1913          mcursor = mcursor->next;
1914        }
1915      xmlAddChild (n, nc);
1916
1917#ifdef DEBUG
1918      fprintf (stderr, "printProcessResponse 1 177\n");
1919#endif
1920
1921      nc = xmlNewNode (ns, BAD_CAST "OutputDefinitions");
1922      mcursor = outputs;
1923      scursor = NULL;
1924      while (mcursor != NULL)
1925        {
1926          scursor = getElements (serv->outputs, mcursor->name);
1927          printOutputDefinitions1 (doc, nc, ns, ns_ows, scursor, mcursor,
1928                                   "Output");
1929          mcursor = mcursor->next;
1930        }
1931      xmlAddChild (n, nc);
1932    }
1933#ifdef DEBUG
1934  fprintf (stderr, "printProcessResponse 1 190\n");
1935#endif
1936
1937  /**
1938   * Display the process output only when requested !
1939   */
1940  if (status == SERVICE_SUCCEEDED)
1941    {
1942      nc = xmlNewNode (ns, BAD_CAST "ProcessOutputs");
1943      maps *mcursor = outputs;
1944      elements *scursor = serv->outputs;
1945      map *testResponse = getMap (request, "RawDataOutput");
1946      if (testResponse == NULL)
1947        testResponse = getMap (request, "ResponseDocument");
1948      while (mcursor != NULL)
1949        {
1950          map *tmp0 = getMap (mcursor->content, "inRequest");
1951          scursor = getElements (serv->outputs, mcursor->name);
1952          if (scursor != NULL)
1953            {
1954              if (testResponse == NULL || tmp0 == NULL)
1955                printIOType (doc, nc, ns, ns_ows, ns_xlink, scursor, mcursor,
1956                             "Output");
1957              else if (tmp0 != NULL && strncmp (tmp0->value, "true", 4) == 0)
1958                printIOType (doc, nc, ns, ns_ows, ns_xlink, scursor, mcursor,
1959                             "Output");
1960            }
1961          else
1962        /**
1963         * In case there was no definition found in the ZCFG file but
1964         * present in the service code
1965         */
1966            printIOType (doc, nc, ns, ns_ows, ns_xlink, scursor, mcursor,
1967                         "Output");
1968          mcursor = mcursor->next;
1969        }
1970      xmlAddChild (n, nc);
1971    }
1972
1973#ifdef DEBUG
1974  fprintf (stderr, "printProcessResponse 1 202\n");
1975#endif
1976  nr = soapEnvelope (m, n);
1977  xmlDocSetRootElement (doc, nr);
1978
1979  if (hasStoredExecuteResponse == true)
1980    {
1981      /* We need to write the ExecuteResponse Document somewhere */
1982      FILE *output = fopen (stored_path, "w");
1983      if (output == NULL)
1984        {
1985          /* If the file cannot be created return an ExceptionReport */
1986          char tmpMsg[1024];
1987          sprintf (tmpMsg,
1988                   _
1989                   ("Unable to create the file : \"%s\" for storing the ExecuteResponse."),
1990                   stored_path);
1991          map *errormap = createMap ("text", tmpMsg);
1992          addToMap (errormap, "code", "InternalError");
1993          printExceptionReportResponse (m, errormap,out);
1994          freeMap (&errormap);
1995          free (errormap);
1996          xmlFreeDoc (doc);
1997          xmlCleanupParser ();
1998          zooXmlCleanupNs ();
1999          return;
2000        }
2001      xmlChar *xmlbuff;
2002      int buffersize;
2003      xmlDocDumpFormatMemoryEnc (doc, &xmlbuff, &buffersize, "UTF-8", 1);
2004      fwrite (xmlbuff, 1, xmlStrlen (xmlbuff) * sizeof (char), output);
2005      xmlFree (xmlbuff);
2006      fclose (output);
2007    }
2008  printDocument (m, doc, pid,out);
2009
2010  xmlCleanupParser ();
2011  zooXmlCleanupNs ();
2012}
2013
2014
2015void
2016printDocument (maps * m, xmlDocPtr doc, int pid,FCGX_Stream * out)
2017{
2018  char *encoding = getEncoding (m);
2019  if (pid == getpid ())
2020    {
2021      printHeaders (m,out);
2022      FCGX_FPrintF(out,"Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding);
2023      //printf ("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding);
2024    }
2025  //fflush (stdout);
2026  xmlChar *xmlbuff;
2027  int buffersize;
2028  /*
2029   * Dump the document to a buffer and print it on stdout
2030   * for demonstration purposes.
2031   */
2032  xmlDocDumpFormatMemoryEnc (doc, &xmlbuff, &buffersize, encoding, 1);
2033  FCGX_FPrintF(out,(char *)xmlbuff);
2034  FCGX_FFlush(out);
2035  //printf ("%s", xmlbuff);
2036  //fflush (stdout);
2037  /*
2038   * Free associated memory.
2039   */
2040  xmlFree (xmlbuff);
2041  xmlFreeDoc (doc);
2042  xmlCleanupParser ();
2043  zooXmlCleanupNs ();
2044}
2045
2046void
2047printOutputDefinitions1 (xmlDocPtr doc, xmlNodePtr nc, xmlNsPtr ns_wps,
2048                         xmlNsPtr ns_ows, elements * e, maps * m,
2049                         const char *type)
2050{
2051  xmlNodePtr nc1;
2052  nc1 = xmlNewNode (ns_wps, BAD_CAST type);
2053  map *tmp = NULL;
2054  if (e != NULL && e->defaults != NULL)
2055    tmp = e->defaults->content;
2056  else
2057    {
2058      /*
2059         dumpElements(e);
2060       */
2061      return;
2062    }
2063  while (tmp != NULL)
2064    {
2065      if (strncasecmp (tmp->name, "MIMETYPE", strlen (tmp->name)) == 0
2066          || strncasecmp (tmp->name, "ENCODING", strlen (tmp->name)) == 0
2067          || strncasecmp (tmp->name, "SCHEMA", strlen (tmp->name)) == 0
2068          || strncasecmp (tmp->name, "UOM", strlen (tmp->name)) == 0)
2069        xmlNewProp (nc1, BAD_CAST tmp->name, BAD_CAST tmp->value);
2070      tmp = tmp->next;
2071    }
2072  tmp = getMap (e->defaults->content, "asReference");
2073  if (tmp == NULL)
2074    xmlNewProp (nc1, BAD_CAST "asReference", BAD_CAST "false");
2075
2076  tmp = e->content;
2077
2078  printDescription (nc1, ns_ows, m->name, e->content);
2079
2080  xmlAddChild (nc, nc1);
2081
2082}
2083
2084void
2085printOutputDefinitions (xmlDocPtr doc, xmlNodePtr nc, xmlNsPtr ns_wps,
2086                        xmlNsPtr ns_ows, elements * e, map * m,
2087                        const char *type)
2088{
2089  xmlNodePtr nc1;
2090  nc1 = xmlNewNode (ns_wps, BAD_CAST type);
2091  map *tmp = NULL;
2092  if (e != NULL && e->defaults != NULL)
2093    tmp = e->defaults->content;
2094  else
2095    {
2096      /*
2097         dumpElements(e);
2098       */
2099      return;
2100    }
2101  while (tmp != NULL)
2102    {
2103      xmlNewProp (nc1, BAD_CAST tmp->name, BAD_CAST tmp->value);
2104      tmp = tmp->next;
2105    }
2106  tmp = getMap (e->defaults->content, "asReference");
2107  if (tmp == NULL)
2108    xmlNewProp (nc1, BAD_CAST "asReference", BAD_CAST "false");
2109
2110  tmp = e->content;
2111
2112  printDescription (nc1, ns_ows, m->name, e->content);
2113
2114  xmlAddChild (nc, nc1);
2115
2116}
2117
2118void
2119printIOType (xmlDocPtr doc, xmlNodePtr nc, xmlNsPtr ns_wps, xmlNsPtr ns_ows,
2120             xmlNsPtr ns_xlink, elements * e, maps * m, const char *type)
2121{
2122  xmlNodePtr nc1, nc2, nc3;
2123  nc1 = xmlNewNode (ns_wps, BAD_CAST type);
2124  map *tmp = NULL;
2125  if (e != NULL)
2126    tmp = e->content;
2127  else
2128    tmp = m->content;
2129#ifdef DEBUG
2130  dumpMap (tmp);
2131  dumpElements (e);
2132#endif
2133  nc2 = xmlNewNode (ns_ows, BAD_CAST "Identifier");
2134  if (e != NULL)
2135    nc3 = xmlNewText (BAD_CAST e->name);
2136  else
2137    nc3 = xmlNewText (BAD_CAST m->name);
2138  xmlAddChild (nc2, nc3);
2139  xmlAddChild (nc1, nc2);
2140  xmlAddChild (nc, nc1);
2141  if (e != NULL)
2142    tmp = getMap (e->content, "Title");
2143  else
2144    tmp = getMap (m->content, "Title");
2145
2146  if (tmp != NULL)
2147    {
2148      nc2 = xmlNewNode (ns_ows, BAD_CAST tmp->name);
2149      nc3 = xmlNewText (BAD_CAST _ss (tmp->value));
2150      xmlAddChild (nc2, nc3);
2151      xmlAddChild (nc1, nc2);
2152    }
2153
2154  if (e != NULL)
2155    tmp = getMap (e->content, "Abstract");
2156  else
2157    tmp = getMap (m->content, "Abstract");
2158  if (tmp != NULL)
2159    {
2160      nc2 = xmlNewNode (ns_ows, BAD_CAST tmp->name);
2161      nc3 = xmlNewText (BAD_CAST _ss (tmp->value));
2162      xmlAddChild (nc2, nc3);
2163      xmlAddChild (nc1, nc2);
2164      xmlAddChild (nc, nc1);
2165    }
2166
2167  /**
2168   * IO type Reference or full Data ?
2169   */
2170#ifdef DEBUG
2171  fprintf (stderr, "FORMAT %s %s\n", e->format, e->format);
2172#endif
2173  map *tmpMap = getMap (m->content, "Reference");
2174  if (tmpMap == NULL)
2175    {
2176      nc2 = xmlNewNode (ns_wps, BAD_CAST "Data");
2177      if (e != NULL)
2178        {
2179          if (strncasecmp (e->format, "LiteralOutput", strlen (e->format)) ==
2180              0)
2181            nc3 = xmlNewNode (ns_wps, BAD_CAST "LiteralData");
2182          else
2183            if (strncasecmp (e->format, "ComplexOutput", strlen (e->format))
2184                == 0)
2185            nc3 = xmlNewNode (ns_wps, BAD_CAST "ComplexData");
2186          else
2187            if (strncasecmp
2188                (e->format, "BoundingBoxOutput", strlen (e->format)) == 0)
2189            nc3 = xmlNewNode (ns_wps, BAD_CAST "BoundingBoxData");
2190          else
2191            nc3 = xmlNewNode (ns_wps, BAD_CAST e->format);
2192        }
2193      else
2194        {
2195          map *tmpV = getMapFromMaps (m, "format", "value");
2196          if (tmpV != NULL)
2197            nc3 = xmlNewNode (ns_wps, BAD_CAST tmpV->value);
2198          else
2199            nc3 = xmlNewNode (ns_wps, BAD_CAST "LitteralData");
2200        }
2201      tmp = m->content;
2202#ifdef USE_MS
2203      map *testMap = getMap (tmp, "requestedMimeType");
2204#endif
2205      while (tmp != NULL)
2206        {
2207          if (strcasecmp (tmp->name, "mimeType") == 0 ||
2208              strcasecmp (tmp->name, "encoding") == 0 ||
2209              strcasecmp (tmp->name, "schema") == 0 ||
2210              strcasecmp (tmp->name, "datatype") == 0 ||
2211              strcasecmp (tmp->name, "uom") == 0)
2212            {
2213#ifdef USE_MS
2214              if (testMap == NULL
2215                  || (testMap != NULL
2216                      && strncasecmp (testMap->value, "text/xml", 8) == 0))
2217                {
2218#endif
2219                  xmlNewProp (nc3, BAD_CAST tmp->name, BAD_CAST tmp->value);
2220#ifdef USE_MS
2221                }
2222              else if (strcasecmp (tmp->name, "mimeType") == 0)
2223                {
2224                  if (testMap != NULL)
2225                    xmlNewProp (nc3, BAD_CAST tmp->name,
2226                                BAD_CAST testMap->value);
2227                  else
2228                    xmlNewProp (nc3, BAD_CAST tmp->name, BAD_CAST tmp->value);
2229                }
2230#endif
2231            }
2232          tmp = tmp->next;
2233          xmlAddChild (nc2, nc3);
2234        }
2235      if (e != NULL && e->format != NULL
2236          && strcasecmp (e->format, "BoundingBoxData") == 0)
2237        {
2238          map *bb = getMap (m->content, "value");
2239          if (bb != NULL)
2240            {
2241              map *tmpRes = parseBoundingBox (bb->value);
2242              printBoundingBox (ns_ows, nc3, tmpRes);
2243              freeMap (&tmpRes);
2244              free (tmpRes);
2245            }
2246        }
2247      else
2248        {
2249          if (e != NULL)
2250            tmp = getMap (e->defaults->content, "mimeType");
2251          else
2252            tmp = NULL;
2253#ifdef USE_MS
2254      /**
2255       * In case of OGC WebServices output use, as the data was requested
2256       * with asReference=false we have to download the resulting OWS request
2257       * stored in the Reference map value.
2258       */
2259          map *testMap = getMap (m->content, "requestedMimeType");
2260          if (testMap != NULL)
2261            {
2262              HINTERNET hInternet;
2263              char *tmpValue;
2264              size_t dwRead;
2265              hInternet = InternetOpen (
2266#ifndef WIN32
2267                                         (LPCTSTR)
2268#endif
2269                                         "ZooWPSClient\0",
2270                                         INTERNET_OPEN_TYPE_PRECONFIG,
2271                                         NULL, NULL, 0);
2272              testMap = getMap (m->content, "Reference");
2273              loadRemoteFile (&m, &m->content, &hInternet, testMap->value);
2274              processDownloads (&hInternet);
2275              tmpValue =
2276                (char *) malloc ((hInternet.ihandle[0].nDataLen + 1) *
2277                                 sizeof (char));
2278              InternetReadFile (hInternet.ihandle[0], (LPVOID) tmpValue,
2279                                hInternet.ihandle[0].nDataLen, &dwRead);
2280              InternetCloseHandle (&hInternet);
2281            }
2282#endif
2283          map *tmp1 = getMap (m->content, "encoding");
2284          map *tmp2 = getMap (m->content, "mimeType");
2285          map *tmp3 = getMap (m->content, "value");
2286          int hasValue = 1;
2287          if (tmp3 == NULL)
2288            {
2289              tmp3 = createMap ("value", "");
2290              hasValue = -1;
2291            }
2292          if ((tmp1 != NULL && strncmp (tmp1->value, "base64", 6) == 0)
2293              || (tmp2 != NULL && (strncmp (tmp2->value, "image/", 6) == 0 ||
2294                                   (strncmp (tmp2->value, "application/", 12)
2295                                    == 0
2296                                    && strncmp (tmp2->value,
2297                                                "application/json", 16) != 0
2298                                    && strncmp (tmp2->value,
2299                                                "application/x-javascript",
2300                                                24) != 0
2301                                    && strncmp (tmp2->value,
2302                                                "application/vnd.google-earth.kml",
2303                                                32) != 0))))
2304            {
2305              map *rs = getMap (m->content, "size");
2306              bool isSized = true;
2307              if (rs == NULL)
2308                {
2309                  char tmp1[1024];
2310                  sprintf (tmp1, "%u", strlen (tmp3->value));
2311                  rs = createMap ("size", tmp1);
2312                  isSized = false;
2313                }
2314
2315              xmlAddChild (nc3,
2316                           xmlNewText (BAD_CAST
2317                                       base64 (tmp3->value,
2318                                               atoi (rs->value))));
2319              if (tmp1 == NULL
2320                  || (tmp1 != NULL
2321                      && strncmp (tmp1->value, "base64", 6) != 0))
2322                xmlNewProp (nc3, BAD_CAST "encoding", BAD_CAST "base64");
2323              if (!isSized)
2324                {
2325                  freeMap (&rs);
2326                  free (rs);
2327                }
2328            }
2329          else if (tmp2 != NULL)
2330            {
2331              if (strncmp (tmp2->value, "text/js", 7) == 0 ||
2332                  strncmp (tmp2->value, "application/json", 16) == 0)
2333                xmlAddChild (nc3,
2334                             xmlNewCDataBlock (doc, BAD_CAST tmp3->value,
2335                                               strlen (tmp3->value)));
2336              else
2337                {
2338                  if (strncmp (tmp2->value, "text/xml", 8) == 0 ||
2339                      strncmp (tmp2->value,
2340                               "application/vnd.google-earth.kml", 32) == 0)
2341                    {
2342                      int li = zooXmlAddDoc (tmp3->value);
2343                      xmlDocPtr doc = iDocs[li];
2344                      xmlNodePtr ir = xmlDocGetRootElement (doc);
2345                      xmlAddChild (nc3, ir);
2346                    }
2347                  else
2348                    xmlAddChild (nc3, xmlNewText (BAD_CAST tmp3->value));
2349                }
2350              xmlAddChild (nc2, nc3);
2351            }
2352          else
2353            {
2354              xmlAddChild (nc3, xmlNewText (BAD_CAST tmp3->value));
2355            }
2356          if (hasValue < 0)
2357            {
2358              freeMap (&tmp3);
2359              free (tmp3);
2360            }
2361        }
2362    }
2363  else
2364    {
2365      tmpMap = getMap (m->content, "Reference");
2366      nc3 = nc2 = xmlNewNode (ns_wps, BAD_CAST "Reference");
2367      if (strcasecmp (type, "Output") == 0)
2368        xmlNewProp (nc3, BAD_CAST "href", BAD_CAST tmpMap->value);
2369      else
2370        xmlNewNsProp (nc3, ns_xlink, BAD_CAST "href", BAD_CAST tmpMap->value);
2371      tmp = m->content;
2372#ifdef USE_MS
2373      map *testMap = getMap (tmp, "requestedMimeType");
2374#endif
2375      while (tmp != NULL)
2376        {
2377          if (strcasecmp (tmp->name, "mimeType") == 0 ||
2378              strcasecmp (tmp->name, "encoding") == 0 ||
2379              strcasecmp (tmp->name, "schema") == 0 ||
2380              strcasecmp (tmp->name, "datatype") == 0 ||
2381              strcasecmp (tmp->name, "uom") == 0)
2382            {
2383#ifdef USE_MS
2384              if (testMap != NULL
2385                  && strncasecmp (testMap->value, "text/xml", 8) != 0)
2386                {
2387                  if (strcasecmp (tmp->name, "mimeType") == 0)
2388                    xmlNewProp (nc3, BAD_CAST tmp->name,
2389                                BAD_CAST testMap->value);
2390                }
2391              else
2392#endif
2393              if (strcasecmp (tmp->name, "datatype") == 0)
2394                xmlNewProp (nc3, BAD_CAST "mimeType", BAD_CAST "text/plain");
2395              else
2396                xmlNewProp (nc3, BAD_CAST tmp->name, BAD_CAST tmp->value);
2397            }
2398          tmp = tmp->next;
2399          xmlAddChild (nc2, nc3);
2400        }
2401    }
2402  xmlAddChild (nc1, nc2);
2403  xmlAddChild (nc, nc1);
2404
2405}
2406
2407void
2408printDescription (xmlNodePtr root, xmlNsPtr ns_ows, const char *identifier,
2409                  map * amap)
2410{
2411  xmlNodePtr nc2 = xmlNewNode (ns_ows, BAD_CAST "Identifier");
2412
2413  xmlAddChild (nc2, xmlNewText (BAD_CAST identifier));
2414  xmlAddChild (root, nc2);
2415  map *tmp = amap;
2416  const char *tmp2[2];
2417  tmp2[0] = "Title";
2418  tmp2[1] = "Abstract";
2419  int j = 0;
2420  for (j = 0; j < 2; j++)
2421    {
2422      map *tmp1 = getMap (tmp, tmp2[j]);
2423      if (tmp1 != NULL)
2424        {
2425          nc2 = xmlNewNode (ns_ows, BAD_CAST tmp2[j]);
2426          xmlAddChild (nc2, xmlNewText (BAD_CAST _ss (tmp1->value)));
2427          xmlAddChild (root, nc2);
2428        }
2429    }
2430}
2431
2432char *
2433getEncoding (maps * m)
2434{
2435  if (m != NULL)
2436    {
2437      map *tmp = getMap (m->content, "encoding");
2438      if (tmp != NULL)
2439        {
2440          return tmp->value;
2441        }
2442      else
2443        return (char *) "UTF-8";
2444    }
2445  else
2446    return (char *) "UTF-8";
2447}
2448
2449char *
2450getVersion (maps * m)
2451{
2452  if (m != NULL)
2453    {
2454      map *tmp = getMap (m->content, "version");
2455      if (tmp != NULL)
2456        {
2457          return tmp->value;
2458        }
2459      else
2460        return (char *) "1.0.0";
2461    }
2462  else
2463    return (char *) "1.0.0";
2464}
2465
2466void
2467printExceptionReportResponse (maps * m, map * s,FCGX_Stream * out)
2468{
2469  if (getMapFromMaps (m, "lenv", "hasPrinted") != NULL)
2470    return;
2471  int buffersize;
2472  xmlDocPtr doc;
2473  xmlChar *xmlbuff;
2474  xmlNodePtr n;
2475
2476  zooXmlCleanupNs ();
2477  doc = xmlNewDoc (BAD_CAST "1.0");
2478  maps *tmpMap = getMaps (m, "main");
2479  char *encoding = getEncoding (tmpMap);
2480  const char *exceptionCode;
2481
2482  map *tmp = getMap (s, "code");
2483  if (tmp != NULL)
2484    {
2485      if (strcmp (tmp->value, "OperationNotSupported") == 0)
2486        exceptionCode = "501 Not Implemented";
2487      else
2488        if (strcmp (tmp->value, "MissingParameterValue") == 0 ||
2489            strcmp (tmp->value, "InvalidUpdateSequence") == 0 ||
2490            strcmp (tmp->value, "OptionNotSupported") == 0 ||
2491            strcmp (tmp->value, "VersionNegotiationFailed") == 0 ||
2492            strcmp (tmp->value, "InvalidParameterValue") == 0)
2493        exceptionCode = "400 Bad request";
2494      else if (strcmp (tmp->value, "NoApplicableCode") == 0)
2495        exceptionCode = "501 Internal Server Error";
2496      else
2497        exceptionCode = "501 Internal Server Error";
2498    }
2499  else
2500    exceptionCode = "501 Internal Server Error";
2501
2502  if (m != NULL)
2503    {
2504      map *tmpSid = getMapFromMaps (m, "lenv", "sid");
2505      if (tmpSid != NULL)
2506        {
2507          if (getpid () == atoi (tmpSid->value))
2508            {
2509              printHeaders (m,out);
2510              FCGX_FPrintF(out,"Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding, exceptionCode);
2511              //printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding, exceptionCode);
2512            }
2513        }
2514      else
2515        {
2516          printHeaders (m,out);
2517          FCGX_FPrintF(out,"Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",
2518                            encoding, exceptionCode);
2519          //printf ("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding, exceptionCode);
2520        }
2521    }
2522  else
2523    { 
2524      FCGX_FPrintF(out,"Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding, exceptionCode);
2525      //printf ("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding, exceptionCode);
2526    }
2527  n = createExceptionReportNode (m, s, 1);
2528  xmlDocSetRootElement (doc, n);
2529  xmlDocDumpFormatMemoryEnc (doc, &xmlbuff, &buffersize, encoding, 1);
2530  //printf ("%s", xmlbuff);
2531  FCGX_FPrintF(out,"%s",xmlbuff);
2532FCGX_FFlush(out);
2533  //fflush (stdout);
2534  xmlFreeDoc (doc);
2535  xmlFree (xmlbuff);
2536  xmlCleanupParser ();
2537  zooXmlCleanupNs ();
2538  if (m != NULL)
2539    setMapInMaps (m, "lenv", "hasPrinted", "true");
2540}
2541
2542xmlNodePtr
2543createExceptionReportNode (maps * m, map * s, int use_ns)
2544{
2545
2546  xmlNsPtr ns, ns_xsi;
2547  xmlNodePtr n, nc, nc1;
2548
2549  int nsid = zooXmlAddNs (NULL, "http://www.opengis.net/ows", "ows");
2550  ns = usedNs[nsid];
2551  if (use_ns == 1)
2552    {
2553      ns = NULL;
2554    }
2555  n = xmlNewNode (ns, BAD_CAST "ExceptionReport");
2556  if (use_ns == 1)
2557    {
2558      xmlNewNs (n, BAD_CAST "http://www.opengis.net/ows/1.1", NULL);
2559      int xsiId =
2560        zooXmlAddNs (n, "http://www.w3.org/2001/XMLSchema-instance", "xsi");
2561      ns_xsi = usedNs[xsiId];
2562      xmlNewNsProp (n, ns_xsi, BAD_CAST "schemaLocation",
2563                    BAD_CAST
2564                    "http://www.opengis.net/ows/1.1 http://schemas.opengis.net/ows/1.1.0/owsExceptionReport.xsd");
2565    }
2566
2567
2568  addLangAttr (n, m);
2569  xmlNewProp (n, BAD_CAST "version", BAD_CAST "1.1.0");
2570
2571  nc = xmlNewNode (ns, BAD_CAST "Exception");
2572
2573  map *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 = getMap (s, "locator");
2580  if (tmp != NULL && strcasecmp (tmp->value, "NULL") != 0)
2581    xmlNewProp (nc, BAD_CAST "locator", BAD_CAST tmp->value);
2582
2583
2584  tmp = getMap (s, "text");
2585  nc1 = xmlNewNode (ns, BAD_CAST "ExceptionText");
2586  if (tmp != NULL)
2587    {
2588      xmlNodeSetContent (nc1, BAD_CAST tmp->value);
2589    }
2590  else
2591    {
2592      xmlNodeSetContent (nc1, BAD_CAST _("No debug message available"));
2593    }
2594  xmlAddChild (nc, nc1);
2595  xmlAddChild (n, nc);
2596  return n;
2597}
2598
2599
2600void
2601outputResponse (service * s, maps * request_inputs, maps * request_outputs,
2602                map * request_inputs1, int cpid, maps * m, int res,FCGX_Stream *out,FCGX_Stream *err)
2603{
2604
2605
2606#ifdef DEBUG
2607  dumpMaps (request_inputs);
2608  dumpMaps (request_outputs);
2609  fprintf (stderr, "printProcessResponse\n");
2610#endif
2611  map *toto = getMap (request_inputs1, "RawDataOutput");
2612  int asRaw = 0;
2613  if (toto != NULL)
2614    asRaw = 1;
2615
2616  maps *tmpSess = getMaps (m, "senv");
2617  if (tmpSess != NULL)
2618    {
2619      map *_tmp = getMapFromMaps (m, "lenv", "cookie");
2620      char *sessId = NULL;
2621      if (_tmp != NULL)
2622        {
2623          printf ("Set-Cookie: %s; HttpOnly\r\n", _tmp->value);
2624          printf
2625            ("P3P: CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"\r\n");
2626          char session_file_path[100];
2627          char *tmp1 = strtok (_tmp->value, ";");
2628          if (tmp1 != NULL)
2629            sprintf (session_file_path, "%s", strstr (tmp1, "=") + 1);
2630          else
2631            sprintf (session_file_path, "%s", strstr (_tmp->value, "=") + 1);
2632          sessId = strdup (session_file_path);
2633        }
2634      else
2635        {
2636          maps *t = getMaps (m, "senv");
2637          map *p = t->content;
2638          while (p != NULL)
2639            {
2640              if (strstr (p->name, "ID") != NULL)
2641                {
2642                  sessId = strdup (p->value);
2643                  break;
2644                }
2645              p = p->next;
2646            }
2647        }
2648      char session_file_path[1024];
2649      map *tmpPath = getMapFromMaps (m, "main", "sessPath");
2650      if (tmpPath == NULL)
2651        tmpPath = getMapFromMaps (m, "main", "tmpPath");
2652      sprintf (session_file_path, "%s/sess_%s.cfg", tmpPath->value, sessId);
2653      FILE *teste = fopen (session_file_path, "w");
2654      if (teste == NULL)
2655        {
2656          char tmpMsg[1024];
2657          sprintf (tmpMsg,
2658                   _
2659                   ("Unable to create the file : \"%s\" for storing the session maps."),
2660                   session_file_path);
2661          map *errormap = createMap ("text", tmpMsg);
2662          addToMap (errormap, "code", "InternalError");
2663
2664          printExceptionReportResponse (m, errormap,out);
2665          freeMap (&errormap);
2666          free (errormap);
2667          return;
2668        }
2669      else
2670        {
2671          fclose (teste);
2672          dumpMapsToFile (tmpSess, session_file_path);
2673        }
2674    }
2675
2676
2677  if (asRaw == 0)
2678    {
2679
2680
2681#ifdef DEBUG
2682      fprintf (stderr, "REQUEST_OUTPUTS FINAL\n");
2683      dumpMaps (request_outputs);
2684#endif
2685      maps *tmpI = request_outputs;
2686      while (tmpI != NULL)
2687        {
2688#ifdef USE_MS
2689          map *testMap = getMap (tmpI->content, "useMapserver");
2690#endif
2691          toto = getMap (tmpI->content, "asReference");
2692#ifdef USE_MS
2693          if (toto != NULL && strcasecmp (toto->value, "true") == 0
2694              && testMap == NULL)
2695#else
2696          if (toto != NULL && strcasecmp (toto->value, "true") == 0)
2697#endif
2698            {
2699              elements *in = getElements (s->outputs, tmpI->name);
2700              char *format = NULL;
2701              if (in != NULL)
2702                {
2703                  format = strdup (in->format);
2704                }
2705              else
2706                format = strdup ("LiteralData");
2707              if (strcasecmp (format, "BoundingBoxData") == 0)
2708                {
2709                  addToMap (tmpI->content, "extension", "xml");
2710                  addToMap (tmpI->content, "mimeType", "text/xml");
2711                  addToMap (tmpI->content, "encoding", "UTF-8");
2712                  addToMap (tmpI->content, "schema",
2713                            "http://schemas.opengis.net/ows/1.1.0/owsCommon.xsd");
2714                }
2715              map *ext = getMap (tmpI->content, "extension");
2716              map *tmp1 = getMapFromMaps (m, "main", "tmpPath");
2717              char *file_name, *file_path;
2718              bool hasExt = true;
2719              if (ext == NULL)
2720                {
2721                  // We can fallback to a default list of supported formats using
2722                  // mimeType information if present here. Maybe we can add more formats
2723                  // here.
2724                  // If mimeType was not found, we then set txt as the default extension
2725                  map *mtype = getMap (tmpI->content, "mimeType");
2726                  if (mtype != NULL)
2727                    {
2728                      if (strcasecmp (mtype->value, "text/xml") == 0)
2729                        ext = createMap ("extension", "xml");
2730                      else if (strcasecmp (mtype->value, "application/json")
2731                               == 0)
2732                        ext = createMap ("extension", "js");
2733                      else
2734                        if (strncmp
2735                            (mtype->value, "application/vnd.google-earth.kml",
2736                             32) == 0)
2737                        ext = createMap ("extension", "kml");
2738                      else if (strncmp (mtype->value, "image/", 6) == 0)
2739                        ext =
2740                          createMap ("extension",
2741                                     strstr (mtype->value, "/") + 1);
2742                      else
2743                        ext = createMap ("extension", "txt");
2744                    }
2745                  else
2746                    ext = createMap ("extension", "txt");
2747                  hasExt = false;
2748                }
2749              file_name =
2750                (char *)
2751                malloc ((strlen (s->name) + strlen (ext->value) +
2752                         strlen (tmpI->name) + 1024) * sizeof (char));
2753              int cpid0 = cpid + time (NULL);
2754              sprintf (file_name, "%s_%s_%i.%s", s->name, tmpI->name, cpid0,
2755                       ext->value);
2756              file_path =
2757                (char *)
2758                malloc ((strlen (tmp1->value) + strlen (file_name) +
2759                         2) * sizeof (char));
2760              sprintf (file_path, "%s/%s", tmp1->value, file_name);
2761              FILE *ofile = fopen (file_path, "wb");
2762              if (ofile == NULL)
2763                {
2764                  char tmpMsg[1024];
2765                  sprintf (tmpMsg,
2766                           _
2767                           ("Unable to create the file : \"%s\" for storing the %s final result."),
2768                           file_name, tmpI->name);
2769                  map *errormap = createMap ("text", tmpMsg);
2770                  addToMap (errormap, "code", "InternalError");
2771
2772                  printExceptionReportResponse (m, errormap,out);
2773                  freeMap (&errormap);
2774                  free (errormap);
2775                  free (file_name);
2776                  free (file_path);
2777                  return;
2778                }
2779              free (file_path);
2780              map *tmp2 = getMapFromMaps (m, "main", "tmpUrl");
2781              map *tmp3 = getMapFromMaps (m, "main", "serverAddress");
2782              char *file_url;
2783              if (strncasecmp (tmp2->value, "http://", 7) == 0 ||
2784                  strncasecmp (tmp2->value, "https://", 8) == 0)
2785                {
2786                  file_url =
2787                    (char *)
2788                    malloc ((strlen (tmp2->value) + strlen (file_name) +
2789                             2) * sizeof (char));
2790                  sprintf (file_url, "%s/%s", tmp2->value, file_name);
2791                }
2792              else
2793                {
2794                  file_url =
2795                    (char *)
2796                    malloc ((strlen (tmp3->value) + strlen (tmp2->value) +
2797                             strlen (file_name) + 3) * sizeof (char));
2798                  sprintf (file_url, "%s/%s/%s", tmp3->value, tmp2->value,
2799                           file_name);
2800                }
2801              addToMap (tmpI->content, "Reference", file_url);
2802              if (!hasExt)
2803                {
2804                  freeMap (&ext);
2805                  free (ext);
2806                }
2807              toto = getMap (tmpI->content, "value");
2808              if (strcasecmp (format, "BoundingBoxData") != 0)
2809                {
2810                  map *size = getMap (tmpI->content, "size");
2811                  if (size != NULL && toto != NULL)
2812                    fwrite (toto->value, 1,
2813                            atoi (size->value) * sizeof (char), ofile);
2814                  else if (toto != NULL && toto->value != NULL)
2815                    fwrite (toto->value, 1,
2816                            strlen (toto->value) * sizeof (char), ofile);
2817                }
2818              else
2819                {
2820                  printBoundingBoxDocument (m, tmpI, ofile);
2821                }
2822              free (format);
2823              fclose (ofile);
2824              free (file_name);
2825              free (file_url);
2826            }
2827#ifdef USE_MS
2828          else
2829            {
2830              if (testMap != NULL)
2831                {
2832                  setReferenceUrl (m, tmpI);
2833                }
2834            }
2835#endif
2836          tmpI = tmpI->next;
2837        }
2838      map *r_inputs = getMap (s->content, "serviceProvider");
2839#ifdef DEBUG
2840      fprintf (stderr, "SERVICE : %s\n", r_inputs->value);
2841      dumpMaps (m);
2842#endif
2843      printProcessResponse (m, request_inputs1, cpid,
2844                            s, r_inputs->value, res,
2845                            request_inputs, request_outputs,out);
2846    }
2847  else
2848    {
2849
2850      if (res == SERVICE_FAILED)
2851        {
2852
2853          map *errormap;
2854          map *lenv;
2855          lenv = getMapFromMaps (m, "lenv", "message");
2856          char *tmp0;
2857          if (lenv != NULL)
2858            {
2859              tmp0 =
2860                (char *)
2861                malloc ((strlen (lenv->value) +
2862                         strlen (_
2863                                 ("Unable to run the Service. The message returned back by the Service was the following: "))
2864                         + 1) * sizeof (char));
2865              sprintf (tmp0,
2866                       _
2867                       ("Unable to run the Service. The message returned back by the Service was the following: %s"),
2868                       lenv->value);
2869            }
2870          else
2871            {
2872              tmp0 =
2873                (char *)
2874                malloc ((strlen
2875                         (_
2876                          ("Unable to run the Service. No more information was returned back by the Service."))
2877                         + 1) * sizeof (char));
2878              sprintf (tmp0,
2879                       _
2880                       ("Unable to run the Service. No more information was returned back by the Service."));
2881            }
2882          errormap = createMap ("text", tmp0);
2883          free (tmp0);
2884          addToMap (errormap, "code", "InternalError");
2885          printExceptionReportResponse (m, errormap,out);
2886          freeMap (&errormap);
2887          free (errormap);
2888          return;
2889        }
2890      /**
2891       * We get the requested output or fallback to the first one if the
2892       * requested one is not present in the resulting outputs maps.
2893       */
2894
2895
2896      maps *tmpI = NULL;
2897      map *tmpIV = getMap (request_inputs1, "RawDataOutput");
2898      if (tmpIV != NULL)
2899        {
2900          tmpI = getMaps (request_outputs, tmpIV->value);
2901        }
2902      if (tmpI == NULL)
2903        tmpI = request_outputs;
2904      elements *e = getElements (s->outputs, tmpI->name);
2905      if (e != NULL && strcasecmp (e->format, "BoundingBoxData") == 0)
2906        {
2907          printBoundingBoxDocument (m, tmpI, NULL);
2908        }
2909      else
2910        {
2911          toto = getMap (tmpI->content, "value");
2912          if (toto == NULL)
2913            {
2914              char tmpMsg[1024];
2915              sprintf (tmpMsg,
2916                       _
2917                       ("Wrong RawDataOutput parameter, unable to fetch any result for the name your provided : \"%s\"."),
2918                       tmpI->name);
2919              map *errormap = createMap ("text", tmpMsg);
2920              addToMap (errormap, "code", "InvalidParameterValue");
2921              printExceptionReportResponse (m, errormap,out);
2922              freeMap (&errormap);
2923              free (errormap);
2924              return;
2925            }
2926          map *fname = getMapFromMaps (tmpI, tmpI->name, "filename");
2927          if (fname != NULL)
2928            FCGX_FPrintF(out,"Content-Disposition: attachment; filename=\"%s\"\r\n",fname->value);
2929            //printf ("Content-Disposition: attachment; filename=\"%s\"\r\n",fname->value);
2930          map *rs = getMapFromMaps (tmpI, tmpI->name, "size");
2931          if (rs != NULL)
2932            FCGX_FPrintF(out,"Content-Length: %s\r\n", rs->value);
2933            //printf ("Content-Length: %s\r\n", rs->value);
2934          printHeaders (m,out);
2935          char mime[1024];
2936          map *mi = getMap (tmpI->content, "mimeType");
2937#ifdef DEBUG
2938          fprintf (stderr, "SERVICE OUTPUTS\n");
2939          dumpMaps (request_outputs);
2940          fprintf (stderr, "SERVICE OUTPUTS\n");
2941#endif
2942          map *en = getMap (tmpI->content, "encoding");
2943          if (mi != NULL && en != NULL)
2944            sprintf (mime,
2945                     "Content-Type: %s; charset=%s\r\nStatus: 200 OK\r\n\r\n",
2946                     mi->value, en->value);
2947          else if (mi != NULL)
2948            sprintf (mime,
2949                     "Content-Type: %s; charset=UTF-8\r\nStatus: 200 OK\r\n\r\n",
2950                     mi->value);
2951          else
2952            sprintf (mime,
2953                     "Content-Type: text/plain; charset=utf-8\r\nStatus: 200 OK\r\n\r\n");
2954          FCGX_FPrintF(out,"%s", mime);
2955
2956          //printf ("%s", mime);
2957          if (rs != NULL)
2958            FCGX_PutStr(toto->value,atoi(rs->value),out);
2959            //fwrite (toto->value, 1, atoi (rs->value), stdout);
2960          else
2961             FCGX_PutStr(toto->value,strlen (toto->value),out);
2962            //fwrite (toto->value, 1, strlen (toto->value), stdout);
2963
2964          FCGX_FFlush(out);
2965#ifdef DEBUG
2966          dumpMap (toto);
2967#endif
2968        }
2969    }
2970}
2971
2972char *
2973base64 (const char *input, int length)
2974{
2975  BIO *bmem, *b64;
2976  BUF_MEM *bptr;
2977
2978  b64 = BIO_new (BIO_f_base64 ());
2979  BIO_set_flags (b64, BIO_FLAGS_BASE64_NO_NL);
2980  bmem = BIO_new (BIO_s_mem ());
2981  b64 = BIO_push (b64, bmem);
2982  BIO_write (b64, input, length + 1);
2983  BIO_flush (b64);
2984  BIO_get_mem_ptr (b64, &bptr);
2985
2986  char *buff = (char *) malloc ((bptr->length + 1) * sizeof (char));
2987  memcpy (buff, bptr->data, bptr->length);
2988  buff[bptr->length - 1] = 0;
2989
2990  BIO_free_all (b64);
2991
2992  return buff;
2993}
2994
2995char *
2996base64d (const char *input, int length, int *red)
2997{
2998  BIO *b64, *bmem;
2999
3000  char *buffer = (char *) malloc (length);
3001  if (buffer)
3002    {
3003      memset (buffer, 0, length);
3004      b64 = BIO_new (BIO_f_base64 ());
3005      if (b64)
3006        {
3007          bmem = BIO_new_mem_buf ((unsigned char *) input, length);
3008          bmem = BIO_push (b64, bmem);
3009          *red = BIO_read (bmem, buffer, length);
3010          buffer[length - 1] = 0;
3011          BIO_free_all (bmem);
3012        }
3013    }
3014  return buffer;
3015}
3016
3017void
3018ensureDecodedBase64 (maps ** in)
3019{
3020  maps *cursor = *in;
3021  while (cursor != NULL)
3022    {
3023      map *tmp = getMap (cursor->content, "encoding");
3024      if (tmp != NULL && strncasecmp (tmp->value, "base64", 6) == 0)
3025        {
3026          tmp = getMap (cursor->content, "value");
3027          addToMap (cursor->content, "base64_value", tmp->value);
3028          int size = 0;
3029          char *s = strdup (tmp->value);
3030          free (tmp->value);
3031          tmp->value = base64d (s, strlen (s), &size);
3032          free (s);
3033          char sizes[1024];
3034          sprintf (sizes, "%d", size);
3035          addToMap (cursor->content, "size", sizes);
3036        }
3037      cursor = cursor->next;
3038    }
3039}
3040
3041char *
3042addDefaultValues (maps ** out, elements * in, maps * m, int type)
3043{
3044  elements *tmpInputs = in;
3045  maps *out1 = *out;
3046  if (type == 1)
3047    {
3048      while (out1 != NULL)
3049        {
3050          if (getElements (in, out1->name) == NULL)
3051            return out1->name;
3052          out1 = out1->next;
3053        }
3054      out1 = *out;
3055    }
3056  while (tmpInputs != NULL)
3057    {
3058      maps *tmpMaps = getMaps (out1, tmpInputs->name);
3059      if (tmpMaps == NULL)
3060        {
3061          maps *tmpMaps2 = (maps *) malloc (MAPS_SIZE);
3062          tmpMaps2->name = strdup (tmpInputs->name);
3063          tmpMaps2->content = NULL;
3064          tmpMaps2->next = NULL;
3065
3066          if (type == 0)
3067            {
3068              map *tmpMapMinO = getMap (tmpInputs->content, "minOccurs");
3069              if (tmpMapMinO != NULL)
3070                {
3071                  if (atoi (tmpMapMinO->value) >= 1)
3072                    {
3073                      freeMaps (&tmpMaps2);
3074                      free (tmpMaps2);
3075                      return tmpInputs->name;
3076                    }
3077                  else
3078                    {
3079                      if (tmpMaps2->content == NULL)
3080                        tmpMaps2->content =
3081                          createMap ("minOccurs", tmpMapMinO->value);
3082                      else
3083                        addToMap (tmpMaps2->content, "minOccurs",
3084                                  tmpMapMinO->value);
3085                    }
3086                }
3087              map *tmpMaxO = getMap (tmpInputs->content, "maxOccurs");
3088              if (tmpMaxO != NULL)
3089                {
3090                  if (tmpMaps2->content == NULL)
3091                    tmpMaps2->content =
3092                      createMap ("maxOccurs", tmpMaxO->value);
3093                  else
3094                    addToMap (tmpMaps2->content, "maxOccurs", tmpMaxO->value);
3095                }
3096              map *tmpMaxMB = getMap (tmpInputs->content, "maximumMegabytes");
3097              if (tmpMaxMB != NULL)
3098                {
3099                  if (tmpMaps2->content == NULL)
3100                    tmpMaps2->content =
3101                      createMap ("maximumMegabytes", tmpMaxMB->value);
3102                  else
3103                    addToMap (tmpMaps2->content, "maximumMegabytes",
3104                              tmpMaxMB->value);
3105                }
3106            }
3107
3108          iotype *tmpIoType = tmpInputs->defaults;
3109          if (tmpIoType != NULL)
3110            {
3111              map *tmpm = tmpIoType->content;
3112              while (tmpm != NULL)
3113                {
3114                  if (tmpMaps2->content == NULL)
3115                    tmpMaps2->content = createMap (tmpm->name, tmpm->value);
3116                  else
3117                    addToMap (tmpMaps2->content, tmpm->name, tmpm->value);
3118                  tmpm = tmpm->next;
3119                }
3120            }
3121          addToMap (tmpMaps2->content, "inRequest", "false");
3122          if (type == 0)
3123            {
3124              map *tmpMap = getMap (tmpMaps2->content, "value");
3125              if (tmpMap == NULL)
3126                addToMap (tmpMaps2->content, "value", "NULL");
3127            }
3128          if (out1 == NULL)
3129            {
3130              *out = dupMaps (&tmpMaps2);
3131              out1 = *out;
3132            }
3133          else
3134            addMapsToMaps (&out1, tmpMaps2);
3135          freeMap (&tmpMaps2->content);
3136          free (tmpMaps2->content);
3137          tmpMaps2->content = NULL;
3138          freeMaps (&tmpMaps2);
3139          free (tmpMaps2);
3140          tmpMaps2 = NULL;
3141        }
3142      else
3143        {
3144          iotype *tmpIoType =
3145            getIoTypeFromElement (tmpInputs, tmpInputs->name,
3146                                  tmpMaps->content);
3147          if (type == 0)
3148            {
3149        /**
3150         * In case of an Input maps, then add the minOccurs and maxOccurs to the
3151         * content map.
3152         */
3153              map *tmpMap1 = getMap (tmpInputs->content, "minOccurs");
3154              if (tmpMap1 != NULL)
3155                {
3156                  if (tmpMaps->content == NULL)
3157                    tmpMaps->content =
3158                      createMap ("minOccurs", tmpMap1->value);
3159                  else
3160                    addToMap (tmpMaps->content, "minOccurs", tmpMap1->value);
3161                }
3162              map *tmpMaxO = getMap (tmpInputs->content, "maxOccurs");
3163              if (tmpMaxO != NULL)
3164                {
3165                  if (tmpMaps->content == NULL)
3166                    tmpMaps->content =
3167                      createMap ("maxOccurs", tmpMaxO->value);
3168                  else
3169                    addToMap (tmpMaps->content, "maxOccurs", tmpMaxO->value);
3170                }
3171              map *tmpMaxMB = getMap (tmpInputs->content, "maximumMegabytes");
3172              if (tmpMaxMB != NULL)
3173                {
3174                  if (tmpMaps->content == NULL)
3175                    tmpMaps->content =
3176                      createMap ("maximumMegabytes", tmpMaxMB->value);
3177                  else
3178                    addToMap (tmpMaps->content, "maximumMegabytes",
3179                              tmpMaxMB->value);
3180                }
3181        /**
3182         * Parsing BoundingBoxData, fill the following map and then add it to
3183         * the content map of the Input maps:
3184         * lowerCorner, upperCorner, srs and dimensions
3185         * cf. parseBoundingBox
3186         */
3187              if (strcasecmp (tmpInputs->format, "BoundingBoxData") == 0)
3188                {
3189                  maps *tmpI = getMaps (*out, tmpInputs->name);
3190                  if (tmpI != NULL)
3191                    {
3192                      map *tmpV = getMap (tmpI->content, "value");
3193                      if (tmpV != NULL)
3194                        {
3195                          char *tmpVS = strdup (tmpV->value);
3196                          map *tmp = parseBoundingBox (tmpVS);
3197                          free (tmpVS);
3198                          map *tmpC = tmp;
3199                          while (tmpC != NULL)
3200                            {
3201                              addToMap (tmpMaps->content, tmpC->name,
3202                                        tmpC->value);
3203                              tmpC = tmpC->next;
3204                            }
3205                          freeMap (&tmp);
3206                          free (tmp);
3207                        }
3208                    }
3209                }
3210            }
3211
3212          if (tmpIoType != NULL)
3213            {
3214              map *tmpContent = tmpIoType->content;
3215              map *cval = NULL;
3216              int hasPassed = -1;
3217              while (tmpContent != NULL)
3218                {
3219                  if ((cval =
3220                       getMap (tmpMaps->content, tmpContent->name)) == NULL)
3221                    {
3222#ifdef DEBUG
3223                      fprintf (stderr, "addDefaultValues %s => %s\n",
3224                               tmpContent->name, tmpContent->value);
3225#endif
3226                      if (tmpMaps->content == NULL)
3227                        tmpMaps->content =
3228                          createMap (tmpContent->name, tmpContent->value);
3229                      else
3230                        addToMap (tmpMaps->content, tmpContent->name,
3231                                  tmpContent->value);
3232
3233                      if (hasPassed < 0 && type == 0
3234                          && getMap (tmpMaps->content, "isArray") != NULL)
3235                        {
3236                          map *length = getMap (tmpMaps->content, "length");
3237                          int i;
3238                          char *tcn = strdup (tmpContent->name);
3239                          for (i = 1; i < atoi (length->value); i++)
3240                            {
3241#ifdef DEBUG
3242                              dumpMap (tmpMaps->content);
3243                              fprintf (stderr,
3244                                       "addDefaultValues %s_%d => %s\n", tcn,
3245                                       i, tmpContent->value);
3246#endif
3247                              int len = strlen ((char *) tcn);
3248                              char *tmp1 =
3249                                (char *) malloc ((len + 10) * sizeof (char));
3250                              sprintf (tmp1, "%s_%d", tcn, i);
3251#ifdef DEBUG
3252                              fprintf (stderr, "addDefaultValues %s => %s\n",
3253                                       tmp1, tmpContent->value);
3254#endif
3255                              addToMap (tmpMaps->content, tmp1,
3256                                        tmpContent->value);
3257                              free (tmp1);
3258                              hasPassed = 1;
3259                            }
3260                          free (tcn);
3261                        }
3262                    }
3263                  tmpContent = tmpContent->next;
3264                }
3265#ifdef USE_MS
3266        /**
3267         * check for useMapServer presence
3268         */
3269              map *tmpCheck = getMap (tmpIoType->content, "useMapServer");
3270              if (tmpCheck != NULL)
3271                {
3272                  // Get the default value
3273                  tmpIoType =
3274                    getIoTypeFromElement (tmpInputs, tmpInputs->name, NULL);
3275                  tmpCheck = getMap (tmpMaps->content, "mimeType");
3276                  addToMap (tmpMaps->content, "requestedMimeType",
3277                            tmpCheck->value);
3278                  map *cursor = tmpIoType->content;
3279                  while (cursor != NULL)
3280                    {
3281                      addToMap (tmpMaps->content, cursor->name,
3282                                cursor->value);
3283                      cursor = cursor->next;
3284                    }
3285
3286                  cursor = tmpInputs->content;
3287                  while (cursor != NULL)
3288                    {
3289                      if (strcasecmp (cursor->name, "Title") == 0 ||
3290                          strcasecmp (cursor->name, "Abstract") == 0)
3291                        addToMap (tmpMaps->content, cursor->name,
3292                                  cursor->value);
3293                      cursor = cursor->next;
3294                    }
3295                }
3296#endif
3297            }
3298          if (tmpMaps->content == NULL)
3299            tmpMaps->content = createMap ("inRequest", "true");
3300          else
3301            addToMap (tmpMaps->content, "inRequest", "true");
3302
3303        }
3304      tmpInputs = tmpInputs->next;
3305    }
3306  return "";
3307}
3308
3309/**
3310 * parseBoundingBox : parse a BoundingBox string
3311 *
3312 * OGC 06-121r3 : 10.2 Bounding box
3313 *
3314 * value is provided as : lowerCorner,upperCorner,crs,dimension
3315 * exemple : 189000,834000,285000,962000,urn:ogc:def:crs:OGC:1.3:CRS84
3316 *
3317 * Need to create a map to store boundingbox informations :
3318 *  - lowerCorner : double,double (minimum within this bounding box)
3319 *  - upperCorner : double,double (maximum within this bounding box)
3320 *  - crs : URI (Reference to definition of the CRS)
3321 *  - dimensions : int
3322 *
3323 * Note : support only 2D bounding box.
3324 */
3325map *
3326parseBoundingBox (const char *value)
3327{
3328  map *res = NULL;
3329  if (value != NULL)
3330    {
3331      char *cv, *cvp;
3332      cv = strtok_r ((char *) value, ",", &cvp);
3333      int cnt = 0;
3334      int icnt = 0;
3335      char *currentValue = NULL;
3336      while (cv)
3337        {
3338          if (cnt < 2)
3339            if (currentValue != NULL)
3340              {
3341                char *finalValue =
3342                  (char *) malloc ((strlen (currentValue) + strlen (cv) + 1) *
3343                                   sizeof (char));
3344                sprintf (finalValue, "%s%s", currentValue, cv);
3345                switch (cnt)
3346                  {
3347                  case 0:
3348                    res = createMap ("lowerCorner", finalValue);
3349                    break;
3350                  case 1:
3351                    addToMap (res, "upperCorner", finalValue);
3352                    icnt = -1;
3353                    break;
3354                  }
3355                cnt++;
3356                free (currentValue);
3357                currentValue = NULL;
3358                free (finalValue);
3359              }
3360            else
3361              {
3362                currentValue =
3363                  (char *) malloc ((strlen (cv) + 2) * sizeof (char));
3364                sprintf (currentValue, "%s ", cv);
3365              }
3366          else if (cnt == 2)
3367            {
3368              addToMap (res, "crs", cv);
3369              cnt++;
3370            }
3371          else
3372            addToMap (res, "dimensions", cv);
3373          icnt++;
3374          cv = strtok_r (NULL, ",", &cvp);
3375        }
3376    }
3377  return res;
3378}
3379
3380/**
3381 * printBoundingBox : fill a BoundingBox node (ows:BoundingBox or
3382 * wps:BoundingBoxData). Set crs and dimensions attributes, add
3383 * Lower/UpperCorner nodes to a pre-existing XML node.
3384 */
3385void
3386printBoundingBox (xmlNsPtr ns_ows, xmlNodePtr n, map * boundingbox)
3387{
3388
3389  xmlNodePtr lw = NULL, uc = NULL;
3390
3391  map *tmp = getMap (boundingbox, "value");
3392
3393  tmp = getMap (boundingbox, "lowerCorner");
3394  if (tmp != NULL)
3395    {
3396      lw = xmlNewNode (ns_ows, BAD_CAST "LowerCorner");
3397      xmlAddChild (lw, xmlNewText (BAD_CAST tmp->value));
3398    }
3399
3400  tmp = getMap (boundingbox, "upperCorner");
3401  if (tmp != NULL)
3402    {
3403      uc = xmlNewNode (ns_ows, BAD_CAST "UpperCorner");
3404      xmlAddChild (uc, xmlNewText (BAD_CAST tmp->value));
3405    }
3406
3407  tmp = getMap (boundingbox, "crs");
3408  if (tmp != NULL)
3409    xmlNewProp (n, BAD_CAST "crs", BAD_CAST tmp->value);
3410
3411  tmp = getMap (boundingbox, "dimensions");
3412  if (tmp != NULL)
3413    xmlNewProp (n, BAD_CAST "dimensions", BAD_CAST tmp->value);
3414
3415  xmlAddChild (n, lw);
3416  xmlAddChild (n, uc);
3417
3418}
3419
3420void
3421printBoundingBoxDocument (maps * m, maps * boundingbox, FILE * file)
3422{
3423  //if (file == NULL)
3424   // rewind (stdout);
3425  xmlNodePtr n;
3426  xmlDocPtr doc;
3427  xmlNsPtr ns_ows, ns_xsi;
3428  xmlChar *xmlbuff;
3429  int buffersize;
3430  char *encoding = getEncoding (m);
3431  map *tmp;
3432  if (file == NULL)
3433    {
3434      int pid = 0;
3435      tmp = getMapFromMaps (m, "lenv", "sid");
3436      if (tmp != NULL)
3437        pid = atoi (tmp->value);
3438      if (pid == getpid ())
3439        {
3440          printf
3441            ("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",
3442             encoding);
3443        }
3444      //fflush (stdout);
3445    }
3446
3447  doc = xmlNewDoc (BAD_CAST "1.0");
3448  int owsId = zooXmlAddNs (NULL, "http://www.opengis.net/ows/1.1", "ows");
3449  ns_ows = usedNs[owsId];
3450  n = xmlNewNode (ns_ows, BAD_CAST "BoundingBox");
3451  xmlNewNs (n, BAD_CAST "http://www.opengis.net/ows/1.1", BAD_CAST "ows");
3452  int xsiId =
3453    zooXmlAddNs (n, "http://www.w3.org/2001/XMLSchema-instance", "xsi");
3454  ns_xsi = usedNs[xsiId];
3455  xmlNewNsProp (n, ns_xsi, BAD_CAST "schemaLocation",
3456                BAD_CAST
3457                "http://www.opengis.net/ows/1.1 http://schemas.opengis.net/ows/1.1.0/owsCommon.xsd");
3458  map *tmp1 = getMap (boundingbox->content, "value");
3459  tmp = parseBoundingBox (tmp1->value);
3460  printBoundingBox (ns_ows, n, tmp);
3461  xmlDocSetRootElement (doc, n);
3462
3463  xmlDocDumpFormatMemoryEnc (doc, &xmlbuff, &buffersize, encoding, 1);
3464  if (file == NULL)
3465    printf ("%s", xmlbuff);
3466  else
3467    {
3468      fprintf (file, "%s", xmlbuff);
3469    }
3470
3471  if (tmp != NULL)
3472    {
3473      freeMap (&tmp);
3474      free (tmp);
3475    }
3476  xmlFree (xmlbuff);
3477  xmlFreeDoc (doc);
3478  xmlCleanupParser ();
3479  zooXmlCleanupNs ();
3480
3481}
3482
3483
3484char *
3485getMd5 (char *url)
3486{
3487  EVP_MD_CTX md5ctx;
3488  char *fresult = (char *) malloc ((EVP_MAX_MD_SIZE + 1) * sizeof (char));
3489  unsigned char result[EVP_MAX_MD_SIZE];
3490  unsigned int len;
3491  EVP_DigestInit (&md5ctx, EVP_md5 ());
3492  EVP_DigestUpdate (&md5ctx, url, strlen (url));
3493  EVP_DigestFinal_ex (&md5ctx, result, &len);
3494  EVP_MD_CTX_cleanup (&md5ctx);
3495  int i;
3496  for (i = 0; i < len; i++)
3497    {
3498      if (i > 0)
3499        {
3500          char *tmp = strdup (fresult);
3501          sprintf (fresult, "%s%02x", tmp, result[i]);
3502          free (tmp);
3503        }
3504      else
3505        sprintf (fresult, "%02x", result[i]);
3506    }
3507  return fresult;
3508}
3509
3510/**
3511 * Cache a file for a given request
3512 */
3513void
3514addToCache (maps * conf, char *request, char *content, char *mimeType,
3515            int length)
3516{
3517  map *tmp = getMapFromMaps (conf, "main", "cacheDir");
3518  if (tmp != NULL)
3519    {
3520      char *md5str = getMd5 (request);
3521      char *fname =
3522        (char *) malloc (sizeof (char) *
3523                         (strlen (tmp->value) + strlen (md5str) + 6));
3524      sprintf (fname, "%s/%s.zca", tmp->value, md5str);
3525#ifdef DEBUG
3526      fprintf (stderr, "Cache list : %s\n", fname);
3527      fflush (stderr);
3528#endif
3529      FILE *fo = fopen (fname, "w+");
3530      if (fo == NULL)
3531        {
3532          fprintf (stderr, "Failed to open %s for writting: %s\n", fname,
3533                   strerror (errno));
3534          return;
3535        }
3536      fwrite (content, sizeof (char), length, fo);
3537      fclose (fo);
3538
3539      sprintf (fname, "%s/%s.zcm", tmp->value, md5str);
3540      fo = fopen (fname, "w+");
3541#ifdef DEBUG
3542      fprintf (stderr, "MIMETYPE: %s\n", mimeType);
3543#endif
3544      fwrite (mimeType, sizeof (char), strlen (mimeType), fo);
3545      fclose (fo);
3546
3547      free (md5str);
3548      free (fname);
3549    }
3550}
3551
3552char *
3553isInCache (maps * conf, char *request)
3554{
3555  map *tmpM = getMapFromMaps (conf, "main", "cacheDir");
3556  if (tmpM != NULL)
3557    {
3558      char *md5str = getMd5 (request);
3559#ifdef DEBUG
3560      fprintf (stderr, "MD5STR : (%s)\n\n", md5str);
3561#endif
3562      char *fname =
3563        (char *) malloc (sizeof (char) *
3564                         (strlen (tmpM->value) + strlen (md5str) + 6));
3565      sprintf (fname, "%s/%s.zca", tmpM->value, md5str);
3566      struct stat f_status;
3567      int s = stat (fname, &f_status);
3568      if (s == 0 && f_status.st_size > 0)
3569        {
3570          free (md5str);
3571          return fname;
3572        }
3573      free (md5str);
3574      free (fname);
3575    }
3576  return NULL;
3577}
3578
3579int
3580runHttpRequests (maps ** m, maps ** inputs, HINTERNET * hInternet)
3581{
3582  if (hInternet->nb > 0)
3583    {
3584      processDownloads (hInternet);
3585      maps *content = *inputs;
3586      map *tmp1;
3587      int index = 0;
3588      while (content != NULL)
3589        {
3590          if ((tmp1 = getMap (content->content, "href")) ||
3591              (tmp1 = getMap (content->content, "xlink:href")))
3592            {
3593              if (getMap (content->content, "isCached") == NULL)
3594                {
3595                  char *fcontent;
3596                  char *mimeType = NULL;
3597                  int fsize = 0;
3598
3599                  fcontent =
3600                    (char *) malloc ((hInternet->ihandle[index].nDataLen + 1)
3601                                     * sizeof (char));
3602                  if (fcontent == NULL)
3603                    {
3604                      return errorException (*m,
3605                                             _("Unable to allocate memory."),
3606                                             "InternalError", NULL,NULL);
3607                    }
3608                  size_t dwRead;
3609                  InternetReadFile (hInternet->ihandle[index],
3610                                    (LPVOID) fcontent,
3611                                    hInternet->ihandle[index].nDataLen,
3612                                    &dwRead);
3613                  fcontent[hInternet->ihandle[index].nDataLen] = 0;
3614                  fsize = hInternet->ihandle[index].nDataLen;
3615                  mimeType =
3616                    strdup ((char *) hInternet->ihandle[index].mimeType);
3617
3618                  map *tmpMap = getMapOrFill (&content->content, "value", "");
3619                  free (tmpMap->value);
3620                  tmpMap->value =
3621                    (char *) malloc ((fsize + 1) * sizeof (char));
3622                  if (tmpMap->value == NULL)
3623                    {
3624                      return errorException (*m,
3625                                             _("Unable to allocate memory."),
3626                                             "InternalError", NULL,NULL);
3627                    }
3628                  memcpy (tmpMap->value, fcontent,
3629                          (fsize + 1) * sizeof (char));
3630
3631                  char ltmp1[256];
3632                  sprintf (ltmp1, "%d", fsize);
3633                  addToMap (content->content, "size", ltmp1);
3634                  addToCache (*m, tmp1->value, fcontent, mimeType, fsize);
3635                  free (fcontent);
3636                  free (mimeType);
3637                }
3638              index++;
3639            }
3640          content = content->next;
3641        }
3642    }
3643}
3644
3645/**
3646 * loadRemoteFile:
3647 * Try to load file from cache or download a remote file if not in cache
3648 */
3649int
3650loadRemoteFile (maps ** m, map ** content, HINTERNET * hInternet, char *url)
3651{
3652  char *fcontent;
3653  char *cached = isInCache (*m, url);
3654  char *mimeType = NULL;
3655  int fsize = 0;
3656  if (cached != NULL)
3657    {
3658      struct stat f_status;
3659      int s = stat (cached, &f_status);
3660      if (s == 0)
3661        {
3662          fcontent = (char *) malloc (sizeof (char) * (f_status.st_size + 1));
3663          FILE *f = fopen (cached, "rb");
3664          fread (fcontent, f_status.st_size, 1, f);
3665          fsize = f_status.st_size;
3666          fcontent[fsize] = 0;
3667          fclose (f);
3668        }
3669      cached[strlen (cached) - 1] = 'm';
3670      s = stat (cached, &f_status);
3671      if (s == 0)
3672        {
3673          mimeType = (char *) malloc (sizeof (char) * (f_status.st_size + 1));
3674          FILE *f = fopen (cached, "rb");
3675          fread (mimeType, f_status.st_size, 1, f);
3676          mimeType[f_status.st_size] = 0;
3677          fclose (f);
3678        }
3679    }
3680  else
3681    {
3682      hInternet->waitingRequests[hInternet->nb] = strdup (url);
3683      InternetOpenUrl (hInternet, hInternet->waitingRequests[hInternet->nb],
3684                       NULL, 0, INTERNET_FLAG_NO_CACHE_WRITE, 0);
3685      return 0;
3686    }
3687  if (fsize == 0)
3688    {
3689      return errorException (*m, _("Unable to download the file."),
3690                             "InternalError", NULL,NULL);
3691    }
3692  if (mimeType != NULL)
3693    {
3694      addToMap (*content, "fmimeType", mimeType);
3695    }
3696
3697  map *tmpMap = getMapOrFill (content, "value", "");
3698
3699  free (tmpMap->value);
3700  tmpMap->value = (char *) malloc ((fsize + 1) * sizeof (char));
3701  if (tmpMap->value == NULL)
3702    return errorException (*m, _("Unable to allocate memory."),
3703                           "InternalError", NULL,NULL);
3704  memcpy (tmpMap->value, fcontent, (fsize + 1) * sizeof (char));
3705
3706  char ltmp1[256];
3707  sprintf (ltmp1, "%d", fsize);
3708  addToMap (*content, "size", ltmp1);
3709  if (cached == NULL)
3710    addToCache (*m, url, fcontent, mimeType, fsize);
3711  else
3712    addToMap (*content, "isCached", "true");
3713  free (fcontent);
3714  free (mimeType);
3715  free (cached);
3716  return 0;
3717}
3718
3719int
3720errorException (maps * m, const char *message, const char *errorcode,
3721                const char *locator,FCGX_Stream * out)
3722{
3723  map *errormap = createMap ("text", message);
3724  addToMap (errormap, "code", errorcode);
3725  if (locator != NULL)
3726    addToMap (errormap, "locator", locator);
3727  else
3728    addToMap (errormap, "locator", "NULL");
3729  printExceptionReportResponse (m, errormap,out);
3730  freeMap (&errormap);
3731  free (errormap);
3732  return -1;
3733}
3734
3735
3736char *
3737readVSIFile (maps * conf, const char *dataSource)
3738{
3739  VSILFILE *fichier = VSIFOpenL (dataSource, "rb");
3740  VSIStatBufL file_status;
3741  VSIStatL (dataSource, &file_status);
3742  if (fichier == NULL)
3743    {
3744      char tmp[1024];
3745      sprintf (tmp,
3746               "Failed to open file %s for reading purpose. File seems empty %d.",
3747               dataSource, file_status.st_size);
3748      setMapInMaps (conf, "lenv", "message", tmp);
3749      return NULL;
3750    }
3751  char *res1 = (char *) malloc (file_status.st_size * sizeof (char));
3752  VSIFReadL (res1, 1, file_status.st_size * sizeof (char), fichier);
3753  res1[file_status.st_size - 1] = 0;
3754  VSIFCloseL (fichier);
3755  VSIUnlink (dataSource);
3756  return res1;
3757}
3758
3759void
3760parseIdentifier (maps * conf, char *conf_dir, char *identifier, char *buffer)
3761{
3762  char *saveptr1;
3763  char *tmps1 = strtok_r (identifier, ".", &saveptr1);
3764  int level = 0;
3765  char key[25];
3766  char levels[18];
3767  while (tmps1 != NULL)
3768    {
3769      char *test = zStrdup (tmps1);
3770      char *tmps2 = (char *) malloc ((strlen (test) + 2) * sizeof (char));
3771      sprintf (key, "sprefix_%d", level);
3772      sprintf (tmps2, "%s.", test);
3773      sprintf (levels, "%d", level);
3774      setMapInMaps (conf, "lenv", "level", levels);
3775      setMapInMaps (conf, "lenv", key, tmps2);
3776      free (tmps2);
3777      free (test);
3778      level++;
3779      tmps1 = strtok_r (NULL, ".", &saveptr1);
3780    }
3781  int i = 0;
3782  sprintf (buffer, "%s", conf_dir);
3783  for (i = 0; i < level; i++)
3784    {
3785      char *tmp0 = zStrdup (buffer);
3786      sprintf (key, "sprefix_%d", i);
3787      map *tmp00 = getMapFromMaps (conf, "lenv", key);
3788      if (tmp00 != NULL)
3789        sprintf (buffer, "%s/%s", tmp0, tmp00->value);
3790      free (tmp0);
3791      buffer[strlen (buffer) - 1] = 0;
3792      if (i + 1 < level)
3793        {
3794          map *tmpMap = getMapFromMaps (conf, "lenv", "metapath");
3795          if (tmpMap == NULL || strlen (tmpMap->value) == 0)
3796            {
3797              char *tmp01 = zStrdup (tmp00->value);
3798              tmp01[strlen (tmp01) - 1] = 0;
3799              setMapInMaps (conf, "lenv", "metapath", tmp01);
3800              free (tmp01);
3801              tmp01 = NULL;
3802            }
3803          else
3804            {
3805              if (tmp00 != NULL && tmpMap != NULL)
3806                {
3807                  char *tmp00s = zStrdup (tmp00->value);
3808                  tmp00s[strlen (tmp00s) - 1] = 0;
3809                  char *value =
3810                    (char *)
3811                    malloc ((strlen (tmp00s) + strlen (tmpMap->value) +
3812                             2) * sizeof (char));
3813                  sprintf (value, "%s/%s", tmpMap->value, tmp00s);
3814                  setMapInMaps (conf, "lenv", "metapath", value);
3815                  free (value);
3816                  free (tmp00s);
3817                  value = NULL;
3818                }
3819            }
3820        }
3821      else
3822        {
3823          char *tmp01 = zStrdup (tmp00->value);
3824          tmp01[strlen (tmp01) - 1] = 0;
3825          setMapInMaps (conf, "lenv", "Identifier", tmp01);
3826          free (tmp01);
3827        }
3828    }
3829  char *tmp0 = zStrdup (buffer);
3830  sprintf (buffer, "%s.zcfg", tmp0);
3831  free (tmp0);
3832}
3833
3834int
3835updateStatus (maps * conf, const int percentCompleted, const char *message)
3836{
3837  char tmp[4];
3838  snprintf (tmp, 4, "%d", percentCompleted);
3839  setMapInMaps (conf, "lenv", "status", tmp);
3840  setMapInMaps (conf, "lenv", "message", message);
3841  return _updateStatus (conf);
3842}
3843
3844char *
3845getInputValue (maps * inputs, const char *parameterName,
3846               size_t * numberOfBytes)
3847{
3848  map *res = getMapFromMaps (inputs, parameterName, "value");
3849  if (res != NULL)
3850    {
3851      map *size = getMapFromMaps (inputs, parameterName, "size");
3852      if (size != NULL)
3853        {
3854          *numberOfBytes = (size_t) atoi (size->value);
3855          return res->value;
3856        }
3857      else
3858        {
3859          *numberOfBytes = strlen (res->value);
3860          return res->value;
3861        }
3862    }
3863  return NULL;
3864}
3865
3866int
3867setOutputValue (maps * outputs, const char *parameterName, char *data,
3868                size_t numberOfBytes)
3869{
3870  if (numberOfBytes == -1)
3871    {
3872      setMapInMaps (outputs, parameterName, "value", data);
3873    }
3874  else
3875    {
3876      char size[1024];
3877      map *tmp = getMapFromMaps (outputs, parameterName, "value");
3878      free (tmp->value);
3879      tmp->value = (char *) malloc ((numberOfBytes + 1) * sizeof (char));
3880      memcpy (tmp->value, data, numberOfBytes);
3881      sprintf (size, "%lu", numberOfBytes);
3882      setMapInMaps (outputs, parameterName, "size", size);
3883    }
3884  return 0;
3885}
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