Index: trunk/.dockerignore
===================================================================
--- trunk/.dockerignore	(revision 986)
+++ 	(revision )
@@ -1,3 +1,0 @@
-/Dockerfile
-/docker-compose.yml
-/docker/
Index: trunk/Dockerfile
===================================================================
--- trunk/Dockerfile	(revision 986)
+++ 	(revision )
@@ -1,274 +1,0 @@
-#
-# Base: Ubuntu 18.04 with updates and external packages
-#
-FROM ubuntu:bionic-20201119 AS base
-ARG DEBIAN_FRONTEND=noninteractive
-ARG BUILD_DEPS=" \
-    dirmngr \
-    gpg-agent \
-    software-properties-common \
-"
-ARG RUN_DEPS=" \
-    libcurl3-gnutls \
-    libfcgi \
-    libmapserver-dev \
-    libmozjs185-dev \
-    \
-    saga \
-    libsaga-api-7.3.0 \
-    libotb \
-    otb-bin \
-    \
-    libpq5 \
-    libpython3.6 \
-    libxslt1.1 \
-    gdal-bin \
-    libcgal13 \
-    python3 \
-    r-base \
-    python3-pip\
-"
-RUN set -ex \
-    && apt-get update && apt-get install -y --no-install-recommends $BUILD_DEPS \
-    \
-    && add-apt-repository ppa:osgeolive/nightly \
-    && add-apt-repository ppa:ubuntugis/ppa \
-    && apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E298A3A825C0D65DFD57CBB651716619E084DAB9 \
-    && add-apt-repository 'deb https://cloud.r-project.org/bin/linux/ubuntu bionic-cran35/' \
-    \
-    && apt-get install -y $RUN_DEPS \
-    \
-    && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false $BUILD_DEPS \
-    && rm -rf /var/lib/apt/lists/*
-
-#
-# builder1: base image with zoo-kernel
-#
-FROM base AS builder1
-ARG DEBIAN_FRONTEND=noninteractive
-ARG BUILD_DEPS=" \
-    bison \
-    flex \
-    make \
-    autoconf \
-    gcc \
-    gettext-base \
-    \
-    # Comment lines bellow if nor OTB nor SAGA \
-    libotb-dev \
-    otb-qgis \
-    otb-bin-qt \
-    qttools5-dev \
-    qttools5-dev-tools \
-    qtbase5-dev \
-    libqt5opengl5-dev \
-    libtinyxml-dev \
-    libfftw3-dev \
-    cmake \
-    libsaga-dev \
-    # Comment lines before this one if nor OTB nor SAGA \
-    \
-    libfcgi-dev \
-    libgdal-dev \
-    libwxgtk3.0-dev \
-    libjson-c-dev \
-    libssh2-1-dev \
-    libssl-dev \
-    libxml2-dev \
-    libxslt1-dev \
-    python3-dev \
-    uuid-dev \
-    r-base-dev \
-"
-WORKDIR /zoo-project
-COPY . .
-
-RUN set -ex \
-    && apt-get update && apt-get install -y --no-install-recommends $BUILD_DEPS \
-    \
-    && make -C ./thirds/cgic206 libcgic.a \
-    \
-    && cd ./zoo-project/zoo-kernel \
-    && autoconf \
-    && ./configure --with-python=/usr --with-pyvers=3.6 --with-js=/usr --with-mapserver=/usr --with-ms-version=7 --with-json=/usr --with-r=/usr --with-db-backend --prefix=/usr --with-otb=/usr/ --with-itk=/usr --with-otb-version=6.6 --with-itk-version=4.12 --with-saga=/usr --with-saga-version=7.2 --with-wx-config=/usr/bin/wx-config \
-    && make \
-    && make install \
-    \
-    # TODO: why not copied by 'make'?
-    && cp zoo_loader.cgi main.cfg /usr/lib/cgi-bin/ \
-    && cp ../zoo-services/hello-py/cgi-env/* /usr/lib/cgi-bin/ \
-    && cp ../zoo-services/hello-js/cgi-env/* /usr/lib/cgi-bin/ \
-    && cp ../zoo-api/js/* /usr/lib/cgi-bin/ \
-    && cp ../zoo-services/utils/open-api/cgi-env/* /usr/lib/cgi-bin/ \
-    && cp ../zoo-services/hello-py/cgi-env/* /usr/lib/cgi-bin/ \
-    && cp ../zoo-services/hello-js/cgi-env/* /usr/lib/cgi-bin/ \
-    && cp ../zoo-services/hello-r/cgi-env/* /usr/lib/cgi-bin/ \
-    && cp ../zoo-api/js/* /usr/lib/cgi-bin/ \
-    && cp ../zoo-api/r/minimal.r /usr/lib/cgi-bin/ \
-    \
-    && cp oas.cfg /usr/lib/cgi-bin/ \
-    \
-    # TODO: main.cfg is not processed \
-    && prefix=/usr envsubst < main.cfg > /usr/lib/cgi-bin/main.cfg \
-    \
-    #Comment lines below from here if no OTB \
-    && mkdir otb_build \
-    && cd otb_build \
-    && cmake ../../../thirds/otb2zcfg \
-    && make \
-    && mkdir OTB \
-    && cd OTB \
-    && ITK_AUTOLOAD_PATH=/usr/lib/x86_64-linux-gnu/otb/applications/ ../otb2zcfg \
-    && mkdir /usr/lib/cgi-bin/OTB \
-    && cp *zcfg /usr/lib/cgi-bin/OTB \
-    #&& for i in *zcfg; do cp $i /usr/lib/cgi-bin/$i ; j="$(echo $i | sed "s:.zcfg::g")" ; sed "s:$j:OTB_$j:g" -i  /usr/lib/cgi-bin/OTB_$i ; done \
-    #Comment lines before this one if no OTB \
-    \
-    #Comment lines below from here if no SAGA \
-    && cd .. \
-    && make -C ../../../thirds/saga2zcfg \
-    && mkdir zcfgs \
-    && cd zcfgs \
-    && dpkg -L saga \
-    && export MODULE_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu/saga/ \
-    && export SAGA_MLB=/usr/lib/x86_64-linux-gnu/saga/ \
-    && ln -s /usr/lib/x86_64-linux-gnu/saga/ /usr/lib/saga \
-    && ../../../../thirds/saga2zcfg/saga2zcfg \
-    && mkdir /usr/lib/cgi-bin/SAGA \
-    && ls \
-    && cp -r * /usr/lib/cgi-bin/SAGA \
-    #Remove OTB if not built or SAGA if no SAGA \
-    && for j in OTB SAGA ; do for i in $(find /usr/lib/cgi-bin/$j/ -name "*zcfg"); do sed "s:image/png:image/png\n     useMapserver = true\n     msClassify = true:g;s:text/xml:text/xml\n     useMapserver = true:g;s:mimeType = application/x-ogc-aaigrid:mimeType = application/x-ogc-aaigrid\n   </Supported>\n   <Supported>\n     mimeType = image/png\n     useMapserver=true:g" -i $i; done; done \
-    \
-    && cd ../.. \
-    #Comment lines before this one if nor OTB nor SAGA \
-    \
-    && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false $BUILD_DEPS \
-    && rm -rf /var/lib/apt/lists/*
-
-#
-# Optional zoo modules build.
-#
-FROM base AS builder2
-ARG DEBIAN_FRONTEND=noninteractive
-ARG BUILD_DEPS=" \
-    bison \
-    flex \
-    make \
-    autoconf \
-    g++ \
-    gcc \
-    libc-dev \
-    libfcgi-dev \
-    libgdal-dev \
-    libxml2-dev \
-    libxslt1-dev \
-    libcgal-dev \
-"
-WORKDIR /zoo-project
-COPY ./zoo-project/zoo-services ./zoo-project/zoo-services
-
-# From zoo-kernel
-COPY --from=builder1 /usr/lib/cgi-bin/ /usr/lib/cgi-bin/
-COPY --from=builder1 /usr/lib/libzoo_service.so.1.8 /usr/lib/libzoo_service.so.1.8
-COPY --from=builder1 /usr/lib/libzoo_service.so /usr/lib/libzoo_service.so
-COPY --from=builder1 /usr/com/zoo-project/ /usr/com/zoo-project/
-COPY --from=builder1 /usr/include/zoo/ /usr/include/zoo/
-
-# Additional files from bulder2
-COPY --from=builder1 /zoo-project/zoo-project/zoo-kernel/ZOOMakefile.opts /zoo-project/zoo-project/zoo-kernel/ZOOMakefile.opts
-COPY --from=builder1 /zoo-project/zoo-project/zoo-kernel/sqlapi.h /zoo-project/zoo-project/zoo-kernel/sqlapi.h
-COPY --from=builder1 /zoo-project/zoo-project/zoo-kernel/service.h /zoo-project/zoo-project/zoo-kernel/service.h
-COPY --from=builder1 /zoo-project/zoo-project/zoo-kernel/service_internal.h /zoo-project/zoo-project/zoo-kernel/service_internal.h
-COPY --from=builder1 /zoo-project/zoo-project/zoo-kernel/version.h /zoo-project/zoo-project/zoo-kernel/version.h
-
-RUN set -ex \
-    && apt-get update && apt-get install -y --no-install-recommends $BUILD_DEPS \
-    \
-    && cd ./zoo-project/zoo-services/utils/status \
-    && make \
-    && make install \
-    \
-    && cd ../../cgal \
-    && make \
-    && cp cgi-env/* /usr/lib/cgi-bin/ \
-    \
-    && cd .. \
-    && cd ../zoo-services/ogr/base-vect-ops \
-    && make \
-    && cp cgi-env/* /usr/lib/cgi-bin/ \
-    && cd ../.. \
-    \
-    && cd ../zoo-services/gdal/ \
-    && for i in contour dem grid profile translate warp ; do cd $i ; make && cp cgi-env/* /usr/lib/cgi-bin/ ; cd .. ; done \
-    \
-    && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false $BUILD_DEPS \
-    && rm -rf /var/lib/apt/lists/*
-
-#
-# Optional zoo demos download.
-#
-FROM base AS demos
-ARG DEBIAN_FRONTEND=noninteractive
-ARG BUILD_DEPS=" \
-    git \
-    \
-"
-WORKDIR /zoo-project
-
-RUN set -ex \
-    && apt-get update && apt-get install -y --no-install-recommends $BUILD_DEPS \
-    \
-    && git clone https://github.com/ZOO-Project/examples.git \
-    && git clone https://github.com/swagger-api/swagger-ui.git
-
-#
-# Runtime image with apache2.
-#
-FROM base AS runtime
-ARG DEBIAN_FRONTEND=noninteractive
-ARG RUN_DEPS=" \
-    apache2 \
-    curl \
-    cgi-mapserver \
-    mapserver-bin \
-    #Uncomment the line below to add vi editor \
-    #vim \
-    #Uncomment the lines below to add debuging \
-    #valgrind \
-    #gdb \
-"
-
-# From zoo-kernel
-COPY --from=builder1 /usr/lib/cgi-bin/ /usr/lib/cgi-bin/
-COPY --from=builder1 /usr/lib/libzoo_service.so.1.8 /usr/lib/libzoo_service.so.1.8
-COPY --from=builder1 /usr/lib/libzoo_service.so /usr/lib/libzoo_service.so
-COPY --from=builder1 /usr/com/zoo-project/ /usr/com/zoo-project/
-COPY --from=builder1 /usr/include/zoo/ /usr/include/zoo/
-
-# From optional zoo modules
-COPY --from=builder2 /usr/lib/cgi-bin/ /usr/lib/cgi-bin/
-COPY --from=builder2 /usr/com/zoo-project/ /usr/com/zoo-project/
-
-# From optional zoo demos
-COPY --from=demos /zoo-project/examples/data/ /usr/com/zoo-project/
-COPY --from=demos /zoo-project/examples/ /var/www/html/
-COPY --from=demos /zoo-project/swagger-ui /var/www/html/swagger-ui
-
-
-RUN set -ex \
-    && apt-get update && apt-get install -y --no-install-recommends $RUN_DEPS \
-    \
-    && sed "s=https://petstore.swagger.io/v2/swagger.json=http://localhost/ogc-api/api=g" -i /var/www/html/swagger-ui/dist/index.html \
-    && mv  /var/www/html/swagger-ui/dist  /var/www/html/swagger-ui/oapip \
-    && ln -s /tmp/ /var/www/html/temp \
-    && ln -s /usr/lib/x86_64-linux-gnu/saga/ /usr/lib/saga \
-    && rm -rf /var/lib/apt/lists/* \
-    && pip3 install Cheetah3 redis\
-    && sed "s:AllowOverride None:AllowOverride All:g" -i /etc/apache2/apache2.conf \
-    && mkdir -p /tmp/statusInfos \
-    && chown www-data:www-data -R /tmp/statusInfos /usr/com/zoo-project \
-    && a2enmod cgi rewrite
-
-EXPOSE 80
-CMD /usr/sbin/apache2ctl -D FOREGROUND
Index: trunk/docker-compose.yml
===================================================================
--- trunk/docker-compose.yml	(revision 986)
+++ 	(revision )
@@ -1,52 +1,0 @@
-version: '3'
-services:
-  zookernel:
-    build: .
-    ports:
-      - "80:80"
-    volumes:
-      - ./docker/main.cfg:/usr/lib/cgi-bin/main.cfg
-      - ./docker/oas.cfg:/usr/lib/cgi-bin/oas.cfg
-      - ./docker/default.conf:/etc/apache2/sites-available/000-default.conf
-      - ./zoo-project/zoo-services/utils/open-api/server/publish.py:/usr/lib/cgi-bin/publish.py
-      - ./zoo-project/zoo-services/utils/open-api/server/subscriber.py:/usr/lib/cgi-bin/subscriber.py
-      - ./docker/.htaccess:/var/www/html/.htaccess
-      - ./zoo-project/zoo-services/utils/open-api/templates/index.html:/var/www/index.html
-      - ./zoo-project/zoo-services/utils/open-api/static:/var/www/html/static
-    depends_on:
-      - pgbouncer
-    environment:
-      - ZOO_REDIS_HOST=redis
-  websocketd:
-    build: ./docker/websocketd
-    ports:
-      - 8888:8888
-    environment:
-      - ZOO_REDIS_HOST=redis
-    volumes:
-      - ./zoo-project/zoo-services/utils/open-api/server/subscriber.py:/shell.py
-    command: ["--port=8888", "/shell.py"]
-  pg:
-    image: postgres:9.6.18-alpine
-    restart: always
-    environment:
-      POSTGRES_USER: zoo
-      POSTGRES_PASSWORD: zoo
-      POSTGRES_DB: zoo
-    volumes:
-      # Load the zoo kernel schema
-      - ./zoo-project/zoo-kernel/sql/schema.sql:/docker-entrypoint-initdb.d/1-schema.sql
-  pgbouncer:
-    image: edoburu/pgbouncer:1.8.1
-    environment:
-      DATABASE_URL: "postgres://zoo:zoo@pg/zoo"
-      MAX_CLIENT_CONN: 1000
-      MAX_DB_CONNECTIONS: 100
-      DEFAULT_POOL_SIZE: 100
-      POOL_MODE: transaction
-    ports:
-      - "5432:5432"
-    depends_on:
-      - pg
-  redis:
-    image: redis:6.0.9
Index: trunk/thirds/cgic206/Makefile
===================================================================
--- trunk/thirds/cgic206/Makefile	(revision 986)
+++ trunk/thirds/cgic206/Makefile	(revision 1)
@@ -1,22 +1,15 @@
-OS:=$(shell uname -s)
-CPU:=$(shell uname -m)
-ifeq ($(OS),Darwin)
-	MACOS_CFLAGS=-arch x86_64
-	LIBS= -L./ -lcgic /usr/local/lib/libfcgi.dylib
-else
-	LIBS= -L./ -lcgic /usr/lib/libfcgi.a
-endif
-CFLAGS=-I/usr/local/include -g -Wall ${MACOS_CFLAGS}
+CFLAGS=-g -Wall
 CC=gcc
 AR=ar
 RANLIB=ranlib
+LIBS=-L./ -lcgic ../fcgi-2.4.0/libfcgi/.libs/libfcgi.a 
+CFLAGS=-I//var/www/localhost/include
 
 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/
+	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
Index: trunk/thirds/cgic206/cgic.c
===================================================================
--- trunk/thirds/cgic206/cgic.c	(revision 986)
+++ trunk/thirds/cgic206/cgic.c	(revision 1)
@@ -23,8 +23,4 @@
 #define CGICDEBUGEND
 #endif /* CGICDEBUG */
-
-#ifdef WIN32
-#define _INC_STDIO
-#endif
 
 #include <stdio.h>
@@ -72,5 +68,4 @@
 char *cgiUserAgent;
 char *cgiReferrer;
-char *cgiSid;
 
 FILE *cgiIn;
@@ -79,5 +74,4 @@
 /* True if CGI environment was restored from a file. */
 static int cgiRestored = 0;
-static int cgiTreatUrlEncoding;
 
 static void cgiGetenv(char **s, char *var);
@@ -142,17 +136,8 @@
 	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");
@@ -205,7 +190,4 @@
 	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");
@@ -226,6 +208,6 @@
 #endif /* WIN32 */
 	cgiFormEntryFirst = 0;
-	cgiIn = FCGI_stdin;
-	cgiOut = FCGI_stdout;
+	cgiIn = stdin;
+	cgiOut = stdout;
 	cgiRestored = 0;
 
@@ -241,7 +223,5 @@
 
 
-	cgiTreatUrlEncoding=0;
 	if (cgiStrEqNc(cgiRequestMethod, "post")) {
-		cgiTreatUrlEncoding=0;
 #ifdef CGICDEBUG
 		CGICDEBUGSTART
@@ -313,5 +293,4 @@
 	cgiFreeResources();
 	}
-	FCGI_Finish();
 	return result;
 }
@@ -1118,5 +1097,4 @@
 	while (srcPos < len) {
 		int ch = cp[srcPos];
-		if(cgiTreatUrlEncoding==1)
 		switch (escapeState) {
 			case cgiEscapeRest:
@@ -1126,5 +1104,5 @@
 				s[dstPos++] = ' ';
 			} else {
-				s[dstPos++] = ch;
+				s[dstPos++] = ch;	
 			}
 			break;
@@ -1139,6 +1117,4 @@
 			break;
 		}
-		else
-		  s[dstPos++] = ch;
 		srcPos++;
 	}
Index: trunk/thirds/cgic206/cgic.h
===================================================================
--- trunk/thirds/cgic206/cgic.h	(revision 986)
+++ trunk/thirds/cgic206/cgic.h	(revision 1)
@@ -124,10 +124,4 @@
 #endif
 char *cgiCookie;
-
-extern 
-#ifdef __cplusplus
-"C" 
-#endif
-char *cgiSid;
 
 /* A macro providing the same incorrect spelling that is
Index: trunk/thirds/cgic206/cgic.html
===================================================================
--- trunk/thirds/cgic206/cgic.html	(revision 986)
+++ trunk/thirds/cgic206/cgic.html	(revision 1)
@@ -1630,5 +1630,5 @@
 </strong><br><dd>
 cgiHeaderLocation() should be called if the programmer wishes to
-redirect the user to a different URL. No further output
+redirect the user to a different URL. No futher output
 is needed in this case.
 <p>
Index: trunk/thirds/cgic206/cgictest.c
===================================================================
--- trunk/thirds/cgic206/cgictest.c	(revision 986)
+++ trunk/thirds/cgic206/cgictest.c	(revision 1)
@@ -23,10 +23,8 @@
 	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");
+	cgiHeaderContentType("text/html");
+	fprintf(cgiOut, "<HTML><HEAD>\n");
+	fprintf(cgiOut, "<TITLE>cgic test</TITLE></HEAD>\n");
+	fprintf(cgiOut, "<BODY><H1>cgic test</H1>\n");
 	Name();
 	Address();
@@ -38,5 +36,5 @@
 	NonExButtons();
 	RadioButtons();
-	printf( "</BODY></HTML>\n");
+	fprintf(cgiOut, "</BODY></HTML>\n");
 	return 0;
 }
@@ -47,23 +45,23 @@
 	switch (result) {
 		case cgiFormSuccess:
-		printf( "Name fetched, result code: cgiFormSuccess<br>\n");
+		fprintf(cgiOut, "Name fetched, result code: cgiFormSuccess<br>\n");
 		break;
 		case cgiFormTruncated:
-		printf( "Name fetched, result code: cgiFormTruncated<br>\n");
+		fprintf(cgiOut, "Name fetched, result code: cgiFormTruncated<br>\n");
 		break;
 		case cgiFormEmpty:
-		printf( "Name fetched, result code: cgiFormEmpty<br>\n");
+		fprintf(cgiOut, "Name fetched, result code: cgiFormEmpty<br>\n");
 		break;
 		case cgiFormNotFound:
-		printf( "Name fetched, result code: cgiFormNotFound<br>\n");
+		fprintf(cgiOut, "Name fetched, result code: cgiFormNotFound<br>\n");
 		break;
 		case cgiFormMemory:
-		printf( "Name fetched, result code: cgiFormMemory<br>\n");
+		fprintf(cgiOut, "Name fetched, result code: cgiFormMemory<br>\n");
 		break;
 		default:
-		printf( "Name fetched, unexpected result code: %d\n", result);
+		fprintf(cgiOut, "Name fetched, unexpected result code: %d\n", result);
 		break;
 	}	
-	printf( "Name: %s<BR>\n", name);
+	fprintf(cgiOut, "Name: %s<BR>\n", name);
 }
 	
@@ -71,12 +69,12 @@
 	char address[241];
 	cgiFormString("address", address, 241);
-	printf( "Address: <PRE>\n%s</PRE>\n", address);
+	fprintf(cgiOut, "Address: <PRE>\n%s</PRE>\n", address);
 }
 
 void Hungry() {
 	if (cgiFormCheckboxSingle("hungry") == cgiFormSuccess) {
-		printf( "I'm Hungry!<BR>\n");
+		fprintf(cgiOut, "I'm Hungry!<BR>\n");
 	} else {
-		printf( "I'm Not Hungry!<BR>\n");
+		fprintf(cgiOut, "I'm Not Hungry!<BR>\n");
 	}
 }
@@ -85,5 +83,5 @@
 	double temperature;
 	cgiFormDoubleBounded("temperature", &temperature, 80.0, 120.0, 98.6);
-	printf( "My temperature is %f.<BR>\n", temperature);
+	fprintf(cgiOut, "My temperature is %f.<BR>\n", temperature);
 }
 	
@@ -91,5 +89,5 @@
 	int frogsEaten;
 	cgiFormInteger("frogs", &frogsEaten, 0);
-	printf( "I have eaten %d frogs.<BR>\n", frogsEaten);
+	fprintf(cgiOut, "I have eaten %d frogs.<BR>\n", frogsEaten);
 }
 
@@ -103,5 +101,5 @@
 	int colorChoice;
 	cgiFormSelectSingle("colors", colors, 3, &colorChoice, 0);
-	printf( "I am: %s<BR>\n", colors[colorChoice]);
+	fprintf(cgiOut, "I am: %s<BR>\n", colors[colorChoice]);
 }	 
 
@@ -120,14 +118,14 @@
 		flavorChoices, &invalid);
 	if (result == cgiFormNotFound) {
-		printf( "I hate ice cream.<p>\n");
+		fprintf(cgiOut, "I hate ice cream.<p>\n");
 	} else {	
-		printf( "My favorite ice cream flavors are:\n");
-		printf( "<ul>\n");
+		fprintf(cgiOut, "My favorite ice cream flavors are:\n");
+		fprintf(cgiOut, "<ul>\n");
 		for (i=0; (i < 3); i++) {
 			if (flavorChoices[i]) {
-				printf( "<li>%s\n", flavors[i]);
+				fprintf(cgiOut, "<li>%s\n", flavors[i]);
 			}
 		}
-		printf( "</ul>\n");
+		fprintf(cgiOut, "</ul>\n");
 	}
 }
@@ -148,5 +146,5 @@
 	cgiFormRadio("age", ages, 4, &ageChoice, 0);
 
-	printf( "Age of Truck: %s (method #1)<BR>\n", 
+	fprintf(cgiOut, "Age of Truck: %s (method #1)<BR>\n", 
 		ages[ageChoice]);
 
@@ -159,5 +157,5 @@
 	cgiFormString("age", ageText, 10);
 
-	printf( "Age of Truck: %s (method #2)<BR>\n", ageText);
+	fprintf(cgiOut, "Age of Truck: %s (method #2)<BR>\n", ageText);
 }
 
@@ -180,18 +178,18 @@
 		since votes for nonexistent candidates should probably
 		be discounted... */
-	printf( "Votes (method 1):<BR>\n");
+	fprintf(cgiOut, "Votes (method 1):<BR>\n");
 	result = cgiFormCheckboxMultiple("vote", votes, 4, 
 		voteChoices, &invalid);
 	if (result == cgiFormNotFound) {
-		printf( "I hate them all!<p>\n");
+		fprintf(cgiOut, "I hate them all!<p>\n");
 	} else {	
-		printf( "My preferred candidates are:\n");
-		printf( "<ul>\n");
+		fprintf(cgiOut, "My preferred candidates are:\n");
+		fprintf(cgiOut, "<ul>\n");
 		for (i=0; (i < 4); i++) {
 			if (voteChoices[i]) {
-				printf( "<li>%s\n", votes[i]);
+				fprintf(cgiOut, "<li>%s\n", votes[i]);
 			}
 		}
-		printf( "</ul>\n");
+		fprintf(cgiOut, "</ul>\n");
 	}
 
@@ -200,17 +198,17 @@
 		than the code and invented responses are not a danger
 		or can be checked in some other way. */
-	printf( "Votes (method 2):<BR>\n");
+	fprintf(cgiOut, "Votes (method 2):<BR>\n");
 	result = cgiFormStringMultiple("vote", &responses);
 	if (result == cgiFormNotFound) {	
-		printf( "I hate them all!<p>\n");
+		fprintf(cgiOut, "I hate them all!<p>\n");
 	} else {
 		int i = 0;
-		printf( "My preferred candidates are:\n");
-		printf( "<ul>\n");
+		fprintf(cgiOut, "My preferred candidates are:\n");
+		fprintf(cgiOut, "<ul>\n");
 		while (responses[i]) {
-			printf( "<li>%s\n", responses[i]);
+			fprintf(cgiOut, "<li>%s\n", responses[i]);
 			i++;
 		}
-		printf( "</ul>\n");
+		fprintf(cgiOut, "</ul>\n");
 	}
 	/* We must be sure to free the string array or a memory
Index: trunk/thirds/cgic206/makefile.vc
===================================================================
--- trunk/thirds/cgic206/makefile.vc	(revision 986)
+++ trunk/thirds/cgic206/makefile.vc	(revision 1)
@@ -1,13 +1,13 @@
-GEODIR=\MMBK\SRCS\fcgi-2.4.1-SNAP-0311112127\ 
-DESTDIR=..
+GEODIR=C:/OSGeo4W
+DESTDIR=C:\OSGeo4W
 CFLAGS=-g -Wall
 CC=cl /TP
-LIBS=$(GEODIR)/libfcgi/Release/libfcgi.lib /nologo
+LIBS=$(GEODIR)/lib/libfcgi.lib /nologo
 LIBS1=./libcgic.lib
 
-CFLAGS=/EHa /nologo /DCRT_SECURE_NO_WARNING /MD /W2 /O2 /D "WIN32" \
-	-I $(GEODIR)\include 
+CFLAGS=/EHa /nologo /DCRT_SECURE_NO_WARNING /MT /W2 /O2 /D "WIN32" \
+	-I $(GEODIR)/include 
 
-all: libcgic.lib #cgictest.exe capture.exe 
+all: libcgic.lib cgictest.exe capture.exe
 
 install: libcgic.lib
@@ -24,5 +24,5 @@
 
 cgictest.exe: cgictest.obj 
-	link cgictest.obj $(LIBS) /out:cgictest.exe
+	link cgictest.obj $(LIBS1) /out:cgictest.exe
 
 cgic.obj: 
@@ -30,5 +30,5 @@
 
 capture.exe: capture.obj libcgic.lib
-	$(CC) $(CFLAGS) capture.c $(LIBS)
+	$(CC) $(CFLAGS) capture.c $(LIBS1)
 
 clean:
Index: trunk/thirds/dirent-win32/dirent.c
===================================================================
--- trunk/thirds/dirent-win32/dirent.c	(revision 1)
+++ trunk/thirds/dirent-win32/dirent.c	(revision 1)
@@ -0,0 +1,146 @@
+/*
+
+    Implementation of POSIX directory browsing functions and types for Win32.
+
+    Author:  Kevlin Henney (kevlin@acm.org, kevlin@curbralan.com)
+    History: Created March 1997. Updated June 2003.
+    Rights:  See end of file.
+
+*/
+
+#include <dirent.h>
+#include <errno.h>
+#include <io.h> /* _findfirst and _findnext set errno iff they return -1 */
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+struct DIR
+{
+    long                handle; /* -1 for failed rewind */
+    struct _finddata_t  info;
+    struct dirent       result; /* d_name null iff first time */
+    char                *name;  /* null-terminated char string */
+};
+
+DIR *opendir(const char *name)
+{
+    DIR *dir = 0;
+
+    if(name && name[0])
+    {
+        size_t base_length = strlen(name);
+        const char *all = /* search pattern must end with suitable wildcard */
+            strchr("/\\", name[base_length - 1]) ? "*" : "/*";
+
+        if((dir = (DIR *) malloc(sizeof *dir)) != 0 &&
+           (dir->name = (char *) malloc(base_length + strlen(all) + 1)) != 0)
+        {
+            strcat(strcpy(dir->name, name), all);
+
+            if((dir->handle = (long) _findfirst(dir->name, &dir->info)) != -1)
+            {
+                dir->result.d_name = 0;
+            }
+            else /* rollback */
+            {
+                free(dir->name);
+                free(dir);
+                dir = 0;
+            }
+        }
+        else /* rollback */
+        {
+            free(dir);
+            dir   = 0;
+            errno = ENOMEM;
+        }
+    }
+    else
+    {
+        errno = EINVAL;
+    }
+
+    return dir;
+}
+
+int closedir(DIR *dir)
+{
+    int result = -1;
+
+    if(dir)
+    {
+        if(dir->handle != -1)
+        {
+            result = _findclose(dir->handle);
+        }
+
+        free(dir->name);
+        free(dir);
+    }
+
+    if(result == -1) /* map all errors to EBADF */
+    {
+        errno = EBADF;
+    }
+
+    return result;
+}
+
+struct dirent *readdir(DIR *dir)
+{
+    struct dirent *result = 0;
+
+    if(dir && dir->handle != -1)
+    {
+        if(!dir->result.d_name || _findnext(dir->handle, &dir->info) != -1)
+        {
+            result         = &dir->result;
+            result->d_name = dir->info.name;
+        }
+    }
+    else
+    {
+        errno = EBADF;
+    }
+
+    return result;
+}
+
+void rewinddir(DIR *dir)
+{
+    if(dir && dir->handle != -1)
+    {
+        _findclose(dir->handle);
+        dir->handle = (long) _findfirst(dir->name, &dir->info);
+        dir->result.d_name = 0;
+    }
+    else
+    {
+        errno = EBADF;
+    }
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+/*
+
+    Copyright Kevlin Henney, 1997, 2003. All rights reserved.
+
+    Permission to use, copy, modify, and distribute this software and its
+    documentation for any purpose is hereby granted without fee, provided
+    that this copyright and permissions notice appear in all copies and
+    derivatives.
+    
+    This software is supplied "as is" without express or implied warranty.
+
+    But that said, if there are any problems please get in touch.
+
+*/
+
Index: trunk/thirds/dirent-win32/dirent.h
===================================================================
--- trunk/thirds/dirent-win32/dirent.h	(revision 986)
+++ trunk/thirds/dirent-win32/dirent.h	(revision 1)
@@ -1,373 +1,50 @@
-/*****************************************************************************
- * 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
+#ifndef DIRENT_INCLUDED
+#define DIRENT_INCLUDED
 
-#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
+    Declaration of POSIX directory browsing functions and types for Win32.
+
+    Author:  Kevlin Henney (kevlin@acm.org, kevlin@curbralan.com)
+    History: Created March 1997. Updated June 2003.
+    Rights:  See end of file.
+    
+*/
+
+#ifdef __cplusplus
+extern "C"
+{
 #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 */
+typedef struct DIR DIR;
 
-#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
+struct dirent
+{
+    char *d_name;
+};
 
-/* 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)
+DIR           *opendir(const char *);
+int           closedir(DIR *);
+struct dirent *readdir(DIR *);
+void          rewinddir(DIR *);
 
 /*
- * 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
+    Copyright Kevlin Henney, 1997, 2003. All rights reserved.
 
+    Permission to use, copy, modify, and distribute this software and its
+    documentation for any purpose is hereby granted without fee, provided
+    that this copyright and permissions notice appear in all copies and
+    derivatives.
+    
+    This software is supplied "as is" without express or implied warranty.
 
-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;
+    But that said, if there are any problems please get in touch.
 
-
-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 occurred */
-         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*/
+
+#endif
Index: trunk/zoo-api/js/ZOO-api.js
===================================================================
--- trunk/zoo-api/js/ZOO-api.js	(revision 1)
+++ trunk/zoo-api/js/ZOO-api.js	(revision 1)
@@ -0,0 +1,3201 @@
+/**
+ * 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.
+ */
+
+ZOO = {
+  SERVICE_ACCEPTED: 0,
+  SERVICE_STARTED: 1,
+  SERVICE_PAUSED: 2,
+  SERVICE_SUCCEEDED: 3,
+  SERVICE_FAILED: 4,
+  removeItem: function(array, item) {
+    for(var i = array.length - 1; i >= 0; i--) {
+        if(array[i] == item) {
+            array.splice(i,1);
+        }
+    }
+    return array;
+  },
+  indexOf: function(array, obj) {
+    for(var i=0, len=array.length; i<len; i++) {
+      if (array[i] == obj)
+        return i;
+    }
+    return -1;   
+  },
+  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") {
+        // 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;
+  }
+};
+
+ZOO.String = {
+  startsWith: function(str, sub) {
+    return (str.indexOf(sub) == 0);
+  },
+  contains: function(str, sub) {
+    return (str.indexOf(sub) != -1);
+  },
+  trim: function(str) {
+    return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
+  },
+  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;
+  },
+  tokenRegEx:  /\$\{([\w.]+?)\}/g,
+  numberRegEx: /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/,
+  isNumeric: function(value) {
+    return ZOO.String.numberRegEx.test(value);
+  },
+  numericIf: function(value) {
+    return ZOO.String.isNumeric(value) ? parseFloat(value) : value;
+  }
+};
+
+ZOO.Request = {
+  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);
+  },
+  Post: function(url,body,headers) {
+    if(!(headers instanceof Array)) {
+      var headersArray = [];
+      for (var hname in headers) {
+        headersArray.push(name+': '+headers[name]); 
+      }
+      headers = headersArray;
+    }
+    return ZOORequest('POST',url,body,headers);
+  }
+};
+
+ZOO.Bounds = ZOO.Class({
+  left: null,
+  bottom: null,
+  right: null,
+  top: null,
+  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);
+  },
+  clone:function() {
+    return new ZOO.Bounds(this.left, this.bottom, 
+                          this.right, this.top);
+  },
+  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;
+  },
+  toString:function() {
+    return ( "left-bottom=(" + this.left + "," + this.bottom + ")"
+              + " right-top=(" + this.right + "," + this.top + ")" );
+  },
+  toArray: function() {
+    return [this.left, this.bottom, this.right, this.top];
+  },
+  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;
+  },
+  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)
+      ])
+    ]);
+  },
+  getWidth:function() {
+    return (this.right - this.left);
+  },
+  getHeight:function() {
+    return (this.top - this.bottom);
+  },
+  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);
+  },
+  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;
+      }
+    }
+  },
+  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;
+  },
+  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;
+  },
+  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'
+});
+
+ZOO.Projection = ZOO.Class({
+  proj: null,
+  projCode: null,
+  initialize: function(projCode, options) {
+    ZOO.extend(this, options);
+    this.projCode = projCode;
+    if (Proj4js) {
+      this.proj = new Proj4js.Proj(projCode);
+    }
+  },
+  getCode: function() {
+    return this.proj ? this.proj.srsCode : this.projCode;
+  },
+  getUnits: function() {
+    return this.proj ? this.proj.units : null;
+  },
+  toString: function() {
+    return this.getCode();
+  },
+  equals: function(projection) {
+    if (projection && projection.getCode)
+      return this.getCode() == projection.getCode();
+    else
+      return false;
+  },
+  destroy: function() {
+    this.proj = null;
+    this.projCode = null;
+  },
+  CLASS_NAME: 'ZOO.Projection'
+});
+ZOO.Projection.transform = function(point, source, dest) {
+    if (source.proj && dest.proj)
+        point = Proj4js.transform(source.proj, dest.proj, point);
+    return point;
+};
+
+ZOO.Format = ZOO.Class({
+  options:null,
+  externalProjection: null,
+  internalProjection: null,
+  data: null,
+  keepData: false,
+  initialize: function(options) {
+    ZOO.extend(this, options);
+    this.options = options;
+  },
+  destroy: function() {
+  },
+  read: function(data) {
+  },
+  write: function(data) {
+  },
+  CLASS_NAME: 'ZOO.Format'
+});
+ZOO.Format.WKT = ZOO.Class(ZOO.Format, {
+  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]);
+  },
+  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;
+  },
+  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('');
+  },
+  extract: {
+    'point': function(point) {
+      return point.x + ' ' + point.y;
+    },
+    '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(',');
+    },
+    '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(',');
+    },
+    '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(',');
+    },
+    '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(',');
+    },
+    '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(',');
+    }
+  },
+  parse: {
+    '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])
+            );
+    },
+    '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)
+           );
+    },
+    '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)
+          );
+    },
+    '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)
+          );
+    },
+    '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)
+           );
+    },
+    '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)
+          );
+    },
+    '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'
+});
+ZOO.Format.JSON = ZOO.Class(ZOO.Format, {
+  indent: "    ",
+  space: " ",
+  newline: "\n",
+  level: 0,
+  pretty: false,
+  initialize: function(options) {
+    ZOO.Format.prototype.initialize.apply(this, [options]);
+  },
+  read: function(json, filter) {
+    try {
+      if (/^[\],:{}\s]*$/.test(json.replace(/\\["\\\/bfnrtu]/g, '@').
+                          replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
+                          replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
+        var object = eval('(' + json + ')');
+        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;
+  },
+  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;
+  },
+  writeIndent: function() {
+    var pieces = [];
+    if(this.pretty) {
+      for(var i=0; i<this.level; ++i) {
+        pieces.push(this.indent);
+      }
+    }
+    return pieces.join('');
+  },
+  writeNewline: function() {
+    return (this.pretty) ? this.newline : '';
+  },
+  writeSpace: function() {
+    return (this.pretty) ? this.space : '';
+  },
+  serialize: {
+    '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('');
+    },
+    '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('');
+    },
+    '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 + '"';
+    },
+    'number': function(number) {
+      return isFinite(number) ? String(number) : "null";
+    },
+    'boolean': function(bool) {
+      return String(bool);
+    },
+    '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'
+});
+ZOO.Format.GeoJSON = ZOO.Class(ZOO.Format.JSON, {
+  initialize: function(options) {
+    ZOO.Format.JSON.prototype.initialize.apply(this, [options]);
+  },
+  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) {
+      //OpenLayers.Console.error("Bad JSON: " + json);
+    } else if(typeof(obj.type) != "string") {
+      //OpenLayers.Console.error("Bad GeoJSON - no type: " + json);
+    } else if(this.isValidType(obj, type)) {
+      switch(type) {
+        case "Geometry":
+          try {
+            results = this.parseGeometry(obj);
+          } catch(err) {
+            //OpenLayers.Console.error(err);
+          }
+          break;
+        case "Feature":
+          try {
+            results = this.parseFeature(obj);
+            results.type = "Feature";
+          } catch(err) {
+            //OpenLayers.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;
+                //OpenLayers.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;
+                  //OpenLayers.Console.error(err);
+                }
+              }
+              break;
+            default:
+              try {
+                var geom = this.parseGeometry(obj);
+                results.push(new ZOO.Feature(geom));
+              } catch(err) {
+                results = null;
+                //OpenLayers.Console.error(err);
+              }
+          }
+          break;
+      }
+    }
+    return results;
+  },
+  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
+          //OpenLayers.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 {
+          //OpenLayers.Console.error("Cannot convert types from " +obj.type + " to " + type);
+        }
+    }
+    return valid;
+  },
+  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;
+  },
+  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;
+  },
+  parseCoords: {
+    "point": function(array) {
+      if(array.length != 2) {
+        throw "Only 2D points are supported: " + array;
+      }
+      return new ZOO.Geometry.Point(array[0], array[1]);
+    },
+    "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);
+    },
+    "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);
+    },
+    "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);
+    },
+    "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);
+    },
+    "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);
+    },
+    "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])
+          ])
+      ]);
+    }
+  },
+  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]);
+  },
+  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;
+  },
+  extract: {
+    '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
+      };
+    },
+    '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;
+    },
+    'point': function(point) {
+      return [point.x, point.y];
+    },
+    '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;
+    },
+    '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;
+    },
+    '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;
+    },
+    '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;
+    },
+    '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;
+    },
+    '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'
+});
+ZOO.Format.KML = ZOO.Class(ZOO.Format, {
+  kmlns: "http://www.opengis.net/kml/2.2",
+  foldersName: "ZOO export",
+  foldersDesc: "Created on " + new Date(),
+  placemarksDesc: "No description available",
+  extractAttributes: true,
+  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)
+    };
+    ZOO.Format.prototype.initialize.apply(this, [options]);
+  },
+  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;
+  },
+  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);
+  },
+  parseFeature: function(node) {
+    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); 
+          }                       
+        }
+        break;
+      }
+    }
+    var attributes;
+    if(this.extractAttributes) {
+      attributes = this.parseAttributes(node);
+    }
+    var feature = new ZOO.Feature(geometry, attributes);
+    var fid = node.@id || node.@name;
+    if(fid != null)
+      feature.fid = fid;
+    return feature;
+  },
+  parseGeometry: {
+    '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;
+    },
+    '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;
+    },
+    '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);
+    },
+    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);
+    }
+  },
+  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;
+  },
+  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.@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;
+  },
+  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.appendChild(this.createPlacemarkXML(features[i]));
+      folder.Placemark[i] = this.createPlacemark(features[i]);
+    }
+    return kml.toXMLString();
+  },
+  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.@id = feature.fid;
+    placemark.*[2] = this.buildGeometryNode(feature.geometry);
+    return placemark;
+  },
+  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;
+  },
+  buildGeometry: {
+    'point': function(geometry) {
+      var kml = new XML('<Point xmlns="'+this.kmlns+'"></Point>');
+      kml.coordinates = this.buildCoordinatesNode(geometry);
+      return kml;
+    },
+    'multipoint': function(geometry) {
+      return this.buildGeometry.collection.apply(this, [geometry]);
+    },
+    'linestring': function(geometry) {
+      var kml = new XML('<LineString xmlns="'+this.kmlns+'"></LineString>');
+      kml.coordinates = this.buildCoordinatesNode(geometry);
+      return kml;
+    },
+    'multilinestring': function(geometry) {
+      return this.buildGeometry.collection.apply(this, [geometry]);
+    },
+    'linearring': function(geometry) {
+      var kml = new XML('<LinearRing xmlns="'+this.kmlns+'"></LinearRing>');
+      kml.coordinates = this.buildCoordinatesNode(geometry);
+      return kml;
+    },
+    '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;
+    },
+    'multipolygon': function(geometry) {
+      return this.buildGeometry.collection.apply(this, [geometry]);
+    },
+    '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;
+    }
+  },
+  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'
+});
+ZOO.Format.GML = ZOO.Class(ZOO.Format, {
+  schemaLocation: "http://www.opengis.net/gml http://schemas.opengis.net/gml/2.1.2/feature.xsd",
+  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
+  },
+  defaultPrefix: 'ogr',
+  collectionName: "FeatureCollection",
+  featureName: "sql_statement",
+  geometryName: "geometryProperty",
+  xy: true,
+  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]);
+  },
+  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;
+    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;
+  },
+  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); 
+          }                       
+        }
+        break;
+      }
+    }
+    var attributes;
+    if(this.extractAttributes) {
+      //attributes = this.parseAttributes(node);
+    }
+    var feature = new ZOO.Feature(geometry, attributes);
+    return feature;
+  },
+  parseGeometry: {
+    '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]);
+    },
+    '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);
+    },
+    '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].@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;
+    },
+    '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);
+    },
+    '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);
+    },
+    '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);
+    },
+    '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;
+    }
+  },
+  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.createFeatureXML(features[i]);
+    }
+    return gml.toXMLString();
+  },
+  createFeatureXML: 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;
+  },
+  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;
+  },
+  buildGeometry: {
+    'point': function(geometry) {
+      var gml = new XML('<gml:Point xmlns:gml="'+this.namespaces['gml']+'"></gml:Point>');
+      gml.*::*[0] = this.buildCoordinatesNode(geometry);
+      return gml;
+    },
+    '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;            
+    },
+    'linestring': function(geometry) {
+      var gml = new XML('<gml:LineString xmlns:gml="'+this.namespaces['gml']+'"></gml:LineString>');
+      gml.*::*[0] = this.buildCoordinatesNode(geometry);
+      return gml;
+    },
+    '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;            
+    },
+    'linearring': function(geometry) {
+      var gml = new XML('<gml:LinearRing xmlns:gml="'+this.namespaces['gml']+'"></gml:LinearRing>');
+      gml.*::*[0] = this.buildCoordinatesNode(geometry);
+      return gml;
+    },
+    '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;
+    },
+    '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;            
+    },
+    'bounds': function(bounds) {
+      var gml = new XML('<gml:Box xmlns:gml="'+this.namespaces['gml']+'"></gml:Box>');
+      gml.*::*[0] = this.buildCoordinatesNode(bounds);
+      return gml;
+    }
+  },
+  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'
+});
+ZOO.Format.WPS = ZOO.Class(ZOO.Format, {
+  schemaLocation: "http://www.opengis.net/wps/1.0.0/../wpsExecute_request.xsd",
+  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",
+  },
+  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;
+    }
+  },
+  parseExecuteResponse: function(node) {
+    var outputs = node.*::ProcessOutputs.*::Output;
+    if (outputs.length() > 0) {
+      var data = outputs[0].*::Data.*::*[0];
+      var builder = this.parseData[data.localName().toLowerCase()];
+      if (builder)
+        return builder.apply(this,[data]);
+      else
+        return null;
+    } else
+      return null;
+  },
+  parseData: {
+    'complexdata': function(node) {
+      var result = {value:node.toString()};
+      if (node.@mimeType.length()>0)
+        result.mimeType = node.@mimeType;
+      if (node.@encoding.length()>0)
+        result.encoding = node.@encoding;
+      if (node.@schema.length()>0)
+        result.schema = node.@schema;
+      return result;
+    },
+    'literaldata': function(node) {
+      var result = {value:node.toString()};
+      if (node.@dataType.length()>0)
+        result.dataType = node.@dataType;
+      if (node.@uom.length()>0)
+        result.uom = node.@uom;
+      return result;
+    }
+  },
+  CLASS_NAME: 'ZOO.Format.WPS'
+});
+
+
+ZOO.Feature = ZOO.Class({
+  fid: null,
+  geometry: null,
+  attributes: null,
+  bounds: null,
+  initialize: function(geometry, attributes) {
+    this.geometry = geometry ? geometry : null;
+    this.attributes = {};
+    if (attributes)
+      this.attributes = ZOO.extend(this.attributes,attributes);
+  },
+  destroy: function() {
+    this.geometry = null;
+  },
+  clone: function () {
+    return new ZOO.Feature(this.geometry ? this.geometry.clone() : null,
+            this.attributes);
+  },
+  move: function(x, y) {
+    if(!this.geometry.move)
+      return;
+
+    this.geometry.move(x,y);
+    return this.geometry;
+  },
+  CLASS_NAME: 'ZOO.Feature'
+});
+
+ZOO.Geometry = ZOO.Class({
+  id: null,
+  parent: null,
+  bounds: null,
+  initialize: function() {
+    //generate unique id
+  },
+  destroy: function() {
+    this.id = null;
+    this.bounds = null;
+  },
+  clone: function() {
+    return new ZOO.Geometry();
+  },
+  extendBounds: function(newBounds){
+    var bounds = this.getBounds();
+    if (!bounds)
+      this.setBounds(newBounds);
+    else
+      this.bounds.extend(newBounds);
+  },
+  setBounds: function(bounds) {
+    if (bounds)
+      this.bounds = bounds.clone();
+  },
+  clearBounds: function() {
+    this.bounds = null;
+    if (this.parent)
+      this.parent.clearBounds();
+  },
+  getBounds: function() {
+    if (this.bounds == null) {
+      this.calculateBounds();
+    }
+    return this.bounds;
+  },
+  calculateBounds: function() {
+    return this.bounds = null;
+  },
+  distanceTo: function(geometry, options) {
+  },
+  getVertices: function(nodes) {
+  },
+  getLength: function() {
+    return 0.0;
+  },
+  getArea: function() {
+    return 0.0;
+  },
+  getCentroid: function() {
+    return null;
+  },
+  toString: function() {
+    return ZOO.Format.WKT.prototype.write(
+        new ZOO.Feature(this)
+    );
+  },
+  CLASS_NAME: 'ZOO.Geometry'
+});
+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
+  };
+};
+ZOO.Geometry.Collection = ZOO.Class(ZOO.Geometry, {
+  components: null,
+  componentTypes: null,
+  initialize: function (components) {
+    ZOO.Geometry.prototype.initialize.apply(this, arguments);
+    this.components = [];
+    if (components != null) {
+      this.addComponents(components);
+    }
+  },
+  destroy: function () {
+    this.components.length = 0;
+    this.components = null;
+  },
+  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;
+  },
+  getComponentsString: function(){
+    var strings = [];
+    for(var i=0, len=this.components.length; i<len; i++) {
+      strings.push(this.components[i].toShortString()); 
+    }
+    return strings.join(",");
+  },
+  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
+  },
+  addComponents: function(components){
+    if(!(components instanceof Array))
+      components = [components];
+    for(var i=0, len=components.length; i<len; i++) {
+      this.addComponent(components[i]);
+    }
+  },
+  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;
+  },
+  removeComponents: function(components) {
+    if(!(components instanceof Array))
+      components = [components];
+    for(var i=components.length-1; i>=0; --i) {
+      this.removeComponent(components[i]);
+    }
+  },
+  removeComponent: function(component) {      
+    ZOO.removeItem(this.components, component);
+    // clearBounds() so that it gets recalculated on the next call
+    // to this.getBounds();
+    this.clearBounds();
+  },
+  getLength: function() {
+    var length = 0.0;
+    for (var i=0, len=this.components.length; i<len; i++) {
+      length += this.components[i].getLength();
+    }
+    return length;
+  },
+  getArea: function() {
+    var area = 0.0;
+    for (var i=0, len=this.components.length; i<len; i++) {
+      area += this.components[i].getArea();
+    }
+    return area;
+  },
+  getCentroid: function() {
+    return this.components.length && this.components[0].getCentroid();
+  },
+  move: function(x, y) {
+    for(var i=0, len=this.components.length; i<len; i++) {
+      this.components[i].move(x, y);
+    }
+  },
+  rotate: function(angle, origin) {
+    for(var i=0, len=this.components.length; i<len; ++i) {
+      this.components[i].rotate(angle, origin);
+    }
+  },
+  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;
+  },
+  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;
+  },
+  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;
+  },
+  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;
+  },
+  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'
+});
+ZOO.Geometry.Point = ZOO.Class(ZOO.Geometry, {
+  x: null,
+  y: null,
+  initialize: function(x, y) {
+    ZOO.Geometry.prototype.initialize.apply(this, arguments);
+    this.x = parseFloat(x);
+    this.y = parseFloat(y);
+  },
+  clone: function(obj) {
+    if (obj == null)
+      obj = new ZOO.Geometry.Point(this.x, this.y);
+    // catch any randomly tagged-on properties
+    //OpenLayers.Util.applyDefaults(obj, this);
+    return obj;
+  },
+  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;
+  },
+  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;
+  },
+  toShortString: function() {
+    return (this.x + ", " + this.y);
+  },
+  move: function(x, y) {
+    this.x = this.x + x;
+    this.y = this.y + y;
+    this.clearBounds();
+  },
+  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();
+  },
+  getCentroid: function() {
+    return new ZOO.Geometry.Point(this.x, this.y);
+  },
+  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;
+  },
+  intersects: function(geometry) {
+    var intersect = false;
+    if(geometry.CLASS_NAME == "ZOO.Geometry.Point") {
+      intersect = this.equals(geometry);
+    } else {
+      intersect = geometry.intersects(this);
+    }
+    return intersect;
+  },
+  transform: function(source, dest) {
+    if ((source && dest)) {
+      ZOO.Projection.transform(
+          this, source, dest); 
+      this.bounds = null;
+    }       
+    return this;
+  },
+  getVertices: function(nodes) {
+    return [this];
+  },
+  CLASS_NAME: 'ZOO.Geometry.Point'
+});
+ZOO.Geometry.Surface = ZOO.Class(ZOO.Geometry, {
+  initialize: function() {
+    ZOO.Geometry.prototype.initialize.apply(this, arguments);
+  },
+  CLASS_NAME: "ZOO.Geometry.Surface"
+});
+ZOO.Geometry.MultiPoint = ZOO.Class(
+  ZOO.Geometry.Collection, {
+  componentTypes: ["ZOO.Geometry.Point"],
+  initialize: function(components) {
+    ZOO.Geometry.Collection.prototype.initialize.apply(this,arguments);
+  },
+  addPoint: function(point, index) {
+    this.addComponent(point, index);
+  },
+  removePoint: function(point){
+    this.removeComponent(point);
+  },
+  CLASS_NAME: "ZOO.Geometry.MultiPoint"
+});
+ZOO.Geometry.Curve = ZOO.Class(ZOO.Geometry.MultiPoint, {
+  componentTypes: ["ZOO.Geometry.Point"],
+  initialize: function(points) {
+    ZOO.Geometry.MultiPoint.prototype.initialize.apply(this,arguments);
+  },
+  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;
+  },
+  CLASS_NAME: "ZOO.Geometry.Curve"
+});
+ZOO.Geometry.LineString = ZOO.Class(ZOO.Geometry.Curve, {
+  initialize: function(points) {
+    ZOO.Geometry.Curve.prototype.initialize.apply(this, arguments);        
+  },
+  removeComponent: function(point) {
+    if ( this.components && (this.components.length > 2))
+      ZOO.Geometry.Collection.prototype.removeComponent.apply(this,arguments);
+  },
+  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;
+  },
+  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);
+  },
+  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;
+  },
+  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;
+  },
+  splitWith: function(geometry, options) {
+    return geometry.split(this, options);
+  },
+  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"
+});
+ZOO.Geometry.LinearRing = ZOO.Class(
+  ZOO.Geometry.LineString, {
+  componentTypes: ["ZOO.Geometry.Point"],
+  initialize: function(points) {
+    ZOO.Geometry.LineString.prototype.initialize.apply(this,arguments);
+  },
+  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;
+  },
+  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]);
+    }
+  },
+  move: function(x, y) {
+    for(var i = 0, len=this.components.length; i<len - 1; i++) {
+      this.components[i].move(x, y);
+    }
+  },
+  rotate: function(angle, origin) {
+    for(var i=0, len=this.components.length; i<len - 1; ++i) {
+      this.components[i].rotate(angle, origin);
+    }
+  },
+  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;
+  },
+  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;
+  },
+  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);
+  },
+  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;
+  },
+  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"
+});
+ZOO.Geometry.MultiLineString = ZOO.Class(
+  ZOO.Geometry.Collection, {
+  componentTypes: ["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"
+});
+ZOO.Geometry.Polygon = ZOO.Class(
+  ZOO.Geometry.Collection, {
+  componentTypes: ["ZOO.Geometry.LinearRing"],
+  initialize: function(components) {
+    ZOO.Geometry.Collection.prototype.initialize.apply(this,arguments);
+  },
+  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;
+  },
+  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"
+});
+ZOO.Geometry.MultiPolygon = ZOO.Class(
+  ZOO.Geometry.Collection, {
+  componentTypes: ["ZOO.Geometry.Polygon"],
+  initialize: function(components) {
+    ZOO.Geometry.Collection.prototype.initialize.apply(this,arguments);
+  },
+  CLASS_NAME: "ZOO.Geometry.MultiPolygon"
+});
+
+ZOO.Process = ZOO.Class({
+  schemaLocation: "http://www.opengis.net/wps/1.0.0/../wpsExecute_request.xsd",
+  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",
+  },
+  url: 'http://localhost/zoo',
+  identifier: null,
+  initialize: function(url,identifier) {
+    this.url = url;
+    this.identifier = identifier;
+  },
+  Execute: function(inputs) {
+    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)+'</wps:Execute>');
+    body = body.toXMLString();
+    var response = ZOO.Request.Post(this.url,body,['Content-Type: text/xml; charset=UTF-8']);
+    return response;
+  },
+  buildInput: {
+    '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><wps:Data><wps:ComplexData>'+data.value+'</wps:ComplexData></wps:Data></wps:Input>');
+      input.*::Data.*::ComplexData.@mimeType = data.mimetype ? data.mimetype : 'text/plain';
+      if (data.encoding)
+        input.*::Data.*::ComplexData.@encoding = data.encoding;
+      if (data.schema)
+        input.*::Data.*::ComplexData.@schema = data.schema;
+      input = input.toXMLString();
+      return input;
+    },
+    '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('&','&amp;','gi')+'"/></wps:Input>';
+    },
+    'literal': function(identifier,data) {
+      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.@dataType = data.type;
+      if (data.uom)
+        input.*::Data.*::LiteralData.@uom = data.uom;
+      input = input.toXMLString();
+      return input;
+    }
+  },
+  buildDataInputsNode:function(inputs){
+    var data, builder, inputsArray=[];
+    for (var attr in inputs) {
+      data = inputs[attr];
+      if (data.mimetype || data.type == 'complex')
+        builder = this.buildInput['complex'];
+      else if (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>';
+  },
+  CLASS_NAME: "ZOO.Process"
+});
Index: trunk/zoo-api/js/ZOO-proj4js.js
===================================================================
--- trunk/zoo-api/js/ZOO-proj4js.js	(revision 1)
+++ trunk/zoo-api/js/ZOO-proj4js.js	(revision 1)
@@ -0,0 +1,262 @@
+/**
+ * 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.
+ */
+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=document.getElementsByTagName('script');for(var i=0;i<scripts.length;i++){var src=scripts[i].getAttribute('src');if(src){var index=src.lastIndexOf(scriptName);if((index>-1)&&(index+scriptNameLen==src.length)){this.libPath=src.slice(0,-scriptNameLen);break;}}}
+return this.libPath||"";},
+  loadScript:function(url,onload,onfail,loadCheck){
+  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=srsCode.split('#');if(url[0].match(/epsg.org/)){srsCode='EPSG:'+url[1];}else if(url[0].match(/RIG.xml/)){srsCode='IGNF:'+url[1];}}
+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 definition for: '+this.srsCode);Proj4js.defs[this.srsCode]=Proj4js.defs['WGS84'];this.defsLoaded();},
+  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:function(){this.defData=Proj4js.defs[this.srsCode];var paramName,paramVal;if(!this.defData){return;}
+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(/\s/gi,"");break;case"ellps":this.ellps=paramVal.replace(/\s/gi,"");break;case"a":this.a=parseFloat(paramVal);break;case"b":this.b=parseFloat(paramVal);break;case"rf":this.rf=parseFloat(paramVal);break;case"lat_0":this.lat0=paramVal*Proj4js.common.D2R;break;case"lat_1":this.lat1=paramVal*Proj4js.common.D2R;break;case"lat_2":this.lat2=paramVal*Proj4js.common.D2R;break;case"lat_ts":this.lat_ts=paramVal*Proj4js.common.D2R;break;case"lon_0":this.long0=paramVal*Proj4js.common.D2R;break;case"alpha":this.alpha=parseFloat(paramVal)*Proj4js.common.D2R;break;case"lonc":this.longc=paramVal*Proj4js.common.D2R;break;case"x_0":this.x0=parseFloat(paramVal);break;case"y_0":this.y0=parseFloat(paramVal);break;case"k_0":this.k0=parseFloat(paramVal);break;case"k":this.k0=parseFloat(paramVal);break;case"r_a":this.R_A=true;break;case"zone":this.zone=parseInt(paramVal);break;case"south":this.utmSouth=true;break;case"towgs84":this.datum_params=paramVal.split(",");break;case"to_meter":this.to_meter=parseFloat(paramVal);break;case"from_greenwich":this.from_greenwich=paramVal*Proj4js.common.D2R;break;case"pm":paramVal=paramVal.replace(/\s/gi,"");this.from_greenwich=Proj4js.PrimeMeridian[paramVal]?Proj4js.PrimeMeridian[paramVal]:parseFloat(paramVal);this.from_greenwich*=Proj4js.common.D2R;break;case"no_defs":break;default:}}
+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 +b=6356752.31414036 +ellps=GRS80 +datum=NAD83 +units=degrees",'EPSG:3785':"+title= Google Mercator +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['GOOGLE']=Proj4js.defs['EPSG:3785'];Proj4js.defs['EPSG:900913']=Proj4js.defs['EPSG:3785'];Proj4js.defs['EPSG:102113']=Proj4js.defs['EPSG:3785'];Proj4js.common={PI:3.141592653589793238,HALF_PI:1.570796326794896619,TWO_PI:6.283185307179586477,FORTPI:0.78539816339744833,R2D:57.29577951308232088,D2R:0.01745329251994329577,SEC_TO_RAD:4.84813681109535993589914102357e-6,EPSLN:1.0e-10,MAX_ITER:20,COS_67P5:0.38268343236508977,AD_C:1.0026000,PJD_UNKNOWN:0,PJD_3PARAM:1,PJD_7PARAM:2,PJD_GRIDSHIFT:3,PJD_WGS84:4,PJD_NODATUM:5,SRS_WGS84_SEMIMAJOR:6378137.0,SIXTH:.1666666666666666667,RA4:.04722222222222222222,RA6:.02215608465608465608,RV4:.06944444444444444444,RV6:.04243827160493827160,msfnz:function(eccent,sinphi,cosphi){var con=eccent*sinphi;return cosphi/(Math.sqrt(1.0-con*con));},tsfnz:function(eccent,phi,sinphi){var con=eccent*sinphi;var com=.5*eccent;con=Math.pow(((1.0-con)/(1.0+con)),com);return(Math.tan(.5*(this.HALF_PI-phi))/con);},phi2z:function(eccent,ts){var eccnth=.5*eccent;var con,dphi;var phi=this.HALF_PI-2*Math.atan(ts);for(i=0;i<=15;i++){con=eccent*Math.sin(phi);dphi=this.HALF_PI-2*Math.atan(ts*(Math.pow(((1.0-con)/(1.0+con)),eccnth)))-phi;phi+=dphi;if(Math.abs(dphi)<=.0000000001)return phi;}
+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);},adjust_lon:function(x){x=(Math.abs(x)<this.PI)?x:(x-(this.sign(x)*this.TWO_PI));return x;},adjust_lat:function(x){x=(Math.abs(x)<this.HALF_PI)?x:(x-(this.sign(x)*this.PI));return x;},latiso:function(eccent,phi,sinphi){if(Math.abs(phi)>this.HALF_PI)return+Number.NaN;if(phi==this.HALF_PI)return Number.POSITIVE_INFINITY;if(phi==-1.0*this.HALF_PI)return-1.0*Number.POSITIVE_INFINITY;var con=eccent*sinphi;return Math.log(Math.tan((this.HALF_PI+phi)/2.0))+eccent*Math.log((1.0-con)/(1.0+con))/2.0;},fL:function(x,L){return 2.0*Math.atan(x*Math.exp(L))-this.HALF_PI;},invlatiso:function(eccent,ts){var phi=this.fL(1.0,ts);var Iphi=0.0;var con=0.0;do{Iphi=phi;con=eccent*Math.sin(Iphi);phi=this.fL(Math.exp(eccent*Math.log((1.0+con)/(1.0-con))/2.0),ts)}while(Math.abs(phi-Iphi)>1.0e-12);return phi;},sinh:function(x)
+{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==Proj4js.common.PJD_7PARAM){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]&&this.datum_params[3]==dest.datum_params[3]&&this.datum_params[4]==dest.datum_params[4]&&this.datum_params[5]==dest.datum_params[5]&&this.datum_params[6]==dest.datum_params[6]);}else if(this.datum_type==Proj4js.common.PJD_GRIDSHIFT){return strcmp(pj_param(this.params,"snadgrids").s,pj_param(dest.params,"snadgrids").s)==0;}else{return true;}},geodetic_to_geocentric:function(p){var Longitude=p.x;var Latitude=p.y;var Height=p.z?p.z:0;var X;var Y;var Z;var Error_Code=0;var Rn;var Sin_Lat;var Sin2_Lat;var Cos_Lat;if(Latitude<-Proj4js.common.HALF_PI&&Latitude>-1.001*Proj4js.common.HALF_PI){Latitude=-Proj4js.common.HALF_PI;}else if(Latitude>Proj4js.common.HALF_PI&&Latitude<1.001*Proj4js.common.HALF_PI){Latitude=Proj4js.common.HALF_PI;}else if((Latitude<-Proj4js.common.HALF_PI)||(Latitude>Proj4js.common.HALF_PI)){Proj4js.reportError('geocent:lat out of range:'+Latitude);return null;}
+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 CPHI0;var SPHI0;var CPHI;var SPHI;var SDPHI;var At_Pole;var iter;var X=p.x;var Y=p.y;var Z=p.z?p.z:0.0;var Longitude;var Latitude;var Height;At_Pole=false;P=Math.sqrt(X*X+Y*Y);RR=Math.sqrt(X*X+Y*Y+Z*Z);if(P/this.a<genau){At_Pole=true;Longitude=0.0;if(RR/this.a<genau){Latitude=Proj4js.common.HALF_PI;Height=-this.b;return;}}else{Longitude=Math.atan2(Y,X);}
+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=x[0];this.y=x[1];this.z=x[2]||0.0;}else if(typeof x=='string'){var coords=x.split(',');this.x=parseFloat(coords[0]);this.y=parseFloat(coords[1]);this.z=parseFloat(coords[2])||0.0;}else{this.x=x;this.y=y;this.z=z||0.0;}},clone:function(){return new Proj4js.Point(this.x,this.y,this.z);},toString:function(){return("x="+this.x+",y="+this.y);},toShortString:function(){return(this.x+", "+this.y);}});Proj4js.PrimeMeridian={"greenwich":0.0,"lisbon":-9.131906111111,"paris":2.337229166667,"bogota":-74.080916666667,"madrid":-3.687938888889,"rome":12.452333333333,"bern":7.439583333333,"jakarta":106.807719444444,"ferro":-17.666666666667,"brussels":4.367975,"stockholm":18.058277777778,"athens":23.7163375,"oslo":10.722916666667};Proj4js.Ellipsoid={"MERIT":{a:6378137.0,rf:298.257,ellipseName:"MERIT 1983"},"SGS85":{a:6378136.0,rf:298.257,ellipseName:"Soviet Geodetic System 85"},"GRS80":{a:6378137.0,rf:298.257222101,ellipseName:"GRS 1980(IUGG, 1980)"},"IAU76":{a:6378140.0,rf:298.257,ellipseName:"IAU 1976"},"airy":{a:6377563.396,b:6356256.910,ellipseName:"Airy 1830"},"APL4.":{a:6378137,rf:298.25,ellipseName:"Appl. Physics. 1965"},"NWL9D":{a:6378145.0,rf:298.25,ellipseName:"Naval Weapons Lab., 1965"},"mod_airy":{a:6377340.189,b:6356034.446,ellipseName:"Modified Airy"},"andrae":{a:6377104.43,rf:300.0,ellipseName:"Andrae 1876 (Den., Iclnd.)"},"aust_SA":{a:6378160.0,rf:298.25,ellipseName:"Australian Natl & S. Amer. 1969"},"GRS67":{a:6378160.0,rf:298.2471674270,ellipseName:"GRS 67(IUGG 1967)"},"bessel":{a:6377397.155,rf:299.1528128,ellipseName:"Bessel 1841"},"bess_nam":{a:6377483.865,rf:299.1528128,ellipseName:"Bessel 1841 (Namibia)"},"clrk66":{a:6378206.4,b:6356583.8,ellipseName:"Clarke 1866"},"clrk80":{a:6378249.145,rf:293.4663,ellipseName:"Clarke 1880 mod."},"CPM":{a:6375738.7,rf:334.29,ellipseName:"Comm. des Poids et Mesures 1799"},"delmbr":{a:6376428.0,rf:311.5,ellipseName:"Delambre 1810 (Belgium)"},"engelis":{a:6378136.05,rf:298.2566,ellipseName:"Engelis 1985"},"evrst30":{a:6377276.345,rf:300.8017,ellipseName:"Everest 1830"},"evrst48":{a:6377304.063,rf:300.8017,ellipseName:"Everest 1948"},"evrst56":{a:6377301.243,rf:300.8017,ellipseName:"Everest 1956"},"evrst69":{a:6377295.664,rf:300.8017,ellipseName:"Everest 1969"},"evrstSS":{a:6377298.556,rf:300.8017,ellipseName:"Everest (Sabah & Sarawak)"},"fschr60":{a:6378166.0,rf:298.3,ellipseName:"Fischer (Mercury Datum) 1960"},"fschr60m":{a:6378155.0,rf:298.3,ellipseName:"Fischer 1960"},"fschr68":{a:6378150.0,rf:298.3,ellipseName:"Fischer 1968"},"helmert":{a:6378200.0,rf:298.3,ellipseName:"Helmert 1906"},"hough":{a:6378270.0,rf:297.0,ellipseName:"Hough"},"intl":{a:6378388.0,rf:297.0,ellipseName:"International 1909 (Hayford)"},"kaula":{a:6378163.0,rf:298.24,ellipseName:"Kaula 1961"},"lerch":{a:6378139.0,rf:298.257,ellipseName:"Lerch 1979"},"mprts":{a:6397300.0,rf:191.0,ellipseName:"Maupertius 1738"},"new_intl":{a:6378157.5,b:6356772.2,ellipseName:"New International 1967"},"plessis":{a:6376523.0,rf:6355863.0,ellipseName:"Plessis 1817 (France)"},"krass":{a:6378245.0,rf:298.3,ellipseName:"Krassovsky, 1942"},"SEasia":{a:6378155.0,b:6356773.3205,ellipseName:"Southeast Asia"},"walbeck":{a:6376896.0,b:6355834.8467,ellipseName:"Walbeck"},"WGS60":{a:6378165.0,rf:298.3,ellipseName:"WGS 60"},"WGS66":{a:6378145.0,rf:298.25,ellipseName:"WGS 66"},"WGS72":{a:6378135.0,rf:298.26,ellipseName:"WGS 72"},"WGS84":{a:6378137.0,rf:298.257223563,ellipseName:"WGS 84"},"sphere":{a:6370997.0,b:6370997.0,ellipseName:"Normal Sphere (r=6370997)"}};Proj4js.Datum={"WGS84":{towgs84:"0,0,0",ellipse:"WGS84",datumName:"WGS84"},"GGRS87":{towgs84:"-199.87,74.79,246.62",ellipse:"GRS80",datumName:"Greek_Geodetic_Reference_System_1987"},"NAD83":{towgs84:"0,0,0",ellipse:"GRS80",datumName:"North_American_Datum_1983"},"NAD27":{nadgrids:"@conus,@alaska,@ntv2_0.gsb,@ntv1_can.dat",ellipse:"clrk66",datumName:"North_American_Datum_1927"},"potsdam":{towgs84:"606.0,23.0,413.0",ellipse:"bessel",datumName:"Potsdam Rauenberg 1950 DHDN"},"carthage":{towgs84:"-263.0,6.0,431.0",ellipse:"clark80",datumName:"Carthage 1934 Tunisia"},"hermannskogel":{towgs84:"653.0,-212.0,449.0",ellipse:"bessel",datumName:"Hermannskogel"},"ire65":{towgs84:"482.530,-130.596,564.557,-1.042,-0.214,-0.631,8.15",ellipse:"mod_airy",datumName:"Ireland 1965"},"nzgd49":{towgs84:"59.47,-5.04,187.44,0.47,-0.1,1.024,-4.5993",ellipse:"intl",datumName:"New Zealand Geodetic Datum 1949"},"OSGB36":{towgs84:"446.448,-125.157,542.060,0.1502,0.2470,0.8421,-20.4894",ellipse:"airy",datumName:"Airy 1830"}};Proj4js.WGS84=new Proj4js.Proj('WGS84');Proj4js.Datum['OSB36']=Proj4js.Datum['OSGB36'];Proj4js.Proj.aea={init:function(){if(Math.abs(this.lat1+this.lat2)<Proj4js.common.EPSLN){Proj4js.reportError("aeaInitEqualLatitudes");return;}
+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.e3,this.sin_po,this.cos_po);this.sin_po=Math.sin(this.lat0);this.cos_po=Math.cos(this.lat0);this.t3=this.sin_po;this.qs0=Proj4js.common.qsfnz(this.e3,this.sin_po,this.cos_po);if(Math.abs(this.lat1-this.lat2)>Proj4js.common.EPSLN){this.ns0=(this.ms1*this.ms1-this.ms2*this.ms2)/(this.qs2-this.qs1);}else{this.ns0=this.con;}
+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:function(p){var rh1,qs,con,theta,lon,lat;p.x-=this.x0;p.y=this.rh-p.y+this.y0;if(this.ns0>=0){rh1=Math.sqrt(p.x*p.x+p.y*p.y);con=1.0;}else{rh1=-Math.sqrt(p.x*p.x+p.y*p.y);con=-1.0;}
+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.y0;return p;},inverse:function(p){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((rho=Math.sqrt(p.x*p.x+p.y*p.y))){c=2.0*Math.atan2(rho,this.R2);sinc=Math.sin(c);cosc=Math.cos(c);lat=Math.asin(cosc*this.sinc0+p.y*sinc*this.cosc0/rho);lon=Math.atan2(p.x*sinc,rho*this.cosc0*cosc-p.y*this.sinc0*sinc);}else{lat=this.phic0;lon=0.;}
+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.0*phi);con1=2.0*ml+c*(ml*ml+b)-2.0*a*(c*ml+1.0);con2=eccent*sin2ph*(ml*ml+b-2.0*a*ml)/(2.0*c);con3=2.0*(a-ml)*(c*mlp-2.0/sin2ph)-2.0*mlp;dphi=con1/(con2+con3);phi+=dphi;if(Math.abs(dphi)<=.0000000001)return(phi);}
+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.common.adjust_lon(lon-this.long0);if(Math.abs(lat)<=.0000001){x=this.x0+this.a*con;y=this.y0-this.a*this.ml0;}else{sinphi=Math.sin(lat);cosphi=Math.cos(lat);ml=Proj4js.common.mlfn(this.e0,this.e1,this.e2,this.e3,lat);ms=Proj4js.common.msfnz(this.e,sinphi,cosphi);con=sinphi;x=this.x0+this.a*ms*Math.sin(con)/sinphi;y=this.y0+this.a*(ml-this.ml0+ms*(1.0-Math.cos(con))/sinphi);}
+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_PI){Proj4js.reportError("equi:Inv:DataError");}
+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: llInputOutOfRange: "+lon+" : "+lat);return null;}
+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);this.e2=Proj4js.common.e2fn(this.es);this.e3=Proj4js.common.e3fn(this.es);this.sinphi=Math.sin(this.lat1);this.cosphi=Math.cos(this.lat1);this.ms1=Proj4js.common.msfnz(this.e,this.sinphi,this.cosphi);this.ml1=Proj4js.common.mlfn(this.e0,this.e1,this.e2,this.e3,this.lat1);if(this.mode!=0){if(Math.abs(this.lat1+this.lat2)<Proj4js.common.EPSLN){Proj4js.reportError("eqdc:Init:EqualLatitudes");}
+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;var con,rh1;if(this.ns>=0){var rh1=Math.sqrt(p.x*p.x+p.y*p.y);var con=1.0;}else{rh1=-Math.sqrt(p.x*p.x+p.y*p.y);con=-1.0;}
+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=Math.sin(lat);var cos_phi=Math.cos(lat);if(this.sphere){var b=cos_phi*Math.sin(delta_lon);if((Math.abs(Math.abs(b)-1.0))<.0000000001){Proj4js.reportError("tmerc:forward: Point projects into infinity");return(93);}else{x=.5*this.a*this.k0*Math.log((1.0+b)/(1.0-b));con=Math.acos(cos_phi*Math.cos(delta_lon)/Math.sqrt(1.0-b*b));if(lat<0)con=-con;y=this.a*this.k0*(con-this.lat0);}}else{var al=cos_phi*delta_lon;var als=Math.pow(al,2);var c=this.ep2*Math.pow(cos_phi,2);var tq=Math.tan(lat);var t=Math.pow(tq,2);con=1.0-this.es*Math.pow(sin_phi,2);var n=this.a/Math.sqrt(con);var ml=this.a*Proj4js.common.mlfn(this.e0,this.e1,this.e2,this.e3,lat);x=this.k0*n*al*(1.0+als/6.0*(1.0-t+c+als/20.0*(5.0-18.0*t+Math.pow(t,2)+72.0*c-58.0*this.ep2)))+this.x0;y=this.k0*(ml-this.ml0+n*tq*(als*(0.5+als/24.0*(5.0-t+9.0*c+4.0*Math.pow(c,2)+als/30.0*(61.0-58.0*t+Math.pow(t,2)+600.0*c-330.0*this.ep2)))))+this.y0;}
+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)));lon=Proj4js.common.adjust_lon(this.long0+(d*(1.0-ds/6.0*(1.0+2.0*t+c-ds/20.0*(5.0-2.0*c+28.0*t-3.0*cs+8.0*this.ep2+24.0*ts)))/cos_phi));}else{lat=Proj4js.common.HALF_PI*Proj4js.common.sign(y);lon=this.long0;}}
+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=Math.sin(pc);this.cp=Proj4js.common.latiso(0.0,pc,sinzpc)-this.rs*Proj4js.common.latiso(this.e,this.lat0,sinz);this.n2=this.k0*this.a*Math.sqrt(1.0-this.e*this.e)/(1.0-this.e*this.e*sinz*sinz);this.xs=this.x0;this.ys=this.y0-this.n2*pc;if(!this.title)this.title="Gauss Schreiber transverse mercator";},forward:function(p){var lon=p.x;var lat=p.y;var L=this.rs*(lon-this.lc);var Ls=this.cp+(this.rs*Proj4js.common.latiso(this.e,lat,Math.sin(lat)));var lat1=Math.asin(Math.sin(L)/Proj4js.common.cosh(Ls));var Ls1=Proj4js.common.latiso(0.0,lat1,Math.sin(lat1));p.x=this.xs+(this.n2*Ls1);p.y=this.ys+(this.n2*Math.atan(Proj4js.common.sinh(Ls)/Math.cos(L)));return p;},inverse:function(p){var x=p.x;var y=p.y;var L=Math.atan(Proj4js.common.sinh((x-this.xs)/this.n2)/Math.cos((y-this.ys)/this.n2));var lat1=Math.asin(Math.sin((y-this.ys)/this.n2)/Proj4js.common.cosh((x-this.xs)/this.n2));var LC=Proj4js.common.latiso(0.0,lat1,Math.sin(lat1));p.x=this.lc+L/this.rs;p.y=Proj4js.common.invlatiso(this.e,(LC-this.cp)/this.rs);return p;}};Proj4js.Proj.ortho={init:function(def){;this.sin_p14=Math.sin(this.lat0);this.cos_p14=Math.cos(this.lat0);},forward:function(p){var sinphi,cosphi;var dlon;var coslon;var ksp;var g;var lon=p.x;var lat=p.y;dlon=Proj4js.common.adjust_lon(lon-this.long0);sinphi=Math.sin(lat);cosphi=Math.cos(lat);coslon=Math.cos(dlon);g=this.sin_p14*sinphi+this.cos_p14*cosphi*coslon;ksp=1.0;if((g>0)||(Math.abs(g)<=Proj4js.common.EPSLN)){var x=this.a*ksp*cosphi*Math.sin(dlon);var y=this.y0+this.a*ksp*(this.cos_p14*sinphi-this.sin_p14*cosphi*coslon);}else{Proj4js.reportError("orthoFwdPointError");}
+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>Proj4js.common.EPSLN?this.OBLIQ:this.EQUIT;}
+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-Proj4js.common.HALF_PI)>=Proj4js.common.EPSLN?Math.cos(this.phits)/Math.tan(Proj4js.common.FORTPI-.5*this.phits):2.*this.k0;break;}}},forward:function(p){var lon=p.x;lon=Proj4js.common.adjust_lon(lon-this.long0);var lat=p.y;var x,y;if(this.sphere){var sinphi,cosphi,coslam,sinlam;sinphi=Math.sin(lat);cosphi=Math.cos(lat);coslam=Math.cos(lon);sinlam=Math.sin(lon);switch(this.mode){case this.EQUIT:y=1.+cosphi*coslam;if(y<=Proj4js.common.EPSLN){F_ERROR;}
+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]=-0.0055161;this.A[7]=+0.0026906;this.A[8]=-0.001333;this.A[9]=+0.00067;this.A[10]=-0.00034;this.B_re=new Array();this.B_im=new Array();this.B_re[1]=+0.7557853228;this.B_im[1]=0.0;this.B_re[2]=+0.249204646;this.B_im[2]=+0.003371507;this.B_re[3]=-0.001541739;this.B_im[3]=+0.041058560;this.B_re[4]=-0.10162907;this.B_im[4]=+0.01727609;this.B_re[5]=-0.26623489;this.B_im[5]=-0.36249218;this.B_re[6]=-0.6870983;this.B_im[6]=-1.1651967;this.C_re=new Array();this.C_im=new Array();this.C_re[1]=+1.3231270439;this.C_im[1]=0.0;this.C_re[2]=-0.577245789;this.C_im[2]=-0.007809598;this.C_re[3]=+0.508307513;this.C_im[3]=-0.112208952;this.C_re[4]=-0.15094762;this.C_im[4]=+0.18200602;this.C_re[5]=+1.01418179;this.C_im[5]=+1.64497696;this.C_re[6]=+1.9660549;this.C_im[6]=+2.5127645;this.D=new Array();this.D[1]=+1.5627014243;this.D[2]=+0.5185406398;this.D[3]=-0.03333098;this.D[4]=-0.1052906;this.D[5]=-0.0368594;this.D[6]=+0.007317;this.D[7]=+0.01220;this.D[8]=+0.00394;this.D[9]=-0.0013;},forward:function(p){var lon=p.x;var lat=p.y;var delta_lat=lat-this.lat0;var delta_lon=lon-this.long0;var d_phi=delta_lat/Proj4js.common.SEC_TO_RAD*1E-5;var d_lambda=delta_lon;var d_phi_n=1;var d_psi=0;for(n=1;n<=10;n++){d_phi_n=d_phi_n*d_phi;d_psi=d_psi+this.A[n]*d_phi_n;}
+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*(Math.atan(Math.exp(0.8*p.y/this.a))-Proj4js.common.PI/4.0);p.x=lon;p.y=lat;return p;}};Proj4js.Proj.gnom={init:function(def){this.sin_p14=Math.sin(this.lat0);this.cos_p14=Math.cos(this.lat0);this.infinity_dist=1000*this.a;},forward:function(p){var sinphi,cosphi;var dlon;var coslon;var ksp;var g;var lon=p.x;var lat=p.y;dlon=Proj4js.common.adjust_lon(lon-this.long0);sinphi=Math.sin(lat);cosphi=Math.cos(lat);coslon=Math.cos(dlon);g=this.sin_p14*sinphi+this.cos_p14*cosphi*coslon;ksp=1.0;if((g>0)||(Math.abs(g)<=Proj4js.common.EPSLN)){x=this.x0+this.a*ksp*cosphi*Math.sin(dlon)/g;y=this.y0+this.a*ksp*(this.cos_p14*sinphi-this.sin_p14*cosphi*coslon)/g;}else{Proj4js.reportError("orthoFwdPointError");x=this.x0+this.infinity_dist*cosphi*Math.sin(dlon);y=this.y0+this.infinity_dist*(this.cos_p14*sinphi-this.sin_p14*cosphi*coslon);}
+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+(p.x/this.a)/Math.cos(this.lat_ts));var lat=Math.asin((p.y/this.a)*Math.cos(this.lat_ts));p.x=lon;p.y=lat;return p;}};Proj4js.Proj.eqc={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;if(!this.lat_ts)this.lat_ts=0;if(!this.title)this.title="Equidistant Cylindrical (Plate Carre)";this.rc=Math.cos(this.lat_ts);},forward:function(p){var lon=p.x;var lat=p.y;var dlon=Proj4js.common.adjust_lon(lon-this.long0);var dlat=Proj4js.common.adjust_lat(lat-this.lat0);p.x=this.x0+(this.a*dlon*this.rc);p.y=this.y0+(this.a*dlat);return p;},inverse:function(p){var x=p.x;var y=p.y;p.x=Proj4js.common.adjust_lon(this.long0+((x-this.x0)/(this.a*this.rc)));p.y=Proj4js.common.adjust_lat(this.lat0+((y-this.y0)/(this.a)));return p;}};Proj4js.Proj.cass={init:function(){if(!this.sphere){this.en=this.pj_enfn(this.es)
+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,this.c,this.en);this.n=1./Math.sqrt(1.-this.es*this.n*this.n);this.tn=Math.tan(phi);this.t=this.tn*this.tn;this.a1=lam*this.c;this.c*=this.es*this.c/(1-this.es);this.a2=this.a1*this.a1;x=this.n*this.a1*(1.-this.a2*this.t*(this.C1-(8.-this.t+8.*this.c)*this.a2*this.C2));y-=this.m0-this.n*this.tn*this.a2*(.5+(5.-this.t+6.*this.c)*this.a2*this.C3);}
+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.d2=this.dd*this.dd;phi=ph1-(this.n*this.tn/this.r)*this.d2*(.5-(1.+3.*this.t)*this.d2*this.C3);lam=this.dd*(1.+this.t*this.d2*(-this.C4+(1.+3.*this.t)*this.d2*this.C5))/Math.cos(ph1);}
+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_mlfn:function(arg,es,en){k=1./(1.-es);phi=arg;for(i=Proj4js.common.MAX_ITER;i;--i){s=Math.sin(phi);t=1.-es*s*s;t=(this.pj_mlfn(phi,s,Math.cos(phi),en)-arg)*(t*Math.sqrt(t))*k;phi-=t;if(Math.abs(t)<Proj4js.common.EPSLN)
+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.atan(this.K*Math.pow(Math.tan(0.5*lat+Proj4js.common.FORTPI),this.C)*Proj4js.common.srat(this.e*Math.sin(lat),this.ratexp))-Proj4js.common.HALF_PI;p.x=this.C*lon;return p;},inverse:function(p){var DEL_TOL=1e-14;var lon=p.x/this.C;var lat=p.y;num=Math.pow(Math.tan(0.5*lat+Proj4js.common.FORTPI)/this.K,1./this.C);for(var i=Proj4js.common.MAX_ITER;i>0;--i){lat=2.0*Math.atan(num*Proj4js.common.srat(this.e*Math.sin(p.y),-0.5*this.e))-Proj4js.common.HALF_PI;if(Math.abs(lat-p.y)<DEL_TOL)break;p.y=lat;}
+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.tsfnz(this.e,this.lat0,this.sin_p20);this.con=Math.sqrt(this.con);this.d=this.bl*this.com/(this.cos_p20*this.con);if((this.d*this.d-1.0)>0.0){if(this.lat0>=0.0){this.f=this.d+Math.sqrt(this.d*this.d-1.0);}else{this.f=this.d-Math.sqrt(this.d*this.d-1.0);}}else{this.f=this.d;}
+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.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);}}else{Proj4js.reportError("omerc:Init:DataError");}}else{this.sinphi=Math.sin(this.at1);this.ts1=Proj4js.common.tsfnz(this.e,this.lat1,this.sinphi);this.sinphi=Math.sin(this.lat2);this.ts2=Proj4js.common.tsfnz(this.e,this.lat2,this.sinphi);this.h=Math.pow(this.ts1,this.bl);this.l=Math.pow(this.ts2,this.bl);this.f=this.el/this.h;this.g=.5*(this.f-1.0/this.f);this.j=(this.el*this.el-this.l*this.h)/(this.el*this.el+this.l*this.h);this.p=(this.l-this.h)/(this.l+this.h);this.dlon=this.lon1-this.lon2;if(this.dlon<-Proj4js.common.PI)this.lon2=this.lon2-2.0*Proj4js.common.PI;if(this.dlon>Proj4js.common.PI)this.lon2=this.lon2+2.0*Proj4js.common.PI;this.dlon=this.lon1-this.lon2;this.longc=.5*(this.lon1+this.lon2)-Math.atan(this.j*Math.tan(.5*this.bl*this.dlon)/this.p)/this.bl;this.dlon=Proj4js.common.adjust_lon(this.lon1-this.longc);this.gama=Math.atan(Math.sin(this.bl*this.dlon)/this.g);this.alpha=Proj4js.common.asinz(this.d*Math.sin(this.gama));if(Math.abs(this.lat1-this.lat2)<=Proj4js.common.EPSLN){Proj4js.reportError("omercInitDataError");}else{this.con=Math.abs(this.lat1);}
+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.common.adjust_lon(lon-this.longc);vl=Math.sin(this.bl*dlon);if(Math.abs(Math.abs(lat)-Proj4js.common.HALF_PI)>Proj4js.common.EPSLN){ts1=Proj4js.common.tsfnz(this.e,lat,sin_phi);q=this.el/(Math.pow(ts1,this.bl));s=.5*(q-1.0/q);t=.5*(q+1.0/q);ul=(s*this.singam-vl*this.cosgam)/t;con=Math.cos(this.bl*dlon);if(Math.abs(con)<.0000001){us=this.al*this.bl*dlon;}else{us=this.al*Math.atan((s*this.cosgam+vl*this.singam)/con)/this.bl;if(con<0)us=us+Proj4js.common.PI*this.al/this.bl;}}else{if(lat>=0){ul=this.singam;}else{ul=-this.singam;}
+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*(q+1.0/q);vl=Math.sin(this.bl*us/this.al);ul=(vl*this.cosgam+s*this.singam)/t;if(Math.abs(Math.abs(ul)-1.0)<=Proj4js.common.EPSLN)
+{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){this.ns=Math.log(ms1/ms2)/Math.log(ts1/ts2);}else{this.ns=sin1;}
+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.lat0)/(Math.sqrt(1.-this.es*sinphi*sinphi)*this.rq*this.cosb1);this.ymf=(this.xmf=this.rq)/this.dd;this.xmf*=this.dd;break;}}else{if(this.mode==this.OBLIQ){this.sinph0=Math.sin(this.lat0);this.cosph0=Math.cos(this.lat0);}}},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){var coslam,cosphi,sinphi;sinphi=Math.sin(phi);cosphi=Math.cos(phi);coslam=Math.cos(lam);switch(this.mode){case this.EQUIT:y=(this.mode==this.EQUIT)?1.+cosphi*coslam:1.+this.sinph0*sinphi+this.cosph0*cosphi*coslam;if(y<=Proj4js.common.EPSLN){Proj4js.reportError("laea:fwd:y less than eps");return null;}
+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.sin(t+t)+APA[2]*Math.sin(t+t+t));}};Proj4js.Proj.aeqd={init:function(){this.sin_p12=Math.sin(this.lat0);this.cos_p12=Math.cos(this.lat0);},forward:function(p){var lon=p.x;var lat=p.y;var ksp;var sinphi=Math.sin(p.y);var cosphi=Math.cos(p.y);var dlon=Proj4js.common.adjust_lon(lon-this.long0);var coslon=Math.cos(dlon);var g=this.sin_p12*sinphi+this.cos_p12*cosphi*coslon;if(Math.abs(Math.abs(g)-1.0)<Proj4js.common.EPSLN){ksp=1.0;if(g<0.0){Proj4js.reportError("aeqd:Fwd:PointError");return;}}else{var z=Math.acos(g);ksp=z/Math.sin(z);}
+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(lat);if((Math.abs(con)<Proj4js.common.EPSLN)&&(Math.abs(p.x)<Proj4js.common.EPSLN)){}else{var temp=Math.atan2((p.x*sinz*this.cos_p12),(con*rh));lon=Proj4js.common.adjust_lon(this.long0+Math.atan2((p.x*sinz*this.cos_p12),(con*rh)));}}}
+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.common.PI))lon=-Proj4js.common.PI;if(lon>Proj4js.common.PI)lon=Proj4js.common.PI;arg=(2.0*theta+Math.sin(2.0*theta))/Proj4js.common.PI;if(Math.abs(arg)>1.0)arg=1.0;var lat=Math.asin(arg);p.x=lon;p.y=lat;return p;}};
Index: trunk/zoo-kernel/Doxyfile
===================================================================
--- trunk/zoo-kernel/Doxyfile	(revision 1)
+++ trunk/zoo-kernel/Doxyfile	(revision 1)
@@ -0,0 +1,1417 @@
+# Doxyfile 1.5.6
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a 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.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = ZOO Kernel
+
+# 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         = 0.1
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
+# base path where the generated documentation will be put. 
+# 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       = doc
+
+# 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 cause performance problems for the file system.
+
+CREATE_SUBDIRS         = YES
+
+# 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. 
+# The default language is English, other supported languages are: 
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, 
+# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, 
+# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), 
+# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, 
+# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, 
+# and Ukrainian.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) 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.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) 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.
+
+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" "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.
+
+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.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then 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.
+
+FULL_PATH_NAMES        = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then 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.
+
+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 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.
+
+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 
+# comments will behave just like regular Qt-style comments 
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF      = NO
+
+# 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 comments 
+# will behave just like regular Qt-style comments (thus requiring 
+# an explicit \brief command for a brief description.)
+
+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 behaviour. 
+# 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 behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen 
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member 
+# documentation.
+
+DETAILS_AT_TOP         = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
+# member inherits the documentation from any documented member that it 
+# re-implements.
+
+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.
+
+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.
+
+TAB_SIZE               = 4
+
+# This tag can be used to specify a number of aliases that acts 
+# 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                = 
+
+# 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.
+
+OPTIMIZE_OUTPUT_FOR_C  = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java 
+# sources only. Doxygen will then generate output that is more tailored for 
+# Java. For instance, namespaces will be presented as packages, qualified 
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran 
+# sources only. Doxygen will then generate output that is more tailored for 
+# Fortran.
+
+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.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# 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); v.s. 
+# func(std::string) {}). This also make the inheritance and collaboration 
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip 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.
+
+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 (the default) 
+# 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.
+
+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.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES (the default) 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.
+
+SUBGROUPING            = YES
+
+# When TYPEDEF_HIDES_STRUCT 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.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+#---------------------------------------------------------------------------
+# 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 and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file 
+# will be included in the documentation.
+
+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.
+
+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 (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = YES
+
+# 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.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
+# undocumented members of documented classes, files or namespaces. 
+# If set to NO (the default) 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.
+
+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 (the default) these classes will be included in the various 
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+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 (the default) these declarations will be included in the 
+# documentation.
+
+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 (the default) these blocks will be appended to the 
+# function's detailed documentation block.
+
+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 (the default) then the documentation will be excluded. 
+# Set it to YES to include the internal documentation.
+
+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.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
+# will show members with their full class and namespace scopes in the 
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
+# will put a list of the files that are included by a file in the documentation 
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) 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.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
+# brief documentation of file, namespace and class members alphabetically 
+# by member name. If set to NO (the default) the members will appear in 
+# declaration order.
+
+SORT_BRIEF_DOCS        = 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 default) 
+# the group names will appear in their defined order.
+
+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 default), 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.
+
+SORT_BY_SCOPE_NAME     = 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.
+
+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.
+
+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.
+
+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.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional 
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       = 
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
+# the initial value of a variable or define consists of 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 initializer of individual variables and defines in the 
+# documentation can be controlled using \showinitializer or \hideinitializer 
+# command in the documentation regardless of this setting.
+
+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.
+
+SHOW_USED_FILES        = YES
+
+# If the sources in your project are distributed over multiple directories 
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy 
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES       = NO
+
+# 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 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 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. See the manual for examples.
+
+FILE_VERSION_FILTER    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated 
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are 
+# generated by doxygen. Possible values are YES and NO. If left blank 
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED 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.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR 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.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for 
+# functions that are documented, but have no documentation for their parameters 
+# or return value. If set to NO (the default) doxygen will only warn about 
+# wrong or incomplete parameter documentation, but not about the absence of 
+# documentation.
+
+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)
+
+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 stderr.
+
+WARN_LOGFILE           = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be 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.
+
+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, which is 
+# also the default input encoding. 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.
+
+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 pattern (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 *.h *.hh *.hxx 
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+
+FILE_PATTERNS          = 
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
+# should be searched for input files as well. Possible values are YES and NO. 
+# If left blank NO is used.
+
+RECURSIVE              = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should 
+# 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.
+
+EXCLUDE                = 
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or 
+# directories that are symbolic links (a Unix filesystem feature) are excluded 
+# from the input.
+
+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
+
+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. 
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or 
+# directories that contain image that are 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.
+
+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 
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER 
+# is applied to all files.
+
+FILTER_PATTERNS        = 
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
+# INPUT_FILTER) will be used to filter the input files when producing source 
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+#---------------------------------------------------------------------------
+# 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 also 
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body 
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = YES
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
+# doxygen to hide any special comment blocks from generated source code 
+# fragments. Normal C and C++ comments will always remain visible.
+
+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.
+
+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.
+
+REFERENCES_RELATION    = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# 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 documentstion.
+
+REFERENCES_LINK_SOURCE = 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.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) 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.
+
+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.
+
+ALPHABETICAL_INDEX     = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
+# in which this list will be split (can be a number in the range [1..20])
+
+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 one or more prefixes that 
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
+# generate HTML output.
+
+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. If left blank `html' will be used as the default path.
+
+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). If it is left blank 
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard header.
+
+HTML_HEADER            = 
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard footer.
+
+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 the tag is left blank doxygen 
+# will generate a default style sheet. Note that doxygen will try to copy 
+# the style sheet file to the HTML output directory, so don't put your own 
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        = 
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
+# files or namespaces will be aligned in HTML using tables. If set to 
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
+# will be generated that can be used as input for tools like the 
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) 
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = YES
+
+# 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, 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.
+
+GENERATE_DOCSET        = YES
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the 
+# 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.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, 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.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# 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. For this to work a browser that supports 
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox 
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS  = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, 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.
+
+CHM_FILE               = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, 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.
+
+HHC_LOCATION           = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, 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).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING     = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, 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.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members 
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = YES
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
+# top of each HTML page. The value NO (the default) enables the index and 
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [1..20]) 
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# 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 FRAME, 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 (for instance Mozilla 1.0+, 
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are 
+# probably better off using the HTML help feature. Other possible values 
+# for this tag are: HIERARCHIES, which will generate the Groups, Directories,
+# and Class Hiererachy pages using a tree view instead of an ordered list;
+# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which
+# disables this behavior completely. For backwards compatibility with previous
+# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE
+# respectively.
+
+GENERATE_TREEVIEW      = NONE
+
+# 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.
+
+TREEVIEW_WIDTH         = 250
+
+# Use this tag to change the font size of Latex formulas included 
+# as images in the HTML documentation. The default is 10. Note that 
+# 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.
+
+FORMULA_FONTSIZE       = 10
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
+# generate Latex output.
+
+GENERATE_LATEX         = NO
+
+# 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. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
+# generate index for LaTeX. If left blank `makeindex' will be used as the 
+# default command name.
+
+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.
+
+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, a4wide, letter, legal and 
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
+# packages that should be included in the LaTeX output.
+
+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. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           = 
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
+# is prepared for conversion to pdf (using ps2pdf). 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.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
+# plain latex in the generated Makefile. Set this option to YES to get a 
+# higher quality PDF documentation.
+
+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.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
+# include the index chapters (such as File Index, Compound Index, etc.) 
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+#---------------------------------------------------------------------------
+# 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 very pretty with 
+# other RTF readers or editors.
+
+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. If left blank `rtf' will be used as the default path.
+
+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.
+
+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 other 
+# programs which support those fields. 
+# Note: wordpad (write) and others do not support links.
+
+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.
+
+RTF_STYLESHEET_FILE    = 
+
+# Set optional variables used in the generation of an rtf document. 
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
+# generate man pages
+
+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. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to 
+# the generated man pages (default is the subroutine's section .3)
+
+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 is NO.
+
+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.
+
+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. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_SCHEMA             = 
+
+# The XML_DTD tag can be used to specify an XML DTD, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+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.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
+# generate an AutoGen Definitions (see 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.
+
+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.
+
+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.
+
+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.
+
+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.
+
+PERLMOD_MAKEVAR_PREFIX = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
+# evaluate all C-preprocessor directives found in the sources and include 
+# files.
+
+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 (the default) only conditional 
+# compilation will be performed. Macro expansion can be done in a controlled 
+# way by setting EXPAND_ONLY_PREDEF 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.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+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.
+
+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.
+
+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 
+# 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.
+
+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.
+
+EXPAND_AS_DEFINED      = 
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
+# doxygen's preprocessor will remove all 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.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references   
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. 
+# Optionally an initial location of the external documentation 
+# can be added for each tagfile. 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. If a location is present for each tag, the installdox tool 
+# does not have to be run to correct the links.
+# Note that each tag file must have a 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.
+
+GENERATE_TAGFILE       = 
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
+# in the class index. If set to NO only the inherited external classes 
+# will be listed.
+
+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.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script 
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base 
+# or super classes. Setting the tag to NO turns the diagrams off. Note that 
+# this option is superseded by the HAVE_DOT option below. This is only a 
+# fallback. It is recommended to install and use dot, since it yields more 
+# powerful graphs.
+
+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            = 
+
+# 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.
+
+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, 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)
+
+HAVE_DOT               = YES
+
+# By default doxygen will write a font called FreeSans.ttf to the output 
+# directory and reference it in all dot files that doxygen generates. This 
+# font does not include all possible unicode characters however, so when you need 
+# these (or just want a differently looking font) you can specify the font name 
+# using DOT_FONTNAME. You need 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.
+
+DOT_FONTNAME           = FreeSans
+
+# By default doxygen will tell dot to use the output directory to look for the 
+# FreeSans.ttf font (which doxygen will put there itself). If you specify a 
+# different font using DOT_FONTNAME you can set the path where dot 
+# can find it using this tag.
+
+DOT_FONTPATH           = 
+
+# If the CLASS_GRAPH and HAVE_DOT tags are 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 
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are 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.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for groups, showing the direct groups dependencies
+
+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.
+
+UML_LOOK               = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the 
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
+# 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.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
+# documented header file showing the documented files that directly or 
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are 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.
+
+CALL_GRAPH             = YES
+
+# If the CALLER_GRAPH and HAVE_DOT tags are 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.
+
+CALLER_GRAPH           = YES
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are 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.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH 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.
+
+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).
+
+DOTFILE_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.
+
+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.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent 
+# background. This is enabled by default, which results in a transparent 
+# background. 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).
+
+DOT_TRANSPARENT        = YES
+
+# 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.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
+# generate a legend page explaining the meaning of the various boxes and 
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
+# remove the intermediate dot files that are used to generate 
+# the various graphs.
+
+DOT_CLEANUP            = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine   
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be 
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE           = NO
Index: trunk/zoo-kernel/Makefile.in
===================================================================
--- trunk/zoo-kernel/Makefile.in	(revision 1)
+++ trunk/zoo-kernel/Makefile.in	(revision 1)
@@ -0,0 +1,89 @@
+JAVACFLAGS=@JAVA_CPPFLAGS@
+JAVALDFLAGS=@JAVA_LDFLAGS@
+CFLAGS=-I. -DLINUX_FREE_ISSUE #-DDEBUG #-DDEBUG_SERVICE_CONF
+PHPCFLAGS=@PHP_CPPFLAGS@
+PHPLDFLAGS=@PHP_LDFLAGS@
+PYTHONCFLAGS=@PYTHON_CPPFLAGS@
+PYTHONLDFLAGS=@PYTHON_LDFLAGS@
+JSCFLAGS=@JS_CPPFLAGS@
+JSLDFLAGS=@JS_LDFLAGS@
+XML2CFLAGS=@XML2_CPPFLAGS@
+XML2LDFLAGS=@XML2_LDFLAGS@
+GDAL_CFLAGS=@GDAL_CFLAGS@
+GDAL_LIBS=@GDAL_LIBS@
+PHP_ENABLED=@PHP_ENABLED@
+PHP_FILE=@PHP_FILE@
+JAVA_ENABLED=@JAVA_ENABLED@
+JAVA_FILE=@JAVA_FILE@
+JS_ENABLED=@JS_ENABLED@
+JS_FILE=@JS_FILE@
+
+
+all: zoo_loader.cgi service_loader
+
+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 ${XML2CFLAGS} ${CFLAGS} ${JSCFLAGS} ${JS_ENABLED} -c ulinet.c
+
+service_internal.o: service_internal.c service.h
+	g++ ${XML2CFLAGS} ${CFLAGS} -c service_internal.c
+
+service_internal_python.o: service_internal_python.c service.h
+	g++ ${XML2CFLAGS} ${PYTHONCFLAGS} ${CFLAGS} -c service_internal_python.c
+
+service_internal_php.o: service_internal_php.c service.h
+	g++ -c ${XML2CFLAGS} ${PHPCFLAGS} ${CFLAGS}  ${PHP_ENABLED} service_internal_php.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 ${XML2CFLAGS} ${JSCFLAGS} ${CFLAGS} ${JS_ENABLED} -c service_internal_js.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 -Wall ${XML2CFLAGS} ${CFLAGS} ${PYTHONCFLAGS} ${JAVACFLAGS} ${PHPCFLAGS} ${JS_ENABLED} ${PHP_ENABLED} ${JAVA_ENABLED} -c zoo_service_loader.c  -fno-common -DPIC -o zoo_service_loader.o
+
+zoo_loader.cgi: zoo_loader.c zoo_service_loader.o  ulinet.o service.h lex.sr.o service_conf.tab.o service_conf.y service_internal_python.o  ulinet.o main_conf_read.tab.o lex.cr.o service_internal.o ${PHP_FILE} ${JAVA_FILE} ${JS_FILE}
+	g++ -g -O2 -Wall ${JSCFLAGS} ${PHPCFLAGS} ${JAVACFLAGS} ${XML2CFLAGS} ${PYTHONCFLAGS} ${CFLAGS} -c zoo_loader.c  -fno-common -DPIC -o zoo_loader.o
+	g++  ${JSCFLAGS} ${GDAL_CFLAGS} ${XML2CFLAGS} ${PHPCFLAGS} ${JAVACFLAGS} ${PYTHONCFLAGS} ${CFLAGS} zoo_loader.o zoo_service_loader.o service_internal.o service_internal_python.o  ${PHP_FILE}  ${JS_FILE} ${JAVA_FILE} ulinet.o lex.cr.o lex.sr.o service_conf.tab.o main_conf_read.tab.o -o zoo_loader.cgi -lcurl -lcgic -lcurl ${GDAL_LIBS} ${XML2LDFLAGS} ${PYTHONLDFLAGS}  ${PHPLDFLAGS} ${JAVALDFLAGS} ${JSLDFLAGS} -lfcgi 
+
+service_loader: service.h lex.sr.o service_conf.tab.o service_conf.y service_internal_python.o ulinet.o  service_loader.o main_conf_read.tab.o lex.cr.o service_internal.o
+	g++ ${CFLAGS} lex.sr.o service_conf.tab.o main_conf_read.tab.o lex.cr.o service_internal.o service_internal_python.o ulinet.o service_loader.o -o service_loader -ldl  ${JSLDFLAGS} ${PYTHONLDFLAGS} ${XML2LDFLAGS} -lfl -lcurl  -lssl
+
+install:
+	@echo "##############################################################################"
+	@echo "# This won't install anything !!!                                            #"
+	@echo "#                                                                            #"
+	@echo "# Please copy the zoo_loader.cgi and its companion main.cfg into your cgbin  #"
+	@echo "# directory.                                                                 #"
+	@echo "##############################################################################"
+
+clean:
+	rm -f *.o *.zo *.eo *.tab.c *.tab.h *.sr.c* service_loader lex.* *.lreg *.sibling service_loader.dSYM
Index: trunk/zoo-kernel/configure.ac
===================================================================
--- trunk/zoo-kernel/configure.ac	(revision 1)
+++ trunk/zoo-kernel/configure.ac	(revision 1)
@@ -0,0 +1,384 @@
+AC_PREREQ([2.63])
+AC_INIT([ZOO Kernel], [0.0.1], [bugs@zoo-project.org])
+#AM_INIT_AUTOMAKE
+#AC_CONFIG_HEADERS([config.h])
+
+# Checks for programs.
+AC_PROG_YACC
+AC_PROG_CC
+AC_PROG_LEX
+AC_PROG_CXX
+AC_PROG_SED
+
+# Checks for libraries.
+AC_CHECK_LIB([cgic], [cgiMain])
+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([fl], [main])
+AC_CHECK_LIB([pthread], [main])
+AC_CHECK_LIB([fcgi], [main])
+AC_CHECK_LIB([ssl], [main])
+
+# 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 gdal is installed
+#============================================================================
+
+AC_ARG_WITH([gdal-config], 
+	[AS_HELP_STRING([--with-gdal-config=FILE], [specify 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 libxml2 is installed
+# ===========================================================================
+
+AC_ARG_WITH([xml2config], 
+	[AS_HELP_STRING([--with-xml2config=FILE], [specify 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 specify 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])
+
+
+
+
+# ===========================================================================
+# Detect if python is installed
+# ===========================================================================
+
+AC_ARG_WITH([python], 
+	[AS_HELP_STRING([--with-python=PATH], [specify an alternative directory for python installation])], 
+	[PYTHONCONFIG="$withval/bin/python-config"], [PYTHONCONFIG=""])
+
+if test "x$PYTHONCONFIG" = "x"; then
+	# PYTHON was not specified, so search within the current path
+	AC_PATH_PROG([PYTHONCONFIG], [python-config])
+
+	# If we couldn't find python-config, display a warning
+	if test "x$PYTHONCONFIG" = "x"; then
+		AC_MSG_ERROR([could not find python-config from libpython within the current path. You may need to try re-running configure with a --with-python parameter.])
+	fi
+else
+	# PYTHON was specified; display a message to the user
+	if test "x$PYTHON" = "xyes"; then
+		AC_MSG_ERROR([you must specify a parameter to --with-python, e.g. --with-python=/path/to/python])
+	else
+		if test -f $PYTHONCONFIG; then
+			AC_MSG_RESULT([Using user-specified python-config file: $PYTHONCONFIG])
+		else
+			AC_MSG_ERROR([the user-specified python-config file $PYTHONCONFIG does not exist])
+		fi	
+	fi
+fi
+
+
+# Extract the linker and include flags 
+PYTHON_LDFLAGS=`$PYTHONCONFIG --libs`
+PYTHON_CPPFLAGS=`$PYTHONCONFIG --cflags`
+
+# 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 libpython
+LIBS_SAVE="$LIBS"
+LIBS="$PYTHON_LDFLAGS"
+# Shouldn't we get python here rather than python2.6 :) ??
+PY_LIB=`$PYTHONCONFIG --libs | sed -e 's/^.*\(python2\..\)$/\1/'`
+echo $PY_LIB
+AC_CHECK_LIB([$PY_LIB], [PyObject_CallObject], [], [AC_MSG_ERROR([could not find libpython])], [])
+
+AC_SUBST([PYTHON_CPPFLAGS])
+AC_SUBST([PYTHON_LDFLAGS])
+
+# ===========================================================================
+# Detect if php is installed
+# ===========================================================================
+
+
+
+
+AC_ARG_WITH([php], 
+	[AS_HELP_STRING([--with-php=PATH], [specify an alternative directory for php installation or --with-php=no  to disable php support])], 
+	[PHP_PATH="$withval"], [PHP_PATH=""])
+if test "$PHP_PATH" != "no";
+then 
+	PHPCONFIG="$PHP_PATH/bin/php-config"
+	PHP_ENABLED="-DUSE_PHP"
+	PHP_FILE="service_internal_php.o"
+	if test "x$PHPCONFIG" = "x"; 
+	then
+	# PHP was not specified, so search within the current path
+	AC_PATH_PROG([PHPCONFIG], [php-config])
+
+	# If we couldn't find php-config, display a warning
+	if test "x$PHPCONFIG" = "x"; 
+	then
+		AC_MSG_ERROR([could not find php-config from libphp within the current path. You may need to try re-running configure with a --with-php parameter.])
+	fi
+	else
+		# PHP was specified; display a message to the user
+		if test "x$PHP" = "xyes"; 
+		then
+			AC_MSG_ERROR([you must specify a parameter to --with-php, e.g. --with-php=/path/to/php])
+		else
+			if test -f $PHPCONFIG; 
+			then
+				AC_MSG_RESULT([Using user-specified php-config file: $PHPCONFIG])
+			else
+				AC_MSG_ERROR([the user-specified php-config file $PHPCONFIG does not exist])
+			fi	
+		fi
+	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])], [])
+	AC_SUBST([PHP_CPPFLAGS])
+	AC_SUBST([PHP_LDFLAGS])
+else
+	PHP_ENABLED=""
+	PHP_FILE=""
+fi
+
+AC_SUBST([PHP_ENABLED])
+AC_SUBST([PHP_FILE])
+
+
+# ===========================================================================
+# Detect if java is installed
+# ===========================================================================
+
+
+
+AC_ARG_WITH([java], 
+	[AS_HELP_STRING([--with-java=PATH], [specify an alternative directory for java installation or --with-java=no to disabled java support])], 
+	[JDKHOME="$withval"], [JDKHOME=""])
+
+
+if test "$JDKHOME" != "no";
+then
+	JAVA_ENABLED="-DUSE_JAVA"
+	JAVA_FILE="service_internal_java.o"
+	if test "x$JDKHOME" = "x"; 
+	then
+		# JAVA was not specified, so search within the current path
+		#AC_PATH_PROG([JAVACONFIG], [java])
+
+		# If we couldn't find java-config, display a warning
+		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
+	else
+		# 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])
+		else
+			if test -f $JDKHOME/include/jni.h; 
+			then
+				AC_MSG_RESULT([Using specific java install dir : $JDKHOME])
+			else
+				AC_MSG_ERROR([the specific java install dir $DKHOME does not exist])
+			fi	
+		fi
+	fi
+	# Extract the linker and include flags
+	if test -d "$JDKHOME/jre/lib/i386";
+	then
+		JAVA_LDFLAGS="-L$JDKHOME/jre/lib/i386/ -ljavaplugin_jni -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/ -ljavaplugin_jni -L$JDKHOME/jre/lib/amd64/server/ -ljvm -lpthread"
+                JAVA_CPPFLAGS="-I$JDKHOME/include -I$JDKHOME/include/linux"
+	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 headers include related to libjava])])
+
+	# Ensure we can link against libjava
+	LIBS_SAVE="$LIBS"
+	LIBS="$JAVA_LDFLAGS"
+	# Shouldn't we get java here rather than java5 :) ??
+	AC_CHECK_LIB([javaplugin_jni], [JNI_CreateJavaVM], [], [AC_MSG_ERROR([could not find libjava])], [])
+	AC_CHECK_LIB([jvm], [main], [], [AC_MSG_ERROR([could not find libjava])], [])
+
+	AC_SUBST([JAVA_CPPFLAGS])
+	AC_SUBST([JAVA_LDFLAGS])
+else
+	JAVA_ENABLED=""
+	JAVA_FILE=""
+fi 
+
+AC_SUBST([JAVA_ENABLED])
+AC_SUBST([JAVA_FILE])
+
+
+
+
+
+# ===========================================================================
+# Detect if spidermonkey is installed
+# ===========================================================================
+
+AC_ARG_WITH([js], 
+	[AS_HELP_STRING([--with-js=PATH], [specify an alternative directory for spidermonkey installation or --with-js=no to disabled js support])], 
+	[JSHOME="$withval"], [JSHOME=""])
+if test "$JSHOME" != "no";
+then
+        JS_ENABLED="-DUSE_JS"
+        JS_FILE="service_internal_js.o"
+
+	#if test "x$JSHOME" = "x"; then
+	#	# JS was not specified, so search within the current path
+#		# AC_PATH_PROG([JSCONFIG], [js-config])
+#	
+#		# If we couldn't find js-config, display a warning
+#		if test "x$JSHOME" = "x"; then
+#			AC_MSG_ERROR([could not find js-config from libpython within the current path. You may need to try re-running configure with a --with-js parameter.])
+#		fi
+#	else
+#		# JS was specified; display a message to the user
+#		if test "x$JSHOME" = "xyes"; then
+#			AC_MSG_ERROR([you must specify a parameter to --with-js, e.g. --with-js=/path/to/js])
+#		else
+#			if test -f $JSHOME; then
+#			AC_MSG_RESULT([Using user-specified js-config file: $JSCONFIG])
+#			else
+#				AC_MSG_ERROR([the user-specified js-config file $JSCONFIG does not exist])
+#			fi	
+#		fi
+#	fi
+
+
+	# Extract the linker and include flags 
+	JS_CPPFLAGS="-I$JSHOME/include"
+	JS_LDFLAGS="-L$JSHOME/lib -ljs -lm"
+	# Check headers file
+	CPPFLAGS_SAVE="$CPPFLAGS"
+	CPPFLAGS="$JS_CPPFLAGS"
+	#AC_CHECK_HEADERS([jsapi.h],
+	#		 [], [AC_MSG_ERROR([could not find headers include related to libjs])])
+
+	# Ensure we can link against libjs
+	LIBS_SAVE="$LIBS"
+	LIBS="$JS_LDFLAGS"
+	
+	AC_CHECK_LIB([js], [JS_CallFunctionName], [], [AC_MSG_ERROR([could not find libjs])], [])
+
+	AC_SUBST([JS_CPPFLAGS])
+	AC_SUBST([JS_LDFLAGS])
+
+else
+        JS_ENABLED=""
+        JS_FILE=""
+fi
+
+AC_SUBST([JS_ENABLED])
+AC_SUBST([JS_FILE])
+
+
+
+
+
+
+AC_CONFIG_FILES([Makefile])
+AC_OUTPUT
Index: trunk/zoo-kernel/main.cfg
===================================================================
--- trunk/zoo-kernel/main.cfg	(revision 1)
+++ trunk/zoo-kernel/main.cfg	(revision 1)
@@ -0,0 +1,27 @@
+[main]
+encoding = utf-8
+version = 1.0.0
+serverAddress = http://dev.geolabs.fr/services/wps/
+lang = fr-FR,en-CA
+
+[identification]
+title = The Zoo WPS Development Server
+abstract = Development version of ZooWPS. See http://devpark.geolabs.fr/prj
+fees = None
+accessConstraints = none
+keywords = WPS,GIS,buffer
+
+[provider]
+providerName=GeoLabs SARL
+providerSite=http://dev.geolabs.fr
+individualName=Gerald FENOY
+positionName=Developper
+role=Gérant
+adressDeliveryPoint=1280, avenue des Platanes
+addressCity=Lattes
+addressAdministrativeArea=False
+addressPostalCode=34970
+addressCountry=fr
+addressElectronicMailAddress=gerald@geolabs.fr
+phoneVoice=False
+phoneFacsimile=False
Index: trunk/zoo-kernel/main_conf_read.l
===================================================================
--- trunk/zoo-kernel/main_conf_read.l	(revision 1)
+++ trunk/zoo-kernel/main_conf_read.l	(revision 1)
@@ -0,0 +1,178 @@
+/* pour pouvoir acceder au numero de ligne dans bison */
+%option yylineno
+
+
+%{
+//======================================================
+/**
+Zoo main configuration file parser
+**/
+//======================================================
+
+
+#include <string.h>
+#include "main_conf_read.tab.h"
+static int affichetrace = 0 ;
+static int attentionImpossibleDeTrouverXMLDeclapres = 0 ;
+static int attentionImpossibleDeTrouverPIapres = 0 ;
+
+%}
+
+
+/*====================================================*/
+/*====================================================*/
+/* Les Separateurs xml */
+/*====================================================*/
+S		[ \t\r\n]+
+/*====================================================*/
+
+
+
+
+/*====================================================*/
+/* CharRef regle 66 */
+/*====================================================*/
+CharRef		"&#"[0-9]+";"|"&#x"[0-9a-fA-F]+";"
+/*====================================================*/
+
+
+
+
+/*====================================================*/
+/*   espaces? '=' espaces?    regle 25  */
+/* si on veut pouvoir utiliser S dans bison, */
+/* il faut cr�r au moins une autre start condition */
+/* comme on n'utilise "egalevolue" que pour version et encoding */
+/* il est pr��able de rajouter cette macro */
+/*====================================================*/
+egalevolue		{S}?"="{S}?
+/*====================================================*/
+
+
+
+
+/*====================================================*/
+/* Name regle 5 */
+/*====================================================*/
+/*** Name		[a-zA-Z_:][a-zA-Z0-9.\-_:]* ***/
+Name		([_:]|[\x41-\x5A]|[\x61-\x7A]|[\xC0-\xD6]|[\xD8-\xF6]|[\xF8-\xFF])(([\x41-\x5A]|[\x61-\x7A]|[\xC0-\xD6]|[\xD8-\xF6]|[\xF8-\xFF])|[0-9.\-_:])*
+/*====================================================*/
+
+
+
+
+
+/*====================================================*/
+/* chardata  regle 14 */
+/*====================================================*/
+/**chardata	[a-zA-Z0-9_\-.:" "\"\'\\]***/
+chardata	[^<]*
+/*====================================================*/
+attname	[a-zA-Z0-9_\-:]+
+attvalue1	[,@a-zA-Z0-9_\-.:" "\"\'/\\]+
+
+
+
+
+
+/*====================================================*/
+/* attvalue regle 10 */
+/*====================================================*/
+/* attvalue		\"([^"&]|{CharRef})*\"|\'([^'&]|{CharRef})*\' */
+/* pas tr� classe mais ca marche . */
+attvalue		\"[^"]*\"|\'[^']*\'
+/*====================================================*/
+
+virgule	[,]+
+whitespace                      [ ]{0,}
+whitesp                      [ ]
+newline                 [\r\n]|[\n]
+newlines                 [\r\n]{1,}|[\n]{1,}
+
+
+
+
+
+
+
+
+
+
+/*====================================================*/
+/* initial = de debut a ?> du prolog ; DANSBALISE = dans une balise ; HORSBALISE = hors d'une balise */
+/*====================================================*/
+%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=strdup(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=strdup(yytext); return SPAIR; }
+
+<PAIRSTART,HORSBALISE>{attvalue1}             {if (affichetrace==1) printf ("\n\nATT_VALUE:%s\n",yytext);crlval.chaine=strdup(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;}
+
+<INITIAL>"<?"[Xx][Mm][Ll]  { if (attentionImpossibleDeTrouverXMLDeclapres == 1 || attentionImpossibleDeTrouverPIapres == 1) {/* il y a eut un commentaire ou une balise applicative avant la declaration xml */ 	printf("\nerror : a la ligne %d : il y a eut un commentaire ou un PI avant la declaration xml\n",yylineno); exit (10) ; } ; if (affichetrace==1) printf ("\n\nSTARTXMLDECL:%s\n",yytext) ;return STARTXMLDECL;}
+
+<INITIAL>"version"{egalevolue}\"1.0\"|"version"{egalevolue}\'1.0\'  {if (affichetrace==1) printf ("\n\nVERSIONDECL:%s\n",yytext) ;return VERSIONDECL;}
+<INITIAL>"version"{egalevolue}\"[^"]*\"|"version"{egalevolue}\'[^']*\'  {/* erreur de version encoding */ 	printf("\nerror : a la ligne %d : la version xml n est pas reconnue : %s\n",yylineno,yytext); exit (9) ; }
+
+
+<INITIAL>"encoding"{egalevolue}\"[Ii][Ss][Oo]"-8859-1"\"|"encoding"{egalevolue}\'[Ii][Ss][Oo]"-8859-1"\'  {if (affichetrace==1) printf ("\n\nENCODINGDECL:%s\n",yytext) ; return ENCODINGDECL;}
+<INITIAL>"encoding"{egalevolue}\"[^"]*\"|"encoding"{egalevolue}\'[^']*\'  {/* erreur de version encoding */ 	printf("\nerror : a la ligne %d : la version d encodage n est pas reconnue : %s\n",yylineno,yytext); exit (8) ; }
+
+
+<INITIAL>"standalone"{egalevolue}\"yes\"|"standalone"{egalevolue}\'yes\'|"standalone"{egalevolue}\"no\"|"standalone"{egalevolue}\'no\'  {if (affichetrace==1) printf ("\n\nSDDECL:%s\n",yytext) ; return SDDECL;}
+
+<INITIAL>"standalone"{egalevolue}\"[^"]*\"|"standalone"{egalevolue}\'[^']*\'|"standalone"{egalevolue}\"[^"]*\"|"standalone"{egalevolue}\'[^']*\'  {/* erreur de version encoding */ 	printf("\nerror : a la ligne %d : la version standalone n est pas reconnue : %s\n",yylineno,yytext); exit (7) ; }
+
+
+<INITIAL>"?>"  {if (affichetrace==1) printf ("\n\nENDXMLDECL:%s\n",yytext) ; BEGIN(HORSBALISE);return ENDXMLDECL;}
+
+
+<DANSBALISE,INITIAL,HORSBALISE>{S}   {if (affichetrace==1) printf ("\n\nS:'%s'\n",yytext) ; }
+
+
+<HORSBALISE>"<?"[Xx][Mm][Ll]{S}({S}|{chardata})*"?>"|"<?"[Xx][Mm][Ll]"?>"	{if (affichetrace==1) printf ("\n\nPIERROR:%s\n",yytext) ; return PIERROR;}
+<INITIAL,HORSBALISE>"<?"([^xX]|([xX][^mM])|([xX][mM][^lL]))({S}|([^?]|("?"[^>])))*"?>"		{attentionImpossibleDeTrouverPIapres=1 ;  if (affichetrace==1) printf ("\n\nPI:%s\n",yytext) ; return PI;}
+
+
+<INITIAL,HORSBALISE>{newline}*"<"		    {if (affichetrace==1) printf ("\n\nINFCAR:%s\n",yytext) ; BEGIN(DANSBALISE);return INFCAR;}
+
+
+<DANSBALISE>">"			{if (affichetrace==1) printf ("\n\nSUPCAR:%s\n",yytext) ; BEGIN(HORSBALISE);return SUPCAR;}
+
+
+<DANSBALISE>"/"		{if (affichetrace==1) printf ("\n\nSLASH:%s\n",yytext) ; return SLASH;}
+
+
+<DANSBALISE>{egalevolue}			{if (affichetrace==1) printf ("\n\nEq:'%s'\n",yytext) ; return Eq;}
+
+
+<DANSBALISE>{Name}			{if (affichetrace==1) printf ("\n\nID:%s\n",yytext) ; crlval.s=strdup(yytext);return ID;}
+
+
+<DANSBALISE>{attvalue}		{if (affichetrace==1) printf ("\n\nATTVALUE:%s\n",yytext) ; return ATTVALUE;}
+
+
+<INITIAL,HORSBALISE>"<!--"([^-]|"-"[^-])*"-->"		{attentionImpossibleDeTrouverXMLDeclapres=1; }
+
+
+<INITIAL,DANSBALISE,HORSBALISE>.|\n	{if (affichetrace==1)printf("error : ligne %d : caractere non reconnu '%s'\n",yylineno,yytext); }
+
+%%
+
+
+int yywrap()
+{return 1;}
Index: trunk/zoo-kernel/main_conf_read.y
===================================================================
--- trunk/zoo-kernel/main_conf_read.y	(revision 1)
+++ trunk/zoo-kernel/main_conf_read.y	(revision 1)
@@ -0,0 +1,345 @@
+%{
+//======================================================
+/**
+   Zoo main configuration file parser
+**/
+//======================================================
+
+
+
+#include <string>
+#include <stdio.h>
+#include <ctype.h>
+#include <service.h>
+#include <vector>
+
+static int defaultsc=0;
+static maps* my_maps=NULL;
+static maps* current_maps=NULL;
+static map* previous_content=NULL;
+static map* current_content=NULL;
+static elements* current_element=NULL;
+static map* scontent=NULL;
+static char* curr_key;
+static int debug=0;
+//static int data=-1;
+static int previous_data=0;
+static int current_data=0;
+//static char* myFinalObjectAsJSON="{";
+// namespace
+using namespace std;
+
+extern void crerror(char *s);
+
+void usage(void) ;
+
+extern int crdebug;
+
+extern char crtext[];
+
+extern int crlineno;
+
+extern FILE* crin;
+
+extern int crlex(void);
+
+
+%}
+
+
+
+//======================================================
+/* le type des lval des jetons et des elements non terminaux bison */
+//======================================================
+%union 
+{
+   char * s;
+}
+%union { char* chaine; char* key;char* val;}
+//======================================================
+
+// jetons //
+//======================================================
+/* les jetons que l on retrouve dans FLEX */
+//======================================================
+/* texte on a besoin de récupérer une valeur char* pour la comparer */
+%token <s> ID
+%token <s> CHAINE
+/* STARTXMLDECL et ENDXMLDECL qui sont <?xml et ?>*/
+%token STARTXMLDECL ENDXMLDECL
+//======================================================
+/* version="xxx" et encoding="xxx" */
+%token VERSIONDECL ENCODINGDECL SDDECL
+//======================================================
+/* < et > */
+%token INFCAR SUPCAR 
+//======================================================
+/* / = a1  texte "texte" */
+%token SLASH Eq CHARDATA ATTVALUE PAIR SPAIR EPAIR EPAIRS ANID
+%type <chaine> PAIR
+%type <chaine> EPAIRS
+%type <chaine> EPAIR
+%type <chaine> SPAIR
+
+//======================================================
+/* <!-- xxx -> <? xxx yyy ?> */
+%token PI PIERROR /** COMMENT **/
+//======================================================
+/* <!-- xxx -> <? xxx yyy ?> */
+%token ERREURGENERALE CDATA WHITESPACE NEWLINE
+//======================================================
+// non terminaux typés
+//======================================================
+/* elements non terminaux de type char *     */
+/* uniquement ceux qui devrons etre comparés */
+//======================================================
+%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 {crerror("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	
+{
+	/* les non terminaux rendent les valeurs de leur identifiants de balise */
+	/* en char*, donc on peut comparer ces valeurs avec la fonction C++ strcmp(const char*;const char*) */
+	/* de string */
+	if (strcmp($1,$3) != 0)
+	{
+	   crerror("Opening and ending tag mismatch");
+	   printf("\n  ::details : tag '%s' et '%s' \n",$1,$3);
+	   return 1;
+	   // on retourne different de 0
+	   // sinon yyparse rendra 0
+	   // et dans le main on croira a le fichier xml est valide !
+	}
+}
+// 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
+	printf("* Identifiant : %s\n",$2);
+#endif
+	
+	$$ = $2 ;
+}
+ ;
+//======================================================
+// 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		
+{
+	// on verifie que les attributst ne sont pas en double
+	// sinon on ajoute au vector
+}
+ ;
+//======================================================
+// 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	{}
+ ;
+//======================================================
+// ETag
+//======================================================
+// regle 42
+// BALISE FERMANTE
+// les separateurs après ID sont filtrés
+//======================================================
+ETag
+ : INFCAR SLASH ID SUPCAR
+{
+  /* on renvoie l'identifiant de la balise pour pouvoir comparer les 2 */
+  /* /!\ une balise fermante n'a pas d'attributs (c.f. : W3C) */
+  $$ = $3;
+}
+ ;
+//======================================================
+// 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	          {crerror("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 {curr_key=strdup($1);/*printf("START 0 PAIR FOUND !! \n [%s]\n",$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=strdup($1);if(debug) printf("SPAIR FOUND !!\n"); }
+ ;
+
+
+processid
+ : ANID  {
+   if(current_maps->name!=NULL){
+     current_maps->content=current_content;
+     current_maps->next=(maps*)malloc(MAP_SIZE);
+     current_maps=current_maps->next;
+     current_maps->name=strdup($1);
+     current_content=NULL;
+   }
+   else{
+     current_maps->name=strdup($1);
+   }
+ }
+ ;
+
+%%
+
+// crerror
+//======================================================
+/* fonction qui affiche l erreur si il y en a une */
+//======================================================
+void crerror(char *s)
+{
+  if(debug)
+    printf("\nligne %d : %s\n",crlineno,s);
+}
+
+// main
+//======================================================
+/* fonction principale : entrée dans le programme */
+//======================================================
+int conf_read(char* file,maps* my_map){
+  /* mode debug ou pas : */
+  /* 1 = debug , 0 = normal */
+  //yydebug = 1;
+  
+  crin = fopen(file,"r");
+  if (crin==NULL){
+    printf("error : le fichier specifie n'existe pas ou n'est pas accessible en lecture\n") ;
+    return 2 ;
+  }
+
+  //my_map=(maps*)malloc(sizeof(maps*));
+  my_maps=my_map;
+  my_maps->name=NULL;
+  current_maps=my_maps;
+  
+  int resultatYYParse = crparse() ;
+
+  if(current_content!=NULL)
+    current_maps->content=current_content;
+	  
+  //dumpMaps(my_maps);
+
+  fclose(crin);
+  return resultatYYParse;
+}
+
+
+void usage(void)
+{
+    printf("usage : $./test1 <fichier_de_configuration_principale>\n") ;	 
+}
+//======================================================
+// FIN //
+//======================================================
Index: trunk/zoo-kernel/makefile.vc
===================================================================
--- trunk/zoo-kernel/makefile.vc	(revision 1)
+++ trunk/zoo-kernel/makefile.vc	(revision 1)
@@ -0,0 +1,60 @@
+GEODIR=c:/OSGeo4W
+DESTDIR=c:/OSGeo4W
+TPATH=..\..\..\tools
+TOOLS=$(TPATH)\bin
+CFLAGS=/EHa /nologo /MT /W3 /GX /O2 /D_CRT_SECURE_NO_WARNINGS /DWIN32 $(CJFLAGS) -I./ -I..\thirds\dirent-win32 -IC:\OSGeo4W\apps\Python25\include -I$(GEODIR)/include -I$(TPATH)\include -DLINUX_FREE_ISSUE #-DDEBUG
+CC=cl $(CFLAGS)
+CPP=cl /TP $(CFLAGS)
+
+all:  service_loader
+
+service_loader: service.h lex.sr.obj service_conf.tab.obj service_conf.y service_internal_python.obj service_loader.obj main_conf_read.tab.obj lex.cr.obj service_internal.obj
+	cl $(CFLAGS) lex.sr.obj service_conf.tab.obj main_conf_read.tab.obj lex.cr.obj service_internal.obj service_internal_python.obj service_loader.obj -o service_loader -ldl `python-config --libs` `xml2-config --libs` -lfl -lcurl
+
+main_conf_read.tab.c: main_conf_read.y service.h
+	$(TOOLS)\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
+	$(TOOLS)\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
+	$(TOOLS)\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
+	$(TOOLS)\flex -Psr service_conf.l
+
+lex.sr.obj: lex.sr.c service.h
+	$(CPP) $(CFLAGS) /c lex.sr.c
+
+service_internal.obj: service_internal.c
+	$(CPP) $(CFLAGS) /c service_internal.c
+
+service_internal_python.obj: service_internal_python.c service.h
+	$(CPP) /c $(CFLAGS) service_internal_python.c
+
+service_internal_java.obj: service_internal_java.c service.h
+	$(CPP) /c $(CFLAGS) $(CJFLAGS) service_internal_java.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
+
+zoo_loader.cgi: zoo_loader.obj zoo_service_loader.obj service_internal.obj service_internal_python.obj ulinet.obj lex.cr.obj lex.sr.obj service_conf.tab.obj main_conf_read.tab.obj dirent.obj
+	link zoo_loader.obj dirent.obj service_internal.obj service_internal_python.obj ulinet.obj main_conf_read.tab.obj lex.cr.obj service_conf.tab.obj lex.sr.obj  zoo_service_loader.obj /out:zoo_loader.cgi  $(GEODIR)/lib/libfcgi.lib $(GEODIR)/lib/libcurl_imp.lib  $(GEODIR)/apps/Python25/libs/python25.lib $(GEODIR)/lib/libxml2.lib $(GEODIR)/lib/libcgic.lib $(GEODIR)/lib/gdal_i.lib $(TOOLS)\..\lib\libeay32.dll.a $(TOOLS)\..\lib\libcrypto.a $(TOOLS)\..\lib\libssl32.dll.a /machine:i386 
+
+clean:
+	erase -f *.obj *.tab.c* *.tab.h *.sr.c* lex.* *.lreg *.sibling
Index: trunk/zoo-kernel/service.c
===================================================================
--- trunk/zoo-kernel/service.c	(revision 1)
+++ trunk/zoo-kernel/service.c	(revision 1)
@@ -0,0 +1,58 @@
+#include "service.h"
+
+map* createMap(char* name,char* value){
+  map* tmp=(map *)malloc(sizeof(map*));
+  tmp->name=strdup(name);
+  tmp->value=strdup(value);
+  tmp->next=NULL;
+  return tmp;
+}
+
+bool hasKey(map* m,char *key){
+  map* tmp=m;
+  while(tmp!=NULL){
+    if(strcmp(tmp->name,key)==0)
+      return true;
+    tmp=tmp->next;
+  }
+#ifdef DEBUG_MAP
+  printf("NOT FOUND \n");
+#endif
+  return false;
+}
+
+map* getMap(map* m,char *key){
+  map* tmp=m;
+  while(tmp!=NULL){
+    if(strcmp(tmp->name,key)==0)
+      return tmp;
+    tmp=tmp->next;
+  }
+  return NULL;
+}
+
+void* addToMap(map* m,char* n,char* v){
+  if(hasKey(m,n)==false){
+    map* _cursor=m;
+    while(_cursor->next)
+      _cursor=_cursor->next;
+    _cursor->next=createMap(n,v);
+  }
+  else{
+    map *tmp=getMap(m,n);
+    tmp->value=strdup(v);
+  }
+}
+
+void* _dumpMap(map* t){
+  fprintf(stderr,"[%s] => [%s] \n",t->name,t->value);
+  fflush(stderr);
+}
+
+void* dumpMap(map* t){
+  map* tmp=t;
+  while(tmp!=NULL){
+    _dumpMap(tmp);
+    tmp=tmp->next;
+  }
+}
Index: trunk/zoo-kernel/service.h
===================================================================
--- trunk/zoo-kernel/service.h	(revision 1)
+++ trunk/zoo-kernel/service.h	(revision 1)
@@ -0,0 +1,540 @@
+/**
+ * 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_H
+#define ZOO_SERVICE_H 1
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+
+#define bool int
+#define true 1
+#define false -1
+#define SERVICE_ACCEPTED 0
+#define SERVICE_STARTED 1
+#define SERVICE_PAUSED 2
+#define SERVICE_SUCCEEDED 3
+#define SERVICE_FAILED 4
+#define ELEMENTS_SIZE (sizeof(char*)+(((2*sizeof(char*))+sizeof(maps*))*2)+sizeof(char*)+(((2*sizeof(char*))+sizeof(iotype*))*2)+sizeof(elements*))
+#define MAP_SIZE (2*sizeof(char*))+sizeof(map*)
+#define MAPS_SIZE (2*sizeof(char*))+sizeof(map*)+sizeof(maps*)
+
+
+  static char* mtoupper(char* str){
+    char* tmp=strdup(str);
+    if(tmp){
+      int cnt=strlen(tmp);
+      int i;
+      for(i=0;i<cnt;i++){
+	tmp[i]=toupper(str[i]);
+	tmp[i+1]=0;
+      }
+    }
+    else
+      tmp[0]=0;
+    return tmp;
+  }
+
+  typedef struct maps{
+    char* name;
+    struct map* content;
+    struct maps* next;
+  } maps;
+
+  typedef struct map{
+    char* name;
+    char* value;
+    struct map* next;
+  } map;
+
+#ifdef WIN32
+#define NULLMAP ((map*) 0)
+#else
+#define NULLMAP NULL
+#endif
+
+  static 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);
+    }
+    return NULL;
+  }
+
+  static void* dumpMap(map* t){
+    map* tmp=t;
+    while(tmp!=NULL){
+      _dumpMap(tmp);
+      tmp=tmp->next;
+    }
+    return NULL;
+  }
+
+  static void dumpMaps(maps* m){
+    maps* tmp=m;
+    while(tmp!=NULL){
+      fprintf(stderr,"MAP => [%s] \n",tmp->name);
+      dumpMap(tmp->content);
+      tmp=tmp->next;
+    }
+  }
+
+  static map* createMap(char* name,char* value){
+    map* tmp=(map *)malloc(MAP_SIZE);
+    tmp->name=strdup(name);
+    tmp->value=strdup(value);
+    tmp->next=NULL;
+    return tmp;
+  }
+
+  static int count(map* m){
+    map* tmp=m;
+    int c=0;
+    while(tmp!=NULL){
+      c++;
+      tmp=tmp->next;
+    }
+    return c;
+  }
+    
+  static bool hasKey(map* m,char *key){
+    map* tmp=m;
+    while(tmp!=NULL){
+      if(strcmp(mtoupper(tmp->name),mtoupper(key))==0)
+	return true;
+      tmp=tmp->next;
+    }
+#ifdef DEBUG_MAP
+    fprintf(stderr,"NOT FOUND \n");
+#endif
+    return false;
+  }
+
+  static maps* getMaps(maps* m,char *key){
+    maps* tmp=m;
+    while(tmp!=NULL){
+      if(strcmp(mtoupper(tmp->name),mtoupper(key))==0)
+	return tmp;
+      tmp=tmp->next;
+    }
+    return NULL;
+  }
+
+  static map* getMap(map* m,char *key){
+    map* tmp=m;
+    while(tmp!=NULL){
+      if(strcmp(mtoupper(tmp->name),mtoupper(key))==0)
+	return tmp;
+      tmp=tmp->next;
+    }
+    return NULL;
+  }
+
+  static map* getMapFromMaps(maps* m,char* key,char* subkey){
+    maps* _tmpm=getMaps(m,key);
+    if(_tmpm!=NULL){
+      map* tmpm=getMap(_tmpm->content,mtoupper(subkey));
+      return tmpm;
+    }
+    else return NULL;
+  }
+
+  static void* freeMap(map** mo){
+    map* _cursor=*mo;
+    if(_cursor!=NULL){
+      free(_cursor->name);
+      free(_cursor->value);
+      if(_cursor->next!=NULL){
+	freeMap(&_cursor->next);
+	free(_cursor->next);
+      }
+    }
+	return NULL;
+  }
+
+
+  typedef struct iotype{
+    struct map* content;
+    struct iotype* next;
+  } iotype;
+
+  typedef struct elements{
+    char* name;
+    struct map* content;
+    struct map* metadata;
+    char* format;
+    struct iotype* defaults;
+    struct iotype* supported;
+    struct elements* next;
+  } elements;
+
+  typedef struct service{
+    char* name;
+    struct map* content;
+    struct map* metadata;
+    struct elements* inputs;
+    struct elements* outputs; 
+  } service;
+
+  typedef struct services{
+    struct service* content; 
+    struct services* next; 
+  } services;
+
+  static bool hasElement(elements* e,char* key){
+    elements* tmp=e;
+    while(tmp!=NULL){
+      mtoupper(key);
+      mtoupper(tmp->name);
+      if(strcmp(key,tmp->name)==0)
+	return true;
+      tmp=tmp->next;
+    }
+    return false;
+  }
+
+  static elements* getElements(elements* m,char *key){
+    elements* tmp=m;
+    while(tmp!=NULL){
+      mtoupper(tmp->name);
+      mtoupper(key);
+      if(strcmp(tmp->name,key)==0)
+	return tmp;
+      tmp=tmp->next;
+    }
+    return NULL;
+  }
+
+
+  static void* freeIOType(iotype** i){
+    iotype* _cursor=*i;
+    if(_cursor!=NULL){
+      freeMap(&_cursor->content);
+      free(_cursor->content);
+      freeIOType(&_cursor->next);
+      free(_cursor->next);
+    }
+	return NULL;
+  }
+
+  static void freeElements(elements** e){
+    elements* tmp=*e;
+    if(tmp!=NULL){
+#ifdef DEBUG
+      fprintf(stderr,"FREE 1");
+#endif
+      free(tmp->name);
+      freeMap(&tmp->content);
+#ifdef DEBUG
+      fprintf(stderr,"FREE 2");
+#endif
+      free(tmp->content);
+      freeMap(&tmp->metadata);
+#ifdef DEBUG
+      fprintf(stderr,"FREE 3");
+#endif
+      free(tmp->metadata);
+#ifdef DEBUG
+      fprintf(stderr,"FREE 4");
+#endif
+      free(tmp->format);
+      freeIOType(&tmp->defaults);
+#ifdef DEBUG
+      fprintf(stderr,"FREE 5");
+#endif
+      if(tmp->defaults!=NULL)
+	free(tmp->defaults);
+      freeIOType(&tmp->supported);
+#ifdef DEBUG
+      fprintf(stderr,"FREE 6");
+#endif
+      if(tmp->supported!=NULL)
+	free(tmp->supported);
+      tmp=tmp->next;
+    }
+  }
+
+  static void* freeService(service** s){
+    service* tmp=*s;
+    if(tmp!=NULL){
+      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);
+    }
+  }
+
+  static void* addMapToMap(map** mo,map* mi){
+    map* tmp=mi;
+    map* _cursor=*mo;
+    while(tmp!=NULL){
+      if(_cursor==NULL){
+	*mo=(map*)malloc(MAP_SIZE);
+	*mo=createMap(tmp->name,tmp->value);
+	_cursor=*mo;
+	_cursor->next=NULL;
+      }
+      else{
+	while(_cursor->next!=NULL)
+	  _cursor=_cursor->next;
+	_cursor->next=createMap(tmp->name,tmp->value);
+      }
+      tmp=tmp->next;
+    }
+    return NULL;
+  }
+
+  static void* addMapsToMaps(maps** mo,maps* mi){
+    maps* tmp=mi;
+    maps* _cursor=*mo;
+    while(tmp!=NULL){
+      if(_cursor==NULL){
+	*mo=(maps*)malloc(MAP_SIZE);
+	*mo=mi;
+	_cursor=*mo;
+      }
+      else{
+	while(_cursor->next!=NULL)
+	  _cursor=_cursor->next;
+	_cursor->next=tmp;
+      }
+      tmp=tmp->next;
+    }
+    return NULL;
+  }
+
+  static void* addMapToIotype(iotype** io,map* mi){
+    iotype* tmp=*io;
+    while(tmp!=NULL){
+      fprintf(stderr,">> CURRENT MAP");
+      dumpMap(tmp->content);
+      tmp=tmp->next;
+    }
+    tmp=(iotype*)malloc(ELEMENTS_SIZE);
+    tmp->content=NULL;
+    tmp->next=NULL;
+    addMapToMap(&tmp->content,mi);
+    return NULL;
+  }
+
+  static void* addToMap(map* m,char* n,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);
+      tmp->value=strdup(v);
+    }
+    return NULL;
+  }
+
+
+  static 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;
+    }
+    return NULL;
+  }
+
+
+  static elements* dupElements(elements* e){
+    if(e!=NULL){
+#ifdef DEBUG
+      dumpElements(e);
+#endif
+      elements* tmp=(elements*)malloc(ELEMENTS_SIZE);
+      tmp->name=strdup(e->name);
+      tmp->content=NULL;
+      addMapToMap(&tmp->content,e->content);
+      tmp->metadata=NULL;
+      addMapToMap(&tmp->metadata,e->metadata);
+      tmp->format=strdup(e->format);
+      if(e->defaults!=NULL){
+	tmp->defaults=(iotype*)malloc(MAP_SIZE);
+	tmp->defaults->content=NULL;
+	tmp->defaults->next=NULL;
+	addMapToMap(&tmp->defaults->content,e->defaults->content);
+	while(e->defaults->next!=NULL){
+	  tmp->defaults->next=(iotype*)malloc(MAP_SIZE);
+	  addMapToMap(&tmp->defaults->next->content,e->defaults->content);
+	}
+      }
+      if(e->supported!=NULL){
+	tmp->supported=(iotype*)malloc(MAP_SIZE);
+	tmp->supported->content=NULL;
+	tmp->supported->next=NULL;
+	addMapToMap(&tmp->supported->content,e->supported->content);
+	iotype *tmp2=e->supported->next;
+	while(tmp2!=NULL){
+	  tmp->supported->next=(iotype*)malloc(MAP_SIZE);
+	  addMapToMap(&tmp->supported->next->content,tmp2->content);
+	  tmp2=tmp2->next;
+	}
+      }
+      tmp->next=NULL;
+      return tmp;
+    }
+    return NULL;
+  }
+
+  static void* addToElements(elements* m,elements* e){
+    elements* _cursor=m;
+    elements* tmp=e;
+    if(_cursor==NULL){
+      m=dupElements(tmp);
+      return NULL;
+    }
+    while(_cursor->next!=NULL)
+      _cursor=_cursor->next;
+    _cursor->next=dupElements(tmp);
+    return NULL;
+  }
+
+  static void* dumpService(service* s){
+    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");
+    return NULL;
+  }
+
+  static 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);
+	return NULL;
+  }
+
+  static 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
+	addMapToMap(&trorf->content,createMap(tmp[i][j],tmp[i][j+1]));
+      }
+      trorf=trorf->next;
+    }
+    m=&trorf;
+    return NULL;
+  }
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: trunk/zoo-kernel/service_conf.l
===================================================================
--- trunk/zoo-kernel/service_conf.l	(revision 1)
+++ trunk/zoo-kernel/service_conf.l	(revision 1)
@@ -0,0 +1,220 @@
+/* pour pouvoir acceder au numero de ligne dans bison */
+%option noyywrap
+%option yylineno
+
+
+%{
+//======================================================
+/**
+
+ fichier flex de verification xml
+ ter d'analyse syntaxique 2006-2007
+ ==================================
+ 
+ auteurs:
+ Jean-Marie CODOL
+   &
+ Naitan GROLLEMUND
+
+
+
+
+======
+ ce fichier est li�a 3 autres fichiers :
+ parser.y
+ makefile
+ README
+ 
+ pour compiler ce projet :
+ 	  linux : taper $make all
+ 	  windows : ouvrir avec dev-c++, configurer le makefile du projet et compiler
+	            naviguer avec la ligne de commande jusqu'au repertoire.
+======
+
+
+ pour plus d'informations, voir le README
+
+
+**/
+//======================================================
+
+
+//======================================================
+/* pour avoir acces a strdup() */
+/* en effet, il faut garder une trace de la valeur */
+/* car yytext va varier et on ne pourra plus reconnaitre les */
+/* identifiants si on ne copie pas ces valeurs */
+#include <string.h>
+
+//======================================================
+/* pour la liaison avec bison */
+#include "service_conf.tab.h"
+
+//======================================================
+/* afficher ou pas une trace : */
+#ifdef DEBUG_SERVICE_CONF
+int affichetrace = 1;
+#else
+int affichetrace = 0;
+#endif
+//======================================================
+
+
+//======================================================
+/* on a l interdiction de mettre un commentaire avant une declaration : */
+int attentionImpossibleDeTrouverXMLDeclapres = 0 ;
+//======================================================
+
+//======================================================
+/* on a l interdiction de mettre un pi avant une declaration : */
+int attentionImpossibleDeTrouverPIapres = 0 ;
+//======================================================
+
+%}
+
+
+/*====================================================*/
+/*====================================================*/
+/* Les Separateurs xml */
+/*====================================================*/
+S		[ \t\r\n]+
+/*====================================================*/
+
+
+
+
+/*====================================================*/
+/* CharRef regle 66 */
+/*====================================================*/
+CharRef		"&#"[0-9]+";"|"&#x"[0-9a-fA-F]+";"
+/*====================================================*/
+
+
+
+
+/*====================================================*/
+/*   espaces? '=' espaces?    regle 25  */
+/* si on veut pouvoir utiliser S dans bison, */
+/* il faut cr�r au moins une autre start condition */
+/* comme on n'utilise "egalevolue" que pour version et encoding */
+/* il est pr��able de rajouter cette macro */
+/*====================================================*/
+egalevolue		{S}?"="{S}?
+/*====================================================*/
+
+
+
+
+/*====================================================*/
+/* Name regle 5 */
+/*====================================================*/
+/*** Name		[a-zA-Z_:][a-zA-Z0-9.\-_:]* ***/
+Name		([_:]|[\x41-\x5A]|[\x61-\x7A]|[\xC0-\xD6]|[\xD8-\xF6]|[\xF8-\xFF])(([\x41-\x5A]|[\x61-\x7A]|[\xC0-\xD6]|[\xD8-\xF6]|[\xF8-\xFF])|[0-9.\-_:])*
+/*====================================================*/
+
+
+
+
+
+/*====================================================*/
+/* chardata  regle 14 */
+/*====================================================*/
+/**chardata	[a-zA-Z0-9_\-.:" "\"\'\\]***/
+chardata	[^<]*
+/*====================================================*/
+attname	[a-zA-Z0-9_\-]+
+attvalue1	[a-zA-Z0-9_\-.:" "\"\'/\\\(\)]+
+
+
+
+
+
+/*====================================================*/
+/* attvalue regle 10 */
+/*====================================================*/
+/* attvalue		\"([^"&]|{CharRef})*\"|\'([^'&]|{CharRef})*\' */
+/* pas tr� classe mais ca marche . */
+attvalue		\"[^"]*\"|\'[^']*\'\(\)
+/*====================================================*/
+
+whitespace                      [ ]{0,}
+whitesp                      [ ]
+newline                 [\r\n]|[\n]
+newlines                 [\r\n]{1,}|[\n]{1,}
+
+
+/*====================================================*/
+/* initial = de debut a ?> du prolog ; DANSBALISE = dans une balise ; HORSBALISE = hors d'une balise */
+/*====================================================*/
+%x DANSBALISE HORSBALISE PAIRSTART
+/*====================================================*/
+
+
+
+
+%%
+
+"\n" {  if (affichetrace==1) fprintf (stderr,"\n\nNEWLINE\n") ;return NEWLINE;}
+
+{newline}+{whitesp}*			{  if (affichetrace==1) fprintf (stderr,"\n\nNEWLINE 1\n") ; return NEWLINE;}
+
+<INITIAL,HORSBALISE>"["{attname}"]"             {  if (affichetrace==1){ fprintf (stderr,"\n\nANID:%s\n",yytext); fprintf(stderr,"[ZOO: service_conf.l line 161 srlval.chaine=strdup(%s), srlval.chaine=%s]\n",yytext,srlval.chaine);fflush(stderr);}srlval.chaine=strdup(yytext);srlval.chaine[strlen(srlval.chaine)-1]=0;srlval.chaine+=1;if (affichetrace==1){fprintf(stderr,"[ZOO: service_conf.l line 161 srlval.chaine=strdup(%s) done]\n",yytext);fflush(stderr);} return ANID; }
+
+<INITIAL,HORSBALISE>{attname}             {  if (affichetrace==1){fprintf (stderr,"\n\nATT_NAME:%s\n",yytext); fprintf(stderr,"[ZOO: service_conf.l line 163 srlval.chaine=strdup(%s)]\n",yytext);fflush(stderr);}srlval.chaine=strdup(yytext); if (affichetrace==1){fprintf(stderr,"[ZOO: service_conf.l line 163 srlval.chaine=strdup(%s) done]\n",yytext);fflush(stderr);} return SPAIR; }
+
+<PAIRSTART,HORSBALISE>{attvalue1}             { if (affichetrace==1){ fprintf (stderr,"\n\nATT_VALUE:%s\n",yytext);fprintf(stderr,"[ZOO: service_conf.l line 165 srlval.chaine=strdup(%s)]\n",yytext);fflush(stderr);}srlval.chaine=strdup(yytext);if (affichetrace==1){fprintf(stderr,"[ZOO: service_conf.l line 165 srlval.chaine=strdup(%s)]\n",yytext);fflush(stderr);BEGIN(INITIAL);} return EPAIR;}
+
+<PAIRSTART,INITIAL,HORSBALISE>{whitesp}*"="{whitesp}*             {  BEGIN(PAIRSTART);}
+
+<PAIRSTART,INITIAL,HORSBALISE,DANSBALISE>{newline}+{whitesp}*             { if (affichetrace==1) fprintf (stderr,"\n\nNEWLINE 2\n") ; BEGIN(INITIAL);  return NEWLINE;}
+
+<INITIAL>"<?"[Xx][Mm][Ll]  {   if (attentionImpossibleDeTrouverXMLDeclapres == 1 || attentionImpossibleDeTrouverPIapres == 1) {/* il y a eut un commentaire ou une balise applicative avant la declaration xml */ fprintf(stderr,"\nerror : a la ligne %d : il y a eut un commentaire ou un PI avant la declaration xml\n",srlineno); exit (10) ; } ; if (affichetrace==1) fprintf (stderr,"\n\nSTARTXMLDECL:%s\n",srtext) ;  return STARTXMLDECL;}
+
+<INITIAL>"version"{egalevolue}\"1.0\"|"version"{egalevolue}\'1.0\'  {  if (affichetrace==1) fprintf (stderr,"\n\nVERSIONDECL:%s\n",srtext) ;return VERSIONDECL;  }
+<INITIAL>"version"{egalevolue}\"[^"]*\"|"version"{egalevolue}\'[^']*\'  {/* erreur de version encoding */ fprintf(stderr,"\nerror : a la ligne %d : la version xml n est pas reconnue : %s\n",srlineno,yytext); exit (9) ; }
+
+
+<INITIAL>"encoding"{egalevolue}\"[Ii][Ss][Oo]"-8859-1"\"|"encoding"{egalevolue}\'[Ii][Ss][Oo]"-8859-1"\'  { if (affichetrace==1) fprintf (stderr,"\n\nENCODINGDECL:%s\n",yytext) ; return ENCODINGDECL;}
+<INITIAL>"encoding"{egalevolue}\"[^"]*\"|"encoding"{egalevolue}\'[^']*\'  {/* erreur de version encoding */ 	fprintf(stderr,"\nerror : a la ligne %d : la version d encodage n est pas reconnue : %s\n",srlineno,yytext); exit (8) ; }
+
+
+<INITIAL>"standalone"{egalevolue}\"yes\"|"standalone"{egalevolue}\'yes\'|"standalone"{egalevolue}\"no\"|"standalone"{egalevolue}\'no\'  { if (affichetrace==1) fprintf (stderr,"\n\nSDDECL:%s\n",yytext) ; return SDDECL;}
+
+<INITIAL>"standalone"{egalevolue}\"[^"]*\"|"standalone"{egalevolue}\'[^']*\'|"standalone"{egalevolue}\"[^"]*\"|"standalone"{egalevolue}\'[^']*\'  { /* erreur de version encoding */ 	fprintf(stderr,"\nerror : a la ligne %d : la version standalone n est pas reconnue : %s\n",srlineno,yytext); exit (7) ; }
+
+
+<INITIAL>"?>"  { if (affichetrace==1) fprintf (stderr,"\n\nENDXMLDECL:%s\n",yytext) ; BEGIN(HORSBALISE); return ENDXMLDECL;}
+
+
+<DANSBALISE,INITIAL,HORSBALISE>{S}   { if (affichetrace==1) fprintf (stderr,"\n\nS:'%s'\n",yytext) ; }
+
+
+<HORSBALISE>"<?"[Xx][Mm][Ll]{S}({S}|{chardata})*"?>"|"<?"[Xx][Mm][Ll]"?>"	{ if (affichetrace==1) fprintf (stderr,"\n\nPIERROR:%s\n",yytext) ; return PIERROR;}
+<INITIAL,HORSBALISE>"<?"([^xX]|([xX][^mM])|([xX][mM][^lL]))({S}|([^?]|("?"[^>])))*"?>"		{ attentionImpossibleDeTrouverPIapres=1 ;  if (affichetrace==1) fprintf (stderr,"\n\nPI:%s\n",yytext) ; return PI;}
+
+
+<INITIAL,HORSBALISE>{newline}*"<"		    { if (affichetrace==1) fprintf (stderr,"\n\nINFCAR:%s\n",yytext) ; BEGIN(DANSBALISE); return INFCAR;}
+
+
+<DANSBALISE>">"			{ if (affichetrace==1) fprintf (stderr,"\n\nSUPCAR:%s\n",yytext) ; BEGIN(HORSBALISE);return SUPCAR;}
+
+
+<DANSBALISE>"/"		{if (affichetrace==1) fprintf (stderr,"\n\nSLASH:%s\n",yytext) ; return SLASH;}
+
+
+<DANSBALISE>{egalevolue}			{if (affichetrace==1) fprintf (stderr,"\n\nEq:'%s'\n",yytext) ; return Eq;}
+
+
+<DANSBALISE>{Name}			{if (affichetrace==1){fprintf (stderr,"\n\nID:%s\n",yytext) ; fprintf(stderr,"[ZOO: service_conf.l line 208 srlval.chaine=strdup(%s)]\n",yytext);fflush(stderr);}srlval.s=strdup(yytext);if (affichetrace==1){fprintf(stderr,"[ZOO: service_conf.l line 208 srlval.chaine=strdup(%s)]\n",yytext);fflush(stderr);}return ID;}
+
+
+<DANSBALISE>{attvalue}		{if (affichetrace==1) fprintf (stderr,"\n\nATTVALUE:%s\n",yytext) ; return ATTVALUE;}
+
+
+<INITIAL,HORSBALISE>"<!--"([^-]|"-"[^-])*"-->"		{attentionImpossibleDeTrouverXMLDeclapres=1; }
+
+
+<INITIAL,DANSBALISE,HORSBALISE>.|\n	{if (affichetrace==1) fprintf(stderr,"error : ligne %d : caractere non reconnu '%s'\n",srlineno,yytext);}
+
+%%
+
Index: trunk/zoo-kernel/service_conf.y
===================================================================
--- trunk/zoo-kernel/service_conf.y	(revision 1)
+++ trunk/zoo-kernel/service_conf.y	(revision 1)
@@ -0,0 +1,772 @@
+%{
+//======================================================
+/**
+ * Thx to Jean-Marie CODOL and Naitan GROLLEMUND
+ * copyright 2009 GeoLabs SARL 
+ * Author : Gérald FENOY
+ *
+ */
+//======================================================
+
+#include <string>
+#include <stdio.h>
+#include <ctype.h>
+#include <service.h>
+#include <vector>
+
+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 int services_c=0;
+static service* my_service=NULL;
+static map* previous_content=NULL;
+static map* current_content=NULL;
+static elements* current_element=NULL;
+static map* scontent=NULL;
+static char* curr_key;
+static int debug=0;
+static int data=-1;
+static int previous_data=0;
+static int current_data=0;
+static char* myFinalObjectAsJSON="{";
+// namespace
+using namespace std;
+//======================================================
+
+// srerror
+void srerror(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);
+
+vector<char*> lattribute;
+
+%}
+
+
+
+%union 
+{char * s;char* chaine;char* key;char* val;}
+
+// jetons //
+%token <s> ID
+%token <s> CHAINE
+/* STARTXMLDECL et ENDXMLDECL qui sont <?xml et ?>*/
+%token STARTXMLDECL ENDXMLDECL
+//======================================================
+/* version="xxx" et encoding="xxx" */
+%token VERSIONDECL ENCODINGDECL SDDECL
+//======================================================
+/* < et > */
+%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	
+{
+  if (strcmp($1,$3) != 0)
+    {
+      //srerror("Opening and ending tag mismatch");
+      fprintf(stderr,"Opening and ending tag mismatch\n  ::details : tag '%s' et '%s' \n",$1,$3);
+      lattribute.clear();
+      //return 1;
+    }
+}
+// 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
+{
+  /* l'astuce consiste a vider le contenu du vector ici !! */
+  /* parce que cet element est reconnu AVANT la balise fermante */
+  /* et APRES l'analyse des eventuelles balises internes ou successeur */
+  lattribute.clear();
+	
+  if(my_service->content==NULL){
+#ifdef DEBUG_SERVICE_CONF
+    fprintf(stderr,"NO CONTENT\n");
+#endif
+    //addMapToMap(&my_service->content,current_content);
+    //freeMap(&current_content);
+    my_service->content=current_content;
+    current_content=NULL;
+    my_service->metadata=NULL;
+    wait_maincontent=false;
+  }
+
+  if(strcmp($2,"DataInputs")==0){
+    if(wait_mainmetadata==true){
+      if(my_service->metadata==NULL)
+	my_service->metadata=current_content;
+      else{
+	addMapToMap(&my_service->metadata,current_content);
+	freeMap(&current_content);
+      }
+      current_content=NULL;
+    }
+    if(current_element==NULL){
+#ifdef DEBUG_SERVICE_CONF
+      fprintf(stderr,"(DATAINPUTS - 184) FREE current_element\n");
+#endif
+      freeElements(&current_element);
+      free(current_element);
+      current_element=NULL;
+#ifdef DEBUG_SERVICE_CONF
+      fprintf(stderr,"(DATAINPUTS - 186) ALLOCATE current_element\n");
+#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->next=NULL;
+    }
+    wait_inputs=true;
+    current_data=1;
+    previous_data=1;
+  }
+  else
+    if(strcmp($2,"DataOutputs")==0){
+      if(wait_inputs==true){
+#ifdef DEBUG_SERVICE_CONF
+	fprintf(stderr,"(DATAOUTPUTS) DUP INPUTS current_element\n");
+#endif
+	if(my_service->inputs==NULL)
+	  my_service->inputs=dupElements(current_element);
+	else
+	  addToElements(my_service->inputs,current_element);
+#ifdef DEBUG_SERVICE_CONF
+	dumpElements(current_element);
+	dumpElements(my_service->inputs);
+	fprintf(stderr,"(DATAOUTPUTS) FREE current_element\n");
+#endif
+	freeElements(&current_element);
+	free(current_element);
+	current_element=NULL;
+	wait_inputs=false;
+      }
+      if(current_element==NULL){
+#ifdef DEBUG_SERVICE_CONF
+	fprintf(stderr,"(DATAOUTPUTS - 206) ALLOCATE current_element (%s)\n",$2);
+#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;
+      }
+      wait_outputs=true;
+      current_data=2;
+      previous_data=1;
+    }
+    else
+      if(strcmp($2,"MetaData")==0){
+	current_data=3;
+	if(current_element!=NULL){
+	  wait_metadata=true;
+#ifdef DEBUG_SERVICE_CONF
+	  fprintf(stderr,"add current_content to current_element->content\n");
+	  fprintf(stderr,"LINE 247");
+#endif
+	  addMapToMap(&current_element->content,current_content);
+	  freeMap(&current_content);
+	  free(current_content);
+	}
+	else{
+	  wait_mainmetadata=true;
+	}
+	current_content=NULL;
+      }
+      else
+	if(strcmp($2,"ComplexData")==0 || strcmp($2,"LiteralData")==0
+	|| strcmp($2,"ComplexOutput")==0 || strcmp($2,"LiteralOutput")==0){
+	  current_data=4;
+	  if(wait_metadata==true){
+	    if(current_content!=NULL){
+	      current_element->metadata=current_content;
+	      current_element->next=NULL;
+	      current_element->format=$2;
+	      current_element->defaults=NULL;
+	    }
+	  }else{ // No MainMetaData
+	    //addMapToMap(&current_element->content,current_content);
+	    //freeMap(&current_content);
+	    //free(current_content);
+	    current_element->content=current_content;
+	    current_element->metadata=NULL;
+	    current_element->next=NULL;
+	    current_element->format=$2;
+	    current_element->defaults=NULL;
+	  }
+	  current_content=NULL;
+	  wait_metadata=false;
+	}
+	else
+	  if(strcmp($2,"Default")==0){
+	    wait_defaults=true;
+	    current_data=5;
+	  }
+	  else
+	    if(strcmp($2,"Supported")==0){
+	      wait_supporteds=true;
+	      if(wait_defaults==true){
+		defaultsc++;
+		freeMap(&current_content);
+		current_content=NULL;
+	      }
+	      current_data=5;
+	    }
+#ifdef DEBUG_SERVICE_CONF
+  printf("* Identifiant : %s\n",$2);
+#endif
+		
+  /* et on renvoie l'identifiant de balise afin de pouvoir le comparer */
+  /* avec la balise jumelle fermante ! */
+  $$ = $2 ;
+}
+ ;
+//======================================================
+// 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		
+{
+	// on verifie que les attributst ne sont pas en double
+	// sinon on ajoute au vector
+#ifdef DEBUG_SERVICE_CONF
+  printf ("attribute : %s\n",$1) ;
+#endif
+  for(int i=0;i < lattribute.size(); i++)
+    {
+      if (strcmp($1,lattribute.at(i)) == 0)
+	{
+	  fprintf (stderr,"attributs identiques : %d -- %s , %s",i,lattribute.at(i),$1) ;
+	  //srerror("attribut redondant !:");
+	}
+    }
+  lattribute.push_back($1);
+}
+ ;
+//======================================================
+// 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	{lattribute.clear();/* voir Stag */}
+ ;
+//======================================================
+// ETag
+//======================================================
+// regle 42
+// BALISE FERMANTE
+// les separateurs après ID sont filtrés
+//======================================================
+ETag
+ : INFCAR SLASH ID SUPCAR
+{
+  if(strcmp($3,"DataInputs")==0){
+    current_data=1;
+  }
+  if(strcmp($3,"DataOutputs")==0){
+    current_data=2;
+  }
+  if(strcmp($3,"MetaData")==0){
+    current_data=previous_data;
+  }
+  if(strcmp($3,"ComplexData")==0 || strcmp($3,"LiteralData")==0 
+     || strcmp($3,"ComplexOutput")==0 || strcmp($3,"LiteralOutput")==0){
+    current_content=NULL;
+  }
+  if(strcmp($3,"Default")==0){
+    current_data=previous_data;
+    if(current_element->defaults==NULL){
+      current_element->defaults=(iotype*)malloc(MAP_SIZE);
+    }
+    current_element->defaults->content=current_content;
+    current_element->defaults->next=NULL;
+    wait_defaults=false;
+    current_content=NULL;
+    current_element->supported=NULL;
+  }
+  if(strcmp($3,"Supported")==0){
+    current_data=previous_data;
+    if(current_element->supported==NULL){
+      current_element->supported=(iotype*)malloc(MAP_SIZE);
+      current_element->supported->content=current_content;
+      current_element->supported->next=NULL;
+      /**
+       * Need to free this ressource (HERE ?)
+      free(current_content);
+      */
+    }
+    else{ 
+      /*current_element->supported->next=(iotype*)malloc(sizeof(iotype*));
+      current_element->supported->next->content=NULL;
+      current_element->supported->next->next=NULL;
+      iotype* tmp1=current_element->supported;
+      while(tmp1!=NULL){
+	addMapToMap(&current_element->supported->next->content,current_content);
+	freeMap(&current_content);
+#ifdef DEBUG_SERVICE_CONF
+	fprintf(stderr,"LINE 409");
+#endif
+	free(current_content);
+	current_content=NULL;
+	tmp1=tmp1->next;
+	}*/
+    }
+    current_content=NULL;
+  }
+  /* on renvoie l'identifiant de la balise pour pouvoir comparer les 2 */
+  /* /!\ une balise fermante n'a pas d'attributs (c.f. : W3C) */
+  $$ = $3;
+}
+ ;
+//======================================================
+// 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"); }
+| EPAIR {
+#ifdef DEBUG_SERVICE_CONF
+    fprintf(stderr,"EPAIR FOUND !! \n"); 
+    fprintf(stderr,"[%s=>%s]\n",curr_key,$1);
+    fprintf(stderr,"[ZOO: service_conf.y line 482 free(%s)]\n",curr_key);
+    dumpMap(current_content);
+    fflush(stderr);
+#endif
+  if(current_content==NULL){
+#ifdef DEBUG_SERVICE_CONF
+    fprintf(stderr,"[ZOO: service_conf.y line 482 free(%s)]\n",curr_key);
+#endif
+    current_content=createMap(curr_key,$1);
+#ifdef DEBUG_SERVICE_CONF
+    fprintf(stderr,"[ZOO: service_conf.y line 482 free(%s)]\n",curr_key);
+#endif
+    //current_content->next=NULL;
+  }
+  else{ 
+#ifdef DEBUG_SERVICE_CONF
+    dumpMap(current_content);
+    fprintf(stderr,"addToMap(current_content,%s,%s) !! \n",curr_key,$1); 
+    
+#endif
+    //map* tmp1=createMap(curr_key,$1);
+    addToMap(current_content,curr_key,$1);
+    //freeMap(&tmp1);
+    //free(tmp1);
+#ifdef DEBUG_SERVICE_CONF
+    fprintf(stderr,"addToMap(current_content,%s,%s) end !! \n",curr_key,$1); 
+#endif    
+  }
+  //free(curr_key);
+  curr_key=NULL;
+#ifdef DEBUG_SERVICE_CONF
+  fprintf(stderr,"EPAIR FOUND !! \n"); 
+  fprintf(stderr,"[%s=>%s]\n",curr_key,$1);
+  fprintf(stderr,"[ZOO: service_conf.y line 505 free(%s)]\n",curr_key);
+  fflush(stderr);
+#endif
+  }
+| SPAIR  { curr_key=$1; if(debug) fprintf(stderr,"SPAIR FOUND !!\n"); }
+ ;
+
+
+processid
+: ANID  {
+  if(data==-1){
+    data=1;
+    my_service->name=$1;
+    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){
+	//fprintf(stderr,"ELEMENT (%s)",current_element->name);
+	if(my_service->inputs==NULL){
+#ifdef DEBUG_SERVICE_CONF
+	  fprintf(stderr,"count (%i) (%s)\n",tmp_count%2,$1);
+	  fflush(stderr);
+#endif
+	  //if(tmp_count==1){
+#ifdef DEBUG_SERVICE_CONF
+	  fprintf(stderr,"(DATAINPUTS - 464)DUP current_element\n");
+	  dumpElements(current_element);
+#endif
+	  my_service->inputs=dupElements(current_element);
+#ifdef DEBUG_SERVICE_CONF
+	  fprintf(stderr,"(DATAINPUTS - 466)FREE current_element\n");
+#endif
+	  freeElements(&current_element);
+	  current_element=NULL;
+	  tmp_count++;
+	}
+	else{
+	  addToElements(my_service->inputs,current_element);
+#ifdef DEBUG_SERVICE_CONF
+	  fprintf(stderr,"(DATAINPUTS - 6)FREE current_element (after adding to allread existing inputs)");
+#endif
+	  freeElements(&current_element);
+	}
+#ifdef DEBUG_SERVICE_CONF
+	dumpElements(my_service->inputs);
+#endif
+	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
+	current_element->name=strdup($1);
+#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){ 
+	if(wait_inputs==true){
+	  fprintf(stderr,"dup INPUTS\n");
+	  if(current_element->name!=NULL){
+	    if(my_service->inputs==NULL){
+	      my_service->inputs=dupElements(current_element);
+	    }
+	    else{
+#ifdef DEBUG_SERVICE_CONF
+	      fprintf(stderr,"LAST NAME IN %s (current - %s)\n",$1,current_element->name);
+#endif
+	      addToElements(my_service->inputs,current_element);
+	    }
+#ifdef DEBUG_SERVICE_CONF
+	    dumpElements(current_element);
+	    fprintf(stderr,"(DATAOUTPUTS - 531) FREE current_element\n");
+#endif
+	    freeElements(&current_element);
+	    free(&current_element);
+#ifdef DEBUG_SERVICE_CONF
+	    fprintf(stderr,"free OUTPUTS\n");
+#endif
+	    current_element=NULL;
+#ifdef DEBUG_SERVICE_CONF
+	    fprintf(stderr,"(DATAOUTPUTS - 536) 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 OUT %s\n",$1);
+	    fprintf(stderr,"(DATAOUTPUTS - 545) SET NAME OF current_element\n");
+#endif
+	    current_element->name=strdup($1);
+	    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;
+	  current_content=NULL;
+	}
+	else
+	  if(current_element->name==NULL){
+#ifdef DEBUG_SERVICE_CONF
+	    fprintf(stderr,"NAME OUT %s\n",$1);
+	    fprintf(stderr,"(DATAOUTPUTS - 545) SET NAME OF current_element\n");
+#endif
+	    current_element->name=strdup($1);
+	    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_outputs=true;
+      }
+  }
+ }
+ ;
+
+%%
+
+// srerror
+//======================================================
+/* fonction qui affiche l erreur si il y en a une */
+//======================================================
+void srerror(char *s)
+{
+  if(debug)
+    fprintf(stderr,"\nligne %d : %s\n",srlineno,s);
+}
+
+/**
+ * getServiceFromFile :
+ * set service given as second parameter with informations extracted from the
+ * definition file.
+ */
+int getServiceFromFile(char* file,service** service){
+
+  freeMap(&previous_content);
+  previous_content=NULL;
+  freeMap(&current_content);
+  current_content=NULL;
+  freeMap(&scontent);
+#ifdef DEBUG_SERVICE_CONF
+  fprintf(stderr,"(STARTING)FREE current_element\n");
+#endif
+  freeElements(&current_element);
+  current_element=NULL;
+#ifdef DEBUG_SERVICE_CONF
+  fprintf(stderr,"(STARTING)FREE my_service\n");
+#endif
+  //freeService(&my_service);
+  //free(my_service);
+#ifdef DEBUG_SERVICE_CONF
+  fprintf(stderr,"(STARTING)FREE my_service done\n");
+#endif
+  my_service=NULL;
+  scontent=NULL;
+
+  wait_maincontent=true;
+  wait_mainmetadata=false;
+  wait_metadata=false;
+  wait_inputs=false;
+  wait_defaults=false;
+  wait_supporteds=false;
+  wait_outputs=false;
+  wait_data=false;
+  data=-1;
+  previous_data=1;
+  current_data=0;
+  
+  my_service=*service;
+
+  srin = fopen(file,"r");
+  if (srin==NULL){
+    fprintf(stderr,"error : le fichier specifie n'existe pas ou n'est pas accessible en lecture\n") ;
+    return 22;
+  }
+
+  //printf(" ");
+  int resultatYYParse = srparse() ;
+  
+  if(wait_outputs==true && current_element->name!=NULL){
+    if(my_service->outputs==NULL){      
+#ifdef DEBUG_SERVICE_CONF
+      fprintf(stderr,"(DATAOUTPUTS - 623) DUP current_element\n");
+#endif
+      my_service->outputs=dupElements(current_element);
+      current_element=NULL;
+    }
+    else{
+#ifdef DEBUG_SERVICE_CONF
+      fprintf(stderr,"(DATAOUTPUTS - 628) COPY current_element\n");
+#endif
+      addToElements(my_service->outputs,current_element);
+    }
+#ifdef DEBUG_SERVICE_CONF
+    fprintf(stderr,"(DATAOUTPUTS - 631) FREE current_element\n");
+#endif
+    freeElements(&current_element);
+  }
+  if(current_element!=NULL){
+    freeElements(&current_element);
+    fprintf(stderr,"LINE 709");
+    //free(current_element);
+    current_element=NULL;
+  }
+  if(current_content!=NULL){
+    freeMap(&current_content);
+    fprintf(stderr,"LINE 715");
+    //free(current_content);
+    current_content=NULL;
+  }
+  fclose(srin);
+#ifdef DEBUG_SERVICE_CONF
+  dumpService(my_service);
+#endif
+  *service=my_service;
+
+  return resultatYYParse;
+}
Index: trunk/zoo-kernel/service_internal.c
===================================================================
--- trunk/zoo-kernel/service_internal.c	(revision 1)
+++ trunk/zoo-kernel/service_internal.c	(revision 1)
@@ -0,0 +1,2102 @@
+/**
+ * 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.
+ */
+
+#include "service_internal.h"
+
+/* Converts a hex character to its integer value */
+char from_hex(char ch) {
+  return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
+}
+
+/* Converts an integer value to its hex character*/
+char to_hex(char code) {
+  static char hex[] = "0123456789abcdef";
+  return hex[code & 15];
+}
+
+/* Returns a url-encoded version of str */
+/* IMPORTANT: 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;
+}
+
+/* Returns a url-decoded version of str */
+/* IMPORTANT: 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;
+}
+
+
+void printProcessResponse1(maps* m,map* request, int pid,service* serv,char* service,int status,maps* inputs,maps* outputs){
+  if(getpid()==pid)
+    printf("Content-Type: text/xml; charset=utf-8\r\nStatus: 200 OK\r\n\r\n");  
+  xmlNsPtr ns,ns_ows,ns_xlink,ns_xsi;
+  xmlNodePtr nr,n,nc,nc1,nc2,nc3,pseudor;
+  xmlDocPtr doc;
+  xmlChar *xmlbuff;
+  int buffersize;
+  time_t time1;  
+  time(&time1);
+  /**
+   * Create the document and its temporary root.
+   */
+  doc = xmlNewDoc(BAD_CAST "1.0");
+  pseudor = xmlNewNode(ns, BAD_CAST "root");
+  ns_ows=xmlNewNs(pseudor,BAD_CAST "http://www.opengis.net/ows/1.1",BAD_CAST "ows");
+  nr = xmlNewNode(ns, BAD_CAST "root");
+  ns=xmlNewNs(nr,BAD_CAST "http://www.opengis.net/wps/1.0.0",BAD_CAST "wps");
+
+  maps* tmp_maps=getMaps(m,"main");
+  if(tmp_maps!=NULL){
+    map* tmp=getMap(tmp_maps->content,"encoding");
+    if(tmp!=NULL){
+      doc->encoding = xmlCharStrdup(tmp->value);
+    }
+    else
+      doc->encoding = xmlCharStrdup("UTF-8");
+  }
+  
+  n = xmlNewNode(ns, BAD_CAST "ExecuteResponse");  
+  xmlNewNs(n,BAD_CAST "http://www.opengis.net/ows/1.1",BAD_CAST "ows");
+  xmlNewNs(n,BAD_CAST "http://www.opengis.net/wps/1.0.0",BAD_CAST "wps");
+  xmlNewNs(n,BAD_CAST "http://www.w3.org/1999/xlink",BAD_CAST "xlink");
+  xmlNewNs(n,BAD_CAST "http://www.w3.org/2001/XMLSchema-instance",BAD_CAST "xsi");
+  xmlNewProp(n,BAD_CAST "xsi:schemaLocation",BAD_CAST "http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsExecute_response.xsd");
+  xmlNewProp(n,BAD_CAST "service",BAD_CAST "WPS");
+  xmlNewProp(n,BAD_CAST "version",BAD_CAST "1.0.0");
+  xmlNewProp(n,BAD_CAST "xml:lang",BAD_CAST "en");
+  char tmp[256];
+  char url[256];
+  memset(tmp,0,256);
+  memset(url,0,256);
+  if(tmp_maps!=NULL){
+    map* tmpm=getMap(tmp_maps->content,"serverAddress");
+    map* tmpm1=getMap(tmp_maps->content,"tmpUrl");
+    if(tmpm!=NULL && tmpm1!=NULL){
+      sprintf(url,"%s/%s/%s_%i.xml",tmpm->value,tmpm1->value,service,pid);
+    }
+	if(tmpm1!=NULL)
+      sprintf(tmp,"%s/",tmpm->value);
+  }
+
+  xmlNewProp(n,BAD_CAST "serviceInstance",BAD_CAST tmp);
+  if(status!=SERVICE_SUCCEEDED){
+    xmlNewProp(n,BAD_CAST "statusLocation",BAD_CAST url);
+  }
+
+  nc = xmlNewNode(ns, BAD_CAST "Process");
+  map* tmp2=getMap(serv->content,"processVersion");
+
+  if(tmp2!=NULL)
+    xmlNewProp(nc,BAD_CAST "wps:processVersion",BAD_CAST tmp2->value);
+  
+  printDescription(nc,ns_ows,serv->name,serv->content);
+  fflush(stderr);
+
+  xmlAddChild(n,nc);
+
+  nc = xmlNewNode(ns, BAD_CAST "Status");
+  const struct tm *tm;
+  size_t len;
+  time_t now;
+  char *tmp1;
+  
+  now = time ( NULL );
+  tm = localtime ( &now );
+
+  tmp1 = new char[TIME_SIZE];
+
+  len = strftime ( tmp1, TIME_SIZE, "%Y-%m-%dT%I:%M:%SZ", tm );
+
+  switch(status){
+  case SERVICE_SUCCEEDED:
+    xmlNewProp(nc,BAD_CAST "creationTime",BAD_CAST tmp1);
+    nc1 = xmlNewNode(ns, BAD_CAST "ProcessSucceeded");
+    break;
+  case SERVICE_STARTED:
+    xmlNewProp(nc,BAD_CAST "creationTime",BAD_CAST tmp1);
+    nc1 = xmlNewNode(ns, BAD_CAST "ProcessStarted");
+    xmlNewProp(nc1,BAD_CAST "percentCompleted",BAD_CAST "NEED_SERVICE_ACCESS"); 
+    break;
+  case SERVICE_ACCEPTED:
+    xmlNewProp(nc,BAD_CAST "creationTime",BAD_CAST tmp1);
+    nc1 = xmlNewNode(ns, BAD_CAST "ProcessAccepted");
+    break;
+  case SERVICE_FAILED:
+    nc1 = xmlNewNode(ns, BAD_CAST "ProcessFailed");
+    break;
+  default :
+    printf("error code not know : %i\n",status);
+    exit(1);
+    break;
+  }
+  xmlAddChild(nc,nc1);
+  xmlAddChild(n,nc);
+
+#ifdef DEBUG
+  fprintf(stderr,"printProcessResponse 1 161\n");
+#endif
+
+  map* lineage=getMap(request,"lineage");
+  if(lineage!=NULL){
+    nc = xmlNewNode(ns, BAD_CAST "DataInputs");
+    int i;
+    maps* mcursor=inputs;
+    elements* scursor=serv->inputs;
+    while(mcursor!=NULL && scursor!=NULL){
+      printIOType1(doc,nc,ns,ns_ows,scursor,mcursor,"Input");
+      mcursor=mcursor->next;
+      scursor=scursor->next;
+    }
+    xmlAddChild(n,nc);
+    
+#ifdef DEBUG
+    fprintf(stderr,"printProcessResponse 1 177\n");
+#endif
+
+    nc = xmlNewNode(ns, BAD_CAST "OutputDefinitions");
+    mcursor=outputs;
+    scursor=serv->outputs;
+    while(mcursor!=NULL /*&& scursor!=NULL*/){
+      printOutputDefinitions1(doc,nc,ns,ns_ows,scursor,mcursor,"Output");
+      mcursor=mcursor->next;
+      //scursor=scursor->next;
+    }
+    xmlAddChild(n,nc);
+  }
+#ifdef DEBUG
+  fprintf(stderr,"printProcessResponse 1 190\n");
+#endif
+
+  /**
+   * Display the process output only when requested !
+   */
+  if(status==SERVICE_SUCCEEDED){
+    nc = xmlNewNode(ns, BAD_CAST "ProcessOutputs");
+    maps* mcursor=outputs;
+    elements* scursor=serv->outputs;
+    while(mcursor!=NULL/* && scursor!=NULL*/){
+      //xmlAddChild(nc,xmlNewComment(BAD_CAST "Here we need to check for output format from metadata"));
+      printIOType1(doc,nc,ns,ns_ows,scursor,mcursor,"Output");
+      mcursor=mcursor->next;
+      //scursor=scursor->next;
+    }
+    xmlAddChild(n,nc);
+  }
+#ifdef DEBUG
+  fprintf(stderr,"printProcessResponse 1 202\n");
+#endif
+
+  xmlAddChild(nr,n);
+  xmlDocSetRootElement(doc, n);
+
+  /*
+   * Dump the document to a buffer and print it
+   * for demonstration purposes.
+   */
+  xmlDocDumpFormatMemory(doc, &xmlbuff, &buffersize, 1);
+  printf((char *) xmlbuff);
+  
+  /*
+   * Free associated memory.
+   */
+  xmlFree(xmlbuff);
+  xmlFree(nr);
+  xmlFree(n);
+  xmlFreeDoc(doc);
+
+}
+
+
+void printProcessResponse(maps* m,int pid,service* serv,char* service,int status,map* inputs,map* outputs){
+  
+  xmlNsPtr ns,ns_ows,ns_xlink,ns_xsi;
+  xmlNodePtr nr,n,nc,nc1,nc2,nc3,pseudor;
+  xmlDocPtr doc;
+  xmlChar *xmlbuff;
+  int buffersize;
+  time_t time1;  
+  time(&time1);
+  /**
+   * Create the document and its temporary root.
+   */
+  doc = xmlNewDoc(BAD_CAST "1.0");
+  pseudor = xmlNewNode(ns, BAD_CAST "root");
+  ns_ows=xmlNewNs(pseudor,BAD_CAST "http://www.opengis.net/ows/1.1",BAD_CAST "ows");
+  nr = xmlNewNode(ns, BAD_CAST "root");
+  ns=xmlNewNs(nr,BAD_CAST "http://www.opengis.net/wps/1.0.0",BAD_CAST "wps");
+
+  maps* tmp_maps=getMaps(m,"main");
+  if(tmp_maps!=NULL){
+    map* tmp=getMap(tmp_maps->content,"encoding");
+    if(tmp!=NULL){
+      doc->encoding = xmlCharStrdup(tmp->value);
+    }
+    else
+      doc->encoding = xmlCharStrdup("UTF-8");
+  }
+  
+  n = xmlNewNode(ns, BAD_CAST "ExecuteResponse");  
+  xmlNewNs(n,BAD_CAST "http://www.opengis.net/ows/1.1",BAD_CAST "ows");
+  xmlNewNs(n,BAD_CAST "http://www.opengis.net/wps/1.0.0",BAD_CAST "wps");
+  xmlNewNs(n,BAD_CAST "http://www.w3.org/1999/xlink",BAD_CAST "xlink");
+  xmlNewNs(n,BAD_CAST "http://www.w3.org/2001/XMLSchema-instance",BAD_CAST "xsi");
+  xmlNewProp(n,BAD_CAST "xsi:schemaLocation",BAD_CAST "http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsExecute_response.xsd");
+  xmlNewProp(n,BAD_CAST "service",BAD_CAST "WPS");
+  xmlNewProp(n,BAD_CAST "version",BAD_CAST "1.0.0");
+  xmlNewProp(n,BAD_CAST "xml:lang",BAD_CAST "en");
+  char tmp[256];
+  char url[256];
+  memset(tmp,0,256);
+  memset(url,0,256);
+  if(tmp_maps!=NULL){
+    map* tmpm=getMap(tmp_maps->content,"serverAddress");
+    if(tmpm!=NULL){
+      sprintf(url,"%s/temp/%s_%i.xml",tmpm->value,service,pid);
+      sprintf(tmp,"%s/%s",tmpm->value,service);
+    }
+  }
+
+  //sprintf(tmp,"%s/%s",SERVICE_URL,service);
+  xmlNewProp(n,BAD_CAST "serviceInstance",BAD_CAST tmp);
+  //memset(tmp,0,256);
+  
+  
+  if(status!=SERVICE_SUCCEEDED){
+    xmlNewProp(n,BAD_CAST "statusLocation",BAD_CAST url);
+  }
+
+
+  nc = xmlNewNode(ns, BAD_CAST "Process");
+  map* tmp2=getMap(serv->content,"processVersion");
+
+  if(tmp2!=NULL)
+    xmlNewProp(nc,BAD_CAST "wps:processVersion",BAD_CAST tmp2->value);
+  
+  printDescription(nc,ns_ows,serv->name,serv->content);
+  fflush(stderr);
+
+  xmlAddChild(n,nc);
+
+  nc = xmlNewNode(ns, BAD_CAST "Status");
+  const struct tm *tm;
+  size_t len;
+  time_t now;
+  char *tmp1;
+  
+  now = time ( NULL );
+  tm = localtime ( &now );
+
+  tmp1 = new char[TIME_SIZE];
+
+  len = strftime ( tmp1, TIME_SIZE, "%Y-%m-%dT%I:%M:%SZ", tm );
+
+  switch(status){
+  case SERVICE_SUCCEEDED:
+    xmlNewProp(nc,BAD_CAST "creationTime",BAD_CAST tmp1);
+    nc1 = xmlNewNode(ns, BAD_CAST "ProcessSucceeded");
+    break;
+  case SERVICE_STARTED:
+    xmlNewProp(nc,BAD_CAST "creationTime",BAD_CAST tmp1);
+    nc1 = xmlNewNode(ns, BAD_CAST "ProcessStarted");
+    xmlNewProp(nc1,BAD_CAST "percentCompleted",BAD_CAST "NEED_SERVICE_ACCESS"); 
+    break;
+  case SERVICE_ACCEPTED:
+    xmlNewProp(nc,BAD_CAST "creationTime",BAD_CAST tmp1);
+    nc1 = xmlNewNode(ns, BAD_CAST "ProcessSucceeded");
+    break;
+  case SERVICE_FAILED:
+    nc1 = xmlNewNode(ns, BAD_CAST "ProcessFailed");
+    break;
+  default :
+    printf("error code not know : %i\n",status);
+    exit(1);
+    break;
+  }
+  xmlAddChild(nc,nc1);
+  xmlAddChild(n,nc);
+
+  fprintf(stderr,"printProcessResponse 1\n");
+
+  nc = xmlNewNode(ns, BAD_CAST "DataInputs");
+  int i;
+  map* mcursor=inputs;
+  elements* scursor=serv->inputs;
+  while(mcursor!=NULL && scursor!=NULL){
+    //xmlAddChild(nc,xmlNewComment(BAD_CAST "Here we need to check for input format from metadata"));
+    printIOType(doc,nc,ns,ns_ows,scursor,mcursor,"Input");
+    mcursor=mcursor->next;
+    scursor=scursor->next;
+  }
+  xmlAddChild(n,nc);
+
+  fprintf(stderr,"printProcessResponse 1\n");
+
+  nc = xmlNewNode(ns, BAD_CAST "OutputDefinitions");
+  mcursor=outputs;
+  scursor=serv->outputs;
+  //dumpMap(mcursor);
+  while(mcursor!=NULL && scursor!=NULL){
+    //xmlAddChild(nc,xmlNewComment(BAD_CAST "Here we need to check for output format from metadata"));
+    printOutputDefinitions(doc,nc,ns,ns_ows,scursor,mcursor,"Output");
+    mcursor=mcursor->next;
+    scursor=scursor->next;
+  }
+  xmlAddChild(n,nc);
+
+  fprintf(stderr,"printProcessResponse 1\n");
+  
+  nc = xmlNewNode(ns, BAD_CAST "ProcessOutputs");
+  mcursor=outputs;
+  scursor=serv->outputs;
+  while(mcursor!=NULL && scursor!=NULL){
+    //xmlAddChild(nc,xmlNewComment(BAD_CAST "Here we need to check for output format from metadata"));
+    printIOType(doc,nc,ns,ns_ows,scursor,mcursor,"Output");
+    mcursor=mcursor->next;
+    scursor=scursor->next;
+  }
+  xmlAddChild(n,nc);
+  fprintf(stderr,"printProcessResponse 1\n");
+
+  xmlAddChild(nr,n);
+  xmlDocSetRootElement(doc, n);
+
+  /*
+   * Dump the document to a buffer and print it
+   * for demonstration purposes.
+   */
+  xmlDocDumpFormatMemory(doc, &xmlbuff, &buffersize, 1);
+  printf((char *) xmlbuff);
+  
+  /*
+   * Free associated memory.
+   */
+  xmlFree(xmlbuff);
+  xmlFreeDoc(doc);
+
+}
+
+
+void printGetCapabilitiesResponse(service** serv,int sc,char* service,maps* m){
+
+  xmlNsPtr ns,ns_ows,ns_xlink,ns_xsi;
+  xmlNodePtr nr,n,nc,nc1,nc2,nc3,nc4,nc5,nc6,pseudor;
+  xmlDocPtr doc;
+  xmlChar *xmlbuff;
+  int buffersize;
+  /**
+   * Create the document and its temporary root.
+   */
+  nr = xmlNewNode(ns, BAD_CAST "root");
+  ns=xmlNewNs(nr,BAD_CAST "http://www.opengis.net/wps/1.0.0",BAD_CAST "wps");
+
+  maps* toto1=getMaps(m,"main");
+  doc = xmlNewDoc(BAD_CAST "1.0");
+  if(toto1!=NULL){
+    map* tmp=getMap(toto1->content,"encoding");
+    if(tmp!=NULL){
+      doc->encoding = xmlCharStrdup(tmp->value);
+    }
+    else
+      doc->encoding = xmlCharStrdup("UTF-8");
+  }
+  else
+    doc->encoding = xmlCharStrdup ("UTF-8");
+
+  n = xmlNewNode(ns, BAD_CAST "Capabilities");  
+  ns_ows=xmlNewNs(n,BAD_CAST "http://www.opengis.net/ows/1.1",BAD_CAST "ows");
+  xmlNewNs(n,BAD_CAST "http://www.opengis.net/wps/1.0.0",BAD_CAST "wps");
+  xmlNewNs(n,BAD_CAST "http://www.w3.org/1999/xlink",BAD_CAST "xlink");
+  xmlNewNs(n,BAD_CAST "http://www.w3.org/2001/XMLSchema-instance",BAD_CAST "xsi");
+  xmlNewProp(n,BAD_CAST "xsi:schemaLocation",BAD_CAST "http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsGetCapabilities_response.xsd");
+  xmlNewProp(n,BAD_CAST "service",BAD_CAST "WPS");
+  
+  if(toto1!=NULL){
+    map* tmp=getMap(toto1->content,"version");
+    if(tmp!=NULL){
+      xmlNewProp(n,BAD_CAST "version",BAD_CAST tmp->value);
+    }
+    else
+      xmlNewProp(n,BAD_CAST "version",BAD_CAST "1.0.0");
+  }
+  else
+    xmlNewProp(n,BAD_CAST "version",BAD_CAST "1.0.0");
+
+  char tmp[256];
+  
+  nc = xmlNewNode(ns_ows, BAD_CAST "ServiceIdentification");
+  maps* tmp4=getMaps(m,"identification");
+  if(tmp4!=NULL){
+    map* tmp2=tmp4->content;
+    while(tmp2!=NULL){
+      if(strcmp(tmp2->name,"keywords")!=0 &&
+	 strcmp(tmp2->name,"serverAddress")!=0 &&
+	 strcmp(tmp2->name,"lang")!=0 &&
+	 strcmp(tmp2->name,"encoding")!=0 &&
+	 strcmp(tmp2->name,"version")!=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);
+	}
+      tmp2=tmp2->next;
+    }
+  }
+  else{
+    fprintf(stderr,"TMP4 NOT FOUND !!");
+    //dumpMaps(tmp4);
+    return;
+  }
+  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;
+    while(tmp2!=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 || 
+	   strcmp(tmp2->name,"ProviderSite")==0){
+	  nc1 = xmlNewNode(ns_ows, BAD_CAST tmp2->name);
+	  xmlAddChild(nc1,xmlNewText(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){
+	      char *toto=NULL;
+	      char *toto1=tmp2->name;
+	      toto=strstr(toto1,"Phone");
+	      nc1 = xmlNewNode(ns_ows, BAD_CAST toto1+5);
+	      xmlAddChild(nc1,xmlNewText(BAD_CAST tmp2->value));
+	      xmlAddChild(nc5,nc1);
+	    }
+	    else 
+	      if(strncmp(tmp2->name,"Address",7)==0){
+		char *toto=NULL;
+		char *toto1=tmp2->name;
+		toto=strstr(toto1,"Address");
+		nc1 = xmlNewNode(ns_ows, BAD_CAST toto1+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 !!");
+    //dumpMaps(tmp4);
+  }
+  xmlAddChild(nc4,nc5);
+  xmlAddChild(nc4,nc6);
+  xmlAddChild(nc3,nc4);
+  xmlAddChild(nc,nc3);
+  xmlAddChild(n,nc);
+
+
+  nc = xmlNewNode(ns_ows, BAD_CAST "OperationsMetadata");
+  char *tmp2[3];
+  tmp2[0]="GetCapabilities";
+  tmp2[1]="DescribeProcess";
+  tmp2[2]="Execute";
+  int j=0;
+
+
+  for(j=0;j<3;j++){
+    nc1 = xmlNewNode(ns_ows, BAD_CAST "Operation");
+    xmlNewProp(nc1,BAD_CAST "name",BAD_CAST tmp2[j]);
+    nc2 = xmlNewNode(ns_ows, BAD_CAST "DCP");
+    nc3 = xmlNewNode(ns_ows, BAD_CAST "HTTP");
+    nc4 = xmlNewNode(ns_ows, BAD_CAST "Get");
+    sprintf(tmp,"%s/%s",SERVICE_URL,service);
+    xmlNewProp(nc4,BAD_CAST "xlink:href",BAD_CAST tmp);
+    xmlAddChild(nc3,nc4);
+    if(j>0){
+      nc4 = xmlNewNode(ns_ows, BAD_CAST "Post");
+      xmlNewProp(nc4,BAD_CAST "xlink:href",BAD_CAST tmp);
+      xmlAddChild(nc3,nc4);
+    }
+    xmlAddChild(nc2,nc3);
+    xmlAddChild(nc1,nc2);    
+    xmlAddChild(nc,nc1);    
+  }
+  xmlAddChild(n,nc);
+
+
+  nc = xmlNewNode(ns, BAD_CAST "ProcessOfferings");
+  /**
+   * Need to loop over various operations
+   */
+  int cursor=0;
+  map* tmp1;
+  for(cursor=0;cursor<sc;cursor++){
+    //dumpService(serv[cursor]);
+    if(serv[cursor]->content!=NULL){
+      nc1 = xmlNewNode(ns, BAD_CAST "Process");
+      tmp1=getMap(serv[cursor]->content,"processVersion");
+      if(tmp1!=NULL)
+	xmlNewProp(nc1,BAD_CAST "wps:processVersion",BAD_CAST tmp1->value);
+      
+      printDescription(nc1,ns_ows,serv[cursor]->name,serv[cursor]->content);
+      tmp1=serv[cursor]->metadata;
+      while(tmp1!=NULL){
+	nc2 = xmlNewNode(ns_ows, BAD_CAST "Metadata");
+	xmlNewProp(nc2,BAD_CAST tmp1->name,BAD_CAST tmp1->value);
+	xmlAddChild(nc1,nc2);
+	tmp1=tmp1->next;
+      }
+      xmlAddChild(nc,nc1);
+      xmlAddChild(n,nc);
+    }
+  }
+
+
+  nc1 = xmlNewNode(ns, BAD_CAST "Languages");
+  nc2 = xmlNewNode(ns, BAD_CAST "Default");
+  nc3 = xmlNewNode(ns, BAD_CAST "Supported");
+  
+  toto1=getMaps(m,"main");
+  if(toto1!=NULL){
+    tmp1=getMap(toto1->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){
+	  xmlAddChild(nc2,nc4);
+	  xmlAddChild(nc1,nc2);
+	  xmlNewProp(n,BAD_CAST "xml:lang",BAD_CAST buff);
+	  dcount++;
+	}
+	nc4 = xmlNewNode(ns_ows, BAD_CAST "Language");
+	xmlAddChild(nc4,xmlNewText(BAD_CAST buff));
+	xmlAddChild(nc3,nc4);
+	j=0;
+	buff[j]=0;
+      }
+      i++;
+    }
+    if(strlen(buff)>0){
+      nc4 = xmlNewNode(ns_ows, BAD_CAST "Language");
+      xmlAddChild(nc4,xmlNewText(BAD_CAST buff));	      
+      xmlAddChild(nc3,nc4);
+    }
+  }
+  xmlAddChild(nc1,nc3);
+  xmlAddChild(n,nc1);
+  
+  xmlDocSetRootElement(doc, n);
+    
+  /*
+   * Dump the document to a buffer and print it
+   * for demonstration purposes.
+   */
+  xmlDocDumpFormatMemory(doc, &xmlbuff, &buffersize, 1);
+  printf((char *) xmlbuff);
+  
+  /*
+   * Free associated memory.
+   */
+  xmlFree(xmlbuff);
+  //xmlFreeDoc(doc);
+
+}
+
+xmlNodePtr printGetCapabilitiesHeader(xmlDocPtr doc,char* service,maps* m){
+
+  xmlNsPtr ns,ns_ows,ns_xlink,ns_xsi;
+  xmlNodePtr nr,n,nc,nc1,nc2,nc3,nc4,nc5,nc6,pseudor;
+  //xmlDocPtr doc;
+  xmlChar *xmlbuff;
+  int buffersize;
+  /**
+   * Create the document and its temporary root.
+   */
+  nr = xmlNewNode(ns, BAD_CAST "root");
+  ns=xmlNewNs(nr,BAD_CAST "http://www.opengis.net/wps/1.0.0",BAD_CAST "wps");
+
+  maps* toto1=getMaps(m,"main");
+  //doc = xmlNewDoc(BAD_CAST "1.0");
+  if(toto1!=NULL){
+    map* tmp=getMap(toto1->content,"encoding");
+    if(tmp!=NULL){
+      doc->encoding = xmlCharStrdup(tmp->value);
+    }
+    else
+      doc->encoding = xmlCharStrdup("UTF-8");
+  }
+  else
+    doc->encoding = xmlCharStrdup ("UTF-8");
+
+  n = xmlNewNode(ns, BAD_CAST "Capabilities");  
+  ns_ows=xmlNewNs(n,BAD_CAST "http://www.opengis.net/ows/1.1",BAD_CAST "ows");
+  xmlNewNs(n,BAD_CAST "http://www.opengis.net/wps/1.0.0",BAD_CAST "wps");
+  xmlNewNs(n,BAD_CAST "http://www.w3.org/1999/xlink",BAD_CAST "xlink");
+  xmlNewNs(n,BAD_CAST "http://www.w3.org/2001/XMLSchema-instance",BAD_CAST "xsi");
+  xmlNewProp(n,BAD_CAST "xsi:schemaLocation",BAD_CAST "http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsGetCapabilities_response.xsd");
+  xmlNewProp(n,BAD_CAST "service",BAD_CAST "WPS");
+  
+  if(toto1!=NULL){
+    map* tmp=getMap(toto1->content,"version");
+    if(tmp!=NULL){
+      xmlNewProp(n,BAD_CAST "version",BAD_CAST tmp->value);
+    }
+    else
+      xmlNewProp(n,BAD_CAST "version",BAD_CAST "1.0.0");
+  }
+  else
+    xmlNewProp(n,BAD_CAST "version",BAD_CAST "1.0.0");
+
+  char tmp[256];
+  
+  nc = xmlNewNode(ns_ows, BAD_CAST "ServiceIdentification");
+  maps* tmp4=getMaps(m,"identification");
+  if(tmp4!=NULL){
+    map* tmp2=tmp4->content;
+    while(tmp2!=NULL){
+      if(strcmp(tmp2->name,"keywords")!=0 &&
+	 strcmp(tmp2->name,"serverAddress")!=0 &&
+	 strcmp(tmp2->name,"lang")!=0 &&
+	 strcmp(tmp2->name,"encoding")!=0 &&
+	 strcmp(tmp2->name,"version")!=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");
+	  xmlAddChild(nc2,xmlNewText(BAD_CAST "1.0.0"));
+	  xmlAddChild(nc,nc2);	  
+	}
+      tmp2=tmp2->next;
+    }
+  }
+  else{
+    fprintf(stderr,"TMP4 NOT FOUND !!");
+    //dumpMaps(tmp4);
+    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;
+    while(tmp2!=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);
+	    xmlNewProp(nc1,BAD_CAST "xlink: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){
+		char *toto=NULL;
+		char *toto1=tmp2->name;
+		toto=strstr(toto1,"Phone");
+		nc1 = xmlNewNode(ns_ows, BAD_CAST toto1+5);
+		xmlAddChild(nc1,xmlNewText(BAD_CAST tmp2->value));
+		xmlAddChild(nc5,nc1);
+	      }
+	      else 
+		if(strncmp(tmp2->name,"Address",7)==0){
+		  char *toto=NULL;
+		  char *toto1=tmp2->name;
+		  toto=strstr(toto1,"Address");
+		  nc1 = xmlNewNode(ns_ows, BAD_CAST toto1+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 !!");
+    //dumpMaps(tmp4);
+  }
+  xmlAddChild(nc4,nc5);
+  xmlAddChild(nc4,nc6);
+  xmlAddChild(nc3,nc4);
+  xmlAddChild(nc,nc3);
+  xmlAddChild(n,nc);
+
+
+  nc = xmlNewNode(ns_ows, BAD_CAST "OperationsMetadata");
+  char *tmp2[3];
+  tmp2[0]="GetCapabilities";
+  tmp2[1]="DescribeProcess";
+  tmp2[2]="Execute";
+  int j=0;
+
+  if(toto1!=NULL){
+    map* tmp=getMap(toto1->content,"serverAddress");
+    if(tmp!=NULL){
+      SERVICE_URL = strdup(tmp->value);
+    }
+    else
+      SERVICE_URL = "not_found";
+  }
+  else
+    SERVICE_URL = "not_found";
+
+  for(j=0;j<3;j++){
+    nc1 = xmlNewNode(ns_ows, BAD_CAST "Operation");
+    xmlNewProp(nc1,BAD_CAST "name",BAD_CAST tmp2[j]);
+    nc2 = xmlNewNode(ns_ows, BAD_CAST "DCP");
+    nc3 = xmlNewNode(ns_ows, BAD_CAST "HTTP");
+    nc4 = xmlNewNode(ns_ows, BAD_CAST "Get");
+    sprintf(tmp,"%s/%s",SERVICE_URL,service);
+    xmlNewProp(nc4,BAD_CAST "xlink:href",BAD_CAST tmp);
+    xmlAddChild(nc3,nc4);
+    if(j>0){
+      nc4 = xmlNewNode(ns_ows, BAD_CAST "Post");
+      xmlNewProp(nc4,BAD_CAST "xlink:href",BAD_CAST tmp);
+      xmlAddChild(nc3,nc4);
+    }
+    xmlAddChild(nc2,nc3);
+    xmlAddChild(nc1,nc2);    
+    xmlAddChild(nc,nc1);    
+  }
+  xmlAddChild(n,nc);
+
+  nc = xmlNewNode(ns, BAD_CAST "ProcessOfferings");
+  xmlAddChild(n,nc);
+
+
+
+  nc1 = xmlNewNode(ns, BAD_CAST "Languages");
+  nc2 = xmlNewNode(ns, BAD_CAST "Default");
+  nc3 = xmlNewNode(ns, BAD_CAST "Supported");
+  
+  toto1=getMaps(m,"main");
+  if(toto1!=NULL){
+    map* tmp1=getMap(toto1->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){
+	  xmlAddChild(nc2,nc4);
+	  xmlAddChild(nc1,nc2);
+	  xmlNewProp(n,BAD_CAST "xml:lang",BAD_CAST buff);
+	  dcount++;
+	}
+	nc4 = xmlNewNode(ns_ows, BAD_CAST "Language");
+	xmlAddChild(nc4,xmlNewText(BAD_CAST buff));
+	xmlAddChild(nc3,nc4);
+	j=0;
+	buff[j]=0;
+      }
+      i++;
+    }
+    if(strlen(buff)>0){
+      nc4 = xmlNewNode(ns_ows, BAD_CAST "Language");
+      xmlAddChild(nc4,xmlNewText(BAD_CAST buff));	      
+      xmlAddChild(nc3,nc4);
+    }
+  }
+  xmlAddChild(nc1,nc3);
+  xmlAddChild(n,nc1);
+  
+  xmlDocSetRootElement(doc, n);
+
+  return nc;
+}
+
+void printGetCapabilitiesForProcess(maps* m,xmlNodePtr nc,service* serv){
+
+  xmlNsPtr ns,ns_ows;
+  xmlNodePtr nr,n,nc1,nc2,nc3,nc4,nc5,nc6,pseudor;
+
+  nr = xmlNewNode(ns, BAD_CAST "root");
+  ns=xmlNewNs(nr,BAD_CAST "http://www.opengis.net/wps/1.0.0",BAD_CAST "wps");
+  ns_ows=xmlNewNs(nr,BAD_CAST "http://www.opengis.net/ows/1.1.0",BAD_CAST "ows");
+
+  int cursor=0;
+  map* tmp1;
+  if(serv->content!=NULL){
+    nc1 = xmlNewNode(ns, BAD_CAST "Process");
+    tmp1=getMap(serv->content,"processVersion");
+    if(tmp1!=NULL)
+      xmlNewProp(nc1,BAD_CAST "wps:processVersion",BAD_CAST tmp1->value);
+    
+    printDescription(nc1,ns_ows,serv->name,serv->content);
+    tmp1=serv->metadata;
+    while(tmp1!=NULL){
+      nc2 = xmlNewNode(ns_ows, BAD_CAST "Metadata");
+      char toto[1024];
+      sprintf(toto,"xlink:%s",tmp1->name);
+      xmlNewProp(nc2,BAD_CAST toto,BAD_CAST tmp1->value);
+      xmlAddChild(nc1,nc2);
+      tmp1=tmp1->next;
+    }
+    xmlAddChild(nc,nc1);
+  }
+  
+}
+
+void printDocument(xmlDocPtr doc){
+  rewind(stdout);
+  printf("Content-Type: text/xml; charset=utf-8\r\nStatus: 200 OK\r\n\r\n");
+  fflush(stdout);
+  xmlChar *xmlbuff;
+  int buffersize;
+  /*
+   * Dump the document to a buffer and print it on stdout
+   * for demonstration purposes.
+   */
+  xmlDocDumpFormatMemory(doc, &xmlbuff, &buffersize, 1);
+  printf((char *) xmlbuff);
+  /*
+   * Free associated memory.
+   */
+  xmlFree(xmlbuff);
+  xmlFreeDoc(doc);
+}
+
+void printGetCapabilitiesDocument(xmlDocPtr doc){
+  printf("Content-Type: text/xml; charset=utf-8\r\nStatus: 200 OK\r\n\r\n");
+  xmlChar *xmlbuff;
+  int buffersize;
+  /*
+   * Dump the document to a buffer and print it on stdout
+   * for demonstration purposes.
+   */
+  xmlDocDumpFormatMemory(doc, &xmlbuff, &buffersize, 1);
+  printf((char *) xmlbuff);
+  /*
+   * Free associated memory.
+   */
+  xmlFree(xmlbuff);
+
+}
+  
+
+void printDescribeProcessResponse(service* serv,char* service){
+
+  xmlNsPtr ns,ns_ows,ns_xlink,ns_xsi;
+  xmlNodePtr nr,n,nc,nc1,nc2,nc3,nc4,nc5,nc6,pseudor;
+  xmlDocPtr doc;
+  xmlChar *xmlbuff;
+  int buffersize;
+  /**
+   * Create the document and its temporary root.
+   */
+  nr = xmlNewNode(ns, BAD_CAST "root");
+  ns=xmlNewNs(nr,BAD_CAST "http://schemas.opengis.net/wps/1.0.0",BAD_CAST "wps");
+
+  doc = xmlNewDoc(BAD_CAST "1.0");
+  doc->encoding = xmlCharStrdup ("UTF-8");
+
+  n = xmlNewNode(ns, BAD_CAST "ProcessDescriptions");  
+  ns_ows=xmlNewNs(n,BAD_CAST "http://www.opengis.net/ows/1.1",BAD_CAST "ows");
+  xmlNewNs(n,BAD_CAST "http://www.opengis.net/wps/1.0.0",BAD_CAST "wps");
+  xmlNewNs(n,BAD_CAST "http://www.w3.org/1999/xlink",BAD_CAST "xlink");
+  xmlNewNs(n,BAD_CAST "http://www.w3.org/2001/XMLSchema-instance",BAD_CAST "xsi");
+  xmlNewProp(n,BAD_CAST "xsi:schemaLocation",BAD_CAST "http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsDescribeProcess_response.xsd");
+  xmlNewProp(n,BAD_CAST "service",BAD_CAST "WPS");
+  xmlNewProp(n,BAD_CAST "version",BAD_CAST "1.0.0");
+  char tmp[256];
+  
+  nc = xmlNewNode(NULL, BAD_CAST "ProcessDescription");
+  char *tmp4[3];
+  tmp4[0]="processVersion";
+  tmp4[1]="storeSupported";
+  tmp4[2]="statusSupported";
+  int j=0;
+  map* tmp1=NULL;
+  for(j=0;j<3;j++){
+    tmp1=getMap(serv->content,tmp4[j]);
+    if(tmp1!=NULL){
+      if(j==0)
+	xmlNewProp(nc,BAD_CAST "wps:processVersion",BAD_CAST tmp1->value);      
+      else
+	xmlNewProp(nc,BAD_CAST tmp4[j],BAD_CAST tmp1->value);      
+    }
+    else{
+      if(j>0)
+	xmlNewProp(nc,BAD_CAST tmp4[j],BAD_CAST "false");      
+    }
+  }
+  
+  printDescription(nc,ns_ows,serv->name,serv->content);
+
+  tmp1=serv->metadata;
+  while(tmp1!=NULL){
+    nc1 = xmlNewNode(ns_ows, BAD_CAST "Metadata");
+    xmlNewProp(nc1,BAD_CAST tmp1->name,BAD_CAST tmp1->value);
+    xmlAddChild(nc,nc1);
+    tmp1=tmp1->next;
+  }
+
+  tmp1=getMap(serv->content,"Profile");
+  if(tmp1!=NULL){
+    nc1 = xmlNewNode(ns, BAD_CAST "Profile");
+    xmlAddChild(nc1,xmlNewText(BAD_CAST tmp1->value));
+    xmlAddChild(nc,nc1);
+  }
+
+  nc1 = xmlNewNode(NULL, BAD_CAST "DataInputs");
+  
+  elements* e=serv->inputs;
+  while(e!=NULL){
+    nc2 = xmlNewNode(NULL, BAD_CAST "Input");
+    tmp1=getMap(e->content,"minOccurs");
+    if(tmp1){
+      xmlNewProp(nc2,BAD_CAST tmp1->name,BAD_CAST tmp1->value);
+    }
+    tmp1=getMap(e->content,"maxOccurs");
+    if(tmp1){
+      xmlNewProp(nc2,BAD_CAST tmp1->name,BAD_CAST tmp1->value);
+    }
+
+    printDescription(nc2,ns_ows,e->name,e->content);
+
+
+    nc3 = xmlNewNode(NULL, BAD_CAST e->format);
+    iotype* _tmp=e->defaults;
+    if(_tmp!=NULL){
+      if(strcmp(e->format,"LiteralData")!=0){
+	nc4 = xmlNewNode(NULL, BAD_CAST "Default");
+	nc5 = xmlNewNode(NULL, BAD_CAST "Format");
+      }
+      else{
+	nc4 = xmlNewNode(NULL, BAD_CAST "UOMs");
+	nc5 = xmlNewNode(NULL, BAD_CAST "Default");
+      }
+      tmp1=_tmp->content;
+      while(tmp1!=NULL){
+#ifdef DEBUG
+	printf("DATATYPE DEFAULT ? %s\n",tmp1->name);
+#endif
+	if(strcmp(tmp1->name,"DataType")==0){
+	  nc6 = xmlNewNode(ns_ows, BAD_CAST tmp1->name);
+	  xmlAddChild(nc6,xmlNewText(BAD_CAST tmp1->value));
+	  char tmp[1024];
+	  sprintf(tmp,"http://www.w3.org/TR/xmlschema-2/#%s",tmp1->value);
+	  xmlNewProp(nc6,BAD_CAST "ows:reference",BAD_CAST tmp);
+	  xmlAddChild(nc3,nc6);
+	  tmp1=tmp1->next;
+	  continue;
+	}
+	if(strcmp(tmp1->name,"asReference")!=0 && 
+	   strcmp(tmp1->name,"DataType")!=0 && 
+	   strcmp(tmp1->name,"value")!=0){
+	  nc6 = xmlNewNode(ns_ows, BAD_CAST tmp1->name);
+	  xmlAddChild(nc6,xmlNewText(BAD_CAST tmp1->value));
+	  xmlAddChild(nc5,nc6);
+	}
+	else{
+	  if(strcmp(tmp1->name,"value")==0){
+	    nc6 = xmlNewNode(NULL, BAD_CAST "DefaultValue");
+	    xmlAddChild(nc6,xmlNewText(BAD_CAST tmp1->value));
+	    xmlAddChild(nc3,nc6);
+	  }
+	}
+	tmp1=tmp1->next;
+      }
+      xmlAddChild(nc4,nc5);
+      xmlAddChild(nc3,nc4);
+    }
+    xmlAddChild(nc2,nc3);
+    
+    _tmp=e->supported;
+    if(_tmp!=NULL){
+      if(strcmp(e->format,"LiteralData")!=0){
+	nc4 = xmlNewNode(NULL, BAD_CAST "Supported");
+	nc5 = xmlNewNode(NULL, BAD_CAST "Format");
+      }
+      else{
+	nc5 = xmlNewNode(NULL, BAD_CAST "Supported");
+	
+      }
+      tmp1=_tmp->content;
+      while(tmp1!=NULL){
+	/*if(strcmp(e->format,"LiteralData")==0)
+	  xmlAddChild(nc5,nc6);*/
+	nc6 = xmlNewNode(ns_ows, BAD_CAST tmp1->name);
+	xmlAddChild(nc6,xmlNewText(BAD_CAST tmp1->value));
+	xmlAddChild(nc5,nc6);
+	tmp1=tmp1->next;
+      }
+      xmlAddChild(nc4,nc5);
+      if(strcmp(e->format,"LiteralData")!=0){
+	xmlAddChild(nc3,nc4);
+      }
+    }
+    if(strcmp(e->format,"LiteralData")!=0){
+      xmlAddChild(nc2,nc3);
+    }
+    xmlAddChild(nc1,nc2);
+    
+    
+    e=e->next;
+  }
+  xmlAddChild(nc,nc1);
+
+  nc1 = xmlNewNode(NULL, BAD_CAST "ProcessOutputs");
+  
+  e=serv->outputs;
+  while(e!=NULL){
+    nc2 = xmlNewNode(NULL, BAD_CAST "Output");
+    tmp1=getMap(e->content,"minOccurs");
+    if(tmp1){
+      xmlNewProp(nc2,BAD_CAST tmp1->name,BAD_CAST tmp1->value);
+    }
+    tmp1=getMap(e->content,"maxOccurs");
+    if(tmp1){
+      xmlNewProp(nc2,BAD_CAST tmp1->name,BAD_CAST tmp1->value);
+    }
+
+    printDescription(nc2,ns_ows,e->name,e->content);
+
+    nc3 = xmlNewNode(ns, BAD_CAST e->format);
+    fprintf(stderr,"LITERALDATA ? %s",e->format);
+    iotype* _tmp=e->defaults;
+    if(_tmp!=NULL){
+      if(strcmp(e->format,"LiteralData")!=0 &&
+	 strcmp(e->format,"LiteralOutput")!=0){
+	nc4 = xmlNewNode(NULL, BAD_CAST "Default");
+	nc5 = xmlNewNode(NULL, BAD_CAST "Format");
+      }   
+      else{
+	nc4 = xmlNewNode(NULL, BAD_CAST "UOMs");
+	nc5 = xmlNewNode(NULL, BAD_CAST "Default");
+      }
+
+      /*nc4 = xmlNewNode(NULL, BAD_CAST "Default");
+	nc5 = xmlNewNode(NULL, BAD_CAST "Format");
+      */
+      tmp1=_tmp->content;
+      while(tmp1!=NULL){
+#ifdef DEBUG
+	printf("DATATYPE DEFAULT ? %s\n",tmp1->name);
+	fprintf(stderr,"DEBUG DATATYPE !!\n");
+	dumpMap(tmp1);
+#endif
+	if(strcmp(tmp1->name,"DataType")==0){
+	  nc6 = xmlNewNode(ns_ows, BAD_CAST tmp1->name);
+	  xmlAddChild(nc6,xmlNewText(BAD_CAST tmp1->value));
+	  char tmp[1024];
+	  sprintf(tmp,"http://www.w3.org/TR/xmlschema-2/#%s",tmp1->value);
+	  xmlNewProp(nc6,BAD_CAST "ows:reference",BAD_CAST tmp);
+	  xmlAddChild(nc5,nc6);
+	  tmp1=tmp1->next;
+	  continue;
+	}
+	if(strcmp(tmp1->name,"asReference")!=0 && strcmp(tmp1->name,"DataType")!=0){
+	  nc6 = xmlNewNode(ns_ows, BAD_CAST tmp1->name);
+	  xmlAddChild(nc6,xmlNewText(BAD_CAST tmp1->value));
+	  xmlAddChild(nc5,nc6);
+	}
+	tmp1=tmp1->next;
+      }
+      xmlAddChild(nc4,nc5);
+      xmlAddChild(nc3,nc4);	    
+    }
+    _tmp=e->supported;
+    while(_tmp!=NULL){
+      nc4 = xmlNewNode(NULL, BAD_CAST "Supported");
+      nc5 = xmlNewNode(NULL, BAD_CAST "Format");
+      tmp1=_tmp->content;
+      while(tmp1!=NULL){
+#ifdef DEBUG
+	printf("DATATYPE SUPPORTED ? %s\n",tmp1->name);
+#endif
+	if(strcmp(tmp1->name,"asReference")!=0 && strcmp(tmp1->name,"DataType")!=0){
+	  nc6 = xmlNewNode(ns_ows, BAD_CAST tmp1->name);
+	  xmlAddChild(nc6,xmlNewText(BAD_CAST tmp1->value));
+	  xmlAddChild(nc5,nc6);
+	}
+	tmp1=tmp1->next;
+      }
+      _tmp=_tmp->next;
+      xmlAddChild(nc4,nc5);
+      xmlAddChild(nc3,nc4);
+    }
+    xmlAddChild(nc2,nc3);
+
+    xmlAddChild(nc3,nc4);
+      
+    
+    xmlAddChild(nc2,nc3);
+    
+    xmlAddChild(nc1,nc2);
+    
+    e=e->next;
+  }
+  xmlAddChild(nc,nc1);
+
+  xmlAddChild(n,nc);
+
+  xmlDocSetRootElement(doc, n);
+    
+  /*
+   * Dump the document to a buffer and print it
+   * for demonstration purposes.
+   */
+  xmlDocDumpFormatMemory(doc, &xmlbuff, &buffersize, 1);
+  printf((char *) xmlbuff);
+  
+  /*
+   * Free associated memory.
+   */
+  xmlFree(xmlbuff);
+  //xmlFreeDoc(doc);
+
+}
+
+xmlNodePtr printDescribeProcessHeader(xmlDocPtr doc,char* service,maps* m){
+
+  xmlNsPtr ns,ns_ows,ns_xlink,ns_xsi;
+  //xmlDocPtr doc;
+  xmlNodePtr n,nr;
+  xmlChar *xmlbuff;
+  int buffersize;
+  /**
+   * Create the document and its temporary root.
+   */
+  nr = xmlNewNode(ns, BAD_CAST "root");
+  ns=xmlNewNs(nr,BAD_CAST "http://schemas.opengis.net/wps/1.0.0",BAD_CAST "wps");
+
+  /*doc = xmlNewDoc(BAD_CAST "1.0");
+    doc->encoding = xmlCharStrdup ("UTF-8");*/
+
+  n = xmlNewNode(ns, BAD_CAST "ProcessDescriptions");  
+  ns_ows=xmlNewNs(n,BAD_CAST "http://www.opengis.net/ows/1.1",BAD_CAST "ows");
+  xmlNewNs(n,BAD_CAST "http://www.opengis.net/wps/1.0.0",BAD_CAST "wps");
+  xmlNewNs(n,BAD_CAST "http://www.w3.org/1999/xlink",BAD_CAST "xlink");
+  xmlNewNs(n,BAD_CAST "http://www.w3.org/2001/XMLSchema-instance",BAD_CAST "xsi");
+  xmlNewProp(n,BAD_CAST "xsi:schemaLocation",BAD_CAST "http://www.opengis.net/wps/1.0.0 http://schemas.opengis.net/wps/1.0.0/wpsDescribeProcess_response.xsd");
+  xmlNewProp(n,BAD_CAST "service",BAD_CAST "WPS");
+  xmlNewProp(n,BAD_CAST "version",BAD_CAST "1.0.0");
+  xmlNewProp(n,BAD_CAST "xml:lang",BAD_CAST "en");
+
+  xmlDocSetRootElement(doc, n);
+
+  return n;
+}
+
+void printDescribeProcessForProcess(maps* m,xmlNodePtr nc,service** serv,int sc){
+  xmlNsPtr ns,ns_ows,ns_xlink,ns_xsi;
+  xmlNodePtr nr,n,nc1,nc2,nc3,nc4,nc5,nc6,pseudor;
+
+  char tmp[256];
+  n=nc;
+  nr = xmlNewNode(ns, BAD_CAST "root");
+  
+  ns=xmlNewNs(nr,BAD_CAST "http://www.opengis.net/wps/1.0.0",BAD_CAST "wps");
+  ns_ows=xmlNewNs(nr,BAD_CAST "http://www.opengis.net/ows/1.1.0",BAD_CAST "ows");
+
+  nc = xmlNewNode(NULL, BAD_CAST "ProcessDescription");
+  char *tmp4[3];
+  tmp4[0]="processVersion";
+  tmp4[1]="storeSupported";
+  tmp4[2]="statusSupported";
+  int j=0;
+  map* tmp1=NULL;
+  for(j=0;j<3;j++){
+    tmp1=getMap(serv[0]->content,tmp4[j]);
+    if(tmp1!=NULL){
+      if(j==0)
+	xmlNewProp(nc,BAD_CAST "wps:processVersion",BAD_CAST tmp1->value);      
+      else
+	xmlNewProp(nc,BAD_CAST tmp4[j],BAD_CAST tmp1->value);      
+    }
+    else{
+      if(j>0)
+	xmlNewProp(nc,BAD_CAST tmp4[j],BAD_CAST "false");      
+    }
+  }
+  
+  printDescription(nc,ns_ows,serv[0]->name,serv[0]->content);
+
+  tmp1=serv[0]->metadata;
+  while(tmp1!=NULL){
+    nc1 = xmlNewNode(ns_ows, BAD_CAST "Metadata");
+    char toto[1024];
+    sprintf(toto,"xlink:%s",tmp1->name);
+    xmlNewProp(nc1,BAD_CAST toto,BAD_CAST tmp1->value);
+    xmlAddChild(nc,nc1);
+    tmp1=tmp1->next;
+  }
+
+  tmp1=getMap(serv[0]->content,"Profile");
+  if(tmp1!=NULL){
+    nc1 = xmlNewNode(ns, BAD_CAST "Profile");
+    xmlAddChild(nc1,xmlNewText(BAD_CAST tmp1->value));
+    xmlAddChild(nc,nc1);
+  }
+
+  nc1 = xmlNewNode(NULL, BAD_CAST "DataInputs");
+  
+  elements* e=serv[0]->inputs;
+  while(e!=NULL){
+    nc2 = xmlNewNode(NULL, BAD_CAST "Input");
+    tmp1=getMap(e->content,"minOccurs");
+    if(tmp1){
+      xmlNewProp(nc2,BAD_CAST tmp1->name,BAD_CAST tmp1->value);
+    }
+    tmp1=getMap(e->content,"maxOccurs");
+    if(tmp1){
+      xmlNewProp(nc2,BAD_CAST tmp1->name,BAD_CAST tmp1->value);
+    }
+
+    printDescription(nc2,ns_ows,e->name,e->content);
+
+
+    nc3 = xmlNewNode(NULL, BAD_CAST e->format);
+    iotype* _tmp=e->defaults;
+    int datatype=0;
+    if(_tmp!=NULL){
+      if(strcmp(e->format,"LiteralData")!=0){
+	nc4 = xmlNewNode(NULL, BAD_CAST "Default");
+	nc5 = xmlNewNode(NULL, BAD_CAST "Format");
+      }
+      else{
+	nc4 = xmlNewNode(NULL, BAD_CAST "UOMs");
+	nc5 = xmlNewNode(NULL, BAD_CAST "Default");
+	datatype=1;
+      }
+      tmp1=_tmp->content;
+      int default1=0;
+      xmlNodePtr nc7;
+      while(tmp1!=NULL){
+#ifdef DEBUG
+	printf("DATATYPE DEFAULT ? %s\n",tmp1->name);
+#endif
+	if(strcmp(tmp1->name,"DataType")==0){
+	  nc6 = xmlNewNode(ns_ows, BAD_CAST tmp1->name);
+	  xmlAddChild(nc6,xmlNewText(BAD_CAST tmp1->value));
+	  char tmp[1024];
+	  sprintf(tmp,"http://www.w3.org/TR/xmlschema-2/#%s",tmp1->value);
+	  xmlNewProp(nc6,BAD_CAST "ows:reference",BAD_CAST tmp);
+	  xmlAddChild(nc3,nc6);
+	  tmp1=tmp1->next;
+	  continue;
+	}
+	if(strcmp(tmp1->name,"asReference")!=0 && 
+	   strcmp(tmp1->name,"DataType")!=0 && 
+	   strcmp(tmp1->name,"value")!=0){
+	  if(datatype==0)
+	  nc6 = xmlNewNode(NULL, BAD_CAST tmp1->name);
+	  else
+	  nc6 = xmlNewNode(ns_ows, BAD_CAST tmp1->name);
+	  xmlAddChild(nc6,xmlNewText(BAD_CAST tmp1->value));
+	  xmlAddChild(nc5,nc6);
+	}
+	else{
+	  if(strcmp(tmp1->name,"value")==0){
+	    nc7 = xmlNewNode(NULL, BAD_CAST "DefaultValue");
+	    xmlAddChild(nc7,xmlNewText(BAD_CAST tmp1->value));
+	    default1=1;
+	  }
+	}
+	tmp1=tmp1->next;
+      }
+      xmlAddChild(nc4,nc5);
+      xmlAddChild(nc3,nc4);
+      if(datatype==1){
+		xmlAddChild(nc3,xmlNewNode(ns_ows, BAD_CAST "AnyValue"));
+		if(default1>0)
+	    xmlAddChild(nc3,nc7);
+      }
+    }
+    xmlAddChild(nc2,nc3);
+    
+    _tmp=e->supported;
+    if(_tmp!=NULL){
+      if(datatype==0){
+	nc4 = xmlNewNode(NULL, BAD_CAST "Supported");
+	nc5 = xmlNewNode(NULL, BAD_CAST "Format");
+      }
+      else{
+	nc5 = xmlNewNode(NULL, BAD_CAST "Supported");
+      }
+      tmp1=_tmp->content;
+      while(tmp1!=NULL){
+	/*if(strcmp(e->format,"LiteralData")==0)
+	  xmlAddChild(nc5,nc6);*/
+	if(datatype==0)
+	nc6 = xmlNewNode(NULL, BAD_CAST tmp1->name);
+	else
+	nc6 = xmlNewNode(ns_ows, BAD_CAST tmp1->name);
+	xmlAddChild(nc6,xmlNewText(BAD_CAST tmp1->value));
+	xmlAddChild(nc5,nc6);
+	tmp1=tmp1->next;
+      }
+      if(datatype==0){
+        xmlAddChild(nc4,nc5);
+	xmlAddChild(nc3,nc4);
+      }else{
+      	xmlAddChild(nc4,nc5);
+	//xmlAddChild(nc3,xmlNewNode(ns_ows, BAD_CAST "AnyValue"));
+	}
+    }
+    if(strcmp(e->format,"LiteralData")!=0){
+      xmlAddChild(nc2,nc3);
+    }
+    xmlAddChild(nc1,nc2);
+    
+    
+    e=e->next;
+  }
+  xmlAddChild(nc,nc1);
+
+  nc1 = xmlNewNode(NULL, BAD_CAST "ProcessOutputs");
+  
+  e=serv[0]->outputs;
+  while(e!=NULL){
+    nc2 = xmlNewNode(NULL, BAD_CAST "Output");
+    tmp1=getMap(e->content,"minOccurs");
+    if(tmp1){
+      xmlNewProp(nc2,BAD_CAST tmp1->name,BAD_CAST tmp1->value);
+    }
+    tmp1=getMap(e->content,"maxOccurs");
+    if(tmp1){
+      xmlNewProp(nc2,BAD_CAST tmp1->name,BAD_CAST tmp1->value);
+    }
+
+    printDescription(nc2,ns_ows,e->name,e->content);
+
+    if(strcmp(mtoupper(e->format),"LITERALDATA")==0)
+      nc3 = xmlNewNode(NULL, BAD_CAST "LiteralOutput");
+    else
+      if(strcmp(mtoupper(e->format),"COMPLEXDATA")==0)
+	nc3 = xmlNewNode(NULL, BAD_CAST "ComplexOutput");
+      else
+	nc3 = xmlNewNode(NULL, BAD_CAST e->format);
+    iotype* _tmp=e->defaults;
+    int datatype=0;
+    if(_tmp!=NULL){
+     if(strcmp(e->format,"LiteralOutput")==0 ||
+	strcmp(e->format,"LiteralData")==0){
+     	datatype=1;
+	nc4 = xmlNewNode(NULL, BAD_CAST "UOMs");
+	nc5 = xmlNewNode(NULL, BAD_CAST "Default");
+     }
+      else{
+      nc4 = xmlNewNode(NULL, BAD_CAST "Default");
+      nc5 = xmlNewNode(NULL, BAD_CAST "Format");
+      }
+      tmp1=_tmp->content;
+      while(tmp1!=NULL){
+#ifdef DEBUG
+	printf("DATATYPE DEFAULT ? %s\n",tmp1->name);
+#endif
+	if(strcmp(tmp1->name,"DataType")==0){
+	  nc6 = xmlNewNode(ns_ows, BAD_CAST tmp1->name);
+	  xmlAddChild(nc6,xmlNewText(BAD_CAST tmp1->value));
+	  char tmp[1024];
+	  sprintf(tmp,"http://www.w3.org/TR/xmlschema-2/#%s",tmp1->value);
+	  xmlNewProp(nc6,BAD_CAST "ows:reference",BAD_CAST tmp);
+	  xmlAddChild(nc3,nc6);
+	  tmp1=tmp1->next;
+	  datatype=1;
+	  continue;
+	}
+	if(strcmp(tmp1->name,"asReference")!=0 && strcmp(tmp1->name,"DataType")!=0){
+	  if(datatype==0)
+	  nc6 = xmlNewNode(NULL, BAD_CAST tmp1->name);
+	  else
+	  nc6 = xmlNewNode(ns_ows, BAD_CAST tmp1->name);
+	  xmlAddChild(nc6,xmlNewText(BAD_CAST tmp1->value));
+	  xmlAddChild(nc5,nc6);
+	}
+	tmp1=tmp1->next;
+      }
+      xmlAddChild(nc4,nc5);
+      xmlAddChild(nc3,nc4);	    
+    }
+    _tmp=e->supported;
+    while(_tmp!=NULL){
+    if(datatype==0){
+      nc4 = xmlNewNode(NULL, BAD_CAST "Supported");
+      nc5 = xmlNewNode(NULL, BAD_CAST "Format");
+      }
+      else
+      nc5 = xmlNewNode(NULL, BAD_CAST "Supported");
+      tmp1=_tmp->content;
+      while(tmp1!=NULL){
+#ifdef DEBUG
+	printf("DATATYPE SUPPORTED ? %s\n",tmp1->name);
+#endif
+	if(strcmp(tmp1->name,"asReference")!=0 && strcmp(tmp1->name,"DataType")!=0){
+	  if(datatype==0)
+	  nc6 = xmlNewNode(NULL, BAD_CAST tmp1->name);
+	  else
+	  nc6 = xmlNewNode(ns_ows, BAD_CAST tmp1->name);
+	  xmlAddChild(nc6,xmlNewText(BAD_CAST tmp1->value));
+	  xmlAddChild(nc5,nc6);
+	}
+	tmp1=tmp1->next;
+      }
+      _tmp=_tmp->next;
+      if(datatype==0){
+         xmlAddChild(nc4,nc5);
+         xmlAddChild(nc3,nc4);
+      }else
+      xmlAddChild(nc4,nc5);
+    }
+    xmlAddChild(nc2,nc3);
+
+    xmlAddChild(nc3,nc4);
+      
+    
+    xmlAddChild(nc2,nc3);
+    
+    xmlAddChild(nc1,nc2);
+    
+    e=e->next;
+  }
+  xmlAddChild(nc,nc1);
+
+  xmlAddChild(n,nc);
+
+}
+
+void printDescribeProcessDocument(xmlDocPtr doc){
+  xmlChar *xmlbuff;
+  int buffersize;
+  /*
+   * Dump the document to a buffer and print it
+   * for demonstration purposes.
+   */
+  xmlDocDumpFormatMemory(doc, &xmlbuff, &buffersize, 1);
+  printf((char *) xmlbuff);
+  
+  /*
+   * Free associated memory.
+   */
+  xmlFree(xmlbuff);
+  //xmlFreeDoc(doc);
+
+}
+//printGetCapabilitiesHeader
+
+void printOutputDefinitions1(xmlDocPtr doc,xmlNodePtr nc,xmlNsPtr ns_wps,xmlNsPtr ns_ows,elements* e,maps* m,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(strcmp(mtoupper(tmp->name),"MIMETYPE")==0
+       || strcmp(mtoupper(tmp->name),"ENCODING")==0
+       || strcmp(mtoupper(tmp->name),"SCHEMA")==0
+       || strcmp(mtoupper(tmp->name),"UOM")==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);
+
+  xmlAddChild(nc,nc1);
+
+}
+
+void printOutputDefinitions(xmlDocPtr doc,xmlNodePtr nc,xmlNsPtr ns_wps,xmlNsPtr ns_ows,elements* e,map* m,char* type){
+  xmlNodePtr nc1,nc2,nc3;
+  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){
+    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);
+
+  xmlAddChild(nc,nc1);
+
+}
+
+void printIOType1(xmlDocPtr doc,xmlNodePtr nc,xmlNsPtr ns_wps,xmlNsPtr ns_ows,elements* e,maps* m,char* type){
+  xmlNodePtr nc1,nc2,nc3;
+  nc1=xmlNewNode(ns_wps, BAD_CAST type);
+  map *tmp=e->content;
+#ifdef DEBUG
+  dumpMap(tmp);
+  dumpElements(e);
+#endif
+  nc2=xmlNewNode(ns_ows, BAD_CAST "Identifier");
+  xmlAddChild(nc2,xmlNewText(BAD_CAST m->name));
+  xmlAddChild(nc1,nc2);
+  xmlAddChild(nc,nc1);
+  nc2=xmlNewNode(ns_ows, BAD_CAST tmp->name);
+  xmlAddChild(nc2,xmlNewText(BAD_CAST tmp->value));
+  xmlAddChild(nc1,nc2);
+  xmlAddChild(nc,nc1);
+  tmp=tmp->next;
+
+  /**
+   * IO type Reference or full Data ?
+   */
+#ifdef DEBUG
+  fprintf(stderr,"FORMAT %s %s\n",e->format,mtoupper(e->format));
+#endif
+  nc2=xmlNewNode(ns_wps, BAD_CAST "Data");
+  if(strcmp(mtoupper(e->format),"LITERALOUTPUT")==0)
+    nc3=xmlNewNode(ns_wps, BAD_CAST "LiteralData");
+  else
+    if(strcmp(mtoupper(e->format),"COMPLEXOUTPUT")==0)
+      nc3=xmlNewNode(ns_wps, BAD_CAST "ComplexData");
+    else
+      nc3=xmlNewNode(ns_wps, BAD_CAST e->format);
+  tmp=m->content;
+  while(tmp!=NULL){
+    if(strcmp(tmp->name,"value")!=0)
+      xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST tmp->value);
+    tmp=tmp->next;
+    xmlAddChild(nc2,nc3);
+  }
+  tmp=getMap(e->defaults->content,"mimeType");
+  map* tmp1=getMap(m->content,"encoding");
+  map* tmp2=getMap(m->content,"mimeType");
+  map* toto=getMap(m->content,"value");
+  if((tmp1!=NULL && strncmp(tmp1->value,"base64",6)==0)
+     || (tmp2!=NULL && (strncmp(tmp2->value,"image/",6)==0
+			|| strncmp(tmp2->value,"application/",6)==0)) ){
+    map* rs=getMap(m->content,"size");
+    if(rs==NULL){
+      char tmp1[1024];
+      sprintf(tmp1,"%d",strlen(toto->value));
+      rs=createMap("z",tmp1);
+    }
+    xmlAddChild(nc3,xmlNewText(BAD_CAST base64((const unsigned char*)toto->value,atoi(rs->value))));
+  }
+  else if(tmp!=NULL){
+    if(strcmp(tmp->value,"text/js")==0)
+      xmlAddChild(nc3,xmlNewCDataBlock(doc,BAD_CAST toto->value,strlen(toto->value)));
+    else
+      xmlAddChild(nc3,xmlNewText(BAD_CAST toto->value));
+    xmlAddChild(nc2,nc3);
+  }
+  else
+    xmlAddChild(nc3,xmlNewText(BAD_CAST toto->value));
+
+  xmlAddChild(nc1,nc2);
+  xmlAddChild(nc,nc1);
+
+}
+
+void printIOType(xmlDocPtr doc,xmlNodePtr nc,xmlNsPtr ns_wps,xmlNsPtr ns_ows,elements* e,map* m,char* type){
+  xmlNodePtr nc1,nc2,nc3;
+  nc1=xmlNewNode(ns_wps, BAD_CAST type);
+  map *tmp=e->content;
+  nc2=xmlNewNode(ns_ows, BAD_CAST "Identifier");
+  xmlAddChild(nc2,xmlNewText(BAD_CAST m->name));
+  xmlAddChild(nc1,nc2);
+  xmlAddChild(nc,nc1);
+  nc2=xmlNewNode(ns_ows, BAD_CAST tmp->name);
+  xmlAddChild(nc2,xmlNewText(BAD_CAST tmp->value));
+  xmlAddChild(nc1,nc2);
+  xmlAddChild(nc,nc1);
+  tmp=tmp->next;
+
+  /**
+   * IO type Reference or full Data ?
+   */
+#ifdef DEBUG
+  printf("FORMAT %s\n",e->format);
+#endif
+  nc2=xmlNewNode(ns_wps, BAD_CAST "Data");
+  nc3=xmlNewNode(ns_wps, BAD_CAST e->format);
+  tmp=e->defaults->content;
+  while(tmp!=NULL){
+    xmlNewProp(nc3,BAD_CAST tmp->name,BAD_CAST tmp->value);
+    tmp=tmp->next;
+    xmlAddChild(nc2,nc3);
+  }
+  tmp=getMap(e->defaults->content,"mimeType");
+  if(tmp!=NULL){
+    if(strcmp(tmp->value,"text/js")==0)
+      xmlAddChild(nc3,xmlNewCDataBlock(doc,BAD_CAST m->value,strlen(m->value)));
+    else
+      xmlAddChild(nc3,xmlNewText(BAD_CAST m->value));
+    xmlAddChild(nc2,nc3);
+  }
+  else
+    xmlAddChild(nc3,xmlNewText(BAD_CAST m->value));
+
+  xmlAddChild(nc1,nc2);
+  xmlAddChild(nc,nc1);
+
+}
+
+void printDescription(xmlNodePtr root,xmlNsPtr ns_ows,char* identifier,map* amap){
+  xmlNodePtr nc2 = xmlNewNode(ns_ows, BAD_CAST "Identifier");
+  xmlAddChild(nc2,xmlNewText(BAD_CAST identifier));
+  xmlAddChild(root,nc2);
+  map* tmp=amap;
+  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 tmp1->value));
+      xmlAddChild(root,nc2);
+    }
+  }
+}
+
+void printExceptionReportResponse(maps* m,map* s){
+  
+  printf("Content-Type: text/xml; charset=utf-8\r\nStatus: 200 OK\r\n\r\n");  
+  int buffersize;
+  xmlDocPtr doc;
+  xmlChar *xmlbuff;
+  xmlNsPtr ns=NULL;
+  xmlNodePtr nr = xmlNewNode(ns, BAD_CAST "root");
+  ns=xmlNewNs(nr,BAD_CAST "http://www.opengis.net/ows/1.1",BAD_CAST "ows");
+
+  maps* toto1=getMaps(m,"main");
+  doc = xmlNewDoc(BAD_CAST "1.0");
+  if(toto1!=NULL){
+    map* tmp=getMap(toto1->content,"encoding");
+  //map* tmp=getMapFromMaps(m,"main","encoding");
+    if(tmp!=NULL){
+      doc->encoding = xmlCharStrdup(tmp->value);
+    }
+    else
+      doc->encoding = xmlCharStrdup("UTF-8");
+  }
+  else
+    doc->encoding = xmlCharStrdup ("UTF-8");
+
+  xmlNodePtr n = xmlNewNode(ns, BAD_CAST "ExceptionReport");  
+  xmlNsPtr ns_ows=xmlNewNs(n,BAD_CAST "http://www.opengis.net/ows/1.1",BAD_CAST "ows");
+  xmlNewNs(n,BAD_CAST "http://www.w3.org/1999/xlink",BAD_CAST "xlink");
+  xmlNewNs(n,BAD_CAST "http://www.w3.org/2001/XMLSchema-instance",BAD_CAST "xsi");
+  xmlNewProp(n,BAD_CAST "xsi:schemaLocation",BAD_CAST "http://www.opengis.net/ows/1.1 http://schemas.opengis.net/ows/1.1.0/owsExceptionReport.xsd");
+  xmlNewProp(n,BAD_CAST "xml:lan",BAD_CAST "en");
+  xmlNewProp(n,BAD_CAST "service",BAD_CAST "WPS");
+
+  if(toto1!=NULL){
+    map* tmp=getMap(toto1->content,"version");
+    if(tmp!=NULL){
+      xmlNewProp(n,BAD_CAST "version",BAD_CAST tmp->value);
+    }
+    else
+      xmlNewProp(n,BAD_CAST "version",BAD_CAST "1.0.0");
+  }
+  else
+    xmlNewProp(n,BAD_CAST "version",BAD_CAST "1.0.0");
+
+
+  xmlNodePtr nc = xmlNewNode(ns, BAD_CAST "Exception");  
+
+  map* 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=getMap(s,"text");
+  xmlNodePtr nc1 = xmlNewNode(ns, BAD_CAST "ExceptionText");
+  if(tmp!=NULL){
+    xmlAddChild(nc1,xmlNewText(BAD_CAST tmp->value));
+  }
+  else
+    xmlAddChild(nc1,xmlNewText(BAD_CAST "No debug message available"));
+  
+  xmlAddChild(nc,nc1);
+  xmlAddChild(n,nc);
+  xmlDocSetRootElement(doc, n);
+
+  xmlDocDumpFormatMemory(doc, &xmlbuff, &buffersize, 1);
+  printf((char *) xmlbuff);
+  xmlFree(xmlbuff);
+  xmlFree(ns_ows);
+  xmlFree(nr);
+  xmlFree(nc1);
+  xmlFree(nc);
+  xmlFree(n);
+  xmlFree(ns);
+  xmlFree(doc);
+}
+
+
+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;
+   
+  if(asRaw==0){
+    map *r_inputs=getMap(s->content,"serviceProvider");
+#ifdef DEBUG
+    fprintf(stderr,"SERVICE : %s\n",r_inputs->value);
+    dumpMaps(m);
+#endif
+    printProcessResponse1(m,request_inputs1,cpid,
+			  s,r_inputs->value,res,
+			  request_inputs,
+			  request_outputs);
+  }
+  else{
+    /**
+     * We get the first output only !!
+     */
+    char mime[1024];
+    map* mi=getMap(request_outputs->content,"mimeType");
+#ifdef DEBUG
+    fprintf(stderr,"SERVICE OUTPUTS\n");
+    dumpMaps(request_outputs);
+    fprintf(stderr,"SERVICE OUTPUTS\n");
+#endif
+    map* en=getMap(request_outputs->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(mime);
+    toto=getMapFromMaps(request_outputs,
+			request_outputs->name,"value");
+    if(mi!=NULL && strncmp(mi->value,"image",5)==0){
+      map* rs=getMapFromMaps(request_outputs,
+			     request_outputs->name,"size");
+      fwrite(toto->value,atoi(rs->value),1,stdout);
+    }
+    else
+      printf(toto->value);
+#ifdef DEBUG
+    dumpMap(toto);
+#endif
+  }
+}
+
+char *base64(const unsigned char *input, int length)
+{
+  BIO *bmem, *b64;
+  BUF_MEM *bptr;
+
+  b64 = BIO_new(BIO_f_base64());
+  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);
+  memcpy(buff, bptr->data, bptr->length-1);
+  buff[bptr->length-1] = 0;
+
+  BIO_free_all(b64);
+
+  fprintf(stderr,"BASE64 [%s] \n",buff);
+  return buff;
+}
+
+void addDefaultValues(maps** out,elements* in,maps* m,char* type){
+  elements* tmpInputs=in;
+  maps* out1=*out;
+  while(tmpInputs!=NULL){
+    maps *tmpMaps=getMaps(out1,tmpInputs->name);
+    if(tmpMaps==NULL){
+      map* tmpMap1=getMap(tmpInputs->content,"minOccurs");
+      if(strcmp(type,"inputs")==0)
+	if(tmpMap1!=NULL && atoi(tmpMap1->value)>=1){
+	  char tmps[1024];
+	  sprintf(tmps,"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.",tmpInputs->name);
+	  map* tmpe=createMap("text",tmps);
+	  addToMap(tmpe,"code","MissingParameterValue");
+	  printExceptionReportResponse(m,tmpe);
+	  exit(1);
+	}
+      tmpMaps=(maps*)malloc(MAPS_SIZE);
+      tmpMaps->name=strdup((char*)tmpInputs->name);
+      tmpMaps->content=NULL;
+      iotype* tmpIoType=tmpInputs->defaults;
+      while(tmpIoType!=NULL){
+	tmpMaps->content=tmpIoType->content;
+	tmpMaps->content->next;
+	tmpIoType=tmpIoType->next;
+      }
+      map *tmpMap=getMap(tmpMaps->content,"value");
+      if(tmpMap==NULL)
+	addToMap(tmpMaps->content,"value","NULL");
+      tmpMaps->next=NULL;
+      dumpMaps(tmpMaps);
+      if(out1==NULL){
+	out1=(maps*)malloc(MAPS_SIZE);
+	out1->name=tmpMaps->name;
+	out1->content=tmpMaps->content;
+	out1->next=NULL;
+	*out=out1;
+      }
+      else
+	addMapsToMaps(&out1,tmpMaps);
+    }
+    else{
+      map* tmpContent=tmpInputs->defaults->content;
+      while(tmpContent!=NULL){
+	map* tmpIn=getMap(out1->content,tmpContent->name);
+	if(tmpIn==NULL)
+	  if(out1->content==NULL)
+	    out1->content=createMap(tmpContent->name,tmpContent->value);
+	  else
+	    addToMap(out1->content,tmpContent->name,tmpContent->value);
+	tmpContent=tmpContent->next;
+      }
+    }
+    tmpInputs=tmpInputs->next;
+  }
+}
Index: trunk/zoo-kernel/service_internal.h
===================================================================
--- trunk/zoo-kernel/service_internal.h	(revision 1)
+++ trunk/zoo-kernel/service_internal.h	(revision 1)
@@ -0,0 +1,87 @@
+/**
+ * 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_H
+#define ZOO_SERVICE_INTERNAL_H 1
+
+#pragma once 
+
+#define DEFAULT_SERVICE_URL "http://dev.geolabs.fr/zoo-wps/"
+#define TIME_SIZE 40
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <time.h>
+#include <ctype.h>
+#ifndef WIN32
+#include <xlocale.h>
+#endif
+#include "service.h"
+#include <openssl/sha.h>
+#include <openssl/hmac.h>
+#include <openssl/evp.h>
+#include <openssl/bio.h>
+#include <openssl/buffer.h>
+
+extern   int getServiceFromFile(char*,service**);
+extern   int conf_read(char*,maps*);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <libxml/parser.h>
+  static char* SERVICE_URL;
+
+  void URLDecode(char *);
+  char *url_encode(char *);
+  
+  void printExceptionReportResponse(maps*,map*);
+  void printProcessResponse1(maps*,map*,int,service*,char*,int,maps*,maps*);
+  void printProcessResponse(maps*,int,service*,char*,int,map*,map*);
+  void printGetCapabilitiesResponse(service**,int,char*,maps*);
+  xmlNodePtr printGetCapabilitiesHeader(xmlDocPtr,char*,maps*);
+  void printGetCapabilitiesForProcess(maps*,xmlNodePtr,service*);
+  void printGetCapabilitiesDocument(xmlDocPtr);
+  void printDescribeProcessResponse(service*,char*);
+  xmlNodePtr printDescribeProcessHeader(xmlDocPtr,char*,maps*);
+  void printDescribeProcessForProcess(maps*,xmlNodePtr,service**,int);
+  void printDescribeProcessDocument(xmlDocPtr);
+  void printDocument(xmlDocPtr);
+  void printDescription(xmlNodePtr,xmlNsPtr,char*,map*);
+  void printIOType1(xmlDocPtr,xmlNodePtr,xmlNsPtr,xmlNsPtr,elements*,maps*,char*);
+  void printIOType(xmlDocPtr,xmlNodePtr,xmlNsPtr,xmlNsPtr,elements*,map*,char*);
+  void printOutputDefinitions1(xmlDocPtr,xmlNodePtr,xmlNsPtr,xmlNsPtr,elements*,maps*,char*);
+  void printOutputDefinitions(xmlDocPtr,xmlNodePtr,xmlNsPtr,xmlNsPtr,elements*,map*,char*);
+  
+  void outputResponse(service*,maps*,maps*,map*,int,maps*,int);
+
+  char *base64(const unsigned char*,int);
+
+  void addDefaultValues(maps**,elements*,maps*,char*);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: trunk/zoo-kernel/service_internal_java.c
===================================================================
--- trunk/zoo-kernel/service_internal_java.c	(revision 1)
+++ trunk/zoo-kernel/service_internal_java.c	(revision 1)
@@ -0,0 +1,325 @@
+/**
+ * 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.
+ */
+
+#include "service_internal_java.h"
+
+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[2048];
+  char oclasspath[2068];
+  int res=SERVICE_FAILED;
+  if(tmp!=NULL){
+    sprintf(classpath,"%s/%s/:$CLASSPATH",ntmp,tmp->value);
+    sprintf(oclasspath,"-Djava.class.path=%s/%s",ntmp,tmp->value);
+  }
+  else{
+    sprintf(classpath,"%s:$CLASSPATH",ntmp);
+    sprintf(oclasspath,"-Djava.class.path=%s",ntmp);
+  }
+#ifdef DEBUG
+  fprintf(stderr,"CLASSPATH=%s\n",classpath);
+#endif
+  setenv("CLASSPATH",classpath,1);
+
+  JavaVMOption options[2];
+  JavaVMInitArgs vm_args;
+  JavaVM *jvm;
+  JNIEnv *env;
+  long result;
+  jmethodID pmid;
+  jfieldID fid;
+  jobject jobj;
+  jclass cls,cls_gr;
+  int i;
+
+  options[0].optionString = oclasspath;
+  options[1].optionString = "-Djava.compiler=NONE";
+
+  vm_args.version = JNI_VERSION_1_4;
+  vm_args.options = options;
+  vm_args.nOptions = 2;
+  vm_args.ignoreUnrecognized = JNI_FALSE;
+
+  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");
+  cls = (*env)->FindClass(env,tmp->value);
+  cls_gr = (*env)->NewGlobalRef(env, cls);
+  if( cls == NULL ) {
+    char pbt[10240];
+    sprintf(pbt,"can't find class %s\n",tmp->value);
+    map* err=createMap("text",pbt);
+    addToMap(err,"code","NoApplicableCode");
+    printExceptionReportResponse(m,err);
+    (*jvm)->DestroyJavaVM(jvm);
+    return 1;
+  }
+#ifdef DEBUG
+  else{
+    fprintf(stderr,"%s loaded\n",tmp->value);
+  }
+#endif
+
+  if (cls != NULL) {
+    (*env)->ExceptionClear(env);
+    pmid=(*env)->GetStaticMethodID(env,cls_gr, s->name, "(Ljava/util/HashMap;Ljava/util/HashMap;Ljava/util/HashMap;)I");
+    if (pmid!=0){
+#ifdef DEBUG
+      fprintf(stderr,"Function successfully loaded\n");
+#endif
+      /**
+       * The 3 standard parameter for each services
+       */
+      jobject arg1=HashMap_FromMaps(env,m);
+      jobject arg2=HashMap_FromMaps(env,inputs);
+      jobject arg3=HashMap_FromMaps(env,outputs);
+      jint pValue=0;
+
+      pValue=(*env)->CallStaticIntMethod(env,cls,pmid,arg1,arg2,arg3);
+      if (pValue != NULL){
+	res=pValue;
+	//inputs=mapsFromHashMap(env,arg2);
+	outputs=mapsFromHashMap(env,arg3);
+	*real_outputs=outputs;
+
+#ifdef DEBUG
+	fprintf(stderr,"Result of call: %i\n", pValue);
+	dumpMaps(inputs);
+	dumpMaps(outputs);
+	/*fprintf(stderr,"printProcessResponse(%i,\"%s\",%i,inputs,outputs);",
+	  getpid(),tmp->value,PyInt_AsLong(pValue));*/
+#endif
+      }else{	  
+	/**
+	 * Error handling displayig stack trace in ExceptionReport
+	 */
+	map *tmpm=getMapFromMaps(*main_conf,"main","tmpPath");
+	char tmps[1024];
+	sprintf(tmps,"%s/%d.ztmp",tmpm->value,getpid());
+	int old_stdout=dup(fileno(stdout));
+	FILE* new_stdout=fopen(tmps,"w+");
+	dup2(fileno(new_stdout),fileno(stdout));
+	(*env)->ExceptionDescribe(env);
+	fflush(stdout);
+	dup2(old_stdout,fileno(stdout));
+	fseek(new_stdout, 0, SEEK_END);
+	long flen=ftell(new_stdout);
+	rewind(new_stdout);
+	char tmps1[flen];
+	fread(tmps1,flen,1,new_stdout);
+	fclose(new_stdout);
+	char pbt[100+flen];
+	sprintf(pbt,"Unable to run your java process properly. Server returns : %s",tmps1);
+	map* err=createMap("text",pbt);
+	addToMap(err,"code","NoApplicableCode");
+	printExceptionReportResponse(m,err);
+	(*jvm)->DestroyJavaVM(jvm);
+	return 1;
+      }
+    }
+    else{
+      char tmpS[1024];
+      sprintf(tmpS, "Cannot find function %s \n", s->name);
+      map* tmps=createMap("text",tmpS);
+      printExceptionReportResponse(m,tmps);
+      (*jvm)->DestroyJavaVM(jvm);
+      exit(-1);
+    }
+  }else{
+    char tmpS[1024];
+    sprintf(tmpS, "Cannot find function %s \n", tmp->value);
+    map* tmps=createMap("text",tmpS);
+    printExceptionReportResponse(m,tmps);
+    if (PyErr_Occurred())
+      PyErr_Print();
+  }
+  (*jvm)->DestroyJavaVM(jvm);
+  return res;
+}
+
+jobject HashMap_FromMaps(JNIEnv *env,maps* t){
+  jclass scHashMapClass,scHashMap_class;
+  jmethodID scHashMap_constructor;
+  jobject scObject,scObject1;
+  scHashMapClass = (*env)->FindClass(env, "java/util/HashMap");
+  scHashMap_class = (*env)->NewGlobalRef(env, scHashMapClass);
+  scHashMap_constructor = (*env)->GetMethodID(env, scHashMap_class, "<init>", "()V");   
+  if(scHashMap_constructor!=NULL){
+    scObject = (*env)->NewObject(env, scHashMap_class, scHashMap_constructor);
+    jmethodID put_mid = 0;
+
+    put_mid = (*env)->GetMethodID(env,scHashMapClass, "put",
+				  "(Ljava/lang/Object;Ljava/lang/Object;)"
+				  "Ljava/lang/Object;");
+    maps* tmp=t;
+    while(tmp!=NULL){
+      map* tmp1=tmp->content;
+      scObject1 = (*env)->NewObject(env, scHashMap_class, scHashMap_constructor);
+      while(tmp1!=NULL){
+	(*env)->CallObjectMethod(env,scObject1, put_mid, (*env)->NewStringUTF(env,tmp1->name), (*env)->NewStringUTF(env,tmp1->value));
+	tmp1=tmp1->next;
+      }
+      (*env)->CallObjectMethod(env,scObject, put_mid, (*env)->NewStringUTF(env,tmp->name), scObject1);
+      tmp=tmp->next;
+    } 
+    return scObject;
+  }
+  else
+    return NULL;
+}
+
+maps* mapsFromHashMap(JNIEnv *env,jobject t){
+#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 scHashMapClass,scHashMap_class,scSetClass,scIteratorClass,scMapEntryClass,scSet_class,scMapClass;
+  jmethodID entrySet_mid,iterator_mid,hasNext_mid,next_mid,getKey_mid,getValue_mid;
+  jobject scObject,scObject1;
+  scHashMapClass=(*env)->GetObjectClass(env,t);
+  //scMapClass=(*env)->FindClass(env, "java/util/HashMap");
+  //scHashMapClass = (*env)->FindClass(env, "java/util/HashMap");
+  if(scHashMapClass==NULL){
+    fprintf(stderr,"Unable to load java.util.HashMap\n");
+    return NULL;
+  }
+  entrySet_mid = (*env)->GetMethodID(env, scHashMapClass, "entrySet", "()Ljava/util/Set;"); 
+  if(entrySet_mid==0){
+    fprintf(stderr,"unable to load entrySet from HashMap object (%d) \n",entrySet_mid);
+    return NULL;
+  }
+#ifdef DEBUG
+  else
+    fprintf(stderr,"entrySet loaded from HashMap object (%d) \n",entrySet_mid);
+#endif
+
+  scSetClass = (*env)->FindClass(env, "java/util/Set");
+  iterator_mid = (*env)->GetMethodID(env, scSetClass, "iterator", "()Ljava/util/Iterator;"); 
+#ifdef DEBUG
+  fprintf(stderr,"mapsFromHashMap 1 (%d) \n",iterator_mid);
+#endif
+
+  scIteratorClass = (*env)->FindClass(env, "java/util/Iterator");
+  hasNext_mid = (*env)->GetMethodID(env, scIteratorClass, "hasNext", "()Z");
+#ifdef DEBUG
+  fprintf(stderr,"mapsFromHashMap 2 (%d)\n",hasNext_mid);
+#endif
+  next_mid = (*env)->GetMethodID(env, scIteratorClass, "next", "()Ljava/lang/Object;");
+#ifdef DEBUG
+  fprintf(stderr,"mapsFromHashMap 3 (%d)\n",next_mid);
+#endif
+
+  scMapEntryClass = (*env)->FindClass(env, "java/util/Map$Entry");
+  getKey_mid = (*env)->GetMethodID(env, scMapEntryClass, "getKey", "()Ljava/lang/Object;");
+#ifdef DEBUG
+  fprintf(stderr,"mapsFromHashMap 4 (%d)\n",getKey_mid);
+#endif
+  getValue_mid = (*env)->GetMethodID(env, scMapEntryClass, "getValue", "()Ljava/lang/Object;");
+#ifdef DEBUG
+  fprintf(stderr,"mapsFromHashMap 5 (%d)\n",getValue_mid);
+#endif
+
+  jobject final_set=(*env)->CallObjectMethod(env,t,entrySet_mid);
+  jobject final_iterator=(*env)->CallObjectMethod(env,final_set,iterator_mid);
+
+
+  maps* final_res=NULL;
+  map* res=NULL;
+#ifdef DEBUG
+  int i=0;
+#endif
+  while((*env)->CallBooleanMethod(env,final_iterator,hasNext_mid)){
+#ifdef DEBUG
+    fprintf(stderr,"mapsFromHashMap loop %d\n",i);
+    i++;
+#endif
+    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);
+#ifdef DEBUG
+    int j=0;
+#endif
+    while((*env)->CallBooleanMethod(env,iterator,hasNext_mid)){
+#ifdef DEBUG
+      fprintf(stderr,"mapsFromHashMap internal loop %d\n",j);
+      j++;
+#endif
+      jobject tmp1=(*env)->CallObjectMethod(env,iterator,next_mid);
+      jobject jk=(*env)->CallObjectMethod(env,tmp1,getKey_mid);
+      jobject jv=(*env)->CallObjectMethod(env,tmp1,getValue_mid);
+
+#ifdef DEBUG
+      jstring jkd=(*env)->GetStringUTFChars(env, jk, NULL);
+      jstring jvd=(*env)->GetStringUTFChars(env, jv, NULL);
+      fprintf(stderr,"%s %s\n",jkd,jvd);
+#endif
+
+      if(res==NULL){
+	res=createMap((*env)->GetStringUTFChars(env, jk, NULL),
+		      (*env)->GetStringUTFChars(env, jv, NULL));
+      }else
+	addToMap(res,(*env)->GetStringUTFChars(env, jk, NULL),
+		 (*env)->GetStringUTFChars(env, jv, NULL));
+    }
+    jobject jk=(*env)->CallObjectMethod(env,tmp,getKey_mid);
+    maps* cmap=(maps*)malloc(sizeof(maps));
+    cmap->name=(*env)->GetStringUTFChars(env, jk, NULL);
+    cmap->content=res;
+    cmap->next=NULL;
+    if(final_res==NULL){
+      final_res=cmap;
+    }else
+      addMapsToMaps(final_res,cmap);
+    final_res->next=NULL;
+    res=NULL;
+  }
+#ifdef DEBUG
+  fprintf(stderr,"mapsFromHashMap end\n");
+#endif
+
+  return final_res;
+}
Index: trunk/zoo-kernel/service_internal_java.h
===================================================================
--- trunk/zoo-kernel/service_internal_java.h	(revision 1)
+++ trunk/zoo-kernel/service_internal_java.h	(revision 1)
@@ -0,0 +1,46 @@
+/**
+ * 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* t);
+
+maps* mapsFromHashMap(JNIEnv*,jobject t);
+
+int zoo_java_support(maps**,map*,service*,maps**,maps**);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
Index: trunk/zoo-kernel/service_internal_js.c
===================================================================
--- trunk/zoo-kernel/service_internal_js.c	(revision 1)
+++ trunk/zoo-kernel/service_internal_js.c	(revision 1)
@@ -0,0 +1,417 @@
+/**
+ * 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.
+ */
+
+#include "service_internal_js.h"
+
+static char dbg[1024];
+
+int zoo_js_support(maps** main_conf,map* request,service* s,
+		   maps **inputs,maps **outputs)
+{
+  /* The class of the global object. */
+  JSClass global_class = {
+    "global", JSCLASS_GLOBAL_FLAGS,
+    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+    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);
+  JS_SetVersion(cx, JSVERSION_LATEST);
+  JS_SetErrorReporter(cx, reportError);
+
+  /* Create the global object. */
+  global = JS_NewObject(cx, &global_class, NULL, NULL);
+  if (global == NULL){
+    return 1;
+  }
+
+  /* Populate the global object with the standard globals,
+     like Object and Array. */
+  if (!JS_InitStandardClasses(cx, global)){
+    return 1;
+  }
+  if (!JS_DefineFunction(cx, global, "ZOORequest", JSRequest, 4, 0))
+    return 1;
+
+  /* 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* tmpm1=getMap(request,"metapath");
+  map* tmpm2=getMap(s->content,"serviceProvider");
+  char *filename[strlen(tmpm1->value)+strlen(tmpm2->value)+6];
+  char ntmp[1024];
+  getcwd(ntmp,1024);
+  sprintf(filename,"%s/%s%s",ntmp,tmpm1->value,tmpm2->value);
+  struct stat file_status;
+  stat(filename, &file_status);
+  char source[file_status.st_size];
+  uint16 lineno;
+  jsval rval;
+  FILE *jsfile=fopen(filename,"rb");
+  JSBool ok ;
+  JSScript *script = JS_CompileFileHandle(cx, global, filename, jsfile);
+  if(script){
+    (void)JS_ExecuteScript(cx, global, script, &rval);
+  }
+  else{
+    char tmp1[1024];
+    sprintf(tmp1,"Unable to load JavaScript file %s",filename);
+    map* err=createMap("text",tmp1);
+    addMapToMap(&err,createMap("code","NoApplicableCode"));
+    printExceptionReportResponse(mc,err);
+    JS_DestroyContext(cx);
+    JS_DestroyRuntime(rt);
+    JS_ShutDown();
+    exit(-1);
+  }
+  /* Call a function in obj's scope. */
+  jsval argv[3];
+  argv[0] = OBJECT_TO_JSVAL(JSObject_FromMaps(cx,*main_conf));
+  argv[1] = OBJECT_TO_JSVAL(JSObject_FromMaps(cx,*inputs));
+  argv[2] = OBJECT_TO_JSVAL(JSObject_FromMaps(cx,*outputs));
+  jsval rval1;
+#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) {
+#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);
+    if (ok==JS_TRUE) {
+#ifdef JS_DEBUG
+      fprintf(stderr,"Function run sucessfully !\n");
+#endif
+      /*char tmpres[10];
+      sprintf(tmpres,"%p",(void *)d);
+      res=atoi(tmpres);*/
+    }
+  }else{
+    /* Unable to run JS function */
+    char tmp1[1024];
+    //sprintf(tmp1,"Unable to run %s from the JavScript file %s",s->name,filename);
+    sprintf(tmp1,"Unable to run %s from the JavScript file %s : \n %s",s->name,filename,dbg);
+    fprintf(stderr,"%s",tmp1);
+    map* err=createMap("text",tmp1);
+    addMapToMap(err,createMap("code","NoApplicableCode"));
+    printExceptionReportResponse(*main_conf,err);
+    JS_DestroyContext(cx);
+    JS_DestroyRuntime(rt);
+    JS_ShutDown();
+    exit(-1);
+  }
+
+  jsval t=OBJECT_TO_JSVAL(d);
+  //JSVAL_TO_OBJECT(t);
+  if(JS_IsArrayObject(cx,t)){
+#ifdef JS_DEBUG
+    fprintf(stderr,"An array was returned !\n");
+#endif
+    jsdouble len;
+    if((JS_GetArrayLength(cx, t, &len)==JS_FALSE)){
+#ifdef JS_DEBUG
+      fprintf(stderr,"outputs array is empty\n");
+#endif
+    }
+    jsval tmp1;
+    JSBool hasResult=JS_GetElement(cx,t,0,&tmp1);
+    res=JSVAL_TO_INT(tmp1);
+#ifdef JS_DEBUG
+    fprintf(stderr," * %d * \n",res);
+#endif
+    jsval tmp2;
+    JSBool hasElement=JS_GetElement(cx,t,1,&tmp2);
+    out=mapsFromJSObject(cx,tmp2);
+    *outputs=out;
+  }
+  else{
+    //#ifdef JS_DEBUG
+    fprintf(stderr,"The service didn't return an array !\n");
+    //#endif
+    jsval tmp1;
+    JSBool hasResult=JS_GetProperty(cx,t,"result",&tmp1);
+    res=JSVAL_TO_INT(tmp1);
+
+    //#ifdef JS_DEBUG
+    fprintf(stderr," * %d * \n",res);
+    //#endif
+    jsval tmp2;
+    JSBool hasElement=JS_GetProperty(cx,t,"outputs",&tmp2);
+    if(!hasElement)
+      fprintf(stderr,"No outputs property returned\n");
+    if(JS_IsArrayObject(cx,tmp2))
+      fprintf(stderr,"outputs is array an as expected\n");
+    else
+      fprintf(stderr,"outputs is not an array as expected\n");
+    out=mapsFromJSObject(cx,tmp2);
+#ifdef JS_DEBUG
+    dumpMaps(out);
+#endif
+    *outputs=out;
+  }
+
+  *inputs=mapsFromJSObject(cx,argv[1]);
+  *main_conf=mapsFromJSObject(cx,argv[0]);
+
+  
+  //}
+  //else
+  // ERROR 
+  //;
+
+  /* Cleanup. */
+  JS_MaybeGC(cx);
+  JS_DestroyScript(cx, script);
+  JS_DestroyContext(cx);
+  JS_DestroyRuntime(rt);
+  JS_ShutDown();
+  fflush(stderr);
+#ifdef JS_DEBUG
+  fprintf(stderr,"Returned value %d\n",res);
+#endif
+  return res;
+}
+
+JSObject* JSObject_FromMaps(JSContext *cx,maps* t){
+  JSObject *res = JS_NewArrayObject(cx, 0, NULL);
+  maps* tmp=t;
+  while(tmp!=NULL){
+    jsuint len;
+    JSObject* res1=JS_NewObject(cx, NULL, NULL, NULL);
+    JSObject *pval=JSObject_FromMap(cx,tmp->content);
+    jsval pvalj=OBJECT_TO_JSVAL(pval);
+    JS_SetProperty(cx, res1, tmp->name, &pvalj);
+    JS_GetArrayLength(cx, res, &len);
+    jsval res1j = OBJECT_TO_JSVAL(res1);
+    JS_SetElement(cx,res,len,&res1j);
+#ifdef JS_DEBUG
+    fprintf(stderr,"Length of the Array %d, element : %s added \n",len,tmp->name);
+#endif
+    tmp=tmp->next;
+  }  
+  return res;
+}
+
+JSObject* JSObject_FromMap(JSContext *cx,map* t){
+  JSObject* res=JS_NewObject(cx, NULL, NULL, NULL);
+  jsval resf =  OBJECT_TO_JSVAL(res);
+  map* tmpm=t;
+  while(tmpm!=NULL){
+    jsval jsstr = STRING_TO_JSVAL(JS_NewString(cx,tmpm->value,strlen(tmpm->value)));
+    JS_SetProperty(cx, resf, tmpm->name,&jsstr);
+#ifdef JS_DEBUG
+    fprintf(stderr,"%s => %s\n",tmpm->name,tmpm->value);
+#endif
+    tmpm=tmpm->next;
+  }
+  return res;
+}
+
+maps* mapsFromJSObject(JSContext *cx,jsval t){
+  maps *res=NULL;
+  maps *tres=NULL;
+  JSVAL_TO_OBJECT(t);
+#ifdef JS_DEBUG
+  fprintf(stderr,"Is finally an array ?\n");
+#endif
+  if(JS_IsArrayObject(cx,t)){
+#ifdef JS_DEBUG
+    fprintf(stderr,"Is finally an array !\n");
+#endif
+  }
+#ifdef JS_DEBUG
+  else
+    fprintf(stderr,"Is not an array !\n");
+#endif
+  jsdouble len;
+  if((JS_GetArrayLength(cx, t, &len)==JS_FALSE)){
+#ifdef JS_DEBUG
+    fprintf(stderr,"outputs array is empty\n");
+#endif
+  }
+  int i=0;
+  char tmp[10];
+  sprintf(tmp,"%d",len);
+  int clen=atoi(tmp);
+#ifdef JS_DEBUG
+  fprintf(stderr,"outputs array length : %d\n",len);
+#endif
+  for(i=0;i<len;i++){
+#ifdef JS_DEBUG
+    fprintf(stderr,"outputs array length : %d step %d\n",len,i);
+#endif
+    jsval tmp1;
+    JSBool hasElement=JS_GetElement(cx,t,i,&tmp1);
+    JSVAL_TO_OBJECT(tmp1);
+    JSIdArray *idp=JS_Enumerate(cx,tmp1);
+    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++) { 
+	jsid* id = idp->vector[index];
+	jsval vp;
+	JSString* str; 
+	JS_IdToValue(cx,id,&vp);
+	char *c, *tmp;
+	JSString *jsmsg;
+	size_t len1;
+	jsmsg = JS_ValueToString(cx,vp);
+	len1 = JS_GetStringLength(jsmsg);
+#ifdef JS_DEBUG
+	fprintf(stderr,"Enumerate id : %d => %s\n",i,JS_GetStringBytes(jsmsg));
+#endif
+	jsval nvp;
+	if((JS_GetProperty(cx, tmp1, JS_GetStringBytes(jsmsg), &nvp)==JS_FALSE))
+#ifdef JS_DEBUG
+	fprintf(stderr,"Enumerate id : %d => %s => No more value\n",i,JS_GetStringBytes(jsmsg));
+#endif
+	if(JSVAL_IS_OBJECT(nvp)){
+#ifdef JS_DEBUG
+	  fprintf(stderr,"JSVAL NVP IS OBJECT\n");
+#endif
+	}
+#ifdef JS_DEBUG
+	else
+	  fprintf(stderr,"JSVAL NVP IS NOT OBJECT !!\n");
+#endif
+	JSObject *nvp1;
+	JS_ValueToObject(cx,nvp,&nvp1);
+	jsval nvp1j=OBJECT_TO_JSVAL(nvp1);
+	if(JSVAL_IS_OBJECT(nvp1j)){
+#ifdef JS_DEBUG
+	  fprintf(stderr,"JSVAL NVP1J IS OBJECT\n");
+#endif
+	  tres=(maps*)malloc(sizeof(maps*));
+	  tres->name=strdup(JS_GetStringBytes(jsmsg));
+	  tres->content=mapFromJSObject(cx,nvp1j);
+	  tres->next=NULL;
+#ifdef JS_DEBUG
+	  dumpMaps(res);
+#endif
+	  if(res==NULL)
+	    res=tres;
+	  else
+	    addMapsToMaps(&res,tres);
+#ifdef JS_DEBUG
+	  dumpMaps(res);
+#endif
+	}
+#ifdef JS_DEBUG
+	else
+	  fprintf(stderr,"JSVAL NVP1J IS NOT OBJECT !!\n");
+#endif
+      }
+    }
+  }
+#ifdef JS_DEBUG
+  dumpMaps(res);
+#endif
+  return res;
+}
+
+map* mapFromJSObject(JSContext *cx,jsval t){
+  map *res=NULL;
+  JSIdArray *idp=JS_Enumerate(cx,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++) { 
+      jsid* id = idp->vector[index];
+      jsval vp;
+      JSString* str; 
+      JS_IdToValue(cx,id,&vp);
+      char *c, *tmp;
+      JSString *jsmsg,*jsmsg1;
+      size_t len,len1;
+      jsmsg = JS_ValueToString(cx,vp);
+      len = JS_GetStringLength(jsmsg);
+      jsval nvp;
+      JS_GetProperty(cx, t, JS_GetStringBytes(jsmsg), &nvp);
+      jsmsg1 = JS_ValueToString(cx,nvp);
+      len1 = JS_GetStringLength(jsmsg1);
+#ifdef JS_DEBUG
+      fprintf(stderr,"Enumerate id : %d [ %s => %s ]\n",index,JS_GetStringBytes(jsmsg),JS_GetStringBytes(jsmsg1));
+#endif
+      if(res!=NULL)
+	addMapToMap(&res,createMap(JS_GetStringBytes(jsmsg),JS_GetStringBytes(jsmsg1)));
+      else
+	res=createMap(JS_GetStringBytes(jsmsg),JS_GetStringBytes(jsmsg1));
+    }
+  }
+#ifdef JS_DEBUG
+  dumpMap(res);
+#endif
+  return res;
+}
+
+
+/* The error reporter callback. */
+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);
+}
+
Index: trunk/zoo-kernel/service_internal_js.h
===================================================================
--- trunk/zoo-kernel/service_internal_js.h	(revision 1)
+++ trunk/zoo-kernel/service_internal_js.h	(revision 1)
@@ -0,0 +1,58 @@
+/**
+ * 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 
+
+#define XP_UNIX 0
+
+#include "service.h"
+#include "service_internal.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include "jsapi.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);
+
+  void reportError(JSContext *cx, const char *message, JSErrorReport *report);
+  
+  int zoo_js_support(maps**,map*,service*,maps **,maps **);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
Index: trunk/zoo-kernel/service_internal_php.c
===================================================================
--- trunk/zoo-kernel/service_internal_php.c	(revision 1)
+++ trunk/zoo-kernel/service_internal_php.c	(revision 1)
@@ -0,0 +1,238 @@
+/**
+ * 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.
+ */
+
+#include "service_internal_php.h"
+
+#ifdef ZTS
+void ***tsrm_ls;
+#endif
+
+int zoo_php_support(maps** main_conf,map* request,service* s,maps **real_inputs,maps **real_outputs){
+  fprintf(stderr,"STARING PHP SCRIPT\n");
+  maps* m=*main_conf;
+  maps* inputs=*real_inputs;
+  maps* outputs=*real_outputs;
+  char ntmp[1024];
+  getcwd(ntmp,1024);
+  map* tmp=getMap(request,"metapath");
+
+  int res=SERVICE_FAILED;
+
+  tmp=getMap(s->content,"serviceProvider");
+  zend_file_handle iscript;
+  iscript.type=ZEND_HANDLE_FP;
+  iscript.filename=tmp->value;
+  iscript.opened_path=NULL;
+  //iscript.free_filname=0;
+  if(!(iscript.handle.fp=fopen(iscript.filename,"rb"))){
+    char tmp1[1024];
+    sprintf(tmp1,"Unable to load PHP file %s",tmp->value);
+    map* err=createMap("text",tmp1);
+    addToMap(err,"code","NoApplicableCode");
+    printExceptionReportResponse(m,err);
+    exit(-1);
+  }
+
+  php_embed_init(0,NULL,&tsrm_ls);
+
+  fprintf(stderr,"PHP EMBEDED\n");
+  
+  zend_try {
+    fprintf(stderr,"PHP EMBEDED include script %s\n",tmp->value);
+    php_execute_script(&iscript TSRMLS_CC);
+    fprintf(stderr,"PHP EMBEDED include script done\n");
+
+    zval *iargs[3];
+    zval iret, ifunc,ifile;
+      
+    ZVAL_STRING(&ifunc, s->name, 0);
+    fprintf(stderr,"PHP EMBEDED include script done\n");
+    iargs[0] = php_Array_from_maps(*main_conf);
+    fprintf(stderr,"PHP EMBEDED include script done\n");
+    iargs[1] = php_Array_from_maps(*real_inputs);
+    fprintf(stderr,"PHP EMBEDED include script done\n");
+    iargs[2] = php_Array_from_maps(*real_outputs);
+    fprintf(stderr,"PHP EMBEDED include script done\n");
+    
+    call_user_function(EG(function_table), NULL, &ifunc, &iret, 3, iargs TSRMLS_CC);
+
+    HashTable* t=HASH_OF(iargs[2]);
+    *real_outputs=php_maps_from_Array(t);
+    
+    dumpMaps(*real_outputs);
+
+    char tmp1[1024];
+
+    sprintf(tmp1,"PHP EMBEDED ran function successfully and return %d !?",Z_STRVAL(iret));
+
+    res=SERVICE_SUCCEEDED;
+
+  } zend_catch { 
+    map* err=createMap("text","Unable to process.");
+    addToMap(err,"code","NoApplicableCode");
+    printExceptionReportResponse(m,err);
+    exit(-1);
+  } zend_end_try();
+
+  php_embed_shutdown(TSRMLS_C);
+
+  return res;
+}
+
+zval *php_Array_from_maps(maps* t){
+  zval *mapArray;
+  zval *mapArrayTmp;
+  maps* tmp=t;
+  int tres=0;
+  fprintf(stderr,"arra_init\n");
+  MAKE_STD_ZVAL(mapArray);
+  tres=array_init(mapArray);
+  fprintf(stderr,"arra_init %d\n",tres);
+  while(tmp!=NULL){
+    add_assoc_zval(mapArray,tmp->name,php_Array_from_map(tmp->content));
+    tmp=tmp->next;
+  }
+  return mapArray;
+}
+
+zval *php_Array_from_map(map* t){
+  zval *mapArray;
+  zval *mapArrayTmp;
+  map* tmp=t;
+  int tres=0;
+  fprintf(stderr,"arra_init\n");
+  MAKE_STD_ZVAL(mapArray);
+  tres=array_init(mapArray);
+  fprintf(stderr,"arra_init\n");
+  while(tmp!=NULL){
+    fprintf(stderr,"=> %s %d %s %d \n",tmp->name,strlen(tmp->name),tmp->value,strlen(tmp->value));
+    tres=add_assoc_string(mapArray,tmp->name,tmp->value,1);
+    tmp=tmp->next;
+  }
+  return mapArray;
+}
+
+maps* php_maps_from_Array(HashTable *t){
+  //#ifdef DEBUG
+  fprintf(stderr,"mapsFromPHPArray start\n");
+  //#endif
+  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); 
+    fprintf(stderr,"key : %s\n",key);
+    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;
+    fprintf(stderr,"key : %s\n",key);
+    zval_copy_ctor(&tmpcopy); 
+    fprintf(stderr,"key : %s\n",key);
+    /**
+     * 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);
+    }
+    fprintf(stderr,"key : %s\n",key);
+    HashTable* t=HASH_OF(*ppzval);
+    fprintf(stderr,"key : %s\n",key);
+    cursor->content=php_map_from_HasTable(t);
+    cursor->next=NULL;
+    if(final_res==NULL)
+      final_res=cursor;
+    else
+      addMapsToMaps(&final_res,cursor);
+    fprintf(stderr,"key : %s\n",key);
+    /**
+     * Toss out old copy
+     */
+    zval_dtor(&tmpcopy);
+  }
+  return final_res;
+}
+
+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; 
+    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(final_res==NULL){
+      fprintf(stderr,"%s => %s\n",key,Z_STRVAL(tmpcopy));
+      final_res=createMap(key,Z_STRVAL(tmpcopy));
+    }
+    else{
+      fprintf(stderr,"%s => %s\n",key,Z_STRVAL(tmpcopy));
+      addMapToMap(&final_res,createMap(key,Z_STRVAL(tmpcopy)));
+    }
+    /* Toss out old copy */ 
+    zval_dtor(&tmpcopy); 
+  }
+  return final_res;
+}
Index: trunk/zoo-kernel/service_internal_php.h
===================================================================
--- trunk/zoo-kernel/service_internal_php.h	(revision 1)
+++ trunk/zoo-kernel/service_internal_php.h	(revision 1)
@@ -0,0 +1,49 @@
+/**
+ * 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>
+#include <sapi/embed/php_embed.h>
+#include <zend_stream.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+  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);
+  int zoo_php_support(maps**,map*,service*,maps**,maps**);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
Index: trunk/zoo-kernel/service_internal_python.c
===================================================================
--- trunk/zoo-kernel/service_internal_python.c	(revision 1)
+++ trunk/zoo-kernel/service_internal_python.c	(revision 1)
@@ -0,0 +1,371 @@
+/**
+ * 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.
+ */
+
+#include "service_internal_python.h"
+
+int python_support(maps* m,service* s,int argc,char** argv,map *inputs,map *outputs){
+  Py_Initialize();
+  PyObject *pName, *pModule, *pFunc;
+  pName = PyString_FromString(argv[2]);
+  pModule = PyImport_Import(pName);
+  int i;
+  if (pModule != NULL) {
+    pFunc=PyObject_GetAttrString(pModule,argv[4]);
+    if (pFunc && PyCallable_Check(pFunc)){
+      PyDictObject* arg1=PyDict_FromMap(inputs);
+      PyDictObject* arg2=PyDict_FromMap(outputs);
+      PyObject *pArgs=PyTuple_New(2);
+      PyObject *pValue;
+      PyTuple_SetItem(pArgs, 0, (PyObject *)arg1);
+      PyTuple_SetItem(pArgs, 1, (PyObject *)arg2);
+      pValue = PyString_FromString(argv[argc-1]);
+#ifdef DEBUG
+      fprintf(stderr,"Function successfully loaded\n");
+#endif	
+      /**
+       * Need to check if we need to fork to load a status enabled 
+       */
+      if(strcmp(PyString_AsString(pValue),"bg")!=0){
+#ifdef DEBUG
+	fprintf(stderr,"RUN IN NORMAL MODE \n");
+#endif
+	pValue = PyObject_CallObject(pFunc, pArgs);
+	if (pValue != NULL) {
+	  inputs=mapFromPyDict(arg1);
+	  outputs=mapFromPyDict(arg2);
+#ifdef DEBUG
+	  fprintf(stderr,"Result of call: %i\n", PyInt_AsLong(pValue));
+	  dumpMap(inputs);
+	  dumpMap(outputs);
+#ifndef WIN32
+	  fprintf(stderr,"printProcessResponse(%i,\"%s\",%i,inputs,outputs);",getpid(),argv[1],PyInt_AsLong(pValue));
+#endif
+#endif
+	  printProcessResponse(m,getpid(),s,argv[2],PyInt_AsLong(pValue),inputs,outputs);
+	}
+      }
+      else{
+	pid_t pid;
+#ifdef WIN32
+	pid = 0;
+#else
+	pid = fork ();
+#endif
+	if (pid > 0) {
+	  /* dady */
+	  printProcessResponse(m,pid,s,argv[2],SERVICE_STARTED,inputs,outputs);
+	}else if (pid == 0) {
+	  /* son */
+#ifdef DEBUG
+	  fprintf(stderr,"RUN IN BACKGROUND MODE \n");
+#endif
+	  char tmp1[256];
+	  sprintf(tmp1,"service/temp/%s_%d.xml",argv[2],getpid());
+#ifndef WIN32
+	  stdout =
+#endif
+		  freopen(tmp1 , "w+" , stdout);
+	  printProcessResponse(m,getpid(),s,argv[2],SERVICE_STARTED,inputs,outputs);
+	  fflush(stdout);
+	  pValue = PyObject_CallObject(pFunc, pArgs);
+	  if (pValue != NULL) {
+	    rewind(stdout);
+	    inputs=mapFromPyDict(arg1);
+	    outputs=mapFromPyDict(arg2);
+#ifdef DEBUG
+	    fprintf(stderr,"Result of call: %ld\n", PyInt_AsLong(pValue));
+	    dumpMap(inputs);
+	    dumpMap(outputs);
+	    fprintf(stderr,"printProcessResponse(%i,%s,%i,inputs,outputs);",s,getpid(),argv[2],PyInt_AsLong(pValue));
+#endif
+//	    sleep(6);
+	    printProcessResponse(m,getpid(),s,argv[2],PyInt_AsLong(pValue),inputs,outputs);
+	  }
+	  exit(1);
+	} else {
+	  /* error */
+	}
+      }
+      Py_DECREF(pArgs);
+      Py_DECREF(pValue);
+#ifdef DEBUG
+      fprintf(stderr,"Function ran successfully\n");
+#endif	
+    }
+    else{
+      char tmpS[1024];
+      sprintf(tmpS, "Cannot find function %s \n", argv[4]);
+      map* tmps=createMap("text",tmpS);
+      printExceptionReportResponse(m,tmps);
+      //fprintf(stderr, "Cannot find function %s \n", argv[2]);
+      exit(-1);
+    }
+  }else{
+    char tmpS[1024];
+    sprintf(tmpS, "Cannot find function %s \n", argv[4]);
+    map* tmps=createMap("text",tmpS);
+    printExceptionReportResponse(m,tmps);
+    //fprintf(stderr, "Cannot find function %s \n", argv[4]);
+    if (PyErr_Occurred())
+      PyErr_Print();
+
+  }
+  Py_Finalize();
+  return 2;
+}
+
+int zoo_python_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=NULL;
+  tmp=getMapFromMaps(*main_conf,"env","PYTHONPATH");
+  char *python_path=NULL;
+  if(tmp!=NULL){
+	  python_path=(char*)malloc((1+strlen(tmp->value))*sizeof(char));
+	  sprintf(python_path,"%s",tmp->value);
+  }
+  else{
+	python_path=(char*)malloc(2*sizeof(char));
+	python_path=".";
+  }
+  tmp=NULL;
+  tmp=getMap(request,"metapath");
+  char *pythonpath=(char*)malloc((1+strlen(python_path)+2048)*sizeof(char));
+  if(tmp!=NULL && strcmp(tmp->value,"")!=0)
+#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
+#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);
+#endif
+  free(python_path);
+  free(pythonpath);
+  //
+  Py_Initialize();
+  PyObject *pName, *pModule, *pFunc;
+  tmp=getMap(s->content,"serviceProvider");
+  //if(tmp!=NULL)
+  pName = PyString_FromString(tmp->value);
+  pModule = PyImport_Import(pName);
+  int i;
+  int res=SERVICE_FAILED;
+  int cpid=getpid();
+  if (pModule != NULL) {
+    pFunc=PyObject_GetAttrString(pModule,s->name);
+    if (pFunc && PyCallable_Check(pFunc)){
+      PyDictObject* arg1=PyDict_FromMaps(m);
+      PyDictObject* arg2=PyDict_FromMaps(inputs);
+      PyDictObject* arg3=PyDict_FromMaps(outputs);
+      PyObject *pArgs=PyTuple_New(3);
+      PyObject *pValue;
+      PyTuple_SetItem(pArgs, 0, (PyObject *)arg1);
+      PyTuple_SetItem(pArgs, 1, (PyObject *)arg2);
+      PyTuple_SetItem(pArgs, 2, (PyObject *)arg3);
+      tmp=getMap(request,"storeExecuteResponse");
+#ifdef DEBUG
+      fprintf(stderr,"RUN IN NORMAL MODE \n");
+      //fflush(stderr);
+#endif
+      pValue = PyObject_CallObject(pFunc, pArgs);
+      if (pValue != NULL) {
+	res=PyInt_AsLong(pValue);
+	/*inputs=mapsFromPyDict(arg2);
+	dumpMaps(inputs);*/
+	outputs=mapsFromPyDict(arg3);
+	*real_outputs=outputs;
+
+#ifdef DEBUG
+	fprintf(stderr,"Result of call: %i\n", PyInt_AsLong(pValue));
+	dumpMaps(inputs);
+	dumpMaps(outputs);
+	fprintf(stderr,"printProcessResponse(%i,\"%s\",%i,inputs,outputs);",
+		getpid(),tmp->value,PyInt_AsLong(pValue));
+	dumpMaps(outputs);
+#endif
+	Py_DECREF(pValue);
+	Py_XDECREF(pFunc);
+      	Py_DECREF(pArgs);
+	Py_DECREF(pModule);
+      }else{
+	  
+	PyObject *ptype,*pvalue, *ptraceback;
+	PyErr_Fetch(&ptype, &pvalue, &ptraceback);
+	PyObject *trace=PyObject_Str(pvalue);
+	char tb[1024];
+	char pbt[10240];
+	if(PyString_Check(trace))
+	  sprintf(pbt,"TRACE : %s",PyString_AsString(trace));
+	else
+	  fprintf(stderr,"EMPTY TRACE ?");
+	trace=NULL;
+	trace=PyObject_Str(ptype);
+	if(PyString_Check(trace))
+	  sprintf(pbt,"%s\nTRACE : %s",strdup(pbt),PyString_AsString(trace));
+	else
+	  fprintf(stderr,"EMPTY TRACE ?");
+	PyObject *t;
+	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))
+	  sprintf(pbt,"%s\nUnable to run your python process properly. Please check the following messages : %s",strdup(pbt),PyString_AsString(trace));
+	else
+	  sprintf(pbt,"%s \n Unable to run your python process properly. Unable to provide any futher informations.",strdup(pbt));
+	map* err=createMap("text",pbt);
+	addToMap(err,"code","NoApplicableCode");
+	printExceptionReportResponse(m,err);
+	Py_XDECREF(pFunc);
+      	Py_DECREF(pArgs);
+	Py_DECREF(pModule);
+	exit(-1);
+      }
+    }
+    else{
+      char tmpS[1024];
+      sprintf(tmpS, "Cannot find the %s function int the %s file.\n", s->name, tmp->value);
+      map* tmps=createMap("text",tmpS);
+      printExceptionReportResponse(m,tmps);
+      //fprintf(stderr, "Cannot find function %s \n", argv[2]);
+      Py_XDECREF(pFunc);
+      Py_DECREF(pModule);
+      exit(-1);
+    }
+  } else{
+    char tmpS[1024];
+    sprintf(tmpS, "Cannot find function %s \n", tmp->value);
+    map* tmps=createMap("text",tmpS);
+    printExceptionReportResponse(m,tmps);
+    //fprintf(stderr, "Cannot find function %s \n", argv[4]);
+    if (PyErr_Occurred())
+      PyErr_Print();
+    exit(-1);
+  } 
+  Py_Finalize();
+  return res;
+}
+
+PyDictObject* PyDict_FromMaps(maps* t){
+  PyObject* res=PyDict_New( );
+  maps* tmp=t;
+  while(tmp!=NULL){
+    if(PyDict_SetItem(res,PyString_FromString(tmp->name),(PyObject*)PyDict_FromMap(tmp->content))<0){
+      fprintf(stderr,"Unable to parse params...");
+      exit(1);
+    }
+    tmp=tmp->next;
+  }  
+  return (PyDictObject*) res;
+}
+
+PyDictObject* PyDict_FromMap(map* t){
+  PyObject* res=PyDict_New( );
+  map* tmp=t;
+  while(tmp!=NULL){
+    if(PyDict_SetItem(res,PyString_FromString(tmp->name),PyString_FromString(tmp->value))<0){
+      fprintf(stderr,"Unable to parse params...");
+      exit(1);
+    }
+    tmp=tmp->next;
+  }
+  return (PyDictObject*) res;
+}
+
+maps* mapsFromPyDict(PyDictObject* t){
+  maps* res=NULL;
+  maps* cursor=res;
+  PyObject* list=PyDict_Keys((PyObject*)t);
+  int nb=PyList_Size(list);
+  int i;
+  for(i=0;i<nb;i++){
+#ifdef DEBUG
+    fprintf(stderr,">> parsing maps %d\n",i);
+#endif
+    PyObject* key=PyList_GetItem(list,i);
+    PyObject* value=PyDict_GetItem((PyObject*)t,key);
+#ifdef DEBUG
+    fprintf(stderr,">> DEBUG VALUES : %s => %s\n",
+	    PyString_AsString(key),PyString_AsString(value));
+#endif
+    if(cursor!=NULL){
+      cursor=cursor->next;
+    }
+    cursor=(maps*)malloc(sizeof(maps*));
+    cursor->name=PyString_AsString(key);
+#ifdef DEBUG
+    dumpMap(mapFromPyDict((PyDictObject*)value));
+#endif
+    cursor->content=mapFromPyDict((PyDictObject*)value);
+    cursor->next=NULL;
+    if(res==NULL)
+      res=cursor;
+    else
+      addMapsToMaps(&res,cursor);
+#ifdef DEBUG
+    dumpMaps(res);
+    fprintf(stderr,">> parsed maps %d\n",i);
+#endif
+  }
+  return res;
+}
+
+map* mapFromPyDict(PyDictObject* t){
+  map* res=NULL;
+  PyObject* list=PyDict_Keys((PyObject*)t);
+  int nb=PyList_Size(list);
+  int i;
+  for(i=0;i<nb;i++){
+    PyObject* key=PyList_GetItem(list,i);
+    PyObject* value=PyDict_GetItem((PyObject*)t,key);
+#ifdef DEBUG
+    fprintf(stderr,">> DEBUG VALUES : %s => %s\n",
+	    PyString_AsString(key),PyString_AsString(value));
+#endif
+    if(res!=NULL)
+      addToMap(res,PyString_AsString(key),PyString_AsString(value));
+    else
+      res=createMap(PyString_AsString(key),PyString_AsString(value));
+  }
+  return res;
+}
Index: trunk/zoo-kernel/service_internal_python.h
===================================================================
--- trunk/zoo-kernel/service_internal_python.h	(revision 1)
+++ trunk/zoo-kernel/service_internal_python.h	(revision 1)
@@ -0,0 +1,47 @@
+/**
+ * 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.h"
+#include "service_internal.h"
+#include <Python.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 python_support(maps*,service*,int,char**,map *,map *);
+int zoo_python_support(maps**,map*,service*,maps**,maps**);
+
+#endif
Index: trunk/zoo-kernel/service_loader.c
===================================================================
--- trunk/zoo-kernel/service_loader.c	(revision 1)
+++ trunk/zoo-kernel/service_loader.c	(revision 1)
@@ -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;
+}
Index: trunk/zoo-kernel/ulinet.c
===================================================================
--- trunk/zoo-kernel/ulinet.c	(revision 1)
+++ trunk/zoo-kernel/ulinet.c	(revision 1)
@@ -0,0 +1,499 @@
+/**
+ *  ulinet.c
+ *
+ * Author : Gérald FENOY
+ *
+ * Copyright (c) 2008-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.
+ *
+ */
+
+#define _ULINET
+#include "ulinet.h"
+#include <assert.h>
+
+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 || strlen((char*)buffer)==0){
+    buffer=NULL;
+    return -1;
+  }
+  psInternet=(HINTERNET *)data;
+  if(psInternet->pabyData){
+    psInternet->pabyData=(char*)realloc(psInternet->pabyData,psInternet->nDataLen+realsize+1);
+    psInternet->nDataAlloc+=psInternet->nDataLen+realsize+1;
+  }
+  else{
+    psInternet->pabyData=(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;
+}
+
+size_t header_write_data(void *buffer, size_t size, size_t nmemb, void *data){
+  if(strncmp("Set-Cookie: ",buffer,12)==0){
+    int i;
+    char env[1024];
+    char path[1024];
+    char domain[1024];
+	char* tmp;
+    for(i=0;i<12;i++)
+#ifndef WIN32
+      buffer++;
+#else
+	;
+#endif
+    sscanf(buffer,"%s; path=%s; domain=%s",env,path,domain);
+    tmp=strcat(env,CCookie);
+#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,tmp);
+  }
+  return size * nmemb;//write_data_into(buffer,size,nmemb,data,HEADER);
+};
+
+
+void setProxy(CURL* handle,char* host,long port){
+}
+
+/**
+ * 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;
+  CFStringRef key_host;
+  CFStringRef key_port;
+  
+  bool proxy_enabled;
+  char *proxy_host;
+  long proxy_port;
+  
+  proxyDict = NULL;
+  proxies = NULL;
+
+  err = noErr;
+  proxyDict = SCDynamicStoreCopyProxies(NULL);
+
+  if(proto=="http"){
+      key_enabled=kSCPropNetProxiesHTTPEnable;
+      key_host=kSCPropNetProxiesHTTPProxy;
+      key_port=kSCPropNetProxiesHTTPPort;
+  }
+  else
+    if(proto=="https"){
+      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
+/**
+ * Linux (Gnome)
+ */
+bool setProxiesForProtcol(CURL* handle,const char *proto){
+#ifdef MSG_LAF_VERBOSE
+  fprintf( stderr, "setProxiesForProtocol (do nothing) ...\n" );
+#endif
+}
+#endif
+
+HINTERNET InternetOpen(char* lpszAgent,int dwAccessType,char* lpszProxyName,char* lpszProxyBypass,int dwFlags){
+  
+  HINTERNET ret;
+  struct MemoryStruct header;
+  ret.hasCacheFile=0;
+  ret.nDataAlloc = 0;
+
+  ret.handle=curl_easy_init();
+
+  curl_easy_setopt(ret.handle, CURLOPT_COOKIEFILE, "ALL");
+#ifndef TIGER
+  curl_easy_setopt(ret.handle, CURLOPT_COOKIELIST, "ALL");
+#endif
+  curl_easy_setopt(ret.handle, CURLOPT_USERAGENT, lpszAgent);
+  
+  curl_easy_setopt(ret.handle,CURLOPT_FOLLOWLOCATION,1);
+  curl_easy_setopt(ret.handle,CURLOPT_MAXREDIRS,3);
+  
+  header.memory=NULL;
+  header.size = 0;
+
+  curl_easy_setopt(ret.handle, CURLOPT_HEADERFUNCTION, header_write_data);
+  curl_easy_setopt(ret.handle, CURLOPT_WRITEHEADER, (void *)&header);
+
+#ifdef MSG_LAF_VERBOSE
+  curl_easy_setopt(ret.handle, CURLOPT_VERBOSE, 1);
+#endif
+
+  return ret;
+}
+
+static size_t 
+CurlWriteCB(void *buffer, size_t size, size_t nmemb, void *reqInfo){
+  HINTERNET *psInternet = (HINTERNET *) reqInfo;
+
+  memcpy( psInternet->pabyData + psInternet->nDataLen, buffer,  nmemb * size );
+  psInternet->nDataLen += nmemb * size;
+  psInternet->pabyData[psInternet->nDataLen] = 0;
+
+  return nmemb *size;
+}
+
+void InternetCloseHandle(HINTERNET handle){
+  if(handle.hasCacheFile>0){
+    fclose(handle.file);
+    unlink(handle.filename);
+  }
+  else{
+    handle.pabyData = NULL;
+    handle.nDataAlloc = handle.nDataLen = 0;
+  }
+  if(handle.handle)
+    curl_easy_cleanup(handle.handle);
+}
+
+HINTERNET InternetOpenUrl(HINTERNET hInternet,LPCTSTR lpszUrl,LPCTSTR lpszHeaders,size_t dwHeadersLength,size_t dwFlags,size_t dwContext){
+
+  char filename[255];
+  hInternet.nDataLen = 0;
+
+  hInternet.nDataAlloc = 0;
+  hInternet.pabyData= NULL;
+      
+  switch(dwFlags)
+    {
+    case INTERNET_FLAG_NO_CACHE_WRITE:    
+      hInternet.hasCacheFile=-1;
+      curl_easy_setopt(hInternet.handle, CURLOPT_WRITEFUNCTION, write_data_into);
+      curl_easy_setopt(hInternet.handle, CURLOPT_WRITEDATA, &hInternet);
+      break;
+    default:
+      sprintf(filename,"/tmp/HTCcache%d",(int)time(NULL));
+      printf("file=%s",filename);
+#ifdef MSG_LAF_VERBOSE
+      printf("file=%s",filename);
+#endif
+      hInternet.filename=filename;
+      hInternet.file=fopen(hInternet.filename,"w+");
+    
+      hInternet.hasCacheFile=1;
+      curl_easy_setopt(hInternet.handle, CURLOPT_WRITEFUNCTION, NULL);
+      curl_easy_setopt(hInternet.handle, CURLOPT_WRITEDATA, hInternet.file);
+      hInternet.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\n",lpszHeaders);
+#endif
+    //curl_easy_setopt(hInternet.handle,CURLOPT_COOKIE,lpszHeaders);
+    curl_easy_setopt(hInternet.handle,CURLOPT_POST,1);
+#ifdef ULINET_DEBUG
+    fprintf(stderr,"** (%s) %d **\n",lpszHeaders,dwHeadersLength);
+#endif
+    curl_easy_setopt(hInternet.handle,CURLOPT_POSTFIELDS,lpszHeaders);
+    //curl_easy_setopt(hInternet.handle,CURLOPT_POSTFIELDSIZE,dwHeadersLength+1);
+    if(hInternet.header!=NULL)
+      curl_easy_setopt(hInternet.handle,CURLOPT_HTTPHEADER,hInternet.header);
+  }
+
+  curl_easy_setopt(hInternet.handle,CURLOPT_URL,lpszUrl);
+  curl_easy_perform(hInternet.handle);
+
+  return hInternet;
+};
+
+int freeCookieList(HINTERNET hInternet){
+  memset(&CCookie[0],0,1024);
+#ifndef TIGER
+  curl_easy_setopt(hInternet.handle, CURLOPT_COOKIELIST, "ALL");
+#endif
+  return 1;
+}
+
+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[0]=0;
+
+  if( *lpdwNumberOfBytesRead < dwDataSize )
+      return 0;
+  else
+      return 1; // TRUE
+}
+
+bool InternetGetCookie(LPCTSTR lpszUrl,LPCTSTR lpszCookieName,LPTSTR lpszCookieData,LPDWORD lpdwSize){
+
+  bool ret=1;  
+  int count=0;
+  int hasCookie=-1;
+  char TMP[1024];
+  int j;
+  int tmpC=0;
+  lpszUrl=NULL;
+
+  for(j=0;j<strlen(CCookie);j++){
+    if(lpszCookieName[count]==CCookie[j]){
+      hasCookie=1;
+      count++;
+      if(count==strlen(lpszCookieName))
+	break;
+      continue;
+    }
+  }
+
+  if(hasCookie>0){
+    if(CCookie[count]=='='){
+      int i=0;
+      count++;
+      for(i=count;i<strlen(CCookie);i++){
+	if(CCookie[i]!=';'){
+	  TMP[tmpC]=CCookie[i];
+	  tmpC++;
+	}
+	else{
+	  break;
+	}
+      }
+    }
+  }
+  else
+    return -1;
+
+  TMP[tmpC]=0;
+  strncpy(lpszCookieData,TMP,strlen(TMP)+1);
+  lpdwSize=(size_t*) strlen(lpszCookieData);
+
+#ifdef MSG_LAF_VERBOSE
+  printf("Cookie returned : (%s)",(char*)lpszCookieData);
+#endif
+
+  return ret;
+
+}
+
+#ifdef USE_JS
+#include "jsapi.h"
+
+char* JSValToChar(JSContext* context, jsval* arg) {
+  if(!JSVAL_IS_STRING(*arg)) {
+    return NULL;
+  }
+  char *c, *tmp;
+  JSString *jsmsg;
+  size_t len;
+  jsmsg = JS_ValueToString(context,*arg);
+  len = JS_GetStringLength(jsmsg);
+  tmp = JS_GetStringBytes(jsmsg);
+  c = (char*)malloc((len+1)*sizeof(char));
+  c[len] = '\0';
+  int i;
+#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;
+}
+
+HINTERNET setHeader(HINTERNET handle,JSContext *cx,JSObject *header){
+  jsuint length=0;
+#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
+    jsint i=0;
+    handle.header=NULL;
+    for(i=0;i<length;i++){
+      jsval tmp;
+      JS_GetElement(cx,header,i,&tmp);
+      char *tmp1=JSValToChar(cx,&tmp);
+#ifdef ULINET_DEBUG
+      fprintf(stderr,"Element of array n° %d, value : %s\n",i,tmp1);
+#endif
+      handle.header=curl_slist_append(handle.header, tmp1);
+      free(tmp1);
+    }
+  }
+  else{
+    fprintf(stderr,"not an array !!!!!!!\n");
+  }
+  return handle;
+}
+
+JSBool
+JSRequest(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
+{
+  HINTERNET hInternet;
+  char *url;
+  char *method;
+  JS_MaybeGC(cx);
+  hInternet=InternetOpen((LPCTSTR)"ZooWPSClient\0",
+			 INTERNET_OPEN_TYPE_PRECONFIG,
+			 NULL,NULL, 0);
+  if(!CHECK_INET_HANDLE(hInternet))
+    return JS_FALSE;
+  int i=0;
+  if(argc>=2){
+    method=JSValToChar(cx,&argv[0]);
+    url=JSValToChar(cx,&argv[1]);
+  }
+  else{
+    method=strdup("GET");
+    url=JSValToChar(cx,argv);
+  }
+  HINTERNET res;
+  if(argc==4){
+    char *body;
+    body=JSValToChar(cx,&argv[2]);
+    JSObject *header=JSVAL_TO_OBJECT(argv[3]);
+    HINTERNET res1;
+#ifdef ULINET_DEBUG
+    fprintf(stderr,"URL (%s) \nBODY (%s)\n",url,body);
+#endif
+    if(JS_IsArrayObject(cx,header))
+      res1=setHeader(hInternet,cx,header);
+#ifdef ULINET_DEBUG
+    fprintf(stderr,"BODY (%s)\n",body);
+#endif
+    res=InternetOpenUrl(res1,url,body,strlen(body),
+			INTERNET_FLAG_NO_CACHE_WRITE,0);    
+    free(body);
+  }else{
+    if(argc==3){
+      char *body=JSValToChar(cx,&argv[2]);
+      res=InternetOpenUrl(hInternet,url,body,strlen(body),
+			  INTERNET_FLAG_NO_CACHE_WRITE,0);
+      free(body);
+    }
+    res=InternetOpenUrl(hInternet,url,NULL,0,
+			INTERNET_FLAG_NO_CACHE_WRITE,0);
+  }
+  char* tmpValue=(char*)malloc((res.nDataLen+1)*sizeof(char));
+  size_t dwRead;
+  InternetReadFile(res,(LPVOID)tmpValue,res.nDataLen,&dwRead);
+#ifdef ULINET_DEBUG
+  fprintf(stderr,"content downloaded (%d) (%s) \n",dwRead,tmpValue);
+#endif
+  *rval=STRING_TO_JSVAL(JS_NewString(cx,tmpValue,strlen(tmpValue)));
+  free(url);
+  if(argc>=2)
+    free(method);
+  if(argc==4 && res.header!=NULL){
+    curl_slist_free_all(res.header);
+  }
+  InternetCloseHandle(hInternet);
+  JS_MaybeGC(cx);
+  return JS_TRUE;
+}
+#endif
Index: trunk/zoo-kernel/ulinet.h
===================================================================
--- trunk/zoo-kernel/ulinet.h	(revision 1)
+++ trunk/zoo-kernel/ulinet.h	(revision 1)
@@ -0,0 +1,148 @@
+/**
+ * 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 <stdlib.h>
+#include <fcntl.h>
+#include <curl/curl.h>
+#ifndef WIN32
+#include <unistd.h>
+#endif
+#include <string.h>
+#include "time.h"
+#ifdef USE_JS
+#define XP_UNIX 0
+#include "jsapi.h"
+#endif
+
+
+#ifdef _ULINET
+static char CCookie[1024];
+#else
+extern char HEADER[3072];
+extern char CCookie[1024];
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+  //static pthread_mutex_t hMutexConnect = PTHREAD_MUTEX_INITIALIZER;
+
+struct MemoryStruct {
+  char *memory;
+  size_t size;
+};
+
+typedef struct {
+  CURL *handle;
+  struct curl_slist *header;
+  char* filename;
+  FILE* file;
+  size_t size;
+  int hasCacheFile;
+  int nDataLen;
+  int nDataAlloc;
+  unsigned char *pabyData;
+} HINTERNET;
+
+size_t write_data_into(void *buffer, size_t size, size_t nmemb, void *data);
+
+size_t content_write_data(void *buffer, size_t size, size_t nmemb, void *data);
+
+size_t header_write_data(void *buffer, size_t size, size_t nmemb, void *data);
+
+
+void setProxy(CURL* handle,char* host,long port);
+
+
+#if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__))
+
+#include <CoreServices/CoreServices.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+char* CFStringToCString(CFStringRef dest,char * buffer);
+OSStatus setProxiesForProtcol(CURL* handle,const char *proto);
+
+#else
+
+//#include <gconf/gconf-client.h>
+int setProxiesForProtcol(CURL* handle,const char *proto);
+
+#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* lpszAgent,int dwAccessType,char* lpszProxyName,char* lpszProxyBypass,int dwFlags);
+
+void InternetCloseHandle(HINTERNET handle);
+
+#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 hInternet,LPCTSTR lpszUrl,LPCTSTR lpszHeaders,size_t dwHeadersLength,size_t dwFlags,size_t dwContext);
+
+int freeCookieList(HINTERNET hInternet);
+
+int InternetReadFile(HINTERNET hInternet,LPVOID lpBuffer,int dwNumberOfBytesToRead,size_t *lpdwNumberOfBytesRead);
+
+bool InternetGetCookie(LPCTSTR lpszUrl,LPCTSTR lpszCookieName,LPTSTR lpszCookieData,LPDWORD lpdwSize);
+
+#ifdef USE_JS
+JSBool JSRequest(JSContext*, JSObject*, uintN, jsval*, jsval*);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
Index: trunk/zoo-kernel/zoo_loader.c
===================================================================
--- trunk/zoo-kernel/zoo_loader.c	(revision 1)
+++ trunk/zoo-kernel/zoo_loader.c	(revision 1)
@@ -0,0 +1,317 @@
+/**
+ * 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.
+ */
+
+/**
+ * Specific includes
+ */
+#include "fcgio.h"
+#include "fcgi_config.h" 
+#include "fcgi_stdio.h"
+#include <sys/types.h>
+#include <unistd.h>
+extern "C" {
+#include "cgic.h"
+}
+
+#include "service_internal.h"
+extern "C" {
+#include <libxml/tree.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+}
+
+#ifndef STRTOK_R
+char *
+strtok_r(char *s1, const char *s2, char **lasts)
+{
+  char *ret;
+
+  if (s1 == NULL)
+    s1 = *lasts;
+  while(*s1 && strchr(s2, *s1))
+    ++s1;
+  if(*s1 == '\0')
+    return NULL;
+  ret = s1;
+  while(*s1 && !strchr(s2, *s1))
+    ++s1;
+  if(*s1)
+    *s1++ = '\0';
+  *lasts = s1;
+  return ret;
+}
+
+#endif
+
+xmlNodeSet* extractFromDoc(xmlDocPtr,char*);
+int runRequest(map*);
+
+using namespace std;
+
+char* strtoupper(char* str)
+{
+  int leng=strlen(str);
+  for(int i=0; i<leng; i++)
+    if (97<=str[i]&&str[i]<=122)//a-z
+      str[i]-=32;
+  return str;
+}
+
+char* strtolower(char* str)
+{
+  int leng=strlen(str);
+  for(int i=0; i<leng; i++)
+    if (65<=str[i]&&str[i]<=90)//A-Z
+      str[i]+=32;
+  return str;
+}
+
+char* remplace(char* delim,char* rep,char* source){
+  if(strcmp(source,"")==0){
+#ifdef DEBUG
+    //char *tmp="RETURN NULL !\n";
+    //printf((void*)tmp);
+#endif
+    return "NULL";
+  }
+
+  char *_token; 
+  char *origin=strdup(source);
+  char result[1024]="";
+  _token = strtok(source, delim);
+#ifdef DEBUG
+  fprintf(stderr,"\nREPLACE TOKEN (%s == %s => %d)\n ",_token,origin,strcmp(_token,origin));
+#endif
+  if(strcmp(_token,origin)!=0)
+    while(_token!=NULL){
+      sprintf(result,"%s%s%s",result,_token,rep);
+      _token = strtok (NULL, delim);
+      if(_token==NULL)
+	result[strlen(result)-strlen(rep)]=0;
+#ifdef DEBUG
+      fprintf(stderr,"\n\nRESULT(%s)\n\n",result);
+#endif
+    }
+  else
+    return origin;
+  
+  return strdup(result);
+}
+
+
+char *colors[] = {
+  "red", "green", "blue"
+};
+
+#define colorsTotal 3
+#define TRUE -1
+#define FALSE -1
+static bool started=FALSE;
+static bool isStarted=FALSE;
+
+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);
+#endif
+  
+  /**
+   * Read the main configuration file
+   */
+  if(!isStarted){
+    maps* m;
+    m=(maps*)malloc(sizeof(maps*));  
+    conf_read("main.cfg",m);
+#ifdef REAL_FCGI
+#ifdef DEBUG
+    printf("ok passed");
+#endif    
+#endif    
+    isStarted=TRUE;
+  }
+
+#ifdef DEBUG
+  char textb[23];
+  sprintf(textb,"\n%s\n%s\n",cgiRemoteAddr,cgiRequestMethod);
+  fprintf(stderr,"****%s\n%s\n***",textb,cgiQueryString);
+#endif
+
+  map* tmp=NULL;
+    
+  if(strncmp(cgiContentType,"text/xml",8)==0){
+    char *buffer=new char[cgiContentLength];
+    if(fread(buffer,1,cgiContentLength,cgiIn)){
+      buffer[cgiContentLength]=0;
+      tmp=createMap("request",buffer);
+    }else{
+      /* Here we have to return an error message ... */
+      return 1; 
+    }
+  }
+  else{
+    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(tmp!=NULL)
+	addToMap(tmp,*arrayStep,value);
+      else
+	tmp=createMap(*arrayStep,value);
+      arrayStep++;
+    }
+    cgiStringArrayFree(array);
+  }
+
+  /**
+   * In case that the POST method was used, then check if params came in XML
+   * format (attribute request should be the once).
+   */
+  if(strcmp(cgiRequestMethod,mtoupper("post"))==0 && count(tmp)==1){
+    /**
+     * First include the MetaPath and the ServiceProvider default parameters
+     * (which should be always available in GET params so in cgiQueryString)
+     */
+    char *saveptr1, *saveptr2;
+    char *str1, *str2, *token, *subtoken;
+    str1=cgiQueryString;
+    token=strtok_r(str1,"&",&saveptr1);
+    while(token!=NULL){
+#ifdef DEBUG
+      fprintf(stderr,"%s",token);
+#endif
+      str2=token;
+      subtoken=strtok_r(str2,"=",&saveptr2);
+#ifdef DEBUG
+      fprintf(stderr,"%s\n",subtoken);
+#endif
+      char* tmp_name;
+      if(subtoken!=NULL){
+	tmp_name=subtoken;
+#ifdef DEBUG
+	fprintf(stderr,"%s",subtoken);
+#endif
+	subtoken=strtok_r(NULL,"=",&saveptr2);
+	if(subtoken!=NULL)
+	  addToMap(tmp,tmp_name,subtoken);
+	else
+	  addToMap(tmp,tmp_name,"");
+      }
+      token=strtok_r(NULL,"&",&saveptr1);
+    }
+    /**
+     * Store the original XML request in xrequest map
+     */
+    map* t1=getMap(tmp,"request");
+    if(t1!=NULL){
+      addToMap(tmp,"xrequest",t1->value);
+      xmlInitParser();
+      xmlDocPtr doc = xmlParseMemory(t1->value,cgiContentLength);      
+      xmlNodePtr cur = xmlDocGetRootElement(doc);
+      char *tval;
+      tval=NULL;
+      tval = (char*) xmlGetProp(cur,BAD_CAST "service");
+      if(tval!=NULL)
+	addToMap(tmp,"service",tval);
+      tval=NULL;
+      tval = (char*) xmlGetProp(cur,BAD_CAST "language");
+      if(tval!=NULL)
+	addToMap(tmp,"language",tval);
+      
+      char* requests[3];
+      requests[0]="GetCapabilities";
+      requests[1]="DescribeProcess";
+      requests[2]="Execute";
+      for(int j=0;j<3;j++){
+	char tt[35];
+	sprintf(tt,"/*[local-name()='%s']",requests[j]);
+	xmlNodeSet* req=extractFromDoc(doc,tt);
+#ifdef DEBUG
+	fprintf(stderr,"%i",req->nodeNr);
+#endif
+	if(req->nodeNr==1){
+	  t1->value=requests[j];
+	  j=2;
+	}
+	xmlFree(req);
+      }
+      if(strcmp(mtoupper(t1->value),mtoupper("GetCapabilities"))==0){	
+	xmlNodeSet* vers=extractFromDoc(doc,"/*/*/*[local-name()='Version']");
+	xmlChar* content=xmlNodeListGetString(doc, vers->nodeTab[0]->xmlChildrenNode,1);
+	addToMap(tmp,"version",(char*)content);
+	xmlFree(vers);
+	xmlFree(content);
+      }else{
+	tval=NULL;
+	tval = (char*) xmlGetProp(cur,BAD_CAST "version");
+	if(tval!=NULL)
+	  addToMap(tmp,"version",tval);
+	xmlFree(tval);
+	tval = (char*) xmlGetProp(cur,BAD_CAST "language");
+	if(tval!=NULL)
+	  addToMap(tmp,"language",tval);
+	xmlNodeSet* id=extractFromDoc(doc,"/*/*[local-name()='Identifier']");
+	char* identifiers=NULL;
+	identifiers=(char*)malloc(cgiContentLength);
+	identifiers[0]=0;
+	for(int k=0;k<id->nodeNr;k++){
+	  xmlChar* content=xmlNodeListGetString(doc, id->nodeTab[k]->xmlChildrenNode,1);
+	  if(strlen(identifiers)>0){
+	    sprintf(identifiers,"%s,%s",identifiers,content);
+	    identifiers[strlen(identifiers)]=0;
+	  }
+	  else{
+	    sprintf(identifiers,"%s",content);
+	    identifiers[strlen(identifiers)]=0;
+	  }
+	  xmlFree(content);
+	}
+	xmlFree(id);
+	addToMap(tmp,"Identifier",identifiers);
+      }
+      //xmlCleanupParser();
+      xmlFree(tval);
+    }
+  }
+  //dumpMap(tmp);
+  runRequest(tmp);
+  //dumpMap(tmp);
+
+  return 0;
+
+}
Index: trunk/zoo-kernel/zoo_service_loader.c
===================================================================
--- trunk/zoo-kernel/zoo_service_loader.c	(revision 1)
+++ trunk/zoo-kernel/zoo_service_loader.c	(revision 1)
@@ -0,0 +1,1713 @@
+/**
+ * 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.
+ */
+
+#define length(x) (sizeof(x) / sizeof(x[0]))
+
+extern "C" int yylex();
+extern "C" int crlex();
+extern "C" {
+#include <libxml/tree.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+}
+
+#include "cgic.h"
+#include "ulinet.h"
+
+#include <string.h>
+
+#include "service.h"
+#include "service_internal.h"
+#include "service_internal_python.h"
+
+#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
+
+
+#include <dirent.h>
+#include <signal.h>
+#include <unistd.h>
+#ifndef WIN32
+#include <dlfcn.h>
+#include <libgen.h>
+#else
+#include <windows.h>
+#include <direct.h>
+#endif
+#include <fcntl.h>
+#include <time.h>
+#include <stdarg.h>
+
+xmlNodeSet* extractFromDoc(xmlDocPtr doc,char* search){
+  xmlXPathContextPtr xpathCtx;
+  xmlXPathObjectPtr xpathObj;
+  xpathCtx = xmlXPathNewContext(doc);
+  xpathObj = xmlXPathEvalExpression(BAD_CAST search,xpathCtx);
+  xmlXPathFreeContext(xpathCtx); 
+  return xpathObj->nodesetval;
+}
+
+void sigint_handler(int sig){
+  fprintf(stderr,"Not this time!\n");
+}
+
+int runRequest(map* request_inputs)
+{
+
+  map* r_inputs=NULL,*tmps=NULL;
+  maps* m=NULL;
+  int argc=count(request_inputs);
+
+  char* REQUEST=NULL;
+  /**
+   * Parsing service specfic configuration file
+   */
+  m=(maps*)malloc(MAPS_SIZE);
+  char ntmp[1024];
+#ifndef WIN32
+  getcwd(ntmp,1024);
+#else
+  _getcwd(ntmp,1024);
+#endif
+  char conf_file[1024];
+  sprintf(conf_file,"%s/main.cfg",ntmp);  
+  conf_read(conf_file,m);
+  
+  /**
+   * Check for minimum inputs
+   */
+  r_inputs=getMap(request_inputs,"Request");
+  if(r_inputs==NULLMAP){ 
+  tmps=createMap("text","Parameter <request> was not specified");
+    addToMap(tmps,"code","MissingParameterValue");
+    printExceptionReportResponse(m,tmps);
+    return 1;
+  }
+  else
+    REQUEST=strdup(r_inputs->value);
+  r_inputs=NULL;
+  r_inputs=getMap(request_inputs,"Service");
+  if(r_inputs==NULLMAP){ 
+    tmps=createMap("text","Parameter <service> was not specified");
+    addToMap(tmps,"code","MissingParameterValue");
+    printExceptionReportResponse(m,tmps);
+    return 1;
+  }
+  if(strcmp(mtoupper(REQUEST),"GETCAPABILITIES")!=0){
+    r_inputs=getMap(request_inputs,"Version");
+    if(r_inputs==NULL){ 
+      tmps=createMap("text","Parameter <version> was not specified");
+      addToMap(tmps,"code","MissingParameterValue");
+      printExceptionReportResponse(m,tmps);
+      return 1;
+    }
+  }
+
+  /**
+   * Need to print std exception message here
+   */
+  char SP[1024];
+  if ((argc < 5 && strcmp(mtoupper(REQUEST),"GETCAPABILITIES")!=0) || (argc < 4 && strcmp(mtoupper(REQUEST),"GETCAPABILITIES")==0)){
+    r_inputs=getMap(request_inputs,"ServiceProvider");
+    if(r_inputs==NULLMAP){
+      tmps=createMap("text","Parameter <serviceprovider> was not specified");
+      addToMap(tmps,"code","MissingParameterValue");
+      printExceptionReportResponse(m,tmps);    
+      return 1;
+    }
+    else
+      sprintf(SP,"%s",r_inputs->value);
+    r_inputs=getMap(request_inputs,"MetaPath");
+    if(r_inputs==NULLMAP){
+      tmps=createMap("text","Parameter <metapath> was not specified");
+      addToMap(tmps,"code","MissingParameterValue");
+      printExceptionReportResponse(m,tmps);    
+      return 1;
+    }
+    tmps=createMap("text","Parameter <unknown> was not specified");
+    addToMap(tmps,"code","MissingParameterValue");
+    printExceptionReportResponse(m,tmps);    
+    return 1;
+  }
+
+  map* outputs=NULL;
+  maps* request_output_real_format=NULL;
+  map* tmpm=getMapFromMaps(m,"main","serverAddress");
+  if(tmpm!=NULL)
+    SERVICE_URL=strdup(tmpm->value);
+  else
+    SERVICE_URL=DEFAULT_SERVICE_URL;
+
+  service* s[100];
+  service* s1;
+  int scount=0;
+
+#ifdef DEBUG
+  dumpMap(r_inputs);
+#endif
+  char conf_dir[1024];
+  int t;
+  char tmps1[1024];
+
+  if(strcmp(mtoupper(REQUEST),mtoupper("GetCapabilities"))==0){
+    int i=0;
+    struct dirent *dp;
+    r_inputs=NULL;
+    r_inputs=getMap(request_inputs,"metapath");
+#ifdef DEBUG
+    dumpMap(r_inputs);
+#endif
+    sprintf(conf_dir,"%s/%s",ntmp,r_inputs->value);
+	DIR *dirp = opendir(conf_dir);
+    if(dirp==NULL){
+      tmps=createMap("text","The specified path doesn't exist.");
+      addToMap(tmps,"code","InvalidParameterValue");
+      printExceptionReportResponse(m,tmps);    
+      return -1;
+    }
+    xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0");
+    doc->encoding = xmlCharStrdup ("UTF-8");
+    r_inputs=NULL;
+    r_inputs=getMap(request_inputs,"ServiceProvider");
+    xmlNodePtr n = printGetCapabilitiesHeader(doc,r_inputs->value,m);
+    /**
+     * Strange, here we need to close stdout to ensure that no uneeded 
+     * char will be printed (parser issue ?)
+     */
+    int saved_stdout = dup(fileno(stdout));
+    dup2(fileno(stderr),fileno(stdout));
+    while ((dp = readdir(dirp)) != NULL)
+      if(strstr(dp->d_name,".zcfg")!=0){
+	sprintf(tmps1,"%s/%s",conf_dir,dp->d_name);
+	char *tmps=tmps1;
+	s1=(service*)malloc(sizeof(service*));
+	s[0]=(service*)malloc(sizeof(service*));
+#ifdef DEBUG
+	fprintf(stderr,"#################\n%s\n#################\n",tmps1);
+#endif
+	t=getServiceFromFile(tmps1,&s1);
+#ifdef DEBUG
+	dumpService(s1);
+	fflush(stdout);
+	fflush(stderr);
+#endif
+	s[0]=s1;
+	printGetCapabilitiesForProcess(m,n,s1);
+	//freeService(&s1);
+	//s1=NULL;
+	scount++;
+      }
+    (void)closedir(dirp);
+    fflush(stdout);
+    dup2(saved_stdout,fileno(stdout));
+    
+    printDocument(doc);
+    fflush(stdout);
+    xmlFree(n);
+    return 0;
+  }
+  else{
+    r_inputs=getMap(request_inputs,"Identifier");
+    if(r_inputs==NULL 
+       || strlen(r_inputs->name)==0 || strlen(r_inputs->value)==0){ 
+      if(r_inputs!=NULL && strlen(r_inputs->value)==0)
+	tmps=createMap("text","Mandatory value for <identifier> was not specified");
+      else
+	tmps=createMap("text","Mandatory <identifier> was not specified");
+      addToMap(tmps,"code","MissingParameterValue");
+      printExceptionReportResponse(m,tmps);
+      return 1;
+    }
+
+    r_inputs=getMap(request_inputs,"metapath");
+    sprintf(conf_dir,"%s/%s",ntmp,r_inputs->value);
+    struct dirent *dp;
+    DIR *dirp = opendir(conf_dir);
+    if(dirp==NULL){
+      tmps=createMap("text","The specified metapath path doesn't exist.");
+      addToMap(tmps,"code","InvalidParameterValue");
+      printExceptionReportResponse(m,tmps);    
+      return -1;
+    }
+    if(strcmp(mtoupper(REQUEST),"DESCRIBEPROCESS")==0){
+      /**
+       * Loop over Identifier list
+       */
+      xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0");
+      doc->encoding = xmlCharStrdup ("UTF-8");
+      r_inputs=NULL;
+      r_inputs=getMap(request_inputs,"ServiceProvider");
+      xmlNodePtr n;
+      if(r_inputs!=NULL)
+	n = printDescribeProcessHeader(doc,r_inputs->value,m);
+
+      r_inputs=getMap(request_inputs,"Identifier");
+      char *tmps=strtok(r_inputs->value,",");
+      
+      char buff[256];
+      char buff1[1024];
+      int i=0;
+      int j=0;
+      int end=-1;
+      int saved_stdout = dup(fileno(stdout));
+      dup2(fileno(stderr),fileno(stdout));
+      while(tmps){
+	memset(buff,0,256);
+	sprintf(buff,"%s.zcfg",tmps);
+	memset(buff1,0,1024);
+#ifdef DEBUG
+	fprintf(stderr,"\n#######%s\n########\n",buff1);
+#endif
+	while ((dp = readdir(dirp)) != NULL)
+	  if(strcmp(dp->d_name,buff)==0){
+	    memset(buff1,0,1024);
+	    sprintf(buff1,"%s/%s",conf_dir,dp->d_name);
+	    s1=(service*)malloc(sizeof(service*));
+	    s[scount]=(service*)malloc(sizeof(service*));
+#ifdef DEBUG
+	    fprintf(stderr,"#################\n%s\n#################\n",tmps1);
+#endif
+	    t=getServiceFromFile(buff1,&s1);
+	    /*dumpService(s1);
+	      fflush(stdout);
+	      fflush(stderr);*/
+	    s[0]=s1;
+	    printDescribeProcessForProcess(m,n,s,1);
+	    scount++;
+	  }
+	rewinddir(dirp);
+	tmps=strtok(NULL,",");
+      }
+      (void)closedir(dirp);
+      fflush(stdout);
+      dup2(saved_stdout,fileno(stdout));
+
+      printDocument(doc);
+      fflush(stdout);
+      //xmlFree(n);
+#ifndef LINUX_FREE_ISSUE
+      free(s1);
+#endif
+      return 0;
+    }
+    else
+      if(strcmp(mtoupper(REQUEST),"EXECUTE")!=0){
+	tmps=createMap("text","Unenderstood <request> value. Please check that it was set to GetCapabilities, DescribeProcess or Execute.");
+	addToMap(tmps,"code","InvalidParameterValue");
+	printExceptionReportResponse(m,tmps);
+#ifdef DEBUG
+	fprintf(stderr,"No request found %s",REQUEST);
+#endif	
+	free(s);
+	return 0;
+      }
+  }
+  
+  s1=NULL;
+  s1=(service*)malloc(sizeof(service*));
+  s[0]=(service*)malloc(sizeof(service*));
+  r_inputs=getMap(request_inputs,"MetaPath");
+  sprintf(tmps1,"%s/%s",ntmp,r_inputs->value);
+  r_inputs=getMap(request_inputs,"Identifier");
+
+  sprintf(tmps1,"%s/%s.zcfg",strdup(tmps1),r_inputs->value);
+
+#ifdef DEBUG
+  fprintf(stderr,"Trying to load %s\n", tmps1);
+#endif
+  int saved_stdout = dup(fileno(stdout));
+  dup2(fileno(stderr),fileno(stdout));
+  t=getServiceFromFile(tmps1,&s1);
+  fflush(stdout);
+  dup2(saved_stdout,fileno(stdout));
+  if(t==22){
+    tmps=createMap("text","The value for <indetifier> seems to be wrong. Please, ensure that the process exsits using the GetCapabilities request.");
+    addToMap(tmps,"code","InvalidParameterValue");
+    printExceptionReportResponse(m,tmps);
+    exit(0);
+  }
+  s[0]=s1;
+
+#ifdef DEBUG
+  dumpService(s1);
+#endif
+  map* inputs=NULL;
+  elements* c_inputs=s1->inputs;
+  int j;
+  
+  /**
+   * Create the input 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;
+  map* postRequest=NULL;
+  postRequest=getMap(request_inputs,"xrequest");
+  if(postRequest==NULLMAP){
+    /**
+     * Parsing outputs provided as KVP
+     */
+    r_inputs=NULL;
+#ifdef DEBUG
+    fprintf(stderr,"OUTPUT Parsing ... \n");
+#endif
+    r_inputs=getMap(request_inputs,"ResponseDocument");	
+    if(r_inputs==NULLMAP)
+      r_inputs=getMap(request_inputs,"RawDataOutput");
+#ifdef DEBUG
+    fprintf(stderr,"OUTPUT Parsing ... \n");
+#endif
+    if(r_inputs!=NULLMAP){
+#ifdef DEBUG
+      fprintf(stderr,"OUTPUT Parsing start now ... \n");
+#endif
+      char current_output_as_string[10240];
+      char cursor_output[10240];
+      sprintf(cursor_output,"%s",strdup(r_inputs->value));
+      j=0;
+      map* request_kvp_outputs=NULL;
+	
+      /**
+       * Put each Output into the outputs_as_text array
+       */
+      char * pToken;
+      maps* tmp_output=NULL;
+#ifdef DEBUG
+      fprintf(stderr,"OUTPUT [%s]\n",cursor_output);
+#endif
+      pToken=strtok(cursor_output,";");
+      char** outputs_as_text=(char**)malloc(128*sizeof(char*));
+      i=0;
+      while(pToken!=NULL){
+#ifdef DEBUG
+	fprintf(stderr,"***%s***\n",pToken);
+	fflush(stderr);
+	fprintf(stderr,"***%s***\n",pToken);
+#endif
+	outputs_as_text[i]=(char*)malloc(strlen(pToken)*sizeof(char));
+	sprintf(outputs_as_text[i],"%s",pToken);
+	pToken = strtok(NULL,";");
+	i++;
+      }
+      for(j=0;j<i;j++){
+	char *tmp=strdup(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);
+	      tmp_output->name=strdup(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;
+#ifdef DEBUG
+	    fprintf(stderr,"OUTPUT DEF [%s]=[%s]\n",tmpn,tmpv+1);
+#endif
+	    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++;
+#ifdef DEBUG
+	  fprintf(stderr,"***%s***\n",tmpc);
+#endif
+	  tmpc=strtok(NULL,"@");
+	}
+	if(request_output_real_format==NULL)
+	  request_output_real_format=tmp_output;
+	else
+	  addMapsToMaps(&request_output_real_format,tmp_output);
+#ifdef DEBUG
+	dumpMaps(tmp_output);
+	fflush(stderr);
+#endif
+	tmp_output=tmp_output->next;
+      }
+      //dumpMaps(request_output_real_format);
+    }
+
+
+    /**
+     * Parsing inputs provided as KVP
+     */
+    r_inputs=getMap(request_inputs,"DataInputs");
+#ifdef DEBUG
+    fprintf(stderr,"DATA INPUTS [%s]\n",r_inputs->value);
+#endif
+    char current_input_as_string[40960];
+    char cursor_input[40960];
+    sprintf(cursor_input,"%s",strdup(r_inputs->value));
+    j=0;
+    map* request_kvp_inputs=NULL;
+  
+    /**
+     * Put each DataInputs into the inputs_as_text array
+     */
+    char * pToken;
+    pToken=strtok(cursor_input,";");
+    char** inputs_as_text=(char**)malloc(100*sizeof(char*));
+    i=0;
+    while(pToken!=NULL){
+#ifdef DEBUG
+      fprintf(stderr,"***%s***\n",pToken);
+#endif
+      fflush(stderr);
+#ifdef DEBUG
+      fprintf(stderr,"***%s***\n",pToken);
+#endif
+      inputs_as_text[i]=(char*)malloc(strlen(pToken)*sizeof(char));
+      sprintf(inputs_as_text[i],"%s",pToken);
+      pToken = strtok(NULL,";");
+      i++;
+    }
+
+    for(j=0;j<i;j++){
+      char *tmp=strdup(inputs_as_text[j]);
+      char *tmpc;
+      tmpc=strtok(tmp,"@");
+      while(tmpc!=NULL){
+#ifdef DEBUG
+	fprintf(stderr,"***\n***%s***\n",tmpc);
+#endif
+	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;
+	int cnt=0;
+#ifdef DEBUG
+	fprintf(stderr,"***\n*** %s = %s ***\n",tmpn,tmpv+1);
+#endif
+	if(tmpmaps==NULL){
+	  tmpmaps=(maps*)malloc(MAPS_SIZE);
+	  tmpmaps->name=strdup(tmpn);
+	  tmpmaps->content=createMap("value",tmpv+1);
+	  tmpmaps->next=NULL;
+	}
+	tmpc=strtok(NULL,"@");
+	while(tmpc!=NULL){
+#ifdef DEBUG
+	  fprintf(stderr,"*** KVP NON URL-ENCODED \n***%s***\n",tmpc);
+#endif
+	  char *tmpv1=strstr(tmpc,"=");
+#ifdef DEBUG
+	  fprintf(stderr,"*** VALUE NON URL-ENCODED \n***%s***\n",tmpv1+1);
+#endif
+	  char tmpn1[1024];
+	  memset(tmpn1,0,1024);
+	  strncpy(tmpn1,tmpc,strlen(tmpc)-strlen(tmpv1));
+	  tmpn1[strlen(tmpc)-strlen(tmpv1)]=0;
+#ifdef DEBUG
+	  fprintf(stderr,"*** NAME NON URL-ENCODED \n***%s***\n",tmpn1);
+	  fprintf(stderr,"*** VALUE NON URL-ENCODED \n***%s***\n",tmpv1+1);
+#endif
+	  if(strcmp(tmpn1,"xlink:href")!=0)
+	    addToMap(tmpmaps->content,tmpn1,tmpv1+1);
+	  else{
+#ifdef DEBUG
+	    fprintf(stderr,"REQUIRE TO DOWNLOAD A FILE FROM A SERVER : url(%s)\n",tmpv1+1);
+#endif
+#ifndef WIN32
+		if(CHECK_INET_HANDLE(hInternet))
+#endif
+		{
+	      res=InternetOpenUrl(hInternet,tmpv1+1,NULL,0,
+					    INTERNET_FLAG_NO_CACHE_WRITE,0);
+#ifdef DEBUG
+	      fprintf(stderr,"(%s) content-length : %d,,res.nDataAlloc %d \n",
+		      tmpv1+1,res.nDataAlloc,res.nDataLen);
+#endif
+	      char* tmpContent=(char*)malloc((res.nDataLen+1)*sizeof(char));
+	      size_t dwRead;
+	      InternetReadFile(res, (LPVOID)tmpContent,res.nDataLen, &dwRead);
+	      map* tmpMap=getMap(tmpmaps->content,"value");
+	      if(tmpMap!=NULL)
+		tmpMap->value=tmpContent;
+	    }
+	    addToMap(tmpmaps->content,tmpn1,tmpv1+1);
+	  }
+	  tmpc=strtok(NULL,"@");
+	}
+	if(request_input_real_format==NULL)
+	  request_input_real_format=tmpmaps;
+	else
+	  addMapsToMaps(&request_input_real_format,tmpmaps);
+#ifdef DEBUG
+	dumpMaps(tmpmaps);
+	fflush(stderr);
+#endif
+	tmpmaps=tmpmaps->next;
+      }
+    }
+  } 
+  else {
+    xmlInitParser();
+    //dumpMap(postRequest);
+#ifdef DEBUG
+    fflush(stderr);
+    fprintf(stderr,"BEFORE %s\n",postRequest->value);
+    fflush(stderr);
+#endif
+    xmlDocPtr doc =
+      xmlParseMemory(postRequest->value,cgiContentLength);//strlen(postRequest->value));
+#ifdef DEBUG
+    fprintf(stderr,"AFTER\n");
+    fflush(stderr);
+#endif
+    xmlNodePtr cur = xmlDocGetRootElement(doc);
+    /**
+     * Parse every Input in DataInputs node.
+     */
+    maps* tempMaps=NULL;
+    xmlNodeSet* tmps=extractFromDoc(doc,
+				    "/*/*/*[local-name()='Input']");
+#ifdef DEBUG
+    fprintf(stderr,"*****%d*****\n",tmps->nodeNr);
+#endif
+    for(int k=0;k<tmps->nodeNr;k++){
+      maps *tmpmaps=NULL;
+      xmlNodePtr cur=tmps->nodeTab[k];
+      if(tmps->nodeTab[k]->type == XML_ELEMENT_NODE) {
+	/**
+	 * A specific Input node.
+	 */
+#ifdef DEBUG
+	fprintf(stderr, "= element 0 node \"%s\"\n", cur->name);
+#endif
+	xmlNodePtr cur1=cur->children;
+	while(cur1){
+#ifdef DEBUG
+	  fprintf(stderr, "= element 1 node \"%s\" = (%s)\n", 
+		  cur1->name,xmlNodeListGetString(doc,cur1,1));
+#endif
+	  xmlNodePtr cur2=cur1/*->next*/;
+	  while(cur2){
+	    /**
+	     * Indentifier
+	     */
+	    if(strcmp(mtoupper((char*)cur2->name),
+		      mtoupper("Identifier"))==0){
+	      xmlChar *val=
+		xmlNodeListGetString(doc,cur2->xmlChildrenNode,1);
+	      if(tmpmaps==NULL){
+		tmpmaps=(maps*)malloc(MAPS_SIZE);
+		tmpmaps->name=strdup((char*)val);
+		tmpmaps->content=NULL;
+		tmpmaps->next=NULL;
+	      }
+	      xmlFree(val);
+	    }
+	    /**
+	     * Title, Asbtract
+	     */
+	    if(strcmp(mtoupper((char*)cur2->name),
+		      mtoupper("Title"))==0 ||
+	       strcmp(mtoupper((char*)cur2->name),
+		      mtoupper("Abstract"))==0){
+	      xmlChar *val=
+		xmlNodeListGetString(doc,cur2->xmlChildrenNode,1);
+	      if(tmpmaps==NULL){
+		tmpmaps=(maps*)malloc(MAPS_SIZE);
+		tmpmaps->name="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);
+	      }
+#ifdef DEBUG
+	      dumpMaps(tmpmaps);
+#endif
+	      xmlFree(val);
+	    }
+	    /**
+	     * InputDataFormChoice (Reference or Data ?) 
+	     */
+	    if(strcmp(mtoupper((char*)cur2->name),
+		      mtoupper("Reference"))==0){
+	      /**
+	       * Get every attribute from a Reference node
+	       * mimeType, encoding, schema, href, method
+	       * Header and Body gesture should be added here
+	       */
+#ifdef DEBUG
+	      fprintf(stderr,"REFERENCE\n");
+#endif
+	      map* referenceMap=NULL;
+	      char *refs[5];
+	      refs[0]="mimeType";
+	      refs[1]="encoding";
+	      refs[2]="schema";
+	      refs[3]="method";
+	      refs[4]="href";
+	      char*url;
+	      for(int l=0;l<5;l++){
+#ifdef DEBUG
+		fprintf(stderr,"*** %s ***\t",refs[l]);
+#endif
+		xmlChar *val=xmlGetProp(cur2,BAD_CAST refs[l]);
+		if(val!=NULL && strlen((char*)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 && strcmp(ltmp->value,"POST")==0)
+		       && CHECK_INET_HANDLE(hInternet)){
+			res=InternetOpenUrl(hInternet,(char*)val,NULL,0,
+					    INTERNET_FLAG_NO_CACHE_WRITE,0);
+			char* tmpContent=
+			  (char*)malloc((res.nDataLen+1)*sizeof(char));
+			size_t dwRead;
+			InternetReadFile(res, (LPVOID)tmpContent,
+					 res.nDataLen, &dwRead);
+			tmpContent[res.nDataLen]=0;
+			addToMap(tmpmaps->content,"value",tmpContent);
+		    }
+		  }
+		  
+		}
+#ifdef DEBUG
+		fprintf(stderr,"%s\n",val);
+#endif
+		xmlFree(val);
+	      }
+#ifdef POST_DEBUG
+	      fprintf(stderr,"Parse Header and Body from Reference \n");
+#endif
+	      xmlNodePtr cur3=cur2->children;
+	      hInternet.header=NULL;
+	      while(cur3){
+		if(strcmp(mtoupper((char*)cur3->name), mtoupper("Header"))==0 ){
+		  xmlNodePtr cur4=cur3;
+		  char *tmp=new char[cgiContentLength];
+		  char *ha[2];
+		  ha[0]="key";
+		  ha[1]="value";
+		  int hai;
+		  char *has;
+		  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=(char*)malloc((1+strlen((char*)val))*sizeof(char));
+		      sprintf(key,"%s",(char*)val);
+		    }else{
+		      has=(char*)malloc((3+strlen((char*)val)+strlen(key))*sizeof(char));
+		      sprintf(has,"%s: %s",key,(char*)val);
+#ifdef POST_DEBUG
+		      fprintf(stderr,"%s\n",has);
+#endif
+		    }
+		  }
+		  hInternet.header=curl_slist_append(hInternet.header, has);
+		  //free(has);
+		}
+		else{
+#ifdef POST_DEBUG
+		  fprintf(stderr,"Try to fetch the body part of the request ...\n");
+#endif
+		  if(strcmp(mtoupper((char*)cur3->name),mtoupper("Body"))==0 ){
+#ifdef POST_DEBUG
+		    fprintf(stderr,"Body part found !!!\n",(char*)cur3->content);
+#endif
+		    char *tmp=new char[cgiContentLength];
+		    memset(tmp,cgiContentLength,0);
+		    xmlNodePtr cur4=cur3->children;
+		    while(cur4!=NULL){
+		      xmlDocPtr bdoc = xmlNewDoc(BAD_CAST "1.0");
+		      bdoc->encoding = xmlCharStrdup ("UTF-8");
+		      xmlDocSetRootElement(bdoc,cur4);
+		      xmlChar* btmps;
+		      int bsize;
+		      xmlDocDumpMemory(bdoc,&btmps,&bsize);
+#ifdef POST_DEBUG
+		      fprintf(stderr,"Body part found !!! %s %s\n",tmp,(char*)btmps);
+#endif
+		      if(btmps!=NULL)
+			sprintf(tmp,"%s",(char*)btmps);
+		      xmlFreeDoc(bdoc);
+		      cur4=cur4->next;
+		    }
+		    map *btmp=getMap(tmpmaps->content,"href");
+		    if(btmp!=NULL){
+#ifdef POST_DEBUG
+		      fprintf(stderr,"%s %s\n",btmp->value,tmp);
+		      curl_easy_setopt(hInternet.handle, CURLOPT_VERBOSE, 1);
+#endif
+		      res=InternetOpenUrl(hInternet,btmp->value,tmp,strlen(tmp),
+					  INTERNET_FLAG_NO_CACHE_WRITE,0);
+		      char* tmpContent=
+			(char*)malloc((res.nDataLen+1)*sizeof(char));
+		      size_t dwRead;
+		      InternetReadFile(res, (LPVOID)tmpContent,
+				       res.nDataLen, &dwRead);
+		      tmpContent[res.nDataLen]=0;
+		      if(hInternet.header!=NULL)
+			curl_slist_free_all(hInternet.header);
+		      addToMap(tmpmaps->content,"value",tmpContent);
+#ifdef POST_DEBUG
+		      fprintf(stderr,"DL CONTENT : (%s)\n",tmpContent);
+#endif
+		    }
+		  }
+		  else
+		    if(strcmp(mtoupper((char*)cur3->name),mtoupper("BodyReference"))==0 ){
+		      xmlChar *val=xmlGetProp(cur3,BAD_CAST "href");
+		      HINTERNET bInternet,res1;
+		      bInternet=InternetOpen(
+#ifndef WIN32
+				  (LPCTSTR)
+#endif
+				  "ZooWPSClient\0",
+					     INTERNET_OPEN_TYPE_PRECONFIG,
+					     NULL,NULL, 0);
+		      if(!CHECK_INET_HANDLE(bInternet))
+			fprintf(stderr,"WARNING : hInternet handle failed to initialize");
+#ifdef POST_DEBUG
+		      curl_easy_setopt(bInternet.handle, CURLOPT_VERBOSE, 1);
+#endif
+		      res1=InternetOpenUrl(bInternet,(char*)val,NULL,0,
+					   INTERNET_FLAG_NO_CACHE_WRITE,0);
+		      char* tmp=
+			(char*)malloc((res1.nDataLen+1)*sizeof(char));
+		      size_t bRead;
+		      InternetReadFile(res1, (LPVOID)tmp,
+				       res1.nDataLen, &bRead);
+		      tmp[res1.nDataLen]=0;
+		      InternetCloseHandle(bInternet);
+		      map *btmp=getMap(tmpmaps->content,"href");
+		      if(btmp!=NULL){
+#ifdef POST_DEBUG
+			fprintf(stderr,"%s %s\n",btmp->value,tmp);
+			curl_easy_setopt(hInternet.handle, CURLOPT_VERBOSE, 1);
+#endif
+			res=InternetOpenUrl(hInternet,btmp->value,tmp,
+					    strlen(tmp),
+					    INTERNET_FLAG_NO_CACHE_WRITE,0);
+			char* tmpContent=
+			  (char*)malloc((res.nDataLen+1)*sizeof(char));
+			size_t dwRead;
+			InternetReadFile(res, (LPVOID)tmpContent,
+					 res.nDataLen, &dwRead);
+			tmpContent[res.nDataLen]=0;
+			if(hInternet.header!=NULL)
+			  curl_slist_free_all(hInternet.header);
+			addToMap(tmpmaps->content,"value",tmpContent);
+#ifdef POST_DEBUG
+			fprintf(stderr,"DL CONTENT : (%s)\n",tmpContent);
+#endif
+		      }
+		    }
+		}
+		cur3=cur3->next;
+	      }
+#ifdef POST_DEBUG
+	      fprintf(stderr,"Header and Body was parsed from Reference \n");
+#endif
+#ifdef DEBUG
+	      dumpMap(tmpmaps->content);
+	      fprintf(stderr, "= element 2 node \"%s\" = (%s)\n", 
+		      cur2->name,cur2->content);
+#endif
+	    }
+	    else if(strcmp(mtoupper((char*)cur2->name),
+			   mtoupper("Data"))==0){
+#ifdef DEBUG
+	      fprintf(stderr,"DATA\n");
+#endif
+	      xmlNodePtr cur4=cur2->children;
+	      while(cur4){
+		if(strcmp(mtoupper((char*)cur4->name),
+			  mtoupper("LiteralData"))==0){
+		  /**
+		   * Get every attribute from a LiteralData node
+		   * dataType , uom
+		   */
+		  char *lits[2];
+		  lits[0]="dataType";
+		  lits[1]="uom";
+		  for(int l=0;l<2;l++){
+#ifdef DEBUG
+		    fprintf(stderr,"*** %s ***\t",lits[l]);
+#endif
+		    xmlChar *val=xmlGetProp(cur4,BAD_CAST lits[l]);
+		    if(val!=NULL && strlen((char*)val)>0){
+		      if(tmpmaps->content!=NULL)
+			addToMap(tmpmaps->content,lits[l],(char*)val);
+		      else
+			tmpmaps->content=createMap(lits[l],(char*)val);
+		    }
+#ifdef DEBUG
+		    fprintf(stderr,"%s\n",val);
+#endif
+		    xmlFree(val);
+		  }
+		  xmlChar* mv=xmlNodeListGetString(doc,
+						   cur4->xmlChildrenNode,1);
+		  if(tmpmaps->content!=NULL)
+		    addToMap(tmpmaps->content,
+			     "value",
+			     (char*)mv);
+		  else
+		    tmpmaps->content=
+		      createMap("value",
+				(char*)mv);
+		  xmlFree(mv);
+		}
+		else if(strcmp(mtoupper((char*)cur4->name),
+			       mtoupper("ComplexData"))==0){
+		  /**
+		   * Get every attribute from a Reference node
+		   * mimeType, encoding, schema
+		   */
+		  char *coms[2];
+		  coms[0]="mimeType";
+		  coms[1]="encoding";
+		  coms[2]="schema";
+		  for(int l=0;l<2;l++){
+#ifdef DEBUG
+		    fprintf(stderr,"*** %s ***\t",coms[l]);
+#endif
+		    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);
+		    }
+#ifdef DEBUG
+		    fprintf(stderr,"%s\n",val);
+#endif
+		    xmlFree(val);
+		  }
+		  xmlChar* mv=xmlNodeListGetString(doc,
+						   cur4->xmlChildrenNode,1);
+		  if(tmpmaps->content!=NULL)
+		    addToMap(tmpmaps->content,
+			     "value",
+			     (char*)mv);
+		  else
+		    tmpmaps->content=
+		      createMap("value",
+				(char*)mv);
+		  xmlFree(mv);
+		}
+		cur4=cur4->next;
+	      }
+	    }
+#ifdef DEBUG
+	    dumpMap(tmpmaps->content);
+	    fprintf(stderr, "= element 2 node \"%s\" = (%s)\n", 
+		    cur2->name,cur2->content);	
+#endif
+	    xmlNodePtr cur3=cur->children;
+	    while(cur3){
+#ifdef DEBUG
+	      fprintf(stderr, "= element 3 node \"%s\" = (%s)\n",cur3->name,
+		      xmlNodeListGetString(doc,cur3->xmlChildrenNode,1));
+#endif
+	      if(strcmp(mtoupper((char*)cur3->name),
+			mtoupper("Title"))==0){
+#ifdef DEBUG
+		fprintf(stderr, "= element 3 node \"%s\" = (%s)\n", 
+			cur3->name,xmlNodeListGetString(doc,cur3,1));
+#endif
+	      }
+	      cur3=cur3->children;
+	    }
+	    cur2=cur2->next;
+	  }
+	  cur1=cur1->children;
+	}
+	if(request_input_real_format==NULL)
+	  request_input_real_format=tmpmaps;
+	else
+	  addMapsToMaps(&request_input_real_format,tmpmaps);
+#ifdef DEBUG
+	dumpMaps(tmpmaps);
+#endif
+	fflush(stderr);
+	tmpmaps=tmpmaps->next;
+	      
+      } else {
+#ifdef DEBUG
+	fprintf(stderr, "= node \"%s\": type %d\n", cur->name, cur->type);
+#endif
+      }
+#ifdef DEBUG
+      dumpMaps(tmpmaps); 
+#endif
+    }
+    
+    xmlFree(tmps);
+    tmps=extractFromDoc(doc,"/*/*/*[local-name()='ResponseDocument']");
+#ifdef DEBUG
+    fprintf(stderr,"*****%d*****\n",tmps->nodeNr);
+#endif
+    for(int k=0;k<tmps->nodeNr;k++){
+      addToMap(request_inputs,"ResponseDocument","");
+      request_output_real_format;
+      maps *tmpmaps=NULL;
+      xmlNodePtr cur=tmps->nodeTab[k];
+      if(cur->type == XML_ELEMENT_NODE) {
+	/**
+	 * A specific responseDocument node.
+	 */
+	if(tmpmaps==NULL){
+	  tmpmaps=(maps*)malloc(MAPS_SIZE);
+	  tmpmaps->name="unknownIdentifier";
+	  tmpmaps->next=NULL;
+	}
+	/**
+	 * Get every attribute from a LiteralData node
+	 * storeExecuteResponse, lineage, status
+	 */
+	char *ress[3];
+	ress[0]="storeExecuteResponse";
+	ress[1]="lineage";
+	ress[2]="status";
+	xmlChar *val;
+	for(int l=0;l<3;l++){
+#ifdef DEBUG
+	  fprintf(stderr,"*** %s ***\t",ress[l]);
+#endif
+	  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);
+	    addToMap(request_inputs,ress[l],(char*)val);
+	  }
+#ifdef DEBUG
+	  fprintf(stderr,"%s\n",val);
+#endif
+	  xmlFree(val);
+	}
+	xmlNodePtr cur1=cur->children;
+	while(cur1){
+	  if(strcmp(mtoupper((char*)cur1->name),
+		    mtoupper("Output"))==0){
+	    /**
+	     * Get every attribute from a Output node
+	     * mimeType, encoding, schema, uom, asReference
+	     */
+	    char *outs[5];
+	    outs[0]="mimeType";
+	    outs[1]="encoding";
+	    outs[2]="schema";
+	    outs[3]="uom";
+	    outs[4]="asReference";
+	    for(int l=0;l<5;l++){
+#ifdef DEBUG
+	      fprintf(stderr,"*** %s ***\t",outs[l]);
+#endif
+	      val=xmlGetProp(cur1,BAD_CAST outs[l]);
+	      if(val!=NULL && strlen((char*)val)>0){
+		if(tmpmaps->content!=NULL)
+		  addToMap(tmpmaps->content,outs[l],(char*)val);
+		else
+		  tmpmaps->content=createMap(outs[l],(char*)val);
+	      }
+#ifdef DEBUG
+	      fprintf(stderr,"%s\n",val);
+#endif
+	      xmlFree(val);
+	    }
+	    
+	    xmlNodePtr cur2=cur1->children;
+	    while(cur2){
+	      /**
+	       * Indentifier
+	       */
+	      if(strcmp(mtoupper((char*)cur2->name),
+			mtoupper("Identifier"))==0){
+		xmlChar *val=
+		  xmlNodeListGetString(doc,cur2->xmlChildrenNode,1);
+		if(tmpmaps==NULL){
+		  tmpmaps=(maps*)malloc(MAPS_SIZE);
+		  tmpmaps->name=strdup((char*)val);
+		  tmpmaps->content=NULL;
+		  tmpmaps->next=NULL;
+		}
+		else
+		  tmpmaps->name=strdup((char*)val);;
+		xmlFree(val);
+	      }
+	      /**
+	       * Title, Asbtract
+	       */
+	      if(strcmp(mtoupper((char*)cur2->name),
+			mtoupper("Title"))==0 ||
+		 strcmp(mtoupper((char*)cur2->name),
+			mtoupper("Abstract"))==0){
+		xmlChar *val=
+		  xmlNodeListGetString(doc,cur2->xmlChildrenNode,1);
+		if(tmpmaps==NULL){
+		  tmpmaps=(maps*)malloc(MAPS_SIZE);
+		  tmpmaps->name="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);
+	      }
+	      cur2=cur2->next;
+	    }
+	  }
+	  cur1=cur1->next;
+	}
+      }
+      //xmlFree(cur);
+      if(request_output_real_format==NULL)
+	request_output_real_format=tmpmaps;
+      else
+	addMapsToMaps(&request_output_real_format,tmpmaps);
+#ifdef DEBUG
+      dumpMaps(tmpmaps);
+#endif
+    }
+
+    xmlFree(tmps);
+    tmps=extractFromDoc(doc,"/*/*/*[local-name()='RawDataOutput']");
+#ifdef DEBUG
+    fprintf(stderr,"*****%d*****\n",tmps->nodeNr);
+#endif
+    for(int k=0;k<tmps->nodeNr;k++){
+      addToMap(request_inputs,"RawDataOutput","");
+      xmlNodePtr cur1=tmps->nodeTab[k];
+      xmlChar *val;
+      /**
+       * Get every attribute from a Output node
+       * mimeType, encoding, schema, uom, asReference
+       */
+      char *outs[4];
+      outs[0]="mimeType";
+      outs[1]="encoding";
+      outs[2]="schema";
+      outs[3]="uom";
+      for(int l=0;l<4;l++){
+#ifdef DEBUG
+	fprintf(stderr,"*** %s ***\t",outs[l]);
+#endif
+	val=xmlGetProp(cur1,BAD_CAST outs[l]);
+	if(val!=NULL && strlen((char*)val)>0){
+	  if(tmpmaps==NULL){
+	    tmpmaps=(maps*)malloc(MAPS_SIZE);
+	    tmpmaps->name="unknownIdentifier";
+	    tmpmaps->content=createMap(outs[l],(char*)val);
+	    tmpmaps->next=NULL;
+	  }
+	  else
+	    addToMap(tmpmaps->content,outs[l],(char*)val);
+	}
+#ifdef DEBUG
+	fprintf(stderr,"%s\n",val);
+#endif
+	xmlFree(val);
+      }
+	    
+      xmlNodePtr cur2=cur1->children;
+      while(cur2){
+	/**
+	 * Indentifier
+	 */
+	if(strcmp(mtoupper((char*)cur2->name),
+		  mtoupper("Identifier"))==0){
+	  val=
+	    xmlNodeListGetString(doc,cur2->xmlChildrenNode,1);
+	  if(tmpmaps==NULL){
+	    tmpmaps=(maps*)malloc(MAPS_SIZE);
+	    tmpmaps->name=strdup((char*)val);
+	    tmpmaps->content=NULL;
+	    tmpmaps->next=NULL;
+	  }
+	  else
+	    tmpmaps->name=strdup((char*)val);;
+	  xmlFree(val);
+	}
+	cur2=cur2->next;
+      }
+      if(request_output_real_format==NULL)
+	request_output_real_format=tmpmaps;
+      else
+	addMapsToMaps(&request_output_real_format,tmpmaps);
+#ifdef DEBUG
+      dumpMaps(tmpmaps);
+#endif
+    }
+    
+    xmlFree(tmps);
+    xmlCleanupParser();
+  }
+
+  if(CHECK_INET_HANDLE(hInternet))
+    InternetCloseHandle(hInternet);
+
+#ifdef DEBUG
+  fprintf(stderr,"\n%i\n",i);
+  dumpMaps(request_input_real_format);
+  dumpMaps(request_output_real_format);
+  dumpElements();
+#endif
+
+  /**
+   * Ensure that each requested arguments are present in the request
+   * DataInputs and ResponseDocument / RawDataOutput
+   */
+  addDefaultValues(&request_input_real_format,s1->inputs,m,"inputs");
+  addDefaultValues(&request_output_real_format,s1->outputs,m,"outputs");
+
+  const struct tm *tm;
+  size_t len;
+  time_t now;
+  char *sDate;
+  
+  now = time ( NULL );
+  tm = localtime ( &now );
+
+  sDate = new char[TIME_SIZE];
+
+  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
+      fflush(stderr);
+      fprintf(stderr,"setting variable... %s\n",
+#endif
+	      SetEnvironmentVariable(mapcs->name,mapcs->value)
+#ifdef DEBUG
+	      ? "OK" : "FAILED");
+#else
+      ;
+#endif
+#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;
+    }
+  }
+  
+  len = strftime ( sDate, TIME_SIZE, "%d-%B-%YT%I:%M:%SZ", tm );
+
+#ifdef DEBUG
+  dumpMap(request_inputs);
+#endif
+
+  /**
+   * Need to check if we need to fork to load a status enabled 
+   */
+  r_inputs=NULL;
+  r_inputs=getMap(request_inputs,"storeExecuteResponse");
+  int eres=SERVICE_STARTED;
+  int cpid=getpid();
+#ifdef DEBUG
+  dumpMap(request_inputs);
+#endif
+
+  if(r_inputs==NULLMAP){
+    /**
+     * Extract serviceType to know what kind of service shoudl be loaded
+     */
+    r_inputs=NULL;
+    r_inputs=getMap(s1->content,"serviceType");
+#ifdef DEBUG
+    fprintf(stderr,"LOAD A %s SERVICE PROVIDER IN NORMAL MODE \n",r_inputs->value);
+    fflush(stderr);
+#endif
+
+	if(strncmp(mtoupper(r_inputs->value),"C",1)==0){
+      r_inputs=getMap(request_inputs,"metapath");
+      sprintf(tmps1,"%s/%s",ntmp,r_inputs->value);
+	  char *altPath=strdup(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
+      DWORD errstr;
+	  errstr = GetLastError();
+#ifdef DEBUG
+	  fprintf(stderr,"%s loaded (%d) \n",tmps1,errstr);
+#endif
+#else
+      char *errstr;
+	  errstr = dlerror();
+#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 %s",r_inputs->value,mtoupper(r_inputs->value));
+	fflush(stderr);
+#endif
+	if(strcmp(mtoupper(r_inputs->value),"C-FORTRAN")==0){
+#ifdef WIN32
+	  //Strange return value needed here !
+	  return 1;
+#endif
+	  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 = GetLastError();
+#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{
+	  errstr = GetLastError();
+#ifdef DEBUG
+	  fprintf(stderr,"Function %s failed to load because of %d\n",r_inputs->value,errstr);
+#endif
+	  r_inputs=getMap(request_inputs,"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); 
+#ifdef DEBUG
+	  /*if(!execute)*/
+	  errstr = GetLastError();
+	  fprintf(stderr,"Function %s failed to load because of %d\n",r_inputs->value,errstr);
+	  /*else
+	  fprintf(stderr,"Function %s loaded\n",r_inputs->value);*/
+#endif
+#else
+	  execute_t execute=(execute_t)dlsym(so,r_inputs->value);
+#endif
+
+#ifdef DEBUG
+#ifdef WIN32
+	  errstr = GetLastError();
+#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
+	  //return 1;
+	}
+
+	//dlclose(so);
+      } else {
+	/**
+	 * Unable to load the specified shared library
+	 */
+	char tmps[1024];
+	sprintf(tmps,"C Library can't be loaded %s \n",errstr);
+	map* tmps1=createMap("text",tmps);
+	printExceptionReportResponse(m,tmps1);
+	exit(1);
+      }
+    }
+    else{
+	if(strcmp(mtoupper(r_inputs->value),"PYTHON")==0){
+		eres=zoo_python_support(&m,request_inputs,s1,&request_input_real_format,&request_output_real_format);
+      	}
+	else
+
+	#ifdef USE_JAVA
+	if(strcmp(mtoupper(r_inputs->value),"JAVA")==0){
+	  eres=zoo_java_support(&m,request_inputs,s1,&request_input_real_format,&request_output_real_format);
+	}
+	else
+	#endif
+
+	#ifdef USE_PHP
+	  if(strcmp(mtoupper(r_inputs->value),"PHP")==0){
+	    eres=zoo_php_support(&m,request_inputs,s1,&request_input_real_format,&request_output_real_format);
+	  }
+	else
+	#endif
+	
+	#ifdef USE_JS
+	    if(strcmp(mtoupper(r_inputs->value),"JS")==0){
+	      eres=zoo_js_support(&m,request_inputs,s1,&request_input_real_format,&request_output_real_format);
+	      //dumpMaps(request_output_real_format);
+	      //exit(-1);
+	    }
+	    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);
+	      map* tmps=createMap("text",tmpv);
+	      printExceptionReportResponse(m,tmps);
+	      return(-1);
+	    }
+    }
+  }
+  else{
+
+    pid_t   pid;
+#ifdef DEBUG
+    fprintf(stderr,"\nPID : %d\n",cpid);
+#endif
+#ifndef WIN32
+	pid = fork ();
+#else
+	pid = 0;
+#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.
+       */
+      char tmp1[256];
+      r_inputs=getMapFromMaps(m,"main","tmpPath");
+      sprintf(tmp1,"%s",r_inputs->value);
+      r_inputs=getMap(s1->content,"ServiceProvider");
+      sprintf(tmp1,"%s/%s",strdup(tmp1),r_inputs->value);
+      sprintf(tmp1,"%s_%d.xml",strdup(tmp1),cpid);
+#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",tmp1);
+#endif
+      freopen(tmp1 , "w+", stdout);
+      fclose(stdin);
+      fclose(stderr);
+      /**
+       * 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.
+       */
+      printProcessResponse1(m,request_inputs,cpid,
+			    s[0],r_inputs->value,SERVICE_STARTED,
+			    request_input_real_format,
+			    request_output_real_format);
+      fflush(stdout);
+      rewind(stdout);
+      /**
+       * Extract serviceType to know what kind of service shoudl be loaded
+       */
+      r_inputs=NULL;
+      r_inputs=getMap(s1->content,"serviceType");
+#ifdef DEBUG
+      fprintf(stderr,"LOAD A %s SERVICE PROVIDER IN BACKGROUND MODE \n",r_inputs->value);
+#endif
+
+      if(strncmp(mtoupper(r_inputs->value),"C",1)==0){
+	r_inputs=getMap(request_inputs,"metapath");
+	sprintf(tmps1,"%s/%s",ntmp,r_inputs->value);
+	r_inputs=getMap(s1->content,"ServiceProvider");
+	sprintf(tmps1,"%s/%s",strdup(tmps1),r_inputs->value);
+  
+#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
+	  DWORD errstr;
+	  errstr = GetLastError();
+#else
+	  char *errstr;
+	  errstr = dlerror();
+#endif
+	if( so != NULL ) {
+	  r_inputs=getMap(s1->content,"serviceType");
+#ifdef DEBUG
+	  fprintf(stderr,"r_inputs->value = %s\n",r_inputs->value);
+#endif
+	  if(strcmp(mtoupper(r_inputs->value),"C-FORTRAN")==0){
+	    r_inputs=getMap(request_inputs,"Identifier");
+#ifdef DEBUG
+	    fprintf(stderr,"Try to load function %s\n",r_inputs->value);
+#endif
+	    typedef int (*execute_t)(char***,char***,char***);
+	    char fname[1024];
+	    sprintf(fname,"%s_",r_inputs->value);
+#ifdef DEBUG
+	    fprintf(stderr,"Try to load function %s\n",fname);
+#endif
+#ifdef WIN32
+	  execute_t execute=(execute_t)GetProcAddress(so,fname); 
+#else
+	  execute_t execute=(execute_t)dlsym(so,fname);
+#endif
+#ifdef DEBUG
+#ifdef WIN32
+	  errstr = GetLastError();
+#else
+	  errstr = dlerror();
+#endif
+#endif	
+	    char main_conf[10][10][1024];
+	    char inputs[10][10][1024];
+	    char outputs[10][10][1024];
+	    for(int i=0;i<10;i++){
+	      for(int j=0;j<10;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]);
+	    charxxxToMaps((char***)&outputs[0],&request_output_real_format);
+
+	  }else{
+
+	    typedef int (*execute_t)(maps**,maps**,maps**);
+#ifdef DEBUG
+	    fprintf(stderr,"Library loaded %s \n",errstr);
+#endif
+	    r_inputs=getMap(request_inputs,"Identifier");
+#ifdef DEBUG
+	    fprintf(stderr,"Try to load function %s\n",r_inputs->value);
+#endif
+#ifdef WIN32
+	  execute_t execute=(execute_t)GetProcAddress(so,r_inputs->value); 
+#else
+	  execute_t execute=(execute_t)dlsym(so,r_inputs->value);
+#endif
+#ifdef DEBUG
+#ifdef WIN32
+	  errstr = GetLastError();
+#else
+	  errstr = dlerror();
+#endif
+	    fprintf(stderr,"Function loaded %s\n",errstr);
+#endif	
+	    /**
+	     * set the status code value returned by the service function itself
+	     */
+	    eres=execute(&m,&request_input_real_format,&request_output_real_format);
+	    //dlclose(so);
+	  }
+	} else {
+	  //#ifdef DEBUG
+	  /**
+	   * Should fallback to others languages.
+	   * Maybe beter to keep this informations anywhere 
+	   * (in the service metadata ?)
+	   */
+	  char tmps2[1024];
+	  sprintf(tmps1,"C Library can't be loaded %s \n",errstr);
+	  map* tmps=createMap("text",tmps1);
+	  printExceptionReportResponse(m,tmps);
+	  exit(1);
+	}
+      } else{
+	if(strcmp(mtoupper(r_inputs->value),"PYTHON")==0){
+	  eres=zoo_python_support(&m,request_inputs,s1,&request_input_real_format,&request_output_real_format);
+	}
+	else
+
+	#ifdef USE_JAVA
+	  if(strcmp(mtoupper(r_inputs->value),"JAVA")==0){
+	    eres=zoo_java_support(&m,request_inputs,s1,&request_input_real_format,&request_output_real_format);
+	  }
+	  else
+	#endif
+	
+	#ifdef USE_PHP
+	    if(strcmp(mtoupper(r_inputs->value),"PHP")==0){
+	      eres=zoo_php_support(&m,request_inputs,s1,&request_input_real_format,&request_output_real_format);
+	    }
+	    else
+	#endif
+
+	#ifdef USE_JS
+	    if(strcmp(mtoupper(r_inputs->value),"JS")==0){
+		eres=zoo_js_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);
+	      map* tmps=createMap("text",tmpv);
+	      printExceptionReportResponse(m,tmps);
+	      return -1;
+	    }
+      }
+  
+      //res=execute(&m,&request_input_real_format,&request_output_real_format);
+    } else {
+      /**
+       * error server don't accept the process need to output a valid 
+       * error response here !!!
+       */
+    }
+      	
+  }
+
+#ifdef DEBUG
+  dumpMaps(request_output_real_format);
+#endif
+  outputResponse(s1,request_input_real_format,
+		 request_output_real_format,request_inputs,
+		 cpid,m,eres);
+
+#ifdef DEBUG
+  fprintf(stderr,"Processed response \n");
+  fflush(stdout);
+  fflush(stderr);
+#endif
+
+  //dlclose(so);
+  return 0;
+}
Index: trunk/zoo-services/arithmetics/Makefile
===================================================================
--- trunk/zoo-services/arithmetics/Makefile	(revision 1)
+++ trunk/zoo-services/arithmetics/Makefile	(revision 1)
@@ -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
+
+clean:
+	rm -f cgi-env/test_service.zo
Index: trunk/zoo-services/arithmetics/cgi-env/Multiply.zcfg
===================================================================
--- trunk/zoo-services/arithmetics/cgi-env/Multiply.zcfg	(revision 1)
+++ trunk/zoo-services/arithmetics/cgi-env/Multiply.zcfg	(revision 1)
@@ -0,0 +1,56 @@
+[Multiply]
+ Title = Multiply two values
+ Abstract = Multiply two values and stor the result in Result.
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = demo_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>
+     value = 1.0
+     UOM = meters
+    </Default>
+    <Supported>
+     UOM = feet
+    </Supported>
+   </LiteralData>
+  [B]
+   Title = second value
+   Abstract = The value used to multiply by A.
+   minOccurs = 1
+   maxOccurs = 1
+   <LiteralData>
+    DataType = float
+    <Default>
+     UOM = meters
+    </Default>
+    <Supported>
+     UOM = feet
+    </Supported>
+   </LiteralData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = A x B 
+   Abstract = The value of A x B.
+   <LiteralOutput>
+    DataType = float
+    <Default>
+     UOM = meters
+    </Default>
+    <Supported>
+     UOM = feet
+    </Supported>
+   </LiteralOutput>
+ </DataOutputs>  
Index: trunk/zoo-services/arithmetics/makefile.vc
===================================================================
--- trunk/zoo-services/arithmetics/makefile.vc	(revision 1)
+++ trunk/zoo-services/arithmetics/makefile.vc	(revision 1)
@@ -0,0 +1,11 @@
+GEODIR=c:/OSGeo4W/
+TOOLS=c:/Users/djay/GeoLabs/tools/
+CFLAGS=-I$(GEODIR)/include -I$(TOOLS)/include -I../../../zoo-kernel/ -I./ -DLINUX_FREE_ISSUE -DDEBUG
+CPP=cl /TP 
+
+cgi-env/service.zo: service.c
+	$(CPP) $(CFLAGS) /c service.c
+	link /dll /out:cgi-env/ogr_service.zso ../../../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
Index: trunk/zoo-services/arithmetics/test_service.c
===================================================================
--- trunk/zoo-services/arithmetics/test_service.c	(revision 1)
+++ trunk/zoo-services/arithmetics/test_service.c	(revision 1)
@@ -0,0 +1,100 @@
+#include "service.h"
+
+extern "C" {
+
+  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;
+	outputs=(maps*)malloc(sizeof(maps*));
+	outputs->name="Result";
+	char tmp[256];
+	sprintf(tmp,"%i",res);
+	outputs->content=createMap("value",tmp);
+	addMapToMap(&outputs->content,createMap("datatype","float"));
+	addMapToMap(&outputs->content,createMap("uom","meter"));
+	outputs->next=NULL;
+	dumpMaps(outputs);
+  	fprintf(stderr,"\nService internal print\n===\n");
+	return SERVICE_SUCCEEDED;
+  }
+
+  int helloworld1(maps*& conf,maps*& inputs,maps*& outputs){
+    outputs=(maps*)malloc(sizeof(maps*));
+    outputs->name="Result";
+    outputs->content=createMap("value","Hello World");
+    addMapToMap(&outputs->content,createMap("datatype","string"));
+    return SERVICE_SUCCEEDED; 
+  }
+
+  int helloworld(map*& inputs,map*& outputs){
+    outputs=createMap("output_0","Hello World\n");
+    return SERVICE_SUCCEEDED; 
+  }
+
+  int printArguments(map*& inputs,map*& outputs){
+    char *res=(char *)malloc(sizeof(char));
+    map* tmp=inputs;
+    while(tmp!=NULL){
+      res=(char *)realloc(res,strlen(res)+strlen(tmp->value)+strlen(tmp->name)+6);
+      sprintf(res,"%s,\"%s\"=\"%s\"",res,tmp->name,tmp->value);
+      //sprintf(res,"%s,\"%s\"=\"%s\"",res,tmp->name,tmp->value);
+      tmp=tmp->next;
+    }
+    char *tmpVal=strdup(res+1);
+    outputs=createMap("output_0",tmpVal);
+    addToMap(outputs,"output_1",tmpVal);
+
+    /*dumpMap(outputs);
+      dumpMap(inputs);*/
+    return SERVICE_SUCCEEDED; 
+  }
+
+  int buildJsonArrayOfArgs(map*& inputs,map*& outputs){
+    char *res=(char *)malloc(sizeof(char));
+    map* tmp=inputs;
+    while(tmp!=NULL){
+      res=(char *)realloc(res,strlen(res)+strlen(tmp->value)+3);
+      sprintf(res,"%s,\"%s\"",res,tmp->value);
+      tmp=tmp->next;
+    }
+    char *tmpVal;
+    if(strncmp(res,",",1)!=0){
+      free(tmpVal);
+      tmpVal=strdup(res+1);
+      //dumpMap(inputs);      
+    }else
+      tmpVal=strdup(res);
+    tmpVal=(char*)realloc(tmpVal,strlen(tmpVal)+2);
+    sprintf(tmpVal,"[%s]",tmpVal);
+    outputs=createMap("output_0",tmpVal+1);
+    //dumpMap(outputs);
+    //dumpMap(inputs);
+    return SERVICE_SUCCEEDED; 
+  }
+
+}
Index: trunk/zoo-services/arithmetics/test_service.h
===================================================================
--- trunk/zoo-services/arithmetics/test_service.h	(revision 1)
+++ trunk/zoo-services/arithmetics/test_service.h	(revision 1)
@@ -0,0 +1,1 @@
+int helloworld(int);
Index: trunk/zoo-services/cgal/Makefile
===================================================================
--- trunk/zoo-services/cgal/Makefile	(revision 1)
+++ trunk/zoo-services/cgal/Makefile	(revision 1)
@@ -0,0 +1,9 @@
+CFLAGS=-I../../zoo-kernel-svn/ -I./ `xml2-config --cflags` `python-config --cflags` -DLINUX_FREE_ISSUE #-DDEBUG
+CC=gcc
+
+cgi-env/service.zo: service.c
+	g++ ${CFLAGS} -shared -fpic -o cgi-env/service.zo ./service.c -lgdal
+
+clean:
+	rm -f *.zo *.o *.tab.c *.tab.h *.sr.c* service_loader lex.* *.lreg *.sibling
+	rm -rf service_loader.dSYM
Index: trunk/zoo-services/cgal/service.c
===================================================================
--- trunk/zoo-services/cgal/service.c	(revision 1)
+++ trunk/zoo-services/cgal/service.c	(revision 1)
@@ -0,0 +1,624 @@
+#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"
+
+typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
+
+typedef CGAL::Delaunay_triangulation_2<K>  Triangulation;
+typedef Triangulation::Edge_iterator  Edge_iterator;
+typedef Triangulation::Point          Point;
+
+typedef CGAL::Constrained_Delaunay_triangulation_2<K> CDT;
+typedef CDT::Point Point;
+typedef CDT::Vertex_handle Vertex_handle;
+
+typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
+typedef CGAL::Triangulation_euclidean_traits_xy_3<K>  Gt;
+typedef CGAL::Delaunay_triangulation_2<Gt> DelaunayTriangulation;
+
+typedef Triangulation::Vertex_circulator Vertex_circulator;
+
+typedef K::Point_3   Point1;
+
+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>
+
+  xmlNodeSet* extractFromDoc(xmlDocPtr,char*);
+  void printExceptionReportResponse(maps*,map*);
+
+  char *base64(const unsigned char *input, int length){
+    BIO *bmem, *b64;
+    BUF_MEM *bptr;
+
+    b64 = BIO_new(BIO_f_base64());
+    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);
+    memcpy(buff, bptr->data, bptr->length);
+    buff[bptr->length] = 0;
+
+    BIO_free_all(b64);
+
+    return buff;
+  }
+
+  OGRGeometryH createGeometryFromGML(maps* conf,char* inputStr){
+    xmlInitParser();
+    xmlDocPtr doc = xmlParseMemory(inputStr,strlen(inputStr));
+    xmlChar *xmlbuff;
+    int buffersize;
+    xmlXPathContextPtr xpathCtx;
+    xmlXPathObjectPtr xpathObj;
+    char * xpathExpr="/*/*/*/*/*[local-name()='Polygon' or local-name()='MultiPolygon']";
+    xpathCtx = xmlXPathNewContext(doc);
+    xpathObj = xmlXPathEvalExpression(BAD_CAST xpathExpr,xpathCtx);
+    if(!xpathObj->nodesetval){
+      map* tmp=createMap("text","Unable to parse Input Polygon");
+      addToMap(tmp,"code","InvalidParameterValue");
+      printExceptionReportResponse(conf,tmp);
+      exit(0);
+    }
+    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=strdup(strstr((char*)xmlbuff,"?>")+2);
+    xmlXPathFreeObject(xpathObj);
+    xmlXPathFreeContext(xpathCtx); 
+    xmlFree(xmlbuff);
+    xmlFreeDoc(doc);
+    xmlCleanupParser();
+    fprintf(stderr,"\nService internal print\n Loading the geometry from GML string ...");
+    OGRGeometryH res=OGR_G_CreateFromGML(tmp);
+    if(res==NULL){
+      map* tmp=createMap("text","Unable to call OGR_G_CreatFromGML");
+      addToMap(tmp,"code","NoApplicableCode");
+      printExceptionReportResponse(conf,tmp);
+      exit(0);
+    }
+    else
+      return OGR_G_CreateFromGML(tmp);
+  }
+
+  
+  int Delaunay(maps*& conf,maps*& inputs,maps*& outputs){
+    fprintf(stderr,"\nService internal print\nStarting\n");
+    maps* cursor=inputs;
+    OGRGeometryH geometry,res;
+    int bufferDistance;
+    xmlInitParser();
+    map* tmpm=NULL;
+    tmpm=getMapFromMaps(inputs,"InputPoints","value");
+
+    xmlInitParser();
+    xmlDocPtr doc =
+      xmlParseMemory(tmpm->value,strlen(tmpm->value));
+    xmlNodePtr cur = xmlDocGetRootElement(doc);
+    /**
+     * Parse every Input in DataInputs node.
+     */
+    maps* tempMaps=NULL;
+    xmlXPathContextPtr xpathCtx;
+    xmlXPathObjectPtr xpathObj;
+    xpathCtx = xmlXPathNewContext(doc);
+    xpathObj = xmlXPathEvalExpression(BAD_CAST "/*/*[local-name()='featureMember']/*/*/*[local-name()='Point']/*[local-name()='coordinates']",xpathCtx);
+    xmlXPathFreeContext(xpathCtx); 
+    xmlNodeSet* toto=xpathObj->nodesetval;
+
+    if(toto==NULL)
+      fprintf(stderr,"IMPOSSIBLE DE CONTINUER !!!!\n");
+    char filepath[2048];
+    map* tmpMap=getMapFromMaps(conf,"main","tmpPath");
+    if(tmpMap!=NULL){
+      sprintf(filepath,"%s/varonoi_%d.tmp",tmpMap->value,getpid());
+    }
+    FILE *fo=fopen(filepath,"w");
+    fprintf(stderr,"File Creation (%s) OK\nPrinting %d Points.\n",filepath,toto->nodeNr);
+    for(int k=0;k<toto->nodeNr;k++){
+      xmlNodePtr cur=toto->nodeTab[k];
+      char *val=
+	(char*)xmlNodeListGetString(doc,cur->xmlChildrenNode,1);
+      char *tmp=strstr(val,",");
+      char tmp1[1024];
+      strncpy(tmp1,val,strlen(val)-strlen(tmp));
+      tmp1[strlen(val)-strlen(tmp)]=0;
+      char buff[1024];
+      sprintf(buff,"%s %s\n",tmp1,tmp+1);
+      fwrite(buff,1,strlen(buff)*sizeof(char),fo);
+    }
+    fclose(fo);
+    fprintf(stderr,"File Close (%s) OK\n",filepath);
+
+    std::ifstream in(filepath);
+
+    std::istream_iterator<Point1> begin(in);
+    std::istream_iterator<Point1> end;
+
+    DelaunayTriangulation dt1;
+    dt1.insert(begin, end);
+
+    OGRRegisterAll();
+    /* -------------------------------------------------------------------- */
+    /*      Try opening the output datasource as an existing, writable      */
+    /* -------------------------------------------------------------------- */
+    OGRDataSource       *poODS;
+    
+    OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
+    OGRSFDriver          *poDriver = NULL;
+    int                  iDriver;
+
+    tmpMap=getMapFromMaps(outputs,"Result","mimeType");
+    char *oDriver=(char*)malloc(7*sizeof(char));
+    oDriver="GeoJSON";
+    if(tmpMap!=NULL){
+      if(strcmp(tmpMap->value,"text/xml")==0){
+	fprintf(stderr,"USEING GML \n");
+	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() );
+	  }
+	
+	fprintf(stderr,"{\"type\": \"error\", \"%s\"}",emessage);   
+	exit( 1 );
+      }
+
+    if( !poDriver->TestCapability( ODrCCreateDataSource ) ){
+      char emessage[1024];
+      sprintf( emessage,  "%s driver does not support data source creation.\n",
+	       "json" );
+      fprintf(stderr,"{\"type\": \"error\", \"%s\"}",emessage);   
+      exit( 1 );
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Create the output data source.                                  */
+    /* -------------------------------------------------------------------- */
+    map* tpath=getMapFromMaps(conf,"main","tmpPath");
+    char *pszDestDataSource=(char*)malloc(strlen(tpath->value)+20);
+    char **papszDSCO=NULL;
+    sprintf(pszDestDataSource,"%s/result_%d.json",tpath->value,getpid());
+    fprintf(stderr,"\n *%s* \n",pszDestDataSource);
+    poODS = poDriver->CreateDataSource( pszDestDataSource, papszDSCO );
+    if( poODS == NULL ){
+      char emessage[1024];      
+      sprintf( emessage,  "%s driver failed to create %s\n", 
+	       "json", pszDestDataSource );
+      fprintf(stderr,"{\"type\": \"error\", \"%s\"}",emessage);   
+      exit( 1 );
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Create the layer.                                               */
+    /* -------------------------------------------------------------------- */
+    if( !poODS->TestCapability( ODsCCreateLayer ) )
+      {
+	char emessage[1024];
+	sprintf( emessage, 
+		 "Layer %s not found, and CreateLayer not supported by driver.", 
+		 "Result" );
+	fprintf(stderr,"{\"type\": \"error\",\"message\": \"%s\"}",emessage);
+	return FALSE;
+      }
+    
+    CPLErrorReset();
+    
+    OGRLayer *poDstLayer = poODS->CreateLayer( "Result", NULL,wkbLineString,NULL);
+    if( poDstLayer == NULL ){
+      fprintf( stderr,"Layer creation failed.\n" );
+      exit( 1 );
+    }
+
+    Vertex_circulator vc = dt1.incident_vertices(dt1.infinite_vertex()),
+      done(vc);
+    if (vc != 0) {
+      do {std::cout << vc->point() << std::endl;}while(++vc != done);
+    }
+
+    DelaunayTriangulation::Edge_iterator eit=dt1.edges_begin();
+    int i=0;
+    for ( ; eit !=dt1.edges_end(); ++eit) {
+      fprintf(stderr,"Edge %d\n",i);
+      i++;
+      /*CGAL::Object o = dt1.dual(eit);
+      if (const K::Segment_2 *tmp=CGAL::object_cast<K::Segment_2>(&o)) {
+	const K::Point_2 p1=tmp->source();
+	const K::Point_2 p2=tmp->target();
+	//#ifdef DEBUG
+	fprintf(stderr,"P1 %d %d | P2 %d %d\n",p1.x(),p1.y(),p2.x(),p2.y());
+	//#endif
+	}*/
+      /*if (const K::Segment_3 *tmp=CGAL::object_cast<K::Segment_3>(eit)) {
+	const K::Point_3 p1=tmp->source();
+	const K::Point_3 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 ){
+	  fprintf( stderr,"Failed to create feature in file.\n" );
+	  exit( 1 );
+	  }
+	  OGR_F_Destroy( hFeature );*/
+    }
+  
+    int idg=0;
+    for (DelaunayTriangulation::Face_iterator fit = dt1.faces_begin(); fit!=
+	   dt1.faces_end(); ++fit) {
+      int idx = 0;
+      int i0, i1, i2;
+
+      OGRFeatureH hFeature = OGR_F_Create( OGR_L_GetLayerDefn( poDstLayer ) );
+      OGRGeometryH currLine=OGR_G_CreateGeometry(wkbLineString);
+      
+      for(i0=0;i0<3;i0++){
+	if(!dt1.is_infinite((*fit).vertex(i0)))
+	  OGR_G_AddPoint_2D(currLine,(*fit).vertex(i0)->point().x(),
+			    (*fit).vertex(i0)->point().y());
+	if(i0==2 && !dt1.is_infinite((*fit).vertex(0)))
+	  OGR_G_AddPoint_2D(currLine,(*fit).vertex(0)->point().x(),
+			    (*fit).vertex(0)->point().y());
+      }
+      OGR_F_SetGeometry( hFeature, currLine );
+      OGR_G_DestroyGeometry(currLine);
+      if( OGR_L_CreateFeature( poDstLayer, hFeature ) != OGRERR_NONE ){
+	fprintf( stderr,"Failed to create feature in file.\n" );
+	exit( 1 );
+      }
+      OGR_F_Destroy( hFeature );
+
+      /*OGRFeatureH hFeature=NULL;
+      OGRGeometryH currLine=NULL;
+      if(idg==0) {
+	hFeature = OGR_F_Create( OGR_L_GetLayerDefn( poDstLayer ) );
+	currLine=OGR_G_CreateGeometry(wkbLineString);      
+	}*/
+
+      for (DelaunayTriangulation::Vertex_iterator vit = dt1.vertices_begin(); vit!=
+	     dt1.vertices_end(); ++vit) {
+	idx++;
+	/*if(idg==0)
+	  OGR_G_AddPoint_2D(currLine,(*vit).point().x(),
+	  (*vit).point().y());*/
+
+
+	if ((*vit).point() == (*fit).vertex(0)->point()){
+	  i0 = idx; 
+	  /*OGR_G_AddPoint_2D(currLine,(*fit).vertex(i0)->point().x(),
+	    (*fit).vertex(i0)->point().y());**/
+	}
+	if ((*vit).point() == (*fit).vertex(1)->point()){  
+	  i1 = idx; 
+	  /*OGR_G_AddPoint_2D(currLine,(*fit).vertex(i1)->point().x(),
+	    (*fit).vertex(i1)->point().y());*/
+	}
+	if ((*vit).point() == (*fit).vertex(2)->point()){  
+	  i2 = idx; 
+	  /*OGR_G_AddPoint_2D(currLine,(*fit).vertex(i2)->point().x(),
+	    (*fit).vertex(i2)->point().y());*/
+	}
+      }
+      /*if(idg==0){
+	OGR_F_SetGeometry( hFeature, currLine );
+	OGR_G_DestroyGeometry(currLine);
+	if( OGR_L_CreateFeature( poDstLayer, hFeature ) != OGRERR_NONE ){
+	  fprintf( stderr,"Failed to create feature in file.\n" );
+	  exit( 1 );
+	}
+	OGR_F_Destroy( hFeature );
+	idg++;
+	}*/
+
+      std::cerr << "f " << i0 << " " << dt1.triangle(fit) << std::endl;
+      
+    } 
+    OGR_DS_Destroy( poODS );
+    OGRCleanupAll();
+
+ 
+    char tmp1[1024];
+    outputs=(maps*)malloc(sizeof(maps*));
+    outputs->name="Result";
+
+    FILE * fichier=fopen(pszDestDataSource,"r"); 
+    struct stat file_status;
+    stat(pszDestDataSource, &file_status);
+    fprintf(stderr,"%s (%d)",pszDestDataSource,file_status.st_size);
+    char *res1=(char *)malloc(file_status.st_size*sizeof(char));
+    if(fichier==NULL)
+      fprintf(stderr,"Failed to open file %s for reading purpose.\n",pszDestDataSource);
+    fread(res1,1,(file_status.st_size)*sizeof(char),fichier);
+    res1[strlen(res1)]=0;
+    fclose(fichier);
+    //unlink(pszDestDataSource);
+    //fprintf(stderr,"Read (%s).\n",res1);
+    
+    outputs->content=createMap("value",res1);
+    
+    if(strcmp(oDriver,"GML")==0)
+      addMapToMap(&outputs->content,createMap("mimeType","text/xml"));
+    else
+      addMapToMap(&outputs->content,createMap("mimeType","text/plain"));
+
+    addMapToMap(&outputs->content,createMap("encoding","UTF-8"));
+    outputs->next=NULL;
+    fprintf(stderr,"\nService internal print\n===\n");
+    xmlCleanupParser();
+
+    return SERVICE_SUCCEEDED;
+  }
+  
+
+  int Voronoi(maps*& conf,maps*& inputs,maps*& outputs){
+    fprintf(stderr,"\nService internal print\nStarting\n");
+    maps* cursor=inputs;
+    OGRGeometryH geometry,res;
+    int bufferDistance;
+    xmlInitParser();
+    map* tmpm=NULL;
+    tmpm=getMapFromMaps(inputs,"InputPoints","value");
+    
+    xmlInitParser();
+    xmlDocPtr doc =
+      xmlParseMemory(tmpm->value,strlen(tmpm->value));
+    xmlNodePtr cur = xmlDocGetRootElement(doc);
+    /**
+     * Parse every Input in DataInputs node.
+     */
+    maps* tempMaps=NULL;
+    xmlXPathContextPtr xpathCtx;
+    xmlXPathObjectPtr xpathObj;
+    xpathCtx = xmlXPathNewContext(doc);
+    xpathObj = xmlXPathEvalExpression(BAD_CAST "/*/*[local-name()='featureMember']/*/*/*[local-name()='Point']/*[local-name()='coordinates']",xpathCtx);
+    xmlXPathFreeContext(xpathCtx); 
+    xmlNodeSet* toto=xpathObj->nodesetval;
+
+    if(toto==NULL)
+      fprintf(stderr,"IMPOSSIBLE DE CONTINUER !!!!\n");
+    char filepath[2048];
+    map* tmpMap=getMapFromMaps(conf,"main","tmpPath");
+    if(tmpMap!=NULL){
+      sprintf(filepath,"%s/varonoi_%d.tmp",tmpMap->value,getpid());
+    }
+    FILE *fo=fopen(filepath,"w");
+    fprintf(stderr,"File Creation (%s) OK\nPrinting %d Points.\n",filepath,toto->nodeNr);
+    for(int k=0;k<toto->nodeNr;k++){
+      xmlNodePtr cur=toto->nodeTab[k];
+      char *val=
+	(char*)xmlNodeListGetString(doc,cur->xmlChildrenNode,1);
+      char *tmp=strstr(val,",");
+      char tmp1[1024];
+      strncpy(tmp1,val,strlen(val)-strlen(tmp));
+      tmp1[strlen(val)-strlen(tmp)]=0;
+      char buff[1024];
+      sprintf(buff,"%s %s\n",tmp1,tmp+1);
+      fwrite(buff,1,strlen(buff)*sizeof(char),fo);
+    }
+    fclose(fo);
+    fprintf(stderr,"File Close (%s) OK\n",filepath);
+
+    std::ifstream in(filepath);
+    std::istream_iterator<Point> begin(in);
+    std::istream_iterator<Point> end;
+    Triangulation T;
+    T.insert(begin, end);
+
+    OGRRegisterAll();
+    /* -------------------------------------------------------------------- */
+    /*      Try opening the output datasource as an existing, writable      */
+    /* -------------------------------------------------------------------- */
+    OGRDataSource       *poODS;
+    
+    OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
+    OGRSFDriver          *poDriver = NULL;
+    int                  iDriver;
+
+    tmpMap=getMapFromMaps(outputs,"Result","mimeType");
+    char *oDriver=(char*)malloc(7*sizeof(char));
+    oDriver="GeoJSON";
+    if(tmpMap!=NULL){
+      if(strcmp(tmpMap->value,"text/xml")==0){
+	fprintf(stderr,"USEING GML \n");
+	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() );
+	  }
+	
+	fprintf(stderr,"{\"type\": \"error\", \"%s\"}",emessage);   
+	exit( 1 );
+      }
+
+    if( !poDriver->TestCapability( ODrCCreateDataSource ) ){
+      char emessage[1024];
+      sprintf( emessage,  "%s driver does not support data source creation.\n",
+	       "json" );
+      fprintf(stderr,"{\"type\": \"error\", \"%s\"}",emessage);   
+      exit( 1 );
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Create the output data source.                                  */
+    /* -------------------------------------------------------------------- */
+    map* tpath=getMapFromMaps(conf,"main","tmpPath");
+    char *pszDestDataSource=(char*)malloc(strlen(tpath->value)+20);
+    char **papszDSCO=NULL;
+    sprintf(pszDestDataSource,"%s/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 );
+      fprintf(stderr,"{\"type\": \"error\", \"%s\"}",emessage);   
+      exit( 1 );
+    }
+
+    /* -------------------------------------------------------------------- */
+    /*      Create the layer.                                               */
+    /* -------------------------------------------------------------------- */
+    if( !poODS->TestCapability( ODsCCreateLayer ) )
+      {
+	char emessage[1024];
+	sprintf( emessage, 
+		 "Layer %s not found, and CreateLayer not supported by driver.", 
+		 "Result" );
+	fprintf(stderr,"{\"type\": \"error\",\"message\": \"%s\"}",emessage);
+	return FALSE;
+      }
+    
+    CPLErrorReset();
+    
+    OGRLayer *poDstLayer = poODS->CreateLayer( "Result", NULL,wkbLineString,NULL);
+    if( poDstLayer == NULL ){
+      fprintf( stderr,"Layer creation failed.\n" );
+      exit( 1 );
+    }
+
+
+    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 K::Segment_2 *tmp=CGAL::object_cast<K::Segment_2>(&o)) {
+	const K::Point_2 p1=tmp->source();
+	const K::Point_2 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 ){
+	  fprintf( stderr,"Failed to create feature in file.\n" );
+	  exit( 1 );
+	}
+	OGR_F_Destroy( hFeature );
+	++ns ;
+      }
+      else if (CGAL::object_cast<K::Ray_2>(&o)) {++nr;}
+    }
+    OGR_DS_Destroy( poODS );
+    OGRCleanupAll();
+
+#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 tmp1[1024];
+    outputs=(maps*)malloc(sizeof(maps*));
+    outputs->name="Result";
+
+    FILE * fichier=fopen(pszDestDataSource,"r"); 
+    struct stat file_status;
+    stat(pszDestDataSource, &file_status);
+    //fprintf(stderr,"%s (%d)",pszDestDataSource,file_status.st_size);
+    char *res1=(char *)malloc(file_status.st_size*sizeof(char));
+    if(fichier==NULL)
+      fprintf(stderr,"Failed to open file %s for reading purpose.\n",pszDestDataSource);
+    fread(res1,1,(file_status.st_size)*sizeof(char),fichier);
+    res1[strlen(res1)]=0;
+    fclose(fichier);
+    unlink(pszDestDataSource);
+    //fprintf(stderr,"Read (%s).\n",res1);
+    
+    outputs->content=createMap("value",res1);
+    
+    if(strcmp(oDriver,"GML")==0)
+      addMapToMap(&outputs->content,createMap("mimeType","text/xml"));
+    else
+      addMapToMap(&outputs->content,createMap("mimeType","text/plain"));
+
+    addMapToMap(&outputs->content,createMap("encoding","UTF-8"));
+    outputs->next=NULL;
+    fprintf(stderr,"\nService internal print\n===\n");
+    xmlCleanupParser();
+    return SERVICE_SUCCEEDED;
+  }
+
+}
Index: trunk/zoo-services/gdal/grid/Makefile
===================================================================
--- trunk/zoo-services/gdal/grid/Makefile	(revision 1)
+++ trunk/zoo-services/gdal/grid/Makefile	(revision 1)
@@ -0,0 +1,8 @@
+CFLAGS=-I../../../zoo-kernel-svn/ -I./ `xml2-config --cflags` `python-config --cflags` -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 -lgdal
+
+clean:
+	rm -f cgi-env/*.zo
Index: trunk/zoo-services/gdal/grid/cgi-env/Gdal_Grid.zcfg
===================================================================
--- trunk/zoo-services/gdal/grid/cgi-env/Gdal_Grid.zcfg	(revision 1)
+++ trunk/zoo-services/gdal/grid/cgi-env/Gdal_Grid.zcfg	(revision 1)
@@ -0,0 +1,69 @@
+[Gdal_Grid]
+ Title = Convert raster data from one format to another. 
+ Abstract = Converts raster data between different formats.
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceType = C
+ serviceProvider = gdal_grid_service.zo
+ <MetaData lang="en">
+   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>  
Index: trunk/zoo-services/gdal/grid/service.c
===================================================================
--- trunk/zoo-services/gdal/grid/service.c	(revision 1)
+++ trunk/zoo-services/gdal/grid/service.c	(revision 1)
@@ -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@ak4719.spb.edu
+ *
+ * ****************************************************************************
+ * Copyright (c) 2007, Andrey Kiselev <dron@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(strcmp(mtoupper((char*)pszFormat),"AAIGRID")==0)
+        ext="csv";
+      else 
+        if(strcmp(mtoupper((char*)pszFormat),"PNG")==0)
+          ext="png";
+        else
+          if(strcmp(mtoupper((char*)pszFormat),"GIF")==0)
+            ext="gif";
+          else
+            if(strcmp(mtoupper((char*)pszFormat),"JPEG")==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
Index: trunk/zoo-services/gdal/translate/Makefile
===================================================================
--- trunk/zoo-services/gdal/translate/Makefile	(revision 1)
+++ trunk/zoo-services/gdal/translate/Makefile	(revision 1)
@@ -0,0 +1,9 @@
+CFLAGS=-I../../../zoo-kernel-svn/ -I./ `xml2-config --cflags` `python-config --cflags` -DLINUX_FREE_ISSUE #-DDEBUG
+CC=gcc
+
+cgi-env/service.zo: service.c
+	g++ ${CFLAGS} -shared -fpic -o cgi-env/service.zo ./service.c -lgdal
+
+clean:
+	rm -f *.zo *.o *.tab.c *.tab.h *.sr.c* service_loader lex.* *.lreg *.sibling
+	rm -rf service_loader.dSYM
Index: trunk/zoo-services/gdal/translate/cgi-env/Gdal_Translate.zcfg
===================================================================
--- trunk/zoo-services/gdal/translate/cgi-env/Gdal_Translate.zcfg	(revision 1)
+++ trunk/zoo-services/gdal/translate/cgi-env/Gdal_Translate.zcfg	(revision 1)
@@ -0,0 +1,57 @@
+[Gdal_Translate]
+ Title = Convert raster data from one format to another. 
+ Abstract = Converts raster data between different formats.
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceType = C
+ serviceProvider = gdal_service.zo
+ <MetaData lang="en">
+   Test = My Demo
+ </MetaData>
+ <DataInputs>
+  [Format]
+   Title = Format of the output data
+   Abstract = Select the output format.
+   minOccurs = 0
+   maxOccurs = 1
+   <LiteralData>
+    DataType = string
+    <Default>
+     value = AAIGrid
+    </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>
+     uom = feet
+    </Default>	
+   </LiteralData>
+  [OutputDataSourceName]
+   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>	
+   </LiteralData>
+ </DataInputs>
+ <DataOutputs>
+  [OutputedDataSourceName]
+   Title = The resulting converted file
+   Abstract = The file name resulting of the convertion
+   <LiteralData>
+    DataType = string
+    <Default>
+     uom = feet
+    </Default>	
+   </LiteralData>
+ </DataOutputs>  
Index: trunk/zoo-services/gdal/translate/service.c
===================================================================
--- trunk/zoo-services/gdal/translate/service.c	(revision 1)
+++ trunk/zoo-services/gdal/translate/service.c	(revision 1)
@@ -0,0 +1,825 @@
+/******************************************************************************
+ * $Id$
+ *
+ * Project:  GDAL Utilities
+ * Purpose:  GDAL Image Translator Program
+ * Author:   Frank Warmerdam, warmerdam@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()                            */
+  /************************************************************************/
+
+  int Gdal_Translate(maps*& conf,maps*& inputs,maps*& outputs)
+  {
+    
+    fprintf(stderr,"STARTING GDAL TRANSLATE\n");
+    fflush(stderr);
+
+    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*)malloc(sizeof(char)*(strlen(dataPath)+strlen(tmpMap->value)+4));
+      sprintf((char*)pszSource,"%s/%s.tif",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(strcmp(mtoupper((char*)pszFormat),"AAIGRID")==0)
+	ext="csv";
+      else 
+	if(strcmp(mtoupper((char*)pszFormat),"PNG")==0)
+	  ext="png";
+	else
+	  if(strcmp(mtoupper((char*)pszFormat),"GIF")==0)
+	    ext="gif";
+	  else
+	    if(strcmp(mtoupper((char*)pszFormat),"JPEG")==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,"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;
+	}
+	fprintf(stderr,"%s\n\n",t);
+	fprintf(stderr,"%f - %f - %f - %f\n\n",dfULX,dfULY,dfLRX,dfLRY);
+	t=strtok(NULL,",");
+	cnt++;
+      }
+    }
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"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 );
+	    /**
+	     * Avoiding GDALDestroyDriverManager() call
+	     */
+	  exit( 1 );
+	}
+      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,"==%s %s %s %==\n",pszFormat,pszSource,pszDest);
+    fflush(stderr);
+
+    if( pszDest == NULL ){
+	fprintf(stderr,"exit line 416");
+	fflush(stderr);
+	/**
+	 * Avoiding GDALDestroyDriverManager() call
+	 */
+        exit( 10 );
+      }
+
+    if ( strcmp(pszSource, pszDest) == 0)
+      {
+        fprintf(stderr, "Source and destination datasets must be different.\n");
+	fflush(stderr);
+	/**
+	 * Avoiding GDALDestroyDriverManager() call
+	 */
+        exit( 1 );
+      }
+
+    /* ----------------------------------------------------------------- */
+    /*      Attempt to open source file.                                 */
+    /* ----------------------------------------------------------------- */
+
+    hDataset = GDALOpenShared( pszSource, GA_ReadOnly );
+    
+    if( hDataset == NULL ){
+        fprintf( stderr,
+                 "GDALOpen failed - %d\n%s\n",
+                 CPLGetLastErrorNo(), CPLGetLastErrorMsg() );
+	fflush(stderr);
+	/**
+	 * Avoiding GDALDestroyDriverManager() call
+	 */
+        exit( 1 );
+      }
+
+    /* ----------------------------------------------------------------- */
+    /*      Handle subdatasets.                                          */
+    /* ----------------------------------------------------------------- */
+    if( !bCopySubDatasets 
+        && CSLCount(GDALGetMetadata( hDataset, "SUBDATASETS" )) > 0 
+        && GDALGetRasterCount(hDataset) == 0 )
+      {
+        fprintf( stderr,
+                 "Input file contains subdatasets. Please, select one of them for reading.\n" );
+	fflush(stderr);
+        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;
+        CPLFree( 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 )
+      printf( "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 );
+            CPLFree( 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;
+        
+        printf( "Output driver `%s' not recognised.\n", pszFormat );
+        printf( "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 )
+	      {
+                printf( "  %s: %s\n",
+                        GDALGetDriverShortName( hDriver  ),
+                        GDALGetDriverLongName( hDriver ) );
+	      }
+	  }
+        printf( "\n" );
+        
+        GDALClose( hDataset );
+        CPLFree( panBandList );
+	fflush(stderr);
+	/**
+	 * Avoiding GDALDestroyDriverManager() call
+	 */
+        CSLDestroy( papszCreateOptions );
+        exit( 1 );
+      }
+
+    /* ----------------------------------------------------------------- */
+    /*   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.                              */
+    /* ----------------------------------------------------------------- */
+    if( eOutputType == GDT_Unknown 
+        && !bScale && CSLCount(papszMetadataOptions) == 0 && bDefBands 
+        && anSrcWin[0] == 0 && anSrcWin[1] == 0 
+        && anSrcWin[2] == GDALGetRasterXSize(hDataset)
+        && anSrcWin[3] == GDALGetRasterYSize(hDataset) 
+        && pszOXSize == NULL && pszOYSize == NULL 
+        && nGCPCount == 0 && !bGotBounds
+        && pszOutputSRS == NULL && !bSetNoData
+        && nRGBExpand == 0)
+      {
+        
+        hOutDS = GDALCreateCopy( hDriver, pszDest, hDataset, 
+                                 bStrict, papszCreateOptions, 
+                                 pfnProgress, NULL );
+
+        if( hOutDS != NULL )
+	  GDALClose( hOutDS );
+        
+        GDALClose( hDataset );
+
+        CPLFree( panBandList );
+
+        if( !bSubCall )
+	  {
+            GDALDumpOpenDatasets( stderr );
+	    /**
+	     * Avoiding GDALDestroyDriverManager() call
+	     */
+	  }
+
+        CSLDestroy( papszCreateOptions );
+	outputs=(maps*)malloc(sizeof(maps*));
+	outputs->name="OutputedPolygon";
+	outputs->content=createMap("value",(char*)pszDest);
+	outputs->next=NULL;
+	
+	return SERVICE_SUCCEEDED;
+      }
+    fprintf(stderr,"==%s %s %s %==\n",pszFormat,pszSource,pszDest);
+    fflush(stderr);
+
+    /* ----------------------------------------------------------------- */
+    /*      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)));
+      }
+    fprintf(stderr,"==%s %s %s %==\n",pszFormat,pszSource,pszDest);
+    fflush(stderr);
+
+    /* ================================================================= */
+    /*      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 );
+        CPLFree( 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 );
+        CPLFree( pasGCPs );
+      }
+
+    /* ----------------------------------------------------------------- */
+    /*      Transfer generally applicable metadata.                      */
+    /* ----------------------------------------------------------------- */
+    poVDS->SetMetadata( ((GDALDataset*)hDataset)->GetMetadata() );
+    AttachMetadata( (GDALDatasetH) poVDS, papszMetadataOptions );
+    fprintf(stderr,"Transfer generally applicable metadata.\n");
+    fflush(stderr);
+
+    /* ----------------------------------------------------------------- */
+    /*      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 );
+                CPLFree( 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().                 */
+    /* ----------------------------------------------------------------- */
+    fprintf(stderr,"DEBUG pszDest %s\n",pszDest);
+    hOutDS = GDALCreateCopy( hDriver, pszDest, (GDALDatasetH) poVDS,
+                             bStrict, papszCreateOptions, 
+                             pfnProgress, NULL );
+    fprintf(stderr,"DEBUG pszDest %s\n",pszDest);
+    fflush(stderr);
+
+    if( hOutDS != NULL )
+      {
+        GDALClose( hOutDS );
+      }
+    
+    GDALClose( (GDALDatasetH) poVDS );
+        
+    GDALClose( hDataset );
+
+    CPLFree( panBandList );
+    
+    CPLFree( pszOutputSRS );
+
+    if( !bSubCall )
+      {
+        GDALDumpOpenDatasets( stderr );
+	fflush(stderr);
+	/**
+	 * Avoiding GDALDestroyDriverManager() call
+	 */
+      }
+
+    CSLDestroy( papszCreateOptions );
+    
+    outputs=(maps*)malloc(sizeof(maps*));
+    outputs->name="OutputedPolygon";
+    outputs->content=createMap("value",(char*)pszDest);
+    outputs->next=NULL;
+
+    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);
+        CPLFree( pszKey );
+      }
+
+    CSLDestroy( papszMetadataOptions );
+  }
+
+}
Index: trunk/zoo-services/hello-fotran/Makefile
===================================================================
--- trunk/zoo-services/hello-fotran/Makefile	(revision 1)
+++ trunk/zoo-services/hello-fotran/Makefile	(revision 1)
@@ -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
Index: trunk/zoo-services/hello-fotran/cgi-env/hellof.zcfg
===================================================================
--- trunk/zoo-services/hello-fotran/cgi-env/hellof.zcfg	(revision 1)
+++ trunk/zoo-services/hello-fotran/cgi-env/hellof.zcfg	(revision 1)
@@ -0,0 +1,49 @@
+[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 lang="en">
+   title = Demo
+ </MetaData>
+ <DataInputs>
+  [S]
+   Title = The string
+   Abstract = The name to display in the welcome message.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData lang="en">
+    title = Mon test  
+   </MetaData>   
+   <LiteralData>
+    DataType = string
+    <Default>
+     value = Your Name
+     UOM = meter
+    </Default>
+    <Supported>
+     UOM = meter
+    </Supported>
+   </LiteralData>
+ </DataInputs>
+ <DataOutputs>
+  [result]
+   Title = The string
+   Abstract = The string created by service.
+   <MetaData lang="en">
+    title = Mon test  
+   </MetaData>   
+   <LiteralData>
+    DataType = string
+    <Default>
+     UOM = meter
+    </Default>
+    <Supported>
+     UOM = meter
+    </Supported>
+   </LiteralData>
+ </DataOutputs>  
Index: trunk/zoo-services/hello-fotran/service.f
===================================================================
--- trunk/zoo-services/hello-fotran/service.f	(revision 1)
+++ trunk/zoo-services/hello-fotran/service.f	(revision 1)
@@ -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
+
Index: trunk/zoo-services/hello-java/HelloJava.java
===================================================================
--- trunk/zoo-services/hello-java/HelloJava.java	(revision 1)
+++ trunk/zoo-services/hello-java/HelloJava.java	(revision 1)
@@ -0,0 +1,38 @@
+/**
+ * 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 hm1 = new HashMap();
+        hm1.put("dataType","string");
+        HashMap tmp=(HashMap)(inputs.get("S"));
+        String v=tmp.get("value").toString();
+        hm1.put("value","Hello "+v+" from JAVA World !!");
+        outputs.put("Result",hm1);
+        return 3;
+  }
+}
Index: trunk/zoo-services/hello-java/cgi-env/HelloWorldJava.zcfg
===================================================================
--- trunk/zoo-services/hello-java/cgi-env/HelloWorldJava.zcfg	(revision 1)
+++ trunk/zoo-services/hello-java/cgi-env/HelloWorldJava.zcfg	(revision 1)
@@ -0,0 +1,41 @@
+[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>
+     UOM = meters
+    </Default>
+    <Supported>
+     UOM = feet
+    </Supported>
+   </LiteralData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = The hello string
+   Abstract = The Hello message string.
+   <LiteralOutput>
+    DataType = string
+    <Default>
+     UOM = meters
+    </Default>
+    <Supported>
+     UOM = feet
+    </Supported>
+   </LiteralOutput>
+ </DataOutputs>  
Index: trunk/zoo-services/hello-js/cgi-env/hellojs.zcfg
===================================================================
--- trunk/zoo-services/hello-js/cgi-env/hellojs.zcfg	(revision 1)
+++ trunk/zoo-services/hello-js/cgi-env/hellojs.zcfg	(revision 1)
@@ -0,0 +1,47 @@
+[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 lang="en">
+   title = Demo
+ </MetaData>
+ <DataInputs>
+  [S]
+   Title = Name
+   Abstract = The name to display in the hello message
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData lang="en">
+    title = Mon test  
+   </MetaData>   
+   <LiteralData>
+    DataType = string
+    <Default>
+     value = Your Name Here
+    </Default>
+    <Supported>
+     value = Your Name Here
+    </Supported>
+   </LiteralData>
+ </DataInputs>
+ <DataOutputs>
+  [result]
+   Title = The resulting string
+   Abstract = The string created by service.
+   <MetaData lang="en">
+    title = Mon test  
+   </MetaData>   
+   <LiteralOutput>
+    <Default>
+     datatype = string
+    </Default>
+    <Supported>
+     dataType = string
+    </Supported>
+   </LiteralOutput>
+ </DataOutputs>  
Index: trunk/zoo-services/hello-js/cgi-env/hellojs1.zcfg
===================================================================
--- trunk/zoo-services/hello-js/cgi-env/hellojs1.zcfg	(revision 1)
+++ trunk/zoo-services/hello-js/cgi-env/hellojs1.zcfg	(revision 1)
@@ -0,0 +1,47 @@
+[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 lang="en">
+   title = Demo
+ </MetaData>
+ <DataInputs>
+  [S]
+   Title = Name
+   Abstract = The name to display in the hello message
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData lang="en">
+    title = Mon test  
+   </MetaData>   
+   <LiteralData>
+    DataType = string
+    <Default>
+     value = Your Name Here
+    </Default>
+    <Supported>
+     value = Your Name Here
+    </Supported>
+   </LiteralData>
+ </DataInputs>
+ <DataOutputs>
+  [result]
+   Title = The resulting string
+   Abstract = The string created by service.
+   <MetaData lang="en">
+    title = Mon test  
+   </MetaData>   
+   <LiteralOutput>
+    <Default>
+     datatype = string
+    </Default>
+    <Supported>
+     dataType = string
+    </Supported>
+   </LiteralOutput>
+ </DataOutputs>  
Index: trunk/zoo-services/hello-js/hello.js
===================================================================
--- trunk/zoo-services/hello-js/hello.js	(revision 1)
+++ trunk/zoo-services/hello-js/hello.js	(revision 1)
@@ -0,0 +1,13 @@
+
+function hellojs(conf,inputs,outputs){
+	outputs[0]["result"]=["value"]="Hello "+inputs[0]["S"]["value"]+" from the JS World !";
+	//SERVICE_SUCEEDED
+	return Array(3,outputs);
+}
+
+function hellojs1(conf,inputs,outputs){
+	outputs[0]["result"]["value"]="Hello "+inputs[0]["S"]["value"]+" from the JS World !"];
+	//SERVICE_SUCEEDED
+	return {"result":3,"outputs": outputs};
+}
+
Index: trunk/zoo-services/hello-php/cgi-env/HelloPHP.zcfg
===================================================================
--- trunk/zoo-services/hello-php/cgi-env/HelloPHP.zcfg	(revision 1)
+++ trunk/zoo-services/hello-php/cgi-env/HelloPHP.zcfg	(revision 1)
@@ -0,0 +1,41 @@
+[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>
+     UOM = meters
+    </Default>
+    <Supported>
+     UOM = feet
+    </Supported>
+   </LiteralData>
+ </DataInputs>
+ <DataOutputs>
+  [Result]
+   Title = The hello string
+   Abstract = The Hello message string.
+   <LiteralOutput>
+    DataType = string
+    <Default>
+     UOM = meters
+    </Default>
+    <Supported>
+     UOM = feet
+    </Supported>
+   </LiteralOutput>
+ </DataOutputs>  
Index: trunk/zoo-services/hello-php/hello.php
===================================================================
--- trunk/zoo-services/hello-php/hello.php	(revision 1)
+++ trunk/zoo-services/hello-php/hello.php	(revision 1)
@@ -0,0 +1,9 @@
+<?
+
+function HelloPHP(&$main_conf,&$inputs,&$outputs){
+  $outputs=Array();
+  $outputs["Result"]["value"]="Hello ".$inputs[S][value]." from the PHP world !!";
+  return 3;
+}
+
+?>
Index: trunk/zoo-services/hello-py/cgi-env/HelloPy.zcfg
===================================================================
--- trunk/zoo-services/hello-py/cgi-env/HelloPy.zcfg	(revision 1)
+++ trunk/zoo-services/hello-py/cgi-env/HelloPy.zcfg	(revision 1)
@@ -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 lang="en">
+   title = Demo
+ </MetaData>
+ <DataInputs>
+  [a]
+   Title = Input string
+   Abstract = The name to display in the welcome message.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData lang="en">
+    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 lang="en">
+    title = My test
+   </MetaData>
+   <LiteralData>
+    DataType = string
+    <Default>
+     UOM = meter
+    </Default>
+    <Supported>
+     UOM = meter
+    </Supported>
+   </LiteralData>
+ </DataOutputs>
Index: trunk/zoo-services/hello-py/test_service.py
===================================================================
--- trunk/zoo-services/hello-py/test_service.py	(revision 1)
+++ trunk/zoo-services/hello-py/test_service.py	(revision 1)
@@ -0,0 +1,5 @@
+import sys
+def HelloPy(conf,inputs,outputs):
+	outputs["Result"]["value"]="Hello "+inputs["a"]["value"]+" from Python World !"
+	return 3
+
Index: trunk/zoo-services/ogr/base-vect-ops/Makefile
===================================================================
--- trunk/zoo-services/ogr/base-vect-ops/Makefile	(revision 1)
+++ trunk/zoo-services/ogr/base-vect-ops/Makefile	(revision 1)
@@ -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/service.zo: service.c
+	g++ ${CFLAGS} -shared -fpic -o cgi-env/ogr_service.zo ./service.c `gdal-config --libs`
+
+clean:
+	rm -f cgi-env/ogr_service.zo
Index: trunk/zoo-services/ogr/base-vect-ops/cgi-env/Boundary.zcfg
===================================================================
--- trunk/zoo-services/ogr/base-vect-ops/cgi-env/Boundary.zcfg	(revision 1)
+++ trunk/zoo-services/ogr/base-vect-ops/cgi-env/Boundary.zcfg	(revision 1)
@@ -0,0 +1,71 @@
+[Boundary]
+ Title = Compute 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_service.zo
+ serviceType = C
+ <MetaData>
+   Test = 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 lang="en">
+    Test = Mon test  
+   </MetaData>   
+   <ComplexData>
+    <Default>
+     mimeType = text/js
+     encoding = UTF-8
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Supported>
+   </ComplexData>
+  [BufferDistance]
+   Title = Buffer Distance
+   Abstract = Distance to be used to calculate buffer.
+   minOccurs = 0
+   maxOccurs = 1
+   <LiteralData>
+    DataType = float
+    <Default>
+     uom = meters
+    </Default>
+    <Supported>
+     uom = feet
+    </Supported>
+   </LiteralData>
+ </DataInputs>
+ <DataOutputs>
+  [Boundary]
+   Title = The geometry created
+   Abstract = The geometry containing the boundary of the geometry on which the method is invoked.
+   <MetaData lang="en">
+    Test1 = 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 = text/xml
+     encoding = base64
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Supported>
+    <Supported>
+     mimeType = text/js
+     encoding = UTF-8
+    </Supported>
+   </ComplexData>
+ </DataOutputs>  
Index: trunk/zoo-services/ogr/base-vect-ops/cgi-env/Buffer.zcfg
===================================================================
--- trunk/zoo-services/ogr/base-vect-ops/cgi-env/Buffer.zcfg	(revision 1)
+++ trunk/zoo-services/ogr/base-vect-ops/cgi-env/Buffer.zcfg	(revision 1)
@@ -0,0 +1,74 @@
+[Buffer]
+ Title = Create a buffer around a polygon. 
+ Abstract = Create 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_service.zo
+ serviceType = C
+ <MetaData lang="en">
+   Test = 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 lang="en">
+    Test = 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 = aplication/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>
+  [BufferedPolygon]
+   Title = Buffered Polygon
+   Abstract = GML stream describing the buffered polygon feature.
+   <MetaData lang="en">
+    Test1 = 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 = text/xml
+     encoding = base64
+     schema = http://fooa/gml/3.1.0/polygon.xsd
+    </Supported>
+    <Supported>
+     mimeType = application/json
+     encoding = UTF-8
+    </Supported>
+   </ComplexData>
+ </DataOutputs>  
Index: trunk/zoo-services/ogr/base-vect-ops/cgi-env/Centroid.zcfg
===================================================================
--- trunk/zoo-services/ogr/base-vect-ops/cgi-env/Centroid.zcfg	(revision 1)
+++ trunk/zoo-services/ogr/base-vect-ops/cgi-env/Centroid.zcfg	(revision 1)
@@ -0,0 +1,59 @@
+[Centroid]
+ Title = Get the centroid of a polygon. 
+ Abstract = Create 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:centroid
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = ogr_service.zo
+ serviceType = C
+ <MetaData lang="en">
+   Test = 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 lang="en">
+    Test = 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>
+  [Centroid]
+   Title = The Centroid
+   Abstract = JSON String / GML Entity of the centroid
+   <MetaData lang="en">
+    Test1 = Mon test  
+   </MetaData>   
+   <ComplexData>
+    <Default>
+     mimeType = text/js
+     encoding = UTF-8
+    </Default>
+    <Supported>
+     mimeType = text/xml
+     encoding = base64
+     schema = http://fooa/gml/3.1.0/point.xsd
+    </Supported>
+    <Supported>
+     mimeType = text/xml
+     encoding = UTF-8
+     schema = http://fooa/gml/3.1.0/point.xsd
+     asReference = true	
+    </Supported>
+   </ComplexData>
+ </DataOutputs>  
Index: trunk/zoo-services/ogr/base-vect-ops/cgi-env/ConvexHull.zcfg
===================================================================
--- trunk/zoo-services/ogr/base-vect-ops/cgi-env/ConvexHull.zcfg	(revision 1)
+++ trunk/zoo-services/ogr/base-vect-ops/cgi-env/ConvexHull.zcfg	(revision 1)
@@ -0,0 +1,53 @@
+[ConvexHull]
+ Title = Compute 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_service.zo
+ serviceType = C
+ <MetaData lang="en">
+   Test = 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 lang="en">
+   Test1 = 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 lang="en">
+    Test1 = 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>
+ </DataOutputs> 
Index: trunk/zoo-services/ogr/base-vect-ops/cgi-env/Difference.zcfg
===================================================================
--- trunk/zoo-services/ogr/base-vect-ops/cgi-env/Difference.zcfg	(revision 1)
+++ trunk/zoo-services/ogr/base-vect-ops/cgi-env/Difference.zcfg	(revision 1)
@@ -0,0 +1,73 @@
+[Difference]
+ Title = Compute 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_service.zo
+ serviceType = C
+ <MetaData>
+   Test = Demo
+ </MetaData>
+ <DataInputs>
+  [InputEntity1]
+   Title = the first geometry 
+   Abstract = the first geometry to compare against.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData lang="en">
+    Test = 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 lang="en">
+    Test = 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 lang="en">
+    Test1 = Mon test  
+   </MetaData>   
+    <ComplexData>
+     <Default>
+       mimeType = application/json
+       encoding = UTF-8
+     </Default>
+     <Supported>
+      mimeType = text/xml
+      schema = http://fooa/gml/3.1.0/polygon.xsd
+      encoding = UTF-8
+     </Supported>
+    </ComplexData>
+ </DataOutputs>  
Index: trunk/zoo-services/ogr/base-vect-ops/cgi-env/Distance.zcfg
===================================================================
--- trunk/zoo-services/ogr/base-vect-ops/cgi-env/Distance.zcfg	(revision 1)
+++ trunk/zoo-services/ogr/base-vect-ops/cgi-env/Distance.zcfg	(revision 1)
@@ -0,0 +1,71 @@
+[Distance]
+ Title = Calcul la distance entre deux entites geographique. 
+ Abstract = Calcul de la distance entre deux entites geographique. 
+ Profile = urn:ogc:wps:1.0.0:buffer
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = ogr_service.zo
+ serviceType = C
+ <MetaData>
+   Test = Demo
+ </MetaData>
+ <DataInputs>
+  [InputEntity1]
+   Title = the first geometry 
+   Abstract = the first geometry to compare against.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData lang="en">
+    Test = 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 lang="en">
+    Test = 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 lang="en">
+    Test1 = Mon test  
+   </MetaData>   
+    <LiteralData>
+     DataType = float
+     <Default>
+      uom = meters
+     </Default>
+     <Supported>
+      uom = feet
+     </Supported>
+    </LiteralData>
+ </DataOutputs>  
Index: trunk/zoo-services/ogr/base-vect-ops/cgi-env/GetArea.zcfg
===================================================================
--- trunk/zoo-services/ogr/base-vect-ops/cgi-env/GetArea.zcfg	(revision 1)
+++ trunk/zoo-services/ogr/base-vect-ops/cgi-env/GetArea.zcfg	(revision 1)
@@ -0,0 +1,50 @@
+[GetArea]
+ Title = Compute geometry area.
+ Abstract = Computes the area for a geometry
+ processVersion = 2
+ storeSupported = true
+ statusSupported = true
+ serviceProvider = ogr_service.zo
+ serviceType = C
+ <MetaData lang="en">
+   Test = 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 lang="en">
+   Test1 = 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 lang="en">
+    Test1 = Mon test  
+   </MetaData>   
+   <LiteralData>
+    DataType = float
+    <Default>
+     uom = degree
+    </Default>
+    <Supported>
+     uom = meter
+    </Supported>
+   </LiteralData>
+ </DataOutputs> 
Index: trunk/zoo-services/ogr/base-vect-ops/cgi-env/Intersection.zcfg
===================================================================
--- trunk/zoo-services/ogr/base-vect-ops/cgi-env/Intersection.zcfg	(revision 1)
+++ trunk/zoo-services/ogr/base-vect-ops/cgi-env/Intersection.zcfg	(revision 1)
@@ -0,0 +1,73 @@
+[Intersection]
+ 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
+ <MetaData>
+   Test = Demo
+ </MetaData>
+ <DataInputs>
+  [InputEntity1]
+   Title = the first geometry 
+   Abstract = the first geometry to compare against.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData lang="en">
+    Test = 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 lang="en">
+    Test = 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 lang="en">
+    Test1 = Mon test  
+   </MetaData>   
+    <ComplexData>
+     <Default>
+       mimeType = application/json
+       encoding = UTF-8
+     </Default>
+     <Supported>
+      mimeType = text/xml
+      schema = http://fooa/gml/3.1.0/polygon.xsd
+      encoding = UTF-8
+     </Supported>
+    </ComplexData>
+ </DataOutputs>  
Index: trunk/zoo-services/ogr/base-vect-ops/cgi-env/SymDifference.zcfg
===================================================================
--- trunk/zoo-services/ogr/base-vect-ops/cgi-env/SymDifference.zcfg	(revision 1)
+++ trunk/zoo-services/ogr/base-vect-ops/cgi-env/SymDifference.zcfg	(revision 1)
@@ -0,0 +1,73 @@
+[SymDifference]
+ Title = Compute 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_service.zo
+ serviceType = C
+ <MetaData>
+   Test = Demo
+ </MetaData>
+ <DataInputs>
+  [InputEntity1]
+   Title = the first geometry 
+   Abstract = the first geometry to compare against.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData lang="en">
+    Test = 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 lang="en">
+    Test = 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 lang="en">
+    Test1 = Mon test  
+   </MetaData>   
+    <ComplexData>
+     <Default>
+       mimeType = application/json
+       encoding = UTF-8
+     </Default>
+     <Supported>
+      mimeType = text/xml
+      schema = http://fooa/gml/3.1.0/polygon.xsd
+      encoding = UTF-8
+     </Supported>
+    </ComplexData>
+ </DataOutputs>  
Index: trunk/zoo-services/ogr/base-vect-ops/cgi-env/Union.zcfg
===================================================================
--- trunk/zoo-services/ogr/base-vect-ops/cgi-env/Union.zcfg	(revision 1)
+++ trunk/zoo-services/ogr/base-vect-ops/cgi-env/Union.zcfg	(revision 1)
@@ -0,0 +1,73 @@
+[Union]
+ Title = Compute 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_service.zo
+ serviceType = C
+ <MetaData>
+   Test = Demo
+ </MetaData>
+ <DataInputs>
+  [InputEntity1]
+   Title = the first geometry 
+   Abstract = the first geometry to compare against.
+   minOccurs = 1
+   maxOccurs = 1
+   <MetaData lang="en">
+    Test = 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 lang="en">
+    Test = 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 lang="en">
+    Test1 = Mon test  
+   </MetaData>   
+    <ComplexData>
+     <Default>
+       mimeType = application/json
+       encoding = UTF-8
+     </Default>
+     <Supported>
+      mimeType = text/xml
+      schema = http://fooa/gml/3.1.0/polygon.xsd
+      encoding = UTF-8
+     </Supported>
+    </ComplexData>
+ </DataOutputs>  
Index: trunk/zoo-services/ogr/base-vect-ops/makefile.vc
===================================================================
--- trunk/zoo-services/ogr/base-vect-ops/makefile.vc	(revision 1)
+++ trunk/zoo-services/ogr/base-vect-ops/makefile.vc	(revision 1)
@@ -0,0 +1,11 @@
+GEODIR=c:/OSGeo4W/
+TOOLS=c:/Users/djay/GeoLabs/tools/
+CFLAGS=-I$(GEODIR)/include -I$(TOOLS)/include -I../../../zoo-kernel/ -I./ -DLINUX_FREE_ISSUE -DDEBUG
+CPP=cl /TP 
+
+cgi-env/service.zo: service.c
+	$(CPP) $(CFLAGS) /c service.c
+	link /dll /out:cgi-env/ogr_service.zso ../../../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
Index: trunk/zoo-services/ogr/base-vect-ops/service.c
===================================================================
--- trunk/zoo-services/ogr/base-vect-ops/service.c	(revision 1)
+++ trunk/zoo-services/ogr/base-vect-ops/service.c	(revision 1)
@@ -0,0 +1,620 @@
+/**
+ * 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_minixml.h"
+#include "ogr_api.h"
+#include "service.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>
+
+  xmlNodeSet* extractFromDoc(xmlDocPtr,char*);
+  void printExceptionReportResponse(maps*,map*);
+  char *base64(const unsigned 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;
+    char * xpathExpr="/*/*/*/*/*[local-name()='Polygon' or local-name()='MultiPolygon']";
+    xpathCtx = xmlXPathNewContext(doc);
+    xpathObj = xmlXPathEvalExpression(BAD_CAST xpathExpr,xpathCtx);
+    if(!xpathObj->nodesetval){
+      map* tmp=createMap("text","Unable to parse Input Polygon");
+      addToMap(tmp,"code","InvalidParameterValue");
+      printExceptionReportResponse(conf,tmp);
+      exit(0);
+    }
+    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=strdup(strstr((char*)xmlbuff,"?>")+2);
+    xmlXPathFreeObject(xpathObj);
+    xmlXPathFreeContext(xpathCtx); 
+    xmlFree(xmlbuff);
+    xmlFreeDoc(doc);
+    xmlCleanupParser();
+#ifdef DEBUG
+    fprintf(stderr,"\nService internal print\n Loading the geometry from GML string ...");
+#endif
+    OGRGeometryH res=OGR_G_CreateFromGML(tmp);
+    if(res==NULL){
+    	map* tmp=createMap("text","Unable to call OGR_G_CreatFromGML");
+	addToMap(tmp,"code","NoApplicableCode");
+	printExceptionReportResponse(conf,tmp);
+	exit(0);
+    }
+    else
+    	return OGR_G_CreateFromGML(tmp);
+  }
+
+  int applyTwo(maps*& conf,maps*& inputs,maps*& outputs,OGRGeometryH (*myFunc)(OGRGeometryH,OGRGeometryH)){
+#ifdef DEBUG
+    fprintf(stderr,"\nService internal print1\n");
+#endif
+    fflush(stderr);
+
+    maps* cursor=inputs;
+    OGRGeometryH geometry1,geometry2;
+    OGRGeometryH res;
+    {
+      map* tmp=getMapFromMaps(inputs,"InputEntity1","value");
+      map* tmp1=getMapFromMaps(inputs,"InputEntity1","mimeType");
+      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);
+    }
+    {
+      map* tmp=getMapFromMaps(inputs,"InputEntity2","value");
+      map* tmp1=getMapFromMaps(inputs,"InputEntity2","mimeType");
+#ifdef DEBUG
+      fprintf(stderr,"MY MAP\n");
+      dumpMap(tmp1);
+      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);
+    }
+    res=(*myFunc)(geometry1,geometry2);
+    outputs=(maps*)malloc(sizeof(maps*));
+    outputs->name="Result";
+    char tmpres[100];
+    sprintf(tmpres,"%d",res);
+    outputs->content=createMap("value",OGR_G_ExportToJson(res));
+    addMapToMap(&outputs->content,createMap("mimeType","text/plain"));
+    addMapToMap(&outputs->content,createMap("encoding","UTF-8"));
+    outputs->next=NULL;
+    return SERVICE_SUCCEEDED;
+  }
+
+#ifdef WIN32
+  __declspec(dllexport)
+#endif
+  int Difference(maps*& conf,maps*& inputs,maps*& outputs){
+    return applyTwo(conf,inputs,outputs,&OGR_G_Difference);
+  }
+
+#ifdef WIN32
+  __declspec(dllexport)
+#endif
+  int SymDifference(maps*& conf,maps*& inputs,maps*& outputs){
+    return applyTwo(conf,inputs,outputs,&OGR_G_SymmetricDifference);
+  }
+
+#ifdef WIN32
+  __declspec(dllexport)
+#endif
+  int Intersection(maps*& conf,maps*& inputs,maps*& outputs){
+    return applyTwo(conf,inputs,outputs,&OGR_G_Intersection);
+  }
+
+  int applyOne(maps*& conf,maps*& inputs,maps*& outputs,OGRGeometryH (*myFunc)(OGRGeometryH)){
+#ifdef DEBUG
+    fprintf(stderr,"\nService internal print\n");
+#endif
+    maps* cursor=inputs;
+    OGRGeometryH geometry,res;
+    int bufferDistance;
+#ifdef DEBUG
+    dumpMaps(cursor);
+#endif
+    map* tmp=getMapFromMaps(inputs,"InputPolygon","value");
+    if(!tmp)
+      return SERVICE_FAILED;
+    map* tmp1=getMapFromMaps(inputs,"InputPolygon","mimeTime");
+    if(tmp1!=NULL){
+      if(strncmp(tmp1->value,"text/js",7)==0)
+        geometry=OGR_G_CreateGeometryFromJson(tmp->value);
+      else
+        geometry=createGeometryFromGML(conf,tmp->value);
+      }
+    else
+      geometry=createGeometryFromGML(conf,tmp->value);
+    res=(*myFunc)(geometry);
+    /**
+     * Here we should check what is the requested output.
+     * Let's use JSON per default.
+     */
+    //outputs=(maps*)malloc(sizeof(maps*));
+    outputs->name="Result";
+    if(tmp1!=NULL){
+      if(strncmp(tmp1->value,"text/js",7)==0){
+        outputs->content=createMap("value",OGR_G_ExportToJson(tmp->value));
+	addMapToMap(&outputs->content,createMap("mimeType","text/plain"));
+	addMapToMap(&outputs->content,createMap("encoding","UTF-8"));
+      }
+      else{
+        outputs->content=createMap("value",OGR_G_ExportToGML(res));
+	addMapToMap(&outputs->content,createMap("mimeType","text/xml"));
+	addMapToMap(&outputs->content,createMap("encoding","UTF-8"));
+	addMapToMap(&outputs->content,createMap("schema","http://fooa/gml/3.1.0/polygon.xsd"));
+      }
+    }else{
+      outputs->content=createMap("value",OGR_G_ExportToJson(res));
+      addMapToMap(&outputs->content,createMap("mimeType","text/plain"));
+      addMapToMap(&outputs->content,createMap("encoding","UTF-8"));
+    }
+    outputs->next=NULL;
+#ifdef DEBUG
+    dumpMaps(outputs);
+    fprintf(stderr,"\nService internal print\n===\n");
+#endif
+    return SERVICE_SUCCEEDED;
+  }
+
+#ifdef WIN32
+  __declspec(dllexport)
+#endif
+  int ConvexHull(maps*& conf,maps*& inputs,maps*& outputs){
+    return applyOne(conf,inputs,outputs,&OGR_G_ConvexHull);
+  }
+
+#ifdef WIN32
+  __declspec(dllexport)
+#endif
+  int Boundary(maps*& conf,maps*& inputs,maps*& outputs){
+#ifdef DEBUG
+    fprintf(stderr,"\nService internal print\nStarting\n");
+#endif
+    maps* cursor=inputs;
+    OGRGeometryH geometry,res;
+    int bufferDistance;
+    xmlInitParser();
+    
+    if(cursor!=NULL){
+      map* tmp=getMapFromMaps(inputs,"InputPolygon","value");
+      map* tmp1=getMapFromMaps(inputs,"InputPolygon","mimeType");
+      if(tmp1!=NULL){
+        if(strncmp(tmp1->value,"text/js",7)==0)
+      	  geometry=OGR_G_CreateGeometryFromJson(tmp->value);
+	else
+	  geometry=createGeometryFromGML(conf,tmp->value);
+      }
+      else
+      	geometry=createGeometryFromGML(conf,tmp->value);
+    }
+    res=OGR_G_GetBoundary(geometry);
+    outputs=(maps*)malloc(sizeof(maps*));
+    outputs->name="Boundary";
+    outputs->content=createMap("value",OGR_G_ExportToJson(res));
+    addMapToMap(&outputs->content,createMap("mimeType","text/plain"));
+    addMapToMap(&outputs->content,createMap("encoding","UTF-8"));
+    /*
+    outputs->content=createMap("value",OGR_G_ExportToGML(res));
+    addMapToMap(&outputs->content,createMap("mimeType","text/xml"));
+    addMapToMap(&outputs->content,createMap("encoding","UTF-8"));
+    addMapToMap(&outputs->content,createMap("schema","http://fooa/gml/3.1.0/polygon.xsd"));
+    */
+    outputs->next=NULL;
+#ifdef DEBUG
+    fprintf(stderr,"\nService internal print\n===\n");
+#endif
+    xmlCleanupParser();
+    return SERVICE_SUCCEEDED;
+    }
+
+#ifdef WIN32
+  __declspec(dllexport)
+#endif
+  int Centroid(maps*& conf,maps*& inputs,maps*& outputs){
+#ifdef DEBUG
+    fprintf(stderr,"\nService internal print\n");
+#endif
+    maps* cursor=inputs;
+    OGRGeometryH geometry,res=NULL;
+    int bufferDistance;    
+    if(cursor!=NULL){
+#ifdef DEBUG
+      fprintf(stderr,"\nService internal print\n");
+      dumpMaps(cursor);
+      fprintf(stderr,"\nService internal print\n");
+      dumpMaps(inputs);
+      fprintf(stderr,"\nService internal print\n");
+#endif
+      map* tmp=getMapFromMaps(inputs,"InputPolygon","value");
+      map* tmp1=getMapFromMaps(inputs,"InputPolygon","mimeType");
+      if(tmp1!=NULL){
+        if(strncmp(tmp1->value,"application/json",16)==0)
+      	  geometry=OGR_G_CreateGeometryFromJson(tmp->value);
+	else
+	  geometry=createGeometryFromGML(conf,tmp->value);
+      }
+      else
+      	geometry=createGeometryFromGML(conf,tmp->value);
+    }else{
+    /**
+     * Print WPSExceptionError message here !!
+     */
+    }
+#ifdef DEBUG
+    dumpMaps(outputs);
+#endif
+    res=OGR_G_CreateGeometryFromJson("{\"type\": \"Point\", \"coordinates\": [0,0] }");
+    OGRwkbGeometryType gtype=OGR_G_GetGeometryType(geometry);
+    if(gtype!=wkbPolygon){
+    	fprintf(stderr,"\n\nGeometry Type is not Polygon, let us use the ConvexHull !\n\n");
+    	geometry=OGR_G_ConvexHull(OGR_G_Clone(geometry));
+    }else{
+    	fprintf(stderr,"\n\nGeometry Type is Polygon, thanks !\n\n");
+    }
+    int c=OGR_G_Centroid(geometry,res);
+#ifdef DEBUG
+    fprintf(stderr,"\n\nC VALUE : %d\n\n",c);
+#endif
+    map* tmp=getMapFromMaps(outputs,"Result","mimeType");
+#ifdef DEBUG
+    dumpMaps(outputs);
+#endif
+    if(tmp!=NULL){
+#ifdef DEBUG
+      dumpMap(tmp);
+#endif
+      if(strncmp(mtoupper(tmp->value),mtoupper("application/json"),16)==0){
+	outputs->content=createMap("value",OGR_G_ExportToJson(res));
+	addMapToMap(&outputs->content,createMap("mimeType","text/plain"));
+	addMapToMap(&outputs->content,createMap("encoding","UTF-8"));
+      }
+      else if(strncmp(mtoupper(tmp->value),mtoupper("text/xml"),8)==0){
+	/*xmlInitParser();
+	xmlDocPtr doc = xmlParseMemory(tmp->value,strlen(tmp->value));
+	xmlChar *xmlbuff;
+	int buffersize;*/
+	outputs->content=createMap("value",OGR_G_ExportToGML(res));
+	addMapToMap(&outputs->content,createMap("mimeType","text/xml"));
+	map* tmp1=getMapFromMaps(outputs,"Result","encoding");
+	if(tmp1!=NULL)
+	  addMapToMap(&outputs->content,createMap("encoding",tmp1->value));
+	else
+	  addMapToMap(&outputs->content,createMap("encoding","UTF-8"));
+	/*xmlDocDumpFormatMemory(doc, &xmlbuff, &buffersize, 1);
+	outputs->content=createMap("value",OGR_G_ExportToGML(res));
+	xmlFree(xmlbuff);
+	xmlFreeDoc(doc);
+	xmlCleanupParser();
+	*/
+      }
+    else{
+      outputs=(maps*)malloc(sizeof(maps*));
+      outputs->name="Result";
+      outputs->content=createMap("value",OGR_G_ExportToJson(res));
+      addMapToMap(&outputs->content,createMap("mimeType","text/plain"));
+      addMapToMap(&outputs->content,createMap("encoding","UTF-8"));
+      outputs->next=NULL;
+    }
+    outputs->next=NULL;
+    }
+    else{
+      outputs=(maps*)malloc(sizeof(maps*));
+      outputs->name="Result";
+      outputs->content=createMap("value",OGR_G_ExportToJson(res));
+      addMapToMap(&outputs->content,createMap("mimeType","text/plain"));
+      addMapToMap(&outputs->content,createMap("encoding","UTF-8"));
+      outputs->next=NULL;
+    }
+    outputs->next=NULL;
+#ifdef DEBUG
+    dumpMaps(outputs);
+    fprintf(stderr,"\nService internal print\n===\n");
+#endif
+    return SERVICE_SUCCEEDED;
+  }
+
+#ifdef WIN32
+  __declspec(dllexport)
+#endif
+  int Buffer(maps*& conf,maps*& inputs,maps*& outputs){
+#ifdef DEBUG
+    fprintf(stderr,"\nService internal print\n");
+#endif
+    maps* cursor=inputs;
+    OGRGeometryH geometry,res;
+    int bufferDistance;    
+    if(cursor!=NULL){
+#ifdef DEBUG
+      fprintf(stderr,"\nService internal print\n");
+      dumpMaps(cursor);
+      fprintf(stderr,"\nService internal print\n");
+      dumpMaps(inputs);
+      fprintf(stderr,"\nService internal print\n");
+#endif
+      map* tmp=getMapFromMaps(inputs,"InputPolygon","value");
+      map* tmp1=getMapFromMaps(inputs,"InputPolygon","mimeType");
+      if(tmp1!=NULL){
+        if(strncmp(tmp1->value,"application/json",16)==0)
+      	  geometry=OGR_G_CreateGeometryFromJson(tmp->value);
+	else
+	  geometry=createGeometryFromGML(conf,tmp->value);
+      }
+      else
+      	geometry=createGeometryFromGML(conf,tmp->value);
+    }
+    if(cursor!=NULL){
+      map* tmp=getMapFromMaps(cursor,"BufferDistance","value");
+      if(tmp==NULL){
+	bufferDistance=10;
+      }
+      else
+	bufferDistance=atoi(tmp->value);
+#ifdef DEBUG
+      fprintf(stderr,"\nService internal print (BufferDistance value: %i)\n",bufferDistance);
+#endif
+    }
+#ifdef DEBUG
+    dumpMaps(outputs);
+#endif
+    map* tmp=getMapFromMaps(outputs,"BufferedPolygon","mimeType");
+    res=OGR_G_Buffer(geometry,bufferDistance,30);
+#ifdef DEBUG
+    dumpMap(tmp);
+#endif
+    if(tmp!=NULL){
+#ifdef DEBUG
+      dumpMap(tmp);
+#endif
+      if(strncmp(mtoupper(tmp->value),mtoupper("application/json"),16)==0){
+	outputs->content=createMap("value",OGR_G_ExportToJson(res));
+	addMapToMap(&outputs->content,createMap("mimeType","text/plain"));
+	addMapToMap(&outputs->content,createMap("encoding","UTF-8"));
+      }
+      else if(strcmp(mtoupper(tmp->value),mtoupper("text/xml"))==0){
+	xmlInitParser();
+	xmlDocPtr doc = xmlParseMemory(tmp->value,strlen(tmp->value));
+	xmlChar *xmlbuff;
+	int buffersize;
+	outputs->content=createMap("value",OGR_G_ExportToGML(res));
+	addMapToMap(&outputs->content,createMap("mimeType","text/xml"));
+	map* tmp1=getMapFromMaps(outputs,"BufferedPolygon","encoding");
+	if(tmp1!=NULL)
+	  addMapToMap(&outputs->content,createMap("encoding",tmp1->value));
+	else
+	  addMapToMap(&outputs->content,createMap("encoding","UTF-8"));
+	xmlDocDumpFormatMemory(doc, &xmlbuff, &buffersize, 1);
+	outputs->content=createMap("value",OGR_G_ExportToGML(res));
+	xmlFree(xmlbuff);
+	xmlFreeDoc(doc);
+	xmlCleanupParser();
+      }
+    else{
+      outputs=(maps*)malloc(sizeof(maps*));
+      outputs->name="BufferedPolygon";
+      outputs->content=createMap("value",OGR_G_ExportToJson(res));
+      addMapToMap(&outputs->content,createMap("mimeType","text/plain"));
+      addMapToMap(&outputs->content,createMap("encoding","UTF-8"));
+      outputs->next=NULL;
+    }
+    outputs->next=NULL;
+    }
+    else{
+      outputs=(maps*)malloc(sizeof(maps*));
+      outputs->name="BufferedPolygon";
+      outputs->content=createMap("value",OGR_G_ExportToJson(res));
+      addMapToMap(&outputs->content,createMap("mimeType","text/plain"));
+      addMapToMap(&outputs->content,createMap("encoding","UTF-8"));
+      outputs->next=NULL;
+    }
+    outputs->next=NULL;
+#ifdef DEBUG
+    dumpMaps(outputs);
+    fprintf(stderr,"\nService internal print\n===\n");
+#endif
+    return SERVICE_SUCCEEDED;
+  }
+
+#ifdef WIN32
+  __declspec(dllexport)
+#endif
+  int Union(maps*& conf,maps*& inputs,maps*& outputs){
+#ifdef DEBUG
+    fprintf(stderr,"\nService internal print1\n");
+    fflush(stderr);
+#endif
+    maps* cursor=inputs;
+    OGRGeometryH geometry1,geometry2;
+    OGRGeometryH res;
+    {
+      map* tmp=getMapFromMaps(inputs,"InputEntity1","value");
+      map* tmp1=getMapFromMaps(inputs,"InputEntity1","mimeType");
+      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);
+    }
+    {
+      map* tmp=getMapFromMaps(inputs,"InputEntity2","value");
+      map* tmp1=getMapFromMaps(inputs,"InputEntity2","mimeType");
+#ifdef DEBUG
+      fprintf(stderr,"MY MAP\n");
+      dumpMap(tmp1);
+      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);
+    }
+    res=OGR_G_Union(geometry1,geometry2);
+    outputs=(maps*)malloc(sizeof(maps*));
+    outputs->name="Result";
+    char tmpres[100];
+    sprintf(tmpres,"%d",res);
+    outputs->content=createMap("value",OGR_G_ExportToJson(res));
+    addMapToMap(&outputs->content,createMap("mimeType","text/plain"));
+    addMapToMap(&outputs->content,createMap("encoding","UTF-8"));
+    outputs->next=NULL;
+    return SERVICE_SUCCEEDED;
+  }
+
+#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);
+    }
+    {
+      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);
+    }
+    res=OGR_G_Distance(geometry1,geometry2);
+    outputs=(maps*)malloc(sizeof(maps*));
+    outputs->name="Distance";
+    char tmpres[100];
+    sprintf(tmpres,"%d",res);
+    outputs->content=createMap("value",tmpres);
+    addMapToMap(&outputs->content,createMap("datatype","float"));
+    outputs->next=NULL;
+#ifdef DEBUG
+    dumpMaps(outputs);
+    fprintf(stderr,"\nService internal print\n===\n");
+#endif
+    return SERVICE_SUCCEEDED;
+  }
+
+  int GetArea(maps*& conf,maps*& inputs,maps*& outputs){
+    fprintf(stderr,"GETAREA \n");
+    double res;
+    /**
+     * Extract Geometry from the InputEntity1 value
+     */
+    OGRGeometryH geometry1;
+    map* tmp=getMapFromMaps(inputs,"InputEntity1","value");
+    fprintf(stderr,"geometry creation %s \n",tmp->value);
+    geometry1=createGeometryFromGML(conf,tmp->value);
+    fprintf(stderr,"geometry created %s \n",tmp->value);
+    res=OGR_G_GetArea(geometry1);
+    fprintf(stderr,"area %d \n",res);
+    /**
+     * Creating the outputs
+     */
+    outputs=(maps*)malloc(sizeof(maps*));
+    outputs->name="Area";
+    char tmp1[100];
+    sprintf(tmp1,"%d",res);
+    outputs->content=createMap("value",tmp1);
+    addMapToMap(&outputs->content,createMap("datatype","float"));
+    outputs->next=NULL;
+#ifdef DEBUG
+    dumpMaps(outputs);
+#endif
+    return SERVICE_SUCCEEDED;
+  }
+
+}
Index: trunk/zoo-services/ogr/ogr2ogr/Makefile
===================================================================
--- trunk/zoo-services/ogr/ogr2ogr/Makefile	(revision 1)
+++ trunk/zoo-services/ogr/ogr2ogr/Makefile	(revision 1)
@@ -0,0 +1,9 @@
+GDAL_SRC=/var/tmp/portage/sci-libs/gdal-1.6.1/work/gdal-1.6.1/ogr/
+CFLAGS=-I$(GDAL_SRC) -I../../../zoo-kernel-svn/ -I./ `xml2-config --cflags` `python-config --cflags` -DLINUX_FREE_ISSUE #-DDEBUG
+CC=gcc
+
+cgi-env/ogr2ogr_service.zo: service.c
+	g++  -DZOO_SERVICE ${CFLAGS} -shared -fpic -o cgi-env/ogr2ogr_service.zo ./service.c -lgdal
+
+clean:
+	rm -f cgi-env/*.zo
Index: trunk/zoo-services/ogr/ogr2ogr/cgi-env/Ogr2Ogr.zcfg
===================================================================
--- trunk/zoo-services/ogr/ogr2ogr/cgi-env/Ogr2Ogr.zcfg	(revision 1)
+++ trunk/zoo-services/ogr/ogr2ogr/cgi-env/Ogr2Ogr.zcfg	(revision 1)
@@ -0,0 +1,69 @@
+[Ogr2Ogr]
+ Title = Convert raster data from one format to another. 
+ Abstract = Converts raster data between different formats.
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceType = C
+ serviceProvider = ogr2ogr_service.zo
+ <MetaData lang="en">
+   title = My Demo
+ </MetaData>
+ <DataInputs>
+  [F]
+   Title = Format of the input data
+   Abstract = Select the input 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>  
Index: trunk/zoo-services/ogr/ogr2ogr/makefile.vc
===================================================================
--- trunk/zoo-services/ogr/ogr2ogr/makefile.vc	(revision 1)
+++ trunk/zoo-services/ogr/ogr2ogr/makefile.vc	(revision 1)
@@ -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
Index: trunk/zoo-services/ogr/ogr2ogr/service.c
===================================================================
--- trunk/zoo-services/ogr/ogr2ogr/service.c	(revision 1)
+++ trunk/zoo-services/ogr/ogr2ogr/service.c	(revision 1)
@@ -0,0 +1,1222 @@
+/******************************************************************************
+ * $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@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 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 = FALSE;
+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;
+    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;
+
+    /* 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");
+		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;
+    tmpMap=getMapFromMaps(inputs,"F","value");
+    if(tmpMap!=NULL){
+      pszFormat=tmpMap->value;
+    }
+
+	tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"DSCO","value");
+    if(tmpMap!=NULL){
+	  papszDSCO = CSLAddString(papszDSCO, tmpMap->value );
+    }
+
+	tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"LCO","value");
+    if(tmpMap!=NULL){
+	  papszLCO = CSLAddString(papszLCO, tmpMap->value );
+    }
+
+	tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"LCO","value");
+    if(tmpMap!=NULL){
+	  papszLCO = CSLAddString(papszLCO, tmpMap->value );
+    }
+
+	tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"preserve_fid","value");
+    if(tmpMap!=NULL){
+	  bPreserveFID = TRUE;
+    }
+
+	tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"skipfailure","value");
+    if(tmpMap!=NULL){
+	  bPreserveFID = TRUE;
+	  bSkipFailures = TRUE;
+	  nGroupTransactions = 1; /* #2409 */
+	}
+
+	tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"append","value");
+    if(tmpMap!=NULL){
+	  bAppend = TRUE;
+	}
+
+	tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"overwrite","value");
+    if(tmpMap!=NULL){
+	  bOverwrite = TRUE;
+	}
+
+	tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"update","value");
+    if(tmpMap!=NULL){
+	  bUpdate = TRUE;
+	}
+
+	tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"fid","value");
+    if(tmpMap!=NULL){
+	  nFIDToFetch = atoi(tmpMap->value);
+	}
+
+	tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"sql","value");
+    if(tmpMap!=NULL){
+	  pszSQLStatement = tmpMap->value;
+	}
+
+	tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"nln","value");
+    if(tmpMap!=NULL){
+	  pszNewLayerName = tmpMap->value;
+	}
+
+	tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"nlt","value");
+    if(tmpMap!=NULL){
+	  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){
+	  nGroupTransactions = atoi(tmpMap->value);
+	}
+
+	tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"s_srs","value");
+    if(tmpMap!=NULL){
+	  pszSourceSRSDef = tmpMap->value;
+	}
+
+	tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"s_srs","value");
+    if(tmpMap!=NULL){
+	  pszSourceSRSDef = tmpMap->value;
+	}
+
+	tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"a_srs","value");
+    if(tmpMap!=NULL){
+	  pszOutputSRSDef = tmpMap->value;
+	}
+
+	tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"t_srs","value");
+    if(tmpMap!=NULL){
+	  pszOutputSRSDef = tmpMap->value;
+	  bTransform = TRUE;
+	}
+
+	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++;
+      }
+
+	  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){
+	  pszWHERE = tmpMap->value;
+	}
+
+	tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"where","value");
+    if(tmpMap!=NULL){
+	  pszWHERE = tmpMap->value;
+	}
+
+	tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"select","value");
+    if(tmpMap!=NULL){
+	  pszSelect = tmpMap->value;
+	  papszSelFields = CSLTokenizeStringComplex(pszSelect, " ,", 
+		  FALSE, FALSE );
+	}
+
+	tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"segmentize","value");
+    if(tmpMap!=NULL){
+	  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){
+      pszDataSource=(char*)malloc(sizeof(char)*(strlen(dataPath)+strlen(tmpMap->value)+1));
+      sprintf((char*)pszDataSource,"%s/%s",dataPath,tmpMap->value);
+    }
+
+    tmpMap=NULL;
+    tmpMap=getMapFromMaps(inputs,"OutputDSN","value");
+    if(tmpMap!=NULL){
+      pszDestDataSource=(char*)malloc(sizeof(char)*(strlen(tempPath)+strlen(tmpMap->value)+4));
+      /*char *ext=new char[4];
+      ext="tif";
+      if(strcmp(mtoupper((char*)pszFormat),"AAIGRID")==0)
+        ext="csv";
+      else 
+        if(strcmp(mtoupper((char*)pszFormat),"PNG")==0)
+          ext="png";
+        else
+          if(strcmp(mtoupper((char*)pszFormat),"GIF")==0)
+            ext="gif";
+          else
+            if(strcmp(mtoupper((char*)pszFormat),"JPEG")==0)
+              ext="jpg";*/
+      sprintf((char*)pszDestDataSource,"%s/%s",tempPath,tmpMap->value/*,ext*/);
+    }
+
+#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
+	{
+#endif
+        Usage();
+#ifdef ZOO_SERVICE
+		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
+		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
+		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
+			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
+			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
+			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
+			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
+			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.\n" );
+        
+        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
+			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 )
+            {
+                CPLError( CE_Failure, CPLE_AppDefined, 
+                          "Terminating translation prematurely after failed\n"
+                          "translation of layer %s (use -skipfailures to skip errors)\n", 
+                          poLayer->GetLayerDefn()->GetName() );
+
+#ifdef ZOO_SERVICE
+				return SERVICE_FAILED;
+#else
+                exit( 1 );
+#endif
+            }
+        }
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Close down.                                                     */
+/* -------------------------------------------------------------------- */
+    delete poOutputSRS;
+    delete poSourceSRS;
+    delete poODS;
+    delete poDS;
+
+    CSLDestroy(papszSelFields);
+#ifndef ZOO_SERVICE
+	CSLDestroy( papszArgv );
+#endif
+    CSLDestroy( papszLayers );
+    CSLDestroy( papszDSCO );
+    CSLDestroy( papszLCO );
+
+    OGRCleanupAll();
+
+#ifdef DBMALLOC
+    malloc_dump(1);
+#endif
+    
+#ifdef ZOO_SERVICE
+	outputs=(maps*)malloc(sizeof(maps*));
+    outputs->name="GeneratedFile";
+    outputs->content=createMap("value",(char*)pszDestDataSource);
+    addMapToMap(&outputs->content,createMap("dataType","string"));
+    outputs->next=NULL;
+    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;
+
+    if (papszSelFields && !bAppend )
+    {
+        for( iField=0; papszSelFields[iField] != NULL; iField++)
+        {
+            int iSrcField = poFDefn->GetFieldIndex(papszSelFields[iField]);
+            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) );
+    }
+
+/* -------------------------------------------------------------------- */
+/*      Transfer features.                                              */
+/* -------------------------------------------------------------------- */
+    OGRFeature  *poFeature;
+    int         nFeaturesInTransaction = 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;
+
+        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() );
+
+#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
Index: trunk/zoo-services/openoffice/cgi-env/Exporter.py
===================================================================
--- trunk/zoo-services/openoffice/cgi-env/Exporter.py	(revision 1)
+++ trunk/zoo-services/openoffice/cgi-env/Exporter.py	(revision 1)
@@ -0,0 +1,97 @@
+#
+# 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 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
Index: trunk/zoo-services/openoffice/cgi-env/OdtConverter.zcfg
===================================================================
--- trunk/zoo-services/openoffice/cgi-env/OdtConverter.zcfg	(revision 1)
+++ trunk/zoo-services/openoffice/cgi-env/OdtConverter.zcfg	(revision 1)
@@ -0,0 +1,55 @@
+[OdtConverter]
+ Title = Convert raster data from one format to another. 
+ Abstract = Converts raster data between different formats.
+ processVersion = 1
+ storeSupported = true
+ statusSupported = true
+ serviceType = Python
+ serviceProvider = Exporter
+ <MetaData lang="en">
+   title = My Demo
+ </MetaData>
+ <DataInputs>
+  [InputDoc]
+   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>
+  [OutputDoc]
+   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>
+  [OutputedDoc]
+   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>  
