Index: branches/prototype-v0/zoo-project/zoo-kernel/service_callback.c
===================================================================
--- branches/prototype-v0/zoo-project/zoo-kernel/service_callback.c	(revision 851)
+++ branches/prototype-v0/zoo-project/zoo-kernel/service_callback.c	(revision 854)
@@ -30,5 +30,15 @@
 #include "service_json.h"
 #include "service_internal_ms.h"
+#include "sqlapi.h"
 #include <pthread.h>
+#include <libxml/tree.h>
+#include <libxml/parser.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+
+#include <libxslt/xslt.h>
+#include <libxslt/xsltInternals.h>
+#include <libxslt/transform.h>
+#include <libxslt/xsltutils.h>
 
 #ifdef __cplusplus
@@ -36,7 +46,34 @@
 #endif
 
+  /**
+   * Parameter definition to be used for sending parameters to a thread.
+   */
+  typedef struct {
+    maps *conf;      //!< the main configuration file
+    map *url;        //!< the callback url maps
+    json_object *res;//!< the JSON object to post 
+    int step;        //!< the current step [0,6]
+    int state;       //!< the current state [0,1]
+  } local_params;
+
+  /**
+   * Number of threads
+   */
   int nbThreads=0;
+  /**
+   * Current step
+   */
   int cStep=0;
+  /**
+   * Is there any ongoing HTTP request
+   */
+  int isOngoing=0;
+  /**
+   * Threads array
+   */
   pthread_t* myThreads=NULL;
+  /**
+   * Steps array
+   */
   bool steps[7][2]={
     {false,false},
@@ -48,4 +85,8 @@
     {false,false}
   };
+  /**
+   * Arguments array to give to the _invokeCallback thread's function
+   */
+  local_params** local_arguments;
   
   /**
@@ -71,45 +112,4 @@
   }
 
-  /**
-   * Parameter definition to be used for sending parameters to a thread.
-   */
-  typedef struct {
-    maps *conf;      //!< the main configuration file
-    map *url;        //!< the callback url maps
-    json_object *res;//!< the JSON object to post 
-    int step;        //!< the current step [0,6]
-    int state;       //!< the current state [0,1]
-  } local_params;
-
-  /**
-   * Verify if the URL should use a shared cache or not.
-   *
-   * In case the security section contains a key named "shared", then if the
-   * domain listed in the shared key are contained in the url given as parameter
-   * then it return "SHARED" in other cases, it returns "OTHER".
-   *
-   * @param conf the main configuration file maps
-   * @param url the URL to evaluate
-   * @return a string "SHARED" in case the host is in a domain listed in the
-   * shared key, "OTHER" in other cases.
-   */
-  char* getProvenance(maps* conf,const char* url){
-    map* sharedCache=getMapFromMaps(conf,"security","shared");
-    if(sharedCache!=NULL){
-      char *res=NULL;
-      char *hosts=sharedCache->value;
-      char *curs=strtok(hosts,",");
-      while(curs!=NULL){
-	if(strstr(url,curs)==NULL)
-	  res="OTHER";
-	else{
-	  res="SHARED";
-	  return res;
-	}
-      }
-      return res;
-    }
-    return "OTHER";
-  }
 
   /**
@@ -133,21 +133,44 @@
     hInternet.waitingRequests[0] = zStrdup(URL);
     free(URL);
-    fprintf(stderr,"************************* From thread %d %s %d: REQUEST PARAMETERS\n",pthread_self(),__FILE__,__LINE__);
+#ifdef CALLBACK_DEBUG
+    fprintf(stderr,"************************* From thread %d %s %d: REQUEST PARAMETERS cStep %d %d\n",pthread_self(),__FILE__,__LINE__,cStep,isOngoing);
     fprintf(stderr," * JSON: [%s] \n",jsonStr);
     fprintf(stderr," * URL: %s/ \n\n",hInternet.waitingRequests[0]);
     fprintf(stderr,"************************* From thread %d %s %d: REQUEST PARAMETERS\n",pthread_self(),__FILE__,__LINE__);
-    while( cStep!=7 &&
+#endif
+    while( (arg->step!=7 || isOngoing>0) &&
 	   ( cStep!=arg->step || (arg->state!=0 && steps[arg->step][0]==false) )
 	   ){
-      sleep(1);
-    }
+      struct timespec tv;
+      tv.tv_sec = 0;
+      tv.tv_nsec = (long) 5*1e+9;
+      nanosleep(&tv, &tv);
+      //sleep(1);
+    }
+    isOngoing=1;
+#ifdef CALLBACK_DEBUG
     fprintf(stderr,"************************* From thread %d %s %d: REQUEST START\n\n",pthread_self(),__FILE__,__LINE__);
     int i=0;
     for(i=0;i<7;i++){
       fprintf(stderr,"%d) %d %d\n",i,steps[i][0],steps[i][1]);
-      fflush(stderr);
-    }
-    fprintf(stderr,"************************* From thread %d %s %d: REQUEST START\n",pthread_self(),__FILE__,__LINE__);
+    }
+#endif
+    const struct tm *tm;
+    size_t len;
+    time_t now;
+    char *tmp1;
+    map *tmpStatus;
+    
+    now = time ( NULL );
+    tm = localtime ( &now );
+    
+    tmp1 = (char*)malloc((TIME_SIZE+1)*sizeof(char));
+    len = strftime ( tmp1, TIME_SIZE, "%Y-%m-%dT%I:%M:%SZ", tm );
+
+#ifdef CALLBACK_DEBUG    
+    fprintf(stderr,"************************* From thread %d %s %d: REQUEST START (%s)\n",pthread_self(),__FILE__,__LINE__,tmp1);
     fflush(stderr);
+#endif    
+    free(tmp1);
     res1 = InternetOpenUrl (&hInternet,
 			    hInternet.waitingRequests[0], 
@@ -158,6 +181,13 @@
     //curl_easy_setopt(hInternet.ihandle[hInternet.nb].handle, CURLOPT_VERBOSE, 1);x
     processDownloads(&hInternet);
-    fprintf(stderr,"************************* From thread %d %s %d: REQUEST END\n\n",pthread_self(),__FILE__,__LINE__);
-    fflush(stderr);
+    now = time ( NULL );
+    tm = localtime ( &now );
+    tmp1 = (char*)malloc((TIME_SIZE+1)*sizeof(char));
+    len = strftime ( tmp1, TIME_SIZE, "%Y-%m-%dT%I:%M:%SZ", tm );
+    
+#ifdef CALLBACK_DEBUG    
+    fprintf(stderr,"************************* From thread %d %s %d: REQUEST END (%s)\n\n",pthread_self(),__FILE__,__LINE__,tmp1);
+#endif    
+    free(tmp1);
     char *tmp = (char *) malloc ((hInternet.ihandle[0].nDataLen + 1)
 				 * sizeof (char));
@@ -177,7 +207,8 @@
     json_object_put(arg->res);
     InternetCloseHandle(&hInternet);
+    isOngoing=0;
     if(cStep==0 || cStep==6 || arg->state==1)
       cStep=arg->step+1;
-    steps[arg->step][arg->state]=true;
+#ifdef CALLBACK_DEBUG    
     fprintf(stderr,"************************* From thread %d %s %d: RESPONSE CONTENT\n",pthread_self(),__FILE__,__LINE__);
     for(i=0;i<7;i++){
@@ -187,6 +218,10 @@
     fprintf(stderr,"************************* From thread %d %s %d\n\n",pthread_self(),__FILE__,__LINE__);
     fflush(stderr);
+#endif
+    steps[arg->step][arg->state]=true;
     free(tmp);
-    free(args);
+    //free(args);
+    fprintf(stderr,"************************* From thread %d %s %d: EXIT\n\n",pthread_self(),__FILE__,__LINE__);
+    fflush(stderr);
     pthread_exit(NULL);
   }
@@ -237,14 +272,14 @@
 
     tmp1 = (char*)malloc((TIME_SIZE+1)*sizeof(char));
-
-    len = strftime ( tmp1, TIME_SIZE, "%Y-%m-%dT%I:%M:%SZ", tm );
+    len = strftime ( tmp1, TIME_SIZE, "%Y-%m-%dT%H:%M:%SZ", tm );
     json_object *jsStr0=json_object_new_string(tmp1);
     json_object_object_add(res,"datetime",jsStr0);
-
+    free(tmp1);
+    
     switch(step){
     case 0: {
       // Create a new analyze
       maps* lenv=getMaps(conf,"lenv");
-      sid=getMapFromMaps(conf,"lenv","xrequest");
+      sid=getMapFromMaps(conf,"renv","xrequest");
       if(sid!=NULL){
 	json_object *jsStr=json_object_new_string(sid->value);
@@ -256,10 +291,24 @@
 	json_object_object_add(res,"process_identifier",jsStr);
       }
+      // Save the Execute request on disk 
+      map* tmpPath=getMapFromMaps(conf,"main","tmpPath");
+      map* req=getMapFromMaps(conf,"renv","xrequest");
+      sid=getMapFromMaps(conf,"lenv","usid");
+      char* executePath=(char*)malloc((strlen(tmpPath->value)+strlen(sid->value)+14)*sizeof(char));
+      sprintf(executePath,"%s/execute_%s.xml",tmpPath->value,sid->value);
+      FILE* saveExecute=fopen(executePath,"wb");
+      fwrite(req->value,1,strlen(req->value)*sizeof(char),saveExecute);
+      fflush(saveExecute);
+      fclose(saveExecute);
+      setMapInMaps(conf,"lenv","execute_file",executePath);
+      free(executePath);
       break;
     }
+      
     case 1: {
       // Fetching data inputs
       maps* curs=inputs;
-      char *keys[8][2]={
+      dumpMaps(curs);
+      char *keys[10][2]={
 	{
 	  "href",
@@ -287,10 +336,18 @@
 	},
 	{
-	  "ref_wfs_link",
-	  "ref_wfs_link"
+	  "ref_wcs_link",
+	  "ref_wcs_link"
+	},
+	{
+	  "ref_wcs_preview_link",
+	  "ref_wcs_preview_link"
 	},
 	{
 	  "geodatatype",
 	  "datatype"
+	},
+	{
+	  "wcs_extent",
+	  "boundingbox"
 	}	
       };
@@ -300,6 +357,11 @@
 	sid=getMap(curs->content,"ref_wms_link");
 	json_object *res2=json_object_new_object();
-	if(tmpMap!=NULL && sid==NULL){
-	  addToMap(curs->content,"generated_file",tmpMap->value);
+	if(tmpMap!=NULL){
+	  if(sid==NULL){
+	    addToMap(curs->content,"generated_file",tmpMap->value);
+	    addToMap(curs->content,"storage",tmpMap->value);
+	  }
+	  fprintf(stderr,"%s %d\n",__FILE__,__LINE__);
+	  dumpMap(curs->content);
 	  struct stat buf;
 	  char timeStr[ 100 ] = "";
@@ -314,10 +376,8 @@
 	  }
 	  setReferenceUrl(conf,curs);
-	  //outputMapfile(conf,curs);
-	  dumpMaps(curs);
 	}
 	int i=0;
 	int hasRef=-1;
-	for(;i<8;i++){
+	for(;i<10;i++){
 	  sid=getMap(curs->content,keys[i][0]);
 	  if(sid!=NULL){
@@ -340,5 +400,142 @@
       break;
     }
+      
     case 2: {
+      // Update the execute request stored on disk at step 1,1 to modify the references used.
+      if(state==0){
+	fprintf(stderr,"%s %d \n",__FILE__,__LINE__);
+	fflush(stderr);
+	maps* curs=inputs;
+	fprintf(stderr,"%s %d \n",__FILE__,__LINE__);
+	fflush(stderr);
+	xmlInitParser();
+	fprintf(stderr,"%s %d \n",__FILE__,__LINE__);
+	fflush(stderr);
+	map* xmlPath=getMapFromMaps(conf,"lenv","execute_file");
+	dumpMap(xmlPath);
+	fprintf(stderr,"%s %d \n",__FILE__,__LINE__);
+	fflush(stderr);
+	while(curs!=NULL){
+	  fprintf(stderr,"%s %d \n",__FILE__,__LINE__);
+	  fflush(stderr);
+	  dumpMap(curs->content);
+	  //map* bvMap=getMap(curs->content,"byValue");
+	  // TODO handle mapArray
+	  //if(bvMap!=NULL && strncasecmp(bvMap->value,"true",4)==0){
+	  if(getMap(curs->content,"href")==NULL && getMap(curs->content,"mimeType")!=NULL){
+	    map* tmpMap=getMap(curs->content,"cache_file");
+	    addToMap(curs->content,"generated_file",tmpMap->value);
+	    addToMap(curs->content,"storage",tmpMap->value);
+	    setReferenceUrl(conf,curs);
+	    fprintf(stderr,"%s %d \n",__FILE__,__LINE__);
+	    fflush(stderr);
+	    dumpMap(curs->content);
+	    fprintf(stderr,"%s %d \n",__FILE__,__LINE__);
+	    fflush(stderr);
+	    const char *params[5];
+	    int xmlLoadExtDtdDefaultValue;
+	    int hasFile=-1;
+	    map* xslPath=getMapFromMaps(conf,"callback","template");
+	    fprintf(stderr,"%s %d \n",__FILE__,__LINE__);
+	    fflush(stderr);
+	    dumpMap(xslPath);
+	    fprintf(stderr,"%s %d \n",__FILE__,__LINE__);
+	    fflush(stderr);
+	    map* filePath=getMap(curs->content,"ref_wfs_link");
+	    if(filePath==NULL)
+	      filePath=getMap(curs->content,"ref_wcs_link");
+	    fprintf(stderr,"%s %d \n",__FILE__,__LINE__);
+	    fflush(stderr);
+	    dumpMap(filePath);
+	    fprintf(stderr,"%s %d \n",__FILE__,__LINE__);
+	    fflush(stderr);
+	    char* inputName=curs->name;
+	    fprintf(stderr,"%s %d \n",__FILE__,__LINE__);
+	    fflush(stderr);
+	    if(xslPath==NULL || xmlPath==NULL || filePath==NULL)
+	      break;
+	    fprintf(stderr,"%s %d \n",__FILE__,__LINE__);
+	    fflush(stderr);
+	    char *tmpParam=(char*)malloc((strlen(curs->name)+11)*sizeof(char));
+	    char *tmpParam1=(char*)malloc((strlen(filePath->value)+11)*sizeof(char));
+	    sprintf(tmpParam,"string(\"%s\")",curs->name);	    
+	    sprintf(tmpParam1,"string(\"%s\")",filePath->value);	    
+	    params[0]="attr";
+	    params[1]=tmpParam;
+	    params[2]="value";
+	    params[3]=tmpParam1;//filePath->value;
+	    params[4]=NULL;
+	    fprintf(stderr, "## XSLT PARAMETERS ATTR: %s VALUE: %s \n",
+		    tmpParam,tmpParam1);
+	    xmlSubstituteEntitiesDefault(1);
+	    fprintf(stderr,"%s %d \n",__FILE__,__LINE__);
+	    fflush(stderr);
+	    xmlLoadExtDtdDefaultValue = 0;
+	    xsltStylesheetPtr cur = NULL;
+	    xmlDocPtr doc, res;
+	    cur = xsltParseStylesheetFile(BAD_CAST xslPath->value);
+	    doc = xmlParseFile(xmlPath->value);
+	    fflush(stderr);
+	    res = xsltApplyStylesheet(cur, doc, params);
+	    xmlChar *xmlbuff;
+	    int buffersize;
+	    xmlDocDumpFormatMemory(res, &xmlbuff, &buffersize, 1);
+	    // Store the executeRequest in file again
+	    free(tmpParam);
+	    free(tmpParam1);
+	    fprintf(stderr," # Request / XSLT: %s\n",xmlbuff);
+	    fflush(stderr);
+	    FILE* saveExecute=fopen(xmlPath->value,"wb");
+	    fwrite(xmlbuff,1,buffersize,saveExecute);
+	    fflush(saveExecute);
+	    fclose(saveExecute);
+	    xmlFree(xmlbuff);
+	    xmlFreeDoc(doc);
+	    xsltFreeStylesheet(cur);
+	  }
+	  fprintf(stderr,"%s %d \n",__FILE__,__LINE__);
+	  fflush(stderr);
+	  curs=curs->next;
+	}
+	fprintf(stderr,"%s %d \n",__FILE__,__LINE__);
+	fflush(stderr);
+	xmlCleanupParser();
+	fprintf(stderr,"%s %d \n",__FILE__,__LINE__);
+	fflush(stderr);
+	FILE* f0=fopen(xmlPath->value,"rb");
+	if(f0!=NULL){
+	  long flen;
+	  char *fcontent;
+	  fseek (f0, 0, SEEK_END);
+	  flen = ftell (f0);
+	  fseek (f0, 0, SEEK_SET);
+	  fcontent = (char *) malloc ((flen + 1) * sizeof (char));
+	  fread(fcontent,flen,1,f0);
+	  fcontent[flen]=0;
+	  fclose(f0);
+	  fprintf(stderr,"%s %d \n",__FILE__,__LINE__);
+	  fflush(stderr);
+	  map *schema=getMapFromMaps(conf,"database","schema");
+	  map* sid=getMapFromMaps(conf,"lenv","usid");
+	  fprintf(stderr,"%s %d \n",__FILE__,__LINE__);
+	  fflush(stderr);
+	  char *req=(char*)malloc((flen+strlen(schema->value)+strlen(sid->value)+66)*sizeof(char));
+	  fprintf(stderr,"%s %d \n",__FILE__,__LINE__);
+	  fflush(stderr);
+	  sprintf(req,"UPDATE %s.services set request_execute_content=$$%s$$ WHERE uuid=$$%s$$",schema->value,fcontent,sid->value);
+	  fprintf(stderr,"%s %d \n",__FILE__,__LINE__);
+	  fflush(stderr);
+	  execSql(conf,1,req);
+	  fprintf(stderr,"%s %d \n",__FILE__,__LINE__);
+	  fflush(stderr);
+	  free(fcontent);
+	  fprintf(stderr,"%s %d \n",__FILE__,__LINE__);
+	  fflush(stderr);
+	  free(req);
+	  fprintf(stderr,"%s %d \n",__FILE__,__LINE__);
+	  fflush(stderr);
+	}
+      }
+
       // Uploading data input to cluster
       maps* in=getMaps(conf,"uploadQueue");
@@ -371,4 +568,5 @@
       break;
     }
+      
     case 3: {
       // Generating job script
@@ -380,4 +578,5 @@
       break;
     }
+      
     case 4: {
       // Submitting job to cluster
@@ -389,10 +588,11 @@
       break;
     }
+      
     case 5: {
       // Downloading process outputs from cluster
       //json_object* in=mapsToJson(outputs);
-      dumpMaps(outputs);
       maps* curs=outputs;
-      char *keys[8][2]={
+      dumpMaps(curs);
+      char *keys[10][2]={
 	{
 	  "Reference",
@@ -400,9 +600,9 @@
 	},
 	{
-	  "storage",
+	  "generated_file",
 	  "cachefile"
 	},
 	{
-	  "fmimeType",
+	  "mimeType",
 	  "mimetype"
 	},
@@ -412,4 +612,12 @@
 	},
 	{
+	  "geodatatype",
+	  "datatype"
+	},
+	{
+	  "wms_extent",
+	  "boundingbox"
+	},
+	{
 	  "ref_wms_link",
 	  "ref_wms_link"
@@ -420,20 +628,40 @@
 	},
 	{
+	  "ref_wcs_link",
+	  "ref_wcs_preview_link"
+	},
+	{
 	  "ref_wfs_link",
 	  "ref_wfs_link"
-	},
-	{
-	  "geodatatype",
-	  "datatype"
 	}	
+      };
+      char* specifics[5][2]={
+	{
+	  "download_link",
+	  "ref_download_link"
+	},
+	{
+	  "wms_link",
+	  "ref_wms_link"
+	},
+	{
+	  "wfs_link",
+	  "ref_wfs_link"
+	},
+	{
+	  "wcs_link",
+	  "ref_wcs_link"
+	},
+	{
+	  "wcs_link",
+	  "ref_wcs_preview_link"
+	}
       };
       json_object *res1=json_object_new_object();
       while(curs!=NULL){	
-	map* tmpMap=getMap(curs->content,"cache_file");
-	sid=getMap(curs->content,"ref_wms_link");
 	json_object *res2=json_object_new_object();
 	int i=0;
 	int hasRef=-1;
-	for(;i<8;i++){
+	for(;i<10;i++){
 	  sid=getMap(curs->content,keys[i][0]);
 	  if(sid!=NULL){
@@ -448,23 +676,55 @@
 	else{
 	  maps* curs0=curs->child;
-	  while(curs0!=NULL){
-	    json_object *res3=json_object_new_object();
-	    int i0=0;
-	    int hasRef0=-1;
-	    for(;i0<8;i0++){
-	      sid=getMap(curs0->content,keys[i0][0]);
-	      if(sid!=NULL){
-		json_object *jsStr=json_object_new_string(sid->value);
-		json_object_object_add(res3,keys[i0][1],jsStr);
-		//if(i0==0)
-		hasRef0=1;
+	  int i=0;
+	  int bypass=-1;
+	  for(i=0;i<5;i++){
+	    maps* specificMaps;
+	    if((specificMaps=getMaps(curs0,specifics[i][0]))!=NULL){
+	      int hasRef0=-1;
+	      int i0=0;
+	      for(;i0<6;i0++){
+		sid=getMap(specificMaps->content,keys[i0][0]);
+		if(sid!=NULL){
+		  json_object *jsStr=json_object_new_string(sid->value);
+		  if(i0==0){
+		    json_object_object_add(res2,specifics[i][1],jsStr);
+		  }
+		  else
+		    json_object_object_add(res2,keys[i0][1],jsStr);
+		  hasRef0=1;
+		  bypass=1;
+		  if(i==1){
+		    struct stat buf;
+		    char timeStr[ 100 ] = "";
+		    if (stat(sid->value, &buf)==0){
+		      strftime(timeStr, 100, "%d-%m-%Y %H:%M:%S", localtime( &buf.st_mtime));
+		      json_object *jsStr=json_object_new_string(timeStr);
+		      json_object_object_add(res2,"creation_date",jsStr);
+		    }
+		  }
+		}
+	      }	      
+	    }
+	  }
+	  if(bypass<0)
+	    while(curs0!=NULL){
+	      json_object *res3=json_object_new_object();
+	      int i0=0;
+	      int hasRef0=-1;
+	      for(;i0<10;i0++){
+		sid=getMap(curs0->content,keys[i0][0]);
+		if(sid!=NULL){
+		  json_object *jsStr=json_object_new_string(sid->value);
+		  json_object_object_add(res3,keys[i0][1],jsStr);
+		  //if(i0==0)
+		  hasRef0=1;
+		}
 	      }
+	      if(hasRef0<0)
+		json_object_put(res3);
+	      else
+		json_object_object_add(res2,curs0->name,res3);
+	      curs0=curs0->next;
 	    }
-	    if(hasRef0<0)
-	      json_object_put(res3);
-	    else
-	      json_object_object_add(res2,curs0->name,res3);
-	    curs0=curs0->next;
-	  }	  
 	  json_object_object_add(res1,curs->name,res2);
 	}
@@ -474,13 +734,55 @@
       break;
     }
+      
     case 6: {
       // Finalize HPC
-      sid=getMapFromMaps(conf,"lenv","local_script");
-      if(sid!=NULL){
-	json_object *jsStr=json_object_new_string(sid->value);
-	json_object_object_add(res,"inputs",jsStr);
-      }
+      char *keys[6][2]={
+	{
+	  "SubmitTime",
+	  "hpc_submission_date"
+	},
+	{
+	  "JobId",
+	  "hpc_job_identifier"
+	},
+	{
+	  "JobName",
+	  "hpc_job_name"
+	},
+	{
+	  "StartTime",
+	  "hpc_start_date"
+	},
+	{
+	  "EndTime",
+	  "hpc_end_date"
+	},
+	{
+	  "JobState",
+	  "hpc_status"
+	}	
+      };
+      int i=0;
+      if(getMaps(conf,"henv")!=NULL){
+	for(i=0;i<6;i++){
+	  sid=getMapFromMaps(conf,"henv",keys[i][0]);
+	  if(sid!=NULL){
+	    json_object *jsStr=json_object_new_string(sid->value);
+	    json_object_object_add(res,keys[i][1],jsStr);
+	  }
+	}
+      }
+      if((sid=getMapFromMaps(conf,"henv","billing_nb_cpu"))!=NULL){
+        json_object *jsStr=json_object_new_string(sid->value);
+	json_object_object_add(res,"hpc_cpu_usage",jsStr);
+      }else{
+	json_object *jsStr=json_object_new_string("1");
+	json_object_object_add(res,"hpc_cpu_usage",jsStr);
+      }
+      json_object *jsStr=json_object_new_string("succeeded");
+      json_object_object_add(res,"wps_status",jsStr);
       break;
     }
+      
     case 7: {
       // Error or Dismiss
@@ -490,5 +792,9 @@
 	json_object_object_add(res,"message",jsStr);
       }
-      json_object *jsStr=json_object_new_string("failed");
+      json_object *jsStr;
+      if(state==1)
+	jsStr=json_object_new_string("dismissed");
+      else
+	jsStr=json_object_new_string("failed");
       json_object_object_add(res,"wps_status",jsStr);
       break;
@@ -498,11 +804,15 @@
       }
     }
-   
-    local_params* argumentsA=(local_params*)malloc(MAPS_SIZE+MAP_SIZE+sizeof(json_object*)+(2*sizeof(int)));
-    argumentsA->conf=conf;
-    argumentsA->url=url;
-    argumentsA->res=res;
-    argumentsA->step=step;
-    argumentsA->state=state;
+
+    if(local_arguments==NULL)
+      local_arguments=(local_params**)malloc(sizeof(local_params*));
+    else
+      local_arguments=(local_params**)realloc(local_arguments,(nbThreads+1)*sizeof(local_params*));
+    local_arguments[nbThreads]=(local_params*)malloc(MAPS_SIZE+MAP_SIZE+sizeof(json_object*)+(2*sizeof(int)));	
+    local_arguments[nbThreads]->conf=conf;
+    local_arguments[nbThreads]->url=url;
+    local_arguments[nbThreads]->res=res;
+    local_arguments[nbThreads]->step=step;
+    local_arguments[nbThreads]->state=state;
     //pthread_t p1;
     if(myThreads==NULL)
@@ -510,5 +820,5 @@
     else
       myThreads=(pthread_t*)realloc(myThreads,(nbThreads+1)*sizeof(pthread_t));
-    if(pthread_create(&myThreads[nbThreads], NULL, _invokeCallback, (void*)argumentsA)==-1){
+    if(pthread_create(&myThreads[nbThreads], NULL, _invokeCallback, (void*)local_arguments[nbThreads])==-1){
       setMapInMaps(conf,"lenv","message",_("Unable to create a new thread"));
       return false;
@@ -519,9 +829,16 @@
   }
 
+  /**
+   * Wait for the threads to end then, clean used memory.
+   */
   void cleanupCallbackThreads(){
     int i=0;
     for(i=0;i<nbThreads;i++){
+      fprintf(stderr,"%s %d %d \n",__FILE__,__LINE__,i);
+      fflush(stderr);
       pthread_join(myThreads[i],NULL);
-    }
+      free(local_arguments[i]);
+    }
+    free(local_arguments);
     free(myThreads);
   }
