[zoo-project] 01/02: Imported Upstream version 1.5.0

Angelos Tzotsos kalxas-guest at moszumanska.debian.org
Sat Jun 11 21:23:22 UTC 2016


This is an automated email from the git hooks/post-receive script.

kalxas-guest pushed a commit to branch master
in repository zoo-project.

commit 4e4969123f5ff7869fa14cbae43f978369ebe32b
Author: Angelos Tzotsos <gcpp.kalxas at gmail.com>
Date:   Sun Jun 12 00:12:03 2016 +0300

    Imported Upstream version 1.5.0
---
 testing/README                                     |   30 +
 testing/extractExceptionInfo.xsl                   |   14 +
 testing/extractStatusLocation.xsl                  |   15 +
 testing/requests/dp.xml                            |    4 +
 testing/requests/igml_o.xml                        |   19 +
 testing/requests/ijson_o.xml                       |   19 +
 testing/requests/ir_o.xml                          |   17 +
 testing/requests/ir_o_async.xml                    |   17 +
 testing/requests/ir_or.xml                         |   17 +
 testing/requests/ir_or_async.xml                   |   17 +
 testing/requests/irb_o.xml                         |   22 +
 testing/requests/irb_o_async.xml                   |   22 +
 testing/requests/irb_or.xml                        |   22 +
 testing/requests/irb_or_async.xml                  |   22 +
 testing/run.sh                                     |  255 +
 thirds/cgic206/Makefile                            |   41 +
 thirds/cgic206/capture.c                           |   12 +
 thirds/cgic206/cgic.c                              | 2556 ++++++
 thirds/cgic206/cgic.h                              |  457 ++
 thirds/cgic206/cgic.html                           | 2116 +++++
 thirds/cgic206/cgictest.c                          |  222 +
 thirds/cgic206/debian/changelog                    |   32 +
 thirds/cgic206/debian/compat                       |    1 +
 thirds/cgic206/debian/control                      |   35 +
 thirds/cgic206/debian/copyright                    |   28 +
 thirds/cgic206/debian/libcgic-dev.docs             |    1 +
 thirds/cgic206/debian/libcgic-dev.examples         |    2 +
 thirds/cgic206/debian/libcgic-dev.install          |    2 +
 thirds/cgic206/debian/libcgic-dev.links            |    1 +
 thirds/cgic206/debian/rules                        |    7 +
 thirds/cgic206/debian/watch                        |    4 +
 thirds/cgic206/license.txt                         |  109 +
 thirds/cgic206/makefile.vc                         |   35 +
 thirds/cgic206/readme.txt                          |   14 +
 thirds/cgic206/support.txt                         |   46 +
 thirds/dirent-win32/dirent.h                       |  373 +
 thirds/include/unistd.h                            |   41 +
 thirds/otb2zcfg/CMakeLists.txt                     |   14 +
 thirds/otb2zcfg/README.txt                         |   17 +
 thirds/otb2zcfg/otb2zcfg.cxx                       |  396 +
 thirds/saga2zcfg/Makefile                          |   14 +
 thirds/saga2zcfg/saga2zcfg.c                       |  403 +
 zoo-project/COMMITTERS                             |   30 +
 zoo-project/HISTORY.txt                            |  131 +
 zoo-project/LICENSE                                |  166 +
 zoo-project/zoo-api/java/Makefile                  |   35 +
 zoo-project/zoo-api/java/ZOO.java                  |   10 +
 zoo-project/zoo-api/java/zoo-api.c                 |   31 +
 zoo-project/zoo-api/js/ZOO-api.js                  | 6322 +++++++++++++++
 zoo-project/zoo-api/js/ZOO-proj4js.js              |  258 +
 zoo-project/zoo-client/lib/js/wps-client/utils.js  |   74 +
 .../zoo-client/lib/js/wps-client/wps-payload.js    |  292 +
 zoo-project/zoo-client/lib/js/wps-client/zoo.js    | 1003 +++
 .../lib/tpl/payload_DescribeProcess.mustache       |    5 +
 .../lib/tpl/payload_DescribeProcess2.mustache      |   14 +
 .../zoo-client/lib/tpl/payload_Dismiss.mustache    |   10 +
 .../zoo-client/lib/tpl/payload_Execute.mustache    |   84 +
 .../zoo-client/lib/tpl/payload_Execute2.mustache   |   62 +
 .../lib/tpl/payload_GetCapabilities.mustache       |    5 +
 .../lib/tpl/payload_GetCapabilities2.mustache      |    7 +
 zoo-project/zoo-kernel/Doxyfile                    | 2303 ++++++
 zoo-project/zoo-kernel/LICENSE                     |   21 +
 zoo-project/zoo-kernel/Makefile.in                 |  117 +
 zoo-project/zoo-kernel/README                      |    3 +
 zoo-project/zoo-kernel/ZOOMakefile.opts.in         |   97 +
 zoo-project/zoo-kernel/autom4te.cache/output.0     | 8345 ++++++++++++++++++++
 zoo-project/zoo-kernel/autom4te.cache/requests     |   77 +
 zoo-project/zoo-kernel/autom4te.cache/traces.0     |  778 ++
 zoo-project/zoo-kernel/caching.c                   |  381 +
 zoo-project/zoo-kernel/caching.h                   |   40 +
 zoo-project/zoo-kernel/config.log                  | 5747 ++++++++++++++
 zoo-project/zoo-kernel/config.status               | 1002 +++
 zoo-project/zoo-kernel/configure                   | 8345 ++++++++++++++++++++
 zoo-project/zoo-kernel/configure.ac                |  776 ++
 zoo-project/zoo-kernel/doc/index.dox               |   20 +
 zoo-project/zoo-kernel/locale/po/en_US.utf8.po     |  171 +
 zoo-project/zoo-kernel/locale/po/fr_FR.utf8.po     |  174 +
 zoo-project/zoo-kernel/locale/po/ja_JP.utf8.po     |  174 +
 zoo-project/zoo-kernel/locale/po/messages.po       |  364 +
 zoo-project/zoo-kernel/locale/po/messages.po.orig  |  364 +
 zoo-project/zoo-kernel/locale/po/messages.po.save  |  328 +
 zoo-project/zoo-kernel/locale/po/new.pot           |  329 +
 zoo-project/zoo-kernel/main.cfg                    |   32 +
 zoo-project/zoo-kernel/main_conf_read.l            |   65 +
 zoo-project/zoo-kernel/main_conf_read.y            |  175 +
 zoo-project/zoo-kernel/makefile.vc                 |  104 +
 zoo-project/zoo-kernel/messages.po.new             |  328 +
 zoo-project/zoo-kernel/mimetypes.h                 |  837 ++
 zoo-project/zoo-kernel/nmake.opt                   |   89 +
 zoo-project/zoo-kernel/otbZooWatcher.cxx           |   70 +
 zoo-project/zoo-kernel/otbZooWatcher.h             |   91 +
 zoo-project/zoo-kernel/request_parser.c            | 1762 +++++
 zoo-project/zoo-kernel/request_parser.h            |   55 +
 zoo-project/zoo-kernel/response_print.c            | 2847 +++++++
 zoo-project/zoo-kernel/response_print.h            |  233 +
 zoo-project/zoo-kernel/server_internal.c           | 1203 +++
 zoo-project/zoo-kernel/server_internal.h           |   73 +
 zoo-project/zoo-kernel/service.c                   | 1451 ++++
 zoo-project/zoo-kernel/service.h                   |  335 +
 zoo-project/zoo-kernel/service_conf.l              |  102 +
 zoo-project/zoo-kernel/service_conf.y              |  876 ++
 zoo-project/zoo-kernel/service_internal.c          |  734 ++
 zoo-project/zoo-kernel/service_internal.h          |  131 +
 zoo-project/zoo-kernel/service_internal_java.c     |  732 ++
 zoo-project/zoo-kernel/service_internal_java.h     |   52 +
 zoo-project/zoo-kernel/service_internal_js.c       |  985 +++
 zoo-project/zoo-kernel/service_internal_js.h       |   62 +
 zoo-project/zoo-kernel/service_internal_ms.c       | 1173 +++
 zoo-project/zoo-kernel/service_internal_ms.h       |   62 +
 zoo-project/zoo-kernel/service_internal_otb.c      |  483 ++
 zoo-project/zoo-kernel/service_internal_otb.h      |   53 +
 zoo-project/zoo-kernel/service_internal_perl.c     |  201 +
 zoo-project/zoo-kernel/service_internal_perl.h     |   64 +
 zoo-project/zoo-kernel/service_internal_php.c      |  455 ++
 zoo-project/zoo-kernel/service_internal_php.h      |   43 +
 zoo-project/zoo-kernel/service_internal_python.c   |  686 ++
 zoo-project/zoo-kernel/service_internal_python.h   |   52 +
 zoo-project/zoo-kernel/service_internal_ruby.c     |  486 ++
 zoo-project/zoo-kernel/service_internal_ruby.h     |   78 +
 zoo-project/zoo-kernel/service_internal_saga.c     | 1186 +++
 zoo-project/zoo-kernel/service_internal_saga.h     |   35 +
 zoo-project/zoo-kernel/service_loader.c            |  272 +
 zoo-project/zoo-kernel/service_yaml.c              |  459 ++
 zoo-project/zoo-kernel/sql/schema.sql              |   69 +
 zoo-project/zoo-kernel/sqlapi.c                    |  477 ++
 zoo-project/zoo-kernel/sqlapi.h                    |   51 +
 zoo-project/zoo-kernel/ulinet.c                    |  463 ++
 zoo-project/zoo-kernel/ulinet.h                    |  176 +
 zoo-project/zoo-kernel/zcfg2yaml                   |  Bin 0 -> 229828 bytes
 zoo-project/zoo-kernel/zcfg2yaml.c                 |   44 +
 zoo-project/zoo-kernel/zoo_loader.c                |  410 +
 zoo-project/zoo-kernel/zoo_loader.cgi              |  Bin 0 -> 594772 bytes
 zoo-project/zoo-kernel/zoo_service_loader.c        | 2258 ++++++
 zoo-project/zoo-services/arithmetics/Makefile      |    8 +
 .../zoo-services/arithmetics/cgi-env/Multiply.zcfg |   43 +
 zoo-project/zoo-services/arithmetics/makefile.vc   |   12 +
 .../zoo-services/arithmetics/test_service.c        |   42 +
 zoo-project/zoo-services/cgal/Makefile             |   19 +
 zoo-project/zoo-services/cgal/cgal_service.c       |   81 +
 zoo-project/zoo-services/cgal/cgal_service.h       |   45 +
 .../zoo-services/cgal/cgi-env/Delaunay.zcfg        |   55 +
 zoo-project/zoo-services/cgal/cgi-env/Voronoi.zcfg |   59 +
 zoo-project/zoo-services/cgal/delaunay.c           |  187 +
 zoo-project/zoo-services/cgal/voronoi.c            |  228 +
 zoo-project/zoo-services/gdal/contour/Makefile     |   13 +
 .../gdal/contour/cgi-env/Gdal_Contour.zcfg         |   65 +
 zoo-project/zoo-services/gdal/contour/makefile.vc  |   25 +
 zoo-project/zoo-services/gdal/contour/service.c    |  401 +
 zoo-project/zoo-services/gdal/dem/Makefile         |   15 +
 .../zoo-services/gdal/dem/cgi-env/Gdal_Dem.zcfg    |   56 +
 zoo-project/zoo-services/gdal/dem/makefile.vc      |   23 +
 zoo-project/zoo-services/gdal/dem/service.c        | 2899 +++++++
 zoo-project/zoo-services/gdal/grid/Makefile        |   15 +
 .../zoo-services/gdal/grid/cgi-env/Gdal_Grid.zcfg  |   69 +
 zoo-project/zoo-services/gdal/grid/service.c       | 1258 +++
 .../gdal/ndvi/cgi-env/ExtractNDVI.zcfg             |   58 +
 zoo-project/zoo-services/gdal/ndvi/cgi-env/ndvi.py |  107 +
 zoo-project/zoo-services/gdal/profile/Makefile     |   15 +
 .../gdal/profile/cgi-env/GdalExtractProfile.zcfg   |   57 +
 zoo-project/zoo-services/gdal/profile/makefile.vc  |   23 +
 zoo-project/zoo-services/gdal/profile/service.c    |  194 +
 zoo-project/zoo-services/gdal/translate/Makefile   |   16 +
 .../gdal/translate/cgi-env/Gdal_Translate.zcfg     |   61 +
 .../zoo-services/gdal/translate/makefile.vc        |   23 +
 zoo-project/zoo-services/gdal/translate/service.c  |  925 +++
 zoo-project/zoo-services/gdal/warp/Makefile        |   15 +
 .../zoo-services/gdal/warp/cgi-env/Gdal_Warp.zcfg  |  129 +
 zoo-project/zoo-services/gdal/warp/makefile.vc     |   23 +
 zoo-project/zoo-services/gdal/warp/service.c       | 2150 +++++
 zoo-project/zoo-services/hello-fortran/LICENSE     |   21 +
 zoo-project/zoo-services/hello-fortran/Makefile    |    5 +
 .../zoo-services/hello-fortran/cgi-env/hellof.zcfg |   40 +
 zoo-project/zoo-services/hello-fortran/service.f   |   44 +
 zoo-project/zoo-services/hello-java/HelloJava.java |   53 +
 zoo-project/zoo-services/hello-java/Makefile       |    5 +
 .../hello-java/cgi-env/HelloWorldJava.zcfg         |   33 +
 .../hello-java/cgi-env/JavaLongProcess.zcfg        |   33 +
 zoo-project/zoo-services/hello-js/cgi-env/hello.js |   36 +
 .../zoo-services/hello-js/cgi-env/hellojs.zcfg     |   40 +
 .../zoo-services/hello-js/cgi-env/hellojs1.zcfg    |   40 +
 zoo-project/zoo-services/hello-perl/Hello.pl       |   32 +
 .../zoo-services/hello-perl/cgi-env/HelloPL.zcfg   |   39 +
 .../zoo-services/hello-php/cgi-env/HelloPHP.zcfg   |   33 +
 .../zoo-services/hello-php/cgi-env/hello.php       |   34 +
 .../zoo-services/hello-py/cgi-env/HelloPy.zcfg     |   47 +
 .../zoo-services/hello-py/cgi-env/test_service.py  |   31 +
 .../ogr/base-vect-ops-py/cgi-env/BoundaryPy.zcfg   |   56 +
 .../ogr/base-vect-ops-py/cgi-env/BufferPy.zcfg     |   68 +
 .../ogr/base-vect-ops-py/cgi-env/CentroidPy.zcfg   |   43 +
 .../ogr/base-vect-ops-py/cgi-env/ConvexHullPy.zcfg |   51 +
 .../ogr/base-vect-ops-py/cgi-env/DifferencePy.zcfg |   75 +
 .../base-vect-ops-py/cgi-env/IntersectionPy.zcfg   |   75 +
 .../base-vect-ops-py/cgi-env/SymDifferencePy.zcfg  |   83 +
 .../ogr/base-vect-ops-py/cgi-env/UnionPy.zcfg      |   73 +
 .../ogr/base-vect-ops-py/cgi-env/ogr_sp.py         |  394 +
 .../zoo-services/ogr/base-vect-ops/Makefile        |   19 +
 .../ogr/base-vect-ops/cgi-env/Boundary.zcfg        |   60 +
 .../ogr/base-vect-ops/cgi-env/Buffer.zcfg          |   70 +
 .../ogr/base-vect-ops/cgi-env/Centroid.zcfg        |   55 +
 .../ogr/base-vect-ops/cgi-env/Contains.zcfg        |   57 +
 .../ogr/base-vect-ops/cgi-env/ConvexHull.zcfg      |   54 +
 .../ogr/base-vect-ops/cgi-env/Crosses.zcfg         |   57 +
 .../ogr/base-vect-ops/cgi-env/Difference.zcfg      |   75 +
 .../ogr/base-vect-ops/cgi-env/Disjoint.zcfg        |   57 +
 .../ogr/base-vect-ops/cgi-env/Distance.zcfg        |   71 +
 .../ogr/base-vect-ops/cgi-env/Equals.zcfg          |   57 +
 .../ogr/base-vect-ops/cgi-env/GetArea.zcfg         |   50 +
 .../ogr/base-vect-ops/cgi-env/Intersection.zcfg    |   75 +
 .../ogr/base-vect-ops/cgi-env/Intersects.zcfg      |   57 +
 .../ogr/base-vect-ops/cgi-env/IsSimple.zcfg        |   37 +
 .../ogr/base-vect-ops/cgi-env/IsValid.zcfg         |   37 +
 .../ogr/base-vect-ops/cgi-env/Simplify.zcfg        |   61 +
 .../ogr/base-vect-ops/cgi-env/SymDifference.zcfg   |   75 +
 .../ogr/base-vect-ops/cgi-env/Touches.zcfg         |   57 +
 .../ogr/base-vect-ops/cgi-env/Union.zcfg           |   75 +
 .../ogr/base-vect-ops/cgi-env/Within.zcfg          |   57 +
 .../ogr/base-vect-ops/locale/po/fr_FR.utf8.po      |  320 +
 .../ogr/base-vect-ops/locale/po/ja_JP.utf8.po      |  308 +
 .../ogr/base-vect-ops/locale/po/messages.po        |  299 +
 .../zoo-services/ogr/base-vect-ops/makefile.vc     |   25 +
 .../zoo-services/ogr/base-vect-ops/service.c       | 1472 ++++
 zoo-project/zoo-services/ogr/ogr2ogr/Makefile      |   14 +
 .../zoo-services/ogr/ogr2ogr/cgi-env/Ogr2Ogr.zcfg  |   62 +
 zoo-project/zoo-services/ogr/ogr2ogr/makefile.vc   |   11 +
 zoo-project/zoo-services/ogr/ogr2ogr/service.c     | 1303 +++
 .../zoo-services/openoffice/cgi-env/Exporter.py    |   99 +
 .../openoffice/cgi-env/OdtConverter.zcfg           |   43 +
 .../zoo-services/openoffice/cgi-env/Xml2Pdf.zcfg   |   39 +
 .../zoo-services/openoffice/cgi-env/oo_service.py  |  144 +
 zoo-project/zoo-services/qrencode/Makefile         |   10 +
 .../zoo-services/qrencode/cgi-env/QREncode.zcfg    |   69 +
 zoo-project/zoo-services/qrencode/makefile.vc      |   23 +
 zoo-project/zoo-services/qrencode/qrenc-service.c  | 1215 +++
 zoo-project/zoo-services/utils/registry/Makefile   |   24 +
 .../utils/registry/cgi-env/GetFromRegistry.zcfg    |   36 +
 .../zoo-services/utils/registry/makefile.vc        |   24 +
 zoo-project/zoo-services/utils/registry/service.c  |  138 +
 zoo-project/zoo-services/utils/status/Makefile     |   12 +
 .../utils/status/cgi-env/GetStatus.zcfg            |   43 +
 .../zoo-services/utils/status/cgi-env/demo.zcfg    |   32 +
 .../utils/status/cgi-env/longProcess.zcfg          |   36 +
 .../zoo-services/utils/status/cgi-env/service.py   |   14 +
 .../utils/status/cgi-env/updateStatus.xsl          |   26 +
 .../utils/status/locale/po/fr_FR.utf8.po           |   91 +
 .../utils/status/locale/po/messages.po             |   82 +
 zoo-project/zoo-services/utils/status/makefile.vc  |   10 +
 zoo-project/zoo-services/utils/status/service.c    |  153 +
 zoo-project/zoo-services/utils/status/test.sh      |   19 +
 248 files changed, 87453 insertions(+)

diff --git a/testing/README b/testing/README
new file mode 100644
index 0000000..7611f41
--- /dev/null
+++ b/testing/README
@@ -0,0 +1,30 @@
+Please use the following syntaxe:
+
+  ./run.sh <WPSInstance> <ServiceName>
+
+where <WPSInstance> should be the url to a WPS Server and <ServiceName> should 
+be the service name you want to run tests with.
+
+For instance to test the Buffer service on a localhost WPS server, use the 
+following command:
+
+  ./run.sh http://localhost/cgi-bin/zoo_loader.cgi Buffer
+
+
+Important note:  sometimes XML validation failed because xmllint is unable to download
+a file required to validate. In such case, you can use the file /etc/xml/catalog on your
+local machine to use a local copy of the missing file.
+
+For instance, in case xml.xsd can't be downloaded, then you can download a copy using
+this url http://www.w3.org/2001/xml.xsd, store it in /etc/schemas directory and then 
+use the following /etc/xml/catalog file:
+
+<?xml version="1.0"?>
+<!DOCTYPE catalog PUBLIC "-//OASIS//DTD Entity Resolution XML Catalog V1.0//EN" "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd">
+<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+<rewriteSystem systemIdStartString="http://www.w3.org/2001/xml.xsd"
+                rewritePrefix="file:///etc/schemas/xml.xsd" />
+</catalog>
+
+Obviously, you can do similar manipulation for the OGC schemas to use local files 
+rather than downloading them for each tests.
diff --git a/testing/extractExceptionInfo.xsl b/testing/extractExceptionInfo.xsl
new file mode 100644
index 0000000..af1b699
--- /dev/null
+++ b/testing/extractExceptionInfo.xsl
@@ -0,0 +1,14 @@
+<?xml version="1.0"  encoding="UTF-8"?>
+
+<xsl:stylesheet version="1.0"
+                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+		xmlns:ows="http://www.opengis.net/ows/1.1"
+		xmlns:xlink="http://www.w3.org/1999/xlink">
+
+  <xsl:output method="text"/>
+
+  <xsl:template match="*/*">
+      <xsl:text>Code: </xsl:text><xsl:value-of select="@exceptionCode" /><xsl:text>, Locator: </xsl:text><xsl:value-of select="@locator" />
+  </xsl:template> 
+
+</xsl:stylesheet>
diff --git a/testing/extractStatusLocation.xsl b/testing/extractStatusLocation.xsl
new file mode 100644
index 0000000..8d410a9
--- /dev/null
+++ b/testing/extractStatusLocation.xsl
@@ -0,0 +1,15 @@
+<?xml version="1.0"  encoding="UTF-8"?>
+
+<xsl:stylesheet version="1.0"
+                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+		xmlns:ows="http://www.opengis.net/ows/1.1"
+		xmlns:wps="http://www.opengis.net/wps/1.0.0"
+		xmlns:xlink="http://www.w3.org/1999/xlink">
+
+  <xsl:output method="text"/>
+
+  <xsl:template match="wps:ExecuteResponse">
+    <xsl:value-of select="@statusLocation" />
+  </xsl:template> 
+
+</xsl:stylesheet>
diff --git a/testing/requests/dp.xml b/testing/requests/dp.xml
new file mode 100644
index 0000000..00e3f1e
--- /dev/null
+++ b/testing/requests/dp.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<DescribeProcess xmlns="http://www.opengis.net/wps/1.0.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wps/1.0.0 ../wpsDescribeProcess_request.xsd" service="WPS" version="1.0.0" language="en-US">
+	<ows:Identifier>ServiceName</ows:Identifier>
+</DescribeProcess>
diff --git a/testing/requests/igml_o.xml b/testing/requests/igml_o.xml
new file mode 100644
index 0000000..cc5b828
--- /dev/null
+++ b/testing/requests/igml_o.xml
@@ -0,0 +1,19 @@
+<wps:Execute service="WPS" version="1.0.0" xmlns:wps="http://www.opengis.net/wps/1.0.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wps/1.0.0 ../wpsExecute_request.xsd">
+<ows:Identifier>ServiceName</ows:Identifier>
+<wps:DataInputs>
+<wps:Input>
+<ows:Identifier>InputName</ows:Identifier>
+<ows:Title>Playground area</ows:Title>
+<wps:Data>
+<wps:ComplexData mimeType="text/xml"><wfs:FeatureCollection xmlns="http://www.opengis.net/wfs" xmlns:wfs="http://www.opengis.net/wfs" xmlns:topp="http://www.openplans.org/topp" xmlns:gml="http://www.opengis.net/gml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.openplans.org/topp http://www.zoo-project.org:8082/geoserver/wfs?service=WFS&version=1.0.0&request=DescribeFeatureType&typeName=topp%3Astates http://www.opengis.net/wfs http://www [...]
+</wps:Data>
+</wps:Input>
+</wps:DataInputs>
+<wps:ResponseForm>
+<wps:ResponseDocument>
+<wps:Output>
+<ows:Identifier>Result</ows:Identifier>
+</wps:Output>
+</wps:ResponseDocument>
+</wps:ResponseForm>
+</wps:Execute>
diff --git a/testing/requests/ijson_o.xml b/testing/requests/ijson_o.xml
new file mode 100644
index 0000000..d430059
--- /dev/null
+++ b/testing/requests/ijson_o.xml
@@ -0,0 +1,19 @@
+<wps:Execute service="WPS" version="1.0.0" xmlns:wps="http://www.opengis.net/wps/1.0.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wps/1.0.0 ../wpsExecute_request.xsd">
+<ows:Identifier>ServiceName</ows:Identifier>
+<wps:DataInputs>
+<wps:Input>
+<ows:Identifier>InputPolygon</ows:Identifier>
+<ows:Title>Playground area</ows:Title>
+<wps:Data>
+<wps:ComplexData mimeType="application/json">{"type":"Polygon","coordinates":[[[-102.036758,36.988972],[-106.860657,36.989491],[-109.047821,36.996643],[-109.055199,38.24493],[-109.052864,39.518196],[-109.050591,40.210545],[-109.047638,40.998474],[-107.918037,41.00341],[-104.051201,41.003227],[-102.620789,41.000225],[-102.047279,40.998077],[-102.04557,40.697323],[-102.036758,36.988972]]]}</wps:ComplexData>
+</wps:Data>
+</wps:Input>
+</wps:DataInputs>
+<wps:ResponseForm>
+<wps:ResponseDocument>
+<wps:Output>
+<ows:Identifier>Result</ows:Identifier>
+</wps:Output>
+</wps:ResponseDocument>
+</wps:ResponseForm>
+</wps:Execute>
diff --git a/testing/requests/ir_o.xml b/testing/requests/ir_o.xml
new file mode 100644
index 0000000..935f5ed
--- /dev/null
+++ b/testing/requests/ir_o.xml
@@ -0,0 +1,17 @@
+<wps:Execute service="WPS" version="1.0.0" xmlns:wps="http://www.opengis.net/wps/1.0.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wps/1.0.0 ../wpsExecute_request.xsd">
+<ows:Identifier>ServiceName</ows:Identifier>
+<wps:DataInputs>
+<wps:Input>
+<ows:Identifier>InputPolygon</ows:Identifier>
+<ows:Title>Playground area</ows:Title>
+<wps:Reference xlink:href="http://www.zoo-project.org:8082/geoserver/ows?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.0.0&typename=topp:states&SRS=EPSG:4326&FeatureID=states.15" />
+</wps:Input>
+</wps:DataInputs>
+<wps:ResponseForm>
+<wps:ResponseDocument>
+<wps:Output>
+<ows:Identifier>Result</ows:Identifier>
+</wps:Output>
+</wps:ResponseDocument>
+</wps:ResponseForm>
+</wps:Execute>
diff --git a/testing/requests/ir_o_async.xml b/testing/requests/ir_o_async.xml
new file mode 100644
index 0000000..cc00ca1
--- /dev/null
+++ b/testing/requests/ir_o_async.xml
@@ -0,0 +1,17 @@
+<wps:Execute service="WPS" version="1.0.0" xmlns:wps="http://www.opengis.net/wps/1.0.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wps/1.0.0 ../wpsExecute_request.xsd">
+<ows:Identifier>ServiceName</ows:Identifier>
+<wps:DataInputs>
+<wps:Input>
+<ows:Identifier>InputPolygon</ows:Identifier>
+<ows:Title>Playground area</ows:Title>
+<wps:Reference xlink:href="http://www.zoo-project.org:8082/geoserver/ows?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.0.0&typename=topp:states&SRS=EPSG:4326&FeatureID=states.15" />
+</wps:Input>
+</wps:DataInputs>
+<wps:ResponseForm>
+<wps:ResponseDocument storeExecuteResponse="true" status="true">
+<wps:Output>
+<ows:Identifier>Result</ows:Identifier>
+</wps:Output>
+</wps:ResponseDocument>
+</wps:ResponseForm>
+</wps:Execute>
diff --git a/testing/requests/ir_or.xml b/testing/requests/ir_or.xml
new file mode 100644
index 0000000..3a44c19
--- /dev/null
+++ b/testing/requests/ir_or.xml
@@ -0,0 +1,17 @@
+<wps:Execute service="WPS" version="1.0.0" xmlns:wps="http://www.opengis.net/wps/1.0.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wps/1.0.0 ../wpsExecute_request.xsd">
+<ows:Identifier>ServiceName</ows:Identifier>
+<wps:DataInputs>
+<wps:Input>
+<ows:Identifier>InputPolygon</ows:Identifier>
+<ows:Title>Playground area</ows:Title>
+<wps:Reference xlink:href="http://www.zoo-project.org:8082/geoserver/ows?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.0.0&typename=topp:states&SRS=EPSG:4326&FeatureID=states.15" />
+</wps:Input>
+</wps:DataInputs>
+<wps:ResponseForm>
+<wps:ResponseDocument>
+<wps:Output asReference="true">
+<ows:Identifier>Result</ows:Identifier>
+</wps:Output>
+</wps:ResponseDocument>
+</wps:ResponseForm>
+</wps:Execute>
diff --git a/testing/requests/ir_or_async.xml b/testing/requests/ir_or_async.xml
new file mode 100644
index 0000000..b6cd538
--- /dev/null
+++ b/testing/requests/ir_or_async.xml
@@ -0,0 +1,17 @@
+<wps:Execute service="WPS" version="1.0.0" xmlns:wps="http://www.opengis.net/wps/1.0.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wps/1.0.0 ../wpsExecute_request.xsd">
+<ows:Identifier>ServiceName</ows:Identifier>
+<wps:DataInputs>
+<wps:Input>
+<ows:Identifier>InputPolygon</ows:Identifier>
+<ows:Title>Playground area</ows:Title>
+<wps:Reference xlink:href="http://www.zoo-project.org:8082/geoserver/ows?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.0.0&typename=topp:states&SRS=EPSG:4326&FeatureID=states.15" />
+</wps:Input>
+</wps:DataInputs>
+<wps:ResponseForm>
+<wps:ResponseDocument storeExecuteResponse="true" status="true">
+<wps:Output asReference="true">
+<ows:Identifier>Result</ows:Identifier>
+</wps:Output>
+</wps:ResponseDocument>
+</wps:ResponseForm>
+</wps:Execute>
diff --git a/testing/requests/irb_o.xml b/testing/requests/irb_o.xml
new file mode 100644
index 0000000..ad43aa2
--- /dev/null
+++ b/testing/requests/irb_o.xml
@@ -0,0 +1,22 @@
+<wps:Execute service="WPS" version="1.0.0" xmlns:wps="http://www.opengis.net/wps/1.0.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wps/1.0.0 ../wpsExecute_request.xsd">
+<ows:Identifier>ServiceName</ows:Identifier>
+<wps:DataInputs>
+<wps:Input>
+<ows:Identifier>InputPolygon</ows:Identifier>
+<ows:Title>Playground area</ows:Title>
+<wps:Reference xlink:href="http://www.zoo-project.org:8082/geoserver/ows" method="POST">
+<wps:Header key="Content-type" value="text/xml" />
+<wps:Body>
+<wfs:GetFeature xmlns:wfs="http://www.opengis.net/wfs" service="WFS" version="1.1.0" maxFeatures="10" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><wfs:Query typeName="states" srsName="EPSG:4326"><ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"><ogc:BBOX><ogc:PropertyName>the_geom</ogc:PropertyName><gml:Envelope xmlns:gml="http://www.opengis.net/gml" srsName="EPSG:4326"><gml:lowerCorne [...]
+</wps:Body>
+</wps:Reference>
+</wps:Input>
+</wps:DataInputs>
+<wps:ResponseForm>
+<wps:ResponseDocument>
+<wps:Output>
+<ows:Identifier>Result</ows:Identifier>
+</wps:Output>
+</wps:ResponseDocument>
+</wps:ResponseForm>
+</wps:Execute>
diff --git a/testing/requests/irb_o_async.xml b/testing/requests/irb_o_async.xml
new file mode 100644
index 0000000..5c6f7f3
--- /dev/null
+++ b/testing/requests/irb_o_async.xml
@@ -0,0 +1,22 @@
+<wps:Execute service="WPS" version="1.0.0" xmlns:wps="http://www.opengis.net/wps/1.0.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wps/1.0.0 ../wpsExecute_request.xsd">
+<ows:Identifier>ServiceName</ows:Identifier>
+<wps:DataInputs>
+<wps:Input>
+<ows:Identifier>InputPolygon</ows:Identifier>
+<ows:Title>Playground area</ows:Title>
+<wps:Reference xlink:href="http://www.zoo-project.org:8082/geoserver/ows" method="POST">
+<wps:Header key="Content-type" value="text/xml" />
+<wps:Body>
+<wfs:GetFeature xmlns:wfs="http://www.opengis.net/wfs" service="WFS" version="1.1.0" maxFeatures="10" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><wfs:Query typeName="states" srsName="EPSG:4326"><ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"><ogc:BBOX><ogc:PropertyName>the_geom</ogc:PropertyName><gml:Envelope xmlns:gml="http://www.opengis.net/gml" srsName="EPSG:4326"><gml:lowerCorne [...]
+</wps:Body>
+</wps:Reference>
+</wps:Input>
+</wps:DataInputs>
+<wps:ResponseForm>
+<wps:ResponseDocument storeExecuteResponse="true" status="true">
+<wps:Output>
+<ows:Identifier>Result</ows:Identifier>
+</wps:Output>
+</wps:ResponseDocument>
+</wps:ResponseForm>
+</wps:Execute>
diff --git a/testing/requests/irb_or.xml b/testing/requests/irb_or.xml
new file mode 100644
index 0000000..ac9f6e0
--- /dev/null
+++ b/testing/requests/irb_or.xml
@@ -0,0 +1,22 @@
+<wps:Execute service="WPS" version="1.0.0" xmlns:wps="http://www.opengis.net/wps/1.0.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wps/1.0.0 ../wpsExecute_request.xsd">
+<ows:Identifier>ServiceName</ows:Identifier>
+<wps:DataInputs>
+<wps:Input>
+<ows:Identifier>InputPolygon</ows:Identifier>
+<ows:Title>Playground area</ows:Title>
+<wps:Reference xlink:href="http://www.zoo-project.org:8082/geoserver/ows" method="POST">
+<wps:Header key="Content-type" value="text/xml" />
+<wps:Body>
+<wfs:GetFeature xmlns:wfs="http://www.opengis.net/wfs" service="WFS" version="1.1.0" maxFeatures="10" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><wfs:Query typeName="states" srsName="EPSG:4326"><ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"><ogc:BBOX><ogc:PropertyName>the_geom</ogc:PropertyName><gml:Envelope xmlns:gml="http://www.opengis.net/gml" srsName="EPSG:4326"><gml:lowerCorne [...]
+</wps:Body>
+</wps:Reference>
+</wps:Input>
+</wps:DataInputs>
+<wps:ResponseForm>
+<wps:ResponseDocument>
+<wps:Output asReference="true">
+<ows:Identifier>Result</ows:Identifier>
+</wps:Output>
+</wps:ResponseDocument>
+</wps:ResponseForm>
+</wps:Execute>
diff --git a/testing/requests/irb_or_async.xml b/testing/requests/irb_or_async.xml
new file mode 100644
index 0000000..cda070d
--- /dev/null
+++ b/testing/requests/irb_or_async.xml
@@ -0,0 +1,22 @@
+<wps:Execute service="WPS" version="1.0.0" xmlns:wps="http://www.opengis.net/wps/1.0.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wps/1.0.0 ../wpsExecute_request.xsd">
+<ows:Identifier>ServiceName</ows:Identifier>
+<wps:DataInputs>
+<wps:Input>
+<ows:Identifier>InputPolygon</ows:Identifier>
+<ows:Title>Playground area</ows:Title>
+<wps:Reference xlink:href="http://www.zoo-project.org:8082/geoserver/ows" method="POST">
+<wps:Header key="Content-type" value="text/xml" />
+<wps:Body>
+<wfs:GetFeature xmlns:wfs="http://www.opengis.net/wfs" service="WFS" version="1.1.0" maxFeatures="10" xsi:schemaLocation="http://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><wfs:Query typeName="states" srsName="EPSG:4326"><ogc:Filter xmlns:ogc="http://www.opengis.net/ogc"><ogc:BBOX><ogc:PropertyName>the_geom</ogc:PropertyName><gml:Envelope xmlns:gml="http://www.opengis.net/gml" srsName="EPSG:4326"><gml:lowerCorne [...]
+</wps:Body>
+</wps:Reference>
+</wps:Input>
+</wps:DataInputs>
+<wps:ResponseForm>
+<wps:ResponseDocument storeExecuteResponse="true" status="true">
+<wps:Output asReference="true">
+<ows:Identifier>Result</ows:Identifier>
+</wps:Output>
+</wps:ResponseDocument>
+</wps:ResponseForm>
+</wps:Execute>
diff --git a/testing/run.sh b/testing/run.sh
new file mode 100755
index 0000000..134782d
--- /dev/null
+++ b/testing/run.sh
@@ -0,0 +1,255 @@
+#!/bin/bash
+
+Usage=$(cat <<EOF
+Please use the following syntaxe:
+
+  ./run.sh <WPSInstance> <ServiceName> <Request>
+
+where <WPSInstance> should be the url to a WPS Server, <ServiceName> should 
+be the service name you want to run tests with (you can use multiple service 
+names, use quote and seperate them using space), <Request> should contain the 
+requests you want to use (you can use more than one at a time).
+
+For instance to test the Buffer service on a localhost WPS server, use the 
+following command:
+
+  ./run.sh http://localhost/cgi-bin/zoo_loader.cgi Buffer "GetCapabilities DescribeProcess Execute"
+
+EOF
+)
+
+if [ -z "$1" ] || [ -z "$2" ]; then
+    echo "$Usage"
+    exit
+fi
+
+WPSInstance=$1
+ServiceName=$2
+NBRequests=1000
+NBConcurrents=50
+pstat=0
+
+iter=0
+
+function testPostRequests {
+#
+# Tests for Execute using POST requests
+#
+    for i in $1; 
+    do
+	cat requests/${i}.xml | sed "s:ServiceName:${ServiceName}:g;s:InputName:$(cat tmp/inputName.txt):g" > tmp/${i}1.xml
+	if [ -z "$(echo $i | grep async)" ]; then
+	    postRequest "${WPSInstance}" "tmp/outputE${i}.xml" "Execute" "tmp/${i}1.xml"
+	else
+	    postRequest "${WPSInstance}" "tmp/outputE${i}.xml" "Execute" "tmp/${i}1.xml" "async"
+	fi
+	echo ""
+    done
+
+}
+
+function plotStat {
+    echo " **"
+    echo " * Plot statistics ..."
+    echo " **"
+    cp run.tsv tmp/run$1.tsv
+    sed "s:\[image\]:$2:g;s:\[file\]:$3:g" -i tmp/run$1.tsv
+    gnuplot tmp/run$1.tsv
+    cp run1.tsv tmp/run1$1.tsv
+    sed "s:\[image\]:$(echo $2 | sed "s:.jpg:1.jpg:g"):g;s:\[file\]:$3:g" -i tmp/run1$1.tsv
+    gnuplot tmp/run1$1.tsv
+}
+
+
+function kvpRequest {
+    echo " **"
+    echo " <h1> Simple KVP request start on $(date) </h1>"
+    echo " <a href='$1'>$1</a>"
+    
+    RESP=$(curl -v -o "$2" "$1" 2> tmp/temp.log; grep "< HTTP" tmp/temp.log | cut -d' ' -f3)
+    if [ "${3}" == "owsExceptionReport" ]; then
+	echo " *********************************"
+	if [ "$RESP" ==	"200" ]; then
+	    echo " ! Invalid response code ($RESP)"
+	else
+	    echo " * Valid response code ($RESP)"
+	fi
+	echo " *********************************"
+	echo " * Checking for ${3} response XML validity..."
+    	echo " * Schema: [http://schemas.opengis.net/ows/1.1.0/${3}.xsd]"
+	echo " *********************************"
+	xmllint --noout --schema http://schemas.opengis.net/ows/1.1.0/${3}.xsd "$2" 2> tmp/res${iter}.txt
+	echo " *********************************"
+	echo "Verifying that the missing / wrong argument was referenced in locator and the exceptionCode take the corresponding value ..."
+	echo -n " *********************************"
+	xsltproc ./extractExceptionInfo.xsl "$2"
+	echo " *********************************"
+    else
+	if [ "$RESP" ==	"200" ]; then
+	    echo " * Valid response code ($RESP)"
+	else
+	    echo " ! Invalid response code ($RESP)"
+	fi
+	echo " * Checking for ${3} response XML validity..."
+	echo " * Schema: [http://schemas.opengis.net/wps/1.0.0/wps${3}_response.xsd]"
+	xmllint --noout --schema http://schemas.opengis.net/wps/1.0.0/wps${3}_response.xsd "$2" 2> tmp/res${iter}.txt
+	v="$(cat tmp/res${iter}.txt | grep validates)"
+	echo ""
+    fi
+    echo " **"
+    echo " * Sending $NBRequests ${3} requests starting on $(date) ..."
+    echo " **"
+    ab -g tmp/stat${3}${iter}.plot -e tmp/stat${3}${iter}.txt -n "$NBRequests" -c "$NBConcurrents" "$1"
+    if [ "$pstat" -eq 1 ]; then
+	plotStat ${iter} tmp/stat${3}${iter}.jpg tmp/stat${3}${iter}.plot
+    fi
+    iter=$(expr $iter + 1)
+    echo " ** Ending on $(date)"
+}
+
+function postRequest {
+    echo " **"
+    echo " * Simple POST request started on $(date)"
+    echo " **"
+    echo " * Checking for ${3} request XML validity..."
+    echo " * Schema: http://schemas.opengis.net/wps/1.0.0/wps${3}_request.xsd"
+    echo " *********************************"
+    xmllint --noout --schema http://schemas.opengis.net/wps/1.0.0/wps${3}_request.xsd "$4" 
+    echo " *********************************"
+    curl -H "Content-type: text/xml" -d@"$4" -o "$2" "$1"
+    echo " * Checking for ${3} response XML validity on $(date) ..."
+    echo " * Schema: http://schemas.opengis.net/wps/1.0.0/wps${3}_response.xsd"
+    echo " *********************************"
+    xmllint --noout --schema http://schemas.opengis.net/wps/1.0.0/wps${3}_response.xsd "$2"
+    echo " *********************************"
+    if [ -z "$5" ]; then
+	echo ""
+    else
+	echo " * Schema: http://schemas.opengis.net/wps/1.0.0/wps${3}_response.xsd"
+	echo " *********************************"
+	xmllint --noout --schema http://schemas.opengis.net/wps/1.0.0/wps${3}_response.xsd "$(xsltproc ./extractStatusLocation.xsl $2)"
+	echo " *********************************"
+    fi
+    echo " * Sending $NBRequests ${3} XML requests on $(date) ..."
+    ab -g tmp/stat${3}${iter}.plot -e tmp/stat${3}${iter}.txt -T "text/xml" -p "$4" -n "$NBRequests" -c "$NBConcurrents" "$1"
+    if [ "$pstat" -eq 1 ]; then
+	plotStat ${iter} tmp/stat${3}${iter}.jpg tmp/stat${3}${iter}.plot
+    fi
+    iter=$(expr $iter + 1)
+    echo " ** Ending on $(date)"
+}
+
+function kvpRequestWrite {
+    suffix=""
+    cnt=0
+    cnt0=0
+    for i in $2; do
+	if [ ! $1 -eq $cnt0 ]; then
+	    if [ $cnt -gt 0 ]; then
+		suffix="$suffix&$(echo $i | sed 's:\"::g')"
+	    else
+		suffix="$(echo $i | sed 's:\"::g')"
+	    fi
+	    cnt=$(expr $cnt + 1)
+	fi
+	cnt0=$(expr $cnt0 + 1)
+    done
+    echo $suffix
+}
+
+function kvpWrongRequestWrite {
+    suffix=""
+    cnt=0
+    cnt0=0
+    for i in $2; do
+	if [ ! $1 -eq $cnt0 ]; then
+	    if [ $cnt -gt 0 ]; then
+		suffix="$suffix&$(echo $i | sed 's:\"::g')"
+	    else
+		suffix="$(echo $i | sed 's:\"::g')"
+	    fi
+	    cnt=$(expr $cnt + 1)
+	else
+	    cnt1=0
+	    for j in $3; do 
+		if [ $cnt1 -eq $1 ]; then
+		    suffix="$suffix&$(echo $j | sed 's:\"::g')"
+		fi
+		cnt1=$(expr $cnt1 + 1)
+	    done
+	fi
+	cnt0=$(expr $cnt0 + 1)
+    done
+    echo $suffix
+}
+
+for i in $3; do
+    if [ "$i" == "GetCapabilities" ]; then
+#
+# Tests for GetCapabilities using KVP (including wrong requests) and POST requests
+#
+	kvpRequest "${WPSInstance}?REQUEST=GetCapabilities&SERVICE=WPS" "tmp/outputGC1.xml" "GetCapabilities"
+
+	params='"request=GetCapabilities" "service=WPS"'
+
+	suffix=$(kvpRequestWrite -1 "$params")
+	kvpRequest "${WPSInstance}?$suffix" "tmp/outputGC2.xml" "GetCapabilities"
+
+	for j in 0 1; do 
+	    suffix=$(kvpRequestWrite $j "$params")
+	    kvpRequest "${WPSInstance}?$suffix" "tmp/outputGC$(expr $j + 3).xml" "owsExceptionReport"
+	done
+
+	paramsw='"request=GetCapabilitie" "service=WXS"'
+	for j in 0 1; do 
+	    suffix=$(kvpWrongRequestWrite $j "$params" "$paramsw")
+	    kvpRequest "${WPSInstance}?$suffix" "tmp/outputGC$(expr $j + 5).xml" "owsExceptionReport"
+	done
+
+	echo "Check if differences between upper case and lower case parameter names"
+	diff -ru tmp/outputGC1.xml tmp/outputGC2.xml 
+
+	echo ""
+
+	curl -o tmp/10_wpsGetCapabilities_request.xml http://schemas.opengis.net/wps/1.0.0/examples/10_wpsGetCapabilities_request.xml
+	postRequest "${WPSInstance}" "tmp/outputGCp.xml" "GetCapabilities" "tmp/10_wpsGetCapabilities_request.xml"
+	echo ""
+    fi
+    if [ "$i" == "DescribeProcess" ]; then
+#
+# Tests for DescribeProcess using KVP and POST requests
+#
+	kvpRequest "${WPSInstance}?request=DescribeProcess&service=WPS&version=1.0.0&Identifier=ALL" "tmp/outputDPall.xml" "DescribeProcess"
+
+	params='"request=DescribeProcess" "service=WPS" "version=1.0.0" "Identifier='${ServiceName}'"'
+
+	suffix=$(kvpRequestWrite -1 "$params")
+	kvpRequest "${WPSInstance}?$suffix" "tmp/outputDPb1.xml" "DescribeProcess"
+	
+	for j in 0 1 2 3; do 
+	    suffix=$(kvpRequestWrite $j "$params")
+	    kvpRequest "${WPSInstance}?$suffix" "tmp/outputDPb$(expr $j + 2).xml" "owsExceptionReport"
+	done
+
+	paramsw='"request=DescribeProces" "service=WXS" "version=1.2.0" "Identifier=Undefined"'
+	
+	for j in 0 1 2 3; do 
+	    suffix=$(kvpWrongRequestWrite $j "$params")
+	    kvpRequest "${WPSInstance}?$suffix" "tmp/outputDPb$(expr $j + 6).xml" "owsExceptionReport"
+	done
+
+
+	cat requests/dp.xml | sed "s:ServiceName:${ServiceName}:g" > tmp/dp1.xml
+	postRequest "${WPSInstance}" "tmp/outputDPp.xml" "DescribeProcess" "tmp/dp1.xml"
+	xsltproc extractInputs.xsl tmp/outputDPp.xml > tmp/inputName.txt
+	echo "" 
+    fi
+    if [ "$i" == "ExecuteSync" ]; then
+	testPostRequests "ijson_o igml_o ir_o ir_or irb_o irb_or"
+	echo "" 
+    fi
+    if [ "$i" == "ExecuteAsync" ]; then	
+	testPostRequests "ir_o_async ir_or_async irb_o_async irb_or_async"
+	echo "" 
+    fi
+done
diff --git a/thirds/cgic206/Makefile b/thirds/cgic206/Makefile
new file mode 100644
index 0000000..844dc77
--- /dev/null
+++ b/thirds/cgic206/Makefile
@@ -0,0 +1,41 @@
+OS:=$(shell uname -s)
+CPU:=$(shell uname -m)
+ifeq ($(OS),Darwin)
+	MACOS_CFLAGS=-arch x86_64
+	LIBS= -L./ -lcgic /usr/lib/libfcgi.dylib
+else
+ifeq ($(CPU),x86_64)
+	LIBS= -L./ -lcgic /usr/lib64/libfcgi.so
+else
+	LIBS= -L./ -lcgic /usr/lib/libfcgi.a
+endif
+endif
+CFLAGS=-g -Wall ${MACOS_CFLAGS}
+CC=gcc
+AR=ar
+RANLIB=ranlib
+
+all: libcgic.a cgictest.cgi capture
+
+install: libcgic.a
+	mkdir -p ../../dist/lib
+	cp libcgic.a  ../../dist/lib
+	cp cgic.h  ../../dist/include
+	@echo libcgic.a is in  ../../dist/lib/ and cgic.h is in  ../../dist/include/
+
+libcgic.a: cgic.o cgic.h
+	rm -f libcgic.a
+	$(AR) rc libcgic.a cgic.o
+	$(RANLIB) libcgic.a
+
+#mingw32 and cygwin users: replace .cgi with .exe
+
+cgictest.cgi: cgictest.o libcgic.a
+	gcc cgictest.o -o cgictest.cgi ${LIBS}
+
+capture: capture.o libcgic.a
+	gcc capture.o -o capture ${LIBS}
+
+clean:
+	rm -f *.o *.a cgictest.cgi capture
+
diff --git a/thirds/cgic206/capture.c b/thirds/cgic206/capture.c
new file mode 100644
index 0000000..dddf5ac
--- /dev/null
+++ b/thirds/cgic206/capture.c
@@ -0,0 +1,12 @@
+#include "cgic.h"
+
+int cgiMain() {
+	cgiWriteEnvironment("/tmp/capcgi.dat");
+	cgiHeaderContentType("text/html");
+	fprintf(cgiOut, "<title>Captured</title>\n");
+	fprintf(cgiOut, "<h1>Captured</h1>\n");
+	fprintf(cgiOut, "Your form submission was captured for use in\n");
+	fprintf(cgiOut, "debugging CGI code.\n");
+	return 0;
+}
+
diff --git a/thirds/cgic206/cgic.c b/thirds/cgic206/cgic.c
new file mode 100644
index 0000000..81a35ba
--- /dev/null
+++ b/thirds/cgic206/cgic.c
@@ -0,0 +1,2556 @@
+/* cgicTempDir is the only setting you are likely to need
+	to change in this file. */
+
+/* Used only in Unix environments, in conjunction with mkstemp(). 
+	Elsewhere (Windows), temporary files go where the tmpnam() 
+	function suggests. If this behavior does not work for you, 
+	modify the getTempFileName() function to suit your needs. */
+
+#define cgicTempDir "/tmp"
+
+#include <fcgi_stdio.h>
+#if CGICDEBUG
+#define CGICDEBUGSTART \
+	{ \
+		FILE *dout; \
+		dout = fopen("/home/boutell/public_html/debug", "a"); \
+	
+#define CGICDEBUGEND \
+		fclose(dout); \
+	}
+#else /* CGICDEBUG */
+#define CGICDEBUGSTART
+#define CGICDEBUGEND
+#endif /* CGICDEBUG */
+
+#ifdef WIN32
+#define _INC_STDIO
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef WIN32
+#include <io.h>
+
+/* cgic 2.01 */
+#include <fcntl.h>
+
+#else
+#include <unistd.h>
+#endif /* WIN32 */
+#include "cgic.h"
+
+#define cgiStrEq(a, b) (!strcmp((a), (b)))
+
+char *cgiServerSoftware;
+char *cgiServerName;
+char *cgiGatewayInterface;
+char *cgiServerProtocol;
+char *cgiServerPort;
+char *cgiRequestMethod;
+char *cgiPathInfo;
+char *cgiPathTranslated;
+char *cgiScriptName;
+char *cgiQueryString;
+char *cgiRemoteHost;
+char *cgiRemoteAddr;
+char *cgiAuthType;
+char *cgiRemoteUser;
+char *cgiRemoteIdent;
+char cgiContentTypeData[1024];
+char *cgiContentType = cgiContentTypeData;
+char *cgiMultipartBoundary;
+char *cgiCookie;
+int cgiContentLength;
+char *cgiAccept;
+char *cgiUserAgent;
+char *cgiReferrer;
+char *cgiSid;
+
+FILE *cgiIn;
+FILE *cgiOut;
+
+/* True if CGI environment was restored from a file. */
+static int cgiRestored = 0;
+static int cgiTreatUrlEncoding;
+
+static void cgiGetenv(char **s, char *var);
+
+typedef enum {
+	cgiParseSuccess,
+	cgiParseMemory,
+	cgiParseIO
+} cgiParseResultType;
+
+/* One form entry, consisting of an attribute-value pair,
+	and an optional filename and content type. All of
+	these are guaranteed to be valid null-terminated strings,
+	which will be of length zero in the event that the
+	field is not present, with the exception of tfileName
+	which will be null when 'in' is null. DO NOT MODIFY THESE 
+	VALUES. Make local copies if modifications are desired. */
+
+typedef struct cgiFormEntryStruct {
+        char *attr;
+	/* value is populated for regular form fields only.
+		For file uploads, it points to an empty string, and file
+		upload data should be read from the file tfileName. */ 
+	char *value;
+	/* When fileName is not an empty string, tfileName is not null,
+		and 'value' points to an empty string. */
+	/* Valid for both files and regular fields; does not include
+		terminating null of regular fields. */
+	int valueLength;
+	char *fileName;	
+	char *contentType;
+	/* Temporary file name for working storage of file uploads. */
+	char *tfileName;
+        struct cgiFormEntryStruct *next;
+} cgiFormEntry;
+
+/* The first form entry. */
+static cgiFormEntry *cgiFormEntryFirst;
+
+static cgiParseResultType cgiParseGetFormInput();
+static cgiParseResultType cgiParsePostFormInput();
+static cgiParseResultType cgiParsePostMultipartInput();
+static cgiParseResultType cgiParseFormInput(char *data, int length);
+static void cgiSetupConstants();
+static void cgiFreeResources();
+static int cgiStrEqNc(char *s1, char *s2);
+static int cgiStrBeginsNc(char *s1, char *s2);
+
+//int cgiMain_init() {}
+
+
+int main(int argc, char *argv[]) {
+	int result;
+	char *cgiContentLengthString;
+	char *e;
+	while (FCGI_Accept() >= 0) {
+	cgiSetupConstants();
+	cgiGetenv(&cgiServerSoftware, "SERVER_SOFTWARE");
+	cgiGetenv(&cgiServerName, "SERVER_NAME");
+	cgiGetenv(&cgiGatewayInterface, "GATEWAY_INTERFACE");
+	cgiGetenv(&cgiServerProtocol, "SERVER_PROTOCOL");
+	cgiGetenv(&cgiServerPort, "SERVER_PORT");
+	cgiGetenv(&cgiRequestMethod, "REQUEST_METHOD");
+	if(strcmp(cgiRequestMethod,"")==0 && argc>=1)
+		cgiRequestMethod="GET";
+	cgiGetenv(&cgiPathInfo, "PATH_INFO");
+	cgiGetenv(&cgiPathTranslated, "PATH_TRANSLATED");
+	cgiGetenv(&cgiScriptName, "SCRIPT_NAME");
+	cgiGetenv(&cgiQueryString, "QUERY_STRING");
+	cgiSid=NULL;
+	if(cgiQueryString!=NULL && argc>=2){
+		cgiQueryString=argv[1];
+		if(argc>2){
+		  cgiSid=argv[2];
+		}
+	}
+	cgiGetenv(&cgiRemoteHost, "REMOTE_HOST");
+	cgiGetenv(&cgiRemoteAddr, "REMOTE_ADDR");
+	cgiGetenv(&cgiAuthType, "AUTH_TYPE");
+	cgiGetenv(&cgiRemoteUser, "REMOTE_USER");
+	cgiGetenv(&cgiRemoteIdent, "REMOTE_IDENT");
+	/* 2.0: the content type string needs to be parsed and modified, so
+		copy it to a buffer. */
+	e = getenv("CONTENT_TYPE");
+	if (e) {
+		if (strlen(e) < sizeof(cgiContentTypeData)) {
+			strcpy(cgiContentType, e);
+		} else {
+			/* Truncate safely in the event of what is almost certainly
+				a hack attempt */
+			strncpy(cgiContentType, e, sizeof(cgiContentTypeData));
+			cgiContentType[sizeof(cgiContentTypeData) - 1] = '\0';
+		}
+	} else {
+		cgiContentType[0] = '\0';
+	}
+	/* Never null */
+	cgiMultipartBoundary = "";
+	/* 2.0: parse semicolon-separated additional parameters of the
+		content type. The one we're interested in is 'boundary'.
+		We discard the rest to make cgiContentType more useful
+		to the typical programmer. */
+	if (strchr(cgiContentType, ';')) {
+		char *sat = strchr(cgiContentType, ';');
+		while (sat) {
+			*sat = '\0';
+			sat++;
+			while (isspace(*sat)) {
+				sat++;
+			}	
+			if (cgiStrBeginsNc(sat, "boundary=")) {
+				char *s;
+				cgiMultipartBoundary = sat + strlen("boundary=");
+				s = cgiMultipartBoundary;
+				while ((*s) && (!isspace(*s))) {
+					s++;
+				}
+				*s = '\0';
+				break;
+			} else {
+				sat = strchr(sat, ';');
+			} 	
+		}
+	}
+	cgiGetenv(&cgiContentLengthString, "CONTENT_LENGTH");
+	cgiContentLength = atoi(cgiContentLengthString);	
+	if(cgiContentLength==0 && argc>=2){
+		cgiContentLength=strlen(argv[1]);
+	}
+	cgiGetenv(&cgiAccept, "HTTP_ACCEPT");
+	cgiGetenv(&cgiUserAgent, "HTTP_USER_AGENT");
+	cgiGetenv(&cgiReferrer, "HTTP_REFERER");
+	cgiGetenv(&cgiCookie, "HTTP_COOKIE");
+#ifdef CGICDEBUG
+	CGICDEBUGSTART
+	fprintf(dout, "%d\n", cgiContentLength);
+	fprintf(dout, "%s\n", cgiRequestMethod);
+	fprintf(dout, "%s\n", cgiContentType);
+	CGICDEBUGEND	
+#endif /* CGICDEBUG */
+#ifdef WIN32
+	/* 1.07: Must set stdin and stdout to binary mode */
+	/* 2.0: this is particularly crucial now and must not be removed */
+	_setmode( FCGI_fileno( stdin ), _O_BINARY );
+	_setmode( FCGI_fileno( stdout ), _O_BINARY );
+#endif /* WIN32 */
+	cgiFormEntryFirst = 0;
+	cgiIn = FCGI_stdin;
+	cgiOut = FCGI_stdout;
+	cgiRestored = 0;
+
+
+	/* These five lines keep compilers from
+		producing warnings that argc and argv
+		are unused. They have no actual function. */
+	if (argc) {
+		if (argv[0]) {
+			cgiRestored = 0;
+		}
+	}	
+
+
+	cgiTreatUrlEncoding=0;
+	if (cgiStrEqNc(cgiRequestMethod, "post")) {
+		cgiTreatUrlEncoding=0;
+#ifdef CGICDEBUG
+		CGICDEBUGSTART
+		fprintf(dout, "POST recognized\n");
+		CGICDEBUGEND
+#endif /* CGICDEBUG */
+		if (cgiStrEqNc(cgiContentType, "application/x-www-form-urlencoded")) {	
+#ifdef CGICDEBUG
+			CGICDEBUGSTART
+			fprintf(dout, "Calling PostFormInput\n");
+			CGICDEBUGEND	
+#endif /* CGICDEBUG */
+			if (cgiParsePostFormInput() != cgiParseSuccess) {
+#ifdef CGICDEBUG
+				CGICDEBUGSTART
+				fprintf(dout, "PostFormInput failed\n");
+				CGICDEBUGEND	
+#endif /* CGICDEBUG */
+				cgiFreeResources();
+				return -1;
+			}	
+#ifdef CGICDEBUG
+			CGICDEBUGSTART
+			fprintf(dout, "PostFormInput succeeded\n");
+			CGICDEBUGEND	
+#endif /* CGICDEBUG */
+		} else if (cgiStrEqNc(cgiContentType, "multipart/form-data")) {
+#ifdef CGICDEBUG
+			CGICDEBUGSTART
+			fprintf(dout, "Calling PostMultipartInput\n");
+			CGICDEBUGEND	
+#endif /* CGICDEBUG */
+			if (cgiParsePostMultipartInput() != cgiParseSuccess) {
+#ifdef CGICDEBUG
+				CGICDEBUGSTART
+				fprintf(dout, "PostMultipartInput failed\n");
+				CGICDEBUGEND	
+#endif /* CGICDEBUG */
+				cgiFreeResources();
+				return -1;
+			}	
+#ifdef CGICDEBUG
+			CGICDEBUGSTART
+			fprintf(dout, "PostMultipartInput succeeded\n");
+			CGICDEBUGEND	
+#endif /* CGICDEBUG */
+		}
+	} else if (cgiStrEqNc(cgiRequestMethod, "get")) {	
+		/* The spec says this should be taken care of by
+			the server, but... it isn't */
+		cgiContentLength = strlen(cgiQueryString);
+		if (cgiParseGetFormInput() != cgiParseSuccess) {
+#ifdef CGICDEBUG
+			CGICDEBUGSTART
+			fprintf(dout, "GetFormInput failed\n");
+			CGICDEBUGEND	
+#endif /* CGICDEBUG */
+			cgiFreeResources();
+			return -1;
+		} else {	
+#ifdef CGICDEBUG
+			CGICDEBUGSTART
+			fprintf(dout, "GetFormInput succeeded\n");
+			CGICDEBUGEND	
+#endif /* CGICDEBUG */
+		}
+	}
+	result = cgiMain();
+	cgiFreeResources();
+	}
+	FCGI_Finish();
+	return result;
+}
+
+static void cgiGetenv(char **s, char *var){
+	*s = getenv(var);
+	if (!(*s)) {
+		*s = "";
+	}
+}
+
+static cgiParseResultType cgiParsePostFormInput() {
+	char *input;
+	cgiParseResultType result;
+	if (!cgiContentLength) {
+		return cgiParseSuccess;
+	}
+	input = (char *) malloc(cgiContentLength);
+	if (!input) {
+		return cgiParseMemory;	
+	}
+	if (((int) fread(input, 1, cgiContentLength, cgiIn)) 
+		!= cgiContentLength) 
+	{
+		return cgiParseIO;
+	}	
+	result = cgiParseFormInput(input, cgiContentLength);
+	free(input);
+	return result;
+}
+
+/* 2.0: A virtual datastream supporting putback of 
+	enough characters to handle multipart boundaries easily.
+	A simple memset(&mp, 0, sizeof(mp)) is suitable initialization. */
+
+typedef struct {
+	/* Buffer for putting characters back */
+	char putback[1024];	
+	/* Position in putback from which next character will be read.
+		If readPos == writePos, then next character should
+		come from cgiIn. */
+	int readPos;
+	/* Position in putback to which next character will be put back.
+		If writePos catches up to readPos, as opposed to the other
+		way around, the stream no longer functions properly.
+		Calling code must guarantee that no more than 
+		sizeof(putback) bytes are put back at any given time. */
+	int writePos;
+	/* Offset in the virtual datastream; can be compared
+		to cgiContentLength */
+	int offset;
+} mpStream, *mpStreamPtr;
+
+int mpRead(mpStreamPtr mpp, char *buffer, int len)
+{
+	int ilen = len;
+	int got = 0;
+	while (len) {
+		if (mpp->readPos != mpp->writePos) {
+			*buffer++ = mpp->putback[mpp->readPos++];
+			mpp->readPos %= sizeof(mpp->putback);
+			got++;
+			len--;
+		} else {
+			break;
+		}	
+	}
+	/* Refuse to read past the declared length in order to
+		avoid deadlock */
+	if (len > (cgiContentLength - mpp->offset)) {
+		len = cgiContentLength - mpp->offset;
+	}
+	if (len) {
+		int fgot = fread(buffer, 1, len, cgiIn);
+		if (fgot >= 0) {
+			mpp->offset += (got + fgot);
+			return got + fgot;
+		} else if (got > 0) {
+			mpp->offset += got;
+			return got;
+		} else {
+			/* EOF or error */
+			return fgot;
+		}
+	} else if (got) {
+		return got;
+	} else if (ilen) {	
+		return EOF;
+	} else {
+		/* 2.01 */
+		return 0;
+	}
+}
+
+void mpPutBack(mpStreamPtr mpp, char *data, int len)
+{
+	mpp->offset -= len;
+	while (len) {
+		mpp->putback[mpp->writePos++] = *data++;
+		mpp->writePos %= sizeof(mpp->putback);
+		len--;
+	}
+}
+
+/* This function copies the body to outf if it is not null, otherwise to
+	a newly allocated character buffer at *outP, which will be null
+	terminated; if both outf and outP are null the body is not stored.
+	If bodyLengthP is not null, the size of the body in bytes is stored
+	to *bodyLengthP, not including any terminating null added to *outP. 
+	If 'first' is nonzero, a preceding newline is not expected before
+	the boundary. If 'first' is zero, a preceding newline is expected.
+	Upon return mpp is positioned after the boundary and its trailing 
+	newline, if any; if the boundary is followed by -- the next two 
+	characters read after this function returns will be --. Upon error, 
+	if outP is not null, *outP is a null pointer; *bodyLengthP 
+	is set to zero. Returns cgiParseSuccess, cgiParseMemory 
+	or cgiParseIO. */
+
+static cgiParseResultType afterNextBoundary(mpStreamPtr mpp,
+	FILE *outf,
+	char **outP,
+	int *bodyLengthP,
+	int first
+	);
+
+static int readHeaderLine(
+	mpStreamPtr mpp,	
+	char *attr,
+	int attrSpace,
+	char *value,
+	int valueSpace);
+
+static void decomposeValue(char *value,
+	char *mvalue, int mvalueSpace,
+	char **argNames,
+	char **argValues,
+	int argValueSpace);
+
+/* tfileName must be 1024 bytes to ensure adequacy on
+	win32 (1024 exceeds the maximum path length and
+	certainly exceeds observed behavior of _tmpnam).
+	May as well also be 1024 bytes on Unix, although actual
+	length is strlen(cgiTempDir) + a short unique pattern. */
+	
+static cgiParseResultType getTempFileName(char *tfileName);
+
+static cgiParseResultType cgiParsePostMultipartInput() {
+	cgiParseResultType result;
+	cgiFormEntry *n = 0, *l = 0;
+	int got;
+	FILE *outf = 0;
+	char *out = 0;
+	char tfileName[1024];
+	mpStream mp;
+	mpStreamPtr mpp = ∓
+	memset(&mp, 0, sizeof(mp));
+	if (!cgiContentLength) {
+		return cgiParseSuccess;
+	}
+	/* Read first boundary, including trailing newline */
+	result = afterNextBoundary(mpp, 0, 0, 0, 1);
+	if (result == cgiParseIO) {	
+		/* An empty submission is not necessarily an error */
+		return cgiParseSuccess;
+	} else if (result != cgiParseSuccess) {
+		return result;
+	}
+	while (1) {
+		char d[1024];
+		char fvalue[1024];
+		char fname[1024];
+		int bodyLength = 0;
+		char ffileName[1024];
+		char fcontentType[1024];
+		char attr[1024];
+		char value[1024];
+		fvalue[0] = 0;
+		fname[0] = 0;
+		ffileName[0] = 0;
+		fcontentType[0] = 0;
+		out = 0;
+		outf = 0;
+		/* Check for EOF */
+		got = mpRead(mpp, d, 2);
+		if (got < 2) {
+			/* Crude EOF */
+			break;
+		}
+		if ((d[0] == '-') && (d[1] == '-')) {
+			/* Graceful EOF */
+			break;
+		}
+		mpPutBack(mpp, d, 2);
+		/* Read header lines until end of header */
+		while (readHeaderLine(
+				mpp, attr, sizeof(attr), value, sizeof(value))) 
+		{
+			char *argNames[3];
+			char *argValues[2];
+			/* Content-Disposition: form-data; 
+				name="test"; filename="googley.gif" */
+			if (cgiStrEqNc(attr, "Content-Disposition")) {
+				argNames[0] = "name";
+				argNames[1] = "filename";
+				argNames[2] = 0;
+				argValues[0] = fname;
+				argValues[1] = ffileName;
+				decomposeValue(value, 
+					fvalue, sizeof(fvalue),
+					argNames,
+					argValues,
+					1024);	
+			} else if (cgiStrEqNc(attr, "Content-Type")) {
+				argNames[0] = 0;
+				decomposeValue(value, 
+					fcontentType, sizeof(fcontentType),
+					argNames,
+					0,
+					0);
+			}
+		}
+		if (!cgiStrEqNc(fvalue, "form-data")) {
+			/* Not form data */	
+			continue;
+		}
+		/* Body is everything from here until the next 
+			boundary. So, set it aside and move past boundary. 
+			If a filename was submitted as part of the
+			disposition header, store to a temporary file.
+			Otherwise, store to a memory buffer (it is
+			presumably a regular form field). */
+		if (strlen(ffileName)) {
+			if (getTempFileName(tfileName) != cgiParseSuccess) {
+				return cgiParseIO;
+			}	
+			outf = fopen(tfileName, "w+b");
+		} else {
+			outf = 0;
+			tfileName[0] = '\0';
+		}	
+		result = afterNextBoundary(mpp, outf, &out, &bodyLength, 0);
+		if (result != cgiParseSuccess) {
+			/* Lack of a boundary here is an error. */
+			if (outf) {
+				fclose(outf);
+				unlink(tfileName);
+			}
+			if (out) {
+				free(out);
+			}
+			return result;
+		}
+		/* OK, we have a new pair, add it to the list. */
+		n = (cgiFormEntry *) malloc(sizeof(cgiFormEntry));	
+		if (!n) {
+			goto outOfMemory;
+		}
+		memset(n, 0, sizeof(cgiFormEntry));
+		/* 2.01: one of numerous new casts required
+			to please C++ compilers */
+		n->attr = (char *) malloc(strlen(fname) + 1);
+		if (!n->attr) {
+			goto outOfMemory;
+		}
+		strcpy(n->attr, fname);
+		if (out) {
+			n->value = out;
+			out = 0;
+		} else if (outf) {
+			n->value = (char *) malloc(1);
+			if (!n->value) {
+				goto outOfMemory;
+			}
+			n->value[0] = '\0';
+			fclose(outf);
+		}
+		n->valueLength = bodyLength;
+		n->next = 0;
+		if (!l) {
+			cgiFormEntryFirst = n;
+		} else {
+			l->next = n;
+		}
+		n->fileName = (char *) malloc(strlen(ffileName) + 1);
+		if (!n->fileName) {
+			goto outOfMemory;
+		}
+		strcpy(n->fileName, ffileName);
+		n->contentType = (char *) malloc(strlen(fcontentType) + 1);
+		if (!n->contentType) {
+			goto outOfMemory;
+		}
+		strcpy(n->contentType, fcontentType);
+		n->tfileName = (char *) malloc(strlen(tfileName) + 1);
+		if (!n->tfileName) {
+			goto outOfMemory;
+		}
+		strcpy(n->tfileName, tfileName);
+
+		l = n;			
+	}	
+	return cgiParseSuccess;
+outOfMemory:
+	if (n) {
+		if (n->attr) {
+			free(n->attr);
+		}
+		if (n->value) {
+			free(n->value);
+		}
+		if (n->fileName) {
+			free(n->fileName);
+		}
+		if (n->tfileName) {
+			free(n->tfileName);
+		}
+		if (n->contentType) {
+			free(n->contentType);
+		}
+		free(n);
+	}
+	if (out) {
+		free(out);
+	}
+	if (outf) {
+		fclose(outf);
+		unlink(tfileName);
+	}
+	return cgiParseMemory;
+}
+
+static cgiParseResultType getTempFileName(char *tfileName)
+{
+#ifndef WIN32
+	/* Unix. Use the robust 'mkstemp' function to create
+		a temporary file that is truly unique, with
+		permissions that are truly safe. The 
+		fopen-for-write destroys any bogus information
+		written by potential hackers during the brief
+		window between the file's creation and the
+		chmod call (glibc 2.0.6 and lower might
+		otherwise have allowed this). */
+	int outfd; 
+	strcpy(tfileName, cgicTempDir "/cgicXXXXXX");
+	outfd = mkstemp(tfileName);
+	if (outfd == -1) {
+		return cgiParseIO;
+	}
+	close(outfd);
+	/* Fix the permissions */
+	if (chmod(tfileName, 0600) != 0) {
+		unlink(tfileName);
+		return cgiParseIO;
+	}
+#else
+	/* Non-Unix. Do what we can. */
+	if (!tmpnam(tfileName)) {
+		return cgiParseIO;
+	}
+#endif
+	return cgiParseSuccess;
+}
+
+
+#define APPEND(string, char) \
+	{ \
+		if ((string##Len + 1) < string##Space) { \
+			string[string##Len++] = (char); \
+		} \
+	}
+
+#define RAPPEND(string, ch) \
+	{ \
+		if ((string##Len + 1) == string##Space)  { \
+			char *sold = string; \
+			string##Space *= 2; \
+			string = (char *) realloc(string, string##Space); \
+			if (!string) { \
+				string = sold; \
+				goto outOfMemory; \
+			} \
+		} \
+		string[string##Len++] = (ch); \
+	}
+		
+#define BAPPEND(ch) \
+	{ \
+		if (outf) { \
+			putc(ch, outf); \
+			outLen++; \
+		} else if (out) { \
+			RAPPEND(out, ch); \
+		} \
+	}
+
+cgiParseResultType afterNextBoundary(mpStreamPtr mpp, FILE *outf, char **outP,
+	int *bodyLengthP, int first)
+{
+	int outLen = 0;
+	int outSpace = 256;
+	char *out = 0;
+	cgiParseResultType result;
+	int boffset;
+	int got;
+	char d[2];	
+	/* This is large enough, because the buffer into which the
+		original boundary string is fetched is shorter by more
+		than four characters due to the space required for
+		the attribute name */
+	char workingBoundaryData[1024];
+	char *workingBoundary = workingBoundaryData;
+	int workingBoundaryLength;
+	if ((!outf) && (outP)) {
+		out = (char *) malloc(outSpace);
+		if (!out) {
+			goto outOfMemory;
+		}
+	}
+	boffset = 0;
+	sprintf(workingBoundaryData, "\r\n--%s", cgiMultipartBoundary);
+	if (first) {
+		workingBoundary = workingBoundaryData + 2;
+	}
+	workingBoundaryLength = strlen(workingBoundary);
+	while (1) {
+		got = mpRead(mpp, d, 1);
+		if (got != 1) {
+			/* 2.01: cgiParseIO, not cgiFormIO */
+			result = cgiParseIO;
+			goto error;
+		}
+		if (d[0] == workingBoundary[boffset]) {
+			/* We matched the next byte of the boundary.
+				Keep track of our progress into the
+				boundary and don't emit anything. */
+			boffset++;
+			if (boffset == workingBoundaryLength) {
+				break;
+			} 
+		} else if (boffset > 0) {
+			/* We matched part, but not all, of the
+				boundary. Now we have to be careful:
+				put back all except the first
+				character and try again. The 
+				real boundary could begin in the
+				middle of a false match. We can
+				emit the first character only so far. */
+			BAPPEND(workingBoundary[0]);
+			mpPutBack(mpp, 
+				workingBoundary + 1, boffset - 1);
+			mpPutBack(mpp, d, 1);
+			boffset = 0;
+		} else {		
+			/* Not presently in the middle of a boundary
+				match; just emit the character. */
+			BAPPEND(d[0]);
+		}	
+	}
+	/* Read trailing newline or -- EOF marker. A literal EOF here
+		would be an error in the input stream. */
+	got = mpRead(mpp, d, 2);
+	if (got != 2) {
+		result = cgiParseIO;
+		goto error;
+	}	
+	if ((d[0] == '\r') && (d[1] == '\n')) {
+		/* OK, EOL */
+	} else if (d[0] == '-') {
+		/* Probably EOF, but we check for
+			that later */
+		mpPutBack(mpp, d, 2);
+	}	
+	if (out && outSpace) {
+		char *oout = out;
+		out[outLen] = '\0';
+		out = (char *) realloc(out, outLen + 1);
+		if (!out) {
+			/* Surprising if it happens; and not fatal! We were
+				just trying to give some space back. We can
+				keep it if we have to. */
+			out = oout;
+		}
+		*outP = out;
+	}
+	if (bodyLengthP) {
+		*bodyLengthP = outLen;
+	}
+	return cgiParseSuccess;
+outOfMemory:
+	result = cgiParseMemory;
+	if (outP) {
+		if (out) {
+			free(out);
+		}
+		*outP = '\0';	
+	}
+error:
+	if (bodyLengthP) {
+		*bodyLengthP = 0;
+	}
+	if (out) {
+		free(out);
+	}
+	if (outP) {
+		*outP = 0;	
+	}
+	return result;
+}
+
+static void decomposeValue(char *value,
+	char *mvalue, int mvalueSpace,
+	char **argNames,
+	char **argValues,
+	int argValueSpace)
+{
+	char argName[1024];
+	int argNameSpace = sizeof(argName);
+	int argNameLen = 0;
+	int mvalueLen = 0;
+	char *argValue;
+	int argNum = 0;
+	while (argNames[argNum]) {
+		if (argValueSpace) {
+			argValues[argNum][0] = '\0';
+		}
+		argNum++;
+	}
+	while (isspace(*value)) {
+		value++;
+	}
+	/* Quoted mvalue */
+	if (*value == '\"') {
+		value++;
+		while ((*value) && (*value != '\"')) {
+			APPEND(mvalue, *value);
+			value++;
+		}
+		while ((*value) && (*value != ';')) {
+			value++;
+		}
+	} else {
+		/* Unquoted mvalue */
+		while ((*value) && (*value != ';')) {
+			APPEND(mvalue, *value);
+			value++;
+		}	
+	}	
+	if (mvalueSpace) {
+		mvalue[mvalueLen] = '\0';
+	}
+	while (*value == ';') {
+		int argNum;
+		int argValueLen = 0;
+		/* Skip the ; between parameters */
+		value++;
+		/* Now skip leading whitespace */
+		while ((*value) && (isspace(*value))) { 
+			value++;
+		}
+		/* Now read the parameter name */
+		argNameLen = 0;
+		while ((*value) && (isalnum(*value))) {
+			APPEND(argName, *value);
+			value++;
+		}
+		if (argNameSpace) {
+			argName[argNameLen] = '\0';
+		}
+		while ((*value) && isspace(*value)) {
+			value++;
+		}
+		if (*value != '=') {
+			/* Malformed line */
+			return;	
+		}
+		value++;
+		while ((*value) && isspace(*value)) {
+			value++;
+		}
+		/* Find the parameter in the argument list, if present */
+		argNum = 0;
+		argValue = 0;
+		while (argNames[argNum]) {
+			if (cgiStrEqNc(argName, argNames[argNum])) {
+				argValue = argValues[argNum];
+				break;
+			}
+			argNum++;
+		}		
+		/* Finally, read the parameter value */
+		if (*value == '\"') {
+			value++;
+			while ((*value) && (*value != '\"')) {
+				if (argValue) {
+					APPEND(argValue, *value);
+				}
+				value++;
+			}
+			while ((*value) && (*value != ';')) {
+				value++;
+			}
+		} else {
+			/* Unquoted value */
+			while ((*value) && (*value != ';')) {
+				if (argNames[argNum]) {
+					APPEND(argValue, *value);
+				}
+				value++;
+			}	
+		}	
+		if (argValueSpace) {
+			argValue[argValueLen] = '\0';
+		}
+	}	 	
+}
+
+static int readHeaderLine(
+	mpStreamPtr mpp,
+	char *attr,
+	int attrSpace,
+	char *value,
+	int valueSpace)
+{	
+	int attrLen = 0;
+	int valueLen = 0;
+	int valueFound = 0;
+	while (1) {
+		char d[1];
+		int got = mpRead(mpp, d, 1);
+		if (got != 1) {	
+			return 0;
+		}
+		if (d[0] == '\r') {
+			got = mpRead(mpp, d, 1);
+			if (got == 1) {	
+				if (d[0] == '\n') {
+					/* OK */
+				} else {
+					mpPutBack(mpp, d, 1);
+				}
+			}
+			break;
+		} else if (d[0] == '\n') {
+			break;
+		} else if ((d[0] == ':') && attrLen) {
+			valueFound = 1;
+			while (mpRead(mpp, d, 1) == 1) {
+				if (!isspace(d[0])) {
+					mpPutBack(mpp, d, 1);
+					break;
+				} 
+			}
+		} else if (!valueFound) {
+			if (!isspace(*d)) {
+				if (attrLen < (attrSpace - 1)) {
+					attr[attrLen++] = *d;
+				}
+			}		
+		} else if (valueFound) {	
+			if (valueLen < (valueSpace - 1)) {
+				value[valueLen++] = *d;
+			}
+		}
+	}
+	if (attrSpace) {
+		attr[attrLen] = '\0';
+	}
+	if (valueSpace) {
+		value[valueLen] = '\0';
+	}
+	if (attrLen && valueLen) {
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+static cgiParseResultType cgiParseGetFormInput() {
+	return cgiParseFormInput(cgiQueryString, cgiContentLength);
+}
+
+typedef enum {
+	cgiEscapeRest,
+	cgiEscapeFirst,
+	cgiEscapeSecond
+} cgiEscapeState;
+
+typedef enum {
+	cgiUnescapeSuccess,
+	cgiUnescapeMemory
+} cgiUnescapeResultType;
+
+static cgiUnescapeResultType cgiUnescapeChars(char **sp, char *cp, int len);
+
+static cgiParseResultType cgiParseFormInput(char *data, int length) {
+	/* Scan for pairs, unescaping and storing them as they are found. */
+	int pos = 0;
+	cgiFormEntry *n;
+	cgiFormEntry *l = 0;
+	while (pos != length) {
+		int foundEq = 0;
+		int foundAmp = 0;
+		int start = pos;
+		int len = 0;
+		char *attr;
+		char *value;
+		while (pos != length) {
+			if (data[pos] == '=') {
+				foundEq = 1;
+				pos++;
+				break;
+			}
+			pos++;
+			len++;
+		}
+		if (!foundEq) {
+			break;
+		}
+		if (cgiUnescapeChars(&attr, data+start, len)
+			!= cgiUnescapeSuccess) {
+			return cgiParseMemory;
+		}	
+		start = pos;
+		len = 0;
+		while (pos != length) {
+			if (data[pos] == '&') {
+				foundAmp = 1;
+				pos++;
+				break;
+			}
+			pos++;
+			len++;
+		}
+		/* The last pair probably won't be followed by a &, but
+			that's fine, so check for that after accepting it */
+		if (cgiUnescapeChars(&value, data+start, len)
+			!= cgiUnescapeSuccess) {
+			free(attr);
+			return cgiParseMemory;
+		}	
+		/* OK, we have a new pair, add it to the list. */
+		n = (cgiFormEntry *) malloc(sizeof(cgiFormEntry));	
+		if (!n) {
+			free(attr);
+			free(value);
+			return cgiParseMemory;
+		}
+		n->attr = attr;
+		n->value = value;
+		n->valueLength = strlen(n->value);
+		n->fileName = (char *) malloc(1);
+		if (!n->fileName) {
+			free(attr);
+			free(value);
+			free(n);
+			return cgiParseMemory;
+		}	
+		n->fileName[0] = '\0';
+		n->contentType = (char *) malloc(1);
+		if (!n->contentType) {
+			free(attr);
+			free(value);
+			free(n->fileName);
+			free(n);
+			return cgiParseMemory;
+		}	
+		n->contentType[0] = '\0';
+		n->tfileName = (char *) malloc(1);
+		if (!n->tfileName) {
+			free(attr);
+			free(value);
+			free(n->fileName);
+			free(n->contentType);
+			free(n);
+			return cgiParseMemory;
+		}	
+		n->tfileName[0] = '\0';
+		n->next = 0;
+		if (!l) {
+			cgiFormEntryFirst = n;
+		} else {
+			l->next = n;
+		}
+		l = n;
+		if (!foundAmp) {
+			break;
+		}			
+	}
+	return cgiParseSuccess;
+}
+
+static int cgiHexValue[256];
+
+cgiUnescapeResultType cgiUnescapeChars(char **sp, char *cp, int len) {
+	char *s;
+	cgiEscapeState escapeState = cgiEscapeRest;
+	int escapedValue = 0;
+	int srcPos = 0;
+	int dstPos = 0;
+	s = (char *) malloc(len + 1);
+	if (!s) {
+		return cgiUnescapeMemory;
+	}
+	while (srcPos < len) {
+		int ch = cp[srcPos];
+		if(cgiTreatUrlEncoding==1)
+		switch (escapeState) {
+			case cgiEscapeRest:
+			if (ch == '%') {
+				escapeState = cgiEscapeFirst;
+			} else if (ch == '+') {
+				s[dstPos++] = ' ';
+			} else {
+				s[dstPos++] = ch;
+			}
+			break;
+			case cgiEscapeFirst:
+			escapedValue = cgiHexValue[ch] << 4;	
+			escapeState = cgiEscapeSecond;
+			break;
+			case cgiEscapeSecond:
+			escapedValue += cgiHexValue[ch];
+			s[dstPos++] = escapedValue;
+			escapeState = cgiEscapeRest;
+			break;
+		}
+		else
+		  s[dstPos++] = ch;
+		srcPos++;
+	}
+	s[dstPos] = '\0';
+	*sp = s;
+	return cgiUnescapeSuccess;
+}		
+	
+static void cgiSetupConstants() {
+	int i;
+	for (i=0; (i < 256); i++) {
+		cgiHexValue[i] = 0;
+	}
+	cgiHexValue['0'] = 0;	
+	cgiHexValue['1'] = 1;	
+	cgiHexValue['2'] = 2;	
+	cgiHexValue['3'] = 3;	
+	cgiHexValue['4'] = 4;	
+	cgiHexValue['5'] = 5;	
+	cgiHexValue['6'] = 6;	
+	cgiHexValue['7'] = 7;	
+	cgiHexValue['8'] = 8;	
+	cgiHexValue['9'] = 9;
+	cgiHexValue['A'] = 10;
+	cgiHexValue['B'] = 11;
+	cgiHexValue['C'] = 12;
+	cgiHexValue['D'] = 13;
+	cgiHexValue['E'] = 14;
+	cgiHexValue['F'] = 15;
+	cgiHexValue['a'] = 10;
+	cgiHexValue['b'] = 11;
+	cgiHexValue['c'] = 12;
+	cgiHexValue['d'] = 13;
+	cgiHexValue['e'] = 14;
+	cgiHexValue['f'] = 15;
+}
+
+static void cgiFreeResources() {
+	cgiFormEntry *c = cgiFormEntryFirst;
+	cgiFormEntry *n;
+	while (c) {
+		n = c->next;
+		free(c->attr);
+		free(c->value);
+		free(c->fileName);
+		free(c->contentType);
+		if (strlen(c->tfileName)) {
+			unlink(c->tfileName);
+		}
+		free(c->tfileName);
+		free(c);
+		c = n;
+	}
+	/* If the cgi environment was restored from a saved environment,
+		then these are in allocated space and must also be freed */
+	if (cgiRestored) {
+		free(cgiServerSoftware);
+		free(cgiServerName);
+		free(cgiGatewayInterface);
+		free(cgiServerProtocol);
+		free(cgiServerPort);
+		free(cgiRequestMethod);
+		free(cgiPathInfo);
+		free(cgiPathTranslated);
+		free(cgiScriptName);
+		free(cgiQueryString);
+		free(cgiRemoteHost);
+		free(cgiRemoteAddr);
+		free(cgiAuthType);
+		free(cgiRemoteUser);
+		free(cgiRemoteIdent);
+		free(cgiContentType);
+		free(cgiAccept);
+		free(cgiUserAgent);
+		free(cgiReferrer);
+	}
+	/* 2.0: to clean up the environment for cgiReadEnvironment,
+		we must set these correctly */
+	cgiFormEntryFirst = 0;
+	cgiRestored = 0;
+}
+
+static cgiFormResultType cgiFormEntryString(
+	cgiFormEntry *e, char *result, int max, int newlines);
+
+static cgiFormEntry *cgiFormEntryFindFirst(char *name);
+static cgiFormEntry *cgiFormEntryFindNext();
+
+cgiFormResultType cgiFormString(
+        char *name, char *result, int max) {
+	cgiFormEntry *e;
+	e = cgiFormEntryFindFirst(name);
+	if (!e) {
+		strcpy(result, "");
+		return cgiFormNotFound;
+	}
+	return cgiFormEntryString(e, result, max, 1);
+}
+
+cgiFormResultType cgiFormFileName(
+	char *name, char *result, int resultSpace)
+{
+	cgiFormEntry *e;
+	int resultLen = 0;
+	char *s;
+	e = cgiFormEntryFindFirst(name);
+	if (!e) {
+		strcpy(result, "");
+		return cgiFormNotFound;
+	}
+	s = e->fileName;
+	while (*s) {
+		APPEND(result, *s);
+		s++;
+	}	
+	if (resultSpace) {
+		result[resultLen] = '\0';
+	}
+	if (!strlen(e->fileName)) {
+		return cgiFormNoFileName;
+	} else if (((int) strlen(e->fileName)) > (resultSpace - 1)) {
+		return cgiFormTruncated;
+	} else {
+		return cgiFormSuccess;
+	}
+}
+
+cgiFormResultType cgiFormFileContentType(
+	char *name, char *result, int resultSpace)
+{
+	cgiFormEntry *e;
+	int resultLen = 0;
+	char *s;
+	e = cgiFormEntryFindFirst(name);
+	if (!e) {
+		if (resultSpace) {
+			result[0] = '\0';
+		}	
+		return cgiFormNotFound;
+	}
+	s = e->contentType;
+	while (*s) {
+		APPEND(result, *s);
+		s++;
+	}	
+	if (resultSpace) {
+		result[resultLen] = '\0';
+	}
+	if (!strlen(e->contentType)) {
+		return cgiFormNoContentType;
+	} else if (((int) strlen(e->contentType)) > (resultSpace - 1)) {
+		return cgiFormTruncated;
+	} else {
+		return cgiFormSuccess;
+	}
+}
+
+cgiFormResultType cgiFormFileSize(
+	char *name, int *sizeP)
+{
+	cgiFormEntry *e;
+	e = cgiFormEntryFindFirst(name);
+	if (!e) {
+		if (sizeP) {
+			*sizeP = 0;
+		}
+		return cgiFormNotFound;
+	} else if (!strlen(e->tfileName)) {
+		if (sizeP) {
+			*sizeP = 0;
+		}
+		return cgiFormNotAFile;
+	} else {
+		if (sizeP) {
+			*sizeP = e->valueLength;
+		}
+		return cgiFormSuccess;
+	}
+}
+
+typedef struct cgiFileStruct {
+	FILE *in;
+} cgiFile;
+
+cgiFormResultType cgiFormFileOpen(
+	char *name, cgiFilePtr *cfpp)
+{
+	cgiFormEntry *e;
+	cgiFilePtr cfp;
+	e = cgiFormEntryFindFirst(name);
+	if (!e) {
+		*cfpp = 0;
+		return cgiFormNotFound;
+	}
+	if (!strlen(e->tfileName)) {
+		*cfpp = 0;
+		return cgiFormNotAFile;
+	}
+	cfp = (cgiFilePtr) malloc(sizeof(cgiFile));
+	if (!cfp) {
+		*cfpp = 0;
+		return cgiFormMemory;
+	}
+	cfp->in = fopen(e->tfileName, "rb");
+	if (!cfp->in) {
+		free(cfp);
+		return cgiFormIO;
+	}
+	*cfpp = cfp;
+	return cgiFormSuccess;
+}
+
+cgiFormResultType cgiFormFileRead(
+	cgiFilePtr cfp, char *buffer, 
+	int bufferSize, int *gotP)
+{
+	int got = 0;
+	if (!cfp) {
+		return cgiFormOpenFailed;
+	}
+	got = fread(buffer, 1, bufferSize, cfp->in);
+	if (got <= 0) {
+		return cgiFormEOF;
+	}
+	*gotP = got;
+	return cgiFormSuccess;
+}
+
+cgiFormResultType cgiFormFileClose(cgiFilePtr cfp)
+{
+	if (!cfp) {
+		return cgiFormOpenFailed;
+	}
+	fclose(cfp->in);
+	free(cfp);
+	return cgiFormSuccess;
+}
+
+cgiFormResultType cgiFormStringNoNewlines(
+        char *name, char *result, int max) {
+	cgiFormEntry *e;
+	e = cgiFormEntryFindFirst(name);
+	if (!e) {
+		strcpy(result, "");
+		return cgiFormNotFound;
+	}
+	return cgiFormEntryString(e, result, max, 0);
+}
+
+cgiFormResultType cgiFormStringMultiple(
+        char *name, char ***result) {
+	char **stringArray;
+	cgiFormEntry *e;
+	int i;
+	int total = 0;
+	/* Make two passes. One would be more efficient, but this
+		function is not commonly used. The select menu and
+		radio box functions are faster. */
+	e = cgiFormEntryFindFirst(name);
+	if (e != 0) {
+		do {
+			total++;
+		} while ((e = cgiFormEntryFindNext()) != 0); 
+	}
+	stringArray = (char **) malloc(sizeof(char *) * (total + 1));
+	if (!stringArray) {
+		*result = 0;
+		return cgiFormMemory;
+	}
+	/* initialize all entries to null; the last will stay that way */
+	for (i=0; (i <= total); i++) {
+		stringArray[i] = 0;
+	}
+	/* Now go get the entries */
+	e = cgiFormEntryFindFirst(name);
+#ifdef CGICDEBUG
+	CGICDEBUGSTART
+	fprintf(dout, "StringMultiple Beginning\n");
+	CGICDEBUGEND
+#endif /* CGICDEBUG */
+	if (e) {
+		i = 0;
+		do {
+			int max = (int) (strlen(e->value) + 1);
+			stringArray[i] = (char *) malloc(max);
+			if (stringArray[i] == 0) {
+				/* Memory problems */
+				cgiStringArrayFree(stringArray);
+				*result = 0;
+				return cgiFormMemory;
+			}	
+			strcpy(stringArray[i], e->value);
+			cgiFormEntryString(e, stringArray[i], max, 1);
+			i++;
+		} while ((e = cgiFormEntryFindNext()) != 0); 
+		*result = stringArray;
+#ifdef CGICDEBUG
+		CGICDEBUGSTART
+		fprintf(dout, "StringMultiple Succeeding\n");
+		CGICDEBUGEND
+#endif /* CGICDEBUG */
+		return cgiFormSuccess;
+	} else {
+		*result = stringArray;
+#ifdef CGICDEBUG
+		CGICDEBUGSTART
+		fprintf(dout, "StringMultiple found nothing\n");
+		CGICDEBUGEND
+#endif /* CGICDEBUG */
+		return cgiFormNotFound;
+	}	
+}
+
+cgiFormResultType cgiFormStringSpaceNeeded(
+        char *name, int *result) {
+	cgiFormEntry *e;
+	e = cgiFormEntryFindFirst(name);
+	if (!e) {
+		*result = 1;
+		return cgiFormNotFound; 
+	}
+	*result = ((int) strlen(e->value)) + 1;
+	return cgiFormSuccess;
+}
+
+static cgiFormResultType cgiFormEntryString(
+	cgiFormEntry *e, char *result, int max, int newlines) {
+	char *dp, *sp;
+	int truncated = 0;
+	int len = 0;
+	int avail = max-1;
+	int crCount = 0;
+	int lfCount = 0;	
+	dp = result;
+	sp = e->value;	
+	while (1) {
+		int ch;
+		/* 1.07: don't check for available space now.
+			We check for it immediately before adding
+			an actual character. 1.06 handled the
+			trailing null of the source string improperly,
+			resulting in a cgiFormTruncated error. */
+		ch = *sp;
+		/* Fix the CR/LF, LF, CR nightmare: watch for
+			consecutive bursts of CRs and LFs in whatever
+			pattern, then actually output the larger number 
+			of LFs. Consistently sane, yet it still allows
+			consecutive blank lines when the user
+			actually intends them. */
+		if ((ch == 13) || (ch == 10)) {
+			if (ch == 13) {
+				crCount++;
+			} else {
+				lfCount++;
+			}	
+		} else {
+			if (crCount || lfCount) {
+				int lfsAdd = crCount;
+				if (lfCount > crCount) {
+					lfsAdd = lfCount;
+				}
+				/* Stomp all newlines if desired */
+				if (!newlines) {
+					lfsAdd = 0;
+				}
+				while (lfsAdd) {
+					if (len >= avail) {
+						truncated = 1;
+						break;
+					}
+					*dp = 10;
+					dp++;
+					lfsAdd--;
+					len++;		
+				}
+				crCount = 0;
+				lfCount = 0;
+			}
+			if (ch == '\0') {
+				/* The end of the source string */
+				break;				
+			}	
+			/* 1.06: check available space before adding
+				the character, because a previously added
+				LF may have brought us to the limit */
+			if (len >= avail) {
+				truncated = 1;
+				break;
+			}
+			*dp = ch;
+			dp++;
+			len++;
+		}
+		sp++;	
+	}	
+	*dp = '\0';
+	if (truncated) {
+		return cgiFormTruncated;
+	} else if (!len) {
+		return cgiFormEmpty;
+	} else {
+		return cgiFormSuccess;
+	}
+}
+
+static int cgiFirstNonspaceChar(char *s);
+
+cgiFormResultType cgiFormInteger(
+        char *name, int *result, int defaultV) {
+	cgiFormEntry *e;
+	int ch;
+	e = cgiFormEntryFindFirst(name);
+	if (!e) {
+		*result = defaultV;
+		return cgiFormNotFound; 
+	}	
+	if (!strlen(e->value)) {
+		*result = defaultV;
+		return cgiFormEmpty;
+	}
+	ch = cgiFirstNonspaceChar(e->value);
+	if (!(isdigit(ch)) && (ch != '-') && (ch != '+')) {
+		*result = defaultV;
+		return cgiFormBadType;
+	} else {
+		*result = atoi(e->value);
+		return cgiFormSuccess;
+	}
+}
+
+cgiFormResultType cgiFormIntegerBounded(
+        char *name, int *result, int min, int max, int defaultV) {
+	cgiFormResultType error = cgiFormInteger(name, result, defaultV);
+	if (error != cgiFormSuccess) {
+		return error;
+	}
+	if (*result < min) {
+		*result = min;
+		return cgiFormConstrained;
+	} 
+	if (*result > max) {
+		*result = max;
+		return cgiFormConstrained;
+	} 
+	return cgiFormSuccess;
+}
+
+cgiFormResultType cgiFormDouble(
+        char *name, double *result, double defaultV) {
+	cgiFormEntry *e;
+	int ch;
+	e = cgiFormEntryFindFirst(name);
+	if (!e) {
+		*result = defaultV;
+		return cgiFormNotFound; 
+	}	
+	if (!strlen(e->value)) {
+		*result = defaultV;
+		return cgiFormEmpty;
+	} 
+	ch = cgiFirstNonspaceChar(e->value);
+	if (!(isdigit(ch)) && (ch != '.') && (ch != '-') && (ch != '+')) {
+		*result = defaultV;
+		return cgiFormBadType;
+	} else {
+		*result = atof(e->value);
+		return cgiFormSuccess;
+	}
+}
+
+cgiFormResultType cgiFormDoubleBounded(
+        char *name, double *result, double min, double max, double defaultV) {
+	cgiFormResultType error = cgiFormDouble(name, result, defaultV);
+	if (error != cgiFormSuccess) {
+		return error;
+	}
+	if (*result < min) {
+		*result = min;
+		return cgiFormConstrained;
+	} 
+	if (*result > max) {
+		*result = max;
+		return cgiFormConstrained;
+	} 
+	return cgiFormSuccess;
+}
+
+cgiFormResultType cgiFormSelectSingle(
+	char *name, char **choicesText, int choicesTotal, 
+	int *result, int defaultV) 
+{
+	cgiFormEntry *e;
+	int i;
+	e = cgiFormEntryFindFirst(name);
+#ifdef CGICDEBUG
+	CGICDEBUGSTART
+	fprintf(dout, "%d\n", (int) e);
+	CGICDEBUGEND
+#endif /* CGICDEBUG */
+	if (!e) {
+		*result = defaultV;
+		return cgiFormNotFound;
+	}
+	for (i=0; (i < choicesTotal); i++) {
+#ifdef CGICDEBUG
+		CGICDEBUGSTART
+		fprintf(dout, "%s %s\n", choicesText[i], e->value);
+		CGICDEBUGEND
+#endif /* CGICDEBUG */
+		if (cgiStrEq(choicesText[i], e->value)) {
+#ifdef CGICDEBUG
+			CGICDEBUGSTART
+			fprintf(dout, "MATCH\n");
+			CGICDEBUGEND
+#endif /* CGICDEBUG */
+			*result = i;
+			return cgiFormSuccess;
+		}
+	}
+	*result = defaultV;
+	return cgiFormNoSuchChoice;
+}
+
+cgiFormResultType cgiFormSelectMultiple(
+	char *name, char **choicesText, int choicesTotal, 
+	int *result, int *invalid) 
+{
+	cgiFormEntry *e;
+	int i;
+	int hits = 0;
+	int invalidE = 0;
+	for (i=0; (i < choicesTotal); i++) {
+		result[i] = 0;
+	}
+	e = cgiFormEntryFindFirst(name);
+	if (!e) {
+		*invalid = invalidE;
+		return cgiFormNotFound;
+	}
+	do {
+		int hit = 0;
+		for (i=0; (i < choicesTotal); i++) {
+			if (cgiStrEq(choicesText[i], e->value)) {
+				result[i] = 1;
+				hits++;
+				hit = 1;
+				break;
+			}
+		}
+		if (!(hit)) {
+			invalidE++;
+		}
+	} while ((e = cgiFormEntryFindNext()) != 0);
+
+	*invalid = invalidE;
+
+	if (hits) {
+		return cgiFormSuccess;
+	} else {
+		return cgiFormNotFound;
+	}
+}
+
+cgiFormResultType cgiFormCheckboxSingle(
+	char *name)
+{
+	cgiFormEntry *e;
+	e = cgiFormEntryFindFirst(name);
+	if (!e) {
+		return cgiFormNotFound;
+	}
+	return cgiFormSuccess;
+}
+
+extern cgiFormResultType cgiFormCheckboxMultiple(
+	char *name, char **valuesText, int valuesTotal, 
+	int *result, int *invalid)
+{
+	/* Implementation is identical to cgiFormSelectMultiple. */
+	return cgiFormSelectMultiple(name, valuesText, 
+		valuesTotal, result, invalid);
+}
+
+cgiFormResultType cgiFormRadio(
+	char *name, 
+	char **valuesText, int valuesTotal, int *result, int defaultV)
+{
+	/* Implementation is identical to cgiFormSelectSingle. */
+	return cgiFormSelectSingle(name, valuesText, valuesTotal, 
+		result, defaultV);
+}
+
+cgiFormResultType cgiCookieString(
+	char *name,
+	char *value,
+	int space)
+{
+	char *p = cgiCookie;
+	while (*p) {
+		char *n = name;
+		/* 2.02: if cgiCookie is exactly equal to name, this
+			can cause an overrun. The server probably wouldn't
+			allow it, since a name without values makes no sense 
+			-- but then again it might not check, so this is a
+			genuine security concern. Thanks to Nicolas 
+			Tomadakis. */
+		while (*p == *n) {
+			if ((p == '\0') && (n == '\0')) {
+				/* Malformed cookie header from client */
+				return cgiFormNotFound;
+			}
+			p++;
+			n++;
+		}
+		if ((!*n) && (*p == '=')) {
+			p++;
+			while ((*p != ';') && (*p != '\0') &&
+				(space > 1)) 
+			{
+				*value = *p;
+				value++;
+				p++;
+				space--;
+			}
+			if (space > 0) {
+				*value = '\0';
+			}
+			/* Correct parens: 2.02. Thanks to
+				Mathieu Villeneuve-Belair. */
+			if (!(((*p) == ';') || ((*p) == '\0')))
+			{
+				return cgiFormTruncated;
+			} else {	
+				return cgiFormSuccess;
+			}
+		} else {
+			/* Skip to next cookie */	
+			while (*p) {
+				if (*p == ';') {
+					break;
+				}
+				p++;
+			}
+			if (!*p) {
+				/* 2.01: default to empty */
+				if (space) {
+					*value = '\0';
+				}
+				return cgiFormNotFound;
+			}
+			p++;	
+			/* Allow whitespace after semicolon */
+			while ((*p) && isspace(*p)) {
+				p++;
+			} 
+		}
+	}
+	/* 2.01: actually the above loop never terminates except
+		with a return, but do this to placate gcc */
+	if (space) {
+		*value = '\0';
+	}
+	return cgiFormNotFound;
+}
+
+cgiFormResultType cgiCookieInteger(
+	char *name,
+	int *result,
+	int defaultV)
+{
+	char buffer[256];
+	cgiFormResultType r = 
+		cgiCookieString(name, buffer, sizeof(buffer));
+	if (r != cgiFormSuccess) {
+		*result = defaultV;
+	} else {
+		*result = atoi(buffer);
+	}
+	return r;
+}
+
+void cgiHeaderCookieSetInteger(char *name, int value, int secondsToLive,
+	char *path, char *domain)
+{
+	char svalue[256];
+	sprintf(svalue, "%d", value);
+	cgiHeaderCookieSetString(name, svalue, secondsToLive, path, domain);
+}
+
+char *days[] = {
+	"Sun",
+	"Mon",
+	"Tue",
+	"Wed",
+	"Thu",
+	"Fri",
+	"Sat"
+};
+
+char *months[] = {
+	"Jan",
+	"Feb",
+	"Mar",
+	"Apr",
+	"May",
+	"Jun",
+	"Jul",
+	"Aug",
+	"Sep",
+	"Oct",
+	"Nov",
+	"Dec"
+};
+
+void cgiHeaderCookieSetString(char *name, char *value, int secondsToLive,
+	char *path, char *domain)
+{
+	/* cgic 2.02: simpler and more widely compatible implementation.
+		Thanks to Chunfu Lai. 
+	   cgic 2.03: yes, but it didn't work. Reimplemented by
+		Thomas Boutell. ; after last element was a bug. 
+	   Examples of real world cookies that really work:
+   	   Set-Cookie: MSNADS=UM=; domain=.slate.com; 
+             expires=Tue, 26-Apr-2022 19:00:00 GMT; path=/
+	   Set-Cookie: MC1=V=3&ID=b5bc08af2b8a43ff85fcb5efd8b238f0; 
+             domain=.slate.com; expires=Mon, 04-Oct-2021 19:00:00 GMT; path=/
+	*/
+	time_t now;
+	time_t then;
+	struct tm *gt;
+	time(&now);
+	then = now + secondsToLive;
+	gt = gmtime(&then);
+	fprintf(cgiOut, 
+		"Set-Cookie: %s=%s; domain=%s; expires=%s, %02d-%s-%04d %02d:%02d:%02d GMT; path=%s\r\n",
+		name, value, domain, 
+		days[gt->tm_wday],
+		gt->tm_mday,
+		months[gt->tm_mon],
+		gt->tm_year + 1900, 	
+		gt->tm_hour,
+		gt->tm_min,
+		gt->tm_sec,
+		path);
+}
+
+void cgiHeaderLocation(char *redirectUrl) {
+	fprintf(cgiOut, "Location: %s\r\n\r\n", redirectUrl);
+}
+
+void cgiHeaderStatus(int status, char *statusMessage) {
+	fprintf(cgiOut, "Status: %d %s\r\n\r\n", status, statusMessage);
+}
+
+void cgiHeaderContentType(char *mimeType) {
+	fprintf(cgiOut, "Content-type: %s\r\n\r\n", mimeType);
+}
+
+static int cgiWriteString(FILE *out, char *s);
+
+static int cgiWriteInt(FILE *out, int i);
+
+#define CGIC_VERSION "2.0"
+
+cgiEnvironmentResultType cgiWriteEnvironment(char *filename) {
+	FILE *out;
+	cgiFormEntry *e;
+	/* Be sure to open in binary mode */
+	out = fopen(filename, "wb");
+	if (!out) {
+		/* Can't create file */
+		return cgiEnvironmentIO;
+	}
+	if (!cgiWriteString(out, "CGIC2.0")) {
+		goto error;
+	}
+	if (!cgiWriteString(out, cgiServerSoftware)) {
+		goto error;
+	}
+	if (!cgiWriteString(out, cgiServerName)) {
+		goto error;
+	}
+	if (!cgiWriteString(out, cgiGatewayInterface)) {
+		goto error;
+	}
+	if (!cgiWriteString(out, cgiServerProtocol)) {
+		goto error;
+	}
+	if (!cgiWriteString(out, cgiServerPort)) {
+		goto error;
+	}
+	if (!cgiWriteString(out, cgiRequestMethod)) {
+		goto error;
+	}
+	if (!cgiWriteString(out, cgiPathInfo)) {
+		goto error;
+	}
+	if (!cgiWriteString(out, cgiPathTranslated)) {
+		goto error;
+	}
+	if (!cgiWriteString(out, cgiScriptName)) {
+		goto error;
+	}
+	if (!cgiWriteString(out, cgiQueryString)) {
+		goto error;
+	}
+	if (!cgiWriteString(out, cgiRemoteHost)) {
+		goto error;
+	}
+	if (!cgiWriteString(out, cgiRemoteAddr)) {
+		goto error;
+	}
+	if (!cgiWriteString(out, cgiAuthType)) {
+		goto error;
+	}
+	if (!cgiWriteString(out, cgiRemoteUser)) {
+		goto error;
+	}
+	if (!cgiWriteString(out, cgiRemoteIdent)) {
+		goto error;
+	}
+	if (!cgiWriteString(out, cgiContentType)) {
+		goto error;
+	}
+	if (!cgiWriteString(out, cgiAccept)) {
+		goto error;
+	}
+	if (!cgiWriteString(out, cgiUserAgent)) {
+		goto error;
+	}
+	if (!cgiWriteString(out, cgiReferrer)) {
+		goto error;
+	}
+	if (!cgiWriteString(out, cgiCookie)) {
+		goto error;
+	}
+	if (!cgiWriteInt(out, cgiContentLength)) {
+		goto error;
+	}
+	e = cgiFormEntryFirst;
+	while (e) {
+		cgiFilePtr fp;
+		if (!cgiWriteString(out, e->attr)) {
+			goto error;
+		}
+		if (!cgiWriteString(out, e->value)) {
+			goto error;
+		}
+		/* New 2.0 fields and file uploads */
+		if (!cgiWriteString(out, e->fileName)) {
+			goto error;
+		}
+		if (!cgiWriteString(out, e->contentType)) {
+			goto error;
+		}
+		if (!cgiWriteInt(out, e->valueLength)) {
+			goto error;
+		}
+		if (cgiFormFileOpen(e->attr, &fp) == cgiFormSuccess) {
+			char buffer[1024];
+			int got;
+			if (!cgiWriteInt(out, 1)) {
+				cgiFormFileClose(fp);
+				goto error;
+			}
+			while (cgiFormFileRead(fp, buffer, 
+				sizeof(buffer), &got) == cgiFormSuccess)
+			{
+				if (((int) fwrite(buffer, 1, got, out)) != got) {
+					cgiFormFileClose(fp);
+					goto error;
+				}
+			}
+			if (cgiFormFileClose(fp) != cgiFormSuccess) {
+				goto error;
+			}
+		} else {
+			if (!cgiWriteInt(out, 0)) {
+				goto error;
+			}
+		}
+		e = e->next;
+	}
+	fclose(out);
+	return cgiEnvironmentSuccess;
+error:
+	fclose(out);
+	/* If this function is not defined in your system,
+		you must substitute the appropriate 
+		file-deletion function. */
+	unlink(filename);
+	return cgiEnvironmentIO;
+}
+
+static int cgiWriteString(FILE *out, char *s) {
+	int len = (int) strlen(s);
+	cgiWriteInt(out, len);
+	if (((int) fwrite(s, 1, len, out)) != len) {
+		return 0;
+	}
+	return 1;
+}
+
+static int cgiWriteInt(FILE *out, int i) {
+	if (!fwrite(&i, sizeof(int), 1, out)) {
+		return 0;
+	}
+	return 1;
+}
+
+static int cgiReadString(FILE *out, char **s);
+
+static int cgiReadInt(FILE *out, int *i);
+
+cgiEnvironmentResultType cgiReadEnvironment(char *filename) {
+	FILE *in;
+	cgiFormEntry *e = 0, *p;
+	char *version;
+	/* Prevent compiler warnings */
+	cgiEnvironmentResultType result = cgiEnvironmentIO;
+	/* Free any existing data first */
+	cgiFreeResources();
+	/* Be sure to open in binary mode */
+	in = fopen(filename, "rb");
+	if (!in) {
+		/* Can't access file */
+		return cgiEnvironmentIO;
+	}
+	if (!cgiReadString(in, &version)) {
+		goto error;
+	}
+	if (strcmp(version, "CGIC" CGIC_VERSION)) {
+		/* 2.02: Merezko Oleg */
+		free(version);
+		return cgiEnvironmentWrongVersion;
+	}	
+	/* 2.02: Merezko Oleg */
+	free(version);
+	if (!cgiReadString(in, &cgiServerSoftware)) {
+		goto error;
+	}
+	if (!cgiReadString(in, &cgiServerName)) {
+		goto error;
+	}
+	if (!cgiReadString(in, &cgiGatewayInterface)) {
+		goto error;
+	}
+	if (!cgiReadString(in, &cgiServerProtocol)) {
+		goto error;
+	}
+	if (!cgiReadString(in, &cgiServerPort)) {
+		goto error;
+	}
+	if (!cgiReadString(in, &cgiRequestMethod)) {
+		goto error;
+	}
+	if (!cgiReadString(in, &cgiPathInfo)) {
+		goto error;
+	}
+	if (!cgiReadString(in, &cgiPathTranslated)) {
+		goto error;
+	}
+	if (!cgiReadString(in, &cgiScriptName)) {
+		goto error;
+	}
+	if (!cgiReadString(in, &cgiQueryString)) {
+		goto error;
+	}
+	if (!cgiReadString(in, &cgiRemoteHost)) {
+		goto error;
+	}
+	if (!cgiReadString(in, &cgiRemoteAddr)) {
+		goto error;
+	}
+	if (!cgiReadString(in, &cgiAuthType)) {
+		goto error;
+	}
+	if (!cgiReadString(in, &cgiRemoteUser)) {
+		goto error;
+	}
+	if (!cgiReadString(in, &cgiRemoteIdent)) {
+		goto error;
+	}
+	if (!cgiReadString(in, &cgiContentType)) {
+		goto error;
+	}
+	if (!cgiReadString(in, &cgiAccept)) {
+		goto error;
+	}
+	if (!cgiReadString(in, &cgiUserAgent)) {
+		goto error;
+	}
+	if (!cgiReadString(in, &cgiReferrer)) {
+		goto error;
+	}
+	/* 2.0 */
+	if (!cgiReadString(in, &cgiCookie)) {
+		goto error;
+	}
+	if (!cgiReadInt(in, &cgiContentLength)) {
+		goto error;
+	}
+	p = 0;
+	while (1) {
+		int fileFlag;
+		e = (cgiFormEntry *) calloc(1, sizeof(cgiFormEntry));
+		if (!e) {
+			cgiFreeResources();
+			fclose(in);
+			return cgiEnvironmentMemory;
+		}
+		memset(e, 0, sizeof(cgiFormEntry));
+		if (!cgiReadString(in, &e->attr)) {
+			/* This means we've reached the end of the list. */
+			/* 2.02: thanks to Merezko Oleg */
+			free(e);
+			break;
+		}
+		if (!cgiReadString(in, &e->value)) {
+			goto outOfMemory;
+		}
+		if (!cgiReadString(in, &e->fileName)) {
+			goto outOfMemory;
+		}
+		if (!cgiReadString(in, &e->contentType)) {
+			goto outOfMemory;
+		}
+		if (!cgiReadInt(in, &e->valueLength)) {
+			goto outOfMemory;
+		}
+		if (!cgiReadInt(in, &fileFlag)) {
+			goto outOfMemory;
+		}
+		if (fileFlag) {
+			char buffer[1024];
+			FILE *out;
+			char tfileName[1024];
+			int got;
+			int len = e->valueLength;
+			if (getTempFileName(tfileName)
+				!= cgiParseSuccess)
+			{
+				result = cgiEnvironmentIO;
+				goto error;
+			}
+			out = fopen(tfileName, "w+b");
+			if (!out) {
+				result = cgiEnvironmentIO;
+				goto error;
+			}
+			while (len > 0) {		
+				/* 2.01: try is a bad variable name in
+					C++, and it wasn't being used
+					properly either */
+				int tryr = len;
+				if (tryr > ((int) sizeof(buffer))) {
+					tryr = sizeof(buffer);
+				}
+				got = fread(buffer, 1, tryr, in);
+				if (got <= 0) {
+					result = cgiEnvironmentIO;
+					fclose(out);
+					unlink(tfileName);
+					goto error;
+				}
+				if (((int) fwrite(buffer, 1, got, out)) != got) {
+					result = cgiEnvironmentIO;
+					fclose(out);
+					unlink(tfileName);
+					goto error;
+				}
+				len -= got;
+			}
+			/* cgic 2.05: should be fclose not rewind */
+			fclose(out);
+			e->tfileName = (char *) malloc((int) strlen(tfileName) + 1);
+			if (!e->tfileName) {
+				result = cgiEnvironmentMemory;
+				unlink(tfileName);
+				goto error;
+			}
+			strcpy(e->tfileName, tfileName);
+		} else {
+			e->tfileName = (char *) malloc(1);
+			if (!e->tfileName) {
+				result = cgiEnvironmentMemory;
+				goto error;
+			}
+		}	
+		e->next = 0;
+		if (p) {
+			p->next = e;
+		} else {
+			cgiFormEntryFirst = e;
+		}	
+		p = e;
+	}
+	fclose(in);
+	cgiRestored = 1;
+	return cgiEnvironmentSuccess;
+outOfMemory:
+	result = cgiEnvironmentMemory;
+error:
+	cgiFreeResources();
+	fclose(in);
+	if (e) {
+		if (e->attr) {
+			free(e->attr);
+		}
+		if (e->value) {
+			free(e->value);
+		}
+		if (e->fileName) {
+			free(e->fileName);
+		}
+		if (e->contentType) {
+			free(e->contentType);
+		}
+		if (e->tfileName) {
+			free(e->tfileName);
+		}
+		free(e);
+	}
+	return result;
+}
+
+static int cgiReadString(FILE *in, char **s) {
+	int len;
+	/* 2.0 fix: test cgiReadInt for failure! */ 
+	if (!cgiReadInt(in, &len)) {
+		return 0;
+	}
+	*s = (char *) malloc(len + 1);
+	if (!(*s)) {
+		return 0;
+	}	
+	if (((int) fread(*s, 1, len, in)) != len) {
+		return 0;
+	}
+	(*s)[len] = '\0';
+	return 1;
+}
+
+static int cgiReadInt(FILE *out, int *i) {
+	if (!fread(i, sizeof(int), 1, out)) {
+		return 0;
+	}
+	return 1;
+}
+
+static int cgiStrEqNc(char *s1, char *s2) {
+	while(1) {
+		if (!(*s1)) {
+			if (!(*s2)) {
+				return 1;
+			} else {
+				return 0;
+			}
+		} else if (!(*s2)) {
+			return 0;
+		}
+		if (isalpha(*s1)) {
+			if (tolower(*s1) != tolower(*s2)) {
+				return 0;
+			}
+		} else if ((*s1) != (*s2)) {
+			return 0;
+		}
+		s1++;
+		s2++;
+	}
+}
+
+static int cgiStrBeginsNc(char *s1, char *s2) {
+	while(1) {
+		if (!(*s2)) {
+			return 1;
+		} else if (!(*s1)) {
+			return 0;
+		}
+		if (isalpha(*s1)) {
+			if (tolower(*s1) != tolower(*s2)) {
+				return 0;
+			}
+		} else if ((*s1) != (*s2)) {
+			return 0;
+		}
+		s1++;
+		s2++;
+	}
+}
+
+static char *cgiFindTarget = 0;
+static cgiFormEntry *cgiFindPos = 0;
+
+static cgiFormEntry *cgiFormEntryFindFirst(char *name) {
+	cgiFindTarget = name;
+	cgiFindPos = cgiFormEntryFirst;
+	return cgiFormEntryFindNext();
+}
+
+static cgiFormEntry *cgiFormEntryFindNext() {
+	while (cgiFindPos) {
+		cgiFormEntry *c = cgiFindPos;
+		cgiFindPos = c->next;
+		if (!strcmp(c -> attr, cgiFindTarget)) {
+			return c;
+		}
+	}
+	return 0;
+}
+
+static int cgiFirstNonspaceChar(char *s) {
+	int len = strspn(s, " \n\r\t");
+	return s[len];
+}
+
+void cgiStringArrayFree(char **stringArray) {
+	char *p;
+	char **arrayItself = stringArray;
+	p = *stringArray;
+	while (p) {
+		free(p);
+		stringArray++;
+		p = *stringArray;
+	}
+	/* 2.0: free the array itself! */
+	free(arrayItself);
+}	
+
+cgiFormResultType cgiCookies(char ***result) {
+	char **stringArray;
+	int i;
+	int total = 0;
+	char *p;
+	char *n;
+	p = cgiCookie;
+	while (*p) {
+		if (*p == '=') {
+			total++;
+		}
+		p++;
+	}
+	stringArray = (char **) malloc(sizeof(char *) * (total + 1));
+	if (!stringArray) {
+		*result = 0;
+		return cgiFormMemory;
+	}
+	/* initialize all entries to null; the last will stay that way */
+	for (i=0; (i <= total); i++) {
+		stringArray[i] = 0;
+	}
+	i = 0;
+	p = cgiCookie;
+	while (*p) {
+		while (*p && isspace(*p)) {
+			p++;
+		}
+		n = p;
+		while (*p && (*p != '=')) {
+			p++;
+		}
+		if (p != n) {
+			stringArray[i] = (char *) malloc((p - n) + 1);
+			if (!stringArray[i]) {
+				cgiStringArrayFree(stringArray);
+				*result = 0;
+				return cgiFormMemory;
+			}	
+			memcpy(stringArray[i], n, p - n);
+			stringArray[i][p - n] = '\0';
+			i++;
+		}
+		while (*p && (*p != ';')) {
+			p++;	
+		}
+		if (!*p) {
+			break;
+		}
+		if (*p == ';') {
+			p++;
+		}
+	}
+	*result = stringArray;
+	return cgiFormSuccess;
+}
+
+cgiFormResultType cgiFormEntries(char ***result) {
+	char **stringArray;
+	cgiFormEntry *e, *pe;
+	int i;
+	int total = 0;
+	e = cgiFormEntryFirst;
+	while (e) {
+		/* Don't count a field name more than once if
+			multiple values happen to be present for it */
+		pe = cgiFormEntryFirst;
+		while (pe != e) {
+			if (!strcmp(e->attr, pe->attr)) {
+				goto skipSecondValue;
+			}
+			pe = pe->next;					
+		}
+		total++;
+skipSecondValue:
+		e = e->next;
+	}
+	stringArray = (char **) malloc(sizeof(char *) * (total + 1));
+	if (!stringArray) {
+		*result = 0;
+		return cgiFormMemory;
+	}
+	/* initialize all entries to null; the last will stay that way */
+	for (i=0; (i <= total); i++) {
+		stringArray[i] = 0;
+	}
+	/* Now go get the entries */
+	e = cgiFormEntryFirst;
+	i = 0;
+	while (e) {
+		int space;
+		/* Don't return a field name more than once if
+			multiple values happen to be present for it */
+		pe = cgiFormEntryFirst;
+		while (pe != e) {
+			if (!strcmp(e->attr, pe->attr)) {
+				goto skipSecondValue2;
+			}
+			pe = pe->next;					
+		}		
+		space = (int) strlen(e->attr) + 1;
+		stringArray[i] = (char *) malloc(space);
+		if (stringArray[i] == 0) {
+			/* Memory problems */
+			cgiStringArrayFree(stringArray);
+			*result = 0;
+			return cgiFormMemory;
+		}	
+		strcpy(stringArray[i], e->attr);
+		i++;
+skipSecondValue2:
+		e = e->next;
+	}
+	*result = stringArray;
+	return cgiFormSuccess;
+}
+
+#define TRYPUTC(ch) \
+	{ \
+		if (putc((ch), cgiOut) == EOF) { \
+			return cgiFormIO; \
+		} \
+	} 
+
+cgiFormResultType cgiHtmlEscapeData(char *data, int len)
+{
+	while (len--) {
+		if (*data == '<') {
+			TRYPUTC('&');
+			TRYPUTC('l');
+			TRYPUTC('t');
+			TRYPUTC(';');
+		} else if (*data == '&') {
+			TRYPUTC('&');
+			TRYPUTC('a');
+			TRYPUTC('m');
+			TRYPUTC('p');
+			TRYPUTC(';');
+		} else if (*data == '>') {
+			TRYPUTC('&');
+			TRYPUTC('g');
+			TRYPUTC('t');
+			TRYPUTC(';');
+		} else {
+			TRYPUTC(*data);
+		}
+		data++;
+	}
+	return cgiFormSuccess;
+}
+
+cgiFormResultType cgiHtmlEscape(char *s)
+{
+	return cgiHtmlEscapeData(s, (int) strlen(s));
+}
+
+/* Output data with the " character HTML-escaped, and no
+	other characters escaped. This is useful when outputting
+	the contents of a tag attribute such as 'href' or 'src'.
+	'data' is not null-terminated; 'len' is the number of
+	bytes in 'data'. Returns cgiFormIO in the event
+	of error, cgiFormSuccess otherwise. */
+cgiFormResultType cgiValueEscapeData(char *data, int len)
+{
+	while (len--) {
+		if (*data == '\"') {
+			TRYPUTC('&');
+			TRYPUTC('#');
+			TRYPUTC('3');
+			TRYPUTC('4');
+			TRYPUTC(';');
+		} else {
+			TRYPUTC(*data);
+		}
+		data++;
+	}
+	return cgiFormSuccess;
+}
+
+cgiFormResultType cgiValueEscape(char *s)
+{
+	return cgiValueEscapeData(s, (int) strlen(s));
+}
+
+
diff --git a/thirds/cgic206/cgic.h b/thirds/cgic206/cgic.h
new file mode 100644
index 0000000..2cce85d
--- /dev/null
+++ b/thirds/cgic206/cgic.h
@@ -0,0 +1,457 @@
+/* The CGI_C library, by Thomas Boutell, version 2.01. CGI_C is intended
+	to be a high-quality API to simplify CGI programming tasks. */
+
+/* Make sure this is only included once. */
+
+#ifndef CGI_C
+#define CGI_C 1
+
+/* Bring in standard I/O since some of the functions refer to
+	types defined by it, such as FILE *. */
+
+#include "fcgi_stdio.h"
+//#include <stdio.h>
+
+/* The various CGI environment variables. Instead of using getenv(),
+	the programmer should refer to these, which are always
+	valid null-terminated strings (they may be empty, but they 
+	will never be null). If these variables are used instead
+	of calling getenv(), then it will be possible to save
+	and restore CGI environments, which is highly convenient
+	for debugging. */
+
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+char *cgiServerSoftware;
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+char *cgiServerName;
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+char *cgiGatewayInterface;
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+char *cgiServerProtocol;
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+char *cgiServerPort;
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+char *cgiRequestMethod;
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+char *cgiPathInfo;
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+char *cgiPathTranslated;
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+char *cgiScriptName;
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+char *cgiQueryString;
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+char *cgiRemoteHost;
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+char *cgiRemoteAddr;
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+char *cgiAuthType;
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+char *cgiRemoteUser;
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+char *cgiRemoteIdent;
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+char *cgiContentType;
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+char *cgiAccept;
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+char *cgiUserAgent;
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+char *cgiReferrer;
+
+/* Cookies as sent to the server. You can also get them
+	individually, or as a string array; see the documentation. */
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+char *cgiCookie;
+
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+char *cgiSid;
+
+/* A macro providing the same incorrect spelling that is
+	found in the HTTP/CGI specifications */
+#define cgiReferer cgiReferrer
+
+/* The number of bytes of data received.
+	Note that if the submission is a form submission
+	the library will read and parse all the information
+	directly from cgiIn; the programmer need not do so. */
+
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+int cgiContentLength;
+
+/* Pointer to CGI output. The cgiHeader functions should be used
+	first to output the mime headers; the output HTML
+	page, GIF image or other web document should then be written
+	to cgiOut by the programmer. In the standard CGIC library,
+	cgiOut is always equivalent to stdout. */
+
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+FILE *cgiOut;
+
+/* Pointer to CGI input. The programmer does not read from this.
+	We have continued to export it for backwards compatibility
+	so that cgic 1.x applications link properly. */
+
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+FILE *cgiIn;
+
+/* Possible return codes from the cgiForm family of functions (see below). */
+
+typedef enum {
+	cgiFormSuccess,
+	cgiFormTruncated,
+	cgiFormBadType,
+	cgiFormEmpty,
+	cgiFormNotFound,
+	cgiFormConstrained,
+	cgiFormNoSuchChoice,
+	cgiFormMemory,
+	cgiFormNoFileName,
+	cgiFormNoContentType,
+	cgiFormNotAFile,
+	cgiFormOpenFailed,
+	cgiFormIO,
+	cgiFormEOF
+} cgiFormResultType;
+
+/* These functions are used to retrieve form data. See
+	cgic.html for documentation. */
+
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+cgiFormResultType cgiFormString(
+	char *name, char *result, int max);
+
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+cgiFormResultType cgiFormStringNoNewlines(
+	char *name, char *result, int max);
+
+
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+cgiFormResultType cgiFormStringSpaceNeeded(
+	char *name, int *length);
+
+
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+cgiFormResultType cgiFormStringMultiple(
+	char *name, char ***ptrToStringArray);
+
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+void cgiStringArrayFree(char **stringArray);
+
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+cgiFormResultType cgiFormInteger(
+	char *name, int *result, int defaultV);
+
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+cgiFormResultType cgiFormIntegerBounded(
+	char *name, int *result, int min, int max, int defaultV);
+
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+cgiFormResultType cgiFormDouble(
+	char *name, double *result, double defaultV);
+
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+cgiFormResultType cgiFormDoubleBounded(
+	char *name, double *result, double min, double max, double defaultV);
+
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+cgiFormResultType cgiFormSelectSingle(
+	char *name, char **choicesText, int choicesTotal, 
+	int *result, int defaultV);	
+
+
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+cgiFormResultType cgiFormSelectMultiple(
+	char *name, char **choicesText, int choicesTotal, 
+	int *result, int *invalid);
+
+/* Just an alias; users have asked for this */
+#define cgiFormSubmitClicked cgiFormCheckboxSingle
+
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+cgiFormResultType cgiFormCheckboxSingle(
+	char *name);
+
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+cgiFormResultType cgiFormCheckboxMultiple(
+	char *name, char **valuesText, int valuesTotal, 
+	int *result, int *invalid);
+
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+cgiFormResultType cgiFormRadio(
+	char *name, char **valuesText, int valuesTotal, 
+	int *result, int defaultV);	
+
+/* The paths returned by this function are the original names of files
+	as reported by the uploading web browser and shoult NOT be
+	blindly assumed to be "safe" names for server-side use! */
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+cgiFormResultType cgiFormFileName(
+	char *name, char *result, int max);
+
+/* The content type of the uploaded file, as reported by the browser.
+	It should NOT be assumed that browsers will never falsify
+	such information. */
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+cgiFormResultType cgiFormFileContentType(
+	char *name, char *result, int max);
+
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+cgiFormResultType cgiFormFileSize(
+	char *name, int *sizeP);
+
+typedef struct cgiFileStruct *cgiFilePtr;
+
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+cgiFormResultType cgiFormFileOpen(
+	char *name, cgiFilePtr *cfpp);
+
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+cgiFormResultType cgiFormFileRead(
+	cgiFilePtr cfp, char *buffer, int bufferSize, int *gotP);
+
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+cgiFormResultType cgiFormFileClose(
+	cgiFilePtr cfp);
+
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+cgiFormResultType cgiCookieString(
+	char *name, char *result, int max);
+
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+cgiFormResultType cgiCookieInteger(
+	char *name, int *result, int defaultV);
+
+cgiFormResultType cgiCookies(
+	char ***ptrToStringArray);
+
+/* path can be null or empty in which case a path of / (entire site) is set. 
+	domain can be a single web site; if it is an entire domain, such as
+	'boutell.com', it should begin with a dot: '.boutell.com' */
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+void cgiHeaderCookieSetString(char *name, char *value, 
+	int secondsToLive, char *path, char *domain);
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+void cgiHeaderCookieSetInteger(char *name, int value,
+	int secondsToLive, char *path, char *domain);
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+void cgiHeaderLocation(char *redirectUrl);
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+void cgiHeaderStatus(int status, char *statusMessage);
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+void cgiHeaderContentType(char *mimeType);
+
+typedef enum {
+	cgiEnvironmentIO,
+	cgiEnvironmentMemory,
+	cgiEnvironmentSuccess,
+	cgiEnvironmentWrongVersion
+} cgiEnvironmentResultType;
+
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+cgiEnvironmentResultType cgiWriteEnvironment(char *filename);
+extern cgiEnvironmentResultType cgiReadEnvironment(char *filename);
+
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+int cgiMain();
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+int cgiMain_init();
+
+
+extern 
+#ifdef __cplusplus
+"C" 
+#endif
+cgiFormResultType cgiFormEntries(
+	char ***ptrToStringArray);
+
+/* Output string with the <, &, and > characters HTML-escaped. 
+	's' is null-terminated. Returns cgiFormIO in the event
+	of error, cgiFormSuccess otherwise. */
+cgiFormResultType cgiHtmlEscape(char *s);
+
+/* Output data with the <, &, and > characters HTML-escaped. 
+	'data' is not null-terminated; 'len' is the number of
+	bytes in 'data'. Returns cgiFormIO in the event
+	of error, cgiFormSuccess otherwise. */
+cgiFormResultType cgiHtmlEscapeData(char *data, int len);
+
+/* Output string with the " character HTML-escaped, and no
+	other characters escaped. This is useful when outputting
+	the contents of a tag attribute such as 'href' or 'src'.
+	's' is null-terminated. Returns cgiFormIO in the event
+	of error, cgiFormSuccess otherwise. */
+cgiFormResultType cgiValueEscape(char *s);
+
+/* Output data with the " character HTML-escaped, and no
+	other characters escaped. This is useful when outputting
+	the contents of a tag attribute such as 'href' or 'src'.
+	'data' is not null-terminated; 'len' is the number of
+	bytes in 'data'. Returns cgiFormIO in the event
+	of error, cgiFormSuccess otherwise. */
+cgiFormResultType cgiValueEscapeData(char *data, int len);
+
+#endif /* CGI_C */
+
diff --git a/thirds/cgic206/cgic.html b/thirds/cgic206/cgic.html
new file mode 100644
index 0000000..6f1f0fb
--- /dev/null
+++ b/thirds/cgic206/cgic.html
@@ -0,0 +1,2116 @@
+<html>
+<head>
+<title>cgic: an ANSI C library for CGI Programming</title>
+</head>
+<body>
+<h1>cgic 2.05: an ANSI C library for CGI Programming</h1>
+<h2>By <a href="http://www.boutell.com/boutell/">Thomas Boutell</a></h2>
+<em><a href="http://www.boutell.com/cgic/">
+The LATEST documentation is available here. Check often
+for new releases.</a></em>
+<blockquote>
+<strong>IMPORTANT NOTICES:</strong>
+<p>
+If you have CGIC 1.05 or earlier, you should upgrade to CGIC 1.07,
+or to CGIC 2.02 or better, in order to obtain important security fixes.
+<p>
+If you have CGIC 2.0 or CGIC 2.01 and you use the cgiCookie routines, 
+you should upgrade to CGIC 2.02 or better, in order to obtain
+important security fixes.
+</blockquote>
+<h3>Table of Contents</h3>
+<ul>
+<li><a href="#credits">Credits and license terms</a>
+<li><a href="#support">How to get support</a>
+<li><a href="#whatsnew205">What's new in version XYZ of CGIC?</a>
+<li><a href="#whatis">What is cgic?</a>
+<li><a href="#obtain">Obtaining cgic</a>
+<li><a href="#build">Building and testing cgic: a sample application</a>
+<li><a href="#nocompile">What to do if it won't compile</a>
+<li><a href="#howto">How to write a cgic application</a>
+<li><a href="#images">How can I generate images from my cgic application?</a>
+<li><a href="#debug">CGI debugging features: using capture</a>
+<li><a href="#functions">cgic function reference</a>
+<li><a href="#variables">cgic variable reference</a>
+<li><a href="#resultcodes">cgic result code reference</a>
+<li><a href="#index">cgic quick index</a>
+</ul>
+
+<h3><a name="credits">Credits and License Terms</a></h3>
+
+cgic can be used free of charge, <strong>provided that a
+credit notice is provided online.</strong> Alternatively,
+a nonexclusive Commercial License can be purchased, which
+grants the right to use cgic without a public credit notice.
+<p>
+Please see the file
+<code><a href="license.txt">license.txt</a></code>
+for the details of the Basic License and Commercial License,
+including ordering information for the Commercial License.
+<p>
+Thanks are due to Robert Gustavsson, Ken Holervich, Bob Nestor, 
+Jon Ribbens, Thomas Strangert, Wu Yongwei, and other CGIC users 
+who have corresponded over the years. Although the implementation
+of multipart/form-data file upload support in CGIC 2.x is my own, 
+I particularly wish to thank those who submitted their own 
+implementations of this feature.
+<h3><a name="support">How to Get Support</a></h3>
+<blockquote>
+<h4>STOP! READ THIS FIRST! REALLY!</h4>
+    Are you getting a "server error," indicating that your web server
+    "cannot allow POST to this URL," or a similar message? <strong>YOU MUST
+    CONFIGURE YOUR WEB SERVER TO ALLOW CGI PROGRAMS, AND YOU MUST
+    INSTALL CGI PROGRAMS IN THE LOCATION (OR WITH THE EXTENSION) THAT
+    YOUR WEB SERVER EXPECTS TO SEE.</strong> Please don't send me email about
+    this, unless you wish me to configure your web server for you; I can
+    certainly do that for $50/hr, but you can probably straighten this out
+    yourself or have your web server administrator do it.
+</blockquote>
+<h4>Free Support</h4>
+Please submit support inquiries about CGIC via our                              <a href="http://www.boutell.com/contact/">contact page</a>.
+Please note that we receive a large volume of inquiries and cannot always
+respond personally. Sometimes
+the response must take the form of an eventual
+new release or an addition to a FAQ or other document, as opposed to an
+detailed individual response.
+<h4>Hourly Support</h4>
+Those requiring support in detail may arrange for direct support
+from the author, Thomas Boutell, at the rate of $50/hr, billed
+directly by credit card. To make arrangements, contact us via our
+our <a href="https://www.boutell.com/freeform/">secure
+message page</a>. To avoid delay, be sure to specifically mention
+that you wish to purchase CGIC support at the hourly rate above.
+<h3><a name="whatsnew205">What's new in version 2.05?</a></h3>
+Uploaded files properly closed; corrects a resource leak and enables
+file uploads to work properly on platforms with particular file
+locking semantics.
+<h3><a name="whatsnew204">What's new in version 2.04?</a></h3>
+Documentation fixes: the cgiHtmlEscape, cgiHtmlEscapeData,
+cgiValueEscape, and cgiValueEscapeData routines were named
+incorrectly in the manual. No code changes in version 2.04.
+<h3><a name="whatsnew203">What's new in version 2.03?</a></h3>
+<ul>
+<li>Support for setting cookies has been reimplemented. The new
+code closely follows the actual practice of web sites that successfully
+use cookies, rather than attempting to implement the specification.
+The new code can successfully set more than one cookie at a time in
+typical web browsers.
+</ul>
+<h3><a name="whatsnew202">What's new in version 2.02?</a></h3>
+<ul>
+<li>In CGIC 2.0 and 2.01, if the HTTP_COOKIE environment variable
+was exactly equal to the name of a cookie requested with cgiCookieString,
+with no value or equal sign or other characters present, a buffer
+overrun could take place. This was not normal behavior and it is
+unknown whether any actual web server would allow it to occur, however
+we have of course released a patch to correct it. 
+Thanks to Nicolas Tomadakis.
+<li>cgiCookieString returned cgiFormTruncated when cgiFormSuccess would
+be appropriate. Fixed; thanks to Mathieu Villeneuve-Belair.
+<li>Cookies are now set using a simpler Set-Cookie: header, and with
+one header line per cookie, based on data collected by Chunfu Lai. 
+<li>Memory leaks in cgiReadEnvironment fixed by Merezko Oleg. These
+memory leaks were <em>not</em> experienced in a normal CGI situation, only
+when reading a saved CGI environment.
+</ul>
+<h3><a name="whatsnew201">What's new in version 2.01?</a></h3>
+<ul>
+<li>Makefile supports "make install"
+<li>Compiles without warnings under both C and C++ with strict
+warnings and strict ANSI compliance enabled
+<li>Builds out of the box on Windows (#include <fcntl.h> was needed)
+<li>Rare problem in cgiReadEnvironment corrected; no impact on
+normal CGI operations
+<li>cgiCookieString now sets the result to an empty string
+when returning cgiFormNotFound
+<li>Minor code cleanups
+</ul>
+<h3><a name="whatsnew200">What's new in version 2.0?</a></h3>
+1. CGIC 2.0 provides support for file upload fields. User-uploaded
+files are kept in temporary files, to avoid the use of
+excessive swap space (Solaris users may wish to change the
+<code>cgicTempDir</code> macro in cgic.c before compiling).
+The <code><a href="#cgiFormFileName">cgiFormFileName</a></code>, 
+<code><a href="#cgiFormFileContentType">cgiFormFileContentType</a></code>, 
+<code><a href="#cgiFormFileSize">cgiFormFileSize</a></code>, 
+<code><a href="#cgiFormFileOpen">cgiFormFileOpen</a></code>, 
+<code><a href="#cgiFormFileRead">cgiFormFileRead</a></code>, and
+<code><a href="#cgiFormFileClose">cgiFormFileClose</a></code> functions
+provide a complete interface to this new functionality. Remember,
+the <code>enctype</code> attribute of the <code>form</code> tag
+must be set to <code>multipart/form-data</code> when
+<code><input type="file"></code> tags are used.
+<p>
+2. CGIC 2.0 provides support for setting and examining cookies
+(persistent data storage on the browser side).
+The <code><a href="#cgiCookieString">cgiCookieString</a></code>,
+and <code><a href="#cgiCookieInteger">cgiCookieInteger</a></code>
+and <code><a href="#cgiCookies">cgiCookies</a></code>
+functions retrieve cookies. The 
+<code><a href="#cgiHeaderCookieSetString">cgiHeaderCookieSetString</a></code>
+and <code><a href="#cgiHeaderCookieSetInteger">cgiHeaderCookieSetInteger</a></code> functions set cookies.
+<p>
+3. CGIC 2.0 offers a convenient way to retrieve a list of all form fields.
+The new <code><a href="#cgiFormEntries">cgiFormEntries</a></code>
+function performs this operation.
+<p>
+4. CGIC 2.0 provides convenience functions to correctly escape
+text before outputting it as part of HTML, or as part of the 
+value of a tag attribute, such as the <code>HREF</code> or
+<code>VALUE</code> attribute. See 
+<code><a href="#cgiHtmlEscape">cgiHtmlEscape</a></code>,
+<code><a href="#cgiHtmlEscapeData">cgiHtmlEscapeData</a></code>,
+<code><a href="#cgiValueEscape">cgiValueEscape</a></code> and
+<code><a href="#cgiValueEscapeData">cgiValueEscapeData</a></code>.
+<p>
+5. Users have often asked the correct way to determine which submit
+button was clicked. This could always be accomplished in previous versions,
+but CGIC 2.0 also provides 
+<a href="#cgiFormSubmitClicked">cgiFormSubmitClicked</a>,
+a convenient alternate label for the 
+<a href="#cgiFormCheckboxSingle">cgiFormCheckboxSingle</a> function.
+<h3><a name="whatsnew107">What's new in version 1.07?</a></h3>
+A problem with the cgiFormString and related functions has been
+corrected. These functions were previously incorrectly returning cgiFormTruncated
+in cases where the returned string fit the buffer exactly.
+<h3><a name="whatsnew106">What's new in version 1.06?</a></h3>
+1. A potentially significant buffer overflow problem has been
+corrected. Jon Ribbens correctly pointed out to me (and to the
+Internet's bugtraq mailing list) that the cgiFormEntryString
+function, which is used directly or indirectly by almost all
+CGIC programs, can potentially write past the buffer passed
+to it by the programmer. This bug has been corrected.
+Upgrading to version 1.06 is <strong>strongly recommended.</strong>
+<P>
+2. The function <code>cgiSaferSystem()</code> has been
+removed entirely. This function escaped only a few metacharacters,
+while most shells have many, and there was no way to account for
+the many different operating system shells that might be in use
+on different operating systems. Since this led to a false sense
+of security, the function has been removed. It is our recommendation
+that user input should never be passed directly on the command line
+unless it has been carefully shown to contain only characters
+regarded as safe and appropriate by the programmer. Even then, it is
+better to design your utilities to accept their input from standard
+input rather than the command line.
+<h3><a name="whatsnew105">What's new in version 1.05?</a></h3>
+Non-exclusive commercial license fee reduced to $200.
+<h3><a name="whatsnew104">What's new in version 1.04?</a></h3>
+For consistency with other packages, the standard Makefile
+now produces a true library for cgic (libcgic.a). 
+<h3><a name="whatsnew103">What's new in version 1.03?</a></h3>
+Version 1.03 sends line feeds only (ascii 10) to end 
+Content-type:, Status:, and other HTTP protocol output lines,
+instead of CR/LF sequences. The standard specifies CR/LF.
+Unfortunately, too many servers reject CR/LF to make
+implementation of that standard practical. No server
+tested ever rejects LF alone in this context. 
+<h3><a name="whatsnew102">What's new in version 1.02?</a></h3>
+Version 1.02 corrects bugs in previous versions:
+<ul>
+<li>
+<a href="#cgiFormDoubleBounded">cgiFormDoubleBounded</a> specified
+its arguments in the wrong order, with surprising results.
+This bug has been corrected.
+<li>
+Many small changes have been made to increase compatibility.
+cgic now compiles with no warnings under the compilers
+available at boutell.com.
+</ul>
+<h3><a name="whatsnew101">What's new in version 1.01?</a></h3>
+Version 1.01 adds no major functionality but corrects 
+significant bugs and incompatibilities:
+<ul>
+<li>
+<a href="#cgiFormInteger">cgiFormInteger</a>,
+<a href="#cgiFormIntegerBounded">cgiFormIntegerBounded</a>,
+<a href="#cgiFormDouble">cgiFormDouble</a> and
+<a href="#cgiFormDoubleBounded">cgiFormDoubleBounded</a> now
+accept negative numbers properly. They also accept positive
+numbers with an explicit + sign.
+<li>Hex values containing the digit <code>9</code> are
+now properly decoded.
+<li><a href="#cgiFormString">cgiFormString</a> now
+represents each newline as a single line feed (ascii 10 decimal)
+as described in the documentation, not a carriage return
+(ascii 13 decimal) as in version 1.0. The latter approach
+pleased no one.
+<li><a href="#cgiFormString">cgiFormString</a> and
+<a href="#cgiFormStringNoNewlines">cgiFormStringNoNewlines</a>
+no longer erroneously return cgiFormEmpty in place of
+cgiFormSuccess.
+<li>The main() function of cgic now flushes standard output
+and sleeps for one second before exiting in order to inhibit
+problems with the completion of I/O on some platforms. This was
+not a cgic bug per se, but has been reported as a common problem
+with CGI when used with the CERN server. This change should
+improve compatibility.
+<li>The single selection example in the testform.html
+example now works properly. This was an error in the
+form itself, not cgic.
+<li><a href="#cgiRemoteUser">cgiRemoteUser</a> and
+<a href="#cgiRemoteIdent">cgiRemoteIdent</a> are now
+documented accurately. They were reversed earlier.
+</ul>
+<h3><a name="whatis">What is cgic?</a></h3>
+cgic is an ANSI C-language library for the creation of CGI-based
+World Wide Web applications. For basic information about
+the CGI standard, see the <a href="http://hoohoo.ncsa.uiuc.edu/cgi/">
+CGI documentation</a> at NCSA.
+<p>
+cgic performs the following tasks:
+<ul>
+<li>Parses form data, correcting for defective and/or inconsistent browsers
+<li>Transparently accepts both GET and POST form data
+<li>Accepts uploaded files as well as regular form fields
+<li>Provides functions to set and retrieve "cookies"
+(browser-side persistent information)
+<li>Handles line breaks in form fields in a consistent manner
+<li>Provides string, integer, floating-point, and single- and
+multiple-choice functions to retrieve form data
+<li>Provides bounds checking for numeric fields
+<li>Loads CGI environment variables into C strings which are always non-null
+<li>Provides a way to capture CGI situations for replay in a debugging
+environment, including file uploads and cookies
+</ul>
+<p>
+cgic is compatible with any CGI-compliant server environment, and
+compiles without modification in Posix/Unix/Linux and Windows
+environments.
+<h3><a name="obtain">Obtaining cgic</a></h3>
+cgic is distributed via the web in two forms: as a Windows-compatible
+.ZIP file, and as a gzipped tar file. Most users of Windows and
+related operating systems have access to 'unzip' or 'pkunzip'. All modern Unix 
+systems come with 'gunzip' and 'tar' as standard equipment, and gzip/gunzip
+is not difficult to find if yours does not. Versions
+of these programs for other operating systems are widely
+available if you do not already have them.
+<p>
+<strong>Important:</strong> to use cgic, you will need an ANSI-standard
+C compiler. Under Unix, just obtain and use gcc. Most Unix systems have
+standardiszed on gcc. Users of Windows operating systems should not have
+ANSI C-related problems as all of the popular compilers follow the ANSI 
+standard.
+<p>
+<strong>Note for Windows Programmers:</strong> you must use a modern
+32-bit compiler. Visual C++ 2.0 or higher, Borland C++ and the
+mingw32 gcc compiler are all appropriate, as is cygwin. Do 
+<strong>NOT</strong> use an ancient 16-bit DOS executable compiler, please.
+<blockquote>
+<h4>What Operating System Does Your WEB SERVER Run?</h4>
+Remember, the computer on your desk is usually NOT your web server.
+Compiling a Windows console executable will not give you a CGI program that
+can be installed on a Linux-based server. 
+</blockquote>
+Your web browser should inquire whether to save the file to disk
+when you select one of the links below. Under Unix and compatible
+operating systems, save it, then issue the following
+commands to unpack it:
+<pre>
+gunzip cgic205.tar.gz
+tar -xf cgic205.tar
+</pre>
+This should produce the subdirectory 'cgic205', which will contain
+the complete cgic distribution for version 2.05, including a copy of this 
+documentation in the file cgic.html.
+<p>
+Under Windows and compatible operating systems, save it,
+open a console ("DOS") window, and issue the following commands to unpack it:
+<pre>
+unzip /d cgic205.zip
+</pre>
+Or use the unzip utility of your choice.
+<p>
+This command also produces the subdirectory 'cgic205', which will contain
+the complete cgic distribution for version 2.0, including a copy of this 
+documentation in the file cgic.html.
+<p>
+cgic is available via the web from www.boutell.com:
+<ul>
+<li><a href="http://www.boutell.com/cgic/cgic205.tar.gz">Obtain cgic: gzipped tar file</a>
+<li><a href="http://www.boutell.com/cgic/cgic205.zip">Obtain cgic: .ZIP file</a>
+</ul>
+<h3><a name="build">Building cgic: a sample application</a></h3>
+The sample application 'cgictest.c' is provided as part of the
+cgic distribution. This CGI program displays an input form, 
+accepts a submission, and then displays what was submitted.
+In the process essentially all of cgic's features are tested.
+<p>
+On a Unix system, you can build cgictest simply by typing
+'make cgictest.cgi'. cgic.c and cgictest.c will be compiled and linked
+together to produce the cgictest application. Under non-Unix
+operating systems, you will need to create and compile an appropriate
+project containing the files cgic.c and cgictest.c. 
+<p>
+<strong>IMPORTANT:</strong> after compiling cgictest.cgi, you will
+need to place it in a location on your server system which is
+designated by your server administrator as an appropriate location
+for CGI scripts. Some servers are configured to recognize any
+file ending in .cgi as a CGI program when it is found in any
+subdirectory of the server's web space, but this is not always
+the case! The right locations for CGI
+programs vary greatly from one server to another. Resolving
+this issue is between you, your web server administrator,
+and your web server documentation. Before submitting a bug
+report for cgic, make certain that the CGI example programs
+which came with your server <em>do</em> work for you. Otherwise
+it is very likely that you have a server configuration problem.
+<p>
+Once you have moved cgictest.cgi (or cgictest.exe, under Windows)
+to an appropriate cgi directory,
+use the web browser of your choice to access the URL at which
+you have installed it 
+(for instance, <code>www.mysite.com/cgi-bin/cgictest.cgi</code>).
+Fill out the various fields in any manner you wish, then
+select the SUBMIT button.
+<p>
+If all goes well, cgictest.cgi will respond with a page which
+indicates the various settings you submitted. If not,
+please reread the section above regarding the correct location in
+which to install your CGI program on your web server.
+<h3><a name="nocompile">What to do if it won't compile</a></h3>
+<ul>
+<li><strong>Are you using Visual C++ or Borland C++? Did you forget to add
+cgic.c to your project?</strong>
+<li><strong>Make sure you are using an ANSI C or C++ compiler.</strong>
+(All of the Windows compilers are ANSI C compliant.)
+</ul>
+If none of the above proves effective, please see the
+section regarding <a href="#support">support</a>.
+<h3><a name="howto">How to write a cgic application</a></h3>
+<em>Note: </em> All cgic applications must be linked to the cgic.c module
+itself. How to do this depends on your operating system; under Unix,
+just use the provided Makefile as an example.
+<p>
+Since all CGI applications must perform certain initial
+tasks, such as parsing form data and examining
+environment variables, the cgic library provides its
+own main() function. When you write applications that
+use cgic, you will begin your own programs by writing
+a cgiMain() function, which cgic will invoke when
+the initial cgi work has been successfully completed. Your
+program must also be sure to #include the file cgic.h.
+<p>
+<strong>Important:</strong> if you write your own main()
+function, your program will not link properly. Your own
+code should begin with cgiMain(). The library
+provides main() for you. (Those who prefer different behavior
+can easily modify cgic.c.)
+<p>
+Consider the cgiMain function of cgictest.c:
+<p>
+<PRE>
+int cgiMain() {
+#ifdef DEBUG
+  LoadEnvironment();
+#endif /* DEBUG */
+  /* Load a previously saved CGI scenario if that button
+    has been pressed. */
+  if (cgiFormSubmitClicked("loadenvironment") == cgiFormSuccess) {
+    LoadEnvironment();
+  }
+  /* Set any new cookie requested. Must be done *before*
+    outputting the content type. */
+  CookieSet();
+  /* Send the content type, letting the browser know this is HTML */
+  cgiHeaderContentType("text/html");
+  /* Top of the page */
+  fprintf(cgiOut, "<HTML><HEAD>\n");
+  fprintf(cgiOut, "<TITLE>cgic test</TITLE></HEAD>\n");
+  fprintf(cgiOut, "<BODY><H1>cgic test</H1>\n");
+  /* If a submit button has already been clicked, act on the 
+    submission of the form. */
+  if ((cgiFormSubmitClicked("testcgic") == cgiFormSuccess) ||
+    cgiFormSubmitClicked("saveenvironment") == cgiFormSuccess)
+  {
+    HandleSubmit();
+    fprintf(cgiOut, "<hr>\n");
+  }
+  /* Now show the form */
+  ShowForm();
+  /* Finish up the page */
+  fprintf(cgiOut, "</BODY></HTML>\n");
+  return 0;
+}
+</PRE>
+Note the DEBUG #ifdef. If DEBUG is defined at compile time, either by
+inserting the line "#define DEBUG 1" into the program or by setting
+it in the Makefile or other development environment, then the
+LoadEnvironment function is invoked. This function calls 
+<a href="#cgiReadEnvironment">cgiReadEnvironment()</a> 
+to restore a captured CGI environment for debugging purposes. See
+also the discussion of the <a href="#debug">capture</a> program, which is
+provided for use in CGI debugging. Because this is a test program,
+the <a href="#cgiFormSubmitClicked">cgiFormSubmitClicked</a> function is
+also called to check for the use of a button that requests the reloading
+of a saved CGI environment. A completed CGI program typically would
+never allow the end user to make that decision.
+<h4>Setting Cookies</h4>
+Next, one of the cgiHeader functions should be called.
+This particular program demonstrates many features, including
+the setting of cookies. If the programmer wishes to set a cookie,
+the cookie-setting function must be called
+first, before other headers are output. This is done by the
+CookieSet() function of cgictest.c:
+<pre>
+void CookieSet()
+{
+  char cname[1024];
+  char cvalue[1024];
+  /* Must set cookies BEFORE calling 
+    cgiHeaderContentType */
+  cgiFormString("cname", cname, sizeof(cname));  
+  cgiFormString("cvalue", cvalue, sizeof(cvalue));  
+  if (strlen(cname)) {
+    /* Cookie lives for one day (or until 
+      browser chooses to get rid of it, which 
+      may be immediately), and applies only to 
+      this script on this site. */  
+    cgiHeaderCookieSetString(cname, cvalue,
+      86400, cgiScriptName, cgiServerName);
+  }
+}
+</pre>
+Since this is a test program, the <a href="#cgiFormString">cgiFormString</a> 
+function is used to fetch the name and value from the form previously filled
+in by the user. Normally, cookie names and values are chosen to meet the
+needs of the programmer and provide a means of identifying the same
+user again later.
+<p>
+The <a href="#cgiHeaderCookieSetString">cgiHeaderCookieSetString</a>
+function sets the cookie by requesting that the web browser store it.
+<strong>There is never any guarantee that this will happen!</strong>
+Many browsers reject cookies completely; others do not necessarily keep
+them as long as requested or return them with their values intact.
+Always code defensively when using cookies.
+<p>
+The cname and cvalue parameters are of course the namd and value for
+the cookie. The third argument is the time, in seconds, that the
+cookie should "live" on the browser side before it expires; in this
+case it has been set to 86,400 seconds, which is exactly one day. 
+<strong>The browser may or may not respect this setting, as with everything
+else about cookies.</strong>
+<p>
+The fourth argument identifies the "path" within the web site for which
+the cookie is considered valid. A cookie that should be sent back
+for every access to the site should be set with a path of <code>/</code>.
+In this case the cookie is relevant only to the CGI program itself, so
+<code><a href="#cgiScriptName">cgiScriptName</a></code> (the URL of the CGI program, not including the
+domain name) is sent. Similarly, a cookie can be considered relevant
+to a single web site or to an entire domain, such as 
+<code>www.boutell.com</code> or the entire <code>.boutell.com</code>
+domain. In this case, the current site on which the program is running
+is the only relevant site, so <code><a href="#cgiServerName">cgiServerName</a></code> is used
+as the domain.
+<h4>Outputting the Content Type Header</h4>
+Next, <a href="#cgiHeaderContentType">cgiHeaderContentType()</a> is 
+called to indicate the MIME type of the document being output, in this case 
+"text/html" (a normal HTML document). A few other common MIME types are
+"image/gif", "image/jpeg" and "audio/wav". 
+<p>
+Note that <a href="#cgiHeaderStatus">cgiHeaderStatus()</a> or 
+<a href="#cgiHeaderLocation">cgiHeaderLocation()</a> could have
+been invoked instead to output an error code or redirect the
+request to a different URL. Only one of the cgiHeader functions
+should be called in a single execution of the program.
+<p>
+<strong>Important:</strong> one of the cgiHeader functions,
+usually <a href="#cgiHeaderContentType">cgiHeaderContentType()</a>, 
+<em>must</em> be invoked before outputting any other
+response to the user. Otherwise, the result will not be a valid
+document and the browser's behavior will be unpredictable.
+You may, of course, output your own ContentType and other
+header information to <a href="#cgiOut">cgiOut</a> if you prefer. The cgiHeader functions
+are provided as a convenience.
+<h4>Handling Form Submissions</h4>
+Like many CGI programs, cgictest makes decisions about the way it
+should behave based on whether various submit buttons have been clicked.
+When either the testcgic or saveenvironment button is present, cgictest
+invokes the HandleSubmit function, which invokes additional functions to
+handle various parts of the form:
+<pre>
+void HandleSubmit()
+{
+  Name();
+  Address();
+  Hungry();
+  Temperature();
+  Frogs();
+  Color();
+  Flavors();
+  NonExButtons();
+  RadioButtons();
+  File();
+  Entries();
+  Cookies();
+  /* The saveenvironment button, in addition to submitting 
+    the form, also saves the resulting CGI scenario to 
+    disk for later replay with the 'load saved environment' 
+    button. */
+  if (cgiFormSubmitClicked("saveenvironment") == cgiFormSuccess) {
+    SaveEnvironment();
+  }
+}
+</pre>
+<h4>Handling Text Input</h4>
+The Name() function of cgictest is shown below, in its simplest
+possible form:
+<PRE>
+void Name() {
+        char name[81];
+        <a href="#cgiFormStringNoNewlines">cgiFormStringNoNewlines</a>("name", name, 81);
+        fprintf(cgiOut, "Name: ");
+        cgicHtmlEscape(name);
+        fprintf(cgiOut, "<BR>\n");
+}
+</PRE>
+The purpose of this function is to retrieve and display the name that was
+input by the user. Since the programmer has decided that names should
+be permitted to have up to 80 characters, a buffer of 81 characters
+has been declared (allowing for the final null character). 
+The <a href="#cgiFormStringNoNewlines">cgiFormStringNoNewlines()</a>
+function is then invoked to retrieve the name and ensure that
+carriage returns are not present in the name (despite the
+incorrect behavior of some web browsers). The first argument
+is the name of the input field in the form, the second argument
+is the buffer to which the data should be copied, and the third
+argument is the size of the buffer. cgic will never write beyond
+the size of the buffer, and will always provide a null-terminated
+string in response; if the buffer is too small, the string will
+be shortened. If this is not acceptable, the
+<a href="#cgiFormStringSpaceNeeded">cgiFormStringSpaceNeeded()</a>
+function can be used to check the amount of space needed; the
+return value of cgiFormStringNoNewlines() can also be checked
+to determine whether truncation occurred. See
+the full description of <a href="#cgiFormStringNoNewlines">
+cgiFormStringNoNewlines()</a>.
+<h4>Handling Output</h4>
+Note that Name() writes its HTML output to <a href="#cgiOut">cgiOut</a>, not
+to stdout.
+<p>
+The actual name submitted by the user may or may not contain
+characters that have special meaning in HTML, specifically the
+the <code><</code>, <code>></code>, and <code>&</code> characters.
+The <a href="#cgiHtmlEscape">cgiHtmlEscape</a> function is used to output
+the user-entered name with any occurrences of these characters
+correctly escaped as <code>&lt;</code>, <code>&gt;</code>, 
+and <code>&amp;</code>.
+<p>
+<strong>Important:</strong> <a href="#cgiOut">cgiOut</a> is normally equivalent
+to stdout, and there is no performance penalty for using it.
+It is recommended that you write output to <a href="#cgiOut">cgiOut</a> to ensure compatibility
+with modified versions of the cgic library for special
+environments that do not provide stdin and stdout for
+each cgi connection.
+<p>
+Note that, for text input areas in which carriage returns <em>are</em>
+desired, the function <a href="#cgiFormString">cgiFormString</a>
+should be used instead. cgiFormString ensures that line breaks
+are always represented by a single carriage return (ascii decimal 13),
+making life easier for the programmer. See the source code to
+the Address() function of cgictest.c for an example.
+<h4>Handling Single Checkboxes</h4>
+Consider the Hungry() function, which determines whether
+the user has selected the "hungry" checkbox:
+<PRE>
+void Hungry() {
+        if (<a href="#cgiFormCheckboxSingle">cgiFormCheckboxSingle</a>("hungry") == <a href="#cgiFormSuccess">cgiFormSuccess</a>) {
+                fprintf(cgiOut, "I'm Hungry!<BR>\n");
+        } else {
+                fprintf(cgiOut, "I'm Not Hungry!<BR>\n");
+        }
+}
+</PRE>
+This function takes advantage of the
+<a href="#cgiFormCheckboxSingle">cgiFormCheckboxSingle()</a> function, which
+determines whether a single checkbox has been selected. 
+cgiFormCheckboxSingle() accepts the name attribute of the checkbox
+as its sole argument and returns <a href="#cgiFormSuccess">
+cgiFormSuccess</a> if the checkbox is selected, or 
+<a href="#cgiFormNotFound">cgiFormNotFound</a> if it is not.
+If multiple checkboxes with the same name are in use,
+consider the <a href="#cgiFormCheckboxMultiple">
+cgiFormCheckboxMultiple()</a> and 
+<a href="#cgiFormStringMultiple">cgiFormStringMultiple()</a>
+functions.
+<h4>Handling Numeric Input</h4>
+Now consider the Temperature() function, which retrieves
+a temperature in degrees (a floating-point value) and ensures
+that it lies within particular bounds:
+<PRE>
+void Temperature() {
+        double temperature;
+        <a href="#cgiFormDoubleBounded">cgiFormDoubleBounded</a>("temperature", &temperature, 80.0, 120.0, 98.6);
+        fprintf(<a href="#cgiOut">cgiOut</a>, "My temperature is %f.<BR>\n", temperature);
+}
+</PRE>
+The temperature is retrieved by the function 
+<a href="#cgiFormDoubleBounded">cgiFormDoubleBounded()</a>. The first
+argument is the name of the temperature input field in the form;
+the second argument points to the address of the variable that will 
+contain the result. The next two arguments are the lower and upper
+bounds, respectively. The final argument is the default value to
+be returned if the user did not submit a value.
+<p>
+This function always retrieves a reasonable value within the
+specified bounds; values above or below bounds are constrained
+to fit the bounds. However, the return value of
+cgiFormDoubleBounded can be checked to make sure the
+actual user entry was in bounds, not blank, and so forth;
+see the description of <a href="#cgiFormDoubleBounded">
+cgiFormDoubleBounded()</a> for more details. If bounds checking
+is not desired, consider using <a href="#cgiFormDouble">
+cgiFormDouble()</a> instead.
+<p>
+Note that, for integer input, the functions
+<a href="#cgiFormInteger">cgiFormInteger</a> and
+<a href="#cgiFormIntegerBounded">cgiFormIntegerBounded</a>
+are available. The behavior of these functions is similar to
+that of their floating-point counterparts above.
+<h4>Handling Single-Choice Input</h4>
+The <SELECT> tag of HTML is used to provide the user with
+several choices. Radio buttons and checkboxes can also be used
+when the number of choices is relatively small. Consider
+the Color() function of cgictest.c:
+<PRE>
+char *colors[] = {
+        "Red",
+        "Green",
+        "Blue"
+};
+
+void Color() {
+        int colorChoice;
+        <a href="#cgiFormSelectSingle">cgiFormSelectSingle</a>("colors", colors, 3, &colorChoice, 0);
+        fprintf(<a href="#cgiOut">cgiOut</a>, "I am: %s<BR>\n", colors[colorChoice]);
+}
+</PRE>
+This function determines which of several colors the user chose
+from a <SELECT> list in the form. An array of colors is
+declared; the <a href="#cgiFormSelectSingle">cgiFormSelectSingle()</a>
+function is then invoked to determine which, if any, of those choices
+was selected. The first argument indicates the name of the input
+field in the form. The second argument points to the list of
+acceptable colors. The third argument indicates the number of
+entries in the color array. The fourth argument points to the
+variable which will accept the chosen color, and the last argument
+indicates the index of the default value to be set if no
+selection was submitted by the browser. 
+<p>
+<a href="#cgiFormSelectSingle">cgiFormSelectSingle()</a> will
+always indicate a reasonable selection value. However, if
+the programmer wishes to know for certain that a value was
+actually submitted, that the value submitted was a legal
+response, and so on, the return value of cgiFormSelectSingle()
+can be consulted. See the full description of
+<a href="#cgiFormSelectSingle">cgiFormSelectSingle()</a> for
+more information.
+<p>
+Note that radio button groups and <SELECT> lists can both
+be handled by this function. If you are processing radio
+button groups, you may prefer to invoke 
+<a href="#cgiFormRadio">cgiFormRadio()</a>, which functions
+identically. 
+<p>
+<em>"What if I won't know the acceptable choices at runtime?"</em>
+<p>
+If the acceptable choices aren't known <em>until</em> runtime,
+one can simply load the choices from disk. But if the acceptable
+choices aren't fixed at all (consider a list of country names;
+new names may be added to the form at any time and it is
+inconvenient to also update program code or a separate list
+of countries), simply invoke 
+<a href="#cgiFormStringNoNewlines">cgiFormStringNoNewlines()</a>
+instead to retrieve the string directly. Keep in mind that, if
+you do so, validating the response to make sure it is
+safe and legitimate becomes a problem for your own
+program to solve. The advantage of cgiFormSelectSingle() is that invalid 
+responses are never returned.
+<p>
+To handle multiple-selection <SELECT> lists and
+groups of checkboxes with the same name, see the
+discussion of the NonExButtons() function of cgictest.c, immediately below.
+<h4>Handling Multiple-Choice Input</h4>
+Consider the first half of the NonExButtons() function of cgictest.c:
+<PRE>
+char *votes[] = {
+  "A",
+  "B",
+  "C",
+  "D"
+};
+
+void NonExButtons() {
+  int voteChoices[4];
+  int i;
+  int result;  
+  int invalid;
+
+  char **responses;
+
+  /* Method #1: check for valid votes. This is a good idea,
+    since votes for nonexistent candidates should probably
+    be discounted... */
+  fprintf(<a href="#cgiOut">cgiOut</a>, "Votes (method 1):<BR>\n");
+  result = <a href="#cgiFormCheckboxMultiple">cgiFormCheckboxMultiple</a>("vote", votes, 4, 
+    voteChoices, &invalid);
+  if (result == <a href="#cgiFormNotFound">cgiFormNotFound</a>) {
+    fprintf(<a href="#cgiOut">cgiOut</a>, "I hate them all!<p>\n");
+  } else {  
+    fprintf(<a href="#cgiOut">cgiOut</a>, "My preferred candidates are:\n");
+    fprintf(<a href="#cgiOut">cgiOut</a>, "<ul>\n");
+    for (i=0; (i < 4); i++) {
+      if (voteChoices[i]) {
+        fprintf(<a href="#cgiOut">cgiOut</a>, "<li>%s\n", votes[i]);
+      }
+    }
+    fprintf(<a href="#cgiOut">cgiOut</a>, "</ul>\n");
+  }
+</PRE>
+This function takes advantage of
+<a href="#cgiFormCheckboxMultiple">cgiFormCheckboxMultiple()</a>,
+which is used to identify one or more selected checkboxes with 
+the same name. This function performs identically to
+<a href="#cgiFormSelectMultiple">cgiFormSelectMultiple()</a>.
+That is, <SELECT> tags with the MULTIPLE attribute are handled
+just like a group of several checkboxes with the same name.
+<p>
+The first argument to <a href="#cgiFormCheckboxMultiple">
+cgiFormCheckboxMultiple()</a> is the name given to all
+checkbox input fields in the group. The second argument
+points to an array of legitimate values; these should
+correspond to the VALUE attributes of the checkboxes
+(or OPTION tags in a <SELECT> list). The third argument
+indicates the number of entries in the array of
+legitimate values. The fourth argument points to
+an array of integers with the same number of entries
+as the array of legitimate values; each entry
+will be set true if that checkbox or option was selected,
+false otherwise.
+<p>
+The last argument points to an integer which will be set to the 
+number of invalid responses (responses not in the array of
+valid responses) that were submitted. If this value is not
+of interest, the last argument may be a null pointer (0).
+<p>
+Note that the return value of cgiFormCheckboxMultiple is
+inspected to determine whether any choices at all were
+set. See the full description of
+<a href="#cgiFormCheckboxMultiple">cgiFormCheckboxMultiple</a>
+for other possible return values. 
+<p>
+<em>"What if I won't know the acceptable choices at runtime?"</em>
+<p>
+If the acceptable choices aren't known <em>until</em> runtime,
+one can simply load the choices from disk. But if the acceptable
+choices aren't fixed at all (consider a list of ice cream flavors;
+new names may be added to the form at any time and it is
+inconvenient to also update program code or a separate list
+of countries), a more dynamic approach is needed. Consider
+the second half of the NonExButtons() function of cgictest.c:
+<PRE>
+  /* Method #2: get all the names voted for and trust them.
+    This is good if the form will change more often
+    than the code and invented responses are not a danger
+    or can be checked in some other way. */
+  fprintf(<a href="#cgiOut">cgiOut</a>, "Votes (method 2):<BR>\n");
+  result = <a href="#cgiFormStringMultiple">cgiFormStringMultiple</a>("vote", &responses);
+  if (result == <a href="#cgiFormNotFound">cgiFormNotFound</a>) {  
+    fprintf(<a href="#cgiOut">cgiOut</a>, "I hate them all!<p>\n");
+  } else {
+    int i = 0;
+    fprintf(<a href="#cgiOut">cgiOut</a>, "My preferred candidates are:\n");
+    fprintf(<a href="#cgiOut">cgiOut</a>, "<ul>\n");
+    while (responses[i]) {
+      fprintf(<a href="#cgiOut">cgiOut</a>, "<li>%s\n", responses[i]);
+      i++;
+    }
+    fprintf(<a href="#cgiOut">cgiOut</a>, "</ul>\n");
+  }
+  /* We must be sure to free the string array or a memory
+    leak will occur. Simply calling free() would free
+    the array but not the individual strings. The
+    function cgiStringArrayFree() does the job completely. */  
+  <A HREF="#cgiStringArrayFree">cgiStringArrayFree</a>(responses);
+}
+</PRE>
+This code excerpt demonstrates an alternate means of retrieving
+a list of choices. The function
+<a href="#cgiFormStringMultiple">cgiFormStringMultiple()</a> is used
+to retrieve an array consisting of all the strings submitted
+for with a particular input field name. This works both for
+<SELECT> tags with the MULTIPLE attribute and for 
+groups of checkboxes with the same name. 
+<P>
+The first argument to <a href="#cgiFormStringMultiple">
+cgiFormStringMultiple()</a> is the name of the input field or
+group of input fields in question. The second argument should
+be the address of a pointer to a pointer to a string, which
+isn't as bad as it sounds. Consider the following simple call
+of the function:
+<PRE>
+/* An array of strings; each C string is an array of characters */
+char **responses; 
+
+<a href="#cgiFormStringMultiple">cgiFormStringMultiple</a>("vote", &responses);
+</PRE>
+<em>"How do I know how many responses there are?"</em>
+<p>
+After the call, the last entry in the string array will be
+a null pointer. Thus the simple loop:
+<PRE>
+int i = 0;
+while (responses[i]) {
+  /* Do something with the string responses[i] */
+  i++;
+}
+</PRE>
+can be used to walk through the array until the last
+entry is encountered.
+<p>
+<strong>Important:</strong> the 
+<a href="#cgiFormStringMultiple">cgiFormStringMultiple</a> function
+returns a pointer to <strong>allocated memory</strong>. Your code
+should not modify the strings in the responses array or the responses
+array itself; if modification is needed, the strings should be
+copied. When your code is done examining the responses array,
+you <strong>MUST</strong> call <a href="#cgiStringArrayFree">
+cgiStringArrayFree()</a> with the array as an argument to free the memory 
+associated with the array. Otherwise, the memory will not be available 
+again until the program exists. <strong>Don't</strong> just call the 
+free() function; if you do, the individual strings will not be freed.
+<h4>Accessing Uploaded Files</h4>
+CGIC provides functions to access files that have been uploaded
+as part of a form submission. <strong>IMPORTANT: you MUST</strong> set
+the <code>enctype</code> attribute of your <code>form</code> tag
+to <code>multipart/form-data</code> for this feature to work! For an
+example, see the <a href="#ShowForm">ShowForm</a> function of 
+cgictest.c, examined below.
+<p>
+The <code>File</code> function of cgictest.c takes care of 
+receiving uploaded files:
+<pre>
+void File()
+{
+  cgiFilePtr file;
+  char name[1024];
+  char contentType[1024];
+  char buffer[1024];
+  int size;
+  int got;
+  if (cgiFormFileName("file", name, sizeof(name)) != 
+    cgiFormSuccess) 
+  {
+    printf("<p>No file was uploaded.<p>\n");
+    return;
+  } 
+        fprintf(cgiOut, "The filename submitted was: ");
+        cgiHtmlEscape(name);
+        fprintf(cgiOut, "<p>\n");
+        cgiFormFileSize("file", &size);
+        fprintf(cgiOut, "The file size was: %d bytes<p>\n", size);
+        cgiFormFileContentType("file", contentType, sizeof(contentType));
+        fprintf(cgiOut, "The alleged content type of the file was: ");
+        cgiHtmlEscape(contentType);
+        fprintf(cgiOut, "<p>\n");
+  fprintf(cgiOut, "Of course, this is only the claim the browser "
+    "made when uploading the file. Much like the filename, "
+    "it cannot be trusted.<p>\n");
+  fprintf(cgiOut, "The file's contents are shown here:<p>\n");
+  if (cgiFormFileOpen("file", &file) != cgiFormSuccess) {
+    fprintf(cgiOut, "Could not open the file.<p>\n");
+    return;
+  }
+  fprintf(cgiOut, "<pre>\n");
+  while (cgiFormFileRead(file, buffer, sizeof(buffer), &got) ==
+    cgiFormSuccess)
+  {
+    cgiHtmlEscapeData(buffer, got);
+  }
+  fprintf(cgiOut, "</pre>\n");
+  cgiFormFileClose(file);
+}
+</pre>
+First, the File function checks to determine the filename that was
+submitted by the user. <strong>VERY IMPORTANT: this filename may or
+may not bear any relation to the real name of the file on the user's
+computer, may be deliberately manipulated with malicious intent,</strong>
+and should not be used for <strong>any</strong> purpose unless you have
+determined that its content is safe for your intended use and will not,
+at the very least, overwrite another file of importance to you, especially if
+you intend to use it as a file name on the server side. The cgic library
+itself does not use this file name for temporary storage.
+<p>
+If the <a href="#cgiFormFileName">cgiFormFileName</a> function does
+not succeed, no file was uploaded.
+<p>
+Next, the <a href="#cgiFormFileSize">cgiFormFileSize</a> function is called
+to determine the size of the uploaded file, in bytes.
+<p>
+The File function then proceeds to query the content type of the uploaded
+file.  Files uploaded by the user have their own content type information, 
+which may be useful in determining whether the file is an image, HTML document,
+word processing document, or other type of file. However,
+<strong>as with the filename and any other claim made by the browser,
+this information should not be blindly trusted.</strong> The browser
+may upload a file with the name <code>picture.jpg</code> and the
+content type <code>image/jpeg</code>, but this does not guarantee that the
+actual file will contain a valid JPEG image suitable for display.
+<p>
+The content type submitted by the browser can be queried using the
+<a href="#cgiFormFileContentType">cgiFormFileContentType</a> function.
+<p>
+Of course, CGIC also provides access to the actual uploded file. 
+First, the programmer calls <a href="#cgiFormFileOpen">cgiFormFileOpen</a>,
+passing the address of a <code>cgiFilePtr</code> object. If this function
+succeeds, the <code>cgiFilePtr</code> object becomes valid, and can be
+used in subsequent calls to <a href="#cgiFormFileRead">cgiFormFileRead</a>.
+Notice that the number of bytes read may be less than the number requested,
+in particular on the last successful call before cgiFormFileRead begins
+to return <code>cgiFormEOF</code>. When cgiFormFileRead no longer returns 
+cgiFormSuccess, 
+the programmer calls <a href="#cgiFormClose">cgiFormFileClose</a> to
+release the <code>cgiFilePtr</code> object.
+<p>
+The uploaded file data may contain anything, including binary data,
+null characters, and so on. The example program uses the 
+<a href="#cgiHtmlEscapeData">cgiHtmlEscapeData</a> function to output the
+data with any special characters that have meaning in HTML escaped.
+Most programs will save the uploaded information to a server-side file or
+database.
+<h4>Fetching All Form Entries</h4>
+From time to time, the programmer may not know the names of all
+form fields in advance. In such situations it is convenient to
+use the <a href="#cgiFormEntries">cgiFormEntries</a> function.
+The Entries function of cgictest.c demonstrates the use of
+cgiFormEntries:
+<pre>
+void Entries()
+{
+        char **array, **arrayStep;
+        fprintf(cgiOut, "List of All Submitted Form Field Names:<p>\n");
+        if (cgiFormEntries(&array) != cgiFormSuccess) {
+                return;
+        }
+        arrayStep = array;
+        fprintf(cgiOut, "<ul>\n");
+        while (*arrayStep) {
+                fprintf(cgiOut, "<li>");
+                cgiHtmlEscape(*arrayStep);
+                fprintf(cgiOut, "\n");
+                arrayStep++;
+        }
+        fprintf(cgiOut, "</ul>\n");
+        cgiStringArrayFree(array);
+}
+</pre>
+The cgiFormEntries function retrieves an array of form field names.
+This array consists of pointers to strings, with a final null pointer
+to mark the end of the list. The above code illustrates one way of
+looping through the returned strings. Note the final call to
+<a href="#cgiStringArrayFree">cgiStringArrayFree</a>, which is
+essential in order to return the memory used to store the strings
+and the string array.
+<h4>Retrieving Cookies</h4>
+The Cookies function of cgictest.c displays a list of all cookies
+submitted by the browser with the current form submission, along
+with their values:
+<pre>
+void Cookies()
+{
+  char **array, **arrayStep;
+  char cname[1024], cvalue[1024];
+  fprintf(cgiOut, "Cookies Submitted On This Call, With Values "
+    "(Many Browsers NEVER Submit Cookies):<p>\n");
+  if (cgiCookies(&array) != cgiFormSuccess) {
+    return;
+  }
+  arrayStep = array;
+  fprintf(cgiOut, "<table border=1>\n");
+  fprintf(cgiOut, "<tr><th>Cookie<th>Value</tr>\n");
+  while (*arrayStep) {
+    char value[1024];
+    fprintf(cgiOut, "<tr>");
+    fprintf(cgiOut, "<td>");
+    cgiHtmlEscape(*arrayStep);
+    fprintf(cgiOut, "<td>");
+    cgiCookieString(*arrayStep, value, sizeof(value));
+    cgiHtmlEscape(value);
+    fprintf(cgiOut, "\n");
+    arrayStep++;
+  }
+  fprintf(cgiOut, "</table>\n");
+  cgiFormString("cname", cname, sizeof(cname));  
+  cgiFormString("cvalue", cvalue, sizeof(cvalue));  
+  if (strlen(cname)) {
+    fprintf(cgiOut, "New Cookie Set On This Call:<p>\n");
+    fprintf(cgiOut, "Name: ");  
+    cgiHtmlEscape(cname);
+    fprintf(cgiOut, "Value: ");  
+    cgiHtmlEscape(cvalue);
+    fprintf(cgiOut, "<p>\n");
+    fprintf(cgiOut, "If your browser accepts cookies "
+      "(many do not), this new cookie should appear "
+      "in the above list the next time the form is "
+      "submitted.<p>\n"); 
+  }
+  cgiStringArrayFree(array);
+}
+</pre>
+<strong>VERY IMPORTANT: YOUR BROWSER MIGHT NOT SUBMIT COOKIES,
+EVER, REGARDLESS OF WHAT VALUES YOU ENTER INTO THE TEST FORM.</strong>
+Many, many browsers are configured not to accept or send cookies;
+others are configured to send them as little as possible to meet the
+bare minimum requirements for entry into popular sites. Users will often
+refuse your cookies; make sure your code still works in that situation!
+<p>
+The above code uses the <a href="#cgiCookies">cgiCookies</a> function
+to retrieve a list of all currently set cookies as a null-terminated
+array of strings. The <a href="#cgiCookieString">cgiCookieString</a>
+function is then used to fetch the value associated with each cookie;
+this function works much like <a href="#cgiFormString">cgiFormString</a>,
+discussed earlier. Note that a cookie set as a part of the current
+form submission process does not appear on this list immediately, as
+it has not yet been sent back by the browser. It should appear on
+future submissions, provided that the browser chooses to accept
+and resend the cookie at all.
+<h4>Displaying a Form That Submits to the Current Program</h4>
+CGI programmers often need to display HTML pages as part of the output
+of CGI programs; these HTML pages often contain forms which should submit
+fields back to the same program they came from. Provided that your
+web server is well-configured, this can be done conveniently using
+the cgiScriptName environment variable, as shown below. Here is the
+source code of the ShowForm function of cgictest.c:
+<pre>
+void ShowForm()
+{
+  fprintf(cgiOut, "<!-- 2.0: multipart/form-data is required 
+    "for file uploads. -->");
+  fprintf(cgiOut, "<form method=\"POST\" "
+    "enctype=\"multipart/form-data\" ");
+  fprintf(cgiOut, "  action=\"");
+  cgiValueEscape(cgiScriptName);
+  fprintf(cgiOut, "\">\n");
+  fprintf(cgiOut, "<p>\n");
+  fprintf(cgiOut, "Text Field containing Plaintext\n");
+  fprintf(cgiOut, "<p>\n");
+  fprintf(cgiOut, "<input type=\"text\" name=\"name\">Your Name\n");
+  fprintf(cgiOut, "<p>\n");
+  fprintf(cgiOut, "Multiple-Line Text Field\n");
+  fprintf(cgiOut, "<p>\n");
+  fprintf(cgiOut, "<textarea NAME=\"address\" ROWS=4 COLS=40>\n");
+  fprintf(cgiOut, "Default contents go here. \n");
+  fprintf(cgiOut, "</textarea>\n");
+  fprintf(cgiOut, "<p>\n");
+  fprintf(cgiOut, "Checkbox\n");
+  fprintf(cgiOut, "<p>\n");
+  fprintf(cgiOut, "<input type=\"checkbox\" name=\"hungry\" checked>Hungry\n");
+  fprintf(cgiOut, "<p>\n");
+  fprintf(cgiOut, "Text Field containing a Numeric Value\n");
+  fprintf(cgiOut, "<p>\n");
+  fprintf(cgiOut, "<input type=\"text\" name=\"temperature\" value=\"98.6\">\n");
+  fprintf(cgiOut, "Blood Temperature (80.0-120.0)\n");
+  fprintf(cgiOut, "<p>\n");
+  fprintf(cgiOut, "Text Field containing an Integer Value\n");
+  fprintf(cgiOut, "<p>\n");
+  fprintf(cgiOut, "<input type=\"text\" name=\"frogs\" value=\"1\">\n");
+  fprintf(cgiOut, "Frogs Eaten\n");
+  fprintf(cgiOut, "<p>\n");
+  fprintf(cgiOut, "Single-SELECT\n");
+  fprintf(cgiOut, "<br>\n");
+  fprintf(cgiOut, "<select name=\"colors\">\n");
+  fprintf(cgiOut, "<option value=\"Red\">Red\n");
+  fprintf(cgiOut, "<option value=\"Green\">Green\n");
+  fprintf(cgiOut, "<option value=\"Blue\">Blue\n");
+  fprintf(cgiOut, "</select>\n");
+  fprintf(cgiOut, "<br>\n");
+  fprintf(cgiOut, "Multiple-SELECT\n");
+  fprintf(cgiOut, "<br>\n");
+  fprintf(cgiOut, "<select name=\"flavors\" multiple>\n");
+  fprintf(cgiOut, "<option value=\"pistachio\">Pistachio\n");
+  fprintf(cgiOut, "<option value=\"walnut\">Walnut\n");
+  fprintf(cgiOut, "<option value=\"creme\">Creme\n");
+  fprintf(cgiOut, "</select>\n");
+  fprintf(cgiOut, "<p>Exclusive Radio Button Group: Age of "
+    "Truck in Years\n");
+  fprintf(cgiOut, "<input type=\"radio\" name=\"age\" "
+    "value=\"1\">1\n");
+  fprintf(cgiOut, "<input type=\"radio\" name=\"age\" "
+    "value=\"2\">2\n");
+  fprintf(cgiOut, "<input type=\"radio\" name=\"age\" "
+    "value=\"3\" checked>3\n");
+  fprintf(cgiOut, "<input type=\"radio\" name=\"age\" "
+    "value=\"4\">4\n");
+  fprintf(cgiOut, "<p>Nonexclusive Checkbox Group: "
+    "Voting for Zero through Four Candidates\n");
+  fprintf(cgiOut, "<input type=\"checkbox\" name=\"vote\" "
+    "value=\"A\">A\n");
+  fprintf(cgiOut, "<input type=\"checkbox\" name=\"vote\" "
+    "value=\"B\">B\n");
+  fprintf(cgiOut, "<input type=\"checkbox\" name=\"vote\" "
+    "value=\"C\">C\n");
+  fprintf(cgiOut, "<input type=\"checkbox\" name=\"vote\" "
+    "value=\"D\">D\n");
+  fprintf(cgiOut, "<p>File Upload:\n");
+  fprintf(cgiOut, "<input type=\"file\" name=\"file\" "
+    "value=\"\"> (Select A Local File)\n");
+  fprintf(cgiOut, "<p>\n");
+  fprintf(cgiOut, "<p>Set a Cookie<p>\n");
+  fprintf(cgiOut, "<input name=\"cname\" "
+    "value=\"\"> Cookie Name\n");
+  fprintf(cgiOut, "<input name=\"cvalue\" "
+    "value=\"\"> Cookie Value<p>\n");
+  fprintf(cgiOut, "<input type=\"submit\" "
+    "name=\"testcgic\" value=\"Submit Request\">\n");
+  fprintf(cgiOut, "<input type=\"reset\" "
+    "value=\"Reset Request\">\n");
+  fprintf(cgiOut, "<p>Save the CGI Environment<p>\n");
+  fprintf(cgiOut, "Pressing this button will submit the form, then "
+    "save the CGI environment so that it can be replayed later "
+    "by calling cgiReadEnvironment (in a debugger, for "
+    "instance).<p>\n");
+  fprintf(cgiOut, "<input type=\"submit\" name=\"saveenvironment\" "
+    "value=\"Save Environment\">\n");
+  fprintf(cgiOut, "</form>\n");
+}
+</pre>
+Note the use of <code>enctype="multipart/form-data"</code> in the
+<code>FORM</code> tag. This is absolutely required if the form
+will contain file upload fields, as in the above example. Most
+browsers will not even attempt file uploads without the
+presence of this attribute.
+<h4>Examining CGI environment variables</h4>
+The CGI standard specifies a number of environment variables
+which are set by the server. However, servers are somewhat
+unpredictable as to whether these variables will be null or
+point to empty strings when an environment variable is not set.
+Also, in order to allow the programmer to restore saved
+CGI environments, the cgic library needs have a way of insulating
+the programmer from the actual environment variables.
+<p>
+Instead of calling getenv() to determine the value of a
+variable such as HTTP_USER_AGENT (the browser software being used),
+always use the
+<a href="#variables">cgic copies of the environment variables</a>,
+which are always valid C strings (they are never null, although
+they may point to an empty string). For instance, the cgic
+variable containing the name of the browser software is
+<a href="#cgiUserAgent">cgiUserAgent</a>. The referring URL appears
+in the variable <a href="#cgiReferrer">cgiReferrer</a>.
+<h3><a name="images">How can I generate images from my cgic application?</a></h3>
+cgic can be used in conjunction with the
+<a href="http://www.boutell.com/gd/">gd graphics library</a>, which
+can produce GIF images on the fly.
+<p>
+The following short sample program hints at the possibilities:
+<pre>
+#include "cgic.h"
+#include "gd.h"
+
+char *colors[] = {
+  "red", "green", "blue"
+};
+
+#define colorsTotal 3
+
+int cgiMain() {
+  int colorChosen;
+  gdImagePtr im;
+  int r, g, b;
+  /* Use gd to create an image */
+  im = gdImageCreate(64, 64);
+  r = gdImageColorAllocate(im, 255, 0, 0);  
+  g = gdImageColorAllocate(im, 0, 255, 0);  
+  b = gdImageColorAllocate(im, 0, 0, 255);  
+  /* Now use cgic to find out what color the user requested */
+  <a href="#cgiFormSelectSingle">cgiFormSelectSingle</a>("color", 3, &colorChosen, 0);  
+  /* Now fill with the desired color */
+  switch(colorChosen) {
+    case 0:
+    gdImageFill(im, 32, 32, r);
+    break;
+    case 1:
+    gdImageFill(im, 32, 32, g);
+    break;
+    case 2:
+    gdImageFill(im, 32, 32, b);
+    break;
+  }  
+  /* Now output the image. Note the content type! */
+  cgiHeaderContentType("image/gif");
+  /* Send the image to cgiOut */
+  gdImageGif(im, cgiOut);
+  /* Free the gd image */
+  gdImageDestroy(im);
+  return 0;
+}
+</pre>
+Note that this program would need to be linked with both cgic.o
+and libgd.a. Often programs of this type respond to one
+cgiPathInfo value or set of form fields by returning an HTML page 
+with an inline image reference that, in turn, generates a GIF image.
+<h3><a name="debug">Debugging CGI applications: using capture</a></h3>
+Debugging CGI applications can be a painful task. Since CGI applications
+run in a special environment created by the web server, it is difficult
+to execute them in a debugger. However, the cgic library provides a way 
+of capturing "live" CGI environments to a file, and also provides a way
+to reload saved environments. 
+<p>
+The provided program 'capture.c' can be used to capture CGI
+environments. Just change the first line of the cgiMain() function
+of capture.c to save the CGI environment to a filename appropriate
+on your system and type 'make capture'. Then place capture in your
+cgi directory and set the form action or other link you want to test
+to point to it. When the form submission or other link takes place,
+capture will write the CGI environment active at that time to
+the filename you specified in the source. The
+<a href="#cgiReadEnvironment">cgiReadEnvironment()</a> function can then 
+be invoked on the same filename at the beginning of the cgiMain() function 
+of the application you want to test in order to restore the captured 
+environment.  You can then execute your program in the debugger of your choice,
+and it should perform exactly as it would have performed had
+it been launched by the actual web server, including file uploads,
+cookies and all other phenomena within the purview of cgic.
+<p>
+<strong>Important:</strong> Make sure you specify the full path, as the
+current working directory of a CGI script may not be what you
+think it is!
+<p>
+<strong>Even More Important:</strong> If you call getenv() yourself
+in your code, instead of using the provided <a href="#variables">
+cgic copies of the CGI environment variables</a>, you will
+<em>not</em> get the values you expect when running with
+a saved CGI environment. Always use the cgic variables instead
+of calling getenv().
+<h3><a name="functions">cgic function reference</a></h3>
+<dl>
+<br><dt><strong><a name="cgiFormString">cgiFormResultType cgiFormString(
+  char *name, char *result, int max)</a>
+</strong><br><dd>cgiFormString attempts to retrieve the string sent for the
+  specified input field. The text will be copied into
+  the buffer specified by result, up to but not
+  exceeding max-1 bytes; a terminating null is then
+  added to complete the string. Regardless of the newline
+  format submitted by the browser, cgiFormString always
+  encodes each newline as a single line feed (ascii decimal 10); as
+  a result the final string may be slightly shorter than indicated
+  by a call to <a href="#cgiFormStringSpaceNeeded">
+  cgiFormStringSpaceNeeded</a> but will never be longer.
+  cgiFormString returns <a href="#cgiFormSuccess">cgiFormSuccess</a> if the string was 
+  successfully retrieved, 
+  <a href="#cgiFormTruncated">cgiFormTruncated</a> if the string was
+  retrieved but was truncated to fit the buffer,
+  cgiFormEmpty if the string was 
+  retrieved but was empty, and <a href="#cgiFormNotFound">cgiFormNotFound</a> if no 
+  such input field was submitted. In the last case, 
+  an empty string is copied to result. 
+<br><br><dt><strong><a name="cgiFormStringNoNewlines">
+cgiFormResultType cgiFormStringNoNewlines(
+  char *name, char *result, int max)</a>
+</strong><br><dd>
+cgiFormStringNoNewlines() is exactly equivalent to <a href="#cgiFormString">
+  cgiFormString()</a>, except
+  that any carriage returns or line feeds that occur in the input
+  will be stripped out. The use of this function is recommended
+  for single-line text input fields, as some browsers will submit
+  carriage returns and line feeds when they should not. 
+<br><br><dt><strong><a name="cgiFormStringSpaceNeeded">
+cgiFormResultType cgiFormStringSpaceNeeded(
+  char *name, int *length)</a>
+</strong><br><dd>
+cgiFormStringSpaceNeeded() is used to determine the length of the input text 
+  buffer needed to receive the contents of the specified input field. 
+  This is useful if the programmer wishes to allocate sufficient memory 
+  for input of arbitrary length. The actual length of the string 
+  retrieved by a subsequent call to cgiFormString() may be slightly shorter
+  but will never be longer than *result. On success, cgiFormStringSpaceNeeded() 
+  sets the value pointed to by length to the number of bytes of data, 
+  including the terminating null, and returns <a href="#cgiFormSuccess">cgiFormSuccess</a>. If no 
+  value was submitted for the specified field, cgiFormStringSpaceNeeded sets 
+  the value pointed to by length to 1 and returns <a href="#cgiFormNotFound">cgiFormNotFound</a>. 1 is
+  set to ensure space for an empty string (a single null
+  character) if cgiFormString is called despite the return value.
+
+<br><br><dt><strong><a name="cgiFormStringMultiple">cgiFormResultType cgiFormStringMultiple(
+  char *name, char ***ptrToStringArray)</a>
+</strong><br><dd>cgiFormStringMultiple is useful in the unusual case in which several
+  input elements in the form have the same name and, for whatever
+  reason, the programmer does not wish to use the checkbox, radio 
+  button and selection menu functions provided below. This is
+  occasionally needed if the programmer cannot know 
+  in advance what values might appear in a multiple-selection list
+  or group of checkboxes on a form. The value pointed to
+  by result will be set to a pointer to an array of strings; the last
+  entry in the array will be a null pointer.  This array is allocated 
+  by the CGI library. Important: when done working with the array,
+  you must call cgiStringArrayFree() with the array pointer as the 
+  argument.  cgiFormStringMultiple() returns <a href="#cgiFormSuccess">cgiFormSuccess</a> if at least
+  one occurrence of the name is found, <a href="#cgiFormNotFound">cgiFormNotFound</a>
+  if no occurrences are found, or cgiFormMemory if not enough
+  memory is available to allocate the array to be returned.
+  In all cases except the last, ptrToStringArray is set to point to a 
+  valid array of strings, with the last element in the array being a 
+  null pointer; in the out-of-memory case ptrToStringArray is set to 
+  a null pointer.
+
+<br><br><dt><strong><a name="cgiFormEntries">cgiFormResultType cgiFormEntries(
+  char ***ptrToStringArray)</a>
+</strong><br><dd>cgiFormEntries is useful when the programmer cannot know the names
+  of all relevant form fields in advance. The value pointed to
+  by result will be set to a pointer to an array of strings; the last
+  entry in the array will be a null pointer.  This array is allocated 
+  by the CGI library. Important: when done working with the array,
+  you must call cgiStringArrayFree() with the array pointer as the 
+  argument. cgiFormEntries() returns <a href="#cgiFormSuccess">cgiFormSuccess</a> except in the event of an out of memory error.
+  On success, ptrToStringArray is set to point to a 
+  valid array of strings, with the last element in the array being a 
+  null pointer; in the out-of-memory case ptrToStringArray is set to 
+  a null pointer, and 
+  <a href="#cgiFormOutOfMemory">cgiFormOutOfMemory</a> is returned.
+
+<br><br><dt><strong><a name="cgiStringArrayFree">void cgiStringArrayFree(char **stringArray)
+</a>
+</strong><br><dd>
+cgiStringArrayFree() is used to free the memory associated with
+  a string array created by 
+  <a href="#cgiFormStringMultiple">cgiFormStringMultiple()</a>,
+  <a href="#cgiFormEntries">cgiFormEntries()</a>, or
+  <a href="#cgiFormCookies">cgiFormCookies()</a>.
+<br><br><dt><strong><a name="cgiFormInteger">cgiFormResultType cgiFormInteger(
+  char *name, int *result, int defaultV)</a>
+</strong><br><dd>cgiFormInteger() attempts to retrieve the integer sent for the
+  specified input field. The value pointed to by result
+  will be set to the value submitted. cgiFormInteger() returns 
+  cgiFormSuccess if the value was successfully retrieved,
+  cgiFormEmpty if the value submitted is an empty string,
+  cgiFormBadType if the value submitted is not an integer,
+  and <a href="#cgiFormNotFound">cgiFormNotFound</a> if no such input field was submitted. 
+  In the last three cases, the value pointed to by result
+  is set to the specified default.
+<br><br><dt><strong><a name="cgiFormIntegerBounded">
+cgiFormResultType cgiFormIntegerBounded(
+  char *name, int *result, int min, int max, int defaultV)</a>
+</strong><br><dd>cgiFormIntegerBounded() attempts to retrieve the integer sent for the
+  specified input field, and constrains the result to be within
+  the specified bounds. The value pointed to by result
+  will be set to the value submitted. cgiFormIntegerBounded() returns 
+  cgiFormSuccess if the value was successfully retrieved,
+  <a href="#cgiFormConstrained">cgiFormConstrained</a> if the value was out of bounds and result
+  was adjusted accordingly, <a href="#cgiFormEmpty">cgiFormEmpty</a> if the value submitted is 
+  an empty string, <a href="#cgiFormBadType">cgiFormBadType</a> if the value submitted is not an 
+  integer, and <a href="#cgiFormNotFound">cgiFormNotFound</a> if no such input field was submitted. 
+  In the last three cases, the value pointed to by result
+  is set to the specified default.
+
+<br><br><dt><strong><a name="cgiFormDouble">cgiFormResultType cgiFormDouble(
+  char *name, double *result, double defaultV)</a>
+</strong><br><dd>cgiFormDouble attempts to retrieve the floating-point value sent for 
+  the specified input field. The value pointed to by result
+  will be set to the value submitted. cgiFormDouble returns 
+  cgiFormSuccess if the value was successfully retrieved,
+  cgiFormEmpty if the value submitted is an empty string,
+  cgiFormBadType if the value submitted is not a number,
+  and <a href="#cgiFormNotFound">cgiFormNotFound</a> if no such input field was submitted. 
+  In the last three cases, the value pointed to by result
+  is set to the specified default. 
+<br><br><dt><strong><a name="cgiFormDoubleBounded">
+cgiFormResultType cgiFormDoubleBounded(
+  char *name, double *result, double min, double max, 
+  double defaultV)</a>
+</strong><br><dd>
+cgiFormDoubleBounded() attempts to retrieve the floating-point
+  value  sent for the specified input field, and constrains the 
+  result to be within the specified bounds. The value pointed to by 
+  result will be set to the value submitted. cgiFormDoubleBounded() returns 
+  cgiFormSuccess if the value was successfully retrieved,
+  <a href="#cgiFormConstrained">cgiFormConstrained</a> if the value was out of bounds and result
+  was adjusted accordingly, <a href="#cgiFormEmpty">cgiFormEmpty</a> if the value submitted is 
+  an empty string, <a href="#cgiFormBadType">cgiFormBadType</a> if the value submitted is not a 
+  number, and <a href="#cgiFormNotFound">cgiFormNotFound</a> if no such input field was submitted. 
+  In the last three cases, the value pointed to by result
+  is set to the specified default. 
+
+<br><br><dt><strong><a name="cgiFormSelectSingle">
+cgiFormResultType cgiFormSelectSingle(
+  char *name, char **choicesText, int choicesTotal, 
+  int *result, int defaultV)</a>
+</strong><br><dd>
+cgiFormSelectSingle() retrieves the selection number associated with a
+  <SELECT> element that does not allow multiple selections. name
+  should identify the NAME attribute of the <SELECT> element. choicesText 
+  should point to an array of strings identifying each choice; 
+  choicesTotal should indicate the total number of choices. The value 
+  pointed to by result will be set to the position of the actual choice
+  selected within the choicesText array, if any, or to the value of 
+  default, if no selection was submitted or an invalid selection was 
+  made.  cgiFormSelectSingle() returns <a href="#cgiFormSuccess">cgiFormSuccess</a> if the value was
+  successfully retrieved, <a href="#cgiFormNotFound">cgiFormNotFound</a> if no selection
+  was submitted, and <a href="#cgiFormNoSuchChoice">cgiFormNoSuchChoice</a> if the selection
+  does not match any of the possibilities in the choicesText array. 
+<br><dt><strong>
+<a name="cgiFormSelectMultiple">
+cgiFormResultType cgiFormSelectMultiple(
+  char *name, char **choicesText, int choicesTotal, 
+  int *result, int *invalid)</a>
+</strong><br><dd>cgiFormSelectMultiple() retrieves the selection numbers associated with a
+  <SELECT> element that does allow multiple selections. name should
+  identify the NAME attribute of the <SELECT> element. choicesText 
+  should point to an array of strings identifying each choice; 
+  choicesTotal should indicate the total number of choices. result
+  should point to an array of integers with as many elements as there
+  are strings in the choicesText array. For each choice in the
+  choicesText array that is selected, the corresponding integer in
+  the result array will be set to one; other entries in the result
+  array will be set to zero. cgiFormSelectMultiple() returns <a href="#cgiFormSuccess">cgiFormSuccess</a> 
+  if at least one valid selection was successfully retrieved or
+  cgiFormNotFound if no valid selections were submitted.
+  The integer pointed to by invalid is set to the number of
+  invalid selections that were submitted, which should be zero
+  unless the form and the choicesText array do not agree.
+
+<br><br><dt><strong>
+<a name="cgiFormSubmitClicked">
+cgiFormResultType cgiFormSubmitClicked(
+  char *name)</a>
+</strong><br><dd>
+It is often desirable to know whether a particular submit button was clicked,
+  when multiple submit buttons with different name attributes exist.
+  cgiFormSubmitClicked is an alternative name for the 
+  <a href="#cgiFormCheckboxSingle">cgiFormCheckboxSingle</a> function,
+  which is suitable for testing whether a particular submit button
+  was used.
+<br><br><dt><strong>
+<a name="cgiFormCheckboxSingle">
+cgiFormResultType cgiFormCheckboxSingle(
+  char *name)</a>
+</strong><br><dd>
+cgiFormCheckboxSingle determines whether the checkbox with the specified name
+  is checked. cgiFormCheckboxSingle returns <a href="#cgiFormSuccess">cgiFormSuccess</a> if the
+  button is checked, <a href="#cgiFormNotFound">cgiFormNotFound</a> if the checkbox is
+  not checked. cgiFormCheckboxSingle is intended for single
+  checkboxes with a unique name; see below for functions to
+  deal with multiple checkboxes with the same name, and
+  with radio buttons.
+
+<br><br><dt><strong><a name="cgiFormCheckboxMultiple">
+cgiFormResultType cgiFormCheckboxMultiple(
+  char *name, char **valuesText, int valuesTotal, 
+  int *result, int *invalid)</a>
+</strong><br><dd>cgiFormCheckboxMultiple() determines which checkboxes among a group
+  of checkboxes with the same name are checked. This is distinct
+  from radio buttons (see <a href="#cgiFormRadio">cgiFormRadio</a>). 
+  valuesText 
+  should point to an array of strings identifying the VALUE
+  attribute of each checkbox; valuesTotal should indicate the total 
+  number of checkboxes. result should point to an array of integers with 
+  as many elements as there are strings in the valuesText array. For 
+  each choice in the valuesText array that is selected, the corresponding
+  integer in the result array will be set to one; other entries in the 
+  result array will be set to zero. cgiFormCheckboxMultiple returns 
+  cgiFormSuccess if at least one valid checkbox was checked or
+  cgiFormNotFound if no valid checkboxes were checked.
+  The integer pointed to by invalid is set to the number of
+  invalid selections that were submitted, which should be zero
+  unless the form and the valuesText array do not agree.
+<br><br><dt><strong><a name="cgiFormRadio">
+cgiFormResultType cgiFormRadio(
+  char *name, char **valuesText, int valuesTotal, 
+  int *result, int defaultV)</a>
+</strong><br><dd>cgiFormRadio() determines which, if any, of a group of radio boxes with
+  the same name was selected. valuesText should point to an array of 
+  strings identifying the VALUE attribute of each radio box; 
+  valuesTotal should indicate the total number of radio boxes. The value 
+  pointed to by result will be set to the position of the actual choice 
+  selected within the valuesText array, if any, or to the value of 
+  default, if no radio box was checked or an invalid selection was 
+  made. cgiFormRadio() returns <a href="#cgiFormSuccess">cgiFormSuccess</a> if a checked radio box was 
+  found in the group, <a href="#cgiFormNotFound">cgiFormNotFound</a> if no box was checked, and 
+  <a href="#cgiFormNoSuchChoice">cgiFormNoSuchChoice</a> if the radio box submitted does not match any of 
+  the possibilities in the valuesText array.
+
+<br><dt><strong><a name="cgiFormFileName">cgiFormResultType cgiFormFileName(
+  char *name, char *fileName, int max)</a>
+</strong><br><dd>cgiFormFileName attempts to retrieve the file name uploaded by the
+  user for the specified form input field of type <code>file</code>. 
+  <strong>NEVER, EVER TRUST THIS FILENAME TO BE REASONABLE AND
+  SAFE FOR DIRECT USE ON THE SERVER SIDE.</strong>
+  The text will be copied into
+  the buffer specified by fileName, up to but not
+  exceeding max-1 bytes; a terminating null is then
+  added to complete the string. cgiFormFileName returns 
+  <a href="#cgiFormSuccess">cgiFormSuccess</a> if the string was 
+  successfully retrieved and was not empty,
+  <a href="#cgiFormNoFileName">cgiFormNoFileName</a> if the string was 
+  successfully retrieved but empty indicating that no file was uploaded,
+  <a href="#cgiFormTruncated">cgiFormTruncated</a> if the string was
+  retrieved but was truncated to fit the buffer,
+  and <a href="#cgiFormNotFound">cgiFormNotFound</a> if no 
+  such input field was submitted. In the last case, 
+  an empty string is copied to result. 
+<br><dt><strong><a name="cgiFormFileSize">cgiFormResultType cgiFormFileSize(
+  char *name, int *sizeP)</a>
+</strong><br><dd>cgiFormFileSize attempts to retrieve the size, in bytes, of a
+  file uploaded by the browser in response to the
+  input field of type <code>file</code> specified by the
+  <code>name</code> parameter. On success, the size is stored
+  to *sizeP, and this function returns 
+  <a href="#cgiFormSuccess">cgiFormSuccess</a>. If the form
+  field does not exist, this function returns 
+  <a href="#cgiFormNotFound">cgiFormNotFound</a>.
+  If the form field exists but no file was uploaded, this function
+  returns <a href="#cgiFormNotAFile">cgiFormNotAFile</a>.
+<br><dt><strong><a name="cgiFormFileContentType">cgiFormResultType cgiFormFileContentType(
+  char *name, char *contentType, int max)</a>
+</strong><br><dd>cgiFormString attempts to retrieve the content name claimed by the
+  user for the specified form input field of type <code>file</code>. 
+  <strong>THERE IS NO GUARANTEE THAT THE CONTENT TYPE WILL BE
+  ACCURATE.</strong>
+  The content type string will be copied into
+  the buffer specified by contentType, up to but not
+  exceeding max-1 bytes; a terminating null is then
+  added to complete the string. cgiFormFileContentType returns 
+  <a href="#cgiFormSuccess">cgiFormSuccess</a> if the string was 
+  successfully retrieved and was not empty,
+  <a href="#cgiFormNoContentType">cgiFormNoContentType</a> if the string was 
+  successfully retrieved but empty indicating that no file was uploaded
+  or the browser did not know the content type,
+  <a href="#cgiFormTruncated">cgiFormTruncated</a> if the string was
+  retrieved but was truncated to fit the buffer,
+  and <a href="#cgiFormNotFound">cgiFormNotFound</a> if no 
+  such input field was submitted. In the last case, 
+  an empty string is copied to result. 
+
+<br><dt><strong><a name="cgiFormFileOpen">cgiFormResultType cgiFormFileOpen(
+  char *name, cgiFilePtr *cfpp)</a>
+</strong><br><dd>cgiFormFileOpen attempts to open the actual uploaded file data for
+  the specified form field of type <code>file</code>. Upon success,
+  this function returns retrieve the content name claimed by the
+  user for the specified form input field of type <code>file</code>. 
+  On success, this function sets *cfpp to a valid cgiFilePtr
+  object for use with <a href="#cgiFormFileRead</a>cgiFormFileRead</a>
+  and returns <a href="#cgiFormSuccess">cgiFormSuccess</a>.
+  On failure, this function sets *cfpp to a null pointer, and
+  returns <a href="#cgiFormNotFound">cgiFormNotFound</a>,
+  <a href="#cgiFormNotAFile">cgiFormNotAFile</a>,
+  <a href="#cgiFormMemory">cgiFormMemory</a> or
+  <a href="#cgiFormIO">cgiFormIO</a> as appropriate.
+<p>
+  See also <a href="#cgiFormFileRead">cgiFormFileRead</a> 
+and <a href="#cgiFormFileClose">cgiFormFileClose</a>.
+<br><dt><strong><a name="cgiFormFileRead">cgiFormResultType cgiFormFileRead(
+  cgiFilePtr cfp, char *buffer, int bufferSize, int *gotP)</a>
+</strong><br><dd>cgiFormFileRead attempts to read up to <code>bufferSize</code>
+  bytes from a cgiFilePtr object previously opened with
+  <a href="#cgiFormFileOpen">cgiFormFileOpen</a>. If any data
+  is successfully read, it is copied to <code>buffer</code>, 
+  and the number of bytes successfully read is stored 
+  to <code>*gotP</code>. This function returns 
+  <a href="#cgiFormSuccess">cgiFormSuccess</a> if any data
+  is successfully read. At end of file, this function
+  returns <a href="#cgiFormEOF">cgiFormEOF</a>. In the event
+  of an I/O error, this function returns 
+  <a href="#cgiFormIO">cgiFormIO</a>. If cfp is a null pointer,
+  this function returns <a href="#cgiFormOpenFailed">cgiFormOpenFailed</a>.
+  <p>
+  See also <a href="#cgiFormFileOpen">cgiFormFileOpen</a> 
+and <a href="#cgiFormFileClose">cgiFormFileClose</a>.
+<br><dt><strong><a name="cgiFormFileClose">cgiFormResultType cgiFormFileClose(
+  cgiFilePtr cfp)</a>
+</strong><br><dd>cgiFormFileClose closes a cgiFilePtr object previously opened
+  with <a href="#cgiFormFileOpen">cgiFormFileOpen</a>, freeing
+  memory and other system resources. This
+  function returns <a href="#cgiFormSuccess">cgiFormSuccess</a>
+  unless cfp is null, in which case 
+  <a href="#cgiFormOpenFailed">cgiFormOpenFailed</a> is returned.
+<p>
+  See also <a href="#cgiFormFileOpen">cgiFormFileOpen</a> 
+and <a href="#cgiFormFileRead">cgiFormFileRead</a>.
+<br><br><dt><strong><a name="cgiHeaderLocation">
+void cgiHeaderLocation(char *redirectUrl)</a>
+</strong><br><dd>
+cgiHeaderLocation() should be called if the programmer wishes to
+redirect the user to a different URL. No futher output
+is needed in this case.
+<p>
+If you wish to set cookies,
+<strong>you must make your calls to 
+<a href="#cgiHeaderCookieSetString">cgiHeaderCookieSetString</a>
+and 
+<a href="#cgiHeaderCookieSetInteger">cgiHeaderCookieSetInteger</a>
+</strong> BEFORE invoking cgiHeaderLocation. 
+<br><br><dt><strong><a name="cgiHeaderStatus">
+void cgiHeaderStatus(int status, char *statusMessage)</a>
+</strong><br><dd>
+cgiHeaderStatus() should be called if the programmer wishes to
+output an HTTP error status code instead of a document. The status
+code is the first argument; the second argument is the status
+message to be displayed to the user.
+<p>
+If you wish to set cookies,
+<strong>you must make your calls to 
+<a href="#cgiHeaderCookieSetString">cgiHeaderCookieSetString</a>
+and 
+<a href="#cgiHeaderCookieSetInteger">cgiHeaderCookieSetInteger</a>
+</strong> BEFORE invoking cgiHeaderStatus.
+<br><br><dt><strong><a name="cgiHeaderContentType">
+void cgiHeaderContentType(char *mimeType)</a>
+</strong><br><dd>
+cgiHeaderContentType() should be called if the programmer wishes to
+output a new document in response to the user's request. This is
+the normal case. The single argument is the MIME document type
+of the response; typical values are "text/html" for HTML documents, 
+"text/plain" for plain ASCII without HTML tags, "image/gif" for
+a GIF image and "audio/basic" for .au-format audio.
+<p>
+If you wish to set cookies,
+<strong>you must make your calls to 
+<a href="#cgiHeaderCookieSetString">cgiHeaderCookieSetString</a>
+and 
+<a href="#cgiHeaderCookieSetInteger">cgiHeaderCookieSetInteger</a>
+</strong> BEFORE invoking cgiHeaderContentType.
+<br><br><dt><strong><a name="cgiHeaderCookieSetString">
+void cgiHeaderCookieSetString(char *name, char *value,
+  int secondsToLive, char *path, char *domain)</a>
+</strong><br><dd>
+cgiHeaderCookieSetString() should be called when the programmer wishes
+to store a piece of information in the user's browser, so that the
+stored information is again presented to the server on subsequent
+accesses to the relevant site. The first argument is the name of the
+cookie to be stored; for best results in all browsers, use a short
+name without spaces or unusual punctuation. The second argument is
+the value of the cookie to be stored. Again, for best results, use
+a short string; it is recommended that cookies be used to store a
+unique identifier which is then used to look up more detailed
+information in a database on the server side. Attempts to store
+elaborate information on the browser side are much more likely to fail.
+The third argument is the number of seconds that the cookie should
+be kept by the browser; 86400 is a single full day, 365*86400 is
+roughly one year. The fourth argument is the partial URL of the
+web site within which the cookie is relevant. If the cookie should
+be sent to the server for every access to the entire site, 
+set this argument to <code>/</code>. The final argument is the
+web site name or entire domain for which this cookie should be
+submitted; if you choose to have the cookie sent back for an
+entire domain, this argument must begin with a dot, such as
+<code>.boutell.com</code>. The cgic variables <a name="#cgiScriptName</a>
+and <a name="#cgiServerName">cgiServerName</a> are convenient
+values for the fourth and fifth arguments.
+See also <a href="#cgiHeaderCookieSetInteger">cgiHeaderCookieSetInteger</a>,
+<a href="#cgiCookieString">cgiCookieString</a>, 
+<a href="#cgiCookieString">cgiCookieInteger</a> and
+<a href="#cgiCookies">cgiCookies</a>.
+<br><br><dt><strong><a name="cgiHeaderCookieSetInteger">
+void cgiHeaderCookieSetInteger(char *name, int value,
+  int secondsToLive, char *path, char *domain)</a>
+</strong><br><dd>
+cgiHeaderCookieSetInteger() is identical to
+<a href="#cgiHeaderCookieSetString">cgiHeaderCookieSetString</a>,
+except that the value to be set is an integer rather than a string.
+See <a href="#cgiHeaderCookieSetString">cgiHeaderCookieSetString</a>
+for complete information.
+<br>
+<br><dt><strong><a name="cgiCookieString">cgiFormResultType cgiCookieString(
+  char *name, char *result, int max)</a>
+</strong><br><dd>cgiFormString attempts to retrieve the string sent for the
+  specified cookie (browser-side persistent storage). The 
+  text will be copied into
+  the buffer specified by result, up to but not
+  exceeding max-1 bytes; a terminating null is then
+  added to complete the string.
+  cgiCookieString returns <a href="#cgiFormSuccess">cgiFormSuccess</a> if the string was 
+  successfully retrieved, 
+  <a href="#cgiFormTruncated">cgiFormTruncated</a> if the string was
+  retrieved but was truncated to fit the buffer,
+  cgiFormEmpty if the string was 
+  retrieved but was empty, and <a href="#cgiFormNotFound">cgiFormNotFound</a> if no 
+  such cookie was submitted. In the last case, 
+  an empty string is copied to result. 
+<br><br><dt><strong><a name="cgiCookieInteger">cgiFormResultType cgiCookieInteger(
+  char *name, int *result, int defaultV)</a>
+  See also <a href="#cgiCookieString">cgiCookieInteger</a>,
+  <a href="#cgiCookies">cgiCookies</a>,
+  <a href="#cgiHeaderCookieSetString>cgiHeaderCookieSetString</a>, and
+  <a href="#cgiHeaderCookieSetInteger>cgiHeaderCookieSetInteger</a>.
+</strong><br><dd>cgiCookieInteger() attempts to retrieve the integer sent for the
+  specified cookie (browser-side persistent storage). The value 
+  pointed to by result will be set to the value submitted. 
+  cgiCookieInteger() returns 
+  cgiFormSuccess if the value was successfully retrieved,
+  cgiFormEmpty if the value submitted is an empty string,
+  cgiFormBadType if the value submitted is not an integer,
+  and <a href="#cgiFormNotFound">cgiFormNotFound</a> if no such 
+  input field was submitted. In the last three cases, the value 
+  pointed to by result is set to the specified default.
+  See also <a href="#cgiCookieString">cgiCookieString</a>,
+  <a href="#cgiCookies">cgiCookies</a>,
+  <a href="#cgiHeaderCookieSetString>cgiHeaderCookieSetString</a>, and
+  <a href="#cgiHeaderCookieSetInteger>cgiHeaderCookieSetInteger</a>.
+<br><br><dt><strong><a name="cgiCookies">cgiFormResultType cgiCookies(
+  char *name, char ***ptrToStringArray)</a>
+</strong><br><dd>cgiCookies is useful when the programmer cannot know the names
+  of all relevant cookies (browser-side persistent strings) in advance.
+  The value pointed to by result will be set to a pointer to an array 
+  of strings; the last
+  entry in the array will be a null pointer.  This array is allocated 
+  by the CGI library. Important: when done working with the array,
+  you must call cgiStringArrayFree() with the array pointer as the 
+  argument. cgiCookies() returns <a href="#cgiFormSuccess">cgiFormSuccess</a> except in the event of an out of memory error.
+  On success, ptrToStringArray is set to point to a 
+  valid array of strings, with the last element in the array being a 
+  null pointer; in the out-of-memory case ptrToStringArray is set to 
+  a null pointer, and 
+  <a href="#cgiFormOutOfMemory">cgiFormOutOfMemory</a> is returned.
+<br><br><dt><strong><a name="cgiHtmlEscape">
+cgiFormResultType cgiHtmlEscape(char *s)</a>
+</strong><br><dd>
+cgiHtmlEscape() outputs the specified null-terminated string to 
+<a href="#cgiOut">cgiOut</a>,
+escaping any <, &, and > characters encountered correctly so that
+they do not interfere with HTML markup. Returns 
+<a href="#cgiFormSuccess">cgiFormSuccess</a>, or
+<a href="#cgiFormIO">cgiFormIO</a> in the event of an I/O error.
+<p> 
+<br><br><dt><strong><a name="cgiHtmlEscapeData">
+cgiFormResultType cgiHtmlEscapeData(char *data, int len)</a>
+</strong><br><dd>
+cgiHtmlEscapeData() is identical to <a href="#cgiHtmlEscape">cgiHtmlEscape</a>,
+except that the data is not null-terminated. This version of the function
+outputs <code>len</code> bytes. See <a href="#cgiHtmlEscape">cgiHtmlEscape</a>
+for more information.
+<br><br><dt><strong><a name="cgiValueEscape">
+cgiFormResultType cgiValueEscape(char *s)</a>
+</strong><br><dd>
+cgiValueEscape() outputs the specified null-terminated string to 
+<a href="#cgiOut">cgiOut</a>,
+escaping any " characters encountered correctly so that
+they do not interfere with the quotation marks of HTML attribute
+values. This is useful when outputting a string as part of the
+value attribute of an input tag, or the href attribute of a link
+or form tag. This function returns
+<a href="#cgiFormSuccess">cgiFormSuccess</a>, or
+<a href="#cgiFormIO">cgiFormIO</a> in the event of an I/O error.
+<p> 
+<br><br><dt><strong><a name="cgiValueEscapeData">
+cgiFormResultType cgiValueEscapeData(char *data, int len)</a>
+</strong><br><dd>
+cgiValueEscapeData() is identical to <a href="#cgiValueEscape">cgiValueEscape</a>,
+except that the data is not null-terminated. This version of the function
+outputs <code>len</code> bytes. See <a href="#cgiValueEscape">cgiValueEscape</a>
+for more information.
+<br><br><dt><strong><a name="cgiWriteEnvironment">
+cgiEnvironmentResultType cgiWriteEnvironment(char *filename)</a>
+</strong><br><dd>
+cgiWriteEnvironment() can
+  be used to write the entire CGI environment, including
+  form data, to the specified output file; <a href="#cgiReadEnvironment">
+  cgiReadEnvironment()</a> 
+  can then be used to restore that environment from the specified
+  input file for debugging. Of course, these will only work as expected
+  if you use the <a href="#variables">cgic copies of the CGI environment 
+  variables</a> and <a href="#cgiIn">cgiIn</a> and 
+  <a href="#cgiOut">cgiOut</a> rather than stdin and
+  stdout (also see above). These functions are useful in order 
+  to capture real CGI situations while the web server is running, then
+  recreate them in a debugging environment. Both functions
+  return <a href="#cgiEnvironmentSuccess">cgiEnvironmentSuccess</a> on 
+  success, <a href="#cgiEnvironmentIO">cgiEnvironmentIO</a> on an I/O 
+  error, and <a href="#cgiEnvironmentMemory">cgiEnvironmentMemory</a>
+  on an out-of-memory error.
+<br><br><dt><strong><a name="cgiReadEnvironment">
+cgiEnvironmentResultType cgiReadEnvironment(char *filename)</a>
+</strong><br><dd>
+cgiReadEnvironment() restores a CGI environment saved to the specified file by
+  <a href="#cgiWriteEnvironment">cgiWriteEnvironment().</a> 
+  Of course, these will only work as expected
+  if you use the <a href="#variables">cgic copies of the CGI environment 
+  variables</a> and <a href="#cgiIn">cgiIn</a> and 
+  <a href="#cgiOut">cgiOut</a> rather than stdin and
+  stdout (also see above). These functions are useful in order 
+  to capture real CGI situations while the web server is running, then
+  recreate them in a debugging environment. Both functions
+  return <a href="#cgiEnvironmentSuccess">cgiEnvironmentSuccess</a> on success, 
+  <a href="#cgiEnvironmentIO">cgiEnvironmentIO</a> on an I/O error, and 
+  <a href="#cgiEnvironmentMemory">cgiEnvironmentMemory</a>
+  on an out-of-memory error.
+<br><br><dt><strong><a name="cgiMain">int cgiMain()</a>
+</strong><br><dd><strong>The programmer must write this function</strong>, which performs 
+  the unique task of the program and is invoked by the true main() 
+  function, found in the cgic library itself. The return value from 
+  cgiMain will be the return value of the program. It is expected that 
+  the user will make numerous calls to the cgiForm functions
+  from within this function. See <a href="#howto">how to write
+  a cgic application</a> for details.
+</dl>
+<h3><a name="variables">cgic variable reference</a></h3>
+This section provides a reference guide to the various global
+variables provided by cgic for the programmer to utilize.
+These variables should always be used in preference to
+stdin, stdout, and calls to getenv() in order to ensure
+compatibility with the <a href="#debug">cgic CGI debugging features</a>.
+<p>
+Most of these variables are equivalent to various CGI environment
+variables. The most important difference is that the cgic
+environment string variables are never null pointers. They will always 
+point to valid C strings of zero or more characters.
+<dl>
+<br><dt><strong><a name="cgiServerSoftware">char *cgiServerSoftware</a>
+</strong><br><dd>Points to the name of the server software,
+or to an empty string if unknown.
+<br><dt><strong><a name="cgiServerName">char *cgiServerName</a>
+</strong><br><dd>Points to the name of the server,
+or to an empty string if unknown.
+<br><dt><strong><a name="cgiGatewayInterface">char *cgiGatewayInterface</a>
+</strong><br><dd>Points to the name of the gateway interface (usually CGI/1.1),
+or to an empty string if unknown.
+<br><dt><strong><a name="cgiServerProtocol">char *cgiServerProtocol</a>
+</strong><br><dd>Points to the protocol in use (usually HTTP/1.0),
+or to an empty string if unknown.
+<br><dt><strong><a name="cgiServerPort">char *cgiServerPort</a>
+</strong><br><dd>Points to the port number on which the server is listening
+for HTTP connections (usually 80), or an empty string if unknown.
+<br><dt><strong><a name="cgiRequestMethod">char *cgiRequestMethod</a>
+</strong><br><dd>Points to the method used in the request (usually GET or POST),
+or an empty string if unknown (this should not happen).
+<br><dt><strong><a name="cgiPathInfo">char *cgiPathInfo</a>
+</strong><br><dd>Most web servers recognize any additional path information in 
+the URL of the request beyond the name of the CGI program itself and
+pass that information on to the program. cgiPathInfo points to this
+additional path information.
+<br><dt><strong><a name="cgiPathTranslated">char *cgiPathTranslated</a>
+</strong><br><dd>Most web servers recognize any additional path information in 
+the URL of the request beyond the name of the CGI program itself and
+pass that information on to the program. cgiPathTranslated points
+to this additional path information, translated by the server into a 
+filesystem path on the local server.
+<br><dt><strong><a name="cgiScriptName">char *cgiScriptName</a>
+</strong><br><dd>Points to the name under which the program was invoked.
+<br><dt><strong><a name="cgiQueryString">char *cgiQueryString</a>
+</strong><br><dd>Contains any query information submitted by the user as a result
+of a GET-method form or an <ISINDEX> tag. Note that this
+information need not be parsed directly unless an <ISINDEX> tag
+was used; normally it is parsed automatically by the cgic library. Use 
+the cgiForm family of functions to retrieve the values associated
+with form input fields. See <a href="#howto">how to write
+a cgic application</a> for more information.
+<br><dt><strong><a name="cgiRemoteHost">char *cgiRemoteHost</a>
+</strong><br><dd>Points to the fully resolved hostname of the browser, if known,
+or an empty string if unknown.
+<br><dt><strong><a name="cgiRemoteAddr">char *cgiRemoteAddr</a>
+</strong><br><dd>Points to the dotted-decimal IP address of the browser, if known,
+or an empty string if unknown.
+<br><dt><strong><a name="cgiAuthType">char *cgiAuthType</a>
+</strong><br><dd>Points to the type of authorization used for the request,
+if any, or an empty string if none or unknown.
+<br><dt><strong><a name="cgiRemoteUser">char *cgiRemoteUser</a>
+</strong><br><dd>Points to the user name under which the user has 
+authenticated; an empty string if no authentication has
+taken place. The certainty of this information depends on
+the type of authorization in use; see
+<a href="#cgiAuthType">cgiAuthType</a>.
+<br><dt><strong><a name="cgiRemoteIdent">char *cgiRemoteIdent</a>
+</strong><br><dd>Points to the user name volunteered by the user via
+the user identification protocol; an empty
+string if unknown. This information is not secure.
+Identification demons can be installed by users on
+insecure systems such as Windows machines.
+<br><dt><strong><a name="cgiContentType">char *cgiContentType</a>
+</strong><br><dd>Points to the MIME content type of the information
+submitted by the user, if any; an empty string if no
+information was submitted. If this string is equal to
+<code>application/x-www-form-urlencoded</code> or
+<code>multipart/form-data</code>, the cgic
+library will automatically examine the form data submitted.
+If this string has any other non-empty value, a different
+type of data has been submitted. This is currently very rare,
+as most browsers can only submit forms and file uploads which
+cgic parses directly.
+<br><dt><strong><a name="cgiContentType">char *cgiCookie</a>
+</strong><br><dd>Points to the raw cookie (browser-side persistent storage)
+data submitted by the web browser. 
+Programmers should use the functions <a href="#cgiCookies">cgiCookies</a>,
+<a href="#cgiCookieString">cgiCookieString</a> and
+<a href="#cgiCookieInteger">cgiCookieInteger</a> instead of
+examining this string directly.
+<br><dt><strong><a name="cgiAccept">char *cgiAccept</a>
+</strong><br><dd>Points to a space-separated list of MIME content types
+acceptable to the browser (see <a href="#cgiHeaderContentType">
+cgiHeaderContentType()</a> ), or an empty string. Unfortunately, this variable
+is not supplied in a useful form by most current browsers. Programmers wishing
+to make decisions based on the capabilities of the browser
+are advised to check the <a href="#cgiUserAgent">cgiUserAgent</a>
+variable against a list of browsers and capabilities instead.
+<br><dt><strong><a name="cgiUserAgent">char *cgiUserAgent</a>
+</strong><br><dd>
+Points to the name of the browser in use, or an empty
+string if this information is not available. 
+<br><dt><strong><a name="cgiReferrer">char *cgiReferrer</a>
+</strong><br><dd>
+Points to the URL of the previous page visited by the user. This is
+often the URL of the form that brought the user to your program.
+Note that reporting this information is entirely up to the browser,
+which may choose not do so, and may choose not to do so truthfully.
+However, this variable is typically accurate. <strong>The frequently
+used misspelling cgiReferer is also supplied as a macro.</strong>
+<br><dt><strong><a name="cgiContentLength">int cgiContentLength</a>
+</strong><br><dd>The number of bytes of form or query data received.
+  Note that if the submission is a form or query submission
+  the library will read and parse all the information
+  directly from cgiIn and/or cgiQueryString. The programmer should
+  not do so, and indeed the cgiIn pointer will be at end-of-file
+  in such cases.
+<br><dt><strong><a name="cgiOut">FILE *cgiOut</a>
+</strong><br><dd>Pointer to CGI output. The cgiHeader functions, such as
+  <a href="#cgiHeaderContentType">cgiHeaderContentType</a>, should 
+  be used first to output the mime headers; the output HTML
+  page, GIF image or other web document should then be written
+  to cgiOut by the programmer using standard C I/O functions
+  such as fprintf() and fwrite(). cgiOut is normally equivalent
+  to stdout; however, it is recommended that cgiOut be used to
+  ensure compatibility with future versions of cgic for
+  specialized environments.
+<br><dt><strong><a name="cgiIn">FILE *cgiIn</a>
+</strong><br><dd>Pointer to CGI input. In 99.99% of cases, you will not 
+  need this. CGIC 2.0 supports both regular POST form submissions
+  and multipart/form-data file upload form submissions directly.
+</dl>
+<H3><a name="resultcodes">cgic result code reference</a></h3>
+<p>
+In most cases, cgic functions are designed to produce reasonable results
+even when browsers and users do unreasonable things. However, it is sometimes
+important to know precisely which unreasonable things took place, especially
+when assigning a default value or bounding a value is an inadequate
+solution. The following result codes are useful in making this determination.
+<dl>
+<br><dt><strong><a name="cgiFormSuccess">cgiFormSuccess</a>
+</strong><br><dd>Indicates that the function successfully performed at least one
+action (or retrieved at least one value, where applicable).
+<br><dt><strong><a name="cgiFormTruncated">cgiFormTruncated</a>
+</strong><br><dd>Indicates that a string value retrieved from the user was
+cut short to avoid overwriting the end of a buffer.
+<br><dt><strong><a name="cgiFormBadType">cgiFormBadType</a>
+</strong><br><dd>Indicates that a "numeric" value submitted by the user was
+in fact not a legal number.
+<br><dt><strong><a name="cgiFormEmpty">cgiFormEmpty</a>
+</strong><br><dd>Indicates that a field was retrieved but contained no data.
+<br><dt><strong><a name="cgiFormNotFound">cgiFormNotFound</a>
+</strong><br><dd>Indicates that no value was submitted for a particular field.
+<br><dt><strong><a name="cgiFormConstrained">cgiFormConstrained</a>
+</strong><br><dd>Indicates that a numeric value was beyond the specified bounds
+and was forced to the lower or upper bound as appropriate.
+<br><dt><strong><a name="cgiFormNoSuchChoice">cgiFormNoSuchChoice</a>
+</strong><br><dd>Indicates that the value submitted for a single-choice field
+(such as a radio-button group) was not one of the acceptable values.
+This usually indicates a discrepancy between the form and the program.
+<br><dt><strong><a name="cgiFormEOF">cgiFormEOF</a>
+</strong><br><dd>Returned by <a href="#cgiFormFileRead">cgiFormFileRead</a>
+when, at the start of the call, the cgiFilePtr object is already
+positioned at the end of the uploaded file data. 
+<br><dt><strong><a name="cgiFormEOF">cgiFormIO</a>
+</strong><br><dd>Returned by <a href="#cgiFormFileRead">cgiFormFileRead</a>
+when an I/O error occurs while reading uploaded file data.
+<br><dt><strong><a name="cgiFormNotAFile">cgiFormNotAFile</a>
+</strong><br><dd>Returned in response to an attempt to manipulate a form field
+that is not a file upload field using a file-related function.
+<br><dt><strong><a name="cgiFormNoContentType">cgiFormNoContentType</a>
+</strong><br><dd>Returned in response to an attempt to fetch the content type of
+a file-upload field when the content type is not specified by the browser.
+<br><dt><strong><a name="cgiFormNoFileName">cgiFormNoFileName</a>
+</strong><br><dd>Returned in response to an attempt to fetch the file name of
+a file-upload field when a file name is not specified by the browser.
+<br><dt><strong><a name="cgiFormOpenFailed">cgiFormOpenFailed</a>
+</strong><br><dd>Returned in response to an attempt to read from a null
+cgiFilePtr object, typically when the programmer has failed to
+check the result of a call to <a href="#cgiFormFileOpen">cgiFormFileOpen</a>.
+<br><dt><strong><a name="cgiEnvironmentMemory">cgiEnvironmentMemory</a>
+</strong><br><dd>Indicates that an attempt to read or write the CGI environment
+to or from a capture file failed due to an out-of-memory error.
+<br><dt><strong><a name="cgiEnvironmentSuccess">cgiEnvironmentSuccess</a>
+</strong><br><dd>Indicates that an attempt to read or write the CGI environment
+to or from a capture file was successful.
+<br><dt><strong><a name="cgiEnvironmentIO">cgiEnvironmentIO</a>
+</strong><br><dd>Indicates that an attempt to read or write the CGI environment
+to or from a capture file failed due to an I/O error. 
+<br><dt><strong><a name="cgiEnvironmentWrongVersion">cgiEnvironmentWrongVersion</a>
+</strong><br><dd>Indicates that an attempt to read from a saved debugging CGI environment
+produced by a pre-2.0 version of CGIC was made. 
+</dl>
+<h3><a name="index">cgic quick index</a></h3>
+<a href="#cgiAccept">cgiAccept</a> |
+<a href="#cgiAuthType">cgiAuthType</a> |
+<a href="#cgiContentLength">cgiContentLength</a> |
+<a href="#cgiContentType">cgiContentType</a> |
+<a href="#cgiEnvironmentIO">cgiEnvironmentIO</a> |
+<a href="#cgiEnvironmentMemory">cgiEnvironmentMemory</a> |
+<a href="#cgiEnvironmentSuccess">cgiEnvironmentSuccess</a> |
+<a href="#cgiCookieInteger">cgiCookieInteger</a> |
+<a href="#cgiCookies">cgiCookies</a> |
+<a href="#cgiCookieSetInteger">cgiCookieSetInteger</a> |
+<a href="#cgiCookieSetString">cgiCookieSetString</a> |
+<a href="#cgiCookieString">cgiCookieString</a> |
+<a href="#cgiHtmlEscape">cgiHtmlEscape</a> |
+<a href="#cgiHtmlEscapeData">cgiHtmlEscapeData</a> |
+<a href="#cgiValueEscape">cgiValueEscape</a> |
+<a href="#cgiValueEscapeData">cgiValueEscapeData</a> |
+<a href="#cgiFormBadType">cgiFormBadType</a> |
+<a href="#cgiFormCheckboxMultiple">cgiFormCheckboxMultiple()</a> |
+<a href="#cgiFormCheckboxSingle">cgiFormCheckboxSingle()</a> |
+<a href="#cgiFormConstrained">cgiFormConstrained</a> |
+<a href="#cgiFormDouble">cgiFormDouble()</a> |
+<a href="#cgiFormDoubleBounded">cgiFormDoubleBounded()</a> |
+<a href="#cgiFormEOF">cgiFormEOF</a> |
+<a href="#cgiFormEmpty">cgiFormEmpty</a> |
+<a href="#cgiFormEntries">cgiFormEntries</a> |
+<a href="#cgiFormFileClose">cgiFormFileClose</a> |
+<a href="#cgiFormFileContentType">cgiFormFileContentType</a> |
+<a href="#cgiFormFileName">cgiFormFileName</a> |
+<a href="#cgiFormFileOpen">cgiFormFileOpen</a> |
+<a href="#cgiFormFileRead">cgiFormFileRead</a> |
+<a href="#cgiFormFileSize">cgiFormFileSize</a> |
+<a href="#cgiFormInteger">cgiFormInteger()</a> |
+<a href="#cgiFormIntegerBounded">cgiFormIntegerBounded()</a> |
+<a href="#cgiFormNoContentType>cgiFormNoContentType</a> |
+<a href="#cgiFormNoFileName>cgiFormNoFileName</a> |
+<a href="#cgiFormNoSuchChoice">cgiFormNoSuchChoice</a> |
+<a href="#cgiFormNotAFile>cgiFormNotAFile</a> |
+<a href="#cgiFormNotFound">cgiFormNotFound</a> |
+<a href="#cgiFormRadio">cgiFormRadio()</a> |
+<a href="#cgiFormSelectMultiple">cgiFormSelectMultiple()</a> |
+<a href="#cgiFormSelectSingle">cgiFormSelectSingle()</a> |
+<a href="#cgiFormString">cgiFormString()</a> |
+<a href="#cgiFormStringMultiple">cgiFormStringMultiple()</a> |
+<a href="#cgiFormStringNoNewlines">cgiFormStringNoNewlines()</a> |
+<a href="#cgiFormStringSpaceNeeded">cgiFormStringSpaceNeeded()</a> |
+<a href="#cgiFormSuccess">cgiFormSuccess</a> |
+<a href="#cgiFormTruncated">cgiFormTruncated</a> |
+<a href="#cgiGatewayInterface">cgiGatewayInterface</a> |
+<a href="#cgiHeaderContentType">cgiHeaderContentType()</a> |
+<a href="#cgiHeaderLocation">cgiHeaderLocation()</a> |
+<a href="#cgiHeaderStatus">cgiHeaderStatus()</a> |
+<a href="#cgiIn">cgiIn</a> |
+<a href="#cgiMain">cgiMain()</a>
+<a href="#cgiOut">cgiOut</a> |
+<a href="#cgiPathInfo">cgiPathInfo</a> |
+<a href="#cgiPathTranslated">cgiPathTranslated</a> |
+<a href="#cgiQueryString">cgiQueryString</a> |
+<a href="#cgiReadEnvironment">cgiReadEnvironment()</a> |
+<a href="#cgiReferrer">cgiReferrer()</a> |
+<a href="#cgiRemoteAddr">cgiRemoteAddr</a> |
+<a href="#cgiRemoteHost">cgiRemoteHost</a> |
+<a href="#cgiRemoteIdent">cgiRemoteIdent</a> |
+<a href="#cgiRemoteUser">cgiRemoteUser</a> |
+<a href="#cgiRequestMethod">cgiRequestMethod</a> |
+<a href="#cgiScriptName">cgiScriptName</a> |
+<a href="#cgiServerName">cgiServerName</a> |
+<a href="#cgiServerPort">cgiServerPort</a> |
+<a href="#cgiServerProtocol">cgiServerProtocol</a> |
+<a href="#cgiServerSoftware">cgiServerSoftware</a> |
+<a href="#cgiStringArrayFree">cgiStringArrayFree()</a> |
+<a href="#cgiUserAgent">cgiUserAgent</a> |
+<a href="#cgiWriteEnvironment">cgiWriteEnvironment()</a>
+<p>
+<hr>
+<em><a href="http://www.boutell.com/">Boutell.Com, Inc.</a></em>
+</body>
+</html>
+
+
diff --git a/thirds/cgic206/cgictest.c b/thirds/cgic206/cgictest.c
new file mode 100644
index 0000000..19427c3
--- /dev/null
+++ b/thirds/cgic206/cgictest.c
@@ -0,0 +1,222 @@
+
+/*
+  $Id: cgictest.c,v 1.2 2004/04/07 17:09:27 fox Exp $
+ */
+
+#include <stdio.h>
+#include "cgic.h"
+
+void Name();
+void Address();
+void Hungry();
+void Temperature();
+void Frogs();
+void Color();
+void Flavors();
+void NonExButtons();
+void RadioButtons();
+
+
+int cgiMain() {
+#if DEBUG
+	/* Load a saved CGI scenario if we're debugging */
+	cgiReadEnvironment("/home/boutell/public_html/capcgi.dat");
+#endif
+	dup2(cgiOut,stdout);
+	printf("Content-Type: text/html; charset=utf-8\r\nStatus: 200 OK\r\n\r\n");
+	//cgiHeaderContentType("text/html");
+	printf( "<HTML><HEAD>\n");
+	printf( "<TITLE>cgic test</TITLE></HEAD>\n");
+	printf( "<BODY><H1>cgic test</H1>\n");
+	Name();
+	Address();
+	Hungry();
+	Temperature();
+	Frogs();
+	Color();
+	Flavors();
+	NonExButtons();
+	RadioButtons();
+	printf( "</BODY></HTML>\n");
+	return 0;
+}
+
+void Name() {
+	char name[81];
+	int result = cgiFormStringNoNewlines("name", name, 81);
+	switch (result) {
+		case cgiFormSuccess:
+		printf( "Name fetched, result code: cgiFormSuccess<br>\n");
+		break;
+		case cgiFormTruncated:
+		printf( "Name fetched, result code: cgiFormTruncated<br>\n");
+		break;
+		case cgiFormEmpty:
+		printf( "Name fetched, result code: cgiFormEmpty<br>\n");
+		break;
+		case cgiFormNotFound:
+		printf( "Name fetched, result code: cgiFormNotFound<br>\n");
+		break;
+		case cgiFormMemory:
+		printf( "Name fetched, result code: cgiFormMemory<br>\n");
+		break;
+		default:
+		printf( "Name fetched, unexpected result code: %d\n", result);
+		break;
+	}	
+	printf( "Name: %s<BR>\n", name);
+}
+	
+void Address() {
+	char address[241];
+	cgiFormString("address", address, 241);
+	printf( "Address: <PRE>\n%s</PRE>\n", address);
+}
+
+void Hungry() {
+	if (cgiFormCheckboxSingle("hungry") == cgiFormSuccess) {
+		printf( "I'm Hungry!<BR>\n");
+	} else {
+		printf( "I'm Not Hungry!<BR>\n");
+	}
+}
+	
+void Temperature() {
+	double temperature;
+	cgiFormDoubleBounded("temperature", &temperature, 80.0, 120.0, 98.6);
+	printf( "My temperature is %f.<BR>\n", temperature);
+}
+	
+void Frogs() {
+	int frogsEaten;
+	cgiFormInteger("frogs", &frogsEaten, 0);
+	printf( "I have eaten %d frogs.<BR>\n", frogsEaten);
+}
+
+char *colors[] = {
+	"Red",
+	"Green",
+	"Blue"
+};
+
+void Color() {
+	int colorChoice;
+	cgiFormSelectSingle("colors", colors, 3, &colorChoice, 0);
+	printf( "I am: %s<BR>\n", colors[colorChoice]);
+}	 
+
+char *flavors[] = {
+	"pistachio",
+	"walnut",
+	"creme"
+};
+
+void Flavors() {
+	int flavorChoices[3];
+	int i;
+	int result;	
+	int invalid;
+	result = cgiFormSelectMultiple("flavors", flavors, 3, 
+		flavorChoices, &invalid);
+	if (result == cgiFormNotFound) {
+		printf( "I hate ice cream.<p>\n");
+	} else {	
+		printf( "My favorite ice cream flavors are:\n");
+		printf( "<ul>\n");
+		for (i=0; (i < 3); i++) {
+			if (flavorChoices[i]) {
+				printf( "<li>%s\n", flavors[i]);
+			}
+		}
+		printf( "</ul>\n");
+	}
+}
+
+char *ages[] = {
+	"1",
+	"2",
+	"3",
+	"4"
+};
+
+void RadioButtons() {
+	int ageChoice;
+	char ageText[10];
+	/* Approach #1: check for one of several valid responses. 
+		Good if there are a short list of possible button values and
+		you wish to enumerate them. */
+	cgiFormRadio("age", ages, 4, &ageChoice, 0);
+
+	printf( "Age of Truck: %s (method #1)<BR>\n", 
+		ages[ageChoice]);
+
+	/* Approach #2: just get the string. Good
+		if the information is not critical or if you wish
+		to verify it in some other way. Note that if
+		the information is numeric, cgiFormInteger,
+		cgiFormDouble, and related functions may be
+		used instead of cgiFormString. */	
+	cgiFormString("age", ageText, 10);
+
+	printf( "Age of Truck: %s (method #2)<BR>\n", ageText);
+}
+
+char *votes[] = {
+	"A",
+	"B",
+	"C",
+	"D"
+};
+
+void NonExButtons() {
+	int voteChoices[4];
+	int i;
+	int result;	
+	int invalid;
+
+	char **responses;
+
+	/* Method #1: check for valid votes. This is a good idea,
+		since votes for nonexistent candidates should probably
+		be discounted... */
+	printf( "Votes (method 1):<BR>\n");
+	result = cgiFormCheckboxMultiple("vote", votes, 4, 
+		voteChoices, &invalid);
+	if (result == cgiFormNotFound) {
+		printf( "I hate them all!<p>\n");
+	} else {	
+		printf( "My preferred candidates are:\n");
+		printf( "<ul>\n");
+		for (i=0; (i < 4); i++) {
+			if (voteChoices[i]) {
+				printf( "<li>%s\n", votes[i]);
+			}
+		}
+		printf( "</ul>\n");
+	}
+
+	/* Method #2: get all the names voted for and trust them.
+		This is good if the form will change more often
+		than the code and invented responses are not a danger
+		or can be checked in some other way. */
+	printf( "Votes (method 2):<BR>\n");
+	result = cgiFormStringMultiple("vote", &responses);
+	if (result == cgiFormNotFound) {	
+		printf( "I hate them all!<p>\n");
+	} else {
+		int i = 0;
+		printf( "My preferred candidates are:\n");
+		printf( "<ul>\n");
+		while (responses[i]) {
+			printf( "<li>%s\n", responses[i]);
+			i++;
+		}
+		printf( "</ul>\n");
+	}
+	/* We must be sure to free the string array or a memory
+		leak will occur. Simply calling free() would free
+		the array but not the individual strings. The
+		function cgiStringArrayFree() does the job completely. */	
+	cgiStringArrayFree(responses);
+}
+
diff --git a/thirds/cgic206/debian/changelog b/thirds/cgic206/debian/changelog
new file mode 100644
index 0000000..1e2aa6a
--- /dev/null
+++ b/thirds/cgic206/debian/changelog
@@ -0,0 +1,32 @@
+libcgic (2.06-1~trusty3) trusty; urgency=low
+
+  * New version to be used for ZOO-Kernel.
+
+ -- Angelos Tzotsos <gcpp.kalxas at gmail.com>  Tue, 10 Jun 2014 19:29:04 +0200
+
+libcgic (2.05-3) unstable; urgency=low
+
+  * debian/control: Suggests: httpd.  Closes: #600138.
+  * debian/control: Fixed debhelper-but-no-misc-depends.
+
+ -- Bart Martens <bartm at debian.org>  Sun, 13 May 2012 08:33:04 +0000
+
+libcgic (2.05-2) unstable; urgency=low
+
+  * debian/control: Standards-Version, Homepage.
+
+ -- Bart Martens <bartm at debian.org>  Sun, 13 Jul 2008 09:31:48 +0200
+
+libcgic (2.05-1) unstable; urgency=low
+
+  * New maitnainer.  Closes: #438643.
+  * New upstream release.
+  * debian/*: Repackaged with cdbs.
+  * debian/changelog-upstream.html: Removed.
+  * debian/Makefile.examples: Removed.
+  * debian/README.Debian: Removed.
+  * debian/copyright: Updated.
+  * debian/watch: Updated.
+
+ -- Bart Martens <bartm at knars.be>  Sun, 19 Aug 2007 09:18:53 +0200
+
diff --git a/thirds/cgic206/debian/compat b/thirds/cgic206/debian/compat
new file mode 100644
index 0000000..7ed6ff8
--- /dev/null
+++ b/thirds/cgic206/debian/compat
@@ -0,0 +1 @@
+5
diff --git a/thirds/cgic206/debian/control b/thirds/cgic206/debian/control
new file mode 100644
index 0000000..d5ba147
--- /dev/null
+++ b/thirds/cgic206/debian/control
@@ -0,0 +1,35 @@
+Source: libcgic
+Section: libs
+Priority: optional
+Maintainer: Bart Martens <bartm at debian.org>
+Build-Depends: cdbs, libfcgi-dev, debhelper (>= 5)
+Standards-Version: 3.9.3
+Homepage: http://www.boutell.com/cgic/
+
+Package: libcgic-dev
+Section: libdevel
+Architecture: any
+Depends: libc6-dev, ${misc:Depends}
+Suggests: httpd
+Conflicts: libcgicg1-dev
+Replaces: libcgicg1-dev
+Description: C library for developing CGI applications
+ Cgic is an ANSI-C library for the creation of CGI-based World Wide Web
+ applications.  Cgic provides the following:
+ .
+   * Parses form data, correcting for defective and/or inconsistent
+     browsers
+   * Transparently accepts both GET and POST form data
+   * Handles line breaks in form fields in a consistent manner
+   * Provides string, integer, floating-point, and single- and
+     multiple-choice functions to retrieve form data
+   * Provides bounds checking for numeric fields
+   * Loads CGI environment variables into C strings which are always
+     non-null
+   * Provides a way to capture CGI situations for replay in a debugging
+     environment
+ .
+ This package provides a static library version of cgic, examples of using
+ cgic (including a CGI application that captures a CGI environment for use
+ in debugging), and header files.
+
diff --git a/thirds/cgic206/debian/copyright b/thirds/cgic206/debian/copyright
new file mode 100644
index 0000000..954eae2
--- /dev/null
+++ b/thirds/cgic206/debian/copyright
@@ -0,0 +1,28 @@
+This package was debianized by Brian Bassett brian at butterfly.ml.org on
+Tue, 11 Nov 1997 17:28:04 -0800.
+
+It was downloaded from:
+
+    http://www.boutell.com/cgic/
+
+Upstream author:
+
+    Thomas Boutell <boutell at boutell.com>
+
+Copyright:
+
+    Copyright (C) 1996-2004 by Thomas Boutell and Boutell.Com, Inc.
+
+License:
+
+    CGIC, copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+    2004 by Thomas Boutell and Boutell.Com, Inc.. Permission is granted to
+    use CGIC in any application, commercial or noncommercial, at no cost.
+    HOWEVER, this copyright paragraph must appear on a "credits" page
+    accessible in the public online and offline documentation of the program.
+    Modified versions of the CGIC library should not be distributed without
+    the attachment of a clear statement regarding the author of the
+    modifications, and this notice may in no case be removed.
+    Modifications may also be submitted to the author for inclusion
+    in the main CGIC distribution.
+
diff --git a/thirds/cgic206/debian/libcgic-dev.docs b/thirds/cgic206/debian/libcgic-dev.docs
new file mode 100644
index 0000000..8c40a55
--- /dev/null
+++ b/thirds/cgic206/debian/libcgic-dev.docs
@@ -0,0 +1 @@
+cgic.html
diff --git a/thirds/cgic206/debian/libcgic-dev.examples b/thirds/cgic206/debian/libcgic-dev.examples
new file mode 100644
index 0000000..995f292
--- /dev/null
+++ b/thirds/cgic206/debian/libcgic-dev.examples
@@ -0,0 +1,2 @@
+capture.c
+cgictest.c
diff --git a/thirds/cgic206/debian/libcgic-dev.install b/thirds/cgic206/debian/libcgic-dev.install
new file mode 100644
index 0000000..8315d7a
--- /dev/null
+++ b/thirds/cgic206/debian/libcgic-dev.install
@@ -0,0 +1,2 @@
+cgic.h usr/include/
+libcgic.a usr/lib/
diff --git a/thirds/cgic206/debian/libcgic-dev.links b/thirds/cgic206/debian/libcgic-dev.links
new file mode 100644
index 0000000..ba5e875
--- /dev/null
+++ b/thirds/cgic206/debian/libcgic-dev.links
@@ -0,0 +1 @@
+/usr/lib/libcgic.so.2.06 /usr/lib/libcgic.so
diff --git a/thirds/cgic206/debian/rules b/thirds/cgic206/debian/rules
new file mode 100755
index 0000000..a8f32de
--- /dev/null
+++ b/thirds/cgic206/debian/rules
@@ -0,0 +1,7 @@
+#!/usr/bin/make -f
+
+include /usr/share/cdbs/1/rules/debhelper.mk
+include /usr/share/cdbs/1/class/makefile.mk
+
+clean::
+	rm -f libcgic.so.2.06
diff --git a/thirds/cgic206/debian/watch b/thirds/cgic206/debian/watch
new file mode 100644
index 0000000..3dff489
--- /dev/null
+++ b/thirds/cgic206/debian/watch
@@ -0,0 +1,4 @@
+version=3
+opts="uversionmangle=s/^(\d)(\d\d)$/$1.$2/" \
+http://www.boutell.com/cgic/ \
+cgic(.*)\.t.*
diff --git a/thirds/cgic206/license.txt b/thirds/cgic206/license.txt
new file mode 100644
index 0000000..b32fb89
--- /dev/null
+++ b/thirds/cgic206/license.txt
@@ -0,0 +1,109 @@
+CGIC License Terms
+------------------
+
+Basic License
+-------------
+
+CGIC, copyright 2009 GeoLabs SARL.
+CGIC, copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+2004 by Thomas Boutell and Boutell.Com, Inc.. Permission is granted to 
+use CGIC in any application, commercial or noncommercial, at no cost. 
+HOWEVER, this copyright paragraph must appear on a "credits" page 
+accessible in the public online and offline documentation of the program. 
+Modified versions of the CGIC library should not be distributed without 
+the attachment of a clear statement regarding the author of the 
+modifications, and this notice may in no case be removed. 
+Modifications may also be submitted to the author for inclusion 
+in the main CGIC distribution.                                 
+
+IF YOU WOULD PREFER NOT TO ATTACH THE ABOVE NOTICE to
+the public documentation of your application, consult the
+information which follows regarding the availability
+of a nonexclusive commercial license for CGIC.
+
+Commercial License
+------------------
+
+The price of a nonexclusive commercial license is $200 U.S. 
+To purchase the license:
+
+1. Print and sign two copies of the document below.
+
+2. Send both copies, along with Visa, Mastercard, Discover, or
+Amex card number, cardholder's name, and expiration date 
+OR a check for $200 in U.S. funds drawn on a U.S. bank, to:
+
+Boutell.Com, Inc.
+PO Box 63767
+Philadelphia, PA 19147 USA
+
+Credit card orders may alternatively be faxed to:
+
+Boutell.Com, Inc.
+(208) 445-0327
+
+BE SURE TO INCLUDE AN EMAIL ADDRESS, as well as
+a postal address and phone number.
+
+3. We will return one signed copy to you promptly.
+
+You will also receive swift notification of new
+versions of CGIC, in addition to ongoing
+email support.
+
+* * *
+
+CGIC Nonexclusive Commercial License
+
+The licensee named below is granted the right
+to utilize CGIC, major version 1 or 2, any minor
+version thereof, in CGI applications without the
+need for a credit notice of any kind. CGI applications
+developed by the holder of this license may be
+distributed freely in source code or binary form
+without additional fees or royalties. This license does 
+not grant the right to use CGIC to create a development tool 
+which passes on substantially all of the capabilities of the 
+CGIC library to the user of the tool, unless that tool is 
+to be used internally by the license holder only in order
+to develop CGI applications. This license may not
+be resold, but applications developed in accordance
+with the terms of the license may be distributed
+freely subject to the limitations described above.
+
+Future minor (2.x) versions of CGIC will be covered by this
+license free of charge. If significant defects of workmanship
+are discovered in version 2.x, minor releases to correct them
+will be made available before or at the same time that 
+those defects are addressed in any future major version. 
+Future "major" (3.x) versions will be available to
+licensees at an upgrade price of $50.
+
+If, for any reason, any portion of this license is found 
+to be invalid, that portion of the license only
+is invalidated and the remainder of the agreement
+remains in effect.
+
+If this license has not been signed by Thomas Boutell
+or M. L. Grant on behalf of Boutell. Com, Inc., 
+it is invalid.
+
+Licensee's Name:              _____________________
+
+Signed for Licensee:          _____________________
+
+Complete Mailing Address:     _____________________
+
+                              _____________________
+
+                              _____________________
+
+Phone Number:                 _____________________
+
+Email Address:                _____________________
+
+Signed for Boutell.Com, Inc.: _____________________
+
+Date:                         _____________________
+
+
diff --git a/thirds/cgic206/makefile.vc b/thirds/cgic206/makefile.vc
new file mode 100644
index 0000000..1518f8a
--- /dev/null
+++ b/thirds/cgic206/makefile.vc
@@ -0,0 +1,35 @@
+GEODIR=\MMBK\SRCS\fcgi-2.4.1-SNAP-0311112127\ 
+DESTDIR=..
+CFLAGS=-g -Wall
+CC=cl /TP
+LIBS=$(GEODIR)/libfcgi/Release/libfcgi.lib /nologo
+LIBS1=./libcgic.lib
+
+CFLAGS=/EHa /nologo /DCRT_SECURE_NO_WARNING /MD /W2 /O2 /D "WIN32" \
+	-I $(GEODIR)\include 
+
+all: libcgic.lib #cgictest.exe capture.exe 
+
+install: libcgic.lib
+	copy libcgic.lib  $(DESTDIR)\lib
+	copy cgic.h  $(DESTDIR)\include
+	@echo libcgic.lib is now installed in  $(DESTDIR)\lib and cgic.h is in  $(DESTDIR)\include.
+
+libcgic.lib: cgic.obj cgic.h
+	if exist cgic.lib del cgic.lib
+	lib /out:libcgic.lib cgic.obj $(LIBS)
+
+cgictest.obj: cgictest.c libcgic.lib
+	$(CC) $(CFLAGS) -c cgictest.c
+
+cgictest.exe: cgictest.obj 
+	link cgictest.obj $(LIBS) /out:cgictest.exe
+
+cgic.obj: 
+	$(CC) $(CFLAGS) -c cgic.c 
+
+capture.exe: capture.obj libcgic.lib
+	$(CC) $(CFLAGS) capture.c $(LIBS)
+
+clean:
+	erase *.obj *.lib *.exe *.manifest
diff --git a/thirds/cgic206/readme.txt b/thirds/cgic206/readme.txt
new file mode 100644
index 0000000..4a79968
--- /dev/null
+++ b/thirds/cgic206/readme.txt
@@ -0,0 +1,14 @@
+This is the CGIC CGI development library for C programmers.
+Copyright 2009 GeoLabs SARL
+Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+2004, Thomas Boutell and Boutell.Com, Inc.
+
+See the file cgic.html for complete documentation in a single
+HTML hypertext file to be accessed with your web browser. If you
+preferer, there is a plaintext version in the file cgic.txt. 
+Or see http://www.boutell.com/cgic/ for the latest copy of 
+the documentation.
+
+See the files license.txt and support.txt for terms of use and
+technical support information.
+
diff --git a/thirds/cgic206/support.txt b/thirds/cgic206/support.txt
new file mode 100644
index 0000000..e7884bf
--- /dev/null
+++ b/thirds/cgic206/support.txt
@@ -0,0 +1,46 @@
+Support for CGIC
+----------------
+
+   ____
+  /    \
+ | STOP |
+  \____/
+  
+    Are you getting a "server error," indicating that your web server
+    "cannot allow POST to this URL," or a similar message? YOU MUST
+    CONFIGURE YOUR WEB SERVER TO ALLOW CGI PROGRAMS, AND YOU MUST
+    INSTALL CGI PROGRAMS IN THE LOCATION (OR WITH THE EXTENSION) THAT
+    YOUR WEB SERVER EXPECTS TO SEE. Please don't send me email about
+    this, unless you are purchasing commercial support. It is strictly 
+    between you and your web server's documentation, or between you and 
+    your ISP. If you wish to purchase commercial support, we will gladly 
+    attempt to help you resolve such problems, but the cooperation of 
+    your web server administrator will be necessary in most cases. Thanks!
+
+Free Support
+------------
+ 
+Anyone can mail questions about the gd and cgic libraries to 
+boutell at boutell.com. However, I receive a very large volume of email on 
+many subjects, and while I do my best to respond to all queries this can 
+take some time. Sometimes the response must take the form of an eventual 
+new release or an addition to a FAQ or other document, as opposed to an 
+detailed individual response.
+
+Hourly Support
+--------------
+
+Those requiring support in detail may arrange for direct support
+from the author, Thomas Boutell, at the rate of $50/hr, billed
+directly by credit card. Purchase orders are also accepted from
+Fortune 500 corporations and institutions in good standing.
+To make arrangements, contact boutell at boutell.com. Alternatively,
+use our free-form secure message page at:
+
+https://www.boutell.com/freeform/
+
+To avoid delay and/or confusion, be sure to specifically mention that 
+you wish to purchase CGIC support at the hourly rate above.
+
+-Thomas Boutell, boutell at boutell.com
+
diff --git a/thirds/dirent-win32/dirent.h b/thirds/dirent-win32/dirent.h
new file mode 100644
index 0000000..8abbbea
--- /dev/null
+++ b/thirds/dirent-win32/dirent.h
@@ -0,0 +1,373 @@
+/*****************************************************************************
+ * dirent.h - dirent API for Microsoft Visual Studio
+ *
+ * Copyright (C) 2006 Toni Ronkko
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * ``Software''), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Mar 15, 2011, Toni Ronkko
+ * Defined FILE_ATTRIBUTE_DEVICE for MSVC 6.0.
+ *
+ * Aug 11, 2010, Toni Ronkko
+ * Added d_type and d_namlen fields to dirent structure.  The former is
+ * especially useful for determining whether directory entry represents a
+ * file or a directory.  For more information, see
+ * http://www.delorie.com/gnu/docs/glibc/libc_270.html
+ *
+ * Aug 11, 2010, Toni Ronkko
+ * Improved conformance to the standards.  For example, errno is now set
+ * properly on failure and assert() is never used.  Thanks to Peter Brockam
+ * for suggestions.
+ *
+ * Aug 11, 2010, Toni Ronkko
+ * Fixed a bug in rewinddir(): when using relative directory names, change
+ * of working directory no longer causes rewinddir() to fail.
+ *
+ * Dec 15, 2009, John Cunningham
+ * Added rewinddir member function
+ *
+ * Jan 18, 2008, Toni Ronkko
+ * Using FindFirstFileA and WIN32_FIND_DATAA to avoid converting string
+ * between multi-byte and unicode representations.  This makes the
+ * code simpler and also allows the code to be compiled under MingW.  Thanks
+ * to Azriel Fasten for the suggestion.
+ *
+ * Mar 4, 2007, Toni Ronkko
+ * Bug fix: due to the strncpy_s() function this file only compiled in
+ * Visual Studio 2005.  Using the new string functions only when the
+ * compiler version allows.
+ *
+ * Nov  2, 2006, Toni Ronkko
+ * Major update: removed support for Watcom C, MS-DOS and Turbo C to
+ * simplify the file, updated the code to compile cleanly on Visual
+ * Studio 2005 with both unicode and multi-byte character strings,
+ * removed rewinddir() as it had a bug.
+ *
+ * Aug 20, 2006, Toni Ronkko
+ * Removed all remarks about MSVC 1.0, which is antiqued now.  Simplified
+ * comments by removing SGML tags.
+ *
+ * May 14 2002, Toni Ronkko
+ * Embedded the function definitions directly to the header so that no
+ * source modules need to be included in the Visual Studio project.  Removed
+ * all the dependencies to other projects so that this very header can be
+ * used independently.
+ *
+ * May 28 1998, Toni Ronkko
+ * First version.
+ *****************************************************************************/
+#ifndef DIRENT_H
+#define DIRENT_H
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+/* Entries missing from MSVC 6.0 */
+#if !defined(FILE_ATTRIBUTE_DEVICE)
+# define FILE_ATTRIBUTE_DEVICE 0x40
+#endif
+
+/* File type and permission flags for stat() */
+#if defined(_MSC_VER)  &&  !defined(S_IREAD)
+# define S_IFMT   _S_IFMT                      /* file type mask */
+# define S_IFDIR  _S_IFDIR                     /* directory */
+# define S_IFCHR  _S_IFCHR                     /* character device */
+# define S_IFFIFO _S_IFFIFO                    /* pipe */
+# define S_IFREG  _S_IFREG                     /* regular file */
+# define S_IREAD  _S_IREAD                     /* read permission */
+# define S_IWRITE _S_IWRITE                    /* write permission */
+# define S_IEXEC  _S_IEXEC                     /* execute permission */
+#endif
+#define S_IFBLK   0                            /* block device */
+#define S_IFLNK   0                            /* link */
+#define S_IFSOCK  0                            /* socket */
+
+#if defined(_MSC_VER)
+# define S_IRUSR  S_IREAD                      /* read, user */
+# define S_IWUSR  S_IWRITE                     /* write, user */
+# define S_IXUSR  0                            /* execute, user */
+# define S_IRGRP  0                            /* read, group */
+# define S_IWGRP  0                            /* write, group */
+# define S_IXGRP  0                            /* execute, group */
+# define S_IROTH  0                            /* read, others */
+# define S_IWOTH  0                            /* write, others */
+# define S_IXOTH  0                            /* execute, others */
+#endif
+
+/* Indicates that d_type field is available in dirent structure */
+#define _DIRENT_HAVE_D_TYPE
+
+/* File type flags for d_type */
+#define DT_LNK -100
+#define DT_UNKNOWN  0
+#define DT_REG      S_IFREG
+#define DT_DIR      S_IFDIR
+#define DT_FIFO     S_IFFIFO
+#define DT_SOCK     S_IFSOCK
+#define DT_CHR      S_IFCHR
+#define DT_BLK      S_IFBLK
+
+/* Macros for converting between st_mode and d_type */
+#define IFTODT(mode) ((mode) & S_IFMT)
+#define DTTOIF(type) (type)
+
+/*
+ * File type macros.  Note that block devices, sockets and links cannot be
+ * distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are
+ * only defined for compatibility.  These macros should always return false
+ * on Windows.
+ */
+#define	S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFFIFO)
+#define	S_ISDIR(mode)  (((mode) & S_IFMT) == S_IFDIR)
+#define	S_ISREG(mode)  (((mode) & S_IFMT) == S_IFREG)
+#define	S_ISLNK(mode)  (((mode) & S_IFMT) == S_IFLNK)
+#define	S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
+#define	S_ISCHR(mode)  (((mode) & S_IFMT) == S_IFCHR)
+#define	S_ISBLK(mode)  (((mode) & S_IFMT) == S_IFBLK)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct dirent
+{
+   char d_name[MAX_PATH + 1];                  /* File name */
+   size_t d_namlen;                            /* Length of name without \0 */
+   int d_type;                                 /* File type */
+} dirent;
+
+
+typedef struct DIR
+{
+   dirent           curentry;                  /* Current directory entry */
+   WIN32_FIND_DATAA find_data;                 /* Private file data */
+   int              cached;                    /* True if data is valid */
+   HANDLE           search_handle;             /* Win32 search handle */
+   char             patt[MAX_PATH + 3];        /* Initial directory name */
+} DIR;
+
+
+/* Forward declarations */
+static DIR *opendir(const char *dirname);
+static struct dirent *readdir(DIR *dirp);
+static int closedir(DIR *dirp);
+static void rewinddir(DIR* dirp);
+
+
+/* Use the new safe string functions introduced in Visual Studio 2005 */
+#if defined(_MSC_VER) && _MSC_VER >= 1400
+# define DIRENT_STRNCPY(dest,src,size) strncpy_s((dest),(size),(src),_TRUNCATE)
+#else
+# define DIRENT_STRNCPY(dest,src,size) strncpy((dest),(src),(size))
+#endif
+
+/* Set errno variable */
+#if defined(_MSC_VER)
+#define DIRENT_SET_ERRNO(x) _set_errno (x)
+#else
+#define DIRENT_SET_ERRNO(x) (errno = (x))
+#endif
+
+
+
+/*****************************************************************************
+ * Open directory stream DIRNAME for read and return a pointer to the
+ * internal working area that is used to retrieve individual directory
+ * entries.
+ */
+static DIR *opendir(const char *dirname)
+{
+   DIR *dirp;
+
+   /* ensure that the resulting search pattern will be a valid file name */
+   if (dirname == NULL) {
+      DIRENT_SET_ERRNO (ENOENT);
+      return NULL;
+   }
+   if (strlen (dirname) + 3 >= MAX_PATH) {
+      DIRENT_SET_ERRNO (ENAMETOOLONG);
+      return NULL;
+   }
+
+   /* construct new DIR structure */
+   dirp = (DIR*) malloc (sizeof (struct DIR));
+   if (dirp != NULL) {
+      int error;
+
+      /*
+       * Convert relative directory name to an absolute one.  This
+       * allows rewinddir() to function correctly when the current working
+       * directory is changed between opendir() and rewinddir().
+       */
+      if (GetFullPathNameA (dirname, MAX_PATH, dirp->patt, NULL)) {
+         char *p;
+
+         /* append the search pattern "\\*\0" to the directory name */
+         p = strchr (dirp->patt, '\0');
+         if (dirp->patt < p  &&  *(p-1) != '\\'  &&  *(p-1) != ':') {
+           *p++ = '\\';
+         }
+         *p++ = '*';
+         *p = '\0';
+
+         /* open directory stream and retrieve the first entry */
+         dirp->search_handle = FindFirstFileA (dirp->patt, &dirp->find_data);
+         if (dirp->search_handle != INVALID_HANDLE_VALUE) {
+            /* a directory entry is now waiting in memory */
+            dirp->cached = 1;
+            error = 0;
+         } else {
+            /* search pattern is not a directory name? */
+            DIRENT_SET_ERRNO (ENOENT);
+            error = 1;
+         }
+      } else {
+         /* buffer too small */
+         DIRENT_SET_ERRNO (ENOMEM);
+         error = 1;
+      }
+
+      if (error) {
+         free (dirp);
+         dirp = NULL;
+      }
+   }
+
+   return dirp;
+}
+
+
+/*****************************************************************************
+ * Read a directory entry, and return a pointer to a dirent structure
+ * containing the name of the entry in d_name field.  Individual directory
+ * entries returned by this very function include regular files,
+ * sub-directories, pseudo-directories "." and "..", but also volume labels,
+ * hidden files and system files may be returned.
+ */
+static struct dirent *readdir(DIR *dirp)
+{
+   DWORD attr;
+   if (dirp == NULL) {
+      /* directory stream did not open */
+      DIRENT_SET_ERRNO (EBADF);
+      return NULL;
+   }
+
+   /* get next directory entry */
+   if (dirp->cached != 0) {
+      /* a valid directory entry already in memory */
+      dirp->cached = 0;
+   } else {
+      /* get the next directory entry from stream */
+      if (dirp->search_handle == INVALID_HANDLE_VALUE) {
+         return NULL;
+      }
+      if (FindNextFileA (dirp->search_handle, &dirp->find_data) == FALSE) {
+         /* the very last entry has been processed or an error occured */
+         FindClose (dirp->search_handle);
+         dirp->search_handle = INVALID_HANDLE_VALUE;
+         return NULL;
+      }
+   }
+
+   /* copy as a multibyte character string */
+   DIRENT_STRNCPY ( dirp->curentry.d_name,
+             dirp->find_data.cFileName,
+             sizeof(dirp->curentry.d_name) );
+   dirp->curentry.d_name[MAX_PATH] = '\0';
+
+   /* compute the length of name */
+   dirp->curentry.d_namlen = strlen (dirp->curentry.d_name);
+
+   /* determine file type */
+   attr = dirp->find_data.dwFileAttributes;
+   if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
+      dirp->curentry.d_type = DT_CHR;
+   } else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
+      dirp->curentry.d_type = DT_DIR;
+   } else {
+      dirp->curentry.d_type = DT_REG;
+   }
+   return &dirp->curentry;
+}
+
+
+/*****************************************************************************
+ * Close directory stream opened by opendir() function.  Close of the
+ * directory stream invalidates the DIR structure as well as any previously
+ * read directory entry.
+ */
+static int closedir(DIR *dirp)
+{
+   if (dirp == NULL) {
+      /* invalid directory stream */
+      DIRENT_SET_ERRNO (EBADF);
+      return -1;
+   }
+
+   /* release search handle */
+   if (dirp->search_handle != INVALID_HANDLE_VALUE) {
+      FindClose (dirp->search_handle);
+      dirp->search_handle = INVALID_HANDLE_VALUE;
+   }
+
+   /* release directory structure */
+   free (dirp);
+   return 0;
+}
+
+
+/*****************************************************************************
+ * Resets the position of the directory stream to which dirp refers to the
+ * beginning of the directory.  It also causes the directory stream to refer
+ * to the current state of the corresponding directory, as a call to opendir()
+ * would have done.  If dirp does not refer to a directory stream, the effect
+ * is undefined.
+ */
+static void rewinddir(DIR* dirp)
+{
+   if (dirp != NULL) {
+      /* release search handle */
+      if (dirp->search_handle != INVALID_HANDLE_VALUE) {
+         FindClose (dirp->search_handle);
+      }
+
+      /* open new search handle and retrieve the first entry */
+      dirp->search_handle = FindFirstFileA (dirp->patt, &dirp->find_data);
+      if (dirp->search_handle != INVALID_HANDLE_VALUE) {
+         /* a directory entry is now waiting in memory */
+         dirp->cached = 1;
+      } else {
+         /* failed to re-open directory: no directory entry in memory */
+         dirp->cached = 0;
+      }
+   }
+}
+
+#ifdef __cplusplus
+}
+#endif
+#endif /*DIRENT_H*/
diff --git a/thirds/include/unistd.h b/thirds/include/unistd.h
new file mode 100644
index 0000000..ba08365
--- /dev/null
+++ b/thirds/include/unistd.h
@@ -0,0 +1,41 @@
+/**
+ * Author : Gérald FENOY
+ *
+ * Copyright (c) 2009-2013 GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef __STRICT_AINSI__
+
+#include <io.h>
+#include <process.h>
+#define mode_t int
+#define strtok_r strtok_s
+#define S_IRWXU _S_IREAD|_S_IWRITE
+#define S_IRGRP _S_IREAD|_S_IWRITE
+#define S_IROTH _S_IREAD|_S_IWRITE
+#define S_IXGRP _S_IREAD|_S_IWRITE
+#define S_IXOTH _S_IREAD|_S_IWRITE
+#define S_IWOTH _S_IREAD|_S_IWRITE
+#define S_IRUSR _S_IREAD
+#define S_IXGRP _S_IREAD|_S_IWRITE
+#define S_IWGRP _S_IREAD|_S_IWRITE
+#define S_IWUSR _S_IREAD|_S_IWRITE
+
+#endif
diff --git a/thirds/otb2zcfg/CMakeLists.txt b/thirds/otb2zcfg/CMakeLists.txt
new file mode 100644
index 0000000..9dfcdd8
--- /dev/null
+++ b/thirds/otb2zcfg/CMakeLists.txt
@@ -0,0 +1,14 @@
+PROJECT(otb2zcfg)  
+ 
+cmake_minimum_required(VERSION 2.6)  
+ 
+FIND_PACKAGE(OTB)  
+IF(OTB_FOUND)  
+  INCLUDE(${OTB_USE_FILE})  
+ELSE(OTB_FOUND)  
+  MESSAGE(FATAL_ERROR  
+      "Cannot build OTB project without OTB.  Please set OTB_DIR.")  
+ENDIF(OTB_FOUND)  
+ 
+ADD_EXECUTABLE(otb2zcfg otb2zcfg.cxx )  
+TARGET_LINK_LIBRARIES(otb2zcfg OTBCommon OTBApplicationEngine OTBIO ${ITK_LIBRARIES}) 
diff --git a/thirds/otb2zcfg/README.txt b/thirds/otb2zcfg/README.txt
new file mode 100644
index 0000000..b615c4d
--- /dev/null
+++ b/thirds/otb2zcfg/README.txt
@@ -0,0 +1,17 @@
+To build the otb2zcfg utility you should run the following command:
+
+ mkdir build
+ cd build
+ ccmake ..
+ make
+
+ 
+To generate the zcfgs for the OTB Applications available, you should run the following:
+
+ mkdir zcfgs
+ cd zcfgs
+ export ITK_AUTOLOAD_PATH=/your/path/to/otb/applications
+ ../build/otb2zcfg
+ cp *zcfg /location/to/your/cgi-bin
+
+This ITK_AUTOLOAD_PATH environment variable will be required in the [env] section of your main.cfg.
diff --git a/thirds/otb2zcfg/otb2zcfg.cxx b/thirds/otb2zcfg/otb2zcfg.cxx
new file mode 100644
index 0000000..c664211
--- /dev/null
+++ b/thirds/otb2zcfg/otb2zcfg.cxx
@@ -0,0 +1,396 @@
+#include "otbWrapperApplicationRegistry.h"
+#include "otbWrapperApplication.h"
+#include "otbImage.h" 
+#include <iostream> 
+
+using namespace otb::Wrapper;
+
+std::string ReplaceAll(std::string str, const std::string& from, const std::string& to) {
+    size_t start_pos = 0;
+    while((start_pos = str.find(from, start_pos)) != std::string::npos) {
+        str.replace(start_pos, from.length(), to);
+        start_pos += to.length(); // Handles case where 'to' is a substring of 'from'
+    }
+    return str;
+}
+
+void printDefaultOutput(){
+  std::cout << "  [Result]" << std::endl;
+  std::cout << "   Title = the result message" << std::endl;
+  std::cout << "   Abstract = the result message" << std::endl;
+  std::cout << "   <LiteralData>" << std::endl;
+  std::cout << "    dataType = string" << std::endl;
+  std::cout << "    <Default />" << std::endl;
+  std::cout << "   </LiteralData>" << std::endl;
+}
+
+void printAscii(){
+  std::cout << "    <Default>" << std::endl;
+  std::cout << "     mimeType = text/plain" << std::endl;
+  std::cout << "     encoding = ascii" << std::endl;
+  std::cout << "    </Default>" << std::endl;
+}
+
+void printXml(){
+  std::cout << "    <Default>" << std::endl;
+  std::cout << "     mimeType = text/xml" << std::endl;
+  std::cout << "     encoding = utf-8" << std::endl;
+  std::cout << "    </Default>" << std::endl;
+}
+
+void printGeoid(){
+  std::cout << "    <Default>" << std::endl;
+  std::cout << "     mimeType = application/octet-stream" << std::endl;
+  std::cout << "    </Default>" << std::endl;
+}
+
+void printCSV(){
+  std::cout << "    <Default>" << std::endl;
+  std::cout << "     mimeType = text/csv" << std::endl;
+  std::cout << "     encoding = utf-8" << std::endl;
+  std::cout << "    </Default>" << std::endl;
+}
+
+void printUnknown(){
+  std::cout << "    <Default>" << std::endl;
+  std::cout << "     mimeType = text/xml" << std::endl;
+  std::cout << "     encoding = utf-8" << std::endl;
+  std::cout << "    </Default>" << std::endl;
+  std::cout << "    <Supported>" << std::endl;
+  std::cout << "     mimeType = text/plain" << std::endl;
+  std::cout << "     encoding = utf-8" << std::endl;
+  std::cout << "    </Supported>" << std::endl;
+}
+
+void printImages(){
+  std::cout << "    <Default>" << std::endl;
+  std::cout << "     mimeType = image/tiff" << std::endl;
+  std::cout << "    </Default>" << std::endl;
+#if defined(OTB_USE_JPEG2000)
+  std::cout << "    <Supported>" << std::endl;
+  std::cout << "     mimeType = image/jp2" << std::endl;
+  std::cout << "    </Supported>" << std::endl;
+#endif
+  std::cout << "    <Supported>" << std::endl;
+  std::cout << "     mimeType = image/jpeg" << std::endl;
+  std::cout << "    </Supported>" << std::endl;
+  std::cout << "    <Supported>" << std::endl;
+  std::cout << "     mimeType = image/png" << std::endl;
+  std::cout << "    </Supported>" << std::endl;
+}
+
+void printKmz(){
+  std::cout << "    <Default>" << std::endl;
+  std::cout << "     mimeType = application/vnd.google-earth.kmz" << std::endl;
+  std::cout << "     extension = kmz" << std::endl;
+  std::cout << "    </Default>" << std::endl;
+}
+
+void printVector(){
+  std::cout << "    <Default>" << std::endl;
+  std::cout << "     mimeType = text/xml" << std::endl;
+  std::cout << "     encoding = utf-8" << std::endl;
+  std::cout << "    </Default>" << std::endl;
+  std::cout << "    <Supported>" << std::endl;
+  std::cout << "     mimeType = application/vnd.google-earth.kml+xml" << std::endl;
+  std::cout << "     encoding = utf-8" << std::endl;
+  std::cout << "    </Supported>" << std::endl;
+  std::cout << "    <Supported>" << std::endl;
+  std::cout << "     mimeType = application/zip" << std::endl;
+  std::cout << "    </Supported>" << std::endl;
+}
+
+void printOutputImage(){
+  std::cout << "   <LiteralData>" << std::endl;
+  std::cout << "    dataType = string" << std::endl;
+  std::cout << "    <Default>" << std::endl;
+  std::cout << "     value = float" << std::endl;
+  std::cout << "     AllowedValues = uint8,uint16,int16n,int32,int32,float,double" << std::endl;
+  std::cout << "    </Default>" << std::endl;
+  std::cout << "   </LiteralData>" << std::endl;
+}
+
+void printOutputComplexImage(){
+  std::cout << "   <LiteralData>" << std::endl;
+  std::cout << "    dataType = string" << std::endl;
+  std::cout << "    <Default>" << std::endl;
+  std::cout << "     value = cfloat" << std::endl;
+  std::cout << "     AllowedValues = cfloat,cdouble" << std::endl;
+  std::cout << "    </Default>" << std::endl;
+  std::cout << "   </LiteralData>" << std::endl;
+}
+
+int main(int itkNotUsed(argc), char * itkNotUsed(argv)[]) 
+{ 
+  typedef otb::Image<unsigned short, 2> ImageType; 
+ 
+  ImageType::Pointer image = ImageType::New(); 
+ 
+  const char * ITK_AUTOLOAD_PATH = itksys::SystemTools::GetEnv("ITK_AUTOLOAD_PATH");
+  std::cerr << "ERROR: Module search path: " << (ITK_AUTOLOAD_PATH ? ITK_AUTOLOAD_PATH : "none (check ITK_AUTOLOAD_PATH)") << std::endl;
+
+  std::vector<std::string> list = ApplicationRegistry::GetAvailableApplications();
+  if (list.size() == 0)
+    std::cerr << "ERROR: Available modules : none." << std::endl;
+  else{
+    std::cerr << "ERROR: Available modules :" << std::endl;
+    for (std::vector<std::string>::const_iterator it = list.begin(); it != list.end(); ++it){
+      std::string filename= *it + ".zcfg";
+      std::ofstream out(filename.c_str(),std::ofstream::out);
+      std::streambuf *coutbuf = std::cout.rdbuf();
+      std::cout.rdbuf(out.rdbuf());
+
+      std::cerr << *it << std::endl;
+      std::cout << "[" << *it << "]" << std::endl;
+      Application::Pointer m_Application=ApplicationRegistry::CreateApplication(*it);
+      std::string s0 = m_Application->GetDescription();
+      s0=ReplaceAll(ReplaceAll(s0,std::string("\n"),std::string("")),std::string("\t"),std::string(""));
+      std::cout << " Title = " << s0 << std::endl;
+      s0 = m_Application->GetDocLongDescription();
+      s0=ReplaceAll(ReplaceAll(s0,std::string("\n"),std::string("")),std::string("\t"),std::string(""));
+      std::cout << " Abstract = " << s0 << std::endl;
+      const std::vector<std::string> appKeyList = m_Application->GetParametersKeys(true);
+      std::cout << " storeSupported = true"<< std::endl;
+      std::cout << " statusSupported = true" << std::endl;
+      std::cout << " serviceProvider = " << *it << std::endl;
+      std::cout << " serviceType = OTB" << std::endl;
+      std::cout << " <DataInputs>" << std::endl;
+      for (unsigned int i = 0; i < appKeyList.size(); i++){
+	const std::string paramKey(appKeyList[i]);
+	Parameter::Pointer param = m_Application->GetParameterByKey(paramKey);
+	ParameterType type = m_Application->GetParameterType(paramKey);
+	Role role = m_Application->GetParameterRole(paramKey);
+      
+	if(paramKey!="inxml" && paramKey!="outxml" && role==0 && type!=17 
+	   && type!=ParameterType_OutputFilename && type!=ParameterType_OutputVectorData){
+	  std::vector<std::string> values;
+	  std::string s = m_Application->GetParameterDescription(paramKey);
+	  s=ReplaceAll(ReplaceAll(ReplaceAll(s,std::string("\n"),std::string("")),std::string("\t"),std::string("")),std::string("<"),std::string("<"));
+	  std::cout << "  [" << paramKey << "]" << std::endl;
+	  if(s.length()>0){
+	    std::cout << "   Title = " << s << std::endl;
+	    std::cout << "   Abstract = " << s << std::endl;
+	  }else{
+	    std::cout << "   Title = " << paramKey << std::endl;
+	    std::cout << "   Abstract = " << paramKey << std::endl;
+	  }
+	  std::cout << "   minOccurs = " << m_Application->IsMandatory(paramKey) << std::endl;
+	  /* Bounded and unbounded parameters */
+	  if(type == ParameterType_StringList || type == ParameterType_InputImageList
+	     || type == ParameterType_InputVectorDataList || type == ParameterType_InputFilenameList
+	     || type == ParameterType_ListView)
+	    std::cout << "   maxOccurs = 1024" << std::endl;
+	  else
+	    std::cout << "   maxOccurs = 1" << std::endl;
+	  std::replace( s.begin(), s.end(), '\n', ' ');
+	  
+	  if(type == ParameterType_StringList || type == ParameterType_String || type == ParameterType_Float
+	     || type == ParameterType_Int || type == ParameterType_Choice || type == ParameterType_ListView
+	     || type == ParameterType_RAM || type == ParameterType_Empty || type == ParameterType_Directory){
+	    std::cout << "   <LiteralData>" << std::endl;
+	    std::string lt;
+	    if(type == ParameterType_Int || type == ParameterType_RAM)
+	      lt="integer";
+	    if(type == ParameterType_Float)
+	      lt="float";
+	    if(type == ParameterType_String || type == ParameterType_StringList
+	       || type == ParameterType_Choice || type == ParameterType_Directory
+	       || type == ParameterType_ListView)
+	      lt="string";
+	    if(type == ParameterType_Empty)
+	      lt="boolean";
+	    std::cout << "    dataType = " << lt << std::endl;
+	    if(type == ParameterType_Choice || type == ParameterType_ListView){
+	      const std::vector<std::string> nList = m_Application->GetChoiceNames(paramKey);
+	      const std::vector<std::string> keysList = m_Application->GetChoiceKeys(paramKey);
+	      if(keysList.size()==0){
+		std::cout << "    <Default />" << std::endl;
+	      }
+	      for (unsigned int j = 0; j < keysList.size(); j++){
+		const std::string key(keysList[j]);
+		if(j==0){
+		  std::cout << "    <Default>" << std::endl;
+		  if(m_Application->HasValue(paramKey))
+		    std::cout << "    value = " << m_Application->GetParameterAsString(paramKey) << std::endl;
+		  else
+		    std::cout << "    value = " << key << std::endl;
+		}
+		else{
+		  if(j==1){
+		    std::cout << "    AllowedValues = "+keysList[0]+",";
+		  }
+		  std::cout << keysList[j];
+		  if(j+1>=keysList.size()){
+		    std::cout << std::endl;
+		    std::cout << "    </Default>" << std::endl;
+		  }
+		  else
+		    std::cout << ",";
+		}
+	      }
+	    }
+	    else{
+	      if(type!=17 && m_Application->HasValue(paramKey)){
+		std::cout << "    <Default>" << std::endl;
+		std::cout << "     value = " << m_Application->GetParameterAsString(paramKey) << std::endl;
+		std::cout << "    </Default>" << std::endl;
+	      }
+	      else
+		std::cout << "    <Default />" << std::endl;
+	    }
+	    std::cout << "   </LiteralData>" << std::endl;
+	  }
+	  else{
+	    if(type == ParameterType_OutputImage)
+	      printOutputImage();
+	    else{
+	      if(type == ParameterType_ComplexOutputImage){
+		printOutputComplexImage();
+	      }else{
+		std::cout << "   <ComplexData>" << std::endl;
+		if(type == ParameterType_InputImage || type == ParameterType_InputImageList || type == ParameterType_ComplexInputImage){
+		  printImages();
+		}
+		else
+		  if(type == ParameterType_InputVectorData || type == ParameterType_InputVectorDataList){
+		    printVector();
+		  }
+		  else
+		    if(type == ParameterType_InputFilename || type == ParameterType_OutputFilename){
+		      
+		      std::string geoid("geoid");
+		      if(paramKey.find(geoid)!= std::string::npos)
+			printGeoid();
+		      else{
+			std::string dtype("vector");
+			std::string descr(m_Application->GetParameterDescription(paramKey));
+			if(descr.find(dtype)!= std::string::npos)
+			  printVector();
+			else{
+			  std::string dtype1("ASCII");
+			  if(descr.find(dtype1)!= std::string::npos)
+			    printAscii();
+			  else{
+			    std::string dtype2("XML");
+			    std::string dtype3("xml");
+			    if(descr.find(dtype2)!= std::string::npos || descr.find(dtype3)!= std::string::npos)
+			      printXml();
+			    else
+			      printImages();
+			  }
+			}
+		      }
+		    }
+		std::cout << "   </ComplexData>" << std::endl;
+	      }
+	    }
+	  }
+
+
+	}
+      }
+      std::cout << " <DataInputs>" << std::endl;
+      std::cout << " <DataOutputs>" << std::endl;
+      int hasOutput=-1;
+      for (unsigned int i = 0; i < appKeyList.size(); i++){
+	const std::string paramKey(appKeyList[i]);
+	std::vector<std::string> values;
+	Parameter::Pointer param = m_Application->GetParameterByKey(paramKey);
+	ParameterType type = m_Application->GetParameterType(paramKey);
+	Role role = m_Application->GetParameterRole(paramKey);
+	
+	if(paramKey!="inxml" && paramKey!="outxml" &&
+	   ((type == ParameterType_OutputVectorData || type == ParameterType_OutputImage
+	     || type == ParameterType_OutputImage || type == ParameterType_ComplexOutputImage
+	     || type == ParameterType_OutputFilename) || role==1) && type != ParameterType_Group){
+	  hasOutput=1;
+	  std::vector<std::string> values;
+	  Parameter::Pointer param = m_Application->GetParameterByKey(paramKey);
+	  ParameterType type = m_Application->GetParameterType(paramKey);
+	  Role role = m_Application->GetParameterRole(paramKey);
+	  std::cout << "  [" << paramKey << "]" << std::endl;
+	  std::string s=m_Application->GetParameterDescription(paramKey);
+	  if(s.length()>0){
+	    std::cout << "   Title = " << s << std::endl;
+	    std::cout << "   Abstract = " << s << std::endl;
+	  }else{
+	    std::cout << "   Title = " << paramKey << std::endl;
+	    std::cout << "   Abstract = " << paramKey << std::endl;
+	  }
+
+	  if(type == ParameterType_OutputImage || type == ParameterType_ComplexOutputImage){
+	    std::cout << "   <ComplexData>" << std::endl;
+	    printImages();
+	    std::cout << "   </ComplexData>" << std::endl;
+	  }
+	  else
+	    if(type == ParameterType_OutputVectorData || type == ParameterType_OutputImage){
+	      std::cout << "   <ComplexData>" << std::endl;
+	      if(type == ParameterType_OutputImage)
+		printImages();
+	      else
+		printVector();
+	      std::cout << "   </ComplexData>" << std::endl;
+	    }
+	    else
+	      if(type == ParameterType_String || type == ParameterType_StringList
+		 || type == ParameterType_Float || type == ParameterType_Int){
+		std::cout << "   <LiteralData>" << std::endl;
+		std::string lt;
+		if(type == ParameterType_Int)
+		  lt="integer";
+		if(type == ParameterType_Float)
+		  lt="float";
+		if(type == ParameterType_String || type == ParameterType_StringList)
+		  lt="string";
+		std::cout << "    dataType = " << lt << std::endl;
+		std::cout << "    <Default />" << std::endl;
+		std::cout << "   </LiteralData>" << std::endl;
+	      }
+	      else
+		if(type == ParameterType_OutputFilename){
+		  std::cout << "   <ComplexData>" << std::endl;
+		  std::string descr(m_Application->GetParameterDescription(paramKey));
+		  std::string dtype("csv");
+		  std::string dtype1("CSV");
+		  if(descr.find(dtype)!= std::string::npos || descr.find(dtype1)!= std::string::npos)
+		    printCSV();
+		  else{
+		    std::string dtype2("text file");
+		    if(descr.find(dtype2)!= std::string::npos)
+		      printAscii();
+		    else{
+		      std::string dtype2("XML");
+		      std::string dtype3("xml");
+		      if(descr.find(dtype2)!= std::string::npos || descr.find(dtype3)!= std::string::npos)
+			printXml();
+		      else{
+			std::string dtype4("vector");
+			std::string dtype5("Vector");
+			if(descr.find(dtype4)!= std::string::npos || descr.find(dtype5)!= std::string::npos)
+			  printVector();
+		       	else{
+			  std::string dtype6("kmz");
+			  std::string dtype7("Kmz");
+			  if(descr.find(dtype6)!= std::string::npos || descr.find(dtype6)!= std::string::npos)
+			    printKmz();
+			  else
+			    printUnknown();
+			}
+		      }
+		    }
+		  }
+		  std::cout << "   </ComplexData>" << std::endl;
+		}
+	}
+      }
+      if(hasOutput<0)
+	printDefaultOutput();
+      std::cout << " </DataOutputs>" << std::endl;
+      std::cout.rdbuf(coutbuf);
+    }
+  }
+ 
+  return EXIT_SUCCESS; 
+}
+
diff --git a/thirds/saga2zcfg/Makefile b/thirds/saga2zcfg/Makefile
new file mode 100644
index 0000000..d05c8d1
--- /dev/null
+++ b/thirds/saga2zcfg/Makefile
@@ -0,0 +1,14 @@
+ZRPATH=../../zoo-project
+include ${ZRPATH}/zoo-kernel/ZOOMakefile.opts
+CFLAGS=${ZOO_CFLAGS} ${XML2CFLAGS} ${GDAL_CFLAGS} ${PYTHONCFLAGS} -DLINUX_FREE_ISSUE #-DDEBUG
+CC=gcc
+
+WXCXX=`wx-config --cxx`
+WXCFLAGS=`wx-config --cxxflags`
+WXLIBS=`wx-config --libs`
+
+saga2zcfg: saga2zcfg.c
+	${WXCXX} ${SAGA_CFLAGS} ${WXCFLAGS} ${CFLAGS} -fpic -o saga2zcfg ./saga2zcfg.c ${GDAL_LIBS} ${MACOS_LD_FLAGS}  ${WXLIBS} ${SAGA_LDFLAGS}
+
+clean:
+	rm -f saga2zcfg
diff --git a/thirds/saga2zcfg/saga2zcfg.c b/thirds/saga2zcfg/saga2zcfg.c
new file mode 100644
index 0000000..7e231c3
--- /dev/null
+++ b/thirds/saga2zcfg/saga2zcfg.c
@@ -0,0 +1,403 @@
+#include <locale.h>
+
+#include <wx/app.h>
+#include <wx/utils.h>
+
+#include <api_core.h>
+#include <module_library.h>
+
+int Callback(TSG_UI_Callback_ID ID, CSG_UI_Parameter &Param_1, CSG_UI_Parameter &Param_2){
+  return( 1 );
+}
+
+TSG_PFNC_UI_Callback Get_Callback(void){
+  return( &Callback );
+}
+
+void cleanAbstract(CSG_String abstract,char**res){
+  char* tmp=strdup(abstract.b_str());
+  CSG_String val=CSG_String("")+tmp;
+  if(val.Contains("\r")){
+    val.Replace("\r","<br/>");
+  }
+  if(val.Contains("\n")){
+    val.Replace("\n","<br/>");
+  }
+  if(val.Contains("<")){
+    val.Replace("<","<");
+  }
+  if(val.Contains(">")){
+    val.Replace(">",">");
+  }
+  free(tmp);
+  if(val.is_Empty())
+    *res=NULL;
+  else
+    *res=strdup(val.b_str());
+}
+
+void printBasicMetadata(FILE* stdout,CSG_Parameter* param,bool out=false,bool range=false,bool min=true,bool tin=false,char* tname=NULL,char* ttitle=NULL){
+  fprintf(stdout," [%s]\n",(CSG_String(param->Get_Identifier())+(range?(min?"_MIN":"_MAX"):(tin?CSG_String("_")+tname:""))).b_str());
+  fprintf(stdout,"  Title = %s\n",(CSG_String(param->Get_Name())+(range?(min?" (min value)":" (max value)"):(tin&&ttitle!=NULL?ttitle:""))).b_str());
+  if(CSG_String(param->Get_Description()).is_Empty())
+    fprintf(stdout,"  Abstract = %s\n",CSG_String(param->Get_Name()).b_str());
+  else{
+    char* tmp=strdup(CSG_String(param->Get_Description()).b_str());
+    CSG_String val=CSG_String("")+tmp;
+    if(val.Contains("\r")){
+      val.Replace("\r","<br/>");
+    }
+    if(val.Contains("\n")){
+      val.Replace("\n","<br/>");
+    }
+    if(val.Contains("<")){
+      val.Replace("<","<");
+    }
+    if(val.Contains(">")){
+      val.Replace(">",">");
+    }
+    free(tmp);
+    fprintf(stdout,"  Abstract = %s\n",val.b_str());
+  }
+  if(!out){
+    if(param->is_Option() || param->is_Optional()){
+      fprintf(stdout,"  minOccurs = 0\n");
+      if(param->is_Option())
+	fprintf(stdout,"  maxOccurs = 1\n");
+      else{
+	if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("_list")))
+	  fprintf(stdout,"  maxOccurs = 1024\n");
+	else
+	  fprintf(stdout,"  maxOccurs = 1\n");
+      }
+    }else{
+      if(param->is_Input())
+	fprintf(stdout,"  minOccurs = 1\n");
+      if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("_list")))
+	fprintf(stdout,"  maxOccurs = 1024\n");
+      else
+	fprintf(stdout,"  maxOccurs = 1\n");
+    }
+  }
+  if(range){
+    
+  }
+}
+
+void printGrids(FILE* stdout){
+  fprintf(stdout,"  <ComplexData>\n");
+  fprintf(stdout,"   <Default>\n");
+  fprintf(stdout,"    mimeType = image/tiff\n");
+  fprintf(stdout,"   </Default>\n");
+  fprintf(stdout,"   <Supported>\n");
+  fprintf(stdout,"    mimeType = application/x-ogc-envi\n");
+  fprintf(stdout,"   </Supported>\n");
+  fprintf(stdout,"   <Supported>\n");
+  fprintf(stdout,"    mimeType = application/x-ogc-aaigrid\n");
+  fprintf(stdout,"   </Supported>\n");
+  fprintf(stdout,"  </ComplexData>\n");
+}
+
+void printShapes(FILE* stdout){
+  fprintf(stdout,"  <ComplexData>\n");
+  fprintf(stdout,"   <Default>\n");
+  fprintf(stdout,"    mimeType = text/xml\n");
+  fprintf(stdout,"    encoding = utf-8\n");
+  fprintf(stdout,"   </Default>\n");
+  fprintf(stdout,"   <Supported>\n");
+  fprintf(stdout,"    mimeType = application/vnd.google-earth.kml+xml\n");
+  fprintf(stdout,"   </Supported>\n");
+  fprintf(stdout,"   <Supported>\n");
+  fprintf(stdout,"    mimeType = application/json\n");
+  fprintf(stdout,"   </Supported>\n");
+  fprintf(stdout,"  </ComplexData>\n");
+}
+
+void printTables(FILE* stdout){
+  fprintf(stdout,"  <ComplexData>\n");
+  fprintf(stdout,"   <Default>\n");
+  fprintf(stdout,"    mimeType = text/csv\n");
+  fprintf(stdout,"    encoding = utf-8\n");
+  fprintf(stdout,"   </Default>\n");
+  fprintf(stdout,"   <Supported>\n");
+  fprintf(stdout,"    mimeType = text/csv\n");
+  fprintf(stdout,"    encoding = base64\n");
+  fprintf(stdout,"   </Supported>\n");
+  fprintf(stdout,"  </ComplexData>\n");
+}
+
+void printPoints(FILE* stdout){
+  fprintf(stdout,"  <ComplexData>\n");
+  fprintf(stdout,"   <Default>\n");
+  fprintf(stdout,"    mimeType = application/x-ogc-lasf\n");
+  fprintf(stdout,"    extension = las\n");
+  fprintf(stdout,"   </Default>\n");
+  fprintf(stdout,"  </ComplexData>\n");
+}
+
+int main(int argc, char *argv[]) {
+  if( !wxInitialize() ){
+    fprintf(stderr,"initialisation failed");
+    return -1;
+  }
+  setlocale(LC_NUMERIC, "C");
+  static bool g_bShow_Messages = false;
+  SG_Set_UI_Callback(Get_Callback());
+  int n = SG_Get_Module_Library_Manager().Add_Directory(wxT(MODULE_LIBRARY_PATH),false);
+  if( SG_Get_Module_Library_Manager().Get_Count() <= 0 ){
+    fprintf(stderr,"could not load any tool library");
+    return -2;
+  }
+
+  for(int i=0;i<SG_Get_Module_Library_Manager().Get_Count();i++){
+    
+    CSG_Module_Library * library=SG_Get_Module_Library_Manager().Get_Library(i);
+    int lc=library->Get_Count();
+    if(!library->Get_Library_Name().Contains("io_")) {
+
+      for(int j=0;j<lc;j++){
+	CSG_Module * module=library->Get_Module(j);
+	if(module!=NULL && !module->needs_GUI() /*&& !module->is_Interactive()*/ ){
+
+	  mkdir(library->Get_Library_Name().b_str(),0755);
+
+	  FILE *stdout1=fopen((library->Get_Library_Name()+"/"+module->Get_ID()+".zcfg").b_str(),"w+");
+	  fprintf(stdout1,"[%d]\n",j);
+	  fprintf(stdout1," Title = %s\n",module->Get_Name().b_str());
+	  if(CSG_String(module->Get_Description()).is_Empty() ||
+	     module->Get_Description().Length()<module->Get_Name().Length() )
+	    fprintf(stdout1," Abstract = %s\n",module->Get_Name().b_str());
+	  else{
+	    char *val0;
+	    cleanAbstract(module->Get_Description(),&val0);
+	    if(val0==NULL)
+	      fprintf(stdout1," Abstract = %s\n",module->Get_Name().b_str());
+	    else{
+	      fprintf(stdout1," Abstract = %s\n",val0);
+	      free(val0);
+	    }
+	  }
+	  fprintf(stdout1," storeSupported = true\n");
+	  fprintf(stdout1," statusSupported = true\n");
+	  fprintf(stdout1," serviceType = SAGA\n");
+	  fprintf(stdout1," serviceProvider = %s\n",library->Get_Library_Name().b_str());
+	  CSG_Parameters * params=module->Get_Parameters();
+	  int pc=params->Get_Count();
+
+	  fprintf(stdout1," <DataInputs>\n");
+	  for(int k=0;k<pc;k++){
+	    CSG_Parameter * param=params->Get_Parameter(k);
+	    
+	    if(CSG_String(param->Get_Type_Identifier()).is_Same_As(CSG_String("parameters"),true)){
+	      int pc0=param->asParameters()->Get_Count();
+	      int l;
+	      fprintf(stderr,"%s\n",CSG_String(param->Get_Name()).b_str());
+	      for(l=0;l<pc0;l++){
+		CSG_Parameter * param0=param->asParameters()->Get_Parameter(l);
+		fprintf(stderr,"%s\n",CSG_String(param0->Get_Type_Identifier()).b_str());
+	      }
+	    }
+	    
+	    // Node should be used for defining Complex ComplexData
+	    if(CSG_String(param->Get_Type_Identifier()).is_Same_As(CSG_String("color"))){
+	      
+	    }
+	    else if(CSG_String(param->Get_Type_Identifier()).is_Same_As(CSG_String("range"),true)){
+
+	      param->Restore_Default();
+
+	      printBasicMetadata(stdout1,param,false,true,true);
+	      fprintf(stdout1,"  <LiteralData>\n");
+	      fprintf(stdout1,"   dataType = float\n");
+	      CSG_Parameter_Range *range=param->asRange();
+	      fprintf(stdout1,"   <Default>\n");
+	      fprintf(stdout1,"    value = %f\n",((CSG_Parameter_Range*)param->Get_Data())->Get_LoVal());
+	      fprintf(stdout1,"   </Default>\n");
+	      fprintf(stdout1,"  </LiteralData>\n");
+
+	      printBasicMetadata(stdout1,param,false,true,false);
+	      fprintf(stdout1,"  <LiteralData>\n");
+	      fprintf(stdout1,"   dataType = float\n");
+	      fprintf(stdout1,"   <Default>\n");
+	      fprintf(stdout1,"    value = %f\n",((CSG_Parameter_Range*)param->Get_Data())->Get_HiVal());
+	      fprintf(stdout1,"   </Default>\n");
+	      fprintf(stdout1,"  </LiteralData>\n");
+
+	    }
+	    else if(param!=NULL && !param->is_Output() 
+		    && 
+		    !CSG_String(param->Get_Type_Identifier()).is_Same_As(CSG_String("parameters"),true)
+		    && 
+		    !CSG_String(param->Get_Type_Identifier()).is_Same_As(CSG_String("grid_system"),true)
+		    && 
+		    !CSG_String(param->Get_Type_Identifier()).is_Same_As(CSG_String("node"),true)){
+	    
+	      printBasicMetadata(stdout1,param);
+
+	      if(CSG_String(param->Get_Type_Identifier()).is_Same_As(CSG_String("file"),true)){
+		if(CSG_String(param->Get_Description()).Contains(CSG_String("HTML"))){
+		  fprintf(stdout1,"  <ComplexData>\n");	       
+		  fprintf(stdout1,"   <Default>\n");
+		  fprintf(stdout1,"    mimeType = text/html\n");
+		  fprintf(stdout1,"    encoding = utf-8\n");
+		  fprintf(stdout1,"   </Default>\n");
+		  fprintf(stdout1,"  <ComplexData>\n");
+		}
+		else{
+		  fprintf(stdout1,"  <ComplexData>\n");	       
+		  fprintf(stdout1,"   <Default>\n");
+		  if(CSG_String(param->Get_Description()).Contains(CSG_String("HTML"))){
+		    fprintf(stdout1,"    mimeType = text/html\n");
+		  }else
+		    if(CSG_String(param->Get_Description()).Contains(CSG_String("SVG"))){
+		      fprintf(stdout1,"    mimeType = image/svg+xml\n");
+		    }else
+		      fprintf(stdout1,"    mimeType = text/plain\n");
+		  if(CSG_String(param->Get_Description()).Contains(CSG_String("ASCII"))){
+		    fprintf(stdout1,"    encoding = ascii\n");
+		  }else
+		    fprintf(stdout1,"    encoding = utf-8\n");
+		  fprintf(stdout1,"   </Default>\n");
+		  fprintf(stdout1,"  </ComplexData>\n");
+		}
+	      }
+	      if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("shapes")) ||
+		 CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("tin")) ){
+		printShapes(stdout1);
+	      }
+	      if(CSG_String(param->Get_Type_Identifier()).Contains("points")){
+		printPoints(stdout1);
+	      }
+	      if(CSG_String(param->Get_Type_Identifier()).Contains("grid") ||
+		 CSG_String(param->Get_Type_Identifier()).Contains("data_")){
+		printGrids(stdout1);
+	      }
+	      if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("table"))){
+		printTables(stdout1);
+	      }
+	      if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("text"))){
+		fprintf(stdout1,"  <LiteralData>\n");
+		fprintf(stdout1,"   dataType = string\n");
+		fprintf(stdout1,"   <Default>\n");
+		if( !param->Get_Data()->Get_Default().is_Empty() ){
+		  fprintf(stdout1,"    value = %s\n",param->Get_Data()->Get_Default().b_str());
+		}
+		fprintf(stdout1,"   </Default>\n");
+		fprintf(stdout1,"  </LiteralData>\n");
+	      }
+	      if(CSG_String(param->Get_Type_Identifier()).is_Same_As(CSG_String("double"),true)
+		 || 
+		 CSG_String(param->Get_Type_Identifier()).is_Same_As(CSG_String("degree"),true)
+		 || 
+		 CSG_String(param->Get_Type_Identifier()).is_Same_As(CSG_String("integer"),true)){
+		fprintf(stdout1,"  <LiteralData>\n");
+		if(CSG_String(param->Get_Type_Identifier()).is_Same_As(CSG_String("double"),true) || 
+		 CSG_String(param->Get_Type_Identifier()).is_Same_As(CSG_String("degree"),true))
+		  fprintf(stdout1,"   dataType = float\n");
+		else
+		  fprintf(stdout1,"   dataType = integer\n");
+
+		fprintf(stdout1,"   <Default>\n");
+		if( !param->Get_Data()->Get_Default().is_Empty() ){
+		  fprintf(stdout1,"    value = %s\n",param->Get_Data()->Get_Default().b_str());
+		}
+		if(param->asValue()->has_Minimum() && param->asValue()->has_Maximum()){
+		  fprintf(stdout1,"    rangeMin = %f\n",param->asValue()->Get_Minimum());
+		  fprintf(stdout1,"    rangeMax = %f\n",param->asValue()->Get_Maximum());
+		  fprintf(stdout1,"    rangeClosure = c\n");
+		}
+		fprintf(stdout1,"   </Default>\n");
+		fprintf(stdout1,"  </LiteralData>\n");
+	      }
+	      if(CSG_String(param->Get_Type_Identifier()).is_Same_As(CSG_String("boolean"),true)){
+		fprintf(stdout1,"  <LiteralData>\n");
+		fprintf(stdout1,"   dataType = bool\n");
+		fprintf(stdout1,"   <Default>\n");
+		if( !param->Get_Data()->Get_Default().is_Empty() ){
+		  fprintf(stdout1,"    value = %s\n",(param->Get_Data()->Get_Default().Contains("0")?"false":"true"));
+		}
+		fprintf(stdout1,"   </Default>\n");
+		fprintf(stdout1,"  </LiteralData>\n");	
+	      }
+	      if(CSG_String(param->Get_Type_Identifier()).is_Same_As(CSG_String("choice"),true)){
+		CSG_Parameter_Choice* choice=param->asChoice();
+		if(choice!=NULL){
+		  fprintf(stdout1,"  <LiteralData>\n");
+		  fprintf(stdout1,"   dataType = string\n");
+		  fprintf(stdout1,"   AllowedValues = ");
+		  int clen=choice->Get_Count();
+		  if(clen>0){
+		    for(int l=0;l<clen;l++){
+		      //fprintf(stdout1,"%d",l);
+		      fprintf(stdout1,"%s",(CSG_String(choice->Get_Item(l))).b_str());
+		      if(l+1<clen)
+			fprintf(stdout1,",");
+		    }
+		    fprintf(stdout1,"\n");
+		  }
+		  fprintf(stdout1,"   <Default>\n");
+		  if( !param->Get_Data()->Get_Default().is_Empty() ){
+		    fprintf(stdout1,"    value = %s\n",CSG_String(choice->Get_Item(atoi(param->Get_Data()->Get_Default()))).b_str());
+		  }
+		  fprintf(stdout1,"   </Default>\n");
+		  fprintf(stdout1,"  </LiteralData>\n");
+		}
+	      }
+	    }
+	  }
+	  fprintf(stdout1," </DataInputs>\n");
+	  fprintf(stdout1," <DataOutputs>\n");
+
+	  bool hasOutput=false;
+
+	  for(int k=0;k<pc;k++){
+	    CSG_Parameter * param=params->Get_Parameter(k);
+	    if(param!=NULL && param->is_Output()){
+	      hasOutput=true;
+	      if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("tin"))){
+		char* tinOut[5]={
+		  (char*)"POINTS",
+		  (char*)"CENTER",
+		  (char*)"EDGES",
+		  (char*)"TRIANGLES",
+		  (char*)"POLYGONS"
+		};
+		for(int l=0;l<5;l++){
+		  char *ttitle=(char*)malloc((strlen(tinOut[l])+8)*sizeof(char));
+		  sprintf(ttitle,"%s Shapes",tinOut[l]);
+		  printBasicMetadata(stdout1,param,true,false,true,true,tinOut[l],ttitle);
+		  printShapes(stdout1);
+		}
+	      }
+	      else {
+		printBasicMetadata(stdout1,param,true);
+
+		if(CSG_String(param->Get_Type_Identifier()).Contains("points")){
+		  printPoints(stdout1);
+		}
+		if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("shapes"))){
+		  printShapes(stdout1);
+		}
+		if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("grid")) ||
+		   CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("data_object"))){
+		  printGrids(stdout1);
+		}
+		if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("table"))){
+		  printTables(stdout1);
+		}
+
+	      }
+	    }
+	  }
+	  fprintf(stdout1,"</DataOutputs>\n");
+	  fclose(stdout1);
+	  if(!hasOutput)
+	    unlink((library->Get_Library_Name()+"/"+module->Get_ID()+".zcfg").b_str());
+	}
+      }
+    }
+  }
+  wxUninitialize();
+
+  return 0;
+}
diff --git a/zoo-project/COMMITTERS b/zoo-project/COMMITTERS
new file mode 100644
index 0000000..9a103ed
--- /dev/null
+++ b/zoo-project/COMMITTERS
@@ -0,0 +1,30 @@
+===========================================================
+List of ZOO-Project committers
+===========================================================
+
+Folks who have agreed to ZOO-Project Commiter Guildlines terms:
+
+SVN Login(s)  Name/Contact
+============  ============
+david         David SAGGIORATO
+	      dsaggiorato at free.fr
+djay          Gérald FENOY *SVN Admin*
+	      gerald.fenoy at geolabs.fr
+jmckenna      Jeff MCKENNA
+	      jmckenna at gatewaygeomatics.com
+kalxas        Angelos TZOTSOS
+	      gcpp.kalxas at gmail.com
+lucadelu      Luca DELUCCHI
+	      lucadeluge at gmail.com
+nbozon	      Nicolas BOZON
+	      nicolas.bozon at gmail.com
+neteler       Markus NETELER
+	      neteler at osgeo.org
+nmarco        Marco NEGRETTI
+	      marco.negretti at polimi.it
+knut	      Knut LANDMARK
+	      Knut.Landmark at ffi.no
+reluc         René-Luc D'HONT
+	      rldhont at gmail.com
+tclarke       Trevor CLARKE
+	      tclarke at ball.com
diff --git a/zoo-project/HISTORY.txt b/zoo-project/HISTORY.txt
new file mode 100644
index 0000000..b6fe369
--- /dev/null
+++ b/zoo-project/HISTORY.txt
@@ -0,0 +1,131 @@
+Version 1.5.0-dev
+  * Complete rewrite of the documentation to use modern style
+  * Fix asynchronous POST request on WIN32 platforms
+  * Add utils/registry service
+  * Initial support for WPS 2.0.0 including the Dismiss extension
+  * Fix concurrency access to status informations
+  * Use simple file rather than shared memory for storing status informations
+  * Add support for db backend to store status informations
+  * Add the lib_zoo_service shared library to be linked against C services
+  * Add ZOO-API for the PHP language (with documentation)
+  * Add doxygen comments in source code
+  * Add support for multiple Exception nodes
+  * Add a length key when creating MapArray
+  * Add OTB support for applications as a service
+  * Add the otb2zcfg utility to produce zcfg for otb applications
+  * Add OTB Application Observer to have progress status updates
+  * Fix maxOccurs handling
+  * Fix gesture of downloaded inputs when multiple values are given
+  * Add detection of generated_file key in outputs to read the file
+  generated by a service
+  * Add a minimal parsing API 
+  * Run validateRequest (download, default settings and decoding)
+  after fork if any
+  * Add SAGA-GIS support for modules as a service
+  * Add saga2zcfg utility to generate zcfg for SAGA-GIS modules
+  * Add SAGA-GIS Observer to have ongoing status updates
+
+Version 1.4.0
+  * Small fix for mimeType of results for CGAL services
+
+Version 1.4.0-rc1
+  * Binary support for PHP language
+  * ZOO-API for the Java language
+  * ZOO-Client Javascript API
+  * FastCGI fixes
+  * JavaScript ZOO-API enhancements (COOKIE use and Output in
+  generated XML)
+  * Add debian files
+  * Inputs passed by reference downloaded in parallel
+  * Conform behavior for DescribeProcess when the Identifier was not
+  found
+  * Add support of maximumMegabytes keywords for ComplexData Inputs
+  * Add the optional YAML ZCFG support #4 and the zcfg2yaml converter
+  * Return error messages that enable the service provider to quickly
+  identify the root cause of errors due to configuration file syntax
+  (ticket #90)
+  * Fix logic in addMapToMap (ticket #91)
+  * Enable AllowedValue and multiple Range definitions using default
+  and supported blocks
+  * Add the lastest revision number in version.h (available in Python
+  ZOO-API)
+  * Add the optional Ruby Language Support to the ZOO-Kernel with an
+  API similar to the Python ZOO-API
+  * Small rewrite of Python support
+  * Inputs can be requested over https protocol (ticket #86)
+  * Add capability to define both percentage of execution and a
+  message (ticket #87). 
+  * Add usid in lenv section used to generate an unique identifier
+  based on time and the process identifier.
+  * Add gdal_contour service
+  * Add dynamic definition of serverAddress from the main section
+
+Version 1.3.0-rc2
+  * Fix POST Request issue (ticket #34)
+  * Fix COOKIE gesture (ticket #79)
+  * Remove verbose messages when using MapServer W*S (ticket #80)
+  * Add COMMITTERS  and LICENSE files
+
+Version 1.3.0-rc1
+
+  * Updating ZOO.Class object with the OpenLayers.Class Updating
+    ZOO.Class with the (ticket #64)
+  * Correct the content of proj4js (ticket #63)
+  * Enhance the COOKIE gesture (ticket #68)
+  * Support for dataInputs URLEncoded and xlink:href (ticket #62)
+  * Use the same object structure for JavaScript arguments than for
+    Python
+  * Add the Normalized Difference Vegetation Index service
+  * Add importScripts function to JavaScript support (ticket #66)
+  * Add multiple inputs values for the same identifier (ticket #72)
+  * Add Python ZOO-API to access ZOO-Kernel internel functions
+  * Add a [headers] section in main.cfg file to add specifics to
+    header returned
+  * Add support for multiple outputs for both GET and POST requests
+  * Add Content-Length to the headers if the result is sized
+  * Add Content-Disposition to the headers if the result contains a
+    filename
+  * Add support for sending headers through JS ZOO-api
+  * Add support for multi-valued inputs in JS ZOO-api
+  * Fixing issue about invalid status document #73
+  * Add Python-3.3.0 support
+  * Update documentation
+  * Add MapServer W*S Support documentation #34
+
+Version 1.2.0-rc3
+
+  * add basic SOAP Envelope support (ticket #49)
+  * support request when Content-Length header is not set by the
+  * client (ticket #57)
+  * fix issue when POST request is empty (ticket #45)
+  * add minimalist cache system (ticket #51)
+  * fix Python support (ticket #29)
+
+Verseion 1.2.0-rc2
+
+  * fix for process to run in background
+  * add support for ALL identifier for !DescribeProcess
+  * add a small test suite in the testing directory to test ogr base-vect-ops
+  * big fix for storage of Session maps on disk
+  * support for {{{<Default />}}} node in ZCFG files
+  * fastcgi version now support both !GetCapabilities and !DescribeProcess requests
+
+Version 1.2.0-rc1
+
+  * add WIN32 support
+  * add GRASS support through wps-grass-bridge
+  * add languages support using libintl 
+  * binary support for inputs and outputs for both JAVA and Python
+  * automatic loading of ZOO-API and proj4js files (if present in the ZOO-Kernel directory) when loading JS Service Provider 
+  * numerous memory leaks removed
+  * add PERL support
+  * enhance speed for JAVA support 
+  * enhance POST request support
+  * add !BoundingBoxData support
+  * Python support is now optional as other languages
+  * add lenv section before running the service to store informations runtime specific 
+  * add COOKIE support and {{{senv}}} section to store informations session specific
+  * add {{{USE_GDB}}} compilation flag to remove signal handling for debuging purpose
+  * enhance base64 support when included in and XML POST request
+  * return !ExceptionReport when no protocol was specified for xlink:href value
+
diff --git a/zoo-project/LICENSE b/zoo-project/LICENSE
new file mode 100644
index 0000000..4b0710f
--- /dev/null
+++ b/zoo-project/LICENSE
@@ -0,0 +1,166 @@
+ZOO-Project Licensing
+---------------------
+
+This file attempts to include all licenses that apply within the ZOO-Project
+source tree, in particular any that are supposed to be exposed to the end user
+for credit requirements for instance.
+
+ZOO-Kernel License
+------------------
+
+Copyright (c) 2009-2015 GeoLabs SARL
+Copyright 2010-2011 Fondazione Edmund Mach. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy 
+of this software and associated documentation files (the “Software”), to deal
+in the Software without restriction, including without limitation the rights 
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
+copies of the Software, and to permit persons to whom the Software is 
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies of this Software or works derived from this Software.
+
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+ZOO-Kernel OTB Support
+----------------------
+
+Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
+See OTBCopyright.txt for details.
+
+Some parts of this code are derived from ITK. See ITKCopyright.txt
+for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even
+ the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ PURPOSE.  See the above copyright notices for more information.
+
+See Ref: http://hg.orfeo-toolbox.org/OTB/ Copyright
+
+ZOO-API License
+---------------
+
+Copyright 2011-2013 GeoLabs SARL. All rights reserved.
+Copyright 2010 3liz SARL. All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+Copyright (c) 2006-2011 by OpenLayers Contributors (see 
+https://github.com/openlayers/openlayers/blob/master/authors.txt for full 
+list of contributors). Published under the Clear BSD license.
+See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+full text of the license.
+
+qrencode ZOO-Services License
+-----------------------------
+
+Copyright (C) 2006-2012 Kentaro Fukuchi <kentaro at fukuchi.org>
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+Other ZOO-Services License
+--------------------------
+
+Copyright (c) 2009-2013, GeoLabs SARL
+Copyright (c) 2006, 2009 Matthew Perry 
+Copyright (c) 2009 Even Rouault
+Copyright (c) 2007, Andrey Kiselev <dron at ak4719.spb.edu>
+Copyright (c) 1998, 1999, 2002, Frank Warmerdam
+Copyright (c) 2002, i3 - information integration and imaging Fort Collin, CO
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+CGIC License
+------------
+
+CGIC, copyright 2009 GeoLabs SARL.
+CGIC, copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+2004 by Thomas Boutell and Boutell.Com, Inc.. Permission is granted to 
+use CGIC in any application, commercial or noncommercial, at no cost. 
+HOWEVER, this copyright paragraph must appear on a "credits" page 
+accessible in the public online and offline documentation of the program. 
+Modified versions of the CGIC library should not be distributed without 
+the attachment of a clear statement regarding the author of the 
+modifications, and this notice may in no case be removed. 
+Modifications may also be submitted to the author for inclusion 
+in the main CGIC distribution.                                 
+
+IF YOU WOULD PREFER NOT TO ATTACH THE ABOVE NOTICE to
+the public documentation of your application, consult the
+information which follows regarding the availability
+of a nonexclusive commercial license for CGIC.
+
+dirent-win32 License
+--------------------
+
+Copyright (C) 2006 Toni Ronkko
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+``Software''), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL TONI RONKKO BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/zoo-project/zoo-api/java/Makefile b/zoo-project/zoo-api/java/Makefile
new file mode 100644
index 0000000..3b8425f
--- /dev/null
+++ b/zoo-project/zoo-api/java/Makefile
@@ -0,0 +1,35 @@
+include ../../zoo-kernel/ZOOMakefile.opts
+
+OS:=$(shell uname -s)
+ext=so
+ifeq ($(OS),Darwin)
+	ext=dylib
+endif
+
+JAVA_FILES=../../zoo-kernel/${JAVA_FILE}
+
+ifeq ($(JS_ENABLED),-DUSE_JS)
+	JS_FILES=../../zoo-kernel/${JS_FILE},
+endif
+ifeq ($(MS_FILE),service_internal_ms.o)
+	MS_FILES=../../zoo-kernel/${MS_FILE},
+endif
+
+
+
+all: libZOO.${ext}
+
+ZOO.class: ZOO.java
+	javac ZOO.java
+
+ZOO.h: ZOO.java ZOO.class
+	javah ZOO
+
+zoo-api.o: zoo-api.c ZOO.h
+	gcc -fPIC -c zoo-api.c ${JAVACFLAGS} ${XML2CFLAGS} -I../../zoo-kernel/ -I../../../thirds/cgic206/
+
+libZOO.${ext}: zoo-api.o
+	gcc zoo-api.o -shared -o libZOO.${ext} -Wl,../../zoo-kernel/service_internal.o,${JAVA_FILES},${MS_FILES}${JS_FILES}../../zoo-kernel/ulinet.o ${GDAL_LIBS} ${XML2LDFLAGS} ${PYTHONLDFLAGS} ${PERLLDFLAGS}  ${PHPLDFLAGS} ${JAVALDFLAGS} ${JSLDFLAGS} -lcrypto ${MS_LDFLAGS} ${MACOS_LD_FLAGS} -lcurl -lfcgi ${MACOS_LD_NET_FLAGS}
+
+clean:
+	rm -f *${ext} *o *.h *class
diff --git a/zoo-project/zoo-api/java/ZOO.java b/zoo-project/zoo-api/java/ZOO.java
new file mode 100644
index 0000000..83568c7
--- /dev/null
+++ b/zoo-project/zoo-api/java/ZOO.java
@@ -0,0 +1,10 @@
+import java.lang.*;
+import java.util.*;
+
+public class ZOO {
+    static { System.loadLibrary("ZOO"); }
+    public static Integer SERVICE_SUCCEEDED=3;
+    public static Integer SERVICE_FAILED=4;
+    public static native String _(String a);
+    public static native Integer updateStatus(HashMap conf,String pourcent,String message);
+}
diff --git a/zoo-project/zoo-api/java/zoo-api.c b/zoo-project/zoo-api/java/zoo-api.c
new file mode 100644
index 0000000..9a879ba
--- /dev/null
+++ b/zoo-project/zoo-api/java/zoo-api.c
@@ -0,0 +1,31 @@
+#include "ZOO.h"
+#include "service.h"
+#include "service_internal.h"
+#include "service_internal_java.h"
+
+JNIEXPORT jstring JNICALL Java_ZOO__1
+  (JNIEnv *env, jclass class, jstring msg){
+  const char *message = (*env)->GetStringUTFChars(env,msg, 0);
+  return (*env)->NewStringUTF(env, _(message));
+
+}
+
+JNIEXPORT jobject JNICALL Java_ZOO_updateStatus
+  (JNIEnv *env, jclass class, jobject conf, jstring pourc, jstring msg){
+
+  jclass scHashMapClass,scHashMap_class;
+#ifdef JAVA7
+  scHashMapClass = (*env).FindClass("java/util/HashMap");
+#else
+  scHashMapClass = (*env)->FindClass(env, "java/util/HashMap");
+#endif
+  const char *pourcent = (*env)->GetStringUTFChars(env,pourc, 0);
+  const char *message = (*env)->GetStringUTFChars(env,msg, 0);
+  maps* m = mapsFromHashMap(env,conf,scHashMapClass);
+  setMapInMaps(m,"lenv","status",pourcent);
+  setMapInMaps(m,"lenv","message",message);
+  _updateStatus(m);
+  freeMaps(&m);
+  free(m);
+  return (jint)0;
+}
diff --git a/zoo-project/zoo-api/js/ZOO-api.js b/zoo-project/zoo-api/js/ZOO-api.js
new file mode 100644
index 0000000..3e6f3ee
--- /dev/null
+++ b/zoo-project/zoo-api/js/ZOO-api.js
@@ -0,0 +1,6322 @@
+/**
+ * Author : René-Luc D'Hont
+ *
+ * Copyright 2010 3liz SARL. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/* Copyright (c) 2006-2011 by OpenLayers Contributors (see 
+ * https://github.com/openlayers/openlayers/blob/master/authors.txt for full 
+ * list of contributors). Published under the Clear BSD license.
+ * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
+ * full text of the license. 
+ */
+
+/**
+ * Class: ZOO
+ */
+ZOO = {
+  /**
+   * Constant: SERVICE_ACCEPTED
+   * {Integer} used for
+   */
+  SERVICE_ACCEPTED: 0,
+  /**
+   * Constant: SERVICE_STARTED
+   * {Integer} used for
+   */
+  SERVICE_STARTED: 1,
+  /**
+   * Constant: SERVICE_PAUSED
+   * {Integer} used for
+   */
+  SERVICE_PAUSED: 2,
+  /**
+   * Constant: SERVICE_SUCCEEDED
+   * {Integer} used for
+   */
+  SERVICE_SUCCEEDED: 3,
+  /**
+   * Constant: SERVICE_FAILED
+   * {Integer} used for
+   */
+  SERVICE_FAILED: 4,
+  /** 
+   * Function: removeItem
+   * Remove an object from an array. Iterates through the array
+   *     to find the item, then removes it.
+   *
+   * Parameters:
+   * array - {Array}
+   * item - {Object}
+   * 
+   * Return
+   * {Array} A reference to the array
+   */
+  removeItem: function(array, item) {
+    for(var i = array.length - 1; i >= 0; i--) {
+        if(array[i] == item) {
+            array.splice(i,1);
+        }
+    }
+    return array;
+  },
+  /** 
+   * Function: indexOf
+   * 
+   * Parameters:
+   * array - {Array}
+   * obj - {Object}
+   * 
+   * Returns:
+   * {Integer} The index at, which the first object was found in the array.
+   *           If not found, returns -1.
+   */
+  indexOf: function(array, obj) {
+    for(var i=0, len=array.length; i<len; i++) {
+      if (array[i] == obj)
+        return i;
+    }
+    return -1;   
+  },
+  /**
+   * Function: extend
+   * Copy all properties of a source object to a destination object. Modifies
+   *     the passed in destination object.  Any properties on the source object
+   *     that are set to undefined will not be (re)set on the destination object.
+   *
+   * Parameters:
+   * destination - {Object} The object that will be modified
+   * source - {Object} The object with properties to be set on the destination
+   *
+   * Returns:
+   * {Object} The destination object.
+   */
+  extend: function(destination, source) {
+    destination = destination || {};
+    if(source) {
+      for(var property in source) {
+        var value = source[property];
+        if(value !== undefined)
+          destination[property] = value;
+      }
+    }
+    return destination;
+  },
+  /**
+   * Function: rad
+   * 
+   * Parameters:
+   * x - {Float}
+   * 
+   * Returns:
+   * {Float}
+   */
+  rad: function(x) {return x*Math.PI/180;},
+  /**
+   * Function: distVincenty
+   * Given two objects representing points with geographic coordinates, this
+   *     calculates the distance between those points on the surface of an
+   *     ellipsoid.
+   * 
+   * Parameters:
+   * p1 - {<ZOO.Geometry.Point>} (or any object with both .x, .y properties)
+   * p2 - {<ZOO.Geometry.Point>} (or any object with both .x, .y properties)
+   * 
+   * Returns:
+   * {Float} The distance (in km) between the two input points as measured on an
+   *     ellipsoid.  Note that the input point objects must be in geographic
+   *     coordinates (decimal degrees) and the return distance is in kilometers.
+   */
+  distVincenty: function(p1, p2) {
+    var a = 6378137, b = 6356752.3142,  f = 1/298.257223563;
+    var L = ZOO.rad(p2.x - p1.y);
+    var U1 = Math.atan((1-f) * Math.tan(ZOO.rad(p1.y)));
+    var U2 = Math.atan((1-f) * Math.tan(ZOO.rad(p2.y)));
+    var sinU1 = Math.sin(U1), cosU1 = Math.cos(U1);
+    var sinU2 = Math.sin(U2), cosU2 = Math.cos(U2);
+    var lambda = L, lambdaP = 2*Math.PI;
+    var iterLimit = 20;
+    while (Math.abs(lambda-lambdaP) > 1e-12 && --iterLimit>0) {
+        var sinLambda = Math.sin(lambda), cosLambda = Math.cos(lambda);
+        var sinSigma = Math.sqrt((cosU2*sinLambda) * (cosU2*sinLambda) +
+        (cosU1*sinU2-sinU1*cosU2*cosLambda) * (cosU1*sinU2-sinU1*cosU2*cosLambda));
+        if (sinSigma==0) {
+            return 0;  // co-incident points
+        }
+        var cosSigma = sinU1*sinU2 + cosU1*cosU2*cosLambda;
+        var sigma = Math.atan2(sinSigma, cosSigma);
+        var alpha = Math.asin(cosU1 * cosU2 * sinLambda / sinSigma);
+        var cosSqAlpha = Math.cos(alpha) * Math.cos(alpha);
+        var cos2SigmaM = cosSigma - 2*sinU1*sinU2/cosSqAlpha;
+        var C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));
+        lambdaP = lambda;
+        lambda = L + (1-C) * f * Math.sin(alpha) *
+        (sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));
+    }
+    if (iterLimit==0) {
+        return NaN;  // formula failed to converge
+    }
+    var uSq = cosSqAlpha * (a*a - b*b) / (b*b);
+    var A = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));
+    var B = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq)));
+    var deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-
+        B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));
+    var s = b*A*(sigma-deltaSigma);
+    var d = s.toFixed(3)/1000; // round to 1mm precision
+    return d;
+  },
+  /**
+   * Function: Class
+   * Method used to create ZOO classes. Includes support for
+   *     multiple inheritance.
+   */
+  Class: function() {
+    var Class = function() {
+      this.initialize.apply(this, arguments);
+    };
+    var extended = {};
+    var parent;
+    for(var i=0; i<arguments.length; ++i) {
+      if(typeof arguments[i] == "function") {
+        // get the prototype of the superclass
+        parent = arguments[i].prototype;
+      } else {
+        // in this case we're extending with the prototype
+        parent = arguments[i];
+      }
+      ZOO.extend(extended, parent);
+    }
+    Class.prototype = extended;
+
+    return Class;
+  },
+  /**
+   * Function: UpdateStatus
+   * Method used to update the status of the process
+   *
+   * Parameters:
+   * env - {Object} The environment object
+   * value - {Float} the status value between 0 to 100
+   */
+  UpdateStatus: function(env,value) {
+    return ZOOUpdateStatus(env,value);
+  }
+};
+
+/**
+ * Class: ZOO.String
+ * Contains convenience methods for string manipulation
+ */
+ZOO.String = {
+  /**
+   * Function: startsWith
+   * Test whether a string starts with another string. 
+   * 
+   * Parameters:
+   * str - {String} The string to test.
+   * sub - {Sring} The substring to look for.
+   *  
+   * Returns:
+   * {Boolean} The first string starts with the second.
+   */
+  startsWith: function(str, sub) {
+    return (str.indexOf(sub) == 0);
+  },
+  /**
+   * Function: contains
+   * Test whether a string contains another string.
+   * 
+   * Parameters:
+   * str - {String} The string to test.
+   * sub - {String} The substring to look for.
+   * 
+   * Returns:
+   * {Boolean} The first string contains the second.
+   */
+  contains: function(str, sub) {
+    return (str.indexOf(sub) != -1);
+  },
+  /**
+   * Function: trim
+   * Removes leading and trailing whitespace characters from a string.
+   * 
+   * Parameters:
+   * str - {String} The (potentially) space padded string.  This string is not
+   *     modified.
+   * 
+   * Returns:
+   * {String} A trimmed version of the string with all leading and 
+   *     trailing spaces removed.
+   */
+  trim: function(str) {
+    return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
+  },
+  /**
+   * Function: camelize
+   * Camel-case a hyphenated string. 
+   *     Ex. "chicken-head" becomes "chickenHead", and
+   *     "-chicken-head" becomes "ChickenHead".
+   *
+   * Parameters:
+   * str - {String} The string to be camelized.  The original is not modified.
+   * 
+   * Returns:
+   * {String} The string, camelized
+   *
+   */
+  camelize: function(str) {
+    var oStringList = str.split('-');
+    var camelizedString = oStringList[0];
+    for (var i=1, len=oStringList.length; i<len; i++) {
+      var s = oStringList[i];
+      camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
+    }
+    return camelizedString;
+  },
+  /**
+   * Property: tokenRegEx
+   * Used to find tokens in a string.
+   * Examples: ${a}, ${a.b.c}, ${a-b}, ${5}
+   */
+  tokenRegEx:  /\$\{([\w.]+?)\}/g,
+  /**
+   * Property: numberRegEx
+   * Used to test strings as numbers.
+   */
+  numberRegEx: /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/,
+  /**
+   * Function: isNumeric
+   * Determine whether a string contains only a numeric value.
+   *
+   * Examples:
+   * (code)
+   * ZOO.String.isNumeric("6.02e23") // true
+   * ZOO.String.isNumeric("12 dozen") // false
+   * ZOO.String.isNumeric("4") // true
+   * ZOO.String.isNumeric(" 4 ") // false
+   * (end)
+   *
+   * Returns:
+   * {Boolean} String contains only a number.
+   */
+  isNumeric: function(value) {
+    return ZOO.String.numberRegEx.test(value);
+  },
+  /**
+   * Function: numericIf
+   * Converts a string that appears to be a numeric value into a number.
+   * 
+   * Returns
+   * {Number|String} a Number if the passed value is a number, a String
+   *     otherwise. 
+   */
+  numericIf: function(value) {
+    return ZOO.String.isNumeric(value) ? parseFloat(value) : value;
+  }
+};
+
+/**
+ * Class: ZOO.Class
+ * Object for creating CLASS
+ */
+ZOO.Class = function() {
+  var len = arguments.length;
+  var P = arguments[0];
+  var F = arguments[len-1];
+  var C = typeof F.initialize == "function" ?
+    F.initialize :
+    function(){ P.prototype.initialize.apply(this, arguments); };
+
+  if (len > 1) {
+    var newArgs = [C, P].concat(
+          Array.prototype.slice.call(arguments).slice(1, len-1), F);
+    ZOO.inherit.apply(null, newArgs);
+  } else {
+    C.prototype = F;
+  }
+  return C;
+};
+/**
+ * Function: create
+ * Function for creating CLASS
+ */
+ZOO.Class.create = function() {
+  return function() {
+    if (arguments && arguments[0] != ZOO.Class.isPrototype) {
+      this.initialize.apply(this, arguments);
+    }
+  };
+};
+/**
+ * Function: inherit
+ * Function for inheriting CLASS
+ */
+ZOO.Class.inherit = function (P) {
+  var C = function() {
+   P.call(this);
+  };
+  var newArgs = [C].concat(Array.prototype.slice.call(arguments));
+  ZOO.inherit.apply(null, newArgs);
+  return C.prototype;
+};
+/**
+ * Function: inherit
+ * Function for inheriting CLASS
+ */
+ZOO.inherit = function(C, P) {
+  var F = function() {};
+  F.prototype = P.prototype;
+  C.prototype = new F;
+  var i, l, o;
+  for(i=2, l=arguments.length; i<l; i++) {
+    o = arguments[i];
+    if(typeof o === "function") {
+      o = o.prototype;
+    }
+    ZOO.Util.extend(C.prototype, o);
+  }
+};
+/**
+ * Class: ZOO.Util
+ * Object for utilities
+ */
+ZOO.Util = ZOO.Util || {};
+/**
+ * Function: extend
+ * Function for extending object
+ */
+ZOO.Util.extend = function(destination, source) {
+  destination = destination || {};
+  if (source) {
+    for (var property in source) {
+      var value = source[property];
+      if (value !== undefined) {
+        destination[property] = value;
+      }
+    }
+  }
+  return destination;
+};
+
+ZOO._=function(str){
+    return ZOOTranslate(str);
+};
+
+/**
+ * Class: ZOO.Request
+ * Contains convenience methods for working with ZOORequest which
+ *     replace XMLHttpRequest. Because of we are not in a browser
+ *     JavaScript environment, ZOO Project provides a method to 
+ *     query servers which is based on curl : ZOORequest.
+ */
+ZOO.Request = {
+  /**
+   * Function: GET
+   * Send an HTTP GET request.
+   *
+   * Parameters:
+   * url - {String} The URL to request.
+   * params - {Object} Params to add to the url
+   * 
+   * Returns:
+   * {String} Request result.
+   */
+  Get: function(url,params) {
+    var paramsArray = [];
+    for (var key in params) {
+      var value = params[key];
+      if ((value != null) && (typeof value != 'function')) {
+        var encodedValue;
+        if (typeof value == 'object' && value.constructor == Array) {
+          /* value is an array; encode items and separate with "," */
+          var encodedItemArray = [];
+          for (var itemIndex=0, len=value.length; itemIndex<len; itemIndex++) {
+            encodedItemArray.push(encodeURIComponent(value[itemIndex]));
+          }
+          encodedValue = encodedItemArray.join(",");
+        }
+        else {
+          /* value is a string; simply encode */
+          encodedValue = encodeURIComponent(value);
+        }
+        paramsArray.push(encodeURIComponent(key) + "=" + encodedValue);
+      }
+    }
+    var paramString = paramsArray.join("&");
+    if(paramString.length > 0) {
+      var separator = (url.indexOf('?') > -1) ? '&' : '?';
+      url += separator + paramString;
+    }
+    return ZOORequest('GET',url);
+  },
+  /**
+   * Function: POST
+   * Send an HTTP POST request.
+   *
+   * Parameters:
+   * url - {String} The URL to request.
+   * body - {String} The request's body to send.
+   * headers - {Object} A key-value object of headers to push to
+   *     the request's head
+   * 
+   * Returns:
+   * {String} Request result.
+   */
+  Post: function(url,body,headers) {
+    if(!(headers instanceof Array)) {
+      var headersArray = [];
+      for (var name in headers) {
+        headersArray.push(name+': '+headers[name]); 
+      }
+      headers = headersArray;
+    }
+    return ZOORequest('POST',url,body,headers);
+  }
+};
+
+/**
+ * Class: ZOO.Bounds
+ * Instances of this class represent bounding boxes.  Data stored as left,
+ *     bottom, right, top floats. All values are initialized to null,
+ *     however, you should make sure you set them before using the bounds
+ *     for anything.
+ */
+ZOO.Bounds = ZOO.Class({
+  /**
+   * Property: left
+   * {Number} Minimum horizontal coordinate.
+   */
+  left: null,
+  /**
+   * Property: bottom
+   * {Number} Minimum vertical coordinate.
+   */
+  bottom: null,
+  /**
+   * Property: right
+   * {Number} Maximum horizontal coordinate.
+   */
+  right: null,
+  /**
+   * Property: top
+   * {Number} Maximum vertical coordinate.
+   */
+  top: null,
+  /**
+   * Constructor: ZOO.Bounds
+   * Construct a new bounds object.
+   *
+   * Parameters:
+   * left - {Number} The left bounds of the box.  Note that for width
+   *        calculations, this is assumed to be less than the right value.
+   * bottom - {Number} The bottom bounds of the box.  Note that for height
+   *          calculations, this is assumed to be more than the top value.
+   * right - {Number} The right bounds.
+   * top - {Number} The top bounds.
+   */
+  initialize: function(left, bottom, right, top) {
+    if (left != null)
+      this.left = parseFloat(left);
+    if (bottom != null)
+      this.bottom = parseFloat(bottom);
+    if (right != null)
+      this.right = parseFloat(right);
+    if (top != null)
+      this.top = parseFloat(top);
+  },
+  /**
+   * Method: clone
+   * Create a cloned instance of this bounds.
+   *
+   * Returns:
+   * {<ZOO.Bounds>} A fresh copy of the bounds
+   */
+  clone:function() {
+    return new ZOO.Bounds(this.left, this.bottom, 
+                          this.right, this.top);
+  },
+  /**
+   * Method: equals
+   * Test a two bounds for equivalence.
+   *
+   * Parameters:
+   * bounds - {<ZOO.Bounds>}
+   *
+   * Returns:
+   * {Boolean} The passed-in bounds object has the same left,
+   *           right, top, bottom components as this.  Note that if bounds 
+   *           passed in is null, returns false.
+   */
+  equals:function(bounds) {
+    var equals = false;
+    if (bounds != null)
+        equals = ((this.left == bounds.left) && 
+                  (this.right == bounds.right) &&
+                  (this.top == bounds.top) && 
+                  (this.bottom == bounds.bottom));
+    return equals;
+  },
+  /** 
+   * Method: toString
+   * 
+   * Returns:
+   * {String} String representation of bounds object. 
+   *          (ex.<i>"left-bottom=(5,42) right-top=(10,45)"</i>)
+   */
+  toString:function() {
+    return ( "left-bottom=(" + this.left + "," + this.bottom + ")"
+              + " right-top=(" + this.right + "," + this.top + ")" );
+  },
+  /**
+   * APIMethod: toArray
+   *
+   * Returns:
+   * {Array} array of left, bottom, right, top
+   */
+  toArray: function() {
+    return [this.left, this.bottom, this.right, this.top];
+  },
+  /** 
+   * Method: toBBOX
+   * 
+   * Parameters:
+   * decimal - {Integer} How many significant digits in the bbox coords?
+   *                     Default is 6
+   * 
+   * Returns:
+   * {String} Simple String representation of bounds object.
+   *          (ex. <i>"5,42,10,45"</i>)
+   */
+  toBBOX:function(decimal) {
+    if (decimal== null)
+      decimal = 6; 
+    var mult = Math.pow(10, decimal);
+    var bbox = Math.round(this.left * mult) / mult + "," + 
+               Math.round(this.bottom * mult) / mult + "," + 
+               Math.round(this.right * mult) / mult + "," + 
+               Math.round(this.top * mult) / mult;
+    return bbox;
+  },
+  /**
+   * Method: toGeometry
+   * Create a new polygon geometry based on this bounds.
+   *
+   * Returns:
+   * {<ZOO.Geometry.Polygon>} A new polygon with the coordinates
+   *     of this bounds.
+   */
+  toGeometry: function() {
+    return new ZOO.Geometry.Polygon([
+      new ZOO.Geometry.LinearRing([
+        new ZOO.Geometry.Point(this.left, this.bottom),
+        new ZOO.Geometry.Point(this.right, this.bottom),
+        new ZOO.Geometry.Point(this.right, this.top),
+        new ZOO.Geometry.Point(this.left, this.top)
+      ])
+    ]);
+  },
+  /**
+   * Method: getWidth
+   * 
+   * Returns:
+   * {Float} The width of the bounds
+   */
+  getWidth:function() {
+    return (this.right - this.left);
+  },
+  /**
+   * Method: getHeight
+   * 
+   * Returns:
+   * {Float} The height of the bounds (top minus bottom).
+   */
+  getHeight:function() {
+    return (this.top - this.bottom);
+  },
+  /**
+   * Method: add
+   * 
+   * Parameters:
+   * x - {Float}
+   * y - {Float}
+   * 
+   * Returns:
+   * {<ZOO.Bounds>} A new bounds whose coordinates are the same as
+   *     this, but shifted by the passed-in x and y values.
+   */
+  add:function(x, y) {
+    if ( (x == null) || (y == null) )
+      return null;
+    return new ZOO.Bounds(this.left + x, this.bottom + y,
+                                 this.right + x, this.top + y);
+  },
+  /**
+   * Method: extend
+   * Extend the bounds to include the point, lonlat, or bounds specified.
+   *     Note, this function assumes that left < right and bottom < top.
+   * 
+   * Parameters: 
+   * object - {Object} Can be Point, or Bounds
+   */
+  extend:function(object) {
+    var bounds = null;
+    if (object) {
+      // clear cached center location
+      switch(object.CLASS_NAME) {
+        case "ZOO.Geometry.Point":
+          bounds = new ZOO.Bounds(object.x, object.y,
+                                         object.x, object.y);
+          break;
+        case "ZOO.Bounds":    
+          bounds = object;
+          break;
+      }
+      if (bounds) {
+        if ( (this.left == null) || (bounds.left < this.left))
+          this.left = bounds.left;
+        if ( (this.bottom == null) || (bounds.bottom < this.bottom) )
+          this.bottom = bounds.bottom;
+        if ( (this.right == null) || (bounds.right > this.right) )
+          this.right = bounds.right;
+        if ( (this.top == null) || (bounds.top > this.top) )
+          this.top = bounds.top;
+      }
+    }
+  },
+  /**
+   * APIMethod: contains
+   * 
+   * Parameters:
+   * x - {Float}
+   * y - {Float}
+   * inclusive - {Boolean} Whether or not to include the border.
+   *     Default is true.
+   *
+   * Returns:
+   * {Boolean} Whether or not the passed-in coordinates are within this
+   *     bounds.
+   */
+  contains:function(x, y, inclusive) {
+     //set default
+     if (inclusive == null)
+       inclusive = true;
+     if (x == null || y == null)
+       return false;
+     x = parseFloat(x);
+     y = parseFloat(y);
+
+     var contains = false;
+     if (inclusive)
+       contains = ((x >= this.left) && (x <= this.right) && 
+                   (y >= this.bottom) && (y <= this.top));
+     else
+       contains = ((x > this.left) && (x < this.right) && 
+                   (y > this.bottom) && (y < this.top));
+     return contains;
+  },
+  /**
+   * Method: intersectsBounds
+   * Determine whether the target bounds intersects this bounds.  Bounds are
+   *     considered intersecting if any of their edges intersect or if one
+   *     bounds contains the other.
+   * 
+   * Parameters:
+   * bounds - {<ZOO.Bounds>} The target bounds.
+   * inclusive - {Boolean} Treat coincident borders as intersecting.  Default
+   *     is true.  If false, bounds that do not overlap but only touch at the
+   *     border will not be considered as intersecting.
+   *
+   * Returns:
+   * {Boolean} The passed-in bounds object intersects this bounds.
+   */
+  intersectsBounds:function(bounds, inclusive) {
+    if (inclusive == null)
+      inclusive = true;
+    var intersects = false;
+    var mightTouch = (
+        this.left == bounds.right ||
+        this.right == bounds.left ||
+        this.top == bounds.bottom ||
+        this.bottom == bounds.top
+    );
+    if (inclusive || !mightTouch) {
+      var inBottom = (
+          ((bounds.bottom >= this.bottom) && (bounds.bottom <= this.top)) ||
+          ((this.bottom >= bounds.bottom) && (this.bottom <= bounds.top))
+          );
+      var inTop = (
+          ((bounds.top >= this.bottom) && (bounds.top <= this.top)) ||
+          ((this.top > bounds.bottom) && (this.top < bounds.top))
+          );
+      var inLeft = (
+          ((bounds.left >= this.left) && (bounds.left <= this.right)) ||
+          ((this.left >= bounds.left) && (this.left <= bounds.right))
+          );
+      var inRight = (
+          ((bounds.right >= this.left) && (bounds.right <= this.right)) ||
+          ((this.right >= bounds.left) && (this.right <= bounds.right))
+          );
+      intersects = ((inBottom || inTop) && (inLeft || inRight));
+    }
+    return intersects;
+  },
+  /**
+   * Method: containsBounds
+   * Determine whether the target bounds is contained within this bounds.
+   * 
+   * bounds - {<ZOO.Bounds>} The target bounds.
+   * partial - {Boolean} If any of the target corners is within this bounds
+   *     consider the bounds contained.  Default is false.  If true, the
+   *     entire target bounds must be contained within this bounds.
+   * inclusive - {Boolean} Treat shared edges as contained.  Default is
+   *     true.
+   *
+   * Returns:
+   * {Boolean} The passed-in bounds object is contained within this bounds. 
+   */
+  containsBounds:function(bounds, partial, inclusive) {
+    if (partial == null)
+      partial = false;
+    if (inclusive == null)
+      inclusive = true;
+    var bottomLeft  = this.contains(bounds.left, bounds.bottom, inclusive);
+    var bottomRight = this.contains(bounds.right, bounds.bottom, inclusive);
+    var topLeft  = this.contains(bounds.left, bounds.top, inclusive);
+    var topRight = this.contains(bounds.right, bounds.top, inclusive);
+    return (partial) ? (bottomLeft || bottomRight || topLeft || topRight)
+                     : (bottomLeft && bottomRight && topLeft && topRight);
+  },
+  CLASS_NAME: 'ZOO.Bounds'
+});
+
+/**
+ * Class: ZOO.Projection
+ * Class for coordinate transforms between coordinate systems.
+ *     Depends on the zoo-proj4js library. zoo-proj4js library 
+ *     is loaded by the ZOO Kernel with zoo-api.
+ */
+ZOO.Projection = ZOO.Class({
+  /**
+   * Property: proj
+   * {Object} Proj4js.Proj instance.
+   */
+  proj: null,
+  /**
+   * Property: projCode
+   * {String}
+   */
+  projCode: null,
+  /**
+   * Constructor: ZOO.Projection
+   * This class offers several methods for interacting with a wrapped 
+   *     zoo-pro4js projection object. 
+   *
+   * Parameters:
+   * projCode - {String} A string identifying the Well Known Identifier for
+   *    the projection.
+   * options - {Object} An optional object to set additional properties.
+   *
+   * Returns:
+   * {<ZOO.Projection>} A projection object.
+   */
+  initialize: function(projCode, options) {
+    ZOO.extend(this, options);
+    this.projCode = projCode;
+    if (Proj4js) {
+      this.proj = new Proj4js.Proj(projCode);
+    }
+  },
+  /**
+   * Method: getCode
+   * Get the string SRS code.
+   *
+   * Returns:
+   * {String} The SRS code.
+   */
+  getCode: function() {
+    return this.proj ? this.proj.srsCode : this.projCode;
+  },
+  /**
+   * Method: getUnits
+   * Get the units string for the projection -- returns null if 
+   *     zoo-proj4js is not available.
+   *
+   * Returns:
+   * {String} The units abbreviation.
+   */
+  getUnits: function() {
+    return this.proj ? this.proj.units : null;
+  },
+  /**
+   * Method: toString
+   * Convert projection to string (getCode wrapper).
+   *
+   * Returns:
+   * {String} The projection code.
+   */
+  toString: function() {
+    return this.getCode();
+  },
+  /**
+   * Method: equals
+   * Test equality of two projection instances.  Determines equality based
+   *     soley on the projection code.
+   *
+   * Returns:
+   * {Boolean} The two projections are equivalent.
+   */
+  equals: function(projection) {
+    if (projection && projection.getCode)
+      return this.getCode() == projection.getCode();
+    else
+      return false;
+  },
+  /* Method: destroy
+   * Destroy projection object.
+   */
+  destroy: function() {
+    this.proj = null;
+    this.projCode = null;
+  },
+  CLASS_NAME: 'ZOO.Projection'
+});
+/**
+ * Method: transform
+ * Transform a point coordinate from one projection to another.  Note that
+ *     the input point is transformed in place.
+ * 
+ * Parameters:
+ * point - {{ZOO.Geometry.Point> | Object} An object with x and y
+ *     properties representing coordinates in those dimensions.
+ * sourceProj - {ZOO.Projection} Source map coordinate system
+ * destProj - {ZOO.Projection} Destination map coordinate system
+ *
+ * Returns:
+ * point - {object} A transformed coordinate.  The original point is modified.
+ */
+ZOO.Projection.transform = function(point, source, dest) {
+    if (source.proj && dest.proj)
+        point = Proj4js.transform(source.proj, dest.proj, point);
+    return point;
+};
+
+/**
+ * Class: ZOO.Format
+ * Base class for format reading/writing a variety of formats. Subclasses
+ *     of ZOO.Format are expected to have read and write methods.
+ */
+ZOO.Format = ZOO.Class({
+  /**
+   * Property: options
+   * {Object} A reference to options passed to the constructor.
+   */
+  options:null,
+  /**
+   * Property: externalProjection
+   * {<ZOO.Projection>} When passed a externalProjection and
+   *     internalProjection, the format will reproject the geometries it
+   *     reads or writes. The externalProjection is the projection used by
+   *     the content which is passed into read or which comes out of write.
+   *     In order to reproject, a projection transformation function for the
+   *     specified projections must be available. This support is provided 
+   *     via zoo-proj4js.
+   */
+  externalProjection: null,
+  /**
+   * Property: internalProjection
+   * {<ZOO.Projection>} When passed a externalProjection and
+   *     internalProjection, the format will reproject the geometries it
+   *     reads or writes. The internalProjection is the projection used by
+   *     the geometries which are returned by read or which are passed into
+   *     write.  In order to reproject, a projection transformation function
+   *     for the specified projections must be available. This support is 
+   *     provided via zoo-proj4js.
+   */
+  internalProjection: null,
+  /**
+   * Property: data
+   * {Object} When <keepData> is true, this is the parsed string sent to
+   *     <read>.
+   */
+  data: null,
+  /**
+   * Property: keepData
+   * {Object} Maintain a reference (<data>) to the most recently read data.
+   *     Default is false.
+   */
+  keepData: false,
+  /**
+   * Constructor: ZOO.Format
+   * Instances of this class are not useful.  See one of the subclasses.
+   *
+   * Parameters:
+   * options - {Object} An optional object with properties to set on the
+   *           format
+   *
+   * Valid options:
+   * keepData - {Boolean} If true, upon <read>, the data property will be
+   *     set to the parsed object (e.g. the json or xml object).
+   *
+   * Returns:
+   * An instance of ZOO.Format
+   */
+  initialize: function(options) {
+    ZOO.extend(this, options);
+    this.options = options;
+  },
+  /**
+   * Method: destroy
+   * Clean up.
+   */
+  destroy: function() {
+  },
+  /**
+   * Method: read
+   * Read data from a string, and return an object whose type depends on the
+   * subclass. 
+   * 
+   * Parameters:
+   * data - {string} Data to read/parse.
+   *
+   * Returns:
+   * Depends on the subclass
+   */
+  read: function(data) {
+  },
+  /**
+   * Method: write
+   * Accept an object, and return a string. 
+   *
+   * Parameters:
+   * object - {Object} Object to be serialized
+   *
+   * Returns:
+   * {String} A string representation of the object.
+   */
+  write: function(data) {
+  },
+  CLASS_NAME: 'ZOO.Format'
+});
+/**
+ * Class: ZOO.Format.WKT
+ * Class for reading and writing Well-Known Text. Create a new instance
+ * with the <ZOO.Format.WKT> constructor.
+ * 
+ * Inherits from:
+ *  - <ZOO.Format>
+ */
+ZOO.Format.WKT = ZOO.Class(ZOO.Format, {
+  /**
+   * Constructor: ZOO.Format.WKT
+   * Create a new parser for WKT
+   *
+   * Parameters:
+   * options - {Object} An optional object whose properties will be set on
+   *           this instance
+   *
+   * Returns:
+   * {<ZOO.Format.WKT>} A new WKT parser.
+   */
+  initialize: function(options) {
+    this.regExes = {
+      'typeStr': /^\s*(\w+)\s*\(\s*(.*)\s*\)\s*$/,
+      'spaces': /\s+/,
+      'parenComma': /\)\s*,\s*\(/,
+      'doubleParenComma': /\)\s*\)\s*,\s*\(\s*\(/,  // can't use {2} here
+      'trimParens': /^\s*\(?(.*?)\)?\s*$/
+    };
+    ZOO.Format.prototype.initialize.apply(this, [options]);
+  },
+  /**
+   * Method: read
+   * Deserialize a WKT string and return a vector feature or an
+   *     array of vector features.  Supports WKT for POINT, 
+   *     MULTIPOINT, LINESTRING, MULTILINESTRING, POLYGON, 
+   *     MULTIPOLYGON, and GEOMETRYCOLLECTION.
+   *
+   * Parameters:
+   * wkt - {String} A WKT string
+   *
+   * Returns:
+   * {<ZOO.Feature.Vector>|Array} A feature or array of features for
+   *     GEOMETRYCOLLECTION WKT.
+   */
+  read: function(wkt) {
+    var features, type, str;
+    var matches = this.regExes.typeStr.exec(wkt);
+    if(matches) {
+      type = matches[1].toLowerCase();
+      str = matches[2];
+      if(this.parse[type]) {
+        features = this.parse[type].apply(this, [str]);
+      }
+      if (this.internalProjection && this.externalProjection) {
+        if (features && 
+            features.CLASS_NAME == "ZOO.Feature") {
+          features.geometry.transform(this.externalProjection,
+                                      this.internalProjection);
+        } else if (features &&
+            type != "geometrycollection" &&
+            typeof features == "object") {
+          for (var i=0, len=features.length; i<len; i++) {
+            var component = features[i];
+            component.geometry.transform(this.externalProjection,
+                                         this.internalProjection);
+          }
+        }
+      }
+    }    
+    return features;
+  },
+  /**
+   * Method: write
+   * Serialize a feature or array of features into a WKT string.
+   *
+   * Parameters:
+   * features - {<ZOO.Feature.Vector>|Array} A feature or array of
+   *            features
+   *
+   * Returns:
+   * {String} The WKT string representation of the input geometries
+   */
+  write: function(features) {
+    var collection, geometry, type, data, isCollection;
+    if(features.constructor == Array) {
+      collection = features;
+      isCollection = true;
+    } else {
+      collection = [features];
+      isCollection = false;
+    }
+    var pieces = [];
+    if(isCollection)
+      pieces.push('GEOMETRYCOLLECTION(');
+    for(var i=0, len=collection.length; i<len; ++i) {
+      if(isCollection && i>0)
+        pieces.push(',');
+      geometry = collection[i].geometry;
+      type = geometry.CLASS_NAME.split('.')[2].toLowerCase();
+      if(!this.extract[type])
+        return null;
+      if (this.internalProjection && this.externalProjection) {
+        geometry = geometry.clone();
+        geometry.transform(this.internalProjection, 
+                          this.externalProjection);
+      }                       
+      data = this.extract[type].apply(this, [geometry]);
+      pieces.push(type.toUpperCase() + '(' + data + ')');
+    }
+    if(isCollection)
+      pieces.push(')');
+    return pieces.join('');
+  },
+  /**
+   * Property: extract
+   * Object with properties corresponding to the geometry types.
+   * Property values are functions that do the actual data extraction.
+   */
+  extract: {
+    /**
+     * Return a space delimited string of point coordinates.
+     * @param {<ZOO.Geometry.Point>} point
+     * @returns {String} A string of coordinates representing the point
+     */
+    'point': function(point) {
+      return point.x + ' ' + point.y;
+    },
+    /**
+     * Return a comma delimited string of point coordinates from a multipoint.
+     * @param {<ZOO.Geometry.MultiPoint>} multipoint
+     * @returns {String} A string of point coordinate strings representing
+     *                  the multipoint
+     */
+    'multipoint': function(multipoint) {
+      var array = [];
+      for(var i=0, len=multipoint.components.length; i<len; ++i) {
+        array.push(this.extract.point.apply(this, [multipoint.components[i]]));
+      }
+      return array.join(',');
+    },
+    /**
+     * Return a comma delimited string of point coordinates from a line.
+     * @param {<ZOO.Geometry.LineString>} linestring
+     * @returns {String} A string of point coordinate strings representing
+     *                  the linestring
+     */
+    'linestring': function(linestring) {
+      var array = [];
+      for(var i=0, len=linestring.components.length; i<len; ++i) {
+        array.push(this.extract.point.apply(this, [linestring.components[i]]));
+      }
+      return array.join(',');
+    },
+    /**
+     * Return a comma delimited string of linestring strings from a multilinestring.
+     * @param {<ZOO.Geometry.MultiLineString>} multilinestring
+     * @returns {String} A string of of linestring strings representing
+     *                  the multilinestring
+     */
+    'multilinestring': function(multilinestring) {
+      var array = [];
+      for(var i=0, len=multilinestring.components.length; i<len; ++i) {
+        array.push('(' +
+            this.extract.linestring.apply(this, [multilinestring.components[i]]) +
+            ')');
+      }
+      return array.join(',');
+    },
+    /**
+     * Return a comma delimited string of linear ring arrays from a polygon.
+     * @param {<ZOO.Geometry.Polygon>} polygon
+     * @returns {String} An array of linear ring arrays representing the polygon
+     */
+    'polygon': function(polygon) {
+      var array = [];
+      for(var i=0, len=polygon.components.length; i<len; ++i) {
+        array.push('(' +
+            this.extract.linestring.apply(this, [polygon.components[i]]) +
+            ')');
+      }
+      return array.join(',');
+    },
+    /**
+     * Return an array of polygon arrays from a multipolygon.
+     * @param {<ZOO.Geometry.MultiPolygon>} multipolygon
+     * @returns {Array} An array of polygon arrays representing
+     *                  the multipolygon
+     */
+    'multipolygon': function(multipolygon) {
+      var array = [];
+      for(var i=0, len=multipolygon.components.length; i<len; ++i) {
+        array.push('(' +
+            this.extract.polygon.apply(this, [multipolygon.components[i]]) +
+            ')');
+      }
+      return array.join(',');
+    }
+  },
+  /**
+   * Property: parse
+   * Object with properties corresponding to the geometry types.
+   *     Property values are functions that do the actual parsing.
+   */
+  parse: {
+    /**
+     * Method: parse.point
+     * Return point feature given a point WKT fragment.
+     *
+     * Parameters:
+     * str - {String} A WKT fragment representing the point
+     * Returns:
+     * {<ZOO.Feature>} A point feature
+     */
+    'point': function(str) {
+       var coords = ZOO.String.trim(str).split(this.regExes.spaces);
+            return new ZOO.Feature(
+                new ZOO.Geometry.Point(coords[0], coords[1])
+            );
+    },
+    /**
+     * Method: parse.multipoint
+     * Return a multipoint feature given a multipoint WKT fragment.
+     *
+     * Parameters:
+     * str - {String} A WKT fragment representing the multipoint
+     *
+     * Returns:
+     * {<ZOO.Feature>} A multipoint feature
+     */
+    'multipoint': function(str) {
+       var points = ZOO.String.trim(str).split(',');
+       var components = [];
+       for(var i=0, len=points.length; i<len; ++i) {
+         components.push(this.parse.point.apply(this, [points[i]]).geometry);
+       }
+       return new ZOO.Feature(
+           new ZOO.Geometry.MultiPoint(components)
+           );
+    },
+    /**
+     * Method: parse.linestring
+     * Return a linestring feature given a linestring WKT fragment.
+     *
+     * Parameters:
+     * str - {String} A WKT fragment representing the linestring
+     *
+     * Returns:
+     * {<ZOO.Feature>} A linestring feature
+     */
+    'linestring': function(str) {
+      var points = ZOO.String.trim(str).split(',');
+      var components = [];
+      for(var i=0, len=points.length; i<len; ++i) {
+        components.push(this.parse.point.apply(this, [points[i]]).geometry);
+      }
+      return new ZOO.Feature(
+          new ZOO.Geometry.LineString(components)
+          );
+    },
+    /**
+     * Method: parse.multilinestring
+     * Return a multilinestring feature given a multilinestring WKT fragment.
+     *
+     * Parameters:
+     * str - {String} A WKT fragment representing the multilinestring
+     *
+     * Returns:
+     * {<ZOO.Feature>} A multilinestring feature
+     */
+    'multilinestring': function(str) {
+      var line;
+      var lines = ZOO.String.trim(str).split(this.regExes.parenComma);
+      var components = [];
+      for(var i=0, len=lines.length; i<len; ++i) {
+        line = lines[i].replace(this.regExes.trimParens, '$1');
+        components.push(this.parse.linestring.apply(this, [line]).geometry);
+      }
+      return new ZOO.Feature(
+          new ZOO.Geometry.MultiLineString(components)
+          );
+    },
+    /**
+     * Method: parse.polygon
+     * Return a polygon feature given a polygon WKT fragment.
+     *
+     * Parameters:
+     * str - {String} A WKT fragment representing the polygon
+     *
+     * Returns:
+     * {<ZOO.Feature>} A polygon feature
+     */
+    'polygon': function(str) {
+       var ring, linestring, linearring;
+       var rings = ZOO.String.trim(str).split(this.regExes.parenComma);
+       var components = [];
+       for(var i=0, len=rings.length; i<len; ++i) {
+         ring = rings[i].replace(this.regExes.trimParens, '$1');
+         linestring = this.parse.linestring.apply(this, [ring]).geometry;
+         linearring = new ZOO.Geometry.LinearRing(linestring.components);
+         components.push(linearring);
+       }
+       return new ZOO.Feature(
+           new ZOO.Geometry.Polygon(components)
+           );
+    },
+    /**
+     * Method: parse.multipolygon
+     * Return a multipolygon feature given a multipolygon WKT fragment.
+     *
+     * Parameters:
+     * str - {String} A WKT fragment representing the multipolygon
+     *
+     * Returns:
+     * {<ZOO.Feature>} A multipolygon feature
+     */
+    'multipolygon': function(str) {
+      var polygon;
+      var polygons = ZOO.String.trim(str).split(this.regExes.doubleParenComma);
+      var components = [];
+      for(var i=0, len=polygons.length; i<len; ++i) {
+        polygon = polygons[i].replace(this.regExes.trimParens, '$1');
+        components.push(this.parse.polygon.apply(this, [polygon]).geometry);
+      }
+      return new ZOO.Feature(
+          new ZOO.Geometry.MultiPolygon(components)
+          );
+    },
+    /**
+     * Method: parse.geometrycollection
+     * Return an array of features given a geometrycollection WKT fragment.
+     *
+     * Parameters:
+     * str - {String} A WKT fragment representing the geometrycollection
+     *
+     * Returns:
+     * {Array} An array of ZOO.Feature
+     */
+    'geometrycollection': function(str) {
+      // separate components of the collection with |
+      str = str.replace(/,\s*([A-Za-z])/g, '|$1');
+      var wktArray = ZOO.String.trim(str).split('|');
+      var components = [];
+      for(var i=0, len=wktArray.length; i<len; ++i) {
+        components.push(ZOO.Format.WKT.prototype.read.apply(this,[wktArray[i]]));
+      }
+      return components;
+    }
+  },
+  CLASS_NAME: 'ZOO.Format.WKT'
+});
+/**
+ * Class: ZOO.Format.JSON
+ * A parser to read/write JSON safely. Create a new instance with the
+ *     <ZOO.Format.JSON> constructor.
+ *
+ * Inherits from:
+ *  - <ZOO.Format>
+ */
+ZOO.Format.JSON = ZOO.Class(ZOO.Format, {
+  /**
+   * Property: indent
+   * {String} For "pretty" printing, the indent string will be used once for
+   *     each indentation level.
+   */
+  indent: "    ",
+  /**
+   * Property: space
+   * {String} For "pretty" printing, the space string will be used after
+   *     the ":" separating a name/value pair.
+   */
+  space: " ",
+  /**
+   * Property: newline
+   * {String} For "pretty" printing, the newline string will be used at the
+   *     end of each name/value pair or array item.
+   */
+  newline: "\n",
+  /**
+   * Property: level
+   * {Integer} For "pretty" printing, this is incremented/decremented during
+   *     serialization.
+   */
+  level: 0,
+  /**
+   * Property: pretty
+   * {Boolean} Serialize with extra whitespace for structure.  This is set
+   *     by the <write> method.
+   */
+  pretty: false,
+  /**
+   * Constructor: ZOO.Format.JSON
+   * Create a new parser for JSON.
+   *
+   * Parameters:
+   * options - {Object} An optional object whose properties will be set on
+   *     this instance.
+   */
+  initialize: function(options) {
+    ZOO.Format.prototype.initialize.apply(this, [options]);
+  },
+  /**
+   * Method: read
+   * Deserialize a json string.
+   *
+   * Parameters:
+   * json - {String} A JSON string
+   * filter - {Function} A function which will be called for every key and
+   *     value at every level of the final result. Each value will be
+   *     replaced by the result of the filter function. This can be used to
+   *     reform generic objects into instances of classes, or to transform
+   *     date strings into Date objects.
+   *     
+   * Returns:
+   * {Object} An object, array, string, or number .
+   */
+  read: function(json, filter) {
+    /**
+     * Parsing happens in three stages. In the first stage, we run the text
+     *     against a regular expression which looks for non-JSON
+     *     characters. We are especially concerned with '()' and 'new'
+     *     because they can cause invocation, and '=' because it can cause
+     *     mutation. But just to be safe, we will reject all unexpected
+     *     characters.
+     */
+    try {
+      if (/^[\],:{}\s]*$/.test(json.replace(/\\["\\\/bfnrtu]/g, '@').
+                          replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
+                          replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
+        /**
+         * In the second stage we use the eval function to compile the
+         *     text into a JavaScript structure. The '{' operator is
+         *     subject to a syntactic ambiguity in JavaScript - it can
+         *     begin a block or an object literal. We wrap the text in
+         *     parens to eliminate the ambiguity.
+         */
+        var object = eval('(' + json + ')');
+        /**
+         * In the optional third stage, we recursively walk the new
+         *     structure, passing each name/value pair to a filter
+         *     function for possible transformation.
+         */
+        if(typeof filter === 'function') {
+          function walk(k, v) {
+            if(v && typeof v === 'object') {
+              for(var i in v) {
+                if(v.hasOwnProperty(i)) {
+                  v[i] = walk(i, v[i]);
+                }
+              }
+            }
+            return filter(k, v);
+          }
+          object = walk('', object);
+        }
+        if(this.keepData) {
+          this.data = object;
+        }
+        return object;
+      }
+    } catch(e) {
+      // Fall through if the regexp test fails.
+    }
+    return null;
+  },
+  /**
+   * Method: write
+   * Serialize an object into a JSON string.
+   *
+   * Parameters:
+   * value - {String} The object, array, string, number, boolean or date
+   *     to be serialized.
+   * pretty - {Boolean} Structure the output with newlines and indentation.
+   *     Default is false.
+   *
+   * Returns:
+   * {String} The JSON string representation of the input value.
+   */
+  write: function(value, pretty) {
+    this.pretty = !!pretty;
+    var json = null;
+    var type = typeof value;
+    if(this.serialize[type]) {
+      try {
+        json = this.serialize[type].apply(this, [value]);
+      } catch(err) {
+        //OpenLayers.Console.error("Trouble serializing: " + err);
+      }
+    }
+    return json;
+  },
+  /**
+   * Method: writeIndent
+   * Output an indentation string depending on the indentation level.
+   *
+   * Returns:
+   * {String} An appropriate indentation string.
+   */
+  writeIndent: function() {
+    var pieces = [];
+    if(this.pretty) {
+      for(var i=0; i<this.level; ++i) {
+        pieces.push(this.indent);
+      }
+    }
+    return pieces.join('');
+  },
+  /**
+   * Method: writeNewline
+   * Output a string representing a newline if in pretty printing mode.
+   *
+   * Returns:
+   * {String} A string representing a new line.
+   */
+  writeNewline: function() {
+    return (this.pretty) ? this.newline : '';
+  },
+  /**
+   * Method: writeSpace
+   * Output a string representing a space if in pretty printing mode.
+   *
+   * Returns:
+   * {String} A space.
+   */
+  writeSpace: function() {
+    return (this.pretty) ? this.space : '';
+  },
+  /**
+   * Property: serialize
+   * Object with properties corresponding to the serializable data types.
+   *     Property values are functions that do the actual serializing.
+   */
+  serialize: {
+    /**
+     * Method: serialize.object
+     * Transform an object into a JSON string.
+     *
+     * Parameters:
+     * object - {Object} The object to be serialized.
+     * 
+     * Returns:
+     * {String} A JSON string representing the object.
+     */
+    'object': function(object) {
+       // three special objects that we want to treat differently
+       if(object == null)
+         return "null";
+       if(object.constructor == Date)
+         return this.serialize.date.apply(this, [object]);
+       if(object.constructor == Array)
+         return this.serialize.array.apply(this, [object]);
+       var pieces = ['{'];
+       this.level += 1;
+       var key, keyJSON, valueJSON;
+
+       var addComma = false;
+       for(key in object) {
+         if(object.hasOwnProperty(key)) {
+           // recursive calls need to allow for sub-classing
+           keyJSON = ZOO.Format.JSON.prototype.write.apply(this,
+                                                           [key, this.pretty]);
+           valueJSON = ZOO.Format.JSON.prototype.write.apply(this,
+                                                             [object[key], this.pretty]);
+           if(keyJSON != null && valueJSON != null) {
+             if(addComma)
+               pieces.push(',');
+             pieces.push(this.writeNewline(), this.writeIndent(),
+                         keyJSON, ':', this.writeSpace(), valueJSON);
+             addComma = true;
+           }
+         }
+       }
+       this.level -= 1;
+       pieces.push(this.writeNewline(), this.writeIndent(), '}');
+       return pieces.join('');
+    },
+    /**
+     * Method: serialize.array
+     * Transform an array into a JSON string.
+     *
+     * Parameters:
+     * array - {Array} The array to be serialized
+     * 
+     * Returns:
+     * {String} A JSON string representing the array.
+     */
+    'array': function(array) {
+      var json;
+      var pieces = ['['];
+      this.level += 1;
+      for(var i=0, len=array.length; i<len; ++i) {
+        // recursive calls need to allow for sub-classing
+        json = ZOO.Format.JSON.prototype.write.apply(this,
+                                                     [array[i], this.pretty]);
+        if(json != null) {
+          if(i > 0)
+            pieces.push(',');
+          pieces.push(this.writeNewline(), this.writeIndent(), json);
+        }
+      }
+      this.level -= 1;    
+      pieces.push(this.writeNewline(), this.writeIndent(), ']');
+      return pieces.join('');
+    },
+    /**
+     * Method: serialize.string
+     * Transform a string into a JSON string.
+     *
+     * Parameters:
+     * string - {String} The string to be serialized
+     * 
+     * Returns:
+     * {String} A JSON string representing the string.
+     */
+    'string': function(string) {
+      var m = {
+                '\b': '\\b',
+                '\t': '\\t',
+                '\n': '\\n',
+                '\f': '\\f',
+                '\r': '\\r',
+                '"' : '\\"',
+                '\\': '\\\\'
+      };
+      if(/["\\\x00-\x1f]/.test(string)) {
+        return '"' + string.replace(/([\x00-\x1f\\"])/g, function(a, b) {
+            var c = m[b];
+            if(c)
+              return c;
+            c = b.charCodeAt();
+            return '\\u00' +
+            Math.floor(c / 16).toString(16) +
+            (c % 16).toString(16);
+        }) + '"';
+      }
+      return '"' + string + '"';
+    },
+    /**
+     * Method: serialize.number
+     * Transform a number into a JSON string.
+     *
+     * Parameters:
+     * number - {Number} The number to be serialized.
+     *
+     * Returns:
+     * {String} A JSON string representing the number.
+     */
+    'number': function(number) {
+      return isFinite(number) ? String(number) : "null";
+    },
+    /**
+     * Method: serialize.boolean
+     * Transform a boolean into a JSON string.
+     *
+     * Parameters:
+     * bool - {Boolean} The boolean to be serialized.
+     * 
+     * Returns:
+     * {String} A JSON string representing the boolean.
+     */
+    'boolean': function(bool) {
+      return String(bool);
+    },
+    /**
+     * Method: serialize.date
+     * Transform a date into a JSON string.
+     *
+     * Parameters:
+     * date - {Date} The date to be serialized.
+     * 
+     * Returns:
+     * {String} A JSON string representing the date.
+     */
+    'date': function(date) {    
+      function format(number) {
+        // Format integers to have at least two digits.
+        return (number < 10) ? '0' + number : number;
+      }
+      return '"' + date.getFullYear() + '-' +
+        format(date.getMonth() + 1) + '-' +
+        format(date.getDate()) + 'T' +
+        format(date.getHours()) + ':' +
+        format(date.getMinutes()) + ':' +
+        format(date.getSeconds()) + '"';
+    }
+  },
+  CLASS_NAME: 'ZOO.Format.JSON'
+});
+/**
+ * Class: ZOO.Format.GeoJSON
+ * Read and write GeoJSON. Create a new parser with the
+ *     <ZOO.Format.GeoJSON> constructor.
+ *
+ * Inherits from:
+ *  - <ZOO.Format.JSON>
+ */
+ZOO.Format.GeoJSON = ZOO.Class(ZOO.Format.JSON, {
+  /**
+   * Constructor: ZOO.Format.GeoJSON
+   * Create a new parser for GeoJSON.
+   *
+   * Parameters:
+   * options - {Object} An optional object whose properties will be set on
+   *     this instance.
+   */
+  initialize: function(options) {
+    ZOO.Format.JSON.prototype.initialize.apply(this, [options]);
+  },
+  /**
+   * Method: read
+   * Deserialize a GeoJSON string.
+   *
+   * Parameters:
+   * json - {String} A GeoJSON string
+   * type - {String} Optional string that determines the structure of
+   *     the output.  Supported values are "Geometry", "Feature", and
+   *     "FeatureCollection".  If absent or null, a default of
+   *     "FeatureCollection" is assumed.
+   * filter - {Function} A function which will be called for every key and
+   *     value at every level of the final result. Each value will be
+   *     replaced by the result of the filter function. This can be used to
+   *     reform generic objects into instances of classes, or to transform
+   *     date strings into Date objects.
+   *
+   * Returns: 
+   * {Object} The return depends on the value of the type argument. If type
+   *     is "FeatureCollection" (the default), the return will be an array
+   *     of <ZOO.Feature>. If type is "Geometry", the input json
+   *     must represent a single geometry, and the return will be an
+   *     <ZOO.Geometry>.  If type is "Feature", the input json must
+   *     represent a single feature, and the return will be an
+   *     <ZOO.Feature>.
+   */
+  read: function(json, type, filter) {
+    type = (type) ? type : "FeatureCollection";
+    var results = null;
+    var obj = null;
+    if (typeof json == "string")
+      obj = ZOO.Format.JSON.prototype.read.apply(this,[json, filter]);
+    else
+      obj = json;
+    if(!obj) {
+      //ZOO.Console.error("Bad JSON: " + json);
+    } else if(typeof(obj.type) != "string") {
+      //ZOO.Console.error("Bad GeoJSON - no type: " + json);
+    } else if(this.isValidType(obj, type)) {
+      switch(type) {
+        case "Geometry":
+          try {
+            results = this.parseGeometry(obj);
+          } catch(err) {
+            //ZOO.Console.error(err);
+          }
+          break;
+        case "Feature":
+          try {
+            results = this.parseFeature(obj);
+            results.type = "Feature";
+          } catch(err) {
+            //ZOO.Console.error(err);
+          }
+          break;
+        case "FeatureCollection":
+          // for type FeatureCollection, we allow input to be any type
+          results = [];
+          switch(obj.type) {
+            case "Feature":
+              try {
+                results.push(this.parseFeature(obj));
+              } catch(err) {
+                results = null;
+                //ZOO.Console.error(err);
+              }
+              break;
+            case "FeatureCollection":
+              for(var i=0, len=obj.features.length; i<len; ++i) {
+                try {
+                  results.push(this.parseFeature(obj.features[i]));
+                } catch(err) {
+                  results = null;
+                  //ZOO.Console.error(err);
+                }
+              }
+              break;
+            default:
+              try {
+                var geom = this.parseGeometry(obj);
+                results.push(new ZOO.Feature(geom));
+              } catch(err) {
+                results = null;
+                //ZOO.Console.error(err);
+              }
+          }
+          break;
+      }
+    }
+    return results;
+  },
+  /**
+   * Method: isValidType
+   * Check if a GeoJSON object is a valid representative of the given type.
+   *
+   * Returns:
+   * {Boolean} The object is valid GeoJSON object of the given type.
+   */
+  isValidType: function(obj, type) {
+    var valid = false;
+    switch(type) {
+      case "Geometry":
+        if(ZOO.indexOf(
+              ["Point", "MultiPoint", "LineString", "MultiLineString",
+              "Polygon", "MultiPolygon", "Box", "GeometryCollection"],
+              obj.type) == -1) {
+          // unsupported geometry type
+          //ZOO.Console.error("Unsupported geometry type: " +obj.type);
+        } else {
+          valid = true;
+        }
+        break;
+      case "FeatureCollection":
+        // allow for any type to be converted to a feature collection
+        valid = true;
+        break;
+      default:
+        // for Feature types must match
+        if(obj.type == type) {
+          valid = true;
+        } else {
+          //ZOO.Console.error("Cannot convert types from " +obj.type + " to " + type);
+        }
+    }
+    return valid;
+  },
+  /**
+   * Method: parseFeature
+   * Convert a feature object from GeoJSON into an
+   *     <ZOO.Feature>.
+   *
+   * Parameters:
+   * obj - {Object} An object created from a GeoJSON object
+   *
+   * Returns:
+   * {<ZOO.Feature>} A feature.
+   */
+  parseFeature: function(obj) {
+    var feature, geometry, attributes, bbox;
+    attributes = (obj.properties) ? obj.properties : {};
+    bbox = (obj.geometry && obj.geometry.bbox) || obj.bbox;
+    try {
+      geometry = this.parseGeometry(obj.geometry);
+    } catch(err) {
+      // deal with bad geometries
+      throw err;
+    }
+    feature = new ZOO.Feature(geometry, attributes);
+    if(bbox)
+      feature.bounds = ZOO.Bounds.fromArray(bbox);
+    if(obj.id)
+      feature.fid = obj.id;
+    return feature;
+  },
+  /**
+   * Method: parseGeometry
+   * Convert a geometry object from GeoJSON into an <ZOO.Geometry>.
+   *
+   * Parameters:
+   * obj - {Object} An object created from a GeoJSON object
+   *
+   * Returns: 
+   * {<ZOO.Geometry>} A geometry.
+   */
+  parseGeometry: function(obj) {
+    if (obj == null)
+      return null;
+    var geometry, collection = false;
+    if(obj.type == "GeometryCollection") {
+      if(!(obj.geometries instanceof Array)) {
+        throw "GeometryCollection must have geometries array: " + obj;
+      }
+      var numGeom = obj.geometries.length;
+      var components = new Array(numGeom);
+      for(var i=0; i<numGeom; ++i) {
+        components[i] = this.parseGeometry.apply(
+            this, [obj.geometries[i]]
+            );
+      }
+      geometry = new ZOO.Geometry.Collection(components);
+      collection = true;
+    } else {
+      if(!(obj.coordinates instanceof Array)) {
+        throw "Geometry must have coordinates array: " + obj;
+      }
+      if(!this.parseCoords[obj.type.toLowerCase()]) {
+        throw "Unsupported geometry type: " + obj.type;
+      }
+      try {
+        geometry = this.parseCoords[obj.type.toLowerCase()].apply(
+            this, [obj.coordinates]
+            );
+      } catch(err) {
+        // deal with bad coordinates
+        throw err;
+      }
+    }
+        // We don't reproject collections because the children are reprojected
+        // for us when they are created.
+    if (this.internalProjection && this.externalProjection && !collection) {
+      geometry.transform(this.externalProjection, 
+          this.internalProjection); 
+    }                       
+    return geometry;
+  },
+  /**
+   * Property: parseCoords
+   * Object with properties corresponding to the GeoJSON geometry types.
+   *     Property values are functions that do the actual parsing.
+   */
+  parseCoords: {
+    /**
+     * Method: parseCoords.point
+     * Convert a coordinate array from GeoJSON into an
+     *     <ZOO.Geometry.Point>.
+     *
+     * Parameters:
+     * array - {Object} The coordinates array from the GeoJSON fragment.
+     *
+     * Returns:
+     * {<ZOO.Geometry.Point>} A geometry.
+     */
+    "point": function(array) {
+      if(array.length != 2) {
+        throw "Only 2D points are supported: " + array;
+      }
+      return new ZOO.Geometry.Point(array[0], array[1]);
+    },
+    /**
+     * Method: parseCoords.multipoint
+     * Convert a coordinate array from GeoJSON into an
+     *     <ZOO.Geometry.MultiPoint>.
+     *
+     * Parameters:
+     * array - {Object} The coordinates array from the GeoJSON fragment.
+     *
+     * Returns:
+     * {<ZOO.Geometry.MultiPoint>} A geometry.
+     */
+    "multipoint": function(array) {
+      var points = [];
+      var p = null;
+      for(var i=0, len=array.length; i<len; ++i) {
+        try {
+          p = this.parseCoords["point"].apply(this, [array[i]]);
+        } catch(err) {
+          throw err;
+        }
+        points.push(p);
+      }
+      return new ZOO.Geometry.MultiPoint(points);
+    },
+    /**
+     * Method: parseCoords.linestring
+     * Convert a coordinate array from GeoJSON into an
+     *     <ZOO.Geometry.LineString>.
+     *
+     * Parameters:
+     * array - {Object} The coordinates array from the GeoJSON fragment.
+     *
+     * Returns:
+     * {<ZOO.Geometry.LineString>} A geometry.
+     */
+    "linestring": function(array) {
+      var points = [];
+      var p = null;
+      for(var i=0, len=array.length; i<len; ++i) {
+        try {
+          p = this.parseCoords["point"].apply(this, [array[i]]);
+        } catch(err) {
+          throw err;
+        }
+        points.push(p);
+      }
+      return new ZOO.Geometry.LineString(points);
+    },
+    /**
+     * Method: parseCoords.multilinestring
+     * Convert a coordinate array from GeoJSON into an
+     *     <ZOO.Geometry.MultiLineString>.
+     *
+     * Parameters:
+     * array - {Object} The coordinates array from the GeoJSON fragment.
+     *
+     * Returns:
+     * {<ZOO.Geometry.MultiLineString>} A geometry.
+     */
+    "multilinestring": function(array) {
+      var lines = [];
+      var l = null;
+      for(var i=0, len=array.length; i<len; ++i) {
+        try {
+          l = this.parseCoords["linestring"].apply(this, [array[i]]);
+        } catch(err) {
+          throw err;
+        }
+        lines.push(l);
+      }
+      return new ZOO.Geometry.MultiLineString(lines);
+    },
+    /**
+     * Method: parseCoords.polygon
+     * Convert a coordinate array from GeoJSON into an
+     *     <ZOO.Geometry.Polygon>.
+     *
+     * Parameters:
+     * array - {Object} The coordinates array from the GeoJSON fragment.
+     *
+     * Returns:
+     * {<ZOO.Geometry.Polygon>} A geometry.
+     */
+    "polygon": function(array) {
+      var rings = [];
+      var r, l;
+      for(var i=0, len=array.length; i<len; ++i) {
+        try {
+          l = this.parseCoords["linestring"].apply(this, [array[i]]);
+        } catch(err) {
+          throw err;
+        }
+        r = new ZOO.Geometry.LinearRing(l.components);
+        rings.push(r);
+      }
+      return new ZOO.Geometry.Polygon(rings);
+    },
+    /**
+     * Method: parseCoords.multipolygon
+     * Convert a coordinate array from GeoJSON into an
+     *     <ZOO.Geometry.MultiPolygon>.
+     *
+     * Parameters:
+     * array - {Object} The coordinates array from the GeoJSON fragment.
+     *
+     * Returns:
+     * {<ZOO.Geometry.MultiPolygon>} A geometry.
+     */
+    "multipolygon": function(array) {
+      var polys = [];
+      var p = null;
+      for(var i=0, len=array.length; i<len; ++i) {
+        try {
+          p = this.parseCoords["polygon"].apply(this, [array[i]]);
+        } catch(err) {
+          throw err;
+        }
+        polys.push(p);
+      }
+      return new ZOO.Geometry.MultiPolygon(polys);
+    },
+    /**
+     * Method: parseCoords.box
+     * Convert a coordinate array from GeoJSON into an
+     *     <ZOO.Geometry.Polygon>.
+     *
+     * Parameters:
+     * array - {Object} The coordinates array from the GeoJSON fragment.
+     *
+     * Returns:
+     * {<ZOO.Geometry.Polygon>} A geometry.
+     */
+    "box": function(array) {
+      if(array.length != 2) {
+        throw "GeoJSON box coordinates must have 2 elements";
+      }
+      return new ZOO.Geometry.Polygon([
+          new ZOO.Geometry.LinearRing([
+            new ZOO.Geometry.Point(array[0][0], array[0][1]),
+            new ZOO.Geometry.Point(array[1][0], array[0][1]),
+            new ZOO.Geometry.Point(array[1][0], array[1][1]),
+            new ZOO.Geometry.Point(array[0][0], array[1][1]),
+            new Z0O.Geometry.Point(array[0][0], array[0][1])
+          ])
+      ]);
+    }
+  },
+  /**
+   * Method: write
+   * Serialize a feature, geometry, array of features into a GeoJSON string.
+   *
+   * Parameters:
+   * obj - {Object} An <ZOO.Feature>, <ZOO.Geometry>,
+   *     or an array of features.
+   * pretty - {Boolean} Structure the output with newlines and indentation.
+   *     Default is false.
+   *
+   * Returns:
+   * {String} The GeoJSON string representation of the input geometry,
+   *     features, or array of features.
+   */
+  write: function(obj, pretty) {
+    var geojson = {
+      "type": null
+    };
+    if(obj instanceof Array) {
+      geojson.type = "FeatureCollection";
+      var numFeatures = obj.length;
+      geojson.features = new Array(numFeatures);
+      for(var i=0; i<numFeatures; ++i) {
+        var element = obj[i];
+        if(!element instanceof ZOO.Feature) {
+          var msg = "FeatureCollection only supports collections " +
+            "of features: " + element;
+          throw msg;
+        }
+        geojson.features[i] = this.extract.feature.apply(this, [element]);
+      }
+    } else if (obj.CLASS_NAME.indexOf("ZOO.Geometry") == 0) {
+      geojson = this.extract.geometry.apply(this, [obj]);
+    } else if (obj instanceof ZOO.Feature) {
+      geojson = this.extract.feature.apply(this, [obj]);
+      /*
+      if(obj.layer && obj.layer.projection) {
+        geojson.crs = this.createCRSObject(obj);
+      }
+      */
+    }
+    return ZOO.Format.JSON.prototype.write.apply(this,
+                                                 [geojson, pretty]);
+  },
+  /**
+   * Method: createCRSObject
+   * Create the CRS object for an object.
+   *
+   * Parameters:
+   * object - {<ZOO.Feature>} 
+   *
+   * Returns:
+   * {Object} An object which can be assigned to the crs property
+   * of a GeoJSON object.
+   */
+  createCRSObject: function(object) {
+    //var proj = object.layer.projection.toString();
+    var proj = object.projection.toString();
+    var crs = {};
+    if (proj.match(/epsg:/i)) {
+      var code = parseInt(proj.substring(proj.indexOf(":") + 1));
+      if (code == 4326) {
+        crs = {
+          "type": "OGC",
+          "properties": {
+            "urn": "urn:ogc:def:crs:OGC:1.3:CRS84"
+          }
+        };
+      } else {    
+        crs = {
+          "type": "EPSG",
+          "properties": {
+            "code": code 
+          }
+        };
+      }    
+    }
+    return crs;
+  },
+  /**
+   * Property: extract
+   * Object with properties corresponding to the GeoJSON types.
+   *     Property values are functions that do the actual value extraction.
+   */
+  extract: {
+    /**
+     * Method: extract.feature
+     * Return a partial GeoJSON object representing a single feature.
+     *
+     * Parameters:
+     * feature - {<ZOO.Feature>}
+     *
+     * Returns:
+     * {Object} An object representing the point.
+     */
+    'feature': function(feature) {
+      var geom = this.extract.geometry.apply(this, [feature.geometry]);
+      return {
+        "type": "Feature",
+        "id": feature.fid == null ? feature.id : feature.fid,
+        "properties": feature.attributes,
+        "geometry": geom
+      };
+    },
+    /**
+     * Method: extract.geometry
+     * Return a GeoJSON object representing a single geometry.
+     *
+     * Parameters:
+     * geometry - {<ZOO.Geometry>}
+     *
+     * Returns:
+     * {Object} An object representing the geometry.
+     */
+    'geometry': function(geometry) {
+      if (geometry == null)
+        return null;
+      if (this.internalProjection && this.externalProjection) {
+        geometry = geometry.clone();
+        geometry.transform(this.internalProjection, 
+            this.externalProjection);
+      }                       
+      var geometryType = geometry.CLASS_NAME.split('.')[2];
+      var data = this.extract[geometryType.toLowerCase()].apply(this, [geometry]);
+      var json;
+      if(geometryType == "Collection")
+        json = {
+          "type": "GeometryCollection",
+          "geometries": data
+        };
+      else
+        json = {
+          "type": geometryType,
+          "coordinates": data
+        };
+      return json;
+    },
+    /**
+     * Method: extract.point
+     * Return an array of coordinates from a point.
+     *
+     * Parameters:
+     * point - {<ZOO.Geometry.Point>}
+     *
+     * Returns: 
+     * {Array} An array of coordinates representing the point.
+     */
+    'point': function(point) {
+      return [point.x, point.y];
+    },
+    /**
+     * Method: extract.multipoint
+     * Return an array of coordinates from a multipoint.
+     *
+     * Parameters:
+     * multipoint - {<ZOO.Geometry.MultiPoint>}
+     *
+     * Returns: 
+     * {Array} An array of point coordinate arrays representing
+     *     the multipoint.
+     */
+    'multipoint': function(multipoint) {
+      var array = [];
+      for(var i=0, len=multipoint.components.length; i<len; ++i) {
+        array.push(this.extract.point.apply(this, [multipoint.components[i]]));
+      }
+      return array;
+    },
+    /**
+     * Method: extract.linestring
+     * Return an array of coordinate arrays from a linestring.
+     *
+     * Parameters:
+     * linestring - {<ZOO.Geometry.LineString>}
+     *
+     * Returns:
+     * {Array} An array of coordinate arrays representing
+     *     the linestring.
+     */
+    'linestring': function(linestring) {
+      var array = [];
+      for(var i=0, len=linestring.components.length; i<len; ++i) {
+        array.push(this.extract.point.apply(this, [linestring.components[i]]));
+      }
+      return array;
+    },
+    /**
+     * Method: extract.multilinestring
+     * Return an array of linestring arrays from a linestring.
+     * 
+     * Parameters:
+     * multilinestring - {<ZOO.Geometry.MultiLineString>}
+     * 
+     * Returns:
+     * {Array} An array of linestring arrays representing
+     *     the multilinestring.
+     */
+    'multilinestring': function(multilinestring) {
+      var array = [];
+      for(var i=0, len=multilinestring.components.length; i<len; ++i) {
+        array.push(this.extract.linestring.apply(this, [multilinestring.components[i]]));
+      }
+      return array;
+    },
+    /**
+     * Method: extract.polygon
+     * Return an array of linear ring arrays from a polygon.
+     *
+     * Parameters:
+     * polygon - {<ZOO.Geometry.Polygon>}
+     * 
+     * Returns:
+     * {Array} An array of linear ring arrays representing the polygon.
+     */
+    'polygon': function(polygon) {
+      var array = [];
+      for(var i=0, len=polygon.components.length; i<len; ++i) {
+        array.push(this.extract.linestring.apply(this, [polygon.components[i]]));
+      }
+      return array;
+    },
+    /**
+     * Method: extract.multipolygon
+     * Return an array of polygon arrays from a multipolygon.
+     * 
+     * Parameters:
+     * multipolygon - {<ZOO.Geometry.MultiPolygon>}
+     * 
+     * Returns:
+     * {Array} An array of polygon arrays representing
+     *     the multipolygon
+     */
+    'multipolygon': function(multipolygon) {
+      var array = [];
+      for(var i=0, len=multipolygon.components.length; i<len; ++i) {
+        array.push(this.extract.polygon.apply(this, [multipolygon.components[i]]));
+      }
+      return array;
+    },
+    /**
+     * Method: extract.collection
+     * Return an array of geometries from a geometry collection.
+     * 
+     * Parameters:
+     * collection - {<ZOO.Geometry.Collection>}
+     * 
+     * Returns:
+     * {Array} An array of geometry objects representing the geometry
+     *     collection.
+     */
+    'collection': function(collection) {
+      var len = collection.components.length;
+      var array = new Array(len);
+      for(var i=0; i<len; ++i) {
+        array[i] = this.extract.geometry.apply(
+            this, [collection.components[i]]
+            );
+      }
+      return array;
+    }
+  },
+  CLASS_NAME: 'ZOO.Format.GeoJSON'
+});
+/**
+ * Class: ZOO.Format.KML
+ * Read/Write KML. Create a new instance with the <ZOO.Format.KML>
+ *     constructor. 
+ * 
+ * Inherits from:
+ *  - <ZOO.Format>
+ */
+ZOO.Format.KML = ZOO.Class(ZOO.Format, {
+  /**
+   * Property: kmlns
+   * {String} KML Namespace to use. Defaults to 2.2 namespace.
+   */
+  kmlns: "http://www.opengis.net/kml/2.2",
+  /** 
+   * Property: foldersName
+   * {String} Name of the folders.  Default is "ZOO export".
+   *          If set to null, no name element will be created.
+   */
+  foldersName: "ZOO export",
+  /** 
+   * Property: foldersDesc
+   * {String} Description of the folders. Default is "Exported on [date]."
+   *          If set to null, no description element will be created.
+   */
+  foldersDesc: "Created on " + new Date(),
+  /** 
+   * Property: placemarksDesc
+   * {String} Name of the placemarks.  Default is "No description available".
+   */
+  placemarksDesc: "No description available",
+  /**
+   * Property: extractAttributes
+   * {Boolean} Extract attributes from KML.  Default is true.
+   *           Extracting styleUrls requires this to be set to true
+   */
+  extractAttributes: true,
+  /**
+   * Constructor: ZOO.Format.KML
+   * Create a new parser for KML.
+   *
+   * Parameters:
+   * options - {Object} An optional object whose properties will be set on
+   *     this instance.
+   */
+  initialize: function(options) {
+    // compile regular expressions once instead of every time they are used
+    this.regExes = {
+           trimSpace: (/^\s*|\s*$/g),
+           removeSpace: (/\s*/g),
+           splitSpace: (/\s+/),
+           trimComma: (/\s*,\s*/g),
+           kmlColor: (/(\w{2})(\w{2})(\w{2})(\w{2})/),
+           kmlIconPalette: (/root:\/\/icons\/palette-(\d+)(\.\w+)/),
+           straightBracket: (/\$\[(.*?)\]/g)
+    };
+    // KML coordinates are always in longlat WGS84
+    this.externalProjection = new ZOO.Projection("EPSG:4326");
+    ZOO.Format.prototype.initialize.apply(this, [options]);
+  },
+  /**
+   * APIMethod: read
+   * Read data from a string, and return a list of features. 
+   * 
+   * Parameters: 
+   * data    - {String} data to read/parse.
+   *
+   * Returns:
+   * {Array(<ZOO.Feature>)} List of features.
+   */
+  read: function(data) {
+    this.features = [];
+    data = data.replace(/^<\?xml\s+version\s*=\s*(["'])[^\1]+\1[^?]*\?>/, "");
+    data = new XML(data);
+    var placemarks = data..*::Placemark;
+    this.parseFeatures(placemarks);
+    return this.features;
+  },
+  /**
+   * Method: parseFeatures
+   * Loop through all Placemark nodes and parse them.
+   * Will create a list of features
+   * 
+   * Parameters: 
+   * nodes    - {Array} of {E4XElement} data to read/parse.
+   * options  - {Object} Hash of options
+   * 
+   */
+  parseFeatures: function(nodes) {
+    var features = new Array(nodes.length());
+    for(var i=0, len=nodes.length(); i<len; i++) {
+      var featureNode = nodes[i];
+      var feature = this.parseFeature.apply(this,[featureNode]) ;
+      features[i] = feature;
+    }
+    this.features = this.features.concat(features);
+  },
+  /**
+   * Method: parseFeature
+   * This function is the core of the KML parsing code in ZOO.
+   *     It creates the geometries that are then attached to the returned
+   *     feature, and calls parseAttributes() to get attribute data out.
+   *
+   * Parameters:
+   * node - {E4XElement}
+   *
+   * Returns:
+   * {<ZOO.Feature>} A vector feature.
+   */
+  parseFeature: function(node) {
+    // only accept one geometry per feature - look for highest "order"
+    var order = ["MultiGeometry", "Polygon", "LineString", "Point"];
+    var type, nodeList, geometry, parser;
+    for(var i=0, len=order.length; i<len; ++i) {
+      type = order[i];
+      nodeList = node.descendants(QName(null,type));
+      if (nodeList.length()> 0) {
+        var parser = this.parseGeometry[type.toLowerCase()];
+        if(parser) {
+          geometry = parser.apply(this, [nodeList[0]]);
+          if (this.internalProjection && this.externalProjection) {
+            geometry.transform(this.externalProjection, 
+                               this.internalProjection); 
+          }                       
+        }
+        // stop looking for different geometry types
+        break;
+      }
+    }
+    // construct feature (optionally with attributes)
+    var attributes;
+    if(this.extractAttributes) {
+      attributes = this.parseAttributes(node);
+    }
+    var feature = new ZOO.Feature(geometry, attributes);
+    var fid = node. at id || node. at name;
+    if(fid != null)
+      feature.fid = fid;
+    return feature;
+  },
+  /**
+   * Property: parseGeometry
+   * Properties of this object are the functions that parse geometries based
+   *     on their type.
+   */
+  parseGeometry: {
+    /**
+     * Method: parseGeometry.point
+     * Given a KML node representing a point geometry, create a ZOO
+     *     point geometry.
+     *
+     * Parameters:
+     * node - {E4XElement} A KML Point node.
+     *
+     * Returns:
+     * {<ZOO.Geometry.Point>} A point geometry.
+     */
+    'point': function(node) {
+      var coordString = node.*::coordinates.toString();
+      coordString = coordString.replace(this.regExes.removeSpace, "");
+      coords = coordString.split(",");
+      var point = null;
+      if(coords.length > 1) {
+        // preserve third dimension
+        if(coords.length == 2) {
+          coords[2] = null;
+        }
+        point = new ZOO.Geometry.Point(coords[0], coords[1], coords[2]);
+      }
+      return point;
+    },
+    /**
+     * Method: parseGeometry.linestring
+     * Given a KML node representing a linestring geometry, create a
+     *     ZOO linestring geometry.
+     *
+     * Parameters:
+     * node - {E4XElement} A KML LineString node.
+     *
+     * Returns:
+     * {<ZOO.Geometry.LineString>} A linestring geometry.
+     */
+    'linestring': function(node, ring) {
+      var line = null;
+      var coordString = node.*::coordinates.toString();
+      coordString = coordString.replace(this.regExes.trimSpace,
+          "");
+      coordString = coordString.replace(this.regExes.trimComma,
+          ",");
+      var pointList = coordString.split(this.regExes.splitSpace);
+      var numPoints = pointList.length;
+      var points = new Array(numPoints);
+      var coords, numCoords;
+      for(var i=0; i<numPoints; ++i) {
+        coords = pointList[i].split(",");
+        numCoords = coords.length;
+        if(numCoords > 1) {
+          if(coords.length == 2) {
+            coords[2] = null;
+          }
+          points[i] = new ZOO.Geometry.Point(coords[0],
+                                             coords[1],
+                                             coords[2]);
+        }
+      }
+      if(numPoints) {
+        if(ring) {
+          line = new ZOO.Geometry.LinearRing(points);
+        } else {
+          line = new ZOO.Geometry.LineString(points);
+        }
+      } else {
+        throw "Bad LineString coordinates: " + coordString;
+      }
+      return line;
+    },
+    /**
+     * Method: parseGeometry.polygon
+     * Given a KML node representing a polygon geometry, create a
+     *     ZOO polygon geometry.
+     *
+     * Parameters:
+     * node - {E4XElement} A KML Polygon node.
+     *
+     * Returns:
+     * {<ZOO.Geometry.Polygon>} A polygon geometry.
+     */
+    'polygon': function(node) {
+      var nodeList = node..*::LinearRing;
+      var numRings = nodeList.length();
+      var components = new Array(numRings);
+      if(numRings > 0) {
+        // this assumes exterior ring first, inner rings after
+        var ring;
+        for(var i=0, len=nodeList.length(); i<len; ++i) {
+          ring = this.parseGeometry.linestring.apply(this,
+                                                     [nodeList[i], true]);
+          if(ring) {
+            components[i] = ring;
+          } else {
+            throw "Bad LinearRing geometry: " + i;
+          }
+        }
+      }
+      return new ZOO.Geometry.Polygon(components);
+    },
+    /**
+     * Method: parseGeometry.multigeometry
+     * Given a KML node representing a multigeometry, create a
+     *     ZOO geometry collection.
+     *
+     * Parameters:
+     * node - {E4XElement} A KML MultiGeometry node.
+     *
+     * Returns:
+     * {<ZOO.Geometry.Collection>} A geometry collection.
+     */
+    'multigeometry': function(node) {
+      var child, parser;
+      var parts = [];
+      var children = node.*::*;
+      for(var i=0, len=children.length(); i<len; ++i ) {
+        child = children[i];
+        var type = child.localName();
+        var parser = this.parseGeometry[type.toLowerCase()];
+        if(parser) {
+          parts.push(parser.apply(this, [child]));
+        }
+      }
+      return new ZOO.Geometry.Collection(parts);
+    }
+  },
+  /**
+   * Method: parseAttributes
+   *
+   * Parameters:
+   * node - {E4XElement}
+   *
+   * Returns:
+   * {Object} An attributes object.
+   */
+  parseAttributes: function(node) {
+    var attributes = {};
+    var edNodes = node.*::ExtendedData;
+    if (edNodes.length() > 0) {
+      attributes = this.parseExtendedData(edNodes[0])
+    }
+    var child, grandchildren;
+    var children = node.*::*;
+    for(var i=0, len=children.length(); i<len; ++i) {
+      child = children[i];
+      grandchildren = child..*::*;
+      if(grandchildren.length() == 1) {
+        var name = child.localName();
+        var value = child.toString();
+        if (value) {
+          value = value.replace(this.regExes.trimSpace, "");
+          attributes[name] = value;
+        }
+      }
+    }
+    return attributes;
+  },
+  /**
+   * Method: parseExtendedData
+   * Parse ExtendedData from KML. Limited support for schemas/datatypes.
+   *     See http://code.google.com/apis/kml/documentation/kmlreference.html#extendeddata
+   *     for more information on extendeddata.
+   *
+   * Parameters:
+   * node - {E4XElement}
+   *
+   * Returns:
+   * {Object} An attributes object.
+   */
+  parseExtendedData: function(node) {
+    var attributes = {};
+    var dataNodes = node.*::Data;
+    for (var i = 0, len = dataNodes.length(); i < len; i++) {
+      var data = dataNodes[i];
+      var key = data. at name;
+      var ed = {};
+      var valueNode = data.*::value;
+      if (valueNode.length() > 0)
+        ed['value'] = valueNode[0].toString();
+      var nameNode = data.*::displayName;
+      if (nameNode.length() > 0)
+        ed['displayName'] = valueNode[0].toString();
+      attributes[key] = ed;
+    }
+    return attributes;
+  },
+  /**
+   * Method: write
+   * Accept Feature Collection, and return a string. 
+   * 
+   * Parameters:
+   * features - {Array(<ZOO.Feature>} An array of features.
+   *
+   * Returns:
+   * {String} A KML string.
+   */
+  write: function(features) {
+    if(!(features instanceof Array))
+      features = [features];
+    var kml = new XML('<kml xmlns="'+this.kmlns+'"></kml>');
+    var folder = kml.Document.Folder;
+    folder.name = this.foldersName;
+    folder.description = this.foldersDesc;
+    for(var i=0, len=features.length; i<len; ++i) {
+      folder.Placemark[i] = this.createPlacemark(features[i]);
+    }
+    return kml.toXMLString();
+  },
+  /**
+   * Method: createPlacemark
+   * Creates and returns a KML placemark node representing the given feature. 
+   * 
+   * Parameters:
+   * feature - {<ZOO.Feature>}
+   * 
+   * Returns:
+   * {E4XElement}
+   */
+  createPlacemark: function(feature) {
+    var placemark = new XML('<Placemark xmlns="'+this.kmlns+'"></Placemark>');
+    placemark.name = (feature.attributes.name) ?
+                    feature.attributes.name : feature.id;
+    placemark.description = (feature.attributes.description) ?
+                             feature.attributes.description : this.placemarksDesc;
+    if(feature.fid != null)
+      placemark. at id = feature.fid;
+    placemark.*[2] = this.buildGeometryNode(feature.geometry);
+    return placemark;
+  },
+  /**
+   * Method: buildGeometryNode
+   * Builds and returns a KML geometry node with the given geometry.
+   * 
+   * Parameters:
+   * geometry - {<ZOO.Geometry>}
+   * 
+   * Returns:
+   * {E4XElement}
+   */
+  buildGeometryNode: function(geometry) {
+    if (this.internalProjection && this.externalProjection) {
+      geometry = geometry.clone();
+      geometry.transform(this.internalProjection, 
+                         this.externalProjection);
+    }
+    var className = geometry.CLASS_NAME;
+    var type = className.substring(className.lastIndexOf(".") + 1);
+    var builder = this.buildGeometry[type.toLowerCase()];
+    var node = null;
+    if(builder) {
+      node = builder.apply(this, [geometry]);
+    }
+    return node;
+  },
+  /**
+   * Property: buildGeometry
+   * Object containing methods to do the actual geometry node building
+   *     based on geometry type.
+   */
+  buildGeometry: {
+    /**
+     * Method: buildGeometry.point
+     * Given a ZOO point geometry, create a KML point.
+     *
+     * Parameters:
+     * geometry - {<ZOO.Geometry.Point>} A point geometry.
+     *
+     * Returns:
+     * {E4XElement} A KML point node.
+     */
+    'point': function(geometry) {
+      var kml = new XML('<Point xmlns="'+this.kmlns+'"></Point>');
+      kml.coordinates = this.buildCoordinatesNode(geometry);
+      return kml;
+    },
+    /**
+     * Method: buildGeometry.multipoint
+     * Given a ZOO multipoint geometry, create a KML
+     *     GeometryCollection.
+     *
+     * Parameters:
+     * geometry - {<ZOO.Geometry.MultiPoint>} A multipoint geometry.
+     *
+     * Returns:
+     * {E4XElement} A KML GeometryCollection node.
+     */
+    'multipoint': function(geometry) {
+      return this.buildGeometry.collection.apply(this, [geometry]);
+    },
+    /**
+     * Method: buildGeometry.linestring
+     * Given a ZOO linestring geometry, create a KML linestring.
+     *
+     * Parameters:
+     * geometry - {<ZOO.Geometry.LineString>} A linestring geometry.
+     *
+     * Returns:
+     * {E4XElement} A KML linestring node.
+     */
+    'linestring': function(geometry) {
+      var kml = new XML('<LineString xmlns="'+this.kmlns+'"></LineString>');
+      kml.coordinates = this.buildCoordinatesNode(geometry);
+      return kml;
+    },
+    /**
+     * Method: buildGeometry.multilinestring
+     * Given a ZOO multilinestring geometry, create a KML
+     *     GeometryCollection.
+     *
+     * Parameters:
+     * geometry - {<ZOO.Geometry.MultiLineString>} A multilinestring geometry.
+     *
+     * Returns:
+     * {E4XElement} A KML GeometryCollection node.
+     */
+    'multilinestring': function(geometry) {
+      return this.buildGeometry.collection.apply(this, [geometry]);
+    },
+    /**
+     * Method: buildGeometry.linearring
+     * Given a ZOO linearring geometry, create a KML linearring.
+     *
+     * Parameters:
+     * geometry - {<ZOO.Geometry.LinearRing>} A linearring geometry.
+     *
+     * Returns:
+     * {E4XElement} A KML linearring node.
+     */
+    'linearring': function(geometry) {
+      var kml = new XML('<LinearRing xmlns="'+this.kmlns+'"></LinearRing>');
+      kml.coordinates = this.buildCoordinatesNode(geometry);
+      return kml;
+    },
+    /**
+     * Method: buildGeometry.polygon
+     * Given a ZOO polygon geometry, create a KML polygon.
+     *
+     * Parameters:
+     * geometry - {<ZOO.Geometry.Polygon>} A polygon geometry.
+     *
+     * Returns:
+     * {E4XElement} A KML polygon node.
+     */
+    'polygon': function(geometry) {
+      var kml = new XML('<Polygon xmlns="'+this.kmlns+'"></Polygon>');
+      var rings = geometry.components;
+      var ringMember, ringGeom, type;
+      for(var i=0, len=rings.length; i<len; ++i) {
+        type = (i==0) ? "outerBoundaryIs" : "innerBoundaryIs";
+        ringMember = new XML('<'+type+' xmlns="'+this.kmlns+'"></'+type+'>');
+        ringMember.LinearRing = this.buildGeometry.linearring.apply(this,[rings[i]]);
+        kml.*[i] = ringMember;
+      }
+      return kml;
+    },
+    /**
+     * Method: buildGeometry.multipolygon
+     * Given a ZOO multipolygon geometry, create a KML
+     *     GeometryCollection.
+     *
+     * Parameters:
+     * geometry - {<ZOO.Geometry.Point>} A multipolygon geometry.
+     *
+     * Returns:
+     * {E4XElement} A KML GeometryCollection node.
+     */
+    'multipolygon': function(geometry) {
+      return this.buildGeometry.collection.apply(this, [geometry]);
+    },
+    /**
+     * Method: buildGeometry.collection
+     * Given a ZOO geometry collection, create a KML MultiGeometry.
+     *
+     * Parameters:
+     * geometry - {<ZOO.Geometry.Collection>} A geometry collection.
+     *
+     * Returns:
+     * {E4XElement} A KML MultiGeometry node.
+     */
+    'collection': function(geometry) {
+      var kml = new XML('<MultiGeometry xmlns="'+this.kmlns+'"></MultiGeometry>');
+      var child;
+      for(var i=0, len=geometry.components.length; i<len; ++i) {
+        kml.*[i] = this.buildGeometryNode.apply(this,[geometry.components[i]]);
+      }
+      return kml;
+    }
+  },
+  /**
+   * Method: buildCoordinatesNode
+   * Builds and returns the KML coordinates node with the given geometry
+   *     <coordinates>...</coordinates>
+   * 
+   * Parameters:
+   * geometry - {<ZOO.Geometry>}
+   * 
+   * Return:
+   * {E4XElement}
+   */
+  buildCoordinatesNode: function(geometry) {
+    var cooridnates = new XML('<coordinates xmlns="'+this.kmlns+'"></coordinates>');
+    var points = geometry.components;
+    if(points) {
+      // LineString or LinearRing
+      var point;
+      var numPoints = points.length;
+      var parts = new Array(numPoints);
+      for(var i=0; i<numPoints; ++i) {
+        point = points[i];
+        parts[i] = point.x + "," + point.y;
+      }
+      coordinates = parts.join(" ");
+    } else {
+      // Point
+      coordinates = geometry.x + "," + geometry.y;
+    }
+    return coordinates;
+  },
+  CLASS_NAME: 'ZOO.Format.KML'
+});
+/**
+ * Class: ZOO.Format.GML
+ * Read/Write GML. Create a new instance with the <ZOO.Format.GML>
+ *     constructor.  Supports the GML simple features profile.
+ * 
+ * Inherits from:
+ *  - <ZOO.Format>
+ */
+ZOO.Format.GML = ZOO.Class(ZOO.Format, {
+  /**
+   * Property: schemaLocation
+   * {String} Schema location for a particular minor version.
+   */
+  schemaLocation: "http://www.opengis.net/gml http://schemas.opengis.net/gml/2.1.2/feature.xsd",
+  /**
+   * Property: namespaces
+   * {Object} Mapping of namespace aliases to namespace URIs.
+   */
+  namespaces: {
+    ogr: "http://ogr.maptools.org/",
+    gml: "http://www.opengis.net/gml",
+    xlink: "http://www.w3.org/1999/xlink",
+    xsi: "http://www.w3.org/2001/XMLSchema-instance",
+    wfs: "http://www.opengis.net/wfs" // this is a convenience for reading wfs:FeatureCollection
+  },
+  /**
+   * Property: defaultPrefix
+   */
+  defaultPrefix: 'ogr',
+  /** 
+   * Property: collectionName
+   * {String} Name of featureCollection element.
+   */
+  collectionName: "FeatureCollection",
+  /*
+   * Property: featureName
+   * {String} Element name for features. Default is "sql_statement".
+   */
+  featureName: "sql_statement",
+  /**
+   * Property: geometryName
+   * {String} Name of geometry element.  Defaults to "geometryProperty".
+   */
+  geometryName: "geometryProperty",
+  /**
+   * Property: xy
+   * {Boolean} Order of the GML coordinate true:(x,y) or false:(y,x)
+   * Changing is not recommended, a new Format should be instantiated.
+   */
+  xy: true,
+  /**
+   * Property: extractAttributes
+   * {Boolean} Could we extract attributes
+   */
+  extractAttributes: true,
+  /**
+   * Constructor: ZOO.Format.GML
+   * Create a new parser for GML.
+   *
+   * Parameters:
+   * options - {Object} An optional object whose properties will be set on
+   *     this instance.
+   */
+  initialize: function(options) {
+    // compile regular expressions once instead of every time they are used
+    this.regExes = {
+      trimSpace: (/^\s*|\s*$/g),
+      removeSpace: (/\s*/g),
+      splitSpace: (/\s+/),
+      trimComma: (/\s*,\s*/g)
+    };
+    ZOO.Format.prototype.initialize.apply(this, [options]);
+  },
+  /**
+   * Method: read
+   * Read data from a string, and return a list of features. 
+   * 
+   * Parameters:
+   * data - {String} data to read/parse.
+   *
+   * Returns:
+   * {Array(<ZOO.Feature>)} An array of features.
+   */
+  read: function(data) {
+    this.features = [];
+    data = data.replace(/^<\?xml\s+version\s*=\s*(["'])[^\1]+\1[^?]*\?>/, "");
+    data = new XML(data);
+
+    var gmlns = Namespace(this.namespaces['gml']);
+    var featureNodes = data..gmlns::featureMember;
+    if (data.localName() == 'featureMember')
+      featureNodes = data;
+    var features = [];
+    for(var i=0,len=featureNodes.length(); i<len; i++) {
+      var feature = this.parseFeature(featureNodes[i]);
+      if(feature) {
+        features.push(feature);
+      }
+    }
+    return features;
+  },
+  /**
+   * Method: parseFeature
+   * This function is the core of the GML parsing code in ZOO.
+   *    It creates the geometries that are then attached to the returned
+   *    feature, and calls parseAttributes() to get attribute data out.
+   *    
+   * Parameters:
+   * node - {E4XElement} A GML feature node. 
+   */
+  parseFeature: function(node) {
+    // only accept one geometry per feature - look for highest "order"
+    var gmlns = Namespace(this.namespaces['gml']);
+    var order = ["MultiPolygon", "Polygon",
+                 "MultiLineString", "LineString",
+                 "MultiPoint", "Point", "Envelope", "Box"];
+    var type, nodeList, geometry, parser;
+    for(var i=0; i<order.length; ++i) {
+      type = order[i];
+      nodeList = node.descendants(QName(gmlns,type));
+      if (nodeList.length() > 0) {
+        var parser = this.parseGeometry[type.toLowerCase()];
+        if(parser) {
+          geometry = parser.apply(this, [nodeList[0]]);
+          if (this.internalProjection && this.externalProjection) {
+            geometry.transform(this.externalProjection, 
+                               this.internalProjection); 
+          }                       
+        }
+        // stop looking for different geometry types
+        break;
+      }
+    }
+    var attributes;
+    if(this.extractAttributes) {
+      attributes = this.parseAttributes(node);
+    }
+    var feature = new ZOO.Feature(geometry, attributes);
+    return feature;
+  },
+  /**
+   * Property: parseGeometry
+   * Properties of this object are the functions that parse geometries based
+   *     on their type.
+   */
+  parseGeometry: {
+    /**
+     * Method: parseGeometry.point
+     * Given a GML node representing a point geometry, create a ZOO
+     *     point geometry.
+     *
+     * Parameters:
+     * node - {E4XElement} A GML node.
+     *
+     * Returns:
+     * {<ZOO.Geometry.Point>} A point geometry.
+     */
+    'point': function(node) {
+      /**
+       * Three coordinate variations to consider:
+       * 1) <gml:pos>x y z</gml:pos>
+       * 2) <gml:coordinates>x, y, z</gml:coordinates>
+       * 3) <gml:coord><gml:X>x</gml:X><gml:Y>y</gml:Y></gml:coord>
+       */
+      var nodeList, coordString;
+      var coords = [];
+      // look for <gml:pos>
+      var nodeList = node..*::pos;
+      if(nodeList.length() > 0) {
+        coordString = nodeList[0].toString();
+        coordString = coordString.replace(this.regExes.trimSpace, "");
+        coords = coordString.split(this.regExes.splitSpace);
+      }
+      // look for <gml:coordinates>
+      if(coords.length == 0) {
+        nodeList = node..*::coordinates;
+        if(nodeList.length() > 0) {
+          coordString = nodeList[0].toString();
+          coordString = coordString.replace(this.regExes.removeSpace,"");
+          coords = coordString.split(",");
+        }
+      }
+      // look for <gml:coord>
+      if(coords.length == 0) {
+        nodeList = node..*::coord;
+        if(nodeList.length() > 0) {
+          var xList = nodeList[0].*::X;
+          var yList = nodeList[0].*::Y;
+          if(xList.length() > 0 && yList.length() > 0)
+            coords = [xList[0].toString(),
+                      yList[0].toString()];
+        }
+      }
+      // preserve third dimension
+      if(coords.length == 2)
+        coords[2] = null;
+      if (this.xy)
+        return new ZOO.Geometry.Point(coords[0],coords[1],coords[2]);
+      else
+        return new ZOO.Geometry.Point(coords[1],coords[0],coords[2]);
+    },
+    /**
+     * Method: parseGeometry.multipoint
+     * Given a GML node representing a multipoint geometry, create a
+     *     ZOO multipoint geometry.
+     *
+     * Parameters:
+     * node - {E4XElement} A GML node.
+     *
+     * Returns:
+     * {<ZOO.Geometry.MultiPoint>} A multipoint geometry.
+     */
+    'multipoint': function(node) {
+      var nodeList = node..*::Point;
+      var components = [];
+      if(nodeList.length() > 0) {
+        var point;
+        for(var i=0, len=nodeList.length(); i<len; ++i) {
+          point = this.parseGeometry.point.apply(this, [nodeList[i]]);
+          if(point)
+            components.push(point);
+        }
+      }
+      return new ZOO.Geometry.MultiPoint(components);
+    },
+    /**
+     * Method: parseGeometry.linestring
+     * Given a GML node representing a linestring geometry, create a
+     *     ZOO linestring geometry.
+     *
+     * Parameters:
+     * node - {E4XElement} A GML node.
+     *
+     * Returns:
+     * {<ZOO.Geometry.LineString>} A linestring geometry.
+     */
+    'linestring': function(node, ring) {
+      /**
+       * Two coordinate variations to consider:
+       * 1) <gml:posList dimension="d">x0 y0 z0 x1 y1 z1</gml:posList>
+       * 2) <gml:coordinates>x0, y0, z0 x1, y1, z1</gml:coordinates>
+       */
+      var nodeList, coordString;
+      var coords = [];
+      var points = [];
+      // look for <gml:posList>
+      nodeList = node..*::posList;
+      if(nodeList.length() > 0) {
+        coordString = nodeList[0].toString();
+        coordString = coordString.replace(this.regExes.trimSpace, "");
+        coords = coordString.split(this.regExes.splitSpace);
+        var dim = parseInt(nodeList[0]. at dimension);
+        var j, x, y, z;
+        for(var i=0; i<coords.length/dim; ++i) {
+          j = i * dim;
+          x = coords[j];
+          y = coords[j+1];
+          z = (dim == 2) ? null : coords[j+2];
+          if (this.xy)
+            points.push(new ZOO.Geometry.Point(x, y, z));
+          else
+            points.push(new Z0O.Geometry.Point(y, x, z));
+        }
+      }
+      // look for <gml:coordinates>
+      if(coords.length == 0) {
+        nodeList = node..*::coordinates;
+        if(nodeList.length() > 0) {
+          coordString = nodeList[0].toString();
+          coordString = coordString.replace(this.regExes.trimSpace,"");
+          coordString = coordString.replace(this.regExes.trimComma,",");
+          var pointList = coordString.split(this.regExes.splitSpace);
+          for(var i=0; i<pointList.length; ++i) {
+            coords = pointList[i].split(",");
+            if(coords.length == 2)
+              coords[2] = null;
+            if (this.xy)
+              points.push(new ZOO.Geometry.Point(coords[0],coords[1],coords[2]));
+            else
+              points.push(new ZOO.Geometry.Point(coords[1],coords[0],coords[2]));
+          }
+        }
+      }
+      var line = null;
+      if(points.length != 0) {
+        if(ring)
+          line = new ZOO.Geometry.LinearRing(points);
+        else
+          line = new ZOO.Geometry.LineString(points);
+      }
+      return line;
+    },
+    /**
+     * Method: parseGeometry.multilinestring
+     * Given a GML node representing a multilinestring geometry, create a
+     *     ZOO multilinestring geometry.
+     *
+     * Parameters:
+     * node - {E4XElement} A GML node.
+     *
+     * Returns:
+     * {<ZOO.Geometry.MultiLineString>} A multilinestring geometry.
+     */
+    'multilinestring': function(node) {
+      var nodeList = node..*::LineString;
+      var components = [];
+      if(nodeList.length() > 0) {
+        var line;
+        for(var i=0, len=nodeList.length(); i<len; ++i) {
+          line = this.parseGeometry.linestring.apply(this, [nodeList[i]]);
+          if(point)
+            components.push(point);
+        }
+      }
+      return new ZOO.Geometry.MultiLineString(components);
+    },
+    /**
+     * Method: parseGeometry.polygon
+     * Given a GML node representing a polygon geometry, create a
+     *     ZOO polygon geometry.
+     *
+     * Parameters:
+     * node - {E4XElement} A GML node.
+     *
+     * Returns:
+     * {<ZOO.Geometry.Polygon>} A polygon geometry.
+     */
+    'polygon': function(node) {
+      nodeList = node..*::LinearRing;
+      var components = [];
+      if(nodeList.length() > 0) {
+        // this assumes exterior ring first, inner rings after
+        var ring;
+        for(var i=0, len = nodeList.length(); i<len; ++i) {
+          ring = this.parseGeometry.linestring.apply(this,[nodeList[i], true]);
+          if(ring)
+            components.push(ring);
+        }
+      }
+      return new ZOO.Geometry.Polygon(components);
+    },
+    /**
+     * Method: parseGeometry.multipolygon
+     * Given a GML node representing a multipolygon geometry, create a
+     *     ZOO multipolygon geometry.
+     *
+     * Parameters:
+     * node - {E4XElement} A GML node.
+     *
+     * Returns:
+     * {<ZOO.Geometry.MultiPolygon>} A multipolygon geometry.
+     */
+    'multipolygon': function(node) {
+      var nodeList = node..*::Polygon;
+      var components = [];
+      if(nodeList.length() > 0) {
+        var polygon;
+        for(var i=0, len=nodeList.length(); i<len; ++i) {
+          polygon = this.parseGeometry.polygon.apply(this, [nodeList[i]]);
+          if(polygon)
+            components.push(polygon);
+        }
+      }
+      return new ZOO.Geometry.MultiPolygon(components);
+    },
+    /**
+     * Method: parseGeometry.envelope
+     * Given a GML node representing an envelope, create a
+     *     ZOO polygon geometry.
+     *
+     * Parameters:
+     * node - {E4XElement} A GML node.
+     *
+     * Returns:
+     * {<ZOO.Geometry.Polygon>} A polygon geometry.
+     */
+    'envelope': function(node) {
+      var components = [];
+      var coordString;
+      var envelope;
+      var lpoint = node..*::lowerCorner;
+      if (lpoint.length() > 0) {
+        var coords = [];
+        if(lpoint.length() > 0) {
+          coordString = lpoint[0].toString();
+          coordString = coordString.replace(this.regExes.trimSpace, "");
+          coords = coordString.split(this.regExes.splitSpace);
+        }
+        if(coords.length == 2)
+          coords[2] = null;
+        if (this.xy)
+          var lowerPoint = new ZOO.Geometry.Point(coords[0], coords[1],coords[2]);
+        else
+          var lowerPoint = new ZOO.Geometry.Point(coords[1], coords[0],coords[2]);
+      }
+      var upoint = node..*::upperCorner;
+      if (upoint.length() > 0) {
+        var coords = [];
+        if(upoint.length > 0) {
+          coordString = upoint[0].toString();
+          coordString = coordString.replace(this.regExes.trimSpace, "");
+          coords = coordString.split(this.regExes.splitSpace);
+        }
+        if(coords.length == 2)
+          coords[2] = null;
+        if (this.xy)
+          var upperPoint = new ZOO.Geometry.Point(coords[0], coords[1],coords[2]);
+        else
+          var upperPoint = new ZOO.Geometry.Point(coords[1], coords[0],coords[2]);
+      }
+      if (lowerPoint && upperPoint) {
+        components.push(new ZOO.Geometry.Point(lowerPoint.x, lowerPoint.y));
+        components.push(new ZOO.Geometry.Point(upperPoint.x, lowerPoint.y));
+        components.push(new ZOO.Geometry.Point(upperPoint.x, upperPoint.y));
+        components.push(new ZOO.Geometry.Point(lowerPoint.x, upperPoint.y));
+        components.push(new ZOO.Geometry.Point(lowerPoint.x, lowerPoint.y));
+        var ring = new ZOO.Geometry.LinearRing(components);
+        envelope = new ZOO.Geometry.Polygon([ring]);
+      }
+      return envelope;
+    }
+  },
+  /**
+   * Method: parseAttributes
+   *
+   * Parameters:
+   * node - {<E4XElement>}
+   *
+   * Returns:
+   * {Object} An attributes object.
+   */
+  parseAttributes: function(node) {
+    var attributes = {};
+    // assume attributes are children of the first type 1 child
+    var childNode = node.*::*[0];
+    var child, grandchildren;
+    var children = childNode.*::*;
+    for(var i=0, len=children.length(); i<len; ++i) {
+      child = children[i];
+      grandchildren = child..*::*;
+      if(grandchildren.length() == 1) {
+        var name = child.localName();
+        var value = child.toString();
+        if (value) {
+          value = value.replace(this.regExes.trimSpace, "");
+          attributes[name] = value;
+        } else
+          attributes[name] = null;
+      }
+    }
+    return attributes;
+  },
+  /**
+   * Method: write
+   * Generate a GML document string given a list of features. 
+   * 
+   * Parameters:
+   * features - {Array(<ZOO.Feature>)} List of features to
+   *     serialize into a string.
+   *
+   * Returns:
+   * {String} A string representing the GML document.
+   */
+  write: function(features) {
+    if(!(features instanceof Array)) {
+      features = [features];
+    }
+    var pfx = this.defaultPrefix;
+    var name = pfx+':'+this.collectionName;
+    var gml = new XML('<'+name+' xmlns:'+pfx+'="'+this.namespaces[pfx]+'" xmlns:gml="'+this.namespaces['gml']+'" xmlns:xsi="'+this.namespaces['xsi']+'" xsi:schemaLocation="'+this.schemaLocation+'"></'+name+'>');
+    for(var i=0; i<features.length; i++) {
+      gml.*::*[i] = this.createFeature(features[i]);
+    }
+    return gml.toXMLString();
+  },
+  /** 
+   * Method: createFeature
+   * Accept an ZOO.Feature, and build a GML node for it.
+   *
+   * Parameters:
+   * feature - {<ZOO.Feature>} The feature to be built as GML.
+   *
+   * Returns:
+   * {E4XElement} A node reprensting the feature in GML.
+   */
+  createFeature: function(feature) {
+    var pfx = this.defaultPrefix;
+    var name = pfx+':'+this.featureName;
+    var fid = feature.fid || feature.id;
+    var gml = new XML('<gml:featureMember xmlns:gml="'+this.namespaces['gml']+'"><'+name+' xmlns:'+pfx+'="'+this.namespaces[pfx]+'" fid="'+fid+'"></'+name+'></gml:featureMember>');
+    var geometry = feature.geometry;
+    gml.*::*[0].*::* = this.buildGeometryNode(geometry);
+    for(var attr in feature.attributes) {
+      var attrNode = new XML('<'+pfx+':'+attr+' xmlns:'+pfx+'="'+this.namespaces[pfx]+'">'+feature.attributes[attr]+'</'+pfx+':'+attr+'>');
+      gml.*::*[0].appendChild(attrNode);
+    }
+    return gml;
+  },
+  /**
+   * Method: buildGeometryNode
+   *
+   * Parameters:
+   * geometry - {<ZOO.Geometry>} The geometry to be built as GML.
+   *
+   * Returns:
+   * {E4XElement} A node reprensting the geometry in GML.
+   */
+  buildGeometryNode: function(geometry) {
+    if (this.externalProjection && this.internalProjection) {
+      geometry = geometry.clone();
+      geometry.transform(this.internalProjection, 
+          this.externalProjection);
+    }    
+    var className = geometry.CLASS_NAME;
+    var type = className.substring(className.lastIndexOf(".") + 1);
+    var builder = this.buildGeometry[type.toLowerCase()];
+    var pfx = this.defaultPrefix;
+    var name = pfx+':'+this.geometryName;
+    var gml = new XML('<'+name+' xmlns:'+pfx+'="'+this.namespaces[pfx]+'"></'+name+'>');
+    if (builder)
+      gml.*::* = builder.apply(this, [geometry]);
+    return gml;
+  },
+  /**
+   * Property: buildGeometry
+   * Object containing methods to do the actual geometry node building
+   *     based on geometry type.
+   */
+  buildGeometry: {
+    /**
+     * Method: buildGeometry.point
+     * Given a ZOO point geometry, create a GML point.
+     *
+     * Parameters:
+     * geometry - {<ZOO.Geometry.Point>} A point geometry.
+     *
+     * Returns:
+     * {E4XElement} A GML point node.
+     */
+    'point': function(geometry) {
+      var gml = new XML('<gml:Point xmlns:gml="'+this.namespaces['gml']+'"></gml:Point>');
+      gml.*::*[0] = this.buildCoordinatesNode(geometry);
+      return gml;
+    },
+    /**
+     * Method: buildGeometry.multipoint
+     * Given a ZOO multipoint geometry, create a GML multipoint.
+     *
+     * Parameters:
+     * geometry - {<ZOO.Geometry.MultiPoint>} A multipoint geometry.
+     *
+     * Returns:
+     * {E4XElement} A GML multipoint node.
+     */
+    'multipoint': function(geometry) {
+      var gml = new XML('<gml:MultiPoint xmlns:gml="'+this.namespaces['gml']+'"></gml:MultiPoint>');
+      var points = geometry.components;
+      var pointMember;
+      for(var i=0; i<points.length; i++) { 
+        pointMember = new XML('<gml:pointMember xmlns:gml="'+this.namespaces['gml']+'"></gml:pointMember>');
+        pointMember.*::* = this.buildGeometry.point.apply(this,[points[i]]);
+        gml.*::*[i] = pointMember;
+      }
+      return gml;            
+    },
+    /**
+     * Method: buildGeometry.linestring
+     * Given a ZOO linestring geometry, create a GML linestring.
+     *
+     * Parameters:
+     * geometry - {<ZOO.Geometry.LineString>} A linestring geometry.
+     *
+     * Returns:
+     * {E4XElement} A GML linestring node.
+     */
+    'linestring': function(geometry) {
+      var gml = new XML('<gml:LineString xmlns:gml="'+this.namespaces['gml']+'"></gml:LineString>');
+      gml.*::*[0] = this.buildCoordinatesNode(geometry);
+      return gml;
+    },
+    /**
+     * Method: buildGeometry.multilinestring
+     * Given a ZOO multilinestring geometry, create a GML
+     *     multilinestring.
+     *
+     * Parameters:
+     * geometry - {<ZOO.Geometry.MultiLineString>} A multilinestring
+     *     geometry.
+     *
+     * Returns:
+     * {E4XElement} A GML multilinestring node.
+     */
+    'multilinestring': function(geometry) {
+      var gml = new XML('<gml:MultiLineString xmlns:gml="'+this.namespaces['gml']+'"></gml:MultiLineString>');
+      var lines = geometry.components;
+      var lineMember;
+      for(var i=0; i<lines.length; i++) { 
+        lineMember = new XML('<gml:lineStringMember xmlns:gml="'+this.namespaces['gml']+'"></gml:lineStringMember>');
+        lineMember.*::* = this.buildGeometry.linestring.apply(this,[lines[i]]);
+        gml.*::*[i] = lineMember;
+      }
+      return gml;            
+    },
+    /**
+     * Method: buildGeometry.linearring
+     * Given a ZOO linearring geometry, create a GML linearring.
+     *
+     * Parameters:
+     * geometry - {<ZOO.Geometry.LinearRing>} A linearring geometry.
+     *
+     * Returns:
+     * {E4XElement} A GML linearring node.
+     */
+    'linearring': function(geometry) {
+      var gml = new XML('<gml:LinearRing xmlns:gml="'+this.namespaces['gml']+'"></gml:LinearRing>');
+      gml.*::*[0] = this.buildCoordinatesNode(geometry);
+      return gml;
+    },
+    /**
+     * Method: buildGeometry.polygon
+     * Given an ZOO polygon geometry, create a GML polygon.
+     *
+     * Parameters:
+     * geometry - {<ZOO.Geometry.Polygon>} A polygon geometry.
+     *
+     * Returns:
+     * {E4XElement} A GML polygon node.
+     */
+    'polygon': function(geometry) {
+      var gml = new XML('<gml:Polygon xmlns:gml="'+this.namespaces['gml']+'"></gml:Polygon>');
+      var rings = geometry.components;
+      var ringMember, type;
+      for(var i=0; i<rings.length; ++i) {
+        type = (i==0) ? "outerBoundaryIs" : "innerBoundaryIs";
+        var ringMember = new XML('<gml:'+type+' xmlns:gml="'+this.namespaces['gml']+'"></gml:'+type+'>');
+        ringMember.*::* = this.buildGeometry.linearring.apply(this,[rings[i]]);
+        gml.*::*[i] = ringMember;
+      }
+      return gml;
+    },
+    /**
+     * Method: buildGeometry.multipolygon
+     * Given a ZOO multipolygon geometry, create a GML multipolygon.
+     *
+     * Parameters:
+     * geometry - {<ZOO.Geometry.MultiPolygon>} A multipolygon
+     *     geometry.
+     *
+     * Returns:
+     * {E4XElement} A GML multipolygon node.
+     */
+    'multipolygon': function(geometry) {
+      var gml = new XML('<gml:MultiPolygon xmlns:gml="'+this.namespaces['gml']+'"></gml:MultiPolygon>');
+      var polys = geometry.components;
+      var polyMember;
+      for(var i=0; i<polys.length; i++) { 
+        polyMember = new XML('<gml:polygonMember xmlns:gml="'+this.namespaces['gml']+'"></gml:polygonMember>');
+        polyMember.*::* = this.buildGeometry.polygon.apply(this,[polys[i]]);
+        gml.*::*[i] = polyMember;
+      }
+      return gml;            
+    }
+  },
+  /**
+   * Method: buildCoordinatesNode
+   * builds the coordinates XmlNode
+   * (code)
+   * <gml:coordinates decimal="." cs="," ts=" ">...</gml:coordinates>
+   * (end)
+   * Parameters: 
+   * geometry - {<ZOO.Geometry>} 
+   *
+   * Returns:
+   * {E4XElement} created E4XElement
+   */
+  buildCoordinatesNode: function(geometry) {
+    var parts = [];
+    if(geometry instanceof ZOO.Bounds){
+      parts.push(geometry.left + "," + geometry.bottom);
+      parts.push(geometry.right + "," + geometry.top);
+    } else {
+      var points = (geometry.components) ? geometry.components : [geometry];
+      for(var i=0; i<points.length; i++) {
+        parts.push(points[i].x + "," + points[i].y);                
+      }            
+    }
+    return new XML('<gml:coordinates xmlns:gml="'+this.namespaces['gml']+'" decimal="." cs=", " ts=" ">'+parts.join(" ")+'</gml:coordinates>');
+  },
+  CLASS_NAME: 'ZOO.Format.GML'
+});
+/**
+ * Class: ZOO.Format.WPS
+ * Read/Write WPS. Create a new instance with the <ZOO.Format.WPS>
+ *     constructor. Supports only parseExecuteResponse.
+ * 
+ * Inherits from:
+ *  - <ZOO.Format>
+ */
+ZOO.Format.WPS = ZOO.Class(ZOO.Format, {
+  /**
+   * Property: schemaLocation
+   * {String} Schema location for a particular minor version.
+   */
+  schemaLocation: "http://www.opengis.net/wps/1.0.0/../wpsExecute_request.xsd",
+  /**
+   * Property: namespaces
+   * {Object} Mapping of namespace aliases to namespace URIs.
+   */
+  namespaces: {
+    ows: "http://www.opengis.net/ows/1.1",
+    wps: "http://www.opengis.net/wps/1.0.0",
+    xlink: "http://www.w3.org/1999/xlink",
+    xsi: "http://www.w3.org/2001/XMLSchema-instance",
+  },
+  /**
+   * Method: read
+   *
+   * Parameters:
+   * data - {String} A WPS xml document
+   *
+   * Returns:
+   * {Object} Execute response.
+   */
+  read:function(data) {
+    data = data.replace(/^<\?xml\s+version\s*=\s*(["'])[^\1]+\1[^?]*\?>/, "");
+    data = new XML(data);
+    switch (data.localName()) {
+      case 'ExecuteResponse':
+        return this.parseExecuteResponse(data);
+      default:
+        return null;
+    }
+  },
+  /**
+   * Method: parseExecuteResponse
+   *
+   * Parameters:
+   * node - {E4XElement} A WPS ExecuteResponse document
+   *
+   * Returns:
+   * {Object} Execute response.
+   */
+  parseExecuteResponse: function(node) {
+    var outputs = node.*::ProcessOutputs.*::Output;
+    if (outputs.length() > 0) {
+      var res=[];
+      for(var i=0;i<outputs.length();i++){
+        var data = outputs[i].*::Data.*::*[0];
+	if(!data){
+          data = outputs[i].*::Reference;
+	}
+	var builder = this.parseData[data.localName().toLowerCase()];
+	if (builder)
+	  res.push(builder.apply(this,[data]));
+	else
+	  res.push(null);
+      }
+      return res.length>1?res:res[0];
+    } else
+      return null;
+  },
+  /**
+   * Property: parseData
+   * Object containing methods to analyse data response.
+   */
+  parseData: {
+    /**
+     * Method: parseData.complexdata
+     * Given an Object representing the WPS complex data response.
+     *
+     * Parameters:
+     * node - {E4XElement} A WPS node.
+     *
+     * Returns:
+     * {Object} A WPS complex data response.
+     */
+    'complexdata': function(node) {
+      var result = {value:node.toString()};
+      if (node. at mimeType.length()>0)
+        result.mimeType = node. at mimeType;
+      if (node. at encoding.length()>0)
+        result.encoding = node. at encoding;
+      if (node. at schema.length()>0)
+        result.schema = node. at schema;
+      return result;
+    },
+    /**
+     * Method: parseData.literaldata
+     * Given an Object representing the WPS literal data response.
+     *
+     * Parameters:
+     * node - {E4XElement} A WPS node.
+     *
+     * Returns:
+     * {Object} A WPS literal data response.
+     */
+    'literaldata': function(node) {
+      var result = {value:node.toString()};
+      if (node. at dataType.length()>0)
+        result.dataType = node. at dataType;
+      if (node. at uom.length()>0)
+        result.uom = node. at uom;
+      return result;
+    },
+    /**
+     * Method: parseData.reference
+     * Given an Object representing the WPS reference response.
+     *
+     * Parameters:
+     * node - {E4XElement} A WPS node.
+     *
+     * Returns:
+     * {Object} A WPS reference response.
+     */
+    'reference': function(node) {
+      var result = {type:'reference',value:node. at href};
+      return result;
+    }
+  },
+  CLASS_NAME: 'ZOO.Format.WPS'
+});
+
+/**
+ * Class: ZOO.Feature
+ * Vector features use the ZOO.Geometry classes as geometry description.
+ * They have an 'attributes' property, which is the data object
+ */
+ZOO.Feature = ZOO.Class({
+  /** 
+   * Property: fid 
+   * {String} 
+   */
+  fid: null,
+  /** 
+   * Property: geometry 
+   * {<ZOO.Geometry>} 
+   */
+  geometry: null,
+  /** 
+   * Property: attributes 
+   * {Object} This object holds arbitrary properties that describe the
+   *     feature.
+   */
+  attributes: null,
+  /**
+   * Property: bounds
+   * {<ZOO.Bounds>} The box bounding that feature's geometry, that
+   *     property can be set by an <ZOO.Format> object when
+   *     deserializing the feature, so in most cases it represents an
+   *     information set by the server. 
+   */
+  bounds: null,
+  /** 
+   * Constructor: ZOO.Feature
+   * Create a vector feature. 
+   * 
+   * Parameters:
+   * geometry - {<ZOO.Geometry>} The geometry that this feature
+   *     represents.
+   * attributes - {Object} An optional object that will be mapped to the
+   *     <attributes> property. 
+   */
+  initialize: function(geometry, attributes) {
+    this.geometry = geometry ? geometry : null;
+    this.attributes = {};
+    if (attributes)
+      this.attributes = ZOO.extend(this.attributes,attributes);
+  },
+  /** 
+   * Method: destroy
+   * nullify references to prevent circular references and memory leaks
+   */
+  destroy: function() {
+    this.geometry = null;
+  },
+  /**
+   * Method: clone
+   * Create a clone of this vector feature.  Does not set any non-standard
+   *     properties.
+   *
+   * Returns:
+   * {<ZOO.Feature>} An exact clone of this vector feature.
+   */
+  clone: function () {
+    return new ZOO.Feature(this.geometry ? this.geometry.clone() : null,
+            this.attributes);
+  },
+  /**
+   * Method: move
+   * Moves the feature and redraws it at its new location
+   *
+   * Parameters:
+   * x - {Float}
+   * y - {Float}
+   */
+  move: function(x, y) {
+    if(!this.geometry.move)
+      return;
+
+    this.geometry.move(x,y);
+    return this.geometry;
+  },
+  CLASS_NAME: 'ZOO.Feature'
+});
+
+/**
+ * Class: ZOO.Geometry
+ * A Geometry is a description of a geographic object. Create an instance
+ * of this class with the <ZOO.Geometry> constructor. This is a base class,
+ * typical geometry types are described by subclasses of this class.
+ */
+ZOO.Geometry = ZOO.Class({
+  /**
+   * Property: id
+   * {String} A unique identifier for this geometry.
+   */
+  id: null,
+  /**
+   * Property: parent
+   * {<ZOO.Geometry>}This is set when a Geometry is added as component
+   * of another geometry
+   */
+  parent: null,
+  /**
+   * Property: bounds 
+   * {<ZOO.Bounds>} The bounds of this geometry
+   */
+  bounds: null,
+  /**
+   * Constructor: ZOO.Geometry
+   * Creates a geometry object.  
+   */
+  initialize: function() {
+    //generate unique id
+  },
+  /**
+   * Method: destroy
+   * Destroy this geometry.
+   */
+  destroy: function() {
+    this.id = null;
+    this.bounds = null;
+  },
+  /**
+   * Method: clone
+   * Create a clone of this geometry.  Does not set any non-standard
+   *     properties of the cloned geometry.
+   * 
+   * Returns:
+   * {<ZOO.Geometry>} An exact clone of this geometry.
+   */
+  clone: function() {
+    return new ZOO.Geometry();
+  },
+  /**
+   * Method: extendBounds
+   * Extend the existing bounds to include the new bounds. 
+   * If geometry's bounds is not yet set, then set a new Bounds.
+   * 
+   * Parameters:
+   * newBounds - {<ZOO.Bounds>} 
+   */
+  extendBounds: function(newBounds){
+    var bounds = this.getBounds();
+    if (!bounds)
+      this.setBounds(newBounds);
+    else
+      this.bounds.extend(newBounds);
+  },
+  /**
+   * Set the bounds for this Geometry.
+   * 
+   * Parameters:
+   * bounds - {<ZOO.Bounds>} 
+   */
+  setBounds: function(bounds) {
+    if (bounds)
+      this.bounds = bounds.clone();
+  },
+  /**
+   * Method: clearBounds
+   * Nullify this components bounds and that of its parent as well.
+   */
+  clearBounds: function() {
+    this.bounds = null;
+    if (this.parent)
+      this.parent.clearBounds();
+  },
+  /**
+   * Method: getBounds
+   * Get the bounds for this Geometry. If bounds is not set, it 
+   * is calculated again, this makes queries faster.
+   * 
+   * Returns:
+   * {<ZOO.Bounds>}
+   */
+  getBounds: function() {
+    if (this.bounds == null) {
+      this.calculateBounds();
+    }
+    return this.bounds;
+  },
+  /** 
+   * Method: calculateBounds
+   * Recalculate the bounds for the geometry. 
+   */
+  calculateBounds: function() {
+    // This should be overridden by subclasses.
+    return this.bounds;
+  },
+  distanceTo: function(geometry, options) {
+  },
+  getVertices: function(nodes) {
+  },
+  getLength: function() {
+    return 0.0;
+  },
+  getArea: function() {
+    return 0.0;
+  },
+  getCentroid: function() {
+    return null;
+  },
+  /**
+   * Method: toString
+   * Returns the Well-Known Text representation of a geometry
+   *
+   * Returns:
+   * {String} Well-Known Text
+   */
+  toString: function() {
+    return ZOO.Format.WKT.prototype.write(
+        new ZOO.Feature(this)
+    );
+  },
+  CLASS_NAME: 'ZOO.Geometry'
+});
+/**
+ * Function: ZOO.Geometry.fromWKT
+ * Generate a geometry given a Well-Known Text string.
+ *
+ * Parameters:
+ * wkt - {String} A string representing the geometry in Well-Known Text.
+ *
+ * Returns:
+ * {<ZOO.Geometry>} A geometry of the appropriate class.
+ */
+ZOO.Geometry.fromWKT = function(wkt) {
+  var format = arguments.callee.format;
+  if(!format) {
+    format = new ZOO.Format.WKT();
+    arguments.callee.format = format;
+  }
+  var geom;
+  var result = format.read(wkt);
+  if(result instanceof ZOO.Feature) {
+    geom = result.geometry;
+  } else if(result instanceof Array) {
+    var len = result.length;
+    var components = new Array(len);
+    for(var i=0; i<len; ++i) {
+      components[i] = result[i].geometry;
+    }
+    geom = new ZOO.Geometry.Collection(components);
+  }
+  return geom;
+};
+ZOO.Geometry.segmentsIntersect = function(seg1, seg2, options) {
+  var point = options && options.point;
+  var tolerance = options && options.tolerance;
+  var intersection = false;
+  var x11_21 = seg1.x1 - seg2.x1;
+  var y11_21 = seg1.y1 - seg2.y1;
+  var x12_11 = seg1.x2 - seg1.x1;
+  var y12_11 = seg1.y2 - seg1.y1;
+  var y22_21 = seg2.y2 - seg2.y1;
+  var x22_21 = seg2.x2 - seg2.x1;
+  var d = (y22_21 * x12_11) - (x22_21 * y12_11);
+  var n1 = (x22_21 * y11_21) - (y22_21 * x11_21);
+  var n2 = (x12_11 * y11_21) - (y12_11 * x11_21);
+  if(d == 0) {
+    // parallel
+    if(n1 == 0 && n2 == 0) {
+      // coincident
+      intersection = true;
+    }
+  } else {
+    var along1 = n1 / d;
+    var along2 = n2 / d;
+    if(along1 >= 0 && along1 <= 1 && along2 >=0 && along2 <= 1) {
+      // intersect
+      if(!point) {
+        intersection = true;
+      } else {
+        // calculate the intersection point
+        var x = seg1.x1 + (along1 * x12_11);
+        var y = seg1.y1 + (along1 * y12_11);
+        intersection = new ZOO.Geometry.Point(x, y);
+      }
+    }
+  }
+  if(tolerance) {
+    var dist;
+    if(intersection) {
+      if(point) {
+        var segs = [seg1, seg2];
+        var seg, x, y;
+        // check segment endpoints for proximity to intersection
+        // set intersection to first endpoint within the tolerance
+        outer: for(var i=0; i<2; ++i) {
+          seg = segs[i];
+          for(var j=1; j<3; ++j) {
+            x = seg["x" + j];
+            y = seg["y" + j];
+            dist = Math.sqrt(
+                Math.pow(x - intersection.x, 2) +
+                Math.pow(y - intersection.y, 2)
+            );
+            if(dist < tolerance) {
+              intersection.x = x;
+              intersection.y = y;
+              break outer;
+            }
+          }
+        }
+      }
+    } else {
+      // no calculated intersection, but segments could be within
+      // the tolerance of one another
+      var segs = [seg1, seg2];
+      var source, target, x, y, p, result;
+      // check segment endpoints for proximity to intersection
+      // set intersection to first endpoint within the tolerance
+      outer: for(var i=0; i<2; ++i) {
+        source = segs[i];
+        target = segs[(i+1)%2];
+        for(var j=1; j<3; ++j) {
+          p = {x: source["x"+j], y: source["y"+j]};
+          result = ZOO.Geometry.distanceToSegment(p, target);
+          if(result.distance < tolerance) {
+            if(point) {
+              intersection = new ZOO.Geometry.Point(p.x, p.y);
+            } else {
+              intersection = true;
+            }
+            break outer;
+          }
+        }
+      }
+    }
+  }
+  return intersection;
+};
+ZOO.Geometry.distanceToSegment = function(point, segment) {
+  var x0 = point.x;
+  var y0 = point.y;
+  var x1 = segment.x1;
+  var y1 = segment.y1;
+  var x2 = segment.x2;
+  var y2 = segment.y2;
+  var dx = x2 - x1;
+  var dy = y2 - y1;
+  var along = ((dx * (x0 - x1)) + (dy * (y0 - y1))) /
+               (Math.pow(dx, 2) + Math.pow(dy, 2));
+  var x, y;
+  if(along <= 0.0) {
+    x = x1;
+    y = y1;
+  } else if(along >= 1.0) {
+    x = x2;
+    y = y2;
+  } else {
+    x = x1 + along * dx;
+    y = y1 + along * dy;
+  }
+  return {
+    distance: Math.sqrt(Math.pow(x - x0, 2) + Math.pow(y - y0, 2)),
+    x: x, y: y
+  };
+};
+/**
+ * Class: ZOO.Geometry.Collection
+ * A Collection is exactly what it sounds like: A collection of different 
+ * Geometries. These are stored in the local parameter <components> (which
+ * can be passed as a parameter to the constructor). 
+ * 
+ * As new geometries are added to the collection, they are NOT cloned. 
+ * When removing geometries, they need to be specified by reference (ie you 
+ * have to pass in the *exact* geometry to be removed).
+ * 
+ * The <getArea> and <getLength> functions here merely iterate through
+ * the components, summing their respective areas and lengths.
+ *
+ * Create a new instance with the <ZOO.Geometry.Collection> constructor.
+ *
+ * Inerhits from:
+ *  - <ZOO.Geometry> 
+ */
+ZOO.Geometry.Collection = ZOO.Class(ZOO.Geometry, {
+  /**
+   * Property: components
+   * {Array(<ZOO.Geometry>)} The component parts of this geometry
+   */
+  components: null,
+  /**
+   * Property: componentTypes
+   * {Array(String)} An array of class names representing the types of
+   * components that the collection can include.  A null value means the
+   * component types are not restricted.
+   */
+  componentTypes: null,
+  /**
+   * Constructor: ZOO.Geometry.Collection
+   * Creates a Geometry Collection -- a list of geoms.
+   *
+   * Parameters: 
+   * components - {Array(<ZOO.Geometry>)} Optional array of geometries
+   *
+   */
+  initialize: function (components) {
+    ZOO.Geometry.prototype.initialize.apply(this, arguments);
+    this.components = [];
+    if (components != null) {
+      this.addComponents(components);
+    }
+  },
+  /**
+   * Method: destroy
+   * Destroy this geometry.
+   */
+  destroy: function () {
+    this.components.length = 0;
+    this.components = null;
+  },
+  /**
+   * Method: clone
+   * Clone this geometry.
+   *
+   * Returns:
+   * {<ZOO.Geometry.Collection>} An exact clone of this collection
+   */
+  clone: function() {
+    var geometry = eval("new " + this.CLASS_NAME + "()");
+    for(var i=0, len=this.components.length; i<len; i++) {
+      geometry.addComponent(this.components[i].clone());
+    }
+    return geometry;
+  },
+  /**
+   * Method: getComponentsString
+   * Get a string representing the components for this collection
+   * 
+   * Returns:
+   * {String} A string representation of the components of this geometry
+   */
+  getComponentsString: function(){
+    var strings = [];
+    for(var i=0, len=this.components.length; i<len; i++) {
+      strings.push(this.components[i].toShortString()); 
+    }
+    return strings.join(",");
+  },
+  /**
+   * Method: calculateBounds
+   * Recalculate the bounds by iterating through the components and 
+   * calling extendBounds() on each item.
+   */
+  calculateBounds: function() {
+    this.bounds = null;
+    if ( this.components && this.components.length > 0) {
+      this.setBounds(this.components[0].getBounds());
+      for (var i=1, len=this.components.length; i<len; i++) {
+        this.extendBounds(this.components[i].getBounds());
+      }
+    }
+    return this.bounds
+  },
+  /**
+   * APIMethod: addComponents
+   * Add components to this geometry.
+   *
+   * Parameters:
+   * components - {Array(<ZOO.Geometry>)} An array of geometries to add
+   */
+  addComponents: function(components){
+    if(!(components instanceof Array))
+      components = [components];
+    for(var i=0, len=components.length; i<len; i++) {
+      this.addComponent(components[i]);
+    }
+  },
+  /**
+   * Method: addComponent
+   * Add a new component (geometry) to the collection.  If this.componentTypes
+   * is set, then the component class name must be in the componentTypes array.
+   *
+   * The bounds cache is reset.
+   * 
+   * Parameters:
+   * component - {<ZOO.Geometry>} A geometry to add
+   * index - {int} Optional index into the array to insert the component
+   *
+   * Returns:
+   * {Boolean} The component geometry was successfully added
+   */
+  addComponent: function(component, index) {
+    var added = false;
+    if(component) {
+      if(this.componentTypes == null ||
+          (ZOO.indexOf(this.componentTypes,
+                       component.CLASS_NAME) > -1)) {
+        if(index != null && (index < this.components.length)) {
+          var components1 = this.components.slice(0, index);
+          var components2 = this.components.slice(index, 
+                                                  this.components.length);
+          components1.push(component);
+          this.components = components1.concat(components2);
+        } else {
+          this.components.push(component);
+        }
+        component.parent = this;
+        this.clearBounds();
+        added = true;
+      }
+    }
+    return added;
+  },
+  /**
+   * Method: removeComponents
+   * Remove components from this geometry.
+   *
+   * Parameters:
+   * components - {Array(<ZOO.Geometry>)} The components to be removed
+   */
+  removeComponents: function(components) {
+    if(!(components instanceof Array))
+      components = [components];
+    for(var i=components.length-1; i>=0; --i) {
+      this.removeComponent(components[i]);
+    }
+  },
+  /**
+   * Method: removeComponent
+   * Remove a component from this geometry.
+   *
+   * Parameters:
+   * component - {<ZOO.Geometry>} 
+   */
+  removeComponent: function(component) {      
+    ZOO.removeItem(this.components, component);
+    // clearBounds() so that it gets recalculated on the next call
+    // to this.getBounds();
+    this.clearBounds();
+  },
+  /**
+   * Method: getLength
+   * Calculate the length of this geometry
+   *
+   * Returns:
+   * {Float} The length of the geometry
+   */
+  getLength: function() {
+    var length = 0.0;
+    for (var i=0, len=this.components.length; i<len; i++) {
+      length += this.components[i].getLength();
+    }
+    return length;
+  },
+  /**
+   * APIMethod: getArea
+   * Calculate the area of this geometry. Note how this function is 
+   * overridden in <ZOO.Geometry.Polygon>.
+   *
+   * Returns:
+   * {Float} The area of the collection by summing its parts
+   */
+  getArea: function() {
+    var area = 0.0;
+    for (var i=0, len=this.components.length; i<len; i++) {
+      area += this.components[i].getArea();
+    }
+    return area;
+  },
+  /** 
+   * APIMethod: getGeodesicArea
+   * Calculate the approximate area of the polygon were it projected onto
+   *     the earth.
+   *
+   * Parameters:
+   * projection - {<ZOO.Projection>} The spatial reference system
+   *     for the geometry coordinates.  If not provided, Geographic/WGS84 is
+   *     assumed.
+   * 
+   * Reference:
+   * Robert. G. Chamberlain and William H. Duquette, "Some Algorithms for
+   *     Polygons on a Sphere", JPL Publication 07-03, Jet Propulsion
+   *     Laboratory, Pasadena, CA, June 2007 http://trs-new.jpl.nasa.gov/dspace/handle/2014/40409
+   *
+   * Returns:
+   * {float} The approximate geodesic area of the geometry in square meters.
+   */
+  getGeodesicArea: function(projection) {
+    var area = 0.0;
+    for(var i=0, len=this.components.length; i<len; i++) {
+      area += this.components[i].getGeodesicArea(projection);
+    }
+    return area;
+  },
+  /**
+   * Method: getCentroid
+   *
+   * Returns:
+   * {<ZOO.Geometry.Point>} The centroid of the collection
+   */
+  getCentroid: function() {
+    return this.components.length && this.components[0].getCentroid();
+  },
+  /**
+   * Method: getGeodesicLength
+   * Calculate the approximate length of the geometry were it projected onto
+   *     the earth.
+   *
+   * Parameters:
+   * projection - {<ZOO.Projection>} The spatial reference system
+   *     for the geometry coordinates.  If not provided, Geographic/WGS84 is
+   *     assumed.
+   * 
+   * Returns:
+   * {Float} The appoximate geodesic length of the geometry in meters.
+   */
+  getGeodesicLength: function(projection) {
+    var length = 0.0;
+    for(var i=0, len=this.components.length; i<len; i++) {
+      length += this.components[i].getGeodesicLength(projection);
+    }
+    return length;
+  },
+  /**
+   * Method: move
+   * Moves a geometry by the given displacement along positive x and y axes.
+   *     This modifies the position of the geometry and clears the cached
+   *     bounds.
+   *
+   * Parameters:
+   * x - {Float} Distance to move geometry in positive x direction. 
+   * y - {Float} Distance to move geometry in positive y direction.
+   */
+  move: function(x, y) {
+    for(var i=0, len=this.components.length; i<len; i++) {
+      this.components[i].move(x, y);
+    }
+  },
+  /**
+   * Method: rotate
+   * Rotate a geometry around some origin
+   *
+   * Parameters:
+   * angle - {Float} Rotation angle in degrees (measured counterclockwise
+   *                 from the positive x-axis)
+   * origin - {<ZOO.Geometry.Point>} Center point for the rotation
+   */
+  rotate: function(angle, origin) {
+    for(var i=0, len=this.components.length; i<len; ++i) {
+      this.components[i].rotate(angle, origin);
+    }
+  },
+  /**
+   * Method: resize
+   * Resize a geometry relative to some origin.  Use this method to apply
+   *     a uniform scaling to a geometry.
+   *
+   * Parameters:
+   * scale - {Float} Factor by which to scale the geometry.  A scale of 2
+   *                 doubles the size of the geometry in each dimension
+   *                 (lines, for example, will be twice as long, and polygons
+   *                 will have four times the area).
+   * origin - {<ZOO.Geometry.Point>} Point of origin for resizing
+   * ratio - {Float} Optional x:y ratio for resizing.  Default ratio is 1.
+   * 
+   * Returns:
+   * {ZOO.Geometry} - The current geometry. 
+   */
+  resize: function(scale, origin, ratio) {
+    for(var i=0; i<this.components.length; ++i) {
+      this.components[i].resize(scale, origin, ratio);
+    }
+    return this;
+  },
+  distanceTo: function(geometry, options) {
+    var edge = !(options && options.edge === false);
+    var details = edge && options && options.details;
+    var result, best;
+    var min = Number.POSITIVE_INFINITY;
+    for(var i=0, len=this.components.length; i<len; ++i) {
+      result = this.components[i].distanceTo(geometry, options);
+      distance = details ? result.distance : result;
+      if(distance < min) {
+        min = distance;
+        best = result;
+        if(min == 0)
+          break;
+      }
+    }
+    return best;
+  },
+  /** 
+   * Method: equals
+   * Determine whether another geometry is equivalent to this one.  Geometries
+   *     are considered equivalent if all components have the same coordinates.
+   * 
+   * Parameters:
+   * geom - {<ZOO.Geometry>} The geometry to test. 
+   *
+   * Returns:
+   * {Boolean} The supplied geometry is equivalent to this geometry.
+   */
+  equals: function(geometry) {
+    var equivalent = true;
+    if(!geometry || !geometry.CLASS_NAME ||
+       (this.CLASS_NAME != geometry.CLASS_NAME))
+      equivalent = false;
+    else if(!(geometry.components instanceof Array) ||
+             (geometry.components.length != this.components.length))
+      equivalent = false;
+    else
+      for(var i=0, len=this.components.length; i<len; ++i) {
+        if(!this.components[i].equals(geometry.components[i])) {
+          equivalent = false;
+          break;
+        }
+      }
+    return equivalent;
+  },
+  /**
+   * Method: transform
+   * Reproject the components geometry from source to dest.
+   * 
+   * Parameters:
+   * source - {<ZOO.Projection>} 
+   * dest - {<ZOO.Projection>}
+   * 
+   * Returns:
+   * {<ZOO.Geometry>} 
+   */
+  transform: function(source, dest) {
+    if (source && dest) {
+      for (var i=0, len=this.components.length; i<len; i++) {  
+        var component = this.components[i];
+        component.transform(source, dest);
+      }
+      this.bounds = null;
+    }
+    return this;
+  },
+  /**
+   * Method: intersects
+   * Determine if the input geometry intersects this one.
+   *
+   * Parameters:
+   * geometry - {<ZOO.Geometry>} Any type of geometry.
+   *
+   * Returns:
+   * {Boolean} The input geometry intersects this one.
+   */
+  intersects: function(geometry) {
+    var intersect = false;
+    for(var i=0, len=this.components.length; i<len; ++ i) {
+      intersect = geometry.intersects(this.components[i]);
+      if(intersect)
+        break;
+    }
+    return intersect;
+  },
+  /**
+   * Method: getVertices
+   * Return a list of all points in this geometry.
+   *
+   * Parameters:
+   * nodes - {Boolean} For lines, only return vertices that are
+   *     endpoints.  If false, for lines, only vertices that are not
+   *     endpoints will be returned.  If not provided, all vertices will
+   *     be returned.
+   *
+   * Returns:
+   * {Array} A list of all vertices in the geometry.
+   */
+  getVertices: function(nodes) {
+    var vertices = [];
+    for(var i=0, len=this.components.length; i<len; ++i) {
+      Array.prototype.push.apply(
+          vertices, this.components[i].getVertices(nodes)
+          );
+    }
+    return vertices;
+  },
+  CLASS_NAME: 'ZOO.Geometry.Collection'
+});
+/**
+ * Class: ZOO.Geometry.Point
+ * Point geometry class. 
+ * 
+ * Inherits from:
+ *  - <ZOO.Geometry> 
+ */
+ZOO.Geometry.Point = ZOO.Class(ZOO.Geometry, {
+  /** 
+   * Property: x 
+   * {float} 
+   */
+  x: null,
+  /** 
+   * Property: y 
+   * {float} 
+   */
+  y: null,
+  /**
+   * Constructor: ZOO.Geometry.Point
+   * Construct a point geometry.
+   *
+   * Parameters:
+   * x - {float} 
+   * y - {float}
+   * 
+   */
+  initialize: function(x, y) {
+    ZOO.Geometry.prototype.initialize.apply(this, arguments);
+    this.x = parseFloat(x);
+    this.y = parseFloat(y);
+  },
+  /**
+   * Method: clone
+   * 
+   * Returns:
+   * {<ZOO.Geometry.Point>} An exact clone of this ZOO.Geometry.Point
+   */
+  clone: function(obj) {
+    if (obj == null)
+      obj = new ZOO.Geometry.Point(this.x, this.y);
+    // catch any randomly tagged-on properties
+    // ZOO.Util.applyDefaults(obj, this);
+    return obj;
+  },
+  /** 
+   * Method: calculateBounds
+   * Create a new Bounds based on the x/y
+   */
+  calculateBounds: function () {
+    this.bounds = new ZOO.Bounds(this.x, this.y,
+                                        this.x, this.y);
+  },
+  distanceTo: function(geometry, options) {
+    var edge = !(options && options.edge === false);
+    var details = edge && options && options.details;
+    var distance, x0, y0, x1, y1, result;
+    if(geometry instanceof ZOO.Geometry.Point) {
+      x0 = this.x;
+      y0 = this.y;
+      x1 = geometry.x;
+      y1 = geometry.y;
+      distance = Math.sqrt(Math.pow(x0 - x1, 2) + Math.pow(y0 - y1, 2));
+      result = !details ?
+        distance : {x0: x0, y0: y0, x1: x1, y1: y1, distance: distance};
+    } else {
+      result = geometry.distanceTo(this, options);
+      if(details) {
+        // switch coord order since this geom is target
+        result = {
+          x0: result.x1, y0: result.y1,
+          x1: result.x0, y1: result.y0,
+          distance: result.distance
+        };
+      }
+    }
+    return result;
+  },
+  /** 
+   * Method: equals
+   * Determine whether another geometry is equivalent to this one.  Geometries
+   *     are considered equivalent if all components have the same coordinates.
+   * 
+   * Parameters:
+   * geom - {<ZOO.Geometry.Point>} The geometry to test. 
+   *
+   * Returns:
+   * {Boolean} The supplied geometry is equivalent to this geometry.
+   */
+  equals: function(geom) {
+    var equals = false;
+    if (geom != null)
+      equals = ((this.x == geom.x && this.y == geom.y) ||
+                (isNaN(this.x) && isNaN(this.y) && isNaN(geom.x) && isNaN(geom.y)));
+    return equals;
+  },
+  /**
+   * Method: toShortString
+   *
+   * Returns:
+   * {String} Shortened String representation of Point object. 
+   *         (ex. <i>"5, 42"</i>)
+   */
+  toShortString: function() {
+    return (this.x + ", " + this.y);
+  },
+  /**
+   * Method: move
+   * Moves a geometry by the given displacement along positive x and y axes.
+   *     This modifies the position of the geometry and clears the cached
+   *     bounds.
+   *
+   * Parameters:
+   * x - {Float} Distance to move geometry in positive x direction. 
+   * y - {Float} Distance to move geometry in positive y direction.
+   */
+  move: function(x, y) {
+    this.x = this.x + x;
+    this.y = this.y + y;
+    this.clearBounds();
+  },
+  /**
+   * Method: rotate
+   * Rotate a point around another.
+   *
+   * Parameters:
+   * angle - {Float} Rotation angle in degrees (measured counterclockwise
+   *                 from the positive x-axis)
+   * origin - {<ZOO.Geometry.Point>} Center point for the rotation
+   */
+  rotate: function(angle, origin) {
+        angle *= Math.PI / 180;
+        var radius = this.distanceTo(origin);
+        var theta = angle + Math.atan2(this.y - origin.y, this.x - origin.x);
+        this.x = origin.x + (radius * Math.cos(theta));
+        this.y = origin.y + (radius * Math.sin(theta));
+        this.clearBounds();
+  },
+  /**
+   * Method: getCentroid
+   *
+   * Returns:
+   * {<ZOO.Geometry.Point>} The centroid of the collection
+   */
+  getCentroid: function() {
+    return new ZOO.Geometry.Point(this.x, this.y);
+  },
+  /**
+   * Method: resize
+   * Resize a point relative to some origin.  For points, this has the effect
+   *     of scaling a vector (from the origin to the point).  This method is
+   *     more useful on geometry collection subclasses.
+   *
+   * Parameters:
+   * scale - {Float} Ratio of the new distance from the origin to the old
+   *                 distance from the origin.  A scale of 2 doubles the
+   *                 distance between the point and origin.
+   * origin - {<ZOO.Geometry.Point>} Point of origin for resizing
+   * ratio - {Float} Optional x:y ratio for resizing.  Default ratio is 1.
+   * 
+   * Returns:
+   * {ZOO.Geometry} - The current geometry. 
+   */
+  resize: function(scale, origin, ratio) {
+    ratio = (ratio == undefined) ? 1 : ratio;
+    this.x = origin.x + (scale * ratio * (this.x - origin.x));
+    this.y = origin.y + (scale * (this.y - origin.y));
+    this.clearBounds();
+    return this;
+  },
+  /**
+   * Method: intersects
+   * Determine if the input geometry intersects this one.
+   *
+   * Parameters:
+   * geometry - {<ZOO.Geometry>} Any type of geometry.
+   *
+   * Returns:
+   * {Boolean} The input geometry intersects this one.
+   */
+  intersects: function(geometry) {
+    var intersect = false;
+    if(geometry.CLASS_NAME == "ZOO.Geometry.Point") {
+      intersect = this.equals(geometry);
+    } else {
+      intersect = geometry.intersects(this);
+    }
+    return intersect;
+  },
+  /**
+   * Method: transform
+   * Translate the x,y properties of the point from source to dest.
+   * 
+   * Parameters:
+   * source - {<ZOO.Projection>} 
+   * dest - {<ZOO.Projection>}
+   * 
+   * Returns:
+   * {<ZOO.Geometry>} 
+   */
+  transform: function(source, dest) {
+    if ((source && dest)) {
+      ZOO.Projection.transform(
+          this, source, dest); 
+      this.bounds = null;
+    }       
+    return this;
+  },
+  /**
+   * Method: getVertices
+   * Return a list of all points in this geometry.
+   *
+   * Parameters:
+   * nodes - {Boolean} For lines, only return vertices that are
+   *     endpoints.  If false, for lines, only vertices that are not
+   *     endpoints will be returned.  If not provided, all vertices will
+   *     be returned.
+   *
+   * Returns:
+   * {Array} A list of all vertices in the geometry.
+   */
+  getVertices: function(nodes) {
+    return [this];
+  },
+  CLASS_NAME: 'ZOO.Geometry.Point'
+});
+/**
+ * Class: ZOO.Geometry.Surface
+ * Surface geometry class. 
+ * 
+ * Inherits from:
+ *  - <ZOO.Geometry> 
+ */
+ZOO.Geometry.Surface = ZOO.Class(ZOO.Geometry, {
+  initialize: function() {
+    ZOO.Geometry.prototype.initialize.apply(this, arguments);
+  },
+  CLASS_NAME: "ZOO.Geometry.Surface"
+});
+/**
+ * Class: ZOO.Geometry.MultiPoint
+ * MultiPoint is a collection of Points. Create a new instance with the
+ * <ZOO.Geometry.MultiPoint> constructor.
+ *
+ * Inherits from:
+ *  - <ZOO.Geometry.Collection>
+ */
+ZOO.Geometry.MultiPoint = ZOO.Class(
+  ZOO.Geometry.Collection, {
+  /**
+   * Property: componentTypes
+   * {Array(String)} An array of class names representing the types of
+   * components that the collection can include.  A null value means the
+   * component types are not restricted.
+   */
+  componentTypes: ["ZOO.Geometry.Point"],
+  /**
+   * Constructor: ZOO.Geometry.MultiPoint
+   * Create a new MultiPoint Geometry
+   *
+   * Parameters:
+   * components - {Array(<ZOO.Geometry.Point>)} 
+   *
+   * Returns:
+   * {<ZOO.Geometry.MultiPoint>}
+   */
+  initialize: function(components) {
+    ZOO.Geometry.Collection.prototype.initialize.apply(this,arguments);
+  },
+  /**
+   * Method: addPoint
+   * Wrapper for <ZOO.Geometry.Collection.addComponent>
+   *
+   * Parameters:
+   * point - {<ZOO.Geometry.Point>} Point to be added
+   * index - {Integer} Optional index
+   */
+  addPoint: function(point, index) {
+    this.addComponent(point, index);
+  },
+  /**
+   * Method: removePoint
+   * Wrapper for <ZOO.Geometry.Collection.removeComponent>
+   *
+   * Parameters:
+   * point - {<ZOO.Geometry.Point>} Point to be removed
+   */
+  removePoint: function(point){
+    this.removeComponent(point);
+  },
+  CLASS_NAME: "ZOO.Geometry.MultiPoint"
+});
+/**
+ * Class: ZOO.Geometry.Curve
+ * A Curve is a MultiPoint, whose points are assumed to be connected. To 
+ * this end, we provide a "getLength()" function, which iterates through 
+ * the points, summing the distances between them. 
+ * 
+ * Inherits: 
+ *  - <ZOO.Geometry.MultiPoint>
+ */
+ZOO.Geometry.Curve = ZOO.Class(ZOO.Geometry.MultiPoint, {
+  /**
+   * Property: componentTypes
+   * {Array(String)} An array of class names representing the types of 
+   *                 components that the collection can include.  A null 
+   *                 value means the component types are not restricted.
+   */
+  componentTypes: ["ZOO.Geometry.Point"],
+  /**
+   * Constructor: ZOO.Geometry.Curve
+   * 
+   * Parameters:
+   * point - {Array(<ZOO.Geometry.Point>)}
+   */
+  initialize: function(points) {
+    ZOO.Geometry.MultiPoint.prototype.initialize.apply(this,arguments);
+  },
+  /**
+   * Method: getLength
+   * 
+   * Returns:
+   * {Float} The length of the curve
+   */
+  getLength: function() {
+    var length = 0.0;
+    if ( this.components && (this.components.length > 1)) {
+      for(var i=1, len=this.components.length; i<len; i++) {
+        length += this.components[i-1].distanceTo(this.components[i]);
+      }
+    }
+    return length;
+  },
+  /**
+     * APIMethod: getGeodesicLength
+     * Calculate the approximate length of the geometry were it projected onto
+     *     the earth.
+     *
+     * projection - {<ZOO.Projection>} The spatial reference system
+     *     for the geometry coordinates.  If not provided, Geographic/WGS84 is
+     *     assumed.
+     * 
+     * Returns:
+     * {Float} The appoximate geodesic length of the geometry in meters.
+     */
+    getGeodesicLength: function(projection) {
+      var geom = this;  // so we can work with a clone if needed
+      if(projection) {
+        var gg = new ZOO.Projection("EPSG:4326");
+        if(!gg.equals(projection)) {
+          geom = this.clone().transform(projection, gg);
+       }
+     }
+     var length = 0.0;
+     if(geom.components && (geom.components.length > 1)) {
+       var p1, p2;
+       for(var i=1, len=geom.components.length; i<len; i++) {
+         p1 = geom.components[i-1];
+         p2 = geom.components[i];
+        // this returns km and requires x/y properties
+        length += ZOO.distVincenty(p1,p2);
+      }
+    }
+    // convert to m
+    return length * 1000;
+  },
+  CLASS_NAME: "ZOO.Geometry.Curve"
+});
+/**
+ * Class: ZOO.Geometry.LineString
+ * A LineString is a Curve which, once two points have been added to it, can 
+ * never be less than two points long.
+ * 
+ * Inherits from:
+ *  - <ZOO.Geometry.Curve>
+ */
+ZOO.Geometry.LineString = ZOO.Class(ZOO.Geometry.Curve, {
+  /**
+   * Constructor: ZOO.Geometry.LineString
+   * Create a new LineString geometry
+   *
+   * Parameters:
+   * points - {Array(<ZOO.Geometry.Point>)} An array of points used to
+   *          generate the linestring
+   *
+   */
+  initialize: function(points) {
+    ZOO.Geometry.Curve.prototype.initialize.apply(this, arguments);        
+  },
+  /**
+   * Method: removeComponent
+   * Only allows removal of a point if there are three or more points in 
+   * the linestring. (otherwise the result would be just a single point)
+   *
+   * Parameters: 
+   * point - {<ZOO.Geometry.Point>} The point to be removed
+   */
+  removeComponent: function(point) {
+    if ( this.components && (this.components.length > 2))
+      ZOO.Geometry.Collection.prototype.removeComponent.apply(this,arguments);
+  },
+  /**
+   * Method: intersects
+   * Test for instersection between two geometries.  This is a cheapo
+   *     implementation of the Bently-Ottmann algorigithm.  It doesn't
+   *     really keep track of a sweep line data structure.  It is closer
+   *     to the brute force method, except that segments are sorted and
+   *     potential intersections are only calculated when bounding boxes
+   *     intersect.
+   *
+   * Parameters:
+   * geometry - {<ZOO.Geometry>}
+   *
+   * Returns:
+   * {Boolean} The input geometry intersects this geometry.
+   */
+  intersects: function(geometry) {
+    var intersect = false;
+    var type = geometry.CLASS_NAME;
+    if(type == "ZOO.Geometry.LineString" ||
+       type == "ZOO.Geometry.LinearRing" ||
+       type == "ZOO.Geometry.Point") {
+      var segs1 = this.getSortedSegments();
+      var segs2;
+      if(type == "ZOO.Geometry.Point")
+        segs2 = [{
+          x1: geometry.x, y1: geometry.y,
+          x2: geometry.x, y2: geometry.y
+        }];
+      else
+        segs2 = geometry.getSortedSegments();
+      var seg1, seg1x1, seg1x2, seg1y1, seg1y2,
+          seg2, seg2y1, seg2y2;
+      // sweep right
+      outer: for(var i=0, len=segs1.length; i<len; ++i) {
+         seg1 = segs1[i];
+         seg1x1 = seg1.x1;
+         seg1x2 = seg1.x2;
+         seg1y1 = seg1.y1;
+         seg1y2 = seg1.y2;
+         inner: for(var j=0, jlen=segs2.length; j<jlen; ++j) {
+           seg2 = segs2[j];
+           if(seg2.x1 > seg1x2)
+             break;
+           if(seg2.x2 < seg1x1)
+             continue;
+           seg2y1 = seg2.y1;
+           seg2y2 = seg2.y2;
+           if(Math.min(seg2y1, seg2y2) > Math.max(seg1y1, seg1y2))
+             continue;
+           if(Math.max(seg2y1, seg2y2) < Math.min(seg1y1, seg1y2))
+             continue;
+           if(ZOO.Geometry.segmentsIntersect(seg1, seg2)) {
+             intersect = true;
+             break outer;
+           }
+         }
+      }
+    } else {
+      intersect = geometry.intersects(this);
+    }
+    return intersect;
+  },
+  /**
+   * Method: getSortedSegments
+   *
+   * Returns:
+   * {Array} An array of segment objects.  Segment objects have properties
+   *     x1, y1, x2, and y2.  The start point is represented by x1 and y1.
+   *     The end point is represented by x2 and y2.  Start and end are
+   *     ordered so that x1 < x2.
+   */
+  getSortedSegments: function() {
+    var numSeg = this.components.length - 1;
+    var segments = new Array(numSeg);
+    for(var i=0; i<numSeg; ++i) {
+      point1 = this.components[i];
+      point2 = this.components[i + 1];
+      if(point1.x < point2.x)
+        segments[i] = {
+          x1: point1.x,
+          y1: point1.y,
+          x2: point2.x,
+          y2: point2.y
+        };
+      else
+        segments[i] = {
+          x1: point2.x,
+          y1: point2.y,
+          x2: point1.x,
+          y2: point1.y
+        };
+    }
+    // more efficient to define this somewhere static
+    function byX1(seg1, seg2) {
+      return seg1.x1 - seg2.x1;
+    }
+    return segments.sort(byX1);
+  },
+  /**
+   * Method: splitWithSegment
+   * Split this geometry with the given segment.
+   *
+   * Parameters:
+   * seg - {Object} An object with x1, y1, x2, and y2 properties referencing
+   *     segment endpoint coordinates.
+   * options - {Object} Properties of this object will be used to determine
+   *     how the split is conducted.
+   *
+   * Valid options:
+   * edge - {Boolean} Allow splitting when only edges intersect.  Default is
+   *     true.  If false, a vertex on the source segment must be within the
+   *     tolerance distance of the intersection to be considered a split.
+   * tolerance - {Number} If a non-null value is provided, intersections
+   *     within the tolerance distance of one of the source segment's
+   *     endpoints will be assumed to occur at the endpoint.
+   *
+   * Returns:
+   * {Object} An object with *lines* and *points* properties.  If the given
+   *     segment intersects this linestring, the lines array will reference
+   *     geometries that result from the split.  The points array will contain
+   *     all intersection points.  Intersection points are sorted along the
+   *     segment (in order from x1,y1 to x2,y2).
+   */
+  splitWithSegment: function(seg, options) {
+    var edge = !(options && options.edge === false);
+    var tolerance = options && options.tolerance;
+    var lines = [];
+    var verts = this.getVertices();
+    var points = [];
+    var intersections = [];
+    var split = false;
+    var vert1, vert2, point;
+    var node, vertex, target;
+    var interOptions = {point: true, tolerance: tolerance};
+    var result = null;
+    for(var i=0, stop=verts.length-2; i<=stop; ++i) {
+      vert1 = verts[i];
+      points.push(vert1.clone());
+      vert2 = verts[i+1];
+      target = {x1: vert1.x, y1: vert1.y, x2: vert2.x, y2: vert2.y};
+      point = ZOO.Geometry.segmentsIntersect(seg, target, interOptions);
+      if(point instanceof ZOO.Geometry.Point) {
+        if((point.x === seg.x1 && point.y === seg.y1) ||
+           (point.x === seg.x2 && point.y === seg.y2) ||
+            point.equals(vert1) || point.equals(vert2))
+          vertex = true;
+        else
+          vertex = false;
+        if(vertex || edge) {
+          // push intersections different than the previous
+          if(!point.equals(intersections[intersections.length-1]))
+            intersections.push(point.clone());
+          if(i === 0) {
+            if(point.equals(vert1))
+              continue;
+          }
+          if(point.equals(vert2))
+            continue;
+          split = true;
+          if(!point.equals(vert1))
+            points.push(point);
+          lines.push(new ZOO.Geometry.LineString(points));
+          points = [point.clone()];
+        }
+      }
+    }
+    if(split) {
+      points.push(vert2.clone());
+      lines.push(new ZOO.Geometry.LineString(points));
+    }
+    if(intersections.length > 0) {
+      // sort intersections along segment
+      var xDir = seg.x1 < seg.x2 ? 1 : -1;
+      var yDir = seg.y1 < seg.y2 ? 1 : -1;
+      result = {
+        lines: lines,
+        points: intersections.sort(function(p1, p2) {
+           return (xDir * p1.x - xDir * p2.x) || (yDir * p1.y - yDir * p2.y);
+        })
+      };
+    }
+    return result;
+  },
+  /**
+   * Method: split
+   * Use this geometry (the source) to attempt to split a target geometry.
+   * 
+   * Parameters:
+   * target - {<ZOO.Geometry>} The target geometry.
+   * options - {Object} Properties of this object will be used to determine
+   *     how the split is conducted.
+   *
+   * Valid options:
+   * mutual - {Boolean} Split the source geometry in addition to the target
+   *     geometry.  Default is false.
+   * edge - {Boolean} Allow splitting when only edges intersect.  Default is
+   *     true.  If false, a vertex on the source must be within the tolerance
+   *     distance of the intersection to be considered a split.
+   * tolerance - {Number} If a non-null value is provided, intersections
+   *     within the tolerance distance of an existing vertex on the source
+   *     will be assumed to occur at the vertex.
+   * 
+   * Returns:
+   * {Array} A list of geometries (of this same type as the target) that
+   *     result from splitting the target with the source geometry.  The
+   *     source and target geometry will remain unmodified.  If no split
+   *     results, null will be returned.  If mutual is true and a split
+   *     results, return will be an array of two arrays - the first will be
+   *     all geometries that result from splitting the source geometry and
+   *     the second will be all geometries that result from splitting the
+   *     target geometry.
+   */
+  split: function(target, options) {
+    var results = null;
+    var mutual = options && options.mutual;
+    var sourceSplit, targetSplit, sourceParts, targetParts;
+    if(target instanceof ZOO.Geometry.LineString) {
+      var verts = this.getVertices();
+      var vert1, vert2, seg, splits, lines, point;
+      var points = [];
+      sourceParts = [];
+      for(var i=0, stop=verts.length-2; i<=stop; ++i) {
+        vert1 = verts[i];
+        vert2 = verts[i+1];
+        seg = {
+          x1: vert1.x, y1: vert1.y,
+          x2: vert2.x, y2: vert2.y
+        };
+        targetParts = targetParts || [target];
+        if(mutual)
+          points.push(vert1.clone());
+        for(var j=0; j<targetParts.length; ++j) {
+          splits = targetParts[j].splitWithSegment(seg, options);
+          if(splits) {
+            // splice in new features
+            lines = splits.lines;
+            if(lines.length > 0) {
+              lines.unshift(j, 1);
+              Array.prototype.splice.apply(targetParts, lines);
+              j += lines.length - 2;
+            }
+            if(mutual) {
+              for(var k=0, len=splits.points.length; k<len; ++k) {
+                point = splits.points[k];
+                if(!point.equals(vert1)) {
+                  points.push(point);
+                  sourceParts.push(new ZOO.Geometry.LineString(points));
+                  if(point.equals(vert2))
+                    points = [];
+                  else
+                    points = [point.clone()];
+                }
+              }
+            }
+          }
+        }
+      }
+      if(mutual && sourceParts.length > 0 && points.length > 0) {
+        points.push(vert2.clone());
+        sourceParts.push(new ZOO.Geometry.LineString(points));
+      }
+    } else {
+      results = target.splitWith(this, options);
+    }
+    if(targetParts && targetParts.length > 1)
+      targetSplit = true;
+    else
+      targetParts = [];
+    if(sourceParts && sourceParts.length > 1)
+      sourceSplit = true;
+    else
+      sourceParts = [];
+    if(targetSplit || sourceSplit) {
+      if(mutual)
+        results = [sourceParts, targetParts];
+      else
+        results = targetParts;
+    }
+    return results;
+  },
+  /**
+   * Method: splitWith
+   * Split this geometry (the target) with the given geometry (the source).
+   *
+   * Parameters:
+   * geometry - {<ZOO.Geometry>} A geometry used to split this
+   *     geometry (the source).
+   * options - {Object} Properties of this object will be used to determine
+   *     how the split is conducted.
+   *
+   * Valid options:
+   * mutual - {Boolean} Split the source geometry in addition to the target
+   *     geometry.  Default is false.
+   * edge - {Boolean} Allow splitting when only edges intersect.  Default is
+   *     true.  If false, a vertex on the source must be within the tolerance
+   *     distance of the intersection to be considered a split.
+   * tolerance - {Number} If a non-null value is provided, intersections
+   *     within the tolerance distance of an existing vertex on the source
+   *     will be assumed to occur at the vertex.
+   * 
+   * Returns:
+   * {Array} A list of geometries (of this same type as the target) that
+   *     result from splitting the target with the source geometry.  The
+   *     source and target geometry will remain unmodified.  If no split
+   *     results, null will be returned.  If mutual is true and a split
+   *     results, return will be an array of two arrays - the first will be
+   *     all geometries that result from splitting the source geometry and
+   *     the second will be all geometries that result from splitting the
+   *     target geometry.
+   */
+  splitWith: function(geometry, options) {
+    return geometry.split(this, options);
+  },
+  /**
+   * Method: getVertices
+   * Return a list of all points in this geometry.
+   *
+   * Parameters:
+   * nodes - {Boolean} For lines, only return vertices that are
+   *     endpoints.  If false, for lines, only vertices that are not
+   *     endpoints will be returned.  If not provided, all vertices will
+   *     be returned.
+   *
+   * Returns:
+   * {Array} A list of all vertices in the geometry.
+   */
+  getVertices: function(nodes) {
+    var vertices;
+    if(nodes === true)
+      vertices = [
+        this.components[0],
+        this.components[this.components.length-1]
+      ];
+    else if (nodes === false)
+      vertices = this.components.slice(1, this.components.length-1);
+    else
+      vertices = this.components.slice();
+    return vertices;
+  },
+  distanceTo: function(geometry, options) {
+    var edge = !(options && options.edge === false);
+    var details = edge && options && options.details;
+    var result, best = {};
+    var min = Number.POSITIVE_INFINITY;
+    if(geometry instanceof ZOO.Geometry.Point) {
+      var segs = this.getSortedSegments();
+      var x = geometry.x;
+      var y = geometry.y;
+      var seg;
+      for(var i=0, len=segs.length; i<len; ++i) {
+        seg = segs[i];
+        result = ZOO.Geometry.distanceToSegment(geometry, seg);
+        if(result.distance < min) {
+          min = result.distance;
+          best = result;
+          if(min === 0)
+            break;
+        } else {
+          // if distance increases and we cross y0 to the right of x0, no need to keep looking.
+          if(seg.x2 > x && ((y > seg.y1 && y < seg.y2) || (y < seg.y1 && y > seg.y2)))
+            break;
+        }
+      }
+      if(details)
+        best = {
+          distance: best.distance,
+          x0: best.x, y0: best.y,
+          x1: x, y1: y
+        };
+      else
+        best = best.distance;
+    } else if(geometry instanceof ZOO.Geometry.LineString) { 
+      var segs0 = this.getSortedSegments();
+      var segs1 = geometry.getSortedSegments();
+      var seg0, seg1, intersection, x0, y0;
+      var len1 = segs1.length;
+      var interOptions = {point: true};
+      outer: for(var i=0, len=segs0.length; i<len; ++i) {
+        seg0 = segs0[i];
+        x0 = seg0.x1;
+        y0 = seg0.y1;
+        for(var j=0; j<len1; ++j) {
+          seg1 = segs1[j];
+          intersection = ZOO.Geometry.segmentsIntersect(seg0, seg1, interOptions);
+          if(intersection) {
+            min = 0;
+            best = {
+              distance: 0,
+              x0: intersection.x, y0: intersection.y,
+              x1: intersection.x, y1: intersection.y
+            };
+            break outer;
+          } else {
+            result = ZOO.Geometry.distanceToSegment({x: x0, y: y0}, seg1);
+            if(result.distance < min) {
+              min = result.distance;
+              best = {
+                distance: min,
+                x0: x0, y0: y0,
+                x1: result.x, y1: result.y
+              };
+            }
+          }
+        }
+      }
+      if(!details)
+        best = best.distance;
+      if(min !== 0) {
+        // check the final vertex in this line's sorted segments
+        if(seg0) {
+          result = geometry.distanceTo(
+              new ZOO.Geometry.Point(seg0.x2, seg0.y2),
+              options
+              );
+          var dist = details ? result.distance : result;
+          if(dist < min) {
+            if(details)
+              best = {
+                distance: min,
+                x0: result.x1, y0: result.y1,
+                x1: result.x0, y1: result.y0
+              };
+            else
+              best = dist;
+          }
+        }
+      }
+    } else {
+      best = geometry.distanceTo(this, options);
+      // swap since target comes from this line
+      if(details)
+        best = {
+          distance: best.distance,
+          x0: best.x1, y0: best.y1,
+          x1: best.x0, y1: best.y0
+        };
+    }
+    return best;
+  },
+  CLASS_NAME: "ZOO.Geometry.LineString"
+});
+/**
+ * Class: ZOO.Geometry.LinearRing
+ * 
+ * A Linear Ring is a special LineString which is closed. It closes itself 
+ * automatically on every addPoint/removePoint by adding a copy of the first
+ * point as the last point. 
+ * 
+ * Also, as it is the first in the line family to close itself, a getArea()
+ * function is defined to calculate the enclosed area of the linearRing
+ * 
+ * Inherits:
+ *  - <ZOO.Geometry.LineString>
+ */
+ZOO.Geometry.LinearRing = ZOO.Class(
+  ZOO.Geometry.LineString, {
+  /**
+   * Property: componentTypes
+   * {Array(String)} An array of class names representing the types of 
+   *                 components that the collection can include.  A null 
+   *                 value means the component types are not restricted.
+   */
+  componentTypes: ["ZOO.Geometry.Point"],
+  /**
+   * Constructor: ZOO.Geometry.LinearRing
+   * Linear rings are constructed with an array of points.  This array
+   *     can represent a closed or open ring.  If the ring is open (the last
+   *     point does not equal the first point), the constructor will close
+   *     the ring.  If the ring is already closed (the last point does equal
+   *     the first point), it will be left closed.
+   * 
+   * Parameters:
+   * points - {Array(<ZOO.Geometry.Point>)} points
+   */
+  initialize: function(points) {
+    ZOO.Geometry.LineString.prototype.initialize.apply(this,arguments);
+  },
+  /**
+   * Method: addComponent
+   * Adds a point to geometry components.  If the point is to be added to
+   *     the end of the components array and it is the same as the last point
+   *     already in that array, the duplicate point is not added.  This has 
+   *     the effect of closing the ring if it is not already closed, and 
+   *     doing the right thing if it is already closed.  This behavior can 
+   *     be overridden by calling the method with a non-null index as the 
+   *     second argument.
+   *
+   * Parameter:
+   * point - {<ZOO.Geometry.Point>}
+   * index - {Integer} Index into the array to insert the component
+   * 
+   * Returns:
+   * {Boolean} Was the Point successfully added?
+   */
+  addComponent: function(point, index) {
+    var added = false;
+    //remove last point
+    var lastPoint = this.components.pop();
+    // given an index, add the point
+    // without an index only add non-duplicate points
+    if(index != null || !point.equals(lastPoint))
+      added = ZOO.Geometry.Collection.prototype.addComponent.apply(this,arguments);
+    //append copy of first point
+    var firstPoint = this.components[0];
+    ZOO.Geometry.Collection.prototype.addComponent.apply(this,[firstPoint]);
+    return added;
+  },
+  /**
+   * APIMethod: removeComponent
+   * Removes a point from geometry components.
+   *
+   * Parameters:
+   * point - {<ZOO.Geometry.Point>}
+   */
+  removeComponent: function(point) {
+    if (this.components.length > 4) {
+      //remove last point
+      this.components.pop();
+      //remove our point
+      ZOO.Geometry.Collection.prototype.removeComponent.apply(this,arguments);
+      //append copy of first point
+      var firstPoint = this.components[0];
+      ZOO.Geometry.Collection.prototype.addComponent.apply(this,[firstPoint]);
+    }
+  },
+  /**
+   * Method: move
+   * Moves a geometry by the given displacement along positive x and y axes.
+   *     This modifies the position of the geometry and clears the cached
+   *     bounds.
+   *
+   * Parameters:
+   * x - {Float} Distance to move geometry in positive x direction. 
+   * y - {Float} Distance to move geometry in positive y direction.
+   */
+  move: function(x, y) {
+    for(var i = 0, len=this.components.length; i<len - 1; i++) {
+      this.components[i].move(x, y);
+    }
+  },
+  /**
+   * Method: rotate
+   * Rotate a geometry around some origin
+   *
+   * Parameters:
+   * angle - {Float} Rotation angle in degrees (measured counterclockwise
+   *                 from the positive x-axis)
+   * origin - {<ZOO.Geometry.Point>} Center point for the rotation
+   */
+  rotate: function(angle, origin) {
+    for(var i=0, len=this.components.length; i<len - 1; ++i) {
+      this.components[i].rotate(angle, origin);
+    }
+  },
+  /**
+   * Method: resize
+   * Resize a geometry relative to some origin.  Use this method to apply
+   *     a uniform scaling to a geometry.
+   *
+   * Parameters:
+   * scale - {Float} Factor by which to scale the geometry.  A scale of 2
+   *                 doubles the size of the geometry in each dimension
+   *                 (lines, for example, will be twice as long, and polygons
+   *                 will have four times the area).
+   * origin - {<ZOO.Geometry.Point>} Point of origin for resizing
+   * ratio - {Float} Optional x:y ratio for resizing.  Default ratio is 1.
+   * 
+   * Returns:
+   * {ZOO.Geometry} - The current geometry. 
+   */
+  resize: function(scale, origin, ratio) {
+    for(var i=0, len=this.components.length; i<len - 1; ++i) {
+      this.components[i].resize(scale, origin, ratio);
+    }
+    return this;
+  },
+  /**
+   * Method: transform
+   * Reproject the components geometry from source to dest.
+   *
+   * Parameters:
+   * source - {<ZOO.Projection>}
+   * dest - {<ZOO.Projection>}
+   * 
+   * Returns:
+   * {<ZOO.Geometry>} 
+   */
+  transform: function(source, dest) {
+    if (source && dest) {
+      for (var i=0, len=this.components.length; i<len - 1; i++) {
+        var component = this.components[i];
+        component.transform(source, dest);
+      }
+      this.bounds = null;
+    }
+    return this;
+  },
+  /**
+   * Method: getCentroid
+   *
+   * Returns:
+   * {<ZOO.Geometry.Point>} The centroid of the ring
+   */
+  getCentroid: function() {
+    if ( this.components && (this.components.length > 2)) {
+      var sumX = 0.0;
+      var sumY = 0.0;
+      for (var i = 0; i < this.components.length - 1; i++) {
+        var b = this.components[i];
+        var c = this.components[i+1];
+        sumX += (b.x + c.x) * (b.x * c.y - c.x * b.y);
+        sumY += (b.y + c.y) * (b.x * c.y - c.x * b.y);
+      }
+      var area = -1 * this.getArea();
+      var x = sumX / (6 * area);
+      var y = sumY / (6 * area);
+    }
+    return new ZOO.Geometry.Point(x, y);
+  },
+  /**
+   * Method: getArea
+   * Note - The area is positive if the ring is oriented CW, otherwise
+   *         it will be negative.
+   * 
+   * Returns:
+   * {Float} The signed area for a ring.
+   */
+  getArea: function() {
+    var area = 0.0;
+    if ( this.components && (this.components.length > 2)) {
+      var sum = 0.0;
+      for (var i=0, len=this.components.length; i<len - 1; i++) {
+        var b = this.components[i];
+        var c = this.components[i+1];
+        sum += (b.x + c.x) * (c.y - b.y);
+      }
+      area = - sum / 2.0;
+    }
+    return area;
+  },
+  /**
+   * Method: getGeodesicArea
+   * Calculate the approximate area of the polygon were it projected onto
+   *     the earth.  Note that this area will be positive if ring is oriented
+   *     clockwise, otherwise it will be negative.
+   *
+   * Parameters:
+   * projection - {<ZOO.Projection>} The spatial reference system
+   *     for the geometry coordinates.  If not provided, Geographic/WGS84 is
+   *     assumed.
+   * 
+   * Reference:
+   * Robert. G. Chamberlain and William H. Duquette, "Some Algorithms for
+   *     Polygons on a Sphere", JPL Publication 07-03, Jet Propulsion
+   *     Laboratory, Pasadena, CA, June 2007 http://trs-new.jpl.nasa.gov/dspace/handle/2014/40409
+   *
+   * Returns:
+   * {float} The approximate signed geodesic area of the polygon in square
+   *     meters.
+   */
+  getGeodesicArea: function(projection) {
+    var ring = this;  // so we can work with a clone if needed
+    if(projection) {
+      var gg = new ZOO.Projection("EPSG:4326");
+      if(!gg.equals(projection)) {
+        ring = this.clone().transform(projection, gg);
+      }
+    }
+    var area = 0.0;
+    var len = ring.components && ring.components.length;
+    if(len > 2) {
+      var p1, p2;
+      for(var i=0; i<len-1; i++) {
+        p1 = ring.components[i];
+        p2 = ring.components[i+1];
+        area += ZOO.rad(p2.x - p1.x) *
+                (2 + Math.sin(ZOO.rad(p1.y)) +
+                Math.sin(ZOO.rad(p2.y)));
+      }
+      area = area * 6378137.0 * 6378137.0 / 2.0;
+    }
+    return area;
+  },
+  /**
+   * Method: containsPoint
+   * Test if a point is inside a linear ring.  For the case where a point
+   *     is coincident with a linear ring edge, returns 1.  Otherwise,
+   *     returns boolean.
+   *
+   * Parameters:
+   * point - {<ZOO.Geometry.Point>}
+   *
+   * Returns:
+   * {Boolean | Number} The point is inside the linear ring.  Returns 1 if
+   *     the point is coincident with an edge.  Returns boolean otherwise.
+   */
+  containsPoint: function(point) {
+    var approx = OpenLayers.Number.limitSigDigs;
+    var digs = 14;
+    var px = approx(point.x, digs);
+    var py = approx(point.y, digs);
+    function getX(y, x1, y1, x2, y2) {
+      return (((x1 - x2) * y) + ((x2 * y1) - (x1 * y2))) / (y1 - y2);
+    }
+    var numSeg = this.components.length - 1;
+    var start, end, x1, y1, x2, y2, cx, cy;
+    var crosses = 0;
+    for(var i=0; i<numSeg; ++i) {
+      start = this.components[i];
+      x1 = approx(start.x, digs);
+      y1 = approx(start.y, digs);
+      end = this.components[i + 1];
+      x2 = approx(end.x, digs);
+      y2 = approx(end.y, digs);
+
+      /**
+       * The following conditions enforce five edge-crossing rules:
+       *    1. points coincident with edges are considered contained;
+       *    2. an upward edge includes its starting endpoint, and
+       *    excludes its final endpoint;
+       *    3. a downward edge excludes its starting endpoint, and
+       *    includes its final endpoint;
+       *    4. horizontal edges are excluded; and
+       *    5. the edge-ray intersection point must be strictly right
+       *    of the point P.
+       */
+      if(y1 == y2) {
+        // horizontal edge
+        if(py == y1) {
+          // point on horizontal line
+          if(x1 <= x2 && (px >= x1 && px <= x2) || // right or vert
+              x1 >= x2 && (px <= x1 && px >= x2)) { // left or vert
+            // point on edge
+            crosses = -1;
+            break;
+          }
+        }
+        // ignore other horizontal edges
+        continue;
+      }
+      cx = approx(getX(py, x1, y1, x2, y2), digs);
+      if(cx == px) {
+        // point on line
+        if(y1 < y2 && (py >= y1 && py <= y2) || // upward
+            y1 > y2 && (py <= y1 && py >= y2)) { // downward
+          // point on edge
+          crosses = -1;
+          break;
+        }
+      }
+      if(cx <= px) {
+        // no crossing to the right
+        continue;
+      }
+      if(x1 != x2 && (cx < Math.min(x1, x2) || cx > Math.max(x1, x2))) {
+        // no crossing
+        continue;
+      }
+      if(y1 < y2 && (py >= y1 && py < y2) || // upward
+          y1 > y2 && (py < y1 && py >= y2)) { // downward
+        ++crosses;
+      }
+    }
+    var contained = (crosses == -1) ?
+      // on edge
+      1 :
+      // even (out) or odd (in)
+      !!(crosses & 1);
+
+    return contained;
+  },
+  intersects: function(geometry) {
+    var intersect = false;
+    if(geometry.CLASS_NAME == "ZOO.Geometry.Point")
+      intersect = this.containsPoint(geometry);
+    else if(geometry.CLASS_NAME == "ZOO.Geometry.LineString")
+      intersect = geometry.intersects(this);
+    else if(geometry.CLASS_NAME == "ZOO.Geometry.LinearRing")
+      intersect = ZOO.Geometry.LineString.prototype.intersects.apply(
+          this, [geometry]
+          );
+    else
+      for(var i=0, len=geometry.components.length; i<len; ++ i) {
+        intersect = geometry.components[i].intersects(this);
+        if(intersect)
+          break;
+      }
+    return intersect;
+  },
+  getVertices: function(nodes) {
+    return (nodes === true) ? [] : this.components.slice(0, this.components.length-1);
+  },
+  CLASS_NAME: "ZOO.Geometry.LinearRing"
+});
+/**
+ * Class: ZOO.Geometry.MultiLineString
+ * A MultiLineString is a geometry with multiple <ZOO.Geometry.LineString>
+ * components.
+ * 
+ * Inherits from:
+ *  - <ZOO.Geometry.Collection>
+ */
+ZOO.Geometry.MultiLineString = ZOO.Class(
+  ZOO.Geometry.Collection, {
+  componentTypes: ["ZOO.Geometry.LineString"],
+  /**
+   * Constructor: ZOO.Geometry.MultiLineString
+   * Constructor for a MultiLineString Geometry.
+   *
+   * Parameters: 
+   * components - {Array(<ZOO.Geometry.LineString>)} 
+   *
+   */
+  initialize: function(components) {
+    ZOO.Geometry.Collection.prototype.initialize.apply(this,arguments);        
+  },
+  split: function(geometry, options) {
+    var results = null;
+    var mutual = options && options.mutual;
+    var splits, sourceLine, sourceLines, sourceSplit, targetSplit;
+    var sourceParts = [];
+    var targetParts = [geometry];
+    for(var i=0, len=this.components.length; i<len; ++i) {
+      sourceLine = this.components[i];
+      sourceSplit = false;
+      for(var j=0; j < targetParts.length; ++j) { 
+        splits = sourceLine.split(targetParts[j], options);
+        if(splits) {
+          if(mutual) {
+            sourceLines = splits[0];
+            for(var k=0, klen=sourceLines.length; k<klen; ++k) {
+              if(k===0 && sourceParts.length)
+                sourceParts[sourceParts.length-1].addComponent(
+                  sourceLines[k]
+                );
+              else
+                sourceParts.push(
+                  new ZOO.Geometry.MultiLineString([
+                    sourceLines[k]
+                    ])
+                );
+            }
+            sourceSplit = true;
+            splits = splits[1];
+          }
+          if(splits.length) {
+            // splice in new target parts
+            splits.unshift(j, 1);
+            Array.prototype.splice.apply(targetParts, splits);
+            break;
+          }
+        }
+      }
+      if(!sourceSplit) {
+        // source line was not hit
+        if(sourceParts.length) {
+          // add line to existing multi
+          sourceParts[sourceParts.length-1].addComponent(
+              sourceLine.clone()
+              );
+        } else {
+          // create a fresh multi
+          sourceParts = [
+            new ZOO.Geometry.MultiLineString(
+                sourceLine.clone()
+                )
+            ];
+        }
+      }
+    }
+    if(sourceParts && sourceParts.length > 1)
+      sourceSplit = true;
+    else
+      sourceParts = [];
+    if(targetParts && targetParts.length > 1)
+      targetSplit = true;
+    else
+      targetParts = [];
+    if(sourceSplit || targetSplit) {
+      if(mutual)
+        results = [sourceParts, targetParts];
+      else
+        results = targetParts;
+    }
+    return results;
+  },
+  splitWith: function(geometry, options) {
+    var results = null;
+    var mutual = options && options.mutual;
+    var splits, targetLine, sourceLines, sourceSplit, targetSplit, sourceParts, targetParts;
+    if(geometry instanceof ZOO.Geometry.LineString) {
+      targetParts = [];
+      sourceParts = [geometry];
+      for(var i=0, len=this.components.length; i<len; ++i) {
+        targetSplit = false;
+        targetLine = this.components[i];
+        for(var j=0; j<sourceParts.length; ++j) {
+          splits = sourceParts[j].split(targetLine, options);
+          if(splits) {
+            if(mutual) {
+              sourceLines = splits[0];
+              if(sourceLines.length) {
+                // splice in new source parts
+                sourceLines.unshift(j, 1);
+                Array.prototype.splice.apply(sourceParts, sourceLines);
+                j += sourceLines.length - 2;
+              }
+              splits = splits[1];
+              if(splits.length === 0) {
+                splits = [targetLine.clone()];
+              }
+            }
+            for(var k=0, klen=splits.length; k<klen; ++k) {
+              if(k===0 && targetParts.length) {
+                targetParts[targetParts.length-1].addComponent(
+                    splits[k]
+                    );
+              } else {
+                targetParts.push(
+                    new ZOO.Geometry.MultiLineString([
+                      splits[k]
+                      ])
+                    );
+              }
+            }
+            targetSplit = true;                    
+          }
+        }
+        if(!targetSplit) {
+          // target component was not hit
+          if(targetParts.length) {
+            // add it to any existing multi-line
+            targetParts[targetParts.length-1].addComponent(
+                targetLine.clone()
+                );
+          } else {
+            // or start with a fresh multi-line
+            targetParts = [
+              new ZOO.Geometry.MultiLineString([
+                  targetLine.clone()
+                  ])
+              ];
+          }
+
+        }
+      }
+    } else {
+      results = geometry.split(this);
+    }
+    if(sourceParts && sourceParts.length > 1)
+      sourceSplit = true;
+    else
+      sourceParts = [];
+    if(targetParts && targetParts.length > 1)
+      targetSplit = true;
+    else
+      targetParts = [];
+    if(sourceSplit || targetSplit) {
+      if(mutual)
+        results = [sourceParts, targetParts];
+      else
+        results = targetParts;
+    }
+    return results;
+  },
+  CLASS_NAME: "ZOO.Geometry.MultiLineString"
+});
+/**
+ * Class: ZOO.Geometry.Polygon 
+ * Polygon is a collection of <ZOO.Geometry.LinearRing>. 
+ * 
+ * Inherits from:
+ *  - <ZOO.Geometry.Collection> 
+ */
+ZOO.Geometry.Polygon = ZOO.Class(
+  ZOO.Geometry.Collection, {
+  componentTypes: ["ZOO.Geometry.LinearRing"],
+  /**
+   * Constructor: ZOO.Geometry.Polygon
+   * Constructor for a Polygon geometry. 
+   * The first ring (this.component[0])is the outer bounds of the polygon and 
+   * all subsequent rings (this.component[1-n]) are internal holes.
+   *
+   *
+   * Parameters:
+   * components - {Array(<ZOO.Geometry.LinearRing>)} 
+   */
+  initialize: function(components) {
+    ZOO.Geometry.Collection.prototype.initialize.apply(this,arguments);
+  },
+  /** 
+   * Method: getArea
+   * Calculated by subtracting the areas of the internal holes from the 
+   *   area of the outer hole.
+   * 
+   * Returns:
+   * {float} The area of the geometry
+   */
+  getArea: function() {
+    var area = 0.0;
+    if ( this.components && (this.components.length > 0)) {
+      area += Math.abs(this.components[0].getArea());
+      for (var i=1, len=this.components.length; i<len; i++) {
+        area -= Math.abs(this.components[i].getArea());
+      }
+    }
+    return area;
+  },
+  /** 
+   * APIMethod: getGeodesicArea
+   * Calculate the approximate area of the polygon were it projected onto
+   *     the earth.
+   *
+   * Parameters:
+   * projection - {<ZOO.Projection>} The spatial reference system
+   *     for the geometry coordinates.  If not provided, Geographic/WGS84 is
+   *     assumed.
+   * 
+   * Reference:
+   * Robert. G. Chamberlain and William H. Duquette, "Some Algorithms for
+   *     Polygons on a Sphere", JPL Publication 07-03, Jet Propulsion
+   *     Laboratory, Pasadena, CA, June 2007 http://trs-new.jpl.nasa.gov/dspace/handle/2014/40409
+   *
+   * Returns:
+   * {float} The approximate geodesic area of the polygon in square meters.
+   */
+  getGeodesicArea: function(projection) {
+    var area = 0.0;
+    if(this.components && (this.components.length > 0)) {
+      area += Math.abs(this.components[0].getGeodesicArea(projection));
+      for(var i=1, len=this.components.length; i<len; i++) {
+          area -= Math.abs(this.components[i].getGeodesicArea(projection));
+      }
+    }
+    return area;
+  },
+  /**
+   * Method: containsPoint
+   * Test if a point is inside a polygon.  Points on a polygon edge are
+   *     considered inside.
+   *
+   * Parameters:
+   * point - {<ZOO.Geometry.Point>}
+   *
+   * Returns:
+   * {Boolean | Number} The point is inside the polygon.  Returns 1 if the
+   *     point is on an edge.  Returns boolean otherwise.
+   */
+  containsPoint: function(point) {
+    var numRings = this.components.length;
+    var contained = false;
+    if(numRings > 0) {
+    // check exterior ring - 1 means on edge, boolean otherwise
+      contained = this.components[0].containsPoint(point);
+      if(contained !== 1) {
+        if(contained && numRings > 1) {
+          // check interior rings
+          var hole;
+          for(var i=1; i<numRings; ++i) {
+            hole = this.components[i].containsPoint(point);
+            if(hole) {
+              if(hole === 1)
+                contained = 1;
+              else
+                contained = false;
+              break;
+            }
+          }
+        }
+      }
+    }
+    return contained;
+  },
+  intersects: function(geometry) {
+    var intersect = false;
+    var i, len;
+    if(geometry.CLASS_NAME == "ZOO.Geometry.Point") {
+      intersect = this.containsPoint(geometry);
+    } else if(geometry.CLASS_NAME == "ZOO.Geometry.LineString" ||
+              geometry.CLASS_NAME == "ZOO.Geometry.LinearRing") {
+      // check if rings/linestrings intersect
+      for(i=0, len=this.components.length; i<len; ++i) {
+        intersect = geometry.intersects(this.components[i]);
+        if(intersect) {
+          break;
+        }
+      }
+      if(!intersect) {
+        // check if this poly contains points of the ring/linestring
+        for(i=0, len=geometry.components.length; i<len; ++i) {
+          intersect = this.containsPoint(geometry.components[i]);
+          if(intersect) {
+            break;
+          }
+        }
+      }
+    } else {
+      for(i=0, len=geometry.components.length; i<len; ++ i) {
+        intersect = this.intersects(geometry.components[i]);
+        if(intersect)
+          break;
+      }
+    }
+    // check case where this poly is wholly contained by another
+    if(!intersect && geometry.CLASS_NAME == "ZOO.Geometry.Polygon") {
+      // exterior ring points will be contained in the other geometry
+      var ring = this.components[0];
+      for(i=0, len=ring.components.length; i<len; ++i) {
+        intersect = geometry.containsPoint(ring.components[i]);
+        if(intersect)
+          break;
+      }
+    }
+    return intersect;
+  },
+  distanceTo: function(geometry, options) {
+    var edge = !(options && options.edge === false);
+    var result;
+    // this is the case where we might not be looking for distance to edge
+    if(!edge && this.intersects(geometry))
+      result = 0;
+    else
+      result = ZOO.Geometry.Collection.prototype.distanceTo.apply(
+          this, [geometry, options]
+          );
+    return result;
+  },
+  CLASS_NAME: "ZOO.Geometry.Polygon"
+});
+/**
+ * Method: createRegularPolygon
+ * Create a regular polygon around a radius. Useful for creating circles 
+ * and the like.
+ *
+ * Parameters:
+ * origin - {<ZOO.Geometry.Point>} center of polygon.
+ * radius - {Float} distance to vertex, in map units.
+ * sides - {Integer} Number of sides. 20 approximates a circle.
+ * rotation - {Float} original angle of rotation, in degrees.
+ */
+ZOO.Geometry.Polygon.createRegularPolygon = function(origin, radius, sides, rotation) {  
+    var angle = Math.PI * ((1/sides) - (1/2));
+    if(rotation) {
+        angle += (rotation / 180) * Math.PI;
+    }
+    var rotatedAngle, x, y;
+    var points = [];
+    for(var i=0; i<sides; ++i) {
+        rotatedAngle = angle + (i * 2 * Math.PI / sides);
+        x = origin.x + (radius * Math.cos(rotatedAngle));
+        y = origin.y + (radius * Math.sin(rotatedAngle));
+        points.push(new ZOO.Geometry.Point(x, y));
+    }
+    var ring = new ZOO.Geometry.LinearRing(points);
+    return new ZOO.Geometry.Polygon([ring]);
+};
+/**
+ * Class: ZOO.Geometry.MultiPolygon
+ * MultiPolygon is a geometry with multiple <ZOO.Geometry.Polygon>
+ * components.  Create a new instance with the <ZOO.Geometry.MultiPolygon>
+ * constructor.
+ * 
+ * Inherits from:
+ *  - <ZOO.Geometry.Collection>
+ */
+ZOO.Geometry.MultiPolygon = ZOO.Class(
+  ZOO.Geometry.Collection, {
+  componentTypes: ["ZOO.Geometry.Polygon"],
+  /**
+   * Constructor: ZOO.Geometry.MultiPolygon
+   * Create a new MultiPolygon geometry
+   *
+   * Parameters:
+   * components - {Array(<ZOO.Geometry.Polygon>)} An array of polygons
+   *              used to generate the MultiPolygon
+   *
+   */
+  initialize: function(components) {
+    ZOO.Geometry.Collection.prototype.initialize.apply(this,arguments);
+  },
+  CLASS_NAME: "ZOO.Geometry.MultiPolygon"
+});
+/**
+ * Class: ZOO.Process
+ * Used to query OGC WPS process defined by its URL and its identifier. 
+ * Usefull for chaining localhost process.
+ */
+ZOO.Process = ZOO.Class({
+  /**
+   * Property: schemaLocation
+   * {String} Schema location for a particular minor version.
+   */
+  schemaLocation: "http://www.opengis.net/wps/1.0.0/../wpsExecute_request.xsd",
+  /**
+   * Property: namespaces
+   * {Object} Mapping of namespace aliases to namespace URIs.
+   */
+  namespaces: {
+    ows: "http://www.opengis.net/ows/1.1",
+    wps: "http://www.opengis.net/wps/1.0.0",
+    xlink: "http://www.w3.org/1999/xlink",
+    xsi: "http://www.w3.org/2001/XMLSchema-instance",
+  },
+  /**
+   * Property: url
+   * {String} The OGC's Web PRocessing Service URL, 
+   *          default is http://localhost/zoo.
+   */
+  url: 'http://localhost/zoo',
+  /**
+   * Property: identifier
+   * {String} Process identifier in the OGC's Web Processing Service.
+   */
+  identifier: null,
+  /**
+   * Constructor: ZOO.Process
+   * Create a new Process
+   *
+   * Parameters:
+   * url - {String} The OGC's Web Processing Service URL.
+   * identifier - {String} The process identifier in the OGC's Web Processing Service.
+   *
+   */
+  initialize: function(url,identifier) {
+    this.url = url;
+    this.identifier = identifier;
+  },
+  /**
+   * Method: Execute
+   * Query the OGC's Web PRocessing Servcie to Execute the process.
+   *
+   * Parameters:
+   * inputs - {Object}
+   *
+   * Returns:
+   * {String} The OGC's Web processing Service XML response. The result 
+   *          needs to be interpreted.
+   */
+  Execute: function(inputs,outputs) {
+    if (this.identifier == null)
+      return null;
+    var body = new XML('<wps:Execute service="WPS" version="1.0.0" xmlns:wps="'+this.namespaces['wps']+'" xmlns:ows="'+this.namespaces['ows']+'" xmlns:xlink="'+this.namespaces['xlink']+'" xmlns:xsi="'+this.namespaces['xsi']+'" xsi:schemaLocation="'+this.schemaLocation+'"><ows:Identifier>'+this.identifier+'</ows:Identifier>'+this.buildDataInputsNode(inputs)+this.buildDataOutputsNode(outputs)+'</wps:Execute>');
+    body = body.toXMLString();
+    var headers=['Content-Type: text/xml; charset=UTF-8'];
+      if(arguments.length>2){
+	headers[headers.length]=arguments[2];
+      }
+    var response = ZOO.Request.Post(this.url,body,headers);
+    return response;
+  },
+  buildOutput:{
+    /**
+     * Method: buildOutput.ResponseDocument
+     * Given an E4XElement representing the WPS ResponseDocument output.
+     *
+     * Parameters:
+     * identifier - {String} the input indetifier
+     * data - {Object} A WPS complex data input.
+     *
+     * Returns:
+     * {E4XElement} A WPS Input node.
+     */
+    'ResponseDocument': function(identifier,obj) {
+      var output = new XML('<wps:ResponseForm xmlns:wps="'+this.namespaces['wps']+'"><wps:ResponseDocument><wps:Output'+(obj["mimeType"]?' mimeType="'+obj["mimeType"]+'" ':'')+(obj["encoding"]?' encoding="'+obj["encoding"]+'" ':'')+(obj["asReference"]?' asReference="'+obj["asReference"]+'" ':'')+'><ows:Identifier xmlns:ows="'+this.namespaces['ows']+'">'+identifier+'</ows:Identifier></wps:Output></wps:ResponseDocument></wps:ResponseForm>');
+      if (obj.encoding)
+        output.*::Data.*::ComplexData. at encoding = obj.encoding;
+      if (obj.schema)
+        output.*::Data.*::ComplexData. at schema = obj.schema;
+      output = output.toXMLString();
+      return output;
+    },
+    'RawDataOutput': function(identifier,obj) {
+      var output = new XML('<wps:ResponseForm xmlns:wps="'+this.namespaces['wps']+'"><wps:RawDataOutput '+(obj["mimeType"]?' mimeType="'+obj["mimeType"]+'" ':'')+(obj["encoding"]?' encoding="'+obj["encoding"]+'" ':'')+'><ows:Identifier xmlns:ows="'+this.namespaces['ows']+'">'+identifier+'</ows:Identifier></wps:RawDataOutput></wps:ResponseForm>');
+      if (obj.encoding)
+        output.*::Data.*::ComplexData. at encoding = obj.encoding;
+      if (obj.schema)
+        output.*::Data.*::ComplexData. at schema = obj.schema;
+      output = output.toXMLString();
+      return output;
+    }
+
+  },
+  /**
+   * Property: buildInput
+   * Object containing methods to build WPS inputs.
+   */
+  buildInput: {
+    /**
+     * Method: buildInput.complex
+     * Given an E4XElement representing the WPS complex data input.
+     *
+     * Parameters:
+     * identifier - {String} the input indetifier
+     * data - {Object} A WPS complex data input.
+     *
+     * Returns:
+     * {E4XElement} A WPS Input node.
+     */
+    'complex': function(identifier,data) {
+      var input = new XML('<wps:Input xmlns:wps="'+this.namespaces['wps']+'"><ows:Identifier xmlns:ows="'+this.namespaces['ows']+'">'+identifier+'</ows:Identifier>'+(data.value?'<wps:Data><wps:ComplexData><![CDATA['+data.value+']]></wps:ComplexData></wps:Data>':(data.xlink?'<wps:Reference xmlns:xlink="'+this.namespaces['xlink']+'" xlink:href="'+data.xlink+'" mimeType="'+data.mimeType+'" />':''))+'</wps:Input>');
+      if(data.xlink)
+	input.*::Reference. at mimeType = data.mimetype ? data.mimetype : 'application/json';
+      else
+	input.*::Data.*::ComplexData. at mimeType = data.mimetype ? data.mimetype : 'application/json';
+      if (data.encoding)
+        input.*::Data.*::ComplexData. at encoding = data.encoding;
+      if (data.schema)
+        input.*::Data.*::ComplexData. at schema = data.schema;
+      input = input.toXMLString();
+      return input;
+    },
+    /**
+     * Method: buildInput.reference
+     * Given an E4XElement representing the WPS reference input.
+     *
+     * Parameters:
+     * identifier - {String} the input indetifier
+     * data - {Object} A WPS reference input.
+     *
+     * Returns:
+     * {E4XElement} A WPS Input node.
+     */
+    'reference': function(identifier,data) {
+      return '<wps:Input xmlns:wps="'+this.namespaces['wps']+'"><ows:Identifier xmlns:ows="'+this.namespaces['ows']+'">'+identifier+'</ows:Identifier><wps:Reference xmlns:xlink="'+this.namespaces['xlink']+'" xlink:href="'+data.value.replace('&','&','gi')+'"/></wps:Input>';
+    },
+    /**
+     * Method: buildInput.literal
+     * Given an E4XElement representing the WPS literal data input.
+     *
+     * Parameters:
+     * identifier - {String} the input indetifier
+     * data - {Object} A WPS literal data input.
+     *
+     * Returns:
+     * {E4XElement} The WPS Input node.
+     */
+    'literal': function(identifier,data) {
+	if(data && !eval(data["isArray"])){
+	    var input = new XML('<wps:Input xmlns:wps="'+this.namespaces['wps']+'"><ows:Identifier xmlns:ows="'+this.namespaces['ows']+'">'+identifier+'</ows:Identifier><wps:Data><wps:LiteralData>'+data.value+'</wps:LiteralData></wps:Data></wps:Input>');
+      if (data.type)
+        input.*::Data.*::LiteralData. at dataType = data.type;
+      if (data.uom)
+        input.*::Data.*::LiteralData. at uom = data.uom;
+      input = input.toXMLString();
+      return input;
+	}else if(data){
+	    var inputf="";
+	    for(i=0;i<parseInt(data["length"]);i++){
+		var input = new XML('<wps:Input xmlns:wps="'+this.namespaces['wps']+'"><ows:Identifier xmlns:ows="'+this.namespaces['ows']+'">'+identifier+'</ows:Identifier><wps:Data><wps:LiteralData>'+data.value[i]+'</wps:LiteralData></wps:Data></wps:Input>');
+		if (data.type)
+		    input.*::Data.*::LiteralData. at dataType = data.type;
+		if (data.uom)
+		    input.*::Data.*::LiteralData. at uom = data.uom;
+		inputf += input.toXMLString();
+	    }
+	    return inputf;
+	}
+	
+    }
+  },
+  /**
+   * Method: buildDataInputsNode
+   * Method to build the WPS DataInputs element.
+   *
+   * Parameters:
+   * inputs - {Object}
+   *
+   * Returns:
+   * {E4XElement} The WPS DataInputs node for Execute query.
+   */
+  buildDataInputsNode:function(inputs){
+    var data, builder, inputsArray=[];
+    for (var attr in inputs) {
+      data = inputs[attr];
+	if (data && (data.mimetype || data.type == 'complex'))
+        builder = this.buildInput['complex'];
+	else if (data && (data.type == 'reference' || data.type == 'url'))
+        builder = this.buildInput['reference'];
+      else
+        builder = this.buildInput['literal'];
+      inputsArray.push(builder.apply(this,[attr,data]));
+    }
+    return '<wps:DataInputs xmlns:wps="'+this.namespaces['wps']+'">'+inputsArray.join('\n')+'</wps:DataInputs>';
+  },
+
+  buildDataOutputsNode:function(outputs){
+    var data, builder, outputsArray=[];
+    for (var attr in outputs) {
+      data = outputs[attr];
+      builder = this.buildOutput[data.type];
+      outputsArray.push(builder.apply(this,[attr,data]));
+    }
+    return outputsArray.join('\n');
+  },
+
+  CLASS_NAME: "ZOO.Process"
+});
diff --git a/zoo-project/zoo-api/js/ZOO-proj4js.js b/zoo-project/zoo-api/js/ZOO-proj4js.js
new file mode 100644
index 0000000..9c2a9c5
--- /dev/null
+++ b/zoo-project/zoo-api/js/ZOO-proj4js.js
@@ -0,0 +1,258 @@
+/*
+  proj4js.js -- Javascript reprojection library. 
+  
+  Authors:      Mike Adair madairATdmsolutions.ca
+                Richard Greenwood richATgreenwoodmap.com
+                Didier Richard didier.richardATign.fr
+                Stephen Irons
+  License:      MIT as per: http://trac.osgeo.org/proj4js/browser/trunk/LICENSE
+                Note: This program is an almost direct port of the C library
+                Proj4.
+*/
+
+/**
+ * Author : René-Luc D'Hont
+ *
+ * Copyright 2010 3liz SARL. All rights reserved.
+ */
+
+Proj4js={defaultDatum:'WGS84',transform:function(source,dest,point){if(!source.readyToUse||!dest.readyToUse){this.reportError("Proj4js initialization for "+source.srsCode+" not yet complete");return point;}
+if((source.srsProjNumber=="900913"&&dest.datumCode!="WGS84")||(dest.srsProjNumber=="900913"&&source.datumCode!="WGS84")){var wgs84=Proj4js.WGS84;this.transform(source,wgs84,point);source=wgs84;}
+if(source.projName=="longlat"){point.x*=Proj4js.common.D2R;point.y*=Proj4js.common.D2R;}else{if(source.to_meter){point.x*=source.to_meter;point.y*=source.to_meter;}
+source.inverse(point);}
+if(source.from_greenwich){point.x+=source.from_greenwich;}
+point=this.datum_transform(source.datum,dest.datum,point);if(dest.from_greenwich){point.x-=dest.from_greenwich;}
+if(dest.projName=="longlat"){point.x*=Proj4js.common.R2D;point.y*=Proj4js.common.R2D;}else{dest.forward(point);if(dest.to_meter){point.x/=dest.to_meter;point.y/=dest.to_meter;}}
+return point;},datum_transform:function(source,dest,point){if(source.compare_datums(dest)){return point;}
+if(source.datum_type==Proj4js.common.PJD_NODATUM||dest.datum_type==Proj4js.common.PJD_NODATUM){return point;}
+if(source.datum_type==Proj4js.common.PJD_GRIDSHIFT)
+{alert("ERROR: Grid shift transformations are not implemented yet.");}
+if(dest.datum_type==Proj4js.common.PJD_GRIDSHIFT)
+{alert("ERROR: Grid shift transformations are not implemented yet.");}
+if(source.es!=dest.es||source.a!=dest.a||source.datum_type==Proj4js.common.PJD_3PARAM||source.datum_type==Proj4js.common.PJD_7PARAM||dest.datum_type==Proj4js.common.PJD_3PARAM||dest.datum_type==Proj4js.common.PJD_7PARAM)
+{source.geodetic_to_geocentric(point);if(source.datum_type==Proj4js.common.PJD_3PARAM||source.datum_type==Proj4js.common.PJD_7PARAM){source.geocentric_to_wgs84(point);}
+if(dest.datum_type==Proj4js.common.PJD_3PARAM||dest.datum_type==Proj4js.common.PJD_7PARAM){dest.geocentric_from_wgs84(point);}
+dest.geocentric_to_geodetic(point);}
+if(dest.datum_type==Proj4js.common.PJD_GRIDSHIFT)
+{alert("ERROR: Grid shift transformations are not implemented yet.");}
+return point;},reportError:function(msg){},extend:function(destination,source){destination=destination||{};if(source){for(var property in source){var value=source[property];if(value!==undefined){destination[property]=value;}}}
+return destination;},Class:function(){var Class=function(){this.initialize.apply(this,arguments);};var extended={};var parent;for(var i=0;i<arguments.length;++i){if(typeof arguments[i]=="function"){parent=arguments[i].prototype;}else{parent=arguments[i];}
+Proj4js.extend(extended,parent);}
+Class.prototype=extended;return Class;},bind:function(func,object){var args=Array.prototype.slice.apply(arguments,[2]);return function(){var newArgs=args.concat(Array.prototype.slice.apply(arguments,[0]));return func.apply(object,newArgs);};},scriptName:"proj4js-compressed.js",defsLookupService:'http://spatialreference.org/ref',libPath:null,getScriptLocation:function(){if(this.libPath)return this.libPath;var scriptName=this.scriptName;var scriptNameLen=scriptName.length;var scripts=docum [...]
+return this.libPath||"";},
+  loadScript:function(url,onload,onfail,loadCheck){
+    var script = [];
+  var script = ZOORequest('GET',url);
+  try {
+    eval(script);
+    onload();
+  } catch (e) {
+    onfail();
+  }
+    /*
+    var script=document.createElement('script');
+    script.defer=false;
+    script.type="text/javascript";
+    script.id=url;
+    script.src=url;
+    script.onload=onload;
+    script.onerror=onfail;
+    script.loadCheck=loadCheck;
+    if(/MSIE/.test(navigator.userAgent)){script.onreadystatechange=this.checkReadyState;}
+    document.getElementsByTagName('head')[0].appendChild(script);
+    */
+  },
+  checkReadyState:function(){if(this.readyState=='loaded'){if(!this.loadCheck()){this.onerror();}else{this.onload();}}}};Proj4js.Proj=Proj4js.Class({readyToUse:false,title:null,projName:null,units:null,datum:null,x0:0,y0:0,initialize:function(srsCode){this.srsCodeInput=srsCode;if(srsCode.indexOf('urn:')==0){var urn=srsCode.split(':');if((urn[1]=='ogc'||urn[1]=='x-ogc')&&(urn[2]=='def')&&(urn[3]=='crs')){srsCode=urn[4]+':'+urn[urn.length-1];}}else if(srsCode.indexOf('http://')==0){var url [...]
+this.srsCode=srsCode.toUpperCase();if(this.srsCode.indexOf("EPSG")==0){this.srsCode=this.srsCode;this.srsAuth='epsg';this.srsProjNumber=this.srsCode.substring(5);}else if(this.srsCode.indexOf("IGNF")==0){this.srsCode=this.srsCode;this.srsAuth='IGNF';this.srsProjNumber=this.srsCode.substring(5);}else if(this.srsCode.indexOf("CRS")==0){this.srsCode=this.srsCode;this.srsAuth='CRS';this.srsProjNumber=this.srsCode.substring(4);}else{this.srsAuth='';this.srsProjNumber=this.srsCode;}
+this.loadProjDefinition();},
+  loadProjDefinition:function(){
+    if(Proj4js.defs[this.srsCode]){this.defsLoaded();return;}
+    this.loadFromService();
+  /*
+    var url=Proj4js.getScriptLocation()+'defs/'+this.srsAuth.toUpperCase()+this.srsProjNumber+'.js';
+    Proj4js.loadScript(url,Proj4js.bind(this.defsLoaded,this),Proj4js.bind(this.loadFromService,this),Proj4js.bind(this.checkDefsLoaded,this));
+    */
+  },
+  loadFromService:function(){var url=Proj4js.defsLookupService+'/'+this.srsAuth+'/'+this.srsProjNumber+'/proj4js/';Proj4js.loadScript(url,Proj4js.bind(this.defsLoaded,this),Proj4js.bind(this.defsFailed,this),Proj4js.bind(this.checkDefsLoaded,this));},defsLoaded:function(){this.parseDefs();this.loadProjCode(this.projName);},checkDefsLoaded:function(){if(Proj4js.defs[this.srsCode]){return true;}else{return false;}},defsFailed:function(){Proj4js.reportError('failed to load projection defini [...]
+  loadProjCode:function(projName){
+    if(Proj4js.Proj[projName]){this.initTransforms();return;}
+    var url=Proj4js.getScriptLocation()+'projCode/'+projName+'.js';
+    Proj4js.loadScript(url,Proj4js.bind(this.loadProjCodeSuccess,this,projName),Proj4js.bind(this.loadProjCodeFailure,this,projName),Proj4js.bind(this.checkCodeLoaded,this,projName));
+  },
+  loadProjCodeSuccess:function(projName){if(Proj4js.Proj[projName].dependsOn){this.loadProjCode(Proj4js.Proj[projName].dependsOn);}else{this.initTransforms();}},loadProjCodeFailure:function(projName){Proj4js.reportError("failed to find projection file for: "+projName);},checkCodeLoaded:function(projName){if(Proj4js.Proj[projName]){return true;}else{return false;}},initTransforms:function(){Proj4js.extend(this,Proj4js.Proj[this.projName]);this.init();this.readyToUse=true;},parseDefs:funct [...]
+var paramArray=this.defData.split("+");for(var prop=0;prop<paramArray.length;prop++){var property=paramArray[prop].split("=");paramName=property[0].toLowerCase();paramVal=property[1];switch(paramName.replace(/\s/gi,"")){case"":break;case"title":this.title=paramVal;break;case"proj":this.projName=paramVal.replace(/\s/gi,"");break;case"units":this.units=paramVal.replace(/\s/gi,"");break;case"datum":this.datumCode=paramVal.replace(/\s/gi,"");break;case"nadgrids":this.nagrids=paramVal.replace [...]
+this.deriveConstants();},deriveConstants:function(){if(this.nagrids=='@null')this.datumCode='none';if(this.datumCode&&this.datumCode!='none'){var datumDef=Proj4js.Datum[this.datumCode];if(datumDef){this.datum_params=datumDef.towgs84?datumDef.towgs84.split(','):null;this.ellps=datumDef.ellipse;this.datumName=datumDef.datumName?datumDef.datumName:this.datumCode;}}
+if(!this.a){var ellipse=Proj4js.Ellipsoid[this.ellps]?Proj4js.Ellipsoid[this.ellps]:Proj4js.Ellipsoid['WGS84'];Proj4js.extend(this,ellipse);}
+if(this.rf&&!this.b)this.b=(1.0-1.0/this.rf)*this.a;if(Math.abs(this.a-this.b)<Proj4js.common.EPSLN){this.sphere=true;this.b=this.a;}
+this.a2=this.a*this.a;this.b2=this.b*this.b;this.es=(this.a2-this.b2)/this.a2;this.e=Math.sqrt(this.es);if(this.R_A){this.a*=1.-this.es*(Proj4js.common.SIXTH+this.es*(Proj4js.common.RA4+this.es*Proj4js.common.RA6));this.a2=this.a*this.a;this.b2=this.b*this.b;this.es=0.;}
+this.ep2=(this.a2-this.b2)/this.b2;if(!this.k0)this.k0=1.0;this.datum=new Proj4js.datum(this);}});Proj4js.Proj.longlat={init:function(){},forward:function(pt){return pt;},inverse:function(pt){return pt;}};Proj4js.defs={'WGS84':"+title=long/lat:WGS84 +proj=longlat +ellps=WGS84 +datum=WGS84 +units=degrees",'EPSG:4326':"+title=long/lat:WGS84 +proj=longlat +a=6378137.0 +b=6356752.31424518 +ellps=WGS84 +datum=WGS84 +units=degrees",'EPSG:4269':"+title=long/lat:NAD83 +proj=longlat +a=6378137.0  [...]
+alert("phi2z has NoConvergence");return(-9999);},qsfnz:function(eccent,sinphi){var con;if(eccent>1.0e-7){con=eccent*sinphi;return((1.0-eccent*eccent)*(sinphi/(1.0-con*con)-(.5/eccent)*Math.log((1.0-con)/(1.0+con))));}else{return(2.0*sinphi);}},asinz:function(x){if(Math.abs(x)>1.0){x=(x>1.0)?1.0:-1.0;}
+return Math.asin(x);},e0fn:function(x){return(1.0-0.25*x*(1.0+x/16.0*(3.0+1.25*x)));},e1fn:function(x){return(0.375*x*(1.0+0.25*x*(1.0+0.46875*x)));},e2fn:function(x){return(0.05859375*x*x*(1.0+0.75*x));},e3fn:function(x){return(x*x*x*(35.0/3072.0));},mlfn:function(e0,e1,e2,e3,phi){return(e0*phi-e1*Math.sin(2.0*phi)+e2*Math.sin(4.0*phi)-e3*Math.sin(6.0*phi));},srat:function(esinp,exp){return(Math.pow((1.0-esinp)/(1.0+esinp),exp));},sign:function(x){if(x<0.0)return(-1);else return(1);},ad [...]
+{var r=Math.exp(x);r=(r-1.0/r)/2.0;return r;},cosh:function(x)
+{var r=Math.exp(x);r=(r+1.0/r)/2.0;return r;},tanh:function(x)
+{var r=Math.exp(x);r=(r-1.0/r)/(r+1.0/r);return r;},asinh:function(x)
+{var s=(x>=0?1.0:-1.0);return s*(Math.log(Math.abs(x)+Math.sqrt(x*x+1.0)));},acosh:function(x)
+{return 2.0*Math.log(Math.sqrt((x+1.0)/2.0)+Math.sqrt((x-1.0)/2.0));},atanh:function(x)
+{return Math.log((x-1.0)/(x+1.0))/2.0;},gN:function(a,e,sinphi)
+{var temp=e*sinphi;return a/Math.sqrt(1.0-temp*temp);}};Proj4js.datum=Proj4js.Class({initialize:function(proj){this.datum_type=Proj4js.common.PJD_WGS84;if(proj.datumCode&&proj.datumCode=='none'){this.datum_type=Proj4js.common.PJD_NODATUM;}
+if(proj&&proj.datum_params){for(var i=0;i<proj.datum_params.length;i++){proj.datum_params[i]=parseFloat(proj.datum_params[i]);}
+if(proj.datum_params[0]!=0||proj.datum_params[1]!=0||proj.datum_params[2]!=0){this.datum_type=Proj4js.common.PJD_3PARAM;}
+if(proj.datum_params.length>3){if(proj.datum_params[3]!=0||proj.datum_params[4]!=0||proj.datum_params[5]!=0||proj.datum_params[6]!=0){this.datum_type=Proj4js.common.PJD_7PARAM;proj.datum_params[3]*=Proj4js.common.SEC_TO_RAD;proj.datum_params[4]*=Proj4js.common.SEC_TO_RAD;proj.datum_params[5]*=Proj4js.common.SEC_TO_RAD;proj.datum_params[6]=(proj.datum_params[6]/1000000.0)+1.0;}}}
+if(proj){this.a=proj.a;this.b=proj.b;this.es=proj.es;this.ep2=proj.ep2;this.datum_params=proj.datum_params;}},compare_datums:function(dest){if(this.datum_type!=dest.datum_type){return false;}else if(this.a!=dest.a||Math.abs(this.es-dest.es)>0.000000000050){return false;}else if(this.datum_type==Proj4js.common.PJD_3PARAM){return(this.datum_params[0]==dest.datum_params[0]&&this.datum_params[1]==dest.datum_params[1]&&this.datum_params[2]==dest.datum_params[2]);}else if(this.datum_type==Proj [...]
+if(Longitude>Proj4js.common.PI)Longitude-=(2*Proj4js.common.PI);Sin_Lat=Math.sin(Latitude);Cos_Lat=Math.cos(Latitude);Sin2_Lat=Sin_Lat*Sin_Lat;Rn=this.a/(Math.sqrt(1.0e0-this.es*Sin2_Lat));X=(Rn+Height)*Cos_Lat*Math.cos(Longitude);Y=(Rn+Height)*Cos_Lat*Math.sin(Longitude);Z=((Rn*(1-this.es))+Height)*Sin_Lat;p.x=X;p.y=Y;p.z=Z;return Error_Code;},geocentric_to_geodetic:function(p){var genau=1.E-12;var genau2=(genau*genau);var maxiter=30;var P;var RR;var CT;var ST;var RX;var RK;var RN;var C [...]
+CT=Z/RR;ST=P/RR;RX=1.0/Math.sqrt(1.0-this.es*(2.0-this.es)*ST*ST);CPHI0=ST*(1.0-this.es)*RX;SPHI0=CT*RX;iter=0;do
+{iter++;RN=this.a/Math.sqrt(1.0-this.es*SPHI0*SPHI0);Height=P*CPHI0+Z*SPHI0-RN*(1.0-this.es*SPHI0*SPHI0);RK=this.es*RN/(RN+Height);RX=1.0/Math.sqrt(1.0-RK*(2.0-RK)*ST*ST);CPHI=ST*(1.0-RK)*RX;SPHI=CT*RX;SDPHI=SPHI*CPHI0-CPHI*SPHI0;CPHI0=CPHI;SPHI0=SPHI;}
+while(SDPHI*SDPHI>genau2&&iter<maxiter);Latitude=Math.atan(SPHI/Math.abs(CPHI));p.x=Longitude;p.y=Latitude;p.z=Height;return p;},geocentric_to_geodetic_noniter:function(p){var X=p.x;var Y=p.y;var Z=p.z?p.z:0;var Longitude;var Latitude;var Height;var W;var W2;var T0;var T1;var S0;var S1;var Sin_B0;var Sin3_B0;var Cos_B0;var Sin_p1;var Cos_p1;var Rn;var Sum;var At_Pole;X=parseFloat(X);Y=parseFloat(Y);Z=parseFloat(Z);At_Pole=false;if(X!=0.0)
+{Longitude=Math.atan2(Y,X);}
+else
+{if(Y>0)
+{Longitude=Proj4js.common.HALF_PI;}
+else if(Y<0)
+{Longitude=-Proj4js.common.HALF_PI;}
+else
+{At_Pole=true;Longitude=0.0;if(Z>0.0)
+{Latitude=Proj4js.common.HALF_PI;}
+else if(Z<0.0)
+{Latitude=-Proj4js.common.HALF_PI;}
+else
+{Latitude=Proj4js.common.HALF_PI;Height=-this.b;return;}}}
+W2=X*X+Y*Y;W=Math.sqrt(W2);T0=Z*Proj4js.common.AD_C;S0=Math.sqrt(T0*T0+W2);Sin_B0=T0/S0;Cos_B0=W/S0;Sin3_B0=Sin_B0*Sin_B0*Sin_B0;T1=Z+this.b*this.ep2*Sin3_B0;Sum=W-this.a*this.es*Cos_B0*Cos_B0*Cos_B0;S1=Math.sqrt(T1*T1+Sum*Sum);Sin_p1=T1/S1;Cos_p1=Sum/S1;Rn=this.a/Math.sqrt(1.0-this.es*Sin_p1*Sin_p1);if(Cos_p1>=Proj4js.common.COS_67P5)
+{Height=W/Cos_p1-Rn;}
+else if(Cos_p1<=-Proj4js.common.COS_67P5)
+{Height=W/-Cos_p1-Rn;}
+else
+{Height=Z/Sin_p1+Rn*(this.es-1.0);}
+if(At_Pole==false)
+{Latitude=Math.atan(Sin_p1/Cos_p1);}
+p.x=Longitude;p.y=Latitude;p.z=Height;return p;},geocentric_to_wgs84:function(p){if(this.datum_type==Proj4js.common.PJD_3PARAM)
+{p.x+=this.datum_params[0];p.y+=this.datum_params[1];p.z+=this.datum_params[2];}
+else if(this.datum_type==Proj4js.common.PJD_7PARAM)
+{var Dx_BF=this.datum_params[0];var Dy_BF=this.datum_params[1];var Dz_BF=this.datum_params[2];var Rx_BF=this.datum_params[3];var Ry_BF=this.datum_params[4];var Rz_BF=this.datum_params[5];var M_BF=this.datum_params[6];var x_out=M_BF*(p.x-Rz_BF*p.y+Ry_BF*p.z)+Dx_BF;var y_out=M_BF*(Rz_BF*p.x+p.y-Rx_BF*p.z)+Dy_BF;var z_out=M_BF*(-Ry_BF*p.x+Rx_BF*p.y+p.z)+Dz_BF;p.x=x_out;p.y=y_out;p.z=z_out;}},geocentric_from_wgs84:function(p){if(this.datum_type==Proj4js.common.PJD_3PARAM)
+{p.x-=this.datum_params[0];p.y-=this.datum_params[1];p.z-=this.datum_params[2];}
+else if(this.datum_type==Proj4js.common.PJD_7PARAM)
+{var Dx_BF=this.datum_params[0];var Dy_BF=this.datum_params[1];var Dz_BF=this.datum_params[2];var Rx_BF=this.datum_params[3];var Ry_BF=this.datum_params[4];var Rz_BF=this.datum_params[5];var M_BF=this.datum_params[6];var x_tmp=(p.x-Dx_BF)/M_BF;var y_tmp=(p.y-Dy_BF)/M_BF;var z_tmp=(p.z-Dz_BF)/M_BF;p.x=x_tmp+Rz_BF*y_tmp-Ry_BF*z_tmp;p.y=-Rz_BF*x_tmp+y_tmp+Rx_BF*z_tmp;p.z=Ry_BF*x_tmp-Rx_BF*y_tmp+z_tmp;}}});Proj4js.Point=Proj4js.Class({initialize:function(x,y,z){if(typeof x=='object'){this.x= [...]
+this.temp=this.b/this.a;this.es=1.0-Math.pow(this.temp,2);this.e3=Math.sqrt(this.es);this.sin_po=Math.sin(this.lat1);this.cos_po=Math.cos(this.lat1);this.t1=this.sin_po;this.con=this.sin_po;this.ms1=Proj4js.common.msfnz(this.e3,this.sin_po,this.cos_po);this.qs1=Proj4js.common.qsfnz(this.e3,this.sin_po,this.cos_po);this.sin_po=Math.sin(this.lat2);this.cos_po=Math.cos(this.lat2);this.t2=this.sin_po;this.ms2=Proj4js.common.msfnz(this.e3,this.sin_po,this.cos_po);this.qs2=Proj4js.common.qsfnz [...]
+this.c=this.ms1*this.ms1+this.ns0*this.qs1;this.rh=this.a*Math.sqrt(this.c-this.ns0*this.qs0)/this.ns0;},forward:function(p){var lon=p.x;var lat=p.y;this.sin_phi=Math.sin(lat);this.cos_phi=Math.cos(lat);var qs=Proj4js.common.qsfnz(this.e3,this.sin_phi,this.cos_phi);var rh1=this.a*Math.sqrt(this.c-this.ns0*qs)/this.ns0;var theta=this.ns0*Proj4js.common.adjust_lon(lon-this.long0);var x=rh1*Math.sin(theta)+this.x0;var y=this.rh-rh1*Math.cos(theta)+this.y0;p.x=x;p.y=y;return p;},inverse:func [...]
+theta=0.0;if(rh1!=0.0){theta=Math.atan2(con*p.x,con*p.y);}
+con=rh1*this.ns0/this.a;qs=(this.c-con*con)/this.ns0;if(this.e3>=1e-10){con=1-.5*(1.0-this.es)*Math.log((1.0-this.e3)/(1.0+this.e3))/this.e3;if(Math.abs(Math.abs(con)-Math.abs(qs))>.0000000001){lat=this.phi1z(this.e3,qs);}else{if(qs>=0){lat=.5*PI;}else{lat=-.5*PI;}}}else{lat=this.phi1z(e3,qs);}
+lon=Proj4js.common.adjust_lon(theta/this.ns0+this.long0);p.x=lon;p.y=lat;return p;},phi1z:function(eccent,qs){var con,com,dphi;var phi=Proj4js.common.asinz(.5*qs);if(eccent<Proj4js.common.EPSLN)return phi;var eccnts=eccent*eccent;for(var i=1;i<=25;i++){sinphi=Math.sin(phi);cosphi=Math.cos(phi);con=eccent*sinphi;com=1.0-con*con;dphi=.5*com*com/cosphi*(qs/(1.0-eccnts)-sinphi/com+.5/eccent*Math.log((1.0-con)/(1.0+con)));phi=phi+dphi;if(Math.abs(dphi)<=1e-7)return phi;}
+Proj4js.reportError("aea:phi1z:Convergence error");return null;}};Proj4js.Proj.sterea={dependsOn:'gauss',init:function(){Proj4js.Proj['gauss'].init.apply(this);if(!this.rc){Proj4js.reportError("sterea:init:E_ERROR_0");return;}
+this.sinc0=Math.sin(this.phic0);this.cosc0=Math.cos(this.phic0);this.R2=2.0*this.rc;if(!this.title)this.title="Oblique Stereographic Alternative";},forward:function(p){p.x=Proj4js.common.adjust_lon(p.x-this.long0);Proj4js.Proj['gauss'].forward.apply(this,[p]);sinc=Math.sin(p.y);cosc=Math.cos(p.y);cosl=Math.cos(p.x);k=this.k0*this.R2/(1.0+this.sinc0*sinc+this.cosc0*cosc*cosl);p.x=k*cosc*Math.sin(p.x);p.y=k*(this.cosc0*sinc-this.sinc0*cosc*cosl);p.x=this.a*p.x+this.x0;p.y=this.a*p.y+this.y [...]
+p.x=lon;p.y=lat;Proj4js.Proj['gauss'].inverse.apply(this,[p]);p.x=Proj4js.common.adjust_lon(p.x+this.long0);return p;}};function phi4z(eccent,e0,e1,e2,e3,a,b,c,phi){var sinphi,sin2ph,tanph,ml,mlp,con1,con2,con3,dphi,i;phi=a;for(i=1;i<=15;i++){sinphi=Math.sin(phi);tanphi=Math.tan(phi);c=tanphi*Math.sqrt(1.0-eccent*sinphi*sinphi);sin2ph=Math.sin(2.0*phi);ml=e0*phi-e1*sin2ph+e2*Math.sin(4.0*phi)-e3*Math.sin(6.0*phi);mlp=e0-2.0*e1*Math.cos(2.0*phi)+4.0*e2*Math.cos(4.0*phi)-6.0*e3*Math.cos(6. [...]
+Proj4js.reportError("phi4z: No convergence");return null;}
+function e4fn(x){var con,com;con=1.0+x;com=1.0-x;return(Math.sqrt((Math.pow(con,con))*(Math.pow(com,com))));}
+Proj4js.Proj.poly={init:function(){var temp;if(this.lat0=0)this.lat0=90;this.temp=this.b/this.a;this.es=1.0-Math.pow(this.temp,2);this.e=Math.sqrt(this.es);this.e0=Proj4js.common.e0fn(this.es);this.e1=Proj4js.common.e1fn(this.es);this.e2=Proj4js.common.e2fn(this.es);this.e3=Proj4js.common.e3fn(this.es);this.ml0=Proj4js.common.mlfn(this.e0,this.e1,this.e2,this.e3,this.lat0);},forward:function(p){var sinphi,cosphi;var al;var c;var con,ml;var ms;var x,y;var lon=p.x;var lat=p.y;con=Proj4js.c [...]
+p.x=x;p.y=y;return p;},inverse:function(p){var sin_phi,cos_phi;var al;var b;var c;var con,ml;var iflg;var lon,lat;p.x-=this.x0;p.y-=this.y0;al=this.ml0+p.y/this.a;iflg=0;if(Math.abs(al)<=.0000001){lon=p.x/this.a+this.long0;lat=0.0;}else{b=al*al+(p.x/this.a)*(p.x/this.a);iflg=phi4z(this.es,this.e0,this.e1,this.e2,this.e3,this.al,b,c,lat);if(iflg!=1)return(iflg);lon=Proj4js.common.adjust_lon((Proj4js.common.asinz(p.x*c/this.a)/Math.sin(lat))+this.long0);}
+p.x=lon;p.y=lat;return p;}};Proj4js.Proj.equi={init:function(){if(!this.x0)this.x0=0;if(!this.y0)this.y0=0;if(!this.lat0)this.lat0=0;if(!this.long0)this.long0=0;},forward:function(p){var lon=p.x;var lat=p.y;var dlon=Proj4js.common.adjust_lon(lon-this.long0);var x=this.x0+this.a*dlon*Math.cos(this.lat0);var y=this.y0+this.a*lat;this.t1=x;this.t2=Math.cos(this.lat0);p.x=x;p.y=y;return p;},inverse:function(p){p.x-=this.x0;p.y-=this.y0;var lat=p.y/this.a;if(Math.abs(lat)>Proj4js.common.HALF_ [...]
+var lon=Proj4js.common.adjust_lon(this.long0+p.x/(this.a*Math.cos(this.lat0)));p.x=lon;p.y=lat;}};Proj4js.Proj.merc={init:function(){if(this.lat_ts){if(this.sphere){this.k0=Math.cos(this.lat_ts);}else{this.k0=Proj4js.common.msfnz(this.es,Math.sin(this.lat_ts),Math.cos(this.lat_ts));}}},forward:function(p){var lon=p.x;var lat=p.y;if(lat*Proj4js.common.R2D>90.0&&lat*Proj4js.common.R2D<-90.0&&lon*Proj4js.common.R2D>180.0&&lon*Proj4js.common.R2D<-180.0){Proj4js.reportError("merc:forward: llI [...]
+var x,y;if(Math.abs(Math.abs(lat)-Proj4js.common.HALF_PI)<=Proj4js.common.EPSLN){Proj4js.reportError("merc:forward: ll2mAtPoles");return null;}else{if(this.sphere){x=this.x0+this.a*this.k0*Proj4js.common.adjust_lon(lon-this.long0);y=this.y0+this.a*this.k0*Math.log(Math.tan(Proj4js.common.FORTPI+0.5*lat));}else{var sinphi=Math.sin(lat);var ts=Proj4js.common.tsfnz(this.e,lat,sinphi);x=this.x0+this.a*this.k0*Proj4js.common.adjust_lon(lon-this.long0);y=this.y0-this.a*this.k0*Math.log(ts);}
+p.x=x;p.y=y;return p;}},inverse:function(p){var x=p.x-this.x0;var y=p.y-this.y0;var lon,lat;if(this.sphere){lat=Proj4js.common.HALF_PI-2.0*Math.atan(Math.exp(-y/this.a*this.k0));}else{var ts=Math.exp(-y/(this.a*this.k0));lat=Proj4js.common.phi2z(this.e,ts);if(lat==-9999){Proj4js.reportError("merc:inverse: lat = -9999");return null;}}
+lon=Proj4js.common.adjust_lon(this.long0+x/(this.a*this.k0));p.x=lon;p.y=lat;return p;}};Proj4js.Proj.utm={dependsOn:'tmerc',init:function(){if(!this.zone){Proj4js.reportError("utm:init: zone must be specified for UTM");return;}
+this.lat0=0.0;this.long0=((6*Math.abs(this.zone))-183)*Proj4js.common.D2R;this.x0=500000.0;this.y0=this.utmSouth?10000000.0:0.0;this.k0=0.9996;Proj4js.Proj['tmerc'].init.apply(this);this.forward=Proj4js.Proj['tmerc'].forward;this.inverse=Proj4js.Proj['tmerc'].inverse;}};Proj4js.Proj.eqdc={init:function(){if(!this.mode)this.mode=0;this.temp=this.b/this.a;this.es=1.0-Math.pow(this.temp,2);this.e=Math.sqrt(this.es);this.e0=Proj4js.common.e0fn(this.es);this.e1=Proj4js.common.e1fn(this.es);th [...]
+this.sinphi=Math.sin(this.lat2);this.cosphi=Math.cos(this.lat2);this.ms2=Proj4js.common.msfnz(this.e,this.sinphi,this.cosphi);this.ml2=Proj4js.common.mlfn(this.e0,this.e1,this.e2,this.e3,this.lat2);if(Math.abs(this.lat1-this.lat2)>=Proj4js.common.EPSLN){this.ns=(this.ms1-this.ms2)/(this.ml2-this.ml1);}else{this.ns=this.sinphi;}}else{this.ns=this.sinphi;}
+this.g=this.ml1+this.ms1/this.ns;this.ml0=Proj4js.common.mlfn(this.e0,this.e1,this.e2,this.e3,this.lat0);this.rh=this.a*(this.g-this.ml0);},forward:function(p){var lon=p.x;var lat=p.y;var ml=Proj4js.common.mlfn(this.e0,this.e1,this.e2,this.e3,lat);var rh1=this.a*(this.g-ml);var theta=this.ns*Proj4js.common.adjust_lon(lon-this.long0);var x=this.x0+rh1*Math.sin(theta);var y=this.y0+this.rh-rh1*Math.cos(theta);p.x=x;p.y=y;return p;},inverse:function(p){p.x-=this.x0;p.y=this.rh-p.y+this.y0;v [...]
+var theta=0.0;if(rh1!=0.0)theta=Math.atan2(con*p.x,con*p.y);var ml=this.g-rh1/this.a;var lat=this.phi3z(this.ml,this.e0,this.e1,this.e2,this.e3);var lon=Proj4js.common.adjust_lon(this.long0+theta/this.ns);p.x=lon;p.y=lat;return p;},phi3z:function(ml,e0,e1,e2,e3){var phi;var dphi;phi=ml;for(var i=0;i<15;i++){dphi=(ml+e1*Math.sin(2.0*phi)-e2*Math.sin(4.0*phi)+e3*Math.sin(6.0*phi))/e0-phi;phi+=dphi;if(Math.abs(dphi)<=.0000000001){return phi;}}
+Proj4js.reportError("PHI3Z-CONV:Latitude failed to converge after 15 iterations");return null;}};Proj4js.Proj.tmerc={init:function(){this.e0=Proj4js.common.e0fn(this.es);this.e1=Proj4js.common.e1fn(this.es);this.e2=Proj4js.common.e2fn(this.es);this.e3=Proj4js.common.e3fn(this.es);this.ml0=this.a*Proj4js.common.mlfn(this.e0,this.e1,this.e2,this.e3,this.lat0);},forward:function(p){var lon=p.x;var lat=p.y;var delta_lon=Proj4js.common.adjust_lon(lon-this.long0);var con;var x,y;var sin_phi=Ma [...]
+p.x=x;p.y=y;return p;},inverse:function(p){var con,phi;var delta_phi;var i;var max_iter=6;var lat,lon;if(this.sphere){var f=Math.exp(p.x/(this.a*this.k0));var g=.5*(f-1/f);var temp=this.lat0+p.y/(this.a*this.k0);var h=Math.cos(temp);con=Math.sqrt((1.0-h*h)/(1.0+g*g));lat=Proj4js.common.asinz(con);if(temp<0)
+lat=-lat;if((g==0)&&(h==0)){lon=this.long0;}else{lon=Proj4js.common.adjust_lon(Math.atan2(g,h)+this.long0);}}else{var x=p.x-this.x0;var y=p.y-this.y0;con=(this.ml0+y/this.k0)/this.a;phi=con;for(i=0;true;i++){delta_phi=((con+this.e1*Math.sin(2.0*phi)-this.e2*Math.sin(4.0*phi)+this.e3*Math.sin(6.0*phi))/this.e0)-phi;phi+=delta_phi;if(Math.abs(delta_phi)<=Proj4js.common.EPSLN)break;if(i>=max_iter){Proj4js.reportError("tmerc:inverse: Latitude failed to converge");return(95);}}
+if(Math.abs(phi)<Proj4js.common.HALF_PI){var sin_phi=Math.sin(phi);var cos_phi=Math.cos(phi);var tan_phi=Math.tan(phi);var c=this.ep2*Math.pow(cos_phi,2);var cs=Math.pow(c,2);var t=Math.pow(tan_phi,2);var ts=Math.pow(t,2);con=1.0-this.es*Math.pow(sin_phi,2);var n=this.a/Math.sqrt(con);var r=n*(1.0-this.es)/con;var d=x/(n*this.k0);var ds=Math.pow(d,2);lat=phi-(n*tan_phi*ds/r)*(0.5-ds/24.0*(5.0+3.0*t+10.0*c-4.0*cs-9.0*this.ep2-ds/30.0*(61.0+90.0*t+298.0*c+45.0*ts-252.0*this.ep2-3.0*cs)));l [...]
+p.x=lon;p.y=lat;return p;}};Proj4js.defs["GOOGLE"]="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs";Proj4js.defs["EPSG:900913"]=Proj4js.defs["GOOGLE"];Proj4js.Proj.gstmerc={init:function(){var temp=this.b/this.a;this.e=Math.sqrt(1.0-temp*temp);this.lc=this.long0;this.rs=Math.sqrt(1.0+this.e*this.e*Math.pow(Math.cos(this.lat0),4.0)/(1.0-this.e*this.e));var sinz=Math.sin(this.lat0);var pc=Math.asin(sinz/this.rs);var sinzpc=M [...]
+p.x=x;p.y=y;return p;},inverse:function(p){var rh;var z;var sinz,cosz;var temp;var con;var lon,lat;p.x-=this.x0;p.y-=this.y0;rh=Math.sqrt(p.x*p.x+p.y*p.y);if(rh>this.a+.0000001){Proj4js.reportError("orthoInvDataError");}
+z=Proj4js.common.asinz(rh/this.a);sinz=Math.sin(z);cosz=Math.cos(z);lon=this.long0;if(Math.abs(rh)<=Proj4js.common.EPSLN){lat=this.lat0;}
+lat=Proj4js.common.asinz(cosz*this.sin_p14+(p.y*sinz*this.cos_p14)/rh);con=Math.abs(lat0)-Proj4js.common.HALF_PI;if(Math.abs(con)<=Proj4js.common.EPSLN){if(this.lat0>=0){lon=Proj4js.common.adjust_lon(this.long0+Math.atan2(p.x,-p.y));}else{lon=Proj4js.common.adjust_lon(this.long0-Math.atan2(-p.x,p.y));}}
+con=cosz-this.sin_p14*Math.sin(lat);if((Math.abs(con)>=Proj4js.common.EPSLN)||(Math.abs(x)>=Proj4js.common.EPSLN)){lon=Proj4js.common.adjust_lon(this.long0+Math.atan2((p.x*sinz*this.cos_p14),(con*rh)));}
+p.x=lon;p.y=lat;return p;}};Proj4js.Proj.somerc={init:function(){var phy0=this.lat0;this.lambda0=this.long0;var sinPhy0=Math.sin(phy0);var semiMajorAxis=this.a;var invF=this.rf;var flattening=1/invF;var e2=2*flattening-Math.pow(flattening,2);var e=this.e=Math.sqrt(e2);this.R=semiMajorAxis*Math.sqrt(1-e2)/(1-e2*Math.pow(sinPhy0,2.0));this.alpha=Math.sqrt(1+e2/(1-e2)*Math.pow(Math.cos(phy0),4.0));this.b0=Math.asin(sinPhy0/this.alpha);this.K=Math.log(Math.tan(Math.PI/4.0+this.b0/2.0))
+-this.alpha*Math.log(Math.tan(Math.PI/4.0+phy0/2.0))
++this.alpha*e/2*Math.log((1+e*sinPhy0)/(1-e*sinPhy0));},forward:function(p){var Sa1=Math.log(Math.tan(Math.PI/4.0-p.y/2.0));var Sa2=this.e/2.0*Math.log((1+this.e*Math.sin(p.y))/(1-this.e*Math.sin(p.y)));var S=-this.alpha*(Sa1+Sa2)+this.K;var b=2.0*(Math.atan(Math.exp(S))-Math.PI/4.0);var I=this.alpha*(p.x-this.lambda0);var rotI=Math.atan(Math.sin(I)/(Math.sin(this.b0)*Math.tan(b)+
+Math.cos(this.b0)*Math.cos(I)));var rotB=Math.asin(Math.cos(this.b0)*Math.sin(b)-
+Math.sin(this.b0)*Math.cos(b)*Math.cos(I));p.y=this.R/2.0*Math.log((1+Math.sin(rotB))/(1-Math.sin(rotB)))
++this.y0;p.x=this.R*rotI+this.x0;return p;},inverse:function(p){var Y=p.x-this.x0;var X=p.y-this.y0;var rotI=Y/this.R;var rotB=2*(Math.atan(Math.exp(X/this.R))-Math.PI/4.0);var b=Math.asin(Math.cos(this.b0)*Math.sin(rotB)
++Math.sin(this.b0)*Math.cos(rotB)*Math.cos(rotI));var I=Math.atan(Math.sin(rotI)/(Math.cos(this.b0)*Math.cos(rotI)-Math.sin(this.b0)*Math.tan(rotB)));var lambda=this.lambda0+I/this.alpha;var S=0.0;var phy=b;var prevPhy=-1000.0;var iteration=0;while(Math.abs(phy-prevPhy)>0.0000001)
+{if(++iteration>20)
+{Proj4js.reportError("omercFwdInfinity");return;}
+S=1.0/this.alpha*(Math.log(Math.tan(Math.PI/4.0+b/2.0))-this.K)
++this.e*Math.log(Math.tan(Math.PI/4.0
++Math.asin(this.e*Math.sin(phy))/2.0));prevPhy=phy;phy=2.0*Math.atan(Math.exp(S))-Math.PI/2.0;}
+p.x=lambda;p.y=phy;return p;}};Proj4js.Proj.stere={ssfn_:function(phit,sinphi,eccen){sinphi*=eccen;return(Math.tan(.5*(Proj4js.common.HALF_PI+phit))*Math.pow((1.-sinphi)/(1.+sinphi),.5*eccen));},TOL:1.e-8,NITER:8,CONV:1.e-10,S_POLE:0,N_POLE:1,OBLIQ:2,EQUIT:3,init:function(){this.phits=this.lat_ts?this.lat_ts:Proj4js.common.HALF_PI;var t=Math.abs(this.lat0);if((Math.abs(t)-Proj4js.common.HALF_PI)<Proj4js.common.EPSLN){this.mode=this.lat0<0.?this.S_POLE:this.N_POLE;}else{this.mode=t>Proj4j [...]
+this.phits=Math.abs(this.phits);if(this.es){var X;switch(this.mode){case this.N_POLE:case this.S_POLE:if(Math.abs(this.phits-Proj4js.common.HALF_PI)<Proj4js.common.EPSLN){this.akm1=2.*this.k0/Math.sqrt(Math.pow(1+this.e,1+this.e)*Math.pow(1-this.e,1-this.e));}else{t=Math.sin(this.phits);this.akm1=Math.cos(this.phits)/Proj4js.common.tsfnz(this.e,this.phits,t);t*=this.e;this.akm1/=Math.sqrt(1.-t*t);}
+break;case this.EQUIT:this.akm1=2.*this.k0;break;case this.OBLIQ:t=Math.sin(this.lat0);X=2.*Math.atan(this.ssfn_(this.lat0,t,this.e))-Proj4js.common.HALF_PI;t*=this.e;this.akm1=2.*this.k0*Math.cos(this.lat0)/Math.sqrt(1.-t*t);this.sinX1=Math.sin(X);this.cosX1=Math.cos(X);break;}}else{switch(this.mode){case this.OBLIQ:this.sinph0=Math.sin(this.lat0);this.cosph0=Math.cos(this.lat0);case this.EQUIT:this.akm1=2.*this.k0;break;case this.S_POLE:case this.N_POLE:this.akm1=Math.abs(this.phits-Pr [...]
+y=this.akm1/y;x=y*cosphi*sinlam;y*=sinphi;break;case this.OBLIQ:y=1.+this.sinph0*sinphi+this.cosph0*cosphi*coslam;if(y<=Proj4js.common.EPSLN){F_ERROR;}
+y=this.akm1/y;x=y*cosphi*sinlam;y*=this.cosph0*sinphi-this.sinph0*cosphi*coslam;break;case this.N_POLE:coslam=-coslam;lat=-lat;case this.S_POLE:if(Math.abs(lat-Proj4js.common.HALF_PI)<this.TOL){F_ERROR;}
+y=this.akm1*Math.tan(Proj4js.common.FORTPI+.5*lat);x=sinlam*y;y*=coslam;break;}}else{coslam=Math.cos(lon);sinlam=Math.sin(lon);sinphi=Math.sin(lat);if(this.mode==this.OBLIQ||this.mode==this.EQUIT){X=2.*Math.atan(this.ssfn_(lat,sinphi,this.e));sinX=Math.sin(X-Proj4js.common.HALF_PI);cosX=Math.cos(X);}
+switch(this.mode){case this.OBLIQ:A=this.akm1/(this.cosX1*(1.+this.sinX1*sinX+this.cosX1*cosX*coslam));y=A*(this.cosX1*sinX-this.sinX1*cosX*coslam);x=A*cosX;break;case this.EQUIT:A=2.*this.akm1/(1.+cosX*coslam);y=A*sinX;x=A*cosX;break;case this.S_POLE:lat=-lat;coslam=-coslam;sinphi=-sinphi;case this.N_POLE:x=this.akm1*Proj4js.common.tsfnz(this.e,lat,sinphi);y=-x*coslam;break;}
+x=x*sinlam;}
+p.x=x*this.a+this.x0;p.y=y*this.a+this.y0;return p;},inverse:function(p){var x=(p.x-this.x0)/this.a;var y=(p.y-this.y0)/this.a;var lon,lat;var cosphi,sinphi,tp=0.0,phi_l=0.0,rho,halfe=0.0,pi2=0.0;var i;if(this.sphere){var c,rh,sinc,cosc;rh=Math.sqrt(x*x+y*y);c=2.*Math.atan(rh/this.akm1);sinc=Math.sin(c);cosc=Math.cos(c);lon=0.;switch(this.mode){case this.EQUIT:if(Math.abs(rh)<=Proj4js.common.EPSLN){lat=0.;}else{lat=Math.asin(y*sinc/rh);}
+if(cosc!=0.||x!=0.)lon=Math.atan2(x*sinc,cosc*rh);break;case this.OBLIQ:if(Math.abs(rh)<=Proj4js.common.EPSLN){lat=this.phi0;}else{lat=Math.asin(cosc*sinph0+y*sinc*cosph0/rh);}
+c=cosc-sinph0*Math.sin(lat);if(c!=0.||x!=0.){lon=Math.atan2(x*sinc*cosph0,c*rh);}
+break;case this.N_POLE:y=-y;case this.S_POLE:if(Math.abs(rh)<=Proj4js.common.EPSLN){lat=this.phi0;}else{lat=Math.asin(this.mode==this.S_POLE?-cosc:cosc);}
+lon=(x==0.&&y==0.)?0.:Math.atan2(x,y);break;}}else{rho=Math.sqrt(x*x+y*y);switch(this.mode){case this.OBLIQ:case this.EQUIT:tp=2.*Math.atan2(rho*this.cosX1,this.akm1);cosphi=Math.cos(tp);sinphi=Math.sin(tp);if(rho==0.0){phi_l=Math.asin(cosphi*this.sinX1);}else{phi_l=Math.asin(cosphi*this.sinX1+(y*sinphi*this.cosX1/rho));}
+tp=Math.tan(.5*(Proj4js.common.HALF_PI+phi_l));x*=sinphi;y=rho*this.cosX1*cosphi-y*this.sinX1*sinphi;pi2=Proj4js.common.HALF_PI;halfe=.5*this.e;break;case this.N_POLE:y=-y;case this.S_POLE:tp=-rho/this.akm1;phi_l=Proj4js.common.HALF_PI-2.*Math.atan(tp);pi2=-Proj4js.common.HALF_PI;halfe=-.5*this.e;break;}
+for(i=this.NITER;i--;phi_l=lat){sinphi=this.e*Math.sin(phi_l);lat=2.*Math.atan(tp*Math.pow((1.+sinphi)/(1.-sinphi),halfe))-pi2;if(Math.abs(phi_l-lat)<this.CONV){if(this.mode==this.S_POLE)lat=-lat;lon=(x==0.&&y==0.)?0.:Math.atan2(x,y);p.x=Proj4js.common.adjust_lon(lon+this.long0);p.y=lat;return p;}}}}};Proj4js.Proj.nzmg={iterations:1,init:function(){this.A=new Array();this.A[1]=+0.6399175073;this.A[2]=-0.1358797613;this.A[3]=+0.063294409;this.A[4]=-0.02526853;this.A[5]=+0.0117879;this.A[6 [...]
+var th_re=d_psi;var th_im=d_lambda;var th_n_re=1;var th_n_im=0;var th_n_re1;var th_n_im1;var z_re=0;var z_im=0;for(n=1;n<=6;n++){th_n_re1=th_n_re*th_re-th_n_im*th_im;th_n_im1=th_n_im*th_re+th_n_re*th_im;th_n_re=th_n_re1;th_n_im=th_n_im1;z_re=z_re+this.B_re[n]*th_n_re-this.B_im[n]*th_n_im;z_im=z_im+this.B_im[n]*th_n_re+this.B_re[n]*th_n_im;}
+x=(z_im*this.a)+this.x0;y=(z_re*this.a)+this.y0;p.x=x;p.y=y;return p;},inverse:function(p){var x=p.x;var y=p.y;var delta_x=x-this.x0;var delta_y=y-this.y0;var z_re=delta_y/this.a;var z_im=delta_x/this.a;var z_n_re=1;var z_n_im=0;var z_n_re1;var z_n_im1;var th_re=0;var th_im=0;for(n=1;n<=6;n++){z_n_re1=z_n_re*z_re-z_n_im*z_im;z_n_im1=z_n_im*z_re+z_n_re*z_im;z_n_re=z_n_re1;z_n_im=z_n_im1;th_re=th_re+this.C_re[n]*z_n_re-this.C_im[n]*z_n_im;th_im=th_im+this.C_im[n]*z_n_re+this.C_re[n]*z_n_im;}
+for(i=0;i<this.iterations;i++){var th_n_re=th_re;var th_n_im=th_im;var th_n_re1;var th_n_im1;var num_re=z_re;var num_im=z_im;for(n=2;n<=6;n++){th_n_re1=th_n_re*th_re-th_n_im*th_im;th_n_im1=th_n_im*th_re+th_n_re*th_im;th_n_re=th_n_re1;th_n_im=th_n_im1;num_re=num_re+(n-1)*(this.B_re[n]*th_n_re-this.B_im[n]*th_n_im);num_im=num_im+(n-1)*(this.B_im[n]*th_n_re+this.B_re[n]*th_n_im);}
+th_n_re=1;th_n_im=0;var den_re=this.B_re[1];var den_im=this.B_im[1];for(n=2;n<=6;n++){th_n_re1=th_n_re*th_re-th_n_im*th_im;th_n_im1=th_n_im*th_re+th_n_re*th_im;th_n_re=th_n_re1;th_n_im=th_n_im1;den_re=den_re+n*(this.B_re[n]*th_n_re-this.B_im[n]*th_n_im);den_im=den_im+n*(this.B_im[n]*th_n_re+this.B_re[n]*th_n_im);}
+var den2=den_re*den_re+den_im*den_im;th_re=(num_re*den_re+num_im*den_im)/den2;th_im=(num_im*den_re-num_re*den_im)/den2;}
+var d_psi=th_re;var d_lambda=th_im;var d_psi_n=1;var d_phi=0;for(n=1;n<=9;n++){d_psi_n=d_psi_n*d_psi;d_phi=d_phi+this.D[n]*d_psi_n;}
+var lat=this.lat0+(d_phi*Proj4js.common.SEC_TO_RAD*1E5);var lon=this.long0+d_lambda;p.x=lon;p.y=lat;return p;}};Proj4js.Proj.mill={init:function(){},forward:function(p){var lon=p.x;var lat=p.y;var dlon=Proj4js.common.adjust_lon(lon-this.long0);var x=this.x0+this.a*dlon;var y=this.y0+this.a*Math.log(Math.tan((Proj4js.common.PI/4.0)+(lat/2.5)))*1.25;p.x=x;p.y=y;return p;},inverse:function(p){p.x-=this.x0;p.y-=this.y0;var lon=Proj4js.common.adjust_lon(this.long0+p.x/this.a);var lat=2.5*(Mat [...]
+p.x=x;p.y=y;return p;},inverse:function(p){var rh;var z;var sinc,cosc;var c;var lon,lat;p.x=(p.x-this.x0)/this.a;p.y=(p.y-this.y0)/this.a;p.x/=this.k0;p.y/=this.k0;if((rh=Math.sqrt(p.x*p.x+p.y*p.y))){c=Math.atan2(rh,this.rc);sinc=Math.sin(c);cosc=Math.cos(c);lat=Proj4js.common.asinz(cosc*this.sin_p14+(p.y*sinc*this.cos_p14)/rh);lon=Math.atan2(p.x*sinc,rh*this.cos_p14*cosc-p.y*this.sin_p14*sinc);lon=Proj4js.common.adjust_lon(this.long0+lon);}else{lat=this.phic0;lon=0.0;}
+p.x=lon;p.y=lat;return p;}};Proj4js.Proj.sinu={init:function(){this.R=6370997.0;},forward:function(p){var x,y,delta_lon;var lon=p.x;var lat=p.y;delta_lon=Proj4js.common.adjust_lon(lon-this.long0);x=this.R*delta_lon*Math.cos(lat)+this.x0;y=this.R*lat+this.y0;p.x=x;p.y=y;return p;},inverse:function(p){var lat,temp,lon;p.x-=this.x0;p.y-=this.y0;lat=p.y/this.R;if(Math.abs(lat)>Proj4js.common.HALF_PI){Proj4js.reportError("sinu:Inv:DataError");}
+temp=Math.abs(lat)-Proj4js.common.HALF_PI;if(Math.abs(temp)>Proj4js.common.EPSLN){temp=this.long0+p.x/(this.R*Math.cos(lat));lon=Proj4js.common.adjust_lon(temp);}else{lon=this.long0;}
+p.x=lon;p.y=lat;return p;}};Proj4js.Proj.vandg={init:function(){this.R=6370997.0;},forward:function(p){var lon=p.x;var lat=p.y;var dlon=Proj4js.common.adjust_lon(lon-this.long0);var x,y;if(Math.abs(lat)<=Proj4js.common.EPSLN){x=this.x0+this.R*dlon;y=this.y0;}
+var theta=Proj4js.common.asinz(2.0*Math.abs(lat/Proj4js.common.PI));if((Math.abs(dlon)<=Proj4js.common.EPSLN)||(Math.abs(Math.abs(lat)-Proj4js.common.HALF_PI)<=Proj4js.common.EPSLN)){x=this.x0;if(lat>=0){y=this.y0+Proj4js.common.PI*this.R*Math.tan(.5*theta);}else{y=this.y0+Proj4js.common.PI*this.R*-Math.tan(.5*theta);}}
+var al=.5*Math.abs((Proj4js.common.PI/dlon)-(dlon/Proj4js.common.PI));var asq=al*al;var sinth=Math.sin(theta);var costh=Math.cos(theta);var g=costh/(sinth+costh-1.0);var gsq=g*g;var m=g*(2.0/sinth-1.0);var msq=m*m;var con=Proj4js.common.PI*this.R*(al*(g-msq)+Math.sqrt(asq*(g-msq)*(g-msq)-(msq+asq)*(gsq-msq)))/(msq+asq);if(dlon<0){con=-con;}
+x=this.x0+con;con=Math.abs(con/(Proj4js.common.PI*this.R));if(lat>=0){y=this.y0+Proj4js.common.PI*this.R*Math.sqrt(1.0-con*con-2.0*al*con);}else{y=this.y0-Proj4js.common.PI*this.R*Math.sqrt(1.0-con*con-2.0*al*con);}
+p.x=x;p.y=y;return p;},inverse:function(p){var dlon;var xx,yy,xys,c1,c2,c3;var al,asq;var a1;var m1;var con;var th1;var d;p.x-=this.x0;p.y-=this.y0;con=Proj4js.common.PI*this.R;xx=p.x/con;yy=p.y/con;xys=xx*xx+yy*yy;c1=-Math.abs(yy)*(1.0+xys);c2=c1-2.0*yy*yy+xx*xx;c3=-2.0*c1+1.0+2.0*yy*yy+xys*xys;d=yy*yy/c3+(2.0*c2*c2*c2/c3/c3/c3-9.0*c1*c2/c3/c3)/27.0;a1=(c1-c2*c2/3.0/c3)/c3;m1=2.0*Math.sqrt(-a1/3.0);con=((3.0*d)/a1)/m1;if(Math.abs(con)>1.0){if(con>=0.0){con=1.0;}else{con=-1.0;}}
+th1=Math.acos(con)/3.0;if(p.y>=0){lat=(-m1*Math.cos(th1+Proj4js.common.PI/3.0)-c2/3.0/c3)*Proj4js.common.PI;}else{lat=-(-m1*Math.cos(th1+PI/3.0)-c2/3.0/c3)*Proj4js.common.PI;}
+if(Math.abs(xx)<Proj4js.common.EPSLN){lon=this.long0;}
+lon=Proj4js.common.adjust_lon(this.long0+Proj4js.common.PI*(xys-1.0+Math.sqrt(1.0+2.0*(xx*xx-yy*yy)+xys*xys))/2.0/xx);p.x=lon;p.y=lat;return p;}};Proj4js.Proj.cea={init:function(){},forward:function(p){var lon=p.x;var lat=p.y;dlon=Proj4js.common.adjust_lon(lon-this.long0);var x=this.x0+this.a*dlon*Math.cos(this.lat_ts);var y=this.y0+this.a*Math.sin(lat)/Math.cos(this.lat_ts);p.x=x;p.y=y;return p;},inverse:function(p){p.x-=this.x0;p.y-=this.y0;var lon=Proj4js.common.adjust_lon(this.long0+ [...]
+this.m0=this.pj_mlfn(this.lat0,Math.sin(this.lat0),Math.cos(this.lat0),this.en);}},C1:.16666666666666666666,C2:.00833333333333333333,C3:.04166666666666666666,C4:.33333333333333333333,C5:.06666666666666666666,forward:function(p){var x,y;var lam=p.x;var phi=p.y;lam=Proj4js.common.adjust_lon(lam-this.long0);if(this.sphere){x=Math.asin(Math.cos(phi)*Math.sin(lam));y=Math.atan2(Math.tan(phi),Math.cos(lam))-this.phi0;}else{this.n=Math.sin(phi);this.c=Math.cos(phi);y=this.pj_mlfn(phi,this.n,thi [...]
+p.x=this.a*x+this.x0;p.y=this.a*y+this.y0;return p;},inverse:function(p){p.x-=this.x0;p.y-=this.y0;var x=p.x/this.a;var y=p.y/this.a;if(this.sphere){this.dd=y+this.lat0;phi=Math.asin(Math.sin(this.dd)*Math.cos(x));lam=Math.atan2(Math.tan(x),Math.cos(this.dd));}else{ph1=this.pj_inv_mlfn(this.m0+y,this.es,this.en);this.tn=Math.tan(ph1);this.t=this.tn*this.tn;this.n=Math.sin(ph1);this.r=1./(1.-this.es*this.n*this.n);this.n=Math.sqrt(this.r);this.r*=(1.-this.es)*this.n;this.dd=x/this.n;this. [...]
+p.x=Proj4js.common.adjust_lon(this.long0+lam);p.y=phi;return p;},pj_enfn:function(es){en=new Array();en[0]=this.C00-es*(this.C02+es*(this.C04+es*(this.C06+es*this.C08)));en[1]=es*(this.C22-es*(this.C04+es*(this.C06+es*this.C08)));var t=es*es;en[2]=t*(this.C44-es*(this.C46+es*this.C48));t*=es;en[3]=t*(this.C66-es*this.C68);en[4]=t*es*this.C88;return en;},pj_mlfn:function(phi,sphi,cphi,en){cphi*=sphi;sphi*=sphi;return(en[0]*phi-cphi*(en[1]+sphi*(en[2]+sphi*(en[3]+sphi*en[4]))));},pj_inv_ml [...]
+return phi;}
+Proj4js.reportError("cass:pj_inv_mlfn: Convergence error");return phi;},C00:1.0,C02:.25,C04:.046875,C06:.01953125,C08:.01068115234375,C22:.75,C44:.46875,C46:.01302083333333333333,C48:.00712076822916666666,C66:.36458333333333333333,C68:.00569661458333333333,C88:.3076171875}
+Proj4js.Proj.gauss={init:function(){sphi=Math.sin(this.lat0);cphi=Math.cos(this.lat0);cphi*=cphi;this.rc=Math.sqrt(1.0-this.es)/(1.0-this.es*sphi*sphi);this.C=Math.sqrt(1.0+this.es*cphi*cphi/(1.0-this.es));this.phic0=Math.asin(sphi/this.C);this.ratexp=0.5*this.C*this.e;this.K=Math.tan(0.5*this.phic0+Proj4js.common.FORTPI)/(Math.pow(Math.tan(0.5*this.lat0+Proj4js.common.FORTPI),this.C)*Proj4js.common.srat(this.e*sphi,this.ratexp));},forward:function(p){var lon=p.x;var lat=p.y;p.y=2.0*Math [...]
+if(!i){Proj4js.reportError("gauss:inverse:convergence failed");return null;}
+p.x=lon;p.y=lat;return p;}};Proj4js.Proj.omerc={init:function(){if(!this.mode)this.mode=0;if(!this.lon1){this.lon1=0;this.mode=1;}
+if(!this.lon2)this.lon2=0;if(!this.lat2)this.lat2=0;var temp=this.b/this.a;var es=1.0-Math.pow(temp,2);var e=Math.sqrt(es);this.sin_p20=Math.sin(this.lat0);this.cos_p20=Math.cos(this.lat0);this.con=1.0-this.es*this.sin_p20*this.sin_p20;this.com=Math.sqrt(1.0-es);this.bl=Math.sqrt(1.0+this.es*Math.pow(this.cos_p20,4.0)/(1.0-es));this.al=this.a*this.bl*this.k0*this.com/this.con;if(Math.abs(this.lat0)<Proj4js.common.EPSLN){this.ts=1.0;this.d=1.0;this.el=1.0;}else{this.ts=Proj4js.common.tsfn [...]
+this.el=this.f*Math.pow(this.ts,this.bl);}
+if(this.mode!=0){this.g=.5*(this.f-1.0/this.f);this.gama=Proj4js.common.asinz(Math.sin(this.alpha)/this.d);this.longc=this.longc-Proj4js.common.asinz(this.g*Math.tan(this.gama))/this.bl;this.con=Math.abs(this.lat0);if((this.con>Proj4js.common.EPSLN)&&(Math.abs(this.con-Proj4js.common.HALF_PI)>Proj4js.common.EPSLN)){this.singam=Math.sin(this.gama);this.cosgam=Math.cos(this.gama);this.sinaz=Math.sin(this.alpha);this.cosaz=Math.cos(this.alpha);if(this.lat0>=0){this.u=(this.al/this.bl)*Math. [...]
+if((this.con<=Proj4js.common.EPSLN)||(Math.abs(this.con-HALF_PI)<=Proj4js.common.EPSLN)){Proj4js.reportError("omercInitDataError");}else{if(Math.abs(Math.abs(this.lat0)-Proj4js.common.HALF_PI)<=Proj4js.common.EPSLN){Proj4js.reportError("omercInitDataError");}}
+this.singam=Math.sin(this.gam);this.cosgam=Math.cos(this.gam);this.sinaz=Math.sin(this.alpha);this.cosaz=Math.cos(this.alpha);if(this.lat0>=0){this.u=(this.al/this.bl)*Math.atan(Math.sqrt(this.d*this.d-1.0)/this.cosaz);}else{this.u=-(this.al/this.bl)*Math.atan(Math.sqrt(this.d*this.d-1.0)/this.cosaz);}}},forward:function(p){var theta;var sin_phi,cos_phi;var b;var c,t,tq;var con,n,ml;var q,us,vl;var ul,vs;var s;var dlon;var ts1;var lon=p.x;var lat=p.y;sin_phi=Math.sin(lat);dlon=Proj4js.co [...]
+us=this.al*lat/this.bl;}
+if(Math.abs(Math.abs(ul)-1.0)<=Proj4js.common.EPSLN){Proj4js.reportError("omercFwdInfinity");}
+vs=.5*this.al*Math.log((1.0-ul)/(1.0+ul))/this.bl;us=us-this.u;var x=this.x0+vs*this.cosaz+us*this.sinaz;var y=this.y0+us*this.cosaz-vs*this.sinaz;p.x=x;p.y=y;return p;},inverse:function(p){var delta_lon;var theta;var delta_theta;var sin_phi,cos_phi;var b;var c,t,tq;var con,n,ml;var vs,us,q,s,ts1;var vl,ul,bs;var dlon;var flag;p.x-=this.x0;p.y-=this.y0;flag=0;vs=p.x*this.cosaz-p.y*this.sinaz;us=p.y*this.cosaz+p.x*this.sinaz;us=us+this.u;q=Math.exp(-this.bl*vs/this.al);s=.5*(q-1.0/q);t=.5 [...]
+{lon=this.longc;if(ul>=0.0){lat=Proj4js.common.HALF_PI;}else{lat=-Proj4js.common.HALF_PI;}}else{con=1.0/this.bl;ts1=Math.pow((this.el/Math.sqrt((1.0+ul)/(1.0-ul))),con);lat=Proj4js.common.phi2z(this.e,ts1);theta=this.longc-Math.atan2((s*this.cosgam-vl*this.singam),con)/this.bl;lon=Proj4js.common.adjust_lon(theta);}
+p.x=lon;p.y=lat;return p;}};Proj4js.Proj.lcc={init:function(){if(!this.lat2){this.lat2=this.lat0;}
+if(!this.k0)this.k0=1.0;if(Math.abs(this.lat1+this.lat2)<Proj4js.common.EPSLN){Proj4js.reportError("lcc:init: Equal Latitudes");return;}
+var temp=this.b/this.a;this.e=Math.sqrt(1.0-temp*temp);var sin1=Math.sin(this.lat1);var cos1=Math.cos(this.lat1);var ms1=Proj4js.common.msfnz(this.e,sin1,cos1);var ts1=Proj4js.common.tsfnz(this.e,this.lat1,sin1);var sin2=Math.sin(this.lat2);var cos2=Math.cos(this.lat2);var ms2=Proj4js.common.msfnz(this.e,sin2,cos2);var ts2=Proj4js.common.tsfnz(this.e,this.lat2,sin2);var ts0=Proj4js.common.tsfnz(this.e,this.lat0,Math.sin(this.lat0));if(Math.abs(this.lat1-this.lat2)>Proj4js.common.EPSLN){t [...]
+this.f0=ms1/(this.ns*Math.pow(ts1,this.ns));this.rh=this.a*this.f0*Math.pow(ts0,this.ns);if(!this.title)this.title="Lambert Conformal Conic";},forward:function(p){var lon=p.x;var lat=p.y;if(lat<=90.0&&lat>=-90.0&&lon<=180.0&&lon>=-180.0){}else{Proj4js.reportError("lcc:forward: llInputOutOfRange: "+lon+" : "+lat);return null;}
+var con=Math.abs(Math.abs(lat)-Proj4js.common.HALF_PI);var ts,rh1;if(con>Proj4js.common.EPSLN){ts=Proj4js.common.tsfnz(this.e,lat,Math.sin(lat));rh1=this.a*this.f0*Math.pow(ts,this.ns);}else{con=lat*this.ns;if(con<=0){Proj4js.reportError("lcc:forward: No Projection");return null;}
+rh1=0;}
+var theta=this.ns*Proj4js.common.adjust_lon(lon-this.long0);p.x=this.k0*(rh1*Math.sin(theta))+this.x0;p.y=this.k0*(this.rh-rh1*Math.cos(theta))+this.y0;return p;},inverse:function(p){var rh1,con,ts;var lat,lon;x=(p.x-this.x0)/this.k0;y=(this.rh-(p.y-this.y0)/this.k0);if(this.ns>0){rh1=Math.sqrt(x*x+y*y);con=1.0;}else{rh1=-Math.sqrt(x*x+y*y);con=-1.0;}
+var theta=0.0;if(rh1!=0){theta=Math.atan2((con*x),(con*y));}
+if((rh1!=0)||(this.ns>0.0)){con=1.0/this.ns;ts=Math.pow((rh1/(this.a*this.f0)),con);lat=Proj4js.common.phi2z(this.e,ts);if(lat==-9999)return null;}else{lat=-Proj4js.common.HALF_PI;}
+lon=Proj4js.common.adjust_lon(theta/this.ns+this.long0);p.x=lon;p.y=lat;return p;}};Proj4js.Proj.laea={S_POLE:1,N_POLE:2,EQUIT:3,OBLIQ:4,init:function(){var t=Math.abs(this.lat0);if(Math.abs(t-Proj4js.common.HALF_PI)<Proj4js.common.EPSLN){this.mode=this.lat0<0.?this.S_POLE:this.N_POLE;}else if(Math.abs(t)<Proj4js.common.EPSLN){this.mode=this.EQUIT;}else{this.mode=this.OBLIQ;}
+if(this.es>0){var sinphi;this.qp=Proj4js.common.qsfnz(this.e,1.0);this.mmf=.5/(1.-this.es);this.apa=this.authset(this.es);switch(this.mode){case this.N_POLE:case this.S_POLE:this.dd=1.;break;case this.EQUIT:this.rq=Math.sqrt(.5*this.qp);this.dd=1./this.rq;this.xmf=1.;this.ymf=.5*this.qp;break;case this.OBLIQ:this.rq=Math.sqrt(.5*this.qp);sinphi=Math.sin(this.lat0);this.sinb1=Proj4js.common.qsfnz(this.e,sinphi)/this.qp;this.cosb1=Math.sqrt(1.-this.sinb1*this.sinb1);this.dd=Math.cos(this.l [...]
+y=Math.sqrt(2./y);x=y*cosphi*Math.sin(lam);y*=(this.mode==this.EQUIT)?sinphi:this.cosph0*sinphi-this.sinph0*cosphi*coslam;break;case this.N_POLE:coslam=-coslam;case this.S_POLE:if(Math.abs(phi+this.phi0)<Proj4js.common.EPSLN){Proj4js.reportError("laea:fwd:phi < eps");return null;}
+y=Proj4js.common.FORTPI-phi*.5;y=2.*((this.mode==this.S_POLE)?Math.cos(y):Math.sin(y));x=y*Math.sin(lam);y*=coslam;break;}}else{var coslam,sinlam,sinphi,q,sinb=0.0,cosb=0.0,b=0.0;coslam=Math.cos(lam);sinlam=Math.sin(lam);sinphi=Math.sin(phi);q=Proj4js.common.qsfnz(this.e,sinphi);if(this.mode==this.OBLIQ||this.mode==this.EQUIT){sinb=q/this.qp;cosb=Math.sqrt(1.-sinb*sinb);}
+switch(this.mode){case this.OBLIQ:b=1.+this.sinb1*sinb+this.cosb1*cosb*coslam;break;case this.EQUIT:b=1.+cosb*coslam;break;case this.N_POLE:b=Proj4js.common.HALF_PI+phi;q=this.qp-q;break;case this.S_POLE:b=phi-Proj4js.common.HALF_PI;q=this.qp+q;break;}
+if(Math.abs(b)<Proj4js.common.EPSLN){Proj4js.reportError("laea:fwd:b < eps");return null;}
+switch(this.mode){case this.OBLIQ:case this.EQUIT:b=Math.sqrt(2./b);if(this.mode==this.OBLIQ){y=this.ymf*b*(this.cosb1*sinb-this.sinb1*cosb*coslam);}else{y=(b=Math.sqrt(2./(1.+cosb*coslam)))*sinb*this.ymf;}
+x=this.xmf*b*cosb*sinlam;break;case this.N_POLE:case this.S_POLE:if(q>=0.){x=(b=Math.sqrt(q))*sinlam;y=coslam*((this.mode==this.S_POLE)?b:-b);}else{x=y=0.;}
+break;}}
+p.x=this.a*x+this.x0;p.y=this.a*y+this.y0;return p;},inverse:function(p){p.x-=this.x0;p.y-=this.y0;var x=p.x/this.a;var y=p.y/this.a;if(this.sphere){var cosz=0.0,rh,sinz=0.0;rh=Math.sqrt(x*x+y*y);var phi=rh*.5;if(phi>1.){Proj4js.reportError("laea:Inv:DataError");return null;}
+phi=2.*Math.asin(phi);if(this.mode==this.OBLIQ||this.mode==this.EQUIT){sinz=Math.sin(phi);cosz=Math.cos(phi);}
+switch(this.mode){case this.EQUIT:phi=(Math.abs(rh)<=Proj4js.common.EPSLN)?0.:Math.asin(y*sinz/rh);x*=sinz;y=cosz*rh;break;case this.OBLIQ:phi=(Math.abs(rh)<=Proj4js.common.EPSLN)?this.phi0:Math.asin(cosz*sinph0+y*sinz*cosph0/rh);x*=sinz*cosph0;y=(cosz-Math.sin(phi)*sinph0)*rh;break;case this.N_POLE:y=-y;phi=Proj4js.common.HALF_PI-phi;break;case this.S_POLE:phi-=Proj4js.common.HALF_PI;break;}
+lam=(y==0.&&(this.mode==this.EQUIT||this.mode==this.OBLIQ))?0.:Math.atan2(x,y);}else{var cCe,sCe,q,rho,ab=0.0;switch(this.mode){case this.EQUIT:case this.OBLIQ:x/=this.dd;y*=this.dd;rho=Math.sqrt(x*x+y*y);if(rho<Proj4js.common.EPSLN){p.x=0.;p.y=this.phi0;return p;}
+sCe=2.*Math.asin(.5*rho/this.rq);cCe=Math.cos(sCe);x*=(sCe=Math.sin(sCe));if(this.mode==this.OBLIQ){ab=cCe*this.sinb1+y*sCe*this.cosb1/rho
+q=this.qp*ab;y=rho*this.cosb1*cCe-y*this.sinb1*sCe;}else{ab=y*sCe/rho;q=this.qp*ab;y=rho*cCe;}
+break;case this.N_POLE:y=-y;case this.S_POLE:q=(x*x+y*y);if(!q){p.x=0.;p.y=this.phi0;return p;}
+ab=1.-q/this.qp;if(this.mode==this.S_POLE){ab=-ab;}
+break;}
+lam=Math.atan2(x,y);phi=this.authlat(Math.asin(ab),this.apa);}
+p.x=Proj4js.common.adjust_lon(this.long0+lam);p.y=phi;return p;},P00:.33333333333333333333,P01:.17222222222222222222,P02:.10257936507936507936,P10:.06388888888888888888,P11:.06640211640211640211,P20:.01641501294219154443,authset:function(es){var t;var APA=new Array();APA[0]=es*this.P00;t=es*es;APA[0]+=t*this.P01;APA[1]=t*this.P10;t*=es;APA[0]+=t*this.P02;APA[1]+=t*this.P11;APA[2]=t*this.P20;return APA;},authlat:function(beta,APA){var t=beta+beta;return(beta+APA[0]*Math.sin(t)+APA[1]*Math [...]
+p.x=this.x0+this.a*ksp*cosphi*Math.sin(dlon);p.y=this.y0+this.a*ksp*(this.cos_p12*sinphi-this.sin_p12*cosphi*coslon);return p;},inverse:function(p){p.x-=this.x0;p.y-=this.y0;var rh=Math.sqrt(p.x*p.x+p.y*p.y);if(rh>(2.0*Proj4js.common.HALF_PI*this.a)){Proj4js.reportError("aeqdInvDataError");return;}
+var z=rh/this.a;var sinz=Math.sin(z);var cosz=Math.cos(z);var lon=this.long0;var lat;if(Math.abs(rh)<=Proj4js.common.EPSLN){lat=this.lat0;}else{lat=Proj4js.common.asinz(cosz*this.sin_p12+(p.y*sinz*this.cos_p12)/rh);var con=Math.abs(this.lat0)-Proj4js.common.HALF_PI;if(Math.abs(con)<=Proj4js.common.EPSLN){if(lat0>=0.0){lon=Proj4js.common.adjust_lon(this.long0+Math.atan2(p.x,-p.y));}else{lon=Proj4js.common.adjust_lon(this.long0-Math.atan2(-p.x,p.y));}}else{con=cosz-this.sin_p12*Math.sin(la [...]
+p.x=lon;p.y=lat;return p;}};Proj4js.Proj.moll={init:function(){},forward:function(p){var lon=p.x;var lat=p.y;var delta_lon=Proj4js.common.adjust_lon(lon-this.long0);var theta=lat;var con=Proj4js.common.PI*Math.sin(lat);for(var i=0;true;i++){var delta_theta=-(theta+Math.sin(theta)-con)/(1.0+Math.cos(theta));theta+=delta_theta;if(Math.abs(delta_theta)<Proj4js.common.EPSLN)break;if(i>=50){Proj4js.reportError("moll:Fwd:IterationError");}}
+theta/=2.0;if(Proj4js.common.PI/2-Math.abs(lat)<Proj4js.common.EPSLN)delta_lon=0;var x=0.900316316158*this.a*delta_lon*Math.cos(theta)+this.x0;var y=1.4142135623731*this.a*Math.sin(theta)+this.y0;p.x=x;p.y=y;return p;},inverse:function(p){var theta;var arg;p.x-=this.x0;var arg=p.y/(1.4142135623731*this.a);if(Math.abs(arg)>0.999999999999)arg=0.999999999999;var theta=Math.asin(arg);var lon=Proj4js.common.adjust_lon(this.long0+(p.x/(0.900316316158*this.a*Math.cos(theta))));if(lon<(-Proj4js. [...]
diff --git a/zoo-project/zoo-client/lib/js/wps-client/utils.js b/zoo-project/zoo-client/lib/js/wps-client/utils.js
new file mode 100644
index 0000000..033e566
--- /dev/null
+++ b/zoo-project/zoo-client/lib/js/wps-client/utils.js
@@ -0,0 +1,74 @@
+define([
+], function() {
+    
+    
+    // parseUri 1.2.2
+    // (c) Steven Levithan <stevenlevithan.com>
+    // MIT License
+
+    function parseUri (str) {
+    	var	o   = parseUri.options,
+    		m   = o.parser[o.strictMode ? "strict" : "loose"].exec(str),
+    		uri = {},
+    		i   = 14;
+
+    	while (i--) uri[o.key[i]] = m[i] || "";
+
+    	uri[o.q.name] = {};
+    	uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
+    		if ($1) uri[o.q.name][$1] = $2;
+    	});
+
+    	return uri;
+    };
+
+    parseUri.options = {
+    	strictMode: false,
+    	key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],
+    	q:   {
+    		name:   "queryKey",
+    		parser: /(?:^|&)([^&=]*)=?([^&]*)/g
+    	},
+    	parser: {
+    		strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
+    		loose:  /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
+    	}
+    };
+    
+    
+    //
+    function xmlToString(data) {
+        //data.xml check for IE
+        var xmlstr = data.xml ? data.xml : (new XMLSerializer()).serializeToString(data);
+        return xmlstr;
+    }
+
+    function equalsString(a, b) {
+    	if (!a) {
+    		return false;
+    	}
+
+    	if (!b) {
+    		return false;
+    	}
+
+    	return jQuery.trim(a).localeCompare(jQuery.trim(b)) == 0;
+    }
+
+    function encodeXML(str) {
+        return str.replace(/&/g, '&')
+                   .replace(/</g, '<')
+                   .replace(/>/g, '>')
+                   .replace(/"/g, '"')
+                   .replace(/'/g, ''');
+    };
+    
+    return {
+        parseUri: parseUri,
+        xmlToString: xmlToString,
+        equalsString: equalsString,
+        encodeXML: encodeXML,
+    };
+    
+    
+});
\ No newline at end of file
diff --git a/zoo-project/zoo-client/lib/js/wps-client/wps-payload.js b/zoo-project/zoo-client/lib/js/wps-client/wps-payload.js
new file mode 100644
index 0000000..1a4e6a7
--- /dev/null
+++ b/zoo-project/zoo-client/lib/js/wps-client/wps-payload.js
@@ -0,0 +1,292 @@
+/**
+ * Author : Samuel Souk aloun
+ *
+ * Copyright (c) 2014 GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+define([
+    'jquery', 'utils'
+], function($, utils) {
+    
+    /**
+     * The wpsPayload module is using the 
+     * [Hogan.js]{@link http://twitter.github.io/hogan.js/} templating engine to
+     * generate XML requests to be sent to a WPS Server.
+     * In the ZOO-Client API, the Hogan.js templates have to be compiled before
+     * you can use them from you application. Please refer to the ZOO-Client 
+     * installation documentation for more informations.
+     * 
+     * @module wpsPayload 
+     * @requires payloads
+     * @requires jquery
+     * @requires utils
+     */
+    
+    return {
+
+	/** @exports wpsPayload */
+        
+        /**
+	 * The getPayload function uses the mustache 
+	 * templates and the parameters provided to generate a valid WPS XML 
+	 * request.
+	 * 
+	 * @static
+	 * @param {Object} params - The object representing the request.
+	 * @returns {string} - The corresponding XML request
+	 * @example
+	 * // GetCapabilities
+	 * var request_params = {
+         *     request: 'GetCapabilities',
+	 *     language: 'en-US'
+         * };
+	 * console.wpsPayload.getPayload(request_params));
+	 * @example
+	 * // DescribeProcess with Identifier value set to "all".
+	 * var request_params = {
+         *     request: 'DescribeProcess',
+	 *     identifier: ["all"]
+         * };
+	 * console.log(wpsPayload.getPayload(request_params));
+	 * @example
+	 * //
+	 * var request_params = {
+	 *     request: 'Execute',
+	 *     Identifier: "Buffer",
+	 *     DataInputs: [{"identifier":"InputPolygon","href":"http://features.org/toto.xml","mimeType":"text/xml"}],
+	 *     DataOutputs: [{"identifier":"Result","mimeType":"application/json"}], 
+	 *     language: 'en-US'
+	 * };
+	 * console.log(wpsPayload.getPayload(request_params));
+	 */
+        getPayload: function(params) {
+            if (params.request == 'DescribeProcess') {
+                return this.getPayload_DescribeProcess(params);
+            } else if (params.request == 'GetCapabilities') {
+                return this.getPayload_GetCapabilities(params);
+            } else if (params.request == 'Execute') {
+                return this.getPayload_Execute(params);
+            } else if (params.request == 'Dismiss') {
+                return this.getPayload_Dismiss(params);
+            } else {
+                console.log("#### UNKNOWN REQUEST ####");
+            }
+        },
+
+        /**
+	 * The getPayload_GetCapabilities function is used to generate a valid 
+	 * WPS XML GetCapabilities request using the 
+	 * [payload_GetCapabilities.mustache]{@link http://zoo-project.org/trac/browser/trunk/zoo-project/zoo-client/lib/tpl/payload_GetCapabilities.mustache} 
+	 * template.
+	 * 
+	 * @static
+	 * @param {Object} params - The object representing the request.
+	 * @returns {string} - The corresponding XML request
+	 * @example
+	 * // log the XML request in console
+	 * var request_params = {
+	 *     language: 'en-US'
+         * };
+	 * console.log(wpsPayload.getPayload_GetCapabilities(request_params));
+	 */
+        getPayload_GetCapabilities: function(params) {
+	    var id="payload_GetCapabilities";
+	    if(params.version=="2.0.0")
+		id+="2";
+	    return templates[id].render(params);
+        },
+        
+        /**
+	 * The getPayload_DescribeProcess function is used to generate a valid 
+	 * WPS XML DescribeProcess  request using the 
+	 * [payload_DescribeProcess.mustache]{@link http://zoo-project.org/trac/browser/trunk/zoo-project/zoo-client/lib/tpl/payload_DescribeProcess.mustache} 
+	 * template.
+	 * 
+	 * @static
+	 * @param {Object} params - The object representing the request.
+	 * @returns {string} - The corresponding XML request
+	 * @example
+	 * // log the XML request in console
+	 * var request_params = {
+	 *     Identifier: ["Buffer","Centroid"],
+	 *     language: 'en-US'
+         * };
+	 * console.log(wpsPayload.getPayload_DescribeProcess(request_params));
+	 */
+        getPayload_DescribeProcess: function(params) {
+	    var id="payload_DescribeProcess";
+	    if(params.version=="2.0.0")
+		id+="2";
+            if (params.Identifier) {
+                if ($.isArray(params.Identifier)) {
+                    return templates[id].render({identifiers: params.Identifier,language: params.language});
+                }
+                else {
+                    return templates[id].render({identifiers: [params.Identifier],language: params.language});
+                }
+            }
+            // TODO: no Identifier
+        },
+
+        /**
+	 * The getPayload_Dismiss function is used to generate a valid 
+	 * WPS XML Dimiss request using the 
+	 * [payload_Dismiss.mustache]{@link http://zoo-project.org/trac/browser/trunk/zoo-project/zoo-client/lib/tpl/payload_Dismiss.mustache} 
+	 * template.
+	 * 
+	 * @static
+	 * @param {Object} params - The object representing the request.
+	 * @returns {string} - The corresponding XML request
+	 * @example
+	 * // log the XML request in console
+	 * var request_params = {
+	 *     jobId: ["XXXX","XXX"]
+         * };
+	 * console.log(wpsPayload.getPayload_DescribeProcess(request_params));
+	 */
+        getPayload_Dismiss: function(params) {
+	    var id="payload_Dismiss";
+	    params.version="2.0.0";
+            if (params.jobid) {
+                if ($.isArray(params.jobid)) {
+                    return templates[id].render({jobid: params.jobid});
+                }
+                else {
+                    return templates[id].render({jobid: [params.jobid]});
+                }
+            }
+            // TODO: no Identifier
+        },
+
+
+        /**
+	 * The getPayload_Execute function is used to generate a valid WPS XML 
+	 * Excute request using the 
+	 * [payload_Execute.mustache]{@link http://zoo-project.org/trac/browser/trunk/zoo-project/zoo-client/lib/tpl/payload_Execute.mustache}
+	 * template.
+	 * 
+	 * @static
+	 * @param {Object} params - The object representing the request.
+	 * @returns {string} - The corresponding XML request
+	 * @example
+	 * // log the XML request in console
+	 * var request_params = {
+	 *     Identifier: "Buffer",
+	 *     DataInputs: [{"identifier":"InputPolygon","href":"http://features.org/toto.xml","mimeType":"text/xml"}],
+	 *     DataOutputs: [{"identifier":"Result","mimeType":"application/json"}], 
+	 *     language: 'en-US'
+	 * };
+	 * console.log(wpsPayload.getPayload_Execute(request_params));
+	 */
+        getPayload_Execute: function(params) {
+	    var id="payload_Execute";
+	    if(params.version=="2.0.0")
+		id+="2";
+            if (params.DataInputs) {
+                for (var i = 0; i < params.DataInputs.length; i++) {
+		    /**
+		     * Define inputs type depending on presence of mimeType, 
+		     * dataType and crs or dimension for ComplexData, 
+		     * LiteralData and BoundingBox data respectively
+		     */
+		    var hasType=false;
+		    var lp={"data":"literal","mime":"complex"};
+		    for(j in lp){
+			if (params.DataInputs[i][j+"Type"]) {
+			    params.DataInputs[i]['is_'+lp[j]] = true;
+			    params.DataInputs[i].type=lp[j];
+			    if(j=="mime"){
+				params.DataInputs[i].is_XML=(params.DataInputs[i][j+"Type"]=="text/xml");
+				if(!params.DataInputs[i].is_XML){
+				    var tmp=params.DataInputs[i][j+"Type"].split(";");
+				    params.DataInputs[i].is_XML=(tmp[0]=="text/xml");
+				}
+			    }
+			    hasType=true;
+			}
+                    }
+		    if(!hasType){
+			if (params.DataInputs[i]["type"]=="bbox" || 
+			    params.DataInputs[i]["dimension"] || 
+			    params.DataInputs[i]["crs"]){
+
+			    params.DataInputs[i]['is_bbox'] = true;
+			    params.DataInputs[i].type='bbox';
+			    hasType=true;
+			    
+			}
+			if(!hasType){
+			    params.DataInputs[i]['is_literal'] = true;
+			    params.DataInputs[i].type = "literal";
+			}
+		    }
+                    /*
+                     * Set some default values and flags.
+                     */
+                    if (params.DataInputs[i].type == 'bbox') {
+                	if (!params.DataInputs[i].crs) {
+                    	    params.DataInputs[i].crs = "EPSG:4326";
+                    	}
+                    	if (!params.DataInputs[i].dimension) {
+                    	    params.DataInputs[i].dimension = 2;
+                    	}
+            	    }
+                    
+                    // Complex data from payload callback.
+                    if (params.DataInputs[i].complexPayload_callback) {
+                        params.DataInputs[i].value = window[params.DataInputs[i].complexPayload_callback];
+                    }
+                    
+                    // Complex data from reference.
+                    if (params.DataInputs[i].href) {
+                        params.DataInputs[i].is_reference = true;
+                        //params.DataInputs[i].href = utils.encodeXML(params.DataInputs[i].href);
+                        if (params.DataInputs[i].method == 'POST') {
+                            params.DataInputs[i].is_post = true;
+                        } else {
+                            params.DataInputs[i].is_get = true;
+                        }
+                    }
+                    else {                        
+                        // Complex data, embeded
+                    }
+                } // for i loop
+            }
+
+            //console.log("==== OUTPUTS ====");
+            if (params.DataOutputs || params.storeExecuteResponse || params.status || params.lineage) {
+                
+                for (var i = 0; i < params.DataOutputs.length; i++) {
+                    //console.log(params.DataOutputs[i]);
+                    
+                    if (params.DataOutputs[i].type) {
+                        params.DataOutputs[i]['is_'+params.DataOutputs[i].type] = true;
+                    }
+                }
+            }
+            
+            return templates[id].render(params);
+        },
+        
+
+    };
+
+});
diff --git a/zoo-project/zoo-client/lib/js/wps-client/zoo.js b/zoo-project/zoo-client/lib/js/wps-client/zoo.js
new file mode 100644
index 0000000..6dd991b
--- /dev/null
+++ b/zoo-project/zoo-client/lib/js/wps-client/zoo.js
@@ -0,0 +1,1003 @@
+/**
+ * Author : Samuel Souk aloun
+ *
+ * Copyright (c) 2014 GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+define([
+    'xml2json', 'queryString', 'wpsPayload', 'utils'
+], function(X2JS, qs, wpsPayload, utils) {
+
+    /** 
+     * The ZooProcess Class
+     * @constructs ZooProcess
+     * @param {Object} params Parameters
+     * @example
+     * var myZooObject = new ZooProcess({
+     *     url: "http://localhost/cgi-bin/zoo_loader.cgi",
+     *     delay: 2500
+     * });
+     */
+    var ZooProcess = function(params) {
+        
+        /**
+	 * Object configuring the xml2json use.
+	 *
+         * @access private
+	 * @memberof ZooProcess#
+	 * @var _x2js {x2js}
+         */         
+        var _x2js = new X2JS({
+            arrayAccessFormPaths: [
+            'ProcessDescriptions.ProcessDescription.DataInputs.Input',
+            'ProcessDescriptions.ProcessDescription.DataInputs.Input.ComplexData.Supported.Format',
+            'ProcessDescriptions.ProcessDescription.ProcessOutputs.Output',
+            'ProcessDescriptions.ProcessDescription.ProcessOutputs.Output.ComplexOutput.Supported.Format',
+            'Capabilities.ServiceIdentification.Keywords'
+            ],   
+        });
+
+       
+        /**
+         * @access public
+	 * @memberof ZooProcess#
+	 * @var debug {Boolean} true if verbose messages should be displayed on the console
+	 * @default false
+         */         
+        this.debug = false;
+        /**
+         * @access public
+	 * @memberof ZooProcess#
+	 * @var url {String} The WPS Server URL
+	 */
+        this.url = params.url;
+        /**
+         * @access public
+	 * @memberof ZooProcess#
+	 * @var version {String} The WPS version
+	 */
+        this.version = params.version?params.version:"1.0.0";
+        /**
+         * @access public
+	 * @memberof ZooProcess#
+	 * @var language {String} The language to be used to request the WPS Server
+	 * @default "en-US"
+	 */
+        this.language = params.language?params.language:"en-US";
+        /**
+         * @access public
+	 * @memberof ZooProcess#
+	 * @var statusLocation {Object} An object to store the statusLocation 
+	 * URLs when running request including both the storeExecuteResponse and
+	 * the status parameters set to true.
+	 */
+        this.statusLocation = {};
+        /**
+         * @access public
+	 * @memberof ZooProcess#
+	 * @var launched {Object} An object to store the running asynchrone services.
+	 */
+        this.launched = {};
+        /**
+         * @access public
+	 * @memberof ZooProcess#
+	 * @var terminated {Object} An object to store the finished services.
+	 */
+        this.terminated = {};
+        /**
+         * @access public
+	 * @memberof ZooProcess#
+	 * @var percent {Object} An object to store the percentage of completude of services.
+	 */
+        this.percent = {};
+        /**
+         * @access public
+	 * @memberof ZooProcess#
+	 * @var delay {Integer} The time (in milliseconds) between each polling requests.
+	 * @default 2000
+	 */
+        this.delay = params.delay || 2000;
+        
+	/**
+	 * The getCapabilities method run the GetCapabilities request by calling {@link ZooProcess#request}.
+	 * 
+	 * @method getCapabilities
+	 * @memberof ZooProcess#
+	 * @param {Object} params The parameter for the request and callback functions to call on success or
+	 * on failure.
+	 * @example
+	 * // Log the array of available processes in console
+	 * myZooObject.getCapabilities({
+	 *     type: 'POST',
+	 *     success: function(data){
+	 *         console.log(data["Capabilities"]["ProcessOfferings"]["Process"]);
+	 *     }
+	 * });
+	 */
+        this.getCapabilities = function(params) {
+            var closure = this;
+
+            if (!params.hasOwnProperty('type')) {
+                params.type = 'GET';
+            }
+
+            var zoo_request_params = {
+                request: 'GetCapabilities',
+                service: 'WPS',
+                version: (params.hasOwnProperty('version')?params.version:closure.version),
+            }
+
+            this.request(zoo_request_params, params.success, params.error, params.type);
+        };
+        
+	/**
+	 * The describeProcess method run the DescribeProcess request by calling {@link ZooProcess#request}.
+	 * 
+	 * @method describeProcess
+	 * @memberof ZooProcess#
+	 * @param {Object} params 
+	 * @example
+	 * // Log x2js representation of all available services in console
+	 * myZooObject.describeProcess({
+	 *     type: 'POST',
+	 *     identifier: "all"
+	 *     success: function(data){
+	 *         console.log(data);
+	 *     }
+	 * });
+	 */
+        this.describeProcess = function(params) {
+            var closure = this;
+
+            if (!params.hasOwnProperty('type')) {
+                params.type = 'GET';
+            }
+
+            var zoo_request_params = {
+                Identifier: params.identifier,
+                request: 'DescribeProcess',
+                service: 'WPS',
+                version: (params.hasOwnProperty('version')?params.version:closure.version),
+            }
+
+            this.request(zoo_request_params, params.success, params.error, params.type);
+        };
+        
+	/**
+	 * The convertParams method convert parameters for Execute requests
+	 *
+	 * @method convertParams
+	 * @memberof ZooProcess#
+	 * @param {Object} params The original object
+	 * @returns {Object} The converted object
+	 */
+	this.convertParams = function(params){
+	    var closure = this;
+	    if(closure.debug){
+		console.log("======== Execute "+params.identifier);
+		console.log(params);
+	    }
+
+            if (!params.hasOwnProperty('type')) {
+                params.type = 'GET';
+            }
+
+            var zoo_request_params = {
+                request: 'Execute',
+                service: 'WPS',
+                version: (params.hasOwnProperty('version')?params.version:closure.version),
+                Identifier: params.identifier,
+                DataInputs: params.dataInputs ? params.dataInputs : '',
+                DataOutputs: params.dataOutputs ? params.dataOutputs : '',
+            }
+
+	    console.log(zoo_request_params);
+
+            if (params.hasOwnProperty('responseDocument')) {
+                zoo_request_params.ResponseDocument = params.responseDocument;
+            }
+            if (params.hasOwnProperty('mode')) {
+                zoo_request_params.mode = params.mode;
+            }
+            if (params.hasOwnProperty('storeExecuteResponse') &&  params.storeExecuteResponse) {
+                zoo_request_params.storeExecuteResponse = 'true';
+            }
+            if (params.hasOwnProperty('status') &&  params.status) {
+                zoo_request_params.status = 'true';
+            }
+            if (params.hasOwnProperty('lineage') &&  params.lineage) {
+                zoo_request_params.lineage = 'true';
+            }
+	    return zoo_request_params;
+	};
+
+	/**
+	 * The buildRequest method is building the object expected by
+	 * [jQuery.ajax]{@link http://api.jquery.com/jquery.ajax/}.
+	 * In case of GET request, it will use {@link ZooProcess#getQueryString}.
+	 * In case of POST request, it will use {@link module:wpsPayload} getPayload.
+	 *
+	 * @method buildRequest
+	 * @memberof ZooProcess#
+	 * @param {Object} params the request parameters
+	 * @param {String} type the request method ("GET" or "POST")
+	 * @returns {Object} The expected object to give as input for the 
+	 * [jQuery.ajax]{@link http://api.jquery.com/jquery.ajax/} function.
+	 */
+	this.buildRequest = function(params,type){
+            var closure = this;
+	    if(closure.debug){
+		console.log('======== REQUEST method='+type);
+		console.log(params);
+	    }
+            var url = this.url;
+            var payload;
+            var headers;
+	    if(params.hasOwnProperty('DataOutputs'))
+		for(var i=0;i<params.DataOutputs.length;i++)
+		    if(params.DataOutputs[i].type==="raw"){
+			params["RawDataOutput"]=params.DataOutputs[i];
+			break;
+		    }
+
+	    params["language"]=this.language;
+            if (type == 'GET') {
+                url += '?' + this.getQueryString(params);
+            } else if (type == 'POST') {
+                payload = wpsPayload.getPayload(params);
+		if(closure.debug){
+                    console.log("======== POST PAYLOAD ========");
+                    console.log(payload);
+		    console.log(params);
+		}
+
+                headers = {
+                    "Content-Type": "text/xml"        
+                };
+            }
+	    
+            if(closure.debug){
+		console.log("ajax url: "+url);
+	    }
+	    return {"url":url,"headers": headers,"data": payload,"type":type};
+	};
+
+	/**
+	 * The getRequest method call the {@link ZooProcess#buildRequest} method
+	 * by giving the {@link ZooProcess#convertParams} result as first 
+	 * argument and the detected type (default is 'GET') defined in params.
+	 * 
+	 * @method getRequest
+	 * @memberof ZooProcess#
+	 * @params {Object} params The request parameters
+	 */
+	this.getRequest = function(params){
+	    var closure = this;
+	    var type = 'GET';
+	    if(params.hasOwnProperty("type"))
+		type=params["type"];
+	    return closure.buildRequest(closure.convertParams(params),type);
+	};
+
+	/**
+	 * The execute method run the Execute request by calling {@link ZooProcess#request}
+	 * with the params converted by {@link ZooProcess#convertParams}.
+	 *
+	 * @method execute
+	 * @memberof ZooProcess#
+	 * @param {Object} param Parameters
+	 * @example
+	 * myZooObject.execute({
+	 *     identifier: "Buffer",
+	 *     dataInputs: [{"identifier":"InputPolygon","href":"http://features.org/toto.xml","mimeType":"text/xml"}],
+	 *     dataOutputs: [{"identifier":"Result","mimeType":"application/json","type":"raw"}],
+	 *     type: 'POST',
+	 *     success: function(data) {
+	 *         console.log(data);
+	 *     }
+	 * });
+	 */
+        this.execute = function(params) {
+            var closure = this;
+            this.request(closure.convertParams(params), params.success, params.error, params.type);
+        };
+
+        
+	/**
+	 * The request method call {@link ZooProcess#buildRequest} method to
+	 * to build parameters to give to 
+	 * [jQuery.ajax]{@link http://api.jquery.com/jquery.ajax/}.
+	 * If the request succeed and if the content-type of the response is 
+	 * "text/xml" then xml2json is called on the resulting data and passed 
+	 * to the onSuccess callback function given in parameter. In case the
+	 * request failed, the WPS Exception Repport will be parsed with 
+	 * xml2json and given as parameter to the onError callback function.
+	 *
+	 * @method request
+	 * @memberof ZooProcess#
+	 * @param {Object} params The object used as parameter for
+	 * [jQuery.ajax]{@link http://api.jquery.com/jquery.ajax/}
+	 * @param {Function} onSuccess The callback function called if the request succeed
+	 * @param {Function} onError The callback function called if the request failed 
+	 * @param {String} type The request method ('GET' or 'POST')
+	 */
+        this.request = function(params, onSuccess, onError, type) {
+            var closure = this;
+
+	    var obj;
+	    obj=closure.buildRequest(params,type);
+            $.ajax(obj)
+		.always(
+                    function() {
+			//console.log("ALWAYS");
+                    }
+		)
+		.fail(
+                    function(jqXHR, textStatus, errorThrown) {
+			if(closure.debug){
+			    console.log("======== ERROR ========");
+			}
+			var robj=_x2js.xml2json( jqXHR.responseXML );
+			if(closure.debug){
+			    console.log(robj);
+			}
+			if(onError)
+			    onError(robj);
+                    }
+		)
+		.done(
+                    function(data, textStatus, jqXHR) {
+			if(closure.debug){
+			    console.log("======== SUCCESS ========2");
+			    console.log(data);
+			}
+			var ctype=jqXHR.getResponseHeader("Content-Type").split(";")[0];
+			if( ctype=="text/xml" )
+			{
+			    var tmpD=data;
+			    data = _x2js.xml2json( data );
+			    data._origin=tmpD;
+			}
+			var launched;
+			var version=(params.version?params.version:closure.version);
+			if(version=="1.0.0"){
+			    if (params.storeExecuteResponse == 'true' && params.status == 'true') {
+				launched = closure.parseStatusLocation(data);            
+				closure.statusLocation[launched.sid] = launched.statusLocation;
+				
+				if ( launched.hasOwnProperty('sid') && 
+				     !closure.launched.hasOwnProperty(launched.sid)) {
+				    closure.launched[launched.sid] = launched.statusLocation;
+				}
+			    }
+			}
+			else{
+			    if (params.mode == 'async') {
+				launched = closure.parseJobID(data);
+				closure.statusLocation[launched.sid] = closure.url+"?request=GetStatus&service=WPS&version=2.0.0&JobID="+launched.jobid;
+				if ( launched.hasOwnProperty('sid') && 
+				     !closure.launched.hasOwnProperty(launched.sid)) {
+				    closure.launched[launched.sid] = launched.jobid;
+				}
+			    }	    
+			}
+
+			if(onSuccess)
+			    onSuccess(data, launched);
+		    });
+        };
+        
+	/**
+	 * The watch method should be used from the success callback function
+	 * passed to {@link ZooProcess#execute} when both status and 
+	 * storeExecuteResponse parameters are set to 'true', so when the 
+	 * service should be called asynchronously. This function is
+	 * responsible for polling the WPS server until the service end (success
+	 * or failure). It call the {@link ZooProcess#getStatus} method every
+	 * {@link ZooProcess#delay} milliseconds.
+	 *
+	 * @method watch
+	 * @memberof ZooProcess#
+	 * @param {Integer} sid The identifier of the running service
+	 * @param {Object} handlers The callback function definitions 
+	 * (onPercentCompleted, onProcessSucceeded, onError)
+	 * @example
+	 * zoo.execute({
+	 *     identifier: 'MyIdentifier',
+	 *     type: 'POST',
+	 *     dataInputs: myInputs,
+	 *     dataOutputs: myOupts,
+	 *     storeExecuteResponse: true,
+	 *     status: true,
+	 *     success: function(data, launched) {
+	 *         zoo.watch(launched.sid, {
+         *             onPercentCompleted: function(data) {
+	 *                 console.log("**** PercentCompleted ****");
+	 *                 console.log(data);
+         *                 progress.text(data.text+' : '+(data.percentCompleted)+'%');
+         *             },
+	 *             onProcessSucceeded: function(data) {
+         *                 progress.css('width', (100)+'%');
+	 *                 progress.text(data.text+' : '+(100)+'%');
+	 *                     if (data.result.ExecuteResponse.ProcessOutputs) {
+	 *                         console.log("**** onSuccess ****");
+	 *                         console.log(data.result);
+	 *                     }
+	 *             },
+	 *             onError: function(data) {
+	 *                 console.log("**** onError ****");
+	 *                 console.log(data);
+	 *             },
+         *         });
+	 *     },
+	 *     error: function(data) {
+	 *         console.log("**** ERROR ****");
+	 *         console.log(data);
+	 *         notify("Execute asynchrone failed", 'danger');
+	 *     }
+	 * });
+	 */
+        this.watch = function(sid, handlers) {
+            //onPercentCompleted, onProcessSucceeded, onError
+            var closure = this;
+	    if(closure.debug){
+		console.log("WATCH: "+sid);
+	    }
+
+            function onSuccess(data) {
+		if(closure.debug){
+                    console.log("++++ getStatus SUCCESS "+sid);
+                    console.log(data);
+		}
+
+		if(data.StatusInfo || data.Result){
+		    if (data.Result) {
+
+			var ret = {
+                            sid: sid,
+                            text: "",
+                            result: data
+			};
+
+			if (handlers.onProcessSucceeded instanceof Function) {
+                            handlers.onProcessSucceeded(ret);
+			}
+
+			return;
+		    }
+		    if (data.StatusInfo.Status == "Running") {
+			if(closure.debug){
+			    console.log("#### ProcessStarted");
+			}
+			
+			var message="";
+			for(index=0;index<data._origin.childNodes[0].childNodes.length;index++){
+			    if(data._origin.childNodes[0].childNodes[index].nodeType==8){
+				message=data._origin.childNodes[0].childNodes[index].textContent;
+			    }
+			}
+			var ret = {
+                            sid: sid,
+                            percentCompleted: (data.StatusInfo.PercentCompleted?data.StatusInfo.PercentCompleted:0),
+                            text: message,
+                            creationTime: "",
+			};
+
+			if (handlers.onPercentCompleted instanceof Function) {
+                            handlers.onPercentCompleted(ret);
+			}
+                    }
+                    else if (data.StatusInfo.Status == "Succeeded") {
+			if(closure.debug){
+			    console.log("#### ProcessSucceeded");
+			}
+
+			var text = "";
+			closure.terminated[sid] = true;
+
+			ret = {
+                            sid: sid,
+                            text: text,
+                            result: data
+			};
+			
+			closure.getResult(sid, onSuccess, onError);
+                    }
+                    else {
+			if(closure.debug){
+			    console.log("#### UNHANDLED EXCEPTION");
+			}
+			closure.terminated[sid] = true;
+			ret = {
+                            sid: sid,
+                            code: 'BAD',
+                            text: 'UNHANDLED EXCEPTION'
+			};
+			
+			//closure.emit('exception', ret);
+			if (handlers.onError instanceof Function) {
+                            handlers.onError(ret);
+			}
+                    }
+
+		    return
+		}
+
+		if (data.ExecuteResponse.Status.ProcessAccepted) {
+                    var ret = {
+                        sid: sid,
+                        percentCompleted: 0,
+                        text: data.ExecuteResponse.Status.ProcessAccepted.__text,
+                        creationTime: data.ExecuteResponse.Status._creationTime,
+                    };
+
+                    closure.percent[sid] = ret.percentCompleted;
+                    //closure.emit('percent', ret);
+
+                    if (handlers.onPercentCompleted instanceof Function) {
+                        handlers.onPercentCompleted(ret);
+                    }
+
+		}
+                else if (data.ExecuteResponse.Status.ProcessStarted) {
+		    if(closure.debug){
+			console.log("#### ProcessStarted");
+		    }
+
+                    var ret = {
+                        sid: sid,
+                        percentCompleted: data.ExecuteResponse.Status.ProcessStarted._percentCompleted,
+                        text: data.ExecuteResponse.Status.ProcessStarted.__text,
+                        creationTime: data.ExecuteResponse.Status._creationTime,
+                    };
+
+                    closure.percent[sid] = ret.percentCompleted;
+                    //closure.emit('percent', ret);
+
+                    if (handlers.onPercentCompleted instanceof Function) {
+                        handlers.onPercentCompleted(ret);
+                    }
+                }
+                else if (data.ExecuteResponse.Status.ProcessSucceeded) {
+		    if(closure.debug){
+			console.log("#### ProcessSucceeded");
+		    }
+
+                    var text = data.ExecuteResponse.Status.ProcessSucceeded.__text;
+                    closure.terminated[sid] = true;
+
+                    ret = {
+                        sid: sid,
+                        text: text,
+                        result: data
+                    };
+
+                    //closure.emit('success', ret);
+                    if (handlers.onProcessSucceeded instanceof Function) {
+                        handlers.onProcessSucceeded(ret);
+                    }
+                }
+                else {
+		    if(closure.debug){
+			console.log("#### UNHANDLED EXCEPTION");
+		    }
+                    closure.terminated[sid] = true;
+                    ret = {
+                        sid: sid,
+                        code: 'BAD',
+                        text: 'UNHANDLED EXCEPTION'
+                    };
+
+                    //closure.emit('exception', ret);
+                    if (handlers.onError instanceof Function) {
+                        handlers.onError(ret);
+                    }
+                }    
+            }
+
+            function onError(data) {
+		if(closure.debug){
+                    console.log("++++ getStatus ERROR "+sid);
+                    console.log(data);
+		}
+            }
+
+            function ping(sid) {
+		if(closure.debug){
+                    console.log("PING: "+sid);
+		}
+
+                closure.getStatus(sid, onSuccess, onError);
+                if (closure.terminated[sid]) {
+		    if(closure.debug){
+			console.log("++++ getStatus TERMINATED "+sid);
+		    }
+                }
+                else if (!closure.percent.hasOwnProperty(sid) || closure.percent[sid]<100) {
+                    setTimeout( function() {
+                        ping(sid);
+                     }, closure.delay);
+                } else {
+		    if(closure.debug){
+			console.log(closure.percent);
+		    }
+                }
+            }
+
+            ping(sid);
+        };
+        
+	/**
+	 * The getStatus method call 
+	 * [jQuery.ajax]{@link http://api.jquery.com/jquery.ajax/} to fecth the
+	 * ExecuteResponse document which contains a Status node and
+	 * potentially the result (when the asynch service end). This method is
+	 * used by {@link ZooProcess#watch} to get the ongoing status of 
+	 * services called asynchronously.
+	 * 
+	 * @method getStatus
+	 * @memberof ZooProcess#
+	 * @param {Integer} sid Service Identifier
+	 * @param {Function} onSuccess callback 
+	 * @param {Function} onError callback 
+	 */
+        this.getStatus = function(sid, onSuccess, onError) {
+            var closure = this;
+	    if(closure.debug){
+		console.log("GET STATUS: "+sid);
+	    }
+            if (closure.terminated[sid]) {
+		if(closure.debug){
+                    console.log("DEBUG TERMINATED");
+		}
+                return;
+            }
+            if (!closure.launched[sid]) {
+		if(closure.debug){
+                    console.log("DEBUG LAUNCHED");
+		}
+                return;
+            }
+
+            $.ajax({
+		url: closure.statusLocation[sid]
+	    })
+		.fail(
+                    function(jqXHR, textStatus, errorThrown) {
+			if(closure.debug){
+			    console.log("======== ERROR ========");
+			}
+			var robj=_x2js.xml2json( jqXHR.responseXML );
+			if(closure.debug){
+			    console.log(robj);
+			}
+			if(onError)
+			    onError(robj);
+                    }
+		)
+		.done(
+                    function(data, textStatus, jqXHR) {
+			if(closure.debug){
+			    console.log("======== SUCCESS ========2");
+			    console.log(data);
+			}
+			var ctype=jqXHR.getResponseHeader("Content-Type").split(";")[0];
+			if( ctype=="text/xml" ){
+			    var tmpD=data;
+			    data = _x2js.xml2json( data );
+			    data._origin=tmpD;
+			}
+			if(onSuccess)
+			    onSuccess(data);
+		    });
+        };
+
+	/**
+	 * The getResult method is used by {@link ZooProcess#watch} to get the
+	 * final result of services called asynchronously.
+	 * 
+	 * @method getResult
+	 * @memberof ZooProcess#
+	 * @param {Integer} sid Service Identifier
+	 * @param {Function} onSuccess callback 
+	 * @param {Function} onError callback 
+	 */
+        this.getResult = function(sid, onSuccess, onError) {
+            var closure = this;
+	    if(closure.debug){
+		console.log("GET STATUS: "+sid);
+		console.log(closure.statusLocation[sid].replace(/GetStatus/g,"GetResult"));
+	    }
+            $.ajax({
+		url: closure.statusLocation[sid].replace(/GetStatus/g,"GetResult")
+	    })
+		.fail(
+                    function(jqXHR, textStatus, errorThrown) {
+			if(closure.debug){
+			    console.log("======== ERROR ========");
+			}
+			var robj=_x2js.xml2json( jqXHR.responseXML );
+			if(closure.debug){
+			    console.log(robj);
+			}
+			if(onError)
+			    onError(robj);
+                    }
+		)
+		.done(
+                    function(data, textStatus, jqXHR) {
+			if(closure.debug){
+			    console.log("======== SUCCESS ========2");
+			    console.log(data);
+			}
+			var ctype=jqXHR.getResponseHeader("Content-Type").split(";")[0];
+			if( ctype=="text/xml" ){
+			    var tmpD=data;
+			    data = _x2js.xml2json( data );
+			    data._origin=tmpD;
+			}
+			if(onSuccess)
+			    onSuccess(data);
+		    });
+        };
+        
+	/**
+	 * The getQueryString method generate a KVP GET request which can be 
+	 * used to request a WPS server.
+	 *
+	 * @method getQueryString
+	 * @memberof ZooProcess#
+	 * @param {Object} params The WPS requests parameters
+	 * @returns {String} The GET WPS request
+	 * @example
+	 * // Log GetCapabilities GET request in console
+	 * var request_params = {
+	 *     request: 'GetCapabilities',
+         *     service: 'WPS',
+         *     version: '1.0.0',
+	 *     language; 'en-US'
+         * }
+	 * console.log(myZooObject.getQueryString(request_params));
+	 */
+        this.getQueryString = function(params) {
+	    var closure = this;
+            var ret = '';
+
+            serializeInputs = function(obj) {
+		if(closure.debug){
+		    console.log("SERIALIZE dataInputs");
+		    console.log(obj);
+		}
+		var lt=$.type(obj);
+		if(lt === "string") {
+                    return obj;
+		}
+		var str = [];
+		for(var p in obj){
+		    if(lt === "array"){
+			if(obj[p].hasOwnProperty("href"))
+			    str.push(obj[p]["identifier"] + "=Reference");
+			else
+			    str.push(obj[p]["identifier"] + "=" + obj[p]["value"]);
+			for(var q in obj[p]){
+			    if(q!="identifier" && q!="value" && q!="href")
+				str.push("@" + q + "=" + obj[p][q]);
+			    else
+				if(q=="href")
+				    str.push("@xlink:" + q + "=" + encodeURIComponent(obj[p][q]));
+			}
+			str.push(";");
+		    }
+		    else
+			if (obj.hasOwnProperty(p)) {
+			    if(p=="href")
+				str.push(p + "=" + encodeURIComponent(obj[p]));
+			    else
+				str.push(p + "=" + obj[p]);
+			}
+		}
+		return str.join("");
+            }
+
+            serializeOutputs = function(obj) {
+		if(closure.debug){
+		    console.log("SERIALIZE dataOutputs");
+		    console.log(obj);
+		}
+		var lt=$.type(obj);
+		if(lt === "string") {
+                    return obj;
+		}
+		var str = [];
+		for(var p in obj){
+		    str.push(obj[p]["identifier"]);
+		    for(var q in obj[p]){
+			if(q!="identifier" && q!="type")
+			    str.push("@" + q + "=" + obj[p][q]);
+		    }
+		    str.push(";");
+		}
+		return str.join("");
+            }
+	    
+            var responseDocument = params.ResponseDocument;
+            var tmp_params = {};
+
+            var objectKeys = Object.keys || function (obj) {
+                var keys = [];
+                for (var key in obj) keys.push(key);
+                return keys;
+            };
+
+            var skip = {
+                'DataInputs': true,
+                'DataOutputs': true,
+                'ResponseDocument': true,
+                'RawDataOutput': true,
+            }
+            var keys = objectKeys(params);
+            for (var i = 0; i < keys.length; i++) {
+                var key = keys[i];
+                if (skip.hasOwnProperty(key) && skip[key]) {
+                    continue;
+                }
+                if (params.hasOwnProperty(key)) {
+                    tmp_params[key] = params[key];
+                }
+            }
+            ret = qs.stringify(tmp_params);
+
+            //req_options.path = req_options.path.replace("&DataInputs=sid%3D", "&DataInputs=sid=")
+            if (params.hasOwnProperty('DataInputs')) {
+              //var dataInputs = params.DataInputs;
+		var dataInputs = serializeInputs(params.DataInputs);
+		if(closure.debug){
+		    console.log("dataInputs: "+dataInputs);
+		}
+		ret += '&DataInputs=' + dataInputs;
+            }
+            
+            if (params.hasOwnProperty('DataOutputs')) {
+		var dataOutputs = serializeOutputs(params.DataOutputs);
+		if(closure.debug){
+		    console.log("dataOutputs: "+dataOutputs);
+		}
+		if(dataOutputs!=""){
+		    var displayInputs=true;
+		    for(var i=0;i<params.DataOutputs.length;i++)
+			if(params.DataOutputs[i].type==="raw"){
+			    ret += '&RawDataOutput=' + dataOutputs;
+			    displayInputs=false;
+			    break;
+			}
+		    if(displayInputs)
+			ret += '&ResponseDocument=' + dataOutputs;
+		}
+            }else{
+		if (params.hasOwnProperty('RawDataOutput')) {
+		    ret+="&RawDataOutput="+params['RawDataOutput']+";";
+		}else{
+		    if (params.hasOwnProperty('ResponseDocument')) {
+			var lt=$.type(params['ResponseDocument']);
+			if(lt === "string") {
+			    ret+="&ResponseDocument="+params['ResponseDocument']+";";
+			}else{
+			    var tmp_ret=serializeOutputs(params['ResponseDocument']);
+			    ret+="&ResponseDocument="+tmp;
+			}
+		    }
+		}
+	    }
+            
+            return ret;
+        };
+        
+	/**
+	 * The parseStatusLocation method parse the statusLocation and return an
+	 * object with sid and statusLocation attributes which contains
+	 * respectively: a unique identifier named sid and the statusLocation
+	 * value returned by the WPS server.
+	 * 
+	 * @method parseStatusLocation
+	 * @memberof ZooProcess#
+	 * @param {Object} data The XML response parsed by x2js.xml2json
+	 * @returns {Object} The result is an object with sid and statusLocation
+	 */
+        this.parseStatusLocation = function(data) {
+            var closure = this;
+
+            if (statusLocation = data.ExecuteResponse._statusLocation) {
+		if(closure.debug){
+                    console.log("statusLocation: "+statusLocation);
+		}
+
+		var lsid=0;
+		for(i in closure.statusLocation)
+		    lsid++;
+		
+                return {sid: lsid, statusLocation: statusLocation};
+            }
+        };        
+
+	/**
+	 * The parseJobID method parse the JobID and return an
+	 * object with sid and the JobID attributes which contains
+	 * respectively: a unique identifier named sid and the JobID
+	 * value returned by the WPS server.
+	 * 
+	 * @method parseJobID
+	 * @memberof ZooProcess#
+	 * @param {Object} data The XML response parsed by x2js.xml2json
+	 * @returns {Object} The result is an object with sid and jobID
+	 */
+        this.parseJobID = function(data) {
+            var closure = this;
+
+            if (jobID = data.StatusInfo.JobID) {
+
+		var lsid=0;
+		for(i in closure.statusLocation)
+		    lsid++;
+		
+                return {sid: lsid, jobid: jobID};
+            }
+        }; 
+
+	/**
+	 * The dismiss method run the Dismiss request by calling {@link ZooProcess#request}.
+	 * 
+	 * @method dismiss
+	 * @memberof ZooProcess#
+	 * @param {Object} params 
+	 * @example
+	 * // Log x2js representation of all available services in console
+	 * myZooObject.dismiss({
+	 *     type: 'POST',
+	 *     jobid: "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
+	 *     success: function(data){
+	 *         console.log(data);
+	 *     }
+	 * });
+	 */
+        this.dismiss = function(params) {
+            var closure = this;
+
+            if (!params.hasOwnProperty('type')) {
+                params.type = 'GET';
+            }
+
+            var zoo_request_params = {
+                Identifier: params.identifier,
+                request: 'Dismiss',
+                service: 'WPS',
+		jobid: params.jobid,
+                version: "2.0.0",
+            }
+
+            this.request(zoo_request_params, params.success, params.error, params.type);
+        };
+
+    };
+    
+
+    return ZooProcess;
+
+});
diff --git a/zoo-project/zoo-client/lib/tpl/payload_DescribeProcess.mustache b/zoo-project/zoo-client/lib/tpl/payload_DescribeProcess.mustache
new file mode 100644
index 0000000..d4673e2
--- /dev/null
+++ b/zoo-project/zoo-client/lib/tpl/payload_DescribeProcess.mustache
@@ -0,0 +1,5 @@
+<DescribeProcess xmlns="http://www.opengis.net/wps/1.0.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wps/1.0.0 ../wpsDescribeProcess_request.xsd" service="WPS" version="1.0.0" language="{{language}}">
+{{#identifiers}}
+  <ows:Identifier>{{.}}</ows:Identifier>
+{{/identifiers}}
+</DescribeProcess>
\ No newline at end of file
diff --git a/zoo-project/zoo-client/lib/tpl/payload_DescribeProcess2.mustache b/zoo-project/zoo-client/lib/tpl/payload_DescribeProcess2.mustache
new file mode 100644
index 0000000..fccfe99
--- /dev/null
+++ b/zoo-project/zoo-client/lib/tpl/payload_DescribeProcess2.mustache
@@ -0,0 +1,14 @@
+<wps:DescribeProcess
+	xmlns:ows="http://www.opengis.net/ows/2.0"
+	xmlns:wps="http://www.opengis.net/wps/2.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://www.opengis.net/wps/2.0 ../wps.xsd"
+	
+	service="WPS"
+	version="2.0.0">
+	
+{{#identifiers}}
+  <ows:Identifier>{{.}}</ows:Identifier>
+{{/identifiers}}
+	
+</wps:DescribeProcess>
diff --git a/zoo-project/zoo-client/lib/tpl/payload_Dismiss.mustache b/zoo-project/zoo-client/lib/tpl/payload_Dismiss.mustache
new file mode 100644
index 0000000..ab8dd0a
--- /dev/null
+++ b/zoo-project/zoo-client/lib/tpl/payload_Dismiss.mustache
@@ -0,0 +1,10 @@
+<wps:Dismiss
+	xmlns:wps="http://www.opengis.net/wps/2.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://www.opengis.net/wps/2.0 ../wps.xsd"
+	service="WPS"
+	version="2.0.0">
+{{#jobid}}
+	<wps:JobID>{{.}}</wps:JobID>
+{{/jobid}}
+</wps:Dismiss>
\ No newline at end of file
diff --git a/zoo-project/zoo-client/lib/tpl/payload_Execute.mustache b/zoo-project/zoo-client/lib/tpl/payload_Execute.mustache
new file mode 100644
index 0000000..f234bb4
--- /dev/null
+++ b/zoo-project/zoo-client/lib/tpl/payload_Execute.mustache
@@ -0,0 +1,84 @@
+<wps:Execute service="WPS" version="1.0.0" xmlns:wps="http://www.opengis.net/wps/1.0.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wps/1.0.0
+../wpsExecute_request.xsd" language="{{language}}">
+  <!-- template-version: 0.21 -->
+	<ows:Identifier>{{Identifier}}</ows:Identifier>
+	<wps:DataInputs>
+{{#DataInputs}}
+{{#is_literal}}
+		<wps:Input>
+			<ows:Identifier>{{identifier}}</ows:Identifier>
+			<wps:Data>
+				<wps:LiteralData{{#dataType}} dataType="{{dataType}}"{{/dataType}}>{{value}}</wps:LiteralData>
+			</wps:Data>
+		</wps:Input>
+{{/is_literal}}
+{{#is_bbox}}
+		<wps:Input>
+			<ows:Identifier>{{identifier}}</ows:Identifier>
+			<wps:Data>
+				<wps:BoundingBoxData ows:crs="{{crs}}" ows:dimensions="{{dimension}}">
+            <ows:LowerCorner>{{lowerCorner}}</ows:LowerCorner>
+            <ows:UpperCorner>{{upperCorner}}</ows:UpperCorner>
+         </wps:BoundingBoxData>
+			</wps:Data>
+		</wps:Input>
+{{/is_bbox}}
+{{#is_complex}}
+{{#is_reference}}
+{{#is_get}}
+		<wps:Input>
+			<ows:Identifier>{{identifier}}</ows:Identifier>
+			<wps:Reference xlink:href="{{href}}"{{#schema}} schema="{{shema}}"{{/schema}}{{#mimeType}} mimeType="{{mimeType}}"{{/mimeType}}{{#encoding}} encoding="{{encoding}}"{{/encoding}}/>
+		</wps:Input>
+{{/is_get}}
+{{#is_post}}
+		<wps:Input>
+			<ows:Identifier>{{identifier}}</ows:Identifier>
+			<wps:Reference xlink:href="{{href}}" method="{{method}}">
+{{#headers}}
+			  <wps:Header key="{{key}}" value="{{value}}" />
+{{/headers}}
+			  <wps:Body>{{{value}}}</wps:Body>
+			</wps:Reference>
+		</wps:Input>
+{{/is_post}}
+{{/is_reference}}
+{{^is_reference}}
+		<wps:Input>
+      <ows:Identifier>{{identifier}}</ows:Identifier>
+      <wps:Data>
+        <wps:ComplexData{{#schema}} schema="{{shema}}"{{/schema}}{{#mimeType}} mimeType="{{mimeType}}"{{/mimeType}}{{#encoding}} encoding="{{encoding}}"{{/encoding}}>{{#is_XML}}
+	 {{{value}}}{{/is_XML}}{{^is_XML}}<![CDATA[{{{value}}}]]>{{/is_XML}}
+        </wps:ComplexData>
+      </wps:Data>
+    </wps:Input>
+{{/is_reference}}
+{{/is_complex}}
+{{/DataInputs}}
+	</wps:DataInputs>	
+	<wps:ResponseForm>
+{{#RawDataOutput}}
+{{#DataOutputs}}
+    <wps:RawDataOutput mimeType="{{mimeType}}">
+      <ows:Identifier>{{identifier}}</ows:Identifier>
+    </wps:RawDataOutput>
+{{/DataOutputs}}
+{{/RawDataOutput}}
+{{^RawDataOutput}}
+    <wps:ResponseDocument{{#storeExecuteResponse}} storeExecuteResponse="{{storeExecuteResponse}}"{{/storeExecuteResponse}}{{#lineage}} lineage="{{lineage}}"{{/lineage}}{{#status}} status="{{status}}"{{/status}}>
+{{#DataOutputs}}
+{{#is_literal}}
+      <wps:Output{{#dataType}} dataType="{{dataType}}"{{/dataType}}{{#uom}} uom="{{uom}}"{{/uom}}>
+        <ows:Identifier>{{identifier}}</ows:Identifier>
+      </wps:Output>
+{{/is_literal}}
+{{^is_literal}}
+      <wps:Output{{#asReference}} asReference="{{asReference}}"{{/asReference}}{{#schema}} schema="{{schema}}"{{/schema}}{{#mimeType}} mimeType="{{mimeType}}"{{/mimeType}}{{#encoding}} encoding="{{encoding}}"{{/encoding}}>
+        <ows:Identifier>{{identifier}}</ows:Identifier>
+      </wps:Output>
+{{/is_literal}}
+{{/DataOutputs}}
+    </wps:ResponseDocument>
+{{/RawDataOutput}}
+  </wps:ResponseForm>	
+</wps:Execute>
\ No newline at end of file
diff --git a/zoo-project/zoo-client/lib/tpl/payload_Execute2.mustache b/zoo-project/zoo-client/lib/tpl/payload_Execute2.mustache
new file mode 100644
index 0000000..dd6cee0
--- /dev/null
+++ b/zoo-project/zoo-client/lib/tpl/payload_Execute2.mustache
@@ -0,0 +1,62 @@
+<wps:Execute
+	xmlns:wps="http://www.opengis.net/wps/2.0"
+	xmlns:ows="http://www.opengis.net/ows/2.0"
+	xmlns:xlink="http://www.w3.org/1999/xlink"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://www.opengis.net/wps/2.0 ../wps.xsd"
+	
+	service="WPS"
+	version="2.0.0"
+	response="{{#RawDataOutput}}{{/RawDataOutput}}{{^RawDataOutput}}document{{/RawDataOutput}}"
+	mode="{{#mode}}{{mode}}{{/mode}}{{^mode}}sync{{/mode}}">
+
+	<ows:Identifier>{{Identifier}}</ows:Identifier>
+{{#DataInputs}}
+{{#is_literal}}
+		<wps:Input id="{{identifier}}">
+			<wps:Data>{{value}}</wps:Data>
+		</wps:Input>
+{{/is_literal}}
+{{#is_bbox}}
+		<wps:Input id="{{identifier}}">
+			<wps:Data>
+				<wps:BoundingBoxData ows:crs="{{crs}}" ows:dimensions="{{dimension}}">
+            <ows:LowerCorner>{{lowerCorner}}</ows:LowerCorner>
+            <ows:UpperCorner>{{upperCorner}}</ows:UpperCorner>
+         </wps:BoundingBoxData>
+			</wps:Data>
+		</wps:Input>
+{{/is_bbox}}
+{{#is_complex}}
+{{#is_reference}}
+{{#is_get}}
+		<wps:Input id="{{identifier}}">
+			<wps:Reference xlink:href="{{href}}"/>
+		</wps:Input>
+{{/is_get}}
+{{#is_post}}
+		<wps:Input id="{{identifier}}">
+			<wps:Reference xlink:href="{{href}}" method="{{method}}">
+{{#mimeType}}
+			  <wps:Header key="Content-type" value="{{mimeType}}" />
+{{/mimeType}}
+			  <wps:Body>{{{complexPayload}}}</wps:Body>
+			</wps:Reference>
+		</wps:Input>
+{{/is_post}}
+{{/is_reference}}
+{{^is_reference}}
+		<wps:Input id="{{identifier}}">
+      <wps:Data>
+        <wps:ComplexData{{#schema}} schema="{{shema}}"{{/schema}}{{#mimeType}} mimeType="{{mimeType}}"{{/mimeType}}{{#encoding}} encoding="{{encoding}}"{{/encoding}}>
+        	{{{complexPayload}}}
+        </wps:ComplexData>
+      </wps:Data>
+    </wps:Input>
+{{/is_reference}}
+{{/is_complex}}
+{{/DataInputs}}
+{{#DataOutputs}}
+      <wps:Output id="{{identifier}}" transmission="{{#asReference}}{{asReference}}{{/asReference}}{{^asReference}}value{{/asReference}}"{{#schema}} schema="{{schema}}"{{/schema}}{{#mimeType}} mimeType="{{mimeType}}"{{/mimeType}}{{#encoding}} encoding="{{encoding}}"{{/encoding}}{{#uom}} uom="{{uom}}"{{/uom}} />
+{{/DataOutputs}}
+</wps:Execute>
\ No newline at end of file
diff --git a/zoo-project/zoo-client/lib/tpl/payload_GetCapabilities.mustache b/zoo-project/zoo-client/lib/tpl/payload_GetCapabilities.mustache
new file mode 100644
index 0000000..fbcb225
--- /dev/null
+++ b/zoo-project/zoo-client/lib/tpl/payload_GetCapabilities.mustache
@@ -0,0 +1,5 @@
+<wps:GetCapabilities xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:wps="http://www.opengis.net/wps/1.0.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/wps/1.0.0 ../wpsGetCapabilities_request.xsd" language="{{language}}" service="WPS">
+    <wps:AcceptVersions>
+        <ows:Version>1.0.0</ows:Version>
+    </wps:AcceptVersions>
+</wps:GetCapabilities>
\ No newline at end of file
diff --git a/zoo-project/zoo-client/lib/tpl/payload_GetCapabilities2.mustache b/zoo-project/zoo-client/lib/tpl/payload_GetCapabilities2.mustache
new file mode 100644
index 0000000..a48c058
--- /dev/null
+++ b/zoo-project/zoo-client/lib/tpl/payload_GetCapabilities2.mustache
@@ -0,0 +1,7 @@
+<wps:GetCapabilities
+	xmlns:wps="http://www.opengis.net/wps/2.0"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://www.opengis.net/wps/2.0 ../wps.xsd"
+	service="WPS">
+	
+</wps:GetCapabilities>
\ No newline at end of file
diff --git a/zoo-project/zoo-kernel/Doxyfile b/zoo-project/zoo-kernel/Doxyfile
new file mode 100644
index 0000000..39d433f
--- /dev/null
+++ b/zoo-project/zoo-kernel/Doxyfile
@@ -0,0 +1,2303 @@
+# Doxyfile 1.8.6
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME           = "ZOO-Project"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER         =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF          =
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
+# the documentation. The maximum height of the logo should not exceed 55 pixels
+# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
+# to the output directory.
+
+PROJECT_LOGO           =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       =
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF       =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES        = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH        =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH    =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF      = YES
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
+# new page for each member. If set to NO, the documentation of a member will be
+# part of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE               = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
+
+ALIASES                =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST              =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C  = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make
+# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
+# (default is Fortran), use: inc=Fortran f=C.
+#
+# Note For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING      = y=C 
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT       = YES
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by by putting a % sign in front of the word
+# or globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT       = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING            = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS  = YES
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE      = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL            = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC         = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO these classes will be included in the various overviews. This option has
+# no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC  = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES   = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING  = NO
+
+# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
+# todo list. This list is created by putting \todo commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
+# test list. This list is created by putting \test commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS       =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES the list
+# will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES        = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER    =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE            =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. Do not use file names with spaces, bibtex cannot handle them. See
+# also \cite for info how to create references.
+
+CITE_BIB_FILES         =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS               = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO doxygen will only warn about wrong or incomplete parameter
+# documentation, but not about the absence of documentation.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE           =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces.
+# Note: If this tag is empty the current directory is searched.
+
+INPUT                  =
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank the
+# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
+# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
+# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
+# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
+# *.qsf, *.as and *.js.
+
+FILE_PATTERNS          = *.dox *.y *.c *.cxx *.h 
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE                =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS        =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH           =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS       =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH             =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+
+INPUT_FILTER           =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS        =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER ) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES    = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION    = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS        = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX     = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX          =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER            =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER            =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET        =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user-
+# defined cascading style sheet that is included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefor more robust against future updates.
+# Doxygen will copy the style sheet file to the output directory. For an example
+# see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET  =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES       =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the stylesheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE    = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT    = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA  = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP         = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET        = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME  = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP      = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE               =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler ( hhc.exe). If non-empty
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION           =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated (
+# YES) or that it should be included in the master .chm file ( NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI           = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING     =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated (
+# YES) or a normal table of contents ( NO) in the .chm file.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE               =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE          = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME   =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS  =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS  =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION           =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP   = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID         = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX          = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW      = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH         = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW    = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE       = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT    = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using prerendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX            = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT         = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS     =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE       =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE           = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavours of web server based searching depending on the
+# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for
+# searching and an index file used by the script. When EXTERNAL_SEARCH is
+# enabled the indexing and searching needs to be provided by external tools. See
+# the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH    = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH        = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL       =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE        = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID     =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS  =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX         = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE             = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. To get the times font for
+# instance you can specify
+# EXTRA_PACKAGES=times
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES         =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber. Doxygen will
+# replace them by respectively the title of the page, the current date and time,
+# only the current date, the version number of doxygen, the project name (see
+# PROJECT_NAME), or the project number (see PROJECT_NUMBER).
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER           =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER           =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES      =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS         = YES
+
+# If the LATEX_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE        = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES     = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE      = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE        = plain
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE    =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE    =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify a XML schema, which can be used by a
+# validating XML parser to check the syntax of the XML files.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_SCHEMA             =
+
+# The XML_DTD tag can be used to specify a XML DTD, which can be used by a
+# validating XML parser to check the syntax of the XML files.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_DTD                =
+
+# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK       = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT         = docbook
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
+# Definitions (see http://autogen.sf.net) file that captures the structure of
+# the code including all documentation. Note that this feature is still
+# experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
+# in the source code. If set to NO only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES the includes files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH           =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS  =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED             =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED      =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all refrences to function-like macros that are alone on a line, have an
+# all uppercase name, and do not end with a semicolon. Such function macros are
+# typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have an unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES               =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE       =
+
+# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
+# class index. If set to NO only the inherited external classes will be listed.
+# The default value is: NO.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
+# the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS        = YES
+
+# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES         = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS         = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH            =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH               =
+
+# If set to YES, the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: NO.
+
+HAVE_DOT               = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS        = 0
+
+# When you want a differently looking font n the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME           = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH           =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK               = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS   = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH          = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH           = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot.
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, jpg, gif and svg.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT       = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG        = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH               =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS           =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS           =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS           =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS      = YES
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP            = YES
diff --git a/zoo-project/zoo-kernel/LICENSE b/zoo-project/zoo-kernel/LICENSE
new file mode 100644
index 0000000..3c27d92
--- /dev/null
+++ b/zoo-project/zoo-kernel/LICENSE
@@ -0,0 +1,21 @@
+ZOO-Kernel License
+
+Copyright (c) 2009-2013 GeoLabs SARL
+
+Permission is hereby granted, free of charge, to any person obtaining a copy 
+of this software and associated documentation files (the “Software”), to deal
+in the Software without restriction, including without limitation the rights 
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
+copies of the Software, and to permit persons to whom the Software is 
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies of this Software or works derived from this Software.
+
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/zoo-project/zoo-kernel/Makefile.in b/zoo-project/zoo-kernel/Makefile.in
new file mode 100644
index 0000000..a85cc82
--- /dev/null
+++ b/zoo-project/zoo-kernel/Makefile.in
@@ -0,0 +1,117 @@
+include ZOOMakefile.opts
+
+all: version.h zoo_loader.cgi ${YAML_FILE1}
+
+version.h:
+	echo "#define ZOO_VERSION \"`svnversion`\"" > version.h
+
+service.o: service.c service.h
+	gcc ${YAML_CFLAGS} ${XML2CFLAGS} ${CFLAGS} -fPIC -c service.c
+
+main_conf_read.tab.c: main_conf_read.y service.h
+	bison -p cr -d main_conf_read.y
+
+main_conf_read.tab.o: main_conf_read.tab.c service.h
+	g++ ${CFLAGS} -c main_conf_read.tab.c
+
+lex.cr.c: main_conf_read.y main_conf_read.l main_conf_read.tab.c service.h
+	flex -P cr --header-file main_conf_read.l
+
+lex.cr.o: lex.cr.c service.h
+	g++ ${CFLAGS} -c lex.cr.c
+
+service_conf.tab.c: service_conf.y service.h
+	bison -p sr -d service_conf.y
+
+service_conf.tab.o: service_conf.tab.c service.h
+	g++ ${CFLAGS} -c service_conf.tab.c
+
+lex.sr.c: service_conf.y service_conf.l service_conf.tab.c service.h
+	flex -P sr --header-file service_conf.l
+
+lex.sr.o: lex.sr.c service.h
+	g++ ${CFLAGS} -c lex.sr.c
+
+ulinet.o: ulinet.c
+	gcc -fPIC ${XML2CFLAGS} ${CFLAGS} ${JSCFLAGS} ${JS_ENABLED} -c ulinet.c
+
+request_parser.o: request_parser.c request_parser.h
+	g++ -fPIC ${XML2CFLAGS} ${CFLAGS} ${JSCFLAGS} ${JS_ENABLED} -c request_parser.c
+
+sqlapi.o: sqlapi.c sqlapi.h
+	g++ -fPIC ${GDAL_CFLAGS} ${XML2CFLAGS} ${CFLAGS} ${JSCFLAGS} ${JS_ENABLED} -c sqlapi.c
+
+caching.o: caching.c
+	g++ -fPIC ${XML2CFLAGS} ${CFLAGS} ${JSCFLAGS} ${JS_ENABLED} -c caching.c
+
+response_print.o: response_print.c response_print.h
+	g++ -fPIC ${GDAL_CFLAGS} ${XML2CFLAGS} ${CFLAGS} ${JSCFLAGS} ${JS_ENABLED} -c response_print.c
+
+server_internal.o: server_internal.c server_internal.h service.h mimetypes.h
+	g++ ${GDAL_CFLAGS} ${JS_ENABLED} ${JSCFLAGS} ${XML2CFLAGS} ${CFLAGS} -fPIC -c server_internal.c
+
+service_internal.o: service_internal.c service_internal.h service.h
+	gcc ${GDAL_CFLAGS} ${JS_ENABLED} ${JSCFLAGS} ${XML2CFLAGS} ${CFLAGS} -fPIC -c service_internal.c
+
+service_yaml.o: service_yaml.c service.h
+	gcc ${YAML_CFLAGS} ${XML2CFLAGS} ${CFLAGS} -fPIC -c service_yaml.c
+
+service_internal_ms.o: service_internal_ms.c
+	gcc ${JS_ENABLED} ${JSCFLAGS} ${XML2CFLAGS} ${CFLAGS} -fPIC -c service_internal_ms.c
+
+service_internal_python.o: service_internal_python.c service.h
+	g++ ${XML2CFLAGS} ${PYTHONCFLAGS} ${CFLAGS} -c service_internal_python.c
+
+service_internal_otb.o: service_internal_otb.c service_internal_otb.h service.h
+	g++ ${XML2CFLAGS} ${OTBCFLAGS} ${CFLAGS} -c service_internal_otb.c
+
+service_internal_saga.o: service_internal_saga.c service_internal_saga.h service.h
+	g++ ${XML2CFLAGS} ${SAGA_CFLAGS} ${CFLAGS} -c service_internal_saga.c
+
+otbZooWatcher.o: otbZooWatcher.cxx otbZooWatcher.h  service.h
+	g++ ${OTBCFLAGS} ${CFLAGS} -c otbZooWatcher.cxx
+
+service_internal_php.o: service_internal_php.c service.h
+	g++ -c ${XML2CFLAGS} ${PHPCFLAGS} ${CFLAGS}  ${PHP_ENABLED} service_internal_php.c
+
+service_internal_perl.o: service_internal_perl.c service.h
+	gcc -c ${XML2CFLAGS} ${PERLCFLAGS} ${CFLAGS}  ${PERL_ENABLED} service_internal_perl.c
+
+service_internal_java.o: service_internal_java.c service.h
+	gcc -c ${XML2CFLAGS} ${JAVACFLAGS} ${CFLAGS} ${JAVA_ENABLED} service_internal_java.c
+
+service_internal_js.o: service_internal_js.c service_internal_js.h
+	gcc -fPIC ${XML2CFLAGS} ${JSCFLAGS} ${CFLAGS} ${JS_ENABLED} -c service_internal_js.c
+
+service_internal_ruby.o: service_internal_ruby.c service_internal_ruby.h
+	g++ ${XML2CFLAGS} ${RUBYCFLAGS} ${CFLAGS} ${JSCFLAGS} ${JS_ENABLED} -c service_internal_ruby.c
+
+service_loader.o: service_loader.c service.h
+	g++ -c ${XML2CFLAGS} ${PYTHONCFLAGS} ${CFLAGS} service_loader.c
+
+zoo_service_loader.o: zoo_service_loader.c service.h
+	g++ -g -O2 ${XML2CFLAGS} ${CFLAGS} ${SAGA_CFLAGS} ${OTBCFLAGS} ${PYTHONCFLAGS} ${JAVACFLAGS} ${JSCFLAGS} ${PERLCFLAGS} ${PHPCFLAGS} ${SAGA_ENABLED} ${OTB_ENABLED} ${PYTHON_ENABLED} ${JS_ENABLED} ${PHP_ENABLED} ${PERL_ENABLED} ${JAVA_ENABLED} -c zoo_service_loader.c  -fno-common -DPIC -o zoo_service_loader.o
+
+libzoo_service.${EXT}: version.h service_internal.o service.o sqlapi.o
+	gcc -shared  ${GDAL_CFLAGS} ${DEFAULT_OPTS} -fpic -o libzoo_service.${EXT} ${CFLAGS}  service_internal.o service.o sqlapi.o -lfcgi ${GDAL_LIBS}
+
+zoo_loader.cgi: version.h libzoo_service.${EXT} zoo_loader.c zoo_service_loader.o  ulinet.o service.h lex.sr.o service_conf.tab.o service_conf.y ulinet.o main_conf_read.tab.o lex.cr.o request_parser.o response_print.o server_internal.o caching.o ${MS_FILE} ${PYTHON_FILE} ${PHP_FILE} ${JAVA_FILE} ${JS_FILE} ${PERL_FILE} ${RUBY_FILE} ${YAML_FILE} ${OTB_FILE} ${SAGA_FILE}
+	g++ -g -O2 ${JSCFLAGS} ${PHPCFLAGS}  ${PERLCFLAGS} ${RUBYCFLAGS}  ${JAVACFLAGS} ${XML2CFLAGS} ${PYTHONCFLAGS} ${CFLAGS} -c zoo_loader.c  -fno-common -DPIC -o zoo_loader.o
+	g++  ${JSCFLAGS} ${SAGA_CFLAGS} ${OTBCFLAGS} ${GDAL_CFLAGS} ${XML2CFLAGS} ${PHPCFLAGS} ${PERLCFLAGS} ${JAVACFLAGS} ${PYTHONCFLAGS} ${CFLAGS} zoo_loader.o zoo_service_loader.o ${MS_FILE} ${PYTHON_FILE}  ${PERL_FILE} ${PHP_FILE}  ${JS_FILE} ${JAVA_FILE} ${YAML_FILE} ${OTB_FILE} ${SAGA_FILE} response_print.o server_internal.o caching.o request_parser.o ulinet.o lex.cr.o lex.sr.o service_conf.tab.o main_conf_read.tab.o -o zoo_loader.cgi -L. ${LDFLAGS}
+
+zcfg2yaml: zcfg2yaml.c service.h lex.sr.o service_conf.tab.o service_conf.y main_conf_read.tab.o lex.cr.o response_print.o server_internal.o service_internal.o ${MS_FILE} ${YAML_FILE}
+	g++ -g -O2 ${JSCFLAGS} ${RUBYCFLAGS} ${XML2CFLAGS} ${CFLAGS} -c zcfg2yaml.c  -fno-common -DPIC -o zcfg2yaml.o
+	g++  ${XML2CFLAGS} ${CFLAGS} zcfg2yaml.o server_internal.o service_internal.o ${MS_FILE} response_print.o lex.cr.o lex.sr.o service_conf.tab.o main_conf_read.tab.o  ${YAML_FILE} -o zcfg2yaml -L. ${LDFLAGS}
+
+install:
+	install -d ${CGI_DIR}
+	install zoo_loader.cgi ${CGI_DIR}/
+	install libzoo_service.${EXT} ${DESTDIR}${INST_LIB}/${LIBZOO_SERVICE}
+	(cd ${DESTDIR}${INST_LIB} ; \
+	 if [ -e "libzoo_service.${EXT}" ]; then rm  libzoo_service.${EXT}; fi ; \
+	 ln -s ${LIBZOO_SERVICE} libzoo_service.${EXT})
+	install -d ${DESTDIR}${INST_INCLUDE}/zoo
+	install sqlapi.h service.h service_internal.h ${DESTDIR}${INST_INCLUDE}/zoo
+
+clean:
+	rm -f version.h *.o *.zo *.eo *.tab.c *.tab.h *.sr.c* service_loader lex.* *.lreg *.sibling service_loader.dSYM *${EXT}
diff --git a/zoo-project/zoo-kernel/README b/zoo-project/zoo-kernel/README
new file mode 100644
index 0000000..bda4e44
--- /dev/null
+++ b/zoo-project/zoo-kernel/README
@@ -0,0 +1,3 @@
+For information on how to compile and install the ZOO Kernel, please refer to:
+
+http://zoo-project.org/docs/kernel/installation.html
diff --git a/zoo-project/zoo-kernel/ZOOMakefile.opts.in b/zoo-project/zoo-kernel/ZOOMakefile.opts.in
new file mode 100644
index 0000000..260436b
--- /dev/null
+++ b/zoo-project/zoo-kernel/ZOOMakefile.opts.in
@@ -0,0 +1,97 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+PREFIX=@prefix@
+INST_LIB=@libdir@
+INST_INCLUDE=@includedir@
+VERSION=1.5
+REVISION=0
+EXT=so
+DEFAULT_OPTS=-Wl,-soname,libzoo_service.so.${VERSION}
+OS:=$(shell uname -s)
+ifeq ($(OS),Darwin)
+	MACOS_LD_FLAGS=-lintl
+	MACOS_LD_NET_FLAGS=-framework SystemConfiguration -framework CoreFoundation
+	MACOS_CFLAGS=-arch $(shell uname -m)
+	EXT=dylib
+	DEFAULT_OPTS=-Wl,-compatibility_version,${VERSION},-current_version,${VERSION},-install_name,${DESTDIR}${INST_LIB}/libzoo_service.${VERSION}.${REVISION}.dylib
+	LIBZOO_SERVICE=libzoo_service.${VERSION}.${REVISION}.${EXT}
+else
+	LIBZOO_SERVICE=libzoo_service.${EXT}.${VERSION}
+endif
+
+CGI_DIR=@CGI_DIR@
+
+YAML_CFLAGS=@YAML_CPPFLAGS@
+YAML_LDFLAGS=@YAML_LDFLAGS@
+YAML_FILE=@YAML_FILE@
+YAML_FILE1=@YAML_FILE1@
+
+GDAL_CFLAGS=@GDAL_CFLAGS@
+GDAL_LIBS=@GDAL_LIBS@
+
+XML2CFLAGS=@XML2_CPPFLAGS@
+XML2LDFLAGS=@XML2_LDFLAGS@
+
+XSLT_CFLAGS=@XSLT_CPPFLAGS@
+XSLT_LDFLAGS=@XSLT_LDFLAGS@
+
+GEOS_CFLAGS=@GEOS_CPPFLAGS@
+GEOS_LDFLAGS=@GEOS_LDFLAGS@
+
+CGAL_CFLAGS=@CGAL_CPPFLAGS@
+CGAL_LDFLAGS=@CGAL_LDFLAGS@
+
+PYTHONCFLAGS=@PYTHON_CPPFLAGS@
+PYTHONLDFLAGS=@PYTHON_LDFLAGS@
+PYTHON_ENABLED=@PYTHON_ENABLED@
+PYTHON_FILE=@PYTHON_FILE@
+
+RUBYCFLAGS=@RUBY_CPPFLAGS@
+RUBYLDFLAGS=@RUBY_LDFLAGS@
+RUBY_ENABLED=@RUBY_ENABLED@
+RUBY_FILE=@RUBY_FILE@
+
+JS_ENABLED=@JS_ENABLED@
+JSCFLAGS=@JS_CPPFLAGS@
+JSLDFLAGS=@JS_LDFLAGS@
+JS_FILE=@JS_FILE@
+ifeq ($(JS_ENABLED),-DUSE_JS)
+     JS_LDFLAGS=${ZRPATH}/zoo-kernel/ulinet.o ${ZRPATH}/zoo-kernel/service_internal_js.o -lcurl 
+endif
+
+MS_CFLAGS=@MS_CFLAGS@
+MS_LDFLAGS=@MS_LIBS@
+MS_FILE=@MS_FILE@
+
+ZOO_CFLAGS=-I${ZRPATH}/../thirds/cgic206/ -I${ZRPATH}/zoo-kernel/
+ZOO_LDFLAGS=-lcrypto -luuid
+
+JAVACFLAGS=@JAVA_CPPFLAGS@
+JAVALDFLAGS=@JAVA_LDFLAGS@
+JAVA_ENABLED=@JAVA_ENABLED@
+JAVA_FILE=@JAVA_FILE@
+
+PHPCFLAGS=@PHP_CPPFLAGS@
+PHPLDFLAGS=@PHP_LDFLAGS@
+PHP_ENABLED=@PHP_ENABLED@
+PHP_FILE=@PHP_FILE@
+
+
+PERLCFLAGS=@PERL_CPPFLAGS@
+PERLLDFLAGS=@PERL_LDFLAGS@
+PERL_ENABLED=@PERL_ENABLED@
+PERL_FILE=@PERL_FILE@
+
+OTBCFLAGS=@OTB_CPPFLAGS@
+OTBLDFLAGS=@OTB_LDFLAGS@
+OTB_ENABLED=@OTB_ENABLED@
+OTB_FILE=@OTB_FILE@
+
+SAGA_CFLAGS=@SAGA_CPPFLAGS@
+SAGA_LDFLAGS=@SAGA_LDFLAGS@
+SAGA_ENABLED=@SAGA_ENABLED@
+SAGA_FILE=@SAGA_FILE@
+
+CFLAGS=@RELY_ON_DB@ @DEB_DEF@ -fpic ${YAML_CFLAGS} ${MACOS_CFLAGS} ${MS_CFLAGS} -I../../thirds/cgic206 -I. -DLINUX_FREE_ISSUE #-DDEBUG #-DDEBUG_SERVICE_CONF
+LDFLAGS=-lzoo_service @DEFAULT_LIBS@ -L../../thirds/cgic206 -lcgic ${GDAL_LIBS} ${XML2LDFLAGS} ${PYTHONLDFLAGS} ${PERLLDFLAGS}  ${PHPLDFLAGS} ${JAVALDFLAGS} ${JSLDFLAGS} -lfcgi -lcrypto -luuid ${MS_LDFLAGS} ${MACOS_LD_FLAGS} ${MACOS_LD_NET_FLAGS} ${YAML_LDFLAGS} ${OTBLDFLAGS} ${SAGA_LDFLAGS}
+
diff --git a/zoo-project/zoo-kernel/autom4te.cache/output.0 b/zoo-project/zoo-kernel/autom4te.cache/output.0
new file mode 100644
index 0000000..fdc2f45
--- /dev/null
+++ b/zoo-project/zoo-kernel/autom4te.cache/output.0
@@ -0,0 +1,8345 @@
+@%:@! /bin/sh
+@%:@ Guess values for system-dependent variables and create Makefiles.
+@%:@ Generated by GNU Autoconf 2.69 for ZOO Kernel 1.5.0.
+@%:@
+@%:@ Report bugs to <bugs at zoo-project.org>.
+@%:@ 
+@%:@ 
+@%:@ Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+@%:@ 
+@%:@ 
+@%:@ This configure script is free software; the Free Software Foundation
+@%:@ gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in @%:@(
+  *posix*) :
+    set -o posix ;; @%:@(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in @%:@(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in @%:@((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+  # into an infinite loop, continuously re-executing ourselves.
+  if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+    _as_can_reexec=no; export _as_can_reexec;
+    # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in @%:@ ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+  fi
+  # We don't want this to propagate to other subprocesses.
+          { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+  as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in @%:@(
+  *posix*) :
+    set -o posix ;; @%:@(
+  *) :
+     ;;
+esac
+fi
+"
+  as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+  
+else
+  exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+  as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+  as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+  if (eval "$as_required") 2>/dev/null; then :
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+  
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  as_found=:
+  case $as_dir in @%:@(
+	 /*)
+	   for as_base in sh bash ksh sh5; do
+	     # Try only shells that exist, to save several forks.
+	     as_shell=$as_dir/$as_base
+	     if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+		    { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  CONFIG_SHELL=$as_shell as_have_required=yes
+		   if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  break 2
+fi
+fi
+	   done;;
+       esac
+  as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+	      { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+  CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+      if test "x$CONFIG_SHELL" != x; then :
+  export CONFIG_SHELL
+             # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in @%:@ ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+    if test x$as_have_required = xno; then :
+  $as_echo "$0: This script requires a shell more modern than all"
+  $as_echo "$0: the shells that I found on your system."
+  if test x${ZSH_VERSION+set} = xset ; then
+    $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+    $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+  else
+    $as_echo "$0: Please tell bug-autoconf at gnu.org and
+$0: bugs at zoo-project.org about your system, including any
+$0: error possibly output before this message. Then install
+$0: a modern shell, or manually run the script under such a
+$0: shell if you do have one."
+  fi
+  exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+@%:@ as_fn_unset VAR
+@%:@ ---------------
+@%:@ Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+@%:@ as_fn_set_status STATUS
+@%:@ -----------------------
+@%:@ Set @S|@? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} @%:@ as_fn_set_status
+
+@%:@ as_fn_exit STATUS
+@%:@ -----------------
+@%:@ Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} @%:@ as_fn_exit
+
+@%:@ as_fn_mkdir_p
+@%:@ -------------
+@%:@ Create "@S|@as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} @%:@ as_fn_mkdir_p
+
+@%:@ as_fn_executable_p FILE
+@%:@ -----------------------
+@%:@ Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} @%:@ as_fn_executable_p
+@%:@ as_fn_append VAR VALUE
+@%:@ ----------------------
+@%:@ Append the text in VALUE to the end of the definition contained in VAR. Take
+@%:@ advantage of any shell optimizations that allow amortized linear growth over
+@%:@ repeated appends, instead of the typical quadratic growth present in naive
+@%:@ implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+@%:@ as_fn_arith ARG...
+@%:@ ------------------
+@%:@ Perform arithmetic evaluation on the ARGs, and store the result in the
+@%:@ global @S|@as_val. Take advantage of shells that can avoid forks. The arguments
+@%:@ must be portable across @S|@(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+@%:@ as_fn_error STATUS ERROR [LINENO LOG_FD]
+@%:@ ----------------------------------------
+@%:@ Output "`basename @S|@0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+@%:@ provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+@%:@ script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} @%:@ as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+  as_lineno_1=$LINENO as_lineno_1a=$LINENO
+  as_lineno_2=$LINENO as_lineno_2a=$LINENO
+  eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+  # already done that, so ensure we don't try to do so again and fall
+  # in an infinite loop.  This has already happened in practice.
+  _as_can_reexec=no; export _as_can_reexec
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in @%:@(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIB@&t at OBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='ZOO Kernel'
+PACKAGE_TARNAME='zoo-kernel'
+PACKAGE_VERSION='1.5.0'
+PACKAGE_STRING='ZOO Kernel 1.5.0'
+PACKAGE_BUGREPORT='bugs at zoo-project.org'
+PACKAGE_URL=''
+
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='LTLIBOBJS
+SAGA_ENABLED
+SAGA_FILE
+SAGA_LDFLAGS
+SAGA_CPPFLAGS
+OTB_ENABLED
+OTB_FILE
+OTB_LDFLAGS
+OTB_CPPFLAGS
+PERL_FILE
+PERL_ENABLED
+PERL_LDFLAGS
+PERL_CPPFLAGS
+PERLCONFIG
+RUBY_FILE
+RUBY_ENABLED
+RUBY_LDFLAGS
+RUBY_CPPFLAGS
+JAVA_FILE
+JAVA_ENABLED
+JAVA_LDFLAGS
+JAVA_CPPFLAGS
+PHP_FILE
+PHP_ENABLED
+PHP_LDFLAGS
+PHP_CPPFLAGS
+PHPCONFIG
+JS_FILE
+JS_ENABLED
+JS_LDFLAGS
+JS_CPPFLAGS
+CXXCPP
+PYTHON_FILE
+PYTHON_ENABLED
+PYTHON_LDFLAGS
+PYTHON_CPPFLAGS
+PYTHONCONFIG
+MS_FILE
+MS_LIBS
+MS_CFLAGS
+CGAL_LDFLAGS
+CGAL_CPPFLAGS
+GEOS_LDFLAGS
+GEOS_CPPFLAGS
+GEOSCONFIG
+PROJ_LDFLAGS
+PROJ_CPPFLAGS
+GDAL_LIBS
+GDAL_CFLAGS
+GDAL_CONFIG
+XSLT_LDFLAGS
+XSLT_CPPFLAGS
+XSLTCONFIG
+XML2_LDFLAGS
+XML2_CPPFLAGS
+XML2CONFIG
+FCGI_LDFLAGS
+FCGI_CPPFLAGS
+YAML_FILE1
+YAML_FILE
+YAML_LDFLAGS
+YAML_CPPFLAGS
+RELY_ON_DB
+CGI_DIR
+DEB_DEF
+LIB@&t at OBJS
+ALLOCA
+EGREP
+GREP
+CPP
+DEFAULT_LIBS
+SED
+ac_ct_CXX
+CXXFLAGS
+CXX
+LEXLIB
+LEX_OUTPUT_ROOT
+LEX
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+YFLAGS
+YACC
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+with_cgi_dir
+with_db_backend
+with_yaml
+with_fastcgi
+with_xml2config
+with_xsltconfig
+with_gdal_config
+with_proj
+with_geosconfig
+with_cgal
+with_mapserver
+with_python
+with_pyvers
+with_js
+with_php
+with_java
+with_ruby
+with_rvers
+with_perl
+with_itk
+with_itk_version
+with_otb
+with_wx_config
+with_saga
+'
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+YACC
+YFLAGS
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CXX
+CXXFLAGS
+CCC
+CPP
+CXXCPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *=)   ac_optarg= ;;
+  *)    ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    case $ac_envvar in #(
+      '' | [0-9]* | *[!_$as_cr_alnum]* )
+      as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+    esac
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+  case $enable_option_checking in
+    no) ;;
+    fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+  esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
+		datadir sysconfdir sharedstatedir localstatedir includedir \
+		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+		libdir localedir mandir
+do
+  eval ac_val=\$$ac_var
+  # Remove trailing slashes.
+  case $ac_val in
+    */ )
+      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+      eval $ac_var=\$ac_val;;
+  esac
+  # Be sure to have absolute directory names.
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_myself" : 'X\(//\)[^/]' \| \
+	 X"$as_myself" : 'X\(//\)$' \| \
+	 X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+	cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+	pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures ZOO Kernel 1.5.0 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking ...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          @<:@@S|@ac_default_prefix@:>@
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          @<:@PREFIX@:>@
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR            user executables [EPREFIX/bin]
+  --sbindir=DIR           system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR        program executables [EPREFIX/libexec]
+  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --libdir=DIR            object code libraries [EPREFIX/lib]
+  --includedir=DIR        C header files [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
+  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR           info documentation [DATAROOTDIR/info]
+  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR            man documentation [DATAROOTDIR/man]
+  --docdir=DIR            documentation root @<:@DATAROOTDIR/doc/zoo-kernel@:>@
+  --htmldir=DIR           html documentation [DOCDIR]
+  --dvidir=DIR            dvi documentation [DOCDIR]
+  --pdfdir=DIR            pdf documentation [DOCDIR]
+  --psdir=DIR             ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of ZOO Kernel 1.5.0:";;
+   esac
+  cat <<\_ACEOF
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-cgi-dir=PATH     Specifies an alternative cgi directory path (
+                          default: /usr/lib/cgi-bin)
+  --with-db-backend       Relies on a database for storing status messages and
+                          response files
+  --with-yaml=PATH        Specifies an alternative location for the yaml
+                          library
+  --with-fastcgi=PATH     Specifies an alternative location for the fastcgi
+                          library
+  --with-xml2config=FILE  Specifies an alternative xml2-config file
+  --with-xsltconfig=FILE  Specifies an alternative xslt-config file
+  --with-gdal-config=FILE Specifies an alternative gdal-config file
+  --with-proj=PATH        Specifies an alternative location for PROJ4 setup
+  --with-geosconfig=FILE  Specifies an alternative geos-config file
+  --with-cgal=PATH        Specifies an alternative location for CGAL setup
+  --with-mapserver=PATH   Specifies the path for MapServer compiled source
+                          tree
+  --with-python=PATH      To enable python support or Specifies an alternative
+                          directory for python installation, disabled by
+                          default
+  --with-pyvers=NUM       To use a specific python version
+  --with-js=PATH          Specifies --with-js=path-to-js to enable js support,
+                          specify --with-js on linux debian like, js support
+                          is disabled by default
+  --with-php=PATH         To enable php support or specify an alternative
+                          directory for php installation, disabled by default
+  --with-java=PATH        To enable java support, specify a JDK_HOME, disabled
+                          by default
+  --with-ruby=PATH        To enable ruby support or specify an alternative
+                          directory for ruby installation, disabled by default
+  --with-rvers=NUM        To use a specific ruby version
+  --with-perl=PATH        To enable perl support or specify an alternative
+                          directory for perl installation, disabled by default
+  --with-itk=PATH         Specifies an alternative location for the itk
+                          library
+  --with-itk-version=VERSION 
+                          Specifies an alternative version for the itk library
+  --with-otb=PATH         Specifies an alternative location for the otb
+                          library
+  --with-wx-config=PATH   Specifies an alternative path for the wx-config tool
+  --with-saga=PATH        Specifies an alternative location for the SAGA-GIS
+                          library
+
+Some influential environment variables:
+  YACC        The `Yet Another Compiler Compiler' implementation to use.
+              Defaults to the first program found out of: `bison -y', `byacc',
+              `yacc'.
+  YFLAGS      The list of arguments that will be passed by default to @S|@YACC.
+              This script will default YFLAGS to the empty string to avoid a
+              default value of `-d' given by some make applications.
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  LIBS        libraries to pass to the linker, e.g. -l<library>
+  CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+              you have headers in a nonstandard directory <include dir>
+  CXX         C++ compiler command
+  CXXFLAGS    C++ compiler flags
+  CPP         C preprocessor
+  CXXCPP      C++ preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to <bugs at zoo-project.org>.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" ||
+      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+      continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+ZOO Kernel configure 1.5.0
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+@%:@ ac_fn_c_try_compile LINENO
+@%:@ --------------------------
+@%:@ Try to compile conftest. at S|@ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} @%:@ ac_fn_c_try_compile
+
+@%:@ ac_fn_c_try_link LINENO
+@%:@ -----------------------
+@%:@ Try to link conftest. at S|@ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext conftest$ac_exeext
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 test -x conftest$ac_exeext
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+  # interfere with the next link command; also delete a directory that is
+  # left behind by Apple's compiler.  We do this before executing the actions.
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} @%:@ ac_fn_c_try_link
+
+@%:@ ac_fn_cxx_try_compile LINENO
+@%:@ ----------------------------
+@%:@ Try to compile conftest. at S|@ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} @%:@ ac_fn_cxx_try_compile
+
+@%:@ ac_fn_c_check_type LINENO TYPE VAR INCLUDES
+@%:@ -------------------------------------------
+@%:@ Tests whether TYPE exists after having included INCLUDES, setting cache
+@%:@ variable VAR accordingly.
+ac_fn_c_check_type ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=no"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+if (sizeof ($2))
+	 return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+if (sizeof (($2)))
+	    return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  
+else
+  eval "$3=yes"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} @%:@ ac_fn_c_check_type
+
+@%:@ ac_fn_c_try_cpp LINENO
+@%:@ ----------------------
+@%:@ Try to preprocess conftest. at S|@ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } > conftest.i && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+    ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} @%:@ ac_fn_c_try_cpp
+
+@%:@ ac_fn_c_try_run LINENO
+@%:@ ----------------------
+@%:@ Try to link conftest. at S|@ac_ext, and return whether this succeeded. Assumes
+@%:@ that executables *can* be run.
+ac_fn_c_try_run ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: program exited with status $ac_status" >&5
+       $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_retval=$ac_status
+fi
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} @%:@ ac_fn_c_try_run
+
+@%:@ ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+@%:@ -------------------------------------------------------
+@%:@ Tests whether HEADER exists and can be compiled using the include files in
+@%:@ INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+@%:@include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} @%:@ ac_fn_c_check_header_compile
+
+@%:@ ac_fn_c_check_func LINENO FUNC VAR
+@%:@ ----------------------------------
+@%:@ Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $2 (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} @%:@ ac_fn_c_check_func
+
+@%:@ ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+@%:@ -------------------------------------------------------
+@%:@ Tests whether HEADER exists, giving a warning if it cannot be compiled using
+@%:@ the include files in INCLUDES and setting the cache variable VAR
+@%:@ accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if eval \${$3+:} false; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+@%:@include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_header_compiler=yes
+else
+  ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+@%:@include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  ac_header_preproc=yes
+else
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+  yes:no: )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+    ;;
+  no:yes:* )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+( $as_echo "## ----------------------------------- ##
+## Report this to bugs at zoo-project.org ##
+## ----------------------------------- ##"
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} @%:@ ac_fn_c_check_header_mongrel
+
+@%:@ ac_fn_c_find_intX_t LINENO BITS VAR
+@%:@ -----------------------------------
+@%:@ Finds a signed integer type with width BITS, setting cache variable VAR
+@%:@ accordingly.
+ac_fn_c_find_intX_t ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for int$2_t" >&5
+$as_echo_n "checking for int$2_t... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=no"
+     # Order is important - never check a type that is potentially smaller
+     # than half of the expected target width.
+     for ac_type in int$2_t 'int' 'long int' \
+	 'long long int' 'short int' 'signed char'; do
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_includes_default
+	     enum { N = $2 / 2 - 1 };
+int
+main ()
+{
+static int test_array @<:@1 - 2 * !(0 < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1))@:>@;
+test_array @<:@0@:>@ = 0;
+return test_array @<:@0@:>@;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_includes_default
+	        enum { N = $2 / 2 - 1 };
+int
+main ()
+{
+static int test_array @<:@1 - 2 * !(($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1)
+		 < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 2))@:>@;
+test_array @<:@0@:>@ = 0;
+return test_array @<:@0@:>@;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  
+else
+  case $ac_type in @%:@(
+  int$2_t) :
+    eval "$3=yes" ;; @%:@(
+  *) :
+    eval "$3=\$ac_type" ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+       if eval test \"x\$"$3"\" = x"no"; then :
+  
+else
+  break
+fi
+     done
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} @%:@ ac_fn_c_find_intX_t
+
+@%:@ ac_fn_c_find_uintX_t LINENO BITS VAR
+@%:@ ------------------------------------
+@%:@ Finds an unsigned integer type with width BITS, setting cache variable VAR
+@%:@ accordingly.
+ac_fn_c_find_uintX_t ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uint$2_t" >&5
+$as_echo_n "checking for uint$2_t... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=no"
+     # Order is important - never check a type that is potentially smaller
+     # than half of the expected target width.
+     for ac_type in uint$2_t 'unsigned int' 'unsigned long int' \
+	 'unsigned long long int' 'unsigned short int' 'unsigned char'; do
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array @<:@1 - 2 * !((($ac_type) -1 >> ($2 / 2 - 1)) >> ($2 / 2 - 1) == 3)@:>@;
+test_array @<:@0@:>@ = 0;
+return test_array @<:@0@:>@;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  case $ac_type in @%:@(
+  uint$2_t) :
+    eval "$3=yes" ;; @%:@(
+  *) :
+    eval "$3=\$ac_type" ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+       if eval test \"x\$"$3"\" = x"no"; then :
+  
+else
+  break
+fi
+     done
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} @%:@ ac_fn_c_find_uintX_t
+
+@%:@ ac_fn_cxx_try_cpp LINENO
+@%:@ ------------------------
+@%:@ Try to preprocess conftest. at S|@ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_cpp ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } > conftest.i && {
+	 test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+    ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} @%:@ ac_fn_cxx_try_cpp
+
+@%:@ ac_fn_cxx_check_header_mongrel LINENO HEADER VAR INCLUDES
+@%:@ ---------------------------------------------------------
+@%:@ Tests whether HEADER exists, giving a warning if it cannot be compiled using
+@%:@ the include files in INCLUDES and setting the cache variable VAR
+@%:@ accordingly.
+ac_fn_cxx_check_header_mongrel ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if eval \${$3+:} false; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+@%:@include <$2>
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_header_compiler=yes
+else
+  ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+@%:@include <$2>
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+  ac_header_preproc=yes
+else
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in #((
+  yes:no: )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+    ;;
+  no:yes:* )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+( $as_echo "## ----------------------------------- ##
+## Report this to bugs at zoo-project.org ##
+## ----------------------------------- ##"
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} @%:@ ac_fn_cxx_check_header_mongrel
+
+@%:@ ac_fn_cxx_try_link LINENO
+@%:@ -------------------------
+@%:@ Try to link conftest. at S|@ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_link ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext conftest$ac_exeext
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 test -x conftest$ac_exeext
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+  # interfere with the next link command; also delete a directory that is
+  # left behind by Apple's compiler.  We do this before executing the actions.
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} @%:@ ac_fn_cxx_try_link
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by ZOO Kernel $as_me 1.5.0, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    $as_echo "PATH: $as_dir"
+  done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+    2)
+      as_fn_append ac_configure_args1 " '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+	ac_must_keep_next=false # Got value, back to normal.
+      else
+	case $ac_arg in
+	  *=* | --config-cache | -C | -disable-* | --disable-* \
+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+	  | -with-* | --with-* | -without-* | --without-* | --x)
+	    case "$ac_configure_args0 " in
+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+	    esac
+	    ;;
+	  -* ) ac_must_keep_next=true ;;
+	esac
+      fi
+      as_fn_append ac_configure_args " '$ac_arg'"
+      ;;
+    esac
+  done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+	"s/'\''/'\''\\\\'\'''\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      $as_echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=\$$ac_var
+	case $ac_val in
+	*\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+	esac
+	$as_echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      $as_echo "$as_me: caught signal $ac_signal"
+    $as_echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+@%:@define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+@%:@define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+@%:@define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+@%:@define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+@%:@define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+@%:@define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+  # We do not want a PATH search for config.site.
+  case $CONFIG_SITE in @%:@((
+    -*)  ac_site_file1=./$CONFIG_SITE;;
+    */*) ac_site_file1=$CONFIG_SITE;;
+    *)   ac_site_file1=./$CONFIG_SITE;;
+  esac
+elif test "x$prefix" != xNONE; then
+  ac_site_file1=$prefix/share/config.site
+  ac_site_file2=$prefix/etc/config.site
+else
+  ac_site_file1=$ac_default_prefix/share/config.site
+  ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+  test "x$ac_site_file" = xNONE && continue
+  if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file" \
+      || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special files
+  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.
+  if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+	# differences in whitespace do not lead to failure.
+	ac_old_val_w=`echo x $ac_old_val`
+	ac_new_val_w=`echo x $ac_new_val`
+	if test "$ac_old_val_w" != "$ac_new_val_w"; then
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+	  ac_cache_corrupted=:
+	else
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+	  eval $ac_var=\$ac_old_val
+	fi
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
+$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
+$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+# Checks for programs.
+for ac_prog in 'bison -y' byacc
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_YACC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$YACC"; then
+  ac_cv_prog_YACC="$YACC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_YACC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+YACC=$ac_cv_prog_YACC
+if test -n "$YACC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $YACC" >&5
+$as_echo "$YACC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$YACC" && break
+done
+test -n "$YACC" || YACC="yacc"
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $@%:@ != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+	;;
+    [ab].out )
+	# We found the default executable, but exeext='' is most
+	# certainly right.
+	break;;
+    *.* )
+	if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+	then :; else
+	   ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	fi
+	# We set ac_cv_exeext here because the later test for it is not
+	# safe: cross compilers may not add the suffix if given an `-o'
+	# argument, so we may need to know it at that point already.
+	# Even if this section looks crufty: it has the advantage of
+	# actually working.
+	break;;
+    * )
+	break;;
+  esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+  ac_file=''
+fi
+if test -z "$ac_file"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	  break;;
+    * ) break;;
+  esac
+done
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+@%:@include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+  { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+  if { ac_try='./conftest$ac_cv_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+    fi
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+else
+  CFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  
+else
+  ac_c_werror_flag=$ac_save_c_werror_flag
+	 CFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+  xno)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+  
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+for ac_prog in flex lex
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_LEX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$LEX"; then
+  ac_cv_prog_LEX="$LEX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_LEX="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+LEX=$ac_cv_prog_LEX
+if test -n "$LEX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LEX" >&5
+$as_echo "$LEX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$LEX" && break
+done
+test -n "$LEX" || LEX=":"
+
+if test "x$LEX" != "x:"; then
+  cat >conftest.l <<_ACEOF
+%%
+a { ECHO; }
+b { REJECT; }
+c { yymore (); }
+d { yyless (1); }
+e { /* IRIX 6.5 flex 2.5.4 underquotes its yyless argument.  */
+    yyless ((input () != 0)); }
+f { unput (yytext[0]); }
+. { BEGIN INITIAL; }
+%%
+#ifdef YYTEXT_POINTER
+extern char *yytext;
+#endif
+int
+main (void)
+{
+  return ! yylex () + ! yywrap ();
+}
+_ACEOF
+{ { ac_try="$LEX conftest.l"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$LEX conftest.l") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking lex output file root" >&5
+$as_echo_n "checking lex output file root... " >&6; }
+if ${ac_cv_prog_lex_root+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  
+if test -f lex.yy.c; then
+  ac_cv_prog_lex_root=lex.yy
+elif test -f lexyy.c; then
+  ac_cv_prog_lex_root=lexyy
+else
+  as_fn_error $? "cannot find output from $LEX; giving up" "$LINENO" 5
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_root" >&5
+$as_echo "$ac_cv_prog_lex_root" >&6; }
+LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root
+
+if test -z "${LEXLIB+set}"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking lex library" >&5
+$as_echo_n "checking lex library... " >&6; }
+if ${ac_cv_lib_lex+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  
+    ac_save_LIBS=$LIBS
+    ac_cv_lib_lex='none needed'
+    for ac_lib in '' -lfl -ll; do
+      LIBS="$ac_lib $ac_save_LIBS"
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+`cat $LEX_OUTPUT_ROOT.c`
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_lex=$ac_lib
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+      test "$ac_cv_lib_lex" != 'none needed' && break
+    done
+    LIBS=$ac_save_LIBS
+  
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lex" >&5
+$as_echo "$ac_cv_lib_lex" >&6; }
+  test "$ac_cv_lib_lex" != 'none needed' && LEXLIB=$ac_cv_lib_lex
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether yytext is a pointer" >&5
+$as_echo_n "checking whether yytext is a pointer... " >&6; }
+if ${ac_cv_prog_lex_yytext_pointer+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  # POSIX says lex can declare yytext either as a pointer or an array; the
+# default is implementation-dependent.  Figure out which it is, since
+# not all implementations provide the %pointer and %array declarations.
+ac_cv_prog_lex_yytext_pointer=no
+ac_save_LIBS=$LIBS
+LIBS="$LEXLIB $ac_save_LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+  #define YYTEXT_POINTER 1
+`cat $LEX_OUTPUT_ROOT.c`
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_prog_lex_yytext_pointer=yes
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_save_LIBS
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_yytext_pointer" >&5
+$as_echo "$ac_cv_prog_lex_yytext_pointer" >&6; }
+if test $ac_cv_prog_lex_yytext_pointer = yes; then
+  
+$as_echo "@%:@define YYTEXT_POINTER 1" >>confdefs.h
+
+fi
+rm -f conftest.l $LEX_OUTPUT_ROOT.c
+
+fi
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+  if test -n "$CCC"; then
+    CXX=$CCC
+  else
+    if test -n "$ac_tool_prefix"; then
+  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CXX"; then
+  ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
+$as_echo "$CXX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CXX" && break
+  done
+fi
+if test -z "$CXX"; then
+  ac_ct_CXX=$CXX
+  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CXX"; then
+  ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CXX="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
+$as_echo "$ac_ct_CXX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CXX" && break
+done
+
+  if test "x$ac_ct_CXX" = x; then
+    CXX="g++"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CXX=$ac_ct_CXX
+  fi
+fi
+
+  fi
+fi
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5
+$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
+if ${ac_cv_cxx_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
+$as_echo "$ac_cv_cxx_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GXX=yes
+else
+  GXX=
+fi
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
+$as_echo_n "checking whether $CXX accepts -g... " >&6; }
+if ${ac_cv_prog_cxx_g+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+   ac_cxx_werror_flag=yes
+   ac_cv_prog_cxx_g=no
+   CXXFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_prog_cxx_g=yes
+else
+  CXXFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  
+else
+  ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+	 CXXFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_prog_cxx_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
+$as_echo "$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+  CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+  if test "$GXX" = yes; then
+    CXXFLAGS="-g -O2"
+  else
+    CXXFLAGS="-g"
+  fi
+else
+  if test "$GXX" = yes; then
+    CXXFLAGS="-O2"
+  else
+    CXXFLAGS=
+  fi
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
+$as_echo_n "checking for a sed that does not truncate output... " >&6; }
+if ${ac_cv_path_SED+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+            ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
+     for ac_i in 1 2 3 4 5 6 7; do
+       ac_script="$ac_script$as_nl$ac_script"
+     done
+     echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed
+     { ac_script=; unset ac_script;}
+     if test -z "$SED"; then
+  ac_path_SED_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in sed gsed; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_SED="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_SED" || continue
+# Check for GNU ac_path_SED and select it if it is found.
+  # Check for GNU $ac_path_SED
+case `"$ac_path_SED" --version 2>&1` in
+*GNU*)
+  ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo '' >> "conftest.nl"
+    "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_SED_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_SED="$ac_path_SED"
+      ac_path_SED_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_SED_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_SED"; then
+    as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5
+  fi
+else
+  ac_cv_path_SED=$SED
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5
+$as_echo "$ac_cv_path_SED" >&6; }
+ SED="$ac_cv_path_SED"
+  rm -f conftest.sed
+
+
+# Checks for libraries.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for curl_easy_init,curl_easy_setopt,curl_easy_cleanup,curl_easy_perform in -lcurl" >&5
+$as_echo_n "checking for curl_easy_init,curl_easy_setopt,curl_easy_cleanup,curl_easy_perform in -lcurl... " >&6; }
+if ${ac_cv_lib_curl_curl_easy_init_curl_easy_setopt_curl_easy_cleanup_curl_easy_perform+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcurl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char curl_easy_init,curl_easy_setopt,curl_easy_cleanup,curl_easy_perform ();
+int
+main ()
+{
+return curl_easy_init,curl_easy_setopt,curl_easy_cleanup,curl_easy_perform ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_curl_curl_easy_init_curl_easy_setopt_curl_easy_cleanup_curl_easy_perform=yes
+else
+  ac_cv_lib_curl_curl_easy_init_curl_easy_setopt_curl_easy_cleanup_curl_easy_perform=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_curl_curl_easy_init_curl_easy_setopt_curl_easy_cleanup_curl_easy_perform" >&5
+$as_echo "$ac_cv_lib_curl_curl_easy_init_curl_easy_setopt_curl_easy_cleanup_curl_easy_perform" >&6; }
+if test "x$ac_cv_lib_curl_curl_easy_init_curl_easy_setopt_curl_easy_cleanup_curl_easy_perform" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+@%:@define HAVE_LIBCURL 1
+_ACEOF
+
+  LIBS="-lcurl $LIBS"
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen,dlsym,dlerror,dlclose in -ldl" >&5
+$as_echo_n "checking for dlopen,dlsym,dlerror,dlclose in -ldl... " >&6; }
+if ${ac_cv_lib_dl_dlopen_dlsym_dlerror_dlclose+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen,dlsym,dlerror,dlclose ();
+int
+main ()
+{
+return dlopen,dlsym,dlerror,dlclose ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dl_dlopen_dlsym_dlerror_dlclose=yes
+else
+  ac_cv_lib_dl_dlopen_dlsym_dlerror_dlclose=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen_dlsym_dlerror_dlclose" >&5
+$as_echo "$ac_cv_lib_dl_dlopen_dlsym_dlerror_dlclose" >&6; }
+if test "x$ac_cv_lib_dl_dlopen_dlsym_dlerror_dlclose" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+@%:@define HAVE_LIBDL 1
+_ACEOF
+
+  LIBS="-ldl $LIBS"
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for EVP_DigestInit,EVP_md5,EVP_DigestUpdate,BIO_f_base64,BIO_new in -lcrypto" >&5
+$as_echo_n "checking for EVP_DigestInit,EVP_md5,EVP_DigestUpdate,BIO_f_base64,BIO_new in -lcrypto... " >&6; }
+if ${ac_cv_lib_crypto_EVP_DigestInit_EVP_md5_EVP_DigestUpdate_BIO_f_base64_BIO_new+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcrypto  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char EVP_DigestInit,EVP_md5,EVP_DigestUpdate,BIO_f_base64,BIO_new ();
+int
+main ()
+{
+return EVP_DigestInit,EVP_md5,EVP_DigestUpdate,BIO_f_base64,BIO_new ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_crypto_EVP_DigestInit_EVP_md5_EVP_DigestUpdate_BIO_f_base64_BIO_new=yes
+else
+  ac_cv_lib_crypto_EVP_DigestInit_EVP_md5_EVP_DigestUpdate_BIO_f_base64_BIO_new=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_EVP_DigestInit_EVP_md5_EVP_DigestUpdate_BIO_f_base64_BIO_new" >&5
+$as_echo "$ac_cv_lib_crypto_EVP_DigestInit_EVP_md5_EVP_DigestUpdate_BIO_f_base64_BIO_new" >&6; }
+if test "x$ac_cv_lib_crypto_EVP_DigestInit_EVP_md5_EVP_DigestUpdate_BIO_f_base64_BIO_new" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+@%:@define HAVE_LIBCRYPTO 1
+_ACEOF
+
+  LIBS="-lcrypto $LIBS"
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_generate_time in -luuid" >&5
+$as_echo_n "checking for uuid_generate_time in -luuid... " >&6; }
+if ${ac_cv_lib_uuid_uuid_generate_time+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-luuid  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char uuid_generate_time ();
+int
+main ()
+{
+return uuid_generate_time ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_uuid_uuid_generate_time=yes
+else
+  ac_cv_lib_uuid_uuid_generate_time=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_uuid_uuid_generate_time" >&5
+$as_echo "$ac_cv_lib_uuid_uuid_generate_time" >&6; }
+if test "x$ac_cv_lib_uuid_uuid_generate_time" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+@%:@define HAVE_LIBUUID 1
+_ACEOF
+
+  LIBS="-luuid $LIBS"
+
+fi
+
+
+DEFAULT_LIBS="$LIBS"
+
+
+
+# Checks for header files.
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if ${ac_cv_prog_CPP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+@%:@ifdef __STDC__
+@%:@ include <limits.h>
+@%:@else
+@%:@ include <assert.h>
+@%:@endif
+		     Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+@%:@include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+  
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+@%:@ifdef __STDC__
+@%:@ include <limits.h>
+@%:@else
+@%:@ include <assert.h>
+@%:@endif
+		     Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+@%:@include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+  
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$GREP"; then
+  ac_path_GREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in grep ggrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_GREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_GREP"; then
+    as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+ 
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     if test -z "$EGREP"; then
+  ac_path_EGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in egrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_EGREP" || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_EGREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_EGREP"; then
+    as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+ 
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_header_stdc=yes
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then :
+  
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then :
+  
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then :
+  :
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+		   (('a' <= (c) && (c) <= 'i') \
+		     || ('j' <= (c) && (c) <= 'r') \
+		     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+	|| toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+  
+$as_echo "@%:@define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+		  inttypes.h stdint.h unistd.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+@%:@define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+ 
+fi
+
+done
+
+
+ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default"
+if test "x$ac_cv_type_size_t" = xyes; then :
+  
+else
+  
+cat >>confdefs.h <<_ACEOF
+@%:@define size_t unsigned int
+_ACEOF
+
+fi
+
+# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
+# for constant arguments.  Useless!
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working alloca.h" >&5
+$as_echo_n "checking for working alloca.h... " >&6; }
+if ${ac_cv_working_alloca_h+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+@%:@include <alloca.h>
+int
+main ()
+{
+char *p = (char *) alloca (2 * sizeof (int));
+			  if (p) return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_working_alloca_h=yes
+else
+  ac_cv_working_alloca_h=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_working_alloca_h" >&5
+$as_echo "$ac_cv_working_alloca_h" >&6; }
+if test $ac_cv_working_alloca_h = yes; then
+  
+$as_echo "@%:@define HAVE_ALLOCA_H 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for alloca" >&5
+$as_echo_n "checking for alloca... " >&6; }
+if ${ac_cv_func_alloca_works+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+#else
+# ifdef _MSC_VER
+#  include <malloc.h>
+#  define alloca _alloca
+# else
+#  ifdef HAVE_ALLOCA_H
+#   include <alloca.h>
+#  else
+#   ifdef _AIX
+ #pragma alloca
+#   else
+#    ifndef alloca /* predefined by HP cc +Olibcalls */
+void *alloca (size_t);
+#    endif
+#   endif
+#  endif
+# endif
+#endif
+
+int
+main ()
+{
+char *p = (char *) alloca (1);
+				    if (p) return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_func_alloca_works=yes
+else
+  ac_cv_func_alloca_works=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_alloca_works" >&5
+$as_echo "$ac_cv_func_alloca_works" >&6; }
+
+if test $ac_cv_func_alloca_works = yes; then
+  
+$as_echo "@%:@define HAVE_ALLOCA 1" >>confdefs.h
+
+else
+  # The SVR3 libPW and SVR4 libucb both contain incompatible functions
+# that cause trouble.  Some versions do not even contain alloca or
+# contain a buggy version.  If you still want to use their alloca,
+# use ar to extract alloca.o from them instead of compiling alloca.c.
+
+ALLOCA=\${LIBOBJDIR}alloca.$ac_objext
+
+$as_echo "@%:@define C_ALLOCA 1" >>confdefs.h
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether \`alloca.c' needs Cray hooks" >&5
+$as_echo_n "checking whether \`alloca.c' needs Cray hooks... " >&6; }
+if ${ac_cv_os_cray+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#if defined CRAY && ! defined CRAY2
+webecray
+#else
+wenotbecray
+#endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "webecray" >/dev/null 2>&1; then :
+  ac_cv_os_cray=yes
+else
+  ac_cv_os_cray=no
+fi
+rm -f conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_os_cray" >&5
+$as_echo "$ac_cv_os_cray" >&6; }
+if test $ac_cv_os_cray = yes; then
+  for ac_func in _getb67 GETB67 getb67; do
+    as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  
+cat >>confdefs.h <<_ACEOF
+@%:@define CRAY_STACKSEG_END $ac_func
+_ACEOF
+
+    break
+fi
+
+  done
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking stack direction for C alloca" >&5
+$as_echo_n "checking stack direction for C alloca... " >&6; }
+if ${ac_cv_c_stack_direction+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "$cross_compiling" = yes; then :
+  ac_cv_c_stack_direction=0
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_includes_default
+int
+find_stack_direction (int *addr, int depth)
+{
+  int dir, dummy = 0;
+  if (! addr)
+    addr = &dummy;
+  *addr = addr < &dummy ? 1 : addr == &dummy ? 0 : -1;
+  dir = depth ? find_stack_direction (addr, depth - 1) : 0;
+  return dir + dummy;
+}
+
+int
+main (int argc, char **argv)
+{
+  return find_stack_direction (0, argc + !argv + 20) < 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  ac_cv_c_stack_direction=1
+else
+  ac_cv_c_stack_direction=-1
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_stack_direction" >&5
+$as_echo "$ac_cv_c_stack_direction" >&6; }
+cat >>confdefs.h <<_ACEOF
+@%:@define STACK_DIRECTION $ac_cv_c_stack_direction
+_ACEOF
+
+
+fi
+
+for ac_header in fcntl.h inttypes.h libintl.h malloc.h stddef.h stdlib.h string.h unistd.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+@%:@define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+ 
+fi
+
+done
+
+
+# Checks for typedefs, structures, and compiler characteristics.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdbool.h that conforms to C99" >&5
+$as_echo_n "checking for stdbool.h that conforms to C99... " >&6; }
+if ${ac_cv_header_stdbool_h+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+             #include <stdbool.h>
+             #ifndef bool
+              "error: bool is not defined"
+             #endif
+             #ifndef false
+              "error: false is not defined"
+             #endif
+             #if false
+              "error: false is not 0"
+             #endif
+             #ifndef true
+              "error: true is not defined"
+             #endif
+             #if true != 1
+              "error: true is not 1"
+             #endif
+             #ifndef __bool_true_false_are_defined
+              "error: __bool_true_false_are_defined is not defined"
+             #endif
+
+             struct s { _Bool s: 1; _Bool t; } s;
+
+             char a[true == 1 ? 1 : -1];
+             char b[false == 0 ? 1 : -1];
+             char c[__bool_true_false_are_defined == 1 ? 1 : -1];
+             char d[(bool) 0.5 == true ? 1 : -1];
+             /* See body of main program for 'e'.  */
+             char f[(_Bool) 0.0 == false ? 1 : -1];
+             char g[true];
+             char h[sizeof (_Bool)];
+             char i[sizeof s.t];
+             enum { j = false, k = true, l = false * true, m = true * 256 };
+             /* The following fails for
+                HP aC++/ANSI C B3910B A.05.55 [Dec 04 2003]. */
+             _Bool n[m];
+             char o[sizeof n == m * sizeof n[0] ? 1 : -1];
+             char p[-1 - (_Bool) 0 < 0 && -1 - (bool) 0 < 0 ? 1 : -1];
+             /* Catch a bug in an HP-UX C compiler.  See
+                http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html
+                http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html
+              */
+             _Bool q = true;
+             _Bool *pq = &q;
+           
+int
+main ()
+{
+
+             bool e = &s;
+             *pq |= q;
+             *pq |= ! q;
+             /* Refer to every declared value, to avoid compiler optimizations.  */
+             return (!a + !b + !c + !d + !e + !f + !g + !h + !i + !!j + !k + !!l
+                     + !m + !n + !o + !p + !q + !pq);
+           
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_header_stdbool_h=yes
+else
+  ac_cv_header_stdbool_h=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdbool_h" >&5
+$as_echo "$ac_cv_header_stdbool_h" >&6; }
+   ac_fn_c_check_type "$LINENO" "_Bool" "ac_cv_type__Bool" "$ac_includes_default"
+if test "x$ac_cv_type__Bool" = xyes; then :
+  
+cat >>confdefs.h <<_ACEOF
+@%:@define HAVE__BOOL 1
+_ACEOF
+
+
+fi
+
+
+if test $ac_cv_header_stdbool_h = yes; then
+  
+$as_echo "@%:@define HAVE_STDBOOL_H 1" >>confdefs.h
+
+fi
+
+ac_fn_c_find_intX_t "$LINENO" "16" "ac_cv_c_int16_t"
+case $ac_cv_c_int16_t in #(
+  no|yes) ;; #(
+  *)
+    
+cat >>confdefs.h <<_ACEOF
+@%:@define int16_t $ac_cv_c_int16_t
+_ACEOF
+;;
+esac
+
+ac_fn_c_find_intX_t "$LINENO" "32" "ac_cv_c_int32_t"
+case $ac_cv_c_int32_t in #(
+  no|yes) ;; #(
+  *)
+    
+cat >>confdefs.h <<_ACEOF
+@%:@define int32_t $ac_cv_c_int32_t
+_ACEOF
+;;
+esac
+
+ac_fn_c_find_intX_t "$LINENO" "8" "ac_cv_c_int8_t"
+case $ac_cv_c_int8_t in #(
+  no|yes) ;; #(
+  *)
+    
+cat >>confdefs.h <<_ACEOF
+@%:@define int8_t $ac_cv_c_int8_t
+_ACEOF
+;;
+esac
+
+ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default"
+if test "x$ac_cv_type_pid_t" = xyes; then :
+  
+else
+  
+cat >>confdefs.h <<_ACEOF
+@%:@define pid_t int
+_ACEOF
+
+fi
+
+ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default"
+if test "x$ac_cv_type_size_t" = xyes; then :
+  
+else
+  
+cat >>confdefs.h <<_ACEOF
+@%:@define size_t unsigned int
+_ACEOF
+
+fi
+
+ac_fn_c_find_uintX_t "$LINENO" "16" "ac_cv_c_uint16_t"
+case $ac_cv_c_uint16_t in #(
+  no|yes) ;; #(
+  *)
+    
+    
+cat >>confdefs.h <<_ACEOF
+@%:@define uint16_t $ac_cv_c_uint16_t
+_ACEOF
+;;
+  esac
+
+ac_fn_c_find_uintX_t "$LINENO" "32" "ac_cv_c_uint32_t"
+case $ac_cv_c_uint32_t in #(
+  no|yes) ;; #(
+  *)
+    
+$as_echo "@%:@define _UINT32_T 1" >>confdefs.h
+
+    
+cat >>confdefs.h <<_ACEOF
+@%:@define uint32_t $ac_cv_c_uint32_t
+_ACEOF
+;;
+  esac
+
+ac_fn_c_find_uintX_t "$LINENO" "8" "ac_cv_c_uint8_t"
+case $ac_cv_c_uint8_t in #(
+  no|yes) ;; #(
+  *)
+    
+$as_echo "@%:@define _UINT8_T 1" >>confdefs.h
+
+    
+cat >>confdefs.h <<_ACEOF
+@%:@define uint8_t $ac_cv_c_uint8_t
+_ACEOF
+;;
+  esac
+
+
+# Checks for library functions.
+for ac_header in vfork.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "vfork.h" "ac_cv_header_vfork_h" "$ac_includes_default"
+if test "x$ac_cv_header_vfork_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+@%:@define HAVE_VFORK_H 1
+_ACEOF
+ 
+fi
+
+done
+
+for ac_func in fork vfork
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+@%:@define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+ 
+fi
+done
+
+if test "x$ac_cv_func_fork" = xyes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working fork" >&5
+$as_echo_n "checking for working fork... " >&6; }
+if ${ac_cv_func_fork_works+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "$cross_compiling" = yes; then :
+  ac_cv_func_fork_works=cross
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+
+	  /* By Ruediger Kuhlmann. */
+	  return fork () < 0;
+	
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  ac_cv_func_fork_works=yes
+else
+  ac_cv_func_fork_works=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_fork_works" >&5
+$as_echo "$ac_cv_func_fork_works" >&6; }
+
+else
+  ac_cv_func_fork_works=$ac_cv_func_fork
+fi
+if test "x$ac_cv_func_fork_works" = xcross; then
+  case $host in
+    *-*-amigaos* | *-*-msdosdjgpp*)
+      # Override, as these systems have only a dummy fork() stub
+      ac_cv_func_fork_works=no
+      ;;
+    *)
+      ac_cv_func_fork_works=yes
+      ;;
+  esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&5
+$as_echo "$as_me: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&2;}
+fi
+ac_cv_func_vfork_works=$ac_cv_func_vfork
+if test "x$ac_cv_func_vfork" = xyes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working vfork" >&5
+$as_echo_n "checking for working vfork... " >&6; }
+if ${ac_cv_func_vfork_works+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "$cross_compiling" = yes; then :
+  ac_cv_func_vfork_works=cross
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+/* Thanks to Paul Eggert for this test.  */
+$ac_includes_default
+#include <sys/wait.h>
+#ifdef HAVE_VFORK_H
+# include <vfork.h>
+#endif
+/* On some sparc systems, changes by the child to local and incoming
+   argument registers are propagated back to the parent.  The compiler
+   is told about this with #include <vfork.h>, but some compilers
+   (e.g. gcc -O) don't grok <vfork.h>.  Test for this by using a
+   static variable whose address is put into a register that is
+   clobbered by the vfork.  */
+static void
+#ifdef __cplusplus
+sparc_address_test (int arg)
+# else
+sparc_address_test (arg) int arg;
+#endif
+{
+  static pid_t child;
+  if (!child) {
+    child = vfork ();
+    if (child < 0) {
+      perror ("vfork");
+      _exit(2);
+    }
+    if (!child) {
+      arg = getpid();
+      write(-1, "", 0);
+      _exit (arg);
+    }
+  }
+}
+
+int
+main ()
+{
+  pid_t parent = getpid ();
+  pid_t child;
+
+  sparc_address_test (0);
+
+  child = vfork ();
+
+  if (child == 0) {
+    /* Here is another test for sparc vfork register problems.  This
+       test uses lots of local variables, at least as many local
+       variables as main has allocated so far including compiler
+       temporaries.  4 locals are enough for gcc 1.40.3 on a Solaris
+       4.1.3 sparc, but we use 8 to be safe.  A buggy compiler should
+       reuse the register of parent for one of the local variables,
+       since it will think that parent can't possibly be used any more
+       in this routine.  Assigning to the local variable will thus
+       munge parent in the parent process.  */
+    pid_t
+      p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(),
+      p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid();
+    /* Convince the compiler that p..p7 are live; otherwise, it might
+       use the same hardware register for all 8 local variables.  */
+    if (p != p1 || p != p2 || p != p3 || p != p4
+	|| p != p5 || p != p6 || p != p7)
+      _exit(1);
+
+    /* On some systems (e.g. IRIX 3.3), vfork doesn't separate parent
+       from child file descriptors.  If the child closes a descriptor
+       before it execs or exits, this munges the parent's descriptor
+       as well.  Test for this by closing stdout in the child.  */
+    _exit(close(fileno(stdout)) != 0);
+  } else {
+    int status;
+    struct stat st;
+
+    while (wait(&status) != child)
+      ;
+    return (
+	 /* Was there some problem with vforking?  */
+	 child < 0
+
+	 /* Did the child fail?  (This shouldn't happen.)  */
+	 || status
+
+	 /* Did the vfork/compiler bug occur?  */
+	 || parent != getpid()
+
+	 /* Did the file descriptor bug occur?  */
+	 || fstat(fileno(stdout), &st) != 0
+	 );
+  }
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  ac_cv_func_vfork_works=yes
+else
+  ac_cv_func_vfork_works=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_vfork_works" >&5
+$as_echo "$ac_cv_func_vfork_works" >&6; }
+
+fi;
+if test "x$ac_cv_func_fork_works" = xcross; then
+  ac_cv_func_vfork_works=$ac_cv_func_vfork
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&5
+$as_echo "$as_me: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&2;}
+fi
+
+if test "x$ac_cv_func_vfork_works" = xyes; then
+  
+$as_echo "@%:@define HAVE_WORKING_VFORK 1" >>confdefs.h
+
+else
+  
+$as_echo "@%:@define vfork fork" >>confdefs.h
+
+fi
+if test "x$ac_cv_func_fork_works" = xyes; then
+  
+$as_echo "@%:@define HAVE_WORKING_FORK 1" >>confdefs.h
+
+fi
+
+for ac_header in stdlib.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default"
+if test "x$ac_cv_header_stdlib_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+@%:@define HAVE_STDLIB_H 1
+_ACEOF
+ 
+fi
+
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible malloc" >&5
+$as_echo_n "checking for GNU libc compatible malloc... " >&6; }
+if ${ac_cv_func_malloc_0_nonnull+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "$cross_compiling" = yes; then :
+  ac_cv_func_malloc_0_nonnull=no
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#if defined STDC_HEADERS || defined HAVE_STDLIB_H
+# include <stdlib.h>
+#else
+char *malloc ();
+#endif
+
+int
+main ()
+{
+return ! malloc (0);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  ac_cv_func_malloc_0_nonnull=yes
+else
+  ac_cv_func_malloc_0_nonnull=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_malloc_0_nonnull" >&5
+$as_echo "$ac_cv_func_malloc_0_nonnull" >&6; }
+if test $ac_cv_func_malloc_0_nonnull = yes; then :
+  
+$as_echo "@%:@define HAVE_MALLOC 1" >>confdefs.h
+
+else
+  $as_echo "@%:@define HAVE_MALLOC 0" >>confdefs.h
+
+   case " $LIB@&t at OBJS " in
+  *" malloc.$ac_objext "* ) ;;
+  *) LIB@&t at OBJS="$LIB@&t at OBJS malloc.$ac_objext"
+ ;;
+esac
+
+   
+$as_echo "@%:@define malloc rpl_malloc" >>confdefs.h
+
+fi
+
+
+for ac_header in stdlib.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default"
+if test "x$ac_cv_header_stdlib_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+@%:@define HAVE_STDLIB_H 1
+_ACEOF
+ 
+fi
+
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible realloc" >&5
+$as_echo_n "checking for GNU libc compatible realloc... " >&6; }
+if ${ac_cv_func_realloc_0_nonnull+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "$cross_compiling" = yes; then :
+  ac_cv_func_realloc_0_nonnull=no
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#if defined STDC_HEADERS || defined HAVE_STDLIB_H
+# include <stdlib.h>
+#else
+char *realloc ();
+#endif
+
+int
+main ()
+{
+return ! realloc (0, 0);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  ac_cv_func_realloc_0_nonnull=yes
+else
+  ac_cv_func_realloc_0_nonnull=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_realloc_0_nonnull" >&5
+$as_echo "$ac_cv_func_realloc_0_nonnull" >&6; }
+if test $ac_cv_func_realloc_0_nonnull = yes; then :
+  
+$as_echo "@%:@define HAVE_REALLOC 1" >>confdefs.h
+
+else
+  $as_echo "@%:@define HAVE_REALLOC 0" >>confdefs.h
+
+   case " $LIB@&t at OBJS " in
+  *" realloc.$ac_objext "* ) ;;
+  *) LIB@&t at OBJS="$LIB@&t at OBJS realloc.$ac_objext"
+ ;;
+esac
+
+   
+$as_echo "@%:@define realloc rpl_realloc" >>confdefs.h
+
+fi
+
+
+for ac_func in dup2 getcwd memset setenv strdup strstr
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+@%:@define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+ 
+fi
+done
+
+
+#============================================================================
+# Detect if run on debian / ubuntu
+#============================================================================
+if test -f "/usr/bin/dpkg"
+then
+	DEB_DEF=-DDEB
+fi
+
+
+
+@%:@ Check whether --with-cgi-dir was given.
+if test "${with_cgi_dir+set}" = set; then :
+  withval=$with_cgi_dir; CGI_DIR="$withval"
+else
+  CGI_DIR="/usr/lib/cgi-bin"
+fi
+
+
+
+
+@%:@ Check whether --with-db-backend was given.
+if test "${with_db_backend+set}" = set; then :
+  withval=$with_db_backend; RELY_ON_DB="-DRELY_ON_DB"
+else
+  RELY_ON_DB=""
+fi
+
+
+
+
+# ===========================================================================
+# Detect if libyaml is available
+# ===========================================================================
+
+
+@%:@ Check whether --with-yaml was given.
+if test "${with_yaml+set}" = set; then :
+  withval=$with_yaml; YAMLPATH="$withval"
+else
+  YAMLPATH=""
+fi
+
+
+if test -z "$YAMLPATH"
+then
+	YAML_LDFLAGS=""
+	YAML_CPPFLAGS=""
+	YAML_FILE=""
+	YAML_FILE1=""
+else
+
+	# Extract the linker and include flags
+	YAML_LDFLAGS="-L$YAMLPATH/lib -lyaml"
+	YAML_CPPFLAGS="-I$YAMLPATH/include -DYAML"
+	YAML_FILE="service_yaml.o"
+	YAML_FILE1="zcfg2yaml"
+	
+	# Check headers file
+	CPPFLAGS_SAVE="$CPPFLAGS"
+	CPPFLAGS="$YAML_CPPFLAGS"
+	LIBS_SAVE="$LIBS"
+	LIBS="$YAML_LDFLAGS"
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for yaml_parser_initialize,yaml_parser_set_input_file,yaml_parser_scan in -lyaml" >&5
+$as_echo_n "checking for yaml_parser_initialize,yaml_parser_set_input_file,yaml_parser_scan in -lyaml... " >&6; }
+if ${ac_cv_lib_yaml_yaml_parser_initialize_yaml_parser_set_input_file_yaml_parser_scan+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lyaml  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char yaml_parser_initialize,yaml_parser_set_input_file,yaml_parser_scan ();
+int
+main ()
+{
+return yaml_parser_initialize,yaml_parser_set_input_file,yaml_parser_scan ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_yaml_yaml_parser_initialize_yaml_parser_set_input_file_yaml_parser_scan=yes
+else
+  ac_cv_lib_yaml_yaml_parser_initialize_yaml_parser_set_input_file_yaml_parser_scan=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_yaml_yaml_parser_initialize_yaml_parser_set_input_file_yaml_parser_scan" >&5
+$as_echo "$ac_cv_lib_yaml_yaml_parser_initialize_yaml_parser_set_input_file_yaml_parser_scan" >&6; }
+if test "x$ac_cv_lib_yaml_yaml_parser_initialize_yaml_parser_set_input_file_yaml_parser_scan" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+@%:@define HAVE_LIBYAML 1
+_ACEOF
+
+  LIBS="-lyaml $LIBS"
+
+fi
+
+	for ac_header in yaml.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "yaml.h" "ac_cv_header_yaml_h" "$ac_includes_default"
+if test "x$ac_cv_header_yaml_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+@%:@define HAVE_YAML_H 1
+_ACEOF
+ 
+else
+  as_fn_error $? "could not find headers include related to YAML" "$LINENO" 5
+fi
+
+done
+
+	LIBS="$LIBS_SAVE"
+fi
+
+
+
+
+
+# ===========================================================================
+# Detect if fastcgi is available
+# ===========================================================================
+
+
+@%:@ Check whether --with-fastcgi was given.
+if test "${with_fastcgi+set}" = set; then :
+  withval=$with_fastcgi; FCGIPATH="$withval"
+else
+  FCGIPATH="/usr"
+fi
+
+
+# Extract the linker and include flags
+FCGI_LDFLAGS="-L$FCGIPATH/lib"
+FCGI_CPPFLAGS="-I$FCGIPATH/include"
+
+# Check headers file
+CPPFLAGS_SAVE="$CPPFLAGS"
+CPPFLAGS="$FCGI_CPPFLAGS"
+LIBS_SAVE="$LIBS"
+LIBS="$FCGI_LDFLAGS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lfcgi" >&5
+$as_echo_n "checking for main in -lfcgi... " >&6; }
+if ${ac_cv_lib_fcgi_main+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lfcgi  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+return main ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_fcgi_main=yes
+else
+  ac_cv_lib_fcgi_main=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_fcgi_main" >&5
+$as_echo "$ac_cv_lib_fcgi_main" >&6; }
+if test "x$ac_cv_lib_fcgi_main" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+@%:@define HAVE_LIBFCGI 1
+_ACEOF
+
+  LIBS="-lfcgi $LIBS"
+
+fi
+
+for ac_header in fcgi_stdio.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "fcgi_stdio.h" "ac_cv_header_fcgi_stdio_h" "$ac_includes_default"
+if test "x$ac_cv_header_fcgi_stdio_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+@%:@define HAVE_FCGI_STDIO_H 1
+_ACEOF
+ 
+else
+  as_fn_error $? "could not find headers include related to fastcgi" "$LINENO" 5
+fi
+
+done
+
+LIBS="$LIBS_SAVE"
+
+
+
+# ===========================================================================
+# Detect if libxml2 is installed
+# ===========================================================================
+
+
+@%:@ Check whether --with-xml2config was given.
+if test "${with_xml2config+set}" = set; then :
+  withval=$with_xml2config; XML2CONFIG="$withval"
+else
+  XML2CONFIG=""
+fi
+
+
+if test "x$XML2CONFIG" = "x"; then
+	# XML2CONFIG was not specified, so search within the current path
+	# Extract the first word of "xml2-config", so it can be a program name with args.
+set dummy xml2-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_XML2CONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $XML2CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_XML2CONFIG="$XML2CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_XML2CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+XML2CONFIG=$ac_cv_path_XML2CONFIG
+if test -n "$XML2CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XML2CONFIG" >&5
+$as_echo "$XML2CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+	# If we couldn't find xml2-config, display a warning
+	if test "x$XML2CONFIG" = "x"; then
+		as_fn_error $? "could not find xml2-config from libxml2 within the current path. You may need to try re-running configure with a --with-xml2config parameter." "$LINENO" 5
+	fi
+else
+	# XML2CONFIG was specified; display a message to the user
+	if test "x$XML2CONFIG" = "xyes"; then
+		as_fn_error $? "you must Specifies a parameter to --with-xml2config, e.g. --with-xml2config=/path/to/xml2-config" "$LINENO" 5
+	else
+		if test -f $XML2CONFIG; then
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Using user-specified xml2-config file: $XML2CONFIG" >&5
+$as_echo "Using user-specified xml2-config file: $XML2CONFIG" >&6; }
+		else
+			as_fn_error $? "the user-specified xml2-config file $XML2CONFIG does not exist" "$LINENO" 5
+		fi	
+	fi
+fi
+
+# Extract the linker and include flags 
+XML2_LDFLAGS=`$XML2CONFIG --libs`
+XML2_CPPFLAGS=`$XML2CONFIG --cflags`
+
+# Check headers file
+CPPFLAGS_SAVE="$CPPFLAGS"
+CPPFLAGS="$XML2_CPPFLAGS"
+for ac_header in libxml/tree.h libxml/parser.h libxml/xpath.h libxml/xpathInternals.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+@%:@define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+ 
+else
+  as_fn_error $? "could not find headers include related to libxml2" "$LINENO" 5
+fi
+
+done
+
+
+# Ensure we can link against libxml2
+LIBS_SAVE="$LIBS"
+LIBS="$XML2_LDFLAGS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for xmlInitParser in -lxml2" >&5
+$as_echo_n "checking for xmlInitParser in -lxml2... " >&6; }
+if ${ac_cv_lib_xml2_xmlInitParser+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lxml2  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char xmlInitParser ();
+int
+main ()
+{
+return xmlInitParser ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_xml2_xmlInitParser=yes
+else
+  ac_cv_lib_xml2_xmlInitParser=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_xml2_xmlInitParser" >&5
+$as_echo "$ac_cv_lib_xml2_xmlInitParser" >&6; }
+if test "x$ac_cv_lib_xml2_xmlInitParser" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+@%:@define HAVE_LIBXML2 1
+_ACEOF
+
+  LIBS="-lxml2 $LIBS"
+
+else
+  as_fn_error $? "could not find libxml2" "$LINENO" 5
+fi
+
+
+
+
+LIBS="$LIBS_SAVE"
+
+
+# ===========================================================================
+# Detect if libxslt is installed
+# ===========================================================================
+
+
+@%:@ Check whether --with-xsltconfig was given.
+if test "${with_xsltconfig+set}" = set; then :
+  withval=$with_xsltconfig; XSLTCONFIG="$withval"
+else
+  XSLTCONFIG=""
+fi
+
+
+if test "x$XSLTCONFIG" = "x"; then
+	# XSLTCONFIG was not specified, so search within the current path
+	# Extract the first word of "xslt-config", so it can be a program name with args.
+set dummy xslt-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_XSLTCONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $XSLTCONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_XSLTCONFIG="$XSLTCONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_XSLTCONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+XSLTCONFIG=$ac_cv_path_XSLTCONFIG
+if test -n "$XSLTCONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XSLTCONFIG" >&5
+$as_echo "$XSLTCONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+	# If we couldn't find xslt-config, display a warning
+	if test "x$XSLTCONFIG" = "x"; then
+		as_fn_error $? "could not find xslt-config from libxslt within the current path. You may need to try re-running configure with a --with-xtltconfig parameter." "$LINENO" 5
+	fi
+else
+	# XSLTCONFIG was specified; display a message to the user
+	if test "x$XSLTCONFIG" = "xyes"; then
+		as_fn_error $? "you must Specifies a parameter to --with-xsltconfig, e.g. --with-xsltconfig=/path/to/xslt-config" "$LINENO" 5
+	else
+		if test -f $XSLTCONFIG; then
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Using user-specified xslt-config file: $XSLTCONFIG" >&5
+$as_echo "Using user-specified xslt-config file: $XSLTCONFIG" >&6; }
+		else
+			as_fn_error $? "the user-specified xslt-config file $XSLTCONFIG does not exist" "$LINENO" 5
+		fi	
+	fi
+fi
+
+# Extract the linker and include flags 
+XSLT_LDFLAGS=`$XSLTCONFIG --libs`
+XSLT_CPPFLAGS=`$XSLTCONFIG --cflags`
+
+# Check headers file
+CPPFLAGS_SAVE="$CPPFLAGS"
+CPPFLAGS="$XSLT_CPPFLAGS"
+for ac_header in libxslt/xslt.h libxslt/xsltInternals.h libxslt/transform.h libxslt/xsltutils.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+@%:@define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+ 
+else
+  as_fn_error $? "could not find headers include related to libxlst" "$LINENO" 5
+fi
+
+done
+
+
+
+
+
+#============================================================================
+# Detect if gdal is installed
+#============================================================================
+
+
+@%:@ Check whether --with-gdal-config was given.
+if test "${with_gdal_config+set}" = set; then :
+  withval=$with_gdal_config; GDAL_CONFIG="$withval"
+else
+  GDAL_CONFIG=""
+fi
+
+if test -z $GDAL_CONFIG;
+then
+	# Extract the first word of "gdal-config", so it can be a program name with args.
+set dummy gdal-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_GDAL_CONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $GDAL_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_GDAL_CONFIG="$GDAL_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_GDAL_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+GDAL_CONFIG=$ac_cv_path_GDAL_CONFIG
+if test -n "$GDAL_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GDAL_CONFIG" >&5
+$as_echo "$GDAL_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+	if test -z $GDAL_CONFIG; 
+	then
+		as_fn_error $? "could not find gdal-config from libgdal within the current path. You may need to try re-running configure with a --with-gdal-config parameter." "$LINENO" 5
+	fi
+	
+else
+	if test -f $GDAL_CONFIG; then
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Using user-specified gdal-config file: $GDAL_CONFIG" >&5
+$as_echo "Using user-specified gdal-config file: $GDAL_CONFIG" >&6; }
+	else
+		as_fn_error $? "the user-specified gdal-config file $GDAL_CONFIG does not exist" "$LINENO" 5
+	fi
+fi
+
+GDAL_CFLAGS="`$GDAL_CONFIG --cflags`"
+GDAL_LIBS="`$GDAL_CONFIG --libs`"
+
+
+
+
+# ===========================================================================
+# Detect if proj is installed
+# ===========================================================================
+
+
+@%:@ Check whether --with-proj was given.
+if test "${with_proj+set}" = set; then :
+  withval=$with_proj; PROJPATH="$withval"
+else
+  PROJPATH=""
+fi
+
+
+# Extract the linker and include flags
+PROJ_LDFLAGS="-L$PROJPATH/lib"
+PROJ_CPPFLAGS="-I$PROJPATH/include"
+
+# Check headers file
+CPPFLAGS_SAVE="$CPPFLAGS"
+CPPFLAGS="$PROJ_CPPFLAGS"
+for ac_header in proj_api.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "proj_api.h" "ac_cv_header_proj_api_h" "$ac_includes_default"
+if test "x$ac_cv_header_proj_api_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+@%:@define HAVE_PROJ_API_H 1
+_ACEOF
+ 
+else
+  as_fn_error $? "could not find headers include related to PROJ4" "$LINENO" 5
+fi
+
+done
+
+
+
+
+
+# ===========================================================================
+# Detect if libgeos is installed
+# ===========================================================================
+
+
+@%:@ Check whether --with-geosconfig was given.
+if test "${with_geosconfig+set}" = set; then :
+  withval=$with_geosconfig; GEOSCONFIG="$withval"
+else
+  GEOSCONFIG=""
+fi
+
+
+if test "x$GEOSCONFIG" = "x"; then
+	# GEOSCONFIG was not specified, so search within the current path
+	# Extract the first word of "geos-config", so it can be a program name with args.
+set dummy geos-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_GEOSCONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $GEOSCONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_GEOSCONFIG="$GEOSCONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_GEOSCONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+GEOSCONFIG=$ac_cv_path_GEOSCONFIG
+if test -n "$GEOSCONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GEOSCONFIG" >&5
+$as_echo "$GEOSCONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+	# If we couldn't find geos-config, display a warning
+	if test "x$GEOSCONFIG" = "x"; then
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not find geos-config from libgeos within the current path. You may need to try re-running configure with a --with-geosconfig parameter." >&5
+$as_echo "$as_me: WARNING: could not find geos-config from libgeos within the current path. You may need to try re-running configure with a --with-geosconfig parameter." >&2;}
+	fi
+else
+	# GEOSCONFIG was specified; display a message to the user
+	if test "x$GEOSCONFIG" = "xyes"; then
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: you must Specifies a parameter to --with-geosconfig, e.g. --with-geosconfig=/path/to/geos-config" >&5
+$as_echo "$as_me: WARNING: you must Specifies a parameter to --with-geosconfig, e.g. --with-geosconfig=/path/to/geos-config" >&2;}
+	else
+		if test -f $GEOSCONFIG; then
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Using user-specified geos-config file: $GEOSCONFIG" >&5
+$as_echo "Using user-specified geos-config file: $GEOSCONFIG" >&6; }
+		else
+			as_fn_error $? "the user-specified geos-config file $GEOSCONFIG does not exist" "$LINENO" 5
+		fi	
+	fi
+fi
+
+GEOS_LDFLAGS=`$GEOSCONFIG --libs`
+GEOS_CPPFLAGS=`$GEOSCONFIG --cflags`
+
+# Check headers file
+CPPFLAGS_SAVE="$CPPFLAGS"
+CPPFLAGS="$GEOS_CPPFLAGS"
+for ac_header in geos_c.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "geos_c.h" "ac_cv_header_geos_c_h" "$ac_includes_default"
+if test "x$ac_cv_header_geos_c_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+@%:@define HAVE_GEOS_C_H 1
+_ACEOF
+ 
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not find headers include related to libgeos" >&5
+$as_echo "$as_me: WARNING: could not find headers include related to libgeos" >&2;}
+fi
+
+done
+
+
+
+
+
+
+# ===========================================================================
+# Detect if cgal is installed
+# ===========================================================================
+
+
+@%:@ Check whether --with-cgal was given.
+if test "${with_cgal+set}" = set; then :
+  withval=$with_cgal; CGALPATH="$withval"
+else
+  CGALPATH="/usr"
+fi
+
+
+
+# Check headers file
+CPPFLAGS_SAVE="$CPPFLAGS"
+CPPFLAGS="$CGAL_CPPFLAGS"
+for ac_header in CGAL/Delaunay_triangulation_2.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "CGAL/Delaunay_triangulation_2.h" "ac_cv_header_CGAL_Delaunay_triangulation_2_h" "$ac_includes_default"
+if test "x$ac_cv_header_CGAL_Delaunay_triangulation_2_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+@%:@define HAVE_CGAL_DELAUNAY_TRIANGULATION_2_H 1
+_ACEOF
+ 
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not find headers include related to libCGAL" >&5
+$as_echo "$as_me: WARNING: could not find headers include related to libCGAL" >&2;}
+fi
+
+done
+
+
+# Extract the linker and include flags
+CGAL_LDFLAGS="-L$CGALPATH/lib"
+CGAL_CPPFLAGS="-I$CGALPATH/include"
+
+
+
+
+#============================================================================
+# Detect if mapserver is installed
+#============================================================================
+
+
+@%:@ Check whether --with-mapserver was given.
+if test "${with_mapserver+set}" = set; then :
+  withval=$with_mapserver; MS_SRC_PATH="$withval"
+else
+  MS_SRC_PATH=""
+fi
+
+
+if test -z $MS_SRC_PATH;
+then
+	MS_CPPFLAGS=""
+	MS_LDFLAGS=""
+else
+       if test "x$MS_SRC_PATH" = "xmacos";
+       then
+               MS_LDFLAGS="/Library/Frameworks/MapServer.framework//Versions/6.0/MapServer -lintl"
+               MS_CPPFLAGS="-DUSE_MS `/Library/Frameworks/MapServer.framework/Programs/mapserver-config --includes` -I/Library/Frameworks/MapServer.framework/Versions/Current/Headers/ -I../mapserver "
+               { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Please make sure that ../mapserver exists and contains MapServer source tree" >&5
+$as_echo "$as_me: WARNING: Please make sure that ../mapserver exists and contains MapServer source tree" >&2;}
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using MacOS X Framework for MapServer" >&5
+$as_echo "Using MacOS X Framework for MapServer" >&6; }
+       else
+               if test -d $MS_SRC_PATH; then
+                       MS_LDFLAGS="-L$MS_SRC_PATH -lmapserver `$MS_SRC_PATH/mapserver-config --libs`"
+                       MS_CPPFLAGS="-DUSE_MS `$MS_SRC_PATH/mapserver-config --includes` `$MS_SRC_PATH/mapserver-config --cflags` -I$MS_SRC_PATH "
+               
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using user-specified MapServer src path: $MS_SRC_PATH" >&5
+$as_echo "Using user-specified MapServer src path: $MS_SRC_PATH" >&6; }
+               else
+                       as_fn_error $? "the user-specified mapserver-config file $MS_SRC_PATH does not exist" "$LINENO" 5
+               fi
+       fi
+       MS_FILE="service_internal_ms.o"
+fi
+
+MS_CFLAGS="$MS_CPPFLAGS"
+MS_LIBS="$MS_LDFLAGS"
+
+
+
+
+
+# ===========================================================================
+# Detect if python is installed
+# ===========================================================================
+
+
+@%:@ Check whether --with-python was given.
+if test "${with_python+set}" = set; then :
+  withval=$with_python; PYTHON_PATH="$withval"; PYTHON_ENABLED="-DUSE_PYTHON"
+else
+  PYTHON_ENABLED=""
+fi
+
+
+
+@%:@ Check whether --with-pyvers was given.
+if test "${with_pyvers+set}" = set; then :
+  withval=$with_pyvers; PYTHON_VERS="$withval"
+else
+  PYTHON_VERS=""
+fi
+
+
+
+if test -z "$PYTHON_ENABLED"
+then
+	PYTHON_FILE=""
+else
+	PYTHONCONFIG="$PYTHON_PATH/bin/python${PYTHON_VERS}-config"
+	PYTHON_FILE="service_internal_python.o"
+	if test  "$PYTHON_PATH" = "yes"
+	then
+		# PHP was not specified, so search within the current path
+		PYTHONCFG_PATH=`which python${PYTHON_VERS}-config`
+		if test -z "${PYTHONCFG_PATH}" ; then
+		# Extract the first word of "python-config-${PYTHON_VERS}", so it can be a program name with args.
+set dummy python-config-${PYTHON_VERS}; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PYTHONCONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $PYTHONCONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_PYTHONCONFIG="$PYTHONCONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_PYTHONCONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+PYTHONCONFIG=$ac_cv_path_PYTHONCONFIG
+if test -n "$PYTHONCONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHONCONFIG" >&5
+$as_echo "$PYTHONCONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+		else
+		# Extract the first word of "python${PYTHON_VERS}-config", so it can be a program name with args.
+set dummy python${PYTHON_VERS}-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PYTHONCONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $PYTHONCONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_PYTHONCONFIG="$PYTHONCONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_PYTHONCONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+PYTHONCONFIG=$ac_cv_path_PYTHONCONFIG
+if test -n "$PYTHONCONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHONCONFIG" >&5
+$as_echo "$PYTHONCONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+		fi
+	else
+		PYTHONCONFIG="$PYTHON_PATH/bin/python${PYTHON_VERS}-config"
+	fi
+
+	# Extract the linker and include flags 
+	PYTHON_LDFLAGS=`$PYTHONCONFIG --ldflags`
+	PYTHON_CPPFLAGS=`$PYTHONCONFIG --includes`
+
+	# Check headers file
+	CPPFLAGS_SAVE="$CPPFLAGS"
+	CPPFLAGS="$PYTHON_CPPFLAGS"
+	for ac_header in Python.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "Python.h" "ac_cv_header_Python_h" "$ac_includes_default"
+if test "x$ac_cv_header_Python_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+@%:@define HAVE_PYTHON_H 1
+_ACEOF
+ 
+else
+  as_fn_error $? "could not find headers include related to libpython" "$LINENO" 5
+fi
+
+done
+
+
+	# Ensure we can link against libphp
+	LIBS_SAVE="$LIBS"
+	LIBS="$PYTHON_LDFLAGS"
+	PY_LIB=`$PYTHONCONFIG --libs | sed -e 's/^.*\(python2\..\)$/\1/'`
+	as_ac_Lib=`$as_echo "ac_cv_lib_$PY_LIB''_PyObject_CallObject" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PyObject_CallObject in -l$PY_LIB" >&5
+$as_echo_n "checking for PyObject_CallObject in -l$PY_LIB... " >&6; }
+if eval \${$as_ac_Lib+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-l$PY_LIB  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char PyObject_CallObject ();
+int
+main ()
+{
+return PyObject_CallObject ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  eval "$as_ac_Lib=yes"
+else
+  eval "$as_ac_Lib=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+eval ac_res=\$$as_ac_Lib
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+@%:@define `$as_echo "HAVE_LIB$PY_LIB" | $as_tr_cpp` 1
+_ACEOF
+
+  LIBS="-l$PY_LIB $LIBS"
+
+else
+  as_fn_error $? "could not find libpython" "$LINENO" 5
+fi
+
+	
+	
+	LIBS="$LIBS_SAVE"
+fi
+
+
+
+
+# ===========================================================================
+# Detect if spidermonkey is installed
+# ===========================================================================
+
+
+@%:@ Check whether --with-js was given.
+if test "${with_js+set}" = set; then :
+  withval=$with_js; JSHOME="$withval";JS_ENABLED="-DUSE_JS"
+else
+  JS_ENABLED=""
+fi
+
+
+if test -z "$JS_ENABLED"
+then
+	JS_FILE=""
+else
+	JS_FILE="service_internal_js.o"
+	if test "$JSHOME" = "yes"
+	then
+
+		#on teste si on est sous debian like 
+		if test -f "/usr/bin/dpkg"
+		then
+			if test -n "`dpkg -l | grep libmozjs185-dev`"
+			then
+				JS_CPPFLAGS="-I/usr/include/js/"
+                        	JS_LDFLAGS="-L/usr/lib -lmozjs185 -lm"
+                        	JS_LIB="mozjs185"
+			else 
+				XUL_VERSION="`dpkg -l | grep xulrunner | grep dev | head -1| awk '{print $3;}' | cut -d'+' -f1`"
+				if test -n "$XUL_VERSION"
+				then
+					JS_CPPFLAGS="-I/usr/include/xulrunner-$XUL_VERSION"
+					JS_LDFLAGS="-L/usr/lib/xulrunner-$XUL_VERSION -lmozjs -lm"
+					JS_LIB="mozjs"
+				else
+					as_fn_error $? "You must install libmozjs185-dev or xulrunner-dev " "$LINENO" 5
+				fi
+			fi
+		else
+			as_fn_error $? "You must  specify your custom install of libmozjs185" "$LINENO" 5
+		fi
+	else
+		JS_CPPFLAGS="-I$JSHOME/include/js/"
+                JS_LDFLAGS="-L$JSHOME/lib -lmozjs185 -lm"
+                JS_LIB="mozjs185"
+
+	fi 
+	CPPFLAGS_SAVE="$CPPFLAGS"
+        CPPFLAGS="$JS_CPPFLAGS"
+	ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+	
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5
+$as_echo_n "checking how to run the C++ preprocessor... " >&6; }
+if test -z "$CXXCPP"; then
+  if ${ac_cv_prog_CXXCPP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+      # Double quotes because CXXCPP needs to be expanded
+    for CXXCPP in "$CXX -E" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+@%:@ifdef __STDC__
+@%:@ include <limits.h>
+@%:@else
+@%:@ include <assert.h>
+@%:@endif
+		     Syntax error
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+  
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+@%:@include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+  break
+fi
+
+    done
+    ac_cv_prog_CXXCPP=$CXXCPP
+  
+fi
+  CXXCPP=$ac_cv_prog_CXXCPP
+else
+  ac_cv_prog_CXXCPP=$CXXCPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5
+$as_echo "$CXXCPP" >&6; }
+ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+@%:@ifdef __STDC__
+@%:@ include <limits.h>
+@%:@else
+@%:@ include <assert.h>
+@%:@endif
+		     Syntax error
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+  
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+@%:@include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+  
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+for ac_header in jsapi.h
+do :
+  ac_fn_cxx_check_header_mongrel "$LINENO" "jsapi.h" "ac_cv_header_jsapi_h" "$ac_includes_default"
+if test "x$ac_cv_header_jsapi_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+@%:@define HAVE_JSAPI_H 1
+_ACEOF
+ 
+else
+  as_fn_error $? "could not find headers include related to libjs" "$LINENO" 5
+fi
+
+done
+
+
+	ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+	LIBS_SAVE="$LIBS"
+        LIBS="$JS_LDFLAGS"
+
+        as_ac_Lib=`$as_echo "ac_cv_lib_$JS_LIB''_JS_CompileFile,JS_CallFunctionName" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for JS_CompileFile,JS_CallFunctionName in -l$JS_LIB" >&5
+$as_echo_n "checking for JS_CompileFile,JS_CallFunctionName in -l$JS_LIB... " >&6; }
+if eval \${$as_ac_Lib+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-l$JS_LIB  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char JS_CompileFile,JS_CallFunctionName ();
+int
+main ()
+{
+return JS_CompileFile,JS_CallFunctionName ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  eval "$as_ac_Lib=yes"
+else
+  eval "$as_ac_Lib=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+eval ac_res=\$$as_ac_Lib
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+@%:@define `$as_echo "HAVE_LIB$JS_LIB" | $as_tr_cpp` 1
+_ACEOF
+
+  LIBS="-l$JS_LIB $LIBS"
+
+else
+  as_fn_error $? "could not find $JS_LIB" "$LINENO" 5
+fi
+
+	LIBS="$LIBS_SAVE"
+	
+        
+        
+fi
+
+
+
+
+# ===========================================================================
+# Detect if php is installed
+# ===========================================================================
+
+
+@%:@ Check whether --with-php was given.
+if test "${with_php+set}" = set; then :
+  withval=$with_php; PHP_PATH="$withval"; PHP_ENABLED="-DUSE_PHP"
+else
+  PHP_ENABLED=""
+fi
+
+
+
+if test -z "$PHP_ENABLED"
+then
+	PHP_FILE=""
+else
+	PHPCONFIG="$PHP_PATH/bin/php-config"
+	PHP_FILE="service_internal_php.o"
+	if test  "$PHP_PATH" = "yes"
+	then
+		# PHP was not specified, so search within the current path
+		# Extract the first word of "php-config", so it can be a program name with args.
+set dummy php-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PHPCONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $PHPCONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_PHPCONFIG="$PHPCONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_PHPCONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+PHPCONFIG=$ac_cv_path_PHPCONFIG
+if test -n "$PHPCONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PHPCONFIG" >&5
+$as_echo "$PHPCONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+	else
+		PHPCONFIG="$PHP_PATH/bin/php-config"
+	fi
+
+	# Extract the linker and include flags 
+	PHP_LDFLAGS="-L/`$PHPCONFIG --prefix`/lib -lphp5"
+	PHP_CPPFLAGS=`$PHPCONFIG --includes`
+
+	# Check headers file
+	CPPFLAGS_SAVE="$CPPFLAGS"
+	CPPFLAGS="$PHP_CPPFLAGS"
+	for ac_header in sapi/embed/php_embed.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "sapi/embed/php_embed.h" "ac_cv_header_sapi_embed_php_embed_h" "$ac_includes_default"
+if test "x$ac_cv_header_sapi_embed_php_embed_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+@%:@define HAVE_SAPI_EMBED_PHP_EMBED_H 1
+_ACEOF
+ 
+else
+  as_fn_error $? "could not find headers include related to libphp" "$LINENO" 5
+fi
+
+done
+
+
+	# Ensure we can link against libphp
+	LIBS_SAVE="$LIBS"
+	LIBS="$PHP_LDFLAGS"
+	# Shouldn't we get php here rather than php5 :) ??
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for call_user_function in -lphp5" >&5
+$as_echo_n "checking for call_user_function in -lphp5... " >&6; }
+if ${ac_cv_lib_php5_call_user_function+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lphp5  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char call_user_function ();
+int
+main ()
+{
+return call_user_function ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_php5_call_user_function=yes
+else
+  ac_cv_lib_php5_call_user_function=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_php5_call_user_function" >&5
+$as_echo "$ac_cv_lib_php5_call_user_function" >&6; }
+if test "x$ac_cv_lib_php5_call_user_function" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+@%:@define HAVE_LIBPHP5 1
+_ACEOF
+
+  LIBS="-lphp5 $LIBS"
+
+else
+  as_fn_error $? "could not find libphp" "$LINENO" 5
+fi
+
+	LIBS="$LIBS_SAVE"
+	
+	
+fi
+
+
+
+
+# ===========================================================================
+# Detect if java is installed
+# ===========================================================================
+
+
+@%:@ Check whether --with-java was given.
+if test "${with_java+set}" = set; then :
+  withval=$with_java; JDKHOME="$withval"; JAVA_ENABLED="-DUSE_JAVA"
+else
+  JAVA_ENABLED=""
+fi
+
+
+if test -z "$JAVA_ENABLED"
+then
+	JAVA_FILE=""
+else
+	JAVA_FILE="service_internal_java.o"
+	if test "x$JDKHOME" = "x"; 
+	then
+		as_fn_error $? "could not find java installation path within the current path. You may need to try re-running configure with a --with-java parameter." "$LINENO" 5
+	fi	# JAVA was specified; display a message to the user
+	if test "x$JDKHOME" = "xyes"; 
+	then
+		as_fn_error $? "you must specify a parameter to --with-java, e.g. --with-java=/path/to/java" "$LINENO" 5
+	fi
+
+	# Extract the linker and include flags
+	if test "x$JDKHOME" = "xmacos";
+	then
+		JAVA_LDFLAGS="-framework JavaVM"
+		JAVA_CPPFLAGS="-I/Applications/Xcode.app/Contents/Developer//Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/System/Library/Frameworks/JavaVM.framework/Versions/A/Headers/"
+	else
+		if test -d "$JDKHOME/jre/lib/i386";
+		then
+			JAVA_LDFLAGS="-L$JDKHOME/jre/lib/i386/server/ -ljvm -lpthread"
+			JAVA_CPPFLAGS="-I$JDKHOME/include -I$JDKHOME/include/linux"
+		else
+			JAVA_LDFLAGS="-L$JDKHOME/jre/lib/amd64/server/ -ljvm -lpthread"
+			JAVA_CPPFLAGS="-I$JDKHOME/include -I$JDKHOME/include/linux"
+		fi
+	fi
+
+	# Check headers file (second time we check that in fact)
+	CPPFLAGS_SAVE="$CPPFLAGS"
+	CPPFLAGS="$JAVA_CPPFLAGS"
+	for ac_header in jni.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "jni.h" "ac_cv_header_jni_h" "$ac_includes_default"
+if test "x$ac_cv_header_jni_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+@%:@define HAVE_JNI_H 1
+_ACEOF
+ 
+else
+  as_fn_error $? "could not find jni.h file" "$LINENO" 5
+fi
+
+done
+
+
+	# Ensure we can link against libjava
+	LIBS_SAVE="$LIBS"
+	LIBS="$JAVA_LDFLAGS"
+	if test "x$JDKHOME" != "xmacos";
+	then
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for JNI_CreateJavaVM in -ljvm" >&5
+$as_echo_n "checking for JNI_CreateJavaVM in -ljvm... " >&6; }
+if ${ac_cv_lib_jvm_JNI_CreateJavaVM+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ljvm  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char JNI_CreateJavaVM ();
+int
+main ()
+{
+return JNI_CreateJavaVM ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_jvm_JNI_CreateJavaVM=yes
+else
+  ac_cv_lib_jvm_JNI_CreateJavaVM=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_jvm_JNI_CreateJavaVM" >&5
+$as_echo "$ac_cv_lib_jvm_JNI_CreateJavaVM" >&6; }
+if test "x$ac_cv_lib_jvm_JNI_CreateJavaVM" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+@%:@define HAVE_LIBJVM 1
+_ACEOF
+
+  LIBS="-ljvm $LIBS"
+
+else
+  as_fn_error $? "could not find libjvm" "$LINENO" 5
+fi
+
+	fi
+	LIBS="$LIBS_SAVE"
+
+	
+	
+fi 
+
+
+
+
+# ===========================================================================
+# Detect if ruby is installed
+# ===========================================================================
+
+@%:@ Check whether --with-ruby was given.
+if test "${with_ruby+set}" = set; then :
+  withval=$with_ruby; RUBY_PATH="$withval"; RUBY_ENABLED="-DUSE_RUBY"
+else
+  RUBY_ENABLED=""
+fi
+
+
+
+@%:@ Check whether --with-rvers was given.
+if test "${with_rvers+set}" = set; then :
+  withval=$with_rvers; RUBY_VERS="$withval"
+else
+  RUBY_VERS=""
+fi
+
+
+
+if test -z "$RUBY_ENABLED"
+then
+	RUBY_FILE=""
+else
+	RUBY_FILE="service_internal_ruby.o"
+
+	# Extract the linker and include flags 
+	RUBY_LDFLAGS="-lruby"
+	RUBY_CPPFLAGS="-I$RUBY_PATH -I$RUBY_PATH/x86_64-darwin13.0/ -DZRUBY_VERSION=$RUBY_VERS"
+
+	# Check headers file
+	CPPFLAGS_SAVE="$CPPFLAGS"
+	CPPFLAGS="$RUBY_CPPFLAGS"
+	for ac_header in ruby.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "ruby.h" "ac_cv_header_ruby_h" "$ac_includes_default"
+if test "x$ac_cv_header_ruby_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+@%:@define HAVE_RUBY_H 1
+_ACEOF
+ 
+else
+  as_fn_error $? "could not find headers include related to libruby" "$LINENO" 5
+fi
+
+done
+
+
+	# Ensure we can link against libphp
+	LIBS_SAVE="$LIBS"
+	LIBS="$RUBY_LDFLAGS"
+	# AC_CHECK_LIB([lruby], [PyObject_CallObject], [], [AC_MSG_ERROR([could not find libpython])], [])
+	LIBS="$LIBS_SAVE"
+	
+	
+fi
+
+
+
+
+# ===========================================================================
+# Detect if perl is installed
+# ===========================================================================
+
+
+@%:@ Check whether --with-perl was given.
+if test "${with_perl+set}" = set; then :
+  withval=$with_perl; PERL_PATH="$withval"; PERL_ENABLED="-DUSE_PERL"
+else
+  PERL_ENABLED=""
+fi
+
+
+
+if test -z "$PERL_ENABLED"
+then
+	PERL_FILE=""
+else
+	PERL_FILE="service_internal_perl.o"
+	if test  "$PERL_PATH" = "yes"
+	then
+		# Perl was not specified, so search within the current path
+		# Extract the first word of "perl", so it can be a program name with args.
+set dummy perl; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PERLCONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $PERLCONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_PERLCONFIG="$PERLCONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_PERLCONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+PERLCONFIG=$ac_cv_path_PERLCONFIG
+if test -n "$PERLCONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERLCONFIG" >&5
+$as_echo "$PERLCONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+	else
+		PERLCONFIG="$PERL_PATH/bin/perl"
+	fi
+
+	# Extract the linker and include flags 
+	PERL_LDFLAGS=`$PERLCONFIG -MExtUtils::Embed -e ldopts`
+	PERL_CPPFLAGS=`$PERLCONFIG -MExtUtils::Embed -e ccopts`
+
+	# Check headers file
+	CPPFLAGS_SAVE="$CPPFLAGS"
+	CPPFLAGS="$PERL_CPPFLAGS"
+	for ac_header in EXTERN.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "EXTERN.h" "ac_cv_header_EXTERN_h" "$ac_includes_default"
+if test "x$ac_cv_header_EXTERN_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+@%:@define HAVE_EXTERN_H 1
+_ACEOF
+ 
+else
+  as_fn_error $? "could not find headers include related to libperl" "$LINENO" 5
+fi
+
+done
+
+
+	
+	
+fi
+
+
+
+
+# ===========================================================================
+# Detect if otb is available
+# ===========================================================================
+
+
+@%:@ Check whether --with-itk was given.
+if test "${with_itk+set}" = set; then :
+  withval=$with_itk; ITKPATH="$withval"
+else
+  ITKPATH=""
+fi
+
+
+
+@%:@ Check whether --with-itk-version was given.
+if test "${with_itk_version+set}" = set; then :
+  withval=$with_itk_version; ITKVERS="$withval"
+else
+  ITKVERS=""
+fi
+
+
+
+@%:@ Check whether --with-otb was given.
+if test "${with_otb+set}" = set; then :
+  withval=$with_otb; OTBPATH="$withval"
+else
+  OTBPATH=""
+fi
+
+
+if test -z "$OTBPATH"
+then
+	OTB_LDFLAGS=""
+	OTB_CPPFLAGS=""
+	OTB_FILE=""
+	OTB_ENABLED=""
+else
+	if test -z "$ITKVERS" 
+    	then
+		ITKVERS="4.5"
+    	fi
+	OTB_ENABLED="-DUSE_OTB"
+	OTB_LDFLAGS="-L$OTBPATH/lib/otb -lOTBIO -lOTBCommon -lOTBApplicationEngine -L$ITKPATH/lib -lITKBiasCorrection-$ITKVERS -lITKCommon-$ITKVERS -lITKIOImageBase-$ITKVERS -lITKKLMRegionGrowing-$ITKVERS -lITKLabelMap-$ITKVERS -lITKMesh-$ITKVERS -lITKMetaIO-$ITKVERS -lITKOptimizers-$ITKVERS -lITKPath-$ITKVERS -lITKPolynomials-$ITKVERS -lITKQuadEdgeMesh-$ITKVERS -lITKSpatialObjects-$ITKVERS -lITKStatistics-$ITKVERS -lITKVNLInstantiation-$ITKVERS -lITKWatersheds-$ITKVERS -litkNetlibSlatec-$ITKVE [...]
+	OTB_CPPFLAGS="-I$OTBPATH/include/otb/ApplicationEngine -I$OTBPATH/include/otb/Common -I$ITKPATH/include/ITK-$ITKVERS -I$OTBPATH/include/otb/Utilities/ITK -I$OTBPATH/include/otb/ -I$OTBPATH/include/otb/IO -I$OTBPATH/include/otb/UtilitiesAdapters/OssimAdapters -I$OTBPATH/include/otb/UtilitiesAdapters/CurlAdapters -I$OTBPATH/include/otb/Utilities/BGL -I$OTBPATH/include/otb/UtilitiesAdapters/ITKPendingPatches -I$OTBPATH/include/otb/Utilities/otbconfigfile $GDAL_CFLAGS"
+	OTB_FILE="otbZooWatcher.o service_internal_otb.o"
+	
+	ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+	# Check headers file
+	CPPFLAGS_SAVE="$CPPFLAGS"
+	CPPFLAGS="$OTB_CPPFLAGS"
+	LDFLAGS_SAVE="$LDFLAGS"
+	LIBS="$LIBS_SAVE $OTB_LDFLAGS"
+	for ac_header in otbWrapperApplication.h otbWrapperInputImageListParameter.h otbWrapperApplicationRegistry.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_cxx_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+@%:@define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+ 
+else
+  as_fn_error $? "could not find header file $i related to OTB" "$LINENO" 5
+fi
+
+done
+
+	ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+	ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+	LDFLAGS_SAVE="$LDFLAGS"
+	LDFLAGS="$OTB_LDFLAGS"
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include "otbWrapperApplication.h",std::vector<std::string> list = otb::Wrapwper::ApplicationRegistry::GetAvailableApplication();
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: checking for GetAvailableApplication... yes" >&5
+$as_echo "checking for GetAvailableApplication... yes" >&6; }
+else
+  as_fn_error $? "checking for GetAvailableApplication... failed" "$LINENO" 5
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+	LDFLAGS="$LDFLAGS_SAVE"
+			
+fi
+
+
+
+
+
+# ===========================================================================
+# Detect if saga-gis is available
+# ===========================================================================
+
+
+@%:@ Check whether --with-wx-config was given.
+if test "${with_wx_config+set}" = set; then :
+  withval=$with_wx_config; WXCFG="$withval"
+else
+  WXCFG=""
+fi
+
+
+
+@%:@ Check whether --with-saga was given.
+if test "${with_saga+set}" = set; then :
+  withval=$with_saga; SAGAPATH="$withval"
+else
+  SAGAPATH=""
+fi
+
+
+if test -z "$SAGAPATH"
+then
+	SAGA_LDFLAGS=""
+	SAGA_CPPFLAGS=""
+	SAGA_FILE=""
+	SAGA_ENABLED=""
+else
+	if test -z "$WXCFG" ; then
+	   WXCFG="$(which wx-config)"
+	fi
+	if test "`$WXCFG --list | grep unicode`" == "" ; then
+	   as_fn_error $? "SAGA requires a unicode build of wxGTK" "$LINENO" 5
+	fi
+	WX_ISSUE="-D_WX_WXCRTVARARG_H_"
+	SAGA_DEFS="-D_SAGA_LINUX -D_TYPEDEF_BYTE -D_TYPEDEF_WORD -DMODULE_LIBRARY_PATH=\\\"$SAGAPATH/lib/saga\\\""
+	SAGA_CPPFLAGS=" -fPIC -I$SAGAPATH/include/saga/saga_core/saga_api/ `$WXCFG --unicode=yes --static=no --cxxflags` -D_SAGA_UNICODE $SAGA_DEFS $WX_ISSUE"
+	SAGA_LDFLAGS="-fPIC `$WXCFG --unicode=yes --static=no --libs` -lsaga_api"
+	SAGA_ENABLED="-DUSE_SAGA"
+	SAGA_FILE="service_internal_saga.o"
+	
+	ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+	# Check headers file
+	CPPFLAGS_SAVE="$CPPFLAGS"
+	CPPFLAGS="$SAGA_CPPFLAGS"
+	LIBS_SAVE="$LIBS"
+	LIBS="$SAGA_LDFLAGS"
+	for ac_header in module_library.h
+do :
+  ac_fn_cxx_check_header_mongrel "$LINENO" "module_library.h" "ac_cv_header_module_library_h" "$ac_includes_default"
+if test "x$ac_cv_header_module_library_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+@%:@define HAVE_MODULE_LIBRARY_H 1
+_ACEOF
+ 
+else
+  as_fn_error $? "could not find header file $i related to SAGA-GIS" "$LINENO" 5
+fi
+
+done
+
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include "module_library.h",SG_Get_Module_Library_Manager();
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: checking for SG_Get_Module_Library_Manager... yes" >&5
+$as_echo "checking for SG_Get_Module_Library_Manager... yes" >&6; }
+else
+  as_fn_error $? "checking for SG_Get_Module_Library_Manager... failed" "$LINENO" 5
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+	LIBS="$LIBS_SAVE"
+	ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+fi
+
+
+
+
+
+ac_config_files="$ac_config_files Makefile"
+
+ac_config_files="$ac_config_files ZOOMakefile.opts"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes: double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \.
+      sed -n \
+	"s/'/'\\\\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    if test "x$cache_file" != "x/dev/null"; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+      if test ! -f "$cache_file" || test -h "$cache_file"; then
+	cat confcache >"$cache_file"
+      else
+        case $cache_file in #(
+        */* | ?:*)
+	  mv -f confcache "$cache_file"$$ &&
+	  mv -f "$cache_file"$$ "$cache_file" ;; #(
+        *)
+	  mv -f confcache "$cache_file" ;;
+	esac
+      fi
+    fi
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then branch to the quote section.  Otherwise,
+# look for a macro that doesn't take arguments.
+ac_script='
+:mline
+/\\$/{
+ N
+ s,\\\n,,
+ b mline
+}
+t clear
+:clear
+s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 (][^	 (]*([^)]*)\)[	 ]*\(.*\)/-D\1=\2/g
+t quote
+s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 ][^	 ]*\)[	 ]*\(.*\)/-D\1=\2/g
+t quote
+b any
+:quote
+s/[	 `~#$^&*(){}\\|;'\''"<>?]/\\&/g
+s/\[/\\&/g
+s/\]/\\&/g
+s/\$/$$/g
+H
+:any
+${
+	g
+	s/^\n//
+	s/\n/ /g
+	p
+}
+'
+DEFS=`sed -n "$ac_script" confdefs.h`
+
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIB@&t at OBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIB@&t at OBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in @%:@(
+  *posix*) :
+    set -o posix ;; @%:@(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in @%:@(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in @%:@((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+@%:@ as_fn_error STATUS ERROR [LINENO LOG_FD]
+@%:@ ----------------------------------------
+@%:@ Output "`basename @S|@0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+@%:@ provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+@%:@ script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} @%:@ as_fn_error
+
+
+@%:@ as_fn_set_status STATUS
+@%:@ -----------------------
+@%:@ Set @S|@? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} @%:@ as_fn_set_status
+
+@%:@ as_fn_exit STATUS
+@%:@ -----------------
+@%:@ Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} @%:@ as_fn_exit
+
+@%:@ as_fn_unset VAR
+@%:@ ---------------
+@%:@ Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+@%:@ as_fn_append VAR VALUE
+@%:@ ----------------------
+@%:@ Append the text in VALUE to the end of the definition contained in VAR. Take
+@%:@ advantage of any shell optimizations that allow amortized linear growth over
+@%:@ repeated appends, instead of the typical quadratic growth present in naive
+@%:@ implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+@%:@ as_fn_arith ARG...
+@%:@ ------------------
+@%:@ Perform arithmetic evaluation on the ARGs, and store the result in the
+@%:@ global @S|@as_val. Take advantage of shells that can avoid forks. The arguments
+@%:@ must be portable across @S|@(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in @%:@(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+@%:@ as_fn_mkdir_p
+@%:@ -------------
+@%:@ Create "@S|@as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} @%:@ as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+
+@%:@ as_fn_executable_p FILE
+@%:@ -----------------------
+@%:@ Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} @%:@ as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by ZOO Kernel $as_me 1.5.0, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration.  Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+      --config     print configuration, then exit
+  -q, --quiet, --silent
+                   do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+      --file=FILE[:TEMPLATE] 
+                   instantiate the configuration file FILE
+
+Configuration files:
+$config_files
+
+Report bugs to <bugs at zoo-project.org>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+ZOO Kernel config.status 1.5.0
+configured by $0, generated by GNU Autoconf 2.69,
+  with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=?*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  --*=)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    $as_echo "$ac_cs_version"; exit ;;
+  --config | --confi | --conf | --con | --co | --c )
+    $as_echo "$ac_cs_config"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    '') as_fn_error $? "missing file argument" ;;
+    esac
+    as_fn_append CONFIG_FILES " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --he | --h |  --help | --hel | -h )
+    $as_echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+  *) as_fn_append ac_config_targets " $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  shift
+  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+  CONFIG_SHELL='$SHELL'
+  export CONFIG_SHELL
+  exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../@%:@@%:@ /;s/...$/ @%:@@%:@/;p;x;p;x' <<_ASBOX
+@%:@@%:@ Running $as_me. @%:@@%:@
+_ASBOX
+  $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+    "ZOOMakefile.opts") CONFIG_FILES="$CONFIG_FILES ZOOMakefile.opts" ;;
+
+  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp= ac_tmp=
+  trap 'exit_status=$?
+  : "${ac_tmp:=$tmp}"
+  { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+  trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+  eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+  ac_cs_awk_cr='\\r'
+else
+  ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+  echo "cat >conf$$subs.awk <<_ACEOF" &&
+  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+  echo "_ACEOF"
+} >conf$$subs.sh ||
+  as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  . ./conf$$subs.sh ||
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+  if test $ac_delim_n = $ac_delim_num; then
+    break
+  elif $ac_last_try; then
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+  N
+  s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+  for (key in S) S_is_set[key] = 1
+  FS = ""
+
+}
+{
+  line = $ 0
+  nfields = split(line, field, "@")
+  substed = 0
+  len = length(field[1])
+  for (i = 2; i < nfields; i++) {
+    key = field[i]
+    keylen = length(key)
+    if (S_is_set[key]) {
+      value = S[key]
+      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+      len += length(value) + length(field[++i])
+      substed = 1
+    } else
+      len += 1 + keylen
+  }
+
+  print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+  cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+  || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[	 ]*VPATH[	 ]*=[	 ]*/{
+h
+s///
+s/^/:/
+s/[	 ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[	 ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[	 ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+
+eval set X "  :F $CONFIG_FILES      "
+shift
+for ac_tag
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$ac_tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
+	 # because $ac_f cannot contain `:'.
+	 test -f "$ac_f" ||
+	   case $ac_f in
+	   [\\/$]*) false;;
+	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+	   esac ||
+	   as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+      esac
+      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+      as_fn_append ac_file_inputs " '$ac_f'"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input='Generated from '`
+	  $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+	`' by configure.'
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+    fi
+    # Neutralize special characters interpreted by sed in replacement strings.
+    case $configure_input in #(
+    *\&* | *\|* | *\\* )
+       ac_sed_conf_input=`$as_echo "$configure_input" |
+       sed 's/[\\\\&|]/\\\\&/g'`;; #(
+    *) ac_sed_conf_input=$configure_input;;
+    esac
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$ac_tmp/stdin" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  as_dir="$ac_dir"; as_fn_mkdir_p
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+  s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+  >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' \
+      "$ac_tmp/out"`; test -z "$ac_out"; } &&
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&2;}
+
+  rm -f "$ac_tmp/stdin"
+  case $ac_file in
+  -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+  *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+  esac \
+  || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+  
+  
+  
+  esac
+
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+  as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
diff --git a/zoo-project/zoo-kernel/autom4te.cache/requests b/zoo-project/zoo-kernel/autom4te.cache/requests
new file mode 100644
index 0000000..287911c
--- /dev/null
+++ b/zoo-project/zoo-kernel/autom4te.cache/requests
@@ -0,0 +1,77 @@
+# This file was generated.
+# It contains the lists of macros which have been traced.
+# It can be safely removed.
+
+ at request = (
+             bless( [
+                      '0',
+                      1,
+                      [
+                        '/usr/local/Cellar/autoconf/2.69/share/autoconf'
+                      ],
+                      [
+                        '/usr/local/Cellar/autoconf/2.69/share/autoconf/autoconf/autoconf.m4f',
+                        'configure.ac'
+                      ],
+                      {
+                        '_AM_COND_ELSE' => 1,
+                        'sinclude' => 1,
+                        'include' => 1,
+                        'AC_DEFINE_TRACE_LITERAL' => 1,
+                        '_AM_COND_IF' => 1,
+                        'AC_CONFIG_AUX_DIR' => 1,
+                        'AM_XGETTEXT_OPTION' => 1,
+                        'AM_ENABLE_MULTILIB' => 1,
+                        'AM_AUTOMAKE_VERSION' => 1,
+                        'AC_SUBST_TRACE' => 1,
+                        'AC_CONFIG_LINKS' => 1,
+                        '_LT_AC_TAGCONFIG' => 1,
+                        'AC_PROG_LIBTOOL' => 1,
+                        'AM_MAINTAINER_MODE' => 1,
+                        'AC_REQUIRE_AUX_FILE' => 1,
+                        'AC_SUBST' => 1,
+                        'AC_FC_PP_SRCEXT' => 1,
+                        'AC_INIT' => 1,
+                        'm4_pattern_forbid' => 1,
+                        '_AM_SUBST_NOTMAKE' => 1,
+                        'LT_SUPPORTED_TAG' => 1,
+                        'AM_NLS' => 1,
+                        'LT_INIT' => 1,
+                        'AC_CANONICAL_HOST' => 1,
+                        'm4_include' => 1,
+                        'AC_FC_SRCEXT' => 1,
+                        'AC_CONFIG_SUBDIRS' => 1,
+                        '_AM_COND_ENDIF' => 1,
+                        'AM_PATH_GUILE' => 1,
+                        'AM_PROG_FC_C_O' => 1,
+                        'AC_FC_PP_DEFINE' => 1,
+                        'AM_PROG_CXX_C_O' => 1,
+                        'AC_FC_FREEFORM' => 1,
+                        'AM_SILENT_RULES' => 1,
+                        'AM_MAKEFILE_INCLUDE' => 1,
+                        'AC_CANONICAL_SYSTEM' => 1,
+                        'AM_PROG_MOC' => 1,
+                        'AM_PROG_F77_C_O' => 1,
+                        'AC_CANONICAL_TARGET' => 1,
+                        'AM_CONDITIONAL' => 1,
+                        'm4_sinclude' => 1,
+                        'LT_CONFIG_LTDL_DIR' => 1,
+                        'AM_PROG_AR' => 1,
+                        'AC_CANONICAL_BUILD' => 1,
+                        'AM_INIT_AUTOMAKE' => 1,
+                        'AC_CONFIG_HEADERS' => 1,
+                        'AM_POT_TOOLS' => 1,
+                        '_AM_MAKEFILE_INCLUDE' => 1,
+                        'AC_CONFIG_FILES' => 1,
+                        'AM_GNU_GETTEXT_INTL_SUBDIR' => 1,
+                        'm4_pattern_allow' => 1,
+                        'AC_LIBSOURCE' => 1,
+                        'AC_CONFIG_LIBOBJ_DIR' => 1,
+                        '_m4_warn' => 1,
+                        'AM_GNU_GETTEXT' => 1,
+                        'AH_OUTPUT' => 1,
+                        'AM_PROG_CC_C_O' => 1
+                      }
+                    ], 'Autom4te::Request' )
+           );
+
diff --git a/zoo-project/zoo-kernel/autom4te.cache/traces.0 b/zoo-project/zoo-kernel/autom4te.cache/traces.0
new file mode 100644
index 0000000..80e374f
--- /dev/null
+++ b/zoo-project/zoo-kernel/autom4te.cache/traces.0
@@ -0,0 +1,778 @@
+m4trace:configure.ac:1: -1- AC_INIT([ZOO Kernel], [1.5.0], [bugs at zoo-project.org])
+m4trace:configure.ac:1: -1- m4_pattern_forbid([^_?A[CHUM]_])
+m4trace:configure.ac:1: -1- m4_pattern_forbid([_AC_])
+m4trace:configure.ac:1: -1- m4_pattern_forbid([^LIBOBJS$], [do not use LIBOBJS directly, use AC_LIBOBJ (see section `AC_LIBOBJ vs LIBOBJS'])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^AS_FLAGS$])
+m4trace:configure.ac:1: -1- m4_pattern_forbid([^_?m4_])
+m4trace:configure.ac:1: -1- m4_pattern_forbid([^dnl$])
+m4trace:configure.ac:1: -1- m4_pattern_forbid([^_?AS_])
+m4trace:configure.ac:1: -1- AC_SUBST([SHELL])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([SHELL])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^SHELL$])
+m4trace:configure.ac:1: -1- AC_SUBST([PATH_SEPARATOR])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([PATH_SEPARATOR])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^PATH_SEPARATOR$])
+m4trace:configure.ac:1: -1- AC_SUBST([PACKAGE_NAME], [m4_ifdef([AC_PACKAGE_NAME],      ['AC_PACKAGE_NAME'])])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([PACKAGE_NAME])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^PACKAGE_NAME$])
+m4trace:configure.ac:1: -1- AC_SUBST([PACKAGE_TARNAME], [m4_ifdef([AC_PACKAGE_TARNAME],   ['AC_PACKAGE_TARNAME'])])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([PACKAGE_TARNAME])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^PACKAGE_TARNAME$])
+m4trace:configure.ac:1: -1- AC_SUBST([PACKAGE_VERSION], [m4_ifdef([AC_PACKAGE_VERSION],   ['AC_PACKAGE_VERSION'])])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([PACKAGE_VERSION])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^PACKAGE_VERSION$])
+m4trace:configure.ac:1: -1- AC_SUBST([PACKAGE_STRING], [m4_ifdef([AC_PACKAGE_STRING],    ['AC_PACKAGE_STRING'])])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([PACKAGE_STRING])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^PACKAGE_STRING$])
+m4trace:configure.ac:1: -1- AC_SUBST([PACKAGE_BUGREPORT], [m4_ifdef([AC_PACKAGE_BUGREPORT], ['AC_PACKAGE_BUGREPORT'])])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([PACKAGE_BUGREPORT])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^PACKAGE_BUGREPORT$])
+m4trace:configure.ac:1: -1- AC_SUBST([PACKAGE_URL], [m4_ifdef([AC_PACKAGE_URL],       ['AC_PACKAGE_URL'])])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([PACKAGE_URL])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^PACKAGE_URL$])
+m4trace:configure.ac:1: -1- AC_SUBST([exec_prefix], [NONE])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([exec_prefix])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^exec_prefix$])
+m4trace:configure.ac:1: -1- AC_SUBST([prefix], [NONE])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([prefix])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^prefix$])
+m4trace:configure.ac:1: -1- AC_SUBST([program_transform_name], [s,x,x,])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([program_transform_name])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^program_transform_name$])
+m4trace:configure.ac:1: -1- AC_SUBST([bindir], ['${exec_prefix}/bin'])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([bindir])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^bindir$])
+m4trace:configure.ac:1: -1- AC_SUBST([sbindir], ['${exec_prefix}/sbin'])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([sbindir])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^sbindir$])
+m4trace:configure.ac:1: -1- AC_SUBST([libexecdir], ['${exec_prefix}/libexec'])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([libexecdir])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^libexecdir$])
+m4trace:configure.ac:1: -1- AC_SUBST([datarootdir], ['${prefix}/share'])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([datarootdir])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^datarootdir$])
+m4trace:configure.ac:1: -1- AC_SUBST([datadir], ['${datarootdir}'])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([datadir])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^datadir$])
+m4trace:configure.ac:1: -1- AC_SUBST([sysconfdir], ['${prefix}/etc'])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([sysconfdir])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^sysconfdir$])
+m4trace:configure.ac:1: -1- AC_SUBST([sharedstatedir], ['${prefix}/com'])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([sharedstatedir])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^sharedstatedir$])
+m4trace:configure.ac:1: -1- AC_SUBST([localstatedir], ['${prefix}/var'])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([localstatedir])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^localstatedir$])
+m4trace:configure.ac:1: -1- AC_SUBST([includedir], ['${prefix}/include'])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([includedir])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^includedir$])
+m4trace:configure.ac:1: -1- AC_SUBST([oldincludedir], ['/usr/include'])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([oldincludedir])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^oldincludedir$])
+m4trace:configure.ac:1: -1- AC_SUBST([docdir], [m4_ifset([AC_PACKAGE_TARNAME],
+				     ['${datarootdir}/doc/${PACKAGE_TARNAME}'],
+				     ['${datarootdir}/doc/${PACKAGE}'])])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([docdir])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^docdir$])
+m4trace:configure.ac:1: -1- AC_SUBST([infodir], ['${datarootdir}/info'])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([infodir])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^infodir$])
+m4trace:configure.ac:1: -1- AC_SUBST([htmldir], ['${docdir}'])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([htmldir])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^htmldir$])
+m4trace:configure.ac:1: -1- AC_SUBST([dvidir], ['${docdir}'])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([dvidir])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^dvidir$])
+m4trace:configure.ac:1: -1- AC_SUBST([pdfdir], ['${docdir}'])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([pdfdir])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^pdfdir$])
+m4trace:configure.ac:1: -1- AC_SUBST([psdir], ['${docdir}'])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([psdir])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^psdir$])
+m4trace:configure.ac:1: -1- AC_SUBST([libdir], ['${exec_prefix}/lib'])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([libdir])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^libdir$])
+m4trace:configure.ac:1: -1- AC_SUBST([localedir], ['${datarootdir}/locale'])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([localedir])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^localedir$])
+m4trace:configure.ac:1: -1- AC_SUBST([mandir], ['${datarootdir}/man'])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([mandir])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^mandir$])
+m4trace:configure.ac:1: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_NAME])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^PACKAGE_NAME$])
+m4trace:configure.ac:1: -1- AH_OUTPUT([PACKAGE_NAME], [/* Define to the full name of this package. */
+@%:@undef PACKAGE_NAME])
+m4trace:configure.ac:1: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_TARNAME])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^PACKAGE_TARNAME$])
+m4trace:configure.ac:1: -1- AH_OUTPUT([PACKAGE_TARNAME], [/* Define to the one symbol short name of this package. */
+@%:@undef PACKAGE_TARNAME])
+m4trace:configure.ac:1: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_VERSION])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^PACKAGE_VERSION$])
+m4trace:configure.ac:1: -1- AH_OUTPUT([PACKAGE_VERSION], [/* Define to the version of this package. */
+@%:@undef PACKAGE_VERSION])
+m4trace:configure.ac:1: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_STRING])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^PACKAGE_STRING$])
+m4trace:configure.ac:1: -1- AH_OUTPUT([PACKAGE_STRING], [/* Define to the full name and version of this package. */
+@%:@undef PACKAGE_STRING])
+m4trace:configure.ac:1: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_BUGREPORT])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^PACKAGE_BUGREPORT$])
+m4trace:configure.ac:1: -1- AH_OUTPUT([PACKAGE_BUGREPORT], [/* Define to the address where bug reports for this package should be sent. */
+@%:@undef PACKAGE_BUGREPORT])
+m4trace:configure.ac:1: -1- AC_DEFINE_TRACE_LITERAL([PACKAGE_URL])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^PACKAGE_URL$])
+m4trace:configure.ac:1: -1- AH_OUTPUT([PACKAGE_URL], [/* Define to the home page for this package. */
+@%:@undef PACKAGE_URL])
+m4trace:configure.ac:1: -1- AC_SUBST([DEFS])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([DEFS])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^DEFS$])
+m4trace:configure.ac:1: -1- AC_SUBST([ECHO_C])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([ECHO_C])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^ECHO_C$])
+m4trace:configure.ac:1: -1- AC_SUBST([ECHO_N])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([ECHO_N])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^ECHO_N$])
+m4trace:configure.ac:1: -1- AC_SUBST([ECHO_T])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([ECHO_T])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^ECHO_T$])
+m4trace:configure.ac:1: -1- AC_SUBST([LIBS])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([LIBS])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^LIBS$])
+m4trace:configure.ac:1: -1- AC_SUBST([build_alias])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([build_alias])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^build_alias$])
+m4trace:configure.ac:1: -1- AC_SUBST([host_alias])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([host_alias])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^host_alias$])
+m4trace:configure.ac:1: -1- AC_SUBST([target_alias])
+m4trace:configure.ac:1: -1- AC_SUBST_TRACE([target_alias])
+m4trace:configure.ac:1: -1- m4_pattern_allow([^target_alias$])
+m4trace:configure.ac:4: -1- AC_SUBST([YACC])
+m4trace:configure.ac:4: -1- AC_SUBST_TRACE([YACC])
+m4trace:configure.ac:4: -1- m4_pattern_allow([^YACC$])
+m4trace:configure.ac:4: -1- AC_SUBST([YACC])
+m4trace:configure.ac:4: -1- AC_SUBST_TRACE([YACC])
+m4trace:configure.ac:4: -1- m4_pattern_allow([^YACC$])
+m4trace:configure.ac:4: -1- AC_SUBST([YFLAGS])
+m4trace:configure.ac:4: -1- AC_SUBST_TRACE([YFLAGS])
+m4trace:configure.ac:4: -1- m4_pattern_allow([^YFLAGS$])
+m4trace:configure.ac:5: -1- AC_SUBST([CC])
+m4trace:configure.ac:5: -1- AC_SUBST_TRACE([CC])
+m4trace:configure.ac:5: -1- m4_pattern_allow([^CC$])
+m4trace:configure.ac:5: -1- AC_SUBST([CFLAGS])
+m4trace:configure.ac:5: -1- AC_SUBST_TRACE([CFLAGS])
+m4trace:configure.ac:5: -1- m4_pattern_allow([^CFLAGS$])
+m4trace:configure.ac:5: -1- AC_SUBST([LDFLAGS])
+m4trace:configure.ac:5: -1- AC_SUBST_TRACE([LDFLAGS])
+m4trace:configure.ac:5: -1- m4_pattern_allow([^LDFLAGS$])
+m4trace:configure.ac:5: -1- AC_SUBST([LIBS])
+m4trace:configure.ac:5: -1- AC_SUBST_TRACE([LIBS])
+m4trace:configure.ac:5: -1- m4_pattern_allow([^LIBS$])
+m4trace:configure.ac:5: -1- AC_SUBST([CPPFLAGS])
+m4trace:configure.ac:5: -1- AC_SUBST_TRACE([CPPFLAGS])
+m4trace:configure.ac:5: -1- m4_pattern_allow([^CPPFLAGS$])
+m4trace:configure.ac:5: -1- AC_SUBST([CC])
+m4trace:configure.ac:5: -1- AC_SUBST_TRACE([CC])
+m4trace:configure.ac:5: -1- m4_pattern_allow([^CC$])
+m4trace:configure.ac:5: -1- AC_SUBST([CC])
+m4trace:configure.ac:5: -1- AC_SUBST_TRACE([CC])
+m4trace:configure.ac:5: -1- m4_pattern_allow([^CC$])
+m4trace:configure.ac:5: -1- AC_SUBST([CC])
+m4trace:configure.ac:5: -1- AC_SUBST_TRACE([CC])
+m4trace:configure.ac:5: -1- m4_pattern_allow([^CC$])
+m4trace:configure.ac:5: -1- AC_SUBST([CC])
+m4trace:configure.ac:5: -1- AC_SUBST_TRACE([CC])
+m4trace:configure.ac:5: -1- m4_pattern_allow([^CC$])
+m4trace:configure.ac:5: -1- AC_SUBST([ac_ct_CC])
+m4trace:configure.ac:5: -1- AC_SUBST_TRACE([ac_ct_CC])
+m4trace:configure.ac:5: -1- m4_pattern_allow([^ac_ct_CC$])
+m4trace:configure.ac:5: -1- AC_SUBST([EXEEXT], [$ac_cv_exeext])
+m4trace:configure.ac:5: -1- AC_SUBST_TRACE([EXEEXT])
+m4trace:configure.ac:5: -1- m4_pattern_allow([^EXEEXT$])
+m4trace:configure.ac:5: -1- AC_SUBST([OBJEXT], [$ac_cv_objext])
+m4trace:configure.ac:5: -1- AC_SUBST_TRACE([OBJEXT])
+m4trace:configure.ac:5: -1- m4_pattern_allow([^OBJEXT$])
+m4trace:configure.ac:6: -1- AC_SUBST([LEX])
+m4trace:configure.ac:6: -1- AC_SUBST_TRACE([LEX])
+m4trace:configure.ac:6: -1- m4_pattern_allow([^LEX$])
+m4trace:configure.ac:6: -1- AC_SUBST([LEX_OUTPUT_ROOT], [$ac_cv_prog_lex_root])
+m4trace:configure.ac:6: -1- AC_SUBST_TRACE([LEX_OUTPUT_ROOT])
+m4trace:configure.ac:6: -1- m4_pattern_allow([^LEX_OUTPUT_ROOT$])
+m4trace:configure.ac:6: -1- AC_SUBST([LEXLIB])
+m4trace:configure.ac:6: -1- AC_SUBST_TRACE([LEXLIB])
+m4trace:configure.ac:6: -1- m4_pattern_allow([^LEXLIB$])
+m4trace:configure.ac:6: -1- AC_DEFINE_TRACE_LITERAL([YYTEXT_POINTER])
+m4trace:configure.ac:6: -1- m4_pattern_allow([^YYTEXT_POINTER$])
+m4trace:configure.ac:6: -1- AH_OUTPUT([YYTEXT_POINTER], [/* Define to 1 if `lex\' declares `yytext\' as a `char *\' by default, not a
+   `char@<:@@:>@\'. */
+@%:@undef YYTEXT_POINTER])
+m4trace:configure.ac:7: -1- AC_SUBST([CXX])
+m4trace:configure.ac:7: -1- AC_SUBST_TRACE([CXX])
+m4trace:configure.ac:7: -1- m4_pattern_allow([^CXX$])
+m4trace:configure.ac:7: -1- AC_SUBST([CXXFLAGS])
+m4trace:configure.ac:7: -1- AC_SUBST_TRACE([CXXFLAGS])
+m4trace:configure.ac:7: -1- m4_pattern_allow([^CXXFLAGS$])
+m4trace:configure.ac:7: -1- AC_SUBST([LDFLAGS])
+m4trace:configure.ac:7: -1- AC_SUBST_TRACE([LDFLAGS])
+m4trace:configure.ac:7: -1- m4_pattern_allow([^LDFLAGS$])
+m4trace:configure.ac:7: -1- AC_SUBST([LIBS])
+m4trace:configure.ac:7: -1- AC_SUBST_TRACE([LIBS])
+m4trace:configure.ac:7: -1- m4_pattern_allow([^LIBS$])
+m4trace:configure.ac:7: -1- AC_SUBST([CPPFLAGS])
+m4trace:configure.ac:7: -1- AC_SUBST_TRACE([CPPFLAGS])
+m4trace:configure.ac:7: -1- m4_pattern_allow([^CPPFLAGS$])
+m4trace:configure.ac:7: -1- AC_SUBST([CXX])
+m4trace:configure.ac:7: -1- AC_SUBST_TRACE([CXX])
+m4trace:configure.ac:7: -1- m4_pattern_allow([^CXX$])
+m4trace:configure.ac:7: -1- AC_SUBST([ac_ct_CXX])
+m4trace:configure.ac:7: -1- AC_SUBST_TRACE([ac_ct_CXX])
+m4trace:configure.ac:7: -1- m4_pattern_allow([^ac_ct_CXX$])
+m4trace:configure.ac:8: -1- AC_SUBST([SED])
+m4trace:configure.ac:8: -1- AC_SUBST_TRACE([SED])
+m4trace:configure.ac:8: -1- m4_pattern_allow([^SED$])
+m4trace:configure.ac:11: -1- AH_OUTPUT([HAVE_LIBCURL], [/* Define to 1 if you have the `curl\' library (-lcurl). */
+@%:@undef HAVE_LIBCURL])
+m4trace:configure.ac:11: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBCURL])
+m4trace:configure.ac:11: -1- m4_pattern_allow([^HAVE_LIBCURL$])
+m4trace:configure.ac:12: -1- AH_OUTPUT([HAVE_LIBDL], [/* Define to 1 if you have the `dl\' library (-ldl). */
+@%:@undef HAVE_LIBDL])
+m4trace:configure.ac:12: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBDL])
+m4trace:configure.ac:12: -1- m4_pattern_allow([^HAVE_LIBDL$])
+m4trace:configure.ac:13: -1- AH_OUTPUT([HAVE_LIBCRYPTO], [/* Define to 1 if you have the `crypto\' library (-lcrypto). */
+@%:@undef HAVE_LIBCRYPTO])
+m4trace:configure.ac:13: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBCRYPTO])
+m4trace:configure.ac:13: -1- m4_pattern_allow([^HAVE_LIBCRYPTO$])
+m4trace:configure.ac:14: -1- AH_OUTPUT([HAVE_LIBUUID], [/* Define to 1 if you have the `uuid\' library (-luuid). */
+@%:@undef HAVE_LIBUUID])
+m4trace:configure.ac:14: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBUUID])
+m4trace:configure.ac:14: -1- m4_pattern_allow([^HAVE_LIBUUID$])
+m4trace:configure.ac:17: -1- AC_SUBST([DEFAULT_LIBS])
+m4trace:configure.ac:17: -1- AC_SUBST_TRACE([DEFAULT_LIBS])
+m4trace:configure.ac:17: -1- m4_pattern_allow([^DEFAULT_LIBS$])
+m4trace:configure.ac:21: -1- AC_SUBST([CPP])
+m4trace:configure.ac:21: -1- AC_SUBST_TRACE([CPP])
+m4trace:configure.ac:21: -1- m4_pattern_allow([^CPP$])
+m4trace:configure.ac:21: -1- AC_SUBST([CPPFLAGS])
+m4trace:configure.ac:21: -1- AC_SUBST_TRACE([CPPFLAGS])
+m4trace:configure.ac:21: -1- m4_pattern_allow([^CPPFLAGS$])
+m4trace:configure.ac:21: -1- AC_SUBST([CPP])
+m4trace:configure.ac:21: -1- AC_SUBST_TRACE([CPP])
+m4trace:configure.ac:21: -1- m4_pattern_allow([^CPP$])
+m4trace:configure.ac:21: -1- AC_SUBST([GREP])
+m4trace:configure.ac:21: -1- AC_SUBST_TRACE([GREP])
+m4trace:configure.ac:21: -1- m4_pattern_allow([^GREP$])
+m4trace:configure.ac:21: -1- AC_SUBST([EGREP])
+m4trace:configure.ac:21: -1- AC_SUBST_TRACE([EGREP])
+m4trace:configure.ac:21: -1- m4_pattern_allow([^EGREP$])
+m4trace:configure.ac:21: -1- AC_DEFINE_TRACE_LITERAL([STDC_HEADERS])
+m4trace:configure.ac:21: -1- m4_pattern_allow([^STDC_HEADERS$])
+m4trace:configure.ac:21: -1- AH_OUTPUT([STDC_HEADERS], [/* Define to 1 if you have the ANSI C header files. */
+@%:@undef STDC_HEADERS])
+m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_SYS_TYPES_H], [/* Define to 1 if you have the <sys/types.h> header file. */
+@%:@undef HAVE_SYS_TYPES_H])
+m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_SYS_STAT_H], [/* Define to 1 if you have the <sys/stat.h> header file. */
+@%:@undef HAVE_SYS_STAT_H])
+m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_STDLIB_H], [/* Define to 1 if you have the <stdlib.h> header file. */
+@%:@undef HAVE_STDLIB_H])
+m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_STRING_H], [/* Define to 1 if you have the <string.h> header file. */
+@%:@undef HAVE_STRING_H])
+m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_MEMORY_H], [/* Define to 1 if you have the <memory.h> header file. */
+@%:@undef HAVE_MEMORY_H])
+m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_STRINGS_H], [/* Define to 1 if you have the <strings.h> header file. */
+@%:@undef HAVE_STRINGS_H])
+m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_INTTYPES_H], [/* Define to 1 if you have the <inttypes.h> header file. */
+@%:@undef HAVE_INTTYPES_H])
+m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_STDINT_H], [/* Define to 1 if you have the <stdint.h> header file. */
+@%:@undef HAVE_STDINT_H])
+m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_UNISTD_H], [/* Define to 1 if you have the <unistd.h> header file. */
+@%:@undef HAVE_UNISTD_H])
+m4trace:configure.ac:21: -1- AC_DEFINE_TRACE_LITERAL([size_t])
+m4trace:configure.ac:21: -1- m4_pattern_allow([^size_t$])
+m4trace:configure.ac:21: -1- AH_OUTPUT([size_t], [/* Define to `unsigned int\' if <sys/types.h> does not define. */
+@%:@undef size_t])
+m4trace:configure.ac:21: -1- AC_DEFINE_TRACE_LITERAL([HAVE_ALLOCA_H])
+m4trace:configure.ac:21: -1- m4_pattern_allow([^HAVE_ALLOCA_H$])
+m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_ALLOCA_H], [/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
+   */
+@%:@undef HAVE_ALLOCA_H])
+m4trace:configure.ac:21: -1- AC_DEFINE_TRACE_LITERAL([HAVE_ALLOCA])
+m4trace:configure.ac:21: -1- m4_pattern_allow([^HAVE_ALLOCA$])
+m4trace:configure.ac:21: -1- AH_OUTPUT([HAVE_ALLOCA], [/* Define to 1 if you have `alloca\', as a function or macro. */
+@%:@undef HAVE_ALLOCA])
+m4trace:configure.ac:21: -1- AC_LIBSOURCE([alloca.c])
+m4trace:configure.ac:21: -1- AC_SUBST([ALLOCA], [\${LIBOBJDIR}alloca.$ac_objext])
+m4trace:configure.ac:21: -1- AC_SUBST_TRACE([ALLOCA])
+m4trace:configure.ac:21: -1- m4_pattern_allow([^ALLOCA$])
+m4trace:configure.ac:21: -1- AC_DEFINE_TRACE_LITERAL([C_ALLOCA])
+m4trace:configure.ac:21: -1- m4_pattern_allow([^C_ALLOCA$])
+m4trace:configure.ac:21: -1- AH_OUTPUT([C_ALLOCA], [/* Define to 1 if using `alloca.c\'. */
+@%:@undef C_ALLOCA])
+m4trace:configure.ac:21: -1- AC_DEFINE_TRACE_LITERAL([CRAY_STACKSEG_END])
+m4trace:configure.ac:21: -1- m4_pattern_allow([^CRAY_STACKSEG_END$])
+m4trace:configure.ac:21: -1- AH_OUTPUT([CRAY_STACKSEG_END], [/* Define to one of `_getb67\', `GETB67\', `getb67\' for Cray-2 and Cray-YMP
+   systems. This function is required for `alloca.c\' support on those systems.
+   */
+@%:@undef CRAY_STACKSEG_END])
+m4trace:configure.ac:21: -1- AH_OUTPUT([STACK_DIRECTION], [/* If using the C implementation of alloca, define if you know the
+   direction of stack growth for your system; otherwise it will be
+   automatically deduced at runtime.
+	STACK_DIRECTION > 0 => grows toward higher addresses
+	STACK_DIRECTION < 0 => grows toward lower addresses
+	STACK_DIRECTION = 0 => direction of growth unknown */
+@%:@undef STACK_DIRECTION])
+m4trace:configure.ac:21: -1- AC_DEFINE_TRACE_LITERAL([STACK_DIRECTION])
+m4trace:configure.ac:21: -1- m4_pattern_allow([^STACK_DIRECTION$])
+m4trace:configure.ac:22: -1- AH_OUTPUT([HAVE_FCNTL_H], [/* Define to 1 if you have the <fcntl.h> header file. */
+@%:@undef HAVE_FCNTL_H])
+m4trace:configure.ac:22: -1- AH_OUTPUT([HAVE_INTTYPES_H], [/* Define to 1 if you have the <inttypes.h> header file. */
+@%:@undef HAVE_INTTYPES_H])
+m4trace:configure.ac:22: -1- AH_OUTPUT([HAVE_LIBINTL_H], [/* Define to 1 if you have the <libintl.h> header file. */
+@%:@undef HAVE_LIBINTL_H])
+m4trace:configure.ac:22: -1- AH_OUTPUT([HAVE_MALLOC_H], [/* Define to 1 if you have the <malloc.h> header file. */
+@%:@undef HAVE_MALLOC_H])
+m4trace:configure.ac:22: -1- AH_OUTPUT([HAVE_STDDEF_H], [/* Define to 1 if you have the <stddef.h> header file. */
+@%:@undef HAVE_STDDEF_H])
+m4trace:configure.ac:22: -1- AH_OUTPUT([HAVE_STDLIB_H], [/* Define to 1 if you have the <stdlib.h> header file. */
+@%:@undef HAVE_STDLIB_H])
+m4trace:configure.ac:22: -1- AH_OUTPUT([HAVE_STRING_H], [/* Define to 1 if you have the <string.h> header file. */
+@%:@undef HAVE_STRING_H])
+m4trace:configure.ac:22: -1- AH_OUTPUT([HAVE_UNISTD_H], [/* Define to 1 if you have the <unistd.h> header file. */
+@%:@undef HAVE_UNISTD_H])
+m4trace:configure.ac:25: -1- AC_DEFINE_TRACE_LITERAL([HAVE__BOOL])
+m4trace:configure.ac:25: -1- m4_pattern_allow([^HAVE__BOOL$])
+m4trace:configure.ac:25: -1- AH_OUTPUT([HAVE__BOOL], [/* Define to 1 if the system has the type `_Bool\'. */
+@%:@undef HAVE__BOOL])
+m4trace:configure.ac:25: -1- AC_DEFINE_TRACE_LITERAL([HAVE_STDBOOL_H])
+m4trace:configure.ac:25: -1- m4_pattern_allow([^HAVE_STDBOOL_H$])
+m4trace:configure.ac:25: -1- AH_OUTPUT([HAVE_STDBOOL_H], [/* Define to 1 if stdbool.h conforms to C99. */
+@%:@undef HAVE_STDBOOL_H])
+m4trace:configure.ac:26: -1- AC_DEFINE_TRACE_LITERAL([int16_t])
+m4trace:configure.ac:26: -1- m4_pattern_allow([^int16_t$])
+m4trace:configure.ac:26: -1- AH_OUTPUT([int16_t], [/* Define to the type of a signed integer type of width exactly 16 bits if
+   such a type exists and the standard includes do not define it. */
+@%:@undef int16_t])
+m4trace:configure.ac:27: -1- AC_DEFINE_TRACE_LITERAL([int32_t])
+m4trace:configure.ac:27: -1- m4_pattern_allow([^int32_t$])
+m4trace:configure.ac:27: -1- AH_OUTPUT([int32_t], [/* Define to the type of a signed integer type of width exactly 32 bits if
+   such a type exists and the standard includes do not define it. */
+@%:@undef int32_t])
+m4trace:configure.ac:28: -1- AC_DEFINE_TRACE_LITERAL([int8_t])
+m4trace:configure.ac:28: -1- m4_pattern_allow([^int8_t$])
+m4trace:configure.ac:28: -1- AH_OUTPUT([int8_t], [/* Define to the type of a signed integer type of width exactly 8 bits if such
+   a type exists and the standard includes do not define it. */
+@%:@undef int8_t])
+m4trace:configure.ac:29: -1- AC_DEFINE_TRACE_LITERAL([pid_t])
+m4trace:configure.ac:29: -1- m4_pattern_allow([^pid_t$])
+m4trace:configure.ac:29: -1- AH_OUTPUT([pid_t], [/* Define to `int\' if <sys/types.h> does not define. */
+@%:@undef pid_t])
+m4trace:configure.ac:30: -1- AC_DEFINE_TRACE_LITERAL([size_t])
+m4trace:configure.ac:30: -1- m4_pattern_allow([^size_t$])
+m4trace:configure.ac:30: -1- AH_OUTPUT([size_t], [/* Define to `unsigned int\' if <sys/types.h> does not define. */
+@%:@undef size_t])
+m4trace:configure.ac:31: -1- AC_DEFINE_TRACE_LITERAL([uint16_t])
+m4trace:configure.ac:31: -1- m4_pattern_allow([^uint16_t$])
+m4trace:configure.ac:31: -1- AH_OUTPUT([uint16_t], [/* Define to the type of an unsigned integer type of width exactly 16 bits if
+   such a type exists and the standard includes do not define it. */
+@%:@undef uint16_t])
+m4trace:configure.ac:32: -1- AC_DEFINE_TRACE_LITERAL([_UINT32_T])
+m4trace:configure.ac:32: -1- m4_pattern_allow([^_UINT32_T$])
+m4trace:configure.ac:32: -1- AH_OUTPUT([_UINT32_T], [/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
+   <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
+   @%:@define below would cause a syntax error. */
+@%:@undef _UINT32_T])
+m4trace:configure.ac:32: -1- AC_DEFINE_TRACE_LITERAL([uint32_t])
+m4trace:configure.ac:32: -1- m4_pattern_allow([^uint32_t$])
+m4trace:configure.ac:32: -1- AH_OUTPUT([uint32_t], [/* Define to the type of an unsigned integer type of width exactly 32 bits if
+   such a type exists and the standard includes do not define it. */
+@%:@undef uint32_t])
+m4trace:configure.ac:33: -1- AC_DEFINE_TRACE_LITERAL([_UINT8_T])
+m4trace:configure.ac:33: -1- m4_pattern_allow([^_UINT8_T$])
+m4trace:configure.ac:33: -1- AH_OUTPUT([_UINT8_T], [/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
+   <pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
+   @%:@define below would cause a syntax error. */
+@%:@undef _UINT8_T])
+m4trace:configure.ac:33: -1- AC_DEFINE_TRACE_LITERAL([uint8_t])
+m4trace:configure.ac:33: -1- m4_pattern_allow([^uint8_t$])
+m4trace:configure.ac:33: -1- AH_OUTPUT([uint8_t], [/* Define to the type of an unsigned integer type of width exactly 8 bits if
+   such a type exists and the standard includes do not define it. */
+@%:@undef uint8_t])
+m4trace:configure.ac:36: -1- AH_OUTPUT([HAVE_VFORK_H], [/* Define to 1 if you have the <vfork.h> header file. */
+@%:@undef HAVE_VFORK_H])
+m4trace:configure.ac:36: -1- AC_DEFINE_TRACE_LITERAL([HAVE_VFORK_H])
+m4trace:configure.ac:36: -1- m4_pattern_allow([^HAVE_VFORK_H$])
+m4trace:configure.ac:36: -1- AH_OUTPUT([HAVE_FORK], [/* Define to 1 if you have the `fork\' function. */
+@%:@undef HAVE_FORK])
+m4trace:configure.ac:36: -1- AH_OUTPUT([HAVE_VFORK], [/* Define to 1 if you have the `vfork\' function. */
+@%:@undef HAVE_VFORK])
+m4trace:configure.ac:36: -1- AC_DEFINE_TRACE_LITERAL([HAVE_WORKING_VFORK])
+m4trace:configure.ac:36: -1- m4_pattern_allow([^HAVE_WORKING_VFORK$])
+m4trace:configure.ac:36: -1- AH_OUTPUT([HAVE_WORKING_VFORK], [/* Define to 1 if `vfork\' works. */
+@%:@undef HAVE_WORKING_VFORK])
+m4trace:configure.ac:36: -1- AC_DEFINE_TRACE_LITERAL([vfork])
+m4trace:configure.ac:36: -1- m4_pattern_allow([^vfork$])
+m4trace:configure.ac:36: -1- AH_OUTPUT([vfork], [/* Define as `fork\' if `vfork\' does not work. */
+@%:@undef vfork])
+m4trace:configure.ac:36: -1- AC_DEFINE_TRACE_LITERAL([HAVE_WORKING_FORK])
+m4trace:configure.ac:36: -1- m4_pattern_allow([^HAVE_WORKING_FORK$])
+m4trace:configure.ac:36: -1- AH_OUTPUT([HAVE_WORKING_FORK], [/* Define to 1 if `fork\' works. */
+@%:@undef HAVE_WORKING_FORK])
+m4trace:configure.ac:37: -1- AH_OUTPUT([HAVE_STDLIB_H], [/* Define to 1 if you have the <stdlib.h> header file. */
+@%:@undef HAVE_STDLIB_H])
+m4trace:configure.ac:37: -1- AC_DEFINE_TRACE_LITERAL([HAVE_STDLIB_H])
+m4trace:configure.ac:37: -1- m4_pattern_allow([^HAVE_STDLIB_H$])
+m4trace:configure.ac:37: -1- AC_DEFINE_TRACE_LITERAL([HAVE_MALLOC])
+m4trace:configure.ac:37: -1- m4_pattern_allow([^HAVE_MALLOC$])
+m4trace:configure.ac:37: -1- AH_OUTPUT([HAVE_MALLOC], [/* Define to 1 if your system has a GNU libc compatible `malloc\' function, and
+   to 0 otherwise. */
+@%:@undef HAVE_MALLOC])
+m4trace:configure.ac:37: -1- AC_DEFINE_TRACE_LITERAL([HAVE_MALLOC])
+m4trace:configure.ac:37: -1- m4_pattern_allow([^HAVE_MALLOC$])
+m4trace:configure.ac:37: -1- AC_SUBST([LIB@&t at OBJS], ["$LIB@&t at OBJS malloc.$ac_objext"])
+m4trace:configure.ac:37: -1- AC_SUBST_TRACE([LIB@&t at OBJS])
+m4trace:configure.ac:37: -1- m4_pattern_allow([^LIB@&t at OBJS$])
+m4trace:configure.ac:37: -1- AC_LIBSOURCE([malloc.c])
+m4trace:configure.ac:37: -1- AC_DEFINE_TRACE_LITERAL([malloc])
+m4trace:configure.ac:37: -1- m4_pattern_allow([^malloc$])
+m4trace:configure.ac:37: -1- AH_OUTPUT([malloc], [/* Define to rpl_malloc if the replacement function should be used. */
+@%:@undef malloc])
+m4trace:configure.ac:38: -1- AH_OUTPUT([HAVE_STDLIB_H], [/* Define to 1 if you have the <stdlib.h> header file. */
+@%:@undef HAVE_STDLIB_H])
+m4trace:configure.ac:38: -1- AC_DEFINE_TRACE_LITERAL([HAVE_STDLIB_H])
+m4trace:configure.ac:38: -1- m4_pattern_allow([^HAVE_STDLIB_H$])
+m4trace:configure.ac:38: -1- AC_DEFINE_TRACE_LITERAL([HAVE_REALLOC])
+m4trace:configure.ac:38: -1- m4_pattern_allow([^HAVE_REALLOC$])
+m4trace:configure.ac:38: -1- AH_OUTPUT([HAVE_REALLOC], [/* Define to 1 if your system has a GNU libc compatible `realloc\' function,
+   and to 0 otherwise. */
+@%:@undef HAVE_REALLOC])
+m4trace:configure.ac:38: -1- AC_DEFINE_TRACE_LITERAL([HAVE_REALLOC])
+m4trace:configure.ac:38: -1- m4_pattern_allow([^HAVE_REALLOC$])
+m4trace:configure.ac:38: -1- AC_SUBST([LIB@&t at OBJS], ["$LIB@&t at OBJS realloc.$ac_objext"])
+m4trace:configure.ac:38: -1- AC_SUBST_TRACE([LIB@&t at OBJS])
+m4trace:configure.ac:38: -1- m4_pattern_allow([^LIB@&t at OBJS$])
+m4trace:configure.ac:38: -1- AC_LIBSOURCE([realloc.c])
+m4trace:configure.ac:38: -1- AC_DEFINE_TRACE_LITERAL([realloc])
+m4trace:configure.ac:38: -1- m4_pattern_allow([^realloc$])
+m4trace:configure.ac:38: -1- AH_OUTPUT([realloc], [/* Define to rpl_realloc if the replacement function should be used. */
+@%:@undef realloc])
+m4trace:configure.ac:39: -1- AH_OUTPUT([HAVE_DUP2], [/* Define to 1 if you have the `dup2\' function. */
+@%:@undef HAVE_DUP2])
+m4trace:configure.ac:39: -1- AH_OUTPUT([HAVE_GETCWD], [/* Define to 1 if you have the `getcwd\' function. */
+@%:@undef HAVE_GETCWD])
+m4trace:configure.ac:39: -1- AH_OUTPUT([HAVE_MEMSET], [/* Define to 1 if you have the `memset\' function. */
+@%:@undef HAVE_MEMSET])
+m4trace:configure.ac:39: -1- AH_OUTPUT([HAVE_SETENV], [/* Define to 1 if you have the `setenv\' function. */
+@%:@undef HAVE_SETENV])
+m4trace:configure.ac:39: -1- AH_OUTPUT([HAVE_STRDUP], [/* Define to 1 if you have the `strdup\' function. */
+@%:@undef HAVE_STRDUP])
+m4trace:configure.ac:39: -1- AH_OUTPUT([HAVE_STRSTR], [/* Define to 1 if you have the `strstr\' function. */
+@%:@undef HAVE_STRSTR])
+m4trace:configure.ac:48: -1- AC_SUBST([DEB_DEF])
+m4trace:configure.ac:48: -1- AC_SUBST_TRACE([DEB_DEF])
+m4trace:configure.ac:48: -1- m4_pattern_allow([^DEB_DEF$])
+m4trace:configure.ac:53: -1- AC_SUBST([CGI_DIR])
+m4trace:configure.ac:53: -1- AC_SUBST_TRACE([CGI_DIR])
+m4trace:configure.ac:53: -1- m4_pattern_allow([^CGI_DIR$])
+m4trace:configure.ac:58: -1- AC_SUBST([RELY_ON_DB])
+m4trace:configure.ac:58: -1- AC_SUBST_TRACE([RELY_ON_DB])
+m4trace:configure.ac:58: -1- m4_pattern_allow([^RELY_ON_DB$])
+m4trace:configure.ac:88: -1- AH_OUTPUT([HAVE_LIBYAML], [/* Define to 1 if you have the `yaml\' library (-lyaml). */
+@%:@undef HAVE_LIBYAML])
+m4trace:configure.ac:88: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBYAML])
+m4trace:configure.ac:88: -1- m4_pattern_allow([^HAVE_LIBYAML$])
+m4trace:configure.ac:90: -1- AH_OUTPUT([HAVE_YAML_H], [/* Define to 1 if you have the <yaml.h> header file. */
+@%:@undef HAVE_YAML_H])
+m4trace:configure.ac:90: -1- AC_DEFINE_TRACE_LITERAL([HAVE_YAML_H])
+m4trace:configure.ac:90: -1- m4_pattern_allow([^HAVE_YAML_H$])
+m4trace:configure.ac:93: -1- AC_SUBST([YAML_CPPFLAGS])
+m4trace:configure.ac:93: -1- AC_SUBST_TRACE([YAML_CPPFLAGS])
+m4trace:configure.ac:93: -1- m4_pattern_allow([^YAML_CPPFLAGS$])
+m4trace:configure.ac:94: -1- AC_SUBST([YAML_LDFLAGS])
+m4trace:configure.ac:94: -1- AC_SUBST_TRACE([YAML_LDFLAGS])
+m4trace:configure.ac:94: -1- m4_pattern_allow([^YAML_LDFLAGS$])
+m4trace:configure.ac:95: -1- AC_SUBST([YAML_FILE])
+m4trace:configure.ac:95: -1- AC_SUBST_TRACE([YAML_FILE])
+m4trace:configure.ac:95: -1- m4_pattern_allow([^YAML_FILE$])
+m4trace:configure.ac:96: -1- AC_SUBST([YAML_FILE1])
+m4trace:configure.ac:96: -1- AC_SUBST_TRACE([YAML_FILE1])
+m4trace:configure.ac:96: -1- m4_pattern_allow([^YAML_FILE1$])
+m4trace:configure.ac:115: -1- AH_OUTPUT([HAVE_LIBFCGI], [/* Define to 1 if you have the `fcgi\' library (-lfcgi). */
+@%:@undef HAVE_LIBFCGI])
+m4trace:configure.ac:115: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBFCGI])
+m4trace:configure.ac:115: -1- m4_pattern_allow([^HAVE_LIBFCGI$])
+m4trace:configure.ac:117: -1- AH_OUTPUT([HAVE_FCGI_STDIO_H], [/* Define to 1 if you have the <fcgi_stdio.h> header file. */
+@%:@undef HAVE_FCGI_STDIO_H])
+m4trace:configure.ac:117: -1- AC_DEFINE_TRACE_LITERAL([HAVE_FCGI_STDIO_H])
+m4trace:configure.ac:117: -1- m4_pattern_allow([^HAVE_FCGI_STDIO_H$])
+m4trace:configure.ac:119: -1- AC_SUBST([FCGI_CPPFLAGS])
+m4trace:configure.ac:119: -1- AC_SUBST_TRACE([FCGI_CPPFLAGS])
+m4trace:configure.ac:119: -1- m4_pattern_allow([^FCGI_CPPFLAGS$])
+m4trace:configure.ac:120: -1- AC_SUBST([FCGI_LDFLAGS])
+m4trace:configure.ac:120: -1- AC_SUBST_TRACE([FCGI_LDFLAGS])
+m4trace:configure.ac:120: -1- m4_pattern_allow([^FCGI_LDFLAGS$])
+m4trace:configure.ac:132: -1- AC_SUBST([XML2CONFIG])
+m4trace:configure.ac:132: -1- AC_SUBST_TRACE([XML2CONFIG])
+m4trace:configure.ac:132: -1- m4_pattern_allow([^XML2CONFIG$])
+m4trace:configure.ac:159: -1- AH_OUTPUT([HAVE_LIBXML_TREE_H], [/* Define to 1 if you have the <libxml/tree.h> header file. */
+@%:@undef HAVE_LIBXML_TREE_H])
+m4trace:configure.ac:159: -1- AH_OUTPUT([HAVE_LIBXML_PARSER_H], [/* Define to 1 if you have the <libxml/parser.h> header file. */
+@%:@undef HAVE_LIBXML_PARSER_H])
+m4trace:configure.ac:159: -1- AH_OUTPUT([HAVE_LIBXML_XPATH_H], [/* Define to 1 if you have the <libxml/xpath.h> header file. */
+@%:@undef HAVE_LIBXML_XPATH_H])
+m4trace:configure.ac:159: -1- AH_OUTPUT([HAVE_LIBXML_XPATHINTERNALS_H], [/* Define to 1 if you have the <libxml/xpathInternals.h> header file. */
+@%:@undef HAVE_LIBXML_XPATHINTERNALS_H])
+m4trace:configure.ac:164: -1- AH_OUTPUT([HAVE_LIBXML2], [/* Define to 1 if you have the `xml2\' library (-lxml2). */
+@%:@undef HAVE_LIBXML2])
+m4trace:configure.ac:164: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBXML2])
+m4trace:configure.ac:164: -1- m4_pattern_allow([^HAVE_LIBXML2$])
+m4trace:configure.ac:166: -1- AC_SUBST([XML2_CPPFLAGS])
+m4trace:configure.ac:166: -1- AC_SUBST_TRACE([XML2_CPPFLAGS])
+m4trace:configure.ac:166: -1- m4_pattern_allow([^XML2_CPPFLAGS$])
+m4trace:configure.ac:167: -1- AC_SUBST([XML2_LDFLAGS])
+m4trace:configure.ac:167: -1- AC_SUBST_TRACE([XML2_LDFLAGS])
+m4trace:configure.ac:167: -1- m4_pattern_allow([^XML2_LDFLAGS$])
+m4trace:configure.ac:181: -1- AC_SUBST([XSLTCONFIG])
+m4trace:configure.ac:181: -1- AC_SUBST_TRACE([XSLTCONFIG])
+m4trace:configure.ac:181: -1- m4_pattern_allow([^XSLTCONFIG$])
+m4trace:configure.ac:208: -1- AH_OUTPUT([HAVE_LIBXSLT_XSLT_H], [/* Define to 1 if you have the <libxslt/xslt.h> header file. */
+@%:@undef HAVE_LIBXSLT_XSLT_H])
+m4trace:configure.ac:208: -1- AH_OUTPUT([HAVE_LIBXSLT_XSLTINTERNALS_H], [/* Define to 1 if you have the <libxslt/xsltInternals.h> header file. */
+@%:@undef HAVE_LIBXSLT_XSLTINTERNALS_H])
+m4trace:configure.ac:208: -1- AH_OUTPUT([HAVE_LIBXSLT_TRANSFORM_H], [/* Define to 1 if you have the <libxslt/transform.h> header file. */
+@%:@undef HAVE_LIBXSLT_TRANSFORM_H])
+m4trace:configure.ac:208: -1- AH_OUTPUT([HAVE_LIBXSLT_XSLTUTILS_H], [/* Define to 1 if you have the <libxslt/xsltutils.h> header file. */
+@%:@undef HAVE_LIBXSLT_XSLTUTILS_H])
+m4trace:configure.ac:210: -1- AC_SUBST([XSLT_CPPFLAGS])
+m4trace:configure.ac:210: -1- AC_SUBST_TRACE([XSLT_CPPFLAGS])
+m4trace:configure.ac:210: -1- m4_pattern_allow([^XSLT_CPPFLAGS$])
+m4trace:configure.ac:211: -1- AC_SUBST([XSLT_LDFLAGS])
+m4trace:configure.ac:211: -1- AC_SUBST_TRACE([XSLT_LDFLAGS])
+m4trace:configure.ac:211: -1- m4_pattern_allow([^XSLT_LDFLAGS$])
+m4trace:configure.ac:222: -1- AC_SUBST([GDAL_CONFIG])
+m4trace:configure.ac:222: -1- AC_SUBST_TRACE([GDAL_CONFIG])
+m4trace:configure.ac:222: -1- m4_pattern_allow([^GDAL_CONFIG$])
+m4trace:configure.ac:239: -1- AC_SUBST([GDAL_CFLAGS])
+m4trace:configure.ac:239: -1- AC_SUBST_TRACE([GDAL_CFLAGS])
+m4trace:configure.ac:239: -1- m4_pattern_allow([^GDAL_CFLAGS$])
+m4trace:configure.ac:240: -1- AC_SUBST([GDAL_LIBS])
+m4trace:configure.ac:240: -1- AC_SUBST_TRACE([GDAL_LIBS])
+m4trace:configure.ac:240: -1- m4_pattern_allow([^GDAL_LIBS$])
+m4trace:configure.ac:258: -1- AH_OUTPUT([HAVE_PROJ_API_H], [/* Define to 1 if you have the <proj_api.h> header file. */
+@%:@undef HAVE_PROJ_API_H])
+m4trace:configure.ac:258: -1- AC_DEFINE_TRACE_LITERAL([HAVE_PROJ_API_H])
+m4trace:configure.ac:258: -1- m4_pattern_allow([^HAVE_PROJ_API_H$])
+m4trace:configure.ac:260: -1- AC_SUBST([PROJ_CPPFLAGS])
+m4trace:configure.ac:260: -1- AC_SUBST_TRACE([PROJ_CPPFLAGS])
+m4trace:configure.ac:260: -1- m4_pattern_allow([^PROJ_CPPFLAGS$])
+m4trace:configure.ac:261: -1- AC_SUBST([PROJ_LDFLAGS])
+m4trace:configure.ac:261: -1- AC_SUBST_TRACE([PROJ_LDFLAGS])
+m4trace:configure.ac:261: -1- m4_pattern_allow([^PROJ_LDFLAGS$])
+m4trace:configure.ac:273: -1- AC_SUBST([GEOSCONFIG])
+m4trace:configure.ac:273: -1- AC_SUBST_TRACE([GEOSCONFIG])
+m4trace:configure.ac:273: -1- m4_pattern_allow([^GEOSCONFIG$])
+m4trace:configure.ac:299: -1- AH_OUTPUT([HAVE_GEOS_C_H], [/* Define to 1 if you have the <geos_c.h> header file. */
+@%:@undef HAVE_GEOS_C_H])
+m4trace:configure.ac:299: -1- AC_DEFINE_TRACE_LITERAL([HAVE_GEOS_C_H])
+m4trace:configure.ac:299: -1- m4_pattern_allow([^HAVE_GEOS_C_H$])
+m4trace:configure.ac:301: -1- AC_SUBST([GEOS_CPPFLAGS])
+m4trace:configure.ac:301: -1- AC_SUBST_TRACE([GEOS_CPPFLAGS])
+m4trace:configure.ac:301: -1- m4_pattern_allow([^GEOS_CPPFLAGS$])
+m4trace:configure.ac:302: -1- AC_SUBST([GEOS_LDFLAGS])
+m4trace:configure.ac:302: -1- AC_SUBST_TRACE([GEOS_LDFLAGS])
+m4trace:configure.ac:302: -1- m4_pattern_allow([^GEOS_LDFLAGS$])
+m4trace:configure.ac:318: -1- AH_OUTPUT([HAVE_CGAL_DELAUNAY_TRIANGULATION_2_H], [/* Define to 1 if you have the <CGAL/Delaunay_triangulation_2.h> header file.
+   */
+@%:@undef HAVE_CGAL_DELAUNAY_TRIANGULATION_2_H])
+m4trace:configure.ac:318: -1- AC_DEFINE_TRACE_LITERAL([HAVE_CGAL_DELAUNAY_TRIANGULATION_2_H])
+m4trace:configure.ac:318: -1- m4_pattern_allow([^HAVE_CGAL_DELAUNAY_TRIANGULATION_2_H$])
+m4trace:configure.ac:325: -1- AC_SUBST([CGAL_CPPFLAGS])
+m4trace:configure.ac:325: -1- AC_SUBST_TRACE([CGAL_CPPFLAGS])
+m4trace:configure.ac:325: -1- m4_pattern_allow([^CGAL_CPPFLAGS$])
+m4trace:configure.ac:326: -1- AC_SUBST([CGAL_LDFLAGS])
+m4trace:configure.ac:326: -1- AC_SUBST_TRACE([CGAL_LDFLAGS])
+m4trace:configure.ac:326: -1- m4_pattern_allow([^CGAL_LDFLAGS$])
+m4trace:configure.ac:362: -1- AC_SUBST([MS_CFLAGS])
+m4trace:configure.ac:362: -1- AC_SUBST_TRACE([MS_CFLAGS])
+m4trace:configure.ac:362: -1- m4_pattern_allow([^MS_CFLAGS$])
+m4trace:configure.ac:363: -1- AC_SUBST([MS_LIBS])
+m4trace:configure.ac:363: -1- AC_SUBST_TRACE([MS_LIBS])
+m4trace:configure.ac:363: -1- m4_pattern_allow([^MS_LIBS$])
+m4trace:configure.ac:364: -1- AC_SUBST([MS_FILE])
+m4trace:configure.ac:364: -1- AC_SUBST_TRACE([MS_FILE])
+m4trace:configure.ac:364: -1- m4_pattern_allow([^MS_FILE$])
+m4trace:configure.ac:390: -1- AC_SUBST([PYTHONCONFIG])
+m4trace:configure.ac:390: -1- AC_SUBST_TRACE([PYTHONCONFIG])
+m4trace:configure.ac:390: -1- m4_pattern_allow([^PYTHONCONFIG$])
+m4trace:configure.ac:392: -1- AC_SUBST([PYTHONCONFIG])
+m4trace:configure.ac:392: -1- AC_SUBST_TRACE([PYTHONCONFIG])
+m4trace:configure.ac:392: -1- m4_pattern_allow([^PYTHONCONFIG$])
+m4trace:configure.ac:406: -1- AH_OUTPUT([HAVE_PYTHON_H], [/* Define to 1 if you have the <Python.h> header file. */
+@%:@undef HAVE_PYTHON_H])
+m4trace:configure.ac:406: -1- AC_DEFINE_TRACE_LITERAL([HAVE_PYTHON_H])
+m4trace:configure.ac:406: -1- m4_pattern_allow([^HAVE_PYTHON_H$])
+m4trace:configure.ac:413: -1- AC_SUBST([PYTHON_CPPFLAGS])
+m4trace:configure.ac:413: -1- AC_SUBST_TRACE([PYTHON_CPPFLAGS])
+m4trace:configure.ac:413: -1- m4_pattern_allow([^PYTHON_CPPFLAGS$])
+m4trace:configure.ac:414: -1- AC_SUBST([PYTHON_LDFLAGS])
+m4trace:configure.ac:414: -1- AC_SUBST_TRACE([PYTHON_LDFLAGS])
+m4trace:configure.ac:414: -1- m4_pattern_allow([^PYTHON_LDFLAGS$])
+m4trace:configure.ac:418: -1- AC_SUBST([PYTHON_ENABLED])
+m4trace:configure.ac:418: -1- AC_SUBST_TRACE([PYTHON_ENABLED])
+m4trace:configure.ac:418: -1- m4_pattern_allow([^PYTHON_ENABLED$])
+m4trace:configure.ac:419: -1- AC_SUBST([PYTHON_FILE])
+m4trace:configure.ac:419: -1- AC_SUBST_TRACE([PYTHON_FILE])
+m4trace:configure.ac:419: -1- m4_pattern_allow([^PYTHON_FILE$])
+m4trace:configure.ac:469: -1- AH_OUTPUT([HAVE_JSAPI_H], [/* Define to 1 if you have the <jsapi.h> header file. */
+@%:@undef HAVE_JSAPI_H])
+m4trace:configure.ac:469: -1- AC_SUBST([CXXCPP])
+m4trace:configure.ac:469: -1- AC_SUBST_TRACE([CXXCPP])
+m4trace:configure.ac:469: -1- m4_pattern_allow([^CXXCPP$])
+m4trace:configure.ac:469: -1- AC_SUBST([CPPFLAGS])
+m4trace:configure.ac:469: -1- AC_SUBST_TRACE([CPPFLAGS])
+m4trace:configure.ac:469: -1- m4_pattern_allow([^CPPFLAGS$])
+m4trace:configure.ac:469: -1- AC_SUBST([CXXCPP])
+m4trace:configure.ac:469: -1- AC_SUBST_TRACE([CXXCPP])
+m4trace:configure.ac:469: -1- m4_pattern_allow([^CXXCPP$])
+m4trace:configure.ac:469: -1- AC_DEFINE_TRACE_LITERAL([HAVE_JSAPI_H])
+m4trace:configure.ac:469: -1- m4_pattern_allow([^HAVE_JSAPI_H$])
+m4trace:configure.ac:478: -1- AC_SUBST([JS_CPPFLAGS])
+m4trace:configure.ac:478: -1- AC_SUBST_TRACE([JS_CPPFLAGS])
+m4trace:configure.ac:478: -1- m4_pattern_allow([^JS_CPPFLAGS$])
+m4trace:configure.ac:479: -1- AC_SUBST([JS_LDFLAGS])
+m4trace:configure.ac:479: -1- AC_SUBST_TRACE([JS_LDFLAGS])
+m4trace:configure.ac:479: -1- m4_pattern_allow([^JS_LDFLAGS$])
+m4trace:configure.ac:482: -1- AC_SUBST([JS_ENABLED])
+m4trace:configure.ac:482: -1- AC_SUBST_TRACE([JS_ENABLED])
+m4trace:configure.ac:482: -1- m4_pattern_allow([^JS_ENABLED$])
+m4trace:configure.ac:483: -1- AC_SUBST([JS_FILE])
+m4trace:configure.ac:483: -1- AC_SUBST_TRACE([JS_FILE])
+m4trace:configure.ac:483: -1- m4_pattern_allow([^JS_FILE$])
+m4trace:configure.ac:503: -1- AC_SUBST([PHPCONFIG])
+m4trace:configure.ac:503: -1- AC_SUBST_TRACE([PHPCONFIG])
+m4trace:configure.ac:503: -1- m4_pattern_allow([^PHPCONFIG$])
+m4trace:configure.ac:516: -1- AH_OUTPUT([HAVE_SAPI_EMBED_PHP_EMBED_H], [/* Define to 1 if you have the <sapi/embed/php_embed.h> header file. */
+@%:@undef HAVE_SAPI_EMBED_PHP_EMBED_H])
+m4trace:configure.ac:516: -1- AC_DEFINE_TRACE_LITERAL([HAVE_SAPI_EMBED_PHP_EMBED_H])
+m4trace:configure.ac:516: -1- m4_pattern_allow([^HAVE_SAPI_EMBED_PHP_EMBED_H$])
+m4trace:configure.ac:522: -1- AH_OUTPUT([HAVE_LIBPHP5], [/* Define to 1 if you have the `php5\' library (-lphp5). */
+@%:@undef HAVE_LIBPHP5])
+m4trace:configure.ac:522: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBPHP5])
+m4trace:configure.ac:522: -1- m4_pattern_allow([^HAVE_LIBPHP5$])
+m4trace:configure.ac:524: -1- AC_SUBST([PHP_CPPFLAGS])
+m4trace:configure.ac:524: -1- AC_SUBST_TRACE([PHP_CPPFLAGS])
+m4trace:configure.ac:524: -1- m4_pattern_allow([^PHP_CPPFLAGS$])
+m4trace:configure.ac:525: -1- AC_SUBST([PHP_LDFLAGS])
+m4trace:configure.ac:525: -1- AC_SUBST_TRACE([PHP_LDFLAGS])
+m4trace:configure.ac:525: -1- m4_pattern_allow([^PHP_LDFLAGS$])
+m4trace:configure.ac:528: -1- AC_SUBST([PHP_ENABLED])
+m4trace:configure.ac:528: -1- AC_SUBST_TRACE([PHP_ENABLED])
+m4trace:configure.ac:528: -1- m4_pattern_allow([^PHP_ENABLED$])
+m4trace:configure.ac:529: -1- AC_SUBST([PHP_FILE])
+m4trace:configure.ac:529: -1- AC_SUBST_TRACE([PHP_FILE])
+m4trace:configure.ac:529: -1- m4_pattern_allow([^PHP_FILE$])
+m4trace:configure.ac:573: -1- AH_OUTPUT([HAVE_JNI_H], [/* Define to 1 if you have the <jni.h> header file. */
+@%:@undef HAVE_JNI_H])
+m4trace:configure.ac:573: -1- AC_DEFINE_TRACE_LITERAL([HAVE_JNI_H])
+m4trace:configure.ac:573: -1- m4_pattern_allow([^HAVE_JNI_H$])
+m4trace:configure.ac:580: -1- AH_OUTPUT([HAVE_LIBJVM], [/* Define to 1 if you have the `jvm\' library (-ljvm). */
+@%:@undef HAVE_LIBJVM])
+m4trace:configure.ac:580: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBJVM])
+m4trace:configure.ac:580: -1- m4_pattern_allow([^HAVE_LIBJVM$])
+m4trace:configure.ac:584: -1- AC_SUBST([JAVA_CPPFLAGS])
+m4trace:configure.ac:584: -1- AC_SUBST_TRACE([JAVA_CPPFLAGS])
+m4trace:configure.ac:584: -1- m4_pattern_allow([^JAVA_CPPFLAGS$])
+m4trace:configure.ac:585: -1- AC_SUBST([JAVA_LDFLAGS])
+m4trace:configure.ac:585: -1- AC_SUBST_TRACE([JAVA_LDFLAGS])
+m4trace:configure.ac:585: -1- m4_pattern_allow([^JAVA_LDFLAGS$])
+m4trace:configure.ac:588: -1- AC_SUBST([JAVA_ENABLED])
+m4trace:configure.ac:588: -1- AC_SUBST_TRACE([JAVA_ENABLED])
+m4trace:configure.ac:588: -1- m4_pattern_allow([^JAVA_ENABLED$])
+m4trace:configure.ac:589: -1- AC_SUBST([JAVA_FILE])
+m4trace:configure.ac:589: -1- AC_SUBST_TRACE([JAVA_FILE])
+m4trace:configure.ac:589: -1- m4_pattern_allow([^JAVA_FILE$])
+m4trace:configure.ac:617: -1- AH_OUTPUT([HAVE_RUBY_H], [/* Define to 1 if you have the <ruby.h> header file. */
+@%:@undef HAVE_RUBY_H])
+m4trace:configure.ac:617: -1- AC_DEFINE_TRACE_LITERAL([HAVE_RUBY_H])
+m4trace:configure.ac:617: -1- m4_pattern_allow([^HAVE_RUBY_H$])
+m4trace:configure.ac:624: -1- AC_SUBST([RUBY_CPPFLAGS])
+m4trace:configure.ac:624: -1- AC_SUBST_TRACE([RUBY_CPPFLAGS])
+m4trace:configure.ac:624: -1- m4_pattern_allow([^RUBY_CPPFLAGS$])
+m4trace:configure.ac:625: -1- AC_SUBST([RUBY_LDFLAGS])
+m4trace:configure.ac:625: -1- AC_SUBST_TRACE([RUBY_LDFLAGS])
+m4trace:configure.ac:625: -1- m4_pattern_allow([^RUBY_LDFLAGS$])
+m4trace:configure.ac:628: -1- AC_SUBST([RUBY_ENABLED])
+m4trace:configure.ac:628: -1- AC_SUBST_TRACE([RUBY_ENABLED])
+m4trace:configure.ac:628: -1- m4_pattern_allow([^RUBY_ENABLED$])
+m4trace:configure.ac:629: -1- AC_SUBST([RUBY_FILE])
+m4trace:configure.ac:629: -1- AC_SUBST_TRACE([RUBY_FILE])
+m4trace:configure.ac:629: -1- m4_pattern_allow([^RUBY_FILE$])
+m4trace:configure.ac:648: -1- AC_SUBST([PERLCONFIG])
+m4trace:configure.ac:648: -1- AC_SUBST_TRACE([PERLCONFIG])
+m4trace:configure.ac:648: -1- m4_pattern_allow([^PERLCONFIG$])
+m4trace:configure.ac:661: -1- AH_OUTPUT([HAVE_EXTERN_H], [/* Define to 1 if you have the <EXTERN.h> header file. */
+@%:@undef HAVE_EXTERN_H])
+m4trace:configure.ac:661: -1- AC_DEFINE_TRACE_LITERAL([HAVE_EXTERN_H])
+m4trace:configure.ac:661: -1- m4_pattern_allow([^HAVE_EXTERN_H$])
+m4trace:configure.ac:663: -1- AC_SUBST([PERL_CPPFLAGS])
+m4trace:configure.ac:663: -1- AC_SUBST_TRACE([PERL_CPPFLAGS])
+m4trace:configure.ac:663: -1- m4_pattern_allow([^PERL_CPPFLAGS$])
+m4trace:configure.ac:664: -1- AC_SUBST([PERL_LDFLAGS])
+m4trace:configure.ac:664: -1- AC_SUBST_TRACE([PERL_LDFLAGS])
+m4trace:configure.ac:664: -1- m4_pattern_allow([^PERL_LDFLAGS$])
+m4trace:configure.ac:667: -1- AC_SUBST([PERL_ENABLED])
+m4trace:configure.ac:667: -1- AC_SUBST_TRACE([PERL_ENABLED])
+m4trace:configure.ac:667: -1- m4_pattern_allow([^PERL_ENABLED$])
+m4trace:configure.ac:668: -1- AC_SUBST([PERL_FILE])
+m4trace:configure.ac:668: -1- AC_SUBST_TRACE([PERL_FILE])
+m4trace:configure.ac:668: -1- m4_pattern_allow([^PERL_FILE$])
+m4trace:configure.ac:709: -1- AH_OUTPUT([HAVE_OTBWRAPPERAPPLICATION_H], [/* Define to 1 if you have the <otbWrapperApplication.h> header file. */
+@%:@undef HAVE_OTBWRAPPERAPPLICATION_H])
+m4trace:configure.ac:709: -1- AH_OUTPUT([HAVE_OTBWRAPPERINPUTIMAGELISTPARAMETER_H], [/* Define to 1 if you have the <otbWrapperInputImageListParameter.h> header
+   file. */
+@%:@undef HAVE_OTBWRAPPERINPUTIMAGELISTPARAMETER_H])
+m4trace:configure.ac:709: -1- AH_OUTPUT([HAVE_OTBWRAPPERAPPLICATIONREGISTRY_H], [/* Define to 1 if you have the <otbWrapperApplicationRegistry.h> header file.
+   */
+@%:@undef HAVE_OTBWRAPPERAPPLICATIONREGISTRY_H])
+m4trace:configure.ac:719: -1- AC_SUBST([OTB_CPPFLAGS])
+m4trace:configure.ac:719: -1- AC_SUBST_TRACE([OTB_CPPFLAGS])
+m4trace:configure.ac:719: -1- m4_pattern_allow([^OTB_CPPFLAGS$])
+m4trace:configure.ac:720: -1- AC_SUBST([OTB_LDFLAGS])
+m4trace:configure.ac:720: -1- AC_SUBST_TRACE([OTB_LDFLAGS])
+m4trace:configure.ac:720: -1- m4_pattern_allow([^OTB_LDFLAGS$])
+m4trace:configure.ac:721: -1- AC_SUBST([OTB_FILE])
+m4trace:configure.ac:721: -1- AC_SUBST_TRACE([OTB_FILE])
+m4trace:configure.ac:721: -1- m4_pattern_allow([^OTB_FILE$])
+m4trace:configure.ac:722: -1- AC_SUBST([OTB_ENABLED])
+m4trace:configure.ac:722: -1- AC_SUBST_TRACE([OTB_ENABLED])
+m4trace:configure.ac:722: -1- m4_pattern_allow([^OTB_ENABLED$])
+m4trace:configure.ac:763: -1- AH_OUTPUT([HAVE_MODULE_LIBRARY_H], [/* Define to 1 if you have the <module_library.h> header file. */
+@%:@undef HAVE_MODULE_LIBRARY_H])
+m4trace:configure.ac:763: -1- AC_DEFINE_TRACE_LITERAL([HAVE_MODULE_LIBRARY_H])
+m4trace:configure.ac:763: -1- m4_pattern_allow([^HAVE_MODULE_LIBRARY_H$])
+m4trace:configure.ac:769: -1- AC_SUBST([SAGA_CPPFLAGS])
+m4trace:configure.ac:769: -1- AC_SUBST_TRACE([SAGA_CPPFLAGS])
+m4trace:configure.ac:769: -1- m4_pattern_allow([^SAGA_CPPFLAGS$])
+m4trace:configure.ac:770: -1- AC_SUBST([SAGA_LDFLAGS])
+m4trace:configure.ac:770: -1- AC_SUBST_TRACE([SAGA_LDFLAGS])
+m4trace:configure.ac:770: -1- m4_pattern_allow([^SAGA_LDFLAGS$])
+m4trace:configure.ac:771: -1- AC_SUBST([SAGA_FILE])
+m4trace:configure.ac:771: -1- AC_SUBST_TRACE([SAGA_FILE])
+m4trace:configure.ac:771: -1- m4_pattern_allow([^SAGA_FILE$])
+m4trace:configure.ac:772: -1- AC_SUBST([SAGA_ENABLED])
+m4trace:configure.ac:772: -1- AC_SUBST_TRACE([SAGA_ENABLED])
+m4trace:configure.ac:772: -1- m4_pattern_allow([^SAGA_ENABLED$])
+m4trace:configure.ac:774: -1- AC_CONFIG_FILES([Makefile])
+m4trace:configure.ac:775: -1- AC_CONFIG_FILES([ZOOMakefile.opts])
+m4trace:configure.ac:776: -1- AC_SUBST([LIB@&t at OBJS], [$ac_libobjs])
+m4trace:configure.ac:776: -1- AC_SUBST_TRACE([LIB@&t at OBJS])
+m4trace:configure.ac:776: -1- m4_pattern_allow([^LIB@&t at OBJS$])
+m4trace:configure.ac:776: -1- AC_SUBST([LTLIBOBJS], [$ac_ltlibobjs])
+m4trace:configure.ac:776: -1- AC_SUBST_TRACE([LTLIBOBJS])
+m4trace:configure.ac:776: -1- m4_pattern_allow([^LTLIBOBJS$])
+m4trace:configure.ac:776: -1- AC_SUBST_TRACE([top_builddir])
+m4trace:configure.ac:776: -1- AC_SUBST_TRACE([top_build_prefix])
+m4trace:configure.ac:776: -1- AC_SUBST_TRACE([srcdir])
+m4trace:configure.ac:776: -1- AC_SUBST_TRACE([abs_srcdir])
+m4trace:configure.ac:776: -1- AC_SUBST_TRACE([top_srcdir])
+m4trace:configure.ac:776: -1- AC_SUBST_TRACE([abs_top_srcdir])
+m4trace:configure.ac:776: -1- AC_SUBST_TRACE([builddir])
+m4trace:configure.ac:776: -1- AC_SUBST_TRACE([abs_builddir])
+m4trace:configure.ac:776: -1- AC_SUBST_TRACE([abs_top_builddir])
diff --git a/zoo-project/zoo-kernel/caching.c b/zoo-project/zoo-kernel/caching.c
new file mode 100644
index 0000000..82ca669
--- /dev/null
+++ b/zoo-project/zoo-kernel/caching.c
@@ -0,0 +1,381 @@
+/*
+ * Author : Gérald Fenoy
+ *
+ *  Copyright 2008-2015 GeoLabs SARL. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "caching.h"
+#include "service.h"
+#include "service_internal.h"
+#include "response_print.h"
+#include <openssl/md5.h>
+#include <openssl/hmac.h>
+#include <openssl/evp.h>
+#include <openssl/bio.h>
+#include <openssl/buffer.h>
+
+/**
+ * Compute md5
+ * 
+ * @param url the char* 
+ * @return a char* representing the md5 of the url
+ * @warning make sure to free ressources returned by this function
+ */
+char* getMd5(char* url){
+  EVP_MD_CTX md5ctx;
+  char* fresult=(char*)malloc((EVP_MAX_MD_SIZE+1)*sizeof(char));
+  unsigned char result[EVP_MAX_MD_SIZE];
+  unsigned int len;
+  EVP_DigestInit(&md5ctx, EVP_md5());
+  EVP_DigestUpdate(&md5ctx, url, strlen(url));
+  EVP_DigestFinal_ex(&md5ctx,result,&len);
+  EVP_MD_CTX_cleanup(&md5ctx);
+  int i;
+  for(i = 0; i < len; i++){
+    if(i>0){
+      char *tmp=strdup(fresult);
+      sprintf(fresult,"%s%02x", tmp,result[i]);
+      free(tmp);
+    }
+    else
+      sprintf(fresult,"%02x",result[i]);
+  }
+  return fresult;
+}
+
+
+/**
+ * Cache a file for a given request.
+ * For each cached file, the are two files stored, a .zca and a .zcm containing
+ * the downloaded content and the mimeType respectively. 
+ *
+ * @param conf the maps containing the settings of the main.cfg file
+ * @param request the url used too fetch the content
+ * @param content the downloaded content
+ * @param mimeType the content mimeType 
+ * @param length the content size
+ * @param filepath a buffer for storing the path of the cached file; may be NULL
+ * @param max_path the size of the allocated filepath buffer  
+ */
+void addToCache(maps* conf,char* request,char* content,char* mimeType,int length, 
+                char* filepath, size_t max_path){
+  map* tmp=getMapFromMaps(conf,"main","cacheDir");
+  if(tmp!=NULL){
+    char* md5str=getMd5(request);
+    char* fname=(char*)malloc(sizeof(char)*(strlen(tmp->value)+strlen(md5str)+6));
+    sprintf(fname,"%s/%s.zca",tmp->value,md5str);
+#ifdef DEBUG
+    fprintf(stderr,"Cache list : %s\n",fname);
+    fflush(stderr);
+#endif
+    FILE* fo=fopen(fname,"w+");
+    if(fo==NULL){
+#ifdef DEBUG
+      fprintf (stderr, "Failed to open %s for writing: %s\n",fname, strerror(errno));
+#endif
+      filepath = NULL;	
+      return;
+    }
+    fwrite(content,sizeof(char),length,fo);
+    fclose(fo);
+	
+	if (filepath != NULL) {
+		strncpy(filepath, fname, max_path);
+	}	
+
+    sprintf(fname,"%s/%s.zcm",tmp->value,md5str);
+    fo=fopen(fname,"w+");
+#ifdef DEBUG
+    fprintf(stderr,"MIMETYPE: %s\n",mimeType);
+#endif
+    fwrite(mimeType,sizeof(char),strlen(mimeType),fo);
+    fclose(fo);
+
+    free(md5str);
+    free(fname);
+  }
+  else {
+	  filepath = NULL;
+  }	  
+}
+
+/**
+ * Verify if a url is available in the cache
+ *
+ * @param conf the maps containing the settings of the main.cfg file
+ * @param request the url
+ * @return the full name of the cached file if any, NULL in other case
+ * @warning make sure to free ressources returned by this function (if not NULL)
+ */
+char* isInCache(maps* conf,char* request){
+  map* tmpM=getMapFromMaps(conf,"main","cacheDir");
+  if(tmpM!=NULL){
+    char* md5str=getMd5(request);
+#ifdef DEBUG
+    fprintf(stderr,"MD5STR : (%s)\n\n",md5str);
+#endif
+    char* fname=(char*)malloc(sizeof(char)*(strlen(tmpM->value)+strlen(md5str)+6));
+    sprintf(fname,"%s/%s.zca",tmpM->value,md5str);
+    struct stat f_status;
+    int s=stat(fname, &f_status);
+    if(s==0 && f_status.st_size>0){
+      free(md5str);
+      return fname;
+    }
+    free(md5str);
+    free(fname);
+  }
+  return NULL;
+}
+
+/**
+ * Effectively run all the HTTP requests in the queue
+ *
+ * @param m the maps containing the settings of the main.cfg file
+ * @param inputs the maps containing the inputs (defined in the requests+added
+ *  per default based on the zcfg file)
+ * @param hInternet the HINTERNET pointer
+ * @return 0 on success
+ */
+int runHttpRequests(maps** m,maps** inputs,HINTERNET* hInternet){
+  if(hInternet->nb>0){
+    processDownloads(hInternet);
+    maps* content=*inputs;
+    map* tmp1;
+    int index=0;
+    char sindex[5];
+    while(content!=NULL){
+      
+      map* length=getMap(content->content,"length");
+      int shouldClean=-1;
+      if(length==NULL){
+	length=createMap("length","1");
+	shouldClean=1;
+      }
+      for(int i=0;i<atoi(length->value);i++){
+	char* fcontent;
+	char *mimeType=NULL;
+	int fsize=0;
+	char cname[15];
+	char vname[11];
+	char vname1[11];
+	char sname[9];
+	char mname[15];
+	char icname[14];
+	char xname[16];
+	char oname[12];
+	if(index>0)
+	  sprintf(vname1,"value_%d",index);
+	else
+	  sprintf(vname1,"value");
+
+	if(i>0){
+	  tmp1=getMap(content->content,cname);
+	  sprintf(cname,"cache_file_%d",i);
+	  sprintf(vname,"value_%d",i);
+	  sprintf(sname,"size_%d",i);
+	  sprintf(mname,"mimeType_%d",i);
+	  sprintf(icname,"isCached_%d",i);
+	  sprintf(xname,"Reference_%d",i);
+	  sprintf(oname,"Order_%d",i);
+	}else{
+	  sprintf(cname,"cache_file");
+	  sprintf(vname,"value");
+	  sprintf(sname,"size");
+	  sprintf(mname,"mimeType");
+	  sprintf(icname,"isCached");
+	  sprintf(xname,"Reference");
+	  sprintf(oname,"Order");
+	}
+
+	map* tmap=getMap(content->content,oname);
+	sprintf(sindex,"%d",index+1);
+	if((tmp1=getMap(content->content,xname))!=NULL && tmap!=NULL && strcasecmp(tmap->value,sindex)==0){
+
+	  if(getMap(content->content,icname)==NULL){
+	    
+	    fcontent=(char*)malloc((hInternet->ihandle[index].nDataLen+1)*sizeof(char));
+	    if(fcontent == NULL){
+	      return errorException(*m, _("Unable to allocate memory"), "InternalError",NULL);
+	    }
+	    size_t dwRead;
+	    InternetReadFile(hInternet->ihandle[index], 
+			     (LPVOID)fcontent, 
+			     hInternet->ihandle[index].nDataLen, 
+			     &dwRead);
+	    fcontent[hInternet->ihandle[index].nDataLen]=0;
+	    fsize=hInternet->ihandle[index].nDataLen;
+	    if(hInternet->ihandle[index].mimeType==NULL)
+	      mimeType=strdup("none");
+	    else
+	      mimeType=strdup(hInternet->ihandle[index].mimeType);	      
+	    
+	    map* tmpMap=getMapOrFill(&content->content,vname,"");
+	    free(tmpMap->value);
+	    tmpMap->value=(char*)malloc((fsize+1)*sizeof(char));
+	    if(tmpMap->value==NULL){
+	      return errorException(*m, _("Unable to allocate memory"), "InternalError",NULL);
+	    }
+	    memcpy(tmpMap->value,fcontent,(fsize+1)*sizeof(char));
+	    
+	    char ltmp1[256];
+	    sprintf(ltmp1,"%d",fsize);
+	    map* tmp=getMapFromMaps(*m,"main","cacheDir");
+	    if(tmp!=NULL){
+	      char* md5str=getMd5(tmp1->value);
+	      char* fname=(char*)malloc(sizeof(char)*(strlen(tmp->value)+strlen(md5str)+6));
+	      sprintf(fname,"%s/%s.zca",tmp->value,md5str);
+	      addToMap(content->content,cname,fname);
+	      free(fname);
+	    }
+	    addToMap(content->content,sname,ltmp1);
+	    addToMap(content->content,mname,mimeType);
+	    addToCache(*m,tmp1->value,fcontent,mimeType,fsize, NULL, 0);
+	    free(fcontent);
+	    free(mimeType);
+	    index++;
+
+	  }
+	}
+      }
+      if(shouldClean>0){
+	freeMap(&length);
+	free(length);
+      }
+      
+      content=content->next;
+    }
+    
+  }
+  return 0;
+}
+
+/**
+ * Add a request in the download queue
+ *
+ * @param m the maps containing the settings of the main.cfg file
+ * @param url the url to add to the queue
+ */
+void addRequestToQueue(maps** m,HINTERNET* hInternet,const char* url,bool req){
+  hInternet->waitingRequests[hInternet->nb]=strdup(url);
+  if(req)
+    InternetOpenUrl(hInternet,hInternet->waitingRequests[hInternet->nb],NULL,0,INTERNET_FLAG_NO_CACHE_WRITE,0);
+  maps *oreq=getMaps(*m,"orequests");
+  if(oreq==NULL){
+    oreq=(maps*)malloc(MAPS_SIZE);
+    oreq->name=zStrdup("orequests");
+    oreq->content=createMap("value",url);
+    oreq->next=NULL;
+    addMapsToMaps(m,oreq);
+    freeMaps(&oreq);
+    free(oreq);
+  }else{
+    setMapArray(oreq->content,"value",hInternet->nb-1,url);
+  }
+}
+
+/**
+ * Try to load file from cache or download a remote file if not in cache
+ *
+ * @param m the maps containing the settings of the main.cfg file
+ * @param content the map to update
+ * @param hInternet the HINTERNET pointer
+ * @param url the url to fetch
+ * @return 0
+ */
+int loadRemoteFile(maps** m,map** content,HINTERNET* hInternet,char *url){
+  char* fcontent;
+  char* cached=isInCache(*m,url);
+  char *mimeType=NULL;
+  int fsize=0;
+
+  map* t=getMap(*content,"xlink:href");
+  if(t==NULL){
+    t=getMap((*content),"href");
+    addToMap(*content,"xlink:href",url);
+  }
+
+  if(cached!=NULL){
+
+    struct stat f_status;
+    int s=stat(cached, &f_status);
+    if(s==0){
+      fcontent=(char*)malloc(sizeof(char)*(f_status.st_size+1));
+      FILE* f=fopen(cached,"rb");
+      fread(fcontent,f_status.st_size,1,f);
+      fsize=f_status.st_size;
+      fcontent[fsize]=0;
+      fclose(f);
+      addToMap(*content,"cache_file",cached);
+    }
+    cached[strlen(cached)-1]='m';
+    s=stat(cached, &f_status);
+    if(s==0){
+      mimeType=(char*)malloc(sizeof(char)*(f_status.st_size+1));
+      FILE* f=fopen(cached,"rb");
+      fread(mimeType,f_status.st_size,1,f);
+      mimeType[f_status.st_size]=0;
+      fclose(f);
+    }
+
+  }else{    
+    addRequestToQueue(m,hInternet,url,true);
+    return 0;
+  }
+  if(fsize==0){
+    return errorException(*m, _("Unable to download the file."), "InternalError",NULL);
+  }
+  if(mimeType!=NULL){
+    addToMap(*content,"fmimeType",mimeType);
+  }
+
+  map* tmpMap=getMapOrFill(content,"value","");
+    
+  free(tmpMap->value);
+
+  tmpMap->value=(char*)malloc((fsize+1)*sizeof(char));
+  if(tmpMap->value==NULL)
+    return errorException(*m, _("Unable to allocate memory"), "InternalError",NULL);
+  memcpy(tmpMap->value,fcontent,(fsize+1)*sizeof(char));
+
+  char ltmp1[256];
+  sprintf(ltmp1,"%d",fsize);
+  addToMap(*content,"size",ltmp1);
+  if(cached==NULL){
+    addToCache(*m,url,fcontent,mimeType,fsize, NULL, 0);
+  }
+  else{
+    addToMap(*content,"isCached","true");
+    map* tmp=getMapFromMaps(*m,"main","cacheDir");
+    if(tmp!=NULL){
+      map *c=getMap((*content),"xlink:href");
+      char* md5str=getMd5(c->value);
+      char* fname=(char*)malloc(sizeof(char)*(strlen(tmp->value)+strlen(md5str)+6));
+      sprintf(fname,"%s/%s.zca",tmp->value,md5str);
+      addToMap(*content,"cache_file",fname);
+      free(fname);
+    }
+  }
+  free(fcontent);
+  free(mimeType);
+  free(cached);
+  return 0;
+}
diff --git a/zoo-project/zoo-kernel/caching.h b/zoo-project/zoo-kernel/caching.h
new file mode 100644
index 0000000..0ae3b0a
--- /dev/null
+++ b/zoo-project/zoo-kernel/caching.h
@@ -0,0 +1,40 @@
+/*
+ * Author : Gérald Fenoy
+ *
+ *  Copyright 2008-2015 GeoLabs SARL. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "ulinet.h"
+#include "service.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+  void addToCache(maps*,char*,char*,char*,int,char*,size_t);
+  char* isInCache(maps*,char*);
+  int runHttpRequests(maps**,maps**,HINTERNET*);
+  void addRequestToQueue(maps**,HINTERNET*,const char*,bool);
+  int loadRemoteFile(maps**,map**,HINTERNET*,char*);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/zoo-project/zoo-kernel/config.log b/zoo-project/zoo-kernel/config.log
new file mode 100644
index 0000000..db6dcca
--- /dev/null
+++ b/zoo-project/zoo-kernel/config.log
@@ -0,0 +1,5747 @@
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by ZOO Kernel configure 1.5.0, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  $ ./configure --with-python=yes --with-pyvers=2.7 --with-js=/usr/local/ --with-mapserver=/Users/djay/MapMint/src/mapserver-6.2.0/ --with-gdal-config=/Library/Frameworks/GDAL.framework/unix/bin/gdal-config --with-proj=/Library/Frameworks/PROJ.framework/unix --with-fastcgi=/usr/local/ --with-yaml=/usr/local/ --with-java=macos --with-geosconfig=/Library/Frameworks/GEOS.framework/unix/bin/geos-config --with-otb=/usr/local/ --with-saga=/usr/local/ --with-db-backend
+
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = MBP-de-Fenoy-2.home
+uname -m = x86_64
+uname -r = 14.3.0
+uname -s = Darwin
+uname -v = Darwin Kernel Version 14.3.0: Mon Mar 23 11:59:05 PDT 2015; root:xnu-2782.20.48~5/RELEASE_X86_64
+
+/usr/bin/uname -p = i386
+/bin/uname -X     = unknown
+
+/bin/arch              = unknown
+/usr/bin/arch -k       = unknown
+/usr/convex/getsysinfo = unknown
+/usr/bin/hostinfo      = Mach kernel version:
+	 Darwin Kernel Version 14.3.0: Mon Mar 23 11:59:05 PDT 2015; root:xnu-2782.20.48~5/RELEASE_X86_64
+Kernel configured for up to 8 processors.
+4 processors are physically available.
+8 processors are logically available.
+Processor type: i486 (Intel 80486)
+Processors active: 0 1 2 3 4 5 6 7
+Primary memory available: 16.00 gigabytes
+Default processor set: 309 tasks, 1497 threads, 8 processors
+Load average: 2.41, Mach factor: 5.58
+/bin/machine           = unknown
+/usr/bin/oslevel       = unknown
+/bin/universe          = unknown
+
+PATH: /usr/local/bin
+PATH: /usr/bin
+PATH: /bin
+PATH: /usr/sbin
+PATH: /sbin
+PATH: /opt/X11/bin
+PATH: /usr/local/MacGPG2/bin
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+configure:2646: checking for bison
+configure:2662: found /usr/bin/bison
+configure:2673: result: bison -y
+configure:2733: checking for gcc
+configure:2749: found /usr/bin/gcc
+configure:2760: result: gcc
+configure:2989: checking for C compiler version
+configure:2998: gcc --version >&5
+Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
+Target: x86_64-apple-darwin14.3.0
+Thread model: posix
+Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
+configure:3009: $? = 0
+configure:2998: gcc -v >&5
+Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
+Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
+Target: x86_64-apple-darwin14.3.0
+Thread model: posix
+configure:3009: $? = 0
+configure:2998: gcc -V >&5
+clang: error: argument to '-V' is missing (expected 1 value)
+clang: error: no input files
+configure:3009: $? = 1
+configure:2998: gcc -qversion >&5
+clang: error: unknown argument: '-qversion'
+clang: error: no input files
+configure:3009: $? = 1
+configure:3029: checking whether the C compiler works
+configure:3051: gcc    conftest.c  >&5
+configure:3055: $? = 0
+configure:3103: result: yes
+configure:3106: checking for C compiler default output file name
+configure:3108: result: a.out
+configure:3114: checking for suffix of executables
+configure:3121: gcc -o conftest    conftest.c  >&5
+configure:3125: $? = 0
+configure:3147: result: 
+configure:3169: checking whether we are cross compiling
+configure:3177: gcc -o conftest    conftest.c  >&5
+configure:3181: $? = 0
+configure:3188: ./conftest
+configure:3192: $? = 0
+configure:3207: result: no
+configure:3212: checking for suffix of object files
+configure:3234: gcc -c   conftest.c >&5
+configure:3238: $? = 0
+configure:3259: result: o
+configure:3263: checking whether we are using the GNU C compiler
+configure:3282: gcc -c   conftest.c >&5
+configure:3282: $? = 0
+configure:3291: result: yes
+configure:3300: checking whether gcc accepts -g
+configure:3320: gcc -c -g  conftest.c >&5
+configure:3320: $? = 0
+configure:3361: result: yes
+configure:3378: checking for gcc option to accept ISO C89
+configure:3441: gcc  -c -g -O2  conftest.c >&5
+configure:3441: $? = 0
+configure:3454: result: none needed
+configure:3479: checking for flex
+configure:3495: found /usr/bin/flex
+configure:3506: result: flex
+configure:3544: flex conftest.l
+configure:3548: $? = 0
+configure:3550: checking lex output file root
+configure:3564: result: lex.yy
+configure:3569: checking lex library
+configure:3583: gcc -o conftest -g -O2   conftest.c   >&5
+Undefined symbols for architecture x86_64:
+  "_yywrap", referenced from:
+      _yylex in conftest-ae0f70.o
+      _main in conftest-ae0f70.o
+ld: symbol(s) not found for architecture x86_64
+clang: error: linker command failed with exit code 1 (use -v to see invocation)
+configure:3583: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ZOO Kernel"
+| #define PACKAGE_TARNAME "zoo-kernel"
+| #define PACKAGE_VERSION "1.5.0"
+| #define PACKAGE_STRING "ZOO Kernel 1.5.0"
+| #define PACKAGE_BUGREPORT "bugs at zoo-project.org"
+| #define PACKAGE_URL ""
+| /* end confdefs.h.  */
+| 
+| #line 3 "lex.yy.c"
+| 
+| #define  YY_INT_ALIGNED short int
+| 
+| /* A lexical scanner generated by flex */
+| 
+| #define FLEX_SCANNER
+| #define YY_FLEX_MAJOR_VERSION 2
+| #define YY_FLEX_MINOR_VERSION 5
+| #define YY_FLEX_SUBMINOR_VERSION 35
+| #if YY_FLEX_SUBMINOR_VERSION > 0
+| #define FLEX_BETA
+| #endif
+| 
+| /* First, we deal with  platform-specific or compiler-specific issues. */
+| 
+| /* begin standard C headers. */
+| #include <stdio.h>
+| #include <string.h>
+| #include <errno.h>
+| #include <stdlib.h>
+| 
+| /* end standard C headers. */
+| 
+| /* flex integer type definitions */
+| 
+| #ifndef FLEXINT_H
+| #define FLEXINT_H
+| 
+| /* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+| 
+| #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+| 
+| /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+|  * if you want the limit (max/min) macros for int types. 
+|  */
+| #ifndef __STDC_LIMIT_MACROS
+| #define __STDC_LIMIT_MACROS 1
+| #endif
+| 
+| #include <inttypes.h>
+| typedef int8_t flex_int8_t;
+| typedef uint8_t flex_uint8_t;
+| typedef int16_t flex_int16_t;
+| typedef uint16_t flex_uint16_t;
+| typedef int32_t flex_int32_t;
+| typedef uint32_t flex_uint32_t;
+| typedef uint64_t flex_uint64_t;
+| #else
+| typedef signed char flex_int8_t;
+| typedef short int flex_int16_t;
+| typedef int flex_int32_t;
+| typedef unsigned char flex_uint8_t; 
+| typedef unsigned short int flex_uint16_t;
+| typedef unsigned int flex_uint32_t;
+| #endif /* ! C99 */
+| 
+| /* Limits of integral types. */
+| #ifndef INT8_MIN
+| #define INT8_MIN               (-128)
+| #endif
+| #ifndef INT16_MIN
+| #define INT16_MIN              (-32767-1)
+| #endif
+| #ifndef INT32_MIN
+| #define INT32_MIN              (-2147483647-1)
+| #endif
+| #ifndef INT8_MAX
+| #define INT8_MAX               (127)
+| #endif
+| #ifndef INT16_MAX
+| #define INT16_MAX              (32767)
+| #endif
+| #ifndef INT32_MAX
+| #define INT32_MAX              (2147483647)
+| #endif
+| #ifndef UINT8_MAX
+| #define UINT8_MAX              (255U)
+| #endif
+| #ifndef UINT16_MAX
+| #define UINT16_MAX             (65535U)
+| #endif
+| #ifndef UINT32_MAX
+| #define UINT32_MAX             (4294967295U)
+| #endif
+| 
+| #endif /* ! FLEXINT_H */
+| 
+| #ifdef __cplusplus
+| 
+| /* The "const" storage-class-modifier is valid. */
+| #define YY_USE_CONST
+| 
+| #else	/* ! __cplusplus */
+| 
+| /* C99 requires __STDC__ to be defined as 1. */
+| #if defined (__STDC__)
+| 
+| #define YY_USE_CONST
+| 
+| #endif	/* defined (__STDC__) */
+| #endif	/* ! __cplusplus */
+| 
+| #ifdef YY_USE_CONST
+| #define yyconst const
+| #else
+| #define yyconst
+| #endif
+| 
+| /* Returned upon end-of-file. */
+| #define YY_NULL 0
+| 
+| /* Promotes a possibly negative, possibly signed char to an unsigned
+|  * integer for use as an array index.  If the signed char is negative,
+|  * we want to instead treat it as an 8-bit unsigned char, hence the
+|  * double cast.
+|  */
+| #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+| 
+| /* Enter a start condition.  This macro really ought to take a parameter,
+|  * but we do it the disgusting crufty way forced on us by the ()-less
+|  * definition of BEGIN.
+|  */
+| #define BEGIN (yy_start) = 1 + 2 *
+| 
+| /* Translate the current start state into a value that can be later handed
+|  * to BEGIN to return to the state.  The YYSTATE alias is for lex
+|  * compatibility.
+|  */
+| #define YY_START (((yy_start) - 1) / 2)
+| #define YYSTATE YY_START
+| 
+| /* Action number for EOF rule of a given start state. */
+| #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+| 
+| /* Special action meaning "start processing a new file". */
+| #define YY_NEW_FILE yyrestart(yyin  )
+| 
+| #define YY_END_OF_BUFFER_CHAR 0
+| 
+| /* Size of default input buffer. */
+| #ifndef YY_BUF_SIZE
+| #define YY_BUF_SIZE 16384
+| #endif
+| 
+| /* The state buf must be large enough to hold one state per character in the main buffer.
+|  */
+| #define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+| 
+| #ifndef YY_TYPEDEF_YY_BUFFER_STATE
+| #define YY_TYPEDEF_YY_BUFFER_STATE
+| typedef struct yy_buffer_state *YY_BUFFER_STATE;
+| #endif
+| 
+| #ifndef YY_TYPEDEF_YY_SIZE_T
+| #define YY_TYPEDEF_YY_SIZE_T
+| typedef size_t yy_size_t;
+| #endif
+| 
+| extern yy_size_t yyleng;
+| 
+| extern FILE *yyin, *yyout;
+| 
+| #define EOB_ACT_CONTINUE_SCAN 0
+| #define EOB_ACT_END_OF_FILE 1
+| #define EOB_ACT_LAST_MATCH 2
+| 
+|     #define YY_LESS_LINENO(n)
+|     
+| /* Return all but the first "n" matched characters back to the input stream. */
+| #define yyless(n) \
+| 	do \
+| 		{ \
+| 		/* Undo effects of setting up yytext. */ \
+|         int yyless_macro_arg = (n); \
+|         YY_LESS_LINENO(yyless_macro_arg);\
+| 		*yy_cp = (yy_hold_char); \
+| 		YY_RESTORE_YY_MORE_OFFSET \
+| 		(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+| 		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+| 		} \
+| 	while ( 0 )
+| 
+| #define unput(c) yyunput( c, (yytext_ptr)  )
+| 
+| #ifndef YY_STRUCT_YY_BUFFER_STATE
+| #define YY_STRUCT_YY_BUFFER_STATE
+| struct yy_buffer_state
+| 	{
+| 	FILE *yy_input_file;
+| 
+| 	char *yy_ch_buf;		/* input buffer */
+| 	char *yy_buf_pos;		/* current position in input buffer */
+| 
+| 	/* Size of input buffer in bytes, not including room for EOB
+| 	 * characters.
+| 	 */
+| 	yy_size_t yy_buf_size;
+| 
+| 	/* Number of characters read into yy_ch_buf, not including EOB
+| 	 * characters.
+| 	 */
+| 	yy_size_t yy_n_chars;
+| 
+| 	/* Whether we "own" the buffer - i.e., we know we created it,
+| 	 * and can realloc() it to grow it, and should free() it to
+| 	 * delete it.
+| 	 */
+| 	int yy_is_our_buffer;
+| 
+| 	/* Whether this is an "interactive" input source; if so, and
+| 	 * if we're using stdio for input, then we want to use getc()
+| 	 * instead of fread(), to make sure we stop fetching input after
+| 	 * each newline.
+| 	 */
+| 	int yy_is_interactive;
+| 
+| 	/* Whether we're considered to be at the beginning of a line.
+| 	 * If so, '^' rules will be active on the next match, otherwise
+| 	 * not.
+| 	 */
+| 	int yy_at_bol;
+| 
+|     int yy_bs_lineno; /**< The line count. */
+|     int yy_bs_column; /**< The column count. */
+|     
+| 	/* Whether to try to fill the input buffer when we reach the
+| 	 * end of it.
+| 	 */
+| 	int yy_fill_buffer;
+| 
+| 	int yy_buffer_status;
+| 
+| #define YY_BUFFER_NEW 0
+| #define YY_BUFFER_NORMAL 1
+| 	/* When an EOF's been seen but there's still some text to process
+| 	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+| 	 * shouldn't try reading from the input source any more.  We might
+| 	 * still have a bunch of tokens to match, though, because of
+| 	 * possible backing-up.
+| 	 *
+| 	 * When we actually see the EOF, we change the status to "new"
+| 	 * (via yyrestart()), so that the user can continue scanning by
+| 	 * just pointing yyin at a new input file.
+| 	 */
+| #define YY_BUFFER_EOF_PENDING 2
+| 
+| 	};
+| #endif /* !YY_STRUCT_YY_BUFFER_STATE */
+| 
+| /* Stack of input buffers. */
+| static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+| static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+| static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
+| 
+| /* We provide macros for accessing buffer states in case in the
+|  * future we want to put the buffer states in a more general
+|  * "scanner state".
+|  *
+|  * Returns the top of the stack, or NULL.
+|  */
+| #define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+|                           ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+|                           : NULL)
+| 
+| /* Same as previous macro, but useful when we know that the buffer stack is not
+|  * NULL or when we need an lvalue. For internal use only.
+|  */
+| #define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+| 
+| /* yy_hold_char holds the character lost when yytext is formed. */
+| static char yy_hold_char;
+| static yy_size_t yy_n_chars;		/* number of characters read into yy_ch_buf */
+| yy_size_t yyleng;
+| 
+| /* Points to current character in buffer. */
+| static char *yy_c_buf_p = (char *) 0;
+| static int yy_init = 0;		/* whether we need to initialize */
+| static int yy_start = 0;	/* start state number */
+| 
+| /* Flag which is used to allow yywrap()'s to do buffer switches
+|  * instead of setting up a fresh yyin.  A bit of a hack ...
+|  */
+| static int yy_did_buffer_switch_on_eof;
+| 
+| void yyrestart (FILE *input_file  );
+| void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer  );
+| YY_BUFFER_STATE yy_create_buffer (FILE *file,int size  );
+| void yy_delete_buffer (YY_BUFFER_STATE b  );
+| void yy_flush_buffer (YY_BUFFER_STATE b  );
+| void yypush_buffer_state (YY_BUFFER_STATE new_buffer  );
+| void yypop_buffer_state (void );
+| 
+| static void yyensure_buffer_stack (void );
+| static void yy_load_buffer_state (void );
+| static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file  );
+| 
+| #define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
+| 
+| YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size  );
+| YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str  );
+| YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len  );
+| 
+| void *yyalloc (yy_size_t  );
+| void *yyrealloc (void *,yy_size_t  );
+| void yyfree (void *  );
+| 
+| #define yy_new_buffer yy_create_buffer
+| 
+| #define yy_set_interactive(is_interactive) \
+| 	{ \
+| 	if ( ! YY_CURRENT_BUFFER ){ \
+|         yyensure_buffer_stack (); \
+| 		YY_CURRENT_BUFFER_LVALUE =    \
+|             yy_create_buffer(yyin,YY_BUF_SIZE ); \
+| 	} \
+| 	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+| 	}
+| 
+| #define yy_set_bol(at_bol) \
+| 	{ \
+| 	if ( ! YY_CURRENT_BUFFER ){\
+|         yyensure_buffer_stack (); \
+| 		YY_CURRENT_BUFFER_LVALUE =    \
+|             yy_create_buffer(yyin,YY_BUF_SIZE ); \
+| 	} \
+| 	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+| 	}
+| 
+| #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+| 
+| /* Begin user sect3 */
+| 
+| typedef unsigned char YY_CHAR;
+| 
+| FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+| 
+| typedef int yy_state_type;
+| 
+| extern int yylineno;
+| 
+| int yylineno = 1;
+| 
+| extern char *yytext;
+| #define yytext_ptr yytext
+| 
+| static yy_state_type yy_get_previous_state (void );
+| static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
+| static int yy_get_next_buffer (void );
+| static void yy_fatal_error (yyconst char msg[]  );
+| 
+| /* Done after the current pattern has been matched and before the
+|  * corresponding action - sets up yytext.
+|  */
+| #define YY_DO_BEFORE_ACTION \
+| 	(yytext_ptr) = yy_bp; \
+| 	(yytext_ptr) -= (yy_more_len); \
+| 	yyleng = (yy_size_t) (yy_cp - (yytext_ptr)); \
+| 	(yy_hold_char) = *yy_cp; \
+| 	*yy_cp = '\0'; \
+| 	(yy_c_buf_p) = yy_cp;
+| 
+| #define YY_NUM_RULES 8
+| #define YY_END_OF_BUFFER 9
+| /* This struct is not used in this scanner,
+|    but its presence is necessary. */
+| struct yy_trans_info
+| 	{
+| 	flex_int32_t yy_verify;
+| 	flex_int32_t yy_nxt;
+| 	};
+| static yyconst flex_int16_t yy_acclist[23] =
+|     {   0,
+|         9,    7,    8,    8,    1,    7,    8,    2,    7,    8,
+|         3,    7,    8,    4,    7,    8,    5,    7,    8,    6,
+|         7,    8
+|     } ;
+| 
+| static yyconst flex_int16_t yy_accept[14] =
+|     {   0,
+|         1,    1,    1,    2,    4,    5,    8,   11,   14,   17,
+|        20,   23,   23
+|     } ;
+| 
+| static yyconst flex_int32_t yy_ec[256] =
+|     {   0,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    2,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    3,    4,    5,    6,
+| 
+|         7,    8,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+| 
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1
+|     } ;
+| 
+| static yyconst flex_int32_t yy_meta[9] =
+|     {   0,
+|         1,    1,    1,    1,    1,    1,    1,    1
+|     } ;
+| 
+| static yyconst flex_int16_t yy_base[13] =
+|     {   0,
+|         0,    0,    9,   10,   10,   10,   10,   10,   10,   10,
+|        10,   10
+|     } ;
+| 
+| static yyconst flex_int16_t yy_def[13] =
+|     {   0,
+|        12,    1,   12,   12,   12,   12,   12,   12,   12,   12,
+|        12,    0
+|     } ;
+| 
+| static yyconst flex_int16_t yy_nxt[19] =
+|     {   0,
+|         4,    5,    6,    7,    8,    9,   10,   11,   12,    3,
+|        12,   12,   12,   12,   12,   12,   12,   12
+|     } ;
+| 
+| static yyconst flex_int16_t yy_chk[19] =
+|     {   0,
+|         1,    1,    1,    1,    1,    1,    1,    1,    3,   12,
+|        12,   12,   12,   12,   12,   12,   12,   12
+|     } ;
+| 
+| extern int yy_flex_debug;
+| int yy_flex_debug = 0;
+| 
+| static yy_state_type *yy_state_buf=0, *yy_state_ptr=0;
+| static char *yy_full_match;
+| static int yy_lp;
+| #define REJECT \
+| { \
+| *yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ \
+| yy_cp = (yy_full_match); /* restore poss. backed-over text */ \
+| ++(yy_lp); \
+| goto find_rule; \
+| }
+| 
+| static int yy_more_flag = 0;
+| static int yy_more_len = 0;
+| #define yymore() ((yy_more_flag) = 1)
+| #define YY_MORE_ADJ (yy_more_len)
+| #define YY_RESTORE_YY_MORE_OFFSET
+| char *yytext;
+| #line 1 "conftest.l"
+| #line 469 "lex.yy.c"
+| 
+| #define INITIAL 0
+| 
+| #ifndef YY_NO_UNISTD_H
+| /* Special case for "unistd.h", since it is non-ANSI. We include it way
+|  * down here because we want the user's section 1 to have been scanned first.
+|  * The user has a chance to override it with an option.
+|  */
+| #include <unistd.h>
+| #endif
+| 
+| #ifndef YY_EXTRA_TYPE
+| #define YY_EXTRA_TYPE void *
+| #endif
+| 
+| static int yy_init_globals (void );
+| 
+| /* Accessor methods to globals.
+|    These are made visible to non-reentrant scanners for convenience. */
+| 
+| int yylex_destroy (void );
+| 
+| int yyget_debug (void );
+| 
+| void yyset_debug (int debug_flag  );
+| 
+| YY_EXTRA_TYPE yyget_extra (void );
+| 
+| void yyset_extra (YY_EXTRA_TYPE user_defined  );
+| 
+| FILE *yyget_in (void );
+| 
+| void yyset_in  (FILE * in_str  );
+| 
+| FILE *yyget_out (void );
+| 
+| void yyset_out  (FILE * out_str  );
+| 
+| yy_size_t yyget_leng (void );
+| 
+| char *yyget_text (void );
+| 
+| int yyget_lineno (void );
+| 
+| void yyset_lineno (int line_number  );
+| 
+| /* Macros after this point can all be overridden by user definitions in
+|  * section 1.
+|  */
+| 
+| #ifndef YY_SKIP_YYWRAP
+| #ifdef __cplusplus
+| extern "C" int yywrap (void );
+| #else
+| extern int yywrap (void );
+| #endif
+| #endif
+| 
+|     static void yyunput (int c,char *buf_ptr  );
+|     
+| #ifndef yytext_ptr
+| static void yy_flex_strncpy (char *,yyconst char *,int );
+| #endif
+| 
+| #ifdef YY_NEED_STRLEN
+| static int yy_flex_strlen (yyconst char * );
+| #endif
+| 
+| #ifndef YY_NO_INPUT
+| 
+| #ifdef __cplusplus
+| static int yyinput (void );
+| #else
+| static int input (void );
+| #endif
+| 
+| #endif
+| 
+| /* Amount of stuff to slurp up with each read. */
+| #ifndef YY_READ_BUF_SIZE
+| #define YY_READ_BUF_SIZE 8192
+| #endif
+| 
+| /* Copy whatever the last rule matched to the standard output. */
+| #ifndef ECHO
+| /* This used to be an fputs(), but since the string might contain NUL's,
+|  * we now use fwrite().
+|  */
+| #define ECHO fwrite( yytext, yyleng, 1, yyout )
+| #endif
+| 
+| /* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+|  * is returned in "result".
+|  */
+| #ifndef YY_INPUT
+| #define YY_INPUT(buf,result,max_size) \
+| 	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+| 		{ \
+| 		int c = '*'; \
+| 		yy_size_t n; \
+| 		for ( n = 0; n < max_size && \
+| 			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+| 			buf[n] = (char) c; \
+| 		if ( c == '\n' ) \
+| 			buf[n++] = (char) c; \
+| 		if ( c == EOF && ferror( yyin ) ) \
+| 			YY_FATAL_ERROR( "input in flex scanner failed" ); \
+| 		result = n; \
+| 		} \
+| 	else \
+| 		{ \
+| 		errno=0; \
+| 		while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+| 			{ \
+| 			if( errno != EINTR) \
+| 				{ \
+| 				YY_FATAL_ERROR( "input in flex scanner failed" ); \
+| 				break; \
+| 				} \
+| 			errno=0; \
+| 			clearerr(yyin); \
+| 			} \
+| 		}\
+| \
+| 
+| #endif
+| 
+| /* No semi-colon after return; correct usage is to write "yyterminate();" -
+|  * we don't want an extra ';' after the "return" because that will cause
+|  * some compilers to complain about unreachable statements.
+|  */
+| #ifndef yyterminate
+| #define yyterminate() return YY_NULL
+| #endif
+| 
+| /* Number of entries by which start-condition stack grows. */
+| #ifndef YY_START_STACK_INCR
+| #define YY_START_STACK_INCR 25
+| #endif
+| 
+| /* Report a fatal error. */
+| #ifndef YY_FATAL_ERROR
+| #define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+| #endif
+| 
+| /* end tables serialization structures and prototypes */
+| 
+| /* Default declaration of generated scanner - a define so the user can
+|  * easily add parameters.
+|  */
+| #ifndef YY_DECL
+| #define YY_DECL_IS_OURS 1
+| 
+| extern int yylex (void);
+| 
+| #define YY_DECL int yylex (void)
+| #endif /* !YY_DECL */
+| 
+| /* Code executed at the beginning of each rule, after yytext and yyleng
+|  * have been set up.
+|  */
+| #ifndef YY_USER_ACTION
+| #define YY_USER_ACTION
+| #endif
+| 
+| /* Code executed at the end of each rule. */
+| #ifndef YY_BREAK
+| #define YY_BREAK break;
+| #endif
+| 
+| #define YY_RULE_SETUP \
+| 	YY_USER_ACTION
+| 
+| /** The main scanner function which does all the work.
+|  */
+| YY_DECL
+| {
+| 	register yy_state_type yy_current_state;
+| 	register char *yy_cp, *yy_bp;
+| 	register int yy_act;
+|     
+| #line 1 "conftest.l"
+| 
+| #line 653 "lex.yy.c"
+| 
+| 	if ( !(yy_init) )
+| 		{
+| 		(yy_init) = 1;
+| 
+| #ifdef YY_USER_INIT
+| 		YY_USER_INIT;
+| #endif
+| 
+|         /* Create the reject buffer large enough to save one state per allowed character. */
+|         if ( ! (yy_state_buf) )
+|             (yy_state_buf) = (yy_state_type *)yyalloc(YY_STATE_BUF_SIZE  );
+|             if ( ! (yy_state_buf) )
+|                 YY_FATAL_ERROR( "out of dynamic memory in yylex()" );
+| 
+| 		if ( ! (yy_start) )
+| 			(yy_start) = 1;	/* first start state */
+| 
+| 		if ( ! yyin )
+| 			yyin = stdin;
+| 
+| 		if ( ! yyout )
+| 			yyout = stdout;
+| 
+| 		if ( ! YY_CURRENT_BUFFER ) {
+| 			yyensure_buffer_stack ();
+| 			YY_CURRENT_BUFFER_LVALUE =
+| 				yy_create_buffer(yyin,YY_BUF_SIZE );
+| 		}
+| 
+| 		yy_load_buffer_state( );
+| 		}
+| 
+| 	while ( 1 )		/* loops until end-of-file is reached */
+| 		{
+| 		(yy_more_len) = 0;
+| 		if ( (yy_more_flag) )
+| 			{
+| 			(yy_more_len) = (yy_c_buf_p) - (yytext_ptr);
+| 			(yy_more_flag) = 0;
+| 			}
+| 		yy_cp = (yy_c_buf_p);
+| 
+| 		/* Support of yytext. */
+| 		*yy_cp = (yy_hold_char);
+| 
+| 		/* yy_bp points to the position in yy_ch_buf of the start of
+| 		 * the current run.
+| 		 */
+| 		yy_bp = yy_cp;
+| 
+| 		yy_current_state = (yy_start);
+| 
+| 		(yy_state_ptr) = (yy_state_buf);
+| 		*(yy_state_ptr)++ = yy_current_state;
+| 
+| yy_match:
+| 		do
+| 			{
+| 			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+| 			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+| 				{
+| 				yy_current_state = (int) yy_def[yy_current_state];
+| 				if ( yy_current_state >= 13 )
+| 					yy_c = yy_meta[(unsigned int) yy_c];
+| 				}
+| 			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+| 			*(yy_state_ptr)++ = yy_current_state;
+| 			++yy_cp;
+| 			}
+| 		while ( yy_base[yy_current_state] != 10 );
+| 
+| yy_find_action:
+| 		yy_current_state = *--(yy_state_ptr);
+| 		(yy_lp) = yy_accept[yy_current_state];
+| goto find_rule; /* Shut up GCC warning -Wall */
+| find_rule: /* we branch to this label when backing up */
+| 		for ( ; ; ) /* until we find what rule we matched */
+| 			{
+| 			if ( (yy_lp) && (yy_lp) < yy_accept[yy_current_state + 1] )
+| 				{
+| 				yy_act = yy_acclist[(yy_lp)];
+| 					{
+| 					(yy_full_match) = yy_cp;
+| 					break;
+| 					}
+| 				}
+| 			--yy_cp;
+| 			yy_current_state = *--(yy_state_ptr);
+| 			(yy_lp) = yy_accept[yy_current_state];
+| 			}
+| 
+| 		YY_DO_BEFORE_ACTION;
+| 
+| do_action:	/* This label is used only to access EOF actions. */
+| 
+| 		switch ( yy_act )
+| 	{ /* beginning of action switch */
+| case 1:
+| YY_RULE_SETUP
+| #line 2 "conftest.l"
+| { ECHO; }
+| 	YY_BREAK
+| case 2:
+| YY_RULE_SETUP
+| #line 3 "conftest.l"
+| { REJECT; }
+| 	YY_BREAK
+| case 3:
+| YY_RULE_SETUP
+| #line 4 "conftest.l"
+| { yymore (); }
+| 	YY_BREAK
+| case 4:
+| YY_RULE_SETUP
+| #line 5 "conftest.l"
+| { yyless (1); }
+| 	YY_BREAK
+| case 5:
+| YY_RULE_SETUP
+| #line 6 "conftest.l"
+| { /* IRIX 6.5 flex 2.5.4 underquotes its yyless argument.  */
+|     yyless ((input () != 0)); }
+| 	YY_BREAK
+| case 6:
+| YY_RULE_SETUP
+| #line 8 "conftest.l"
+| { unput (yytext[0]); }
+| 	YY_BREAK
+| case 7:
+| YY_RULE_SETUP
+| #line 9 "conftest.l"
+| { BEGIN INITIAL; }
+| 	YY_BREAK
+| case 8:
+| YY_RULE_SETUP
+| #line 10 "conftest.l"
+| ECHO;
+| 	YY_BREAK
+| #line 793 "lex.yy.c"
+| 			case YY_STATE_EOF(INITIAL):
+| 				yyterminate();
+| 
+| 	case YY_END_OF_BUFFER:
+| 		{
+| 		/* Amount of text matched not including the EOB char. */
+| 		int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+| 
+| 		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+| 		*yy_cp = (yy_hold_char);
+| 		YY_RESTORE_YY_MORE_OFFSET
+| 
+| 		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+| 			{
+| 			/* We're scanning a new file or input source.  It's
+| 			 * possible that this happened because the user
+| 			 * just pointed yyin at a new source and called
+| 			 * yylex().  If so, then we have to assure
+| 			 * consistency between YY_CURRENT_BUFFER and our
+| 			 * globals.  Here is the right place to do so, because
+| 			 * this is the first action (other than possibly a
+| 			 * back-up) that will match for the new input source.
+| 			 */
+| 			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+| 			YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+| 			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+| 			}
+| 
+| 		/* Note that here we test for yy_c_buf_p "<=" to the position
+| 		 * of the first EOB in the buffer, since yy_c_buf_p will
+| 		 * already have been incremented past the NUL character
+| 		 * (since all states make transitions on EOB to the
+| 		 * end-of-buffer state).  Contrast this with the test
+| 		 * in input().
+| 		 */
+| 		if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+| 			{ /* This was really a NUL. */
+| 			yy_state_type yy_next_state;
+| 
+| 			(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+| 
+| 			yy_current_state = yy_get_previous_state(  );
+| 
+| 			/* Okay, we're now positioned to make the NUL
+| 			 * transition.  We couldn't have
+| 			 * yy_get_previous_state() go ahead and do it
+| 			 * for us because it doesn't know how to deal
+| 			 * with the possibility of jamming (and we don't
+| 			 * want to build jamming into it because then it
+| 			 * will run more slowly).
+| 			 */
+| 
+| 			yy_next_state = yy_try_NUL_trans( yy_current_state );
+| 
+| 			yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+| 
+| 			if ( yy_next_state )
+| 				{
+| 				/* Consume the NUL. */
+| 				yy_cp = ++(yy_c_buf_p);
+| 				yy_current_state = yy_next_state;
+| 				goto yy_match;
+| 				}
+| 
+| 			else
+| 				{
+| 				yy_cp = (yy_c_buf_p);
+| 				goto yy_find_action;
+| 				}
+| 			}
+| 
+| 		else switch ( yy_get_next_buffer(  ) )
+| 			{
+| 			case EOB_ACT_END_OF_FILE:
+| 				{
+| 				(yy_did_buffer_switch_on_eof) = 0;
+| 
+| 				if ( yywrap( ) )
+| 					{
+| 					/* Note: because we've taken care in
+| 					 * yy_get_next_buffer() to have set up
+| 					 * yytext, we can now set up
+| 					 * yy_c_buf_p so that if some total
+| 					 * hoser (like flex itself) wants to
+| 					 * call the scanner after we return the
+| 					 * YY_NULL, it'll still work - another
+| 					 * YY_NULL will get returned.
+| 					 */
+| 					(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+| 
+| 					yy_act = YY_STATE_EOF(YY_START);
+| 					goto do_action;
+| 					}
+| 
+| 				else
+| 					{
+| 					if ( ! (yy_did_buffer_switch_on_eof) )
+| 						YY_NEW_FILE;
+| 					}
+| 				break;
+| 				}
+| 
+| 			case EOB_ACT_CONTINUE_SCAN:
+| 				(yy_c_buf_p) =
+| 					(yytext_ptr) + yy_amount_of_matched_text;
+| 
+| 				yy_current_state = yy_get_previous_state(  );
+| 
+| 				yy_cp = (yy_c_buf_p);
+| 				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+| 				goto yy_match;
+| 
+| 			case EOB_ACT_LAST_MATCH:
+| 				(yy_c_buf_p) =
+| 				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+| 
+| 				yy_current_state = yy_get_previous_state(  );
+| 
+| 				yy_cp = (yy_c_buf_p);
+| 				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+| 				goto yy_find_action;
+| 			}
+| 		break;
+| 		}
+| 
+| 	default:
+| 		YY_FATAL_ERROR(
+| 			"fatal flex scanner internal error--no action found" );
+| 	} /* end of action switch */
+| 		} /* end of scanning one token */
+| } /* end of yylex */
+| 
+| /* yy_get_next_buffer - try to read in a new buffer
+|  *
+|  * Returns a code representing an action:
+|  *	EOB_ACT_LAST_MATCH -
+|  *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+|  *	EOB_ACT_END_OF_FILE - end of file
+|  */
+| static int yy_get_next_buffer (void)
+| {
+|     	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+| 	register char *source = (yytext_ptr);
+| 	register int number_to_move, i;
+| 	int ret_val;
+| 
+| 	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+| 		YY_FATAL_ERROR(
+| 		"fatal flex scanner internal error--end of buffer missed" );
+| 
+| 	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+| 		{ /* Don't try to fill the buffer, so this is an EOF. */
+| 		if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+| 			{
+| 			/* We matched a single character, the EOB, so
+| 			 * treat this as a final EOF.
+| 			 */
+| 			return EOB_ACT_END_OF_FILE;
+| 			}
+| 
+| 		else
+| 			{
+| 			/* We matched some text prior to the EOB, first
+| 			 * process it.
+| 			 */
+| 			return EOB_ACT_LAST_MATCH;
+| 			}
+| 		}
+| 
+| 	/* Try to read more data. */
+| 
+| 	/* First move last chars to start of buffer. */
+| 	number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+| 
+| 	for ( i = 0; i < number_to_move; ++i )
+| 		*(dest++) = *(source++);
+| 
+| 	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+| 		/* don't do the read, it's not guaranteed to return an EOF,
+| 		 * just force an EOF
+| 		 */
+| 		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+| 
+| 	else
+| 		{
+| 			yy_size_t num_to_read =
+| 			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+| 
+| 		while ( num_to_read <= 0 )
+| 			{ /* Not enough room in the buffer - grow it. */
+| 
+| 			YY_FATAL_ERROR(
+| "input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+| 
+| 			}
+| 
+| 		if ( num_to_read > YY_READ_BUF_SIZE )
+| 			num_to_read = YY_READ_BUF_SIZE;
+| 
+| 		/* Read in more data. */
+| 		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+| 			(yy_n_chars), num_to_read );
+| 
+| 		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+| 		}
+| 
+| 	if ( (yy_n_chars) == 0 )
+| 		{
+| 		if ( number_to_move == YY_MORE_ADJ )
+| 			{
+| 			ret_val = EOB_ACT_END_OF_FILE;
+| 			yyrestart(yyin  );
+| 			}
+| 
+| 		else
+| 			{
+| 			ret_val = EOB_ACT_LAST_MATCH;
+| 			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+| 				YY_BUFFER_EOF_PENDING;
+| 			}
+| 		}
+| 
+| 	else
+| 		ret_val = EOB_ACT_CONTINUE_SCAN;
+| 
+| 	if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+| 		/* Extend the array by 50%, plus the number we really need. */
+| 		yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+| 		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size  );
+| 		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+| 			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+| 	}
+| 
+| 	(yy_n_chars) += number_to_move;
+| 	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+| 	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+| 
+| 	(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+| 
+| 	return ret_val;
+| }
+| 
+| /* yy_get_previous_state - get the state just before the EOB char was reached */
+| 
+|     static yy_state_type yy_get_previous_state (void)
+| {
+| 	register yy_state_type yy_current_state;
+| 	register char *yy_cp;
+|     
+| 	yy_current_state = (yy_start);
+| 
+| 	(yy_state_ptr) = (yy_state_buf);
+| 	*(yy_state_ptr)++ = yy_current_state;
+| 
+| 	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+| 		{
+| 		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+| 		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+| 			{
+| 			yy_current_state = (int) yy_def[yy_current_state];
+| 			if ( yy_current_state >= 13 )
+| 				yy_c = yy_meta[(unsigned int) yy_c];
+| 			}
+| 		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+| 		*(yy_state_ptr)++ = yy_current_state;
+| 		}
+| 
+| 	return yy_current_state;
+| }
+| 
+| /* yy_try_NUL_trans - try to make a transition on the NUL character
+|  *
+|  * synopsis
+|  *	next_state = yy_try_NUL_trans( current_state );
+|  */
+|     static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
+| {
+| 	register int yy_is_jam;
+|     
+| 	register YY_CHAR yy_c = 1;
+| 	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+| 		{
+| 		yy_current_state = (int) yy_def[yy_current_state];
+| 		if ( yy_current_state >= 13 )
+| 			yy_c = yy_meta[(unsigned int) yy_c];
+| 		}
+| 	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+| 	yy_is_jam = (yy_current_state == 12);
+| 	if ( ! yy_is_jam )
+| 		*(yy_state_ptr)++ = yy_current_state;
+| 
+| 	return yy_is_jam ? 0 : yy_current_state;
+| }
+| 
+|     static void yyunput (int c, register char * yy_bp )
+| {
+| 	register char *yy_cp;
+|     
+|     yy_cp = (yy_c_buf_p);
+| 
+| 	/* undo effects of setting up yytext */
+| 	*yy_cp = (yy_hold_char);
+| 
+| 	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+| 		{ /* need to shift things up to make room */
+| 		/* +2 for EOB chars. */
+| 		register yy_size_t number_to_move = (yy_n_chars) + 2;
+| 		register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+| 					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+| 		register char *source =
+| 				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+| 
+| 		while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+| 			*--dest = *--source;
+| 
+| 		yy_cp += (int) (dest - source);
+| 		yy_bp += (int) (dest - source);
+| 		YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+| 			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+| 
+| 		if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+| 			YY_FATAL_ERROR( "flex scanner push-back overflow" );
+| 		}
+| 
+| 	*--yy_cp = (char) c;
+| 
+| 	(yytext_ptr) = yy_bp;
+| 	(yy_hold_char) = *yy_cp;
+| 	(yy_c_buf_p) = yy_cp;
+| }
+| 
+| #ifndef YY_NO_INPUT
+| #ifdef __cplusplus
+|     static int yyinput (void)
+| #else
+|     static int input  (void)
+| #endif
+| 
+| {
+| 	int c;
+|     
+| 	*(yy_c_buf_p) = (yy_hold_char);
+| 
+| 	if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+| 		{
+| 		/* yy_c_buf_p now points to the character we want to return.
+| 		 * If this occurs *before* the EOB characters, then it's a
+| 		 * valid NUL; if not, then we've hit the end of the buffer.
+| 		 */
+| 		if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+| 			/* This was really a NUL. */
+| 			*(yy_c_buf_p) = '\0';
+| 
+| 		else
+| 			{ /* need more input */
+| 			yy_size_t offset = (yy_c_buf_p) - (yytext_ptr);
+| 			++(yy_c_buf_p);
+| 
+| 			switch ( yy_get_next_buffer(  ) )
+| 				{
+| 				case EOB_ACT_LAST_MATCH:
+| 					/* This happens because yy_g_n_b()
+| 					 * sees that we've accumulated a
+| 					 * token and flags that we need to
+| 					 * try matching the token before
+| 					 * proceeding.  But for input(),
+| 					 * there's no matching to consider.
+| 					 * So convert the EOB_ACT_LAST_MATCH
+| 					 * to EOB_ACT_END_OF_FILE.
+| 					 */
+| 
+| 					/* Reset buffer status. */
+| 					yyrestart(yyin );
+| 
+| 					/*FALLTHROUGH*/
+| 
+| 				case EOB_ACT_END_OF_FILE:
+| 					{
+| 					if ( yywrap( ) )
+| 						return 0;
+| 
+| 					if ( ! (yy_did_buffer_switch_on_eof) )
+| 						YY_NEW_FILE;
+| #ifdef __cplusplus
+| 					return yyinput();
+| #else
+| 					return input();
+| #endif
+| 					}
+| 
+| 				case EOB_ACT_CONTINUE_SCAN:
+| 					(yy_c_buf_p) = (yytext_ptr) + offset;
+| 					break;
+| 				}
+| 			}
+| 		}
+| 
+| 	c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */
+| 	*(yy_c_buf_p) = '\0';	/* preserve yytext */
+| 	(yy_hold_char) = *++(yy_c_buf_p);
+| 
+| 	return c;
+| }
+| #endif	/* ifndef YY_NO_INPUT */
+| 
+| /** Immediately switch to a different input stream.
+|  * @param input_file A readable stream.
+|  * 
+|  * @note This function does not reset the start condition to @c INITIAL .
+|  */
+|     void yyrestart  (FILE * input_file )
+| {
+|     
+| 	if ( ! YY_CURRENT_BUFFER ){
+|         yyensure_buffer_stack ();
+| 		YY_CURRENT_BUFFER_LVALUE =
+|             yy_create_buffer(yyin,YY_BUF_SIZE );
+| 	}
+| 
+| 	yy_init_buffer(YY_CURRENT_BUFFER,input_file );
+| 	yy_load_buffer_state( );
+| }
+| 
+| /** Switch to a different input buffer.
+|  * @param new_buffer The new input buffer.
+|  * 
+|  */
+|     void yy_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
+| {
+|     
+| 	/* TODO. We should be able to replace this entire function body
+| 	 * with
+| 	 *		yypop_buffer_state();
+| 	 *		yypush_buffer_state(new_buffer);
+|      */
+| 	yyensure_buffer_stack ();
+| 	if ( YY_CURRENT_BUFFER == new_buffer )
+| 		return;
+| 
+| 	if ( YY_CURRENT_BUFFER )
+| 		{
+| 		/* Flush out information for old buffer. */
+| 		*(yy_c_buf_p) = (yy_hold_char);
+| 		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+| 		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+| 		}
+| 
+| 	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+| 	yy_load_buffer_state( );
+| 
+| 	/* We don't actually know whether we did this switch during
+| 	 * EOF (yywrap()) processing, but the only time this flag
+| 	 * is looked at is after yywrap() is called, so it's safe
+| 	 * to go ahead and always set it.
+| 	 */
+| 	(yy_did_buffer_switch_on_eof) = 1;
+| }
+| 
+| static void yy_load_buffer_state  (void)
+| {
+|     	(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+| 	(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+| 	yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+| 	(yy_hold_char) = *(yy_c_buf_p);
+| }
+| 
+| /** Allocate and initialize an input buffer state.
+|  * @param file A readable stream.
+|  * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+|  * 
+|  * @return the allocated buffer state.
+|  */
+|     YY_BUFFER_STATE yy_create_buffer  (FILE * file, int  size )
+| {
+| 	YY_BUFFER_STATE b;
+|     
+| 	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
+| 	if ( ! b )
+| 		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+| 
+| 	b->yy_buf_size = size;
+| 
+| 	/* yy_ch_buf has to be 2 characters longer than the size given because
+| 	 * we need to put in 2 end-of-buffer characters.
+| 	 */
+| 	b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2  );
+| 	if ( ! b->yy_ch_buf )
+| 		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+| 
+| 	b->yy_is_our_buffer = 1;
+| 
+| 	yy_init_buffer(b,file );
+| 
+| 	return b;
+| }
+| 
+| /** Destroy the buffer.
+|  * @param b a buffer created with yy_create_buffer()
+|  * 
+|  */
+|     void yy_delete_buffer (YY_BUFFER_STATE  b )
+| {
+|     
+| 	if ( ! b )
+| 		return;
+| 
+| 	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+| 		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+| 
+| 	if ( b->yy_is_our_buffer )
+| 		yyfree((void *) b->yy_ch_buf  );
+| 
+| 	yyfree((void *) b  );
+| }
+| 
+| #ifndef __cplusplus
+| extern int isatty (int );
+| #endif /* __cplusplus */
+|     
+| /* Initializes or reinitializes a buffer.
+|  * This function is sometimes called more than once on the same buffer,
+|  * such as during a yyrestart() or at EOF.
+|  */
+|     static void yy_init_buffer  (YY_BUFFER_STATE  b, FILE * file )
+| 
+| {
+| 	int oerrno = errno;
+|     
+| 	yy_flush_buffer(b );
+| 
+| 	b->yy_input_file = file;
+| 	b->yy_fill_buffer = 1;
+| 
+|     /* If b is the current buffer, then yy_init_buffer was _probably_
+|      * called from yyrestart() or through yy_get_next_buffer.
+|      * In that case, we don't want to reset the lineno or column.
+|      */
+|     if (b != YY_CURRENT_BUFFER){
+|         b->yy_bs_lineno = 1;
+|         b->yy_bs_column = 0;
+|     }
+| 
+|         b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+|     
+| 	errno = oerrno;
+| }
+| 
+| /** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+|  * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+|  * 
+|  */
+|     void yy_flush_buffer (YY_BUFFER_STATE  b )
+| {
+|     	if ( ! b )
+| 		return;
+| 
+| 	b->yy_n_chars = 0;
+| 
+| 	/* We always need two end-of-buffer characters.  The first causes
+| 	 * a transition to the end-of-buffer state.  The second causes
+| 	 * a jam in that state.
+| 	 */
+| 	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+| 	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+| 
+| 	b->yy_buf_pos = &b->yy_ch_buf[0];
+| 
+| 	b->yy_at_bol = 1;
+| 	b->yy_buffer_status = YY_BUFFER_NEW;
+| 
+| 	if ( b == YY_CURRENT_BUFFER )
+| 		yy_load_buffer_state( );
+| }
+| 
+| /** Pushes the new state onto the stack. The new state becomes
+|  *  the current state. This function will allocate the stack
+|  *  if necessary.
+|  *  @param new_buffer The new state.
+|  *  
+|  */
+| void yypush_buffer_state (YY_BUFFER_STATE new_buffer )
+| {
+|     	if (new_buffer == NULL)
+| 		return;
+| 
+| 	yyensure_buffer_stack();
+| 
+| 	/* This block is copied from yy_switch_to_buffer. */
+| 	if ( YY_CURRENT_BUFFER )
+| 		{
+| 		/* Flush out information for old buffer. */
+| 		*(yy_c_buf_p) = (yy_hold_char);
+| 		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+| 		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+| 		}
+| 
+| 	/* Only push if top exists. Otherwise, replace top. */
+| 	if (YY_CURRENT_BUFFER)
+| 		(yy_buffer_stack_top)++;
+| 	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+| 
+| 	/* copied from yy_switch_to_buffer. */
+| 	yy_load_buffer_state( );
+| 	(yy_did_buffer_switch_on_eof) = 1;
+| }
+| 
+| /** Removes and deletes the top of the stack, if present.
+|  *  The next element becomes the new top.
+|  *  
+|  */
+| void yypop_buffer_state (void)
+| {
+|     	if (!YY_CURRENT_BUFFER)
+| 		return;
+| 
+| 	yy_delete_buffer(YY_CURRENT_BUFFER );
+| 	YY_CURRENT_BUFFER_LVALUE = NULL;
+| 	if ((yy_buffer_stack_top) > 0)
+| 		--(yy_buffer_stack_top);
+| 
+| 	if (YY_CURRENT_BUFFER) {
+| 		yy_load_buffer_state( );
+| 		(yy_did_buffer_switch_on_eof) = 1;
+| 	}
+| }
+| 
+| /* Allocates the stack if it does not exist.
+|  *  Guarantees space for at least one push.
+|  */
+| static void yyensure_buffer_stack (void)
+| {
+| 	yy_size_t num_to_alloc;
+|     
+| 	if (!(yy_buffer_stack)) {
+| 
+| 		/* First allocation is just for 2 elements, since we don't know if this
+| 		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
+| 		 * immediate realloc on the next call.
+|          */
+| 		num_to_alloc = 1;
+| 		(yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
+| 								(num_to_alloc * sizeof(struct yy_buffer_state*)
+| 								);
+| 		if ( ! (yy_buffer_stack) )
+| 			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+| 								  
+| 		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+| 				
+| 		(yy_buffer_stack_max) = num_to_alloc;
+| 		(yy_buffer_stack_top) = 0;
+| 		return;
+| 	}
+| 
+| 	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+| 
+| 		/* Increase the buffer to prepare for a possible push. */
+| 		int grow_size = 8 /* arbitrary grow size */;
+| 
+| 		num_to_alloc = (yy_buffer_stack_max) + grow_size;
+| 		(yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
+| 								((yy_buffer_stack),
+| 								num_to_alloc * sizeof(struct yy_buffer_state*)
+| 								);
+| 		if ( ! (yy_buffer_stack) )
+| 			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+| 
+| 		/* zero only the new slots.*/
+| 		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+| 		(yy_buffer_stack_max) = num_to_alloc;
+| 	}
+| }
+| 
+| /** Setup the input buffer state to scan directly from a user-specified character buffer.
+|  * @param base the character buffer
+|  * @param size the size in bytes of the character buffer
+|  * 
+|  * @return the newly allocated buffer state object. 
+|  */
+| YY_BUFFER_STATE yy_scan_buffer  (char * base, yy_size_t  size )
+| {
+| 	YY_BUFFER_STATE b;
+|     
+| 	if ( size < 2 ||
+| 	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
+| 	     base[size-1] != YY_END_OF_BUFFER_CHAR )
+| 		/* They forgot to leave room for the EOB's. */
+| 		return 0;
+| 
+| 	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
+| 	if ( ! b )
+| 		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+| 
+| 	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
+| 	b->yy_buf_pos = b->yy_ch_buf = base;
+| 	b->yy_is_our_buffer = 0;
+| 	b->yy_input_file = 0;
+| 	b->yy_n_chars = b->yy_buf_size;
+| 	b->yy_is_interactive = 0;
+| 	b->yy_at_bol = 1;
+| 	b->yy_fill_buffer = 0;
+| 	b->yy_buffer_status = YY_BUFFER_NEW;
+| 
+| 	yy_switch_to_buffer(b  );
+| 
+| 	return b;
+| }
+| 
+| /** Setup the input buffer state to scan a string. The next call to yylex() will
+|  * scan from a @e copy of @a str.
+|  * @param yystr a NUL-terminated string to scan
+|  * 
+|  * @return the newly allocated buffer state object.
+|  * @note If you want to scan bytes that may contain NUL values, then use
+|  *       yy_scan_bytes() instead.
+|  */
+| YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
+| {
+|     
+| 	return yy_scan_bytes(yystr,strlen(yystr) );
+| }
+| 
+| /** Setup the input buffer state to scan the given bytes. The next call to yylex() will
+|  * scan from a @e copy of @a bytes.
+|  * @param bytes the byte buffer to scan
+|  * @param len the number of bytes in the buffer pointed to by @a bytes.
+|  * 
+|  * @return the newly allocated buffer state object.
+|  */
+| YY_BUFFER_STATE yy_scan_bytes  (yyconst char * yybytes, yy_size_t  _yybytes_len )
+| {
+| 	YY_BUFFER_STATE b;
+| 	char *buf;
+| 	yy_size_t n, i;
+|     
+| 	/* Get memory for full buffer, including space for trailing EOB's. */
+| 	n = _yybytes_len + 2;
+| 	buf = (char *) yyalloc(n  );
+| 	if ( ! buf )
+| 		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+| 
+| 	for ( i = 0; i < _yybytes_len; ++i )
+| 		buf[i] = yybytes[i];
+| 
+| 	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+| 
+| 	b = yy_scan_buffer(buf,n );
+| 	if ( ! b )
+| 		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+| 
+| 	/* It's okay to grow etc. this buffer, and we should throw it
+| 	 * away when we're done.
+| 	 */
+| 	b->yy_is_our_buffer = 1;
+| 
+| 	return b;
+| }
+| 
+| #ifndef YY_EXIT_FAILURE
+| #define YY_EXIT_FAILURE 2
+| #endif
+| 
+| static void yy_fatal_error (yyconst char* msg )
+| {
+|     	(void) fprintf( stderr, "%s\n", msg );
+| 	exit( YY_EXIT_FAILURE );
+| }
+| 
+| /* Redefine yyless() so it works in section 3 code. */
+| 
+| #undef yyless
+| #define yyless(n) \
+| 	do \
+| 		{ \
+| 		/* Undo effects of setting up yytext. */ \
+|         int yyless_macro_arg = (n); \
+|         YY_LESS_LINENO(yyless_macro_arg);\
+| 		yytext[yyleng] = (yy_hold_char); \
+| 		(yy_c_buf_p) = yytext + yyless_macro_arg; \
+| 		(yy_hold_char) = *(yy_c_buf_p); \
+| 		*(yy_c_buf_p) = '\0'; \
+| 		yyleng = yyless_macro_arg; \
+| 		} \
+| 	while ( 0 )
+| 
+| /* Accessor  methods (get/set functions) to struct members. */
+| 
+| /** Get the current line number.
+|  * 
+|  */
+| int yyget_lineno  (void)
+| {
+|         
+|     return yylineno;
+| }
+| 
+| /** Get the input stream.
+|  * 
+|  */
+| FILE *yyget_in  (void)
+| {
+|         return yyin;
+| }
+| 
+| /** Get the output stream.
+|  * 
+|  */
+| FILE *yyget_out  (void)
+| {
+|         return yyout;
+| }
+| 
+| /** Get the length of the current token.
+|  * 
+|  */
+| yy_size_t yyget_leng  (void)
+| {
+|         return yyleng;
+| }
+| 
+| /** Get the current token.
+|  * 
+|  */
+| 
+| char *yyget_text  (void)
+| {
+|         return yytext;
+| }
+| 
+| /** Set the current line number.
+|  * @param line_number
+|  * 
+|  */
+| void yyset_lineno (int  line_number )
+| {
+|     
+|     yylineno = line_number;
+| }
+| 
+| /** Set the input stream. This does not discard the current
+|  * input buffer.
+|  * @param in_str A readable stream.
+|  * 
+|  * @see yy_switch_to_buffer
+|  */
+| void yyset_in (FILE *  in_str )
+| {
+|         yyin = in_str ;
+| }
+| 
+| void yyset_out (FILE *  out_str )
+| {
+|         yyout = out_str ;
+| }
+| 
+| int yyget_debug  (void)
+| {
+|         return yy_flex_debug;
+| }
+| 
+| void yyset_debug (int  bdebug )
+| {
+|         yy_flex_debug = bdebug ;
+| }
+| 
+| static int yy_init_globals (void)
+| {
+|         /* Initialization is the same as for the non-reentrant scanner.
+|      * This function is called from yylex_destroy(), so don't allocate here.
+|      */
+| 
+|     (yy_buffer_stack) = 0;
+|     (yy_buffer_stack_top) = 0;
+|     (yy_buffer_stack_max) = 0;
+|     (yy_c_buf_p) = (char *) 0;
+|     (yy_init) = 0;
+|     (yy_start) = 0;
+| 
+|     (yy_state_buf) = 0;
+|     (yy_state_ptr) = 0;
+|     (yy_full_match) = 0;
+|     (yy_lp) = 0;
+| 
+| /* Defined in main.c */
+| #ifdef YY_STDINIT
+|     yyin = stdin;
+|     yyout = stdout;
+| #else
+|     yyin = (FILE *) 0;
+|     yyout = (FILE *) 0;
+| #endif
+| 
+|     /* For future reference: Set errno on error, since we are called by
+|      * yylex_init()
+|      */
+|     return 0;
+| }
+| 
+| /* yylex_destroy is for both reentrant and non-reentrant scanners. */
+| int yylex_destroy  (void)
+| {
+|     
+|     /* Pop the buffer stack, destroying each element. */
+| 	while(YY_CURRENT_BUFFER){
+| 		yy_delete_buffer(YY_CURRENT_BUFFER  );
+| 		YY_CURRENT_BUFFER_LVALUE = NULL;
+| 		yypop_buffer_state();
+| 	}
+| 
+| 	/* Destroy the stack itself. */
+| 	yyfree((yy_buffer_stack) );
+| 	(yy_buffer_stack) = NULL;
+| 
+|     yyfree ( (yy_state_buf) );
+|     (yy_state_buf)  = NULL;
+| 
+|     /* Reset the globals. This is important in a non-reentrant scanner so the next time
+|      * yylex() is called, initialization will occur. */
+|     yy_init_globals( );
+| 
+|     return 0;
+| }
+| 
+| /*
+|  * Internal utility routines.
+|  */
+| 
+| #ifndef yytext_ptr
+| static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+| {
+| 	register int i;
+| 	for ( i = 0; i < n; ++i )
+| 		s1[i] = s2[i];
+| }
+| #endif
+| 
+| #ifdef YY_NEED_STRLEN
+| static int yy_flex_strlen (yyconst char * s )
+| {
+| 	register int n;
+| 	for ( n = 0; s[n]; ++n )
+| 		;
+| 
+| 	return n;
+| }
+| #endif
+| 
+| void *yyalloc (yy_size_t  size )
+| {
+| 	return (void *) malloc( size );
+| }
+| 
+| void *yyrealloc  (void * ptr, yy_size_t  size )
+| {
+| 	/* The cast to (char *) in the following accommodates both
+| 	 * implementations that use char* generic pointers, and those
+| 	 * that use void* generic pointers.  It works with the latter
+| 	 * because both ANSI C and C++ allow castless assignment from
+| 	 * any pointer type to void*, and deal with argument conversions
+| 	 * as though doing an assignment.
+| 	 */
+| 	return (void *) realloc( (char *) ptr, size );
+| }
+| 
+| void yyfree (void * ptr )
+| {
+| 	free( (char *) ptr );	/* see yyrealloc() for (char *) cast */
+| }
+| 
+| #define YYTABLES_NAME "yytables"
+| 
+| #line 10 "conftest.l"
+| 
+| 
+| #ifdef YYTEXT_POINTER
+| extern char *yytext;
+| #endif
+| int
+| main (void)
+| {
+|   return ! yylex () + ! yywrap ();
+| }
+configure:3583: gcc -o conftest -g -O2   conftest.c -lfl  >&5
+ld: library not found for -lfl
+clang: error: linker command failed with exit code 1 (use -v to see invocation)
+configure:3583: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ZOO Kernel"
+| #define PACKAGE_TARNAME "zoo-kernel"
+| #define PACKAGE_VERSION "1.5.0"
+| #define PACKAGE_STRING "ZOO Kernel 1.5.0"
+| #define PACKAGE_BUGREPORT "bugs at zoo-project.org"
+| #define PACKAGE_URL ""
+| /* end confdefs.h.  */
+| 
+| #line 3 "lex.yy.c"
+| 
+| #define  YY_INT_ALIGNED short int
+| 
+| /* A lexical scanner generated by flex */
+| 
+| #define FLEX_SCANNER
+| #define YY_FLEX_MAJOR_VERSION 2
+| #define YY_FLEX_MINOR_VERSION 5
+| #define YY_FLEX_SUBMINOR_VERSION 35
+| #if YY_FLEX_SUBMINOR_VERSION > 0
+| #define FLEX_BETA
+| #endif
+| 
+| /* First, we deal with  platform-specific or compiler-specific issues. */
+| 
+| /* begin standard C headers. */
+| #include <stdio.h>
+| #include <string.h>
+| #include <errno.h>
+| #include <stdlib.h>
+| 
+| /* end standard C headers. */
+| 
+| /* flex integer type definitions */
+| 
+| #ifndef FLEXINT_H
+| #define FLEXINT_H
+| 
+| /* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+| 
+| #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+| 
+| /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+|  * if you want the limit (max/min) macros for int types. 
+|  */
+| #ifndef __STDC_LIMIT_MACROS
+| #define __STDC_LIMIT_MACROS 1
+| #endif
+| 
+| #include <inttypes.h>
+| typedef int8_t flex_int8_t;
+| typedef uint8_t flex_uint8_t;
+| typedef int16_t flex_int16_t;
+| typedef uint16_t flex_uint16_t;
+| typedef int32_t flex_int32_t;
+| typedef uint32_t flex_uint32_t;
+| typedef uint64_t flex_uint64_t;
+| #else
+| typedef signed char flex_int8_t;
+| typedef short int flex_int16_t;
+| typedef int flex_int32_t;
+| typedef unsigned char flex_uint8_t; 
+| typedef unsigned short int flex_uint16_t;
+| typedef unsigned int flex_uint32_t;
+| #endif /* ! C99 */
+| 
+| /* Limits of integral types. */
+| #ifndef INT8_MIN
+| #define INT8_MIN               (-128)
+| #endif
+| #ifndef INT16_MIN
+| #define INT16_MIN              (-32767-1)
+| #endif
+| #ifndef INT32_MIN
+| #define INT32_MIN              (-2147483647-1)
+| #endif
+| #ifndef INT8_MAX
+| #define INT8_MAX               (127)
+| #endif
+| #ifndef INT16_MAX
+| #define INT16_MAX              (32767)
+| #endif
+| #ifndef INT32_MAX
+| #define INT32_MAX              (2147483647)
+| #endif
+| #ifndef UINT8_MAX
+| #define UINT8_MAX              (255U)
+| #endif
+| #ifndef UINT16_MAX
+| #define UINT16_MAX             (65535U)
+| #endif
+| #ifndef UINT32_MAX
+| #define UINT32_MAX             (4294967295U)
+| #endif
+| 
+| #endif /* ! FLEXINT_H */
+| 
+| #ifdef __cplusplus
+| 
+| /* The "const" storage-class-modifier is valid. */
+| #define YY_USE_CONST
+| 
+| #else	/* ! __cplusplus */
+| 
+| /* C99 requires __STDC__ to be defined as 1. */
+| #if defined (__STDC__)
+| 
+| #define YY_USE_CONST
+| 
+| #endif	/* defined (__STDC__) */
+| #endif	/* ! __cplusplus */
+| 
+| #ifdef YY_USE_CONST
+| #define yyconst const
+| #else
+| #define yyconst
+| #endif
+| 
+| /* Returned upon end-of-file. */
+| #define YY_NULL 0
+| 
+| /* Promotes a possibly negative, possibly signed char to an unsigned
+|  * integer for use as an array index.  If the signed char is negative,
+|  * we want to instead treat it as an 8-bit unsigned char, hence the
+|  * double cast.
+|  */
+| #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+| 
+| /* Enter a start condition.  This macro really ought to take a parameter,
+|  * but we do it the disgusting crufty way forced on us by the ()-less
+|  * definition of BEGIN.
+|  */
+| #define BEGIN (yy_start) = 1 + 2 *
+| 
+| /* Translate the current start state into a value that can be later handed
+|  * to BEGIN to return to the state.  The YYSTATE alias is for lex
+|  * compatibility.
+|  */
+| #define YY_START (((yy_start) - 1) / 2)
+| #define YYSTATE YY_START
+| 
+| /* Action number for EOF rule of a given start state. */
+| #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+| 
+| /* Special action meaning "start processing a new file". */
+| #define YY_NEW_FILE yyrestart(yyin  )
+| 
+| #define YY_END_OF_BUFFER_CHAR 0
+| 
+| /* Size of default input buffer. */
+| #ifndef YY_BUF_SIZE
+| #define YY_BUF_SIZE 16384
+| #endif
+| 
+| /* The state buf must be large enough to hold one state per character in the main buffer.
+|  */
+| #define YY_STATE_BUF_SIZE   ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+| 
+| #ifndef YY_TYPEDEF_YY_BUFFER_STATE
+| #define YY_TYPEDEF_YY_BUFFER_STATE
+| typedef struct yy_buffer_state *YY_BUFFER_STATE;
+| #endif
+| 
+| #ifndef YY_TYPEDEF_YY_SIZE_T
+| #define YY_TYPEDEF_YY_SIZE_T
+| typedef size_t yy_size_t;
+| #endif
+| 
+| extern yy_size_t yyleng;
+| 
+| extern FILE *yyin, *yyout;
+| 
+| #define EOB_ACT_CONTINUE_SCAN 0
+| #define EOB_ACT_END_OF_FILE 1
+| #define EOB_ACT_LAST_MATCH 2
+| 
+|     #define YY_LESS_LINENO(n)
+|     
+| /* Return all but the first "n" matched characters back to the input stream. */
+| #define yyless(n) \
+| 	do \
+| 		{ \
+| 		/* Undo effects of setting up yytext. */ \
+|         int yyless_macro_arg = (n); \
+|         YY_LESS_LINENO(yyless_macro_arg);\
+| 		*yy_cp = (yy_hold_char); \
+| 		YY_RESTORE_YY_MORE_OFFSET \
+| 		(yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+| 		YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+| 		} \
+| 	while ( 0 )
+| 
+| #define unput(c) yyunput( c, (yytext_ptr)  )
+| 
+| #ifndef YY_STRUCT_YY_BUFFER_STATE
+| #define YY_STRUCT_YY_BUFFER_STATE
+| struct yy_buffer_state
+| 	{
+| 	FILE *yy_input_file;
+| 
+| 	char *yy_ch_buf;		/* input buffer */
+| 	char *yy_buf_pos;		/* current position in input buffer */
+| 
+| 	/* Size of input buffer in bytes, not including room for EOB
+| 	 * characters.
+| 	 */
+| 	yy_size_t yy_buf_size;
+| 
+| 	/* Number of characters read into yy_ch_buf, not including EOB
+| 	 * characters.
+| 	 */
+| 	yy_size_t yy_n_chars;
+| 
+| 	/* Whether we "own" the buffer - i.e., we know we created it,
+| 	 * and can realloc() it to grow it, and should free() it to
+| 	 * delete it.
+| 	 */
+| 	int yy_is_our_buffer;
+| 
+| 	/* Whether this is an "interactive" input source; if so, and
+| 	 * if we're using stdio for input, then we want to use getc()
+| 	 * instead of fread(), to make sure we stop fetching input after
+| 	 * each newline.
+| 	 */
+| 	int yy_is_interactive;
+| 
+| 	/* Whether we're considered to be at the beginning of a line.
+| 	 * If so, '^' rules will be active on the next match, otherwise
+| 	 * not.
+| 	 */
+| 	int yy_at_bol;
+| 
+|     int yy_bs_lineno; /**< The line count. */
+|     int yy_bs_column; /**< The column count. */
+|     
+| 	/* Whether to try to fill the input buffer when we reach the
+| 	 * end of it.
+| 	 */
+| 	int yy_fill_buffer;
+| 
+| 	int yy_buffer_status;
+| 
+| #define YY_BUFFER_NEW 0
+| #define YY_BUFFER_NORMAL 1
+| 	/* When an EOF's been seen but there's still some text to process
+| 	 * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+| 	 * shouldn't try reading from the input source any more.  We might
+| 	 * still have a bunch of tokens to match, though, because of
+| 	 * possible backing-up.
+| 	 *
+| 	 * When we actually see the EOF, we change the status to "new"
+| 	 * (via yyrestart()), so that the user can continue scanning by
+| 	 * just pointing yyin at a new input file.
+| 	 */
+| #define YY_BUFFER_EOF_PENDING 2
+| 
+| 	};
+| #endif /* !YY_STRUCT_YY_BUFFER_STATE */
+| 
+| /* Stack of input buffers. */
+| static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+| static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+| static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
+| 
+| /* We provide macros for accessing buffer states in case in the
+|  * future we want to put the buffer states in a more general
+|  * "scanner state".
+|  *
+|  * Returns the top of the stack, or NULL.
+|  */
+| #define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+|                           ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+|                           : NULL)
+| 
+| /* Same as previous macro, but useful when we know that the buffer stack is not
+|  * NULL or when we need an lvalue. For internal use only.
+|  */
+| #define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+| 
+| /* yy_hold_char holds the character lost when yytext is formed. */
+| static char yy_hold_char;
+| static yy_size_t yy_n_chars;		/* number of characters read into yy_ch_buf */
+| yy_size_t yyleng;
+| 
+| /* Points to current character in buffer. */
+| static char *yy_c_buf_p = (char *) 0;
+| static int yy_init = 0;		/* whether we need to initialize */
+| static int yy_start = 0;	/* start state number */
+| 
+| /* Flag which is used to allow yywrap()'s to do buffer switches
+|  * instead of setting up a fresh yyin.  A bit of a hack ...
+|  */
+| static int yy_did_buffer_switch_on_eof;
+| 
+| void yyrestart (FILE *input_file  );
+| void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer  );
+| YY_BUFFER_STATE yy_create_buffer (FILE *file,int size  );
+| void yy_delete_buffer (YY_BUFFER_STATE b  );
+| void yy_flush_buffer (YY_BUFFER_STATE b  );
+| void yypush_buffer_state (YY_BUFFER_STATE new_buffer  );
+| void yypop_buffer_state (void );
+| 
+| static void yyensure_buffer_stack (void );
+| static void yy_load_buffer_state (void );
+| static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file  );
+| 
+| #define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
+| 
+| YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size  );
+| YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str  );
+| YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len  );
+| 
+| void *yyalloc (yy_size_t  );
+| void *yyrealloc (void *,yy_size_t  );
+| void yyfree (void *  );
+| 
+| #define yy_new_buffer yy_create_buffer
+| 
+| #define yy_set_interactive(is_interactive) \
+| 	{ \
+| 	if ( ! YY_CURRENT_BUFFER ){ \
+|         yyensure_buffer_stack (); \
+| 		YY_CURRENT_BUFFER_LVALUE =    \
+|             yy_create_buffer(yyin,YY_BUF_SIZE ); \
+| 	} \
+| 	YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+| 	}
+| 
+| #define yy_set_bol(at_bol) \
+| 	{ \
+| 	if ( ! YY_CURRENT_BUFFER ){\
+|         yyensure_buffer_stack (); \
+| 		YY_CURRENT_BUFFER_LVALUE =    \
+|             yy_create_buffer(yyin,YY_BUF_SIZE ); \
+| 	} \
+| 	YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+| 	}
+| 
+| #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+| 
+| /* Begin user sect3 */
+| 
+| typedef unsigned char YY_CHAR;
+| 
+| FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+| 
+| typedef int yy_state_type;
+| 
+| extern int yylineno;
+| 
+| int yylineno = 1;
+| 
+| extern char *yytext;
+| #define yytext_ptr yytext
+| 
+| static yy_state_type yy_get_previous_state (void );
+| static yy_state_type yy_try_NUL_trans (yy_state_type current_state  );
+| static int yy_get_next_buffer (void );
+| static void yy_fatal_error (yyconst char msg[]  );
+| 
+| /* Done after the current pattern has been matched and before the
+|  * corresponding action - sets up yytext.
+|  */
+| #define YY_DO_BEFORE_ACTION \
+| 	(yytext_ptr) = yy_bp; \
+| 	(yytext_ptr) -= (yy_more_len); \
+| 	yyleng = (yy_size_t) (yy_cp - (yytext_ptr)); \
+| 	(yy_hold_char) = *yy_cp; \
+| 	*yy_cp = '\0'; \
+| 	(yy_c_buf_p) = yy_cp;
+| 
+| #define YY_NUM_RULES 8
+| #define YY_END_OF_BUFFER 9
+| /* This struct is not used in this scanner,
+|    but its presence is necessary. */
+| struct yy_trans_info
+| 	{
+| 	flex_int32_t yy_verify;
+| 	flex_int32_t yy_nxt;
+| 	};
+| static yyconst flex_int16_t yy_acclist[23] =
+|     {   0,
+|         9,    7,    8,    8,    1,    7,    8,    2,    7,    8,
+|         3,    7,    8,    4,    7,    8,    5,    7,    8,    6,
+|         7,    8
+|     } ;
+| 
+| static yyconst flex_int16_t yy_accept[14] =
+|     {   0,
+|         1,    1,    1,    2,    4,    5,    8,   11,   14,   17,
+|        20,   23,   23
+|     } ;
+| 
+| static yyconst flex_int32_t yy_ec[256] =
+|     {   0,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    2,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    3,    4,    5,    6,
+| 
+|         7,    8,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+| 
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1,    1,    1,    1,    1,    1,
+|         1,    1,    1,    1,    1
+|     } ;
+| 
+| static yyconst flex_int32_t yy_meta[9] =
+|     {   0,
+|         1,    1,    1,    1,    1,    1,    1,    1
+|     } ;
+| 
+| static yyconst flex_int16_t yy_base[13] =
+|     {   0,
+|         0,    0,    9,   10,   10,   10,   10,   10,   10,   10,
+|        10,   10
+|     } ;
+| 
+| static yyconst flex_int16_t yy_def[13] =
+|     {   0,
+|        12,    1,   12,   12,   12,   12,   12,   12,   12,   12,
+|        12,    0
+|     } ;
+| 
+| static yyconst flex_int16_t yy_nxt[19] =
+|     {   0,
+|         4,    5,    6,    7,    8,    9,   10,   11,   12,    3,
+|        12,   12,   12,   12,   12,   12,   12,   12
+|     } ;
+| 
+| static yyconst flex_int16_t yy_chk[19] =
+|     {   0,
+|         1,    1,    1,    1,    1,    1,    1,    1,    3,   12,
+|        12,   12,   12,   12,   12,   12,   12,   12
+|     } ;
+| 
+| extern int yy_flex_debug;
+| int yy_flex_debug = 0;
+| 
+| static yy_state_type *yy_state_buf=0, *yy_state_ptr=0;
+| static char *yy_full_match;
+| static int yy_lp;
+| #define REJECT \
+| { \
+| *yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ \
+| yy_cp = (yy_full_match); /* restore poss. backed-over text */ \
+| ++(yy_lp); \
+| goto find_rule; \
+| }
+| 
+| static int yy_more_flag = 0;
+| static int yy_more_len = 0;
+| #define yymore() ((yy_more_flag) = 1)
+| #define YY_MORE_ADJ (yy_more_len)
+| #define YY_RESTORE_YY_MORE_OFFSET
+| char *yytext;
+| #line 1 "conftest.l"
+| #line 469 "lex.yy.c"
+| 
+| #define INITIAL 0
+| 
+| #ifndef YY_NO_UNISTD_H
+| /* Special case for "unistd.h", since it is non-ANSI. We include it way
+|  * down here because we want the user's section 1 to have been scanned first.
+|  * The user has a chance to override it with an option.
+|  */
+| #include <unistd.h>
+| #endif
+| 
+| #ifndef YY_EXTRA_TYPE
+| #define YY_EXTRA_TYPE void *
+| #endif
+| 
+| static int yy_init_globals (void );
+| 
+| /* Accessor methods to globals.
+|    These are made visible to non-reentrant scanners for convenience. */
+| 
+| int yylex_destroy (void );
+| 
+| int yyget_debug (void );
+| 
+| void yyset_debug (int debug_flag  );
+| 
+| YY_EXTRA_TYPE yyget_extra (void );
+| 
+| void yyset_extra (YY_EXTRA_TYPE user_defined  );
+| 
+| FILE *yyget_in (void );
+| 
+| void yyset_in  (FILE * in_str  );
+| 
+| FILE *yyget_out (void );
+| 
+| void yyset_out  (FILE * out_str  );
+| 
+| yy_size_t yyget_leng (void );
+| 
+| char *yyget_text (void );
+| 
+| int yyget_lineno (void );
+| 
+| void yyset_lineno (int line_number  );
+| 
+| /* Macros after this point can all be overridden by user definitions in
+|  * section 1.
+|  */
+| 
+| #ifndef YY_SKIP_YYWRAP
+| #ifdef __cplusplus
+| extern "C" int yywrap (void );
+| #else
+| extern int yywrap (void );
+| #endif
+| #endif
+| 
+|     static void yyunput (int c,char *buf_ptr  );
+|     
+| #ifndef yytext_ptr
+| static void yy_flex_strncpy (char *,yyconst char *,int );
+| #endif
+| 
+| #ifdef YY_NEED_STRLEN
+| static int yy_flex_strlen (yyconst char * );
+| #endif
+| 
+| #ifndef YY_NO_INPUT
+| 
+| #ifdef __cplusplus
+| static int yyinput (void );
+| #else
+| static int input (void );
+| #endif
+| 
+| #endif
+| 
+| /* Amount of stuff to slurp up with each read. */
+| #ifndef YY_READ_BUF_SIZE
+| #define YY_READ_BUF_SIZE 8192
+| #endif
+| 
+| /* Copy whatever the last rule matched to the standard output. */
+| #ifndef ECHO
+| /* This used to be an fputs(), but since the string might contain NUL's,
+|  * we now use fwrite().
+|  */
+| #define ECHO fwrite( yytext, yyleng, 1, yyout )
+| #endif
+| 
+| /* Gets input and stuffs it into "buf".  number of characters read, or YY_NULL,
+|  * is returned in "result".
+|  */
+| #ifndef YY_INPUT
+| #define YY_INPUT(buf,result,max_size) \
+| 	if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+| 		{ \
+| 		int c = '*'; \
+| 		yy_size_t n; \
+| 		for ( n = 0; n < max_size && \
+| 			     (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+| 			buf[n] = (char) c; \
+| 		if ( c == '\n' ) \
+| 			buf[n++] = (char) c; \
+| 		if ( c == EOF && ferror( yyin ) ) \
+| 			YY_FATAL_ERROR( "input in flex scanner failed" ); \
+| 		result = n; \
+| 		} \
+| 	else \
+| 		{ \
+| 		errno=0; \
+| 		while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+| 			{ \
+| 			if( errno != EINTR) \
+| 				{ \
+| 				YY_FATAL_ERROR( "input in flex scanner failed" ); \
+| 				break; \
+| 				} \
+| 			errno=0; \
+| 			clearerr(yyin); \
+| 			} \
+| 		}\
+| \
+| 
+| #endif
+| 
+| /* No semi-colon after return; correct usage is to write "yyterminate();" -
+|  * we don't want an extra ';' after the "return" because that will cause
+|  * some compilers to complain about unreachable statements.
+|  */
+| #ifndef yyterminate
+| #define yyterminate() return YY_NULL
+| #endif
+| 
+| /* Number of entries by which start-condition stack grows. */
+| #ifndef YY_START_STACK_INCR
+| #define YY_START_STACK_INCR 25
+| #endif
+| 
+| /* Report a fatal error. */
+| #ifndef YY_FATAL_ERROR
+| #define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+| #endif
+| 
+| /* end tables serialization structures and prototypes */
+| 
+| /* Default declaration of generated scanner - a define so the user can
+|  * easily add parameters.
+|  */
+| #ifndef YY_DECL
+| #define YY_DECL_IS_OURS 1
+| 
+| extern int yylex (void);
+| 
+| #define YY_DECL int yylex (void)
+| #endif /* !YY_DECL */
+| 
+| /* Code executed at the beginning of each rule, after yytext and yyleng
+|  * have been set up.
+|  */
+| #ifndef YY_USER_ACTION
+| #define YY_USER_ACTION
+| #endif
+| 
+| /* Code executed at the end of each rule. */
+| #ifndef YY_BREAK
+| #define YY_BREAK break;
+| #endif
+| 
+| #define YY_RULE_SETUP \
+| 	YY_USER_ACTION
+| 
+| /** The main scanner function which does all the work.
+|  */
+| YY_DECL
+| {
+| 	register yy_state_type yy_current_state;
+| 	register char *yy_cp, *yy_bp;
+| 	register int yy_act;
+|     
+| #line 1 "conftest.l"
+| 
+| #line 653 "lex.yy.c"
+| 
+| 	if ( !(yy_init) )
+| 		{
+| 		(yy_init) = 1;
+| 
+| #ifdef YY_USER_INIT
+| 		YY_USER_INIT;
+| #endif
+| 
+|         /* Create the reject buffer large enough to save one state per allowed character. */
+|         if ( ! (yy_state_buf) )
+|             (yy_state_buf) = (yy_state_type *)yyalloc(YY_STATE_BUF_SIZE  );
+|             if ( ! (yy_state_buf) )
+|                 YY_FATAL_ERROR( "out of dynamic memory in yylex()" );
+| 
+| 		if ( ! (yy_start) )
+| 			(yy_start) = 1;	/* first start state */
+| 
+| 		if ( ! yyin )
+| 			yyin = stdin;
+| 
+| 		if ( ! yyout )
+| 			yyout = stdout;
+| 
+| 		if ( ! YY_CURRENT_BUFFER ) {
+| 			yyensure_buffer_stack ();
+| 			YY_CURRENT_BUFFER_LVALUE =
+| 				yy_create_buffer(yyin,YY_BUF_SIZE );
+| 		}
+| 
+| 		yy_load_buffer_state( );
+| 		}
+| 
+| 	while ( 1 )		/* loops until end-of-file is reached */
+| 		{
+| 		(yy_more_len) = 0;
+| 		if ( (yy_more_flag) )
+| 			{
+| 			(yy_more_len) = (yy_c_buf_p) - (yytext_ptr);
+| 			(yy_more_flag) = 0;
+| 			}
+| 		yy_cp = (yy_c_buf_p);
+| 
+| 		/* Support of yytext. */
+| 		*yy_cp = (yy_hold_char);
+| 
+| 		/* yy_bp points to the position in yy_ch_buf of the start of
+| 		 * the current run.
+| 		 */
+| 		yy_bp = yy_cp;
+| 
+| 		yy_current_state = (yy_start);
+| 
+| 		(yy_state_ptr) = (yy_state_buf);
+| 		*(yy_state_ptr)++ = yy_current_state;
+| 
+| yy_match:
+| 		do
+| 			{
+| 			register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+| 			while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+| 				{
+| 				yy_current_state = (int) yy_def[yy_current_state];
+| 				if ( yy_current_state >= 13 )
+| 					yy_c = yy_meta[(unsigned int) yy_c];
+| 				}
+| 			yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+| 			*(yy_state_ptr)++ = yy_current_state;
+| 			++yy_cp;
+| 			}
+| 		while ( yy_base[yy_current_state] != 10 );
+| 
+| yy_find_action:
+| 		yy_current_state = *--(yy_state_ptr);
+| 		(yy_lp) = yy_accept[yy_current_state];
+| goto find_rule; /* Shut up GCC warning -Wall */
+| find_rule: /* we branch to this label when backing up */
+| 		for ( ; ; ) /* until we find what rule we matched */
+| 			{
+| 			if ( (yy_lp) && (yy_lp) < yy_accept[yy_current_state + 1] )
+| 				{
+| 				yy_act = yy_acclist[(yy_lp)];
+| 					{
+| 					(yy_full_match) = yy_cp;
+| 					break;
+| 					}
+| 				}
+| 			--yy_cp;
+| 			yy_current_state = *--(yy_state_ptr);
+| 			(yy_lp) = yy_accept[yy_current_state];
+| 			}
+| 
+| 		YY_DO_BEFORE_ACTION;
+| 
+| do_action:	/* This label is used only to access EOF actions. */
+| 
+| 		switch ( yy_act )
+| 	{ /* beginning of action switch */
+| case 1:
+| YY_RULE_SETUP
+| #line 2 "conftest.l"
+| { ECHO; }
+| 	YY_BREAK
+| case 2:
+| YY_RULE_SETUP
+| #line 3 "conftest.l"
+| { REJECT; }
+| 	YY_BREAK
+| case 3:
+| YY_RULE_SETUP
+| #line 4 "conftest.l"
+| { yymore (); }
+| 	YY_BREAK
+| case 4:
+| YY_RULE_SETUP
+| #line 5 "conftest.l"
+| { yyless (1); }
+| 	YY_BREAK
+| case 5:
+| YY_RULE_SETUP
+| #line 6 "conftest.l"
+| { /* IRIX 6.5 flex 2.5.4 underquotes its yyless argument.  */
+|     yyless ((input () != 0)); }
+| 	YY_BREAK
+| case 6:
+| YY_RULE_SETUP
+| #line 8 "conftest.l"
+| { unput (yytext[0]); }
+| 	YY_BREAK
+| case 7:
+| YY_RULE_SETUP
+| #line 9 "conftest.l"
+| { BEGIN INITIAL; }
+| 	YY_BREAK
+| case 8:
+| YY_RULE_SETUP
+| #line 10 "conftest.l"
+| ECHO;
+| 	YY_BREAK
+| #line 793 "lex.yy.c"
+| 			case YY_STATE_EOF(INITIAL):
+| 				yyterminate();
+| 
+| 	case YY_END_OF_BUFFER:
+| 		{
+| 		/* Amount of text matched not including the EOB char. */
+| 		int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+| 
+| 		/* Undo the effects of YY_DO_BEFORE_ACTION. */
+| 		*yy_cp = (yy_hold_char);
+| 		YY_RESTORE_YY_MORE_OFFSET
+| 
+| 		if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+| 			{
+| 			/* We're scanning a new file or input source.  It's
+| 			 * possible that this happened because the user
+| 			 * just pointed yyin at a new source and called
+| 			 * yylex().  If so, then we have to assure
+| 			 * consistency between YY_CURRENT_BUFFER and our
+| 			 * globals.  Here is the right place to do so, because
+| 			 * this is the first action (other than possibly a
+| 			 * back-up) that will match for the new input source.
+| 			 */
+| 			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+| 			YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+| 			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+| 			}
+| 
+| 		/* Note that here we test for yy_c_buf_p "<=" to the position
+| 		 * of the first EOB in the buffer, since yy_c_buf_p will
+| 		 * already have been incremented past the NUL character
+| 		 * (since all states make transitions on EOB to the
+| 		 * end-of-buffer state).  Contrast this with the test
+| 		 * in input().
+| 		 */
+| 		if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+| 			{ /* This was really a NUL. */
+| 			yy_state_type yy_next_state;
+| 
+| 			(yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+| 
+| 			yy_current_state = yy_get_previous_state(  );
+| 
+| 			/* Okay, we're now positioned to make the NUL
+| 			 * transition.  We couldn't have
+| 			 * yy_get_previous_state() go ahead and do it
+| 			 * for us because it doesn't know how to deal
+| 			 * with the possibility of jamming (and we don't
+| 			 * want to build jamming into it because then it
+| 			 * will run more slowly).
+| 			 */
+| 
+| 			yy_next_state = yy_try_NUL_trans( yy_current_state );
+| 
+| 			yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+| 
+| 			if ( yy_next_state )
+| 				{
+| 				/* Consume the NUL. */
+| 				yy_cp = ++(yy_c_buf_p);
+| 				yy_current_state = yy_next_state;
+| 				goto yy_match;
+| 				}
+| 
+| 			else
+| 				{
+| 				yy_cp = (yy_c_buf_p);
+| 				goto yy_find_action;
+| 				}
+| 			}
+| 
+| 		else switch ( yy_get_next_buffer(  ) )
+| 			{
+| 			case EOB_ACT_END_OF_FILE:
+| 				{
+| 				(yy_did_buffer_switch_on_eof) = 0;
+| 
+| 				if ( yywrap( ) )
+| 					{
+| 					/* Note: because we've taken care in
+| 					 * yy_get_next_buffer() to have set up
+| 					 * yytext, we can now set up
+| 					 * yy_c_buf_p so that if some total
+| 					 * hoser (like flex itself) wants to
+| 					 * call the scanner after we return the
+| 					 * YY_NULL, it'll still work - another
+| 					 * YY_NULL will get returned.
+| 					 */
+| 					(yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+| 
+| 					yy_act = YY_STATE_EOF(YY_START);
+| 					goto do_action;
+| 					}
+| 
+| 				else
+| 					{
+| 					if ( ! (yy_did_buffer_switch_on_eof) )
+| 						YY_NEW_FILE;
+| 					}
+| 				break;
+| 				}
+| 
+| 			case EOB_ACT_CONTINUE_SCAN:
+| 				(yy_c_buf_p) =
+| 					(yytext_ptr) + yy_amount_of_matched_text;
+| 
+| 				yy_current_state = yy_get_previous_state(  );
+| 
+| 				yy_cp = (yy_c_buf_p);
+| 				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+| 				goto yy_match;
+| 
+| 			case EOB_ACT_LAST_MATCH:
+| 				(yy_c_buf_p) =
+| 				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+| 
+| 				yy_current_state = yy_get_previous_state(  );
+| 
+| 				yy_cp = (yy_c_buf_p);
+| 				yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+| 				goto yy_find_action;
+| 			}
+| 		break;
+| 		}
+| 
+| 	default:
+| 		YY_FATAL_ERROR(
+| 			"fatal flex scanner internal error--no action found" );
+| 	} /* end of action switch */
+| 		} /* end of scanning one token */
+| } /* end of yylex */
+| 
+| /* yy_get_next_buffer - try to read in a new buffer
+|  *
+|  * Returns a code representing an action:
+|  *	EOB_ACT_LAST_MATCH -
+|  *	EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+|  *	EOB_ACT_END_OF_FILE - end of file
+|  */
+| static int yy_get_next_buffer (void)
+| {
+|     	register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+| 	register char *source = (yytext_ptr);
+| 	register int number_to_move, i;
+| 	int ret_val;
+| 
+| 	if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+| 		YY_FATAL_ERROR(
+| 		"fatal flex scanner internal error--end of buffer missed" );
+| 
+| 	if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+| 		{ /* Don't try to fill the buffer, so this is an EOF. */
+| 		if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+| 			{
+| 			/* We matched a single character, the EOB, so
+| 			 * treat this as a final EOF.
+| 			 */
+| 			return EOB_ACT_END_OF_FILE;
+| 			}
+| 
+| 		else
+| 			{
+| 			/* We matched some text prior to the EOB, first
+| 			 * process it.
+| 			 */
+| 			return EOB_ACT_LAST_MATCH;
+| 			}
+| 		}
+| 
+| 	/* Try to read more data. */
+| 
+| 	/* First move last chars to start of buffer. */
+| 	number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+| 
+| 	for ( i = 0; i < number_to_move; ++i )
+| 		*(dest++) = *(source++);
+| 
+| 	if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+| 		/* don't do the read, it's not guaranteed to return an EOF,
+| 		 * just force an EOF
+| 		 */
+| 		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+| 
+| 	else
+| 		{
+| 			yy_size_t num_to_read =
+| 			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+| 
+| 		while ( num_to_read <= 0 )
+| 			{ /* Not enough room in the buffer - grow it. */
+| 
+| 			YY_FATAL_ERROR(
+| "input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+| 
+| 			}
+| 
+| 		if ( num_to_read > YY_READ_BUF_SIZE )
+| 			num_to_read = YY_READ_BUF_SIZE;
+| 
+| 		/* Read in more data. */
+| 		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+| 			(yy_n_chars), num_to_read );
+| 
+| 		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+| 		}
+| 
+| 	if ( (yy_n_chars) == 0 )
+| 		{
+| 		if ( number_to_move == YY_MORE_ADJ )
+| 			{
+| 			ret_val = EOB_ACT_END_OF_FILE;
+| 			yyrestart(yyin  );
+| 			}
+| 
+| 		else
+| 			{
+| 			ret_val = EOB_ACT_LAST_MATCH;
+| 			YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+| 				YY_BUFFER_EOF_PENDING;
+| 			}
+| 		}
+| 
+| 	else
+| 		ret_val = EOB_ACT_CONTINUE_SCAN;
+| 
+| 	if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+| 		/* Extend the array by 50%, plus the number we really need. */
+| 		yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+| 		YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size  );
+| 		if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+| 			YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+| 	}
+| 
+| 	(yy_n_chars) += number_to_move;
+| 	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+| 	YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+| 
+| 	(yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+| 
+| 	return ret_val;
+| }
+| 
+| /* yy_get_previous_state - get the state just before the EOB char was reached */
+| 
+|     static yy_state_type yy_get_previous_state (void)
+| {
+| 	register yy_state_type yy_current_state;
+| 	register char *yy_cp;
+|     
+| 	yy_current_state = (yy_start);
+| 
+| 	(yy_state_ptr) = (yy_state_buf);
+| 	*(yy_state_ptr)++ = yy_current_state;
+| 
+| 	for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+| 		{
+| 		register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+| 		while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+| 			{
+| 			yy_current_state = (int) yy_def[yy_current_state];
+| 			if ( yy_current_state >= 13 )
+| 				yy_c = yy_meta[(unsigned int) yy_c];
+| 			}
+| 		yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+| 		*(yy_state_ptr)++ = yy_current_state;
+| 		}
+| 
+| 	return yy_current_state;
+| }
+| 
+| /* yy_try_NUL_trans - try to make a transition on the NUL character
+|  *
+|  * synopsis
+|  *	next_state = yy_try_NUL_trans( current_state );
+|  */
+|     static yy_state_type yy_try_NUL_trans  (yy_state_type yy_current_state )
+| {
+| 	register int yy_is_jam;
+|     
+| 	register YY_CHAR yy_c = 1;
+| 	while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+| 		{
+| 		yy_current_state = (int) yy_def[yy_current_state];
+| 		if ( yy_current_state >= 13 )
+| 			yy_c = yy_meta[(unsigned int) yy_c];
+| 		}
+| 	yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+| 	yy_is_jam = (yy_current_state == 12);
+| 	if ( ! yy_is_jam )
+| 		*(yy_state_ptr)++ = yy_current_state;
+| 
+| 	return yy_is_jam ? 0 : yy_current_state;
+| }
+| 
+|     static void yyunput (int c, register char * yy_bp )
+| {
+| 	register char *yy_cp;
+|     
+|     yy_cp = (yy_c_buf_p);
+| 
+| 	/* undo effects of setting up yytext */
+| 	*yy_cp = (yy_hold_char);
+| 
+| 	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+| 		{ /* need to shift things up to make room */
+| 		/* +2 for EOB chars. */
+| 		register yy_size_t number_to_move = (yy_n_chars) + 2;
+| 		register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+| 					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+| 		register char *source =
+| 				&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+| 
+| 		while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+| 			*--dest = *--source;
+| 
+| 		yy_cp += (int) (dest - source);
+| 		yy_bp += (int) (dest - source);
+| 		YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+| 			(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+| 
+| 		if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+| 			YY_FATAL_ERROR( "flex scanner push-back overflow" );
+| 		}
+| 
+| 	*--yy_cp = (char) c;
+| 
+| 	(yytext_ptr) = yy_bp;
+| 	(yy_hold_char) = *yy_cp;
+| 	(yy_c_buf_p) = yy_cp;
+| }
+| 
+| #ifndef YY_NO_INPUT
+| #ifdef __cplusplus
+|     static int yyinput (void)
+| #else
+|     static int input  (void)
+| #endif
+| 
+| {
+| 	int c;
+|     
+| 	*(yy_c_buf_p) = (yy_hold_char);
+| 
+| 	if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+| 		{
+| 		/* yy_c_buf_p now points to the character we want to return.
+| 		 * If this occurs *before* the EOB characters, then it's a
+| 		 * valid NUL; if not, then we've hit the end of the buffer.
+| 		 */
+| 		if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+| 			/* This was really a NUL. */
+| 			*(yy_c_buf_p) = '\0';
+| 
+| 		else
+| 			{ /* need more input */
+| 			yy_size_t offset = (yy_c_buf_p) - (yytext_ptr);
+| 			++(yy_c_buf_p);
+| 
+| 			switch ( yy_get_next_buffer(  ) )
+| 				{
+| 				case EOB_ACT_LAST_MATCH:
+| 					/* This happens because yy_g_n_b()
+| 					 * sees that we've accumulated a
+| 					 * token and flags that we need to
+| 					 * try matching the token before
+| 					 * proceeding.  But for input(),
+| 					 * there's no matching to consider.
+| 					 * So convert the EOB_ACT_LAST_MATCH
+| 					 * to EOB_ACT_END_OF_FILE.
+| 					 */
+| 
+| 					/* Reset buffer status. */
+| 					yyrestart(yyin );
+| 
+| 					/*FALLTHROUGH*/
+| 
+| 				case EOB_ACT_END_OF_FILE:
+| 					{
+| 					if ( yywrap( ) )
+| 						return 0;
+| 
+| 					if ( ! (yy_did_buffer_switch_on_eof) )
+| 						YY_NEW_FILE;
+| #ifdef __cplusplus
+| 					return yyinput();
+| #else
+| 					return input();
+| #endif
+| 					}
+| 
+| 				case EOB_ACT_CONTINUE_SCAN:
+| 					(yy_c_buf_p) = (yytext_ptr) + offset;
+| 					break;
+| 				}
+| 			}
+| 		}
+| 
+| 	c = *(unsigned char *) (yy_c_buf_p);	/* cast for 8-bit char's */
+| 	*(yy_c_buf_p) = '\0';	/* preserve yytext */
+| 	(yy_hold_char) = *++(yy_c_buf_p);
+| 
+| 	return c;
+| }
+| #endif	/* ifndef YY_NO_INPUT */
+| 
+| /** Immediately switch to a different input stream.
+|  * @param input_file A readable stream.
+|  * 
+|  * @note This function does not reset the start condition to @c INITIAL .
+|  */
+|     void yyrestart  (FILE * input_file )
+| {
+|     
+| 	if ( ! YY_CURRENT_BUFFER ){
+|         yyensure_buffer_stack ();
+| 		YY_CURRENT_BUFFER_LVALUE =
+|             yy_create_buffer(yyin,YY_BUF_SIZE );
+| 	}
+| 
+| 	yy_init_buffer(YY_CURRENT_BUFFER,input_file );
+| 	yy_load_buffer_state( );
+| }
+| 
+| /** Switch to a different input buffer.
+|  * @param new_buffer The new input buffer.
+|  * 
+|  */
+|     void yy_switch_to_buffer  (YY_BUFFER_STATE  new_buffer )
+| {
+|     
+| 	/* TODO. We should be able to replace this entire function body
+| 	 * with
+| 	 *		yypop_buffer_state();
+| 	 *		yypush_buffer_state(new_buffer);
+|      */
+| 	yyensure_buffer_stack ();
+| 	if ( YY_CURRENT_BUFFER == new_buffer )
+| 		return;
+| 
+| 	if ( YY_CURRENT_BUFFER )
+| 		{
+| 		/* Flush out information for old buffer. */
+| 		*(yy_c_buf_p) = (yy_hold_char);
+| 		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+| 		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+| 		}
+| 
+| 	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+| 	yy_load_buffer_state( );
+| 
+| 	/* We don't actually know whether we did this switch during
+| 	 * EOF (yywrap()) processing, but the only time this flag
+| 	 * is looked at is after yywrap() is called, so it's safe
+| 	 * to go ahead and always set it.
+| 	 */
+| 	(yy_did_buffer_switch_on_eof) = 1;
+| }
+| 
+| static void yy_load_buffer_state  (void)
+| {
+|     	(yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+| 	(yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+| 	yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+| 	(yy_hold_char) = *(yy_c_buf_p);
+| }
+| 
+| /** Allocate and initialize an input buffer state.
+|  * @param file A readable stream.
+|  * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+|  * 
+|  * @return the allocated buffer state.
+|  */
+|     YY_BUFFER_STATE yy_create_buffer  (FILE * file, int  size )
+| {
+| 	YY_BUFFER_STATE b;
+|     
+| 	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
+| 	if ( ! b )
+| 		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+| 
+| 	b->yy_buf_size = size;
+| 
+| 	/* yy_ch_buf has to be 2 characters longer than the size given because
+| 	 * we need to put in 2 end-of-buffer characters.
+| 	 */
+| 	b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2  );
+| 	if ( ! b->yy_ch_buf )
+| 		YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+| 
+| 	b->yy_is_our_buffer = 1;
+| 
+| 	yy_init_buffer(b,file );
+| 
+| 	return b;
+| }
+| 
+| /** Destroy the buffer.
+|  * @param b a buffer created with yy_create_buffer()
+|  * 
+|  */
+|     void yy_delete_buffer (YY_BUFFER_STATE  b )
+| {
+|     
+| 	if ( ! b )
+| 		return;
+| 
+| 	if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+| 		YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+| 
+| 	if ( b->yy_is_our_buffer )
+| 		yyfree((void *) b->yy_ch_buf  );
+| 
+| 	yyfree((void *) b  );
+| }
+| 
+| #ifndef __cplusplus
+| extern int isatty (int );
+| #endif /* __cplusplus */
+|     
+| /* Initializes or reinitializes a buffer.
+|  * This function is sometimes called more than once on the same buffer,
+|  * such as during a yyrestart() or at EOF.
+|  */
+|     static void yy_init_buffer  (YY_BUFFER_STATE  b, FILE * file )
+| 
+| {
+| 	int oerrno = errno;
+|     
+| 	yy_flush_buffer(b );
+| 
+| 	b->yy_input_file = file;
+| 	b->yy_fill_buffer = 1;
+| 
+|     /* If b is the current buffer, then yy_init_buffer was _probably_
+|      * called from yyrestart() or through yy_get_next_buffer.
+|      * In that case, we don't want to reset the lineno or column.
+|      */
+|     if (b != YY_CURRENT_BUFFER){
+|         b->yy_bs_lineno = 1;
+|         b->yy_bs_column = 0;
+|     }
+| 
+|         b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+|     
+| 	errno = oerrno;
+| }
+| 
+| /** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+|  * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+|  * 
+|  */
+|     void yy_flush_buffer (YY_BUFFER_STATE  b )
+| {
+|     	if ( ! b )
+| 		return;
+| 
+| 	b->yy_n_chars = 0;
+| 
+| 	/* We always need two end-of-buffer characters.  The first causes
+| 	 * a transition to the end-of-buffer state.  The second causes
+| 	 * a jam in that state.
+| 	 */
+| 	b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+| 	b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+| 
+| 	b->yy_buf_pos = &b->yy_ch_buf[0];
+| 
+| 	b->yy_at_bol = 1;
+| 	b->yy_buffer_status = YY_BUFFER_NEW;
+| 
+| 	if ( b == YY_CURRENT_BUFFER )
+| 		yy_load_buffer_state( );
+| }
+| 
+| /** Pushes the new state onto the stack. The new state becomes
+|  *  the current state. This function will allocate the stack
+|  *  if necessary.
+|  *  @param new_buffer The new state.
+|  *  
+|  */
+| void yypush_buffer_state (YY_BUFFER_STATE new_buffer )
+| {
+|     	if (new_buffer == NULL)
+| 		return;
+| 
+| 	yyensure_buffer_stack();
+| 
+| 	/* This block is copied from yy_switch_to_buffer. */
+| 	if ( YY_CURRENT_BUFFER )
+| 		{
+| 		/* Flush out information for old buffer. */
+| 		*(yy_c_buf_p) = (yy_hold_char);
+| 		YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+| 		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+| 		}
+| 
+| 	/* Only push if top exists. Otherwise, replace top. */
+| 	if (YY_CURRENT_BUFFER)
+| 		(yy_buffer_stack_top)++;
+| 	YY_CURRENT_BUFFER_LVALUE = new_buffer;
+| 
+| 	/* copied from yy_switch_to_buffer. */
+| 	yy_load_buffer_state( );
+| 	(yy_did_buffer_switch_on_eof) = 1;
+| }
+| 
+| /** Removes and deletes the top of the stack, if present.
+|  *  The next element becomes the new top.
+|  *  
+|  */
+| void yypop_buffer_state (void)
+| {
+|     	if (!YY_CURRENT_BUFFER)
+| 		return;
+| 
+| 	yy_delete_buffer(YY_CURRENT_BUFFER );
+| 	YY_CURRENT_BUFFER_LVALUE = NULL;
+| 	if ((yy_buffer_stack_top) > 0)
+| 		--(yy_buffer_stack_top);
+| 
+| 	if (YY_CURRENT_BUFFER) {
+| 		yy_load_buffer_state( );
+| 		(yy_did_buffer_switch_on_eof) = 1;
+| 	}
+| }
+| 
+| /* Allocates the stack if it does not exist.
+|  *  Guarantees space for at least one push.
+|  */
+| static void yyensure_buffer_stack (void)
+| {
+| 	yy_size_t num_to_alloc;
+|     
+| 	if (!(yy_buffer_stack)) {
+| 
+| 		/* First allocation is just for 2 elements, since we don't know if this
+| 		 * scanner will even need a stack. We use 2 instead of 1 to avoid an
+| 		 * immediate realloc on the next call.
+|          */
+| 		num_to_alloc = 1;
+| 		(yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
+| 								(num_to_alloc * sizeof(struct yy_buffer_state*)
+| 								);
+| 		if ( ! (yy_buffer_stack) )
+| 			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+| 								  
+| 		memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+| 				
+| 		(yy_buffer_stack_max) = num_to_alloc;
+| 		(yy_buffer_stack_top) = 0;
+| 		return;
+| 	}
+| 
+| 	if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+| 
+| 		/* Increase the buffer to prepare for a possible push. */
+| 		int grow_size = 8 /* arbitrary grow size */;
+| 
+| 		num_to_alloc = (yy_buffer_stack_max) + grow_size;
+| 		(yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
+| 								((yy_buffer_stack),
+| 								num_to_alloc * sizeof(struct yy_buffer_state*)
+| 								);
+| 		if ( ! (yy_buffer_stack) )
+| 			YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+| 
+| 		/* zero only the new slots.*/
+| 		memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+| 		(yy_buffer_stack_max) = num_to_alloc;
+| 	}
+| }
+| 
+| /** Setup the input buffer state to scan directly from a user-specified character buffer.
+|  * @param base the character buffer
+|  * @param size the size in bytes of the character buffer
+|  * 
+|  * @return the newly allocated buffer state object. 
+|  */
+| YY_BUFFER_STATE yy_scan_buffer  (char * base, yy_size_t  size )
+| {
+| 	YY_BUFFER_STATE b;
+|     
+| 	if ( size < 2 ||
+| 	     base[size-2] != YY_END_OF_BUFFER_CHAR ||
+| 	     base[size-1] != YY_END_OF_BUFFER_CHAR )
+| 		/* They forgot to leave room for the EOB's. */
+| 		return 0;
+| 
+| 	b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state )  );
+| 	if ( ! b )
+| 		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+| 
+| 	b->yy_buf_size = size - 2;	/* "- 2" to take care of EOB's */
+| 	b->yy_buf_pos = b->yy_ch_buf = base;
+| 	b->yy_is_our_buffer = 0;
+| 	b->yy_input_file = 0;
+| 	b->yy_n_chars = b->yy_buf_size;
+| 	b->yy_is_interactive = 0;
+| 	b->yy_at_bol = 1;
+| 	b->yy_fill_buffer = 0;
+| 	b->yy_buffer_status = YY_BUFFER_NEW;
+| 
+| 	yy_switch_to_buffer(b  );
+| 
+| 	return b;
+| }
+| 
+| /** Setup the input buffer state to scan a string. The next call to yylex() will
+|  * scan from a @e copy of @a str.
+|  * @param yystr a NUL-terminated string to scan
+|  * 
+|  * @return the newly allocated buffer state object.
+|  * @note If you want to scan bytes that may contain NUL values, then use
+|  *       yy_scan_bytes() instead.
+|  */
+| YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
+| {
+|     
+| 	return yy_scan_bytes(yystr,strlen(yystr) );
+| }
+| 
+| /** Setup the input buffer state to scan the given bytes. The next call to yylex() will
+|  * scan from a @e copy of @a bytes.
+|  * @param bytes the byte buffer to scan
+|  * @param len the number of bytes in the buffer pointed to by @a bytes.
+|  * 
+|  * @return the newly allocated buffer state object.
+|  */
+| YY_BUFFER_STATE yy_scan_bytes  (yyconst char * yybytes, yy_size_t  _yybytes_len )
+| {
+| 	YY_BUFFER_STATE b;
+| 	char *buf;
+| 	yy_size_t n, i;
+|     
+| 	/* Get memory for full buffer, including space for trailing EOB's. */
+| 	n = _yybytes_len + 2;
+| 	buf = (char *) yyalloc(n  );
+| 	if ( ! buf )
+| 		YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+| 
+| 	for ( i = 0; i < _yybytes_len; ++i )
+| 		buf[i] = yybytes[i];
+| 
+| 	buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+| 
+| 	b = yy_scan_buffer(buf,n );
+| 	if ( ! b )
+| 		YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+| 
+| 	/* It's okay to grow etc. this buffer, and we should throw it
+| 	 * away when we're done.
+| 	 */
+| 	b->yy_is_our_buffer = 1;
+| 
+| 	return b;
+| }
+| 
+| #ifndef YY_EXIT_FAILURE
+| #define YY_EXIT_FAILURE 2
+| #endif
+| 
+| static void yy_fatal_error (yyconst char* msg )
+| {
+|     	(void) fprintf( stderr, "%s\n", msg );
+| 	exit( YY_EXIT_FAILURE );
+| }
+| 
+| /* Redefine yyless() so it works in section 3 code. */
+| 
+| #undef yyless
+| #define yyless(n) \
+| 	do \
+| 		{ \
+| 		/* Undo effects of setting up yytext. */ \
+|         int yyless_macro_arg = (n); \
+|         YY_LESS_LINENO(yyless_macro_arg);\
+| 		yytext[yyleng] = (yy_hold_char); \
+| 		(yy_c_buf_p) = yytext + yyless_macro_arg; \
+| 		(yy_hold_char) = *(yy_c_buf_p); \
+| 		*(yy_c_buf_p) = '\0'; \
+| 		yyleng = yyless_macro_arg; \
+| 		} \
+| 	while ( 0 )
+| 
+| /* Accessor  methods (get/set functions) to struct members. */
+| 
+| /** Get the current line number.
+|  * 
+|  */
+| int yyget_lineno  (void)
+| {
+|         
+|     return yylineno;
+| }
+| 
+| /** Get the input stream.
+|  * 
+|  */
+| FILE *yyget_in  (void)
+| {
+|         return yyin;
+| }
+| 
+| /** Get the output stream.
+|  * 
+|  */
+| FILE *yyget_out  (void)
+| {
+|         return yyout;
+| }
+| 
+| /** Get the length of the current token.
+|  * 
+|  */
+| yy_size_t yyget_leng  (void)
+| {
+|         return yyleng;
+| }
+| 
+| /** Get the current token.
+|  * 
+|  */
+| 
+| char *yyget_text  (void)
+| {
+|         return yytext;
+| }
+| 
+| /** Set the current line number.
+|  * @param line_number
+|  * 
+|  */
+| void yyset_lineno (int  line_number )
+| {
+|     
+|     yylineno = line_number;
+| }
+| 
+| /** Set the input stream. This does not discard the current
+|  * input buffer.
+|  * @param in_str A readable stream.
+|  * 
+|  * @see yy_switch_to_buffer
+|  */
+| void yyset_in (FILE *  in_str )
+| {
+|         yyin = in_str ;
+| }
+| 
+| void yyset_out (FILE *  out_str )
+| {
+|         yyout = out_str ;
+| }
+| 
+| int yyget_debug  (void)
+| {
+|         return yy_flex_debug;
+| }
+| 
+| void yyset_debug (int  bdebug )
+| {
+|         yy_flex_debug = bdebug ;
+| }
+| 
+| static int yy_init_globals (void)
+| {
+|         /* Initialization is the same as for the non-reentrant scanner.
+|      * This function is called from yylex_destroy(), so don't allocate here.
+|      */
+| 
+|     (yy_buffer_stack) = 0;
+|     (yy_buffer_stack_top) = 0;
+|     (yy_buffer_stack_max) = 0;
+|     (yy_c_buf_p) = (char *) 0;
+|     (yy_init) = 0;
+|     (yy_start) = 0;
+| 
+|     (yy_state_buf) = 0;
+|     (yy_state_ptr) = 0;
+|     (yy_full_match) = 0;
+|     (yy_lp) = 0;
+| 
+| /* Defined in main.c */
+| #ifdef YY_STDINIT
+|     yyin = stdin;
+|     yyout = stdout;
+| #else
+|     yyin = (FILE *) 0;
+|     yyout = (FILE *) 0;
+| #endif
+| 
+|     /* For future reference: Set errno on error, since we are called by
+|      * yylex_init()
+|      */
+|     return 0;
+| }
+| 
+| /* yylex_destroy is for both reentrant and non-reentrant scanners. */
+| int yylex_destroy  (void)
+| {
+|     
+|     /* Pop the buffer stack, destroying each element. */
+| 	while(YY_CURRENT_BUFFER){
+| 		yy_delete_buffer(YY_CURRENT_BUFFER  );
+| 		YY_CURRENT_BUFFER_LVALUE = NULL;
+| 		yypop_buffer_state();
+| 	}
+| 
+| 	/* Destroy the stack itself. */
+| 	yyfree((yy_buffer_stack) );
+| 	(yy_buffer_stack) = NULL;
+| 
+|     yyfree ( (yy_state_buf) );
+|     (yy_state_buf)  = NULL;
+| 
+|     /* Reset the globals. This is important in a non-reentrant scanner so the next time
+|      * yylex() is called, initialization will occur. */
+|     yy_init_globals( );
+| 
+|     return 0;
+| }
+| 
+| /*
+|  * Internal utility routines.
+|  */
+| 
+| #ifndef yytext_ptr
+| static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+| {
+| 	register int i;
+| 	for ( i = 0; i < n; ++i )
+| 		s1[i] = s2[i];
+| }
+| #endif
+| 
+| #ifdef YY_NEED_STRLEN
+| static int yy_flex_strlen (yyconst char * s )
+| {
+| 	register int n;
+| 	for ( n = 0; s[n]; ++n )
+| 		;
+| 
+| 	return n;
+| }
+| #endif
+| 
+| void *yyalloc (yy_size_t  size )
+| {
+| 	return (void *) malloc( size );
+| }
+| 
+| void *yyrealloc  (void * ptr, yy_size_t  size )
+| {
+| 	/* The cast to (char *) in the following accommodates both
+| 	 * implementations that use char* generic pointers, and those
+| 	 * that use void* generic pointers.  It works with the latter
+| 	 * because both ANSI C and C++ allow castless assignment from
+| 	 * any pointer type to void*, and deal with argument conversions
+| 	 * as though doing an assignment.
+| 	 */
+| 	return (void *) realloc( (char *) ptr, size );
+| }
+| 
+| void yyfree (void * ptr )
+| {
+| 	free( (char *) ptr );	/* see yyrealloc() for (char *) cast */
+| }
+| 
+| #define YYTABLES_NAME "yytables"
+| 
+| #line 10 "conftest.l"
+| 
+| 
+| #ifdef YYTEXT_POINTER
+| extern char *yytext;
+| #endif
+| int
+| main (void)
+| {
+|   return ! yylex () + ! yywrap ();
+| }
+configure:3583: gcc -o conftest -g -O2   conftest.c -ll  >&5
+configure:3583: $? = 0
+configure:3593: result: -ll
+configure:3599: checking whether yytext is a pointer
+configure:3616: gcc -o conftest -g -O2   conftest.c -ll  >&5
+configure:3616: $? = 0
+configure:3624: result: yes
+configure:3692: checking for g++
+configure:3708: found /usr/bin/g++
+configure:3719: result: g++
+configure:3746: checking for C++ compiler version
+configure:3755: g++ --version >&5
+Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
+Target: x86_64-apple-darwin14.3.0
+Thread model: posix
+Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
+configure:3766: $? = 0
+configure:3755: g++ -v >&5
+Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
+Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
+Target: x86_64-apple-darwin14.3.0
+Thread model: posix
+configure:3766: $? = 0
+configure:3755: g++ -V >&5
+clang: error: argument to '-V' is missing (expected 1 value)
+clang: error: no input files
+configure:3766: $? = 1
+configure:3755: g++ -qversion >&5
+clang: error: unknown argument: '-qversion'
+clang: error: no input files
+configure:3766: $? = 1
+configure:3770: checking whether we are using the GNU C++ compiler
+configure:3789: g++ -c   conftest.cpp >&5
+configure:3789: $? = 0
+configure:3798: result: yes
+configure:3807: checking whether g++ accepts -g
+configure:3827: g++ -c -g  conftest.cpp >&5
+configure:3827: $? = 0
+configure:3868: result: yes
+configure:3891: checking for a sed that does not truncate output
+configure:3955: result: /usr/bin/sed
+configure:3962: checking for curl_easy_init,curl_easy_setopt,curl_easy_cleanup,curl_easy_perform in -lcurl
+configure:3987: gcc -o conftest -g -O2   conftest.c -lcurl   >&5
+conftest.c:21:8: warning: expression result unused [-Wunused-value]
+return curl_easy_init,curl_easy_setopt,curl_easy_cleanup,curl_easy_perform ();
+       ^~~~~~~~~~~~~~
+conftest.c:21:23: warning: expression result unused [-Wunused-value]
+return curl_easy_init,curl_easy_setopt,curl_easy_cleanup,curl_easy_perform ();
+                      ^~~~~~~~~~~~~~~~
+conftest.c:21:40: warning: expression result unused [-Wunused-value]
+return curl_easy_init,curl_easy_setopt,curl_easy_cleanup,curl_easy_perform ();
+                                       ^~~~~~~~~~~~~~~~~
+3 warnings generated.
+configure:3987: $? = 0
+configure:3996: result: yes
+configure:4007: checking for dlopen,dlsym,dlerror,dlclose in -ldl
+configure:4032: gcc -o conftest -g -O2   conftest.c -ldl  -lcurl  >&5
+conftest.c:22:8: warning: expression result unused [-Wunused-value]
+return dlopen,dlsym,dlerror,dlclose ();
+       ^~~~~~
+conftest.c:22:15: warning: expression result unused [-Wunused-value]
+return dlopen,dlsym,dlerror,dlclose ();
+              ^~~~~
+conftest.c:22:21: warning: expression result unused [-Wunused-value]
+return dlopen,dlsym,dlerror,dlclose ();
+                    ^~~~~~~
+3 warnings generated.
+configure:4032: $? = 0
+configure:4041: result: yes
+configure:4052: checking for EVP_DigestInit,EVP_md5,EVP_DigestUpdate,BIO_f_base64,BIO_new in -lcrypto
+configure:4077: gcc -o conftest -g -O2   conftest.c -lcrypto  -ldl -lcurl  >&5
+conftest.c:23:8: warning: expression result unused [-Wunused-value]
+return EVP_DigestInit,EVP_md5,EVP_DigestUpdate,BIO_f_base64,BIO_new ();
+       ^~~~~~~~~~~~~~
+conftest.c:23:23: warning: expression result unused [-Wunused-value]
+return EVP_DigestInit,EVP_md5,EVP_DigestUpdate,BIO_f_base64,BIO_new ();
+                      ^~~~~~~
+conftest.c:23:31: warning: expression result unused [-Wunused-value]
+return EVP_DigestInit,EVP_md5,EVP_DigestUpdate,BIO_f_base64,BIO_new ();
+                              ^~~~~~~~~~~~~~~~
+conftest.c:23:48: warning: expression result unused [-Wunused-value]
+return EVP_DigestInit,EVP_md5,EVP_DigestUpdate,BIO_f_base64,BIO_new ();
+                                               ^~~~~~~~~~~~
+4 warnings generated.
+configure:4077: $? = 0
+configure:4086: result: yes
+configure:4097: checking for uuid_generate_time in -luuid
+configure:4122: gcc -o conftest -g -O2   conftest.c -luuid  -lcrypto -ldl -lcurl  >&5
+configure:4122: $? = 0
+configure:4131: result: yes
+configure:4153: checking how to run the C preprocessor
+configure:4184: gcc -E  conftest.c
+configure:4184: $? = 0
+configure:4198: gcc -E  conftest.c
+conftest.c:14:10: fatal error: 'ac_nonexistent.h' file not found
+#include <ac_nonexistent.h>
+         ^
+1 error generated.
+configure:4198: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ZOO Kernel"
+| #define PACKAGE_TARNAME "zoo-kernel"
+| #define PACKAGE_VERSION "1.5.0"
+| #define PACKAGE_STRING "ZOO Kernel 1.5.0"
+| #define PACKAGE_BUGREPORT "bugs at zoo-project.org"
+| #define PACKAGE_URL ""
+| #define YYTEXT_POINTER 1
+| #define HAVE_LIBCURL 1
+| #define HAVE_LIBDL 1
+| #define HAVE_LIBCRYPTO 1
+| #define HAVE_LIBUUID 1
+| /* end confdefs.h.  */
+| #include <ac_nonexistent.h>
+configure:4223: result: gcc -E
+configure:4243: gcc -E  conftest.c
+configure:4243: $? = 0
+configure:4257: gcc -E  conftest.c
+conftest.c:14:10: fatal error: 'ac_nonexistent.h' file not found
+#include <ac_nonexistent.h>
+         ^
+1 error generated.
+configure:4257: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ZOO Kernel"
+| #define PACKAGE_TARNAME "zoo-kernel"
+| #define PACKAGE_VERSION "1.5.0"
+| #define PACKAGE_STRING "ZOO Kernel 1.5.0"
+| #define PACKAGE_BUGREPORT "bugs at zoo-project.org"
+| #define PACKAGE_URL ""
+| #define YYTEXT_POINTER 1
+| #define HAVE_LIBCURL 1
+| #define HAVE_LIBDL 1
+| #define HAVE_LIBCRYPTO 1
+| #define HAVE_LIBUUID 1
+| /* end confdefs.h.  */
+| #include <ac_nonexistent.h>
+configure:4286: checking for grep that handles long lines and -e
+configure:4344: result: /usr/bin/grep
+configure:4349: checking for egrep
+configure:4411: result: /usr/bin/grep -E
+configure:4416: checking for ANSI C header files
+configure:4436: gcc -c -g -O2  conftest.c >&5
+configure:4436: $? = 0
+configure:4509: gcc -o conftest -g -O2   conftest.c -luuid -lcrypto -ldl -lcurl  >&5
+configure:4509: $? = 0
+configure:4509: ./conftest
+configure:4509: $? = 0
+configure:4520: result: yes
+configure:4533: checking for sys/types.h
+configure:4533: gcc -c -g -O2  conftest.c >&5
+configure:4533: $? = 0
+configure:4533: result: yes
+configure:4533: checking for sys/stat.h
+configure:4533: gcc -c -g -O2  conftest.c >&5
+configure:4533: $? = 0
+configure:4533: result: yes
+configure:4533: checking for stdlib.h
+configure:4533: gcc -c -g -O2  conftest.c >&5
+configure:4533: $? = 0
+configure:4533: result: yes
+configure:4533: checking for string.h
+configure:4533: gcc -c -g -O2  conftest.c >&5
+configure:4533: $? = 0
+configure:4533: result: yes
+configure:4533: checking for memory.h
+configure:4533: gcc -c -g -O2  conftest.c >&5
+configure:4533: $? = 0
+configure:4533: result: yes
+configure:4533: checking for strings.h
+configure:4533: gcc -c -g -O2  conftest.c >&5
+configure:4533: $? = 0
+configure:4533: result: yes
+configure:4533: checking for inttypes.h
+configure:4533: gcc -c -g -O2  conftest.c >&5
+configure:4533: $? = 0
+configure:4533: result: yes
+configure:4533: checking for stdint.h
+configure:4533: gcc -c -g -O2  conftest.c >&5
+configure:4533: $? = 0
+configure:4533: result: yes
+configure:4533: checking for unistd.h
+configure:4533: gcc -c -g -O2  conftest.c >&5
+configure:4533: $? = 0
+configure:4533: result: yes
+configure:4545: checking for size_t
+configure:4545: gcc -c -g -O2  conftest.c >&5
+configure:4545: $? = 0
+configure:4545: gcc -c -g -O2  conftest.c >&5
+conftest.c:60:21: error: expected expression
+if (sizeof ((size_t)))
+                    ^
+1 error generated.
+configure:4545: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ZOO Kernel"
+| #define PACKAGE_TARNAME "zoo-kernel"
+| #define PACKAGE_VERSION "1.5.0"
+| #define PACKAGE_STRING "ZOO Kernel 1.5.0"
+| #define PACKAGE_BUGREPORT "bugs at zoo-project.org"
+| #define PACKAGE_URL ""
+| #define YYTEXT_POINTER 1
+| #define HAVE_LIBCURL 1
+| #define HAVE_LIBDL 1
+| #define HAVE_LIBCRYPTO 1
+| #define HAVE_LIBUUID 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| /* end confdefs.h.  */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| #  include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| #  include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| int
+| main ()
+| {
+| if (sizeof ((size_t)))
+| 	    return 0;
+|   ;
+|   return 0;
+| }
+configure:4545: result: yes
+configure:4558: checking for working alloca.h
+configure:4575: gcc -o conftest -g -O2   conftest.c -luuid -lcrypto -ldl -lcurl  >&5
+configure:4575: $? = 0
+configure:4583: result: yes
+configure:4591: checking for alloca
+configure:4628: gcc -o conftest -g -O2   conftest.c -luuid -lcrypto -ldl -lcurl  >&5
+configure:4628: $? = 0
+configure:4636: result: yes
+configure:4745: checking fcntl.h usability
+configure:4745: gcc -c -g -O2  conftest.c >&5
+configure:4745: $? = 0
+configure:4745: result: yes
+configure:4745: checking fcntl.h presence
+configure:4745: gcc -E  conftest.c
+configure:4745: $? = 0
+configure:4745: result: yes
+configure:4745: checking for fcntl.h
+configure:4745: result: yes
+configure:4745: checking for inttypes.h
+configure:4745: result: yes
+configure:4745: checking libintl.h usability
+configure:4745: gcc -c -g -O2  conftest.c >&5
+configure:4745: $? = 0
+configure:4745: result: yes
+configure:4745: checking libintl.h presence
+configure:4745: gcc -E  conftest.c
+configure:4745: $? = 0
+configure:4745: result: yes
+configure:4745: checking for libintl.h
+configure:4745: result: yes
+configure:4745: checking malloc.h usability
+configure:4745: gcc -c -g -O2  conftest.c >&5
+conftest.c:62:10: fatal error: 'malloc.h' file not found
+#include <malloc.h>
+         ^
+1 error generated.
+configure:4745: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ZOO Kernel"
+| #define PACKAGE_TARNAME "zoo-kernel"
+| #define PACKAGE_VERSION "1.5.0"
+| #define PACKAGE_STRING "ZOO Kernel 1.5.0"
+| #define PACKAGE_BUGREPORT "bugs at zoo-project.org"
+| #define PACKAGE_URL ""
+| #define YYTEXT_POINTER 1
+| #define HAVE_LIBCURL 1
+| #define HAVE_LIBDL 1
+| #define HAVE_LIBCRYPTO 1
+| #define HAVE_LIBUUID 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_ALLOCA_H 1
+| #define HAVE_ALLOCA 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_LIBINTL_H 1
+| /* end confdefs.h.  */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| #  include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| #  include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| #include <malloc.h>
+configure:4745: result: no
+configure:4745: checking malloc.h presence
+configure:4745: gcc -E  conftest.c
+conftest.c:29:10: fatal error: 'malloc.h' file not found
+#include <malloc.h>
+         ^
+1 error generated.
+configure:4745: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ZOO Kernel"
+| #define PACKAGE_TARNAME "zoo-kernel"
+| #define PACKAGE_VERSION "1.5.0"
+| #define PACKAGE_STRING "ZOO Kernel 1.5.0"
+| #define PACKAGE_BUGREPORT "bugs at zoo-project.org"
+| #define PACKAGE_URL ""
+| #define YYTEXT_POINTER 1
+| #define HAVE_LIBCURL 1
+| #define HAVE_LIBDL 1
+| #define HAVE_LIBCRYPTO 1
+| #define HAVE_LIBUUID 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_ALLOCA_H 1
+| #define HAVE_ALLOCA 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_LIBINTL_H 1
+| /* end confdefs.h.  */
+| #include <malloc.h>
+configure:4745: result: no
+configure:4745: checking for malloc.h
+configure:4745: result: no
+configure:4745: checking stddef.h usability
+configure:4745: gcc -c -g -O2  conftest.c >&5
+configure:4745: $? = 0
+configure:4745: result: yes
+configure:4745: checking stddef.h presence
+configure:4745: gcc -E  conftest.c
+configure:4745: $? = 0
+configure:4745: result: yes
+configure:4745: checking for stddef.h
+configure:4745: result: yes
+configure:4745: checking for stdlib.h
+configure:4745: result: yes
+configure:4745: checking for string.h
+configure:4745: result: yes
+configure:4745: checking for unistd.h
+configure:4745: result: yes
+configure:4757: checking for stdbool.h that conforms to C99
+configure:4824: gcc -c -g -O2  conftest.c >&5
+conftest.c:82:24: warning: address of 's' will always evaluate to 'true' [-Wpointer-bool-conversion]
+             bool e = &s;
+                  ~    ^
+1 warning generated.
+configure:4824: $? = 0
+configure:4831: result: yes
+configure:4833: checking for _Bool
+configure:4833: gcc -c -g -O2  conftest.c >&5
+configure:4833: $? = 0
+configure:4833: gcc -c -g -O2  conftest.c >&5
+conftest.c:69:20: error: expected expression
+if (sizeof ((_Bool)))
+                   ^
+1 error generated.
+configure:4833: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ZOO Kernel"
+| #define PACKAGE_TARNAME "zoo-kernel"
+| #define PACKAGE_VERSION "1.5.0"
+| #define PACKAGE_STRING "ZOO Kernel 1.5.0"
+| #define PACKAGE_BUGREPORT "bugs at zoo-project.org"
+| #define PACKAGE_URL ""
+| #define YYTEXT_POINTER 1
+| #define HAVE_LIBCURL 1
+| #define HAVE_LIBDL 1
+| #define HAVE_LIBCRYPTO 1
+| #define HAVE_LIBUUID 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_ALLOCA_H 1
+| #define HAVE_ALLOCA 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_LIBINTL_H 1
+| #define HAVE_STDDEF_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_UNISTD_H 1
+| /* end confdefs.h.  */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| #  include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| #  include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| int
+| main ()
+| {
+| if (sizeof ((_Bool)))
+| 	    return 0;
+|   ;
+|   return 0;
+| }
+configure:4833: result: yes
+configure:4850: checking for int16_t
+configure:4850: gcc -c -g -O2  conftest.c >&5
+configure:4850: $? = 0
+configure:4850: gcc -c -g -O2  conftest.c >&5
+conftest.c:72:24: error: 'test_array' declared as an array with a negative size
+static int test_array [1 - 2 * !((int16_t) (((((int16_t) 1 << N) << N) - 1) * 2 + 1)
+                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+1 error generated.
+configure:4850: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ZOO Kernel"
+| #define PACKAGE_TARNAME "zoo-kernel"
+| #define PACKAGE_VERSION "1.5.0"
+| #define PACKAGE_STRING "ZOO Kernel 1.5.0"
+| #define PACKAGE_BUGREPORT "bugs at zoo-project.org"
+| #define PACKAGE_URL ""
+| #define YYTEXT_POINTER 1
+| #define HAVE_LIBCURL 1
+| #define HAVE_LIBDL 1
+| #define HAVE_LIBCRYPTO 1
+| #define HAVE_LIBUUID 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_ALLOCA_H 1
+| #define HAVE_ALLOCA 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_LIBINTL_H 1
+| #define HAVE_STDDEF_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE__BOOL 1
+| #define HAVE_STDBOOL_H 1
+| /* end confdefs.h.  */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| #  include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| #  include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| 	        enum { N = 16 / 2 - 1 };
+| int
+| main ()
+| {
+| static int test_array [1 - 2 * !((int16_t) (((((int16_t) 1 << N) << N) - 1) * 2 + 1)
+| 		 < (int16_t) (((((int16_t) 1 << N) << N) - 1) * 2 + 2))];
+| test_array [0] = 0;
+| return test_array [0];
+| 
+|   ;
+|   return 0;
+| }
+configure:4850: result: yes
+configure:4861: checking for int32_t
+configure:4861: gcc -c -g -O2  conftest.c >&5
+configure:4861: $? = 0
+configure:4861: gcc -c -g -O2  conftest.c >&5
+conftest.c:72:24: error: 'test_array' declared as an array with a negative size
+static int test_array [1 - 2 * !((int32_t) (((((int32_t) 1 << N) << N) - 1) * 2 + 1)
+                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+1 error generated.
+configure:4861: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ZOO Kernel"
+| #define PACKAGE_TARNAME "zoo-kernel"
+| #define PACKAGE_VERSION "1.5.0"
+| #define PACKAGE_STRING "ZOO Kernel 1.5.0"
+| #define PACKAGE_BUGREPORT "bugs at zoo-project.org"
+| #define PACKAGE_URL ""
+| #define YYTEXT_POINTER 1
+| #define HAVE_LIBCURL 1
+| #define HAVE_LIBDL 1
+| #define HAVE_LIBCRYPTO 1
+| #define HAVE_LIBUUID 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_ALLOCA_H 1
+| #define HAVE_ALLOCA 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_LIBINTL_H 1
+| #define HAVE_STDDEF_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE__BOOL 1
+| #define HAVE_STDBOOL_H 1
+| /* end confdefs.h.  */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| #  include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| #  include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| 	        enum { N = 32 / 2 - 1 };
+| int
+| main ()
+| {
+| static int test_array [1 - 2 * !((int32_t) (((((int32_t) 1 << N) << N) - 1) * 2 + 1)
+| 		 < (int32_t) (((((int32_t) 1 << N) << N) - 1) * 2 + 2))];
+| test_array [0] = 0;
+| return test_array [0];
+| 
+|   ;
+|   return 0;
+| }
+configure:4861: result: yes
+configure:4872: checking for int8_t
+configure:4872: gcc -c -g -O2  conftest.c >&5
+configure:4872: $? = 0
+configure:4872: gcc -c -g -O2  conftest.c >&5
+conftest.c:72:24: error: 'test_array' declared as an array with a negative size
+static int test_array [1 - 2 * !((int8_t) (((((int8_t) 1 << N) << N) - 1) * 2 + 1)
+                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+1 error generated.
+configure:4872: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ZOO Kernel"
+| #define PACKAGE_TARNAME "zoo-kernel"
+| #define PACKAGE_VERSION "1.5.0"
+| #define PACKAGE_STRING "ZOO Kernel 1.5.0"
+| #define PACKAGE_BUGREPORT "bugs at zoo-project.org"
+| #define PACKAGE_URL ""
+| #define YYTEXT_POINTER 1
+| #define HAVE_LIBCURL 1
+| #define HAVE_LIBDL 1
+| #define HAVE_LIBCRYPTO 1
+| #define HAVE_LIBUUID 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_ALLOCA_H 1
+| #define HAVE_ALLOCA 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_LIBINTL_H 1
+| #define HAVE_STDDEF_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE__BOOL 1
+| #define HAVE_STDBOOL_H 1
+| /* end confdefs.h.  */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| #  include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| #  include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| 	        enum { N = 8 / 2 - 1 };
+| int
+| main ()
+| {
+| static int test_array [1 - 2 * !((int8_t) (((((int8_t) 1 << N) << N) - 1) * 2 + 1)
+| 		 < (int8_t) (((((int8_t) 1 << N) << N) - 1) * 2 + 2))];
+| test_array [0] = 0;
+| return test_array [0];
+| 
+|   ;
+|   return 0;
+| }
+configure:4872: result: yes
+configure:4883: checking for pid_t
+configure:4883: gcc -c -g -O2  conftest.c >&5
+configure:4883: $? = 0
+configure:4883: gcc -c -g -O2  conftest.c >&5
+conftest.c:71:20: error: expected expression
+if (sizeof ((pid_t)))
+                   ^
+1 error generated.
+configure:4883: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ZOO Kernel"
+| #define PACKAGE_TARNAME "zoo-kernel"
+| #define PACKAGE_VERSION "1.5.0"
+| #define PACKAGE_STRING "ZOO Kernel 1.5.0"
+| #define PACKAGE_BUGREPORT "bugs at zoo-project.org"
+| #define PACKAGE_URL ""
+| #define YYTEXT_POINTER 1
+| #define HAVE_LIBCURL 1
+| #define HAVE_LIBDL 1
+| #define HAVE_LIBCRYPTO 1
+| #define HAVE_LIBUUID 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_ALLOCA_H 1
+| #define HAVE_ALLOCA 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_LIBINTL_H 1
+| #define HAVE_STDDEF_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE__BOOL 1
+| #define HAVE_STDBOOL_H 1
+| /* end confdefs.h.  */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| #  include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| #  include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| int
+| main ()
+| {
+| if (sizeof ((pid_t)))
+| 	    return 0;
+|   ;
+|   return 0;
+| }
+configure:4883: result: yes
+configure:4894: checking for size_t
+configure:4894: result: yes
+configure:4905: checking for uint16_t
+configure:4905: gcc -c -g -O2  conftest.c >&5
+configure:4905: $? = 0
+configure:4905: result: yes
+configure:4917: checking for uint32_t
+configure:4917: gcc -c -g -O2  conftest.c >&5
+configure:4917: $? = 0
+configure:4917: result: yes
+configure:4931: checking for uint8_t
+configure:4931: gcc -c -g -O2  conftest.c >&5
+configure:4931: $? = 0
+configure:4931: result: yes
+configure:4949: checking vfork.h usability
+configure:4949: gcc -c -g -O2  conftest.c >&5
+conftest.c:68:10: fatal error: 'vfork.h' file not found
+#include <vfork.h>
+         ^
+1 error generated.
+configure:4949: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ZOO Kernel"
+| #define PACKAGE_TARNAME "zoo-kernel"
+| #define PACKAGE_VERSION "1.5.0"
+| #define PACKAGE_STRING "ZOO Kernel 1.5.0"
+| #define PACKAGE_BUGREPORT "bugs at zoo-project.org"
+| #define PACKAGE_URL ""
+| #define YYTEXT_POINTER 1
+| #define HAVE_LIBCURL 1
+| #define HAVE_LIBDL 1
+| #define HAVE_LIBCRYPTO 1
+| #define HAVE_LIBUUID 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_ALLOCA_H 1
+| #define HAVE_ALLOCA 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_LIBINTL_H 1
+| #define HAVE_STDDEF_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE__BOOL 1
+| #define HAVE_STDBOOL_H 1
+| /* end confdefs.h.  */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| #  include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| #  include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| #include <vfork.h>
+configure:4949: result: no
+configure:4949: checking vfork.h presence
+configure:4949: gcc -E  conftest.c
+conftest.c:35:10: fatal error: 'vfork.h' file not found
+#include <vfork.h>
+         ^
+1 error generated.
+configure:4949: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ZOO Kernel"
+| #define PACKAGE_TARNAME "zoo-kernel"
+| #define PACKAGE_VERSION "1.5.0"
+| #define PACKAGE_STRING "ZOO Kernel 1.5.0"
+| #define PACKAGE_BUGREPORT "bugs at zoo-project.org"
+| #define PACKAGE_URL ""
+| #define YYTEXT_POINTER 1
+| #define HAVE_LIBCURL 1
+| #define HAVE_LIBDL 1
+| #define HAVE_LIBCRYPTO 1
+| #define HAVE_LIBUUID 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_ALLOCA_H 1
+| #define HAVE_ALLOCA 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_LIBINTL_H 1
+| #define HAVE_STDDEF_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE__BOOL 1
+| #define HAVE_STDBOOL_H 1
+| /* end confdefs.h.  */
+| #include <vfork.h>
+configure:4949: result: no
+configure:4949: checking for vfork.h
+configure:4949: result: no
+configure:4962: checking for fork
+configure:4962: gcc -o conftest -g -O2   conftest.c -luuid -lcrypto -ldl -lcurl  >&5
+configure:4962: $? = 0
+configure:4962: result: yes
+configure:4962: checking for vfork
+configure:4962: gcc -o conftest -g -O2   conftest.c -luuid -lcrypto -ldl -lcurl  >&5
+conftest.c:59:6: warning: incompatible redeclaration of library function 'vfork' [-Wincompatible-library-redeclaration]
+char vfork ();
+     ^
+conftest.c:59:6: note: 'vfork' is a builtin with type 'int (void)'
+1 warning generated.
+configure:4962: $? = 0
+configure:4962: result: yes
+configure:4972: checking for working fork
+configure:4994: gcc -o conftest -g -O2   conftest.c -luuid -lcrypto -ldl -lcurl  >&5
+configure:4994: $? = 0
+configure:4994: ./conftest
+configure:4994: $? = 0
+configure:5004: result: yes
+configure:5025: checking for working vfork
+configure:5135: result: yes
+configure:5162: checking for stdlib.h
+configure:5162: result: yes
+configure:5172: checking for GNU libc compatible malloc
+configure:5196: gcc -o conftest -g -O2   conftest.c -luuid -lcrypto -ldl -lcurl  >&5
+configure:5196: $? = 0
+configure:5196: ./conftest
+configure:5196: $? = 0
+configure:5206: result: yes
+configure:5229: checking for stdlib.h
+configure:5229: result: yes
+configure:5239: checking for GNU libc compatible realloc
+configure:5263: gcc -o conftest -g -O2   conftest.c -luuid -lcrypto -ldl -lcurl  >&5
+configure:5263: $? = 0
+configure:5263: ./conftest
+configure:5263: $? = 0
+configure:5273: result: yes
+configure:5297: checking for dup2
+configure:5297: gcc -o conftest -g -O2   conftest.c -luuid -lcrypto -ldl -lcurl  >&5
+configure:5297: $? = 0
+configure:5297: result: yes
+configure:5297: checking for getcwd
+configure:5297: gcc -o conftest -g -O2   conftest.c -luuid -lcrypto -ldl -lcurl  >&5
+configure:5297: $? = 0
+configure:5297: result: yes
+configure:5297: checking for memset
+configure:5297: gcc -o conftest -g -O2   conftest.c -luuid -lcrypto -ldl -lcurl  >&5
+conftest.c:68:6: warning: incompatible redeclaration of library function 'memset' [-Wincompatible-library-redeclaration]
+char memset ();
+     ^
+conftest.c:68:6: note: 'memset' is a builtin with type 'void *(void *, int, unsigned long)'
+1 warning generated.
+configure:5297: $? = 0
+configure:5297: result: yes
+configure:5297: checking for setenv
+configure:5297: gcc -o conftest -g -O2   conftest.c -luuid -lcrypto -ldl -lcurl  >&5
+configure:5297: $? = 0
+configure:5297: result: yes
+configure:5297: checking for strdup
+configure:5297: gcc -o conftest -g -O2   conftest.c -luuid -lcrypto -ldl -lcurl  >&5
+conftest.c:70:6: warning: incompatible redeclaration of library function 'strdup' [-Wincompatible-library-redeclaration]
+char strdup ();
+     ^
+conftest.c:70:6: note: 'strdup' is a builtin with type 'char *(const char *)'
+1 warning generated.
+configure:5297: $? = 0
+configure:5297: result: yes
+configure:5297: checking for strstr
+configure:5297: gcc -o conftest -g -O2   conftest.c -luuid -lcrypto -ldl -lcurl  >&5
+conftest.c:71:6: warning: incompatible redeclaration of library function 'strstr' [-Wincompatible-library-redeclaration]
+char strstr ();
+     ^
+conftest.c:71:6: note: 'strstr' is a builtin with type 'char *(const char *, const char *)'
+1 warning generated.
+configure:5297: $? = 0
+configure:5297: result: yes
+configure:5369: checking for yaml_parser_initialize,yaml_parser_set_input_file,yaml_parser_scan in -lyaml
+configure:5394: gcc -o conftest -g -O2 -I/usr/local//include -DYAML  conftest.c -lyaml  -L/usr/local//lib -lyaml >&5
+conftest.c:60:8: warning: expression result unused [-Wunused-value]
+return yaml_parser_initialize,yaml_parser_set_input_file,yaml_parser_scan ();
+       ^~~~~~~~~~~~~~~~~~~~~~
+conftest.c:60:31: warning: expression result unused [-Wunused-value]
+return yaml_parser_initialize,yaml_parser_set_input_file,yaml_parser_scan ();
+                              ^~~~~~~~~~~~~~~~~~~~~~~~~~
+2 warnings generated.
+configure:5394: $? = 0
+configure:5403: result: yes
+configure:5416: checking yaml.h usability
+configure:5416: gcc -c -g -O2 -I/usr/local//include -DYAML conftest.c >&5
+configure:5416: $? = 0
+configure:5416: result: yes
+configure:5416: checking yaml.h presence
+configure:5416: gcc -E -I/usr/local//include -DYAML conftest.c
+configure:5416: $? = 0
+configure:5416: result: yes
+configure:5416: checking for yaml.h
+configure:5416: result: yes
+configure:5457: checking for main in -lfcgi
+configure:5476: gcc -o conftest -g -O2 -I/usr/local//include  conftest.c -lfcgi  -L/usr/local//lib >&5
+configure:5476: $? = 0
+configure:5485: result: yes
+configure:5498: checking fcgi_stdio.h usability
+configure:5498: gcc -c -g -O2 -I/usr/local//include conftest.c >&5
+configure:5498: $? = 0
+configure:5498: result: yes
+configure:5498: checking fcgi_stdio.h presence
+configure:5498: gcc -E -I/usr/local//include conftest.c
+configure:5498: $? = 0
+configure:5498: result: yes
+configure:5498: checking for fcgi_stdio.h
+configure:5498: result: yes
+configure:5531: checking for xml2-config
+configure:5549: found /usr/local/bin/xml2-config
+configure:5561: result: /usr/local/bin/xml2-config
+configure:5598: checking libxml/tree.h usability
+configure:5598: gcc -c -g -O2 -I/usr/local/include/libxml2 conftest.c >&5
+configure:5598: $? = 0
+configure:5598: result: yes
+configure:5598: checking libxml/tree.h presence
+configure:5598: gcc -E -I/usr/local/include/libxml2 conftest.c
+configure:5598: $? = 0
+configure:5598: result: yes
+configure:5598: checking for libxml/tree.h
+configure:5598: result: yes
+configure:5598: checking libxml/parser.h usability
+configure:5598: gcc -c -g -O2 -I/usr/local/include/libxml2 conftest.c >&5
+configure:5598: $? = 0
+configure:5598: result: yes
+configure:5598: checking libxml/parser.h presence
+configure:5598: gcc -E -I/usr/local/include/libxml2 conftest.c
+configure:5598: $? = 0
+configure:5598: result: yes
+configure:5598: checking for libxml/parser.h
+configure:5598: result: yes
+configure:5598: checking libxml/xpath.h usability
+configure:5598: gcc -c -g -O2 -I/usr/local/include/libxml2 conftest.c >&5
+configure:5598: $? = 0
+configure:5598: result: yes
+configure:5598: checking libxml/xpath.h presence
+configure:5598: gcc -E -I/usr/local/include/libxml2 conftest.c
+configure:5598: $? = 0
+configure:5598: result: yes
+configure:5598: checking for libxml/xpath.h
+configure:5598: result: yes
+configure:5598: checking libxml/xpathInternals.h usability
+configure:5598: gcc -c -g -O2 -I/usr/local/include/libxml2 conftest.c >&5
+configure:5598: $? = 0
+configure:5598: result: yes
+configure:5598: checking libxml/xpathInternals.h presence
+configure:5598: gcc -E -I/usr/local/include/libxml2 conftest.c
+configure:5598: $? = 0
+configure:5598: result: yes
+configure:5598: checking for libxml/xpathInternals.h
+configure:5598: result: yes
+configure:5614: checking for xmlInitParser in -lxml2
+configure:5639: gcc -o conftest -g -O2 -I/usr/local/include/libxml2  conftest.c -lxml2  -L/usr/local/lib -lxml2 -lz -liconv -lm >&5
+configure:5639: $? = 0
+configure:5648: result: yes
+configure:5684: checking for xslt-config
+configure:5702: found /usr/local/bin/xslt-config
+configure:5714: result: /usr/local/bin/xslt-config
+configure:5751: checking libxslt/xslt.h usability
+configure:5751: gcc -c -g -O2 -I/usr/local/include -I/usr/local/include/libxml2 conftest.c >&5
+configure:5751: $? = 0
+configure:5751: result: yes
+configure:5751: checking libxslt/xslt.h presence
+configure:5751: gcc -E -I/usr/local/include -I/usr/local/include/libxml2 conftest.c
+configure:5751: $? = 0
+configure:5751: result: yes
+configure:5751: checking for libxslt/xslt.h
+configure:5751: result: yes
+configure:5751: checking libxslt/xsltInternals.h usability
+configure:5751: gcc -c -g -O2 -I/usr/local/include -I/usr/local/include/libxml2 conftest.c >&5
+configure:5751: $? = 0
+configure:5751: result: yes
+configure:5751: checking libxslt/xsltInternals.h presence
+configure:5751: gcc -E -I/usr/local/include -I/usr/local/include/libxml2 conftest.c
+configure:5751: $? = 0
+configure:5751: result: yes
+configure:5751: checking for libxslt/xsltInternals.h
+configure:5751: result: yes
+configure:5751: checking libxslt/transform.h usability
+configure:5751: gcc -c -g -O2 -I/usr/local/include -I/usr/local/include/libxml2 conftest.c >&5
+configure:5751: $? = 0
+configure:5751: result: yes
+configure:5751: checking libxslt/transform.h presence
+configure:5751: gcc -E -I/usr/local/include -I/usr/local/include/libxml2 conftest.c
+configure:5751: $? = 0
+configure:5751: result: yes
+configure:5751: checking for libxslt/transform.h
+configure:5751: result: yes
+configure:5751: checking libxslt/xsltutils.h usability
+configure:5751: gcc -c -g -O2 -I/usr/local/include -I/usr/local/include/libxml2 conftest.c >&5
+configure:5751: $? = 0
+configure:5751: result: yes
+configure:5751: checking libxslt/xsltutils.h presence
+configure:5751: gcc -E -I/usr/local/include -I/usr/local/include/libxml2 conftest.c
+configure:5751: $? = 0
+configure:5751: result: yes
+configure:5751: checking for libxslt/xsltutils.h
+configure:5751: result: yes
+configure:5828: result: Using user-specified gdal-config file: /Library/Frameworks/GDAL.framework/unix/bin/gdal-config
+configure:5863: checking proj_api.h usability
+configure:5863: gcc -c -g -O2 -I/Library/Frameworks/PROJ.framework/unix/include conftest.c >&5
+configure:5863: $? = 0
+configure:5863: result: yes
+configure:5863: checking proj_api.h presence
+configure:5863: gcc -E -I/Library/Frameworks/PROJ.framework/unix/include conftest.c
+configure:5863: $? = 0
+configure:5863: result: yes
+configure:5863: checking for proj_api.h
+configure:5863: result: yes
+configure:5947: result: Using user-specified geos-config file: /Library/Frameworks/GEOS.framework/unix/bin/geos-config
+configure:5963: checking geos_c.h usability
+configure:5963: gcc -c -g -O2 -I/Library/Frameworks/GEOS.framework/Versions/3/unix/include conftest.c >&5
+configure:5963: $? = 0
+configure:5963: result: yes
+configure:5963: checking geos_c.h presence
+configure:5963: gcc -E -I/Library/Frameworks/GEOS.framework/Versions/3/unix/include conftest.c
+configure:5963: $? = 0
+configure:5963: result: yes
+configure:5963: checking for geos_c.h
+configure:5963: result: yes
+configure:6000: checking CGAL/Delaunay_triangulation_2.h usability
+configure:6000: gcc -c -g -O2  conftest.c >&5
+conftest.c:97:10: fatal error: 'CGAL/Delaunay_triangulation_2.h' file not found
+#include <CGAL/Delaunay_triangulation_2.h>
+         ^
+1 error generated.
+configure:6000: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ZOO Kernel"
+| #define PACKAGE_TARNAME "zoo-kernel"
+| #define PACKAGE_VERSION "1.5.0"
+| #define PACKAGE_STRING "ZOO Kernel 1.5.0"
+| #define PACKAGE_BUGREPORT "bugs at zoo-project.org"
+| #define PACKAGE_URL ""
+| #define YYTEXT_POINTER 1
+| #define HAVE_LIBCURL 1
+| #define HAVE_LIBDL 1
+| #define HAVE_LIBCRYPTO 1
+| #define HAVE_LIBUUID 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_ALLOCA_H 1
+| #define HAVE_ALLOCA 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_LIBINTL_H 1
+| #define HAVE_STDDEF_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE__BOOL 1
+| #define HAVE_STDBOOL_H 1
+| #define HAVE_FORK 1
+| #define HAVE_VFORK 1
+| #define HAVE_WORKING_VFORK 1
+| #define HAVE_WORKING_FORK 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_MALLOC 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_REALLOC 1
+| #define HAVE_DUP2 1
+| #define HAVE_GETCWD 1
+| #define HAVE_MEMSET 1
+| #define HAVE_SETENV 1
+| #define HAVE_STRDUP 1
+| #define HAVE_STRSTR 1
+| #define HAVE_LIBYAML 1
+| #define HAVE_YAML_H 1
+| #define HAVE_LIBFCGI 1
+| #define HAVE_FCGI_STDIO_H 1
+| #define HAVE_LIBXML_TREE_H 1
+| #define HAVE_LIBXML_PARSER_H 1
+| #define HAVE_LIBXML_XPATH_H 1
+| #define HAVE_LIBXML_XPATHINTERNALS_H 1
+| #define HAVE_LIBXML2 1
+| #define HAVE_LIBXSLT_XSLT_H 1
+| #define HAVE_LIBXSLT_XSLTINTERNALS_H 1
+| #define HAVE_LIBXSLT_TRANSFORM_H 1
+| #define HAVE_LIBXSLT_XSLTUTILS_H 1
+| #define HAVE_PROJ_API_H 1
+| #define HAVE_GEOS_C_H 1
+| /* end confdefs.h.  */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| #  include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| #  include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| #include <CGAL/Delaunay_triangulation_2.h>
+configure:6000: result: no
+configure:6000: checking CGAL/Delaunay_triangulation_2.h presence
+configure:6000: gcc -E  conftest.c
+conftest.c:64:10: fatal error: 'CGAL/Delaunay_triangulation_2.h' file not found
+#include <CGAL/Delaunay_triangulation_2.h>
+         ^
+1 error generated.
+configure:6000: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ZOO Kernel"
+| #define PACKAGE_TARNAME "zoo-kernel"
+| #define PACKAGE_VERSION "1.5.0"
+| #define PACKAGE_STRING "ZOO Kernel 1.5.0"
+| #define PACKAGE_BUGREPORT "bugs at zoo-project.org"
+| #define PACKAGE_URL ""
+| #define YYTEXT_POINTER 1
+| #define HAVE_LIBCURL 1
+| #define HAVE_LIBDL 1
+| #define HAVE_LIBCRYPTO 1
+| #define HAVE_LIBUUID 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_ALLOCA_H 1
+| #define HAVE_ALLOCA 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_LIBINTL_H 1
+| #define HAVE_STDDEF_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE__BOOL 1
+| #define HAVE_STDBOOL_H 1
+| #define HAVE_FORK 1
+| #define HAVE_VFORK 1
+| #define HAVE_WORKING_VFORK 1
+| #define HAVE_WORKING_FORK 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_MALLOC 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_REALLOC 1
+| #define HAVE_DUP2 1
+| #define HAVE_GETCWD 1
+| #define HAVE_MEMSET 1
+| #define HAVE_SETENV 1
+| #define HAVE_STRDUP 1
+| #define HAVE_STRSTR 1
+| #define HAVE_LIBYAML 1
+| #define HAVE_YAML_H 1
+| #define HAVE_LIBFCGI 1
+| #define HAVE_FCGI_STDIO_H 1
+| #define HAVE_LIBXML_TREE_H 1
+| #define HAVE_LIBXML_PARSER_H 1
+| #define HAVE_LIBXML_XPATH_H 1
+| #define HAVE_LIBXML_XPATHINTERNALS_H 1
+| #define HAVE_LIBXML2 1
+| #define HAVE_LIBXSLT_XSLT_H 1
+| #define HAVE_LIBXSLT_XSLTINTERNALS_H 1
+| #define HAVE_LIBXSLT_TRANSFORM_H 1
+| #define HAVE_LIBXSLT_XSLTUTILS_H 1
+| #define HAVE_PROJ_API_H 1
+| #define HAVE_GEOS_C_H 1
+| /* end confdefs.h.  */
+| #include <CGAL/Delaunay_triangulation_2.h>
+configure:6000: result: no
+configure:6000: checking for CGAL/Delaunay_triangulation_2.h
+configure:6000: result: no
+configure:6007: WARNING: could not find headers include related to libCGAL
+configure:6052: result: Using user-specified MapServer src path: /Users/djay/MapMint/src/mapserver-6.2.0/
+configure:6145: checking for python2.7-config
+configure:6163: found /usr/bin/python2.7-config
+configure:6175: result: /usr/bin/python2.7-config
+configure:6197: checking Python.h usability
+configure:6197: gcc -c -g -O2 -I/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 -I/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 conftest.c >&5
+configure:6197: $? = 0
+configure:6197: result: yes
+configure:6197: checking Python.h presence
+configure:6197: gcc -E -I/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 -I/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 conftest.c
+configure:6197: $? = 0
+configure:6197: result: yes
+configure:6197: checking for Python.h
+configure:6197: result: yes
+configure:6215: checking for PyObject_CallObject in -lpython2.7
+configure:6240: gcc -o conftest -g -O2 -I/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 -I/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7  conftest.c -lpython2.7  -L/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/config -ldl -framework CoreFoundation -lpython2.7 >&5
+configure:6240: $? = 0
+configure:6250: result: yes
+configure:6334: checking how to run the C++ preprocessor
+configure:6361: g++ -E -I/usr/local//include/js/ conftest.cpp
+configure:6361: $? = 0
+configure:6375: g++ -E -I/usr/local//include/js/ conftest.cpp
+conftest.cpp:66:10: fatal error: 'ac_nonexistent.h' file not found
+#include <ac_nonexistent.h>
+         ^
+1 error generated.
+configure:6375: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ZOO Kernel"
+| #define PACKAGE_TARNAME "zoo-kernel"
+| #define PACKAGE_VERSION "1.5.0"
+| #define PACKAGE_STRING "ZOO Kernel 1.5.0"
+| #define PACKAGE_BUGREPORT "bugs at zoo-project.org"
+| #define PACKAGE_URL ""
+| #define YYTEXT_POINTER 1
+| #define HAVE_LIBCURL 1
+| #define HAVE_LIBDL 1
+| #define HAVE_LIBCRYPTO 1
+| #define HAVE_LIBUUID 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_ALLOCA_H 1
+| #define HAVE_ALLOCA 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_LIBINTL_H 1
+| #define HAVE_STDDEF_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE__BOOL 1
+| #define HAVE_STDBOOL_H 1
+| #define HAVE_FORK 1
+| #define HAVE_VFORK 1
+| #define HAVE_WORKING_VFORK 1
+| #define HAVE_WORKING_FORK 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_MALLOC 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_REALLOC 1
+| #define HAVE_DUP2 1
+| #define HAVE_GETCWD 1
+| #define HAVE_MEMSET 1
+| #define HAVE_SETENV 1
+| #define HAVE_STRDUP 1
+| #define HAVE_STRSTR 1
+| #define HAVE_LIBYAML 1
+| #define HAVE_YAML_H 1
+| #define HAVE_LIBFCGI 1
+| #define HAVE_FCGI_STDIO_H 1
+| #define HAVE_LIBXML_TREE_H 1
+| #define HAVE_LIBXML_PARSER_H 1
+| #define HAVE_LIBXML_XPATH_H 1
+| #define HAVE_LIBXML_XPATHINTERNALS_H 1
+| #define HAVE_LIBXML2 1
+| #define HAVE_LIBXSLT_XSLT_H 1
+| #define HAVE_LIBXSLT_XSLTINTERNALS_H 1
+| #define HAVE_LIBXSLT_TRANSFORM_H 1
+| #define HAVE_LIBXSLT_XSLTUTILS_H 1
+| #define HAVE_PROJ_API_H 1
+| #define HAVE_GEOS_C_H 1
+| #define HAVE_PYTHON_H 1
+| #define HAVE_LIBPYTHON2_7 1
+| /* end confdefs.h.  */
+| #include <ac_nonexistent.h>
+configure:6400: result: g++ -E
+configure:6420: g++ -E -I/usr/local//include/js/ conftest.cpp
+configure:6420: $? = 0
+configure:6434: g++ -E -I/usr/local//include/js/ conftest.cpp
+conftest.cpp:66:10: fatal error: 'ac_nonexistent.h' file not found
+#include <ac_nonexistent.h>
+         ^
+1 error generated.
+configure:6434: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "ZOO Kernel"
+| #define PACKAGE_TARNAME "zoo-kernel"
+| #define PACKAGE_VERSION "1.5.0"
+| #define PACKAGE_STRING "ZOO Kernel 1.5.0"
+| #define PACKAGE_BUGREPORT "bugs at zoo-project.org"
+| #define PACKAGE_URL ""
+| #define YYTEXT_POINTER 1
+| #define HAVE_LIBCURL 1
+| #define HAVE_LIBDL 1
+| #define HAVE_LIBCRYPTO 1
+| #define HAVE_LIBUUID 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_ALLOCA_H 1
+| #define HAVE_ALLOCA 1
+| #define HAVE_FCNTL_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_LIBINTL_H 1
+| #define HAVE_STDDEF_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE__BOOL 1
+| #define HAVE_STDBOOL_H 1
+| #define HAVE_FORK 1
+| #define HAVE_VFORK 1
+| #define HAVE_WORKING_VFORK 1
+| #define HAVE_WORKING_FORK 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_MALLOC 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_REALLOC 1
+| #define HAVE_DUP2 1
+| #define HAVE_GETCWD 1
+| #define HAVE_MEMSET 1
+| #define HAVE_SETENV 1
+| #define HAVE_STRDUP 1
+| #define HAVE_STRSTR 1
+| #define HAVE_LIBYAML 1
+| #define HAVE_YAML_H 1
+| #define HAVE_LIBFCGI 1
+| #define HAVE_FCGI_STDIO_H 1
+| #define HAVE_LIBXML_TREE_H 1
+| #define HAVE_LIBXML_PARSER_H 1
+| #define HAVE_LIBXML_XPATH_H 1
+| #define HAVE_LIBXML_XPATHINTERNALS_H 1
+| #define HAVE_LIBXML2 1
+| #define HAVE_LIBXSLT_XSLT_H 1
+| #define HAVE_LIBXSLT_XSLTINTERNALS_H 1
+| #define HAVE_LIBXSLT_TRANSFORM_H 1
+| #define HAVE_LIBXSLT_XSLTUTILS_H 1
+| #define HAVE_PROJ_API_H 1
+| #define HAVE_GEOS_C_H 1
+| #define HAVE_PYTHON_H 1
+| #define HAVE_LIBPYTHON2_7 1
+| /* end confdefs.h.  */
+| #include <ac_nonexistent.h>
+configure:6465: checking jsapi.h usability
+configure:6465: g++ -c -g -O2 -I/usr/local//include/js/ conftest.cpp >&5
+configure:6465: $? = 0
+configure:6465: result: yes
+configure:6465: checking jsapi.h presence
+configure:6465: g++ -E -I/usr/local//include/js/ conftest.cpp
+configure:6465: $? = 0
+configure:6465: result: yes
+configure:6465: checking for jsapi.h
+configure:6465: result: yes
+configure:6488: checking for JS_CompileFile,JS_CallFunctionName in -lmozjs185
+configure:6513: gcc -o conftest -g -O2 -I/usr/local//include/js/  conftest.c -lmozjs185  -L/usr/local//lib -lmozjs185 -lm >&5
+conftest.c:78:8: warning: expression result unused [-Wunused-value]
+return JS_CompileFile,JS_CallFunctionName ();
+       ^~~~~~~~~~~~~~
+1 warning generated.
+configure:6513: $? = 0
+configure:6523: result: yes
+configure:6741: checking jni.h usability
+configure:6741: gcc -c -g -O2 -I/Applications/Xcode.app/Contents/Developer//Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/System/Library/Frameworks/JavaVM.framework/Versions/A/Headers/ conftest.c >&5
+configure:6741: $? = 0
+configure:6741: result: yes
+configure:6741: checking jni.h presence
+configure:6741: gcc -E -I/Applications/Xcode.app/Contents/Developer//Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/System/Library/Frameworks/JavaVM.framework/Versions/A/Headers/ conftest.c
+configure:6741: $? = 0
+configure:6741: result: yes
+configure:6741: checking for jni.h
+configure:6741: result: yes
+configure:7034: checking otbWrapperApplication.h usability
+configure:7034: g++ -c -g -O2 -I/usr/local//include/otb/ApplicationEngine -I/usr/local//include/otb/Common -I/include/ITK-4.5 -I/usr/local//include/otb/Utilities/ITK -I/usr/local//include/otb/ -I/usr/local//include/otb/IO -I/usr/local//include/otb/UtilitiesAdapters/OssimAdapters -I/usr/local//include/otb/UtilitiesAdapters/CurlAdapters -I/usr/local//include/otb/Utilities/BGL -I/usr/local//include/otb/UtilitiesAdapters/ITKPendingPatches -I/usr/local//include/otb/Utilities/otbconfigfile -I/ [...]
+configure:7034: $? = 0
+configure:7034: result: yes
+configure:7034: checking otbWrapperApplication.h presence
+configure:7034: g++ -E -I/usr/local//include/otb/ApplicationEngine -I/usr/local//include/otb/Common -I/include/ITK-4.5 -I/usr/local//include/otb/Utilities/ITK -I/usr/local//include/otb/ -I/usr/local//include/otb/IO -I/usr/local//include/otb/UtilitiesAdapters/OssimAdapters -I/usr/local//include/otb/UtilitiesAdapters/CurlAdapters -I/usr/local//include/otb/Utilities/BGL -I/usr/local//include/otb/UtilitiesAdapters/ITKPendingPatches -I/usr/local//include/otb/Utilities/otbconfigfile -I/Library [...]
+configure:7034: $? = 0
+configure:7034: result: yes
+configure:7034: checking for otbWrapperApplication.h
+configure:7034: result: yes
+configure:7034: checking otbWrapperInputImageListParameter.h usability
+configure:7034: g++ -c -g -O2 -I/usr/local//include/otb/ApplicationEngine -I/usr/local//include/otb/Common -I/include/ITK-4.5 -I/usr/local//include/otb/Utilities/ITK -I/usr/local//include/otb/ -I/usr/local//include/otb/IO -I/usr/local//include/otb/UtilitiesAdapters/OssimAdapters -I/usr/local//include/otb/UtilitiesAdapters/CurlAdapters -I/usr/local//include/otb/Utilities/BGL -I/usr/local//include/otb/UtilitiesAdapters/ITKPendingPatches -I/usr/local//include/otb/Utilities/otbconfigfile -I/ [...]
+configure:7034: $? = 0
+configure:7034: result: yes
+configure:7034: checking otbWrapperInputImageListParameter.h presence
+configure:7034: g++ -E -I/usr/local//include/otb/ApplicationEngine -I/usr/local//include/otb/Common -I/include/ITK-4.5 -I/usr/local//include/otb/Utilities/ITK -I/usr/local//include/otb/ -I/usr/local//include/otb/IO -I/usr/local//include/otb/UtilitiesAdapters/OssimAdapters -I/usr/local//include/otb/UtilitiesAdapters/CurlAdapters -I/usr/local//include/otb/Utilities/BGL -I/usr/local//include/otb/UtilitiesAdapters/ITKPendingPatches -I/usr/local//include/otb/Utilities/otbconfigfile -I/Library [...]
+configure:7034: $? = 0
+configure:7034: result: yes
+configure:7034: checking for otbWrapperInputImageListParameter.h
+configure:7034: result: yes
+configure:7034: checking otbWrapperApplicationRegistry.h usability
+configure:7034: g++ -c -g -O2 -I/usr/local//include/otb/ApplicationEngine -I/usr/local//include/otb/Common -I/include/ITK-4.5 -I/usr/local//include/otb/Utilities/ITK -I/usr/local//include/otb/ -I/usr/local//include/otb/IO -I/usr/local//include/otb/UtilitiesAdapters/OssimAdapters -I/usr/local//include/otb/UtilitiesAdapters/CurlAdapters -I/usr/local//include/otb/Utilities/BGL -I/usr/local//include/otb/UtilitiesAdapters/ITKPendingPatches -I/usr/local//include/otb/Utilities/otbconfigfile -I/ [...]
+configure:7034: $? = 0
+configure:7034: result: yes
+configure:7034: checking otbWrapperApplicationRegistry.h presence
+configure:7034: g++ -E -I/usr/local//include/otb/ApplicationEngine -I/usr/local//include/otb/Common -I/include/ITK-4.5 -I/usr/local//include/otb/Utilities/ITK -I/usr/local//include/otb/ -I/usr/local//include/otb/IO -I/usr/local//include/otb/UtilitiesAdapters/OssimAdapters -I/usr/local//include/otb/UtilitiesAdapters/CurlAdapters -I/usr/local//include/otb/Utilities/BGL -I/usr/local//include/otb/UtilitiesAdapters/ITKPendingPatches -I/usr/local//include/otb/Utilities/otbconfigfile -I/Library [...]
+configure:7034: $? = 0
+configure:7034: result: yes
+configure:7034: checking for otbWrapperApplicationRegistry.h
+configure:7034: result: yes
+configure:7071: g++ -o conftest -g -O2 -I/usr/local//include/otb/ApplicationEngine -I/usr/local//include/otb/Common -I/include/ITK-4.5 -I/usr/local//include/otb/Utilities/ITK -I/usr/local//include/otb/ -I/usr/local//include/otb/IO -I/usr/local//include/otb/UtilitiesAdapters/OssimAdapters -I/usr/local//include/otb/UtilitiesAdapters/CurlAdapters -I/usr/local//include/otb/Utilities/BGL -I/usr/local//include/otb/UtilitiesAdapters/ITKPendingPatches -I/usr/local//include/otb/Utilities/otbconfi [...]
+conftest.cpp:72:35: warning: extra tokens at end of #include directive [-Wextra-tokens]
+#include "otbWrapperApplication.h",std::vector<std::string> list = otb::Wrapwper::ApplicationRegistry::GetAvailableApplication();
+                                  ^
+                                  //
+1 warning generated.
+ld: warning: directory not found for option '-L/lib'
+ld: warning: directory not found for option '-L/lib'
+configure:7071: $? = 0
+configure:7072: result: checking for GetAvailableApplication... yes
+configure:7142: checking module_library.h usability
+configure:7142: g++ -c -g -O2  -fPIC -I/usr/local//include/saga/saga_core/saga_api/ -I/usr/local/lib/wx/include/osx_cocoa-unicode-3.0 -I/usr/local/include/wx-3.0 -D_FILE_OFFSET_BITS=64 -DWXUSINGDLL -D__WXMAC__ -D__WXOSX__ -D__WXOSX_COCOA__  -D_SAGA_UNICODE -D_SAGA_LINUX -D_TYPEDEF_BYTE -D_TYPEDEF_WORD -DMODULE_LIBRARY_PATH=\"/usr/local//lib/saga\" -D_WX_WXCRTVARARG_H_ conftest.cpp >&5
+In file included from <built-in>:326:
+<command line>:10:30: warning: missing terminating '"' character [-Winvalid-pp-token]
+#define MODULE_LIBRARY_PATH \"/usr/local//lib/saga\"
+                             ^
+In file included from conftest.cpp:105:
+In file included from /usr/local//include/saga/saga_core/saga_api/module_library.h:77:
+In file included from /usr/local//include/saga/saga_core/saga_api/module.h:76:
+In file included from /usr/local//include/saga/saga_core/saga_api/parameters.h:77:
+In file included from /usr/local//include/saga/saga_core/saga_api/grid.h:77:
+In file included from /usr/local//include/saga/saga_core/saga_api/table.h:77:
+In file included from /usr/local//include/saga/saga_core/saga_api/dataobject.h:84:
+In file included from /usr/local//include/saga/saga_core/saga_api/mat_tools.h:77:
+In file included from /usr/local//include/saga/saga_core/saga_api/geo_tools.h:78:
+/usr/local//include/saga/saga_core/saga_api/metadata.h:158:51: warning: 'this' pointer cannot be null in well-defined C++ code; comparison may be assumed to always evaluate to true [-Wtautological-undefined-compare]
+        bool                                            is_Valid                        (void)                                          const   {       return( this != NULL );                                 }
+                                                                                                                                                                ^~~~    ~~~~
+2 warnings generated.
+configure:7142: $? = 0
+configure:7142: result: yes
+configure:7142: checking module_library.h presence
+configure:7142: g++ -E  -fPIC -I/usr/local//include/saga/saga_core/saga_api/ -I/usr/local/lib/wx/include/osx_cocoa-unicode-3.0 -I/usr/local/include/wx-3.0 -D_FILE_OFFSET_BITS=64 -DWXUSINGDLL -D__WXMAC__ -D__WXOSX__ -D__WXOSX_COCOA__  -D_SAGA_UNICODE -D_SAGA_LINUX -D_TYPEDEF_BYTE -D_TYPEDEF_WORD -DMODULE_LIBRARY_PATH=\"/usr/local//lib/saga\" -D_WX_WXCRTVARARG_H_ conftest.cpp
+In file included from <built-in>:326:
+<command line>:10:30: warning: missing terminating '"' character [-Winvalid-pp-token]
+#define MODULE_LIBRARY_PATH \"/usr/local//lib/saga\"
+                             ^
+1 warning generated.
+configure:7142: $? = 0
+configure:7142: result: yes
+configure:7142: checking for module_library.h
+configure:7142: result: yes
+configure:7165: g++ -o conftest -g -O2  -fPIC -I/usr/local//include/saga/saga_core/saga_api/ -I/usr/local/lib/wx/include/osx_cocoa-unicode-3.0 -I/usr/local/include/wx-3.0 -D_FILE_OFFSET_BITS=64 -DWXUSINGDLL -D__WXMAC__ -D__WXOSX__ -D__WXOSX_COCOA__  -D_SAGA_UNICODE -D_SAGA_LINUX -D_TYPEDEF_BYTE -D_TYPEDEF_WORD -DMODULE_LIBRARY_PATH=\"/usr/local//lib/saga\" -D_WX_WXCRTVARARG_H_  conftest.cpp -fPIC -L/usr/local/lib   -framework IOKit -framework Carbon -framework Cocoa -framework AudioToolb [...]
+In file included from <built-in>:326:
+<command line>:10:30: warning: missing terminating '"' character [-Winvalid-pp-token]
+#define MODULE_LIBRARY_PATH \"/usr/local//lib/saga\"
+                             ^
+conftest.cpp:73:28: warning: extra tokens at end of #include directive [-Wextra-tokens]
+#include "module_library.h",SG_Get_Module_Library_Manager();
+                           ^
+                           //
+In file included from conftest.cpp:73:
+In file included from /usr/local//include/saga/saga_core/saga_api/module_library.h:77:
+In file included from /usr/local//include/saga/saga_core/saga_api/module.h:76:
+In file included from /usr/local//include/saga/saga_core/saga_api/parameters.h:77:
+In file included from /usr/local//include/saga/saga_core/saga_api/grid.h:77:
+In file included from /usr/local//include/saga/saga_core/saga_api/table.h:77:
+In file included from /usr/local//include/saga/saga_core/saga_api/dataobject.h:84:
+In file included from /usr/local//include/saga/saga_core/saga_api/mat_tools.h:77:
+In file included from /usr/local//include/saga/saga_core/saga_api/geo_tools.h:78:
+/usr/local//include/saga/saga_core/saga_api/metadata.h:158:51: warning: 'this' pointer cannot be null in well-defined C++ code; comparison may be assumed to always evaluate to true [-Wtautological-undefined-compare]
+        bool                                            is_Valid                        (void)                                          const   {       return( this != NULL );                                 }
+                                                                                                                                                                ^~~~    ~~~~
+3 warnings generated.
+configure:7165: $? = 0
+configure:7166: result: checking for SG_Get_Module_Library_Manager... yes
+configure:7340: creating ./config.status
+
+## ---------------------- ##
+## Running config.status. ##
+## ---------------------- ##
+
+This file was extended by ZOO Kernel config.status 1.5.0, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  CONFIG_FILES    = 
+  CONFIG_HEADERS  = 
+  CONFIG_LINKS    = 
+  CONFIG_COMMANDS = 
+  $ ./config.status 
+
+on MBP-de-Fenoy-2.home
+
+config.status:835: creating Makefile
+config.status:835: creating ZOOMakefile.opts
+
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+
+ac_cv_c_compiler_gnu=yes
+ac_cv_c_int16_t=yes
+ac_cv_c_int32_t=yes
+ac_cv_c_int8_t=yes
+ac_cv_c_uint16_t=yes
+ac_cv_c_uint32_t=yes
+ac_cv_c_uint8_t=yes
+ac_cv_cxx_compiler_gnu=yes
+ac_cv_env_CCC_set=
+ac_cv_env_CCC_value=
+ac_cv_env_CC_set=
+ac_cv_env_CC_value=
+ac_cv_env_CFLAGS_set=
+ac_cv_env_CFLAGS_value=
+ac_cv_env_CPPFLAGS_set=
+ac_cv_env_CPPFLAGS_value=
+ac_cv_env_CPP_set=
+ac_cv_env_CPP_value=
+ac_cv_env_CXXCPP_set=
+ac_cv_env_CXXCPP_value=
+ac_cv_env_CXXFLAGS_set=
+ac_cv_env_CXXFLAGS_value=
+ac_cv_env_CXX_set=
+ac_cv_env_CXX_value=
+ac_cv_env_LDFLAGS_set=
+ac_cv_env_LDFLAGS_value=
+ac_cv_env_LIBS_set=
+ac_cv_env_LIBS_value=
+ac_cv_env_YACC_set=
+ac_cv_env_YACC_value=
+ac_cv_env_YFLAGS_set=
+ac_cv_env_YFLAGS_value=
+ac_cv_env_build_alias_set=
+ac_cv_env_build_alias_value=
+ac_cv_env_host_alias_set=
+ac_cv_env_host_alias_value=
+ac_cv_env_target_alias_set=
+ac_cv_env_target_alias_value=
+ac_cv_func_alloca_works=yes
+ac_cv_func_dup2=yes
+ac_cv_func_fork=yes
+ac_cv_func_fork_works=yes
+ac_cv_func_getcwd=yes
+ac_cv_func_malloc_0_nonnull=yes
+ac_cv_func_memset=yes
+ac_cv_func_realloc_0_nonnull=yes
+ac_cv_func_setenv=yes
+ac_cv_func_strdup=yes
+ac_cv_func_strstr=yes
+ac_cv_func_vfork=yes
+ac_cv_func_vfork_works=yes
+ac_cv_header_CGAL_Delaunay_triangulation_2_h=no
+ac_cv_header_Python_h=yes
+ac_cv_header_fcgi_stdio_h=yes
+ac_cv_header_fcntl_h=yes
+ac_cv_header_geos_c_h=yes
+ac_cv_header_inttypes_h=yes
+ac_cv_header_jni_h=yes
+ac_cv_header_jsapi_h=yes
+ac_cv_header_libintl_h=yes
+ac_cv_header_libxml_parser_h=yes
+ac_cv_header_libxml_tree_h=yes
+ac_cv_header_libxml_xpathInternals_h=yes
+ac_cv_header_libxml_xpath_h=yes
+ac_cv_header_libxslt_transform_h=yes
+ac_cv_header_libxslt_xsltInternals_h=yes
+ac_cv_header_libxslt_xslt_h=yes
+ac_cv_header_libxslt_xsltutils_h=yes
+ac_cv_header_malloc_h=no
+ac_cv_header_memory_h=yes
+ac_cv_header_module_library_h=yes
+ac_cv_header_otbWrapperApplicationRegistry_h=yes
+ac_cv_header_otbWrapperApplication_h=yes
+ac_cv_header_otbWrapperInputImageListParameter_h=yes
+ac_cv_header_proj_api_h=yes
+ac_cv_header_stdbool_h=yes
+ac_cv_header_stdc=yes
+ac_cv_header_stddef_h=yes
+ac_cv_header_stdint_h=yes
+ac_cv_header_stdlib_h=yes
+ac_cv_header_string_h=yes
+ac_cv_header_strings_h=yes
+ac_cv_header_sys_stat_h=yes
+ac_cv_header_sys_types_h=yes
+ac_cv_header_unistd_h=yes
+ac_cv_header_vfork_h=no
+ac_cv_header_yaml_h=yes
+ac_cv_lib_crypto_EVP_DigestInit_EVP_md5_EVP_DigestUpdate_BIO_f_base64_BIO_new=yes
+ac_cv_lib_curl_curl_easy_init_curl_easy_setopt_curl_easy_cleanup_curl_easy_perform=yes
+ac_cv_lib_dl_dlopen_dlsym_dlerror_dlclose=yes
+ac_cv_lib_fcgi_main=yes
+ac_cv_lib_lex=-ll
+ac_cv_lib_mozjs185___JS_CompileFile_JS_CallFunctionName=yes
+ac_cv_lib_python2_7___PyObject_CallObject=yes
+ac_cv_lib_uuid_uuid_generate_time=yes
+ac_cv_lib_xml2_xmlInitParser=yes
+ac_cv_lib_yaml_yaml_parser_initialize_yaml_parser_set_input_file_yaml_parser_scan=yes
+ac_cv_objext=o
+ac_cv_path_EGREP='/usr/bin/grep -E'
+ac_cv_path_GREP=/usr/bin/grep
+ac_cv_path_PYTHONCONFIG=/usr/bin/python2.7-config
+ac_cv_path_SED=/usr/bin/sed
+ac_cv_path_XML2CONFIG=/usr/local/bin/xml2-config
+ac_cv_path_XSLTCONFIG=/usr/local/bin/xslt-config
+ac_cv_prog_CPP='gcc -E'
+ac_cv_prog_CXXCPP='g++ -E'
+ac_cv_prog_LEX=flex
+ac_cv_prog_YACC='bison -y'
+ac_cv_prog_ac_ct_CC=gcc
+ac_cv_prog_ac_ct_CXX=g++
+ac_cv_prog_cc_c89=
+ac_cv_prog_cc_g=yes
+ac_cv_prog_cxx_g=yes
+ac_cv_prog_lex_root=lex.yy
+ac_cv_prog_lex_yytext_pointer=yes
+ac_cv_type__Bool=yes
+ac_cv_type_pid_t=yes
+ac_cv_type_size_t=yes
+ac_cv_working_alloca_h=yes
+
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+
+ALLOCA=''
+CC='gcc'
+CFLAGS='-g -O2'
+CGAL_CPPFLAGS='-I/usr/include'
+CGAL_LDFLAGS='-L/usr/lib'
+CGI_DIR='/usr/lib/cgi-bin'
+CPP='gcc -E'
+CPPFLAGS=' -fPIC -I/usr/local//include/saga/saga_core/saga_api/ -I/usr/local/lib/wx/include/osx_cocoa-unicode-3.0 -I/usr/local/include/wx-3.0 -D_FILE_OFFSET_BITS=64 -DWXUSINGDLL -D__WXMAC__ -D__WXOSX__ -D__WXOSX_COCOA__  -D_SAGA_UNICODE -D_SAGA_LINUX -D_TYPEDEF_BYTE -D_TYPEDEF_WORD -DMODULE_LIBRARY_PATH=\"/usr/local//lib/saga\" -D_WX_WXCRTVARARG_H_'
+CXX='g++'
+CXXCPP='g++ -E'
+CXXFLAGS='-g -O2'
+DEB_DEF=''
+DEFAULT_LIBS='-luuid -lcrypto -ldl -lcurl '
+DEFS='-DPACKAGE_NAME=\"ZOO\ Kernel\" -DPACKAGE_TARNAME=\"zoo-kernel\" -DPACKAGE_VERSION=\"1.5.0\" -DPACKAGE_STRING=\"ZOO\ Kernel\ 1.5.0\" -DPACKAGE_BUGREPORT=\"bugs at zoo-project.org\" -DPACKAGE_URL=\"\" -DYYTEXT_POINTER=1 -DHAVE_LIBCURL=1 -DHAVE_LIBDL=1 -DHAVE_LIBCRYPTO=1 -DHAVE_LIBUUID=1 -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_ALLOCA_H= [...]
+ECHO_C='\c'
+ECHO_N=''
+ECHO_T=''
+EGREP='/usr/bin/grep -E'
+EXEEXT=''
+FCGI_CPPFLAGS='-I/usr/local//include'
+FCGI_LDFLAGS='-L/usr/local//lib'
+GDAL_CFLAGS='-I/Library/Frameworks/GDAL.framework/Versions/1.11/Headers'
+GDAL_CONFIG='/Library/Frameworks/GDAL.framework/unix/bin/gdal-config'
+GDAL_LIBS='-L/Library/Frameworks/GDAL.framework/Versions/1.11/unix/lib -lgdal'
+GEOSCONFIG='/Library/Frameworks/GEOS.framework/unix/bin/geos-config'
+GEOS_CPPFLAGS='-I/Library/Frameworks/GEOS.framework/Versions/3/unix/include'
+GEOS_LDFLAGS='-L/Library/Frameworks/GEOS.framework/Versions/3/unix/lib -lgeos'
+GREP='/usr/bin/grep'
+JAVA_CPPFLAGS='-I/Applications/Xcode.app/Contents/Developer//Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/System/Library/Frameworks/JavaVM.framework/Versions/A/Headers/'
+JAVA_ENABLED='-DUSE_JAVA'
+JAVA_FILE='service_internal_java.o'
+JAVA_LDFLAGS='-framework JavaVM'
+JS_CPPFLAGS='-I/usr/local//include/js/'
+JS_ENABLED='-DUSE_JS'
+JS_FILE='service_internal_js.o'
+JS_LDFLAGS='-L/usr/local//lib -lmozjs185 -lm'
+LDFLAGS=''
+LEX='flex'
+LEXLIB='-ll'
+LEX_OUTPUT_ROOT='lex.yy'
+LIBOBJS=''
+LIBS='-luuid -lcrypto -ldl -lcurl  -L/usr/local//lib/otb -lOTBIO -lOTBCommon -lOTBApplicationEngine -L/lib -lITKBiasCorrection-4.5 -lITKCommon-4.5 -lITKIOImageBase-4.5 -lITKKLMRegionGrowing-4.5 -lITKLabelMap-4.5 -lITKMesh-4.5 -lITKMetaIO-4.5 -lITKOptimizers-4.5 -lITKPath-4.5 -lITKPolynomials-4.5 -lITKQuadEdgeMesh-4.5 -lITKSpatialObjects-4.5 -lITKStatistics-4.5 -lITKVNLInstantiation-4.5 -lITKWatersheds-4.5 -litkNetlibSlatec-4.5 -litksys-4.5 -litkdouble-conversion-4.5 -litkv3p_lsqr-4.5 -li [...]
+LTLIBOBJS=''
+MS_CFLAGS='-DUSE_MS -I/Library/Frameworks/FreeType.framework/unix/include/freetype2 -I/Library/Frameworks/FreeType.framework/unix/include -Irenderers/agg/include -I/Library/Frameworks/PROJ.framework/unix//include -I/Library/Frameworks/GDAL.framework/Versions/Current/Headers -I/Library/Frameworks/GEOS.framework/Versions/3/unix/include -I/usr/include/libxml2 -I/Library/Frameworks/cairo.framework/unix/include/cairo/ -I/usr/include/apr-1 -I/usr/include/apache2 -arch i386 -arch x86_64 -Wall - [...]
+MS_FILE='service_internal_ms.o'
+MS_LIBS='-L/Users/djay/MapMint/src/mapserver-6.2.0/ -lmapserver -L/Library/Frameworks/FreeType.framework/unix/lib -lfreetype -lz -lbz2 -Wl,-framework,CoreServices -Wl,-framework,ApplicationServices -L/Library/Frameworks/PROJ.framework/unix//lib -lproj -ljpeg -lpng -L/Library/Frameworks/GDAL.framework/Versions/Current/unix/lib -lgdal -lcurl -L/Library/Frameworks/GEOS.framework/Versions/3/unix/lib -lgeos_c -liconv -lxml2 -lm -ldl -lstdc++ -L/Library/Frameworks/cairo.framework/unix/lib/ -lc [...]
+OBJEXT='o'
+OTB_CPPFLAGS='-I/usr/local//include/otb/ApplicationEngine -I/usr/local//include/otb/Common -I/include/ITK-4.5 -I/usr/local//include/otb/Utilities/ITK -I/usr/local//include/otb/ -I/usr/local//include/otb/IO -I/usr/local//include/otb/UtilitiesAdapters/OssimAdapters -I/usr/local//include/otb/UtilitiesAdapters/CurlAdapters -I/usr/local//include/otb/Utilities/BGL -I/usr/local//include/otb/UtilitiesAdapters/ITKPendingPatches -I/usr/local//include/otb/Utilities/otbconfigfile -I/Library/Framewor [...]
+OTB_ENABLED='-DUSE_OTB'
+OTB_FILE='otbZooWatcher.o service_internal_otb.o'
+OTB_LDFLAGS='-L/usr/local//lib/otb -lOTBIO -lOTBCommon -lOTBApplicationEngine -L/lib -lITKBiasCorrection-4.5 -lITKCommon-4.5 -lITKIOImageBase-4.5 -lITKKLMRegionGrowing-4.5 -lITKLabelMap-4.5 -lITKMesh-4.5 -lITKMetaIO-4.5 -lITKOptimizers-4.5 -lITKPath-4.5 -lITKPolynomials-4.5 -lITKQuadEdgeMesh-4.5 -lITKSpatialObjects-4.5 -lITKStatistics-4.5 -lITKVNLInstantiation-4.5 -lITKWatersheds-4.5 -litkNetlibSlatec-4.5 -litksys-4.5 -litkdouble-conversion-4.5 -litkv3p_lsqr-4.5 -litkv3p_netlib-4.5 -litk [...]
+PACKAGE_BUGREPORT='bugs at zoo-project.org'
+PACKAGE_NAME='ZOO Kernel'
+PACKAGE_STRING='ZOO Kernel 1.5.0'
+PACKAGE_TARNAME='zoo-kernel'
+PACKAGE_URL=''
+PACKAGE_VERSION='1.5.0'
+PATH_SEPARATOR=':'
+PERLCONFIG=''
+PERL_CPPFLAGS=''
+PERL_ENABLED=''
+PERL_FILE=''
+PERL_LDFLAGS=''
+PHPCONFIG=''
+PHP_CPPFLAGS=''
+PHP_ENABLED=''
+PHP_FILE=''
+PHP_LDFLAGS=''
+PROJ_CPPFLAGS='-I/Library/Frameworks/PROJ.framework/unix/include'
+PROJ_LDFLAGS='-L/Library/Frameworks/PROJ.framework/unix/lib'
+PYTHONCONFIG='/usr/bin/python2.7-config'
+PYTHON_CPPFLAGS='-I/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 -I/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7'
+PYTHON_ENABLED='-DUSE_PYTHON'
+PYTHON_FILE='service_internal_python.o'
+PYTHON_LDFLAGS='-L/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/config -ldl -framework CoreFoundation -lpython2.7'
+RELY_ON_DB='-DRELY_ON_DB'
+RUBY_CPPFLAGS=''
+RUBY_ENABLED=''
+RUBY_FILE=''
+RUBY_LDFLAGS=''
+SAGA_CPPFLAGS=' -fPIC -I/usr/local//include/saga/saga_core/saga_api/ -I/usr/local/lib/wx/include/osx_cocoa-unicode-3.0 -I/usr/local/include/wx-3.0 -D_FILE_OFFSET_BITS=64 -DWXUSINGDLL -D__WXMAC__ -D__WXOSX__ -D__WXOSX_COCOA__  -D_SAGA_UNICODE -D_SAGA_LINUX -D_TYPEDEF_BYTE -D_TYPEDEF_WORD -DMODULE_LIBRARY_PATH=\"/usr/local//lib/saga\" -D_WX_WXCRTVARARG_H_'
+SAGA_ENABLED='-DUSE_SAGA'
+SAGA_FILE='service_internal_saga.o'
+SAGA_LDFLAGS='-fPIC -L/usr/local/lib   -framework IOKit -framework Carbon -framework Cocoa -framework AudioToolbox -framework System -framework OpenGL -lwx_osx_cocoau-3.0  -lsaga_api'
+SED='/usr/bin/sed'
+SHELL='/bin/sh'
+XML2CONFIG='/usr/local/bin/xml2-config'
+XML2_CPPFLAGS='-I/usr/local/include/libxml2'
+XML2_LDFLAGS='-L/usr/local/lib -lxml2 -lz -liconv -lm'
+XSLTCONFIG='/usr/local/bin/xslt-config'
+XSLT_CPPFLAGS='-I/usr/local/include -I/usr/local/include/libxml2'
+XSLT_LDFLAGS='-L/usr/local/lib -lxslt -lxml2 -lz -liconv -lm'
+YACC='bison -y'
+YAML_CPPFLAGS='-I/usr/local//include -DYAML'
+YAML_FILE1='zcfg2yaml'
+YAML_FILE='service_yaml.o'
+YAML_LDFLAGS='-L/usr/local//lib -lyaml'
+YFLAGS=''
+ac_ct_CC='gcc'
+ac_ct_CXX='g++'
+bindir='${exec_prefix}/bin'
+build_alias=''
+datadir='${datarootdir}'
+datarootdir='${prefix}/share'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+dvidir='${docdir}'
+exec_prefix='${prefix}'
+host_alias=''
+htmldir='${docdir}'
+includedir='${prefix}/include'
+infodir='${datarootdir}/info'
+libdir='${exec_prefix}/lib'
+libexecdir='${exec_prefix}/libexec'
+localedir='${datarootdir}/locale'
+localstatedir='${prefix}/var'
+mandir='${datarootdir}/man'
+oldincludedir='/usr/include'
+pdfdir='${docdir}'
+prefix='/usr/local'
+program_transform_name='s,x,x,'
+psdir='${docdir}'
+sbindir='${exec_prefix}/sbin'
+sharedstatedir='${prefix}/com'
+sysconfdir='${prefix}/etc'
+target_alias=''
+
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+
+/* confdefs.h */
+#define PACKAGE_NAME "ZOO Kernel"
+#define PACKAGE_TARNAME "zoo-kernel"
+#define PACKAGE_VERSION "1.5.0"
+#define PACKAGE_STRING "ZOO Kernel 1.5.0"
+#define PACKAGE_BUGREPORT "bugs at zoo-project.org"
+#define PACKAGE_URL ""
+#define YYTEXT_POINTER 1
+#define HAVE_LIBCURL 1
+#define HAVE_LIBDL 1
+#define HAVE_LIBCRYPTO 1
+#define HAVE_LIBUUID 1
+#define STDC_HEADERS 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_SYS_STAT_H 1
+#define HAVE_STDLIB_H 1
+#define HAVE_STRING_H 1
+#define HAVE_MEMORY_H 1
+#define HAVE_STRINGS_H 1
+#define HAVE_INTTYPES_H 1
+#define HAVE_STDINT_H 1
+#define HAVE_UNISTD_H 1
+#define HAVE_ALLOCA_H 1
+#define HAVE_ALLOCA 1
+#define HAVE_FCNTL_H 1
+#define HAVE_INTTYPES_H 1
+#define HAVE_LIBINTL_H 1
+#define HAVE_STDDEF_H 1
+#define HAVE_STDLIB_H 1
+#define HAVE_STRING_H 1
+#define HAVE_UNISTD_H 1
+#define HAVE__BOOL 1
+#define HAVE_STDBOOL_H 1
+#define HAVE_FORK 1
+#define HAVE_VFORK 1
+#define HAVE_WORKING_VFORK 1
+#define HAVE_WORKING_FORK 1
+#define HAVE_STDLIB_H 1
+#define HAVE_MALLOC 1
+#define HAVE_STDLIB_H 1
+#define HAVE_REALLOC 1
+#define HAVE_DUP2 1
+#define HAVE_GETCWD 1
+#define HAVE_MEMSET 1
+#define HAVE_SETENV 1
+#define HAVE_STRDUP 1
+#define HAVE_STRSTR 1
+#define HAVE_LIBYAML 1
+#define HAVE_YAML_H 1
+#define HAVE_LIBFCGI 1
+#define HAVE_FCGI_STDIO_H 1
+#define HAVE_LIBXML_TREE_H 1
+#define HAVE_LIBXML_PARSER_H 1
+#define HAVE_LIBXML_XPATH_H 1
+#define HAVE_LIBXML_XPATHINTERNALS_H 1
+#define HAVE_LIBXML2 1
+#define HAVE_LIBXSLT_XSLT_H 1
+#define HAVE_LIBXSLT_XSLTINTERNALS_H 1
+#define HAVE_LIBXSLT_TRANSFORM_H 1
+#define HAVE_LIBXSLT_XSLTUTILS_H 1
+#define HAVE_PROJ_API_H 1
+#define HAVE_GEOS_C_H 1
+#define HAVE_PYTHON_H 1
+#define HAVE_LIBPYTHON2_7 1
+#define HAVE_JSAPI_H 1
+#define HAVE_LIBMOZJS185 1
+#define HAVE_JNI_H 1
+#define HAVE_OTBWRAPPERAPPLICATION_H 1
+#define HAVE_OTBWRAPPERINPUTIMAGELISTPARAMETER_H 1
+#define HAVE_OTBWRAPPERAPPLICATIONREGISTRY_H 1
+#define HAVE_MODULE_LIBRARY_H 1
+
+configure: exit 0
diff --git a/zoo-project/zoo-kernel/config.status b/zoo-project/zoo-kernel/config.status
new file mode 100755
index 0000000..4147fc0
--- /dev/null
+++ b/zoo-project/zoo-kernel/config.status
@@ -0,0 +1,1002 @@
+#! /bin/sh
+# Generated by configure.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by ZOO Kernel $as_me 1.5.0, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+# Files that config.status was made for.
+config_files=" Makefile ZOOMakefile.opts"
+
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration.  Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+      --config     print configuration, then exit
+  -q, --quiet, --silent
+                   do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+      --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+
+Configuration files:
+$config_files
+
+Report bugs to <bugs at zoo-project.org>."
+
+ac_cs_config="'--with-python=yes' '--with-pyvers=2.7' '--with-js=/usr/local/' '--with-mapserver=/Users/djay/MapMint/src/mapserver-6.2.0/' '--with-gdal-config=/Library/Frameworks/GDAL.framework/unix/bin/gdal-config' '--with-proj=/Library/Frameworks/PROJ.framework/unix' '--with-fastcgi=/usr/local/' '--with-yaml=/usr/local/' '--with-java=macos' '--with-geosconfig=/Library/Frameworks/GEOS.framework/unix/bin/geos-config' '--with-otb=/usr/local/' '--with-saga=/usr/local/' '--with-db-backend'"
+ac_cs_version="\
+ZOO Kernel config.status 1.5.0
+configured by ./configure, generated by GNU Autoconf 2.69,
+  with options \"$ac_cs_config\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='/Users/djay/MapMint/zoo-project-1.5.0/trunk/zoo-project/zoo-kernel'
+srcdir='.'
+test -n "$AWK" || AWK=awk
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=?*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  --*=)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    $as_echo "$ac_cs_version"; exit ;;
+  --config | --confi | --conf | --con | --co | --c )
+    $as_echo "$ac_cs_config"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    '') as_fn_error $? "missing file argument" ;;
+    esac
+    as_fn_append CONFIG_FILES " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --he | --h |  --help | --hel | -h )
+    $as_echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+  *) as_fn_append ac_config_targets " $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+if $ac_cs_recheck; then
+  set X /bin/sh './configure'  '--with-python=yes' '--with-pyvers=2.7' '--with-js=/usr/local/' '--with-mapserver=/Users/djay/MapMint/src/mapserver-6.2.0/' '--with-gdal-config=/Library/Frameworks/GDAL.framework/unix/bin/gdal-config' '--with-proj=/Library/Frameworks/PROJ.framework/unix' '--with-fastcgi=/usr/local/' '--with-yaml=/usr/local/' '--with-java=macos' '--with-geosconfig=/Library/Frameworks/GEOS.framework/unix/bin/geos-config' '--with-otb=/usr/local/' '--with-saga=/usr/local/' '--w [...]
+  shift
+  $as_echo "running CONFIG_SHELL=/bin/sh $*" >&6
+  CONFIG_SHELL='/bin/sh'
+  export CONFIG_SHELL
+  exec "$@"
+fi
+
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  $as_echo "$ac_log"
+} >&5
+
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+    "ZOOMakefile.opts") CONFIG_FILES="$CONFIG_FILES ZOOMakefile.opts" ;;
+
+  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp= ac_tmp=
+  trap 'exit_status=$?
+  : "${ac_tmp:=$tmp}"
+  { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+  trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+  eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+  ac_cs_awk_cr='\\r'
+else
+  ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+cat >>"$ac_tmp/subs1.awk" <<\_ACAWK &&
+S["LTLIBOBJS"]=""
+S["SAGA_ENABLED"]="-DUSE_SAGA"
+S["SAGA_FILE"]="service_internal_saga.o"
+S["SAGA_LDFLAGS"]="-fPIC -L/usr/local/lib   -framework IOKit -framework Carbon -framework Cocoa -framework AudioToolbox -framework System -framework OpenGL -lwx_osx_co"\
+"coau-3.0  -lsaga_api"
+S["SAGA_CPPFLAGS"]=" -fPIC -I/usr/local//include/saga/saga_core/saga_api/ -I/usr/local/lib/wx/include/osx_cocoa-unicode-3.0 -I/usr/local/include/wx-3.0 -D_FILE_OFFSET_B"\
+"ITS=64 -DWXUSINGDLL -D__WXMAC__ -D__WXOSX__ -D__WXOSX_COCOA__  -D_SAGA_UNICODE -D_SAGA_LINUX -D_TYPEDEF_BYTE -D_TYPEDEF_WORD -DMODULE_LIBRARY_PATH=\\"\
+"\"/usr/local//lib/saga\\\" -D_WX_WXCRTVARARG_H_"
+S["OTB_ENABLED"]="-DUSE_OTB"
+S["OTB_FILE"]="otbZooWatcher.o service_internal_otb.o"
+S["OTB_LDFLAGS"]="-L/usr/local//lib/otb -lOTBIO -lOTBCommon -lOTBApplicationEngine -L/lib -lITKBiasCorrection-4.5 -lITKCommon-4.5 -lITKIOImageBase-4.5 -lITKKLMRegionG"\
+"rowing-4.5 -lITKLabelMap-4.5 -lITKMesh-4.5 -lITKMetaIO-4.5 -lITKOptimizers-4.5 -lITKPath-4.5 -lITKPolynomials-4.5 -lITKQuadEdgeMesh-4.5 -lITKSpatial"\
+"Objects-4.5 -lITKStatistics-4.5 -lITKVNLInstantiation-4.5 -lITKWatersheds-4.5 -litkNetlibSlatec-4.5 -litksys-4.5 -litkdouble-conversion-4.5 -litkv3p"\
+"_lsqr-4.5 -litkv3p_netlib-4.5 -litkvcl-4.5 -litkvnl-4.5 -litkvnl_algo-4.5 -litkzlib-4.5"
+S["OTB_CPPFLAGS"]="-I/usr/local//include/otb/ApplicationEngine -I/usr/local//include/otb/Common -I/include/ITK-4.5 -I/usr/local//include/otb/Utilities/ITK -I/usr/local"\
+"//include/otb/ -I/usr/local//include/otb/IO -I/usr/local//include/otb/UtilitiesAdapters/OssimAdapters -I/usr/local//include/otb/UtilitiesAdapters/Cu"\
+"rlAdapters -I/usr/local//include/otb/Utilities/BGL -I/usr/local//include/otb/UtilitiesAdapters/ITKPendingPatches -I/usr/local//include/otb/Utilities"\
+"/otbconfigfile -I/Library/Frameworks/GDAL.framework/Versions/1.11/Headers"
+S["PERL_FILE"]=""
+S["PERL_ENABLED"]=""
+S["PERL_LDFLAGS"]=""
+S["PERL_CPPFLAGS"]=""
+S["PERLCONFIG"]=""
+S["RUBY_FILE"]=""
+S["RUBY_ENABLED"]=""
+S["RUBY_LDFLAGS"]=""
+S["RUBY_CPPFLAGS"]=""
+S["JAVA_FILE"]="service_internal_java.o"
+S["JAVA_ENABLED"]="-DUSE_JAVA"
+S["JAVA_LDFLAGS"]="-framework JavaVM"
+S["JAVA_CPPFLAGS"]="-I/Applications/Xcode.app/Contents/Developer//Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/System/Library/Frameworks/JavaVM.framework/Ver"\
+"sions/A/Headers/"
+S["PHP_FILE"]=""
+S["PHP_ENABLED"]=""
+S["PHP_LDFLAGS"]=""
+S["PHP_CPPFLAGS"]=""
+S["PHPCONFIG"]=""
+S["JS_FILE"]="service_internal_js.o"
+S["JS_ENABLED"]="-DUSE_JS"
+S["JS_LDFLAGS"]="-L/usr/local//lib -lmozjs185 -lm"
+S["JS_CPPFLAGS"]="-I/usr/local//include/js/"
+S["CXXCPP"]="g++ -E"
+S["PYTHON_FILE"]="service_internal_python.o"
+S["PYTHON_ENABLED"]="-DUSE_PYTHON"
+S["PYTHON_LDFLAGS"]="-L/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/config -ldl -framework CoreFoundation -lpython2.7"
+S["PYTHON_CPPFLAGS"]="-I/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 -I/System/Library/Frameworks/Python.framework/Versions/2.7/include/pyth"\
+"on2.7"
+S["PYTHONCONFIG"]="/usr/bin/python2.7-config"
+S["MS_FILE"]="service_internal_ms.o"
+S["MS_LIBS"]="-L/Users/djay/MapMint/src/mapserver-6.2.0/ -lmapserver -L/Library/Frameworks/FreeType.framework/unix/lib -lfreetype -lz -lbz2 -Wl,-framework,CoreSer"\
+"vices -Wl,-framework,ApplicationServices -L/Library/Frameworks/PROJ.framework/unix//lib -lproj -ljpeg -lpng -L/Library/Frameworks/GDAL.framework/Ver"\
+"sions/Current/unix/lib -lgdal -lcurl -L/Library/Frameworks/GEOS.framework/Versions/3/unix/lib -lgeos_c -liconv -lxml2 -lm -ldl -lstdc++ -L/Library/F"\
+"rameworks/cairo.framework/unix/lib/ -lcairo -L/usr/lib -R/usr/lib -lapr-1"
+S["MS_CFLAGS"]="-DUSE_MS -I/Library/Frameworks/FreeType.framework/unix/include/freetype2 -I/Library/Frameworks/FreeType.framework/unix/include -Irenderers/agg/inclu"\
+"de -I/Library/Frameworks/PROJ.framework/unix//include -I/Library/Frameworks/GDAL.framework/Versions/Current/Headers -I/Library/Frameworks/GEOS.frame"\
+"work/Versions/3/unix/include -I/usr/include/libxml2 -I/Library/Frameworks/cairo.framework/unix/include/cairo/ -I/usr/include/apr-1 -I/usr/include/ap"\
+"ache2 -arch i386 -arch x86_64 -Wall -Wdeclaration-after-statement -DNDEBUG -DMOD_WMS_ENABLED -DUSE_CAIRO -DUSE_WMS_LYR -DUSE_WFS_LYR -DUSE_SOS_SVR -"\
+"DUSE_LIBXML2 -DUSE_CURL -DUSE_CURLOPT_PROXYAUTH -DUSE_KML -DUSE_WCS_SVR -DUSE_WFS_SVR -DUSE_WMS_SVR -DUSE_GDAL -DUSE_OGR -DUSE_GEOS -DHAVE_SYNC_FETC"\
+"H_AND_ADD -DUSE_PROJ -DUSE_ICONV -DUSE_JPEG -DUSE_PNG -DUSE_FREETYPE -DHAVE_VSNPRINTF -DNEED_STRRSTR -DDISABLE_CVSID -I/Library/Frameworks/FreeType."\
+"framework/unix/include/freetype2 -I/Library/Frameworks/FreeType.framework/unix/include -Irenderers/agg/include -I/Library/Frameworks/PROJ.framework/"\
+"unix//include -I/Library/Frameworks/GDAL.framework/Versions/Current/Headers -I/Library/Frameworks/GEOS.framework/Versions/3/unix/include -I/usr/incl"\
+"ude/libxml2 -I/Library/Frameworks/cairo.framework/unix/include/cairo/ -I/usr/include/apr-1 -I/usr/include/apache2 -I/Users/djay/MapMint/src/mapserve"\
+"r-6.2.0/ "
+S["CGAL_LDFLAGS"]="-L/usr/lib"
+S["CGAL_CPPFLAGS"]="-I/usr/include"
+S["GEOS_LDFLAGS"]="-L/Library/Frameworks/GEOS.framework/Versions/3/unix/lib -lgeos"
+S["GEOS_CPPFLAGS"]="-I/Library/Frameworks/GEOS.framework/Versions/3/unix/include"
+S["GEOSCONFIG"]="/Library/Frameworks/GEOS.framework/unix/bin/geos-config"
+S["PROJ_LDFLAGS"]="-L/Library/Frameworks/PROJ.framework/unix/lib"
+S["PROJ_CPPFLAGS"]="-I/Library/Frameworks/PROJ.framework/unix/include"
+S["GDAL_LIBS"]="-L/Library/Frameworks/GDAL.framework/Versions/1.11/unix/lib -lgdal"
+S["GDAL_CFLAGS"]="-I/Library/Frameworks/GDAL.framework/Versions/1.11/Headers"
+S["GDAL_CONFIG"]="/Library/Frameworks/GDAL.framework/unix/bin/gdal-config"
+S["XSLT_LDFLAGS"]="-L/usr/local/lib -lxslt -lxml2 -lz -liconv -lm"
+S["XSLT_CPPFLAGS"]="-I/usr/local/include -I/usr/local/include/libxml2"
+S["XSLTCONFIG"]="/usr/local/bin/xslt-config"
+S["XML2_LDFLAGS"]="-L/usr/local/lib -lxml2 -lz -liconv -lm"
+S["XML2_CPPFLAGS"]="-I/usr/local/include/libxml2"
+S["XML2CONFIG"]="/usr/local/bin/xml2-config"
+S["FCGI_LDFLAGS"]="-L/usr/local//lib"
+S["FCGI_CPPFLAGS"]="-I/usr/local//include"
+S["YAML_FILE1"]="zcfg2yaml"
+S["YAML_FILE"]="service_yaml.o"
+S["YAML_LDFLAGS"]="-L/usr/local//lib -lyaml"
+S["YAML_CPPFLAGS"]="-I/usr/local//include -DYAML"
+S["RELY_ON_DB"]="-DRELY_ON_DB"
+S["CGI_DIR"]="/usr/lib/cgi-bin"
+S["DEB_DEF"]=""
+S["LIBOBJS"]=""
+S["ALLOCA"]=""
+S["EGREP"]="/usr/bin/grep -E"
+S["GREP"]="/usr/bin/grep"
+S["CPP"]="gcc -E"
+S["DEFAULT_LIBS"]="-luuid -lcrypto -ldl -lcurl "
+S["SED"]="/usr/bin/sed"
+S["ac_ct_CXX"]="g++"
+S["CXXFLAGS"]="-g -O2"
+S["CXX"]="g++"
+S["LEXLIB"]="-ll"
+S["LEX_OUTPUT_ROOT"]="lex.yy"
+S["LEX"]="flex"
+S["OBJEXT"]="o"
+S["EXEEXT"]=""
+S["ac_ct_CC"]="gcc"
+S["CPPFLAGS"]=" -fPIC -I/usr/local//include/saga/saga_core/saga_api/ -I/usr/local/lib/wx/include/osx_cocoa-unicode-3.0 -I/usr/local/include/wx-3.0 -D_FILE_OFFSET_B"\
+"ITS=64 -DWXUSINGDLL -D__WXMAC__ -D__WXOSX__ -D__WXOSX_COCOA__  -D_SAGA_UNICODE -D_SAGA_LINUX -D_TYPEDEF_BYTE -D_TYPEDEF_WORD -DMODULE_LIBRARY_PATH=\\"\
+"\"/usr/local//lib/saga\\\" -D_WX_WXCRTVARARG_H_"
+S["LDFLAGS"]=""
+S["CFLAGS"]="-g -O2"
+S["CC"]="gcc"
+S["YFLAGS"]=""
+S["YACC"]="bison -y"
+S["target_alias"]=""
+S["host_alias"]=""
+S["build_alias"]=""
+S["LIBS"]="-luuid -lcrypto -ldl -lcurl  -L/usr/local//lib/otb -lOTBIO -lOTBCommon -lOTBApplicationEngine -L/lib -lITKBiasCorrection-4.5 -lITKCommon-4.5 -lITKIO"\
+"ImageBase-4.5 -lITKKLMRegionGrowing-4.5 -lITKLabelMap-4.5 -lITKMesh-4.5 -lITKMetaIO-4.5 -lITKOptimizers-4.5 -lITKPath-4.5 -lITKPolynomials-4.5 -lITK"\
+"QuadEdgeMesh-4.5 -lITKSpatialObjects-4.5 -lITKStatistics-4.5 -lITKVNLInstantiation-4.5 -lITKWatersheds-4.5 -litkNetlibSlatec-4.5 -litksys-4.5 -litkd"\
+"ouble-conversion-4.5 -litkv3p_lsqr-4.5 -litkv3p_netlib-4.5 -litkvcl-4.5 -litkvnl-4.5 -litkvnl_algo-4.5 -litkzlib-4.5"
+S["ECHO_T"]=""
+S["ECHO_N"]=""
+S["ECHO_C"]="\\c"
+S["DEFS"]="-DPACKAGE_NAME=\\\"ZOO\\ Kernel\\\" -DPACKAGE_TARNAME=\\\"zoo-kernel\\\" -DPACKAGE_VERSION=\\\"1.5.0\\\" -DPACKAGE_STRING=\\\"ZOO\\ Kernel\\ 1.5.0\\\" -DPACKAGE_BUGREP"\
+"ORT=\\\"bugs at zoo-project.org\\\" -DPACKAGE_URL=\\\"\\\" -DYYTEXT_POINTER=1 -DHAVE_LIBCURL=1 -DHAVE_LIBDL=1 -DHAVE_LIBCRYPTO=1 -DHAVE_LIBUUID=1 -DSTDC_HEADER"\
+"S=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STD"\
+"INT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_ALLOCA_H=1 -DHAVE_ALLOCA=1 -DHAVE_FCNTL_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_LIBINTL_H=1 -DHAVE_STDDEF_H=1 -DHAVE_STDLIB_"\
+"H=1 -DHAVE_STRING_H=1 -DHAVE_UNISTD_H=1 -DHAVE__BOOL=1 -DHAVE_STDBOOL_H=1 -DHAVE_FORK=1 -DHAVE_VFORK=1 -DHAVE_WORKING_VFORK=1 -DHAVE_WORKING_FORK=1 "\
+"-DHAVE_STDLIB_H=1 -DHAVE_MALLOC=1 -DHAVE_STDLIB_H=1 -DHAVE_REALLOC=1 -DHAVE_DUP2=1 -DHAVE_GETCWD=1 -DHAVE_MEMSET=1 -DHAVE_SETENV=1 -DHAVE_STRDUP=1 -"\
+"DHAVE_STRSTR=1 -DHAVE_LIBYAML=1 -DHAVE_YAML_H=1 -DHAVE_LIBFCGI=1 -DHAVE_FCGI_STDIO_H=1 -DHAVE_LIBXML_TREE_H=1 -DHAVE_LIBXML_PARSER_H=1 -DHAVE_LIBXML"\
+"_XPATH_H=1 -DHAVE_LIBXML_XPATHINTERNALS_H=1 -DHAVE_LIBXML2=1 -DHAVE_LIBXSLT_XSLT_H=1 -DHAVE_LIBXSLT_XSLTINTERNALS_H=1 -DHAVE_LIBXSLT_TRANSFORM_H=1 -"\
+"DHAVE_LIBXSLT_XSLTUTILS_H=1 -DHAVE_PROJ_API_H=1 -DHAVE_GEOS_C_H=1 -DHAVE_PYTHON_H=1 -DHAVE_LIBPYTHON2_7=1 -DHAVE_JSAPI_H=1 -DHAVE_LIBMOZJS185=1 -DHA"\
+"VE_JNI_H=1 -DHAVE_OTBWRAPPERAPPLICATION_H=1 -DHAVE_OTBWRAPPERINPUTIMAGELISTPARAMETER_H=1 -DHAVE_OTBWRAPPERAPPLICATIONREGISTRY_H=1 -DHAVE_MODULE_LIBR"\
+"ARY_H=1"
+S["mandir"]="${datarootdir}/man"
+S["localedir"]="${datarootdir}/locale"
+S["libdir"]="${exec_prefix}/lib"
+S["psdir"]="${docdir}"
+S["pdfdir"]="${docdir}"
+S["dvidir"]="${docdir}"
+S["htmldir"]="${docdir}"
+S["infodir"]="${datarootdir}/info"
+S["docdir"]="${datarootdir}/doc/${PACKAGE_TARNAME}"
+S["oldincludedir"]="/usr/include"
+S["includedir"]="${prefix}/include"
+S["localstatedir"]="${prefix}/var"
+S["sharedstatedir"]="${prefix}/com"
+S["sysconfdir"]="${prefix}/etc"
+S["datadir"]="${datarootdir}"
+S["datarootdir"]="${prefix}/share"
+S["libexecdir"]="${exec_prefix}/libexec"
+S["sbindir"]="${exec_prefix}/sbin"
+S["bindir"]="${exec_prefix}/bin"
+S["program_transform_name"]="s,x,x,"
+S["prefix"]="/usr/local"
+S["exec_prefix"]="${prefix}"
+S["PACKAGE_URL"]=""
+S["PACKAGE_BUGREPORT"]="bugs at zoo-project.org"
+S["PACKAGE_STRING"]="ZOO Kernel 1.5.0"
+S["PACKAGE_VERSION"]="1.5.0"
+S["PACKAGE_TARNAME"]="zoo-kernel"
+S["PACKAGE_NAME"]="ZOO Kernel"
+S["PATH_SEPARATOR"]=":"
+S["SHELL"]="/bin/sh"
+_ACAWK
+cat >>"$ac_tmp/subs1.awk" <<_ACAWK &&
+  for (key in S) S_is_set[key] = 1
+  FS = ""
+
+}
+{
+  line = $ 0
+  nfields = split(line, field, "@")
+  substed = 0
+  len = length(field[1])
+  for (i = 2; i < nfields; i++) {
+    key = field[i]
+    keylen = length(key)
+    if (S_is_set[key]) {
+      value = S[key]
+      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+      len += length(value) + length(field[++i])
+      substed = 1
+    } else
+      len += 1 + keylen
+  }
+
+  print line
+}
+
+_ACAWK
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+  cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+  || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+fi # test -n "$CONFIG_FILES"
+
+
+eval set X "  :F $CONFIG_FILES      "
+shift
+for ac_tag
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$ac_tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
+	 # because $ac_f cannot contain `:'.
+	 test -f "$ac_f" ||
+	   case $ac_f in
+	   [\\/$]*) false;;
+	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+	   esac ||
+	   as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+      esac
+      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+      as_fn_append ac_file_inputs " '$ac_f'"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input='Generated from '`
+	  $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+	`' by configure.'
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+    fi
+    # Neutralize special characters interpreted by sed in replacement strings.
+    case $configure_input in #(
+    *\&* | *\|* | *\\* )
+       ac_sed_conf_input=`$as_echo "$configure_input" |
+       sed 's/[\\\\&|]/\\\\&/g'`;; #(
+    *) ac_sed_conf_input=$configure_input;;
+    esac
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$ac_tmp/stdin" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  as_dir="$ac_dir"; as_fn_mkdir_p
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+  ac_datarootdir_hack='
+  s&@datadir@&${datarootdir}&g
+  s&@docdir@&${datarootdir}/doc/${PACKAGE_TARNAME}&g
+  s&@infodir@&${datarootdir}/info&g
+  s&@localedir@&${datarootdir}/locale&g
+  s&@mandir@&${datarootdir}/man&g
+  s&\${datarootdir}&${prefix}/share&g' ;;
+esac
+ac_sed_extra="/^[	 ]*VPATH[	 ]*=[	 ]*/{
+h
+s///
+s/^/:/
+s/[	 ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[	 ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[	 ]*$//
+}
+
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+  >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' \
+      "$ac_tmp/out"`; test -z "$ac_out"; } &&
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&2;}
+
+  rm -f "$ac_tmp/stdin"
+  case $ac_file in
+  -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+  *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+  esac \
+  || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+
+
+
+  esac
+
+done # for ac_tag
+
+
+as_fn_exit 0
diff --git a/zoo-project/zoo-kernel/configure b/zoo-project/zoo-kernel/configure
new file mode 100755
index 0000000..f208d33
--- /dev/null
+++ b/zoo-project/zoo-kernel/configure
@@ -0,0 +1,8345 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69 for ZOO Kernel 1.5.0.
+#
+# Report bugs to <bugs at zoo-project.org>.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+  # into an infinite loop, continuously re-executing ourselves.
+  if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+    _as_can_reexec=no; export _as_can_reexec;
+    # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+  fi
+  # We don't want this to propagate to other subprocesses.
+          { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+  as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+"
+  as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+  exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+  as_suggested="  as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+  as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+  eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+  test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+  if (eval "$as_required") 2>/dev/null; then :
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+  if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  as_found=:
+  case $as_dir in #(
+	 /*)
+	   for as_base in sh bash ksh sh5; do
+	     # Try only shells that exist, to save several forks.
+	     as_shell=$as_dir/$as_base
+	     if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+		    { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  CONFIG_SHELL=$as_shell as_have_required=yes
+		   if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+  break 2
+fi
+fi
+	   done;;
+       esac
+  as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+	      { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+  CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+      if test "x$CONFIG_SHELL" != x; then :
+  export CONFIG_SHELL
+             # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+  *v*x* | *x*v* ) as_opts=-vx ;;
+  *v* ) as_opts=-v ;;
+  *x* ) as_opts=-x ;;
+  * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+    if test x$as_have_required = xno; then :
+  $as_echo "$0: This script requires a shell more modern than all"
+  $as_echo "$0: the shells that I found on your system."
+  if test x${ZSH_VERSION+set} = xset ; then
+    $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+    $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+  else
+    $as_echo "$0: Please tell bug-autoconf at gnu.org and
+$0: bugs at zoo-project.org about your system, including any
+$0: error possibly output before this message. Then install
+$0: a modern shell, or manually run the script under such a
+$0: shell if you do have one."
+  fi
+  exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+  as_lineno_1=$LINENO as_lineno_1a=$LINENO
+  as_lineno_2=$LINENO as_lineno_2a=$LINENO
+  eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+  test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+  # already done that, so ensure we don't try to do so again and fall
+  # in an infinite loop.  This has already happened in practice.
+  _as_can_reexec=no; export _as_can_reexec
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='ZOO Kernel'
+PACKAGE_TARNAME='zoo-kernel'
+PACKAGE_VERSION='1.5.0'
+PACKAGE_STRING='ZOO Kernel 1.5.0'
+PACKAGE_BUGREPORT='bugs at zoo-project.org'
+PACKAGE_URL=''
+
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='LTLIBOBJS
+SAGA_ENABLED
+SAGA_FILE
+SAGA_LDFLAGS
+SAGA_CPPFLAGS
+OTB_ENABLED
+OTB_FILE
+OTB_LDFLAGS
+OTB_CPPFLAGS
+PERL_FILE
+PERL_ENABLED
+PERL_LDFLAGS
+PERL_CPPFLAGS
+PERLCONFIG
+RUBY_FILE
+RUBY_ENABLED
+RUBY_LDFLAGS
+RUBY_CPPFLAGS
+JAVA_FILE
+JAVA_ENABLED
+JAVA_LDFLAGS
+JAVA_CPPFLAGS
+PHP_FILE
+PHP_ENABLED
+PHP_LDFLAGS
+PHP_CPPFLAGS
+PHPCONFIG
+JS_FILE
+JS_ENABLED
+JS_LDFLAGS
+JS_CPPFLAGS
+CXXCPP
+PYTHON_FILE
+PYTHON_ENABLED
+PYTHON_LDFLAGS
+PYTHON_CPPFLAGS
+PYTHONCONFIG
+MS_FILE
+MS_LIBS
+MS_CFLAGS
+CGAL_LDFLAGS
+CGAL_CPPFLAGS
+GEOS_LDFLAGS
+GEOS_CPPFLAGS
+GEOSCONFIG
+PROJ_LDFLAGS
+PROJ_CPPFLAGS
+GDAL_LIBS
+GDAL_CFLAGS
+GDAL_CONFIG
+XSLT_LDFLAGS
+XSLT_CPPFLAGS
+XSLTCONFIG
+XML2_LDFLAGS
+XML2_CPPFLAGS
+XML2CONFIG
+FCGI_LDFLAGS
+FCGI_CPPFLAGS
+YAML_FILE1
+YAML_FILE
+YAML_LDFLAGS
+YAML_CPPFLAGS
+RELY_ON_DB
+CGI_DIR
+DEB_DEF
+LIBOBJS
+ALLOCA
+EGREP
+GREP
+CPP
+DEFAULT_LIBS
+SED
+ac_ct_CXX
+CXXFLAGS
+CXX
+LEXLIB
+LEX_OUTPUT_ROOT
+LEX
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+YFLAGS
+YACC
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+with_cgi_dir
+with_db_backend
+with_yaml
+with_fastcgi
+with_xml2config
+with_xsltconfig
+with_gdal_config
+with_proj
+with_geosconfig
+with_cgal
+with_mapserver
+with_python
+with_pyvers
+with_js
+with_php
+with_java
+with_ruby
+with_rvers
+with_perl
+with_itk
+with_itk_version
+with_otb
+with_wx_config
+with_saga
+'
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+YACC
+YFLAGS
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CXX
+CXXFLAGS
+CCC
+CPP
+CXXCPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *=)   ac_optarg= ;;
+  *)    ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid feature name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      as_fn_error $? "invalid package name: $ac_useropt"
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+	 ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    case $ac_envvar in #(
+      '' | [0-9]* | *[!_$as_cr_alnum]* )
+      as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+    esac
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+  case $enable_option_checking in
+    no) ;;
+    fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+  esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
+		datadir sysconfdir sharedstatedir localstatedir includedir \
+		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+		libdir localedir mandir
+do
+  eval ac_val=\$$ac_var
+  # Remove trailing slashes.
+  case $ac_val in
+    */ )
+      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+      eval $ac_var=\$ac_val;;
+  esac
+  # Be sure to have absolute directory names.
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_myself" : 'X\(//\)[^/]' \| \
+	 X"$as_myself" : 'X\(//\)$' \| \
+	 X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+	cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+	pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures ZOO Kernel 1.5.0 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking ...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR            user executables [EPREFIX/bin]
+  --sbindir=DIR           system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR        program executables [EPREFIX/libexec]
+  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --libdir=DIR            object code libraries [EPREFIX/lib]
+  --includedir=DIR        C header files [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
+  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR           info documentation [DATAROOTDIR/info]
+  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR            man documentation [DATAROOTDIR/man]
+  --docdir=DIR            documentation root [DATAROOTDIR/doc/zoo-kernel]
+  --htmldir=DIR           html documentation [DOCDIR]
+  --dvidir=DIR            dvi documentation [DOCDIR]
+  --pdfdir=DIR            pdf documentation [DOCDIR]
+  --psdir=DIR             ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of ZOO Kernel 1.5.0:";;
+   esac
+  cat <<\_ACEOF
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-cgi-dir=PATH     Specifies an alternative cgi directory path (
+                          default: /usr/lib/cgi-bin)
+  --with-db-backend       Relies on a database for storing status messages and
+                          response files
+  --with-yaml=PATH        Specifies an alternative location for the yaml
+                          library
+  --with-fastcgi=PATH     Specifies an alternative location for the fastcgi
+                          library
+  --with-xml2config=FILE  Specifies an alternative xml2-config file
+  --with-xsltconfig=FILE  Specifies an alternative xslt-config file
+  --with-gdal-config=FILE Specifies an alternative gdal-config file
+  --with-proj=PATH        Specifies an alternative location for PROJ4 setup
+  --with-geosconfig=FILE  Specifies an alternative geos-config file
+  --with-cgal=PATH        Specifies an alternative location for CGAL setup
+  --with-mapserver=PATH   Specifies the path for MapServer compiled source
+                          tree
+  --with-python=PATH      To enable python support or Specifies an alternative
+                          directory for python installation, disabled by
+                          default
+  --with-pyvers=NUM       To use a specific python version
+  --with-js=PATH          Specifies --with-js=path-to-js to enable js support,
+                          specify --with-js on linux debian like, js support
+                          is disabled by default
+  --with-php=PATH         To enable php support or specify an alternative
+                          directory for php installation, disabled by default
+  --with-java=PATH        To enable java support, specify a JDK_HOME, disabled
+                          by default
+  --with-ruby=PATH        To enable ruby support or specify an alternative
+                          directory for ruby installation, disabled by default
+  --with-rvers=NUM        To use a specific ruby version
+  --with-perl=PATH        To enable perl support or specify an alternative
+                          directory for perl installation, disabled by default
+  --with-itk=PATH         Specifies an alternative location for the itk
+                          library
+  --with-itk-version=VERSION
+                          Specifies an alternative version for the itk library
+  --with-otb=PATH         Specifies an alternative location for the otb
+                          library
+  --with-wx-config=PATH   Specifies an alternative path for the wx-config tool
+  --with-saga=PATH        Specifies an alternative location for the SAGA-GIS
+                          library
+
+Some influential environment variables:
+  YACC        The `Yet Another Compiler Compiler' implementation to use.
+              Defaults to the first program found out of: `bison -y', `byacc',
+              `yacc'.
+  YFLAGS      The list of arguments that will be passed by default to $YACC.
+              This script will default YFLAGS to the empty string to avoid a
+              default value of `-d' given by some make applications.
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  LIBS        libraries to pass to the linker, e.g. -l<library>
+  CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+              you have headers in a nonstandard directory <include dir>
+  CXX         C++ compiler command
+  CXXFLAGS    C++ compiler flags
+  CPP         C preprocessor
+  CXXCPP      C++ preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to <bugs at zoo-project.org>.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" ||
+      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+      continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+ZOO Kernel configure 1.5.0
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext conftest$ac_exeext
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 test -x conftest$ac_exeext
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+  # interfere with the next link command; also delete a directory that is
+  # left behind by Apple's compiler.  We do this before executing the actions.
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_cxx_try_compile LINENO
+# ----------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext
+  if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_compile
+
+# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
+# -------------------------------------------
+# Tests whether TYPE exists after having included INCLUDES, setting cache
+# variable VAR accordingly.
+ac_fn_c_check_type ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=no"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+if (sizeof ($2))
+	 return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+if (sizeof (($2)))
+	    return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  eval "$3=yes"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_type
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } > conftest.i && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+    ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: program exited with status $ac_status" >&5
+       $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_retval=$ac_status
+fi
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $2 (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  eval "$3=yes"
+else
+  eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_func
+
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if eval \${$3+:} false; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_header_compiler=yes
+else
+  ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  ac_header_preproc=yes
+else
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+  yes:no: )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+    ;;
+  no:yes:* )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+( $as_echo "## ----------------------------------- ##
+## Report this to bugs at zoo-project.org ##
+## ----------------------------------- ##"
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_mongrel
+
+# ac_fn_c_find_intX_t LINENO BITS VAR
+# -----------------------------------
+# Finds a signed integer type with width BITS, setting cache variable VAR
+# accordingly.
+ac_fn_c_find_intX_t ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for int$2_t" >&5
+$as_echo_n "checking for int$2_t... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=no"
+     # Order is important - never check a type that is potentially smaller
+     # than half of the expected target width.
+     for ac_type in int$2_t 'int' 'long int' \
+	 'long long int' 'short int' 'signed char'; do
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_includes_default
+	     enum { N = $2 / 2 - 1 };
+int
+main ()
+{
+static int test_array [1 - 2 * !(0 < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1))];
+test_array [0] = 0;
+return test_array [0];
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_includes_default
+	        enum { N = $2 / 2 - 1 };
+int
+main ()
+{
+static int test_array [1 - 2 * !(($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 1)
+		 < ($ac_type) ((((($ac_type) 1 << N) << N) - 1) * 2 + 2))];
+test_array [0] = 0;
+return test_array [0];
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  case $ac_type in #(
+  int$2_t) :
+    eval "$3=yes" ;; #(
+  *) :
+    eval "$3=\$ac_type" ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+       if eval test \"x\$"$3"\" = x"no"; then :
+
+else
+  break
+fi
+     done
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_find_intX_t
+
+# ac_fn_c_find_uintX_t LINENO BITS VAR
+# ------------------------------------
+# Finds an unsigned integer type with width BITS, setting cache variable VAR
+# accordingly.
+ac_fn_c_find_uintX_t ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uint$2_t" >&5
+$as_echo_n "checking for uint$2_t... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=no"
+     # Order is important - never check a type that is potentially smaller
+     # than half of the expected target width.
+     for ac_type in uint$2_t 'unsigned int' 'unsigned long int' \
+	 'unsigned long long int' 'unsigned short int' 'unsigned char'; do
+       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+static int test_array [1 - 2 * !((($ac_type) -1 >> ($2 / 2 - 1)) >> ($2 / 2 - 1) == 3)];
+test_array [0] = 0;
+return test_array [0];
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  case $ac_type in #(
+  uint$2_t) :
+    eval "$3=yes" ;; #(
+  *) :
+    eval "$3=\$ac_type" ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+       if eval test \"x\$"$3"\" = x"no"; then :
+
+else
+  break
+fi
+     done
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_find_uintX_t
+
+# ac_fn_cxx_try_cpp LINENO
+# ------------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_cpp ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } > conftest.i && {
+	 test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+    ac_retval=1
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_cpp
+
+# ac_fn_cxx_check_header_mongrel LINENO HEADER VAR INCLUDES
+# ---------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_cxx_check_header_mongrel ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  if eval \${$3+:} false; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_header_compiler=yes
+else
+  ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <$2>
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+  ac_header_preproc=yes
+else
+  ac_header_preproc=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in #((
+  yes:no: )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+    ;;
+  no:yes:* )
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+( $as_echo "## ----------------------------------- ##
+## Report this to bugs at zoo-project.org ##
+## ----------------------------------- ##"
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_cxx_check_header_mongrel
+
+# ac_fn_cxx_try_link LINENO
+# -------------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_cxx_try_link ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  rm -f conftest.$ac_objext conftest$ac_exeext
+  if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    grep -v '^ *+' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+    mv -f conftest.er1 conftest.err
+  fi
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; } && {
+	 test -z "$ac_cxx_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+	 test "$cross_compiling" = yes ||
+	 test -x conftest$ac_exeext
+       }; then :
+  ac_retval=0
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_retval=1
+fi
+  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+  # interfere with the next link command; also delete a directory that is
+  # left behind by Apple's compiler.  We do this before executing the actions.
+  rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+  as_fn_set_status $ac_retval
+
+} # ac_fn_cxx_try_link
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by ZOO Kernel $as_me 1.5.0, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    $as_echo "PATH: $as_dir"
+  done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+    2)
+      as_fn_append ac_configure_args1 " '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+	ac_must_keep_next=false # Got value, back to normal.
+      else
+	case $ac_arg in
+	  *=* | --config-cache | -C | -disable-* | --disable-* \
+	  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+	  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+	  | -with-* | --with-* | -without-* | --without-* | --x)
+	    case "$ac_configure_args0 " in
+	      "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+	    esac
+	    ;;
+	  -* ) ac_must_keep_next=true ;;
+	esac
+      fi
+      as_fn_append ac_configure_args " '$ac_arg'"
+      ;;
+    esac
+  done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+	"s/'\''/'\''\\\\'\'''\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      $as_echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+      echo
+      for ac_var in $ac_subst_files
+      do
+	eval ac_val=\$$ac_var
+	case $ac_val in
+	*\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+	esac
+	$as_echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      $as_echo "$as_me: caught signal $ac_signal"
+    $as_echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+  # We do not want a PATH search for config.site.
+  case $CONFIG_SITE in #((
+    -*)  ac_site_file1=./$CONFIG_SITE;;
+    */*) ac_site_file1=$CONFIG_SITE;;
+    *)   ac_site_file1=./$CONFIG_SITE;;
+  esac
+elif test "x$prefix" != xNONE; then
+  ac_site_file1=$prefix/share/config.site
+  ac_site_file2=$prefix/etc/config.site
+else
+  ac_site_file1=$ac_default_prefix/share/config.site
+  ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+  test "x$ac_site_file" = xNONE && continue
+  if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file" \
+      || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special files
+  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.
+  if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+	# differences in whitespace do not lead to failure.
+	ac_old_val_w=`echo x $ac_old_val`
+	ac_new_val_w=`echo x $ac_new_val`
+	if test "$ac_old_val_w" != "$ac_new_val_w"; then
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+	  ac_cache_corrupted=:
+	else
+	  { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+	  eval $ac_var=\$ac_old_val
+	fi
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   former value:  \`$ac_old_val'" >&5
+$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
+	{ $as_echo "$as_me:${as_lineno-$LINENO}:   current value: \`$ac_new_val'" >&5
+$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+  { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+# Checks for programs.
+for ac_prog in 'bison -y' byacc
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_YACC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$YACC"; then
+  ac_cv_prog_YACC="$YACC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_YACC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+YACC=$ac_cv_prog_YACC
+if test -n "$YACC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $YACC" >&5
+$as_echo "$YACC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$YACC" && break
+done
+test -n "$YACC" || YACC="yacc"
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+	;;
+    [ab].out )
+	# We found the default executable, but exeext='' is most
+	# certainly right.
+	break;;
+    *.* )
+	if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+	then :; else
+	   ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	fi
+	# We set ac_cv_exeext here because the later test for it is not
+	# safe: cross compilers may not add the suffix if given an `-o'
+	# argument, so we may need to know it at that point already.
+	# Even if this section looks crufty: it has the advantage of
+	# actually working.
+	break;;
+    * )
+	break;;
+  esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+  ac_file=''
+fi
+if test -z "$ac_file"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+	  break;;
+    * ) break;;
+  esac
+done
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+  { { ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+  if { ac_try='./conftest$ac_cv_exeext'
+  { { case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+	cross_compiling=yes
+    else
+	{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+    fi
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; then :
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+else
+  CFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  ac_c_werror_flag=$ac_save_c_werror_flag
+	 CFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+	-Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+  xno)
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+for ac_prog in flex lex
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_LEX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$LEX"; then
+  ac_cv_prog_LEX="$LEX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_LEX="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+LEX=$ac_cv_prog_LEX
+if test -n "$LEX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LEX" >&5
+$as_echo "$LEX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$LEX" && break
+done
+test -n "$LEX" || LEX=":"
+
+if test "x$LEX" != "x:"; then
+  cat >conftest.l <<_ACEOF
+%%
+a { ECHO; }
+b { REJECT; }
+c { yymore (); }
+d { yyless (1); }
+e { /* IRIX 6.5 flex 2.5.4 underquotes its yyless argument.  */
+    yyless ((input () != 0)); }
+f { unput (yytext[0]); }
+. { BEGIN INITIAL; }
+%%
+#ifdef YYTEXT_POINTER
+extern char *yytext;
+#endif
+int
+main (void)
+{
+  return ! yylex () + ! yywrap ();
+}
+_ACEOF
+{ { ac_try="$LEX conftest.l"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$LEX conftest.l") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking lex output file root" >&5
+$as_echo_n "checking lex output file root... " >&6; }
+if ${ac_cv_prog_lex_root+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+if test -f lex.yy.c; then
+  ac_cv_prog_lex_root=lex.yy
+elif test -f lexyy.c; then
+  ac_cv_prog_lex_root=lexyy
+else
+  as_fn_error $? "cannot find output from $LEX; giving up" "$LINENO" 5
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_root" >&5
+$as_echo "$ac_cv_prog_lex_root" >&6; }
+LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root
+
+if test -z "${LEXLIB+set}"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking lex library" >&5
+$as_echo_n "checking lex library... " >&6; }
+if ${ac_cv_lib_lex+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+
+    ac_save_LIBS=$LIBS
+    ac_cv_lib_lex='none needed'
+    for ac_lib in '' -lfl -ll; do
+      LIBS="$ac_lib $ac_save_LIBS"
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+`cat $LEX_OUTPUT_ROOT.c`
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_lex=$ac_lib
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+      test "$ac_cv_lib_lex" != 'none needed' && break
+    done
+    LIBS=$ac_save_LIBS
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lex" >&5
+$as_echo "$ac_cv_lib_lex" >&6; }
+  test "$ac_cv_lib_lex" != 'none needed' && LEXLIB=$ac_cv_lib_lex
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether yytext is a pointer" >&5
+$as_echo_n "checking whether yytext is a pointer... " >&6; }
+if ${ac_cv_prog_lex_yytext_pointer+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  # POSIX says lex can declare yytext either as a pointer or an array; the
+# default is implementation-dependent.  Figure out which it is, since
+# not all implementations provide the %pointer and %array declarations.
+ac_cv_prog_lex_yytext_pointer=no
+ac_save_LIBS=$LIBS
+LIBS="$LEXLIB $ac_save_LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+  #define YYTEXT_POINTER 1
+`cat $LEX_OUTPUT_ROOT.c`
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_prog_lex_yytext_pointer=yes
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_save_LIBS
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_yytext_pointer" >&5
+$as_echo "$ac_cv_prog_lex_yytext_pointer" >&6; }
+if test $ac_cv_prog_lex_yytext_pointer = yes; then
+
+$as_echo "#define YYTEXT_POINTER 1" >>confdefs.h
+
+fi
+rm -f conftest.l $LEX_OUTPUT_ROOT.c
+
+fi
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+  if test -n "$CCC"; then
+    CXX=$CCC
+  else
+    if test -n "$ac_tool_prefix"; then
+  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CXX"; then
+  ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5
+$as_echo "$CXX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CXX" && break
+  done
+fi
+if test -z "$CXX"; then
+  ac_ct_CXX=$CXX
+  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CXX+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CXX"; then
+  ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_prog_ac_ct_CXX="$ac_prog"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5
+$as_echo "$ac_ct_CXX" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CXX" && break
+done
+
+  if test "x$ac_ct_CXX" = x; then
+    CXX="g++"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CXX=$ac_ct_CXX
+  fi
+fi
+
+  fi
+fi
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+  { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+  (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+  ac_status=$?
+  if test -s conftest.err; then
+    sed '10a\
+... rest of stderr output deleted ...
+         10q' conftest.err >conftest.er1
+    cat conftest.er1 >&5
+  fi
+  rm -f conftest.er1 conftest.err
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5
+$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
+if ${ac_cv_cxx_compiler_gnu+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_compiler_gnu=yes
+else
+  ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5
+$as_echo "$ac_cv_cxx_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GXX=yes
+else
+  GXX=
+fi
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5
+$as_echo_n "checking whether $CXX accepts -g... " >&6; }
+if ${ac_cv_prog_cxx_g+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+   ac_cxx_werror_flag=yes
+   ac_cv_prog_cxx_g=no
+   CXXFLAGS="-g"
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_prog_cxx_g=yes
+else
+  CXXFLAGS=""
+      cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+
+else
+  ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+	 CXXFLAGS="-g"
+	 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+  ac_cv_prog_cxx_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5
+$as_echo "$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+  CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+  if test "$GXX" = yes; then
+    CXXFLAGS="-g -O2"
+  else
+    CXXFLAGS="-g"
+  fi
+else
+  if test "$GXX" = yes; then
+    CXXFLAGS="-O2"
+  else
+    CXXFLAGS=
+  fi
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
+$as_echo_n "checking for a sed that does not truncate output... " >&6; }
+if ${ac_cv_path_SED+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+            ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/
+     for ac_i in 1 2 3 4 5 6 7; do
+       ac_script="$ac_script$as_nl$ac_script"
+     done
+     echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed
+     { ac_script=; unset ac_script;}
+     if test -z "$SED"; then
+  ac_path_SED_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in sed gsed; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_SED="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_SED" || continue
+# Check for GNU ac_path_SED and select it if it is found.
+  # Check for GNU $ac_path_SED
+case `"$ac_path_SED" --version 2>&1` in
+*GNU*)
+  ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo '' >> "conftest.nl"
+    "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_SED_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_SED="$ac_path_SED"
+      ac_path_SED_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_SED_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_SED"; then
+    as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5
+  fi
+else
+  ac_cv_path_SED=$SED
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5
+$as_echo "$ac_cv_path_SED" >&6; }
+ SED="$ac_cv_path_SED"
+  rm -f conftest.sed
+
+
+# Checks for libraries.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for curl_easy_init,curl_easy_setopt,curl_easy_cleanup,curl_easy_perform in -lcurl" >&5
+$as_echo_n "checking for curl_easy_init,curl_easy_setopt,curl_easy_cleanup,curl_easy_perform in -lcurl... " >&6; }
+if ${ac_cv_lib_curl_curl_easy_init_curl_easy_setopt_curl_easy_cleanup_curl_easy_perform+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcurl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char curl_easy_init,curl_easy_setopt,curl_easy_cleanup,curl_easy_perform ();
+int
+main ()
+{
+return curl_easy_init,curl_easy_setopt,curl_easy_cleanup,curl_easy_perform ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_curl_curl_easy_init_curl_easy_setopt_curl_easy_cleanup_curl_easy_perform=yes
+else
+  ac_cv_lib_curl_curl_easy_init_curl_easy_setopt_curl_easy_cleanup_curl_easy_perform=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_curl_curl_easy_init_curl_easy_setopt_curl_easy_cleanup_curl_easy_perform" >&5
+$as_echo "$ac_cv_lib_curl_curl_easy_init_curl_easy_setopt_curl_easy_cleanup_curl_easy_perform" >&6; }
+if test "x$ac_cv_lib_curl_curl_easy_init_curl_easy_setopt_curl_easy_cleanup_curl_easy_perform" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBCURL 1
+_ACEOF
+
+  LIBS="-lcurl $LIBS"
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen,dlsym,dlerror,dlclose in -ldl" >&5
+$as_echo_n "checking for dlopen,dlsym,dlerror,dlclose in -ldl... " >&6; }
+if ${ac_cv_lib_dl_dlopen_dlsym_dlerror_dlclose+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldl  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlopen,dlsym,dlerror,dlclose ();
+int
+main ()
+{
+return dlopen,dlsym,dlerror,dlclose ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_dl_dlopen_dlsym_dlerror_dlclose=yes
+else
+  ac_cv_lib_dl_dlopen_dlsym_dlerror_dlclose=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen_dlsym_dlerror_dlclose" >&5
+$as_echo "$ac_cv_lib_dl_dlopen_dlsym_dlerror_dlclose" >&6; }
+if test "x$ac_cv_lib_dl_dlopen_dlsym_dlerror_dlclose" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBDL 1
+_ACEOF
+
+  LIBS="-ldl $LIBS"
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for EVP_DigestInit,EVP_md5,EVP_DigestUpdate,BIO_f_base64,BIO_new in -lcrypto" >&5
+$as_echo_n "checking for EVP_DigestInit,EVP_md5,EVP_DigestUpdate,BIO_f_base64,BIO_new in -lcrypto... " >&6; }
+if ${ac_cv_lib_crypto_EVP_DigestInit_EVP_md5_EVP_DigestUpdate_BIO_f_base64_BIO_new+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcrypto  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char EVP_DigestInit,EVP_md5,EVP_DigestUpdate,BIO_f_base64,BIO_new ();
+int
+main ()
+{
+return EVP_DigestInit,EVP_md5,EVP_DigestUpdate,BIO_f_base64,BIO_new ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_crypto_EVP_DigestInit_EVP_md5_EVP_DigestUpdate_BIO_f_base64_BIO_new=yes
+else
+  ac_cv_lib_crypto_EVP_DigestInit_EVP_md5_EVP_DigestUpdate_BIO_f_base64_BIO_new=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypto_EVP_DigestInit_EVP_md5_EVP_DigestUpdate_BIO_f_base64_BIO_new" >&5
+$as_echo "$ac_cv_lib_crypto_EVP_DigestInit_EVP_md5_EVP_DigestUpdate_BIO_f_base64_BIO_new" >&6; }
+if test "x$ac_cv_lib_crypto_EVP_DigestInit_EVP_md5_EVP_DigestUpdate_BIO_f_base64_BIO_new" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBCRYPTO 1
+_ACEOF
+
+  LIBS="-lcrypto $LIBS"
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_generate_time in -luuid" >&5
+$as_echo_n "checking for uuid_generate_time in -luuid... " >&6; }
+if ${ac_cv_lib_uuid_uuid_generate_time+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-luuid  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char uuid_generate_time ();
+int
+main ()
+{
+return uuid_generate_time ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_uuid_uuid_generate_time=yes
+else
+  ac_cv_lib_uuid_uuid_generate_time=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_uuid_uuid_generate_time" >&5
+$as_echo "$ac_cv_lib_uuid_uuid_generate_time" >&6; }
+if test "x$ac_cv_lib_uuid_uuid_generate_time" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBUUID 1
+_ACEOF
+
+  LIBS="-luuid $LIBS"
+
+fi
+
+
+DEFAULT_LIBS="$LIBS"
+
+
+
+# Checks for header files.
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if ${ac_cv_prog_CPP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$GREP"; then
+  ac_path_GREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in grep ggrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_GREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_GREP"; then
+    as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     if test -z "$EGREP"; then
+  ac_path_EGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_prog in egrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+      as_fn_executable_p "$ac_path_EGREP" || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    as_fn_arith $ac_count + 1 && ac_count=$as_val
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_EGREP_found && break 3
+    done
+  done
+  done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_EGREP"; then
+    as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+  fi
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_header_stdc=yes
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then :
+  :
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+		   (('a' <= (c) && (c) <= 'i') \
+		     || ('j' <= (c) && (c) <= 'r') \
+		     || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+	|| toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+  ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+		  inttypes.h stdint.h unistd.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default"
+if test "x$ac_cv_type_size_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define size_t unsigned int
+_ACEOF
+
+fi
+
+# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
+# for constant arguments.  Useless!
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working alloca.h" >&5
+$as_echo_n "checking for working alloca.h... " >&6; }
+if ${ac_cv_working_alloca_h+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <alloca.h>
+int
+main ()
+{
+char *p = (char *) alloca (2 * sizeof (int));
+			  if (p) return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_working_alloca_h=yes
+else
+  ac_cv_working_alloca_h=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_working_alloca_h" >&5
+$as_echo "$ac_cv_working_alloca_h" >&6; }
+if test $ac_cv_working_alloca_h = yes; then
+
+$as_echo "#define HAVE_ALLOCA_H 1" >>confdefs.h
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for alloca" >&5
+$as_echo_n "checking for alloca... " >&6; }
+if ${ac_cv_func_alloca_works+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __GNUC__
+# define alloca __builtin_alloca
+#else
+# ifdef _MSC_VER
+#  include <malloc.h>
+#  define alloca _alloca
+# else
+#  ifdef HAVE_ALLOCA_H
+#   include <alloca.h>
+#  else
+#   ifdef _AIX
+ #pragma alloca
+#   else
+#    ifndef alloca /* predefined by HP cc +Olibcalls */
+void *alloca (size_t);
+#    endif
+#   endif
+#  endif
+# endif
+#endif
+
+int
+main ()
+{
+char *p = (char *) alloca (1);
+				    if (p) return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_func_alloca_works=yes
+else
+  ac_cv_func_alloca_works=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_alloca_works" >&5
+$as_echo "$ac_cv_func_alloca_works" >&6; }
+
+if test $ac_cv_func_alloca_works = yes; then
+
+$as_echo "#define HAVE_ALLOCA 1" >>confdefs.h
+
+else
+  # The SVR3 libPW and SVR4 libucb both contain incompatible functions
+# that cause trouble.  Some versions do not even contain alloca or
+# contain a buggy version.  If you still want to use their alloca,
+# use ar to extract alloca.o from them instead of compiling alloca.c.
+
+ALLOCA=\${LIBOBJDIR}alloca.$ac_objext
+
+$as_echo "#define C_ALLOCA 1" >>confdefs.h
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether \`alloca.c' needs Cray hooks" >&5
+$as_echo_n "checking whether \`alloca.c' needs Cray hooks... " >&6; }
+if ${ac_cv_os_cray+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#if defined CRAY && ! defined CRAY2
+webecray
+#else
+wenotbecray
+#endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "webecray" >/dev/null 2>&1; then :
+  ac_cv_os_cray=yes
+else
+  ac_cv_os_cray=no
+fi
+rm -f conftest*
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_os_cray" >&5
+$as_echo "$ac_cv_os_cray" >&6; }
+if test $ac_cv_os_cray = yes; then
+  for ac_func in _getb67 GETB67 getb67; do
+    as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+
+cat >>confdefs.h <<_ACEOF
+#define CRAY_STACKSEG_END $ac_func
+_ACEOF
+
+    break
+fi
+
+  done
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking stack direction for C alloca" >&5
+$as_echo_n "checking stack direction for C alloca... " >&6; }
+if ${ac_cv_c_stack_direction+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "$cross_compiling" = yes; then :
+  ac_cv_c_stack_direction=0
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_includes_default
+int
+find_stack_direction (int *addr, int depth)
+{
+  int dir, dummy = 0;
+  if (! addr)
+    addr = &dummy;
+  *addr = addr < &dummy ? 1 : addr == &dummy ? 0 : -1;
+  dir = depth ? find_stack_direction (addr, depth - 1) : 0;
+  return dir + dummy;
+}
+
+int
+main (int argc, char **argv)
+{
+  return find_stack_direction (0, argc + !argv + 20) < 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  ac_cv_c_stack_direction=1
+else
+  ac_cv_c_stack_direction=-1
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_stack_direction" >&5
+$as_echo "$ac_cv_c_stack_direction" >&6; }
+cat >>confdefs.h <<_ACEOF
+#define STACK_DIRECTION $ac_cv_c_stack_direction
+_ACEOF
+
+
+fi
+
+for ac_header in fcntl.h inttypes.h libintl.h malloc.h stddef.h stdlib.h string.h unistd.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+# Checks for typedefs, structures, and compiler characteristics.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdbool.h that conforms to C99" >&5
+$as_echo_n "checking for stdbool.h that conforms to C99... " >&6; }
+if ${ac_cv_header_stdbool_h+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+             #include <stdbool.h>
+             #ifndef bool
+              "error: bool is not defined"
+             #endif
+             #ifndef false
+              "error: false is not defined"
+             #endif
+             #if false
+              "error: false is not 0"
+             #endif
+             #ifndef true
+              "error: true is not defined"
+             #endif
+             #if true != 1
+              "error: true is not 1"
+             #endif
+             #ifndef __bool_true_false_are_defined
+              "error: __bool_true_false_are_defined is not defined"
+             #endif
+
+             struct s { _Bool s: 1; _Bool t; } s;
+
+             char a[true == 1 ? 1 : -1];
+             char b[false == 0 ? 1 : -1];
+             char c[__bool_true_false_are_defined == 1 ? 1 : -1];
+             char d[(bool) 0.5 == true ? 1 : -1];
+             /* See body of main program for 'e'.  */
+             char f[(_Bool) 0.0 == false ? 1 : -1];
+             char g[true];
+             char h[sizeof (_Bool)];
+             char i[sizeof s.t];
+             enum { j = false, k = true, l = false * true, m = true * 256 };
+             /* The following fails for
+                HP aC++/ANSI C B3910B A.05.55 [Dec 04 2003]. */
+             _Bool n[m];
+             char o[sizeof n == m * sizeof n[0] ? 1 : -1];
+             char p[-1 - (_Bool) 0 < 0 && -1 - (bool) 0 < 0 ? 1 : -1];
+             /* Catch a bug in an HP-UX C compiler.  See
+                http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html
+                http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html
+              */
+             _Bool q = true;
+             _Bool *pq = &q;
+
+int
+main ()
+{
+
+             bool e = &s;
+             *pq |= q;
+             *pq |= ! q;
+             /* Refer to every declared value, to avoid compiler optimizations.  */
+             return (!a + !b + !c + !d + !e + !f + !g + !h + !i + !!j + !k + !!l
+                     + !m + !n + !o + !p + !q + !pq);
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  ac_cv_header_stdbool_h=yes
+else
+  ac_cv_header_stdbool_h=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdbool_h" >&5
+$as_echo "$ac_cv_header_stdbool_h" >&6; }
+   ac_fn_c_check_type "$LINENO" "_Bool" "ac_cv_type__Bool" "$ac_includes_default"
+if test "x$ac_cv_type__Bool" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE__BOOL 1
+_ACEOF
+
+
+fi
+
+
+if test $ac_cv_header_stdbool_h = yes; then
+
+$as_echo "#define HAVE_STDBOOL_H 1" >>confdefs.h
+
+fi
+
+ac_fn_c_find_intX_t "$LINENO" "16" "ac_cv_c_int16_t"
+case $ac_cv_c_int16_t in #(
+  no|yes) ;; #(
+  *)
+
+cat >>confdefs.h <<_ACEOF
+#define int16_t $ac_cv_c_int16_t
+_ACEOF
+;;
+esac
+
+ac_fn_c_find_intX_t "$LINENO" "32" "ac_cv_c_int32_t"
+case $ac_cv_c_int32_t in #(
+  no|yes) ;; #(
+  *)
+
+cat >>confdefs.h <<_ACEOF
+#define int32_t $ac_cv_c_int32_t
+_ACEOF
+;;
+esac
+
+ac_fn_c_find_intX_t "$LINENO" "8" "ac_cv_c_int8_t"
+case $ac_cv_c_int8_t in #(
+  no|yes) ;; #(
+  *)
+
+cat >>confdefs.h <<_ACEOF
+#define int8_t $ac_cv_c_int8_t
+_ACEOF
+;;
+esac
+
+ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default"
+if test "x$ac_cv_type_pid_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define pid_t int
+_ACEOF
+
+fi
+
+ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default"
+if test "x$ac_cv_type_size_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define size_t unsigned int
+_ACEOF
+
+fi
+
+ac_fn_c_find_uintX_t "$LINENO" "16" "ac_cv_c_uint16_t"
+case $ac_cv_c_uint16_t in #(
+  no|yes) ;; #(
+  *)
+
+
+cat >>confdefs.h <<_ACEOF
+#define uint16_t $ac_cv_c_uint16_t
+_ACEOF
+;;
+  esac
+
+ac_fn_c_find_uintX_t "$LINENO" "32" "ac_cv_c_uint32_t"
+case $ac_cv_c_uint32_t in #(
+  no|yes) ;; #(
+  *)
+
+$as_echo "#define _UINT32_T 1" >>confdefs.h
+
+
+cat >>confdefs.h <<_ACEOF
+#define uint32_t $ac_cv_c_uint32_t
+_ACEOF
+;;
+  esac
+
+ac_fn_c_find_uintX_t "$LINENO" "8" "ac_cv_c_uint8_t"
+case $ac_cv_c_uint8_t in #(
+  no|yes) ;; #(
+  *)
+
+$as_echo "#define _UINT8_T 1" >>confdefs.h
+
+
+cat >>confdefs.h <<_ACEOF
+#define uint8_t $ac_cv_c_uint8_t
+_ACEOF
+;;
+  esac
+
+
+# Checks for library functions.
+for ac_header in vfork.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "vfork.h" "ac_cv_header_vfork_h" "$ac_includes_default"
+if test "x$ac_cv_header_vfork_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_VFORK_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_func in fork vfork
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+if test "x$ac_cv_func_fork" = xyes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working fork" >&5
+$as_echo_n "checking for working fork... " >&6; }
+if ${ac_cv_func_fork_works+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "$cross_compiling" = yes; then :
+  ac_cv_func_fork_works=cross
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$ac_includes_default
+int
+main ()
+{
+
+	  /* By Ruediger Kuhlmann. */
+	  return fork () < 0;
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  ac_cv_func_fork_works=yes
+else
+  ac_cv_func_fork_works=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_fork_works" >&5
+$as_echo "$ac_cv_func_fork_works" >&6; }
+
+else
+  ac_cv_func_fork_works=$ac_cv_func_fork
+fi
+if test "x$ac_cv_func_fork_works" = xcross; then
+  case $host in
+    *-*-amigaos* | *-*-msdosdjgpp*)
+      # Override, as these systems have only a dummy fork() stub
+      ac_cv_func_fork_works=no
+      ;;
+    *)
+      ac_cv_func_fork_works=yes
+      ;;
+  esac
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&5
+$as_echo "$as_me: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&2;}
+fi
+ac_cv_func_vfork_works=$ac_cv_func_vfork
+if test "x$ac_cv_func_vfork" = xyes; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working vfork" >&5
+$as_echo_n "checking for working vfork... " >&6; }
+if ${ac_cv_func_vfork_works+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "$cross_compiling" = yes; then :
+  ac_cv_func_vfork_works=cross
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+/* Thanks to Paul Eggert for this test.  */
+$ac_includes_default
+#include <sys/wait.h>
+#ifdef HAVE_VFORK_H
+# include <vfork.h>
+#endif
+/* On some sparc systems, changes by the child to local and incoming
+   argument registers are propagated back to the parent.  The compiler
+   is told about this with #include <vfork.h>, but some compilers
+   (e.g. gcc -O) don't grok <vfork.h>.  Test for this by using a
+   static variable whose address is put into a register that is
+   clobbered by the vfork.  */
+static void
+#ifdef __cplusplus
+sparc_address_test (int arg)
+# else
+sparc_address_test (arg) int arg;
+#endif
+{
+  static pid_t child;
+  if (!child) {
+    child = vfork ();
+    if (child < 0) {
+      perror ("vfork");
+      _exit(2);
+    }
+    if (!child) {
+      arg = getpid();
+      write(-1, "", 0);
+      _exit (arg);
+    }
+  }
+}
+
+int
+main ()
+{
+  pid_t parent = getpid ();
+  pid_t child;
+
+  sparc_address_test (0);
+
+  child = vfork ();
+
+  if (child == 0) {
+    /* Here is another test for sparc vfork register problems.  This
+       test uses lots of local variables, at least as many local
+       variables as main has allocated so far including compiler
+       temporaries.  4 locals are enough for gcc 1.40.3 on a Solaris
+       4.1.3 sparc, but we use 8 to be safe.  A buggy compiler should
+       reuse the register of parent for one of the local variables,
+       since it will think that parent can't possibly be used any more
+       in this routine.  Assigning to the local variable will thus
+       munge parent in the parent process.  */
+    pid_t
+      p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(),
+      p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid();
+    /* Convince the compiler that p..p7 are live; otherwise, it might
+       use the same hardware register for all 8 local variables.  */
+    if (p != p1 || p != p2 || p != p3 || p != p4
+	|| p != p5 || p != p6 || p != p7)
+      _exit(1);
+
+    /* On some systems (e.g. IRIX 3.3), vfork doesn't separate parent
+       from child file descriptors.  If the child closes a descriptor
+       before it execs or exits, this munges the parent's descriptor
+       as well.  Test for this by closing stdout in the child.  */
+    _exit(close(fileno(stdout)) != 0);
+  } else {
+    int status;
+    struct stat st;
+
+    while (wait(&status) != child)
+      ;
+    return (
+	 /* Was there some problem with vforking?  */
+	 child < 0
+
+	 /* Did the child fail?  (This shouldn't happen.)  */
+	 || status
+
+	 /* Did the vfork/compiler bug occur?  */
+	 || parent != getpid()
+
+	 /* Did the file descriptor bug occur?  */
+	 || fstat(fileno(stdout), &st) != 0
+	 );
+  }
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  ac_cv_func_vfork_works=yes
+else
+  ac_cv_func_vfork_works=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_vfork_works" >&5
+$as_echo "$ac_cv_func_vfork_works" >&6; }
+
+fi;
+if test "x$ac_cv_func_fork_works" = xcross; then
+  ac_cv_func_vfork_works=$ac_cv_func_vfork
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&5
+$as_echo "$as_me: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&2;}
+fi
+
+if test "x$ac_cv_func_vfork_works" = xyes; then
+
+$as_echo "#define HAVE_WORKING_VFORK 1" >>confdefs.h
+
+else
+
+$as_echo "#define vfork fork" >>confdefs.h
+
+fi
+if test "x$ac_cv_func_fork_works" = xyes; then
+
+$as_echo "#define HAVE_WORKING_FORK 1" >>confdefs.h
+
+fi
+
+for ac_header in stdlib.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default"
+if test "x$ac_cv_header_stdlib_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_STDLIB_H 1
+_ACEOF
+
+fi
+
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible malloc" >&5
+$as_echo_n "checking for GNU libc compatible malloc... " >&6; }
+if ${ac_cv_func_malloc_0_nonnull+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "$cross_compiling" = yes; then :
+  ac_cv_func_malloc_0_nonnull=no
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#if defined STDC_HEADERS || defined HAVE_STDLIB_H
+# include <stdlib.h>
+#else
+char *malloc ();
+#endif
+
+int
+main ()
+{
+return ! malloc (0);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  ac_cv_func_malloc_0_nonnull=yes
+else
+  ac_cv_func_malloc_0_nonnull=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_malloc_0_nonnull" >&5
+$as_echo "$ac_cv_func_malloc_0_nonnull" >&6; }
+if test $ac_cv_func_malloc_0_nonnull = yes; then :
+
+$as_echo "#define HAVE_MALLOC 1" >>confdefs.h
+
+else
+  $as_echo "#define HAVE_MALLOC 0" >>confdefs.h
+
+   case " $LIBOBJS " in
+  *" malloc.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS malloc.$ac_objext"
+ ;;
+esac
+
+
+$as_echo "#define malloc rpl_malloc" >>confdefs.h
+
+fi
+
+
+for ac_header in stdlib.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default"
+if test "x$ac_cv_header_stdlib_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_STDLIB_H 1
+_ACEOF
+
+fi
+
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible realloc" >&5
+$as_echo_n "checking for GNU libc compatible realloc... " >&6; }
+if ${ac_cv_func_realloc_0_nonnull+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  if test "$cross_compiling" = yes; then :
+  ac_cv_func_realloc_0_nonnull=no
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#if defined STDC_HEADERS || defined HAVE_STDLIB_H
+# include <stdlib.h>
+#else
+char *realloc ();
+#endif
+
+int
+main ()
+{
+return ! realloc (0, 0);
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+  ac_cv_func_realloc_0_nonnull=yes
+else
+  ac_cv_func_realloc_0_nonnull=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+  conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_realloc_0_nonnull" >&5
+$as_echo "$ac_cv_func_realloc_0_nonnull" >&6; }
+if test $ac_cv_func_realloc_0_nonnull = yes; then :
+
+$as_echo "#define HAVE_REALLOC 1" >>confdefs.h
+
+else
+  $as_echo "#define HAVE_REALLOC 0" >>confdefs.h
+
+   case " $LIBOBJS " in
+  *" realloc.$ac_objext "* ) ;;
+  *) LIBOBJS="$LIBOBJS realloc.$ac_objext"
+ ;;
+esac
+
+
+$as_echo "#define realloc rpl_realloc" >>confdefs.h
+
+fi
+
+
+for ac_func in dup2 getcwd memset setenv strdup strstr
+do :
+  as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+#============================================================================
+# Detect if run on debian / ubuntu
+#============================================================================
+if test -f "/usr/bin/dpkg"
+then
+	DEB_DEF=-DDEB
+fi
+
+
+
+# Check whether --with-cgi-dir was given.
+if test "${with_cgi_dir+set}" = set; then :
+  withval=$with_cgi_dir; CGI_DIR="$withval"
+else
+  CGI_DIR="/usr/lib/cgi-bin"
+fi
+
+
+
+
+# Check whether --with-db-backend was given.
+if test "${with_db_backend+set}" = set; then :
+  withval=$with_db_backend; RELY_ON_DB="-DRELY_ON_DB"
+else
+  RELY_ON_DB=""
+fi
+
+
+
+
+# ===========================================================================
+# Detect if libyaml is available
+# ===========================================================================
+
+
+# Check whether --with-yaml was given.
+if test "${with_yaml+set}" = set; then :
+  withval=$with_yaml; YAMLPATH="$withval"
+else
+  YAMLPATH=""
+fi
+
+
+if test -z "$YAMLPATH"
+then
+	YAML_LDFLAGS=""
+	YAML_CPPFLAGS=""
+	YAML_FILE=""
+	YAML_FILE1=""
+else
+
+	# Extract the linker and include flags
+	YAML_LDFLAGS="-L$YAMLPATH/lib -lyaml"
+	YAML_CPPFLAGS="-I$YAMLPATH/include -DYAML"
+	YAML_FILE="service_yaml.o"
+	YAML_FILE1="zcfg2yaml"
+
+	# Check headers file
+	CPPFLAGS_SAVE="$CPPFLAGS"
+	CPPFLAGS="$YAML_CPPFLAGS"
+	LIBS_SAVE="$LIBS"
+	LIBS="$YAML_LDFLAGS"
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for yaml_parser_initialize,yaml_parser_set_input_file,yaml_parser_scan in -lyaml" >&5
+$as_echo_n "checking for yaml_parser_initialize,yaml_parser_set_input_file,yaml_parser_scan in -lyaml... " >&6; }
+if ${ac_cv_lib_yaml_yaml_parser_initialize_yaml_parser_set_input_file_yaml_parser_scan+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lyaml  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char yaml_parser_initialize,yaml_parser_set_input_file,yaml_parser_scan ();
+int
+main ()
+{
+return yaml_parser_initialize,yaml_parser_set_input_file,yaml_parser_scan ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_yaml_yaml_parser_initialize_yaml_parser_set_input_file_yaml_parser_scan=yes
+else
+  ac_cv_lib_yaml_yaml_parser_initialize_yaml_parser_set_input_file_yaml_parser_scan=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_yaml_yaml_parser_initialize_yaml_parser_set_input_file_yaml_parser_scan" >&5
+$as_echo "$ac_cv_lib_yaml_yaml_parser_initialize_yaml_parser_set_input_file_yaml_parser_scan" >&6; }
+if test "x$ac_cv_lib_yaml_yaml_parser_initialize_yaml_parser_set_input_file_yaml_parser_scan" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBYAML 1
+_ACEOF
+
+  LIBS="-lyaml $LIBS"
+
+fi
+
+	for ac_header in yaml.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "yaml.h" "ac_cv_header_yaml_h" "$ac_includes_default"
+if test "x$ac_cv_header_yaml_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_YAML_H 1
+_ACEOF
+
+else
+  as_fn_error $? "could not find headers include related to YAML" "$LINENO" 5
+fi
+
+done
+
+	LIBS="$LIBS_SAVE"
+fi
+
+
+
+
+
+# ===========================================================================
+# Detect if fastcgi is available
+# ===========================================================================
+
+
+# Check whether --with-fastcgi was given.
+if test "${with_fastcgi+set}" = set; then :
+  withval=$with_fastcgi; FCGIPATH="$withval"
+else
+  FCGIPATH="/usr"
+fi
+
+
+# Extract the linker and include flags
+FCGI_LDFLAGS="-L$FCGIPATH/lib"
+FCGI_CPPFLAGS="-I$FCGIPATH/include"
+
+# Check headers file
+CPPFLAGS_SAVE="$CPPFLAGS"
+CPPFLAGS="$FCGI_CPPFLAGS"
+LIBS_SAVE="$LIBS"
+LIBS="$FCGI_LDFLAGS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lfcgi" >&5
+$as_echo_n "checking for main in -lfcgi... " >&6; }
+if ${ac_cv_lib_fcgi_main+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lfcgi  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+
+int
+main ()
+{
+return main ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_fcgi_main=yes
+else
+  ac_cv_lib_fcgi_main=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_fcgi_main" >&5
+$as_echo "$ac_cv_lib_fcgi_main" >&6; }
+if test "x$ac_cv_lib_fcgi_main" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBFCGI 1
+_ACEOF
+
+  LIBS="-lfcgi $LIBS"
+
+fi
+
+for ac_header in fcgi_stdio.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "fcgi_stdio.h" "ac_cv_header_fcgi_stdio_h" "$ac_includes_default"
+if test "x$ac_cv_header_fcgi_stdio_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_FCGI_STDIO_H 1
+_ACEOF
+
+else
+  as_fn_error $? "could not find headers include related to fastcgi" "$LINENO" 5
+fi
+
+done
+
+LIBS="$LIBS_SAVE"
+
+
+
+# ===========================================================================
+# Detect if libxml2 is installed
+# ===========================================================================
+
+
+# Check whether --with-xml2config was given.
+if test "${with_xml2config+set}" = set; then :
+  withval=$with_xml2config; XML2CONFIG="$withval"
+else
+  XML2CONFIG=""
+fi
+
+
+if test "x$XML2CONFIG" = "x"; then
+	# XML2CONFIG was not specified, so search within the current path
+	# Extract the first word of "xml2-config", so it can be a program name with args.
+set dummy xml2-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_XML2CONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $XML2CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_XML2CONFIG="$XML2CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_XML2CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+XML2CONFIG=$ac_cv_path_XML2CONFIG
+if test -n "$XML2CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XML2CONFIG" >&5
+$as_echo "$XML2CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+	# If we couldn't find xml2-config, display a warning
+	if test "x$XML2CONFIG" = "x"; then
+		as_fn_error $? "could not find xml2-config from libxml2 within the current path. You may need to try re-running configure with a --with-xml2config parameter." "$LINENO" 5
+	fi
+else
+	# XML2CONFIG was specified; display a message to the user
+	if test "x$XML2CONFIG" = "xyes"; then
+		as_fn_error $? "you must Specifies a parameter to --with-xml2config, e.g. --with-xml2config=/path/to/xml2-config" "$LINENO" 5
+	else
+		if test -f $XML2CONFIG; then
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Using user-specified xml2-config file: $XML2CONFIG" >&5
+$as_echo "Using user-specified xml2-config file: $XML2CONFIG" >&6; }
+		else
+			as_fn_error $? "the user-specified xml2-config file $XML2CONFIG does not exist" "$LINENO" 5
+		fi
+	fi
+fi
+
+# Extract the linker and include flags
+XML2_LDFLAGS=`$XML2CONFIG --libs`
+XML2_CPPFLAGS=`$XML2CONFIG --cflags`
+
+# Check headers file
+CPPFLAGS_SAVE="$CPPFLAGS"
+CPPFLAGS="$XML2_CPPFLAGS"
+for ac_header in libxml/tree.h libxml/parser.h libxml/xpath.h libxml/xpathInternals.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  as_fn_error $? "could not find headers include related to libxml2" "$LINENO" 5
+fi
+
+done
+
+
+# Ensure we can link against libxml2
+LIBS_SAVE="$LIBS"
+LIBS="$XML2_LDFLAGS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for xmlInitParser in -lxml2" >&5
+$as_echo_n "checking for xmlInitParser in -lxml2... " >&6; }
+if ${ac_cv_lib_xml2_xmlInitParser+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lxml2  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char xmlInitParser ();
+int
+main ()
+{
+return xmlInitParser ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_xml2_xmlInitParser=yes
+else
+  ac_cv_lib_xml2_xmlInitParser=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_xml2_xmlInitParser" >&5
+$as_echo "$ac_cv_lib_xml2_xmlInitParser" >&6; }
+if test "x$ac_cv_lib_xml2_xmlInitParser" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBXML2 1
+_ACEOF
+
+  LIBS="-lxml2 $LIBS"
+
+else
+  as_fn_error $? "could not find libxml2" "$LINENO" 5
+fi
+
+
+
+
+LIBS="$LIBS_SAVE"
+
+
+# ===========================================================================
+# Detect if libxslt is installed
+# ===========================================================================
+
+
+# Check whether --with-xsltconfig was given.
+if test "${with_xsltconfig+set}" = set; then :
+  withval=$with_xsltconfig; XSLTCONFIG="$withval"
+else
+  XSLTCONFIG=""
+fi
+
+
+if test "x$XSLTCONFIG" = "x"; then
+	# XSLTCONFIG was not specified, so search within the current path
+	# Extract the first word of "xslt-config", so it can be a program name with args.
+set dummy xslt-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_XSLTCONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $XSLTCONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_XSLTCONFIG="$XSLTCONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_XSLTCONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+XSLTCONFIG=$ac_cv_path_XSLTCONFIG
+if test -n "$XSLTCONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $XSLTCONFIG" >&5
+$as_echo "$XSLTCONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+	# If we couldn't find xslt-config, display a warning
+	if test "x$XSLTCONFIG" = "x"; then
+		as_fn_error $? "could not find xslt-config from libxslt within the current path. You may need to try re-running configure with a --with-xtltconfig parameter." "$LINENO" 5
+	fi
+else
+	# XSLTCONFIG was specified; display a message to the user
+	if test "x$XSLTCONFIG" = "xyes"; then
+		as_fn_error $? "you must Specifies a parameter to --with-xsltconfig, e.g. --with-xsltconfig=/path/to/xslt-config" "$LINENO" 5
+	else
+		if test -f $XSLTCONFIG; then
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Using user-specified xslt-config file: $XSLTCONFIG" >&5
+$as_echo "Using user-specified xslt-config file: $XSLTCONFIG" >&6; }
+		else
+			as_fn_error $? "the user-specified xslt-config file $XSLTCONFIG does not exist" "$LINENO" 5
+		fi
+	fi
+fi
+
+# Extract the linker and include flags
+XSLT_LDFLAGS=`$XSLTCONFIG --libs`
+XSLT_CPPFLAGS=`$XSLTCONFIG --cflags`
+
+# Check headers file
+CPPFLAGS_SAVE="$CPPFLAGS"
+CPPFLAGS="$XSLT_CPPFLAGS"
+for ac_header in libxslt/xslt.h libxslt/xsltInternals.h libxslt/transform.h libxslt/xsltutils.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  as_fn_error $? "could not find headers include related to libxlst" "$LINENO" 5
+fi
+
+done
+
+
+
+
+
+#============================================================================
+# Detect if gdal is installed
+#============================================================================
+
+
+# Check whether --with-gdal-config was given.
+if test "${with_gdal_config+set}" = set; then :
+  withval=$with_gdal_config; GDAL_CONFIG="$withval"
+else
+  GDAL_CONFIG=""
+fi
+
+if test -z $GDAL_CONFIG;
+then
+	# Extract the first word of "gdal-config", so it can be a program name with args.
+set dummy gdal-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_GDAL_CONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $GDAL_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_GDAL_CONFIG="$GDAL_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_GDAL_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+GDAL_CONFIG=$ac_cv_path_GDAL_CONFIG
+if test -n "$GDAL_CONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GDAL_CONFIG" >&5
+$as_echo "$GDAL_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+	if test -z $GDAL_CONFIG;
+	then
+		as_fn_error $? "could not find gdal-config from libgdal within the current path. You may need to try re-running configure with a --with-gdal-config parameter." "$LINENO" 5
+	fi
+
+else
+	if test -f $GDAL_CONFIG; then
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Using user-specified gdal-config file: $GDAL_CONFIG" >&5
+$as_echo "Using user-specified gdal-config file: $GDAL_CONFIG" >&6; }
+	else
+		as_fn_error $? "the user-specified gdal-config file $GDAL_CONFIG does not exist" "$LINENO" 5
+	fi
+fi
+
+GDAL_CFLAGS="`$GDAL_CONFIG --cflags`"
+GDAL_LIBS="`$GDAL_CONFIG --libs`"
+
+
+
+
+# ===========================================================================
+# Detect if proj is installed
+# ===========================================================================
+
+
+# Check whether --with-proj was given.
+if test "${with_proj+set}" = set; then :
+  withval=$with_proj; PROJPATH="$withval"
+else
+  PROJPATH=""
+fi
+
+
+# Extract the linker and include flags
+PROJ_LDFLAGS="-L$PROJPATH/lib"
+PROJ_CPPFLAGS="-I$PROJPATH/include"
+
+# Check headers file
+CPPFLAGS_SAVE="$CPPFLAGS"
+CPPFLAGS="$PROJ_CPPFLAGS"
+for ac_header in proj_api.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "proj_api.h" "ac_cv_header_proj_api_h" "$ac_includes_default"
+if test "x$ac_cv_header_proj_api_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_PROJ_API_H 1
+_ACEOF
+
+else
+  as_fn_error $? "could not find headers include related to PROJ4" "$LINENO" 5
+fi
+
+done
+
+
+
+
+
+# ===========================================================================
+# Detect if libgeos is installed
+# ===========================================================================
+
+
+# Check whether --with-geosconfig was given.
+if test "${with_geosconfig+set}" = set; then :
+  withval=$with_geosconfig; GEOSCONFIG="$withval"
+else
+  GEOSCONFIG=""
+fi
+
+
+if test "x$GEOSCONFIG" = "x"; then
+	# GEOSCONFIG was not specified, so search within the current path
+	# Extract the first word of "geos-config", so it can be a program name with args.
+set dummy geos-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_GEOSCONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $GEOSCONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_GEOSCONFIG="$GEOSCONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_GEOSCONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+GEOSCONFIG=$ac_cv_path_GEOSCONFIG
+if test -n "$GEOSCONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GEOSCONFIG" >&5
+$as_echo "$GEOSCONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+	# If we couldn't find geos-config, display a warning
+	if test "x$GEOSCONFIG" = "x"; then
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not find geos-config from libgeos within the current path. You may need to try re-running configure with a --with-geosconfig parameter." >&5
+$as_echo "$as_me: WARNING: could not find geos-config from libgeos within the current path. You may need to try re-running configure with a --with-geosconfig parameter." >&2;}
+	fi
+else
+	# GEOSCONFIG was specified; display a message to the user
+	if test "x$GEOSCONFIG" = "xyes"; then
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: you must Specifies a parameter to --with-geosconfig, e.g. --with-geosconfig=/path/to/geos-config" >&5
+$as_echo "$as_me: WARNING: you must Specifies a parameter to --with-geosconfig, e.g. --with-geosconfig=/path/to/geos-config" >&2;}
+	else
+		if test -f $GEOSCONFIG; then
+			{ $as_echo "$as_me:${as_lineno-$LINENO}: result: Using user-specified geos-config file: $GEOSCONFIG" >&5
+$as_echo "Using user-specified geos-config file: $GEOSCONFIG" >&6; }
+		else
+			as_fn_error $? "the user-specified geos-config file $GEOSCONFIG does not exist" "$LINENO" 5
+		fi
+	fi
+fi
+
+GEOS_LDFLAGS=`$GEOSCONFIG --libs`
+GEOS_CPPFLAGS=`$GEOSCONFIG --cflags`
+
+# Check headers file
+CPPFLAGS_SAVE="$CPPFLAGS"
+CPPFLAGS="$GEOS_CPPFLAGS"
+for ac_header in geos_c.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "geos_c.h" "ac_cv_header_geos_c_h" "$ac_includes_default"
+if test "x$ac_cv_header_geos_c_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_GEOS_C_H 1
+_ACEOF
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not find headers include related to libgeos" >&5
+$as_echo "$as_me: WARNING: could not find headers include related to libgeos" >&2;}
+fi
+
+done
+
+
+
+
+
+
+# ===========================================================================
+# Detect if cgal is installed
+# ===========================================================================
+
+
+# Check whether --with-cgal was given.
+if test "${with_cgal+set}" = set; then :
+  withval=$with_cgal; CGALPATH="$withval"
+else
+  CGALPATH="/usr"
+fi
+
+
+
+# Check headers file
+CPPFLAGS_SAVE="$CPPFLAGS"
+CPPFLAGS="$CGAL_CPPFLAGS"
+for ac_header in CGAL/Delaunay_triangulation_2.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "CGAL/Delaunay_triangulation_2.h" "ac_cv_header_CGAL_Delaunay_triangulation_2_h" "$ac_includes_default"
+if test "x$ac_cv_header_CGAL_Delaunay_triangulation_2_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_CGAL_DELAUNAY_TRIANGULATION_2_H 1
+_ACEOF
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: could not find headers include related to libCGAL" >&5
+$as_echo "$as_me: WARNING: could not find headers include related to libCGAL" >&2;}
+fi
+
+done
+
+
+# Extract the linker and include flags
+CGAL_LDFLAGS="-L$CGALPATH/lib"
+CGAL_CPPFLAGS="-I$CGALPATH/include"
+
+
+
+
+#============================================================================
+# Detect if mapserver is installed
+#============================================================================
+
+
+# Check whether --with-mapserver was given.
+if test "${with_mapserver+set}" = set; then :
+  withval=$with_mapserver; MS_SRC_PATH="$withval"
+else
+  MS_SRC_PATH=""
+fi
+
+
+if test -z $MS_SRC_PATH;
+then
+	MS_CPPFLAGS=""
+	MS_LDFLAGS=""
+else
+       if test "x$MS_SRC_PATH" = "xmacos";
+       then
+               MS_LDFLAGS="/Library/Frameworks/MapServer.framework//Versions/6.0/MapServer -lintl"
+               MS_CPPFLAGS="-DUSE_MS `/Library/Frameworks/MapServer.framework/Programs/mapserver-config --includes` -I/Library/Frameworks/MapServer.framework/Versions/Current/Headers/ -I../mapserver "
+               { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Please make sure that ../mapserver exists and contains MapServer source tree" >&5
+$as_echo "$as_me: WARNING: Please make sure that ../mapserver exists and contains MapServer source tree" >&2;}
+               { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using MacOS X Framework for MapServer" >&5
+$as_echo "Using MacOS X Framework for MapServer" >&6; }
+       else
+               if test -d $MS_SRC_PATH; then
+                       MS_LDFLAGS="-L$MS_SRC_PATH -lmapserver `$MS_SRC_PATH/mapserver-config --libs`"
+                       MS_CPPFLAGS="-DUSE_MS `$MS_SRC_PATH/mapserver-config --includes` `$MS_SRC_PATH/mapserver-config --cflags` -I$MS_SRC_PATH "
+
+                       { $as_echo "$as_me:${as_lineno-$LINENO}: result: Using user-specified MapServer src path: $MS_SRC_PATH" >&5
+$as_echo "Using user-specified MapServer src path: $MS_SRC_PATH" >&6; }
+               else
+                       as_fn_error $? "the user-specified mapserver-config file $MS_SRC_PATH does not exist" "$LINENO" 5
+               fi
+       fi
+       MS_FILE="service_internal_ms.o"
+fi
+
+MS_CFLAGS="$MS_CPPFLAGS"
+MS_LIBS="$MS_LDFLAGS"
+
+
+
+
+
+# ===========================================================================
+# Detect if python is installed
+# ===========================================================================
+
+
+# Check whether --with-python was given.
+if test "${with_python+set}" = set; then :
+  withval=$with_python; PYTHON_PATH="$withval"; PYTHON_ENABLED="-DUSE_PYTHON"
+else
+  PYTHON_ENABLED=""
+fi
+
+
+
+# Check whether --with-pyvers was given.
+if test "${with_pyvers+set}" = set; then :
+  withval=$with_pyvers; PYTHON_VERS="$withval"
+else
+  PYTHON_VERS=""
+fi
+
+
+
+if test -z "$PYTHON_ENABLED"
+then
+	PYTHON_FILE=""
+else
+	PYTHONCONFIG="$PYTHON_PATH/bin/python${PYTHON_VERS}-config"
+	PYTHON_FILE="service_internal_python.o"
+	if test  "$PYTHON_PATH" = "yes"
+	then
+		# PHP was not specified, so search within the current path
+		PYTHONCFG_PATH=`which python${PYTHON_VERS}-config`
+		if test -z "${PYTHONCFG_PATH}" ; then
+		# Extract the first word of "python-config-${PYTHON_VERS}", so it can be a program name with args.
+set dummy python-config-${PYTHON_VERS}; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PYTHONCONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $PYTHONCONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_PYTHONCONFIG="$PYTHONCONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_PYTHONCONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+PYTHONCONFIG=$ac_cv_path_PYTHONCONFIG
+if test -n "$PYTHONCONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHONCONFIG" >&5
+$as_echo "$PYTHONCONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+		else
+		# Extract the first word of "python${PYTHON_VERS}-config", so it can be a program name with args.
+set dummy python${PYTHON_VERS}-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PYTHONCONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $PYTHONCONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_PYTHONCONFIG="$PYTHONCONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_PYTHONCONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+PYTHONCONFIG=$ac_cv_path_PYTHONCONFIG
+if test -n "$PYTHONCONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHONCONFIG" >&5
+$as_echo "$PYTHONCONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+		fi
+	else
+		PYTHONCONFIG="$PYTHON_PATH/bin/python${PYTHON_VERS}-config"
+	fi
+
+	# Extract the linker and include flags
+	PYTHON_LDFLAGS=`$PYTHONCONFIG --ldflags`
+	PYTHON_CPPFLAGS=`$PYTHONCONFIG --includes`
+
+	# Check headers file
+	CPPFLAGS_SAVE="$CPPFLAGS"
+	CPPFLAGS="$PYTHON_CPPFLAGS"
+	for ac_header in Python.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "Python.h" "ac_cv_header_Python_h" "$ac_includes_default"
+if test "x$ac_cv_header_Python_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_PYTHON_H 1
+_ACEOF
+
+else
+  as_fn_error $? "could not find headers include related to libpython" "$LINENO" 5
+fi
+
+done
+
+
+	# Ensure we can link against libphp
+	LIBS_SAVE="$LIBS"
+	LIBS="$PYTHON_LDFLAGS"
+	PY_LIB=`$PYTHONCONFIG --libs | sed -e 's/^.*\(python2\..\)$/\1/'`
+	as_ac_Lib=`$as_echo "ac_cv_lib_$PY_LIB''_PyObject_CallObject" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for PyObject_CallObject in -l$PY_LIB" >&5
+$as_echo_n "checking for PyObject_CallObject in -l$PY_LIB... " >&6; }
+if eval \${$as_ac_Lib+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-l$PY_LIB  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char PyObject_CallObject ();
+int
+main ()
+{
+return PyObject_CallObject ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  eval "$as_ac_Lib=yes"
+else
+  eval "$as_ac_Lib=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+eval ac_res=\$$as_ac_Lib
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_LIB$PY_LIB" | $as_tr_cpp` 1
+_ACEOF
+
+  LIBS="-l$PY_LIB $LIBS"
+
+else
+  as_fn_error $? "could not find libpython" "$LINENO" 5
+fi
+
+
+
+	LIBS="$LIBS_SAVE"
+fi
+
+
+
+
+# ===========================================================================
+# Detect if spidermonkey is installed
+# ===========================================================================
+
+
+# Check whether --with-js was given.
+if test "${with_js+set}" = set; then :
+  withval=$with_js; JSHOME="$withval";JS_ENABLED="-DUSE_JS"
+else
+  JS_ENABLED=""
+fi
+
+
+if test -z "$JS_ENABLED"
+then
+	JS_FILE=""
+else
+	JS_FILE="service_internal_js.o"
+	if test "$JSHOME" = "yes"
+	then
+
+		#on teste si on est sous debian like
+		if test -f "/usr/bin/dpkg"
+		then
+			if test -n "`dpkg -l | grep libmozjs185-dev`"
+			then
+				JS_CPPFLAGS="-I/usr/include/js/"
+                        	JS_LDFLAGS="-L/usr/lib -lmozjs185 -lm"
+                        	JS_LIB="mozjs185"
+			else
+				XUL_VERSION="`dpkg -l | grep xulrunner | grep dev | head -1| awk '{print $3;}' | cut -d'+' -f1`"
+				if test -n "$XUL_VERSION"
+				then
+					JS_CPPFLAGS="-I/usr/include/xulrunner-$XUL_VERSION"
+					JS_LDFLAGS="-L/usr/lib/xulrunner-$XUL_VERSION -lmozjs -lm"
+					JS_LIB="mozjs"
+				else
+					as_fn_error $? "You must install libmozjs185-dev or xulrunner-dev " "$LINENO" 5
+				fi
+			fi
+		else
+			as_fn_error $? "You must  specify your custom install of libmozjs185" "$LINENO" 5
+		fi
+	else
+		JS_CPPFLAGS="-I$JSHOME/include/js/"
+                JS_LDFLAGS="-L$JSHOME/lib -lmozjs185 -lm"
+                JS_LIB="mozjs185"
+
+	fi
+	CPPFLAGS_SAVE="$CPPFLAGS"
+        CPPFLAGS="$JS_CPPFLAGS"
+	ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5
+$as_echo_n "checking how to run the C++ preprocessor... " >&6; }
+if test -z "$CXXCPP"; then
+  if ${ac_cv_prog_CXXCPP+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+      # Double quotes because CXXCPP needs to be expanded
+    for CXXCPP in "$CXX -E" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+  break
+fi
+
+    done
+    ac_cv_prog_CXXCPP=$CXXCPP
+
+fi
+  CXXCPP=$ac_cv_prog_CXXCPP
+else
+  ac_cv_prog_CXXCPP=$CXXCPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5
+$as_echo "$CXXCPP" >&6; }
+ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+		     Syntax error
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+
+else
+  # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_cxx_try_cpp "$LINENO"; then :
+  # Broken: success on invalid input.
+continue
+else
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+for ac_header in jsapi.h
+do :
+  ac_fn_cxx_check_header_mongrel "$LINENO" "jsapi.h" "ac_cv_header_jsapi_h" "$ac_includes_default"
+if test "x$ac_cv_header_jsapi_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_JSAPI_H 1
+_ACEOF
+
+else
+  as_fn_error $? "could not find headers include related to libjs" "$LINENO" 5
+fi
+
+done
+
+
+	ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+	LIBS_SAVE="$LIBS"
+        LIBS="$JS_LDFLAGS"
+
+        as_ac_Lib=`$as_echo "ac_cv_lib_$JS_LIB''_JS_CompileFile,JS_CallFunctionName" | $as_tr_sh`
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for JS_CompileFile,JS_CallFunctionName in -l$JS_LIB" >&5
+$as_echo_n "checking for JS_CompileFile,JS_CallFunctionName in -l$JS_LIB... " >&6; }
+if eval \${$as_ac_Lib+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-l$JS_LIB  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char JS_CompileFile,JS_CallFunctionName ();
+int
+main ()
+{
+return JS_CompileFile,JS_CallFunctionName ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  eval "$as_ac_Lib=yes"
+else
+  eval "$as_ac_Lib=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+eval ac_res=\$$as_ac_Lib
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_LIB$JS_LIB" | $as_tr_cpp` 1
+_ACEOF
+
+  LIBS="-l$JS_LIB $LIBS"
+
+else
+  as_fn_error $? "could not find $JS_LIB" "$LINENO" 5
+fi
+
+	LIBS="$LIBS_SAVE"
+
+
+
+fi
+
+
+
+
+# ===========================================================================
+# Detect if php is installed
+# ===========================================================================
+
+
+# Check whether --with-php was given.
+if test "${with_php+set}" = set; then :
+  withval=$with_php; PHP_PATH="$withval"; PHP_ENABLED="-DUSE_PHP"
+else
+  PHP_ENABLED=""
+fi
+
+
+
+if test -z "$PHP_ENABLED"
+then
+	PHP_FILE=""
+else
+	PHPCONFIG="$PHP_PATH/bin/php-config"
+	PHP_FILE="service_internal_php.o"
+	if test  "$PHP_PATH" = "yes"
+	then
+		# PHP was not specified, so search within the current path
+		# Extract the first word of "php-config", so it can be a program name with args.
+set dummy php-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PHPCONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $PHPCONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_PHPCONFIG="$PHPCONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_PHPCONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+PHPCONFIG=$ac_cv_path_PHPCONFIG
+if test -n "$PHPCONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PHPCONFIG" >&5
+$as_echo "$PHPCONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+	else
+		PHPCONFIG="$PHP_PATH/bin/php-config"
+	fi
+
+	# Extract the linker and include flags
+	PHP_LDFLAGS="-L/`$PHPCONFIG --prefix`/lib -lphp5"
+	PHP_CPPFLAGS=`$PHPCONFIG --includes`
+
+	# Check headers file
+	CPPFLAGS_SAVE="$CPPFLAGS"
+	CPPFLAGS="$PHP_CPPFLAGS"
+	for ac_header in sapi/embed/php_embed.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "sapi/embed/php_embed.h" "ac_cv_header_sapi_embed_php_embed_h" "$ac_includes_default"
+if test "x$ac_cv_header_sapi_embed_php_embed_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_SAPI_EMBED_PHP_EMBED_H 1
+_ACEOF
+
+else
+  as_fn_error $? "could not find headers include related to libphp" "$LINENO" 5
+fi
+
+done
+
+
+	# Ensure we can link against libphp
+	LIBS_SAVE="$LIBS"
+	LIBS="$PHP_LDFLAGS"
+	# Shouldn't we get php here rather than php5 :) ??
+	{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for call_user_function in -lphp5" >&5
+$as_echo_n "checking for call_user_function in -lphp5... " >&6; }
+if ${ac_cv_lib_php5_call_user_function+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lphp5  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char call_user_function ();
+int
+main ()
+{
+return call_user_function ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_php5_call_user_function=yes
+else
+  ac_cv_lib_php5_call_user_function=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_php5_call_user_function" >&5
+$as_echo "$ac_cv_lib_php5_call_user_function" >&6; }
+if test "x$ac_cv_lib_php5_call_user_function" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBPHP5 1
+_ACEOF
+
+  LIBS="-lphp5 $LIBS"
+
+else
+  as_fn_error $? "could not find libphp" "$LINENO" 5
+fi
+
+	LIBS="$LIBS_SAVE"
+
+
+fi
+
+
+
+
+# ===========================================================================
+# Detect if java is installed
+# ===========================================================================
+
+
+# Check whether --with-java was given.
+if test "${with_java+set}" = set; then :
+  withval=$with_java; JDKHOME="$withval"; JAVA_ENABLED="-DUSE_JAVA"
+else
+  JAVA_ENABLED=""
+fi
+
+
+if test -z "$JAVA_ENABLED"
+then
+	JAVA_FILE=""
+else
+	JAVA_FILE="service_internal_java.o"
+	if test "x$JDKHOME" = "x";
+	then
+		as_fn_error $? "could not find java installation path within the current path. You may need to try re-running configure with a --with-java parameter." "$LINENO" 5
+	fi	# JAVA was specified; display a message to the user
+	if test "x$JDKHOME" = "xyes";
+	then
+		as_fn_error $? "you must specify a parameter to --with-java, e.g. --with-java=/path/to/java" "$LINENO" 5
+	fi
+
+	# Extract the linker and include flags
+	if test "x$JDKHOME" = "xmacos";
+	then
+		JAVA_LDFLAGS="-framework JavaVM"
+		JAVA_CPPFLAGS="-I/Applications/Xcode.app/Contents/Developer//Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/System/Library/Frameworks/JavaVM.framework/Versions/A/Headers/"
+	else
+		if test -d "$JDKHOME/jre/lib/i386";
+		then
+			JAVA_LDFLAGS="-L$JDKHOME/jre/lib/i386/server/ -ljvm -lpthread"
+			JAVA_CPPFLAGS="-I$JDKHOME/include -I$JDKHOME/include/linux"
+		else
+			JAVA_LDFLAGS="-L$JDKHOME/jre/lib/amd64/server/ -ljvm -lpthread"
+			JAVA_CPPFLAGS="-I$JDKHOME/include -I$JDKHOME/include/linux"
+		fi
+	fi
+
+	# Check headers file (second time we check that in fact)
+	CPPFLAGS_SAVE="$CPPFLAGS"
+	CPPFLAGS="$JAVA_CPPFLAGS"
+	for ac_header in jni.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "jni.h" "ac_cv_header_jni_h" "$ac_includes_default"
+if test "x$ac_cv_header_jni_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_JNI_H 1
+_ACEOF
+
+else
+  as_fn_error $? "could not find jni.h file" "$LINENO" 5
+fi
+
+done
+
+
+	# Ensure we can link against libjava
+	LIBS_SAVE="$LIBS"
+	LIBS="$JAVA_LDFLAGS"
+	if test "x$JDKHOME" != "xmacos";
+	then
+		{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for JNI_CreateJavaVM in -ljvm" >&5
+$as_echo_n "checking for JNI_CreateJavaVM in -ljvm... " >&6; }
+if ${ac_cv_lib_jvm_JNI_CreateJavaVM+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-ljvm  $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char JNI_CreateJavaVM ();
+int
+main ()
+{
+return JNI_CreateJavaVM ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_jvm_JNI_CreateJavaVM=yes
+else
+  ac_cv_lib_jvm_JNI_CreateJavaVM=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_jvm_JNI_CreateJavaVM" >&5
+$as_echo "$ac_cv_lib_jvm_JNI_CreateJavaVM" >&6; }
+if test "x$ac_cv_lib_jvm_JNI_CreateJavaVM" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBJVM 1
+_ACEOF
+
+  LIBS="-ljvm $LIBS"
+
+else
+  as_fn_error $? "could not find libjvm" "$LINENO" 5
+fi
+
+	fi
+	LIBS="$LIBS_SAVE"
+
+
+
+fi
+
+
+
+
+# ===========================================================================
+# Detect if ruby is installed
+# ===========================================================================
+
+# Check whether --with-ruby was given.
+if test "${with_ruby+set}" = set; then :
+  withval=$with_ruby; RUBY_PATH="$withval"; RUBY_ENABLED="-DUSE_RUBY"
+else
+  RUBY_ENABLED=""
+fi
+
+
+
+# Check whether --with-rvers was given.
+if test "${with_rvers+set}" = set; then :
+  withval=$with_rvers; RUBY_VERS="$withval"
+else
+  RUBY_VERS=""
+fi
+
+
+
+if test -z "$RUBY_ENABLED"
+then
+	RUBY_FILE=""
+else
+	RUBY_FILE="service_internal_ruby.o"
+
+	# Extract the linker and include flags
+	RUBY_LDFLAGS="-lruby"
+	RUBY_CPPFLAGS="-I$RUBY_PATH -I$RUBY_PATH/x86_64-darwin13.0/ -DZRUBY_VERSION=$RUBY_VERS"
+
+	# Check headers file
+	CPPFLAGS_SAVE="$CPPFLAGS"
+	CPPFLAGS="$RUBY_CPPFLAGS"
+	for ac_header in ruby.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "ruby.h" "ac_cv_header_ruby_h" "$ac_includes_default"
+if test "x$ac_cv_header_ruby_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_RUBY_H 1
+_ACEOF
+
+else
+  as_fn_error $? "could not find headers include related to libruby" "$LINENO" 5
+fi
+
+done
+
+
+	# Ensure we can link against libphp
+	LIBS_SAVE="$LIBS"
+	LIBS="$RUBY_LDFLAGS"
+	# AC_CHECK_LIB([lruby], [PyObject_CallObject], [], [AC_MSG_ERROR([could not find libpython])], [])
+	LIBS="$LIBS_SAVE"
+
+
+fi
+
+
+
+
+# ===========================================================================
+# Detect if perl is installed
+# ===========================================================================
+
+
+# Check whether --with-perl was given.
+if test "${with_perl+set}" = set; then :
+  withval=$with_perl; PERL_PATH="$withval"; PERL_ENABLED="-DUSE_PERL"
+else
+  PERL_ENABLED=""
+fi
+
+
+
+if test -z "$PERL_ENABLED"
+then
+	PERL_FILE=""
+else
+	PERL_FILE="service_internal_perl.o"
+	if test  "$PERL_PATH" = "yes"
+	then
+		# Perl was not specified, so search within the current path
+		# Extract the first word of "perl", so it can be a program name with args.
+set dummy perl; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PERLCONFIG+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $PERLCONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_PERLCONFIG="$PERLCONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_PERLCONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  ;;
+esac
+fi
+PERLCONFIG=$ac_cv_path_PERLCONFIG
+if test -n "$PERLCONFIG"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERLCONFIG" >&5
+$as_echo "$PERLCONFIG" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+	else
+		PERLCONFIG="$PERL_PATH/bin/perl"
+	fi
+
+	# Extract the linker and include flags
+	PERL_LDFLAGS=`$PERLCONFIG -MExtUtils::Embed -e ldopts`
+	PERL_CPPFLAGS=`$PERLCONFIG -MExtUtils::Embed -e ccopts`
+
+	# Check headers file
+	CPPFLAGS_SAVE="$CPPFLAGS"
+	CPPFLAGS="$PERL_CPPFLAGS"
+	for ac_header in EXTERN.h
+do :
+  ac_fn_c_check_header_mongrel "$LINENO" "EXTERN.h" "ac_cv_header_EXTERN_h" "$ac_includes_default"
+if test "x$ac_cv_header_EXTERN_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_EXTERN_H 1
+_ACEOF
+
+else
+  as_fn_error $? "could not find headers include related to libperl" "$LINENO" 5
+fi
+
+done
+
+
+
+
+fi
+
+
+
+
+# ===========================================================================
+# Detect if otb is available
+# ===========================================================================
+
+
+# Check whether --with-itk was given.
+if test "${with_itk+set}" = set; then :
+  withval=$with_itk; ITKPATH="$withval"
+else
+  ITKPATH=""
+fi
+
+
+
+# Check whether --with-itk-version was given.
+if test "${with_itk_version+set}" = set; then :
+  withval=$with_itk_version; ITKVERS="$withval"
+else
+  ITKVERS=""
+fi
+
+
+
+# Check whether --with-otb was given.
+if test "${with_otb+set}" = set; then :
+  withval=$with_otb; OTBPATH="$withval"
+else
+  OTBPATH=""
+fi
+
+
+if test -z "$OTBPATH"
+then
+	OTB_LDFLAGS=""
+	OTB_CPPFLAGS=""
+	OTB_FILE=""
+	OTB_ENABLED=""
+else
+	if test -z "$ITKVERS"
+    	then
+		ITKVERS="4.5"
+    	fi
+	OTB_ENABLED="-DUSE_OTB"
+	OTB_LDFLAGS="-L$OTBPATH/lib/otb -lOTBIO -lOTBCommon -lOTBApplicationEngine -L$ITKPATH/lib -lITKBiasCorrection-$ITKVERS -lITKCommon-$ITKVERS -lITKIOImageBase-$ITKVERS -lITKKLMRegionGrowing-$ITKVERS -lITKLabelMap-$ITKVERS -lITKMesh-$ITKVERS -lITKMetaIO-$ITKVERS -lITKOptimizers-$ITKVERS -lITKPath-$ITKVERS -lITKPolynomials-$ITKVERS -lITKQuadEdgeMesh-$ITKVERS -lITKSpatialObjects-$ITKVERS -lITKStatistics-$ITKVERS -lITKVNLInstantiation-$ITKVERS -lITKWatersheds-$ITKVERS -litkNetlibSlatec-$ITKVE [...]
+	OTB_CPPFLAGS="-I$OTBPATH/include/otb/ApplicationEngine -I$OTBPATH/include/otb/Common -I$ITKPATH/include/ITK-$ITKVERS -I$OTBPATH/include/otb/Utilities/ITK -I$OTBPATH/include/otb/ -I$OTBPATH/include/otb/IO -I$OTBPATH/include/otb/UtilitiesAdapters/OssimAdapters -I$OTBPATH/include/otb/UtilitiesAdapters/CurlAdapters -I$OTBPATH/include/otb/Utilities/BGL -I$OTBPATH/include/otb/UtilitiesAdapters/ITKPendingPatches -I$OTBPATH/include/otb/Utilities/otbconfigfile $GDAL_CFLAGS"
+	OTB_FILE="otbZooWatcher.o service_internal_otb.o"
+
+	ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+	# Check headers file
+	CPPFLAGS_SAVE="$CPPFLAGS"
+	CPPFLAGS="$OTB_CPPFLAGS"
+	LDFLAGS_SAVE="$LDFLAGS"
+	LIBS="$LIBS_SAVE $OTB_LDFLAGS"
+	for ac_header in otbWrapperApplication.h otbWrapperInputImageListParameter.h otbWrapperApplicationRegistry.h
+do :
+  as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_cxx_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+else
+  as_fn_error $? "could not find header file $i related to OTB" "$LINENO" 5
+fi
+
+done
+
+	ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+	ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+	LDFLAGS_SAVE="$LDFLAGS"
+	LDFLAGS="$OTB_LDFLAGS"
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include "otbWrapperApplication.h",std::vector<std::string> list = otb::Wrapwper::ApplicationRegistry::GetAvailableApplication();
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: checking for GetAvailableApplication... yes" >&5
+$as_echo "checking for GetAvailableApplication... yes" >&6; }
+else
+  as_fn_error $? "checking for GetAvailableApplication... failed" "$LINENO" 5
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+	LDFLAGS="$LDFLAGS_SAVE"
+
+fi
+
+
+
+
+
+# ===========================================================================
+# Detect if saga-gis is available
+# ===========================================================================
+
+
+# Check whether --with-wx-config was given.
+if test "${with_wx_config+set}" = set; then :
+  withval=$with_wx_config; WXCFG="$withval"
+else
+  WXCFG=""
+fi
+
+
+
+# Check whether --with-saga was given.
+if test "${with_saga+set}" = set; then :
+  withval=$with_saga; SAGAPATH="$withval"
+else
+  SAGAPATH=""
+fi
+
+
+if test -z "$SAGAPATH"
+then
+	SAGA_LDFLAGS=""
+	SAGA_CPPFLAGS=""
+	SAGA_FILE=""
+	SAGA_ENABLED=""
+else
+	if test -z "$WXCFG" ; then
+	   WXCFG="$(which wx-config)"
+	fi
+	if test "`$WXCFG --list | grep unicode`" == "" ; then
+	   as_fn_error $? "SAGA requires a unicode build of wxGTK" "$LINENO" 5
+	fi
+	WX_ISSUE="-D_WX_WXCRTVARARG_H_"
+	SAGA_DEFS="-D_SAGA_LINUX -D_TYPEDEF_BYTE -D_TYPEDEF_WORD -DMODULE_LIBRARY_PATH=\\\"$SAGAPATH/lib/saga\\\""
+	SAGA_CPPFLAGS=" -fPIC -I$SAGAPATH/include/saga/saga_core/saga_api/ `$WXCFG --unicode=yes --static=no --cxxflags` -D_SAGA_UNICODE $SAGA_DEFS $WX_ISSUE"
+	SAGA_LDFLAGS="-fPIC `$WXCFG --unicode=yes --static=no --libs` -lsaga_api"
+	SAGA_ENABLED="-DUSE_SAGA"
+	SAGA_FILE="service_internal_saga.o"
+
+	ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+	# Check headers file
+	CPPFLAGS_SAVE="$CPPFLAGS"
+	CPPFLAGS="$SAGA_CPPFLAGS"
+	LIBS_SAVE="$LIBS"
+	LIBS="$SAGA_LDFLAGS"
+	for ac_header in module_library.h
+do :
+  ac_fn_cxx_check_header_mongrel "$LINENO" "module_library.h" "ac_cv_header_module_library_h" "$ac_includes_default"
+if test "x$ac_cv_header_module_library_h" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_MODULE_LIBRARY_H 1
+_ACEOF
+
+else
+  as_fn_error $? "could not find header file $i related to SAGA-GIS" "$LINENO" 5
+fi
+
+done
+
+	cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include "module_library.h",SG_Get_Module_Library_Manager();
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: checking for SG_Get_Module_Library_Manager... yes" >&5
+$as_echo "checking for SG_Get_Module_Library_Manager... yes" >&6; }
+else
+  as_fn_error $? "checking for SG_Get_Module_Library_Manager... failed" "$LINENO" 5
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+	LIBS="$LIBS_SAVE"
+	ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+fi
+
+
+
+
+
+ac_config_files="$ac_config_files Makefile"
+
+ac_config_files="$ac_config_files ZOOMakefile.opts"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) { eval $ac_var=; unset $ac_var;} ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes: double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \.
+      sed -n \
+	"s/'/'\\\\''/g;
+	  s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    if test "x$cache_file" != "x/dev/null"; then
+      { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+      if test ! -f "$cache_file" || test -h "$cache_file"; then
+	cat confcache >"$cache_file"
+      else
+        case $cache_file in #(
+        */* | ?:*)
+	  mv -f confcache "$cache_file"$$ &&
+	  mv -f "$cache_file"$$ "$cache_file" ;; #(
+        *)
+	  mv -f confcache "$cache_file" ;;
+	esac
+      fi
+    fi
+  else
+    { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+# Transform confdefs.h into DEFS.
+# Protect against shell expansion while executing Makefile rules.
+# Protect against Makefile macro expansion.
+#
+# If the first sed substitution is executed (which looks for macros that
+# take arguments), then branch to the quote section.  Otherwise,
+# look for a macro that doesn't take arguments.
+ac_script='
+:mline
+/\\$/{
+ N
+ s,\\\n,,
+ b mline
+}
+t clear
+:clear
+s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 (][^	 (]*([^)]*)\)[	 ]*\(.*\)/-D\1=\2/g
+t quote
+s/^[	 ]*#[	 ]*define[	 ][	 ]*\([^	 ][^	 ]*\)[	 ]*\(.*\)/-D\1=\2/g
+t quote
+b any
+:quote
+s/[	 `~#$^&*(){}\\|;'\''"<>?]/\\&/g
+s/\[/\\&/g
+s/\]/\\&/g
+s/\$/$$/g
+H
+:any
+${
+	g
+	s/^\n//
+	s/\n/ /g
+	p
+}
+'
+DEFS=`sed -n "$ac_script" confdefs.h`
+
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in #(
+  *posix*) :
+    set -o posix ;; #(
+  *) :
+     ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+    && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='print -r --'
+  as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in #(
+      *"$as_nl"*)
+	expr "X$arg" : "X\\(.*\\)$as_nl";
+	arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""	$as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+  done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh).  But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there.  '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+  as_status=$1; test $as_status -eq 0 && as_status=1
+  if test "$4"; then
+    as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+    $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+  fi
+  $as_echo "$as_me: error: $2" >&2
+  as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+  return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+  set +e
+  as_fn_set_status $1
+  exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+  { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+  eval 'as_fn_append ()
+  {
+    eval $1+=\$2
+  }'
+else
+  as_fn_append ()
+  {
+    eval $1=\$$1\$2
+  }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+  eval 'as_fn_arith ()
+  {
+    as_val=$(( $* ))
+  }'
+else
+  as_fn_arith ()
+  {
+    as_val=`expr "$@" || test $? -eq 1`
+  }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+	 X"$0" : 'X\(//\)$' \| \
+	 X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\/\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+  case `echo 'xy\c'` in
+  *c*) ECHO_T='	';;	# ECHO_T is single tab character.
+  xy)  ECHO_C='\c';;
+  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null
+       ECHO_T='	';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -pR'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -pR'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -pR'
+  fi
+else
+  as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || eval $as_mkdir_p || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$as_dir" : 'X\(//\)[^/]' \| \
+	 X"$as_dir" : 'X\(//\)$' \| \
+	 X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p='mkdir -p "$as_dir"'
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+  test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by ZOO Kernel $as_me 1.5.0, which was
+generated by GNU Autoconf 2.69.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration.  Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+      --config     print configuration, then exit
+  -q, --quiet, --silent
+                   do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+      --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+
+Configuration files:
+$config_files
+
+Report bugs to <bugs at zoo-project.org>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+ZOO Kernel config.status 1.5.0
+configured by $0, generated by GNU Autoconf 2.69,
+  with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=?*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  --*=)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    $as_echo "$ac_cs_version"; exit ;;
+  --config | --confi | --conf | --con | --co | --c )
+    $as_echo "$ac_cs_config"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    '') as_fn_error $? "missing file argument" ;;
+    esac
+    as_fn_append CONFIG_FILES " '$ac_optarg'"
+    ac_need_defaults=false;;
+  --he | --h |  --help | --hel | -h )
+    $as_echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+  *) as_fn_append ac_config_targets " $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+  set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  shift
+  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+  CONFIG_SHELL='$SHELL'
+  export CONFIG_SHELL
+  exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+    "ZOOMakefile.opts") CONFIG_FILES="$CONFIG_FILES ZOOMakefile.opts" ;;
+
+  *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp= ac_tmp=
+  trap 'exit_status=$?
+  : "${ac_tmp:=$tmp}"
+  { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+  trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+  eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+  ac_cs_awk_cr='\\r'
+else
+  ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+  echo "cat >conf$$subs.awk <<_ACEOF" &&
+  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+  echo "_ACEOF"
+} >conf$$subs.sh ||
+  as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  . ./conf$$subs.sh ||
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+  if test $ac_delim_n = $ac_delim_num; then
+    break
+  elif $ac_last_try; then
+    as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+  N
+  s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+  for (key in S) S_is_set[key] = 1
+  FS = ""
+
+}
+{
+  line = $ 0
+  nfields = split(line, field, "@")
+  substed = 0
+  len = length(field[1])
+  for (i = 2; i < nfields; i++) {
+    key = field[i]
+    keylen = length(key)
+    if (S_is_set[key]) {
+      value = S[key]
+      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+      len += length(value) + length(field[++i])
+      substed = 1
+    } else
+      len += 1 + keylen
+  }
+
+  print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+  cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+  || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[	 ]*VPATH[	 ]*=[	 ]*/{
+h
+s///
+s/^/:/
+s/[	 ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[	 ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[	 ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+
+eval set X "  :F $CONFIG_FILES      "
+shift
+for ac_tag
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$ac_tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+	 # (if the path is not absolute).  The absolute path cannot be DOS-style,
+	 # because $ac_f cannot contain `:'.
+	 test -f "$ac_f" ||
+	   case $ac_f in
+	   [\\/$]*) false;;
+	   *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+	   esac ||
+	   as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+      esac
+      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+      as_fn_append ac_file_inputs " '$ac_f'"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input='Generated from '`
+	  $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+	`' by configure.'
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+    fi
+    # Neutralize special characters interpreted by sed in replacement strings.
+    case $configure_input in #(
+    *\&* | *\|* | *\\* )
+       ac_sed_conf_input=`$as_echo "$configure_input" |
+       sed 's/[\\\\&|]/\\\\&/g'`;; #(
+    *) ac_sed_conf_input=$configure_input;;
+    esac
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$ac_tmp/stdin" \
+      || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+	 X"$ac_file" : 'X\(//\)[^/]' \| \
+	 X"$ac_file" : 'X\(//\)$' \| \
+	 X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)[^/].*/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\/\)$/{
+	    s//\1/
+	    q
+	  }
+	  /^X\(\/\).*/{
+	    s//\1/
+	    q
+	  }
+	  s/.*/./; q'`
+  as_dir="$ac_dir"; as_fn_mkdir_p
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+  s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+  >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[	 ]*datarootdir[	 ]*:*=/p' \
+      "$ac_tmp/out"`; test -z "$ac_out"; } &&
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined" >&2;}
+
+  rm -f "$ac_tmp/stdin"
+  case $ac_file in
+  -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+  *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+  esac \
+  || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+
+
+
+  esac
+
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+  as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
diff --git a/zoo-project/zoo-kernel/configure.ac b/zoo-project/zoo-kernel/configure.ac
new file mode 100644
index 0000000..6978af3
--- /dev/null
+++ b/zoo-project/zoo-kernel/configure.ac
@@ -0,0 +1,776 @@
+AC_INIT([ZOO Kernel], [1.5.0], [bugs at zoo-project.org])
+
+# Checks for programs.
+AC_PROG_YACC
+AC_PROG_CC
+AC_PROG_LEX
+AC_PROG_CXX
+AC_PROG_SED
+
+# Checks for libraries.
+AC_CHECK_LIB([curl], [curl_easy_init,curl_easy_setopt,curl_easy_cleanup,curl_easy_perform])
+AC_CHECK_LIB([dl], [dlopen,dlsym,dlerror,dlclose])
+AC_CHECK_LIB([crypto], [EVP_DigestInit,EVP_md5,EVP_DigestUpdate,BIO_f_base64,BIO_new])
+AC_CHECK_LIB([uuid], [uuid_generate_time])
+
+DEFAULT_LIBS="$LIBS"
+AC_SUBST([DEFAULT_LIBS])
+
+
+# Checks for header files.
+AC_FUNC_ALLOCA
+AC_CHECK_HEADERS([fcntl.h inttypes.h libintl.h malloc.h stddef.h stdlib.h string.h unistd.h])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_HEADER_STDBOOL
+AC_TYPE_INT16_T
+AC_TYPE_INT32_T
+AC_TYPE_INT8_T
+AC_TYPE_PID_T
+AC_TYPE_SIZE_T
+AC_TYPE_UINT16_T
+AC_TYPE_UINT32_T
+AC_TYPE_UINT8_T
+
+# Checks for library functions.
+AC_FUNC_FORK
+AC_FUNC_MALLOC
+AC_FUNC_REALLOC
+AC_CHECK_FUNCS([dup2 getcwd memset setenv strdup strstr])
+
+#============================================================================
+# Detect if run on debian / ubuntu
+#============================================================================
+if test -f "/usr/bin/dpkg"
+then
+	DEB_DEF=-DDEB
+fi
+AC_SUBST([DEB_DEF])
+
+AC_ARG_WITH([cgi-dir],
+    [AS_HELP_STRING([--with-cgi-dir=PATH], [Specifies an alternative cgi directory path ( default: /usr/lib/cgi-bin) ])],
+    [CGI_DIR="$withval"], [CGI_DIR="/usr/lib/cgi-bin"])
+AC_SUBST([CGI_DIR])
+
+AC_ARG_WITH([db-backend],
+    [AS_HELP_STRING([--with-db-backend], [Relies on a database for storing status messages and response files ])],
+    [RELY_ON_DB="-DRELY_ON_DB"], [RELY_ON_DB=""])
+AC_SUBST([RELY_ON_DB])
+
+
+# ===========================================================================
+# Detect if libyaml is available
+# ===========================================================================
+
+AC_ARG_WITH([yaml],
+        [AS_HELP_STRING([--with-yaml=PATH], [Specifies an alternative location for the yaml library])],
+        [YAMLPATH="$withval"], [YAMLPATH=""])
+
+if test -z "$YAMLPATH"
+then
+	YAML_LDFLAGS=""
+	YAML_CPPFLAGS=""
+	YAML_FILE=""
+	YAML_FILE1=""
+else
+
+	# Extract the linker and include flags
+	YAML_LDFLAGS="-L$YAMLPATH/lib -lyaml"
+	YAML_CPPFLAGS="-I$YAMLPATH/include -DYAML"
+	YAML_FILE="service_yaml.o"
+	YAML_FILE1="zcfg2yaml"
+	
+	# Check headers file
+	CPPFLAGS_SAVE="$CPPFLAGS"
+	CPPFLAGS="$YAML_CPPFLAGS"
+	LIBS_SAVE="$LIBS"
+	LIBS="$YAML_LDFLAGS"
+	AC_CHECK_LIB([yaml], [yaml_parser_initialize,yaml_parser_set_input_file,yaml_parser_scan])
+	AC_CHECK_HEADERS([yaml.h],
+                 [], [AC_MSG_ERROR([could not find headers include related to YAML])])
+	LIBS="$LIBS_SAVE"
+fi
+AC_SUBST([YAML_CPPFLAGS])
+AC_SUBST([YAML_LDFLAGS])
+AC_SUBST([YAML_FILE])
+AC_SUBST([YAML_FILE1])
+
+# ===========================================================================
+# Detect if fastcgi is available
+# ===========================================================================
+
+AC_ARG_WITH([fastcgi],
+        [AS_HELP_STRING([--with-fastcgi=PATH], [Specifies an alternative location for the fastcgi library])],
+        [FCGIPATH="$withval"], [FCGIPATH="/usr"])
+
+# Extract the linker and include flags
+FCGI_LDFLAGS="-L$FCGIPATH/lib"
+FCGI_CPPFLAGS="-I$FCGIPATH/include"
+
+# Check headers file
+CPPFLAGS_SAVE="$CPPFLAGS"
+CPPFLAGS="$FCGI_CPPFLAGS"
+LIBS_SAVE="$LIBS"
+LIBS="$FCGI_LDFLAGS"
+AC_CHECK_LIB([fcgi], [main])
+AC_CHECK_HEADERS([fcgi_stdio.h],
+                 [], [AC_MSG_ERROR([could not find headers include related to fastcgi])])
+LIBS="$LIBS_SAVE"
+AC_SUBST([FCGI_CPPFLAGS])
+AC_SUBST([FCGI_LDFLAGS])
+
+# ===========================================================================
+# Detect if libxml2 is installed
+# ===========================================================================
+
+AC_ARG_WITH([xml2config], 
+	[AS_HELP_STRING([--with-xml2config=FILE], [Specifies an alternative xml2-config file])], 
+	[XML2CONFIG="$withval"], [XML2CONFIG=""])
+
+if test "x$XML2CONFIG" = "x"; then
+	# XML2CONFIG was not specified, so search within the current path
+	AC_PATH_PROG([XML2CONFIG], [xml2-config])
+
+	# If we couldn't find xml2-config, display a warning
+	if test "x$XML2CONFIG" = "x"; then
+		AC_MSG_ERROR([could not find xml2-config from libxml2 within the current path. You may need to try re-running configure with a --with-xml2config parameter.])
+	fi
+else
+	# XML2CONFIG was specified; display a message to the user
+	if test "x$XML2CONFIG" = "xyes"; then
+		AC_MSG_ERROR([you must Specifies a parameter to --with-xml2config, e.g. --with-xml2config=/path/to/xml2-config])
+	else
+		if test -f $XML2CONFIG; then
+			AC_MSG_RESULT([Using user-specified xml2-config file: $XML2CONFIG])
+		else
+			AC_MSG_ERROR([the user-specified xml2-config file $XML2CONFIG does not exist])
+		fi	
+	fi
+fi
+
+# Extract the linker and include flags 
+XML2_LDFLAGS=`$XML2CONFIG --libs`
+XML2_CPPFLAGS=`$XML2CONFIG --cflags`
+
+# Check headers file
+CPPFLAGS_SAVE="$CPPFLAGS"
+CPPFLAGS="$XML2_CPPFLAGS"
+AC_CHECK_HEADERS([libxml/tree.h libxml/parser.h libxml/xpath.h libxml/xpathInternals.h],
+		 [], [AC_MSG_ERROR([could not find headers include related to libxml2])])
+
+# Ensure we can link against libxml2
+LIBS_SAVE="$LIBS"
+LIBS="$XML2_LDFLAGS"
+AC_CHECK_LIB([xml2], [xmlInitParser], [], [AC_MSG_ERROR([could not find libxml2])], [])
+
+AC_SUBST([XML2_CPPFLAGS])
+AC_SUBST([XML2_LDFLAGS])
+LIBS="$LIBS_SAVE"
+
+
+# ===========================================================================
+# Detect if libxslt is installed
+# ===========================================================================
+
+AC_ARG_WITH([xsltconfig], 
+	[AS_HELP_STRING([--with-xsltconfig=FILE], [Specifies an alternative xslt-config file])], 
+	[XSLTCONFIG="$withval"], [XSLTCONFIG=""])
+
+if test "x$XSLTCONFIG" = "x"; then
+	# XSLTCONFIG was not specified, so search within the current path
+	AC_PATH_PROG([XSLTCONFIG], [xslt-config])
+
+	# If we couldn't find xslt-config, display a warning
+	if test "x$XSLTCONFIG" = "x"; then
+		AC_MSG_ERROR([could not find xslt-config from libxslt within the current path. You may need to try re-running configure with a --with-xtltconfig parameter.])
+	fi
+else
+	# XSLTCONFIG was specified; display a message to the user
+	if test "x$XSLTCONFIG" = "xyes"; then
+		AC_MSG_ERROR([you must Specifies a parameter to --with-xsltconfig, e.g. --with-xsltconfig=/path/to/xslt-config])
+	else
+		if test -f $XSLTCONFIG; then
+			AC_MSG_RESULT([Using user-specified xslt-config file: $XSLTCONFIG])
+		else
+			AC_MSG_ERROR([the user-specified xslt-config file $XSLTCONFIG does not exist])
+		fi	
+	fi
+fi
+
+# Extract the linker and include flags 
+XSLT_LDFLAGS=`$XSLTCONFIG --libs`
+XSLT_CPPFLAGS=`$XSLTCONFIG --cflags`
+
+# Check headers file
+CPPFLAGS_SAVE="$CPPFLAGS"
+CPPFLAGS="$XSLT_CPPFLAGS"
+AC_CHECK_HEADERS([libxslt/xslt.h libxslt/xsltInternals.h libxslt/transform.h libxslt/xsltutils.h],
+		 [], [AC_MSG_ERROR([could not find headers include related to libxlst])])
+
+AC_SUBST([XSLT_CPPFLAGS])
+AC_SUBST([XSLT_LDFLAGS])
+
+#============================================================================
+# Detect if gdal is installed
+#============================================================================
+
+AC_ARG_WITH([gdal-config], 
+	[AS_HELP_STRING([--with-gdal-config=FILE], [Specifies an alternative gdal-config file])], 
+	[GDAL_CONFIG="$withval"], [GDAL_CONFIG=""])
+if test -z $GDAL_CONFIG;
+then
+	AC_PATH_PROG([GDAL_CONFIG], [gdal-config])
+	if test -z $GDAL_CONFIG; 
+	then
+		AC_MSG_ERROR([could not find gdal-config from libgdal within the current path. You may need to try re-running configure with a --with-gdal-config parameter.])
+	fi
+	
+else
+	if test -f $GDAL_CONFIG; then
+		AC_MSG_RESULT([Using user-specified gdal-config file: $GDAL_CONFIG])
+	else
+		AC_MSG_ERROR([the user-specified gdal-config file $GDAL_CONFIG does not exist])
+	fi
+fi
+
+GDAL_CFLAGS="`$GDAL_CONFIG --cflags`"
+GDAL_LIBS="`$GDAL_CONFIG --libs`"
+
+AC_SUBST([GDAL_CFLAGS])
+AC_SUBST([GDAL_LIBS])
+
+# ===========================================================================
+# Detect if proj is installed
+# ===========================================================================
+
+AC_ARG_WITH([proj],
+        [AS_HELP_STRING([--with-proj=PATH], [Specifies an alternative location for PROJ4 setup])],
+        [PROJPATH="$withval"], [PROJPATH=""])
+
+# Extract the linker and include flags
+PROJ_LDFLAGS="-L$PROJPATH/lib"
+PROJ_CPPFLAGS="-I$PROJPATH/include"
+
+# Check headers file
+CPPFLAGS_SAVE="$CPPFLAGS"
+CPPFLAGS="$PROJ_CPPFLAGS"
+AC_CHECK_HEADERS([proj_api.h],
+                 [], [AC_MSG_ERROR([could not find headers include related to PROJ4])])
+
+AC_SUBST([PROJ_CPPFLAGS])
+AC_SUBST([PROJ_LDFLAGS])
+
+# ===========================================================================
+# Detect if libgeos is installed
+# ===========================================================================
+
+AC_ARG_WITH([geosconfig], 
+	[AS_HELP_STRING([--with-geosconfig=FILE], [Specifies an alternative geos-config file])], 
+	[GEOSCONFIG="$withval"], [GEOSCONFIG=""])
+
+if test "x$GEOSCONFIG" = "x"; then
+	# GEOSCONFIG was not specified, so search within the current path
+	AC_PATH_PROG([GEOSCONFIG], [geos-config])
+
+	# If we couldn't find geos-config, display a warning
+	if test "x$GEOSCONFIG" = "x"; then
+		AC_MSG_WARN([could not find geos-config from libgeos within the current path. You may need to try re-running configure with a --with-geosconfig parameter.])
+	fi
+else
+	# GEOSCONFIG was specified; display a message to the user
+	if test "x$GEOSCONFIG" = "xyes"; then
+		AC_MSG_WARN([you must Specifies a parameter to --with-geosconfig, e.g. --with-geosconfig=/path/to/geos-config])
+	else
+		if test -f $GEOSCONFIG; then
+			AC_MSG_RESULT([Using user-specified geos-config file: $GEOSCONFIG])
+		else
+			AC_MSG_ERROR([the user-specified geos-config file $GEOSCONFIG does not exist])
+		fi	
+	fi
+fi
+
+GEOS_LDFLAGS=`$GEOSCONFIG --libs`
+GEOS_CPPFLAGS=`$GEOSCONFIG --cflags`
+
+# Check headers file
+CPPFLAGS_SAVE="$CPPFLAGS"
+CPPFLAGS="$GEOS_CPPFLAGS"
+AC_CHECK_HEADERS([geos_c.h],
+		 [], [AC_MSG_WARN([could not find headers include related to libgeos])])
+
+AC_SUBST([GEOS_CPPFLAGS])
+AC_SUBST([GEOS_LDFLAGS])
+
+
+# ===========================================================================
+# Detect if cgal is installed
+# ===========================================================================
+
+AC_ARG_WITH([cgal],
+        [AS_HELP_STRING([--with-cgal=PATH], [Specifies an alternative location for CGAL setup])],
+        [CGALPATH="$withval"], [CGALPATH="/usr"])
+
+
+# Check headers file
+CPPFLAGS_SAVE="$CPPFLAGS"
+CPPFLAGS="$CGAL_CPPFLAGS"
+AC_CHECK_HEADERS([CGAL/Delaunay_triangulation_2.h],
+         [], [AC_MSG_WARN([could not find headers include related to libCGAL])])
+
+# Extract the linker and include flags
+CGAL_LDFLAGS="-L$CGALPATH/lib"
+CGAL_CPPFLAGS="-I$CGALPATH/include"
+
+
+AC_SUBST([CGAL_CPPFLAGS])
+AC_SUBST([CGAL_LDFLAGS])
+#============================================================================
+# Detect if mapserver is installed
+#============================================================================
+
+AC_ARG_WITH([mapserver], 
+       [AS_HELP_STRING([--with-mapserver=PATH], [Specifies the path for MapServer compiled source tree])], 
+       [MS_SRC_PATH="$withval"], [MS_SRC_PATH=""])
+
+if test -z $MS_SRC_PATH;
+then
+	MS_CPPFLAGS=""
+	MS_LDFLAGS=""
+else
+       if test "x$MS_SRC_PATH" = "xmacos";
+       then
+               MS_LDFLAGS="/Library/Frameworks/MapServer.framework//Versions/6.0/MapServer -lintl"
+               MS_CPPFLAGS="-DUSE_MS `/Library/Frameworks/MapServer.framework/Programs/mapserver-config --includes` -I/Library/Frameworks/MapServer.framework/Versions/Current/Headers/ -I../mapserver "
+               AC_MSG_WARN([Please make sure that ../mapserver exists and contains MapServer source tree])
+               AC_MSG_RESULT([Using MacOS X Framework for MapServer])
+       else
+               if test -d $MS_SRC_PATH; then
+                       MS_LDFLAGS="-L$MS_SRC_PATH -lmapserver `$MS_SRC_PATH/mapserver-config --libs`"
+                       MS_CPPFLAGS="-DUSE_MS `$MS_SRC_PATH/mapserver-config --includes` `$MS_SRC_PATH/mapserver-config --cflags` -I$MS_SRC_PATH "
+               
+                       AC_MSG_RESULT([Using user-specified MapServer src path: $MS_SRC_PATH])
+               else
+                       AC_MSG_ERROR([the user-specified mapserver-config file $MS_SRC_PATH does not exist])
+               fi
+       fi
+       MS_FILE="service_internal_ms.o"
+fi
+
+MS_CFLAGS="$MS_CPPFLAGS"
+MS_LIBS="$MS_LDFLAGS"
+
+AC_SUBST([MS_CFLAGS])
+AC_SUBST([MS_LIBS])
+AC_SUBST([MS_FILE])
+
+# ===========================================================================
+# Detect if python is installed
+# ===========================================================================
+
+AC_ARG_WITH([python], 
+	[AS_HELP_STRING([--with-python=PATH], [To enable python support or Specifies an alternative directory for python installation,  disabled by default])], 
+	[PYTHON_PATH="$withval"; PYTHON_ENABLED="-DUSE_PYTHON"], [PYTHON_ENABLED=""])
+
+AC_ARG_WITH([pyvers], 
+	[AS_HELP_STRING([--with-pyvers=NUM], [To use a specific python version])], 
+	[PYTHON_VERS="$withval"], [PYTHON_VERS=""])
+
+
+if test -z "$PYTHON_ENABLED"
+then
+	PYTHON_FILE=""
+else
+	PYTHONCONFIG="$PYTHON_PATH/bin/python${PYTHON_VERS}-config"
+	PYTHON_FILE="service_internal_python.o"
+	if test  "$PYTHON_PATH" = "yes"
+	then
+		# PHP was not specified, so search within the current path
+		PYTHONCFG_PATH=`which python${PYTHON_VERS}-config`
+		if test -z "${PYTHONCFG_PATH}" ; then
+		AC_PATH_PROG([PYTHONCONFIG], [python-config-${PYTHON_VERS}])
+		else
+		AC_PATH_PROG([PYTHONCONFIG], [python${PYTHON_VERS}-config])
+		fi
+	else
+		PYTHONCONFIG="$PYTHON_PATH/bin/python${PYTHON_VERS}-config"
+	fi
+
+	# Extract the linker and include flags 
+	PYTHON_LDFLAGS=`$PYTHONCONFIG --ldflags`
+	PYTHON_CPPFLAGS=`$PYTHONCONFIG --includes`
+
+	# Check headers file
+	CPPFLAGS_SAVE="$CPPFLAGS"
+	CPPFLAGS="$PYTHON_CPPFLAGS"
+	AC_CHECK_HEADERS([Python.h],
+		 [], [AC_MSG_ERROR([could not find headers include related to libpython])])
+
+	# Ensure we can link against libphp
+	LIBS_SAVE="$LIBS"
+	LIBS="$PYTHON_LDFLAGS"
+	PY_LIB=`$PYTHONCONFIG --libs | sed -e 's/^.*\(python2\..\)$/\1/'`
+	AC_CHECK_LIB([$PY_LIB], [PyObject_CallObject], [], [AC_MSG_ERROR([could not find libpython])], [])
+	AC_SUBST([PYTHON_CPPFLAGS])
+	AC_SUBST([PYTHON_LDFLAGS])
+	LIBS="$LIBS_SAVE"
+fi
+
+AC_SUBST([PYTHON_ENABLED])
+AC_SUBST([PYTHON_FILE])
+
+# ===========================================================================
+# Detect if spidermonkey is installed
+# ===========================================================================
+
+AC_ARG_WITH([js], 
+	[AS_HELP_STRING([--with-js=PATH], [Specifies --with-js=path-to-js to enable js support, specify --with-js on linux debian like, js support is disabled by default ])], 
+	[JSHOME="$withval";JS_ENABLED="-DUSE_JS"], [JS_ENABLED=""])
+
+if test -z "$JS_ENABLED"
+then
+	JS_FILE=""
+else
+	JS_FILE="service_internal_js.o"
+	if test "$JSHOME" = "yes"
+	then
+
+		#on teste si on est sous debian like 
+		if test -f "/usr/bin/dpkg"
+		then
+			if test -n "`dpkg -l | grep libmozjs185-dev`"
+			then
+				JS_CPPFLAGS="-I/usr/include/js/"
+                        	JS_LDFLAGS="-L/usr/lib -lmozjs185 -lm"
+                        	JS_LIB="mozjs185"
+			else 
+				XUL_VERSION="`dpkg -l | grep xulrunner | grep dev | head -1| awk '{print $3;}' | cut -d'+' -f1`"
+				if test -n "$XUL_VERSION"
+				then
+					JS_CPPFLAGS="-I/usr/include/xulrunner-$XUL_VERSION"
+					JS_LDFLAGS="-L/usr/lib/xulrunner-$XUL_VERSION -lmozjs -lm"
+					JS_LIB="mozjs"
+				else
+					AC_MSG_ERROR([You must install libmozjs185-dev or xulrunner-dev ])
+				fi
+			fi
+		else
+			AC_MSG_ERROR([You must  specify your custom install of libmozjs185])
+		fi
+	else
+		JS_CPPFLAGS="-I$JSHOME/include/js/"
+                JS_LDFLAGS="-L$JSHOME/lib -lmozjs185 -lm"
+                JS_LIB="mozjs185"
+
+	fi 
+	CPPFLAGS_SAVE="$CPPFLAGS"
+        CPPFLAGS="$JS_CPPFLAGS"
+	AC_LANG_PUSH([C++])
+	AC_CHECK_HEADERS([jsapi.h],
+                        [], [AC_MSG_ERROR([could not find headers include related to libjs])])
+
+	AC_LANG_POP([C++])
+	LIBS_SAVE="$LIBS"
+        LIBS="$JS_LDFLAGS"
+
+        AC_CHECK_LIB([$JS_LIB], [JS_CompileFile,JS_CallFunctionName], [], [AC_MSG_ERROR([could not find $JS_LIB])], [])
+	LIBS="$LIBS_SAVE"
+	
+        AC_SUBST([JS_CPPFLAGS])
+        AC_SUBST([JS_LDFLAGS])
+fi
+
+AC_SUBST([JS_ENABLED])
+AC_SUBST([JS_FILE])
+
+# ===========================================================================
+# Detect if php is installed
+# ===========================================================================
+
+AC_ARG_WITH([php], 
+	[AS_HELP_STRING([--with-php=PATH], [To enable php support or specify an alternative directory for php installation,  disabled by default])], 
+	[PHP_PATH="$withval"; PHP_ENABLED="-DUSE_PHP"], [PHP_ENABLED=""])
+
+
+if test -z "$PHP_ENABLED"
+then
+	PHP_FILE=""
+else
+	PHPCONFIG="$PHP_PATH/bin/php-config"
+	PHP_FILE="service_internal_php.o"
+	if test  "$PHP_PATH" = "yes"
+	then
+		# PHP was not specified, so search within the current path
+		AC_PATH_PROG([PHPCONFIG], [php-config])
+	else
+		PHPCONFIG="$PHP_PATH/bin/php-config"
+	fi
+
+	# Extract the linker and include flags 
+	PHP_LDFLAGS="-L/`$PHPCONFIG --prefix`/lib -lphp5"
+	PHP_CPPFLAGS=`$PHPCONFIG --includes`
+
+	# Check headers file
+	CPPFLAGS_SAVE="$CPPFLAGS"
+	CPPFLAGS="$PHP_CPPFLAGS"
+	AC_CHECK_HEADERS([sapi/embed/php_embed.h],
+		 [], [AC_MSG_ERROR([could not find headers include related to libphp])])
+
+	# Ensure we can link against libphp
+	LIBS_SAVE="$LIBS"
+	LIBS="$PHP_LDFLAGS"
+	# Shouldn't we get php here rather than php5 :) ??
+	AC_CHECK_LIB([php5], [call_user_function], [], [AC_MSG_ERROR([could not find libphp])], [])
+	LIBS="$LIBS_SAVE"
+	AC_SUBST([PHP_CPPFLAGS])
+	AC_SUBST([PHP_LDFLAGS])
+fi
+
+AC_SUBST([PHP_ENABLED])
+AC_SUBST([PHP_FILE])
+
+# ===========================================================================
+# Detect if java is installed
+# ===========================================================================
+
+AC_ARG_WITH([java], 
+	[AS_HELP_STRING([--with-java=PATH], [To enable java support, specify a JDK_HOME,  disabled by default])], 
+	[JDKHOME="$withval"; JAVA_ENABLED="-DUSE_JAVA"], [JAVA_ENABLED=""])
+
+if test -z "$JAVA_ENABLED"
+then
+	JAVA_FILE=""
+else
+	JAVA_FILE="service_internal_java.o"
+	if test "x$JDKHOME" = "x"; 
+	then
+		AC_MSG_ERROR([could not find java installation path within the current path. You may need to try re-running configure with a --with-java parameter.])
+	fi	# JAVA was specified; display a message to the user
+	if test "x$JDKHOME" = "xyes"; 
+	then
+		AC_MSG_ERROR([you must specify a parameter to --with-java, e.g. --with-java=/path/to/java])
+	fi
+
+	# Extract the linker and include flags
+	if test "x$JDKHOME" = "xmacos";
+	then
+		JAVA_LDFLAGS="-framework JavaVM"
+		JAVA_CPPFLAGS="-I/Applications/Xcode.app/Contents/Developer//Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/System/Library/Frameworks/JavaVM.framework/Versions/A/Headers/"
+	else
+		if test -d "$JDKHOME/jre/lib/i386";
+		then
+			JAVA_LDFLAGS="-L$JDKHOME/jre/lib/i386/server/ -ljvm -lpthread"
+			JAVA_CPPFLAGS="-I$JDKHOME/include -I$JDKHOME/include/linux"
+		else
+			JAVA_LDFLAGS="-L$JDKHOME/jre/lib/amd64/server/ -ljvm -lpthread"
+			JAVA_CPPFLAGS="-I$JDKHOME/include -I$JDKHOME/include/linux"
+		fi
+	fi
+
+	# Check headers file (second time we check that in fact)
+	CPPFLAGS_SAVE="$CPPFLAGS"
+	CPPFLAGS="$JAVA_CPPFLAGS"
+	AC_CHECK_HEADERS([jni.h],
+			 [], [AC_MSG_ERROR([could not find jni.h file])])
+
+	# Ensure we can link against libjava
+	LIBS_SAVE="$LIBS"
+	LIBS="$JAVA_LDFLAGS"
+	if test "x$JDKHOME" != "xmacos";
+	then
+		AC_CHECK_LIB([jvm], [JNI_CreateJavaVM], [], [AC_MSG_ERROR([could not find libjvm])], [])
+	fi
+	LIBS="$LIBS_SAVE"
+
+	AC_SUBST([JAVA_CPPFLAGS])
+	AC_SUBST([JAVA_LDFLAGS])
+fi 
+
+AC_SUBST([JAVA_ENABLED])
+AC_SUBST([JAVA_FILE])
+
+# ===========================================================================
+# Detect if ruby is installed
+# ===========================================================================
+AC_ARG_WITH([ruby], 
+	[AS_HELP_STRING([--with-ruby=PATH], [To enable ruby support or specify an alternative directory for ruby installation,  disabled by default])], 
+	[RUBY_PATH="$withval"; RUBY_ENABLED="-DUSE_RUBY"], [RUBY_ENABLED=""])
+
+AC_ARG_WITH([rvers], 
+	[AS_HELP_STRING([--with-rvers=NUM], [To use a specific ruby version])], 
+	[RUBY_VERS="$withval"], [RUBY_VERS=""])
+
+
+if test -z "$RUBY_ENABLED"
+then
+	RUBY_FILE=""
+else
+	RUBY_FILE="service_internal_ruby.o"
+
+	# Extract the linker and include flags 
+	RUBY_LDFLAGS="-lruby"
+	RUBY_CPPFLAGS="-I$RUBY_PATH -I$RUBY_PATH/x86_64-darwin13.0/ -DZRUBY_VERSION=$RUBY_VERS"
+
+	# Check headers file
+	CPPFLAGS_SAVE="$CPPFLAGS"
+	CPPFLAGS="$RUBY_CPPFLAGS"
+	AC_CHECK_HEADERS([ruby.h],
+		 [], [AC_MSG_ERROR([could not find headers include related to libruby])])
+
+	# Ensure we can link against libphp
+	LIBS_SAVE="$LIBS"
+	LIBS="$RUBY_LDFLAGS"
+	# AC_CHECK_LIB([lruby], [PyObject_CallObject], [], [AC_MSG_ERROR([could not find libpython])], [])
+	LIBS="$LIBS_SAVE"
+	AC_SUBST([RUBY_CPPFLAGS])
+	AC_SUBST([RUBY_LDFLAGS])
+fi
+
+AC_SUBST([RUBY_ENABLED])
+AC_SUBST([RUBY_FILE])
+
+# ===========================================================================
+# Detect if perl is installed
+# ===========================================================================
+
+AC_ARG_WITH([perl], 
+	[AS_HELP_STRING([--with-perl=PATH], [To enable perl support or specify an alternative directory for perl installation,  disabled by default])], 
+	[PERL_PATH="$withval"; PERL_ENABLED="-DUSE_PERL"], [PERL_ENABLED=""])
+
+
+if test -z "$PERL_ENABLED"
+then
+	PERL_FILE=""
+else
+	PERL_FILE="service_internal_perl.o"
+	if test  "$PERL_PATH" = "yes"
+	then
+		# Perl was not specified, so search within the current path
+		AC_PATH_PROG([PERLCONFIG], [perl])
+	else
+		PERLCONFIG="$PERL_PATH/bin/perl"
+	fi
+
+	# Extract the linker and include flags 
+	PERL_LDFLAGS=`$PERLCONFIG -MExtUtils::Embed -e ldopts`
+	PERL_CPPFLAGS=`$PERLCONFIG -MExtUtils::Embed -e ccopts`
+
+	# Check headers file
+	CPPFLAGS_SAVE="$CPPFLAGS"
+	CPPFLAGS="$PERL_CPPFLAGS"
+	AC_CHECK_HEADERS([EXTERN.h],
+		 [], [AC_MSG_ERROR([could not find headers include related to libperl])])
+
+	AC_SUBST([PERL_CPPFLAGS])
+	AC_SUBST([PERL_LDFLAGS])
+fi
+
+AC_SUBST([PERL_ENABLED])
+AC_SUBST([PERL_FILE])
+
+# ===========================================================================
+# Detect if otb is available
+# ===========================================================================
+
+AC_ARG_WITH([itk],
+        [AS_HELP_STRING([--with-itk=PATH], [Specifies an alternative location for the itk library])],
+        [ITKPATH="$withval"], [ITKPATH=""])
+
+AC_ARG_WITH([itk-version],
+        [AS_HELP_STRING([--with-itk-version=VERSION], [Specifies an alternative version for the itk library])],
+        [ITKVERS="$withval"], [ITKVERS=""])
+
+AC_ARG_WITH([otb],
+        [AS_HELP_STRING([--with-otb=PATH], [Specifies an alternative location for the otb library])],
+        [OTBPATH="$withval"], [OTBPATH=""])
+
+if test -z "$OTBPATH"
+then
+	OTB_LDFLAGS=""
+	OTB_CPPFLAGS=""
+	OTB_FILE=""
+	OTB_ENABLED=""
+else
+	if test -z "$ITKVERS" 
+    	then
+		ITKVERS="4.5"
+    	fi
+	OTB_ENABLED="-DUSE_OTB"
+	OTB_LDFLAGS="-L$OTBPATH/lib/otb -lOTBIO -lOTBCommon -lOTBApplicationEngine -L$ITKPATH/lib -lITKBiasCorrection-$ITKVERS -lITKCommon-$ITKVERS -lITKIOImageBase-$ITKVERS -lITKKLMRegionGrowing-$ITKVERS -lITKLabelMap-$ITKVERS -lITKMesh-$ITKVERS -lITKMetaIO-$ITKVERS -lITKOptimizers-$ITKVERS -lITKPath-$ITKVERS -lITKPolynomials-$ITKVERS -lITKQuadEdgeMesh-$ITKVERS -lITKSpatialObjects-$ITKVERS -lITKStatistics-$ITKVERS -lITKVNLInstantiation-$ITKVERS -lITKWatersheds-$ITKVERS -litkNetlibSlatec-$ITKVE [...]
+	OTB_CPPFLAGS="-I$OTBPATH/include/otb/ApplicationEngine -I$OTBPATH/include/otb/Common -I$ITKPATH/include/ITK-$ITKVERS -I$OTBPATH/include/otb/Utilities/ITK -I$OTBPATH/include/otb/ -I$OTBPATH/include/otb/IO -I$OTBPATH/include/otb/UtilitiesAdapters/OssimAdapters -I$OTBPATH/include/otb/UtilitiesAdapters/CurlAdapters -I$OTBPATH/include/otb/Utilities/BGL -I$OTBPATH/include/otb/UtilitiesAdapters/ITKPendingPatches -I$OTBPATH/include/otb/Utilities/otbconfigfile $GDAL_CFLAGS"
+	OTB_FILE="otbZooWatcher.o service_internal_otb.o"
+	
+	AC_LANG_PUSH([C++])
+	# Check headers file
+	CPPFLAGS_SAVE="$CPPFLAGS"
+	CPPFLAGS="$OTB_CPPFLAGS"
+	LDFLAGS_SAVE="$LDFLAGS"
+	LIBS="$LIBS_SAVE $OTB_LDFLAGS"
+	AC_CHECK_HEADERS([otbWrapperApplication.h otbWrapperInputImageListParameter.h otbWrapperApplicationRegistry.h],
+			[], [AC_MSG_ERROR([could not find header file $i related to OTB])])
+	AC_LANG_POP([C++])
+	AC_LANG(C++)
+	LDFLAGS_SAVE="$LDFLAGS"
+	LDFLAGS="$OTB_LDFLAGS"
+	AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include "otbWrapperApplication.h"],[std::vector<std::string> list = otb::Wrapwper::ApplicationRegistry::GetAvailableApplication();]])],
+		[AC_MSG_RESULT([checking for GetAvailableApplication... yes])],[AC_MSG_ERROR([checking for GetAvailableApplication... failed])])
+	LDFLAGS="$LDFLAGS_SAVE"
+			
+fi
+AC_SUBST([OTB_CPPFLAGS])
+AC_SUBST([OTB_LDFLAGS])
+AC_SUBST([OTB_FILE])
+AC_SUBST([OTB_ENABLED])
+
+# ===========================================================================
+# Detect if saga-gis is available
+# ===========================================================================
+
+AC_ARG_WITH([wx-config],
+        [AS_HELP_STRING([--with-wx-config=PATH], [Specifies an alternative path for the wx-config tool])],
+        [WXCFG="$withval"], [WXCFG=""])
+
+AC_ARG_WITH([saga],
+        [AS_HELP_STRING([--with-saga=PATH], [Specifies an alternative location for the SAGA-GIS library])],
+        [SAGAPATH="$withval"], [SAGAPATH=""])
+
+if test -z "$SAGAPATH"
+then
+	SAGA_LDFLAGS=""
+	SAGA_CPPFLAGS=""
+	SAGA_FILE=""
+	SAGA_ENABLED=""
+else
+	if test -z "$WXCFG" ; then
+	   WXCFG="$(which wx-config)"
+	fi
+	if test "`$WXCFG --list | grep unicode`" == "" ; then
+	   AC_MSG_ERROR(SAGA requires a unicode build of wxGTK)
+	fi
+	WX_ISSUE="-D_WX_WXCRTVARARG_H_"
+	SAGA_DEFS="-D_SAGA_LINUX -D_TYPEDEF_BYTE -D_TYPEDEF_WORD -DMODULE_LIBRARY_PATH=\\\"$SAGAPATH/lib/saga\\\""
+	SAGA_CPPFLAGS=" -fPIC -I$SAGAPATH/include/saga/saga_core/saga_api/ `$WXCFG --unicode=yes --static=no --cxxflags` -D_SAGA_UNICODE $SAGA_DEFS $WX_ISSUE"
+	SAGA_LDFLAGS="-fPIC `$WXCFG --unicode=yes --static=no --libs` -lsaga_api"
+	SAGA_ENABLED="-DUSE_SAGA"
+	SAGA_FILE="service_internal_saga.o"
+	
+	AC_LANG_PUSH([C++])
+	# Check headers file
+	CPPFLAGS_SAVE="$CPPFLAGS"
+	CPPFLAGS="$SAGA_CPPFLAGS"
+	LIBS_SAVE="$LIBS"
+	LIBS="$SAGA_LDFLAGS"
+	AC_CHECK_HEADERS([module_library.h],
+			[], [AC_MSG_ERROR([could not find header file $i related to SAGA-GIS])])
+	AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include "module_library.h"],[SG_Get_Module_Library_Manager();]])],
+		[AC_MSG_RESULT([checking for SG_Get_Module_Library_Manager... yes])],[AC_MSG_ERROR([checking for SG_Get_Module_Library_Manager... failed])])
+	LIBS="$LIBS_SAVE"
+	AC_LANG_POP([C++])
+fi
+AC_SUBST([SAGA_CPPFLAGS])
+AC_SUBST([SAGA_LDFLAGS])
+AC_SUBST([SAGA_FILE])
+AC_SUBST([SAGA_ENABLED])
+
+AC_CONFIG_FILES([Makefile])
+AC_CONFIG_FILES([ZOOMakefile.opts])
+AC_OUTPUT
diff --git a/zoo-project/zoo-kernel/doc/index.dox b/zoo-project/zoo-kernel/doc/index.dox
new file mode 100644
index 0000000..a896125
--- /dev/null
+++ b/zoo-project/zoo-kernel/doc/index.dox
@@ -0,0 +1,20 @@
+#ifndef DOXYGEN_SKIP                                                            
+/* $Id$ */               
+#endif /* DOXYGEN_SKIP */                                                       
+
+/*! \mainpage ZOO-Project C-API Documentation
+
+
+<a href="http://zoo-project.org/">ZOO-Project</a> is an open source WPS platform
+that is released under an <a href="http://zoo-project.org/trac/browser/trunk/zoo-project/LICENSE">X/MIT</a> style 
+<a href="http://www.opensource.org/"> Open Source</a> license. ZOO-Project software is incubating at the <a href="http://www.osgeo.org/">Open Source
+Geospatial Foundation</a>. 
+
+Home: http://www.zoo-project.org<br>
+Download: 
+ <a href="http://zoo-project.org/site/Downloads#Downloads">http at zoo-project.org</a>,
+ <a href="http://zoo-project.org/site/Downloads#Fordevelopers">svn at zoo-project.org</a>
+
+This documentation describes the ZOO-Project C-API. You can start your visit by the Data Structures link above which details all available structures in ZOO-Project. The Files link presents all source files used to generate this documentation.
+
+*/
diff --git a/zoo-project/zoo-kernel/locale/po/en_US.utf8.po b/zoo-project/zoo-kernel/locale/po/en_US.utf8.po
new file mode 100644
index 0000000..0932054
--- /dev/null
+++ b/zoo-project/zoo-kernel/locale/po/en_US.utf8.po
@@ -0,0 +1,171 @@
+# English translations for ZOO Kernel package.
+# Copyright (C) 2010 THE ZOO Kernel'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the ZOO Kernel package.
+# root <gerald.fenoy at geolabs.fr>, 2010.
+#
+#: service_internal.c:1672 zoo_service_loader.c:158 zoo_service_loader.c:160
+#: zoo_service_loader.c:220 zoo_service_loader.c:267 zoo_service_loader.c:341
+#: zoo_service_loader.c:1135 zoo_service_loader.c:1277
+#: zoo_service_loader.c:1364
+msgid ""
+msgstr ""
+"Project-Id-Version: ZOO Kernel 0.0.1\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-09-28 00:38+0200\n"
+"PO-Revision-Date: 2010-09-28 00:39+0200\n"
+"Last-Translator: root <gerald.fenoy at geolabs.fr>\n"
+"Language-Team: English\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: service_internal.c:1056
+#, c-format
+msgid ""
+"ZOO Service \"%s\" is currently running. Please, reload this document to get "
+"the up-to-date status of the Service."
+msgstr ""
+"ZOO Service \"%s\" is currently running. Please, reload this document to get "
+"the up-to-date status of the Service."
+
+#: service_internal.c:1062
+#, c-format
+msgid ""
+"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."
+msgstr ""
+"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."
+
+#: service_internal.c:1079
+msgid "No more information available"
+msgstr "No more information available"
+
+#: service_internal.c:1432 service_internal.c:1485
+msgid "No debug message available"
+msgstr "No debug message available"
+
+#: service_internal.c:1546
+msgid "Unable to fetch any result"
+msgstr "Unable to fetch any result"
+
+#: service_internal.c:1587
+#, c-format
+msgid ""
+"Unable to run the Service. The message returned back by the Service was the "
+"following : %s"
+msgstr ""
+"Unable to run the Service. The message returned back by the Service was the "
+"following : %s"
+
+#: service_internal.c:1589
+#, c-format
+msgid ""
+"Unable to run the Service. No more information was returned back by the "
+"Service."
+msgstr ""
+"Unable to run the Service. No more information was returned back by the "
+"Service."
+
+#: zoo_service_loader.c:119
+#, c-format
+msgid "ZOO Kernel failed to process your request receiving signal %d = %s"
+msgstr "ZOO Kernel failed to process your request receiving signal %d = %s"
+
+#: zoo_service_loader.c:147 zoo_service_loader.c:280 zoo_service_loader.c:367
+#: zoo_service_loader.c:420 zoo_service_loader.c:547 zoo_service_loader.c:623
+#: zoo_service_loader.c:637 zoo_service_loader.c:664 zoo_service_loader.c:705
+#: zoo_service_loader.c:788 zoo_service_loader.c:806 zoo_service_loader.c:864
+#: zoo_service_loader.c:905 zoo_service_loader.c:952 zoo_service_loader.c:987
+#: zoo_service_loader.c:1005 zoo_service_loader.c:1146
+#: zoo_service_loader.c:1218 zoo_service_loader.c:1238
+#: zoo_service_loader.c:1298 zoo_service_loader.c:1324
+msgid "Unable to allocate memory."
+msgstr "Unable to allocate memory."
+
+#: zoo_service_loader.c:181
+msgid "Parameter <request> was not specified"
+msgstr "Parameter <request> was not specified"
+
+#: zoo_service_loader.c:191 zoo_service_loader.c:402
+msgid ""
+"Unenderstood <request> value. Please check that it was set to "
+"GetCapabilities, DescribeProcess or Execute."
+msgstr ""
+"Unenderstood <request> value. Please check that it was set to "
+"GetCapabilities, DescribeProcess or Execute."
+
+#: zoo_service_loader.c:201
+msgid "Parameter <service> was not specified"
+msgstr "Parameter <service> was not specified"
+
+#: zoo_service_loader.c:210
+msgid "Parameter <version> was not specified"
+msgstr "Parameter <version> was not specified"
+
+#: zoo_service_loader.c:257
+msgid "The specified path doesn't exist."
+msgstr "The specified path doesn't exist."
+
+#: zoo_service_loader.c:311
+msgid "Mandatory <identifier> was not specified"
+msgstr "Mandatory <identifier> was not specified"
+
+#: zoo_service_loader.c:322
+msgid "The specified path path doesn't exist."
+msgstr "The specified path path doesn't exist."
+
+#: zoo_service_loader.c:404
+#, c-format
+msgid "No request found %s"
+msgstr "No request found %s"
+
+#: zoo_service_loader.c:441
+#, c-format
+msgid ""
+"The value for <indetifier> seems to be wrong (%s). Please, ensure that the "
+"process exist using the GetCapabilities request."
+msgstr ""
+"The value for <indetifier> seems to be wrong (%s). Please, ensure that the "
+"process exist using the GetCapabilities request."
+
+#: zoo_service_loader.c:519 zoo_service_loader.c:530
+msgid "Unable to allocate memory"
+msgstr "Unable to allocate memory"
+
+#: zoo_service_loader.c:606
+msgid "Parameter <DataInputs> was not specified"
+msgstr "Parameter <DataInputs> was not specified"
+
+#: service_internal.c:1048
+#, c-format
+msgid "Service \"%s\" run successfully."
+msgstr "Service \"%s\" run successfully."
+
+#: zoo_service_loader.c:1366
+#, c-format
+msgid ""
+"The <%s> argument was not specified in DataInputs but defined as requested "
+"in ZOO ServicesProvider configuration file, please correct your query or the "
+"ZOO Configuration file."
+msgstr ""
+"The <%s> argument was not specified in DataInputs but defined as requested "
+"in ZOO ServicesProvider configuration file, please correct your query or the "
+"ZOO Configuration file."
+
+#: zoo_service_loader.c:1651 zoo_service_loader.c:1871
+#, c-format
+msgid ""
+"Programming Language (%s) set in ZCFG file is not currently supported by ZOO "
+"Kernel.\n"
+msgstr ""
+"Programming Language (%s) set in ZCFG file is not currently supported by ZOO "
+"Kernel.\n"
+
+
+#: zoo_service_loader.c:1700
+msgid "Unable to run the child process properly"
+msgstr "Unable to run the child process properly"
diff --git a/zoo-project/zoo-kernel/locale/po/fr_FR.utf8.po b/zoo-project/zoo-kernel/locale/po/fr_FR.utf8.po
new file mode 100644
index 0000000..75a2af5
--- /dev/null
+++ b/zoo-project/zoo-kernel/locale/po/fr_FR.utf8.po
@@ -0,0 +1,174 @@
+# French translations for ZOO Kernel package.
+# Copyright (C) 2010 THE ZOO Kernel'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the ZOO Kernel package.
+# root <gerald.fenoy at geolabs.fr>, 2010.
+#
+#: service_internal.c:1672 zoo_service_loader.c:158 zoo_service_loader.c:160
+#: zoo_service_loader.c:220 zoo_service_loader.c:267 zoo_service_loader.c:341
+#: zoo_service_loader.c:1135 zoo_service_loader.c:1277
+#: zoo_service_loader.c:1364
+msgid ""
+msgstr ""
+"Project-Id-Version: ZOO Kernel 0.0.1\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-09-28 00:38+0200\n"
+"PO-Revision-Date: 2010-09-28 00:39+0200\n"
+"Last-Translator: root <gerald.fenoy at geolabs.fr>\n"
+"Language-Team: French\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
+#: service_internal.c:34
+msgid "0123456789abcdef"
+msgstr ""
+
+#: service_internal.c:1056
+#, c-format
+msgid ""
+"ZOO Service \"%s\" is currently running. Please, reload this document to get "
+"the up-to-date status of the Service."
+msgstr ""
+"Le Service ZOO \"%s\" est en cous d'exécution. Merci de recharger document pour"
+" obtenir une version à jour du status du Service."
+
+#: service_internal.c:1062
+#, c-format
+msgid ""
+"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."
+msgstr ""
+"Le Service \"%s\" a été accepté par le Noyau ZOO et tourne en tâche de fond. "
+"Merci de consulter le lien fourni dans ce document afin d'obtenir le status actuel du "
+"Service."
+
+#: service_internal.c:1079
+msgid "No more information available"
+msgstr "Pas plus d'information disponible"
+
+#: service_internal.c:1432 service_internal.c:1485
+msgid "No debug message available"
+msgstr "Pas de message de débuguage disponible"
+
+#: service_internal.c:1546
+msgid "Unable to fetch any result"
+msgstr "Impossible de récupérer un résultat"
+
+#: service_internal.c:1587
+#, c-format
+msgid ""
+"Unable to run the Service. The message returned back by the Service was the "
+"following : %s"
+msgstr ""
+"Impossible d'exécuter le Service. Le message retourné par le Service est le suivant : %s"
+
+#: service_internal.c:1589
+#, c-format
+msgid ""
+"Unable to run the Service. No more information was returned back by the "
+"Service."
+msgstr ""
+"Impossible d'exécuter le Service. Pas plus d'information disponible."
+
+#: zoo_service_loader.c:119
+#, c-format
+msgid "ZOO Kernel failed to process your request receiving signal %d = %s"
+msgstr ""
+"Le Noyau ZOO a rencontré un problème lors de l'exécution de votre resquête et a "
+"reçu le signal %d : %s "
+
+#: zoo_service_loader.c:147 zoo_service_loader.c:280 zoo_service_loader.c:367
+#: zoo_service_loader.c:420 zoo_service_loader.c:547 zoo_service_loader.c:623
+#: zoo_service_loader.c:637 zoo_service_loader.c:664 zoo_service_loader.c:705
+#: zoo_service_loader.c:788 zoo_service_loader.c:806 zoo_service_loader.c:864
+#: zoo_service_loader.c:905 zoo_service_loader.c:952 zoo_service_loader.c:987
+#: zoo_service_loader.c:1005 zoo_service_loader.c:1146
+#: zoo_service_loader.c:1218 zoo_service_loader.c:1238
+#: zoo_service_loader.c:1298 zoo_service_loader.c:1324
+msgid "Unable to allocate memory."
+msgstr "Impossible d'allouer de la mémoire."
+
+#: zoo_service_loader.c:181
+msgid "Parameter <request> was not specified"
+msgstr "Le paramètre <request> n'a pas été spécifié"
+
+#: zoo_service_loader.c:191 zoo_service_loader.c:402
+msgid ""
+"Unenderstood <request> value. Please check that it was set to "
+"GetCapabilities, DescribeProcess or Execute."
+msgstr ""
+"La valeur de <request> est incompréhensible. Merci d'utiliser l'une des valeurs "
+"suivantes : GetCapabilities, DescribeProcess ou Execute."
+
+#: zoo_service_loader.c:201
+msgid "Parameter <service> was not specified"
+msgstr "La paramètre <service> n'a pas été spécifié"
+
+#: zoo_service_loader.c:210
+msgid "Parameter <version> was not specified"
+msgstr "Le paramètre <version> n'a pas été spécifié"
+
+#: zoo_service_loader.c:257
+msgid "The specified path doesn't exist."
+msgstr "Le chemin spécifié n'existe pas"
+
+#: zoo_service_loader.c:311
+msgid "Mandatory <identifier> was not specified"
+msgstr "Le paramètre obligatoire <identifier> n'a pas été précisé"
+
+#: zoo_service_loader.c:322
+msgid "The specified path path doesn't exist."
+msgstr "Le chemin fourni n'existe pas."
+
+#: zoo_service_loader.c:404
+#, c-format
+msgid "No request found %s"
+msgstr "Aucune requête trouvée %s"
+
+#: zoo_service_loader.c:441
+#, c-format
+msgid ""
+"The value for <indetifier> seems to be wrong (%s). Please, ensure that the "
+"process exist using the GetCapabilities request."
+msgstr ""
+"La valeur pour le paramètre <identifier> semble éronné (%s). Merci de vous assurer que"
+" le service existe en utilisant une requête GetCapabilities."
+
+#: zoo_service_loader.c:519 zoo_service_loader.c:530
+msgid "Unable to allocate memory"
+msgstr "Impossible d'allouer de la mémoire"
+
+#: zoo_service_loader.c:606
+msgid "Parameter <DataInputs> was not specified"
+msgstr "Paramètre <DataInputs> n'a pas été précisé"
+
+#: service_internal.c:1048
+#, c-format
+msgid "Service \"%s\" run successfully."
+msgstr "Le Service \"%s\" a été exécuté avec succès."
+
+#: zoo_service_loader.c:1366
+#, c-format
+msgid ""
+"The <%s> argument was not specified in DataInputs but defined as requested "
+"in ZOO ServicesProvider configuration file, please correct your query or the "
+"ZOO Configuration file."
+msgstr ""
+"L'argument <%s> n'a pas été précisé dans les données en entrée (DataInputs) mais "
+"est défini comme obligatoire dans le fichier de méta-données du Service ZOO (zcfg). "
+"Merci de corriger votre requête ou le fichier de méta-données."
+
+#: zoo_service_loader.c:1651 zoo_service_loader.c:1871
+#, c-format
+msgid ""
+"Programming Language (%s) set in ZCFG file is not currently supported by ZOO "
+"Kernel.\n"
+msgstr ""
+"Le langage de programmation (%s) utilisé dans le fichier ZCFG n'est actuellement pas "
+"supporté par votre installation du noyau ZOO.\n"
+
+#: zoo_service_loader.c:1700
+msgid "Unable to run the child process properly"
+msgstr "Impossible d'exécuter le processus en tâche de fond"
diff --git a/zoo-project/zoo-kernel/locale/po/ja_JP.utf8.po b/zoo-project/zoo-kernel/locale/po/ja_JP.utf8.po
new file mode 100644
index 0000000..561296f
--- /dev/null
+++ b/zoo-project/zoo-kernel/locale/po/ja_JP.utf8.po
@@ -0,0 +1,174 @@
+# Japanese translations for ZOO Kernel package.
+# Copyright (C) 2010 THE ZOO Kernel'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the ZOO Kernel package.
+# Daisuke YOSHIDA <yoshida at la.tezuka-gu.ac.jp>, 2010.
+#
+#: service_internal.c:1672 zoo_service_loader.c:158 zoo_service_loader.c:160
+#: zoo_service_loader.c:220 zoo_service_loader.c:267 zoo_service_loader.c:341
+#: zoo_service_loader.c:1135 zoo_service_loader.c:1277
+#: zoo_service_loader.c:1364
+msgid ""
+msgstr ""
+"Project-Id-Version: ZOO Kernel 0.0.1\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-09-28 00:38+0200\n"
+"PO-Revision-Date: 2010-09-28 00:39+0200\n"
+"Last-Translator: Daisuke YOSHIDA <yoshida at la.tezuka-gu.ac.jp>\n"
+"Language-Team: Japanese\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
+#: service_internal.c:34
+msgid "0123456789abcdef"
+msgstr ""
+
+#: service_internal.c:1056
+#, c-format
+msgid ""
+"ZOO Service \"%s\" is currently running. Please, reload this document to get "
+"the up-to-date status of the Service."
+msgstr ""
+"現在,ZOOサービス \"%s\" が動作しています. このサービスのステータスを最新のものにするために,"
+"このドキュメントを再読込してください."
+
+#: service_internal.c:1062
+#, c-format
+msgid ""
+"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."
+msgstr ""
+"ZOOカーネルが \"%s\" サービスをアクセプトし,バックグラウンドタスクとして動作しています."
+"ドキュメントを最新の状態に保つために,ドキュメントで提供されている"
+"statusLocation属性を確認してください."
+
+#: service_internal.c:1079
+msgid "No more information available"
+msgstr "情報はありません."
+
+#: service_internal.c:1432 service_internal.c:1485
+msgid "No debug message available"
+msgstr "デバッグメッセージはありません."
+
+#: service_internal.c:1546
+msgid "Unable to fetch any result"
+msgstr "結果が取得できませんでした."
+
+#: service_internal.c:1587
+#, c-format
+msgid ""
+"Unable to run the Service. The message returned back by the Service was the "
+"following : %s"
+msgstr ""
+"サービスを開始することができませんでした.このサービスによって返されたメッセージは  %s です。"
+
+#: service_internal.c:1589
+#, c-format
+msgid ""
+"Unable to run the Service. No more information was returned back by the "
+"Service."
+msgstr ""
+"サービスを開始できませんでした.このサービスによって返された情報はありません ."
+
+#: zoo_service_loader.c:119
+#, c-format
+msgid "ZOO Kernel failed to process your request receiving signal %d = %s"
+msgstr ""
+"ZOOカーネルはリクエストを処理することができませんでした.受け取ったシグナルは"
+"%d : %s です."
+
+#: zoo_service_loader.c:147 zoo_service_loader.c:280 zoo_service_loader.c:367
+#: zoo_service_loader.c:420 zoo_service_loader.c:547 zoo_service_loader.c:623
+#: zoo_service_loader.c:637 zoo_service_loader.c:664 zoo_service_loader.c:705
+#: zoo_service_loader.c:788 zoo_service_loader.c:806 zoo_service_loader.c:864
+#: zoo_service_loader.c:905 zoo_service_loader.c:952 zoo_service_loader.c:987
+#: zoo_service_loader.c:1005 zoo_service_loader.c:1146
+#: zoo_service_loader.c:1218 zoo_service_loader.c:1238
+#: zoo_service_loader.c:1298 zoo_service_loader.c:1324
+msgid "Unable to allocate memory."
+msgstr "Impossible d'allouer de la mémoire."
+
+#: zoo_service_loader.c:181
+msgid "Parameter <request> was not specified"
+msgstr "パラメーターが指定されていません."
+
+#: zoo_service_loader.c:191 zoo_service_loader.c:402
+msgid ""
+"Unenderstood <request> value. Please check that it was set to "
+"GetCapabilities, DescribeProcess or Execute."
+msgstr ""
+"<request>値を認識しました. 値が下記のリクエストを指定されているか確認してください."
+"GetCapabilities, DescribeProcess, Execute."
+
+#: zoo_service_loader.c:201
+msgid "Parameter <service> was not specified"
+msgstr "<service> パラメーターが指定されていません."
+
+#: zoo_service_loader.c:210
+msgid "Parameter <version> was not specified"
+msgstr "<version>パラメーターが指定されていません."
+
+#: zoo_service_loader.c:257
+msgid "The specified path doesn't exist."
+msgstr "指定されたパスが存在しません."
+
+#: zoo_service_loader.c:311
+msgid "Mandatory <identifier> was not specified"
+msgstr "<identifier>値(要指定)が指定されていません."
+
+#: zoo_service_loader.c:322
+msgid "The specified path path doesn't exist."
+msgstr "指定されたパスが存在しません."
+
+#: zoo_service_loader.c:404
+#, c-format
+msgid "No request found %s"
+msgstr "%sのリクエストが見つかりません."
+
+#: zoo_service_loader.c:441
+#, c-format
+msgid ""
+"The value for <indetifier> seems to be wrong (%s). Please, ensure that the "
+"process exist using the GetCapabilities request."
+msgstr ""
+"<identifier>についての値が不正です(%s). GetCapabilitiesにより"
+"そのプロセスが存在しているか確認してください."
+
+#: zoo_service_loader.c:519 zoo_service_loader.c:530
+msgid "Unable to allocate memory"
+msgstr "メモリを割り当てられません."
+
+#: zoo_service_loader.c:606
+msgid "Parameter <DataInputs> was not specified"
+msgstr "<DataInputs> パラメーターが指定されていません."
+
+#: service_internal.c:1048
+#, c-format
+msgid "Service \"%s\" run successfully."
+msgstr " \"%s\"サービスが動作しました."
+
+#: zoo_service_loader.c:1366
+#, c-format
+msgid ""
+"The <%s> argument was not specified in DataInputs but defined as requested "
+"in ZOO ServicesProvider configuration file, please correct your query or the "
+"ZOO Configuration file."
+msgstr ""
+"DataInputsの中の引数 <%s>が指定されていませんでしたが,"
+"ZOO ServicesProviderの設定ファイル(zcfg)の中で定義されています."
+"クエリー,もしくはZOO設定ファイルを修正してください."
+
+#: zoo_service_loader.c:1651 zoo_service_loader.c:1871
+#, c-format
+msgid ""
+"Programming Language (%s) set in ZCFG file is not currently supported by ZOO "
+"Kernel.\n"
+msgstr ""
+"ZCFGファイルの中で設定されているプログラム言語 (%s) は "
+"現在のZOOカーネルではサポートしていません.\n"
+
+#: zoo_service_loader.c:1700
+msgid "Unable to run the child process properly"
+msgstr "子プロセスを開始することができません."
diff --git a/zoo-project/zoo-kernel/locale/po/messages.po b/zoo-project/zoo-kernel/locale/po/messages.po
new file mode 100644
index 0000000..174e001
--- /dev/null
+++ b/zoo-project/zoo-kernel/locale/po/messages.po
@@ -0,0 +1,364 @@
+# ZOO-Kernel Internationalization.
+# Copyright (C) 2015 GeoLabs SARL
+# This file is distributed under the same license as the PACKAGE package.
+# Gerald Fenoy <gerald.fenoy at geolabs.fr>, 2015.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ZOO-Kernel 1.5.0\n"
+"Report-Msgid-Bugs-To: zoo-discuss at lists.osgeo.org\n"
+"POT-Creation-Date: 2015-07-02 18:06+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: caching.c:217 caching.c:235 caching.c:356 request_parser.c:214
+#: request_parser.c:225 request_parser.c:262 request_parser.c:403
+#: request_parser.c:414 request_parser.c:441 request_parser.c:537
+#: request_parser.c:562 request_parser.c:665 request_parser.c:782
+#: request_parser.c:1112 request_parser.c:1204 zcfg2yaml.c:38
+#: zoo_service_loader.c:259 zoo_service_loader.c:880 zoo_service_loader.c:1363
+#: zoo_service_loader.c:1559
+msgid "Unable to allocate memory"
+msgstr "Unable to allocate memory"
+
+#: caching.c:344
+msgid "Unable to download the file."
+msgstr "Unable to download the file."
+
+#: request_parser.c:92
+#, c-format
+msgid "The maximum allowed occurrences for <%s> (%i) was exceeded."
+msgstr "The maximum allowed occurrences for <%s> (%i) was exceeded."
+
+#: request_parser.c:113
+#, c-format
+msgid "ZOO-Kernel was unable to load your data for %s position %s."
+msgstr "ZOO-Kernel was unable to load your data for %s position %s."
+
+#: request_parser.c:124
+#, c-format
+msgid "The maximum allowed occurrences for <%s> is one."
+msgstr "The maximum allowed occurrences for <%s> is one."
+
+#: request_parser.c:315
+#, c-format
+msgid "Unable to find a valid protocol to download the remote file %s"
+msgstr "Unable to find a valid protocol to download the remote file %s"
+
+#: request_parser.c:613
+msgid "Unable to add a request in the queue."
+msgstr "Unable to add a request in the queue."
+
+#: request_parser.c:1021
+msgid "Unable to append maps to maps."
+msgstr "Unable to append maps to maps."
+
+#: request_parser.c:1291
+msgid "Duplicate <Output> elements in WPS Execute request"
+msgstr "Duplicate <Output> elements in WPS Execute request"
+
+#: request_parser.c:1487
+#, c-format
+msgid ""
+"The <%s> parameter has a size limit (%s MB) defined in the ZOO "
+"ServicesProvider configuration file, but the reference you provided exceeds "
+"this limit (%f MB)."
+msgstr ""
+"The <%s> parameter has a size limit (%s MB) defined in the ZOO "
+"ServicesProvider configuration file, but the reference you provided exceeds "
+"this limit (%f MB)."
+
+#: request_parser.c:1519
+#, c-format
+msgid ""
+"The <%s> argument was not specified in DataInputs but is required according "
+"to the ZOO ServicesProvider configuration file."
+msgstr ""
+"The <%s> argument was not specified in DataInputs but is required according "
+"to the ZOO ServicesProvider configuration file."
+
+#: request_parser.c:1545
+#, c-format
+msgid ""
+"The <%s> argument specified as %s identifier was not recognized (not defined "
+"in the ZOO Configuration File)."
+msgstr ""
+"The <%s> argument specified as %s identifier was not recognized (not defined "
+"in the ZOO Configuration File)."
+
+#: request_parser.c:1663
+#, c-format
+msgid "Mandatory parameter <%s> was not specified"
+msgstr "Mandatory parameter <%s> was not specified"
+
+#: request_parser.c:1712
+#, c-format
+msgid "The value <%s> was not recognized, %s %s the only acceptable value."
+msgstr "The value <%s> was not recognized, %s %s the only acceptable value."
+
+#: request_parser.c:1715
+msgid "is"
+msgstr "is"
+
+#: request_parser.c:1727
+msgid "are"
+msgstr "are"
+
+#: response_print.c:1630
+#, c-format
+msgid "The service \"%s\" ran successfully."
+msgstr "The service \"%s\" ran successfully."
+
+#: response_print.c:1638
+#, c-format
+msgid ""
+"The ZOO service \"%s\" is currently running. Please reload this document to "
+"get the up-to-date status of the service."
+msgstr ""
+"The ZOO service \"%s\" is currently running. Please reload this document to "
+"get the up-to-date status of the service."
+
+#: response_print.c:1644
+#, fuzzy, c-format
+msgid ""
+"The service \"%s\" was accepted by the ZOO-Kernel and is running as a "
+"background task. Please access the URL in the statusLocation attribute "
+"provided in this document to get the up-to-date status and results."
+msgstr ""
+"The service \"%s\" was accepted by the ZOO kernel and is running as a "
+"background task. Please access the URL in the statusLocation attribute "
+"provided in this document to get the up-to-date status and results."
+
+#: response_print.c:1661
+msgid "No more information available"
+msgstr "No more information available"
+
+#: response_print.c:1668
+#, c-format
+msgid "error code not know : %i\n"
+msgstr "error code not know : %i\n"
+
+#: response_print.c:1760
+msgid "Lock failed."
+msgstr "Lock failed."
+
+#: response_print.c:1773
+#, c-format
+msgid "Unable to create the file \"%s\" for storing the ExecuteResponse."
+msgstr "Unable to create the file \"%s\" for storing the ExecuteResponse."
+
+#: response_print.c:2290
+msgid "No debug message available"
+msgstr "No debug message available"
+
+#: response_print.c:2378
+#, c-format
+msgid "Unable to create the file \"%s\" for storing the session maps."
+msgstr "Unable to create the file \"%s\" for storing the session maps."
+
+#: response_print.c:2394
+msgid ""
+"Unable to run the Service. The message returned back by the Service was the "
+"following: "
+msgstr ""
+"Unable to run the Service. The message returned back by the Service was the "
+"following: "
+
+#: response_print.c:2395
+#, c-format
+msgid ""
+"Unable to run the Service. The message returned back by the Service was the "
+"following: %s"
+msgstr ""
+"Unable to run the Service. The message returned back by the Service was the "
+"following: %s"
+
+#: response_print.c:2398 response_print.c:2399
+msgid ""
+"Unable to run the Service. No more information was returned back by the "
+"Service."
+msgstr ""
+"Unable to run the Service. No more information was returned back by the "
+"Service."
+
+#: response_print.c:2486
+#, c-format
+msgid "Unable to create the file \"%s\" for storing the %s final result."
+msgstr "Unable to create the file \"%s\" for storing the %s final result."
+
+#: response_print.c:2572
+#, c-format
+msgid ""
+"Wrong RawDataOutput parameter: unable to fetch any result for the given "
+"parameter name: \"%s\"."
+msgstr ""
+"Wrong RawDataOutput parameter: unable to fetch any result for the given "
+"parameter name: \"%s\"."
+
+#: server_internal.c:869 server_internal.c:946
+msgid ""
+"The JobID from the request does not match any of the Jobs running on this "
+"server"
+msgstr ""
+"The JobID from the request does not match any of the Jobs running on this "
+"server"
+
+#: server_internal.c:875 server_internal.c:907
+msgid "The result for the requested JobID has not yet been generated. "
+msgstr "The result for the requested JobID has not yet been generated. "
+
+#: server_internal.c:988
+msgid "The job cannot be removed, a file cannot be removed"
+msgstr "The job cannot be removed, a file cannot be removed"
+
+#: server_internal.c:1063
+msgid "Unable to open the registry directory."
+msgstr ""
+
+#: server_internal.c:1082
+msgid "Unable to allocate memory."
+msgstr "Unable to allocate memory."
+
+#: server_internal.c:1093 zoo_service_loader.c:276 zoo_service_loader.c:1384
+#: zoo_service_loader.c:1427
+#, c-format
+msgid "Unable to parse the ZCFG file: %s (%s)"
+msgstr "Unable to parse the ZCFG file: %s (%s)"
+
+#: server_internal.c:1096 zoo_service_loader.c:279 zoo_service_loader.c:1389
+#: zoo_service_loader.c:1431
+#, c-format
+msgid "Unable to parse the ZCFG file: %s."
+msgstr "Unable to parse the ZCFG file: %s."
+
+#: service_internal_ms.c:136
+msgid "Unable to find any mapserverAddress defined in the main.cfg file"
+msgstr "Unable to find any mapserverAddress defined in the main.cfg file"
+
+#: service_internal_php.c:227
+#, c-format
+msgid "Unable to load the PHP file %s"
+msgstr "Unable to load the PHP file %s"
+
+#: service_internal_python.c:316
+#, c-format
+msgid "Python module %s cannot be loaded. Message: %s\n"
+msgstr "Python module %s cannot be loaded. Message: %s\n"
+
+#: service_internal_python.c:355
+#, c-format
+msgid ""
+"%s\n"
+"Unable to run your python process properly. Please check the following "
+"messages : %s"
+msgstr ""
+"%s\n"
+"Unable to run your python process properly. Please check the following "
+"messages : %s"
+
+#: service_internal_python.c:361
+#, c-format
+msgid ""
+"%s \n"
+" Unable to run your python process properly. Unable to provide any futher "
+"informations."
+msgstr ""
+"%s \n"
+" Unable to run your python process properly. Unable to provide any futher "
+"informations."
+
+#: zoo_service_loader.c:352
+#, c-format
+msgid "ZOO Kernel failed to process your request, receiving signal %d = %s"
+msgstr "ZOO Kernel failed to process your request, receiving signal %d = %s"
+
+#: zoo_service_loader.c:527
+#, c-format
+msgid "Error occured while running the %s function: %s"
+msgstr "Error occured while running the %s function: %s"
+
+#: zoo_service_loader.c:578
+#, c-format
+msgid "Unable to load C Library %s"
+msgstr "Unable to load C Library %s"
+
+#: zoo_service_loader.c:672
+#, c-format
+msgid ""
+"Programming Language (%s) set in ZCFG file is not currently supported by ZOO "
+"Kernel.\n"
+msgstr ""
+"Programming Language (%s) set in ZCFG file is not currently supported by ZOO "
+"Kernel.\n"
+
+#: zoo_service_loader.c:737
+msgid "Unable to cache HTTP POST Execute request."
+msgstr "Unable to cache HTTP POST Execute request."
+
+#: zoo_service_loader.c:895
+msgid "Unable to load the main.cfg file."
+msgstr "Unable to load the main.cfg file."
+
+#: zoo_service_loader.c:940
+#, c-format
+msgid "The value %s is not supported for the <language> parameter"
+msgstr "The value %s is not supported for the <language> parameter"
+
+#: zoo_service_loader.c:1238
+#, fuzzy
+msgid "The specified path does not exist."
+msgstr "The specified path path does not exist."
+
+#: zoo_service_loader.c:1303
+#, c-format
+msgid ""
+"Unable to parse the ZCFG file for the following ZOO-Service: %s. Message: %s"
+msgstr ""
+"Unable to parse the ZCFG file for the following ZOO-Service: %s. Message: %s"
+
+#: zoo_service_loader.c:1308
+#, c-format
+msgid "Unable to parse the ZCFG file for the following ZOO-Service: %s."
+msgstr "Unable to parse the ZCFG file for the following ZOO-Service: %s."
+
+#: zoo_service_loader.c:1534
+msgid "Unable to run Execute request using the GET HTTP method"
+msgstr "Unable to run Execute request using the GET HTTP method"
+
+#: zoo_service_loader.c:1606
+#, c-format
+msgid ""
+"The value for <identifier> seems to be wrong (%s). Please specify one of the "
+"processes in the list returned by a GetCapabilities request."
+msgstr ""
+"The value for <identifier> seems to be wrong (%s). Please specify one of the "
+"processes in the list returned by a GetCapabilities request."
+
+#: zoo_service_loader.c:1733
+msgid ""
+"The status parameter cannot be set to true if storeExecuteResponse is set to "
+"false. Please modify your request parameters."
+msgstr ""
+"The status parameter cannot be set to true if storeExecuteResponse is set to "
+"false. Please modify your request parameters."
+
+#: zoo_service_loader.c:1761
+msgid "The process does not permit the desired execution mode."
+msgstr "The process does not permit the desired execution mode."
+
+#: zoo_service_loader.c:1837
+msgid "No message provided"
+msgstr "No message provided"
+
+#: zoo_service_loader.c:1995
+msgid "Initializing"
+msgstr "Initializing"
+
+#: zoo_service_loader.c:2142
+msgid "Unable to run the child process properly"
+msgstr "Unable to run the child process properly"
diff --git a/zoo-project/zoo-kernel/locale/po/messages.po.orig b/zoo-project/zoo-kernel/locale/po/messages.po.orig
new file mode 100644
index 0000000..0bfccb6
--- /dev/null
+++ b/zoo-project/zoo-kernel/locale/po/messages.po.orig
@@ -0,0 +1,364 @@
+# ZOO-Kernel Internationalization.
+# Copyright (C) 2015 GeoLabs SARL
+# This file is distributed under the same license as the PACKAGE package.
+# Gerald Fenoy <gerald.fenoy at geolabs.fr>, 2015.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: ZOO-Kernel Internationalization\n"
+"Report-Msgid-Bugs-To: zoo-discuss at lists.osgeo.org\n"
+"POT-Creation-Date: 2015-07-01 22:23+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: caching.c:217 caching.c:235 caching.c:356 request_parser.c:214
+#: request_parser.c:225 request_parser.c:262 request_parser.c:441
+#: request_parser.c:537 request_parser.c:562 request_parser.c:665
+#: request_parser.c:782 request_parser.c:1112 request_parser.c:1204
+#: server_internal.c:1077 zcfg2yaml.c:38 zoo_service_loader.c:259
+#: zoo_service_loader.c:880 zoo_service_loader.c:1363
+#: zoo_service_loader.c:1559 server_internal.c:1082
+msgid "Unable to allocate memory."
+msgstr "Unable to allocate memory."
+
+#: caching.c:344
+msgid "Unable to download the file."
+msgstr "Unable to download the file."
+
+#: request_parser.c:92
+#, c-format
+msgid "The maximum allowed occurrences for <%s> (%i) was exceeded."
+msgstr "The maximum allowed occurrences for <%s> (%i) was exceeded."
+
+#: request_parser.c:113
+#, c-format
+msgid "ZOO-Kernel was unable to load your data for %s position %s."
+msgstr "ZOO-Kernel was unable to load your data for %s position %s."
+
+#: request_parser.c:124
+#, c-format
+msgid "The maximum allowed occurrences for <%s> is one."
+msgstr "The maximum allowed occurrences for <%s> is one."
+
+#: request_parser.c:315
+#, c-format
+msgid "Unable to find a valid protocol to download the remote file %s"
+msgstr "Unable to find a valid protocol to download the remote file %s"
+
+#: request_parser.c:403 request_parser.c:414
+msgid "Unable to allocate memory"
+msgstr "Unable to allocate memory"
+
+#: request_parser.c:613
+msgid "Unable to add a request in the queue."
+msgstr "Unable to add a request in the queue."
+
+#: request_parser.c:1021
+msgid "Unable to append maps to maps."
+msgstr "Unable to append maps to maps."
+
+#: request_parser.c:1291
+msgid "Duplicate <Output> elements in WPS Execute request"
+msgstr "Duplicate <Output> elements in WPS Execute request"
+
+#: request_parser.c:1487
+#, c-format
+msgid ""
+"The <%s> parameter has a size limit (%s MB) defined in the ZOO "
+"ServicesProvider configuration file, but the reference you provided exceeds "
+"this limit (%f MB)."
+msgstr ""
+"The <%s> parameter has a size limit (%s MB) defined in the ZOO "
+"ServicesProvider configuration file, but the reference you provided exceeds "
+"this limit (%f MB)."
+
+#: request_parser.c:1519
+#, c-format
+msgid ""
+"The <%s> argument was not specified in DataInputs but is required according "
+"to the ZOO ServicesProvider configuration file."
+msgstr ""
+"The <%s> argument was not specified in DataInputs but is required according "
+"to the ZOO ServicesProvider configuration file."
+
+#: request_parser.c:1545
+#, c-format
+msgid ""
+"The <%s> argument specified as %s identifier was not recognized (not defined "
+"in the ZOO Configuration File)."
+msgstr ""
+"The <%s> argument specified as %s identifier was not recognized (not defined "
+"in the ZOO Configuration File)."
+
+#: request_parser.c:1663
+#, c-format
+msgid "Mandatory parameter <%s> was not specified"
+msgstr "Mandatory parameter <%s> was not specified"
+
+#: request_parser.c:1712
+#, c-format
+msgid "The value <%s> was not recognized, %s %s the only acceptable value."
+msgstr "The value <%s> was not recognized, %s %s the only acceptable value."
+
+#: request_parser.c:1715
+msgid "is"
+msgstr "is"
+
+#: request_parser.c:1727
+msgid "are"
+msgstr "are"
+
+#: response_print.c:1628
+#, c-format
+msgid "The service \"%s\" ran successfully."
+msgstr "The service \"%s\" ran successfully."
+
+#: response_print.c:1636
+#, c-format
+msgid ""
+"The ZOO service \"%s\" is currently running. Please reload this document to "
+"get the up-to-date status of the service."
+msgstr ""
+"The ZOO service \"%s\" is currently running. Please reload this document to "
+"get the up-to-date status of the service."
+
+#: response_print.c:1642
+#, c-format
+msgid ""
+"The service \"%s\" was accepted by the ZOO kernel and is running as a "
+"background task. Please access the URL in the statusLocation attribute "
+"provided in this document to get the up-to-date status and results."
+msgstr ""
+"The service \"%s\" was accepted by the ZOO kernel and is running as a "
+"background task. Please access the URL in the statusLocation attribute "
+"provided in this document to get the up-to-date status and results."
+
+#: response_print.c:1659
+msgid "No more information available"
+msgstr "No more information available"
+
+#: response_print.c:1666
+#, c-format
+msgid "error code not know : %i\n"
+msgstr "error code not know : %i\n"
+
+#: response_print.c:1758
+msgid "Lock failed."
+msgstr "Lock failed."
+
+#: response_print.c:1771
+#, c-format
+msgid "Unable to create the file \"%s\" for storing the ExecuteResponse."
+msgstr "Unable to create the file \"%s\" for storing the ExecuteResponse."
+
+#: response_print.c:2288
+msgid "No debug message available"
+msgstr "No debug message available"
+
+#: response_print.c:2376
+#, c-format
+msgid "Unable to create the file \"%s\" for storing the session maps."
+msgstr "Unable to create the file \"%s\" for storing the session maps."
+
+#: response_print.c:2392
+msgid ""
+"Unable to run the Service. The message returned back by the Service was the "
+"following: "
+msgstr ""
+"Unable to run the Service. The message returned back by the Service was the "
+"following: "
+
+#: response_print.c:2393
+#, c-format
+msgid ""
+"Unable to run the Service. The message returned back by the Service was the "
+"following: %s"
+msgstr ""
+"Unable to run the Service. The message returned back by the Service was the "
+"following: %s"
+
+#: response_print.c:2396 response_print.c:2397
+msgid ""
+"Unable to run the Service. No more information was returned back by the "
+"Service."
+msgstr ""
+"Unable to run the Service. No more information was returned back by the "
+"Service."
+
+#: response_print.c:2484
+#, c-format
+msgid "Unable to create the file \"%s\" for storing the %s final result."
+msgstr "Unable to create the file \"%s\" for storing the %s final result."
+
+#: response_print.c:2570
+#, c-format
+msgid ""
+"Wrong RawDataOutput parameter: unable to fetch any result for the given "
+"parameter name: \"%s\"."
+msgstr ""
+"Wrong RawDataOutput parameter: unable to fetch any result for the given "
+"parameter name: \"%s\"."
+
+#: server_internal.c:869 server_internal.c:946
+msgid ""
+"The JobID from the request does not match any of the Jobs running on this "
+"server"
+msgstr ""
+"The JobID from the request does not match any of the Jobs running on this "
+"server"
+
+#: server_internal.c:875 server_internal.c:907
+msgid "The result for the requested JobID has not yet been generated. "
+msgstr "The result for the requested JobID has not yet been generated. "
+
+#: server_internal.c:988
+msgid "The job cannot be removed, a file cannot be removed"
+msgstr "The job cannot be removed, a file cannot be removed"
+
+#: server_internal.c:1088 zoo_service_loader.c:276 zoo_service_loader.c:1384
+#: zoo_service_loader.c:1427 server_internal.c:1093
+#, c-format
+msgid "Unable to parse the ZCFG file: %s (%s)"
+msgstr "Unable to parse the ZCFG file: %s (%s)"
+
+#: server_internal.c:1091 zoo_service_loader.c:279 zoo_service_loader.c:1389
+#: zoo_service_loader.c:1431 server_internal.c:1096
+#, c-format
+msgid "Unable to parse the ZCFG file: %s."
+msgstr "Unable to parse the ZCFG file: %s."
+
+#: service_internal_ms.c:136
+msgid "Unable to find any mapserverAddress defined in the main.cfg file"
+msgstr "Unable to find any mapserverAddress defined in the main.cfg file"
+
+#: service_internal_php.c:227
+#, c-format
+msgid "Unable to load the PHP file %s"
+msgstr "Unable to load the PHP file %s"
+
+#: service_internal_python.c:316
+#, c-format
+msgid "Python module %s cannot be loaded. Message: %s\n"
+msgstr "Python module %s cannot be loaded. Message: %s\n"
+
+#: service_internal_python.c:355
+#, c-format
+msgid ""
+"%s\n"
+"Unable to run your python process properly. Please check the following "
+"messages : %s"
+msgstr ""
+"%s\n"
+"Unable to run your python process properly. Please check the following "
+"messages : %s"
+
+#: service_internal_python.c:361
+#, c-format
+msgid ""
+"%s \n"
+" Unable to run your python process properly. Unable to provide any futher "
+"informations."
+msgstr ""
+"%s \n"
+" Unable to run your python process properly. Unable to provide any futher "
+"informations."
+
+#: zoo_service_loader.c:352
+#, c-format
+msgid "ZOO Kernel failed to process your request, receiving signal %d = %s"
+msgstr "ZOO Kernel failed to process your request, receiving signal %d = %s"
+
+#: zoo_service_loader.c:527
+#, c-format
+msgid "Error occured while running the %s function: %s"
+msgstr "Error occured while running the %s function: %s"
+
+#: zoo_service_loader.c:578
+#, c-format
+msgid "Unable to load C Library %s"
+msgstr "Unable to load C Library %s"
+
+#: zoo_service_loader.c:672
+#, c-format
+msgid ""
+"Programming Language (%s) set in ZCFG file is not currently supported by ZOO "
+"Kernel.\n"
+msgstr ""
+"Programming Language (%s) set in ZCFG file is not currently supported by ZOO "
+"Kernel.\n"
+
+#: zoo_service_loader.c:737
+msgid "Unable to cache HTTP POST Execute request."
+msgstr "Unable to cache HTTP POST Execute request."
+
+#: zoo_service_loader.c:895
+msgid "Unable to load the main.cfg file."
+msgstr "Unable to load the main.cfg file."
+
+#: zoo_service_loader.c:940
+#, c-format
+msgid "The value %s is not supported for the <language> parameter"
+msgstr "The value %s is not supported for the <language> parameter"
+
+#: zoo_service_loader.c:1238
+msgid "The specified path path does not exist."
+msgstr "The specified path path does not exist."
+
+#: zoo_service_loader.c:1303
+#, c-format
+msgid ""
+"Unable to parse the ZCFG file for the following ZOO-Service: %s. Message: %s"
+msgstr ""
+"Unable to parse the ZCFG file for the following ZOO-Service: %s. Message: %s"
+
+#: zoo_service_loader.c:1308
+#, c-format
+msgid "Unable to parse the ZCFG file for the following ZOO-Service: %s."
+msgstr "Unable to parse the ZCFG file for the following ZOO-Service: %s."
+
+#: zoo_service_loader.c:1534
+msgid "Unable to run Execute request using the GET HTTP method"
+msgstr "Unable to run Execute request using the GET HTTP method"
+
+#: zoo_service_loader.c:1606
+#, c-format
+msgid ""
+"The value for <identifier> seems to be wrong (%s). Please specify one of the "
+"processes in the list returned by a GetCapabilities request."
+msgstr ""
+"The value for <identifier> seems to be wrong (%s). Please specify one of the "
+"processes in the list returned by a GetCapabilities request."
+
+#: zoo_service_loader.c:1733
+msgid ""
+"The status parameter cannot be set to true if storeExecuteResponse is set to "
+"false. Please modify your request parameters."
+msgstr ""
+"The status parameter cannot be set to true if storeExecuteResponse is set to "
+"false. Please modify your request parameters."
+
+#: zoo_service_loader.c:1761
+msgid "The process does not permit the desired execution mode."
+msgstr "The process does not permit the desired execution mode."
+
+#: zoo_service_loader.c:1837
+msgid "No message provided"
+msgstr "No message provided"
+
+#: zoo_service_loader.c:1995
+msgid "Initializing"
+msgstr "Initializing"
+
+#: zoo_service_loader.c:2142
+msgid "Unable to run the child process properly"
+msgstr "Unable to run the child process properly"
+
+#: server_internal.c:1063
+msgid "Unable to open the registry directory."
+msgstr ""
diff --git a/zoo-project/zoo-kernel/locale/po/messages.po.save b/zoo-project/zoo-kernel/locale/po/messages.po.save
new file mode 100644
index 0000000..32951ab
--- /dev/null
+++ b/zoo-project/zoo-kernel/locale/po/messages.po.save
@@ -0,0 +1,328 @@
+# ZOO-Kernel Internationalization.
+# Copyright (C) 2015 GeoLabs SARL
+# This file is distributed under the same license as the PACKAGE package.
+# Gerald Fenoy <gerald.fenoy at geolabs.fr>, 2015.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ZOO-Kernel 1.5.0\n"
+"Report-Msgid-Bugs-To: zoo-discuss at lists.osgeo.org\n"
+"POT-Creation-Date: 2015-07-02 17:38+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: caching.c:217 caching.c:235 caching.c:356 request_parser.c:214
+#: request_parser.c:225 request_parser.c:262 request_parser.c:403
+#: request_parser.c:414 request_parser.c:441 request_parser.c:537
+#: request_parser.c:562 request_parser.c:665 request_parser.c:782
+#: request_parser.c:1112 request_parser.c:1204 zcfg2yaml.c:38
+#: zoo_service_loader.c:259 zoo_service_loader.c:880 zoo_service_loader.c:1363
+#: zoo_service_loader.c:1559
+msgid "Unable to allocate memory"
+msgstr ""
+
+#: caching.c:344
+msgid "Unable to download the file."
+msgstr ""
+
+#: request_parser.c:92
+#, c-format
+msgid "The maximum allowed occurrences for <%s> (%i) was exceeded."
+msgstr ""
+
+#: request_parser.c:113
+#, c-format
+msgid "ZOO-Kernel was unable to load your data for %s position %s."
+msgstr ""
+
+#: request_parser.c:124
+#, c-format
+msgid "The maximum allowed occurrences for <%s> is one."
+msgstr ""
+
+#: request_parser.c:315
+#, c-format
+msgid "Unable to find a valid protocol to download the remote file %s"
+msgstr ""
+
+#: request_parser.c:613
+msgid "Unable to add a request in the queue."
+msgstr ""
+
+#: request_parser.c:1021
+msgid "Unable to append maps to maps."
+msgstr ""
+
+#: request_parser.c:1291
+msgid "Duplicate <Output> elements in WPS Execute request"
+msgstr ""
+
+#: request_parser.c:1487
+#, c-format
+msgid ""
+"The <%s> parameter has a size limit (%s MB) defined in the ZOO "
+"ServicesProvider configuration file, but the reference you provided exceeds "
+"this limit (%f MB)."
+msgstr ""
+
+#: request_parser.c:1519
+#, c-format
+msgid ""
+"The <%s> argument was not specified in DataInputs but is required according "
+"to the ZOO ServicesProvider configuration file."
+msgstr ""
+
+#: request_parser.c:1545
+#, c-format
+msgid ""
+"The <%s> argument specified as %s identifier was not recognized (not defined "
+"in the ZOO Configuration File)."
+msgstr ""
+
+#: request_parser.c:1663
+#, c-format
+msgid "Mandatory parameter <%s> was not specified"
+msgstr ""
+
+#: request_parser.c:1712
+#, c-format
+msgid "The value <%s> was not recognized, %s %s the only acceptable value."
+msgstr ""
+
+#: request_parser.c:1715
+msgid "is"
+msgstr ""
+
+#: request_parser.c:1727
+msgid "are"
+msgstr ""
+
+#: response_print.c:1630
+#, c-format
+msgid "The service \"%s\" ran successfully."
+msgstr ""
+
+#: response_print.c:1638
+#, c-format
+msgid ""
+"The ZOO service \"%s\" is currently running. Please reload this document to "
+"get the up-to-date status of the service."
+msgstr ""
+
+#: response_print.c:1644
+#, c-format
+msgid ""
+"The service \"%s\" was accepted by the ZOO kernel and is running as a "
+"background task. Please access the URL in the statusLocation attribute "
+"provided in this document to get the up-to-date status and results."
+msgstr ""
+
+#: response_print.c:1661
+msgid "No more information available"
+msgstr ""
+
+#: response_print.c:1668
+#, c-format
+msgid "error code not know : %i\n"
+msgstr ""
+
+#: response_print.c:1760
+msgid "Lock failed."
+msgstr ""
+
+#: response_print.c:1773
+#, c-format
+msgid "Unable to create the file \"%s\" for storing the ExecuteResponse."
+msgstr ""
+
+#: response_print.c:2290
+msgid "No debug message available"
+msgstr ""
+
+#: response_print.c:2378
+#, c-format
+msgid "Unable to create the file \"%s\" for storing the session maps."
+msgstr ""
+
+#: response_print.c:2394
+msgid ""
+"Unable to run the Service. The message returned back by the Service was the "
+"following: "
+msgstr ""
+
+#: response_print.c:2395
+#, c-format
+msgid ""
+"Unable to run the Service. The message returned back by the Service was the "
+"following: %s"
+msgstr ""
+
+#: response_print.c:2398 response_print.c:2399
+msgid ""
+"Unable to run the Service. No more information was returned back by the "
+"Service."
+msgstr ""
+
+#: response_print.c:2486
+#, c-format
+msgid "Unable to create the file \"%s\" for storing the %s final result."
+msgstr ""
+
+#: response_print.c:2572
+#, c-format
+msgid ""
+"Wrong RawDataOutput parameter: unable to fetch any result for the given "
+"parameter name: \"%s\"."
+msgstr ""
+
+#: server_internal.c:869 server_internal.c:946
+msgid ""
+"The JobID from the request does not match any of the Jobs running on this "
+"server"
+msgstr ""
+
+#: server_internal.c:875 server_internal.c:907
+msgid "The result for the requested JobID has not yet been generated. "
+msgstr ""
+
+#: server_internal.c:988
+msgid "The job cannot be removed, a file cannot be removed"
+msgstr ""
+
+#: server_internal.c:1063
+msgid "Unable to open the registry directory."
+msgstr ""
+
+#: server_internal.c:1082
+msgid "Unable to allocate memory."
+msgstr ""
+
+#: server_internal.c:1093 zoo_service_loader.c:276 zoo_service_loader.c:1384
+#: zoo_service_loader.c:1427
+#, c-format
+msgid "Unable to parse the ZCFG file: %s (%s)"
+msgstr ""
+
+#: server_internal.c:1096 zoo_service_loader.c:279 zoo_service_loader.c:1389
+#: zoo_service_loader.c:1431
+#, c-format
+msgid "Unable to parse the ZCFG file: %s."
+msgstr ""
+
+#: service_internal_ms.c:136
+msgid "Unable to find any mapserverAddress defined in the main.cfg file"
+msgstr ""
+
+#: service_internal_php.c:227
+#, c-format
+msgid "Unable to load the PHP file %s"
+msgstr ""
+
+#: service_internal_python.c:316
+#, c-format
+msgid "Python module %s cannot be loaded. Message: %s\n"
+msgstr ""
+
+#: service_internal_python.c:355
+#, c-format
+msgid ""
+"%s\n"
+"Unable to run your python process properly. Please check the following "
+"messages : %s"
+msgstr ""
+
+#: service_internal_python.c:361
+#, c-format
+msgid ""
+"%s \n"
+" Unable to run your python process properly. Unable to provide any futher "
+"informations."
+msgstr ""
+
+#: zoo_service_loader.c:352
+#, c-format
+msgid "ZOO Kernel failed to process your request, receiving signal %d = %s"
+msgstr ""
+
+#: zoo_service_loader.c:527
+#, c-format
+msgid "Error occured while running the %s function: %s"
+msgstr ""
+
+#: zoo_service_loader.c:578
+#, c-format
+msgid "Unable to load C Library %s"
+msgstr ""
+
+#: zoo_service_loader.c:672
+#, c-format
+msgid ""
+"Programming Language (%s) set in ZCFG file is not currently supported by ZOO "
+"Kernel.\n"
+msgstr ""
+
+#: zoo_service_loader.c:737
+msgid "Unable to cache HTTP POST Execute request."
+msgstr ""
+
+#: zoo_service_loader.c:895
+msgid "Unable to load the main.cfg file."
+msgstr ""
+
+#: zoo_service_loader.c:940
+#, c-format
+msgid "The value %s is not supported for the <language> parameter"
+msgstr ""
+
+#: zoo_service_loader.c:1238
+msgid "The specified path does not exist."
+msgstr ""
+
+#: zoo_service_loader.c:1303
+#, c-format
+msgid ""
+"Unable to parse the ZCFG file for the following ZOO-Service: %s. Message: %s"
+msgstr ""
+
+#: zoo_service_loader.c:1308
+#, c-format
+msgid "Unable to parse the ZCFG file for the following ZOO-Service: %s."
+msgstr ""
+
+#: zoo_service_loader.c:1534
+msgid "Unable to run Execute request using the GET HTTP method"
+msgstr ""
+
+#: zoo_service_loader.c:1606
+#, c-format
+msgid ""
+"The value for <identifier> seems to be wrong (%s). Please specify one of the "
+"processes in the list returned by a GetCapabilities request."
+msgstr ""
+
+#: zoo_service_loader.c:1733
+msgid ""
+"The status parameter cannot be set to true if storeExecuteResponse is set to "
+"false. Please modify your request parameters."
+msgstr ""
+
+#: zoo_service_loader.c:1761
+msgid "The process does not permit the desired execution mode."
+msgstr ""
+
+#: zoo_service_loader.c:1837
+msgid "No message provided"
+msgstr ""
+
+#: zoo_service_loader.c:1995
+msgid "Initializing"
+msgstr ""
+
+#: zoo_service_loader.c:2142
+msgid "Unable to run the child process properly"
+msgstr ""
diff --git a/zoo-project/zoo-kernel/locale/po/new.pot b/zoo-project/zoo-kernel/locale/po/new.pot
new file mode 100644
index 0000000..cdc1413
--- /dev/null
+++ b/zoo-project/zoo-kernel/locale/po/new.pot
@@ -0,0 +1,329 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL at ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2015-07-02 18:06+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: caching.c:217 caching.c:235 caching.c:356 request_parser.c:214
+#: request_parser.c:225 request_parser.c:262 request_parser.c:403
+#: request_parser.c:414 request_parser.c:441 request_parser.c:537
+#: request_parser.c:562 request_parser.c:665 request_parser.c:782
+#: request_parser.c:1112 request_parser.c:1204 zcfg2yaml.c:38
+#: zoo_service_loader.c:259 zoo_service_loader.c:880 zoo_service_loader.c:1363
+#: zoo_service_loader.c:1559
+msgid "Unable to allocate memory"
+msgstr ""
+
+#: caching.c:344
+msgid "Unable to download the file."
+msgstr ""
+
+#: request_parser.c:92
+#, c-format
+msgid "The maximum allowed occurrences for <%s> (%i) was exceeded."
+msgstr ""
+
+#: request_parser.c:113
+#, c-format
+msgid "ZOO-Kernel was unable to load your data for %s position %s."
+msgstr ""
+
+#: request_parser.c:124
+#, c-format
+msgid "The maximum allowed occurrences for <%s> is one."
+msgstr ""
+
+#: request_parser.c:315
+#, c-format
+msgid "Unable to find a valid protocol to download the remote file %s"
+msgstr ""
+
+#: request_parser.c:613
+msgid "Unable to add a request in the queue."
+msgstr ""
+
+#: request_parser.c:1021
+msgid "Unable to append maps to maps."
+msgstr ""
+
+#: request_parser.c:1291
+msgid "Duplicate <Output> elements in WPS Execute request"
+msgstr ""
+
+#: request_parser.c:1487
+#, c-format
+msgid ""
+"The <%s> parameter has a size limit (%s MB) defined in the ZOO "
+"ServicesProvider configuration file, but the reference you provided exceeds "
+"this limit (%f MB)."
+msgstr ""
+
+#: request_parser.c:1519
+#, c-format
+msgid ""
+"The <%s> argument was not specified in DataInputs but is required according "
+"to the ZOO ServicesProvider configuration file."
+msgstr ""
+
+#: request_parser.c:1545
+#, c-format
+msgid ""
+"The <%s> argument specified as %s identifier was not recognized (not defined "
+"in the ZOO Configuration File)."
+msgstr ""
+
+#: request_parser.c:1663
+#, c-format
+msgid "Mandatory parameter <%s> was not specified"
+msgstr ""
+
+#: request_parser.c:1712
+#, c-format
+msgid "The value <%s> was not recognized, %s %s the only acceptable value."
+msgstr ""
+
+#: request_parser.c:1715
+msgid "is"
+msgstr ""
+
+#: request_parser.c:1727
+msgid "are"
+msgstr ""
+
+#: response_print.c:1630
+#, c-format
+msgid "The service \"%s\" ran successfully."
+msgstr ""
+
+#: response_print.c:1638
+#, c-format
+msgid ""
+"The ZOO service \"%s\" is currently running. Please reload this document to "
+"get the up-to-date status of the service."
+msgstr ""
+
+#: response_print.c:1644
+#, c-format
+msgid ""
+"The service \"%s\" was accepted by the ZOO-Kernel and is running as a "
+"background task. Please access the URL in the statusLocation attribute "
+"provided in this document to get the up-to-date status and results."
+msgstr ""
+
+#: response_print.c:1661
+msgid "No more information available"
+msgstr ""
+
+#: response_print.c:1668
+#, c-format
+msgid "error code not know : %i\n"
+msgstr ""
+
+#: response_print.c:1760
+msgid "Lock failed."
+msgstr ""
+
+#: response_print.c:1773
+#, c-format
+msgid "Unable to create the file \"%s\" for storing the ExecuteResponse."
+msgstr ""
+
+#: response_print.c:2290
+msgid "No debug message available"
+msgstr ""
+
+#: response_print.c:2378
+#, c-format
+msgid "Unable to create the file \"%s\" for storing the session maps."
+msgstr ""
+
+#: response_print.c:2394
+msgid ""
+"Unable to run the Service. The message returned back by the Service was the "
+"following: "
+msgstr ""
+
+#: response_print.c:2395
+#, c-format
+msgid ""
+"Unable to run the Service. The message returned back by the Service was the "
+"following: %s"
+msgstr ""
+
+#: response_print.c:2398 response_print.c:2399
+msgid ""
+"Unable to run the Service. No more information was returned back by the "
+"Service."
+msgstr ""
+
+#: response_print.c:2486
+#, c-format
+msgid "Unable to create the file \"%s\" for storing the %s final result."
+msgstr ""
+
+#: response_print.c:2572
+#, c-format
+msgid ""
+"Wrong RawDataOutput parameter: unable to fetch any result for the given "
+"parameter name: \"%s\"."
+msgstr ""
+
+#: server_internal.c:869 server_internal.c:946
+msgid ""
+"The JobID from the request does not match any of the Jobs running on this "
+"server"
+msgstr ""
+
+#: server_internal.c:875 server_internal.c:907
+msgid "The result for the requested JobID has not yet been generated. "
+msgstr ""
+
+#: server_internal.c:988
+msgid "The job cannot be removed, a file cannot be removed"
+msgstr ""
+
+#: server_internal.c:1063
+msgid "Unable to open the registry directory."
+msgstr ""
+
+#: server_internal.c:1082
+msgid "Unable to allocate memory."
+msgstr ""
+
+#: server_internal.c:1093 zoo_service_loader.c:276 zoo_service_loader.c:1384
+#: zoo_service_loader.c:1427
+#, c-format
+msgid "Unable to parse the ZCFG file: %s (%s)"
+msgstr ""
+
+#: server_internal.c:1096 zoo_service_loader.c:279 zoo_service_loader.c:1389
+#: zoo_service_loader.c:1431
+#, c-format
+msgid "Unable to parse the ZCFG file: %s."
+msgstr ""
+
+#: service_internal_ms.c:136
+msgid "Unable to find any mapserverAddress defined in the main.cfg file"
+msgstr ""
+
+#: service_internal_php.c:227
+#, c-format
+msgid "Unable to load the PHP file %s"
+msgstr ""
+
+#: service_internal_python.c:316
+#, c-format
+msgid "Python module %s cannot be loaded. Message: %s\n"
+msgstr ""
+
+#: service_internal_python.c:355
+#, c-format
+msgid ""
+"%s\n"
+"Unable to run your python process properly. Please check the following "
+"messages : %s"
+msgstr ""
+
+#: service_internal_python.c:361
+#, c-format
+msgid ""
+"%s \n"
+" Unable to run your python process properly. Unable to provide any futher "
+"informations."
+msgstr ""
+
+#: zoo_service_loader.c:352
+#, c-format
+msgid "ZOO Kernel failed to process your request, receiving signal %d = %s"
+msgstr ""
+
+#: zoo_service_loader.c:527
+#, c-format
+msgid "Error occured while running the %s function: %s"
+msgstr ""
+
+#: zoo_service_loader.c:578
+#, c-format
+msgid "Unable to load C Library %s"
+msgstr ""
+
+#: zoo_service_loader.c:672
+#, c-format
+msgid ""
+"Programming Language (%s) set in ZCFG file is not currently supported by ZOO "
+"Kernel.\n"
+msgstr ""
+
+#: zoo_service_loader.c:737
+msgid "Unable to cache HTTP POST Execute request."
+msgstr ""
+
+#: zoo_service_loader.c:895
+msgid "Unable to load the main.cfg file."
+msgstr ""
+
+#: zoo_service_loader.c:940
+#, c-format
+msgid "The value %s is not supported for the <language> parameter"
+msgstr ""
+
+#: zoo_service_loader.c:1238
+msgid "The specified path does not exist."
+msgstr ""
+
+#: zoo_service_loader.c:1303
+#, c-format
+msgid ""
+"Unable to parse the ZCFG file for the following ZOO-Service: %s. Message: %s"
+msgstr ""
+
+#: zoo_service_loader.c:1308
+#, c-format
+msgid "Unable to parse the ZCFG file for the following ZOO-Service: %s."
+msgstr ""
+
+#: zoo_service_loader.c:1534
+msgid "Unable to run Execute request using the GET HTTP method"
+msgstr ""
+
+#: zoo_service_loader.c:1606
+#, c-format
+msgid ""
+"The value for <identifier> seems to be wrong (%s). Please specify one of the "
+"processes in the list returned by a GetCapabilities request."
+msgstr ""
+
+#: zoo_service_loader.c:1733
+msgid ""
+"The status parameter cannot be set to true if storeExecuteResponse is set to "
+"false. Please modify your request parameters."
+msgstr ""
+
+#: zoo_service_loader.c:1761
+msgid "The process does not permit the desired execution mode."
+msgstr ""
+
+#: zoo_service_loader.c:1837
+msgid "No message provided"
+msgstr ""
+
+#: zoo_service_loader.c:1995
+msgid "Initializing"
+msgstr ""
+
+#: zoo_service_loader.c:2142
+msgid "Unable to run the child process properly"
+msgstr ""
diff --git a/zoo-project/zoo-kernel/main.cfg b/zoo-project/zoo-kernel/main.cfg
new file mode 100644
index 0000000..8386482
--- /dev/null
+++ b/zoo-project/zoo-kernel/main.cfg
@@ -0,0 +1,32 @@
+[main]
+encoding = utf-8
+version = 1.0.0
+serverAddress = http://www.zoo-project.org/zoo/
+lang = fr-FR,en-CA,en-US
+tmpPath=/tmp/
+tmpUrl = ../mpPathRelativeToServerAdress/
+dataPath = /tmp/
+cacheDir = /tmp/
+
+[identification]
+title = The Zoo WPS Development Server
+abstract = Development version of ZooWPS. See http://www.zoo-project.org
+fees = None
+accessConstraints = none
+keywords = WPS,GIS,buffer
+
+[provider]
+providerName=ZOO Project
+providerSite=http://www.zoo-project.org
+individualName=Gerald FENOY
+positionName=Developer
+role=Dev
+addressDeliveryPoint=1280, avenue des Platanes
+addressCity=Lattes
+addressAdministrativeArea=False
+addressPostalCode=34970
+addressCountry=fr
+addressElectronicMailAddress=gerald at geolabs.fr
+phoneVoice=False
+phoneFacsimile=False
+
diff --git a/zoo-project/zoo-kernel/main_conf_read.l b/zoo-project/zoo-kernel/main_conf_read.l
new file mode 100644
index 0000000..da3ed46
--- /dev/null
+++ b/zoo-project/zoo-kernel/main_conf_read.l
@@ -0,0 +1,65 @@
+/*
+ * Zoo main configuration file parser
+ *
+ * Author : Gérald FENOY
+ *
+ * Copyright (c) 209-2015 GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+%option yylineno
+
+%{
+
+#include <string.h>
+#include "main_conf_read.tab.h"
+static int affichetrace = 0 ;
+
+%}
+
+attname	[a-zA-Z0-9_\-:]+
+
+attvalue1	[%\*,;@a-zA-Z0-9_\-.:" "\"\'/\\\(\)\+\x41-\xff?&=]+
+
+whitesp                      [ ]
+newline                 [\r\n]|[\n]
+
+%x DANSBALISE HORSBALISE PAIRSTART
+
+%%
+
+"\n" {if (affichetrace==1) printf ("\n\nNEWLINE\n") ; return NEWLINE;}
+
+{newline}+{whitesp}*			{if (affichetrace==1) printf ("\n\nNEWLINE 1\n") ; return NEWLINE;}
+
+<INITIAL,HORSBALISE>"["{attname}"]"             {if (affichetrace==1) printf ("\n\nANID:%s\n",yytext); crlval.chaine=yytext;crlval.chaine[strlen(crlval.chaine)-1]=0;crlval.chaine+=1;return ANID; }
+
+<INITIAL,HORSBALISE>{attname}             {if (affichetrace==1) printf ("\n\nATT_NAME:%s\n",yytext); crlval.chaine=yytext; return SPAIR; }
+
+<PAIRSTART,HORSBALISE>{attvalue1}             {if (affichetrace==1) printf ("\n\nATT_VALUE:%s\n",yytext);crlval.chaine=yytext;BEGIN(INITIAL);return EPAIR;}
+
+<PAIRSTART,INITIAL,HORSBALISE>{whitesp}*"="{whitesp}*             {BEGIN(PAIRSTART);}
+
+<PAIRSTART,INITIAL,HORSBALISE,DANSBALISE>{newline}+{whitesp}*			{if (affichetrace==1) printf ("\n\nNEWLINE 2\n") ; BEGIN(INITIAL); return NEWLINE;}
+
+%%
+
+
+int crwrap()
+{return 1;}
diff --git a/zoo-project/zoo-kernel/main_conf_read.y b/zoo-project/zoo-kernel/main_conf_read.y
new file mode 100644
index 0000000..b0deda0
--- /dev/null
+++ b/zoo-project/zoo-kernel/main_conf_read.y
@@ -0,0 +1,175 @@
+/*
+ * Zoo main configuration file parser
+ *
+ * Author : Gérald FENOY
+ *
+ * Copyright (c) 209-2015 GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+%{
+#include <service.h>
+
+static maps* my_maps=NULL;
+static maps* current_maps=NULL;
+static map* current_content=NULL;
+static char* curr_key;
+static int debug=0;
+
+extern void crerror(const char *s);
+
+void usage(void) ;
+
+extern int crdebug;
+
+extern char crtext[];
+
+extern int crlineno;
+
+extern FILE* crin;
+
+extern int crlex(void);
+extern int crlex_destroy(void);
+
+%}
+
+%union { char* s;char* chaine; char* key;char* val;}
+
+%token <s> ID
+%token <s> CHAINE
+
+%token PAIR SPAIR EPAIR EPAIRS ANID
+%type <chaine> PAIR
+%type <chaine> EPAIRS
+%type <chaine> EPAIR
+%type <chaine> SPAIR
+
+%token WHITESPACE NEWLINE
+
+%type <s> ANID
+
+%%
+
+document
+ : miscetoile miscetoile {}
+ | contentetoile processid contentetoile document {}
+ ;
+
+miscetoile
+ : {}
+ ;
+
+Attributeetoile
+ : Attributeetoile  {}
+ | 	                          {/* Epsilon */}
+ ;
+
+contentetoile
+: contentetoile NEWLINE {}
+ | contentetoile pair {}
+ | {/* Epsilon */}
+ ;
+
+pair: PAIR {curr_key=zStrdup($1);}
+| EPAIR {
+  if(current_content==NULL) 
+    current_content=createMap(curr_key,$1);
+  else{ 
+    addToMap(current_content,curr_key,$1);
+  }
+  if(debug){ 
+    printf("EPAIR FOUND !! \n"); 
+    printf("[%s=>%s]\n",curr_key,$1);
+  }
+  free(curr_key);
+  }
+| SPAIR  {curr_key=zStrdup($1);if(debug) printf("SPAIR FOUND !!\n"); }
+ ;
+
+
+processid
+: ANID  {
+   if(current_maps->name!=NULL){
+     addMapToMap(&current_maps->content,current_content);
+     freeMap(&current_content);
+     free(current_content);
+     current_maps->next=NULL;
+     current_maps->next=(maps*)malloc(MAPS_SIZE);
+     current_maps->next->name=zStrdup($1);
+     current_maps->next->content=NULL;
+     current_maps->next->next=NULL;
+     current_maps=current_maps->next;
+     current_content=current_maps->content;
+   }
+   else{
+     current_maps->name=(char*)malloc((strlen($1)+1)*sizeof(char));
+     snprintf(current_maps->name,(strlen($1)+1),"%s",$1);
+     current_maps->content=NULL;
+     current_maps->next=NULL;
+     current_content=NULL;
+   }
+ }
+ ;
+
+%%
+
+/**
+ * Print on stderr the message and the line number of the error which occured.
+ *
+ * @param s the error message
+ */
+void crerror(const char *s)
+{
+  if(debug)
+    printf("\nligne %d : %s\n",crlineno,s);
+}
+
+/**
+ * Parse the main.cfg file and fill the maps structure.
+ *
+ * @param file the filename to parse
+ * @param my_map the maps structure to fill
+ */
+int conf_read(const char* file,maps* my_map){
+  
+  crin = fopen(file,"r");
+  if (crin==NULL){
+    return 2 ;
+  }
+
+  my_maps=my_map;
+  my_maps->name=NULL;
+  current_maps=my_maps;
+  
+  int resultatYYParse = crparse() ;
+  if(current_content!=NULL){
+    addMapToMap(&current_maps->content,current_content);
+    current_maps->next=NULL;
+    freeMap(&current_content);
+    free(current_content);
+  }
+
+  fclose(crin);
+#ifndef WIN32
+  crlex_destroy();
+#endif
+
+  return resultatYYParse;
+}
+
diff --git a/zoo-project/zoo-kernel/makefile.vc b/zoo-project/zoo-kernel/makefile.vc
new file mode 100644
index 0000000..4f2f99d
--- /dev/null
+++ b/zoo-project/zoo-kernel/makefile.vc
@@ -0,0 +1,104 @@
+# WIN32 Makefile tested using VC-9.0
+# Don't forget to set your PATH using the following command :
+# c:\Progam Files (x86)\Microsoft Visual Studio 9.0\VC\bin\vcvars32.bat
+# set PATH=%PATH%;$(TOOLS)
+# using value for TOOLS relative to your local installation
+#
+
+!INCLUDE nmake.opt
+
+all:  $(PROGRAMNAME) zcfg2yaml
+
+version.h:
+	set VERS=`svnversion .`
+	echo #define ZOO_VERSION "$(VERS)" > version.h
+
+main_conf_read.tab.c: main_conf_read.y service.h
+	bison -p cr -d main_conf_read.y
+
+main_conf_read.tab.obj: main_conf_read.tab.c service.h
+	$(CPP) /EHsc $(CFLAGS) main_conf_read.tab.c /c
+
+lex.cr.c: main_conf_read.y main_conf_read.l main_conf_read.tab.c service.h
+	flex -Pcr main_conf_read.l
+
+lex.cr.obj: lex.cr.c service.h
+	$(CPP) $(CFLAGS) /c lex.cr.c
+
+service_conf.tab.c: service_conf.y service.h
+	bison -p sr -d service_conf.y
+
+service_conf.tab.obj: service_conf.tab.c service.h
+	$(CPP) $(CFLAGS) service_conf.tab.c /c
+
+lex.sr.c: service_conf.y service_conf.l service_conf.tab.c service.h
+	flex -Psr service_conf.l
+
+lex.sr.obj: lex.sr.c service.h
+	$(CPP) $(CFLAGS) /c lex.sr.c
+
+zcfg2yaml.obj: zcfg2yaml.c
+	$(CPP) $(CFLAGS) /c zcfg2yaml.c
+
+service_internal.obj: service_internal.c service_internal.h
+	$(CPP) $(CFLAGS) /c service_internal.c
+
+server_internal.obj: server_internal.c server_internal.h
+	$(CPP) $(CFLAGS) /c server_internal.c
+
+caching.obj: caching.c caching.h
+	$(CPP) $(CFLAGS) /c caching.c
+
+request_parser.obj: request_parser.c request_parser.h
+	$(CPP) $(CFLAGS) /c request_parser.c
+
+response_print.obj: response_print.c response_print.h
+	$(CPP) $(CFLAGS) /c response_print.c
+
+service.obj: service.c service.h
+	$(CPP) $(CFLAGS) /c service.c
+
+sqlapi.obj: sqlapi.c sqlapi.h
+	$(CPP) $(CFLAGS) /c sqlapi.c
+
+service_internal_js.obj: service_internal_js.c service.h
+	$(CPP) /c $(CFLAGS) service_internal_js.c
+
+service_internal_java.obj: service_internal_java.c service.h
+	$(CPP) /c $(CFLAGS) service_internal_java.c
+
+service_internal_ruby.obj: service_internal_ruby.c service_internal_ruby.h service.h
+	$(CPP) /c $(CFLAGS) service_internal_ruby.c
+
+service_internal_python.obj: service_internal_python.c service.h
+	$(CPP) /c $(CFLAGS) service_internal_python.c
+
+service_internal_ms.obj: service_internal_ms.c service.h
+	$(CPP) /c $(CFLAGS) service_internal_ms.c
+
+service_loader.obj: service_loader.c service.h
+	$(CPP) /c $(CFLAGS)  service_loader.c
+
+zoo_service_loader.obj: zoo_service_loader.c service.h
+	$(CPP) /c $(CFLAGS)  zoo_service_loader.c
+
+zoo_loader.obj: zoo_loader.c service.h
+	$(CPP) /EHsc /c $(CFLAGS) zoo_loader.c
+
+service_internal_php.obj: service_internal_php.c service_internal_php.h service.h
+	$(CPP) /c $(CFLAGS) $(PHP_CFLAGS) service_internal_php.c
+
+$(LIBZOO_SERVICE): service_internal.obj service.obj sqlapi.obj
+	link /dll /out:$(LIBZOO_SERVICE) ./service.obj ./service_internal.obj ./sqlapi.obj $(LDFLAGS) /FORCE:MULTIPLE
+
+$(PROGRAMNAME): version.h $(LIBZOO_SERVICE) zoo_loader.obj zoo_service_loader.obj service_internal.obj $(PY_FILE) $(JAVA_FILE) $(MS_FILE) $(JS_FILE) $(RUBY_FILE) $(PHP_FILE) ulinet.obj lex.cr.obj lex.sr.obj service_conf.tab.obj main_conf_read.tab.obj request_parser.obj response_print.obj server_internal.obj caching.obj
+	link zoo_loader.obj request_parser.obj response_print.obj server_internal.obj caching.obj $(PY_FILE) $(JAVA_FILE) $(MS_FILE) $(JS_FILE) $(RUBY_FILE) $(PHP_FILE) ulinet.obj main_conf_read.tab.obj lex.cr.obj service_conf.tab.obj lex.sr.obj  zoo_service_loader.obj ./libzoo_service.lib /out:$(PROGRAMNAME) $(LDFLAGS) $(LDFLAGSCGI) 
+
+zcfg2yaml: version.h zcfg2yaml.obj zoo_service_loader.obj service_internal.obj $(PY_FILE) $(JAVA_FILE) $(MS_FILE) $(JS_FILE) $(RUBY_FILE) ulinet.obj lex.cr.obj lex.sr.obj service_conf.tab.obj main_conf_read.tab.obj
+	link zcfg2yaml.obj server_internal.obj $(PY_FILE) $(JAVA_FILE) $(MS_FILE) $(JS_FILE) $(RUBY_FILE) $(PHP_FILE) ulinet.obj response_print.obj main_conf_read.tab.obj lex.cr.obj service_conf.tab.obj lex.sr.obj ./libzoo_service.lib /out:zcfg2yaml.exe $(LDFLAGS) $(LDFLAGSCGI)
+
+clean:
+	erase -f *.cgi *.obj *.tab.c* *.tab.h *.sr.c* lex.* *.lreg *.sibling *.lib *.dll
+
+embed-manifest: zoo_loader.cgi
+	mt.exe -manifest zoo_loader.cgi.manifest -outputresource:zoo_loader.cgi;1
\ No newline at end of file
diff --git a/zoo-project/zoo-kernel/messages.po.new b/zoo-project/zoo-kernel/messages.po.new
new file mode 100644
index 0000000..32951ab
--- /dev/null
+++ b/zoo-project/zoo-kernel/messages.po.new
@@ -0,0 +1,328 @@
+# ZOO-Kernel Internationalization.
+# Copyright (C) 2015 GeoLabs SARL
+# This file is distributed under the same license as the PACKAGE package.
+# Gerald Fenoy <gerald.fenoy at geolabs.fr>, 2015.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: ZOO-Kernel 1.5.0\n"
+"Report-Msgid-Bugs-To: zoo-discuss at lists.osgeo.org\n"
+"POT-Creation-Date: 2015-07-02 17:38+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: caching.c:217 caching.c:235 caching.c:356 request_parser.c:214
+#: request_parser.c:225 request_parser.c:262 request_parser.c:403
+#: request_parser.c:414 request_parser.c:441 request_parser.c:537
+#: request_parser.c:562 request_parser.c:665 request_parser.c:782
+#: request_parser.c:1112 request_parser.c:1204 zcfg2yaml.c:38
+#: zoo_service_loader.c:259 zoo_service_loader.c:880 zoo_service_loader.c:1363
+#: zoo_service_loader.c:1559
+msgid "Unable to allocate memory"
+msgstr ""
+
+#: caching.c:344
+msgid "Unable to download the file."
+msgstr ""
+
+#: request_parser.c:92
+#, c-format
+msgid "The maximum allowed occurrences for <%s> (%i) was exceeded."
+msgstr ""
+
+#: request_parser.c:113
+#, c-format
+msgid "ZOO-Kernel was unable to load your data for %s position %s."
+msgstr ""
+
+#: request_parser.c:124
+#, c-format
+msgid "The maximum allowed occurrences for <%s> is one."
+msgstr ""
+
+#: request_parser.c:315
+#, c-format
+msgid "Unable to find a valid protocol to download the remote file %s"
+msgstr ""
+
+#: request_parser.c:613
+msgid "Unable to add a request in the queue."
+msgstr ""
+
+#: request_parser.c:1021
+msgid "Unable to append maps to maps."
+msgstr ""
+
+#: request_parser.c:1291
+msgid "Duplicate <Output> elements in WPS Execute request"
+msgstr ""
+
+#: request_parser.c:1487
+#, c-format
+msgid ""
+"The <%s> parameter has a size limit (%s MB) defined in the ZOO "
+"ServicesProvider configuration file, but the reference you provided exceeds "
+"this limit (%f MB)."
+msgstr ""
+
+#: request_parser.c:1519
+#, c-format
+msgid ""
+"The <%s> argument was not specified in DataInputs but is required according "
+"to the ZOO ServicesProvider configuration file."
+msgstr ""
+
+#: request_parser.c:1545
+#, c-format
+msgid ""
+"The <%s> argument specified as %s identifier was not recognized (not defined "
+"in the ZOO Configuration File)."
+msgstr ""
+
+#: request_parser.c:1663
+#, c-format
+msgid "Mandatory parameter <%s> was not specified"
+msgstr ""
+
+#: request_parser.c:1712
+#, c-format
+msgid "The value <%s> was not recognized, %s %s the only acceptable value."
+msgstr ""
+
+#: request_parser.c:1715
+msgid "is"
+msgstr ""
+
+#: request_parser.c:1727
+msgid "are"
+msgstr ""
+
+#: response_print.c:1630
+#, c-format
+msgid "The service \"%s\" ran successfully."
+msgstr ""
+
+#: response_print.c:1638
+#, c-format
+msgid ""
+"The ZOO service \"%s\" is currently running. Please reload this document to "
+"get the up-to-date status of the service."
+msgstr ""
+
+#: response_print.c:1644
+#, c-format
+msgid ""
+"The service \"%s\" was accepted by the ZOO kernel and is running as a "
+"background task. Please access the URL in the statusLocation attribute "
+"provided in this document to get the up-to-date status and results."
+msgstr ""
+
+#: response_print.c:1661
+msgid "No more information available"
+msgstr ""
+
+#: response_print.c:1668
+#, c-format
+msgid "error code not know : %i\n"
+msgstr ""
+
+#: response_print.c:1760
+msgid "Lock failed."
+msgstr ""
+
+#: response_print.c:1773
+#, c-format
+msgid "Unable to create the file \"%s\" for storing the ExecuteResponse."
+msgstr ""
+
+#: response_print.c:2290
+msgid "No debug message available"
+msgstr ""
+
+#: response_print.c:2378
+#, c-format
+msgid "Unable to create the file \"%s\" for storing the session maps."
+msgstr ""
+
+#: response_print.c:2394
+msgid ""
+"Unable to run the Service. The message returned back by the Service was the "
+"following: "
+msgstr ""
+
+#: response_print.c:2395
+#, c-format
+msgid ""
+"Unable to run the Service. The message returned back by the Service was the "
+"following: %s"
+msgstr ""
+
+#: response_print.c:2398 response_print.c:2399
+msgid ""
+"Unable to run the Service. No more information was returned back by the "
+"Service."
+msgstr ""
+
+#: response_print.c:2486
+#, c-format
+msgid "Unable to create the file \"%s\" for storing the %s final result."
+msgstr ""
+
+#: response_print.c:2572
+#, c-format
+msgid ""
+"Wrong RawDataOutput parameter: unable to fetch any result for the given "
+"parameter name: \"%s\"."
+msgstr ""
+
+#: server_internal.c:869 server_internal.c:946
+msgid ""
+"The JobID from the request does not match any of the Jobs running on this "
+"server"
+msgstr ""
+
+#: server_internal.c:875 server_internal.c:907
+msgid "The result for the requested JobID has not yet been generated. "
+msgstr ""
+
+#: server_internal.c:988
+msgid "The job cannot be removed, a file cannot be removed"
+msgstr ""
+
+#: server_internal.c:1063
+msgid "Unable to open the registry directory."
+msgstr ""
+
+#: server_internal.c:1082
+msgid "Unable to allocate memory."
+msgstr ""
+
+#: server_internal.c:1093 zoo_service_loader.c:276 zoo_service_loader.c:1384
+#: zoo_service_loader.c:1427
+#, c-format
+msgid "Unable to parse the ZCFG file: %s (%s)"
+msgstr ""
+
+#: server_internal.c:1096 zoo_service_loader.c:279 zoo_service_loader.c:1389
+#: zoo_service_loader.c:1431
+#, c-format
+msgid "Unable to parse the ZCFG file: %s."
+msgstr ""
+
+#: service_internal_ms.c:136
+msgid "Unable to find any mapserverAddress defined in the main.cfg file"
+msgstr ""
+
+#: service_internal_php.c:227
+#, c-format
+msgid "Unable to load the PHP file %s"
+msgstr ""
+
+#: service_internal_python.c:316
+#, c-format
+msgid "Python module %s cannot be loaded. Message: %s\n"
+msgstr ""
+
+#: service_internal_python.c:355
+#, c-format
+msgid ""
+"%s\n"
+"Unable to run your python process properly. Please check the following "
+"messages : %s"
+msgstr ""
+
+#: service_internal_python.c:361
+#, c-format
+msgid ""
+"%s \n"
+" Unable to run your python process properly. Unable to provide any futher "
+"informations."
+msgstr ""
+
+#: zoo_service_loader.c:352
+#, c-format
+msgid "ZOO Kernel failed to process your request, receiving signal %d = %s"
+msgstr ""
+
+#: zoo_service_loader.c:527
+#, c-format
+msgid "Error occured while running the %s function: %s"
+msgstr ""
+
+#: zoo_service_loader.c:578
+#, c-format
+msgid "Unable to load C Library %s"
+msgstr ""
+
+#: zoo_service_loader.c:672
+#, c-format
+msgid ""
+"Programming Language (%s) set in ZCFG file is not currently supported by ZOO "
+"Kernel.\n"
+msgstr ""
+
+#: zoo_service_loader.c:737
+msgid "Unable to cache HTTP POST Execute request."
+msgstr ""
+
+#: zoo_service_loader.c:895
+msgid "Unable to load the main.cfg file."
+msgstr ""
+
+#: zoo_service_loader.c:940
+#, c-format
+msgid "The value %s is not supported for the <language> parameter"
+msgstr ""
+
+#: zoo_service_loader.c:1238
+msgid "The specified path does not exist."
+msgstr ""
+
+#: zoo_service_loader.c:1303
+#, c-format
+msgid ""
+"Unable to parse the ZCFG file for the following ZOO-Service: %s. Message: %s"
+msgstr ""
+
+#: zoo_service_loader.c:1308
+#, c-format
+msgid "Unable to parse the ZCFG file for the following ZOO-Service: %s."
+msgstr ""
+
+#: zoo_service_loader.c:1534
+msgid "Unable to run Execute request using the GET HTTP method"
+msgstr ""
+
+#: zoo_service_loader.c:1606
+#, c-format
+msgid ""
+"The value for <identifier> seems to be wrong (%s). Please specify one of the "
+"processes in the list returned by a GetCapabilities request."
+msgstr ""
+
+#: zoo_service_loader.c:1733
+msgid ""
+"The status parameter cannot be set to true if storeExecuteResponse is set to "
+"false. Please modify your request parameters."
+msgstr ""
+
+#: zoo_service_loader.c:1761
+msgid "The process does not permit the desired execution mode."
+msgstr ""
+
+#: zoo_service_loader.c:1837
+msgid "No message provided"
+msgstr ""
+
+#: zoo_service_loader.c:1995
+msgid "Initializing"
+msgstr ""
+
+#: zoo_service_loader.c:2142
+msgid "Unable to run the child process properly"
+msgstr ""
diff --git a/zoo-project/zoo-kernel/mimetypes.h b/zoo-project/zoo-kernel/mimetypes.h
new file mode 100644
index 0000000..5fe95cb
--- /dev/null
+++ b/zoo-project/zoo-kernel/mimetypes.h
@@ -0,0 +1,837 @@
+#include "service.h"
+ 
+typedef enum MimeTypes {
+	 M_Type,
+	 M_Extension
+} mimetype;
+
+#define NUM_MIME_TYPES 767
+
+/*
+ * This array has been constructed based on the
+ * Apache web server's mime.types file
+ */
+const char* const MIME[NUM_MIME_TYPES][2] = {
+	{ "application/andrew-inset", "ez" },
+	{ "application/applixware", "aw" },
+	{ "application/atom+xml", "atom" },
+	{ "application/atomcat+xml", "atomcat" },
+	{ "application/atomsvc+xml", "atomsvc" },
+	{ "application/ccxml+xml", "ccxml" },
+	{ "application/cdmi-capability", "cdmia" },
+	{ "application/cdmi-container", "cdmic" },
+	{ "application/cdmi-domain", "cdmid" },
+	{ "application/cdmi-object", "cdmio" },
+	{ "application/cdmi-queue", "cdmiq" },
+	{ "application/cu-seeme", "cu" },
+	{ "application/davmount+xml", "davmount" },
+	{ "application/docbook+xml", "dbk" },
+	{ "application/dssc+der", "dssc" },
+	{ "application/dssc+xml", "xdssc" },
+	{ "application/ecmascript", "ecma" },
+	{ "application/emma+xml", "emma" },
+	{ "application/epub+zip", "epub" },
+	{ "application/exi", "exi" },
+	{ "application/font-tdpfr", "pfr" },
+	{ "application/gml+xml", "gml" },
+	{ "application/gpx+xml", "gpx" },
+	{ "application/gxf", "gxf" },
+	{ "application/hyperstudio", "stk" },
+	{ "application/inkml+xml", "ink" },
+	{ "application/ipfix", "ipfix" },
+	{ "application/java-archive", "jar" },
+	{ "application/java-serialized-object", "ser" },
+	{ "application/java-vm", "class" },
+	{ "application/javascript", "js" },
+	{ "application/json", "json" },
+	{ "application/jsonml+json", "jsonml" },
+	{ "application/lost+xml", "lostxml" },
+	{ "application/mac-binhex40", "hqx" },
+	{ "application/mac-compactpro", "cpt" },
+	{ "application/mads+xml", "mads" },
+	{ "application/marc", "mrc" },
+	{ "application/marcxml+xml", "mrcx" },
+	{ "application/mathematica", "ma" },
+	{ "application/mathml+xml", "mathml" },
+	{ "application/mbox", "mbox" },
+	{ "application/mediaservercontrol+xml", "mscml" },
+	{ "application/metalink+xml", "metalink" },
+	{ "application/metalink4+xml", "meta4" },
+	{ "application/mets+xml", "mets" },
+	{ "application/mods+xml", "mods" },
+	{ "application/mp21", "m21" },
+	{ "application/mp4", "mp4s" },
+	{ "application/msword", "doc" },
+	{ "application/mxf", "mxf" },
+	{ "application/octet-stream", "bin" },
+	{ "application/oda", "oda" },
+	{ "application/oebps-package+xml", "opf" },
+	{ "application/ogg", "ogx" },
+	{ "application/omdoc+xml", "omdoc" },
+	{ "application/onenote", "onetoc" },
+	{ "application/oxps", "oxps" },
+	{ "application/patch-ops-error+xml", "xer" },
+	{ "application/pdf", "pdf" },
+	{ "application/pgp-encrypted", "pgp" },
+	{ "application/pgp-signature", "asc" },
+	{ "application/pics-rules", "prf" },
+	{ "application/pkcs10", "p10" },
+	{ "application/pkcs7-mime", "p7m" },
+	{ "application/pkcs7-signature", "p7s" },
+	{ "application/pkcs8", "p8" },
+	{ "application/pkix-attr-cert", "ac" },
+	{ "application/pkix-cert", "cer" },
+	{ "application/pkix-crl", "crl" },
+	{ "application/pkix-pkipath", "pkipath" },
+	{ "application/pkixcmp", "pki" },
+	{ "application/pls+xml", "pls" },
+	{ "application/postscript", "ps" },
+	{ "application/prs.cww", "cww" },
+	{ "application/pskc+xml", "pskcxml" },
+	{ "application/rdf+xml", "rdf" },
+	{ "application/reginfo+xml", "rif" },
+	{ "application/relax-ng-compact-syntax", "rnc" },
+	{ "application/resource-lists+xml", "rl" },
+	{ "application/resource-lists-diff+xml", "rld" },
+	{ "application/rls-services+xml", "rs" },
+	{ "application/rpki-ghostbusters", "gbr" },
+	{ "application/rpki-manifest", "mft" },
+	{ "application/rpki-roa", "roa" },
+	{ "application/rsd+xml", "rsd" },
+	{ "application/rss+xml", "rss" },
+	{ "application/rtf", "rtf" },
+	{ "application/sbml+xml", "sbml" },
+	{ "application/scvp-cv-request", "scq" },
+	{ "application/scvp-cv-response", "scs" },
+	{ "application/scvp-vp-request", "spq" },
+	{ "application/scvp-vp-response", "spp" },
+	{ "application/sdp", "sdp" },
+	{ "application/set-payment-initiation", "setpay" },
+	{ "application/set-registration-initiation", "setreg" },
+	{ "application/shf+xml", "shf" },
+	{ "application/smil+xml", "smi" },
+	{ "application/sparql-query", "rq" },
+	{ "application/sparql-results+xml", "srx" },
+	{ "application/srgs", "gram" },
+	{ "application/srgs+xml", "grxml" },
+	{ "application/sru+xml", "sru" },
+	{ "application/ssdl+xml", "ssdl" },
+	{ "application/ssml+xml", "ssml" },
+	{ "application/tei+xml", "tei" },
+	{ "application/thraud+xml", "tfi" },
+	{ "application/timestamped-data", "tsd" },
+	{ "application/vnd.3gpp.pic-bw-large", "plb" },
+	{ "application/vnd.3gpp.pic-bw-small", "psb" },
+	{ "application/vnd.3gpp.pic-bw-var", "pvb" },
+	{ "application/vnd.3gpp2.tcap", "tcap" },
+	{ "application/vnd.3m.post-it-notes", "pwn" },
+	{ "application/vnd.accpac.simply.aso", "aso" },
+	{ "application/vnd.accpac.simply.imp", "imp" },
+	{ "application/vnd.acucobol", "acu" },
+	{ "application/vnd.acucorp", "atc" },
+	{ "application/vnd.adobe.air-application-installer-package+zip", "air" },
+	{ "application/vnd.adobe.formscentral.fcdt", "fcdt" },
+	{ "application/vnd.adobe.fxp", "fxp" },
+	{ "application/vnd.adobe.xdp+xml", "xdp" },
+	{ "application/vnd.adobe.xfdf", "xfdf" },
+	{ "application/vnd.ahead.space", "ahead" },
+	{ "application/vnd.airzip.filesecure.azf", "azf" },
+	{ "application/vnd.airzip.filesecure.azs", "azs" },
+	{ "application/vnd.amazon.ebook", "azw" },
+	{ "application/vnd.americandynamics.acc", "acc" },
+	{ "application/vnd.amiga.ami", "ami" },
+	{ "application/vnd.android.package-archive", "apk" },
+	{ "application/vnd.anser-web-certificate-issue-initiation", "cii" },
+	{ "application/vnd.anser-web-funds-transfer-initiation", "fti" },
+	{ "application/vnd.antix.game-component", "atx" },
+	{ "application/vnd.apple.installer+xml", "mpkg" },
+	{ "application/vnd.apple.mpegurl", "m3u8" },
+	{ "application/vnd.aristanetworks.swi", "swi" },
+	{ "application/vnd.astraea-software.iota", "iota" },
+	{ "application/vnd.audiograph", "aep" },
+	{ "application/vnd.blueice.multipass", "mpm" },
+	{ "application/vnd.bmi", "bmi" },
+	{ "application/vnd.businessobjects", "rep" },
+	{ "application/vnd.chemdraw+xml", "cdxml" },
+	{ "application/vnd.chipnuts.karaoke-mmd", "mmd" },
+	{ "application/vnd.cinderella", "cdy" },
+	{ "application/vnd.claymore", "cla" },
+	{ "application/vnd.cloanto.rp9", "rp9" },
+	{ "application/vnd.clonk.c4group", "c4g" },
+	{ "application/vnd.cluetrust.cartomobile-config", "c11amc" },
+	{ "application/vnd.cluetrust.cartomobile-config-pkg", "c11amz" },
+	{ "application/vnd.commonspace", "csp" },
+	{ "application/vnd.contact.cmsg", "cdbcmsg" },
+	{ "application/vnd.cosmocaller", "cmc" },
+	{ "application/vnd.crick.clicker", "clkx" },
+	{ "application/vnd.crick.clicker.keyboard", "clkk" },
+	{ "application/vnd.crick.clicker.palette", "clkp" },
+	{ "application/vnd.crick.clicker.template", "clkt" },
+	{ "application/vnd.crick.clicker.wordbank", "clkw" },
+	{ "application/vnd.criticaltools.wbs+xml", "wbs" },
+	{ "application/vnd.ctc-posml", "pml" },
+	{ "application/vnd.cups-ppd", "ppd" },
+	{ "application/vnd.curl.car", "car" },
+	{ "application/vnd.curl.pcurl", "pcurl" },
+	{ "application/vnd.dart", "dart" },
+	{ "application/vnd.data-vision.rdz", "rdz" },
+	{ "application/vnd.dece.data", "uvf" },
+	{ "application/vnd.dece.ttml+xml", "uvt" },
+	{ "application/vnd.dece.unspecified", "uvx" },
+	{ "application/vnd.dece.zip", "uvz" },
+	{ "application/vnd.denovo.fcselayout-link", "fe_launch" },
+	{ "application/vnd.dna", "dna" },
+	{ "application/vnd.dolby.mlp", "mlp" },
+	{ "application/vnd.dpgraph", "dpg" },
+	{ "application/vnd.dreamfactory", "dfac" },
+	{ "application/vnd.ds-keypoint", "kpxx" },
+	{ "application/vnd.dvb.ait", "ait" },
+	{ "application/vnd.dvb.service", "svc" },
+	{ "application/vnd.dynageo", "geo" },
+	{ "application/vnd.ecowin.chart", "mag" },
+	{ "application/vnd.enliven", "nml" },
+	{ "application/vnd.epson.esf", "esf" },
+	{ "application/vnd.epson.msf", "msf" },
+	{ "application/vnd.epson.quickanime", "qam" },
+	{ "application/vnd.epson.salt", "slt" },
+	{ "application/vnd.epson.ssf", "ssf" },
+	{ "application/vnd.eszigno3+xml", "es3" },
+	{ "application/vnd.ezpix-album", "ez2" },
+	{ "application/vnd.ezpix-package", "ez3" },
+	{ "application/vnd.fdf", "fdf" },
+	{ "application/vnd.fdsn.mseed", "mseed" },
+	{ "application/vnd.fdsn.seed", "seed" },
+	{ "application/vnd.flographit", "gph" },
+	{ "application/vnd.fluxtime.clip", "ftc" },
+	{ "application/vnd.framemaker", "fm" },
+	{ "application/vnd.frogans.fnc", "fnc" },
+	{ "application/vnd.frogans.ltf", "ltf" },
+	{ "application/vnd.fsc.weblaunch", "fsc" },
+	{ "application/vnd.fujitsu.oasys", "oas" },
+	{ "application/vnd.fujitsu.oasys2", "oa2" },
+	{ "application/vnd.fujitsu.oasys3", "oa3" },
+	{ "application/vnd.fujitsu.oasysgp", "fg5" },
+	{ "application/vnd.fujitsu.oasysprs", "bh2" },
+	{ "application/vnd.fujixerox.ddd", "ddd" },
+	{ "application/vnd.fujixerox.docuworks", "xdw" },
+	{ "application/vnd.fujixerox.docuworks.binder", "xbd" },
+	{ "application/vnd.fuzzysheet", "fzs" },
+	{ "application/vnd.genomatix.tuxedo", "txd" },
+	{ "application/vnd.geogebra.file", "ggb" },
+	{ "application/vnd.geogebra.tool", "ggt" },
+	{ "application/vnd.geometry-explorer", "gex" },
+	{ "application/vnd.geonext", "gxt" },
+	{ "application/vnd.geoplan", "g2w" },
+	{ "application/vnd.geospace", "g3w" },
+	{ "application/vnd.gmx", "gmx" },
+	{ "application/vnd.google-earth.kml+xml", "kml" },
+	{ "application/vnd.google-earth.kmz", "kmz" },
+	{ "application/vnd.grafeq", "gqf" },
+	{ "application/vnd.groove-account", "gac" },
+	{ "application/vnd.groove-help", "ghf" },
+	{ "application/vnd.groove-identity-message", "gim" },
+	{ "application/vnd.groove-injector", "grv" },
+	{ "application/vnd.groove-tool-message", "gtm" },
+	{ "application/vnd.groove-tool-template", "tpl" },
+	{ "application/vnd.groove-vcard", "vcg" },
+	{ "application/vnd.hal+xml", "hal" },
+	{ "application/vnd.handheld-entertainment+xml", "zmm" },
+	{ "application/vnd.hbci", "hbci" },
+	{ "application/vnd.hhe.lesson-player", "les" },
+	{ "application/vnd.hp-hpgl", "hpgl" },
+	{ "application/vnd.hp-hpid", "hpid" },
+	{ "application/vnd.hp-hps", "hps" },
+	{ "application/vnd.hp-jlyt", "jlt" },
+	{ "application/vnd.hp-pcl", "pcl" },
+	{ "application/vnd.hp-pclxl", "pclxl" },
+	{ "application/vnd.hydrostatix.sof-data", "sfd-hdstx" },
+	{ "application/vnd.ibm.minipay", "mpy" },
+	{ "application/vnd.ibm.modcap", "afp" },
+	{ "application/vnd.ibm.rights-management", "irm" },
+	{ "application/vnd.ibm.secure-container", "sc" },
+	{ "application/vnd.iccprofile", "icc" },
+	{ "application/vnd.igloader", "igl" },
+	{ "application/vnd.immervision-ivp", "ivp" },
+	{ "application/vnd.immervision-ivu", "ivu" },
+	{ "application/vnd.insors.igm", "igm" },
+	{ "application/vnd.intercon.formnet", "xpw" },
+	{ "application/vnd.intergeo", "i2g" },
+	{ "application/vnd.intu.qbo", "qbo" },
+	{ "application/vnd.intu.qfx", "qfx" },
+	{ "application/vnd.ipunplugged.rcprofile", "rcprofile" },
+	{ "application/vnd.irepository.package+xml", "irp" },
+	{ "application/vnd.is-xpr", "xpr" },
+	{ "application/vnd.isac.fcs", "fcs" },
+	{ "application/vnd.jam", "jam" },
+	{ "application/vnd.jcp.javame.midlet-rms", "rms" },
+	{ "application/vnd.jisp", "jisp" },
+	{ "application/vnd.joost.joda-archive", "joda" },
+	{ "application/vnd.kahootz", "ktz" },
+	{ "application/vnd.kde.karbon", "karbon" },
+	{ "application/vnd.kde.kchart", "chrt" },
+	{ "application/vnd.kde.kformula", "kfo" },
+	{ "application/vnd.kde.kivio", "flw" },
+	{ "application/vnd.kde.kontour", "kon" },
+	{ "application/vnd.kde.kpresenter", "kpr" },
+	{ "application/vnd.kde.kspread", "ksp" },
+	{ "application/vnd.kde.kword", "kwd" },
+	{ "application/vnd.kenameaapp", "htke" },
+	{ "application/vnd.kidspiration", "kia" },
+	{ "application/vnd.kinar", "kne" },
+	{ "application/vnd.koan", "skp" },
+	{ "application/vnd.kodak-descriptor", "sse" },
+	{ "application/vnd.las.las+xml", "lasxml" },
+	{ "application/vnd.llamagraphics.life-balance.desktop", "lbd" },
+	{ "application/vnd.llamagraphics.life-balance.exchange+xml", "lbe" },
+	{ "application/vnd.lotus-1-2-3", "123" },
+	{ "application/vnd.lotus-approach", "apr" },
+	{ "application/vnd.lotus-freelance", "pre" },
+	{ "application/vnd.lotus-notes", "nsf" },
+	{ "application/vnd.lotus-organizer", "org" },
+	{ "application/vnd.lotus-screencam", "scm" },
+	{ "application/vnd.lotus-wordpro", "lwp" },
+	{ "application/vnd.macports.portpkg", "portpkg" },
+	{ "application/vnd.mcd", "mcd" },
+	{ "application/vnd.medcalcdata", "mc1" },
+	{ "application/vnd.mediastation.cdkey", "cdkey" },
+	{ "application/vnd.mfer", "mwf" },
+	{ "application/vnd.mfmp", "mfm" },
+	{ "application/vnd.micrografx.flo", "flo" },
+	{ "application/vnd.micrografx.igx", "igx" },
+	{ "application/vnd.mif", "mif" },
+	{ "application/vnd.mobius.daf", "daf" },
+	{ "application/vnd.mobius.dis", "dis" },
+	{ "application/vnd.mobius.mbk", "mbk" },
+	{ "application/vnd.mobius.mqy", "mqy" },
+	{ "application/vnd.mobius.msl", "msl" },
+	{ "application/vnd.mobius.plc", "plc" },
+	{ "application/vnd.mobius.txf", "txf" },
+	{ "application/vnd.mophun.application", "mpn" },
+	{ "application/vnd.mophun.certificate", "mpc" },
+	{ "application/vnd.mozilla.xul+xml", "xul" },
+	{ "application/vnd.ms-artgalry", "cil" },
+	{ "application/vnd.ms-cab-compressed", "cab" },
+	{ "application/vnd.ms-excel", "xls" },
+	{ "application/vnd.ms-excel.addin.macroenabled.12", "xlam" },
+	{ "application/vnd.ms-excel.sheet.binary.macroenabled.12", "xlsb" },
+	{ "application/vnd.ms-excel.sheet.macroenabled.12", "xlsm" },
+	{ "application/vnd.ms-excel.template.macroenabled.12", "xltm" },
+	{ "application/vnd.ms-fontobject", "eot" },
+	{ "application/vnd.ms-htmlhelp", "chm" },
+	{ "application/vnd.ms-ims", "ims" },
+	{ "application/vnd.ms-lrm", "lrm" },
+	{ "application/vnd.ms-officetheme", "thmx" },
+	{ "application/vnd.ms-pki.seccat", "cat" },
+	{ "application/vnd.ms-pki.stl", "stl" },
+	{ "application/vnd.ms-powerpoint", "ppt" },
+	{ "application/vnd.ms-powerpoint.addin.macroenabled.12", "ppam" },
+	{ "application/vnd.ms-powerpoint.presentation.macroenabled.12", "pptm" },
+	{ "application/vnd.ms-powerpoint.slide.macroenabled.12", "sldm" },
+	{ "application/vnd.ms-powerpoint.slideshow.macroenabled.12", "ppsm" },
+	{ "application/vnd.ms-powerpoint.template.macroenabled.12", "potm" },
+	{ "application/vnd.ms-project", "mpp" },
+	{ "application/vnd.ms-word.document.macroenabled.12", "docm" },
+	{ "application/vnd.ms-word.template.macroenabled.12", "dotm" },
+	{ "application/vnd.ms-works", "wps" },
+	{ "application/vnd.ms-wpl", "wpl" },
+	{ "application/vnd.ms-xpsdocument", "xps" },
+	{ "application/vnd.mseq", "mseq" },
+	{ "application/vnd.musician", "mus" },
+	{ "application/vnd.muvee.style", "msty" },
+	{ "application/vnd.mynfc", "taglet" },
+	{ "application/vnd.neurolanguage.nlu", "nlu" },
+	{ "application/vnd.nitf", "ntf" },
+	{ "application/vnd.noblenet-directory", "nnd" },
+	{ "application/vnd.noblenet-sealer", "nns" },
+	{ "application/vnd.noblenet-web", "nnw" },
+	{ "application/vnd.nokia.n-gage.data", "ngdat" },
+	{ "application/vnd.nokia.n-gage.symbian.install", "n-gage" },
+	{ "application/vnd.nokia.radio-preset", "rpst" },
+	{ "application/vnd.nokia.radio-presets", "rpss" },
+	{ "application/vnd.novadigm.edm", "edm" },
+	{ "application/vnd.novadigm.edx", "edx" },
+	{ "application/vnd.novadigm.ext", "ext" },
+	{ "application/vnd.oasis.opendocument.chart", "odc" },
+	{ "application/vnd.oasis.opendocument.chart-template", "otc" },
+	{ "application/vnd.oasis.opendocument.database", "odb" },
+	{ "application/vnd.oasis.opendocument.formula", "odf" },
+	{ "application/vnd.oasis.opendocument.formula-template", "odft" },
+	{ "application/vnd.oasis.opendocument.graphics", "odg" },
+	{ "application/vnd.oasis.opendocument.graphics-template", "otg" },
+	{ "application/vnd.oasis.opendocument.image", "odi" },
+	{ "application/vnd.oasis.opendocument.image-template", "oti" },
+	{ "application/vnd.oasis.opendocument.presentation", "odp" },
+	{ "application/vnd.oasis.opendocument.presentation-template", "otp" },
+	{ "application/vnd.oasis.opendocument.spreadsheet", "ods" },
+	{ "application/vnd.oasis.opendocument.spreadsheet-template", "ots" },
+	{ "application/vnd.oasis.opendocument.text", "odt" },
+	{ "application/vnd.oasis.opendocument.text-master", "odm" },
+	{ "application/vnd.oasis.opendocument.text-template", "ott" },
+	{ "application/vnd.oasis.opendocument.text-web", "oth" },
+	{ "application/vnd.olpc-sugar", "xo" },
+	{ "application/vnd.oma.dd2+xml", "dd2" },
+	{ "application/vnd.openofficeorg.extension", "oxt" },
+	{ "application/vnd.openxmlformats-officedocument.presentationml.presentation", "pptx" },
+	{ "application/vnd.openxmlformats-officedocument.presentationml.slide", "sldx" },
+	{ "application/vnd.openxmlformats-officedocument.presentationml.slideshow", "ppsx" },
+	{ "application/vnd.openxmlformats-officedocument.presentationml.template", "potx" },
+	{ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "xlsx" },
+	{ "application/vnd.openxmlformats-officedocument.spreadsheetml.template", "xltx" },
+	{ "application/vnd.openxmlformats-officedocument.wordprocessingml.document", "docx" },
+	{ "application/vnd.openxmlformats-officedocument.wordprocessingml.template", "dotx" },
+	{ "application/vnd.osgeo.mapguide.package", "mgp" },
+	{ "application/vnd.osgi.dp", "dp" },
+	{ "application/vnd.osgi.subsystem", "esa" },
+	{ "application/vnd.palm", "pdb" },
+	{ "application/vnd.pawaafile", "paw" },
+	{ "application/vnd.pg.format", "str" },
+	{ "application/vnd.pg.osasli", "ei6" },
+	{ "application/vnd.picsel", "efif" },
+	{ "application/vnd.pmi.widget", "wg" },
+	{ "application/vnd.pocketlearn", "plf" },
+	{ "application/vnd.powerbuilder6", "pbd" },
+	{ "application/vnd.previewsystems.box", "box" },
+	{ "application/vnd.proteus.magazine", "mgz" },
+	{ "application/vnd.publishare-delta-tree", "qps" },
+	{ "application/vnd.pvi.ptid1", "ptid" },
+	{ "application/vnd.quark.quarkxpress", "qxd" },
+	{ "application/vnd.realvnc.bed", "bed" },
+	{ "application/vnd.recordare.musicxml", "mxl" },
+	{ "application/vnd.recordare.musicxml+xml", "musicxml" },
+	{ "application/vnd.rig.cryptonote", "cryptonote" },
+	{ "application/vnd.rim.cod", "cod" },
+	{ "application/vnd.rn-realmedia", "rm" },
+	{ "application/vnd.rn-realmedia-vbr", "rmvb" },
+	{ "application/vnd.route66.link66+xml", "link66" },
+	{ "application/vnd.sailingtracker.track", "st" },
+	{ "application/vnd.seemail", "see" },
+	{ "application/vnd.sema", "sema" },
+	{ "application/vnd.semd", "semd" },
+	{ "application/vnd.semf", "semf" },
+	{ "application/vnd.shana.informed.formdata", "ifm" },
+	{ "application/vnd.shana.informed.formtemplate", "itp" },
+	{ "application/vnd.shana.informed.interchange", "iif" },
+	{ "application/vnd.shana.informed.package", "ipk" },
+	{ "application/vnd.simtech-mindmapper", "twd" },
+	{ "application/vnd.smaf", "mmf" },
+	{ "application/vnd.smart.teacher", "teacher" },
+	{ "application/vnd.solent.sdkm+xml", "sdkm" },
+	{ "application/vnd.spotfire.dxp", "dxp" },
+	{ "application/vnd.spotfire.sfs", "sfs" },
+	{ "application/vnd.stardivision.calc", "sdc" },
+	{ "application/vnd.stardivision.draw", "sda" },
+	{ "application/vnd.stardivision.impress", "sdd" },
+	{ "application/vnd.stardivision.math", "smf" },
+	{ "application/vnd.stardivision.writer", "sdw" },
+	{ "application/vnd.stardivision.writer-global", "sgl" },
+	{ "application/vnd.stepmania.package", "smzip" },
+	{ "application/vnd.stepmania.stepchart", "sm" },
+	{ "application/vnd.sun.xml.calc", "sxc" },
+	{ "application/vnd.sun.xml.calc.template", "stc" },
+	{ "application/vnd.sun.xml.draw", "sxd" },
+	{ "application/vnd.sun.xml.draw.template", "std" },
+	{ "application/vnd.sun.xml.impress", "sxi" },
+	{ "application/vnd.sun.xml.impress.template", "sti" },
+	{ "application/vnd.sun.xml.math", "sxm" },
+	{ "application/vnd.sun.xml.writer", "sxw" },
+	{ "application/vnd.sun.xml.writer.global", "sxg" },
+	{ "application/vnd.sun.xml.writer.template", "stw" },
+	{ "application/vnd.sus-calendar", "sus" },
+	{ "application/vnd.svd", "svd" },
+	{ "application/vnd.symbian.install", "sis" },
+	{ "application/vnd.syncml+xml", "xsm" },
+	{ "application/vnd.syncml.dm+wbxml", "bdm" },
+	{ "application/vnd.syncml.dm+xml", "xdm" },
+	{ "application/vnd.tao.intent-module-archive", "tao" },
+	{ "application/vnd.tcpdump.pcap", "pcap" },
+	{ "application/vnd.tmobile-livetv", "tmo" },
+	{ "application/vnd.trid.tpt", "tpt" },
+	{ "application/vnd.triscape.mxs", "mxs" },
+	{ "application/vnd.trueapp", "tra" },
+	{ "application/vnd.ufdl", "ufd" },
+	{ "application/vnd.uiq.theme", "utz" },
+	{ "application/vnd.umajin", "umj" },
+	{ "application/vnd.unity", "unityweb" },
+	{ "application/vnd.uoml+xml", "uoml" },
+	{ "application/vnd.vcx", "vcx" },
+	{ "application/vnd.visio", "vsd" },
+	{ "application/vnd.visionary", "vis" },
+	{ "application/vnd.vsf", "vsf" },
+	{ "application/vnd.wap.wbxml", "wbxml" },
+	{ "application/vnd.wap.wmlc", "wmlc" },
+	{ "application/vnd.wap.wmlscriptc", "wmlsc" },
+	{ "application/vnd.webturbo", "wtb" },
+	{ "application/vnd.wolfram.player", "nbp" },
+	{ "application/vnd.wordperfect", "wpd" },
+	{ "application/vnd.wqd", "wqd" },
+	{ "application/vnd.wt.stf", "stf" },
+	{ "application/vnd.xara", "xar" },
+	{ "application/vnd.xfdl", "xfdl" },
+	{ "application/vnd.yamaha.hv-dic", "hvd" },
+	{ "application/vnd.yamaha.hv-script", "hvs" },
+	{ "application/vnd.yamaha.hv-voice", "hvp" },
+	{ "application/vnd.yamaha.openscoreformat", "osf" },
+	{ "application/vnd.yamaha.openscoreformat.osfpvg+xml", "osfpvg" },
+	{ "application/vnd.yamaha.smaf-audio", "saf" },
+	{ "application/vnd.yamaha.smaf-phrase", "spf" },
+	{ "application/vnd.yellowriver-custom-menu", "cmp" },
+	{ "application/vnd.zul", "zir" },
+	{ "application/vnd.zzazz.deck+xml", "zaz" },
+	{ "application/voicexml+xml", "vxml" },
+	{ "application/widget", "wgt" },
+	{ "application/winhlp", "hlp" },
+	{ "application/wsdl+xml", "wsdl" },
+	{ "application/wspolicy+xml", "wspolicy" },
+	{ "application/x-7z-compressed", "7z" },
+	{ "application/x-abiword", "abw" },
+	{ "application/x-ace-compressed", "ace" },
+	{ "application/x-apple-diskimage", "dmg" },
+	{ "application/x-authorware-bin", "aab" },
+	{ "application/x-authorware-map", "aam" },
+	{ "application/x-authorware-seg", "aas" },
+	{ "application/x-bcpio", "bcpio" },
+	{ "application/x-bittorrent", "torrent" },
+	{ "application/x-blorb", "blb" },
+	{ "application/x-bzip", "bz" },
+	{ "application/x-bzip2", "bz2" },
+	{ "application/x-cbr", "cbr" },
+	{ "application/x-cdlink", "vcd" },
+	{ "application/x-cfs-compressed", "cfs" },
+	{ "application/x-chat", "chat" },
+	{ "application/x-chess-pgn", "pgn" },
+	{ "application/x-conference", "nsc" },
+	{ "application/x-cpio", "cpio" },
+	{ "application/x-csh", "csh" },
+	{ "application/x-debian-package", "deb" },
+	{ "application/x-dgc-compressed", "dgc" },
+	{ "application/x-director", "dir" },
+	{ "application/x-doom", "wad" },
+	{ "application/x-dtbncx+xml", "ncx" },
+	{ "application/x-dtbook+xml", "dtb" },
+	{ "application/x-dtbresource+xml", "res" },
+	{ "application/x-dvi", "dvi" },
+	{ "application/x-envoy", "evy" },
+	{ "application/x-eva", "eva" },
+	{ "application/x-font-bdf", "bdf" },
+	{ "application/x-font-ghostscript", "gsf" },
+	{ "application/x-font-linux-psf", "psf" },
+	{ "application/x-font-otf", "otf" },
+	{ "application/x-font-pcf", "pcf" },
+	{ "application/x-font-snf", "snf" },
+	{ "application/x-font-ttf", "ttf" },
+	{ "application/x-font-type1", "pfa" },
+	{ "application/font-woff", "woff" },
+	{ "application/x-freearc", "arc" },
+	{ "application/x-futuresplash", "spl" },
+	{ "application/x-gca-compressed", "gca" },
+	{ "application/x-glulx", "ulx" },
+	{ "application/x-gnumeric", "gnumeric" },
+	{ "application/x-gramps-xml", "gramps" },
+	{ "application/x-gtar", "gtar" },
+	{ "application/x-hdf", "hdf" },
+	{ "application/x-install-instructions", "install" },
+	{ "application/x-iso9660-image", "iso" },
+	{ "application/x-java-jnlp-file", "jnlp" },
+	{ "application/x-latex", "latex" },
+	{ "application/x-lzh-compressed", "lzh" },
+	{ "application/x-mie", "mie" },
+	{ "application/x-mobipocket-ebook", "prc" },
+	{ "application/x-ms-application", "application" },
+	{ "application/x-ms-shortcut", "lnk" },
+	{ "application/x-ms-wmd", "wmd" },
+	{ "application/x-ms-wmz", "wmz" },
+	{ "application/x-ms-xbap", "xbap" },
+	{ "application/x-msaccess", "mdb" },
+	{ "application/x-msbinder", "obd" },
+	{ "application/x-mscardfile", "crd" },
+	{ "application/x-msclip", "clp" },
+	{ "application/x-msdownload", "exe" },
+	{ "application/x-msmediaview", "mvb" },
+	{ "application/x-msmetafile", "wmf" },
+	{ "application/x-msmoney", "mny" },
+	{ "application/x-mspublisher", "pub" },
+	{ "application/x-msschedule", "scd" },
+	{ "application/x-msterminal", "trm" },
+	{ "application/x-mswrite", "wri" },
+	{ "application/x-netcdf", "nc" },
+	{ "application/x-nzb", "nzb" },
+	{ "application/x-pkcs12", "p12" },
+	{ "application/x-pkcs7-certificates", "p7b" },
+	{ "application/x-pkcs7-certreqresp", "p7r" },
+	{ "application/x-rar-compressed", "rar" },
+	{ "application/x-research-info-systems", "ris" },
+	{ "application/x-sh", "sh" },
+	{ "application/x-shar", "shar" },
+	{ "application/x-shockwave-flash", "swf" },
+	{ "application/x-silverlight-app", "xap" },
+	{ "application/x-sql", "sql" },
+	{ "application/x-stuffit", "sit" },
+	{ "application/x-stuffitx", "sitx" },
+	{ "application/x-subrip", "srt" },
+	{ "application/x-sv4cpio", "sv4cpio" },
+	{ "application/x-sv4crc", "sv4crc" },
+	{ "application/x-t3vm-image", "t3" },
+	{ "application/x-tads", "gam" },
+	{ "application/x-tar", "tar" },
+	{ "application/x-tcl", "tcl" },
+	{ "application/x-tex", "tex" },
+	{ "application/x-tex-tfm", "tfm" },
+	{ "application/x-texinfo", "texinfo" },
+	{ "application/x-tgif", "obj" },
+	{ "application/x-ustar", "ustar" },
+	{ "application/x-wais-source", "src" },
+	{ "application/x-x509-ca-cert", "der" },
+	{ "application/x-xfig", "fig" },
+	{ "application/x-xliff+xml", "xlf" },
+	{ "application/x-xpinstall", "xpi" },
+	{ "application/x-xz", "xz" },
+	{ "application/x-zmachine", "z1" },
+	{ "application/xaml+xml", "xaml" },
+	{ "application/xcap-diff+xml", "xdf" },
+	{ "application/xenc+xml", "xenc" },
+	{ "application/xhtml+xml", "xhtml" },
+	{ "application/xml", "xml" },
+	{ "application/xml-dtd", "dtd" },
+	{ "application/xop+xml", "xop" },
+	{ "application/xproc+xml", "xpl" },
+	{ "application/xslt+xml", "xslt" },
+	{ "application/xspf+xml", "xspf" },
+	{ "application/xv+xml", "mxml" },
+	{ "application/yang", "yang" },
+	{ "application/yin+xml", "yin" },
+	{ "application/zip", "zip" },
+	{ "audio/adpcm", "adp" },
+	{ "audio/basic", "au" },
+	{ "audio/midi", "mid" },
+	{ "audio/mp4", "mp4a" },
+	{ "audio/mpeg", "mpga" },
+	{ "audio/ogg", "oga" },
+	{ "audio/s3m", "s3m" },
+	{ "audio/silk", "sil" },
+	{ "audio/vnd.dece.audio", "uva" },
+	{ "audio/vnd.digital-winds", "eol" },
+	{ "audio/vnd.dra", "dra" },
+	{ "audio/vnd.dts", "dts" },
+	{ "audio/vnd.dts.hd", "dtshd" },
+	{ "audio/vnd.lucent.voice", "lvp" },
+	{ "audio/vnd.ms-playready.media.pya", "pya" },
+	{ "audio/vnd.nuera.ecelp4800", "ecelp4800" },
+	{ "audio/vnd.nuera.ecelp7470", "ecelp7470" },
+	{ "audio/vnd.nuera.ecelp9600", "ecelp9600" },
+	{ "audio/vnd.rip", "rip" },
+	{ "audio/webm", "weba" },
+	{ "audio/x-aac", "aac" },
+	{ "audio/x-aiff", "aif" },
+	{ "audio/x-caf", "caf" },
+	{ "audio/x-flac", "flac" },
+	{ "audio/x-matroska", "mka" },
+	{ "audio/x-mpegurl", "m3u" },
+	{ "audio/x-ms-wax", "wax" },
+	{ "audio/x-ms-wma", "wma" },
+	{ "audio/x-pn-realaudio", "ram" },
+	{ "audio/x-pn-realaudio-plugin", "rmp" },
+	{ "audio/x-wav", "wav" },
+	{ "audio/xm", "xm" },
+	{ "chemical/x-cdx", "cdx" },
+	{ "chemical/x-cif", "cif" },
+	{ "chemical/x-cmdf", "cmdf" },
+	{ "chemical/x-cml", "cml" },
+	{ "chemical/x-csml", "csml" },
+	{ "chemical/x-xyz", "xyz" },
+	{ "image/bmp", "bmp" },
+	{ "image/cgm", "cgm" },
+	{ "image/g3fax", "g3" },
+	{ "image/gif", "gif" },
+	{ "image/ief", "ief" },
+	{ "image/jpg", "jpg" },
+	{ "image/jpeg", "jpeg" },
+	{ "image/ktx", "ktx" },
+	{ "image/png", "png" },
+	{ "image/prs.btif", "btif" },
+	{ "image/sgi", "sgi" },
+	{ "image/svg+xml", "svg" },
+	{ "image/tiff", "tiff" },
+	{ "image/vnd.adobe.photoshop", "psd" },
+	{ "image/vnd.dece.graphic", "uvi" },
+	{ "image/vnd.dvb.subtitle", "sub" },
+	{ "image/vnd.djvu", "djvu" },
+	{ "image/vnd.dwg", "dwg" },
+	{ "image/vnd.dxf", "dxf" },
+	{ "image/vnd.fastbidsheet", "fbs" },
+	{ "image/vnd.fpx", "fpx" },
+	{ "image/vnd.fst", "fst" },
+	{ "image/vnd.fujixerox.edmics-mmr", "mmr" },
+	{ "image/vnd.fujixerox.edmics-rlc", "rlc" },
+	{ "image/vnd.ms-modi", "mdi" },
+	{ "image/vnd.ms-photo", "wdp" },
+	{ "image/vnd.net-fpx", "npx" },
+	{ "image/vnd.wap.wbmp", "wbmp" },
+	{ "image/vnd.xiff", "xif" },
+	{ "image/webp", "webp" },
+	{ "image/x-3ds", "3ds" },
+	{ "image/x-cmu-raster", "ras" },
+	{ "image/x-cmx", "cmx" },
+	{ "image/x-freehand", "fh" },
+	{ "image/x-icon", "ico" },
+	{ "image/x-mrsid-image", "sid" },
+	{ "image/x-pcx", "pcx" },
+	{ "image/x-pict", "pic" },
+	{ "image/x-portable-anymap", "pnm" },
+	{ "image/x-portable-bitmap", "pbm" },
+	{ "image/x-portable-graymap", "pgm" },
+	{ "image/x-portable-pixmap", "ppm" },
+	{ "image/x-rgb", "rgb" },
+	{ "image/x-tga", "tga" },
+	{ "image/x-xbitmap", "xbm" },
+	{ "image/x-xpixmap", "xpm" },
+	{ "image/x-xwindowdump", "xwd" },
+	{ "message/rfc822", "eml" },
+	{ "model/iges", "igs" },
+	{ "model/mesh", "msh" },
+	{ "model/vnd.collada+xml", "dae" },
+	{ "model/vnd.dwf", "dwf" },
+	{ "model/vnd.gdl", "gdl" },
+	{ "model/vnd.gtw", "gtw" },
+	{ "model/vnd.mts", "mts" },
+	{ "model/vnd.vtu", "vtu" },
+	{ "model/vrml", "wrl" },
+	{ "model/x3d+binary", "x3db" },
+	{ "model/x3d+vrml", "x3dv" },
+	{ "model/x3d+xml", "x3d" },
+	{ "text/cache-manifest", "appcache" },
+	{ "text/calendar", "ics" },
+	{ "text/css", "css" },
+	{ "text/csv", "csv" },
+	{ "text/html", "html" },
+	{ "text/n3", "n3" },
+	{ "text/plain", "txt" },
+	{ "text/prs.lines.tag", "dsc" },
+	{ "text/richtext", "rtx" },
+	{ "text/sgml", "sgml" },
+	{ "text/tab-separated-values", "tsv" },
+	{ "text/troff", "t" },
+	{ "text/turtle", "ttl" },
+	{ "text/uri-list", "uri" },
+	{ "text/vcard", "vcard" },
+	{ "text/vnd.curl", "curl" },
+	{ "text/vnd.curl.dcurl", "dcurl" },
+	{ "text/vnd.curl.scurl", "scurl" },
+	{ "text/vnd.curl.mcurl", "mcurl" },
+	{ "text/vnd.dvb.subtitle", "sub" },
+	{ "text/vnd.fly", "fly" },
+	{ "text/vnd.fmi.flexstor", "flx" },
+	{ "text/vnd.graphviz", "gv" },
+	{ "text/vnd.in3d.3dml", "3dml" },
+	{ "text/vnd.in3d.spot", "spot" },
+	{ "text/vnd.sun.j2me.app-descriptor", "jad" },
+	{ "text/vnd.wap.wml", "wml" },
+	{ "text/vnd.wap.wmlscript", "wmls" },
+	{ "text/x-asm", "s" },
+	{ "text/x-c", "c" },
+	{ "text/x-fortran", "f" },
+	{ "text/x-java-source", "java" },
+	{ "text/x-opml", "opml" },
+	{ "text/x-pascal", "p" },
+	{ "text/x-nfo", "nfo" },
+	{ "text/x-setext", "etx" },
+	{ "text/x-sfv", "sfv" },
+	{ "text/x-uuencode", "uu" },
+	{ "text/x-vcalendar", "vcs" },
+	{ "text/x-vcard", "vcf" },
+	{ "text/xml", "xml" },
+	{ "video/3gpp", "3gp" },
+	{ "video/3gpp2", "3g2" },
+	{ "video/h261", "h261" },
+	{ "video/h263", "h263" },
+	{ "video/h264", "h264" },
+	{ "video/jpeg", "jpgv" },
+	{ "video/jpm", "jpm" },
+	{ "video/mj2", "mj2" },
+	{ "video/mp4", "mp4" },
+	{ "video/mpeg", "mpeg" },
+	{ "video/ogg", "ogv" },
+	{ "video/quicktime", "qt" },
+	{ "video/vnd.dece.hd", "uvh" },
+	{ "video/vnd.dece.mobile", "uvm" },
+	{ "video/vnd.dece.pd", "uvp" },
+	{ "video/vnd.dece.sd", "uvs" },
+	{ "video/vnd.dece.video", "uvv" },
+	{ "video/vnd.dvb.file", "dvb" },
+	{ "video/vnd.fvt", "fvt" },
+	{ "video/vnd.mpegurl", "mxu" },
+	{ "video/vnd.ms-playready.media.pyv", "pyv" },
+	{ "video/vnd.uvvu.mp4", "uvu" },
+	{ "video/vnd.vivo", "viv" },
+	{ "video/webm", "webm" },
+	{ "video/x-f4v", "f4v" },
+	{ "video/x-fli", "fli" },
+	{ "video/x-flv", "flv" },
+	{ "video/x-m4v", "m4v" },
+	{ "video/x-matroska", "mkv" },
+	{ "video/x-mng", "mng" },
+	{ "video/x-ms-asf", "asf" },
+	{ "video/x-ms-vob", "vob" },
+	{ "video/x-ms-wm", "wm" },
+	{ "video/x-ms-wmv", "wmv" },
+	{ "video/x-ms-wmx", "wmx" },
+	{ "video/x-ms-wvx", "wvx" },
+	{ "video/x-msvideo", "avi" },
+	{ "video/x-sgi-movie", "movie" },
+	{ "video/x-smv", "smv" },
+	{ "x-conference/x-cooltalk", "ice" }
+};
+
+/**
+* Obtain default file extension for a give MIME type
+*
+* @param mimeType a MIME type (lowercase string), e.g. "image/png"
+* @param extension a buffer in which to store the file extension; the default value is "txt" if no extension is found
+* @param length the size of the buffer extension
+* @return true if a file extension is found for the given MIME type, otherwise false
+*/
+static bool getFileExtension(const char* mimeType, char* extension, size_t length) {
+
+	bool hasExt = false;
+	strncpy(extension, "txt", length);
+	
+	if (mimeType != NULL) { 	
+		for (int i = 0; i < NUM_MIME_TYPES; i++) {					
+			if 	(strncmp(mimeType, MIME[i][M_Type], strlen(MIME[i][M_Type])) == 0) {
+				strncpy(extension, MIME[i][M_Extension], length);
+				hasExt = true;
+				break;				
+			}		
+		}
+		if (hasExt == false && strncmp(mimeType, "image/", 6) == 0) {
+			strncpy(extension, strstr(mimeType, "/") + 1, length);
+		}	
+	}	
+	return hasExt;
+}
+
+/**
+* Obtain default file extension for a give MIME type
+*
+* @param mimeType a MIME type (lowercase string), e.g. "image/png"
+* @param hasExt the value of this pointer is set to true if a default file extension is found, otherwise false
+* @return a map with name "extension" and value set to file extension, e.g. "png"; if not found the default value is "txt" 
+*/
+static map* getFileExtensionMap(const char* mimeType, bool* hasExt) {
+
+	map* ext = createMap("extension", "txt");
+	*hasExt = false;
+	
+	if (mimeType != NULL) { 	
+		for (int i = 0; i < NUM_MIME_TYPES; i++) {			
+			if 	(strncmp(mimeType, MIME[i][M_Type], strlen(MIME[i][M_Type])) == 0) {
+				ext->value = zStrdup(MIME[i][M_Extension]);
+				*hasExt = true;
+				break;				
+			}		
+		}
+		if (*hasExt == false && strncmp(mimeType, "image/", 6) == 0) {
+			ext->value = zStrdup(strstr(mimeType, "/") + 1);
+		}			
+	}	
+	return ext;
+}
diff --git a/zoo-project/zoo-kernel/nmake.opt b/zoo-project/zoo-kernel/nmake.opt
new file mode 100755
index 0000000..9d9f6ad
--- /dev/null
+++ b/zoo-project/zoo-kernel/nmake.opt
@@ -0,0 +1,89 @@
+PROGRAMNAME=zoo_loader.cgi
+LIBZOO_SERVICE=libzoo_service.dll
+
+CC=cl $(CFLAGS)
+CPP=cl /TP $(CFLAGS)
+
+#PY_DIR=C:/"Program Files (x86)"/Python3.3
+#PY_LIB=$(PY_DIR)/libs/python33.lib
+
+#PHP_DIR=C:\php-sdk\phpdev\vc12\x86\php-5.5.10-src
+#PHP_LIB=$(PHP_DIR)\Release_TS\php5embed.lib
+
+!IF DEFINED(MS_DIR)
+MS_BASE=$(MS_DIR)
+!INCLUDE $(MS_DIR)\nmake.opt
+!ENDIF
+
+!IFDEF JS_DIR
+JS_CFLAGS=-DXP_WIN -DUSE_JS -I$(JS_DIR)
+JS_LDFLAGS=$(JS_DIR)/mozjs185-1.0.lib
+JS_FILE=service_internal_js.obj
+!ENDIF
+
+!IFDEF MS_DIR
+MS_CFLAGS=-DUSE_MS -I$(MS_DIR)
+MS_LDFLAGS=$(MS_DIR)/mapserver_i.lib
+MS_FILE=service_internal_ms.obj
+!ENDIF
+
+!IFDEF JDK_DIR
+JAVA_CFLAGS=-DJAVA7 -DUSE_JAVA -I"$(JDK_DIR)\include" -I"$(JDK_DIR)\include\win32"
+JAVA_LDFLAGS="$(JDK_DIR)/lib/jvm.lib"
+JAVA_FILE=service_internal_java.obj
+!ENDIF
+
+!IFDEF PY_DIR
+PY_CFLAGS=-DUSE_PYTHON -I$(PY_DIR)\Include -I$(PY_DIR)\PC
+PY_LDFLAGS=$(PY_LIBRARY) 
+PY_FILE=service_internal_python.obj
+!ENDIF
+
+!IFDEF PHP_DIR
+PHP_LIB=$(PHP_DIR)\Release_TS\php5embed.lib
+PHP_CURL_LIB=$(PHP_DIR)\Release_TS\php_curl.lib
+PHP_SRC=$(PHP_DIR)
+PHP_LDFLAGS=$(PHP_LIB) $(PHP_CURL_LIB)
+PHP_FILE=service_internal_php.obj
+PHP_CFLAGS=-I$(PHP_SRC) -I$(PHP_SRC)\Zend -I$(PHP_SRC)\TSRM /DPHP_WIN32 /DZEND_WIN32 /DWIN32 /D_USE_32BIT_TIME_T /DZTS /DUSE_PHP
+!ENDIF
+
+!IFDEF RUBY_DIR
+#################################################################
+#RUBY 1.8.7
+ZRUBY_VERSION=1
+RUBY_CFLAGS=-DZRUBY_VERSION=1 -DUSE_RUBY -I$(RUBY_DIR) 
+RUBY_LDFLAGS="$(RUBY_DIR)/msvcr100-ruby18.lib"
+#################################################################
+#RUBY 1.9.3
+#ZRUBY_VERSION=2
+#RUBY_CFLAGS=-DZRUBY_VERSION=2 -DUSE_RUBY -I$(RUBY_DIR)/include/ruby-1.9.1/ -I$(RUBY_DIR)/include/ruby-1.9.1/i386-mswin32_100
+#RUBY_LDFLAGS="$(RUBY_DIR)/lib/msvcr100-ruby191.lib"
+#RUBY 2.1.0
+#ZRUBY_VERSION=2
+#RUBY_CFLAGS=-DZRUBY_VERSION=2 -DUSE_RUBY -I$(RUBY_DIR)/include/ruby-2.1.0/ -I$(RUBY_DIR)/include/ruby-2.1.0/i386-mswin32_100
+#RUBY_LDFLAGS="$(RUBY_DIR)/lib/msvcr100-ruby210.lib"
+#################################################################
+RUBY_FILE=service_internal_ruby.obj
+!IFDEF MS_DIR
+RUBY_CFLAGS=$(RUBY_CFLAGS) -DHAVE_ROUND
+!ENDIF
+!ENDIF
+
+!IFNDEF ZOOK_DIR
+ZOOK_DIR=.
+!ENDIF
+
+TROOT=$(ZOOK_DIR)
+TPATH=$(ZOOK_DIR)\..\..\..\tools
+LIBINTL_CPATH=$(ZOOK_DIR)\..\..\..\
+PYTHON_CPATH=$(PY_DIR)
+
+!IFDEF DB
+DB_FLAGS=-DRELY_ON_DB
+!ENDIF
+
+CFLAGS= $(DB_FLAGS) $(MS_DEFS) $(INCLUDES) $(CFLAGS1) /nologo /MD /W3 /EHsc /Ox /D_CRT_SECURE_NO_WARNINGS /DWIN32 /DPROGRAMNAME=\"$(PROGRAMNAME)\" $(CJFLAGS) -I$(ZOOK_DIR) $(RUBY_CFLAGS) -I./ $(JAVA_CFLAGS) $(MS_CFLAGS) -I$(TROOT)\..\..\thirds\dirent-win32 -I$(INTL_DIR) -I$(CURL_DIR)\include -I$(XML2_DIR)\include -I$(GDAL_DIR)\port $(JS_CFLAGS) -I$(GDAL_DIR)\ogr -I$(GDAL_DIR)\gcore -I$(GD_DIR) -I$(ICONV_DIR) -I$(TROOT)\..\..\thirds\include -I$(TROOT)\..\..\thirds\cgic206 -I$(PYTHON_CPATH [...]
+
+LDFLAGSCGI=$(TROOT)/../../thirds/cgic206/libcgic.lib 
+LDFLAGS=$(FCGI_DIR)/libfcgi/Release/libfcgi.lib $(CURL_LIBRARY) $(PY_LDFLAGS) $(XML2_LIBRARY) $(SSL_DIR)/out32dll/libeay32.lib $(JAVA_LDFLAGS) $(SSL_DIR)/out32dll/ssleay32.lib $(MS_LDFLAGS) $(INTL_DIR)/intl.lib $(XML2_DIR)/win32/bin.msvc/libxml2.lib $(GDAL_DIR)/gdal_i.lib $(CURL_DIR)/lib/libcurl.lib $(JS_LDFLAGS) $(RUBY_LDFLAGS) $(PHP_LDFLAGS) /machine:i386
diff --git a/zoo-project/zoo-kernel/otbZooWatcher.cxx b/zoo-project/zoo-kernel/otbZooWatcher.cxx
new file mode 100644
index 0000000..6b803a9
--- /dev/null
+++ b/zoo-project/zoo-kernel/otbZooWatcher.cxx
@@ -0,0 +1,70 @@
+/*=========================================================================
+
+  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
+  See OTBCopyright.txt for details.
+
+  Some parts of this code are derived from ITK. See ITKCopyright.txt
+  for details.
+
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+
+  See Ref: http://hg.orfeo-toolbox.org/OTB/ Copyright
+
+=========================================================================*/
+#include "otbZooWatcher.h"
+#include "service_internal.h"
+
+ZooWatcher
+::ZooWatcher()
+{
+}
+
+ZooWatcher
+::ZooWatcher(itk::ProcessObject* process,
+	     const char *comment)
+  : otb::FilterWatcherBase(process, comment)
+{
+}
+
+ZooWatcher
+::ZooWatcher(itk::ProcessObject* process,
+	     const std::string& comment)
+  : otb::FilterWatcherBase(process, comment.c_str())
+{
+}
+
+void
+ZooWatcher
+::ShowProgress()
+{
+  if (m_Process)
+    {
+      int progressPercent = static_cast<int>(m_Process->GetProgress() * 100);
+      updateStatus(m_Conf,progressPercent,m_Comment.c_str());
+    }
+}
+
+void
+ZooWatcher
+::StartFilter()
+{
+  m_TimeProbe.Start();
+}
+
+void
+ZooWatcher
+::EndFilter()
+{
+  m_TimeProbe.Stop();
+  std::ostringstream elapsedTime;
+  elapsedTime.precision(1);
+  elapsedTime << m_TimeProbe.GetMean();
+
+  std::cerr << " (OTB Execution: "
+            << elapsedTime.str()
+            << " seconds)"
+            << std::endl;
+}
diff --git a/zoo-project/zoo-kernel/otbZooWatcher.h b/zoo-project/zoo-kernel/otbZooWatcher.h
new file mode 100644
index 0000000..e8cc176
--- /dev/null
+++ b/zoo-project/zoo-kernel/otbZooWatcher.h
@@ -0,0 +1,91 @@
+/*=========================================================================
+
+  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
+  See OTBCopyright.txt for details.
+
+  Some parts of this code are derived from ITK. See ITKCopyright.txt
+  for details.
+
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notices for more information.
+
+  See Ref: http://hg.orfeo-toolbox.org/OTB/ Copyright
+
+=========================================================================*/
+#ifndef __zooOtbWatcher_h
+#define __zooOtbWatcher_h
+
+#include "otbFilterWatcherBase.h"
+#include "service.h"
+
+/**
+ * Observer used to access the ongoing status of a running OTB Application
+ */
+class /*ITK_EXPORT*/ ZooWatcher : public otb::FilterWatcherBase
+{
+public:
+
+  /**
+   * Constructor
+   * @param process the itk::ProcessObject to monitor
+   * @param comment comment string that is prepended to each event message
+   */
+  ZooWatcher(itk::ProcessObject* process,
+                        const char *comment = "");
+
+  /**
+   * Constructor
+   * @param process the itk::ProcessObject to monitor
+   * @param comment comment string that is prepended to each event message
+   */
+  ZooWatcher(itk::ProcessObject* process,
+                        const std::string& comment = "");
+
+  /** Default constructor */
+  ZooWatcher();
+
+  /** 
+   * Copy the original conf in the m_Conf property
+   *
+   * @param conf the maps pointer to copy
+   */
+  void SetConf(maps **conf)
+  {
+    m_Conf=dupMaps(conf);
+  }
+  /**  
+   * Get Configuration maps (m_Conf)
+   * @return the m_Conf property
+   */
+  const maps& GetConf() const
+  {
+    return *m_Conf;
+  }
+  /**  
+   * Free Configuration maps (m_Conf)
+   */
+  void FreeConf(){
+    freeMaps(&m_Conf);
+    free(m_Conf);
+  }
+protected:
+
+  /** Callback method to show the ProgressEvent */
+  virtual void ShowProgress();
+
+  /** Callback method to show the StartEvent */
+  virtual void StartFilter();
+
+  /** Callback method to show the EndEvent */
+  virtual void EndFilter();
+
+private:
+
+  /** Main conf maps */
+  maps* m_Conf;
+
+};
+
+#endif
diff --git a/zoo-project/zoo-kernel/request_parser.c b/zoo-project/zoo-kernel/request_parser.c
new file mode 100644
index 0000000..8ccb1a8
--- /dev/null
+++ b/zoo-project/zoo-kernel/request_parser.c
@@ -0,0 +1,1762 @@
+/*
+ * Author : Gérald FENOY
+ *
+ * Copyright (c) 2015 GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "request_parser.h"
+#include "service_internal.h"
+#include "server_internal.h"
+#include "response_print.h"
+#include "caching.h"
+
+/**
+ * Apply XPath Expression on XML document.
+ *
+ * @param doc the XML Document
+ * @param search the XPath expression
+ * @return xmlXPathObjectPtr containing the resulting nodes set
+ */
+xmlXPathObjectPtr
+extractFromDoc (xmlDocPtr doc, const char *search)
+{
+  xmlXPathContextPtr xpathCtx;
+  xmlXPathObjectPtr xpathObj;
+  xpathCtx = xmlXPathNewContext (doc);
+  xpathObj = xmlXPathEvalExpression (BAD_CAST search, xpathCtx);
+  xmlXPathFreeContext (xpathCtx);
+  return xpathObj;
+}
+
+/**
+ * Create (or append to) an array valued maps value = "["",""]"
+ *
+ * @param m the conf maps containing the main.cfg settings
+ * @param mo the map to update
+ * @param mi the map to append
+ * @param elem the elements containing default definitions
+ * @return 0 on success, -1 on failure
+ */
+int appendMapsToMaps (maps * m, maps * mo, maps * mi, elements * elem){
+  maps *tmpMaps = getMaps (mo, mi->name);
+  map *tmap = getMapType (tmpMaps->content);
+  elements *el = getElements (elem, mi->name);
+  int hasEl = 1;
+  if (el == NULL)
+    hasEl = -1;
+  if (tmap == NULL)
+    {
+      if (hasEl > 0)
+	tmap = getMapType (el->defaults->content);
+    }
+  
+  map *testMap = NULL;
+  if (hasEl > 0)
+    {
+      testMap = getMap (el->content, "maxOccurs");
+    }
+  else
+    {
+      testMap = createMap ("maxOccurs", "unbounded");
+    }
+    
+  if (testMap != NULL)
+    {
+      if (strncasecmp (testMap->value, "unbounded", 9) != 0
+	  && atoi (testMap->value) > 1)
+	{
+	  addMapsArrayToMaps (&mo, mi, tmap->name);
+	  map* nb=getMapFromMaps(mo,mi->name,"length");
+	  if (nb!=NULL && atoi(nb->value)>atoi(testMap->value))
+	    {
+	      char emsg[1024];
+	      sprintf (emsg,
+		       _("The maximum allowed occurrences for <%s> (%i) was exceeded."),
+		       mi->name, atoi (testMap->value));
+	      errorException (m, emsg, "InternalError", NULL);
+	      return -1;
+	    }
+	}
+      else
+	{
+	  if (strncasecmp (testMap->value, "unbounded", 9) == 0)
+	    {
+	      if (hasEl < 0)
+		{
+		  freeMap (&testMap);
+		  free (testMap);
+		}
+	      if (addMapsArrayToMaps (&mo, mi, tmap->name) < 0)
+		{
+		  char emsg[1024];
+		  map *tmpMap = getMap (mi->content, "length");
+		  sprintf (emsg,
+			   _
+			   ("ZOO-Kernel was unable to load your data for %s position %s."),
+			   mi->name, tmpMap->value);
+		  errorException (m, emsg, "InternalError", NULL);
+		  return -1;
+		}
+	    }
+	  else
+	    {
+	      char emsg[1024];
+	      sprintf (emsg,
+		       _
+		       ("The maximum allowed occurrences for <%s> is one."),
+		       mi->name);
+	      errorException (m, emsg, "InternalError", NULL);
+	      return -1;
+	    }
+	}
+    }
+  return 0;
+}
+
+/**
+ * Make sure that each value encoded in base64 in a maps is decoded.
+ *
+ * @param in the maps containing the values
+ * @see readBase64
+ */
+void ensureDecodedBase64(maps **in){
+  maps* cursor=*in;
+  while(cursor!=NULL){
+    map *tmp=getMap(cursor->content,"encoding");
+    if(tmp!=NULL && strncasecmp(tmp->value,"base64",6)==0){
+      tmp=getMap(cursor->content,"value");
+      readBase64(&tmp);
+      addToMap(cursor->content,"base64_value",tmp->value);
+      int size=0;
+      char *s=strdup(tmp->value);
+      free(tmp->value);
+      tmp->value=base64d(s,strlen(s),&size);
+      free(s);
+      char sizes[1024];
+      sprintf(sizes,"%d",size);
+      addToMap(cursor->content,"size",sizes);
+    }
+    map* length=getMap(cursor->content,"length");
+    if(length!=NULL){
+      int len=atoi(length->value);
+      for(int i=1;i<len;i++){
+	tmp=getMapArray(cursor->content,"encoding",i);
+	if(tmp!=NULL && strncasecmp(tmp->value,"base64",6)==0){
+	  char key[17];
+	  sprintf(key,"base64_value_%d",i);
+	  tmp=getMapArray(cursor->content,"value",i);
+	  readBase64(&tmp);
+	  addToMap(cursor->content,key,tmp->value);
+	  int size=0;
+	  char *s=strdup(tmp->value);
+	  free(tmp->value);
+	  tmp->value=base64d(s,strlen(s),&size);
+	  free(s);
+	  char sizes[1024];
+	  sprintf(sizes,"%d",size);
+	  sprintf(key,"size_%d",i);
+	  addToMap(cursor->content,key,sizes);
+	}
+      }
+    }
+    cursor=cursor->next;
+  }
+}
+
+/**
+ * Parse inputs provided as KVP and store them in a maps.
+ *
+ * @param main_conf the conf maps containing the main.cfg settings
+ * @param s the service
+ * @param request_inputs the map storing KVP raw value 
+ * @param request_output the maps to store the KVP pairs 
+ * @param hInternet the HINTERNET queue to add potential requests
+ * @return 0 on success, -1 on failure
+ */
+int kvpParseInputs(maps** main_conf,service* s,map *request_inputs,maps** request_output,HINTERNET* hInternet){
+  // Parsing inputs provided as KVP
+  maps *tmpmaps = *request_output;
+  map* r_inputs = getMap (request_inputs, "DataInputs");
+  char* cursor_input;
+  if (r_inputs != NULL){
+    //snprintf (cursor_input, 40960, "%s", r_inputs->value);
+    if(strstr(r_inputs->value,"=")==NULL)
+      cursor_input = url_decode (r_inputs->value);
+    else
+      cursor_input = zStrdup (r_inputs->value);
+    int j = 0;
+
+    // Put each DataInputs into the inputs_as_text array
+    char *pToken;
+    pToken = strtok (cursor_input, ";");
+    char **inputs_as_text = (char **) malloc (100 * sizeof (char *));
+    if (inputs_as_text == NULL)
+      {
+	free(cursor_input);
+	return errorException (*main_conf, _("Unable to allocate memory"),
+			       "InternalError", NULL);
+      }
+    int i = 0;
+    while (pToken != NULL)
+      {
+	inputs_as_text[i] =
+	  (char *) malloc ((strlen (pToken) + 1) * sizeof (char));
+	if (inputs_as_text[i] == NULL)
+	  {
+	    free(cursor_input);
+	    return errorException (*main_conf, _("Unable to allocate memory"),
+				   "InternalError", NULL);
+	  }
+	snprintf (inputs_as_text[i], strlen (pToken) + 1, "%s", pToken);
+	pToken = strtok (NULL, ";");
+	i++;
+      }
+	
+    for (j = 0; j < i; j++)
+      {
+	char *tmp = zStrdup (inputs_as_text[j]);
+	free (inputs_as_text[j]);
+	char *tmpc;
+	tmpc = strtok (tmp, "@");
+	while (tmpc != NULL)
+	  {
+	    char *tmpv = strstr (tmpc, "=");
+	    char tmpn[256];
+	    memset (tmpn, 0, 256);
+	    if (tmpv != NULL)
+	      {
+		strncpy (tmpn, tmpc,
+			 (strlen (tmpc) - strlen (tmpv)) * sizeof (char));
+		tmpn[strlen (tmpc) - strlen (tmpv)] = 0;
+	      }
+	    else
+	      {
+		strncpy (tmpn, tmpc, strlen (tmpc) * sizeof (char));
+		tmpn[strlen (tmpc)] = 0;
+	      }
+	    if (tmpmaps == NULL)
+	      {
+		tmpmaps = (maps *) malloc (MAPS_SIZE);
+		if (tmpmaps == NULL)
+		  {
+		    free(cursor_input);
+		    return errorException (*main_conf,
+					   _("Unable to allocate memory"),
+					   "InternalError", NULL);
+		  }
+		tmpmaps->name = zStrdup (tmpn);
+		if (tmpv != NULL)
+		  {
+		    char *tmpvf = url_decode (tmpv + 1);
+		    tmpmaps->content = createMap ("value", tmpvf);
+		    free (tmpvf);
+		  }
+		else
+		  tmpmaps->content = createMap ("value", "Reference");
+		tmpmaps->next = NULL;
+	      }
+	    tmpc = strtok (NULL, "@");
+	    while (tmpc != NULL)
+	      {
+		char *tmpv1 = strstr (tmpc, "=");
+		char tmpn1[1024];
+		memset (tmpn1, 0, 1024);
+		if (tmpv1 != NULL)
+		  {
+		    strncpy (tmpn1, tmpc, strlen (tmpc) - strlen (tmpv1));
+		    tmpn1[strlen (tmpc) - strlen (tmpv1)] = 0;
+		    addToMap (tmpmaps->content, tmpn1, tmpv1 + 1);
+		  }
+		else
+		  {
+		    strncpy (tmpn1, tmpc, strlen (tmpc));
+		    tmpn1[strlen (tmpc)] = 0;
+		    map *lmap = getLastMap (tmpmaps->content);
+		    char *tmpValue =
+		      (char *) malloc ((strlen (tmpv) + strlen (tmpc) + 1) *
+				       sizeof (char));
+		    sprintf (tmpValue, "%s@%s", tmpv + 1, tmpc);
+		    free (lmap->value);
+		    lmap->value = zStrdup (tmpValue);
+		    free (tmpValue);
+		    tmpc = strtok (NULL, "@");
+		    continue;
+		  }
+		if (strcmp (tmpn1, "xlink:href") != 0)
+		  addToMap (tmpmaps->content, tmpn1, tmpv1 + 1);
+		else if (tmpv1 != NULL)
+		  {
+		    char *tmpx2 = url_decode (tmpv1 + 1);
+		    if (strncasecmp (tmpx2, "http://", 7) != 0 &&
+			strncasecmp (tmpx2, "ftp://", 6) != 0 &&
+			strncasecmp (tmpx2, "https://", 8) != 0)
+		      {
+			char emsg[1024];
+			sprintf (emsg,
+				 _
+				 ("Unable to find a valid protocol to download the remote file %s"),
+				 tmpv1 + 1);
+			free(cursor_input);
+			return errorException (*main_conf, emsg, "InternalError", NULL);
+		      }
+		    addToMap (tmpmaps->content, tmpn1, tmpx2);
+		    {
+		      if (loadRemoteFile
+			  (&*main_conf, &tmpmaps->content, hInternet, tmpx2) < 0)
+			{
+			  free(cursor_input);
+			  return errorException (*main_conf, "Unable to fetch any ressource", "InternalError", NULL);
+			}
+		      }
+		    free (tmpx2);
+		    addIntToMap (tmpmaps->content, "Order", hInternet->nb);
+		    addToMap (tmpmaps->content, "Reference", tmpv1 + 1);
+		  }
+		tmpc = strtok (NULL, "@");
+	      }
+	    if (*request_output == NULL)
+	      *request_output = dupMaps (&tmpmaps);
+	    else
+	      {
+		maps *testPresence =
+		  getMaps (*request_output, tmpmaps->name);
+		if (testPresence != NULL)
+		  {
+		    elements *elem =
+		      getElements (s->inputs, tmpmaps->name);
+		    if (elem != NULL)
+		      {
+			if (appendMapsToMaps
+			    (*main_conf, *request_output, tmpmaps,
+			     elem) < 0)
+			  {
+			    free(cursor_input);
+			    return errorException (*main_conf, "Unable to append maps", "InternalError", NULL);
+			  }
+		      }
+		  }
+		else
+		  addMapsToMaps (request_output, tmpmaps);
+	      }
+	    freeMaps (&tmpmaps);
+	    free (tmpmaps);
+	    tmpmaps = NULL;
+	    free (tmp);
+	  }
+      }
+    free (inputs_as_text);
+    free(cursor_input);
+  }
+  return 1;
+}
+
+/**
+ * Parse outputs provided as KVP and store them in a maps.
+ *
+ * @param main_conf the conf maps containing the main.cfg settings
+ * @param request_inputs the map storing KVP raw value 
+ * @param request_output the maps to store the KVP pairs 
+ * @return 0 on success, -1 on failure
+ */
+int kvpParseOutputs(maps** main_conf,map *request_inputs,maps** request_output){
+  /**
+   * Parsing outputs provided as KVP
+   */
+  map *r_inputs = NULL;
+  r_inputs = getMap (request_inputs, "ResponseDocument");
+  if (r_inputs == NULL)
+    r_inputs = getMap (request_inputs, "RawDataOutput");
+
+  if (r_inputs != NULL)
+    {
+      char *cursor_output = zStrdup (r_inputs->value);
+      int j = 0;
+
+      /**
+       * Put each Output into the outputs_as_text array
+       */
+      char *pToken;
+      maps *tmp_output = NULL;
+      pToken = strtok (cursor_output, ";");
+      char **outputs_as_text = (char **) malloc (128 * sizeof (char *));
+      if (outputs_as_text == NULL)
+	{
+	  free(cursor_output);
+	  return errorException (*main_conf, _("Unable to allocate memory"),
+				 "InternalError", NULL);
+	}
+      int i = 0;
+      while (pToken != NULL)
+	{
+	  outputs_as_text[i] =
+	    (char *) malloc ((strlen (pToken) + 1) * sizeof (char));
+	  if (outputs_as_text[i] == NULL)
+	    {
+	      free(cursor_output);
+	      return errorException (*main_conf, _("Unable to allocate memory"),
+				     "InternalError", NULL);
+	    }
+	  snprintf (outputs_as_text[i], strlen (pToken) + 1, "%s",
+		    pToken);
+	  pToken = strtok (NULL, ";");
+	  i++;
+	}
+      for (j = 0; j < i; j++)
+	{
+	  char *tmp = zStrdup (outputs_as_text[j]);
+	  free (outputs_as_text[j]);
+	  char *tmpc;
+	  tmpc = strtok (tmp, "@");
+	  int k = 0;
+	  while (tmpc != NULL)
+	    {
+	      if (k == 0)
+		{
+		  if (tmp_output == NULL)
+		    {
+		      tmp_output = (maps *) malloc (MAPS_SIZE);
+		      if (tmp_output == NULL)
+			{
+			  free(cursor_output);
+			  return errorException (*main_conf,
+						 _
+						 ("Unable to allocate memory"),
+						 "InternalError", NULL);
+			}
+		      tmp_output->name = zStrdup (tmpc);
+		      tmp_output->content = NULL;
+		      tmp_output->next = NULL;
+		    }
+		}
+	      else
+		{
+		  char *tmpv = strstr (tmpc, "=");
+		  char tmpn[256];
+		  memset (tmpn, 0, 256);
+		  strncpy (tmpn, tmpc,
+			   (strlen (tmpc) -
+			    strlen (tmpv)) * sizeof (char));
+		  tmpn[strlen (tmpc) - strlen (tmpv)] = 0;
+		  if (tmp_output->content == NULL)
+		    {
+		      tmp_output->content = createMap (tmpn, tmpv + 1);
+		      tmp_output->content->next = NULL;
+		    }
+		  else
+		    addToMap (tmp_output->content, tmpn, tmpv + 1);
+		}
+	      k++;
+	      tmpc = strtok (NULL, "@");
+	    }
+	  if (*request_output == NULL)
+	    *request_output = dupMaps (&tmp_output);
+	  else
+	    addMapsToMaps (request_output, tmp_output);
+	  freeMaps (&tmp_output);
+	  free (tmp_output);
+	  tmp_output = NULL;
+	  free (tmp);
+	}
+      free (outputs_as_text);
+      free(cursor_output);
+    }
+  return 1;
+}
+
+/**
+ * Parse inputs from XML nodes and store them in a maps.
+ *
+ * @param main_conf the conf maps containing the main.cfg settings
+ * @param s the service
+ * @param request_output the maps to store the KVP pairs 
+ * @param doc the xmlDocPtr containing the original request
+ * @param nodes the input nodes array
+ * @param hInternet the HINTERNET queue to add potential requests
+ * @return 0 on success, -1 on failure
+ */
+int xmlParseInputs(maps** main_conf,service* s,maps** request_output,xmlDocPtr doc,xmlNodeSet* nodes,HINTERNET* hInternet){
+  int k = 0;
+  int l = 0;
+  map* version=getMapFromMaps(*main_conf,"main","rversion");
+  int vid=getVersionId(version->value);
+  for (k=0; k < nodes->nodeNr; k++)
+    {
+      maps *tmpmaps = NULL;
+      xmlNodePtr cur = nodes->nodeTab[k];
+
+      if (nodes->nodeTab[k]->type == XML_ELEMENT_NODE)
+	{
+	  // A specific Input node.
+	  if(vid==1){
+	    tmpmaps = (maps *) malloc (MAPS_SIZE);
+	    xmlChar *val = xmlGetProp (cur, BAD_CAST "id");
+	    tmpmaps->name = zStrdup ((char *) val);
+	    tmpmaps->content = NULL;
+	    tmpmaps->next = NULL;
+	  }
+
+	  xmlNodePtr cur2 = cur->children;
+	  while (cur2 != NULL)
+	    {
+	      while (cur2 != NULL && cur2->type != XML_ELEMENT_NODE)
+		cur2 = cur2->next;
+	      if (cur2 == NULL)
+		break;
+	      // Indentifier
+	      if (xmlStrncasecmp
+		  (cur2->name, BAD_CAST "Identifier",
+		   xmlStrlen (cur2->name)) == 0)
+		{
+		  xmlChar *val =
+		    xmlNodeListGetString (doc, cur2->xmlChildrenNode, 1);
+		  if (tmpmaps == NULL)
+		    {
+		      tmpmaps = (maps *) malloc (MAPS_SIZE);
+		      if (tmpmaps == NULL)
+			{
+			  return errorException (*main_conf,
+						 _
+						 ("Unable to allocate memory"),
+						 "InternalError", NULL);
+			}
+		      tmpmaps->name = zStrdup ((char *) val);
+		      tmpmaps->content = NULL;
+		      tmpmaps->next = NULL;
+		    }
+		  xmlFree (val);
+		}
+	      // Title, Asbtract
+	      if (xmlStrncasecmp
+		  (cur2->name, BAD_CAST "Title",
+		   xmlStrlen (cur2->name)) == 0
+		  || xmlStrncasecmp (cur2->name, BAD_CAST "Abstract",
+				     xmlStrlen (cur2->name)) == 0)
+		{
+		  xmlChar *val =
+		    xmlNodeListGetString (doc, cur2->xmlChildrenNode, 1);
+		  if (tmpmaps == NULL)
+		    {
+		      tmpmaps = (maps *) malloc (MAPS_SIZE);
+		      if (tmpmaps == NULL)
+			{
+			  return errorException (*main_conf,
+						 _
+						 ("Unable to allocate memory"),
+						 "InternalError", NULL);
+			}
+		      tmpmaps->name = zStrdup ("missingIndetifier");
+		      tmpmaps->content =
+			createMap ((char *) cur2->name, (char *) val);
+		      tmpmaps->next = NULL;
+		    }
+		  else
+		    {
+		      if (tmpmaps->content != NULL)
+			addToMap (tmpmaps->content,
+				  (char *) cur2->name, (char *) val);
+		      else
+			tmpmaps->content =
+			  createMap ((char *) cur2->name, (char *) val);
+		    }
+		  xmlFree (val);
+		}
+	      // InputDataFormChoice (Reference or Data ?) 
+	      if (xmlStrcasecmp (cur2->name, BAD_CAST "Reference") == 0)
+		{
+		  // Get every attribute from a Reference node
+		  // mimeType, encoding, schema, href, method
+		  // Header and Body gesture should be added here
+		  const char *refs[5] =
+		    { "mimeType", "encoding", "schema", "method",
+		      "href"
+		    };
+		  for (l = 0; l < 5; l++)
+		    {
+		      xmlChar *val = xmlGetProp (cur2, BAD_CAST refs[l]);
+		      if (val != NULL && xmlStrlen (val) > 0)
+			{
+			  if (tmpmaps->content != NULL)
+			    addToMap (tmpmaps->content, refs[l],
+				      (char *) val);
+			  else
+			    tmpmaps->content =
+			      createMap (refs[l], (char *) val);
+
+			  map *ltmp = getMap (tmpmaps->content, "method");
+			  if (l == 4 )
+			    {
+			      if ((ltmp==NULL || strncmp (ltmp->value, "POST",4) != 0))
+				{
+				  if (loadRemoteFile
+				      (main_conf, &tmpmaps->content, hInternet,
+				       (char *) val) != 0)
+				    {
+				      return errorException (*main_conf,
+							     _("Unable to add a request in the queue."),
+							     "InternalError",
+							     NULL);
+				    }
+				  addIntToMap (tmpmaps->content, "Order", hInternet->nb);
+				}
+			      addToMap (tmpmaps->content, "Reference", (char*) val);
+			    }
+			}
+		      xmlFree (val);
+		    }
+		  // Parse Header and Body from Reference
+		  xmlNodePtr cur3 = cur2->children;
+		  while (cur3 != NULL)
+		    {
+		      while (cur3 != NULL
+			     && cur3->type != XML_ELEMENT_NODE)
+			cur3 = cur3->next;
+		      if (cur3 == NULL)
+			break;
+		      if (xmlStrcasecmp (cur3->name, BAD_CAST "Header") ==
+			  0)
+			{
+			  const char *ha[2];
+			  ha[0] = "key";
+			  ha[1] = "value";
+			  int hai;
+			  char *has=NULL;
+			  char *key;
+			  for (hai = 0; hai < 2; hai++)
+			    {
+			      xmlChar *val =
+				xmlGetProp (cur3, BAD_CAST ha[hai]);
+#ifdef POST_DEBUG
+			      fprintf (stderr, "%s = %s\n", ha[hai],
+				       (char *) val);
+#endif
+			      if (hai == 0)
+				{
+				  key = zStrdup ((char *) val);
+				}
+			      else
+				{
+				  has =
+				    (char *)
+				    malloc ((4 + xmlStrlen (val) +
+					     strlen (key)) *
+					    sizeof (char));
+				  if (has == NULL)
+				    {
+				      return errorException (*main_conf,
+							     _
+							     ("Unable to allocate memory"),
+							     "InternalError",
+							     NULL);
+				    }
+				  snprintf (has,
+					    (3 + xmlStrlen (val) +
+					     strlen (key)), "%s: %s", key,
+					    (char *) val);
+				  free (key);
+				}
+			      xmlFree (val);
+			    }
+			  if (has != NULL){
+			    hInternet->ihandle[hInternet->nb].header = NULL;
+			    hInternet->ihandle[hInternet->nb].header =
+			      curl_slist_append (hInternet->ihandle
+						 [hInternet->nb].header,
+						 has);
+			    free (has);
+			  }
+			}
+		      else
+			{
+#ifdef POST_DEBUG
+			  fprintf (stderr,
+				   "Try to fetch the body part of the request ...\n");
+#endif
+			  if (xmlStrcasecmp (cur3->name, BAD_CAST "Body")
+			      == 0)
+			    {
+#ifdef POST_DEBUG
+			      fprintf (stderr, "Body part found (%s) !!!\n",
+				       (char *) cur3->content);
+#endif
+			      char *tmp = NULL;
+			      xmlNodePtr cur4 = cur3->children;
+			      while (cur4 != NULL)
+				{
+				  while (cur4 && cur4 != NULL && cur4->type && cur4->type != XML_ELEMENT_NODE){
+				    if(cur4->next)
+				      cur4 = cur4->next;
+				    else
+				      cur4 = NULL;
+				  }
+				  if(cur4 != NULL) {
+				    xmlDocPtr bdoc =
+				      xmlNewDoc (BAD_CAST "1.0");
+				    bdoc->encoding =
+				      xmlCharStrdup ("UTF-8");
+				    xmlDocSetRootElement (bdoc, cur4);
+				    xmlChar *btmps;
+				    int bsize;
+				    // TODO : check for encoding defined in the input
+				    xmlDocDumpFormatMemoryEnc(bdoc, &btmps, &bsize, "UTF-8", 0);
+				    if (btmps != NULL){
+				      tmp = (char *) malloc ((bsize + 1) * sizeof (char));
+
+				      sprintf (tmp, "%s", (char*) btmps);
+					  
+				      xmlFreeDoc (bdoc);
+					  
+				      map *btmp =
+					getMap (tmpmaps->content, "Reference");
+				      if (btmp != NULL)
+					{
+					  addRequestToQueue(main_conf,hInternet,(char *) btmp->value,false);
+					  InternetOpenUrl (hInternet,
+							   btmp->value,
+							   tmp,
+							   xmlStrlen(btmps),
+							   INTERNET_FLAG_NO_CACHE_WRITE,
+							   0);
+					  addIntToMap (tmpmaps->content, "Order", hInternet->nb);
+					}
+				      xmlFree (btmps);
+				      free (tmp);
+				      break;
+				    }
+				  }
+				  cur4 = cur4->next;
+				}
+			    }
+			  else
+			    if (xmlStrcasecmp
+				(cur3->name,
+				 BAD_CAST "BodyReference") == 0)
+			      {
+				xmlChar *val =
+				  xmlGetProp (cur3, BAD_CAST "href");
+				HINTERNET bInternet, res1, res;
+				bInternet = InternetOpen (
+#ifndef WIN32
+							  (LPCTSTR)
+#endif
+							  "ZooWPSClient\0",
+							  INTERNET_OPEN_TYPE_PRECONFIG,
+							  NULL, NULL, 0);
+				if (!CHECK_INET_HANDLE (bInternet))
+				  fprintf (stderr,
+					   "WARNING : bInternet handle failed to initialize");
+				bInternet.waitingRequests[0] =
+				  strdup ((char *) val);
+				res1 =
+				  InternetOpenUrl (&bInternet,
+						   bInternet.waitingRequests
+						   [0], NULL, 0,
+						   INTERNET_FLAG_NO_CACHE_WRITE,
+						   0);
+				processDownloads (&bInternet);
+				char *tmp =
+				  (char *)
+				  malloc ((bInternet.ihandle[0].nDataLen +
+					   1) * sizeof (char));
+				if (tmp == NULL)
+				  {
+				    return errorException (*main_conf,
+							   _
+							   ("Unable to allocate memory"),
+							   "InternalError",
+							   NULL);
+				  }
+				size_t bRead;
+				InternetReadFile (bInternet.ihandle[0],
+						  (LPVOID) tmp,
+						  bInternet.
+						  ihandle[0].nDataLen,
+						  &bRead);
+				tmp[bInternet.ihandle[0].nDataLen] = 0;
+				InternetCloseHandle (&bInternet);
+				map *btmp =
+				  getMap (tmpmaps->content, "href");
+				if (btmp != NULL)
+				  {
+				    addRequestToQueue(main_conf,hInternet,(char *) btmp->value,false);
+
+				    res =
+				      InternetOpenUrl (hInternet,
+						       btmp->value,
+						       tmp,
+						       strlen(tmp),
+						       INTERNET_FLAG_NO_CACHE_WRITE,
+						       0);
+				    addIntToMap (tmpmaps->content, "Order", hInternet->nb);
+				  }
+				free (tmp);
+			      }
+			}
+		      cur3 = cur3->next;
+		    }
+		}
+	      else if (xmlStrcasecmp (cur2->name, BAD_CAST "Data") == 0)
+		{
+		  xmlNodePtr cur4 = cur2->children;
+		  if(vid==1){
+		    // Get every dataEncodingAttributes from a Data node:
+		    // mimeType, encoding, schema
+		    const char *coms[3] =
+		      { "mimeType", "encoding", "schema" };
+		    for (l = 0; l < 3; l++){
+		      xmlChar *val =
+			  xmlGetProp (cur4, BAD_CAST coms[l]);
+			if (val != NULL && strlen ((char *) val) > 0){
+			  if (tmpmaps->content != NULL)
+			    addToMap (tmpmaps->content,coms[l],(char *) val);
+			  else
+			    tmpmaps->content =
+			      createMap (coms[l],(char *) val);
+			}
+			xmlFree (val);
+		    }
+		    while (cur4 != NULL){
+		      while(cur4 != NULL && 
+			    cur4->type != XML_CDATA_SECTION_NODE &&
+			    cur4->type != XML_TEXT_NODE)
+			cur4=cur4->next;
+		      if(cur4!=NULL){
+			if(cur4->content!=NULL)
+			  if (tmpmaps->content != NULL)
+			    addToMap (tmpmaps->content, "value",
+				      (char *) cur4->content);
+			  else
+			    tmpmaps->content =
+			      createMap ("value", (char *) cur4->content);
+			cur4=cur4->next;
+		      }
+		    }
+		  }
+
+
+		  while (cur4 != NULL)
+		    {
+		      while (cur4 != NULL
+			     && cur4->type != XML_ELEMENT_NODE)
+			cur4 = cur4->next;
+		      if (cur4 == NULL)
+			break;
+		      if (xmlStrcasecmp
+			  (cur4->name, BAD_CAST "LiteralData") == 0)
+			{
+			  // Get every attribute from a LiteralData node
+			  // dataType , uom
+			  char *list[2];
+			  list[0] = zStrdup ("dataType");
+			  list[1] = zStrdup ("uom");
+			  for (l = 0; l < 2; l++)
+			    {
+			      xmlChar *val =
+				xmlGetProp (cur4, BAD_CAST list[l]);
+			      if (val != NULL
+				  && strlen ((char *) val) > 0)
+				{
+				  if (tmpmaps->content != NULL)
+				    addToMap (tmpmaps->content, list[l],
+					      (char *) val);
+				  else
+				    tmpmaps->content =
+				      createMap (list[l], (char *) val);
+				}
+			      xmlFree (val);
+			      free (list[l]);
+			    }
+			}
+		      else
+			if (xmlStrcasecmp
+			    (cur4->name, BAD_CAST "ComplexData") == 0)
+			  {
+			    // Get every attribute from a Reference node
+			    // mimeType, encoding, schema
+			    const char *coms[3] =
+			      { "mimeType", "encoding", "schema" };
+			    for (l = 0; l < 3; l++)
+			      {
+				xmlChar *val =
+				  xmlGetProp (cur4, BAD_CAST coms[l]);
+				if (val != NULL
+				    && strlen ((char *) val) > 0)
+				  {
+				    if (tmpmaps->content != NULL)
+				      addToMap (tmpmaps->content, coms[l],
+						(char *) val);
+				    else
+				      tmpmaps->content =
+					createMap (coms[l], (char *) val);
+				  }
+				xmlFree (val);
+			      }
+			  }
+
+		      map *test = getMap (tmpmaps->content, "encoding");
+
+		      if (test == NULL)
+			{ 
+			  if (tmpmaps->content != NULL)
+			    addToMap (tmpmaps->content, "encoding",
+				      "utf-8");
+			  else
+			    tmpmaps->content =
+			      createMap ("encoding", "utf-8");
+			  test = getMap (tmpmaps->content, "encoding");
+			}
+
+		      if (strcasecmp (test->value, "base64") != 0)
+			{ 
+			  xmlChar *mv = xmlNodeListGetString (doc,
+							      cur4->xmlChildrenNode,
+							      1);
+			  map *ltmp =
+			    getMap (tmpmaps->content, "mimeType");
+			  if (mv == NULL
+			      ||
+			      (xmlStrcasecmp
+			       (cur4->name, BAD_CAST "ComplexData") == 0
+			       && (ltmp == NULL
+				   || strncasecmp (ltmp->value,
+						   "text/xml", 8) == 0)))
+			    {
+			      xmlDocPtr doc1 = xmlNewDoc (BAD_CAST "1.0");
+			      int buffersize;
+			      xmlNodePtr cur5 = cur4->children;
+			      while (cur5 != NULL
+				     && cur5->type != XML_ELEMENT_NODE
+				     && cur5->type != XML_CDATA_SECTION_NODE)
+				cur5 = cur5->next;
+			      if (cur5 != NULL
+				  && cur5->type != XML_CDATA_SECTION_NODE)
+				{
+				  xmlDocSetRootElement (doc1, cur5);
+				  xmlDocDumpFormatMemoryEnc (doc1, &mv,
+							     &buffersize,
+							     "utf-8", 0);
+				  addIntToMap (tmpmaps->content, "size",
+					       buffersize);
+				  xmlFreeDoc (doc1);
+				}
+			      else
+				{
+				  if (cur5 != NULL
+				      && cur5->type == XML_CDATA_SECTION_NODE){
+				    xmlDocPtr doc2 = xmlParseMemory((const char*)cur5->content,xmlStrlen(cur5->content));
+				    xmlDocSetRootElement (doc1,xmlDocGetRootElement(doc2));
+				    xmlDocDumpFormatMemoryEnc (doc1, &mv,
+							       &buffersize,
+							       "utf-8", 0);
+				    addIntToMap(tmpmaps->content, "size",buffersize);
+				    xmlFreeDoc (doc2);
+				    xmlFreeDoc (doc1);
+				  }
+				}
+			    }else{
+			    xmlNodePtr cur5 = cur4->children;
+			    while (cur5 != NULL
+				   && cur5->type != XML_CDATA_SECTION_NODE)
+			      cur5 = cur5->next;
+			    if (cur5 != NULL
+				&& cur5->type == XML_CDATA_SECTION_NODE){
+			      xmlFree(mv);
+			      mv=xmlStrdup(cur5->content);
+			    }
+			  }
+			  if (mv != NULL)
+			    {
+			      addToMap (tmpmaps->content, "value",
+					(char*) mv);
+			      xmlFree (mv);
+			    }
+			}
+		      else
+			{
+			  xmlChar *tmp = xmlNodeListGetRawString (doc,
+								  cur4->xmlChildrenNode,
+								  0);
+			  addToMap (tmpmaps->content, "value",
+				    (char *) tmp);
+			  xmlFree (tmp);
+			}
+
+		      cur4 = cur4->next;
+		    }
+		}
+	      cur2 = cur2->next;
+	      while (cur2 != NULL && cur2->type != XML_ELEMENT_NODE){
+		cur2 = cur2->next;
+	      }
+	    }
+	  {
+	    maps *testPresence =
+	      getMaps (*request_output, tmpmaps->name);
+	    if (testPresence != NULL)
+	      {
+		elements *elem = getElements (s->inputs, tmpmaps->name);
+		if (elem != NULL)
+		  {
+		    if (appendMapsToMaps
+			(*main_conf, *request_output, tmpmaps, elem) < 0)
+		      {
+			return errorException (*main_conf,
+					       _("Unable to append maps to maps."),
+					       "InternalError",
+					       NULL);
+		      }
+		  }
+	      }
+	    else
+	      addMapsToMaps (request_output, tmpmaps);
+	  }
+	  freeMaps (&tmpmaps);
+	  free (tmpmaps);
+	  tmpmaps = NULL;
+	}
+    }
+  return 1;
+}
+
+/**
+ * Parse outputs from XML nodes and store them in a maps (WPS version 2.0.0).
+ *
+ * @param main_conf the conf maps containing the main.cfg settings
+ * @param request_inputs the map storing KVP raw value 
+ * @param request_output the maps to store the KVP pairs 
+ * @param doc the xmlDocPtr containing the original request
+ * @param cur the xmlNodePtr corresponding to the ResponseDocument or RawDataOutput XML node
+ * @param raw true if the node is RawDataOutput, false in case of ResponseDocument
+ * @return 0 on success, -1 on failure
+ */
+int xmlParseOutputs2(maps** main_conf,map** request_inputs,maps** request_output,xmlDocPtr doc,xmlNodeSet* nodes){
+  int k = 0;
+  int l = 0;
+  for (k=0; k < nodes->nodeNr; k++){
+    maps *tmpmaps = NULL;
+    xmlNodePtr cur = nodes->nodeTab[k];
+    if (cur->type == XML_ELEMENT_NODE){
+      maps *tmpmaps = (maps *) malloc (MAPS_SIZE);
+      xmlChar *val = xmlGetProp (cur, BAD_CAST "id");
+      if(val!=NULL)
+	tmpmaps->name = zStrdup ((char*)val);
+      else
+	tmpmaps->name = zStrdup ("unknownIdentifier");
+      tmpmaps->content = NULL;
+      tmpmaps->next = NULL;
+      const char ress[4][13] =
+	{ "mimeType", "encoding", "schema", "transmission" };
+      for (l = 0; l < 4; l++){
+	val = xmlGetProp (cur, BAD_CAST ress[l]);
+	if (val != NULL && strlen ((char *) val) > 0)
+	  {
+	    if (tmpmaps->content != NULL)
+	      addToMap (tmpmaps->content, ress[l],
+			(char *) val);
+	    else
+	      tmpmaps->content =
+		createMap (ress[l], (char *) val);
+	    if(l==3 && strncasecmp((char*)val,"reference",xmlStrlen(val))==0)
+	      addToMap (tmpmaps->content,"asReference","true");
+	  }
+	xmlFree (val);
+      }
+      if (*request_output == NULL)
+	*request_output = dupMaps(&tmpmaps);
+      else
+	addMapsToMaps(request_output,tmpmaps);
+    }
+  }
+  return 0;
+}
+
+/**
+ * Parse outputs from XML nodes and store them in a maps.
+ *
+ * @param main_conf the conf maps containing the main.cfg settings
+ * @param request_inputs the map storing KVP raw value 
+ * @param request_output the maps to store the KVP pairs 
+ * @param doc the xmlDocPtr containing the original request
+ * @param cur the xmlNodePtr corresponding to the ResponseDocument or RawDataOutput XML node
+ * @param raw true if the node is RawDataOutput, false in case of ResponseDocument
+ * @return 0 on success, -1 on failure
+ */
+int xmlParseOutputs(maps** main_conf,map** request_inputs,maps** request_output,xmlDocPtr doc,xmlNodePtr cur,bool raw){
+  int l=0;
+  if( raw == true)
+    {
+      addToMap (*request_inputs, "RawDataOutput", "");
+      if (cur->type == XML_ELEMENT_NODE)
+	{
+
+	  maps *tmpmaps = (maps *) malloc (MAPS_SIZE);
+	  if (tmpmaps == NULL)
+	    {
+	      return errorException (*main_conf, _("Unable to allocate memory"),
+				     "InternalError", NULL);
+	    }
+	  tmpmaps->name = zStrdup ("unknownIdentifier");
+	  tmpmaps->content = NULL;
+	  tmpmaps->next = NULL;
+
+	  // Get every attribute from a RawDataOutput node
+	  // mimeType, encoding, schema, uom
+	  const char *outs[4] =
+	    { "mimeType", "encoding", "schema", "uom" };
+	  for (l = 0; l < 4; l++)
+	    {
+	      xmlChar *val = xmlGetProp (cur, BAD_CAST outs[l]);
+	      if (val != NULL)
+		{
+		  if (strlen ((char *) val) > 0)
+		    {
+		      if (tmpmaps->content != NULL)
+			addToMap (tmpmaps->content, outs[l],
+				  (char *) val);
+		      else
+			tmpmaps->content =
+			  createMap (outs[l], (char *) val);
+		    }
+		  xmlFree (val);
+		}
+	    }
+	  xmlNodePtr cur2 = cur->children;
+	  while (cur2 != NULL && cur2->type != XML_ELEMENT_NODE)
+	    cur2 = cur2->next;
+	  while (cur2 != NULL)
+	    {
+	      if (xmlStrncasecmp
+		  (cur2->name, BAD_CAST "Identifier",
+		   xmlStrlen (cur2->name)) == 0)
+		{
+		  xmlChar *val =
+		    xmlNodeListGetString (NULL, cur2->xmlChildrenNode, 1);
+		  free (tmpmaps->name);
+		  tmpmaps->name = zStrdup ((char *) val);
+		  xmlFree (val);
+		}
+	      cur2 = cur2->next;
+	      while (cur2 != NULL && cur2->type != XML_ELEMENT_NODE)
+		cur2 = cur2->next;
+	    }
+	  if (*request_output == NULL)
+	    *request_output = dupMaps (&tmpmaps);
+	  else
+	    addMapsToMaps (request_output, tmpmaps);
+	  if (tmpmaps != NULL)
+	    {
+	      freeMaps (&tmpmaps);
+	      free (tmpmaps);
+	      tmpmaps = NULL;
+	    }
+	}
+    }
+  else
+    {
+      addToMap (*request_inputs, "ResponseDocument", "");
+
+      if (cur->type == XML_ELEMENT_NODE) {
+	// Get every attribute: storeExecuteResponse, lineage, status
+	const char *ress[3] =
+	  { "storeExecuteResponse", "lineage", "status" };
+	xmlChar *val;
+	for (l = 0; l < 3; l++)
+	  {
+	    val = xmlGetProp (cur, BAD_CAST ress[l]);
+	    if (val != NULL && strlen ((char *) val) > 0)
+	      {
+		addToMap (*request_inputs, ress[l], (char *) val);
+	      }
+	    xmlFree (val);
+	  }
+			
+	xmlNodePtr cur1 = cur->children;		
+	while (cur1 != NULL) // iterate over Output nodes
+	  {
+	    if (cur1->type != XML_ELEMENT_NODE || 
+		xmlStrncasecmp(cur1->name, BAD_CAST "Output", 
+			       xmlStrlen (cur1->name)) != 0) {
+	      cur1 = cur1->next;
+	      continue;
+	    }
+				
+	    maps *tmpmaps = (maps *) malloc (MAPS_SIZE); // one per Output node
+	    if (tmpmaps == NULL) {
+	      return errorException (*main_conf,
+				     _
+				     ("Unable to allocate memory"),
+				     "InternalError", NULL);
+	    }
+	    tmpmaps->name = zStrdup ("unknownIdentifier");
+	    tmpmaps->content = NULL;
+	    tmpmaps->next = NULL;
+				
+	    xmlNodePtr elems = cur1->children;
+				
+	    while (elems != NULL) {
+
+	      // Identifier
+	      if (xmlStrncasecmp
+		  (elems->name, BAD_CAST "Identifier",
+		   xmlStrlen (elems->name)) == 0)
+		{
+		  xmlChar *val =
+		    xmlNodeListGetString (doc, elems->xmlChildrenNode, 1);
+		
+		  free(tmpmaps->name);
+		  tmpmaps->name = zStrdup ((char *) val);
+		  if (tmpmaps->content == NULL) {
+		    tmpmaps->content = createMap("Identifier", zStrdup ((char *) val));
+		  }
+		  else {
+		    addToMap(tmpmaps->content, "Identifier", zStrdup ((char *) val));
+		  }
+
+		  map* tt = getMap (*request_inputs, "ResponseDocument");
+		  if (strlen(tt->value) == 0) {
+		    addToMap (*request_inputs, "ResponseDocument",
+			      (char *) val);
+		  }
+		  else {
+		    char* tmp = (char*) malloc((strlen(tt->value) + 1 
+						+ strlen((char*) val) + 1) * sizeof(char));
+		    sprintf (tmp, "%s;%s", tt->value, (char *) val);
+		    free(tt->value);
+		    tt->value = tmp;
+		  }
+		  xmlFree (val);
+		}
+	      
+	      // Title, Abstract
+	      else if (xmlStrncasecmp(elems->name, BAD_CAST "Title",
+				      xmlStrlen (elems->name)) == 0
+		       || xmlStrncasecmp(elems->name, BAD_CAST "Abstract",
+					 xmlStrlen (elems->name)) == 0)
+		{
+		  xmlChar *val =
+		    xmlNodeListGetString (doc, elems->xmlChildrenNode, 1);
+							
+		  if (tmpmaps->content == NULL) {
+		    tmpmaps->content = createMap((char*) elems->name, zStrdup ((char *) val));
+		  }
+		  else {
+		    addToMap(tmpmaps->content, (char*) elems->name, zStrdup ((char *) val));
+		  }
+		  xmlFree (val);
+		}
+	      elems = elems->next;
+	    }
+				
+	    // Get every attribute from an Output node:
+	    // mimeType, encoding, schema, uom, asReference
+	    const char *outs[5] =
+	      { "mimeType", "encoding", "schema", "uom", "asReference" };
+					  
+	    for (l = 0; l < 5; l++) {
+	      xmlChar *val = xmlGetProp (cur1, BAD_CAST outs[l]);				
+	      if (val != NULL && xmlStrlen(val) > 0) {
+		if (tmpmaps->content != NULL) {
+		  addToMap (tmpmaps->content, outs[l], (char *) val);
+		}			  
+		else {
+		  tmpmaps->content = createMap (outs[l], (char *) val);
+		}	
+	      }
+	      xmlFree (val);
+	    }
+				
+	    if (*request_output == NULL) {
+	      *request_output = tmpmaps;
+	    }	
+	    else if (getMaps(*request_output, tmpmaps->name) != NULL) {
+	      return errorException (*main_conf,
+				     _
+				     ("Duplicate <Output> elements in WPS Execute request"),
+				     "InternalError", NULL);
+	    }
+	    else {
+	      maps* mptr = *request_output;
+	      while (mptr->next != NULL) {
+		mptr = mptr->next;
+	      }
+	      mptr->next = tmpmaps;	
+	    }					
+	    cur1 = cur1->next;
+	  }			 
+      }
+    }
+  return 1;
+}
+
+/**
+ * Parse XML request and store informations in maps.
+ *
+ * @param main_conf the conf maps containing the main.cfg settings
+ * @param post the string containing the XML request
+ * @param request_inputs the map storing KVP raw value 
+ * @param s the service
+ * @param inputs the maps to store the KVP pairs 
+ * @param outputs the maps to store the KVP pairs 
+ * @param hInternet the HINTERNET queue to add potential requests
+ * @return 0 on success, -1 on failure
+ */
+int xmlParseRequest(maps** main_conf,const char* post,map** request_inputs,service* s,maps** inputs,maps** outputs,HINTERNET* hInternet){
+
+  map* version=getMapFromMaps(*main_conf,"main","rversion");
+  int vid=getVersionId(version->value);
+
+  xmlInitParser ();
+  xmlDocPtr doc = xmlParseMemory (post, cgiContentLength);
+
+  /**
+   * Extract Input nodes from the XML Request.
+   */
+  xmlXPathObjectPtr tmpsptr =
+    extractFromDoc (doc, (vid==0?"/*/*/*[local-name()='Input']":"/*/*[local-name()='Input']"));
+  xmlNodeSet *tmps = tmpsptr->nodesetval;
+  if(tmps==NULL || xmlParseInputs(main_conf,s,inputs,doc,tmps,hInternet)<0){
+    xmlXPathFreeObject (tmpsptr);
+    xmlFreeDoc (doc);
+    xmlCleanupParser ();
+    return -1;
+  }
+  xmlXPathFreeObject (tmpsptr);
+
+  if(vid==1){
+    tmpsptr =
+      extractFromDoc (doc, "/*[local-name()='Execute']");
+    bool asRaw = false;
+    tmps = tmpsptr->nodesetval;
+    if(tmps->nodeNr > 0){
+      int k = 0;
+      for (k=0; k < tmps->nodeNr; k++){
+	maps *tmpmaps = NULL;
+	xmlNodePtr cur = tmps->nodeTab[k];
+	if (cur->type == XML_ELEMENT_NODE){
+	  xmlChar *val = xmlGetProp (cur, BAD_CAST "mode");
+	  if(val!=NULL)
+	    addToMap(*request_inputs,"mode",(char*)val);
+	  else
+	    addToMap(*request_inputs,"mode","auto");
+	  val = xmlGetProp (cur, BAD_CAST "response");
+	  if(val!=NULL){
+	    addToMap(*request_inputs,"response",(char*)val);
+	    if(strncasecmp((char*)val,"raw",xmlStrlen(val))==0)
+	      addToMap(*request_inputs,"RawDataOutput","");
+	    else
+	      addToMap(*request_inputs,"ResponseDocument","");
+	  }
+	  else{
+	    addToMap(*request_inputs,"response","document");
+	    addToMap(*request_inputs,"ResponseDocument","");
+	  }
+	}
+      }
+    }
+    xmlXPathFreeObject (tmpsptr);
+    tmpsptr =
+      extractFromDoc (doc, "/*/*[local-name()='Output']");
+    tmps = tmpsptr->nodesetval;
+    if(tmps->nodeNr > 0){
+      if(xmlParseOutputs2(main_conf,request_inputs,outputs,doc,tmps)<0){
+	xmlXPathFreeObject (tmpsptr);
+	xmlFreeDoc (doc);
+	xmlCleanupParser ();
+	return -1;
+      }
+    }
+  }
+  else{
+    // Extract ResponseDocument / RawDataOutput from the XML Request 
+    tmpsptr =
+      extractFromDoc (doc, "/*/*/*[local-name()='ResponseDocument']");
+    bool asRaw = false;
+    tmps = tmpsptr->nodesetval;
+    if (tmps->nodeNr == 0)
+      {
+	xmlXPathFreeObject (tmpsptr);
+	tmpsptr =
+	  extractFromDoc (doc, "/*/*/*[local-name()='RawDataOutput']");
+	tmps = tmpsptr->nodesetval;
+	asRaw = true;
+      }
+    if(tmps->nodeNr != 0){
+      if(xmlParseOutputs(main_conf,request_inputs,outputs,doc,tmps->nodeTab[0],asRaw)<0){
+	xmlXPathFreeObject (tmpsptr);
+	xmlFreeDoc (doc);
+	xmlCleanupParser ();
+	return -1;
+      }
+    }
+  }
+  xmlXPathFreeObject (tmpsptr);
+  xmlFreeDoc (doc);
+  xmlCleanupParser ();
+  return 1;
+}
+
+/**
+ * Parse request and store informations in maps.
+ *
+ * @param main_conf the conf maps containing the main.cfg settings
+ * @param post the string containing the XML request
+ * @param request_inputs the map storing KVP raw value 
+ * @param s the service
+ * @param inputs the maps to store the KVP pairs 
+ * @param outputs the maps to store the KVP pairs 
+ * @param hInternet the HINTERNET queue to add potential requests
+ * @return 0 on success, -1 on failure
+ * @see kvpParseOutputs,kvpParseInputs,xmlParseRequest
+ */
+int parseRequest(maps** main_conf,map** request_inputs,service* s,maps** inputs,maps** outputs,HINTERNET* hInternet){
+  map *postRequest = NULL;
+  postRequest = getMap (*request_inputs, "xrequest");
+  if (postRequest == NULLMAP)
+    {
+      if(kvpParseOutputs(main_conf,*request_inputs,outputs)<0){
+	return -1;
+      }
+      if(kvpParseInputs(main_conf,s,*request_inputs,inputs,hInternet)<0){
+	return -1;
+      }
+    }
+  else
+    {
+      //Parse XML request
+      if(xmlParseRequest(main_conf,postRequest->value,request_inputs,s,inputs,outputs,hInternet)<0){
+	return -1;
+      }
+    }
+  return 1;
+}
+
+/**
+ * Ensure that each requested arguments are present in the request
+ * DataInputs and ResponseDocument / RawDataOutput. Potentially run
+ * http requests from the queue in parallel.
+ * For optional inputs add default values defined in the ZCFG file.
+ * 
+ * @param main_conf
+ * @param s 
+ * @param original_request
+ * @param request_inputs
+ * @param request_outputs
+ * @param hInternet 
+ * 
+ * @see runHttpRequests
+ */
+int validateRequest(maps** main_conf,service* s,map* original_request, maps** request_inputs,maps** request_outputs,HINTERNET* hInternet){
+
+  runHttpRequests (main_conf, request_inputs, hInternet);
+  InternetCloseHandle (hInternet);
+
+  map* errI=NULL;
+  char *dfv = addDefaultValues (request_inputs, s->inputs, *main_conf, 0,&errI);
+
+  maps *ptr = *request_inputs;
+  while (ptr != NULL)
+    {
+      map *tmp0 = getMap (ptr->content, "size");
+      map *tmp1 = getMap (ptr->content, "maximumMegabytes");
+      if (tmp1 != NULL && tmp0 != NULL)
+        {
+          float i = atof (tmp0->value) / 1048576.0;
+          if (i >= atoi (tmp1->value))
+            {
+              char tmps[1024];
+              map *tmpe = createMap ("code", "FileSizeExceeded");
+              snprintf (tmps, 1024,
+                        _
+                        ("The <%s> parameter has a size limit (%s MB) defined in the ZOO ServicesProvider configuration file, but the reference you provided exceeds this limit (%f MB)."),
+                        ptr->name, tmp1->value, i);
+              addToMap (tmpe, "locator", ptr->name);
+              addToMap (tmpe, "text", tmps);
+              printExceptionReportResponse (*main_conf, tmpe);
+              freeMap (&tmpe);
+              free (tmpe);
+	      return -1;
+            }
+        }
+      ptr = ptr->next;
+    }
+
+  map* errO=NULL;
+  char *dfv1 =
+    addDefaultValues (request_outputs, s->outputs, *main_conf, 1,&errO);
+  if (strcmp (dfv1, "") != 0 || strcmp (dfv, "") != 0)
+    {
+      char tmps[1024];
+      map *tmpe = NULL;
+      if (strcmp (dfv, "") != 0)
+        {
+	  tmpe = createMap ("code", "MissingParameterValue");
+	  int nb=0;
+	  int length=1;
+	  map* len=getMap(errI,"length");
+	  if(len!=NULL)
+	    length=atoi(len->value);
+	  for(nb=0;nb<length;nb++){
+	    map* errp=getMapArray(errI,"value",nb);
+	    snprintf (tmps, 1024,
+		      _
+		      ("The <%s> argument was not specified in DataInputs but is required according to the ZOO ServicesProvider configuration file."),
+		      errp->value);
+	    setMapArray (tmpe, "locator", nb , errp->value);
+	    setMapArray (tmpe, "text", nb , tmps);
+	    setMapArray (tmpe, "code", nb , "MissingParameterValue");
+	  }
+	}
+      if (strcmp (dfv1, "") != 0)
+        {
+	  int ilength=0;
+	  if(tmpe==NULL)
+	    tmpe = createMap ("code", "InvalidParameterValue");
+	  else{
+	    map* len=getMap(tmpe,"length");
+	    if(len!=NULL)
+	      ilength=atoi(len->value);
+	  }
+	  int nb=0;
+	  int length=1;
+	  map* len=getMap(errO,"length");
+	  if(len!=NULL)
+	    length=atoi(len->value);
+	  for(nb=0;nb<length;nb++){
+	    map* errp=getMapArray(errO,"value",nb);
+	    snprintf (tmps, 1024,
+		      _
+		      ("The <%s> argument specified as %s identifier was not recognized (not defined in the ZOO Configuration File)."),
+		      errp->value,
+		      ((getMap(original_request,"RawDataOutput")!=NULL)?"RawDataOutput":"ResponseDocument"));
+	    setMapArray (tmpe, "locator", nb+ilength , errp->value);
+	    setMapArray (tmpe, "text", nb+ilength , tmps);
+	    setMapArray (tmpe, "code", nb+ilength , "InvalidParameterValue");
+	  }
+	}
+      printExceptionReportResponse (*main_conf, tmpe);
+      if(errI!=NULL){
+	freeMap(&errI);
+	free(errI);
+      }
+      if(errO!=NULL){
+	freeMap(&errO);
+	free(errO);
+      }
+      freeMap (&tmpe);
+      free (tmpe);
+      return -1;
+    }
+  maps *tmpReqI = *request_inputs;
+  while (tmpReqI != NULL)
+    {
+      char name[1024];
+      if (getMap (tmpReqI->content, "isFile") != NULL)
+        {
+          if (cgiFormFileName (tmpReqI->name, name, sizeof (name)) ==
+              cgiFormSuccess)
+            {
+              int BufferLen = 1024;
+              cgiFilePtr file;
+              int targetFile;
+              char storageNameOnServer[2048];
+              char fileNameOnServer[64];
+              char contentType[1024];
+              char buffer[1024];
+              char *tmpStr = NULL;
+              int size;
+              int got, t;
+              map *path = getMapFromMaps (*main_conf, "main", "tmpPath");
+              cgiFormFileSize (tmpReqI->name, &size);
+              cgiFormFileContentType (tmpReqI->name, contentType,
+                                      sizeof (contentType));
+              if (cgiFormFileOpen (tmpReqI->name, &file) == cgiFormSuccess)
+                {
+                  t = -1;
+                  while (1)
+                    {
+                      tmpStr = strstr (name + t + 1, "\\");
+                      if (NULL == tmpStr)
+                        tmpStr = strstr (name + t + 1, "/");
+                      if (NULL != tmpStr)
+                        t = (int) (tmpStr - name);
+                      else
+                        break;
+                    }
+                  strcpy (fileNameOnServer, name + t + 1);
+
+                  sprintf (storageNameOnServer, "%s/%s", path->value,
+                           fileNameOnServer);
+#ifdef DEBUG
+                  fprintf (stderr, "Name on server %s\n",
+                           storageNameOnServer);
+                  fprintf (stderr, "fileNameOnServer: %s\n",
+                           fileNameOnServer);
+#endif
+                  targetFile =
+                    open (storageNameOnServer, O_RDWR | O_CREAT | O_TRUNC,
+                          S_IRWXU | S_IRGRP | S_IROTH);
+                  if (targetFile < 0)
+                    {
+#ifdef DEBUG
+                      fprintf (stderr, "could not create the new file,%s\n",
+                               fileNameOnServer);
+#endif
+                    }
+                  else
+                    {
+                      while (cgiFormFileRead (file, buffer, BufferLen, &got)
+                             == cgiFormSuccess)
+                        {
+                          if (got > 0)
+                            write (targetFile, buffer, got);
+                        }
+                    }
+                  addToMap (tmpReqI->content, "lref", storageNameOnServer);
+                  cgiFormFileClose (file);
+                  close (targetFile);
+#ifdef DEBUG
+                  fprintf (stderr, "File \"%s\" has been uploaded",
+                           fileNameOnServer);
+#endif
+                }
+            }
+        }
+      tmpReqI = tmpReqI->next;
+    }
+
+  ensureDecodedBase64 (request_inputs);
+  return 1;
+}
+
+
+/**
+ * Verify if a parameter value is valid.
+ * 
+ * @param request the request map
+ * @param res the error map potentially generated
+ * @param toCheck the parameter to use
+ * @param avalues the acceptable values (or null if testing only for presence)
+ * @param mandatory verify the presence of the parameter if mandatory > 0 
+ */
+void checkValidValue(map* request,map** res,const char* toCheck,const char** avalues,int mandatory){
+  map* lres=*res;
+  map* r_inputs = getMap (request,toCheck);
+  if (r_inputs == NULL){
+    if(mandatory>0){
+      char *replace=_("Mandatory parameter <%s> was not specified");
+      char *message=(char*)malloc((strlen(replace)+strlen(toCheck)+1)*sizeof(char));
+      sprintf(message,replace,toCheck);
+      if(lres==NULL){
+	lres=createMap("code","MissingParameterValue");
+	addToMap(lres,"text",message);
+	addToMap(lres,"locator",toCheck);       
+      }else{
+	int length=1;
+	map* len=getMap(lres,"length");
+	if(len!=NULL){
+	  length=atoi(len->value);
+	}
+	setMapArray(lres,"text",length,message);
+	setMapArray(lres,"locator",length,toCheck);
+	setMapArray(lres,"code",length,"MissingParameter");
+      }
+      free(message);
+    }
+  }else{
+    if(avalues==NULL)
+      return;
+    int nb=0;
+    int hasValidValue=-1;
+    if(strncasecmp(toCheck,"Accept",6)==0){
+      char *tmp=zStrdup(r_inputs->value);
+      char *pToken,*saveptr;
+      pToken=strtok_r(tmp,",",&saveptr);
+      while(pToken!=NULL){
+	while(avalues[nb]!=NULL){
+	  if(strcasecmp(avalues[nb],pToken)==0){
+	    hasValidValue=1;
+	    break;
+	  }
+	  nb++;
+	}
+	pToken=strtok_r(NULL,",",&saveptr);
+      }
+      free(tmp);
+    }else{
+      while(avalues[nb]!=NULL){
+	if(strcasecmp(avalues[nb],r_inputs->value)==0){
+	  hasValidValue=1;
+	  break;
+	}
+	nb++;
+      }
+    }
+    if(hasValidValue<0){
+      char *replace=_("The value <%s> was not recognized, %s %s the only acceptable value.");
+      nb=0;
+      char *vvalues=NULL;
+      char* num=_("is");
+      while(avalues[nb]!=NULL){
+	char *tvalues;
+	if(vvalues==NULL){
+	  vvalues=(char*)malloc((strlen(avalues[nb])+3)*sizeof(char));
+	  sprintf(vvalues,"%s",avalues[nb]);
+	}
+	else{
+	  tvalues=zStrdup(vvalues);
+	  vvalues=(char*)realloc(vvalues,(strlen(tvalues)+strlen(avalues[nb])+3)*sizeof(char));
+	  sprintf(vvalues,"%s, %s",tvalues,avalues[nb]);
+	  free(tvalues);
+	  num=_("are");
+	}
+	nb++;
+      }
+      char *message=(char*)malloc((strlen(replace)+strlen(num)+strlen(vvalues)+strlen(toCheck)+1)*sizeof(char));
+      sprintf(message,replace,toCheck,vvalues,num);
+      const char *code="VersionNegotiationFailed";
+      code="InvalidParameterValue";
+      const char *locator=toCheck;
+      if( strncasecmp(toCheck,"version",7)==0 ||
+	  strncasecmp(toCheck,"AcceptVersions",14)==0 )
+	code="VersionNegotiationFailed";
+      if( strncasecmp(toCheck,"request",7)==0){
+	code="OperationNotSupported";
+	locator=r_inputs->value;
+      }
+      if(lres==NULL){
+	lres=createMap("code","InvalidParameterValue");
+	addToMap(lres,"text",message);
+	addToMap(lres,"locator",locator);       
+      }else{
+	int length=1;
+	map* len=getMap(lres,"length");
+	if(len!=NULL){
+	  length=atoi(len->value);
+	}
+	setMapArray(lres,"text",length,message);
+	setMapArray(lres,"locator",length,locator);
+	setMapArray(lres,"code",length,"InvalidParameterValue");
+      }
+    }
+  }
+  if(lres!=NULL){
+    *res=lres;
+  }
+}
diff --git a/zoo-project/zoo-kernel/request_parser.h b/zoo-project/zoo-kernel/request_parser.h
new file mode 100644
index 0000000..4ebcdc0
--- /dev/null
+++ b/zoo-project/zoo-kernel/request_parser.h
@@ -0,0 +1,55 @@
+/*
+ * Author : Gérald FENOY
+ *
+ * Copyright (c) 2015 GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef ZOO_REQUEST_PARSER_H
+#define ZOO_REQUEST_PARSER_H 1
+
+#pragma once 
+
+#include "service.h"
+#include "ulinet.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <libxml/parser.h>
+#include <libxml/xpath.h>
+
+  xmlXPathObjectPtr extractFromDoc (xmlDocPtr, const char *);
+  int appendMapsToMaps (maps*, maps*, maps*, elements*);
+  void ensureDecodedBase64(maps**);
+  int kvpParseInputs(maps**,service*,map*,maps**,HINTERNET*);
+  int kvpParseOutputs(maps**,map *,maps**);
+  int xmlParseInputs(maps**,service*,maps**,xmlDocPtr,xmlNodeSet*,HINTERNET*);
+  int xmlParseOutputs(maps**,map**,maps**,xmlDocPtr,xmlNodePtr,bool);
+  int xmlParseRequest(maps**,const char*,map**,service*,maps**,maps**,HINTERNET*);
+  int parseRequest(maps**,map**,service*,maps**,maps**,HINTERNET*);
+  void checkValidValue(map*,map**,const char*,const char**,int);
+  int validateRequest(maps**,service*,map*,maps**,maps**,HINTERNET*);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/zoo-project/zoo-kernel/response_print.c b/zoo-project/zoo-kernel/response_print.c
new file mode 100644
index 0000000..d08505a
--- /dev/null
+++ b/zoo-project/zoo-kernel/response_print.c
@@ -0,0 +1,2847 @@
+/*
+ * Author : Gérald FENOY
+ *
+ * Copyright (c) 2009-2015 GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "response_print.h"
+#include "request_parser.h"
+#include "server_internal.h"
+#include "service_internal.h"
+#ifdef USE_MS
+#include "service_internal_ms.h"
+#else
+#include "cpl_vsi.h"
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE -1
+#endif
+
+#ifndef WIN32
+#include <dlfcn.h>
+#endif
+
+#include "mimetypes.h"
+
+
+/**
+ * Add prefix to the service name.
+ * 
+ * @param conf the conf maps containing the main.cfg settings
+ * @param level the map containing the level information
+ * @param serv the service structure created from the zcfg file
+ */
+void addPrefix(maps* conf,map* level,service* serv){
+  if(level!=NULL){
+    char key[25];
+    char* prefix=NULL;
+    int clevel=atoi(level->value);
+    int cl=0;
+    for(cl=0;cl<clevel;cl++){
+      sprintf(key,"sprefix_%d",cl);
+      map* tmp2=getMapFromMaps(conf,"lenv",key);
+      if(tmp2!=NULL){
+	if(prefix==NULL)
+	  prefix=zStrdup(tmp2->value);
+	else{
+	  int plen=strlen(prefix);
+	  prefix=(char*)realloc(prefix,(plen+strlen(tmp2->value)+2)*sizeof(char));
+	  memcpy(prefix+plen,tmp2->value,strlen(tmp2->value)*sizeof(char));
+	  prefix[plen+strlen(tmp2->value)]=0;
+	}
+      }
+    }
+    if(prefix!=NULL){
+      char* tmp0=strdup(serv->name);
+      free(serv->name);
+      serv->name=(char*)malloc((strlen(prefix)+strlen(tmp0)+1)*sizeof(char));
+      sprintf(serv->name,"%s%s",prefix,tmp0);
+      free(tmp0);
+      free(prefix);
+      prefix=NULL;
+    }
+  }
+}
+
+/**
+ * Print the HTTP headers based on a map.
+ * 
+ * @param m the map containing the headers informations
+ */
+void printHeaders(maps* m){
+  maps *_tmp=getMaps(m,"headers");
+  if(_tmp!=NULL){
+    map* _tmp1=_tmp->content;
+    while(_tmp1!=NULL){
+      printf("%s: %s\r\n",_tmp1->name,_tmp1->value);
+      _tmp1=_tmp1->next;
+    }
+  }
+}
+
+/**
+ * Add a land attribute to a XML node
+ *
+ * @param n the XML node to add the attribute
+ * @param m the map containing the language key to add as xml:lang
+ */
+void addLangAttr(xmlNodePtr n,maps *m){
+  map *tmpLmap=getMapFromMaps(m,"main","language");
+  if(tmpLmap!=NULL)
+    xmlNewProp(n,BAD_CAST "xml:lang",BAD_CAST tmpLmap->value);
+  else
+    xmlNewProp(n,BAD_CAST "xml:lang",BAD_CAST "en-US");
+}
+
+/**
+ * Replace the first letter by its upper case version in a new char array
+ *
+ * @param tmp the char*
+ * @return a new char* with first letter in upper case
+ * @warning be sure to free() the returned string after use
+ */
+char *zCapitalize1(char *tmp){
+  char *res=zStrdup(tmp);
+  if(res[0]>=97 && res[0]<=122)
+    res[0]-=32;
+  return res;
+}
+
+/**
+ * Replace all letters by their upper case version in a new char array
+ *
+ * @param tmp the char*
+ * @return a new char* with first letter in upper case
+ * @warning be sure to free() the returned string after use
+ */
+char *zCapitalize(char *tmp){
+  int i=0;
+  char *res=zStrdup(tmp);
+  for(i=0;i<strlen(res);i++)
+    if(res[i]>=97 && res[i]<=122)
+      res[i]-=32;
+  return res;
+}
+
+/**
+ * Search for an existing XML namespace in usedNS.
+ * 
+ * @param name the name of the XML namespace to search
+ * @return the index of the XML namespace found or -1 if not found.
+ */
+int zooXmlSearchForNs(const char* name){
+  int i;
+  int res=-1;
+  for(i=0;i<nbNs;i++)
+    if(strncasecmp(name,nsName[i],strlen(nsName[i]))==0){
+      res=i;
+      break;
+    }
+  return res;
+}
+
+/**
+ * Add an XML namespace to the usedNS if it was not already used.
+ * 
+ * @param nr the xmlNodePtr to attach the XML namspace (can be NULL)
+ * @param url the url of the XML namespace to add
+ * @param name the name of the XML namespace to add
+ * @return the index of the XML namespace added.
+ */
+int zooXmlAddNs(xmlNodePtr nr,const char* url,const char* name){
+#ifdef DEBUG
+  fprintf(stderr,"zooXmlAddNs %d %s \n",nbNs,name);
+#endif
+  int currId=-1;
+  if(nbNs==0){
+    nbNs++;
+    currId=0;
+    nsName[currId]=strdup(name);
+    usedNs[currId]=xmlNewNs(nr,BAD_CAST url,BAD_CAST name);
+  }else{
+    currId=zooXmlSearchForNs(name);
+    if(currId<0){
+      nbNs++;
+      currId=nbNs-1;
+      nsName[currId]=strdup(name);
+      usedNs[currId]=xmlNewNs(nr,BAD_CAST url,BAD_CAST name);
+    }
+  }
+  return currId;
+}
+
+/**
+ * Free allocated memory to store used XML namespace.
+ */
+void zooXmlCleanupNs(){
+  int j;
+#ifdef DEBUG
+  fprintf(stderr,"zooXmlCleanup %d\n",nbNs);
+#endif
+  for(j=nbNs-1;j>=0;j--){
+#ifdef DEBUG
+    fprintf(stderr,"zooXmlCleanup %d\n",j);
+#endif
+    if(j==0)
+      xmlFreeNs(usedNs[j]);
+    free(nsName[j]);
+    nbNs--;
+  }
+  nbNs=0;
+}
+
+/**
+ * Add a XML document to the iDocs.
+ * 
+ * @param value the string containing the XML document
+ * @return the index of the XML document added.
+ */
+int zooXmlAddDoc(const char* value){
+  int currId=0;
+  nbDocs++;
+  currId=nbDocs-1;
+  iDocs[currId]=xmlParseMemory(value,strlen(value));
+  return currId;
+}
+
+/**
+ * Free allocated memort to store XML documents
+ */
+void zooXmlCleanupDocs(){
+  int j;
+  for(j=nbDocs-1;j>=0;j--){
+    xmlFreeDoc(iDocs[j]);
+  }
+  nbDocs=0;
+}
+
+/**
+ * Generate a SOAP Envelope node when required (if the isSoap key of the [main]
+ * section is set to true).
+ * 
+ * @param conf the conf maps containing the main.cfg settings
+ * @param n the node used as children of the generated soap:Envelope
+ * @return the generated soap:Envelope (if isSoap=true) or the input node n 
+ *  (when isSoap=false)
+ */
+xmlNodePtr soapEnvelope(maps* conf,xmlNodePtr n){
+  map* soap=getMapFromMaps(conf,"main","isSoap");
+  if(soap!=NULL && strcasecmp(soap->value,"true")==0){
+    int lNbNs=nbNs;
+    nsName[lNbNs]=strdup("soap");
+    usedNs[lNbNs]=xmlNewNs(NULL,BAD_CAST "http://www.w3.org/2003/05/soap-envelope",BAD_CAST "soap");
+    nbNs++;
+    xmlNodePtr nr = xmlNewNode(usedNs[lNbNs], BAD_CAST "Envelope");
+    nsName[nbNs]=strdup("soap");
+    usedNs[nbNs]=xmlNewNs(nr,BAD_CAST "http://www.w3.org/2003/05/soap-envelope",BAD_CAST "soap");
+    nbNs++;
+    nsName[nbNs]=strdup("xsi");
+    usedNs[nbNs]=xmlNewNs(nr,BAD_CAST "http://www.w3.org/2001/XMLSchema-instance",BAD_CAST "xsi");
+    nbNs++;
+    xmlNsPtr ns_xsi=usedNs[nbNs-1];
+    xmlNewNsProp(nr,ns_xsi,BAD_CAST "schemaLocation",BAD_CAST "http://www.w3.org/2003/05/soap-envelope http://www.w3.org/2003/05/soap-envelope");
+    xmlNodePtr nr1 = xmlNewNode(usedNs[lNbNs], BAD_CAST "Body");
+    xmlAddChild(nr1,n);
+    xmlAddChild(nr,nr1);
+    return nr;
+  }else
+    return n;
+}
+
+/**
+ * Generate a WPS header.
+ * 
+ * @param doc the document to add the header
+ * @param m the conf maps containing the main.cfg settings
+ * @param req the request type (GetCapabilities,DescribeProcess,Execute)
+ * @param rname the root node name
+ * @return the generated wps:rname xmlNodePtr (can be wps: Capabilities, 
+ *  wps:ProcessDescriptions,wps:ExecuteResponse)
+ */
+xmlNodePtr printWPSHeader(xmlDocPtr doc,maps* m,const char* req,const char* rname,const char* version,int reqId){
+
+  xmlNsPtr ns,ns_xsi;
+  xmlNodePtr n;
+
+  int vid=getVersionId(version);
+
+  int wpsId=zooXmlAddNs(NULL,schemas[vid][2],"wps");
+  ns=usedNs[wpsId];
+  n = xmlNewNode(ns, BAD_CAST rname);
+  zooXmlAddNs(n,schemas[vid][1],"ows");
+  xmlNewNs(n,BAD_CAST schemas[vid][2],BAD_CAST "wps");
+  zooXmlAddNs(n,"http://www.w3.org/1999/xlink","xlink");
+  int xsiId=zooXmlAddNs(n,"http://www.w3.org/2001/XMLSchema-instance","xsi");
+  ns_xsi=usedNs[xsiId];
+  char *tmp=(char*) malloc((86+strlen(req)+1)*sizeof(char));
+  sprintf(tmp,schemas[vid][4],schemas[vid][2],schemas[vid][3],req);
+  xmlNewNsProp(n,ns_xsi,BAD_CAST "schemaLocation",BAD_CAST tmp);
+  free(tmp);
+  if(vid==0 || reqId==0){
+    xmlNewProp(n,BAD_CAST "service",BAD_CAST "WPS");
+    xmlNewProp(n,BAD_CAST "version",BAD_CAST schemas[vid][0]);
+  }
+  if(vid==0)
+    addLangAttr(n,m);
+  xmlNodePtr fn=soapEnvelope(m,n);
+  xmlDocSetRootElement(doc, fn);
+  return n;
+}
+
+void addLanguageNodes(maps* conf,xmlNodePtr n,xmlNsPtr ns,xmlNsPtr ns_ows){
+  xmlNodePtr nc1,nc2,nc3,nc4;
+  map* version=getMapFromMaps(conf,"main","rversion");
+  int vid=getVersionId(version->value);
+  if(vid==1)
+    nc1 = xmlNewNode(ns_ows, BAD_CAST "Languages");
+  else{
+    nc1 = xmlNewNode(ns, BAD_CAST "Languages");
+    nc2 = xmlNewNode(ns, BAD_CAST "Default");
+    nc3 = xmlNewNode(ns, BAD_CAST "Supported");
+  }
+
+  maps* tmp=getMaps(conf,"main");
+  if(tmp!=NULL){
+    map* tmp1=getMap(tmp->content,"lang");
+    char *toto=tmp1->value;
+    char buff[256];
+    int i=0;
+    int j=0;
+    int dcount=0;
+    while(toto[i]){
+      if(toto[i]!=',' && toto[i]!=0){
+	buff[j]=toto[i];
+	buff[j+1]=0;
+	j++;
+      }
+      else{
+	nc4 = xmlNewNode(ns_ows, BAD_CAST "Language");
+	xmlAddChild(nc4,xmlNewText(BAD_CAST buff));
+	if(dcount==0){
+	  if(vid==0){
+	    xmlAddChild(nc2,nc4);
+	    xmlAddChild(nc1,nc2);
+	  }
+	  dcount++;
+	}
+	nc4 = xmlNewNode(ns_ows, BAD_CAST "Language");
+	xmlAddChild(nc4,xmlNewText(BAD_CAST buff));
+	if(vid==0)
+	  xmlAddChild(nc3,nc4);
+	else
+	  xmlAddChild(nc1,nc4);
+	j=0;
+	buff[j]=0;
+      }
+      i++;
+    }
+    if(strlen(buff)>0){
+      nc4 = xmlNewNode(ns_ows, BAD_CAST "Language");
+      xmlAddChild(nc4,xmlNewText(BAD_CAST buff));	      
+	if(vid==0)
+	  xmlAddChild(nc3,nc4);
+	else
+	  xmlAddChild(nc1,nc4);
+    }
+  }
+  if(vid==0)
+    xmlAddChild(nc1,nc3);
+  xmlAddChild(n,nc1);
+}
+
+/**
+ * Generate a Capabilities header.
+ * 
+ * @param doc the document to add the header
+ * @param m the conf maps containing the main.cfg settings
+ * @return the generated wps:ProcessOfferings xmlNodePtr 
+ */
+xmlNodePtr printGetCapabilitiesHeader(xmlDocPtr doc,maps* m,const char* version="1.0.0"){
+
+  xmlNsPtr ns,ns_ows,ns_xlink;
+  xmlNodePtr n,nc,nc1,nc2,nc3,nc4,nc5,nc6;
+  n = printWPSHeader(doc,m,"GetCapabilities","Capabilities",version,0);
+  maps* toto1=getMaps(m,"main");
+  char tmp[256];
+  map* v=getMapFromMaps(m,"main","rversion");
+  int vid=getVersionId(v->value);
+
+  int wpsId=zooXmlAddNs(NULL,schemas[vid][2],"wps");
+  ns=usedNs[wpsId];
+  int xlinkId=zooXmlAddNs(NULL,"http://www.w3.org/1999/xlink","xlink");
+  ns_xlink=usedNs[xlinkId];
+  int owsId=zooXmlAddNs(NULL,schemas[vid][1],"ows");
+  ns_ows=usedNs[owsId];
+
+  nc = xmlNewNode(ns_ows, BAD_CAST "ServiceIdentification");
+  maps* tmp4=getMaps(m,"identification");
+  if(tmp4!=NULL){
+    map* tmp2=tmp4->content;
+    const char *orderedFields[5];
+    orderedFields[0]="Title";
+    orderedFields[1]="Abstract";
+    orderedFields[2]="Keywords";
+    orderedFields[3]="Fees";
+    orderedFields[4]="AccessConstraints";
+    int oI=0;
+    for(oI=0;oI<5;oI++)
+      if((tmp2=getMap(tmp4->content,orderedFields[oI]))!=NULL){
+	if(strcasecmp(tmp2->name,"abstract")==0 ||
+	   strcasecmp(tmp2->name,"title")==0 ||
+	   strcasecmp(tmp2->name,"accessConstraints")==0 ||
+	   strcasecmp(tmp2->name,"fees")==0){
+	  tmp2->name[0]=toupper(tmp2->name[0]);
+	  nc1 = xmlNewNode(ns_ows, BAD_CAST tmp2->name);
+	  xmlAddChild(nc1,xmlNewText(BAD_CAST tmp2->value));
+	  xmlAddChild(nc,nc1);
+	}
+	else
+	  if(strcmp(tmp2->name,"keywords")==0){
+	    nc1 = xmlNewNode(ns_ows, BAD_CAST "Keywords");
+	    char *toto=tmp2->value;
+	    char buff[256];
+	    int i=0;
+	    int j=0;
+	    while(toto[i]){
+	      if(toto[i]!=',' && toto[i]!=0){
+		buff[j]=toto[i];
+		buff[j+1]=0;
+		j++;
+	      }
+	      else{
+		nc2 = xmlNewNode(ns_ows, BAD_CAST "Keyword");
+		xmlAddChild(nc2,xmlNewText(BAD_CAST buff));	      
+		xmlAddChild(nc1,nc2);
+		j=0;
+	      }
+	      i++;
+	    }
+	    if(strlen(buff)>0){
+	      nc2 = xmlNewNode(ns_ows, BAD_CAST "Keyword");
+	      xmlAddChild(nc2,xmlNewText(BAD_CAST buff));	      
+	      xmlAddChild(nc1,nc2);
+	    }
+	    xmlAddChild(nc,nc1);
+	    nc2 = xmlNewNode(ns_ows, BAD_CAST "ServiceType");
+	    xmlAddChild(nc2,xmlNewText(BAD_CAST "WPS"));
+	    xmlAddChild(nc,nc2);
+	    nc2 = xmlNewNode(ns_ows, BAD_CAST "ServiceTypeVersion");
+	    map* tmpv=getMapFromMaps(m,"main","rversion");
+	    xmlAddChild(nc2,xmlNewText(BAD_CAST tmpv->value));
+	    xmlAddChild(nc,nc2);
+	  }
+	tmp2=tmp2->next;
+      }
+  }
+  else{
+    fprintf(stderr,"TMP4 NOT FOUND !!");
+    return NULL;
+  }
+  xmlAddChild(n,nc);
+
+  nc = xmlNewNode(ns_ows, BAD_CAST "ServiceProvider");
+  nc3 = xmlNewNode(ns_ows, BAD_CAST "ServiceContact");
+  nc4 = xmlNewNode(ns_ows, BAD_CAST "ContactInfo");
+  nc5 = xmlNewNode(ns_ows, BAD_CAST "Phone");
+  nc6 = xmlNewNode(ns_ows, BAD_CAST "Address");
+  tmp4=getMaps(m,"provider");
+  if(tmp4!=NULL){
+    map* tmp2=tmp4->content;
+    const char *tmpAddress[6];
+    tmpAddress[0]="addressDeliveryPoint";
+    tmpAddress[1]="addressCity";
+    tmpAddress[2]="addressAdministrativeArea";
+    tmpAddress[3]="addressPostalCode";
+    tmpAddress[4]="addressCountry";
+    tmpAddress[5]="addressElectronicMailAddress";
+    const char *tmpPhone[2];
+    tmpPhone[0]="phoneVoice";
+    tmpPhone[1]="phoneFacsimile";
+    const char *orderedFields[12];
+    orderedFields[0]="providerName";
+    orderedFields[1]="providerSite";
+    orderedFields[2]="individualName";
+    orderedFields[3]="positionName";
+    orderedFields[4]=tmpPhone[0];
+    orderedFields[5]=tmpPhone[1];
+    orderedFields[6]=tmpAddress[0];
+    orderedFields[7]=tmpAddress[1];
+    orderedFields[8]=tmpAddress[2];
+    orderedFields[9]=tmpAddress[3];
+    orderedFields[10]=tmpAddress[4];
+    orderedFields[11]=tmpAddress[5];
+    int oI=0;
+    for(oI=0;oI<12;oI++)
+      if((tmp2=getMap(tmp4->content,orderedFields[oI]))!=NULL){
+	if(strcmp(tmp2->name,"keywords")!=0 &&
+	   strcmp(tmp2->name,"serverAddress")!=0 &&
+	   strcmp(tmp2->name,"lang")!=0){
+	  tmp2->name[0]=toupper(tmp2->name[0]);
+	  if(strcmp(tmp2->name,"ProviderName")==0){
+	    nc1 = xmlNewNode(ns_ows, BAD_CAST tmp2->name);
+	    xmlAddChild(nc1,xmlNewText(BAD_CAST tmp2->value));
+	    xmlAddChild(nc,nc1);
+	  }
+	  else{
+	    if(strcmp(tmp2->name,"ProviderSite")==0){
+	      nc1 = xmlNewNode(ns_ows, BAD_CAST tmp2->name);
+	      xmlNewNsProp(nc1,ns_xlink,BAD_CAST "href",BAD_CAST tmp2->value);
+	      xmlAddChild(nc,nc1);
+	    } 
+	    else  
+	      if(strcmp(tmp2->name,"IndividualName")==0 || 
+		 strcmp(tmp2->name,"PositionName")==0){
+		nc1 = xmlNewNode(ns_ows, BAD_CAST tmp2->name);
+		xmlAddChild(nc1,xmlNewText(BAD_CAST tmp2->value));
+		xmlAddChild(nc3,nc1);
+	      } 
+	      else 
+		if(strncmp(tmp2->name,"Phone",5)==0){
+		  int j;
+		  for(j=0;j<2;j++)
+		    if(strcasecmp(tmp2->name,tmpPhone[j])==0){
+		      char *tmp4=tmp2->name;
+		      nc1 = xmlNewNode(ns_ows, BAD_CAST tmp4+5);
+		      xmlAddChild(nc1,xmlNewText(BAD_CAST tmp2->value));
+		      xmlAddChild(nc5,nc1);
+		    }
+		}
+		else 
+		  if(strncmp(tmp2->name,"Address",7)==0){
+		    int j;
+		    for(j=0;j<6;j++)
+		      if(strcasecmp(tmp2->name,tmpAddress[j])==0){
+			char *tmp4=tmp2->name;
+			nc1 = xmlNewNode(ns_ows, BAD_CAST tmp4+7);
+			xmlAddChild(nc1,xmlNewText(BAD_CAST tmp2->value));
+			xmlAddChild(nc6,nc1);
+		      }
+		  }
+	  }
+	}
+	else
+	  if(strcmp(tmp2->name,"keywords")==0){
+	    nc1 = xmlNewNode(ns_ows, BAD_CAST "Keywords");
+	    char *toto=tmp2->value;
+	    char buff[256];
+	    int i=0;
+	    int j=0;
+	    while(toto[i]){
+	      if(toto[i]!=',' && toto[i]!=0){
+		buff[j]=toto[i];
+		buff[j+1]=0;
+		j++;
+	      }
+	      else{
+		nc2 = xmlNewNode(ns_ows, BAD_CAST "Keyword");
+		xmlAddChild(nc2,xmlNewText(BAD_CAST buff));	      
+		xmlAddChild(nc1,nc2);
+		j=0;
+	      }
+	      i++;
+	    }
+	    if(strlen(buff)>0){
+	      nc2 = xmlNewNode(ns_ows, BAD_CAST "Keyword");
+	      xmlAddChild(nc2,xmlNewText(BAD_CAST buff));	      
+	      xmlAddChild(nc1,nc2);
+	    }
+	    xmlAddChild(nc,nc1);
+	  }
+	tmp2=tmp2->next;
+      }
+  }
+  else{
+    fprintf(stderr,"TMP4 NOT FOUND !!");
+  }
+  xmlAddChild(nc4,nc5);
+  xmlAddChild(nc4,nc6);
+  xmlAddChild(nc3,nc4);
+  xmlAddChild(nc,nc3);
+  xmlAddChild(n,nc);
+
+
+  nc = xmlNewNode(ns_ows, BAD_CAST "OperationsMetadata");
+
+  int j=0;
+
+  if(toto1!=NULL){
+    map* tmp=getMap(toto1->content,"serverAddress");
+    if(tmp!=NULL){
+      SERVICE_URL = strdup(tmp->value);
+    }
+    else
+      SERVICE_URL = strdup("not_defined");
+  }
+  else
+    SERVICE_URL = strdup("not_defined");
+
+  for(j=0;j<nbSupportedRequests;j++){
+    if(requests[vid][j]==NULL)
+      break;
+    else{
+      nc1 = xmlNewNode(ns_ows, BAD_CAST "Operation");
+      xmlNewProp(nc1,BAD_CAST "name",BAD_CAST requests[vid][j]);
+      nc2 = xmlNewNode(ns_ows, BAD_CAST "DCP");
+      nc3 = xmlNewNode(ns_ows, BAD_CAST "HTTP");
+      if(vid!=1 || j!=2){
+	nc4 = xmlNewNode(ns_ows, BAD_CAST "Get");
+	xmlNewNsProp(nc4,ns_xlink,BAD_CAST "href",BAD_CAST SERVICE_URL);
+	xmlAddChild(nc3,nc4);
+      }
+      nc4 = xmlNewNode(ns_ows, BAD_CAST "Post");
+      xmlNewNsProp(nc4,ns_xlink,BAD_CAST "href",BAD_CAST SERVICE_URL);
+      xmlAddChild(nc3,nc4);
+      xmlAddChild(nc2,nc3);
+      xmlAddChild(nc1,nc2);
+      xmlAddChild(nc,nc1);
+    }
+  }
+  xmlAddChild(n,nc);
+
+  if(vid==1)
+    addLanguageNodes(m,n,ns,ns_ows);
+  free(SERVICE_URL);
+
+  nc = xmlNewNode(ns, BAD_CAST root_nodes[vid][0]);
+  xmlAddChild(n,nc);
+
+  if(vid==0)
+    addLanguageNodes(m,n,ns,ns_ows);
+
+  return nc;
+}
+
+/**
+ * Generate a wps:Process node for a servie and add it to a given node.
+ * 
+ * @param reg the profiles registry
+ * @param m the conf maps containing the main.cfg settings
+ * @param registry the profile registry if any
+ * @param nc the XML node to add the Process node
+ * @param serv the service structure created from the zcfg file
+ * @return the generated wps:ProcessOfferings xmlNodePtr 
+ */
+void printGetCapabilitiesForProcess(registry *reg, maps* m,xmlNodePtr nc,service* serv){
+  xmlNsPtr ns,ns_ows,ns_xml,ns_xlink;
+  xmlNodePtr n=NULL,nc1,nc2;
+  map* version=getMapFromMaps(m,"main","rversion");
+  int vid=getVersionId(version->value);
+  // Initialize or get existing namespaces
+  int wpsId=zooXmlAddNs(NULL,schemas[vid][2],"wps");
+  ns=usedNs[wpsId];
+  int owsId=zooXmlAddNs(NULL,schemas[vid][1],"ows");
+  ns_ows=usedNs[owsId];
+  int xmlId=zooXmlAddNs(NULL,"http://www.w3.org/XML/1998/namespace","xml");
+  ns_xml=usedNs[xmlId];
+  int xlinkId=zooXmlAddNs(n,"http://www.w3.org/1999/xlink","xlink");
+  ns_xlink=usedNs[xlinkId];
+  map* tmp1;
+  if(serv->content!=NULL){
+    nc1 = xmlNewNode(ns, BAD_CAST capabilities[vid][0]);
+    int i=1;
+    int limit=3;
+    if(vid==1){
+      ns=NULL;
+      limit=7;
+    }
+    for(;i<limit;i+=2){
+      if(capabilities[vid][i]==NULL)
+	break;
+      else{
+	tmp1=getMap(serv->content,capabilities[vid][i]);
+	if(tmp1!=NULL){
+	  if(vid==1 && i==1 && strlen(tmp1->value)<5){
+	    char *val=(char*)malloc((strlen(tmp1->value)+5)*sizeof(char));
+	    sprintf(val,"%s.0.0",tmp1->value);
+	    xmlNewNsProp(nc1,ns,BAD_CAST capabilities[vid][i],BAD_CAST val);
+	    free(val);
+	  }
+	  else
+	    xmlNewNsProp(nc1,ns,BAD_CAST capabilities[vid][i],BAD_CAST tmp1->value);
+	}
+	else
+	  xmlNewNsProp(nc1,ns,BAD_CAST capabilities[vid][i],BAD_CAST capabilities[vid][i+1]);
+      }
+    }
+    map* tmp3=getMapFromMaps(m,"lenv","level");
+    addPrefix(m,tmp3,serv);
+    printDescription(nc1,ns_ows,serv->name,serv->content,vid);
+    tmp1=serv->metadata;
+    while(tmp1!=NULL){
+      nc2 = xmlNewNode(ns_ows, BAD_CAST "Metadata");
+      xmlNewNsProp(nc2,ns_xlink,BAD_CAST tmp1->name,BAD_CAST tmp1->value);
+      xmlAddChild(nc1,nc2);
+      tmp1=tmp1->next;
+    }
+
+    xmlAddChild(nc,nc1);
+  }
+}
+
+/**
+ * Attach attributes to a ProcessDescription or a ProcessOffering node.
+ * 
+ * @param n the XML node to attach the attributes to
+ * @param ns the XML namespace to create the attributes
+ * @param content the servive main content created from the zcfg file
+ * @param vid the version identifier (0 for 1.0.0 and 1 for 2.0.0)
+ */
+void attachAttributes(xmlNodePtr n,xmlNsPtr ns,map* content,int vid){
+  int limit=(vid==1?7:3);
+  for(int i=1;i<limit;i+=2){
+    map* tmp1=getMap(content,capabilities[vid][i]);
+    if(tmp1!=NULL){
+      if(vid==1 && i==1 && strlen(tmp1->value)<5){
+	char *val=(char*)malloc((strlen(tmp1->value)+5)*sizeof(char));
+	sprintf(val,"%s.0.0",tmp1->value);
+	xmlNewNsProp(n,ns,BAD_CAST capabilities[vid][i],BAD_CAST val);
+	free(val);
+      }
+      else
+	xmlNewNsProp(n,ns,BAD_CAST capabilities[vid][i],BAD_CAST tmp1->value);
+    }
+    else
+      xmlNewNsProp(n,ns,BAD_CAST capabilities[vid][i],BAD_CAST capabilities[vid][i+1]);
+  }
+}
+
+/**
+ * Add the ows:Metadata nodes relative to the profile registry
+ *
+ * @param n the XML node to add the ows:Metadata
+ * @param ns_ows the ows XML namespace
+ * @param ns_xlink the ows xlink namespace
+ * @param reg the profile registry
+ * @param main_conf the map containing the main configuration content
+ * @param serv the service 
+ */
+void addInheritedMetadata(xmlNodePtr n,xmlNsPtr ns_ows,xmlNsPtr ns_xlink,registry* reg,maps* main_conf,service* serv){
+  int vid=1;
+  map* tmp1=getMap(serv->content,"extend");
+  if(tmp1==NULL)
+    tmp1=getMap(serv->content,"concept");
+  if(tmp1!=NULL){
+    map* level=getMap(serv->content,"level");
+    if(level!=NULL){
+      xmlNodePtr nc1 = xmlNewNode(ns_ows, BAD_CAST "Metadata");
+      char* ckey=level->value;
+      if(strncasecmp(level->value,"profile",7)==0)
+	ckey="generic";
+      if(strncasecmp(level->value,"generic",7)==0)
+	ckey="concept";
+      service* inherited=getServiceFromRegistry(reg,ckey,tmp1->value);
+      if(inherited!=NULL){
+	addInheritedMetadata(n,ns_ows,ns_xlink,reg,main_conf,inherited);
+      }
+      char cschema[71];
+      sprintf(cschema,"%s%s",schemas[vid][7],ckey);
+      map* regUrl=getMapFromMaps(main_conf,"main","registryUrl");
+      map* regExt=getMapFromMaps(main_conf,"main","registryExt");
+      char* registryUrl=(char*)malloc((strlen(regUrl->value)+strlen(ckey)+
+				       (regExt!=NULL?strlen(regExt->value)+1:0)+
+				       strlen(tmp1->value)+2)*sizeof(char));
+      if(regExt!=NULL)
+	sprintf(registryUrl,"%s%s/%s.%s",regUrl->value,ckey,tmp1->value,regExt->value);
+      else
+	sprintf(registryUrl,"%s%s/%s",regUrl->value,ckey,tmp1->value);
+      xmlNewNsProp(nc1,ns_xlink,BAD_CAST "role",BAD_CAST cschema);
+      xmlNewNsProp(nc1,ns_xlink,BAD_CAST "href",BAD_CAST registryUrl);
+      free(registryUrl);
+      xmlAddChild(n,nc1);
+    }
+  }
+}
+
+/**
+ * Generate a ProcessDescription node for a servie and add it to a given node.
+ * 
+ * @param reg the profile registry
+ * @param m the conf maps containing the main.cfg settings
+ * @param nc the XML node to add the Process node
+ * @param serv the servive structure created from the zcfg file
+ * @return the generated wps:ProcessOfferings xmlNodePtr 
+ */
+void printDescribeProcessForProcess(registry *reg, maps* m,xmlNodePtr nc,service* serv){
+  xmlNsPtr ns,ns_ows,ns_xlink;
+  xmlNodePtr n,nc1,nc2;
+  map* version=getMapFromMaps(m,"main","rversion");
+  int vid=getVersionId(version->value);
+
+  n=nc;
+  
+  int wpsId=zooXmlAddNs(NULL,schemas[vid][3],"wps");
+  ns=usedNs[wpsId];
+  int owsId=zooXmlAddNs(NULL,schemas[vid][1],"ows");
+  ns_ows=usedNs[owsId];
+  int xlinkId=zooXmlAddNs(NULL,"http://www.w3.org/1999/xlink","xlink");
+  ns_xlink=usedNs[xlinkId];
+  map* tmp1=NULL;
+
+  if(vid==0){
+    nc = xmlNewNode(NULL, BAD_CAST "ProcessDescription");
+    attachAttributes(nc,ns,serv->content,vid);
+  }
+  else{
+    nc2 = xmlNewNode(ns, BAD_CAST "ProcessOffering");
+    // In case mode was defined in the ZCFG file then restrict the 
+    // jobControlOptions value to this value. The dismiss is always 
+    // supported whatever you can set in the ZCFG file.
+    // cf. http://docs.opengeospatial.org/is/14-065/14-065.html#47 (Table 30)
+    map* mode=getMap(serv->content,"mode");
+    if(mode!=NULL){
+      if( strncasecmp(mode->value,"sync",strlen(mode->value))==0 ||
+	  strncasecmp(mode->value,"async",strlen(mode->value))==0 ){
+	char toReplace[22];
+	sprintf(toReplace,"%s-execute dismiss",mode->value);
+	addToMap(serv->content,capabilities[vid][3],toReplace);
+      }
+    }
+    attachAttributes(nc2,NULL,serv->content,vid);
+    map* level=getMap(serv->content,"level");
+    if(level!=NULL && strcasecmp(level->value,"generic")==0)
+      nc = xmlNewNode(ns, BAD_CAST "GenericProcess");
+    else
+      nc = xmlNewNode(ns, BAD_CAST "Process");
+  }
+  
+  tmp1=getMapFromMaps(m,"lenv","level");
+  addPrefix(m,tmp1,serv);
+  printDescription(nc,ns_ows,serv->name,serv->content,vid);
+
+  if(vid==0){
+    tmp1=serv->metadata;
+    while(tmp1!=NULL){
+      nc1 = xmlNewNode(ns_ows, BAD_CAST "Metadata");
+      xmlNewNsProp(nc1,ns_xlink,BAD_CAST tmp1->name,BAD_CAST tmp1->value);
+      xmlAddChild(nc,nc1);
+      tmp1=tmp1->next;
+    }
+    tmp1=getMap(serv->content,"Profile");
+    if(tmp1!=NULL && vid==0){
+      nc1 = xmlNewNode(ns, BAD_CAST "Profile");
+      xmlAddChild(nc1,xmlNewText(BAD_CAST tmp1->value));
+      xmlAddChild(nc,nc1);
+    }
+  }else{
+    addInheritedMetadata(nc,ns_ows,ns_xlink,reg,m,serv);
+  }
+
+  if(serv->inputs!=NULL){
+    elements* e=serv->inputs;
+    if(vid==0){
+      nc1 = xmlNewNode(NULL, BAD_CAST "DataInputs");
+      printFullDescription(1,e,"Input",ns,ns_ows,nc1,vid);
+      xmlAddChild(nc,nc1);
+    }
+    else{
+      printFullDescription(1,e,"wps:Input",ns,ns_ows,nc,vid);
+    }
+  }
+
+  elements* e=serv->outputs;
+  if(vid==0){
+    nc1 = xmlNewNode(NULL, BAD_CAST "ProcessOutputs");
+    printFullDescription(0,e,"Output",ns,ns_ows,nc1,vid);
+    xmlAddChild(nc,nc1);
+  }
+  else{
+    printFullDescription(0,e,"wps:Output",ns,ns_ows,nc,vid);
+  }
+  if(vid==0)
+    xmlAddChild(n,nc);
+  else{
+    xmlAddChild(nc2,nc);
+    xmlAddChild(n,nc2);
+  }
+
+}
+
+/**
+ * Generate the required XML tree for the detailled metadata informations of 
+ * inputs or outputs
+ *
+ * @param in 1 in case of inputs, 0 for outputs
+ * @param elem the elements structure containing the metadata informations
+ * @param type the name ("Input" or "Output") of the XML node to create
+ * @param ns_ows the ows XML namespace
+ * @param ns_ows the ows XML namespace
+ * @param nc1 the XML node to use to add the created tree
+ * @param vid the WPS version id (0 for 1.0.0, 1 for 2.0.0)
+ */
+void printFullDescription(int in,elements *elem,const char* type,xmlNsPtr ns,xmlNsPtr ns_ows,xmlNodePtr nc1,int vid){
+  xmlNsPtr ns1=NULL;
+  if(vid==1)
+    ns1=ns;
+
+  xmlNodePtr nc2,nc3,nc4,nc5,nc6,nc7,nc8,nc9;
+  elements* e=elem;
+  nc9=NULL;
+  map* tmp1=NULL;
+  while(e!=NULL){
+    int default1=0;
+    int isAnyValue=1;
+    nc2 = xmlNewNode(NULL, BAD_CAST type);
+    if(strstr(type,"Input")!=NULL){
+      tmp1=getMap(e->content,"minOccurs");
+      if(tmp1!=NULL){
+	xmlNewProp(nc2,BAD_CAST tmp1->name,BAD_CAST tmp1->value);
+      }else
+	xmlNewProp(nc2,BAD_CAST "minOccurs",BAD_CAST "0");
+      tmp1=getMap(e->content,"maxOccurs");
+      if(tmp1!=NULL){
+	if(strcasecmp(tmp1->value,"unbounded")!=0)
+	  xmlNewProp(nc2,BAD_CAST tmp1->name,BAD_CAST tmp1->value);
+	else
+	  xmlNewProp(nc2,BAD_CAST "maxOccurs",BAD_CAST "1000");
+      }else
+	xmlNewProp(nc2,BAD_CAST "maxOccurs",BAD_CAST "1");
+      if((tmp1=getMap(e->content,"maximumMegabytes"))!=NULL){
+	xmlNewProp(nc2,BAD_CAST "maximumMegabytes",BAD_CAST tmp1->value);
+      }
+    }
+
+    printDescription(nc2,ns_ows,e->name,e->content,vid);
+
+    if(e->format!=NULL){
+      const char orderedFields[13][14]={
+	"mimeType",
+	"encoding",
+	"schema",
+	"dataType",
+	"uom",
+	"CRS",
+	"AllowedValues",
+	"range",
+	"rangeMin",
+	"rangeMax",
+	"rangeClosure",
+	"rangeSpace"
+      };
+
+      //Build the (Literal/Complex/BoundingBox)Data node
+      if(strncmp(type,"Output",6)==0){
+	if(strncasecmp(e->format,"LITERALDATA",strlen(e->format))==0)
+	  nc3 = xmlNewNode(ns1, BAD_CAST "LiteralOutput");
+	else if(strncasecmp(e->format,"COMPLEXDATA",strlen(e->format))==0)
+	  nc3 = xmlNewNode(ns1, BAD_CAST "ComplexOutput");
+	else if(strncasecmp(e->format,"BOUNDINGBOXDATA",strlen(e->format))==0)
+	  nc3 = xmlNewNode(ns1, BAD_CAST "BoundingBoxOutput");
+	else
+	  nc3 = xmlNewNode(ns1, BAD_CAST e->format);
+      }else{
+	if(strncasecmp(e->format,"LITERALDATA",strlen(e->format))==0 ||
+	   strncasecmp(e->format,"LITERALOUTPUT",strlen(e->format))==0){
+	  nc3 = xmlNewNode(ns1, BAD_CAST "LiteralData");
+	}
+	else if(strncasecmp(e->format,"COMPLEXDATA",strlen(e->format))==0)
+	  nc3 = xmlNewNode(ns1, BAD_CAST "ComplexData");
+	else if(strncasecmp(e->format,"BOUNDINGBOXDATA",strlen(e->format))==0)
+	  nc3 = xmlNewNode(ns1, BAD_CAST "BoundingBoxData");
+	else
+	  nc3 = xmlNewNode(ns1, BAD_CAST e->format);
+      }
+
+      iotype* _tmp0=NULL;
+      iotype* _tmp=e->defaults;
+      int datatype=0;
+      bool hasUOM=false;
+      bool hasUOM1=false;
+      if(_tmp!=NULL){
+	if(strcmp(e->format,"LiteralOutput")==0 ||
+	   strcmp(e->format,"LiteralData")==0){
+	  datatype=1;
+	  if(vid==1){
+	    nc4 = xmlNewNode(ns1, BAD_CAST "Format");
+	    xmlNewProp(nc4,BAD_CAST "mimeType",BAD_CAST "text/plain");
+	    xmlNewProp(nc4,BAD_CAST "default",BAD_CAST "true");
+	    xmlAddChild(nc3,nc4);
+	    nc5 = xmlNewNode(NULL, BAD_CAST "LiteralDataDomain");
+	    xmlNewProp(nc5,BAD_CAST "default",BAD_CAST "true");
+	  }
+	  else{
+	    nc4 = xmlNewNode(NULL, BAD_CAST "UOMs");
+	    nc5 = xmlNewNode(NULL, BAD_CAST "Default");
+	  }
+	}
+	else if(strcmp(e->format,"BoundingBoxOutput")==0 ||
+		strcmp(e->format,"BoundingBoxData")==0){
+	  datatype=2;
+	  nc5 = xmlNewNode(NULL, BAD_CAST "Default");
+	}
+	else{
+	  if(vid==0)
+	    nc4 = xmlNewNode(NULL, BAD_CAST "Default");
+	  nc5 = xmlNewNode(ns1, BAD_CAST "Format");
+	  if(vid==1){
+	    xmlNewProp(nc5,BAD_CAST "default",BAD_CAST "true");
+	    int oI=0;
+	    for(oI=0;oI<3;oI++)
+	      if((tmp1=getMap(_tmp->content,orderedFields[oI]))!=NULL){
+		xmlNewProp(nc5,BAD_CAST orderedFields[oI],BAD_CAST tmp1->value);
+	      }
+	  }
+	}
+      
+	tmp1=_tmp->content;
+
+	if(vid==0)
+	  if((tmp1=getMap(_tmp->content,"DataType"))!=NULL){
+	    nc8 = xmlNewNode(ns_ows, BAD_CAST "DataType");
+	    xmlAddChild(nc8,xmlNewText(BAD_CAST tmp1->value));
+	    char tmp[1024];
+	    sprintf(tmp,"http://www.w3.org/TR/xmlschema-2/#%s",tmp1->value);
+	    xmlNewNsProp(nc8,ns_ows,BAD_CAST "reference",BAD_CAST tmp);
+	    if(vid==0)
+	      xmlAddChild(nc3,nc8);
+	    else
+	      xmlAddChild(nc5,nc8);
+	    datatype=1;
+	  }
+
+	bool isInput=false;
+	if(strncmp(type,"Input",5)==0 || strncmp(type,"wps:Input",9)==0){
+	  isInput=true;
+	  if((tmp1=getMap(_tmp->content,"AllowedValues"))!=NULL){
+	    nc6 = xmlNewNode(ns_ows, BAD_CAST "AllowedValues");
+	    char *token,*saveptr1;
+	    token=strtok_r(tmp1->value,",",&saveptr1);
+	    while(token!=NULL){
+	      nc7 = xmlNewNode(ns_ows, BAD_CAST "Value");
+	      char *tmps=strdup(token);
+	      tmps[strlen(tmps)]=0;
+	      xmlAddChild(nc7,xmlNewText(BAD_CAST tmps));
+	      free(tmps);
+	      xmlAddChild(nc6,nc7);
+	      token=strtok_r(NULL,",",&saveptr1);
+	    }
+	    if(getMap(_tmp->content,"range")!=NULL ||
+	       getMap(_tmp->content,"rangeMin")!=NULL ||
+	       getMap(_tmp->content,"rangeMax")!=NULL ||
+	       getMap(_tmp->content,"rangeClosure")!=NULL )
+	      goto doRange;
+	    if(vid==0)
+	      xmlAddChild(nc3,nc6);
+	    else
+	      xmlAddChild(nc5,nc6);
+	    isAnyValue=-1;
+	  }
+
+	  tmp1=getMap(_tmp->content,"range");
+	  if(tmp1==NULL)
+	    tmp1=getMap(_tmp->content,"rangeMin");
+	  if(tmp1==NULL)
+	    tmp1=getMap(_tmp->content,"rangeMax");
+	
+	  if(tmp1!=NULL && isAnyValue==1){
+	    nc6 = xmlNewNode(ns_ows, BAD_CAST "AllowedValues");
+	  doRange:
+	  
+	    /**
+	     * Range: Table 46 OGC Web Services Common Standard
+	     */
+	    nc8 = xmlNewNode(ns_ows, BAD_CAST "Range");
+	  
+	    map* tmp0=getMap(tmp1,"range");
+	    if(tmp0!=NULL){
+	      char* pToken;
+	      char* orig=zStrdup(tmp0->value);
+	      /**
+	       * RangeClosure: Table 47 OGC Web Services Common Standard
+	       */
+	      const char *tmp="closed";
+	      if(orig[0]=='[' && orig[strlen(orig)-1]=='[')
+		tmp="closed-open";
+	      else
+		if(orig[0]==']' && orig[strlen(orig)-1]==']')
+		  tmp="open-closed";
+		else
+		  if(orig[0]==']' && orig[strlen(orig)-1]=='[')
+		    tmp="open";
+	      xmlNewNsProp(nc8,ns_ows,BAD_CAST "rangeClosure",BAD_CAST tmp);
+	      pToken=strtok(orig,",");
+	      int nci0=0;
+	      while(pToken!=NULL){
+		char *tmpStr=(char*) malloc((strlen(pToken))*sizeof(char));
+		if(nci0==0){
+		  nc7 = xmlNewNode(ns_ows, BAD_CAST "MinimumValue");
+		  strncpy( tmpStr, pToken+1, strlen(pToken)-1 );
+		  tmpStr[strlen(pToken)-1] = '\0';
+		}else{
+		  nc7 = xmlNewNode(ns_ows, BAD_CAST "MaximumValue");
+		  const char* bkt;
+		  if ( ( bkt = strchr(pToken, '[') ) != NULL || ( bkt = strchr(pToken, ']') ) != NULL ){
+		    strncpy( tmpStr, pToken, bkt - pToken );
+		    tmpStr[bkt - pToken] = '\0';
+		  }
+		}
+		xmlAddChild(nc7,xmlNewText(BAD_CAST tmpStr));
+		free(tmpStr);
+		xmlAddChild(nc8,nc7);
+		nci0++;
+		pToken = strtok(NULL,",");
+	      }		    
+	      if(getMap(tmp1,"rangeSpacing")==NULL){
+		nc7 = xmlNewNode(ns_ows, BAD_CAST "Spacing");
+		xmlAddChild(nc7,xmlNewText(BAD_CAST "1"));
+		xmlAddChild(nc8,nc7);
+	      }
+	      free(orig);
+	    }else{
+	    
+	      tmp0=getMap(tmp1,"rangeMin");
+	      if(tmp0!=NULL){
+		nc7 = xmlNewNode(ns_ows, BAD_CAST "MinimumValue");
+		xmlAddChild(nc7,xmlNewText(BAD_CAST tmp0->value));
+		xmlAddChild(nc8,nc7);
+	      }else{
+		nc7 = xmlNewNode(ns_ows, BAD_CAST "MinimumValue");
+		xmlAddChild(nc8,nc7);
+	      }
+	      tmp0=getMap(tmp1,"rangeMax");
+	      if(tmp0!=NULL){
+		nc7 = xmlNewNode(ns_ows, BAD_CAST "MaximumValue");
+		xmlAddChild(nc7,xmlNewText(BAD_CAST tmp0->value));
+		xmlAddChild(nc8,nc7);
+	      }else{
+		nc7 = xmlNewNode(ns_ows, BAD_CAST "MaximumValue");
+		xmlAddChild(nc8,nc7);
+	      }
+	      tmp0=getMap(tmp1,"rangeSpacing");
+	      if(tmp0!=NULL){
+		nc7 = xmlNewNode(ns_ows, BAD_CAST "Spacing");
+		xmlAddChild(nc7,xmlNewText(BAD_CAST tmp0->value));
+		xmlAddChild(nc8,nc7);
+	      }
+	      tmp0=getMap(tmp1,"rangeClosure");
+	      if(tmp0!=NULL){
+		const char *tmp="closed";
+		if(strcasecmp(tmp0->value,"co")==0)
+		  tmp="closed-open";
+		else
+		  if(strcasecmp(tmp0->value,"oc")==0)
+		    tmp="open-closed";
+		  else
+		    if(strcasecmp(tmp0->value,"o")==0)
+		      tmp="open";
+		xmlNewNsProp(nc8,ns_ows,BAD_CAST "rangeClosure",BAD_CAST tmp);
+	      }else
+		xmlNewNsProp(nc8,ns_ows,BAD_CAST "rangeClosure",BAD_CAST "closed");
+	    }
+	    if(_tmp0==NULL){
+	      xmlAddChild(nc6,nc8);
+	      _tmp0=e->supported;
+	      if(_tmp0!=NULL &&
+		 (getMap(_tmp0->content,"range")!=NULL ||
+		  getMap(_tmp0->content,"rangeMin")!=NULL ||
+		  getMap(_tmp0->content,"rangeMax")!=NULL ||
+		  getMap(_tmp0->content,"rangeClosure")!=NULL )){
+		tmp1=_tmp0->content;
+		goto doRange;
+	      }
+	    }else{
+	      _tmp0=_tmp0->next;
+	      if(_tmp0!=NULL){
+		xmlAddChild(nc6,nc8);
+		if(getMap(_tmp0->content,"range")!=NULL ||
+		   getMap(_tmp0->content,"rangeMin")!=NULL ||
+		   getMap(_tmp0->content,"rangeMax")!=NULL ||
+		   getMap(_tmp0->content,"rangeClosure")!=NULL ){
+		  tmp1=_tmp0->content;
+		  goto doRange;
+		}
+	      }
+	    }
+	    xmlAddChild(nc6,nc8);
+	    if(vid==0)
+	      xmlAddChild(nc3,nc6);
+	    else
+	      xmlAddChild(nc5,nc6);
+	    isAnyValue=-1;
+	  }
+	
+	}
+      
+	int oI=0;
+	/*if(vid==0)*/ {
+	  for(oI=0;oI<13;oI++)
+	    if((tmp1=getMap(_tmp->content,orderedFields[oI]))!=NULL){
+#ifdef DEBUG
+	      printf("DATATYPE DEFAULT ? %s\n",tmp1->name);
+#endif
+	      if(strcmp(tmp1->name,"asReference")!=0 &&
+		 strncasecmp(tmp1->name,"DataType",8)!=0 &&
+		 strcasecmp(tmp1->name,"extension")!=0 &&
+		 strcasecmp(tmp1->name,"value")!=0 &&
+		 strcasecmp(tmp1->name,"AllowedValues")!=0 &&
+		 strncasecmp(tmp1->name,"range",5)!=0){
+		if(datatype!=1){
+		  char *tmp2=zCapitalize1(tmp1->name);
+		  nc9 = xmlNewNode(NULL, BAD_CAST tmp2);
+		  free(tmp2);
+		}
+		else{
+		  char *tmp2=zCapitalize(tmp1->name);
+		  nc9 = xmlNewNode(ns_ows, BAD_CAST tmp2);
+		  free(tmp2);
+		}
+		xmlAddChild(nc9,xmlNewText(BAD_CAST tmp1->value));
+		if(vid==0 || oI>=3){
+		  if(vid==0 || oI!=4)
+		    xmlAddChild(nc5,nc9);
+		  if(oI==4 && vid==1){
+		    xmlNewProp(nc9,BAD_CAST "default",BAD_CAST "true");
+		  }
+		}
+		else
+		  xmlFree(nc9);
+		if(strcasecmp(tmp1->name,"uom")==0)
+		  hasUOM1=true;
+		hasUOM=true;
+	      }else 	  
+		tmp1=tmp1->next;
+	    }
+	}
+    
+	if(datatype!=2){
+	  if(hasUOM==true){
+	    if(vid==0){
+	      xmlAddChild(nc4,nc5);
+	      xmlAddChild(nc3,nc4);
+	    }
+	    else{
+	      xmlAddChild(nc3,nc5);
+	    }
+	  }else{
+	    if(hasUOM1==false && vid==0){
+	      xmlFreeNode(nc5);
+	      if(datatype==1)
+		xmlFreeNode(nc4);
+	    }
+	    else
+	      xmlAddChild(nc3,nc5);
+	  }
+	}else{
+	  xmlAddChild(nc3,nc5);
+	}
+      
+	if(datatype!=1 && default1<0){
+	  xmlFreeNode(nc5);
+	  if(datatype!=2)
+	    xmlFreeNode(nc4);
+	}
+
+
+	if((isInput || vid==1) && datatype==1 &&
+	   getMap(_tmp->content,"AllowedValues")==NULL &&
+	   getMap(_tmp->content,"range")==NULL &&
+	   getMap(_tmp->content,"rangeMin")==NULL &&
+	   getMap(_tmp->content,"rangeMax")==NULL &&
+	   getMap(_tmp->content,"rangeClosure")==NULL ){
+	  tmp1=getMap(_tmp->content,"dataType");
+	  // We were tempted to define default value for boolean as {true,false}
+	  if(tmp1!=NULL && strcasecmp(tmp1->value,"boolean")==0){
+	    nc6 = xmlNewNode(ns_ows, BAD_CAST "AllowedValues");
+	    nc7 = xmlNewNode(ns_ows, BAD_CAST "Value");
+	    xmlAddChild(nc7,xmlNewText(BAD_CAST "true"));
+	    xmlAddChild(nc6,nc7);
+	    nc7 = xmlNewNode(ns_ows, BAD_CAST "Value");
+	    xmlAddChild(nc7,xmlNewText(BAD_CAST "false"));
+	    xmlAddChild(nc6,nc7);
+	    if(vid==0)
+	      xmlAddChild(nc3,nc6);
+	    else
+	      xmlAddChild(nc5,nc6);
+	  }
+	  else
+	    if(vid==0)
+	      xmlAddChild(nc3,xmlNewNode(ns_ows, BAD_CAST "AnyValue"));
+	    else
+	      xmlAddChild(nc5,xmlNewNode(ns_ows, BAD_CAST "AnyValue"));
+	}
+
+	if(vid==1){
+	  if((tmp1=getMap(_tmp->content,"DataType"))!=NULL){
+	    nc8 = xmlNewNode(ns_ows, BAD_CAST "DataType");
+	    xmlAddChild(nc8,xmlNewText(BAD_CAST tmp1->value));
+	    char tmp[1024];
+	    sprintf(tmp,"http://www.w3.org/TR/xmlschema-2/#%s",tmp1->value);
+	    xmlNewNsProp(nc8,ns_ows,BAD_CAST "reference",BAD_CAST tmp);
+	    if(vid==0)
+	      xmlAddChild(nc3,nc8);
+	    else
+	      xmlAddChild(nc5,nc8);
+	    datatype=1;
+	  }
+	  if(hasUOM==true){
+	    tmp1=getMap(_tmp->content,"uom");
+	    if(tmp1!=NULL){
+	      char *tmp2=zCapitalize(tmp1->name);
+	      nc9 = xmlNewNode(ns_ows, BAD_CAST tmp2);
+	      free(tmp2);
+	      //xmlNewProp(nc9, BAD_CAST "default", BAD_CAST "true");
+	      xmlAddChild(nc9,xmlNewText(BAD_CAST tmp1->value));
+	      xmlAddChild(nc5,nc9);
+	      /*struct iotype * _ltmp=e->supported;
+		while(_ltmp!=NULL){
+		tmp1=getMap(_ltmp->content,"uom");
+		if(tmp1!=NULL){
+		char *tmp2=zCapitalize(tmp1->name);
+		nc9 = xmlNewNode(ns_ows, BAD_CAST tmp2);
+		free(tmp2);
+		xmlAddChild(nc9,xmlNewText(BAD_CAST tmp1->value));
+		xmlAddChild(nc5,nc9);
+		}
+		_ltmp=_ltmp->next;
+		}*/
+	    
+	    }
+	  }
+	  if(e->defaults!=NULL && (tmp1=getMap(e->defaults->content,"value"))!=NULL){
+	    nc7 = xmlNewNode(ns_ows, BAD_CAST "DefaultValue");
+	    xmlAddChild(nc7,xmlNewText(BAD_CAST tmp1->value));
+	    xmlAddChild(nc5,nc7);
+	  }
+	}
+
+	map* metadata=e->metadata;
+	xmlNodePtr n=NULL;
+	int xlinkId=zooXmlAddNs(n,"http://www.w3.org/1999/xlink","xlink");
+	xmlNsPtr ns_xlink=usedNs[xlinkId];
+
+	while(metadata!=NULL){
+	  nc6=xmlNewNode(ns_ows, BAD_CAST "Metadata");
+	  xmlNewNsProp(nc6,ns_xlink,BAD_CAST metadata->name,BAD_CAST metadata->value);
+	  xmlAddChild(nc2,nc6);
+	  metadata=metadata->next;
+	}
+
+      }
+
+      _tmp=e->supported;
+      if(_tmp==NULL && datatype!=1)
+	_tmp=e->defaults;
+
+      int hasSupported=-1;
+
+      while(_tmp!=NULL){
+	if(hasSupported<0){
+	  if(datatype==0){
+	    if(vid==0)
+	      nc4 = xmlNewNode(NULL, BAD_CAST "Supported");
+	    nc5 = xmlNewNode(ns1, BAD_CAST "Format");
+	    if(vid==1){
+	      int oI=0;
+	      for(oI=0;oI<3;oI++)
+		if((tmp1=getMap(_tmp->content,orderedFields[oI]))!=NULL){
+		  xmlNewProp(nc5,BAD_CAST orderedFields[oI],BAD_CAST tmp1->value);
+		}
+	    }
+	  }
+	  else
+	    if(vid==0)
+	      nc5 = xmlNewNode(NULL, BAD_CAST "Supported");
+	  hasSupported=0;
+	}else
+	  if(datatype==0){
+	    nc5 = xmlNewNode(ns1, BAD_CAST "Format");
+	    if(vid==1){
+	      int oI=0;
+	      for(oI=0;oI<3;oI++)
+		if((tmp1=getMap(_tmp->content,orderedFields[oI]))!=NULL){
+		  xmlNewProp(nc5,BAD_CAST orderedFields[oI],BAD_CAST tmp1->value);
+		}
+	    }
+	  }
+	tmp1=_tmp->content;
+	int oI=0;
+	for(oI=0;oI<6;oI++)
+	  if((tmp1=getMap(_tmp->content,orderedFields[oI]))!=NULL){
+#ifdef DEBUG
+	    printf("DATATYPE SUPPORTED ? %s\n",tmp1->name);
+#endif
+	    if(strcmp(tmp1->name,"asReference")!=0 && 
+	       strcmp(tmp1->name,"value")!=0 && 
+	       strcmp(tmp1->name,"DataType")!=0 &&
+	       strcasecmp(tmp1->name,"extension")!=0){
+	      if(datatype!=1){
+		char *tmp2=zCapitalize1(tmp1->name);
+		nc6 = xmlNewNode(NULL, BAD_CAST tmp2);
+		free(tmp2);
+	      }
+	      else{
+		char *tmp2=zCapitalize(tmp1->name);
+		nc6 = xmlNewNode(ns_ows, BAD_CAST tmp2);
+		free(tmp2);
+	      }
+	      if(datatype==2){
+		char *tmpv,*tmps;
+		tmps=strtok_r(tmp1->value,",",&tmpv);
+		while(tmps){
+		  xmlAddChild(nc6,xmlNewText(BAD_CAST tmps));
+		  tmps=strtok_r(NULL,",",&tmpv);
+		  if(tmps){
+		    char *tmp2=zCapitalize1(tmp1->name);
+		    nc6 = xmlNewNode(NULL, BAD_CAST tmp2);
+		    free(tmp2);
+		  }
+		}
+	      }
+	      else{
+		xmlAddChild(nc6,xmlNewText(BAD_CAST tmp1->value));
+	      }
+	      if(vid==0 || oI>=3){
+		if(vid==0 || oI!=4)
+		  xmlAddChild(nc5,nc6);
+		else
+		  xmlFree(nc6);
+	      }
+	      else
+		xmlFree(nc6);
+	    }
+	    tmp1=tmp1->next;
+	  }
+	if(hasSupported<=0){
+	  if(datatype==0){
+	    if(vid==0){
+	      xmlAddChild(nc4,nc5);
+	      xmlAddChild(nc3,nc4);
+	    }
+	    else{
+	      xmlAddChild(nc3,nc5);
+	    }
+
+	  }else{
+	    if(datatype!=1)
+	      xmlAddChild(nc3,nc5);
+	  }
+	  hasSupported=1;
+	}
+	else
+	  if(datatype==0){
+	    if(vid==0){
+	      xmlAddChild(nc4,nc5);
+	      xmlAddChild(nc3,nc4);
+	    }
+	    else{
+	      xmlAddChild(nc3,nc5);
+	    }
+	  }
+	  else
+	    if(datatype!=1)
+	      xmlAddChild(nc3,nc5);
+
+	_tmp=_tmp->next;
+      }
+
+      if(hasSupported==0){
+	if(datatype==0 && vid!=0)
+	  xmlFreeNode(nc4);
+	xmlFreeNode(nc5);
+      }
+
+      _tmp=e->defaults;
+      if(datatype==1 && hasUOM1==true){
+	if(vid==0){
+	  xmlAddChild(nc4,nc5);
+	  xmlAddChild(nc3,nc4);
+	}
+	else{
+	  xmlAddChild(nc3,nc5);
+	}
+      }
+
+      if(vid==0 && _tmp!=NULL && (tmp1=getMap(_tmp->content,"value"))!=NULL){
+	nc7 = xmlNewNode(NULL, BAD_CAST "DefaultValue");
+	xmlAddChild(nc7,xmlNewText(BAD_CAST tmp1->value));
+	xmlAddChild(nc3,nc7);
+      }
+    
+      xmlAddChild(nc2,nc3);
+    }
+    
+    xmlAddChild(nc1,nc2);
+    
+    e=e->next;
+  }
+}
+
+/**
+ * Generate a wps:Execute XML document.
+ * 
+ * @param m the conf maps containing the main.cfg settings
+ * @param request the map representing the HTTP request
+ * @param pid the process identifier linked to a service
+ * @param serv the serv structure created from the zcfg file
+ * @param service the service name
+ * @param status the status returned by the service
+ * @param inputs the inputs provided
+ * @param outputs the outputs generated by the service
+ */
+void printProcessResponse(maps* m,map* request, int pid,service* serv,const char* service,int status,maps* inputs,maps* outputs){
+  xmlNsPtr ns,ns_ows,ns_xlink;
+  xmlNodePtr nr,n,nc,nc1=NULL,nc3;
+  xmlDocPtr doc;
+  time_t time1;  
+  time(&time1);
+  nr=NULL;
+
+  doc = xmlNewDoc(BAD_CAST "1.0");
+  map* version=getMapFromMaps(m,"main","rversion");
+  int vid=getVersionId(version->value);
+  n = printWPSHeader(doc,m,"Execute",root_nodes[vid][2],(version!=NULL?version->value:"1.0.0"),2);
+  int wpsId=zooXmlAddNs(NULL,schemas[vid][2],"wps");
+  ns=usedNs[wpsId];
+  int owsId=zooXmlAddNs(NULL,schemas[vid][1],"ows");
+  ns_ows=usedNs[owsId];
+  int xlinkId=zooXmlAddNs(NULL,"http://www.w3.org/1999/xlink","xlink");
+  ns_xlink=usedNs[xlinkId];
+  bool hasStoredExecuteResponse=false;
+  char stored_path[1024];
+  memset(stored_path,0,1024);
+    
+  if(vid==0){
+    char tmp[256];
+    char url[1024];
+    memset(tmp,0,256);
+    memset(url,0,1024);
+    maps* tmp_maps=getMaps(m,"main");
+    if(tmp_maps!=NULL){
+      map* tmpm1=getMap(tmp_maps->content,"serverAddress");
+      /**
+       * Check if the ZOO Service GetStatus is available in the local directory.
+       * If yes, then it uses a reference to an URL which the client can access
+       * to get information on the status of a running Service (using the 
+       * percentCompleted attribute). 
+       * Else fallback to the initial method using the xml file to write in ...
+       */
+      char ntmp[1024];
+#ifndef WIN32
+      getcwd(ntmp,1024);
+#else
+      _getcwd(ntmp,1024);
+#endif
+      struct stat myFileInfo;
+      int statRes;
+      char file_path[1024];
+      sprintf(file_path,"%s/GetStatus.zcfg",ntmp);
+      statRes=stat(file_path,&myFileInfo);
+      if(statRes==0){
+	char currentSid[128];
+	map* tmpm=getMap(tmp_maps->content,"rewriteUrl");
+	map *tmp_lenv=NULL;
+	tmp_lenv=getMapFromMaps(m,"lenv","usid");
+	if(tmp_lenv==NULL)
+	  sprintf(currentSid,"%i",pid);
+	else
+	  sprintf(currentSid,"%s",tmp_lenv->value);
+	if(tmpm==NULL || strcasecmp(tmpm->value,"false")==0){
+	  sprintf(url,"%s?request=Execute&service=WPS&version=1.0.0&Identifier=GetStatus&DataInputs=sid=%s&RawDataOutput=Result",tmpm1->value,currentSid);
+	}else{
+	  if(strlen(tmpm->value)>0)
+	    if(strcasecmp(tmpm->value,"true")!=0)
+	      sprintf(url,"%s/%s/GetStatus/%s",tmpm1->value,tmpm->value,currentSid);
+	    else
+	      sprintf(url,"%s/GetStatus/%s",tmpm1->value,currentSid);
+	  else
+	    sprintf(url,"%s/?request=Execute&service=WPS&version=1.0.0&Identifier=GetStatus&DataInputs=sid=%s&RawDataOutput=Result",tmpm1->value,currentSid);
+	}
+      }else{
+	int lpid;
+	map* tmpm2=getMapFromMaps(m,"lenv","usid");
+	map* tmpm3=getMap(tmp_maps->content,"tmpUrl");
+	if(tmpm1!=NULL && tmpm3!=NULL){
+	  if( strncasecmp( tmpm3->value, "http://", 7) == 0 ||
+	      strncasecmp( tmpm3->value, "https://", 8 ) == 0 ){
+	    sprintf(url,"%s/%s_%s.xml",tmpm3->value,service,tmpm2->value);
+	  }else
+	    sprintf(url,"%s/%s_%s.xml",tmpm1->value,service,tmpm2->value);
+	}
+      }
+      if(tmpm1!=NULL){
+	sprintf(tmp,"%s",tmpm1->value);
+      }
+      int lpid;
+      map* tmpm2=getMapFromMaps(m,"lenv","usid");
+      tmpm1=getMapFromMaps(m,"main","TmpPath");
+      sprintf(stored_path,"%s/%s_%s.xml",tmpm1->value,service,tmpm2->value);
+    }
+
+    xmlNewProp(n,BAD_CAST "serviceInstance",BAD_CAST tmp);
+    map* test=getMap(request,"storeExecuteResponse");
+    if(test!=NULL && strcasecmp(test->value,"true")==0){
+      xmlNewProp(n,BAD_CAST "statusLocation",BAD_CAST url);
+      hasStoredExecuteResponse=true;
+    }
+
+    nc = xmlNewNode(ns, BAD_CAST "Process");
+    map* tmp2=getMap(serv->content,"processVersion");
+    if(tmp2!=NULL)
+      xmlNewNsProp(nc,ns,BAD_CAST "processVersion",BAD_CAST tmp2->value);
+    else
+      xmlNewNsProp(nc,ns,BAD_CAST "processVersion",BAD_CAST "1");
+  
+    map* tmpI=getMapFromMaps(m,"lenv","oIdentifier");
+    printDescription(nc,ns_ows,tmpI->value,serv->content,0);
+
+    xmlAddChild(n,nc);
+
+    nc = xmlNewNode(ns, BAD_CAST "Status");
+    const struct tm *tm;
+    size_t len;
+    time_t now;
+    char *tmp1;
+    map *tmpStatus;
+  
+    now = time ( NULL );
+    tm = localtime ( &now );
+
+    tmp1 = (char*)malloc((TIME_SIZE+1)*sizeof(char));
+
+    len = strftime ( tmp1, TIME_SIZE, "%Y-%m-%dT%I:%M:%SZ", tm );
+
+    xmlNewProp(nc,BAD_CAST "creationTime",BAD_CAST tmp1);
+
+    char sMsg[2048];
+    switch(status){
+    case SERVICE_SUCCEEDED:
+      nc1 = xmlNewNode(ns, BAD_CAST "ProcessSucceeded");
+      sprintf(sMsg,_("The service \"%s\" ran successfully."),serv->name);
+      nc3=xmlNewText(BAD_CAST sMsg);
+      xmlAddChild(nc1,nc3);
+      break;
+    case SERVICE_STARTED:
+      nc1 = xmlNewNode(ns, BAD_CAST "ProcessStarted");
+      tmpStatus=getMapFromMaps(m,"lenv","status");
+      xmlNewProp(nc1,BAD_CAST "percentCompleted",BAD_CAST tmpStatus->value);
+      sprintf(sMsg,_("The ZOO service \"%s\" is currently running. Please reload this document to get the up-to-date status of the service."),serv->name);
+      nc3=xmlNewText(BAD_CAST sMsg);
+      xmlAddChild(nc1,nc3);
+      break;
+    case SERVICE_ACCEPTED:
+      nc1 = xmlNewNode(ns, BAD_CAST "ProcessAccepted");
+      sprintf(sMsg,_("The service \"%s\" was accepted by the ZOO-Kernel and is running as a background task. Please access the URL in the statusLocation attribute provided in this document to get the up-to-date status and results."),serv->name);
+      nc3=xmlNewText(BAD_CAST sMsg);
+      xmlAddChild(nc1,nc3);
+      break;
+    case SERVICE_FAILED:
+      nc1 = xmlNewNode(ns, BAD_CAST "ProcessFailed");
+      map *errorMap;
+      map *te;
+      te=getMapFromMaps(m,"lenv","code");
+      if(te!=NULL)
+	errorMap=createMap("code",te->value);
+      else
+	errorMap=createMap("code","NoApplicableCode");
+      te=getMapFromMaps(m,"lenv","message");
+      if(te!=NULL)
+	addToMap(errorMap,"text",_ss(te->value));
+      else
+	addToMap(errorMap,"text",_("No more information available"));
+      nc3=createExceptionReportNode(m,errorMap,0);
+      freeMap(&errorMap);
+      free(errorMap);
+      xmlAddChild(nc1,nc3);
+      break;
+    default :
+      printf(_("error code not know : %i\n"),status);
+      //exit(1);
+      break;
+    }
+    xmlAddChild(nc,nc1);
+    xmlAddChild(n,nc);
+    free(tmp1);
+
+#ifdef DEBUG
+    fprintf(stderr,"printProcessResponse %d\n",__LINE__);
+#endif
+
+    map* lineage=getMap(request,"lineage");
+    if(lineage!=NULL && strcasecmp(lineage->value,"true")==0){
+      nc = xmlNewNode(ns, BAD_CAST "DataInputs");
+      maps* mcursor=inputs;
+      elements* scursor=NULL;
+      while(mcursor!=NULL /*&& scursor!=NULL*/){
+	scursor=getElements(serv->inputs,mcursor->name);
+	printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Input",vid);
+	mcursor=mcursor->next;
+      }
+      xmlAddChild(n,nc);
+
+      nc = xmlNewNode(ns, BAD_CAST "OutputDefinitions");
+      mcursor=outputs;
+      scursor=NULL;
+      while(mcursor!=NULL){
+	scursor=getElements(serv->outputs,mcursor->name);
+	printOutputDefinitions(doc,nc,ns,ns_ows,scursor,mcursor,"Output");
+	mcursor=mcursor->next;
+      }
+      xmlAddChild(n,nc);
+    }
+  }
+
+  /**
+   * Display the process output only when requested !
+   */
+  if(status==SERVICE_SUCCEEDED){
+    if(vid==0){
+      nc = xmlNewNode(ns, BAD_CAST "ProcessOutputs");
+    }
+    maps* mcursor=outputs;
+    elements* scursor=serv->outputs;
+    map* testResponse=getMap(request,"RawDataOutput");
+    if(testResponse==NULL)
+      testResponse=getMap(request,"ResponseDocument");
+    while(mcursor!=NULL){
+      map* tmp0=getMap(mcursor->content,"inRequest");
+      scursor=getElements(serv->outputs,mcursor->name);
+      if(scursor!=NULL){
+	if(testResponse==NULL || tmp0==NULL){
+	  if(vid==0)
+	    printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Output",vid);
+	  else
+	    printIOType(doc,n,ns,ns_ows,ns_xlink,scursor,mcursor,"Output",vid);
+	}
+	else
+
+	  if(tmp0!=NULL && strncmp(tmp0->value,"true",4)==0){
+	    if(vid==0)
+	      printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Output",vid);
+	    else
+	      printIOType(doc,n,ns,ns_ows,ns_xlink,scursor,mcursor,"Output",vid);
+	  }
+      }else
+	/**
+	 * In case there was no definition found in the ZCFG file but 
+	 * present in the service code
+	 */
+	if(vid==0)
+	  printIOType(doc,nc,ns,ns_ows,ns_xlink,scursor,mcursor,"Output",vid);
+	else
+	  printIOType(doc,n,ns,ns_ows,ns_xlink,scursor,mcursor,"Output",vid);
+      mcursor=mcursor->next;
+    }
+    if(vid==0)
+      xmlAddChild(n,nc);
+  }
+  
+  if(vid==0 && 
+     hasStoredExecuteResponse==true 
+     && status!=SERVICE_STARTED 
+#ifndef WIN32
+     && status!=SERVICE_ACCEPTED
+#endif
+     ){
+#ifndef RELY_ON_DB
+    semid lid=acquireLock(m);//,1);
+    if(lid<0){
+      /* If the lock failed */
+      errorException(m,_("Lock failed."),"InternalError",NULL);
+      xmlFreeDoc(doc);
+      xmlCleanupParser();
+      zooXmlCleanupNs();
+      return;
+    }
+    else{
+#endif
+      /* We need to write the ExecuteResponse Document somewhere */
+      FILE* output=fopen(stored_path,"w");
+      if(output==NULL){
+	/* If the file cannot be created return an ExceptionReport */
+	char tmpMsg[1024];
+	sprintf(tmpMsg,_("Unable to create the file \"%s\" for storing the ExecuteResponse."),stored_path);
+
+	errorException(m,tmpMsg,"InternalError",NULL);
+	xmlFreeDoc(doc);
+	xmlCleanupParser();
+	zooXmlCleanupNs();
+#ifndef RELY_ON_DB
+	unlockShm(lid);
+#endif
+	return;
+      }
+      xmlChar *xmlbuff;
+      int buffersize;
+      xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, "UTF-8", 1);
+      fwrite(xmlbuff,1,xmlStrlen(xmlbuff)*sizeof(char),output);
+      xmlFree(xmlbuff);
+      fclose(output);
+#ifndef RELY_ON_DB
+#ifdef DEBUG
+      fprintf(stderr,"UNLOCK %s %d !\n",__FILE__,__LINE__);
+#endif
+      unlockShm(lid);
+      map* v=getMapFromMaps(m,"lenv","sid");
+      // Remove the lock when running as a normal task
+      if(getpid()==atoi(v->value)){
+	removeShmLock (m, 1);
+      }
+    }
+#endif
+  }
+  printDocument(m,doc,pid);
+
+  xmlCleanupParser();
+  zooXmlCleanupNs();
+}
+
+/**
+ * Print a XML document.
+ * 
+ * @param m the conf maps containing the main.cfg settings
+ * @param doc the XML document
+ * @param pid the process identifier linked to a service
+ */
+void printDocument(maps* m, xmlDocPtr doc,int pid){
+  char *encoding=getEncoding(m);
+  if(pid==getpid()){
+    printHeaders(m);
+    printf("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding);
+  }
+  fflush(stdout);
+  xmlChar *xmlbuff;
+  int buffersize;
+  /*
+   * Dump the document to a buffer and print it on stdout
+   * for demonstration purposes.
+   */
+  xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);
+  printf("%s",xmlbuff);
+  fflush(stdout);
+  /*
+   * Free associated memory.
+   */
+  xmlFree(xmlbuff);
+  xmlFreeDoc(doc);
+  xmlCleanupParser();
+  zooXmlCleanupNs();
+}
+
+/**
+ * Print a XML document.
+ * 
+ * @param doc the XML document (unused)
+ * @param nc the XML node to add the output definition
+ * @param ns_wps the wps XML namespace
+ * @param ns_ows the ows XML namespace
+ * @param e the output elements 
+ * @param m the conf maps containing the main.cfg settings
+ * @param type the type (unused)
+ */
+void printOutputDefinitions(xmlDocPtr doc,xmlNodePtr nc,xmlNsPtr ns_wps,xmlNsPtr ns_ows,elements* e,maps* m,const char* type){
+  xmlNodePtr nc1;
+  nc1=xmlNewNode(ns_wps, BAD_CAST type);
+  map *tmp=NULL;  
+  if(e!=NULL && e->defaults!=NULL)
+    tmp=e->defaults->content;
+  else{
+    /*
+    dumpElements(e);
+    */
+    return;
+  }
+  while(tmp!=NULL){
+    if(strncasecmp(tmp->name,"MIMETYPE",strlen(tmp->name))==0
+       || strncasecmp(tmp->name,"ENCODING",strlen(tmp->name))==0
+       || strncasecmp(tmp->name,"SCHEMA",strlen(tmp->name))==0
+       || strncasecmp(tmp->name,"UOM",strlen(tmp->name))==0)
+    xmlNewProp(nc1,BAD_CAST tmp->name,BAD_CAST tmp->value);
+    tmp=tmp->next;
+  }
+  tmp=getMap(e->defaults->content,"asReference");
+  if(tmp==NULL)
+    xmlNewProp(nc1,BAD_CAST "asReference",BAD_CAST "false");
+
+  tmp=e->content;
+
+  printDescription(nc1,ns_ows,m->name,e->content,0);
+
+  xmlAddChild(nc,nc1);
+
+}
+
+/**
+ * Generate XML nodes describing inputs or outputs metadata.
+ * 
+ * @param doc the XML document 
+ * @param nc the XML node to add the definition
+ * @param ns_wps the wps namespace
+ * @param ns_ows the ows namespace
+ * @param ns_xlink the xlink namespace
+ * @param e the output elements 
+ * @param m the conf maps containing the main.cfg settings
+ * @param type the type
+ */
+void printIOType(xmlDocPtr doc,xmlNodePtr nc,xmlNsPtr ns_wps,xmlNsPtr ns_ows,xmlNsPtr ns_xlink,elements* e,maps* m,const char* type,int vid){
+
+  xmlNodePtr nc1,nc2,nc3;
+  nc1=xmlNewNode(ns_wps, BAD_CAST type);
+  map *tmp=NULL;
+  if(e!=NULL)
+    tmp=e->content;
+  else
+    tmp=m->content;
+
+  if(vid==0){
+    nc2=xmlNewNode(ns_ows, BAD_CAST "Identifier");
+    if(e!=NULL)
+      nc3=xmlNewText(BAD_CAST e->name);
+    else
+      nc3=xmlNewText(BAD_CAST m->name);
+    
+    xmlAddChild(nc2,nc3);
+    xmlAddChild(nc1,nc2);
+  
+    xmlAddChild(nc,nc1);
+
+    if(e!=NULL)
+      tmp=getMap(e->content,"Title");
+    else
+      tmp=getMap(m->content,"Title");
+    
+    if(tmp!=NULL){
+      nc2=xmlNewNode(ns_ows, BAD_CAST tmp->name);
+      nc3=xmlNewText(BAD_CAST _ss(tmp->value));
+      xmlAddChild(nc2,nc3);  
+      xmlAddChild(nc1,nc2);
+    }
+
+    if(e!=NULL)
+      tmp=getMap(e->content,"Abstract");
+    else
+      tmp=getMap(m->content,"Abstract");
+
+    if(tmp!=NULL){
+      nc2=xmlNewNode(ns_ows, BAD_CAST tmp->name);
+      nc3=xmlNewText(BAD_CAST _ss(tmp->value));
+      xmlAddChild(nc2,nc3);  
+      xmlAddChild(nc1,nc2);
+      xmlAddChild(nc,nc1);
+    }
+  }else{
+    xmlNewProp(nc1,BAD_CAST "id",BAD_CAST (e!=NULL?e->name:m->name));
+  }
+
+  /**
+   * IO type Reference or full Data ?
+   */
+  map *tmpMap=getMap(m->content,"Reference");
+  if(tmpMap==NULL){
+    nc2=xmlNewNode(ns_wps, BAD_CAST "Data");
+    if(e!=NULL){
+      if(strncasecmp(e->format,"LiteralOutput",strlen(e->format))==0)
+	nc3=xmlNewNode(ns_wps, BAD_CAST "LiteralData");
+      else
+        if(strncasecmp(e->format,"ComplexOutput",strlen(e->format))==0)
+	  nc3=xmlNewNode(ns_wps, BAD_CAST "ComplexData");
+	else if(strncasecmp(e->format,"BoundingBoxOutput",strlen(e->format))==0)
+	  nc3=xmlNewNode(ns_wps, BAD_CAST "BoundingBoxData");
+	else
+	  nc3=xmlNewNode(ns_wps, BAD_CAST e->format);
+    }
+    else {
+      map* tmpV=getMapFromMaps(m,"format","value");
+      if(tmpV!=NULL)
+	nc3=xmlNewNode(ns_wps, BAD_CAST tmpV->value);
+      else
+	nc3=xmlNewNode(ns_wps, BAD_CAST "LiteralData");
+    } 
+    tmp=m->content;
+
+    while(tmp!=NULL){
+      if(strcasecmp(tmp->name,"mimeType")==0 ||
+	 strcasecmp(tmp->name,"encoding")==0 ||
+	 strcasecmp(tmp->name,"schema")==0 ||
+	 strcasecmp(tmp->name,"datatype")==0 ||
+	 strcasecmp(tmp->name,"uom")==0) {
+	
+	if(vid==0)
+	  xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST tmp->value);
+	else{
+	  if(strcasecmp(tmp->name,"datatype")==0)
+	    xmlNewProp(nc2,BAD_CAST "mimeType",BAD_CAST "text/plain");
+	  else
+	    if(strcasecmp(tmp->name,"uom")!=0)
+	      xmlNewProp(nc2,BAD_CAST tmp->name,BAD_CAST tmp->value);
+	}
+      }
+      if(vid==0)
+	xmlAddChild(nc2,nc3);
+      tmp=tmp->next;
+    }
+    if(e!=NULL && e->format!=NULL && strcasecmp(e->format,"BoundingBoxData")==0) {
+      map* bb=getMap(m->content,"value");
+      if(bb!=NULL) {
+	map* tmpRes=parseBoundingBox(bb->value);
+	printBoundingBox(ns_ows,nc3,tmpRes);
+	freeMap(&tmpRes);
+	free(tmpRes);
+      }
+    }
+    else {
+      if(e!=NULL)
+	tmp=getMap(e->defaults->content,"mimeType");
+      else
+	tmp=NULL;
+	
+      map* tmp1=getMap(m->content,"encoding");
+      map* tmp2=getMap(m->content,"mimeType");
+      map* tmp3=getMap(m->content,"value");
+      int hasValue=1;
+      if(tmp3==NULL){
+	tmp3=createMap("value","");
+	hasValue=-1;
+      }
+
+      if( ( tmp1 != NULL && strncmp(tmp1->value,"base64",6) == 0 )     // if encoding is base64
+	  || 	                                                       // or if 
+	  ( tmp2 != NULL && ( strstr(tmp2->value,"text") == NULL       //  mime type is not text 
+			      &&                                       //  nor 
+			      strstr(tmp2->value,"xml") == NULL        //  xml
+			      &&                                       // nor
+			      strstr(tmp2->value,"javascript") == NULL // javascript
+			      &&
+			      strstr(tmp2->value,"json") == NULL
+			      &&
+			      strstr(tmp2->value,"ecmascript") == NULL
+			      &&
+			      // include for backwards compatibility,
+			      // although correct mime type is ...kml+xml:
+			      strstr(tmp2->value,"google-earth.kml") == NULL							)
+	    )
+	  ) { 	                                                 // then	
+	map* rs=getMap(m->content,"size");                       // obtain size
+	bool isSized=true;
+	if(rs==NULL){
+	  char tmp1[1024];
+	  sprintf(tmp1,"%ld",strlen(tmp3->value));
+	  rs=createMap("size",tmp1);
+	  isSized=false;
+	}
+	 
+	xmlAddChild((vid==0?nc3:nc2),xmlNewText(BAD_CAST base64(tmp3->value, atoi(rs->value))));  // base 64 encode in XML
+		
+	if(tmp1==NULL || (tmp1!=NULL && strncmp(tmp1->value,"base64",6)!=0)) {
+	  xmlAttrPtr ap = xmlHasProp((vid==0?nc3:nc2), BAD_CAST "encoding");
+	  if (ap != NULL) {
+	    xmlRemoveProp(ap);
+	  }			
+	  xmlNewProp((vid==0?nc3:nc2),BAD_CAST "encoding",BAD_CAST "base64");
+	}
+		
+	if(!isSized){
+	  freeMap(&rs);
+	  free(rs);
+	}
+      }
+      else if (tmp2!=NULL) {                                 // else (text-based format) 
+	if(strstr(tmp2->value, "javascript") != NULL ||      //    if javascript put code in CDATA block 
+	   strstr(tmp2->value, "json") != NULL ||            //    (will not be parsed by XML reader) 
+	   strstr(tmp2->value, "ecmascript") != NULL
+	   ) {
+	  xmlAddChild((vid==0?nc3:nc2),xmlNewCDataBlock(doc,BAD_CAST tmp3->value,strlen(tmp3->value)));
+	}   
+	else {                                                     // else
+	  if (strstr(tmp2->value, "xml") != NULL ||                 // if XML-based format
+	      // include for backwards compatibility,
+	      // although correct mime type is ...kml+xml:		   
+	      strstr(tmp2->value, "google-earth.kml") != NULL
+	      ) { 
+			  
+	    int li=zooXmlAddDoc(tmp3->value);
+	    xmlDocPtr doc = iDocs[li];
+	    xmlNodePtr ir = xmlDocGetRootElement(doc);
+	    xmlAddChild((vid==0?nc3:nc2),ir);
+	  }
+	  else                                                     // else	
+	    xmlAddChild((vid==0?nc3:nc2),xmlNewText(BAD_CAST tmp3->value));    //   add text node
+	}
+	xmlAddChild(nc2,nc3);
+      }
+      else {
+	xmlAddChild((vid==0?nc3:nc2),xmlNewText(BAD_CAST tmp3->value));
+      }
+	  
+      if(hasValue<0) {
+	freeMap(&tmp3);
+	free(tmp3);
+      }
+    }
+  }
+  else { // Reference
+    tmpMap=getMap(m->content,"Reference");
+    nc3=nc2=xmlNewNode(ns_wps, BAD_CAST "Reference");
+    if(strcasecmp(type,"Output")==0)
+      xmlNewProp(nc3,BAD_CAST "href",BAD_CAST tmpMap->value);
+    else
+      xmlNewNsProp(nc3,ns_xlink,BAD_CAST "href",BAD_CAST tmpMap->value);
+    
+    tmp=m->content;
+    while(tmp!=NULL) {
+      if(strcasecmp(tmp->name,"mimeType")==0 ||
+	 strcasecmp(tmp->name,"encoding")==0 ||
+	 strcasecmp(tmp->name,"schema")==0 ||
+	 strcasecmp(tmp->name,"datatype")==0 ||
+	 strcasecmp(tmp->name,"uom")==0){
+
+	if(strcasecmp(tmp->name,"datatype")==0)
+	  xmlNewProp(nc3,BAD_CAST "mimeType",BAD_CAST "text/plain");
+	else
+	  xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST tmp->value);
+      }
+      tmp=tmp->next;
+      xmlAddChild(nc2,nc3);
+    }
+  }
+  xmlAddChild(nc1,nc2);
+  xmlAddChild(nc,nc1);
+}
+
+/**
+ * Create XML node with basic ows metadata informations (Identifier,Title,Abstract)
+ *
+ * @param root the root XML node to add the description
+ * @param ns_ows the ows XML namespace
+ * @param identifier the identifier to use
+ * @param amap the map containing the ows metadata informations 
+ */
+void printDescription(xmlNodePtr root,xmlNsPtr ns_ows,const char* identifier,map* amap,int vid=0){
+  xmlNodePtr nc2;
+  if(vid==0){
+    nc2 = xmlNewNode(ns_ows, BAD_CAST "Identifier");
+    xmlAddChild(nc2,xmlNewText(BAD_CAST identifier));
+    xmlAddChild(root,nc2);
+  }
+  map* tmp=amap;
+  const char *tmp2[2];
+  tmp2[0]="Title";
+  tmp2[1]="Abstract";
+  int j=0;
+  for(j=0;j<2;j++){
+    map* tmp1=getMap(tmp,tmp2[j]);
+    if(tmp1!=NULL){
+      nc2 = xmlNewNode(ns_ows, BAD_CAST tmp2[j]);
+      xmlAddChild(nc2,xmlNewText(BAD_CAST _ss(tmp1->value)));
+      xmlAddChild(root,nc2);
+    }
+  }
+  if(vid==1){
+    nc2 = xmlNewNode(ns_ows, BAD_CAST "Identifier");
+    xmlAddChild(nc2,xmlNewText(BAD_CAST identifier));
+    xmlAddChild(root,nc2);
+  }
+}
+
+/**
+ * Print an OWS ExceptionReport Document and HTTP headers (when required) 
+ * depending on the code.
+ * Set hasPrinted value to true in the [lenv] section.
+ * 
+ * @param m the maps containing the settings of the main.cfg file
+ * @param s the map containing the text,code,locator keys
+ */
+void printExceptionReportResponse(maps* m,map* s){
+  if(getMapFromMaps(m,"lenv","hasPrinted")!=NULL)
+    return;
+  int buffersize;
+  xmlDocPtr doc;
+  xmlChar *xmlbuff;
+  xmlNodePtr n;
+
+  zooXmlCleanupNs();
+  doc = xmlNewDoc(BAD_CAST "1.0");
+  maps* tmpMap=getMaps(m,"main");
+  char *encoding=getEncoding(tmpMap);
+  const char *exceptionCode;
+  
+  map* tmp=getMap(s,"code");
+  if(tmp!=NULL){
+    if(strcmp(tmp->value,"OperationNotSupported")==0 ||
+       strcmp(tmp->value,"NoApplicableCode")==0)
+      exceptionCode="501 Not Implemented";
+    else
+      if(strcmp(tmp->value,"MissingParameterValue")==0 ||
+	 strcmp(tmp->value,"InvalidUpdateSequence")==0 ||
+	 strcmp(tmp->value,"OptionNotSupported")==0 ||
+	 strcmp(tmp->value,"VersionNegotiationFailed")==0 ||
+	 strcmp(tmp->value,"InvalidParameterValue")==0)
+	exceptionCode="400 Bad request";
+      else
+	exceptionCode="501 Internal Server Error";
+  }
+  else
+    exceptionCode="501 Internal Server Error";
+
+  if(m!=NULL){
+    map *tmpSid=getMapFromMaps(m,"lenv","sid");
+    if(tmpSid!=NULL){
+      if( getpid()==atoi(tmpSid->value) ){
+	printHeaders(m);
+	printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode);
+      }
+    }
+    else{
+      printHeaders(m);
+      printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode);
+    }
+  }else{
+    printf("Content-Type: text/xml; charset=%s\r\nStatus: %s\r\n\r\n",encoding,exceptionCode);
+  }
+  n=createExceptionReportNode(m,s,1);
+  xmlDocSetRootElement(doc, n);
+  xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);
+  printf("%s",xmlbuff);
+  fflush(stdout);
+  xmlFreeDoc(doc);
+  xmlFree(xmlbuff);
+  xmlCleanupParser();
+  zooXmlCleanupNs();
+  if(m!=NULL)
+    setMapInMaps(m,"lenv","hasPrinted","true");
+}
+
+/**
+ * Create an OWS ExceptionReport Node.
+ * 
+ * @param m the conf maps
+ * @param s the map containing the text,code,locator keys
+ * @param use_ns (0/1) choose if you want to generate an ExceptionReport or 
+ *  ows:ExceptionReport node respectively
+ * @return the ExceptionReport/ows:ExceptionReport node
+ */
+xmlNodePtr createExceptionReportNode(maps* m,map* s,int use_ns){
+  
+  xmlNsPtr ns,ns_xsi;
+  xmlNodePtr n,nc,nc1;
+
+  int nsid=zooXmlAddNs(NULL,"http://www.opengis.net/ows","ows");
+  ns=usedNs[nsid];
+  if(use_ns==0){
+    ns=NULL;
+  }
+  n = xmlNewNode(ns, BAD_CAST "ExceptionReport");
+  map* version=getMapFromMaps(m,"main","rversion");
+  int vid=getVersionId(version->value);
+  if(vid<0)
+    vid=0;
+  if(use_ns==1){
+    xmlNewNs(n,BAD_CAST schemas[vid][1],BAD_CAST"ows");
+    int xsiId=zooXmlAddNs(n,"http://www.w3.org/2001/XMLSchema-instance","xsi");
+    ns_xsi=usedNs[xsiId];
+    char tmp[1024];
+    sprintf(tmp,"%s %s",schemas[vid][1],schemas[vid][5]);
+    xmlNewNsProp(n,ns_xsi,BAD_CAST "schemaLocation",BAD_CAST tmp);
+  }
+
+
+  addLangAttr(n,m);
+  xmlNewProp(n,BAD_CAST "version",BAD_CAST schemas[vid][6]);
+  
+  int length=1;
+  int cnt=0;
+  map* len=getMap(s,"length");
+  if(len!=NULL)
+    length=atoi(len->value);
+  for(cnt=0;cnt<length;cnt++){
+    nc = xmlNewNode(ns, BAD_CAST "Exception");
+    
+    map* tmp=getMapArray(s,"code",cnt);
+    if(tmp==NULL)
+      tmp=getMap(s,"code");
+    if(tmp!=NULL)
+      xmlNewProp(nc,BAD_CAST "exceptionCode",BAD_CAST tmp->value);
+    else
+      xmlNewProp(nc,BAD_CAST "exceptionCode",BAD_CAST "NoApplicableCode");
+    
+    tmp=getMapArray(s,"locator",cnt);
+    if(tmp==NULL)
+      tmp=getMap(s,"locator");
+    if(tmp!=NULL && strcasecmp(tmp->value,"NULL")!=0)
+      xmlNewProp(nc,BAD_CAST "locator",BAD_CAST tmp->value);
+
+    tmp=getMapArray(s,"text",cnt);
+    nc1 = xmlNewNode(ns, BAD_CAST "ExceptionText");
+    if(tmp!=NULL){
+      xmlNodePtr txt=xmlNewText(BAD_CAST tmp->value);
+      xmlAddChild(nc1,txt);
+    }
+    else{
+      xmlNodeSetContent(nc1, BAD_CAST _("No debug message available"));
+    }
+    xmlAddChild(nc,nc1);
+    xmlAddChild(n,nc);
+  }
+  return n;
+}
+
+/**
+ * Print an OWS ExceptionReport.
+ * 
+ * @param m the conf maps
+ * @param message the error message 
+ * @param errorcode the error code
+ * @param locator the potential locator
+ */
+int errorException(maps *m, const char *message, const char *errorcode, const char *locator) 
+{
+  map* errormap = createMap("text", message);
+  addToMap(errormap,"code", errorcode);
+  if(locator!=NULL)
+    addToMap(errormap,"locator", locator);
+  else
+    addToMap(errormap,"locator", "NULL");
+  printExceptionReportResponse(m,errormap);
+  freeMap(&errormap);
+  free(errormap);
+  return -1;
+}
+
+/**
+ * Generate the output response (RawDataOutput or ResponseDocument)
+ *
+ * @param s the service structure containing the metadata informations
+ * @param request_inputs the inputs provided to the service for execution
+ * @param request_outputs the outputs updated by the service execution
+ * @param request_inputs1 the map containing the HTTP request
+ * @param cpid the process identifier attached to a service execution
+ * @param m the conf maps containing the main.cfg settings
+ * @param res the value returned by the service execution
+ */
+void outputResponse(service* s,maps* request_inputs,maps* request_outputs,
+		    map* request_inputs1,int cpid,maps* m,int res){
+#ifdef DEBUG
+  dumpMaps(request_inputs);
+  dumpMaps(request_outputs);
+  fprintf(stderr,"printProcessResponse\n");
+#endif
+  map* toto=getMap(request_inputs1,"RawDataOutput");
+  int asRaw=0;
+  if(toto!=NULL)
+    asRaw=1;
+  map* version=getMapFromMaps(m,"main","rversion");
+  int vid=getVersionId(version->value);
+
+  maps* tmpSess=getMaps(m,"senv");
+  if(tmpSess!=NULL){
+    map *_tmp=getMapFromMaps(m,"lenv","cookie");
+    char* sessId=NULL;
+    if(_tmp!=NULL){
+      printf("Set-Cookie: %s; HttpOnly\r\n",_tmp->value);
+      printf("P3P: CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"\r\n");
+      char session_file_path[100];
+      char *tmp1=strtok(_tmp->value,";");
+      if(tmp1!=NULL)
+	sprintf(session_file_path,"%s",strstr(tmp1,"=")+1);
+      else
+	sprintf(session_file_path,"%s",strstr(_tmp->value,"=")+1);
+      sessId=strdup(session_file_path);
+    }else{
+      maps* t=getMaps(m,"senv");
+      map*p=t->content;
+      while(p!=NULL){
+	if(strstr(p->name,"ID")!=NULL){
+	  sessId=strdup(p->value);
+	  break;
+	}
+	p=p->next;
+      }
+    }
+    char session_file_path[1024];
+    map *tmpPath=getMapFromMaps(m,"main","sessPath");
+    if(tmpPath==NULL)
+      tmpPath=getMapFromMaps(m,"main","tmpPath");
+    sprintf(session_file_path,"%s/sess_%s.cfg",tmpPath->value,sessId);
+    FILE* teste=fopen(session_file_path,"w");
+    if(teste==NULL){
+      char tmpMsg[1024];
+      sprintf(tmpMsg,_("Unable to create the file \"%s\" for storing the session maps."),session_file_path);
+      errorException(m,tmpMsg,"InternalError",NULL);
+
+      return;
+    }
+    else{
+      fclose(teste);
+      dumpMapsToFile(tmpSess,session_file_path,1);
+    }
+  }
+  
+  if(res==SERVICE_FAILED){
+    map *lenv;
+    lenv=getMapFromMaps(m,"lenv","message");
+    char *tmp0;
+    if(lenv!=NULL){
+      tmp0=(char*)malloc((strlen(lenv->value)+strlen(_("Unable to run the Service. The message returned back by the Service was the following: "))+1)*sizeof(char));
+      sprintf(tmp0,_("Unable to run the Service. The message returned back by the Service was the following: %s"),lenv->value);
+    }
+    else{
+      tmp0=(char*)malloc((strlen(_("Unable to run the Service. No more information was returned back by the Service."))+1)*sizeof(char));
+      sprintf(tmp0,"%s",_("Unable to run the Service. No more information was returned back by the Service."));
+    }
+    errorException(m,tmp0,"InternalError",NULL);
+    free(tmp0);
+    return;
+  }
+
+  if(res==SERVICE_ACCEPTED && vid==1){
+    map* statusInfo=createMap("Status","Accepted");
+    map *usid=getMapFromMaps(m,"lenv","usid");
+    addToMap(statusInfo,"JobID",usid->value);
+    printStatusInfo(m,statusInfo,"Execute");
+    freeMap(&statusInfo);
+    free(statusInfo);
+    return;
+  }
+
+  map *tmp1=getMapFromMaps(m,"main","tmpPath");
+  if(asRaw==0){
+#ifdef DEBUG
+    fprintf(stderr,"REQUEST_OUTPUTS FINAL\n");
+    dumpMaps(request_outputs);
+#endif
+    maps* tmpI=request_outputs;
+    map* usid=getMapFromMaps(m,"lenv","usid");
+    int itn=0;
+    while(tmpI!=NULL){
+#ifdef USE_MS
+      map* testMap=getMap(tmpI->content,"useMapserver");	
+#endif
+      map *gfile=getMap(tmpI->content,"generated_file");
+      char *file_name;
+      if(gfile!=NULL){
+	gfile=getMap(tmpI->content,"expected_generated_file");
+	if(gfile==NULL){
+	  gfile=getMap(tmpI->content,"generated_file");
+	}
+	readGeneratedFile(m,tmpI->content,gfile->value);	    
+	file_name=(char*)malloc((strlen(gfile->value)+strlen(tmp1->value)+1)*sizeof(char));
+	for(int i=0;i<strlen(gfile->value);i++)
+	  file_name[i]=gfile->value[i+strlen(tmp1->value)];
+      }
+
+      toto=getMap(tmpI->content,"asReference");
+#ifdef USE_MS
+      if(toto!=NULL && strcasecmp(toto->value,"true")==0 && testMap==NULL)
+#else
+      if(toto!=NULL && strcasecmp(toto->value,"true")==0)
+#endif
+	{
+	  elements* in=getElements(s->outputs,tmpI->name);
+	  char *format=NULL;
+	  if(in!=NULL && in->format!=NULL){
+	    format=zStrdup(in->format);
+	  }else
+	    format=zStrdup("LiteralData");
+	  if(strcasecmp(format,"BoundingBoxData")==0){
+	    addToMap(tmpI->content,"extension","xml");
+	    addToMap(tmpI->content,"mimeType","text/xml");
+	    addToMap(tmpI->content,"encoding","UTF-8");
+	    addToMap(tmpI->content,"schema","http://schemas.opengis.net/ows/1.1.0/owsCommon.xsd");
+	  }
+
+	  if(gfile==NULL) {
+	    map *ext=getMap(tmpI->content,"extension");
+	    char *file_path;
+	    char file_ext[32];
+
+	    if( ext != NULL && ext->value != NULL) {
+	      strncpy(file_ext, ext->value, 32);
+	    }
+	    else {
+	      // Obtain default file extension (see mimetypes.h).	      
+	      // If the MIME type is not recognized, txt is used as the default extension
+	      map* mtype=getMap(tmpI->content,"mimeType");
+	      getFileExtension(mtype != NULL ? mtype->value : NULL, file_ext, 32);
+	    }
+
+	    file_name=(char*)malloc((strlen(s->name)+strlen(usid->value)+strlen(file_ext)+strlen(tmpI->name)+45)*sizeof(char));
+	    sprintf(file_name,"%s_%s_%s_%d.%s",s->name,tmpI->name,usid->value,itn,file_ext);
+	    itn++;
+	    file_path=(char*)malloc((strlen(tmp1->value)+strlen(file_name)+2)*sizeof(char));
+	    sprintf(file_path,"%s/%s",tmp1->value,file_name);
+
+	    FILE *ofile=fopen(file_path,"wb");
+	    if(ofile==NULL){
+	      char tmpMsg[1024];
+	      sprintf(tmpMsg,_("Unable to create the file \"%s\" for storing the %s final result."),file_name,tmpI->name);
+	      errorException(m,tmpMsg,"InternalError",NULL);
+	      free(file_name);
+	      free(file_path);
+	      return;
+	    }
+	    free(file_path);
+
+	    toto=getMap(tmpI->content,"value");
+	    if(strcasecmp(format,"BoundingBoxData")!=0){
+	      map* size=getMap(tmpI->content,"size");
+	      if(size!=NULL && toto!=NULL)
+		fwrite(toto->value,1,(atoi(size->value))*sizeof(char),ofile);
+	      else
+		if(toto!=NULL && toto->value!=NULL)
+		  fwrite(toto->value,1,strlen(toto->value)*sizeof(char),ofile);
+	    }else{
+	      printBoundingBoxDocument(m,tmpI,ofile);
+	    }
+	    fclose(ofile);
+
+	  }
+
+	  map *tmp2=getMapFromMaps(m,"main","tmpUrl");
+	  map *tmp3=getMapFromMaps(m,"main","serverAddress");
+	  char *file_url;
+	  if(strncasecmp(tmp2->value,"http://",7)==0 ||
+	     strncasecmp(tmp2->value,"https://",8)==0){
+	    file_url=(char*)malloc((strlen(tmp2->value)+strlen(file_name)+2)*sizeof(char));
+	    sprintf(file_url,"%s/%s",tmp2->value,file_name);
+	  }else{
+	    file_url=(char*)malloc((strlen(tmp3->value)+strlen(tmp2->value)+strlen(file_name)+3)*sizeof(char));
+	    sprintf(file_url,"%s/%s/%s",tmp3->value,tmp2->value,file_name);
+	  }
+
+	  addToMap(tmpI->content,"Reference",file_url);
+	  free(format);
+	  free(file_name);
+	  free(file_url);
+	  
+	}
+#ifdef USE_MS
+      else{
+	if(testMap!=NULL){
+	  setReferenceUrl(m,tmpI);
+	}
+      }
+#endif
+      tmpI=tmpI->next;
+    }
+#ifdef DEBUG
+    fprintf(stderr,"SERVICE : %s\n",s->name);
+    dumpMaps(m);
+#endif
+    printProcessResponse(m,request_inputs1,cpid,
+			 s, s->name,res,  // replace serviceProvider with serviceName in stored response file name
+			 request_inputs,
+			 request_outputs);
+  }
+  else{
+    /**
+     * We get the requested output or fallback to the first one if the 
+     * requested one is not present in the resulting outputs maps.
+     */
+    maps* tmpI=NULL;
+    map* tmpIV=getMap(request_inputs1,"RawDataOutput");
+    if(tmpIV!=NULL){
+      tmpI=getMaps(request_outputs,tmpIV->value);
+    }
+    if(tmpI==NULL)
+      tmpI=request_outputs;
+    elements* e=getElements(s->outputs,tmpI->name);
+    if(e!=NULL && strcasecmp(e->format,"BoundingBoxData")==0){
+      printBoundingBoxDocument(m,tmpI,NULL);
+    }else{
+      map *gfile=getMap(tmpI->content,"generated_file");
+      if(gfile!=NULL){
+	gfile=getMap(tmpI->content,"expected_generated_file");
+	if(gfile==NULL){
+	  gfile=getMap(tmpI->content,"generated_file");
+	}
+	readGeneratedFile(m,tmpI->content,gfile->value);
+      }
+      toto=getMap(tmpI->content,"value");
+      if(toto==NULL){
+	char tmpMsg[1024];
+	sprintf(tmpMsg,_("Wrong RawDataOutput parameter: unable to fetch any result for the given parameter name: \"%s\"."),tmpI->name);
+	errorException(m,tmpMsg,"InvalidParameterValue","RawDataOutput");
+	return;
+      }
+      map* fname=getMapFromMaps(tmpI,tmpI->name,"filename");
+      if(fname!=NULL)
+	printf("Content-Disposition: attachment; filename=\"%s\"\r\n",fname->value);
+      map* rs=getMapFromMaps(tmpI,tmpI->name,"size");
+      if(rs!=NULL)
+	printf("Content-Length: %s\r\n",rs->value);
+      printHeaders(m);
+      char mime[1024];
+      map* mi=getMap(tmpI->content,"mimeType");
+#ifdef DEBUG
+      fprintf(stderr,"SERVICE OUTPUTS\n");
+      dumpMaps(request_outputs);
+      fprintf(stderr,"SERVICE OUTPUTS\n");
+#endif
+      map* en=getMap(tmpI->content,"encoding");
+      if(mi!=NULL && en!=NULL)
+	sprintf(mime,
+		"Content-Type: %s; charset=%s\r\nStatus: 200 OK\r\n\r\n",
+		mi->value,en->value);
+      else
+	if(mi!=NULL)
+	  sprintf(mime,
+		  "Content-Type: %s; charset=UTF-8\r\nStatus: 200 OK\r\n\r\n",
+		  mi->value);
+	else
+	  sprintf(mime,"Content-Type: text/plain; charset=utf-8\r\nStatus: 200 OK\r\n\r\n");
+      printf("%s",mime);
+      if(rs!=NULL)
+	fwrite(toto->value,1,atoi(rs->value),stdout);
+      else
+	fwrite(toto->value,1,strlen(toto->value),stdout);
+#ifdef DEBUG
+      dumpMap(toto);
+#endif
+    }
+  }
+}
+
+/**
+ * Create required XML nodes for boundingbox and update the current XML node
+ *
+ * @param ns_ows the ows XML namespace
+ * @param n the XML node to update
+ * @param boundingbox the map containing the boundingbox definition
+ */
+void printBoundingBox(xmlNsPtr ns_ows,xmlNodePtr n,map* boundingbox){
+
+  xmlNodePtr lw=NULL,uc=NULL;
+
+  map* tmp=getMap(boundingbox,"value");
+
+  tmp=getMap(boundingbox,"lowerCorner");
+  if(tmp!=NULL){
+    lw=xmlNewNode(ns_ows,BAD_CAST "LowerCorner");
+    xmlAddChild(lw,xmlNewText(BAD_CAST tmp->value));
+  }
+
+  tmp=getMap(boundingbox,"upperCorner");
+  if(tmp!=NULL){
+    uc=xmlNewNode(ns_ows,BAD_CAST "UpperCorner");
+    xmlAddChild(uc,xmlNewText(BAD_CAST tmp->value));
+  }
+
+  tmp=getMap(boundingbox,"crs");
+  if(tmp!=NULL)
+    xmlNewProp(n,BAD_CAST "crs",BAD_CAST tmp->value);
+
+  tmp=getMap(boundingbox,"dimensions");
+  if(tmp!=NULL)
+    xmlNewProp(n,BAD_CAST "dimensions",BAD_CAST tmp->value);
+
+  xmlAddChild(n,lw);
+  xmlAddChild(n,uc);
+
+}
+
+/**
+ * Parse a BoundingBox string
+ *
+ * [OGC 06-121r3](http://portal.opengeospatial.org/files/?artifact_id=20040):
+ *  10.2 Bounding box
+ * 
+ *
+ * Value is provided as : lowerCorner,upperCorner,crs,dimension
+ * Exemple : 189000,834000,285000,962000,urn:ogc:def:crs:OGC:1.3:CRS84
+ *
+ * A map to store boundingbox informations should contain:
+ *  - lowerCorner : double,double (minimum within this bounding box)
+ *  - upperCorner : double,double (maximum within this bounding box)
+ *  - crs : URI (Reference to definition of the CRS)
+ *  - dimensions : int 
+ * 
+ * Note : support only 2D bounding box.
+ *
+ * @param value the char* containing the KVP bouding box
+ * @return a map containing all the bounding box keys
+ */
+map* parseBoundingBox(const char* value){
+  map *res=NULL;
+  if(value!=NULL){
+    char *cv,*cvp;
+    cv=strtok_r((char*) value,",",&cvp);
+    int cnt=0;
+    int icnt=0;
+    char *currentValue=NULL;
+    while(cv){
+      if(cnt<2)
+	if(currentValue!=NULL){
+	  char *finalValue=(char*)malloc((strlen(currentValue)+strlen(cv)+1)*sizeof(char));
+	  sprintf(finalValue,"%s%s",currentValue,cv);
+	  switch(cnt){
+	  case 0:
+	    res=createMap("lowerCorner",finalValue);
+	    break;
+	  case 1:
+	    addToMap(res,"upperCorner",finalValue);
+	    icnt=-1;
+	    break;
+	  }
+	  cnt++;
+	  free(currentValue);
+	  currentValue=NULL;
+	  free(finalValue);
+	}
+	else{
+	  currentValue=(char*)malloc((strlen(cv)+2)*sizeof(char));
+	  sprintf(currentValue,"%s ",cv);
+	}
+      else
+	if(cnt==2){
+	  addToMap(res,"crs",cv);
+	  cnt++;
+	}
+	else
+	  addToMap(res,"dimensions",cv);
+      icnt++;
+      cv=strtok_r(NULL,",",&cvp);
+    }
+  }
+  return res;
+}
+
+/**
+ * Print an ows:BoundingBox XML document
+ *
+ * @param m the maps containing the settings of the main.cfg file
+ * @param boundingbox the maps containing the boundingbox definition
+ * @param file the file to print the BoundingBox (if NULL then print on stdout)
+ * @see parseBoundingBox, printBoundingBox
+ */
+void printBoundingBoxDocument(maps* m,maps* boundingbox,FILE* file){
+  if(file==NULL)
+    rewind(stdout);
+  xmlNodePtr n;
+  xmlDocPtr doc;
+  xmlNsPtr ns_ows,ns_xsi;
+  xmlChar *xmlbuff;
+  int buffersize;
+  char *encoding=getEncoding(m);
+  map *tmp;
+  if(file==NULL){
+    int pid=0;
+    tmp=getMapFromMaps(m,"lenv","sid");
+    if(tmp!=NULL)
+      pid=atoi(tmp->value);
+    if(pid==getpid()){
+      printf("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding);
+    }
+    fflush(stdout);
+  }
+
+  doc = xmlNewDoc(BAD_CAST "1.0");
+  int owsId=zooXmlAddNs(NULL,"http://www.opengis.net/ows/1.1","ows");
+  ns_ows=usedNs[owsId];
+  n = xmlNewNode(ns_ows, BAD_CAST "BoundingBox");
+  xmlNewNs(n,BAD_CAST "http://www.opengis.net/ows/1.1",BAD_CAST "ows");
+  int xsiId=zooXmlAddNs(n,"http://www.w3.org/2001/XMLSchema-instance","xsi");
+  ns_xsi=usedNs[xsiId];
+  xmlNewNsProp(n,ns_xsi,BAD_CAST "schemaLocation",BAD_CAST "http://www.opengis.net/ows/1.1 http://schemas.opengis.net/ows/1.1.0/owsCommon.xsd");
+  map *tmp1=getMap(boundingbox->content,"value");
+  tmp=parseBoundingBox(tmp1->value);
+  printBoundingBox(ns_ows,n,tmp);
+  xmlDocSetRootElement(doc, n);
+
+  xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);
+  if(file==NULL)
+    printf("%s",xmlbuff);
+  else{
+    fprintf(file,"%s",xmlbuff);
+  }
+
+  if(tmp!=NULL){
+    freeMap(&tmp);
+    free(tmp);
+  }
+  xmlFree(xmlbuff);
+  xmlFreeDoc(doc);
+  xmlCleanupParser();
+  zooXmlCleanupNs();
+  
+}
+
+/**
+ * Print a StatusInfo XML document.
+ * a statusInfo map should contain the following keys:
+ *  * JobID corresponding to usid key from the lenv section
+ *  * Status the current state (Succeeded,Failed,Accepted,Running)
+ *  * PercentCompleted (optional) the percent completed
+ *  * Message (optional) any messages the service may wish to share
+ *
+ * @param conf the maps containing the settings of the main.cfg file
+ * @param statusInfo the map containing the statusInfo definition
+ * @param req the WPS requests (GetResult, GetStatus or Dismiss)
+ */
+void printStatusInfo(maps* conf,map* statusInfo,char* req){
+  rewind(stdout);
+  xmlNodePtr n,n1;
+  xmlDocPtr doc;
+  xmlNsPtr ns;
+  xmlChar *xmlbuff;
+  int buffersize;
+  char *encoding=getEncoding(conf);
+  map *tmp;
+  int pid=0;
+  printf("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding);
+
+  map* version=getMapFromMaps(conf,"main","rversion");
+  int vid=getVersionId(version->value);
+
+  doc = xmlNewDoc(BAD_CAST "1.0");
+  n1=printWPSHeader(doc,conf,req,"StatusInfo",version->value,1);
+
+  map* val=getMap(statusInfo,"JobID");
+  int wpsId=zooXmlAddNs(NULL,schemas[vid][2],"wps");
+  ns=usedNs[wpsId];
+  n = xmlNewNode(ns, BAD_CAST "JobID");
+  xmlAddChild(n,xmlNewText(BAD_CAST val->value));
+
+  xmlAddChild(n1,n);
+
+  val=getMap(statusInfo,"Status");
+  n = xmlNewNode(ns, BAD_CAST "Status");
+  xmlAddChild(n,xmlNewText(BAD_CAST val->value));
+
+  xmlAddChild(n1,n);
+
+  if(strncasecmp(val->value,"Failed",6)!=0 &&
+     strncasecmp(val->value,"Succeeded",9)!=0){
+    val=getMap(statusInfo,"PercentCompleted");
+    if(val!=NULL){
+      n = xmlNewNode(ns, BAD_CAST "PercentCompleted");
+      xmlAddChild(n,xmlNewText(BAD_CAST val->value));
+      xmlAddChild(n1,n);
+    }
+
+    val=getMap(statusInfo,"Message");
+    if(val!=NULL){    
+      xmlAddChild(n1,xmlNewComment(BAD_CAST val->value));
+    }
+  }
+  xmlDocSetRootElement(doc, n1);
+
+  xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, encoding, 1);
+  printf("%s",xmlbuff);
+
+  xmlFree(xmlbuff);
+  xmlFreeDoc(doc);
+  xmlCleanupParser();
+  zooXmlCleanupNs();
+  
+}
+
diff --git a/zoo-project/zoo-kernel/response_print.h b/zoo-project/zoo-kernel/response_print.h
new file mode 100644
index 0000000..dc14d06
--- /dev/null
+++ b/zoo-project/zoo-kernel/response_print.h
@@ -0,0 +1,233 @@
+/*
+ * Author : Gérald FENOY
+ *
+ * Copyright (c) 2009-2013 GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef ZOO_RESPONSE_PRINT_H
+#define ZOO_RESPONSE_PRINT_H 1
+
+#pragma once 
+
+/**
+ * The default service url (overriden by serverAddress)
+ */
+#define DEFAULT_SERVICE_URL "http://www.zoo-project.org/"
+/**
+ * The time size
+ */
+#define TIME_SIZE 40
+
+#include <libintl.h>
+#include <locale.h>
+/**
+ * ZOO-Kernel internal messages translation function
+ */
+#define _(String) dgettext ("zoo-kernel",String)
+/**
+ * ZOO-Services messages translation function
+ */
+#define _ss(String) dgettext ("zoo-services",String)
+
+/**
+ * ZOO-Kernel was unable to create a lock
+ */
+#define ZOO_LOCK_CREATE_FAILED -4
+/**
+ * ZOO-Kernel was unable to acquire a lock
+ */
+#define ZOO_LOCK_ACQUIRE_FAILED -5
+/**
+ * ZOO-Kernel was unable to release a lock
+ */
+#define ZOO_LOCK_RELEASE_FAILED -6
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include "cgic.h"
+#ifndef WIN32
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/sem.h>
+#else
+#include <direct.h>
+#endif
+#include <stdio.h>
+#include <time.h>
+#include <ctype.h>
+#ifdef WIN32
+#ifndef USE_RUBY
+#include <unistd.h>
+#endif
+#endif
+#ifndef WIN32
+#include <xlocale.h>
+#endif
+#include "ulinet.h"
+
+#include "service.h"
+#include <openssl/sha.h>
+#include <openssl/md5.h>
+#include <openssl/hmac.h>
+#include <openssl/evp.h>
+#include <openssl/bio.h>
+#include <openssl/buffer.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <libxml/parser.h>
+#include <libxml/xpath.h>
+
+  /**
+   * Maximum number of XML namespaces
+   */
+#define ZOO_NS_MAX 10
+  /**
+   * Maximum number of XML docs
+   */
+#define ZOO_DOC_MAX 20
+
+  /**
+   * Global char* to store the serverAddress value of the [main] section
+   */
+  static char* SERVICE_URL;
+
+  /**
+   * Array of xmlNsPtr storing all used XML namespace
+   */
+  static xmlNsPtr usedNs[ZOO_NS_MAX];
+  /**
+   * Array storing names of the used XML namespace
+   */
+  static char* nsName[ZOO_NS_MAX];
+  /**
+   * Number of XML namespaces
+   */
+  static int nbNs=0;
+  /**
+   * Array of xmlDocPtr storing XML docs
+   */
+  static xmlDocPtr iDocs[ZOO_DOC_MAX];
+  /**
+   * Number of XML docs
+   */
+  static int nbDocs=0;
+
+  /**
+   * Definitions of acceptable final status
+   */
+  static char wpsStatus[2][11]={
+    "Succeeded",
+    "Failed"
+  };
+  /**
+   * Definitions of schemas depending on the WPS version
+   */
+  static const char* schemas[2][8]={
+    {"1.0.0","http://www.opengis.net/ows/1.1","http://www.opengis.net/wps/1.0.0","http://schemas.opengis.net/wps/1.0.0","%s %s/wps%s_response.xsd","http://schemas.opengis.net/ows/1.1.0/owsExceptionReport.xsd","1.1.0"},
+    {"2.0.0","http://www.opengis.net/ows/2.0","http://www.opengis.net/wps/2.0","http://schemas.opengis.net/wps/2.0","http://www.opengis.net/wps/2.0 http://schemas.opengis.net/wps/2.0/wps.xsd","http://schemas.opengis.net/ows/2.0/owsExceptionReport.xsd","2.0.2","http://www.opengis.net/spec/wps/2.0/def/process-profile/"},
+  };
+  /**
+   * Definitions of support requests (depending on the WPS version)
+   */
+  static int nbSupportedRequests=7;
+  /**
+   * Definitions of requests depending on the WPS version
+   */
+  static const char* requests[2][7]={
+    {"GetCapabilities","DescribeProcess","Execute",NULL},
+    {"GetCapabilities","DescribeProcess","Execute","GetStatus","GetResult","Dismiss",NULL},
+  };
+  /**
+   * Definitions requests requiring identifier (depending on the WPS version)
+   */
+  static int nbReqIdentifier=2;
+  /**
+   * Definitions requests requiring jobid (only for WPS version 2.0.0)
+   */
+  static int nbReqJob=3;
+  /**
+   * Definitions of root node for response depending on the request and the WPS version
+   */
+  static const char root_nodes[2][4][20]={
+    {"ProcessOfferings","ProcessDescriptions","ExecuteResponse",NULL},
+    {"Contents","ProcessOfferings","Result",NULL}
+  };
+
+  /**
+   * Name and corresponding attributes depending on the WPS version
+   */
+  static const char* capabilities[2][7]={
+    {
+      "Process",
+      "processVersion","1",
+      "storeSupported","true",
+      "statusSupported","true"
+    },
+    {
+      "ProcessSummary",
+      "processVersion","1.0.0",
+      "jobControlOptions","sync-execute async-execute dismiss",
+      "outputTransmission","value reference"
+    }
+  };
+
+  void addLangAttr(xmlNodePtr,maps*);
+
+  void printHeaders(maps*);
+
+  int zooXmlSearchForNs(const char*);
+  int zooXmlAddNs(xmlNodePtr,const char*,const char*);
+  void zooXmlCleanupNs();
+
+  int zooXmlAddDoc(xmlNodePtr,const char*,const char*);
+  void zooXmlCleanupDocs();
+  
+  void printExceptionReportResponse(maps*,map*);
+  xmlNodePtr createExceptionReportNode(maps*,map*,int);
+  void printProcessResponse(maps*,map*,int,service*,const char*,int,maps*,maps*);
+  xmlNodePtr printWPSHeader(xmlDocPtr,maps*,const char*,const char*,const char*,int);
+  xmlNodePtr printGetCapabilitiesHeader(xmlDocPtr,maps*,const char*);
+  void printGetCapabilitiesForProcess(registry*,maps*,xmlNodePtr,service*);
+  void printDescribeProcessForProcess(registry*,maps*,xmlNodePtr,service*);
+  void printFullDescription(int,elements*,const char*,xmlNsPtr,xmlNsPtr,xmlNodePtr,int);
+  void printDocument(maps*,xmlDocPtr,int);
+  void printDescription(xmlNodePtr,xmlNsPtr,const char*,map*,int);
+  void printIOType(xmlDocPtr,xmlNodePtr,xmlNsPtr,xmlNsPtr,xmlNsPtr,elements*,maps*,const char*,int);
+  map* parseBoundingBox(const char*);
+  void printBoundingBox(xmlNsPtr,xmlNodePtr,map*);
+  void printBoundingBoxDocument(maps*,maps*,FILE*);
+  void printOutputDefinitions(xmlDocPtr,xmlNodePtr,xmlNsPtr,xmlNsPtr,elements*,maps*,const char*);
+  void printStatusInfo(maps*,map*,char*);
+
+  void outputResponse(service*,maps*,maps*,map*,int,maps*,int);
+
+  int errorException(maps *, const char *, const char *, const char*);
+
+  xmlNodePtr soapEnvelope(maps*,xmlNodePtr);
+  int checkForSoapEnvelope(xmlDocPtr);
+  
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/zoo-project/zoo-kernel/server_internal.c b/zoo-project/zoo-kernel/server_internal.c
new file mode 100644
index 0000000..0f64322
--- /dev/null
+++ b/zoo-project/zoo-kernel/server_internal.c
@@ -0,0 +1,1203 @@
+/*
+ * Author : Gérald Fenoy
+ *
+ *  Copyright 2008-2015 GeoLabs SARL. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "server_internal.h"
+#include "service_internal.h"
+#include "response_print.h"
+#include "mimetypes.h"
+#ifndef WIN32
+#include <dlfcn.h>
+#include <uuid/uuid.h>
+#else
+#include <rpc.h>
+#define ERROR_MSG_MAX_LENGTH 1024
+#endif
+#include <signal.h>
+
+/**
+ * Detect WPS version used (1.0.0 or 2.0.0).
+ *
+ * @param version number as char* (1.0.0 or 2.0.0)
+ * @return 0 in case of version 1.0.0, 1 for 2.0.0, -1 in other case
+ */
+int getVersionId(const char* version){
+  int schemaId=0;
+  for(;schemaId<2;schemaId++){
+    if(strncasecmp(version,schemas[schemaId][0],5)==0)
+      return schemaId;
+  }
+  return -1;
+}
+
+/**
+ * Generate a UUID.
+ * ref: https://www.ietf.org/rfc/rfc4122.txt / 4.2 
+ *
+ * @return a new char* containing the UUID, make sure to free the returned 
+ *  ressource once used.
+ */
+char *get_uuid(){
+  char *res=(char*)malloc(37*sizeof(char));
+#ifdef WIN32
+  UUID uuid;
+  UuidCreate(&uuid);
+  RPC_CSTR rest = NULL;
+  UuidToString(&uuid,&rest);
+#else
+  uuid_t uuid;
+  uuid_generate_time(uuid);
+  char rest[128];
+  uuid_unparse(uuid,rest);
+#endif
+  sprintf(res,"%s",rest);
+#ifdef WIN32
+  RpcStringFree(&rest);
+#endif
+  return res;
+}
+
+/**
+ * Extract the service identifier from the full service identifier
+ * ie: 
+ *  - Full service name: OTB.BandMath
+ *  - Service name: BandMath
+ *
+ * @param conf the maps containing the settings of the main.cfg file
+ * @param conf_dir the full path to the ZOO-Kernel directory
+ * @param identifier the full service name (potentialy including a prefix, ie:
+ *  Prefix.MyService)
+ * @param buffer the resulting service identifier (without any prefix)
+ */
+void parseIdentifier(maps* conf,char* conf_dir,char *identifier,char* buffer){
+  setMapInMaps(conf,"lenv","oIdentifier",identifier);
+  char *lid=zStrdup(identifier);
+  char *saveptr1;
+  char *tmps1=strtok_r(lid,".",&saveptr1);
+  int level=0;
+  char key[25];
+  char levels[18];
+  while(tmps1!=NULL){
+    char *test=zStrdup(tmps1);
+    char* tmps2=(char*)malloc((strlen(test)+2)*sizeof(char));
+    sprintf(key,"sprefix_%d",level);
+    sprintf(tmps2,"%s.",test);
+    sprintf(levels,"%d",level);
+    setMapInMaps(conf,"lenv","level",levels);
+    setMapInMaps(conf,"lenv",key,tmps2);
+    free(tmps2);
+    free(test);
+    level++;
+    tmps1=strtok_r(NULL,".",&saveptr1);
+  }
+  int i=0;
+  sprintf(buffer,"%s",conf_dir);
+  for(i=0;i<level;i++){
+    char *tmp0=zStrdup(buffer);
+    sprintf(key,"sprefix_%d",i);
+    map* tmp00=getMapFromMaps(conf,"lenv",key);
+    if(tmp00!=NULL)
+      sprintf(buffer,"%s/%s",tmp0,tmp00->value);
+    free(tmp0);
+    buffer[strlen(buffer)-1]=0;
+    if(i+1<level){ 
+      #ifdef IGNORE_METAPATH
+        map* tmpMap = createMap("metapath", "");
+      #else  
+        map* tmpMap=getMapFromMaps(conf,"lenv","metapath");
+      #endif	  
+      if(tmpMap==NULL || strlen(tmpMap->value)==0){
+	char *tmp01=zStrdup(tmp00->value);
+	tmp01[strlen(tmp01)-1]=0;
+	setMapInMaps(conf,"lenv","metapath",tmp01);
+	free(tmp01);
+	tmp01=NULL;
+      }
+      else{
+	if(tmp00!=NULL && tmpMap!=NULL){
+	  char *tmp00s=zStrdup(tmp00->value);
+	  tmp00s[strlen(tmp00s)-1]=0;
+	  char *value=(char*)malloc((strlen(tmp00s)+strlen(tmpMap->value)+2)*sizeof(char));
+	  sprintf(value,"%s/%s",tmpMap->value,tmp00s);
+	  setMapInMaps(conf,"lenv","metapath",value);
+	  free(value);
+	  free(tmp00s);
+	  value=NULL;
+	}
+      }
+    }else{
+      char *tmp01=zStrdup(tmp00->value);
+      tmp01[strlen(tmp01)-1]=0;
+      setMapInMaps(conf,"lenv","Identifier",tmp01);
+      free(tmp01);
+    }
+  }
+  char *tmp0=zStrdup(buffer);
+  sprintf(buffer,"%s.zcfg",tmp0);
+  free(tmp0);
+  free(lid);
+}
+
+/**
+ * Converts a hex character to its integer value 
+ *
+ * @param ch the char to convert
+ * @return the converted char 
+ */
+char from_hex(char ch) {
+  return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
+}
+
+/**
+ * Converts an integer value to its hec character 
+ *
+ * @param code the char to convert
+ * @return the converted char 
+ */
+char to_hex(char code) {
+  static char hex[] = "0123456789abcdef";
+  return hex[code & 15];
+}
+
+/**
+ * URLEncode an url
+ *
+ * @param str the url to encode
+ * @return a url-encoded version of str
+ * @warning be sure to free() the returned string after use
+ */
+char *url_encode(char *str) {
+  char *pstr = str, *buf = (char*) malloc(strlen(str) * 3 + 1), *pbuf = buf;
+  while (*pstr) {
+    if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~') 
+      *pbuf++ = *pstr;
+    else if (*pstr == ' ') 
+      *pbuf++ = '+';
+    else 
+      *pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4), *pbuf++ = to_hex(*pstr & 15);
+    pstr++;
+  }
+  *pbuf = '\0';
+  return buf;
+}
+
+/**
+ * Decode an URLEncoded url
+ *
+ * @param str the URLEncoded url to decode
+ * @return a url-decoded version of str
+ * @warning be sure to free() the returned string after use
+ */
+char *url_decode(char *str) {
+  char *pstr = str, *buf = (char*) malloc(strlen(str) + 1), *pbuf = buf;
+  while (*pstr) {
+    if (*pstr == '%') {
+      if (pstr[1] && pstr[2]) {
+        *pbuf++ = from_hex(pstr[1]) << 4 | from_hex(pstr[2]);
+        pstr += 2;
+      }
+    } else if (*pstr == '+') { 
+      *pbuf++ = ' ';
+    } else {
+      *pbuf++ = *pstr;
+    }
+    pstr++;
+  }
+  *pbuf = '\0';
+  return buf;
+}
+
+/**
+ * Verify if a given language is listed in the lang list defined in the [main] 
+ * section of the main.cfg file.
+ * 
+ * @param conf the map containing the settings from the main.cfg file
+ * @param str the specific language
+ * @return 1 if the specific language is listed, -1 in other case.
+ */
+int isValidLang(maps* conf,const char *str){
+  map *tmpMap=getMapFromMaps(conf,"main","lang");
+  char *tmp=zStrdup(tmpMap->value);
+  char *pToken,*saveptr;
+  pToken=strtok_r(tmp,",",&saveptr);
+  int res=-1;
+  char *pToken1,*saveptr1;
+  pToken1=strtok_r(tmp,",",&saveptr1);
+  while(pToken1!=NULL){
+    while(pToken!=NULL){
+      if(strcasecmp(pToken1,pToken)==0){
+	res=1;
+	break;
+      }
+      pToken=strtok_r(NULL,",",&saveptr);
+    }
+    pToken1=strtok_r(NULL,",",&saveptr1);
+  }
+  free(tmp);
+  return res;
+}
+
+
+/**
+ * Access the value of the encoding key in a maps
+ *
+ * @param m the maps to search for the encoding key
+ * @return the value of the encoding key in a maps if encoding key exists,
+ *  "UTF-8" in other case.
+ */
+char* getEncoding(maps* m){
+  if(m!=NULL){
+    map* tmp=getMap(m->content,"encoding");
+    if(tmp!=NULL){
+      return tmp->value;
+    }
+    else
+      return (char*)"UTF-8";
+  }
+  else
+    return (char*)"UTF-8";  
+}
+
+/**
+ * Access the value of the version key in a maps
+ *
+ * @param m the maps to search for the version key
+ * @return the value of the version key in a maps if encoding key exists,
+ *  "1.0.0" in other case.
+ */
+char* getVersion(maps* m){
+  if(m!=NULL){
+    map* tmp=getMap(m->content,"version");
+    if(tmp!=NULL){
+      return tmp->value;
+    }
+    else
+      return (char*)"1.0.0";
+  }
+  else
+    return (char*)"1.0.0";
+}
+
+/**
+ * Read a file generated by a service.
+ * 
+ * @param m the conf maps
+ * @param content the output item
+ * @param filename the file to read
+ */
+void readGeneratedFile(maps* m,map* content,char* filename){
+  FILE * file=fopen(filename,"rb");
+  if(file==NULL){
+    fprintf(stderr,"Failed to open file %s for reading purpose.\n",filename);
+    setMapInMaps(m,"lenv","message","Unable to read produced file. Please try again later");
+    return ;
+  }
+  fseek(file, 0, SEEK_END);
+  long count = ftell(file);
+  rewind(file);
+  struct stat file_status; 
+  stat(filename, &file_status);
+  map* tmpMap1=getMap(content,"value");
+  if(tmpMap1==NULL){
+    addToMap(content,"value","");
+    tmpMap1=getMap(content,"value");
+  }
+  free(tmpMap1->value);
+  tmpMap1->value=(char*) malloc((count+1)*sizeof(char));  
+  fread(tmpMap1->value,1,count,file);
+  tmpMap1->value[count]=0;
+  fclose(file);
+  char rsize[1000];
+  sprintf(rsize,"%ld",count);
+  addToMap(content,"size",rsize);
+}
+
+
+/**
+ * Write a file from value and length
+ *
+ * @param fname the file name
+ * @param val the value
+ * @param length the value length
+ */
+int writeFile(char* fname,char* val,int length){
+  FILE* of=fopen(fname,"wb");
+  if(of==NULL){
+    return -1;
+  }
+  size_t ret=fwrite(val,sizeof(char),length,of);
+  if(ret<length){
+    fprintf(stderr,"Write error occured!\n");
+    fclose(of);
+    return -1;
+  }
+  fclose(of);
+  return 1;
+}
+
+/**
+ * Dump all values in a maps as files
+ *
+ * @param main_conf the maps containing the settings of the main.cfg file
+ * @param in the maps containing values to dump as files
+ */
+void dumpMapsValuesToFiles(maps** main_conf,maps** in){
+  map* tmpPath=getMapFromMaps(*main_conf,"main","tmpPath");
+  map* tmpSid=getMapFromMaps(*main_conf,"lenv","usid");
+  maps* inputs=*in;
+  int length=0;
+  while(inputs!=NULL){
+    if(getMap(inputs->content,"mimeType")!=NULL &&
+       getMap(inputs->content,"cache_file")==NULL){
+      map* cMap=inputs->content;
+      if(getMap(cMap,"length")!=NULL){
+	map* tmpLength=getMap(cMap,"length");
+	int len=atoi(tmpLength->value);
+	int k=0;
+	for(k=0;k<len;k++){
+	  map* cMimeType=getMapArray(cMap,"mimeType",k);
+	  map* cValue=getMapArray(cMap,"value",k);
+	  map* cSize=getMapArray(cMap,"size",k);
+	  char file_ext[32];
+	  getFileExtension(cMimeType != NULL ? cMimeType->value : NULL, file_ext, 32);
+	  char* val=(char*)malloc((strlen(tmpPath->value)+strlen(inputs->name)+strlen(tmpSid->value)+strlen(file_ext)+16)*sizeof(char));
+	  sprintf(val,"%s/Input_%s_%s_%d.%s",tmpPath->value,inputs->name,tmpSid->value,k,file_ext);
+	  length=0;
+	  if(cSize!=NULL){
+	    length=atoi(cSize->value);
+	  }
+	  writeFile(val,cValue->value,length);
+	  setMapArray(cMap,"cache_file",k,val);
+	  free(val);
+	}
+      }else{
+	int length=0;
+	map* cMimeType=getMap(cMap,"mimeType");
+	map* cValue=getMap(cMap,"value");
+	map* cSize=getMap(cMap,"size");
+	char file_ext[32];
+	getFileExtension(cMimeType != NULL ? cMimeType->value : NULL, file_ext, 32);
+	char *val=(char*)malloc((strlen(tmpPath->value)+strlen(inputs->name)+strlen(tmpSid->value)+strlen(file_ext)+16)*sizeof(char));
+	sprintf(val,"%s/Input_%s_%s_%d.%s",tmpPath->value,inputs->name,tmpSid->value,0,file_ext);
+	if(cSize!=NULL){
+	  length=atoi(cSize->value);
+	}
+	writeFile(val,cValue->value,length);
+	addToMap(cMap,"cache_file",val);
+	free(val);
+      }
+    }
+    inputs=inputs->next;
+  }
+}
+
+
+/**
+ * Base64 encoding of a char*
+ *
+ * @param input the value to encode
+ * @param length the value length
+ * @return the buffer containing the base64 value
+ * @warning make sure to free the returned value
+ */
+char *base64(const char *input, int length)
+{
+  BIO *bmem, *b64;
+  BUF_MEM *bptr;
+
+  b64 = BIO_new(BIO_f_base64());
+  BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
+  bmem = BIO_new(BIO_s_mem());
+  b64 = BIO_push(b64, bmem);
+  BIO_write(b64, input, length);
+  BIO_flush(b64);
+  BIO_get_mem_ptr(b64, &bptr);
+
+  char *buff = (char *)malloc((bptr->length+1)*sizeof(char));
+  memcpy(buff, bptr->data, bptr->length);
+  buff[bptr->length] = 0;
+
+  BIO_free_all(b64);
+
+  return buff;
+}
+
+/**
+ * Base64 decoding of a char*
+ *
+ * @param input the value to decode
+ * @param length the value length
+ * @param red the value length
+ * @return the buffer containing the base64 value 
+ * @warning make sure to free the returned value
+ */
+char *base64d(const char *input, int length,int* red)
+{
+  BIO *b64, *bmem;
+
+  char *buffer = (char *)malloc(length);
+  if(buffer){
+    memset(buffer, 0, length);
+    b64 = BIO_new(BIO_f_base64());
+    if(b64){
+      bmem = BIO_new_mem_buf((unsigned char*)input,length);
+      bmem = BIO_push(b64, bmem);
+      *red=BIO_read(bmem, buffer, length);
+      buffer[length-1]=0;
+      BIO_free_all(bmem);
+    }
+  }
+  return buffer;
+}
+
+/**
+ * Read Base64 value and split it value by lines of 64 char.
+ *
+ * @param in the map containing the value to split
+ */
+void readBase64(map **in){
+  char *res = NULL;
+  char *curs = (*in)->value;
+  int i = 0;
+  for (i = 0; i <= strlen ((*in)->value) / 64;
+       i++)
+    {
+      if (res == NULL)
+	res =
+	  (char *) malloc (65 * sizeof (char));
+      else
+	res =
+	  (char *) realloc (res,
+			    (((i + 1) * 65) +
+			     i) * sizeof (char));
+      int csize = i * 65;
+      strncpy (res + csize, curs, 64);
+      if (i == strlen ((*in)->value) / 64)
+	strcat (res, "\n\0");
+      else
+	{
+	  strncpy (res + (((i + 1) * 64) + i),
+		   "\n\0", 2);
+	  curs += 64;
+	}
+    }
+  free ((*in)->value);
+  (*in)->value = zStrdup (res);
+  free (res);
+}
+
+
+/**
+ * Add the default values defined in the zcfg to a maps.
+ *
+ * @param out the maps containing the inputs or outputs given in the initial
+ *  HTTP request
+ * @param in the description of all inputs or outputs available for a service
+ * @param m the maps containing the settings of the main.cfg file
+ * @param type 0 for inputs and 1 for outputs
+ * @param err the map to store potential missing mandatory input parameters or
+ *  wrong output names depending on the type.
+ * @return "" if no error was detected, the name of last input or output causing
+ *  an error.
+ */
+char* addDefaultValues(maps** out,elements* in,maps* m,int type,map** err){
+  map *res=*err;
+  elements* tmpInputs=in;
+  maps* out1=*out;
+  char *result=NULL;
+  int nb=0;
+  if(type==1){
+    while(out1!=NULL){
+      if(getElements(in,out1->name)==NULL){
+	if(res==NULL){
+	  res=createMap("value",out1->name);
+	}else{
+	  setMapArray(res,"value",nb,out1->name);
+	}
+	nb++;
+	result=out1->name;
+      }
+      out1=out1->next;
+    }
+    if(res!=NULL){
+      *err=res;
+      return result;
+    }
+    out1=*out;
+  }
+  while(tmpInputs!=NULL){
+    maps *tmpMaps=getMaps(out1,tmpInputs->name);
+    if(tmpMaps==NULL){
+      maps* tmpMaps2=(maps*)malloc(MAPS_SIZE);
+      tmpMaps2->name=strdup(tmpInputs->name);
+      tmpMaps2->content=NULL;
+      tmpMaps2->next=NULL;
+      
+      if(type==0){
+	map* tmpMapMinO=getMap(tmpInputs->content,"minOccurs");
+	if(tmpMapMinO!=NULL){
+	  if(atoi(tmpMapMinO->value)>=1){
+	    freeMaps(&tmpMaps2);
+	    free(tmpMaps2);
+	    if(res==NULL){
+	      res=createMap("value",tmpInputs->name);
+	    }else{
+	      setMapArray(res,"value",nb,tmpInputs->name);
+	    }
+	    nb++;
+	    result=tmpInputs->name;
+	  }
+	  else{
+	    if(tmpMaps2->content==NULL)
+	      tmpMaps2->content=createMap("minOccurs",tmpMapMinO->value);
+	    else
+	      addToMap(tmpMaps2->content,"minOccurs",tmpMapMinO->value);
+	  }
+	}
+	if(res==NULL){
+	  map* tmpMaxO=getMap(tmpInputs->content,"maxOccurs");
+	  if(tmpMaxO!=NULL){
+	    if(tmpMaps2->content==NULL)
+	      tmpMaps2->content=createMap("maxOccurs",tmpMaxO->value);
+	    else
+	      addToMap(tmpMaps2->content,"maxOccurs",tmpMaxO->value);
+	  }
+	  map* tmpMaxMB=getMap(tmpInputs->content,"maximumMegabytes");
+	  if(tmpMaxMB!=NULL){
+	    if(tmpMaps2->content==NULL)
+	      tmpMaps2->content=createMap("maximumMegabytes",tmpMaxMB->value);
+	    else
+	      addToMap(tmpMaps2->content,"maximumMegabytes",tmpMaxMB->value);
+	  }
+	}
+      }
+
+      if(res==NULL){
+	iotype* tmpIoType=tmpInputs->defaults;
+	if(tmpIoType!=NULL){
+	  map* tmpm=tmpIoType->content;
+	  while(tmpm!=NULL){
+	    if(tmpMaps2->content==NULL)
+	      tmpMaps2->content=createMap(tmpm->name,tmpm->value);
+	    else
+	      addToMap(tmpMaps2->content,tmpm->name,tmpm->value);
+	    tmpm=tmpm->next;
+	  }
+	}
+	addToMap(tmpMaps2->content,"inRequest","false");
+	if(type==0){
+	  map *tmpMap=getMap(tmpMaps2->content,"value");
+	  if(tmpMap==NULL)
+	    addToMap(tmpMaps2->content,"value","NULL");
+	}
+	if(out1==NULL){
+	  *out=dupMaps(&tmpMaps2);
+	  out1=*out;
+	}
+	else
+	  addMapsToMaps(&out1,tmpMaps2);
+	freeMap(&tmpMaps2->content);
+	free(tmpMaps2->content);
+	tmpMaps2->content=NULL;
+	freeMaps(&tmpMaps2);
+	free(tmpMaps2);
+	tmpMaps2=NULL;
+      }
+    }
+    else{
+      iotype* tmpIoType=getIoTypeFromElement(tmpInputs,tmpInputs->name,
+					     tmpMaps->content);
+      if(type==0) {
+	/**
+	 * In case of an Input maps, then add the minOccurs and maxOccurs to the
+	 * content map.
+	 */
+	map* tmpMap1=getMap(tmpInputs->content,"minOccurs");
+	if(tmpMap1!=NULL){
+	  if(tmpMaps->content==NULL)
+	    tmpMaps->content=createMap("minOccurs",tmpMap1->value);
+	  else
+	    addToMap(tmpMaps->content,"minOccurs",tmpMap1->value);
+	}
+	map* tmpMaxO=getMap(tmpInputs->content,"maxOccurs");
+	if(tmpMaxO!=NULL){
+	  if(tmpMaps->content==NULL)
+	    tmpMaps->content=createMap("maxOccurs",tmpMaxO->value);
+	  else
+	    addToMap(tmpMaps->content,"maxOccurs",tmpMaxO->value);
+	}
+	map* tmpMaxMB=getMap(tmpInputs->content,"maximumMegabytes");
+	if(tmpMaxMB!=NULL){
+	  if(tmpMaps->content==NULL)
+	    tmpMaps->content=createMap("maximumMegabytes",tmpMaxMB->value);
+	  else
+	    addToMap(tmpMaps->content,"maximumMegabytes",tmpMaxMB->value);
+	}
+	/**
+	 * Parsing BoundingBoxData, fill the following map and then add it to
+	 * the content map of the Input maps: 
+	 * lowerCorner, upperCorner, srs and dimensions
+	 * cf. parseBoundingBox
+	 */
+	if(tmpInputs->format!=NULL && strcasecmp(tmpInputs->format,"BoundingBoxData")==0){
+	  maps* tmpI=getMaps(*out,tmpInputs->name);
+	  if(tmpI!=NULL){
+	    map* tmpV=getMap(tmpI->content,"value");
+	    if(tmpV!=NULL){
+	      char *tmpVS=strdup(tmpV->value);
+	      map* tmp=parseBoundingBox(tmpVS);
+	      free(tmpVS);
+	      map* tmpC=tmp;
+	      while(tmpC!=NULL){
+		addToMap(tmpMaps->content,tmpC->name,tmpC->value);
+		tmpC=tmpC->next;
+	      }
+	      freeMap(&tmp);
+	      free(tmp);
+	    }
+	  }
+	}
+      }
+
+      if(tmpIoType!=NULL){
+	map* tmpContent=tmpIoType->content;
+	map* cval=NULL;
+	int hasPassed=-1;
+	while(tmpContent!=NULL){
+	  if((cval=getMap(tmpMaps->content,tmpContent->name))==NULL){
+#ifdef DEBUG
+	    fprintf(stderr,"addDefaultValues %s => %s\n",tmpContent->name,tmpContent->value);
+#endif
+	    if(tmpMaps->content==NULL)
+	      tmpMaps->content=createMap(tmpContent->name,tmpContent->value);
+	    else
+	      addToMap(tmpMaps->content,tmpContent->name,tmpContent->value);
+	    
+	    if(hasPassed<0 && type==0 && getMap(tmpMaps->content,"isArray")!=NULL){
+	      map* length=getMap(tmpMaps->content,"length");
+	      int i;
+	      char *tcn=strdup(tmpContent->name);
+	      for(i=1;i<atoi(length->value);i++){
+#ifdef DEBUG
+		dumpMap(tmpMaps->content);
+		fprintf(stderr,"addDefaultValues %s_%d => %s\n",tcn,i,tmpContent->value);
+#endif
+		int len=strlen((char*) tcn);
+		char *tmp1=(char *)malloc((len+10)*sizeof(char));
+		sprintf(tmp1,"%s_%d",tcn,i);
+#ifdef DEBUG
+		fprintf(stderr,"addDefaultValues %s => %s\n",tmp1,tmpContent->value);
+#endif
+		addToMap(tmpMaps->content,tmp1,tmpContent->value);
+		free(tmp1);
+		hasPassed=1;
+	      }
+	      free(tcn);
+	    }
+	  }
+	  tmpContent=tmpContent->next;
+	}
+#ifdef USE_MS
+	/**
+	 * check for useMapServer presence
+	 */
+	map* tmpCheck=getMap(tmpIoType->content,"useMapServer");
+	if(tmpCheck!=NULL){
+	  // Get the default value
+	  tmpIoType=getIoTypeFromElement(tmpInputs,tmpInputs->name,NULL);
+	  tmpCheck=getMap(tmpMaps->content,"mimeType");
+	  addToMap(tmpMaps->content,"requestedMimeType",tmpCheck->value);
+	  map* cursor=tmpIoType->content;
+	  while(cursor!=NULL){
+	    addToMap(tmpMaps->content,cursor->name,cursor->value);
+	    cursor=cursor->next;
+	  }
+	  
+	  cursor=tmpInputs->content;
+	  while(cursor!=NULL){
+	    if(strcasecmp(cursor->name,"Title")==0 ||
+	       strcasecmp(cursor->name,"Abstract")==0)
+	      addToMap(tmpMaps->content,cursor->name,cursor->value);
+           cursor=cursor->next;
+	  }
+	}
+#endif
+      }
+      if(tmpMaps->content==NULL)
+	tmpMaps->content=createMap("inRequest","true");
+      else
+	addToMap(tmpMaps->content,"inRequest","true");
+
+    }
+    tmpInputs=tmpInputs->next;
+  }
+  if(res!=NULL){
+    *err=res;
+    return result;
+  }
+  return "";
+}
+
+/**
+ * Access the last error message returned by the OS when trying to dynamically
+ * load a shared library.
+ *
+ * @return the last error message
+ * @warning The character string returned from getLastErrorMessage resides
+ * in a static buffer. The application should not write to this
+ * buffer or attempt to free() it.
+ */ 
+char* getLastErrorMessage() {                                              
+#ifdef WIN32
+  LPVOID lpMsgBuf;
+  DWORD errCode = GetLastError();
+  static char msg[ERROR_MSG_MAX_LENGTH];
+  size_t i;
+  
+  DWORD length = FormatMessage(
+			       FORMAT_MESSAGE_ALLOCATE_BUFFER | 
+			       FORMAT_MESSAGE_FROM_SYSTEM |
+			       FORMAT_MESSAGE_IGNORE_INSERTS,
+			       NULL,
+			       errCode,
+			       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+			       (LPTSTR) &lpMsgBuf,
+			       0, NULL );	
+  
+#ifdef UNICODE		
+  wcstombs_s( &i, msg, ERROR_MSG_MAX_LENGTH,
+	      (wchar_t*) lpMsgBuf, _TRUNCATE );
+#else
+  strcpy_s( msg, ERROR_MSG_MAX_LENGTH,
+	    (char *) lpMsgBuf );		
+#endif	
+  LocalFree(lpMsgBuf);
+
+  return msg;
+#else
+  return dlerror();
+#endif
+}
+
+#include <dirent.h>
+#ifndef RELY_ON_DB
+/**
+ * Read the Result file (.res).
+ *
+ * @param conf the maps containing the setting of the main.cfg file
+ * @param pid the service identifier (usid key from the [lenv] section)
+ */
+void readFinalRes(maps* conf,char* pid,map* statusInfo){
+  map* r_inputs = getMapFromMaps (conf, "main", "tmpPath");
+  char* fbkpid =
+    (char *)
+    malloc ((strlen (r_inputs->value) + strlen (pid) + 7) * sizeof (char));
+  sprintf (fbkpid, "%s/%s.res", r_inputs->value, pid);
+  struct stat file_status;
+  int istat = stat (fbkpid, &file_status);
+  if (istat == 0 && file_status.st_size > 0)
+    {
+      maps *res = (maps *) malloc (MAPS_SIZE);
+      conf_read (fbkpid, res);
+      map* status=getMapFromMaps(res,"status","status");
+      addToMap(statusInfo,"Status",status->value);
+      freeMaps(&res);
+      free(res);
+    }
+  else
+    addToMap(statusInfo,"Status","Failed");  
+  free(fbkpid);
+}
+
+/**
+ * Check if a service is running.
+ *
+ * @param conf the maps containing the setting of the main.cfg file
+ * @param pid the unique service identifier (usid from the lenv section)
+ * @return 1 in case the service is still running, 0 otherwise
+ */
+int isRunning(maps* conf,char* pid){
+  int res=0;
+  map* r_inputs = getMapFromMaps (conf, "main", "tmpPath");
+  char* fbkpid =
+    (char *)
+    malloc ((strlen (r_inputs->value) + strlen (pid) + 7) * sizeof (char));
+  sprintf (fbkpid, "%s/%s.pid", r_inputs->value, pid);
+  FILE* f0 = fopen (fbkpid, "r");
+  if(f0!=NULL){
+    fclose(f0);
+    res=1;
+  }
+  free(fbkpid);
+  return res;
+}
+#else
+#include "sqlapi.h"
+#endif
+
+/**
+ * Run GetStatus requests.
+ *
+ * @param conf the maps containing the setting of the main.cfg file
+ * @param pid the service identifier (usid key from the [lenv] section)
+ * @param req the request (GetStatus / GetResult)
+ */
+void runGetStatus(maps* conf,char* pid,char* req){
+  map* r_inputs = getMapFromMaps (conf, "main", "tmpPath");
+  char *sid=getStatusId(conf,pid);
+  if(sid==NULL){
+    errorException (conf, _("The JobID from the request does not match any of the Jobs running on this server"),
+		    "NoSuchJob", pid);
+  }else{
+    map* statusInfo=createMap("JobID",pid);
+    if(isRunning(conf,pid)>0){
+      if(strncasecmp(req,"GetResult",strlen(req))==0){
+	errorException (conf, _("The result for the requested JobID has not yet been generated. "),
+			"ResultNotReady", pid);
+	return;
+      }
+      else
+	if(strncasecmp(req,"GetStatus",strlen(req))==0){
+	  addToMap(statusInfo,"Status","Running");
+	  char* tmpStr=_getStatus(conf,pid);
+	  if(tmpStr!=NULL && strncmp(tmpStr,"-1",2)!=0){
+	    char *tmpStr1=strdup(tmpStr);
+	    char *tmpStr0=strdup(strstr(tmpStr,"|")+1);
+	    free(tmpStr);
+	    tmpStr1[strlen(tmpStr1)-strlen(tmpStr0)-1]='\0';
+	    addToMap(statusInfo,"PercentCompleted",tmpStr1);
+	    addToMap(statusInfo,"Message",tmpStr0);
+	    free(tmpStr0);
+	    free(tmpStr1);
+	  }
+	}
+    }
+    else{
+      if(strncasecmp(req,"GetResult",strlen(req))==0){
+	char* result=_getStatusFile(conf,pid);
+	if(result!=NULL){
+	  char *encoding=getEncoding(conf);
+	  printf("Content-Type: text/xml; charset=%s\r\nStatus: 200 OK\r\n\r\n",encoding);
+	  printf("%s",result);
+	  fflush(stdout);
+	  freeMap(&statusInfo);
+	  free(statusInfo);
+	  return;
+	}else{
+	  errorException (conf, _("The result for the requested JobID has not yet been generated. "),
+			  "ResultNotReady", pid);
+	  freeMap(&statusInfo);
+	  free(statusInfo);
+	  return;
+	}
+      }else
+	if(strncasecmp(req,"GetStatus",strlen(req))==0){
+	  readFinalRes(conf,pid,statusInfo);
+	  char* tmpStr=_getStatus(conf,pid);
+	  if(tmpStr!=NULL && strncmp(tmpStr,"-1",2)!=0){
+	    char *tmpStr1=strdup(tmpStr);
+	    char *tmpStr0=strdup(strstr(tmpStr,"|")+1);
+	    free(tmpStr);
+	    tmpStr1[strlen(tmpStr1)-strlen(tmpStr0)-1]='\0';
+	    addToMap(statusInfo,"PercentCompleted",tmpStr1);
+	    addToMap(statusInfo,"Message",tmpStr0);
+	    free(tmpStr0);
+	    free(tmpStr1);
+	  }
+	}
+    }
+    printStatusInfo(conf,statusInfo,req);
+    freeMap(&statusInfo);
+    free(statusInfo);
+  }
+  return;
+}
+
+/**
+ * Run Dismiss requests.
+ *
+ * @param conf the maps containing the setting of the main.cfg file
+ * @param pid the service identifier (usid key from the [lenv] section)
+ */
+void runDismiss(maps* conf,char* pid){
+  map* r_inputs = getMapFromMaps (conf, "main", "tmpPath");
+  char *sid=getStatusId(conf,pid);
+  if(sid==NULL){
+    errorException (conf, _("The JobID from the request does not match any of the Jobs running on this server"),
+		    "NoSuchJob", pid);
+  }else{
+    // We should send the Dismiss request to the target host if it differs
+    char* fbkpid =
+      (char *)
+      malloc ((strlen (r_inputs->value) + strlen (pid) + 7) * sizeof (char));
+    sprintf (fbkpid, "%s/%s.pid", r_inputs->value, pid);
+    FILE* f0 = fopen (fbkpid, "r");
+    if(f0!=NULL){
+      long flen;
+      char *fcontent;
+      fseek (f0, 0, SEEK_END);
+      flen = ftell (f0);
+      fseek (f0, 0, SEEK_SET);
+      fcontent = (char *) malloc ((flen + 1) * sizeof (char));
+      fread(fcontent,flen,1,f0);
+      fcontent[flen]=0;
+      fclose(f0);
+#ifndef WIN32
+      kill(atoi(fcontent),SIGKILL);
+#else
+      HANDLE myZooProcess=OpenProcess(PROCESS_ALL_ACCESS,false,atoi(fcontent));
+      TerminateProcess(myZooProcess,1);
+      CloseHandle(myZooProcess);
+#endif
+      free(fcontent);
+    }
+    free(fbkpid);
+    struct dirent *dp;
+    DIR *dirp = opendir(r_inputs->value);
+    char fileName[1024];
+    int hasFile=-1;
+    if(dirp!=NULL){
+      while ((dp = readdir(dirp)) != NULL){
+#ifdef DEBUG
+	fprintf(stderr,"File : %s searched : %s\n",dp->d_name,tmp);
+#endif
+	if(strstr(dp->d_name,pid)!=0){
+	  sprintf(fileName,"%s/%s",r_inputs->value,dp->d_name);
+	  if(unlink(fileName)!=0){
+	    errorException (conf, 
+			    _("The job cannot be removed, a file cannot be removed"),
+			    "NoApplicableCode", NULL);
+	    return;
+	  }
+	}
+      }
+    }
+#ifdef RELY_ON_DB
+    removeService(conf,pid);
+#endif
+    map* statusInfo=createMap("JobID",pid);
+    addToMap(statusInfo,"Status","Dismissed");
+    printStatusInfo(conf,statusInfo,"Dismiss");
+    free(statusInfo);
+  }
+  return;
+}
+
+extern int getServiceFromFile (maps *, const char *, service **);
+
+/**
+ * Parse the service file using getServiceFromFile or use getServiceFromYAML
+ * if YAML support was activated.
+ *
+ * @param conf the conf maps containing the main.cfg settings
+ * @param file the file name to parse
+ * @param service the service to update witht the file content
+ * @param name the service name
+ * @return true if the file can be parsed or false
+ * @see getServiceFromFile, getServiceFromYAML
+ */
+int readServiceFile (maps * conf, char *file, service ** service, char *name){
+  int t = getServiceFromFile (conf, file, service);
+#ifdef YAML
+  if (t < 0){
+    t = getServiceFromYAML (conf, file, service, name);
+  }
+#endif
+  return t;
+}
+
+/**
+ * Create the profile registry.
+ *
+ * The profile registry is optional (created only if the registry key is
+ * available in the [main] section of the main.cfg file) and can be used to
+ * store the profiles hierarchy. The registry is a directory which should
+ * contain the following sub-directories: 
+ *  * concept: direcotry containing .html files describing concept
+ *  * generic: directory containing .zcfg files for wps:GenericProcess
+ *  * implementation: directory containing .zcfg files for wps:Process
+ *
+ * @param m the conf maps containing the main.cfg settings
+ * @param r the registry to update
+ * @param reg_dir the resgitry 
+ * @return 0 if the resgitry is null or was correctly updated, -1 on failure
+ */
+int createRegistry (maps* m,registry ** r, char *reg_dir)
+{
+  char registryKeys[3][15]={
+    "concept",
+    "generic",
+    "implementation"
+  };
+  int scount = 0,i=0;
+  if (reg_dir == NULL)
+    return 0;
+  for(i=0;i<3;i++){
+    char * tmpName =
+      (char *) malloc ((strlen (reg_dir) + strlen (registryKeys[i]) + 2) *
+		       sizeof (char));
+    sprintf (tmpName, "%s/%s", reg_dir, registryKeys[i]);
+    
+    DIR *dirp1 = opendir (tmpName);
+    if(dirp1==NULL){
+      setMapInMaps(m,"lenv","message",_("Unable to open the registry directory."));
+      setMapInMaps(m,"lenv","type","InternalError");
+      return -1;
+    }
+    struct dirent *dp1;
+    while ((dp1 = readdir (dirp1)) != NULL){
+      char* extn = strstr(dp1->d_name, ".zcfg");
+      if(dp1->d_name[0] != '.' && extn != NULL && strlen(extn) == 5)
+	{
+	  int t;
+	  char *tmps1=
+	    (char *) malloc ((strlen (tmpName) + strlen (dp1->d_name) + 2) *
+			     sizeof (char));
+	  sprintf (tmps1, "%s/%s", tmpName, dp1->d_name);
+	  char *tmpsn = zStrdup (dp1->d_name);
+	  tmpsn[strlen (tmpsn) - 5] = 0;
+	  service* s1 = (service *) malloc (SERVICE_SIZE);
+	  if (s1 == NULL)
+	    {
+	      setMapInMaps(m,"lenv","message",_("Unable to allocate memory."));
+	      setMapInMaps(m,"lenv","type","InternalError");
+	      return -2;
+	    }
+	  t = readServiceFile (m, tmps1, &s1, tmpsn);
+	  free (tmpsn);
+	  if (t < 0)
+	    {
+	      map *tmp00 = getMapFromMaps (m, "lenv", "message");
+	      char tmp01[1024];
+	      if (tmp00 != NULL)
+		sprintf (tmp01, _("Unable to parse the ZCFG file: %s (%s)"),
+			 dp1->d_name, tmp00->value);
+	      else
+		sprintf (tmp01, _("Unable to parse the ZCFG file: %s."),
+			 dp1->d_name);
+	      setMapInMaps(m,"lenv","message",tmp01);
+	      setMapInMaps(m,"lenv","type","InternalError");
+	      return -1;
+	    }
+	  if(strncasecmp(registryKeys[i],"implementation",14)==0){
+	    inheritance(*r,&s1);
+	  }
+	  addServiceToRegistry(r,registryKeys[i],s1);
+	  freeService (&s1);
+	  free (s1);
+	  scount++;
+	}
+    }
+    (void) closedir (dirp1);
+  }
+  return 0;
+}
+
+#ifdef WIN32
+/**
+ * Create a KVP request for executing background task.
+ * TODO: use the XML request in case of input POST request.
+ *
+ * @param m the maps containing the parameters from the main.cfg file
+ * @param length the total length of the KVP parameters
+ * @param type
+ */
+char* getMapsAsKVP(maps* m,int length,int type){
+  char *dataInputsKVP=(char*) malloc(length*sizeof(char));
+  char *dataInputsKVPi=NULL;
+  maps* curs=m;
+  int i=0;
+  while(curs!=NULL){
+    map *inRequest=getMap(curs->content,"inRequest");
+    map *hasLength=getMap(curs->content,"length");
+    if((inRequest!=NULL && strncasecmp(inRequest->value,"true",4)==0) ||
+       inRequest==NULL){
+      if(i==0)
+	if(type==0){
+	  sprintf(dataInputsKVP,"%s=",curs->name);
+	  if(hasLength!=NULL){
+	    dataInputsKVPi=(char*)malloc((strlen(curs->name)+2)*sizeof(char));
+	    sprintf(dataInputsKVPi,"%s=",curs->name);
+	  }
+	}
+	else
+	  sprintf(dataInputsKVP,"%s",curs->name);
+      else{
+	char *temp=zStrdup(dataInputsKVP);
+	if(type==0)
+	  sprintf(dataInputsKVP,"%s;%s=",temp,curs->name);
+	else
+	  sprintf(dataInputsKVP,"%s;%s",temp,curs->name);
+      }
+      map* icurs=curs->content;
+      if(type==0){
+	char *temp=zStrdup(dataInputsKVP);
+	if(getMap(curs->content,"xlink:href")!=NULL)
+	  sprintf(dataInputsKVP,"%sReference",temp);
+	else{
+	  if(hasLength!=NULL){
+	    int j;
+	    for(j=0;j<atoi(hasLength->value);j++){
+	      map* tmp0=getMapArray(curs->content,"value",j);
+	      if(j==0)
+		free(temp);
+	      temp=zStrdup(dataInputsKVP);
+	      if(j==0)
+		sprintf(dataInputsKVP,"%s%s",temp,tmp0->value);
+	      else
+		sprintf(dataInputsKVP,"%s;%s%s",temp,dataInputsKVPi,tmp0->value);
+	    }
+	  }
+	  else
+	    sprintf(dataInputsKVP,"%s%s",temp,icurs->value);
+	}
+	free(temp);
+      }
+      while(icurs!=NULL){
+	if(strncasecmp(icurs->name,"value",5)!=0 &&
+	   strncasecmp(icurs->name,"mimeType_",9)!=0 &&
+	   strncasecmp(icurs->name,"dataType_",9)!=0 &&
+	   strncasecmp(icurs->name,"size",4)!=0 &&
+	   strncasecmp(icurs->name,"length",4)!=0 &&
+	   strncasecmp(icurs->name,"isArray",7)!=0 &&
+	   strcasecmp(icurs->name,"Reference")!=0 &&
+	   strcasecmp(icurs->name,"minOccurs")!=0 &&
+	   strcasecmp(icurs->name,"maxOccurs")!=0 &&
+	   strncasecmp(icurs->name,"fmimeType",9)!=0 &&
+	   strcasecmp(icurs->name,"inRequest")!=0){
+	  char *itemp=zStrdup(dataInputsKVP);
+	  if(strcasecmp(icurs->name,"xlink:href")!=0)
+	    sprintf(dataInputsKVP,"%s@%s=%s",itemp,icurs->name,icurs->value);
+	  else
+	    sprintf(dataInputsKVP,"%s@%s=%s",itemp,icurs->name,url_encode(icurs->value));
+	  free(itemp);
+	}
+	icurs=icurs->next;
+      }
+    }
+    curs=curs->next;
+    i++;
+  }
+  return dataInputsKVP;
+}
+#endif
diff --git a/zoo-project/zoo-kernel/server_internal.h b/zoo-project/zoo-kernel/server_internal.h
new file mode 100644
index 0000000..6ff451b
--- /dev/null
+++ b/zoo-project/zoo-kernel/server_internal.h
@@ -0,0 +1,73 @@
+/*
+ * Author : Gérald Fenoy
+ *
+ *  Copyright 2008-2015 GeoLabs SARL. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifdef WIN32
+#pragma comment(lib, "rpcrt4.lib")
+#endif
+
+#include "ulinet.h"
+#include "service.h"
+#include <openssl/sha.h>
+#include <openssl/md5.h>
+#include <openssl/hmac.h>
+#include <openssl/evp.h>
+#include <openssl/bio.h>
+#include <openssl/buffer.h>
+
+extern   int conf_read(const char*,maps*);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <libxml/parser.h>
+#include <libxml/xpath.h>
+
+  char *get_uuid();  
+  char *base64(const char*,int);
+  char *base64d(const char*,int,int*);
+  void readBase64(map **);
+  char *url_decode(char *);
+  int getVersionId(const char*);
+  void readGeneratedFile(maps*,map*,char*);
+  int getServiceFromYAML(maps*,char*,service**,char *name);
+  char* addDefaultValues(maps**,elements*,maps*,int,map**);
+  char* getEncoding(maps*);
+  void parseIdentifier(maps*,char*,char*,char*);
+  void dumpMapsValuesToFiles(maps**,maps**);
+  void runDismiss(maps*,char*);
+  void runGetStatus(maps*,char*,char*);
+
+  int isValidLang(maps*,const char*);
+  
+  char* getLastErrorMessage();
+  int readServiceFile (maps *, char *, service **, char *);
+  int createRegistry (maps*,registry **,char *);
+
+#ifdef WIN32
+  char* getMapsAsKVP(maps*,int,int);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/zoo-project/zoo-kernel/service.c b/zoo-project/zoo-kernel/service.c
new file mode 100644
index 0000000..e66d0cd
--- /dev/null
+++ b/zoo-project/zoo-kernel/service.c
@@ -0,0 +1,1451 @@
+/*
+ * Author : Gérald FENOY
+ *
+ * Copyright (c) 2015 GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "service.h"
+
+#ifdef _MSC_VER
+#include <stdarg.h>
+/**
+ * snprintf for Visual Studio compiler.
+ *
+ * See https://dxr.mozilla.org/mozilla-central/source/media/mtransport/third_party/nrappkit/src/util/util.c
+ */
+int snprintf(char *buffer, size_t n, const char *format, ...)
+{
+  va_list argp;
+  int ret;
+  va_start(argp, format);
+  ret = _vscprintf(format, argp);
+  vsnprintf_s(buffer, n, _TRUNCATE, format, argp);
+  va_end(argp);
+  return ret;
+}
+#endif
+
+/**
+ * Dump a map on stderr
+ *
+ * @param t the map to dump
+ */
+void _dumpMap(map* t){
+  if(t!=NULL){
+    fprintf(stderr,"%s: %s\n",t->name,t->value);
+    fflush(stderr);
+  }else{
+    fprintf(stderr,"NULL\n");
+    fflush(stderr);
+  }
+}
+
+/**
+ * Dump a map on stderr, see _dumpMap()
+ *
+ * @param t the map to dump
+ */
+void dumpMap(map* t){
+  map* tmp=t;
+  while(tmp!=NULL){
+    _dumpMap(tmp);
+    tmp=tmp->next;
+  }
+}
+
+/**
+ * Dump a map to a file
+ *
+ * @param t the map to dump to file
+ * @param file the file to store the map
+ */
+void dumpMapToFile(map* t,FILE* file){
+  map* tmp=t;
+  while(tmp!=NULL){
+    fprintf(file,"%s = %s\n",tmp->name,tmp->value);
+    tmp=tmp->next;
+  }
+}
+
+/**
+ * Dump a maps on stderr, see dumpMap().
+ *
+ * @param m the map to dump
+ */
+void dumpMaps(maps* m){
+  maps* tmp=m;
+  while(tmp!=NULL){
+    fprintf(stderr,"MAP => [%s] \n",tmp->name);
+    dumpMap(tmp->content);
+    tmp=tmp->next;
+  }
+}
+
+/**
+ * Dump a maps to a file, see dumpMapToFile().
+ *
+ * @param m the map to dump
+ * @param file_path the full path to the file name to store the map
+ */
+void dumpMapsToFile(maps* m,char* file_path,int limit){
+  FILE* file=fopen(file_path,"w+");
+  maps* tmp=m;
+  int cnt=0;
+  while(tmp!=NULL){
+    fprintf(file,"[%s]\n",tmp->name);
+    dumpMapToFile(tmp->content,file);
+    fflush(file);
+    tmp=tmp->next;
+    cnt++;
+    if(limit>=0 && cnt==limit)
+      tmp=NULL;
+  }
+  fflush(file);
+  fclose(file);
+}
+
+/**
+ * Create a new map
+ *
+ * @param name the key to add to the map
+ * @param value the corresponding value to add to the map
+ * @return the allocated map
+ */
+map* createMap(const char* name,const char* value){
+  map* tmp=(map *)malloc(MAP_SIZE);
+  tmp->name=zStrdup(name);
+  tmp->value=zStrdup(value);
+  tmp->next=NULL;
+  return tmp;
+}
+
+/**
+ * Count number of map in a map
+ *
+ * @param m the maps to count
+ * @return number of map in a map
+ */
+int count(map* m){
+  map* tmp=m;
+  int c=0;
+  while(tmp!=NULL){
+    c++;
+    tmp=tmp->next;
+  }
+  return c;
+}
+
+/**
+ * Verify if a key exist in a map
+ *
+ * @param m the map to search for the key
+ * @param key the key to search in the map
+ * @return true if the key wwas found, false in other case
+ */
+bool hasKey(map* m,const char *key){
+  map* tmp=m;
+  while(tmp!=NULL){
+    if(strcasecmp(tmp->name,key)==0)
+      return true;
+    tmp=tmp->next;
+  }
+#ifdef DEBUG_MAP
+  fprintf(stderr,"NOT FOUND \n");
+#endif
+  return false;
+}
+
+/**
+ * Access a specific maps
+ *
+ * @param m the maps to search for the key
+ * @param key the key to search in the maps
+ * @return a pointer on the maps found or NULL if not found
+ */
+maps* getMaps(maps* m,const char *key){
+  maps* tmp=m;
+  while(tmp!=NULL){
+    if(strcasecmp(tmp->name,key)==0){
+      return tmp;
+    }
+    tmp=tmp->next;
+  }
+  return NULL;
+}
+
+/**
+ * Access a specific map
+ *
+ * @param m the map to search for the key
+ * @param key the key to search in the map
+ * @return a pointer on the map found or NULL if not found
+ */
+map* getMap(map* m,const char *key){
+  map* tmp=m;
+  while(tmp!=NULL){
+    if(strcasecmp(tmp->name,key)==0){
+      return tmp;
+    }
+    tmp=tmp->next;
+  }
+  return NULL;
+}
+
+
+/**
+ * Access the last map
+ *
+ * @param m the map to search for the lastest map
+ * @return a pointer on the lastest map found or NULL if not found
+ */
+map* getLastMap(map* m){
+  map* tmp=m;
+  while(tmp!=NULL){
+    if(tmp->next==NULL){
+      return tmp;
+    }
+    tmp=tmp->next;
+  }
+  return NULL;
+}
+
+/**
+ * Access a specific map from a maps
+ *
+ * @param m the maps to search for the key
+ * @param key the key to search in the maps
+ * @param subkey the key to search in the map (found for the key, if any)
+ * @return a pointer on the map found or NULL if not found
+ */
+map* getMapFromMaps(maps* m,const char* key,const char* subkey){
+  maps* _tmpm=getMaps(m,key);
+  if(_tmpm!=NULL){
+    map* _ztmpm=getMap(_tmpm->content,subkey);
+    return _ztmpm;
+  }
+  else return NULL;
+}
+
+/**
+ * Free allocated memory of a map.
+ * Require to call free on mo after calling this function.
+ *
+ * @param mo the map to free
+ */
+void freeMap(map** mo){
+  map* _cursor=*mo;
+  if(_cursor!=NULL){
+#ifdef DEBUG
+    fprintf(stderr,"freeMap\n");
+#endif
+    free(_cursor->name);
+    free(_cursor->value);
+    if(_cursor->next!=NULL){
+      freeMap(&_cursor->next);
+      free(_cursor->next);
+    }
+  }
+}
+
+/**
+ * Free allocated memory of a maps.
+ * Require to call free on mo after calling this function.
+ *
+ * @param mo the maps to free
+ */
+void freeMaps(maps** mo){
+  maps* _cursor=*mo;
+  if(_cursor && _cursor!=NULL){
+#ifdef DEBUG
+    fprintf(stderr,"freeMaps\n");
+#endif
+    free(_cursor->name);
+    if(_cursor->content!=NULL){
+      freeMap(&_cursor->content);
+      free(_cursor->content);
+    }
+    if(_cursor->next!=NULL){
+      freeMaps(&_cursor->next);
+      free(_cursor->next);
+    }
+  }
+}
+
+/**
+ * Verify if an elements contains a name equal to the given key.
+ *
+ * @param e the elements to search for the key
+ * @param key the elements name to search
+ * @return true if the elements contains the name, false in other cases.
+ */ 
+bool hasElement(elements* e,const char* key){
+  elements* tmp=e;
+  while(tmp!=NULL){
+    if(strcasecmp(key,tmp->name)==0)
+      return true;
+    tmp=tmp->next;
+  }
+  return false;
+}
+
+/**
+ * Access a specific elements named key.
+ *
+ * @param m the elements to search
+ * @param key the elements name to search
+ * @return a pointer to the specific element if found, NULL in other case.
+ */ 
+elements* getElements(elements* m,char *key){
+  elements* tmp=m;
+  while(tmp!=NULL){
+    if(strcasecmp(tmp->name,key)==0)
+      return tmp;
+    tmp=tmp->next;
+  }
+  return NULL;
+}
+
+/**
+ * Free allocated memory of an iotype.
+ * Require to call free on i after calling this function.
+ *
+ * @param i the iotype to free
+ */
+void freeIOType(iotype** i){
+  iotype* _cursor=*i;
+  if(_cursor!=NULL){
+    if(_cursor->next!=NULL){
+      freeIOType(&_cursor->next);
+      free(_cursor->next);
+    }
+    freeMap(&_cursor->content);
+    free(_cursor->content);
+  }
+}
+
+/**
+ * Free allocated memory of an elements.
+ * Require to call free on e after calling this function.
+ *
+ * @param e the iotype to free
+ */
+void freeElements(elements** e){
+  elements* tmp=*e;
+  if(tmp!=NULL){
+    if(tmp->name!=NULL)
+      free(tmp->name);
+    freeMap(&tmp->content);
+    if(tmp->content!=NULL)
+      free(tmp->content);
+    freeMap(&tmp->metadata);
+    if(tmp->metadata!=NULL)
+      free(tmp->metadata);
+    if(tmp->format!=NULL)
+      free(tmp->format);
+    freeIOType(&tmp->defaults);
+    if(tmp->defaults!=NULL)
+      free(tmp->defaults);
+    freeIOType(&tmp->supported);
+    if(tmp->supported!=NULL){
+      free(tmp->supported);
+    }
+    freeElements(&tmp->next);
+    if(tmp->next!=NULL)
+      free(tmp->next);
+  }
+}
+
+/**
+ * Free allocated memory of a service.
+ * Require to call free on e after calling this function.
+ *
+ * @param s the service to free
+ */
+void freeService(service** s){
+  service* tmp=*s;
+  if(tmp!=NULL){
+    if(tmp->name!=NULL)
+      free(tmp->name);
+    freeMap(&tmp->content);
+    if(tmp->content!=NULL)
+      free(tmp->content);
+    freeMap(&tmp->metadata);
+    if(tmp->metadata!=NULL)
+      free(tmp->metadata);
+    freeElements(&tmp->inputs);
+    if(tmp->inputs!=NULL)
+      free(tmp->inputs);
+    freeElements(&tmp->outputs);
+    if(tmp->outputs!=NULL)
+      free(tmp->outputs);
+  }
+}
+
+/**
+ * Add key value pair to an existing map.
+ *
+ * @param m the map to add the KVP
+ * @param n the key to add
+ * @param v the corresponding value to add
+ */
+void addToMap(map* m,const char* n,const char* v){
+  if(hasKey(m,n)==false){
+    map* _cursor=m;
+    while(_cursor->next!=NULL){
+      _cursor=_cursor->next;
+    }
+    _cursor->next=createMap(n,v);
+  }
+  else{
+    map *tmp=getMap(m,n);
+    if(tmp->value!=NULL)
+      free(tmp->value);
+    tmp->value=zStrdup(v);
+  }
+}
+
+/**
+ * Add a key and an integer value to an existing map.
+ *
+ * @param m the map to add the KVP
+ * @param n the key to add
+ * @param v the corresponding value to add
+ */
+void addIntToMap(map* m,const char* n,const int v){
+  char svalue[10];
+  sprintf(svalue,"%d",v);
+  if(hasKey(m,n)==false){
+    map* _cursor=m;
+    while(_cursor->next!=NULL){
+      _cursor=_cursor->next;
+    }
+    _cursor->next=createMap(n,svalue);
+  }
+  else{
+    map *tmp=getMap(m,n);
+    if(tmp->value!=NULL)
+      free(tmp->value);
+    tmp->value=zStrdup(svalue);
+  }
+}
+
+/**
+ * Add a key and a binary value to an existing map.
+ *
+ * @param m the map to add the KVP
+ * @param n the key to add
+ * @param v the corresponding value to add
+ * @param size the size of the given value
+ */
+void addToMapWithSize(map* m,const char* n,const char* v,int size){
+  if(hasKey(m,n)==false){
+    map* _cursor=m;
+    if(_cursor!=NULL){
+      addToMap(m,n,"");
+    }else{
+      m=createMap(n,"");
+    }
+  }
+  char sname[10]="size";
+  if(strlen(n)>5)
+    sprintf(sname,"size_%s",n+6);
+  map *tmp=getMap(m,n);
+  if(tmp->value!=NULL)
+    free(tmp->value);
+  tmp->value=(char*)malloc((size+1)*sizeof(char));
+  memmove(tmp->value,v,size*sizeof(char));
+  tmp->value[size]=0;
+  char sin[128];
+  sprintf(sin,"%d",size);
+  addToMap(m,sname,sin);
+}
+
+/**
+ * Add a map at the end of another map.
+ *
+ * @param mo the map to add mi
+ * @param mi the map to add to mo
+ */
+void addMapToMap(map** mo,map* mi){
+  map* tmp=mi;
+  map* _cursor=*mo;
+  while(tmp!=NULL){
+    if(_cursor==NULL){
+      *mo=createMap(tmp->name,tmp->value);
+      (*mo)->next=NULL;
+    }
+    else{
+#ifdef DEBUG
+      fprintf(stderr,"_CURSOR\n");
+      dumpMap(_cursor);
+#endif
+      while(_cursor->next!=NULL)
+	_cursor=_cursor->next;
+      map* tmp1=getMap(*mo,tmp->name);
+      if(tmp1==NULL){
+	_cursor->next=createMap(tmp->name,tmp->value);
+      }
+      else{
+	addToMap(*mo,tmp->name,tmp->value);
+      }
+    }
+    _cursor=*mo;
+    tmp=tmp->next;
+#ifdef DEBUG
+    fprintf(stderr,"MO\n");
+    dumpMap(*mo);
+#endif
+  }
+}
+
+/**
+ * Add a map to iotype.
+ *
+ * @param io the iotype to add the map
+ * @param mi the map to add to io
+ */
+void addMapToIoType(iotype** io,map* mi){
+  iotype* tmp=*io;
+  while(tmp->next!=NULL){
+    tmp=tmp->next;
+  }
+  tmp->next=(iotype*)malloc(IOTYPE_SIZE);
+  tmp->next->content=NULL;
+  addMapToMap(&tmp->next->content,mi);
+  tmp->next->next=NULL;
+}
+
+/**
+ * Access a specific map or set its value.
+ *
+ * @param m the map to search for the key
+ * @param key the key to search/add in the map
+ * @param value the value to add if the key does not exist
+ * @return a pointer on the map found or NULL if not found
+ */
+map* getMapOrFill(map** m,const char *key,const char* value){
+  map* tmp=*m;
+  map* tmpMap=getMap(tmp,key);
+  if(tmpMap==NULL){
+    if(tmp!=NULL){
+      addToMap((*m),key,value);
+    }
+    else
+      (*m)=createMap(key,value);
+    tmpMap=getMap(*m,key);
+  }
+  return tmpMap;
+}
+
+/**
+ * Verify if a map is contained in another map.
+ *
+ * @param m the map to search for i
+ * @param i the map to search in m
+ * @return true if i was found in m, false in other case
+ */
+bool contains(map* m,map* i){
+  while(i!=NULL){      
+    if(strcasecmp(i->name,"value")!=0 &&
+       strcasecmp(i->name,"xlink:href")!=0 &&
+       strcasecmp(i->name,"useMapServer")!=0 &&
+       strcasecmp(i->name,"asReference")!=0){
+      map *tmp;
+      if(hasKey(m,i->name) && (tmp=getMap(m,i->name))!=NULL && 
+	 strcasecmp(i->value,tmp->value)!=0)
+	return false;
+    }
+    i=i->next;
+  }
+  return true;
+}
+
+/**
+ * Access a specific iotype from an elements.
+ *
+ * @param e the elements to search for the name
+ * @param name the name to search in the elements e
+ * @param values the map to verify it was contained in the defaults or 
+ *  supported content of the elements e
+ * @return a pointer on the iotype found or NULL if not found
+ */
+iotype* getIoTypeFromElement(elements* e,char *name, map* values){
+  elements* cursor=e;
+  while(cursor!=NULL){
+    if(strcasecmp(cursor->name,name)==0){
+      if(contains(cursor->defaults->content,values)==true)
+	return cursor->defaults;
+      else{
+	iotype* tmp=cursor->supported;
+	while(tmp!=NULL){
+	  if(contains(tmp->content,values)==true)
+	    return tmp;	    
+	  tmp=tmp->next;
+	}
+      }
+    }
+    cursor=cursor->next;
+  }
+  return NULL;
+}
+
+/**
+ * Load binary values from a map (in) and add them to another map (out)
+ *
+ * @param out the map to add binaries values
+ * @param in the map containing the binary values to add ti out
+ * @param pos index of the binary in an array (in case of "MapArray")
+ */
+void loadMapBinary(map** out,map* in,int pos){
+  map* size=getMap(in,"size");
+  map *lout=*out;
+  if(size!=NULL && pos>0){
+    char tmp[11];
+    sprintf(tmp,"size_%d",pos);
+    size=getMap(in,tmp);
+    sprintf(tmp,"value_%d",pos);
+    map* tmpVin=getMap(in,tmp);
+    map* tmpVout=getMap(lout,tmp);
+    free(tmpVout->value);
+    tmpVout->value=(char*)malloc((atoi(size->value)+1)*sizeof(char));
+    memmove(tmpVout->value,tmpVin->value,atoi(size->value)*sizeof(char));
+    tmpVout->value[atoi(size->value)]=0;
+  }else{
+    if(size!=NULL){
+      map* tmpVin=getMap(in,"value");
+      map* tmpVout=getMap(lout,"value");
+      free(tmpVout->value);
+      tmpVout->value=(char*)malloc((atoi(size->value)+1)*sizeof(char));
+      memmove(tmpVout->value,tmpVin->value,atoi(size->value)*sizeof(char));
+      tmpVout->value[atoi(size->value)]=0;
+    }
+  }
+}
+  
+/**
+ * Load binary values from a map (in) and add them to another map (out).
+ * This function will take care of MapArray.
+ * @see loadMapBinary
+ *
+ * @param out the map to add binaries values
+ * @param in the map containing the binary values to add ti out
+ */
+void loadMapBinaries(map** out,map* in){
+  map* size=getMap(in,"size");
+  map* length=getMap(in,"length");
+  if(length!=NULL){
+    int len=atoi(length->value);
+    int i=0;
+    for(i=0;i<len;i++){
+      loadMapBinary(out,in,i);
+    }
+  }
+  else
+    if(size!=NULL)
+      loadMapBinary(out,in,-1);
+}
+
+/**
+ * Duplicate a Maps
+ * 
+ * @param mo the maps to clone
+ * @return the allocated maps containing a copy of the mo maps
+ */
+maps* dupMaps(maps** mo){
+  maps* _cursor=*mo;
+  maps* res=NULL;
+  if(_cursor!=NULL){
+    res=(maps*)malloc(MAPS_SIZE);
+    res->name=zStrdup(_cursor->name);
+    res->content=NULL;
+    res->next=NULL;
+    map* mc=_cursor->content;
+    if(mc!=NULL){
+      addMapToMap(&res->content,mc);
+      loadMapBinaries(&res->content,mc);
+    }
+    res->next=dupMaps(&_cursor->next);
+  }
+  return res;
+}
+
+/**
+ * Add a maps at the end of another maps.
+ *
+ * @see addMapToMap, dupMaps, getMaps
+ * @param mo the maps to add mi
+ * @param mi the maps to add to mo
+ */
+void addMapsToMaps(maps** mo,maps* mi){
+  maps* tmp=mi;
+  maps* _cursor=*mo;
+  while(tmp!=NULL){
+    if(_cursor==NULL){
+      *mo=dupMaps(&mi);
+    }
+    else{
+      while(_cursor->next!=NULL)
+	_cursor=_cursor->next;
+      maps* tmp1=getMaps(*mo,tmp->name);
+      if(tmp1==NULL)
+	_cursor->next=dupMaps(&tmp);
+      else
+	addMapToMap(&tmp1->content,tmp->content);
+      _cursor=*mo;
+    }
+    tmp=tmp->next;
+  }
+}
+
+/**
+ * Access a specific map array element
+ *
+ * @param m the map to search for the key
+ * @param key the key to search in the map
+ * @param index of the MapArray 
+ * @return a pointer on the map found or NULL if not found
+ */
+map* getMapArray(map* m,const char* key,int index){
+  char tmp[1024];
+  if(index>0)
+    sprintf(tmp,"%s_%d",key,index);
+  else
+    sprintf(tmp,"%s",key);
+#ifdef DEBUG
+  fprintf(stderr,"** KEY %s\n",tmp);
+#endif
+  map* tmpMap=getMap(m,tmp);
+#ifdef DEBUG
+  if(tmpMap!=NULL)
+    dumpMap(tmpMap);
+#endif
+  return tmpMap;
+}
+
+/**
+ * Add a key value in a MapArray for a specific index
+ *
+ * @param m the map to search for the key
+ * @param key the key to search in the map
+ * @param index the index of the MapArray 
+ * @param value the value to set in the MapArray 
+ * @return a pointer on the map found or NULL if not found
+ */
+void setMapArray(map* m,const char* key,int index,const char* value){
+  char tmp[1024];
+  if(index>0){
+    sprintf(tmp,"%s_%d",key,index);
+    map* len=getMap(m,"length");
+    if((len!=NULL && atoi(len->value)<index+1) || len==NULL){
+      char tmp0[5];
+      sprintf(tmp0,"%d",index+1);
+      addToMap(m,"length",tmp0);
+    }
+  }
+  else
+    sprintf(tmp,"%s",key);
+  map* tmpSize=getMapArray(m,"size",index);
+  if(tmpSize!=NULL && strncasecmp(key,"value",5)==0){
+#ifdef DEBUG
+    fprintf(stderr,"%s\n",tmpSize->value);
+#endif
+    map* ptr=getMapOrFill(&m,tmp,(char *)"");
+    free(ptr->value);
+    ptr->value=(char*)malloc((atoi(tmpSize->value)+1)*sizeof(char));
+    memcpy(ptr->value,value,atoi(tmpSize->value)); 
+  }
+  else
+    addToMap(m,tmp,value);
+}
+
+/**
+ * Access the map "type"
+ *
+ * @param mt the map
+ * @return a pointer on the map for mimeType/dataType/CRS if found, NULL in
+ *  other case
+ */
+map* getMapType(map* mt){
+  map* tmap=getMap(mt,(char *)"mimeType");
+  if(tmap==NULL){
+    tmap=getMap(mt,"dataType");
+    if(tmap==NULL){
+      tmap=getMap(mt,"CRS");
+    }
+  }
+#ifdef DEBUG
+  dumpMap(tmap);
+#endif
+  return tmap;
+}
+
+/**
+ * Add a Maps containing a MapArray to a Maps
+ *
+ * @see getMapType
+ * @param mo the maps
+ * @param mi the maps
+ * @param typ the map "type"
+ * @return 
+ */
+int addMapsArrayToMaps(maps** mo,maps* mi,char* typ){
+  maps* tmp=mi;    
+  maps* _cursor=getMaps(*mo,tmp->name);
+
+  if(_cursor==NULL)
+    return -1;
+
+  map* tmpLength=getMap(_cursor->content,"length");
+  char tmpLen[10];
+  int len=1;
+  if(tmpLength!=NULL){
+    len=atoi(tmpLength->value);
+  }
+
+  char *tmpV[12]={
+    (char*)"size",
+    (char*)"value",
+    (char*)"uom",
+    (char*)"Reference",
+    (char*)"Order",
+    (char*)"cache_file",
+    (char*)"fmimeType",
+    (char*)"xlink:href",
+    typ,
+    (char*)"schema",
+    (char*)"encoding",
+    (char*)"isCached"
+  };
+  sprintf(tmpLen,"%d",len+1);
+  addToMap(_cursor->content,"length",tmpLen);
+  int i=0;
+  for(i=0;i<12;i++){
+    map* tmpVI=getMap(tmp->content,tmpV[i]);
+    if(tmpVI!=NULL){
+#ifdef DEBUG
+      fprintf(stderr,"%s = %s\n",tmpV[i],tmpVI->value);
+#endif
+      setMapArray(_cursor->content,tmpV[i],len,tmpVI->value);
+    }
+  }
+    
+  addToMap(_cursor->content,"isArray","true");
+  return 0;
+}
+
+/**
+ * Set a key value pair to a map contained in a Maps
+ *
+ * @param m the maps
+ * @param key the maps name
+ * @param subkey the map name included in the maps corresponding to key
+ * @param value the corresponding value to add in the map
+ */
+void setMapInMaps(maps* m,const char* key,const char* subkey,const char *value){
+  maps* _tmpm=getMaps(m,key);
+  if(_tmpm!=NULL){
+    map* _ztmpm=getMap(_tmpm->content,subkey);
+    if(_ztmpm!=NULL){
+      if(_ztmpm->value!=NULL)
+	free(_ztmpm->value);
+      _ztmpm->value=zStrdup(value);
+    }else{
+      maps *tmp=(maps*)malloc(MAPS_SIZE);
+      tmp->name=zStrdup(key);
+      tmp->content=createMap(subkey,value);
+      tmp->next=NULL;
+      addMapsToMaps(&_tmpm,tmp);
+      freeMaps(&tmp);
+      free(tmp);
+    }
+  }else{
+    maps *tmp=(maps*)malloc(MAPS_SIZE);
+    tmp->name=zStrdup(key);
+    tmp->content=createMap(subkey,value);
+    tmp->next=NULL;
+    addMapsToMaps(&m,tmp);
+    freeMaps(&tmp);
+    free(tmp);
+  }
+}
+
+/**
+ * Dump an elements on stderr
+ *
+ * @param e the elements to dump
+ */
+void dumpElements(elements* e){
+  elements* tmp=e;
+  while(tmp!=NULL){
+    fprintf(stderr,"ELEMENT [%s]\n",tmp->name);
+    fprintf(stderr," > CONTENT [%s]\n",tmp->name);
+    dumpMap(tmp->content);
+    fprintf(stderr," > METADATA [%s]\n",tmp->name);
+    dumpMap(tmp->metadata);
+    fprintf(stderr," > FORMAT [%s]\n",tmp->format);
+    iotype* tmpio=tmp->defaults;
+    int ioc=0;
+    while(tmpio!=NULL){
+      fprintf(stderr," > DEFAULTS [%s] (%i)\n",tmp->name,ioc);
+      dumpMap(tmpio->content);
+      tmpio=tmpio->next;
+      ioc++;
+    }
+    tmpio=tmp->supported;
+    ioc=0;
+    while(tmpio!=NULL){
+      fprintf(stderr," > SUPPORTED [%s] (%i)\n",tmp->name,ioc);
+      dumpMap(tmpio->content);
+      tmpio=tmpio->next;
+      ioc++;
+    }
+    fprintf(stderr,"------------------\n");
+    tmp=tmp->next;
+  }
+}
+
+/**
+ * Dump an elements on stderr using the YAML syntaxe
+ *
+ * @param e the elements to dump
+ */
+void dumpElementsAsYAML(elements* e){
+  elements* tmp=e;
+  int i;
+  while(tmp!=NULL){
+    for(i=0;i<2;i++)
+      fprintf(stderr," ");
+    fprintf(stderr,"%s:\n",tmp->name);
+    map* mcurs=tmp->content;
+    while(mcurs!=NULL){
+      for(i=0;i<4;i++)
+	fprintf(stderr," ");
+      _dumpMap(mcurs);
+      mcurs=mcurs->next;
+    }
+    mcurs=tmp->metadata;
+    if(mcurs!=NULL){
+      for(i=0;i<4;i++)
+	fprintf(stderr," ");
+      fprintf(stderr,"MetaData:\n");
+      while(mcurs!=NULL){
+	for(i=0;i<6;i++)
+	  fprintf(stderr," ");
+	_dumpMap(mcurs);
+	mcurs=mcurs->next;
+      }
+    }
+    for(i=0;i<4;i++)
+      fprintf(stderr," ");
+    fprintf(stderr,"%s:\n",tmp->format);
+    iotype* tmpio=tmp->defaults;
+    int ioc=0;
+    while(tmpio!=NULL){
+      for(i=0;i<6;i++)
+	fprintf(stderr," ");
+      fprintf(stderr,"default:\n");
+      mcurs=tmpio->content;
+      while(mcurs!=NULL){
+	for(i=0;i<8;i++)
+	  fprintf(stderr," ");
+	if(strcasecmp(mcurs->name,"range")==0){
+	  fprintf(stderr,"range: \"%s\"\n",mcurs->value);
+	}else
+	  _dumpMap(mcurs);
+	mcurs=mcurs->next;
+      }
+      tmpio=tmpio->next;
+      ioc++;
+    }
+    tmpio=tmp->supported;
+    ioc=0;
+    while(tmpio!=NULL){
+      for(i=0;i<6;i++)
+	fprintf(stderr," ");
+      fprintf(stderr,"supported:\n");
+      mcurs=tmpio->content;
+      while(mcurs!=NULL){
+	for(i=0;i<8;i++)
+	  fprintf(stderr," ");
+	if(strcasecmp(mcurs->name,"range")==0){
+	  fprintf(stderr,"range: \"%s\"\n",mcurs->value);
+	}else
+	  _dumpMap(mcurs);
+	mcurs=mcurs->next;
+      }
+      tmpio=tmpio->next;
+      ioc++;
+    }
+    tmp=tmp->next;
+  }
+}
+
+/**
+ * Duplicate an elements
+ * 
+ * @param e the elements to clone
+ * @return the allocated elements containing a copy of the elements e
+ */
+elements* dupElements(elements* e){
+  elements* cursor=e;
+  elements* tmp=NULL;
+  if(cursor!=NULL){
+#ifdef DEBUG
+    fprintf(stderr,">> %s %i\n",__FILE__,__LINE__);
+    dumpElements(e);
+    fprintf(stderr,">> %s %i\n",__FILE__,__LINE__);
+#endif
+    tmp=(elements*)malloc(ELEMENTS_SIZE);
+    tmp->name=zStrdup(e->name);
+    tmp->content=NULL;
+    addMapToMap(&tmp->content,e->content);
+    tmp->metadata=NULL;
+    addMapToMap(&tmp->metadata,e->metadata);
+    if(e->format!=NULL)
+      tmp->format=zStrdup(e->format);
+    else
+      tmp->format=NULL;
+    if(e->defaults!=NULL){
+      tmp->defaults=(iotype*)malloc(IOTYPE_SIZE);
+      tmp->defaults->content=NULL;
+      addMapToMap(&tmp->defaults->content,e->defaults->content);
+      tmp->defaults->next=NULL;
+#ifdef DEBUG
+      fprintf(stderr,">> %s %i\n",__FILE__,__LINE__);
+      dumpMap(tmp->defaults->content);
+#endif
+    }else
+      tmp->defaults=NULL;
+    if(e->supported!=NULL){
+      tmp->supported=(iotype*)malloc(IOTYPE_SIZE);
+      tmp->supported->content=NULL;
+      addMapToMap(&tmp->supported->content,e->supported->content);
+      tmp->supported->next=NULL;
+      iotype *tmp2=e->supported->next;
+      while(tmp2!=NULL){
+	addMapToIoType(&tmp->supported,tmp2->content);
+#ifdef DEBUG
+	fprintf(stderr,">> %s %i\n",__FILE__,__LINE__);
+	dumpMap(tmp->defaults->content);
+#endif
+	tmp2=tmp2->next;
+      }
+    }
+    else
+      tmp->supported=NULL;
+    tmp->next=dupElements(cursor->next);
+  }
+  return tmp;
+}
+
+/**
+ * Add an elements to another elements.
+ *
+ * @see dupElements
+ * @param m the elements to add the e
+ * @param e the elements to be added to m
+ */
+void addToElements(elements** m,elements* e){
+  elements* tmp=e;
+  if(*m==NULL){
+    *m=dupElements(tmp);
+  }else{
+    addToElements(&(*m)->next,tmp);
+  }
+}
+  
+/**
+ * Dump a service on stderr
+ *
+ * @param s the service to dump
+ */
+void dumpService(service* s){
+  if(s==NULL)
+    return;
+  fprintf(stderr,"++++++++++++++++++\nSERVICE [%s]\n++++++++++++++++++\n",s->name);
+  if(s->content!=NULL){
+    fprintf(stderr,"CONTENT MAP\n");
+    dumpMap(s->content);
+    fprintf(stderr,"CONTENT METADATA\n");
+    dumpMap(s->metadata);
+  }
+  if(s->inputs!=NULL){
+    fprintf(stderr,"INPUT ELEMENTS [%s]\n------------------\n",s->name);
+    dumpElements(s->inputs);
+  }
+  if(s->outputs!=NULL){
+    fprintf(stderr,"OUTPUT ELEMENTS [%s]\n------------------\n",s->name);
+    dumpElements(s->outputs);
+  }
+  fprintf(stderr,"++++++++++++++++++\n");
+}
+
+/**
+ * Dump a service on stderr using the YAML syntaxe
+ *
+ * @param s the service to dump
+ */
+void dumpServiceAsYAML(service* s){
+  int i;
+  fprintf(stderr,"# %s\n\n",s->name);
+  if(s->content!=NULL){
+    map* mcurs=s->content;
+    dumpMap(mcurs);
+    mcurs=s->metadata;
+    if(mcurs!=NULL){
+      fprintf(stderr,"MetaData:\n");
+      while(mcurs!=NULL){
+	for(i=0;i<2;i++)
+	  fprintf(stderr," ");
+	_dumpMap(mcurs);
+	mcurs=mcurs->next;
+      }
+    }
+  }
+  if(s->inputs!=NULL){
+    fprintf(stderr,"\ninputs:\n");
+    dumpElementsAsYAML(s->inputs);
+  }
+  if(s->outputs!=NULL){
+    fprintf(stderr,"\noutputs:\n");
+    dumpElementsAsYAML(s->outputs);
+  }
+}
+
+/**
+ * Duplicate a service
+ * 
+ * @param s the service to clone
+ * @return the allocated service containing a copy of the serfvice s
+ */
+service* dupService(service* s){
+  service *res=(service*)malloc(SERVICE_SIZE);
+  res->name=zStrdup(s->name);
+  res->content=NULL;
+  addMapToMap(&res->content,s->content);
+  res->metadata=NULL;
+  addMapToMap(&res->metadata,s->metadata);
+  res->inputs=dupElements(s->inputs);
+  res->outputs=dupElements(s->outputs);
+  return res;
+}
+
+/**
+ * Print the registry on stderr.
+ * 
+ * @param r the registry
+ */
+void dumpRegistry(registry* r){
+  registry* p=r;
+  while(p!=NULL){
+    fprintf(stderr,"%s \n",p->name);
+    services* s=p->content;
+    s=p->content;
+    while(s!=NULL){
+      dumpService(s->content);
+      s=s->next;
+    }
+    p=p->next;
+  }
+}
+
+/**
+ * Add a service to the registry
+ *
+ * @param reg the resgitry to add the service
+ * @param name the registry name to update
+ * @param content the service to add
+ */
+bool addServiceToRegistry(registry** reg,char* name,service* content){
+  registry *l=*reg;
+  int isInitial=-1;
+  if(l==NULL){
+    l=(registry*)malloc(REGISTRY_SIZE);
+    isInitial=1;
+  }
+  if(l!=NULL){
+    int hasLevel=-1;
+    while(isInitial<0 && l!=NULL){
+      if(l->name!=NULL && strcasecmp(name,l->name)==0){
+	hasLevel=1;
+	break;
+      }
+      l=l->next;
+    }
+    if(hasLevel<0){
+      if(isInitial<0)
+	l=(registry*)malloc(REGISTRY_SIZE);
+      l->name=zStrdup(name);
+      l->content=NULL;
+      l->next=NULL;
+    }
+    if(l->content==NULL){
+      l->content=(services*)malloc(SERVICES_SIZE);
+      l->content->content=dupService(content);
+      l->content->next=NULL;
+    }
+    else{
+      services* s=l->content;
+      while(s->next!=NULL)
+	s=s->next;
+      s->next=(services*)malloc(SERVICES_SIZE);
+      s->next->content=dupService(content);
+      s->next->next=NULL;
+    }
+    l->next=NULL;
+    if(isInitial>0)
+      *reg=l;
+    else{
+      registry *r=*reg;
+      while(r->next!=NULL)
+	r=r->next;
+      r->next=l;
+      r->next->next=NULL;
+    }
+    return true;
+  }
+  else
+    return false;
+}
+
+/**
+ * Free memory allocated for the registry
+ *
+ * @param r the registry
+ */
+void freeRegistry(registry** r){
+  registry* lr=*r;
+  while(lr!=NULL){
+    services* s=lr->content;
+    free(lr->name);
+    while(s!=NULL){
+      service* s1=s->content;
+      s=s->next;
+      if(s1!=NULL){
+	freeService(&s1);
+	free(s1);
+	s1=NULL;
+      }
+    }
+    lr=lr->next;
+  }    
+}
+
+/**
+ * Access a service in the registry
+ *
+ * @param r the registry
+ * @param level the regitry to search ("concept", "generic" or "implementation")
+ * @param sname the service name
+ * @return the service pointer if a corresponding service was found or NULL
+ */
+service* getServiceFromRegistry(registry* r,char  *level,char* sname){
+  registry *lr=r;
+  while(lr!=NULL){
+    if(strcasecmp(lr->name,level)==0){
+      services* s=lr->content;
+      while(s!=NULL){
+	if(s->content!=NULL && strcasecmp(s->content->name,sname)==0)
+	  return s->content;
+	s=s->next;
+      }
+      break;
+    }
+    lr=lr->next;
+  }
+  return NULL;
+}
+
+/**
+ * Apply inheritance to an out map from a reference in map
+ *
+ * @param out the map to update
+ * @param in the reference map (containing inherited properties)
+ */
+void inheritMap(map** out,map* in){
+  map* content=in;
+  if((*out)==NULL){
+    addMapToMap(out,in);
+    return;
+  }
+  while(content!=NULL){
+    map* cmap=getMap(*out,content->name);
+    if(cmap==NULL)
+      addToMap(*out,content->name,content->value);
+    content=content->next;
+  }
+}
+
+/**
+ * Apply inheritance to an out iotype from a reference in iotype
+ * 
+ * @param out the iotype to update
+ * @param in the reference iotype (containing inherited properties)
+ */
+void inheritIOType(iotype** out,iotype* in){
+  iotype* io=in;
+  iotype* oio=*out;
+  if(io!=NULL){
+    if(*out==NULL){
+      *out=(iotype*)malloc(IOTYPE_SIZE);
+      (*out)->content=NULL;
+      addMapToMap(&(*out)->content,io->content);
+      (*out)->next=NULL;
+      oio=*out;
+      inheritIOType(&oio->next,io->next);
+    }else{
+      inheritIOType(&oio->next,io->next);
+    }
+  }
+}
+
+/**
+ * Apply inheritance to an out elements from a reference in elements
+ * 
+ * @param out the elements to update
+ * @param in the reference elements (containing inherited properties)
+ */
+void inheritElements(elements** out,elements* in){
+  elements* content=in;
+  while(content!=NULL && *out!=NULL){
+    elements* cmap=getElements(*out,content->name);
+    if(cmap==NULL)
+      addToElements(out,content);
+    else{
+      inheritMap(&cmap->content,content->content);
+      inheritMap(&cmap->metadata,content->metadata);
+      if(cmap->format==NULL && content->format!=NULL)
+	cmap->format=zStrdup(content->format);
+      inheritIOType(&cmap->defaults,content->defaults);
+      if(cmap->supported==NULL)
+	inheritIOType(&cmap->supported,content->supported);
+      else{
+	iotype* p=content->supported;
+	while(p!=NULL){
+	  addMapToIoType(&cmap->supported,p->content);
+	  p=p->next;
+	}
+      }
+    }
+    content=content->next;
+  }
+}
+
+/**
+ * Apply inheritance to a service based on a registry
+ * 
+ * @param r the registry storing profiles hierarchy
+ * @param s the service to update depending on its inheritance
+ */
+void inheritance(registry *r,service** s){
+  if(r==NULL)
+    return;
+  service* ls=*s;
+  if(ls->content==NULL)
+    return;
+  map* profile=getMap(ls->content,"extend");
+  map* level=getMap(ls->content,"level");
+  if(profile!=NULL&&level!=NULL){
+    service* s1;
+    if(strncasecmp(level->value,"profile",7)==0)
+      s1=getServiceFromRegistry(r,(char*)"generic",profile->value);
+    else
+      s1=getServiceFromRegistry(r,level->value,profile->value);
+      
+    inheritMap(&ls->content,s1->content);
+    inheritMap(&ls->metadata,s1->metadata);
+    if(ls->inputs==NULL && s1->inputs!=NULL){
+      ls->inputs=dupElements(s1->inputs);
+    }else{
+      inheritElements(&ls->inputs,s1->inputs);
+    }
+    if(ls->outputs==NULL && s1->outputs!=NULL){
+      ls->outputs=dupElements(s1->outputs);
+    }else
+      inheritElements(&ls->outputs,s1->outputs);
+  }
+}
+
+/**
+ * Convert a maps to a char*** (only used for Fortran support)
+ *
+ * @param m the maps to convert
+ * @param c the resulting array
+ */
+void mapsToCharXXX(maps* m,char*** c){
+  maps* tm=m;
+  int i=0;
+  int j=0;
+  char tmp[10][30][1024];
+  memset(tmp,0,1024*10*10);
+  while(tm!=NULL){
+    if(i>=10)
+      break;
+    strcpy(tmp[i][j],"name");
+    j++;
+    strcpy(tmp[i][j],tm->name);
+    j++;
+    map* tc=tm->content;
+    while(tc!=NULL){
+      if(j>=30)
+	break;
+      strcpy(tmp[i][j],tc->name);
+      j++;
+      strcpy(tmp[i][j],tc->value);
+      j++;
+      tc=tc->next;
+    }
+    tm=tm->next;
+    j=0;
+    i++;
+  }
+  memcpy(c,tmp,10*10*1024);
+}
+
+/**
+ * Convert a char*** to a maps (only used for Fortran support)
+ *
+ * @param c the array to convert
+ * @param m the resulting maps
+ */
+void charxxxToMaps(char*** c,maps**m){
+  maps* trorf=*m;
+  int i,j;
+  char tmp[10][30][1024];
+  memcpy(tmp,c,10*30*1024);
+  for(i=0;i<10;i++){
+    if(strlen(tmp[i][1])==0)
+      break;
+    trorf->name=tmp[i][1];
+    trorf->content=NULL;
+    trorf->next=NULL;
+    for(j=2;j<29;j+=2){
+      if(strlen(tmp[i][j+1])==0)
+	break;
+      if(trorf->content==NULL)
+	trorf->content=createMap(tmp[i][j],tmp[i][j+1]);
+      else
+	addToMap(trorf->content,tmp[i][j],tmp[i][j+1]);
+    }
+    trorf=trorf->next;
+  }
+  m=&trorf;
+}
diff --git a/zoo-project/zoo-kernel/service.h b/zoo-project/zoo-kernel/service.h
new file mode 100644
index 0000000..f865819
--- /dev/null
+++ b/zoo-project/zoo-kernel/service.h
@@ -0,0 +1,335 @@
+/*
+ * Author : Gérald FENOY
+ *
+ * Copyright (c) 2009-2015 GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef ZOO_SERVICE_H
+#define ZOO_SERVICE_H 1
+
+#pragma once
+
+#ifdef WIN32
+#define ZOO_DLL_EXPORT __declspec( dllexport )
+#else
+#define ZOO_DLL_EXPORT 
+#endif
+
+#ifdef WIN32
+#ifndef USE_MS
+#define strncasecmp _strnicmp
+#define strcasecmp _stricmp
+//#else
+//#define snprintf sprintf_s
+#endif
+#define zStrdup _strdup
+#define zMkdir _mkdir
+#define zOpen _open
+#define zWrite _write
+#define zSleep Sleep
+#include <sys/timeb.h>
+struct ztimeval {
+  long tv_sec; /* seconds */
+  long tv_usec; /* and microseconds */
+};
+static int zGettimeofday(struct ztimeval* tp, void* tzp)
+{
+  if (tp == 0) {
+    return -1;
+  }
+  
+  struct _timeb theTime;
+  _ftime(&theTime);
+  tp->tv_sec = theTime.time;
+  tp->tv_usec = theTime.millitm * 1000;
+  
+  return 0; // The gettimeofday() function shall return 0 on success
+}
+
+#else
+/**
+ * The crossplatform strdup alias
+ */
+#define zStrdup strdup
+/**
+ * The crossplatform mkdir alias
+ */
+#define zMkdir mkdir
+/**
+ * The crossplatform open alias
+ */
+#define zOpen open
+/**
+ * The crossplatform write alias
+ */
+#define zWrite write
+/**
+ * The crossplatform sleep alias
+ */
+#define zSleep sleep
+/**
+ * The crossplatform gettimeofday alias
+ */
+#define zGettimeofday gettimeofday
+/**
+ * The crossplatform timeval alias
+ */
+#define ztimeval timeval
+#endif 
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef WIN32
+#ifdef USE_MS
+#include <mapserver.h>
+#endif
+#endif
+#include <stdlib.h>
+#include <ctype.h>
+
+#include <stdio.h>
+
+#include <string.h>
+#ifndef WIN32
+#include <ctype.h>
+#ifndef bool
+#define bool int
+#endif
+#ifndef true
+  /**
+   * Local true definition
+   */
+#define true 1
+  /**
+   * Local false definition
+   */
+#define false 0
+#endif
+#endif
+
+/**
+ * The global accepted status for a service
+ */
+#define SERVICE_ACCEPTED 0
+/**
+ * The global started status for a service
+ */
+#define SERVICE_STARTED 1
+/**
+ * The global paused status for a service
+ */
+#define SERVICE_PAUSED 2
+/**
+ * The global succeeded status for a service
+ */
+#define SERVICE_SUCCEEDED 3
+/**
+ * The global failed status for a service
+ */
+#define SERVICE_FAILED 4
+
+/**
+ * The memory size to create an elements
+ */
+#define ELEMENTS_SIZE (sizeof(char*)+(((2*sizeof(char*))+sizeof(maps*))*2)+sizeof(char*)+(((2*sizeof(char*))+sizeof(iotype*))*2)+(2*sizeof(elements*)))
+/**
+ * The memory size to create a map
+ */
+#define MAP_SIZE (2*sizeof(char*))+sizeof(NULL)
+/**
+ * The memory size to create an iotype
+ */
+#define IOTYPE_SIZE MAP_SIZE+sizeof(NULL)
+/**
+ * The memory size to create a maps
+ */
+#define MAPS_SIZE (2*sizeof(char*))+sizeof(map*)+MAP_SIZE
+/**
+ * The memory size to create a service
+ */
+#define SERVICE_SIZE (ELEMENTS_SIZE*2)+(MAP_SIZE*2)+sizeof(char*)
+/**
+ * The memory size to create a services
+ */
+#define SERVICES_SIZE SERVICE_SIZE+sizeof(services*)
+/**
+ * The memory size to create a registry
+ */
+#define REGISTRY_SIZE SERVICES_SIZE+sizeof(char*)
+
+#define SHMSZ     27
+
+#include "version.h" 
+
+#ifdef DEBUG_STACK
+  void debugStack(const char* file,const int line){
+    int stack;
+    fprintf(stderr,"stack %p (%s: %d) \n",&stack,file,line);
+  }
+#endif
+
+  /**
+   * KVP linked list
+   */
+  typedef struct map{
+    char* name; //!< the key
+    char* value; //!< the value
+    struct map* next; //!< the pointer to the next map if any or NULL
+  } map;
+
+#ifdef WIN32
+#define NULLMAP ((map*) 0)
+#else
+#define NULLMAP NULL
+#endif
+
+  /**
+   * linked list of map pointer
+   *
+   * Small object to store WPS KVP set.
+   */
+  typedef struct maps{
+    char* name; //!< the maps name
+    struct map* content; //!< the content map
+    struct maps* next; //!< the pointer to the next maps if any or NULL
+  } maps;
+  
+  /**
+   * Not named linked list
+   *
+   * Used to store informations about formats, such as mimeType, encoding ... 
+   */
+  typedef struct iotype{
+    struct map* content; //!< the content map
+    struct iotype* next; //!< the pointer to the next iotype if any or NULL
+  } iotype;
+
+  /**
+   * Metadata information about input or output.
+   *
+   * The elements are used to store metadata informations defined in the ZCFG.
+   */
+  typedef struct elements{
+    char* name; //!< the name
+    struct map* content; //!< the content map
+    struct map* metadata; //!< the metadata map
+    char* format; //!< the format: LiteralData or ComplexData or BoundingBoxData
+    struct iotype* defaults; //!< the default iotype 
+    struct iotype* supported; //!< the supported iotype 
+    struct elements* child; //!< the pointer to the children element if any (or NULL)
+    struct elements* next; //!< the pointer to the next element if any (or NULL)
+  } elements;
+
+  /**
+   * Metadata informations about a full Service.
+   */
+  typedef struct service{
+    char* name; //!< the name
+    struct map* content; //!< the content map
+    struct map* metadata; //!< the metadata map
+    struct elements* inputs; //!< the inputs elements
+    struct elements* outputs; //!< the outputs elements
+  } service;
+
+  /**
+   * Services chained list.
+   */
+  typedef struct services{
+    struct service* content; //!< the content service pointer
+    struct services* next; //!< the pointer to the next services*
+  } services;
+
+  /**
+   * Profile registry.
+   */
+  typedef struct registry{
+    char *name; //!< the name
+    struct services* content; //!< the content services pointer
+    struct registry* next; //!< the next registry pointer
+  } registry;
+
+  ZOO_DLL_EXPORT void _dumpMap(map*);
+  ZOO_DLL_EXPORT void dumpMap(map*);
+  ZOO_DLL_EXPORT void dumpMaps(maps* m);
+  ZOO_DLL_EXPORT void dumpMapToFile(map*,FILE*); // (used only internally)
+  ZOO_DLL_EXPORT void dumpMapsToFile(maps*,char*,int);
+  ZOO_DLL_EXPORT map* createMap(const char*,const char*);
+  ZOO_DLL_EXPORT int count(map*);
+  ZOO_DLL_EXPORT bool hasKey(map*,const char*);
+  ZOO_DLL_EXPORT maps* getMaps(maps*,const char*);
+  ZOO_DLL_EXPORT map* getMap(map*,const char*);
+  ZOO_DLL_EXPORT map* getLastMap(map*);
+  ZOO_DLL_EXPORT map* getMapFromMaps(maps*,const char*,const char*);
+  ZOO_DLL_EXPORT void freeMap(map**);
+  ZOO_DLL_EXPORT void freeMaps(maps** mo);
+  
+
+  ZOO_DLL_EXPORT bool hasElement(elements*,const char*);
+  ZOO_DLL_EXPORT elements* getElements(elements*,char*);
+  ZOO_DLL_EXPORT void freeIOType(iotype**);
+  ZOO_DLL_EXPORT void freeElements(elements**);
+  ZOO_DLL_EXPORT void freeService(service**);
+  ZOO_DLL_EXPORT void addToMap(map*,const char*,const char*);
+  ZOO_DLL_EXPORT void addIntToMap(map*,const char*,const int);
+  ZOO_DLL_EXPORT void addToMapWithSize(map*,const char*,const char*,int);
+  ZOO_DLL_EXPORT void addMapToMap(map**,map*);
+  ZOO_DLL_EXPORT void addMapToIoType(iotype**,map*);
+  ZOO_DLL_EXPORT map* getMapOrFill(map**,const char*,const char*);
+  ZOO_DLL_EXPORT bool contains(map*,map*);
+  ZOO_DLL_EXPORT iotype* getIoTypeFromElement(elements*,char*, map*);
+  ZOO_DLL_EXPORT void loadMapBinary(map**,map*,int);
+  ZOO_DLL_EXPORT void loadMapBinaries(map**,map*);
+  ZOO_DLL_EXPORT maps* dupMaps(maps**);
+  ZOO_DLL_EXPORT void addMapsToMaps(maps**,maps*);
+  ZOO_DLL_EXPORT map* getMapArray(map*,const char*,int);
+  ZOO_DLL_EXPORT void setMapArray(map*,const char*,int,const char*);
+  ZOO_DLL_EXPORT map* getMapType(map*);
+  ZOO_DLL_EXPORT int addMapsArrayToMaps(maps**,maps*,char*);
+  ZOO_DLL_EXPORT void setMapInMaps(maps*,const char*,const char*,const char*);
+  ZOO_DLL_EXPORT void dumpElements(elements*);
+  ZOO_DLL_EXPORT void dumpElementsAsYAML(elements*);
+  ZOO_DLL_EXPORT elements* dupElements(elements*);
+  ZOO_DLL_EXPORT void addToElements(elements**,elements*);
+  ZOO_DLL_EXPORT void dumpService(service*);
+  ZOO_DLL_EXPORT void dumpServiceAsYAML(service*);
+  ZOO_DLL_EXPORT service* dupService(service*);
+  ZOO_DLL_EXPORT void dumpRegistry(registry*);
+  ZOO_DLL_EXPORT bool addServiceToRegistry(registry**,char*,service*);
+  ZOO_DLL_EXPORT void freeRegistry(registry**);
+  ZOO_DLL_EXPORT service* getServiceFromRegistry(registry*,char*,char*);
+  ZOO_DLL_EXPORT void inheritMap(map**,map*);
+  ZOO_DLL_EXPORT void inheritIOType(iotype**,iotype*);
+  ZOO_DLL_EXPORT void inheritElements(elements**,elements*);
+  ZOO_DLL_EXPORT void inheritance(registry*,service**);
+  ZOO_DLL_EXPORT void mapsToCharXXX(maps*,char***);
+  ZOO_DLL_EXPORT void charxxxToMaps(char***,maps**);
+#ifdef _MSC_VER
+  // snprintf for Visual Studio compiler;
+  // it is also used by services (e.g., GetStatus), therefore exported to shared library
+  ZOO_DLL_EXPORT int snprintf(char *buffer, size_t n, const char *format, ...);
+#endif  
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/zoo-project/zoo-kernel/service_conf.l b/zoo-project/zoo-kernel/service_conf.l
new file mode 100644
index 0000000..e23390a
--- /dev/null
+++ b/zoo-project/zoo-kernel/service_conf.l
@@ -0,0 +1,102 @@
+/*
+ * Author : Gérald FENOY
+ *
+ * Copyright (c) 209-2015 GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+%option noyywrap
+%option yylineno
+
+
+%{
+
+#include <string.h>
+#include "service_conf.tab.h"
+
+char *lmsg=NULL;
+
+%}
+
+S		[ \t\r\n]+
+
+CharRef		"&#"[0-9]+";"|"&#x"[0-9a-fA-F]+";"
+
+egalevolue		{S}?"="{S}?
+
+Name		([_:]|[\x41-\x5A]|[\x61-\x7A]|[\xC0-\xD6]|[\xD8-\xF6]|[\xF8-\xFF])(([\x41-\x5A]|[\x61-\x7A]|[\xC0-\xD6]|[\xD8-\xF6]|[\xF8-\xFF])|[0-9.\-_:])*
+
+chardata	[^<]*
+
+attname	[a-zA-Z0-9._\-]+
+attvalue1      [\x80-\xbf\xc2-\xdf\xe0-\xef\xf0-\xf4="#°²θé\^\*\+\,\;;?!~`ú@a-zA-Z0-9%_\-:\:.:" "\"\'/\\\(\)\t\|\$\&>\[\]]+
+
+attvalue		\"[^"]*\"|\'[^']*\'\(\)
+
+whitespace                      [\t]{0,}|[ ]{0,}
+whitesp                      [\t]|[ ]
+newline                 [\r\n]|[\n]
+newlines                 [\r\n]{1,}|[\n]{1,}
+
+
+%x DANSBALISE HORSBALISE PAIRSTART
+
+
+
+
+%%
+
+"\n" { }
+
+{newline}+{whitesp}*			{ return NEWLINE; }
+
+<INITIAL,HORSBALISE>"["{attname}"]"             {  srlval.chaine=yytext;return ANID; }
+
+<INITIAL,HORSBALISE>{attname}             {  srlval.chaine=yytext; return SPAIR; }
+
+<PAIRSTART,HORSBALISE>{attvalue1}             { srlval.chaine=yytext;/*BEGIN(INITIAL);*/ return EPAIR;}
+
+<PAIRSTART,INITIAL,HORSBALISE>{whitesp}*"="{whitesp}*             {  BEGIN(PAIRSTART);}
+
+<PAIRSTART,INITIAL,HORSBALISE>{newline}+{whitesp}*             { BEGIN(INITIAL);  return NEWLINE;}
+
+<DANSBALISE,INITIAL,HORSBALISE>{S}   {  }
+
+<INITIAL,HORSBALISE>{newline}*"<"		    { BEGIN(DANSBALISE); return INFCAR;}
+
+
+<DANSBALISE>">"			{ BEGIN(HORSBALISE);return SUPCAR;}
+
+
+<DANSBALISE>"/"		{return SLASH;}
+
+
+<DANSBALISE>{egalevolue}			{return Eq;}
+
+
+<DANSBALISE>{Name}{newline}*			{memmove(srlval.chaine,yytext,(strlen(yytext)+1)*sizeof(char));return ID;}
+
+
+<DANSBALISE>{attvalue}		{return ATTVALUE;}
+
+
+<INITIAL,DANSBALISE,HORSBALISE>.|\n	{lmsg=(char*)malloc(1024*sizeof(char));sprintf(lmsg,"error: line %d: character not allowed '%s'",srlineno,yytext);fprintf(stderr,"%s \n",lmsg);srlval.chaine=lmsg;fprintf(stderr,"%s \n",lmsg);return -1;}
+
+%%
+
diff --git a/zoo-project/zoo-kernel/service_conf.y b/zoo-project/zoo-kernel/service_conf.y
new file mode 100644
index 0000000..998f2a5
--- /dev/null
+++ b/zoo-project/zoo-kernel/service_conf.y
@@ -0,0 +1,876 @@
+/*
+ * Author : Gérald FENOY
+ *
+ * Copyright (c) 209-2015 GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+%{
+
+#include <string>
+#include <stdio.h>
+#include <ctype.h>
+#include <service.h>
+
+static int tmp_count=1;
+static int defaultsc=0;
+static bool wait_maincontent=true;
+static bool wait_mainmetadata=false;
+static bool wait_metadata=false;
+static bool wait_inputs=false;
+static bool wait_defaults=false;
+static bool wait_supporteds=false;
+static bool wait_outputs=false;
+static bool wait_data=false;
+static service* my_service=NULL;
+static map* current_content=NULL;
+static elements* current_element=NULL;
+static char* curr_key;
+static int debug=0;
+static int data=-1;
+static int previous_data=0;
+static int current_data=0;
+// namespace
+using namespace std;
+
+// srerror
+void srerror(const char *s);
+
+// usage ()
+void usage(void) ;
+
+// srdebug
+extern int srdebug;
+
+extern char srtext[];
+
+// srlineno
+extern int srlineno;
+
+// srin
+extern FILE* srin;
+
+// srlex
+extern int srlex(void);
+extern int srlex_destroy(void);
+
+%}
+
+
+
+%union 
+{char * s;char* chaine;char* key;char* val;}
+
+// jetons //
+%token <s> ID
+%token <s> CHAINE
+
+%token INFCAR SUPCAR 
+
+/* / = a1  texte "texte" */
+%token SLASH Eq CHARDATA ATTVALUE PAIR SPAIR EPAIR ANID
+%type <chaine> PAIR
+%type <chaine> EPAIR
+%type <chaine> SPAIR
+
+/* <!-- xxx -> <? xxx yyy ?> */
+%token PI PIERROR /** COMMENT **/
+
+/* <!-- xxx -> <? xxx yyy ?> */
+%token ERREURGENERALE CDATA WHITESPACE NEWLINE
+%type <s> STag
+%type <s> ETag
+%type <s> ANID
+
+// % start
+
+%%
+// document 
+// regle 1
+// on est a la racine du fichier xml
+document
+ : miscetoile element miscetoile {}
+ | contentetoile processid contentetoile document {}
+ ;
+
+miscetoile
+ : miscetoile PIERROR {  srerror("processing instruction begining with <?xml ?> impossible\n");}
+ | miscetoile PI {}
+ | {}
+ ;
+// element
+// regle 39
+// OUVRANTE CONTENU FERMANTE obligatoirement
+// ou neutre
+// on ne peut pas avoir Epsilon
+// un fichier xml ne peut pas etre vide ou seulement avec un prolog
+element
+ : STag contentetoile ETag	
+{
+}
+
+// pour neutre
+// on a rien a faire, meme pas renvoyer l identificateur de balise
+// vu qu'il n y a pas de comparaison d'identificateurs avec un balise jumelle .
+ | EmptyElemTag          {}
+ ;
+
+// STag
+// regle 40
+// BALISE OUVRANTE
+// on est obligé de faire appel a infcar et supcar
+// pour acceder aux start conditions DANSBALISE et INITIAL
+STag
+: INFCAR ID Attributeetoile SUPCAR
+{
+#ifdef DEBUG_SERVICE_CONF
+  fprintf(stderr,"STag (%s %d) %s %d %d \n",__FILE__,__LINE__,$2,current_data,previous_data);
+  fflush(stderr);
+  dumpMap(current_content);
+#endif
+  if(my_service->content==NULL){
+#ifdef DEBUG_SERVICE_CONF
+    fprintf(stderr,"NO CONTENT\n");
+#endif
+    addMapToMap(&my_service->content,current_content);
+    freeMap(&current_content);
+    free(current_content);
+    current_content=NULL;
+    my_service->metadata=NULL;
+    wait_maincontent=false;
+  }
+  if(strncasecmp($2,"DataInputs",10)==0){
+    if(current_element==NULL){
+#ifdef DEBUG_SERVICE_CONF
+      fprintf(stderr,"(DATAINPUTS - %d) FREE current_element\n",__LINE__);
+#endif
+      freeElements(&current_element);
+      free(current_element);
+#ifdef DEBUG_SERVICE_CONF
+      fprintf(stderr,"(DATAINPUTS - %d) ALLOCATE current_element\n",__LINE__);
+#endif
+      current_element=NULL;
+      current_element=(elements*)malloc(ELEMENTS_SIZE);
+      current_element->name=NULL;
+      current_element->content=NULL;
+      current_element->metadata=NULL;
+      current_element->format=NULL;
+      current_element->defaults=NULL;
+      current_element->supported=NULL;
+      current_element->child=NULL;
+      current_element->next=NULL;
+    }
+    wait_inputs=true;
+    current_data=1;
+    previous_data=1;
+  }
+  else
+    if(strncasecmp($2,"DataOutputs",11)==0){
+      if(wait_inputs==true){
+#ifdef DEBUG_SERVICE_CONF
+	fprintf(stderr,"(DATAOUTPUTS %d) DUP INPUTS current_element\n",__LINE__);
+	fprintf(stderr,"CURRENT_ELEMENT\n");
+	dumpElements(current_element);
+	fprintf(stderr,"SERVICE INPUTS\n");
+	dumpElements(my_service->inputs);
+	dumpService(my_service);
+#endif	
+	if(my_service->inputs==NULL && current_element!=NULL && current_element->name!=NULL){
+	  my_service->inputs=dupElements(current_element);
+	  my_service->inputs->next=NULL;
+	  freeElements(&current_element);
+	}
+	else if(current_element!=NULL && current_element->name!=NULL){
+	  addToElements(&my_service->inputs,current_element);
+	  freeElements(&current_element);
+	}
+#ifdef DEBUG_SERVICE_CONF
+	fprintf(stderr,"CURRENT_ELEMENT\n");
+	dumpElements(current_element);
+	fprintf(stderr,"SERVICE INPUTS\n");
+	dumpElements(my_service->inputs);
+	fprintf(stderr,"(DATAOUTPUTS) FREE current_element\n");
+#endif
+	free(current_element);
+	current_element=NULL;
+	wait_inputs=false;
+      }
+      if(current_element==NULL){
+#ifdef DEBUG_SERVICE_CONF
+	fprintf(stderr,"(DATAOUTPUTS - %d) ALLOCATE current_element (%s)\n",__LINE__,$2);
+	fflush(stderr);
+#endif
+	current_element=(elements*)malloc(ELEMENTS_SIZE);
+	current_element->name=NULL;
+	current_element->content=NULL;
+	current_element->metadata=NULL;
+	current_element->format=NULL;
+	current_element->defaults=NULL;
+	current_element->supported=NULL;
+	current_element->child=NULL;
+	current_element->next=NULL;
+      }
+      wait_outputs=1;
+      current_data=2;
+      previous_data=2;
+    }
+    else
+      if(strncasecmp($2,"MetaData",8)==0){
+	previous_data=current_data;
+	current_data=3;
+	if(current_element!=NULL){
+#ifdef DEBUG_SERVICE_CONF
+	  fprintf(stderr,"add current_content to current_element->content\n");
+	  fprintf(stderr,"LINE %d",__LINE__);
+#endif
+	  addMapToMap(&current_element->content,current_content);
+	  freeMap(&current_content);
+	  free(current_content);
+	  if(previous_data==1 || previous_data==2)
+	    wait_metadata=true;
+	  else
+	    wait_mainmetadata=true;
+	}
+	else{
+	  if(previous_data==1 || previous_data==2)
+	    wait_metadata=true;
+	  else
+	    wait_mainmetadata=true;
+	}
+	current_content=NULL;
+      }
+      else
+	if(strncasecmp($2,"ComplexData",11)==0 || strncasecmp($2,"LiteralData",10)==0
+	   || strncasecmp($2,"ComplexOutput",13)==0 || strncasecmp($2,"LiteralOutput",12)==0
+	   || strncasecmp($2,"BoundingBoxOutput",13)==0 || strncasecmp($2,"BoundingBoxData",12)==0){
+	  current_data=4;
+	  addMapToMap(&current_element->content,current_content);
+	  freeMap(&current_content);
+	  free(current_content);
+	  current_element->next=NULL;
+	  if($2!=NULL)
+	    current_element->format=zStrdup($2);
+	  current_element->defaults=NULL;
+	  current_element->supported=NULL;
+	  current_content=NULL;
+	}
+	else
+	  if(strncasecmp($2,"Default",7)==0){
+	    wait_defaults=true;
+	    current_data=5;
+	  }
+	  else
+	    if(strncasecmp($2,"Supported",9)==0){
+	      wait_supporteds=true;
+	      if(wait_defaults==true){
+		defaultsc++;
+	      }
+	      current_data=5;
+	    }
+#ifdef DEBUG_SERVICE_CONF
+  printf("* Identifiant : %s\n",$2);
+  fflush(stdout);
+#endif
+}
+ ;
+
+// Attributeetoile
+// regle 41
+// une liste qui peut etre vide d'attributs
+// utiliser la récursivité a gauche
+Attributeetoile
+: Attributeetoile attribute  {}
+ | 	                          {/* Epsilon */}
+ ;
+
+// attribute
+// regle 41
+// un attribut est compose d'un identifiant
+// d'un "="
+// et d'une définition de chaine de caractere
+// ( "xxx" ou 'xxx' )
+attribute
+ : ID Eq ATTVALUE		
+{
+#ifdef DEBUG_SERVICE_CONF
+  printf ("attribute : %s\n",$1) ;
+#endif
+}
+ ;
+
+// EmptyElemTag
+// regle 44
+// ICI ON DEFINIT NEUTRE
+// on ne renvoie pas de char*
+// parce qu'il n'y a pas de comparaisons a faire
+// avec un identifiant d'une balise jumelle
+EmptyElemTag
+ : INFCAR ID Attributeetoile SLASH SUPCAR	{
+#ifdef DEBUG_SERVICE_CONF
+  fprintf(stderr,"(%s %d)\n",__FILE__,__LINE__);
+#endif
+   if(strncasecmp($2,"Default",7)==0){
+     wait_defaults=false;
+     current_data=previous_data;
+     if(current_element->defaults==NULL){
+       current_element->defaults=(iotype*)malloc(IOTYPE_SIZE);
+       current_element->defaults->content=NULL;
+     }
+     addMapToMap(&current_element->defaults->content,current_content);
+     freeMap(&current_content);
+     free(current_content);
+     current_element->defaults->next=NULL;
+     wait_defaults=false;
+     current_content=NULL;
+     current_element->supported=NULL;
+     current_element->next=NULL;
+   }
+ }
+ ;
+
+// ETag
+// BALISE FERMANTE
+// les separateurs après ID sont filtrés
+ETag
+ : INFCAR SLASH ID SUPCAR
+{
+#ifdef DEBUG_SERVICE_CONF
+  fprintf(stderr,"ETag %s (%s %d) %d %d \n",$3,__FILE__,__LINE__,current_data,previous_data);
+#endif
+  if(strcmp($3,"DataInputs")==0){
+    current_data=1;
+    if(current_content!=NULL){
+      if(current_element->content==NULL){
+	addMapToMap(&current_element->content,current_content);
+      }
+      freeMap(&current_content);
+      free(current_content);
+      current_content=NULL;
+    }
+    if(current_element!=NULL){
+      if(my_service->content!=NULL && current_element->name!=NULL){
+	if(my_service->inputs==NULL){
+	  my_service->inputs=dupElements(current_element);
+	  my_service->inputs->next=NULL;
+	  tmp_count++;
+	}
+	else{
+	  addToElements(&my_service->inputs,current_element);
+	}
+	freeElements(&current_element);
+	free(current_element);
+	current_element=NULL;
+      }
+    }
+  }
+  if(strcmp($3,"DataOutputs")==0){
+    current_data=2;
+  }
+  if(strcmp($3,"MetaData")==0){
+    if(current_content!=NULL){
+#ifdef DEBUG_SERVICE_CONF
+      fprintf(stderr,"add current_content to current_element->content\n");
+      fprintf(stderr,"LINE %d",__LINE__);
+#endif
+      if(wait_metadata){
+	current_element->metadata=NULL;
+	addMapToMap(&current_element->metadata,current_content);
+	current_element->next=NULL;
+	current_element->defaults=NULL;
+	current_element->supported=NULL;
+      }else{
+	if(wait_mainmetadata){
+	  addMapToMap(&my_service->metadata,current_content);
+	}
+      }
+
+      freeMap(&current_content);
+      free(current_content);
+      current_content=NULL;
+    }
+    current_data=previous_data;
+    wait_mainmetadata=false;
+    wait_metadata=false;
+  }
+  if(strcmp($3,"ComplexData")==0 || strcmp($3,"LiteralData")==0 
+     || strcmp($3,"ComplexOutput")==0 || strcmp($3,"LiteralOutput")==0){
+    if(current_element->format==NULL)
+      current_element->format=zStrdup($3);
+    current_content=NULL;
+  }
+  if(strcmp($3,"Default")==0){
+    current_data=previous_data;
+    if(current_element->defaults==NULL){
+      current_element->defaults=(iotype*)malloc(IOTYPE_SIZE);
+      current_element->defaults->content=NULL;
+    }
+    addMapToMap(&current_element->defaults->content,current_content);
+    freeMap(&current_content);
+    free(current_content);
+    current_element->defaults->next=NULL;
+    wait_defaults=false;
+    current_content=NULL;
+    current_element->supported=NULL;
+    current_element->next=NULL;
+  }
+  if(strcmp($3,"Supported")==0){
+    current_data=previous_data;
+    if(current_element->supported==NULL){
+      if(current_content!=NULL){
+	current_element->supported=(iotype*)malloc(IOTYPE_SIZE);
+	current_element->supported->content=NULL;
+	addMapToMap(&current_element->supported->content,current_content);
+	freeMap(&current_content);
+	free(current_content);
+	current_element->supported->next=NULL;
+	current_content=NULL;
+      }else{
+	current_element->supported=NULL;
+	current_element->next=NULL;
+      }
+    }
+    else{
+#ifdef DEBUG_SERVICE_CONF
+      fprintf(stderr,"SECOND SUPPORTED FORMAT !!!!\n");
+#endif
+      addMapToIoType(&current_element->supported,current_content);
+      freeMap(&current_content);
+      free(current_content);
+      current_content=NULL;
+#ifdef DEBUG_SERVICE_CONF
+      dumpElements(current_element);
+      fprintf(stderr,"SECOND SUPPORTED FORMAT !!!!\n");
+#endif
+    }
+    current_content=NULL;
+  }
+}
+ ;
+
+//======================================================
+// contentetoile
+//======================================================
+// regle 43
+// ENTRE 2 BALISES
+// entre 2 balises, on peut avoir :
+// --- OUVRANTE CONTENU FERMANTE (recursivement !)
+// --- DU TEXTE quelconque
+// --- COMMENTS 
+// --- DES PROCESSES INSTRUCTIONS
+// --- /!\ il peut y avoir une processing instruction invalide ! <?xml
+// --- EPSILON
+// ### et/ou tout ca a la suite en nombre indeterminé
+// ### donc c'est un operateur etoile (*)
+//======================================================
+contentetoile
+: contentetoile element	          {}
+ | contentetoile PIERROR	          {srerror("processing instruction <?xml ?> impossible\n");}
+ | contentetoile PI	                  {}
+///// on filtre les commentaires | contentetoile comment              {} 
+ | contentetoile NEWLINE {/*printf("NEWLINE FOUND !!");*/}
+ | contentetoile pair {}
+ | contentetoile processid {}
+ | contentetoile texteinterbalise	  {}
+ | contentetoile CDATA {}  
+ | {/* Epsilon */}
+ ;
+
+// texteinterbalise
+// regle 14
+// DU TEXTE quelconque
+// c'est du CHARDATA
+// il y a eut un probleme avec ID,
+// on a mis des starts conditions,
+// maintenant on croise les ID dans les dbalises
+// et des CHARDATA hors des balises
+texteinterbalise
+ : CHARDATA		{}
+ ;
+
+pair: PAIR { if(debug) fprintf(stderr,"PAIR FOUND !!\n");if(curr_key!=NULL){free(curr_key);curr_key=NULL;} }
+| EPAIR {
+#ifdef DEBUG_SERVICE_CONF
+  fprintf(stderr,"EPAIR (%s %d)\n",__FILE__,__LINE__);
+  fprintf(stderr,"[%s=>%s]\n",curr_key,$1);
+  dumpMap(current_content);
+  fflush(stderr);
+#endif
+  if($1!=NULL && curr_key!=NULL){
+    if(current_content==NULL){
+#ifdef DEBUG_SERVICE_CONF
+      fprintf(stderr,"[ZOO: service_conf.y line %d free(%s)]\n",__LINE__,curr_key);
+#endif
+      current_content=createMap(curr_key,$1);
+#ifdef DEBUG_SERVICE_CONF
+      fprintf(stderr,"[ZOO: service_conf.y line %d free(%s)]\n",__LINE__,curr_key);
+#endif
+    }
+    else{ 
+#ifdef DEBUG_SERVICE_CONF
+      dumpMap(current_content);
+      fprintf(stderr,"addToMap(current_content,%s,%s) !! \n",curr_key,$1); 
+#endif
+      addToMap(current_content,curr_key,$1);
+#ifdef DEBUG_SERVICE_CONF
+      fprintf(stderr,"addToMap(current_content,%s,%s) end !! \n",curr_key,$1); 
+#endif    
+    }
+  }
+#ifdef DEBUG_SERVICE_CONF
+  fprintf(stderr,"[%s=>%s]\n",curr_key,$1);
+  fprintf(stderr,"[ZOO: service_conf.y line %d free(%s)]\n",__LINE__,curr_key);
+  dumpMap(current_content);
+  fflush(stderr);
+#endif
+  if(curr_key!=NULL){
+    free(curr_key);
+    curr_key=NULL;
+  }
+  }
+| SPAIR  { if(curr_key!=NULL) {free(curr_key);curr_key=NULL;} if($1!=NULL) curr_key=zStrdup($1);if(debug) fprintf(stderr,"SPAIR FOUND !!\n"); }
+ ;
+
+
+processid
+: ANID  {
+#ifdef DEBUG_SERVICE_CONF
+  fprintf(stderr,"processid (%s %d) %s\n",__FILE__,__LINE__,$1);
+#endif
+  if(data==-1){
+    data=1;
+    if($1!=NULL){
+      char *cen=zStrdup($1);
+      my_service->name=(char*)malloc((strlen(cen)-1)*sizeof(char*));
+      cen[strlen(cen)-1]=0;
+      cen+=1;
+      sprintf(my_service->name,"%s",cen);
+      cen-=1;
+      free(cen);
+      my_service->content=NULL;
+      my_service->metadata=NULL;
+      my_service->inputs=NULL;
+      my_service->outputs=NULL;
+    }
+  } else {
+    if(current_data==1){
+      if(my_service->content!=NULL && current_element->name!=NULL){
+	if(my_service->inputs==NULL){
+	  my_service->inputs=dupElements(current_element);
+	  my_service->inputs->next=NULL;
+	  tmp_count++;
+	}
+	else{
+	  addToElements(&my_service->inputs,current_element);
+	}
+#ifdef DEBUG_SERVICE_CONF
+	fprintf(stderr,"(%s %d)FREE current_element (after adding to allread existing inputs)",__FILE__,__LINE__);
+	dumpElements(current_element);
+	fprintf(stderr,"(%s %d)FREE current_element (after adding to allread existing inputs)",__FILE__,__LINE__);
+	dumpElements(my_service->inputs);
+#endif
+	freeElements(&current_element);
+	free(current_element);
+	current_element=NULL;
+#ifdef DEBUG_SERVICE_CONF
+	fprintf(stderr,"(DATAINPUTS - 489) ALLOCATE current_element\n");
+#endif
+	current_element=(elements*)malloc(ELEMENTS_SIZE);
+	current_element->name=NULL;
+	current_element->content=NULL;
+	current_element->metadata=NULL;
+	current_element->format=NULL;
+	current_element->defaults=NULL;
+	current_element->supported=NULL;
+	current_element->next=NULL;
+      }
+      if(current_element->name==NULL){
+#ifdef DEBUG_SERVICE_CONF
+	fprintf(stderr,"NAME IN %s (current - %s)\n",
+		$1,current_element->name);
+#endif
+	wait_inputs=true;
+#ifdef DEBUG_SERVICE_CONF
+	fprintf(stderr,"(DATAINPUTS - 501) SET NAME OF current_element\n");
+#endif
+	if($1!=NULL){ 
+	  char *cen=zStrdup($1);
+	  current_element->name=(char*)malloc((strlen(cen)-1)*sizeof(char*));
+	  cen[strlen(cen)-1]=0;
+	  cen+=1;
+	  sprintf(current_element->name,"%s",cen);
+	  cen-=1;
+	  free(cen);
+#ifdef DEBUG_SERVICE_CONF
+	  fprintf(stderr,"NAME IN %s (current - %s)\n",$1,current_element->name);
+#endif
+	  current_element->content=NULL;
+	  current_element->metadata=NULL;
+	  current_element->format=NULL;
+	  current_element->defaults=NULL;
+	  current_element->supported=NULL;
+	  current_element->next=NULL;
+#ifdef DEBUG_SERVICE_CONF
+	  fprintf(stderr,"NAME IN %s (current - %s)\n",$1,current_element->name);
+#endif
+	}
+      }
+    }
+    else
+      if(current_data==2){ 
+	wait_outputs=1;
+	if(wait_inputs){
+	  if(current_element!=NULL && current_element->name!=NULL){
+	    if(my_service->outputs==NULL){
+	      my_service->outputs=dupElements(current_element);
+	      my_service->outputs->next=NULL;
+	    }
+	    else{
+#ifdef DEBUG_SERVICE_CONF
+	      fprintf(stderr,"LAST NAME IN %s (current - %s)\n",$1,current_element->name);
+#endif
+	      addToElements(&my_service->outputs,current_element);
+	    }
+#ifdef DEBUG_SERVICE_CONF
+	    dumpElements(current_element);
+	    fprintf(stderr,"(DATAOUTPUTS) FREE current_element %s %i\n",__FILE__,__LINE__);
+#endif
+	    freeElements(&current_element);
+	    free(current_element);
+	    current_element=NULL;
+#ifdef DEBUG_SERVICE_CONF
+	    fprintf(stderr,"(DATAOUTPUTS -%d) ALLOCATE current_element %s \n",__LINE__,__FILE__);
+#endif
+	    current_element=(elements*)malloc(ELEMENTS_SIZE);
+	    current_element->name=NULL;
+	    current_element->content=NULL;
+	    current_element->metadata=NULL;
+	    current_element->format=NULL;
+	    current_element->defaults=NULL;
+	    current_element->supported=NULL;
+	    current_element->next=NULL;
+	  }
+	  if(current_element->name==NULL){
+#ifdef DEBUG_SERVICE_CONF
+	    fprintf(stderr,"NAME OUT %s\n",$1);
+	    fprintf(stderr,"(DATAOUTPUTS - %d) SET NAME OF current_element\n",__LINE__);
+#endif
+	    if($1!=NULL){ 
+	      char *cen=zStrdup($1);
+	      current_element->name=(char*)malloc((strlen(cen)-1)*sizeof(char));
+	      cen[strlen(cen)-1]=0;
+	      cen+=1;
+	      sprintf(current_element->name,"%s",cen);
+	      cen-=1;
+	      free(cen);
+	      current_element->content=NULL;
+	      current_element->metadata=NULL;
+	      current_element->format=NULL;
+	      current_element->defaults=NULL;
+	      current_element->supported=NULL;
+	      current_element->next=NULL;
+	    }
+	  }
+
+	  current_content=NULL;
+	}
+	else
+	  if(current_element!=NULL && current_element->name!=NULL){
+	    if(my_service->outputs==NULL)
+	      my_service->outputs=dupElements(current_element);
+	    else
+	      addToElements(&my_service->outputs,current_element);
+#ifdef DEBUG_SERVICE_CONF
+	    fprintf(stderr,"ADD TO OUTPUTS Elements\n");
+	    dupElements(current_element);
+#endif
+	    freeElements(&current_element);
+	    free(current_element);
+	    current_element=NULL;
+	    current_element=(elements*)malloc(ELEMENTS_SIZE);
+	    char *cen=zStrdup($1);
+	    current_element->name=(char*)malloc((strlen(cen)-1)*sizeof(char));
+	    cen[strlen(cen)-1]=0;
+	    cen+=1;
+	    sprintf(current_element->name,"%s",cen);
+	    cen-=1;
+	    free(cen);
+	    current_element->content=NULL;
+	    current_element->metadata=NULL;
+	    current_element->format=NULL;
+	    current_element->defaults=NULL;
+	    current_element->supported=NULL;
+	    current_element->next=NULL;
+	  }
+	  else{
+#ifdef DEBUG_SERVICE_CONF
+	    fprintf(stderr,"NAME OUT %s\n",$1);
+	    fprintf(stderr,"(DATAOUTPUTS - %d) SET NAME OF current_element %s\n",__LINE__,$1);
+#endif
+	    if($1!=NULL){ 
+	      char *cen=zStrdup($1);
+	      current_element->name=(char*)malloc((strlen(cen))*sizeof(char*));
+	      cen[strlen(cen)-1]=0;
+#ifdef DEBUG
+	      fprintf(stderr,"tmp %s\n",cen);
+#endif
+	      cen+=1;
+	      sprintf(current_element->name,"%s",cen);
+	      cen-=1;
+	      free(cen);
+	      current_element->content=NULL;
+	      current_element->metadata=NULL;
+	      current_element->format=NULL;
+	      current_element->defaults=NULL;
+	      current_element->supported=NULL;
+	      current_element->next=NULL;
+	    }
+	  }
+	wait_inputs=false;
+	wait_outputs=1;
+	//wait_outputs=true;
+      }
+  }
+ }
+ ;
+
+%%
+
+/**
+ * Print on stderr the message and the line number of the error which occured.
+ * 
+ * @param s the error message
+ */
+void srerror(const char *s)
+{
+  if(debug)
+    fprintf(stderr,"\nligne %d : %s\n",srlineno,s);
+}
+
+/**
+ * Parse a ZCFG file and fill the service structure.
+ *
+ * @param conf the conf maps containing the main.cfg settings
+ * @param file the fullpath to the ZCFG file
+ * @param service the service structure to fill
+ * @return 0 on success, -1 on failure
+ */
+int getServiceFromFile(maps* conf,const char* file,service** service){
+  if(current_content!=NULL){
+    freeMap(&current_content);
+    free(current_content);
+    current_content=NULL;
+  }
+#ifdef DEBUG_SERVICE_CONF
+  fprintf(stderr,"(STARTING)FREE current_element\n");
+#endif
+  if(current_element!=NULL){
+    freeElements(&current_element);
+    free(current_element);
+    current_element=NULL;
+  }
+  my_service=NULL;
+
+  wait_maincontent=true;
+  wait_mainmetadata=false;
+  wait_metadata=false;
+  wait_inputs=false;
+  wait_defaults=false;
+  wait_supporteds=false;
+  wait_outputs=-1;
+  wait_data=false;
+  data=-1;
+  previous_data=1;
+  current_data=0;
+  
+  my_service=*service;
+
+  srin = fopen(file,"r");
+  if (srin==NULL){
+    setMapInMaps(conf,"lenv","message","file not found");
+    return -1;
+  }
+
+  int resultatYYParse = srparse() ;
+
+#ifdef DEBUG_SERVICE_CONF
+  fprintf(stderr,"RESULT: %d %d\n",resultatYYParse,wait_outputs);
+  dumpElements(current_element);
+#endif
+  if(wait_outputs && current_element!=NULL && current_element->name!=NULL){
+    if(current_content!=NULL){
+      addMapToMap(&current_element->content,current_content);
+    }
+    if(my_service->outputs==NULL){  
+#ifdef DEBUG_SERVICE_CONF
+      fprintf(stderr,"(DATAOUTPUTS - %d) DUP current_element\n",__LINE__);
+#endif
+      my_service->outputs=dupElements(current_element);
+      my_service->outputs->next=NULL;
+    }
+    else{
+#ifdef DEBUG_SERVICE_CONF
+      fprintf(stderr,"(DATAOUTPUTS - %d) COPY current_element\n",__LINE__);
+#endif
+      addToElements(&my_service->outputs,current_element);
+    }
+#ifdef DEBUG_SERVICE_CONF
+    fprintf(stderr,"(DATAOUTPUTS - %d) FREE current_element\n",__LINE__);
+#endif
+    freeElements(&current_element);
+    free(current_element);
+    current_element=NULL;
+#ifdef DEBUG_SERVICE_CONF
+    fprintf(stderr,"(DATAOUTPUTS - %d) FREE current_element\n",__LINE__);
+#endif
+  }
+  if(current_element!=NULL){
+    freeElements(&current_element);
+    free(current_element);
+    current_element=NULL;
+  }
+  int contentOnly=false;
+  if(current_content!=NULL){
+    if(my_service->content==NULL){
+      addMapToMap(&my_service->content,current_content);
+      contentOnly=true;
+      wait_maincontent=false;
+    }
+    freeMap(&current_content);
+    free(current_content);
+    current_content=NULL;
+  }
+  fclose(srin);
+#ifdef DEBUG_SERVICE_CONF
+  dumpService(my_service);
+#endif
+  if(wait_maincontent==true || (contentOnly==false && ((!wait_outputs && current_data==2 && my_service->outputs==NULL) || my_service==NULL || my_service->name==NULL || my_service->content==NULL))){
+    setMapInMaps(conf,"lenv","message",srlval.chaine);
+#ifndef WIN32
+    srlex_destroy();
+#endif
+    return -1;
+  }
+  else
+    *service=my_service;
+
+#ifndef WIN32
+  srlex_destroy();
+#endif
+  return resultatYYParse;
+}
diff --git a/zoo-project/zoo-kernel/service_internal.c b/zoo-project/zoo-kernel/service_internal.c
new file mode 100644
index 0000000..f6c238f
--- /dev/null
+++ b/zoo-project/zoo-kernel/service_internal.c
@@ -0,0 +1,734 @@
+/*
+ * Author : Gérald FENOY
+ *
+ * Copyright (c) 2009-2015 GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#define _LARGEFILE64_SOURCE 1
+#ifdef USE_MS
+#include "service_internal_ms.h"
+#else
+#include "cpl_vsi.h"
+#endif
+#include "service_internal.h"
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE -1
+#endif
+
+#define ERROR_MSG_MAX_LENGTH 1024
+#ifndef RELY_ON_DB
+#include <dirent.h>
+
+/**
+ * Read the sid file attached of a service if any
+ *
+ * @param conf the maps containing the setting of the main.cfg file
+ * @param pid the service identifier (usid key from the [lenv] section)
+ * @return the reported status char* (temporary/final result)
+ */
+char* getStatusId(maps* conf,char* pid){
+  map* r_inputs = getMapFromMaps (conf, "main", "tmpPath");
+  char* fbkpid =
+    (char *)
+    malloc ((strlen (r_inputs->value) + strlen (pid) + 7) * sizeof (char));
+  sprintf (fbkpid, "%s/%s.sid", r_inputs->value, pid);
+  FILE* f0 = fopen (fbkpid, "r");
+  if(f0!=NULL){
+    long flen;
+    char *fcontent;
+    fseek (f0, 0, SEEK_END);
+    flen = ftell (f0);
+    fseek (f0, 0, SEEK_SET);
+    fcontent = (char *) malloc ((flen + 1) * sizeof (char));
+    fread(fcontent,flen,1,f0);
+    fcontent[flen]=0;
+    fclose(f0);
+    return fcontent;
+  }else
+    return NULL;
+}
+
+/**
+ * Acquire the global lock
+ * 
+ * @param conf the maps containing the setting of the main.cfg file
+ * @return a semid 
+ */
+semid acquireLock(maps* conf){
+  semid lockid;
+  int itn=0;
+ toRetry1:
+  lockid=getShmLockId(conf,1);
+  if(
+#ifdef WIN32
+     lockid==NULL
+#else
+     lockid<0
+#endif
+     ){
+#ifdef WIN32
+    return NULL;
+#else
+    return -1;
+#endif
+  }
+  if(lockShm(lockid)<0){
+#ifdef WIN32
+      return NULL;
+#else
+    if(itn<ZOO_LOCK_MAX_RETRY){
+      itn++;
+      goto toRetry1;
+    }else
+      return -1;
+#endif
+  }else
+    return lockid;
+}
+
+/**
+ * Read the cache file of a running service 
+ *
+ * @param conf the maps containing the setting of the main.cfg file
+ * @param pid the service identifier (usid key from the [lenv] section)
+ * @return the reported status char* (temporary/final result)
+ */
+char* _getStatusFile(maps* conf,char* pid){
+  map* tmpTmap = getMapFromMaps (conf, "main", "tmpPath");
+
+  struct dirent *dp;
+  DIR *dirp = opendir(tmpTmap->value);
+  char fileName[1024];
+  int hasFile=-1;
+  if(dirp!=NULL){
+    char tmp[128];
+    sprintf(tmp,"_%s.xml",pid);
+    while ((dp = readdir(dirp)) != NULL){
+#ifdef DEBUG
+      fprintf(stderr,"File : %s searched : %s\n",dp->d_name,tmp);
+#endif
+      if(strstr(dp->d_name,"final_")==0 && strstr(dp->d_name,tmp)!=0){
+	sprintf(fileName,"%s/%s",tmpTmap->value,dp->d_name);
+	hasFile=1;
+	break;
+      }
+    }
+  }
+  if(hasFile>0){
+    semid lockid;
+    char* stat=getStatusId(conf,pid);
+    if(stat!=NULL){
+      setMapInMaps(conf,"lenv","lid",stat);
+      lockid=acquireLock(conf);
+      if(lockid<0)
+	return NULL;
+    }
+
+    FILE* f0 = fopen (fileName, "r");
+    if(f0!=NULL){
+      fseek (f0, 0, SEEK_END);
+      long flen = ftell (f0);
+      fseek (f0, 0, SEEK_SET);
+      char *tmps1 = (char *) malloc ((flen + 1) * sizeof (char));
+      fread(tmps1,flen,1,f0);
+      tmps1[flen]=0;
+      fclose(f0);
+      if(stat!=NULL){
+	unlockShm(lockid);
+	free(stat);
+      }
+
+      return tmps1;
+    }
+    else{
+      if(stat!=NULL){
+	unlockShm(lockid);
+	free(stat);
+      }
+      return NULL;
+    }
+  }
+  else
+    return NULL;
+}
+
+/**
+ * Get the ongoing status of a running service 
+ *
+ * @param conf the maps containing the setting of the main.cfg file
+ * @param pid the service identifier (usid key from the [lenv] section)
+ * @return the reported status char* (MESSAGE|POURCENTAGE)
+ */
+char* _getStatus(maps* conf,char* lid){
+  map* r_inputs = getMapFromMaps (conf, "main", "tmpPath");
+  char* fbkpid =
+    (char *)
+    malloc ((strlen (r_inputs->value) + strlen (lid) + 9) * sizeof (char));
+  sprintf (fbkpid, "%s/%s.status", r_inputs->value, lid);
+  FILE* f0 = fopen (fbkpid, "r");
+  if(f0!=NULL){
+    semid lockid;
+    char* stat;
+    long flen;
+    stat=getStatusId(conf,lid);
+    if(stat!=NULL){
+      setMapInMaps(conf,"lenv","lid",stat);
+      lockid=acquireLock(conf);
+      if(lockid<0)
+	return NULL;
+    }
+    fseek (f0, 0, SEEK_END);
+    flen = ftell (f0);
+    if(flen>0){
+      char *fcontent;
+      fseek (f0, 0, SEEK_SET);
+      fcontent = (char *) malloc ((flen + 1) * sizeof (char));
+      fread(fcontent,flen,1,f0);
+      fcontent[flen]=0;
+      fclose(f0);
+      free(fbkpid);
+      if(stat!=NULL){
+#ifndef WIN32
+	removeShmLock(conf,1);
+#else
+	unlockShm(lockid);
+#endif
+	free(stat);
+      }
+      return fcontent;
+    }
+    fclose(f0);
+    free(fbkpid);
+    if(stat!=NULL){
+      removeShmLock(conf,1);
+      free(stat);
+    }
+    return NULL;
+  }else{
+    free(fbkpid);
+    char* stat=getStatusId(conf,lid);
+    setMapInMaps(conf,"lenv","lid",stat);
+    removeShmLock(conf,1);
+    return NULL;
+  }
+}
+
+/**
+ * Stop handling status repport.
+ *
+ * @param conf the map containing the setting of the main.cfg file
+ */
+void unhandleStatus(maps *conf){
+  map* r_inputs = getMapFromMaps (conf, "main", "tmpPath");
+  map* usid = getMapFromMaps (conf, "lenv", "usid");
+  char* fbkpid =
+    (char *) malloc ((strlen (r_inputs->value) + strlen (usid->value) + 9) 
+		     * sizeof (char));
+  sprintf (fbkpid, "%s/%s.status", r_inputs->value, usid->value);
+  unlink(fbkpid);
+  free(fbkpid);
+}
+
+/**
+ * Update the current status of the running service.
+ *
+ * @see acquireLock, lockShm
+ * @param conf the map containing the setting of the main.cfg file
+ * @return 0 on success, -2 if shmget failed, -1 if shmat failed
+ */
+int _updateStatus(maps *conf){
+  map* r_inputs = getMapFromMaps (conf, "main", "tmpPath");
+  map* sid = getMapFromMaps (conf, "lenv", "usid");
+  char* fbkpid =
+    (char *)
+    malloc ((strlen (r_inputs->value) + strlen (sid->value) + 9) * sizeof (char));
+  sprintf (fbkpid, "%s/%s.status", r_inputs->value, sid->value);
+  map* status=getMapFromMaps(conf,"lenv","status");
+  map* msg=getMapFromMaps(conf,"lenv","message");
+  if(status!=NULL && msg!=NULL &&
+     status->value!=NULL && msg->value!=NULL && 
+     strlen(status->value)>0 && strlen(msg->value)>1){
+    semid lockid;
+    char* stat=getStatusId(conf,sid->value);
+    if(stat!=NULL){
+      lockid=acquireLock(conf);
+      if(lockid<0){
+	dumpMap(status);
+	return ZOO_LOCK_ACQUIRE_FAILED;
+      }
+    }
+    FILE* fstatus=fopen(fbkpid,"w");
+    if(fstatus!=NULL){
+      fprintf(fstatus,"%s|%s",status->value,msg->value);
+      fflush(fstatus);
+      fclose(fstatus);
+    }
+    if(stat!=NULL){
+      unlockShm(lockid);
+      free(stat);
+    }
+  }
+  return 0;
+}
+
+#endif
+
+#ifdef WIN32
+
+#define SHMEMSIZE 4096
+
+size_t getKeyValue(maps* conf, char* key, size_t length){
+  if(conf==NULL) {
+    strncpy(key, "700666", length);
+    return strlen(key);
+  }
+  
+  map *tmpMap=getMapFromMaps(conf,"lenv","lid");
+  if(tmpMap==NULL)
+    tmpMap=getMapFromMaps(conf,"lenv","osid");
+
+  if(tmpMap!=NULL){
+    snprintf(key, length, "zoo_sem_%s", tmpMap->value);      
+  }
+  else {
+    strncpy(key, "-1", length);
+  }
+  return strlen(key);
+}
+
+
+semid getShmLockId(maps* conf, int nsems){
+  semid sem_id;
+  char key[MAX_PATH];
+  getKeyValue(conf, key, MAX_PATH);
+  
+  sem_id = CreateSemaphore( NULL, nsems, nsems+1, key);
+  if(sem_id==NULL){
+#ifdef DEBUG
+    fprintf(stderr,"Semaphore failed to create: %s\n", getLastErrorMessage());
+#endif
+    return NULL;
+  }
+#ifdef DEBUG
+  fprintf(stderr,"%s Accessed !\n",key);
+#endif
+  return sem_id;
+}
+
+int removeShmLock(maps* conf, int nsems){
+  semid sem_id=getShmLockId(conf,1);
+  if (CloseHandle(sem_id) == 0) {
+#ifdef DEBUG
+    fprintf(stderr,"Unable to remove semaphore: %s\n", getLastErrorMessage());
+#endif
+    return -1;
+  }
+#ifdef DEBUG
+  fprintf(stderr,"%d Removed !\n",sem_id);
+#endif
+  return 0;
+}
+
+int lockShm(semid id){
+  DWORD dwWaitResult=WaitForSingleObject(id,INFINITE);
+  switch (dwWaitResult){
+    case WAIT_OBJECT_0:
+      return 0;
+      break;
+    case WAIT_TIMEOUT:
+      return -1;
+      break;
+    default:
+      return -2;
+      break;
+  }
+  return 0;
+}
+
+int unlockShm(semid id){
+  if(!ReleaseSemaphore(id,1,NULL)){
+    return -1;
+  }
+  return 0;
+}
+
+static LPVOID lpvMemG = NULL;      // pointer to shared memory
+static HANDLE hMapObjectG = NULL;  // handle to file mapping
+
+
+char* getStatus(int pid){
+  char *lpszBuf=(char*) malloc(SHMEMSIZE*sizeof(char));
+  int i=0;
+  LPWSTR lpszTmp=NULL;
+  LPVOID lpvMem = NULL;
+  HANDLE hMapObject = NULL;
+  BOOL fIgnore,fInit;
+  char tmp[1024];
+  sprintf(tmp,"%d",pid);
+  if(hMapObject==NULL)
+    hMapObject = CreateFileMapping( 
+				   INVALID_HANDLE_VALUE,   // use paging file
+				   NULL,                   // default security attributes
+				   PAGE_READWRITE,         // read/write access
+				   0,                      // size: high 32-bits
+				   4096,                   // size: low 32-bits
+				   TEXT(tmp));   // name of map object
+  if (hMapObject == NULL){
+#ifdef DEBUG
+    fprintf(stderr,"ERROR on line %d\n",__LINE__);
+#endif
+    return "-1";
+  }
+  if((GetLastError() != ERROR_ALREADY_EXISTS)){
+#ifdef DEBUG
+    fprintf(stderr,"ERROR on line %d\n",__LINE__);
+    fprintf(stderr,"READING STRING S %s\n", getLastErrorMessage());
+#endif
+    fIgnore = UnmapViewOfFile(lpvMem); 
+    fIgnore = CloseHandle(hMapObject);
+    return "-1";
+  }
+  fInit=TRUE;
+  if(lpvMem==NULL)
+    lpvMem = MapViewOfFile( 
+			   hMapObject,     // object to map view of
+			   FILE_MAP_READ,  // read/write access
+			   0,              // high offset:  map from
+			   0,              // low offset:   beginning
+			   0);             // default: map entire file
+  if (lpvMem == NULL){
+#ifdef DEBUG
+    fprintf(stderr,"READING STRING S %d\n",__LINE__);
+    fprintf(stderr,"READING STRING S %s\n", getLastErrorMessage());
+#endif
+    return "-1"; 
+  }
+  lpszTmp = (LPWSTR) lpvMem;
+  while (*lpszTmp){
+    lpszBuf[i] = (char)*lpszTmp;
+    *lpszTmp++; 
+    lpszBuf[i+1] = '\0'; 
+    i++;
+  }
+  return (char*)lpszBuf;
+}
+
+#else
+/**
+ * Number of time to try to access a semaphores set
+ * @see getShmLockId
+ */
+#define MAX_RETRIES 10
+
+#ifndef __APPLE__
+/**
+ * arg for semctl system calls. 
+ */
+union semun {
+  int val; //!< value for SETVAL 
+  struct semid_ds *buf; //!< buffer for IPC_STAT & IPC_SET
+  ushort *array; //!< array for GETALL & SETALL
+};
+#endif
+
+/**
+ * Set in the pre-allocated key the zoo_sem_[OSID] string 
+ * where [OSID] is the lid (if any) or osid value from the [lenv] section.
+ *
+ * @param conf the map containing the setting of the main.cfg file
+ */
+int getKeyValue(maps* conf){
+  if(conf==NULL)
+     return 700666;
+  map *tmpMap=getMapFromMaps(conf,"lenv","lid");
+  if(tmpMap==NULL)
+    tmpMap=getMapFromMaps(conf,"lenv","osid");
+  int key=-1;
+  if(tmpMap!=NULL)
+    key=atoi(tmpMap->value);
+  return key;
+}
+
+/**
+ * Try to create or access a semaphore set.
+ *
+ * @see getKeyValue
+ * @param conf the map containing the setting of the main.cfg file
+ * @param nsems number of semaphores
+ * @return a semaphores set indentifier on success, -1 in other case
+ */
+int getShmLockId(maps* conf, int nsems){
+    int i;
+    union semun arg;
+    struct semid_ds buf;
+    struct sembuf sb;
+    semid sem_id;
+    int key=getKeyValue(conf);
+    
+    sem_id = semget(key, nsems, IPC_CREAT | IPC_EXCL | 0666);
+
+    if (sem_id >= 0) { /* we got it first */
+        sb.sem_op = 1; 
+	sb.sem_flg = 0;
+	arg.val=1;
+        for(sb.sem_num = 0; sb.sem_num < nsems; sb.sem_num++) { 
+            /* do a semop() to "free" the semaphores. */
+            /* this sets the sem_otime field, as needed below. */
+            if (semop(sem_id, &sb, 1) == -1) {
+                int e = errno;
+                semctl(sem_id, 0, IPC_RMID); /* clean up */
+                errno = e;
+                return -1; /* error, check errno */
+            }
+        }
+    } else if (errno == EEXIST) { /* someone else got it first */
+        int ready = 0;
+
+        sem_id = semget(key, nsems, 0); /* get the id */
+        if (sem_id < 0) return sem_id; /* error, check errno */
+
+        /* wait for other process to initialize the semaphore: */
+        arg.buf = &buf;
+        for(i = 0; i < MAX_RETRIES && !ready; i++) {
+            semctl(sem_id, nsems-1, IPC_STAT, arg);
+            if (arg.buf->sem_otime != 0) {
+#ifdef DEBUG
+	      fprintf(stderr,"Semaphore acquired ...\n");
+#endif
+	      ready = 1;
+            } else {
+#ifdef DEBUG
+	      fprintf(stderr,"Retry to access the semaphore later ...\n");
+#endif
+	      zSleep(1);
+            }
+        }
+	errno = ZOO_LOCK_ACQUIRE_FAILED;
+        if (!ready) {
+#ifdef DEBUG
+	  fprintf(stderr,"Unable to access the semaphore ...\n");
+#endif
+	  errno = ETIME;
+	  return -1;
+        }
+    } else {
+        return sem_id; /* error, check errno */
+    }
+#ifdef DEBUG
+    fprintf(stderr,"%d Created !\n",sem_id);
+#endif
+    return sem_id;
+}
+
+/**
+ * Try to remove a semaphore set.
+ *
+ * @param conf the map containing the setting of the main.cfg file
+ * @param nsems number of semaphores
+ * @return 0 if the semaphore can be removed, -1 in other case.
+ */
+int removeShmLock(maps* conf, int nsems){
+  union semun arg;
+  int sem_id=getShmLockId(conf,nsems);
+  if (semctl(sem_id, 0, IPC_RMID, arg) == -1) {
+#ifdef DEBUG
+    perror("semctl remove");
+#endif
+    return -1;
+  }
+#ifdef DEBUG
+  fprintf(stderr,"Semaphore removed!\n");
+#endif
+  return 0;
+}
+
+/**
+ * Lock a semaphore set.
+ *
+ * @param id the semaphores set indetifier
+ * @return 0 if the semaphore can be locked, -1 in other case.
+ */
+int lockShm(int id){
+  struct sembuf sb;
+  sb.sem_num = 0;
+  sb.sem_op = -1;  /* set to allocate resource */
+  sb.sem_flg = SEM_UNDO;
+  if (semop(id, &sb, 1) == -1){
+#ifdef DEBUG
+    perror("semop lock");
+#endif
+    return -1;
+  }
+  return 0;
+}
+
+/**
+ * unLock a semaphore set.
+ *
+ * @param id the semaphores set indetifier
+ * @return 0 if the semaphore can be locked, -1 in other case.
+ */
+int unlockShm(int id){
+  struct sembuf sb;
+  sb.sem_num = 0;
+  sb.sem_op = 1;  /* free resource */
+  sb.sem_flg = SEM_UNDO;
+  if (semop(id, &sb, 1) == -1) {
+#ifdef DEBUG
+    perror("semop unlock");
+#endif
+    return -1;
+  }
+  return 0;
+}
+
+/**
+ * Get the current status of the running service.
+ *
+ * @see getKeyValue, getShmLockId, lockShm
+ * @param pid the semaphores 
+ * @return 0 on success, -2 if shmget failed, -1 if shmat failed
+ */
+char* getStatus(int pid){
+  int shmid;
+  key_t key;
+  void *shm;
+  key=pid;
+  if ((shmid = shmget(key, SHMSZ, 0666)) < 0) {
+#ifdef DEBUG
+    fprintf(stderr,"shmget failed in getStatus\n");
+#endif
+  }else{
+    if ((shm = shmat(shmid, NULL, 0)) == (char *) -1) {
+#ifdef DEBUG
+      fprintf(stderr,"shmat failed in getStatus\n");
+#endif
+    }else{
+      char *ret=strdup((char*)shm);
+      shmdt((void *)shm);
+      return ret;
+    }
+  }
+  return (char*)"-1";
+}
+
+#endif
+
+/**
+ * Update the status of an ongoing service 
+ *
+ * @param conf the maps containing the settings of the main.cfg file
+ * @param percentCompleted percentage of completude of execution of the service
+ * @param message information about the current step executed
+ * @return the value of _updateStatus
+ * @see _updateStatus
+ */
+int updateStatus( maps* conf, const int percentCompleted, const char* message ){
+  char tmp[4];
+  snprintf(tmp,4,"%d",percentCompleted);
+  setMapInMaps( conf, "lenv", "status", tmp );
+  setMapInMaps( conf, "lenv", "message", message);
+  return _updateStatus( conf );
+}
+
+/**
+ * Access an input value 
+ *
+ * @param inputs the maps to search for the input value
+ * @param parameterName the input name to fetch the value
+ * @param numberOfBytes the resulting size of the value to add (for binary
+ *  values), -1 for basic char* data
+ * @return a pointer to the input value if found, NULL in other case.
+ */
+char* getInputValue( maps* inputs, const char* parameterName, size_t* numberOfBytes){
+  map* res=getMapFromMaps(inputs,parameterName,"value");
+  if(res!=NULL){
+    map* size=getMapFromMaps(inputs,parameterName,"size");
+    if(size!=NULL){
+      *numberOfBytes=(size_t)atoi(size->value);
+      return res->value;
+    }else{
+      *numberOfBytes=strlen(res->value);
+      return res->value;
+    }
+  }
+  return NULL;
+}
+
+/**
+ * Read a file using the GDAL VSI API 
+ *
+ * @param conf the maps containing the settings of the main.cfg file
+ * @param dataSource the datasource name to read
+ * @warning make sure to free ressources returned by this function
+ */
+char *readVSIFile(maps* conf,const char* dataSource){
+    VSILFILE * fichier=VSIFOpenL(dataSource,"rb");
+    VSIStatBufL file_status;
+    VSIStatL(dataSource, &file_status);
+    if(fichier==NULL){
+      char tmp[1024];
+      sprintf(tmp,"Failed to open file %s for reading purpose. File seems empty %lld.",
+	      dataSource,file_status.st_size);
+      setMapInMaps(conf,"lenv","message",tmp);
+      return NULL;
+    }
+    char *res1=(char *)malloc(file_status.st_size*sizeof(char));
+    VSIFReadL(res1,1,file_status.st_size*sizeof(char),fichier);
+    res1[file_status.st_size-1]=0;
+    VSIFCloseL(fichier);
+    VSIUnlink(dataSource);
+    return res1;
+}
+
+/**
+ * Set an output value 
+ *
+ * @param outputs the maps to define the output value
+ * @param parameterName the output name to set the value
+ * @param data the value to set
+ * @param numberOfBytes size of the value to add (for binary values), -1 for
+ *  basic char* data
+ * @return 0
+ */
+int  setOutputValue( maps* outputs, const char* parameterName, char* data, size_t numberOfBytes ){
+  if(numberOfBytes==-1){
+    setMapInMaps(outputs,parameterName,"value",data);
+  }else{
+    char size[1024];
+    map* tmp=getMapFromMaps(outputs,parameterName,"value");
+    if(tmp==NULL){
+      setMapInMaps(outputs,parameterName,"value","");
+      tmp=getMapFromMaps(outputs,parameterName,"value");
+    }
+    free(tmp->value);
+    tmp->value=(char*) malloc((numberOfBytes+1)*sizeof(char));
+    memcpy(tmp->value,data,numberOfBytes);
+    sprintf(size,"%lu",numberOfBytes);
+    setMapInMaps(outputs,parameterName,"size",size);
+  }
+  return 0;
+}
+
diff --git a/zoo-project/zoo-kernel/service_internal.h b/zoo-project/zoo-kernel/service_internal.h
new file mode 100644
index 0000000..9891cfa
--- /dev/null
+++ b/zoo-project/zoo-kernel/service_internal.h
@@ -0,0 +1,131 @@
+/*
+ * Author : Gérald FENOY
+ *
+ * Copyright (c) 2009-2013 GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef ZOO_SERVICE_INTERNAL_H
+#define ZOO_SERVICE_INTERNAL_H 1
+
+#pragma once 
+
+/**
+ * The default service url (overriden by serverAddress)
+ */
+#define DEFAULT_SERVICE_URL "http://www.zoo-project.org/"
+/**
+ * The time size
+ */
+#define TIME_SIZE 40
+
+#include <libintl.h>
+#include <locale.h>
+/**
+ * ZOO-Kernel internal messages translation function
+ */
+#define _(String) dgettext ("zoo-kernel",String)
+/**
+ * ZOO-Services messages translation function
+ */
+#define _ss(String) dgettext ("zoo-services",String)
+
+/**
+ * ZOO-Kernel was unable to create a lock
+ */
+#define ZOO_LOCK_CREATE_FAILED -4
+/**
+ * ZOO-Kernel was unable to acquire a lock
+ */
+#define ZOO_LOCK_ACQUIRE_FAILED -5
+/**
+ * ZOO-Kernel was unable to release a lock
+ */
+#define ZOO_LOCK_RELEASE_FAILED -6
+/**
+ * Number of time the ZOO-Kernel will try to acquire lock
+ */
+#define ZOO_LOCK_MAX_RETRY 10
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include "cgic.h"
+#ifndef WIN32
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/sem.h>
+#else
+#include <direct.h>
+#endif
+#include <stdio.h>
+#include <time.h>
+#include <ctype.h>
+#ifndef USE_RUBY
+#include <unistd.h>
+#endif
+#ifndef WIN32
+#include <xlocale.h>
+#endif
+
+#include "service.h"
+
+#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__))
+
+#include <CoreServices/CoreServices.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+  ZOO_DLL_EXPORT char *readVSIFile(maps*,const char*);
+  ZOO_DLL_EXPORT int  setOutputValue( maps*, const char*, char*, size_t);
+  ZOO_DLL_EXPORT char* getInputValue( maps*,const char*,size_t*);
+
+  ZOO_DLL_EXPORT void unhandleStatus(maps*);
+  ZOO_DLL_EXPORT int _updateStatus(maps*);
+  ZOO_DLL_EXPORT char* _getStatus(maps*,char*);
+  ZOO_DLL_EXPORT char* _getStatusFile(maps*,char*);
+  ZOO_DLL_EXPORT char* getStatus(int);
+  ZOO_DLL_EXPORT char* getStatusId(maps*,char*);
+
+  ZOO_DLL_EXPORT int updateStatus( maps*,const int,const char*);
+  ZOO_DLL_EXPORT int removeShmLock(maps*, int);
+  /**
+   * Cross platform type used for Lock identifier
+   */
+#ifndef WIN32
+#define semid int
+#else
+#include <windows.h>
+#define semid HANDLE
+#endif
+  ZOO_DLL_EXPORT semid acquireLock(maps*);
+  ZOO_DLL_EXPORT semid getShmLockId(maps*,int);
+  ZOO_DLL_EXPORT int lockShm(semid);
+  ZOO_DLL_EXPORT int unlockShm(semid);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/zoo-project/zoo-kernel/service_internal_java.c b/zoo-project/zoo-kernel/service_internal_java.c
new file mode 100644
index 0000000..bac3a4d
--- /dev/null
+++ b/zoo-project/zoo-kernel/service_internal_java.c
@@ -0,0 +1,732 @@
+/*
+ * Author : Gérald FENOY
+ *
+ * Copyright (c) 2009-2013 GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "service_internal_java.h"
+#include "response_print.h"
+
+/**
+ * Load a JAVA class then run the static public method corresponding to the 
+ * service by passing the conf, inputs and outputs parameters by reference.
+ *
+ * @param main_conf the conf maps containing the main.cfg settings
+ * @param request the map containing the HTTP request
+ * @param s the service structure
+ * @param real_inputs the maps containing the inputs
+ * @param real_outputs the maps containing the outputs
+ */
+int zoo_java_support(maps** main_conf,map* request,service* s,maps **real_inputs,maps **real_outputs){
+  maps* m=*main_conf;
+  maps* inputs=*real_inputs;
+  maps* outputs=*real_outputs;
+  char ntmp[1024];
+  getcwd(ntmp,1024);
+  map* tmp=getMap(request,"metapath");
+  char *classpath;
+  char *oclasspath;
+  int res=SERVICE_FAILED;
+  char *cclasspath=getenv("CLASSPATH");
+  if(tmp!=NULL){
+    if(cclasspath!=NULL){
+      classpath=(char*) malloc((strlen(ntmp)+strlen(tmp->value)+strlen(cclasspath)+4)*sizeof(char));
+      oclasspath=(char*) malloc((strlen(ntmp)+strlen(tmp->value)+strlen(cclasspath)+22)*sizeof(char));
+#ifndef WIN32
+      sprintf(classpath,"%s/%s/:%s",ntmp,tmp->value,cclasspath);
+#else
+      sprintf(classpath,"%s/%s/;%s",ntmp,tmp->value,cclasspath);
+#endif
+    }
+    else{
+      classpath=(char*) malloc((strlen(ntmp)+strlen(tmp->value)+3)*sizeof(char));
+      oclasspath=(char*) malloc((strlen(ntmp)+strlen(tmp->value)+21)*sizeof(char));
+      sprintf(classpath,"%s/%s/",ntmp,tmp->value);
+    }
+  }else{
+    if(cclasspath!=NULL){
+      classpath=(char*) malloc((strlen(ntmp)+strlen(cclasspath)+3)*sizeof(char));
+      oclasspath=(char*) malloc((strlen(ntmp)+strlen(cclasspath)+21)*sizeof(char));
+#ifndef WIN32
+      sprintf(classpath,"%s/:%s",ntmp,cclasspath);
+#else
+      sprintf(classpath,"%s/;%s",ntmp,cclasspath);
+#endif
+    }
+    else{
+      classpath=(char*) malloc((strlen(ntmp)+2)*sizeof(char));
+      oclasspath=(char*) malloc((strlen(ntmp)+20)*sizeof(char));
+      sprintf(classpath,"%s/",ntmp);
+    }
+
+  }
+  sprintf(oclasspath,"-Djava.class.path=%s",classpath);
+
+#ifdef DEBUG
+  fprintf(stderr,"CLASSPATH=%s\n",classpath);
+  fprintf(stderr,"(%s)\n",oclasspath);
+#endif
+
+  int nb=1;
+  int nbc0=0;
+  maps* javaXXMap=getMaps(*main_conf,"javaxx");
+  if(javaXXMap!=NULL){
+    nbc0+=count(javaXXMap->content);
+  }
+  int nbc1=0;
+  maps* javaXMap=getMaps(*main_conf,"javax");
+  if(javaXMap!=NULL){
+    nbc1+=count(javaXMap->content);
+  }
+#ifdef WIN32
+  nb=2+nbc0+nbc1;
+  JavaVMOption options[nb];
+#else
+  JavaVMOption options[nb+nbc0+nbc1];
+#endif
+  JavaVMInitArgs vm_args;
+  JavaVM *jvm;
+  JNIEnv *env;
+  long result;
+  jmethodID pmid;
+  jclass cls;
+#ifdef JAVA7
+  jobject cls_gr;
+#else
+  jclass cls_gr;
+#endif
+  int i,start;
+  map *cursorxx=NULL;
+  if(javaXXMap!=NULL)
+    cursorxx=javaXXMap->content;
+  map *cursorx=NULL;
+  if(javaXMap!=NULL)
+    cursorx=javaXMap->content;
+  options[0].optionString = oclasspath;
+#ifdef WIN32
+  start=2;
+  options[1].optionString = "-Xmx512m";
+#else
+  start=1;
+#endif
+  for(i=0;i<nbc0;i++){
+    char *tmp=parseJVMXXOption(cursorxx);
+    options[start+i].optionString = tmp;
+    free(tmp);
+    cursorxx=cursorxx->next;
+  }
+  for(;i<nbc1+nbc0;i++){
+    char *tmp=parseJVMXOption(cursorx);
+    options[start+i].optionString = tmp;
+    free(tmp);
+    cursorx=cursorx->next;
+  }
+
+  JNI_GetDefaultJavaVMInitArgs(&vm_args);
+  vm_args.version = JNI_VERSION_1_6;
+  vm_args.options = options;
+  vm_args.nOptions = start+nbc0+nbc1;
+  vm_args.ignoreUnrecognized = JNI_TRUE;
+
+  result = JNI_CreateJavaVM(&jvm,(void **)&env, &vm_args);
+  if(result == JNI_ERR ) {
+    fprintf(stderr,"Error invoking the JVM");
+    return -1;
+  }
+#ifdef DEBUG
+  else
+    fprintf(stderr,"JAVA VM Started\n");
+#endif
+
+  tmp=getMap(s->content,"serviceProvider");
+#ifdef JAVA7
+  cls = env->FindClass(tmp->value);
+  cls_gr = env->NewGlobalRef(cls);
+#else
+  cls = (*env)->FindClass(env,tmp->value);
+  cls_gr = (*env)->NewGlobalRef(env, cls);
+#endif
+  if( cls == NULL ) {
+    displayStack(env,*main_conf);
+#ifdef JAVA7
+    (*jvm).DestroyJavaVM();
+#else
+    (*jvm)->DestroyJavaVM(jvm);
+#endif
+    return -1;
+  }
+#ifdef DEBUG
+  else{
+    fprintf(stderr,"%s loaded\n",tmp->value);
+  }
+#endif
+
+  if (cls != NULL) {
+#ifdef JAVA7
+    (*env).ExceptionClear();
+    pmid=(*env).GetStaticMethodID(cls, s->name, "(Ljava/util/HashMap;Ljava/util/HashMap;Ljava/util/HashMap;)I");
+#else
+    (*env)->ExceptionClear(env);
+    pmid=(*env)->GetStaticMethodID(env,cls_gr, s->name, "(Ljava/util/HashMap;Ljava/util/HashMap;Ljava/util/HashMap;)I");
+#endif
+    if (pmid!=0){
+#ifdef DEBUG
+      fprintf(stderr,"Function successfully loaded\n");
+#endif
+      jclass scHashMapClass,scHashMap_class;
+      jmethodID scHashMap_constructor;
+#ifdef JAVA7
+      scHashMapClass = (*env).FindClass("java/util/HashMap");
+      scHashMap_class = (jclass)(*env).NewGlobalRef(scHashMapClass);
+      scHashMap_constructor = (*env).GetMethodID(scHashMap_class, "<init>", "()V");
+#else
+      scHashMapClass = (*env)->FindClass(env, "java/util/HashMap");
+      scHashMap_class = (*env)->NewGlobalRef(env, scHashMapClass);
+      scHashMap_constructor = (*env)->GetMethodID(env, scHashMap_class, "<init>", "()V");
+#endif
+      /**
+       * The 3 standard parameter for each services
+       */
+      jobject arg1=HashMap_FromMaps(env,m,scHashMapClass,scHashMap_class,scHashMap_constructor);
+      jobject arg2=HashMap_FromMaps(env,inputs,scHashMapClass,scHashMap_class,scHashMap_constructor);
+      jobject arg3=HashMap_FromMaps(env,outputs,scHashMapClass,scHashMap_class,scHashMap_constructor);
+      jint pValue=0;
+
+#ifdef JAVA7
+      pValue=(*env).CallStaticIntMethod(cls,pmid,arg1,arg2,arg3);
+#else
+      pValue=(*env)->CallStaticIntMethod(env,cls,pmid,arg1,arg2,arg3);
+#endif
+      if (pValue != (jint)NULL){
+	res=pValue;
+	m=mapsFromHashMap(env,arg1,scHashMapClass);
+	*main_conf=m;
+	outputs=mapsFromHashMap(env,arg3,scHashMapClass);
+	*real_outputs=outputs;
+
+#ifdef DEBUG
+	fprintf(stderr,"Result of call: %i\n", pValue);
+	dumpMaps(inputs);
+	dumpMaps(outputs);
+#endif
+      }else{
+	displayStack(env,*main_conf);
+#ifdef JAVA7
+	(*jvm).DestroyJavaVM();
+#else
+	(*jvm)->DestroyJavaVM(jvm);
+#endif
+	return -1;
+      }
+    }
+    else{
+      displayStack(env,*main_conf);
+#ifdef JAVA7
+      (*jvm).DestroyJavaVM();
+#else
+      (*jvm)->DestroyJavaVM(jvm);
+#endif
+      return -1;
+    }
+  }
+#ifdef JAVA7
+      (*jvm).DestroyJavaVM();
+#else
+  (*jvm)->DestroyJavaVM(jvm);
+#endif
+  return res;
+}
+
+/**
+ * Error handling: display stack trace in an ExceptionReport Document
+ *
+ * @param env the JNI environment pointer
+ * @param main_conf the conf maps containing the main.cfg settings
+ */
+void displayStack(JNIEnv *env,maps* main_conf){
+  map *tmpm=getMapFromMaps(main_conf,"main","tmpPath");
+  char tmps[1024];
+  sprintf(tmps,"%s/%d.ztmp",tmpm->value,getpid());
+  FILE* new_stdout=fopen(tmps,"wb+");
+  if(new_stdout==NULL){
+    map* err=createMap("text","Unable to run your service, no debug informations can be provided (please verify privileges on tmpPath)");
+    addToMap(err,"code","InternalError");
+    printExceptionReportResponse(main_conf,err);
+    freeMap(&err);
+    free(err);
+    return;
+  }
+  fflush(stderr);
+  dup2(fileno(new_stdout),fileno(stderr));
+  fprintf(stderr,"Unable to run your java process properly: ");
+  fflush(stderr);
+#ifdef JAVA7
+  (*env).ExceptionDescribe();
+#else
+  (*env)->ExceptionDescribe(env);
+#endif
+  fflush(new_stdout);
+  fseek(new_stdout, 0, SEEK_END);
+  long flen=ftell(new_stdout);
+  fseek(new_stdout, 0, SEEK_SET);
+  char *tmps1=(char*)malloc((flen+1)*sizeof(char));
+  fread(tmps1,flen,1,new_stdout);
+  fclose(new_stdout);
+  tmps1[flen]=0;
+  map* err=createMap("text",tmps1);
+  addToMap(err,"code","InternalError");
+  printExceptionReportResponse(main_conf,err);
+  freeMap(&err);
+  free(err);
+}
+
+/**
+ * Create a string containing the JVM -XX:* option for a given map
+ * Depending on the map' name:
+ *  - in case the value is minus then the result will be : -XX:-name
+ *  - in case the value is plus then the result will be : -XX:+name
+ *  - in other cases the result will be : -XX:name=value
+ *
+ * @param m the map containing the option
+ * @return a char* containing the valide JVM option (-XX:*)
+ */
+char *parseJVMXXOption(map* m){
+  char *res=(char*)malloc((strlen(m->name)+strlen(m->value)+5)*sizeof(char));
+  if(strncasecmp(m->value,"minus",5)==0)
+    sprintf(res,"-XX:-%s",m->name);
+  else if(strncasecmp(m->value,"plus",5)==0)
+    sprintf(res,"-XX:+%s",m->name);
+  else
+    sprintf(res,"-XX:%s=%s",m->name,m->value);
+  return res;
+}
+
+/**
+ * Create a string containing the JVM -X** option for a given map.
+ * The result will be in the following format: -Xnamevalue
+ *
+ * @param m the map containing the option
+ * @return a char* containing the valide JVM option (-X**)
+ */
+char *parseJVMXOption(map* m){
+  char *res=(char*)malloc((strlen(m->name)+strlen(m->value)+5)*sizeof(char));
+  sprintf(res,"-X%s%s",m->name,m->value);
+  return res;
+}
+
+/**
+ * Convert a maps to a JAVA HashMap<String,HashMap<String,String>>
+ *
+ * @param env the JNI environment pointer
+ * @param t the maps to convert
+ * @param scHashMapClass the HashMap class
+ * @param scHashMap_class the HashMap class
+ * @param scHashMap_constructor the pointer to the hashMap constructor method
+ * @return a created JAVA HashMap containing the converted maps
+ * @warning make sure to free ressources returned by this function
+ */
+jobject HashMap_FromMaps(JNIEnv *env,maps* t,jclass scHashMapClass,jclass scHashMap_class,jmethodID scHashMap_constructor){
+  jobject scObject,scObject1;
+  if(scHashMap_constructor!=NULL){
+#ifdef JAVA7
+    scObject = (*env).NewObject(scHashMap_class, scHashMap_constructor);
+#else
+    scObject = (*env)->NewObject(env, scHashMap_class, scHashMap_constructor);
+#endif
+    jmethodID put_mid = 0;
+
+#ifdef JAVA7
+    put_mid = (*env).GetMethodID(scHashMapClass, "put",
+				  "(Ljava/lang/Object;Ljava/lang/Object;)"
+				  "Ljava/lang/Object;");
+#else
+    put_mid = (*env)->GetMethodID(env,scHashMapClass, "put",
+				  "(Ljava/lang/Object;Ljava/lang/Object;)"
+				  "Ljava/lang/Object;");
+#endif
+    maps* tmp=t;
+    while(tmp!=NULL){
+      map* tmap=getMapType(tmp->content);
+      map* tmp1=tmp->content;
+#ifdef JAVA7
+      scObject1 = (*env).NewObject(scHashMap_class, scHashMap_constructor);
+#else
+      scObject1 = (*env)->NewObject(env, scHashMap_class, scHashMap_constructor);
+#endif
+      map* sizeV=getMap(tmp1,"size");
+      map* isArray=getMap(tmp1,"isArray");
+      map* alen=getMap(tmp1,"length");
+      while(tmp1!=NULL){
+	if(strcmp(tmp1->name,"value")==0){
+	  if(isArray==NULL){
+	    if(sizeV!=NULL && strcmp(tmp1->name,"value")==0){
+#ifdef JAVA7
+	      jbyteArray tmpData=(*env).NewByteArray(atoi(sizeV->value));
+	      (*env).SetByteArrayRegion(tmpData,0,atoi(sizeV->value),(const jbyte *)tmp1->value);
+	      (*env).CallObjectMethod(scObject1, put_mid, (*env).NewStringUTF(tmp1->name), tmpData);
+#else
+	      jbyteArray tmpData=(*env)->NewByteArray(env,atoi(sizeV->value));
+	      (*env)->SetByteArrayRegion(env,tmpData,0,atoi(sizeV->value),tmp1->value);
+	      (*env)->CallObjectMethod(env,scObject1, put_mid, (*env)->NewStringUTF(env,tmp1->name), tmpData);
+#endif
+	    }else
+#ifdef JAVA7
+	      (*env).CallObjectMethod(scObject1, put_mid, (*env).NewStringUTF(tmp1->name), (*env).NewStringUTF(tmp1->value));
+#else
+	      (*env)->CallObjectMethod(env,scObject1, put_mid, (*env)->NewStringUTF(env,tmp1->name), (*env)->NewStringUTF(env,tmp1->value));
+#endif
+	  }
+	  else{
+	    int alen1=atoi(alen->value);
+	    fprintf(stderr,"LENGTH %d \n",alen1);
+	    
+	    jclass scArrayListClass,scArrayList_class;
+	    jmethodID scArrayList_constructor;
+	    jobject scObject2;
+#ifdef JAVA7
+	    scArrayListClass = (*env).FindClass("java/util/ArrayList");
+	    scArrayList_class = (jclass)(*env).NewGlobalRef(scArrayListClass);
+	    scArrayList_constructor = (*env).GetMethodID(scArrayList_class, "<init>", "()V");
+	    jmethodID add_mid = 0;
+	    scObject2 = (*env).NewObject(scArrayList_class, scArrayList_constructor);
+
+	    add_mid = (*env).GetMethodID(scArrayListClass,
+					  "add","(Ljava/lang/Object;)Z");
+#else
+	    scArrayListClass = (*env)->FindClass(env, "java/util/ArrayList");
+	    scArrayList_class = (*env)->NewGlobalRef(env, scArrayListClass);
+	    scArrayList_constructor = (*env)->GetMethodID(env, scArrayList_class, "<init>", "()V");
+	    jmethodID add_mid = 0;
+	    scObject2 = (*env)->NewObject(env, scArrayList_class, scArrayList_constructor);
+
+	    add_mid = (*env)->GetMethodID(env,scArrayListClass,
+					  "add","(Ljava/lang/Object;)Z");
+#endif	    
+	    int i;
+	    
+	    for(i=0;i<alen1;i++){
+	      map* vMap=getMapArray(tmp->content,"value",i);	    
+	      map* sMap=getMapArray(tmp->content,"size",i);
+	      map* mMap=getMapArray(tmp->content,tmap->value,i);
+	      
+	      if(sMap!=NULL && vMap!=NULL && strncmp(vMap->name,"value",5)==0){
+#ifdef JAVA7
+		jbyteArray tmpData=(*env).NewByteArray(atoi(sMap->value));
+		(*env).SetByteArrayRegion(tmpData,0,atoi(sMap->value),(const jbyte *)vMap->value);
+		(*env).CallObjectMethod(scObject2, add_mid, tmpData);
+#else
+		jbyteArray tmpData=(*env)->NewByteArray(env,atoi(sMap->value));
+		(*env)->SetByteArrayRegion(env,tmpData,0,atoi(sMap->value),vMap->value);
+		(*env)->CallObjectMethod(env,scObject2, add_mid, tmpData);
+#endif
+	      }else{
+#ifdef JAVA7
+		jobject tmpData=(*env).NewStringUTF(vMap->value);
+		(*env).CallObjectMethod(scObject2, add_mid, tmpData);
+#else
+		jobject tmpData=(*env)->NewStringUTF(env,vMap->value);
+		(*env)->CallObjectMethod(env,scObject2, add_mid, tmpData);
+#endif
+	      }
+	      
+	    }
+
+#ifdef JAVA7
+	    (*env).CallObjectMethod(scObject1, put_mid, (*env).NewStringUTF(tmp1->name), scObject2);
+#else	    
+	    (*env)->CallObjectMethod(env,scObject1, put_mid, (*env)->NewStringUTF(env,tmp1->name), scObject2);
+#endif
+
+	  }
+	}
+	else
+#ifdef JAVA7
+	  (*env).CallObjectMethod(scObject1, put_mid, (*env).NewStringUTF(tmp1->name), (*env).NewStringUTF(tmp1->value));
+#else
+	  (*env)->CallObjectMethod(env,scObject1, put_mid, (*env)->NewStringUTF(env,tmp1->name), (*env)->NewStringUTF(env,tmp1->value));
+#endif
+	tmp1=tmp1->next;
+      }
+#ifdef JAVA7
+      (*env).CallObjectMethod(scObject, put_mid, (*env).NewStringUTF(tmp->name), scObject1);
+#else
+      (*env)->CallObjectMethod(env,scObject, put_mid, (*env)->NewStringUTF(env,tmp->name), scObject1);
+#endif
+      tmp=tmp->next;
+    }
+    return scObject;
+  }
+  else
+    return NULL;
+}
+
+/**
+ * Convert a JAVA HashMap<String,HashMap<String,String>> to a maps
+ *
+ * @param env the JNI environment pointer
+ * @param t the HashMap 
+ * @param scHashMapClass the hashMap class
+ * @return a created maps containing the converted HashMap
+ * @warning make sure to free ressources returned by this function
+ */
+maps* mapsFromHashMap(JNIEnv *env,jobject t,jclass scHashMapClass){
+#ifdef DEBUG
+  fprintf(stderr,"mapsFromHashMap start\n");
+#endif
+  /**
+   * What need to be done (in java).
+   * Set set = hm.entrySet();
+   * Iterator i = set.iterator();
+   * while(i.hasNext()){
+   *   Map.Entry me = (Map.Entry)i.next();
+   *   System.out.println(me.getKey() + " : " + me.getValue() );
+   * }
+   */
+  jclass scSetClass,scIteratorClass,scMapEntryClass;
+  jmethodID entrySet_mid,containsKey_mid,get_mid,iterator_mid,hasNext_mid,next_mid,getKey_mid,getValue_mid;
+  if(scHashMapClass==NULL){
+#ifdef DEBUG
+    fprintf(stderr,"Unable to load java.util.HashMap\n");
+#endif
+    return NULL;
+  }
+#ifdef JAVA7
+  entrySet_mid = (*env).GetMethodID(scHashMapClass, "entrySet", "()Ljava/util/Set;"); 
+  containsKey_mid = (*env).GetMethodID(scHashMapClass, "containsKey", "(Ljava/lang/Object;)Z");
+  get_mid = (*env).GetMethodID(scHashMapClass, "get", "(Ljava/lang/Object;)Ljava/lang/Object;"); 
+#else
+  entrySet_mid = (*env)->GetMethodID(env, scHashMapClass, "entrySet", "()Ljava/util/Set;"); 
+  containsKey_mid = (*env)->GetMethodID(env, scHashMapClass, "containsKey", "(Ljava/lang/Object;)Z");
+  get_mid = (*env)->GetMethodID(env, scHashMapClass, "get", "(Ljava/lang/Object;)Ljava/lang/Object;"); 
+#endif
+
+  if(containsKey_mid==0){
+#ifdef DEBUG
+    fprintf(stderr,"unable to load containsKey from HashMap object (%d) \n",entrySet_mid);
+#endif
+    return NULL;
+  }
+  if(get_mid==0){
+#ifdef DEBUG
+    fprintf(stderr,"unable to load get from HashMap object (%d) \n",entrySet_mid);
+#endif
+    return NULL;
+  }
+  if(entrySet_mid==0){
+#ifdef DEBUG
+    fprintf(stderr,"unable to load entrySet from HashMap object (%d) \n",entrySet_mid);
+#endif
+    return NULL;
+  }
+#ifdef DEBUG
+  else
+    fprintf(stderr,"entrySet loaded from HashMap object (%d) \n",entrySet_mid);
+#endif
+
+#ifdef JAVA7
+  scSetClass = (*env).FindClass("java/util/Set");
+  iterator_mid = (*env).GetMethodID(scSetClass, "iterator", "()Ljava/util/Iterator;"); 
+#else
+  scSetClass = (*env)->FindClass(env, "java/util/Set");
+  iterator_mid = (*env)->GetMethodID(env, scSetClass, "iterator", "()Ljava/util/Iterator;"); 
+#endif
+#ifdef DEBUG
+  fprintf(stderr,"mapsFromHashMap 1 (%d) \n",iterator_mid);
+#endif
+
+#ifdef JAVA7
+  scIteratorClass = (*env).FindClass("java/util/Iterator");
+  hasNext_mid = (*env).GetMethodID(scIteratorClass, "hasNext", "()Z");
+#else
+  scIteratorClass = (*env)->FindClass(env, "java/util/Iterator");
+  hasNext_mid = (*env)->GetMethodID(env, scIteratorClass, "hasNext", "()Z");
+#endif
+
+#ifdef DEBUG
+  fprintf(stderr,"mapsFromHashMap 2 (%d)\n",hasNext_mid);
+#endif
+
+#ifdef JAVA7
+  next_mid = (*env).GetMethodID(scIteratorClass, "next", "()Ljava/lang/Object;");
+#else
+  next_mid = (*env)->GetMethodID(env, scIteratorClass, "next", "()Ljava/lang/Object;");
+#endif
+#ifdef DEBUG
+  fprintf(stderr,"mapsFromHashMap 3 (%d)\n",next_mid);
+#endif
+
+#ifdef JAVA7
+  scMapEntryClass = (*env).FindClass("java/util/Map$Entry");
+  getKey_mid = (*env).GetMethodID(scMapEntryClass, "getKey", "()Ljava/lang/Object;");
+#else
+  scMapEntryClass = (*env)->FindClass(env, "java/util/Map$Entry");
+  getKey_mid = (*env)->GetMethodID(env, scMapEntryClass, "getKey", "()Ljava/lang/Object;");
+#endif
+#ifdef DEBUG
+  fprintf(stderr,"mapsFromHashMap 4 (%d)\n",getKey_mid);
+#endif
+#ifdef JAVA7
+  getValue_mid = (*env).GetMethodID(scMapEntryClass, "getValue", "()Ljava/lang/Object;");
+#else
+  getValue_mid = (*env)->GetMethodID(env, scMapEntryClass, "getValue", "()Ljava/lang/Object;");
+#endif
+#ifdef DEBUG
+  fprintf(stderr,"mapsFromHashMap 5 (%d)\n",getValue_mid);
+#endif
+
+#ifdef JAVA7
+  jobject final_set=(*env).CallObjectMethod(t,entrySet_mid);
+  jobject final_iterator=(*env).CallObjectMethod(final_set,iterator_mid);
+#else
+  jobject final_set=(*env)->CallObjectMethod(env,t,entrySet_mid);
+  jobject final_iterator=(*env)->CallObjectMethod(env,final_set,iterator_mid);
+#endif
+
+  maps* final_res=NULL;
+  map* res=NULL;
+#ifdef JAVA7
+  while((*env).CallBooleanMethod(final_iterator,hasNext_mid)){
+    jobject tmp=(*env).CallObjectMethod(final_iterator,next_mid);
+
+    jobject imap=(*env).CallObjectMethod(tmp,getValue_mid);
+    jobject set=(*env).CallObjectMethod(imap,entrySet_mid);
+    jobject iterator=(*env).CallObjectMethod(set,iterator_mid);
+
+#else
+  while((*env)->CallBooleanMethod(env,final_iterator,hasNext_mid)){
+    jobject tmp=(*env)->CallObjectMethod(env,final_iterator,next_mid);
+
+    jobject imap=(*env)->CallObjectMethod(env,tmp,getValue_mid);
+    jobject set=(*env)->CallObjectMethod(env,imap,entrySet_mid);
+    jobject iterator=(*env)->CallObjectMethod(env,set,iterator_mid);
+
+#endif
+    int size=-1;
+#ifdef JAVA7
+    if((*env).CallBooleanMethod(imap,containsKey_mid,(*env).NewStringUTF("size"))){
+      jobject sizeV=(*env).CallObjectMethod(imap, get_mid,(*env).NewStringUTF("size"));
+      const char* sizeVS=(*env).GetStringUTFChars((jstring)sizeV, NULL);
+#else
+    if((*env)->CallBooleanMethod(env,imap,containsKey_mid,(*env)->NewStringUTF(env,"size"))){
+      jobject sizeV=(*env)->CallObjectMethod(env, imap, get_mid,(*env)->NewStringUTF(env,"size"));
+      const char* sizeVS=(*env)->GetStringUTFChars(env, sizeV, NULL);
+#endif
+      size=atoi(sizeVS);
+      fprintf(stderr,"SIZE : %s\n",sizeVS);
+#ifdef JAVA7
+      (*env).ReleaseStringUTFChars((jstring)sizeV, sizeVS);
+#else
+      (*env)->ReleaseStringUTFChars(env, sizeV, sizeVS);
+#endif
+    }
+    
+#ifdef JAVA7
+    while((*env).CallBooleanMethod(iterator,hasNext_mid)){
+      jobject tmp1=(*env).CallObjectMethod(iterator,next_mid);
+      jobject jk=(*env).CallObjectMethod(tmp1,getKey_mid);
+      jobject jv=(*env).CallObjectMethod(tmp1,getValue_mid);
+
+      const char* jkd=(*env).GetStringUTFChars((jstring)jk, NULL);
+#else
+    while((*env)->CallBooleanMethod(env,iterator,hasNext_mid)){
+      jobject tmp1=(*env)->CallObjectMethod(env,iterator,next_mid);
+      jobject jk=(*env)->CallObjectMethod(env,tmp1,getKey_mid);
+      jobject jv=(*env)->CallObjectMethod(env,tmp1,getValue_mid);
+
+      const char* jkd=(*env)->GetStringUTFChars(env, jk, NULL);
+#endif
+      if(size>=0 && strcmp(jkd,"value")==0){
+#ifdef JAVA7
+	jobject value=(jobject)(*env).GetByteArrayElements((jbyteArray)jv, NULL);
+#else
+	jobject value=(*env)->GetByteArrayElements(env, jv, NULL);
+#endif
+	if(res==NULL){
+	  res=createMap(jkd,"");
+	}else{
+	  addToMap(res,jkd,"");
+	}
+	map* tmpR=getMap(res,"value");
+	free(tmpR->value);
+	tmpR->value=(char*)malloc((size+1)*sizeof(char));
+	memmove(tmpR->value,value,size*sizeof(char));
+	tmpR->value[size]=0;
+	char tmp[128];
+	sprintf(tmp,"%d",size);
+	addToMap(res,"size",tmp);
+      }
+      else{
+#ifdef JAVA7
+	const char* jvd=(*env).GetStringUTFChars((jstring)jv, NULL);
+#else
+	const char* jvd=(*env)->GetStringUTFChars(env, jv, NULL);
+#endif
+	if(res==NULL){
+	  res=createMap(jkd,jvd);
+	}else{
+	  addToMap(res,jkd,jvd);
+	}
+#ifdef JAVA7
+	(*env).ReleaseStringUTFChars((jstring)jv, jvd);
+#else
+	(*env)->ReleaseStringUTFChars(env, jv, jvd);
+#endif
+      }
+
+#ifdef JAVA7
+      (*env).ReleaseStringUTFChars((jstring)jk, jkd);
+#else
+      (*env)->ReleaseStringUTFChars(env, jk, jkd);
+#endif
+
+    }
+#ifdef JAVA7
+    jobject jk=(*env).CallObjectMethod(tmp,getKey_mid);
+#else
+    jobject jk=(*env)->CallObjectMethod(env,tmp,getKey_mid);
+#endif
+    maps* cmap=(maps*)malloc(sizeof(maps));
+#ifdef JAVA7
+    cmap->name=(char*)(*env).GetStringUTFChars((jstring)jk, NULL);
+#else
+    cmap->name=(*env)->GetStringUTFChars(env, jk, NULL);
+#endif
+#ifdef DEBUG
+    fprintf(stderr," / %s \n",cmap->name);
+#endif
+    cmap->content=res;
+    cmap->next=NULL;
+    if(final_res==NULL)
+      final_res=dupMaps(&cmap);
+    else
+      addMapsToMaps(&final_res,cmap);
+    freeMaps(&cmap);
+    free(cmap);
+    cmap=NULL;
+    res=NULL;
+  }
+#ifdef DEBUG
+  fprintf(stderr,"mapsFromHashMap end\n");
+#endif
+
+  return final_res;
+}
+
diff --git a/zoo-project/zoo-kernel/service_internal_java.h b/zoo-project/zoo-kernel/service_internal_java.h
new file mode 100644
index 0000000..e26b87b
--- /dev/null
+++ b/zoo-project/zoo-kernel/service_internal_java.h
@@ -0,0 +1,52 @@
+/*
+ * Author : Gérald FENOY
+ *
+ * Copyright (c) 2009-2010 GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef ZOO_SERVICE_INTERNAL_JAVA_H
+#define ZOO_SERVICE_INTERNAL_JAVA_H 1
+
+#pragma once 
+
+#include "service.h"
+#include "service_internal.h"
+#include <jni.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+  jobject HashMap_FromMaps(JNIEnv*,maps*,jclass,jclass,jmethodID);
+  
+  maps* mapsFromHashMap(JNIEnv*,jobject,jclass);
+  
+  void displayStack(JNIEnv*,maps*);
+
+  char *parseJVMXXOption(map*);
+
+  char *parseJVMXOption(map*);
+
+  int zoo_java_support(maps**,map*,service*,maps**,maps**);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/zoo-project/zoo-kernel/service_internal_js.c b/zoo-project/zoo-kernel/service_internal_js.c
new file mode 100644
index 0000000..c6822cf
--- /dev/null
+++ b/zoo-project/zoo-kernel/service_internal_js.c
@@ -0,0 +1,985 @@
+/*
+ * Author : Gérald FENOY
+ *
+ * Copyright (c) 2009-2012 GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "service_internal_js.h"
+#include "response_print.h"
+
+#ifndef JSCLASS_GLOBAL_FLAGS
+#define JSCLSAS_GLOBAL_FLAGS 0
+#endif
+
+static char dbg[1024];
+
+/**
+ * The function used as alert from the JavaScript environment (ZOO-API)
+ *
+ * @param cx the JavaScript context
+ * @param argc the number of parameters
+ * @param argv1 the parameter values
+ * @return true
+ */
+JSBool
+JSAlert(JSContext *cx, uintN argc, jsval *argv1)
+{
+  jsval *argv = JS_ARGV(cx,argv1);
+  int i=0;
+  JS_MaybeGC(cx);
+  for(i=0;i<argc;i++){
+    JSString* jsmsg = JS_ValueToString(cx,argv[i]);
+    char *tmp=JS_EncodeString(cx,jsmsg);
+    fprintf(stderr,"[ZOO-API:JS] %s\n",tmp);
+    free(tmp);
+  }
+  JS_MaybeGC(cx);
+  
+  return JS_TRUE;
+}
+
+/**
+ * The function used as importScript from the JavaScript environment (ZOO-API)
+ * 
+ * @param cx the JavaScript context
+ * @param argc the number of parameters
+ * @param argv1 the parameter values
+ * @return true
+ */
+JSBool 
+JSLoadScripts(JSContext *cx, uintN argc, jsval *argv1)
+{
+  JS_MaybeGC(cx);
+
+  char ntmp[1024];
+  getcwd(ntmp,1024);
+
+  jsval *argv = JS_ARGV(cx,argv1);
+  int i=0;
+  JS_MaybeGC(cx);
+  for(i=0;i<argc;i++){
+    char *filename = JSValToChar(cx,&argv[i]);
+    char *api0=(char*)malloc((strlen(ntmp)+strlen(filename)+2)*sizeof(char));
+    sprintf(api0,"%s/%s",ntmp,filename);
+#ifdef JS_DEBUG
+    fprintf(stderr,"Trying to load %s\n",api0);
+    fflush(stderr);
+#endif
+    JSObject *api_script1=loadZooApiFile(cx,JS_GetGlobalObject(cx),api0);
+    free(api0);
+  }
+  JS_MaybeGC(cx);
+  JS_SET_RVAL(cx, argv1, JSVAL_VOID);
+  
+  return JS_TRUE;
+}
+
+/**
+ * Load a JavaScript file then run the function corresponding to the service by
+ * passing the conf, inputs and outputs parameters by value as JavaScript
+ * Objects.
+ *
+ * @param main_conf the conf maps containing the main.cfg settings
+ * @param request the map containing the HTTP request
+ * @param s the service structure
+ * @param inputs the maps containing the inputs
+ * @param outputs the maps containing the outputs
+ * @return SERVICE_SUCCEEDED or SERVICE_FAILED if the service run, -1 
+ *  if the service failed to load or throw error at runtime.
+ */
+int zoo_js_support(maps** main_conf,map* request,service* s,maps **inputs,maps **outputs)
+{
+  /*maps* main=*main_conf;
+  maps* _inputs=*inputs;
+  maps* _outputs=*outputs;*/
+
+  /* The class of the global object. */
+  JSClass global_class= {
+    "global", JSCLASS_GLOBAL_FLAGS,
+    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
+    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
+    JSCLASS_NO_OPTIONAL_MEMBERS
+  };
+
+  /* JS variables. */
+  JSRuntime *rt;
+  JSContext *cx;
+  JSObject  *global;
+
+  /* Create a JS runtime. */
+  rt = JS_NewRuntime(8L * 1024L * 1024L);
+  if (rt == NULL)
+    return 1;
+  
+  /* Create a context. */
+  cx = JS_NewContext(rt,8192);
+  if (cx == NULL){
+    return 1;
+  }
+  JS_SetOptions(cx, JSOPTION_VAROBJFIX | JSOPTION_JIT | JSOPTION_METHODJIT);
+  JS_SetVersion(cx, JSVERSION_LATEST);
+  JS_SetErrorReporter(cx, reportError);
+
+  /* Create the global object. */
+  global = JS_NewCompartmentAndGlobalObject(cx, &global_class, NULL);
+
+  /* Populate the global object with the standard globals,
+     like Object and Array. */
+  if (!JS_InitStandardClasses(cx, global)){
+    return 1;
+  }
+
+  /* Define specific function and global variable to share with JS runtime
+   */
+  jsval tmp=INT_TO_JSVAL(3);
+  if (!JS_SetProperty(cx, global, "SERVICE_SUCCEEDED", &tmp))
+    return 1;
+  tmp=INT_TO_JSVAL(4);
+  if (!JS_SetProperty(cx, global, "SERVICE_FAILED", &tmp))
+    return 1;
+  if (!JS_DefineFunction(cx, global, "ZOORequest", JSRequest, 4, 0))
+    return 1;
+  if (!JS_DefineFunction(cx, global, "ZOOTranslate", JSTranslate, 4, 0))
+    return 1;
+  if (!JS_DefineFunction(cx, global, "ZOOUpdateStatus", JSUpdateStatus, 2, 0))
+    return 1;
+  if (!JS_DefineFunction(cx, global, "alert", JSAlert, 2, 0))
+    return 1;  
+  if (!JS_DefineFunction(cx, global, "importScripts", JSLoadScripts, 1, 0))
+    return 1;
+
+  /**
+   * Add private context object
+   */
+  void* cxPrivate = request;
+  JS_SetContextPrivate(cx,cxPrivate);
+
+  map* tmpm1=getMap(request,"metapath");
+  char ntmp[1024];
+  getcwd(ntmp,1024);
+
+  /**
+   * Load the first part of the ZOO-API
+   */
+  char *api0=(char*)malloc((strlen(ntmp)+17)*sizeof(char));
+  sprintf(api0,"%s/ZOO-proj4js.js",ntmp);
+#ifdef JS_DEBUG
+  fprintf(stderr,"Trying to load %s\n",api0);
+#endif
+  JSObject *api_script1=loadZooApiFile(cx,global,api0);
+  free(api0);
+  fflush(stderr);
+
+  char *api1=(char*)malloc((strlen(ntmp)+13)*sizeof(char));
+  sprintf(api1,"%s/ZOO-api.js",ntmp);
+#ifdef JS_DEBUG
+  fprintf(stderr,"Trying to load %s\n",api1);
+#endif
+  JSObject *api_script2=loadZooApiFile(cx,global,api1);
+  free(api1);
+  fflush(stderr);
+
+  /* Your application code here. This may include JSAPI calls
+     to create your own custom JS objects and run scripts. */
+  //maps* out=*outputs;
+  int res=SERVICE_FAILED;
+  //maps* mc=*main_conf;
+  map* tmpm2=getMap(s->content,"serviceProvider");
+
+  char *filename=(char*)malloc(strlen(tmpm1->value)+strlen(tmpm2->value)+strlen(ntmp)+3);
+  sprintf(filename,"%s/%s/%s",ntmp,tmpm1->value,tmpm2->value);
+  filename[strlen(tmpm1->value)+strlen(tmpm2->value)+strlen(ntmp)+2]=0;
+#ifdef JS_DEBUG
+  fprintf(stderr,"FILENAME %s\n",filename);
+#endif
+  struct stat file_status;
+  stat(filename, &file_status);
+  //char *source=(char*)malloc(file_status.st_size);
+  //uint16 lineno;
+  jsval rval;
+  JSBool ok ;
+  JSObject *script = JS_CompileFile(cx, global, filename);
+  if(script!=NULL){
+    (void)JS_ExecuteScript(cx, global, script, &rval);
+  }
+  else{
+    char tmp1[1024];
+    sprintf(tmp1,"Unable to load JavaScript file %s",filename);
+    free(filename);
+    errorException(*main_conf,tmp1,"NoApplicableCode",NULL);
+    JS_MaybeGC(cx);
+    JS_DestroyContext(cx);
+    JS_DestroyRuntime(rt);
+    JS_ShutDown();
+    return -1;
+  }
+  
+
+  /* Call a function in obj's scope. */
+  jsval argv[3];
+  JSObject *jsargv1=JSObject_FromMaps(cx,*main_conf);
+  argv[0] = OBJECT_TO_JSVAL(jsargv1);
+  JSObject *jsargv2=JSObject_FromMaps(cx,*inputs);
+  argv[1] = OBJECT_TO_JSVAL(jsargv2);
+  JSObject *jsargv3=JSObject_FromMaps(cx,*outputs);
+  argv[2] = OBJECT_TO_JSVAL(jsargv3);
+  jsval rval1=JSVAL_NULL;
+#ifdef JS_DEBUG
+  fprintf(stderr, "object %p\n", (void *) argv[2]);
+#endif
+
+  ok = JS_CallFunctionName(cx, global, s->name, 3, argv, &rval1);
+
+#ifdef JS_DEBUG
+  fprintf(stderr, "object %p\n", (void *) argv[2]);
+#endif
+
+  JSObject *d;
+  if (ok==JS_TRUE && JSVAL_IS_OBJECT(rval1)==JS_TRUE) {
+#ifdef JS_DEBUG
+    fprintf(stderr,"Function run sucessfully !\n");
+#endif
+    /* Should get a number back from the service function call. */
+    ok = JS_ValueToObject(cx, rval1, &d);
+  }else{
+    /* Unable to run JS function */
+    char tmp1[1024];
+    if(strlen(dbg)==0)
+      sprintf(dbg,"No result was found after the function call");
+    sprintf(tmp1,"Unable to run %s from the JavaScript file %s : \n %s",s->name,filename,dbg);
+#ifdef JS_DEBUG
+    fprintf(stderr,"%s",tmp1);
+#endif
+    errorException(*main_conf,tmp1,"NoApplicableCode",NULL);
+    free(filename);
+    JS_MaybeGC(cx);
+    JS_DestroyContext(cx);
+    JS_DestroyRuntime(rt);
+    JS_ShutDown();
+    // Should return -1 here but the unallocation won't work from zoo_service_loader.c line 1847
+    return -1;
+  }
+
+  //jsval t=OBJECT_TO_JSVAL(d);
+  if(JS_IsArrayObject(cx,d)){
+#ifdef JS_DEBUG
+    fprintf(stderr,"An array was returned !\n");
+#endif
+    jsuint	 len;
+    if((JS_GetArrayLength(cx, d, &len)==JS_FALSE)){
+#ifdef JS_DEBUG
+      fprintf(stderr,"outputs array is empty\n");
+#endif
+    }
+    jsval tmp1;
+    JSBool hasResult=JS_GetElement(cx,d,0,&tmp1);
+    res=JSVAL_TO_INT(tmp1);
+#ifdef JS_DEBUG
+    fprintf(stderr," * %d * \n",res);
+#endif
+    if(res==SERVICE_SUCCEEDED){
+      jsval tmp2;
+      JSBool hasElement=JS_GetElement(cx,d,1,&tmp2);
+      if(hasElement==JS_TRUE){
+	freeMaps(outputs);
+	free(*outputs);
+	*outputs=mapsFromJSObject(cx,tmp2);
+      }
+    }else{
+      jsval tmp3;
+      JSBool hasConf=JS_GetElement(cx,d,1,&tmp3);
+      if(hasConf==JS_TRUE){
+	freeMaps(main_conf);
+	free(*main_conf);
+	*main_conf=mapsFromJSObject(cx,tmp3);
+      }
+    }
+
+  }
+  else{
+#ifdef JS_DEBUG
+    fprintf(stderr,"The service didn't return an array !\n");
+#endif
+    /**
+     * Extract result
+     */
+    jsval tmp1;
+    JSBool hasResult=JS_GetProperty(cx,d,"result",&tmp1);
+    res=JSVAL_TO_INT(tmp1);
+
+#ifdef JS_DEBUG
+    fprintf(stderr," * %d * \n",res);
+#endif
+    /**
+     * Extract outputs when available.
+     */
+    jsval tmp2;
+    JSBool hasElement=JS_GetProperty(cx,d,"outputs",&tmp2);
+    if(!JSVAL_IS_VOID(tmp2) && hasElement==JS_TRUE){
+      freeMaps(outputs);
+      free(*outputs);    
+      *outputs=mapsFromJSObject(cx,tmp2);
+    }
+    JS_MaybeGC(cx);
+#ifdef JS_DEBUG
+    if(JSVAL_IS_VOID(tmp2))
+      fprintf(stderr,"No outputs property returned\n");
+    else{
+      if(JS_IsArrayObject(cx,JSVAL_TO_OBJECT(tmp2)))
+	fprintf(stderr,"outputs is an array as expected\n");
+      else
+	fprintf(stderr,"outputs is not an array as expected\n");
+    }
+    JS_MaybeGC(cx);
+#endif
+
+    /**
+     * Extract conf when available.
+     */
+    jsval tmp3;
+    JSBool hasConf=JS_GetProperty(cx,d,"conf",&tmp3);
+    if(!JSVAL_IS_VOID(tmp3) && hasConf==JS_TRUE){
+      freeMaps(main_conf);
+      free(*main_conf);
+      *main_conf=mapsFromJSObject(cx,tmp3);
+    }
+    JS_MaybeGC(cx);
+
+#ifdef JS_DEBUG
+    dumpMaps(*outputs);
+#endif
+  }
+  /* Cleanup. */
+  JS_MaybeGC(cx);
+  JS_DestroyContext(cx);
+  JS_DestroyRuntime(rt);
+  JS_ShutDown();
+  free(filename);
+#ifdef JS_DEBUG
+  fprintf(stderr,"Returned value %d\n",res);
+#endif
+  return res;
+}
+
+/**
+ * Load a JavaScript file
+ *
+ * @param cx the JavaScript context
+ * @param global the global JavaScript object (not used)
+ * @param filename the file name to load
+ * @return a JavaScript Object on success, NULL if an errro occured
+ */
+JSObject * loadZooApiFile(JSContext *cx,JSObject  *global, char* filename){
+  struct stat api_status;
+  int s=stat(filename, &api_status);
+  if(s==0){
+    jsval rval;
+    JSObject *script = JS_CompileFile(cx, JS_GetGlobalObject(cx), filename);
+    if(script!=NULL){
+      (void)JS_ExecuteScript(cx, JS_GetGlobalObject(cx), script, &rval);
+#ifdef JS_DEBUG
+      fprintf(stderr,"**************\n%s correctly loaded\n**************\n",filename);
+#endif
+      return script;
+    }
+#ifdef JS_DEBUG
+    else
+      fprintf(stderr,"\n**************\nUnable to run %s\n**************\n",filename);
+#endif
+  }
+#ifdef JS_DEBUG
+  else
+    fprintf(stderr,"\n**************\nUnable to load %s\n**************\n",filename);
+#endif
+  return NULL;
+}
+
+/**
+ * Convert a maps to a JavaScript Object
+ *
+ * @param cx the JavaScript context
+ * @param t the maps to convert
+ * @return a new JavaScript Object
+ */
+JSObject* JSObject_FromMaps(JSContext *cx,maps* t){
+  JSObject* res=JS_NewObject(cx, NULL, NULL, NULL);
+  if(res==NULL)
+    fprintf(stderr,"Array Object is NULL!\n");
+  maps* tmp=t;
+  while(tmp!=NULL){
+    JSObject *pval=JSObject_FromMap(cx,tmp->content);
+    jsval pvalj=OBJECT_TO_JSVAL(pval);
+    JS_SetProperty(cx, res, tmp->name, &pvalj);
+#ifdef JS_DEBUG
+    fprintf(stderr,"Length of the Array %d, element : %s added \n",len,tmp->name);
+#endif
+    tmp=tmp->next;
+  }  
+  return res;
+}
+
+/**
+ * Convert a map to a JavaScript Object
+ *
+ * @param cx the JavaScript context
+ * @param t the map to convert
+ * @return a new JavaScript Object
+ */
+JSObject* JSObject_FromMap(JSContext *cx,map* t){
+  JSObject* res=JS_NewObject(cx, NULL, NULL, NULL);
+  map* tmpm=t;
+  map* isArray=getMap(t,"isArray");
+  map* isBinary=getMap(t,"size");
+  map* tmap=getMapType(t);
+#ifdef JS_DEBUG
+  if(tmap==NULL)
+    fprintf(stderr,"tmap is null !\n");
+  else
+    fprintf(stderr,"tmap is not null ! (%s = %s)\n",tmap->name,tmap->value);
+#endif
+  while(isArray==NULL && tmpm!=NULL){
+    jsval jsstr;
+    if((isBinary!=NULL && strncasecmp(tmpm->name,"value",5)==0))
+      jsstr = STRING_TO_JSVAL(JS_NewStringCopyN(cx,tmpm->value,atoi(isBinary->value)));
+    else
+      jsstr = STRING_TO_JSVAL(JS_NewStringCopyN(cx,tmpm->value,strlen(tmpm->value)));
+    JS_SetProperty(cx, res, tmpm->name,&jsstr);
+#ifdef JS_DEBUG
+    fprintf(stderr,"[JS] %s => %s\n",tmpm->name,tmpm->value);
+#endif
+    tmpm=tmpm->next;
+  }
+  if(isArray!=NULL){
+    map* len=getMap(t,"length");
+    int cnt=atoi(len->value);
+    JSObject* values=JS_NewArrayObject( cx, cnt, NULL );
+    JSObject* mvalues=JS_NewArrayObject( cx, cnt, NULL );
+    map *tmpm1,*tmpm2;
+    int i=0;
+    for(i=0;i<cnt;i++){
+      tmpm1=getMapArray(t,"value",i);
+      tmpm2=getMapArray(t,tmap->name,i);
+      if(tmpm1!=NULL){
+	jsval jsstr = STRING_TO_JSVAL(JS_NewStringCopyN(cx,tmpm1->value,strlen(tmpm1->value)));
+	JS_SetElement( cx, values, i, &jsstr );
+      }
+      if(tmpm2!=NULL){
+	jsval jsstr = STRING_TO_JSVAL(JS_NewStringCopyN(cx,tmpm2->value,strlen(tmpm2->value)));
+	JS_SetElement( cx, mvalues, i, &jsstr );
+      }
+    }
+    jsval jvalues=OBJECT_TO_JSVAL(values);
+    jsval jmvalues=OBJECT_TO_JSVAL(mvalues);
+    JS_SetProperty(cx, res,"value",&jvalues);
+    JS_SetProperty(cx, res,tmap->name,&jmvalues);
+  }
+  return res;
+}
+
+/**
+ * Convert a JavaScript Object to a maps
+ *
+ * @param cx the JavaScript context
+ * @param t the JavaScript Object to convert
+ * @return a new maps containing the JavaScript Object
+ */
+maps* mapsFromJSObject(JSContext *cx,jsval t){
+  maps *res=NULL;
+  maps *tres=NULL;
+  jsint oi=0;
+  JSObject* tt=JSVAL_TO_OBJECT(t);
+  if(JS_IsArrayObject(cx,tt)){
+#ifdef JS_DEBUG
+    fprintf(stderr,"Is finally an array !\n");
+#endif
+  }
+  else{
+#ifdef JS_DEBUG
+    fprintf(stderr,"Is not an array !\n");
+#endif
+    JSIdArray *idp=JS_Enumerate(cx,tt);
+    if(idp!=NULL) {
+      int index;
+      jsdouble argNum;
+#ifdef JS_DEBUG
+      fprintf(stderr,"Properties length :  %d \n",idp->length);
+#endif
+      
+      for (index=0,argNum=idp->length;index<argNum;index++) { 
+	jsval id = idp->vector[index];
+	jsval vp;
+	JS_IdToValue(cx,id,&vp);
+	char *tmp;
+	JSString *jsmsg;
+	size_t len1;
+	jsmsg = JS_ValueToString(cx,vp);
+	len1 = JS_GetStringLength(jsmsg);
+	
+	tmp=JS_EncodeString(cx,jsmsg);
+	tres=(maps*)malloc(MAPS_SIZE);
+	tres->name=zStrdup(tmp);
+	tres->content=NULL;
+	tres->next=NULL;
+
+	jsval nvp=JSVAL_NULL;
+	if((JS_GetProperty(cx, tt, tmp, &nvp)==JS_FALSE)){
+#ifdef JS_DEBUG
+	  fprintf(stderr,"Enumerate id : %d => %s => No more value\n",oi,tmp);
+#endif
+	}
+	free(tmp);
+	JSObject *nvp1=JSVAL_TO_OBJECT(JSVAL_NULL);
+	JS_ValueToObject(cx,nvp,&nvp1);
+	jsval nvp1j=OBJECT_TO_JSVAL(nvp1);
+	if(JSVAL_IS_OBJECT(nvp1j)){
+	  tres->content=mapFromJSObject(cx,nvp1j);
+	}
+
+	if(res==NULL)
+	  res=dupMaps(&tres);
+	else
+	  addMapsToMaps(&res,tres);
+	freeMaps(&tres);
+	free(tres);
+	tres=NULL;
+		
+      }
+      JS_DestroyIdArray(cx,idp);
+    }
+  }
+
+  jsuint len;
+  JSBool hasLen=JS_GetArrayLength(cx, tt, &len);
+#ifdef JS_DEBUG
+  if(hasLen==JS_FALSE){
+    fprintf(stderr,"outputs array is empty\n");
+  }
+  fprintf(stderr,"outputs array length : %d\n",len);
+#endif
+  for(oi=0;hasLen && oi < len;oi++){
+#ifdef JS_DEBUG
+    fprintf(stderr,"outputs array length : %d step %d \n",len,oi);
+#endif
+    jsval tmp1;
+    JSBool hasElement=JS_GetElement(cx,tt,oi,&tmp1);
+    JSObject *otmp1=JSVAL_TO_OBJECT(tmp1);
+    JSIdArray *idp=JS_Enumerate(cx,otmp1);
+    if(idp!=NULL) {
+      int index;
+      jsdouble argNum;
+#ifdef JS_DEBUG
+      fprintf(stderr,"Properties length :  %d \n",idp->length);
+#endif
+      tres=(maps*)malloc(MAPS_SIZE);
+      tres->name=NULL;
+      tres->content=NULL;
+      tres->next=NULL;
+
+      for (index=0,argNum=idp->length;index<argNum;index++) { 
+	jsval id = idp->vector[index];
+	jsval vp;
+	JS_IdToValue(cx,id,&vp);
+	char *tmp;
+	JSString *jsmsg;
+	size_t len1;
+	jsmsg = JS_ValueToString(cx,vp);
+	len1 = JS_GetStringLength(jsmsg);
+	tmp=JS_EncodeString(cx,jsmsg);
+#ifdef JS_DEBUG
+	fprintf(stderr,"Enumerate id : %d => %s\n",oi,tmp);
+#endif
+	jsval nvp=JSVAL_NULL;
+	if((JS_GetProperty(cx, JSVAL_TO_OBJECT(tmp1), tmp, &nvp)==JS_FALSE)){
+#ifdef JS_DEBUG
+	  fprintf(stderr,"Enumerate id : %d => %s => No more value\n",oi,tmp);
+#endif
+	}
+	free(tmp);
+	if(JSVAL_IS_OBJECT(nvp)){
+#ifdef JS_DEBUG
+	  fprintf(stderr,"JSVAL NVP IS OBJECT\n");
+#endif
+	}
+
+	JSObject *nvp1=JSVAL_TO_OBJECT(JSVAL_NULL);
+	JS_ValueToObject(cx,nvp,&nvp1);
+	jsval nvp1j=OBJECT_TO_JSVAL(nvp1);
+	if(JSVAL_IS_OBJECT(nvp1j)){
+	  JSString *jsmsg1;
+	  char *tmp1, *tmp2;
+	  JSObject *nvp2=JSVAL_TO_OBJECT(JSVAL_NULL);
+	  jsmsg1 = JS_ValueToString(cx,nvp1j);
+	  len1 = JS_GetStringLength(jsmsg1);
+	  tmp1=JS_EncodeString(cx,jsmsg1);
+	  tmp2=JS_EncodeString(cx,jsmsg);
+#ifdef JS_DEBUG
+	  fprintf(stderr,"JSVAL NVP1J IS OBJECT %s = %s\n",JS_EncodeString(cx,jsmsg),tmp1);
+#endif
+	  if(strcasecmp(tmp1,"[object Object]")==0){
+	    tres->name=zStrdup(tmp2);
+	    tres->content=mapFromJSObject(cx,nvp1j);
+	  }
+	  else
+	    if(strcasecmp(tmp2,"name")==0){
+	      tres->name=zStrdup(tmp1);
+	    }
+	    else{
+	      if(tres->content==NULL)
+		tres->content=createMap(tmp2,tmp1);
+	      else
+		addToMap(tres->content,tmp2,tmp1);
+	    }
+	  free(tmp1);
+	  free(tmp2);
+	}
+#ifdef JS_DEBUG
+	else
+	  fprintf(stderr,"JSVAL NVP1J IS NOT OBJECT !!\n");
+#endif
+      }
+#ifdef JS_DEBUG
+      dumpMaps(tres);
+#endif
+      if(res==NULL)
+	res=dupMaps(&tres);
+      else
+	addMapsToMaps(&res,tres);
+      freeMaps(&tres);
+      free(tres);
+      tres=NULL;
+      JS_DestroyIdArray(cx,idp);
+    }
+  }
+#ifdef JS_DEBUG
+  dumpMaps(res);
+#endif
+  return res;
+}
+
+/**
+ * Convert a JavaScript Object to a map
+ *
+ * @param cx the JavaScript context
+ * @param t the JavaScript Object to convert
+ * @return a new map containing the JavaScript Object
+ */
+map* mapFromJSObject(JSContext *cx,jsval t){
+  map *res=NULL;
+  JSIdArray *idp=JS_Enumerate(cx,JSVAL_TO_OBJECT(t));
+#ifdef JS_DEBUG
+  fprintf(stderr,"Properties %p\n",(void*)t);
+#endif
+  if(idp!=NULL) {
+    int index;
+    jsdouble argNum;
+#ifdef JS_DEBUG
+    fprintf(stderr,"Properties length :  %d \n",idp->length);
+#endif
+    for (index=0,argNum=idp->length;index<argNum;index++) { 
+      jsval id = idp->vector[index];
+      jsval vp;
+      JS_IdToValue(cx,id,&vp);
+      char *tmp, *tmp1;
+      JSString *jsmsg,*jsmsg1;
+      size_t len,len1;
+      jsmsg = JS_ValueToString(cx,vp);
+      len = JS_GetStringLength(jsmsg);
+      jsval nvp;
+      tmp=JS_EncodeString(cx,jsmsg);
+      JS_GetProperty(cx, JSVAL_TO_OBJECT(t), tmp, &nvp);
+      jsmsg1 = JS_ValueToString(cx,nvp);
+      len1 = JS_GetStringLength(jsmsg1);
+      tmp1=JS_EncodeString(cx,jsmsg1);
+#ifdef JS_DEBUG
+      fprintf(stderr,"Enumerate id : %d [ %s => %s ]\n",index,tmp,tmp1);
+#endif
+      if(res!=NULL){
+#ifdef JS_DEBUG
+	fprintf(stderr,"%s - %s\n",tmp,tmp1);
+#endif
+	addToMap(res,tmp,tmp1);
+      }
+      else{
+	res=createMap(tmp,tmp1);
+	res->next=NULL;
+      }
+      free(tmp);
+      free(tmp1);
+#ifdef JS_DEBUG
+      dumpMap(res);
+#endif
+    }
+    JS_DestroyIdArray(cx,idp);
+  }
+#ifdef JS_DEBUG
+  dumpMap(res);
+#endif
+  return res;
+}
+
+/**
+ * Print debug information messages on stderr
+ *
+ * @param cx the JavaScript context
+ * @param message the error message
+ * @param report the JavaScript Error Report
+ */
+void reportError(JSContext *cx, const char *message, JSErrorReport *report)
+{
+  sprintf(dbg,"%s:%u:%s\n",
+	  report->filename ? report->filename : "<no filename>",
+	  (unsigned int) report->lineno,
+	  message);
+#ifdef JS_DEBUG
+  fprintf(stderr,"%s",dbg);
+#endif
+  fflush(stderr);
+}
+
+/**
+ * Convert a JavaScript value to a char*
+ *
+ * @param context the JavaScript context
+ * @param arg the JavaScript value
+ * @return a new char*
+ * @warning be sure to free the ressources returned by this function
+ */
+char* JSValToChar(JSContext* context, jsval* arg) {
+  char *c;
+  char *tmp;
+  JSString *jsmsg;
+  size_t len;
+  int i;
+  if(!JSVAL_IS_STRING(*arg)) {
+    return NULL;
+  }
+  jsmsg = JS_ValueToString(context,*arg);
+  len = JS_GetStringLength(jsmsg);
+  tmp = JS_EncodeString(context,jsmsg);
+  c = (char*)malloc((len+1)*sizeof(char));
+  c[len] = '\0';
+#ifdef ULINET_DEBUG
+  fprintf(stderr,"%d \n",len);
+#endif
+  for(i = 0;i < len;i++) {
+    c[i] = tmp[i];
+    c[i+1] = 0;
+  }
+#ifdef ULINET_DEBUG
+  fprintf(stderr,"%s \n",c);
+#endif
+  return c;
+}
+
+/**
+ * Set the HTTP header of a request
+ *
+ * @param handle the HINTERNET handle
+ * @param cx the JavaScript context
+ * @param header the JavaScript Array containing the headers to send
+ * @return the HINTERNET handle
+ */
+HINTERNET setHeader(HINTERNET* handle,JSContext *cx,JSObject *header){
+  jsuint length=0;
+  jsint i=0;
+  char *tmp1;
+#ifdef ULINET_DEBUG
+  fprintf(stderr,"setHeader\n");
+#endif
+  if(JS_IsArrayObject(cx,header)){
+#ifdef ULINET_DEBUG
+    fprintf(stderr,"header is an array\n");
+#endif
+    JS_GetArrayLength(cx,header,&length);
+#ifdef ULINET_DEBUG
+    fprintf(stderr,"header is an array of %d elements\n",length);
+#endif
+    handle->ihandle[handle->nb].header=NULL;
+    for(i=0;i<length;i++){
+      jsval tmp;
+      JS_GetElement(cx,header,i,&tmp);
+      tmp1=JSValToChar(cx,&tmp);
+#ifdef ULINET_DEBUG
+      curl_easy_setopt(handle->ihandle[handle->nb].handle,CURLOPT_VERBOSE,1);
+      fprintf(stderr,"Element of array n° %d, value : %s\n",i,tmp1);
+#endif
+      handle->ihandle[handle->nb].header=curl_slist_append(handle->ihandle[handle->nb].header, tmp1);
+      free(tmp1);
+    }
+  }
+  else{
+    fprintf(stderr,"not an array !!!!!!!\n");
+  }
+  return *handle;
+}
+
+/**
+ * The function used as ZOOTranslate from the JavaScript environment.
+ * Use the ZOO-Services messages translation function from the Python
+ * environment (ZOO-API)
+ *
+ * @param cx the JavaScript context
+ * @param argc the number of parameters
+ * @param argv1 the parameter values
+ * @return true
+ */
+JSBool
+JSTranslate(JSContext *cx, uintN argc, jsval *argv1)
+{
+  jsval *argv = JS_ARGV(cx,argv1);
+  char *str=JSValToChar(cx,&argv[0]);
+  char *tmpValue=_ss(str);
+  JS_SET_RVAL(cx, argv1,STRING_TO_JSVAL(JS_NewStringCopyN(cx,tmpValue,strlen(tmpValue))));  
+  JS_MaybeGC(cx);
+  return JS_TRUE;
+}
+
+/**
+ * The function used as ZOORequest from the JavaScript environment (ZOO-API)
+ *
+ * @param cx the JavaScript context
+ * @param argc the number of parameters
+ * @param argv1 the parameter values
+ * @return true
+ * @see setHeader
+ */
+JSBool
+JSRequest(JSContext *cx, uintN argc, jsval *argv1)
+{
+  jsval *argv = JS_ARGV(cx,argv1);
+  HINTERNET hInternet;
+  JSObject *header;
+  char *url;
+  char *method;
+  char* tmpValue;
+  size_t dwRead;
+  JS_MaybeGC(cx);
+  hInternet=InternetOpen("ZooWPSClient\0",
+			 INTERNET_OPEN_TYPE_PRECONFIG,
+			 NULL,NULL, 0);
+  if(!CHECK_INET_HANDLE(hInternet))
+    return JS_FALSE;
+  if(argc>=2){
+    method=JSValToChar(cx,&argv[0]);
+    url=JSValToChar(cx,&argv[1]);
+  }
+  else{
+    method=zStrdup("GET");
+    url=JSValToChar(cx,argv);
+  }
+  hInternet.waitingRequests[hInternet.nb]=strdup(url);
+  if(argc==4){
+    char *body;
+    body=JSValToChar(cx,&argv[2]);
+    header=JSVAL_TO_OBJECT(argv[3]);
+#ifdef ULINET_DEBUG
+    fprintf(stderr,"URL (%s) \nBODY (%s)\n",url,body);
+#endif
+    if(JS_IsArrayObject(cx,header))
+      setHeader(&hInternet,cx,header);
+#ifdef ULINET_DEBUG
+    fprintf(stderr,"BODY (%s)\n",body);
+#endif
+    InternetOpenUrl(&hInternet,hInternet.waitingRequests[hInternet.nb],body,strlen(body),
+		    INTERNET_FLAG_NO_CACHE_WRITE,0);    
+    processDownloads(&hInternet);
+    free(body);
+  }else{
+    if(argc==3){
+      char *body=JSValToChar(cx,&argv[2]);
+      InternetOpenUrl(&hInternet,hInternet.waitingRequests[hInternet.nb],body,strlen(body),
+		      INTERNET_FLAG_NO_CACHE_WRITE,0);
+      processDownloads(&hInternet);
+      free(body);
+    }else{
+      InternetOpenUrl(&hInternet,hInternet.waitingRequests[hInternet.nb],NULL,0,
+		      INTERNET_FLAG_NO_CACHE_WRITE,0);
+      processDownloads(&hInternet);
+    }
+  }
+  tmpValue=(char*)malloc((hInternet.ihandle[0].nDataLen+1)*sizeof(char));
+  InternetReadFile(hInternet.ihandle[0],(LPVOID)tmpValue,hInternet.ihandle[0].nDataLen,&dwRead);
+#ifdef ULINET_DEBUG
+  fprintf(stderr,"content downloaded (%d) (%s) \n",dwRead,tmpValue);
+#endif
+  if(dwRead==0){
+    JS_SET_RVAL(cx, argv1,STRING_TO_JSVAL(JS_NewStringCopyN(cx,"Unable to access the file.",strlen("Unable to access the file."))));
+    return JS_TRUE;
+  }
+
+#ifdef ULINET_DEBUG
+  fprintf(stderr,"content downloaded (%d) (%s) \n",dwRead,tmpValue);
+#endif
+  JS_SET_RVAL(cx, argv1,STRING_TO_JSVAL(JS_NewStringCopyN(cx,tmpValue,strlen(tmpValue))));
+  free(url);
+  if(argc>=2)
+    free(method);
+  InternetCloseHandle(&hInternet);
+  JS_MaybeGC(cx);
+  return JS_TRUE;
+}
+
+/**
+ * The function used as ZOOUpdateStatus from the JavaScript environment
+ * (ZOO-API).
+ *
+ * @param cx the JavaScript context
+ * @param argc the number of parameters
+ * @param argv1 the parameter values
+ * @return true
+ * @see setHeader,_updateStatus
+ */
+JSBool
+JSUpdateStatus(JSContext *cx, uintN argc, jsval *argv1)
+{
+  jsval *argv = JS_ARGV(cx,argv1);
+  JS_MaybeGC(cx);
+  int istatus=0;
+  char *status=NULL;
+  maps *conf;
+  if(argc>2){
+#ifdef JS_DEBUG
+    fprintf(stderr,"Number of arguments used to call the function : %i",argc);
+#endif
+    return JS_FALSE;
+  }
+  conf=mapsFromJSObject(cx,argv[0]);
+  if(JS_ValueToInt32(cx,argv[1],&istatus)==JS_TRUE){
+    char tmpStatus[4];
+    sprintf(tmpStatus,"%i",istatus);
+    tmpStatus[3]=0;
+    status=strdup(tmpStatus);
+  }
+  if(getMapFromMaps(conf,"lenv","status")!=NULL){
+    if(status!=NULL){
+      setMapInMaps(conf,"lenv","status",status);
+      free(status);
+    }
+    else
+      setMapInMaps(conf,"lenv","status","15");
+    _updateStatus(conf);
+  }
+  freeMaps(&conf);
+  free(conf);
+  JS_MaybeGC(cx);
+  return JS_TRUE;
+}
+
diff --git a/zoo-project/zoo-kernel/service_internal_js.h b/zoo-project/zoo-kernel/service_internal_js.h
new file mode 100644
index 0000000..4c73044
--- /dev/null
+++ b/zoo-project/zoo-kernel/service_internal_js.h
@@ -0,0 +1,62 @@
+/*
+ * Author : Gérald FENOY
+ *
+ * Copyright (c) 2009-2010 GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef ZOO_SERVICE_INTERNAL_JS_H
+#define ZOO_SERVICE_INTERNAL_JS_H 1
+
+#pragma once 
+#ifdef WIN32
+#include <wchar.h>
+#endif
+#include "service.h"
+#include "service_internal.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include "ulinet.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+  char* JSValToChar(JSContext*, jsval*);
+  JSObject* JSObject_FromMaps(JSContext *,maps*);
+  JSObject* JSObject_FromMap(JSContext *,map*);
+  maps* mapsFromJSObject(JSContext *,jsval);
+  map* mapFromJSObject(JSContext *,jsval);
+  JSBool JSTranslate(JSContext*, uintN, jsval*);
+  JSBool JSRequest(JSContext*, uintN, jsval*);
+  JSBool JSUpdateStatus(JSContext*,uintN,jsval *);
+
+  void reportError(JSContext *cx, const char *message, JSErrorReport *report);
+  
+  int zoo_js_support(maps**,map*,service*,maps **,maps **);
+
+  JSObject *loadZooApiFile(JSContext*,JSObject*,char*);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/zoo-project/zoo-kernel/service_internal_ms.c b/zoo-project/zoo-kernel/service_internal_ms.c
new file mode 100644
index 0000000..4bd79ac
--- /dev/null
+++ b/zoo-project/zoo-kernel/service_internal_ms.c
@@ -0,0 +1,1173 @@
+/*
+ * Author : Gérald FENOY
+ *
+ *  Copyright 2010-2011 Fondazione Edmund Mach. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/**
+ * Cross platform definition of layerObj->class
+ */
+#ifndef WIN32
+#define CLASS class
+#else
+#define CLASS _class
+#endif
+#include "service_internal_ms.h"
+#include "server_internal.h"
+#include "response_print.h"
+
+/**
+ * Get a list of configuration keys having a corresponding mandatory ows_*.
+ * Map composed by a main.cfg maps name as key and the corresponding 
+ * MapServer Mafile Metadata name to use
+ * see doc from here :
+ *  - http://mapserver.org/ogc/wms_server.html
+ *  - http://mapserver.org/ogc/wfs_server.html
+ *  - http://mapserver.org/ogc/wcs_server.html
+ *
+ * @return a new map containing a table linking a name of a configuration key
+ * to a corresponding mandatory ows_* keyword (ie. "fees" => "ows_fees").
+ */
+map* getCorrespondance(){
+  map* res=createMap("encoding","ows_encoding");
+  addToMap(res,"abstract","ows_abstract");
+  addToMap(res,"title","ows_title");
+  addToMap(res,"keywords","ows_keywordlist");
+  addToMap(res,"fees","ows_fees");
+  addToMap(res,"accessConstraints","ows_accessconstraints");
+  addToMap(res,"providerName","ows_attribution_title");
+  addToMap(res,"providerSite","ows_service_onlineresource");
+  addToMap(res,"individualName","ows_contactperson");
+  addToMap(res,"positionName","ows_contactposition");
+  addToMap(res,"providerName","ows_contactorganization");
+  addToMap(res,"role","ows_role");
+  addToMap(res,"addressType","ows_addresstype");
+  addToMap(res,"addressCity","ows_city");
+  addToMap(res,"addressDeliveryPoint","ows_address");
+  addToMap(res,"addressPostalCode","ows_postcode");
+  addToMap(res,"addressAdministrativeArea","ows_stateorprovince");
+  addToMap(res,"addressCountry","ows_country");
+  addToMap(res,"phoneVoice","ows_contactvoicetelephone");
+  addToMap(res,"phoneFacsimile","ows_contactfacsimiletelephone");
+  addToMap(res,"addressElectronicMailAddress","ows_contactelectronicmailaddress");
+  // Missing Madatory Informations
+  addToMap(res,"hoursOfService","ows_hoursofservice");
+  addToMap(res,"contactInstructions","ows_contactinstructions");
+  return res;
+}
+
+/**
+ * Add width and height keys to an output maps containing the maximum width
+ * and height for displaying the full data extent.
+ * Restriction to an image having a size of 640x480 (width * height)
+ *
+ * @param output 
+ * @param minx the lower left x coordinate
+ * @param miny the lower left y coordinate
+ * @param maxx the upper right x coordinate
+ * @param maxy the upper right y coordinate
+ */
+void setMapSize(maps* output,double minx,double miny,double maxx,double maxy){
+  double maxWidth=640;
+  double maxHeight=480;
+  double deltaX=maxx-minx;
+  double deltaY=maxy-miny;
+  double qWidth;
+  qWidth=maxWidth/deltaX;
+  double qHeight;
+  qHeight=maxHeight/deltaY;
+#ifdef DEBUGMS
+  fprintf(stderr,"deltaX : %.15f \ndeltaY : %.15f\n",deltaX,deltaY);
+  fprintf(stderr,"qWidth : %.15f \nqHeight : %.15f\n",qWidth,qHeight);
+#endif
+
+  double width=deltaX*qWidth;
+  double height=height=deltaY*qWidth;
+  if(deltaX<deltaY){
+    width=deltaX*qHeight;
+    height=deltaY*qHeight;
+  }
+  if(height<0)
+    height=-height;
+  if(width<0)
+    width=-width;
+  char sWidth[1024];
+  char sHeight[1024];
+  sprintf(sWidth,"%.3f",width);
+  sprintf(sHeight,"%.3f",height);
+#ifdef DEBUGMS
+  fprintf(stderr,"sWidth : %.15f \nsHeight : %.15f\n",sWidth,sHeight);
+#endif
+  if(output!=NULL){
+    addToMap(output->content,"width",sWidth);
+    addToMap(output->content,"height",sHeight);
+  }
+}
+
+/**
+ * Add a Reference key to an output containing the WMFS/WFS/WCS request for
+ * accessing service result
+ * 
+ * @param m the conf maps containing the main.cfg settings
+ * @param tmpI the specific output maps to add the Reference key
+ */
+void setReferenceUrl(maps* m,maps* tmpI){
+  outputMapfile(m,tmpI);
+  map *msUrl=getMapFromMaps(m,"main","mapserverAddress");
+  if(msUrl==NULL){
+    errorException (m, _("Unable to find any mapserverAddress defined in the main.cfg file"),
+		    "InternalError", NULL);
+    exit(-1);
+  }
+  map *msOgcVersion=getMapFromMaps(m,"main","msOgcVersion");
+  map *dataPath=getMapFromMaps(m,"main","dataPath");
+  map *sid=getMapFromMaps(m,"lenv","usid");
+  map* format=getMap(tmpI->content,"mimeType");
+  map* rformat=getMap(tmpI->content,"requestedMimeType");
+  map* width=getMap(tmpI->content,"width");
+  map* height=getMap(tmpI->content,"height");
+  map* protoMap=getMap(tmpI->content,"msOgc");
+  map* versionMap=getMap(tmpI->content,"msOgcVersion");
+  char options[3][5][25]={
+    {"WMS","1.3.0","GetMap","layers=%s","wms_extent"},
+    {"WFS","1.1.0","GetFeature","typename=%s","wcs_extent"},
+    {"WCS","1.1.0","GetCoverage","coverage=%s","wcs_extent"}
+  };
+  int proto=0;
+  if(rformat==NULL){
+    rformat=getMap(tmpI->content,"mimeType");
+  }
+  if(strncasecmp(rformat->value,"text/xml",8)==0)
+    proto=1;
+  if(strncasecmp(rformat->value,"image/tiff",10)==0)
+    proto=2;
+  if(protoMap!=NULL){
+    if(strncasecmp(protoMap->value,"WMS",3)==0)
+      proto=0;
+    else{
+      if(strncasecmp(protoMap->value,"WFS",3)==0)
+	proto=1;
+      else 
+	proto=2;
+    }
+  }
+  char *protoVersion=options[proto][1];
+  if(proto==1){
+    if(msOgcVersion!=NULL)
+      protoVersion=msOgcVersion->value;
+    if(versionMap!=NULL)
+      protoVersion=versionMap->value;
+  }
+
+  map* extent=getMap(tmpI->content,options[proto][4]);
+  map* crs=getMap(tmpI->content,"crs");
+  int hasCRS=1;
+  if(crs==NULL){
+    crs=getMapFromMaps(m,"main","crs");
+    if(crs==NULL){
+      crs=createMap("crs","epsg:4326");
+      hasCRS=0;
+    }
+  }
+  char layers[128];
+  sprintf(layers,options[proto][3],tmpI->name);
+
+  char* webService_url=(char*)malloc((strlen(msUrl->value)+strlen(format->value)+strlen(tmpI->name)+strlen(width->value)+strlen(height->value)+strlen(extent->value)+256)*sizeof(char));
+
+  if(proto>0){
+    sprintf(webService_url,
+	    "%s?map=%s/%s_%s.map&request=%s&service=%s&version=%s&%s&format=%s&bbox=%s&crs=%s",
+	    msUrl->value,
+	    dataPath->value,
+	    tmpI->name,
+	    sid->value,
+	    options[proto][2],
+	    options[proto][0],
+	    protoVersion,
+	    layers,
+	    rformat->value,
+	    extent->value,
+	    crs->value
+	    );
+  }
+  else{
+    sprintf(webService_url,
+	    "%s?map=%s/%s_%s.map&request=%s&service=%s&version=%s&%s&width=%s&height=%s&format=%s&bbox=%s&crs=%s",
+	    msUrl->value,
+	    dataPath->value,
+	    tmpI->name,
+	    sid->value,
+	    options[proto][2],
+	    options[proto][0],
+	    protoVersion,
+	    layers,
+	    width->value,
+	    height->value,
+	    rformat->value,
+	    extent->value,
+	    crs->value
+	    );
+  }
+  if(hasCRS==0){
+    freeMap(&crs);
+    free(crs);
+  }
+  addToMap(tmpI->content,"Reference",webService_url);
+  free(webService_url);
+}
+
+/**
+ * Set projection for a layer in a MAPFILE using Authority Code and Name if
+ * available or fallback to proj4 definition if available or fallback to
+ * default EPSG:4326
+ *
+ * @param output the output maps
+ * @param m the opened mapObj
+ * @param myLayer the layerObj
+ * @param pszProjection a char* containing the SRS definition in WKT format
+ */
+void setSrsInformations(maps* output,mapObj* m,layerObj* myLayer,
+			char* pszProjection){
+  OGRSpatialReferenceH  hSRS;
+  map* msSrs=NULL;
+  hSRS = OSRNewSpatialReference(NULL);
+  if( pszProjection!=NULL && strlen(pszProjection)>1){
+    if(OSRImportFromWkt( hSRS, &pszProjection ) == CE_None ){
+      char *proj4Str=NULL;
+      if(OSRGetAuthorityName(hSRS,NULL)!=NULL && 
+	 OSRGetAuthorityCode(hSRS,NULL)!=NULL){
+	char tmpSrs[20];
+	sprintf(tmpSrs,"%s:%s",
+		OSRGetAuthorityName(hSRS,NULL),OSRGetAuthorityCode(hSRS,NULL));
+	msLoadProjectionStringEPSG(&m->projection,tmpSrs);
+	msLoadProjectionStringEPSG(&myLayer->projection,tmpSrs);
+	
+	char tmpSrss[256];
+	sprintf(tmpSrss,"EPSG:4326 EPSG:900913 %s",tmpSrs);
+	
+	msInsertHashTable(&(m->web.metadata), "ows_srs", tmpSrss);
+	msInsertHashTable(&(myLayer->metadata), "ows_srs", tmpSrss);
+	
+#ifdef DEBUGMS
+	fprintf(stderr,"isGeo %b\n\n",OSRIsGeographic(hSRS)==TRUE);
+#endif
+	if(output!=NULL){
+	  if(OSRIsGeographic(hSRS)==TRUE)
+	    addToMap(output->content,"crs_isGeographic","true");
+	  else
+	    addToMap(output->content,"crs_isGeographic","false");
+	  addToMap(output->content,"crs",tmpSrs);
+	}
+      }
+      else{
+	OSRExportToProj4(hSRS,&proj4Str);
+	if(proj4Str!=NULL && strlen(proj4Str)>0){
+#ifdef DEBUGMS
+	  fprintf(stderr,"PROJ (%s)\n",proj4Str);
+#endif
+	  msLoadProjectionString(&(m->projection),proj4Str);
+	  msLoadProjectionString(&(myLayer->projection),proj4Str);
+	  if(output!=NULL){ 
+	    if(OSRIsGeographic(hSRS)==TRUE)
+	      addToMap(output->content,"crs_isGeographic","true");
+	    else
+	      addToMap(output->content,"crs_isGeographic","false");
+	  }
+	  free(proj4Str);
+	}
+	else{
+	  msLoadProjectionStringEPSG(&m->projection,"EPSG:4326");
+	  msLoadProjectionStringEPSG(&myLayer->projection,"EPSG:4326");
+	  if(output!=NULL){
+	    addToMap(output->content,"crs_isGeographic","true");
+	  }
+	}
+	if(output!=NULL){
+	  addToMap(output->content,"crs","EPSG:4326");
+	  addToMap(output->content,"real_extent","true");
+	}
+	msInsertHashTable(&(m->web.metadata),"ows_srs", "EPSG:4326 EPSG:900913");
+	msInsertHashTable(&(myLayer->metadata),"ows_srs","EPSG:4326 EPSG:900913");
+      }
+    }
+  }
+  else{
+    if(output!=NULL){
+      msSrs=getMap(output->content,"msSrs");
+    }
+    if(msSrs!=NULL){
+      msLoadProjectionStringEPSG(&m->projection,msSrs->value);
+      msLoadProjectionStringEPSG(&myLayer->projection,msSrs->value);
+      char tmpSrs[128];
+      sprintf(tmpSrs,"%s EPSG:4326 EPSG:900913",msSrs->value);
+      msInsertHashTable(&(m->web.metadata),"ows_srs",tmpSrs);
+      msInsertHashTable(&(myLayer->metadata),"ows_srs",tmpSrs);
+    }else{
+      msLoadProjectionStringEPSG(&m->projection,"EPSG:4326");
+      msLoadProjectionStringEPSG(&myLayer->projection,"EPSG:4326");
+      msInsertHashTable(&(m->web.metadata),"ows_srs","EPSG:4326 EPSG:900913");
+      msInsertHashTable(&(myLayer->metadata),"ows_srs","EPSG:4326 EPSG:900913");
+    }
+    if(output!=NULL){
+      addToMap(output->content,"crs",msSrs->value);
+      addToMap(output->content,"crs_isGeographic","true");
+    }
+  }
+
+  OSRDestroySpatialReference( hSRS );
+}
+
+/**
+ * Set the MAPFILE extent, the the ows_extent for the layer, add wms_extent and
+ * wfs_extent to the output maps and call setMapSize.
+ *
+ * @param output the specific output
+ * @param m the mapObj
+ * @param myLayer the layerObj
+ * @param minX the lower left x coordinate
+ * @param minY the lower left y coordinate
+ * @param maxX the upper right x coordinate
+ * @param maxY the upper right y coordinate
+ * @see setMapSize
+ */
+void setMsExtent(maps* output,mapObj* m,layerObj* myLayer,
+		 double minX,double minY,double maxX,double maxY){
+  msMapSetExtent(m,minX,minY,maxX,maxY);
+#ifdef DEBUGMS
+  fprintf(stderr,"Extent %.15f %.15f %.15f %.15f\n",minX,minY,maxX,maxY);
+#endif
+  char tmpExtent[1024];
+  sprintf(tmpExtent,"%.15f %.15f %.15f %.15f",minX,minY,maxX,maxY);
+#ifdef DEBUGMS
+  fprintf(stderr,"Extent %s\n",tmpExtent);
+#endif
+  msInsertHashTable(&(myLayer->metadata), "ows_extent", tmpExtent);
+  
+  if(output!=NULL){
+    map* test=getMap(output->content,"real_extent");
+    if(test!=NULL){
+      pointObj min, max;
+      projectionObj tempSrs;
+      min.x = m->extent.minx;
+      min.y = m->extent.miny;
+      max.x = m->extent.maxx;
+      max.y = m->extent.maxy;
+      char tmpSrsStr[1024];
+      msInitProjection(&tempSrs);
+      msLoadProjectionStringEPSG(&tempSrs,"EPSG:4326");
+
+      msProjectPoint(&(m->projection),&tempSrs,&min);
+      msProjectPoint(&m->projection,&tempSrs,&max);
+      
+      sprintf(tmpExtent,"%.3f,%.3f,%.3f,%.3f",min.y,min.x,max.y,max.x);
+      map* isGeo=getMap(output->content,"crs_isGeographic");
+#ifdef DEBUGMS
+      fprintf(stderr,"isGeo = %s\n",isGeo->value);
+#endif
+      if(isGeo!=NULL && strcasecmp("true",isGeo->value)==0)
+        sprintf(tmpExtent,"%f,%f,%f,%f", minY,minX, maxY, maxX);
+      addToMap(output->content,"wms_extent",tmpExtent);
+      sprintf(tmpSrsStr,"%.3f,%.3f,%.3f,%.3f",min.x,min.y,max.x,max.y);
+      addToMap(output->content,"wcs_extent",tmpExtent);
+    }else{
+      sprintf(tmpExtent,"%f,%f,%f,%f",minX, minY, maxX, maxY);
+      map* isGeo=getMap(output->content,"crs_isGeographic");
+      if(isGeo!=NULL){
+#ifdef DEBUGMS
+	fprintf(stderr,"isGeo = %s\n",isGeo->value);
+#endif
+	if(isGeo!=NULL && strcasecmp("true",isGeo->value)==0)
+	  sprintf(tmpExtent,"%f,%f,%f,%f", minY,minX, maxY, maxX);
+      }
+      addToMap(output->content,"wms_extent",tmpExtent); 
+      sprintf(tmpExtent,"%.3f,%.3f,%.3f,%.3f",minX,minY,maxX,maxY);
+      addToMap(output->content,"wcs_extent",tmpExtent);
+    }
+  }
+
+  setMapSize(output,minX,minY,maxX,maxY);
+}
+
+/**
+ * Try to open a vector output and define the corresponding layer in the MAPFILE
+ *
+ * @param conf the conf maps containing the main.cfg settings
+ * @param output the specific output maps
+ * @param m the mapObj
+ */
+int tryOgr(maps* conf,maps* output,mapObj* m){
+
+  map* tmpMap=getMap(output->content,"storage");
+  char *pszDataSource=tmpMap->value;
+
+  /**
+   * Try to open the DataSource using OGR
+   */
+  OGRRegisterAll();
+  /**
+   * Try to load the file as ZIP
+   */
+
+  OGRDataSourceH poDS1 = NULL;
+  OGRSFDriverH *poDriver1 = NULL;
+  char *dsName=(char*)malloc((8+strlen(pszDataSource)+1)*sizeof(char));
+  char *odsName=zStrdup(pszDataSource);
+  char *sdsName=zStrdup(pszDataSource);
+  char *demo=".data";
+  sdsName[strlen(sdsName)-(strlen(demo)-1)]='d';
+  sdsName[strlen(sdsName)-(strlen(demo)-2)]='i';
+  sdsName[strlen(sdsName)-(strlen(demo)-3)]='r';
+  sdsName[strlen(sdsName)-(strlen(demo)-4)]=0;
+
+  odsName[strlen(odsName)-(strlen(demo)-1)]='z';
+  odsName[strlen(odsName)-(strlen(demo)-2)]='i';
+  odsName[strlen(odsName)-(strlen(demo)-3)]='p';
+  odsName[strlen(odsName)-(strlen(demo)-4)]=0;
+  sprintf(dsName,"/vsizip/%s",odsName);
+
+#ifdef DEBUGMS
+  fprintf(stderr,"Try loading %s, %s, %s\n",dsName,odsName,dsName);
+#endif
+
+  FILE* file = fopen(pszDataSource, "rb");
+  FILE* fileZ = fopen(odsName, "wb");
+  free(odsName);
+  fseek(file, 0, SEEK_END);
+  unsigned long fileLen=ftell(file);
+  fseek(file, 0, SEEK_SET);
+  char *buffer=(char *)malloc(fileLen+1);
+  fread(buffer, fileLen, 1, file);
+  fwrite(buffer,fileLen, 1, fileZ);
+  fclose(file);
+  fclose(fileZ);
+  free(buffer);
+#ifdef DEBUGMS
+  fprintf(stderr,"Try loading %s",dsName);
+#endif
+  poDS1 = OGROpen( dsName, FALSE, poDriver1 );
+  if( poDS1 == NULL ){
+    fprintf(stderr,"Unable to access the DataSource as ZIP File\n");
+    setMapInMaps(conf,"lenv","message","Unable to open datasource in read only mode");
+    OGR_DS_Destroy(poDS1);
+  }else{
+#ifdef DEBUGMS
+    fprintf(stderr,"The DataSource is a  ZIP File\n");
+#endif
+    char** demo=VSIReadDir(dsName);
+    int i=0;
+    zMkdir(sdsName
+#ifndef WIN32
+		,S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH 
+#endif
+		);
+    while(demo[i]!=NULL){
+#ifdef DEBUGMS
+      fprintf(stderr,"ZIP File content : %s\n",demo[i]);
+#endif
+      char *tmpDs=(char*)malloc((strlen(dsName)+strlen(demo[i])+2)*sizeof(char));
+      sprintf(tmpDs,"%s/%s",dsName,demo[i]);
+      fprintf(stderr,"read : %s\n",tmpDs);
+      
+      VSILFILE* vsif=VSIFOpenL(tmpDs,"rb");
+#ifdef DEBUGMS
+      fprintf(stderr,"open : %s\n",tmpDs);
+#endif
+      VSIFSeekL(vsif,0,SEEK_END);
+      vsi_l_offset size=VSIFTellL(vsif);
+#ifdef DEBUGMS
+      fprintf(stderr,"size : %d\n",size);
+#endif
+      VSIFSeekL(vsif,0,SEEK_SET);
+      char *vsifcontent=(char*) malloc(((int)size+1)*sizeof(char));
+      VSIFReadL(vsifcontent,1,(size_t)size,vsif);
+      char *fpath=(char*) malloc((strlen(sdsName)+strlen(demo[1])+2)*sizeof(char));
+      sprintf(fpath,"%s/%s",sdsName,demo[i]);
+      int f=zOpen(fpath,O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
+      zWrite(f,vsifcontent,(int)size);
+      close(f);
+      chmod(fpath,S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH);
+      char* tmpP=strstr(fpath,".shp");
+      if(tmpP==NULL)
+	tmpP=strstr(fpath,".SHP");
+      if(tmpP!=NULL){
+#ifdef DEBUGMS
+	fprintf(stderr,"*** DEBUG %s\n",strstr(tmpP,"."));
+#endif
+	if( strcmp(tmpP,".shp")==0 || strcmp(tmpP,".SHP")==0 ){
+	  tmpMap=getMap(output->content,"storage");
+	  free(tmpMap->value);
+	  tmpMap->value=(char*) malloc((strlen(fpath)+1)*sizeof(char));
+	  sprintf(tmpMap->value,"%s",fpath);
+	  pszDataSource=tmpMap->value;
+#ifdef DEBUGMS
+	  fprintf(stderr,"*** DEBUG %s\n",pszDataSource);
+#endif
+	}
+      }
+      VSIFCloseL(vsif);
+      i++;
+    }
+  }
+  free(sdsName);
+  free(dsName);
+
+  OGRDataSourceH poDS = NULL;
+  OGRSFDriverH *poDriver = NULL;
+  poDS = OGROpen( pszDataSource, FALSE, poDriver );
+  if( poDS == NULL ){
+#ifdef DEBUGMS
+    fprintf(stderr,"Unable to access the DataSource %s\n",pszDataSource);
+#endif
+    setMapInMaps(conf,"lenv","message","Unable to open datasource in read only mode");
+    OGR_DS_Destroy(poDS);
+    OGRCleanupAll();
+#ifdef DEBUGMS
+    fprintf(stderr,"Unable to access the DataSource, exit! \n"); 
+#endif
+    return -1;
+  }
+
+  int iLayer = 0;
+  for( iLayer=0; iLayer < OGR_DS_GetLayerCount(poDS); iLayer++ ){
+    OGRLayerH poLayer = OGR_DS_GetLayer(poDS,iLayer);
+
+    if( poLayer == NULL ){
+#ifdef DEBUGMS
+      fprintf(stderr,"Unable to access the DataSource Layer \n");
+#endif
+      setMapInMaps(conf,"lenv","message","Unable to open datasource in read only mode");
+      return -1;
+    }
+
+    /**
+     * Add a new layer set name, data
+     */
+    if(msGrowMapLayers(m)==NULL){
+      return -1;
+    }
+    if(initLayer((m->layers[m->numlayers]), m) == -1){
+      return -1;
+    }
+
+    layerObj* myLayer=m->layers[m->numlayers];
+#ifdef DEBUGMS
+    dumpMaps(output);
+#endif
+    myLayer->name = zStrdup(output->name);
+    myLayer->tileitem=NULL;
+    myLayer->data = zStrdup(OGR_L_GetName(poLayer));
+    myLayer->connection = zStrdup(pszDataSource);
+    myLayer->index = m->numlayers;
+    myLayer->dump = MS_TRUE;
+    myLayer->status = MS_ON;
+    msConnectLayer(myLayer,MS_OGR,pszDataSource);
+
+    /**
+     * Detect the Geometry Type or use Polygon
+     */
+    if(OGR_L_GetGeomType(poLayer) != wkbUnknown){
+      switch(OGR_L_GetGeomType(poLayer)){
+      case wkbPoint:
+      case wkbMultiPoint:
+      case wkbPoint25D:
+      case wkbMultiPoint25D:
+#ifdef DEBUGMS
+	fprintf(stderr,"POINT DataSource Layer \n");
+#endif
+	myLayer->type = MS_LAYER_POINT;
+	break;
+      case wkbLineString :
+      case wkbMultiLineString :
+      case wkbLineString25D:
+      case wkbMultiLineString25D:
+#ifdef DEBUGMS
+	fprintf(stderr,"LINE DataSource Layer \n");
+#endif
+	myLayer->type = MS_LAYER_LINE;
+	break;
+      case wkbPolygon:
+      case wkbMultiPolygon:
+      case wkbPolygon25D:
+      case wkbMultiPolygon25D:
+#ifdef DEBUGMS
+	fprintf(stderr,"POLYGON DataSource Layer \n");
+#endif
+	myLayer->type = MS_LAYER_POLYGON;
+	break;
+      default:
+	myLayer->type = MS_LAYER_POLYGON;
+	break;
+      }
+    }else
+      myLayer->type = MS_LAYER_POLYGON;
+
+    /**
+     * Detect spatial reference or use WGS84
+     */
+    OGRSpatialReferenceH srs=OGR_L_GetSpatialRef(poLayer);
+    if(srs!=NULL){
+      char *wkt=NULL;
+      OSRExportToWkt(srs,&wkt);
+      setSrsInformations(output,m,myLayer,wkt);
+      free(wkt);
+    }
+    else{
+      addToMap(output->content,"crs","EPSG:4326");
+      addToMap(output->content,"crs_isGeographic","true");
+      msLoadProjectionStringEPSG(&m->projection,"EPSG:4326");
+      msInsertHashTable(&(m->web.metadata), "ows_srs", "EPSG:4326 EPSG:900913");
+      msInsertHashTable(&(myLayer->metadata), "ows_srs", "EPSG:4326 EPSG:900913");
+    }
+
+    OGREnvelope oExt;
+    if (OGR_L_GetExtent(poLayer,&oExt, TRUE) == OGRERR_NONE){
+      setMsExtent(output,m,myLayer,oExt.MinX, oExt.MinY, oExt.MaxX, oExt.MaxY);
+    }
+  
+    /**
+     * Detect the FID column or use the first attribute field as FID
+     */
+    char *fid=(char*)OGR_L_GetFIDColumn(poLayer);
+    if(strlen(fid)==0){
+      OGRFeatureDefnH def=OGR_L_GetLayerDefn(poLayer);
+      int fIndex=0;
+      for(fIndex=0;fIndex<OGR_FD_GetFieldCount(def);fIndex++){
+	OGRFieldDefnH fdef=OGR_FD_GetFieldDefn(def,fIndex);
+	fid=(char*)OGR_Fld_GetNameRef(fdef);
+	break;
+      }
+    }
+    msInsertHashTable(&(myLayer->metadata), "gml_featureid", fid);
+    msInsertHashTable(&(myLayer->metadata), "gml_include_items", "all");
+    msInsertHashTable(&(myLayer->metadata), "ows_name", output->name);
+    map* tmpMap=getMap(output->content,"title");
+    if(tmpMap!=NULL)
+      msInsertHashTable(&(myLayer->metadata), "ows_title", tmpMap->value);
+    else
+      msInsertHashTable(&(myLayer->metadata), "ows_title", "Default Title");
+    
+    if(msGrowLayerClasses(myLayer) == NULL)
+      return -1;
+    if(initClass((myLayer->CLASS[myLayer->numclasses])) == -1)
+      return -1;
+    myLayer->CLASS[myLayer->numclasses]->type = myLayer->type;
+    if(msGrowClassStyles(myLayer->CLASS[myLayer->numclasses]) == NULL)
+      return -1;
+    if(initStyle(myLayer->CLASS[myLayer->numclasses]->styles[myLayer->CLASS[myLayer->numclasses]->numstyles]) == -1)
+      return -1;
+    /**
+     * Apply msStyle else fallback to the default style
+     */
+    tmpMap=getMap(output->content,"msStyle");
+    if(tmpMap!=NULL)
+      msUpdateStyleFromString(myLayer->CLASS[myLayer->numclasses]->styles[myLayer->CLASS[myLayer->numclasses]->numstyles],tmpMap->value,0);
+    else{
+      /**
+       * Set style
+       */
+      myLayer->CLASS[myLayer->numclasses]->styles[myLayer->CLASS[myLayer->numclasses]->numstyles]->color.red=125;
+      myLayer->CLASS[myLayer->numclasses]->styles[myLayer->CLASS[myLayer->numclasses]->numstyles]->color.green=125;
+      myLayer->CLASS[myLayer->numclasses]->styles[myLayer->CLASS[myLayer->numclasses]->numstyles]->color.blue=255;
+      myLayer->CLASS[myLayer->numclasses]->styles[myLayer->CLASS[myLayer->numclasses]->numstyles]->outlinecolor.red=80;
+      myLayer->CLASS[myLayer->numclasses]->styles[myLayer->CLASS[myLayer->numclasses]->numstyles]->outlinecolor.green=80;
+      myLayer->CLASS[myLayer->numclasses]->styles[myLayer->CLASS[myLayer->numclasses]->numstyles]->outlinecolor.blue=80;
+      
+      /**
+       * Set specific style depending on type
+       */
+      if(myLayer->type == MS_LAYER_POLYGON)
+	myLayer->CLASS[myLayer->numclasses]->styles[myLayer->CLASS[myLayer->numclasses]->numstyles]->width=3;
+      if(myLayer->type == MS_LAYER_LINE){
+	myLayer->CLASS[myLayer->numclasses]->styles[myLayer->CLASS[myLayer->numclasses]->numstyles]->width=3;
+	myLayer->CLASS[myLayer->numclasses]->styles[myLayer->CLASS[myLayer->numclasses]->numstyles]->outlinewidth=1.5;
+      }
+      if(myLayer->type == MS_LAYER_POINT){
+	myLayer->CLASS[myLayer->numclasses]->styles[myLayer->CLASS[myLayer->numclasses]->numstyles]->symbol=1;
+	myLayer->CLASS[myLayer->numclasses]->styles[myLayer->CLASS[myLayer->numclasses]->numstyles]->size=15;
+      }
+      
+    }
+    myLayer->CLASS[myLayer->numclasses]->numstyles++;
+    myLayer->numclasses++;
+    
+    m->layerorder[m->numlayers] = m->numlayers;
+    m->numlayers++;
+
+  }
+
+  OGR_DS_Destroy(poDS);
+  OGRCleanupAll();
+
+  return 1;
+}
+
+/**
+ * Try to open a raster output and define the corresponding layer in the MAPFILE
+ *
+ * @param conf the conf maps containing the main.cfg settings
+ * @param output the specific output maps
+ * @param m the mapObj
+ */
+int tryGdal(maps* conf,maps* output,mapObj* m){
+  map* tmpMap=getMap(output->content,"storage");
+  char *pszFilename=tmpMap->value;
+  GDALDatasetH hDataset;
+  GDALRasterBandH hBand;
+  double adfGeoTransform[6];
+  int i, iBand;
+  
+  /**
+   * Try to open the DataSource using GDAL
+   */
+  GDALAllRegister();
+  hDataset = GDALOpen( pszFilename, GA_ReadOnly );
+  if( hDataset == NULL ){
+#ifdef DEBUGMS
+    fprintf(stderr,"Unable to access the DataSource %s \n",pszFilename);
+#endif
+    setMapInMaps(conf,"lenv","message","gdalinfo failed - unable to open");
+    GDALDestroyDriverManager();
+    return -1;
+  }
+#ifdef DEBUGMS
+  fprintf(stderr,"Accessing the DataSource %s %d\n",pszFilename,__LINE__);
+#endif
+
+  /**
+   * Add a new layer set name, data
+   */
+  if(msGrowMapLayers(m)==NULL){
+    return -1;
+  }
+  if(initLayer((m->layers[m->numlayers]), m) == -1){
+    return -1;
+  }
+  m->layers[m->numlayers]->index=m->numlayers;
+
+  layerObj* myLayer=m->layers[m->numlayers];
+  myLayer->name = zStrdup(output->name);
+  myLayer->tileitem=NULL;
+  myLayer->data = zStrdup(pszFilename);
+  myLayer->index = m->numlayers;
+  myLayer->dump = MS_TRUE;
+  myLayer->status = MS_ON;
+  myLayer->type = MS_LAYER_RASTER;
+
+  char *title=output->name;
+  tmpMap=getMap(output->content,"title");
+  if(tmpMap!=NULL)
+    title=tmpMap->value;
+  char *abstract=output->name;
+  tmpMap=getMap(output->content,"abstract");
+  if(tmpMap!=NULL)
+    abstract=tmpMap->value;
+
+  msInsertHashTable(&(myLayer->metadata), "ows_label", title);
+  msInsertHashTable(&(myLayer->metadata), "ows_title", title);
+  msInsertHashTable(&(myLayer->metadata), "ows_abstract", abstract);
+  msInsertHashTable(&(myLayer->metadata), "ows_rangeset_name", output->name);
+  msInsertHashTable(&(myLayer->metadata), "ows_rangeset_label", title);
+
+  /**
+   * Set Map Size to the raster size
+   */
+  m->width=GDALGetRasterXSize( hDataset );
+  m->height=GDALGetRasterYSize( hDataset );
+  
+  /**
+   * Set projection using Authority Code and Name if available or fallback to 
+   * proj4 definition if available or fallback to default EPSG:4326
+   */
+  const char *tRef=GDALGetProjectionRef( hDataset );
+  if( tRef != NULL && strlen(tRef)>0 ){
+    char *pszProjection;
+    pszProjection = (char *) GDALGetProjectionRef( hDataset );
+#ifdef DEBUGMS
+    fprintf(stderr,"Accessing the DataSource %s\n",GDALGetProjectionRef( hDataset ));
+#endif
+    setSrsInformations(output,m,myLayer,pszProjection);
+  }else{
+    fprintf(stderr,"NO SRS FOUND ! %s\n",GDALGetProjectionRef( hDataset ));    
+  }
+
+
+  /**
+   * Set extent
+   */
+  if( GDALGetGeoTransform( hDataset, adfGeoTransform ) == CE_None ){
+    if( adfGeoTransform[2] == 0.0 && adfGeoTransform[4] == 0.0 ){
+
+      double minX = adfGeoTransform[0]
+	+ adfGeoTransform[2] * GDALGetRasterYSize(hDataset);
+      double minY = adfGeoTransform[3]
+	+ adfGeoTransform[5] * GDALGetRasterYSize(hDataset);
+
+      double maxX = adfGeoTransform[0]
+	+ adfGeoTransform[1] * GDALGetRasterXSize(hDataset);
+      double maxY = adfGeoTransform[3]
+	+ adfGeoTransform[4] * GDALGetRasterXSize(hDataset);
+
+       setMsExtent(output,m,myLayer,minX,minY,maxX,maxY);
+
+    }
+  }
+
+  /**
+   * Extract information about available bands to set the bandcount and the
+   * processing directive
+   */
+  char nBands[2];
+  int nBandsI=GDALGetRasterCount( hDataset );
+  sprintf(nBands,"%d",GDALGetRasterCount( hDataset ));
+  msInsertHashTable(&(myLayer->metadata), "ows_bandcount", nBands);
+  if(nBandsI>=3)
+    msLayerAddProcessing(myLayer,"BANDS=1,2,3");
+  else if(nBandsI>=2)
+    msLayerAddProcessing(myLayer,"BANDS=1,2");
+  else
+    msLayerAddProcessing(myLayer,"BANDS=1");
+
+  /**
+   * Name available Bands
+   */
+  char lBands[6];
+  char *nameBands=NULL;
+  for( iBand = 0; iBand < nBandsI; iBand++ ){
+    sprintf(lBands,"Band%d",iBand+1);
+    if(nameBands==NULL){
+      nameBands=(char*)malloc((strlen(lBands)+1)*sizeof(char));
+      sprintf(nameBands,"%s",lBands);
+    }else{
+      if(iBand<4){
+	char *tmpS=zStrdup(nameBands);
+	nameBands=(char*)realloc(nameBands,(strlen(nameBands)+strlen(lBands)+1)*sizeof(char));
+	sprintf(nameBands,"%s %s",tmpS,lBands);
+	free(tmpS);
+      }
+    }
+  }
+  msInsertHashTable(&(myLayer->metadata), "ows_bandnames", nameBands);
+  
+  /**
+   * Loops over metadata informations to setup specific informations
+   */
+  for( iBand = 0; iBand < nBandsI; iBand++ ){
+    //int         bGotNodata;//, bSuccess;
+    double      adfCMinMax[2]/*, dfNoData*/;
+    //int         nBlockXSize, nBlockYSize, nMaskFlags;
+    //double      /*dfMean, dfStdDev*/;
+    hBand = GDALGetRasterBand( hDataset, iBand+1 );
+
+    CPLErrorReset();
+    GDALComputeRasterMinMax( hBand, FALSE, adfCMinMax );
+    char tmpN[21];
+    sprintf(tmpN,"Band%d",iBand+1);
+    if (CPLGetLastErrorType() == CE_None){
+      char tmpMm[100];
+      sprintf(tmpMm,"%.3f %.3f",adfCMinMax[0],adfCMinMax[1]);
+      char tmpI[21];
+      sprintf(tmpI,"%s_interval",tmpN);
+      msInsertHashTable(&(myLayer->metadata), tmpI, tmpMm);
+
+      map* test=getMap(output->content,"msClassify");
+      if(test!=NULL && strncasecmp(test->value,"true",4)==0){
+	/**
+	 * Classify one band raster pixel value using regular interval
+	 */
+	int _tmpColors[10][3]={
+	  {102,153,204},
+	  {51,102,153},
+	  {102,102,204},
+	  {51,204,0},
+	  {153,255,102},
+	  {204,255,102},
+	  {102,204,153},
+	  {255,69,64},
+	  {255,192,115},
+	  {255,201,115}
+	};
+	  
+	if(nBandsI==1){
+	  double delta=adfCMinMax[1]-adfCMinMax[0];
+	  double interval=delta/10;
+	  double cstep=adfCMinMax[0];
+	  for(i=0;i<10;i++){
+	    /**
+	     * Create a new class
+	     */
+	    if(msGrowLayerClasses(myLayer) == NULL)
+	      return -1;
+	    if(initClass((myLayer->CLASS[myLayer->numclasses])) == -1)
+	      return -1;
+	    myLayer->CLASS[myLayer->numclasses]->type = myLayer->type;
+	    if(msGrowClassStyles(myLayer->CLASS[myLayer->numclasses]) == NULL)
+	      return -1;
+	    if(initStyle(myLayer->CLASS[myLayer->numclasses]->styles[myLayer->CLASS[myLayer->numclasses]->numstyles]) == -1)
+	      return -1;
+	    
+	    /**
+	     * Set class name
+	     */
+	    char className[7];
+	    sprintf(className,"class%d",i);
+	    myLayer->CLASS[myLayer->numclasses]->name=zStrdup(className);
+	    
+	    /**
+	     * Set expression
+	     */
+	    char expression[1024];
+	    if(i+1<10)
+	      sprintf(expression,"([pixel]>=%.3f AND [pixel]<%.3f)",cstep,cstep+interval);
+	    else
+	      sprintf(expression,"([pixel]>=%.3f AND [pixel]<=%.3f)",cstep,cstep+interval);
+	    msLoadExpressionString(&myLayer->CLASS[myLayer->numclasses]->expression,expression);
+	    
+	    /**
+	     * Set color
+	     */
+	    myLayer->CLASS[myLayer->numclasses]->styles[myLayer->CLASS[myLayer->numclasses]->numstyles]->color.red=_tmpColors[i][0];
+	    myLayer->CLASS[myLayer->numclasses]->styles[myLayer->CLASS[myLayer->numclasses]->numstyles]->color.green=_tmpColors[i][1];
+	    myLayer->CLASS[myLayer->numclasses]->styles[myLayer->CLASS[myLayer->numclasses]->numstyles]->color.blue=_tmpColors[i][2];
+	    cstep+=interval;
+	    myLayer->CLASS[myLayer->numclasses]->numstyles++;
+	    myLayer->numclasses++;
+	    
+	  }
+	  
+	  char tmpMm[100];
+	  sprintf(tmpMm,"%.3f %.3f",adfCMinMax[0],adfCMinMax[1]);
+	  
+	}
+      }
+    }
+    if( strlen(GDALGetRasterUnitType(hBand)) > 0 ){
+      char tmpU[21];
+      sprintf(tmpU,"%s_band_uom",tmpN);
+      msInsertHashTable(&(myLayer->metadata), tmpU, GDALGetRasterUnitType(hBand));
+    }
+
+  }
+
+  m->layerorder[m->numlayers] = m->numlayers;
+  m->numlayers++;
+  GDALClose( hDataset );
+  GDALDestroyDriverManager();
+  CPLCleanupTLS();
+  return 1;
+}
+
+/**
+ * Create a MapFile for WMS, WFS or WCS Service output
+ *
+ * @param conf the conf maps containing the main.cfg settings
+ * @param outputs a specific output maps
+ */
+void outputMapfile(maps* conf,maps* outputs){
+
+  /**
+   * First store the value on disk
+   */
+  map* mime=getMap(outputs->content,"mimeType");
+  char *ext="data";
+  if(mime!=NULL)
+    if(strncasecmp(mime->value,"application/json",16)==0)
+      ext="json";
+
+  map* tmpMap=getMapFromMaps(conf,"main","dataPath");
+  map* sidMap=getMapFromMaps(conf,"lenv","usid");
+  char *pszDataSource=(char*)malloc((strlen(tmpMap->value)+strlen(sidMap->value)+strlen(outputs->name)+17)*sizeof(char));
+  sprintf(pszDataSource,"%s/ZOO_DATA_%s_%s.%s",tmpMap->value,outputs->name,sidMap->value,ext); 
+  int f=zOpen(pszDataSource,O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
+  map *gfile=getMap(outputs->content,"generated_file");
+  if(gfile!=NULL){
+    readGeneratedFile(conf,outputs->content,gfile->value);	    
+  }
+  map* sizeMap=getMap(outputs->content,"size");
+  map* vData=getMap(outputs->content,"value");
+  if(sizeMap!=NULL){
+    zWrite(f,vData->value,atoi(sizeMap->value)*sizeof(char));
+  }
+  else{
+    zWrite(f,vData->value,(strlen(vData->value)+1)*sizeof(char));
+  }
+  close(f);
+  addToMap(outputs->content,"storage",pszDataSource);
+  free(pszDataSource);
+
+  /*
+   * Create an empty map, set name, default size and extent
+   */
+  mapObj *myMap=msNewMapObj();
+  free(myMap->name);
+  myMap->name=zStrdup("ZOO-Project_WXS_Server");
+  msMapSetSize(myMap,2048,2048);
+  msMapSetExtent(myMap,-1,-1,1,1);
+  
+  /*
+   * Set imagepath and imageurl using tmpPath and tmpUrl from main.cfg
+   */
+  map *tmp1=getMapFromMaps(conf,"main","tmpPath");
+  myMap->web.imagepath=zStrdup(tmp1->value);
+  tmp1=getMapFromMaps(conf,"main","tmpUrl");
+  myMap->web.imageurl=zStrdup(tmp1->value);
+  
+  /*
+   * Define supported output formats
+   */
+  outputFormatObj *o1=msCreateDefaultOutputFormat(NULL,"AGG/PNG","png");
+  o1->imagemode=MS_IMAGEMODE_RGBA;
+  o1->transparent=MS_TRUE;
+  o1->inmapfile=MS_TRUE;
+  msAppendOutputFormat(myMap,msCloneOutputFormat(o1));
+  msFreeOutputFormat(o1);
+
+#ifdef USE_KML
+  outputFormatObj *o2=msCreateDefaultOutputFormat(NULL,"KML","kml");
+  o2->inmapfile=MS_TRUE;  
+  msAppendOutputFormat(myMap,msCloneOutputFormat(o2));
+  msFreeOutputFormat(o2);
+#endif
+
+  outputFormatObj *o3=msCreateDefaultOutputFormat(NULL,"GDAL/GTiff","tiff");
+  if(!o3)
+    fprintf(stderr,"Unable to initialize GDAL driver !\n");
+  else{
+    o3->imagemode=MS_IMAGEMODE_BYTE;
+    o3->inmapfile=MS_TRUE;  
+    msAppendOutputFormat(myMap,msCloneOutputFormat(o3));
+    msFreeOutputFormat(o3);
+  }
+
+  outputFormatObj *o4=msCreateDefaultOutputFormat(NULL,"GDAL/AAIGRID","grd");
+  if(!o4)
+    fprintf(stderr,"Unable to initialize GDAL driver !\n");
+  else{
+    o4->imagemode=MS_IMAGEMODE_INT16;
+    o4->inmapfile=MS_TRUE;  
+    msAppendOutputFormat(myMap,msCloneOutputFormat(o4));
+    msFreeOutputFormat(o4);
+  }
+
+#ifdef USE_CAIRO
+  outputFormatObj *o5=msCreateDefaultOutputFormat(NULL,"CAIRO/PNG","cairopng");
+  if(!o5)
+    fprintf(stderr,"Unable to initialize CAIRO driver !\n");
+  else{
+    o5->imagemode=MS_IMAGEMODE_RGBA;
+    o5->transparent=MS_TRUE;
+    o5->inmapfile=MS_TRUE;
+    msAppendOutputFormat(myMap,msCloneOutputFormat(o5));
+    msFreeOutputFormat(o5);
+  }
+#endif
+
+  /*
+   * Set default projection to EPSG:4326
+   */
+  msLoadProjectionStringEPSG(&myMap->projection,"EPSG:4326");
+  myMap->transparent=1;
+
+  /**
+   * Set metadata extracted from main.cfg file maps
+   */
+  maps* cursor=conf;
+  map* correspondance=getCorrespondance();
+  while(cursor!=NULL){
+    map* _cursor=cursor->content;
+    map* vMap;
+    while(_cursor!=NULL){
+      if((vMap=getMap(correspondance,_cursor->name))!=NULL){
+	if (msInsertHashTable(&(myMap->web.metadata), vMap->value, _cursor->value) == NULL){
+#ifdef DEBUGMS
+	  fprintf(stderr,"Unable to add metadata");
+#endif
+	  return;
+	}
+      }
+      _cursor=_cursor->next;
+    }
+    cursor=cursor->next;
+  }
+  freeMap(&correspondance);
+  free(correspondance);
+
+  /*
+   * Set mapserver PROJ_LIB/GDAL_DATA or any other config parameter from 
+   * the main.cfg [mapserver] section if any
+   */
+  maps *tmp3=getMaps(conf,"mapserver");
+  if(tmp3!=NULL){
+    map* tmp4=tmp3->content;
+    while(tmp4!=NULL){
+      msSetConfigOption(myMap,tmp4->name,tmp4->value);
+      tmp4=tmp4->next;
+    }
+  }
+
+  /**
+   * Set a ows_rootlayer_title,  
+   */
+  if (msInsertHashTable(&(myMap->web.metadata), "ows_rootlayer_name", "ZOO_Project_Layer") == NULL){
+#ifdef DEBUGMS
+    fprintf(stderr,"Unable to add metadata");
+#endif
+    return;
+  }
+  if (msInsertHashTable(&(myMap->web.metadata), "ows_rootlayer_title", "ZOO_Project_Layer") == NULL){
+#ifdef DEBUGMS
+    fprintf(stderr,"Unable to add metadata");
+#endif
+    return;
+  }
+
+  /**
+   * Enable all the WXS requests using ows_enable_request
+   * see http://mapserver.org/trunk/development/rfc/ms-rfc-67.html
+   */
+  if (msInsertHashTable(&(myMap->web.metadata), "ows_enable_request", "*") == NULL){
+#ifdef DEBUGMS
+    fprintf(stderr,"Unable to add metadata");
+#endif
+    return;
+  }
+  msInsertHashTable(&(myMap->web.metadata), "ows_srs", "EPSG:4326");
+
+  if(tryOgr(conf,outputs,myMap)<0)
+    if(tryGdal(conf,outputs,myMap)<0)
+      return ;
+
+  tmp1=getMapFromMaps(conf,"main","dataPath");
+  char *tmpPath=(char*)malloc((13+strlen(tmp1->value))*sizeof(char));
+  sprintf(tmpPath,"%s/symbols.sym",tmp1->value);
+  msInitSymbolSet(&myMap->symbolset);
+  myMap->symbolset.filename=zStrdup(tmpPath);
+  free(tmpPath);
+
+  map* sid=getMapFromMaps(conf,"lenv","usid");
+  char *mapPath=
+    (char*)malloc((7+strlen(sid->value)+strlen(outputs->name)+strlen(tmp1->value))*sizeof(char));
+  sprintf(mapPath,"%s/%s_%s.map",tmp1->value,outputs->name,sid->value);
+  msSaveMap(myMap,mapPath);
+  free(mapPath);
+  msGDALCleanup();
+  msFreeMap(myMap);
+}
+
diff --git a/zoo-project/zoo-kernel/service_internal_ms.h b/zoo-project/zoo-kernel/service_internal_ms.h
new file mode 100644
index 0000000..5010dee
--- /dev/null
+++ b/zoo-project/zoo-kernel/service_internal_ms.h
@@ -0,0 +1,62 @@
+/*
+ * Author : Gérald FENOY
+ *
+ *  Copyright 2010  Fondazione Edmund Mach. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef ZOO_SERVICE_INTERNAL_MS_H
+#define ZOO_SERVICE_INTERNAL_MS_H 1
+
+#include <sys/stat.h>
+#include "service_internal.h"
+#include "service.h"
+#include "cpl_conv.h"
+#include "cpl_multiproc.h"
+#include "ogr_api.h"
+#include "gdal.h"
+#include "ogr_srs_api.h"
+#include "ulinet.h"
+#ifdef WIN32
+#include <unistd.h>
+#endif
+
+#include <mapserver.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+  map* getCorrespondance();
+  void setMapSize(maps* output,double minx,double miny,double maxy,double maxx);
+  void setReferenceUrl(maps* m,maps* tmpI);
+
+  void setSrsInformations(maps* output,mapObj* m,layerObj* myLayer, char* pszProjection);
+  
+  void setMsExtent(maps* output,mapObj* m,layerObj* myLayer,
+		   double minX,double minY,double maxX,double maxY);
+  int tryOgr(maps* conf,maps* output,mapObj* m);
+  
+  int tryGdal(maps* conf,maps* output,mapObj* m);
+  void outputMapfile(maps* conf,maps* outputs);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+ 
diff --git a/zoo-project/zoo-kernel/service_internal_otb.c b/zoo-project/zoo-kernel/service_internal_otb.c
new file mode 100644
index 0000000..33863fe
--- /dev/null
+++ b/zoo-project/zoo-kernel/service_internal_otb.c
@@ -0,0 +1,483 @@
+/*
+ * Author : Gérald FENOY
+ *
+ * Copyright (c) 2015 GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * See Ref: http://hg.orfeo-toolbox.org/OTB/ Copyright
+ * Some parts of this code are derived from ITK. See ITKCopyright.txt for 
+ * details.
+ */
+
+#include "service_internal_otb.h"
+#include "response_print.h"
+#include "server_internal.h"
+
+using namespace otb::Wrapper;
+
+/**
+ * Global OTB counter 
+ */
+int otbCounter=0;
+
+/**
+ * The ZooWatcher list
+ */
+WatcherListType m_WatcherList;
+/**
+ * A pointer to the conf maps containing the main.cfg settings
+ */
+maps* m_Conf;
+
+/**
+ * The command to create a ZooWatcher and add it to the global m_WatcherList
+ */
+class MyCommand : public itk::Command
+{
+ public:
+  itkNewMacro( MyCommand );
+ public:
+
+  /**
+   * The method that defines the action to be taken by the command. 
+   *
+   * @param caller an itk::Object pointer
+   * @param event an itk::EventObject pointer
+   */
+  void Execute(itk::Object *caller, const itk::EventObject & event)
+  {
+    Execute( (const itk::Object *)caller, event);
+  }
+ 
+  /**
+   * The method that defines the action to be taken by the command. 
+   * Create a new ZooWatcher instance then add it to the m_WatcherList.
+   *
+   * @param caller a const itk::Object pointer
+   * @param event an itk::EventObject pointer
+   * @see ZooWatcher,ZooWatcher::SetConf
+   */
+  void Execute(const itk::Object *caller, const itk::EventObject & event)
+  {
+    const AddProcessToWatchEvent* eventToWatch = dynamic_cast< const AddProcessToWatchEvent*> ( &event );
+    std::string m_CurrentDescription = eventToWatch->GetProcessDescription();
+    ZooWatcher * watch = new ZooWatcher(eventToWatch->GetProcess(),
+					eventToWatch->GetProcessDescription());
+    watch->SetConf(&m_Conf);
+    m_WatcherList.push_back(watch);
+  }
+
+};
+
+/**
+ * Replace all occurence of from by to in a str string
+ *
+ * @param str the string to transform
+ * @param from the string to replace
+ * @param to the string used as replacement
+ * @return the resulting string 
+ */
+std::string ReplaceAll(std::string str, const std::string& from, const std::string& to) {
+    size_t start_pos = 0;
+    while((start_pos = str.find(from, start_pos)) != std::string::npos) {
+        str.replace(start_pos, from.length(), to);
+        start_pos += to.length(); // Handles case where 'to' is a substring of 'from'
+    }
+    return str;
+}
+
+/**
+ * Load and run an OTB Application corresponding to the service by using inputs parameters.
+ * Define the m_Conf 
+ *
+ * @param main_conf the conf maps containing the main.cfg settings
+ * @param request the map containing the HTTP request
+ * @param s the service structure
+ * @param real_inputs the maps containing the inputs
+ * @param real_outputs the maps containing the outputs
+ */
+int zoo_otb_support(maps** main_conf,map* request,service* s,maps **real_inputs,maps **real_outputs){
+  maps* m=*main_conf;
+  maps* inputs=*real_inputs;
+  maps* outputs=*real_outputs;
+  map* tmp0=getMapFromMaps(*main_conf,"lenv","cwd");
+  char *ntmp=tmp0->value;
+  map* tmp=NULL;
+  int res=-1;
+  std::vector<std::string> list = ApplicationRegistry::GetAvailableApplications();
+  if (list.size() == 0){
+    map* tmps=createMap("text","No OTB Application found.");
+    addToMap(tmps,"code","InternalError");
+    printExceptionReportResponse(m,tmps);
+    freeMap(&tmps);
+    free(tmps);
+    res=-1;
+    return res;
+  }
+  else{
+    dumpMapsValuesToFiles(main_conf,real_inputs);
+    for (std::vector<std::string>::const_iterator it = list.begin(); it != list.end(); ++it){
+      if(s->name==*it){
+	Application::Pointer m_Application=ApplicationRegistry::CreateApplication(*it);
+	if (m_Application.IsNull()){
+	  char tmpS[1024];
+	  sprintf(tmpS, "The OTB Application %s cannot be loaded.", (*it).c_str());
+	  map* tmps=createMap("text",tmpS);
+	  addToMap(tmps,"code","InternalError");
+	  printExceptionReportResponse(m,tmps);
+	  freeMap(&tmps);
+	  free(tmps);
+	  res=-1;
+	}else{
+	  // Create Observer on AddProcessToWatchEvent
+	  m_Conf=m;
+	  MyCommand::Pointer myCommand = MyCommand::New();
+	  m_Application->AddObserver(AddProcessToWatchEvent(), myCommand);
+	  char tmpS[1024];
+	  const std::vector<std::string> appKeyList = m_Application->GetParametersKeys(true);
+	  for (unsigned int i = 0; i < appKeyList.size(); i++){
+	    const std::string paramKey(appKeyList[i]);
+	    Parameter::Pointer param = m_Application->GetParameterByKey(paramKey);
+	    ParameterType type = m_Application->GetParameterType(paramKey);
+	    if (type != ParameterType_Group && paramKey!="inxml" && paramKey!="outxml"){
+	      map* test=getMapFromMaps(inputs,paramKey.c_str(),"cache_file");
+	      if(test==NULL){
+		test=getMapFromMaps(inputs,paramKey.c_str(),"inRequest");
+		map* tmpPath=getMapFromMaps(m,"main","tmpPath");
+		map* tmpSid=getMapFromMaps(m,"lenv","usid");
+		char tmp[1024];
+		map* tmpVal=getMapFromMaps(outputs,paramKey.c_str(),"mimeType");
+		maps* tmpMaps=getMaps(outputs,paramKey.c_str());
+		if(tmpMaps!=NULL && test!=NULL && test->value!=NULL && strncasecmp(test->value,"true",4)==0){
+		  test=getMapFromMaps(inputs,paramKey.c_str(),"value");
+		  if(type == ParameterType_OutputImage){
+		    ImagePixelType outPixType = ImagePixelType_float;
+		    if (strncasecmp(test->value,"uint8",5)==0)
+		      outPixType = ImagePixelType_uint8;
+		    else if (strncasecmp(test->value,"int16",5)==0)
+		      outPixType = ImagePixelType_int16;
+		    else if (strncasecmp(test->value,"uint16",6)==0)
+		      outPixType = ImagePixelType_uint16;
+		    else if (strncasecmp(test->value,"int32",5)==0)
+		      outPixType = ImagePixelType_int32;
+		    else if (strncasecmp(test->value,"uint32",6)==0)
+		      outPixType = ImagePixelType_uint32;
+		    else if (strncasecmp(test->value,"double",6)==0)
+		      outPixType = ImagePixelType_double;
+		    const char* ext="tiff";
+		    if(tmpVal!=NULL){
+		      if(strncasecmp(tmpVal->value,"image/jp2",9)==0)
+			 ext="j2k";
+		      else
+			if(strncasecmp(tmpVal->value,"image/png",9)==0)
+			 ext="png";
+			else
+			  if(strncasecmp(tmpVal->value,"image/jpeg",10)==0)
+			    ext="jpeg";
+		    }
+		    sprintf(tmp,"%s/%s_%d_%s.%s",tmpPath->value,s->name,otbCounter,tmpSid->value,ext);
+		    otbCounter++;
+		    m_Application->SetParameterString(paramKey, tmp);
+		    setMapInMaps(inputs,paramKey.c_str(),"generated_file",tmp);
+		    dynamic_cast<OutputImageParameter *> (param.GetPointer())->SetPixelType(outPixType);
+		  }
+		  else{   	 	 
+		    if(test!=NULL && test->value!=NULL)  	 	 
+		      m_Application->SetParameterString(paramKey, test->value);  	 	 
+		  } 
+		}else{
+		  if(type == ParameterType_OutputVectorData){
+		      char* ext="json";
+		      if(tmpVal!=NULL){
+			if(strncasecmp(tmpVal->value,"text/xml",8)==0)
+			ext="gml";
+		      else
+			if(strncasecmp(tmpVal->value,"applicaton/json",15)==0)
+			  ext="json";
+			else
+			  if(strncasecmp(tmpVal->value,"application/zip",14)==0)
+			    ext="shp";
+			  else
+			    if(strncasecmp(tmpVal->value,"application/vnd.google-earth.kml+xml",36)==0)
+			      ext="kml";
+		      }
+		      sprintf(tmp,"%s/%s_%d_%s.%s",tmpPath->value,s->name,otbCounter,tmpSid->value,ext);
+		      otbCounter++;
+		      m_Application->SetParameterString(paramKey, tmp);
+		      setMapInMaps(inputs,paramKey.c_str(),"generated_file",tmp);
+		  }
+		  else
+		    if(type == ParameterType_OutputFilename){
+		      char* ext="txt";
+		      if(tmpVal!=NULL){
+			if(strncasecmp(tmpVal->value,"text/xml",8)==0)
+			  ext="xml";
+			else
+			  if(strncasecmp(tmpVal->value,"text/csv",15)==0)
+			    ext="csv";
+			  else
+			    if(strncasecmp(tmpVal->value,"application/zip",14)==0)
+			      ext="shp";
+			    else
+			      if(strncasecmp(tmpVal->value,"application/vnd.google-earth.kml+xml",36)==0)
+				ext="kml";
+			      else
+				if(strncasecmp(tmpVal->value,"application/vnd.google-earth.kmz",32)==0){
+				  ext="kmz";
+				  sprintf(tmp,"%s/%s_%d_%sxt.%s",tmpPath->value,s->name,otbCounter,tmpSid->value,ext);
+				  m_Application->SetParameterString(paramKey, tmp);
+				  setMapInMaps(outputs,paramKey.c_str(),"expected_generated_file",tmp);
+				}
+
+		      }
+		      sprintf(tmp,"%s/%s_%d_%s.%s",tmpPath->value,s->name,otbCounter,tmpSid->value,ext);
+		      otbCounter++;
+		      m_Application->SetParameterString(paramKey, tmp);
+		      setMapInMaps(inputs,paramKey.c_str(),"generated_file",tmp);
+		    }
+		    else{
+		      test=getMapFromMaps(inputs,paramKey.c_str(),"value");
+		      if(test!=NULL && type!=ParameterType_ListView){
+			m_Application->SetParameterString(paramKey, test->value);
+		      }
+		      else
+			if(type==ParameterType_ListView){
+			  std::vector<std::string> values;
+			  values.push_back(test->value);
+			  map* tmpLength=getMapFromMaps(inputs,paramKey.c_str(),"length");
+			  if(tmpLength!=NULL){
+			    int len=atoi(tmpLength->value);
+			    for(int k=1;k<len;k++){
+			      char tmp[15];
+			      sprintf(tmp,"cache_file_%d",k);
+			      map* tmpVal=getMapFromMaps(inputs,paramKey.c_str(),tmp);
+			      if(tmpVal!=NULL){
+				values.push_back(tmpVal->value);
+			      }
+			    }
+			  }
+			  dynamic_cast<ListViewParameter *> (param.GetPointer())->SetSelectedItems(values);
+			}
+		    }
+		}
+	      }else{
+		if(type == ParameterType_InputImageList){
+		  std::vector<std::string> values;
+		  values.push_back(test->value);
+		  map* tmpPath=getMapFromMaps(inputs,paramKey.c_str(),"length");
+		  if(tmpPath!=NULL){
+		    int len=atoi(tmpPath->value);
+		    for(int k=1;k<len;k++){
+		      char tmp[15];
+		      sprintf(tmp,"cache_file_%d",k);
+		      map* tmpVal=getMapFromMaps(inputs,paramKey.c_str(),tmp);
+		      if(tmpVal!=NULL){
+			values.push_back(tmpVal->value);
+		      }
+		    }
+		  }
+		  dynamic_cast<InputImageListParameter *> (param.GetPointer())->SetListFromFileName(values);
+		}
+		else
+		  if(type == ParameterType_InputVectorData || type == ParameterType_InputFilename){
+		    map* tmpPath=getMapFromMaps(m,"main","tmpPath");
+		    map* tmpSid=getMapFromMaps(m,"lenv","sid");
+		    char tmp[1024];
+		    map* tmpVal=getMapFromMaps(inputs,paramKey.c_str(),"mimeType");
+		    char* ext="json";
+		    if(tmpVal!=NULL){
+		      if(strncasecmp(tmpVal->value,"application/zip",14)==0){
+			char *tmpName=(char*)malloc((strlen(test->value)+9)*sizeof(char));
+			std::string test0(test->value);
+			if(test0.find(".zca")!=std::string::npos){
+			  symlink(test->value,ReplaceAll(test->value,".zca",".zip").c_str());
+			  sprintf(tmpName,"/vsizip/%s",ReplaceAll(test->value,".zca",".zip").c_str());
+			}else
+			  sprintf(tmpName,"/vsizip/%s",test->value);
+			char **files=VSIReadDir(tmpName);
+			int nFiles = CSLCount( files );
+			char *tmpSSName=(char*)malloc((strlen(tmpPath->value)+strlen(paramKey.c_str())+strlen(tmpSid->value)+9)*sizeof(char));
+			sprintf(tmpSSName,"%s/Input_%s_%s",tmpPath->value,paramKey.c_str(),tmpSid->value);
+			mkdir(tmpSSName,0777);
+			    
+			for(int kk=0;kk<nFiles;kk++){
+			  char *tmpSName=(char*)malloc((strlen(tmpName)+strlen(files[kk])+2)*sizeof(char));
+			  sprintf(tmpSName,"%s/%s",tmpName,files[kk]);
+			  VSILFILE* fmain=VSIFOpenL(tmpSName, "rb");
+			  if(fmain!=NULL){
+			    VSIFSeekL(fmain,0,SEEK_END);
+			    long count=VSIFTellL(fmain);
+			    VSIRewindL(fmain);
+
+			    char *content=(char*) malloc((count+1)*sizeof(char));  
+			    VSIFReadL(content,1,count*sizeof(char),fmain);
+			  
+			    char *tmpSSSName=(char*)malloc((strlen(tmpSSName)+strlen(files[kk])+2)*sizeof(char));
+			    sprintf(tmpSSSName,"%s/%s",tmpSSName,files[kk]);
+			    
+			    FILE* fx=fopen(tmpSSSName, "wb");
+			    fwrite(content,1,count,fx);
+			    fclose(fx);
+			    VSIFCloseL(fmain);
+			    free(content);
+			    std::string test1(tmpSSSName);
+			    if(test1.find(".shp")!=std::string::npos){
+			      setMapInMaps(inputs,paramKey.c_str(),"cache_file",tmpSSSName);
+			      test=getMapFromMaps(inputs,paramKey.c_str(),"cache_file");
+			    }
+			    free(tmpSSSName);
+			  }
+			  free(tmpSName);
+			}
+			free(tmpSSName);
+			free(tmpName);
+		      }
+		    }
+		    
+		    m_Application->SetParameterString(paramKey, test->value);
+		  }
+		  else
+		    if(type == ParameterType_InputImage
+		       || type == ParameterType_ComplexInputImage || type == ParameterType_InputVectorData
+		       || type == ParameterType_InputFilename){
+		      m_Application->SetParameterString(paramKey, test->value);
+		  }
+	      }
+	    }
+	    param->SetUserValue(true);
+	    m_Application->UpdateParameters();
+	  }
+
+	  try{
+	    if( m_Application->ExecuteAndWriteOutput() == 0 ){
+	      std::vector< std::pair<std::string, std::string> > paramList;
+	      paramList = m_Application->GetOutputParametersSumUp();
+	      if(paramList.size()>0)
+		for( unsigned int i=0; i<paramList.size(); i++){
+		  setMapInMaps(outputs,paramList[i].first.c_str(),"value",paramList[i].second.c_str());
+		}
+	      else{
+		const std::vector<std::string> appKeyList = m_Application->GetParametersKeys(true);
+		for (unsigned int i = 0; i < appKeyList.size(); i++){
+		  const std::string paramKey(appKeyList[i]);
+		  std::vector<std::string> values;
+		  Parameter::Pointer param = m_Application->GetParameterByKey(paramKey);
+		  ParameterType type = m_Application->GetParameterType(paramKey);
+		  if (type != ParameterType_Group && paramKey!="inxml" && paramKey!="outxml"
+		      && (type == ParameterType_OutputImage || type == ParameterType_OutputFilename
+			  || type == ParameterType_OutputVectorData ) ){
+		    if(type == ParameterType_OutputImage || type == ParameterType_OutputFilename || type == ParameterType_OutputVectorData){
+		      map* test=getMapFromMaps(outputs,paramKey.c_str(),"mimeType");
+		      if(test!=NULL && strncasecmp(test->value,"application/zip",15)==0){
+			
+			test=getMapFromMaps(inputs,paramKey.c_str(),"generated_file");
+			char tmpName[1024];
+			sprintf(tmpName,"/vsizip/%s",ReplaceAll(test->value,".shp",".zip").c_str());
+			VSILFILE* fmain=VSIFOpenL(tmpName, "w");
+			FILE * file;
+			char *tmp;
+			char tmpSName[1024];
+			long count;
+			
+			char *exts[4];
+			exts[0]=".shp";
+			exts[1]=".shx";
+			exts[2]=".dbf";
+			exts[3]=".prj";
+			for(int c=0;c<4;c++){
+			  sprintf(tmpSName,"%s/result%s",tmpName,exts[c]);
+			  
+			  file=fopen(ReplaceAll(test->value,".shp",exts[c]).c_str(),"rb");
+			  if(file!=NULL){
+			    fseek(file, 0, SEEK_END);
+			    count = ftell(file);
+			    rewind(file);
+			    
+			    tmp=(char*) malloc((count+1)*sizeof(char));  
+			    fread(tmp,1,count*sizeof(char),file);
+			    
+			    VSILFILE* fx=VSIFOpenL(tmpSName, "wb");
+			    VSIFWriteL(tmp,1,count,fx);
+			    VSIFCloseL(fx);
+			    fclose(file);
+			    free(tmp);
+			  }
+			}
+			
+			VSIFCloseL(fmain);
+			
+			FILE* file1=fopen(ReplaceAll(test->value,".shp",".zip").c_str(), "rb");
+			fseek(file1, 0, SEEK_END);
+			count=ftell(file1);
+			rewind(file1);
+			
+			tmp=(char*) malloc((count+1)*sizeof(char));  
+			fread(tmp,1,count*sizeof(char),file1);
+			
+			file=fopen(ReplaceAll(test->value,".shp",".zip").c_str(),"wb");
+			fwrite(tmp,1,count,file);
+			fclose(file);
+			free(tmp);
+			fclose(file1);
+			setMapInMaps(inputs,paramKey.c_str(),"generated_file",ReplaceAll(test->value,".shp",".zip").c_str());
+		      }
+		      test=getMapFromMaps(inputs,paramKey.c_str(),"generated_file");
+
+		      if(test!=NULL){
+			setMapInMaps(outputs,paramKey.c_str(),"generated_file",test->value);
+		      }
+
+		    }
+		  }
+		}
+	      }
+	      res=3;
+	      break;
+	    }
+	    else{
+	      sprintf(tmpS, "The OTB Application %s cannot be run.", s->name);
+	      setMapInMaps(m,"lenv","message",tmpS);
+	      res=SERVICE_FAILED;
+	    }
+	  }
+	  catch(std::exception& err){
+	    setMapInMaps(m,"lenv","message",err.what());
+	    return SERVICE_FAILED;
+	    
+	  }
+	  catch(...){
+	    setMapInMaps(m,"lenv","message","An unknown exception has been raised during application execution");
+	    res=SERVICE_FAILED;
+	  }
+	  break;
+	}
+      }
+    }
+  }
+
+  for (unsigned int i = 0; i < m_WatcherList.size(); i++){
+    m_WatcherList[i]->FreeConf();
+    delete m_WatcherList[i];
+    m_WatcherList[i] = NULL;
+  }
+  m_WatcherList.clear();
+
+  return res;
+}
diff --git a/zoo-project/zoo-kernel/service_internal_otb.h b/zoo-project/zoo-kernel/service_internal_otb.h
new file mode 100644
index 0000000..afa066f
--- /dev/null
+++ b/zoo-project/zoo-kernel/service_internal_otb.h
@@ -0,0 +1,53 @@
+/*
+ * Author : Gérald FENOY
+ *
+ * Copyright (c) 2015 GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef ZOO_SERVICE_INTERNAL_OTB_H
+#define ZOO_SERVICE_INTERNAL_OTB_H 1
+
+#pragma once 
+
+#include "otbWrapperApplication.h"
+#include "otbWrapperApplicationRegistry.h"
+#include "otbWrapperInputImageListParameter.h"
+#include "otbWrapperListViewParameter.h"
+#include "otbWrapperAddProcessToWatchEvent.h"
+#include "otbZooWatcher.h"
+#include "service_internal.h"
+#include "service.h"
+#include "cgic.h"
+#ifdef WIN32
+#include <windows.h>
+#include <direct.h>
+#endif
+#include <vector>
+#include <string>
+
+/**
+ * A vector to store the ZooWatcher
+ */
+typedef std::vector<ZooWatcher *> WatcherListType;
+
+int zoo_otb_support(maps**,map*,service*,maps**,maps**);
+
+#endif
diff --git a/zoo-project/zoo-kernel/service_internal_perl.c b/zoo-project/zoo-kernel/service_internal_perl.c
new file mode 100644
index 0000000..092198a
--- /dev/null
+++ b/zoo-project/zoo-kernel/service_internal_perl.c
@@ -0,0 +1,201 @@
+/**
+ * Author : David SAGGIORATO
+ *
+ * Copyright (c) 2009-2010 GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "service_internal_perl.h"
+
+
+static PerlInterpreter *my_perl;
+
+
+void xs_init(pTHX)
+{
+	char *file = __FILE__;
+	dXSUB_SYS;
+	
+	/* DynaLoader is a special case */
+	newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
+}
+
+
+
+int map_to_hash(map * m, HV ** hash_map) {
+	HV * tmp = *hash_map;
+	map * tmp_m = m;
+	do {
+		//printf("map name %s  value %s \n",m->name,m->value);
+
+		if ( NULL == hv_store( tmp, tmp_m->name, strlen(tmp_m->name), sv_2mortal(newSVpv(tmp_m->value, strlen(tmp_m->value))), 0) ) {
+			return 1;
+			}
+		tmp_m = tmp_m->next;
+		}
+	while (tmp_m != NULL);
+	return 0;
+}
+
+int maps_to_hash( maps* m, HV ** hash_maps){
+	HV * tmp = *hash_maps;
+	if (m != NULL) {
+		//printf("maps name %s \n",m->name);
+		HV* hash_m = (HV *)sv_2mortal((SV *)newHV());
+		if (map_to_hash(m->content,&hash_m) != 0){
+			return 1;
+		}
+		
+		if ( NULL == hv_store( tmp, m->name, strlen(m->name),sv_2mortal(newRV_inc((SV *)hash_m)), 0) ) {
+			return 1;
+		}	
+		return maps_to_hash(m->next,hash_maps);
+	}
+	return 0;
+}
+
+int hash_to_map(HV * hh,map ** m){
+	hv_iterinit(hh);
+	*m = (map *)malloc(MAP_SIZE);
+	if (*m == NULL){
+		// erreur d'allocation memoire
+		return 1;
+	}
+	map * tmp = *m;
+	HE * he = hv_iternext(hh);
+	while (he != NULL){
+		//fprintf(stderr,"key : %s  value : %s \n",HeKEY(he),(char *)SvRV(HeVAL(he)));
+		tmp->name = HeKEY(he);
+		tmp->value = (char *)SvRV(HeVAL(he));
+		he = hv_iternext(hh);
+		if(he != NULL){
+			tmp->next = (map *)malloc(MAP_SIZE);
+			if (tmp->next == NULL){
+				//erreur allocation memoire
+				return 1;
+			}
+			tmp=tmp->next;
+		}
+		else {
+			tmp->next = NULL;
+		}
+
+	}
+
+	return 1;
+}
+	
+int hash_to_maps(HV * hh,maps** m){
+	hv_iterinit(hh);
+	*m = (maps *)malloc(MAPS_SIZE);
+	maps * tmp = *m;
+	HE * he = hv_iternext(hh);
+	map *mm;
+	while (he != NULL) {
+		//fprintf(stderr,"key ===> %s \n",HeKEY(he));
+		tmp->name = HeKEY(he);
+		hash_to_map((HV *) SvRV(HeVAL(he)),&mm);
+		tmp->content = mm;
+		he = hv_iternext(hh);
+		if (he != NULL){
+			tmp->next = (maps *)malloc(MAPS_SIZE);
+			tmp= tmp->next;
+		}
+		else {
+			tmp->next = NULL;
+		}		
+	}
+	return 1;
+}
+	
+int zoo_perl_support(maps** main_conf,map* request,service* s,maps **real_inputs,maps **real_outputs){
+	maps* m=*main_conf;
+ 	maps* inputs=*real_inputs;
+	maps* outputs=*real_outputs;
+  	int res=SERVICE_FAILED;
+  	map * tmp=getMap(s->content,"serviceProvide");
+
+	char *my_argv[] = { "", tmp->value };
+	if ((my_perl = perl_alloc()) == NULL){
+		fprintf(stderr,"no memmory");
+		exit(1);
+	}
+	perl_construct( my_perl );
+	perl_parse(my_perl, xs_init, 2, my_argv, (char **)NULL);
+	perl_run(my_perl);
+	
+
+	HV* h_main_conf = (HV *)sv_2mortal((SV *)newHV());
+	HV* h_real_inputs = (HV *)sv_2mortal((SV *)newHV());
+	HV* h_real_outputs = (HV *)sv_2mortal((SV *)newHV());
+	maps_to_hash(m,&h_main_conf);
+	maps_to_hash(inputs,&h_real_inputs);
+	maps_to_hash(outputs,&h_real_outputs);
+	dSP;
+    	ENTER;
+    	SAVETMPS;
+    	PUSHMARK(SP);
+	XPUSHs(sv_2mortal(newRV_inc((SV *)h_main_conf)));
+	XPUSHs(sv_2mortal(newRV_inc((SV *)h_real_inputs)));
+	XPUSHs(sv_2mortal(newRV_inc((SV *)h_real_outputs)));
+	PUTBACK;
+	call_pv(s->name, G_SCALAR);
+	SPAGAIN;
+	res = POPi;
+	hash_to_maps(h_real_outputs,real_outputs);
+	//dumpMaps(*real_outputs);
+	PUTBACK;
+    	FREETMPS;
+    	LEAVE;
+	return SERVICE_SUCCEEDED;
+}
+
+	
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/zoo-project/zoo-kernel/service_internal_perl.h b/zoo-project/zoo-kernel/service_internal_perl.h
new file mode 100644
index 0000000..cd4901d
--- /dev/null
+++ b/zoo-project/zoo-kernel/service_internal_perl.h
@@ -0,0 +1,64 @@
+/**
+ * Author : David SAGGIORATO
+ *
+ * Copyright (c) 2009-2010 GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef ZOO_SERVICE_INTERNAL_PERL_H
+#define ZOO_SERVICE_INTERNAL_PERL_H 1
+
+#pragma once 
+
+#include "service.h"
+#include "service_internal.h"
+#include <stdio.h>
+#include <EXTERN.h>
+#include <perl.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void xs_init (pTHX);
+
+void boot_DynaLoader (pTHX_ CV*);
+
+int map_to_hash(map*, HV** );
+
+int maps_to_hash(maps *, HV ** );
+
+int hash_to_map(HV* ,map**);
+
+int hash_to_maps(HV* ,maps** );
+
+int zoo_perl_support(maps**,map*,service*,maps**,maps**);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
+
+
+
+
+
+
diff --git a/zoo-project/zoo-kernel/service_internal_php.c b/zoo-project/zoo-kernel/service_internal_php.c
new file mode 100644
index 0000000..b59d135
--- /dev/null
+++ b/zoo-project/zoo-kernel/service_internal_php.c
@@ -0,0 +1,455 @@
+/*
+ * Author : Gérald FENOY
+ *
+ * Copyright (c) 2009-2010 GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifdef WIN32
+  #define NO_FCGI_DEFINES
+#endif
+
+#ifndef ZEND_DEBUG
+  #define ZEND_DEBUG 0
+#endif  
+
+#include <sapi/embed/php_embed.h>
+#include <zend_stream.h>
+
+#include "service_internal_php.h"
+#include "response_print.h"
+
+zval *php_Array_from_maps(maps* t);
+zval*  php_Array_from_map(map*);
+maps* php_maps_from_Array(HashTable* t);
+map* php_map_from_HasTable(HashTable* t);
+
+#ifdef ZTS
+void ***tsrm_ls;
+#endif
+
+ZEND_BEGIN_MODULE_GLOBALS(zoo)
+long _SERVICE_SUCCEEDED;
+long _SERVICE_FAILED;
+ZEND_END_MODULE_GLOBALS(zoo)
+
+#ifdef ZTS
+#define ZOO_G(v) TSRMG(zoo_globals_id, zend_zoo_globals *, v)
+#else
+#define ZOO_G(v) (zoo_globals.v)
+#endif
+
+#define PHP_ZOO_VERSION "1.0"
+#define PHP_ZOO_EXTNAME "ZOO"
+
+PHP_MINIT_FUNCTION(zoo);
+PHP_MSHUTDOWN_FUNCTION(zoo);
+PHP_RINIT_FUNCTION(zoo);
+
+PHP_FUNCTION(zoo_Translate);
+PHP_FUNCTION(zoo_UpdateStatus);
+PHP_FUNCTION(zoo_SERVICE_SUCCEEDED);
+PHP_FUNCTION(zoo_SERVICE_FAILED);
+
+extern zend_module_entry zoo_module_entry;
+#define phpext_zoo_ptr &zoo_entry
+
+ZEND_DECLARE_MODULE_GLOBALS(zoo)
+
+static zend_function_entry zoo_functions[] = {
+  PHP_FE(zoo_Translate, NULL)
+  PHP_FE(zoo_UpdateStatus, NULL)
+  PHP_FE(zoo_SERVICE_SUCCEEDED, NULL)
+  PHP_FE(zoo_SERVICE_FAILED, NULL)
+  {NULL, NULL, NULL}
+};
+
+zend_module_entry zoo_module_entry = {
+#if ZEND_MODULE_API_NO >= 20010901
+    STANDARD_MODULE_HEADER,
+#endif
+    PHP_ZOO_EXTNAME,
+    zoo_functions,
+    PHP_MINIT(zoo),
+    PHP_MSHUTDOWN(zoo),
+    PHP_RINIT(zoo),
+    NULL,
+    NULL,
+#if ZEND_MODULE_API_NO >= 20010901
+    PHP_ZOO_VERSION,
+#endif
+    STANDARD_MODULE_PROPERTIES
+};
+
+ZEND_GET_MODULE(zoo)
+
+PHP_INI_BEGIN()
+PHP_INI_END()
+
+static void
+php_zoo_init_globals(zend_zoo_globals *zoo_globals)
+{
+  zoo_globals->_SERVICE_SUCCEEDED=3;
+  zoo_globals->_SERVICE_FAILED=4;
+}
+
+PHP_RINIT_FUNCTION(zoo)
+{
+  return SUCCESS;
+}
+
+PHP_MINIT_FUNCTION(zoo)
+{
+  ZEND_INIT_MODULE_GLOBALS(zoo, php_zoo_init_globals,NULL);
+  REGISTER_INI_ENTRIES();
+  return SUCCESS;
+}
+
+PHP_MSHUTDOWN_FUNCTION(zoo)
+{
+  UNREGISTER_INI_ENTRIES();
+  return SUCCESS;
+}
+
+PHP_FUNCTION(zoo_Translate)
+{
+  char *value;
+  int value_len;
+  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &value, &value_len) == FAILURE) {
+    RETURN_NULL();
+  }
+  RETURN_STRING(_ss(value), 1);
+}
+
+PHP_FUNCTION(zoo_UpdateStatus)
+{
+  zval *arr;
+  char *message;
+  int message_len;
+  long pourcent;
+  char *status=(char*)malloc(4*sizeof(char));
+  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "asl", &arr, &message, &message_len,&pourcent) == FAILURE) {
+    RETURN_NULL();
+  }
+  HashTable* t=HASH_OF(arr);
+  maps* conf=php_maps_from_Array(t);
+  setMapInMaps(conf,"lenv","message",message);
+  sprintf(status,"%d",pourcent);
+  setMapInMaps(conf,"lenv","status",status);
+  _updateStatus(conf);
+  freeMaps(&conf);
+  free(conf);
+  free(status);
+  RETURN_NULL();
+}
+
+PHP_FUNCTION(zoo_SERVICE_SUCCEEDED)
+{
+  RETURN_LONG(ZOO_G(_SERVICE_SUCCEEDED));
+}
+
+PHP_FUNCTION(zoo_SERVICE_FAILED)
+{
+  RETURN_LONG(ZOO_G(_SERVICE_FAILED));
+}
+
+/**
+ * Load a PHP script then run the function corresponding to the service by
+ * passing the conf, inputs and outputs parameters by reference.
+ *
+ * @param main_conf the conf maps containing the main.cfg settings
+ * @param request the map containing the HTTP request
+ * @param s the service structure
+ * @param real_inputs the maps containing the inputs
+ * @param real_outputs the maps containing the outputs
+ */
+int zoo_php_support(maps** main_conf,map* request,service* s,maps **real_inputs,maps **real_outputs){	
+  maps* m=*main_conf;
+  maps* inputs=*real_inputs;
+  maps* outputs=*real_outputs;
+  char ntmp[1024];
+  getcwd(ntmp,1024);
+    
+  map* libp = getMapFromMaps(m, "main", "libPath");  
+  int res=SERVICE_FAILED;
+
+  map* tmp=getMap(s->content,"serviceProvider");
+  if (tmp == NULL || tmp->value == NULL) {
+	  return errorException(m, "Missing serviceProvider (library file)", "NoApplicableCode", NULL);
+  }
+  
+  map* cwd=getMapFromMaps(m,"lenv","cwd");
+#ifdef IGNORE_METAPATH
+  map* mp = createMap("metapath", "");
+#else  
+  map* mp = getMap(request, "metapath");
+#endif
+  char *scriptName;
+  
+  if (libp != NULL && libp->value != NULL) {
+	scriptName = (char*) malloc((strlen(libp->value) + strlen(tmp->value) + 2)*sizeof(char));
+    sprintf (scriptName, "%s/%s", libp->value, tmp->value);	
+  }
+  else {	
+    if(mp!=NULL && strlen(mp->value)>0){
+      scriptName=(char*)malloc((strlen(cwd->value)+strlen(mp->value)+strlen(tmp->value)+3)*sizeof(char));
+      sprintf(scriptName,"%s/%s/%s",cwd->value,mp->value,tmp->value);
+    }else{
+      scriptName=(char*)malloc((strlen(cwd->value)+strlen(tmp->value)+2)*sizeof(char));
+      sprintf(scriptName,"%s/%s",cwd->value,tmp->value);
+    }
+  } 
+  zend_file_handle iscript;
+  iscript.type=ZEND_HANDLE_FD;
+  iscript.opened_path=NULL;
+  iscript.filename=tmp->value;
+  iscript.free_filename=0;
+  FILE* temp=fopen(scriptName,"rb");
+  if(temp==NULL){
+    char tmp1[1024];
+    sprintf(tmp1,_("Unable to load the PHP file %s"),tmp->value);
+    free(scriptName);
+    return errorException(m,tmp1,"NoApplicableCode",NULL);
+  }
+  iscript.handle.fd=fileno(temp);
+
+  php_embed_init(0,NULL PTSRMLS_CC);
+   
+  zend_try {
+    zend_startup_module(&zoo_module_entry);
+    php_execute_script(&iscript TSRMLS_CC);
+    zval *iargs[3];
+    zval iret, ifunc,ifile;
+      
+    ZVAL_STRING(&ifunc, s->name, 0);
+    iargs[0] = php_Array_from_maps(*main_conf);
+    iargs[1] = php_Array_from_maps(*real_inputs);
+    iargs[2] = php_Array_from_maps(*real_outputs);
+      
+    if((res=call_user_function(EG(function_table), NULL, &ifunc, &iret, 3, iargs TSRMLS_CC))==SUCCESS){
+      
+      HashTable* t=HASH_OF(iargs[2]);
+      HashTable* t1=HASH_OF(iargs[0]);
+      freeMaps(real_outputs);
+      free(*real_outputs);
+      freeMaps(main_conf);
+      free(*main_conf);
+      *real_outputs=php_maps_from_Array(t);
+      *main_conf=php_maps_from_Array(t1);
+
+      res=Z_LVAL(iret);
+    }else{
+      free(scriptName);
+      fclose(temp);
+      return errorException(m,"Unable to process.","NoApplicableCode",NULL);;
+    }
+  } zend_catch { 
+    free(scriptName);
+    fclose(temp);
+    return errorException(m,"Unable to process.","NoApplicableCode",NULL);;
+  } zend_end_try();
+  free(scriptName);
+  fclose(temp);
+  php_embed_shutdown(TSRMLS_C);
+
+  return res;
+}
+
+/**
+ * Convert a maps to a php Array
+ *
+ * @param t the maps to convert
+ * @return the php Array
+ */
+zval *php_Array_from_maps(maps* t){
+  zval *mapArray;
+  zval *mapArrayTmp;
+  maps* tmp=t;
+  int tres=0;
+  MAKE_STD_ZVAL(mapArray);
+  tres=array_init(mapArray);
+  while(tmp!=NULL){
+    add_assoc_zval(mapArray,tmp->name,php_Array_from_map(tmp->content));
+    tmp=tmp->next;
+  }
+  return mapArray;
+}
+
+/**
+ * Convert a map to a php Array
+ *
+ * @param t the map to convert
+ * @return the php Array
+ */
+zval *php_Array_from_map(map* t){
+  zval *mapArray;
+  zval *mapArrayTmp;
+  map* tmp=t;
+  int tres=0;
+  MAKE_STD_ZVAL(mapArray);
+  tres=array_init(mapArray);
+  while(tmp!=NULL){
+    map* sMap=getMapArray(tmp,"size",0);    
+	if(strncmp(tmp->name,"value",5)==0 && sMap!=NULL && tmp->value != NULL){
+      tres=add_assoc_stringl(mapArray,tmp->name,tmp->value,atoi(sMap->value),1);
+	} 
+	else if (tmp->value != NULL) {
+      tres=add_assoc_string(mapArray,tmp->name,tmp->value,1);
+	}
+    tmp=tmp->next;
+  }
+  return mapArray;
+}
+
+/**
+ * Convert a php Array to a maps
+ *
+ * @param t the php Array to convert
+ * @return the created maps
+ */
+maps* php_maps_from_Array(HashTable *t){
+  maps* final_res=NULL;
+  maps* cursor=final_res;
+  char key[1024];
+  for(zend_hash_internal_pointer_reset(t); 
+      zend_hash_has_more_elements(t) == SUCCESS; 
+      zend_hash_move_forward(t)) { 
+    char *key; 
+    uint keylen; 
+    ulong idx; 
+    int type; 
+    zval **ppzval, tmpcopy; 
+    type = zend_hash_get_current_key_ex(t, &key, &keylen, &idx, 0, NULL); 
+    if (zend_hash_get_current_data(t, (void**)&ppzval) == FAILURE) { 
+      /**
+       * Should never actually fail since the key is known to exist.
+       */
+      continue; 
+    }
+    /**
+     * Duplicate the zval so that * the orignal’s contents are not destroyed
+     */
+    tmpcopy = **ppzval;
+#ifdef DEBUG
+    fprintf(stderr,"key : %s\n",key);
+#endif
+    zval_copy_ctor(&tmpcopy); 
+#ifdef DEBUG
+    fprintf(stderr,"key : %s\n",key);
+#endif
+    /**
+     * Reset refcount & Convert
+     */
+    INIT_PZVAL(&tmpcopy); 
+    //convert_to_string(&tmpcopy); 
+    if (type == HASH_KEY_IS_STRING) { 
+      /**
+       * String Key / Associative
+       */
+      cursor=(maps*)malloc(MAPS_SIZE);
+      cursor->name=strdup(key);
+    }
+#ifdef DEBUG	
+    fprintf(stderr,"key : %s\n",key);
+#endif	
+    HashTable* t=HASH_OF(*ppzval);
+#ifdef DEBUG
+    fprintf(stderr,"key : %s\n",key);
+#endif
+    cursor->content=php_map_from_HasTable(t);
+    cursor->next=NULL;
+    if(final_res==NULL)
+      final_res=cursor;
+    else{
+      addMapsToMaps(&final_res,cursor);
+      freeMaps(&cursor);
+      free(cursor);
+    }
+#ifdef DEBUG
+    fprintf(stderr,"key : %s\n",key);
+#endif
+    /**
+     * Toss out old copy
+     */
+    zval_dtor(&tmpcopy);
+  }
+  return final_res;
+}
+
+/**
+ * Convert a php Array to a map
+ *
+ * @param t the php Array to convert
+ * @return the created map
+ */
+map* php_map_from_HasTable(HashTable* t){
+#ifdef DEBUG
+  fprintf(stderr,"mapsFromPHPArray start\n");
+#endif
+  map* final_res=(map*)malloc(MAP_SIZE);
+  final_res=NULL;
+  char key[1024];
+  for(zend_hash_internal_pointer_reset(t);
+      zend_hash_has_more_elements(t) == SUCCESS;
+      zend_hash_move_forward(t)) {
+    char *key;
+    uint keylen;
+    ulong idx;
+    int type;
+    int len;
+    zval **ppzval, tmpcopy;
+    type = zend_hash_get_current_key_ex(t, &key, &keylen, &idx, 0, NULL); 
+    if (zend_hash_get_current_data(t, (void**)&ppzval) == FAILURE) { 
+      /* Should never actually fail * since the key is known to exist. */ 
+      continue; 
+    }
+    /**
+     * Duplicate the zval so that * the orignal’s contents are not destroyed 
+     */ 
+    tmpcopy = **ppzval; 
+    zval_copy_ctor(&tmpcopy); 
+    /**
+     * Reset refcount & Convert 
+     */ 
+    INIT_PZVAL(&tmpcopy); 
+    convert_to_string(&tmpcopy);
+    if(strncmp(key,"value",5)==0){
+      len=Z_STRLEN_P(&tmpcopy);
+      addToMapWithSize(final_res,key,Z_STRVAL_P(&tmpcopy),len);
+    }
+    else{
+      if(final_res==NULL){
+#ifdef DEBUG
+	fprintf(stderr,"%s => %s\n",key,Z_STRVAL(tmpcopy));
+#endif
+	final_res=createMap(key,Z_STRVAL(tmpcopy));
+      }
+      else{
+#ifdef DEBUG
+	fprintf(stderr,"%s => %s\n",key,Z_STRVAL(tmpcopy));
+#endif
+	addToMap(final_res,key,Z_STRVAL(tmpcopy));
+      }
+    }
+    /* Toss out old copy */ 
+    zval_dtor(&tmpcopy); 
+  }
+  return final_res;
+}
diff --git a/zoo-project/zoo-kernel/service_internal_php.h b/zoo-project/zoo-kernel/service_internal_php.h
new file mode 100644
index 0000000..699d084
--- /dev/null
+++ b/zoo-project/zoo-kernel/service_internal_php.h
@@ -0,0 +1,43 @@
+/*
+ * Author : Gérald FENOY
+ *
+ * Copyright (c) 2009-2010 GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef ZOO_SERVICE_INTERNAL_PHP_H
+#define ZOO_SERVICE_INTERNAL_PHP_H 1
+
+#pragma once
+
+#include "service.h"
+#include "service_internal.h"
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+  int zoo_php_support(maps**,map*,service*,maps**,maps**);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/zoo-project/zoo-kernel/service_internal_python.c b/zoo-project/zoo-kernel/service_internal_python.c
new file mode 100644
index 0000000..38a0e70
--- /dev/null
+++ b/zoo-project/zoo-kernel/service_internal_python.c
@@ -0,0 +1,686 @@
+/*
+ * Author : Gérald FENOY
+ *
+ * Copyright (c) 2009-2014 GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "service_internal_python.h"
+
+/**
+ * The state for the zoo Python module
+ */
+struct module_state {
+   PyObject *error;
+};
+
+#if PY_MAJOR_VERSION >= 3
+#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
+#define PyInt_FromLong PyLong_FromLong
+#define PyInt_AsLong PyLong_AsLong
+#define PyString_FromString PyUnicode_FromString
+#define PyString_FromStringAndSize PyUnicode_FromStringAndSize
+#define PyString_Check PyUnicode_Check
+#define	PyString_AsString _PyUnicode_AsString
+#define	PyString_Size PyUnicode_GetSize
+#else
+#define GETSTATE(m) (&_state)
+static struct module_state _state;
+#endif
+
+/**
+ * The exception for the zoo Python module
+ */
+static PyObject* ZooError;
+
+/**
+ * Function definitions for the zoo Python Module
+ *
+ * Define the following functions available from a service loaded and running
+ * from the ZOO-Kernel Python environment:
+ *  - "_" corresponding to the PythonTranslate function
+ *  - "updte_status" corresponding to the PythonUpdateStatus function
+ * @see PythonTranslate, PythonUpdateStatus
+ */
+PyMethodDef zooMethods[] = {
+  {"_", PythonTranslate, METH_VARARGS, "Translate a string using the zoo-services textdomain."},
+  {"update_status", PythonUpdateStatus, METH_VARARGS, "Update status percentage of a running process."},
+  {NULL, NULL, 0, NULL} /* tempt not the blade, all fear the sentinel */
+};
+
+#if PY_MAJOR_VERSION >= 3
+
+static int myextension_traverse(PyObject *m, visitproc visit, void *arg) {
+  Py_VISIT(GETSTATE(m)->error);
+  return 0;
+}
+
+static int myextension_clear(PyObject *m) {
+  Py_CLEAR(GETSTATE(m)->error);
+  return 0;
+}
+
+static struct PyModuleDef moduledef = {
+  PyModuleDef_HEAD_INIT,
+  "zoo",
+  NULL,
+  sizeof(struct module_state),
+  zooMethods,
+  NULL,
+  myextension_traverse,
+  myextension_clear,
+  NULL
+};
+#endif
+
+/**
+ * Function to create and initialize the zoo Python module
+ *
+ * @return the Python module (for Python versions < 3, nothing for version >=3)
+ */
+PyMODINIT_FUNC init_zoo(){
+  PyObject *tmp,*d;
+  PyObject *module = 
+#if PY_MAJOR_VERSION >= 3
+    PyModule_Create(&moduledef);
+#else
+    Py_InitModule("zoo", zooMethods);
+#endif
+  if (module == NULL){
+#if PY_MAJOR_VERSION >= 3
+    return NULL;
+#else
+    return;
+#endif
+  }
+
+  struct module_state *st = GETSTATE(module);
+
+  d = PyModule_GetDict(module);
+  tmp = PyInt_FromLong(3);
+  PyDict_SetItemString(d, "SERVICE_SUCCEEDED", tmp);
+  Py_DECREF(tmp);
+
+  tmp = PyInt_FromLong(4);
+  PyDict_SetItemString(d, "SERVICE_FAILED", tmp);
+  Py_DECREF(tmp);
+
+  tmp = PyString_FromString(ZOO_VERSION);
+  PyDict_SetItemString(d, "VERSION", tmp);
+  Py_DECREF(tmp);
+
+  ZooError = PyErr_NewException((char*)"zoo.error", NULL, NULL);
+  Py_INCREF(ZooError);
+  PyModule_AddObject(module, "error", ZooError);
+#if PY_MAJOR_VERSION >= 3
+  return module;
+#endif
+}
+
+/**
+ * Load a Python module then run the function corresponding to the service
+ * by passing the conf, inputs and outputs parameters by reference. 
+ *
+ * @param main_conf the conf maps containing the main.cfg settings
+ * @param request the map containing the HTTP request
+ * @param s the service structure
+ * @param real_inputs the maps containing the inputs
+ * @param real_outputs the maps containing the outputs
+ */
+int zoo_python_support(maps** main_conf,map* request,service* s,maps **real_inputs,maps **real_outputs){
+  char *pythonpath;
+  char *python_path;
+  maps* m=*main_conf;
+  maps* inputs=*real_inputs;
+  maps* outputs=*real_outputs;
+  map* tmp0=getMapFromMaps(*main_conf,"lenv","cwd");
+  char *ntmp=tmp0->value;
+  map* tmp=NULL;
+  int hasToClean=0;
+  tmp=getMapFromMaps(*main_conf,"env","PYTHONPATH");
+#ifdef DEBUG
+  fprintf(stderr,"PYTHON SUPPORT \n");
+#endif
+  if(tmp!=NULL){
+#ifdef DEBUG
+    fprintf(stderr,"PYTHON SUPPORT (%i)\n",strlen(tmp->value));
+#endif
+    python_path=(char*)malloc((strlen(tmp->value))*sizeof(char));
+    sprintf(python_path,"%s",tmp->value);
+    hasToClean=1;
+  }
+  else{
+    python_path=(char*)".";
+  }
+  tmp=NULL;
+  tmp=getMap(request,"metapath");
+  if(tmp!=NULL && strcmp(tmp->value,"")!=0){
+    pythonpath=(char*)malloc((4+strlen(python_path)+strlen(ntmp)+strlen(tmp->value))*sizeof(char));
+#ifdef WIN32
+  sprintf(pythonpath,"%s/%s/;%s",ntmp,tmp->value,python_path);
+#else
+  sprintf(pythonpath,"%s/%s/:%s",ntmp,tmp->value,python_path);
+#endif
+  }
+  else{
+    pythonpath=(char*)malloc((2+strlen(python_path)+strlen(ntmp))*sizeof(char));
+#ifdef WIN32
+    sprintf(pythonpath,"%s;%s",ntmp,python_path);
+#else
+    sprintf(pythonpath,"%s:%s",ntmp,python_path);
+#endif
+  }
+#ifdef DEBUG
+    fprintf(stderr,"PYTHONPATH=%s\n",pythonpath);
+#endif
+#ifndef WIN32
+  setenv("PYTHONPATH",pythonpath,1);
+#else
+  SetEnvironmentVariable("PYTHONPATH",pythonpath);
+  char* toto=(char*)malloc((strlen(pythonpath)+12)*sizeof(char));
+  sprintf(toto,"PYTHONPATH=%s",pythonpath);
+  putenv(toto);
+  free(toto);
+#endif
+  if(hasToClean>0)
+    free(python_path);
+  free(pythonpath);
+
+  PyThreadState *mainstate;
+#if PY_MAJOR_VERSION >= 3
+  PyImport_AppendInittab("zoo", init_zoo);
+#else
+  PyEval_InitThreads();
+#endif
+  Py_Initialize();
+#if PY_MAJOR_VERSION >= 3
+  PyEval_InitThreads();
+  PyImport_ImportModule("zoo");
+#else
+  init_zoo();
+#endif
+  mainstate = PyThreadState_Swap(NULL);
+  PyEval_ReleaseLock();
+  PyGILState_STATE gstate;
+  gstate = PyGILState_Ensure();
+  PyObject *pName, *pModule, *pFunc;
+  tmp=getMap(s->content,"serviceProvider");
+  map* mp=getMap(request,"metapath");
+  if(tmp!=NULL){
+    if(mp!=NULL && strlen(mp->value)>0){
+      char *mps=zStrdup(mp->value);
+      int i,len=strlen(mps);
+      int j=0;
+      for(i=0;i<len;i++){
+	if(mps[i]=='/'){
+	  mps[i]='.';
+	}
+      }
+      char *mn=(char*)malloc((strlen(mps)+strlen(tmp->value)+2)*sizeof(char));
+      sprintf(mn,"%s.%s",mps,tmp->value);
+      pName = PyString_FromString(mn);
+      free(mn);
+      free(mps);
+    }
+    else{
+      pName = PyString_FromString(tmp->value);
+    }
+  }
+  else{
+    errorException (m, "Unable to parse serviceProvider please check your zcfg file.", "NoApplicableCode", NULL);
+    exit(-1);
+  }
+  pModule = PyImport_Import(pName);
+  int res=SERVICE_FAILED;
+  if (pModule != NULL) {
+    pFunc=PyObject_GetAttrString(pModule,s->name);
+    if (pFunc && PyCallable_Check(pFunc)){
+      PyObject *pValue;
+      PyDictObject* arg1=PyDict_FromMaps(m);
+      PyDictObject* arg2=PyDict_FromMaps(inputs);
+      PyDictObject* arg3=PyDict_FromMaps(outputs);
+      PyObject *pArgs=PyTuple_New(3);
+      if (!pArgs)
+	return -1;
+      PyTuple_SetItem(pArgs, 0, (PyObject *)arg1);
+      PyTuple_SetItem(pArgs, 1, (PyObject *)arg2);
+      PyTuple_SetItem(pArgs, 2, (PyObject *)arg3);
+      pValue = PyObject_CallObject(pFunc, pArgs);
+      if (pValue != NULL) {
+	res=PyInt_AsLong(pValue);
+	freeMaps(real_outputs);
+	free(*real_outputs);
+	freeMaps(main_conf);
+	free(*main_conf);
+	*main_conf=mapsFromPyDict(arg1);
+	*real_outputs=mapsFromPyDict(arg3);
+#ifdef DEBUG
+	fprintf(stderr,"Result of call: %i\n", PyInt_AsLong(pValue));
+	dumpMaps(inputs);
+	dumpMaps(*real_outputs);
+#endif
+      }else{	  
+	PythonZooReport(m,tmp->value,0);
+	res=-1;
+      }
+    }
+    else{
+      char tmpS[1024];
+      sprintf(tmpS, "Cannot find the %s function in the %s file.\n", s->name, tmp->value);
+      errorException(m,tmpS,"NoApplicableCode",NULL);
+      res=-1;
+    }
+  } else{
+    PythonZooReport(m,tmp->value,1);
+    res=-1;
+  } 
+#if PY_MAJOR_VERSION < 3
+  PyGILState_Release(gstate);
+  PyEval_AcquireLock();
+#endif
+  PyThreadState_Swap(mainstate);
+  Py_Finalize();
+  return res;
+}
+
+/**
+ * Report Python error which may occur on loading the Python module or at 
+ * runtime.
+ * 
+ * @param m the conf maps containing the main.cfg settings
+ * @param module the service name
+ * @param load 1 if the Python module was not loaded yet
+ */
+void PythonZooReport(maps* m,const char* module,int load){
+  PyObject *pName, *pModule, *pFunc;
+  PyObject *ptype, *pvalue, *ptraceback,*pValue,*pArgs;
+  PyErr_Fetch(&ptype, &pvalue, &ptraceback);
+  char *pStrErrorMessage = PyString_AsString(pvalue);
+  char *tmp0=_("Python module %s cannot be loaded. Message: %s\n");
+  
+  PyObject *trace=PyObject_Str(pvalue);
+  char *pbt=NULL;
+  if(PyString_Check(trace)){
+    pbt=(char*)malloc((7+strlen(PyString_AsString(trace))+1)*sizeof(char));
+    sprintf(pbt,"TRACE: %s",PyString_AsString(trace));
+  }
+  else
+    fprintf(stderr,"EMPTY TRACE ?");
+  
+  trace=NULL;
+  
+  trace=PyObject_Str(ptype);
+  if(PyString_Check(trace)){
+    char *tpbt=zStrdup(pbt);
+    if(pbt!=NULL)
+      free(pbt);
+    pbt=(char*)malloc((1+strlen(tpbt)+strlen(PyString_AsString(trace))+1)*sizeof(char));
+    sprintf(pbt,"%s\n%s",tpbt,PyString_AsString(trace));
+    free(tpbt);
+  }
+  else
+    fprintf(stderr,"EMPTY TRACE ?");
+  
+  if(ptraceback!=NULL){
+    char *tpbt=zStrdup(pbt);
+    pName = PyString_FromString("traceback");
+    pModule = PyImport_Import(pName);
+    pArgs = PyTuple_New(1);
+    PyTuple_SetItem(pArgs, 0, ptraceback);
+    pFunc = PyObject_GetAttrString(pModule,"format_tb");
+    pValue = PyObject_CallObject(pFunc, pArgs);
+    trace=NULL;
+    trace=PyObject_Str(pValue);
+    if(PyString_Check(trace)){
+      if(pbt!=NULL)
+	free(pbt);
+      pbt=(char*)malloc((90+strlen(tpbt)+strlen(PyString_AsString(trace))+1)*sizeof(char));
+      sprintf(pbt,_("%s\nUnable to run your python process properly. Please check the following messages : %s"),tpbt,PyString_AsString(trace));
+    }
+    else{
+      if(pbt!=NULL)
+	free(pbt);
+      pbt=(char*)malloc((90+strlen(tpbt)+strlen(PyString_AsString(trace))+1)*sizeof(char));      
+      sprintf(pbt,_("%s \n Unable to run your python process properly. Unable to provide any futher informations."),tpbt);
+    }
+    free(tpbt);
+  }
+  if(load>0){
+    char *tmpS=(char*)malloc((strlen(tmp0)+strlen(module)+strlen(pbt)+1)*sizeof(char));
+    sprintf(tmpS,tmp0,module,pbt);
+    errorException(m,tmpS,"NoApplicableCode",NULL);
+    free(tmpS);
+  }else
+    errorException(m,pbt,"NoApplicableCode",NULL);
+  free(pbt);
+}
+
+/**
+ * Convert a maps to a Python dictionary
+ *
+ * @param t the maps to convert
+ * @return a new PyDictObject containing the converted maps
+ * @see PyDict_FromMap
+ * @warning make sure to free ressources returned by this function
+ */
+PyDictObject* PyDict_FromMaps(maps* t){
+  PyObject* res=PyDict_New( );
+  maps* tmp=t;
+  while(tmp!=NULL){
+    PyObject* value=(PyObject*)PyDict_FromMap(tmp->content);
+    PyObject* name=PyString_FromString(tmp->name);
+    if(PyDict_SetItem(res,name,value)<0){
+      fprintf(stderr,"Unable to set map value ...");
+      return NULL;
+    }
+    Py_DECREF(name);
+    tmp=tmp->next;
+  }  
+  return (PyDictObject*) res;
+}
+
+/**
+ * Convert a map to a Python dictionary
+ *
+ * @param t the map to convert
+ * @return a new PyDictObject containing the converted maps
+ * @warning make sure to free ressources returned by this function
+ */
+PyDictObject* PyDict_FromMap(map* t){
+  PyObject* res=PyDict_New( );
+  map* tmp=t;
+  int hasSize=0;
+  map* isArray=getMap(tmp,"isArray");
+  map* size=getMap(tmp,"size");
+  map* tmap=getMapType(tmp);
+  while(tmp!=NULL){
+    PyObject* name=PyString_FromString(tmp->name);
+    if(strcasecmp(tmp->name,"value")==0) {
+      if(isArray!=NULL){
+	map* len=getMap(tmp,"length");
+	int cnt=atoi(len->value);
+	PyObject* value=PyList_New(cnt);
+	PyObject* mvalue=PyList_New(cnt);
+	PyObject* svalue=PyList_New(cnt);
+
+	for(int i=0;i<cnt;i++){
+	  
+	  map* vMap=getMapArray(tmp,"value",i);	    
+	  map* sMap=getMapArray(tmp,"size",i);
+
+	  if(vMap!=NULL){
+	    
+	    PyObject* lvalue;
+	    PyObject* lsvalue;
+	    if(sMap==NULL){
+	      lvalue=PyString_FromString(vMap->value);
+	      lsvalue=Py_None;
+	    }
+	    else{    
+	      lvalue=PyString_FromStringAndSize(vMap->value,atoi(sMap->value));
+	      lsvalue=PyString_FromString(sMap->value);
+	      hasSize=1;
+	    }
+
+	    if(PyList_SetItem(value,i,lvalue)<0){
+	      fprintf(stderr,"Unable to set key value pair...");
+	      return NULL;
+	    } 
+	    if(PyList_SetItem(svalue,i,lsvalue)<0){
+	      fprintf(stderr,"Unable to set key value pair...");
+	      return NULL;
+	    } 
+	  }
+	  
+	  map* mMap=getMapArray(tmp,tmap->name,i);
+	  PyObject* lmvalue;
+	  if(mMap!=NULL){
+	    lmvalue=PyString_FromString(mMap->value);
+	  }else
+	    lmvalue=Py_None;
+	  
+	  if(PyList_SetItem(mvalue,i,lmvalue)<0){
+	      fprintf(stderr,"Unable to set key value pair...");
+	      return NULL;
+	  } 
+	  
+	}
+
+	if(PyDict_SetItem(res,name,value)<0){
+	  fprintf(stderr,"Unable to set key value pair...");
+	  return NULL;
+	}
+	if(PyDict_SetItem(res,PyString_FromString(tmap->name),mvalue)<0){
+	  fprintf(stderr,"Unable to set key value pair...");
+	  return NULL;
+	}
+	if(hasSize>0)
+	  if(PyDict_SetItem(res,PyString_FromString("size"),svalue)<0){
+	    fprintf(stderr,"Unable to set key value pair...");
+	    return NULL;
+	  }
+      }
+      else if(size!=NULL){
+	PyObject* value=PyString_FromStringAndSize(tmp->value,atoi(size->value));
+	if(PyDict_SetItem(res,name,value)<0){
+	  Py_DECREF(value);
+	  fprintf(stderr,"Unable to set key value pair...");
+	  return NULL;
+	}
+	Py_DECREF(value);
+      }
+      else{
+	PyObject* value=PyString_FromString(tmp->value);
+	if(PyDict_SetItem(res,name,value)<0){
+	  Py_DECREF(value);
+	  fprintf(stderr,"Unable to set key value pair...");
+	  return NULL;
+	}
+	Py_DECREF(value);
+      }
+    }
+    else{
+      if(PyDict_GetItem(res,name)==NULL){
+	PyObject* value=PyString_FromString(tmp->value);
+	if(PyDict_SetItem(res,name,value)<0){
+	  Py_DECREF(value);
+	  fprintf(stderr,"Unable to set key value pair...");
+	  return NULL;
+	}
+	Py_DECREF(value);
+      }
+    }
+    Py_DECREF(name);
+    tmp=tmp->next;
+  }
+  return (PyDictObject*) res;
+}
+
+/**
+ * Convert a Python dictionary to a maps 
+ *
+ * @param t the PyDictObject to convert
+ * @return a new maps containing the converted PyDictObject
+ * @warning make sure to free ressources returned by this function
+ */
+maps* mapsFromPyDict(PyDictObject* t){
+  maps* res=NULL;
+  maps* cursor=NULL;
+  PyObject* list=PyDict_Keys((PyObject*)t);
+  int nb=PyList_Size(list);
+  int i;
+  PyObject* key;
+  PyObject* value;
+  for(i=0;i<nb;i++){
+#ifdef DEBUG
+    fprintf(stderr,">> parsing maps %d\n",i);
+#endif
+    key=PyList_GetItem(list,i);
+    value=PyDict_GetItem((PyObject*)t,key);
+#ifdef DEBUG
+    fprintf(stderr,">> DEBUG VALUES : %s => %s\n",
+	    PyString_AsString(key),PyString_AsString(value));
+#endif
+    cursor=(maps*)malloc(MAPS_SIZE);
+    cursor->name=zStrdup(PyString_AsString(key));
+    cursor->content=mapFromPyDict((PyDictObject*)value);
+#ifdef DEBUG
+    dumpMap(cursor->content);
+#endif
+    cursor->next=NULL;
+    if(res==NULL)
+      res=dupMaps(&cursor);
+    else
+      addMapsToMaps(&res,cursor);
+    freeMap(&cursor->content);
+    free(cursor->content);
+    free(cursor);
+#ifdef DEBUG
+    dumpMaps(res);
+    fprintf(stderr,">> parsed maps %d\n",i);
+#endif
+  }
+  Py_DECREF(list);
+  return res;
+}
+
+/**
+ * Convert a Python dictionary to a map 
+ *
+ * @param t the PyDictObject to convert
+ * @return a new map containing the converted PyDictObject
+ * @warning make sure to free ressources returned by this function
+ */
+map* mapFromPyDict(PyDictObject* t){
+  map* res=NULL;
+  PyObject* list=PyDict_Keys((PyObject*)t);
+  int nb=PyList_Size(list);
+  int i;
+  PyObject* key;
+  PyObject* value;
+  for(i=0;i<nb;i++){
+    key=PyList_GetItem(list,i);
+    value=PyDict_GetItem((PyObject*)t,key);
+#ifdef DEBUG
+    fprintf(stderr,">> DEBUG VALUES : %s => %s\n",
+	    PyString_AsString(key),PyString_AsString(value));
+#endif
+    
+    if(strncmp(PyString_AsString(key),"value",5)==0){
+      char *buffer=NULL;
+      Py_ssize_t size;
+#if PY_MAJOR_VERSION >= 3
+      if(PyBytes_Check(value)){
+	size=PyBytes_Size(value);
+	buffer=PyBytes_AsString(value);
+      }
+      else
+	if(PyUnicode_Check(value) && PyUnicode_READY(value) == 0){
+	  buffer=PyUnicode_AsUTF8AndSize(value,&size);
+	}
+	else{
+	  fprintf(stderr,"Unsupported return value.");
+	  return NULL;
+	}
+#else
+      PyString_AsStringAndSize(value,&buffer,&size);
+#endif
+      addToMapWithSize(res,PyString_AsString(key),buffer,size);
+    }else{
+      char* lkey=PyString_AsString(key);
+      char* lvalue=PyString_AsString(value);
+      if(res!=NULL){
+	if(PyString_Size(value)>0)
+	  addToMap(res,lkey,lvalue);
+      }
+      else{
+	if(PyString_Size(value)>0)
+	  res=createMap(lkey,lvalue);
+      }
+    }
+  }
+  Py_DECREF(list);
+  return res;
+}
+
+/**
+ * Use the ZOO-Services messages translation function from the Python
+ * environment
+ *
+ * @param self the Python object on which we can run the method
+ * @param args the Python arguments given from the Python environment
+ * @return a new Python string containing the translated value
+ * @see _ss
+ */
+PyObject*
+PythonTranslate(PyObject* self, PyObject* args)
+{
+  char *str;
+  if (!PyArg_ParseTuple(args, "s", &str)){
+#ifdef DEBUG
+    fprintf(stderr,"Incorrect arguments to update status function");
+#endif
+    return NULL;
+  }
+  return PyString_FromString(_ss(str));
+}
+
+/**
+ * Update the ongoing status of a running service from the Python environment
+ *
+ * @param self the Python object on which we can run the method
+ * @param args the Python arguments given from the Python environment
+ * @return None to the Python environment
+ * @see _updateStatus
+ */
+PyObject*
+PythonUpdateStatus(PyObject* self, PyObject* args)
+{
+  maps* conf;
+  PyObject* confdict;
+  int istatus;
+  char* status=NULL;
+  if (!PyArg_ParseTuple(args, "O!i", &PyDict_Type, &confdict, &istatus)){
+#ifdef DEBUG
+    fprintf(stderr,"Incorrect arguments to update status function");
+#endif
+    Py_RETURN_NONE;
+  }
+  if (istatus < 0 || istatus > 100){
+     PyErr_SetString(ZooError, "Status must be a percentage.");
+     Py_RETURN_NONE;
+  }else{
+     char tmpStatus[4];
+     snprintf(tmpStatus, 4, "%i", istatus);
+     status = zStrdup(tmpStatus);
+  }
+  // create a local copy and update the lenv map
+  conf = mapsFromPyDict((PyDictObject*)confdict);
+  if(status!=NULL){
+    setMapInMaps(conf,"lenv","status",status);
+    free(status);
+  }
+  else
+    setMapInMaps(conf,"lenv","status","15");
+  _updateStatus(conf);
+  freeMaps(&conf);
+  free(conf);
+  Py_RETURN_NONE;
+}
diff --git a/zoo-project/zoo-kernel/service_internal_python.h b/zoo-project/zoo-kernel/service_internal_python.h
new file mode 100644
index 0000000..8980268
--- /dev/null
+++ b/zoo-project/zoo-kernel/service_internal_python.h
@@ -0,0 +1,52 @@
+/*
+ * Author : Gérald FENOY
+ *
+ * Copyright (c) 2009-2010 GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef ZOO_SERVICE_INTERNAL_PYTHON_H
+#define ZOO_SERVICE_INTERNAL_PYTHON_H 1
+
+#pragma once 
+
+#include "service_internal.h"
+#include "response_print.h"
+#include <Python.h>
+#include "cgic.h"
+#ifdef WIN32
+#include <windows.h>
+#include <direct.h>
+#endif
+
+PyDictObject* PyDict_FromMaps(maps* t);
+PyDictObject* PyDict_FromMap(map* t);
+
+maps* mapsFromPyDict(PyDictObject* t);
+map* mapFromPyDict(PyDictObject* t);
+
+int zoo_python_support(maps**,map*,service*,maps**,maps**);
+
+void PythonZooReport(maps*,const char*,int);
+
+PyObject* PythonTranslate(PyObject*, PyObject*);
+PyObject* PythonUpdateStatus(PyObject*, PyObject*);
+
+#endif
diff --git a/zoo-project/zoo-kernel/service_internal_ruby.c b/zoo-project/zoo-kernel/service_internal_ruby.c
new file mode 100644
index 0000000..af2e2c3
--- /dev/null
+++ b/zoo-project/zoo-kernel/service_internal_ruby.c
@@ -0,0 +1,486 @@
+/*
+ * Author : Gérald FENOY
+ *
+ * Copyright (c) 2014 GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "service_internal_ruby.h"
+
+#if RUBY_API_VERSION_MAJOR >= 2 || RUBY_API_VERSION_MINOR == 9 
+int argc=0;
+char **argv=NULL;
+#endif
+
+/**
+ * Load a Ruby file then run the function corresponding to the service by
+ * passing the conf, inputs and outputs parameters by refernce as Ruby Hash.
+ *
+ * @param main_conf the conf maps containing the main.cfg settings
+ * @param request the map containing the HTTP request
+ * @param s the service structure
+ * @param real_inputs the maps containing the inputs
+ * @param real_outputs the maps containing the outputs
+ * @return SERVICE_SUCCEEDED or SERVICE_FAILED if the service run, -1 
+ *  if the service failed to load or throw error at runtime.
+ */
+int zoo_ruby_support(maps** main_conf,map* request,service* s,maps **real_inputs,maps **real_outputs){
+#if RUBY_API_VERSION_MAJOR >= 2 || RUBY_API_VERSION_MINOR == 9
+  ruby_sysinit(&argc,&argv);
+  RUBY_INIT_STACK;
+#endif
+  ruby_init();
+  maps* m=*main_conf;
+  maps* inputs=*real_inputs;
+  maps* outputs=*real_outputs;
+  map* tmp0=getMapFromMaps(*main_conf,"lenv","cwd");
+  char *ntmp=tmp0->value;
+  map* tmp=NULL;
+  ruby_init_loadpath();
+  ruby_script("ZOO_EMBEDDED_ENV");
+  
+  VALUE klass=rb_define_module("Zoo");
+  rb_define_const(klass,"SERVICE_SUCCEEDED",INT2FIX(3));
+  rb_define_const(klass,"SERVICE_FAILED",INT2FIX(4));
+  typedef VALUE (*HOOK)(...);
+  rb_define_module_function(klass,"Translate",reinterpret_cast<HOOK>(RubyTranslate),-1);
+  rb_define_module_function(klass,"UpdateStatus",reinterpret_cast<HOOK>(RubyUpdateStatus),-1);
+
+  int error = 0;
+		
+  ID rFunc=Qnil;
+  tmp=getMap(s->content,"serviceProvider");
+  if(tmp!=NULL){
+#if RUBY_VERSION_MINOR == 8
+    const char* script = ruby_sourcefile = rb_source_filename(tmp->value);
+    rb_protect(LoadWrap, reinterpret_cast<VALUE>(script), &error);
+#else
+    rb_load_protect(rb_str_new2(tmp->value), 0, &error);
+#endif
+    if(error) {
+      ruby_trace_error(m);
+      return -1;
+    }
+#if RUBY_VERSION_MINOR == 8
+    ruby_exec();
+#else
+    ruby_exec_node(NULL);
+#endif
+  }
+  else{
+    map* err=createMap("text","Unable to parse serviceProvider please check your zcfg file.");
+    addToMap(err,"code","NoApplicableCode");
+    printExceptionReportResponse(m,err);
+    return -1;
+  }
+  int res=SERVICE_FAILED;
+  rFunc=rb_intern(s->name);
+  if(rFunc!=Qnil){
+    VALUE arg1=RubyHash_FromMaps(m);
+    VALUE arg2=RubyHash_FromMaps(inputs);
+    VALUE arg3=RubyHash_FromMaps(outputs);
+    VALUE rArgs[3]={arg1,arg2,arg3};
+    if (!rArgs)
+      return -1;
+    struct my_callback data;
+    data.obj=Qnil;
+    data.method_id=rFunc;
+    data.nargs=3;
+    data.args[0]=rArgs[0];
+    data.args[1]=rArgs[1];
+    data.args[2]=rArgs[2];
+    typedef VALUE (*HOOK)(VALUE);
+    VALUE tres=rb_protect(reinterpret_cast<HOOK>(FunCallWrap),(VALUE)(&data),&error);
+    if (TYPE(tres) == T_FIXNUM) {
+      res=FIX2INT(tres);
+      freeMaps(real_outputs);
+      free(*real_outputs);
+      freeMaps(main_conf);
+      free(*main_conf);
+      *main_conf=mapsFromRubyHash(arg1);
+      *real_outputs=mapsFromRubyHash(arg3);
+#ifdef DEBUG
+      dumpMaps(*main_conf);
+      dumpMaps(*real_outputs);
+#endif
+    }else{
+      ruby_trace_error(m);
+      res=-1;
+    }
+  }
+  else{
+    char tmpS[1024];
+    sprintf(tmpS, "Cannot find the %s function in the %s file.\n", s->name, tmp->value);
+    map* tmps=createMap("text",tmpS);
+    printExceptionReportResponse(m,tmps);
+    res=-1;
+  }
+  ruby_finalize();
+  return res;
+}
+
+/**
+ * Load a ruby file
+ *
+ * @arg the file to load
+ * @return Qnil
+ */
+VALUE LoadWrap(VALUE arg) {
+  const char *filename = reinterpret_cast<const char*>(arg);
+  rb_load_file(filename);
+  return Qnil;
+}
+
+/**
+ * Call a ruby function with parameters
+ *
+ * @arg the callback structure
+ * @return the value returned the called ruby function
+ */
+VALUE FunCallWrap(VALUE rdata) {
+  struct my_callback* data = (struct my_callback*) rdata;
+  return rb_funcall2(data->obj,data->method_id,data->nargs,data->args);
+}
+
+/**
+ * Print the Ruby Stack Trace in an ows:ExceptionReport XML Document
+ *
+ * @param m the conf maps containing the main.cfg settings
+ * @see printExceptionReportResponse
+ */
+void ruby_trace_error(maps* m){
+#if RUBY_VERSION_MINOR == 8
+  VALUE lasterr = rb_gv_get("$!");
+#else
+  VALUE lasterr = rb_errinfo();
+  VALUE ruby_errinfo = lasterr;
+#endif
+  VALUE message = rb_obj_as_string(lasterr);
+  VALUE lklass = rb_class_path(CLASS_OF(lasterr));
+#if RUBY_VERSION_MINOR == 8
+  char *trace=(char*)malloc((strlen(RSTRING(lklass)->ptr)+strlen(RSTRING(message)->ptr)+3)*sizeof(char));
+  sprintf(trace,"%s: %s",RSTRING_PTR(lklass),RSTRING_PTR(message));
+#else
+  char *trace=(char*)malloc((strlen(RSTRING_PTR(lklass))+strlen(RSTRING_PTR(message))+3)*sizeof(char));
+  sprintf(trace,"%s: %s",RSTRING_PTR(lklass),RSTRING_PTR(message));
+#endif
+  if(!NIL_P(ruby_errinfo))
+    {
+      VALUE ary = rb_funcall(ruby_errinfo, rb_intern("backtrace"), 0);
+      int c;
+      for (c=0; c<RARRAY_LEN(ary); c++) {
+	int len=strlen(trace);
+	char *tmp0=zStrdup(trace);
+#if RUBY_VERSION_MINOR == 8
+	trace=(char *) realloc(trace,(len+strlen(RSTRING(RARRAY(ary)->ptr[c])->ptr)+2)*sizeof(char));
+	sprintf(trace,"%s\n%s",tmp0,RSTRING(RARRAY(ary)->ptr[c])->ptr);
+#else
+	trace=(char *) realloc(trace,(len+strlen(RSTRING_PTR(RARRAY_PTR(ary)[c]))+2)*sizeof(char));
+	sprintf(trace,"%s\n%s",tmp0,RSTRING_PTR(RARRAY_PTR(ary)[c]));
+#endif
+	free(tmp0);
+      }
+    }
+  map* err=createMap("text",trace);
+  addToMap(err,"code","NoApplicableCode");
+  printExceptionReportResponse(m,err);
+}
+
+/**
+ * Convert a maps to a Ruby Hash
+ *
+ * @param t the maps to convert
+ * @return a new Ruby Hash
+ */
+VALUE RubyHash_FromMaps(maps* t){
+  VALUE res=rb_hash_new();
+  maps* tmp=t;
+  while(tmp!=NULL){
+    VALUE value=RubyHash_FromMap(tmp->content);
+    VALUE name=rb_str_new2(tmp->name);
+    rb_hash_aset(res,name,value);
+    tmp=tmp->next;
+  }  
+  return res;
+}
+
+/**
+ * Push the key on the array
+ *
+ * @param key the key to push
+ * @param value not used
+ * @param ary the Array
+ * @return ST_CONTINUE
+ */
+int
+keys_i(VALUE key,VALUE value,VALUE ary)
+{
+  if (key == Qundef) return ST_CONTINUE;
+  rb_ary_push(ary, key);
+  return ST_CONTINUE;
+}
+
+/**
+ * Return the size of a Ruby Hash
+ * 
+ * @param hash the input Hash
+ */
+VALUE
+rb_hash_size(VALUE hash)
+{
+    return INT2FIX(RHASH_TBL(hash)->num_entries);
+}
+
+/**
+ * Convert a map to a Ruby Hash
+ *
+ * @param t the map to convert
+ * @return a new Ruby Hash
+ */
+VALUE RubyHash_FromMap(map* t){
+  VALUE res=rb_hash_new( );
+  map* tmp=t;
+  int hasSize=0;
+  map* isArray=getMap(tmp,"isArray");
+  map* size=getMap(tmp,"size");
+  map* tmap=getMapType(tmp);
+  while(tmp!=NULL){
+    VALUE name= rb_str_new2(tmp->name);
+    if(strcasecmp(tmp->name,"value")==0) {
+      if(isArray!=NULL){
+	map* len=getMap(tmp,"length");
+	int cnt=atoi(len->value);
+	VALUE value=rb_ary_new2(cnt);
+	VALUE mvalue=rb_ary_new2(cnt);
+	VALUE svalue=rb_ary_new2(cnt);
+
+	for(int i=0;i<cnt;i++){
+	  
+	  map* vMap=getMapArray(tmp,"value",i);	    
+	  map* sMap=getMapArray(tmp,"size",i);
+
+	  if(vMap!=NULL){
+	    
+	    VALUE lvalue;
+	    VALUE lsvalue;
+	    if(sMap==NULL){
+	      lvalue=rb_str_new2(vMap->value);
+	      lsvalue=Qnil;
+	    }
+	    else{
+	      lvalue=rb_str_new(vMap->value,atoi(sMap->value));
+	      lsvalue=rb_str_new2(sMap->value);
+	      hasSize=1;
+	    }
+
+	    rb_ary_push(value,lvalue);
+	    rb_ary_push(svalue,lsvalue);
+	  }
+	  
+	  map* mMap=getMapArray(tmp,tmap->name,i);
+
+	  VALUE lmvalue;
+	  if(mMap!=NULL){
+	    lmvalue=rb_str_new2(mMap->value);
+	  }else
+	    lmvalue=Qnil;
+	  rb_ary_push(mvalue,lmvalue);
+	  
+	}
+
+	rb_hash_aset(res, name, mvalue);
+	rb_hash_aset(res, rb_str_new2(tmap->name), mvalue);
+      
+	if(hasSize>0){
+	  VALUE lname=rb_str_new2("size");
+	  rb_hash_aset(res, lname, value);
+	}
+      }
+      else if(size!=NULL){
+	VALUE value=rb_str_new(tmp->value,atoi(size->value));
+	rb_hash_aset(res, name, value);
+      }
+      else{
+	VALUE value=rb_str_new2(tmp->value);
+	rb_hash_aset(res, name, value);
+      }
+    }
+    else{
+      VALUE value=rb_str_new2(tmp->value);
+      rb_hash_aset(res, name, value);
+    }
+    tmp=tmp->next;
+  }
+  return res;
+}
+
+/**
+ * Convert a Ruby Hash to a maps
+ *
+ * @param t the Ruby Hash to convert
+ * @return a new maps
+ */
+maps* mapsFromRubyHash(VALUE t){
+  maps* res=NULL;
+  maps* cursor=res;
+  VALUE list;
+  list = rb_ary_new();
+  typedef int (*HOOK)(...);
+  rb_hash_foreach(t, reinterpret_cast<HOOK>(keys_i), list);
+  int nb=rb_hash_size(t);
+  int i;
+  for(i=0;i<FIX2INT(nb);i++){
+    VALUE key=rb_ary_pop(list);
+    VALUE value=rb_hash_aref(t,key);
+#ifdef DEBUG
+    fprintf(stderr,">> DEBUG VALUES : %s => %s\n",
+	    StringValueCStr(key),StringValueCStr(value));
+#endif
+    cursor=(maps*)malloc(MAPS_SIZE);
+    cursor->name=StringValueCStr(key);
+    cursor->content=mapFromRubyHash(value);
+    cursor->next=NULL;
+    if(res==NULL)
+      res=dupMaps(&cursor);
+    else
+      addMapsToMaps(&res,cursor);
+    freeMap(&cursor->content);
+    free(cursor->content);
+    free(cursor);
+  }
+  return res;
+}
+
+/**
+ * Convert a Ruby Hash to a map
+ *
+ * @param t the Ruby Hash to convert
+ * @return a new map
+ */
+map* mapFromRubyHash(VALUE t){
+  map* res=NULL;
+  VALUE list;
+  list = rb_ary_new();
+  typedef int (*HOOK)(...);
+  rb_hash_foreach(t,reinterpret_cast<HOOK>(keys_i), list);
+  int nb=RHASH_TBL(t)->num_entries;
+  int i;
+  for(i=0;i<nb;i++){
+    VALUE key=rb_ary_pop(list);
+    VALUE value=rb_hash_aref(t,key);
+#ifdef DEBUG
+    fprintf(stderr,">> DEBUG VALUES : %s => %s\n",
+	    StringValueCStr(key),StringValueCStr(value));
+#endif
+    if(strcmp(StringValueCStr(key),"value")==0){
+      char *buffer=NULL;
+      int size=RSTRING_LEN(value);
+      buffer=StringValueCStr(value);
+      if(res!=NULL){
+	addToMap(res,StringValueCStr(key),"");
+      }else{
+	res=createMap(StringValueCStr(key),"");
+      }
+      map* tmpR=getMap(res,"value");
+      free(tmpR->value);
+      tmpR->value=(char*)malloc((size+1)*sizeof(char));
+      memmove(tmpR->value,buffer,size*sizeof(char));
+      tmpR->value[size]=0;
+      char sin[1024];
+      sprintf(sin,"%d",size);
+      addToMap(res,"size",sin);
+    }else{
+      if(res!=NULL){
+	addToMap(res,StringValueCStr(key),StringValueCStr(value));
+      }
+      else{
+	res=
+	  createMap(StringValueCStr(key),StringValueCStr(value));
+      }
+    }
+  }
+  return res;
+}
+
+/**
+ * Use the ZOO-Services messages translation function from the Ruby
+ * environment (ZOO-API)
+ *
+ * @param argc the number of parameters
+ * @param argv the parameter values given from the Ruby environment
+ * @param obj the Ruby object on which we run the method
+ * @return a new Ruby string containing the translated value
+ * @see _ss
+ */
+VALUE
+RubyTranslate(int argc, VALUE *argv, VALUE obj)
+{
+  return rb_str_new2(_ss(StringValueCStr(argv[0])));
+}
+
+/**
+ * Update the ongoing status of a running service from the Ruby environment
+ * (ZOO-API)
+ *
+ * @param argc the number of parameters
+ * @param argv the parameter values given from the Ruby environment
+ * @param obj the Ruby object on which we run the method
+ * @return a new Ruby string containing the translated value
+ * @see _updateStatus
+ */
+VALUE
+RubyUpdateStatus(int argc, VALUE *argv, VALUE obj)
+{
+  maps* conf;
+  VALUE confdict=argv[0];
+  int istatus=argv[1];
+  char* status;
+  if (istatus < 0 || istatus > 100){
+    fprintf(stderr,"Status must be a percentage.");
+    return Qnil;
+  }else{
+     char tmpStatus[4];
+     snprintf(tmpStatus, 4, "%i", istatus);
+     status = zStrdup(tmpStatus);
+  }
+  /* now update the map */
+  {
+    VALUE lenv = rb_hash_aref(confdict,rb_str_new2("lenv"));
+    if(TYPE(lenv)!=T_NIL){
+      VALUE valobj=rb_str_new2(status);
+      rb_hash_aset(lenv,rb_str_new2("status"),valobj);
+    }
+  }
+  conf = mapsFromRubyHash(confdict);
+  if (getMapFromMaps(conf,"lenv","status") != NULL){
+    fprintf(stderr,"STATUS RETURNED : %s\n",status);
+    if(status!=NULL){
+      setMapInMaps(conf,"lenv","status",status);
+      free(status);
+    }
+    else
+      setMapInMaps(conf,"lenv","status","15");
+    _updateStatus(conf);
+  }
+  freeMaps(&conf);
+  free(conf);
+  return Qnil;
+}
+
diff --git a/zoo-project/zoo-kernel/service_internal_ruby.h b/zoo-project/zoo-kernel/service_internal_ruby.h
new file mode 100644
index 0000000..13cf066
--- /dev/null
+++ b/zoo-project/zoo-kernel/service_internal_ruby.h
@@ -0,0 +1,78 @@
+/*
+ * Author : Gérald FENOY
+ *
+ * Copyright (c) 2014 GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef ZOO_SERVICE_INTERNAL_RUBY_H
+#define ZOO_SERVICE_INTERNAL_RUBY_H 1
+
+#pragma once 
+
+#define RUBY_GLOBAL_SETUP
+#undef NEED_STRLCAT
+#undef NEED_STRLCPY
+#include "service.h"
+#include "service_internal.h"
+#undef RUBY_EXPORT
+#undef STRCASECMP
+#undef STRNCASECMP
+#undef _
+#include <ruby.h>
+#if ZRUBY_VERSION < 2
+#include <version.h>
+#else
+#include <ruby/version.h>
+#endif
+#if RUBY_VERSION_MINOR==8
+#include <st.h>
+#else
+#include <ruby/st.h>
+#endif
+
+#define MAX_ARGS 3
+/**
+ * The Ruby method pointer
+ */
+struct my_callback {
+  VALUE obj; //!< Object used to call a method
+  ID method_id; //!< The method to call
+  int nargs; //!< The arguments number
+  VALUE args[MAX_ARGS]; //!< The arguments values
+};
+
+void ruby_trace_error(maps*);
+VALUE FunCallWrap(VALUE);
+VALUE LoadWrap(VALUE);
+
+VALUE RubyHash_FromMaps(maps*);
+VALUE RubyHash_FromMap(map*);
+
+maps* mapsFromRubyHash(VALUE);
+void createMapsFromRubyHash(maps**,VALUE);
+map* mapFromRubyHash(VALUE);
+
+int zoo_ruby_support(maps**,map*,service*,maps**,maps**);
+
+VALUE RubyTranslate(int,VALUE*,VALUE);
+VALUE RubyUpdateStatus(int,VALUE*,VALUE);
+
+#endif
diff --git a/zoo-project/zoo-kernel/service_internal_saga.c b/zoo-project/zoo-kernel/service_internal_saga.c
new file mode 100644
index 0000000..7aa8c6d
--- /dev/null
+++ b/zoo-project/zoo-kernel/service_internal_saga.c
@@ -0,0 +1,1186 @@
+/*
+ * Author : Gérald FENOY
+ *
+ * Copyright (c) 2015 GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <limits.h>
+#include <locale.h>
+#include <wx/string.h>
+#include <wx/app.h>
+#include <api_core.h>
+#include <data_manager.h>
+#include <module_library.h>
+#define _ZOO_SAGA
+#include "service_internal_saga.h"
+#include "server_internal.h"
+#include "mimetypes.h"
+
+/**
+ * Global SAGA-GIS output counter 
+ */
+int sagaOutputCounter=0;
+
+/**
+ * Observer used to access the ongoing status of a running OTB Application
+ */
+class SagaWatcher
+{
+ public:
+  static int Callback(TSG_UI_Callback_ID ID, CSG_UI_Parameter &Param_1, CSG_UI_Parameter &Param_2);
+  /** 
+   * Define the message value
+   *
+   * @param conf the maps pointer to copy
+   */
+  static void SetMessage(const char *mess)
+  {
+    FreeMessage();
+    message=zStrdup(mess);
+  }
+  /** 
+   * Free the message value
+   *
+   */
+  static void FreeMessage()
+  {
+    if(message!=NULL)
+      free(message);
+    message=NULL;
+  }
+  /** 
+   * Copy the original conf in the m_conf property
+   *
+   * @param conf the maps pointer to copy
+   */
+  void SetConf(maps **conf)
+  {
+    m_conf=dupMaps(conf);
+  }
+  /**  
+   * Get Configuration maps (m_conf)
+   * @return the m_conf property
+   */
+  const maps& GetConf()
+  {
+    return *m_conf;
+  }
+  /**  
+   * Free Configuration maps (m_Conf)
+   */
+  void FreeConf(){
+    freeMaps(&m_conf);
+    free(m_conf);
+  }
+ private:
+  /** Main conf maps */
+  static maps* m_conf;
+  /** Status */
+  static int status;
+  /** Message */
+  static char* message;
+};
+
+maps* SagaWatcher::m_conf;
+char* SagaWatcher::message=zStrdup("No message left");
+int SagaWatcher::status=1;
+
+/**
+ * The callback function called at any SAGA-GIS module step
+ *
+ * @param id a TSG_UI_Callback_ID as defined in api_core.h (line 1290)
+ * @param param1 
+ * @param param2
+ */
+int
+SagaWatcher::
+Callback(TSG_UI_Callback_ID id, CSG_UI_Parameter &param1, CSG_UI_Parameter &param2)
+{
+
+  int res = 1;
+  switch( id )
+    {
+    default:
+      return 0;
+      break;
+
+    case CALLBACK_DLG_ERROR:
+      return 1;
+      break;
+
+    case CALLBACK_DLG_PARAMETERS:
+    case CALLBACK_PROCESS_SET_OKAY:
+    case CALLBACK_DATAOBJECT_COLORS_GET:
+    case CALLBACK_DATAOBJECT_COLORS_SET:
+    case CALLBACK_DATAOBJECT_PARAMS_GET:
+    case CALLBACK_DATAOBJECT_PARAMS_SET:
+    case CALLBACK_DATAOBJECT_UPDATE:
+    case CALLBACK_DATAOBJECT_SHOW:
+    case CALLBACK_DLG_CONTINUE:
+    case CALLBACK_PROCESS_SET_READY:
+    case CALLBACK_PROCESS_GET_OKAY:
+      return res;
+      break;
+
+    case CALLBACK_PROCESS_SET_PROGRESS:
+      {
+	int cPercent= param2.Number != 0.0 ? 1 + (int)(100.0 * param1.Number / param2.Number) : 100 ;
+	if( cPercent != status ){
+	  status=cPercent;
+	}else
+	  return res;
+      }
+      break;
+
+    case CALLBACK_PROCESS_SET_TEXT:
+      SetMessage(param1.String.b_str());
+      break;
+
+    case CALLBACK_MESSAGE_ADD:
+      SetMessage(param1.String.b_str());
+      break;
+
+    case CALLBACK_MESSAGE_ADD_ERROR:
+      SetMessage(param1.String.b_str());
+      break;
+
+    case CALLBACK_MESSAGE_ADD_EXECUTION:
+      SetMessage(param1.String.b_str());
+      break;
+
+    case CALLBACK_DLG_MESSAGE:
+      SetMessage((param2.String + ": " + param1.String).b_str());
+      break;
+
+    case CALLBACK_DATAOBJECT_ADD:
+      if(SG_Get_Data_Manager().Add((CSG_Data_Object *)param1.Pointer))
+	res = 1 ;
+      else
+	res = 0;
+      return res;
+      break;
+
+    }
+  updateStatus(m_conf,status,message);
+  return( res );
+}
+
+TSG_PFNC_UI_Callback Get_Callback (SagaWatcher watcher){
+  return( &(watcher.Callback) );
+}
+
+
+/**
+ * Get the default file extension for SAGA-GIS parameter type.
+ * Extensions are the following:
+ *  - sgrd for grid and data_object
+ *  - shp for shapes and tin
+ *  - csv for tables
+ *  - spc for points
+ *
+ * @param param a SAGA-GIS Parameter
+ */ 
+const char* sagaGetDefaultExt(CSG_Parameter* param){
+  if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("grid"))
+     || CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("data_object"))){
+    return "sgrd";
+  }
+  else if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("shapes")) ||
+	  CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("tin"))){
+    return "shp";
+  }
+  else if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("table"))){
+    return "csv";
+  }
+  else if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("points"))){
+    return "spc";
+  }
+  return "unknown";
+}
+
+/**
+ * Load a datasource in the SAGA-GIS Data Manager.
+ *
+ * @param param a SAGA-GIS Parameter
+ * @param arg the arguments map passed to a SAGA-GIS module
+ * @return false on failure, true in case of success
+ */
+bool sagaLoadInput(CSG_Parameter* param,map* arg){
+  if(!param->is_Input() || !param->is_Enabled()){
+    return true;
+  }
+  map* carg=getMap(arg,CSG_String(param->Get_Identifier()).b_str());
+  if(carg!=NULL){
+    wxString fileName(carg->value);
+    if(param->is_DataObject()){
+      // In case it there is a single datasource
+      if(!SG_Get_Data_Manager().Find(&fileName) && !SG_Get_Data_Manager().Add(&fileName) && !param->is_Optional() ){
+	return false;
+      }
+      return( param->Set_Value(SG_Get_Data_Manager().Find(&fileName)) );
+    }
+    else
+      if(param->is_DataObject_List()){
+	// In case there are multiple datasources
+	param->asList()->Del_Items();
+	wxString fileNames(fileName);
+	while( fileNames.Length() > 0 ){
+	  fileName = fileNames.BeforeFirst(';').Trim(false);
+	  fileNames = fileNames.AfterFirst (';');	    
+	  if( !SG_Get_Data_Manager().Find(&fileName) ){
+	    SG_Get_Data_Manager().Add(&fileName);
+	  }
+	  param->asList()->Add_Item(SG_Get_Data_Manager().Find(&fileName));
+	}
+      }
+  }
+  return true;
+}
+
+/**
+ * Extract all SAGA-GIS parameters from a parameters list and set its values to
+ * the one defined in the map.
+ *
+ * @parap params the parameters list
+ * @parap argument the argument map containing the value to use
+ * @return true in success, false in other case
+ */
+bool sagaSetParameters(CSG_Parameters *params,map* argument){
+
+  int pc=params->Get_Count();
+  params->Restore_Defaults();
+
+  for(int k=0;k<pc;k++){
+    CSG_Parameter * param=params->Get_Parameter(k);
+    if( param->is_Output() ){
+      map* omap=getMap(argument,CSG_String(param->Get_Identifier()).b_str());
+      if( param->is_DataObject() && param->is_Optional() && !param->asDataObject() && omap!=NULL){
+	param->Set_Value(DATAOBJECT_CREATE);
+      }
+    }
+    else
+      if( param->is_Option() && !param->is_Information() ){
+	map* inmap=getMap(argument,CSG_String(param->Get_Identifier()).b_str());
+	if(inmap!=NULL){
+	    switch( param->Get_Type() ){
+	    case PARAMETER_TYPE_Bool:
+	      if(strncasecmp(inmap->value,"true",4)==0 || strncasecmp(inmap->value,"1",1)==0){
+		param->Set_Value(1);
+	      }else
+		param->Set_Value(0);
+	      break;
+	    case PARAMETER_TYPE_Parameters:
+	      // TODO: nested inputs gesture
+	      break;
+	    case PARAMETER_TYPE_Int:
+	      param->Set_Value((int)strtol(inmap->value,NULL,10));
+	      break;
+	    case PARAMETER_TYPE_Double:
+	    case PARAMETER_TYPE_Degree:
+	      param->Set_Value((double)strtod(inmap->value,NULL));
+	      break;
+	    case PARAMETER_TYPE_String:
+	      param->Set_Value(CSG_String(inmap->value));
+	      break;
+	    case PARAMETER_TYPE_FilePath:
+	      param->Set_Value(CSG_String(inmap->value));
+	      break;
+	    case PARAMETER_TYPE_FixedTable:
+	      {
+		CSG_Table Table(inmap->value);
+		param->asTable()->Assign_Values(&Table);
+	      }
+	      break;
+	    case PARAMETER_TYPE_Choice:
+	      {
+		int val=(int)strtol(inmap->value,(char**)NULL,10);
+		if(val==0 && strncasecmp(inmap->value,"0",1)!=0)
+		  param->Set_Value(CSG_String(inmap->value));
+		else
+		  param->Set_Value(val);
+	      }
+	      break;
+	    default:
+	      break;
+	    }
+	}else{
+	  if(param->Get_Type()==PARAMETER_TYPE_Range){
+	    inmap=getMap(argument,(CSG_String(param->Get_Identifier())+"_MIN").b_str());
+	    if(inmap!=NULL)
+	      param->asRange()->Set_LoVal(strtod(inmap->value,NULL));
+	    inmap=getMap(argument,(CSG_String(param->Get_Identifier())+"_MAX").b_str());
+	    if(inmap!=NULL)
+	      param->asRange()->Set_HiVal(strtod(inmap->value,NULL));	    
+	  }
+	  if(inmap==NULL){
+	    param->Restore_Default();
+	  }
+	}
+      }
+  }
+
+  for(int k=0;k<pc;k++){
+    CSG_Parameter * param=params->Get_Parameter(k);
+    if( param->is_Input() )
+      if(!sagaLoadInput(param,argument)){
+	fprintf(stderr,"%s %d \n",__FILE__,__LINE__);
+	return false;
+      }
+  }
+  return true;
+}
+
+/**
+ * Save all values outputed by a SAGA-GIS module invocation to files
+ *
+ * @param params the parameters list
+ * @param main_conf the conf maps containing the main.cfg settings
+ * @param outputs the maps to set the generated_file for each output
+ */
+bool sagaSaveOutputs(CSG_Parameters *params,maps* main_conf,maps** outputs)
+{
+  for(int j=0; j<params->Get_Count(); j++)
+    {
+      CSG_Parameter *param = params->Get_Parameter(j);
+      maps* cMaps=getMaps(*outputs,CSG_String(param->Get_Identifier()).b_str());
+      // Specific TIN case
+      if(cMaps==NULL && CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("tin")))
+	cMaps=getMaps(*outputs,(CSG_String(param->Get_Identifier())+"_POINTS").b_str());
+      if(cMaps!=NULL){
+	map* tmpPath=getMapFromMaps(main_conf,"main","tmpPath");
+	map* sid=getMapFromMaps(main_conf,"lenv","usid");
+	const char *file_ext=sagaGetDefaultExt(param);
+
+	if( param->is_Input() )
+	  {
+	    if( param->is_DataObject() )
+	      {
+		CSG_Data_Object *pObject = param->asDataObject();
+		
+		if( pObject && pObject->is_Modified() && SG_File_Exists(pObject->Get_File_Name()) )
+		  {
+		    pObject->Save(pObject->Get_File_Name());
+		    addToMap(cMaps->content,"generated_file",CSG_String(pObject->Get_File_Name()).b_str());
+		  }
+	      }
+	    
+	    else if( param->is_DataObject_List() )
+	      {
+		for(int i=0; i<param->asList()->Get_Count(); i++)
+		  {
+		    CSG_Data_Object *pObject = param->asList()->asDataObject(i);
+		    
+		    if( pObject->is_Modified() && SG_File_Exists(pObject->Get_File_Name()) )
+		      {
+			pObject->Save(pObject->Get_File_Name());
+			setMapArray(cMaps->content,"generated_file",i,CSG_String(pObject->Get_File_Name()).b_str());
+		      }
+		  }
+	      }
+	  }
+	else
+	  if( param->is_Output() )
+	    {
+	      char *realFileName=(char*)malloc((strlen(file_ext)+strlen(sid->value)+strlen(cMaps->name)+14)*sizeof(char));
+	      char *fullFileName=(char*)malloc((strlen(file_ext)+strlen(sid->value)+strlen(cMaps->name)+strlen(tmpPath->value)+16)*sizeof(char));
+	      sprintf(realFileName,"Output_%s_%s_%d",cMaps->name,sid->value,sagaOutputCounter);
+	      sprintf(fullFileName,"%s/Output_%s_%s_%d.%s",tmpPath->value,cMaps->name,sid->value,sagaOutputCounter,file_ext);
+	      sagaOutputCounter+=1;
+	      wxString fileName(fullFileName);
+	      addToMap(cMaps->content,"generated_name",realFileName);
+	      free(realFileName);
+	      free(fullFileName);
+
+	      if( param->is_DataObject() )
+		{
+		  if( param->asDataObject() )
+		    {
+		      param->asDataObject()->Save(&fileName);
+		      addToMap(cMaps->content,"generated_file",CSG_String(param->asDataObject()->Get_File_Name()).b_str());
+		    }
+		}
+	    
+	      else if( param->is_DataObject_List() )
+		{
+		  CSG_Strings	fileNames;
+		
+		  while( fileName.Length() > 0 )
+		    {
+		      CSG_String current_file(&fileName);
+		      current_file = current_file.BeforeFirst(';');
+		      if( current_file.Length() > 0 )
+			{
+			  fileNames += current_file;
+			  fileName = fileName.AfterFirst(';');
+			}
+		      else
+			{
+			  fileNames += &fileName;
+			  fileName.Clear();
+			}
+		    }
+		  
+		  int nFileNames = param->asList()->Get_Count() <= fileNames.Get_Count() ? fileNames.Get_Count() : fileNames.Get_Count() - 1;
+		  for(int i=0; i<param->asList()->Get_Count(); i++)
+		    {
+		      fileNames[i].Trim();
+		      if( i < nFileNames )
+			{
+			  param->asList()->asDataObject(i)->Save(fileNames[i]);
+			}
+		      else
+			{
+			  param->asList()->asDataObject(i)->Save(CSG_String::Format(SG_T("%s_%0*d"),
+										    fileNames[fileNames.Get_Count() - 1].c_str(),
+										    SG_Get_Digit_Count(param->asList()->Get_Count()),
+										    1 + i - nFileNames
+										    ));
+			}
+		      setMapArray(cMaps->content,"generated_file",i,
+				  CSG_String(param->asList()->asDataObject(i)->Get_File_Name()).b_str());
+		    }
+		}
+	    }
+      }
+    }
+  return( true );
+}
+
+/**
+ * Invoke the execution of a SAGA-GIS module.
+ *
+ * @param main_conf the conf maps containing the main.cfg settings
+ * @param lib_name the SAGA-GIS library name
+ * @param module_name the SAGA-GIS module name
+ * @param arguments the map containing the arguments to pass to the module
+ * @param outputs default to NULL, contains the maps to fill with the result
+ */
+int sagaExecuteCmd(maps** main_conf,const char* lib_name,const char* module_name,map* arguments,maps** outputs=NULL){
+  int res=SERVICE_FAILED;
+
+  CSG_Module_Library * library=SG_Get_Module_Library_Manager().Get_Library(CSG_String(lib_name),true);
+  if( library == NULL){
+    char tmp[255];
+    sprintf(tmp,"Counld not load the %s SAGA library",lib_name);
+    setMapInMaps(*main_conf,"lenv","message",tmp);
+    res=SERVICE_FAILED;
+    return res;
+  }
+
+  CSG_Module * module=library->Get_Module(atoi(module_name));
+  if(module == NULL){
+    char tmp[255];
+    sprintf(tmp,"Counld not load the %s module from the %s SAGA library",module_name,lib_name);
+    setMapInMaps(*main_conf,"lenv","message",tmp);
+    res=SERVICE_FAILED;
+    return res;
+  }
+
+  CSG_Parameters * params=module->Get_Parameters();
+  if(!params){
+    char tmp[255];
+    sprintf(tmp,"Counld not find any param for the %s module from the %s SAGA library",module_name,lib_name);
+    setMapInMaps(*main_conf,"lenv","message",tmp);
+    res=SERVICE_FAILED;
+    return res;
+  }
+  
+  sagaSetParameters(params,arguments);
+
+  module->Update_Parameter_States();
+
+  bool retval=false;
+  if(module->On_Before_Execution()){
+    retval=module->Execute();
+    module->On_After_Execution();
+  }
+  
+  if(retval && outputs!=NULL){
+    sagaSaveOutputs(module->Get_Parameters(),*main_conf,outputs);
+    SG_Get_Data_Manager().Delete_Unsaved();
+    return SERVICE_SUCCEEDED;
+  }
+
+  return SERVICE_FAILED;
+
+}
+
+/**
+ * Export a SAGA-GIS Shapes to a file in a specific format (GML,KML,GeoJSON).
+ * saga_cmd io_gdal 4 -FILE my.format -SHAPES my.shp -FORMAT XXX
+ *
+ * @param main_conf the conf maps containing the main.cfg settings
+ * @param in the output maps to fill with the resulting file
+ */
+int sagaExportOGR(maps** conf, maps** in){
+  map* mtype=getMap((*in)->content,"mimeType");
+  map* gfile=getMap((*in)->content,"generated_file");
+  char* fext=NULL;
+  map* arg=NULL;
+  if(strncasecmp(mtype->value,"text/xml",8)==0){
+    fext=zStrdup("xml");
+  }
+  else if(strncasecmp(mtype->value,"application/json",16)==0){
+    fext=zStrdup("json");
+  }
+  else{
+    fext=zStrdup("kml");
+  }
+  char* tmpName=(char*)malloc((strlen(gfile->value)+2)*sizeof(char));
+  strncpy(tmpName,gfile->value,(strlen(gfile->value)-3)*sizeof(char));
+  strncpy(&tmpName[0]+(strlen(gfile->value)-3),fext,(strlen(fext))*sizeof(char));
+  tmpName[strlen(fext)+(strlen(gfile->value)-3)]=0;
+  arg=createMap("SHAPES",gfile->value);
+  addToMap(arg,"FILE",tmpName);
+  if(strncasecmp(mtype->value,"text/xml",8)==0){
+    addToMap(arg,"FORMAT","GML");
+  }
+  else if(strncasecmp(mtype->value,"application/json",16)==0){
+    addToMap(arg,"FORMAT","GeoJSON");
+  }
+  else{
+    addToMap(arg,"FORMAT","LIBKML");
+  }
+  free(fext);
+  free(gfile->value);
+  gfile->value=zStrdup(tmpName);
+  free(tmpName);
+  
+  sagaExecuteCmd(conf,"io_gdal","4",arg);
+  freeMap(&arg);
+  free(arg);
+}
+
+/**
+ * Export a SAGA-GIS pointcloud to a las file.
+ * saga_cmd io_shapes_las 0 -POINTS my.spc -FILE my.las
+ *
+ * @param main_conf the conf maps containing the main.cfg settings
+ * @param in the output maps to fill with the resulting file
+ */
+void sagaExportPC(maps** conf, maps** in){
+  map* mtype=getMap((*in)->content,"mimeType");
+  map* gfile=getMap((*in)->content,"generated_file");
+  char* fext="las";
+  map* arg=NULL;
+  char* tmpName=(char*)malloc((strlen(gfile->value)+2)*sizeof(char));
+  strncpy(tmpName,gfile->value,(strlen(gfile->value)-3)*sizeof(char));
+  strncpy(&tmpName[0]+(strlen(gfile->value)-3),fext,(strlen(fext))*sizeof(char));
+  tmpName[strlen(fext)+(strlen(gfile->value)-3)]=0;
+  arg=createMap("POINTS",gfile->value);
+  addToMap(arg,"FILE",tmpName);
+  free(gfile->value);
+  gfile->value=zStrdup(tmpName);
+  sagaExecuteCmd(conf,"io_shapes_las","0",arg);
+  freeMap(&arg);
+  free(arg);
+  free(tmpName);
+}
+
+/**
+ * Export a SAGA-GIS Grid to a file in a specific format (tiff,hdr,aa).
+ * saga_cmd io_gdal 1 -FILE my.format -GRIDS my.sgrd -FORMAT XXX
+ *
+ * @param main_conf the conf maps containing the main.cfg settings
+ * @param in the output maps to fill with the resulting file
+ */
+int sagaExportGDAL(maps** conf, maps** in/*,CSG_Parameter* param*/){
+  map* mtype=getMap((*in)->content,"extension");
+  map* gfile=getMap((*in)->content,"generated_file");
+  char* fext=NULL;
+  map* arg;
+
+  if(mtype!=NULL)
+    fext=zStrdup(mtype->value);
+  else{
+    fext=zStrdup("tiff");
+  }
+
+  mtype=getMap((*in)->content,"mimeType");
+  if(strncasecmp(mtype->value,"image/tiff",10)==0){
+    arg=createMap("FORMAT","1");
+  }
+  else if(strncasecmp(mtype->value,"application/x-ogc-envi",22)==0){
+    arg=createMap("FORMAT","ENVI .hdr Labelled");
+  }
+  else{
+    arg=createMap("FORMAT","ARC Digitized Raster Graphics");
+  }
+
+  if(gfile!=NULL){
+    char* tmpName=(char*)malloc((strlen(gfile->value)+1)*sizeof(char));
+    strncpy(tmpName,gfile->value,(strlen(gfile->value)-4)*sizeof(char));
+    strncpy(&tmpName[0]+(strlen(gfile->value)-4),fext,(strlen(fext))*sizeof(char));
+    tmpName[strlen(fext)+(strlen(gfile->value)-4)]=0;
+    addToMap(arg,"FILE",tmpName);
+    addToMap(arg,"GRIDS",gfile->value);
+    free(tmpName);
+    free(fext);
+    free(gfile->value);
+    map* tmp=getMap(arg,"FILE");
+    gfile->value=zStrdup(tmp->value);
+    sagaExecuteCmd(conf,"io_gdal","1",arg);
+  }
+  else{
+    // Empty result
+    return true;
+  }
+  freeMap(&arg);
+  free(arg);
+}
+
+/**
+ * Export a SAGA-GIS TIN to a file in a specific format (GML,KML,GeoJSON).
+ * Exporting TIN produce 5 separated files (POINTS, CENTER, EDGES, TRIANGLES 
+ * and POLYGONS). Even if a client can choose which result it want to have,
+ * SAGA-GIS module will be invoked in a way that it will produce in any case
+ * each possible outputs. The selection of a specific output is made in the 
+ * ZOO-Kernel itself and not specifically at this level.
+ * saga_cmd tin_tools 3 -TIN my.shp -POINTS p.shp ...
+ *
+ * @param conf the conf maps containing the main.cfg settings
+ * @param in the output maps to fill with the resulting file
+ * @see sagaExportOGR
+ */
+int sagaExportTIN(maps** conf, maps** in,const char* tname/*,CSG_Parameter* param*/){
+  map* mtype=getMap((*in)->content,"mimeType");
+  map* gfile=getMap((*in)->content,"generated_file");
+  char* fext="shp";
+  map* arg=createMap("TIN",gfile->value);
+
+  char* tinOut[5]={
+    "POINTS",
+    "CENTER",
+    "EDGES",
+    "TRIANGLES",
+    "POLYGONS"
+  };
+  maps* resouts=NULL;
+
+  int i=0;
+  for(i=0;i<5;i++){
+    char* tmpName=(char*)malloc((strlen(gfile->value)+strlen(tinOut[i])+4)*sizeof(char));
+    strncpy(tmpName,gfile->value,(strlen(gfile->value)-3)*sizeof(char));
+    char *tmpSubName=(char*) malloc((strlen(tinOut[i])+3)*sizeof(char));
+    sprintf(tmpSubName,"_%s.",tinOut[i]);
+    strncpy(&tmpName[0]+(strlen(gfile->value)-4),tmpSubName,(strlen(tmpSubName))*sizeof(char));
+    strncpy(&tmpName[0]+(strlen(gfile->value)+strlen(tmpSubName)-4),fext,(strlen(fext))*sizeof(char));
+    tmpName[strlen(fext)+(strlen(gfile->value)+strlen(tmpSubName)-4)]=0;
+
+    maps* louts=(maps*)malloc(MAPS_SIZE);
+    louts->name=zStrdup(tinOut[i]);
+    louts->content=createMap("mimeType","UNKOWN");
+    louts->next=NULL;
+    
+    addToMap(arg,tinOut[i],tmpName);
+    
+    free(tmpName);
+    if(resouts==NULL)
+      resouts=dupMaps(&louts);
+    else
+      addMapsToMaps(&resouts,louts);
+    freeMaps(&louts);
+    free(louts);
+  }
+  
+  sagaExecuteCmd(conf,"tin_tools","3",arg,&resouts);
+
+  for(i=0;i<5;i++){
+    map* generatedFile=getMapFromMaps(resouts,tinOut[i],"generated_file");
+    setMapInMaps(*in,(CSG_String(tname)+"_"+tinOut[i]).b_str(),"generated_file",generatedFile->value);
+    maps* cout=getMaps(*in,(CSG_String(tname)+"_"+tinOut[i]).b_str());
+    sagaExportOGR(conf,&cout);
+  }
+  return true;
+}
+
+/**
+ * Import GDAL Datasource into SAGA-GIS.
+ * saga_cmd io_gdal 0 -TRANSFORM 0 -FILES my.format -GRIDS /tmpPath/MyGridXXX.sgrd
+ * 
+ * @param conf the conf maps containing the main.cfg settings
+ * @param in in the inputs maps
+ */
+int sagaImportGDAL(maps** conf, maps** in){
+  map* l=getMap((*in)->content,"length");
+  bool shouldClean=false;
+  if(l==NULL){
+    l=createMap("length","1");
+    shouldClean=true;
+  }
+  int len=strtol(l->value,NULL,10);
+  int i=0;
+  for(i=0;i<len;i++){
+    map* arg=createMap("TRANSFORM","0");
+    addToMap(arg,"INTERPOL","4");
+    map* v=getMapArray((*in)->content,"cache_file",i);
+    if(v!=NULL)
+      addToMap(arg,"FILES",v->value);
+    addToMap(arg,"GRIDS","");
+
+    maps* louts=(maps*)malloc(MAPS_SIZE);
+    louts->name=zStrdup("GRIDS");
+    louts->content=createMap("mimeType","UNKOWN");
+    louts->next=NULL;
+
+    sagaExecuteCmd(conf,"io_gdal","0",arg,&louts);
+
+    map* tmp=getMapFromMaps(louts,"GRIDS","generated_file");
+    setMapArray((*in)->content,"saga_value",i,tmp->value);
+
+    freeMaps(&louts);
+    free(louts);
+    freeMap(&arg);
+    free(arg);
+  }
+  if(shouldClean){
+    freeMap(&l);
+    free(l);
+  }
+}
+
+/**
+ * Import OGR Datasource into SAGA-GIS.
+ * saga_cmd io_gdal 3 -SHAPES my.shp -FILES my.format
+ * 
+ * @param conf the conf maps containing the main.cfg settings
+ * @param in in the inputs maps
+ */
+int sagaImportOGR(maps** conf, maps** in){
+  char *ext;
+  map* arg;
+  map* l=getMap((*in)->content,"length");
+  bool shouldClean=false;
+  if(l==NULL){
+    l=createMap("length","1");
+    shouldClean=true;
+  }
+  int len=strtol(l->value,NULL,10);
+  int i=0;
+  for(i=0;i<len;i++){
+    map* v=getMapArray((*in)->content,"cache_file",i);
+    arg=createMap("SHAPES","");
+    if(v!=NULL)
+      addToMap(arg,"FILES",v->value);
+
+    maps* louts=(maps*)malloc(MAPS_SIZE);
+    louts->name=zStrdup("SHAPES");
+    louts->content=createMap("mimeType","UNKOWN");
+    louts->next=NULL;
+
+    sagaExecuteCmd(conf,"io_gdal","3",arg,&louts);
+
+    map* tmp=getMapFromMaps(louts,"SHAPES","generated_file");
+    setMapArray((*in)->content,"saga_value",i,tmp->value);
+
+    freeMaps(&louts);
+    free(louts);
+    freeMap(&arg);
+    free(arg);
+  }
+  if(shouldClean){
+    freeMap(&l);
+    free(l);
+  }
+}
+
+/**
+ * Import TIN into SAGA-GIS. Calling this function suppose that sagaImportOGR
+ * was called first.
+ * saga_cmd tin_tools 2 -SHAPES myShapes.shp -TIN myTin.shp
+ * 
+ * @param conf the conf maps containing the main.cfg settings
+ * @param in in the inputs maps
+ * @see sagaImportOGR
+ */
+bool sagaImportTIN(maps** conf, maps** in){
+  char *ext;
+  map* arg;
+  map* l=getMap((*in)->content,"length");
+  bool shouldClean=false;
+  if(l==NULL){
+    l=createMap("length","1");
+    shouldClean=true;
+  }
+  int len=strtol(l->value,NULL,10);
+  int i=0;
+  for(i=0;i<len;i++){
+    map* v=getMapArray((*in)->content,"saga_value",i);
+    arg=createMap("TIN","");
+    if(v!=NULL)
+      addToMap(arg,"SHAPES",v->value);
+    maps* louts=(maps*)malloc(MAPS_SIZE);
+    louts->name=zStrdup("TIN");
+    louts->content=createMap("mimeType","UNKOWN");
+    louts->next=NULL;
+    sagaExecuteCmd(conf,"tin_tools","2",arg,&louts);
+    map* tmp=getMapFromMaps(louts,"TIN","generated_file");
+    v=getMapArray((*in)->content,"saga_value",i);
+    if(tmp!=NULL){
+      if(v!=NULL){
+	free(v->value);
+	v->value=zStrdup(tmp->value);
+      }
+      else
+	setMapArray((*in)->content,"saga_value",i,tmp->value);
+    }
+    freeMaps(&louts);
+    free(louts);
+    freeMap(&arg);
+    free(arg);
+  }
+  if(shouldClean){
+    freeMap(&l);
+    free(l);
+  }
+  return true;
+}
+
+/**
+ * Import table into SAGA-GIS. 
+ * saga_cmd io_table 1 -TABLE myTable -FILENAME myFile -SEPARATOR 2
+ * 
+ * @param conf the conf maps containing the main.cfg settings
+ * @param in in the inputs maps
+ */
+int sagaImportTable(maps** conf, maps** in){
+  char *ext;
+  map* arg;
+  map* l=getMap((*in)->content,"length");
+  bool shouldClean=false;
+  if(l==NULL){
+    l=createMap("length","1");
+    shouldClean=true;
+  }
+  int len=strtol(l->value,NULL,10);
+  int i=0;
+  for(i=0;i<len;i++){
+
+    // Create and fill arg map
+    arg=createMap("SEPARATOR","2");
+    addToMap(arg,"TABLE","");
+    map* v=getMapArray((*in)->content,"cache_file",i);
+    if(v!=NULL)
+      addToMap(arg,"FILENAME",v->value);
+
+    // Create the output maps
+    maps* louts=(maps*)malloc(MAPS_SIZE);
+    louts->name=zStrdup("TABLE");
+    louts->content=createMap("mimeType","UNKOWN");
+    louts->next=NULL;
+
+    // Execute the saga command
+    sagaExecuteCmd(conf,"io_table","1",arg,&louts);
+
+    // Fetch result and add it to the original map as saga_value
+    map* tmp=getMapFromMaps(louts,"TABLE","generated_file");
+    setMapArray((*in)->content,"saga_value",i,tmp->value);
+
+    // Cleanup
+    freeMaps(&louts);
+    free(louts);
+    freeMap(&arg);
+    free(arg);
+
+  }
+  // Cleanup if required
+  if(shouldClean){
+    freeMap(&l);
+    free(l);
+  }
+}
+
+/**
+ * Import las file as pointcloud into SAGA-GIS. 
+ * saga_cmd io_shapes_las 1 -POINTS my.spc -FILENAME my.las
+ * 
+ * @param conf the conf maps containing the main.cfg settings
+ * @param in in the inputs maps
+ */
+int sagaImportPC(maps** conf, maps** in){
+  char *ext;
+  map* arg;
+  map* l=getMap((*in)->content,"length");
+  bool shouldClean=false;
+  if(l==NULL){
+    l=createMap("length","1");
+    shouldClean=true;
+  }
+  int len=strtol(l->value,NULL,10);
+  int i=0;
+  for(i=0;i<len;i++){
+
+    // Create and fill arg map
+    arg=createMap("POINTS","");
+    map* v=getMapArray((*in)->content,"cache_file",i);
+    if(v!=NULL)
+      addToMap(arg,"FILES",v->value);
+
+    // Create the output maps
+    maps* louts=(maps*)malloc(MAPS_SIZE);
+    louts->name=zStrdup("POINTS");
+    louts->content=createMap("mimeType","UNKOWN");
+    louts->next=NULL;
+
+    // Execute the saga command
+    sagaExecuteCmd(conf,"io_shapes_las","1",arg,&louts);
+
+    // Fetch result and add it to the original map as saga_value
+    map* tmp=getMapFromMaps(louts,"POINTS","generated_file");
+    setMapArray((*in)->content,"saga_value",i,tmp->value);
+
+    // Cleanup
+    freeMaps(&louts);
+    free(louts);
+    freeMap(&arg);
+    free(arg);
+
+  }
+  // Cleanup if required
+  if(shouldClean){
+    freeMap(&l);
+    free(l);
+  }
+}
+
+/**
+ * Load and invoke a SAGA-GIS module defined in a service metadata definitions.
+ * Load all the input data into SAGA-GIS using io_gdal, io_tables and 
+ * io_shapes_las for SAGA grids/shapes, tables and pointcloud respectively. 
+ * Load and run the module from its library and invoke it using the data 
+ * imported in SAGA-GIS at first stage. After the execution, export the outputs
+ * to files using io_gdal and io_shapes_las for grids/shapes and pointcloud 
+ * respectively.
+ *
+ * @param main_conf the conf maps containing the main.cfg settings
+ * @param request the map containing the HTTP request
+ * @param s the service structure
+ * @param inputs the maps containing the inputs
+ * @param outputs the maps containing the outputs
+ */
+int zoo_saga_support(maps** main_conf,map* request,service* s,maps** inputs,maps** outputs){
+  int res=SERVICE_FAILED;
+  if( !wxInitialize() ){
+    fprintf(stderr,"initialisation failed");
+    return SERVICE_FAILED;
+  }
+  setlocale(LC_NUMERIC, "C");
+  static bool g_bShow_Messages = false;
+
+  dumpMapsValuesToFiles(main_conf,inputs);
+
+  SagaWatcher watcher=SagaWatcher();
+  watcher.SetConf(main_conf);
+
+  SG_Set_UI_Callback(Get_Callback(watcher));
+
+  int n = SG_Get_Module_Library_Manager().Add_Directory(wxT(MODULE_LIBRARY_PATH),false);
+  if( SG_Get_Module_Library_Manager().Get_Count() <= 0 ){
+    setMapInMaps(*main_conf,"lenv","message","Could not load any SAGA tool library");
+    res=SERVICE_FAILED;
+    return res;
+  }
+
+  map* serviceProvider=getMap(s->content,"serviceProvider");
+
+  // Load the SAGA-GIS library corresponding to the serviceProvider
+  CSG_Module_Library * library=SG_Get_Module_Library_Manager().Get_Library(CSG_String(serviceProvider->value),true);
+  if( library == NULL){
+    char tmp[255];
+    sprintf(tmp,"Counld not load the %s SAGA library",serviceProvider->value);
+    setMapInMaps(*main_conf,"lenv","message",tmp);
+    res=SERVICE_FAILED;
+    return res;
+  }
+  
+  // Load the SAGA-GIS module corresponding to the service name from the library
+  CSG_Module * module=library->Get_Module(atoi(s->name));
+  if(module == NULL){
+    char tmp[255];
+    sprintf(tmp,"Counld not load the %s module from the %s SAGA library",
+	    s->name,serviceProvider->value);
+    setMapInMaps(*main_conf,"lenv","message",tmp);
+    res=SERVICE_FAILED;
+    return res;
+  }
+
+  // Load all the parameters defined for the module
+  CSG_Parameters * params=module->Get_Parameters();
+  int pc=params->Get_Count();
+  if(!params){
+    char tmp[255];
+    sprintf(tmp,"Counld not find any param for the %s module from the %s SAGA library",
+	    s->name,serviceProvider->value);
+    setMapInMaps(*main_conf,"lenv","message",tmp);
+    res=SERVICE_FAILED;
+    return res;
+  }
+
+  // Loop over each inputs to transform raster files to grid when needed, 
+  // import tables, shapes or point clouds
+  for(int k=0;k<pc;k++){
+    CSG_Parameter * param=params->Get_Parameter(k);
+    if(param!=NULL && !param->is_Output()){
+      maps* inmap=getMaps(*inputs,CSG_String(param->Get_Identifier()).b_str());
+      if(inmap!=NULL){
+	map* tmp=getMap(inmap->content,"value");
+	if(tmp==NULL || strncasecmp(tmp->value,"NULL",4)!=0){
+	  if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("grid"))){
+	    sagaImportGDAL(main_conf,&inmap);
+	  }
+	  else if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("tin"))){
+	    sagaImportOGR(main_conf,&inmap);
+	    sagaImportTIN(main_conf,&inmap);
+	  }
+	  else if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("shapes"))){
+	    sagaImportOGR(main_conf,&inmap);
+	  }
+	  else{
+	    if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("table"))){
+	      sagaImportTable(main_conf,&inmap);
+	    }
+	    else
+	      if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("points"))){
+		sagaImportPC(main_conf,&inmap);
+	      }
+	  }
+	}
+      }
+    }
+  }
+
+  // Create a map conraining arguments to pass to the SAGA-GIS module
+  // Fetch all input value (specifically for data imported into SAGA-GIS)
+  maps* inp=*inputs;
+  int k=0;
+  map* cParams=NULL;
+  while(inp!=NULL){
+    map* len=getMap(inp->content,"length");
+    bool shouldClean=false;
+    if(len==NULL){
+      len=createMap("length","1");
+      shouldClean=true;
+    }
+    int len0=strtol(len->value,NULL,10);
+    int i=0;
+    char *cinput=NULL;
+    int clen=0;
+    for(i=0;i<len0;i++){
+      map* val=getMapArray(inp->content,"saga_value",i);
+      if(val==NULL)
+	val=getMapArray(inp->content,"value",i);
+      if(val!=NULL && strncasecmp(val->value,"NULL",4)!=0){
+	if(cinput==NULL){
+	  cinput=zStrdup(val->value);
+	}
+	else{
+	  cinput=(char*)realloc(cinput,(clen+strlen(val->value)+1)*sizeof(char));
+	  strncpy(&cinput[0]+clen,";",1);
+	  strncpy(&cinput[0]+(clen+1),val->value,strlen(val->value));
+	  clen+=1;
+	}
+	clen+=strlen(val->value);
+	cinput[clen]=0;
+      }
+    }
+    if(cinput!=NULL && strncasecmp(cinput,"NULL",4)!=0){
+      if(cParams==NULL)
+	cParams=createMap(inp->name,cinput);
+      else
+	addToMap(cParams,inp->name,cinput);
+      free(cinput);
+    }
+    inp=inp->next;
+  }
+
+  // Fetch all output and define a resulting filename
+  inp=*outputs;
+  map* tmpPath=getMapFromMaps(*main_conf,"main","tmpPath");
+  map* sid=getMapFromMaps(*main_conf,"lenv","usid");
+  while(inp!=NULL){
+    for(int k=0;k<pc;k++){
+      CSG_Parameter * param=params->Get_Parameter(k);
+      if(CSG_String(param->Get_Identifier()).Cmp(inp->name)==0){
+	const char *file_ext=sagaGetDefaultExt(param);
+	char *fileName=(char*)malloc((strlen(file_ext)+strlen(sid->value)+strlen(inp->name)+strlen(tmpPath->value)+11)*sizeof(char));
+	sprintf(fileName,"%s/Output_%s_%s.%s",tmpPath->value,inp->name,sid->value,file_ext);
+	if(cParams==NULL)
+	  cParams=createMap(inp->name,fileName);
+	else
+	  addToMap(cParams,inp->name,fileName);
+      }
+    }
+    inp=inp->next;
+  }
+
+  sagaSetParameters(params,cParams);
+
+  module->Update_Parameter_States();
+  
+  bool retval=false;
+  if(module->On_Before_Execution()){
+    retval=module->Execute();
+    module->On_After_Execution();
+  }
+
+  sagaSaveOutputs(params,*main_conf,outputs);
+
+  // Loop over each outputs to transform grid to raster file when needed, 
+  // export tables, shapes or point clouds
+  for(int k=0;k<pc;k++){
+    CSG_Parameter * param=params->Get_Parameter(k);
+    if(param!=NULL && param->is_Output()){
+      maps* inmap=getMaps(*outputs,CSG_String(param->Get_Identifier()).b_str());
+      if(inmap!=NULL){
+	if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("grid"))
+	   || CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("data_object"))){
+	  sagaExportGDAL(main_conf,&inmap);
+	}else{
+	  if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("shapes"))){
+	    sagaExportOGR(main_conf,&inmap);
+	  }
+	  else{
+	    if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("table"))){
+	    }
+	    else{
+	      if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("tin"))){
+		sagaExportTIN(main_conf,&inmap,"TIN");
+	      }
+	      else
+		if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("points"))){
+		  sagaExportPC(main_conf,&inmap);
+	      }
+	    }
+	  }
+	}
+      }
+      else if(CSG_String(param->Get_Type_Identifier()).Contains(CSG_String("tin"))){
+	sagaExportTIN(main_conf,outputs,CSG_String(param->Get_Identifier()).b_str());
+      }
+	      
+    }
+  }
+
+  wxUninitialize();
+
+  return SERVICE_SUCCEEDED;
+}
diff --git a/zoo-project/zoo-kernel/service_internal_saga.h b/zoo-project/zoo-kernel/service_internal_saga.h
new file mode 100644
index 0000000..b17e799
--- /dev/null
+++ b/zoo-project/zoo-kernel/service_internal_saga.h
@@ -0,0 +1,35 @@
+/*
+ * Author : Gérald FENOY
+ *
+ * Copyright (c) 2015 GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef ZOO_SERVICE_INTERNAL_SAGA_H
+#define ZOO_SERVICE_INTERNAL_SAGA_H 1
+
+#pragma once 
+
+#include "service.h"
+#include "service_internal.h"
+
+int zoo_saga_support(maps**,map*,service*,maps**,maps**);
+
+#endif
diff --git a/zoo-project/zoo-kernel/service_loader.c b/zoo-project/zoo-kernel/service_loader.c
new file mode 100644
index 0000000..6d688f7
--- /dev/null
+++ b/zoo-project/zoo-kernel/service_loader.c
@@ -0,0 +1,272 @@
+/**
+ * Author : Gérald FENOY
+ *
+ * Copyright (c) 2009-2010 GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+/**
+ * Environment variables definitions.
+ * All the following fixed values should be extracted from a configuration main
+ * configuration file for all the potential services.
+ */
+/**
+ * END "Environment variables definitions"
+ */
+#define length(x) (sizeof(x) / sizeof(x[0]))
+
+extern "C" int yylex();
+extern "C" int crlex();
+
+#include <string.h>
+
+#include "service.h"
+#include "service_internal.h"
+#include "service_internal_python.h"
+
+#include <dirent.h>
+#include <signal.h>
+#include <unistd.h>
+#ifndef WIN32
+#include <dlfcn.h>
+#include <libgen.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#include <stdarg.h>
+
+void sigint_handler(int sig){
+    printf("Not this time!\n");
+}
+
+int main(int argc, char *argv[])
+{
+  if (argc < 4){
+    printf( "Usage: %s <servicename> <directory>|<definition_file> <REQUEST> [<functionname> <param_1>[...<param_n>]]\n", basename(argv[0]) );
+    return 1;
+  }
+ 
+  map* outputs=NULL;
+  /**
+   * Parsing inputs (need a loop over all files in the service path !!)
+   */
+  maps* m;
+  m=(maps*)malloc(MAP_SIZE);
+  conf_read("main.cfg",m);
+  map* tmpm=getMapFromMaps(m,"main","serverAddress");
+  int toto=count(tmpm);
+  //printf(" - %i \n",toto);
+
+  if(tmpm!=NULL)
+    SERVICE_URL=strdup(tmpm->value);
+  else
+    SERVICE_URL=DEFAULT_SERVICE_URL;
+
+  service* s[100];
+  service* s1;
+  int scount=0;
+
+  if(strcmp(argv[3],"GetCapabilities")==0){
+    int i=0;
+    struct dirent *dp;
+    DIR *dirp = opendir(argv[1]);
+    int t;
+    xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0");
+    xmlNodePtr n = printGetCapabilitiesHeader(doc,argv[2],m);
+    
+    int saved_stdout = dup(fileno(stdout));
+    stdout = freopen("/dev/null" , "w" , stdout);
+    while ((dp = readdir(dirp)) != NULL)
+      if(strstr(dp->d_name,".zcfg")!=0){
+	char toto1[1024];
+	sprintf(toto1,"%s%s",argv[1],dp->d_name);
+	char *toto=toto1;
+	s1=(service*)malloc(sizeof(char*)+(MAP_SIZE*2)+(2*ELEMENTS_SIZE));
+	//s[scount]=(service*)malloc(sizeof(service*));
+	//#ifdef DEBUG
+	fprintf(stderr,"#################\n%s\n#################\n",toto1);
+	//printf("|(1)");
+	//#endif
+	t=getServiceFromFile(toto1,&s1);
+	
+	//printf("|(2)");
+	printGetCapabilitiesForProcess(m,n,s1);
+	/**
+	 * Valgrind told us that there is an issue regarding a 
+	 * "conditional jump or move depends on uninitialised value(s)" for
+	 * freeIOType
+	 */
+	//freeService(&s1);
+	scount++;
+      }
+    char buf[20];
+    sprintf(buf, "/dev/fd/%d", saved_stdout);
+    stdout = freopen(buf , "w" , stdout);
+
+    printDocument(doc);
+    fflush(stdout);
+    free(m);
+    return 0;
+  }
+  else{
+    s1=(service*)malloc(sizeof(char*)+(MAP_SIZE*2)+(2*ELEMENTS_SIZE));
+    //s[0]=(service*)malloc(sizeof(service*));
+    int t=getServiceFromFile(argv[1],&s1);
+    if(strcmp(argv[3],"DescribeProcess")==0){
+      printDescribeProcessResponse(s1,argv[2]);
+      //dumpMaps(m);
+      //free(s1);
+      return 0;
+    }
+    else
+      if(strcmp(argv[3],"Execute")!=0){
+	fprintf(stderr,"");
+	//free(s);
+	return 0;
+      }
+  }
+  //dumpService(s);
+  s[0]=s1;
+  map* inputs=NULL;
+  elements* c_inputs=s1->inputs;
+  int j;
+  for(j=0;j<argc-5;j++){
+    //dumpElements(c_inputs);
+    if(inputs!=NULL)
+      addToMap(inputs,c_inputs->name,argv[j+5]);
+    else
+      inputs=createMap(c_inputs->name,argv[j+5]);
+    if(c_inputs->next!=NULL || j+1>=argc-5)
+      c_inputs=c_inputs->next;
+    else{
+      map* tmps=createMap("text","ERROR you provided more inputs than requested.");
+      printExceptionReportResponse(m,tmps);
+      //printf("ERROR you provided more inputs than requested.");
+      return -1;
+    }
+#ifdef DEBUG
+    printf("ARGV1 %d %s\n",j,inputs->value);
+#endif
+  }
+
+#ifdef DEBUG
+  dumpMap(inputs);
+#endif
+
+  const struct tm *tm;
+  size_t len;
+  time_t now;
+  char *sDate;
+  
+  now = time ( NULL );
+  tm = localtime ( &now );
+
+  sDate = new char[TIME_SIZE];
+
+  len = strftime ( sDate, TIME_SIZE, "%d-%B-%YT%I:%M:%SZ", tm );
+
+#ifdef DEBUG
+  printf("Trying to load %s\n", argv[2]);
+#endif
+  void* so = dlopen(argv[2], RTLD_LAZY);
+  char *errstr;
+  errstr = dlerror();
+  if( so != NULL ) {
+    typedef int (*execute_t)(map**,map**);
+#ifdef DEBUG
+    printf("Library loaded %s \n",errstr);
+#endif
+    execute_t execute=(execute_t)dlsym(so,argv[4]);
+#ifdef DEBUG
+    errstr = dlerror();
+    printf("Function loaded %s\n",errstr);
+#endif	
+
+    /**
+     * Need to check if we need to fork to load a status enabled 
+     */
+    char _toto[10];
+    sprintf(_toto,"input_%i",argc-5);
+    map* toto=getMap(inputs,_toto);
+    if(strcmp(argv[argc-1],"bg")!=0){
+#ifdef DEBUG
+      printf("RUN IN NORMAL MODE \n");
+#endif
+      int res=execute(&inputs,&outputs);
+#ifdef DEBUG
+      printf("RUNNED IN NORMAL MODE \n");
+      dumpMap(inputs);
+      dumpMap(outputs);
+#endif
+      printProcessResponse(m,getpid(),s[0],argv[2],res,inputs,outputs);
+    }
+    else{
+      pid_t   pid;
+      int cpid=getpid();
+      pid = fork ();
+      if (pid > 0) {
+	/**
+	 * dady :
+	 * set status to SERVICE_ACCEPTED
+	 */
+	printProcessResponse(m,pid,s[0],argv[2],SERVICE_ACCEPTED,inputs,outputs);
+      }else if (pid == 0) {
+	/* son */
+	if (signal(SIGINT, sigint_handler) == SIG_ERR) {
+	  printf("signal");
+	  map* tmps=createMap("text","father received sigint.");
+	  printExceptionReportResponse(m,tmps);
+	  exit(1);
+	}
+#ifdef DEBUG
+	printf("RUN IN BACKGROUND MODE \n");
+#endif
+	char tmp1[256];
+	sprintf(tmp1,"service/temp/%s_%d.xml",argv[2],getpid());
+	stdout = freopen(tmp1 , "w+" , stdout);
+	/**
+	 * set status to SERVICE_STARTED
+	 */
+	printProcessResponse(m,getpid(),s[0],argv[2],SERVICE_STARTED,inputs,outputs);
+	fflush(stdout);
+	rewind(stdout);
+	int t=execute(&inputs,&outputs);
+	/**
+	 * set status to status code returned by the service function
+	 */
+	printProcessResponse(m,getpid(),s[0],argv[2],t,inputs,outputs);
+      } else {
+	/* error */
+      }
+    }
+#ifdef DEBUG
+    errstr = dlerror();
+    printf("Function successfully loaded %s, unloading now.\n",errstr);
+#endif
+    dlclose(so);
+  }
+  else {
+#ifdef DEBUG
+    printf("C Library can't be loaded %s \n",errstr);
+#endif
+    python_support(m,s[0],argc,argv,inputs,outputs);
+  }
+  return 0;
+}
diff --git a/zoo-project/zoo-kernel/service_yaml.c b/zoo-project/zoo-kernel/service_yaml.c
new file mode 100644
index 0000000..d587e09
--- /dev/null
+++ b/zoo-project/zoo-kernel/service_yaml.c
@@ -0,0 +1,459 @@
+/*
+ * Author : Gérald FENOY
+ *
+ *  Copyright 2014 GeoLabs SARL. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <service.h>
+#include <yaml.h>
+
+static service* my_service=NULL;
+static map* current_content=NULL;
+static elements* current_element=NULL;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Read and parse a ZCFG file in YAML format 
+ *
+ * @param conf the conf maps containing the main.cfg settings
+ * @param file the file name to read
+ * @param service the service structure to fill
+ * @param name the service name
+ * @return 1 on success, -1 if error occured
+ */
+int getServiceFromYAML(maps* conf, char* file,service** service,char *name){
+  FILE *fh = fopen("test.yml", "r");
+  if(current_content!=NULL){
+    freeMap(&current_content);
+    free(current_content);
+    current_content=NULL;
+  }
+#ifdef DEBUG_SERVICE_CONF
+  fprintf(stderr,"(STARTING)FREE current_element\n");
+#endif
+  if(current_element!=NULL){
+    freeElements(&current_element);
+    free(current_element);
+    current_element=NULL;
+  }
+  my_service=NULL;
+  
+  my_service=*service;
+  my_service->name=strdup(name);
+  my_service->content=NULL;
+  my_service->metadata=NULL;
+  my_service->inputs=NULL;
+  my_service->outputs=NULL;
+  fh = fopen(file,"r");
+  if (fh==NULL){
+    fprintf(stderr,"error : file not found\n") ;
+    return -1;
+  }
+  yaml_parser_t parser;
+  yaml_token_t  token;   /* new variable */
+
+  /* Initialize parser */
+  if(!yaml_parser_initialize(&parser))
+    fputs("Failed to initialize parser!\n", stderr);
+  if(fh == NULL)
+    fputs("Failed to open file!\n", stderr);
+  /* Set input file */
+  yaml_parser_set_input_file(&parser, fh);
+  /* BEGIN new code */
+  int level=0;
+  int plevel=level;
+  int ilevel=-1;
+  int blevel=-1;
+  int ttype=0;
+  int wait_metadata=-1;
+  char *cur_key;
+  do {
+    yaml_parser_scan(&parser, &token);
+    switch(token.type)
+    {
+    /* Stream start/end */
+    case YAML_STREAM_START_TOKEN: 
+#ifdef DEBUG_YAML
+      puts("STREAM START"); 
+#endif
+      break;
+    case YAML_STREAM_END_TOKEN:   
+#ifdef DEBUG_YAML
+      puts("STREAM END");   
+#endif
+      break;
+    /* Token types (read before actual token) */
+    case YAML_KEY_TOKEN:   
+#ifdef DEBUG_YAML
+      printf("(Key token)   "); 
+#endif
+      ttype=0;
+      break;
+    case YAML_VALUE_TOKEN: 
+#ifdef DEBUG_YAML
+      printf("(Value token) "); 
+#endif
+      ttype=1;
+      break;
+    /* Block delimeters */
+    case YAML_BLOCK_SEQUENCE_START_TOKEN: 
+#ifdef DEBUG_YAML
+      puts("<b>Start Block (Sequence)</b>"); 
+#endif
+      break;
+    case YAML_BLOCK_ENTRY_TOKEN:          
+#ifdef DEBUG_YAML
+      puts("<b>Start Block (Entry)</b>");    
+#endif
+      break;
+    case YAML_BLOCK_END_TOKEN:      
+      blevel--;
+      if(ilevel>=0)
+	ilevel--;
+#ifdef DEBUG_YAML
+      printf("<b>End block</b> (%d,%d,%d,%d)\n", blevel,level,ilevel,ttype); 
+#endif
+      break;
+    /* Data */
+    case YAML_BLOCK_MAPPING_START_TOKEN:  
+#ifdef DEBUG_YAML
+      puts("[Block mapping]");            
+#endif
+      blevel++;
+      break;
+    case YAML_SCALAR_TOKEN:  
+      if(ttype==0){
+	cur_key=zStrdup((char *)token.data.scalar.value);
+      }
+      if(ttype==1){
+	if(current_content==NULL){
+	  current_content=createMap(cur_key,(char *)token.data.scalar.value);
+	}else{
+	  addToMap(current_content,cur_key,(char *)token.data.scalar.value);
+	}
+	free(cur_key);
+	cur_key=NULL;
+      }
+
+      if(ttype==0 && blevel==0 && level==0 && strcasecmp((char *)token.data.scalar.value,"MetaData")==0 && blevel==0){
+	addMapToMap(&my_service->content,current_content);
+#ifdef DEBUG_YAML
+	fprintf(stderr,"MSG: %s %d \n",__FILE__,__LINE__);
+#endif
+	freeMap(&current_content);
+	free(current_content);
+	current_content=NULL;
+	wait_metadata=1;
+      }
+      if(ttype==0 && blevel>0 && level>0 && strcasecmp((char *)token.data.scalar.value,"MetaData")==0){
+	if(current_element->content==NULL && current_content!=NULL)
+	  addMapToMap(&current_element->content,current_content);
+#ifdef DEBUG_YAML
+	dumpMap(current_content);
+	fprintf(stderr,"MSG: %s %d \n",__FILE__,__LINE__);
+#endif
+	freeMap(&current_content);
+	free(current_content);
+	current_content=NULL;
+	wait_metadata=1;
+      }
+      if(ttype==0 && strcasecmp((char *)token.data.scalar.value,"inputs")==0 && blevel==0){
+	if(wait_metadata>0){
+	  addMapToMap(&my_service->metadata,current_content);
+	  wait_metadata=-1;
+	}else{
+	  if(current_content!=NULL && my_service->content==NULL)
+	    addMapToMap(&my_service->content,current_content);
+	}
+#ifdef DEBUG_YAML
+	dumpMap(current_content);
+	fprintf(stderr,"MSG: %s %d \n",__FILE__,__LINE__);
+#endif
+	freeMap(&current_content);
+	free(current_content);
+	current_content=NULL;
+	wait_metadata=false;
+	level++;
+      }
+      if(ttype==0 && strcasecmp((char *)token.data.scalar.value,"outputs")==0 && blevel==1){
+	level++;
+#ifdef DEBUG_YAML
+	dumpMap(current_content);
+	printf("\n***\n%d (%d,%d,%d,%d)\n+++\n", current_element->defaults==NULL,blevel,level,ilevel,ttype); 
+#endif
+	if(current_element->defaults==NULL && current_content!=NULL && ilevel<0){
+	  current_element->defaults=(iotype*)malloc(IOTYPE_SIZE);
+	  current_element->defaults->content=NULL;
+	  current_element->defaults->next=NULL;
+	  addMapToMap(&current_element->defaults->content,current_content);
+#ifdef DEBUG_YAML
+	  dumpElements(current_element);
+	  dumpMap(current_content);
+	  fprintf(stderr,"MSG: %s %d \n",__FILE__,__LINE__);
+#endif
+	  freeMap(&current_content);
+	  free(current_content);
+	  current_content=NULL;
+	}else{
+	  if(current_content!=NULL && ilevel<=0){
+	    addMapToIoType(&current_element->supported,current_content);
+#ifdef DEBUG_YAML
+	    dumpElements(current_element);
+	    dumpMap(current_content);
+	    fprintf(stderr,"MSG: %s %d \n",__FILE__,__LINE__);
+#endif
+	    freeMap(&current_content);
+	    free(current_content);
+	    current_content=NULL;
+	  }
+	}
+      }
+      if(level==1 && strcasecmp((char *)token.data.scalar.value,"default")==0){
+	ilevel=0;
+      }
+      if(level==1 && strcasecmp((char *)token.data.scalar.value,"supported")==0){
+#ifdef DEBUG_YAML
+	dumpMap(current_content);
+	printf("\n***\n%d (%d,%d,%d,%d)\n+++\n", current_element->defaults==NULL,blevel,level,ilevel,ttype); 
+#endif
+	if(current_element->defaults==NULL && current_content!=NULL && ilevel<0){
+	  current_element->defaults=(iotype*)malloc(IOTYPE_SIZE);
+	  current_element->defaults->content=NULL;
+	  current_element->defaults->next=NULL;
+	  addMapToMap(&current_element->defaults->content,current_content);
+#ifdef DEBUG_YAML
+	  dumpElements(current_element);
+	  dumpMap(current_content);
+	  fprintf(stderr,"MSG: %s %d \n",__FILE__,__LINE__);
+#endif
+	  freeMap(&current_content);
+	  free(current_content);
+	  current_content=NULL;
+	}else{
+	  if(current_content!=NULL && ilevel<=0){
+	    if(current_element->supported==NULL){
+	      current_element->supported=(iotype*)malloc(IOTYPE_SIZE);
+	      current_element->supported->content=NULL;
+	      current_element->supported->next=NULL;
+	    }
+	    addMapToMap(&current_element->supported->content,current_content);
+#ifdef DEBUG_YAML
+	    dumpElements(current_element);
+	    fprintf(stderr,"MSG: %s %d \n",__FILE__,__LINE__);
+#endif
+	    freeMap(&current_content);
+	    free(current_content);
+	    current_content=NULL;
+	  }
+	}
+	ilevel=1;
+      }
+
+
+      if(strncasecmp((char *)token.data.scalar.value,"ComplexData",11)==0 || 
+	 strncasecmp((char *)token.data.scalar.value,"LiteralData",10)==0 || 
+	 strncasecmp((char *)token.data.scalar.value,"ComplexOutput",13)==0 || 
+	 strncasecmp((char *)token.data.scalar.value,"LiteralOutput",12)==0 || 
+	 strncasecmp((char *)token.data.scalar.value,"BoundingBoxOutput",13)==0 || 
+	 strncasecmp((char *)token.data.scalar.value,"BoundingBoxData",12)==0){
+	current_element->format=zStrdup((char *)token.data.scalar.value);
+	free(cur_key);
+	cur_key=NULL;
+	if(wait_metadata>0 && current_content!=NULL){
+	  addMapToMap(&current_element->metadata,current_content);
+	  wait_metadata=-1;
+	}else{
+	  if(current_content!=NULL){
+	    addMapToMap(&current_element->content,current_content);
+	  }
+	}
+#ifdef DEBUG_YAML
+	dumpMap(current_content);
+	fprintf(stderr,"MSG: %s %d \n",__FILE__,__LINE__);
+#endif
+	freeMap(&current_content);
+	free(current_content);
+	current_content=NULL;
+#ifdef DEBUG_YAML
+	dumpElements(current_element);
+#endif
+      }
+
+      if(blevel==1 && level==1){
+	if(current_element!=NULL && current_content!=NULL){
+	  if(current_element->defaults==NULL){
+	    current_element->defaults=(iotype*)malloc(IOTYPE_SIZE);
+	    current_element->defaults->content=NULL;
+	    current_element->defaults->next=NULL;
+	    addMapToMap(&current_element->defaults->content,current_content);
+	  }else{
+	    if(current_element->supported==NULL){
+	      current_element->supported=(iotype*)malloc(IOTYPE_SIZE);
+	      current_element->supported->content=NULL;
+	      current_element->supported->next=NULL;
+	      addMapToMap(&current_element->supported->content,current_content);
+	    }else
+	      addMapToIoType(&current_element->supported,current_content);
+	  }
+	}
+	if(current_element!=NULL){
+	  if(my_service->inputs==NULL)
+	    my_service->inputs=dupElements(current_element);
+	  else
+	    addToElements(&my_service->inputs,current_element);
+	  freeElements(&current_element);
+	  free(current_element);
+	}
+	plevel=level;
+	current_element=(elements*)malloc(ELEMENTS_SIZE);
+	current_element->name=zStrdup((char *)token.data.scalar.value);
+	current_element->content=NULL;
+	current_element->metadata=NULL;
+	current_element->format=NULL;
+	current_element->defaults=NULL;
+	current_element->supported=NULL;
+	current_element->next=NULL;
+	
+      }
+      if(blevel==1 && level==2){
+	if(current_element!=NULL && current_content!=NULL){
+	  if(current_element->defaults==NULL){
+	    current_element->defaults=(iotype*)malloc(IOTYPE_SIZE);
+	    current_element->defaults->content=NULL;
+	    current_element->defaults->next=NULL;
+	    addMapToMap(&current_element->defaults->content,current_content);
+	  }else{
+	    if(current_element->supported==NULL){
+	      current_element->supported=(iotype*)malloc(IOTYPE_SIZE);
+	      current_element->supported->content=NULL;
+	      current_element->supported->next=NULL;
+	      addMapToMap(&current_element->supported->content,current_content);
+	    }else
+	      addMapToIoType(&current_element->supported,current_content);
+	  }
+	}
+	if(current_element!=NULL){
+	  if(plevel==level){
+	    if(my_service->outputs==NULL)
+	      my_service->outputs=dupElements(current_element);
+	    else
+	      addToElements(&my_service->outputs,current_element);
+	  }else{
+	    if(my_service->inputs==NULL)
+	      my_service->inputs=dupElements(current_element);
+	    else
+	      addToElements(&my_service->inputs,current_element);
+	  }
+	  freeElements(&current_element);
+	  free(current_element);
+	}
+	plevel=level;
+	current_element=(elements*)malloc(ELEMENTS_SIZE);
+	current_element->name=zStrdup((char *)token.data.scalar.value);
+	current_element->content=NULL;
+	current_element->metadata=NULL;
+	current_element->format=NULL;
+	current_element->defaults=NULL;
+	current_element->supported=NULL;
+	current_element->next=NULL;
+	
+      }
+
+
+#ifdef DEBUG_YAML
+      printf("scalar %s (%d,%d,%d,%d,%d)\n", token.data.scalar.value,blevel,level,plevel,ilevel,ttype); 
+#endif
+      break;
+    /* Others */
+    default:
+      if(token.type==0){
+	char tmp[1024];
+	sprintf(tmp,"Wrong charater found in %s: \\t",name);
+	setMapInMaps(conf,"lenv","message",tmp);
+	return -1;
+      }
+#ifdef DEBUG_YAML
+      printf("Got token of type %d\n", token.type);
+#endif
+      break;
+    }
+    if(token.type != YAML_STREAM_END_TOKEN )
+      yaml_token_delete(&token);
+  } while(token.type != YAML_STREAM_END_TOKEN);
+  yaml_token_delete(&token);
+
+
+#ifdef DEBUG_YAML
+  fprintf(stderr,"MSG: %s %d \n",__FILE__,__LINE__);
+#endif
+  if(current_element!=NULL && current_content!=NULL){
+    if(current_element->defaults==NULL){
+      current_element->defaults=(iotype*)malloc(IOTYPE_SIZE);
+      current_element->defaults->content=NULL;
+      current_element->defaults->next=NULL;
+      addMapToMap(&current_element->defaults->content,current_content);
+    }else{
+      if(current_element->supported==NULL){
+	current_element->supported=(iotype*)malloc(IOTYPE_SIZE);
+	current_element->supported->content=NULL;
+	current_element->supported->next=NULL;
+	addMapToMap(&current_element->supported->content,current_content);
+      }else
+	addMapToIoType(&current_element->supported,current_content);
+    }
+#ifdef DEBUG_YAML
+    dumpMap(current_content);
+    fprintf(stderr,"MSG: %s %d \n",__FILE__,__LINE__);
+#endif
+    freeMap(&current_content);
+    free(current_content);
+    current_content=NULL;
+  }
+  if(current_element!=NULL){
+    if(my_service->outputs==NULL)
+      my_service->outputs=dupElements(current_element);
+    else
+      addToElements(&my_service->outputs,current_element);
+    freeElements(&current_element);
+    free(current_element);
+    current_element=NULL;
+  }
+  /* END new code */
+
+  /* Cleanup */
+  yaml_parser_delete(&parser);
+  fclose(fh);
+
+#ifdef DEBUG_YAML
+  dumpService(my_service);
+#endif
+  *service=my_service;
+
+  return 1;
+}
+#ifdef __cplusplus
+}
+#endif
diff --git a/zoo-project/zoo-kernel/sql/schema.sql b/zoo-project/zoo-kernel/sql/schema.sql
new file mode 100644
index 0000000..29841e8
--- /dev/null
+++ b/zoo-project/zoo-kernel/sql/schema.sql
@@ -0,0 +1,69 @@
+--------------------------------------------------------------------------------
+--
+-- PostgreSQL definition of tables required byt the ZOO-Kernel version >= 1.5.0
+-- if the the db-backend option is activated
+--
+-- Copyright (C) 2015 GeoLabs SARL. All rights reserved.
+-- Author: David Saggiorato <david.saggiorato at geolabs.fr>
+--
+-- Permission is hereby granted, free of charge, to any person obtaining a copy
+-- of this software and associated documentation files (the "Software"), to deal
+-- in the Software without restriction, including without limitation the rights
+-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+-- copies of the Software, and to permit persons to whom the Software is
+-- furnished to do so, subject to the following conditions:
+--
+-- The above copyright notice and this permission notice shall be included in
+-- all copies or substantial portions of the Software.
+--
+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+-- THE SOFTWARE.
+--
+-------------------------------------------------------------------------------- 
+-- If your database is not using UTF-8 per default then uncomment the following 
+-- SET client_encoding = 'UTF8';
+-------------------------------------------------------------------------------- 
+-- Create a dedicated schema to store all tables
+-- Uncomment the following 2 lines to activate the schema use
+-- CREATE SCHEMA zoo;
+-- SET search_path TO zoo;
+--------------------------------------------------------------------------------
+-- Services table
+-- Used to store informations about services running asynchronously
+create table services (
+       osid TEXT unique,
+       sid TEXT unique,
+       uuid TEXT unique,
+       fstate varchar(25),
+       status TEXT,
+       response TEXT,
+       creation_time timestamp with time zone default now(),
+       end_time timestamp with time zone default NULL,
+       progress int,
+       message TEXT
+);
+--------------------------------------------------------------------------------
+-- Responses table 
+-- Used to store the response provided by a services running asynchronously
+create table responses (
+       uuid text references services(uuid) ON DELETE CASCADE,
+       content text,
+       creation_time timestamp with time zone default now()
+);
+--------------------------------------------------------------------------------
+-- Files table
+-- Used to store the files generated during the service execution
+create table files (
+       uuid TEXT references services(uuid) ON DELETE CASCADE,
+       filename text,
+       nature varchar(10),
+       name varchar(255),
+       creation_time timestamp with time zone default now(),
+       expiration_time timestamp with time zone default now() + interval '48 hours'
+);
+--------------------------------------------------------------------------------
diff --git a/zoo-project/zoo-kernel/sqlapi.c b/zoo-project/zoo-kernel/sqlapi.c
new file mode 100644
index 0000000..df13939
--- /dev/null
+++ b/zoo-project/zoo-kernel/sqlapi.c
@@ -0,0 +1,477 @@
+/*
+ * Author : David Saggiorato
+ *          Gérald Fenoy
+ *  Copyright 2015 GeoLabs SARL. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifdef RELY_ON_DB
+#include "ogr_api.h"
+#include "ogrsf_frmts.h"
+#include "ogr_p.h"
+
+#include "sqlapi.h"
+#include <fcgi_stdio.h>
+#include <stdlib.h>
+
+/**
+ * Global GDALDataset pointer
+ */
+OGRDataSource *zoo_DS = NULL;
+
+/**
+ * Global OGRLayer pointer pointing to the lastest result set
+ */
+OGRLayer *zoo_ResultSet = NULL;
+
+/**
+ * Create a GDAL / OGR string for connecting to the db backend
+ * (do not support active_schema)
+ * 
+ * @param conf the maps containing the setting of the main.cfg file
+ */
+char* createInitString(maps* conf){
+  char* res=NULL;
+  char keywords[5][9]={
+    "dbname",
+    "host",
+    "port",
+    "user",
+    "password"
+  };
+  int i=0;
+  maps* cconf=getMaps(conf,"database");
+  int len=0;
+  for(i=0;i<5;i++){
+    map* tmp=getMap(cconf->content,keywords[i]);
+    if(tmp!=NULL){
+      if(res==NULL){
+	res=(char*)malloc((strlen(keywords[i])+strlen(tmp->value)+4)*sizeof(char));
+	sprintf(res,"%s='%s'",keywords[i],tmp->value);
+	len+=strlen(res);
+      }else{
+	char* res1=(char*)malloc((strlen(keywords[i])+strlen(tmp->value)+5)*sizeof(char));
+	sprintf(res1," %s='%s'",keywords[i],tmp->value);
+	res=(char*)realloc(res,(len+strlen(keywords[i])+strlen(tmp->value)+5)*sizeof(char));
+	memcpy(res+len,res1,(strlen(keywords[i])+strlen(tmp->value)+5)*sizeof(char));
+	len+=strlen(res1);
+	res[len]=0;
+	free(res1);
+      }
+    }
+  }
+  map* tmp=getMap(cconf->content,"type");
+  if(tmp!=NULL){
+    char* fres=(char*)malloc((strlen(res)+strlen(tmp->value)+2)*sizeof(char));
+    sprintf(fres,"%s:%s",tmp->value,res);
+    free(res);
+    return fres;
+  }
+  return res;
+}
+
+/**
+ * Connect to the db backend.
+ * 
+ * @param conf the maps containing the setting of the main.cfg file
+ * @see createInitString
+ */
+void init_sql(maps* conf){
+  char* sqlInitString=createInitString(conf);
+  OGRSFDriver *poDriver = NULL;
+  OGRRegisterAll();
+  zoo_DS = OGRSFDriverRegistrar::Open(sqlInitString,false,&poDriver);
+  if( zoo_DS == NULL ){
+#ifdef DEBUG
+    fprintf(stderr,"sqlInitString: %s FAILED !\n",sqlInitString);
+    fflush(stderr);
+#endif
+    free(sqlInitString);
+    setMapInMaps(conf,"lenv","message","Failed to connect to the database backend");
+    return;
+  }
+#ifdef DEBUG
+  fprintf(stderr,"sqlInitString: %s SUCEED !\n",sqlInitString);
+  fflush(stderr);
+#endif
+  free(sqlInitString);
+}
+
+/**
+ * Close any connection to the db backend.
+ * 
+ * @param conf the maps containing the setting of the main.cfg file
+ */
+void close_sql(maps* conf){
+  if( zoo_ResultSet != NULL )
+    zoo_DS->ReleaseResultSet( zoo_ResultSet );
+  if(zoo_DS!=NULL){
+    OGRDataSource::DestroyDataSource( zoo_DS );
+    zoo_DS=NULL;
+  }
+}
+
+/**
+ * Call OGRCleanupAll.
+ * 
+ */
+void end_sql(){
+  OGRCleanupAll();
+}
+
+/**
+ * Execute a SQL query to the SQL Database Backend.
+ * 
+ * @param conf the maps containing the setting of the main.cfg file
+ * @param sqlQuery the SQL query to run
+ * @return -1 in case of failure and 1 if the query succeed.
+ */
+int execSql(maps* conf,const char* sqlQuery){
+  zoo_ResultSet = zoo_DS->ExecuteSQL( sqlQuery, NULL, NULL);
+  if( zoo_ResultSet != NULL ){
+    return 1;
+  }
+  return -1;
+}
+
+/**
+ * Clean any memory allocated by executing a request
+ * 
+ * @param conf the maps containing the setting of the main.cfg file
+ * @param sqlQuery the SQL query to run
+ * @return -1 in case of failure and 1 if the query succeed.
+ */
+void cleanUpResultSet(const maps* conf){
+  if( zoo_ResultSet != NULL ){
+    zoo_DS->ReleaseResultSet( zoo_ResultSet );
+    zoo_ResultSet=NULL;
+  }
+}
+
+/**
+ * Record a file stored during ZOO-Kernel execution
+ * 
+ * @param conf the maps containing the setting of the main.cfg file
+ * @param filename the file's name
+ * @param type the type (Intput,Output,Response)
+ * @param name the maps containing the setting of the main.cfg file
+ */
+void recordStoredFile(maps* conf,const char* filename,const char* type,const char* name){
+  map *uusid=getMapFromMaps(conf,"lenv","usid");
+  map *schema=getMapFromMaps(conf,"database","schema");
+  char *sqlQuery=(char*)malloc((strlen(schema->value)+strlen(uusid->value)+strlen(filename)+strlen(type)+(name!=NULL?strlen(name):2)+68+1)*sizeof(char));
+  if(name!=NULL)
+    sprintf(sqlQuery,"INSERT INTO %s.files (uuid,filename,nature,name) VALUES ('%s','%s','%s','%s');",schema->value,uusid->value,filename,type,name);
+  else
+    sprintf(sqlQuery,"INSERT INTO %s.files (uuid,filename,nature,name) VALUES ('%s','%s','%s',NULL);",schema->value,uusid->value,filename,type);
+  execSql(conf,sqlQuery);
+  free(sqlQuery);
+  cleanUpResultSet(conf);
+}
+
+/**
+ * Insert the reference tuple corresponding to the running service
+ * 
+ * @param conf the maps containing the setting of the main.cfg file
+ */
+void recordServiceStatus(maps* conf){
+  map *sid=getMapFromMaps(conf,"lenv","sid");
+  map *osid=getMapFromMaps(conf,"lenv","osid");
+  map *uusid=getMapFromMaps(conf,"lenv","usid");
+  map *schema=getMapFromMaps(conf,"database","schema");
+  char *sqlQuery=(char*)malloc((strlen(schema->value)+
+				strlen(uusid->value)+
+				strlen(osid->value)+
+				strlen(sid->value)+56+1)*sizeof(char));
+  sprintf(sqlQuery,
+	  "INSERT INTO %s.services (uuid,sid,osid)"
+	  "VALUES ('%s','%s','%s');",
+	  schema->value,
+	  uusid->value,sid->value,osid->value);
+  execSql(conf,sqlQuery);
+  free(sqlQuery);
+  cleanUpResultSet(conf);
+}
+
+/**
+ * Store the content of the result file
+ * 
+ * @param conf the maps containing the setting of the main.cfg file
+ * @param filename the file's name
+ */
+void recordResponse(maps* conf,char* filename){
+  FILE *file = fopen (filename, "rb");
+  fseek (file, 0, SEEK_END);
+  long flen = ftell (file);
+  fseek (file, 0, SEEK_SET);
+  char *tmps = (char *) malloc ((flen + 1) * sizeof (char));
+  fread (tmps, flen, 1, file);
+  tmps[flen]=0;
+  fclose(file);
+  map *sid=getMapFromMaps(conf,"lenv","usid");
+  map *schema=getMapFromMaps(conf,"database","schema");
+  char *sqlQuery=(char*)malloc((strlen(schema->value)+flen+strlen(sid->value)+51+1)*sizeof(char));
+  sprintf(sqlQuery,"INSERT INTO %s.responses (content,uuid) VALUES ($$%s$$,$$%s$$);",schema->value,tmps,sid->value);
+  execSql(conf,sqlQuery);
+  free(sqlQuery);
+  free(tmps);
+  cleanUpResultSet(conf);
+}
+
+/**
+ * Update the current status of the running service.
+ *
+ * @param conf the map containing the setting of the main.cfg file
+ * @return 0 on success, -2 if shmget failed, -1 if shmat failed
+ */
+int _updateStatus(maps* conf){
+  map *sid=getMapFromMaps(conf,"lenv","usid");
+  map *p=getMapFromMaps(conf,"lenv","status");
+  map *msg=getMapFromMaps(conf,"lenv","message");
+  map *schema=getMapFromMaps(conf,"database","schema");
+  char *sqlQuery=(char*)malloc((strlen(schema->value)+strlen(msg->value)+strlen(p->value)+strlen(sid->value)+64+1)*sizeof(char));
+  sprintf(sqlQuery,"UPDATE %s.services set status=$$%s$$,message=$$%s$$ where uuid=$$%s$$;",schema->value,p->value,msg->value,sid->value);
+  fflush(stderr);
+  if( zoo_DS == NULL )
+    init_sql(conf);
+  execSql(conf,sqlQuery);
+  cleanUpResultSet(conf);
+  free(sqlQuery);
+  return 0;
+}
+
+/**
+ * Get the ongoing status of a running service 
+ *
+ * @param conf the maps containing the setting of the main.cfg file
+ * @param pid the service identifier (usid key from the [lenv] section)
+ * @return the reported status char* (MESSAGE|POURCENTAGE)
+ */
+char* _getStatus(maps* conf,char* pid){
+  map *schema=getMapFromMaps(conf,"database","schema");
+  char *sqlQuery=(char*)malloc((strlen(schema->value)+strlen(pid)+58+1)*sizeof(char));
+  sprintf(sqlQuery,"select status||'|'||message from %s.services where uuid=$$%s$$;",schema->value,pid);
+  if( zoo_DS == NULL )
+    init_sql(conf);
+  execSql(conf,sqlQuery);
+  OGRFeature  *poFeature = NULL;
+  const char *tmp1;
+  while( (poFeature = zoo_ResultSet->GetNextFeature()) != NULL ){
+    for( int iField = 0; iField < poFeature->GetFieldCount(); iField++ ){
+      if( poFeature->IsFieldSet( iField ) ){
+	tmp1=strdup(poFeature->GetFieldAsString( iField ));
+      }
+      else
+	tmp1=NULL;
+    }
+    OGRFeature::DestroyFeature( poFeature );
+  }
+  cleanUpResultSet(conf);
+  free(sqlQuery);
+  return (char*)tmp1;
+}
+
+/**
+ * Read the cache file of a running service 
+ *
+ * @param conf the maps containing the setting of the main.cfg file
+ * @param pid the service identifier (usid key from the [lenv] section)
+ * @return the reported status char* (temporary/final result)
+ */
+char* _getStatusFile(maps* conf,char* pid){
+  map *schema=getMapFromMaps(conf,"database","schema");
+  char *sqlQuery=(char*)malloc((strlen(schema->value)+strlen(pid)+82+1)*sizeof(char));
+  sprintf(sqlQuery,
+	  "select content from %s.responses where uuid=$$%s$$"
+	  " order by creation_time desc limit 1",schema->value,pid);
+  if( zoo_DS == NULL )
+    init_sql(conf);
+  execSql(conf,sqlQuery);
+  OGRFeature  *poFeature = NULL;
+  const char *tmp1;
+  int hasRes=-1;
+  while( (poFeature = zoo_ResultSet->GetNextFeature()) != NULL ){
+    for( int iField = 0; iField < poFeature->GetFieldCount(); iField++ ){
+      if( poFeature->IsFieldSet( iField ) ){
+	tmp1=strdup(poFeature->GetFieldAsString( iField ));
+	hasRes=1;
+      }
+      else
+	tmp1=NULL;
+    }
+    OGRFeature::DestroyFeature( poFeature );
+  }
+  if(hasRes<0)
+    tmp1=NULL;
+  cleanUpResultSet(conf);
+  free(sqlQuery);
+  return (char*)tmp1;
+}
+
+/**
+ * Delete a service reference from the database.
+ *
+ * @param conf the map containing the setting of the main.cfg file
+ * @param pid the service identifier (usid key from the [lenv] section)
+ */
+void removeService(maps* conf,char* pid){
+  map *schema=getMapFromMaps(conf,"database","schema");
+  char *sqlQuery=(char*)
+    malloc((strlen(pid)+strlen(schema->value)+38+1)
+	   *sizeof(char));
+  if( zoo_DS == NULL )
+    init_sql(conf);
+  sprintf(sqlQuery,
+	  "DELETE FROM %s.services where uuid=$$%s$$;",
+	  schema->value,pid);
+  execSql(conf,sqlQuery);
+  cleanUpResultSet(conf);
+  close_sql(conf);
+  free(sqlQuery);
+  end_sql();
+}
+
+/**
+ * Stop handling status repport.
+ *
+ * @param conf the map containing the setting of the main.cfg file
+ */
+void unhandleStatus(maps* conf){
+  map *schema=getMapFromMaps(conf,"database","schema");
+  map *sid=getMapFromMaps(conf,"lenv","usid");
+  map *fstate=getMapFromMaps(conf,"lenv","fstate");
+  char *sqlQuery=(char*)malloc((strlen(sid->value)+
+				strlen(schema->value)+
+				(fstate!=NULL?
+				 strlen(fstate->value):
+				 6)
+				+66+1)*sizeof(char));
+  sprintf(sqlQuery,
+	  "UPDATE %s.services set end_time=now(), fstate=$$%s$$"
+	  " where uuid=$$%s$$;",
+	  schema->value,(fstate!=NULL?fstate->value:"Failed"),sid->value);
+  execSql(conf,sqlQuery);
+  cleanUpResultSet(conf);
+  close_sql(conf);
+  free(sqlQuery);
+  end_sql();
+}
+
+/**
+ * Read the sid identifier attached of a service if any
+ *
+ * @param conf the maps containing the setting of the main.cfg file
+ * @param pid the service identifier (usid key from the [lenv] section)
+ * @return the sid value
+ */
+char* getStatusId(maps* conf,char* pid){
+  map *schema=getMapFromMaps(conf,"database","schema");
+  char *sqlQuery=(char*)malloc((strlen(schema->value)+strlen(pid)+58+1)*sizeof(char));
+  sprintf(sqlQuery,
+	  "select osid from %s.services where uuid=$$%s$$",
+	  schema->value,pid);
+  if( zoo_DS == NULL )
+    init_sql(conf);
+  execSql(conf,sqlQuery);
+  OGRFeature  *poFeature = NULL;
+  const char *tmp1;
+  int hasRes=-1;
+  while( (poFeature = zoo_ResultSet->GetNextFeature()) != NULL ){
+    for( int iField = 0; iField < poFeature->GetFieldCount(); iField++ ){
+      if( poFeature->IsFieldSet( iField ) ){
+	tmp1=zStrdup(poFeature->GetFieldAsString( iField ));
+	hasRes=1;
+	break;
+      }
+    }
+    OGRFeature::DestroyFeature( poFeature );
+  }
+  if(hasRes<0)
+    tmp1=NULL;
+  free(sqlQuery);
+  return (char*)tmp1;
+}
+
+/**
+ * Read the Result file (.res).
+ *
+ * @param conf the maps containing the setting of the main.cfg file
+ * @param pid the service identifier (usid key from the [lenv] section)
+ */
+void readFinalRes(maps* conf,char* pid,map* statusInfo){
+  map *schema=getMapFromMaps(conf,"database","schema");
+  char *sqlQuery=(char*)malloc((strlen(schema->value)+strlen(pid)+58+1)*sizeof(char));
+  sprintf(sqlQuery,
+	  "select fstate from %s.services where uuid=$$%s$$",
+	  schema->value,pid);
+  if( zoo_DS == NULL )
+    init_sql(conf);
+  execSql(conf,sqlQuery);
+  OGRFeature  *poFeature = NULL;
+  int hasRes=-1;
+  while( (poFeature = zoo_ResultSet->GetNextFeature()) != NULL ){
+    for( int iField = 0; iField < poFeature->GetFieldCount(); iField++ ){
+      if( poFeature->IsFieldSet( iField ) ){
+	addToMap(statusInfo,"Status",poFeature->GetFieldAsString( iField ));
+	hasRes=1;
+	break;
+      }
+    }
+    OGRFeature::DestroyFeature( poFeature );
+  }
+  if(hasRes<0)
+    addToMap(statusInfo,"Status","Failed");
+  free(sqlQuery);
+  return;
+}
+
+/**
+ * Check if a service is running.
+ *
+ * @param conf the maps containing the setting of the main.cfg file
+ * @param pid the unique service identifier (usid from the lenv section)
+ * @return 1 in case the service is still running, 0 otherwise
+ */
+int isRunning(maps* conf,char* pid){
+  int res=0;
+  map *schema=getMapFromMaps(conf,"database","schema");
+  char *sqlQuery=(char*)malloc((strlen(schema->value)+strlen(pid)+73+1)*sizeof(char));
+  sprintf(sqlQuery,"select count(*) as t from %s.services where uuid=$$%s$$ and end_time is null;",schema->value,pid);
+  if( zoo_DS == NULL )
+    init_sql(conf);
+  execSql(conf,sqlQuery);
+  OGRFeature  *poFeature = NULL;
+  const char *tmp1;
+  while( (poFeature = zoo_ResultSet->GetNextFeature()) != NULL ){
+    for( int iField = 0; iField < poFeature->GetFieldCount(); iField++ ){
+      if( poFeature->IsFieldSet( iField ) && 
+	  atoi(poFeature->GetFieldAsString( iField ))>0 ){
+	res=1;
+	break;
+      }
+    }
+    OGRFeature::DestroyFeature( poFeature );
+  }
+  cleanUpResultSet(conf);
+  free(sqlQuery);
+  return res;
+}
+
+#endif
diff --git a/zoo-project/zoo-kernel/sqlapi.h b/zoo-project/zoo-kernel/sqlapi.h
new file mode 100644
index 0000000..3c5be38
--- /dev/null
+++ b/zoo-project/zoo-kernel/sqlapi.h
@@ -0,0 +1,51 @@
+/*
+ * Author : David Saggiorato
+ *
+ *  Copyright 2008-2009 GeoLabs SARL. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef ZOO_SQLAPI_H
+#define ZOO_SQLAPI_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef RELY_ON_DB
+#include "service.h"
+#include "service_internal.h"
+  ZOO_DLL_EXPORT void init_sql(maps*);
+  ZOO_DLL_EXPORT void close_sql(maps*);
+  ZOO_DLL_EXPORT int execSql(maps*,const char*);
+  ZOO_DLL_EXPORT void recordStoredFile(maps*,const char*,const char*,const char*);
+  ZOO_DLL_EXPORT void recordServiceStatus(maps*);
+  ZOO_DLL_EXPORT void recordResponse(maps*,char*);
+  ZOO_DLL_EXPORT void readFinalRes(maps*,char*,map*);
+  ZOO_DLL_EXPORT int isRunning(maps*,char*);
+  ZOO_DLL_EXPORT char* getStatusId(maps*,char*);
+  ZOO_DLL_EXPORT void removeService(maps*,char*);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/zoo-project/zoo-kernel/ulinet.c b/zoo-project/zoo-kernel/ulinet.c
new file mode 100644
index 0000000..2c4207b
--- /dev/null
+++ b/zoo-project/zoo-kernel/ulinet.c
@@ -0,0 +1,463 @@
+/*
+ *  ulinet.c
+ *
+ * Author : Gérald FENOY
+ *
+ * Copyright (c) 2008-2015 GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#define _ULINET
+#define MAX_WAIT_MSECS 180*1000 /* Wait max. 180 seconds */
+#include "ulinet.h"
+#include <assert.h>
+
+/**
+ * Write the downloaded content to a _HINTERNET structure
+ *
+ * @param buffer the buffer to read
+ * @param size size of each member
+ * @param nmemb number of element to read
+ * @param data the _HINTERNET structure to write in
+ * @return the size red, -1 if buffer is NULL
+ */
+size_t write_data_into(void *buffer, size_t size, size_t nmemb, void *data){
+  size_t realsize = size * nmemb;
+  _HINTERNET *psInternet;
+  if(buffer==NULL){
+    buffer=NULL;
+    return -1;
+  }
+  psInternet=(_HINTERNET *)data;
+  if(psInternet->pabyData){
+    psInternet->pabyData=(unsigned char*)realloc(psInternet->pabyData,psInternet->nDataLen+realsize+1);
+    psInternet->nDataAlloc+=psInternet->nDataLen+realsize+1;
+  }
+  else{
+    psInternet->pabyData=(unsigned char*)malloc(psInternet->nDataLen+realsize+1);
+    psInternet->nDataAlloc=realsize+1;
+  }
+
+  if (psInternet->pabyData) {
+    memcpy( psInternet->pabyData + psInternet->nDataLen, buffer, realsize);
+    psInternet->nDataLen += realsize;
+    psInternet->pabyData[psInternet->nDataLen] = 0;
+  }
+
+  buffer=NULL;
+  return realsize;
+}
+
+/**
+ * In case of presence of "Set-Cookie" in the headers red, store the cookie
+ * identifier in CCookie
+ *
+ * @param buffer the buffer to read
+ * @param size size of each member
+ * @param nmemb number of element to read
+ * @param data the _HINTERNET structure to write in
+ * @return the size red, -1 if buffer is NULL
+ * @see CCookie
+ */
+size_t header_write_data(void *buffer, size_t size, size_t nmemb, void *data){
+  if(strncmp("Set-Cookie: ",(char*)buffer,12)==0){
+    int i;
+    char env[256];
+    char path[256];
+    char domain[256];
+    char* tmp;
+    for(i=0;i<12;i++)
+#ifndef WIN32
+      buffer++;
+#else
+	;
+#endif
+    sscanf((char*)buffer,"%s; path=%s; domain=%s",env,path,domain);
+    tmp=strcat(env,CCookie[0]);
+#ifdef MSG_LAF_OUT
+    printf("\n**Cookie env : [%s] , path : [%s], domain : [%s]**\n",env,path,domain);
+    printf("buffer : %d (%s) (%s) (%s)\n",(buffer==NULL),buffer,tmp,CCookie);
+#endif
+    strcpy(CCookie[0],tmp);
+  }
+  return size * nmemb;//write_data_into(buffer,size,nmemb,data,HEADER);
+};
+
+/**
+ * Define the proxy to use for a CURL handler
+ * 
+ * @param handle the CURL handler
+ * @param host the proxy host (including http://)
+ * @param port the proxy port
+ */
+void setProxy(CURL* handle,char* host,long port){
+  char* proxyDef=(char*)malloc((strlen(host)+10+2)*sizeof(char));
+  sprintf(proxyDef,"%s:%ld",host,port);
+  curl_easy_setopt(handle,CURLOPT_PROXY,proxyDef);
+  free(proxyDef);
+}
+
+/**
+ * MACOSX
+ */
+#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__))
+
+
+char* CFStringToCString(CFStringRef dest,char *buffer){
+  CFStringEncoding encoding = kCFStringEncodingUTF8;
+  Boolean bool2 = CFStringGetCString(dest,buffer,1024,encoding);
+  if(bool2){
+    printf("Loaded into local_buffer");
+    return buffer;
+  }
+  return NULL;
+}
+
+OSStatus setProxiesForProtcol(CURL* handle,const char *proto){
+  OSStatus		err;
+  CFDictionaryRef proxyDict;
+  CFArrayRef		proxies;
+  
+  CFStringRef key_enabled = NULL;
+  CFStringRef key_host = NULL;
+  CFStringRef key_port = NULL;
+  
+  bool proxy_enabled;
+  char *proxy_host;
+  long proxy_port;
+  
+  proxyDict = NULL;
+  proxies = NULL;
+
+  err = noErr;
+  proxyDict = SCDynamicStoreCopyProxies(NULL);
+
+  if(strncmp(proto,"http",4)==0){
+      key_enabled=kSCPropNetProxiesHTTPEnable;
+      key_host=kSCPropNetProxiesHTTPProxy;
+      key_port=kSCPropNetProxiesHTTPPort;
+  }
+  else
+    if(strncmp(proto,"https",5)==0){
+      key_enabled=kSCPropNetProxiesHTTPSEnable;
+      key_host=kSCPropNetProxiesHTTPSProxy;
+      key_port=kSCPropNetProxiesHTTPSPort;
+    }
+
+  CFNumberGetValue(CFDictionaryGetValue(proxyDict,key_enabled),kCFNumberIntType,&proxy_enabled);
+  if(proxy_enabled){
+    CFNumberGetValue(CFDictionaryGetValue(proxyDict,key_port),CFNumberGetType(CFDictionaryGetValue(proxyDict,key_port)),&proxy_port);
+    char buffer[1024];
+    CFStringToCString(CFDictionaryGetValue(proxyDict,key_host),buffer);
+    proxy_host=buffer;
+
+#ifdef MSG_LAF_VERBOSE
+    printf("\n**[PROXY SETTINGS DETECTION %s (%d) %s:%li (%s)]**\n",proto,proxy_enabled,(char*)proxy_host,proxy_port,buffer);
+#endif
+
+    if (proxyDict == NULL) {
+      err = coreFoundationUnknownErr;
+    }
+
+    setProxy(handle,proxy_host,proxy_port);
+  }
+  return err;
+}
+#else
+/**
+ * Should autodetect the proxy configuration (do nothing on linux)
+ *
+ * @param handle a CURL handle
+ * @param proto the protocol requiring the use of a proxy
+ */
+bool setProxiesForProtcol(CURL* handle,const char *proto){
+#ifdef MSG_LAF_VERBOSE
+  fprintf( stderr, "setProxiesForProtocol (do nothing) ...\n" );
+#endif
+  return true;
+}
+#endif
+
+/**
+ * Create a HINTERNET
+ *
+ * @param lpszAgent the HTPP User-Agent to use to send requests
+ * @param  dwAccessType type of access required
+ * @param  lpszProxyName the name of the proxy server(s) to use 
+ * @param  lpszProxyBypass ip address or host names which should not be routed
+ *  through the proxy
+ * @param  dwFlags Options (INTERNET_FLAG_ASYNC,INTERNET_FLAG_FROM_CACHE,INTERNET_FLAG_OFFLINE)
+ * @return the created HINTERNET
+ */
+HINTERNET InternetOpen(char* lpszAgent,int dwAccessType,char* lpszProxyName,char* lpszProxyBypass,int dwFlags){
+  HINTERNET ret;
+  ret.handle=curl_multi_init();
+  ret.agent=strdup(lpszAgent);
+  ret.nb=0;
+  ret.ihandle[ret.nb].header=NULL;
+  return ret;
+}
+
+/**
+ * Close a HINTERNET connection and free allocated ressources
+ *
+ * @param handle0 the HINTERNET connection to close
+ */
+void InternetCloseHandle(HINTERNET* handle0){
+  int i=0;
+  for(i=0;i<handle0->nb;i++){
+    _HINTERNET handle=handle0->ihandle[i];
+    if(handle.hasCacheFile>0){
+      fclose(handle.file);
+      unlink(handle.filename);
+    }
+    else{
+      handle.pabyData = NULL;
+      handle.nDataAlloc = handle.nDataLen = 0;
+    }
+    if(handle0->ihandle[i].header!=NULL){
+      curl_slist_free_all(handle0->ihandle[i].header);
+      handle0->ihandle[i].header=NULL;
+    }
+    if(handle.post!=NULL)
+      free(handle.post);
+    free(handle.mimeType);
+    handle.mimeType = NULL;
+  }
+  if(handle0->handle)
+    curl_multi_cleanup(handle0->handle);
+  free(handle0->agent);
+  for(i=handle0->nb-1;i>=0;i--){
+    free(handle0->waitingRequests[i]);
+  }
+}
+
+/**
+ * Create a new element in the download queue
+ *
+ * @param hInternet the HINTERNET connection to add the download link
+ * @param lpszUrl the url to download
+ * @param lpszHeaders the additional headers to be sent to the HTTP server
+ * @param dwHeadersLength the size of the additional headers
+ * @param dwFlags desired download mode (INTERNET_FLAG_NO_CACHE_WRITE for not using cache file)
+ * @param dwContext not used
+ */
+HINTERNET InternetOpenUrl(HINTERNET* hInternet,LPCTSTR lpszUrl,LPCTSTR lpszHeaders,size_t dwHeadersLength,size_t dwFlags,size_t dwContext){
+
+  char filename[255];
+  struct MemoryStruct header;
+
+  hInternet->ihandle[hInternet->nb].handle=curl_easy_init( );
+  hInternet->ihandle[hInternet->nb].hasCacheFile=0;
+  hInternet->ihandle[hInternet->nb].nDataAlloc = 0;
+  hInternet->ihandle[hInternet->nb].mimeType = NULL;
+  hInternet->ihandle[hInternet->nb].nDataLen = 0;
+  hInternet->ihandle[hInternet->nb].id = hInternet->nb;
+  hInternet->ihandle[hInternet->nb].nDataAlloc = 0;
+  hInternet->ihandle[hInternet->nb].pabyData = NULL;
+  hInternet->ihandle[hInternet->nb].post = NULL;
+
+  curl_easy_setopt(hInternet->ihandle[hInternet->nb].handle, CURLOPT_COOKIEFILE, "ALL");
+#ifndef TIGER
+  curl_easy_setopt(hInternet->ihandle[hInternet->nb].handle, CURLOPT_COOKIELIST, "ALL");
+#endif
+  curl_easy_setopt(hInternet->ihandle[hInternet->nb].handle, CURLOPT_USERAGENT, hInternet->agent);
+  
+  curl_easy_setopt(hInternet->ihandle[hInternet->nb].handle,CURLOPT_FOLLOWLOCATION,1);
+  curl_easy_setopt(hInternet->ihandle[hInternet->nb].handle,CURLOPT_MAXREDIRS,3);
+  
+  header.memory=NULL;
+  header.size = 0;
+
+  curl_easy_setopt(hInternet->ihandle[hInternet->nb].handle, CURLOPT_HEADERFUNCTION, header_write_data);
+  curl_easy_setopt(hInternet->ihandle[hInternet->nb].handle, CURLOPT_WRITEHEADER, (void *)&header);
+
+#ifdef MSG_LAF_VERBOSE
+  curl_easy_setopt(hInternet->ihandle[hInternet->nb].handle, CURLOPT_VERBOSE, 1);
+#endif
+
+      
+  switch(dwFlags)
+    {
+    case INTERNET_FLAG_NO_CACHE_WRITE:
+      hInternet->ihandle[hInternet->nb].hasCacheFile=-1;
+      curl_easy_setopt(hInternet->ihandle[hInternet->nb].handle, CURLOPT_WRITEFUNCTION, write_data_into);
+      curl_easy_setopt(hInternet->ihandle[hInternet->nb].handle, CURLOPT_WRITEDATA, (void*)&hInternet->ihandle[hInternet->nb]);
+      break;
+    default:
+      sprintf(hInternet->ihandle[hInternet->nb].filename,"/tmp/ZOO_Cache%d",(int)time(NULL));
+      hInternet->ihandle[hInternet->nb].filename[24]=0;
+#ifdef MSG_LAF_VERBOSE
+      fprintf(stderr,"file=%s",hInternet->ihandle[hInternet->nb].filename);
+#endif
+      hInternet->ihandle[hInternet->nb].filename=filename;
+      hInternet->ihandle[hInternet->nb].file=fopen(hInternet->ihandle[hInternet->nb].filename,"w+");
+    
+      hInternet->ihandle[hInternet->nb].hasCacheFile=1;
+      curl_easy_setopt(hInternet->ihandle[hInternet->nb].handle, CURLOPT_WRITEFUNCTION, NULL);
+      curl_easy_setopt(hInternet->ihandle[hInternet->nb].handle, CURLOPT_WRITEDATA, hInternet->ihandle[hInternet->nb].file);
+      hInternet->ihandle[hInternet->nb].nDataLen=0;
+      break;
+    }
+#ifdef ULINET_DEBUG
+  fprintf(stderr,"URL (%s)\nBODY (%s)\n",lpszUrl,lpszHeaders);
+#endif
+  if(lpszHeaders!=NULL && strlen(lpszHeaders)>0){
+#ifdef MSG_LAF_VERBOSE
+    fprintf(stderr,"FROM ULINET !!");
+    fprintf(stderr,"HEADER : [%s] %d\n",lpszHeaders,dwHeadersLength);
+#endif
+    curl_easy_setopt(hInternet->ihandle[hInternet->nb].handle,CURLOPT_POST,1);
+#ifdef ULINET_DEBUG
+    fprintf(stderr,"** (%s) %d **\n",lpszHeaders,dwHeadersLength);
+    curl_easy_setopt(hInternet->ihandle[hInternet->nb].handle,CURLOPT_VERBOSE,1);
+#endif
+    hInternet->ihandle[hInternet->nb].post=strdup(lpszHeaders);
+    curl_easy_setopt(hInternet->ihandle[hInternet->nb].handle,CURLOPT_POSTFIELDS,hInternet->ihandle[hInternet->nb].post);
+    curl_easy_setopt(hInternet->ihandle[hInternet->nb].handle,CURLOPT_POSTFIELDSIZE,(long)dwHeadersLength);
+  }
+  if(hInternet->ihandle[hInternet->nb].header!=NULL)
+    curl_easy_setopt(hInternet->ihandle[hInternet->nb].handle,CURLOPT_HTTPHEADER,hInternet->ihandle[hInternet->nb].header);
+
+  curl_easy_setopt(hInternet->ihandle[hInternet->nb].handle,CURLOPT_URL,lpszUrl);
+
+  curl_multi_add_handle(hInternet->handle,hInternet->ihandle[hInternet->nb].handle);
+  
+  hInternet->ihandle[hInternet->nb].header=NULL;
+  ++hInternet->nb;
+
+#ifdef ULINET_DEBUG
+  fprintf(stderr,"DEBUG MIMETYPE: %s\n",hInternet.mimeType);
+  fflush(stderr);
+#endif
+  return *hInternet;
+};
+
+/**
+ * Download all opened urls in the queue
+ *
+ * @param hInternet the HINTERNET structure containing the queue
+ * @return 0
+ */
+int processDownloads(HINTERNET* hInternet){
+  int still_running=0;
+  int msgs_left=0;
+  int i=0;
+  do{
+    curl_multi_perform(hInternet->handle, &still_running);
+  }while(still_running);  
+  for(i=0;i<hInternet->nb;i++){
+    char *tmp;
+    curl_easy_getinfo(hInternet->ihandle[i].handle,CURLINFO_CONTENT_TYPE,&tmp);
+    if(tmp!=NULL)
+      hInternet->ihandle[i].mimeType=strdup(tmp);
+    curl_easy_getinfo(hInternet->ihandle[i].handle,CURLINFO_RESPONSE_CODE,&hInternet->ihandle[i].code);
+    curl_multi_remove_handle(hInternet->handle, hInternet->ihandle[i].handle);
+    curl_easy_cleanup(hInternet->ihandle[i].handle);
+  }
+  return 0;
+}
+
+/**
+ * Initialize the CCookie for a specific index (hInternet.nb)
+ *
+ * @param hInternet the HINTERNET structure to know the CCookie index to reset
+ * @return 1
+ * @see HINTERNET
+ */
+int freeCookieList(HINTERNET hInternet){
+  memset(&CCookie[hInternet.nb][0],0,1024);
+#ifndef TIGER
+  curl_easy_setopt(hInternet.ihandle[hInternet.nb].handle, CURLOPT_COOKIELIST, "ALL");
+#endif
+  return 1;
+}
+
+/**
+ * Copy a downloaded content
+ * 
+ * @param hInternet the _HINTERNET structure
+ * @param lpBuffer the memory space to copy the downloaded content
+ * @param dwNumberOfBytesToRead the size of lpBuffer
+ * @param lpdwNumberOfBytesRead number of bytes red
+ * @return 1 on success, 0 if failure
+ */
+int InternetReadFile(_HINTERNET hInternet,LPVOID lpBuffer,int dwNumberOfBytesToRead, size_t *lpdwNumberOfBytesRead){
+  int dwDataSize;
+
+  if(hInternet.hasCacheFile>0){
+    fseek (hInternet.file , 0 , SEEK_END);
+    dwDataSize=ftell(hInternet.file); //taille du ficher
+    rewind (hInternet.file);
+  }
+  else{
+    memset(lpBuffer,0,hInternet.nDataLen+1);
+    memcpy(lpBuffer, hInternet.pabyData, hInternet.nDataLen );
+    dwDataSize=hInternet.nDataLen;
+    free( hInternet.pabyData );
+    hInternet.pabyData=NULL;
+  }
+
+  if( dwNumberOfBytesToRead /* buffer size */ < dwDataSize )
+    return 0;
+
+#ifdef MSG_LAF_VERBOSE
+  printf("\nfile size : %dko\n",dwDataSize/1024);
+#endif
+
+  if(hInternet.hasCacheFile>0){
+    *lpdwNumberOfBytesRead = fread(lpBuffer,1,dwDataSize,hInternet.file); 
+  }
+  else{
+    *lpdwNumberOfBytesRead = hInternet.nDataLen;
+    free( hInternet.pabyData );
+    hInternet.pabyData = NULL;
+    hInternet.nDataAlloc = hInternet.nDataLen = 0;
+  }
+
+  CCookie[hInternet.id][0]=0;
+
+  if( *lpdwNumberOfBytesRead < dwDataSize )
+      return 0;
+  else
+      return 1; // TRUE
+}
+
+
+/**
+ * Use basic authentication for accessing a ressource
+ * 
+ * @param hInternet the _HINTERNET structure
+ * @param login the login to use to authenticate
+ * @param passwd the password to use to authenticate
+ */
+int setBasicAuth(HINTERNET hInternet,char* login,char* passwd){
+  char *tmp;
+  tmp=(char*)malloc((strlen(login)+strlen(passwd)+2)*sizeof(char));
+  sprintf(tmp,"%s:%s",login,passwd);
+  if(curl_easy_setopt(hInternet.ihandle[hInternet.nb].handle,CURLOPT_USERPWD,tmp)==CURLE_OUT_OF_MEMORY){
+    free(tmp);
+    return -1;
+  }
+  curl_easy_setopt(hInternet.ihandle[hInternet.nb].handle, CURLOPT_HTTPAUTH,CURLAUTH_ANY);
+  free(tmp);
+  return 0;
+}
diff --git a/zoo-project/zoo-kernel/ulinet.h b/zoo-project/zoo-kernel/ulinet.h
new file mode 100644
index 0000000..0614dcd
--- /dev/null
+++ b/zoo-project/zoo-kernel/ulinet.h
@@ -0,0 +1,176 @@
+/*
+ * Author : Gérald FENOY
+ *
+ *  Copyright 2008-2009 GeoLabs SARL. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef _ULINET_H
+#define _ULINET_H
+
+#include "fcgi_stdio.h"
+#include <stdlib.h>
+#include <fcntl.h>
+#include <curl/curl.h>
+#ifndef WIN32
+#include <unistd.h>
+#endif
+#include <string.h>
+#include "time.h"
+#ifdef USE_JS
+#ifdef WIN32
+#define XP_WIN 1
+#else
+#define XP_UNIX 0
+#endif
+#include "jsapi.h"
+#endif
+#ifndef bool
+#define bool int
+#endif
+#ifndef true
+#define true 1
+#define false 0
+#endif
+
+#define MAX_REQ 50
+
+#ifdef _ULINET
+static char CCookie[MAX_REQ][1024];
+#else
+/**
+ * The cookies found
+ */
+extern char CCookie[MAX_REQ][1024];
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+  /**
+   * Headers storage
+   * @see header_write_data
+   */
+  struct MemoryStruct {
+    char *memory; //!< the memory space to store data 
+    size_t size; //!< size of the memory space
+  };
+
+  /**
+   * Individual CURL handler
+   */
+  typedef struct {
+    CURL *handle; //!< the CURL handler
+    struct curl_slist *header; //!< the headers to send
+    char* filename; //!< the cached file name
+    FILE* file; //!< the file pointer
+    unsigned char *pabyData; //!< the downloaded content
+    char *mimeType; //!< the mimeType returned by the server
+    char *post; //!< the potential POST XML content
+    int hasCacheFile; //!< 1 if we used a cache file
+    int nDataLen; //!< the length of the downloaded content
+    int nDataAlloc; //!< 
+    long code; //!< the last received response code
+    int id; //!< The position of the element in the queue
+  } _HINTERNET;
+
+  /**
+   * Multiple CURL handlers
+   */
+  typedef struct {
+    CURLM *handle; //!< the CURLM handler
+    _HINTERNET ihandle[MAX_REQ]; //!< individual handlers in the queue 
+    char *waitingRequests[MAX_REQ]; //!< request in the queue
+    char *agent; //!< The User-Agent to use for HTTP request
+    int nb; //!< number of element in the queue 
+  } HINTERNET;
+
+  size_t write_data_into(void*,size_t,size_t,void*);
+
+  size_t header_write_data(void*,size_t,size_t,void*);
+
+  void setProxy(CURL*,char*,long);
+
+#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__))
+
+#include <CoreServices/CoreServices.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+  char* CFStringToCString(CFStringRef,char*);
+  OSStatus setProxiesForProtcol(CURL*,const char*);
+
+#else
+
+//#include <gconf/gconf-client.h>
+  int setProxiesForProtcol(CURL*,const char*);
+
+#endif
+
+
+#define INTERNET_OPEN_TYPE_DIRECT                      0
+#define INTERNET_OPEN_TYPE_PRECONFIG                   1
+#define INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY 2
+#define INTERNET_OPEN_TYPE_PROXY                       3
+#ifndef WIN32
+typedef char* LPCTSTR;
+#endif
+  HINTERNET InternetOpen(char*,int,char*,char*,int);
+
+  void InternetCloseHandle(HINTERNET*);
+
+#define INTERNET_FLAG_EXISTING_CONNECT         0
+#define INTERNET_FLAG_HYPERLINK                1
+#define INTERNET_FLAG_IGNORE_CERT_CN_INVALID   2
+#define INTERNET_FLAG_IGNORE_CERT_DATE_INVALID 3
+#define INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP  4
+#define INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS 5
+#define INTERNET_FLAG_KEEP_CONNECTION          6
+#define INTERNET_FLAG_NEED_FILE                7
+#define INTERNET_FLAG_NO_AUTH                  8
+#define INTERNET_FLAG_NO_AUTO_REDIRECT         9
+#define INTERNET_FLAG_NO_CACHE_WRITE          10
+//typedef char* LPVOID;
+#ifndef WIN32
+  typedef void* LPVOID;
+  typedef void* LPTSTR;
+  typedef size_t* LPDWORD;
+#endif
+#ifndef bool
+#define bool int
+#endif
+
+#  define CHECK_INET_HANDLE(h) (h.handle != 0)
+
+  HINTERNET InternetOpenUrl(HINTERNET*,LPCTSTR,LPCTSTR,size_t,size_t,size_t);
+
+  int processDownloads(HINTERNET*);
+
+  int freeCookieList(HINTERNET);
+
+  int InternetReadFile(_HINTERNET,LPVOID,int,size_t*);
+
+  int setBasicAuth(HINTERNET,char*,char*);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/zoo-project/zoo-kernel/zcfg2yaml b/zoo-project/zoo-kernel/zcfg2yaml
new file mode 100755
index 0000000..2c9d418
Binary files /dev/null and b/zoo-project/zoo-kernel/zcfg2yaml differ
diff --git a/zoo-project/zoo-kernel/zcfg2yaml.c b/zoo-project/zoo-kernel/zcfg2yaml.c
new file mode 100644
index 0000000..005cc3d
--- /dev/null
+++ b/zoo-project/zoo-kernel/zcfg2yaml.c
@@ -0,0 +1,44 @@
+/**
+ * Author : Gérald FENOY
+ *
+ *  Copyright 2014 GeoLabs SARL. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "server_internal.h"
+#include "response_print.h"
+#include "service.h"
+
+extern   int getServiceFromFile(maps*,const char*,service**);
+
+int main(int argc, char** argv){
+  service* s1=NULL;
+  maps *m=NULL;
+  char conf_file[1024];
+  snprintf(conf_file,1024,"%s",argv[1]);
+  s1=(service*)malloc(SERVICE_SIZE);
+  if(s1 == NULL){ 
+    return errorException(m, _("Unable to allocate memory"),"InternalError",NULL);
+  }
+  int t=getServiceFromFile(m,conf_file,&s1);
+  if(t>=0)
+    dumpServiceAsYAML(s1);
+  return 0;
+}
diff --git a/zoo-project/zoo-kernel/zoo_loader.c b/zoo-project/zoo-kernel/zoo_loader.c
new file mode 100644
index 0000000..204909f
--- /dev/null
+++ b/zoo-project/zoo-kernel/zoo_loader.c
@@ -0,0 +1,410 @@
+/*
+ * Author : Gérald FENOY
+ *
+ *  Copyright 2008-2011 GeoLabs SARL. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#define MALLOC_CHECK_ 0
+#define MALLOC_CHECK 0
+
+/**
+ * Specific includes
+ */
+#include "fcgio.h"
+#include "fcgi_config.h" 
+#include "fcgi_stdio.h"
+#include <sys/types.h>
+#include <unistd.h>
+#include "service_internal.h"
+#include "response_print.h"
+
+extern "C" {
+#include "cgic.h"
+#include <libxml/tree.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+}
+
+#ifdef WIN32
+#include "windows.h"
+#define strtok_r strtok_s
+#endif
+
+#include "service_internal.h"
+#include "request_parser.h"
+
+int runRequest(map**);
+
+using namespace std;
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE -1
+#endif
+
+/**
+ * Main entry point for cgic.
+ * @return 0 on sucess.
+ */
+int cgiMain(){
+  /**
+   * We'll use cgiOut as the default output (stdout) to produce plain text 
+   * response.
+   */
+  dup2(fileno(cgiOut),fileno(stdout));
+#ifdef DEBUG
+  fprintf(cgiOut,"Content-Type: text/plain; charset=utf-8\r\nStatus: 200 OK\r\n\r\n");
+  fprintf(cgiOut,"Welcome on ZOO verbose debuging mode \r\n\r\n");
+  fflush(cgiOut);
+  fprintf (stderr, "Addr:%s\n", cgiRemoteAddr); 
+  fprintf (stderr, "RequestMethod: (%s) %d %d\n", cgiRequestMethod,strncasecmp(cgiRequestMethod,"post",4),strncmp(cgiContentType,"text/xml",8)==0 || strncasecmp(cgiRequestMethod,"post",4)==0); 
+  fprintf (stderr, "Request: %s\n", cgiQueryString);
+  fprintf (stderr, "ContentType: %s\n", cgiContentType);
+  fprintf (stderr, "ContentLength: %d\n", cgiContentLength);
+  fflush(stderr);
+#endif
+  
+  char *strQuery=NULL;
+  if(cgiQueryString!=NULL)
+    strQuery=zStrdup(cgiQueryString);
+  map* tmpMap=NULL;
+
+  if(strncmp(cgiContentType,"text/xml",8)==0 || 
+     strncasecmp(cgiRequestMethod,"post",4)==0){
+    if(cgiContentLength==0){
+       char *buffer=new char[2];
+       char *res=NULL;
+       int r=0;
+       while((r=fread(buffer,sizeof(char),1,cgiIn))){
+	 buffer[1]=0;
+	 if(res==NULL){
+	   res=(char*)malloc(2*sizeof(char));
+	   sprintf(res,"%s",buffer);
+	 }
+	 else{
+	   res=(char*)realloc(res,(cgiContentLength+2)*sizeof(char));
+	   memcpy(res + cgiContentLength, buffer, sizeof(char));
+	   res[cgiContentLength+1]=0;
+	 }
+	 cgiContentLength+=r;
+       }
+       delete[] buffer;
+       if(res!=NULL && (strQuery==NULL || strlen(strQuery)==0))
+	 tmpMap=createMap("request",res);
+       if(res!=NULL)
+	 free(res);
+    }else{
+      char *buffer=new char[cgiContentLength+1];
+      if(fread(buffer,sizeof(char),cgiContentLength,cgiIn)>0){
+	buffer[cgiContentLength]=0;
+	tmpMap=createMap("request",buffer);
+      }else{
+	buffer[0]=0;
+	char **array, **arrayStep;
+	if (cgiFormEntries(&array) != cgiFormSuccess) {
+	  return 1;
+	}
+	arrayStep = array;
+	while (*arrayStep) {
+	  char *ivalue=new char[cgiContentLength];
+	  cgiFormStringNoNewlines(*arrayStep, ivalue, cgiContentLength);
+	  char* tmpValueFinal=(char*) malloc((strlen(*arrayStep)+strlen(ivalue)+2)*sizeof(char));	
+	  sprintf(tmpValueFinal,"%s=%s",*arrayStep,ivalue);
+
+	  if(strlen(buffer)==0){		
+	    sprintf(buffer,"%s",tmpValueFinal);
+	  }else{		
+	    char *tmp=zStrdup(buffer);
+	    sprintf(buffer,"%s&%s",tmp,tmpValueFinal);
+	    free(tmp);
+	  }	  
+	  free(tmpValueFinal);
+#ifdef DEBUG
+	  fprintf(stderr,"(( \n %s \n %s \n ))",*arrayStep,ivalue);
+#endif
+	  delete[]ivalue;
+	  arrayStep++;
+	}	
+	if(tmpMap!=NULL)
+	  addToMap(tmpMap,"request",buffer);
+	else
+	  tmpMap=createMap("request",buffer);
+      }
+      delete[]buffer;
+    }	
+  }
+  else{
+#ifdef DEBUG
+    dumpMap(tmpMap);
+#endif
+    char **array, **arrayStep;
+    if (cgiFormEntries(&array) != cgiFormSuccess) {
+      return 1;
+    }
+    arrayStep = array;
+    while (*arrayStep) {
+      char *value=new char[cgiContentLength];
+      cgiFormStringNoNewlines(*arrayStep, value, cgiContentLength);
+#ifdef DEBUG
+      fprintf(stderr,"(( \n %s \n %s \n ))",*arrayStep,value);
+#endif
+      if(tmpMap!=NULL)
+        addToMap(tmpMap,*arrayStep,value);
+      else
+        tmpMap=createMap(*arrayStep,value);
+      arrayStep++;
+      delete[]value;
+    }
+    cgiStringArrayFree(array);
+  }
+
+#ifdef WIN32
+  map *tmpReq=getMap(tmpMap,"rfile");
+  if(tmpReq!=NULL){
+    FILE *lf=fopen(tmpReq->value,"r");
+    fseek(lf,0,SEEK_END);
+    long flen=ftell(lf);
+    fseek(lf,0,SEEK_SET);
+    char *buffer=(char*)malloc((flen+1)*sizeof(char));
+    fread(buffer,flen,1,lf);
+    char *pchr=strrchr(buffer,'>');
+    cgiContentLength=strlen(buffer)-strlen(pchr)+1;
+    buffer[cgiContentLength]=0;
+    fclose(lf);
+    addToMap(tmpMap,"request",buffer);
+    free(buffer);
+  }
+#endif
+  /**
+   * In case that the POST method was used, then check if params came in XML
+   * format else try to use the attribute "request" which should be the only 
+   * one.
+   */
+  if(strncasecmp(cgiRequestMethod,"post",4)==0 || 
+     (count(tmpMap)==1 && strncmp(tmpMap->value,"<",1)==0) 
+#ifdef WIN32
+     ||tmpReq!=NULL
+#endif
+     ){
+    /**
+     * Store the original XML request in xrequest map
+     */
+    map* t1=getMap(tmpMap,"request");
+    if(t1!=NULL && strncasecmp(t1->value,"<",1)==0) {
+      addToMap(tmpMap,"xrequest",t1->value);
+      xmlInitParser();
+      xmlDocPtr doc = xmlParseMemory(t1->value,cgiContentLength);
+      {
+	xmlXPathObjectPtr reqptr=extractFromDoc(doc,"/*[local-name()='Envelope']/*[local-name()='Body']/*");
+	if(reqptr!=NULL){
+	  xmlNodeSet* req=reqptr->nodesetval;
+	  if(req!=NULL && req->nodeNr==1){
+	    addToMap(tmpMap,"soap","true");
+	    for(int k=0;k < req->nodeNr;k++){
+	      xmlDocSetRootElement(doc, req->nodeTab[k]);
+	      xmlChar *xmlbuff;
+	      int buffersize;
+	      xmlDocDumpFormatMemoryEnc(doc, &xmlbuff, &buffersize, "utf-8", 1);
+	      addToMap(tmpMap,"xrequest",(char*)xmlbuff);
+	      xmlFree(xmlbuff);
+	    }
+	  }
+	  xmlXPathFreeObject(reqptr);
+	}
+      }
+
+      xmlNodePtr cur = xmlDocGetRootElement(doc);
+      char *tval;
+      tval=NULL;
+      tval = (char*) xmlGetProp(cur,BAD_CAST "service");
+      if(tval!=NULL){
+	addToMap(tmpMap,"service",tval);
+	xmlFree(tval);
+      }
+      tval=NULL;
+      tval = (char*) xmlGetProp(cur,BAD_CAST "language");
+      if(tval!=NULL){
+	addToMap(tmpMap,"language",tval);
+	xmlFree(tval);
+      }
+      const char* requests[6]={"GetCapabilities","DescribeProcess","Execute","GetStatus","GetResult","Dismiss"};
+      for(int j=0;j<6;j++){
+	char tt[128];
+	sprintf(tt,"/*[local-name()='%s']",requests[j]);
+	xmlXPathObjectPtr reqptr=extractFromDoc(doc,tt);
+	if(reqptr!=NULL){
+	  xmlNodeSet* req=reqptr->nodesetval;
+#ifdef DEBUG
+	  fprintf(stderr,"%i",req->nodeNr);
+#endif
+	  if(req!=NULL && req->nodeNr==1){
+	    if(t1->value!=NULL)
+	      free(t1->value);
+	    t1->value=zStrdup(requests[j]);
+	    j=5;
+	  }
+	  xmlXPathFreeObject(reqptr);
+	}
+      }
+      if(strncasecmp(t1->value,"GetCapabilities",15)==0){
+	xmlXPathObjectPtr versptr=extractFromDoc(doc,"/*/*/*[local-name()='Version']");
+	xmlNodeSet* vers=versptr->nodesetval;
+	if(vers!=NULL && vers->nodeTab!=NULL && vers->nodeTab[0]!=NULL){
+	  xmlChar* content=xmlNodeListGetString(doc, vers->nodeTab[0]->xmlChildrenNode,1);
+	  addToMap(tmpMap,"version",(char*)content);
+	  xmlFree(content);
+	}
+	if(cur->ns){
+	  addToMap(tmpMap,"wps_schemas",(char*)cur->ns->href);
+	  int j=0;
+	  for(j=0;j<2;j++)
+	    if(strncasecmp(schemas[j][2],(char*)cur->ns->href,strlen(schemas[j][2]))==0){
+	      char vers[6];
+	      sprintf(vers,"%d.0.0",j+1);
+	      addToMap(tmpMap,"version",(char*)vers);
+	    }
+	}
+	xmlXPathFreeObject(versptr);
+      }else{
+	tval=NULL;
+	tval = (char*) xmlGetProp(cur,BAD_CAST "version");
+	if(tval!=NULL){
+	  addToMap(tmpMap,"version",tval);
+	  xmlFree(tval);
+	}
+	tval = (char*) xmlGetProp(cur,BAD_CAST "language");
+	if(tval!=NULL){
+	  addToMap(tmpMap,"language",tval);
+	  xmlFree(tval);
+	}
+	xmlXPathObjectPtr idptr=extractFromDoc(doc,"/*/*[local-name()='Identifier']");
+	if(idptr!=NULL){
+	  xmlNodeSet* id=idptr->nodesetval;
+	  if(id!=NULL){
+	    char* identifiers=NULL;
+	    identifiers=(char*)calloc(cgiContentLength,sizeof(char));
+	    identifiers[0]=0;
+	    for(int k=0;k<id->nodeNr;k++){
+	      xmlChar* content=xmlNodeListGetString(doc, id->nodeTab[k]->xmlChildrenNode,1);
+	      if(strlen(identifiers)>0){
+		char *tmp=zStrdup(identifiers);
+		snprintf(identifiers,strlen(tmp)+xmlStrlen(content)+2,"%s,%s",tmp,content);
+		free(tmp);
+	      }
+	      else{
+		snprintf(identifiers,xmlStrlen(content)+1,"%s",content);
+	      }
+	      xmlFree(content);
+	    }
+	    xmlXPathFreeObject(idptr);
+	    if(identifiers[0]!=0)
+	      addToMap(tmpMap,"Identifier",identifiers);
+	    free(identifiers);
+	  }
+	}
+	if(getMap(tmpMap,"Identifier")==NULL){
+	  idptr=extractFromDoc(doc,"/*/*[local-name()='JobID']");
+	  if(idptr!=NULL){
+	    xmlNodeSet* id=idptr->nodesetval;
+	    if(id!=NULL){
+	      char* identifiers=NULL;
+	      identifiers=(char*)calloc(cgiContentLength,sizeof(char));
+	      identifiers[0]=0;
+	      for(int k=0;k<id->nodeNr;k++){
+		  xmlChar* content=xmlNodeListGetString(doc, id->nodeTab[k]->xmlChildrenNode,1);
+		  if(strlen(identifiers)>0){
+		    char *tmp=zStrdup(identifiers);
+		    snprintf(identifiers,strlen(tmp)+xmlStrlen(content)+2,"%s,%s",tmp,content);
+		    free(tmp);
+		  }
+		  else{
+		    snprintf(identifiers,xmlStrlen(content)+1,"%s",content);
+		  }
+		  xmlFree(content);
+	      }
+	      xmlXPathFreeObject(idptr);
+	      if(identifiers[0]!=0)
+		addToMap(tmpMap,"JobID",identifiers);
+	      free(identifiers);
+	    }
+	  }
+	}
+      }
+      xmlFreeDoc(doc);
+      xmlCleanupParser();
+    }else{
+      freeMap(&tmpMap);
+      free(tmpMap);
+      tmpMap=createMap("not_valid","true");
+    }
+
+    char *token,*saveptr;
+    token=strtok_r(cgiQueryString,"&",&saveptr);
+    while(token!=NULL){
+      char *token1,*saveptr1;
+      char *name=NULL;
+      char *value=NULL;
+      token1=strtok_r(token,"=",&saveptr1);
+      while(token1!=NULL){
+        if(name==NULL)
+          name=zStrdup(token1);
+        else
+          value=zStrdup(token1);
+        token1=strtok_r(NULL,"=",&saveptr1);
+      }	  
+      //addToMap(tmpMap,name,value);
+      /* knut: strtok(_r) ignores delimiter bytes at start and end of string; 
+       * it will return non-empty string or NULL, e.g. "metapath=" yields value=NULL.
+       * This modification sets value="" instead of NULL.
+       */
+      addToMap(tmpMap,name, value != NULL ? value : "");
+      free(name);
+      free(value);
+      name=NULL;
+      value=NULL;
+      token=strtok_r(NULL,"&",&saveptr);
+    }
+    
+  }
+
+  if(strncasecmp(cgiContentType,"multipart/form-data",19)==0){
+    map* tmp=getMap(tmpMap,"dataInputs");
+    if(tmp!=NULL){
+      addToMap(tmpMap,"dataInputs",strstr(strQuery,"dataInputs=")+11);
+    }
+  }
+
+  if(strQuery!=NULL)
+    free(strQuery);
+
+  runRequest(&tmpMap);
+
+  if(tmpMap!=NULL){
+    freeMap(&tmpMap);
+    free(tmpMap);
+  }
+  return 0;
+
+}
diff --git a/zoo-project/zoo-kernel/zoo_loader.cgi b/zoo-project/zoo-kernel/zoo_loader.cgi
new file mode 100755
index 0000000..75b64e8
Binary files /dev/null and b/zoo-project/zoo-kernel/zoo_loader.cgi differ
diff --git a/zoo-project/zoo-kernel/zoo_service_loader.c b/zoo-project/zoo-kernel/zoo_service_loader.c
new file mode 100644
index 0000000..cb13df5
--- /dev/null
+++ b/zoo-project/zoo-kernel/zoo_service_loader.c
@@ -0,0 +1,2258 @@
+/*
+ * Author : Gérald FENOY
+ *
+ *  Copyright 2008-2013 GeoLabs SARL. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+extern "C" int yylex ();
+extern "C" int crlex ();
+
+#ifdef USE_OTB
+#include "service_internal_otb.h"
+#else
+#define length(x) (sizeof(x) / sizeof(x[0]))
+#endif
+
+#include "cgic.h"
+
+extern "C"
+{
+#include <libxml/tree.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+}
+
+#include "ulinet.h"
+
+#include <libintl.h>
+#include <locale.h>
+#include <string.h>
+
+#include "service.h"
+
+#include "service_internal.h"
+#include "server_internal.h"
+#include "response_print.h"
+#include "request_parser.h"
+#include "sqlapi.h"
+#ifdef WIN32
+#include "caching.h"
+#endif
+
+#ifdef USE_PYTHON
+#include "service_internal_python.h"
+#endif
+
+#ifdef USE_SAGA
+#include "service_internal_saga.h"
+#endif
+
+#ifdef USE_JAVA
+#include "service_internal_java.h"
+#endif
+
+#ifdef USE_PHP
+#include "service_internal_php.h"
+#endif
+
+#ifdef USE_JS
+#include "service_internal_js.h"
+#endif
+
+#ifdef USE_RUBY
+#include "service_internal_ruby.h"
+#endif
+
+#ifdef USE_PERL
+#include "service_internal_perl.h"
+#endif
+
+#include <dirent.h>
+#include <signal.h>
+#include <unistd.h>
+#ifndef WIN32
+#include <dlfcn.h>
+#include <libgen.h>
+#else
+#include <windows.h>
+#include <direct.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#define pid_t int;
+#endif
+#include <fcntl.h>
+#include <time.h>
+#include <stdarg.h>
+
+#ifdef WIN32
+extern "C"
+{
+  __declspec (dllexport) char *strcasestr (char const *a, char const *b)
+#ifndef USE_MS
+  {
+    char *x = zStrdup (a);
+    char *y = zStrdup (b);
+
+      x = _strlwr (x);
+      y = _strlwr (y);
+    char *pos = strstr (x, y);
+    char *ret = pos == NULL ? NULL : (char *) (a + (pos - x));
+      free (x);
+      free (y);
+      return ret;
+  };
+#else
+   ;
+#endif
+}
+#endif
+
+/**
+ * Translation function for zoo-kernel
+ */
+#define _(String) dgettext ("zoo-kernel",String)
+/**
+ * Translation function for zoo-service
+ */
+#define __(String) dgettext ("zoo-service",String)
+
+#ifdef WIN32
+  #ifndef PROGRAMNAME
+    #define PROGRAMNAME "zoo_loader.cgi"
+  #endif
+#endif
+
+
+/**
+ * Replace a char by another one in a string
+ *
+ * @param str the string to update
+ * @param toReplace the char to replace
+ * @param toReplaceBy the char that will be used
+ */
+void
+translateChar (char *str, char toReplace, char toReplaceBy)
+{
+  int i = 0, len = strlen (str);
+  for (i = 0; i < len; i++)
+    {
+      if (str[i] == toReplace)
+        str[i] = toReplaceBy;
+    }
+}
+
+/**
+ * Recursivelly parse zcfg starting from the ZOO-Kernel cwd.
+ * Call the func function given in arguments after parsing the ZCFG file.
+ *
+ * @param m the conf maps containing the main.cfg settings
+ * @param r the registry containing profiles hierarchy
+ * @param n the root XML Node to add the sub-elements
+ * @param conf_dir the location of the main.cfg file (basically cwd)
+ * @param prefix the current prefix if any, or NULL
+ * @param saved_stdout the saved stdout identifier
+ * @param level the current level (number of sub-directories to reach the
+ * current path)
+ * @param func a pointer to a function having 4 parameters 
+ *  (registry*, maps*, xmlNodePtr and service*).
+ * @see inheritance, readServiceFile
+ */
+int
+recursReaddirF ( maps * m, registry *r, xmlNodePtr n, char *conf_dir, 
+		 char *prefix, int saved_stdout, int level, 
+		 void (func) (registry *, maps *, xmlNodePtr, service *) )
+{
+  struct dirent *dp;
+  int scount = 0;
+
+  if (conf_dir == NULL)
+    return 1;
+  DIR *dirp = opendir (conf_dir);
+  if (dirp == NULL)
+    {
+      if (level > 0)
+        return 1;
+      else
+        return -1;
+    }
+  char tmp1[25];
+  sprintf (tmp1, "sprefix_%d", level);
+  char levels[17];
+  sprintf (levels, "%d", level);
+  setMapInMaps (m, "lenv", "level", levels);
+  while ((dp = readdir (dirp)) != NULL)
+    if ((dp->d_type == DT_DIR || dp->d_type == DT_LNK) && dp->d_name[0] != '.'
+        && strstr (dp->d_name, ".") == NULL)
+      {
+
+        char *tmp =
+          (char *) malloc ((strlen (conf_dir) + strlen (dp->d_name) + 2) *
+                           sizeof (char));
+        sprintf (tmp, "%s/%s", conf_dir, dp->d_name);
+
+        if (prefix != NULL)
+          {
+            prefix = NULL;
+          }
+        prefix = (char *) malloc ((strlen (dp->d_name) + 2) * sizeof (char));
+        sprintf (prefix, "%s.", dp->d_name);
+
+        //map* tmpMap=getMapFromMaps(m,"lenv",tmp1);
+
+        int res;
+        if (prefix != NULL)
+          {
+            setMapInMaps (m, "lenv", tmp1, prefix);
+            char levels1[17];
+            sprintf (levels1, "%d", level + 1);
+            setMapInMaps (m, "lenv", "level", levels1);
+            res =
+              recursReaddirF (m, r, n, tmp, prefix, saved_stdout, level + 1,
+                              func);
+            sprintf (levels1, "%d", level);
+            setMapInMaps (m, "lenv", "level", levels1);
+            free (prefix);
+            prefix = NULL;
+          }
+        else
+          res = -1;
+        free (tmp);
+        if (res < 0)
+          {
+            return res;
+          }
+      }
+    else
+      {
+        char* extn = strstr(dp->d_name, ".zcfg");
+        if(dp->d_name[0] != '.' && extn != NULL && strlen(extn) == 5)
+          {
+            int t;
+            char tmps1[1024];
+            memset (tmps1, 0, 1024);
+            snprintf (tmps1, 1024, "%s/%s", conf_dir, dp->d_name);
+            service *s1 = (service *) malloc (SERVICE_SIZE);
+            if (s1 == NULL)
+              {
+                dup2 (saved_stdout, fileno (stdout));
+                errorException (m, _("Unable to allocate memory"),
+                                "InternalError", NULL);
+                return -1;
+              }
+#ifdef DEBUG
+            fprintf (stderr, "#################\n%s\n#################\n",
+                     tmps1);
+#endif
+            char *tmpsn = zStrdup (dp->d_name);
+            tmpsn[strlen (tmpsn) - 5] = 0;
+            t = readServiceFile (m, tmps1, &s1, tmpsn);
+            free (tmpsn);
+            if (t < 0)
+              {
+                map *tmp00 = getMapFromMaps (m, "lenv", "message");
+                char tmp01[1024];
+                if (tmp00 != NULL)
+                  sprintf (tmp01, _("Unable to parse the ZCFG file: %s (%s)"),
+                           dp->d_name, tmp00->value);
+                else
+                  sprintf (tmp01, _("Unable to parse the ZCFG file: %s."),
+                           dp->d_name);
+                dup2 (saved_stdout, fileno (stdout));
+                errorException (m, tmp01, "InternalError", NULL);
+                return -1;
+              }
+#ifdef DEBUG
+            dumpService (s1);
+            fflush (stdout);
+            fflush (stderr);
+#endif
+	    inheritance(r,&s1);
+            func (r, m, n, s1);
+            freeService (&s1);
+            free (s1);
+            scount++;
+          }
+      }
+  (void) closedir (dirp);
+  return 1;
+}
+
+/**
+ * Signal handling function which simply call exit(0).
+ *
+ * @param sig the signal number
+ */
+void
+donothing (int sig)
+{
+#ifdef DEBUG
+  fprintf (stderr, "Signal %d after the ZOO-Kernel returned result!\n", sig);
+#endif
+  exit (0);
+}
+
+/**
+ * Signal handling function which create an ExceptionReport node containing the
+ * information message corresponding to the signal number.
+ *
+ * @param sig the signal number
+ */
+void
+sig_handler (int sig)
+{
+  char tmp[100];
+  const char *ssig;
+  switch (sig)
+    {
+    case SIGSEGV:
+      ssig = "SIGSEGV";
+      break;
+    case SIGTERM:
+      ssig = "SIGTERM";
+      break;
+    case SIGINT:
+      ssig = "SIGINT";
+      break;
+    case SIGILL:
+      ssig = "SIGILL";
+      break;
+    case SIGFPE:
+      ssig = "SIGFPE";
+      break;
+    case SIGABRT:
+      ssig = "SIGABRT";
+      break;
+    default:
+      ssig = "UNKNOWN";
+      break;
+    }
+  sprintf (tmp,
+           _
+           ("ZOO Kernel failed to process your request, receiving signal %d = %s"),
+           sig, ssig);
+  errorException (NULL, tmp, "InternalError", NULL);
+#ifdef DEBUG
+  fprintf (stderr, "Not this time!\n");
+#endif
+  exit (0);
+}
+
+/**
+ * Load a service provider and run the service function.
+ *
+ * @param myMap the conf maps containing the main.cfg settings
+ * @param s1 the service structure
+ * @param request_inputs map storing all the request parameters
+ * @param inputs the inputs maps
+ * @param ioutputs the outputs maps
+ * @param eres the result returned by the service execution
+ */
+void
+loadServiceAndRun (maps ** myMap, service * s1, map * request_inputs,
+                   maps ** inputs, maps ** ioutputs, int *eres)
+{
+  char tmps1[1024];
+  char ntmp[1024];
+  maps *m = *myMap;
+  maps *request_output_real_format = *ioutputs;
+  maps *request_input_real_format = *inputs;
+  /**
+   * Extract serviceType to know what kind of service should be loaded
+   */
+  map *r_inputs = NULL;
+#ifndef WIN32
+  getcwd (ntmp, 1024);
+#else
+  _getcwd (ntmp, 1024);
+#endif
+  r_inputs = getMap (s1->content, "serviceType");
+#ifdef DEBUG
+  fprintf (stderr, "LOAD A %s SERVICE PROVIDER \n", r_inputs->value);
+  fflush (stderr);
+#endif
+
+  map* libp = getMapFromMaps(m, "main", "libPath");
+
+  if (strlen (r_inputs->value) == 1
+      && strncasecmp (r_inputs->value, "C", 1) == 0)
+  {
+     if (libp != NULL && libp->value != NULL) {
+	    r_inputs = getMap (s1->content, "ServiceProvider");
+		sprintf (tmps1, "%s/%s", libp->value, r_inputs->value);
+	 }
+     else {	 
+        r_inputs = getMap (request_inputs, "metapath");
+        if (r_inputs != NULL)
+          sprintf (tmps1, "%s/%s", ntmp, r_inputs->value);
+        else
+          sprintf (tmps1, "%s/", ntmp);
+	  
+        char *altPath = zStrdup (tmps1);
+        r_inputs = getMap (s1->content, "ServiceProvider");
+        sprintf (tmps1, "%s/%s", altPath, r_inputs->value);
+        free (altPath);
+	 }
+#ifdef DEBUG
+      fprintf (stderr, "Trying to load %s\n", tmps1);
+#endif
+#ifdef WIN32
+      HINSTANCE so =
+        LoadLibraryEx (tmps1, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
+#else
+      void *so = dlopen (tmps1, RTLD_LAZY);
+#endif
+#ifdef WIN32
+      char* errstr = getLastErrorMessage();
+#else
+      char *errstr;
+      errstr = dlerror ();
+#endif
+#ifdef DEBUG
+	  fprintf (stderr, "%s loaded (%s) \n", tmps1, errstr);
+#endif
+      if (so != NULL)
+        {
+#ifdef DEBUG
+          fprintf (stderr, "Library loaded %s \n", errstr);
+          fprintf (stderr, "Service Shared Object = %s\n", r_inputs->value);
+#endif
+          r_inputs = getMap (s1->content, "serviceType");
+#ifdef DEBUG
+          dumpMap (r_inputs);
+          fprintf (stderr, "%s\n", r_inputs->value);
+          fflush (stderr);
+#endif
+          if (strncasecmp (r_inputs->value, "C-FORTRAN", 9) == 0)
+            {
+              r_inputs = getMap (request_inputs, "Identifier");
+              char fname[1024];
+              sprintf (fname, "%s_", r_inputs->value);
+#ifdef DEBUG
+              fprintf (stderr, "Try to load function %s\n", fname);
+#endif
+#ifdef WIN32
+              typedef int (CALLBACK * execute_t) (char ***, char ***,
+                                                  char ***);
+              execute_t execute = (execute_t) GetProcAddress (so, fname);
+#else
+              typedef int (*execute_t) (char ***, char ***, char ***);
+              execute_t execute = (execute_t) dlsym (so, fname);
+#endif
+#ifdef DEBUG
+#ifdef WIN32
+			  errstr = getLastErrorMessage();
+#else
+              errstr = dlerror ();
+#endif
+              fprintf (stderr, "Function loaded %s\n", errstr);
+#endif
+
+              char main_conf[10][30][1024];
+              char inputs[10][30][1024];
+              char outputs[10][30][1024];
+              for (int i = 0; i < 10; i++)
+                {
+                  for (int j = 0; j < 30; j++)
+                    {
+                      memset (main_conf[i][j], 0, 1024);
+                      memset (inputs[i][j], 0, 1024);
+                      memset (outputs[i][j], 0, 1024);
+                    }
+                }
+              mapsToCharXXX (m, (char ***) main_conf);
+              mapsToCharXXX (request_input_real_format, (char ***) inputs);
+              mapsToCharXXX (request_output_real_format, (char ***) outputs);
+              *eres =
+                execute ((char ***) &main_conf[0], (char ***) &inputs[0],
+                         (char ***) &outputs[0]);
+#ifdef DEBUG
+              fprintf (stderr, "Function run successfully \n");
+#endif
+              charxxxToMaps ((char ***) &outputs[0],
+                             &request_output_real_format);
+            }
+          else
+            {
+#ifdef DEBUG
+#ifdef WIN32
+			  errstr = getLastErrorMessage();
+              fprintf (stderr, "Function %s failed to load because of %s\n",
+                       r_inputs->value, errstr);
+#endif
+#endif
+              r_inputs = getMapFromMaps (m, "lenv", "Identifier");
+#ifdef DEBUG
+              fprintf (stderr, "Try to load function %s\n", r_inputs->value);
+#endif
+              typedef int (*execute_t) (maps **, maps **, maps **);
+#ifdef WIN32
+              execute_t execute =
+                (execute_t) GetProcAddress (so, r_inputs->value);
+#else
+              execute_t execute = (execute_t) dlsym (so, r_inputs->value);
+#endif
+
+              if (execute == NULL)
+                {
+#ifdef WIN32
+				  errstr = getLastErrorMessage();
+#else
+                  errstr = dlerror ();
+#endif
+                  char *tmpMsg =
+                    (char *) malloc (2048 + strlen (r_inputs->value));
+                  sprintf (tmpMsg,
+                           _
+                           ("Error occured while running the %s function: %s"),
+                           r_inputs->value, errstr);
+                  errorException (m, tmpMsg, "InternalError", NULL);
+                  free (tmpMsg);
+#ifdef DEBUG
+                  fprintf (stderr, "Function %s error %s\n", r_inputs->value,
+                           errstr);
+#endif
+                  *eres = -1;
+                  return;
+                }
+
+#ifdef DEBUG
+#ifdef WIN32
+			  errstr = getLastErrorMessage();
+#else
+              errstr = dlerror ();
+#endif
+              fprintf (stderr, "Function loaded %s\n", errstr);
+#endif
+
+#ifdef DEBUG
+              fprintf (stderr, "Now run the function \n");
+              fflush (stderr);
+#endif
+              *eres =
+                execute (&m, &request_input_real_format,
+                         &request_output_real_format);
+#ifdef DEBUG
+              fprintf (stderr, "Function loaded and returned %d\n", eres);
+              fflush (stderr);
+#endif
+            }
+#ifdef WIN32
+          *ioutputs = dupMaps (&request_output_real_format);
+          FreeLibrary (so);
+#else
+          dlclose (so);
+#endif
+        }
+      else
+        {
+      /**
+       * Unable to load the specified shared library
+       */
+          char tmps[1024];
+#ifdef WIN32
+		  errstr = getLastErrorMessage();
+#else
+	      errstr = dlerror ();
+#endif
+          sprintf (tmps, _("Unable to load C Library %s"), errstr);
+	  errorException(m,tmps,"InternalError",NULL);
+          *eres = -1;
+        }
+    }
+  else
+
+#ifdef USE_SAGA
+  if (strncasecmp (r_inputs->value, "SAGA", 6) == 0)
+    {
+      *eres =
+        zoo_saga_support (&m, request_inputs, s1,
+                            &request_input_real_format,
+                            &request_output_real_format);
+    }
+  else
+#endif
+
+#ifdef USE_OTB
+  if (strncasecmp (r_inputs->value, "OTB", 6) == 0)
+    {
+      *eres =
+        zoo_otb_support (&m, request_inputs, s1,
+                            &request_input_real_format,
+                            &request_output_real_format);
+    }
+  else
+#endif
+#ifdef USE_PYTHON
+  if (strncasecmp (r_inputs->value, "PYTHON", 6) == 0)
+    {	  
+      *eres =
+        zoo_python_support (&m, request_inputs, s1,
+                            &request_input_real_format,
+                            &request_output_real_format);
+    }
+  else
+#endif
+
+#ifdef USE_JAVA
+  if (strncasecmp (r_inputs->value, "JAVA", 4) == 0)
+    {
+      *eres =
+        zoo_java_support (&m, request_inputs, s1, &request_input_real_format,
+                          &request_output_real_format);
+    }
+  else
+#endif
+
+#ifdef USE_PHP
+  if (strncasecmp (r_inputs->value, "PHP", 3) == 0)
+    {
+      *eres =
+        zoo_php_support (&m, request_inputs, s1, &request_input_real_format,
+                         &request_output_real_format);
+    }
+  else
+#endif
+
+
+#ifdef USE_PERL
+  if (strncasecmp (r_inputs->value, "PERL", 4) == 0)
+    {
+      *eres =
+        zoo_perl_support (&m, request_inputs, s1, &request_input_real_format,
+                          &request_output_real_format);
+    }
+  else
+#endif
+
+#ifdef USE_JS
+  if (strncasecmp (r_inputs->value, "JS", 2) == 0)
+    {
+      *eres =
+        zoo_js_support (&m, request_inputs, s1, &request_input_real_format,
+                        &request_output_real_format);
+    }
+  else
+#endif
+
+#ifdef USE_RUBY
+  if (strncasecmp (r_inputs->value, "Ruby", 4) == 0)
+    {
+      *eres =
+        zoo_ruby_support (&m, request_inputs, s1, &request_input_real_format,
+                          &request_output_real_format);
+    }
+  else
+#endif
+
+    {
+      char tmpv[1024];
+      sprintf (tmpv,
+               _
+               ("Programming Language (%s) set in ZCFG file is not currently supported by ZOO Kernel.\n"),
+               r_inputs->value);
+      errorException (m, tmpv, "InternalError", NULL);
+      *eres = -1;
+    }
+  *myMap = m;
+  *ioutputs = request_output_real_format;
+}
+
+
+#ifdef WIN32
+/**
+ * createProcess function: create a new process after setting some env variables
+ */
+void
+createProcess (maps * m, map * request_inputs, service * s1, char *opts,
+               int cpid, maps * inputs, maps * outputs)
+{
+  STARTUPINFO si;
+  PROCESS_INFORMATION pi;
+  ZeroMemory (&si, sizeof (si));
+  si.cb = sizeof (si);
+  ZeroMemory (&pi, sizeof (pi));
+  char *tmp = (char *) malloc ((1024 + cgiContentLength) * sizeof (char));
+  char *tmpq = (char *) malloc ((1024 + cgiContentLength) * sizeof (char));
+  map *req = getMap (request_inputs, "request");
+  map *id = getMap (request_inputs, "identifier");
+  map *di = getMap (request_inputs, "DataInputs");
+
+  // The required size for the dataInputsKVP and dataOutputsKVP buffers
+  // may exceed cgiContentLength, hence a 2 kb extension. However, a 
+  // better solution would be to have getMapsAsKVP() determine the required
+  // buffer size before allocating memory.	
+  char *dataInputsKVP = getMapsAsKVP (inputs, cgiContentLength + 2048, 0);
+  char *dataOutputsKVP = getMapsAsKVP (outputs, cgiContentLength + 2048, 1);
+#ifdef DEBUG
+  fprintf (stderr, "DATAINPUTSKVP %s\n", dataInputsKVP);
+  fprintf (stderr, "DATAOUTPUTSKVP %s\n", dataOutputsKVP);
+#endif
+  map *sid = getMapFromMaps (m, "lenv", "osid");
+  map *usid = getMapFromMaps (m, "lenv", "usid");
+  map *r_inputs = getMapFromMaps (m, "main", "tmpPath");
+  map *r_inputs1 = getMap (request_inputs, "metapath");
+  
+  int hasIn = -1;
+  if (r_inputs1 == NULL)
+    {
+      r_inputs1 = createMap ("metapath", "");
+      hasIn = 1;
+    }
+  map *r_inputs2 = getMap (request_inputs, "ResponseDocument");
+  if (r_inputs2 == NULL)
+    r_inputs2 = getMap (request_inputs, "RawDataOutput");
+  map *tmpPath = getMapFromMaps (m, "lenv", "cwd");
+
+  map *tmpReq = getMap (request_inputs, "xrequest");
+  
+  if(r_inputs2 != NULL && tmpReq != NULL) {
+    const char key[] = "rfile=";
+    char* kvp = (char*) malloc((FILENAME_MAX + strlen(key))*sizeof(char));
+    char* filepath = kvp + strlen(key);
+    strncpy(kvp, key, strlen(key));
+    addToCache(m, tmpReq->value, tmpReq->value, "text/xml", strlen(tmpReq->value), 
+	       filepath, FILENAME_MAX);
+    if (filepath == NULL) {
+      errorException( m, _("Unable to cache HTTP POST Execute request."), "InternalError", NULL);  
+      return;
+    }	
+    sprintf(tmp,"\"metapath=%s&%s&cgiSid=%s&usid=%s\"",
+	    r_inputs1->value,kvp,sid->value,usid->value);
+    sprintf(tmpq,"metapath=%s&%s",
+	    r_inputs1->value,kvp);
+    free(kvp);	
+  }
+  else if (r_inputs2 != NULL)
+    {
+      sprintf (tmp,
+               "\"metapath=%s&request=%s&service=WPS&version=1.0.0&Identifier=%s&DataInputs=%s&%s=%s&cgiSid=%s&usid=%s\"",
+               r_inputs1->value, req->value, id->value, dataInputsKVP,
+               r_inputs2->name, dataOutputsKVP, sid->value, usid->value);
+      sprintf (tmpq,
+               "metapath=%s&request=%s&service=WPS&version=1.0.0&Identifier=%s&DataInputs=%s&%s=%s",
+               r_inputs1->value, req->value, id->value, dataInputsKVP,
+               r_inputs2->name, dataOutputsKVP);		   
+    }
+  else
+    {
+      sprintf (tmp,
+               "\"metapath=%s&request=%s&service=WPS&version=1.0.0&Identifier=%s&DataInputs=%s&cgiSid=%s&usid=%s\"",
+               r_inputs1->value, req->value, id->value, dataInputsKVP,
+               sid->value, usid->value);
+      sprintf (tmpq,
+               "metapath=%s&request=%s&service=WPS&version=1.0.0&Identifier=%s&DataInputs=%s",
+               r_inputs1->value, req->value, id->value, dataInputsKVP,
+               sid->value);   
+    }
+
+  if (hasIn > 0)
+    {
+      freeMap (&r_inputs1);
+      free (r_inputs1);
+    }
+  char *tmp1 = zStrdup (tmp);
+  sprintf (tmp, "\"%s\" %s \"%s\"", PROGRAMNAME, tmp1, sid->value);  
+  free (dataInputsKVP);
+  free (dataOutputsKVP);
+#ifdef DEBUG
+  fprintf (stderr, "REQUEST IS : %s \n", tmp);
+#endif
+
+  usid = getMapFromMaps (m, "lenv", "usid");
+  if (usid != NULL && usid->value != NULL) {
+    SetEnvironmentVariable("USID", TEXT (usid->value));
+  }
+  SetEnvironmentVariable ("CGISID", TEXT (sid->value));
+  SetEnvironmentVariable ("QUERY_STRING", TEXT (tmpq));
+  // knut: Prevent REQUEST_METHOD=POST in background process call to cgic:main 
+  // (process hangs when reading cgiIn):
+  SetEnvironmentVariable("REQUEST_METHOD", "GET");
+  SetEnvironmentVariable("CONTENT_TYPE", "text/plain");
+  
+  char clen[1000];
+  sprintf (clen, "%d", strlen (tmpq));
+  SetEnvironmentVariable ("CONTENT_LENGTH", TEXT (clen));
+
+  // ref. https://msdn.microsoft.com/en-us/library/windows/desktop/ms684863%28v=vs.85%29.aspx
+  if (!CreateProcess (NULL,     // No module name (use command line)
+                      TEXT (tmp),       // Command line
+                      NULL,     // Process handle not inheritable
+                      NULL,     // Thread handle not inheritable
+                      FALSE,    // Set handle inheritance to FALSE
+                      CREATE_NO_WINDOW, // Apache won't wait until the end
+                      NULL,     // Use parent's environment block
+                      NULL,     // Use parent's starting directory 
+                      &si,      // Pointer to STARTUPINFO struct
+                      &pi)      // Pointer to PROCESS_INFORMATION struct
+    )
+    {
+#ifdef DEBUG
+      fprintf (stderr, "CreateProcess failed (%d).\n", GetLastError ());
+#endif
+      if (tmp != NULL) {
+        free(tmp);
+      }
+      if (tmpq != NULL) {
+        free(tmpq);
+      }		
+      return;
+    }
+  else
+    {
+#ifdef DEBUG
+      fprintf (stderr, "CreateProcess successful (%d).\n\n\n\n",
+               GetLastError ());
+#endif
+    }
+  CloseHandle (pi.hProcess);
+  CloseHandle (pi.hThread);
+  
+  if (tmp != NULL) {
+    free(tmp);
+  }
+  if (tmpq != NULL) {
+    free(tmpq);
+  }
+  
+#ifdef DEBUG
+  fprintf (stderr, "CreateProcess finished !\n");
+#endif
+}
+#endif
+
+/**
+ * Process the request.
+ *
+ * @param inputs the request parameters map 
+ * @return 0 on sucess, other value on failure
+ * @see conf_read,recursReaddirF
+ */
+int
+runRequest (map ** inputs)
+{
+
+#ifndef USE_GDB
+#ifndef WIN32
+  signal (SIGCHLD, SIG_IGN);
+#endif  
+  signal (SIGSEGV, sig_handler);
+  signal (SIGTERM, sig_handler);
+  signal (SIGINT, sig_handler);
+  signal (SIGILL, sig_handler);
+  signal (SIGFPE, sig_handler);
+  signal (SIGABRT, sig_handler);
+#endif
+
+  map *r_inputs = NULL;
+  map *request_inputs = *inputs;
+#ifdef IGNORE_METAPATH
+  addToMap(request_inputs, "metapath", "");
+#endif  
+  maps *m = NULL;
+  char *REQUEST = NULL;
+  /**
+   * Parsing service specfic configuration file
+   */
+  m = (maps *) malloc (MAPS_SIZE);
+  if (m == NULL)
+    {
+      return errorException (m, _("Unable to allocate memory"),
+                             "InternalError", NULL);
+    }
+  char ntmp[1024];
+#ifndef WIN32
+  getcwd (ntmp, 1024);
+#else
+  _getcwd (ntmp, 1024);
+#endif
+  r_inputs = getMapOrFill (&request_inputs, "metapath", "");
+
+  char conf_file[10240];
+  snprintf (conf_file, 10240, "%s/%s/main.cfg", ntmp, r_inputs->value);
+  if (conf_read (conf_file, m) == 2)
+    {
+      errorException (NULL, _("Unable to load the main.cfg file."),
+                      "InternalError", NULL);
+      free (m);
+      return 1;
+    }
+#ifdef DEBUG
+  fprintf (stderr, "***** BEGIN MAPS\n");
+  dumpMaps (m);
+  fprintf (stderr, "***** END MAPS\n");
+#endif
+
+  map *getPath = getMapFromMaps (m, "main", "gettextPath");
+  if (getPath != NULL)
+    {
+      bindtextdomain ("zoo-kernel", getPath->value);
+      bindtextdomain ("zoo-services", getPath->value);
+    }
+  else
+    {
+      bindtextdomain ("zoo-kernel", "/usr/share/locale/");
+      bindtextdomain ("zoo-services", "/usr/share/locale/");
+    }
+
+  /**
+   * Manage our own error log file (usefull to separate standard apache debug
+   * messages from the ZOO-Kernel ones but also for IIS users to avoid wrong 
+   * headers messages returned by the CGI due to wrong redirection of stderr)
+   */
+  FILE *fstde = NULL;
+  map *fstdem = getMapFromMaps (m, "main", "logPath");
+  if (fstdem != NULL)
+    fstde = freopen (fstdem->value, "a+", stderr);
+
+  r_inputs = getMap (request_inputs, "language");
+  if (r_inputs == NULL)
+    r_inputs = getMap (request_inputs, "AcceptLanguages");
+  if (r_inputs == NULL)
+    r_inputs = getMapFromMaps (m, "main", "language");
+  if (r_inputs != NULL)
+    {
+      if (isValidLang (m, r_inputs->value) < 0)
+        {
+          char tmp[1024];
+          sprintf (tmp,
+                   _
+                   ("The value %s is not supported for the <language> parameter"),
+                   r_inputs->value);
+          errorException (m, tmp, "InvalidParameterValue", "language");
+          freeMaps (&m);
+          free (m);
+          free (REQUEST);
+          return 1;
+
+        }
+      char *tmp = zStrdup (r_inputs->value);
+      setMapInMaps (m, "main", "language", tmp);
+#ifdef DEB
+      char tmp2[12];
+      sprintf (tmp2, "%s.utf-8", tmp);
+      translateChar (tmp2, '-', '_');
+      setlocale (LC_ALL, tmp2);
+#else
+      translateChar (tmp, '-', '_');
+      setlocale (LC_ALL, tmp);
+#endif
+#ifndef WIN32
+      setenv ("LC_ALL", tmp, 1);
+#else
+      char tmp1[12];
+      sprintf (tmp1, "LC_ALL=%s", tmp);
+      putenv (tmp1);
+#endif
+      free (tmp);
+    }
+  else
+    {
+      setlocale (LC_ALL, "en_US");
+#ifndef WIN32
+      setenv ("LC_ALL", "en_US", 1);
+#else
+      char tmp1[12];
+      sprintf (tmp1, "LC_ALL=en_US");
+      putenv (tmp1);
+#endif
+      setMapInMaps (m, "main", "language", "en-US");
+    }
+  setlocale (LC_NUMERIC, "en_US");
+  bind_textdomain_codeset ("zoo-kernel", "UTF-8");
+  textdomain ("zoo-kernel");
+  bind_textdomain_codeset ("zoo-services", "UTF-8");
+  textdomain ("zoo-services");
+
+  map *lsoap = getMap (request_inputs, "soap");
+  if (lsoap != NULL && strcasecmp (lsoap->value, "true") == 0)
+    setMapInMaps (m, "main", "isSoap", "true");
+  else
+    setMapInMaps (m, "main", "isSoap", "false");
+
+  if(strlen(cgiServerName)>0)
+    {
+      char tmpUrl[1024];
+	
+      if ( getenv("HTTPS") != NULL && strncmp(getenv("HTTPS"), "on", 2) == 0 ) {
+	// Knut: check if non-empty instead of "on"?		
+	if ( strncmp(cgiServerPort, "443", 3) == 0 ) { 
+	  sprintf(tmpUrl, "https://%s%s", cgiServerName, cgiScriptName);
+	}
+	else {
+	  sprintf(tmpUrl, "https://%s:%s%s", cgiServerName, cgiServerPort, cgiScriptName);
+	}
+      }
+      else {
+	if ( strncmp(cgiServerPort, "80", 2) == 0 ) { 
+	  sprintf(tmpUrl, "http://%s%s", cgiServerName, cgiScriptName);
+	}
+	else {
+	  sprintf(tmpUrl, "http://%s:%s%s", cgiServerName, cgiServerPort, cgiScriptName);
+	}
+      }
+#ifdef DEBUG
+      fprintf(stderr,"*** %s ***\n",tmpUrl);
+#endif
+      setMapInMaps(m,"main","serverAddress",tmpUrl);
+    }
+
+  //Check for minimum inputs
+  map* version=getMap(request_inputs,"version");
+  if(version==NULL)
+    version=getMapFromMaps(m,"main","version");
+  setMapInMaps(m,"main","rversion",version->value);
+  int vid=getVersionId(version->value);
+  if(vid<0)
+    vid=0;
+  map* err=NULL;
+  const char **vvr=(const char**)requests[vid];
+  checkValidValue(request_inputs,&err,"request",vvr,1);
+  const char *vvs[]={
+    "WPS",
+    NULL
+  };
+  if(err!=NULL){
+    checkValidValue(request_inputs,&err,"service",(const char**)vvs,1);
+    printExceptionReportResponse (m, err);
+    freeMap(&err);
+    free(err);
+    if (count (request_inputs) == 1)
+      {
+	freeMap (&request_inputs);
+	free (request_inputs);
+      }
+    freeMaps (&m);
+    free (m);
+    return 1;
+  }
+  checkValidValue(request_inputs,&err,"service",(const char**)vvs,1);
+
+  const char *vvv[]={
+    "1.0.0",
+    "2.0.0",
+    NULL
+  };
+  r_inputs = getMap (request_inputs, "Request");
+  REQUEST = zStrdup (r_inputs->value);
+  int reqId=-1;
+  if (strncasecmp (REQUEST, "GetCapabilities", 15) != 0){
+    checkValidValue(request_inputs,&err,"version",(const char**)vvv,1);
+    int j=0;
+    for(j=0;j<nbSupportedRequests;j++){
+      if(requests[vid][j]!=NULL && requests[vid][j+1]!=NULL){
+	if(j<nbReqIdentifier && strncasecmp(REQUEST,requests[vid][j+1],strlen(REQUEST))==0){
+	  checkValidValue(request_inputs,&err,"identifier",NULL,1);
+	  reqId=j+1;
+	  break;
+	}
+	else
+	  if(j>=nbReqIdentifier && j<nbReqIdentifier+nbReqJob && 
+	     strncasecmp(REQUEST,requests[vid][j+1],strlen(REQUEST))==0){
+	    checkValidValue(request_inputs,&err,"jobid",NULL,1);
+	    reqId=j+1;
+	    break;
+	  }
+      }else
+	break;
+    }
+  }else{
+    checkValidValue(request_inputs,&err,"AcceptVersions",(const char**)vvv,-1);
+    map* version1=getMap(request_inputs,"AcceptVersions");
+    if(version1!=NULL){
+      if(strstr(version1->value,schemas[1][0])!=NULL)
+	addToMap(request_inputs,"version",schemas[1][0]);
+      else
+	addToMap(request_inputs,"version",version1->value);
+      version=getMap(request_inputs,"version");
+      setMapInMaps(m,"main","rversion",version->value);
+      vid=getVersionId(version->value);
+    }
+  }
+  if(err!=NULL){
+    printExceptionReportResponse (m, err);
+    freeMap(&err);
+    free(err);
+    if (count (request_inputs) == 1)
+      {
+	freeMap (&request_inputs);
+	free (request_inputs);
+      }
+    free(REQUEST);
+    freeMaps (&m);
+    free (m);
+    return 1;
+  }
+
+  r_inputs = getMap (request_inputs, "serviceprovider");
+  if (r_inputs == NULL)
+    {
+      addToMap (request_inputs, "serviceprovider", "");
+    }
+
+  maps *request_output_real_format = NULL;
+  map *tmpm = getMapFromMaps (m, "main", "serverAddress");
+  if (tmpm != NULL)
+    SERVICE_URL = zStrdup (tmpm->value);
+  else
+    SERVICE_URL = zStrdup (DEFAULT_SERVICE_URL);
+
+
+
+  service *s1;
+  int scount = 0;
+#ifdef DEBUG
+  dumpMap (r_inputs);
+#endif
+  char conf_dir[1024];
+  int t;
+  char tmps1[1024];
+
+  r_inputs = NULL;
+  r_inputs = getMap (request_inputs, "metapath");
+  
+  if (r_inputs != NULL)
+    snprintf (conf_dir, 1024, "%s/%s", ntmp, r_inputs->value);
+  else
+    snprintf (conf_dir, 1024, "%s", ntmp);
+
+  map* reg = getMapFromMaps (m, "main", "registry");
+  registry* zooRegistry=NULL;
+  if(reg!=NULL){
+    int saved_stdout = dup (fileno (stdout));
+    dup2 (fileno (stderr), fileno (stdout));
+    if(createRegistry (m,&zooRegistry,reg->value)<0){
+      map *message=getMapFromMaps(m,"lenv","message");
+      map *type=getMapFromMaps(m,"lenv","type");
+      dup2 (saved_stdout, fileno (stdout));
+      errorException (m, message->value,
+		      type->value, NULL);
+      return 0;
+    }
+    dup2 (saved_stdout, fileno (stdout));
+    close(saved_stdout);
+  }
+
+  if (strncasecmp (REQUEST, "GetCapabilities", 15) == 0)
+    {
+#ifdef DEBUG
+      dumpMap (r_inputs);
+#endif
+      xmlDocPtr doc = xmlNewDoc (BAD_CAST "1.0");
+      xmlNodePtr n=printGetCapabilitiesHeader(doc,m,(version!=NULL?version->value:"1.0.0"));
+      /**
+       * Here we need to close stdout to ensure that unsupported chars 
+       * has been found in the zcfg and then printed on stdout
+       */
+      int saved_stdout = dup (fileno (stdout));
+      dup2 (fileno (stderr), fileno (stdout));
+      if (int res =		  
+          recursReaddirF (m, zooRegistry, n, conf_dir, NULL, saved_stdout, 0,
+                          printGetCapabilitiesForProcess) < 0)
+        {
+          freeMaps (&m);
+          free (m);
+	  if(zooRegistry!=NULL){
+	    freeRegistry(&zooRegistry);
+	    free(zooRegistry);
+	  }
+          free (REQUEST);
+          free (SERVICE_URL);
+          fflush (stdout);
+          return res;
+        }
+      fflush (stdout);
+      dup2 (saved_stdout, fileno (stdout));
+      printDocument (m, doc, getpid ());
+      freeMaps (&m);
+      free (m);
+      if(zooRegistry!=NULL){
+	freeRegistry(&zooRegistry);
+	free(zooRegistry);
+      }
+      free (REQUEST);
+      free (SERVICE_URL);
+      fflush (stdout);
+      return 0;
+    }
+  else
+    {
+      r_inputs = getMap (request_inputs, "JobId");
+      if(reqId>nbReqIdentifier){
+	if (strncasecmp (REQUEST, "GetStatus", strlen(REQUEST)) == 0 ||
+	    strncasecmp (REQUEST, "GetResult", strlen(REQUEST)) == 0){
+	  runGetStatus(m,r_inputs->value,REQUEST);
+	  freeMaps (&m);
+	  free (m);
+	  if(zooRegistry!=NULL){
+	    freeRegistry(&zooRegistry);
+	    free(zooRegistry);
+	  }
+	  free (REQUEST);
+	  free (SERVICE_URL);
+	  return 0;
+	}
+	else
+	  if (strncasecmp (REQUEST, "Dismiss", strlen(REQUEST)) == 0){
+	    runDismiss(m,r_inputs->value);
+	    freeMaps (&m);
+	    free (m);
+	    if(zooRegistry!=NULL){
+	      freeRegistry(&zooRegistry);
+	      free(zooRegistry);
+	    }
+	    free (REQUEST);
+	    free (SERVICE_URL);
+	    return 0;
+	    
+	  }
+	return 0;
+      }
+      if(reqId<=nbReqIdentifier){
+	r_inputs = getMap (request_inputs, "Identifier");
+
+	struct dirent *dp;
+	DIR *dirp = opendir (conf_dir);
+	if (dirp == NULL)
+	  {
+	    errorException (m, _("The specified path does not exist."),
+			    "InvalidParameterValue", conf_dir);
+	    freeMaps (&m);
+	    free (m);
+	    if(zooRegistry!=NULL){
+	      freeRegistry(&zooRegistry);
+	      free(zooRegistry);
+	    }
+	    free (REQUEST);
+	    free (SERVICE_URL);
+	    return 0;
+	  }
+	if (strncasecmp (REQUEST, "DescribeProcess", 15) == 0)
+	  {
+	    /**
+	     * Loop over Identifier list
+	     */
+	    xmlDocPtr doc = xmlNewDoc (BAD_CAST "1.0");
+	    r_inputs = NULL;
+	    r_inputs = getMap (request_inputs, "version");
+	    xmlNodePtr n = printWPSHeader(doc,m,"DescribeProcess",
+					  root_nodes[vid][1],(version!=NULL?version->value:"1.0.0"),1);
+
+	    r_inputs = getMap (request_inputs, "Identifier");
+
+	    char *orig = zStrdup (r_inputs->value);
+
+	    int saved_stdout = dup (fileno (stdout));
+	    dup2 (fileno (stderr), fileno (stdout));
+	    if (strcasecmp ("all", orig) == 0)
+	      {
+		if (int res =
+		    recursReaddirF (m, zooRegistry, n, conf_dir, NULL, saved_stdout, 0,
+				    printDescribeProcessForProcess) < 0)
+		  return res;
+	      }
+	    else
+	      {
+		char *saveptr;
+		char *tmps = strtok_r (orig, ",", &saveptr);
+
+		char buff[256];
+		char buff1[1024];
+		while (tmps != NULL)
+		  {
+		    int hasVal = -1;
+		    char *corig = zStrdup (tmps);
+		    if (strstr (corig, ".") != NULL)
+		      {
+
+			parseIdentifier (m, conf_dir, corig, buff1);
+			map *tmpMap = getMapFromMaps (m, "lenv", "metapath");
+			if (tmpMap != NULL)
+			  addToMap (request_inputs, "metapath", tmpMap->value);
+			map *tmpMapI = getMapFromMaps (m, "lenv", "Identifier");
+
+			s1 = (service *) malloc (SERVICE_SIZE);
+			t = readServiceFile (m, buff1, &s1, tmpMapI->value);
+			if (t < 0)
+			  {
+			    map *tmp00 = getMapFromMaps (m, "lenv", "message");
+			    char tmp01[1024];
+			    if (tmp00 != NULL)
+			      sprintf (tmp01,
+				       _
+				       ("Unable to parse the ZCFG file for the following ZOO-Service: %s. Message: %s"),
+				       tmps, tmp00->value);
+			    else
+			      sprintf (tmp01,
+				       _
+				       ("Unable to parse the ZCFG file for the following ZOO-Service: %s."),
+				       tmps);
+			    dup2 (saved_stdout, fileno (stdout));
+			    errorException (m, tmp01, "InvalidParameterValue",
+					    "identifier");
+			    freeMaps (&m);
+			    free (m);
+			    if(zooRegistry!=NULL){
+			      freeRegistry(&zooRegistry);
+			      free(zooRegistry);
+			    }
+			    free (REQUEST);
+			    free (corig);
+			    free (orig);
+			    free (SERVICE_URL);
+			    free (s1);
+			    closedir (dirp);
+			    xmlFreeDoc (doc);
+			    xmlCleanupParser ();
+			    zooXmlCleanupNs ();
+			    return 1;
+			  }
+#ifdef DEBUG
+			dumpService (s1);
+#endif
+			inheritance(zooRegistry,&s1);
+			printDescribeProcessForProcess (zooRegistry,m, n, s1);
+			freeService (&s1);
+			free (s1);
+			s1 = NULL;
+			scount++;
+			hasVal = 1;
+			setMapInMaps (m, "lenv", "level", "0");
+		      }
+		    else
+		      {
+			memset (buff, 0, 256);
+			snprintf (buff, 256, "%s.zcfg", corig);
+			memset (buff1, 0, 1024);
+#ifdef DEBUG
+			printf ("\n#######%s\n########\n", buff);
+#endif
+			while ((dp = readdir (dirp)) != NULL)
+			  {
+			    if (strcasecmp (dp->d_name, buff) == 0)
+			      {
+				memset (buff1, 0, 1024);
+				snprintf (buff1, 1024, "%s/%s", conf_dir,
+					  dp->d_name);
+				s1 = (service *) malloc (SERVICE_SIZE);
+				if (s1 == NULL)
+				  {
+				    dup2 (saved_stdout, fileno (stdout));
+				    return errorException (m,
+							   _
+							   ("Unable to allocate memory"),
+							   "InternalError",
+							   NULL);
+				  }
+#ifdef DEBUG
+				printf
+				  ("#################\n(%s) %s\n#################\n",
+				   r_inputs->value, buff1);
+#endif
+				char *tmp0 = zStrdup (dp->d_name);
+				tmp0[strlen (tmp0) - 5] = 0;
+				t = readServiceFile (m, buff1, &s1, tmp0);
+				free (tmp0);
+				if (t < 0)
+				  {
+				    map *tmp00 =
+				      getMapFromMaps (m, "lenv", "message");
+				    char tmp01[1024];
+				    if (tmp00 != NULL)
+				      sprintf (tmp01,
+					       _
+					       ("Unable to parse the ZCFG file: %s (%s)"),
+					       dp->d_name, tmp00->value);
+				    else
+				      sprintf (tmp01,
+					       _
+					       ("Unable to parse the ZCFG file: %s."),
+					       dp->d_name);
+				    dup2 (saved_stdout, fileno (stdout));
+				    errorException (m, tmp01, "InternalError",
+						    NULL);
+				    freeMaps (&m);
+				    free (m);
+				    if(zooRegistry!=NULL){
+				      freeRegistry(&zooRegistry);
+				      free(zooRegistry);
+				    }
+				    free (orig);
+				    free (REQUEST);
+				    closedir (dirp);
+				    xmlFreeDoc (doc);
+				    xmlCleanupParser ();
+				    zooXmlCleanupNs ();
+				    return 1;
+				  }
+#ifdef DEBUG
+				dumpService (s1);
+#endif
+				inheritance(zooRegistry,&s1);
+				printDescribeProcessForProcess (zooRegistry,m, n, s1);
+				freeService (&s1);
+				free (s1);
+				s1 = NULL;
+				scount++;
+				hasVal = 1;
+			      }
+			  }
+		      }
+		    if (hasVal < 0)
+		      {
+			map *tmp00 = getMapFromMaps (m, "lenv", "message");
+			char tmp01[1024];
+			if (tmp00 != NULL)
+			  sprintf (tmp01,
+				   _("Unable to parse the ZCFG file: %s (%s)"),
+				   buff, tmp00->value);
+			else
+			  sprintf (tmp01,
+				   _("Unable to parse the ZCFG file: %s."),
+				   buff);
+			dup2 (saved_stdout, fileno (stdout));
+			errorException (m, tmp01, "InvalidParameterValue",
+					"Identifier");
+			freeMaps (&m);
+			free (m);
+			if(zooRegistry!=NULL){
+			  freeRegistry(&zooRegistry);
+			  free(zooRegistry);
+			}
+			free (orig);
+			free (REQUEST);
+			closedir (dirp);
+			xmlFreeDoc (doc);
+			xmlCleanupParser ();
+			zooXmlCleanupNs ();
+			return 1;
+		      }
+		    rewinddir (dirp);
+		    tmps = strtok_r (NULL, ",", &saveptr);
+		    if (corig != NULL)
+		      free (corig);
+		  }
+	      }
+	    closedir (dirp);
+	    fflush (stdout);
+	    dup2 (saved_stdout, fileno (stdout));
+	    free (orig);
+	    printDocument (m, doc, getpid ());
+	    freeMaps (&m);
+	    free (m);
+	    if(zooRegistry!=NULL){
+	      freeRegistry(&zooRegistry);
+	      free(zooRegistry);
+	    }
+	    free (REQUEST);
+	    free (SERVICE_URL);
+	    fflush (stdout);
+	    return 0;
+	  }
+	else if (strncasecmp (REQUEST, "Execute", strlen (REQUEST)) != 0)
+	  {
+	    map* version=getMapFromMaps(m,"main","rversion");
+	    int vid=getVersionId(version->value);
+	    int len,j=0;
+	    for(j=0;j<nbSupportedRequests;j++){
+	      if(requests[vid][j]!=NULL)
+		len+=strlen(requests[vid][j])+2;
+	      else{
+		len+=4;
+		break;
+	      }
+	    }
+	    char *tmpStr=(char*)malloc(len*sizeof(char));
+	    int it=0;
+	    for(j=0;j<nbSupportedRequests;j++){
+	      if(requests[vid][j]!=NULL){
+		if(it==0){
+		  sprintf(tmpStr,"%s",requests[vid][j]);
+		  it++;
+		}else{
+		  char *tmpS=zStrdup(tmpStr);
+		  if(j+1<nbSupportedRequests && requests[vid][j+1]==NULL){
+		    sprintf(tmpStr,"%s and %s",tmpS,requests[vid][j]);
+		  }else{
+		    sprintf(tmpStr,"%s, %s",tmpS,requests[vid][j]);
+		  
+		  }
+		  free(tmpS);
+		}
+	      }
+	      else{
+		len+=4;
+		break;
+	      }
+	    }
+	    char* message=(char*)malloc((61+len)*sizeof(char));
+	    sprintf(message,"The <request> value was not recognized. Allowed values are %s.",tmpStr);
+	    errorException (m,_(message),"InvalidParameterValue", "request");
+#ifdef DEBUG
+	    fprintf (stderr, "No request found %s", REQUEST);
+#endif
+	    closedir (dirp);
+	    freeMaps (&m);
+	    free (m);
+	    if(zooRegistry!=NULL){
+	      freeRegistry(&zooRegistry);
+	      free(zooRegistry);
+	    }
+	    free (REQUEST);
+	    free (SERVICE_URL);
+	    fflush (stdout);
+	    return 0;
+	  }
+	closedir (dirp);
+      }
+    }
+
+  map *postRequest = NULL;
+  postRequest = getMap (request_inputs, "xrequest");
+
+  if(vid==1 && postRequest==NULL){
+    errorException (m,_("Unable to run Execute request using the GET HTTP method"),"InvalidParameterValue", "request");  
+    freeMaps (&m);
+    free (m);
+    if(zooRegistry!=NULL){
+      freeRegistry(&zooRegistry);
+      free(zooRegistry);
+    }
+    free (REQUEST);
+    free (SERVICE_URL);
+    fflush (stdout);
+    return 0;
+  }
+  
+  s1 = NULL;
+  s1 = (service *) malloc (SERVICE_SIZE);
+  if (s1 == NULL)
+    {
+      freeMaps (&m);
+      free (m);
+      if(zooRegistry!=NULL){
+	freeRegistry(&zooRegistry);
+	free(zooRegistry);
+      }
+      free (REQUEST);
+      free (SERVICE_URL);
+      return errorException (m, _("Unable to allocate memory"),
+                             "InternalError", NULL);
+    }
+
+  r_inputs = getMap (request_inputs, "MetaPath");
+  if (r_inputs != NULL)
+    snprintf (tmps1, 1024, "%s/%s", ntmp, r_inputs->value);
+  else
+    snprintf (tmps1, 1024, "%s/", ntmp);
+  r_inputs = getMap (request_inputs, "Identifier");
+  char *ttmp = zStrdup (tmps1);
+  snprintf (tmps1, 1024, "%s/%s.zcfg", ttmp, r_inputs->value);
+  free (ttmp);
+#ifdef DEBUG
+  fprintf (stderr, "Trying to load %s\n", tmps1);
+#endif
+  if (strstr (r_inputs->value, ".") != NULL)
+    {
+      char *identifier = zStrdup (r_inputs->value);
+      parseIdentifier (m, conf_dir, identifier, tmps1);
+      map *tmpMap = getMapFromMaps (m, "lenv", "metapath");
+      if (tmpMap != NULL)
+        addToMap (request_inputs, "metapath", tmpMap->value);
+      free (identifier);
+    }
+  else
+    {
+      setMapInMaps (m, "lenv", "Identifier", r_inputs->value);
+      setMapInMaps (m, "lenv", "oIdentifier", r_inputs->value);
+    }
+
+  r_inputs = getMapFromMaps (m, "lenv", "Identifier");
+  int saved_stdout = dup (fileno (stdout));
+  dup2 (fileno (stderr), fileno (stdout));
+  t = readServiceFile (m, tmps1, &s1, r_inputs->value);
+  inheritance(zooRegistry,&s1);
+  if(zooRegistry!=NULL){
+    freeRegistry(&zooRegistry);
+    free(zooRegistry);
+  }
+  fflush (stdout);
+  dup2 (saved_stdout, fileno (stdout));
+  if (t < 0)
+    {
+      char *tmpMsg = (char *) malloc (2048 + strlen (r_inputs->value));
+      sprintf (tmpMsg,
+               _
+               ("The value for <identifier> seems to be wrong (%s). Please specify one of the processes in the list returned by a GetCapabilities request."),
+               r_inputs->value);
+      errorException (m, tmpMsg, "InvalidParameterValue", "identifier");
+      free (tmpMsg);
+      free (s1);
+      freeMaps (&m);
+      free (m);
+      free (REQUEST);
+      free (SERVICE_URL);
+      return 0;
+    }
+  close (saved_stdout);
+
+#ifdef DEBUG
+  dumpService (s1);
+#endif
+  int j;
+
+
+  /**
+   * Create the input and output maps data structure
+   */
+  int i = 0;
+  HINTERNET hInternet;
+  HINTERNET res;
+  hInternet = InternetOpen (
+#ifndef WIN32
+			    (LPCTSTR)
+#endif
+			    "ZooWPSClient\0",
+			    INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
+
+#ifndef WIN32
+  if (!CHECK_INET_HANDLE (hInternet))
+    fprintf (stderr, "WARNING : hInternet handle failed to initialize");
+#endif
+  maps *request_input_real_format = NULL;
+  maps *tmpmaps = request_input_real_format;
+
+
+  if(parseRequest(&m,&request_inputs,s1,&request_input_real_format,&request_output_real_format,&hInternet)<0){
+    freeMaps (&m);
+    free (m);
+    free (REQUEST);
+    free (SERVICE_URL);
+    InternetCloseHandle (&hInternet);
+    freeService (&s1);
+    free (s1);
+    return 0;
+  }
+
+
+  // Define each env variable in runing environment
+  maps *curs = getMaps (m, "env");
+  if (curs != NULL)
+    {
+      map *mapcs = curs->content;
+      while (mapcs != NULLMAP)
+        {
+#ifndef WIN32
+          setenv (mapcs->name, mapcs->value, 1);
+#else
+#ifdef DEBUG
+          fprintf (stderr, "[ZOO: setenv (%s=%s)]\n", mapcs->name,
+                   mapcs->value);
+#endif
+          if (mapcs->value[strlen (mapcs->value) - 2] == '\r')
+            {
+#ifdef DEBUG
+              fprintf (stderr, "[ZOO: Env var finish with \r]\n");
+#endif
+              mapcs->value[strlen (mapcs->value) - 1] = 0;
+            }
+#ifdef DEBUG
+          if (SetEnvironmentVariable (mapcs->name, mapcs->value) == 0)
+            {
+              fflush (stderr);
+              fprintf (stderr, "setting variable... %s\n", "OK");
+            }
+          else
+            {
+              fflush (stderr);
+              fprintf (stderr, "setting variable... %s\n", "OK");
+            }
+#else
+
+
+          SetEnvironmentVariable (mapcs->name, mapcs->value);
+#endif
+          char *toto =
+            (char *)
+            malloc ((strlen (mapcs->name) + strlen (mapcs->value) +
+                     2) * sizeof (char));
+          sprintf (toto, "%s=%s", mapcs->name, mapcs->value);
+          putenv (toto);
+#ifdef DEBUG
+          fflush (stderr);
+#endif
+#endif
+#ifdef DEBUG
+          fprintf (stderr, "[ZOO: setenv (%s=%s)]\n", mapcs->name,
+                   mapcs->value);
+          fflush (stderr);
+#endif
+          mapcs = mapcs->next;
+        }
+    }
+
+#ifdef DEBUG
+  dumpMap (request_inputs);
+#endif
+
+  map *status = getMap (request_inputs, "status");
+  if(vid==0){
+    // Need to check if we need to fork to load a status enabled 
+    r_inputs = NULL;
+    map *store = getMap (request_inputs, "storeExecuteResponse");
+    /**
+     * 05-007r7 WPS 1.0.0 page 57 :
+     * 'If status="true" and storeExecuteResponse is "false" then the service 
+     * shall raise an exception.'
+     */
+    if (status != NULL && strcmp (status->value, "true") == 0 &&
+	store != NULL && strcmp (store->value, "false") == 0)
+      {
+	errorException (m,
+			_
+			("The status parameter cannot be set to true if storeExecuteResponse is set to false. Please modify your request parameters."),
+			"InvalidParameterValue", "storeExecuteResponse");
+	freeService (&s1);
+	free (s1);
+	freeMaps (&m);
+	free (m);
+	
+	freeMaps (&request_input_real_format);
+	free (request_input_real_format);
+	
+	freeMaps (&request_output_real_format);
+	free (request_output_real_format);
+
+	free (REQUEST);
+	free (SERVICE_URL);
+	return 1;
+      }
+    r_inputs = getMap (request_inputs, "storeExecuteResponse");
+  }else{
+    // Define status depending on the WPS 2.0.0 mode attribute
+    status = getMap (request_inputs, "mode");
+    map* mode=getMap(s1->content,"mode");
+    if(strcasecmp(status->value,"async")==0){
+      if(mode!=NULL && strcasecmp(mode->value,"async")==0)
+	addToMap(request_inputs,"status","true");
+      else{
+	if(mode!=NULL){
+	  // see ref. http://docs.opengeospatial.org/is/14-065/14-065.html#61
+	  errorException (m,_("The process does not permit the desired execution mode."),"NoSuchMode", mode->value);  
+	  fflush (stdout);
+	  freeMaps (&m);
+	  free (m);
+	  if(zooRegistry!=NULL){
+	    freeRegistry(&zooRegistry);
+	    free(zooRegistry);
+	  }
+	  freeMaps (&request_input_real_format);
+	  free (request_input_real_format);
+	  freeMaps (&request_output_real_format);
+	  free (request_output_real_format);
+	  free (REQUEST);
+	  free (SERVICE_URL);
+	  return 0;
+	}else
+	  addToMap(request_inputs,"status","true");
+      }
+    }
+    else{
+      if(strcasecmp(status->value,"auto")==0){
+	if(mode!=NULL){
+	  if(strcasecmp(mode->value,"async")==0)
+	    addToMap(request_inputs,"status","false");
+	  else
+	    addToMap(request_inputs,"status","true");
+	}
+	else
+	  addToMap(request_inputs,"status","false");
+      }else
+	addToMap(request_inputs,"status","false");
+    }
+    status = getMap (request_inputs, "status");
+  }
+
+  int eres = SERVICE_STARTED;
+  int cpid = getpid ();
+
+  /**
+   * Initialize the specific [lenv] section which contains runtime variables:
+   * 
+   *  - usid : it is an universally unique identifier  
+   *  - osid : it is an idenfitication number 
+   *  - sid : it is the process idenfitication number (OS)
+   *  - uusid : it is an universally unique identifier 
+   *  - status : value between 0 and 100 to express the  completude of 
+   * the operations of the running service 
+   *  - message : is a string where you can store error messages, in case 
+   * service is failing, or o provide details on the ongoing operation.
+   *  - cwd : is the current working directory
+   *  - soap : is a boolean value, true if the request was contained in a SOAP 
+   * Envelop 
+   *  - sessid : string storing the session identifier (only when cookie is 
+   * used)
+   *  - cgiSid : only defined on Window platforms (for being able to identify 
+   * the created process)
+   *
+   */
+  maps *_tmpMaps = (maps *) malloc (MAPS_SIZE);
+  _tmpMaps->name = zStrdup ("lenv");
+  char tmpBuff[100];
+  struct ztimeval tp;
+  if (zGettimeofday (&tp, NULL) == 0)
+    sprintf (tmpBuff, "%i", (cpid + ((int) tp.tv_sec + (int) tp.tv_usec)));
+  else
+    sprintf (tmpBuff, "%i", (cpid + (int) time (NULL)));
+  _tmpMaps->content = createMap ("osid", tmpBuff);
+  _tmpMaps->next = NULL;
+  sprintf (tmpBuff, "%i", cpid);
+  addToMap (_tmpMaps->content, "sid", tmpBuff);
+  char* tmpUuid=get_uuid();
+  addToMap (_tmpMaps->content, "uusid", tmpUuid);
+  addToMap (_tmpMaps->content, "usid", tmpUuid);
+  free(tmpUuid);
+  addToMap (_tmpMaps->content, "status", "0");
+  addToMap (_tmpMaps->content, "cwd", ntmp);
+  addToMap (_tmpMaps->content, "message", _("No message provided"));
+  map *ltmp = getMap (request_inputs, "soap");
+  if (ltmp != NULL)
+    addToMap (_tmpMaps->content, "soap", ltmp->value);
+  else
+    addToMap (_tmpMaps->content, "soap", "false");
+
+  // Parse the session file and add it to the main maps 
+  if (cgiCookie != NULL && strlen (cgiCookie) > 0)
+    {
+      int hasValidCookie = -1;
+      char *tcook = zStrdup (cgiCookie);
+      char *tmp = NULL;
+      map *testing = getMapFromMaps (m, "main", "cookiePrefix");
+      if (testing == NULL)
+        {
+          tmp = zStrdup ("ID=");
+        }
+      else
+        {
+          tmp =
+            (char *) malloc ((strlen (testing->value) + 2) * sizeof (char));
+          sprintf (tmp, "%s=", testing->value);
+        }
+      if (strstr (cgiCookie, ";") != NULL)
+        {
+          char *token, *saveptr;
+          token = strtok_r (cgiCookie, ";", &saveptr);
+          while (token != NULL)
+            {
+              if (strcasestr (token, tmp) != NULL)
+                {
+                  if (tcook != NULL)
+                    free (tcook);
+                  tcook = zStrdup (token);
+                  hasValidCookie = 1;
+                }
+              token = strtok_r (NULL, ";", &saveptr);
+            }
+        }
+      else
+        {
+          if (strstr (cgiCookie, "=") != NULL
+              && strcasestr (cgiCookie, tmp) != NULL)
+            {
+              tcook = zStrdup (cgiCookie);
+              hasValidCookie = 1;
+            }
+          if (tmp != NULL)
+            {
+              free (tmp);
+            }
+        }
+      if (hasValidCookie > 0)
+        {
+          addToMap (_tmpMaps->content, "sessid", strstr (tcook, "=") + 1);
+          char session_file_path[1024];
+          map *tmpPath = getMapFromMaps (m, "main", "sessPath");
+          if (tmpPath == NULL)
+            tmpPath = getMapFromMaps (m, "main", "tmpPath");
+          char *tmp1 = strtok (tcook, ";");
+          if (tmp1 != NULL)
+            sprintf (session_file_path, "%s/sess_%s.cfg", tmpPath->value,
+                     strstr (tmp1, "=") + 1);
+          else
+            sprintf (session_file_path, "%s/sess_%s.cfg", tmpPath->value,
+                     strstr (cgiCookie, "=") + 1);
+          free (tcook);
+          maps *tmpSess = (maps *) malloc (MAPS_SIZE);
+          struct stat file_status;
+          int istat = stat (session_file_path, &file_status);
+          if (istat == 0 && file_status.st_size > 0)
+            {
+              conf_read (session_file_path, tmpSess);
+              addMapsToMaps (&m, tmpSess);
+              freeMaps (&tmpSess);
+              free (tmpSess);
+            }
+        }
+    }
+  addMapsToMaps (&m, _tmpMaps);
+  freeMaps (&_tmpMaps);
+  free (_tmpMaps);
+  maps* bmap=NULL;
+#ifdef DEBUG
+  dumpMap (request_inputs);
+#endif
+#ifdef WIN32
+  char *cgiSidL = NULL;
+  if (getenv ("CGISID") != NULL)
+    addToMap (request_inputs, "cgiSid", getenv ("CGISID"));
+
+  char* usidp;
+  if ( (usidp = getenv("USID")) != NULL ) {
+    setMapInMaps (m, "lenv", "usid", usidp);
+  }
+
+  map *test1 = getMap (request_inputs, "cgiSid");
+  if (test1 != NULL){
+    cgiSid = zStrdup(test1->value);
+    addToMap (request_inputs, "storeExecuteResponse", "true");
+    addToMap (request_inputs, "status", "true");
+    setMapInMaps (m, "lenv", "osid", test1->value);
+    status = getMap (request_inputs, "status");
+  }
+  test1 = getMap (request_inputs, "usid");
+  if (test1 != NULL){
+    setMapInMaps (m, "lenv", "usid", test1->value);
+    setMapInMaps (m, "lenv", "uusid", test1->value);
+  }
+#endif
+  char *fbkp, *fbkpid, *fbkpres, *fbkp1, *flog;
+  FILE *f0, *f1;
+  if (status != NULL)
+    if (strcasecmp (status->value, "false") == 0)
+      status = NULLMAP;
+  if (status == NULLMAP)
+    {
+      if(validateRequest(&m,s1,request_inputs, &request_input_real_format,&request_output_real_format,&hInternet)<0){
+	freeService (&s1);
+	free (s1);
+	freeMaps (&m);
+	free (m);
+	free (REQUEST);
+	free (SERVICE_URL);
+	freeMaps (&request_input_real_format);
+	free (request_input_real_format);
+	freeMaps (&request_output_real_format);
+	free (request_output_real_format);
+	freeMaps (&tmpmaps);
+	free (tmpmaps);
+	return -1;
+      }
+
+      loadServiceAndRun (&m, s1, request_inputs, &request_input_real_format,
+                         &request_output_real_format, &eres);
+    }
+  else
+    {
+      int pid;
+#ifdef DEBUG
+      fprintf (stderr, "\nPID : %d\n", cpid);
+#endif
+
+#ifndef WIN32
+      pid = fork ();
+#else
+      if (cgiSid == NULL)
+        {
+          createProcess (m, request_inputs, s1, NULL, cpid,
+                         request_input_real_format,
+                         request_output_real_format);
+          pid = cpid;
+        }
+      else
+        {
+          pid = 0;
+          cpid = atoi (cgiSid);
+	  updateStatus(m,0,_("Initializing"));
+        }
+#endif
+      if (pid > 0)
+        {
+	  /**
+	   * dady :
+	   * set status to SERVICE_ACCEPTED
+	   */
+#ifdef DEBUG
+          fprintf (stderr, "father pid continue (origin %d) %d ...\n", cpid,
+                   getpid ());
+#endif
+          eres = SERVICE_ACCEPTED;
+        }
+      else if (pid == 0)
+        {
+	  /**
+	   * son : have to close the stdout, stdin and stderr to let the parent
+	   * process answer to http client.
+	   */
+	  map* usid = getMapFromMaps (m, "lenv", "uusid");
+          map* tmpm = getMapFromMaps (m, "lenv", "osid");
+          int cpid = atoi (tmpm->value);
+          r_inputs = getMapFromMaps (m, "main", "tmpPath");
+	  map* r_inputs1 = createMap("ServiceName", s1->name);
+
+	  // Create the filename for the result file (.res)
+          fbkpres =
+            (char *)
+            malloc ((strlen (r_inputs->value) +
+                     strlen (usid->value) + 7) * sizeof (char));
+          sprintf (fbkpres, "%s/%s.res", r_inputs->value, usid->value);
+	  bmap = (maps *) malloc (MAPS_SIZE);
+	  bmap->name=zStrdup("status");
+	  bmap->content=createMap("usid",usid->value);
+	  bmap->next=NULL;
+	  addToMap(bmap->content,"sid",tmpm->value);
+	  addIntToMap(bmap->content,"pid",getpid());
+	  
+	  // Create PID file referencing the OS process identifier
+          fbkpid =
+            (char *)
+            malloc ((strlen (r_inputs->value) +
+                     strlen (usid->value) + 7) * sizeof (char));
+          sprintf (fbkpid, "%s/%s.pid", r_inputs->value, usid->value);
+
+          f0 = freopen (fbkpid, "w+",stdout);
+	  printf("%d",getpid());
+	  fflush(stdout);
+
+	  // Create SID file referencing the semaphore name
+          fbkp =
+            (char *)
+            malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) +
+                     strlen (usid->value) + 7) * sizeof (char));
+          sprintf (fbkp, "%s/%s.sid", r_inputs->value, usid->value);
+          FILE* f2 = freopen (fbkp, "w+",stdout);
+	  printf("%s",tmpm->value);
+	  fflush(f2);
+	  free(fbkp);
+
+          fbkp =
+            (char *)
+            malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) +
+                     strlen (usid->value) + 7) * sizeof (char));
+          sprintf (fbkp, "%s/%s_%s.xml", r_inputs->value, r_inputs1->value,
+                   usid->value);
+          flog =
+            (char *)
+            malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) +
+                     strlen (usid->value) + 13) * sizeof (char));
+          sprintf (flog, "%s/%s_%s_error.log", r_inputs->value,
+                   r_inputs1->value, usid->value);
+#ifdef DEBUG
+          fprintf (stderr, "RUN IN BACKGROUND MODE \n");
+          fprintf (stderr, "son pid continue (origin %d) %d ...\n", cpid,
+                   getpid ());
+          fprintf (stderr, "\nFILE TO STORE DATA %s\n", r_inputs->value);
+#endif
+          freopen (flog, "w+", stderr);
+          fflush (stderr);
+	  f0 = freopen (fbkp, "w+", stdout);
+	  rewind (stdout);
+#ifndef WIN32
+	  fclose (stdin);
+#endif
+#ifdef RELY_ON_DB
+	  init_sql(m);
+	  recordServiceStatus(m);
+#endif
+	  if(vid==0){
+	    /**
+	     * set status to SERVICE_STARTED and flush stdout to ensure full 
+	     * content was outputed (the file used to store the ResponseDocument).
+	     * The rewind stdout to restart writing from the bgining of the file,
+	     * this way the data will be updated at the end of the process run.
+	     */
+	    printProcessResponse (m, request_inputs, cpid, s1, r_inputs1->value,
+				  SERVICE_STARTED, request_input_real_format,
+				  request_output_real_format);
+	    fflush (stdout);
+#ifdef RELY_ON_DB
+	    recordResponse(m,fbkp);
+#endif
+	  }
+
+          fflush (stderr);
+
+          fbkp1 =
+            (char *)
+            malloc ((strlen (r_inputs->value) + strlen (r_inputs1->value) +
+                     strlen (usid->value) + 13) * sizeof (char));
+          sprintf (fbkp1, "%s/%s_final_%s.xml", r_inputs->value,
+                   r_inputs1->value, usid->value);
+
+          f1 = freopen (fbkp1, "w+", stdout);
+
+	  if(validateRequest(&m,s1,request_inputs, &request_input_real_format,&request_output_real_format,&hInternet)<0){
+	    freeService (&s1);
+	    free (s1);
+	    freeMaps (&m);
+	    free (m);
+	    free (REQUEST);
+	    free (SERVICE_URL);
+	    freeMaps (&request_input_real_format);
+	    free (request_input_real_format);
+	    freeMaps (&request_output_real_format);
+	    free (request_output_real_format);
+	    freeMaps (&tmpmaps);
+	    free (tmpmaps);
+	    fflush (stdout);
+	    fflush (stderr);
+	    unhandleStatus (m);
+	    return -1;
+	  }
+          loadServiceAndRun (&m, s1, request_inputs,
+                             &request_input_real_format,
+                             &request_output_real_format, &eres);
+        }
+      else
+        {
+	  /**
+	   * error server don't accept the process need to output a valid 
+	   * error response here !!!
+	   */
+          eres = -1;
+          errorException (m, _("Unable to run the child process properly"),
+                          "InternalError", NULL);
+        }
+    }
+
+#ifdef DEBUG
+  dumpMaps (request_output_real_format);
+#endif
+  if (eres != -1)
+    outputResponse (s1, request_input_real_format,
+                    request_output_real_format, request_inputs,
+                    cpid, m, eres);
+  fflush (stdout);
+  
+  /**
+   * Ensure that if error occurs when freeing memory, no signal will return
+   * an ExceptionReport document as the result was already returned to the 
+   * client.
+   */
+#ifndef USE_GDB
+  signal (SIGSEGV, donothing);
+  signal (SIGTERM, donothing);
+  signal (SIGINT, donothing);
+  signal (SIGILL, donothing);
+  signal (SIGFPE, donothing);
+  signal (SIGABRT, donothing);
+#endif
+  if (((int) getpid ()) != cpid || cgiSid != NULL)
+    {
+      fclose (stdout);
+      fclose (stderr);
+      /**
+       * Dump back the final file fbkp1 to fbkp
+       */
+      fclose (f0);
+      fclose (f1);
+
+      FILE *f2 = fopen (fbkp1, "rb");
+#ifndef RELY_ON_DB
+      semid lid = getShmLockId (m, 1);
+      if (lid < 0)
+        return -1;
+      lockShm (lid);
+#endif
+      FILE *f3 = fopen (fbkp, "wb+");
+      free (fbkp);
+      fseek (f2, 0, SEEK_END);
+      long flen = ftell (f2);
+      fseek (f2, 0, SEEK_SET);
+      char *tmps1 = (char *) malloc ((flen + 1) * sizeof (char));
+      fread (tmps1, flen, 1, f2);
+#ifdef WIN32
+      char *pchr=strrchr(tmps1,'>');
+      flen=strlen(tmps1)-strlen(pchr)+1;
+      tmps1[flen]=0;
+#endif
+      fwrite (tmps1, 1, flen, f3);
+      fclose (f2);
+      fclose (f3);
+      unlink (fbkpid);
+      switch(eres){
+      default:
+      case SERVICE_FAILED:
+	setMapInMaps(bmap,"status","status",wpsStatus[1]);
+	setMapInMaps(m,"lenv","fstate",wpsStatus[1]);
+	break;
+      case SERVICE_SUCCEEDED:
+	setMapInMaps(bmap,"status","status",wpsStatus[0]);
+	setMapInMaps(m,"lenv","fstate",wpsStatus[0]);
+	break;
+      }
+#ifndef RELY_ON_DB
+      dumpMapsToFile(bmap,fbkpres,1);
+      removeShmLock (m, 1);
+#else
+      recordResponse(m,fbkp1);
+#endif
+      freeMaps(&bmap);
+      free(bmap);
+      unlink (fbkp1);
+      unlink (flog);
+      unhandleStatus (m);
+      free(fbkpid);
+      free(fbkpres);
+      free (flog);
+      free (fbkp1);
+      free (tmps1);
+      if(cgiSid!=NULL)
+	free(cgiSid);
+    }
+
+  freeService (&s1);
+  free (s1);
+  freeMaps (&m);
+  free (m);
+
+  freeMaps (&request_input_real_format);
+  free (request_input_real_format);
+
+  freeMaps (&request_output_real_format);
+  free (request_output_real_format);
+
+  free (REQUEST);
+  free (SERVICE_URL);
+#ifdef DEBUG
+  fprintf (stderr, "Processed response \n");
+  fflush (stdout);
+  fflush (stderr);
+#endif
+
+  if (((int) getpid ()) != cpid || cgiSid != NULL)
+    {
+      exit (0);
+    }
+
+  return 0;
+}
diff --git a/zoo-project/zoo-services/arithmetics/Makefile b/zoo-project/zoo-services/arithmetics/Makefile
new file mode 100644
index 0000000..5ebbd49
--- /dev/null
+++ b/zoo-project/zoo-services/arithmetics/Makefile
@@ -0,0 +1,8 @@
+CFLAGS=-I../../zoo-kernel/ -I./ `xml2-config --cflags` `python-config --cflags`  `gdal-config --cflags`   -DLINUX_FREE_ISSUE #-DDEBUG
+CC=gcc
+
+cgi-env/test_service.zo: test_service.c
+	g++ ${CFLAGS} -shared -fpic -o cgi-env/test_service.zo ./test_service.c -lzoo_service
+
+clean:
+	rm -f cgi-env/test_service.zo
diff --git a/zoo-project/zoo-services/arithmetics/cgi-env/Multiply.zcfg b/zoo-project/zoo-services/arithmetics/cgi-env/Multiply.zcfg
new file mode 100755
index 0000000..1db47ce
--- /dev/null
+++ b/zoo-project/zoo-services/arithmetics/cgi-env/Multiply.zcfg
@@ -0,0 +1,43 @@
+[Multiply]
+ Title = Multiply two values
+ Abstract = Multiply two values and stor the result in Result.
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = test_service.zo
+ serviceType = C
+ <MetaData>
+   title = Demo
+ </MetaData>
+ <DataInputs>
+  [A]
+   Title = first value
+   Abstract = The value used to multiply by B.
+   minOccurs = 1
+   maxOccurs = 1
+   <LiteralData>
+    DataType = float
+    <Default>
+    </Default>
+   </LiteralData>
+  [B]
+   Title = second value
+   Abstract = The value used to multiply by A.
+   minOccurs = 1
+   maxOccurs = 1
+   <LiteralData>
+    DataType = float
+    <Default>
+    </Default>
+   </LiteralData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = A x B 
+   Abstract = The value of A x B.
+   <LiteralOutput>
+    DataType = float
+    <Default>
+    </Default>
+   </LiteralOutput>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/arithmetics/makefile.vc b/zoo-project/zoo-services/arithmetics/makefile.vc
new file mode 100644
index 0000000..f0bd617
--- /dev/null
+++ b/zoo-project/zoo-services/arithmetics/makefile.vc
@@ -0,0 +1,12 @@
+TROOT= ../
+!INCLUDE ../../zoo-kernel/nmake.opt
+
+#CFLAGS=-I$(GEODIR)/include -I$(TOOLS)/include -I../../zoo-kernel/ -I./ -DLINUX_FREE_ISSUE -DDEBUG -DWIN32
+#CPP=cl /TP 
+
+cgi-env/test_service.zo: test_service.c
+	$(CPP) -DWIN32 -DZOO_SERVICE -DNEED_STRCASESTR $(CFLAGS) /c test_service.c
+	link /dll /out:cgi-env/test_service.zo ../../zoo-kernel/service_internal.obj ../../zoo-kernel/ulinet.obj ../../zoo-kernel/service_internal_ms.obj ../../zoo-kernel/service_internal_js.obj ./test_service.obj $(LDFLAGS)
+
+clean:
+	erase cgi-env\demo_service.*
diff --git a/zoo-project/zoo-services/arithmetics/test_service.c b/zoo-project/zoo-services/arithmetics/test_service.c
new file mode 100644
index 0000000..964e62f
--- /dev/null
+++ b/zoo-project/zoo-services/arithmetics/test_service.c
@@ -0,0 +1,42 @@
+#include "service.h"
+
+extern "C" {
+
+#ifdef WIN32
+__declspec(dllexport)
+#endif
+  int Multiply(maps*& conf,maps*& inputs,maps*& outputs){
+  	fprintf(stderr,"\nService internal print\n");
+  	maps* cursor=inputs;
+	int A,B,res;
+	A=0;B=0;
+	if(cursor!=NULL){
+		fprintf(stderr,"\nService internal print\n");
+		dumpMaps(cursor);
+		maps* tmp=getMaps(inputs,"A");
+		if(tmp==NULL)
+			return SERVICE_FAILED;
+		fprintf(stderr,"\nService internal print\n");
+		dumpMap(tmp->content);
+		map* tmpv=getMap(tmp->content,"value");
+		fprintf(stderr,"\nService internal print\n");
+		A=atoi(tmpv->value);
+		fprintf(stderr,"\nService internal print (A value: %i)\n",A);
+		cursor=cursor->next;
+	}
+	if(cursor!=NULL){
+		maps* tmp=getMaps(cursor,"B");
+		map* tmpv=getMap(tmp->content,"value");
+		if(tmpv==NULL)
+			return SERVICE_FAILED;
+		B=atoi(tmpv->value);
+		fprintf(stderr,"\nService internal print (B value: %i)\n",B);
+	}
+	res=A*B;
+	char tmp[256];
+	sprintf(tmp,"%i",res);
+	setMapInMaps(outputs,"Result","value",tmp);
+	return SERVICE_SUCCEEDED;
+  }
+
+}
diff --git a/zoo-project/zoo-services/cgal/Makefile b/zoo-project/zoo-services/cgal/Makefile
new file mode 100644
index 0000000..6d3a4ec
--- /dev/null
+++ b/zoo-project/zoo-services/cgal/Makefile
@@ -0,0 +1,19 @@
+ZRPATH=../..
+include ${ZRPATH}/zoo-kernel/ZOOMakefile.opts
+CFLAGS=${ZOO_CFLAGS} ${XML2CFLAGS} ${GDAL_CFLAGS} ${PYTHONCFLAGS} ${CGAL_CFLAGS} -frounding-math -fPIC -DLINUX_FREE_ISSUE #-DDEBUG
+CC=gcc
+
+cgi-env/cgal_service.zo: delaunay.c voronoi.c cgal_service.o
+	g++ ${CFLAGS} -c ./delaunay.c
+	g++ ${CFLAGS} -c ./voronoi.c
+	g++ ${CFLAGS} -shared -o cgi-env/cgal_service.zo ./delaunay.o ./voronoi.o ./cgal_service.o ${GDAL_LIBS} ${MACOS_LD_FLAGS} ${CGAL_LDFLAGS} -lCGAL -lgmp -lgdal -lzoo_service
+
+cgal_service.o: cgal_service.c cgal_service.h
+	g++ ${CFLAGS} -c ./cgal_service.c
+
+install:
+	install -d ${CGI_DIR}/cgal
+	install cgi-env/* ${CGI_DIR}/cgal/
+
+clean:
+	rm -f cgi-env/*.zo *.o
diff --git a/zoo-project/zoo-services/cgal/cgal_service.c b/zoo-project/zoo-services/cgal/cgal_service.c
new file mode 100644
index 0000000..bf34f63
--- /dev/null
+++ b/zoo-project/zoo-services/cgal/cgal_service.c
@@ -0,0 +1,81 @@
+/**
+ * Author : Gérald FENOY
+ *
+ * Copyright 2009-2013 GeoLabs SARL. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "cgal_service.h"
+
+int parseInput(maps* conf,maps* inputs, std::vector<Point>* points,char* filename){
+  map* tmpm=NULL;
+  tmpm=getMapFromMaps(inputs,"InputPoints","value");
+  VSILFILE *ifile=VSIFileFromMemBuffer(filename,(GByte*)tmpm->value,strlen(tmpm->value),FALSE);
+  VSIFCloseL(ifile);
+  OGRDataSource* ipoDS = OGRSFDriverRegistrar::Open(filename,FALSE);
+  if( ipoDS == NULL )
+    {
+      OGRSFDriverRegistrar    *poR = OGRSFDriverRegistrar::GetRegistrar();
+      
+      fprintf( stderr, "FAILURE:\n"
+	       "Unable to open datasource `%s' with the following drivers.\n",
+	       filename );
+      
+      for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
+        {
+	  fprintf( stderr, "  -> %s\n", poR->GetDriver(iDriver)->GetName() );
+        }
+      char tmp[1024];
+      sprintf(tmp,"Unable to open datasource `%s' with the following drivers.",filename);
+      setMapInMaps(conf,"lenv","message",tmp);
+      return SERVICE_FAILED;
+    }
+  for( int iLayer = 0; iLayer < ipoDS->GetLayerCount();
+       iLayer++ )
+    {
+      OGRLayer        *poLayer = ipoDS->GetLayer(iLayer);
+      
+      if( poLayer == NULL )
+	{
+	  fprintf( stderr, "FAILURE: Couldn't fetch advertised layer %d!\n",
+		   iLayer );
+#ifdef ZOO_SERVICE
+	  char tmp[1024];
+	  sprintf(tmp,"Couldn't fetch advertised layer %d!",iLayer);
+	  setMapInMaps(conf,"lenv","message",tmp);
+	  return SERVICE_FAILED;
+#else
+	  exit( 1 );
+#endif
+	}
+      
+      OGRFeature  *poFeature;
+      while(TRUE){
+	poFeature = poLayer->GetNextFeature();
+	if( poFeature == NULL )
+	  break;
+	if(poFeature->GetGeometryRef() != NULL){
+	  points->push_back(Point(OGR_G_GetX(poFeature->GetGeometryRef(),0),OGR_G_GetY(poFeature->GetGeometryRef(),0)));
+	}
+      }
+    }
+  return SERVICE_SUCCEEDED;
+}
+
+
diff --git a/zoo-project/zoo-services/cgal/cgal_service.h b/zoo-project/zoo-services/cgal/cgal_service.h
new file mode 100644
index 0000000..4ee90a8
--- /dev/null
+++ b/zoo-project/zoo-services/cgal/cgal_service.h
@@ -0,0 +1,45 @@
+/**
+ * Author : Gérald FENOY
+ *
+ * Copyright 2009-2013 GeoLabs SARL. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef ZOO_CGAL_SERVICE_H
+#define ZOO_CGAL_SERVICE_H
+
+#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
+#include <CGAL/Delaunay_triangulation_2.h>
+#include <CGAL/Triangulation_vertex_base_with_info_2.h>
+#include <vector>
+
+#include "cpl_minixml.h"
+#include "ogr_api.h"
+#include "ogrsf_frmts.h"
+#include "service.h"
+#include "service_internal.h"
+
+typedef CGAL::Exact_predicates_inexact_constructions_kernel            Kernel;
+typedef Kernel::Point_2                                                Point;
+
+int parseInput(maps*,maps*, std::vector<Point>*,char*);
+
+#endif
+
diff --git a/zoo-project/zoo-services/cgal/cgi-env/Delaunay.zcfg b/zoo-project/zoo-services/cgal/cgi-env/Delaunay.zcfg
new file mode 100755
index 0000000..4290073
--- /dev/null
+++ b/zoo-project/zoo-services/cgal/cgi-env/Delaunay.zcfg
@@ -0,0 +1,55 @@
+[Delaunay]
+ Title = Delaunay Triangulation. 
+ Abstract = Computes the edges of a Delaunay triangulation for a set of data points.
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = cgal_service.zo
+ serviceType = C
+ <MetaData>
+   title = Demo
+ </MetaData>
+ <DataInputs>
+  [InputPoints]
+   Title = Data points
+   Abstract = The set of data points.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://schemas.opengis.net/gml/3.1.0/base/feature.xsd
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://schemas.opengis.net/gml/3.1.0/base/feature.xsd
+    </Supported>
+   </ComplexData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = Delaunay Triangulation
+   Abstract = JSON String / GML Entity of the Delaunay Triangulation.
+   <ComplexOutput>
+    <Default>
+     mimeType = application/json
+     encoding = UTF-8
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://schemas.opengis.net/gml/3.1.0/base/feature.xsd
+    </Supported>
+    <Supported>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://schemas.opengis.net/gml/3.1.0/base/feature.xsd
+     asReference = true	
+    </Supported>
+   </ComplexOutput>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/cgal/cgi-env/Voronoi.zcfg b/zoo-project/zoo-services/cgal/cgi-env/Voronoi.zcfg
new file mode 100755
index 0000000..9d6d6f7
--- /dev/null
+++ b/zoo-project/zoo-services/cgal/cgi-env/Voronoi.zcfg
@@ -0,0 +1,59 @@
+[Voronoi]
+ Title = Voronoi Diagram. 
+ Abstract = Computes the edges of Voronoi diagram for a set of data points.
+ Profile = urn:ogc:wps:1.0.0:voronoi
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = cgal_service.zo
+ serviceType = C
+ <MetaData>
+   title = Demo
+ </MetaData>
+ <DataInputs>
+  [InputPoints]
+   Title = Data points
+   Abstract = The set of data points.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://schemas.opengis.net/gml/3.1.0/base/feature.xsd
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://schemas.opengis.net/gml/3.1.0/base/feature.xsd
+    </Supported>
+   </ComplexData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = Voronoi Diagram.
+   Abstract = JSON String / GML Entity of the Voronoi Diagram.
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <ComplexOutput>
+    <Default>
+     mimeType = application/json
+     encoding = UTF-8
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://schemas.opengis.net/gml/3.1.0/base/feature.xsd
+    </Supported>
+    <Supported>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://schemas.opengis.net/gml/3.1.0/base/feature.xsd
+     asReference = true	
+    </Supported>
+   </ComplexOutput>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/cgal/delaunay.c b/zoo-project/zoo-services/cgal/delaunay.c
new file mode 100644
index 0000000..29ae586
--- /dev/null
+++ b/zoo-project/zoo-services/cgal/delaunay.c
@@ -0,0 +1,187 @@
+/**
+ * Author : Gérald FENOY
+ *
+ * Copyright 2009-2013 GeoLabs SARL. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "cgal_service.h"
+typedef CGAL::Triangulation_vertex_base_with_info_2<unsigned int, Kernel> Vb;
+typedef CGAL::Triangulation_data_structure_2<Vb>                       Tds;
+typedef CGAL::Delaunay_triangulation_2<Kernel, Tds>                    DelaunayT;
+
+extern "C" {
+
+  int Delaunay(maps*& conf,maps*& inputs,maps*& outputs){
+#ifdef DEBUG
+    fprintf(stderr,"\nService internal print\nStarting\n");
+#endif
+    maps* cursor=inputs;
+    OGRGeometryH geometry,res;
+    int bufferDistance;
+    map* tmpm=NULL;
+    OGRRegisterAll();
+
+    std::vector<Point> points;
+    if(int res=parseInput(conf,inputs,&points,"/vsimem/tmp")!=SERVICE_SUCCEEDED)
+      return res;
+
+    DelaunayT T;
+    T.insert(points.begin(), points.end());
+
+    /* -------------------------------------------------------------------- */
+    /*      Try opening the output datasource as an existing, writable      */
+    /* -------------------------------------------------------------------- */
+    OGRDataSource       *poODS;
+    
+    OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
+    OGRSFDriver          *poDriver = NULL;
+    int                  iDriver;
+
+    map *tmpMap=getMapFromMaps(outputs,"Result","mimeType");
+    const char *oDriver;
+    oDriver="GeoJSON";
+    if(tmpMap!=NULL){
+      if(strcmp(tmpMap->value,"text/xml")==0){
+	oDriver="GML";
+      }
+    }
+    
+    for( iDriver = 0;
+	 iDriver < poR->GetDriverCount() && poDriver == NULL;
+	 iDriver++ )
+      {
+#ifdef DEBUG
+	fprintf(stderr,"D:%s\n",poR->GetDriver(iDriver)->GetName());
+#endif
+	if( EQUAL(poR->GetDriver(iDriver)->GetName(),oDriver) )
+	  {
+	    poDriver = poR->GetDriver(iDriver);
+	  }
+      }
+
+    if( poDriver == NULL )
+      {
+	char emessage[8192];
+	sprintf( emessage, "Unable to find driver `%s'.\n", oDriver );
+	sprintf( emessage,  "%sThe following drivers are available:\n",emessage );
+        
+	for( iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
+	  {
+	    sprintf( emessage,  "%s  -> `%s'\n", emessage, poR->GetDriver(iDriver)->GetName() );
+	  }
+
+	setMapInMaps(conf,"lenv","message",emessage);
+	return SERVICE_FAILED;
+
+      }
+
+    if( !poDriver->TestCapability( ODrCCreateDataSource ) ){
+      char emessage[1024];
+      sprintf( emessage,  "%s driver does not support data source creation.\n",
+	       "json" );
+      setMapInMaps(conf,"lenv","message",emessage);
+      return SERVICE_FAILED;
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Create the output data source.                                  */
+    /* -------------------------------------------------------------------- */
+    char *pszDestDataSource=(char*)malloc(100);
+    char **papszDSCO=NULL;
+    sprintf(pszDestDataSource,"/vsimem/result_%d",getpid());
+    poODS = poDriver->CreateDataSource( pszDestDataSource, papszDSCO );
+    if( poODS == NULL ){
+      char emessage[1024];      
+      sprintf( emessage,  "%s driver failed to create %s\n", 
+	       "json", pszDestDataSource );
+      setMapInMaps(conf,"lenv","message",emessage);
+      return SERVICE_FAILED;
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Create the layer.                                               */
+    /* -------------------------------------------------------------------- */
+    if( !poODS->TestCapability( ODsCCreateLayer ) )
+      {
+	char emessage[1024];
+	sprintf( emessage, 
+		 "Layer %s not found, and CreateLayer not supported by driver.", 
+		 "Result" );
+	setMapInMaps(conf,"lenv","message",emessage);
+	return SERVICE_FAILED;
+      }
+    
+    CPLErrorReset();
+    
+    OGRLayer *poDstLayer = poODS->CreateLayer( "Result", NULL,wkbPolygon,NULL);
+    if( poDstLayer == NULL ){
+      setMapInMaps(conf,"lenv","message","Layer creation failed.\n");
+      return SERVICE_FAILED;
+    }
+
+
+    for(DelaunayT::Finite_faces_iterator fit = T.finite_faces_begin();
+	fit != T.finite_faces_end(); ++fit) {
+      DelaunayT::Face_handle face = fit;
+      OGRFeatureH hFeature = OGR_F_Create( OGR_L_GetLayerDefn( poDstLayer ) );
+      OGRGeometryH hCollection = OGR_G_CreateGeometry( wkbGeometryCollection );
+      OGRGeometryH currLine=OGR_G_CreateGeometry(wkbLinearRing);
+      OGRGeometryH currPoly=OGR_G_CreateGeometry(wkbPolygon);
+      OGR_G_AddPoint_2D(currLine,T.triangle(face)[0].x(),T.triangle(face)[0].y());
+      OGR_G_AddPoint_2D(currLine,T.triangle(face)[1].x(),T.triangle(face)[1].y());
+      OGR_G_AddPoint_2D(currLine,T.triangle(face)[2].x(),T.triangle(face)[2].y());
+      OGR_G_AddPoint_2D(currLine,T.triangle(face)[0].x(),T.triangle(face)[0].y());
+      OGR_G_AddGeometryDirectly( currPoly, currLine ); 
+      OGR_G_AddGeometryDirectly( hCollection, currPoly ); 
+      OGR_F_SetGeometry( hFeature, hCollection ); 
+      OGR_G_DestroyGeometry(hCollection);
+      if( OGR_L_CreateFeature( poDstLayer, hFeature ) != OGRERR_NONE ){
+	setMapInMaps(conf,"lenv","message","Failed to create feature in file.\n");
+	return SERVICE_FAILED;
+      }
+      OGR_F_Destroy( hFeature );
+    }
+    OGR_DS_Destroy( poODS );
+
+#ifdef DEBUG
+    std::cerr << "The Voronoi diagram has " << ns << " finite edges "
+	      << " and " << nr << " rays" << std::endl;
+#endif
+
+    char *res1=readVSIFile(conf,pszDestDataSource);
+    if(res1==NULL)
+      return SERVICE_FAILED;
+
+    setMapInMaps(outputs,"Result","value",res1);
+    free(res1);
+
+    if(strcmp(oDriver,"GML")==0)
+      setMapInMaps(outputs,"Result","mimeType","text/xml");
+    else
+      setMapInMaps(outputs,"Result","mimeType","application/json");
+
+    setMapInMaps(outputs,"Result","encoding","UTF-8");
+    OGRCleanupAll();
+    
+    return SERVICE_SUCCEEDED;
+  }
+
+}
diff --git a/zoo-project/zoo-services/cgal/voronoi.c b/zoo-project/zoo-services/cgal/voronoi.c
new file mode 100644
index 0000000..22feb0d
--- /dev/null
+++ b/zoo-project/zoo-services/cgal/voronoi.c
@@ -0,0 +1,228 @@
+/**
+ * Author : Gérald FENOY
+ *
+ * Copyright 2009-2013 GeoLabs SARL. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
+#include <CGAL/Triangulation_euclidean_traits_xy_3.h>
+#include <CGAL/Delaunay_triangulation_2.h>
+#include <CGAL/Constrained_Delaunay_triangulation_2.h>
+#include <CGAL/Triangulation_conformer_2.h>
+#include <CGAL/Triangulation_face_base_2.h>
+
+#include <fstream>
+
+#include "cpl_minixml.h"
+#include "ogr_api.h"
+#include "ogrsf_frmts.h"
+#include "service.h"
+#include "cgal_service.h"
+
+typedef CGAL::Delaunay_triangulation_2<Kernel>  Triangulation;
+typedef Triangulation::Edge_iterator  Edge_iterator;
+typedef Triangulation::Vertex_circulator Vertex_circulator;
+
+extern "C" {
+
+  int Voronoi(maps*& conf,maps*& inputs,maps*& outputs){
+#ifdef DEBUG
+    fprintf(stderr,"\nService internal print\nStarting\n");
+#endif
+    maps* cursor=inputs;
+    OGRGeometryH geometry,res;
+    int bufferDistance;
+    map* tmpm=NULL;
+    tmpm=getMapFromMaps(inputs,"InputPoints","value");
+
+    OGRRegisterAll();
+
+    std::vector<Point> points;
+    if(int res=parseInput(conf,inputs,&points,"/vsimem/tmp")!=SERVICE_SUCCEEDED)
+      return res;
+    
+    Triangulation T;
+    T.insert(points.begin(), points.end());
+
+    OGRRegisterAll();
+    /* -------------------------------------------------------------------- */
+    /*      Try opening the output datasource as an existing, writable      */
+    /* -------------------------------------------------------------------- */
+    OGRDataSource       *poODS;
+    
+    OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
+    OGRSFDriver          *poDriver = NULL;
+    int                  iDriver;
+
+    map* tmpMap=getMapFromMaps(outputs,"Result","mimeType");
+    const char *oDriver;
+    oDriver="GeoJSON";
+    if(tmpMap!=NULL){
+      if(strcmp(tmpMap->value,"text/xml")==0){
+	oDriver="GML";
+      }
+    }
+    
+    for( iDriver = 0;
+	 iDriver < poR->GetDriverCount() && poDriver == NULL;
+	 iDriver++ )
+      {
+#ifdef DEBUG
+	fprintf(stderr,"D:%s\n",poR->GetDriver(iDriver)->GetName());
+#endif
+	if( EQUAL(poR->GetDriver(iDriver)->GetName(),oDriver) )
+	  {
+	    poDriver = poR->GetDriver(iDriver);
+	  }
+      }
+
+    if( poDriver == NULL )
+      {
+	char emessage[8192];
+	sprintf( emessage, "Unable to find driver `%s'.\n", oDriver );
+	sprintf( emessage,  "%sThe following drivers are available:\n",emessage );
+        
+	for( iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
+	  {
+	    sprintf( emessage,  "%s  -> `%s'\n", emessage, poR->GetDriver(iDriver)->GetName() );
+	  }
+
+	setMapInMaps(conf,"lenv","message",emessage);
+	return SERVICE_FAILED;
+
+      }
+
+    if( !poDriver->TestCapability( ODrCCreateDataSource ) ){
+      char emessage[1024];
+      sprintf( emessage,  "%s driver does not support data source creation.\n",
+	       "json" );
+      setMapInMaps(conf,"lenv","message",emessage);
+      return SERVICE_FAILED;
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Create the output data source.                                  */
+    /* -------------------------------------------------------------------- */
+    map* tpath=getMapFromMaps(conf,"main","tmpPath");
+    char *pszDestDataSource=(char*)malloc(100);
+    char **papszDSCO=NULL;
+    sprintf(pszDestDataSource,"/vsimem/result_%d.json",tpath->value,getpid());
+    poODS = poDriver->CreateDataSource( pszDestDataSource, papszDSCO );
+    if( poODS == NULL ){
+      char emessage[1024];      
+      sprintf( emessage,  "%s driver failed to create %s\n", 
+	       "json", pszDestDataSource );
+      setMapInMaps(conf,"lenv","message",emessage);
+      return SERVICE_FAILED;
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Create the layer.                                               */
+    /* -------------------------------------------------------------------- */
+    if( !poODS->TestCapability( ODsCCreateLayer ) )
+      {
+	char emessage[1024];
+	sprintf( emessage, 
+		 "Layer %s not found, and CreateLayer not supported by driver.", 
+		 "Result" );
+	setMapInMaps(conf,"lenv","message",emessage);
+	return SERVICE_FAILED;
+      }
+    
+    CPLErrorReset();
+    
+    OGRLayer *poDstLayer = poODS->CreateLayer( "Result", NULL,wkbLineString,NULL);
+    if( poDstLayer == NULL ){
+      setMapInMaps(conf,"lenv","message","Layer creation failed.\n");
+      return SERVICE_FAILED;
+    }
+
+
+    int ns = 0;
+    int nr = 0;
+    Edge_iterator eit =T.edges_begin();
+    for ( ; eit !=T.edges_end(); ++eit) {
+      CGAL::Object o = T.dual(eit);
+      if (const Kernel::Segment_2 *tmp=CGAL::object_cast<Kernel::Segment_2>(&o)) {
+	const Point p1=tmp->source();
+	const Point p2=tmp->target();
+#ifdef DEBUG
+	fprintf(stderr,"P1 %d %d | P2 %d %d\n",p1.x(),p1.y(),p2.x(),p2.y());
+#endif
+	OGRFeatureH hFeature = OGR_F_Create( OGR_L_GetLayerDefn( poDstLayer ) );
+	OGRGeometryH currLine=OGR_G_CreateGeometry(wkbLineString);
+	OGR_G_AddPoint_2D(currLine,p1.x(),p1.y());
+	OGR_G_AddPoint_2D(currLine,p2.x(),p2.y());
+	OGR_F_SetGeometry( hFeature, currLine ); 
+	OGR_G_DestroyGeometry(currLine);
+	if( OGR_L_CreateFeature( poDstLayer, hFeature ) != OGRERR_NONE ){
+	  setMapInMaps(conf,"lenv","message","Failed to create feature in file.\n");
+	  return SERVICE_FAILED;
+	}
+	OGR_F_Destroy( hFeature );
+	++ns ;
+      }
+      else if (const Kernel::Ray_2 *tmp=CGAL::object_cast<Kernel::Ray_2>(&o)) { 
+	const Point p1=tmp->source();
+	const Point p2=tmp->point(2);
+	OGRFeatureH hFeature = OGR_F_Create( OGR_L_GetLayerDefn( poDstLayer ) );
+	OGRGeometryH currLine=OGR_G_CreateGeometry(wkbLineString);
+	OGR_G_AddPoint_2D(currLine,p1.x(),p1.y());
+	OGR_G_AddPoint_2D(currLine,p2.x(),p2.y());
+	OGR_F_SetGeometry( hFeature, currLine );
+	OGR_G_DestroyGeometry(currLine);
+	if( OGR_L_CreateFeature( poDstLayer, hFeature ) != OGRERR_NONE ){
+	  setMapInMaps(conf,"lenv","message","Failed to create feature in file.\n");
+	  return SERVICE_FAILED;
+	}
+	OGR_F_Destroy( hFeature );
+	++nr; 
+      }
+    }
+    OGR_DS_Destroy( poODS );
+
+#ifdef DEBUG
+    std::cerr << "The Voronoi diagram has " << ns << " finite edges "
+	      << " and " << nr << " rays" << std::endl;
+    sprintf(tmp1,"%d finite edges, %d rays",ns,nr);
+#endif
+    
+
+    char *res1=readVSIFile(conf,pszDestDataSource);
+    if(res1==NULL)
+      return SERVICE_FAILED;
+    
+    setMapInMaps(outputs,"Result","value",res1);
+    
+    if(strcmp(oDriver,"GML")==0)
+      setMapInMaps(outputs,"Result","mimeType","text/xml");
+    else
+      setMapInMaps(outputs,"Result","mimeType","application/json");
+
+    setMapInMaps(outputs,"Result","encoding","UTF-8");
+#ifdef DEBUG
+    fprintf(stderr,"\nService internal print\n===\n");
+#endif
+    OGRCleanupAll();
+    return SERVICE_SUCCEEDED;
+  }
+
+}
diff --git a/zoo-project/zoo-services/gdal/contour/Makefile b/zoo-project/zoo-services/gdal/contour/Makefile
new file mode 100644
index 0000000..a5a558d
--- /dev/null
+++ b/zoo-project/zoo-services/gdal/contour/Makefile
@@ -0,0 +1,13 @@
+ZRPATH=../../..
+include ${ZRPATH}/zoo-kernel/ZOOMakefile.opts
+CFLAGS=-DZOO_SERVICE ${ZOO_CFLAGS} ${XML2CFLAGS} ${GDAL_CFLAGS} ${PYTHONCFLAGS} -DLINUX_FREE_ISSUE #-DDEBUG
+CC=gcc
+
+cgi-env/contour_service.zo: service.c
+	g++ ${CFLAGS} -shared -fpic -o cgi-env/contour_service.zo ./service.c ${GDAL_LIBS} ${MACOS_LD_FLAGS} -lzoo_service
+install:
+	install -d ${CGI_DIR}/gdal/contour
+	install cgi-env/* ${CGI_DIR}/gdal/contour
+
+clean:
+	rm -f cgi-env/*.zo
diff --git a/zoo-project/zoo-services/gdal/contour/cgi-env/Gdal_Contour.zcfg b/zoo-project/zoo-services/gdal/contour/cgi-env/Gdal_Contour.zcfg
new file mode 100644
index 0000000..a10dff9
--- /dev/null
+++ b/zoo-project/zoo-services/gdal/contour/cgi-env/Gdal_Contour.zcfg
@@ -0,0 +1,65 @@
+[Gdal_Contour]
+ Title = Builds vector contour lines from a raster elevation model.
+ Abstract = http://www.gdal.org/gdal_contour.html
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceType = C
+ serviceProvider = contour_service.zo
+ <DataInputs>
+  [InputDSN]
+   Title = The input data source name
+   Abstract = The input data source name to use.
+   minOccurs = 1
+   maxOccurs = 1
+   <LiteralData>
+    DataType = string
+    <Default />
+   </LiteralData>
+  [OutputDSN]
+   Title = The output data source name
+   Abstract = The output data source name.
+   minOccurs = 1
+   maxOccurs = 1
+   <LiteralData>
+    DataType = string
+    <Default />
+   </LiteralData>
+  [i]
+   Title = An interval value
+   Abstract = The elevation interval between contours.
+   minOccurs = 1
+   maxOccurs = 1
+   <LiteralData>
+    DataType = string
+    <Default />
+   </LiteralData>
+  [a]
+   Title = Attribute name
+   Abstract = provides a name for the attribute in which to put the elevation. If not provided no elevation attribute is attached.
+   minOccurs = 0
+   maxOccurs = 1
+   <LiteralData>
+    DataType = string
+    <Default />
+   </LiteralData>
+  [b]
+   Title = The band number
+   Abstract = A particular band, defaults to band 1.
+   minOccurs = 0
+   maxOccurs = 1
+   <LiteralData>
+    DataType = integer
+    <Default />
+   </LiteralData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = The resulting converted file
+   Abstract = The file name resulting of the convertion
+   <LiteralData>
+    DataType = string
+    <Default>
+    </Default>	
+   </LiteralData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/gdal/contour/makefile.vc b/zoo-project/zoo-services/gdal/contour/makefile.vc
new file mode 100644
index 0000000..cad41d0
--- /dev/null
+++ b/zoo-project/zoo-services/gdal/contour/makefile.vc
@@ -0,0 +1,25 @@
+TROOT= $(ZOOK_DIR)
+!INCLUDE $(ZOOK_DIR)nmake.opt
+
+FILES=$(ZOOK_DIR)/service_internal.obj $(ZOOK_DIR)/ulinet.obj 
+!IFDEF JS_DIR
+FILES=$(FILES) $(ZOOK_DIR)$(JS_FILE)
+!ENDIF
+!IFDEF JDK_DIR
+FILES=$(FILES) $(ZOOK_DIR)$(JAVA_FILE)
+!ENDIF
+!IFDEF PY_DIR
+FILES=$(FILES) $(ZOOK_DIR)$(PY_FILE)
+!ENDIF
+!IF DEFINED(MS_DIR)
+MS_BASE=$(MS_DIR)
+!INCLUDE $(MS_DIR)\nmake.opt
+FILES=$(FILES) $(ZOOK_DIR)$(MS_FILE)
+!ENDIF
+
+cgi-env/contour_service.zo: service.c
+	$(CPP)  /D_CRT_NONSTDC_NO_DEPRECATE -DWIN32 -DZOO_SERVICE -I$(GDAL_DIR)/frmts/vrt -I$(GDAL_DIR)/alg $(CFLAGS) /c service.c
+	link /dll /out:cgi-env/contour_service.zo  $(FILES) ./service.obj $(LDFLAGS) /FORCE:MULTIPLE
+
+clean:
+	erase cgi-env\*.zo
diff --git a/zoo-project/zoo-services/gdal/contour/service.c b/zoo-project/zoo-services/gdal/contour/service.c
new file mode 100644
index 0000000..72e1e95
--- /dev/null
+++ b/zoo-project/zoo-services/gdal/contour/service.c
@@ -0,0 +1,401 @@
+/******************************************************************************
+ * $Id: gdal_contour.cpp 25643 2013-02-12 13:50:42Z bishop $
+ *
+ * Project:  Contour Generator
+ * Purpose:  Contour Generator mainline.
+ * Author:   Frank Warmerdam <warmerdam at pobox.com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2003, Applied Coherent Technology (www.actgate.com). 
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "gdal.h"
+#include "gdal_alg.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "ogr_api.h"
+#include "ogr_srs_api.h"
+#ifdef ZOO_SERVICE
+#include "service.h"
+#endif
+CPL_CVSID("$Id: gdal_contour.cpp 25643 2013-02-12 13:50:42Z bishop $");
+
+#ifdef ZOO_SERVICE
+extern "C" {
+#endif
+
+/************************************************************************/
+/*                            ArgIsNumeric()                            */
+/************************************************************************/
+
+static int ArgIsNumeric( const char *pszArg )
+
+{
+    return CPLGetValueType(pszArg) != CPL_VALUE_STRING;
+}
+
+/************************************************************************/
+/*                               Usage()                                */
+/************************************************************************/
+
+static void Usage(const char* pszErrorMsg = NULL)
+
+{
+    printf( 
+        "Usage: gdal_contour [-b <band>] [-a <attribute_name>] [-3d] [-inodata]\n"
+        "                    [-snodata n] [-f <formatname>] [-i <interval>]\n"
+        "                    [-f <formatname>] [[-dsco NAME=VALUE] ...] [[-lco NAME=VALUE] ...]\n"   
+        "                    [-off <offset>] [-fl <level> <level>...]\n" 
+        "                    [-nln <outlayername>] [-q]\n"
+        "                    <src_filename> <dst_filename>\n" );
+
+    if( pszErrorMsg != NULL )
+        fprintf(stderr, "\nFAILURE: %s\n", pszErrorMsg);
+
+    exit( 1 );
+}
+
+/************************************************************************/
+/*                                main()                                */
+/************************************************************************/
+
+#define CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(nExtraArg) \
+    do { if (i + nExtraArg >= argc) \
+        Usage(CPLSPrintf("%s option requires %d argument(s)", argv[i], nExtraArg)); } while(0)
+
+#ifndef ZOO_SERVICE
+int main( int argc, char ** argv )
+#else
+#ifdef WIN32
+__declspec(dllexport)
+#endif
+  int Gdal_Contour(maps*& conf,maps*& inputs,maps*& outputs)
+#endif
+{
+    fprintf(stderr,"DEBUG HELLO %f %d\n",__FILE__,__LINE__);
+    fflush(stderr);
+    GDALDatasetH	hSrcDS;
+    int i, b3D = FALSE, bNoDataSet = FALSE, bIgnoreNoData = FALSE;
+    int nBandIn = 1;
+    double dfInterval = 0.0, dfNoData = 0.0, dfOffset = 0.0;
+    const char *pszSrcFilename = NULL;
+    const char *pszDstFilename = NULL;
+    const char *pszElevAttrib = NULL;
+    const char *pszFormat = "ESRI Shapefile";
+    char        **papszDSCO = NULL, **papszLCO = NULL;
+    double adfFixedLevels[1000];
+    int    nFixedLevelCount = 0;
+    const char *pszNewLayerName = "contour";
+    int bQuiet = FALSE;
+    GDALProgressFunc pfnProgress = NULL;
+    fprintf(stderr,"DEBUG HELLO %f %d\n",__FILE__,__LINE__);
+    fflush(stderr);
+#ifndef ZOO_SERVICE
+    /* Check that we are running against at least GDAL 1.4 */
+    /* Note to developers : if we use newer API, please change the requirement */
+    if (atoi(GDALVersionInfo("VERSION_NUM")) < 1400)
+    {
+        fprintf(stderr, "At least, GDAL >= 1.4.0 is required for this version of %s, "
+                "which was compiled against GDAL %s\n", argv[0], GDAL_RELEASE_NAME);
+        exit(1);
+    }
+#endif
+    GDALAllRegister();
+    OGRRegisterAll();
+
+#ifndef ZOO_SERVICE
+    argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
+
+/* -------------------------------------------------------------------- */
+/*      Parse arguments.                                                */
+/* -------------------------------------------------------------------- */
+    for( i = 1; i < argc; i++ )
+    {
+        if( EQUAL(argv[i], "--utility_version") )
+        {
+            printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
+                   argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
+            return 0;
+        }
+        else if( EQUAL(argv[i], "--help") )
+            Usage();
+        else if( EQUAL(argv[i],"-a") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszElevAttrib = argv[++i];
+        }
+        else if( EQUAL(argv[i],"-off") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            dfOffset = atof(argv[++i]);
+        }
+        else if( EQUAL(argv[i],"-i") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            dfInterval = atof(argv[++i]);
+        }
+        else if( EQUAL(argv[i],"-fl") )
+        {
+            if( i >= argc-1 )
+                Usage(CPLSPrintf("%s option requires at least 1 argument", argv[i]));
+            while( i < argc-1 
+                   && nFixedLevelCount 
+                             < (int)(sizeof(adfFixedLevels)/sizeof(double))
+                   && ArgIsNumeric(argv[i+1]) )
+                adfFixedLevels[nFixedLevelCount++] = atof(argv[++i]);
+        }
+        else if( EQUAL(argv[i],"-b") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            nBandIn = atoi(argv[++i]);
+        }
+        else if( EQUAL(argv[i],"-f") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszFormat = argv[++i];
+        }
+        else if( EQUAL(argv[i],"-dsco") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            papszDSCO = CSLAddString(papszDSCO, argv[++i] );
+        }
+        else if( EQUAL(argv[i],"-lco") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            papszLCO = CSLAddString(papszLCO, argv[++i] );
+        }
+        else if( EQUAL(argv[i],"-3d")  )
+        {
+            b3D = TRUE;
+        }
+        else if( EQUAL(argv[i],"-snodata") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            bNoDataSet = TRUE;
+            dfNoData = atof(argv[++i]);
+        }
+        else if( EQUAL(argv[i],"-nln") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszNewLayerName = argv[++i];
+        }
+        else if( EQUAL(argv[i],"-inodata") )
+        {
+            bIgnoreNoData = TRUE;
+        }
+        else if ( EQUAL(argv[i],"-q") || EQUAL(argv[i],"-quiet") )
+        {
+            bQuiet = TRUE;
+        }
+        else if( pszSrcFilename == NULL )
+        {
+            pszSrcFilename = argv[i];
+        }
+        else if( pszDstFilename == NULL )
+        {
+            pszDstFilename = argv[i];
+        }
+        else
+            Usage("Too many command options.");
+    }
+#else
+    bQuiet = TRUE;
+    bIgnoreNoData = TRUE;
+    map* tmpMap=NULL;
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"a","value");
+    if(tmpMap!=NULL && strncmp(tmpMap->value,"NULL",4)!=0){
+      pszElevAttrib = strdup(tmpMap->value);
+    }
+    tmpMap=getMapFromMaps(inputs,"off","value");
+    if(tmpMap!=NULL && strncmp(tmpMap->value,"NULL",4)!=0){
+      dfOffset = atof(tmpMap->value);
+    }
+    tmpMap=getMapFromMaps(inputs,"i","value");
+    if(tmpMap!=NULL && strncmp(tmpMap->value,"NULL",4)!=0){
+      dfInterval = atof(tmpMap->value);
+    }
+    tmpMap=getMapFromMaps(inputs,"b","value");
+    if(tmpMap!=NULL && strncmp(tmpMap->value,"NULL",4)!=0){
+      nBandIn = atoi(tmpMap->value);
+    }
+    tmpMap=getMapFromMaps(inputs,"InputDSN","value");
+    if(tmpMap!=NULL && strncmp(tmpMap->value,"NULL",4)!=0){
+      pszSrcFilename = strdup(tmpMap->value);
+    }
+    tmpMap=getMapFromMaps(inputs,"OutputDSN","value");
+    if(tmpMap!=NULL && strncmp(tmpMap->value,"NULL",4)!=0){
+      pszDstFilename = strdup(tmpMap->value);
+    }
+#endif
+    if( dfInterval == 0.0 && nFixedLevelCount == 0 )
+    {
+        Usage("Neither -i nor -fl are specified.");
+    }
+
+    if (pszSrcFilename == NULL)
+    {
+        Usage("Missing source filename.");
+    }
+
+    if (pszDstFilename == NULL)
+    {
+        Usage("Missing destination filename.");
+    }
+    
+    if (!bQuiet)
+        pfnProgress = GDALTermProgress;
+
+/* -------------------------------------------------------------------- */
+/*      Open source raster file.                                        */
+/* -------------------------------------------------------------------- */
+    GDALRasterBandH hBand;
+
+    hSrcDS = GDALOpen( pszSrcFilename, GA_ReadOnly );
+    if( hSrcDS == NULL ){
+#ifndef ZOO_SERVICE
+        exit( 2 );
+#else
+	setMapInMaps(conf,"lenv","message","Unable to open the file");
+#endif
+    }
+    hBand = GDALGetRasterBand( hSrcDS, nBandIn );
+    if( hBand == NULL )
+    {
+#ifndef ZOO_SERVICE
+        CPLError( CE_Failure, CPLE_AppDefined, 
+                  "Band %d does not exist on dataset.", 
+                  nBandIn );
+        exit(2);
+#else
+	char tmp[1024];
+	sprintf(tmp,"Band %d does not exist on dataset.",nBandIn);
+	setMapInMaps(conf,"lenv","message",tmp);
+	return SERVICE_FAILED;
+#endif
+    }
+
+    if( !bNoDataSet && !bIgnoreNoData )
+        dfNoData = GDALGetRasterNoDataValue( hBand, &bNoDataSet );
+
+/* -------------------------------------------------------------------- */
+/*      Try to get a coordinate system from the raster.                 */
+/* -------------------------------------------------------------------- */
+    OGRSpatialReferenceH hSRS = NULL;
+
+    const char *pszWKT = GDALGetProjectionRef( hSrcDS );
+
+    if( pszWKT != NULL && strlen(pszWKT) != 0 )
+        hSRS = OSRNewSpatialReference( pszWKT );
+
+/* -------------------------------------------------------------------- */
+/*      Create the outputfile.                                          */
+/* -------------------------------------------------------------------- */
+    OGRDataSourceH hDS;
+    OGRSFDriverH hDriver = OGRGetDriverByName( pszFormat );
+    OGRFieldDefnH hFld;
+    OGRLayerH hLayer;
+
+    if( hDriver == NULL )
+    {
+#ifndef ZOO_SERVICE
+        fprintf( stderr, "Unable to find format driver named %s.\n", 
+                 pszFormat );
+        exit( 10 );
+#else
+	char tmp[1024];
+        sprintf( tmp, "Unable to find format driver named %s.\n", pszFormat );	
+	setMapInMaps(conf,"lenv","message",tmp);
+	return SERVICE_FAILED;
+#endif
+    }
+
+    hDS = OGR_Dr_CreateDataSource( hDriver, pszDstFilename, papszDSCO );
+    if( hDS == NULL ){
+#ifndef ZOO_SERVICE
+        exit( 1 );
+#else
+	setMapInMaps(conf,"lenv","message","Unable to create the file");
+	return SERVICE_FAILED;
+#endif
+    }
+
+    hLayer = OGR_DS_CreateLayer( hDS, pszNewLayerName, hSRS, 
+                                 b3D ? wkbLineString25D : wkbLineString,
+                                 papszLCO );
+    if( hLayer == NULL )
+        exit( 1 );
+
+    hFld = OGR_Fld_Create( "ID", OFTInteger );
+    OGR_Fld_SetWidth( hFld, 8 );
+    OGR_L_CreateField( hLayer, hFld, FALSE );
+    OGR_Fld_Destroy( hFld );
+
+    if( pszElevAttrib )
+    {
+        hFld = OGR_Fld_Create( pszElevAttrib, OFTReal );
+        OGR_Fld_SetWidth( hFld, 12 );
+        OGR_Fld_SetPrecision( hFld, 3 );
+        OGR_L_CreateField( hLayer, hFld, FALSE );
+        OGR_Fld_Destroy( hFld );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Invoke.                                                         */
+/* -------------------------------------------------------------------- */
+    CPLErr eErr;
+    
+    eErr = GDALContourGenerate( hBand, dfInterval, dfOffset, 
+                         nFixedLevelCount, adfFixedLevels,
+                         bNoDataSet, dfNoData, hLayer, 
+                         OGR_FD_GetFieldIndex( OGR_L_GetLayerDefn( hLayer ), 
+                                               "ID" ), 
+                         (pszElevAttrib == NULL) ? -1 :
+                                 OGR_FD_GetFieldIndex( OGR_L_GetLayerDefn( hLayer ), 
+                                                       pszElevAttrib ), 
+                         pfnProgress, NULL );
+
+    OGR_DS_Destroy( hDS );
+    GDALClose( hSrcDS );
+
+    if (hSRS)
+        OSRDestroySpatialReference( hSRS );
+
+#ifndef ZOO_SERVICE
+    CSLDestroy( argv );
+    CSLDestroy( papszDSCO );
+    CSLDestroy( papszLCO );
+    GDALDestroyDriverManager();
+    OGRCleanupAll();
+    return 0;
+#else
+    GDALDestroyDriverManager();
+    OGRCleanupAll();
+    char tmp[1024];
+    sprintf(tmp,"File %s successfully created.",pszDstFilename);
+    setMapInMaps(outputs,"Result","value",tmp);
+    return SERVICE_SUCCEEDED;
+#endif
+}
+
+#ifdef ZOO_SERVICE
+}
+#endif
diff --git a/zoo-project/zoo-services/gdal/dem/Makefile b/zoo-project/zoo-services/gdal/dem/Makefile
new file mode 100644
index 0000000..219a157
--- /dev/null
+++ b/zoo-project/zoo-services/gdal/dem/Makefile
@@ -0,0 +1,15 @@
+ZRPATH=../../..
+include ${ZRPATH}/zoo-kernel/ZOOMakefile.opts
+CFLAGS=-DZOO_SERVICE ${ZOO_CFLAGS} ${XML2CFLAGS} ${GDAL_CFLAGS} ${PYTHONCFLAGS} -DLINUX_FREE_ISSUE #-DDEBUG
+CC=gcc
+
+cgi-env/dem_service.zo: service.c
+	g++ ${CFLAGS} -shared -fpic -o cgi-env/dem_service.zo ./service.c ${GDAL_LIBS} ${MACOS_LD_FLAGS} -lzoo_service
+
+install:
+	install -d ${CGI_DIR}/gdal/dem
+	install cgi-env/* ${CGI_DIR}/gdal/dem
+
+
+clean:
+	rm -f cgi-env/*.zo
diff --git a/zoo-project/zoo-services/gdal/dem/cgi-env/Gdal_Dem.zcfg b/zoo-project/zoo-services/gdal/dem/cgi-env/Gdal_Dem.zcfg
new file mode 100644
index 0000000..44d152a
--- /dev/null
+++ b/zoo-project/zoo-services/gdal/dem/cgi-env/Gdal_Dem.zcfg
@@ -0,0 +1,56 @@
+[Gdal_Dem]
+ Title = Tools to analyze and visualize DEMs.
+ Abstract = http://www.gdal.org/gdaldem.html
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceType = C
+ serviceProvider = dem_service.zo
+ <DataInputs>
+  [InputDSN]
+   Title = The input data source name
+   Abstract = The input data source name to use.
+   minOccurs = 1
+   maxOccurs = 1
+   <LiteralData>
+    DataType = string
+    <Default />
+   </LiteralData>
+  [OutputDSN]
+   Title = The output data source name
+   Abstract = The output data source name.
+   minOccurs = 1
+   maxOccurs = 1
+   <LiteralData>
+    DataType = string
+    <Default />
+   </LiteralData>
+  [utility]
+   Title = The mode
+   Abstract = This service has 7 different modes :  hillshade,  slope,  aspect, color-relief, TRI, TPI, roughness
+   minOccurs = 1
+   maxOccurs = 1
+   <LiteralData>
+    DataType = string
+    <Default />
+   </LiteralData>
+  [s]
+   Title = The scale
+   Abstract = Scale is the ratio of vertical units to horizontal, for Feet:Latlong use 370400, for Meters:LatLong use 111120
+   minOccurs = 0
+   maxOccurs = 1
+   <LiteralData>
+    DataType = string
+    <Default />
+   </LiteralData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = The resulting converted file
+   Abstract = The file name resulting of the convertion
+   <LiteralData>
+    DataType = string
+    <Default>
+    </Default>	
+   </LiteralData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/gdal/dem/makefile.vc b/zoo-project/zoo-services/gdal/dem/makefile.vc
new file mode 100644
index 0000000..e92552b
--- /dev/null
+++ b/zoo-project/zoo-services/gdal/dem/makefile.vc
@@ -0,0 +1,23 @@
+TROOT= $(ZOOK_DIR)
+!INCLUDE $(ZOOK_DIR)nmake.opt
+
+FILES=$(ZOOK_DIR)/service_internal.obj $(ZOOK_DIR)/ulinet.obj 
+!IFDEF JS_DIR
+FILES=$(FILES) $(ZOOK_DIR)$(JS_FILE)
+!ENDIF
+!IFDEF JDK_DIR
+FILES=$(FILES) $(ZOOK_DIR)$(JAVA_FILE)
+!ENDIF
+!IFDEF PY_DIR
+FILES=$(FILES) $(ZOOK_DIR)$(PY_FILE)
+!ENDIF
+!IFDEF MS_DIR
+FILES=$(FILES) $(ZOOK_DIR)$(MS_FILE)
+!ENDIF
+
+cgi-env/dem_service.zo: service.c
+	$(CPP)  /D_CRT_NONSTDC_NO_DEPRECATE -DWIN32 -DZOO_SERVICE -I$(GDAL_DIR)/frmts/vrt $(CFLAGS) /c service.c
+	link /dll /out:cgi-env/dem_service.zo  $(FILES) ./service.obj $(LDFLAGS) /FORCE:MULTIPLE
+
+clean:
+	erase cgi-env\*.zo
diff --git a/zoo-project/zoo-services/gdal/dem/service.c b/zoo-project/zoo-services/gdal/dem/service.c
new file mode 100644
index 0000000..a74dc7b
--- /dev/null
+++ b/zoo-project/zoo-services/gdal/dem/service.c
@@ -0,0 +1,2899 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GDAL DEM Utilities
+ * Purpose:  
+ * Authors:  Matthew Perry, perrygeo at gmail.com
+ *           Even Rouault, even dot rouault at mines dash paris dot org
+ *           Howard Butler, hobu.inc at gmail.com
+ *           Chris Yesson, chris dot yesson at ioz dot ac dot uk
+ *
+ ******************************************************************************
+ * Copyright (c) 2006, 2009 Matthew Perry 
+ * Copyright (c) 2009 Even Rouault
+ * Portions derived from GRASS 4.1 (public domain) See 
+ * http://trac.osgeo.org/gdal/ticket/2975 for more information regarding 
+ * history of this code
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************
+ *
+ * Slope and aspect calculations based on original method for GRASS GIS 4.1
+ * by Michael Shapiro, U.S.Army Construction Engineering Research Laboratory
+ *    Olga Waupotitsch, U.S.Army Construction Engineering Research Laboratory
+ *    Marjorie Larson, U.S.Army Construction Engineering Research Laboratory
+ * as found in GRASS's r.slope.aspect module.
+ *
+ * Horn's formula is used to find the first order derivatives in x and y directions
+ * for slope and aspect calculations: Horn, B. K. P. (1981).
+ * "Hill Shading and the Reflectance Map", Proceedings of the IEEE, 69(1):14-47. 
+ *
+ * Other reference :
+ * Burrough, P.A. and McDonell, R.A., 1998. Principles of Geographical Information
+ * Systems. p. 190.
+ *
+ * Shaded relief based on original method for GRASS GIS 4.1 by Jim Westervelt,
+ * U.S. Army Construction Engineering Research Laboratory
+ * as found in GRASS's r.shaded.relief (formerly shade.rel.sh) module.
+ * ref: "r.mapcalc: An Algebra for GIS and Image Processing",
+ * by Michael Shapiro and Jim Westervelt, U.S. Army Construction Engineering
+ * Research Laboratory (March/1991)
+ *
+ * Color table of named colors and lookup code derived from src/libes/gis/named_colr.c
+ * of GRASS 4.1
+ *
+ * TRI - Terrain Ruggedness Index is as descibed in Wilson et al (2007)
+ * this is based on the method of Valentine et al. (2004)  
+ * 
+ * TPI - Topographic Position Index follows the description in Wilson et al (2007), following Weiss (2001)
+ * The radius is fixed at 1 cell width/height
+ * 
+ * Roughness - follows the definition in Wilson et al. (2007), which follows Dartnell (2000)
+ *
+ * References for TRI/TPI/Roughness:
+ * Dartnell, P. 2000. Applying Remote Sensing Techniques to map Seafloor 
+ *  Geology/Habitat Relationships. Masters Thesis, San Francisco State 
+ *  University, pp. 108.
+ * Valentine, P. C., S. J. Fuller, L. A. Scully. 2004. Terrain Ruggedness 
+ *  Analysis and Distribution of Boulder Ridges in the Stellwagen Bank National
+ *  Marine Sanctuary Region (poster). Galway, Ireland: 5th International 
+ *  Symposium on Marine Geological and Biological Habitat Mapping (GeoHAB), 
+ *  May 2004.
+ * Weiss, A. D. 2001. Topographic Positions and Landforms Analysis (poster), 
+ *  ESRI International User Conference, July 2001. San Diego, CA: ESRI.
+ * Wilson, M. F. J.; O'Connell, B.; Brown, C.; Guinan, J. C. & Grehan, A. J. 
+ *  Multiscale terrain analysis of multibeam bathymetry data for habitat mapping
+ *  on the continental slope Marine Geodesy, 2007, 30, 3-35
+ ****************************************************************************/
+
+#include <stdlib.h>
+#include <math.h>
+
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "gdal.h"
+#include "gdal_priv.h"
+#ifndef ZOO_SERVICE
+#include "commonutils.h"
+#else
+#include "service.h"
+#endif
+
+CPL_CVSID("$Id$");
+
+#ifdef WIN32
+#define strcasecmp _stricmp
+#define strncasecmp _strnicmp 
+#endif
+
+#ifdef ZOO_SERVICE
+extern "C" {
+#endif
+
+#ifndef M_PI
+# define M_PI  3.1415926535897932384626433832795
+#endif
+
+#define INTERPOL(a,b) ((bSrcHasNoData && (ARE_REAL_EQUAL(a, fSrcNoDataValue) || ARE_REAL_EQUAL(b, fSrcNoDataValue))) ? fSrcNoDataValue : 2 * (a) - (b))
+
+#ifdef ZOO_SERVICE
+static int Usage(maps*& conf, const char* pszErrorMsg = NULL){
+      setMapInMaps(conf,"lenv","message","Missing source.");
+      return SERVICE_FAILED;
+}
+#else
+/************************************************************************/
+/*                               Usage()                                */
+/************************************************************************/
+
+static void Usage(const char* pszErrorMsg = NULL)
+
+{
+    printf( " Usage: \n"
+            " - To generate a shaded relief map from any GDAL-supported elevation raster : \n\n"
+            "     gdaldem hillshade input_dem output_hillshade \n"
+            "                 [-z ZFactor (default=1)] [-s scale* (default=1)] \n"
+            "                 [-az Azimuth (default=315)] [-alt Altitude (default=45)]\n"
+            "                 [-alg ZevenbergenThorne] [-combined]\n"
+            "                 [-compute_edges] [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
+            "\n"
+            " - To generates a slope map from any GDAL-supported elevation raster :\n\n"
+            "     gdaldem slope input_dem output_slope_map \n"
+            "                 [-p use percent slope (default=degrees)] [-s scale* (default=1)]\n"
+            "                 [-alg ZevenbergenThorne]\n"
+            "                 [-compute_edges] [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
+            "\n"
+            " - To generate an aspect map from any GDAL-supported elevation raster\n"
+            "   Outputs a 32-bit float tiff with pixel values from 0-360 indicating azimuth :\n\n"
+            "     gdaldem aspect input_dem output_aspect_map \n"
+            "                 [-trigonometric] [-zero_for_flat]\n"
+            "                 [-alg ZevenbergenThorne]\n"
+            "                 [-compute_edges] [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
+            "\n"
+            " - To generate a color relief map from any GDAL-supported elevation raster\n"
+            "     gdaldem color-relief input_dem color_text_file output_color_relief_map\n"
+            "                 [-alpha] [-exact_color_entry | -nearest_color_entry]\n"
+            "                 [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
+            "     where color_text_file contains lines of the format \"elevation_value red green blue\"\n"
+            "\n"
+            " - To generate a Terrain Ruggedness Index (TRI) map from any GDAL-supported elevation raster\n"
+            "     gdaldem TRI input_dem output_TRI_map\n"
+            "                 [-compute_edges] [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
+            "\n"
+            " - To generate a Topographic Position Index (TPI) map from any GDAL-supported elevation raster\n"
+            "     gdaldem TPI input_dem output_TPI_map\n"
+            "                 [-compute_edges] [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
+            "\n"
+            " - To generate a roughness map from any GDAL-supported elevation raster\n"
+            "     gdaldem roughness input_dem output_roughness_map\n"
+            "                 [-compute_edges] [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
+            "\n"
+            " Notes : \n"
+            "   Scale is the ratio of vertical units to horizontal\n"
+            "    for Feet:Latlong use scale=370400, for Meters:LatLong use scale=111120 \n\n");
+
+    if( pszErrorMsg != NULL )
+        fprintf(stderr, "\nFAILURE: %s\n", pszErrorMsg);
+
+    exit( 1 );
+}
+#endif
+/************************************************************************/
+/*                          ComputeVal()                                */
+/************************************************************************/
+
+typedef float (*GDALGeneric3x3ProcessingAlg) (float* pafWindow, float fDstNoDataValue, void* pData);
+
+static float ComputeVal(int bSrcHasNoData, float fSrcNoDataValue,
+                        float* afWin, float fDstNoDataValue,
+                        GDALGeneric3x3ProcessingAlg pfnAlg,
+                        void* pData,
+                        int bComputeAtEdges)
+{
+    if (bSrcHasNoData && ARE_REAL_EQUAL(afWin[4], fSrcNoDataValue))
+    {
+        return fDstNoDataValue;
+    }
+    else if (bSrcHasNoData)
+    {
+        int k;
+        for(k=0;k<9;k++)
+        {
+            if (ARE_REAL_EQUAL(afWin[k], fSrcNoDataValue))
+            {
+                if (bComputeAtEdges)
+                    afWin[k] = afWin[4];
+                else
+                    return fDstNoDataValue;
+            }
+        }
+    }
+
+    return pfnAlg(afWin, fDstNoDataValue, pData);
+}
+
+/************************************************************************/
+/*                  GDALGeneric3x3Processing()                          */
+/************************************************************************/
+
+CPLErr GDALGeneric3x3Processing  ( GDALRasterBandH hSrcBand,
+                                   GDALRasterBandH hDstBand,
+                                   GDALGeneric3x3ProcessingAlg pfnAlg,
+                                   void* pData,
+                                   int bComputeAtEdges,
+                                   GDALProgressFunc pfnProgress,
+                                   void * pProgressData)
+{
+    CPLErr eErr;
+    float *pafThreeLineWin; /* 3 line rotating source buffer */
+    float *pafOutputBuf;     /* 1 line destination buffer */
+    int i, j;
+
+    int bSrcHasNoData, bDstHasNoData;
+    float fSrcNoDataValue = 0.0, fDstNoDataValue = 0.0;
+
+    int nXSize = GDALGetRasterBandXSize(hSrcBand);
+    int nYSize = GDALGetRasterBandYSize(hSrcBand);
+
+    if (pfnProgress == NULL)
+        pfnProgress = GDALDummyProgress;
+
+/* -------------------------------------------------------------------- */
+/*      Initialize progress counter.                                    */
+/* -------------------------------------------------------------------- */
+    if( !pfnProgress( 0.0, NULL, pProgressData ) )
+    {
+        CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
+        return CE_Failure;
+    }
+
+    pafOutputBuf = (float *) CPLMalloc(sizeof(float)*nXSize);
+    pafThreeLineWin  = (float *) CPLMalloc(3*sizeof(float)*(nXSize+1));
+
+    fSrcNoDataValue = (float) GDALGetRasterNoDataValue(hSrcBand, &bSrcHasNoData);
+    fDstNoDataValue = (float) GDALGetRasterNoDataValue(hDstBand, &bDstHasNoData);
+    if (!bDstHasNoData)
+        fDstNoDataValue = 0.0;
+
+    // Move a 3x3 pafWindow over each cell 
+    // (where the cell in question is #4)
+    // 
+    //      0 1 2
+    //      3 4 5
+    //      6 7 8
+
+    /* Preload the first 2 lines */
+    for ( i = 0; i < 2 && i < nYSize; i++)
+    {
+        GDALRasterIO(   hSrcBand,
+                        GF_Read,
+                        0, i,
+                        nXSize, 1,
+                        pafThreeLineWin + i * nXSize,
+                        nXSize, 1,
+                        GDT_Float32,
+                        0, 0);
+    }
+    
+    if (bComputeAtEdges && nXSize >= 2 && nYSize >= 2)
+    {
+        for (j = 0; j < nXSize; j++)
+        {
+            float afWin[9];
+            int jmin = (j == 0) ? j : j - 1;
+            int jmax = (j == nXSize - 1) ? j : j + 1;
+
+            afWin[0] = INTERPOL(pafThreeLineWin[jmin], pafThreeLineWin[nXSize + jmin]);
+            afWin[1] = INTERPOL(pafThreeLineWin[j],    pafThreeLineWin[nXSize + j]);
+            afWin[2] = INTERPOL(pafThreeLineWin[jmax], pafThreeLineWin[nXSize + jmax]);
+            afWin[3] = pafThreeLineWin[jmin];
+            afWin[4] = pafThreeLineWin[j];
+            afWin[5] = pafThreeLineWin[jmax];
+            afWin[6] = pafThreeLineWin[nXSize + jmin];
+            afWin[7] = pafThreeLineWin[nXSize + j];
+            afWin[8] = pafThreeLineWin[nXSize + jmax];
+
+            pafOutputBuf[j] = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
+                                         afWin, fDstNoDataValue,
+                                         pfnAlg, pData, bComputeAtEdges);
+        }
+        GDALRasterIO(hDstBand, GF_Write,
+                    0, 0, nXSize, 1,
+                    pafOutputBuf, nXSize, 1, GDT_Float32, 0, 0);
+    }
+    else
+    {
+        // Exclude the edges
+        for (j = 0; j < nXSize; j++)
+        {
+            pafOutputBuf[j] = fDstNoDataValue;
+        }
+        GDALRasterIO(hDstBand, GF_Write,
+                    0, 0, nXSize, 1,
+                    pafOutputBuf, nXSize, 1, GDT_Float32, 0, 0);
+    
+        if (nYSize > 1)
+        {
+            GDALRasterIO(hDstBand, GF_Write,
+                        0, nYSize - 1, nXSize, 1,
+                        pafOutputBuf, nXSize, 1, GDT_Float32, 0, 0);
+        }
+    }
+    
+    int nLine1Off = 0*nXSize;
+    int nLine2Off = 1*nXSize;
+    int nLine3Off = 2*nXSize;
+
+    for ( i = 1; i < nYSize-1; i++)
+    {
+        /* Read third line of the line buffer */
+        eErr = GDALRasterIO(   hSrcBand,
+                        GF_Read,
+                        0, i+1,
+                        nXSize, 1,
+                        pafThreeLineWin + nLine3Off,
+                        nXSize, 1,
+                        GDT_Float32,
+                        0, 0);
+        if (eErr != CE_None)
+            goto end;
+
+        if (bComputeAtEdges && nXSize >= 2)
+        {
+            float afWin[9];
+
+            j = 0;
+            afWin[0] = INTERPOL(pafThreeLineWin[nLine1Off + j], pafThreeLineWin[nLine1Off + j+1]);
+            afWin[1] = pafThreeLineWin[nLine1Off + j];
+            afWin[2] = pafThreeLineWin[nLine1Off + j+1];
+            afWin[3] = INTERPOL(pafThreeLineWin[nLine2Off + j], pafThreeLineWin[nLine2Off + j+1]);
+            afWin[4] = pafThreeLineWin[nLine2Off + j];
+            afWin[5] = pafThreeLineWin[nLine2Off + j+1];
+            afWin[6] = INTERPOL(pafThreeLineWin[nLine3Off + j], pafThreeLineWin[nLine3Off + j+1]);
+            afWin[7] = pafThreeLineWin[nLine3Off + j];
+            afWin[8] = pafThreeLineWin[nLine3Off + j+1];
+
+            pafOutputBuf[j] = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
+                                         afWin, fDstNoDataValue,
+                                         pfnAlg, pData, bComputeAtEdges);
+            j = nXSize - 1;
+
+            afWin[0] = pafThreeLineWin[nLine1Off + j-1];
+            afWin[1] = pafThreeLineWin[nLine1Off + j];
+            afWin[2] = INTERPOL(pafThreeLineWin[nLine1Off + j], pafThreeLineWin[nLine1Off + j-1]);
+            afWin[3] = pafThreeLineWin[nLine2Off + j-1];
+            afWin[4] = pafThreeLineWin[nLine2Off + j];
+            afWin[5] = INTERPOL(pafThreeLineWin[nLine2Off + j], pafThreeLineWin[nLine2Off + j-1]);
+            afWin[6] = pafThreeLineWin[nLine3Off + j-1];
+            afWin[7] = pafThreeLineWin[nLine3Off + j];
+            afWin[8] = INTERPOL(pafThreeLineWin[nLine3Off + j], pafThreeLineWin[nLine3Off + j-1]);
+
+            pafOutputBuf[j] = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
+                                         afWin, fDstNoDataValue,
+                                         pfnAlg, pData, bComputeAtEdges);
+        }
+        else
+        {
+            // Exclude the edges
+            pafOutputBuf[0] = fDstNoDataValue;
+            if (nXSize > 1)
+                pafOutputBuf[nXSize - 1] = fDstNoDataValue;
+        }
+
+        for (j = 1; j < nXSize - 1; j++)
+        {
+            float afWin[9];
+            afWin[0] = pafThreeLineWin[nLine1Off + j-1];
+            afWin[1] = pafThreeLineWin[nLine1Off + j];
+            afWin[2] = pafThreeLineWin[nLine1Off + j+1];
+            afWin[3] = pafThreeLineWin[nLine2Off + j-1];
+            afWin[4] = pafThreeLineWin[nLine2Off + j];
+            afWin[5] = pafThreeLineWin[nLine2Off + j+1];
+            afWin[6] = pafThreeLineWin[nLine3Off + j-1];
+            afWin[7] = pafThreeLineWin[nLine3Off + j];
+            afWin[8] = pafThreeLineWin[nLine3Off + j+1];
+
+            pafOutputBuf[j] = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
+                                         afWin, fDstNoDataValue,
+                                         pfnAlg, pData, bComputeAtEdges);
+        }
+
+        /* -----------------------------------------
+         * Write Line to Raster
+         */
+        eErr = GDALRasterIO(hDstBand, GF_Write, 0, i, nXSize, 1,
+                     pafOutputBuf, nXSize, 1, GDT_Float32, 0, 0);
+        if (eErr != CE_None)
+            goto end;
+
+        if( !pfnProgress( 1.0 * (i+1) / nYSize, NULL, pProgressData ) )
+        {
+            CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
+            eErr = CE_Failure;
+            goto end;
+        }
+        
+        int nTemp = nLine1Off;
+        nLine1Off = nLine2Off;
+        nLine2Off = nLine3Off;
+        nLine3Off = nTemp;
+    }
+
+    if (bComputeAtEdges && nXSize >= 2 && nYSize >= 2)
+    {
+        for (j = 0; j < nXSize; j++)
+        {
+            float afWin[9];
+            int jmin = (j == 0) ? j : j - 1;
+            int jmax = (j == nXSize - 1) ? j : j + 1;
+
+            afWin[0] = pafThreeLineWin[nLine1Off + jmin];
+            afWin[1] = pafThreeLineWin[nLine1Off + j];
+            afWin[2] = pafThreeLineWin[nLine1Off + jmax];
+            afWin[3] = pafThreeLineWin[nLine2Off + jmin];
+            afWin[4] = pafThreeLineWin[nLine2Off + j];
+            afWin[5] = pafThreeLineWin[nLine2Off + jmax];
+            afWin[6] = INTERPOL(pafThreeLineWin[nLine2Off + jmin], pafThreeLineWin[nLine1Off + jmin]);
+            afWin[7] = INTERPOL(pafThreeLineWin[nLine2Off + j],    pafThreeLineWin[nLine1Off + j]);
+            afWin[8] = INTERPOL(pafThreeLineWin[nLine2Off + jmax], pafThreeLineWin[nLine1Off + jmax]);
+
+            pafOutputBuf[j] = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
+                                         afWin, fDstNoDataValue,
+                                         pfnAlg, pData, bComputeAtEdges);
+        }
+        GDALRasterIO(hDstBand, GF_Write,
+                     0, i, nXSize, 1,
+                     pafOutputBuf, nXSize, 1, GDT_Float32, 0, 0);
+    }
+
+    pfnProgress( 1.0, NULL, pProgressData );
+    eErr = CE_None;
+
+end:
+    CPLFree(pafOutputBuf);
+    CPLFree(pafThreeLineWin);
+
+    return eErr;
+}
+
+
+/************************************************************************/
+/*                         GDALHillshade()                              */
+/************************************************************************/
+
+typedef struct
+{
+    double nsres;
+    double ewres;
+    double sin_altRadians;
+    double cos_altRadians_mul_z_scale_factor;
+    double azRadians;
+    double square_z_scale_factor;
+    double square_M_PI_2;
+} GDALHillshadeAlgData;
+
+/* Unoptimized formulas are :
+    x = psData->z*((afWin[0] + afWin[3] + afWin[3] + afWin[6]) -
+        (afWin[2] + afWin[5] + afWin[5] + afWin[8])) /
+        (8.0 * psData->ewres * psData->scale);
+
+    y = psData->z*((afWin[6] + afWin[7] + afWin[7] + afWin[8]) -
+        (afWin[0] + afWin[1] + afWin[1] + afWin[2])) /
+        (8.0 * psData->nsres * psData->scale);
+
+    slope = M_PI / 2 - atan(sqrt(x*x + y*y));
+
+    aspect = atan2(y,x);
+
+    cang = sin(alt * degreesToRadians) * sin(slope) +
+           cos(alt * degreesToRadians) * cos(slope) *
+           cos(az * degreesToRadians - M_PI/2 - aspect);
+*/
+
+float GDALHillshadeAlg (float* afWin, float fDstNoDataValue, void* pData)
+{
+    GDALHillshadeAlgData* psData = (GDALHillshadeAlgData*)pData;
+    double x, y, aspect, xx_plus_yy, cang;
+    
+    // First Slope ...
+    x = ((afWin[0] + afWin[3] + afWin[3] + afWin[6]) -
+        (afWin[2] + afWin[5] + afWin[5] + afWin[8])) / psData->ewres;
+
+    y = ((afWin[6] + afWin[7] + afWin[7] + afWin[8]) -
+        (afWin[0] + afWin[1] + afWin[1] + afWin[2])) / psData->nsres;
+
+    xx_plus_yy = x * x + y * y;
+
+    // ... then aspect...
+    aspect = atan2(y,x);
+
+    // ... then the shade value
+    cang = (psData->sin_altRadians -
+           psData->cos_altRadians_mul_z_scale_factor * sqrt(xx_plus_yy) *
+           sin(aspect - psData->azRadians)) /
+           sqrt(1 + psData->square_z_scale_factor * xx_plus_yy);
+
+    if (cang <= 0.0) 
+        cang = 1.0;
+    else
+        cang = 1.0 + (254.0 * cang);
+        
+    return (float) cang;
+}
+
+float GDALHillshadeCombinedAlg (float* afWin, float fDstNoDataValue, void* pData)
+{
+    GDALHillshadeAlgData* psData = (GDALHillshadeAlgData*)pData;
+    double x, y, aspect, xx_plus_yy, cang;
+    
+    // First Slope ...
+    x = ((afWin[0] + afWin[3] + afWin[3] + afWin[6]) -
+        (afWin[2] + afWin[5] + afWin[5] + afWin[8])) / psData->ewres;
+
+    y = ((afWin[6] + afWin[7] + afWin[7] + afWin[8]) -
+        (afWin[0] + afWin[1] + afWin[1] + afWin[2])) / psData->nsres;
+
+    xx_plus_yy = x * x + y * y;
+
+    // ... then aspect...
+    aspect = atan2(y,x);
+    double slope = xx_plus_yy * psData->square_z_scale_factor;
+
+    // ... then the shade value
+    cang = acos((psData->sin_altRadians -
+           psData->cos_altRadians_mul_z_scale_factor * sqrt(xx_plus_yy) *
+           sin(aspect - psData->azRadians)) /
+           sqrt(1 + slope));
+
+    // combined shading
+    cang = 1 - cang * atan(sqrt(slope)) / psData->square_M_PI_2;
+
+    if (cang <= 0.0) 
+        cang = 1.0;
+    else
+        cang = 1.0 + (254.0 * cang);
+        
+    return (float) cang;
+}
+
+float GDALHillshadeZevenbergenThorneAlg (float* afWin, float fDstNoDataValue, void* pData)
+{
+    GDALHillshadeAlgData* psData = (GDALHillshadeAlgData*)pData;
+    double x, y, aspect, xx_plus_yy, cang;
+    
+    // First Slope ...
+    x = (afWin[3] - afWin[5]) / psData->ewres;
+
+    y = (afWin[7] - afWin[1]) / psData->nsres;
+
+    xx_plus_yy = x * x + y * y;
+
+    // ... then aspect...
+    aspect = atan2(y,x);
+
+    // ... then the shade value
+    cang = (psData->sin_altRadians -
+           psData->cos_altRadians_mul_z_scale_factor * sqrt(xx_plus_yy) *
+           sin(aspect - psData->azRadians)) /
+           sqrt(1 + psData->square_z_scale_factor * xx_plus_yy);
+
+    if (cang <= 0.0) 
+        cang = 1.0;
+    else
+        cang = 1.0 + (254.0 * cang);
+        
+    return (float) cang;
+}
+
+float GDALHillshadeZevenbergenThorneCombinedAlg (float* afWin, float fDstNoDataValue, void* pData)
+{
+    GDALHillshadeAlgData* psData = (GDALHillshadeAlgData*)pData;
+    double x, y, aspect, xx_plus_yy, cang;
+    
+    // First Slope ...
+    x = (afWin[3] - afWin[5]) / psData->ewres;
+
+    y = (afWin[7] - afWin[1]) / psData->nsres;
+
+    xx_plus_yy = x * x + y * y;
+
+    // ... then aspect...
+    aspect = atan2(y,x);
+    double slope = xx_plus_yy * psData->square_z_scale_factor;
+
+    // ... then the shade value
+    cang = acos((psData->sin_altRadians -
+           psData->cos_altRadians_mul_z_scale_factor * sqrt(xx_plus_yy) *
+           sin(aspect - psData->azRadians)) /
+           sqrt(1 + slope));
+
+    // combined shading
+    cang = 1 - cang * atan(sqrt(slope)) / psData->square_M_PI_2;
+
+    if (cang <= 0.0) 
+        cang = 1.0;
+    else
+        cang = 1.0 + (254.0 * cang);
+        
+    return (float) cang;
+}
+
+void*  GDALCreateHillshadeData(double* adfGeoTransform,
+                               double z,
+                               double scale,
+                               double alt,
+                               double az,
+                               int bZevenbergenThorne)
+{
+    GDALHillshadeAlgData* pData =
+        (GDALHillshadeAlgData*)CPLMalloc(sizeof(GDALHillshadeAlgData));
+        
+    const double degreesToRadians = M_PI / 180.0;
+    pData->nsres = adfGeoTransform[5];
+    pData->ewres = adfGeoTransform[1];
+    pData->sin_altRadians = sin(alt * degreesToRadians);
+    pData->azRadians = az * degreesToRadians;
+    double z_scale_factor = z / (((bZevenbergenThorne) ? 2 : 8) * scale);
+    pData->cos_altRadians_mul_z_scale_factor =
+        cos(alt * degreesToRadians) * z_scale_factor;
+    pData->square_z_scale_factor = z_scale_factor * z_scale_factor;
+    pData->square_M_PI_2 = (M_PI*M_PI)/4;
+    return pData;
+}
+
+/************************************************************************/
+/*                         GDALSlope()                                  */
+/************************************************************************/
+
+typedef struct
+{
+    double nsres;
+    double ewres;
+    double scale;
+    int    slopeFormat;
+} GDALSlopeAlgData;
+
+float GDALSlopeHornAlg (float* afWin, float fDstNoDataValue, void* pData)
+{
+    const double radiansToDegrees = 180.0 / M_PI;
+    GDALSlopeAlgData* psData = (GDALSlopeAlgData*)pData;
+    double dx, dy, key;
+    
+    dx = ((afWin[0] + afWin[3] + afWin[3] + afWin[6]) - 
+          (afWin[2] + afWin[5] + afWin[5] + afWin[8]))/psData->ewres;
+
+    dy = ((afWin[6] + afWin[7] + afWin[7] + afWin[8]) - 
+          (afWin[0] + afWin[1] + afWin[1] + afWin[2]))/psData->nsres;
+
+    key = (dx * dx + dy * dy);
+
+    if (psData->slopeFormat == 1) 
+        return (float) (atan(sqrt(key) / (8*psData->scale)) * radiansToDegrees);
+    else
+        return (float) (100*(sqrt(key) / (8*psData->scale)));
+}
+
+float GDALSlopeZevenbergenThorneAlg (float* afWin, float fDstNoDataValue, void* pData)
+{
+    const double radiansToDegrees = 180.0 / M_PI;
+    GDALSlopeAlgData* psData = (GDALSlopeAlgData*)pData;
+    double dx, dy, key;
+    
+    dx = (afWin[3] - afWin[5])/psData->ewres;
+
+    dy = (afWin[7] - afWin[1])/psData->nsres;
+
+    key = (dx * dx + dy * dy);
+
+    if (psData->slopeFormat == 1) 
+        return (float) (atan(sqrt(key) / (2*psData->scale)) * radiansToDegrees);
+    else
+        return (float) (100*(sqrt(key) / (2*psData->scale)));
+}
+
+void*  GDALCreateSlopeData(double* adfGeoTransform,
+                           double scale,
+                           int slopeFormat)
+{
+    GDALSlopeAlgData* pData =
+        (GDALSlopeAlgData*)CPLMalloc(sizeof(GDALSlopeAlgData));
+        
+    pData->nsres = adfGeoTransform[5];
+    pData->ewres = adfGeoTransform[1];
+    pData->scale = scale;
+    pData->slopeFormat = slopeFormat;
+    return pData;
+}
+
+/************************************************************************/
+/*                         GDALAspect()                                 */
+/************************************************************************/
+
+typedef struct
+{
+    int bAngleAsAzimuth;
+} GDALAspectAlgData;
+
+float GDALAspectAlg (float* afWin, float fDstNoDataValue, void* pData)
+{
+    const double degreesToRadians = M_PI / 180.0;
+    GDALAspectAlgData* psData = (GDALAspectAlgData*)pData;
+    double dx, dy;
+    float aspect;
+    
+    dx = ((afWin[2] + afWin[5] + afWin[5] + afWin[8]) -
+          (afWin[0] + afWin[3] + afWin[3] + afWin[6]));
+
+    dy = ((afWin[6] + afWin[7] + afWin[7] + afWin[8]) - 
+          (afWin[0] + afWin[1] + afWin[1] + afWin[2]));
+
+    aspect = (float) (atan2(dy,-dx) / degreesToRadians);
+
+    if (dx == 0 && dy == 0)
+    {
+        /* Flat area */
+        aspect = fDstNoDataValue;
+    } 
+    else if ( psData->bAngleAsAzimuth )
+    {
+        if (aspect > 90.0) 
+            aspect = 450.0f - aspect;
+        else
+            aspect = 90.0f - aspect;
+    }
+    else
+    {
+        if (aspect < 0)
+            aspect += 360.0;
+    }
+
+    if (aspect == 360.0) 
+        aspect = 0.0;
+
+    return aspect;
+}
+
+float GDALAspectZevenbergenThorneAlg (float* afWin, float fDstNoDataValue, void* pData)
+{
+    const double degreesToRadians = M_PI / 180.0;
+    GDALAspectAlgData* psData = (GDALAspectAlgData*)pData;
+    double dx, dy;
+    float aspect;
+    
+    dx = (afWin[5] - afWin[3]);
+
+    dy = (afWin[7] - afWin[1]);
+
+    aspect = (float) (atan2(dy,-dx) / degreesToRadians);
+
+    if (dx == 0 && dy == 0)
+    {
+        /* Flat area */
+        aspect = fDstNoDataValue;
+    } 
+    else if ( psData->bAngleAsAzimuth )
+    {
+        if (aspect > 90.0) 
+            aspect = 450.0f - aspect;
+        else
+            aspect = 90.0f - aspect;
+    }
+    else
+    {
+        if (aspect < 0)
+            aspect += 360.0;
+    }
+
+    if (aspect == 360.0) 
+        aspect = 0.0;
+
+    return aspect;
+}
+void*  GDALCreateAspectData(int bAngleAsAzimuth)
+{
+    GDALAspectAlgData* pData =
+        (GDALAspectAlgData*)CPLMalloc(sizeof(GDALAspectAlgData));
+        
+    pData->bAngleAsAzimuth = bAngleAsAzimuth;
+    return pData;
+}
+
+/************************************************************************/
+/*                      GDALColorRelief()                               */
+/************************************************************************/
+
+typedef struct
+{
+    double dfVal;
+    int nR;
+    int nG;
+    int nB;
+    int nA;
+} ColorAssociation;
+
+static int GDALColorReliefSortColors(const void* pA, const void* pB)
+{
+    ColorAssociation* pC1 = (ColorAssociation*)pA;
+    ColorAssociation* pC2 = (ColorAssociation*)pB;
+    return (pC1->dfVal < pC2->dfVal) ? -1 :
+           (pC1->dfVal == pC2->dfVal) ? 0 : 1;
+}
+
+typedef enum
+{
+    COLOR_SELECTION_INTERPOLATE,
+    COLOR_SELECTION_NEAREST_ENTRY,
+    COLOR_SELECTION_EXACT_ENTRY
+} ColorSelectionMode;
+
+static int GDALColorReliefGetRGBA (ColorAssociation* pasColorAssociation,
+                                   int nColorAssociation,
+                                   double dfVal,
+                                   ColorSelectionMode eColorSelectionMode,
+                                   int* pnR,
+                                   int* pnG,
+                                   int* pnB,
+                                   int* pnA)
+{
+    int i;
+    int lower = 0;
+    int upper = nColorAssociation - 1;
+    int mid;
+
+    /* Find the index of the first element in the LUT input array that */
+    /* is not smaller than the dfVal value. */
+    while(TRUE)
+    {
+        mid = (lower + upper) / 2;
+        if (upper - lower <= 1)
+        {
+            if (dfVal < pasColorAssociation[lower].dfVal)
+                i = lower;
+            else if (dfVal < pasColorAssociation[upper].dfVal)
+                i = upper;
+            else
+                i = upper + 1;
+            break;
+        }
+        else if (pasColorAssociation[mid].dfVal >= dfVal)
+        {
+            upper = mid;
+        }
+        else
+        {
+            lower = mid;
+        }
+    }
+
+    if (i == 0)
+    {
+        if (eColorSelectionMode == COLOR_SELECTION_EXACT_ENTRY &&
+            pasColorAssociation[0].dfVal != dfVal)
+        {
+            *pnR = 0;
+            *pnG = 0;
+            *pnB = 0;
+            *pnA = 0;
+            return FALSE;
+        }
+        else
+        {
+            *pnR = pasColorAssociation[0].nR;
+            *pnG = pasColorAssociation[0].nG;
+            *pnB = pasColorAssociation[0].nB;
+            *pnA = pasColorAssociation[0].nA;
+            return TRUE;
+        }
+    }
+    else if (i == nColorAssociation)
+    {
+        if (eColorSelectionMode == COLOR_SELECTION_EXACT_ENTRY &&
+            pasColorAssociation[i-1].dfVal != dfVal)
+        {
+            *pnR = 0;
+            *pnG = 0;
+            *pnB = 0;
+            *pnA = 0;
+            return FALSE;
+        }
+        else
+        {
+            *pnR = pasColorAssociation[i-1].nR;
+            *pnG = pasColorAssociation[i-1].nG;
+            *pnB = pasColorAssociation[i-1].nB;
+            *pnA = pasColorAssociation[i-1].nA;
+            return TRUE;
+        }
+    }
+    else
+    {
+        if (eColorSelectionMode == COLOR_SELECTION_EXACT_ENTRY &&
+            pasColorAssociation[i-1].dfVal != dfVal)
+        {
+            *pnR = 0;
+            *pnG = 0;
+            *pnB = 0;
+            *pnA = 0;
+            return FALSE;
+        }
+        
+        if (eColorSelectionMode == COLOR_SELECTION_NEAREST_ENTRY &&
+            pasColorAssociation[i-1].dfVal != dfVal)
+        {
+            int index;
+            if (dfVal - pasColorAssociation[i-1].dfVal <
+                pasColorAssociation[i].dfVal - dfVal)
+                index = i -1;
+            else
+                index = i;
+
+            *pnR = pasColorAssociation[index].nR;
+            *pnG = pasColorAssociation[index].nG;
+            *pnB = pasColorAssociation[index].nB;
+            *pnA = pasColorAssociation[index].nA;
+            return TRUE;
+        }
+        
+        double dfRatio = (dfVal - pasColorAssociation[i-1].dfVal) /
+            (pasColorAssociation[i].dfVal - pasColorAssociation[i-1].dfVal);
+        *pnR = (int)(0.45 + pasColorAssociation[i-1].nR + dfRatio *
+                (pasColorAssociation[i].nR - pasColorAssociation[i-1].nR));
+        if (*pnR < 0) *pnR = 0;
+        else if (*pnR > 255) *pnR = 255;
+        *pnG = (int)(0.45 + pasColorAssociation[i-1].nG + dfRatio *
+                (pasColorAssociation[i].nG - pasColorAssociation[i-1].nG));
+        if (*pnG < 0) *pnG = 0;
+        else if (*pnG > 255) *pnG = 255;
+        *pnB = (int)(0.45 + pasColorAssociation[i-1].nB + dfRatio *
+                (pasColorAssociation[i].nB - pasColorAssociation[i-1].nB));
+        if (*pnB < 0) *pnB = 0;
+        else if (*pnB > 255) *pnB = 255;
+        *pnA = (int)(0.45 + pasColorAssociation[i-1].nA + dfRatio *
+                (pasColorAssociation[i].nA - pasColorAssociation[i-1].nA));
+        if (*pnA < 0) *pnA = 0;
+        else if (*pnA > 255) *pnA = 255;
+        
+        return TRUE;
+    }
+}
+
+/* dfPct : percentage between 0 and 1 */
+static double GDALColorReliefGetAbsoluteValFromPct(GDALRasterBandH hSrcBand,
+                                                   double dfPct)
+{
+    double dfMin, dfMax;
+    int bSuccessMin, bSuccessMax;
+    dfMin = GDALGetRasterMinimum(hSrcBand, &bSuccessMin);
+    dfMax = GDALGetRasterMaximum(hSrcBand, &bSuccessMax);
+    if (!bSuccessMin || !bSuccessMax)
+    {
+        double dfMean, dfStdDev;
+        fprintf(stderr, "Computing source raster statistics...\n");
+        GDALComputeRasterStatistics(hSrcBand, FALSE, &dfMin, &dfMax,
+                                    &dfMean, &dfStdDev, NULL, NULL);
+    }
+    return dfMin + dfPct * (dfMax - dfMin);
+}
+
+typedef struct
+{
+    const char *name;
+    float r, g, b;
+} NamedColor;
+
+static const NamedColor namedColors[] = {
+    { "white",  1.00, 1.00, 1.00 },
+    { "black",  0.00, 0.00, 0.00 },
+    { "red",    1.00, 0.00, 0.00 },
+    { "green",  0.00, 1.00, 0.00 },
+    { "blue",   0.00, 0.00, 1.00 },
+    { "yellow", 1.00, 1.00, 0.00 },
+    { "magenta",1.00, 0.00, 1.00 },
+    { "cyan",   0.00, 1.00, 1.00 },
+    { "aqua",   0.00, 0.75, 0.75 },
+    { "grey",   0.75, 0.75, 0.75 },
+    { "gray",   0.75, 0.75, 0.75 },
+    { "orange", 1.00, 0.50, 0.00 },
+    { "brown",  0.75, 0.50, 0.25 },
+    { "purple", 0.50, 0.00, 1.00 },
+    { "violet", 0.50, 0.00, 1.00 },
+    { "indigo", 0.00, 0.50, 1.00 },
+};
+
+static
+int GDALColorReliefFindNamedColor(const char *pszColorName, int *pnR, int *pnG, int *pnB)
+{
+    unsigned int i;
+
+    *pnR = *pnG = *pnB = 0;
+    for (i = 0; i < sizeof(namedColors) / sizeof(namedColors[0]); i++)
+    {
+        if (EQUAL(pszColorName, namedColors[i].name))
+        {
+            *pnR = (int)(255. * namedColors[i].r);
+            *pnG = (int)(255. * namedColors[i].g);
+            *pnB = (int)(255. * namedColors[i].b);
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+static
+ColorAssociation* GDALColorReliefParseColorFile(GDALRasterBandH hSrcBand,
+                                                const char* pszColorFilename,
+                                                int* pnColors)
+{
+    VSILFILE* fpColorFile = VSIFOpenL(pszColorFilename, "rt");
+    if (fpColorFile == NULL)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined, "Cannot find %s", pszColorFilename);
+        *pnColors = 0;
+        return NULL;
+    }
+
+    ColorAssociation* pasColorAssociation = NULL;
+    int nColorAssociation = 0;
+
+    int bSrcHasNoData = FALSE;
+    double dfSrcNoDataValue = GDALGetRasterNoDataValue(hSrcBand, &bSrcHasNoData);
+
+    const char* pszLine;
+    int bIsGMT_CPT = FALSE;
+    while ((pszLine = CPLReadLineL(fpColorFile)) != NULL)
+    {
+        if (pszLine[0] == '#' && strstr(pszLine, "COLOR_MODEL"))
+        {
+            if (strstr(pszLine, "COLOR_MODEL = RGB") == NULL)
+            {
+                CPLError(CE_Failure, CPLE_AppDefined, "Only COLOR_MODEL = RGB is supported");
+                CPLFree(pasColorAssociation);
+                *pnColors = 0;
+                return NULL;
+            }
+            bIsGMT_CPT = TRUE;
+        }
+
+        char** papszFields = CSLTokenizeStringComplex(pszLine, " ,\t:", 
+                                                      FALSE, FALSE );
+        /* Skip comment lines */
+        int nTokens = CSLCount(papszFields);
+        if (nTokens >= 1 && (papszFields[0][0] == '#' ||
+                             papszFields[0][0] == '/'))
+        {
+            CSLDestroy(papszFields);
+            continue;
+        }
+
+        if (bIsGMT_CPT && nTokens == 8)
+        {
+            pasColorAssociation =
+                    (ColorAssociation*)CPLRealloc(pasColorAssociation,
+                           (nColorAssociation + 2) * sizeof(ColorAssociation));
+
+            pasColorAssociation[nColorAssociation].dfVal = atof(papszFields[0]);
+            pasColorAssociation[nColorAssociation].nR = atoi(papszFields[1]);
+            pasColorAssociation[nColorAssociation].nG = atoi(papszFields[2]);
+            pasColorAssociation[nColorAssociation].nB = atoi(papszFields[3]);
+            pasColorAssociation[nColorAssociation].nA = 255;
+            nColorAssociation++;
+
+            pasColorAssociation[nColorAssociation].dfVal = atof(papszFields[4]);
+            pasColorAssociation[nColorAssociation].nR = atoi(papszFields[5]);
+            pasColorAssociation[nColorAssociation].nG = atoi(papszFields[6]);
+            pasColorAssociation[nColorAssociation].nB = atoi(papszFields[7]);
+            pasColorAssociation[nColorAssociation].nA = 255;
+            nColorAssociation++;
+        }
+        else if (bIsGMT_CPT && nTokens == 4)
+        {
+            /* The first token might be B (background), F (foreground) or N (nodata) */
+            /* Just interested in N */
+            if (EQUAL(papszFields[0], "N") && bSrcHasNoData)
+            {
+                 pasColorAssociation =
+                    (ColorAssociation*)CPLRealloc(pasColorAssociation,
+                           (nColorAssociation + 1) * sizeof(ColorAssociation));
+
+                pasColorAssociation[nColorAssociation].dfVal = dfSrcNoDataValue;
+                pasColorAssociation[nColorAssociation].nR = atoi(papszFields[1]);
+                pasColorAssociation[nColorAssociation].nG = atoi(papszFields[2]);
+                pasColorAssociation[nColorAssociation].nB = atoi(papszFields[3]);
+                pasColorAssociation[nColorAssociation].nA = 255;
+                nColorAssociation++;
+            }
+        }
+        else if (!bIsGMT_CPT && nTokens >= 2)
+        {
+            pasColorAssociation =
+                    (ColorAssociation*)CPLRealloc(pasColorAssociation,
+                           (nColorAssociation + 1) * sizeof(ColorAssociation));
+            if (EQUAL(papszFields[0], "nv") && bSrcHasNoData)
+                pasColorAssociation[nColorAssociation].dfVal = dfSrcNoDataValue;
+            else if (strlen(papszFields[0]) > 1 && papszFields[0][strlen(papszFields[0])-1] == '%')
+            {
+                double dfPct = atof(papszFields[0]) / 100.;
+                if (dfPct < 0.0 || dfPct > 1.0)
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Wrong value for a percentage : %s", papszFields[0]);
+                    CSLDestroy(papszFields);
+                    VSIFCloseL(fpColorFile);
+                    CPLFree(pasColorAssociation);
+                    *pnColors = 0;
+                    return NULL;
+                }
+                pasColorAssociation[nColorAssociation].dfVal =
+                        GDALColorReliefGetAbsoluteValFromPct(hSrcBand, dfPct);
+            }
+            else
+                pasColorAssociation[nColorAssociation].dfVal = atof(papszFields[0]);
+
+            if (nTokens >= 4)
+            {
+                pasColorAssociation[nColorAssociation].nR = atoi(papszFields[1]);
+                pasColorAssociation[nColorAssociation].nG = atoi(papszFields[2]);
+                pasColorAssociation[nColorAssociation].nB = atoi(papszFields[3]);
+                pasColorAssociation[nColorAssociation].nA =
+                        (CSLCount(papszFields) >= 5 ) ? atoi(papszFields[4]) : 255;
+            }
+            else
+            {
+                int nR, nG, nB;
+                if (!GDALColorReliefFindNamedColor(papszFields[1], &nR, &nG, &nB))
+                {
+                    CPLError(CE_Failure, CPLE_AppDefined,
+                             "Unknown color : %s", papszFields[1]);
+                    CSLDestroy(papszFields);
+                    VSIFCloseL(fpColorFile);
+                    CPLFree(pasColorAssociation);
+                    *pnColors = 0;
+                    return NULL;
+                }
+                pasColorAssociation[nColorAssociation].nR = nR;
+                pasColorAssociation[nColorAssociation].nG = nG;
+                pasColorAssociation[nColorAssociation].nB = nB;
+                            pasColorAssociation[nColorAssociation].nA =
+                    (CSLCount(papszFields) >= 3 ) ? atoi(papszFields[2]) : 255;
+            }
+
+            nColorAssociation ++;
+        }
+        CSLDestroy(papszFields);
+    }
+    VSIFCloseL(fpColorFile);
+
+    if (nColorAssociation == 0)
+    {
+        CPLError(CE_Failure, CPLE_AppDefined,
+                 "No color association found in %s", pszColorFilename);
+        *pnColors = 0;
+        return NULL;
+    }
+
+    qsort(pasColorAssociation, nColorAssociation,
+          sizeof(ColorAssociation), GDALColorReliefSortColors);
+
+    *pnColors = nColorAssociation;
+    return pasColorAssociation;
+}
+
+static
+GByte* GDALColorReliefPrecompute(GDALRasterBandH hSrcBand,
+                                 ColorAssociation* pasColorAssociation,
+                                 int nColorAssociation,
+                                 ColorSelectionMode eColorSelectionMode,
+                                 int* pnIndexOffset)
+{
+    GDALDataType eDT = GDALGetRasterDataType(hSrcBand);
+    GByte* pabyPrecomputed = NULL;
+    int nIndexOffset = (eDT == GDT_Int16) ? 32768 : 0;
+    *pnIndexOffset = nIndexOffset;
+    int nXSize = GDALGetRasterBandXSize(hSrcBand);
+    int nYSize = GDALGetRasterBandXSize(hSrcBand);
+    if (eDT == GDT_Byte ||
+        ((eDT == GDT_Int16 || eDT == GDT_UInt16) && nXSize * nYSize > 65536))
+    {
+        int iMax = (eDT == GDT_Byte) ? 256: 65536;
+        pabyPrecomputed = (GByte*) VSIMalloc(4 * iMax);
+        if (pabyPrecomputed)
+        {
+            int i;
+            for(i=0;i<iMax;i++)
+            {
+                int nR, nG, nB, nA;
+                GDALColorReliefGetRGBA  (pasColorAssociation,
+                                         nColorAssociation,
+                                         i - nIndexOffset,
+                                         eColorSelectionMode,
+                                         &nR, &nG, &nB, &nA);
+                pabyPrecomputed[4 * i] = (GByte) nR;
+                pabyPrecomputed[4 * i + 1] = (GByte) nG;
+                pabyPrecomputed[4 * i + 2] = (GByte) nB;
+                pabyPrecomputed[4 * i + 3] = (GByte) nA;
+            }
+        }
+    }
+    return pabyPrecomputed;
+}
+
+/************************************************************************/
+/* ==================================================================== */
+/*                       GDALColorReliefDataset                        */
+/* ==================================================================== */
+/************************************************************************/
+
+class GDALColorReliefRasterBand;
+
+class GDALColorReliefDataset : public GDALDataset
+{
+    friend class GDALColorReliefRasterBand;
+
+    GDALDatasetH       hSrcDS;
+    GDALRasterBandH    hSrcBand;
+    int                nColorAssociation;
+    ColorAssociation*  pasColorAssociation;
+    ColorSelectionMode eColorSelectionMode;
+    GByte*             pabyPrecomputed;
+    int                nIndexOffset;
+    float*             pafSourceBuf;
+    int*               panSourceBuf;
+    int                nCurBlockXOff;
+    int                nCurBlockYOff;
+
+  public:
+                        GDALColorReliefDataset(GDALDatasetH hSrcDS,
+                                            GDALRasterBandH hSrcBand,
+                                            const char* pszColorFilename,
+                                            ColorSelectionMode eColorSelectionMode,
+                                            int bAlpha);
+                       ~GDALColorReliefDataset();
+
+    CPLErr      GetGeoTransform( double * padfGeoTransform );
+    const char *GetProjectionRef();
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                    GDALColorReliefRasterBand                       */
+/* ==================================================================== */
+/************************************************************************/
+
+class GDALColorReliefRasterBand : public GDALRasterBand
+{
+    friend class GDALColorReliefDataset;
+
+    
+  public:
+                 GDALColorReliefRasterBand( GDALColorReliefDataset *, int );
+    
+    virtual CPLErr          IReadBlock( int, int, void * );
+    virtual GDALColorInterp GetColorInterpretation();
+};
+
+GDALColorReliefDataset::GDALColorReliefDataset(
+                                     GDALDatasetH hSrcDS,
+                                     GDALRasterBandH hSrcBand,
+                                     const char* pszColorFilename,
+                                     ColorSelectionMode eColorSelectionMode,
+                                     int bAlpha)
+{
+    this->hSrcDS = hSrcDS;
+    this->hSrcBand = hSrcBand;
+    nColorAssociation = 0;
+    pasColorAssociation =
+            GDALColorReliefParseColorFile(hSrcBand, pszColorFilename,
+                                          &nColorAssociation);
+    this->eColorSelectionMode = eColorSelectionMode;
+    
+    nRasterXSize = GDALGetRasterXSize(hSrcDS);
+    nRasterYSize = GDALGetRasterYSize(hSrcDS);
+    
+    int nBlockXSize, nBlockYSize;
+    GDALGetBlockSize( hSrcBand, &nBlockXSize, &nBlockYSize);
+    
+    nIndexOffset = 0;
+    pabyPrecomputed =
+        GDALColorReliefPrecompute(hSrcBand,
+                                  pasColorAssociation,
+                                  nColorAssociation,
+                                  eColorSelectionMode,
+                                  &nIndexOffset);
+    
+    int i;
+    for(i=0;i<((bAlpha) ? 4 : 3);i++)
+    {
+        SetBand(i + 1, new GDALColorReliefRasterBand(this, i+1));
+    }
+    
+    pafSourceBuf = NULL;
+    panSourceBuf = NULL;
+    if (pabyPrecomputed)
+        panSourceBuf = (int *) CPLMalloc(sizeof(int)*nBlockXSize*nBlockYSize);
+    else
+        pafSourceBuf = (float *) CPLMalloc(sizeof(float)*nBlockXSize*nBlockYSize);
+    nCurBlockXOff = -1;
+    nCurBlockYOff = -1;
+}
+
+GDALColorReliefDataset::~GDALColorReliefDataset()
+{
+    CPLFree(pasColorAssociation);
+    CPLFree(pabyPrecomputed);
+    CPLFree(panSourceBuf);
+    CPLFree(pafSourceBuf);
+}
+
+CPLErr GDALColorReliefDataset::GetGeoTransform( double * padfGeoTransform )
+{
+    return GDALGetGeoTransform(hSrcDS, padfGeoTransform);
+}
+
+const char *GDALColorReliefDataset::GetProjectionRef()
+{
+    return GDALGetProjectionRef(hSrcDS);
+}
+
+GDALColorReliefRasterBand::GDALColorReliefRasterBand(
+                                    GDALColorReliefDataset * poDS, int nBand)
+{
+    this->poDS = poDS;
+    this->nBand = nBand;
+    eDataType = GDT_Byte;
+    GDALGetBlockSize( poDS->hSrcBand, &nBlockXSize, &nBlockYSize);
+}
+
+CPLErr GDALColorReliefRasterBand::IReadBlock( int nBlockXOff,
+                                              int nBlockYOff,
+                                              void *pImage )
+{
+    GDALColorReliefDataset * poGDS = (GDALColorReliefDataset *) poDS;
+    int nReqXSize, nReqYSize;
+
+    if ((nBlockXOff + 1) * nBlockXSize >= nRasterXSize)
+        nReqXSize = nRasterXSize - nBlockXOff * nBlockXSize;
+    else
+        nReqXSize = nBlockXSize;
+        
+    if ((nBlockYOff + 1) * nBlockYSize >= nRasterYSize)
+        nReqYSize = nRasterYSize - nBlockYOff * nBlockYSize;
+    else
+        nReqYSize = nBlockYSize;
+
+    if ( poGDS->nCurBlockXOff != nBlockXOff ||
+         poGDS->nCurBlockYOff != nBlockYOff )
+    {
+        poGDS->nCurBlockXOff = nBlockXOff;
+        poGDS->nCurBlockYOff = nBlockYOff;
+        
+        CPLErr eErr = GDALRasterIO( poGDS->hSrcBand,
+                            GF_Read,
+                            nBlockXOff * nBlockXSize,
+                            nBlockYOff * nBlockYSize,
+                            nReqXSize, nReqYSize,
+                            (poGDS->panSourceBuf) ?
+                                (void*) poGDS->panSourceBuf :
+                                (void* )poGDS->pafSourceBuf,
+                            nReqXSize, nReqYSize,
+                            (poGDS->panSourceBuf) ? GDT_Int32 : GDT_Float32,
+                            0, 0);
+        if (eErr != CE_None)
+        {
+            memset(pImage, 0, nBlockXSize * nBlockYSize);
+            return eErr;
+        }
+    }
+
+    int x, y, j = 0;
+    if (poGDS->panSourceBuf)
+    {
+        for( y = 0; y < nReqYSize; y++ )
+        {
+            for( x = 0; x < nReqXSize; x++ )
+            {
+                int nIndex = poGDS->panSourceBuf[j] + poGDS->nIndexOffset;
+                ((GByte*)pImage)[y * nBlockXSize + x] = poGDS->pabyPrecomputed[4*nIndex + nBand-1];
+                j++;
+            }
+        }
+    }
+    else
+    {
+        int anComponents[4];
+        for( y = 0; y < nReqYSize; y++ )
+        {
+            for( x = 0; x < nReqXSize; x++ )
+            {
+                GDALColorReliefGetRGBA  (poGDS->pasColorAssociation,
+                                        poGDS->nColorAssociation,
+                                        poGDS->pafSourceBuf[j],
+                                        poGDS->eColorSelectionMode,
+                                        &anComponents[0],
+                                        &anComponents[1],
+                                        &anComponents[2],
+                                        &anComponents[3]);
+                ((GByte*)pImage)[y * nBlockXSize + x] = (GByte) anComponents[nBand-1];
+                j++;
+            }
+        }
+    }
+    
+    return CE_None;
+}
+
+GDALColorInterp GDALColorReliefRasterBand::GetColorInterpretation()
+{
+    return (GDALColorInterp)(GCI_RedBand + nBand - 1);
+}
+
+
+CPLErr GDALColorRelief (GDALRasterBandH hSrcBand,
+                        GDALRasterBandH hDstBand1,
+                        GDALRasterBandH hDstBand2,
+                        GDALRasterBandH hDstBand3,
+                        GDALRasterBandH hDstBand4,
+                        const char* pszColorFilename,
+                        ColorSelectionMode eColorSelectionMode,
+                        GDALProgressFunc pfnProgress,
+                        void * pProgressData)
+{
+    CPLErr eErr;
+    
+    if (hSrcBand == NULL || hDstBand1 == NULL || hDstBand2 == NULL ||
+        hDstBand3 == NULL)
+        return CE_Failure;
+
+    int nColorAssociation = 0;
+    ColorAssociation* pasColorAssociation =
+            GDALColorReliefParseColorFile(hSrcBand, pszColorFilename,
+                                          &nColorAssociation);
+    if (pasColorAssociation == NULL)
+        return CE_Failure;
+
+    int nXSize = GDALGetRasterBandXSize(hSrcBand);
+    int nYSize = GDALGetRasterBandYSize(hSrcBand);
+
+    if (pfnProgress == NULL)
+        pfnProgress = GDALDummyProgress;
+        
+    int nR = 0, nG = 0, nB = 0, nA = 0;
+    
+/* -------------------------------------------------------------------- */
+/*      Precompute the map from values to RGBA quadruplets              */
+/*      for GDT_Byte, GDT_Int16 or GDT_UInt16                           */
+/* -------------------------------------------------------------------- */
+    int nIndexOffset = 0;
+    GByte* pabyPrecomputed =
+        GDALColorReliefPrecompute(hSrcBand,
+                                  pasColorAssociation,
+                                  nColorAssociation,
+                                  eColorSelectionMode,
+                                  &nIndexOffset);
+
+/* -------------------------------------------------------------------- */
+/*      Initialize progress counter.                                    */
+/* -------------------------------------------------------------------- */
+
+    float* pafSourceBuf = NULL;
+    int* panSourceBuf = NULL;
+    if (pabyPrecomputed)
+        panSourceBuf = (int *) CPLMalloc(sizeof(int)*nXSize);
+    else
+        pafSourceBuf = (float *) CPLMalloc(sizeof(float)*nXSize);
+    GByte* pabyDestBuf1  = (GByte*) CPLMalloc( 4 * nXSize );
+    GByte* pabyDestBuf2  =  pabyDestBuf1 + nXSize;
+    GByte* pabyDestBuf3  =  pabyDestBuf2 + nXSize;
+    GByte* pabyDestBuf4  =  pabyDestBuf3 + nXSize;
+    int i, j;
+
+    if( !pfnProgress( 0.0, NULL, pProgressData ) )
+    {
+        CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
+        eErr = CE_Failure;
+        goto end;
+    }
+
+    for ( i = 0; i < nYSize; i++)
+    {
+        /* Read source buffer */
+        eErr = GDALRasterIO(   hSrcBand,
+                        GF_Read,
+                        0, i,
+                        nXSize, 1,
+                        (panSourceBuf) ? (void*) panSourceBuf : (void* )pafSourceBuf,
+                        nXSize, 1,
+                        (panSourceBuf) ? GDT_Int32 : GDT_Float32,
+                        0, 0);
+        if (eErr != CE_None)
+            goto end;
+
+        if (panSourceBuf)
+        {
+            for ( j = 0; j < nXSize; j++)
+            {
+                int nIndex = panSourceBuf[j] + nIndexOffset;
+                pabyDestBuf1[j] = pabyPrecomputed[4 * nIndex];
+                pabyDestBuf2[j] = pabyPrecomputed[4 * nIndex + 1];
+                pabyDestBuf3[j] = pabyPrecomputed[4 * nIndex + 2];
+                pabyDestBuf4[j] = pabyPrecomputed[4 * nIndex + 3];
+            }
+        }
+        else
+        {
+            for ( j = 0; j < nXSize; j++)
+            {
+                GDALColorReliefGetRGBA  (pasColorAssociation,
+                                         nColorAssociation,
+                                         pafSourceBuf[j],
+                                         eColorSelectionMode,
+                                         &nR,
+                                         &nG,
+                                         &nB,
+                                         &nA);
+                pabyDestBuf1[j] = (GByte) nR;
+                pabyDestBuf2[j] = (GByte) nG;
+                pabyDestBuf3[j] = (GByte) nB;
+                pabyDestBuf4[j] = (GByte) nA;
+            }
+        }
+        
+        /* -----------------------------------------
+         * Write Line to Raster
+         */
+        eErr = GDALRasterIO(hDstBand1,
+                      GF_Write,
+                      0, i, nXSize,
+                      1, pabyDestBuf1, nXSize, 1, GDT_Byte, 0, 0);
+        if (eErr != CE_None)
+            goto end;
+
+        eErr = GDALRasterIO(hDstBand2,
+                      GF_Write,
+                      0, i, nXSize,
+                      1, pabyDestBuf2, nXSize, 1, GDT_Byte, 0, 0);
+        if (eErr != CE_None)
+            goto end;
+            
+        eErr = GDALRasterIO(hDstBand3,
+                      GF_Write,
+                      0, i, nXSize,
+                      1, pabyDestBuf3, nXSize, 1, GDT_Byte, 0, 0);
+        if (eErr != CE_None)
+            goto end;
+            
+        if (hDstBand4)
+        {
+            eErr = GDALRasterIO(hDstBand4,
+                        GF_Write,
+                        0, i, nXSize,
+                        1, pabyDestBuf4, nXSize, 1, GDT_Byte, 0, 0);
+            if (eErr != CE_None)
+                goto end;
+        }
+
+        if( !pfnProgress( 1.0 * (i+1) / nYSize, NULL, pProgressData ) )
+        {
+            CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
+            eErr = CE_Failure;
+            goto end;
+        }
+    }
+    pfnProgress( 1.0, NULL, pProgressData );
+    eErr = CE_None;
+
+end:
+    VSIFree(pabyPrecomputed);
+    CPLFree(pafSourceBuf);
+    CPLFree(panSourceBuf);
+    CPLFree(pabyDestBuf1);
+    CPLFree(pasColorAssociation);
+
+    return eErr;
+}
+
+/************************************************************************/
+/*                     GDALGenerateVRTColorRelief()                     */
+/************************************************************************/
+
+CPLErr GDALGenerateVRTColorRelief(const char* pszDstFilename,
+                               GDALDatasetH hSrcDataset,
+                               GDALRasterBandH hSrcBand,
+                               const char* pszColorFilename,
+                               ColorSelectionMode eColorSelectionMode,
+                               int bAddAlpha)
+{
+
+    int nColorAssociation = 0;
+    ColorAssociation* pasColorAssociation =
+            GDALColorReliefParseColorFile(hSrcBand, pszColorFilename,
+                                          &nColorAssociation);
+    if (pasColorAssociation == NULL)
+        return CE_Failure;
+
+    int nXSize = GDALGetRasterBandXSize(hSrcBand);
+    int nYSize = GDALGetRasterBandYSize(hSrcBand);
+
+    VSILFILE* fp = VSIFOpenL(pszDstFilename, "wt");
+    if (fp == NULL)
+    {
+        CPLFree(pasColorAssociation);
+        return CE_Failure;
+    }
+
+    VSIFPrintfL(fp, "<VRTDataset rasterXSize=\"%d\" rasterYSize=\"%d\">\n", nXSize, nYSize);
+    const char* pszProjectionRef = GDALGetProjectionRef(hSrcDataset);
+    if (pszProjectionRef && pszProjectionRef[0] != '\0')
+    {
+        char* pszEscapedString = CPLEscapeString(pszProjectionRef, -1, CPLES_XML);
+        VSIFPrintfL(fp, "  <SRS>%s</SRS>\n", pszEscapedString);
+        VSIFree(pszEscapedString);
+    }
+    double adfGT[6];
+    if (GDALGetGeoTransform(hSrcDataset, adfGT) == CE_None)
+    {
+        VSIFPrintfL(fp, "  <GeoTransform> %.16g, %.16g, %.16g, "
+                        "%.16g, %.16g, %.16g</GeoTransform>\n",
+                        adfGT[0], adfGT[1], adfGT[2], adfGT[3], adfGT[4], adfGT[5]);
+    }
+    int nBands = 3 + (bAddAlpha ? 1 : 0);
+    int iBand;
+
+    int nBlockXSize, nBlockYSize;
+    GDALGetBlockSize(hSrcBand, &nBlockXSize, &nBlockYSize);
+    
+    int bRelativeToVRT;
+    CPLString osPath = CPLGetPath(pszDstFilename);
+    char* pszSourceFilename = CPLStrdup(
+        CPLExtractRelativePath( osPath.c_str(), GDALGetDescription(hSrcDataset), 
+                                &bRelativeToVRT ));
+
+    for(iBand = 0; iBand < nBands; iBand++)
+    {
+        VSIFPrintfL(fp, "  <VRTRasterBand dataType=\"Byte\" band=\"%d\">\n", iBand + 1);
+        VSIFPrintfL(fp, "    <ColorInterp>%s</ColorInterp>\n",
+                    GDALGetColorInterpretationName((GDALColorInterp)(GCI_RedBand + iBand)));
+        VSIFPrintfL(fp, "    <ComplexSource>\n");
+        VSIFPrintfL(fp, "      <SourceFilename relativeToVRT=\"%d\">%s</SourceFilename>\n",
+                        bRelativeToVRT, pszSourceFilename);
+        VSIFPrintfL(fp, "      <SourceBand>%d</SourceBand>\n", GDALGetBandNumber(hSrcBand));
+        VSIFPrintfL(fp, "      <SourceProperties RasterXSize=\"%d\" "
+                        "RasterYSize=\"%d\" DataType=\"%s\" "
+                        "BlockXSize=\"%d\" BlockYSize=\"%d\"/>\n",
+                        nXSize, nYSize,
+                        GDALGetDataTypeName(GDALGetRasterDataType(hSrcBand)),
+                        nBlockXSize, nBlockYSize);
+        VSIFPrintfL(fp, "      <SrcRect xOff=\"0\" yOff=\"0\" xSize=\"%d\" ySize=\"%d\"/>\n",
+                        nXSize, nYSize);
+        VSIFPrintfL(fp, "      <DstRect xOff=\"0\" yOff=\"0\" xSize=\"%d\" ySize=\"%d\"/>\n",
+                        nXSize, nYSize);
+
+        VSIFPrintfL(fp, "      <LUT>");
+        int iColor;
+#define EPSILON 1e-8
+        for(iColor=0;iColor<nColorAssociation;iColor++)
+        {
+            if (eColorSelectionMode == COLOR_SELECTION_NEAREST_ENTRY)
+            {
+                if (iColor > 1)
+                    VSIFPrintfL(fp, ",");
+            }
+            else if (iColor > 0)
+                VSIFPrintfL(fp, ",");
+
+            double dfVal = pasColorAssociation[iColor].dfVal;
+
+            if (eColorSelectionMode == COLOR_SELECTION_EXACT_ENTRY)
+            {
+                VSIFPrintfL(fp, "%.12g:0,", dfVal - EPSILON);
+            }
+            else if (iColor > 0 &&
+                     eColorSelectionMode == COLOR_SELECTION_NEAREST_ENTRY)
+            {
+                double dfMidVal = (dfVal + pasColorAssociation[iColor-1].dfVal) / 2;
+                VSIFPrintfL(fp, "%.12g:%d", dfMidVal - EPSILON,
+                        (iBand == 0) ? pasColorAssociation[iColor-1].nR :
+                        (iBand == 1) ? pasColorAssociation[iColor-1].nG :
+                        (iBand == 2) ? pasColorAssociation[iColor-1].nB :
+                                       pasColorAssociation[iColor-1].nA);
+                VSIFPrintfL(fp, ",%.12g:%d", dfMidVal ,
+                        (iBand == 0) ? pasColorAssociation[iColor].nR :
+                        (iBand == 1) ? pasColorAssociation[iColor].nG :
+                        (iBand == 2) ? pasColorAssociation[iColor].nB :
+                                       pasColorAssociation[iColor].nA);
+
+            }
+
+            if (eColorSelectionMode != COLOR_SELECTION_NEAREST_ENTRY)
+            {
+                if (dfVal != (double)(int)dfVal)
+                    VSIFPrintfL(fp, "%.12g", dfVal);
+                else
+                    VSIFPrintfL(fp, "%d", (int)dfVal);
+                VSIFPrintfL(fp, ":%d",
+                            (iBand == 0) ? pasColorAssociation[iColor].nR :
+                            (iBand == 1) ? pasColorAssociation[iColor].nG :
+                            (iBand == 2) ? pasColorAssociation[iColor].nB :
+                                           pasColorAssociation[iColor].nA);
+            }
+
+            if (eColorSelectionMode == COLOR_SELECTION_EXACT_ENTRY)
+            {
+                VSIFPrintfL(fp, ",%.12g:0", dfVal + EPSILON);
+            }
+
+        }
+        VSIFPrintfL(fp, "</LUT>\n");
+
+        VSIFPrintfL(fp, "    </ComplexSource>\n");
+        VSIFPrintfL(fp, "  </VRTRasterBand>\n");
+    }
+
+    CPLFree(pszSourceFilename);
+
+    VSIFPrintfL(fp, "</VRTDataset>\n");
+
+    VSIFCloseL(fp);
+
+    CPLFree(pasColorAssociation);
+
+    return CE_None;
+}
+
+
+/************************************************************************/
+/*                         GDALTRIAlg()                                 */
+/************************************************************************/
+
+float GDALTRIAlg (float* afWin, float fDstNoDataValue, void* pData)
+{
+    // Terrain Ruggedness is average difference in height
+    return (fabs(afWin[0]-afWin[4]) +
+            fabs(afWin[1]-afWin[4]) +
+            fabs(afWin[2]-afWin[4]) +
+            fabs(afWin[3]-afWin[4]) +
+            fabs(afWin[5]-afWin[4]) +
+            fabs(afWin[6]-afWin[4]) +
+            fabs(afWin[7]-afWin[4]) +
+            fabs(afWin[8]-afWin[4]))/8;
+}
+
+
+/************************************************************************/
+/*                         GDALTPIAlg()                                 */
+/************************************************************************/
+
+float GDALTPIAlg (float* afWin, float fDstNoDataValue, void* pData)
+{
+    // Terrain Position is the difference between
+    // The central cell and the mean of the surrounding cells
+    return afWin[4] - 
+            ((afWin[0]+
+              afWin[1]+
+              afWin[2]+
+              afWin[3]+
+              afWin[5]+
+              afWin[6]+
+              afWin[7]+
+              afWin[8])/8);
+}
+
+/************************************************************************/
+/*                     GDALRoughnessAlg()                               */
+/************************************************************************/
+
+float GDALRoughnessAlg (float* afWin, float fDstNoDataValue, void* pData)
+{
+    // Roughness is the largest difference
+    //  between any two cells
+
+    float pafRoughnessMin = afWin[0];
+    float pafRoughnessMax = afWin[0];
+
+    for ( int k = 1; k < 9; k++)
+    {
+        if (afWin[k] > pafRoughnessMax)
+        {
+            pafRoughnessMax=afWin[k];
+        }
+        if (afWin[k] < pafRoughnessMin)
+        {
+            pafRoughnessMin=afWin[k];
+        }
+    }
+    return pafRoughnessMax - pafRoughnessMin;
+}
+
+/************************************************************************/
+/* ==================================================================== */
+/*                       GDALGeneric3x3Dataset                        */
+/* ==================================================================== */
+/************************************************************************/
+
+class GDALGeneric3x3RasterBand;
+
+class GDALGeneric3x3Dataset : public GDALDataset
+{
+    friend class GDALGeneric3x3RasterBand;
+
+    GDALGeneric3x3ProcessingAlg pfnAlg;
+    void*              pAlgData;
+    GDALDatasetH       hSrcDS;
+    GDALRasterBandH    hSrcBand;
+    float*             apafSourceBuf[3];
+    int                bDstHasNoData;
+    double             dfDstNoDataValue;
+    int                nCurLine;
+    int                bComputeAtEdges;
+
+  public:
+                        GDALGeneric3x3Dataset(GDALDatasetH hSrcDS,
+                                              GDALRasterBandH hSrcBand,
+                                              GDALDataType eDstDataType,
+                                              int bDstHasNoData,
+                                              double dfDstNoDataValue,
+                                              GDALGeneric3x3ProcessingAlg pfnAlg,
+                                              void* pAlgData,
+                                              int bComputeAtEdges);
+                       ~GDALGeneric3x3Dataset();
+
+    CPLErr      GetGeoTransform( double * padfGeoTransform );
+    const char *GetProjectionRef();
+};
+
+/************************************************************************/
+/* ==================================================================== */
+/*                    GDALGeneric3x3RasterBand                       */
+/* ==================================================================== */
+/************************************************************************/
+
+class GDALGeneric3x3RasterBand : public GDALRasterBand
+{
+    friend class GDALGeneric3x3Dataset;
+    int bSrcHasNoData;
+    float fSrcNoDataValue;
+    
+    void                    InitWidthNoData(void* pImage);
+    
+  public:
+                 GDALGeneric3x3RasterBand( GDALGeneric3x3Dataset *poDS,
+                                           GDALDataType eDstDataType );
+    
+    virtual CPLErr          IReadBlock( int, int, void * );
+    virtual double          GetNoDataValue( int* pbHasNoData );
+};
+
+GDALGeneric3x3Dataset::GDALGeneric3x3Dataset(
+                                     GDALDatasetH hSrcDS,
+                                     GDALRasterBandH hSrcBand,
+                                     GDALDataType eDstDataType,
+                                     int bDstHasNoData,
+                                     double dfDstNoDataValue,
+                                     GDALGeneric3x3ProcessingAlg pfnAlg,
+                                     void* pAlgData,
+                                     int bComputeAtEdges)
+{
+    this->hSrcDS = hSrcDS;
+    this->hSrcBand = hSrcBand;
+    this->pfnAlg = pfnAlg;
+    this->pAlgData = pAlgData;
+    this->bDstHasNoData = bDstHasNoData;
+    this->dfDstNoDataValue = dfDstNoDataValue;
+    this->bComputeAtEdges = bComputeAtEdges;
+    
+    CPLAssert(eDstDataType == GDT_Byte || eDstDataType == GDT_Float32);
+
+    nRasterXSize = GDALGetRasterXSize(hSrcDS);
+    nRasterYSize = GDALGetRasterYSize(hSrcDS);
+    
+    SetBand(1, new GDALGeneric3x3RasterBand(this, eDstDataType));
+    
+    apafSourceBuf[0] = (float *) CPLMalloc(sizeof(float)*nRasterXSize);
+    apafSourceBuf[1] = (float *) CPLMalloc(sizeof(float)*nRasterXSize);
+    apafSourceBuf[2] = (float *) CPLMalloc(sizeof(float)*nRasterXSize);
+
+    nCurLine = -1;
+}
+
+GDALGeneric3x3Dataset::~GDALGeneric3x3Dataset()
+{
+    CPLFree(apafSourceBuf[0]);
+    CPLFree(apafSourceBuf[1]);
+    CPLFree(apafSourceBuf[2]);
+}
+
+CPLErr GDALGeneric3x3Dataset::GetGeoTransform( double * padfGeoTransform )
+{
+    return GDALGetGeoTransform(hSrcDS, padfGeoTransform);
+}
+
+const char *GDALGeneric3x3Dataset::GetProjectionRef()
+{
+    return GDALGetProjectionRef(hSrcDS);
+}
+
+GDALGeneric3x3RasterBand::GDALGeneric3x3RasterBand(GDALGeneric3x3Dataset *poDS,
+                                                   GDALDataType eDstDataType)
+{
+    this->poDS = poDS;
+    this->nBand = 1;
+    eDataType = eDstDataType;
+    nBlockXSize = poDS->GetRasterXSize();
+    nBlockYSize = 1;
+
+    bSrcHasNoData = FALSE;
+    fSrcNoDataValue = (float)GDALGetRasterNoDataValue(poDS->hSrcBand,
+                                                      &bSrcHasNoData);
+}
+
+void   GDALGeneric3x3RasterBand::InitWidthNoData(void* pImage)
+{
+    int j;
+    GDALGeneric3x3Dataset * poGDS = (GDALGeneric3x3Dataset *) poDS;
+    if (eDataType == GDT_Byte)
+    {
+        for(j=0;j<nBlockXSize;j++)
+            ((GByte*)pImage)[j] = (GByte) poGDS->dfDstNoDataValue;
+    }
+    else
+    {
+        for(j=0;j<nBlockXSize;j++)
+            ((float*)pImage)[j] = (float) poGDS->dfDstNoDataValue;
+    }
+}
+
+CPLErr GDALGeneric3x3RasterBand::IReadBlock( int nBlockXOff,
+                                             int nBlockYOff,
+                                             void *pImage )
+{
+    int i, j;
+    float fVal;
+    GDALGeneric3x3Dataset * poGDS = (GDALGeneric3x3Dataset *) poDS;
+
+    if (poGDS->bComputeAtEdges && nRasterXSize >= 2 && nRasterYSize >= 2)
+    {
+        if (nBlockYOff == 0)
+        {
+            for(i=0;i<2;i++)
+            {
+                CPLErr eErr = GDALRasterIO( poGDS->hSrcBand,
+                                    GF_Read,
+                                    0, i, nBlockXSize, 1,
+                                    poGDS->apafSourceBuf[i+1],
+                                    nBlockXSize, 1,
+                                    GDT_Float32,
+                                    0, 0);
+                if (eErr != CE_None)
+                {
+                    InitWidthNoData(pImage);
+                    return eErr;
+                }
+            }
+            poGDS->nCurLine = 0;
+
+            for (j = 0; j < nRasterXSize; j++)
+            {
+                float afWin[9];
+                int jmin = (j == 0) ? j : j - 1;
+                int jmax = (j == nRasterXSize - 1) ? j : j + 1;
+
+                afWin[0] = INTERPOL(poGDS->apafSourceBuf[1][jmin], poGDS->apafSourceBuf[2][jmin]);
+                afWin[1] = INTERPOL(poGDS->apafSourceBuf[1][j],    poGDS->apafSourceBuf[2][j]);
+                afWin[2] = INTERPOL(poGDS->apafSourceBuf[1][jmax], poGDS->apafSourceBuf[2][jmax]);
+                afWin[3] = poGDS->apafSourceBuf[1][jmin];
+                afWin[4] = poGDS->apafSourceBuf[1][j];
+                afWin[5] = poGDS->apafSourceBuf[1][jmax];
+                afWin[6] = poGDS->apafSourceBuf[2][jmin];
+                afWin[7] = poGDS->apafSourceBuf[2][j];
+                afWin[8] = poGDS->apafSourceBuf[2][jmax];
+
+                fVal = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
+                                    afWin, (float) poGDS->dfDstNoDataValue,
+                                    poGDS->pfnAlg,
+                                    poGDS->pAlgData,
+                                    poGDS->bComputeAtEdges);
+
+                if (eDataType == GDT_Byte)
+                    ((GByte*)pImage)[j] = (GByte) (fVal + 0.5);
+                else
+                    ((float*)pImage)[j] = fVal;
+            }
+
+            return CE_None;
+        }
+        else if (nBlockYOff == nRasterYSize - 1)
+        {
+            if (poGDS->nCurLine != nRasterYSize - 2)
+            {
+                for(i=0;i<2;i++)
+                {
+                    CPLErr eErr = GDALRasterIO( poGDS->hSrcBand,
+                                        GF_Read,
+                                        0, nRasterYSize - 2 + i, nBlockXSize, 1,
+                                        poGDS->apafSourceBuf[i+1],
+                                        nBlockXSize, 1,
+                                        GDT_Float32,
+                                        0, 0);
+                    if (eErr != CE_None)
+                    {
+                        InitWidthNoData(pImage);
+                        return eErr;
+                    }
+                }
+            }
+
+            for (j = 0; j < nRasterXSize; j++)
+            {
+                float afWin[9];
+                int jmin = (j == 0) ? j : j - 1;
+                int jmax = (j == nRasterXSize - 1) ? j : j + 1;
+
+                afWin[0] = poGDS->apafSourceBuf[1][jmin];
+                afWin[1] = poGDS->apafSourceBuf[1][j];
+                afWin[2] = poGDS->apafSourceBuf[1][jmax];
+                afWin[3] = poGDS->apafSourceBuf[2][jmin];
+                afWin[4] = poGDS->apafSourceBuf[2][j];
+                afWin[5] = poGDS->apafSourceBuf[2][jmax];
+                afWin[6] = INTERPOL(poGDS->apafSourceBuf[2][jmin], poGDS->apafSourceBuf[1][jmin]);
+                afWin[7] = INTERPOL(poGDS->apafSourceBuf[2][j],    poGDS->apafSourceBuf[1][j]);
+                afWin[8] = INTERPOL(poGDS->apafSourceBuf[2][jmax], poGDS->apafSourceBuf[1][jmax]);
+
+                fVal = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
+                                    afWin, (float) poGDS->dfDstNoDataValue,
+                                    poGDS->pfnAlg,
+                                    poGDS->pAlgData,
+                                    poGDS->bComputeAtEdges);
+
+                if (eDataType == GDT_Byte)
+                    ((GByte*)pImage)[j] = (GByte) (fVal + 0.5);
+                else
+                    ((float*)pImage)[j] = fVal;
+            }
+
+            return CE_None;
+        }
+    }
+    else if ( nBlockYOff == 0 || nBlockYOff == nRasterYSize - 1)
+    {
+        InitWidthNoData(pImage);
+        return CE_None;
+    }
+
+    if ( poGDS->nCurLine != nBlockYOff )
+    {
+        if (poGDS->nCurLine + 1 == nBlockYOff)
+        {
+            float* pafTmp =  poGDS->apafSourceBuf[0];
+            poGDS->apafSourceBuf[0] = poGDS->apafSourceBuf[1];
+            poGDS->apafSourceBuf[1] = poGDS->apafSourceBuf[2];
+            poGDS->apafSourceBuf[2] = pafTmp;
+
+            CPLErr eErr = GDALRasterIO( poGDS->hSrcBand,
+                                    GF_Read,
+                                    0, nBlockYOff + 1, nBlockXSize, 1,
+                                    poGDS->apafSourceBuf[2],
+                                    nBlockXSize, 1,
+                                    GDT_Float32,
+                                    0, 0);
+
+            if (eErr != CE_None)
+            {
+                InitWidthNoData(pImage);
+                return eErr;
+            }
+        }
+        else
+        {
+            for(i=0;i<3;i++)
+            {
+                CPLErr eErr = GDALRasterIO( poGDS->hSrcBand,
+                                    GF_Read,
+                                    0, nBlockYOff + i - 1, nBlockXSize, 1,
+                                    poGDS->apafSourceBuf[i],
+                                    nBlockXSize, 1,
+                                    GDT_Float32,
+                                    0, 0);
+                if (eErr != CE_None)
+                {
+                    InitWidthNoData(pImage);
+                    return eErr;
+                }
+            }
+        }
+
+        poGDS->nCurLine = nBlockYOff;
+    }
+
+    if (poGDS->bComputeAtEdges && nRasterXSize >= 2)
+    {
+        float afWin[9];
+
+        j = 0;
+        afWin[0] = INTERPOL(poGDS->apafSourceBuf[0][j], poGDS->apafSourceBuf[0][j+1]);
+        afWin[1] = poGDS->apafSourceBuf[0][j];
+        afWin[2] = poGDS->apafSourceBuf[0][j+1];
+        afWin[3] = INTERPOL(poGDS->apafSourceBuf[1][j], poGDS->apafSourceBuf[1][j+1]);
+        afWin[4] = poGDS->apafSourceBuf[1][j];
+        afWin[5] = poGDS->apafSourceBuf[1][j+1];
+        afWin[6] = INTERPOL(poGDS->apafSourceBuf[2][j], poGDS->apafSourceBuf[2][j+1]);
+        afWin[7] = poGDS->apafSourceBuf[2][j];
+        afWin[8] = poGDS->apafSourceBuf[2][j+1];
+
+        fVal = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
+                                    afWin, (float) poGDS->dfDstNoDataValue,
+                                    poGDS->pfnAlg,
+                                    poGDS->pAlgData,
+                                    poGDS->bComputeAtEdges);
+
+        if (eDataType == GDT_Byte)
+            ((GByte*)pImage)[j] = (GByte) (fVal + 0.5);
+        else
+            ((float*)pImage)[j] = fVal;
+
+        j = nRasterXSize - 1;
+
+        afWin[0] = poGDS->apafSourceBuf[0][j-1];
+        afWin[1] = poGDS->apafSourceBuf[0][j];
+        afWin[2] = INTERPOL(poGDS->apafSourceBuf[0][j], poGDS->apafSourceBuf[0][j-1]);
+        afWin[3] = poGDS->apafSourceBuf[1][j-1];
+        afWin[4] = poGDS->apafSourceBuf[1][j];
+        afWin[5] = INTERPOL(poGDS->apafSourceBuf[1][j], poGDS->apafSourceBuf[1][j-1]);
+        afWin[6] = poGDS->apafSourceBuf[2][j-1];
+        afWin[7] = poGDS->apafSourceBuf[2][j];
+        afWin[8] = INTERPOL(poGDS->apafSourceBuf[2][j], poGDS->apafSourceBuf[2][j-1]);
+
+        fVal = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
+                                    afWin, (float) poGDS->dfDstNoDataValue,
+                                    poGDS->pfnAlg,
+                                    poGDS->pAlgData,
+                                    poGDS->bComputeAtEdges);
+
+        if (eDataType == GDT_Byte)
+            ((GByte*)pImage)[j] = (GByte) (fVal + 0.5);
+        else
+            ((float*)pImage)[j] = fVal;
+    }
+    else
+    {
+        if (eDataType == GDT_Byte)
+        {
+            ((GByte*)pImage)[0] = (GByte) poGDS->dfDstNoDataValue;
+            if (nBlockXSize > 1)
+                ((GByte*)pImage)[nBlockXSize - 1] = (GByte) poGDS->dfDstNoDataValue;
+        }
+        else
+        {
+            ((float*)pImage)[0] = (float) poGDS->dfDstNoDataValue;
+            if (nBlockXSize > 1)
+                ((float*)pImage)[nBlockXSize - 1] = (float) poGDS->dfDstNoDataValue;
+        }
+    }
+
+
+    for(j=1;j<nBlockXSize - 1;j++)
+    {
+        float afWin[9];
+        afWin[0] = poGDS->apafSourceBuf[0][j-1];
+        afWin[1] = poGDS->apafSourceBuf[0][j];
+        afWin[2] = poGDS->apafSourceBuf[0][j+1];
+        afWin[3] = poGDS->apafSourceBuf[1][j-1];
+        afWin[4] = poGDS->apafSourceBuf[1][j];
+        afWin[5] = poGDS->apafSourceBuf[1][j+1];
+        afWin[6] = poGDS->apafSourceBuf[2][j-1];
+        afWin[7] = poGDS->apafSourceBuf[2][j];
+        afWin[8] = poGDS->apafSourceBuf[2][j+1];
+
+        fVal = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
+                                afWin, (float) poGDS->dfDstNoDataValue,
+                                poGDS->pfnAlg,
+                                poGDS->pAlgData,
+                                poGDS->bComputeAtEdges);
+
+        if (eDataType == GDT_Byte)
+            ((GByte*)pImage)[j] = (GByte) (fVal + 0.5);
+        else
+            ((float*)pImage)[j] = fVal;
+
+    }
+
+    return CE_None;
+}
+
+double GDALGeneric3x3RasterBand::GetNoDataValue( int* pbHasNoData )
+{
+    GDALGeneric3x3Dataset * poGDS = (GDALGeneric3x3Dataset *) poDS;
+    if (pbHasNoData)
+        *pbHasNoData = poGDS->bDstHasNoData;
+    return poGDS->dfDstNoDataValue;
+}
+
+/************************************************************************/
+/*                                main()                                */
+/************************************************************************/
+
+typedef enum
+{
+    HILL_SHADE,
+    SLOPE,
+    ASPECT,
+    COLOR_RELIEF,
+    TRI,
+    TPI,
+    ROUGHNESS
+} Algorithm;
+
+#define CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(nExtraArg) \
+    do { if (i + nExtraArg >= argc) \
+        Usage(CPLSPrintf("%s option requires %d argument(s)", argv[i], nExtraArg)); } while(0)
+
+#ifndef ZOO_SERVICE
+int main( int argc, char ** argv )
+#else
+#ifdef WIN32
+__declspec(dllexport)
+#endif
+  int Gdal_Dem(maps*& conf,maps*& inputs,maps*& outputs)
+#endif
+{
+    Algorithm eUtilityMode = HILL_SHADE;
+    double z = 1.0;
+    double scale = 1.0;
+    double az = 315.0;
+    double alt = 45.0;
+    // 0 = 'percent' or 1 = 'degrees'
+    int slopeFormat = 1; 
+    int bAddAlpha = FALSE;
+    int bZeroForFlat = FALSE;
+    int bAngleAsAzimuth = TRUE;
+    ColorSelectionMode eColorSelectionMode = COLOR_SELECTION_INTERPOLATE;
+    
+    int nBand = 1;
+    double  adfGeoTransform[6];
+
+    const char *pszSrcFilename = NULL;
+    const char *pszDstFilename = NULL;
+    const char *pszColorFilename = NULL;
+    const char *pszFormat = "GTiff";
+    int bFormatExplicitelySet = FALSE;
+    char **papszCreateOptions = NULL;
+    
+    GDALDatasetH hSrcDataset = NULL;
+    GDALDatasetH hDstDataset = NULL;
+    GDALRasterBandH hSrcBand = NULL;
+    GDALRasterBandH hDstBand = NULL;
+    GDALDriverH hDriver = NULL;
+
+    GDALProgressFunc pfnProgress = GDALTermProgress;
+    
+    int nXSize = 0;
+    int nYSize = 0;
+    
+    int bComputeAtEdges = FALSE;
+    int bZevenbergenThorne = FALSE;
+    int bCombined = FALSE;
+    int bQuiet = FALSE;
+    
+#ifndef ZOO_SERVICE
+    /* Check strict compilation and runtime library version as we use C++ API */
+    if (! GDAL_CHECK_VERSION(argv[0]))
+        exit(1);
+
+    argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
+    if( argc < 2 )
+    {
+        Usage("Not enough arguments.");
+    }
+
+    if( EQUAL(argv[1], "--utility_version") || EQUAL(argv[1], "--utility-version") )
+    {
+        printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
+                argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
+        return 0;
+    }
+    else if( EQUAL(argv[1],"--help") )
+        Usage();
+    else if ( EQUAL(argv[1], "shade") || EQUAL(argv[1], "hillshade") )
+    {
+        eUtilityMode = HILL_SHADE;
+    }
+    else if ( EQUAL(argv[1], "slope") )
+    {
+        eUtilityMode = SLOPE;
+    }
+    else if ( EQUAL(argv[1], "aspect") )
+    {
+        eUtilityMode = ASPECT;
+    }
+    else if ( EQUAL(argv[1], "color-relief") )
+    {
+        eUtilityMode = COLOR_RELIEF;
+    }
+    else if ( EQUAL(argv[1], "TRI") )
+    {
+        eUtilityMode = TRI;
+    }
+    else if ( EQUAL(argv[1], "TPI") )
+    {
+        eUtilityMode = TPI;
+    }
+    else if ( EQUAL(argv[1], "roughness") )
+    {
+        eUtilityMode = ROUGHNESS;
+    }
+    else
+    {
+        Usage("Missing valid sub-utility mention.");
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Parse arguments.                                                */
+/* -------------------------------------------------------------------- */
+    for(int i = 2; i < argc; i++ )
+    {
+        if( eUtilityMode == HILL_SHADE &&
+            (EQUAL(argv[i], "--z") || EQUAL(argv[i], "-z")))
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            z = atof(argv[++i]);
+        }
+        else if ( eUtilityMode == SLOPE && EQUAL(argv[i], "-p"))
+        {
+            slopeFormat = 0;
+        }
+        else if ( (eUtilityMode == HILL_SHADE || eUtilityMode == SLOPE ||
+                   eUtilityMode == ASPECT) && EQUAL(argv[i], "-alg") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            i ++;
+            if (EQUAL(argv[i], "ZevenbergenThorne"))
+                bZevenbergenThorne = TRUE;
+            else if (!EQUAL(argv[i], "Horn"))
+            {
+                Usage(CPLSPrintf("Wrong value for alg : %s.", argv[i]));
+            }
+        }
+        else if ( eUtilityMode == ASPECT && EQUAL(argv[i], "-trigonometric"))
+        {
+            bAngleAsAzimuth = FALSE;
+        }
+        else if ( eUtilityMode == ASPECT && EQUAL(argv[i], "-zero_for_flat"))
+        {
+            bZeroForFlat = TRUE;
+        }
+        else if ( eUtilityMode == COLOR_RELIEF && EQUAL(argv[i], "-exact_color_entry"))
+        {
+            eColorSelectionMode = COLOR_SELECTION_EXACT_ENTRY;
+        }
+        else if ( eUtilityMode == COLOR_RELIEF && EQUAL(argv[i], "-nearest_color_entry"))
+        {
+            eColorSelectionMode = COLOR_SELECTION_NEAREST_ENTRY;
+        }
+        else if( 
+            (EQUAL(argv[i], "--s") || 
+             EQUAL(argv[i], "-s") ||
+             EQUAL(argv[i], "--scale") ||
+             EQUAL(argv[i], "-scale"))
+          )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            scale = atof(argv[++i]);
+        }
+        else if( eUtilityMode == HILL_SHADE &&
+            (EQUAL(argv[i], "--az") || 
+             EQUAL(argv[i], "-az") ||
+             EQUAL(argv[i], "--azimuth") ||
+             EQUAL(argv[i], "-azimuth"))
+          )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            az = atof(argv[++i]);
+        }
+        else if( eUtilityMode == HILL_SHADE &&
+            (EQUAL(argv[i], "--alt") || 
+             EQUAL(argv[i], "-alt") ||
+             EQUAL(argv[i], "--alt") ||
+             EQUAL(argv[i], "-alt"))
+          )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            alt = atof(argv[++i]);
+        }
+        else if( eUtilityMode == HILL_SHADE &&
+            (EQUAL(argv[i], "-combined") || 
+             EQUAL(argv[i], "--combined"))
+          )
+        {
+            bCombined = TRUE;
+        }
+        else if( eUtilityMode == COLOR_RELIEF &&
+                 EQUAL(argv[i], "-alpha"))
+        {
+            bAddAlpha = TRUE;
+        }
+        else if( eUtilityMode != COLOR_RELIEF &&
+                 EQUAL(argv[i], "-compute_edges"))
+        {
+            bComputeAtEdges = TRUE;
+        }
+        else if( i + 1 < argc &&
+            (EQUAL(argv[i], "--b") || 
+             EQUAL(argv[i], "-b"))
+          )
+        {
+            nBand = atoi(argv[++i]);
+        }
+        else if ( EQUAL(argv[i], "-q") || EQUAL(argv[i], "-quiet") )
+        {
+            pfnProgress = GDALDummyProgress;
+            bQuiet = TRUE;
+        }
+        else if( EQUAL(argv[i],"-co") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            papszCreateOptions = CSLAddString( papszCreateOptions, argv[++i] );
+        }
+        else if( EQUAL(argv[i],"-of") )
+        {
+            CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
+            pszFormat = argv[++i];
+            bFormatExplicitelySet = TRUE;
+        }
+        else if( argv[i][0] == '-' )
+        {
+            Usage(CPLSPrintf("Unkown option name '%s'", argv[i]));
+        }
+        else if( pszSrcFilename == NULL )
+        {
+            pszSrcFilename = argv[i];
+        }
+        else if( eUtilityMode == COLOR_RELIEF && pszColorFilename == NULL )
+        {
+            pszColorFilename = argv[i];
+        }
+        else if( pszDstFilename == NULL )
+        {
+            pszDstFilename = argv[i];
+        }
+        else
+            Usage("Too many command options.");
+    }
+
+    if( pszSrcFilename == NULL )
+    {
+        Usage("Missing source.");
+    }
+    if ( eUtilityMode == COLOR_RELIEF && pszColorFilename == NULL )
+    {
+        Usage("Missing color file.");
+    }
+    if( pszDstFilename == NULL )
+    {
+        Usage("Missing destination.");
+    }
+#else
+    map* tmpMap=NULL;
+
+    pfnProgress = GDALDummyProgress;
+    bQuiet = TRUE;
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"InputDSN","value");
+    if(tmpMap!=NULL){
+      pszSrcFilename=(char*)CPLMalloc(sizeof(char)*(strlen(tmpMap->value)+1));
+      sprintf((char*)pszSrcFilename,"%s",tmpMap->value);
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"OutputDSN","value");
+    if(tmpMap!=NULL){
+      pszDstFilename=(char*)CPLMalloc(sizeof(char)*(strlen(tmpMap->value)+1));
+      sprintf((char*)pszDstFilename,"%s",tmpMap->value);
+      setMapInMaps(outputs,"Result","value",tmpMap->value);
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"utility","value");
+    if(tmpMap!=NULL){
+      if ( EQUAL(tmpMap->value, "shade") || EQUAL(tmpMap->value, "hillshade") )
+	{
+	  eUtilityMode = HILL_SHADE;
+	  map* tmpMap1=getMapFromMaps(inputs,"z","value");
+	  if(tmpMap1==NULL)
+	    return Usage(conf,"Unable to parse your z value");
+	  z = atof(tmpMap1->value);
+
+	  tmpMap1=getMapFromMaps(inputs,"az","value");
+	  if(tmpMap1!=NULL && strcasecmp(tmpMap1->value,"NULL")!=0 )
+	    az = atof(tmpMap1->value);
+
+	  tmpMap1=getMapFromMaps(inputs,"alt","value");
+	  if(tmpMap1!=NULL && strcasecmp(tmpMap1->value,"NULL")!=0 )
+	    alt = atof(tmpMap1->value);
+
+	  tmpMap1=getMapFromMaps(inputs,"c","value");
+	  if(tmpMap1!=NULL && strcasecmp(tmpMap1->value,"true")==0 )	  
+	    bCombined = TRUE;
+	}
+      else if ( EQUAL(tmpMap->value, "slope") )
+	{
+	  eUtilityMode = SLOPE;
+	  map* tmpMap1=getMapFromMaps(inputs,"p","value");
+	  if(tmpMap1!=NULL && strcasecmp(tmpMap1->value,"true")==0)
+	    slopeFormat = 0;
+	}
+      else if ( EQUAL(tmpMap->value, "aspect") )
+	{
+	  eUtilityMode = ASPECT;
+	  map* tmpMap1=getMapFromMaps(inputs,"ece","value");
+	  if(tmpMap1!=NULL && strcasecmp(tmpMap1->value,"true")==0)
+            eColorSelectionMode = COLOR_SELECTION_EXACT_ENTRY;
+	  tmpMap1=getMapFromMaps(inputs,"nce","value");
+	  if(tmpMap1!=NULL && strcasecmp(tmpMap1->value,"true")==0)
+            eColorSelectionMode = COLOR_SELECTION_NEAREST_ENTRY;
+	}
+      else if ( EQUAL(tmpMap->value, "color-relief") )
+	{
+	  eUtilityMode = COLOR_RELIEF;
+	  map* tmpMap1=getMapFromMaps(inputs,"cfn","value");
+	  if(tmpMap!=NULL){
+	    pszColorFilename=strdup(tmpMap1->value);
+	  } 
+	  tmpMap1=getMapFromMaps(inputs,"a","value");
+	  if(tmpMap1!=NULL && strcasecmp(tmpMap1->value,"true")==0)	  
+	    bAddAlpha = TRUE;
+	  tmpMap1=getMapFromMaps(inputs,"ce","value");
+	  if(tmpMap1!=NULL && strcasecmp(tmpMap1->value,"true")==0)	  
+	    bComputeAtEdges = TRUE;
+	}
+      else if ( EQUAL(tmpMap->value, "TRI") )
+	{
+	  eUtilityMode = TRI;
+	}
+      else if ( EQUAL(tmpMap->value, "TPI") )
+	{
+	  eUtilityMode = TPI;
+	}
+      else if ( EQUAL(tmpMap->value, "roughness") )
+	{
+	  eUtilityMode = ROUGHNESS;
+	}
+      else
+	{
+	  return Usage(conf,"Missing valid utility mention.");
+	}
+    }
+    map* tmpMap1=getMapFromMaps(inputs,"s","value");
+    if(tmpMap1!=NULL && strcasecmp(tmpMap1->value,"NULL")!=0 )
+      scale = atof(tmpMap1->value);
+    tmpMap1=getMapFromMaps(inputs,"b","value");
+    if(tmpMap1!=NULL && strcasecmp(tmpMap1->value,"NULL")!=0 )
+      nBand = atoi(tmpMap1->value);
+
+    if( pszSrcFilename == NULL )
+    {
+      return Usage(conf,"Missing source.");
+    }
+    if ( eUtilityMode == COLOR_RELIEF && pszColorFilename == NULL )
+    {
+      return Usage(conf,"Missing color file.");
+    }
+    if( pszDstFilename == NULL )
+    {
+      return Usage(conf,"Missing destination.");
+    }
+#endif
+
+    GDALAllRegister();
+
+    // Open Dataset and get raster band
+    hSrcDataset = GDALOpen( pszSrcFilename, GA_ReadOnly );
+    
+    if( hSrcDataset == NULL )
+    {
+        fprintf( stderr,
+                 "GDALOpen failed - %d\n%s\n",
+                 CPLGetLastErrorNo(), CPLGetLastErrorMsg() );
+        GDALDestroyDriverManager();
+#ifdef ZOO_SERVICE
+	char *tmp=(char*)malloc(1024*sizeof(char));
+	sprintf(tmp,"GDALOpen failed - %d\n%s\n",
+                 CPLGetLastErrorNo(), CPLGetLastErrorMsg());
+	return Usage(conf,"GDALOpen failed");
+#else
+        exit( 1 );
+#endif
+    }
+
+    nXSize = GDALGetRasterXSize(hSrcDataset);
+    nYSize = GDALGetRasterYSize(hSrcDataset);
+
+    if( nBand <= 0 || nBand > GDALGetRasterCount(hSrcDataset) )
+    {
+        fprintf( stderr,
+                 "Unable to fetch band #%d\n", nBand );
+        GDALDestroyDriverManager();
+#ifdef ZOO_SERVICE
+	char *tmp=(char*)malloc(128*sizeof(char));
+	sprintf(tmp,"Unable to fetch band #%d\n", nBand );
+	return Usage(conf,tmp);
+#else
+        exit( 1 );
+#endif
+    }
+    hSrcBand = GDALGetRasterBand( hSrcDataset, nBand );
+
+    GDALGetGeoTransform(hSrcDataset, adfGeoTransform);
+
+    hDriver = GDALGetDriverByName(pszFormat);
+    if( hDriver == NULL 
+        || (GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) == NULL &&
+            GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY, NULL ) == NULL))
+    {
+        int	iDr;
+
+        fprintf( stderr, "Output driver `%s' not recognised to have\n", 
+                 pszFormat );
+        fprintf( stderr, "output support.  The following format drivers are configured\n"
+                "and support output:\n" );
+
+        for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
+        {
+            GDALDriverH hDriver = GDALGetDriver(iDr);
+
+            if( GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) != NULL ||
+                GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY, NULL ) != NULL )
+            {
+                printf( "  %s: %s\n",
+                        GDALGetDriverShortName( hDriver  ),
+                        GDALGetDriverLongName( hDriver ) );
+            }
+        }
+        GDALDestroyDriverManager();
+#ifdef ZOO_SERVICE
+	return Usage(conf,"Output driver not recognised to have output support.");
+#else
+        exit( 1 );
+#endif
+    }
+
+#ifndef ZOO_SERVICE
+    if (!bQuiet && !bFormatExplicitelySet)
+        CheckExtensionConsistency(pszDstFilename, pszFormat);
+#endif
+
+    double dfDstNoDataValue = 0;
+    int bDstHasNoData = FALSE;
+    void* pData = NULL;
+    GDALGeneric3x3ProcessingAlg pfnAlg = NULL;
+
+    if (eUtilityMode == HILL_SHADE)
+    {
+        dfDstNoDataValue = 0;
+        bDstHasNoData = TRUE;
+        pData = GDALCreateHillshadeData   (adfGeoTransform,
+                                           z,
+                                           scale,
+                                           alt,
+                                           az,
+                                           bZevenbergenThorne);
+        if (bZevenbergenThorne)
+        {
+            if(!bCombined)
+                pfnAlg = GDALHillshadeZevenbergenThorneAlg;
+            else
+                pfnAlg = GDALHillshadeZevenbergenThorneCombinedAlg;
+        }
+        else
+        {
+            if(!bCombined)
+                pfnAlg = GDALHillshadeAlg;
+            else
+                pfnAlg = GDALHillshadeCombinedAlg;
+        }
+    }
+    else if (eUtilityMode == SLOPE)
+    {
+        dfDstNoDataValue = -9999;
+        bDstHasNoData = TRUE;
+
+        pData = GDALCreateSlopeData(adfGeoTransform, scale, slopeFormat);
+        if (bZevenbergenThorne)
+            pfnAlg = GDALSlopeZevenbergenThorneAlg;
+        else
+            pfnAlg = GDALSlopeHornAlg;
+    }
+
+    else if (eUtilityMode == ASPECT)
+    {
+        if (!bZeroForFlat)
+        {
+            dfDstNoDataValue = -9999;
+            bDstHasNoData = TRUE;
+        }
+
+        pData = GDALCreateAspectData(bAngleAsAzimuth);
+        if (bZevenbergenThorne)
+            pfnAlg = GDALAspectZevenbergenThorneAlg;
+        else
+            pfnAlg = GDALAspectAlg;
+    }
+    else if (eUtilityMode == TRI)
+    {
+        dfDstNoDataValue = -9999;
+        bDstHasNoData = TRUE;
+        pfnAlg = GDALTRIAlg;
+    }
+    else if (eUtilityMode == TPI)
+    {
+        dfDstNoDataValue = -9999;
+        bDstHasNoData = TRUE;
+        pfnAlg = GDALTPIAlg;
+    }
+    else if (eUtilityMode == ROUGHNESS)
+    {
+        dfDstNoDataValue = -9999;
+        bDstHasNoData = TRUE;
+        pfnAlg = GDALRoughnessAlg;
+    }
+    
+    GDALDataType eDstDataType = (eUtilityMode == HILL_SHADE ||
+                                 eUtilityMode == COLOR_RELIEF) ? GDT_Byte :
+                                                               GDT_Float32;
+
+    if( EQUAL(pszFormat, "VRT") )
+    {
+        if (eUtilityMode == COLOR_RELIEF)
+        {
+            GDALGenerateVRTColorRelief(pszDstFilename,
+                                       hSrcDataset,
+                                       hSrcBand,
+                                       pszColorFilename,
+                                       eColorSelectionMode,
+                                       bAddAlpha);
+            GDALClose(hSrcDataset);
+        
+            CPLFree(pData);
+
+            GDALDestroyDriverManager();
+#ifndef ZOO_SERVICE
+            CSLDestroy( argv );
+#endif
+            CSLDestroy( papszCreateOptions );    
+#ifdef ZOO_SERVICE
+	    return SERVICE_SUCCEEDED;
+#else
+            return 0;
+#endif
+        }
+        else
+        {
+            fprintf(stderr, "VRT driver can only be used with color-relief utility\n");
+            GDALDestroyDriverManager();
+#ifdef ZOO_SERVICE
+	    return Usage(conf,"VRT driver can only be used with color-relief utility");
+#else
+            exit(1);
+#endif
+        }
+    }
+    
+    if( GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) == NULL &&
+        GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY, NULL ) != NULL)
+    {
+        GDALDatasetH hIntermediateDataset;
+        
+        if (eUtilityMode == COLOR_RELIEF)
+            hIntermediateDataset = (GDALDatasetH)
+                new GDALColorReliefDataset (hSrcDataset,
+                                            hSrcBand,
+                                            pszColorFilename,
+                                            eColorSelectionMode,
+                                            bAddAlpha);
+        else
+            hIntermediateDataset = (GDALDatasetH)
+                new GDALGeneric3x3Dataset(hSrcDataset, hSrcBand,
+                                          eDstDataType,
+                                          bDstHasNoData,
+                                          dfDstNoDataValue,
+                                          pfnAlg,
+                                          pData,
+                                          bComputeAtEdges);
+
+        GDALDatasetH hOutDS = GDALCreateCopy(
+                                 hDriver, pszDstFilename, hIntermediateDataset, 
+                                 TRUE, papszCreateOptions, 
+                                 pfnProgress, NULL );
+
+        if( hOutDS != NULL )
+            GDALClose( hOutDS );
+        GDALClose(hIntermediateDataset);
+        GDALClose(hSrcDataset);
+        
+        CPLFree(pData);
+
+        GDALDestroyDriverManager();
+#ifndef ZOO_SERVICE
+        CSLDestroy( argv );
+#endif
+        CSLDestroy( papszCreateOptions );
+        
+#ifdef ZOO_SERVICE
+	return SERVICE_SUCCEEDED;
+#else
+        return 0;
+#endif
+    }
+
+    int nDstBands;
+    if (eUtilityMode == COLOR_RELIEF)
+        nDstBands = (bAddAlpha) ? 4 : 3;
+    else
+        nDstBands = 1;
+
+    hDstDataset = GDALCreate(   hDriver,
+                                pszDstFilename,
+                                nXSize,
+                                nYSize,
+                                nDstBands,
+                                eDstDataType,
+                                papszCreateOptions);
+
+    if( hDstDataset == NULL )
+    {
+        fprintf( stderr,
+                 "Unable to create dataset %s %d\n%s\n", pszDstFilename,
+                 CPLGetLastErrorNo(), CPLGetLastErrorMsg() );
+        GDALDestroyDriverManager();
+#ifdef ZOO_SERVICE
+	char *tmp=(char*)malloc(1024*sizeof(char));
+        sprintf( tmp,
+                 "Unable to create dataset %s %d\n%s\n", pszDstFilename,
+                 CPLGetLastErrorNo(), CPLGetLastErrorMsg() );
+	return Usage(conf,tmp);
+#else
+        exit( 1 );
+#endif
+    }
+    
+    hDstBand = GDALGetRasterBand( hDstDataset, 1 );
+
+    GDALSetGeoTransform(hDstDataset, adfGeoTransform);
+    GDALSetProjection(hDstDataset, GDALGetProjectionRef(hSrcDataset));
+    
+    if (eUtilityMode == COLOR_RELIEF)
+    {
+        GDALColorRelief (hSrcBand, 
+                         GDALGetRasterBand(hDstDataset, 1),
+                         GDALGetRasterBand(hDstDataset, 2),
+                         GDALGetRasterBand(hDstDataset, 3),
+                         (bAddAlpha) ? GDALGetRasterBand(hDstDataset, 4) : NULL,
+                         pszColorFilename,
+                         eColorSelectionMode,
+                         pfnProgress, NULL);
+    }
+    else
+    {
+        if (bDstHasNoData)
+            GDALSetRasterNoDataValue(hDstBand, dfDstNoDataValue);
+        
+        GDALGeneric3x3Processing(hSrcBand, hDstBand,
+                                 pfnAlg, pData,
+                                 bComputeAtEdges,
+                                 pfnProgress, NULL);
+                                    
+    }
+
+    GDALClose(hSrcDataset);
+    GDALClose(hDstDataset);
+    CPLFree(pData);
+
+    GDALDestroyDriverManager();
+#ifdef ZOO_SERVICE
+    CSLDestroy( papszCreateOptions );
+    return SERVICE_SUCCEEDED;
+#else
+    CSLDestroy( argv );
+    CSLDestroy( papszCreateOptions );
+    return 0;
+#endif
+
+}
+
+#ifdef ZOO_SERVICE
+}
+#endif
diff --git a/zoo-project/zoo-services/gdal/grid/Makefile b/zoo-project/zoo-services/gdal/grid/Makefile
new file mode 100644
index 0000000..60a5151
--- /dev/null
+++ b/zoo-project/zoo-services/gdal/grid/Makefile
@@ -0,0 +1,15 @@
+ZRPATH=../../..
+include ${ZRPATH}/zoo-kernel/ZOOMakefile.opts
+CFLAGS=${ZOO_CFLAGS} ${XML2CFLAGS} ${GDAL_CFLAGS} ${PYTHONCFLAGS} -DLINUX_FREE_ISSUE #-DDEBUG
+CC=gcc
+
+cgi-env/service.zo: service.c
+	g++  -DZOO_SERVICE ${CFLAGS} -shared -fpic -o cgi-env/gdal_grid_service.zo ./service.c ${GDAL_LIBS} ${MACOS_LD_FLAGS} -lzoo_service
+
+install:
+	install -d ${CGI_DIR}/gdal/grid
+	install cgi-env/* ${CGI_DIR}/gdal/grid
+
+
+clean:
+	rm -f cgi-env/*.zo
diff --git a/zoo-project/zoo-services/gdal/grid/cgi-env/Gdal_Grid.zcfg b/zoo-project/zoo-services/gdal/grid/cgi-env/Gdal_Grid.zcfg
new file mode 100644
index 0000000..d421a94
--- /dev/null
+++ b/zoo-project/zoo-services/gdal/grid/cgi-env/Gdal_Grid.zcfg
@@ -0,0 +1,69 @@
+[Gdal_Grid]
+ Title =  Computes a regular grid (raster) from scattered data read from a vector data source. 
+ Abstract = http://www.gdal.org/gdal_grid.html
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceType = C
+ serviceProvider = gdal_grid_service.zo
+ <MetaData>
+   title = My Demo
+ </MetaData>
+ <DataInputs>
+  [OF]
+   Title = Format of the output data
+   Abstract = Select the output format.
+   minOccurs = 0
+   maxOccurs = 1
+   <LiteralData>
+    DataType = string
+    <Default>
+     value = AAIGrid
+    </Default>
+    <Supported>
+     value = AAIGrid
+    </Supported>
+   </LiteralData>
+  [InputDSN]
+   Title = The input data source name
+   Abstract = The input data source name to use as source for convertion.
+   minOccurs = 1
+   maxOccurs = 1
+   <LiteralData>
+    DataType = string
+    <Default>
+     uom = feet
+    </Default>	
+    <Supported>
+     value = AAIGrid
+    </Supported>
+   </LiteralData>
+  [OutputDSN]
+   Title = The output data source name
+   Abstract = The output data source name to use as source for convertion.
+   minOccurs = 1
+   maxOccurs = 1
+   <LiteralData>
+    DataType = string
+    <Default>
+     uom = feet
+    </Default>	
+    <Supported>
+     value = AAIGrid
+    </Supported>
+   </LiteralData>
+ </DataInputs>
+ <DataOutputs>
+  [OutputedDataSourceName]
+   Title = The resulting converted file
+   Abstract = The file name resulting of the convertion
+   <LiteralData>
+    DataType = string
+    <Default>
+     uom = feet
+    </Default>	
+    <Supported>
+     value = AAIGrid
+    </Supported>
+   </LiteralData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/gdal/grid/service.c b/zoo-project/zoo-services/gdal/grid/service.c
new file mode 100644
index 0000000..658045b
--- /dev/null
+++ b/zoo-project/zoo-services/gdal/grid/service.c
@@ -0,0 +1,1258 @@
+/* ****************************************************************************
+ * $Id: gdal_grid.cpp 15053 2008-07-27 17:29:27Z rouault $
+ *
+ * Project:  GDAL Utilities
+ * Purpose:  GDAL scattered data gridding (interpolation) tool
+ * Author:   Andrey Kiselev, dron at ak4719.spb.edu
+ *
+ * ****************************************************************************
+ * Copyright (c) 2007, Andrey Kiselev <dron at ak4719.spb.edu>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include <vector>
+#include <algorithm>
+
+#include "cpl_string.h"
+#include "gdal.h"
+#include "gdal_alg.h"
+#include "ogr_spatialref.h"
+#include "ogr_api.h"
+
+#ifdef ZOO_SERVICE
+#include "service.h"
+#endif
+
+CPL_CVSID("$Id: gdal_grid.cpp 15053 2008-07-27 17:29:27Z rouault $");
+
+#ifdef ZOO_SERVICE
+extern "C" {
+#endif
+
+static const char szAlgNameInvDist[] = "invdist";
+static const char szAlgNameAverage[] = "average";
+static const char szAlgNameNearest[] = "nearest";
+static const char szAlgNameMinimum[] = "minimum";
+static const char szAlgNameMaximum[] = "maximum";
+static const char szAlgNameRange[] = "range";
+
+/************************************************************************/
+/*                               Usage()                                */
+/************************************************************************/
+
+static void Usage()
+{
+#ifdef ZOO_SERVICE
+  fprintf(stderr,
+#else
+    printf( 
+#endif
+        "Usage: gdal_grid [--help-general] [--formats]\n"
+        "    [-ot {Byte/Int16/UInt16/UInt32/Int32/Float32/Float64/\n"
+        "          CInt16/CInt32/CFloat32/CFloat64}]\n"
+        "    [-of format] [-co \"NAME=VALUE\"]\n"
+        "    [-zfield field_name]\n"
+        "    [-a_srs srs_def] [-spat xmin ymin xmax ymax]\n"
+        "    [-l layername]* [-where expression] [-sql select_statement]\n"
+        "    [-txe xmin xmax] [-tye ymin ymax] [-outsize xsize ysize]\n"
+        "    [-a algorithm[:parameter1=value1]*]"
+        "    [-quiet]\n"
+        "    <src_datasource> <dst_filename>\n"
+        "\n"
+        "Available algorithms and parameters with their defaults:\n"
+        "    Inverse distance to a power (default)\n"
+        "        invdist:power=2.0:smoothing=0.0:radius1=0.0:radius2=0.0:angle=0.0:max_points=0:min_points=0:nodata=0.0\n"
+        "    Moving average\n"
+        "        average:radius1=0.0:radius2=0.0:angle=0.0:min_points=0:nodata=0.0\n"
+        "    Nearest neighbor\n"
+        "        nearest:radius1=0.0:radius2=0.0:angle=0.0:nodata=0.0\n"
+        "    Various data metrics\n"
+        "        <metric name>:radius1=0.0:radius2=0.0:angle=0.0:min_points=0:nodata=0.0\n"
+        "        possible metrics are:\n"
+        "            minimum\n"
+        "            maximum\n"
+        "            range\n"
+        "\n");
+#ifndef ZOO_SERVICE
+    exit( 1 );
+#endif
+}
+
+/************************************************************************/
+/*                          GetAlgorithmName()                          */
+/*                                                                      */
+/*      Translates algortihm code into mnemonic name.                   */
+/************************************************************************/
+
+void PrintAlgorithmAndOptions(GDALGridAlgorithm eAlgorithm, void *pOptions)
+{
+    switch ( eAlgorithm )
+    {
+        case GGA_InverseDistanceToAPower:
+
+#ifdef ZOO_SERVICE
+	  fprintf(stderr,
+#else
+            printf( 
+#endif
+		   "Algorithm name: \"%s\".\n", szAlgNameInvDist );
+#ifdef ZOO_SERVICE
+		fprintf(stderr,
+#else
+			  printf( 
+#endif
+				 "Options are "
+				 "\"power=%f:smoothing=%f:radius1=%f:radius2=%f:angle=%f"
+                    ":max_points=%lu:min_points=%lu:nodata=%f\"\n",
+                ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfPower,
+                ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfSmoothing,
+                ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfRadius1,
+                ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfRadius2,
+                ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfAngle,
+                (unsigned long)((GDALGridInverseDistanceToAPowerOptions *)pOptions)->nMaxPoints,
+                (unsigned long)((GDALGridInverseDistanceToAPowerOptions *)pOptions)->nMinPoints,
+                ((GDALGridInverseDistanceToAPowerOptions *)pOptions)->dfNoDataValue);
+            break;
+        case GGA_MovingAverage:
+            #ifdef ZOO_SERVICE
+	  fprintf(stderr,
+#else
+            printf( 
+#endif
+ "Algorithm name: \"%s\".\n", szAlgNameAverage );
+            #ifdef ZOO_SERVICE
+	  fprintf(stderr,
+#else
+            printf( 
+#endif
+ "Options are "
+                    "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
+                    ":nodata=%f\"\n",
+                ((GDALGridMovingAverageOptions *)pOptions)->dfRadius1,
+                ((GDALGridMovingAverageOptions *)pOptions)->dfRadius2,
+                ((GDALGridMovingAverageOptions *)pOptions)->dfAngle,
+                (unsigned long)((GDALGridMovingAverageOptions *)pOptions)->nMinPoints,
+                ((GDALGridMovingAverageOptions *)pOptions)->dfNoDataValue);
+            break;
+        case GGA_NearestNeighbor:
+            #ifdef ZOO_SERVICE
+	  fprintf(stderr,
+#else
+            printf( 
+#endif
+ "Algorithm name: \"%s\".\n", szAlgNameNearest );
+            #ifdef ZOO_SERVICE
+	  fprintf(stderr,
+#else
+            printf( 
+#endif
+ "Options are "
+                    "\"radius1=%f:radius2=%f:angle=%f:nodata=%f\"\n",
+                ((GDALGridNearestNeighborOptions *)pOptions)->dfRadius1,
+                ((GDALGridNearestNeighborOptions *)pOptions)->dfRadius2,
+                ((GDALGridNearestNeighborOptions *)pOptions)->dfAngle,
+                ((GDALGridNearestNeighborOptions *)pOptions)->dfNoDataValue);
+            break;
+        case GGA_MetricMinimum:
+            #ifdef ZOO_SERVICE
+	  fprintf(stderr,
+#else
+            printf( 
+#endif
+ "Algorithm name: \"%s\".\n", szAlgNameMinimum );
+            #ifdef ZOO_SERVICE
+	  fprintf(stderr,
+#else
+            printf( 
+#endif
+ "Options are "
+                    "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
+                    ":nodata=%f\"\n",
+                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius1,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius2,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfAngle,
+                (unsigned long)((GDALGridDataMetricsOptions *)pOptions)->nMinPoints,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfNoDataValue);
+            break;
+        case GGA_MetricMaximum:
+            #ifdef ZOO_SERVICE
+	  fprintf(stderr,
+#else
+            printf( 
+#endif
+ "Algorithm name: \"%s\".\n", szAlgNameMaximum );
+            #ifdef ZOO_SERVICE
+	  fprintf(stderr,
+#else
+            printf( 
+#endif
+ "Options are "
+                    "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
+                    ":nodata=%f\"\n",
+                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius1,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius2,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfAngle,
+                (unsigned long)((GDALGridDataMetricsOptions *)pOptions)->nMinPoints,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfNoDataValue);
+            break;
+        case GGA_MetricRange:
+            #ifdef ZOO_SERVICE
+	  fprintf(stderr,
+#else
+            printf( 
+#endif
+ "Algorithm name: \"%s\".\n", szAlgNameRange );
+            #ifdef ZOO_SERVICE
+	  fprintf(stderr,
+#else
+            printf( 
+#endif
+ "Options are "
+                    "\"radius1=%f:radius2=%f:angle=%f:min_points=%lu"
+                    ":nodata=%f\"\n",
+                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius1,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfRadius2,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfAngle,
+                (unsigned long)((GDALGridDataMetricsOptions *)pOptions)->nMinPoints,
+                ((GDALGridDataMetricsOptions *)pOptions)->dfNoDataValue);
+            break;
+        default:
+            #ifdef ZOO_SERVICE
+	  fprintf(stderr,
+#else
+            printf( 
+#endif
+ "Algorithm unknown.\n" );
+            break;
+    }
+}
+
+/************************************************************************/
+/*                      ParseAlgorithmAndOptions()                      */
+/*                                                                      */
+/*      Translates mnemonic gridding algorithm names into               */
+/*      GDALGridAlgorithm code, parse control parameters and assign     */
+/*      defaults.                                                       */
+/************************************************************************/
+
+static CPLErr ParseAlgorithmAndOptions( const char *pszAlgoritm,
+                                        GDALGridAlgorithm *peAlgorithm,
+                                        void **ppOptions )
+{
+    char **papszParms = CSLTokenizeString2( pszAlgoritm, ":", FALSE );
+
+    if ( CSLCount(papszParms) < 1 )
+        return CE_Failure;
+
+    if ( EQUAL(papszParms[0], szAlgNameInvDist) )
+        *peAlgorithm = GGA_InverseDistanceToAPower;
+    else if ( EQUAL(papszParms[0], szAlgNameAverage) )
+        *peAlgorithm = GGA_MovingAverage;
+    else if ( EQUAL(papszParms[0], szAlgNameNearest) )
+        *peAlgorithm = GGA_NearestNeighbor;
+    else if ( EQUAL(papszParms[0], szAlgNameMinimum) )
+        *peAlgorithm = GGA_MetricMinimum;
+    else if ( EQUAL(papszParms[0], szAlgNameMaximum) )
+        *peAlgorithm = GGA_MetricMaximum;
+    else if ( EQUAL(papszParms[0], szAlgNameRange) )
+        *peAlgorithm = GGA_MetricRange;
+    else
+    {
+        fprintf( stderr, "Unsupported gridding method \"%s\".\n",
+                 papszParms[0] );
+        CSLDestroy( papszParms );
+        return CE_Failure;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Parse algorithm parameters and assign defaults.                 */
+/* -------------------------------------------------------------------- */
+    const char  *pszValue;
+
+    switch ( *peAlgorithm )
+    {
+        case GGA_InverseDistanceToAPower:
+        default:
+            *ppOptions =
+                CPLMalloc( sizeof(GDALGridInverseDistanceToAPowerOptions) );
+
+            pszValue = CSLFetchNameValue( papszParms, "power" );
+            ((GDALGridInverseDistanceToAPowerOptions *)*ppOptions)->
+                dfPower = (pszValue) ? atof(pszValue) : 2.0;
+
+            pszValue = CSLFetchNameValue( papszParms, "smoothing" );
+            ((GDALGridInverseDistanceToAPowerOptions *)*ppOptions)->
+                dfSmoothing = (pszValue) ? atof(pszValue) : 0.0;
+
+            pszValue = CSLFetchNameValue( papszParms, "radius1" );
+            ((GDALGridInverseDistanceToAPowerOptions *)*ppOptions)->
+                dfRadius1 = (pszValue) ? atof(pszValue) : 0.0;
+
+            pszValue = CSLFetchNameValue( papszParms, "radius2" );
+            ((GDALGridInverseDistanceToAPowerOptions *)*ppOptions)->
+                dfRadius2 = (pszValue) ? atof(pszValue) : 0.0;
+
+            pszValue = CSLFetchNameValue( papszParms, "angle" );
+            ((GDALGridInverseDistanceToAPowerOptions *)*ppOptions)->
+                dfAngle = (pszValue) ? atof(pszValue) : 0.0;
+
+            pszValue = CSLFetchNameValue( papszParms, "max_points" );
+            ((GDALGridInverseDistanceToAPowerOptions *)*ppOptions)->
+                nMaxPoints = (pszValue) ? atol(pszValue) : 0;
+
+            pszValue = CSLFetchNameValue( papszParms, "min_points" );
+            ((GDALGridInverseDistanceToAPowerOptions *)*ppOptions)->
+                nMinPoints = (pszValue) ? atol(pszValue) : 0;
+
+            pszValue = CSLFetchNameValue( papszParms, "nodata" );
+            ((GDALGridInverseDistanceToAPowerOptions *)*ppOptions)->
+                dfNoDataValue = (pszValue) ? atof(pszValue) : 0.0;
+            break;
+
+        case GGA_MovingAverage:
+            *ppOptions =
+                CPLMalloc( sizeof(GDALGridMovingAverageOptions) );
+
+            pszValue = CSLFetchNameValue( papszParms, "radius1" );
+            ((GDALGridMovingAverageOptions *)*ppOptions)->
+                dfRadius1 = (pszValue) ? atof(pszValue) : 0.0;
+
+            pszValue = CSLFetchNameValue( papszParms, "radius2" );
+            ((GDALGridMovingAverageOptions *)*ppOptions)->
+                dfRadius2 = (pszValue) ? atof(pszValue) : 0.0;
+
+            pszValue = CSLFetchNameValue( papszParms, "angle" );
+            ((GDALGridMovingAverageOptions *)*ppOptions)->
+                dfAngle = (pszValue) ? atof(pszValue) : 0.0;
+
+            pszValue = CSLFetchNameValue( papszParms, "min_points" );
+            ((GDALGridMovingAverageOptions *)*ppOptions)->
+                nMinPoints = (pszValue) ? atol(pszValue) : 0;
+
+            pszValue = CSLFetchNameValue( papszParms, "nodata" );
+            ((GDALGridMovingAverageOptions *)*ppOptions)->
+                dfNoDataValue = (pszValue) ? atof(pszValue) : 0.0;
+            break;
+
+        case GGA_NearestNeighbor:
+            *ppOptions =
+                CPLMalloc( sizeof(GDALGridNearestNeighborOptions) );
+
+            pszValue = CSLFetchNameValue( papszParms, "radius1" );
+            ((GDALGridNearestNeighborOptions *)*ppOptions)->
+                dfRadius1 = (pszValue) ? atof(pszValue) : 0.0;
+
+            pszValue = CSLFetchNameValue( papszParms, "radius2" );
+            ((GDALGridNearestNeighborOptions *)*ppOptions)->
+                dfRadius2 = (pszValue) ? atof(pszValue) : 0.0;
+
+            pszValue = CSLFetchNameValue( papszParms, "angle" );
+            ((GDALGridNearestNeighborOptions *)*ppOptions)->
+                dfAngle = (pszValue) ? atof(pszValue) : 0.0;
+
+            pszValue = CSLFetchNameValue( papszParms, "nodata" );
+            ((GDALGridNearestNeighborOptions *)*ppOptions)->
+                dfNoDataValue = (pszValue) ? atof(pszValue) : 0.0;
+            break;
+
+        case GGA_MetricMinimum:
+        case GGA_MetricMaximum:
+        case GGA_MetricRange:
+            *ppOptions =
+                CPLMalloc( sizeof(GDALGridDataMetricsOptions) );
+
+            pszValue = CSLFetchNameValue( papszParms, "radius1" );
+            ((GDALGridDataMetricsOptions *)*ppOptions)->
+                dfRadius1 = (pszValue) ? atof(pszValue) : 0.0;
+
+            pszValue = CSLFetchNameValue( papszParms, "radius2" );
+            ((GDALGridDataMetricsOptions *)*ppOptions)->
+                dfRadius2 = (pszValue) ? atof(pszValue) : 0.0;
+
+            pszValue = CSLFetchNameValue( papszParms, "angle" );
+            ((GDALGridDataMetricsOptions *)*ppOptions)->
+                dfAngle = (pszValue) ? atof(pszValue) : 0.0;
+
+            pszValue = CSLFetchNameValue( papszParms, "min_points" );
+            ((GDALGridDataMetricsOptions *)*ppOptions)->
+                nMinPoints = (pszValue) ? atol(pszValue) : 0;
+
+            pszValue = CSLFetchNameValue( papszParms, "nodata" );
+            ((GDALGridDataMetricsOptions *)*ppOptions)->
+                dfNoDataValue = (pszValue) ? atof(pszValue) : 0.0;
+            break;
+
+   }
+
+    CSLDestroy( papszParms );
+    return CE_None;
+}
+
+/************************************************************************/
+/*                            ProcessLayer()                            */
+/*                                                                      */
+/*      Process all the features in a layer selection, collecting       */
+/*      geometries and burn values.                                     */
+/************************************************************************/
+
+static void ProcessLayer( OGRLayerH hSrcLayer, GDALDatasetH hDstDS,
+                          GUInt32 nXSize, GUInt32 nYSize, int nBand,
+                          int& bIsXExtentSet, int& bIsYExtentSet,
+                          double& dfXMin, double& dfXMax,
+                          double& dfYMin, double& dfYMax,
+                          const char *pszBurnAttribute,
+                          GDALDataType eType,
+                          GDALGridAlgorithm eAlgorithm, void *pOptions,
+                          int bQuiet, GDALProgressFunc pfnProgress )
+
+{
+/* -------------------------------------------------------------------- */
+/*      Get field index, and check.                                     */
+/* -------------------------------------------------------------------- */
+    int iBurnField = -1;
+
+    if ( pszBurnAttribute )
+    {
+        iBurnField = OGR_FD_GetFieldIndex( OGR_L_GetLayerDefn( hSrcLayer ),
+                                           pszBurnAttribute );
+        if( iBurnField == -1 )
+        {
+            #ifdef ZOO_SERVICE
+	  fprintf(stderr,
+#else
+            printf( 
+#endif
+ "Failed to find field %s on layer %s, skipping.\n",
+                    pszBurnAttribute, 
+                    OGR_FD_GetName( OGR_L_GetLayerDefn( hSrcLayer ) ) );
+            return;
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Collect the geometries from this layer, and build list of       */
+/*      values to be interpolated.                                      */
+/* -------------------------------------------------------------------- */
+    OGRFeatureH hFeat;
+    std::vector<double> adfX, adfY, adfZ;
+
+    OGR_L_ResetReading( hSrcLayer );
+
+    while( (hFeat = OGR_L_GetNextFeature( hSrcLayer )) != NULL )
+    {
+        OGRGeometryH hGeom;
+
+        hGeom = OGR_F_GetGeometryRef( hFeat );
+
+        // FIXME: handle collections
+        if ( hGeom != NULL &&
+             (OGR_G_GetGeometryType( hGeom ) == wkbPoint
+              || OGR_G_GetGeometryType( hGeom ) == wkbPoint25D) )
+        {
+            adfX.push_back( OGR_G_GetX( hGeom, 0 ) );
+            adfY.push_back( OGR_G_GetY( hGeom, 0 ) );
+            if ( iBurnField < 0 )
+                adfZ.push_back( OGR_G_GetZ( hGeom, 0 ) );
+            else
+                adfZ.push_back( OGR_F_GetFieldAsDouble( hFeat, iBurnField ) );
+        }
+
+        
+        OGR_F_Destroy( hFeat );
+    }
+
+    if (adfX.size() == 0)
+    {
+        #ifdef ZOO_SERVICE
+	  fprintf(stderr,
+#else
+            printf( 
+#endif
+ "No point geometry found on layer %s, skipping.\n",
+                OGR_FD_GetName( OGR_L_GetLayerDefn( hSrcLayer ) ) );
+        return;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Compute grid geometry.                                          */
+/* -------------------------------------------------------------------- */
+
+    if ( !bIsXExtentSet )
+    {
+        dfXMin = *std::min_element(adfX.begin(), adfX.end());
+        dfXMax = *std::max_element(adfX.begin(), adfX.end());
+        bIsXExtentSet = TRUE;
+    }
+
+    if ( !bIsYExtentSet )
+    {
+        dfYMin = *std::min_element(adfY.begin(), adfY.end());
+        dfYMax = *std::max_element(adfY.begin(), adfY.end());
+        bIsYExtentSet = TRUE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Perform gridding.                                               */
+/* -------------------------------------------------------------------- */
+
+    const double    dfDeltaX = ( dfXMax - dfXMin ) / nXSize;
+    const double    dfDeltaY = ( dfYMax - dfYMin ) / nYSize;
+
+    if ( !bQuiet )
+    {
+        #ifdef ZOO_SERVICE
+	  fprintf(stderr,
+#else
+            printf( 
+#endif
+ "Grid data type is \"%s\"\n", GDALGetDataTypeName(eType) );
+        #ifdef ZOO_SERVICE
+	  fprintf(stderr,
+#else
+            printf( 
+#endif
+ "Grid size = (%lu %lu).\n",
+                (unsigned long)nXSize, (unsigned long)nYSize );
+        #ifdef ZOO_SERVICE
+	  fprintf(stderr,
+#else
+            printf( 
+#endif
+ "Corner coordinates = (%f %f)-(%f %f).\n",
+                dfXMin - dfDeltaX / 2, dfYMax + dfDeltaY / 2,
+                dfXMax + dfDeltaX / 2, dfYMin - dfDeltaY / 2 );
+        #ifdef ZOO_SERVICE
+	  fprintf(stderr,
+#else
+            printf( 
+#endif
+ "Grid cell size = (%f %f).\n", dfDeltaX, dfDeltaY );
+        #ifdef ZOO_SERVICE
+	  fprintf(stderr,
+#else
+            printf( 
+#endif
+ "Source point count = %lu.\n", (unsigned long)adfX.size() );
+        PrintAlgorithmAndOptions( eAlgorithm, pOptions );
+        #ifdef ZOO_SERVICE
+	  fprintf(stderr,
+#else
+            printf( 
+#endif
+"\n");
+    }
+
+    GDALRasterBandH hBand = GDALGetRasterBand( hDstDS, nBand );
+
+    if (adfX.size() == 0)
+    {
+        // FIXME: Shoulda' set to nodata value instead
+        GDALFillRaster( hBand, 0.0 , 0.0 );
+        return;
+    }
+
+    GUInt32 nXOffset, nYOffset;
+    int     nBlockXSize, nBlockYSize;
+
+    GDALGetBlockSize( hBand, &nBlockXSize, &nBlockYSize );
+    void    *pData =
+        CPLMalloc( nBlockXSize * nBlockYSize * GDALGetDataTypeSize(eType) );
+
+    GUInt32 nBlock = 0;
+    GUInt32 nBlockCount = ((nXSize + nBlockXSize - 1) / nBlockXSize)
+        * ((nYSize + nBlockYSize - 1) / nBlockYSize);
+
+    for ( nYOffset = 0; nYOffset < nYSize; nYOffset += nBlockYSize )
+    {
+        for ( nXOffset = 0; nXOffset < nXSize; nXOffset += nBlockXSize )
+        {
+            void *pScaledProgress;
+            pScaledProgress =
+                GDALCreateScaledProgress( 0.0,
+                                          (double)++nBlock / nBlockCount,
+                                          pfnProgress, NULL );
+
+            int nXRequest = nBlockXSize;
+            if (nXOffset + nXRequest > nXSize)
+                nXRequest = nXSize - nXOffset;
+
+            int nYRequest = nBlockYSize;
+            if (nYOffset + nYRequest > nYSize)
+                nYRequest = nYSize - nYOffset;
+
+            GDALGridCreate( eAlgorithm, pOptions,
+                            adfX.size(), &(adfX[0]), &(adfY[0]), &(adfZ[0]),
+                            dfXMin + dfDeltaX * nXOffset,
+                            dfXMin + dfDeltaX * (nXOffset + nXRequest),
+                            dfYMin + dfDeltaY * nYOffset,
+                            dfYMin + dfDeltaY * (nYOffset + nYRequest),
+                            nXRequest, nYRequest, eType, pData,
+                            GDALScaledProgress, pScaledProgress );
+
+            GDALRasterIO( hBand, GF_Write, nXOffset, nYOffset,
+                          nXRequest, nYRequest, pData,
+                          nXRequest, nYRequest, eType, 0, 0 );
+
+            GDALDestroyScaledProgress( pScaledProgress );
+        }
+    }
+
+    CPLFree( pData );
+}
+
+/************************************************************************/
+/*                                main()                                */
+/************************************************************************/
+#ifdef ZOO_SERVICE
+int Gdal_Grid(maps*& conf,maps*& inputs,maps*& outputs)
+#else
+int main( int argc, char ** argv )
+#endif
+{
+    GDALDriverH     hDriver;
+    const char      *pszSource=NULL, *pszDest=NULL, *pszFormat = "GTiff";
+    char            **papszLayers = NULL;
+    const char      *pszBurnAttribute = NULL;
+    const char      *pszWHERE = NULL, *pszSQL = NULL;
+    GDALDataType    eOutputType = GDT_Float64;
+    char            **papszCreateOptions = NULL;
+    GUInt32         nXSize = 0, nYSize = 0;
+    double          dfXMin = 0.0, dfXMax = 0.0, dfYMin = 0.0, dfYMax = 0.0;
+    int             bIsXExtentSet = FALSE, bIsYExtentSet = FALSE;
+    GDALGridAlgorithm eAlgorithm = GGA_InverseDistanceToAPower;
+    void            *pOptions = NULL;
+    char            *pszOutputSRS = NULL;
+    int             bQuiet = FALSE;
+    GDALProgressFunc pfnProgress = GDALTermProgress;
+    int             i;
+    OGRGeometryH    hSpatialFilter = NULL;
+
+    /* Check that we are running against at least GDAL 1.5 */
+    /* Note to developers : if we use newer API, please change the requirement */
+    if (atoi(GDALVersionInfo("VERSION_NUM")) < 1500)
+    {
+#ifdef ZOO_SERVICE
+        fprintf(stderr, "At least, GDAL >= 1.5.0 is required for this version of this ZOO ServiceProvider, "
+                "which was compiled against GDAL %s\n", GDAL_RELEASE_NAME);
+#else
+        fprintf(stderr, "At least, GDAL >= 1.5.0 is required for this version of %s, "
+                "which was compiled against GDAL %s\n", argv[0], GDAL_RELEASE_NAME);
+#endif
+	return SERVICE_FAILED;
+    }
+
+    GDALAllRegister();
+    OGRRegisterAll();
+
+#ifdef ZOO_SERVICE
+    bQuiet = TRUE;
+    pfnProgress = GDALDummyProgress;
+    map* tmpMap=NULL;
+
+    char dataPath[1024];
+    tmpMap=getMapFromMaps(conf,"main","dataPath");
+    if(tmpMap!=NULL)
+      sprintf(dataPath,"%s",tmpMap->value);
+    tmpMap=NULL;
+
+    char tempPath[1024];
+    tmpMap=getMapFromMaps(conf,"main","tmpPath");
+    if(tmpMap!=NULL){
+      sprintf(tempPath,"%s",tmpMap->value);
+    }
+    tmpMap=NULL;
+
+    tmpMap=getMapFromMaps(inputs,"OF","value");
+    if(tmpMap!=NULL){
+      pszFormat=tmpMap->value;
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"OT","value");
+    if(tmpMap!=NULL){
+      int iType;      
+      for( iType = 1; iType < GDT_TypeCount; iType++ )
+	{
+	  if( GDALGetDataTypeName((GDALDataType)iType) != NULL
+	      && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
+                             tmpMap->value) )
+	    {
+	      eOutputType = (GDALDataType) iType;
+	    }
+	}
+      if( eOutputType == GDT_Unknown )
+	{
+	  fprintf( stderr, "Unknown output pixel type: %s\n", tmpMap->value );
+	  Usage();
+	  return SERVICE_FAILED;
+	}
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"TXE","value");
+    if(tmpMap!=NULL){
+      char *tmp=tmpMap->value;
+      char *t=strtok(tmp,",");
+      int cnt=0;
+      while(t!=NULL){
+        switch(cnt){
+        case 0:
+          dfXMin = atof(t);
+          break;
+        case 1:
+          dfXMax = atof(t);
+          break;
+        }
+	t=strtok(NULL,",");
+	cnt++;
+      }
+      bIsXExtentSet = TRUE;
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"TYE","value");
+    if(tmpMap!=NULL){
+      char *tmp=tmpMap->value;
+      char *t=strtok(tmp,",");
+      int cnt=0;
+      while(t!=NULL){
+        switch(cnt){
+        case 0:
+          dfYMin = atof(t);
+          break;
+        case 1:
+          dfYMax = atof(t);
+          break;
+        }
+	t=strtok(NULL,",");
+	cnt++;
+	
+      }
+      bIsYExtentSet = TRUE;
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"OUTSIZE","value");
+    if(tmpMap!=NULL){
+      char *tmp=tmpMap->value;
+      char *t=strtok(tmp,",");
+      int cnt=0;
+      while(t!=NULL){
+        switch(cnt){
+        case 0:
+          nXSize = atoi(t);
+          break;
+        case 1:
+          nYSize = atoi(t);
+          break;
+        }
+	cnt++;
+      }
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"CO","value");
+    if(tmpMap!=NULL){
+      papszCreateOptions = CSLAddString( papszCreateOptions, tmpMap->value );
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"ZFIELD","value");
+    if(tmpMap!=NULL){
+      pszBurnAttribute = tmpMap->value;
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"WHERE","value");
+    if(tmpMap!=NULL){
+      pszWHERE = tmpMap->value;
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"L","value");
+    if(tmpMap!=NULL){
+      papszLayers = CSLAddString( papszLayers, tmpMap->value );
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"SQL","value");
+    if(tmpMap!=NULL){
+      pszSQL = tmpMap->value;
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"A","value");
+    if(tmpMap!=NULL){
+      if ( ParseAlgorithmAndOptions(tmpMap->value, &eAlgorithm, &pOptions )
+	   != CE_None )
+	{
+	  fprintf( stderr,
+		   "Failed to process algoritm name and parameters.\n" );
+	  return SERVICE_FAILED;
+	}
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"SPAT","value");
+    if(tmpMap!=NULL){
+      char *tmp=tmpMap->value;
+      char *t=strtok(tmp,",");
+      int cnt=0;
+      double dfULX, dfULY, dfLRX, dfLRY;
+      while(t!=NULL){
+        switch(cnt){
+        case 0:
+          dfULX = atof(t);
+          break;
+        case 1:
+          dfULY = atof(t);
+          break;
+        case 2:
+          dfLRX = atof(t);
+          break;
+        case 3:
+          dfLRY = atof(t);
+          break;
+        }
+        fprintf(stderr,"%s\n\n",t);
+        fprintf(stderr,"%f - %f - %f - %f\n\n",dfULX,dfULY,dfLRX,dfLRY);
+        t=strtok(NULL,",");
+        cnt++;
+      }
+      OGRGeometryH hRing = OGR_G_CreateGeometry( wkbLinearRing );
+      
+      OGR_G_AddPoint_2D( hRing, dfULX, dfULY );
+      OGR_G_AddPoint_2D( hRing, dfULX, dfLRY );
+      OGR_G_AddPoint_2D( hRing, dfLRY, dfLRY );
+      OGR_G_AddPoint_2D( hRing, dfLRY, dfULY );
+      OGR_G_AddPoint_2D( hRing, dfULX, dfULY );
+      
+      hSpatialFilter = OGR_G_CreateGeometry( wkbPolygon );
+      OGR_G_AddGeometry( hSpatialFilter, hRing );
+	
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"A_SRS","value");
+    if(tmpMap!=NULL){
+      OGRSpatialReference oOutputSRS;
+      
+      if( oOutputSRS.SetFromUserInput( tmpMap->value ) != OGRERR_NONE )
+	{
+	  fprintf( stderr, "Failed to process SRS definition: %s\n", 
+		   tmpMap->value );
+	  GDALDestroyDriverManager();
+	  return SERVICE_FAILED;
+	}
+      
+      oOutputSRS.exportToWkt( &pszOutputSRS );
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"InputDSN","value");
+    if(tmpMap!=NULL){
+      pszSource=(char*)malloc(sizeof(char)*(strlen(dataPath)+strlen(tmpMap->value)+1));
+      sprintf((char*)pszSource,"%s/%s",dataPath,tmpMap->value);
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"OutputDSN","value");
+    if(tmpMap!=NULL){
+      pszDest=(char*)malloc(sizeof(char)*(strlen(tempPath)+strlen(tmpMap->value)+4));
+      char *ext=new char[4];
+      ext="tif";
+      if(strncasecmp(pszFormat,"AAIGRID",7)==0)
+        ext="csv";
+      else 
+        if(strncasecmp(pszFormat,"PNG",3)==0)
+          ext="png";
+        else
+          if(strncasecmp(pszFormat,"GIF",3)==0)
+            ext="gif";
+          else
+            if(strncasecmp(pszFormat,"JPEG",4)==0)
+              ext="jpg";
+      sprintf((char*)pszDest,"%s/%s.%s",tempPath,tmpMap->value,ext);
+    }
+
+#else
+    argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
+    if( argc < 1 )
+        exit( -argc );
+
+/* -------------------------------------------------------------------- */
+/*      Parse arguments.                                                */
+/* -------------------------------------------------------------------- */
+    for( i = 1; i < argc; i++ )
+    {
+        if( EQUAL(argv[i], "--utility_version") )
+        {
+            printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
+                   argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
+            return 0;
+        }
+        else if( EQUAL(argv[i],"-of") && i < argc-1 )
+        {
+            pszFormat = argv[++i];
+        }
+
+        else if( EQUAL(argv[i],"-quiet") )
+        {
+            bQuiet = TRUE;
+            pfnProgress = GDALDummyProgress;
+        }
+
+        else if( EQUAL(argv[i],"-ot") && i < argc-1 )
+        {
+            int	iType;
+            
+            for( iType = 1; iType < GDT_TypeCount; iType++ )
+            {
+                if( GDALGetDataTypeName((GDALDataType)iType) != NULL
+                    && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
+                             argv[i+1]) )
+                {
+                    eOutputType = (GDALDataType) iType;
+                }
+            }
+
+            if( eOutputType == GDT_Unknown )
+            {
+                fprintf( stderr, "Unknown output pixel type: %s\n", argv[i+1] );
+                Usage();
+                exit( 2 );
+            }
+            i++;
+        }
+
+        else if( EQUAL(argv[i],"-txe") && i < argc-2 )
+        {
+            dfXMin = atof(argv[++i]);
+            dfXMax = atof(argv[++i]);
+            bIsXExtentSet = TRUE;
+        }   
+
+        else if( EQUAL(argv[i],"-tye") && i < argc-2 )
+        {
+            dfYMin = atof(argv[++i]);
+            dfYMax = atof(argv[++i]);
+            bIsYExtentSet = TRUE;
+        }   
+
+        else if( EQUAL(argv[i],"-outsize") && i < argc-2 )
+        {
+            nXSize = atoi(argv[++i]);
+            nYSize = atoi(argv[++i]);
+        }   
+
+        else if( EQUAL(argv[i],"-co") && i < argc-1 )
+        {
+            papszCreateOptions = CSLAddString( papszCreateOptions, argv[++i] );
+        }   
+
+        else if( EQUAL(argv[i],"-zfield") && i < argc-1 )
+        {
+            pszBurnAttribute = argv[++i];
+        }
+
+        else if( EQUAL(argv[i],"-where") && i < argc-1 )
+        {
+            pszWHERE = argv[++i];
+        }
+
+        else if( EQUAL(argv[i],"-l") && i < argc-1 )
+        {
+            papszLayers = CSLAddString( papszLayers, argv[++i] );
+        }
+
+        else if( EQUAL(argv[i],"-sql") && i < argc-1 )
+        {
+            pszSQL = argv[++i];
+        }
+
+        else if( EQUAL(argv[i],"-spat") 
+                 && argv[i+1] != NULL 
+                 && argv[i+2] != NULL 
+                 && argv[i+3] != NULL 
+                 && argv[i+4] != NULL )
+        {
+            OGRGeometryH hRing = OGR_G_CreateGeometry( wkbLinearRing );
+
+            OGR_G_AddPoint_2D( hRing, atof(argv[i+1]), atof(argv[i+2]) );
+            OGR_G_AddPoint_2D( hRing, atof(argv[i+1]), atof(argv[i+4]) );
+            OGR_G_AddPoint_2D( hRing, atof(argv[i+3]), atof(argv[i+4]) );
+            OGR_G_AddPoint_2D( hRing, atof(argv[i+3]), atof(argv[i+2]) );
+            OGR_G_AddPoint_2D( hRing, atof(argv[i+1]), atof(argv[i+2]) );
+
+            hSpatialFilter = OGR_G_CreateGeometry( wkbPolygon );
+            OGR_G_AddGeometry( hSpatialFilter, hRing );
+            i += 4;
+        }
+
+        else if( EQUAL(argv[i],"-a_srs") && i < argc-1 )
+        {
+            OGRSpatialReference oOutputSRS;
+
+            if( oOutputSRS.SetFromUserInput( argv[i+1] ) != OGRERR_NONE )
+            {
+                fprintf( stderr, "Failed to process SRS definition: %s\n", 
+                         argv[i+1] );
+                GDALDestroyDriverManager();
+                exit( 1 );
+            }
+
+            oOutputSRS.exportToWkt( &pszOutputSRS );
+            i++;
+        }   
+
+        else if( EQUAL(argv[i],"-a") && i < argc-1 )
+        {
+            if ( ParseAlgorithmAndOptions( argv[++i], &eAlgorithm, &pOptions )
+                 != CE_None )
+            {
+                fprintf( stderr,
+                         "Failed to process algoritm name and parameters.\n" );
+                exit( 1 );
+            }
+        }
+
+        else if( argv[i][0] == '-' )
+        {
+            fprintf( stderr, "Option %s incomplete, or not recognised.\n\n", 
+                    argv[i] );
+            Usage();
+            GDALDestroyDriverManager();
+            exit( 2 );
+        }
+
+        else if( pszSource == NULL )
+        {
+            pszSource = argv[i];
+        }
+
+        else if( pszDest == NULL )
+        {
+            pszDest = argv[i];
+        }
+
+        else
+        {
+            fprintf( stderr, "Too many command options.\n\n" );
+            Usage();
+            GDALDestroyDriverManager();
+            exit( 2 );
+        }
+    }
+#endif
+
+    if( pszSource == NULL || pszDest == NULL
+        || (pszSQL == NULL && papszLayers == NULL) )
+    {
+        Usage();
+        GDALDestroyDriverManager();
+        exit( 2 );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Find the output driver.                                         */
+/* -------------------------------------------------------------------- */
+    hDriver = GDALGetDriverByName( pszFormat );
+    if( hDriver == NULL )
+    {
+        int	iDr;
+        
+        fprintf( stderr, "Output driver `%s' not recognised.\n", pszFormat );
+        fprintf( stderr,
+        "The following format drivers are configured and support output:\n" );
+        for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
+        {
+            GDALDriverH hDriver = GDALGetDriver(iDr);
+
+            if( GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) != NULL
+                || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY,
+                                        NULL ) != NULL )
+            {
+                fprintf( stderr, "  %s: %s\n",
+                         GDALGetDriverShortName( hDriver  ),
+                         GDALGetDriverLongName( hDriver ) );
+            }
+        }
+        printf( "\n" );
+        Usage();
+        
+        GDALDestroyDriverManager();
+#ifndef ZOO_SERVICE
+        CSLDestroy( argv );
+#endif
+        CSLDestroy( papszCreateOptions );
+	return SERVICE_FAILED;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Open input datasource.                                          */
+/* -------------------------------------------------------------------- */
+    OGRDataSourceH hSrcDS;
+
+    hSrcDS = OGROpen( pszSource, FALSE, NULL );
+    if( hSrcDS == NULL )
+    {
+        fprintf( stderr, "Unable to open input datasource \"%s\".\n",
+                 pszSource );
+        fprintf( stderr, "%s\n", CPLGetLastErrorMsg() );
+	return SERVICE_FAILED;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Create target raster file.                                      */
+/* -------------------------------------------------------------------- */
+    GDALDatasetH    hDstDS;
+    int             nLayerCount = CSLCount(papszLayers);
+    int             nBands = nLayerCount;
+
+    if ( pszSQL )
+        nBands++;
+
+    // FIXME
+    if ( nXSize == 0 )
+        nXSize = 256;
+    if ( nYSize == 0 )
+        nYSize = 256;
+
+    hDstDS = GDALCreate( hDriver, pszDest, nXSize, nYSize, nBands,
+                         eOutputType, papszCreateOptions );
+    if ( hDstDS == NULL )
+    {
+        fprintf( stderr, "Unable to create target dataset \"%s\".\n",
+                 pszDest );
+        fprintf( stderr, "%s\n", CPLGetLastErrorMsg() );
+	return SERVICE_FAILED;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      If algorithm was not specified assigh default one.              */
+/* -------------------------------------------------------------------- */
+    if ( !pOptions )
+        ParseAlgorithmAndOptions( szAlgNameInvDist, &eAlgorithm, &pOptions );
+
+/* -------------------------------------------------------------------- */
+/*      Process SQL request.                                            */
+/* -------------------------------------------------------------------- */
+    if( pszSQL != NULL )
+    {
+        OGRLayerH hLayer;
+
+        hLayer = OGR_DS_ExecuteSQL( hSrcDS, pszSQL, hSpatialFilter, NULL ); 
+        if( hLayer != NULL )
+        {
+            // Custom layer will be rasterized in the first band.
+            ProcessLayer( hLayer, hDstDS, nXSize, nYSize, 1,
+                          bIsXExtentSet, bIsYExtentSet,
+                          dfXMin, dfXMax, dfYMin, dfYMax, pszBurnAttribute,
+                          eOutputType, eAlgorithm, pOptions,
+                          bQuiet, pfnProgress );
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Process each layer.                                             */
+/* -------------------------------------------------------------------- */
+    for( i = 0; i < nLayerCount; i++ )
+    {
+        OGRLayerH hLayer = OGR_DS_GetLayerByName( hSrcDS, papszLayers[i] );
+        if( hLayer == NULL )
+        {
+            fprintf( stderr, "Unable to find layer \"%s\", skipping.\n", 
+                     papszLayers[i] );
+            continue;
+        }
+
+        if( pszWHERE )
+        {
+            if( OGR_L_SetAttributeFilter( hLayer, pszWHERE ) != OGRERR_NONE )
+                break;
+        }
+
+        if( hSpatialFilter != NULL )
+          OGR_L_SetSpatialFilter( hLayer, hSpatialFilter );
+
+        // Fetch the first meaningful SRS definition
+        if ( !pszOutputSRS )
+        {
+            OGRSpatialReferenceH hSRS = OGR_L_GetSpatialRef( hLayer );
+            if ( hSRS )
+                OSRExportToWkt( hSRS, &pszOutputSRS );
+        }
+
+        ProcessLayer( hLayer, hDstDS, nXSize, nYSize,
+                      i + 1 + nBands - nLayerCount,
+                      bIsXExtentSet, bIsYExtentSet,
+                      dfXMin, dfXMax, dfYMin, dfYMax, pszBurnAttribute,
+                      eOutputType, eAlgorithm, pOptions,
+                      bQuiet, pfnProgress );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Apply geotransformation matrix.                                 */
+/* -------------------------------------------------------------------- */
+    double  adfGeoTransform[6];
+    adfGeoTransform[0] = dfXMin;
+    adfGeoTransform[1] = (dfXMax - dfXMin) / nXSize;
+    adfGeoTransform[2] = 0.0;
+    adfGeoTransform[3] = dfYMin;
+    adfGeoTransform[4] = 0.0;
+    adfGeoTransform[5] = (dfYMax - dfYMin) / nYSize;
+    GDALSetGeoTransform( hDstDS, adfGeoTransform );
+
+/* -------------------------------------------------------------------- */
+/*      Apply SRS definition if set.                                    */
+/* -------------------------------------------------------------------- */
+    if ( pszOutputSRS )
+    {
+        GDALSetProjection( hDstDS, pszOutputSRS );
+        CPLFree( pszOutputSRS );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Cleanup                                                         */
+/* -------------------------------------------------------------------- */
+    CSLDestroy( papszCreateOptions );
+    CPLFree( pOptions );
+    OGR_DS_Destroy( hSrcDS );
+    GDALClose( hDstDS );
+#ifndef ZOO_SERVICE
+    CSLDestroy( argv );
+#endif
+    CSLDestroy( papszLayers );
+    OGRCleanupAll();
+
+    GDALDestroyDriverManager();
+ 
+    outputs=(maps*)malloc(sizeof(maps*));
+    outputs->name="OutputedPolygon";
+    outputs->content=createMap("value",(char*)pszDest);
+    addMapToMap(&outputs->content,createMap("dataType","string"));
+    outputs->next=NULL;
+    return SERVICE_SUCCEEDED;
+}
+
+
+#ifdef ZOO_SERVICE
+}
+#endif
diff --git a/zoo-project/zoo-services/gdal/ndvi/cgi-env/ExtractNDVI.zcfg b/zoo-project/zoo-services/gdal/ndvi/cgi-env/ExtractNDVI.zcfg
new file mode 100644
index 0000000..bd31b25
--- /dev/null
+++ b/zoo-project/zoo-services/gdal/ndvi/cgi-env/ExtractNDVI.zcfg
@@ -0,0 +1,58 @@
+[ExtractNDVI]
+ Title = Normalized Difference Vegetation Index. 
+ Abstract = Computes the Normalized Difference Vegetation Index in a new raster file. 
+ Profile = urn:ogc:wps:1.0.0:buffer
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = ndvi
+ serviceType = Python
+ <MetaData>
+   title = Demo
+ </MetaData>
+ <DataInputs>
+  [raster]
+   Title = The raster file to be used
+   Abstract = URI to a raster file that contains the mentionned two bands.
+   minOccurs = 1
+   maxOccurs = 1
+   <ComplexData>
+    <Default>
+     mimeType = image/tiff
+    </Default>
+   </ComplexData>
+  [red]
+   Title = The red band number
+   Abstract = The RED band number to use.
+   minOccurs = 0
+   maxOccurs = 1
+   <LiteralData>
+    DataType = int
+    <Default>
+     value = 1
+    </Default>
+   </LiteralData>
+  [nir]
+   Title = The NIR band number
+   Abstract = The NIR band number to use.
+   minOccurs = 0
+   maxOccurs = 1
+   <LiteralData>
+    DataType = int
+    <Default>
+     value = 2
+    </Default>
+   </LiteralData>
+ </DataInputs>
+ <DataOutputs>
+  [raster]
+   Title = The resulting raster
+   Abstract = A single band raster containing the NDVI of the original raster using formula : (NIR - RED) / (NIR + RED) .
+   <ComplexData>
+    <Default>
+     mimeType = image/tiff
+     extension = tif
+    </Default>
+   </ComplexData>
+ </DataOutputs>  
+
diff --git a/zoo-project/zoo-services/gdal/ndvi/cgi-env/ndvi.py b/zoo-project/zoo-services/gdal/ndvi/cgi-env/ndvi.py
new file mode 100644
index 0000000..3aa0079
--- /dev/null
+++ b/zoo-project/zoo-services/gdal/ndvi/cgi-env/ndvi.py
@@ -0,0 +1,107 @@
+#
+# Python Scripting for ArcGIS
+# by Dr Peter Bunting is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License -
+# See more at:
+# http://www.landmap.ac.uk/index.php/Learning-Materials/Python-Scripting/9.4-Calculate-NDVI-using-GDAL
+#
+
+import sys, os, struct
+
+import osgeo.gdal as gdal
+
+# Calculate and output NDVI from raster bands
+def ExtractNDVI(conf, inputs, outputs):
+    
+    # Open the input dataset
+    gdal.FileFromMemBuffer('/vsimem//temp.tif', inputs["raster"]["value"])
+    dataset = gdal.Open( '/vsimem//temp.tif')
+    if dataset is None:
+        conf["lenv"]["message"]="The dataset could not be openned properly"
+        return 4
+
+    # Create the output dataset
+    driver = gdal.GetDriverByName( "GTiff" )
+    # Get the spatial information from the input file
+    geoTransform=None
+    geoProjection=None
+    print >> sys.stderr,dir(dataset) 
+    try:
+        geoTransform = dataset.GetGeoTransform()
+    except:
+        print >> sys.stderr, "Unable to load geotransform"
+    try:
+        geoProjection = dataset.GetProjection()
+    except:
+        print >> sys.stderr, "Unable to load projection"
+
+    # Create an output file of the same size as the inputted 
+    # image but with only 1 output image band.
+    newDataset = driver.Create("/vsimem//output"+conf["lenv"]["sid"], \
+                               dataset.RasterXSize, dataset.RasterYSize,1, \
+                               gdal.GDT_Float32)
+    # Set spatial informations of the new image.
+    if geoTransform:
+        newDataset.SetGeoTransform(geoTransform)
+    if geoProjection:
+        newDataset.SetProjection(geoProjection)
+    if newDataset is None:
+        conf["lenv"]["message"]='Could not create output image'
+        return 4
+    
+    # Get the RED and NIR image bands of the image
+    red_id=int(inputs["red"]["value"])
+    nir_id=int(inputs["nir"]["value"])
+    red_band = dataset.GetRasterBand(red_id) # RED BAND
+    nir_band = dataset.GetRasterBand(nir_id) # NIR BAND
+
+    # Loop through each line in turn.
+    numLines = red_band.YSize
+    for line in range(numLines):
+        # Define variable for output line.
+        outputLine = ''
+        # Read in data for the current line from the 
+        # image band representing the red wavelength
+        red_scanline = red_band.ReadRaster( 0, line, red_band.XSize, 1, \
+                                          red_band.XSize, 1, gdal.GDT_Float32 )
+        # Unpack the line of data to be read as floating point data
+        red_tuple = struct.unpack('f' * red_band.XSize, red_scanline)
+            
+        # Read in data for the current line from the 
+        # image band representing the NIR wavelength
+        nir_scanline = nir_band.ReadRaster( 0, line, nir_band.XSize, 1, \
+                                          nir_band.XSize, 1, gdal.GDT_Float32 )
+        # Unpack the line of data to be read as floating point data
+        nir_tuple = struct.unpack('f' * nir_band.XSize, nir_scanline)
+
+        # Loop through the columns within the image
+        for i in range(len(red_tuple)):
+            # Calculate the NDVI for the current pixel.
+            ndvi_lower = (nir_tuple[i] + red_tuple[i])
+            ndvi_upper = (nir_tuple[i] - red_tuple[i])
+            ndvi = 0
+            # Becareful of zero divide 
+            if ndvi_lower == 0:
+                ndvi = 0
+            else:
+                ndvi = ndvi_upper/ndvi_lower
+            # Add the current pixel to the output line
+            outputLine = outputLine + struct.pack('f', ndvi)
+        # Write the completed line to the output image
+        newDataset.GetRasterBand(1).WriteRaster(0, line, red_band.XSize, 1, \
+                                         outputLine, buf_xsize=red_band.XSize, 
+                                         buf_ysize=1, buf_type=gdal.GDT_Float32)
+    
+        # Delete the output line following write
+        del outputLine
+    print >> sys.stderr,'NDVI Calculated and Outputted to File'
+    print >> sys.stderr,dir(newDataset)
+    newDataset.FlushCache()
+    vsiFile=gdal.VSIFOpenL("/vsimem//output"+conf["lenv"]["sid"],"r")
+    i=0
+    while gdal.VSIFSeekL(vsiFile,0,os.SEEK_END)>0:
+        i+=1
+    fileSize=gdal.VSIFTellL(vsiFile)
+    gdal.VSIFSeekL(vsiFile,0,os.SEEK_SET)
+    outputs["raster"]["value"]=gdal.VSIFReadL(fileSize,1,vsiFile)
+    gdal.Unlink("/vsimem//output"+conf["lenv"]["sid"])
+    return 3
diff --git a/zoo-project/zoo-services/gdal/profile/Makefile b/zoo-project/zoo-services/gdal/profile/Makefile
new file mode 100755
index 0000000..0fe82a8
--- /dev/null
+++ b/zoo-project/zoo-services/gdal/profile/Makefile
@@ -0,0 +1,15 @@
+ZRPATH=../../..
+include ${ZRPATH}/zoo-kernel/ZOOMakefile.opts
+CFLAGS=${ZOO_CFLAGS} ${XML2CFLAGS} ${GDAL_CFLAGS} ${PYTHONCFLAGS} -DLINUX_FREE_ISSUE #-DDEBUG
+CC=gcc
+
+cgi-env/profile_service.zo: service.c
+	g++  -DZOO_SERVICE ${CFLAGS} -shared -fpic -o cgi-env/profile_service.zo ./service.c ${GDAL_LIBS} ${MACOS_LD_FLAGS} -lzoo_service
+
+install:
+	install -d ${CGI_DIR}/gdal/profile
+	install cgi-env/* ${CGI_DIR}/gdal/profile
+
+
+clean:
+	rm -f cgi-env/*.zo
diff --git a/zoo-project/zoo-services/gdal/profile/cgi-env/GdalExtractProfile.zcfg b/zoo-project/zoo-services/gdal/profile/cgi-env/GdalExtractProfile.zcfg
new file mode 100755
index 0000000..ff1b469
--- /dev/null
+++ b/zoo-project/zoo-services/gdal/profile/cgi-env/GdalExtractProfile.zcfg
@@ -0,0 +1,57 @@
+[GdalExtractProfile]
+ Title = Extract elevation values along a line. 
+ Abstract = Fetch the x,y,z values of a DEM raster file along a linestring
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceType = C
+ serviceProvider = profile_service.zo
+ <MetaData>
+   title = My Demo
+ </MetaData>
+ <DataInputs>
+  [RasterFile]
+   Title = The name of the MNT file
+   Abstract = The file containing elevation model relative to the dataPath defined in the ZOO-Project main configuration file.
+   minOccurs = 0
+   maxOccurs = 1
+   <LiteralData>
+    DataType = string
+    <Default>
+     value = topofr.tif
+    </Default>
+   </LiteralData>
+  [Geometry]
+   Title = The path to calaculate profile
+   Abstract = The input data source name to use as source for convertion.
+   minOccurs = 1
+   maxOccurs = 1
+   <ComplexData>
+    <Default>
+     mimeType = application/json
+     encoding = UTF-8
+     extension = js
+     asReference = true	
+    </Default>
+    <Supported>
+     mimeType = application/json
+     encoding = UTF-8
+    </Supported>
+   </ComplexData>
+ </DataInputs>
+ <DataOutputs>
+  [Profile]
+   Title = The resulting profile
+   Abstract = GeoJSON string containing the X Y Z values where (X,Y) is corresponding to the original coordinates and the elevation value. 
+   <ComplexData>
+    <Default>
+     mimeType = application/json
+     encoding = UTF-8
+     extension = js
+    </Default>
+    <Supported>
+     mimeType = application/json
+     encoding = UTF-8
+    </Supported>
+   </ComplexData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/gdal/profile/makefile.vc b/zoo-project/zoo-services/gdal/profile/makefile.vc
new file mode 100644
index 0000000..a9efa01
--- /dev/null
+++ b/zoo-project/zoo-services/gdal/profile/makefile.vc
@@ -0,0 +1,23 @@
+TROOT= $(ZOOK_DIR)
+!INCLUDE $(ZOOK_DIR)/nmake.opt
+
+FILES=$(ZOOK_DIR)/service_internal.obj $(ZOOK_DIR)/ulinet.obj 
+!IFDEF JS_DIR
+FILES=$(FILES) $(ZOOK_DIR)$(JS_FILE)
+!ENDIF
+!IFDEF JDK_DIR
+FILES=$(FILES) $(ZOOK_DIR)$(JAVA_FILE)
+!ENDIF
+!IFDEF PY_DIR
+FILES=$(FILES) $(ZOOK_DIR)$(PY_FILE)
+!ENDIF
+!IFDEF MS_DIR
+FILES=$(FILES) $(ZOOK_DIR)$(MS_FILE)
+!ENDIF
+
+cgi-env/profile_service.zo: service.c
+	$(CPP)  /D_CRT_NONSTDC_NO_DEPRECATE -DWIN32 -DZOO_SERVICE -I$(GDAL_DIR)/frmts/ $(CFLAGS) /c service.c
+	link /dll /out:cgi-env/profile_service.zo  $(FILES) ./service.obj $(LDFLAGS) /FORCE:MULTIPLE
+
+clean:
+	erase cgi-env\gdal_service.*
diff --git a/zoo-project/zoo-services/gdal/profile/service.c b/zoo-project/zoo-services/gdal/profile/service.c
new file mode 100644
index 0000000..fe21548
--- /dev/null
+++ b/zoo-project/zoo-services/gdal/profile/service.c
@@ -0,0 +1,194 @@
+/* ****************************************************************************
+ * $Id$
+ *
+ * Project:  GdalExtractProfile
+ * Purpose:  Extract Profile from a Raster file for an Input Geometry (LINE)
+ * Author:   Gérald Fenoy, gerald.fenoy at geolabs.fr
+ *
+ * ****************************************************************************
+ * Copyright (c) 2010-2011, GeoLabs SARL
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#ifdef ZOO_SERVICE
+#include "service.h"
+#include "service_internal.h"
+#endif
+#include "gdal.h"
+#include "cpl_conv.h"
+#include "ogr_api.h"
+
+#ifdef ZOO_SERVICE
+extern "C" {
+#endif
+
+#ifdef WIN32
+__declspec(dllexport)
+#endif
+#ifdef ZOO_SERVICE
+int GdalExtractProfile(maps*& conf,maps*& inputs,maps*& outputs)
+#else
+int main(int argc,char** argv)
+#endif
+{
+  char *pszFilename;
+#ifdef ZOO_SERVICE
+  map* tmp=NULL;
+  map* tmp1=NULL;
+  tmp=getMapFromMaps(conf,"main","dataPath");
+  tmp1=getMapFromMaps(inputs,"RasterFile","value");
+  pszFilename=(char *)malloc((2+strlen(tmp->value)+strlen(tmp1->value))*sizeof(char));
+  sprintf(pszFilename,"%s/%s",tmp->value,tmp1->value);
+#else
+  pszFilename=argv[1];
+#endif
+  GDALDatasetH  hDataset;  
+  GDALAllRegister();
+  OGRRegisterAll();
+ 
+  hDataset = GDALOpen( pszFilename, GA_ReadOnly );
+  free(pszFilename);
+  if( hDataset != NULL )
+    {
+      GDALDriverH   hDriver;
+      double        adfGeoTransform[6];
+
+      if( GDALGetGeoTransform( hDataset, adfGeoTransform ) == CE_None )
+	{
+
+
+        GDALRasterBandH hBand;
+        int             nBlockXSize, nBlockYSize;
+        int             bGotMin, bGotMax;
+        double          adfMinMax[2];
+        
+        hBand = GDALGetRasterBand( hDataset, 1 );
+
+        adfMinMax[0] = GDALGetRasterMinimum( hBand, &bGotMin );
+        adfMinMax[1] = GDALGetRasterMaximum( hBand, &bGotMax );
+        if( ! (bGotMin && bGotMax) )
+	  GDALComputeRasterMinMax( hBand, TRUE, adfMinMax );
+#ifdef ZOO_SERVICE
+	  tmp1=getMapFromMaps(inputs,"Geometry","value");
+	  OGRGeometryH geometry=OGR_G_CreateGeometryFromJson(tmp1->value);
+#else
+	  OGRGeometryH geometry=OGR_G_CreateGeometryFromJson(argv[2]);
+#endif
+
+	  OGR_G_Segmentize(geometry, adfGeoTransform[1]);
+	  int nbGeom=OGR_G_GetPointCount(geometry);
+	  int k=0;
+	  double ppx=0,ppy=0;
+	  double value;
+	  char *buffer=NULL;
+	  int length=0;
+	  buffer=(char*)malloc(37*sizeof(char));
+	  sprintf(buffer,"{\"type\":\"LineString\",\"coordinates\":[");
+	  length+=strlen(buffer);
+	  for(k=0;k<nbGeom;k++){
+	    //OGRGeometryH point;
+	    double prx,pry,prz;
+	    OGR_G_GetPoint(geometry,k,&prx,&pry,&prz);
+	    float *pafScanline;
+	    pafScanline = (float *) CPLMalloc(sizeof(float));
+	    int px=(int)floor((prx-adfGeoTransform[0])/adfGeoTransform[1]);
+	    int py=(int)floor((pry-adfGeoTransform[3])/adfGeoTransform[5]);
+	    if(px!=ppx || py!=ppy){
+	      if(GDALRasterIO( hBand, GF_Read, px, py, 1, 1, 
+			    pafScanline, 1, 1, GDT_Float32, 
+			       0, 0 ) != CE_None){
+		char *tmp;
+		tmp=(char*) malloc(300*sizeof(char));
+		sprintf(tmp,"GDALRasterIO failed for point (%d,%d)",px,py);
+		setMapInMaps(conf,"lenv","message",_ss(tmp));
+		CPLFree(pafScanline);
+		free(tmp);
+		return SERVICE_FAILED;
+	      }
+	      if(buffer!=NULL){
+		int len=strlen(buffer);
+		buffer=(char*)realloc(buffer,(len+50+1)*sizeof(char));
+	      }
+	      else
+		buffer=(char*)malloc((51)*sizeof(char));
+	      char *tmpValue=(char *)malloc(50*sizeof(char));
+	      sprintf(tmpValue,"[%.6f,%.6f,%.6f]%c",prx,pry,pafScanline[0],(k+1==nbGeom?' ':','));
+	      strncpy(buffer+length,tmpValue,strlen(tmpValue));
+	      length+=strlen(tmpValue);
+	      buffer[length]=0;
+	      value=pafScanline[0];
+	      free(tmpValue);
+	      //Usefull if we can export 3D JSON string at the end
+	      //OGR_G_SetPoint(geometry,k,prx,pry,pafScanline[0]);	      
+	    }
+	    else{
+	      if(buffer!=NULL)
+		buffer=(char*)realloc(buffer,(strlen(buffer)+50+1)*sizeof(char));
+	      else
+		buffer=(char*)malloc((51)*sizeof(char));
+	      char *tmpValue=(char *)malloc(50*sizeof(char));
+	      sprintf(tmpValue,"[%.6f,%.6f,%.6f]%c",prx,pry,value,(k+1==nbGeom?' ':','));
+	      strncpy(buffer+length,tmpValue,strlen(tmpValue));
+	      length+=strlen(tmpValue);
+	      buffer[length]=0;
+	      free(tmpValue);
+	      value=value;
+	    }
+	    CPLFree(pafScanline);
+	    ppx=px;
+	    ppy=py;
+	  }
+	  buffer=(char*)realloc(buffer,(strlen(buffer)+3)*sizeof(char));
+	  char *tmpValue=(char *)malloc(3*sizeof(char));
+	  sprintf(tmpValue,"]}");
+	  tmpValue[2]=0;
+	  strncpy(buffer+length,tmpValue,strlen(tmpValue));
+	  length+=strlen(tmpValue);
+	  buffer[length]=0;
+#ifdef ZOO_SERVICE
+	  setMapInMaps(outputs,"Profile","value",buffer);
+	  setMapInMaps(outputs,"Profile","mimeType","text/plain");
+#else
+	  fprintf(stderr,"%s\n",buffer);
+#endif
+	  free(buffer);
+	  free(tmpValue);
+	  OGR_G_DestroyGeometry(geometry);
+	}
+    }
+  else{
+#ifdef ZOO_SERVICE
+    setMapInMaps(conf,"lenv","message",_ss("Unable to load your raster file !"));
+    return SERVICE_FAILED;
+#else
+    printf("Unable to load your raster file %s !\n",argv[1]);
+#endif
+  }
+  OGRCleanupAll();
+  GDALClose(hDataset);
+  GDALDestroyDriverManager();
+#ifdef ZOO_SERVICE
+  return SERVICE_SUCCEEDED;
+#endif
+}
+
+#ifdef ZOO_SERVICE
+}
+#endif
diff --git a/zoo-project/zoo-services/gdal/translate/Makefile b/zoo-project/zoo-services/gdal/translate/Makefile
new file mode 100644
index 0000000..ebfe32e
--- /dev/null
+++ b/zoo-project/zoo-services/gdal/translate/Makefile
@@ -0,0 +1,16 @@
+ZRPATH=../../..
+include ${ZRPATH}/zoo-kernel/ZOOMakefile.opts
+CFLAGS=${ZOO_CFLAGS} ${XML2CFLAGS} ${GDAL_CFLAGS} ${PYTHONCFLAGS} -DLINUX_FREE_ISSUE #-DDEBUG
+CC=gcc
+
+cgi-env/translate_service.zo: service.c
+	g++ ${CFLAGS} -shared -fpic -o cgi-env/translate_service.zo ./service.c ${GDAL_LIBS} ${MACOS_LD_FLAGS} -lzoo_service
+
+install:
+	install -d ${CGI_DIR}/gdal/translate
+	install cgi-env/* ${CGI_DIR}/gdal/translate
+
+
+
+clean:
+	rm -f cgi-env/*.zo
diff --git a/zoo-project/zoo-services/gdal/translate/cgi-env/Gdal_Translate.zcfg b/zoo-project/zoo-services/gdal/translate/cgi-env/Gdal_Translate.zcfg
new file mode 100644
index 0000000..3032999
--- /dev/null
+++ b/zoo-project/zoo-services/gdal/translate/cgi-env/Gdal_Translate.zcfg
@@ -0,0 +1,61 @@
+[Gdal_Translate]
+ Title = Convert raster data from one format to another. 
+ Abstract = http://www.gdal.org/gdal_translate.html
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceType = C
+ serviceProvider = translate_service.zo
+ <MetaData>
+   title = My Demo
+ </MetaData>
+ <DataInputs>
+  [Format]
+   Title = Format of the output data
+   Abstract = Select the output format by usig short name of the format (use gda-config --formats for list of available formats on your platform).
+   minOccurs = 0
+   maxOccurs = 1
+   <LiteralData>
+    DataType = string
+    <Default>
+     value = GTiff
+    </Default>
+   </LiteralData>
+  [GCP]
+   Title = Ground Point Control
+   Abstract = Ground Point Control in the form : pixel,line,eating,northing(,elev).
+   minOccurs = 0
+   maxOccurs = unbounded
+   <LiteralData>
+    DataType = string
+    <Default />
+   </LiteralData>
+  [InputDSN]
+   Title = The input data source name
+   Abstract = The input data source name to use as source for convertion.
+   minOccurs = 1
+   maxOccurs = 1
+   <LiteralData>
+    DataType = string
+    <Default />
+   </LiteralData>
+  [OutputDSN]
+   Title = The output data source name
+   Abstract = The output data source name to use as source for convertion.
+   minOccurs = 1
+   maxOccurs = 1
+   <LiteralData>
+    DataType = string
+    <Default />
+   </LiteralData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = The resulting converted file
+   Abstract = The file name resulting of the convertion
+   <LiteralData>
+    DataType = string
+    <Default>
+    </Default>	
+   </LiteralData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/gdal/translate/makefile.vc b/zoo-project/zoo-services/gdal/translate/makefile.vc
new file mode 100644
index 0000000..c296b48
--- /dev/null
+++ b/zoo-project/zoo-services/gdal/translate/makefile.vc
@@ -0,0 +1,23 @@
+TROOT= $(ZOOK_DIR)
+!INCLUDE $(ZOOK_DIR)/nmake.opt
+
+FILES=$(ZOOK_DIR)/service_internal.obj $(ZOOK_DIR)/ulinet.obj 
+!IFDEF JS_DIR
+FILES=$(FILES) $(ZOOK_DIR)$(JS_FILE)
+!ENDIF
+!IFDEF JDK_DIR
+FILES=$(FILES) $(ZOOK_DIR)$(JAVA_FILE)
+!ENDIF
+!IFDEF PY_DIR
+FILES=$(FILES) $(ZOOK_DIR)$(PY_FILE)
+!ENDIF
+!IFDEF MS_DIR
+FILES=$(FILES) $(ZOOK_DIR)$(MS_FILE)
+!ENDIF
+
+cgi-env/translate_service.zo: service.c
+	$(CPP)  /D_CRT_NONSTDC_NO_DEPRECATE -DWIN32 -DZOO_SERVICE -I$(GDAL_DIR)/frmts/vrt $(CFLAGS) /c service.c
+	link /dll /out:cgi-env/translate_service.zo  $(FILES) ./service.obj $(LDFLAGS) /FORCE:MULTIPLE
+
+clean:
+	erase cgi-env\translate_service.*
diff --git a/zoo-project/zoo-services/gdal/translate/service.c b/zoo-project/zoo-services/gdal/translate/service.c
new file mode 100644
index 0000000..3b43c3d
--- /dev/null
+++ b/zoo-project/zoo-services/gdal/translate/service.c
@@ -0,0 +1,925 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GDAL Utilities
+ * Purpose:  GDAL Image Translator Program
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 1998, 2002, Frank Warmerdam
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "cpl_vsi.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "gdal_priv.h"
+#include "ogr_spatialref.h"
+#include "vrtdataset.h"
+
+#include "service.h"
+
+CPL_CVSID("$Id$");
+
+extern "C" {
+
+  static void AttachMetadata( GDALDatasetH, char ** );
+  static int bSubCall = FALSE;
+
+  /************************************************************************/
+  /*                          Gdal_Translate()                            */
+  /************************************************************************/
+
+#ifdef WIN32
+__declspec(dllexport)
+#endif
+  int Gdal_Translate(maps*& conf,maps*& inputs,maps*& outputs)
+  {
+
+
+    GDALDatasetH	hDataset, hOutDS;
+    int			i;
+    int			nRasterXSize, nRasterYSize;
+    const char		*pszSource=NULL, *pszDest=NULL, *pszFormat = "GTiff";
+    GDALDriverH		hDriver;
+    int			*panBandList = NULL, nBandCount = 0, bDefBands = TRUE;
+    double		adfGeoTransform[6];
+    GDALDataType	eOutputType = GDT_Unknown;
+    int			nOXSize = 0, nOYSize = 0;
+    char		*pszOXSize=NULL, *pszOYSize=NULL;
+    char                **papszCreateOptions = NULL;
+    int                 anSrcWin[4], bStrict = FALSE;
+    const char          *pszProjection;
+    int                 bScale = FALSE, bHaveScaleSrc = FALSE;
+    double	        dfScaleSrcMin=0.0, dfScaleSrcMax=255.0;
+    double              dfScaleDstMin=0.0, dfScaleDstMax=255.0;
+    double              dfULX, dfULY, dfLRX, dfLRY;
+    char                **papszMetadataOptions = NULL;
+    char                *pszOutputSRS = NULL;
+    int                 bQuiet = TRUE, bGotBounds = FALSE;
+    GDALProgressFunc    pfnProgress = GDALDummyProgress;
+    int                 nGCPCount = 0;
+    GDAL_GCP            *pasGCPs = NULL;
+    int                 iSrcFileArg = -1, iDstFileArg = -1;
+    int                 bCopySubDatasets = FALSE;
+    double              adfULLR[4] = { 0,0,0,0 };
+    int                 bSetNoData = FALSE;
+    double		dfNoDataReal = 0.0;
+    int                 nRGBExpand = 0;
+
+    anSrcWin[0] = 0;
+    anSrcWin[1] = 0;
+    anSrcWin[2] = 0;
+    anSrcWin[3] = 0;
+
+    dfULX = dfULY = dfLRX = dfLRY = 0.0;
+
+    /* ----------------------------------------------------------------- */
+    /*      Register standard GDAL drivers, and process generic GDAL     */
+    /* ----------------------------------------------------------------- */
+    GDALAllRegister();
+    /* ----------------------------------------------------------------- */
+    /* Extract Format, InputDSN, OutputDSN parameters                    */
+    /* ----------------------------------------------------------------- */
+
+    map* tmpMap=NULL;
+
+    char dataPath[1024];
+    tmpMap=getMapFromMaps(conf,"main","dataPath");
+    if(tmpMap!=NULL)
+      sprintf(dataPath,"%s",tmpMap->value);
+    tmpMap=NULL;
+
+    char tempPath[1024];
+    tmpMap=getMapFromMaps(conf,"main","tmpPath");
+    if(tmpMap!=NULL){
+      sprintf(tempPath,"%s",tmpMap->value);
+    }
+    tmpMap=NULL;
+
+    tmpMap=getMapFromMaps(inputs,"Format","value");
+    if(tmpMap!=NULL){
+      pszFormat=tmpMap->value;
+    }
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"InputDSN","value");
+    if(tmpMap!=NULL){
+      pszSource=(char*)CPLMalloc(sizeof(char)*(strlen(dataPath)+strlen(tmpMap->value)+4));
+      sprintf((char*)pszSource,"%s/%s",dataPath,tmpMap->value);
+    }
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"OutputDSN","value");
+    if(tmpMap!=NULL){
+      pszDest=(char*)CPLMalloc(sizeof(char)*(strlen(tempPath)+strlen(tmpMap->value)+4));
+      char *ext=new char[4];
+      ext="tif";
+      if(strncasecmp(pszFormat,"AAIGRID",7)==0)
+	ext="csv";
+      else 
+	if(strncasecmp(pszFormat,"PNG",3)==0)
+	  ext="png";
+	else
+	  if(strncasecmp(pszFormat,"GIF",3)==0)
+	    ext="gif";
+	  else
+	    if(strncasecmp(pszFormat,"JPEG",4)==0)
+	      ext="jpg";
+      sprintf((char*)pszDest,"%s/%s.%s",tempPath,tmpMap->value,ext);
+      fprintf(stderr,"DEBUG pszDest : %s\n",pszDest);
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"SrcWin","value");
+    if(tmpMap!=NULL){
+      char *tmp=tmpMap->value;
+      char *t=strtok(tmp,",");
+      int cnt=0;
+      while(t!=NULL){
+	anSrcWin[cnt] = atoi(t);
+	t=strtok(NULL,",");
+	cnt++;
+      }
+    }   
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"ProjWin","value");
+    if(tmpMap!=NULL){
+      char *tmp=tmpMap->value;
+      char *t=strtok(tmp,",");
+      int cnt=0;
+      while(t!=NULL){
+	switch(cnt){
+	case 0:
+	  dfULX = atof(t);
+	  break;
+	case 1:
+	  dfULY = atof(t);
+	  break;
+	case 2:
+	  dfLRX = atof(t);
+	  break;
+	case 3:
+	  dfLRY = atof(t);
+	  break;
+	}
+	t=strtok(NULL,",");
+	cnt++;
+      }
+    }
+
+    fprintf(stderr,"DEBUG pszDest : %s %d\n",pszDest,__LINE__);
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"GCP","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0){
+      map* length=getMapFromMaps(inputs,"GCP","length");
+      int len=0;
+      if(length){
+	len=atoi(length->value);
+	int i;
+	maps* currentMaps=getMaps(inputs,"GCP");
+	for(i=0;i<len;i++){
+	  char* endptr = NULL;
+	  /* -gcp pixel line easting northing [elev] */
+	  
+	  nGCPCount++;
+	  pasGCPs = (GDAL_GCP *) 
+	    realloc( pasGCPs, sizeof(GDAL_GCP) * nGCPCount );
+	  GDALInitGCPs( 1, pasGCPs + nGCPCount - 1 );
+
+	  map* currentMap=getMapArray(currentMaps->content,"value",i);
+
+	  char* tmpV=strdup(currentMap->value);
+	  char *res=strtok(tmpV,",");
+	  int j=0;
+	  while(res!=NULL){
+	    switch(j){
+	    case 0:
+	      pasGCPs[nGCPCount-1].dfGCPPixel = CPLAtofM(res);
+	      break;
+	    case 1:
+	      pasGCPs[nGCPCount-1].dfGCPLine = CPLAtofM(res);
+	      break;
+	    case 2:
+	      pasGCPs[nGCPCount-1].dfGCPX = CPLAtofM(res);
+	      break;
+	    case 3:
+	      pasGCPs[nGCPCount-1].dfGCPY = CPLAtofM(res);
+	      break;
+	    case 4:
+	      if(res!=NULL && (strtod(res, &endptr) != 0.0 || res[0] == '0'))
+		if (endptr && *endptr == 0)
+		  pasGCPs[nGCPCount-1].dfGCPZ = CPLAtofM(res);
+	      break;
+	    }
+	    res=strtok(NULL,",");
+	    j++;
+	  }
+	}
+      }else{
+	char* endptr = NULL;
+	/* -gcp pixel line easting northing [elev] */
+	
+	nGCPCount++;
+	pasGCPs = (GDAL_GCP *) 
+	  realloc( pasGCPs, sizeof(GDAL_GCP) * nGCPCount );
+	GDALInitGCPs( 1, pasGCPs + nGCPCount - 1 );
+	
+	char* tmpV=strdup(tmpMap->value);
+	char *res=strtok(tmpV,",");
+	int j=0;
+	while(res!=NULL){
+	  switch(j){
+	  case 0:
+	    pasGCPs[nGCPCount-1].dfGCPPixel = CPLAtofM(res);
+	    break;
+	  case 1:
+	    pasGCPs[nGCPCount-1].dfGCPLine = CPLAtofM(res);
+	    break;
+	  case 2:
+	    pasGCPs[nGCPCount-1].dfGCPX = CPLAtofM(res);
+	    break;
+	  case 3:
+	    pasGCPs[nGCPCount-1].dfGCPY = CPLAtofM(res);
+	    break;
+	  case 4:
+	    if(res!=NULL && (CPLStrtod(res, &endptr) != 0.0 || res[0] == '0'))
+	      if (endptr && *endptr == 0)
+		pasGCPs[nGCPCount-1].dfGCPZ = CPLAtofM(res);
+	    break;
+	  }	    
+	  res=strtok(NULL,",");
+	  j++;
+	}
+      }
+    }
+
+    fprintf(stderr,"DEBUG pszDest : %s %d\n",pszDest,__LINE__);
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"SRS","value");
+    if(tmpMap!=NULL){
+      OGRSpatialReference oOutputSRS;
+      if( oOutputSRS.SetFromUserInput( tmpMap->value ) != OGRERR_NONE )
+	{
+	  char *msg=(char*)CPLMalloc(100*sizeof(char));
+	  sprintf( msg, "Failed to process SRS definition: %s\n", 
+		   tmpMap->value );
+	  setMapInMaps(conf,"lenv","message",msg);
+	  /**
+	   * Avoiding GDALDestroyDriverManager() call
+	   */
+	  return SERVICE_FAILED;
+	}
+      oOutputSRS.exportToWkt( &pszOutputSRS );
+    }
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"Type","value");
+    if(tmpMap!=NULL){
+      int	iType;
+      
+      for( iType = 1; iType < GDT_TypeCount; iType++ )
+	{
+	  if( GDALGetDataTypeName((GDALDataType)iType) != NULL
+	      && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
+		       tmpMap->value) )
+	    {
+	      eOutputType = (GDALDataType) iType;
+	    }
+	}
+      
+      if( eOutputType == GDT_Unknown )
+	{
+	  printf( "Unknown output pixel type: %s\n", tmpMap->value );
+	  /**
+	   * Avoiding GDALDestroyDriverManager() call
+	   */
+	  exit( 2 );
+	}
+    }
+
+    fprintf(stderr,"DEBUG pszDest : %s %d\n",pszDest,__LINE__);
+    if( pszDest == NULL ){
+	fprintf(stderr,"exit line 416");
+	fflush(stderr);
+	/**
+	 * Avoiding GDALDestroyDriverManager() call
+	 */
+        exit( 10 );
+      }
+
+    fprintf(stderr,"DEBUG pszDest : %s %d\n",pszDest,__LINE__);
+    if ( strcmp(pszSource, pszDest) == 0)
+      {
+        fprintf(stderr, "Source and destination datasets must be different.\n");
+	fflush(stderr);
+	/**
+	 * Avoiding GDALDestroyDriverManager() call
+	 */
+        exit( 1 );
+      }
+
+    fprintf(stderr,"DEBUG pszDest : %s %d\n",pszDest,__LINE__);
+    /* ----------------------------------------------------------------- */
+    /*      Attempt to open source file.                                 */
+    /* ----------------------------------------------------------------- */
+
+    hDataset = GDALOpenShared( pszSource, GA_ReadOnly );
+    fprintf(stderr,"DEBUG pszDest : %s %d\n",pszDest,__LINE__);
+    
+    if( hDataset == NULL ){
+      char *msg=(char*) CPLMalloc(1024*sizeof(char));
+      sprintf( msg,
+	       "GDALOpen failed - %d\n%s\n",
+	       CPLGetLastErrorNo(), CPLGetLastErrorMsg() );
+      setMapInMaps(conf,"lenv","message",msg);
+      return SERVICE_FAILED;
+    }
+
+    fprintf(stderr,"DEBUG pszDest : %s %d\n",pszDest,__LINE__);
+    /* ----------------------------------------------------------------- */
+    /*      Handle subdatasets.                                          */
+    /* ----------------------------------------------------------------- */
+    if( !bCopySubDatasets 
+        && CSLCount(GDALGetMetadata( hDataset, "SUBDATASETS" )) > 0 
+        && GDALGetRasterCount(hDataset) == 0 )
+      {
+	char *msg=(char*) CPLMalloc(1024*sizeof(char));
+        sprintf( msg,
+                 "Input file contains subdatasets. Please, select one of them for reading.\n" );
+	setMapInMaps(conf,"lenv","message",msg);
+        GDALClose( hDataset );
+	/**
+	 * Avoiding GDALDestroyDriverManager() call
+	 */
+        exit( 1 );
+      }
+
+    if( CSLCount(GDALGetMetadata( hDataset, "SUBDATASETS" )) > 0 
+        && bCopySubDatasets )
+      {
+        char **papszSubdatasets = GDALGetMetadata(hDataset,"SUBDATASETS");
+        char *pszSubDest = (char *) CPLMalloc(strlen(pszDest)+32);
+        int i;
+        int bOldSubCall = bSubCall;
+        
+        //argv[iDstFileArg] = pszSubDest;
+        bSubCall = TRUE;
+        for( i = 0; papszSubdatasets[i] != NULL; i += 2 )
+	  {
+            //argv[iSrcFileArg] = strstr(papszSubdatasets[i],"=")+1;
+            sprintf( pszSubDest, "%s%d", pszDest, i/2 + 1 );
+            /*if( ProxyMain( argc, argv ) != 0 )
+	      break;*/
+	  }
+        
+        bSubCall = bOldSubCall;
+        free( pszSubDest );
+
+        GDALClose( hDataset );
+
+        if( !bSubCall )
+	  {
+            GDALDumpOpenDatasets( stderr );
+	    fflush(stderr);
+	    /**
+	     * Avoiding GDALDestroyDriverManager() call
+	     */
+	  }
+        return 1;
+      }
+
+    /* ----------------------------------------------------------------- */
+    /*      Collect some information from the source file.               */
+    /* ----------------------------------------------------------------- */
+    nRasterXSize = GDALGetRasterXSize( hDataset );
+    nRasterYSize = GDALGetRasterYSize( hDataset );
+
+    if( !bQuiet )
+      fprintf( stderr, "Input file size is %d, %d\n", nRasterXSize, nRasterYSize );
+
+    if( anSrcWin[2] == 0 && anSrcWin[3] == 0 ){
+        anSrcWin[2] = nRasterXSize;
+        anSrcWin[3] = nRasterYSize;
+      }
+
+    /* ----------------------------------------------------------------- */
+    /*	Build band list to translate	                                 */
+    /* ----------------------------------------------------------------- */
+    if( nBandCount == 0 ){
+        nBandCount = GDALGetRasterCount( hDataset );
+        if( nBandCount == 0 ){
+            fprintf( stderr, "Input file has no bands, and so cannot be translated.\n" );
+	    fflush(stderr);
+	    /**
+	     * Avoiding GDALDestroyDriverManager() call
+	     */
+            exit(1 );
+	  }
+
+        panBandList = (int *) CPLMalloc(sizeof(int)*nBandCount);
+        for( i = 0; i < nBandCount; i++ )
+	  panBandList[i] = i+1;
+      }
+    else
+      {
+        for( i = 0; i < nBandCount; i++ )
+	  {
+            if( panBandList[i] < 1 || panBandList[i] > GDALGetRasterCount(hDataset) )
+	      {
+                fprintf( stderr, 
+                         "Band %d requested, but only bands 1 to %d available.\n",
+                         panBandList[i], GDALGetRasterCount(hDataset) );
+		fflush(stderr);
+		/**
+		 * Avoiding GDALDestroyDriverManager() call
+		 */
+                exit( 2 );
+	      }
+	  }
+
+        if( nBandCount != GDALGetRasterCount( hDataset ) )
+	  bDefBands = FALSE;
+      }
+
+    /* ----------------------------------------------------------------- */
+    /*   Compute the source window from the projected source window      */
+    /*   if the projected coordinates were provided.  Note that the      */
+    /*   projected coordinates are in ulx, uly, lrx, lry format,         */
+    /*   while the anSrcWin is xoff, yoff, xsize, ysize with the         */
+    /*   xoff,yoff being the ulx, uly in pixel/line.                     */
+    /* ----------------------------------------------------------------- */
+    if( dfULX != 0.0 || dfULY != 0.0 
+        || dfLRX != 0.0 || dfLRY != 0.0 )
+      {
+        double	adfGeoTransform[6];
+
+        GDALGetGeoTransform( hDataset, adfGeoTransform );
+
+        if( adfGeoTransform[2] != 0.0 || adfGeoTransform[4] != 0.0 ){
+            fprintf( stderr, 
+                     "The -projwin option was used, but the geotransform is\n"
+                     "rotated.  This configuration is not supported.\n" );
+            GDALClose( hDataset );
+            free( panBandList );
+	    fflush(stderr);
+	    /**
+	     * Avoiding GDALDestroyDriverManager() call
+	     */
+            exit( 1 );
+	  }
+
+        anSrcWin[0] = (int) 
+	  ((dfULX - adfGeoTransform[0]) / adfGeoTransform[1] + 0.001);
+        anSrcWin[1] = (int) 
+	  ((dfULY - adfGeoTransform[3]) / adfGeoTransform[5] + 0.001);
+
+        anSrcWin[2] = (int) ((dfLRX - dfULX) / adfGeoTransform[1] + 0.5);
+        anSrcWin[3] = (int) ((dfLRY - dfULY) / adfGeoTransform[5] + 0.5);
+
+        if( !bQuiet )
+	  fprintf( stdout, 
+		   "Computed -srcwin %d %d %d %d from projected window.\n",
+		   anSrcWin[0], 
+		   anSrcWin[1], 
+		   anSrcWin[2], 
+		   anSrcWin[3] );
+        
+        if( anSrcWin[0] < 0 || anSrcWin[1] < 0 
+            || anSrcWin[0] + anSrcWin[2] > GDALGetRasterXSize(hDataset) 
+            || anSrcWin[1] + anSrcWin[3] > GDALGetRasterYSize(hDataset) )
+	  {
+            fprintf( stderr, 
+                     "Computed -srcwin falls outside raster size of %dx%d.\n",
+                     GDALGetRasterXSize(hDataset), 
+                     GDALGetRasterYSize(hDataset) );
+            exit( 1 );
+	  }
+      }
+
+    /* ----------------------------------------------------------------- */
+    /*      Verify source window.                                        */
+    /* ----------------------------------------------------------------- */
+    if( anSrcWin[0] < 0 || anSrcWin[1] < 0 
+        || anSrcWin[2] <= 0 || anSrcWin[3] <= 0
+        || anSrcWin[0] + anSrcWin[2] > GDALGetRasterXSize(hDataset) 
+        || anSrcWin[1] + anSrcWin[3] > GDALGetRasterYSize(hDataset) )
+      {
+        fprintf( stderr, 
+                 "-srcwin %d %d %d %d falls outside raster size of %dx%d\n"
+                 "or is otherwise illegal.\n",
+                 anSrcWin[0],
+                 anSrcWin[1],
+                 anSrcWin[2],
+                 anSrcWin[3],
+                 GDALGetRasterXSize(hDataset), 
+                 GDALGetRasterYSize(hDataset) );
+        exit( 1 );
+      }
+
+    /* ----------------------------------------------------------------- */
+    /*      Find the output driver.                                      */
+    /* ----------------------------------------------------------------- */
+    hDriver = GDALGetDriverByName( pszFormat );
+    if( hDriver == NULL )
+      {
+        int	iDr;
+        
+	char* msg=(char*) CPLMalloc(4096*sizeof(char));
+	sprintf(msg,"Output driver `%s' not recognised.\nThe following format drivers are configured and support output:\n",pszFormat);
+        for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
+	  {
+            GDALDriverH hDriver = GDALGetDriver(iDr);
+
+            if( GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) != NULL
+                || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY,
+                                        NULL ) != NULL )
+	      {
+		fprintf(stderr,msg);
+		char *tmp=strdup(msg);
+                sprintf( msg,"%s  %s: %s\n",tmp,
+                        GDALGetDriverShortName( hDriver  ),
+                        GDALGetDriverLongName( hDriver ) );
+		free(tmp);
+	      }
+	  }
+	setMapInMaps(conf,"lenv","message",msg);
+        GDALClose( hDataset );
+        free( panBandList );
+	fflush(stderr);
+	/**
+	 * Avoiding GDALDestroyDriverManager() call
+	 */
+        CSLDestroy( papszCreateOptions );
+        return 4;
+      }
+
+    /* ----------------------------------------------------------------- */
+    /*   The short form is to CreateCopy().  We use this if the input    */
+    /*   matches the whole dataset.  Eventually we should rewrite        */
+    /*   this entire program to use virtual datasets to construct a      */
+    /*   virtual input source to copy from.                              */
+    /* ----------------------------------------------------------------- */
+    int bSpatialArrangementPreserved = (
+           anSrcWin[0] == 0 && anSrcWin[1] == 0
+        && anSrcWin[2] == GDALGetRasterXSize(hDataset)
+        && anSrcWin[3] == GDALGetRasterYSize(hDataset)
+        && pszOXSize == NULL && pszOYSize == NULL );
+
+    if( eOutputType == GDT_Unknown 
+        && !bScale && CSLCount(papszMetadataOptions) == 0 && bDefBands 
+        && bSpatialArrangementPreserved
+        && nGCPCount == 0 && !bGotBounds
+        && pszOutputSRS == NULL && !bSetNoData
+        && nRGBExpand == 0)
+      {
+        
+        hOutDS = GDALCreateCopy( hDriver, pszDest, hDataset, 
+                                 FALSE, (char**)0, 
+                                 pfnProgress, NULL );
+
+        if( hOutDS != NULL )
+	  GDALClose( hOutDS );
+        
+        GDALClose( hDataset );
+
+        free( panBandList );
+
+        if( !bSubCall )
+	  {
+            GDALDumpOpenDatasets( stderr );
+	    /**
+	     * Avoiding GDALDestroyDriverManager() call
+	     */
+	  }
+	fprintf(stderr,"==%s %s %s %d==\n",pszFormat,pszSource,pszDest,__LINE__);
+	fflush(stderr);
+
+        CSLDestroy( papszCreateOptions );
+	fprintf(stderr,"==%s %s %s %d==\n",pszFormat,pszSource,pszDest,__LINE__);
+	fflush(stderr);
+	//outputs=(maps*)CPLMalloc(sizeof(maps*));
+	//outputs->name="OutputedPolygon";
+	//outputs->content=createMap("value",(char*)pszDest);
+	//outputs->next=NULL;
+	dumpMaps(outputs);
+	setMapInMaps(outputs,"Result","value",(char*)pszDest);
+	return SERVICE_SUCCEEDED;
+      }
+
+    /* ----------------------------------------------------------------- */
+    /*      Establish some parameters.                                   */
+    /* ----------------------------------------------------------------- */
+    if( pszOXSize == NULL )
+      {
+        nOXSize = anSrcWin[2];
+        nOYSize = anSrcWin[3];
+      }
+    else
+      {
+        nOXSize = (int) ((pszOXSize[strlen(pszOXSize)-1]=='%' 
+                          ? atof(pszOXSize)/100*anSrcWin[2] : atoi(pszOXSize)));
+        nOYSize = (int) ((pszOYSize[strlen(pszOYSize)-1]=='%' 
+                          ? atof(pszOYSize)/100*anSrcWin[3] : atoi(pszOYSize)));
+      }
+
+    /* ================================================================= */
+    /*      Create a virtual dataset.                                    */
+    /* ================================================================= */
+    VRTDataset *poVDS;
+        
+    /* ----------------------------------------------------------------- */
+    /*      Make a virtual clone.                                        */
+    /* ----------------------------------------------------------------- */
+    poVDS = (VRTDataset *) VRTCreate( nOXSize, nOYSize );
+
+    if( nGCPCount == 0 )
+      {
+        if( pszOutputSRS != NULL )
+	  {
+            poVDS->SetProjection( pszOutputSRS );
+	  }
+        else
+	  {
+            pszProjection = GDALGetProjectionRef( hDataset );
+            if( pszProjection != NULL && strlen(pszProjection) > 0 )
+	      poVDS->SetProjection( pszProjection );
+	  }
+      }
+
+    if( bGotBounds )
+      {
+        adfGeoTransform[0] = adfULLR[0];
+        adfGeoTransform[1] = (adfULLR[2] - adfULLR[0]) / nOXSize;
+        adfGeoTransform[2] = 0.0;
+        adfGeoTransform[3] = adfULLR[1];
+        adfGeoTransform[4] = 0.0;
+        adfGeoTransform[5] = (adfULLR[3] - adfULLR[1]) / nOYSize;
+
+        poVDS->SetGeoTransform( adfGeoTransform );
+      }
+
+    else if( GDALGetGeoTransform( hDataset, adfGeoTransform ) == CE_None 
+	     && nGCPCount == 0 )
+      {
+        adfGeoTransform[0] += anSrcWin[0] * adfGeoTransform[1]
+	  + anSrcWin[1] * adfGeoTransform[2];
+        adfGeoTransform[3] += anSrcWin[0] * adfGeoTransform[4]
+	  + anSrcWin[1] * adfGeoTransform[5];
+        
+        adfGeoTransform[1] *= anSrcWin[2] / (double) nOXSize;
+        adfGeoTransform[2] *= anSrcWin[3] / (double) nOYSize;
+        adfGeoTransform[4] *= anSrcWin[2] / (double) nOXSize;
+        adfGeoTransform[5] *= anSrcWin[3] / (double) nOYSize;
+        
+        poVDS->SetGeoTransform( adfGeoTransform );
+      }
+
+    if( nGCPCount != 0 )
+      {
+        const char *pszGCPProjection = pszOutputSRS;
+
+        if( pszGCPProjection == NULL )
+	  pszGCPProjection = GDALGetGCPProjection( hDataset );
+        if( pszGCPProjection == NULL )
+	  pszGCPProjection = "";
+
+        poVDS->SetGCPs( nGCPCount, pasGCPs, pszGCPProjection );
+
+        GDALDeinitGCPs( nGCPCount, pasGCPs );
+        free( pasGCPs );
+      }
+
+    else if( GDALGetGCPCount( hDataset ) > 0 )
+      {
+        GDAL_GCP *pasGCPs;
+        int       nGCPs = GDALGetGCPCount( hDataset );
+
+        pasGCPs = GDALDuplicateGCPs( nGCPs, GDALGetGCPs( hDataset ) );
+
+        for( i = 0; i < nGCPs; i++ )
+	  {
+            pasGCPs[i].dfGCPPixel -= anSrcWin[0];
+            pasGCPs[i].dfGCPLine  -= anSrcWin[1];
+            pasGCPs[i].dfGCPPixel *= (nOXSize / (double) anSrcWin[2] );
+            pasGCPs[i].dfGCPLine  *= (nOYSize / (double) anSrcWin[3] );
+	  }
+            
+        poVDS->SetGCPs( nGCPs, pasGCPs,
+                        GDALGetGCPProjection( hDataset ) );
+
+        GDALDeinitGCPs( nGCPs, pasGCPs );
+        free( pasGCPs );
+      }
+
+    /* ----------------------------------------------------------------- */
+    /*      Transfer generally applicable metadata.                      */
+    /* ----------------------------------------------------------------- */
+    poVDS->SetMetadata( ((GDALDataset*)hDataset)->GetMetadata() );
+    AttachMetadata( (GDALDatasetH) poVDS, papszMetadataOptions );
+
+    /* ----------------------------------------------------------------- */
+    /*      Transfer metadata that remains valid if the spatial          */
+    /*      arrangement of the data is unaltered.                        */
+    /* ----------------------------------------------------------------- */
+    if( anSrcWin[0] == 0 && anSrcWin[1] == 0 
+        && anSrcWin[2] == GDALGetRasterXSize(hDataset)
+        && anSrcWin[3] == GDALGetRasterYSize(hDataset) 
+        && pszOXSize == NULL && pszOYSize == NULL )
+      {
+        char **papszMD;
+
+        papszMD = ((GDALDataset*)hDataset)->GetMetadata("RPC");
+        if( papszMD != NULL )
+	  poVDS->SetMetadata( papszMD, "RPC" );
+      }
+
+    if (nRGBExpand != 0)
+      nBandCount += nRGBExpand - 1;
+
+    /* ================================================================= */
+    /*      Process all bands.                                           */
+    /* ================================================================= */
+    for( i = 0; i < nBandCount; i++ )
+      {
+        VRTSourcedRasterBand   *poVRTBand;
+        GDALRasterBand  *poSrcBand;
+        GDALDataType    eBandType;
+
+        if (nRGBExpand != 0 && i < nRGBExpand)
+	  {
+            poSrcBand = ((GDALDataset *) 
+			 hDataset)->GetRasterBand(panBandList[0]);
+            if (poSrcBand->GetColorTable() == NULL)
+	      {
+                fprintf(stderr, "Error : band %d has no color table\n", panBandList[0]);
+                GDALClose( hDataset );
+                free( panBandList );
+		fflush(stderr);
+		/**
+		 * Avoiding GDALDestroyDriverManager() call
+		 */
+                CSLDestroy( papszCreateOptions );
+                exit( 1 );
+	      }
+	  }
+        else
+	  poSrcBand = ((GDALDataset *) 
+		       hDataset)->GetRasterBand(panBandList[i]);
+
+	/* ------------------------------------------------------------ */
+	/*      Select output data type to match source.                */
+	/* ------------------------------------------------------------ */
+        if( eOutputType == GDT_Unknown )
+	  eBandType = poSrcBand->GetRasterDataType();
+        else
+	  eBandType = eOutputType;
+
+	/* ------------------------------------------------------------ */
+	/*      Create this band.                                       */
+	/* ------------------------------------------------------------ */
+        poVDS->AddBand( eBandType, NULL );
+        poVRTBand = (VRTSourcedRasterBand *) poVDS->GetRasterBand( i+1 );
+            
+	/* ------------------------------------------------------------ */
+	/*      Do we need to collect scaling information?              */
+	/* ------------------------------------------------------------ */
+        double dfScale=1.0, dfOffset=0.0;
+
+        if( bScale && !bHaveScaleSrc )
+	  {
+            double	adfCMinMax[2];
+            GDALComputeRasterMinMax( poSrcBand, TRUE, adfCMinMax );
+            dfScaleSrcMin = adfCMinMax[0];
+            dfScaleSrcMax = adfCMinMax[1];
+	  }
+
+        if( bScale )
+	  {
+            if( dfScaleSrcMax == dfScaleSrcMin )
+	      dfScaleSrcMax += 0.1;
+            if( dfScaleDstMax == dfScaleDstMin )
+	      dfScaleDstMax += 0.1;
+
+            dfScale = (dfScaleDstMax - dfScaleDstMin) 
+	      / (dfScaleSrcMax - dfScaleSrcMin);
+            dfOffset = -1 * dfScaleSrcMin * dfScale + dfScaleDstMin;
+	  }
+
+	/* ------------------------------------------------------------ */
+	/*      Create a simple or complex data source depending on the */
+	/*      translation type required.                              */
+	/* ------------------------------------------------------------ */
+        if( bScale || (nRGBExpand != 0 && i < nRGBExpand) )
+	  {
+            poVRTBand->AddComplexSource( poSrcBand,
+                                         anSrcWin[0], anSrcWin[1], 
+                                         anSrcWin[2], anSrcWin[3], 
+                                         0, 0, nOXSize, nOYSize,
+                                         dfOffset, dfScale,
+                                         VRT_NODATA_UNSET,
+                                         (nRGBExpand != 0 && i < nRGBExpand) ? i + 1 : 0 );
+	  }
+        else
+	  poVRTBand->AddSimpleSource( poSrcBand,
+				      anSrcWin[0], anSrcWin[1], 
+				      anSrcWin[2], anSrcWin[3], 
+				      0, 0, nOXSize, nOYSize );
+
+        /* In case of color table translate, we only set the color interpretation */
+        /* other info copied by CopyCommonInfoFrom are not relevant in RGB expansion */
+        if (nRGBExpand != 0 && i < nRGBExpand)
+	  {
+            poVRTBand->SetColorInterpretation( (GDALColorInterp) (GCI_RedBand + i) );
+	  }
+        else
+	  {
+	    /* --------------------------------------------------------- */
+	    /*      copy over some other information of interest.        */
+	    /* --------------------------------------------------------- */
+            poVRTBand->CopyCommonInfoFrom( poSrcBand );
+	  }
+
+	/* ------------------------------------------------------------- */
+	/*      Set a forcable nodata value?                             */
+	/* ------------------------------------------------------------- */
+        if( bSetNoData )
+	  poVRTBand->SetNoDataValue( dfNoDataReal );
+      }
+
+    /* ----------------------------------------------------------------- */
+    /*      Write to the output file using CopyCreate().                 */
+    /* ----------------------------------------------------------------- */
+    hOutDS = GDALCreateCopy( hDriver, pszDest, (GDALDatasetH) poVDS,
+                             bStrict, papszCreateOptions, 
+                             pfnProgress, NULL );
+
+    if( hOutDS != NULL )
+      {
+        GDALClose( hOutDS );
+      }
+    
+    GDALClose( (GDALDatasetH) poVDS );
+         
+    GDALClose( hDataset );
+   
+    free( panBandList );
+    
+    free( pszOutputSRS );
+
+    if( !bSubCall )
+      {
+        GDALDumpOpenDatasets( stderr );
+	fflush(stderr);
+	/**
+	 * Avoiding GDALDestroyDriverManager() call
+	 */
+      }
+
+    CSLDestroy( papszCreateOptions );
+    
+    setMapInMaps(outputs,"Result","value",(char*)pszDest);
+
+    return SERVICE_SUCCEEDED;
+  }
+
+
+  /************************************************************************/
+  /*                           AttachMetadata()                           */
+  /************************************************************************/
+
+  static void AttachMetadata( GDALDatasetH hDS, char **papszMetadataOptions )
+
+  {
+    int nCount = CSLCount(papszMetadataOptions);
+    int i;
+
+    for( i = 0; i < nCount; i++ )
+      {
+        char    *pszKey = NULL;
+        const char *pszValue;
+        
+        pszValue = CPLParseNameValue( papszMetadataOptions[i], &pszKey );
+        GDALSetMetadataItem(hDS,pszKey,pszValue,NULL);
+        free( pszKey );
+      }
+
+    CSLDestroy( papszMetadataOptions );
+  }
+
+}
diff --git a/zoo-project/zoo-services/gdal/warp/Makefile b/zoo-project/zoo-services/gdal/warp/Makefile
new file mode 100644
index 0000000..f251075
--- /dev/null
+++ b/zoo-project/zoo-services/gdal/warp/Makefile
@@ -0,0 +1,15 @@
+ZRPATH=../../..
+include ${ZRPATH}/zoo-kernel/ZOOMakefile.opts
+CFLAGS=${ZOO_CFLAGS} ${XML2CFLAGS} ${GDAL_CFLAGS} ${PYTHONCFLAGS} -DLINUX_FREE_ISSUE #-DDEBUG
+CC=gcc
+
+cgi-env/warp_service.zo: service.c
+	g++ ${CFLAGS} -shared -fpic -o cgi-env/warp_service.zo ./service.c ${GDAL_LIBS} ${MACOS_LD_FLAGS} -lzoo_service
+
+install:
+	install -d ${CGI_DIR}/gdal/warp
+	install cgi-env/* ${CGI_DIR}/gdal/warp
+
+
+clean:
+	rm -f cgi-env/warp_service.*
diff --git a/zoo-project/zoo-services/gdal/warp/cgi-env/Gdal_Warp.zcfg b/zoo-project/zoo-services/gdal/warp/cgi-env/Gdal_Warp.zcfg
new file mode 100644
index 0000000..bfaf014
--- /dev/null
+++ b/zoo-project/zoo-services/gdal/warp/cgi-env/Gdal_Warp.zcfg
@@ -0,0 +1,129 @@
+[Gdal_Warp]
+ Title = GDAL Warp Tool
+ Abstract = The gdalwarp utility is an image mosaicing, reprojection and warping utility. The program can reproject to any supported projection, and can also apply GCPs stored with the image if the image is "raw" with control information.
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceType = C
+ serviceProvider = warp_service.zo
+ <DataInputs>
+  [Format]
+   Title = Format of the output data
+   Abstract = Select the output format by usig short name of the format (use gda-config --formats for list of available formats on your platform).
+   minOccurs = 0
+   maxOccurs = 1
+   <LiteralData>
+    DataType = string
+    <Default>
+     value = GTiff
+    </Default>
+   </LiteralData>
+  [InputDSN]
+   Title = The input data source name
+   Abstract = The input data source name to use as source for convertion.
+   minOccurs = 1
+   maxOccurs = 1
+   <LiteralData>
+    DataType = string
+    <Default />
+   </LiteralData>
+  [OutputDSN]
+   Title = The output data source name
+   Abstract = The output data source name to use as source for convertion.
+   minOccurs = 1
+   maxOccurs = 1
+   <LiteralData>
+    DataType = string
+    <Default />
+   </LiteralData>
+  [s_srs]
+   Title = The source Spatial reference Set
+   Abstract = The coordinate systems that can be passed are anything supported by the OGRSpatialReference.SetFromUserInput() call, which includes EPSG PCS and GCSes (ie. EPSG:4296), PROJ.4 declarations (as above), or the name of a .prf file containing well known text.
+   minOccurs = 0
+   maxOccurs = 1
+   <LiteralData>
+    DataType = string
+    <Default />
+   </LiteralData>
+  [t_srs]
+   Title = The target Spatial reference Set
+   Abstract = The coordinate systems that can be passed are anything supported by the OGRSpatialReference.SetFromUserInput() call, which includes EPSG PCS and GCSes (ie. EPSG:4296), PROJ.4 declarations (as above), or the name of a .prf file containing well known text.
+   minOccurs = 0
+   maxOccurs = 1
+   <LiteralData>
+    DataType = string
+    <Default />
+   </LiteralData>
+  [tps]
+   Title = Thin Plate Spline
+   Abstract = Force use of thin plate spline transformer based on available GCPs
+   minOccurs = 0
+   maxOccurs = 1
+   <LiteralData>
+    DataType = boolean
+    <Default />
+   </LiteralData>
+  [geoloc]
+   Title = Geolocation
+   Abstract = Force use of Geolocation Arrays
+   minOccurs = 0
+   maxOccurs = 1
+   <LiteralData>
+    DataType = boolean
+    <Default />
+   </LiteralData>
+  [rpc]
+   Title = RPCs
+   Abstract =  Force use of RPCs
+   minOccurs = 0
+   maxOccurs = 1
+   <LiteralData>
+    DataType = boolean
+    <Default />
+   </LiteralData>
+  [r]
+   Title = Resampling method to use
+   Abstract = Available methods are: near (nearest neighbour resampling - default, fastest algorithm, worst interpolation quality), bilinear, cubic, cubicspline, lanczos (Lanczos windowed sinc resampling)
+   minOccurs = 0
+   maxOccurs = 1
+   <LiteralData>
+    DataType = boolean
+    <Default />
+   </LiteralData>
+  [order]
+   Title = The order of polynomial used for warping (1 to 3)
+   Abstract = The default is to select a polynomial order based on the number of GCPs.
+   minOccurs = 0
+   maxOccurs = 1
+   <LiteralData>
+    DataType = string
+    <Default>
+     value=1
+    </Default>
+    <Supported>
+     value=2
+    </Supported>
+    <Supported>
+     value=3
+    </Supported>
+   </LiteralData>
+  [te]
+   Title = xmin,ymin,xmax,ymax
+   Abstract = set georeferenced extents of output file to be created (in target SRS).
+   minOccurs = 0
+   maxOccurs = 1
+   <LiteralData>
+    DataType = string
+    <Default />
+   </LiteralData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = The resulting converted file
+   Abstract = The file name resulting of the convertion
+   <LiteralData>
+    DataType = string
+    <Default>
+    </Default>	
+   </LiteralData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/gdal/warp/makefile.vc b/zoo-project/zoo-services/gdal/warp/makefile.vc
new file mode 100644
index 0000000..269a2b0
--- /dev/null
+++ b/zoo-project/zoo-services/gdal/warp/makefile.vc
@@ -0,0 +1,23 @@
+TROOT= $(ZOOK_DIR)
+!INCLUDE $(ZOOK_DIR)/nmake.opt
+
+FILES=$(ZOOK_DIR)/service_internal.obj $(ZOOK_DIR)/ulinet.obj 
+!IFDEF JS_DIR
+FILES=$(FILES) $(ZOOK_DIR)$(JS_FILE)
+!ENDIF
+!IFDEF JDK_DIR
+FILES=$(FILES) $(ZOOK_DIR)$(JAVA_FILE)
+!ENDIF
+!IFDEF PY_DIR
+FILES=$(FILES) $(ZOOK_DIR)$(PY_FILE)
+!ENDIF
+!IFDEF MS_DIR
+FILES=$(FILES) $(ZOOK_DIR)$(MS_FILE)
+!ENDIF
+
+cgi-env/warp_service.zo: service.c
+	$(CPP)  /DOGR_ENABLED /D_CRT_NONSTDC_NO_DEPRECATE -DWIN32 -DZOO_SERVICE -I$(GDAL_DIR)/frmts/ -I$(GDAL_DIR)/alg/ $(CFLAGS) /c service.c
+	link /dll /out:cgi-env/warp_service.zo  $(FILES) ./service.obj $(LDFLAGS) /FORCE:MULTIPLE
+
+clean:
+	erase cgi-env\warp_service.*
diff --git a/zoo-project/zoo-services/gdal/warp/service.c b/zoo-project/zoo-services/gdal/warp/service.c
new file mode 100644
index 0000000..b110956
--- /dev/null
+++ b/zoo-project/zoo-services/gdal/warp/service.c
@@ -0,0 +1,2150 @@
+/******************************************************************************
+ * $Id: gdalwarp.cpp 24214 2012-04-08 20:17:17Z etourigny $
+ *
+ * Project:  High Performance Image Reprojector
+ * Purpose:  Test program for high performance warper API.
+ * Author:   Frank Warmerdam <warmerdam at pobox.com>
+ *
+ ******************************************************************************
+ * Copyright (c) 2002, i3 - information integration and imaging 
+ *                          Fort Collin, CO
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "gdalwarper.h"
+#include "cpl_string.h"
+#include "ogr_spatialref.h"
+#include "ogr_api.h"
+#include <vector>
+#include "service.h"
+
+CPL_CVSID("$Id: gdalwarp.cpp 24214 2012-04-08 20:17:17Z etourigny $");
+
+extern "C"{
+static void
+LoadCutline( const char *pszCutlineDSName, const char *pszCLayer, 
+             const char *pszCWHERE, const char *pszCSQL, 
+             void **phCutlineRet );
+static void
+TransformCutlineToSource( GDALDatasetH hSrcDS, void *hCutline,
+                          char ***ppapszWarpOptions, char **papszTO );
+
+static GDALDatasetH 
+GDALWarpCreateOutput( maps*& conf,char **papszSrcFiles, const char *pszFilename, 
+                      const char *pszFormat, char **papszTO,
+                      char ***ppapszCreateOptions, GDALDataType eDT,
+                      void ** phTransformArg,
+                      GDALDatasetH* phSrcDS );
+
+static double	       dfMinX=0.0, dfMinY=0.0, dfMaxX=0.0, dfMaxY=0.0;
+static double	       dfXRes=0.0, dfYRes=0.0;
+static int             bTargetAlignedPixels = FALSE;
+static int             nForcePixels=0, nForceLines=0, bQuiet = FALSE;
+static int             bEnableDstAlpha = FALSE, bEnableSrcAlpha = FALSE;
+
+static int             bVRT = FALSE;
+
+/******************************************************************************/
+/*! \page gdalwarp gdalwarp
+
+image reprojection and warping utility
+
+\section gdalwarp_synopsis SYNOPSIS
+
+\htmlonly
+Usage: 
+\endhtmlonly
+
+\verbatim
+gdalwarp [--help-general] [--formats]
+    [-s_srs srs_def] [-t_srs srs_def] [-to "NAME=VALUE"]
+    [-order n | -tps | -rpc | -geoloc] [-et err_threshold]
+    [-refine_gcps tolerance [minimum_gcps]]
+    [-te xmin ymin xmax ymax] [-tr xres yres] [-tap] [-ts width height]
+    [-wo "NAME=VALUE"] [-ot Byte/Int16/...] [-wt Byte/Int16]
+    [-srcnodata "value [value...]"] [-dstnodata "value [value...]"] -dstalpha
+    [-r resampling_method] [-wm memory_in_mb] [-multi] [-q]
+    [-cutline datasource] [-cl layer] [-cwhere expression]
+    [-csql statement] [-cblend dist_in_pixels] [-crop_to_cutline]
+    [-of format] [-co "NAME=VALUE"]* [-overwrite]
+    srcfile* dstfile
+\endverbatim
+
+\section gdalwarp_description DESCRIPTION
+
+<p>
+The gdalwarp utility is an image mosaicing, reprojection and warping
+utility. The program can reproject to any supported projection,
+and can also apply GCPs stored with the image if the image is "raw"
+with control information.
+
+<p>
+<dl>
+<dt> <b>-s_srs</b> <em>srs def</em>:</dt><dd> source spatial reference set.
+The coordinate systems that can be passed are anything supported by the
+OGRSpatialReference.SetFromUserInput() call, which includes EPSG PCS and GCSes
+(ie. EPSG:4296), PROJ.4 declarations (as above), or the name of a .prf file
+containing well known text.</dd>
+<dt> <b>-t_srs</b> <em>srs_def</em>:</dt><dd> target spatial reference set.
+The coordinate systems that can be passed are anything supported by the
+OGRSpatialReference.SetFromUserInput() call, which includes EPSG PCS and GCSes
+(ie. EPSG:4296), PROJ.4 declarations (as above), or the name of a .prf file
+containing well known text.</dd>
+<dt> <b>-to</b> <em>NAME=VALUE</em>:</dt><dd> set a transformer option suitable
+to pass to GDALCreateGenImgProjTransformer2(). </dd>
+<dt> <b>-order</b> <em>n</em>:</dt><dd> order of polynomial used for warping
+(1 to 3). The default is to select a polynomial order based on the number of
+GCPs.</dd>
+<dt> <b>-tps</b>:</dt><dd>Force use of thin plate spline transformer based on
+available GCPs.</dd>
+<dt> <b>-rpc</b>:</dt> <dd>Force use of RPCs.</dd>
+<dt> <b>-geoloc</b>:</dt><dd>Force use of Geolocation Arrays.</dd>
+<dt> <b>-et</b> <em>err_threshold</em>:</dt><dd> error threshold for
+transformation approximation (in pixel units - defaults to 0.125).</dd>
+<dt> <b>-refine_gcps</b> <em>tolerance minimum_gcps</em>:</dt><dd>  (GDAL >= 1.9.0) refines the GCPs by automatically eliminating outliers.
+Outliers will be eliminated until minimum_gcps are left or when no outliers can be detected.
+The tolerance is passed to adjust when a GCP will be eliminated.
+Not that GCP refinement only works with polynomial interpolation.
+The tolerance is in pixel units if no projection is available, otherwise it is in SRS units.
+If minimum_gcps is not provided, the minimum GCPs according to the polynomial model is used.</dd>
+<dt> <b>-te</b> <em>xmin ymin xmax ymax</em>:</dt><dd> set georeferenced
+extents of output file to be created (in target SRS).</dd>
+<dt> <b>-tr</b> <em>xres yres</em>:</dt><dd> set output file resolution (in
+target georeferenced units)</dd>
+<dt> <b>-tap</b>:</dt><dd> (GDAL >= 1.8.0) (target aligned pixels) align
+the coordinates of the extent of the output file to the values of the -tr,
+such that the aligned extent includes the minimum extent.</dd>
+<dt> <b>-ts</b> <em>width height</em>:</dt><dd> set output file size in
+pixels and lines. If width or height is set to 0, the other dimension will be
+guessed from the computed resolution. Note that -ts cannot be used with -tr</dd>
+<dt> <b>-wo</b> <em>"NAME=VALUE"</em>:</dt><dd> Set a warp options.  The 
+GDALWarpOptions::papszWarpOptions docs show all options.  Multiple
+ <b>-wo</b> options may be listed.</dd>
+<dt> <b>-ot</b> <em>type</em>:</dt><dd> For the output bands to be of the
+indicated data type.</dd>
+<dt> <b>-wt</b> <em>type</em>:</dt><dd> Working pixel data type. The data type
+of pixels in the source image and destination image buffers.</dd>
+<dt> <b>-srcnodata</b> <em>value [value...]</em>:</dt><dd> Set nodata masking
+values for input bands (different values can be supplied for each band).  If 
+more than one value is supplied all values should be quoted to keep them 
+together as a single operating system argument.  Masked values will not be 
+used in interpolation.  Use a value of <tt>None</tt> to ignore intrinsic nodata settings on the source dataset.</dd>
+<dt> <b>-dstnodata</b> <em>value [value...]</em>:</dt><dd> Set nodata values
+for output bands (different values can be supplied for each band).  If more
+than one value is supplied all values should be quoted to keep them together
+as a single operating system argument.  New files will be initialized to this
+value and if possible the nodata value will be recorded in the output
+file.</dd>
+<dt> <b>-dstalpha</b>:</dt><dd> Create an output alpha band to identify 
+nodata (unset/transparent) pixels. </dd>
+<dt> <b>-wm</b> <em>memory_in_mb</em>:</dt><dd> Set the amount of memory (in
+megabytes) that the warp API is allowed to use for caching.</dd>
+<dt> <b>-multi</b>:</dt><dd> Use multithreaded warping implementation.
+Multiple threads will be used to process chunks of image and perform
+input/output operation simultaneously.</dd>
+<dt> <b>-q</b>:</dt><dd> Be quiet.</dd>
+<dt> <b>-of</b> <em>format</em>:</dt><dd> Select the output format. The default is GeoTIFF (GTiff). Use the short format name. </dd>
+<dt> <b>-co</b> <em>"NAME=VALUE"</em>:</dt><dd> passes a creation option to
+the output format driver. Multiple <b>-co</b> options may be listed. See
+format specific documentation for legal creation options for each format.
+</dd>
+
+<dt> <b>-cutline</b> <em>datasource</em>:</dt><dd>Enable use of a blend cutline from the name OGR support datasource.</dd>
+<dt> <b>-cl</b> <em>layername</em>:</dt><dd>Select the named layer from the 
+cutline datasource.</dd>
+<dt> <b>-cwhere</b> <em>expression</em>:</dt><dd>Restrict desired cutline features based on attribute query.</dd>
+<dt> <b>-csql</b> <em>query</em>:</dt><dd>Select cutline features using an SQL query instead of from a layer with -cl.</dd>
+<dt> <b>-cblend</b> <em>distance</em>:</dt><dd>Set a blend distance to use to blend over cutlines (in pixels).</dd>
+<dt> <b>-crop_to_cutline</b>:</dt><dd>(GDAL >= 1.8.0) Crop the extent of the target dataset to the extent of the cutline.</dd>
+<dt> <b>-overwrite</b>:</dt><dd>(GDAL >= 1.8.0) Overwrite the target dataset if it already exists.</dd>
+
+<dt> <em>srcfile</em>:</dt><dd> The source file name(s). </dd>
+<dt> <em>dstfile</em>:</dt><dd> The destination file name. </dd>
+</dl>
+
+Mosaicing into an existing output file is supported if the output file 
+already exists. The spatial extent of the existing file will not
+be modified to accomodate new data, so you may have to remove it in that case, or
+use the -overwrite option.
+
+Polygon cutlines may be used as a mask to restrict the area of the destination file
+that may be updated, including blending.  If the OGR layer containing the cutline
+features has no explicit SRS, the cutline features must be in the georeferenced
+units of the destination file. When outputing to a not yet existing target dataset,
+its extent will be the one of the original raster unless -te or -crop_to_cutline are
+specified.
+
+<p>
+\section gdalwarp_example EXAMPLE
+
+For instance, an eight bit spot scene stored in GeoTIFF with
+control points mapping the corners to lat/long could be warped to a UTM
+projection with a command like this:<p>
+
+\verbatim
+gdalwarp -t_srs '+proj=utm +zone=11 +datum=WGS84' raw_spot.tif utm11.tif
+\endverbatim
+
+For instance, the second channel of an ASTER image stored in HDF with
+control points mapping the corners to lat/long could be warped to a UTM
+projection with a command like this:<p>
+
+\verbatim
+gdalwarp HDF4_SDS:ASTER_L1B:"pg-PR1B0000-2002031402_100_001":2 pg-PR1B0000-2002031402_100_001_2.tif
+\endverbatim
+
+\if man
+\section gdalwarp_author AUTHORS
+Frank Warmerdam <warmerdam at pobox.com>, Silke Reimer <silke at intevation.de>
+\endif
+*/
+
+/************************************************************************/
+/*                               GDALExit()                             */
+/*  This function exits and cleans up GDAL and OGR resources            */
+/*  Perhaps it should be added to C api and used in all apps?           */
+/************************************************************************/
+
+static int GDALExit( int nCode )
+{
+  const char  *pszDebug = CPLGetConfigOption("CPL_DEBUG",NULL);
+  if( pszDebug && (EQUAL(pszDebug,"ON") || EQUAL(pszDebug,"") ) )
+  {  
+    GDALDumpOpenDatasets( stderr );
+    CPLDumpSharedList( NULL );
+  }
+
+  GDALDestroyDriverManager();
+
+#ifdef OGR_ENABLED
+  OGRCleanupAll();
+#endif
+
+  return SERVICE_FAILED;
+}
+
+/************************************************************************/
+/*                               Usage()                                */
+/************************************************************************/
+
+static void Usage()
+
+{
+    printf( 
+        "Usage: gdalwarp [--help-general] [--formats]\n"
+        "    [-s_srs srs_def] [-t_srs srs_def] [-to \"NAME=VALUE\"]\n"
+        "    [-order n | -tps | -rpc | -geoloc] [-et err_threshold]\n"
+        "    [-refine_gcps tolerance [minimum_gcps]]\n"
+        "    [-te xmin ymin xmax ymax] [-tr xres yres] [-tap] [-ts width height]\n"
+        "    [-wo \"NAME=VALUE\"] [-ot Byte/Int16/...] [-wt Byte/Int16]\n"
+        "    [-srcnodata \"value [value...]\"] [-dstnodata \"value [value...]\"] -dstalpha\n" 
+        "    [-r resampling_method] [-wm memory_in_mb] [-multi] [-q]\n"
+        "    [-cutline datasource] [-cl layer] [-cwhere expression]\n"
+        "    [-csql statement] [-cblend dist_in_pixels] [-crop_to_cutline]\n"
+        "    [-of format] [-co \"NAME=VALUE\"]* [-overwrite]\n"
+        "    srcfile* dstfile\n"
+        "\n"
+        "Available resampling methods:\n"
+        "    near (default), bilinear, cubic, cubicspline, lanczos.\n" );
+    GDALExit( 1 );
+}
+
+/************************************************************************/
+/*                             SanitizeSRS                              */
+/************************************************************************/
+
+char *SanitizeSRS( const char *pszUserInput )
+
+{
+    OGRSpatialReferenceH hSRS;
+    char *pszResult = NULL;
+
+    CPLErrorReset();
+    
+    hSRS = OSRNewSpatialReference( NULL );
+    if( OSRSetFromUserInput( hSRS, pszUserInput ) == OGRERR_NONE )
+        OSRExportToWkt( hSRS, &pszResult );
+    else
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "Translating source or target SRS failed:\n%s",
+                  pszUserInput );
+        GDALExit( 1 );
+    }
+    
+    OSRDestroySpatialReference( hSRS );
+
+    return pszResult;
+}
+
+/************************************************************************/
+/*                                main()                                */
+/************************************************************************/
+
+#ifdef WIN32
+__declspec(dllexport)
+#endif
+int Gdal_Warp( maps*& conf,maps*& inputs,maps*& outputs )
+
+{
+    GDALDatasetH	hDstDS;
+    const char         *pszFormat = "GTiff";
+    int bFormatExplicitelySet = FALSE;
+    char              **papszSrcFiles = NULL;
+    char               *pszDstFilename = NULL;
+    int                 bCreateOutput = FALSE, i;
+    void               *hTransformArg, *hGenImgProjArg=NULL, *hApproxArg=NULL;
+    char               **papszWarpOptions = NULL;
+    double             dfErrorThreshold = 0.125;
+    double             dfWarpMemoryLimit = 0.0;
+    GDALTransformerFunc pfnTransformer = NULL;
+    char                **papszCreateOptions = NULL;
+    GDALDataType        eOutputType = GDT_Unknown, eWorkingType = GDT_Unknown; 
+    GDALResampleAlg     eResampleAlg = GRA_NearestNeighbour;
+    const char          *pszSrcNodata = NULL;
+    const char          *pszDstNodata = NULL;
+    int                 bMulti = FALSE;
+    char                **papszTO = NULL;
+    char                *pszCutlineDSName = NULL;
+    char                *pszCLayer = NULL, *pszCWHERE = NULL, *pszCSQL = NULL;
+    void                *hCutline = NULL;
+    int                  bHasGotErr = FALSE;
+    int                  bCropToCutline = FALSE;
+    int                  bOverwrite = FALSE;
+
+
+    /* Check that we are running against at least GDAL 1.6 */
+    /* Note to developers : if we use newer API, please change the requirement */
+    if (atoi(GDALVersionInfo("VERSION_NUM")) < 1600)
+    {
+        fprintf(stderr, "At least, GDAL >= 1.6.0 is required for this version of warp_service.zo, "
+                "which was compiled against GDAL %s\n", GDAL_RELEASE_NAME);
+        GDALExit(1);
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Register standard GDAL drivers, and process generic GDAL        */
+/*      command options.                                                */
+/* -------------------------------------------------------------------- */
+    GDALAllRegister();
+
+/* -------------------------------------------------------------------- */
+/*      Parse arguments.                                                */
+/* -------------------------------------------------------------------- */
+    char *dataPath;
+    map* tmpMap=getMapFromMaps(conf,"main","dataPath");
+    if(tmpMap!=NULL)
+      dataPath=strdup(tmpMap->value);
+    tmpMap=NULL;
+
+    char *tempPath;
+    tmpMap=getMapFromMaps(conf,"main","tmpPath");
+    if(tmpMap!=NULL){
+      tempPath=strdup(tmpMap->value);
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"InputDSN","value");
+    if(tmpMap!=NULL){
+      map* length=getMapFromMaps(inputs,"InputDSN","length");
+      if(length!=NULL){
+	int i=0;
+	int len=atoi(length->value);
+	maps* currentMaps=getMaps(inputs,"InputDSN");
+	for(i=0;i<len;i++){
+	  tmpMap=getMapArray(currentMaps->content,"value",i);
+	  papszSrcFiles[i]=(char*)CPLMalloc(sizeof(char)*(strlen(dataPath)+strlen(tmpMap->value)+4));
+	  sprintf((char*)papszSrcFiles[i],"%s/%s",dataPath,tmpMap->value);
+	}
+      }else{
+	char *tmp=(char*)CPLMalloc(sizeof(char)*(strlen(dataPath)+strlen(tmpMap->value)+4));
+	sprintf(tmp,"%s/%s",dataPath,tmpMap->value);
+	papszSrcFiles=CSLAddString( papszSrcFiles, tmp );
+	free(tmp);
+      }
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"OutputDSN","value");
+    if(tmpMap!=NULL){
+      pszDstFilename=(char*)CPLMalloc(sizeof(char)*(strlen(tempPath)+strlen(tmpMap->value)+4));
+      char *ext=new char[4];
+      ext="tif";
+      if(strncasecmp(pszFormat,"AAIGRID",7)==0)
+	ext="csv";
+      else 
+	if(strncasecmp(pszFormat,"PNG",3)==0)
+	  ext="png";
+	else
+	  if(strncasecmp(pszFormat,"GIF",3)==0)
+	    ext="gif";
+	  else
+	    if(strncasecmp(pszFormat,"JPEG",4)==0)
+	      ext="jpg";
+      sprintf(pszDstFilename,"%s/%s.%s",tempPath,tmpMap->value,ext);
+    }
+
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"r","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0 ){
+      if ( EQUAL(tmpMap->value, "near") )
+	eResampleAlg = GRA_NearestNeighbour;
+      else if ( EQUAL(tmpMap->value, "bilinear") )
+	eResampleAlg = GRA_Bilinear;
+      else if ( EQUAL(tmpMap->value, "cubic") )
+	eResampleAlg = GRA_Cubic;
+      else if ( EQUAL(tmpMap->value, "cubicspline") )
+	eResampleAlg = GRA_CubicSpline;
+      else if ( EQUAL(tmpMap->value, "lanczos") )
+	eResampleAlg = GRA_Lanczos;
+      else
+	{
+	  char tmp[1024];
+	  sprintf(tmp,"Unknown resampling method: \"%s\".", tmpMap->value );
+	  setMapInMaps(conf,"lenv","message",tmp);
+	  return SERVICE_FAILED;
+	}
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"t_srs","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0 ){
+      char *pszSRS = SanitizeSRS(tmpMap->value);
+      papszTO = CSLSetNameValue( papszTO, "DST_SRS", pszSRS );
+      CPLFree( pszSRS );
+    }
+
+    tmpMap=getMapFromMaps(inputs,"s_srs","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0 ){
+      char *pszSRS = SanitizeSRS(tmpMap->value);
+      papszTO = CSLSetNameValue( papszTO, "SRC_SRS", pszSRS );
+      CPLFree( pszSRS );
+    }
+
+    tmpMap=getMapFromMaps(inputs,"order","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0 ){
+      const char* pszMethod = CSLFetchNameValue(papszTO, "METHOD");
+      if (pszMethod)
+	fprintf(stderr, "Warning: only one METHOD can be used. Method %s is already defined\n",
+		pszMethod);
+      papszTO = CSLSetNameValue( papszTO, "MAX_GCP_ORDER", tmpMap->value );
+    }
+    
+    tmpMap=getMapFromMaps(inputs,"co","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0 ){
+      papszCreateOptions = CSLAddString( papszCreateOptions, tmpMap->value );
+      bCreateOutput = TRUE;
+    }   
+
+    tmpMap=getMapFromMaps(inputs,"wo","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0 ){
+      papszWarpOptions = CSLAddString( papszWarpOptions, tmpMap->value );
+    }   
+
+    tmpMap=getMapFromMaps(inputs,"multi","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"TRUE",4)==0 ){
+      bMulti = TRUE;
+    }   
+
+    tmpMap=getMapFromMaps(inputs,"dstalpha","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"TRUE",4)==0 ){
+      bEnableDstAlpha = TRUE;
+    }
+
+    tmpMap=getMapFromMaps(inputs,"srcalpha","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"TRUE",4)==0 ){
+      bEnableSrcAlpha = TRUE;
+    }
+
+    tmpMap=getMapFromMaps(inputs,"tap","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"TRUE",4)==0 ){
+      bTargetAlignedPixels = TRUE;
+    }
+
+
+    tmpMap=getMapFromMaps(inputs,"crop_to_cutline","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"TRUE",4)==0 ){
+      bCropToCutline = TRUE;
+      bCreateOutput = TRUE;
+    }
+
+
+    tmpMap=getMapFromMaps(inputs,"tps","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"TRUE",4)==0 ){
+      papszTO = CSLSetNameValue( papszTO, "METHOD", "GCP_TPS" );
+    }
+
+    tmpMap=getMapFromMaps(inputs,"rpc","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"TRUE",4)==0 ){
+      papszTO = CSLSetNameValue( papszTO, "METHOD", "RPC" );
+    }
+
+    tmpMap=getMapFromMaps(inputs,"geoloc","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"TRUE",4)==0 ){
+      papszTO = CSLSetNameValue( papszTO, "METHOD", "GEOLOC_ARRAY" );
+    }
+
+    tmpMap=getMapFromMaps(inputs,"wt","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0 ){
+      int	iType;
+      
+      for( iType = 1; iType < GDT_TypeCount; iType++ )
+	{
+	  if( GDALGetDataTypeName((GDALDataType)iType) != NULL
+	      && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
+		       tmpMap->value) )
+	    {
+	      eWorkingType = (GDALDataType) iType;
+	    }
+	}
+      
+      if( eWorkingType == GDT_Unknown )
+	{
+	  char tmp[1024];
+	  sprintf(tmp,"Unknown output pixel type: %s\n", tmpMap->value );
+	  setMapInMaps(conf,"lenv","message",tmp);
+	  return SERVICE_FAILED;
+	}
+    }
+
+    tmpMap=getMapFromMaps(inputs,"srcnodata","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0 ){
+      pszSrcNodata = strdup(tmpMap->value);
+    }
+
+    tmpMap=getMapFromMaps(inputs,"dstnodata","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0 ){
+      pszDstNodata = strdup(tmpMap->value);
+    }
+
+
+    tmpMap=getMapFromMaps(inputs,"tr","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0 ){
+      char *tmpV=strdup(tmpMap->value);
+      char *res=strtok(tmpV,",");
+      int i=0;
+      while(res!=NULL){
+	if(i==0)
+	  dfXRes = CPLAtofM(res);
+	else
+	  dfYRes = fabs(CPLAtofM(res));
+	res=strtok(NULL,",");
+	i++;
+      }
+      if( dfXRes == 0 || dfYRes == 0 )
+	{
+	  setMapInMaps(conf,"lenv","message","Wrong value for TR parameters");
+	}
+      bCreateOutput = TRUE;
+    }
+
+    tmpMap=getMapFromMaps(inputs,"cblend","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0 ){
+      papszWarpOptions = 
+	CSLSetNameValue( papszWarpOptions, 
+			 "CUTLINE_BLEND_DIST", tmpMap->value );
+    }
+    
+    tmpMap=getMapFromMaps(inputs,"ot","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0 ){
+      int	iType;
+      
+      for( iType = 1; iType < GDT_TypeCount; iType++ )
+	{
+	  if( GDALGetDataTypeName((GDALDataType)iType) != NULL
+	      && EQUAL(GDALGetDataTypeName((GDALDataType)iType),
+		       tmpMap->value) )
+	    {
+	      eOutputType = (GDALDataType) iType;
+	    }
+	}
+
+      if( eOutputType == GDT_Unknown )
+	{
+	  char tmp[128];
+	  sprintf( tmp,"Unknown output pixel type: %s\n", tmpMap->value );
+	  setMapInMaps(conf,"lenv","message",tmp);
+	  return SERVICE_FAILED;
+	}
+      bCreateOutput = TRUE;      
+    }
+
+
+    tmpMap=getMapFromMaps(inputs,"ts","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0 ){
+      char *tmpV=strdup(tmpMap->value);
+      char *res=strtok(tmpV,",");
+      int i=0;
+      while(res!=NULL){
+	if(i==0)
+	  nForcePixels = atoi(res);	  
+	else
+	  nForceLines = atoi(res);	  
+	res=strtok(NULL,",");
+	i++;
+      }
+      free(tmpV);
+      bCreateOutput = TRUE;      
+    }
+
+    tmpMap=getMapFromMaps(inputs,"te","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0 ){
+      char *tmpV=strdup(tmpMap->value);
+      char *res=strtok(tmpV,",");
+      int i=0;
+      while(res!=NULL){
+	switch(i){
+	case 0:
+	  dfMinX = CPLAtofM(res);
+	  break;
+	case 1:
+	  dfMinY = CPLAtofM(res);
+	  break;
+	case 2:
+	  dfMaxX = CPLAtofM(res);
+	  break;
+	case 3:
+	  dfMaxY = CPLAtofM(res);
+	  break;
+	}
+	if(i==0)
+	  nForcePixels = atoi(res);	  
+	else
+	  nForceLines = atoi(res);	  
+	res=strtok(NULL,",");
+	i++;
+      }
+      free(tmpV);
+      bCreateOutput = TRUE;
+    }
+
+    tmpMap=getMapFromMaps(inputs,"te","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0 ){
+      pszCutlineDSName = strdup(tmpMap->value);
+    }
+
+    tmpMap=getMapFromMaps(inputs,"cwhere","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0 ){
+      pszCWHERE = strdup(tmpMap->value);
+    }
+
+    tmpMap=getMapFromMaps(inputs,"cl","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0 ){
+      pszCLayer = strdup(tmpMap->value);
+    }
+
+    tmpMap=getMapFromMaps(inputs,"csql","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0 ){
+      pszCSQL = strdup(tmpMap->value);
+    }
+    
+    tmpMap=getMapFromMaps(inputs,"of","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0 ){
+      pszFormat = strdup(tmpMap->value);
+      bFormatExplicitelySet = TRUE;
+      bCreateOutput = TRUE;
+      if( EQUAL(pszFormat,"VRT") )
+	bVRT = TRUE;
+    }
+
+    tmpMap=getMapFromMaps(inputs,"to","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0 ){
+      papszTO = CSLAddString( papszTO, tmpMap->value );
+    }
+
+    tmpMap=getMapFromMaps(inputs,"et","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0 ){
+      dfErrorThreshold = CPLAtofM(tmpMap->value);
+    }
+    
+
+    tmpMap=getMapFromMaps(inputs,"refine_gpcs","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0 ){
+      char *tmpV=strdup(tmpMap->value);
+      char *res=strtok(tmpV,",");
+      int i=0;
+      while(res!=NULL){
+	if(i==0){
+	  papszTO = CSLSetNameValue( papszTO, "REFINE_TOLERANCE", res );
+	  if(atof(res) < 0){
+	    setMapInMaps(conf,"lenv","message","The tolerance for -refine_gcps may not be negative\n");
+	    return SERVICE_FAILED;
+	  }
+	}else if(i==1){
+	  if(atoi(res) >= 0 && isdigit(res[0]))
+	    papszTO = CSLSetNameValue( papszTO, "REFINE_MINIMUM_GCPS", res );
+	  else
+	    papszTO = CSLSetNameValue( papszTO, "REFINE_MINIMUM_GCPS", "-1" );
+	}
+	res=strtok(NULL,",");
+	i++;
+      }
+    }
+
+    bQuiet = TRUE;
+    
+/* -------------------------------------------------------------------- */
+/*      Check that incompatible options are not used                    */
+/* -------------------------------------------------------------------- */
+
+    if ((nForcePixels != 0 || nForceLines != 0) && 
+        (dfXRes != 0 && dfYRes != 0))
+    {
+      setMapInMaps(conf,"lenv","message","tr and ts options cannot be used at the same time\n");
+      return SERVICE_FAILED;
+    }
+    
+    if (bTargetAlignedPixels && dfXRes == 0 && dfYRes == 0)
+    {
+      setMapInMaps(conf,"lenv","message","tap option cannot be used without using tr");
+      return SERVICE_FAILED;
+    }
+
+
+/* -------------------------------------------------------------------- */
+/*      Does the output dataset already exist?                          */
+/* -------------------------------------------------------------------- */
+
+    /* FIXME ? source filename=target filename and -overwrite is definitely */
+    /* an error. But I can't imagine of a valid case (without -overwrite), */
+    /* where it would make sense. In doubt, let's keep that dubious possibility... */
+    if ( CSLCount(papszSrcFiles) == 1 &&
+         strcmp(papszSrcFiles[0], pszDstFilename) == 0 && bOverwrite)
+    {
+      setMapInMaps(conf,"lenv","message","Source and destination datasets must be different.");
+      return GDALExit(1);
+    }
+
+    CPLPushErrorHandler( CPLQuietErrorHandler );
+    hDstDS = GDALOpen( pszDstFilename, GA_Update );
+    CPLPopErrorHandler();
+
+    if( hDstDS != NULL && bOverwrite )
+    {
+        GDALClose(hDstDS);
+        hDstDS = NULL;
+    }
+
+    if( hDstDS != NULL && bCreateOutput )
+    {
+      char tmp[024];
+      sprintf( tmp, 
+	       "Output dataset %s exists,\n"
+	       "but some commandline options were provided indicating a new dataset\n"
+	       "should be created.  Please delete existing dataset and run again.\n",
+	       pszDstFilename );
+      setMapInMaps(conf,"lenv","message",tmp);
+      return GDALExit(1);
+    }
+
+    /* Avoid overwriting an existing destination file that cannot be opened in */
+    /* update mode with a new GTiff file */
+    if ( hDstDS == NULL && !bOverwrite )
+    {
+        CPLPushErrorHandler( CPLQuietErrorHandler );
+        hDstDS = GDALOpen( pszDstFilename, GA_ReadOnly );
+        CPLPopErrorHandler();
+        
+        if (hDstDS)
+        {
+	  char tmp[1024];
+	  sprintf( tmp, 
+		   "Output dataset %s exists, but cannot be opened in update mode\n",
+		   pszDstFilename );
+	  GDALClose(hDstDS);
+	  setMapInMaps(conf,"lenv","message",tmp);
+	  return GDALExit( 1 );
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      If we have a cutline datasource read it and attach it in the    */
+/*      warp options.                                                   */
+/* -------------------------------------------------------------------- */
+    if( pszCutlineDSName != NULL )
+    {
+        LoadCutline( pszCutlineDSName, pszCLayer, pszCWHERE, pszCSQL,
+                     &hCutline );
+    }
+
+#ifdef OGR_ENABLED
+    if ( bCropToCutline && hCutline != NULL )
+    {
+      
+      
+        OGRGeometryH hCutlineGeom = OGR_G_Clone( (OGRGeometryH) hCutline );
+        OGRSpatialReferenceH hCutlineSRS = OGR_G_GetSpatialReference( hCutlineGeom );
+        const char *pszThisTargetSRS = CSLFetchNameValue( papszTO, "DST_SRS" );
+        OGRCoordinateTransformationH hCT = NULL;
+        if (hCutlineSRS == NULL)
+        {
+            /* We suppose it is in target coordinates */
+        }
+        else if (pszThisTargetSRS != NULL)
+        {
+            OGRSpatialReferenceH hTargetSRS = OSRNewSpatialReference(NULL);
+            if( OSRImportFromWkt( hTargetSRS, (char **)&pszThisTargetSRS ) != CE_None )
+            {
+	      setMapInMaps(conf,"lenv","message","Cannot compute bounding box of cutline.\n");
+                return GDALExit(1);
+            }
+
+            hCT = OCTNewCoordinateTransformation(hCutlineSRS, hTargetSRS);
+
+            OSRDestroySpatialReference(hTargetSRS);
+        }
+        else if (pszThisTargetSRS == NULL)
+        {
+            if (papszSrcFiles[0] != NULL)
+            {
+                GDALDatasetH hSrcDS = GDALOpen(papszSrcFiles[0], GA_ReadOnly);
+                if (hSrcDS == NULL)
+                {
+		  setMapInMaps(conf,"lenv","message","Cannot compute bounding box of cutline.");
+		  return GDALExit(1);
+                }
+
+                OGRSpatialReferenceH  hRasterSRS = NULL;
+                const char *pszProjection = NULL;
+
+                if( GDALGetProjectionRef( hSrcDS ) != NULL
+                    && strlen(GDALGetProjectionRef( hSrcDS )) > 0 )
+                    pszProjection = GDALGetProjectionRef( hSrcDS );
+                else if( GDALGetGCPProjection( hSrcDS ) != NULL )
+                    pszProjection = GDALGetGCPProjection( hSrcDS );
+
+                if( pszProjection == NULL )
+                {
+		  setMapInMaps(conf,"lenv","message","Cannot compute bounding box of cutline.");
+		  return GDALExit(1);
+                }
+
+                hRasterSRS = OSRNewSpatialReference(NULL);
+                if( OSRImportFromWkt( hRasterSRS, (char **)&pszProjection ) != CE_None )
+                {
+		  setMapInMaps(conf,"lenv","message","Cannot compute bounding box of cutline.");
+		  return GDALExit(1);
+                }
+
+                hCT = OCTNewCoordinateTransformation(hCutlineSRS, hRasterSRS);
+
+                OSRDestroySpatialReference(hRasterSRS);
+
+                GDALClose(hSrcDS);
+            }
+            else
+            {
+	      setMapInMaps(conf,"levn","message", "Cannot compute bounding box of cutline.\n");
+	      return GDALExit(1);
+            }
+        }
+
+        if (hCT)
+        {
+            OGR_G_Transform( hCutlineGeom, hCT );
+
+            OCTDestroyCoordinateTransformation(hCT);
+        }
+
+        OGREnvelope sEnvelope;
+        OGR_G_GetEnvelope(hCutlineGeom, &sEnvelope);
+
+        dfMinX = sEnvelope.MinX;
+        dfMinY = sEnvelope.MinY;
+        dfMaxX = sEnvelope.MaxX;
+        dfMaxY = sEnvelope.MaxY;
+        
+        OGR_G_DestroyGeometry(hCutlineGeom);
+    }
+#endif
+    
+/* -------------------------------------------------------------------- */
+/*      If not, we need to create it.                                   */
+/* -------------------------------------------------------------------- */
+    int   bInitDestSetForFirst = FALSE;
+
+    void* hUniqueTransformArg = NULL;
+    GDALDatasetH hUniqueSrcDS = NULL;
+
+    if( hDstDS == NULL )
+    {
+
+      hDstDS = GDALWarpCreateOutput( conf,papszSrcFiles, pszDstFilename,pszFormat,
+                                       papszTO, &papszCreateOptions, 
+                                       eOutputType, &hUniqueTransformArg,
+                                       &hUniqueSrcDS);
+        bCreateOutput = TRUE;
+
+
+        if( CSLFetchNameValue( papszWarpOptions, "INIT_DEST" ) == NULL 
+            && pszDstNodata == NULL )
+        {
+            papszWarpOptions = CSLSetNameValue(papszWarpOptions,
+                                               "INIT_DEST", "0");
+            bInitDestSetForFirst = TRUE;
+        }
+        else if( CSLFetchNameValue( papszWarpOptions, "INIT_DEST" ) == NULL )
+        {
+            papszWarpOptions = CSLSetNameValue(papszWarpOptions,
+                                               "INIT_DEST", "NO_DATA" );
+            bInitDestSetForFirst = TRUE;
+        }
+
+        CSLDestroy( papszCreateOptions );
+        papszCreateOptions = NULL;
+    }
+
+ 
+    if( hDstDS == NULL )
+        GDALExit( 1 );
+
+/* -------------------------------------------------------------------- */
+/*      Loop over all source files, processing each in turn.            */
+/* -------------------------------------------------------------------- */
+    int iSrc;
+
+    for( iSrc = 0; papszSrcFiles[iSrc] != NULL; iSrc++ )
+    {
+        GDALDatasetH hSrcDS;
+       
+/* -------------------------------------------------------------------- */
+/*      Open this file.                                                 */
+/* -------------------------------------------------------------------- */
+        if (hUniqueSrcDS)
+            hSrcDS = hUniqueSrcDS;
+        else
+            hSrcDS = GDALOpen( papszSrcFiles[iSrc], GA_ReadOnly );
+    
+        if( hSrcDS == NULL ){
+	  setMapInMaps(conf,"lenv","message",CPLGetLastErrorMsg());
+	  return GDALExit( 2 );
+	}
+
+/* -------------------------------------------------------------------- */
+/*      Check that there's at least one raster band                     */
+/* -------------------------------------------------------------------- */
+        if ( GDALGetRasterCount(hSrcDS) == 0 )
+        {    
+	  char tmp[1024];
+	  sprintf(tmp, "Input file %s has no raster bands.\n", papszSrcFiles[iSrc] );
+	  setMapInMaps(conf,"lenv","message",tmp);
+	  return GDALExit( 1 );
+        }
+	
+        if( !bQuiet )
+            printf( "Processing input file %s.\n", papszSrcFiles[iSrc] );
+
+/* -------------------------------------------------------------------- */
+/*      Warns if the file has a color table and something more          */
+/*      complicated than nearest neighbour resampling is asked          */
+/* -------------------------------------------------------------------- */
+ 
+	if ( eResampleAlg != GRA_NearestNeighbour &&
+             GDALGetRasterColorTable(GDALGetRasterBand(hSrcDS, 1)) != NULL)
+        {
+                fprintf( stderr, "Warning: Input file %s has a color table, which will likely lead to "
+                        "bad results when using a resampling method other than "
+                        "nearest neighbour. Converting the dataset prior to 24/32 bit "
+                        "is advised.\n", papszSrcFiles[iSrc] );
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Do we have a source alpha band?                                 */
+/* -------------------------------------------------------------------- */
+        if( GDALGetRasterColorInterpretation( 
+                GDALGetRasterBand(hSrcDS,GDALGetRasterCount(hSrcDS)) ) 
+            == GCI_AlphaBand 
+            && !bEnableSrcAlpha )
+        {
+            bEnableSrcAlpha = TRUE;
+            if( !bQuiet )
+                printf( "Using band %d of source image as alpha.\n", 
+                        GDALGetRasterCount(hSrcDS) );
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Create a transformation object from the source to               */
+/*      destination coordinate system.                                  */
+/* -------------------------------------------------------------------- */
+        if (hUniqueTransformArg)
+            hTransformArg = hGenImgProjArg = hUniqueTransformArg;
+        else
+            hTransformArg = hGenImgProjArg =
+                GDALCreateGenImgProjTransformer2( hSrcDS, hDstDS, papszTO );
+
+        if( hTransformArg == NULL ){
+	  setMapInMaps(conf,"lenv","message",CPLGetLastErrorMsg());
+	  return GDALExit( 1 );
+	}
+        
+        pfnTransformer = GDALGenImgProjTransform;
+
+/* -------------------------------------------------------------------- */
+/*      Warp the transformer with a linear approximator unless the      */
+/*      acceptable error is zero.                                       */
+/* -------------------------------------------------------------------- */
+        if( dfErrorThreshold != 0.0 )
+        {
+            hTransformArg = hApproxArg = 
+                GDALCreateApproxTransformer( GDALGenImgProjTransform, 
+                                             hGenImgProjArg, dfErrorThreshold);
+            pfnTransformer = GDALApproxTransform;
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Clear temporary INIT_DEST settings after the first image.       */
+/* -------------------------------------------------------------------- */
+        if( bInitDestSetForFirst && iSrc == 1 )
+            papszWarpOptions = CSLSetNameValue( papszWarpOptions, 
+                                                "INIT_DEST", NULL );
+
+/* -------------------------------------------------------------------- */
+/*      Setup warp options.                                             */
+/* -------------------------------------------------------------------- */
+        GDALWarpOptions *psWO = GDALCreateWarpOptions();
+
+        psWO->papszWarpOptions = CSLDuplicate(papszWarpOptions);
+        psWO->eWorkingDataType = eWorkingType;
+        psWO->eResampleAlg = eResampleAlg;
+
+        psWO->hSrcDS = hSrcDS;
+        psWO->hDstDS = hDstDS;
+
+        psWO->pfnTransformer = pfnTransformer;
+        psWO->pTransformerArg = hTransformArg;
+
+        if( !bQuiet )
+            psWO->pfnProgress = GDALTermProgress;
+
+        if( dfWarpMemoryLimit != 0.0 )
+            psWO->dfWarpMemoryLimit = dfWarpMemoryLimit;
+
+/* -------------------------------------------------------------------- */
+/*      Setup band mapping.                                             */
+/* -------------------------------------------------------------------- */
+        if( bEnableSrcAlpha )
+            psWO->nBandCount = GDALGetRasterCount(hSrcDS) - 1;
+        else
+            psWO->nBandCount = GDALGetRasterCount(hSrcDS);
+
+        psWO->panSrcBands = (int *) CPLMalloc(psWO->nBandCount*sizeof(int));
+        psWO->panDstBands = (int *) CPLMalloc(psWO->nBandCount*sizeof(int));
+
+        for( i = 0; i < psWO->nBandCount; i++ )
+        {
+            psWO->panSrcBands[i] = i+1;
+            psWO->panDstBands[i] = i+1;
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Setup alpha bands used if any.                                  */
+/* -------------------------------------------------------------------- */
+        if( bEnableSrcAlpha )
+            psWO->nSrcAlphaBand = GDALGetRasterCount(hSrcDS);
+
+        if( !bEnableDstAlpha 
+            && GDALGetRasterCount(hDstDS) == psWO->nBandCount+1 
+            && GDALGetRasterColorInterpretation( 
+                GDALGetRasterBand(hDstDS,GDALGetRasterCount(hDstDS))) 
+            == GCI_AlphaBand )
+        {
+            if( !bQuiet )
+                printf( "Using band %d of destination image as alpha.\n", 
+                        GDALGetRasterCount(hDstDS) );
+                
+            bEnableDstAlpha = TRUE;
+        }
+
+        if( bEnableDstAlpha )
+            psWO->nDstAlphaBand = GDALGetRasterCount(hDstDS);
+
+/* -------------------------------------------------------------------- */
+/*      Setup NODATA options.                                           */
+/* -------------------------------------------------------------------- */
+        if( pszSrcNodata != NULL && !EQUALN(pszSrcNodata,"n",1) )
+        {
+            char **papszTokens = CSLTokenizeString( pszSrcNodata );
+            int  nTokenCount = CSLCount(papszTokens);
+
+            psWO->padfSrcNoDataReal = (double *) 
+                CPLMalloc(psWO->nBandCount*sizeof(double));
+            psWO->padfSrcNoDataImag = (double *) 
+                CPLMalloc(psWO->nBandCount*sizeof(double));
+
+            for( i = 0; i < psWO->nBandCount; i++ )
+            {
+                if( i < nTokenCount )
+                {
+                    CPLStringToComplex( papszTokens[i], 
+                                        psWO->padfSrcNoDataReal + i,
+                                        psWO->padfSrcNoDataImag + i );
+                }
+                else
+                {
+                    psWO->padfSrcNoDataReal[i] = psWO->padfSrcNoDataReal[i-1];
+                    psWO->padfSrcNoDataImag[i] = psWO->padfSrcNoDataImag[i-1];
+                }
+            }
+
+            CSLDestroy( papszTokens );
+
+            psWO->papszWarpOptions = CSLSetNameValue(psWO->papszWarpOptions,
+                                               "UNIFIED_SRC_NODATA", "YES" );
+        }
+
+/* -------------------------------------------------------------------- */
+/*      If -srcnodata was not specified, but the data has nodata        */
+/*      values, use them.                                               */
+/* -------------------------------------------------------------------- */
+        if( pszSrcNodata == NULL )
+        {
+            int bHaveNodata = FALSE;
+            double dfReal = 0.0;
+
+            for( i = 0; !bHaveNodata && i < psWO->nBandCount; i++ )
+            {
+                GDALRasterBandH hBand = GDALGetRasterBand( hSrcDS, i+1 );
+                dfReal = GDALGetRasterNoDataValue( hBand, &bHaveNodata );
+            }
+
+            if( bHaveNodata )
+            {
+                if( !bQuiet )
+                {
+                    if (CPLIsNan(dfReal))
+                        printf( "Using internal nodata values (eg. nan) for image %s.\n",
+                                papszSrcFiles[iSrc] );
+                    else
+                        printf( "Using internal nodata values (eg. %g) for image %s.\n",
+                                dfReal, papszSrcFiles[iSrc] );
+                }
+                psWO->padfSrcNoDataReal = (double *) 
+                    CPLMalloc(psWO->nBandCount*sizeof(double));
+                psWO->padfSrcNoDataImag = (double *) 
+                    CPLMalloc(psWO->nBandCount*sizeof(double));
+                
+                for( i = 0; i < psWO->nBandCount; i++ )
+                {
+                    GDALRasterBandH hBand = GDALGetRasterBand( hSrcDS, i+1 );
+
+                    dfReal = GDALGetRasterNoDataValue( hBand, &bHaveNodata );
+
+                    if( bHaveNodata )
+                    {
+                        psWO->padfSrcNoDataReal[i] = dfReal;
+                        psWO->padfSrcNoDataImag[i] = 0.0;
+                    }
+                    else
+                    {
+                        psWO->padfSrcNoDataReal[i] = -123456.789;
+                        psWO->padfSrcNoDataImag[i] = 0.0;
+                    }
+                }
+            }
+        }
+
+/* -------------------------------------------------------------------- */
+/*      If the output dataset was created, and we have a destination    */
+/*      nodata value, go through marking the bands with the information.*/
+/* -------------------------------------------------------------------- */
+        if( pszDstNodata != NULL )
+        {
+            char **papszTokens = CSLTokenizeString( pszDstNodata );
+            int  nTokenCount = CSLCount(papszTokens);
+
+            psWO->padfDstNoDataReal = (double *) 
+                CPLMalloc(psWO->nBandCount*sizeof(double));
+            psWO->padfDstNoDataImag = (double *) 
+                CPLMalloc(psWO->nBandCount*sizeof(double));
+
+            for( i = 0; i < psWO->nBandCount; i++ )
+            {
+                if( i < nTokenCount )
+                {
+                    CPLStringToComplex( papszTokens[i], 
+                                        psWO->padfDstNoDataReal + i,
+                                        psWO->padfDstNoDataImag + i );
+                }
+                else
+                {
+                    psWO->padfDstNoDataReal[i] = psWO->padfDstNoDataReal[i-1];
+                    psWO->padfDstNoDataImag[i] = psWO->padfDstNoDataImag[i-1];
+                }
+                
+                GDALRasterBandH hBand = GDALGetRasterBand( hDstDS, i+1 );
+                int bClamped = FALSE, bRounded = FALSE;
+
+#define CLAMP(val,type,minval,maxval) \
+    do { if (val < minval) { bClamped = TRUE; val = minval; } \
+    else if (val > maxval) { bClamped = TRUE; val = maxval; } \
+    else if (val != (type)val) { bRounded = TRUE; val = (type)(val + 0.5); } } \
+    while(0)
+
+                switch(GDALGetRasterDataType(hBand))
+                {
+                    case GDT_Byte:
+                        CLAMP(psWO->padfDstNoDataReal[i], GByte,
+                              0.0, 255.0);
+                        break;
+                    case GDT_Int16:
+                        CLAMP(psWO->padfDstNoDataReal[i], GInt16,
+                              -32768.0, 32767.0);
+                        break;
+                    case GDT_UInt16:
+                        CLAMP(psWO->padfDstNoDataReal[i], GUInt16,
+                              0.0, 65535.0);
+                        break;
+                    case GDT_Int32:
+                        CLAMP(psWO->padfDstNoDataReal[i], GInt32,
+                              -2147483648.0, 2147483647.0);
+                        break;
+                    case GDT_UInt32:
+                        CLAMP(psWO->padfDstNoDataReal[i], GUInt32,
+                              0.0, 4294967295.0);
+                        break;
+                    default:
+                        break;
+                }
+                    
+                if (bClamped)
+                {
+                    printf( "for band %d, destination nodata value has been clamped "
+                           "to %.0f, the original value being out of range.\n",
+                           i + 1, psWO->padfDstNoDataReal[i]);
+                }
+                else if(bRounded)
+                {
+                    printf("for band %d, destination nodata value has been rounded "
+                           "to %.0f, %s being an integer datatype.\n",
+                           i + 1, psWO->padfDstNoDataReal[i],
+                           GDALGetDataTypeName(GDALGetRasterDataType(hBand)));
+                }
+
+                if( bCreateOutput )
+                {
+                    GDALSetRasterNoDataValue( 
+                        GDALGetRasterBand( hDstDS, psWO->panDstBands[i] ), 
+                        psWO->padfDstNoDataReal[i] );
+                }
+            }
+
+            CSLDestroy( papszTokens );
+        }
+
+/* -------------------------------------------------------------------- */
+/*      If we have a cutline, transform it into the source              */
+/*      pixel/line coordinate system and insert into warp options.      */
+/* -------------------------------------------------------------------- */
+        if( hCutline != NULL )
+        {
+            TransformCutlineToSource( hSrcDS, hCutline, 
+                                      &(psWO->papszWarpOptions), 
+                                      papszTO );
+        }
+
+/* -------------------------------------------------------------------- */
+/*      If we are producing VRT output, then just initialize it with    */
+/*      the warp options and write out now rather than proceeding       */
+/*      with the operations.                                            */
+/* -------------------------------------------------------------------- */
+        if( bVRT )
+        {
+            if( GDALInitializeWarpedVRT( hDstDS, psWO ) != CE_None )
+                GDALExit( 1 );
+
+            GDALClose( hDstDS );
+            GDALClose( hSrcDS );
+
+            /* The warped VRT will clean itself the transformer used */
+            /* So we have only to destroy the hGenImgProjArg if we */
+            /* have wrapped it inside the hApproxArg */
+            if (pfnTransformer == GDALApproxTransform)
+            {
+                if( hGenImgProjArg != NULL )
+                    GDALDestroyGenImgProjTransformer( hGenImgProjArg );
+            }
+
+            GDALDestroyWarpOptions( psWO );
+
+	    setMapInMaps(outputs,"Result","value",pszDstFilename);
+
+            CPLFree( pszDstFilename );
+            CSLDestroy( papszSrcFiles );
+            CSLDestroy( papszWarpOptions );
+            CSLDestroy( papszTO );
+    
+            GDALDumpOpenDatasets( stderr );
+        
+            GDALDestroyDriverManager();
+        
+            return SERVICE_SUCCEEDED;
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Initialize and execute the warp.                                */
+/* -------------------------------------------------------------------- */
+        GDALWarpOperation oWO;
+
+        if( oWO.Initialize( psWO ) == CE_None )
+        {
+            CPLErr eErr;
+            if( bMulti )
+                eErr = oWO.ChunkAndWarpMulti( 0, 0, 
+                                       GDALGetRasterXSize( hDstDS ),
+                                       GDALGetRasterYSize( hDstDS ) );
+            else
+                eErr = oWO.ChunkAndWarpImage( 0, 0, 
+                                       GDALGetRasterXSize( hDstDS ),
+                                       GDALGetRasterYSize( hDstDS ) );
+            if (eErr != CE_None){
+                bHasGotErr = TRUE;
+	    }
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Cleanup                                                         */
+/* -------------------------------------------------------------------- */
+        if( hApproxArg != NULL )
+            GDALDestroyApproxTransformer( hApproxArg );
+        
+        if( hGenImgProjArg != NULL )
+            GDALDestroyGenImgProjTransformer( hGenImgProjArg );
+        
+        GDALDestroyWarpOptions( psWO );
+
+        GDALClose( hSrcDS );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Final Cleanup.                                                  */
+/* -------------------------------------------------------------------- */
+    CPLErrorReset();
+    GDALFlushCache( hDstDS );
+    if( CPLGetLastErrorType() != CE_None )
+        bHasGotErr = TRUE;
+    GDALClose( hDstDS );
+
+    setMapInMaps(outputs,"Result","value",pszDstFilename);
+    
+    CPLFree( pszDstFilename );
+    CSLDestroy( papszSrcFiles );
+    CSLDestroy( papszWarpOptions );
+    CSLDestroy( papszTO );
+
+    GDALDumpOpenDatasets( stderr );
+
+    GDALDestroyDriverManager();
+    
+#ifdef OGR_ENABLED
+    if( hCutline != NULL )
+        OGR_G_DestroyGeometry( (OGRGeometryH) hCutline );
+    OGRCleanupAll();
+#endif
+
+
+/* -------------------------------------------------------------------- */
+/*      Clean allocated arguments.                                      */
+/* -------------------------------------------------------------------- */
+    free(dataPath);
+    free(tempPath);
+
+    tmpMap=getMapFromMaps(inputs,"te","value");
+    if(tmpMap!=NULL){
+      free(pszCutlineDSName);
+    }
+
+    tmpMap=getMapFromMaps(inputs,"cwhere","value");
+    if(tmpMap!=NULL){
+      free(pszCWHERE);
+    }
+
+    tmpMap=getMapFromMaps(inputs,"cl","value");
+    if(tmpMap!=NULL){
+      free(pszCLayer);
+    }
+
+    tmpMap=getMapFromMaps(inputs,"csql","value");
+    if(tmpMap!=NULL){
+      free(pszCSQL);
+    }
+
+    return (bHasGotErr) ? SERVICE_FAILED : SERVICE_SUCCEEDED;
+}
+
+/************************************************************************/
+/*                        GDALWarpCreateOutput()                        */
+/*                                                                      */
+/*      Create the output file based on various commandline options,    */
+/*      and the input file.                                             */
+/*      If there's just one source file, then *phTransformArg and       */
+/*      *phSrcDS will be set, in order them to be reused by main        */
+/*      function. This saves dataset re-opening, and above all transform*/
+/*      recomputation, which can be expensive in the -tps case          */
+/************************************************************************/
+
+static GDALDatasetH 
+GDALWarpCreateOutput( maps*& conf,char **papszSrcFiles, const char *pszFilename, 
+                      const char *pszFormat, char **papszTO, 
+                      char ***ppapszCreateOptions, GDALDataType eDT,
+                      void ** phTransformArg,
+                      GDALDatasetH* phSrcDS)
+
+
+{
+    GDALDriverH hDriver;
+    GDALDatasetH hDstDS;
+    void *hTransformArg;
+    GDALColorTableH hCT = NULL;
+    double dfWrkMinX=0, dfWrkMaxX=0, dfWrkMinY=0, dfWrkMaxY=0;
+    double dfWrkResX=0, dfWrkResY=0;
+    int nDstBandCount = 0;
+    std::vector<GDALColorInterp> apeColorInterpretations;
+
+    *phTransformArg = NULL;
+    *phSrcDS = NULL;
+
+/* -------------------------------------------------------------------- */
+/*      Find the output driver.                                         */
+/* -------------------------------------------------------------------- */
+    hDriver = GDALGetDriverByName( pszFormat );
+    if( hDriver == NULL 
+        || GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) == NULL )
+    {
+        int	iDr;
+        char tmp[2048];
+        sprintf( tmp, "Output driver `%s' not recognised or does not support\n"
+		 "direct output file creation.  The following format drivers are configured\n"
+		 "and support direct output:\n", 
+		 pszFormat );
+
+        for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
+        {
+            GDALDriverH hDriver = GDALGetDriver(iDr);
+
+            if( GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL) != NULL )
+            {
+	      char *_tmp=strdup(tmp);
+	      sprintf( tmp,"%s  %s: %s\n",
+		       _tmp,
+		       GDALGetDriverShortName( hDriver  ),
+		       GDALGetDriverLongName( hDriver ) );
+	      free(_tmp);
+            }
+        }
+	setMapInMaps(conf,"lenv","message",tmp);
+        GDALExit( 1 );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      For virtual output files, we have to set a special subclass     */
+/*      of dataset to create.                                           */
+/* -------------------------------------------------------------------- */
+    if( bVRT )
+        *ppapszCreateOptions = 
+            CSLSetNameValue( *ppapszCreateOptions, "SUBCLASS", 
+                             "VRTWarpedDataset" );
+
+/* -------------------------------------------------------------------- */
+/*      Loop over all input files to collect extents.                   */
+/* -------------------------------------------------------------------- */
+    int     iSrc;
+    char    *pszThisTargetSRS = (char*)CSLFetchNameValue( papszTO, "DST_SRS" );
+    if( pszThisTargetSRS != NULL )
+        pszThisTargetSRS = CPLStrdup( pszThisTargetSRS );
+
+    for( iSrc = 0; papszSrcFiles[iSrc] != NULL; iSrc++ )
+    {
+        GDALDatasetH hSrcDS;
+        const char *pszThisSourceSRS = CSLFetchNameValue(papszTO,"SRC_SRS");
+
+        hSrcDS = GDALOpen( papszSrcFiles[iSrc], GA_ReadOnly );
+        if( hSrcDS == NULL )
+            GDALExit( 1 );
+
+/* -------------------------------------------------------------------- */
+/*      Check that there's at least one raster band                     */
+/* -------------------------------------------------------------------- */
+        if ( GDALGetRasterCount(hSrcDS) == 0 )
+        {
+            fprintf(stderr, "Input file %s has no raster bands.\n", papszSrcFiles[iSrc] );
+            GDALExit( 1 );
+        }
+
+        if( eDT == GDT_Unknown )
+            eDT = GDALGetRasterDataType(GDALGetRasterBand(hSrcDS,1));
+
+/* -------------------------------------------------------------------- */
+/*      If we are processing the first file, and it has a color         */
+/*      table, then we will copy it to the destination file.            */
+/* -------------------------------------------------------------------- */
+        if( iSrc == 0 )
+        {
+            nDstBandCount = GDALGetRasterCount(hSrcDS);
+            hCT = GDALGetRasterColorTable( GDALGetRasterBand(hSrcDS,1) );
+            if( hCT != NULL )
+            {
+                hCT = GDALCloneColorTable( hCT );
+                if( !bQuiet )
+                    printf( "Copying color table from %s to new file.\n", 
+                            papszSrcFiles[iSrc] );
+            }
+
+            for(int iBand = 0; iBand < nDstBandCount; iBand++)
+            {
+                apeColorInterpretations.push_back(
+                    GDALGetRasterColorInterpretation(GDALGetRasterBand(hSrcDS,iBand+1)) );
+            }
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Get the sourcesrs from the dataset, if not set already.         */
+/* -------------------------------------------------------------------- */
+        if( pszThisSourceSRS == NULL )
+        {
+            const char *pszMethod = CSLFetchNameValue( papszTO, "METHOD" );
+
+            if( GDALGetProjectionRef( hSrcDS ) != NULL 
+                && strlen(GDALGetProjectionRef( hSrcDS )) > 0
+                && (pszMethod == NULL || EQUAL(pszMethod,"GEOTRANSFORM")) )
+                pszThisSourceSRS = GDALGetProjectionRef( hSrcDS );
+            
+            else if( GDALGetGCPProjection( hSrcDS ) != NULL
+                     && strlen(GDALGetGCPProjection(hSrcDS)) > 0 
+                     && GDALGetGCPCount( hSrcDS ) > 1 
+                     && (pszMethod == NULL || EQUALN(pszMethod,"GCP_",4)) )
+                pszThisSourceSRS = GDALGetGCPProjection( hSrcDS );
+            else if( pszMethod != NULL && EQUAL(pszMethod,"RPC") )
+                pszThisSourceSRS = SRS_WKT_WGS84;
+            else
+                pszThisSourceSRS = "";
+        }
+
+        if( pszThisTargetSRS == NULL )
+            pszThisTargetSRS = CPLStrdup( pszThisSourceSRS );
+        
+/* -------------------------------------------------------------------- */
+/*      Create a transformation object from the source to               */
+/*      destination coordinate system.                                  */
+/* -------------------------------------------------------------------- */
+        hTransformArg = 
+            GDALCreateGenImgProjTransformer2( hSrcDS, NULL, papszTO );
+        
+        if( hTransformArg == NULL )
+        {
+            CPLFree( pszThisTargetSRS );
+            GDALClose( hSrcDS );
+            return NULL;
+        }
+        
+        GDALTransformerInfo* psInfo = (GDALTransformerInfo*)hTransformArg;
+
+/* -------------------------------------------------------------------- */
+/*      Get approximate output definition.                              */
+/* -------------------------------------------------------------------- */
+        double adfThisGeoTransform[6];
+        double adfExtent[4];
+        int    nThisPixels, nThisLines;
+
+        if( GDALSuggestedWarpOutput2( hSrcDS, 
+                                      psInfo->pfnTransform, hTransformArg, 
+                                      adfThisGeoTransform, 
+                                      &nThisPixels, &nThisLines, 
+                                      adfExtent, 0 ) != CE_None )
+        {
+            CPLFree( pszThisTargetSRS );
+            GDALClose( hSrcDS );
+            return NULL;
+        }
+        
+        if (CPLGetConfigOption( "CHECK_WITH_INVERT_PROJ", NULL ) == NULL)
+        {
+            double MinX = adfExtent[0];
+            double MaxX = adfExtent[2];
+            double MaxY = adfExtent[3];
+            double MinY = adfExtent[1];
+            int bSuccess = TRUE;
+            
+            /* Check that the the edges of the target image are in the validity area */
+            /* of the target projection */
+#define N_STEPS 20
+            int i,j;
+            for(i=0;i<=N_STEPS && bSuccess;i++)
+            {
+                for(j=0;j<=N_STEPS && bSuccess;j++)
+                {
+                    double dfRatioI = i * 1.0 / N_STEPS;
+                    double dfRatioJ = j * 1.0 / N_STEPS;
+                    double expected_x = (1 - dfRatioI) * MinX + dfRatioI * MaxX;
+                    double expected_y = (1 - dfRatioJ) * MinY + dfRatioJ * MaxY;
+                    double x = expected_x;
+                    double y = expected_y;
+                    double z = 0;
+                    /* Target SRS coordinates to source image pixel coordinates */
+                    if (!psInfo->pfnTransform(hTransformArg, TRUE, 1, &x, &y, &z, &bSuccess) || !bSuccess)
+                        bSuccess = FALSE;
+                    /* Source image pixel coordinates to target SRS coordinates */
+                    if (!psInfo->pfnTransform(hTransformArg, FALSE, 1, &x, &y, &z, &bSuccess) || !bSuccess)
+                        bSuccess = FALSE;
+                    if (fabs(x - expected_x) > (MaxX - MinX) / nThisPixels ||
+                        fabs(y - expected_y) > (MaxY - MinY) / nThisLines)
+                        bSuccess = FALSE;
+                }
+            }
+            
+            /* If not, retry with CHECK_WITH_INVERT_PROJ=TRUE that forces ogrct.cpp */
+            /* to check the consistency of each requested projection result with the */
+            /* invert projection */
+            if (!bSuccess)
+            {
+                CPLSetConfigOption( "CHECK_WITH_INVERT_PROJ", "TRUE" );
+                CPLDebug("WARP", "Recompute out extent with CHECK_WITH_INVERT_PROJ=TRUE");
+
+                if( GDALSuggestedWarpOutput2( hSrcDS, 
+                                      psInfo->pfnTransform, hTransformArg, 
+                                      adfThisGeoTransform, 
+                                      &nThisPixels, &nThisLines, 
+                                      adfExtent, 0 ) != CE_None )
+                {
+                    CPLFree( pszThisTargetSRS );
+                    GDALClose( hSrcDS );
+                    return NULL;
+                }
+            }
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Expand the working bounds to include this region, ensure the    */
+/*      working resolution is no more than this resolution.             */
+/* -------------------------------------------------------------------- */
+        if( dfWrkMaxX == 0.0 && dfWrkMinX == 0.0 )
+        {
+            dfWrkMinX = adfExtent[0];
+            dfWrkMaxX = adfExtent[2];
+            dfWrkMaxY = adfExtent[3];
+            dfWrkMinY = adfExtent[1];
+            dfWrkResX = adfThisGeoTransform[1];
+            dfWrkResY = ABS(adfThisGeoTransform[5]);
+        }
+        else
+        {
+            dfWrkMinX = MIN(dfWrkMinX,adfExtent[0]);
+            dfWrkMaxX = MAX(dfWrkMaxX,adfExtent[2]);
+            dfWrkMaxY = MAX(dfWrkMaxY,adfExtent[3]);
+            dfWrkMinY = MIN(dfWrkMinY,adfExtent[1]);
+            dfWrkResX = MIN(dfWrkResX,adfThisGeoTransform[1]);
+            dfWrkResY = MIN(dfWrkResY,ABS(adfThisGeoTransform[5]));
+        }
+
+        if (iSrc == 0 && papszSrcFiles[1] == NULL)
+        {
+            *phTransformArg = hTransformArg;
+            *phSrcDS = hSrcDS;
+        }
+        else
+        {
+            GDALDestroyGenImgProjTransformer( hTransformArg );
+            GDALClose( hSrcDS );
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Did we have any usable sources?                                 */
+/* -------------------------------------------------------------------- */
+    if( nDstBandCount == 0 )
+    {
+        CPLError( CE_Failure, CPLE_AppDefined,
+                  "No usable source images." );
+        CPLFree( pszThisTargetSRS );
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Turn the suggested region into a geotransform and suggested     */
+/*      number of pixels and lines.                                     */
+/* -------------------------------------------------------------------- */
+    double adfDstGeoTransform[6];
+    int nPixels, nLines;
+
+    adfDstGeoTransform[0] = dfWrkMinX;
+    adfDstGeoTransform[1] = dfWrkResX;
+    adfDstGeoTransform[2] = 0.0;
+    adfDstGeoTransform[3] = dfWrkMaxY;
+    adfDstGeoTransform[4] = 0.0;
+    adfDstGeoTransform[5] = -1 * dfWrkResY;
+
+    nPixels = (int) ((dfWrkMaxX - dfWrkMinX) / dfWrkResX + 0.5);
+    nLines = (int) ((dfWrkMaxY - dfWrkMinY) / dfWrkResY + 0.5);
+
+/* -------------------------------------------------------------------- */
+/*      Did the user override some parameters?                          */
+/* -------------------------------------------------------------------- */
+    if( dfXRes != 0.0 && dfYRes != 0.0 )
+    {
+        if( dfMinX == 0.0 && dfMinY == 0.0 && dfMaxX == 0.0 && dfMaxY == 0.0 )
+        {
+            dfMinX = adfDstGeoTransform[0];
+            dfMaxX = adfDstGeoTransform[0] + adfDstGeoTransform[1] * nPixels;
+            dfMaxY = adfDstGeoTransform[3];
+            dfMinY = adfDstGeoTransform[3] + adfDstGeoTransform[5] * nLines;
+        }
+        
+        if ( bTargetAlignedPixels )
+        {
+            dfMinX = floor(dfMinX / dfXRes) * dfXRes;
+            dfMaxX = ceil(dfMaxX / dfXRes) * dfXRes;
+            dfMinY = floor(dfMinY / dfYRes) * dfYRes;
+            dfMaxY = ceil(dfMaxY / dfYRes) * dfYRes;
+        }
+
+        nPixels = (int) ((dfMaxX - dfMinX + (dfXRes/2.0)) / dfXRes);
+        nLines = (int) ((dfMaxY - dfMinY + (dfYRes/2.0)) / dfYRes);
+        adfDstGeoTransform[0] = dfMinX;
+        adfDstGeoTransform[3] = dfMaxY;
+        adfDstGeoTransform[1] = dfXRes;
+        adfDstGeoTransform[5] = -dfYRes;
+    }
+
+    else if( nForcePixels != 0 && nForceLines != 0 )
+    {
+        if( dfMinX == 0.0 && dfMinY == 0.0 && dfMaxX == 0.0 && dfMaxY == 0.0 )
+        {
+            dfMinX = dfWrkMinX;
+            dfMaxX = dfWrkMaxX;
+            dfMaxY = dfWrkMaxY;
+            dfMinY = dfWrkMinY;
+        }
+
+        dfXRes = (dfMaxX - dfMinX) / nForcePixels;
+        dfYRes = (dfMaxY - dfMinY) / nForceLines;
+
+        adfDstGeoTransform[0] = dfMinX;
+        adfDstGeoTransform[3] = dfMaxY;
+        adfDstGeoTransform[1] = dfXRes;
+        adfDstGeoTransform[5] = -dfYRes;
+
+        nPixels = nForcePixels;
+        nLines = nForceLines;
+    }
+
+    else if( nForcePixels != 0 )
+    {
+        if( dfMinX == 0.0 && dfMinY == 0.0 && dfMaxX == 0.0 && dfMaxY == 0.0 )
+        {
+            dfMinX = dfWrkMinX;
+            dfMaxX = dfWrkMaxX;
+            dfMaxY = dfWrkMaxY;
+            dfMinY = dfWrkMinY;
+        }
+
+        dfXRes = (dfMaxX - dfMinX) / nForcePixels;
+        dfYRes = dfXRes;
+
+        adfDstGeoTransform[0] = dfMinX;
+        adfDstGeoTransform[3] = dfMaxY;
+        adfDstGeoTransform[1] = dfXRes;
+        adfDstGeoTransform[5] = -dfYRes;
+
+        nPixels = nForcePixels;
+        nLines = (int) ((dfMaxY - dfMinY + (dfYRes/2.0)) / dfYRes);
+    }
+
+    else if( nForceLines != 0 )
+    {
+        if( dfMinX == 0.0 && dfMinY == 0.0 && dfMaxX == 0.0 && dfMaxY == 0.0 )
+        {
+            dfMinX = dfWrkMinX;
+            dfMaxX = dfWrkMaxX;
+            dfMaxY = dfWrkMaxY;
+            dfMinY = dfWrkMinY;
+        }
+
+        dfYRes = (dfMaxY - dfMinY) / nForceLines;
+        dfXRes = dfYRes;
+
+        adfDstGeoTransform[0] = dfMinX;
+        adfDstGeoTransform[3] = dfMaxY;
+        adfDstGeoTransform[1] = dfXRes;
+        adfDstGeoTransform[5] = -dfYRes;
+
+        nPixels = (int) ((dfMaxX - dfMinX + (dfXRes/2.0)) / dfXRes);
+        nLines = nForceLines;
+    }
+
+    else if( dfMinX != 0.0 || dfMinY != 0.0 || dfMaxX != 0.0 || dfMaxY != 0.0 )
+    {
+        dfXRes = adfDstGeoTransform[1];
+        dfYRes = fabs(adfDstGeoTransform[5]);
+
+        nPixels = (int) ((dfMaxX - dfMinX + (dfXRes/2.0)) / dfXRes);
+        nLines = (int) ((dfMaxY - dfMinY + (dfYRes/2.0)) / dfYRes);
+
+        dfXRes = (dfMaxX - dfMinX) / nPixels;
+        dfYRes = (dfMaxY - dfMinY) / nLines;
+
+        adfDstGeoTransform[0] = dfMinX;
+        adfDstGeoTransform[3] = dfMaxY;
+        adfDstGeoTransform[1] = dfXRes;
+        adfDstGeoTransform[5] = -dfYRes;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Do we want to generate an alpha band in the output file?        */
+/* -------------------------------------------------------------------- */
+    if( bEnableSrcAlpha )
+        nDstBandCount--;
+
+    if( bEnableDstAlpha )
+        nDstBandCount++;
+
+/* -------------------------------------------------------------------- */
+/*      Create the output file.                                         */
+/* -------------------------------------------------------------------- */
+    if( !bQuiet )
+        printf( "Creating output file that is %dP x %dL.\n", nPixels, nLines );
+
+    hDstDS = GDALCreate( hDriver, pszFilename, nPixels, nLines, 
+                         nDstBandCount, eDT, *ppapszCreateOptions );
+    
+    if( hDstDS == NULL )
+    {
+        CPLFree( pszThisTargetSRS );
+        return NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Write out the projection definition.                            */
+/* -------------------------------------------------------------------- */
+    GDALSetProjection( hDstDS, pszThisTargetSRS );
+    GDALSetGeoTransform( hDstDS, adfDstGeoTransform );
+
+    if (*phTransformArg != NULL)
+        GDALSetGenImgProjTransformerDstGeoTransform( *phTransformArg, adfDstGeoTransform);
+
+/* -------------------------------------------------------------------- */
+/*      Try to set color interpretation of source bands to target       */
+/*      dataset.                                                        */
+/*      FIXME? We should likely do that for other drivers than VRT      */
+/*      but it might create spurious .aux.xml files (at least with HFA, */
+/*      and netCDF)                                                     */
+/* -------------------------------------------------------------------- */
+    if( bVRT )
+    {
+        int nBandsToCopy = (int)apeColorInterpretations.size();
+        if ( bEnableSrcAlpha )
+            nBandsToCopy --;
+        for(int iBand = 0; iBand < nBandsToCopy; iBand++)
+        {
+            GDALSetRasterColorInterpretation(
+                GDALGetRasterBand( hDstDS, iBand + 1 ),
+                apeColorInterpretations[iBand] );
+        }
+    }
+    
+/* -------------------------------------------------------------------- */
+/*      Try to set color interpretation of output file alpha band.      */
+/* -------------------------------------------------------------------- */
+    if( bEnableDstAlpha )
+    {
+        GDALSetRasterColorInterpretation( 
+            GDALGetRasterBand( hDstDS, nDstBandCount ), 
+            GCI_AlphaBand );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Copy the color table, if required.                              */
+/* -------------------------------------------------------------------- */
+    if( hCT != NULL )
+    {
+        GDALSetRasterColorTable( GDALGetRasterBand(hDstDS,1), hCT );
+        GDALDestroyColorTable( hCT );
+    }
+
+    CPLFree( pszThisTargetSRS );
+    return hDstDS;
+}
+
+/************************************************************************/
+/*                      GeoTransform_Transformer()                      */
+/*                                                                      */
+/*      Convert points from georef coordinates to pixel/line based      */
+/*      on a geotransform.                                              */
+/************************************************************************/
+
+class CutlineTransformer : public OGRCoordinateTransformation
+{
+public:
+
+    void         *hSrcImageTransformer;
+
+    virtual OGRSpatialReference *GetSourceCS() { return NULL; }
+    virtual OGRSpatialReference *GetTargetCS() { return NULL; }
+
+    virtual int Transform( int nCount, 
+                           double *x, double *y, double *z = NULL ) {
+        int nResult;
+
+        int *pabSuccess = (int *) CPLCalloc(sizeof(int),nCount);
+        nResult = TransformEx( nCount, x, y, z, pabSuccess );
+        CPLFree( pabSuccess );
+
+        return nResult;
+    }
+
+    virtual int TransformEx( int nCount, 
+                             double *x, double *y, double *z = NULL,
+                             int *pabSuccess = NULL ) {
+        return GDALGenImgProjTransform( hSrcImageTransformer, TRUE, 
+                                        nCount, x, y, z, pabSuccess );
+    }
+};
+
+
+/************************************************************************/
+/*                            LoadCutline()                             */
+/*                                                                      */
+/*      Load blend cutline from OGR datasource.                         */
+/************************************************************************/
+
+static void
+LoadCutline( const char *pszCutlineDSName, const char *pszCLayer, 
+             const char *pszCWHERE, const char *pszCSQL, 
+             void **phCutlineRet )
+
+{
+#ifndef OGR_ENABLED
+    CPLError( CE_Failure, CPLE_AppDefined, 
+              "Request to load a cutline failed, this build does not support OGR features.\n" );
+    GDALExit( 1 );
+#else // def OGR_ENABLED
+    OGRRegisterAll();
+
+/* -------------------------------------------------------------------- */
+/*      Open source vector dataset.                                     */
+/* -------------------------------------------------------------------- */
+    OGRDataSourceH hSrcDS;
+
+    hSrcDS = OGROpen( pszCutlineDSName, FALSE, NULL );
+    if( hSrcDS == NULL )
+        GDALExit( 1 );
+
+/* -------------------------------------------------------------------- */
+/*      Get the source layer                                            */
+/* -------------------------------------------------------------------- */
+    OGRLayerH hLayer = NULL;
+
+    if( pszCSQL != NULL )
+        hLayer = OGR_DS_ExecuteSQL( hSrcDS, pszCSQL, NULL, NULL ); 
+    else if( pszCLayer != NULL )
+        hLayer = OGR_DS_GetLayerByName( hSrcDS, pszCLayer );
+    else
+        hLayer = OGR_DS_GetLayer( hSrcDS, 0 );
+
+    if( hLayer == NULL )
+    {
+        fprintf( stderr, "Failed to identify source layer from datasource.\n" );
+        GDALExit( 1 );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Apply WHERE clause if there is one.                             */
+/* -------------------------------------------------------------------- */
+    if( pszCWHERE != NULL )
+        OGR_L_SetAttributeFilter( hLayer, pszCWHERE );
+
+/* -------------------------------------------------------------------- */
+/*      Collect the geometries from this layer, and build list of       */
+/*      burn values.                                                    */
+/* -------------------------------------------------------------------- */
+    OGRFeatureH hFeat;
+    OGRGeometryH hMultiPolygon = OGR_G_CreateGeometry( wkbMultiPolygon );
+
+    OGR_L_ResetReading( hLayer );
+    
+    while( (hFeat = OGR_L_GetNextFeature( hLayer )) != NULL )
+    {
+        OGRGeometryH hGeom = OGR_F_GetGeometryRef(hFeat);
+
+        if( hGeom == NULL )
+        {
+            fprintf( stderr, "ERROR: Cutline feature without a geometry.\n" );
+            GDALExit( 1 );
+        }
+        
+        OGRwkbGeometryType eType = wkbFlatten(OGR_G_GetGeometryType( hGeom ));
+
+        if( eType == wkbPolygon )
+            OGR_G_AddGeometry( hMultiPolygon, hGeom );
+        else if( eType == wkbMultiPolygon )
+        {
+            int iGeom;
+
+            for( iGeom = 0; iGeom < OGR_G_GetGeometryCount( hGeom ); iGeom++ )
+            {
+                OGR_G_AddGeometry( hMultiPolygon, 
+                                   OGR_G_GetGeometryRef(hGeom,iGeom) );
+            }
+        }
+        else
+        {
+            fprintf( stderr, "ERROR: Cutline not of polygon type.\n" );
+            GDALExit( 1 );
+        }
+
+        OGR_F_Destroy( hFeat );
+    }
+
+    if( OGR_G_GetGeometryCount( hMultiPolygon ) == 0 )
+    {
+        fprintf( stderr, "ERROR: Did not get any cutline features.\n" );
+        GDALExit( 1 );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Ensure the coordinate system gets set on the geometry.          */
+/* -------------------------------------------------------------------- */
+    OGR_G_AssignSpatialReference(
+        hMultiPolygon, OGR_L_GetSpatialRef(hLayer) );
+
+    *phCutlineRet = (void *) hMultiPolygon;
+
+/* -------------------------------------------------------------------- */
+/*      Cleanup                                                         */
+/* -------------------------------------------------------------------- */
+    if( pszCSQL != NULL )
+        OGR_DS_ReleaseResultSet( hSrcDS, hLayer );
+
+    OGR_DS_Destroy( hSrcDS );
+#endif
+}
+
+/************************************************************************/
+/*                      TransformCutlineToSource()                      */
+/*                                                                      */
+/*      Transform cutline from its SRS to source pixel/line coordinates.*/
+/************************************************************************/
+static void
+TransformCutlineToSource( GDALDatasetH hSrcDS, void *hCutline,
+                          char ***ppapszWarpOptions, char **papszTO_In )
+
+{
+#ifdef OGR_ENABLED
+    OGRGeometryH hMultiPolygon = OGR_G_Clone( (OGRGeometryH) hCutline );
+    char **papszTO = CSLDuplicate( papszTO_In );
+
+/* -------------------------------------------------------------------- */
+/*      Checkout that SRS are the same.                                 */
+/* -------------------------------------------------------------------- */
+    OGRSpatialReferenceH  hRasterSRS = NULL;
+    const char *pszProjection = NULL;
+
+    if( GDALGetProjectionRef( hSrcDS ) != NULL 
+        && strlen(GDALGetProjectionRef( hSrcDS )) > 0 )
+        pszProjection = GDALGetProjectionRef( hSrcDS );
+    else if( GDALGetGCPProjection( hSrcDS ) != NULL )
+        pszProjection = GDALGetGCPProjection( hSrcDS );
+
+    if( pszProjection != NULL )
+    {
+        hRasterSRS = OSRNewSpatialReference(NULL);
+        if( OSRImportFromWkt( hRasterSRS, (char **)&pszProjection ) != CE_None )
+        {
+            OSRDestroySpatialReference(hRasterSRS);
+            hRasterSRS = NULL;
+        }
+    }
+
+    OGRSpatialReferenceH hCutlineSRS = OGR_G_GetSpatialReference( hMultiPolygon );
+    if( hRasterSRS != NULL && hCutlineSRS != NULL )
+    {
+        /* ok, we will reproject */
+    }
+    else if( hRasterSRS != NULL && hCutlineSRS == NULL )
+    {
+        fprintf(stderr,
+                "Warning : the source raster dataset has a SRS, but the cutline features\n"
+                "not.  We assume that the cutline coordinates are expressed in the destination SRS.\n"
+                "If not, cutline results may be incorrect.\n");
+    }
+    else if( hRasterSRS == NULL && hCutlineSRS != NULL )
+    {
+        fprintf(stderr,
+                "Warning : the input vector layer has a SRS, but the source raster dataset does not.\n"
+                "Cutline results may be incorrect.\n");
+    }
+
+    if( hRasterSRS != NULL )
+        OSRDestroySpatialReference(hRasterSRS);
+
+/* -------------------------------------------------------------------- */
+/*      Extract the cutline SRS WKT.                                    */
+/* -------------------------------------------------------------------- */
+    if( hCutlineSRS != NULL )
+    {
+        char *pszCutlineSRS_WKT = NULL;
+
+        OSRExportToWkt( hCutlineSRS, &pszCutlineSRS_WKT );
+        papszTO = CSLSetNameValue( papszTO, "DST_SRS", pszCutlineSRS_WKT );
+        CPLFree( pszCutlineSRS_WKT );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      It may be unwise to let the mask geometry be re-wrapped by      */
+/*      the CENTER_LONG machinery as this can easily screw up world     */
+/*      spanning masks and invert the mask topology.                    */
+/* -------------------------------------------------------------------- */
+    papszTO = CSLSetNameValue( papszTO, "INSERT_CENTER_LONG", "FALSE" );
+
+/* -------------------------------------------------------------------- */
+/*      Transform the geometry to pixel/line coordinates.               */
+/* -------------------------------------------------------------------- */
+    CutlineTransformer oTransformer;
+
+    /* The cutline transformer will *invert* the hSrcImageTransformer */
+    /* so it will convert from the cutline SRS to the source pixel/line */
+    /* coordinates */
+    oTransformer.hSrcImageTransformer = 
+        GDALCreateGenImgProjTransformer2( hSrcDS, NULL, papszTO );
+
+    CSLDestroy( papszTO );
+
+    if( oTransformer.hSrcImageTransformer == NULL )
+        GDALExit( 1 );
+
+    OGR_G_Transform( hMultiPolygon, 
+                     (OGRCoordinateTransformationH) &oTransformer );
+
+    GDALDestroyGenImgProjTransformer( oTransformer.hSrcImageTransformer );
+
+/* -------------------------------------------------------------------- */
+/*      Convert aggregate geometry into WKT.                            */
+/* -------------------------------------------------------------------- */
+    char *pszWKT = NULL;
+
+    OGR_G_ExportToWkt( hMultiPolygon, &pszWKT );
+    OGR_G_DestroyGeometry( hMultiPolygon );
+
+    *ppapszWarpOptions = CSLSetNameValue( *ppapszWarpOptions, 
+                                          "CUTLINE", pszWKT );
+    CPLFree( pszWKT );
+#endif
+}
+
+}
diff --git a/zoo-project/zoo-services/hello-fortran/LICENSE b/zoo-project/zoo-services/hello-fortran/LICENSE
new file mode 100644
index 0000000..3c27d92
--- /dev/null
+++ b/zoo-project/zoo-services/hello-fortran/LICENSE
@@ -0,0 +1,21 @@
+ZOO-Kernel License
+
+Copyright (c) 2009-2013 GeoLabs SARL
+
+Permission is hereby granted, free of charge, to any person obtaining a copy 
+of this software and associated documentation files (the “Software”), to deal
+in the Software without restriction, including without limitation the rights 
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
+copies of the Software, and to permit persons to whom the Software is 
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies of this Software or works derived from this Software.
+
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
\ No newline at end of file
diff --git a/zoo-project/zoo-services/hello-fortran/Makefile b/zoo-project/zoo-services/hello-fortran/Makefile
new file mode 100644
index 0000000..86b6bde
--- /dev/null
+++ b/zoo-project/zoo-services/hello-fortran/Makefile
@@ -0,0 +1,5 @@
+cgi-env/service.zo: servive.for
+	gfortran -shared -fpic -o cgi-env/fortran_hello.zo ./service.f
+
+clean:
+	rm -f cgi-env/*.zo
diff --git a/zoo-project/zoo-services/hello-fortran/cgi-env/hellof.zcfg b/zoo-project/zoo-services/hello-fortran/cgi-env/hellof.zcfg
new file mode 100755
index 0000000..faaa98c
--- /dev/null
+++ b/zoo-project/zoo-services/hello-fortran/cgi-env/hellof.zcfg
@@ -0,0 +1,40 @@
+[hellof]
+ Title = Hello string
+ Abstract = Create a welcome message.
+ Profile = urn:ogc:wps:1.0.0:buffer
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = driftx_service.zo
+ serviceType = C-FORTRAN
+ <MetaData>
+   title = Demo
+ </MetaData>
+ <DataInputs>
+  [S]
+   Title = The string
+   Abstract = The name to display in the welcome message.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <LiteralData>
+    DataType = string
+    <Default>
+    </Default>
+   </LiteralData>
+ </DataInputs>
+ <DataOutputs>
+  [result]
+   Title = The string
+   Abstract = The string created by service.
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <LiteralData>
+    DataType = string
+    <Default>
+    </Default>
+   </LiteralData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/hello-fortran/service.f b/zoo-project/zoo-services/hello-fortran/service.f
new file mode 100644
index 0000000..0aa123c
--- /dev/null
+++ b/zoo-project/zoo-services/hello-fortran/service.f
@@ -0,0 +1,44 @@
+ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
+c     Simply create a welcome message
+ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
+       Integer FUNCTION HELLOF(zoo_main_cfg,zoo_inputs,zoo_outputs)
+     & RESULT (R)
+       Integer R, ls, iLenStr
+       CHARACTER*(1024) zoo_main_cfg(10,30),zoo_inputs(10,30),
+     & zoo_outputs(10,30)
+        CHARACTER*(1024) TMP
+
+       write(0,*) 'Hello '//zoo_inputs(4,1)//' from the Fortran world !'
+
+       ls = iLenStr(zoo_inputs(4,1))
+       TMP = zoo_inputs(4,1)
+       zoo_outputs(1,1) = 'name'//CHAR(0)
+       zoo_outputs(2,1) = 'result'//CHAR(0)
+       zoo_outputs(3,1) = 'value'//CHAR(0)
+       zoo_outputs(4,1) = 'Hello '//TMP(1:ls)//
+     & ' from the Fortran world !'//CHAR(0)
+       zoo_outputs(5,1) = 'datatype'//CHAR(0)
+       zoo_outputs(6,1) = 'string'//CHAR(0)
+
+       R = 3
+       Return
+       END
+
+       Integer Function iLenStr(cString)
+ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
+c     Compute String Length (thanks to Abdelatif Djerboua from RHEA™)
+ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc
+       Character*(*) cString
+       Integer       iLen,i
+
+      iLen = Len(cString)
+      Do i=iLen,1,-1
+         If(ichar(cString(i:i)).NE.0) Goto 10
+      EndDo
+      i = 1
+  10  Continue
+      iLenStr = i
+
+      Return
+      End Function iLenStr
+
diff --git a/zoo-project/zoo-services/hello-java/HelloJava.java b/zoo-project/zoo-services/hello-java/HelloJava.java
new file mode 100644
index 0000000..9680fa1
--- /dev/null
+++ b/zoo-project/zoo-services/hello-java/HelloJava.java
@@ -0,0 +1,53 @@
+/**
+ * Author : Gérald FENOY
+ *
+ *  Copyright 2008-2009 GeoLabs SARL. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+import java.lang.*;
+import java.util.*;
+
+public class HelloJava {
+    public static int HelloWorldJava(HashMap conf,HashMap inputs, HashMap outputs) {
+        HashMap tmp=(HashMap)(inputs.get("S"));
+        String v=tmp.get("value").toString();
+        HashMap hm1 = (HashMap)(outputs.get("Result"));
+        hm1.put("value",ZOO._("Hello "+v+" from JAVA World !!"));
+        return ZOO.SERVICE_SUCCEEDED;
+    }
+    public static int JavaLongProcess(HashMap conf,HashMap inputs, HashMap outputs) {
+        HashMap tmp=(HashMap)(inputs.get("S"));
+        String v=tmp.get("value").toString();
+	Integer i;
+	for(i=0;i<100;i+=5){
+	    ZOO.updateStatus(conf,String.valueOf(i),"Currently executing tasks "+String.valueOf(i/5)+"..");
+	    try{
+		Thread.sleep(2000);
+	    }catch(java.lang.InterruptedException e){
+	    }finally{
+	    }
+	}
+        HashMap hm1 = (HashMap)(outputs.get("Result"));
+        hm1.put("value",ZOO._("Hello "+v+" from JAVA World !!"));
+        return ZOO.SERVICE_SUCCEEDED;
+    }
+}
+
diff --git a/zoo-project/zoo-services/hello-java/Makefile b/zoo-project/zoo-services/hello-java/Makefile
new file mode 100644
index 0000000..52dbb19
--- /dev/null
+++ b/zoo-project/zoo-services/hello-java/Makefile
@@ -0,0 +1,5 @@
+cgi-env/HelloJava.class: HelloJava.java
+	javac -d cgi-env -cp ../../zoo-api/java/ HelloJava.java 
+
+clean:
+	rm cgi-env/*class
diff --git a/zoo-project/zoo-services/hello-java/cgi-env/HelloWorldJava.zcfg b/zoo-project/zoo-services/hello-java/cgi-env/HelloWorldJava.zcfg
new file mode 100755
index 0000000..a6afbc9
--- /dev/null
+++ b/zoo-project/zoo-services/hello-java/cgi-env/HelloWorldJava.zcfg
@@ -0,0 +1,33 @@
+[HelloWorldJava]
+ Title = Display a string
+ Abstract = Display a string which contains an hello message
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = HelloJava
+ serviceType = Java
+ <MetaData>
+   title = Demo
+ </MetaData>
+ <DataInputs>
+  [S]
+   Title = the string
+   Abstract = The string to add to the hellow one.
+   minOccurs = 1
+   maxOccurs = 1
+   <LiteralData>
+    DataType = string
+    <Default>
+    </Default>
+   </LiteralData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = The hello string
+   Abstract = The Hello message string.
+   <LiteralOutput>
+    DataType = string
+    <Default>
+    </Default>
+   </LiteralOutput>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/hello-java/cgi-env/JavaLongProcess.zcfg b/zoo-project/zoo-services/hello-java/cgi-env/JavaLongProcess.zcfg
new file mode 100644
index 0000000..4cba89e
--- /dev/null
+++ b/zoo-project/zoo-services/hello-java/cgi-env/JavaLongProcess.zcfg
@@ -0,0 +1,33 @@
+[JavaLongProcess]
+ Title = Display a string
+ Abstract = Display a string which contains an hello message after waiting many times to illustrate the way you can use updateStatus ZOO-API function from your Java service
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = HelloJava
+ serviceType = Java
+ <MetaData>
+   title = Demo
+ </MetaData>
+ <DataInputs>
+  [S]
+   Title = the string
+   Abstract = The string to add to the hellow one.
+   minOccurs = 1
+   maxOccurs = 1
+   <LiteralData>
+    DataType = string
+    <Default>
+    </Default>
+   </LiteralData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = The hello string
+   Abstract = The Hello message string.
+   <LiteralOutput>
+    DataType = string
+    <Default>
+    </Default>
+   </LiteralOutput>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/hello-js/cgi-env/hello.js b/zoo-project/zoo-services/hello-js/cgi-env/hello.js
new file mode 100644
index 0000000..c14f764
--- /dev/null
+++ b/zoo-project/zoo-services/hello-js/cgi-env/hello.js
@@ -0,0 +1,36 @@
+/**
+ * Author : Gérald FENOY
+ *
+ * Copyright 2009-2013 GeoLabs SARL. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+function hellojs(conf,inputs,outputs){
+	outputs["result"]["value"]="Hello "+inputs["S"]["value"]+" from the JS World !";
+	//SERVICE_SUCEEDED
+	return Array(3,outputs);
+}
+
+function hellojs1(conf,inputs,outputs){
+	outputs["result"]["value"]="Hello "+inputs["S"]["value"]+" from the JS World !";
+	//SERVICE_SUCEEDED
+	return {"result":3,"outputs": outputs};
+}
+
diff --git a/zoo-project/zoo-services/hello-js/cgi-env/hellojs.zcfg b/zoo-project/zoo-services/hello-js/cgi-env/hellojs.zcfg
new file mode 100755
index 0000000..414aa42
--- /dev/null
+++ b/zoo-project/zoo-services/hello-js/cgi-env/hellojs.zcfg
@@ -0,0 +1,40 @@
+[hellojs]
+ Title = HelloWorld Service in JavaScript
+ Abstract = Output and Hello Wolrd string
+ Profile = urn:ogc:wps:1.0.0:buffer
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = hello.js
+ serviceType = JS
+ <MetaData>
+   title = Demo
+ </MetaData>
+ <DataInputs>
+  [S]
+   Title = Name
+   Abstract = The name to display in the hello message
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <LiteralData>
+    dataType = string
+    <Default>
+    </Default>
+   </LiteralData>
+ </DataInputs>
+ <DataOutputs>
+  [result]
+   Title = The resulting string
+   Abstract = The string created by service.
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <LiteralOutput>
+     dataType = string
+     <Default>
+     </Default>
+   </LiteralOutput>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/hello-js/cgi-env/hellojs1.zcfg b/zoo-project/zoo-services/hello-js/cgi-env/hellojs1.zcfg
new file mode 100755
index 0000000..17009c1
--- /dev/null
+++ b/zoo-project/zoo-services/hello-js/cgi-env/hellojs1.zcfg
@@ -0,0 +1,40 @@
+[hellojs1]
+ Title = HelloWorld Service in JavaScript
+ Abstract = Output and Hello Wolrd string
+ Profile = urn:ogc:wps:1.0.0:buffer
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = hello.js
+ serviceType = JS
+ <MetaData>
+   title = Demo
+ </MetaData>
+ <DataInputs>
+  [S]
+   Title = Name
+   Abstract = The name to display in the hello message
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <LiteralData>
+    dataType = string
+    <Default>
+    </Default>
+   </LiteralData>
+ </DataInputs>
+ <DataOutputs>
+  [result]
+   Title = The resulting string
+   Abstract = The string created by service.
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <LiteralOutput>
+     dataType = string
+    <Default>
+    </Default>
+   </LiteralOutput>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/hello-perl/Hello.pl b/zoo-project/zoo-services/hello-perl/Hello.pl
new file mode 100644
index 0000000..baae954
--- /dev/null
+++ b/zoo-project/zoo-services/hello-perl/Hello.pl
@@ -0,0 +1,32 @@
+#
+# Author : David Saggiorato
+#
+# Copyright 2009-2013 GeoLabs SARL. All rights reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including with
+# out limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+sub HelloPL {
+	my ($main_conf,$real_inputs,$real_outputs) = @_;
+	
+	$real_outputs->{"Result"}->{"value"}=$real_inputs->{"a"}->{"value"};
+	return 3;
+}
+
diff --git a/zoo-project/zoo-services/hello-perl/cgi-env/HelloPL.zcfg b/zoo-project/zoo-services/hello-perl/cgi-env/HelloPL.zcfg
new file mode 100644
index 0000000..dda3cb9
--- /dev/null
+++ b/zoo-project/zoo-services/hello-perl/cgi-env/HelloPL.zcfg
@@ -0,0 +1,39 @@
+[HelloPL]
+ Title = Create a welcome message string.
+ Abstract = Create a welcome string.
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = Hello.pl
+ serviceType = Perl
+ <MetaData>
+   title = Demo
+ </MetaData>
+ <DataInputs>
+  [a]
+   Title = Input string
+   Abstract = The name to display in the welcome message.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData>
+    title = My test
+   </MetaData>
+   <LiteralData>
+    DataType = string
+    <Default>
+    </Default>
+   </LiteralData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = The welcome message
+   Abstract = The welcome message created by service.
+   <MetaData>
+    title = My test
+   </MetaData>
+   <LiteralData>
+    DataType = string
+    <Default>
+    </Default>
+   </LiteralData>
+ </DataOutputs>
diff --git a/zoo-project/zoo-services/hello-php/cgi-env/HelloPHP.zcfg b/zoo-project/zoo-services/hello-php/cgi-env/HelloPHP.zcfg
new file mode 100644
index 0000000..acb476a
--- /dev/null
+++ b/zoo-project/zoo-services/hello-php/cgi-env/HelloPHP.zcfg
@@ -0,0 +1,33 @@
+[HelloPHP]
+ Title = Display a string
+ Abstract = Display a string which contains an hello message
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = hello.php
+ serviceType = PHP
+ <MetaData>
+   title = Demo
+ </MetaData>
+ <DataInputs>
+  [S]
+   Title = the string
+   Abstract = The string to add to the hellow one.
+   minOccurs = 1
+   maxOccurs = 1
+   <LiteralData>
+    DataType = string
+    <Default>
+    </Default>
+   </LiteralData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = The hello string
+   Abstract = The Hello message string.
+   <LiteralOutput>
+    DataType = string
+    <Default>
+    </Default>
+   </LiteralOutput>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/hello-php/cgi-env/hello.php b/zoo-project/zoo-services/hello-php/cgi-env/hello.php
new file mode 100644
index 0000000..03b4aff
--- /dev/null
+++ b/zoo-project/zoo-services/hello-php/cgi-env/hello.php
@@ -0,0 +1,34 @@
+<?
+
+/**
+ * Author : Gérald FENOY
+ *
+ * Copyright 2009-20013 GeoLabs SARL. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+function HelloPHP(&$main_conf,&$inputs,&$outputs){
+  $tmp="Hello ".$inputs["S"]["value"]." from the PHP world !!";
+  $outputs["Result"]["value"]=zoo_Translate($tmp);
+  zoo_UpdateStatus($main_conf,"Final step",99);
+  return zoo_SERVICE_SUCCEEDED();
+}
+
+?>
diff --git a/zoo-project/zoo-services/hello-py/cgi-env/HelloPy.zcfg b/zoo-project/zoo-services/hello-py/cgi-env/HelloPy.zcfg
new file mode 100755
index 0000000..7969406
--- /dev/null
+++ b/zoo-project/zoo-services/hello-py/cgi-env/HelloPy.zcfg
@@ -0,0 +1,47 @@
+[HelloPy]
+ Title = Create a welcome message string.
+ Abstract = Create a welcome string.
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = test_service
+ serviceType = Python
+ <MetaData>
+   title = Demo
+ </MetaData>
+ <DataInputs>
+  [a]
+   Title = Input string
+   Abstract = The name to display in the welcome message.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData>
+    title = My test
+   </MetaData>
+   <LiteralData>
+    DataType = string
+    <Default>
+     UOM = meter
+    </Default>
+    <Supported>
+     UOM = meter
+    </Supported>
+   </LiteralData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = The welcome message
+   Abstract = The welcome message created by service.
+   <MetaData>
+    title = My test
+   </MetaData>
+   <LiteralData>
+    DataType = string
+    <Default>
+     UOM = meter
+    </Default>
+    <Supported>
+     UOM = meter
+    </Supported>
+   </LiteralData>
+ </DataOutputs>
diff --git a/zoo-project/zoo-services/hello-py/cgi-env/test_service.py b/zoo-project/zoo-services/hello-py/cgi-env/test_service.py
new file mode 100644
index 0000000..be35875
--- /dev/null
+++ b/zoo-project/zoo-services/hello-py/cgi-env/test_service.py
@@ -0,0 +1,31 @@
+# -*- coding: utf-8 -*-
+#
+# Author : Gérald FENOY
+#
+# Copyright 2008-2013 GeoLabs SARL. All rights reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including with
+# out limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+import zoo
+
+def HelloPy(conf,inputs,outputs):
+	outputs["Result"]["value"]="Hello "+inputs["a"]["value"]+" from Python World !"
+	return zoo.SERVICE_SUCCEEDED
+
diff --git a/zoo-project/zoo-services/ogr/base-vect-ops-py/cgi-env/BoundaryPy.zcfg b/zoo-project/zoo-services/ogr/base-vect-ops-py/cgi-env/BoundaryPy.zcfg
new file mode 100755
index 0000000..9ab1134
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/base-vect-ops-py/cgi-env/BoundaryPy.zcfg
@@ -0,0 +1,56 @@
+[BoundaryPy]
+ Title = Computes boundary.
+ Abstract = A new geometry object is created and returned containing the boundary of the geometry on which the method is invoked. 
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = ogr_sp
+ serviceType = Python
+ <MetaData>
+   title = Demo
+ </MetaData>
+ <DataInputs>
+  [InputPolygon]
+   Title = Polygon to conpute boundary
+   Abstract = URI to a set of GML that describes the polygon.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://schemas.opengis.net/gml/3.1.0/base/feature.xsd
+    </Default>
+    <Supported>
+     mimeType = application/json
+     encoding = UTF-8
+    </Supported>
+   </ComplexData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = The geometry created
+   Abstract = The geometry containing the boundary of the geometry on which the method is invoked.
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://schemas.opengis.net/gml/3.1.0/base/feature.xsd
+    </Default>
+    <Supported>
+     mimeType = application/json
+     encoding = UTF-8
+    </Supported>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://schemas.opengis.net/gml/3.1.0/base/feature.xsd
+    </Supported>
+   </ComplexData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/ogr/base-vect-ops-py/cgi-env/BufferPy.zcfg b/zoo-project/zoo-services/ogr/base-vect-ops-py/cgi-env/BufferPy.zcfg
new file mode 100755
index 0000000..ced7252
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/base-vect-ops-py/cgi-env/BufferPy.zcfg
@@ -0,0 +1,68 @@
+[BufferPy]
+ Title = Creates a buffer around a polygon. 
+ Abstract = Creates a buffer around a single polygon. Accepts the polygon as GML and provides GML output for the buffered feature. 
+ Profile = urn:ogc:wps:1.0.0:buffer
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = ogr_sp
+ serviceType = Python
+ <MetaData>
+   title = Demo
+ </MetaData>
+ <DataInputs>
+  [InputPolygon]
+   Title = Polygon to be buffered
+   Abstract = URI to a set of GML that describes the polygon.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://schemas.opengis.net/gml/3.1.0/base/feature.xsd
+     asReference = true	
+    </Default>
+    <Supported>
+     mimeType = application/json
+     encoding = UTF-8
+    </Supported>
+   </ComplexData>
+  [BufferDistance]
+   Title = Buffer Distance
+   Abstract = Distance to be used to calculate buffer.
+   minOccurs = 0
+   maxOccurs = 1
+   <LiteralData>
+    DataType = float
+    <Default>
+     uom = meters
+     value = 1
+    </Default>
+    <Supported>
+     uom = feet
+    </Supported>
+   </LiteralData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = Buffered Polygon
+   Abstract = GML stream describing the buffered polygon feature.
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://schemas.opengis.net/gml/3.1.0/base/feature.xsd
+    </Default>
+    <Supported>
+     mimeType = application/json
+     encoding = UTF-8
+    </Supported>
+   </ComplexData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/ogr/base-vect-ops-py/cgi-env/CentroidPy.zcfg b/zoo-project/zoo-services/ogr/base-vect-ops-py/cgi-env/CentroidPy.zcfg
new file mode 100755
index 0000000..9f7c2aa
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/base-vect-ops-py/cgi-env/CentroidPy.zcfg
@@ -0,0 +1,43 @@
+[Clean]
+ Title = Computes the centroid of a polygon 
+ Abstract = Computes the centroid of a polygon that have a valid geometry field.
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = ogr_sp
+ serviceType = Python
+ <DataInputs>
+  [InputData]
+   Title = Polygon to get the centroid
+   Abstract = The centroid which is not necessarily within the geometry.
+   minOccurs = 1
+   maxOccurs = 1
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://schemas.opengis.net/gml/3.1.0/base/feature.xsd
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://schemas.opengis.net/gml/3.1.0/base/feature.xsd
+    </Supported>
+   </ComplexData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = The Centroid
+   Abstract = JSON String / GML Entity of the centroid
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://schemas.opengis.net/gml/3.1.0/point.xsd
+    </Default>
+    <Supported>
+     mimeType = application/json
+     encoding = UTF-8
+    </Supported>
+   </ComplexData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/ogr/base-vect-ops-py/cgi-env/ConvexHullPy.zcfg b/zoo-project/zoo-services/ogr/base-vect-ops-py/cgi-env/ConvexHullPy.zcfg
new file mode 100755
index 0000000..b293af8
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/base-vect-ops-py/cgi-env/ConvexHullPy.zcfg
@@ -0,0 +1,51 @@
+[ConvexHullPy]
+ Title = Computes convex hull.
+ Abstract = A new geometry object is created and returned containing the convex hull of the geometry on which the method is invoked.
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = ogr_sp
+ serviceType = Python
+ <MetaData>
+   title = Demo
+ </MetaData>
+ <DataInputs>
+  [InputPolygon]
+   Title = Polygon to compute convexhull
+   Abstract = URI to a set of GML that describes the polygon.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData>
+   title = Mon test
+   </MetaData>
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://schemas.opengis.net/gml/3.1.0/base/feature.xsd
+    </Default>
+    <Supported>
+     mimeType = application/json
+     encoding = UTF-8
+    </Supported>
+   </ComplexData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = The convex hull of the geometry
+   Abstract = The convex hull of the geometry
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://schemas.opengis.net/gml/3.1.0/base/feature.xsd
+    </Default>
+    <Supported>
+     mimeType = application/json
+     encoding = UTF-8
+    </Supported>
+   </ComplexData>
+ </DataOutputs> 
diff --git a/zoo-project/zoo-services/ogr/base-vect-ops-py/cgi-env/DifferencePy.zcfg b/zoo-project/zoo-services/ogr/base-vect-ops-py/cgi-env/DifferencePy.zcfg
new file mode 100755
index 0000000..f83f161
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/base-vect-ops-py/cgi-env/DifferencePy.zcfg
@@ -0,0 +1,75 @@
+[DifferencePy]
+ Title = Computes difference. 
+ Abstract = Generates a new geometry which is the region of this geometry with the region of the other geometry removed.
+ Profile = urn:ogc:wps:1.0.0:difference
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = ogr_sp
+ serviceType = Python
+ <MetaData>
+   title = Demo
+ </MetaData>
+ <DataInputs>
+  [InputEntity1]
+   Title = the first geometry 
+   Abstract = the first geometry to compare against.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://schemas.opengis.net/gml/3.1.0/base/feature.xsd
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://schemas.opengis.net/gml/3.1.0/base/feature.xsd
+    </Supported>
+   </ComplexData>
+  [InputEntity2]
+   Title = the other geometry
+   Abstract = the other geometry to compare against.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     schema = http://schemas.opengis.net/gml/3.1.0/base/feature.xsd
+     encoding = UTF-8
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://schemas.opengis.net/gml/3.1.0/base/feature.xsd
+    </Supported>
+   </ComplexData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = The difference between two geometries
+   Abstract = The difference between the two geometries.
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+    <ComplexData>
+     <Default>
+      mimeType = text/xml
+      schema = http://schemas.opengis.net/gml/3.1.0/base/feature.xsd
+      encoding = UTF-8
+      extension = xml
+     </Default>
+     <Supported>
+      mimeType = application/json
+      encoding = UTF-8
+      extension = js
+     </Supported>
+    </ComplexData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/ogr/base-vect-ops-py/cgi-env/IntersectionPy.zcfg b/zoo-project/zoo-services/ogr/base-vect-ops-py/cgi-env/IntersectionPy.zcfg
new file mode 100755
index 0000000..e8a4f72
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/base-vect-ops-py/cgi-env/IntersectionPy.zcfg
@@ -0,0 +1,75 @@
+[IntersectionPy]
+ Title = Computes intersection. 
+ Abstract = Generates a new geometry which is the region of intersection of the two geometries operated on.
+ Profile = urn:ogc:wps:1.0.0:union
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = ogr_sp
+ serviceType = Python
+ <MetaData>
+   title = Demo
+ </MetaData>
+ <DataInputs>
+  [InputEntity1]
+   Title = the first geometry 
+   Abstract = the first geometry to compare against.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://schemas.opengis.net/gml/3.1.0/base/feature.xsd
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://schemas.opengis.net/gml/3.1.0/base/feature.xsd
+    </Supported>
+   </ComplexData>
+  [InputEntity2]
+   Title = the other geometry
+   Abstract = the other geometry to compare against.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     schema = http://schemas.opengis.net/gml/3.1.0/base/feature.xsd
+     encoding = UTF-8
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://schemas.opengis.net/gml/3.1.0/base/feature.xsd
+    </Supported>
+   </ComplexData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = Intersection of the two geometries
+   Abstract = A new geometry representing the intersection or NULL if there is no intersection or an error occurs.
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+    <ComplexData>
+     <Default>
+      mimeType = text/xml
+      schema = http://schemas.opengis.net/gml/3.1.0/base/feature.xsd
+      encoding = UTF-8
+      extension = xml
+     </Default>
+     <Supported>
+      mimeType = application/json
+      encoding = UTF-8
+      extension = js
+     </Supported>
+    </ComplexData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/ogr/base-vect-ops-py/cgi-env/SymDifferencePy.zcfg b/zoo-project/zoo-services/ogr/base-vect-ops-py/cgi-env/SymDifferencePy.zcfg
new file mode 100755
index 0000000..0a0457b
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/base-vect-ops-py/cgi-env/SymDifferencePy.zcfg
@@ -0,0 +1,83 @@
+[SymDifferencePy]
+ Title = Computes symmetric difference. 
+ Abstract = Generates a new geometry which is the symmetric difference of this geometry and the other geometry.
+ Profile = urn:ogc:wps:1.0.0:symmetricdifference
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = ogr_sp
+ serviceType = Python
+ <MetaData>
+   title = Demo
+ </MetaData>
+ <DataInputs>
+  [InputEntity1]
+   Title = the first geometry 
+   Abstract = the first geometry to compare against.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://schemas.opengis.net/gml/3.1.0/base/feature.xsd
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://schemas.opengis.net/gml/3.1.0/base/feature.xsd
+    </Supported>
+    <Supported>
+     mimeType = application/json
+     encoding = UTF-8
+    </Supported>
+   </ComplexData>
+  [InputEntity2]
+   Title = the other geometry
+   Abstract = the other geometry to compare against.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     schema = http://schemas.opengis.net/gml/3.1.0/base/feature.xsd
+     encoding = UTF-8
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://schemas.opengis.net/gml/3.1.0/base/feature.xsd
+    </Supported>
+    <Supported>
+     mimeType = application/json
+     encoding = UTF-8
+    </Supported>
+   </ComplexData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = The symmetric difference between two geometries
+   Abstract = The symmetric difference between the two geometries.
+   <MetaData>
+    title = Symmetric Difference  
+   </MetaData>   
+    <ComplexData>
+     <Default>
+      mimeType = text/xml
+      schema = http://schemas.opengis.net/gml/3.1.0/base/feature.xsd
+      encoding = UTF-8
+      extension = xml
+     </Default>
+     <Supported>
+      mimeType = application/json
+      encoding = UTF-8
+      extension = js
+     </Supported>
+    </ComplexData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/ogr/base-vect-ops-py/cgi-env/UnionPy.zcfg b/zoo-project/zoo-services/ogr/base-vect-ops-py/cgi-env/UnionPy.zcfg
new file mode 100755
index 0000000..c47045e
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/base-vect-ops-py/cgi-env/UnionPy.zcfg
@@ -0,0 +1,73 @@
+[UnionPy]
+ Title = Computes union. 
+ Abstract = Generates a new geometry which is the region of union of the two geometries operated on.
+ Profile = urn:ogc:wps:1.0.0:union
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = ogr_sp
+ serviceType = Python
+ <MetaData>
+   title = Demo
+ </MetaData>
+ <DataInputs>
+  [InputEntity1]
+   Title = the first geometry 
+   Abstract = the first geometry to compare against.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://schemas.opengis.net/gml/3.1.0/base/feature.xsd
+    </Default>
+    <Supported>
+     mimeType = application/json
+     encoding = UTF-8
+    </Supported>
+   </ComplexData>
+  [InputEntity2]
+   Title = the other geometry
+   Abstract = the other geometry to compare against.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     schema = http://schemas.opengis.net/gml/3.1.0/base/feature.xsd
+     encoding = UTF-8
+    </Default>
+    <Supported>
+     mimeType = application/json
+     encoding = UTF-8
+    </Supported>
+   </ComplexData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = The union of two geometries
+   Abstract = The geometry representing the union of the two geometries.
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+    <ComplexData>
+     <Default>
+      mimeType = text/xml
+      schema = http://schemas.opengis.net/gml/3.1.0/base/feature.xsd
+      encoding = UTF-8
+      extension = xml
+     </Default>
+     <Supported>
+      mimeType = application/json
+      encoding = UTF-8
+      extension = js
+     </Supported>
+    </ComplexData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/ogr/base-vect-ops-py/cgi-env/ogr_sp.py b/zoo-project/zoo-services/ogr/base-vect-ops-py/cgi-env/ogr_sp.py
new file mode 100644
index 0000000..5fa413f
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/base-vect-ops-py/cgi-env/ogr_sp.py
@@ -0,0 +1,394 @@
+# -*- coding: utf-8 -*-
+#
+# Author : Gérald FENOY
+#
+# Copyright 2009-2013 GeoLabs SARL. All rights reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including with
+# out limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+from osgeo import *
+import osgeo.ogr
+import osgeo.gdal
+import libxml2
+import os
+import sys
+import zoo
+
+def readFileFromBuffer(data,ext):
+    try:
+        geometry=[]
+        print >> sys.stderr,'/vsimem//temp1'+ext
+        #print >> sys.stderr,data
+        osgeo.gdal.FileFromMemBuffer('/vsimem//temp1'+ext,data)
+        ds = osgeo.ogr.Open('/vsimem//temp1'+ext)
+        lyr = ds.GetLayer(0)
+        feat = lyr.GetNextFeature()
+        while feat is not None:
+            geometry+=[feat.Clone()]
+            feat.Destroy()
+            feat = lyr.GetNextFeature()
+        ds.Destroy()
+        osgeo.gdal.Unlink('/vsimem//temp1'+ext)
+        return geometry
+    except Exception,e:
+        print >> sys.stderr,e
+        return []
+    
+def buildFeatureFromGeomtry(conf,geom,driverName,ext):
+    drv = osgeo.ogr.GetDriverByName( driverName )
+    ds = drv.CreateDataSource( "/vsimem//store"+conf["lenv"]["sid"]+"0."+ext )
+    lyr = ds.CreateLayer( "Result", None, osgeo.ogr.wkbUnknown )
+    field_defn = osgeo.ogr.FieldDefn( "Name", osgeo.ogr.OFTString )
+    field_defn.SetWidth( len("Result10000") )
+    lyr.CreateField ( field_defn )
+    feat = osgeo.ogr.Feature(lyr.GetLayerDefn())
+    feat.SetField( "Name", "Input0" )
+    feat.SetGeometry(geom)
+    lyr.CreateFeature(feat)
+    ds.Destroy()
+    return [feat]
+
+def createGeometryFromWFS(conf,my_wfs_response):
+    try:
+        geom=osgeo.ogr.CreateGeometryFromGML(my_wfs_response.replace('<?xml version="1.0" encoding="utf-8"?>\n','').replace('<?xml version=\'1.0\' encoding="utf-8"?>\n',''))
+    except Exception,e:
+        print >> sys.stderr,"**"
+        print >> sys.stderr,e
+        geom=None
+    try:
+        print >> sys.stderr,geom is None
+        if geom is None:
+            if not(conf["lenv"].has_key("cnt")):
+                conf["lenv"]["cnt"]=0
+            else:
+                conf["lenv"]["cnt"]+=1
+            return readFileFromBuffer(my_wfs_response,str(conf["lenv"]["cnt"]))
+        else:
+            return buildFeatureFromGeomtry(conf,geom,"GML","xml")
+    except:
+        print >> sys.stderr,"Unable to load file input data !!!\n\n\n"
+
+def createLayerFromJson(conf,obj):
+    geom=osgeo.ogr.CreateGeometryFromJson(obj)
+    if geom is None:
+        return readFileFromBuffer(obj,".json")
+    else:
+        return buildFeatureFromGeomtry(conf,geom,"GeoJSON","json")
+
+def extractInputs(conf,obj):
+    if obj["mimeType"]=="application/json":
+        return createLayerFromJson(conf,obj["value"])
+    else:
+        return createGeometryFromWFS(conf,obj["value"])
+    
+def outputResult(conf,obj,geom):
+    if obj["mimeType"].count("text/xml")>0:
+        driverName = "GML"
+        extension = [ ".xml" , ".xsd" ]
+        format_list = { "2.": 'GML2', "3.1.1": 'GML3', "3.1": 'GML3Deegree', "3.2": 'GML3.2' }
+        opts=['FORMAT=%s,GML3_LONGSRS=YES',format_list["3.2"]]
+        for i in format_list:
+            if obj["mimeType"].count(i)>0:
+                opts=['FORMAT=%s,GML3_LONGSRS=YES',format_list[i]]
+    if obj["mimeType"]=="application/json":
+        driverName = "GeoJSON"
+        extension = [ ".js" ]
+        opts=None
+    if obj.keys().count("schema")>0 and \
+            obj["schema"]=="http://schemas.opengis.net/kml/2.2.0/ogckml22.xsd":
+        driverName = "KML"
+        extension = [ ".kml" ]
+        opts=None
+    drv = osgeo.ogr.GetDriverByName( driverName )
+    print >> sys.stderr,drv
+    # Create virtual file
+    ds = drv.CreateDataSource( "/vsimem/store"+conf["lenv"]["sid"]+extension[0],options = opts)
+    print >> sys.stderr,ds
+    lyr = ds.CreateLayer( "Result", None, osgeo.ogr.wkbUnknown )
+    print >> sys.stderr,lyr
+    i=0
+    print >> sys.stderr,driverName
+    print >> sys.stderr,extension
+    while i < len(geom):
+        if i==0 and driverName!="GeoJSON":
+            poDstFDefn=geom[i].GetDefnRef()
+            if poDstFDefn is not None:
+                nDstFieldCount = poDstFDefn.GetFieldCount()
+                for iField in range(nDstFieldCount):
+                    poSrcFieldDefn = poDstFDefn.GetFieldDefn(iField)
+                    oFieldDefn = osgeo.ogr.FieldDefn(poSrcFieldDefn.GetNameRef(),poSrcFieldDefn.GetType())
+                    oFieldDefn.SetWidth( poSrcFieldDefn.GetWidth() )
+                    oFieldDefn.SetPrecision( poSrcFieldDefn.GetPrecision() )
+                    lyr.CreateField( oFieldDefn )
+        try:
+            lyr.CreateFeature(geom[i])
+        except:
+            pass
+        geom[i].Destroy()
+        i+=1
+    ds.Destroy()
+    vsiFile=osgeo.gdal.VSIFOpenL("/vsimem/store"+conf["lenv"]["sid"]+extension[0],"r")
+    i=0
+    while osgeo.gdal.VSIFSeekL(vsiFile,0,os.SEEK_END)>0:
+        i+=1
+    fileSize=osgeo.gdal.VSIFTellL(vsiFile)
+    osgeo.gdal.VSIFSeekL(vsiFile,0,os.SEEK_SET)
+    obj["value"]=osgeo.gdal.VSIFReadL(fileSize,1,vsiFile)
+    osgeo.gdal.Unlink("/vsimem/store"+conf["lenv"]["sid"]+extension[0])
+
+def BufferPy(conf,inputs,outputs):
+    print >> sys.stderr, "Starting service ..."
+    try:
+        bdist=float(inputs["BufferDistance"]["value"])
+    except:
+        bdist=1
+    print >> sys.stderr, bdist
+    geometry=extractInputs(conf,inputs["InputPolygon"])
+    i=0
+    rgeometries=[]
+    while i < len(geometry):
+        tmp=geometry[i].Clone()
+        resg=geometry[i].GetGeometryRef().Buffer(bdist)
+        tmp.SetGeometryDirectly(resg)
+        rgeometries+=[tmp]
+        geometry[i].Destroy()
+        resg.thisown=False 
+        tmp.thisown=False
+        i+=1
+    outputResult(conf,outputs["Result"],rgeometries)
+    i=0
+    return zoo.SERVICE_SUCCEEDED
+
+def Clean(conf,inputs,outputs):
+    from shapely.wkb import loads
+    print >> sys.stderr, "Starting service ..."
+    features=extractInputs(conf,inputs["InputData"])
+    i=0
+    rgeometries=[]
+    while i < len(features):
+        tmp=features[i].Clone()
+        resg=features[i].GetGeometryRef()
+        if resg is not None:
+            geom = loads(resg.ExportToWkb())
+            if geom.is_valid:
+                tmp.SetGeometryDirectly(resg)
+                rgeometries+=[tmp]
+                print >> sys.stderr,"valid !"
+            else:
+                print >> sys.stderr,"invalid !"
+                print >> sys.stderr,geom.wkt[0:50]
+        features[i].Destroy()
+        resg.thisown=False 
+        tmp.thisown=False
+        i+=1
+    outputResult(conf,outputs["Result"],rgeometries)
+    i=0
+    print >> sys.stderr,"Return"
+    return zoo.SERVICE_SUCCEEDED
+
+def TransformService(conf,inputs,outputs):
+    from osgeo import osr
+    geometry=extractInputs(conf,inputs["InputData"])
+    sourceRef = osr.SpatialReference()
+    tmp=inputs["SourceCRS"]["value"].split(":")
+    sourceRef.ImportFromEPSG(int(tmp[len(tmp)-1]))
+    targetRef = osr.SpatialReference()    
+    tmp=inputs["TargetCRS"]["value"].split(":")
+    targetRef.ImportFromEPSG(int(tmp[len(tmp)-1]))
+    transform = osr.CoordinateTransformation(sourceRef, targetRef)
+    i=0
+    rgeometries=[]
+    while i < len(geometry):
+        tmp=geometry[i].Clone()
+        resg=geometry[i].GetGeometryRef()
+        resg.Transform(transform)
+        tmp.SetGeometryDirectly(resg.Clone())
+        rgeometries+=[tmp]
+        geometry[i].Destroy()
+        i+=1
+    outputResult(conf,outputs["TransformedData"],rgeometries)
+    return zoo.SERVICE_SUCCEEDED
+
+def BoundaryPy(conf,inputs,outputs):
+    geometry=extractInputs(conf,inputs["InputPolygon"])
+    i=0
+    rgeometries=[]
+    while i < len(geometry):
+        tmp=geometry[i].Clone()
+        resg=geometry[i].GetGeometryRef()
+        resg=resg.GetBoundary()
+        tmp.SetGeometryDirectly(resg)
+        rgeometries+=[tmp]
+        geometry[i].Destroy()
+        i+=1
+    outputResult(conf,outputs["Result"],rgeometries)
+    return zoo.SERVICE_SUCCEEDED
+
+def CentroidPy(conf,inputs,outputs):
+    geometry=extractInputs(conf,inputs["InputPolygon"])
+    i=0
+    rgeometries=[]
+    while i < len(geometry):
+        tmp=geometry[i].Clone()
+        resg=geometry[i].GetGeometryRef()
+        if resg.GetGeometryType()!=3:
+            resg=resg.ConvexHull()
+        resg=resg.Centroid()
+        tmp.SetGeometryDirectly(resg)
+        rgeometries+=[tmp]
+        geometry[i].Destroy()
+        i+=1
+    outputResult(conf,outputs["Result"],rgeometries)
+    return zoo.SERVICE_SUCCEEDED
+
+def ConvexHullPy(conf,inputs,outputs):
+    geometry=extractInputs(conf,inputs["InputPolygon"])
+    i=0
+    rgeometries=[]
+    while i < len(geometry):
+        tmp=geometry[i].Clone()
+        resg=geometry[i].GetGeometryRef().ConvexHull()
+        tmp.SetGeometryDirectly(resg)
+        rgeometries+=[tmp]
+        geometry[i].Destroy()
+        i+=1
+    outputResult(conf,outputs["Result"],rgeometries)
+    return zoo.SERVICE_SUCCEEDED
+
+
+
+def EnvelopePy(conf,inputs,outputs):
+    print >> sys.stderr, inputs
+    try:
+        bdist=float(inputs["BufferDistance"]["value"])
+    except:
+        bdist=10
+    geometry=extractInputs(conf,inputs["InputPolygon"])
+    tmp=geometry[0].GetGeometryRef().GetEnvelope()
+    outputs["Result"]["value"]=str(tmp[0])+','+str(tmp[2])+','+str(tmp[1])+','+str(tmp[3])+','+'urn:ogc:def:crs:OGC:1.3:CRS84'
+    print >> sys.stderr,outputs["Result"]
+    return 3
+
+def UnionPy(conf,inputs,outputs):
+    geometry1=extractInputs(conf,inputs["InputEntity1"])
+    geometry2=extractInputs(conf,inputs["InputEntity2"])
+    rgeometries=[]
+    i=0
+    while i < len(geometry1):
+        j=0
+        while j < len(geometry2):
+            tmp=geometry1[i].Clone()
+            resg=geometry2[j].GetGeometryRef()
+            resg=resg.Union(geometry1[i].GetGeometryRef())
+            tmp.SetGeometryDirectly(resg)
+            if not(resg.IsEmpty()):
+                rgeometries+=[tmp]
+            j+=1
+        geometry1[i].Destroy()
+        i+=1
+    i=0
+    while i < len(geometry2):
+        geometry2[i].Destroy()
+        i+=1
+    outputResult(conf,outputs["Result"],rgeometries)
+    return 3
+
+def IntersectionPy(conf,inputs,outputs):
+
+    geometry1=extractInputs(conf,inputs["InputEntity1"])
+    geometry2=extractInputs(conf,inputs["InputEntity2"])
+
+    print >> sys.stderr,str(len(geometry1))+" "+str(len(geometry2))
+
+    rgeometries=[]
+    fids=[]
+    i=0
+    while i < len(geometry1):
+        j=0
+        while j < len(geometry2):
+            tmp=geometry2[j].Clone()
+            resg=geometry2[j].GetGeometryRef()
+            #resg=resg.Intersection(geometry1[i].GetGeometryRef())
+            resg=geometry1[i].GetGeometryRef().Intersection(resg)
+            tmp.SetGeometryDirectly(resg)
+            if resg is not None and not(resg.IsEmpty()) and fids.count(tmp.GetFID())==0:
+                rgeometries+=[tmp]
+                fids+=[tmp.GetFID()]
+            else:
+                tmp.Destroy()
+            j+=1
+        geometry1[i].Destroy()
+        i+=1
+    i=0
+    while i < len(geometry2):
+        geometry2[i].Destroy()
+        i+=1
+    outputResult(conf,outputs["Result"],rgeometries)
+    print >> sys.stderr,"/outputResult"
+    return 3
+
+def DifferencePy(conf,inputs,outputs):
+    geometry1=extractInputs(conf,inputs["InputEntity1"])
+    geometry2=extractInputs(conf,inputs["InputEntity2"])
+    rgeometries=[]
+    i=0
+    while i < len(geometry1):
+        j=0
+        while j < len(geometry2):
+            tmp=geometry2[j].Clone()
+            resg=geometry1[i].GetGeometryRef()
+            resg=resg.Difference(geometry2[i].GetGeometryRef())
+            tmp.SetGeometryDirectly(resg)
+            if not(resg.IsEmpty()):
+                rgeometries+=[tmp]
+            j+=1
+        geometry1[i].Destroy()
+        i+=1
+    i=0
+    while i < len(geometry2):
+        geometry2[i].Destroy()
+        i+=1
+    outputResult(conf,outputs["Result"],rgeometries)
+    return 3
+
+def SymDifferencePy(conf,inputs,outputs):
+    geometry1=extractInputs(conf,inputs["InputEntity1"])
+    geometry2=extractInputs(conf,inputs["InputEntity2"])
+    rgeometries=[]
+    i=0
+    while i < len(geometry1):
+        j=0
+        while j < len(geometry2):
+            tmp=geometry2[j].Clone()
+            resg=geometry1[i].GetGeometryRef()
+            resg=resg.SymmetricDifference(geometry2[i].GetGeometryRef())
+            tmp.SetGeometryDirectly(resg)
+            rgeometries+=[tmp]
+            j+=1
+        geometry1[i].Destroy()
+        i+=1
+    i=0
+    while i < len(geometry2):
+        geometry2[i].Destroy()
+        i+=1
+    outputResult(conf,outputs["Result"],rgeometries)
+    return 3
+
diff --git a/zoo-project/zoo-services/ogr/base-vect-ops/Makefile b/zoo-project/zoo-services/ogr/base-vect-ops/Makefile
new file mode 100644
index 0000000..ef6c150
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/base-vect-ops/Makefile
@@ -0,0 +1,19 @@
+ZRPATH=../../..
+include ${ZRPATH}/zoo-kernel/ZOOMakefile.opts
+CFLAGS=${ZOO_CFLAGS} ${JSCFLAGS} ${XML2CFLAGS} ${GDAL_CFLAGS} ${GEOS_CFLAGS} -DLINUX_FREE_ISSUE #-DDEBUG
+
+ifneq ($(MS_FILE),)
+	MS_FILES=${ZRPATH}/zoo-kernel/${MS_FILE} -lmapserver
+else
+	MS_FILES=
+endif
+
+cgi-env/ogr_service.zo: service.c
+	g++ ${CFLAGS} -shared -fpic -o cgi-env/ogr_service.zo ./service.c ${GDAL_LIBS} ${XML2LDFLAGS} ${MACOS_LD_FLAGS} ${ZOO_LDFLAGS} ${MACOS_LD_NET_FLAGS} ${GEOS_LDFLAGS} -lfcgi  -lpthread -lzoo_service
+
+install:
+	install -d ${CGI_DIR}/ogr/base-vect-ops
+	install cgi-env/* ${CGI_DIR}/ogr/base-vect-ops
+
+clean:
+	rm -f cgi-env/ogr_service.zo
diff --git a/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Boundary.zcfg b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Boundary.zcfg
new file mode 100755
index 0000000..96e4d3b
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Boundary.zcfg
@@ -0,0 +1,60 @@
+[Boundary]
+ Title = Computes boundary.
+ Abstract = This service shall return a feature callection representing the combinatorial boundary of each geometry in the InputPolygon feature collection.
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = ogr_service.zo
+ serviceType = C
+ <MetaData>
+   title = Demo
+ </MetaData>
+ <DataInputs>
+  [InputPolygon]
+   Title = Polygon to compute boundary
+   Abstract = URI to a set of GML that describes the polygon.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Supported>
+   </ComplexData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = The geometry created
+   Abstract = The geometry containing the boundary of the geometry on which the method is invoked.
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+     extension = xml
+    </Default>
+    <Supported>
+     mimeType = application/json
+     encoding = UTF-8
+     extension = js
+    </Supported>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+     extension = xml
+    </Supported>
+   </ComplexData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Buffer.zcfg b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Buffer.zcfg
new file mode 100755
index 0000000..cf66640
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Buffer.zcfg
@@ -0,0 +1,70 @@
+[Buffer]
+ Title = Create a buffer around a polygon. 
+ Abstract = This service shall return a feature collection representing the buffer of geometry InputPolygon at distance BufferDistance. The buffer of a geometry at distance d is the Polygon or MultiPolygon which contains all points within a distance d of the geometry.
+ Profile = urn:ogc:wps:1.0.0:buffer
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = ogr_service.zo
+ serviceType = C
+ <MetaData>
+   title = Demo
+ </MetaData>
+ <DataInputs>
+  [InputPolygon]
+   Title = Polygon to be buffered
+   Abstract = URI to a set of GML that describes the polygon.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+     asReference = true	
+    </Default>
+    <Supported>
+     mimeType = application/json
+     encoding = UTF-8
+    </Supported>
+   </ComplexData>
+  [BufferDistance]
+   Title = Buffer Distance
+   Abstract = Distance to be used to calculate buffer.
+   minOccurs = 0
+   maxOccurs = 1
+   <LiteralData>
+    DataType = float
+    <Default>
+     uom = meters
+     value = 10
+    </Default>
+    <Supported>
+     uom = feet
+    </Supported>
+   </LiteralData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = Buffered Polygon
+   Abstract = GML stream describing the buffered polygon feature.
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+     extension = xml
+    </Default>
+    <Supported>
+     mimeType = application/json
+     encoding = UTF-8
+     extension = js
+    </Supported>
+   </ComplexData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Centroid.zcfg b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Centroid.zcfg
new file mode 100755
index 0000000..1811e39
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Centroid.zcfg
@@ -0,0 +1,55 @@
+[Centroid]
+ Title = Computes the centroid of a polygon. 
+ Abstract = This service shall return the point that is the geometric centre of gravity of the geometry InputPolygon.
+ Profile = urn:ogc:wps:1.0.0:centroid
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = ogr_service.zo
+ serviceType = C
+ <MetaData>
+   title = Demo
+ </MetaData>
+ <DataInputs>
+  [InputPolygon]
+   Title = Polygon to get the centroid
+   Abstract = The centroid which is not necessarily within the geometry.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Supported>
+   </ComplexData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = The Centroid
+   Abstract = JSON String / GML Entity of the centroid
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://fooa/gml/3.1.0/point.xsd
+     extension = xml
+    </Default>
+    <Supported>
+     mimeType = application/json
+     encoding = UTF-8
+     extension = js
+    </Supported>
+   </ComplexData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Contains.zcfg b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Contains.zcfg
new file mode 100644
index 0000000..bc4fe45
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Contains.zcfg
@@ -0,0 +1,57 @@
+[Contains]
+ Title = Contains
+ Abstract = This service shall return a true value if and only if the geometry g2 lies in the closure (boundary union interior) of geometry g1 - the inverse of Within(g1: Geometry, g2: Geometry).
+ Profile = urn:ogc:wps:1.0.0:union
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = ogr_service.zo
+ serviceType = C
+ <DataInputs>
+  [InputEntity1]
+   Title = the first geometry 
+   Abstract = the first geometry.
+   minOccurs = 1
+   maxOccurs = 1
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Supported>
+   </ComplexData>
+  [InputEntity2]
+   Title = the other geometry
+   Abstract = the other geometry.
+   minOccurs = 1
+   maxOccurs = 1
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+     encoding = UTF-8
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Supported>
+   </ComplexData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = Contains result
+   Abstract = A value true or false if the geometry1 contains the geometry2.
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+    <LiteralData>
+      dataType=boolean
+      <Default />
+    </LiteralData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/ConvexHull.zcfg b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/ConvexHull.zcfg
new file mode 100755
index 0000000..8dc6d40
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/ConvexHull.zcfg
@@ -0,0 +1,54 @@
+[ConvexHull]
+ Title = Compute convex hull.
+ Abstract = This service shall return a feature collection that represents the convex hull of geometry InputPolygon. The convex hull is the smallest convex polygon that contains all points of the geometry. The convex Hull for a geometry of encoding data type Point is the point itself
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = ogr_service.zo
+ serviceType = C
+ <MetaData>
+   title = Demo
+ </MetaData>
+ <DataInputs>
+  [InputPolygon]
+   Title = Polygon to compute convexhull
+   Abstract = URI to a set of GML that describes the polygon.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData>
+   title = Mon test
+   </MetaData>
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Supported>
+   </ComplexData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = The convex hull of the geometry
+   Abstract = The convex hull of the geometry
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+     extension = xml
+    </Default>
+    <Supported>
+     mimeType = application/json
+     encoding = UTF-8
+     extension = js
+    </Supported>
+   </ComplexData>
+ </DataOutputs> 
diff --git a/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Crosses.zcfg b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Crosses.zcfg
new file mode 100644
index 0000000..9d7f597
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Crosses.zcfg
@@ -0,0 +1,57 @@
+[Crosses]
+ Title = Crosses test
+ Abstract = This service shall return a true value if and only if the geometries g1 and g2 share some but neither is containe in the other, and the dimension of the intersection is less than that of both of the geometries.
+ processVersion = 2
+ profile = urn:ogc:wps:1.0.0:union
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = ogr_service.zo
+ serviceType = C
+ <DataInputs>
+  [InputEntity1]
+   Title = the first geometry 
+   Abstract = the first geometry.
+   minOccurs = 1
+   maxOccurs = 1
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Supported>
+   </ComplexData>
+  [InputEntity2]
+   Title = the other geometry
+   Abstract = the other geometry.
+   minOccurs = 1
+   maxOccurs = 1
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+     encoding = UTF-8
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Supported>
+   </ComplexData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = Disjoint result
+   Abstract = true if disjoint.
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+    <LiteralData>
+      dataType=boolean
+      <Default />
+    </LiteralData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Difference.zcfg b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Difference.zcfg
new file mode 100755
index 0000000..3f9cf04
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Difference.zcfg
@@ -0,0 +1,75 @@
+[Difference]
+ Title = Compute difference. 
+ Abstract = This function shall return a bag of geometry values representing the closure of the set difference between the two geometries InputEntity1 and InputEntity2. The difference is the set of all points which lie on InputEntity1 but not on InputEntity2.
+ Profile = urn:ogc:wps:1.0.0:difference
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = ogr_service.zo
+ serviceType = C
+ <MetaData>
+   title = Demo
+ </MetaData>
+ <DataInputs>
+  [InputEntity1]
+   Title = the first geometry 
+   Abstract = the first geometry to compare against.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Supported>
+   </ComplexData>
+  [InputEntity2]
+   Title = the other geometry
+   Abstract = the other geometry to compare against.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Supported>
+   </ComplexData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = The difference between two geometries
+   Abstract = The difference between the two geometries.
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+    <ComplexData>
+     <Default>
+      mimeType = text/xml
+      encoding = UTF-8
+      schema = http://fooa/gml/3.1.0/polygon.xsd
+      extension = xml
+     </Default>
+     <Supported>
+      mimeType = application/json
+      encoding = UTF-8
+      extension = js
+     </Supported>
+    </ComplexData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Disjoint.zcfg b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Disjoint.zcfg
new file mode 100644
index 0000000..29e530c
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Disjoint.zcfg
@@ -0,0 +1,57 @@
+[Disjoint]
+ Title = Disjoint 
+ Abstract = This servuce shall return a true value if and only if the geometries g1 and g2 have no point in common.
+ Profile = urn:ogc:wps:1.0.0:union
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = ogr_service.zo
+ serviceType = C
+ <DataInputs>
+  [InputEntity1]
+   Title = the first geometry 
+   Abstract = the first geometry.
+   minOccurs = 1
+   maxOccurs = 1
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Supported>
+   </ComplexData>
+  [InputEntity2]
+   Title = the other geometry
+   Abstract = the other geometry.
+   minOccurs = 1
+   maxOccurs = 1
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+     encoding = UTF-8
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Supported>
+   </ComplexData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = Disjoint result
+   Abstract = true if disjoint.
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+    <LiteralData>
+      dataType=boolean
+      <Default />
+    </LiteralData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Distance.zcfg b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Distance.zcfg
new file mode 100755
index 0000000..c21527e
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Distance.zcfg
@@ -0,0 +1,71 @@
+[Distance]
+ Title = Compute the distance between two geometries
+ Abstract = Compute the distance between two geometries
+ Profile = urn:ogc:wps:1.0.0:buffer
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = ogr_service.zo
+ serviceType = C
+ <MetaData>
+   title = Demo
+ </MetaData>
+ <DataInputs>
+  [InputEntity1]
+   Title = the first geometry 
+   Abstract = the first geometry to compare against.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Supported>
+   </ComplexData>
+  [InputEntity2]
+   Title = the other geometry
+   Abstract = the other geometry to compare against.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+     encoding = UTF-8
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Supported>
+   </ComplexData>
+ </DataInputs>
+ <DataOutputs>
+  [Distance]
+   Title = The distance between two geometries
+   Abstract = The shortest distance between the two geometries.
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+    <LiteralData>
+     DataType = float
+     <Default>
+      uom = meters
+     </Default>
+     <Supported>
+      uom = feet
+     </Supported>
+    </LiteralData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Equals.zcfg b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Equals.zcfg
new file mode 100644
index 0000000..395e864
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Equals.zcfg
@@ -0,0 +1,57 @@
+[Equals]
+ Title = Equals 
+ Abstract = This service shall return a true value if and only if the geometries g1 and g2 are equal
+ Profile = urn:ogc:wps:1.0.0:union
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = ogr_service.zo
+ serviceType = C
+ <DataInputs>
+  [InputEntity1]
+   Title = the first geometry 
+   Abstract = the first geometry.
+   minOccurs = 1
+   maxOccurs = 1
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Supported>
+   </ComplexData>
+  [InputEntity2]
+   Title = the other geometry
+   Abstract = the other geometry.
+   minOccurs = 1
+   maxOccurs = 1
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+     encoding = UTF-8
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Supported>
+   </ComplexData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = Equals result
+   Abstract = Should be true if two geometries are equivalent..
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+    <LiteralData>
+      dataType=boolean
+      <Default />
+    </LiteralData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/GetArea.zcfg b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/GetArea.zcfg
new file mode 100755
index 0000000..7c38128
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/GetArea.zcfg
@@ -0,0 +1,50 @@
+[GetArea]
+ Title = Compute geometry area.
+ Abstract = Computes the area of a geometry
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = ogr_service.zo
+ serviceType = C
+ <MetaData>
+   title = Demo
+ </MetaData>
+ <DataInputs>
+  [InputPolygon]
+   Title = Polygon to compute are
+   Abstract = URI to a set of GML that describes the polygon.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData>
+   title = Mon test
+   </MetaData>
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Supported>
+   </ComplexData>
+ </DataInputs>
+ <DataOutputs>
+  [Area]
+   Title = Computed Area
+   Abstract = The Computed Area Value
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <LiteralData>
+    DataType = float
+    <Default>
+     uom = degree
+    </Default>
+    <Supported>
+     uom = meter
+    </Supported>
+   </LiteralData>
+ </DataOutputs> 
diff --git a/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Intersection.zcfg b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Intersection.zcfg
new file mode 100755
index 0000000..5623666
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Intersection.zcfg
@@ -0,0 +1,75 @@
+[Intersection]
+ Title = Compute intersection. 
+ Abstract = This function SHALL return a bag of geometry values representing the Point set intersection of geometry InputEntity1 and geometry InputEntity2.
+ Profile = urn:ogc:wps:1.0.0:union
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = ogr_service.zo
+ serviceType = C
+ <MetaData>
+   title = Demo
+ </MetaData>
+ <DataInputs>
+  [InputEntity1]
+   Title = the first geometry 
+   Abstract = the first geometry to compare against.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Supported>
+   </ComplexData>
+  [InputEntity2]
+   Title = the other geometry
+   Abstract = the other geometry to compare against.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+     encoding = UTF-8
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Supported>
+   </ComplexData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = Intersection of geometries
+   Abstract = A new geometry representing the intersection or NULL if there is no intersection or an error occurs.
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+    <ComplexData>
+     <Default>
+      mimeType = text/xml
+      encoding = UTF-8
+      schema = http://fooa/gml/3.1.0/polygon.xsd
+      extension = xml
+     </Default>
+     <Supported>
+      mimeType = application/json
+      encoding = UTF-8
+      extension = js
+     </Supported>
+    </ComplexData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Intersects.zcfg b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Intersects.zcfg
new file mode 100644
index 0000000..0bbc012
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Intersects.zcfg
@@ -0,0 +1,57 @@
+[Intersects]
+ Title = Intersects test
+ Abstract = This service shall return a true value if and only if the geometries g1 and g2 have at least one boundary point in common, but no interior points.
+ Profile = urn:ogc:wps:1.0.0:union
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = ogr_service.zo
+ serviceType = C
+ <DataInputs>
+  [InputEntity1]
+   Title = the first geometry 
+   Abstract = the first geometry to compare against.
+   minOccurs = 1
+   maxOccurs = 1
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Supported>
+   </ComplexData>
+  [InputEntity2]
+   Title = the other geometry
+   Abstract = the other geometry to compare against.
+   minOccurs = 1
+   maxOccurs = 1
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+     encoding = UTF-8
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Supported>
+   </ComplexData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = Contains result
+   Abstract = A value true or false if the geometry1 contains the geometry2.
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+    <LiteralData>
+      dataType=boolean
+      <Default />
+    </LiteralData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/IsSimple.zcfg b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/IsSimple.zcfg
new file mode 100644
index 0000000..f1ad982
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/IsSimple.zcfg
@@ -0,0 +1,37 @@
+[IsSimple]
+ Title = IsSimple test 
+ Abstract = This service shall return a true value if and only if geometry g has no anomalous geometric points, such as self intersection or self tangency. Simple curves intersect themselves only at their endpoints (only if they are also closed, see next function).
+ Profile = urn:ogc:wps:1.0.0:union
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = ogr_service.zo
+ serviceType = C
+ <DataInputs>
+  [InputPolygon]
+   Title = the first geometry 
+   Abstract = the first geometry to compare against.
+   minOccurs = 1
+   maxOccurs = 1
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Supported>
+   </ComplexData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = IsSimple result
+   Abstract = The boolean result
+    <LiteralData>
+      dataType=boolean
+      <Default />
+    </LiteralData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/IsValid.zcfg b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/IsValid.zcfg
new file mode 100644
index 0000000..317e790
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/IsValid.zcfg
@@ -0,0 +1,37 @@
+[IsValid]
+ Title = IsValid test 
+ Abstract = This service shall return a TRUE value if and only if the geometry g is valid
+ Profile = urn:ogc:wps:1.0.0:union
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = ogr_service.zo
+ serviceType = C
+ <DataInputs>
+  [InputPolygon]
+   Title = the first geometry 
+   Abstract = the first geometry to compare against.
+   minOccurs = 1
+   maxOccurs = 1
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Supported>
+   </ComplexData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = Equals result
+   Abstract = Should be true if two geometries are equivalent..
+    <LiteralData>
+      dataType=boolean
+      <Default />
+    </LiteralData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Simplify.zcfg b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Simplify.zcfg
new file mode 100755
index 0000000..5eb4257
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Simplify.zcfg
@@ -0,0 +1,61 @@
+[Simplify]
+ Title = Simplifies polygons geometries. 
+ Abstract = This service shall return a feature collection representing all simplified geometries with all their vertices within the distance of the original geometry defined by the given tolerance.
+ Profile = urn:ogc:wps:1.0.0:buffer
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = ogr_service.zo
+ serviceType = C
+ <DataInputs>
+  [InputPolygon]
+   Title = Polygon to be simplified
+   Abstract = URI to a set of GML that describes the polygon.
+   minOccurs = 1
+   maxOccurs = 1
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+     asReference = true	
+    </Default>
+    <Supported>
+     mimeType = application/json
+     encoding = UTF-8
+    </Supported>
+   </ComplexData>
+  [Tolerance]
+   Title = Buffer Distance
+   Abstract = Distance tolerance for the simplification.
+   minOccurs = 0
+   maxOccurs = 1
+   <LiteralData>
+    DataType = float
+    <Default>
+     uom = meters
+     value = 2
+    </Default>
+    <Supported>
+     uom = feet
+    </Supported>
+   </LiteralData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = Simplified features
+   Abstract = GML stream describing the simplified features.
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+     extension = xml
+    </Default>
+    <Supported>
+     mimeType = application/json
+     encoding = UTF-8
+     extension = js
+    </Supported>
+   </ComplexData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/SymDifference.zcfg b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/SymDifference.zcfg
new file mode 100755
index 0000000..68e090a
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/SymDifference.zcfg
@@ -0,0 +1,75 @@
+[SymDifference]
+ Title = Compute symmetric difference. 
+ Abstract = This service shall return a feature collection representing the closure of the symmetric difference of two Geometries. The symmetric difference is the set of points which lie on either InputEntity1 or InputEntity2 but not in both.
+ Profile = urn:ogc:wps:1.0.0:symmetricdifference
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = ogr_service.zo
+ serviceType = C
+ <MetaData>
+   title = Demo
+ </MetaData>
+ <DataInputs>
+  [InputEntity1]
+   Title = the first geometry 
+   Abstract = the first geometry to compare against.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Supported>
+   </ComplexData>
+  [InputEntity2]
+   Title = the other geometry
+   Abstract = the other geometry to compare against.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+     encoding = UTF-8
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Supported>
+   </ComplexData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = The resulting geometry
+   Abstract = The symmetric difference of two geometries
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+    <ComplexData>
+     <Default>
+      mimeType = text/xml
+      schema = http://fooa/gml/3.1.0/polygon.xsd
+      encoding = UTF-8
+      extension = xml
+     </Default>
+     <Supported>
+      mimeType = application/json
+      encoding = UTF-8
+      extension = js
+     </Supported>
+    </ComplexData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Touches.zcfg b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Touches.zcfg
new file mode 100644
index 0000000..066131f
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Touches.zcfg
@@ -0,0 +1,57 @@
+[Touches]
+ Title = Compute intersection. 
+ Abstract = Generates a new geometry which is the region of intersection of the two geometries operated on.
+ Profile = urn:ogc:wps:1.0.0:union
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = ogr_service.zo
+ serviceType = C
+ <DataInputs>
+  [InputEntity1]
+   Title = the first geometry 
+   Abstract = the first geometry to compare against.
+   minOccurs = 1
+   maxOccurs = 1
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Supported>
+   </ComplexData>
+  [InputEntity2]
+   Title = the other geometry
+   Abstract = the other geometry to compare against.
+   minOccurs = 1
+   maxOccurs = 1
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+     encoding = UTF-8
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Supported>
+   </ComplexData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = Intersects result
+   Abstract = A value true or false if the geometry1 and geometry2 touches.
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+    <LiteralData>
+      dataType=boolean
+      <Default />
+    </LiteralData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Union.zcfg b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Union.zcfg
new file mode 100755
index 0000000..e914f09
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Union.zcfg
@@ -0,0 +1,75 @@
+[Union]
+ Title = Compute union. 
+ Abstract = This service shall return a bag of geometry values representing a Point set union of geometry InputEntity1 with geometry InputEntity2.
+ profile = urn:ogc:wps:1.0.0:union
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = ogr_service.zo
+ serviceType = C
+ <MetaData>
+   title = Demo
+ </MetaData>
+ <DataInputs>
+  [InputEntity1]
+   Title = the first geometry 
+   Abstract = the first geometry to compare against.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Supported>
+   </ComplexData>
+  [InputEntity2]
+   Title = the other geometry
+   Abstract = the other geometry to compare against.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+     encoding = UTF-8
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Supported>
+   </ComplexData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = The union of two geometries
+   Abstract = The geometry representing the union of the two geometries.
+   <MetaData>
+    title = Mon test  
+   </MetaData>
+    <ComplexData>
+     <Default>
+      mimeType = text/xml
+      schema = http://fooa/gml/3.1.0/polygon.xsd
+      encoding = UTF-8
+      extension = xml
+     </Default>
+     <Supported>
+      mimeType = application/json
+      encoding = UTF-8
+      extension = js
+     </Supported>
+    </ComplexData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Within.zcfg b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Within.zcfg
new file mode 100644
index 0000000..ada055a
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/base-vect-ops/cgi-env/Within.zcfg
@@ -0,0 +1,57 @@
+[Within]
+ Title = Within test
+ Abstract = This service shall return a true value if and only if the geometry InputEntity1 is spatially within geometry InputEntity2; that is if every point on InputEntity1 is also on InputEntity2.
+ Profile = urn:ogc:wps:1.0.0:union
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = ogr_service.zo
+ serviceType = C
+ <DataInputs>
+  [InputEntity1]
+   Title = the first geometry 
+   Abstract = the first geometry.
+   minOccurs = 1
+   maxOccurs = 1
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Supported>
+   </ComplexData>
+  [InputEntity2]
+   Title = the other geometry
+   Abstract = the other geometry.
+   minOccurs = 1
+   maxOccurs = 1
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+     encoding = UTF-8
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Supported>
+   </ComplexData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = Within result
+   Abstract = A value true or false if the geometry1 contains the geometry2.
+   <MetaData>
+    title = Mon test  
+   </MetaData>   
+    <LiteralData>
+      dataType=boolean
+      <Default />
+    </LiteralData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/ogr/base-vect-ops/locale/po/fr_FR.utf8.po b/zoo-project/zoo-services/ogr/base-vect-ops/locale/po/fr_FR.utf8.po
new file mode 100644
index 0000000..c1e3a5f
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/base-vect-ops/locale/po/fr_FR.utf8.po
@@ -0,0 +1,320 @@
+# French translations for PACKAGE package.
+# Copyright (C) 2010 THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# root <gerald.fenoy at geolabs.fr>, 2010.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: zoo-services\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-09-28 12:52+0200\n"
+"PO-Revision-Date: 2010-09-28 12:55+0200\n"
+"Last-Translator: root <gerald.fenoy at geolabs.fr>\n"
+"Language-Team: French\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
+#: locale/.cache/my_service_string_to_translate.c:1
+msgid "Compute boundary."
+msgstr "Calcul le contour."
+
+#: locale/.cache/my_service_string_to_translate.c:2
+msgid "Polygon to compute boundary"
+msgstr "Le polygon à utiliser pour calculer le contour"
+
+#: locale/.cache/my_service_string_to_translate.c:3
+msgid "The geometry created"
+msgstr "La géométrie créée"
+
+#: locale/.cache/my_service_string_to_translate.c:4
+msgid ""
+"A new geometry object is created and returned containing the boundary of the "
+"geometry on which the method is invoked. "
+msgstr ""
+"Un nouvel objet géographique contenant le contour de la géométrie passée en "
+"paramètre est créé et retourné. "
+
+#: locale/.cache/my_service_string_to_translate.c:5
+#: locale/.cache/my_service_string_to_translate.c:12
+#: locale/.cache/my_service_string_to_translate.c:25
+#: locale/.cache/my_service_string_to_translate.c:47
+#: locale/.cache/my_service_string_to_translate.c:62
+msgid "URI to a set of GML that describes the polygon."
+msgstr "Le lien vers un fichier GML décrivant un polygone."
+
+#: locale/.cache/my_service_string_to_translate.c:6
+msgid ""
+"The geometry containing the boundary of the geometry on which the method is "
+"invoked."
+msgstr ""
+"La géométrie contenant le contour de la géométrie passée en paramètre."
+
+#: locale/.cache/my_service_string_to_translate.c:7
+msgid "Create a buffer around a polygon. "
+msgstr "Crée une zone tampon atour du polygone."
+
+#: locale/.cache/my_service_string_to_translate.c:8
+msgid "Polygon to be buffered"
+msgstr "Le Polygone à utiliser"
+
+#: locale/.cache/my_service_string_to_translate.c:9
+msgid "Buffer Distance"
+msgstr "La distance pour créer la zone tampon"
+
+#: locale/.cache/my_service_string_to_translate.c:10
+msgid "Buffered Polygon"
+msgstr "La zone tampon correspondant au polygone "
+
+#: locale/.cache/my_service_string_to_translate.c:11
+msgid ""
+"Create a buffer around a single polygon. Accepts the polygon as GML and "
+"provides GML output for the buffered feature. "
+msgstr ""
+"Crée une zone tampon autour d'un polygone. Prend en entrée un GML et fournit une "
+"chaîne GeoJSON de la zone tampon. "
+
+#: locale/.cache/my_service_string_to_translate.c:13
+msgid "Distance to be used to calculate buffer."
+msgstr "La distance à utiliser pour créer la zone tampon."
+
+#: locale/.cache/my_service_string_to_translate.c:14
+msgid "GML stream describing the buffered polygon feature."
+msgstr "Une chaîne GeoJSON contenant la zone tampon."
+
+#: locale/.cache/my_service_string_to_translate.c:15
+msgid "Get the centroid of a polygon. "
+msgstr "Renvoit le centroid d'un polygone"
+
+#: locale/.cache/my_service_string_to_translate.c:16
+msgid "Polygon to get the centroid"
+msgstr "Le polygone à utiliser pour calculer le centroid"
+
+#: locale/.cache/my_service_string_to_translate.c:17
+msgid "The Centroid"
+msgstr "Le centroid"
+
+#: locale/.cache/my_service_string_to_translate.c:18
+msgid "Compute the geometry centroid."
+msgstr "Calcul le centroid d'une géométrie"
+
+#: locale/.cache/my_service_string_to_translate.c:19
+msgid "The centroid which is not necessarily within the geometry."
+msgstr "Le centroid qui n'est pas nécessairement dans la géométrie."
+
+#: locale/.cache/my_service_string_to_translate.c:20
+msgid "JSON String / GML Entity of the centroid"
+msgstr "La chaîne GeoJSON ou l'entité GML du centroid"
+
+#: locale/.cache/my_service_string_to_translate.c:21
+msgid "Compute convex hull."
+msgstr "Calcul de la partie convexe"
+
+#: locale/.cache/my_service_string_to_translate.c:22
+msgid "Polygon to compute convexhull"
+msgstr "Polygone pour calculer la partie convexe"
+
+#: locale/.cache/my_service_string_to_translate.c:23
+#: locale/.cache/my_service_string_to_translate.c:26
+msgid "The convex hull of the geometry"
+msgstr "La partie convexe de la géométrie"
+
+#: locale/.cache/my_service_string_to_translate.c:24
+msgid ""
+"A new geometry object is created and returned containing the convex hull of "
+"the geometry on which the method is invoked."
+msgstr ""
+"Un nouvel objet géographique est créé et retourné. Il contient la partie convexe de la "
+"géométrie sur laquelle on a appliqué la méthode."
+
+#: locale/.cache/my_service_string_to_translate.c:27
+msgid "Compute difference. . "
+msgstr "Calcul de la différence."
+
+#: locale/.cache/my_service_string_to_translate.c:28
+#: locale/.cache/my_service_string_to_translate.c:36
+#: locale/.cache/my_service_string_to_translate.c:50
+#: locale/.cache/my_service_string_to_translate.c:66
+#: locale/.cache/my_service_string_to_translate.c:74
+msgid "the first geometry "
+msgstr "La première géométrie"
+
+#: locale/.cache/my_service_string_to_translate.c:29
+#: locale/.cache/my_service_string_to_translate.c:37
+#: locale/.cache/my_service_string_to_translate.c:51
+#: locale/.cache/my_service_string_to_translate.c:67
+#: locale/.cache/my_service_string_to_translate.c:75
+msgid "the other geometry"
+msgstr "L'autre géométrie"
+
+#: locale/.cache/my_service_string_to_translate.c:30
+msgid "The difference between two geometries"
+msgstr "La différence entre les deux géométries"
+
+#: locale/.cache/my_service_string_to_translate.c:31
+msgid ""
+"Generates a new geometry which is the region of this geometry with the "
+"region of the other geometry removed."
+msgstr ""
+"Génère une nouvelle géométrie qui contient la région de la géométrie dont on a "
+"supprimé l'autre géométrie."
+
+
+#: locale/.cache/my_service_string_to_translate.c:32
+#: locale/.cache/my_service_string_to_translate.c:40
+#: locale/.cache/my_service_string_to_translate.c:54
+#: locale/.cache/my_service_string_to_translate.c:70
+#: locale/.cache/my_service_string_to_translate.c:78
+msgid "the first geometry to compare against."
+msgstr "La première géométrie utilisée pour la comparaison"
+
+#: locale/.cache/my_service_string_to_translate.c:33
+#: locale/.cache/my_service_string_to_translate.c:41
+#: locale/.cache/my_service_string_to_translate.c:55
+#: locale/.cache/my_service_string_to_translate.c:71
+#: locale/.cache/my_service_string_to_translate.c:79
+msgid "the other geometry to compare against."
+msgstr "L'autre géométrie à comparer."
+
+#: locale/.cache/my_service_string_to_translate.c:34
+msgid "The difference between the two geometries."
+msgstr "La différence entre les deux géométries."
+
+#: locale/.cache/my_service_string_to_translate.c:35
+msgid "Calcul la distance entre deux entites geographique. "
+msgstr "Calcul de la distance entre deux objets géographiques."
+
+#: locale/.cache/my_service_string_to_translate.c:38
+msgid "The distance between two geometries"
+msgstr "La distance entre deux géométries"
+
+#: locale/.cache/my_service_string_to_translate.c:39
+msgid "Calcul de la distance entre deux entites geographique. "
+msgstr "Calcul de la distance entre deux entités géographiques."
+
+#: locale/.cache/my_service_string_to_translate.c:42
+msgid "The shortest distance between the two geometries."
+msgstr "La plus courte distance entre de géométries."
+
+#: locale/.cache/my_service_string_to_translate.c:43
+msgid "Compute geometry area."
+msgstr "Calcul l'aire de la géométrie."
+
+#: locale/.cache/my_service_string_to_translate.c:44
+msgid "Polygon to compute are"
+msgstr "Le polygone à utiliser"
+
+#: locale/.cache/my_service_string_to_translate.c:45
+msgid "Computed Area"
+msgstr "L'aire calculée"
+
+#: locale/.cache/my_service_string_to_translate.c:46
+msgid "Computes the area for a geometry"
+msgstr "Calcul de l'aire d'une géométrie"
+
+#: locale/.cache/my_service_string_to_translate.c:48
+msgid "The Computed Area Value"
+msgstr "La valeur de l'aire calculée"
+
+#: locale/.cache/my_service_string_to_translate.c:49
+msgid "Compute intersection. "
+msgstr "Calcul de l'intersection."
+
+#: locale/.cache/my_service_string_to_translate.c:52
+msgid "Intersection of geometries"
+msgstr "L'intersection des géométries."
+
+#: locale/.cache/my_service_string_to_translate.c:53
+msgid ""
+"Generates a new geometry which is the region of intersection of the two "
+"geometries operated on."
+msgstr ""
+"Crée une nouvelle géométrie qui représente l'intersection des deux géométries avec "
+"lesquelles le service est utilisé."
+
+#: locale/.cache/my_service_string_to_translate.c:56
+msgid ""
+"A new geometry representing the intersection or NULL if there is no "
+"intersection or an error occurs."
+msgstr ""
+"Une nouvelle géométrie représentant l'intersection ou NULL si l'intersection est vide "
+"si une erreur s'est produite."
+
+#: locale/.cache/my_service_string_to_translate.c:57
+msgid "Douglas-Peucker like algorithm"
+msgstr "Algorythme de simplification de type Douglas-Peucker"
+
+#: locale/.cache/my_service_string_to_translate.c:58
+msgid "Polygon to simplify"
+msgstr "Le polygone à simplifier"
+
+#: locale/.cache/my_service_string_to_translate.c:59
+msgid "Tolerance to use."
+msgstr "La tolérance à utliser."
+
+#: locale/.cache/my_service_string_to_translate.c:60
+msgid "The simplified geometry"
+msgstr "La géométrie simplifiée"
+
+#: locale/.cache/my_service_string_to_translate.c:61
+msgid ""
+"Simplifies a geometry, ensuring that the result is a valid geometry having "
+"the same dimension and number of components as the input. The simplification "
+"uses a maximum distance difference algorithm similar to the one used in the "
+"Douglas-Peucker algorithm."
+msgstr ""
+"Simplifie une géométrie, en s'assurant que le résultat soit une géométrie valide "
+"ayant la même dimension et le même nombre de composants que la donnée d'entrée. "
+"La simplification utilise un algorythme similaire à l'algorythme Douglas-Peucker."
+
+#: locale/.cache/my_service_string_to_translate.c:63
+msgid "The approximation tolerance to use."
+msgstr "La valeur approximative de la tolérance à utiliser."
+
+#: locale/.cache/my_service_string_to_translate.c:64
+msgid ""
+"The result has the same number of shells and holes (rings) as the input, in "
+"the same order. The result rings touch at no more than the number of "
+"touching point in the input (although they may touch at fewer points)."
+msgstr ""
+"Le résultat a le même nombre composant que l'entrée, dans le même ordre. "
+
+#: locale/.cache/my_service_string_to_translate.c:65
+msgid "Compute symmetric difference. "
+msgstr "Calcul de la différence symétrique."
+
+#: locale/.cache/my_service_string_to_translate.c:68
+msgid "The resulting geometry"
+msgstr "La géométrie résultat"
+
+#: locale/.cache/my_service_string_to_translate.c:69
+msgid ""
+"Generates a new geometry which is the symmetric difference of this geometry "
+"and the other geometry."
+msgstr ""
+"Crée une nouvelle géométrie qui est la difference symétrique des géométries."
+
+#: locale/.cache/my_service_string_to_translate.c:72
+msgid "The symmetric difference of two geometries"
+msgstr "La différence symmétrique de deux géométries"
+
+#: locale/.cache/my_service_string_to_translate.c:73
+msgid "Compute union. "
+msgstr "Cacul l'union."
+
+#: locale/.cache/my_service_string_to_translate.c:76
+msgid "The union of two geometries"
+msgstr "L'union de deux géométries"
+
+#: locale/.cache/my_service_string_to_translate.c:77
+msgid ""
+"Generates a new geometry which is the region of union of the two geometries "
+"operated on."
+msgstr ""
+"Génère une nouvelle géométrie qui est l'union des deux géométrie passées en "
+"paramètre."
+
+#: locale/.cache/my_service_string_to_translate.c:80
+msgid "The geometry representing the union of the two geometries."
+msgstr "La géométrie représentant l'union des deux géométries."
diff --git a/zoo-project/zoo-services/ogr/base-vect-ops/locale/po/ja_JP.utf8.po b/zoo-project/zoo-services/ogr/base-vect-ops/locale/po/ja_JP.utf8.po
new file mode 100644
index 0000000..27db10d
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/base-vect-ops/locale/po/ja_JP.utf8.po
@@ -0,0 +1,308 @@
+# Japanese translations for PACKAGE package.
+# Copyright (C) 2010 THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the ZOO Services package.
+# Daisuke YOSHIDA <yoshida at la.tezuka-gu.ac.jp>, 2010.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: zoo-services\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-09-28 12:52+0200\n"
+"PO-Revision-Date: 2010-09-28 12:55+0200\n"
+"Last-Translator: Daisuke YOSHIDA <yoshida at la.tezuka-gu.ac.jp>\n"
+"Language-Team: Japanese\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
+#: locale/.cache/my_service_string_to_translate.c:1
+msgid "Compute boundary."
+msgstr "境界線を計算."
+
+#: locale/.cache/my_service_string_to_translate.c:2
+msgid "Polygon to compute boundary"
+msgstr "境界線を計算するためのポリゴン."
+
+#: locale/.cache/my_service_string_to_translate.c:3
+msgid "The geometry created"
+msgstr "ジオメトリが作成される."
+
+#: locale/.cache/my_service_string_to_translate.c:4
+msgid ""
+"A new geometry object is created and returned containing the boundary of the "
+"geometry on which the method is invoked. "
+msgstr "新しいジオメトリオブジェクトは作成され,メソッド上に返答された境界面を含むジオメトリが,呼び出される."
+
+
+#: locale/.cache/my_service_string_to_translate.c:5
+#: locale/.cache/my_service_string_to_translate.c:12
+#: locale/.cache/my_service_string_to_translate.c:25
+#: locale/.cache/my_service_string_to_translate.c:47
+#: locale/.cache/my_service_string_to_translate.c:62
+msgid "URI to a set of GML that describes the polygon."
+msgstr "ポリゴンが記述されているGMLセットへのURI."
+
+#: locale/.cache/my_service_string_to_translate.c:6
+msgid ""
+"The geometry containing the boundary of the geometry on which the method is "
+"invoked."
+msgstr "メソッド上の地質境界面を含んでいるジオメトリを起動."
+
+
+#: locale/.cache/my_service_string_to_translate.c:7
+msgid "Create a buffer around a polygon. "
+msgstr "ポリゴン周辺のバッファを作成."
+
+#: locale/.cache/my_service_string_to_translate.c:8
+msgid "Polygon to be buffered"
+msgstr "バッファリングするポリゴン."
+
+#: locale/.cache/my_service_string_to_translate.c:9
+msgid "Buffer Distance"
+msgstr "バッファ距離."
+
+#: locale/.cache/my_service_string_to_translate.c:10
+msgid "Buffered Polygon"
+msgstr "バッファリングされたポリゴン. "
+
+#: locale/.cache/my_service_string_to_translate.c:11
+msgid ""
+"Create a buffer around a single polygon. Accepts the polygon as GML and "
+"provides GML output for the buffered feature. "
+msgstr "シングルポリゴン周辺のバッファの作成.GMLとしてポリゴンを許可し,バッファリングされたフィーチャーのためのGMLを提供."
+
+#: locale/.cache/my_service_string_to_translate.c:13
+msgid "Distance to be used to calculate buffer."
+msgstr "バッファを計算するために使われる距離."
+
+#: locale/.cache/my_service_string_to_translate.c:14
+msgid "GML stream describing the buffered polygon feature."
+msgstr "バッファリングされたポリゴンフィーチャーを記述するGML."
+
+#: locale/.cache/my_service_string_to_translate.c:15
+msgid "Get the centroid of a polygon. "
+msgstr "ポリゴンの中心点を取得."
+
+#: locale/.cache/my_service_string_to_translate.c:16
+msgid "Polygon to get the centroid"
+msgstr "中心点を取得するためのポリゴン."
+
+#: locale/.cache/my_service_string_to_translate.c:17
+msgid "The Centroid"
+msgstr "中心点."
+
+#: locale/.cache/my_service_string_to_translate.c:18
+msgid "Compute the geometry centroid."
+msgstr "ジオメトリの中心点を計算."
+
+#: locale/.cache/my_service_string_to_translate.c:19
+msgid "The centroid which is not necessarily within the geometry."
+msgstr "ジオメトリに含まれる重要ではない中心点."
+
+#: locale/.cache/my_service_string_to_translate.c:20
+msgid "JSON String / GML Entity of the centroid"
+msgstr "中心点のJSON文字列/GMLエンティティ."
+
+#: locale/.cache/my_service_string_to_translate.c:21
+msgid "Compute convex hull."
+msgstr "凸包を計算."
+
+#: locale/.cache/my_service_string_to_translate.c:22
+msgid "Polygon to compute convex hull"
+msgstr "凸包を計算するポリゴン."
+
+#: locale/.cache/my_service_string_to_translate.c:23
+#: locale/.cache/my_service_string_to_translate.c:26
+msgid "The convex hull of the geometry"
+msgstr "ジオメトリの凸包."
+
+#: locale/.cache/my_service_string_to_translate.c:24
+msgid ""
+"A new geometry object is created and returned containing the convex hull of "
+"the geometry on which the method is invoked."
+msgstr "新しいジオメトリオブジェクトは作成されメッソド上に返答され,凸包を含むジオメトリが呼び出される."
+
+
+#: locale/.cache/my_service_string_to_translate.c:27
+msgid "Compute difference. . "
+msgstr "差分の計算."
+
+#: locale/.cache/my_service_string_to_translate.c:28
+#: locale/.cache/my_service_string_to_translate.c:36
+#: locale/.cache/my_service_string_to_translate.c:50
+#: locale/.cache/my_service_string_to_translate.c:66
+#: locale/.cache/my_service_string_to_translate.c:74
+msgid "the first geometry "
+msgstr "最初のジオメトリ."
+
+#: locale/.cache/my_service_string_to_translate.c:29
+#: locale/.cache/my_service_string_to_translate.c:37
+#: locale/.cache/my_service_string_to_translate.c:51
+#: locale/.cache/my_service_string_to_translate.c:67
+#: locale/.cache/my_service_string_to_translate.c:75
+msgid "the other geometry"
+msgstr "その他のジオメトリ."
+
+#: locale/.cache/my_service_string_to_translate.c:30
+msgid "The difference between two geometries"
+msgstr "2つのジオメトリの差。"
+
+#: locale/.cache/my_service_string_to_translate.c:31
+msgid ""
+"Generates a new geometry which is the region of this geometry with the "
+"region of the other geometry removed."
+msgstr "他のジオメトリを削除した領域に,このジオメトリの領域の新しいジオメトリ"
+"を作成"
+
+
+#: locale/.cache/my_service_string_to_translate.c:32
+#: locale/.cache/my_service_string_to_translate.c:40
+#: locale/.cache/my_service_string_to_translate.c:54
+#: locale/.cache/my_service_string_to_translate.c:70
+#: locale/.cache/my_service_string_to_translate.c:78
+msgid "the first geometry to compare against."
+msgstr "対比比較する最初のジオメトリ."
+
+#: locale/.cache/my_service_string_to_translate.c:33
+#: locale/.cache/my_service_string_to_translate.c:41
+#: locale/.cache/my_service_string_to_translate.c:55
+#: locale/.cache/my_service_string_to_translate.c:71
+#: locale/.cache/my_service_string_to_translate.c:79
+msgid "the other geometry to compare against."
+msgstr "対比比較するその他のジオメトリ."
+
+#: locale/.cache/my_service_string_to_translate.c:34
+msgid "The difference between the two geometries."
+msgstr "2つのジオメトリの差分."
+
+#: locale/.cache/my_service_string_to_translate.c:35
+msgid "Calcul la distance entre deux entites geographique. "
+msgstr "Calcul de la distance entre deux objets géographiques."
+
+#: locale/.cache/my_service_string_to_translate.c:38
+msgid "The distance between two geometries"
+msgstr "2つのジオメトリの距離."
+
+#: locale/.cache/my_service_string_to_translate.c:39
+msgid "Calcul de la distance entre deux entites geographique. "
+msgstr "Calcul de la distance entre deux entités géographiques."
+
+#: locale/.cache/my_service_string_to_translate.c:42
+msgid "The shortest distance between the two geometries."
+msgstr "二つのジオメトリの最短距離."
+
+#: locale/.cache/my_service_string_to_translate.c:43
+msgid "Compute geometry area."
+msgstr "ジオメトリ面積の計算."
+
+#: locale/.cache/my_service_string_to_translate.c:44
+msgid "Polygon to compute area"
+msgstr "面積計算するためのポリゴン."
+
+#: locale/.cache/my_service_string_to_translate.c:45
+msgid "Computed Area"
+msgstr "面積計算."
+
+#: locale/.cache/my_service_string_to_translate.c:46
+msgid "Computes the area for a geometry"
+msgstr "ジオメトリの面積を計算する."
+
+#: locale/.cache/my_service_string_to_translate.c:48
+msgid "The Computed Area Value"
+msgstr "計算された面積の値."
+
+#: locale/.cache/my_service_string_to_translate.c:49
+msgid "Compute intersection. "
+msgstr "交点を計算する."
+
+#: locale/.cache/my_service_string_to_translate.c:52
+msgid "Intersection of geometries"
+msgstr "ジオメトリの交点."
+
+#: locale/.cache/my_service_string_to_translate.c:53
+msgid ""
+"Generates a new geometry which is the region of intersection of the two "
+"geometries operated on."
+msgstr "操作された2つのジオメトリの交点の領域の新しいジオメトリを作成."
+
+
+#: locale/.cache/my_service_string_to_translate.c:56
+msgid ""
+"A new geometry representing the intersection or NULL if there is no "
+"intersection or an error occurs."
+msgstr "もし交点、またはエラーが起こっていない場合、交点またはNULLを表す新しいジオメトリ."
+
+#: locale/.cache/my_service_string_to_translate.c:57
+msgid "Douglas-Peucker like algorithm"
+msgstr "Douglas-Peucker的アルゴリズム."
+
+#: locale/.cache/my_service_string_to_translate.c:58
+msgid "Polygon to simplify"
+msgstr "単純化するためのポリゴン."
+
+#: locale/.cache/my_service_string_to_translate.c:59
+msgid "Tolerance to use."
+msgstr "使用する許容値."
+
+#: locale/.cache/my_service_string_to_translate.c:60
+msgid "The simplified geometry"
+msgstr "単純化されたジオメトリ."
+
+#: locale/.cache/my_service_string_to_translate.c:61
+msgid ""
+"Simplifies a geometry, ensuring that the result is a valid geometry having "
+"the same dimension and number of components as the input. The simplification "
+"uses a maximum distance difference algorithm similar to the one used in the "
+"Douglas-Peucker algorithm."
+msgstr ""
+"ジオメトリを単純化"
+"結果がインプットとして同じ次元とコンポーネント数が等しい有効なジオメトリか確認."
+"単純化では,Douglas-Peuckerアルゴリズムと類似した最大距離を使うアルゴリズムを使用."
+
+#: locale/.cache/my_service_string_to_translate.c:63
+msgid "The approximation tolerance to use."
+msgstr "使用する許容値の概要."
+
+#: locale/.cache/my_service_string_to_translate.c:64
+msgid ""
+"The result has the same number of shells and holes (rings) as the input, in "
+"the same order. The result rings touch at no more than the number of "
+"touching point in the input (although they may touch at fewer points)."
+msgstr "結果はインプットとしてshells とholes (rings)が共に等しい数,順序になる."
+"結果のリングはインプットの中のタッチングポイントの数まで達しない.(しかし,より少ないポイントをタッチするかもしれない."
+#: locale/.cache/my_service_string_to_translate.c:65
+msgid "Compute symmetric difference. "
+msgstr "対照的な差を計算."
+
+#: locale/.cache/my_service_string_to_translate.c:68
+msgid "The resulting geometry"
+msgstr "ジオメトリの結果."
+
+#: locale/.cache/my_service_string_to_translate.c:69
+msgid ""
+"Generates a new geometry which is the symmetric difference of this geometry "
+"and the other geometry."
+msgstr "このジオメトリと他のジオメトリで,対照的に異なった新しいジオメトリの作成"
+
+#: locale/.cache/my_service_string_to_translate.c:72
+msgid "The symmetric difference of two geometries"
+msgstr "2つのジオメトリの対照的違い."
+
+#: locale/.cache/my_service_string_to_translate.c:73
+msgid "Compute union. "
+msgstr "結合の計算."
+
+#: locale/.cache/my_service_string_to_translate.c:76
+msgid "The union of two geometries"
+msgstr "2つのジオメトリの結合"
+
+#: locale/.cache/my_service_string_to_translate.c:77
+msgid ""
+"Generates a new geometry which is the region of union of the two geometries "
+"operated on."
+msgstr "操作された2つのジオメトリを結合した領域の新しいジオメトリの作成"
+
+#: locale/.cache/my_service_string_to_translate.c:80
+msgid "The geometry representing the union of the two geometries."
+msgstr "2つのジオメトリの結合を表すジオメトリ"
diff --git a/zoo-project/zoo-services/ogr/base-vect-ops/locale/po/messages.po b/zoo-project/zoo-services/ogr/base-vect-ops/locale/po/messages.po
new file mode 100644
index 0000000..0a7c9db
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/base-vect-ops/locale/po/messages.po
@@ -0,0 +1,299 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL at ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: zoo-services\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-09-28 12:52+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Gérald Fenoy <gerald.fenoy at geolabs.fr>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: locale/.cache/my_service_string_to_translate.c:1
+msgid "Compute boundary."
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:2
+msgid "Polygon to compute boundary"
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:3
+msgid "The geometry created"
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:4
+msgid ""
+"A new geometry object is created and returned containing the boundary of the "
+"geometry on which the method is invoked. "
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:5
+#: locale/.cache/my_service_string_to_translate.c:12
+#: locale/.cache/my_service_string_to_translate.c:25
+#: locale/.cache/my_service_string_to_translate.c:47
+#: locale/.cache/my_service_string_to_translate.c:62
+msgid "URI to a set of GML that describes the polygon."
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:6
+msgid ""
+"The geometry containing the boundary of the geometry on which the method is "
+"invoked."
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:7
+msgid "Create a buffer around a polygon. "
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:8
+msgid "Polygon to be buffered"
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:9
+msgid "Buffer Distance"
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:10
+msgid "Buffered Polygon"
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:11
+msgid ""
+"Create a buffer around a single polygon. Accepts the polygon as GML and "
+"provides GML output for the buffered feature. "
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:13
+msgid "Distance to be used to calculate buffer."
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:14
+msgid "GML stream describing the buffered polygon feature."
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:15
+msgid "Get the centroid of a polygon. "
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:16
+msgid "Polygon to get the centroid"
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:17
+msgid "The Centroid"
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:18
+msgid "Compute the geometry centroid."
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:19
+msgid "The centroid which is not necessarily within the geometry."
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:20
+msgid "JSON String / GML Entity of the centroid"
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:21
+msgid "Compute convex hull."
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:22
+msgid "Polygon to compute convexhull"
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:23
+#: locale/.cache/my_service_string_to_translate.c:26
+msgid "The convex hull of the geometry"
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:24
+msgid ""
+"A new geometry object is created and returned containing the convex hull of "
+"the geometry on which the method is invoked."
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:27
+msgid "Compute difference. . "
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:28
+#: locale/.cache/my_service_string_to_translate.c:36
+#: locale/.cache/my_service_string_to_translate.c:50
+#: locale/.cache/my_service_string_to_translate.c:66
+#: locale/.cache/my_service_string_to_translate.c:74
+msgid "the first geometry "
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:29
+#: locale/.cache/my_service_string_to_translate.c:37
+#: locale/.cache/my_service_string_to_translate.c:51
+#: locale/.cache/my_service_string_to_translate.c:67
+#: locale/.cache/my_service_string_to_translate.c:75
+msgid "the other geometry"
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:30
+msgid "The difference between two geometries"
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:31
+msgid ""
+"Generates a new geometry which is the region of this geometry with the "
+"region of the other geometry removed."
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:32
+#: locale/.cache/my_service_string_to_translate.c:40
+#: locale/.cache/my_service_string_to_translate.c:54
+#: locale/.cache/my_service_string_to_translate.c:70
+#: locale/.cache/my_service_string_to_translate.c:78
+msgid "the first geometry to compare against."
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:33
+#: locale/.cache/my_service_string_to_translate.c:41
+#: locale/.cache/my_service_string_to_translate.c:55
+#: locale/.cache/my_service_string_to_translate.c:71
+#: locale/.cache/my_service_string_to_translate.c:79
+msgid "the other geometry to compare against."
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:34
+msgid "The difference between the two geometries."
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:35
+msgid "Calcul la distance entre deux entites geographique. "
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:38
+msgid "The distance between two geometries"
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:39
+msgid "Calcul de la distance entre deux entites geographique. "
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:42
+msgid "The shortest distance between the two geometries."
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:43
+msgid "Compute geometry area."
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:44
+msgid "Polygon to compute are"
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:45
+msgid "Computed Area"
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:46
+msgid "Computes the area for a geometry"
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:48
+msgid "The Computed Area Value"
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:49
+msgid "Compute intersection. "
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:52
+msgid "Intersection of geometries"
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:53
+msgid ""
+"Generates a new geometry which is the region of intersection of the two "
+"geometries operated on."
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:56
+msgid ""
+"A new geometry representing the intersection or NULL if there is no "
+"intersection or an error occurs."
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:57
+msgid "Douglas-Peucker like algorithm"
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:58
+msgid "Polygon to simplify"
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:59
+msgid "Tolerance to use."
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:60
+msgid "The simplified geometry"
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:61
+msgid ""
+"Simplifies a geometry, ensuring that the result is a valid geometry having "
+"the same dimension and number of components as the input. The simplification "
+"uses a maximum distance difference algorithm similar to the one used in the "
+"Douglas-Peucker algorithm."
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:63
+msgid "The approximation tolerance to use."
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:64
+msgid ""
+"The result has the same number of shells and holes (rings) as the input, in "
+"the same order. The result rings touch at no more than the number of "
+"touching point in the input (although they may touch at fewer points)."
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:65
+msgid "Compute symmetric difference. "
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:68
+msgid "The resulting geometry"
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:69
+msgid ""
+"Generates a new geometry which is the symmetric difference of this geometry "
+"and the other geometry."
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:72
+msgid "The symmetric difference of two geometries"
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:73
+msgid "Compute union. "
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:76
+msgid "The union of two geometries"
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:77
+msgid ""
+"Generates a new geometry which is the region of union of the two geometries "
+"operated on."
+msgstr ""
+
+#: locale/.cache/my_service_string_to_translate.c:80
+msgid "The geometry representing the union of the two geometries."
+msgstr ""
diff --git a/zoo-project/zoo-services/ogr/base-vect-ops/makefile.vc b/zoo-project/zoo-services/ogr/base-vect-ops/makefile.vc
new file mode 100644
index 0000000..5936fa6
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/base-vect-ops/makefile.vc
@@ -0,0 +1,25 @@
+TROOT= $(ZOOK_DIR)
+!INCLUDE $(ZOOK_DIR)/nmake.opt
+
+FILES=$(ZOOK_DIR)/service_internal.obj $(ZOOK_DIR)/ulinet.obj 
+!IFDEF JS_DIR
+FILES=$(FILES) $(ZOOK_DIR)$(JS_FILE)
+!ENDIF
+!IFDEF JDK_DIR
+FILES=$(FILES) $(ZOOK_DIR)$(JAVA_FILE)
+!ENDIF
+!IFDEF PY_DIR
+FILES=$(FILES) $(ZOOK_DIR)$(PY_FILE)
+!ENDIF
+!IFDEF MS_DIR
+FILES=$(FILES) $(ZOOK_DIR)$(MS_FILE)
+!ENDIF
+
+cgi-env/ogr_service.zo: service.c
+	$(CPP)  /D_CRT_NONSTDC_NO_DEPRECATE -DWIN32 -DZOO_SERVICE -I$(GDAL_DIR)/frmts/ $(CFLAGS) /c service.c
+	link /dll /out:cgi-env/ogr_service.zo  $(FILES) ./service.obj $(LDFLAGS) $(GEOS_DIR)/src/geos_c_i.lib /FORCE:MULTIPLE
+
+clean:
+	erase cgi-env\ogr_service.*
+
+#	link /dll /out:cgi-env/ogr_service.zo ../../../zoo-kernel/service_internal.obj ./service.obj -L$(TOOLS)/lib/libssl32.dll.a $(GEODIR)/lib/libxml2.lib $(GEODIR)/lib/gdal_i.lib $(GEODIR)/lib/geos_c_i.lib $(TPATH)/lib/libeay32.dll.a $(TPATH)/lib/libcrypto.a $(TPATH)/lib/libssl32.dll.a $(LIBINTL_CPATH)/lib/libintl.lib 
diff --git a/zoo-project/zoo-services/ogr/base-vect-ops/service.c b/zoo-project/zoo-services/ogr/base-vect-ops/service.c
new file mode 100644
index 0000000..02d39cc
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/base-vect-ops/service.c
@@ -0,0 +1,1472 @@
+/**
+ * Author : Gérald FENOY
+ *
+ * Copyright 2008-2009 GeoLabs SARL. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "cpl_conv.h"
+#include "ogr_api.h"
+#include "ogr_geometry.h"
+
+#include "cpl_minixml.h"
+#include "ogr_api.h"
+#include "ogrsf_frmts.h"
+
+#include "geos_c.h"
+#include "service.h"
+#include "service_internal.h"
+
+extern "C" {
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+
+#include <openssl/sha.h>
+#include <openssl/hmac.h>
+#include <openssl/evp.h>
+#include <openssl/bio.h>
+#include <openssl/buffer.h>
+
+  void printExceptionReportResponse(maps*,map*);
+  char *base64(const char *input, int length);
+
+  OGRGeometryH createGeometryFromGML(maps* conf,char* inputStr){
+    xmlInitParser();
+    xmlDocPtr doc = xmlParseMemory(inputStr,strlen(inputStr));
+    xmlChar *xmlbuff;
+    int buffersize;
+    xmlXPathContextPtr xpathCtx;
+    xmlXPathObjectPtr xpathObj;
+    const char * xpathExpr="/*/*/*/*/*[local-name()='Polygon' or local-name()='MultiPolygon']";
+    xpathCtx = xmlXPathNewContext(doc);
+    xpathObj = xmlXPathEvalExpression(BAD_CAST xpathExpr,xpathCtx);
+    if(!xpathObj->nodesetval){
+      setMapInMaps(conf,"lenv","message",_ss("Unable to parse Input Polygon"));
+      setMapInMaps(conf,"lenv","code","InvalidParameterValue");
+      return NULL;
+    }
+    int size = (xpathObj->nodesetval) ? xpathObj->nodesetval->nodeNr : 0;
+    /**
+     * Create a temporary XML document
+     */
+    xmlDocPtr ndoc = xmlNewDoc(BAD_CAST "1.0");
+    /**
+     * Only one polygon should be provided so we use it as the root node.
+     */
+    for(int k=size-1;k>=0;k--){ 
+      xmlDocSetRootElement(ndoc, xpathObj->nodesetval->nodeTab[k]);
+    }
+    xmlDocDumpFormatMemory(ndoc, &xmlbuff, &buffersize, 1);
+    char *tmp=(char*)calloc((xmlStrlen(xmlStrstr(xmlbuff,BAD_CAST "?>"))-1),sizeof(char));
+    sprintf(tmp,"%s",xmlStrstr(xmlbuff,BAD_CAST "?>")+2);
+    xmlXPathFreeObject(xpathObj);
+    xmlXPathFreeContext(xpathCtx);
+    xmlFree(xmlbuff);
+    xmlFreeDoc(doc);
+    xmlFreeDoc(ndoc);
+#ifndef WIN32
+    xmlCleanupParser();
+#endif
+#ifdef DEBUG
+    fprintf(stderr,"\nService internal print\n Loading the geometry from GML string ...");
+#endif
+    OGRGeometryH res=OGR_G_CreateFromGML(tmp);
+    free(tmp);
+    if(res==NULL){
+      setMapInMaps(conf,"lenv","message",_ss("Unable to call OGR_G_CreatFromGML"));
+      return NULL;
+    }
+    else
+      return res;
+  }
+
+#ifdef WIN32
+  __declspec(dllexport)
+#endif
+  int Simplify(maps*& conf,maps*& inputs,maps*& outputs){
+    OGRRegisterAll();
+
+    double tolerance;
+    map* tmp0=getMapFromMaps(inputs,"Tolerance","value");
+    if(tmp0==NULL){
+      tolerance=atof("2.0");
+    }
+    else
+      tolerance=atof(tmp0->value);
+
+    maps* cursor=inputs;
+    OGRGeometryH geometry;
+    OGRGeometry *res;
+    OGRLayer *poDstLayer;
+    const char *oDriver1;
+    OGRDataSource       *poODS;
+    map* tmp=getMapFromMaps(inputs,"InputPolygon","value");
+    if(!tmp){
+      setMapInMaps(conf,"lenv","message",_ss("Unable to parse the input geometry from InputPolygon"));
+      return SERVICE_FAILED;
+    }
+    char filename[1024];
+    map* tmp1=getMapFromMaps(inputs,"InputPolygon","mimeType");
+    const char *oDriver;
+    oDriver="GeoJSON";
+    sprintf(filename,"/vsimem/input_%d.json",getpid());
+    if(tmp1!=NULL){
+      if(strcmp(tmp1->value,"text/xml")==0){
+	sprintf(filename,"/vsimem/input_%d.xml",getpid());
+	oDriver="GML";
+      }
+    }
+    VSILFILE *ifile=VSIFileFromMemBuffer(filename,(GByte*)tmp->value,strlen(tmp->value),FALSE);
+    VSIFCloseL(ifile);
+    OGRDataSource* ipoDS = OGRSFDriverRegistrar::Open(filename,FALSE);
+    char pszDestDataSource[100];
+    if( ipoDS == NULL )
+      {
+	OGRSFDriverRegistrar    *poR = OGRSFDriverRegistrar::GetRegistrar();
+	
+	fprintf( stderr, "FAILURE:\n"
+		 "Unable to open datasource `%s' with the following drivers.\n",
+		 filename );
+	
+	for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
+	  {
+	    fprintf( stderr, "  -> %s\n", poR->GetDriver(iDriver)->GetName() );
+	  }
+	char tmp[1024];
+	sprintf(tmp,"Unable to open datasource `%s' with the following drivers.",filename);
+	setMapInMaps(conf,"lenv","message",tmp);
+	return SERVICE_FAILED;
+      }
+    for( int iLayer = 0; iLayer < ipoDS->GetLayerCount();
+	 iLayer++ )
+      {
+	OGRLayer        *poLayer = ipoDS->GetLayer(iLayer);
+	
+	if( poLayer == NULL )
+	  {
+	    fprintf( stderr, "FAILURE: Couldn't fetch advertised layer %d!\n",
+		     iLayer );
+	    char tmp[1024];
+	    sprintf(tmp,"Couldn't fetch advertised layer %d!",iLayer);
+	    setMapInMaps(conf,"lenv","message",tmp);
+	    return SERVICE_FAILED;
+	  }
+	
+	OGRFeature  *poFeature;
+	
+	OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
+	OGRSFDriver          *poDriver = NULL;
+	int                  iDriver;
+	
+	map* tmpMap=getMapFromMaps(outputs,"Result","mimeType");
+	oDriver1="GeoJSON";
+	sprintf(pszDestDataSource,"/vsimem/result_%d.json",getpid());
+	if(tmpMap!=NULL){
+	  if(strcmp(tmpMap->value,"text/xml")==0){
+	    sprintf(pszDestDataSource,"/vsimem/result_%d.xml",getpid());
+	    oDriver1="GML";
+	  }
+	}
+	
+	for( iDriver = 0;
+	     iDriver < poR->GetDriverCount() && poDriver == NULL;
+	     iDriver++ )
+	  {
+	    if( EQUAL(poR->GetDriver(iDriver)->GetName(),oDriver1) )
+	      {
+		poDriver = poR->GetDriver(iDriver);
+	      }
+	  }
+	
+	if( poDriver == NULL )
+	  {
+	    char emessage[8192];
+	    sprintf( emessage, "Unable to find driver `%s'.\n", oDriver );
+	    sprintf( emessage,  "%sThe following drivers are available:\n",emessage );
+	    
+	    for( iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
+	      {
+		sprintf( emessage,  "%s  -> `%s'\n", emessage, poR->GetDriver(iDriver)->GetName() );
+	      }
+	    
+	    setMapInMaps(conf,"lenv","message",emessage);
+	    return SERVICE_FAILED;
+	    
+	  }
+	
+	if( !poDriver->TestCapability( ODrCCreateDataSource ) ){
+	  char emessage[1024];
+	  sprintf( emessage,  "%s driver does not support data source creation.\n",
+		   "json" );
+	  setMapInMaps(conf,"lenv","message",emessage);
+	  return SERVICE_FAILED;
+	}
+	
+	char **papszDSCO=NULL;
+	poODS = poDriver->CreateDataSource( pszDestDataSource, papszDSCO );
+	if( poODS == NULL ){
+	  char emessage[1024];      
+	  sprintf( emessage,  "%s driver failed to create %s\n", 
+		   "json", pszDestDataSource );
+	  setMapInMaps(conf,"lenv","message",emessage);
+	  return SERVICE_FAILED;
+	}
+	
+	if( !poODS->TestCapability( ODsCCreateLayer ) )
+	  {
+	    char emessage[1024];
+	    sprintf( emessage, 
+		     "Layer %s not found, and CreateLayer not supported by driver.", 
+		     "Result" );
+	    setMapInMaps(conf,"lenv","message",emessage);
+	    return SERVICE_FAILED;
+	  }
+	
+	poDstLayer = poODS->CreateLayer( "Result", NULL,wkbUnknown,NULL);
+	if( poDstLayer == NULL ){
+	  setMapInMaps(conf,"lenv","message","Layer creation failed.\n");
+	  return SERVICE_FAILED;
+	}
+	
+	OGRFeatureDefn *poFDefn = poLayer->GetLayerDefn();
+	int iField;
+	int hasMmField=0;
+	
+	for( iField = 0; iField < poFDefn->GetFieldCount(); iField++ )
+	  {
+	    OGRFieldDefn *tmp=poFDefn->GetFieldDefn(iField);
+            if (iField >= 0)
+                poDstLayer->CreateField( poFDefn->GetFieldDefn(iField) );
+            else
+            {
+                fprintf( stderr, "Field '%s' not found in source layer.\n", 
+                        iField );
+		return SERVICE_FAILED;
+            }
+	  }
+
+	while(TRUE){
+	  OGRFeature      *poDstFeature = NULL;
+	  poFeature = poLayer->GetNextFeature();
+	  if( poFeature == NULL )
+	    break;
+	  if(poFeature->GetGeometryRef() != NULL){
+	    poDstFeature = OGRFeature::CreateFeature( poDstLayer->GetLayerDefn() );
+	    if( poDstFeature->SetFrom( poFeature, TRUE ) != OGRERR_NONE )
+	      {
+		char tmpMsg[1024];
+		sprintf( tmpMsg,"Unable to translate feature %ld from layer %s.\n",
+			 poFeature->GetFID(), poFDefn->GetName() );
+		
+		OGRFeature::DestroyFeature( poFeature );
+		OGRFeature::DestroyFeature( poDstFeature );
+		return SERVICE_FAILED;
+	      }
+	    geometry=poFeature->GetGeometryRef();
+#if GDAL_VERSION_MAJOR == 1 && GDAL_VERSION_MINOR < 11
+	    GEOSGeometry* ggeometry=((OGRGeometry *) geometry)->exportToGEOS();
+	    GEOSGeometry* gres=GEOSTopologyPreserveSimplify(ggeometry,tolerance);
+	    if(gres!=NULL)
+	      res=(OGRGeometry*)OGRGeometryFactory::createFromGEOS(gres);
+#else
+	    res=((OGRGeometry *) geometry)->SimplifyPreserveTopology(tolerance);
+#endif
+	    if(poDstFeature->SetGeometryDirectly(res) != OGRERR_NONE )
+	      {
+		char tmpMsg[1024];
+		sprintf( tmpMsg,"Unable to translate feature %ld from layer %s.\n",
+			 poFeature->GetFID(), poFDefn->GetName() );
+		
+		OGRFeature::DestroyFeature( poFeature );
+		OGRFeature::DestroyFeature( poDstFeature );
+		return SERVICE_FAILED;
+	      }
+	    OGRFeature::DestroyFeature( poFeature );
+	    if( poDstLayer->CreateFeature( poDstFeature ) != OGRERR_NONE )
+	      {		
+		OGRFeature::DestroyFeature( poDstFeature );
+		return SERVICE_FAILED;
+	      }
+	    OGRFeature::DestroyFeature( poDstFeature );
+#if GDAL_VERSION_MAJOR == 1 && GDAL_VERSION_MINOR < 11
+	    GEOSGeom_destroy( ggeometry);
+	    GEOSGeom_destroy( gres);
+#endif
+	  }
+	}
+      }
+
+    delete poODS;
+    delete ipoDS;
+
+    char *res1=readVSIFile(conf,pszDestDataSource);
+    if(res1==NULL)
+      return SERVICE_FAILED;
+    setMapInMaps(outputs,"Result","value",res1);
+    free(res1);
+
+    OGRCleanupAll();
+    return SERVICE_SUCCEEDED;
+
+}
+
+  int applyOne(maps*& conf,maps*& inputs,maps*& outputs,OGRGeometry* (OGRGeometry::*myFunc)() const,const char* schema){
+    OGRRegisterAll();
+
+    maps* cursor=inputs;
+    OGRGeometryH geometry,res;
+    OGRLayer *poDstLayer;
+    const char *oDriver1;
+    OGRDataSource       *poODS;
+    map* tmp=getMapFromMaps(inputs,"InputPolygon","value");
+    if(!tmp){
+      setMapInMaps(conf,"lenv","message",_ss("Unable to parse the input geometry from InputPolygon"));
+      return SERVICE_FAILED;
+    }
+    char filename[1024];
+    map* tmp1=getMapFromMaps(inputs,"InputPolygon","mimeType");
+    const char *oDriver;
+    oDriver="GeoJSON";
+    sprintf(filename,"/vsimem/input_%d.json",getpid());
+    if(tmp1!=NULL){
+      if(strcmp(tmp1->value,"text/xml")==0){
+	sprintf(filename,"/vsimem/input_%d.xml",getpid());
+	oDriver="GML";
+      }
+    }
+    VSILFILE *ifile=VSIFileFromMemBuffer(filename,(GByte*)tmp->value,strlen(tmp->value),FALSE);
+    VSIFCloseL(ifile);
+    OGRDataSource* ipoDS = OGRSFDriverRegistrar::Open(filename,FALSE);
+    char pszDestDataSource[100];
+    if( ipoDS == NULL )
+      {
+	OGRSFDriverRegistrar    *poR = OGRSFDriverRegistrar::GetRegistrar();
+	
+	fprintf( stderr, "FAILURE:\n"
+		 "Unable to open datasource `%s' with the following drivers.\n",
+		 filename );
+	
+	for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
+	  {
+	    fprintf( stderr, "  -> %s\n", poR->GetDriver(iDriver)->GetName() );
+	  }
+	char tmp[1024];
+	sprintf(tmp,"Unable to open datasource `%s' with the following drivers.",filename);
+	setMapInMaps(conf,"lenv","message",tmp);
+	return SERVICE_FAILED;
+      }
+    for( int iLayer = 0; iLayer < ipoDS->GetLayerCount();
+	 iLayer++ )
+      {
+	OGRLayer        *poLayer = ipoDS->GetLayer(iLayer);
+	
+	if( poLayer == NULL )
+	  {
+	    fprintf( stderr, "FAILURE: Couldn't fetch advertised layer %d!\n",
+		     iLayer );
+	    char tmp[1024];
+	    sprintf(tmp,"Couldn't fetch advertised layer %d!",iLayer);
+	    setMapInMaps(conf,"lenv","message",tmp);
+	    return SERVICE_FAILED;
+	  }
+	
+	OGRFeature  *poFeature;
+
+	/* -------------------------------------------------------------------- */
+	/*      Try opening the output datasource as an existing, writable      */
+	/* -------------------------------------------------------------------- */
+	
+	OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
+	OGRSFDriver          *poDriver = NULL;
+	int                  iDriver;
+	
+	map* tmpMap=getMapFromMaps(outputs,"Result","mimeType");
+	oDriver1="GeoJSON";
+	sprintf(pszDestDataSource,"/vsimem/result_%d.json",getpid());
+	if(tmpMap!=NULL){
+	  if(strcmp(tmpMap->value,"text/xml")==0){
+	    sprintf(pszDestDataSource,"/vsimem/result_%d.xml",getpid());
+	    oDriver1="GML";
+	  }
+	}
+	
+	for( iDriver = 0;
+	     iDriver < poR->GetDriverCount() && poDriver == NULL;
+	     iDriver++ )
+	  {
+	    if( EQUAL(poR->GetDriver(iDriver)->GetName(),oDriver1) )
+	      {
+		poDriver = poR->GetDriver(iDriver);
+	      }
+	  }
+	
+	if( poDriver == NULL )
+	  {
+	    char emessage[8192];
+	    sprintf( emessage, "Unable to find driver `%s'.\n", oDriver );
+	    sprintf( emessage,  "%sThe following drivers are available:\n",emessage );
+	    
+	    for( iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
+	      {
+		sprintf( emessage,  "%s  -> `%s'\n", emessage, poR->GetDriver(iDriver)->GetName() );
+	      }
+	    
+	    setMapInMaps(conf,"lenv","message",emessage);
+	    return SERVICE_FAILED;
+	    
+	  }
+	
+	if( !poDriver->TestCapability( ODrCCreateDataSource ) ){
+	  char emessage[1024];
+	  sprintf( emessage,  "%s driver does not support data source creation.\n",
+		   "json" );
+	  setMapInMaps(conf,"lenv","message",emessage);
+	  return SERVICE_FAILED;
+	}
+	
+	/* -------------------------------------------------------------------- */
+	/*      Create the output data source.                                  */
+	/* -------------------------------------------------------------------- */
+	//map* tpath=getMapFromMaps(conf,"main","tmpPath");
+	char **papszDSCO=NULL;
+	poODS = poDriver->CreateDataSource( pszDestDataSource, papszDSCO );
+	if( poODS == NULL ){
+	  char emessage[1024];      
+	  sprintf( emessage,  "%s driver failed to create %s\n", 
+		   "json", pszDestDataSource );
+	  setMapInMaps(conf,"lenv","message",emessage);
+	  return SERVICE_FAILED;
+	}
+	
+	/* -------------------------------------------------------------------- */
+	/*      Create the layer.                                               */
+	/* -------------------------------------------------------------------- */
+	if( !poODS->TestCapability( ODsCCreateLayer ) )
+	  {
+	    char emessage[1024];
+	    sprintf( emessage, 
+		     "Layer %s not found, and CreateLayer not supported by driver.", 
+		     "Result" );
+	    setMapInMaps(conf,"lenv","message",emessage);
+	    return SERVICE_FAILED;
+	  }
+	
+	//CPLErrorReset();
+	
+	poDstLayer = poODS->CreateLayer( "Result", NULL,wkbUnknown,NULL);
+	if( poDstLayer == NULL ){
+	  setMapInMaps(conf,"lenv","message","Layer creation failed.\n");
+	  return SERVICE_FAILED;
+	}
+	
+	OGRFeatureDefn *poFDefn = poLayer->GetLayerDefn();
+	int iField;
+	int hasMmField=0;
+	
+	for( iField = 0; iField < poFDefn->GetFieldCount(); iField++ )
+	  {
+	    OGRFieldDefn *tmp=poFDefn->GetFieldDefn(iField);
+            if (iField >= 0)
+                poDstLayer->CreateField( poFDefn->GetFieldDefn(iField) );
+            else
+            {
+                fprintf( stderr, "Field '%s' not found in source layer.\n", 
+                        iField );
+		return SERVICE_FAILED;
+            }
+	  }
+
+	while(TRUE){
+	  OGRFeature      *poDstFeature = NULL;
+	  poFeature = poLayer->GetNextFeature();
+	  if( poFeature == NULL )
+	    break;
+	  if(poFeature->GetGeometryRef() != NULL){
+	    poDstFeature = OGRFeature::CreateFeature( poDstLayer->GetLayerDefn() );
+	    if( poDstFeature->SetFrom( poFeature, TRUE ) != OGRERR_NONE )
+	      {
+		char tmpMsg[1024];
+		sprintf( tmpMsg,"Unable to translate feature %ld from layer %s.\n",
+			 poFeature->GetFID(), poFDefn->GetName() );
+		
+		OGRFeature::DestroyFeature( poFeature );
+		OGRFeature::DestroyFeature( poDstFeature );
+		return SERVICE_FAILED;
+	      }
+	    if(poDstFeature->SetGeometryDirectly((poDstFeature->GetGeometryRef()->*myFunc)()) != OGRERR_NONE )
+	      {
+		char tmpMsg[1024];
+		sprintf( tmpMsg,"Unable to translate feature %ld from layer %s.\n",
+			 poFeature->GetFID(), poFDefn->GetName() );
+		
+		OGRFeature::DestroyFeature( poFeature );
+		OGRFeature::DestroyFeature( poDstFeature );
+		return SERVICE_FAILED;
+	      }
+	    OGRFeature::DestroyFeature( poFeature );
+	    if( poDstLayer->CreateFeature( poDstFeature ) != OGRERR_NONE )
+	      {		
+		OGRFeature::DestroyFeature( poDstFeature );
+		return SERVICE_FAILED;
+	      }
+	    OGRFeature::DestroyFeature( poDstFeature );
+	  }
+	}
+
+      }
+
+    delete poODS;
+    delete ipoDS;
+
+    char *res1=readVSIFile(conf,pszDestDataSource);
+    if(res1==NULL)
+      return SERVICE_FAILED;
+    setMapInMaps(outputs,"Result","value",res1);
+    free(res1);
+
+    OGRCleanupAll();
+    return SERVICE_SUCCEEDED;
+  }
+
+#ifdef WIN32
+  __declspec(dllexport)
+#endif
+int Buffer(maps*& conf,maps*& inputs,maps*& outputs){
+    OGRRegisterAll();
+
+    double bufferDistance;
+    map* tmp0=getMapFromMaps(inputs,"BufferDistance","value");
+    if(tmp0==NULL){
+      bufferDistance=atof("10.0");
+    }
+    else
+      bufferDistance=atof(tmp0->value);
+
+    maps* cursor=inputs;
+    OGRGeometryH geometry,res;
+    OGRLayer *poDstLayer;
+    const char *oDriver1;
+    OGRDataSource       *poODS;
+    map* tmp=getMapFromMaps(inputs,"InputPolygon","value");
+    if(!tmp){
+      setMapInMaps(conf,"lenv","message",_ss("Unable to parse the input geometry from InputPolygon"));
+      return SERVICE_FAILED;
+    }
+    char filename[1024];
+    map* tmp1=getMapFromMaps(inputs,"InputPolygon","mimeType");
+    const char *oDriver;
+    oDriver="GeoJSON";
+    sprintf(filename,"/vsimem/input_%d.json",getpid());
+    if(tmp1!=NULL){
+      if(strcmp(tmp1->value,"text/xml")==0){
+	sprintf(filename,"/vsimem/input_%d.xml",getpid());
+	oDriver="GML";
+      }
+    }
+    VSILFILE *ifile=VSIFileFromMemBuffer(filename,(GByte*)tmp->value,strlen(tmp->value),FALSE);
+    VSIFCloseL(ifile);
+    OGRDataSource* ipoDS = OGRSFDriverRegistrar::Open(filename,FALSE);
+    char pszDestDataSource[100];
+    if( ipoDS == NULL )
+      {
+	OGRSFDriverRegistrar    *poR = OGRSFDriverRegistrar::GetRegistrar();
+	
+	fprintf( stderr, "FAILURE:\n"
+		 "Unable to open datasource `%s' with the following drivers.\n",
+		 filename );
+	
+	for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
+	  {
+	    fprintf( stderr, "  -> %s\n", poR->GetDriver(iDriver)->GetName() );
+	  }
+	char tmp[1024];
+	sprintf(tmp,"Unable to open datasource `%s' with the following drivers.",filename);
+	setMapInMaps(conf,"lenv","message",tmp);
+	return SERVICE_FAILED;
+      }
+    for( int iLayer = 0; iLayer < ipoDS->GetLayerCount();
+	 iLayer++ )
+      {
+	OGRLayer        *poLayer = ipoDS->GetLayer(iLayer);
+	
+	if( poLayer == NULL )
+	  {
+	    fprintf( stderr, "FAILURE: Couldn't fetch advertised layer %d!\n",
+		     iLayer );
+	    char tmp[1024];
+	    sprintf(tmp,"Couldn't fetch advertised layer %d!",iLayer);
+	    setMapInMaps(conf,"lenv","message",tmp);
+	    return SERVICE_FAILED;
+	  }
+	
+	OGRFeature  *poFeature;
+
+	/* -------------------------------------------------------------------- */
+	/*      Try opening the output datasource as an existing, writable      */
+	/* -------------------------------------------------------------------- */
+	
+	OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
+	OGRSFDriver          *poDriver = NULL;
+	int                  iDriver;
+	
+	map* tmpMap=getMapFromMaps(outputs,"Result","mimeType");
+	oDriver1="GeoJSON";
+	sprintf(pszDestDataSource,"/vsimem/result_%d.json",getpid());
+	if(tmpMap!=NULL){
+	  if(strcmp(tmpMap->value,"text/xml")==0){
+	    sprintf(pszDestDataSource,"/vsimem/result_%d.xml",getpid());
+	    oDriver1="GML";
+	  }
+	}
+	
+	for( iDriver = 0;
+	     iDriver < poR->GetDriverCount() && poDriver == NULL;
+	     iDriver++ )
+	  {
+	    if( EQUAL(poR->GetDriver(iDriver)->GetName(),oDriver1) )
+	      {
+		poDriver = poR->GetDriver(iDriver);
+	      }
+	  }
+	
+	if( poDriver == NULL )
+	  {
+	    char emessage[8192];
+	    sprintf( emessage, "Unable to find driver `%s'.\n", oDriver );
+	    sprintf( emessage,  "%sThe following drivers are available:\n",emessage );
+	    
+	    for( iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
+	      {
+		sprintf( emessage,  "%s  -> `%s'\n", emessage, poR->GetDriver(iDriver)->GetName() );
+	      }
+	    
+	    setMapInMaps(conf,"lenv","message",emessage);
+	    return SERVICE_FAILED;
+	    
+	  }
+	
+	if( !poDriver->TestCapability( ODrCCreateDataSource ) ){
+	  char emessage[1024];
+	  sprintf( emessage,  "%s driver does not support data source creation.\n",
+		   "json" );
+	  setMapInMaps(conf,"lenv","message",emessage);
+	  return SERVICE_FAILED;
+	}
+	
+	/* -------------------------------------------------------------------- */
+	/*      Create the output data source.                                  */
+	/* -------------------------------------------------------------------- */
+	//map* tpath=getMapFromMaps(conf,"main","tmpPath");
+	char **papszDSCO=NULL;
+	poODS = poDriver->CreateDataSource( pszDestDataSource, papszDSCO );
+	if( poODS == NULL ){
+	  char emessage[1024];      
+	  sprintf( emessage,  "%s driver failed to create %s\n", 
+		   "json", pszDestDataSource );
+	  setMapInMaps(conf,"lenv","message",emessage);
+	  return SERVICE_FAILED;
+	}
+	
+	/* -------------------------------------------------------------------- */
+	/*      Create the layer.                                               */
+	/* -------------------------------------------------------------------- */
+	if( !poODS->TestCapability( ODsCCreateLayer ) )
+	  {
+	    char emessage[1024];
+	    sprintf( emessage, 
+		     "Layer %s not found, and CreateLayer not supported by driver.", 
+		     "Result" );
+	    setMapInMaps(conf,"lenv","message",emessage);
+	    return SERVICE_FAILED;
+	  }
+
+	poDstLayer = poODS->CreateLayer( "Result", NULL,wkbUnknown,NULL);
+	if( poDstLayer == NULL ){
+	  setMapInMaps(conf,"lenv","message","Layer creation failed.\n");
+	  return SERVICE_FAILED;
+	}
+	
+	OGRFeatureDefn *poFDefn = poLayer->GetLayerDefn();
+	int iField;
+	int hasMmField=0;
+	
+	for( iField = 0; iField < poFDefn->GetFieldCount(); iField++ )
+	  {
+	    OGRFieldDefn *tmp=poFDefn->GetFieldDefn(iField);
+            if (iField >= 0)
+                poDstLayer->CreateField( poFDefn->GetFieldDefn(iField) );
+            else
+            {
+                fprintf( stderr, "Field '%s' not found in source layer.\n", 
+                        iField );
+		return SERVICE_FAILED;
+            }
+	  }
+
+	while(TRUE){
+	  OGRFeature      *poDstFeature = NULL;
+	  poFeature = poLayer->GetNextFeature();
+	  if( poFeature == NULL )
+	    break;
+	  if(poFeature->GetGeometryRef() != NULL){
+	    poDstFeature = OGRFeature::CreateFeature( poDstLayer->GetLayerDefn() );
+	    if( poDstFeature->SetFrom( poFeature, TRUE ) != OGRERR_NONE )
+	      {
+		char tmpMsg[1024];
+		sprintf( tmpMsg,"Unable to translate feature %ld from layer %s.\n",
+			 poFeature->GetFID(), poFDefn->GetName() );
+		
+		OGRFeature::DestroyFeature( poFeature );
+		OGRFeature::DestroyFeature( poDstFeature );
+		return SERVICE_FAILED;
+	      }
+	    if(poDstFeature->SetGeometryDirectly(poDstFeature->GetGeometryRef()->Buffer(bufferDistance,30)) != OGRERR_NONE )
+	      {
+		char tmpMsg[1024];
+		sprintf( tmpMsg,"Unable to translate feature %ld from layer %s.\n",
+			 poFeature->GetFID(), poFDefn->GetName() );
+		
+		OGRFeature::DestroyFeature( poFeature );
+		OGRFeature::DestroyFeature( poDstFeature );
+		return SERVICE_FAILED;
+	      }
+	    OGRFeature::DestroyFeature( poFeature );
+	    if( poDstLayer->CreateFeature( poDstFeature ) != OGRERR_NONE )
+	      {		
+		OGRFeature::DestroyFeature( poDstFeature );
+		return SERVICE_FAILED;
+	      }
+	    OGRFeature::DestroyFeature( poDstFeature );
+	  }
+	}
+
+      }
+
+    delete poODS;
+    delete ipoDS;
+
+    char *res1=readVSIFile(conf,pszDestDataSource);
+    if(res1==NULL)
+      return SERVICE_FAILED;
+    setMapInMaps(outputs,"Result","value",res1);
+    free(res1);
+
+    OGRCleanupAll();
+    return SERVICE_SUCCEEDED;
+
+}
+
+#ifdef WIN32
+  __declspec(dllexport)
+#endif
+  int Boundary(maps*& conf,maps*& inputs,maps*& outputs){
+    return applyOne(conf,inputs,outputs,&OGRGeometry::Boundary,"http://fooa/gml/3.1.0/polygon.xsd");
+  }
+
+#ifdef WIN32
+  __declspec(dllexport)
+#endif
+  int ConvexHull(maps*& conf,maps*& inputs,maps*& outputs){
+    return applyOne(conf,inputs,outputs,&OGRGeometry::ConvexHull,"http://fooa/gml/3.1.0/polygon.xsd");
+  }
+
+
+  OGRDataSource* loadEntity(maps* conf,maps* inputs,char **filename,const char **oDriver,const char *entity,int iter){
+    map* tmp=getMapFromMaps(inputs,entity,"value");
+    map* tmp1=getMapFromMaps(inputs,entity,"mimeType");
+    *oDriver="GeoJSON";
+    sprintf(*filename,"/vsimem/input_%d.json",getpid()+iter);
+    if(tmp1!=NULL){
+      if(strcmp(tmp1->value,"text/xml")==0){
+	sprintf(*filename,"/vsimem/input_%d.xml",getpid()+iter);
+	*oDriver="GML";
+      }
+    }
+    VSILFILE *ifile=VSIFileFromMemBuffer(*filename,(GByte*)tmp->value,strlen(tmp->value),FALSE);
+    VSIFCloseL(ifile);
+    return OGRSFDriverRegistrar::Open(*filename,FALSE);    
+  }
+
+  int applyOneBool(maps*& conf,maps*& inputs,maps*& outputs,OGRBoolean (OGRGeometry::*myFunc)() const){
+#ifdef DEBUG
+    fprintf(stderr,"\nService internal print\n");
+#endif
+    OGRRegisterAll();
+
+    maps* cursor=inputs;
+    OGRGeometryH geometry,res;
+    OGRLayer *poDstLayer;
+    const char *oDriver1;
+    OGRDataSource       *poODS;
+#ifdef DEBUG
+    dumpMaps(cursor);
+#endif
+    map* tmp=getMapFromMaps(inputs,"InputPolygon","value");
+    if(!tmp){
+      setMapInMaps(conf,"lenv","message",_ss("Unable to parse the input geometry from InputPolygon"));
+      return SERVICE_FAILED;
+    }
+    char filename[1024];
+    map* tmp1=getMapFromMaps(inputs,"InputPolygon","mimeType");
+    const char *oDriver;
+    oDriver="GeoJSON";
+    sprintf(filename,"/vsimem/input_%d.json",getpid());
+    if(tmp1!=NULL){
+      if(strcmp(tmp1->value,"text/xml")==0){
+	sprintf(filename,"/vsimem/input_%d.xml",getpid());
+	oDriver="GML";
+      }
+    }
+    VSILFILE *ifile=VSIFileFromMemBuffer(filename,(GByte*)tmp->value,strlen(tmp->value),FALSE);
+    VSIFCloseL(ifile);
+    OGRDataSource* ipoDS = OGRSFDriverRegistrar::Open(filename,FALSE);
+    char pszDestDataSource[100];
+    if( ipoDS == NULL )
+      {
+	OGRSFDriverRegistrar    *poR = OGRSFDriverRegistrar::GetRegistrar();
+	
+	fprintf( stderr, "FAILURE:\n"
+		 "Unable to open datasource `%s' with the following drivers.\n",
+		 filename );
+	
+	for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
+	  {
+	    fprintf( stderr, "  -> %s\n", poR->GetDriver(iDriver)->GetName() );
+	  }
+	char tmp[1024];
+	sprintf(tmp,"Unable to open datasource `%s' with the following drivers.",filename);
+	setMapInMaps(conf,"lenv","message",tmp);
+	return SERVICE_FAILED;
+      }
+    for( int iLayer = 0; iLayer < ipoDS->GetLayerCount();
+	 iLayer++ )
+      {
+	OGRLayer        *poLayer = ipoDS->GetLayer(iLayer);
+	
+	if( poLayer == NULL )
+	  {
+	    fprintf( stderr, "FAILURE: Couldn't fetch advertised layer %d!\n",
+		     iLayer );
+	    char tmp[1024];
+	    sprintf(tmp,"Couldn't fetch advertised layer %d!",iLayer);
+	    setMapInMaps(conf,"lenv","message",tmp);
+	    return SERVICE_FAILED;
+	  }
+	
+	OGRFeature  *poFeature;
+
+
+	while(TRUE){
+	  OGRFeature      *poDstFeature = NULL;
+	  poFeature = poLayer->GetNextFeature();
+	  if( poFeature == NULL )
+	    break;
+	  if(poFeature->GetGeometryRef() != NULL){
+	    if((poFeature->GetGeometryRef()->*myFunc)()==0){
+	      setMapInMaps(outputs,"Result","value","false");
+	      OGRFeature::DestroyFeature( poFeature );
+	      delete ipoDS;
+	      return SERVICE_SUCCEEDED;
+	    }
+	  }
+	  OGRFeature::DestroyFeature( poFeature );
+	}
+
+      }
+
+    delete ipoDS;
+    setMapInMaps(outputs,"Result","value","true");
+
+    OGRCleanupAll();
+    return SERVICE_SUCCEEDED;
+  }
+
+#ifdef WIN32
+  __declspec(dllexport)
+#endif
+  int IsSimple(maps*& conf,maps*& inputs,maps*& outputs){
+    return applyOneBool(conf,inputs,outputs,&OGRGeometry::IsSimple);
+  }
+
+#ifdef WIN32
+  __declspec(dllexport)
+#endif
+  int IsClosed(maps*& conf,maps*& inputs,maps*& outputs){
+    return applyOneBool(conf,inputs,outputs,&OGRGeometry::IsRing);
+  }
+
+#ifdef WIN32
+  __declspec(dllexport)
+#endif
+  int IsValid(maps*& conf,maps*& inputs,maps*& outputs){
+    return applyOneBool(conf,inputs,outputs,&OGRGeometry::IsValid);
+  }
+
+  
+  int applyTwo(maps*& conf,maps*& inputs,maps*& outputs,OGRGeometry* (OGRGeometry::*myFunc)(const OGRGeometry*) const){
+#ifdef DEBUG
+    fprintf(stderr,"\nService internal print\n");
+#endif
+    OGRRegisterAll();
+
+    maps* cursor=inputs;
+    OGRGeometryH geometry,res;
+    OGRLayer *poDstLayer;
+    //const char *oDriver1;
+    OGRDataSource       *poODS;
+#ifdef DEBUG
+    dumpMaps(cursor);
+#endif
+
+    char *filename=(char*)malloc(1024*sizeof(char));
+    const char *oDriver1;
+    OGRDataSource* ipoDS1 = loadEntity(conf,inputs,&filename,&oDriver1,"InputEntity1",1);
+
+    char *filename1=(char*)malloc(1024*sizeof(char));
+    const char *oDriver2;
+    OGRDataSource* ipoDS2 = loadEntity(conf,inputs,&filename1,&oDriver2,"InputEntity2",2);
+    const char *oDriver3;
+    char pszDestDataSource[100];
+    if( ipoDS1 == NULL || ipoDS2 == NULL )
+      {
+	OGRSFDriverRegistrar    *poR = OGRSFDriverRegistrar::GetRegistrar();
+	
+	fprintf( stderr, "FAILURE:\n"
+		 "Unable to open datasource `%s' with the following drivers.\n",
+		 filename );
+	
+	for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
+	  {
+	    fprintf( stderr, "  -> %s\n", poR->GetDriver(iDriver)->GetName() );
+	  }
+	char tmp[1024];
+	if( ipoDS1 == NULL )
+	  sprintf(tmp,"Unable to open datasource `%s' with the following drivers.",filename);
+	if( ipoDS2 == NULL )
+	  sprintf(tmp,"Unable to open datasource `%s' with the following drivers.",filename1);
+	setMapInMaps(conf,"lenv","message",tmp);
+	return SERVICE_FAILED;
+      }
+    for( int iLayer = 0; iLayer < ipoDS1->GetLayerCount();
+	 iLayer++ )
+      {
+	OGRLayer        *poLayer1 = ipoDS1->GetLayer(iLayer);
+	
+	if( poLayer1 == NULL )
+	  {
+	    fprintf( stderr, "FAILURE: Couldn't fetch advertised layer %d!\n",
+		     iLayer );
+	    char tmp[1024];
+	    sprintf(tmp,"Couldn't fetch advertised layer %d!",iLayer);
+	    setMapInMaps(conf,"lenv","message",tmp);
+	    return SERVICE_FAILED;
+	  }
+
+	for( int iLayer1 = 0; iLayer1 < ipoDS2->GetLayerCount();
+	     iLayer1++ )
+	  {
+	    OGRLayer        *poLayer2 = ipoDS2->GetLayer(iLayer1);
+	    
+	    if( poLayer1 == NULL )
+	      {
+		fprintf( stderr, "FAILURE: Couldn't fetch advertised layer %d!\n",
+			 iLayer1 );
+		char tmp[1024];
+		sprintf(tmp,"Couldn't fetch advertised layer %d!",iLayer1);
+		setMapInMaps(conf,"lenv","message",tmp);
+		return SERVICE_FAILED;
+	      }
+	
+	    OGRFeature  *poFeature1,*poFeature2;
+
+	    /* -------------------------------------------------------------------- */
+	    /*      Try opening the output datasource as an existing, writable      */
+	    /* -------------------------------------------------------------------- */
+	    
+	    OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
+	    OGRSFDriver          *poDriver = NULL;
+	    int                  iDriver;
+	    
+	    map* tmpMap=getMapFromMaps(outputs,"Result","mimeType");
+	    oDriver3="GeoJSON";
+	    sprintf(pszDestDataSource,"/vsimem/result_%d.json",getpid());
+	    if(tmpMap!=NULL){
+	      if(strcmp(tmpMap->value,"text/xml")==0){
+		sprintf(pszDestDataSource,"/vsimem/result_%d.xml",getpid());
+		oDriver3="GML";
+	      }
+	    }
+	    
+	    for( iDriver = 0;
+		 iDriver < poR->GetDriverCount() && poDriver == NULL;
+		 iDriver++ )
+	      {
+#ifdef DEBUG
+		fprintf(stderr,"D:%s\n",poR->GetDriver(iDriver)->GetName());
+#endif
+		if( EQUAL(poR->GetDriver(iDriver)->GetName(),oDriver3) )
+		  {
+		    poDriver = poR->GetDriver(iDriver);
+		  }
+	      }
+	    
+	    if( poDriver == NULL )
+	      {
+		char emessage[8192];
+		sprintf( emessage, "Unable to find driver `%s'.\n", oDriver1 );
+		sprintf( emessage,  "%sThe following drivers are available:\n",emessage );
+		
+		for( iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
+		  {
+		    sprintf( emessage,  "%s  -> `%s'\n", emessage, poR->GetDriver(iDriver)->GetName() );
+		  }
+		
+		setMapInMaps(conf,"lenv","message",emessage);
+		return SERVICE_FAILED;
+		
+	      }
+	    
+	    if( !poDriver->TestCapability( ODrCCreateDataSource ) ){
+	      char emessage[1024];
+	      sprintf( emessage,  "%s driver does not support data source creation.\n",
+		       "json" );
+	      setMapInMaps(conf,"lenv","message",emessage);
+	      return SERVICE_FAILED;
+	    }
+	    
+	    /* -------------------------------------------------------------------- */
+	    /*      Create the output data source.                                  */
+	    /* -------------------------------------------------------------------- */
+	    //map* tpath=getMapFromMaps(conf,"main","tmpPath");
+	    char **papszDSCO=NULL;
+	    poODS = poDriver->CreateDataSource( pszDestDataSource, papszDSCO );
+	    if( poODS == NULL ){
+	      char emessage[1024];      
+	      sprintf( emessage,  "%s driver failed to create %s\n", 
+		       "json", pszDestDataSource );
+	      setMapInMaps(conf,"lenv","message",emessage);
+	      return SERVICE_FAILED;
+	    }
+	    
+	    /* -------------------------------------------------------------------- */
+	    /*      Create the layer.                                               */
+	    /* -------------------------------------------------------------------- */
+	    if( !poODS->TestCapability( ODsCCreateLayer ) )
+	      {
+		char emessage[1024];
+		sprintf( emessage, 
+			 "Layer %s not found, and CreateLayer not supported by driver.", 
+			 "Result" );
+		setMapInMaps(conf,"lenv","message",emessage);
+		return SERVICE_FAILED;
+	      }
+	    
+	    //CPLErrorReset();
+	    
+	    poDstLayer = poODS->CreateLayer( "Result", NULL,wkbUnknown,NULL);
+	    if( poDstLayer == NULL ){
+	      setMapInMaps(conf,"lenv","message","Layer creation failed.\n");
+	      return SERVICE_FAILED;
+	    }
+	    
+	    OGRFeatureDefn *poFDefn = poLayer2->GetLayerDefn();
+	    int iField;
+	    int hasMmField=0;
+	    
+	    for( iField = 0; iField < poFDefn->GetFieldCount(); iField++ )
+	      {
+		OGRFieldDefn *tmp=poFDefn->GetFieldDefn(iField);
+		if (iField >= 0)
+		  poDstLayer->CreateField( poFDefn->GetFieldDefn(iField) );
+		else
+		  {
+		    fprintf( stderr, "Field '%s' not found in source layer.\n", 
+			     iField );
+		    return SERVICE_FAILED;
+		  }
+	      }
+	    
+	    while(TRUE){
+	      OGRFeature      *poDstFeature = NULL;
+	      poFeature1 = poLayer1->GetNextFeature();
+	      if( poFeature1 == NULL )
+		break;
+	      while(TRUE){
+		poFeature2 = poLayer2->GetNextFeature();
+		if( poFeature2 == NULL )
+		  break;
+
+		if(poFeature1->GetGeometryRef() != NULL && poFeature2->GetGeometryRef() != NULL){
+		  poDstFeature = OGRFeature::CreateFeature( poDstLayer->GetLayerDefn() );
+		  if( poDstFeature->SetFrom( poFeature2, TRUE ) != OGRERR_NONE )
+		    {
+		      char tmpMsg[1024];
+		      sprintf( tmpMsg,"Unable to translate feature %ld from layer %s.\n",
+			       poFeature2->GetFID(), poFDefn->GetName() );
+		      
+		      OGRFeature::DestroyFeature( poFeature1 );
+		      OGRFeature::DestroyFeature( poFeature2 );
+		      OGRFeature::DestroyFeature( poDstFeature );
+		      return SERVICE_FAILED;
+		    }
+		  if(poDstFeature->SetGeometryDirectly((poFeature1->GetGeometryRef()->*myFunc)(poFeature2->GetGeometryRef())) != OGRERR_NONE )
+		    {
+		      char tmpMsg[1024];
+		      sprintf( tmpMsg,"Unable to translate feature %ld from layer %s.\n",
+			       poFeature2->GetFID(), poFDefn->GetName() );
+		      
+		      OGRFeature::DestroyFeature( poFeature1 );
+		      OGRFeature::DestroyFeature( poFeature2 );
+		      OGRFeature::DestroyFeature( poDstFeature );
+		      return SERVICE_FAILED;
+		    }
+		  OGRFeature::DestroyFeature( poFeature2 );
+		  if(!poDstFeature->GetGeometryRef()->IsEmpty())
+		    if( poDstLayer->CreateFeature( poDstFeature ) != OGRERR_NONE )
+		      {		
+			OGRFeature::DestroyFeature( poDstFeature );
+			return SERVICE_FAILED;
+		      }
+		  OGRFeature::DestroyFeature( poDstFeature );
+		}
+	      }
+	    }
+	    OGRFeature::DestroyFeature( poFeature1 );
+	  }
+      }
+
+    delete poODS;
+    delete ipoDS1;
+    delete ipoDS2;
+    free(filename);
+    free(filename1);
+
+    char *res1=readVSIFile(conf,pszDestDataSource);
+    if(res1==NULL)
+      return SERVICE_FAILED;
+    setMapInMaps(outputs,"Result","value",res1);
+    free(res1);
+    OGRCleanupAll();
+    return SERVICE_SUCCEEDED;
+  }
+  
+#ifdef WIN32
+  __declspec(dllexport)
+#endif
+  int Difference(maps*& conf,maps*& inputs,maps*& outputs){
+    return applyTwo(conf,inputs,outputs,&OGRGeometry::Difference);
+  }
+
+#ifdef WIN32
+  __declspec(dllexport)
+#endif
+  int SymDifference(maps*& conf,maps*& inputs,maps*& outputs){
+    return applyTwo(conf,inputs,outputs,&OGRGeometry::SymDifference);
+  }
+
+#ifdef WIN32
+  __declspec(dllexport)
+#endif
+  int Intersection(maps*& conf,maps*& inputs,maps*& outputs){
+    return applyTwo(conf,inputs,outputs,&OGRGeometry::Intersection);
+  }
+
+#ifdef WIN32
+  __declspec(dllexport)
+#endif
+  int Union(maps*& conf,maps*& inputs,maps*& outputs){
+    return applyTwo(conf,inputs,outputs,&OGRGeometry::Union);
+  }
+
+  int applyTwoBool(maps*& conf,maps*& inputs,maps*& outputs,OGRBoolean (OGRGeometry::*myFunc)(const OGRGeometry*) const){
+    OGRRegisterAll();
+
+    maps* cursor=inputs;
+    OGRGeometryH geometry,res;
+    OGRLayer *poDstLayer;
+    OGRDataSource       *poODS;
+
+    char *filename=(char*)malloc(1024*sizeof(char));
+    const char *oDriver1;
+    OGRDataSource* ipoDS1 = loadEntity(conf,inputs,&filename,&oDriver1,"InputEntity1",1);
+
+    char *filename1=(char*)malloc(1024*sizeof(char));
+    const char *oDriver2;
+    OGRDataSource* ipoDS2 = loadEntity(conf,inputs,&filename1,&oDriver2,"InputEntity2",2);
+    const char *oDriver3;
+    char pszDestDataSource[100];
+    if( ipoDS1 == NULL || ipoDS2 == NULL )
+      {
+	OGRSFDriverRegistrar    *poR = OGRSFDriverRegistrar::GetRegistrar();
+	
+	fprintf( stderr, "FAILURE:\n"
+		 "Unable to open datasource `%s' with the following drivers.\n",
+		 filename );
+	
+	for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
+	  {
+	    fprintf( stderr, "  -> %s\n", poR->GetDriver(iDriver)->GetName() );
+	  }
+	char tmp[1024];
+	if( ipoDS1 == NULL )
+	  sprintf(tmp,"Unable to open datasource `%s' with the following drivers.",filename);
+	if( ipoDS2 == NULL )
+	  sprintf(tmp,"Unable to open datasource `%s' with the following drivers.",filename1);
+	setMapInMaps(conf,"lenv","message",tmp);
+	return SERVICE_FAILED;
+      }
+    for( int iLayer = 0; iLayer < ipoDS1->GetLayerCount();
+	 iLayer++ )
+      {
+	OGRLayer        *poLayer1 = ipoDS1->GetLayer(iLayer);
+	
+	if( poLayer1 == NULL )
+	  {
+	    fprintf( stderr, "FAILURE: Couldn't fetch advertised layer %d!\n",
+		     iLayer );
+	    char tmp[1024];
+	    sprintf(tmp,"Couldn't fetch advertised layer %d!",iLayer);
+	    setMapInMaps(conf,"lenv","message",tmp);
+	    return SERVICE_FAILED;
+	  }
+
+	for( int iLayer1 = 0; iLayer1 < ipoDS2->GetLayerCount();
+	     iLayer1++ )
+	  {
+	    OGRLayer        *poLayer2 = ipoDS2->GetLayer(iLayer1);
+	    
+	    if( poLayer1 == NULL )
+	      {
+		fprintf( stderr, "FAILURE: Couldn't fetch advertised layer %d!\n",
+			 iLayer1 );
+		char tmp[1024];
+		sprintf(tmp,"Couldn't fetch advertised layer %d!",iLayer1);
+		setMapInMaps(conf,"lenv","message",tmp);
+		return SERVICE_FAILED;
+	      }
+	
+	    OGRFeature  *poFeature1,*poFeature2;
+
+
+	    while(TRUE){
+	      OGRFeature      *poDstFeature = NULL;
+	      poFeature1 = poLayer1->GetNextFeature();
+	      if( poFeature1 == NULL )
+		break;
+	      while(TRUE){
+		poFeature2 = poLayer2->GetNextFeature();
+		if( poFeature2 == NULL )
+		  break;
+		if(poFeature1->GetGeometryRef() != NULL && poFeature2->GetGeometryRef() != NULL){
+		  if((poFeature1->GetGeometryRef()->*myFunc)(poFeature2->GetGeometryRef())==0){
+		    setMapInMaps(outputs,"Result","value","false");
+		    OGRFeature::DestroyFeature( poFeature1 );
+		    OGRFeature::DestroyFeature( poFeature2 );
+		    delete ipoDS1;
+		    delete ipoDS2;
+		    free(filename);
+		    free(filename1);
+		    return SERVICE_SUCCEEDED;
+		  }
+		}
+		OGRFeature::DestroyFeature( poFeature2 );
+	      }
+	      OGRFeature::DestroyFeature( poFeature1 );
+	    }
+	  }
+      }
+
+    delete ipoDS1;
+    delete ipoDS2;
+    free(filename);
+    free(filename1);
+
+    setMapInMaps(outputs,"Result","value","true");
+
+    OGRCleanupAll();
+    return SERVICE_SUCCEEDED;
+  }
+
+
+#ifdef WIN32
+  __declspec(dllexport)
+#endif
+  int Equals(maps*& conf,maps*& inputs,maps*& outputs){
+    return applyTwoBool(conf,inputs,outputs,(OGRBoolean (OGRGeometry::*)(const OGRGeometry *) const)&OGRGeometry::Equals);
+  }
+
+#ifdef WIN32
+  __declspec(dllexport)
+#endif
+  int Disjoint(maps*& conf,maps*& inputs,maps*& outputs){
+    return applyTwoBool(conf,inputs,outputs,&OGRGeometry::Disjoint);
+  }
+
+#ifdef WIN32
+  __declspec(dllexport)
+#endif
+  int Touches(maps*& conf,maps*& inputs,maps*& outputs){
+    return applyTwoBool(conf,inputs,outputs,&OGRGeometry::Touches);
+  }
+
+#ifdef WIN32
+  __declspec(dllexport)
+#endif
+  int Crosses(maps*& conf,maps*& inputs,maps*& outputs){
+    return applyTwoBool(conf,inputs,outputs,&OGRGeometry::Crosses);
+  }
+
+#ifdef WIN32
+  __declspec(dllexport)
+#endif
+  int Within(maps*& conf,maps*& inputs,maps*& outputs){
+    return applyTwoBool(conf,inputs,outputs,&OGRGeometry::Within);
+  }
+
+#ifdef WIN32
+  __declspec(dllexport)
+#endif
+  int Contains(maps*& conf,maps*& inputs,maps*& outputs){
+    return applyTwoBool(conf,inputs,outputs,&OGRGeometry::Contains);
+  }
+
+#ifdef WIN32
+  __declspec(dllexport)
+#endif
+  int Overlaps(maps*& conf,maps*& inputs,maps*& outputs){
+    return applyTwoBool(conf,inputs,outputs,&OGRGeometry::Overlaps);
+  }
+
+#ifdef WIN32
+  __declspec(dllexport)
+#endif
+  int Intersects(maps*& conf,maps*& inputs,maps*& outputs){
+    return applyTwoBool(conf,inputs,outputs,(OGRBoolean (OGRGeometry::*)(const OGRGeometry *) const)&OGRGeometry::Intersects);
+  }
+
+#ifdef WIN32
+  __declspec(dllexport)
+#endif
+  int Distance(maps*& conf,maps*& inputs,maps*& outputs){
+#ifdef DEBUG
+    fprintf(stderr,"\nService internal print1\n");
+#endif
+    fflush(stderr);
+    maps* cursor=inputs;
+    OGRGeometryH geometry1,geometry2;
+    double res;
+    {
+      map* tmp=getMapFromMaps(inputs,"InputEntity1","value");
+      map* tmp1=getMapFromMaps(inputs,"InputEntity1","mimeType");
+#ifdef DEBUG
+      fprintf(stderr,"MY MAP\n");
+      dumpMap(tmp1);
+      dumpMaps(inputs);
+      fprintf(stderr,"MY MAP\n");
+#endif
+      if(tmp1!=NULL){
+        if(strncmp(tmp1->value,"application/json",16)==0)
+      	  geometry1=OGR_G_CreateGeometryFromJson(tmp->value);
+	else
+	  geometry1=createGeometryFromGML(conf,tmp->value);
+      }
+      else
+      	geometry1=createGeometryFromGML(conf,tmp->value);
+    }
+    if(geometry1==NULL){
+      setMapInMaps(conf,"lenv","message",_ss("Unable to parse input geometry for InputEntity1."));
+      fprintf(stderr,"SERVICE FAILED !\n");
+      return SERVICE_FAILED;
+    }
+    {
+      map* tmp=getMapFromMaps(inputs,"InputEntity2","value");
+      map* tmp1=getMapFromMaps(inputs,"InputEntity2","mimeType");
+#ifdef DEBUG
+      fprintf(stderr,"MY MAP\n");
+      dumpMap(tmp1);
+      dumpMaps(inputs);
+      fprintf(stderr,"MY MAP\n");
+#endif
+      if(tmp1!=NULL){
+        if(strncmp(tmp1->value,"application/json",16)==0)
+      	  geometry2=OGR_G_CreateGeometryFromJson(tmp->value);
+	else
+	  geometry2=createGeometryFromGML(conf,tmp->value);
+      }
+      else
+      	geometry2=createGeometryFromGML(conf,tmp->value);
+    }
+    if(geometry2==NULL){
+      setMapInMaps(conf,"lenv","message",_ss("Unable to parse input geometry for InputEntity2."));
+      fprintf(stderr,"SERVICE FAILED !\n");
+      return SERVICE_FAILED;
+    }
+    res=OGR_G_Distance(geometry1,geometry2);    
+    char tmpres[100];
+    sprintf(tmpres,"%f",res);
+    setMapInMaps(outputs,"Distance","value",tmpres);
+    setMapInMaps(outputs,"Distance","dataType","float");
+#ifdef DEBUG
+    dumpMaps(outputs);
+    fprintf(stderr,"\nService internal print\n===\n");
+#endif
+    return SERVICE_SUCCEEDED;
+  }
+
+#ifdef WIN32
+  __declspec(dllexport)
+#endif
+  int GetArea(maps*& conf,maps*& inputs,maps*& outputs){
+    fprintf(stderr,"GETAREA \n");
+    double res;
+    /**
+     * Extract Geometry from the InputPolygon value
+     */
+    OGRGeometryH geometry;
+    map* tmp=getMapFromMaps(inputs,"InputPolygon","value");
+    if(tmp==NULL){
+      setMapInMaps(conf,"lenv","message",_ss("Unable to parse input geometry from InputPolygon"));
+      return SERVICE_FAILED;
+    }
+    fprintf(stderr,"geometry creation %s \n",tmp->value);
+    geometry=createGeometryFromGML(conf,tmp->value);
+    if(geometry==NULL){
+      setMapInMaps(conf,"lenv","message",_ss("Unable to parse input geometry from InputPolygon"));
+      return SERVICE_FAILED;
+    }
+    fprintf(stderr,"geometry created %s \n",tmp->value);
+    res=OGR_G_Area(geometry);
+    fprintf(stderr,"area %d \n",res);
+    /**
+     * Filling the outputs
+     */
+    char tmp1[100];
+    sprintf(tmp1,"%f",res);
+    setMapInMaps(outputs,"Area","value",tmp1);
+    setMapInMaps(outputs,"Area","dataType","float");
+#ifdef DEBUG
+    dumpMaps(outputs);
+#endif
+    return SERVICE_SUCCEEDED;
+  }
+
+}
diff --git a/zoo-project/zoo-services/ogr/ogr2ogr/Makefile b/zoo-project/zoo-services/ogr/ogr2ogr/Makefile
new file mode 100644
index 0000000..5a02ce0
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/ogr2ogr/Makefile
@@ -0,0 +1,14 @@
+ZRPATH=../../..
+include ${ZRPATH}/zoo-kernel/ZOOMakefile.opts
+CFLAGS=-DZOO_SERVICE ${ZOO_CFLAGS} ${XML2CFLAGS} ${GDAL_CFLAGS} ${PYTHONCFLAGS} -DLINUX_FREE_ISSUE #-DDEBUG
+CC=gcc
+
+cgi-env/ogr2ogr_service.zo: service.c $(DEP_LIBS)
+	g++ $(CFLAGS) $(CPPFLAGS) -shared -fpic $<  -o $@ ${GDAL_LIBS} -lzoo_service
+
+install:
+	install -d ${CGI_DIR}/ogr/ogr2ogr
+	install cgi-env/* ${CGI_DIR}/ogr/ogr2ogr
+
+clean:
+	rm -f cgi-env/*zo
diff --git a/zoo-project/zoo-services/ogr/ogr2ogr/cgi-env/Ogr2Ogr.zcfg b/zoo-project/zoo-services/ogr/ogr2ogr/cgi-env/Ogr2Ogr.zcfg
new file mode 100644
index 0000000..fc0198e
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/ogr2ogr/cgi-env/Ogr2Ogr.zcfg
@@ -0,0 +1,62 @@
+[Ogr2Ogr]
+ Title = Converts vector data from one format to another. 
+ Abstract = http://www.gdal.org/ogr2ogr.html
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceType = C
+ serviceProvider = ogr2ogr_service.zo
+ <MetaData>
+   title = My Demo
+ </MetaData>
+ <DataInputs>
+  [F]
+   Title = Format of the output data
+   Abstract = Select the output format.
+   minOccurs = 0
+   maxOccurs = 1
+   <LiteralData>
+    DataType = string
+    <Default>
+     value = ESRI ShapeFile
+    </Default>
+    <Supported>
+    </Supported>
+   </LiteralData>
+  [InputDSN]
+   Title = The input data source name
+   Abstract = The input data source name to use as source for convertion.
+   minOccurs = 1
+   maxOccurs = 1
+   <LiteralData>
+    DataType = string
+    <Default>
+    </Default>	
+    <Supported>
+    </Supported>
+   </LiteralData>
+  [OutputDSN]
+   Title = The output data source name
+   Abstract = The output data name.
+   minOccurs = 1
+   maxOccurs = 1
+   <LiteralData>
+    DataType = string
+    <Default>
+    </Default>	
+    <Supported>
+    </Supported>
+   </LiteralData>
+ </DataInputs>
+ <DataOutputs>
+  [OutputedDataSourceName]
+   Title = The resulting converted file
+   Abstract = The file name resulting of the convertion
+   <LiteralData>
+    DataType = string
+    <Default>
+    </Default>	
+    <Supported>
+    </Supported>
+   </LiteralData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/ogr/ogr2ogr/makefile.vc b/zoo-project/zoo-services/ogr/ogr2ogr/makefile.vc
new file mode 100644
index 0000000..c402fc0
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/ogr2ogr/makefile.vc
@@ -0,0 +1,11 @@
+GEODIR=c:/OSGeo4W/
+TOOLS=c:/Users/djay/GeoLabs/tools/
+CFLAGS=-I$(GEODIR)/include -I$(TOOLS)/include -I../../../zoo-kernel/ -I./ -DGDAL_1_5_0 -DZOO_SERVICE -DLINUX_FREE_ISSUE -DDEBUG
+CPP=cl /TP 
+
+cgi-env/ogr2ogr_service.zo: service.c
+	$(CPP) $(CFLAGS) /c service.c
+	link /dll /out:cgi-env/ogr2ogr_service.zo ../../../zoo-kernel/service_internal.obj ./service.obj -L$(TOOLS)/lib/libssl32.dll.a $(GEODIR)/lib/libxml2.lib $(GEODIR)/lib/gdal_i.lib $(TOOLS)/lib/libeay32.dll.a $(TOOLS)/lib/libcrypto.a $(TOOLS)/lib/libssl32.dll.a 
+
+clean:
+	rm -f cgi-env/ogr_service.zso
diff --git a/zoo-project/zoo-services/ogr/ogr2ogr/service.c b/zoo-project/zoo-services/ogr/ogr2ogr/service.c
new file mode 100644
index 0000000..3553d8c
--- /dev/null
+++ b/zoo-project/zoo-services/ogr/ogr2ogr/service.c
@@ -0,0 +1,1303 @@
+/******************************************************************************
+ * $Id: ogr2ogr.cpp 15473 2008-10-07 20:59:24Z warmerdam $
+ *
+ * Project:  OpenGIS Simple Features Reference Implementation
+ * Purpose:  Simple client for translating between formats.
+ * Author:   Frank Warmerdam, warmerdam at pobox.com
+ *
+ ******************************************************************************
+ * Copyright (c) 1999, Frank Warmerdam
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ ****************************************************************************/
+
+#include "ogrsf_frmts.h"
+#include "ogr_p.h"
+#include "cpl_conv.h"
+#include "cpl_string.h"
+#include "ogr_api.h"
+#ifdef ZOO_SERVICE
+#include "service.h"
+#endif
+
+CPL_CVSID("$Id: ogr2ogr.cpp 15473 2008-10-07 20:59:24Z warmerdam $");
+
+#ifdef WIN32
+#define strcasecmp _stricmp
+#define strncasecmp _strnicmp 
+#endif
+
+#ifdef ZOO_SERVICE
+extern "C" {
+#endif
+
+static void Usage();
+
+static int TranslateLayer( OGRDataSource *poSrcDS, 
+                           OGRLayer * poSrcLayer,
+                           OGRDataSource *poDstDS,
+                           char ** papszLSCO,
+                           const char *pszNewLayerName,
+                           int bTransform, 
+                           OGRSpatialReference *poOutputSRS,
+                           OGRSpatialReference *poSourceSRS,
+                           char **papszSelFields,
+                           int bAppend, int eGType,
+                           int bOverwrite,
+                           double dfMaxSegmentLength);
+
+static int bSkipFailures = FALSE;
+static int nGroupTransactions = 200;
+static int bPreserveFID = TRUE;
+static int nFIDToFetch = OGRNullFID;
+
+/************************************************************************/
+/*                                main()                                */
+/************************************************************************/
+
+#ifdef ZOO_SERVICE
+#ifdef WIN32
+__declspec(dllexport)
+#endif
+int Ogr2Ogr(maps*& conf,maps*& inputs,maps*& outputs)
+#else
+int main( int nArgc, char ** papszArgv )
+#endif
+{
+    const char  *pszFormat = "ESRI Shapefile";
+    const char  *pszDataSource = NULL;
+    const char  *pszDestDataSource = NULL;
+    const char  *pszwebDestData = NULL;
+    char        **papszLayers = NULL;
+    char        **papszDSCO = NULL, **papszLCO = NULL;
+    int         bTransform = FALSE;
+    int         bAppend = FALSE, bUpdate = FALSE, bOverwrite = FALSE;
+    const char  *pszOutputSRSDef = NULL;
+    const char  *pszSourceSRSDef = NULL;
+    OGRSpatialReference *poOutputSRS = NULL;
+    OGRSpatialReference *poSourceSRS = NULL;
+    const char  *pszNewLayerName = NULL;
+    const char  *pszWHERE = NULL;
+    OGRGeometry *poSpatialFilter = NULL;
+    const char  *pszSelect;
+    char        **papszSelFields = NULL;
+    const char  *pszSQLStatement = NULL;
+    int         eGType = -2;
+    double      dfMaxSegmentLength = 0;
+
+#ifdef ZOO_SERVICE
+    dumpMaps(inputs);
+#endif
+    /* Check strict compilation and runtime library version as we use C++ API */
+    if (! GDAL_CHECK_VERSION("ogr2ogr"))
+#ifdef ZOO_SERVICE
+	{
+		fprintf(stderr,"Not correct version of the gdal library\n");
+		setMapInMaps(conf,"lenv","message","Unable to check gdal version for ogr2ogr_service.zo");
+		return SERVICE_FAILED;
+	}
+#else
+        exit(1);
+#endif
+/* -------------------------------------------------------------------- */
+/*      Register format(s).                                             */
+/* -------------------------------------------------------------------- */
+    OGRRegisterAll();
+
+#ifdef ZOO_SERVICE
+    map *tmpMap=NULL;
+    char dataPath[1024];
+    tmpMap=getMapFromMaps(conf,"main","dataPath");
+    if(tmpMap!=NULL)
+      sprintf(dataPath,"%s",tmpMap->value);
+    tmpMap=NULL;
+    char tempPath[1024];
+    tmpMap=getMapFromMaps(conf,"main","tmpPath");
+    if(tmpMap!=NULL){
+      sprintf(tempPath,"%s",tmpMap->value);
+    }
+    
+    tmpMap=NULL;
+    char serverAddress[1024];
+    tmpMap=getMapFromMaps(conf,"main","serverAddress");
+    if(tmpMap!=NULL){
+      sprintf(serverAddress,"%s",tmpMap->value);
+    }
+    
+    tmpMap=NULL;
+    char tmpurl[1024];
+    tmpMap=getMapFromMaps(conf,"main","tmpurl");
+    if(tmpMap!=NULL){
+      sprintf(tmpurl,"%s",tmpMap->value);
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"F","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0){
+      pszFormat=tmpMap->value;
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"DSCO","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0){
+	  papszDSCO = CSLAddString(papszDSCO, tmpMap->value );
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"LCO","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0){
+	  papszLCO = CSLAddString(papszLCO, tmpMap->value );
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"preserve_fid","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0){
+	  bPreserveFID = TRUE;
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"skipfailure","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0){
+      bSkipFailures = TRUE;
+      nGroupTransactions = 1; /* #2409 */
+    }
+
+    /* if exist, overwrite the data with the same name */
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"overwrite","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0){
+      bOverwrite = TRUE;
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"append","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"TRUE",4)==0){
+      bAppend = TRUE;
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"update","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"TRUE",4)==0){
+      bUpdate = TRUE;
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"fid","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0){
+      nFIDToFetch = atoi(tmpMap->value);
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"sql","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0){
+      pszSQLStatement = tmpMap->value;
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"nln","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0){
+	  pszNewLayerName = tmpMap->value;
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"nlt","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0){
+	  pszNewLayerName = tmpMap->value;
+	  if( EQUAL(tmpMap->value,"NONE") )
+		  eGType = wkbNone;
+	  else if( EQUAL(tmpMap->value,"GEOMETRY") )
+		  eGType = wkbUnknown;
+	  else if( EQUAL(tmpMap->value,"POINT") )
+		  eGType = wkbPoint;
+	  else if( EQUAL(tmpMap->value,"LINESTRING") )
+		  eGType = wkbLineString;
+	  else if( EQUAL(tmpMap->value,"POLYGON") )
+		  eGType = wkbPolygon;
+	  else if( EQUAL(tmpMap->value,"GEOMETRYCOLLECTION") )
+		  eGType = wkbGeometryCollection;
+	  else if( EQUAL(tmpMap->value,"MULTIPOINT") )
+		  eGType = wkbMultiPoint;
+	  else if( EQUAL(tmpMap->value,"MULTILINESTRING") )
+		  eGType = wkbMultiLineString;
+	  else if( EQUAL(tmpMap->value,"MULTIPOLYGON") )
+		  eGType = wkbMultiPolygon;
+	  else if( EQUAL(tmpMap->value,"GEOMETRY25D") )
+		  eGType = wkbUnknown | wkb25DBit;
+	  else if( EQUAL(tmpMap->value,"POINT25D") )
+		  eGType = wkbPoint25D;
+	  else if( EQUAL(tmpMap->value,"LINESTRING25D") )
+		  eGType = wkbLineString25D;
+	  else if( EQUAL(tmpMap->value,"POLYGON25D") )
+		  eGType = wkbPolygon25D;
+	  else if( EQUAL(tmpMap->value,"GEOMETRYCOLLECTION25D") )
+		  eGType = wkbGeometryCollection25D;
+	  else if( EQUAL(tmpMap->value,"MULTIPOINT25D") )
+		  eGType = wkbMultiPoint25D;
+	  else if( EQUAL(tmpMap->value,"MULTILINESTRING25D") )
+		  eGType = wkbMultiLineString25D;
+	  else if( EQUAL(tmpMap->value,"MULTIPOLYGON25D") )
+		  eGType = wkbMultiPolygon25D;
+	  else	  
+	  {
+		  fprintf( stderr, "-nlt %s: type not recognised.\n", 
+			  tmpMap->value );
+		  exit( 1 );
+	  }
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"tg","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0){
+	  nGroupTransactions = atoi(tmpMap->value);
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"s_srs","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0){
+      pszSourceSRSDef = strdup(tmpMap->value);
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"a_srs","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0){
+      pszOutputSRSDef = strdup(tmpMap->value);
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"t_srs","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0){
+      pszOutputSRSDef = strdup(tmpMap->value);
+      bTransform = TRUE;
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"SPAT","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0){
+      char *tmp=tmpMap->value;
+      char *t=strtok(tmp,",");
+      int cnt=0;
+      double dfULX, dfULY, dfLRX, dfLRY;
+      while(t!=NULL){
+        switch(cnt){
+        case 0:
+          dfULX = atof(t);
+          break;
+        case 1:
+          dfULY = atof(t);
+          break;
+        case 2:
+          dfLRX = atof(t);
+          break;
+        case 3:
+          dfLRY = atof(t);
+          break;
+        }
+        fprintf(stderr,"%s\n\n",t);
+        fprintf(stderr,"%f - %f - %f - %f\n\n",dfULX,dfULY,dfLRX,dfLRY);
+        t=strtok(NULL,",");
+        cnt++;
+      }
+
+      OGRLinearRing  oRing;
+      
+      oRing.addPoint( dfULX, dfULY );
+      oRing.addPoint( dfULX, dfLRY );
+      oRing.addPoint( dfLRX, dfLRY );
+      oRing.addPoint( dfLRX, dfULY );
+      oRing.addPoint( dfULX, dfULY );
+      poSpatialFilter = new OGRPolygon();
+      ((OGRPolygon *) poSpatialFilter)->addRing( &oRing );
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"where","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0){
+	  pszWHERE = tmpMap->value;
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"select","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0){
+	  pszSelect = tmpMap->value;
+	  papszSelFields = CSLTokenizeStringComplex(pszSelect, " ,", 
+		  FALSE, FALSE );
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"segmentize","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0){
+	  dfMaxSegmentLength = atof(tmpMap->value);
+    }
+
+    /*tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"segmentize","value");
+    if(tmpMap!=NULL){
+	  dfMaxSegmentLength = atof(tmpMap->value);
+    }*/
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"InputDSN","value");
+    if(tmpMap!=NULL && strncasecmp(tmpMap->value,"NULL",4)!=0){
+      if(strncasecmp(tmpMap->value,"PG",2)!=0 &&
+	 strncasecmp(tmpMap->value,"My",2)!=0 &&
+	 strncasecmp(tmpMap->value,"OCI",3)!=0 ){
+	if(strncasecmp(dataPath,tmpMap->value,strlen(dataPath))==0 ||
+	   strncasecmp(tempPath,tmpMap->value,strlen(tempPath))==0){
+	  pszDataSource=strdup(tmpMap->value);
+	}else{
+	  pszDataSource=(char*)malloc(sizeof(char)*(strlen(dataPath)+strlen(tmpMap->value)+2));
+	  sprintf((char*)pszDataSource,"%s/%s",dataPath,tmpMap->value);
+	}
+      }else{
+	pszDataSource=(char*)malloc(sizeof(char)*(strlen(tmpMap->value)+1));
+	sprintf((char*)pszDataSource,"%s",tmpMap->value);	
+      }
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"OutputDSN","value");
+    if(tmpMap!=NULL){
+      if(strncasecmp(tmpMap->value,"PG",2)!=0 &&
+	 strncasecmp(tmpMap->value,"MY",2)!=0 &&
+	 strncasecmp(tmpMap->value,"OCI",3)!=0){
+	pszDestDataSource=(char*)malloc(sizeof(char)*(strlen(tempPath)+strlen(tmpMap->value)+4));
+	sprintf((char*)pszDestDataSource,"%s/%s",tempPath,tmpMap->value/*,ext*/);
+	pszwebDestData=(char*)malloc(sizeof(char)*(strlen(serverAddress)+strlen(tmpurl)+strlen(tmpMap->value)+4));
+	sprintf((char*)pszwebDestData,"%s%s/%s",serverAddress,tmpurl,tmpMap->value/*,ext*/);
+      }
+      else{
+	pszDestDataSource=(char*)malloc(sizeof(char)*(strlen(tmpMap->value)+1));
+	sprintf((char*)pszDestDataSource,"%s",tmpMap->value/*,ext*/);
+	pszwebDestData=(char*)malloc(sizeof(char)*(strlen(serverAddress)+strlen(tmpurl)+strlen(tmpMap->value)+4));
+	sprintf((char*)pszwebDestData,"%s%s/%s",serverAddress,tmpurl,tmpMap->value/*,ext*/);
+      }
+    }
+
+    fprintf(stderr,"Message %s\n",pszDestDataSource);
+#else
+/* -------------------------------------------------------------------- */
+/*      Processing command line arguments.                              */
+/* -------------------------------------------------------------------- */
+    nArgc = OGRGeneralCmdLineProcessor( nArgc, &papszArgv, 0 );
+    
+    if( nArgc < 1 )
+        exit( -nArgc );
+
+    for( int iArg = 1; iArg < nArgc; iArg++ )
+    {
+        if( EQUAL(papszArgv[iArg], "--utility_version") )
+        {
+				printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
+                   papszArgv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
+            return 0;
+        }
+        else if( EQUAL(papszArgv[iArg],"-f") && iArg < nArgc-1 )
+        {
+            pszFormat = papszArgv[++iArg];
+        }
+        else if( EQUAL(papszArgv[iArg],"-dsco") && iArg < nArgc-1 )
+        {
+            papszDSCO = CSLAddString(papszDSCO, papszArgv[++iArg] );
+        }
+        else if( EQUAL(papszArgv[iArg],"-lco") && iArg < nArgc-1 )
+        {
+            papszLCO = CSLAddString(papszLCO, papszArgv[++iArg] );
+        }
+        else if( EQUAL(papszArgv[iArg],"-preserve_fid") )
+        {
+            bPreserveFID = TRUE;
+        }
+        else if( EQUALN(papszArgv[iArg],"-skip",5) )
+        {
+            bSkipFailures = TRUE;
+            nGroupTransactions = 1; /* #2409 */
+        }
+        else if( EQUAL(papszArgv[iArg],"-append") )
+        {
+            bAppend = TRUE;
+        }
+        else if( EQUAL(papszArgv[iArg],"-overwrite") )
+        {
+            bOverwrite = TRUE;
+        }
+        else if( EQUAL(papszArgv[iArg],"-update") )
+        {
+            bUpdate = TRUE;
+        }
+        else if( EQUAL(papszArgv[iArg],"-fid") && papszArgv[iArg+1] != NULL )
+        {
+            nFIDToFetch = atoi(papszArgv[++iArg]);
+        }
+        else if( EQUAL(papszArgv[iArg],"-sql") && papszArgv[iArg+1] != NULL )
+        {
+            pszSQLStatement = papszArgv[++iArg];
+        }
+        else if( EQUAL(papszArgv[iArg],"-nln") && iArg < nArgc-1 )
+        {
+            pszNewLayerName = papszArgv[++iArg];
+        }
+        else if( EQUAL(papszArgv[iArg],"-nlt") && iArg < nArgc-1 )
+        {
+            if( EQUAL(papszArgv[iArg+1],"NONE") )
+                eGType = wkbNone;
+            else if( EQUAL(papszArgv[iArg+1],"GEOMETRY") )
+                eGType = wkbUnknown;
+            else if( EQUAL(papszArgv[iArg+1],"POINT") )
+                eGType = wkbPoint;
+            else if( EQUAL(papszArgv[iArg+1],"LINESTRING") )
+                eGType = wkbLineString;
+            else if( EQUAL(papszArgv[iArg+1],"POLYGON") )
+                eGType = wkbPolygon;
+            else if( EQUAL(papszArgv[iArg+1],"GEOMETRYCOLLECTION") )
+                eGType = wkbGeometryCollection;
+            else if( EQUAL(papszArgv[iArg+1],"MULTIPOINT") )
+                eGType = wkbMultiPoint;
+            else if( EQUAL(papszArgv[iArg+1],"MULTILINESTRING") )
+                eGType = wkbMultiLineString;
+            else if( EQUAL(papszArgv[iArg+1],"MULTIPOLYGON") )
+                eGType = wkbMultiPolygon;
+            else if( EQUAL(papszArgv[iArg+1],"GEOMETRY25D") )
+                eGType = wkbUnknown | wkb25DBit;
+            else if( EQUAL(papszArgv[iArg+1],"POINT25D") )
+                eGType = wkbPoint25D;
+            else if( EQUAL(papszArgv[iArg+1],"LINESTRING25D") )
+                eGType = wkbLineString25D;
+            else if( EQUAL(papszArgv[iArg+1],"POLYGON25D") )
+                eGType = wkbPolygon25D;
+            else if( EQUAL(papszArgv[iArg+1],"GEOMETRYCOLLECTION25D") )
+                eGType = wkbGeometryCollection25D;
+            else if( EQUAL(papszArgv[iArg+1],"MULTIPOINT25D") )
+                eGType = wkbMultiPoint25D;
+            else if( EQUAL(papszArgv[iArg+1],"MULTILINESTRING25D") )
+                eGType = wkbMultiLineString25D;
+            else if( EQUAL(papszArgv[iArg+1],"MULTIPOLYGON25D") )
+                eGType = wkbMultiPolygon25D;
+            else
+            {
+                fprintf( stderr, "-nlt %s: type not recognised.\n", 
+                         papszArgv[iArg+1] );
+                exit( 1 );
+            }
+            iArg++;
+        }
+        else if( (EQUAL(papszArgv[iArg],"-tg") ||
+                  EQUAL(papszArgv[iArg],"-gt")) && iArg < nArgc-1 )
+        {
+            nGroupTransactions = atoi(papszArgv[++iArg]);
+        }
+        else if( EQUAL(papszArgv[iArg],"-s_srs") && iArg < nArgc-1 )
+        {
+            pszSourceSRSDef = papszArgv[++iArg];
+        }
+        else if( EQUAL(papszArgv[iArg],"-a_srs") && iArg < nArgc-1 )
+        {
+            pszOutputSRSDef = papszArgv[++iArg];
+        }
+        else if( EQUAL(papszArgv[iArg],"-t_srs") && iArg < nArgc-1 )
+        {
+            pszOutputSRSDef = papszArgv[++iArg];
+            bTransform = TRUE;
+        }
+        else if( EQUAL(papszArgv[iArg],"-spat") 
+                 && papszArgv[iArg+1] != NULL 
+                 && papszArgv[iArg+2] != NULL 
+                 && papszArgv[iArg+3] != NULL 
+                 && papszArgv[iArg+4] != NULL )
+        {
+            OGRLinearRing  oRing;
+
+            oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+2]) );
+            oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+4]) );
+            oRing.addPoint( atof(papszArgv[iArg+3]), atof(papszArgv[iArg+4]) );
+            oRing.addPoint( atof(papszArgv[iArg+3]), atof(papszArgv[iArg+2]) );
+            oRing.addPoint( atof(papszArgv[iArg+1]), atof(papszArgv[iArg+2]) );
+
+            poSpatialFilter = new OGRPolygon();
+            ((OGRPolygon *) poSpatialFilter)->addRing( &oRing );
+            iArg += 4;
+        }
+        else if( EQUAL(papszArgv[iArg],"-where") && papszArgv[iArg+1] != NULL )
+        {
+            pszWHERE = papszArgv[++iArg];
+        }
+        else if( EQUAL(papszArgv[iArg],"-select") && papszArgv[iArg+1] != NULL)
+        {
+            pszSelect = papszArgv[++iArg];
+            papszSelFields = CSLTokenizeStringComplex(pszSelect, " ,", 
+                                                      FALSE, FALSE );
+        }
+        else if( EQUAL(papszArgv[iArg],"-segmentize") && iArg < nArgc-1 )
+        {
+            dfMaxSegmentLength = atof(papszArgv[++iArg]);
+        }
+        else if( papszArgv[iArg][0] == '-' )
+        {
+            Usage();
+        }
+        else if( pszDestDataSource == NULL )
+            pszDestDataSource = papszArgv[iArg];
+        else if( pszDataSource == NULL )
+            pszDataSource = papszArgv[iArg];
+        else
+            papszLayers = CSLAddString( papszLayers, papszArgv[iArg] );
+    }
+#endif
+
+    if( pszDataSource == NULL )
+#ifdef ZOO_SERVICE
+	{
+#else
+	  Usage();
+#endif
+#ifdef ZOO_SERVICE
+	  setMapInMaps(conf,"lenv","message","Wrong parameter");
+	  return SERVICE_FAILED;
+	}
+#endif
+
+/* -------------------------------------------------------------------- */
+/*      Open data source.                                               */
+/* -------------------------------------------------------------------- */
+    OGRDataSource       *poDS;
+        
+    poDS = OGRSFDriverRegistrar::Open( pszDataSource, FALSE );
+
+/* -------------------------------------------------------------------- */
+/*      Report failure                                                  */
+/* -------------------------------------------------------------------- */
+    if( poDS == NULL )
+    {
+        OGRSFDriverRegistrar    *poR = OGRSFDriverRegistrar::GetRegistrar();
+        
+        fprintf( stderr, "FAILURE:\n"
+                "Unable to open datasource `%s' with the following drivers.\n",
+                pszDataSource );
+
+        for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
+        {
+            fprintf( stderr, "  -> %s\n", poR->GetDriver(iDriver)->GetName() );
+        }
+#ifdef ZOO_SERVICE
+	char tmp[1024];
+	sprintf(tmp,"Unable to open datasource `%s' with the following drivers.",pszDataSource);
+	setMapInMaps(conf,"lenv","message",tmp);
+	return SERVICE_FAILED;
+#else
+        exit( 1 );
+#endif
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Try opening the output datasource as an existing, writable      */
+/* -------------------------------------------------------------------- */
+    OGRDataSource       *poODS;
+    
+    if( bUpdate )
+    {
+        poODS = OGRSFDriverRegistrar::Open( pszDestDataSource, TRUE );
+        if( poODS == NULL )
+        {
+            fprintf( stderr, "FAILURE:\n"
+                    "Unable to open existing output datasource `%s'.\n",
+                    pszDestDataSource );
+#ifdef ZOO_SERVICE
+	    char tmp[1024];
+	    sprintf(tmp,"Unable to open existing output datasource `%s'.",pszDestDataSource);
+	    setMapInMaps(conf,"lenv","message",tmp);
+	    return SERVICE_FAILED;
+#else
+        exit( 1 );
+#endif
+        }
+
+        if( CSLCount(papszDSCO) > 0 )
+        {
+            fprintf( stderr, "WARNING: Datasource creation options ignored since an existing datasource\n"
+                    "         being updated.\n" );
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Find the output driver.                                         */
+/* -------------------------------------------------------------------- */
+    else
+    {
+        OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
+        OGRSFDriver          *poDriver = NULL;
+        int                  iDriver;
+
+        for( iDriver = 0;
+             iDriver < poR->GetDriverCount() && poDriver == NULL;
+             iDriver++ )
+        {
+            if( EQUAL(poR->GetDriver(iDriver)->GetName(),pszFormat) )
+            {
+                poDriver = poR->GetDriver(iDriver);
+            }
+        }
+
+        if( poDriver == NULL )
+        {
+            fprintf( stderr, "Unable to find driver `%s'.\n", pszFormat );
+            fprintf( stderr,  "The following drivers are available:\n" );
+        
+            for( iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
+            {
+                fprintf( stderr,  "  -> `%s'\n", poR->GetDriver(iDriver)->GetName() );
+            }
+#ifdef ZOO_SERVICE
+	    char tmp[1024];
+	    sprintf(tmp,"Unable to find driver `%s'.",pszFormat);
+	    setMapInMaps(conf,"lenv","message",tmp);
+	    return SERVICE_FAILED;
+#else
+            exit( 1 );
+#endif
+        }
+
+        if( !poDriver->TestCapability( ODrCCreateDataSource ) )
+        {
+            fprintf( stderr,  "%s driver does not support data source creation.\n",
+                    pszFormat );
+#ifdef ZOO_SERVICE
+	    char tmp[1024];
+	    sprintf(tmp,"%s driver does not support data source creation.",pszFormat);
+	    setMapInMaps(conf,"lenv","message",tmp);
+	    return SERVICE_FAILED;
+#else
+            exit( 1 );
+#endif
+        }
+
+/* -------------------------------------------------------------------- */
+/*      Create the output data source.                                  */
+/* -------------------------------------------------------------------- */
+        poODS = poDriver->CreateDataSource( pszDestDataSource, papszDSCO );
+        if( poODS == NULL )
+        {
+            fprintf( stderr,  "%s driver failed to create %s\n", 
+                    pszFormat, pszDestDataSource );
+#ifdef ZOO_SERVICE
+	    char tmp[1024];
+	    sprintf(tmp,"%s driver failed to create %s",pszFormat, pszDestDataSource);
+	    setMapInMaps(conf,"lenv","message",tmp);
+	    return SERVICE_FAILED;
+#else
+            exit( 1 );
+#endif
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Parse the output SRS definition if possible.                    */
+/* -------------------------------------------------------------------- */
+    if( pszOutputSRSDef != NULL )
+    {
+        poOutputSRS = new OGRSpatialReference();
+        if( poOutputSRS->SetFromUserInput( pszOutputSRSDef ) != OGRERR_NONE )
+        {
+            fprintf( stderr,  "Failed to process SRS definition: %s\n", 
+                    pszOutputSRSDef );
+#ifdef ZOO_SERVICE
+	    char tmp[1024];
+	    sprintf(tmp,"Failed to process SRS definition: %s",pszOutputSRSDef);
+	    setMapInMaps(conf,"lenv","message",tmp);
+	    return SERVICE_FAILED;
+#else
+            exit( 1 );
+#endif
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Parse the source SRS definition if possible.                    */
+/* -------------------------------------------------------------------- */
+    if( pszSourceSRSDef != NULL )
+    {
+        poSourceSRS = new OGRSpatialReference();
+        if( poSourceSRS->SetFromUserInput( pszSourceSRSDef ) != OGRERR_NONE )
+        {
+            fprintf( stderr,  "Failed to process SRS definition: %s\n", 
+                    pszSourceSRSDef );
+#ifdef ZOO_SERVICE
+	    char tmp[1024];
+	    sprintf(tmp,"Failed to process SRS definition: %s",pszOutputSRSDef);
+	    setMapInMaps(conf,"lenv","message",tmp);
+	    return SERVICE_FAILED;
+#else
+            exit( 1 );
+#endif
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Special case for -sql clause.  No source layers required.       */
+/* -------------------------------------------------------------------- */
+    if( pszSQLStatement != NULL )
+    {
+        OGRLayer *poResultSet;
+
+        if( pszWHERE != NULL )
+            fprintf( stderr,  "-where clause ignored in combination with -sql.\n" );
+        if( CSLCount(papszLayers) > 0 )
+	  fprintf( stderr,  "layer names ignored in combination with -sql. (%s)\n", pszSQLStatement);
+        
+        poResultSet = poDS->ExecuteSQL( pszSQLStatement, poSpatialFilter, 
+                                        NULL );
+
+        if( poResultSet != NULL )
+        {
+            if( !TranslateLayer( poDS, poResultSet, poODS, papszLCO, 
+                                 pszNewLayerName, bTransform, poOutputSRS,
+                                 poSourceSRS, papszSelFields, bAppend, eGType,
+                                 bOverwrite, dfMaxSegmentLength ))
+            {
+                CPLError( CE_Failure, CPLE_AppDefined, 
+                          "Terminating translation prematurely after failed\n"
+                          "translation from sql statement." );
+
+                exit( 1 );
+            }
+            poDS->ReleaseResultSet( poResultSet );
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Process each data source layer.                                 */
+/* -------------------------------------------------------------------- */
+    for( int iLayer = 0; 
+         pszSQLStatement == NULL && iLayer < poDS->GetLayerCount(); 
+         iLayer++ )
+    {
+        OGRLayer        *poLayer = poDS->GetLayer(iLayer);
+
+        if( poLayer == NULL )
+        {
+            fprintf( stderr, "FAILURE: Couldn't fetch advertised layer %d!\n",
+                    iLayer );
+#ifdef ZOO_SERVICE
+	    char tmp[1024];
+	    sprintf(tmp,"Couldn't fetch advertised layer %d!",iLayer);
+	    setMapInMaps(conf,"lenv","message",tmp);
+	    return SERVICE_FAILED;
+#else
+	    exit( 1 );
+#endif
+        }
+
+        if( CSLCount(papszLayers) == 0
+            || CSLFindString( papszLayers,
+                              poLayer->GetLayerDefn()->GetName() ) != -1 )
+        {
+            if( pszWHERE != NULL )
+                poLayer->SetAttributeFilter( pszWHERE );
+            
+            if( poSpatialFilter != NULL )
+                poLayer->SetSpatialFilter( poSpatialFilter );
+            
+            if( !TranslateLayer( poDS, poLayer, poODS, papszLCO, 
+                                 pszNewLayerName, bTransform, poOutputSRS,
+                                 poSourceSRS, papszSelFields, bAppend, eGType,
+                                 bOverwrite, dfMaxSegmentLength ) 
+                && !bSkipFailures )
+            {
+#ifdef ZOO_SERVICE
+		char tmp[1024];
+		sprintf(tmp,"Terminating translation prematurely after failed of layer %s",poLayer->GetLayerDefn()->GetName() );
+		setMapInMaps(conf,"lenv","message",tmp);
+		return SERVICE_FAILED;
+#else
+                CPLError( CE_Failure, CPLE_AppDefined, 
+                          "Terminating translation prematurely after failed\n"
+                          "translation of layer %s (use -skipfailures to skip errors)\n", 
+                          poLayer->GetLayerDefn()->GetName() );
+
+                exit( 1 );
+#endif
+            }
+        }
+    }
+
+#ifdef ZOO_SERVICE
+    outputs->content=createMap("value",(char*)pszwebDestData);
+#endif
+
+/* -------------------------------------------------------------------- */
+/*      Close down.                                                     */
+/* -------------------------------------------------------------------- */
+    fprintf(stderr,"%s %d\n",__FILE__,__LINE__);
+    delete poOutputSRS;
+    fprintf(stderr,"%s %d\n",__FILE__,__LINE__);
+    delete poSourceSRS;
+    fprintf(stderr,"%s %d\n",__FILE__,__LINE__);
+    delete poODS;
+    fprintf(stderr,"%s %d\n",__FILE__,__LINE__);
+    delete poDS;
+    fprintf(stderr,"%s %d\n",__FILE__,__LINE__);
+
+#ifndef ZOO_SERVICE
+    CSLDestroy(papszSelFields);
+    CSLDestroy( papszArgv );
+#endif
+    fprintf(stderr,"%s %d\n",__FILE__,__LINE__);
+    CSLDestroy( papszLayers );
+    fprintf(stderr,"%s %d\n",__FILE__,__LINE__);
+#ifndef ZOO_SERVICE
+    CSLDestroy( papszDSCO );
+    CSLDestroy( papszLCO );
+#endif
+    fprintf(stderr,"%s %d\n",__FILE__,__LINE__);
+
+    OGRCleanupAll();
+    fprintf(stderr,"%s %d\n",__FILE__,__LINE__);
+
+#ifdef DBMALLOC
+    malloc_dump(1);
+#endif
+    fprintf(stderr,"%s %d\n",__FILE__,__LINE__);
+    
+#ifdef ZOO_SERVICE
+    return SERVICE_SUCCEEDED;
+#else
+    return 0;
+#endif
+}
+
+/************************************************************************/
+/*                               Usage()                                */
+/************************************************************************/
+
+static void Usage()
+
+{
+    OGRSFDriverRegistrar        *poR = OGRSFDriverRegistrar::GetRegistrar();
+
+#ifdef ZOO_SERVICE
+	fprintf(stderr,
+#else
+	printf(
+#endif
+		"Usage: ogr2ogr [--help-general] [-skipfailures] [-append] [-update] [-gt n]\n"
+		"               [-select field_list] [-where restricted_where] \n"
+		"               [-sql <sql statement>] \n" 
+		"               [-spat xmin ymin xmax ymax] [-preserve_fid] [-fid FID]\n"
+		"               [-a_srs srs_def] [-t_srs srs_def] [-s_srs srs_def]\n"
+		"               [-f format_name] [-overwrite] [[-dsco NAME=VALUE] ...]\n"
+		"               [-segmentize max_dist]\n"
+		"               dst_datasource_name src_datasource_name\n"
+		"               [-lco NAME=VALUE] [-nln name] [-nlt type] [layer [layer ...]]\n"
+		"\n"
+		" -f format_name: output file format name, possible values are:\n");
+    
+    for( int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
+    {
+        OGRSFDriver *poDriver = poR->GetDriver(iDriver);
+
+        if( poDriver->TestCapability( ODrCCreateDataSource ) )
+            printf( "     -f \"%s\"\n", poDriver->GetName() );
+    }
+
+#ifdef ZOO_SERVICE
+	fprintf(stderr,
+#else
+	printf(
+#endif
+		" -append: Append to existing layer instead of creating new if it exists\n"
+		" -overwrite: delete the output layer and recreate it empty\n"
+		" -update: Open existing output datasource in update mode\n"
+		" -select field_list: Comma-delimited list of fields from input layer to\n"
+		"                     copy to the new layer (defaults to all)\n" 
+		" -where restricted_where: Attribute query (like SQL WHERE)\n" 
+		" -sql statement: Execute given SQL statement and save result.\n"
+		" -skipfailures: skip features or layers that fail to convert\n"
+		" -gt n: group n features per transaction (default 200)\n"
+		" -spat xmin ymin xmax ymax: spatial query extents\n"
+		" -segmentize max_dist: maximum distance between 2 nodes.\n"
+		"                       Used to create intermediate points\n"
+		" -dsco NAME=VALUE: Dataset creation option (format specific)\n"
+		" -lco  NAME=VALUE: Layer creation option (format specific)\n"
+		" -nln name: Assign an alternate name to the new layer\n"
+		" -nlt type: Force a geometry type for new layer.  One of NONE, GEOMETRY,\n"
+		"      POINT, LINESTRING, POLYGON, GEOMETRYCOLLECTION, MULTIPOINT,\n"
+		"      MULTIPOLYGON, or MULTILINESTRING.  Add \"25D\" for 3D layers.\n"
+		"      Default is type of source layer.\n" );
+
+#ifdef ZOO_SERVICE
+	fprintf(stderr,
+#else
+	printf(
+#endif
+		" -a_srs srs_def: Assign an output SRS\n"
+		" -t_srs srs_def: Reproject/transform to this SRS on output\n"
+		" -s_srs srs_def: Override source SRS\n"
+		"\n" 
+		" Srs_def can be a full WKT definition (hard to escape properly),\n"
+		" or a well known definition (ie. EPSG:4326) or a file with a WKT\n"
+		" definition.\n" );
+
+
+#ifndef ZOO_SERVICE
+	exit( 1 );
+#endif
+}
+
+/************************************************************************/
+/*                           TranslateLayer()                           */
+/************************************************************************/
+
+static int TranslateLayer( OGRDataSource *poSrcDS, 
+                           OGRLayer * poSrcLayer,
+                           OGRDataSource *poDstDS,
+                           char **papszLCO,
+                           const char *pszNewLayerName,
+                           int bTransform, 
+                           OGRSpatialReference *poOutputSRS,
+                           OGRSpatialReference *poSourceSRS,
+                           char **papszSelFields,
+                           int bAppend, int eGType, int bOverwrite,
+                           double dfMaxSegmentLength)
+		
+{
+    OGRLayer    *poDstLayer;
+    OGRFeatureDefn *poFDefn;
+    OGRErr      eErr;
+    int         bForceToPolygon = FALSE;
+    int         bForceToMultiPolygon = FALSE;
+
+    if( pszNewLayerName == NULL )
+        pszNewLayerName = poSrcLayer->GetLayerDefn()->GetName();
+
+    if( wkbFlatten(eGType) == wkbPolygon )
+        bForceToPolygon = TRUE;
+    else if( wkbFlatten(eGType) == wkbMultiPolygon )
+        bForceToMultiPolygon = TRUE;
+
+/* -------------------------------------------------------------------- */
+/*      Setup coordinate transformation if we need it.                  */
+/* -------------------------------------------------------------------- */
+    OGRCoordinateTransformation *poCT = NULL;
+
+    if( bTransform )
+    {
+        if( poSourceSRS == NULL )
+            poSourceSRS = poSrcLayer->GetSpatialRef();
+
+        if( poSourceSRS == NULL )
+        {
+            fprintf( stderr, "Can't transform coordinates, source layer has no\n"
+                    "coordinate system.  Use -s_srs to set one.\n" );
+#ifdef ZOO_SERVICE
+            return SERVICE_FAILED;
+#else
+            exit( 1 );
+#endif
+        }
+
+        CPLAssert( NULL != poSourceSRS );
+        CPLAssert( NULL != poOutputSRS );
+
+        poCT = OGRCreateCoordinateTransformation( poSourceSRS, poOutputSRS );
+        if( poCT == NULL )
+        {
+            char        *pszWKT = NULL;
+
+            fprintf( stderr, "Failed to create coordinate transformation between the\n"
+                   "following coordinate systems.  This may be because they\n"
+                   "are not transformable, or because projection services\n"
+                   "(PROJ.4 DLL/.so) could not be loaded.\n" );
+            
+            poSourceSRS->exportToPrettyWkt( &pszWKT, FALSE );
+            fprintf( stderr,  "Source:\n%s\n", pszWKT );
+            
+            poOutputSRS->exportToPrettyWkt( &pszWKT, FALSE );
+            fprintf( stderr,  "Target:\n%s\n", pszWKT );
+#ifdef ZOO_SERVICE
+            return SERVICE_FAILED;
+#else
+            exit( 1 );
+#endif
+        }
+    }
+    
+/* -------------------------------------------------------------------- */
+/*      Get other info.                                                 */
+/* -------------------------------------------------------------------- */
+    poFDefn = poSrcLayer->GetLayerDefn();
+    
+    if( poOutputSRS == NULL )
+        poOutputSRS = poSrcLayer->GetSpatialRef();
+
+/* -------------------------------------------------------------------- */
+/*      Find the layer.                                                 */
+/* -------------------------------------------------------------------- */
+    int iLayer = -1;
+    poDstLayer = NULL;
+
+    for( iLayer = 0; iLayer < poDstDS->GetLayerCount(); iLayer++ )
+    {
+        OGRLayer        *poLayer = poDstDS->GetLayer(iLayer);
+
+        if( poLayer != NULL 
+            && EQUAL(poLayer->GetLayerDefn()->GetName(),pszNewLayerName) )
+        {
+            poDstLayer = poLayer;
+            break;
+        }
+    }
+    
+/* -------------------------------------------------------------------- */
+/*      If the user requested overwrite, and we have the layer in       */
+/*      question we need to delete it now so it will get recreated      */
+/*      (overwritten).                                                  */
+/* -------------------------------------------------------------------- */
+    if( poDstLayer != NULL && bOverwrite )
+    {
+        if( poDstDS->DeleteLayer( iLayer ) != OGRERR_NONE )
+        {
+            fprintf( stderr, 
+                     "DeleteLayer() failed when overwrite requested.\n" );
+            return FALSE;
+        }
+        poDstLayer = NULL;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      If the layer does not exist, then create it.                    */
+/* -------------------------------------------------------------------- */
+    if( poDstLayer == NULL )
+    {
+        if( eGType == -2 )
+            eGType = poFDefn->GetGeomType();
+
+        if( !poDstDS->TestCapability( ODsCCreateLayer ) )
+        {
+            fprintf( stderr, 
+              "Layer %s not found, and CreateLayer not supported by driver.", 
+                     pszNewLayerName );
+            return FALSE;
+        }
+
+        CPLErrorReset();
+
+        poDstLayer = poDstDS->CreateLayer( pszNewLayerName, poOutputSRS,
+                                           (OGRwkbGeometryType) eGType, 
+                                           papszLCO );
+
+        if( poDstLayer == NULL )
+            return FALSE;
+
+        bAppend = FALSE;
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Otherwise we will append to it, if append was requested.        */
+/* -------------------------------------------------------------------- */
+    else if( !bAppend )
+    {
+        fprintf( stderr, "FAILED: Layer %s already exists, and -append not specified.\n"
+                "        Consider using -append, or -overwrite.\n",
+                pszNewLayerName );
+        return FALSE;
+    }
+    else
+    {
+        if( CSLCount(papszLCO) > 0 )
+        {
+            fprintf( stderr, "WARNING: Layer creation options ignored since an existing layer is\n"
+                    "         being appended to.\n" );
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Add fields.  Default to copy all field.                         */
+/*      If only a subset of all fields requested, then output only      */
+/*      the selected fields, and in the order that they were            */
+/*      selected.                                                       */
+/* -------------------------------------------------------------------- */
+    int         iField;
+    int hasMmField=-1;
+
+    if (papszSelFields && !bAppend )
+    {
+        for( iField=0; papszSelFields[iField] != NULL; iField++)
+        {
+            int iSrcField = poFDefn->GetFieldIndex(papszSelFields[iField]);
+	    OGRFieldDefn *tmp=poFDefn->GetFieldDefn(iSrcField);
+	    fprintf(stderr,"NAME: %s\n",tmp->GetNameRef());
+	    fflush(stderr);
+	    if(tmp!=NULL && strncasecmp(tmp->GetNameRef(),"MMID",4)==0)
+	      hasMmField=1;
+            if (iSrcField >= 0)
+                poDstLayer->CreateField( poFDefn->GetFieldDefn(iSrcField) );
+            else
+            {
+                fprintf( stderr, "Field '%s' not found in source layer.\n", 
+                        papszSelFields[iField] );
+                if( !bSkipFailures )
+                    return FALSE;
+            }
+        }
+
+    }
+    else if( !bAppend )
+    {
+      for( iField = 0; iField < poFDefn->GetFieldCount(); iField++ ){
+            poDstLayer->CreateField( poFDefn->GetFieldDefn(iField) );
+	    OGRFieldDefn *tmp=poFDefn->GetFieldDefn(iField);
+	    if(tmp!=NULL && strncasecmp(tmp->GetNameRef(),"MMID",4)==0)
+	      hasMmField=1;
+	    fprintf(stderr,"NAME: %s\n",tmp->GetNameRef());
+      }
+    }
+    /*if(hasMmField<0){
+      OGRFieldDefn oField( "MMID", OFTInteger );
+      poDstLayer->CreateField( &oField );
+      }*/
+
+/* -------------------------------------------------------------------- */
+/*      Transfer features.                                              */
+/* -------------------------------------------------------------------- */
+    OGRFeature  *poFeature;
+    int         nFeaturesInTransaction = 0;
+    int fCount=0;
+    poSrcLayer->ResetReading();
+
+    if( nGroupTransactions )
+        poDstLayer->StartTransaction();
+
+    while( TRUE )
+    {
+        OGRFeature      *poDstFeature = NULL;
+
+        if( nFIDToFetch != OGRNullFID )
+        {
+            // Only fetch feature on first pass.
+            if( nFeaturesInTransaction == 0 )
+                poFeature = poSrcLayer->GetFeature(nFIDToFetch);
+            else
+                poFeature = NULL;
+        }
+        else
+            poFeature = poSrcLayer->GetNextFeature();
+
+        if( poFeature == NULL )
+            break;
+
+	//poFeature->SetField((poFeature->GetFieldCount()-1),fCount);
+
+        if( ++nFeaturesInTransaction == nGroupTransactions )
+        {
+            poDstLayer->CommitTransaction();
+            poDstLayer->StartTransaction();
+            nFeaturesInTransaction = 0;
+        }
+
+        CPLErrorReset();
+        poDstFeature = OGRFeature::CreateFeature( poDstLayer->GetLayerDefn() );
+
+        if( poDstFeature->SetFrom( poFeature, TRUE ) != OGRERR_NONE )
+        {
+            if( nGroupTransactions )
+                poDstLayer->CommitTransaction();
+            
+            CPLError( CE_Failure, CPLE_AppDefined,
+                      "Unable to translate feature %ld from layer %s.\n",
+                      poFeature->GetFID(), poFDefn->GetName() );
+            
+            OGRFeature::DestroyFeature( poFeature );
+            OGRFeature::DestroyFeature( poDstFeature );
+            return FALSE;
+        }
+
+        if( bPreserveFID )
+            poDstFeature->SetFID( poFeature->GetFID() );
+
+	/*if(hasMmField<0){
+	  poDstFeature->SetField((poDstFeature->GetFieldCount()-1),fCount);
+	  fCount++;
+	}*/
+
+#ifndef GDAL_1_5_0
+        if (poDstFeature->GetGeometryRef() != NULL && dfMaxSegmentLength > 0)
+            poDstFeature->GetGeometryRef()->segmentize(dfMaxSegmentLength);
+#endif
+
+        if( poCT && poDstFeature->GetGeometryRef() != NULL )
+        {
+            eErr = poDstFeature->GetGeometryRef()->transform( poCT );
+            if( eErr != OGRERR_NONE )
+            {
+                if( nGroupTransactions )
+                    poDstLayer->CommitTransaction();
+
+                fprintf( stderr, "Failed to reproject feature %d (geometry probably out of source or destination SRS).\n", 
+                        (int) poFeature->GetFID() );
+                if( !bSkipFailures )
+                {
+                    OGRFeature::DestroyFeature( poFeature );
+                    OGRFeature::DestroyFeature( poDstFeature );
+                    return FALSE;
+                }
+            }
+        }
+
+        if( poDstFeature->GetGeometryRef() != NULL && bForceToPolygon )
+        {
+            poDstFeature->SetGeometryDirectly( 
+                OGRGeometryFactory::forceToPolygon(
+                    poDstFeature->StealGeometry() ) );
+        }
+                    
+        if( poDstFeature->GetGeometryRef() != NULL && bForceToMultiPolygon )
+        {
+            poDstFeature->SetGeometryDirectly( 
+                OGRGeometryFactory::forceToMultiPolygon(
+                    poDstFeature->StealGeometry() ) );
+        }
+                    
+        OGRFeature::DestroyFeature( poFeature );
+
+        CPLErrorReset();
+        if( poDstLayer->CreateFeature( poDstFeature ) != OGRERR_NONE 
+            && !bSkipFailures )
+        {
+            if( nGroupTransactions )
+                poDstLayer->RollbackTransaction();
+
+            OGRFeature::DestroyFeature( poDstFeature );
+            return FALSE;
+        }
+
+        OGRFeature::DestroyFeature( poDstFeature );
+    }
+
+    if( nGroupTransactions )
+        poDstLayer->CommitTransaction();
+
+/* -------------------------------------------------------------------- */
+/*      Cleaning                                                        */
+/* -------------------------------------------------------------------- */
+    delete poCT;
+
+    return TRUE;
+}
+
+#ifdef ZOO_SERVICE
+}
+#endif
diff --git a/zoo-project/zoo-services/openoffice/cgi-env/Exporter.py b/zoo-project/zoo-services/openoffice/cgi-env/Exporter.py
new file mode 100644
index 0000000..4e77c1a
--- /dev/null
+++ b/zoo-project/zoo-services/openoffice/cgi-env/Exporter.py
@@ -0,0 +1,99 @@
+# -*- coding: utf-8 -*-
+#
+# Author : Gérald FENOY
+#
+# Copyright 2008-2013 GeoLabs SARL. All rights reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including with
+# out limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+import uno
+import getopt, sys
+
+from unohelper import Base, systemPathToFileUrl, absolutize
+
+from com.sun.star.beans import PropertyValue
+from com.sun.star.script import CannotConvertException
+from com.sun.star.lang import IllegalArgumentException
+from com.sun.star.task import ErrorCodeIOException
+from com.sun.star.io import IOException, XOutputStream
+
+class OutputStream( Base, XOutputStream ):
+    def __init__( self ):
+        self.closed = 0
+    def closeOutput(self):
+        self.closed = 1
+    def writeBytes( self, seq ):
+        sys.stdout.write( seq.value )
+    def flush( self ):
+        pass
+
+def OdtConverter(conf,inputs,outputs):
+	# get the uno component context from the PyUNO runtime  
+	localContext = uno.getComponentContext()
+
+	# create the UnoUrlResolver 
+	# on a single line
+	resolver = 	localContext.ServiceManager.createInstanceWithContext	("com.sun.star.bridge.UnoUrlResolver", localContext )
+
+	# connect to the running office                                 
+	ctx = resolver.resolve( conf["oo"]["server"].replace("::","=")+";urp;StarOffice.ComponentContext" )
+	smgr = ctx.ServiceManager
+
+	# get the central desktop object
+	desktop = smgr.createInstanceWithContext( "com.sun.star.frame.Desktop",ctx)
+
+	# get the file name
+	adressDoc=systemPathToFileUrl(conf["main"]["dataPath"]+"/"+inputs["InputDoc"]["value"])
+
+	propFich=PropertyValue("Hidden", 0, True, 0),
+
+	myDocument=0
+	try:
+	    myDocument = desktop.loadComponentFromURL(adressDoc,"_blank",0,propFich)
+	except CannotConvertException, e:
+	    print >> sys.stderr,  'Impossible de convertir le fichier pour les raisons suivantes : \n'
+	    print >> sys.stderr,  e
+	    sys.exit(0)
+	except IllegalArgumentException, e:
+	    print >> sys.stderr,  'Impossible de convertir le fichier pour les 	raisons suivantes : \n'
+	    print >> sys.stderr,  e
+	    sys.exit(0)
+
+	outputDoc=systemPathToFileUrl(conf["main"]["tmpPath"]+"/"+inputs["OutputDoc"]["value"])
+
+	tmp=inputs["OutputDoc"]["value"].split('.');
+
+	outputFormat={"pdf": "writer_pdf_Export", "html": "HTML (StarWriter)","odt": "writer8","doc": "MS Word 97","rtf": "Rich Text Format"}
+
+	for i in range(len(outputFormat)) :
+	    if tmp[1]==outputFormat.keys()[i] :
+	        filterName=outputFormat[tmp[1]]
+	        prop1Fich = (
+	            PropertyValue( "FilterName" , 0, filterName , 0 ),
+		        PropertyValue( "Overwrite" , 0, True , 0 )
+	        )
+	        break
+
+	myDocument.storeToURL(outputDoc,prop1Fich)
+	myDocument.close(True)
+	ctx.ServiceManager
+	outputs["OutputedDocument"]={"value": inputs["OutputDoc"]["value"],"dataType": "string"}
+	return 3
diff --git a/zoo-project/zoo-services/openoffice/cgi-env/OdtConverter.zcfg b/zoo-project/zoo-services/openoffice/cgi-env/OdtConverter.zcfg
new file mode 100644
index 0000000..98c0175
--- /dev/null
+++ b/zoo-project/zoo-services/openoffice/cgi-env/OdtConverter.zcfg
@@ -0,0 +1,43 @@
+[OdtConverter]
+ Title = Converts Open Documents. 
+ Abstract = Converts open documents.
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceType = Python
+ serviceProvider = Exporter
+ <MetaData>
+   title = My Demo
+ </MetaData>
+ <DataInputs>
+  [InputDoc]
+   Title = The input data source name
+   Abstract = The input data source name
+   minOccurs = 1
+   maxOccurs = 1
+   <LiteralData>
+    DataType = string
+    <Default>
+    </Default>	
+   </LiteralData>
+  [OutputDoc]
+   Title = The output data source name
+   Abstract = The output data source name to use as source.
+   minOccurs = 1
+   maxOccurs = 1
+   <LiteralData>
+    DataType = string
+    <Default>
+    </Default>	
+   </LiteralData>
+ </DataInputs>
+ <DataOutputs>
+  [OutputedDoc]
+   Title = The resulting converted file
+   Abstract = The file name resulting of the convertion
+   <LiteralData>
+    DataType = string
+    <Default>
+    </Default>	
+   </LiteralData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/openoffice/cgi-env/Xml2Pdf.zcfg b/zoo-project/zoo-services/openoffice/cgi-env/Xml2Pdf.zcfg
new file mode 100644
index 0000000..d758281
--- /dev/null
+++ b/zoo-project/zoo-services/openoffice/cgi-env/Xml2Pdf.zcfg
@@ -0,0 +1,39 @@
+[Xml2Pdf]
+ Title = Convert XML and Open Document to PDF format. 
+ Abstract = Converts XML to PDF format.
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceType = Python
+ serviceProvider = oo_service
+ <DataInputs>
+  [doc]
+   Title = The input Open Document Text
+   Abstract = The input Open Document Text including all required Styles
+   minOccurs = 1
+   maxOccurs = 1
+   <LiteralData>
+    dataType = string
+    <Default/>
+   </LiteralData>
+  [xml]
+   Title = The input XML file
+   Abstract = The input XML file to convert.
+   minOccurs = 1
+   maxOccurs = 1
+   <LiteralData>
+    dataType = string
+    <Default/>
+   </LiteralData>
+ </DataInputs>
+ <DataOutputs>
+  [Document]
+   Title = The resulting file
+   Abstract = The file content resulting of the convertion from XML to PDF
+   <ComplexData>
+    <Default>
+     mimeType=application/pdf
+     extension=pdf
+    </Default>	
+   </ComplexData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/openoffice/cgi-env/oo_service.py b/zoo-project/zoo-services/openoffice/cgi-env/oo_service.py
new file mode 100644
index 0000000..95fb748
--- /dev/null
+++ b/zoo-project/zoo-services/openoffice/cgi-env/oo_service.py
@@ -0,0 +1,144 @@
+#
+# Author : Gérald FENOY
+#
+# Copyright 2008-2013 GeoLabs SARL. All rights reserved.
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+
+import uno
+import getopt, sys, os
+
+from unohelper import Base, systemPathToFileUrl, absolutize
+
+from com.sun.star.beans import PropertyValue
+from com.sun.star.script import CannotConvertException
+from com.sun.star.lang import IllegalArgumentException
+from com.sun.star.task import ErrorCodeIOException
+from com.sun.star.io import IOException, XOutputStream
+from com.sun.star.style.BreakType import PAGE_BEFORE, PAGE_AFTER
+from com.sun.star.text.ControlCharacter import PARAGRAPH_BREAK
+
+from xml.dom import minidom 
+import sys 
+
+keep_trace=''
+
+def addToText(cursor,text,level,value):
+    if level==1:
+        cursor.NumberingStyleName = "NONE"
+        cursor.ParaStyleName="Heading 1"
+        text.insertString( cursor, value , 0 )
+        text.insertControlCharacter( cursor, PARAGRAPH_BREAK , 0 )
+        #print  >> sys.stderr,' * Main Title : ' + value
+    else:
+        i=0
+        prefix=''
+        while i < level-1:
+            prefix+=' '
+            i+=1
+        cursor.NumberingStyleName="List "+str(level-1)
+        text.insertString( cursor, prefix+value , 0 )
+        text.insertControlCharacter( cursor, PARAGRAPH_BREAK , 0 )
+        cursor.NumberingStyleName = "NONE"
+	#print  >> sys.stderr,dir(sys.stderr)
+        #print >> sys.stderr,prefix+' * NumberingStyleName '+str(level-1)+' '+value.encode('iso-8859-15')
+
+def printChildren(cursor,text,node,level,keep_trace):
+    if node.nodeType==3:
+        level-=1
+
+    if not(node.nodeValue!=None and len(node.nodeValue.replace(' ',''))!=1 and keep_trace!='' and keep_trace!=None):
+        if keep_trace!='':
+            addToText(cursor,text,level-1,keep_trace)
+        keep_trace=node.nodeName
+
+    if node.hasChildNodes():
+        for i in node.childNodes:
+            printChildren(cursor,text,i,level+1,keep_trace)
+            keep_trace=''
+    else:
+        if node.nodeValue != None and len(node.nodeValue.replace(' ',''))>1:
+            addToText(cursor,text,level-1,keep_trace+' : '+node.nodeValue)
+            keep_trace=''
+        else:
+            if node.nodeValue != None and len(node.nodeValue.replace(' ',''))>1:
+                addToText(cursor,text,level-1,keep_trace+' : '+node.nodeValue)
+                keep_trace=''
+            else:
+                if keep_trace!='#text':
+                    addToText(cursor,text,level-1,keep_trace)
+                    keep_trace=''
+
+    if node.nodeType==1 and node.hasAttributes():
+        i=0
+        while i<node.attributes.length:
+            addToText(cursor,text,level,'(attr) '+node.attributes.keys()[i] + ' : ' + node.attributes[node.attributes.keys()[i]].value)
+            i+=1
+
+        
+
+def Xml2Pdf(conf,input,output):
+    localContext = uno.getComponentContext()
+    resolver = localContext.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", localContext )
+    ctx = resolver.resolve( "uno:socket,host=127.0.0.1,port=3662;urp;StarOffice.ComponentContext" )
+    smgr = ctx.ServiceManager
+    desktop = smgr.createInstanceWithContext( "com.sun.star.frame.Desktop",ctx)
+    adressDoc=systemPathToFileUrl(input["doc"]["value"])
+    propFich=PropertyValue("Hidden", 0, True, 0),
+    try:
+        myDocument = desktop.loadComponentFromURL(adressDoc,"_blank",0,propFich)
+	#Prefer to create a new document without any style ?
+        #myDocument = desktop.loadComponentFromURL("private:factory/writer","_blank",0,propFich)
+    except:
+        conf["lenv"]["message"]='Unable to load input document'
+	return 4
+    text = myDocument.Text
+    cursor = text.createTextCursor()
+    cursor.gotoStart(0)
+    cursor.gotoEnd(1)
+    xmldoc = minidom.parseString(input['xml']['value'])
+
+    if xmldoc.hasChildNodes():
+        for i in xmldoc.childNodes:
+            if i.nodeType==1:
+                cursor.ParaStyleName="Title"
+                text.insertString( cursor, i.nodeName , 0 )
+                text.insertControlCharacter( cursor, PARAGRAPH_BREAK , 0 )
+                #print >> sys.stderr,' * 1st level' + i.nodeName
+                if i.hasChildNodes():
+                    for j in i.childNodes:
+                        printChildren(cursor,text,j,2,'')
+
+    tmp=myDocument.StyleFamilies.getByName("NumberingStyles")
+
+    tmp1=tmp.getByName("Puce 1")
+
+    prop1Fich = ( PropertyValue( "FilterName" , 0, "writer_pdf_Export", 0 ),PropertyValue( "Overwrite" , 0, True , 0 ) )
+    outputDoc=systemPathToFileUrl("/tmp/output.pdf")
+    myDocument.storeToURL(outputDoc,prop1Fich)
+
+    myDocument.close(True)
+    ctx.ServiceManager
+    output["Document"]["value"]= open('/tmp/output.pdf', 'r').read()
+    print >> sys.stderr,len(output["Document"]["value"])
+    return 3
+
+#To run test from command line uncomment the following line:
+#xml2pdf({},{"file":{"value":"/tmp/demo.xml"},"doc":{"value":"/tmp/demo.odt"}},{})
diff --git a/zoo-project/zoo-services/qrencode/Makefile b/zoo-project/zoo-services/qrencode/Makefile
new file mode 100644
index 0000000..710c69e
--- /dev/null
+++ b/zoo-project/zoo-services/qrencode/Makefile
@@ -0,0 +1,10 @@
+ZRPATH=../..
+include ${ZRPATH}/zoo-kernel/ZOOMakefile.opts
+CFLAGS=${ZOO_CFLAGS} ${XML2CFLAGS} ${GDAL_CFLAGS} ${PYTHONCFLAGS} -DLINUX_FREE_ISSUE #-DDEBUG
+CC=gcc
+
+cgi-env/qrencode.zo: qrenc-service.c
+	g++ -DZOO_SERVICE_PROVIDER ${CFLAGS} -shared -fpic -o cgi-env/qrencode.zo ./qrenc-service.c -lqrencode ${GDAL_LIBS} -lpng ${MACOS_LD_FLAGS}
+
+clean:
+	rm -f cgi-env/*.zo
diff --git a/zoo-project/zoo-services/qrencode/cgi-env/QREncode.zcfg b/zoo-project/zoo-services/qrencode/cgi-env/QREncode.zcfg
new file mode 100644
index 0000000..85ac06f
--- /dev/null
+++ b/zoo-project/zoo-services/qrencode/cgi-env/QREncode.zcfg
@@ -0,0 +1,69 @@
+[QREncode]
+ Title = Encode a string into a QR Code
+ Abstract = Multiply two values and store the result in Result.
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = qrencode.zo
+ serviceType = C
+ <DataInputs>
+  [Text]
+   Title = the input string
+   Abstract = The string to encode using QREncode.
+   minOccurs = 1
+   maxOccurs = 1
+   <LiteralData>
+    dataType = string
+    <Default>
+     uom = meters
+    </Default>
+    <Supported>
+     uom = feet
+    </Supported>
+   </LiteralData>
+  [fgcolor]
+   Title = the input string
+   Abstract = The string (RRGGBBAA) for for foreground color.
+   minOccurs = 0
+   maxOccurs = 1
+   <LiteralData>
+    dataType = string
+    <Default>
+     value=000000
+    </Default>
+   </LiteralData>
+  [bgcolor]
+   Title = the input string
+   Abstract = The string (RRGGBBAA) for for background color.
+   minOccurs = 0
+   maxOccurs = 1
+   <LiteralData>
+    dataType = string
+    <Default>
+     value=ffffff
+    </Default>
+   </LiteralData>
+  [size]
+   Title = the image size
+   Abstract = The generated image size.
+   minOccurs = 0
+   maxOccurs = 1
+   <LiteralData>
+    dataType = integer
+    <Default>
+     value=3
+    </Default>
+   </LiteralData>
+ </DataInputs>
+ <DataOutputs>
+  [QR]
+   Title = the QR Code image 
+   Abstract = The QRCode corresponding to the string encoded.
+   minOccurs = 1
+   maxOccurs = 1
+   <ComplexData>
+       <Default>
+            mimeType = image/png
+       </Default>
+   </ComplexData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/qrencode/makefile.vc b/zoo-project/zoo-services/qrencode/makefile.vc
new file mode 100644
index 0000000..d385539
--- /dev/null
+++ b/zoo-project/zoo-services/qrencode/makefile.vc
@@ -0,0 +1,23 @@
+TROOT= $(ZOOK_DIR)
+!INCLUDE $(ZOOK_DIR)/nmake.opt
+
+FILES=$(ZOOK_DIR)/service_internal.obj $(ZOOK_DIR)/ulinet.obj 
+!IFDEF JS_DIR
+FILES=$(FILES) $(ZOOK_DIR)$(JS_FILE)
+!ENDIF
+!IFDEF JDK_DIR
+FILES=$(FILES) $(ZOOK_DIR)$(JAVA_FILE)
+!ENDIF
+!IFDEF PY_DIR
+FILES=$(FILES) $(ZOOK_DIR)$(PY_FILE)
+!ENDIF
+!IFDEF MS_DIR
+FILES=$(FILES) $(ZOOK_DIR)$(MS_FILE)
+!ENDIF
+
+qrencode.zo: qrenc-service.c
+	$(CPP) -Ivc8\qrcode /DOGR_ENABLED /D_CRT_NONSTDC_NO_DEPRECATE -DWIN32 -DZOO_SERVICE_PROVIDER -I$(GDAL_DIR)/frmts/ -I$(GDAL_DIR)/alg/ $(CFLAGS) -I$(PNG_DIR) /c qrenc-service.c
+	link /dll /out:cgi-env/qrencode.zo  $(FILES) ./qrenc-service.obj $(LDFLAGS) $(PNG_DIR)/libpng15.lib $(QRENCODE_DIR)vc8/.build/Release-Lib/qrcodelib.lib /FORCE:MULTIPLE /NODEFAULTLIB:library
+
+clean:
+	erase qrencode.zo
diff --git a/zoo-project/zoo-services/qrencode/qrenc-service.c b/zoo-project/zoo-services/qrencode/qrenc-service.c
new file mode 100644
index 0000000..f98f40c
--- /dev/null
+++ b/zoo-project/zoo-services/qrencode/qrenc-service.c
@@ -0,0 +1,1215 @@
+/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: t -*-*/
+
+/**
+ * qrencode - QR Code encoder
+ *
+ * QR Code encoding tool
+ * Copyright (C) 2006-2012 Kentaro Fukuchi <kentaro at fukuchi.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <png.h>
+#include <getopt.h>
+
+#ifdef ZOO_SERVICE_PROVIDER
+#define bzero(b,len) (memset((b), '\0', (len)), (void) 0)
+#define bcopy(b1,b2,len) (memmove((b2), (b1), (len)), (void) 0)
+#ifdef WIN32
+#include "windows.h"
+#endif
+#include "service.h"
+#include <sys/stat.h>
+#include <unistd.h>
+#endif
+
+#include "qrencode.h"
+
+#define INCHES_PER_METER (100.0/2.54)
+
+static int casesensitive = 1;
+static int eightbit = 0;
+static int version = 0;
+static int size = 3;
+static int margin = -1;
+static int dpi = 72;
+static int structured = 0;
+static int micro = 0;
+static QRecLevel level = QR_ECLEVEL_L;
+static QRencodeMode hint = QR_MODE_8;
+static unsigned int fg_color[4] = {0, 0, 0, 255};
+static unsigned int bg_color[4] = {255, 255, 255, 255};
+
+enum imageType {
+	PNG_TYPE,
+	EPS_TYPE,
+	SVG_TYPE,
+	ANSI_TYPE,
+	ANSI256_TYPE,
+	ASCII_TYPE,
+	ASCIIi_TYPE,
+	UTF8_TYPE,
+	ANSIUTF8_TYPE
+};
+
+static enum imageType image_type = PNG_TYPE;
+
+static const struct option options[] = {
+	{"help"         , no_argument      , NULL, 'h'},
+	{"output"       , required_argument, NULL, 'o'},
+	{"level"        , required_argument, NULL, 'l'},
+	{"size"         , required_argument, NULL, 's'},
+	{"symversion"   , required_argument, NULL, 'v'},
+	{"margin"       , required_argument, NULL, 'm'},
+	{"dpi"          , required_argument, NULL, 'd'},
+	{"type"         , required_argument, NULL, 't'},
+	{"structured"   , no_argument      , NULL, 'S'},
+	{"kanji"        , no_argument      , NULL, 'k'},
+	{"casesensitive", no_argument      , NULL, 'c'},
+	{"ignorecase"   , no_argument      , NULL, 'i'},
+	{"8bit"         , no_argument      , NULL, '8'},
+	{"micro"        , no_argument      , NULL, 'M'},
+	{"foreground"	, required_argument, NULL, 'f'},
+	{"background"	, required_argument, NULL, 'b'},
+	{"version"      , no_argument      , NULL, 'V'},
+	{NULL, 0, NULL, 0}
+};
+
+static char *optstring = "ho:l:s:v:m:d:t:Skci8MV";
+
+static void usage(int help, int longopt)
+{
+	fprintf(stderr,
+"qrencode version %s\n"
+"Copyright (C) 2006-2012 Kentaro Fukuchi\n", QRcode_APIVersionString());
+	if(help) {
+		if(longopt) {
+			fprintf(stderr,
+"Usage: qrencode [OPTION]... [STRING]\n"
+"Encode input data in a QR Code and save as a PNG or EPS image.\n\n"
+"  -h, --help   display the help message. -h displays only the help of short\n"
+"               options.\n\n"
+"  -o FILENAME, --output=FILENAME\n"
+"               write image to FILENAME. If '-' is specified, the result\n"
+"               will be output to standard output. If -S is given, structured\n"
+"               symbols are written to FILENAME-01.png, FILENAME-02.png, ...\n"
+"               (suffix is removed from FILENAME, if specified)\n"
+"  -s NUMBER, --size=NUMBER\n"
+"               specify module size in dots (pixels). (default=3)\n\n"
+"  -l {LMQH}, --level={LMQH}\n"
+"               specify error correction level from L (lowest) to H (highest).\n"
+"               (default=L)\n\n"
+"  -v NUMBER, --symversion=NUMBER\n"
+"               specify the version of the symbol. (default=auto)\n\n"
+"  -m NUMBER, --margin=NUMBER\n"
+"               specify the width of the margins. (default=4 (2 for Micro)))\n\n"
+"  -d NUMBER, --dpi=NUMBER\n"
+"               specify the DPI of the generated PNG. (default=72)\n\n"
+"  -t {PNG,EPS,SVG,ANSI,ANSI256,ASCII,ASCIIi,UTF8,ANSIUTF8}, --type={PNG,EPS,\n"
+"               SVG,ANSI,ANSI256,ASCII,ASCIIi,UTF8,ANSIUTF8}\n"
+"               specify the type of the generated image. (default=PNG)\n\n"
+"  -S, --structured\n"
+"               make structured symbols. Version must be specified.\n\n"
+"  -k, --kanji  assume that the input text contains kanji (shift-jis).\n\n"
+"  -c, --casesensitive\n"
+"               encode lower-case alphabet characters in 8-bit mode. (default)\n\n"
+"  -i, --ignorecase\n"
+"               ignore case distinctions and use only upper-case characters.\n\n"
+"  -8, --8bit   encode entire data in 8-bit mode. -k, -c and -i will be ignored.\n\n"
+"  -M, --micro  encode in a Micro QR Code. (experimental)\n\n"
+"  --foreground=RRGGBB[AA]\n"
+"  --background=RRGGBB[AA]\n"
+"               specify foreground/background color in hexadecimal notation.\n"
+"               6-digit (RGB) or 8-digit (RGBA) form are supported.\n"
+"               Color output support available only in PNG and SVG.\n"
+"  -V, --version\n"
+"               display the version number and copyrights of the qrencode.\n\n"
+"  [STRING]     input data. If it is not specified, data will be taken from\n"
+"               standard input.\n"
+			);
+		} else {
+			fprintf(stderr,
+"Usage: qrencode [OPTION]... [STRING]\n"
+"Encode input data in a QR Code and save as a PNG or EPS image.\n\n"
+"  -h           display this message.\n"
+"  --help       display the usage of long options.\n"
+"  -o FILENAME  write image to FILENAME. If '-' is specified, the result\n"
+"               will be output to standard output. If -S is given, structured\n"
+"               symbols are written to FILENAME-01.png, FILENAME-02.png, ...\n"
+"               (suffix is removed from FILENAME, if specified)\n"
+"  -s NUMBER    specify module size in dots (pixels). (default=3)\n"
+"  -l {LMQH}    specify error correction level from L (lowest) to H (highest).\n"
+"               (default=L)\n"
+"  -v NUMBER    specify the version of the symbol. (default=auto)\n"
+"  -m NUMBER    specify the width of the margins. (default=4 (2 for Micro))\n"
+"  -d NUMBER    specify the DPI of the generated PNG. (default=72)\n"
+"  -t {PNG,EPS,SVG,ANSI,ANSI256,ASCII,ASCIIi,UTF8,ANSIUTF8}\n"
+"               specify the type of the generated image. (default=PNG)\n"
+"  -S           make structured symbols. Version must be specified.\n"
+"  -k           assume that the input text contains kanji (shift-jis).\n"
+"  -c           encode lower-case alphabet characters in 8-bit mode. (default)\n"
+"  -i           ignore case distinctions and use only upper-case characters.\n"
+"  -8           encode entire data in 8-bit mode. -k, -c and -i will be ignored.\n"
+"  -M           encode in a Micro QR Code.\n"
+"  --foreground=RRGGBB[AA]\n"
+"  --background=RRGGBB[AA]\n"
+"               specify foreground/background color in hexadecimal notation.\n"
+"               6-digit (RGB) or 8-digit (RGBA) form are supported.\n"
+"               Color output support available only in PNG and SVG.\n"
+"  -V           display the version number and copyrights of the qrencode.\n"
+"  [STRING]     input data. If it is not specified, data will be taken from\n"
+"               standard input.\n"
+			);
+		}
+	}
+}
+
+static int color_set(unsigned int color[4], const char *value)
+{
+	int len = strlen(value);
+	int count;
+	if(len == 6) {
+		count = sscanf(value, "%02x%02x%02x%n", &color[0], &color[1], &color[2], &len);
+		if(count < 3 || len != 6) {
+			return -1;
+		}
+		color[3] = 255;
+	} else if(len == 8) {
+		count = sscanf(value, "%02x%02x%02x%02x%n", &color[0], &color[1], &color[2], &color[3], &len);
+		if(count < 4 || len != 8) {
+			return -1;
+		}
+	} else {
+		return -1;
+	}
+	return 0;
+}
+
+#define MAX_DATA_SIZE (7090 * 16) /* from the specification */
+static unsigned char *readStdin(int *length)
+{
+	unsigned char *buffer;
+	int ret;
+
+	buffer = (unsigned char *)malloc(MAX_DATA_SIZE + 1);
+	if(buffer == NULL) {
+		fprintf(stderr, "Memory allocation failed.\n");
+		exit(EXIT_FAILURE);
+	}
+	ret = fread(buffer, 1, MAX_DATA_SIZE, stdin);
+	if(ret == 0) {
+		fprintf(stderr, "No input data.\n");
+		exit(EXIT_FAILURE);
+	}
+	if(feof(stdin) == 0) {
+		fprintf(stderr, "Input data is too large.\n");
+		exit(EXIT_FAILURE);
+	}
+
+	buffer[ret] = '\0';
+	*length = ret;
+
+	return buffer;
+}
+
+static FILE *openFile(const char *outfile)
+{
+	FILE *fp;
+
+	if(outfile == NULL || (outfile[0] == '-' && outfile[1] == '\0')) {
+		fp = stdout;
+	} else {
+		fp = fopen(outfile, "wb");
+		if(fp == NULL) {
+			fprintf(stderr, "Failed to create file: %s\n", outfile);
+			perror(NULL);
+			exit(EXIT_FAILURE);
+		}
+	}
+
+	return fp;
+}
+
+static int writePNG(QRcode *qrcode, const char *outfile)
+{
+	static FILE *fp; // avoid clobbering by setjmp.
+	png_structp png_ptr;
+	png_infop info_ptr;
+	png_colorp palette;
+	png_byte alpha_values[2];
+	unsigned char *row, *p, *q;
+	int x, y, xx, yy, bit;
+	int realwidth;
+
+	realwidth = (qrcode->width + margin * 2) * size;
+	row = (unsigned char *)malloc((realwidth + 7) / 8);
+	if(row == NULL) {
+		fprintf(stderr, "Failed to allocate memory.\n");
+		exit(EXIT_FAILURE);
+	}
+
+	if(outfile[0] == '-' && outfile[1] == '\0') {
+		fp = stdout;
+	} else {
+		fp = fopen(outfile, "wb");
+		if(fp == NULL) {
+			fprintf(stderr, "Failed to create file: %s\n", outfile);
+			perror(NULL);
+			exit(EXIT_FAILURE);
+		}
+	}
+
+	png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+	if(png_ptr == NULL) {
+		fprintf(stderr, "Failed to initialize PNG writer.\n");
+		exit(EXIT_FAILURE);
+	}
+
+	info_ptr = png_create_info_struct(png_ptr);
+	if(info_ptr == NULL) {
+		fprintf(stderr, "Failed to initialize PNG write.\n");
+		exit(EXIT_FAILURE);
+	}
+
+	if(setjmp(png_jmpbuf(png_ptr))) {
+		png_destroy_write_struct(&png_ptr, &info_ptr);
+		fprintf(stderr, "Failed to write PNG image.\n");
+		exit(EXIT_FAILURE);
+	}
+
+	palette = (png_colorp) malloc(sizeof(png_color) * 2);
+	palette[0].red   = fg_color[0];
+	palette[0].green = fg_color[1];
+	palette[0].blue  = fg_color[2];
+	palette[1].red   = bg_color[0];
+	palette[1].green = bg_color[1];
+	palette[1].blue  = bg_color[2];
+	alpha_values[0] = fg_color[3];
+	alpha_values[1] = bg_color[3];
+	png_set_PLTE(png_ptr, info_ptr, palette, 2);
+	png_set_tRNS(png_ptr, info_ptr, alpha_values, 2, NULL);
+
+	png_init_io(png_ptr, fp);
+	png_set_IHDR(png_ptr, info_ptr,
+			realwidth, realwidth,
+			1,
+			PNG_COLOR_TYPE_PALETTE,
+			PNG_INTERLACE_NONE,
+			PNG_COMPRESSION_TYPE_DEFAULT,
+			PNG_FILTER_TYPE_DEFAULT);
+	png_set_pHYs(png_ptr, info_ptr,
+			dpi * INCHES_PER_METER,
+			dpi * INCHES_PER_METER,
+			PNG_RESOLUTION_METER);
+	png_write_info(png_ptr, info_ptr);
+
+	/* top margin */
+	memset(row, 0xff, (realwidth + 7) / 8);
+	for(y=0; y<margin * size; y++) {
+		png_write_row(png_ptr, row);
+	}
+
+	/* data */
+	p = qrcode->data;
+	for(y=0; y<qrcode->width; y++) {
+		bit = 7;
+		memset(row, 0xff, (realwidth + 7) / 8);
+		q = row;
+		q += margin * size / 8;
+		bit = 7 - (margin * size % 8);
+		for(x=0; x<qrcode->width; x++) {
+			for(xx=0; xx<size; xx++) {
+				*q ^= (*p & 1) << bit;
+				bit--;
+				if(bit < 0) {
+					q++;
+					bit = 7;
+				}
+			}
+			p++;
+		}
+		for(yy=0; yy<size; yy++) {
+			png_write_row(png_ptr, row);
+		}
+	}
+	/* bottom margin */
+	memset(row, 0xff, (realwidth + 7) / 8);
+	for(y=0; y<margin * size; y++) {
+		png_write_row(png_ptr, row);
+	}
+
+	png_write_end(png_ptr, info_ptr);
+	png_destroy_write_struct(&png_ptr, &info_ptr);
+
+	fclose(fp);
+	free(row);
+
+	return 0;
+}
+
+static int writeEPS(QRcode *qrcode, const char *outfile)
+{
+	FILE *fp;
+	unsigned char *row, *p;
+	int x, y, yy;
+	int realwidth;
+
+	fp = openFile(outfile);
+   
+	realwidth = (qrcode->width + margin * 2) * size;
+	/* EPS file header */
+	fprintf(fp, "%%!PS-Adobe-2.0 EPSF-1.2\n"
+				"%%%%BoundingBox: 0 0 %d %d\n"
+				"%%%%Pages: 1 1\n"
+				"%%%%EndComments\n", realwidth, realwidth);
+	/* draw point */
+	fprintf(fp, "/p { "
+				"moveto "
+				"0 1 rlineto "
+				"1 0 rlineto "
+				"0 -1 rlineto "
+				"fill "
+				"} bind def "
+				"%d %d scale ", size, size);
+	
+	/* data */
+	p = qrcode->data;
+	for(y=0; y<qrcode->width; y++) {
+		row = (p+(y*qrcode->width));
+		yy = (margin + qrcode->width - y - 1);
+		
+		for(x=0; x<qrcode->width; x++) {
+			if(*(row+x)&0x1) {
+				fprintf(fp, "%d %d p ", margin + x,  yy);
+			}
+		}
+	}
+
+	fprintf(fp, "\n%%%%EOF\n");
+	fclose(fp);
+
+	return 0;
+}
+
+static void writeSVG_writeRect(FILE *fp, int x, int y, int width, char* col, float opacity)
+{
+	if(fg_color[3] != 255) {
+		fprintf(fp, "\t\t\t<rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"1\" "\
+				"fill=\"#%s\" fill-opacity=\"%f\" />\n", 
+				x, y, width, col, opacity );
+	} else {
+		fprintf(fp, "\t\t\t<rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"1\" "\
+				"fill=\"#%s\" />\n", 
+				x, y, width, col );
+	}
+}
+
+static int writeSVG( QRcode *qrcode, const char *outfile )
+{
+	FILE *fp;
+	unsigned char *row, *p;
+	int x, y, x0, pen;
+	int symwidth, realwidth;
+	float scale;
+	char fg[7], bg[7];
+	float fg_opacity;
+	float bg_opacity;
+
+	fp = openFile(outfile);
+
+	scale = dpi * INCHES_PER_METER / 100.0;
+
+	symwidth = qrcode->width + margin * 2;
+	realwidth = symwidth * size;
+
+	snprintf(fg, 7, "%02x%02x%02x", fg_color[0], fg_color[1],  fg_color[2]);
+	snprintf(bg, 7, "%02x%02x%02x", bg_color[0], bg_color[1],  bg_color[2]);
+	fg_opacity = (float)fg_color[3] / 255;
+	bg_opacity = (float)bg_color[3] / 255;
+
+	/* XML declaration */
+	fputs( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n", fp );
+
+	/* DTD 
+	   No document type specified because "while a DTD is provided in [the SVG] 
+	   specification, the use of DTDs for validating XML documents is known to be 
+	   problematic. In particular, DTDs do not handle namespaces gracefully. It 
+	   is *not* recommended that a DOCTYPE declaration be included in SVG 
+	   documents." 
+	   http://www.w3.org/TR/2003/REC-SVG11-20030114/intro.html#Namespace
+	*/
+
+	/* Vanity remark */
+	fprintf( fp, "<!-- Created with qrencode %s (http://fukuchi.org/works/qrencode/index.html.en) -->\n", 
+			QRcode_APIVersionString() );
+
+	/* SVG code start */
+	fprintf( fp, "<svg width=\"%0.2fcm\" height=\"%0.2fcm\" viewBox=\"0 0 %d %d\""\
+			" preserveAspectRatio=\"none\" version=\"1.1\""\
+			" xmlns=\"http://www.w3.org/2000/svg\">\n", 
+			realwidth / scale, realwidth / scale, symwidth, symwidth
+		   );
+
+	/* Make named group */
+	fputs( "\t<g id=\"QRcode\">\n", fp );
+
+	/* Make solid background */
+	if(bg_color[3] != 255) {
+		fprintf(fp, "\t\t<rect x=\"0\" y=\"0\" width=\"%d\" height=\"%d\" fill=\"#%s\" fill-opacity=\"%f\" />\n", symwidth, symwidth, bg, bg_opacity);
+	} else {
+		fprintf(fp, "\t\t<rect x=\"0\" y=\"0\" width=\"%d\" height=\"%d\" fill=\"#%s\" />\n", symwidth, symwidth, bg);
+	}
+
+	/* Create new viewbox for QR data */
+	fputs( "\t\t<g id=\"Pattern\">\n", fp);
+
+	/* Write data */
+	p = qrcode->data;
+	for(y=0; y<qrcode->width; y++) {
+		row = (p+(y*qrcode->width));
+
+		/* simple RLE */
+		pen = 0;
+		x0  = 0;
+		for(x=0; x<qrcode->width; x++) {
+			if( !pen ) {
+				pen = *(row+x)&0x1;
+				x0 = x;
+			} else {
+				if(!(*(row+x)&0x1)) {
+					writeSVG_writeRect(fp, x0 + margin, y + margin, x-x0, fg, fg_opacity);
+					pen = 0;
+				}
+			}
+		}
+		if( pen ) {
+			writeSVG_writeRect(fp, x0 + margin, y + margin, qrcode->width - x0, fg, fg_opacity);
+		}
+	}
+
+	/* Close QR data viewbox */
+	fputs( "\t\t</g>\n", fp );
+
+	/* Close group */
+	fputs( "\t</g>\n", fp );
+
+	/* Close SVG code */
+	fputs( "</svg>\n", fp );
+	fclose( fp );
+
+	return 0;
+}
+
+static void writeANSI_margin(FILE* fp, int realwidth,
+                             char* buffer, int buffer_s,
+                             char* white, int white_s )
+{
+	int y;
+
+	strncpy(buffer, white, white_s);
+	memset(buffer + white_s, ' ', realwidth * 2);
+	strcpy(buffer + white_s + realwidth * 2, "\033[0m\n"); // reset to default colors
+	for(y=0; y<margin; y++ ){
+		fputs(buffer, fp);
+	}
+}
+
+static int writeANSI(QRcode *qrcode, const char *outfile)
+{
+	FILE *fp;
+	unsigned char *row, *p;
+	int x, y;
+	int realwidth;
+	int last;
+
+	char *white, *black, *buffer;
+	int white_s, black_s, buffer_s;
+
+	if( image_type == ANSI256_TYPE ){
+		/* codes for 256 color compatible terminals */
+		white = "\033[48;5;231m";
+		white_s = 11;
+		black = "\033[48;5;16m";
+		black_s = 10;
+	} else {
+		white = "\033[47m";
+		white_s = 5;
+		black = "\033[40m";
+		black_s = 5;
+	}
+
+	size = 1;
+
+	fp = openFile(outfile);
+
+	realwidth = (qrcode->width + margin * 2) * size;
+	buffer_s = ( realwidth * white_s ) * 2;
+	buffer = (char *)malloc( buffer_s );
+	if(buffer == NULL) {
+		fprintf(stderr, "Failed to allocate memory.\n");
+		exit(EXIT_FAILURE);
+	}
+
+	/* top margin */
+	writeANSI_margin(fp, realwidth, buffer, buffer_s, white, white_s);
+
+	/* data */
+	p = qrcode->data;
+	for(y=0; y<qrcode->width; y++) {
+		row = (p+(y*qrcode->width));
+
+		bzero( buffer, buffer_s );
+		strncpy( buffer, white, white_s );
+		for(x=0; x<margin; x++ ){
+			strncat( buffer, "  ", 2 );
+		}
+		last = 0;
+
+		for(x=0; x<qrcode->width; x++) {
+			if(*(row+x)&0x1) {
+				if( last != 1 ){
+					strncat( buffer, black, black_s );
+					last = 1;
+				}
+			} else {
+				if( last != 0 ){
+					strncat( buffer, white, white_s );
+					last = 0;
+				}
+			}
+			strncat( buffer, "  ", 2 );
+		}
+
+		if( last != 0 ){
+			strncat( buffer, white, white_s );
+		}
+		for(x=0; x<margin; x++ ){
+			strncat( buffer, "  ", 2 );
+		}
+		strncat( buffer, "\033[0m\n", 5 );
+		fputs( buffer, fp );
+	}
+
+	/* bottom margin */
+	writeANSI_margin(fp, realwidth, buffer, buffer_s, white, white_s);
+
+	fclose(fp);
+	free(buffer);
+
+	return 0;
+}
+
+static void writeUTF8_margin(FILE* fp, int realwidth,
+			     const char* white, const char *reset,
+			     int use_ansi)
+{
+	int x, y;
+
+	for (y = 0; y < margin/2; y++) {
+		fputs(white, fp);
+		for (x = 0; x < realwidth; x++)
+			fputs("\342\226\210", fp);
+		fputs(reset, fp);
+		fputc('\n', fp);
+	}
+}
+
+static int writeUTF8(QRcode *qrcode, const char *outfile, int use_ansi)
+{
+	FILE *fp;
+	int x, y;
+	int realwidth;
+	unsigned char *p;
+	const char *white, *reset;
+
+	if (use_ansi){
+		white = "\033[40;37;1m";
+		reset = "\033[0m";
+	} else {
+		white = "";
+		reset = "";
+	}
+
+	fp = openFile(outfile);
+
+	realwidth = (qrcode->width + margin * 2);
+
+	/* top margin */
+	writeUTF8_margin(fp, realwidth, white, reset, use_ansi);
+
+	/* data */
+	p = qrcode->data;
+	for(y = 0; y < qrcode->width; y += 2) {
+		unsigned char *row1, *row2;
+		row1 = p + y*qrcode->width;
+		row2 = p + y*qrcode->width + qrcode->width;
+
+		fputs(white, fp);
+
+		for (x = 0; x < margin; x++)
+			fputs("\342\226\210", fp);
+
+		for (x = 0; x < qrcode->width; x++) {
+			if ((*(row1 + x) & 1) && (*(row2 + x) & 1))
+				fputc(' ', fp);
+			else if (*(row1 + x) & 1)
+				fputs("\342\226\204", fp);
+			else if (*(row2 + x) & 1)
+				fputs("\342\226\200", fp);
+			else
+				fputs("\342\226\210", fp);
+		}
+
+		for (x = 0; x < margin; x++)
+			fputs("\342\226\210", fp);
+
+		fputs(reset, fp);
+		fputc('\n', fp);
+	}
+
+	/* bottom margin */
+	writeUTF8_margin(fp, realwidth, white, reset, use_ansi);
+
+	fclose(fp);
+
+	return 0;
+}
+
+static void writeASCII_margin(FILE* fp, int realwidth, char* buffer, int buffer_s, int invert)
+{
+	int y, h;
+
+	h = margin;
+
+	memset(buffer, (invert?'#':' '), realwidth);
+	buffer[realwidth] = '\n';
+	buffer[realwidth + 1] = '\0';
+	for(y=0; y<h; y++ ){
+		fputs(buffer, fp);
+	}
+}
+
+static int writeASCII(QRcode *qrcode, const char *outfile, int invert)
+{
+	FILE *fp;
+	unsigned char *row;
+	int x, y;
+	int realwidth;
+	char *buffer, *p;
+	int buffer_s;
+	char black = '#';
+	char white = ' ';
+
+	if(invert) {
+		black = ' ';
+		white = '#';
+	}
+
+	size = 1;
+
+	fp = openFile(outfile);
+
+	realwidth = (qrcode->width + margin * 2) * 2;
+	buffer_s = realwidth + 1;
+	buffer = (char *)malloc( buffer_s );
+	if(buffer == NULL) {
+		fprintf(stderr, "Failed to allocate memory.\n");
+		exit(EXIT_FAILURE);
+	}
+
+	/* top margin */
+	writeASCII_margin(fp, realwidth, buffer, buffer_s, invert);
+
+	/* data */
+	for(y=0; y<qrcode->width; y++) {
+		row = qrcode->data+(y*qrcode->width);
+		p = buffer;
+
+		memset(p, white, margin * 2);
+		p += margin * 2;
+
+		for(x=0; x<qrcode->width; x++) {
+			if(row[x]&0x1) {
+				*p++ = black;
+				*p++ = black;
+			} else {
+				*p++ = white;
+				*p++ = white;
+			}
+		}
+
+		memset(p, white, margin * 2);
+		p += margin * 2;
+		*p++ = '\n';
+		*p++ = '\0';
+		fputs( buffer, fp );
+	}
+
+	/* bottom margin */
+	writeASCII_margin(fp, realwidth, buffer, buffer_s, invert);
+
+	fclose(fp);
+	free(buffer);
+
+	return 0;
+}
+
+static QRcode *encode(const unsigned char *intext, int length)
+{
+	QRcode *code;
+
+	if(micro) {
+		if(eightbit) {
+			code = QRcode_encodeDataMQR(length, intext, version, level);
+		} else {
+			code = QRcode_encodeStringMQR((char *)intext, version, level, hint, casesensitive);
+		}
+	} else {
+		if(eightbit) {
+			code = QRcode_encodeData(length, intext, version, level);
+		} else {
+			code = QRcode_encodeString((char *)intext, version, level, hint, casesensitive);
+		}
+	}
+
+	return code;
+}
+
+static void qrencode(const unsigned char *intext, int length, const char *outfile)
+{
+	QRcode *qrcode;
+	
+	qrcode = encode(intext, length);
+	if(qrcode == NULL) {
+		perror("Failed to encode the input data");
+		exit(EXIT_FAILURE);
+	}
+	switch(image_type) {
+		case PNG_TYPE:
+			writePNG(qrcode, outfile);
+			break;
+		case EPS_TYPE:
+			writeEPS(qrcode, outfile);
+			break;
+		case SVG_TYPE:
+			writeSVG(qrcode, outfile);
+			break;
+		case ANSI_TYPE:
+		case ANSI256_TYPE:
+			writeANSI(qrcode, outfile);
+			break;
+		case ASCIIi_TYPE:
+			writeASCII(qrcode, outfile,  1);
+			break;
+		case ASCII_TYPE:
+			writeASCII(qrcode, outfile,  0);
+			break;
+		case UTF8_TYPE:
+			writeUTF8(qrcode, outfile, 0);
+			break;
+		case ANSIUTF8_TYPE:
+			writeUTF8(qrcode, outfile, 1);
+			break;
+		default:
+			fprintf(stderr, "Unknown image type.\n");
+			exit(EXIT_FAILURE);
+	}
+	QRcode_free(qrcode);
+}
+
+static QRcode_List *encodeStructured(const unsigned char *intext, int length)
+{
+	QRcode_List *list;
+
+	if(eightbit) {
+		list = QRcode_encodeDataStructured(length, intext, version, level);
+	} else {
+		list = QRcode_encodeStringStructured((char *)intext, version, level, hint, casesensitive);
+	}
+
+	return list;
+}
+
+static void qrencodeStructured(const unsigned char *intext, int length, const char *outfile)
+{
+	QRcode_List *qrlist, *p;
+	char filename[FILENAME_MAX];
+	char *base, *q, *suffix = NULL;
+	const char *type_suffix;
+	int i = 1;
+	size_t suffix_size;
+
+	switch(image_type) {
+		case PNG_TYPE:
+			type_suffix = ".png";
+			break;
+		case EPS_TYPE:
+			type_suffix = ".eps";
+			break;
+		case SVG_TYPE:
+			type_suffix = ".svg";
+			break;
+		case ANSI_TYPE:
+		case ANSI256_TYPE:
+		case ASCII_TYPE:
+		case UTF8_TYPE:
+		case ANSIUTF8_TYPE:
+			type_suffix = ".txt";
+			break;
+		default:
+			fprintf(stderr, "Unknown image type.\n");
+			exit(EXIT_FAILURE);
+	}
+
+	if(outfile == NULL) {
+		fprintf(stderr, "An output filename must be specified to store the structured images.\n");
+		exit(EXIT_FAILURE);
+	}
+	base = strdup(outfile);
+	if(base == NULL) {
+		fprintf(stderr, "Failed to allocate memory.\n");
+		exit(EXIT_FAILURE);
+	}
+	suffix_size = strlen(type_suffix);
+	if(strlen(base) > suffix_size) {
+		q = base + strlen(base) - suffix_size;
+		if(strcasecmp(type_suffix, q) == 0) {
+			suffix = strdup(q);
+			*q = '\0';
+		}
+	}
+	
+	qrlist = encodeStructured(intext, length);
+	if(qrlist == NULL) {
+		perror("Failed to encode the input data");
+		exit(EXIT_FAILURE);
+	}
+
+	for(p = qrlist; p != NULL; p = p->next) {
+		if(p->code == NULL) {
+			fprintf(stderr, "Failed to encode the input data.\n");
+			exit(EXIT_FAILURE);
+		}
+		if(suffix) {
+			snprintf(filename, FILENAME_MAX, "%s-%02d%s", base, i, suffix);
+		} else {
+			snprintf(filename, FILENAME_MAX, "%s-%02d", base, i);
+		}
+		switch(image_type) {
+			case PNG_TYPE: 
+				writePNG(p->code, filename);
+				break;
+			case EPS_TYPE: 
+				writeEPS(p->code, filename);
+				break;
+			case SVG_TYPE: 
+				writeSVG(p->code, filename);
+				break;
+			case ANSI_TYPE:
+			case ANSI256_TYPE:
+				writeANSI(p->code, filename);
+				break;
+			case ASCIIi_TYPE:
+				writeASCII(p->code, filename, 1);
+				break;
+			case ASCII_TYPE:
+				writeASCII(p->code, filename, 0);
+				break;
+			case UTF8_TYPE:
+				writeUTF8(p->code, filename, 0);
+				break;
+			case ANSIUTF8_TYPE:
+				writeUTF8(p->code, filename, 0);
+				break;
+
+			default:
+				fprintf(stderr, "Unknown image type.\n");
+				exit(EXIT_FAILURE);
+		}
+		i++;
+	}
+
+	free(base);
+	if(suffix) {
+		free(suffix);
+	}
+
+	QRcode_List_free(qrlist);
+}
+
+#ifndef ZOO_SERVICE_PROVIDER
+int main(int argc, char **argv)
+#else
+	extern "C" {
+#ifdef WIN32
+__declspec(dllexport)
+#endif
+int QREncode(maps*& conf, maps*& inputs, maps*& outputs)
+#endif
+{
+	int opt, lindex = -1;
+	char *outfile = NULL;
+	unsigned char *intext = NULL;
+	int length = 0;
+
+#ifndef ZOO_SERVICE_PROVIDER
+	while((opt = getopt_long(argc, argv, optstring, options, &lindex)) != -1) {
+		switch(opt) {
+			case 'h':
+				if(lindex == 0) {
+					usage(1, 1);
+				} else {
+					usage(1, 0);
+				}
+				exit(EXIT_SUCCESS);
+				break;
+			case 'o':
+				outfile = optarg;
+				break;
+			case 's':
+				size = atoi(optarg);
+				if(size <= 0) {
+					fprintf(stderr, "Invalid size: %d\n", size);
+					exit(EXIT_FAILURE);
+				}
+				break;
+			case 'v':
+				version = atoi(optarg);
+				if(version < 0) {
+					fprintf(stderr, "Invalid version: %d\n", version);
+					exit(EXIT_FAILURE);
+				}
+				break;
+			case 'l':
+				switch(*optarg) {
+					case 'l':
+					case 'L':
+						level = QR_ECLEVEL_L;
+						break;
+					case 'm':
+					case 'M':
+						level = QR_ECLEVEL_M;
+						break;
+					case 'q':
+					case 'Q':
+						level = QR_ECLEVEL_Q;
+						break;
+					case 'h':
+					case 'H':
+						level = QR_ECLEVEL_H;
+						break;
+					default:
+						fprintf(stderr, "Invalid level: %s\n", optarg);
+						exit(EXIT_FAILURE);
+						break;
+				}
+				break;
+			case 'm':
+				margin = atoi(optarg);
+				if(margin < 0) {
+					fprintf(stderr, "Invalid margin: %d\n", margin);
+					exit(EXIT_FAILURE);
+				}
+				break;
+			case 'd':
+				dpi = atoi(optarg);
+				if( dpi < 0 ) {
+					fprintf(stderr, "Invalid DPI: %d\n", dpi);
+					exit(EXIT_FAILURE);
+				}
+				break;
+			case 't':
+				if(strcasecmp(optarg, "png") == 0) {
+					image_type = PNG_TYPE;
+				} else if(strcasecmp(optarg, "eps") == 0) {
+					image_type = EPS_TYPE;
+				} else if(strcasecmp(optarg, "svg") == 0) {
+					image_type = SVG_TYPE;
+				} else if(strcasecmp(optarg, "ansi") == 0) {
+					image_type = ANSI_TYPE;
+				} else if(strcasecmp(optarg, "ansi256") == 0) {
+					image_type = ANSI256_TYPE;
+				} else if(strcasecmp(optarg, "asciii") == 0) {
+					image_type = ASCIIi_TYPE;
+				} else if(strcasecmp(optarg, "ascii") == 0) {
+					image_type = ASCII_TYPE;
+				} else if(strcasecmp(optarg, "utf8") == 0) {
+					image_type = UTF8_TYPE;
+				} else if(strcasecmp(optarg, "ansiutf8") == 0) {
+					image_type = ANSIUTF8_TYPE;
+				} else {
+					fprintf(stderr, "Invalid image type: %s\n", optarg);
+					exit(EXIT_FAILURE);
+				}
+				break;
+			case 'S':
+				structured = 1;
+			case 'k':
+				hint = QR_MODE_KANJI;
+				break;
+			case 'c':
+				casesensitive = 1;
+				break;
+			case 'i':
+				casesensitive = 0;
+				break;
+			case '8':
+				eightbit = 1;
+				break;
+			case 'M':
+				micro = 1;
+				break;
+			case 'f':
+				if(color_set(fg_color, optarg)) {
+					fprintf(stderr, "Invalid foreground color value.\n");
+					exit(EXIT_FAILURE);
+				}
+				break;
+			case 'b':
+				if(color_set(bg_color, optarg)) {
+					fprintf(stderr, "Invalid background color value.\n");
+					exit(EXIT_FAILURE);
+				}
+				break;
+			case 'V':
+				usage(0, 0);
+				exit(EXIT_SUCCESS);
+				break;
+			default:
+				fprintf(stderr, "Try `qrencode --help' for more information.\n");
+				exit(EXIT_FAILURE);
+				break;
+		}
+	}
+
+	if(argc == 1) {
+		usage(1, 0);
+		exit(EXIT_SUCCESS);
+	}
+
+	if(outfile == NULL && image_type == PNG_TYPE) {
+		fprintf(stderr, "No output filename is given.\n");
+		exit(EXIT_FAILURE);
+	}
+
+	if(optind < argc) {
+		intext = (unsigned char *)argv[optind];
+		length = strlen((char *)intext);
+	}
+	if(intext == NULL) {
+		intext = readStdin(&length);
+	}
+#else
+	outfile=(char*)malloc(1024*sizeof(char));
+	map *tmpMap=getMapFromMaps(conf,"main","tmpPath");
+	sprintf(outfile,"%s/qr_%d.png",tmpMap->value,getpid());
+	tmpMap=getMapFromMaps(inputs,"Text","value");
+	intext=(unsigned char*)tmpMap->value;
+	dpi = 92;
+	level = QR_ECLEVEL_H;
+	map* tmp1=getMapFromMaps(inputs,"size","value");
+	if(tmp1!=NULL)
+		size = atoi(tmp1->value);
+	tmp1=getMapFromMaps(inputs,"bgcolor","value");
+	if(tmp1!=NULL && color_set(bg_color, tmp1->value)){
+		setMapInMaps(conf,"lenv","message","Unable to parse bgcolor settings");
+		return SERVICE_FAILED;
+	}
+	tmp1=getMapFromMaps(inputs,"fgcolor","value");
+	if(tmp1!=NULL && color_set(fg_color, tmp1->value)){
+		setMapInMaps(conf,"lenv","message","Unable to parse fgcolor settings");
+		return SERVICE_FAILED;
+	}
+#endif
+	
+	if(micro && version > MQRSPEC_VERSION_MAX) {
+		fprintf(stderr, "Version should be less or equal to %d.\n", MQRSPEC_VERSION_MAX);
+		exit(EXIT_FAILURE);
+	} else if(!micro && version > QRSPEC_VERSION_MAX) {
+		fprintf(stderr, "Version should be less or equal to %d.\n", QRSPEC_VERSION_MAX);
+		exit(EXIT_FAILURE);
+	}
+
+	if(margin < 0) {
+		if(micro) {
+			margin = 2;
+		} else {
+			margin = 4;
+		}
+	}
+
+	if(micro) {
+		if(version == 0) {
+			fprintf(stderr, "Version must be specified to encode a Micro QR Code symbol.\n");
+			exit(EXIT_FAILURE);
+		}
+		if(structured) {
+			fprintf(stderr, "Micro QR Code does not support structured symbols.\n");
+			exit(EXIT_FAILURE);
+		}
+	}
+
+	if(structured) {
+		if(version == 0) {
+			fprintf(stderr, "Version must be specified to encode structured symbols.\n");
+			exit(EXIT_FAILURE);
+		}
+		qrencodeStructured(intext, length, outfile);
+	} else {
+		qrencode(intext, length, outfile);
+	}
+
+#ifdef ZOO_SERVICE_PROVIDER
+	FILE * fichier=fopen(outfile,"rb");
+	fseek(fichier, 0, SEEK_END);
+	long count = ftell(fichier);
+	rewind(fichier);
+	
+	struct stat file_status;
+	stat(outfile, &file_status);
+	if(fichier==NULL){
+		fprintf(stderr,"Failed to open file %s for reading purpose.\n",outfile);
+		setMapInMaps(conf,"lenv","message","Unable to read produced file. Please try again later");
+		return SERVICE_FAILED;
+	}
+
+	maps* tmp=getMaps(outputs,"QR");
+	map* tmpMap1=getMapFromMaps(outputs,"QR","value");
+	if(tmpMap1==NULL){
+		addToMap(outputs->content,"value","null");
+		tmpMap1=getMapFromMaps(outputs,"QR","value");
+	}
+	free(tmpMap1->value);
+	tmpMap1->value=(char*) malloc((count+1)*sizeof(char));  
+	fread(tmpMap1->value,1,count*sizeof(char),fichier);
+	fclose(fichier);
+	unlink(outfile);
+
+	char rsize[100];
+	sprintf(rsize,"%d",count*sizeof(char));
+	addToMap(tmpMap1,"size",rsize);  
+	return SERVICE_SUCCEEDED;
+#endif
+
+	return 0;
+}
+#ifdef ZOO_SERVICE_PROVIDER
+	}
+#endif
diff --git a/zoo-project/zoo-services/utils/registry/Makefile b/zoo-project/zoo-services/utils/registry/Makefile
new file mode 100644
index 0000000..8941249
--- /dev/null
+++ b/zoo-project/zoo-services/utils/registry/Makefile
@@ -0,0 +1,24 @@
+ZRPATH=../../..
+include ${ZRPATH}/zoo-kernel/ZOOMakefile.opts
+CFLAGS=${ZOO_CFLAGS} ${XML2CFLAGS} ${GDAL_CFLAGS} ${PYTHONCFLAGS} -DLINUX_FREE_ISSUE #-DDEBUG
+
+YAML_FILES=""
+ifeq ("${YAML_FILE}","")
+else
+	YAML_FILES="${ZRPATH}/zoo-kernel/${YAML_FILE}"
+endif
+
+MS_FILES=""
+ifeq ("${MS_FILE}","")
+else
+	MS_FILES="${ZRPATH}/zoo-kernel/${MS_FILE}"
+endif
+
+cgi-env/wps_registry.zo: service.c
+	g++ ${CFLAGS} -shared -fpic -o cgi-env/wps_registry.zo ./service.c ${GDAL_LIBS} ${XML2LDFLAGS} ${MACOS_LD_FLAGS} ${ZOO_LDFLAGS} ${MACOS_LD_NET_FLAGS} ${XSLT_LDFLAGS} -lfcgi -lzoo_service ${ZRPATH}/zoo-kernel/server_internal.o ${ZRPATH}/zoo-kernel/lex.cr.o ${ZRPATH}/zoo-kernel/lex.sr.o ${ZRPATH}/zoo-kernel/service_conf.tab.o ${ZRPATH}/zoo-kernel/main_conf_read.tab.o ${ZRPATH}/zoo-kernel/response_print.o ${YAML_FILES} ${MS_FILES} ${MS_LDFLAGS} ${YAML_LDFLAGS}
+
+install:
+	install -d ${CGI_DIR}
+	install cgi-env/* ${CGI_DIR}/
+clean:
+	rm -f cgi-env/wps_registry.zo
diff --git a/zoo-project/zoo-services/utils/registry/cgi-env/GetFromRegistry.zcfg b/zoo-project/zoo-services/utils/registry/cgi-env/GetFromRegistry.zcfg
new file mode 100644
index 0000000..a8b7040
--- /dev/null
+++ b/zoo-project/zoo-services/utils/registry/cgi-env/GetFromRegistry.zcfg
@@ -0,0 +1,36 @@
+[GetFromRegistry]
+ Title = Provide access to the Profile Registry
+ Abstract = Return a GenericProcess, Process or simple Concept based on the profiles registry
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = wps_registry.zo
+ serviceType = C
+ <DataInputs>
+  [id]
+   Title = The registry path
+   Abstract = The profiles registry path
+   minOccurs = 1
+   maxOccurs = 1
+   <LiteralData>
+    DataType = integer
+    <Default>
+    </Default>
+   </LiteralData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = the GenericProcess, Process or Concept
+   Abstract = The resulting GenericProcess, Process or Concept
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://schemas.opengis.net/wps/2.0/wps.xsd
+    </Default>
+    <Supported>
+     mimeType = text/plain
+     encoding = UTF-8
+    </Supported>
+   </ComplexData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/utils/registry/makefile.vc b/zoo-project/zoo-services/utils/registry/makefile.vc
new file mode 100755
index 0000000..a44cf52
--- /dev/null
+++ b/zoo-project/zoo-services/utils/registry/makefile.vc
@@ -0,0 +1,24 @@
+TROOT= $(ZOOK_DIR)
+!INCLUDE $(ZOOK_DIR)/nmake.opt
+
+FILES=$(ZOOK_DIR)/service_internal.obj $(ZOOK_DIR)/ulinet.obj
+!IFDEF JS_DIR
+FILES=$(FILES) $(ZOOK_DIR)$(JS_FILE)
+!ENDIF
+!IFDEF JDK_DIR
+FILES=$(FILES) $(ZOOK_DIR)$(JAVA_FILE)
+!ENDIF
+!IFDEF PY_DIR
+FILES=$(FILES) $(ZOOK_DIR)$(PY_FILE)
+!ENDIF
+!IFDEF MS_DIR
+FILES=$(FILES) $(ZOOK_DIR)$(MS_FILE)
+!ENDIF
+
+cgi-env/wps_registry.zo: service.c
+	$(CPP) /D_CRT_NONSTDC_NO_DEPRECATE -DWIN32 -DZOO_SERVICE $(CFLAGS) /c service.c
+	link /dll /out:cgi-env/wps_registry.zo $(FILES) ./service.obj $(LDFLAGS) /FORCE:MULTIPLE
+
+clean:
+	erase cgi-env\*_registry.*
+	erase *.obj
diff --git a/zoo-project/zoo-services/utils/registry/service.c b/zoo-project/zoo-services/utils/registry/service.c
new file mode 100644
index 0000000..8b787ea
--- /dev/null
+++ b/zoo-project/zoo-services/utils/registry/service.c
@@ -0,0 +1,138 @@
+/**
+ * Author : Gérald FENOY
+ *
+ * Copyright 2015 GeoLabs SARL. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "service.h"
+#include "service_internal.h"
+#include "server_internal.h"
+#include "response_print.h"
+
+extern "C" {
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+
+#include <libxslt/xslt.h>
+#include <libxslt/xsltInternals.h>
+#include <libxslt/transform.h>
+#include <libxslt/xsltutils.h>
+
+#include <dirent.h>
+
+  /**
+   * GetFromRegistry ZOO Service :
+   * This service is used in the ZOO-Project to browse the profiles registry.
+   */
+#ifdef WIN32
+  __declspec(dllexport)
+#endif
+  int GetFromRegistry(maps*& conf,maps*& inputs,maps*& outputs){
+    const char *params[4 + 1];
+    int xmlLoadExtDtdDefaultValue;
+    map* tmpMap=NULL,*tmpMmap=NULL, *tmpTmap=NULL;
+
+    map* reg = getMapFromMaps (conf, "main", "registry");
+    registry* zooRegistry=NULL;
+    if(reg!=NULL){
+      int saved_stdout = dup (fileno (stdout));
+      dup2 (fileno (stderr), fileno (stdout));
+      createRegistry (conf,&zooRegistry,reg->value);
+      dup2 (saved_stdout, fileno (stdout));
+      close(saved_stdout);
+    }else{
+      setMapInMaps(conf,"lenv","message",_ss("No registry defined"));
+      return SERVICE_FAILED;
+    }
+    tmpMap=getMapFromMaps(inputs,"id","value");
+    if(strstr(tmpMap->value,"/")==NULL){
+      setMapInMaps(conf,"lenv","message",_ss("Unable to parse your registry identifier"));
+      return SERVICE_FAILED;
+    }
+    char* tmp=zStrdup(tmpMap->value);
+    char* tmp1=zStrdup(strstr(tmpMap->value,"/")+1);
+    tmp[strlen(tmp)-strlen(tmp1)-1]=0;
+    service* inherited=getServiceFromRegistry(zooRegistry,tmp,tmp1);
+    if(inherited!=NULL){
+      dumpService(inherited);
+      xmlDocPtr doc = xmlNewDoc (BAD_CAST "1.0");
+      xmlNodePtr n = printWPSHeader(doc,conf,"DescribeProcess",
+				    root_nodes[1][1],"2.0.0",1);
+      setMapInMaps(conf,"main","rversion","2.0.0");
+      printDescribeProcessForProcess(zooRegistry,conf,n,inherited);
+      setMapInMaps(conf,"main","rversion","1.0.0");
+
+
+      xmlNodePtr n1 = xmlFirstElementChild(xmlFirstElementChild(n));
+
+
+      xmlDocPtr doc1 = xmlNewDoc (BAD_CAST "1.0");
+      int vid=1;
+      char *tmp=(char*) malloc((86+strlen("DescribeProcess")+1)*sizeof(char));
+      sprintf(tmp,schemas[vid][4],schemas[vid][2],schemas[vid][3],"DescribeProcess");
+      xmlNewProp(n1,BAD_CAST "xsi:schemaLocation",BAD_CAST tmp);
+      free(tmp);
+
+      n1->ns=xmlCopyNamespaceList(n->ns);
+      n1->nsDef=xmlCopyNamespaceList(n->nsDef);
+      
+      xmlDocSetRootElement(doc1, n1);
+      
+      xmlChar *xmlbuff;
+      int buffersize;
+      xmlDocDumpFormatMemoryEnc(doc1, &xmlbuff, &buffersize, "utf-8", 1);
+      setMapInMaps(outputs,"Result","value",(char*)xmlbuff);
+      xmlFree(xmlbuff);
+      xmlFreeDoc(doc);
+      xmlFreeDoc(doc1);
+      return SERVICE_SUCCEEDED;
+    }else{
+      if(strcasecmp(tmp,"concept")==0){
+	char *file_path=(char*)malloc((strlen(reg->value)+strlen(tmpMap->value)+5)*sizeof(char));
+	sprintf(file_path,"%s/%s.txt",reg->value,tmpMap->value);
+	FILE* f=fopen(file_path,"r");
+	if(f!=NULL){
+	  fseek(f, 0, SEEK_END);
+	  long count = ftell(f);
+	  fseek(f, 0, SEEK_SET);
+	  setMapInMaps(outputs,"Result","value","");
+	  map* tmpMap=getMapFromMaps(outputs,"Result","value");
+	  free(tmpMap->value);
+	  tmpMap->value=(char*) malloc((count+1)*sizeof(char));  
+	  fread(tmpMap->value,1,count,f);
+	  tmpMap->value[count]=0;
+	  fclose(f);
+	  setMapInMaps(outputs,"Result","mimeType","text/plain");
+	  return SERVICE_SUCCEEDED;
+	}else{
+	  setMapInMaps(conf,"lenv","message",_ss("Unable to access this item in the registry."));
+	  return SERVICE_FAILED;
+	}
+      }
+      setMapInMaps(conf,"lenv","message",_ss("Unable to access this item in the registry."));
+      return SERVICE_FAILED;
+    }
+    return SERVICE_SUCCEEDED;
+  }
+
+}
diff --git a/zoo-project/zoo-services/utils/status/Makefile b/zoo-project/zoo-services/utils/status/Makefile
new file mode 100644
index 0000000..198dd6d
--- /dev/null
+++ b/zoo-project/zoo-services/utils/status/Makefile
@@ -0,0 +1,12 @@
+ZRPATH=../../..
+include ${ZRPATH}/zoo-kernel/ZOOMakefile.opts
+CFLAGS=${ZOO_CFLAGS} ${XML2CFLAGS} ${GDAL_CFLAGS} ${PYTHONCFLAGS} -DLINUX_FREE_ISSUE #-DDEBUG
+
+cgi-env/wps_status.zo: service.c
+	g++ ${CFLAGS} -shared -fpic -o cgi-env/wps_status.zo ./service.c ${GDAL_LIBS} ${XML2LDFLAGS} ${MACOS_LD_FLAGS} ${ZOO_LDFLAGS} ${MACOS_LD_NET_FLAGS} ${XSLT_LDFLAGS} -lfcgi -lzoo_service
+
+install:
+	install -d ${CGI_DIR}
+	install cgi-env/* ${CGI_DIR}/
+clean:
+	rm -f cgi-env/wps_status.zo
diff --git a/zoo-project/zoo-services/utils/status/cgi-env/GetStatus.zcfg b/zoo-project/zoo-services/utils/status/cgi-env/GetStatus.zcfg
new file mode 100644
index 0000000..57720a2
--- /dev/null
+++ b/zoo-project/zoo-services/utils/status/cgi-env/GetStatus.zcfg
@@ -0,0 +1,43 @@
+[GetStatus]
+ Title = Produce an updated ExecuteResponse document. 
+ Abstract = Create an ExecuteResponse document from a sid (Service ID), it will use the niternal ZOO Kernel mechanisms to access the current status from a running Service and update the percentCompleted from the original backup file used by the ZOO Kernel when running a Service in background. 
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = wps_status.zo
+ serviceType = C
+ <MetaData>
+   title = Demo GetStatus request
+ </MetaData>
+ <DataInputs>
+  [sid]
+   Title = Service ID
+   Abstract = The ZOO Service ID of the ZOO Service we want to get the current status.
+   minOccurs = 1
+   maxOccurs = 1
+   <LiteralData>
+    DataType = integer
+    <Default>
+    </Default>
+   </LiteralData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = ExecuteResponse document
+   Abstract = The resulting ExecuteResponse document.
+   <MetaData>
+    title = Demo XSL use case
+   </MetaData>   
+   <ComplexData>
+    <Default>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://schemas.opengis.net/wps/1.0.0/wpsExecute_response.xsd
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://schemas.opengis.net/wps/1.0.0/wpsExecute_response.xsd
+    </Supported>
+   </ComplexData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/utils/status/cgi-env/demo.zcfg b/zoo-project/zoo-services/utils/status/cgi-env/demo.zcfg
new file mode 100644
index 0000000..3129dfc
--- /dev/null
+++ b/zoo-project/zoo-services/utils/status/cgi-env/demo.zcfg
@@ -0,0 +1,32 @@
+[demo]
+ Title = Demo long process. 
+ Abstract = This service doesn't do anything except taking its time to return an error message, it demonstrates how to use the update_status function of the Python ZOO-API from your services code.
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = service
+ serviceType = Python
+ <DataInputs>
+  [sid]
+   Title = Service ID
+   Abstract = A ZOO Service ID (unused).
+   minOccurs = 0
+   maxOccurs = 1
+   <LiteralData>
+    dataType = integer
+    <Default />
+   </LiteralData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = ExecuteResponse document
+   Abstract = The resulting ExecuteResponse document.
+   <MetaData>
+    title = Demo XSL use case
+   </MetaData>   
+   <LiteralData>
+    dataType = string
+    <Default>
+    </Default>
+   </LiteralData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/utils/status/cgi-env/longProcess.zcfg b/zoo-project/zoo-services/utils/status/cgi-env/longProcess.zcfg
new file mode 100644
index 0000000..131b7a0
--- /dev/null
+++ b/zoo-project/zoo-services/utils/status/cgi-env/longProcess.zcfg
@@ -0,0 +1,36 @@
+[longProcess]
+ Title = Demo long process. 
+ Abstract = This service doesn't do anything except taking its time, it demonstrates how to use the updateStatus function from your ZOO Service. 
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = wps_status.zo
+ serviceType = C
+ <MetaData>
+   title = Demo GetStatus request
+ </MetaData>
+ <DataInputs>
+  [sid]
+   Title = Service ID
+   Abstract = A ZOO Service ID (unused).
+   minOccurs = 0
+   maxOccurs = 1
+   <LiteralData>
+    dataType = integer
+    <Default>
+    </Default>
+   </LiteralData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = ExecuteResponse document
+   Abstract = The resulting ExecuteResponse document.
+   <MetaData>
+    title = Demo XSL use case
+   </MetaData>   
+   <LiteralData>
+    dataType = string
+    <Default>
+    </Default>
+   </LiteralData>
+ </DataOutputs>  
diff --git a/zoo-project/zoo-services/utils/status/cgi-env/service.py b/zoo-project/zoo-services/utils/status/cgi-env/service.py
new file mode 100644
index 0000000..f0e5872
--- /dev/null
+++ b/zoo-project/zoo-services/utils/status/cgi-env/service.py
@@ -0,0 +1,14 @@
+def demo(conf,inputs,outputs):
+    import zoo,time
+    i=0
+    while i < 100:
+        conf["lenv"]["message"]="Step "+str(i)
+        zoo.update_status(conf,i)
+        time.sleep(0.5)
+        i+=1
+    conf["lenv"]["message"]=zoo._("Error executing the service")
+    return zoo.SERVICE_FAILED
+
+def demo1(conf,inputs,outputs):
+    conf["lenv"]["message"]=zoo._("Error executing the service")
+    return zoo.SERVICE_FAILED
diff --git a/zoo-project/zoo-services/utils/status/cgi-env/updateStatus.xsl b/zoo-project/zoo-services/utils/status/cgi-env/updateStatus.xsl
new file mode 100755
index 0000000..afeaeae
--- /dev/null
+++ b/zoo-project/zoo-services/utils/status/cgi-env/updateStatus.xsl
@@ -0,0 +1,26 @@
+<xsl:stylesheet version="1.0"
+                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                xmlns:ows="http://www.opengis.net/ows/1.1"
+                xmlns:wps="http://www.opengis.net/wps/1.0.0"
+                xmlns:xlink="http://www.w3.org/1999/xlink">
+
+  <xsl:output method="xml"/>
+  <xsl:param name="value" select="string('-1')"/>
+  <xsl:param name="message" select="string('-1')"/>
+
+  <xsl:template match="@*|node()">
+    <xsl:copy>
+      <xsl:apply-templates select="@*|node()"/>
+    </xsl:copy>
+  </xsl:template>
+
+  <xsl:template match="/wps:ExecuteResponse/wps:Status/wps:ProcessStarted">
+    <xsl:copy>
+      <xsl:attribute name="percentCompleted">
+	<xsl:value-of select="$value"/>
+      </xsl:attribute>
+      <xsl:value-of select="$message" />
+    </xsl:copy>
+  </xsl:template>
+
+</xsl:stylesheet>
diff --git a/zoo-project/zoo-services/utils/status/locale/po/fr_FR.utf8.po b/zoo-project/zoo-services/utils/status/locale/po/fr_FR.utf8.po
new file mode 100644
index 0000000..6aa8c5e
--- /dev/null
+++ b/zoo-project/zoo-services/utils/status/locale/po/fr_FR.utf8.po
@@ -0,0 +1,91 @@
+# French translations for PACKAGE package.
+# Copyright (C) 2010 THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# root <gerald.fenoy at geolabs.fr>, 2010.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: zoo-services\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-09-30 03:46+0200\n"
+"PO-Revision-Date: 2010-09-30 03:50+0200\n"
+"Last-Translator: root <gerald.fenoy at geolabs.fr>\n"
+"Language-Team: French\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
+#: ../.cache/my_service_string_to_translate.c:1
+msgid "Produce an updated ExecuteResponse document. "
+msgstr ""
+"Produit un document ExecuteResponse à jour par rapport à l'exécution d'un service en "
+"tâche de fond."
+
+#: ../.cache/my_service_string_to_translate.c:2
+#: ../.cache/my_service_string_to_translate.c:8
+msgid "Service ID"
+msgstr "identifiant de service"
+
+#: ../.cache/my_service_string_to_translate.c:3
+#: ../.cache/my_service_string_to_translate.c:9
+msgid "ExecuteResponse document"
+msgstr ""
+
+#: ../.cache/my_service_string_to_translate.c:4
+msgid ""
+"Create an ExecuteResponse document from a sid (Service ID), it will use the "
+"niternal ZOO Kernel mechanisms to access the current status from a running "
+"Service and update the percentCompleted from the original backup file used "
+"by the ZOO Kernel when running a Service in background. "
+msgstr ""
+
+#: ../.cache/my_service_string_to_translate.c:5
+msgid ""
+"The ZOO Service ID of the ZOO Service we want to get the current status."
+msgstr ""
+"L'identifiant de Service ZOO dont ont veut obetnir le status."
+
+#: ../.cache/my_service_string_to_translate.c:6
+#: ../.cache/my_service_string_to_translate.c:12
+msgid "The resulting ExecuteResponse document."
+msgstr "Le document ExecuteResponse resultant."
+
+#: ../.cache/my_service_string_to_translate.c:7
+msgid "Demo long process. "
+msgstr "Service de démonstration."
+
+#: ../.cache/my_service_string_to_translate.c:10
+msgid ""
+"This service doesn't do anything except taking its time, it demonstrates how "
+"to use the updateStatus function from your ZOO Service. "
+msgstr ""
+"Ce service se contente de prendre son temps, il permet de montrer comment utiliser "
+"la fonction updateStatus depuis vos services ZOO."
+
+#: ../.cache/my_service_string_to_translate.c:11
+msgid "A ZOO Service ID (unused)."
+msgstr "Un identifiant de Service ZOO."
+
+#: ../.cache/my_service_string_to_translate.c:94
+#, c-format
+msgid ""
+"GetStatus was unable to use the tmpPath value set in main.cfg file as "
+"directory %s."
+msgstr ""
+"Le service GetStatus n'a pas été en mesure d'accéder au répertoire correspondant à la "
+"variable tmpPath définie dans le fichier main.cfg comme : %s."
+
+#: ../.cache/my_service_string_to_translate.c:100
+#, c-format
+msgid "GetStatus was unable to find any cache file for Service ID %s."
+msgstr "Le service GetStatus n'a pas été en mesure de trouver un fichier pour l'identifiant de Servicer ZOO %s."
+
+#: ../.cache/my_service_string_to_translate.c:126
+#, c-format
+msgid ""
+"ZOO GetStatus Service was unable to parse the cache xml file available for "
+"the Service ID %s."
+msgstr ""
+"Le Service ZOO GetStatus n'a pas été en mesure de charger le fichier xml pour "
+"l'identifiant %s."
diff --git a/zoo-project/zoo-services/utils/status/locale/po/messages.po b/zoo-project/zoo-services/utils/status/locale/po/messages.po
new file mode 100644
index 0000000..99a8532
--- /dev/null
+++ b/zoo-project/zoo-services/utils/status/locale/po/messages.po
@@ -0,0 +1,82 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL at ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: zoo-services\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2010-09-30 03:46+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL at ADDRESS>\n"
+"Language-Team: LANGUAGE <LL at li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: ../.cache/my_service_string_to_translate.c:1
+msgid "Produce an updated ExecuteResponse document. "
+msgstr ""
+
+#: ../.cache/my_service_string_to_translate.c:2
+#: ../.cache/my_service_string_to_translate.c:8
+msgid "Service ID"
+msgstr ""
+
+#: ../.cache/my_service_string_to_translate.c:3
+#: ../.cache/my_service_string_to_translate.c:9
+msgid "ExecuteResponse document"
+msgstr ""
+
+#: ../.cache/my_service_string_to_translate.c:4
+msgid ""
+"Create an ExecuteResponse document from a sid (Service ID), it will use the "
+"niternal ZOO Kernel mechanisms to access the current status from a running "
+"Service and update the percentCompleted from the original backup file used "
+"by the ZOO Kernel when running a Service in background. "
+msgstr ""
+
+#: ../.cache/my_service_string_to_translate.c:5
+msgid ""
+"The ZOO Service ID of the ZOO Service we want to get the current status."
+msgstr ""
+
+#: ../.cache/my_service_string_to_translate.c:6
+#: ../.cache/my_service_string_to_translate.c:12
+msgid "The resulting ExecuteResponse document."
+msgstr ""
+
+#: ../.cache/my_service_string_to_translate.c:7
+msgid "Demo long process. "
+msgstr ""
+
+#: ../.cache/my_service_string_to_translate.c:10
+msgid ""
+"This service doesn't do anything except taking its time, it demonstrates how "
+"to use the updateStatus function from your ZOO Service. "
+msgstr ""
+
+#: ../.cache/my_service_string_to_translate.c:11
+msgid "A ZOO Service ID (unused)."
+msgstr ""
+
+#: ../.cache/my_service_string_to_translate.c:94
+#, c-format
+msgid ""
+"GetStatus was unable to use the tmpPath value set in main.cfg file as "
+"directory %s."
+msgstr ""
+
+#: ../.cache/my_service_string_to_translate.c:100
+#, c-format
+msgid "GetStatus was unable to find any cache file for Service ID %s."
+msgstr ""
+
+#: ../.cache/my_service_string_to_translate.c:126
+#, c-format
+msgid ""
+"ZOO GetStatus Service was unable to parse the cache xml file available for "
+"the Service ID %s."
+msgstr ""
diff --git a/zoo-project/zoo-services/utils/status/makefile.vc b/zoo-project/zoo-services/utils/status/makefile.vc
new file mode 100755
index 0000000..a1d29de
--- /dev/null
+++ b/zoo-project/zoo-services/utils/status/makefile.vc
@@ -0,0 +1,10 @@
+TROOT= $(ZOOK_DIR)
+!INCLUDE $(ZOOK_DIR)/nmake.opt
+
+cgi-env/wps_status.zo: service.c
+	$(CPP) /D_CRT_NONSTDC_NO_DEPRECATE -DWIN32 -DZOO_SERVICE $(CFLAGS) /c service.c
+	link /dll /out:cgi-env/wps_status.zo $(FILES) ./service.obj $(LDFLAGS) $(XSLT_DIR)\win32\bin.msvc\libxslt.lib $(ZOOK_DIR)\libzoo_service.lib /FORCE:MULTIPLE
+
+clean:
+	erase cgi-env\*_status.*
+	erase *.obj
diff --git a/zoo-project/zoo-services/utils/status/service.c b/zoo-project/zoo-services/utils/status/service.c
new file mode 100644
index 0000000..1d8e1b0
--- /dev/null
+++ b/zoo-project/zoo-services/utils/status/service.c
@@ -0,0 +1,153 @@
+/**
+ * Author : Gérald FENOY
+ *
+ * Copyright 2008-2009 GeoLabs SARL. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "service.h"
+#include "service_internal.h"
+
+extern "C" {
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+
+#include <libxslt/xslt.h>
+#include <libxslt/xsltInternals.h>
+#include <libxslt/transform.h>
+#include <libxslt/xsltutils.h>
+
+#include <dirent.h>
+
+  /**
+   * GetStatus ZOO Service :
+   * This service is used in the ZOO-Project to get information about Services
+   * running as background tasks. The service will first get the XML document 
+   * cached by the ZOO-Kernel before calling effectively the Service, then 
+   * will access the shared memory space created by the Kernel to extract the 
+   * current status of the running Service. Using a simple XSL file it will 
+   * finally produce the final ExecuteResponse including the updated 
+   * percentCompleted attribute of the ProcessStarted node of the cached
+   * document if any (so if the Service is currently running) else it will 
+   * return the final ExecuteResponse stored on the Server file system.
+   */
+  ZOO_DLL_EXPORT int GetStatus(maps*& conf,maps*& inputs,maps*& outputs){	  
+    const char *params[4 + 1];
+    int xmlLoadExtDtdDefaultValue;
+    map* tmpMap=NULL,*tmpMmap=NULL, *tmpTmap=NULL;
+
+    tmpMap=getMapFromMaps(inputs,"sid","value");
+    tmpTmap=getMapFromMaps(conf,"main","tmpPath");
+    tmpMmap=getMapFromMaps(conf,"main","dataPath");
+    if(tmpMmap==NULL)
+      tmpMmap=tmpTmap;
+    xmlInitParser();
+    int hasFile=-1;
+    char xslFileName[1024];
+    char* mem=_getStatusFile(conf,tmpMap->value);
+    if(mem==NULL){
+      char tmp[1024];
+      snprintf(tmp,1024,_ss("GetStatus was unable to find any cache file for Service ID %s."),tmpMap->value);
+      setMapInMaps(conf,"lenv","message",tmp);
+      return SERVICE_FAILED;
+    }
+    sprintf(xslFileName,"%s/updateStatus.xsl",tmpMmap->value);
+    xmlSubstituteEntitiesDefault(1);
+    xmlLoadExtDtdDefaultValue = 0;
+    xsltStylesheetPtr cur = NULL;
+    xmlDocPtr doc, res;
+    cur = xsltParseStylesheetFile(BAD_CAST xslFileName);
+    doc = xmlParseMemory(mem,strlen(mem));
+    //doc = xmlParseFile(fileName);
+    if(cur!=NULL && doc!=NULL){
+      /**
+       * Parse Status to extract Status / Message
+       */
+      char *tmpStr=_getStatus(conf,tmpMap->value);
+#ifdef DEBUG
+      fprintf(stderr,"DEBUG: %s \n",tmpStr);
+#endif
+      if(tmpStr!=NULL && strncmp(tmpStr,"-1",2)!=0){
+	char *tmpStr1=strdup(tmpStr);
+	char *tmpStr0=strdup(strstr(tmpStr,"|")+1);
+	free(tmpStr);
+	tmpStr1[strlen(tmpStr1)-strlen(tmpStr0)-1]='\0';
+	char *tmpStrFinal=(char*)malloc((strlen(tmpStr0)+11)*sizeof(char));
+	sprintf(tmpStrFinal,"string(\"%s\")",tmpStr0);
+	params[0]="value";
+	params[1]=tmpStr1;
+	params[2]="message";
+	params[3]=tmpStrFinal;
+	params[4]=NULL;
+	res = xsltApplyStylesheet(cur, doc, params);
+	xmlChar *xmlbuff;
+	int buffersize;
+	xmlDocDumpFormatMemory(res, &xmlbuff, &buffersize, 1);
+	setMapInMaps(outputs,"Result","value",(char*)xmlbuff);
+	xmlFree(xmlbuff);
+	free(tmpStr1);
+	free(tmpStr0);
+	free(tmpStrFinal);
+      }else{
+	xmlChar *xmlbuff;
+	int buffersize;
+	xmlDocDumpFormatMemory(doc, &xmlbuff, &buffersize, 1);
+	setMapInMaps(outputs,"Result","value",(char*)xmlbuff);
+	xmlFree(xmlbuff);
+      }
+    }
+    else{
+      char tmp[1024];
+      sprintf(tmp,_ss("ZOO GetStatus Service was unable to parse the cache xml file available for the Service ID %s."),tmpMap->value);
+      setMapInMaps(conf,"lenv","message",tmp);
+      return SERVICE_FAILED;
+    }
+    return SERVICE_SUCCEEDED;
+  }
+
+
+  /**
+   * longProcess ZOO Service :
+   * Simple Service which just loop over 100 times then return a welcome message
+   * string, at each step the service will sleep for one second.
+   */
+#ifdef WIN32
+  __declspec(dllexport)
+#endif
+  int longProcess(maps*& conf,maps*& inputs,maps*& outputs){
+    int i=0;
+    while(i<100){
+      char message[10];
+      sprintf(message,"Step %d",i);
+      updateStatus(conf,i,message);
+#ifndef WIN32
+      sleep(1);
+#else
+      Sleep(1000);
+#endif
+      i+=5;
+    }
+    setOutputValue(outputs,"Result",(char*)"\"Long process run successfully\"",-1);
+    return SERVICE_SUCCEEDED;
+  }
+
+}
diff --git a/zoo-project/zoo-services/utils/status/test.sh b/zoo-project/zoo-services/utils/status/test.sh
new file mode 100755
index 0000000..81f11d8
--- /dev/null
+++ b/zoo-project/zoo-services/utils/status/test.sh
@@ -0,0 +1,19 @@
+#!/bin/bash
+
+rm -f log log1
+
+./zoo_loader.cgi "request=Execute&service=WPS&version=1.0.0&Identifier=longProcess&DataInputs=&storeExecuteResponse=true&status=true" > log
+
+if [ -z "$(grep "ows:ExceptionReport" log)" ]; then
+    while [ -z "$(grep "wps:ProcessSucceeded" log1)" ]; 
+    do 
+	./zoo_loader.cgi $(grep statusLocation= ./log | cut -d'?' -f2 | cut -d'"' -f1 | sed "s:amp;::g") > log1 ;
+	cat log1 ; 
+    done
+    cat log1
+else
+    echo "Service failed, please make sure that your main.cfg file contains"
+    echo "in the [main] section valid values for both tmpPath and dataPath."
+    echo 
+    cat log
+fi

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/zoo-project.git



More information about the Pkg-grass-devel mailing list