Index: trunk/zoo-project/zoo-kernel/main_conf_read.y
===================================================================
--- trunk/zoo-project/zoo-kernel/main_conf_read.y	(revision 605)
+++ trunk/zoo-project/zoo-kernel/main_conf_read.y	(revision 607)
@@ -1,9 +1,6 @@
 %{
-//======================================================
-/**
-   Zoo main configuration file parser
-**/
-//======================================================
-
+/*
+ * Zoo main configuration file parser
+ */
 #include <service.h>
 
@@ -285,8 +282,9 @@
 %%
 
-// crerror
-//======================================================
-/* fonction qui affiche l erreur si il y en a une */
-//======================================================
+/**
+ * Print on stderr the message and the line number of the error which occured.
+ *
+ * @param s the error message
+ */
 void crerror(const char *s)
 {
@@ -295,8 +293,10 @@
 }
 
-// main
-//======================================================
-/* fonction principale : entrée dans le programme */
-//======================================================
+/**
+ * Parse the main.cfg file and fill the maps structure.
+ *
+ * @param file the filename to parse
+ * @param my_map the maps structure to fill
+ */
 int conf_read(const char* file,maps* my_map){
   
@@ -326,6 +326,2 @@
 }
 
-
-//======================================================
-// FIN //
-//======================================================
Index: trunk/zoo-project/zoo-kernel/service.h
===================================================================
--- trunk/zoo-project/zoo-kernel/service.h	(revision 605)
+++ trunk/zoo-project/zoo-kernel/service.h	(revision 607)
@@ -160,4 +160,12 @@
  */
 #define SERVICE_SIZE (ELEMENTS_SIZE*2)+(MAP_SIZE*2)+sizeof(char*)
+/**
+ * The memory size to create a services
+ */
+#define SERVICES_SIZE SERVICE_SIZE+sizeof(services*)
+/**
+ * The memory size to create a registry
+ */
+#define REGISTRY_SIZE SERVICES_SIZE+sizeof(char*)
 
 #define SHMSZ     27
@@ -174,15 +182,9 @@
   /**
    * KVP linked list
-   *
-   * Deal with WPS KVP (name,value).
-   * A map is defined as:
-   *  - name : a key,
-   *  - value: a value,
-   *  - next : a pointer to the next map if any.
    */
   typedef struct map{
-    char* name;
-    char* value;
-    struct map* next;
+    char* name; //!< the key
+    char* value; //!< the value
+    struct map* next; //!< the pointer to the next map if any or NULL
   } map;
 
@@ -197,13 +199,9 @@
    *
    * Small object to store WPS KVP set.
-   * Maps is defined as:
-   *  - a name, 
-   *  - a content map,
-   *  - a pointer to the next maps if any.
    */
   typedef struct maps{
-    char* name;          
-    struct map* content; 
-    struct maps* next;   
+    char* name; //!< the maps name
+    struct map* content; //!< the content map
+    struct maps* next; //!< the pointer to the next maps if any or NULL
   } maps;
 
@@ -455,12 +453,8 @@
    *
    * Used to store informations about formats, such as mimeType, encoding ... 
-   *
-   * An iotype is defined as :
-   *  - a content map,
-   *  - a pointer to the next iotype if any.
    */
   typedef struct iotype{
-    struct map* content;
-    struct iotype* next;
+    struct map* content; //!< the content map
+    struct iotype* next; //!< the pointer to the next iotype if any or NULL
   } iotype;
 
@@ -469,49 +463,42 @@
    *
    * The elements are used to store metadata informations defined in the ZCFG.
-   *
-   * An elements is defined as:
-   *  - a name,
-   *  - a content map,
-   *  - a metadata map,
-   *  - a format (possible values are LiteralData, ComplexData or 
-   * BoundingBoxData),
-   *  - a default iotype,
-   *  - a pointer to the next elements id any.
    */
   typedef struct elements{
-    char* name;
-    struct map* content;
-    struct map* metadata;
-    char* format;
-    struct iotype* defaults;
-    struct iotype* supported;
-    struct elements* next;
+    char* name; //!< the name
+    struct map* content; //!< the content map
+    struct map* metadata; //!< the metadata map
+    char* format; //!< the format: LiteralData or ComplexData or BoundingBoxData
+    struct iotype* defaults; //!< the default iotype 
+    struct iotype* supported; //!< the supported iotype 
+    struct elements* next; //!< the pointer to the next element if any (or NULL)
   } elements;
 
   /**
    * Metadata informations about a full Service.
-   *
-   * An element is defined as:
-   *  - a name,
-   *  - a content map,
-   *  - a metadata map,
-   *  - an inputs elements
-   *  - an outputs elements
    */
   typedef struct service{
-    char* name;
-    struct map* content;
-    struct map* metadata;
-    struct elements* inputs;
-    struct elements* outputs; 
+    char* name; //!< the name
+    struct map* content; //!< the content map
+    struct map* metadata; //!< the metadata map
+    struct elements* inputs; //!< the inputs elements
+    struct elements* outputs; //!< the outputs elements
   } service;
 
   /**
-   * Multiple services chained list.
+   * Services chained list.
    */
   typedef struct services{
-    struct service* content; 
-    struct services* next; 
+    struct service* content; //!< the content service pointer
+    struct services* next; //!< the pointer to the next services*
   } services;
+
+  /**
+   * Profile registry.
+   */
+  typedef struct registry{
+    char *name; //!< the name
+    struct services* content; //!< the content services pointer
+    struct registry* next; //!< the next registry pointer
+  } registry;
 
   /**
@@ -1221,5 +1208,8 @@
       tmp->metadata=NULL;
       addMapToMap(&tmp->metadata,e->metadata);
-      tmp->format=zStrdup(e->format);
+      if(e->format!=NULL)
+	tmp->format=zStrdup(e->format);
+      else
+	tmp->format=NULL;
       if(e->defaults!=NULL){
 	tmp->defaults=(iotype*)malloc(IOTYPE_SIZE);
@@ -1324,4 +1314,254 @@
       fprintf(stderr,"\noutputs:\n");
       dumpElementsAsYAML(s->outputs);
+    }
+  }
+
+  /**
+   * Duplicate a service
+   * 
+   * @param s the service to clone
+   * @return the allocated service containing a copy of the serfvice s
+   */
+  static service* dupService(service* s){
+    service *res=(service*)malloc(SERVICE_SIZE);
+    res->name=zStrdup(s->name);
+    res->content=NULL;
+    addMapToMap(&res->content,s->content);
+    res->metadata=NULL;
+    addMapToMap(&res->metadata,s->metadata);
+    res->inputs=dupElements(s->inputs);
+    res->outputs=dupElements(s->outputs);
+    return res;
+  }
+
+  /**
+   * Print the registry on stderr.
+   * 
+   * @param r the registry
+   */
+  static void dumpRegistry(registry* r){
+    registry* p=r;
+    while(p!=NULL){
+      fprintf(stderr,"%s \n",p->name);
+      services* s=p->content;
+      s=p->content;
+      while(s!=NULL){
+	dumpService(s->content);
+	s=s->next;
+      }
+      p=p->next;
+    }
+  }
+
+  /**
+   * Add a service to the registry
+   *
+   * @param reg the resgitry to add the service
+   * @param name the registry name to update
+   * @param content the service to add
+   */
+  static bool addServiceToRegistry(registry** reg,char* name,service* content){
+    registry *l=*reg;
+    int isInitial=-1;
+    if(l==NULL){
+      l=(registry*)malloc(REGISTRY_SIZE);
+      isInitial=1;
+    }
+    if(l!=NULL){
+      int hasLevel=-1;
+      while(isInitial<0 && l!=NULL){
+	if(l->name!=NULL && strcasecmp(name,l->name)==0){
+	  hasLevel=1;
+	  break;
+	}
+	l=l->next;
+      }
+      if(hasLevel<0){
+	if(isInitial<0)
+	  l=(registry*)malloc(REGISTRY_SIZE);
+	l->name=zStrdup(name);
+	l->content=NULL;
+	l->next=NULL;
+      }
+      if(l->content==NULL){
+	l->content=(services*)malloc(SERVICES_SIZE);
+	l->content->content=dupService(content);
+	l->content->next=NULL;
+      }
+      else{
+	services* s=l->content;
+	while(s->next!=NULL)
+	  s=s->next;
+	s->next=(services*)malloc(SERVICES_SIZE);
+	s->next->content=dupService(content);
+	s->next->next=NULL;
+      }
+      l->next=NULL;
+      if(isInitial>0)
+	*reg=l;
+      else{
+	registry *r=*reg;
+	while(r->next!=NULL)
+	  r=r->next;
+	r->next=l;
+	r->next->next=NULL;
+      }
+      return true;
+    }
+    else
+      return false;
+  }
+
+  /**
+   * Free memory allocated for the registry
+   *
+   * @param r the registry
+   */
+  static void freeRegistry(registry** r){
+    registry* lr=*r;
+    while(lr!=NULL){
+      services* s=lr->content;
+      free(lr->name);
+      while(s!=NULL){
+	service* s1=s->content;
+	s=s->next;
+	if(s1!=NULL){
+	  freeService(&s1);
+	  free(s1);
+	  s1=NULL;
+	}
+      }
+      lr=lr->next;
+    }    
+  }
+
+  /**
+   * Access a service in the registry
+   *
+   * @param r the registry
+   * @param level the regitry to search ("concept", "generic" or "implementation")
+   * @param sname the service name
+   * @return the service pointer if a corresponding service was found or NULL
+   */
+  static service* getServiceFromRegistry(registry* r,char  *level,char* sname){
+    registry *lr=r;
+    while(lr!=NULL){
+      if(strcasecmp(lr->name,level)==0){
+	services* s=lr->content;
+	while(s!=NULL){
+	  if(s->content!=NULL && strcasecmp(s->content->name,sname)==0)
+	    return s->content;
+	  s=s->next;
+	}
+	break;
+      }
+      lr=lr->next;
+    }
+    return NULL;
+  }
+
+  /**
+   * Apply inheritance to an out map from a reference in map
+   *
+   * @param out the map to update
+   * @param in the reference map (containing inherited properties)
+   */
+  static void inheritMap(map** out,map* in){
+    map* content=in;
+    while(content!=NULL && *out!=NULL){
+      map* cmap=getMap(*out,content->name);
+      if(cmap==NULL)
+	addToMap(*out,content->name,content->value);
+      content=content->next;
+    }
+  }
+
+  /**
+   * Apply inheritance to an out iotype from a reference in iotype
+   * 
+   * @param out the iotype to update
+   * @param in the reference iotype (containing inherited properties)
+   */
+  static void inheritIOType(iotype** out,iotype* in){
+    iotype* io=in;
+    iotype* oio=*out;
+    if(io!=NULL){
+      if(*out==NULL){
+	*out=(iotype*)malloc(IOTYPE_SIZE);
+	(*out)->content=NULL;
+	addMapToMap(&(*out)->content,io->content);
+	(*out)->next=NULL;
+	oio=*out;
+	inheritIOType(&oio->next,io->next);
+      }else{
+	inheritIOType(&oio->next,io->next);
+      }
+    }
+  }
+
+  /**
+   * Apply inheritance to an out elements from a reference in elements
+   * 
+   * @param out the elements to update
+   * @param in the reference elements (containing inherited properties)
+   */
+  static void inheritElements(elements** out,elements* in){
+    elements* content=in;
+    while(content!=NULL && *out!=NULL){
+      elements* cmap=getElements(*out,content->name);
+      if(cmap==NULL)
+	addToElements(out,content);
+      else{
+	inheritMap(&cmap->content,content->content);
+	inheritMap(&cmap->metadata,content->metadata);
+	if(cmap->format==NULL && content->format!=NULL)
+	  cmap->format=zStrdup(content->format);
+	inheritIOType(&cmap->defaults,content->defaults);
+	if(cmap->supported==NULL)
+	  inheritIOType(&cmap->supported,content->supported);
+	else{
+	  iotype* p=content->supported;
+	  while(p!=NULL){
+	    addMapToIoType(&cmap->supported,p->content);
+	    p=p->next;
+	  }
+	}
+      }
+      content=content->next;
+    }
+  }
+
+  /**
+   * Apply inheritance to a service based on a registry
+   * 
+   * @param r the registry storing profiles hierarchy
+   * @param s the service to update depending on its inheritance
+   */
+  static void inheritance(registry *r,service** s){
+    if(r==NULL)
+      return;
+    service* ls=*s;
+    if(ls->content==NULL)
+      return;
+    map* profile=getMap(ls->content,"extend");
+    map* level=getMap(ls->content,"level");
+    if(profile!=NULL&&level!=NULL){
+      service* s1;
+      if(strncasecmp(level->value,"profile",7)==0)
+	s1=getServiceFromRegistry(r,"generic",profile->value);
+      else
+	s1=getServiceFromRegistry(r,level->value,profile->value);
+      
+      inheritMap(&ls->content,s1->content);
+      inheritMap(&ls->metadata,s1->metadata);
+      if(ls->inputs==NULL && s1->inputs!=NULL){
+	ls->inputs=dupElements(s1->inputs);
+      }else{
+	inheritElements(&ls->inputs,s1->inputs);
+      }
+      if(ls->outputs==NULL && s1->outputs!=NULL){
+	ls->outputs=dupElements(s1->outputs);
+      }else
+	inheritElements(&ls->outputs,s1->outputs);
     }
   }
Index: trunk/zoo-project/zoo-kernel/service_conf.y
===================================================================
--- trunk/zoo-project/zoo-kernel/service_conf.y	(revision 605)
+++ trunk/zoo-project/zoo-kernel/service_conf.y	(revision 607)
@@ -1,5 +1,3 @@
-%{
-//======================================================
-/**
+/*
  * Thx to Jean-Marie CODOL and Naitan GROLLEMUND
  * copyright 2009 GeoLabs SARL 
@@ -7,5 +5,5 @@
  *
  */
-//======================================================
+%{
 
 #include <string>
@@ -22,5 +20,5 @@
 static bool wait_defaults=false;
 static bool wait_supporteds=false;
-static bool wait_outputs=false;
+static bool wait_outputs=-1;
 static bool wait_data=false;
 static service* my_service=NULL;
@@ -34,17 +32,13 @@
 // namespace
 using namespace std;
-//======================================================
 
 // srerror
 void srerror(const char *s);
-//======================================================
 
 // usage ()
 void usage(void) ;
-//======================================================
 
 // srdebug
 extern int srdebug;
-//======================================================
 
 extern char srtext[];
@@ -52,15 +46,11 @@
 // srlineno
 extern int srlineno;
-//======================================================
 
 // srin
 extern FILE* srin;
-//======================================================
 
 // srlex
 extern int srlex(void);
 extern int srlex_destroy(void);
-
-//vector<char*> lattribute;
 
 %}
@@ -76,11 +66,11 @@
 /* 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
@@ -88,8 +78,8 @@
 %type <chaine> EPAIR
 %type <chaine> SPAIR
-//======================================================
+
 /* <!-- xxx -> <? xxx yyy ?> */
 %token PI PIERROR /** COMMENT **/
-//======================================================
+
 /* <!-- xxx -> <? xxx yyy ?> */
 %token ERREURGENERALE CDATA WHITESPACE NEWLINE
@@ -97,14 +87,11 @@
 %type <s> ETag
 %type <s> ANID
-//======================================================
-// %start
-//======================================================
+
+// % start
 
 %%
-// document <//===
-//======================================================
+// document 
 // regle 1
 // on est a la racine du fichier xml
-//======================================================
 document
  : miscetoile element miscetoile {}
@@ -118,5 +105,4 @@
  ;
 // element
-//======================================================
 // regle 39
 // OUVRANTE CONTENU FERMANTE obligatoirement
@@ -124,5 +110,4 @@
 // on ne peut pas avoir Epsilon
 // un fichier xml ne peut pas etre vide ou seulement avec un prolog
-//======================================================
 element
  : STag contentetoile ETag	
@@ -136,12 +121,9 @@
  ;
 
-//======================================================
 // 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
@@ -150,4 +132,5 @@
   fprintf(stderr,"(%s %d) %s\n",__FILE__,__LINE__,$2);
   fflush(stderr);
+  dumpMap(current_content);
 #endif
   if(my_service->content==NULL){
@@ -163,5 +146,5 @@
   }
   if(strncasecmp($2,"DataInputs",10)==0){
-    if(wait_mainmetadata==true){
+    if(wait_mainmetadata==true && current_content!=NULL){
       addMapToMap(&my_service->metadata,current_content);
       freeMap(&current_content);
@@ -238,5 +221,5 @@
 	current_element->next=NULL;
       }
-      wait_outputs=true;
+      wait_outputs=1;
       current_data=2;
       previous_data=2;
@@ -323,11 +306,8 @@
  ;
 
-//======================================================
 // Attributeetoile
-//======================================================
 // regle 41
 // une liste qui peut etre vide d'attributs
 // utiliser la récursivité a gauche
-//======================================================
 Attributeetoile
  : Attributeetoile attribute  {}
@@ -335,7 +315,5 @@
  ;
 
-//======================================================
 // attribute
-//======================================================
 // regle 41
 // un attribut est compose d'un identifiant
@@ -343,5 +321,4 @@
 // et d'une définition de chaine de caractere
 // ( "xxx" ou 'xxx' )
-//======================================================
 attribute
  : ID Eq ATTVALUE		
@@ -353,7 +330,5 @@
  ;
 
-//======================================================
 // EmptyElemTag
-//======================================================
 // regle 44
 // ICI ON DEFINIT NEUTRE
@@ -361,5 +336,4 @@
 // parce qu'il n'y a pas de comparaisons a faire
 // avec un identifiant d'une balise jumelle
-//======================================================
 EmptyElemTag
  : INFCAR ID Attributeetoile SLASH SUPCAR	{
@@ -386,11 +360,7 @@
  ;
 
-//======================================================
 // ETag
-//======================================================
-// regle 42
 // BALISE FERMANTE
 // les separateurs après ID sont filtrés
-//======================================================
 ETag
  : INFCAR SLASH ID SUPCAR
@@ -401,4 +371,27 @@
   if(strcmp($3,"DataInputs")==0){
     current_data=1;
+    if(current_content!=NULL){
+      if(current_element->content==NULL){
+	addMapToMap(&current_element->content,current_content);
+      }
+      freeMap(&current_content);
+      free(current_content);
+      current_content=NULL;
+    }
+    if(current_element!=NULL){
+      if(my_service->content!=NULL && current_element->name!=NULL){
+	if(my_service->inputs==NULL){
+	  my_service->inputs=dupElements(current_element);
+	  my_service->inputs->next=NULL;
+	  tmp_count++;
+	}
+	else{
+	  addToElements(&my_service->inputs,current_element);
+	}
+	freeElements(&current_element);
+	free(current_element);
+	current_element=NULL;
+      }
+    }
   }
   if(strcmp($3,"DataOutputs")==0){
@@ -489,7 +482,5 @@
  ;
 
-//======================================================
 // texteinterbalise
-//======================================================
 // regle 14
 // DU TEXTE quelconque
@@ -499,9 +490,7 @@
 // maintenant on croise les ID dans les dbalises
 // et des CHARDATA hors des balises
-//======================================================
 texteinterbalise
  : CHARDATA		{}
  ;
-//======================================================
 
 pair: PAIR { if(debug) fprintf(stderr,"PAIR FOUND !!\n");if(curr_key!=NULL){free(curr_key);curr_key=NULL;} }
@@ -637,5 +626,5 @@
     else
       if(current_data==2){ 
-	wait_outputs=true;
+	wait_outputs=1;
 	if(wait_inputs){
 	  if(current_element!=NULL && current_element->name!=NULL){
@@ -746,5 +735,5 @@
 	  }
 	wait_inputs=false;
-	wait_outputs=true;
+	wait_outputs=1;
 	//wait_outputs=true;
       }
@@ -755,8 +744,9 @@
 %%
 
-// srerror
-//======================================================
-/* fonction qui affiche l erreur si il y en a une */
-//======================================================
+/**
+ * Print on stderr the message and the line number of the error which occured.
+ * 
+ * @param s the error message
+ */
 void srerror(const char *s)
 {
@@ -766,7 +756,10 @@
 
 /**
- * getServiceFromFile :
- * set service given as second parameter with informations extracted from the
- * definition file.
+ * Parse a ZCFG file and fill the service structure.
+ *
+ * @param conf the conf maps containing the main.cfg settings
+ * @param file the fullpath to the ZCFG file
+ * @param service the service structure to fill
+ * @return 0 on success, -1 on failure
  */
 int getServiceFromFile(maps* conf,const char* file,service** service){
@@ -792,5 +785,5 @@
   wait_defaults=false;
   wait_supporteds=false;
-  wait_outputs=false;
+  wait_outputs=-1;
   wait_data=false;
   data=-1;
@@ -810,7 +803,8 @@
 #ifdef DEBUG_SERVICE_CONF
   fprintf(stderr,"RESULT: %d %d\n",resultatYYParse,wait_outputs);
-#endif
-  if(wait_outputs && current_element!=NULL && current_element->name!=NULL){
-    if(my_service->outputs==NULL){      
+  dumpElements(current_element);
+#endif
+  if(wait_outputs>0 && current_element!=NULL && current_element->name!=NULL){
+    if(my_service->outputs==NULL){  
 #ifdef DEBUG_SERVICE_CONF
       fprintf(stderr,"(DATAOUTPUTS - %d) DUP current_element\n",__LINE__);
@@ -840,5 +834,10 @@
     current_element=NULL;
   }
+  int contentOnly=-1;
   if(current_content!=NULL){
+    if(my_service->content==NULL){
+      addMapToMap(&my_service->content,current_content);
+      contentOnly=1;
+    }
     freeMap(&current_content);
     free(current_content);
@@ -849,6 +848,5 @@
   dumpService(my_service);
 #endif
-  if(wait_outputs<0 || my_service==NULL || my_service->name==NULL || my_service->content==NULL || my_service->outputs==NULL){
-    fprintf(stderr,"%s %d\n",__FILE__,__LINE__);
+  if(contentOnly<0 && ((wait_outputs<0 && current_data==2 && my_service->outputs==NULL) || my_service==NULL || my_service->name==NULL || my_service->content==NULL)){
     setMapInMaps(conf,"lenv","message",srlval.chaine);
 #ifndef WIN32
Index: trunk/zoo-project/zoo-kernel/service_internal.c
===================================================================
--- trunk/zoo-project/zoo-kernel/service_internal.c	(revision 605)
+++ trunk/zoo-project/zoo-kernel/service_internal.c	(revision 607)
@@ -1226,4 +1226,5 @@
  * 
  * @param m the conf maps containing the main.cfg settings
+ * @param registry the profile registry if any
  * @param nc the XML node to add the Process node
  * @param serv the service structure created from the zcfg file
Index: trunk/zoo-project/zoo-kernel/service_internal_ms.c
===================================================================
--- trunk/zoo-project/zoo-kernel/service_internal_ms.c	(revision 605)
+++ trunk/zoo-project/zoo-kernel/service_internal_ms.c	(revision 607)
@@ -131,4 +131,9 @@
   outputMapfile(m,tmpI);
   map *msUrl=getMapFromMaps(m,"main","mapserverAddress");
+  if(msUrl==NULL){
+    errorException (m, _("Unable to find any mapserverAddress defined in the main.cfg file"),
+		    "InternalError", NULL);
+    exit(-1);
+  }
   map *msOgcVersion=getMapFromMaps(m,"main","msOgcVersion");
   map *dataPath=getMapFromMaps(m,"main","dataPath");
@@ -794,7 +799,7 @@
     char *pszProjection;
     pszProjection = (char *) GDALGetProjectionRef( hDataset );
-    //#ifdef DEBUGMS
+#ifdef DEBUGMS
     fprintf(stderr,"Accessing the DataSource %s\n",GDALGetProjectionRef( hDataset ));
-    //#endif
+#endif
     setSrsInformations(output,m,myLayer,pszProjection);
   }else{
Index: trunk/zoo-project/zoo-kernel/service_internal_php.c
===================================================================
--- trunk/zoo-project/zoo-kernel/service_internal_php.c	(revision 605)
+++ trunk/zoo-project/zoo-kernel/service_internal_php.c	(revision 607)
@@ -247,4 +247,8 @@
       HashTable* t=HASH_OF(iargs[2]);
       HashTable* t1=HASH_OF(iargs[0]);
+      freeMaps(real_outputs);
+      free(*real_outputs);
+      freeMaps(main_conf);
+      free(*main_conf);
       *real_outputs=php_maps_from_Array(t);
       *main_conf=php_maps_from_Array(t1);
Index: trunk/zoo-project/zoo-kernel/ulinet.c
===================================================================
--- trunk/zoo-project/zoo-kernel/ulinet.c	(revision 605)
+++ trunk/zoo-project/zoo-kernel/ulinet.c	(revision 607)
@@ -329,8 +329,8 @@
 #endif
     curl_easy_setopt(hInternet->ihandle[hInternet->nb].handle,CURLOPT_POSTFIELDS,lpszHeaders);
-    //curl_easy_setopt(hInternet->handle,CURLOPT_POSTFIELDSIZE,dwHeadersLength+1);
-    if(hInternet->ihandle[hInternet->nb].header!=NULL)
-      curl_easy_setopt(hInternet->ihandle[hInternet->nb].handle,CURLOPT_HTTPHEADER,hInternet->ihandle[hInternet->nb].header);
-  }
+    curl_easy_setopt(hInternet->ihandle[hInternet->nb].handle,CURLOPT_POSTFIELDSIZE,dwHeadersLength+1);
+  }
+  if(hInternet->ihandle[hInternet->nb].header!=NULL)
+    curl_easy_setopt(hInternet->ihandle[hInternet->nb].handle,CURLOPT_HTTPHEADER,hInternet->ihandle[hInternet->nb].header);
 
   curl_easy_setopt(hInternet->ihandle[hInternet->nb].handle,CURLOPT_URL,lpszUrl);
@@ -366,4 +366,5 @@
     if(tmp!=NULL)
       hInternet->ihandle[i].mimeType=strdup(tmp);
+    curl_easy_getinfo(hInternet->ihandle[i].handle,CURLINFO_RESPONSE_CODE,&hInternet->ihandle[i].code);
     curl_multi_remove_handle(hInternet->handle, hInternet->ihandle[i].handle);
     curl_easy_cleanup(hInternet->ihandle[i].handle);
@@ -437,2 +438,22 @@
 }
 
+
+/**
+ * Use basic authentication for accessing a ressource
+ * 
+ * @param hInternet the _HINTERNET structure
+ * @param login the login to use to authenticate
+ * @param passwd the password to use to authenticate
+ */
+int setBasicAuth(HINTERNET hInternet,char* login,char* passwd){
+  char *tmp;
+  tmp=(char*)malloc((strlen(login)+strlen(passwd)+2)*sizeof(char));
+  sprintf(tmp,"%s:%s",login,passwd);
+  if(curl_easy_setopt(hInternet.ihandle[hInternet.nb].handle,CURLOPT_USERPWD,tmp)==CURLE_OUT_OF_MEMORY){
+    free(tmp);
+    return -1;
+  }
+  curl_easy_setopt(hInternet.ihandle[hInternet.nb].handle, CURLOPT_HTTPAUTH,CURLAUTH_ANY);
+  free(tmp);
+  return 0;
+}
Index: trunk/zoo-project/zoo-kernel/ulinet.h
===================================================================
--- trunk/zoo-project/zoo-kernel/ulinet.h	(revision 605)
+++ trunk/zoo-project/zoo-kernel/ulinet.h	(revision 607)
@@ -66,41 +66,42 @@
 #endif
 
-struct MemoryStruct {
-  char *memory; //!< the memory space to store data 
-  size_t size; //!< side of the memory space
-};
+  struct MemoryStruct {
+    char *memory; //!< the memory space to store data 
+    size_t size; //!< size of the memory space
+  };
 
   /**
    * Individual CURL handler
    */
-typedef struct {
-  CURL *handle; //!< the CURL handler
-  struct curl_slist *header; //!< the headers to send
-  char* filename; //!< the cached file name
-  FILE* file; //!< the file pointer
-  unsigned char *pabyData; //!< the downloaded content
-  char *mimeType; //!< the mimeType returned by the server
-  int hasCacheFile; //!< 1 if we used a cache file
-  int nDataLen; //!< the length of the downloaded content
-  int nDataAlloc; //!< 
-  int id; //!< The position of the element in the queue
-} _HINTERNET;
+  typedef struct {
+    CURL *handle; //!< the CURL handler
+    struct curl_slist *header; //!< the headers to send
+    char* filename; //!< the cached file name
+    FILE* file; //!< the file pointer
+    unsigned char *pabyData; //!< the downloaded content
+    char *mimeType; //!< the mimeType returned by the server
+    int hasCacheFile; //!< 1 if we used a cache file
+    int nDataLen; //!< the length of the downloaded content
+    int nDataAlloc; //!< 
+    long code; //!< the last received response code
+    int id; //!< The position of the element in the queue
+  } _HINTERNET;
 
   /**
    * Multiple CURL handlers
    */
-typedef struct {
-  CURLM *handle; //!< the CURLM handler
-  _HINTERNET ihandle[MAX_REQ]; //!< individual handlers in the queue 
-  char *waitingRequests[MAX_REQ]; //!< request in the queue
-  char *agent; //!< The User-Agent to use for HTTP request
-  int nb; //!< number of element in the queue 
-} HINTERNET;
+  typedef struct {
+    CURLM *handle; //!< the CURLM handler
+    _HINTERNET ihandle[MAX_REQ]; //!< individual handlers in the queue 
+    char *waitingRequests[MAX_REQ]; //!< request in the queue
+    char *agent; //!< The User-Agent to use for HTTP request
+    int nb; //!< number of element in the queue 
+  } HINTERNET;
 
-size_t write_data_into(void *buffer, size_t size, size_t nmemb, void *data);
+  size_t write_data_into(void*,size_t,size_t,void*);
 
-size_t header_write_data(void *buffer, size_t size, size_t nmemb, void *data);
+  size_t header_write_data(void*,size_t,size_t,void*);
 
-void setProxy(CURL* handle,char* host,long port);
+  void setProxy(CURL*,char*,long);
 
 #if defined(macintosh) || (defined(__MACH__) && defined(__APPLE__))
@@ -108,11 +109,11 @@
 #include <CoreServices/CoreServices.h>
 #include <SystemConfiguration/SystemConfiguration.h>
-char* CFStringToCString(CFStringRef dest,char * buffer);
-OSStatus setProxiesForProtcol(CURL* handle,const char *proto);
+  char* CFStringToCString(CFStringRef,char*);
+  OSStatus setProxiesForProtcol(CURL*,const char*);
 
 #else
 
 //#include <gconf/gconf-client.h>
-int setProxiesForProtcol(CURL* handle,const char *proto);
+  int setProxiesForProtcol(CURL*,const char*);
 
 #endif
@@ -126,7 +127,7 @@
 typedef char* LPCTSTR;
 #endif
-HINTERNET InternetOpen(char* lpszAgent,int dwAccessType,char* lpszProxyName,char* lpszProxyBypass,int dwFlags);
+  HINTERNET InternetOpen(char*,int,char*,char*,int);
 
-void InternetCloseHandle(HINTERNET* handle);
+  void InternetCloseHandle(HINTERNET*);
 
 #define INTERNET_FLAG_EXISTING_CONNECT         0
@@ -143,7 +144,7 @@
 //typedef char* LPVOID;
 #ifndef WIN32
-typedef void* LPVOID;
-typedef void* LPTSTR;
-typedef size_t* LPDWORD;
+  typedef void* LPVOID;
+  typedef void* LPTSTR;
+  typedef size_t* LPDWORD;
 #endif
 #ifndef bool
@@ -153,11 +154,13 @@
 #  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);
+  HINTERNET InternetOpenUrl(HINTERNET*,LPCTSTR,LPCTSTR,size_t,size_t,size_t);
 
-int processDownloads(HINTERNET* hInternet);
+  int processDownloads(HINTERNET*);
 
-int freeCookieList(HINTERNET hInternet);
+  int freeCookieList(HINTERNET);
 
-int InternetReadFile(_HINTERNET hInternet,LPVOID lpBuffer,int dwNumberOfBytesToRead,size_t *lpdwNumberOfBytesRead);
+  int InternetReadFile(_HINTERNET,LPVOID,int,size_t*);
+
+  int setBasicAuth(HINTERNET,char*,char*);
 
 #ifdef __cplusplus
Index: trunk/zoo-project/zoo-kernel/zoo_loader.c
===================================================================
--- trunk/zoo-project/zoo-kernel/zoo_loader.c	(revision 605)
+++ trunk/zoo-project/zoo-kernel/zoo_loader.c	(revision 607)
@@ -1,3 +1,3 @@
-/**
+/*
  * Author : Gérald FENOY
  *
@@ -67,4 +67,8 @@
 #endif
 
+/**
+ * Main entry point for cgic.
+ * @return 0 on sucess.
+ */
 int cgiMain(){
   /**
Index: trunk/zoo-project/zoo-kernel/zoo_service_loader.c
===================================================================
--- trunk/zoo-project/zoo-kernel/zoo_service_loader.c	(revision 605)
+++ trunk/zoo-project/zoo-kernel/zoo_service_loader.c	(revision 607)
@@ -1,3 +1,3 @@
-/**
+/*
  * Author : Gérald FENOY
  *
@@ -120,5 +120,11 @@
 #endif
 
+/**
+ * Translation function for zoo-kernel
+ */
 #define _(String) dgettext ("zoo-kernel",String)
+/**
+ * Translation function for zoo-service
+ */
 #define __(String) dgettext ("zoo-service",String)
 
@@ -131,4 +137,15 @@
 extern int getServiceFromFile (maps *, const char *, service **);
 
+/**
+ * Parse the service file using getServiceFromFile or use getServiceFromYAML
+ * if YAML support was activated.
+ *
+ * @param conf the conf maps containing the main.cfg settings
+ * @param file the file name to parse
+ * @param service the service to update witht the file content
+ * @param name the service name
+ * @return true if the file can be parsed or false
+ * @see getServiceFromFile, getServiceFromYAML
+ */
 int
 readServiceFile (maps * conf, char *file, service ** service, char *name)
@@ -144,4 +161,11 @@
 }
 
+/**
+ * Replace a char by another one in a string
+ *
+ * @param str the string to update
+ * @param toReplace the char to replace
+ * @param toReplaceBy the char that will be used
+ */
 void
 translateChar (char *str, char toReplace, char toReplaceBy)
@@ -156,6 +180,11 @@
 
 /**
- * Create (or append to) an array valued maps
- * value = "["",""]"
+ * Create (or append to) an array valued maps value = "["",""]"
+ *
+ * @param m the conf maps containing the main.cfg settings
+ * @param mo the map to update
+ * @param mi the map to append
+ * @param elem the elements containing default definitions
+ * @return 0 on success, -1 on failure
  */
 int
@@ -237,6 +266,117 @@
 }
 
+/**
+ * Create the profile registry.
+ *
+ * The profile registry is optional (created only if the registry key is
+ * available in the [main] section of the main.cfg file) and can be used to
+ * store the profiles hierarchy. The registry is a directory which should
+ * contain the following sub-directories: 
+ *  * concept: direcotry containing .html files describing concept
+ *  * generic: directory containing .zcfg files for wps:GenericProcess
+ *  * implementation: directory containing .zcfg files for wps:Process
+ *
+ * @param m the conf maps containing the main.cfg settings
+ * @param r the registry to update
+ * @param reg_dir the resgitry 
+ * @param saved_stdout the saved stdout identifier
+ * @return 0 if the resgitry is null or was correctly updated, -1 on failure
+ */
 int
-recursReaddirF (maps * m, xmlNodePtr n, char *conf_dir, char *prefix,
+createRegistry (maps* m,registry ** r, char *reg_dir, int saved_stdout)
+{
+  struct dirent *dp;
+  int scount = 0;
+
+  if (reg_dir == NULL)
+    return 0;
+  DIR *dirp = opendir (reg_dir);
+  if (dirp == NULL)
+    {
+      return -1;
+    }
+  while ((dp = readdir (dirp)) != NULL){
+    if ((dp->d_type == DT_DIR || dp->d_type == DT_LNK) && dp->d_name[0] != '.')
+      {
+
+        char * tmpName =
+          (char *) malloc ((strlen (reg_dir) + strlen (dp->d_name) + 2) *
+                           sizeof (char));
+        sprintf (tmpName, "%s/%s", reg_dir, dp->d_name);
+	
+	DIR *dirp1 = opendir (tmpName);
+	struct dirent *dp1;
+	while ((dp1 = readdir (dirp1)) != NULL){
+	  char* extn = strstr(dp1->d_name, ".zcfg");
+	  if(dp1->d_name[0] != '.' && extn != NULL && strlen(extn) == 5)
+	    {
+	      int t;
+	      char *tmps1=
+		(char *) malloc ((strlen (tmpName) + strlen (dp1->d_name) + 2) *
+				 sizeof (char));
+	      sprintf (tmps1, "%s/%s", tmpName, dp1->d_name);
+	      char *tmpsn = zStrdup (dp1->d_name);
+	      tmpsn[strlen (tmpsn) - 5] = 0;
+	      service* s1 = (service *) malloc (SERVICE_SIZE);
+	      if (s1 == NULL)
+		{
+		  dup2 (saved_stdout, fileno (stdout));
+		  errorException (m, _("Unable to allocate memory."),
+				  "InternalError", NULL);
+		  return -1;
+		}
+	      t = readServiceFile (m, tmps1, &s1, tmpsn);
+	      free (tmpsn);
+	      if (t < 0)
+		{
+		  map *tmp00 = getMapFromMaps (m, "lenv", "message");
+		  char tmp01[1024];
+		  if (tmp00 != NULL)
+		    sprintf (tmp01, _("Unable to parse the ZCFG file: %s (%s)"),
+			     dp1->d_name, tmp00->value);
+		  else
+		    sprintf (tmp01, _("Unable to parse the ZCFG file: %s."),
+			     dp1->d_name);
+		  dup2 (saved_stdout, fileno (stdout));
+		  errorException (m, tmp01, "InternalError", NULL);
+		  return -1;
+		}
+#ifdef DEBUG
+	      dumpService (s1);
+	      fflush (stdout);
+	      fflush (stderr);
+#endif
+	      if(strncasecmp(dp->d_name,"implementation",14)==0){
+		inheritance(*r,&s1);
+	      }
+	      addServiceToRegistry(r,dp->d_name,s1);
+	      freeService (&s1);
+	      free (s1);
+	      scount++;
+	    }
+	}
+	(void) closedir (dirp1);
+      }
+  }
+  (void) closedir (dirp);
+  return 0;
+}
+
+/**
+ * Recursivelly parse zcfg starting from the ZOO-Kernel cwd.
+ * Call the func function given in arguments after parsing the ZCFG file.
+ *
+ * @param m the conf maps containing the main.cfg settings
+ * @param r the registry containing profiles hierarchy
+ * @param n the root XML Node to add the sub-elements
+ * @param conf_dir the location of the main.cfg file (basically cwd)
+ * @param prefix the current prefix if any, or NULL
+ * @param saved_stdout the saved stdout identifier
+ * @param level the current level (number of sub-directories to reach the
+ * current path)
+ * @see inheritance, readServiceFile
+ */
+int
+recursReaddirF (maps * m, registry *r, xmlNodePtr n, char *conf_dir, char *prefix,
                 int saved_stdout, int level, void (func) (maps *, xmlNodePtr,
                                                           service *))
@@ -287,5 +427,5 @@
             setMapInMaps (m, "lenv", "level", levels1);
             res =
-              recursReaddirF (m, n, tmp, prefix, saved_stdout, level + 1,
+              recursReaddirF (m, r, n, tmp, prefix, saved_stdout, level + 1,
                               func);
             sprintf (levels1, "%d", level);
@@ -346,4 +486,5 @@
             fflush (stderr);
 #endif
+	    inheritance(r,&s1);
             func (m, n, s1);
             freeService (&s1);
@@ -356,4 +497,11 @@
 }
 
+/**
+ * Apply XPath Expression on XML document.
+ *
+ * @param doc the XML Document
+ * @param search the XPath expression
+ * @return xmlXPathObjectPtr containing the resulting nodes set
+ */
 xmlXPathObjectPtr
 extractFromDoc (xmlDocPtr doc, const char *search)
@@ -367,4 +515,9 @@
 }
 
+/**
+ * Signal handling function which simply call exit(0).
+ *
+ * @param sig the signal number
+ */
 void
 donothing (int sig)
@@ -376,4 +529,10 @@
 }
 
+/**
+ * Signal handling function which create an ExceptionReport node containing the
+ * information message corresponding to the signal number.
+ *
+ * @param sig the signal number
+ */
 void
 sig_handler (int sig)
@@ -416,4 +575,14 @@
 }
 
+/**
+ * Load a service provider and run the service function.
+ *
+ * @param myMap the conf maps containing the main.cfg settings
+ * @param s1 the service structure
+ * @param request_inputs map storing all the request parameters
+ * @param inputs the inputs maps
+ * @param ioutputs the outputs maps
+ * @param eres the result returned by the service execution
+ */
 void
 loadServiceAndRun (maps ** myMap, service * s1, map * request_inputs,
@@ -876,4 +1045,11 @@
 #endif
 
+/**
+ * Process the request.
+ *
+ * @param inputs the request parameters map 
+ * @return 0 on sucess, other value on failure
+ * @see conf_read,recursReaddirF
+ */
 int
 runRequest (map ** inputs)
@@ -1113,4 +1289,6 @@
     SERVICE_URL = zStrdup (DEFAULT_SERVICE_URL);
 
+
+
   service *s1;
   int scount = 0;
@@ -1129,4 +1307,13 @@
   else
     snprintf (conf_dir, 1024, "%s", ntmp);
+
+  map* reg = getMapFromMaps (m, "main", "registry");
+  registry* zooRegistry=NULL;
+  if(reg!=NULL){
+    int saved_stdout = dup (fileno (stdout));
+    dup2 (fileno (stderr), fileno (stdout));
+    createRegistry (m,&zooRegistry,reg->value,saved_stdout);
+    dup2 (saved_stdout, fileno (stdout));
+  }
 
   if (strncasecmp (REQUEST, "GetCapabilities", 15) == 0)
@@ -1146,9 +1333,13 @@
       dup2 (fileno (stderr), fileno (stdout));
       if (int res =		  
-          recursReaddirF (m, n, conf_dir, NULL, saved_stdout, 0,
+          recursReaddirF (m, zooRegistry, n, conf_dir, NULL, saved_stdout, 0,
                           printGetCapabilitiesForProcess) < 0)
         {
           freeMaps (&m);
           free (m);
+	  if(zooRegistry!=NULL){
+	    freeRegistry(&zooRegistry);
+	    free(zooRegistry);
+	  }
           free (REQUEST);
           free (SERVICE_URL);
@@ -1160,4 +1351,8 @@
       freeMaps (&m);
       free (m);
+      if(zooRegistry!=NULL){
+	freeRegistry(&zooRegistry);
+	free(zooRegistry);
+      }
       free (REQUEST);
       free (SERVICE_URL);
@@ -1177,4 +1372,8 @@
           freeMaps (&m);
           free (m);
+	  if(zooRegistry!=NULL){
+	    freeRegistry(&zooRegistry);
+	    free(zooRegistry);
+	  }
           free (REQUEST);
           free (SERVICE_URL);
@@ -1200,5 +1399,5 @@
             {
               if (int res =
-                  recursReaddirF (m, n, conf_dir, NULL, saved_stdout, 0,
+                  recursReaddirF (m, zooRegistry, n, conf_dir, NULL, saved_stdout, 0,
                                   printDescribeProcessForProcess) < 0)
                 return res;
@@ -1245,4 +1444,8 @@
                           freeMaps (&m);
                           free (m);
+			  if(zooRegistry!=NULL){
+			    freeRegistry(&zooRegistry);
+			    free(zooRegistry);
+			  }
                           free (REQUEST);
                           free (corig);
@@ -1259,4 +1462,5 @@
                       dumpService (s1);
 #endif
+		      inheritance(zooRegistry,&s1);
                       printDescribeProcessForProcess (m, n, s1);
                       freeService (&s1);
@@ -1321,4 +1525,8 @@
                                   freeMaps (&m);
                                   free (m);
+				  if(zooRegistry!=NULL){
+				    freeRegistry(&zooRegistry);
+				    free(zooRegistry);
+				  }
                                   free (orig);
                                   free (REQUEST);
@@ -1332,4 +1540,5 @@
                               dumpService (s1);
 #endif
+			      inheritance(zooRegistry,&s1);
                               printDescribeProcessForProcess (m, n, s1);
                               freeService (&s1);
@@ -1358,4 +1567,8 @@
                       freeMaps (&m);
                       free (m);
+		      if(zooRegistry!=NULL){
+			freeRegistry(&zooRegistry);
+			free(zooRegistry);
+		      }
                       free (orig);
                       free (REQUEST);
@@ -1379,4 +1592,8 @@
           freeMaps (&m);
           free (m);
+	  if(zooRegistry!=NULL){
+	    freeRegistry(&zooRegistry);
+	    free(zooRegistry);
+	  }
           free (REQUEST);
           free (SERVICE_URL);
@@ -1396,4 +1613,8 @@
           freeMaps (&m);
           free (m);
+	  if(zooRegistry!=NULL){
+	    freeRegistry(&zooRegistry);
+	    free(zooRegistry);
+	  }
           free (REQUEST);
           free (SERVICE_URL);
@@ -1410,4 +1631,8 @@
       freeMaps (&m);
       free (m);
+      if(zooRegistry!=NULL){
+	freeRegistry(&zooRegistry);
+	free(zooRegistry);
+      }
       free (REQUEST);
       free (SERVICE_URL);
@@ -1447,4 +1672,9 @@
   dup2 (fileno (stderr), fileno (stdout));
   t = readServiceFile (m, tmps1, &s1, r_inputs->value);
+  inheritance(zooRegistry,&s1);
+  if(zooRegistry!=NULL){
+    freeRegistry(&zooRegistry);
+    free(zooRegistry);
+  }
   fflush (stdout);
   dup2 (saved_stdout, fileno (stdout));
