diff --git a/gtf.engine/engine/README.txt b/gtf.engine/engine/README.txt
new file mode 100755
index 0000000000000000000000000000000000000000..96459bdac3a94ee35b94e09ba4c63e35ebce34cf
--- /dev/null
+++ b/gtf.engine/engine/README.txt
@@ -0,0 +1,11 @@
+Compilateur
+
+	Le compilateur utilis� est MinGW version 5.1.6
+	Il est disponible sur PICPOUL --> Partage --> Logiciel --> MinGW --> mingw-get-inst-20111118.exe
+	Une fois install�, copier le dossier openssl du dossier MinGW vers <MinGW>/include
+
+
+Compilation
+
+	Pour compiler, il suffit de double-cliquer sur compil.bat
+	La compilation r�cup�re le num�ro de r�vision SVN l'�crit dans le fichier Changelog.txt, compile l'application puis copie les fichiers dans le dossier gtf.engine
diff --git a/gtf.engine/engine/compil-linux.bat b/gtf.engine/engine/compil-linux.bat
new file mode 100755
index 0000000000000000000000000000000000000000..d395b209f8c493aa2c19890929d1126795d2b74b
--- /dev/null
+++ b/gtf.engine/engine/compil-linux.bat
@@ -0,0 +1,21 @@
+@ECHO OFF
+SET letter=%~d0
+SET currentPath=%~p0
+CALL :ChangeSlashes currentPath
+CALL :LoCase letter
+
+REM Compilation
+bash -c "cd  /mnt/%letter%%currentPath% && gcc -g engine.c sha1.h sha1.c -o engine -LC:\MingW\lib\ -lregex"
+REM copie vers le dossier gtf.engine
+COPY "engine" "../gtf.engines/engine"
+pause
+
+GOTO:EOF
+
+:LoCase
+:: Subroutine to convert a variable VALUE to all lower case.
+:: The argument for this subroutine is the variable NAME.
+FOR %%i IN (":=" "A=a" "B=b" "C=c" "D=d" "E=e" "F=f" "G=g" "H=h" "I=i" "J=j" "K=k" "L=l" "M=m" "N=n" "O=o" "P=p" "Q=q" "R=r" "S=s" "T=t" "U=u" "V=v" "W=w" "X=x" "Y=y" "Z=z") DO CALL SET "%1=%%%1:%%~i%%"
+
+:ChangeSlashes
+FOR %%i IN ("\=/") DO CALL SET "%1=%%%1:%%~i%%"
diff --git a/gtf.engine/engine/compil.bat b/gtf.engine/engine/compil.bat
new file mode 100755
index 0000000000000000000000000000000000000000..cee98ded472d3fc590dc4fbcee88d2f510ab7b02
--- /dev/null
+++ b/gtf.engine/engine/compil.bat
@@ -0,0 +1,34 @@
+@Echo OFF
+%~d0
+cd %~dp0
+REM Recuperation du numero de version
+for /f "delims=" %%i in ('svnversion "../engine"') do Set versionComp=%%i
+REM Initialisation de la variable de recuperation de version
+set versionComp = 2473:2481M
+REM Verification de la structure de num de version renvoye pas SVN
+echo %versionComp% | find ":"
+REM Si le num de version contient : version complexe sinon version simple
+if errorlevel 1 (call :simpleversion) else (call :complexeversion)
+
+
+:simpleversion
+REM Recuperation du num de version simple
+for /f "delims=" %%i in ('echo %versionComp:~0,4%') do Set version=%%i
+goto compil
+
+:complexeversion
+REM Recuperation du num de version simple
+for /f "delims=" %%i in ('echo %versionComp:~5,4%') do Set version=%%i
+goto compil
+
+:compil
+REM Suppression du fichier Changelog
+IF EXIST Changelog.txt DEL Changelog.txt
+REM Ecriture du num de version
+echo %version% > Changelog.txt
+REM Compilation en incluant la librairie psapi
+gcc -g engine.c sha1.h sha1.c -o engine.exe -l"psapi" -LC:\MingW\lib\ -lregex
+REM copie vers le dossier gtf.engine
+COPY "engine.exe" "../gtf.engines/engine.exe"
+COPY "Changelog.txt" "../gtf.engines/Changelog.txt"
+pause
\ No newline at end of file
diff --git a/gtf.engine/engine/engine.c b/gtf.engine/engine/engine.c
new file mode 100755
index 0000000000000000000000000000000000000000..5dd2e7c7963e877d78caef15a11aef26a1a2dc0b
--- /dev/null
+++ b/gtf.engine/engine/engine.c
@@ -0,0 +1,545 @@
+#ifdef __unix__
+	#define OS_Windows 0
+	#define MAX_PATH 4096
+	#include <locale.h>
+	typedef unsigned long DWORD;
+	const char * separator = "/";
+#else
+	#define OS_Windows 1
+	#include <windows.h>
+	#include <Winbase.h>
+	#include <tchar.h>
+	#include <psapi.h>
+	const char * separator = "\\";
+#endif
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h> 
+#include <stdlib.h>
+#include <sys/types.h>  
+#include <unistd.h> 
+#include "sha1.h"
+#include <time.h>
+#include "regex.h"
+#include "engine.h"
+
+#define TAILLE_MAX 1000
+
+int num_pid = 0, debug = 0;
+char *current_directory;
+// const char * separator = "/";
+
+int main(int argc, char *argv[]){
+	int valid = 0;;
+	unsigned int i;
+	if (argc > 1){
+		for (i = 0; i < strlen(argv[1]); ++i){
+			if (!isdigit(argv[1][i]))
+			{
+				valid = 1;
+				break;
+			}
+		}
+		if (valid ==0){
+			if (argc > 2){
+				if (strcmp(argv[2],"d") == 0){
+					debug = 1;
+				}
+			}
+		}else{
+			printf("Syntaxe : engine.exe [moteur_number] [d]\n");
+			printf("d : Debug mode\n");
+
+			exit(1);
+		}
+	}else{
+		printf("Syntaxe : engine.exe [motor_number] [d]\n");
+		printf("d : Debug mode\n");
+
+		exit(1);
+	}
+	//declaration des variables
+	int exist_pid_file = 0;
+	
+	// Nom du fichier pid
+	char* pid_file = malloc(strlen("pid_.txt") + strlen(argv[1]) + 1);
+	sprintf(pid_file, "pid_%s.txt", argv[1]);
+	int result = 0;
+	printf("1\n");
+	//R�cup�ration du r�pertoire courant du fichier courant
+	#ifdef __unix__
+		char *cwd_buffer = malloc(sizeof(char) * MAX_PATH);
+		current_directory = getcwd(cwd_buffer, MAX_PATH);
+	#else
+		char current_path[MAX_PATH];
+		GetModuleFileName( NULL, current_path, MAX_PATH );
+		current_directory = RemplacerFragment((char *)current_path, "\\engine.exe", "");
+	#endif
+	writeToDebugLog("R�pertoire courant : ", current_directory);
+	//remplacement du nom de l exe par le nom du fichier pid
+	char* pid_file_path = malloc(strlen(current_directory) + strlen("/") + strlen(pid_file) + 1);
+	sprintf(pid_file_path, "%s%s%s", current_directory, separator, pid_file);
+
+	writeToDebugLog("fichier PID : ", pid_file_path);
+	//test de l'existence des fichiers
+    exist_pid_file = findPidFile(pid_file_path);
+	
+	char tmp[5];
+	sprintf(tmp, "%i", exist_pid_file);
+	writeToDebugLog("existence Fichier pid (0, n existe pas) : ", tmp);
+	char *motor_number = argv[1];
+	//si fichier inexistant
+	if (exist_pid_file == 0){
+		writeToDebugLog("Execution", " robot non existence fichier pid.");
+		result = execRobot(pid_file_path, motor_number);
+	} else {
+		//si fichier vide
+		if (num_pid == 0){
+			writeToDebugLog("Execution", " robot fichier pid vide.");
+			result = execRobot(pid_file_path, motor_number);
+		} else {
+			sprintf(tmp, "%i", num_pid);
+			writeToDebugLog("num PID : ", tmp);
+			int process = 0;
+			process = verifyProcess(num_pid);
+			if (process == 0){
+				writeToDebugLog("Execution", " robot processus fini.");
+				result = execRobot(pid_file_path, motor_number);
+			}
+		} 
+	}
+	return result;
+}
+
+//fonction de recherche d'un numero de pid
+int findPidFile(char *pid_file_path){
+	//declaration des variables
+	char line[512];
+	int nb_lines = 0;
+	FILE *fic;
+	//ouverture du fichier
+	fic = fopen(pid_file_path, "r"); // ouvrir en lecture
+	
+	//si le programme n a pas trouve de fichier
+	if(fic == NULL){
+		return 0;
+	}
+	//si le programme a trouvee un fichier
+	else{
+		//lecture du fichier
+		while(fgets(line, 512, fic) != NULL){
+			//recuperation du pid
+			num_pid = atoi(line);
+			//passage a la ligne suivante
+			nb_lines++;
+		}
+		//fermeture du fichier
+		fclose(fic); 
+		return 1;
+	}
+}
+
+//Fonction de remplacement de chaine de caractere par une autre : n'existe pas par defaut en c.
+char *RemplacerFragment(char *source, char *vieux, char *nouveau){
+	//Recuperation des parametres
+	char *original = source;
+	char temp[256];
+	int ancienne_long = strlen (vieux);
+	int i, j, k, place = -1;
+	 
+	//recherche de la position de l'occurence tant que la fonction n a pas trouvee
+	for (i = 0; source[i] && (place == -1); ++i){
+		for (j = i, k = 0; source[j] == vieux[k]; j++, k++){
+			if (!vieux[k+1]){
+				place = i;
+			}
+		}
+	}
+	//remplacement de lancienne chaine par la nouvelle
+	if (place != -1){
+		//recuperation de la chaine jusqu a l'emplacement de la chaine a remplacer
+		for (j=0; j < place; j++){
+			temp[j] = source[j];
+		}
+		//remplacement de l ancienne valeur par la nouvelle
+		for (i=0; nouveau[i]; i++, j++){
+			temp[j] = nouveau[i];
+		}
+		//reucperation de la fin de la chaine de caracteres
+		for (k = place + ancienne_long; source[k]; k++, j++){
+			temp[j] = source[k];
+		}
+		temp[j] = 0;
+		for (i=0; (source[i] = temp[i]); i++){
+		}
+	}
+	return original;
+} 
+
+int execRobot(char *pid_file_path, char *motor_number){
+	writeToDebugLog("path pid : ", pid_file_path);
+	getWritePid(pid_file_path);
+	char var_env_engine[MAX_PATH];
+	char var_env_php[MAX_PATH];
+	
+	strcpy(var_env_engine, "GTF_ENGINE_HOME=");
+	strcat(var_env_engine, current_directory);
+	
+	strcpy(var_env_php, "PHP_HOME=");
+	strcat(var_env_php, current_directory);
+	strcat(var_env_php, "/php");
+	
+	writeToDebugLog("", var_env_php);
+	writeToDebugLog("", var_env_engine);
+	putenv(var_env_engine);
+	putenv(var_env_php);
+	putenv("PYTHONPATH=");
+	// Changement de la locale pour traiter les nombres
+	setlocale(LC_NUMERIC, "en_US.UTF8");
+	
+	char *argument = verifyLicense(motor_number);
+	writeToDebugLog("value verification : ", argument);
+	char function_robot[512];
+	if (OS_Windows == 0) {
+		sprintf(function_robot, "\"%s%sphp%sbin%sphp\" \"%s%sengine.php\" %s %s", current_directory, separator, separator, separator, current_directory, separator, motor_number, argument);	
+	} else {
+		sprintf(function_robot, "\"\"%s%sphp%sphp.exe\" \"%s%sengine.php\" %s %s\"", current_directory, separator, separator, current_directory, separator, motor_number, argument);		
+	}
+	writeToDebugLog("function : ", function_robot);
+	system(function_robot);
+
+	remove(pid_file_path);
+	return 0;
+}
+
+void getWritePid(char *pid_file_path){
+	FILE *fic;
+	//ouverture du fichier
+	fic = fopen(pid_file_path, "w"); //"w"  : mode texte en �criture (cr�ation)
+	//recuperation du pid
+	pid_t pid = getpid();
+	fprintf(fic, "%i", pid);
+	fclose(fic);
+}
+
+
+int verifyProcess(int num_pid){
+	int running = 0;
+	int i = 0;
+	int j = 0;
+	char *szProcessName;
+	char *szProcessNameWithSpaces;
+	#ifdef __unix__
+		if (getpgid(num_pid) >= 0){
+			FILE *fic;
+			char* process_path = malloc(strlen("/proc//comm") + 6);
+			sprintf(process_path, "/proc/%i/comm", num_pid);
+			//ouverture du fichier
+			fic = fopen(process_path, "r"); // ouvrir en lecture
+	
+			//si le programme n a pas trouve de fichier
+			if(fic != NULL){
+				//lecture du fichier
+				char line[512];
+				int nb_lines = 0;
+				while(fgets(line, 512, fic) != NULL){
+					//recuperation du nom du pid
+					szProcessNameWithSpaces = line;
+					//passage a la ligne suivante
+					nb_lines++;
+				}
+				//trim 
+				while(i < strlen(szProcessNameWithSpaces)){
+					if (&szProcessNameWithSpaces[i] != " " || &szProcessNameWithSpaces[i] != "\n"){
+						i++;
+					} else {
+						szProcessName[j] = szProcessNameWithSpaces[i];
+						i++;
+						j++;
+					}
+				}
+				//fermeture du fichier
+				fclose(fic);
+				writeToDebugLog("Pid name: ",  szProcessName);
+				writeToDebugLog("Exe file : engine", "");
+				if (strcmp(szProcessName, "engine") == 0){
+					running = 1;
+				}
+			}
+		}
+	#elif defined(_WIN32)
+		HANDLE hProcess=OpenProcess(PROCESS_VM_READ|PROCESS_QUERY_INFORMATION,FALSE, num_pid);
+		if(hProcess){
+			HMODULE hMod;
+			DWORD unused;
+			if(EnumProcessModules(hProcess, &hMod, sizeof(hMod), &unused)){
+				GetModuleBaseNameA(hProcess, hMod, szProcessName, sizeof(szProcessName)/sizeof(char));
+				writeToDebugLog("Pid name: ",  szProcessName);
+				writeToDebugLog("Exe file : engine.exe", "");
+				if (strcmp(szProcessName, "engine.exe") == 0){
+					running = 1;
+				}
+			}
+		}
+	#endif
+	return running;
+}
+
+char *verifyLicense(char *motor_number){
+	char *returnValue = "";
+	char expireDate[TAILLE_MAX] = "";
+	char motorNumber[TAILLE_MAX] = "";
+
+	char* licence_path = malloc(strlen(current_directory) + strlen("licenseslicense.txt") + 3);
+	sprintf(licence_path, "%s%slicenses%slicense.txt", current_directory, separator, separator);
+
+	FILE* fichier = NULL;
+	writeToDebugLog("Fichier License : ",licence_path);
+	fichier = fopen(licence_path, "r");
+	if (fichier != NULL){
+		char chaine[TAILLE_MAX] = "";
+		char testChaine[TAILLE_MAX] = "";
+		// char *chaine = "";
+		char *key;
+		char *temp;
+		char toKey[TAILLE_MAX] = "";
+		int z = 0;
+		while (fgets(chaine, TAILLE_MAX, fichier) != NULL){ // On lit le fichier tant qu'on ne re�oit pas d'erreur (NULL)
+			if (chaine[0]!= '#'){
+				RemplacerFragment(chaine, "\r", "");
+				copie(chaine, testChaine);
+				if (strncmp( verifyRegexp(testChaine, "^Expiry date: (Permanent|[0-9]{6,8})"), "error", 1000)  != 0){
+					RemplacerFragment(testChaine, "Expiry date: ", "");
+					copie(testChaine, expireDate);
+				}
+				if (strncmp( verifyRegexp(testChaine, "^Engines: ([0-9]+)"), "error", 1000)  != 0){
+					RemplacerFragment(testChaine, "Engines: ", "");
+					copie(testChaine, motorNumber);
+				}
+				if (chaine[0]!= 'K'){
+					if (z == 0){
+						z = z+1;
+					}else{
+						strcat(toKey, "\n");
+					}
+					temp = RemplacerFragment(chaine, "\n", "");
+					strcat(toKey, temp);
+				}else{
+					if (chaine[1]!= 'e'){
+						if (z == 0){
+							z = z+1;
+						}else{
+							strcat(toKey, "\n");
+						}
+						temp = RemplacerFragment(chaine, "\n", "");
+						strcat(toKey, temp);
+					}else{
+						if (chaine[2]!= 'y'){
+							if (z == 0){
+								z = z+1;
+							}else{
+								strcat(toKey, "\n");
+							}
+							temp = RemplacerFragment(chaine, "\n", "");
+							strcat(toKey, temp);
+						}else{
+							key=RemplacerFragment(chaine, "Key: ", "");
+						}
+					}
+				}
+			}
+		}
+		writeToDebugLog("Expire Date: ",expireDate);
+		writeToDebugLog("Motor Number: ",motorNumber);
+		writeToDebugLog("clef: ", key);
+		writeToDebugLog("Toclef: ", toKey);
+		SHA1Context sha;
+		int i;
+		SHA1Reset(&sha);
+		for(i = 1; i <= 1000; i++) {
+			SHA1Input(&sha, toKey, strlen(toKey));
+		}
+		if (!SHA1Result(&sha)){
+			 writeToErrorLog("Erreur licence : ", "Impossible de hasher la clef");
+			 returnValue = "E001";
+		}else{
+			char clefTemp[5][TAILLE_MAX];
+			char *clef, *clefTest;
+			for(i = 0; i < 5; i++){
+				sprintf(clefTemp[i], "%X ", sha.Message_Digest[i]);
+			}
+			int j=0;
+			for(j = 0; j < 5; j++){
+				clefTest= clefTemp[j];
+				 if (j == 0){
+					clef = clefTest;
+				}else{
+					strcat(clef, clefTest);
+				}
+			}
+			writeToDebugLog("clef calcul�e: ", clef);
+			int result = strncmp(clef, key, 1000);
+			if (result == 0){
+				writeToDebugLog("Comparaison Clefs: ", "Egales");
+				time_t current_time;
+				current_time = time(NULL);
+				struct tm *nowtm;
+				int yy, mm, dd;
+				yy = makeInt(expireDate +  0, 4) -1900;
+				mm = makeInt(expireDate +  4, 2)-1;
+				dd = makeInt(expireDate +  6, 2);
+				nowtm = localtime(&current_time);
+				writeToDebugLog("Comparaison Date Nombre moteur: ",motorNumber);
+				writeToDebugLog("Comparaison Date num�ro moteur: ",motor_number);
+				if (strncmp(expireDate, "permanent", 1000) ==0){
+					writeToDebugLog("Comparaison Date : ", "OK");
+					if (atoi(motor_number) <= atoi(motorNumber)){
+						writeToDebugLog("Comparaison Moteur : ", "Ok");
+						returnValue = "0";
+					}else{
+						writeToDebugLog("Comparaison Moteur : ", "Num�ro de moteur trop grand");
+						returnValue = "E003";
+					}
+				}else{
+					if (yy < nowtm->tm_year){
+						writeToDebugLog("Comparaison Date : ", "Ann�e courante sup�rieure");
+						writeToErrorLog("Erreur licence : ", "Ann�e courante sup�rieure");
+						returnValue = "E002";
+					}else{
+						if (mm < nowtm->tm_mon){
+							writeToDebugLog("Comparaison Date : ", "Mois courant sup�rieur");
+							returnValue = "E002";
+						}else{
+							if (dd < nowtm->tm_mday){
+								writeToDebugLog("Comparaison Date : ", "Jour courant sup�rieur");
+								returnValue = "E002";
+							}else{
+								writeToDebugLog("Comparaison Date : ", "OK");
+								if (atoi(motor_number) <= atoi(motorNumber)){
+									writeToDebugLog("Comparaison Moteur : ", "Ok");
+									returnValue = "0";
+								}else{
+									writeToDebugLog("Comparaison Moteur : ", "Num�ro de moteur trop grand");
+									writeToErrorLog("Erreur licence : ", "Num�ro de moteur trop grand");
+									returnValue = "E003";
+								}
+							}
+						}
+					}
+				}
+				
+			}else{
+				returnValue = "E001";
+				writeToDebugLog("Comparaison Clefs : ", "Diff�rentes");
+				writeToErrorLog("Erreur licence : ", "Clefs diff�rentes");
+			}
+		} 
+		fclose(fichier);
+	}else{
+		// On affiche un message d'erreur si on veut
+		writeToErrorLog("Erreur licence : ", "Ouverture du fichier impossible");
+		returnValue = "E001";
+	}
+	
+	return returnValue;
+}
+
+void writeToDebugLog(char *titre, char *error){
+	if (debug == 1){
+		FILE *fic;
+		//ouverture du fichier
+		char* debug_file_path = malloc(strlen(current_directory) + strlen("engine.log") + 2);
+		sprintf(debug_file_path, "%s%sengine.log", current_directory, separator);
+		fic = fopen(debug_file_path, "a"); //"w"  : mode texte en �criture (cr�ation)
+		char resultat[MAX_PATH];
+		strcpy(resultat, titre);
+		strcat(resultat, error);
+		strcat(resultat, "\n");
+		//recuperation du pid
+		fprintf(fic, "%s", resultat);
+		fclose(fic); 
+	}
+}
+
+void writeToErrorLog(char *titre, char *error){
+	FILE *fic;
+	//ouverture du fichier
+	char* error_file_path = malloc(strlen(current_directory) + strlen("engine_error.log") + 2);
+	sprintf(error_file_path, "%s%sengine_error.log", current_directory, separator);
+	fic = fopen(error_file_path, "a"); //"w"  : mode texte en �criture (cr�ation)
+	char resultat[MAX_PATH];
+	strcpy(resultat, titre);
+	strcat(resultat, error);
+	strcat(resultat, "\n");
+	//recuperation du pid
+	fprintf(fic, "%s", resultat);
+	fclose(fic);
+}
+
+char *verifyRegexp (char *str_request, char *str_regex){
+	char *returnValue = "error";
+	int err;
+	regex_t preg;
+	err = regcomp (&preg, str_regex, REG_EXTENDED);
+	if (err == 0){
+		int match;
+		size_t nmatch = 0;
+		regmatch_t *pmatch = NULL;
+		nmatch = preg.re_nsub;
+		pmatch = malloc (sizeof (*pmatch) * nmatch);
+		if (pmatch){
+			match = regexec (&preg, str_request, nmatch, pmatch, 0);
+			regfree (&preg);
+			if (match == 0){
+				char *site = NULL;
+				int start = pmatch[0].rm_so;
+				int end = pmatch[0].rm_eo;
+				size_t size = end - start;
+				site = malloc (sizeof (*site) * (size + 1));
+				if (site){
+				   strncpy (site, &str_request[start], size);
+				   site[size] = '\0';
+				   returnValue = site;
+				   free (site);
+				}
+			}else if (match == REG_NOMATCH){
+				returnValue = "error";
+			}else{
+				char *text;
+				size_t size;
+				size = regerror (err, &preg, NULL, 0);
+				text = malloc (sizeof (*text) * size);
+				if (text){
+				   regerror (err, &preg, text, size);
+				   returnValue = text;
+				   free (text);
+				}else{
+				   returnValue = "error";
+				}
+			}
+		}else{
+			 returnValue = "error";
+		}	
+	}else{
+		returnValue = "error";
+	}
+	
+	return returnValue;
+}
+
+void copie(char srce[] , char dest[]) { 
+  register int i;     /* un indice est necessaire */
+  for( i=0 ; (dest[i] = srce[i]) != 0 ; i++) 
+     ;
+}
+
+int makeInt(const char *p, int size){
+    const char *endp;
+    int intval = 0;
+    endp = p + size;
+    while (p < endp){
+        intval = intval * 10 + *p - '0';
+        p++;
+    }
+    return intval;
+}
diff --git a/gtf.engine/engine/engine.h b/gtf.engine/engine/engine.h
new file mode 100755
index 0000000000000000000000000000000000000000..88fa8fbd29a4e4588485da5f25c0cdff7e9e086d
--- /dev/null
+++ b/gtf.engine/engine/engine.h
@@ -0,0 +1,11 @@
+int execRobot(char *pid_file_path, char *motor_number);
+void getWritePid(char *pid_file_path);
+int verifyProcess(int num_pid);
+int findPidFile(char *pid_file_path);
+void copie(char srce[] , char dest[]);
+void writeToDebugLog(char *titre, char *error);
+void writeToErrorLog(char *titre, char *error);
+char *RemplacerFragment(char *source, char *vieux, char *nouveau);
+char *verifyRegexp(char *str_request, char *str_regex);
+char *verifyLicense(char *motor_number);
+int makeInt(const char *,int);
\ No newline at end of file
diff --git a/gtf.engine/engine/php.ini b/gtf.engine/engine/php.ini
new file mode 100755
index 0000000000000000000000000000000000000000..982525bc240cc3348dcaae579a6d87cb56112ae5
--- /dev/null
+++ b/gtf.engine/engine/php.ini
@@ -0,0 +1,162 @@
+[PHP]
+engine = On
+short_open_tag = Off
+asp_tags = Off
+precision = 14
+output_buffering = 4096
+zlib.output_compression = Off
+implicit_flush = Off
+unserialize_callback_func =
+serialize_precision = 17
+disable_functions =
+disable_classes =
+zend.enable_gc = On
+expose_php = On
+max_execution_time = 30
+max_input_time = 60
+memory_limit = 128M
+error_reporting = E_ALL & ~E_NOTICE 
+display_errors = Off
+display_startup_errors = Off
+log_errors = On
+log_errors_max_len = 1024
+ignore_repeated_errors = Off
+ignore_repeated_source = Off
+report_memleaks = On
+track_errors = Off
+html_errors = On
+error_log = php.log
+variables_order = "GPCS"
+request_order = "GP"
+register_argc_argv = Off
+auto_globals_jit = On
+post_max_size = 8M
+auto_prepend_file =
+auto_append_file =
+default_mimetype = "text/html"
+include_path = ".;"
+doc_root =
+user_dir =
+ extension_dir = "ext"
+enable_dl = Off
+file_uploads = On
+upload_max_filesize = 2M
+max_file_uploads = 20
+allow_url_fopen = On
+allow_url_include = Off
+default_socket_timeout = 60
+extension=php_curl.dll
+extension=php_gd2.dll
+extension=php_ldap.dll
+extension=php_mbstring.dll
+extension=php_openssl.dll
+extension=php_pdo_pgsql.dll
+extension=php_xsl.dll
+[CLI Server]
+cli_server.color = On
+[Date]
+date.timezone = "EUROPE/Paris"
+[Pdo_mysql]
+pdo_mysql.cache_size = 2000
+pdo_mysql.default_socket=
+[mail function]
+SMTP = localhost
+smtp_port = 25
+mail.add_x_header = On
+[SQL]
+sql.safe_mode = Off
+[ODBC]
+odbc.allow_persistent = On
+odbc.check_persistent = On
+odbc.max_persistent = -1
+odbc.max_links = -1
+odbc.defaultlrl = 4096
+odbc.defaultbinmode = 1
+[Interbase]
+ibase.allow_persistent = 1
+ibase.max_persistent = -1
+ibase.max_links = -1
+ibase.timestampformat = "%Y-%m-%d %H:%M:%S"
+ibase.dateformat = "%Y-%m-%d"
+ibase.timeformat = "%H:%M:%S"
+[MySQL]
+mysql.allow_local_infile = On
+mysql.allow_persistent = On
+mysql.cache_size = 2000
+mysql.max_persistent = -1
+mysql.max_links = -1
+mysql.default_port =
+mysql.default_socket =
+mysql.default_host =
+mysql.default_user =
+mysql.default_password =
+mysql.connect_timeout = 60
+mysql.trace_mode = Off
+[MySQLi]
+mysqli.max_persistent = -1
+mysqli.allow_persistent = On
+mysqli.max_links = -1
+mysqli.cache_size = 2000
+mysqli.default_port = 3306
+mysqli.default_socket =
+mysqli.default_host =
+mysqli.default_user =
+mysqli.default_pw =
+mysqli.reconnect = Off
+[mysqlnd]
+mysqlnd.collect_statistics = On
+mysqlnd.collect_memory_statistics = Off
+[PostgreSQL]
+pgsql.allow_persistent = On
+pgsql.auto_reset_persistent = Off
+pgsql.max_persistent = -1
+pgsql.max_links = -1
+pgsql.ignore_notice = 0
+pgsql.log_notice = 0
+[Sybase-CT]
+sybct.allow_persistent = On
+sybct.max_persistent = -1
+sybct.max_links = -1
+sybct.min_server_severity = 10
+sybct.min_client_severity = 10
+[bcmath]
+bcmath.scale = 0
+[Session]
+session.save_handler = files
+session.use_strict_mode = 0
+session.use_cookies = 1
+session.use_only_cookies = 1
+session.name = PHPSESSID
+session.auto_start = 0
+session.cookie_lifetime = 0
+session.cookie_path = /
+session.cookie_domain =
+session.cookie_httponly =
+session.serialize_handler = php
+session.gc_probability = 1
+session.gc_divisor = 1000
+session.gc_maxlifetime = 1440
+session.referer_check =
+session.cache_limiter = nocache
+session.cache_expire = 180
+session.use_trans_sid = 0
+session.hash_function = 0
+session.hash_bits_per_character = 5
+url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=fakeentry"
+[MSSQL]
+mssql.allow_persistent = On
+mssql.max_persistent = -1
+mssql.max_links = -1
+mssql.min_error_severity = 10
+mssql.min_message_severity = 10
+mssql.compatibility_mode = Off
+mssql.secure_connection = Off
+[Tidy]
+tidy.clean_output = Off
+[soap]
+soap.wsdl_cache_enabled=1
+soap.wsdl_cache_dir="/tmp"
+soap.wsdl_cache_ttl=86400
+soap.wsdl_cache_limit = 5
+[ldap]
+ldap.max_links = -1
diff --git a/gtf.engine/engine/sha1.c b/gtf.engine/engine/sha1.c
new file mode 100755
index 0000000000000000000000000000000000000000..d87c7f4830013b8e7d749e398b0a15ba15acd5c4
--- /dev/null
+++ b/gtf.engine/engine/sha1.c
@@ -0,0 +1,371 @@
+/*
+ *  sha1.c
+ *
+ *  Copyright (C) 1998, 2009
+ *  Paul E. Jones <paulej@packetizer.com>
+ *  All Rights Reserved
+ *
+ *****************************************************************************
+ *  $Id: sha1.c 12 2009-06-22 19:34:25Z paulej $
+ *****************************************************************************
+ *
+ *  Description:
+ *      This file implements the Secure Hashing Standard as defined
+ *      in FIPS PUB 180-1 published April 17, 1995.
+ *
+ *      The Secure Hashing Standard, which uses the Secure Hashing
+ *      Algorithm (SHA), produces a 160-bit message digest for a
+ *      given data stream.  In theory, it is highly improbable that
+ *      two messages will produce the same message digest.  Therefore,
+ *      this algorithm can serve as a means of providing a "fingerprint"
+ *      for a message.
+ *
+ *  Portability Issues:
+ *      SHA-1 is defined in terms of 32-bit "words".  This code was
+ *      written with the expectation that the processor has at least
+ *      a 32-bit machine word size.  If the machine word size is larger,
+ *      the code should still function properly.  One caveat to that
+ *      is that the input functions taking characters and character
+ *      arrays assume that only 8 bits of information are stored in each
+ *      character.
+ *
+ *  Caveats:
+ *      SHA-1 is designed to work with messages less than 2^64 bits
+ *      long. Although SHA-1 allows a message digest to be generated for
+ *      messages of any number of bits less than 2^64, this
+ *      implementation only works with messages with a length that is a
+ *      multiple of the size of an 8-bit character.
+ *
+ */
+
+#include "sha1.h"
+
+/*
+ *  Define the circular shift macro
+ */
+#define SHA1CircularShift(bits,word) \
+                ((((word) << (bits)) & 0xFFFFFFFF) | \
+                ((word) >> (32-(bits))))
+
+/* Function prototypes */
+void SHA1ProcessMessageBlock(SHA1Context *);
+void SHA1PadMessage(SHA1Context *);
+
+/*  
+ *  SHA1Reset
+ *
+ *  Description:
+ *      This function will initialize the SHA1Context in preparation
+ *      for computing a new message digest.
+ *
+ *  Parameters:
+ *      context: [in/out]
+ *          The context to reset.
+ *
+ *  Returns:
+ *      Nothing.
+ *
+ *  Comments:
+ *
+ */
+void SHA1Reset(SHA1Context *context)
+{
+    context->Length_Low             = 0;
+    context->Length_High            = 0;
+    context->Message_Block_Index    = 0;
+
+    context->Message_Digest[0]      = 0x67452301;
+    context->Message_Digest[1]      = 0xEFCDAB89;
+    context->Message_Digest[2]      = 0x98BADCFE;
+    context->Message_Digest[3]      = 0x10325476;
+    context->Message_Digest[4]      = 0xC3D2E1F0;
+
+    context->Computed   = 0;
+    context->Corrupted  = 0;
+}
+
+/*  
+ *  SHA1Result
+ *
+ *  Description:
+ *      This function will return the 160-bit message digest into the
+ *      Message_Digest array within the SHA1Context provided
+ *
+ *  Parameters:
+ *      context: [in/out]
+ *          The context to use to calculate the SHA-1 hash.
+ *
+ *  Returns:
+ *      1 if successful, 0 if it failed.
+ *
+ *  Comments:
+ *
+ */
+int SHA1Result(SHA1Context *context)
+{
+
+    if (context->Corrupted)
+    {
+        return 0;
+    }
+
+    if (!context->Computed)
+    {
+        SHA1PadMessage(context);
+        context->Computed = 1;
+    }
+
+    return 1;
+}
+
+/*  
+ *  SHA1Input
+ *
+ *  Description:
+ *      This function accepts an array of octets as the next portion of
+ *      the message.
+ *
+ *  Parameters:
+ *      context: [in/out]
+ *          The SHA-1 context to update
+ *      message_array: [in]
+ *          An array of characters representing the next portion of the
+ *          message.
+ *      length: [in]
+ *          The length of the message in message_array
+ *
+ *  Returns:
+ *      Nothing.
+ *
+ *  Comments:
+ *
+ */
+void SHA1Input(     SHA1Context         *context,
+                    const unsigned char *message_array,
+                    unsigned            length)
+{
+    if (!length)
+    {
+        return;
+    }
+
+    if (context->Computed || context->Corrupted)
+    {
+        context->Corrupted = 1;
+        return;
+    }
+
+    while(length-- && !context->Corrupted)
+    {
+        context->Message_Block[context->Message_Block_Index++] =
+                                                (*message_array & 0xFF);
+
+        context->Length_Low += 8;
+        /* Force it to 32 bits */
+        context->Length_Low &= 0xFFFFFFFF;
+        if (context->Length_Low == 0)
+        {
+            context->Length_High++;
+            /* Force it to 32 bits */
+            context->Length_High &= 0xFFFFFFFF;
+            if (context->Length_High == 0)
+            {
+                /* Message is too long */
+                context->Corrupted = 1;
+            }
+        }
+
+        if (context->Message_Block_Index == 64)
+        {
+            SHA1ProcessMessageBlock(context);
+        }
+
+        message_array++;
+    }
+}
+
+/*  
+ *  SHA1ProcessMessageBlock
+ *
+ *  Description:
+ *      This function will process the next 512 bits of the message
+ *      stored in the Message_Block array.
+ *
+ *  Parameters:
+ *      None.
+ *
+ *  Returns:
+ *      Nothing.
+ *
+ *  Comments:
+ *      Many of the variable names in the SHAContext, especially the
+ *      single character names, were used because those were the names
+ *      used in the publication.
+ *         
+ *
+ */
+void SHA1ProcessMessageBlock(SHA1Context *context)
+{
+    const unsigned K[] =            /* Constants defined in SHA-1   */      
+    {
+        0x5A827999,
+        0x6ED9EBA1,
+        0x8F1BBCDC,
+        0xCA62C1D6
+    };
+    int         t;                  /* Loop counter                 */
+    unsigned    temp;               /* Temporary word value         */
+    unsigned    W[80];              /* Word sequence                */
+    unsigned    A, B, C, D, E;      /* Word buffers                 */
+
+    /*
+     *  Initialize the first 16 words in the array W
+     */
+    for(t = 0; t < 16; t++)
+    {
+        W[t] = ((unsigned) context->Message_Block[t * 4]) << 24;
+        W[t] |= ((unsigned) context->Message_Block[t * 4 + 1]) << 16;
+        W[t] |= ((unsigned) context->Message_Block[t * 4 + 2]) << 8;
+        W[t] |= ((unsigned) context->Message_Block[t * 4 + 3]);
+    }
+
+    for(t = 16; t < 80; t++)
+    {
+       W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
+    }
+
+    A = context->Message_Digest[0];
+    B = context->Message_Digest[1];
+    C = context->Message_Digest[2];
+    D = context->Message_Digest[3];
+    E = context->Message_Digest[4];
+
+    for(t = 0; t < 20; t++)
+    {
+        temp =  SHA1CircularShift(5,A) +
+                ((B & C) | ((~B) & D)) + E + W[t] + K[0];
+        temp &= 0xFFFFFFFF;
+        E = D;
+        D = C;
+        C = SHA1CircularShift(30,B);
+        B = A;
+        A = temp;
+    }
+
+    for(t = 20; t < 40; t++)
+    {
+        temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
+        temp &= 0xFFFFFFFF;
+        E = D;
+        D = C;
+        C = SHA1CircularShift(30,B);
+        B = A;
+        A = temp;
+    }
+
+    for(t = 40; t < 60; t++)
+    {
+        temp = SHA1CircularShift(5,A) +
+               ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
+        temp &= 0xFFFFFFFF;
+        E = D;
+        D = C;
+        C = SHA1CircularShift(30,B);
+        B = A;
+        A = temp;
+    }
+
+    for(t = 60; t < 80; t++)
+    {
+        temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
+        temp &= 0xFFFFFFFF;
+        E = D;
+        D = C;
+        C = SHA1CircularShift(30,B);
+        B = A;
+        A = temp;
+    }
+
+    context->Message_Digest[0] =
+                        (context->Message_Digest[0] + A) & 0xFFFFFFFF;
+    context->Message_Digest[1] =
+                        (context->Message_Digest[1] + B) & 0xFFFFFFFF;
+    context->Message_Digest[2] =
+                        (context->Message_Digest[2] + C) & 0xFFFFFFFF;
+    context->Message_Digest[3] =
+                        (context->Message_Digest[3] + D) & 0xFFFFFFFF;
+    context->Message_Digest[4] =
+                        (context->Message_Digest[4] + E) & 0xFFFFFFFF;
+
+    context->Message_Block_Index = 0;
+}
+
+/*  
+ *  SHA1PadMessage
+ *
+ *  Description:
+ *      According to the standard, the message must be padded to an even
+ *      512 bits.  The first padding bit must be a '1'.  The last 64
+ *      bits represent the length of the original message.  All bits in
+ *      between should be 0.  This function will pad the message
+ *      according to those rules by filling the Message_Block array
+ *      accordingly.  It will also call SHA1ProcessMessageBlock()
+ *      appropriately.  When it returns, it can be assumed that the
+ *      message digest has been computed.
+ *
+ *  Parameters:
+ *      context: [in/out]
+ *          The context to pad
+ *
+ *  Returns:
+ *      Nothing.
+ *
+ *  Comments:
+ *
+ */
+void SHA1PadMessage(SHA1Context *context)
+{
+    /*
+     *  Check to see if the current message block is too small to hold
+     *  the initial padding bits and length.  If so, we will pad the
+     *  block, process it, and then continue padding into a second
+     *  block.
+     */
+    if (context->Message_Block_Index > 55)
+    {
+        context->Message_Block[context->Message_Block_Index++] = 0x80;
+        while(context->Message_Block_Index < 64)
+        {
+            context->Message_Block[context->Message_Block_Index++] = 0;
+        }
+
+        SHA1ProcessMessageBlock(context);
+
+        while(context->Message_Block_Index < 56)
+        {
+            context->Message_Block[context->Message_Block_Index++] = 0;
+        }
+    }
+    else
+    {
+        context->Message_Block[context->Message_Block_Index++] = 0x80;
+        while(context->Message_Block_Index < 56)
+        {
+            context->Message_Block[context->Message_Block_Index++] = 0;
+        }
+    }
+
+    /*
+     *  Store the message length as the last 8 octets
+     */
+    context->Message_Block[56] = (context->Length_High >> 24) & 0xFF;
+    context->Message_Block[57] = (context->Length_High >> 16) & 0xFF;
+    context->Message_Block[58] = (context->Length_High >> 8) & 0xFF;
+    context->Message_Block[59] = (context->Length_High) & 0xFF;
+    context->Message_Block[60] = (context->Length_Low >> 24) & 0xFF;
+    context->Message_Block[61] = (context->Length_Low >> 16) & 0xFF;
+    context->Message_Block[62] = (context->Length_Low >> 8) & 0xFF;
+    context->Message_Block[63] = (context->Length_Low) & 0xFF;
+
+    SHA1ProcessMessageBlock(context);
+}
diff --git a/gtf.engine/engine/sha1.h b/gtf.engine/engine/sha1.h
new file mode 100755
index 0000000000000000000000000000000000000000..1ca4b104a9647ebdc20f257b9525af825a3575b7
--- /dev/null
+++ b/gtf.engine/engine/sha1.h
@@ -0,0 +1,54 @@
+/*
+ *  sha1.h
+ *
+ *  Copyright (C) 1998, 2009
+ *  Paul E. Jones <paulej@packetizer.com>
+ *  All Rights Reserved
+ *
+ *****************************************************************************
+ *  $Id: sha1.h 12 2009-06-22 19:34:25Z paulej $
+ *****************************************************************************
+ *
+ *  Description:
+ *      This class implements the Secure Hashing Standard as defined
+ *      in FIPS PUB 180-1 published April 17, 1995.
+ *
+ *      Many of the variable names in the SHA1Context, especially the
+ *      single character names, were used because those were the names
+ *      used in the publication.
+ *
+ *      Please read the file sha1.c for more information.
+ *
+ */
+
+#ifndef _SHA1_H_
+#define _SHA1_H_
+
+/* 
+ *  This structure will hold context information for the hashing
+ *  operation
+ */
+typedef struct SHA1Context
+{
+    unsigned Message_Digest[5]; /* Message Digest (output)          */
+
+    unsigned Length_Low;        /* Message length in bits           */
+    unsigned Length_High;       /* Message length in bits           */
+
+    unsigned char Message_Block[64]; /* 512-bit message blocks      */
+    int Message_Block_Index;    /* Index into message block array   */
+
+    int Computed;               /* Is the digest computed?          */
+    int Corrupted;              /* Is the message digest corruped?  */
+} SHA1Context;
+
+/*
+ *  Function Prototypes
+ */
+void SHA1Reset(SHA1Context *);
+int SHA1Result(SHA1Context *);
+void SHA1Input( SHA1Context *,
+                const unsigned char *,
+                unsigned);
+
+#endif
diff --git a/gtf.engine/gtf.engines/Changelog.txt b/gtf.engine/gtf.engines/Changelog.txt
new file mode 100755
index 0000000000000000000000000000000000000000..34a7e1fcc05d33bfa44138217261d0027204984c
--- /dev/null
+++ b/gtf.engine/gtf.engines/Changelog.txt
@@ -0,0 +1 @@
+2194 
diff --git a/gtf.engine/gtf.engines/Traitement.class.inc b/gtf.engine/gtf.engines/Traitement.class.inc
new file mode 100755
index 0000000000000000000000000000000000000000..1a5c2f39e252daa395ee5fddd73a4a2bc1b43c75
--- /dev/null
+++ b/gtf.engine/gtf.engines/Traitement.class.inc
@@ -0,0 +1,781 @@
+<?php
+
+/**
+ * \file Traitement.class.inc
+ * \brief Traitement.class.inc \n \n Ce fichier contient la classe php Traitement.
+ *
+ * Cette classe virtuelle permet de générer les éléments nécessaires à la création d'un rapport ou
+ * à l'éxécution d'un traitement FME.
+ *
+ * Cette classe permet de générer des fichiers textes, csv ou d'images pour la création de rapport.
+ * Elle permet aussi de lancer la création d'un rapport ou l'éxécution d'un traitement FME.
+ *
+ * \author Fabien Marty <fabien.marty@veremes.com>
+ * \update Matthieu Ambrosy <matthieu.ambrosy@veremes.com>
+ */
+require_once ("vmlib/phpUtil.inc");
+require_once ("vmlib/logUtil.inc");
+require_once ("vmlib/stringUtil.inc");
+require_once ("gtf_lib/GtfFmwParser.class.inc");
+require_once 'string.inc';
+
+class Traitement {
+
+    //Variable stockant l'url du log FME
+    var $sLogFme = "";
+
+    /**
+     * Identifiant de la demande.
+     */
+    var $iDemandeId;
+
+    /**
+     * Fichier de log.
+     */
+    var $sRobotLogFile;
+
+    /**
+     * Objet de la classe Bd. Connexion à la base de données
+     */
+    var $oBd;
+
+    /**
+     * Boolean spécifiant si le traitement est en erreur ou pas.
+     */
+    var $bErreur = false;
+
+    /**
+     * Boolean spécifiant si FME a subit un crash.
+     */
+    var $bFmeCrash = false;
+
+    /**
+     * Message d'erreur.
+     */
+    var $sMessageErreur;
+
+    /**
+     * Tableau des paramètres
+     */
+    var $aParametre;
+
+    /**
+     * Chaine contenant les parametres
+     */
+    var $sParams;
+
+    /**
+     * Emplacement du fichier projet FMW
+     */
+    var $sFmwFileName;
+
+    /**
+     * Tableau des propriétés provenant du fichier properties_robot.inc
+     */
+    var $aProperties;
+
+    /**
+     * Tableau des extensions associées à une source de données GUI
+     */
+    var $aExtension;
+    var $sDestination;
+    var $sSource;
+    var $sSourceTemp = "";
+
+    /**
+     * Cette méthode permet d'initialiser les variables.
+     * \param $oBd Connexion à la base de données.
+     * \param $iDemandeId Identifiant de la demande.
+     * \param $sRobotLogFile Fichier de log.
+     */
+    function __construct($oBd, $iDemandeId, $sRobotLogFile, $sParams, $aProperties, $sFmwFileName) {
+        $this->oBd = $oBd;
+        $this->iDemandeId = $iDemandeId;
+        $this->sRobotLogFile = $sRobotLogFile;
+        $this->sFmwFileName = $sFmwFileName;
+        $this->aParametre = $this->dbParamsAsArray($sParams);
+        $this->sParams = $sParams;
+        $this->aProperties = $aProperties;
+        // table de correspondance entre GTF et le FMW utiliser dans les fonction d'encodage 
+        $this->aReplaceGTF = array("\r\n", " ", "(", ")", "$", "&", "@", "°", "'", ",", "\"", "{", "}", "[", "]", ";", "/", "\\", "é", "à");
+        $this->aReplaceFME = array("<lf>", "<space>", "<openparen>", "<closeparen>", "<dollar>", "<amp>", "<at>", "<u00b0>", "<apos>", "<comma>", "<quote>", "<opencurly>", "<closecurly>", "<openbracket>", "<closebracket>", "<semicolon>", "<solidus>", "<backslash>", "<u00e9>", "<u00e0>");
+
+        writeToLog(str_replace('[this->sFmwFileName]', $this->sFmwFileName, str_replace('[sParams]', $sParams, INFO_RESOURCES)), $this->sRobotLogFile);
+    }
+
+    /*
+     * Initialisation du traitement.
+     * \param $oBd Connexion à la base de données.
+     * \param $iDemandeId Identifiant de la demande.
+     * \param $sLogFile Fichier de log.
+     * \param $sParams Liste des paramètres saisis par l'utilisateur à la création de la demande.
+     * \param $aProperties Tableau des properties associés à l'application
+     * \param $sFmwFileName Nom du fichier FMW associé à la demande.
+     */
+
+    /**
+     * Cette méthode permet de générer un nom de fichier unique.
+     * \return une chaîne de caractères.
+     */
+    function UniqFileName() {
+        $sUniqFileName = date('YmdHis') . rand(1, 100000);
+        return $sUniqFileName;
+    }
+
+    /**
+     * Cette méthode permet de générer un tableau de paramètres à partir d'une chaîne dont les délimiteurs sont "|" et "=".
+     * \param $sAllParams Chaine composé de tous les paramètres.
+     * \return un tableau contenant les paramètres.
+     */
+    function dbParamsAsArray($sAllParams) {
+        $aAllParams = Array();
+        $aLigne = explode("|", $sAllParams);
+        //$aLigne = stringExplode($sAllParams, "|", "\"", "\"");
+        foreach ($aLigne as $sValeur) {
+            $aValeurs = explode("=", $sValeur, 2);
+            if ($aValeurs[1] == "") {
+                writeToLog(INFO_NULL_ELEMENT . $aValeurs[0] . ".", $this->sRobotLogFile);
+            }
+            if (!empty($aValeurs[2])) {
+                $sTemp = $aValeurs[1] . "=" . $aValeurs[2];
+                $aValeurs[1] = $sTemp;
+            }
+            $aAllParams[$aValeurs[0]] = $aValeurs[1];
+            writeToLog(str_replace('[aValeurs[0]]', $aValeurs[0], INFO_DB_PARAM) . $aValeurs[1], $this->sRobotLogFile);
+        }
+        return $aAllParams;
+    }
+
+    /**
+     * Cette méthode permet d'éxécuter une ligne de commande et de stocker les paramètres dans un fichier
+     * \param $sCommand Ligne de commande à éxécuter.
+     */
+    function execute($sCommand, $sFMELogFile) {
+        $sExeName = "FME";
+        if (!$this->bErreur) {
+            set_time_limit(0);
+            //$sResultCommande = exec('"'.$this->aProperties["fme_path"].'" APPLY_SETTINGS "Python/Python Interpreter"', $aResult, $iResult);
+            $sResultCommande = exec('"' . $this->aProperties["fme_path"] . '" APPLY_SETTINGS "Python/Use Custom Python" false', $aResult, $iResult);
+            //writeToLog(INFO_INFORM.$sExeName."| ".'"'.$this->aProperties["fme_path"].'" APPLY_SETTINGS "Python/Python Interpreter"', $this->sRobotLogFile);
+            //writeToLog(INFO_INFORM.$sExeName."| ".$sResultCommande, $this->sRobotLogFile);
+            // $sResultCommande = exec('"'.$this->aProperties["fme_path"].'" APPLY_SETTINGS "Python/Python Interpreter" "C:/apps/FME-2015.1-b15477-32/fmepython27/python27.dll"', $aResult, $iResult);
+            // writeToLog(INFO_INFORM.$sExeName."| APPLY_SETTINGS \"Python/Python Interpreter\" \"C:/apps/FME-2015.1-b15477-32/fmepython27\"", $this->sRobotLogFile);
+            // writeToLog(INFO_INFORM.$sExeName."| ".$sResultCommande, $this->sRobotLogFile);
+            $sResultCommande = exec($sCommand, $aResult, $iResult);
+            if ($sResultCommande == "") {
+                $aResultCommande[0] = true;
+            } else {
+                $aResultCommande = explode("|", $sResultCommande);
+            }
+            //Récupération d'une erreur.
+			if ($iResult !=0){
+            //if ($iResult || ($aResultCommande[0] != 0)) {
+                $this->bErreur = true;
+                if (sizeOf($aResultCommande) == 1)
+                    $this->bFmeCrash = false;
+            }
+            //Écriture dans le log
+            if ($this->bErreur) {
+                if (!empty($aResultCommande[1])) {
+                    if ($this->aProperties["convert_utf8"]) {
+                        $aResultCommande[1] = utf8_decode($aResultCommande[1]);
+                    }
+                    $this->sMessageErreur = "Erreur lors de l exécution de la commande." . $aResultCommande[1] . ".";
+                } else {
+                    $this->sMessageErreur = "Erreur lors de l exécution de la commande. Consultez le log du robot.";
+                }
+				$bExistFMELogFile = true;
+				 if (file_exists($sFMELogFile) === false) {
+					$bExistFMELogFile = false;
+				}
+                foreach ($aResult as $sValeur) {
+                    writeToLog(INFO_ERROR . "   " . "| " . $sValeur, $this->sRobotLogFile);
+					if ($bExistFMELogFile === false){
+						$monfichier = fopen($sFMELogFile, 'a');
+						fputs($monfichier, $sValeur. "\n");
+						fclose($monfichier);
+					}
+                }
+                writeToLog(INFO_COMMAND_ERROR . $sCommand . ".", $this->sRobotLogFile);
+            } else {
+                foreach ($aResult as $sValeur) {
+                    if (mb_detect_encoding($sValeur, "UTF-8, ISO-8859-1") != "UTF-8") {
+                        $sValeur = iconv("ISO-8859-1", "UTF-8", $sValeur);
+                    }
+                    writeToLog(INFO_INFORM . $sExeName . "| " . $sValeur, $this->sRobotLogFile);
+                }
+                writeToLog(INFO_SUCCESSFUL_TREATMENT, $this->sRobotLogFile);
+            }
+        }
+    }
+
+    /**
+     * Cette méthode permet de 7zipper des fichiers.
+     * \param $sZipDir Emplacement des fichiers à zipper.
+     * \param $sZipUrl URL du fichier zip.
+     * \param $sZipFileName Nom du fichier zip à compresser.
+     * \return L'url du fichier zip.
+     */
+    function zipFile($sZipDir, $sZipFileDir, $sZipUrl, $sZipFileName) {
+        writeToLog(str_replace('[sZipDir]', $sZipDir, INFO_FILE_COMPRESSION), $this->sRobotLogFile);
+        if (createZip($sZipDir, $sZipFileDir . '/' . $sZipFileName . '.zip', 'log')) {
+            $sZipFile = $sZipUrl . "/" . $sZipFileName . ".zip";
+            writeToLog(INFO_COMPRESSED_FILES . $sZipFile . ".", $this->sRobotLogFile);
+        } else {
+            $this->bErreur = true;
+            $sZipFile = "";
+            writeToLog(INFO_TREATMENT_FAILURE, $this->sRobotLogFile);
+            writeToLog(str_replace('[sZipFileDir]', $sZipFileDir, str_replace('[sZipDir]', $sZipDir, INFO_FILES_COMPRESSION_FAILURE)) . $sZipFileName, $this->sRobotLogFile);
+            $this->sMessageErreur = "Le traitement n\'a produit aucun résultat. Consultez son log.";
+        }
+        return $sZipFile;
+    }
+
+    function unZipSource($sParam) {
+        $this->sSource = $sParam;
+        // Si la chaine contient un accent, la chaine sera en UTF-8, la fonction file_exists et la fonction de dézippage ne gèrent pas utf-8, il faut donc convertir la chaine en ISO-8859-1
+        $bUtf8Param = false;
+        if (mb_check_encoding($sParam, 'UTF-8')) {
+            $sParam = utf8_decode($sParam);
+            $bUtf8Param = true;
+        }
+        // Si le fichier n'est pas trouvé alors il se trouve dans le répertoire upload
+        if (!file_exists($sParam))
+            $sParam = $this->aProperties["upload_dir"] . "/" . $sParam;
+
+        // If faut gérer l'ensemble des zip (.zip, .7z, .rar, bzip2, gzip, tar, wim, xz)
+        if (mb_eregi("(.ZIP)$", strtoupper($sParam), $aOccurence)) {
+            // Décompression du fichier zip.
+            $sDir = $this->unZipFile($sParam);
+        } else { // Le fichier uploadé n'est pas un fichier zippé
+            $sDir = $sParam;
+            $this->sSourceTemp = "";
+        }
+        // Si le paramètre passé était encodé en UTF-8 il faut le réencoder sinon problème avec les accents.
+        if ($bUtf8Param)
+            $sDir = utf8_encode($sDir);
+        return $sDir;
+    }
+
+    /**
+     * Cette méthode permet de dézipper un fichier.
+     * \param $sZipFile Le fichier zip à décompresser.
+     * \return L'emplacement des fichiers qui ont été extraits.
+     */
+    function unZipFile($sZipFile) {
+        if (!$this->bErreur) {
+            writeToLog(INFO_DECOMPRESSING_FILE . $sZipFile . ".", $this->sRobotLogFile);
+            // Les backslashes du chemin de la variable d'environnement TEMP sont remplacés par des slashes
+            $this->aProperties["extract_dir"] = str_replace("\\", "/", $this->aProperties["extract_dir"]);
+            $sExtractDir = $this->aProperties["extract_dir"] . "/" . $this->UniqFileName() . "/";
+            $this->sSourceTemp = $sExtractDir;
+            if (unZip($sZipFile, $sExtractDir)) {
+                writeToLog(INFO_FILE_COMPRESSION_DIRECTORY . $sExtractDir . ".", $this->sRobotLogFile);
+            } else {
+                $this->bErreur = true;
+                writeToLog(INFO_TREATMENT_FAILURE, $this->sRobotLogFile);
+                writeToLog(str_replace('[sZipFile]', $sZipFile, INFO_FILE_COMPRESSION_FAILURE) . $sExtractDir . ".", $this->sRobotLogFile);
+                $this->sMessageErreur = "Impossible de dézipper le fichier. Consultez le log du robot.";
+                $sExtractDir = "";
+            }
+            return $sExtractDir;
+        }
+    }
+
+    /*
+     * Fonction qui se charge de la mise à jour du paramètre "source" s'il existe
+     * $oGtfFmwParser : Objet GtfFmwParser contenant les GUI
+     * $oGui : Objet GUI de la source
+     * $sDirSource : Chaine de caractère contenant le chemin d'accés à la source de données
+     */
+
+    function updateSourceParam($oGui, $oGtfFmwParser, $sDirSource, $bUsePattern) {
+        $sdelimiterFichier = '"""';
+        $sdelimiterParam = '"';
+        $sSourceMacro = $sdelimiterFichier;
+		$aSourceMacro = array();
+        $i = 0;
+
+        if (is_dir($sDirSource)) {
+            $this->aExtension = $oGui->getExtensionArrayNoLower($oGui->sFiltreSource);
+            $iExtension = count($this->aExtension);
+            if (($this->aExtension[0] == "*.*" and $oGui->sType == "FILE_OR_URL") or $oGui->sType == "DIRNAME_SRC" or $oGui->sType == "SOURCE_GEODATABASE") {
+                writeToLog(INFO_VALID_DATA_SOURCE_FILE_EXTENSION . $this->aExtension[0], $this->sRobotLogFile);
+                $sSourceMacro.= $sdelimiterParam . $sDirSource . '/**/' . $sdelimiterParam;
+            } else {
+				if ($bUsePattern){
+					writeToLog(INFO_USE_PATTERN, $this->sRobotLogFile);
+					foreach ($this->aExtension as $sExtension) {
+						if ($sExtension != "*.*" or ( $sExtension == "*.*" and $iExtension == 1)) { // Si le filtre est différent de *.* (ex : *.mdb) ou si le filtre est seulement *.*. Si le filtre est multiple et que l'un d'eux est *.* (ex : *.*, *.mdb...), il ne sera pas pris en compte
+							$aExtension = explode(".", $sExtension);
+							if ($this->countFilesExtension($sDirSource, $aExtension[1]) > 0) {
+								if ($i != 0)
+									$sSourceMacro.= "<space>";
+								writeToLog(INFO_VALID_DATA_SOURCE_FILE_EXTENSION . $sExtension, $this->sRobotLogFile);
+								$sSourceMacro.= $sdelimiterParam . $sDirSource . '/**/' . $sExtension . $sdelimiterParam;
+								$i++;
+							}
+						}
+					}
+				}else{
+					writeToLog(INFO_NO_USE_PATTERN, $this->sRobotLogFile);
+					foreach ($this->aExtension as $sExtension) {
+						if ($sExtension != "*.*" or ( $sExtension == "*.*" and $iExtension == 1)) { // Si le filtre est différent de *.* (ex : *.mdb) ou si le filtre est seulement *.*. Si le 
+							$aExtension = explode(".", $sExtension);
+							$aSourceMacroTmp = array_merge($aSourceMacro, $this->returnFileListToString($sDirSource, $aExtension[1]));
+							$aSourceMacro = array_unique($aSourceMacroTmp);
+							$i++;
+						}
+					}
+					foreach ($aSourceMacro as $source) {
+						if ($sSourceMacro != $sdelimiterFichier){
+							$sSourceMacro.= "<space>";
+						}
+						$sSourceMacro.= $sdelimiterParam . $source . $sdelimiterParam;
+					}
+                }
+            }
+        }else {
+            $sSourceMacro.= $sdelimiterParam . $sDirSource . $sdelimiterParam;
+        }
+        $sSourceMacro .= $sdelimiterFichier;
+        $this->aParametre[$oGui->sDefault_Macro] = $sSourceMacro;
+		
+        return $sSourceMacro;
+    }
+
+    // Compte le nombre de fichier
+    // $sDirSource : Répertoire de base
+    // $sExtension : Filtre
+    function countFilesExtension($sDirSource, $sExtension) {
+        $num = 0;
+        if (!is_dir($sDirSource)) {
+            $path_parts = pathinfo($sDirSource);
+            if (is_file($sDirSource) && $path_parts['extension'] == $sExtension)
+                return 1;
+            else
+                return false;
+        }
+        foreach (scandir($sDirSource) AS $entry) {
+            if (!in_array($entry, array('..', '.')))
+                $num += $this->countFilesExtension($sDirSource . "/" . $entry, $sExtension);
+        }
+        return $num;
+    }
+	
+	function returnFileListToString($sDirSource, $sExtension) {
+        $aFileList = array();
+        if (!is_dir($sDirSource)) {
+            $path_parts = pathinfo($sDirSource);
+            if (is_file($sDirSource) && strtolower($path_parts['extension']) == strtolower($sExtension)){
+                array_push($aFileList,$sDirSource);
+			}
+            
+        }else{
+			foreach (scandir($sDirSource) AS $entry) {
+				if (!in_array($entry, array('..', '.'))){
+					$aFileListTmp = $aFileList;
+					$aFileList = array_merge($aFileListTmp,$this->returnFileListToString($sDirSource . "/" . $entry, $sExtension));
+				}
+				
+			}
+		}
+        return $aFileList;
+    }
+
+    /*
+     * Fonction qui se charge de la mise à jour du paramètre "source" s'il existe
+     * $oGtfFmwParser : Objet GtfFmwParser contenant les GUI
+     * $oGui : Objet GUI de la source
+     * $sDirSource : Chaine de caractère contenant le chemin d'accés à la source de données
+     */
+
+    function updateDestParam($oGui, $oGtfFmwParser, $sNewDir, $sDest) {
+        $this->aExtension = $oGui->getExtensionArray($oGui->sFiltreDest);
+        if ($sDest == "" && $oGui->sType != "DIRNAME") {
+            $sDest = $sNewDir;
+        }
+        $this->aParametre[$oGui->sDefault_Macro] = "";
+        $sDest = normalizeString($sDest);
+        $aDest = explode(".", $sDest);
+        if ($oGui->sType == "DIRNAME" or $oGui->sType == "DEST_GEODATABASE") {
+            $this->aParametre[$oGui->sDefault_Macro] = $this->aProperties["dir_export"] . "/gtf/" . $sNewDir . "/" . $sDest;
+            writeToLog(INFO_OUTPUT_DATA_DIRECTORY . $this->aParametre[$oGui->sDefault_Macro], $this->sRobotLogFile);
+        }
+        if ($oGui->sType == "FILENAME") {
+            if (count($aDest) > 1) { // Dans GTF, la valeur du champ [nom de fichier en sortie] comporte une extension. Ex : result.xls (le fichier résultat sera de l'excel et sera nommé result.
+                $sResult = $sDest;
+            } else {
+                $sResult = str_replace("*", $sDest, $this->aExtension[0]);
+            }
+            $this->aParametre[$oGui->sDefault_Macro].= $this->aProperties["dir_export"] . "/gtf/" . $sNewDir . '/' . $sResult;
+            $this->sDestination = $sResult;
+
+            writeToLog(INFO_OUTPUT_DATA_FILE . $this->aParametre[$oGui->sDefault_Macro], $this->sRobotLogFile);
+        }
+        else if ($oGui->sType == "FILENAME_EXISTING")
+            $this->aParametre[$oGui->sDefault_Macro] = $sDest;
+        return $this->aParametre[$oGtfFmwParser->sDestMacro];
+    }
+
+    /*     * *************************************************************************************** */
+    /*                                          Codage                                        */
+
+    function unichr($u) {
+        return mb_convert_encoding('&#' . intval($u) . ';', 'UTF-8', 'HTML-ENTITIES');
+    }
+
+    function ordutf8($string, &$offset) {
+        $code = ord(substr($string, $offset, 1));
+        if ($code >= 128) {        //otherwise 0xxxxxxx
+            if ($code < 224)
+                $bytesnumber = 2;                //110xxxxx
+            else if ($code < 240)
+                $bytesnumber = 3;        //1110xxxx
+            else if ($code < 248)
+                $bytesnumber = 4;    //11110xxx
+            $codetemp = $code - 192 - ($bytesnumber > 2 ? 32 : 0) - ($bytesnumber > 3 ? 16 : 0);
+            for ($i = 2; $i <= $bytesnumber; $i++) {
+                $offset ++;
+                $code2 = ord(substr($string, $offset, 1)) - 128;        //10xxxxxx
+                $codetemp = $codetemp * 64 + $code2;
+            }
+            $code = $codetemp;
+        }
+        $offset += 1;
+        if ($offset >= strlen($string))
+            $offset = -1;
+        return $code;
+    }
+
+    function encoderFME($sStr) {
+        //table de correcpondance des symboles UTF-8 avec les codes FME/GTF
+        // ATTENTION : laisser < > en premier sinon replace remplace les balises par d'autre balise
+        $aReplaceGTFToFMW = array("<" => "<lt>", ">" => "<gt>");
+        $sReplaced = $sStr;
+
+        //on gere les chevrons simultanèment pour ne pas gener l'encodage après
+        if (strpos($sReplaced, "<") !== false && strpos($sReplaced, ">") !== false) {
+            $sReplaced = strtr($sReplaced, $aReplaceGTFToFMW);
+        }
+
+        //on remplace tous les encodage par leurs symboles
+        for ($i = 0; $i < count($this->aReplaceGTF); $i++) {
+            if (strpos($sReplaced, $this->aReplaceGTF[$i]) !== false) {
+                $sReplaced = str_replace($this->aReplaceGTF[$i], $this->aReplaceFME[$i], $sReplaced);
+            }
+        }
+
+        // on encode les balises UTF-8 		
+
+        $offset = 0;
+        $iPos = 0;
+
+        while ($offset >= 0) {
+            $iCode = $this->ordutf8($sReplaced, $offset);
+            if ($iCode > 127) {
+                $cLetter = dechex($iCode);
+                while (strlen($sLetter) < 4) {
+                    $cLetter = "0" . $cLetter;
+                }
+                $sReplaced = str_replace($sReplaced[$iPos], "<u" . $cLetter . ">", $sReplaced);
+            }
+            $iPos += 1;
+        }
+
+        return $sReplaced;
+    }
+
+    function decoderFME($sStr) {
+        //table de correcpondance des symboles UTF-8 avec les codes FME/GTF
+        // ATTENTION : laisser < > en premier sinon replace remplace les balises par d'autre balise
+        $aReplaceFMWToGTF = array("<lt>" => "<", "<gt>" => ">");
+        $sReplaced = $sStr;
+
+        //on gere les chevrons simultanèment pour ne pas gener l'encodage après
+        if (strpos($sReplaced, "<lt>") !== false && strpos($sReplaced, "<gt>") !== false) {
+            $sReplaced = strtr($sReplaced, $aReplaceFMWToGTF);
+        }
+        //on remplace tous les encodage par leurs symboles
+        for ($i = 0; $i < count($this->aReplaceGTF); $i++) {
+            if (strpos($sReplaced, $this->aReplaceFME[$i]) !== false) {
+                $sReplaced = str_replace($this->aReplaceFME[$i], $this->aReplaceGTF[$i], $sReplaced);
+            }
+        }
+
+        // on decode les balises UTF-8 		
+        $matches = array();
+
+        preg_match_all("/<u[0-9a-fA-F]{4}>/", $sStr, $matches);
+
+        for ($i = 0; $i < count($matches[0]); $i++) {
+            $iCode = hexdec(substr($matches[0][$i], 2, 4));
+            $cChr = $this->unichr($iCode);
+            $sReplaced = str_replace($matches[0][$i], $cChr, $sReplaced);
+        }
+        return $sReplaced;
+    }
+
+    function isDecode($sStr) {
+        for ($i = 0; $i < count($this->aReplaceFME); $i++) {
+            if (strpos($sStr, $this->aReplaceFME[$i]) !== false && strpos($sStr, $this->aReplaceGTF[$i]) === false) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    function isEncode($sStr) {
+        for ($i = 0; $i < count($this->aReplaceFME); $i++) {
+            if (strpos($sStr, $this->aReplaceFME[$i]) === false && strpos($sStr, $this->aReplaceGTF[$i]) !== false) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /*     * *************************************************************************************** */
+
+    /*
+     *  Fonction qui permet de concaténer tous les paramètres nécessaire pour l'appel du TCL
+     *  et qui retourne $sChaine, la chaine des paramètres à passer au TCL
+     *  $oGtfFmwParser : Objet GtfFmwParser contenant les GUI
+     */
+
+    function getTclParams($oGtfFmwParser, $sNewDir) {
+        $aTGui = array();
+        $sChaine = "";
+		$bUsePattern = false;
+        foreach ($oGtfFmwParser->aGuiObject as $aGui) {
+            if ($aGui->sDefault_Macro != "") {
+                array_push($aTGui, $aGui);
+            }
+			if ($aGui->sDefault_Macro == "GTF_FORCE_PATTERN") {
+				if (strtolower($aGui->sDefaultValue) == "true"){
+					$bUsePattern = true;
+				}
+			}
+        }
+        foreach ($aTGui as $oGui) {
+            //Teste si le paramètre est une source
+            if ($oGui->bIsSource) {
+                if ($this->aParametre[$oGui->sDefault_Macro] != "" && substr($this->aParametre[$oGui->sDefault_Macro], 0, 7) != "<quote>") {
+                    $sDirSource = $this->unZipSource($this->aParametre[$oGui->sDefault_Macro]);
+                    $this->updateSourceParam($oGui, $oGtfFmwParser, $sDirSource, $bUsePattern);
+                }
+            }
+            if ($oGui->bIsDest) {
+                $sDest = $this->aParametre[$oGui->sDefault_Macro];
+                $this->updateDestParam($oGui, $oGtfFmwParser, $sNewDir, $sDest);
+            }
+
+            if ($this->aParametre[$oGui->sDefault_Macro] != "") {
+
+                if (!$oGui->bIsSource) {
+                    // Protection des guillemets de chaque valeur pour qu'ils soient correctement envoyé à traitement.tcl
+                    // Cette protection s'effectue uniquement pour les paramètre qui ne sont pas sources (un paramètre source est de ce type : """"param1"" ""param2"" ""param3"""" : les guillemets seraient donc protégé et cela fait planter l'exécution)
+                    //$this->aParametre[$oGui->sDefault_Macro] = str_replace('"', '""', $this->aParametre[$oGui->sDefault_Macro]);
+                }
+                $aBaliseToReplace = array('<GTF_EQUAL>', '<GTF_PIPE>');
+                $aReplacedBalise = array('=', '|');
+                $sGTFOutput = str_replace($aBaliseToReplace, $aReplacedBalise, $this->aParametre[$oGui->sDefault_Macro]);
+                switch ($oGui->sType) {
+                    case "FLOAT":
+                        $sGTFOutput = str_replace(",", ".", $sGTFOutput);
+                        if (!$this->isDecode($sGTFOutput))
+                            $sGTFOutput = $this->decoderFME($sGTFOutput);
+                        break;
+                    case "LOOKUP_CHOICE":
+                        if (!$this->isEncode($sGTFOutput))
+                            $sGTFOutput = $this->encoderFME($sGTFOutput);
+                        break;
+                    case "TEXT_EDIT" :
+                    case "TEXT_EDIT_OR_NUM" :
+                        if (!$this->isEncode($sGTFOutput)) {
+                            //$sGTFOutput = $this->decoderFME($sGTFOutput);
+                            $sGTFOutput = $this->encoderFME($sGTFOutput);
+                        }
+                        break;
+                    case "CHOICE":
+                    case "LOOKUP_LISTBOX":
+                        $sGTFOutput = str_replace('"', '""', $sGTFOutput);
+                        if (!$this->isDecode($sGTFOutput))
+                            $sGTFOutput = $this->decoderFME($sGTFOutput);
+                        break;
+                    default :
+                        //$sGTFOutput = str_replace('"', '""', $sGTFOutput);
+                        if (!$this->isDecode($sGTFOutput))
+                            $sGTFOutput = $this->decoderFME($sGTFOutput);
+                        break;
+                }
+                // Echappement des doubles quotes pour FME.
+                $sGTFOutput = str_replace('"', '\"', $sGTFOutput);
+                //
+                $sChaine .= " --" . $oGui->sDefault_Macro . " \"" . $sGTFOutput . "\"";
+            }
+        }
+
+        // $sChaine = substr($sChaine, 0, -1)."\"";
+        //$sChaine = substr($sChaine, 0, -1);
+        return $sChaine;
+    }
+
+    function listDir($sDossier, $iDemandeId) {
+        $ouverture = @opendir($sDossier);
+        if (!$ouverture)
+            return false;
+        while ($sFichier = readdir($ouverture)) {
+            if ($sFichier == '.' || $sFichier == '..')
+                continue;
+            if (is_dir($sDossier . $sFichier)) {
+                closedir($ouverture);
+                return true;
+            } else {
+                $path_parts = pathinfo($sDossier . $sFichier);
+                if ($sFichier != "fme_" . $iDemandeId . ".log") {
+                    closedir($ouverture);
+                    return true;
+                }
+            }
+        }
+        closedir($ouverture);
+        return False;
+    }
+
+    /*
+     * Fonction qui retourne le nom du fichier résultat qui sera zippé.
+     *  $sDossier correspond au chemin complet dans lequel les fichiers/dossiers résultats seront générés
+     *  $sNewDir correspond au numéro unique du dossier dans lequel les fichiers/dossiers résultats seront générés
+     *  $iDemandeId correspond au numéro de la demande
+     * \return Retourne NULL (s'il y a plusieurs fichiers résultat à zipper) ou le fichier résultat qui sera zippé sous la forme 20140324141501876/ventes.xlsx
+     */
+
+    function CheckResult($sDossier, $sNewDir, $iDemandeId) {
+        $ouverture = @opendir($sDossier);
+        $NbFile = 0;
+        while ($sFichier = readdir($ouverture)) {
+            if ($sFichier == '.' || $sFichier == '..')
+                continue;
+            if (is_dir($sDossier . $sFichier)) {
+                $NbFile = $NbFile + 2;
+            } else {
+                $path_parts = pathinfo($sDossier . $sFichier);
+                if ($sFichier != "fme_" . $iDemandeId . ".log") {
+                    $NbFile = $NbFile + 1;
+                }
+            }
+        }
+        closedir($ouverture);
+        $ouverture = @opendir($sDossier);
+        if ($NbFile != 1) {
+            return "";
+        } else {
+            $pattern = '/^' . str_replace("*", ".+", str_replace(".", "\\.", $this->aProperties['not_compressed_extension'])) . '$/';
+            while ($sFichier = readdir($ouverture)) {
+                if ($sFichier == '.' || $sFichier == '..')
+                    continue;
+                if ($sFichier != "fme_" . $iDemandeId . ".log") {
+                    if (preg_match($pattern, $sFichier)) {
+                        return $sNewDir . "/" . $sFichier;
+                    } else {
+                        return "";
+                    }
+                }
+            }
+        }
+        closedir($ouverture);
+    }
+
+    /*
+     * fonction qui lance la génération de la ligne de commande, l'éxécution de la demande et la mise en forme du résultat
+     * \return Retourne les fichiers résultant zippés
+     */
+
+    function Process() {
+        $oGtfFmwParser = new GtfFmwParser($this->aProperties["workspace_dir"] . "/" . $this->sFmwFileName);
+        // Création du répertoire de sortie des données
+        $sNewDir = $this->UniqFileName();
+		 if (!file_exists($this->aProperties["dir_export"] . "/gtf/")){
+			mkdir($this->aProperties["dir_export"] . "/gtf/");
+		}
+        $sDestDir = $this->aProperties["dir_export"] . "/gtf/" . $sNewDir;
+        mkdir($sDestDir);
+        // Création de l'URL de téléchargement des données
+        $sDestUrl = $this->aProperties["url_export"] . "/gtf/" . $sNewDir;
+
+        //1 Initialisation & calcul du chemin d'accés du fichier TCL
+        $sCommandLine = '"' . $this->aProperties["fme_path"] . '" "' . getenv("GTF_HOME") . "/" . utf8_decode($this->sFmwFileName) . '"';
+
+
+
+        //3 Ajout des paramètres propres au traitement
+        $sTclParams = $this->getTclParams($oGtfFmwParser, $sNewDir);
+        if ($sTclParams != "")
+            $sCommandLine .= $sTclParams;
+
+		$aTGui = array();
+        $sChaine = "";
+		  // Ajout des paramètres GTF_ s'ils sont associés à un paramètre publié du traitement
+        foreach ($oGtfFmwParser->aGuiObject as $aGui) {
+			switch($aGui->sDefault_Macro) {
+				 case 'GTF_ORDER_ID':
+					$sCommandLine .= " --GTF_ORDER_ID \"" . $this->iDemandeId . "\"";
+					break;
+				 case 'GTF_SHARED_DIR':
+					$sCommandLine .= " --GTF_SHARED_DIR \"" . $this->aProperties["shared_dir"] . "\"";
+					break;
+				 case 'GTF_CONNECTION_STRING':
+					if ($aGui->sType == "PASSWORD"){
+						 $sCommandLine .= "  --GTF_CONNECTION_STRING \"" . $this->aProperties["server"] . "," . $this->aProperties["port"] . "," . $this->aProperties["database"] . "," . $this->aProperties["login_scheduler"] . "," . $this->aProperties["password_scheduler"] . "\"";
+					}
+					 break;
+				 case 'GTF_REST_URL':
+					 $sCommandLine .= "  --GTF_REST_URL \"" . $this->aProperties["web_server_name"] . "/" . $this->aProperties["services_alias"] . "/\"";
+					 break;
+				 //case 'GTF_FORCE_PATTERN':
+			}
+           
+        }
+        /*
+         * 2 Passage des paramètres généraux
+         * - FMWFILENAME : fichier Fmw
+         * - LOG_ROBOT : fichier log du robot
+         * - LOG_FILENAME : fichier log pour FME
+         */
+        $sCommandLine.= " -LOG_FILENAME \"" . $sDestDir . "/fme_" . $this->iDemandeId . ".log\" 2>&1";
+        writeToLog(INFO_GTF_HOME . getenv("GTF_HOME"), $this->sRobotLogFile);
+        writeToLog(INFO_FME_PATH . getenv("FME_PATH"), $this->sRobotLogFile);
+        writeToLog(INFO_TREATMENT_COMMAND_LINE . $sCommandLine, $this->sRobotLogFile);
+
+        //4 Lancement de la ligne de commande
+        $this->sLogFme = $sNewDir . "/fme_" . $this->iDemandeId . ".log";
+        $sSql = "UPDATE " . $this->aProperties['schema_gtf'] . ".order SET log_url='" . $this->sLogFme . "' WHERE order_id=" . $this->iDemandeId;
+        $this->oBd->execute($sSql);
+        $this->execute($sCommandLine, $sDestDir . "/fme_" . $this->iDemandeId . ".log");
+        writeToLog(INFO_TREATMENT_COMMAND_LINE . $sCommandLine, $this->sRobotLogFile);
+        if (file_exists($sDestDir . "/fme_" . $this->iDemandeId . ".log") == false) {
+            $this->sLogFme = "";
+        }
+        $bHasFile = $this->listDir($sDestDir, $this->iDemandeId);
+        if ($this->sSourceTemp != "" && $this->aProperties["debug_mode"] == false) {
+            clearDir($this->sSourceTemp);
+        }
+        if ($bHasFile) {
+            $sIsToZip = $this->CheckResult($sDestDir, $sNewDir, $this->iDemandeId);
+
+            if ($sIsToZip == "") {
+                //Compression en zip des fichiers résultant. Le parametres Array() permet de filtrer les extensions à compresser. Exemples : Array("shp","shx","dbf") ; Array("*")		
+                $sZipFile = $this->zipFile($sDestDir, $sDestDir, $sDestUrl, $this->iDemandeId);
+                $sZipFile = str_replace($sDestUrl, $sNewDir, $sZipFile);
+            } else {
+                $sZipFile = str_replace($sDestUrl, $sNewDir, $sIsToZip);
+            }
+        } else {
+            $sZipFile = "";
+        }
+        return $sZipFile;
+    }
+
+}
+
+?>
diff --git a/gtf.engine/gtf.engines/constants.inc b/gtf.engine/gtf.engines/constants.inc
new file mode 100755
index 0000000000000000000000000000000000000000..d4d3d5abb37ce3086688dd8504f039f67584fec3
--- /dev/null
+++ b/gtf.engine/gtf.engines/constants.inc
@@ -0,0 +1,10 @@
+<?php
+// Définition des constantes
+if (!defined("CR")) {
+	define ("CR",chr(13));
+	define ("LF",chr(10));
+	define ("HT",chr(9));
+}
+define ("VM_FALSE",0);
+define ("VM_TRUE",1);
+?>
\ No newline at end of file
diff --git a/gtf.engine/gtf.engines/engine b/gtf.engine/gtf.engines/engine
new file mode 100755
index 0000000000000000000000000000000000000000..53b01477108bf7e5f77ce52eb5b0c48c458e2dd6
Binary files /dev/null and b/gtf.engine/gtf.engines/engine differ
diff --git a/gtf.engine/gtf.engines/engine.exe b/gtf.engine/gtf.engines/engine.exe
new file mode 100755
index 0000000000000000000000000000000000000000..299a2bc1ca56950134511a6694772126a6f3c03c
Binary files /dev/null and b/gtf.engine/gtf.engines/engine.exe differ
diff --git a/gtf.engine/gtf.engines/engine.php b/gtf.engine/gtf.engines/engine.php
new file mode 100755
index 0000000000000000000000000000000000000000..70a33d3367b59ef821e172a0f9b9d13d36d9ef03
--- /dev/null
+++ b/gtf.engine/gtf.engines/engine.php
@@ -0,0 +1,787 @@
+<?php
+
+/**
+ * \file engine.php
+ * \brief engine.php \n \n Ce fichier contient un programme php.
+ *
+ * Ce programme permet de traiter des demandes de traitements.
+ *
+ * \author Fabien Marty <fabien.marty@veremes.com>
+ */
+$properties["id_gtf_engine"] = $_SERVER['argv'][1]; //Identifiant du moteur calculé à partir de la valeur passée en argument
+$ErrorLicense = $_SERVER['argv'][2]; //Identifiant du moteur calculé à partir de la valeur passée en argument
+
+require_once ("php_engine_conf.inc");
+require_once ("vmlib/BD.class.inc");
+require_once ("vmlib/logUtil.inc");
+require_once("vmlib/dbUtil.inc");
+require_once ("gtf_lib/phpUtility.inc");
+require_once("vmlib/phpUtil.inc");
+
+require_once ("properties_engine.inc");
+require_once ("engine.sql.inc");
+//require_once ("PEAR/Mail.php");
+require_once("Ldap.class.inc");
+
+require_once("vmlib/Email.class.inc");
+require_once("gtf_lib/gtf_object/Order.class.inc");
+require_once("vmlib/error.inc");
+require_once 'string.inc';
+
+loadLang("engines", $properties["language"]);
+if ($ErrorLicense == "0") {
+    //writeToLog('|INFO |PHP| dump prop '. var_export($properties,true),$properties["engine_log_file"]);
+
+    $sDateDebut = new DateTime(date("Y-m-d H:i:s"));
+    $sDateFin = new DateTime(date("Y-m-d H:i:s"));
+
+    //Connexion à la base de données de Données gtf : pas de mot de passe pour le robot
+    $oBd = new BD($properties['login_scheduler'], $properties['password_scheduler'], $properties["database"], $properties["server"], $properties["port"], $properties["sgbd"], $properties["page_encoding"]);
+    //$oBd = new Vm  ('admin', 'admin', $properties["database"], $properties["server"], $properties["port"], $properties["sgbd"], $properties["page_encoding"]);
+    if ($oBd->erreurRencontree) {
+        writeToLog(INFO_BASE_CONNECTION_ERROR . $properties["database"], $properties["engine_log_file"]);
+    } else {
+        writeToLog(INFO_BASE_CONNECTION . $properties["database"], $properties["engine_log_file"]);
+
+        //Recherche du Moteur V2 (ExecuteWithParams)
+        //Selection du chemin fme
+        $aParams = array();
+        $aParams['sSchemaGtf'] = array('value' => $properties['schema_gtf'], 'type' => 'schema_name');
+        $aParams['gtf_engine_id'] = array('value' => $properties['id_gtf_engine'], 'type' => 'number');
+        $oPDOResult = $oBd->executeWithParams($aSql['pgsql']['select_fme_path'], $aParams);
+
+        if ($aRecord = $oBd->ligneSuivante($oPDOResult)) {
+            $properties["fme_path"] = $aRecord['fme_path'];
+        } else {
+            $properties["fme_path"] = '';
+        }
+        putenv("FME_PATH=" . $properties["fme_path"]);
+        putenv("GTF_HOME=" . $properties["workspace_dir"] . "/");
+
+        /*
+        // Traitement des demandes en fonction du moteur
+        $iNbTraitement = 0;
+        $aUserToRefresh = Array();
+        //$sSql = $aSql[$properties["sgbd"]]["boucle_1"];
+        if (TesteHeureCreuse($properties["heure_creuse_min"], $properties["heure_creuse_max"])) { // On est en heure creuse (0 correspond à "Heure Creuse")
+            $iPlageHorraire = 0;
+            $sSql = $aSql[$properties["sgbd"]]["boucle_1"];
+        } else { // On est PAS en heure creuse
+            $iPlageHorraire = 0;
+            $sSql = $aSql[$properties["sgbd"]]["boucle_2"];
+        }
+        $sSql = str_replace("[sSchemaGtf]", $properties["schema_gtf"], $sSql);
+        $sSql = str_replace("[iPriorityId]", $iPlageHorraire, $sSql);
+        $sSql = str_replace("[iIdGtfEngine]", $properties["id_gtf_engine"], $sSql);
+        if ($properties["nbr_order_max"] < 1)
+            $properties["nbr_order_max"] = 1;
+        $sSql = str_replace("[iNnbrOrderMax]", $properties["nbr_order_max"], $sSql);
+        $sEnErreur = 2;
+        $oPDOResult = $oBd->execute($sSql);
+        //*/
+        
+        ///*
+        // Traitement des demandes en fonction du moteur7
+        // Gestion des heures creuses
+        $iNbTraitement = 0;
+        $aUserToRefresh = Array();
+        $aParams = array();
+
+        $iPlageHorraire = 0;
+        
+        $aParams['sSchemaGtf'] = array('value' => $properties['schema_gtf'], 'type' => 'schema_name');
+        $aParams['iPriorityId'] = array('value' => $iPlageHorraire, 'type' => 'number');
+        $aParams['iIdGtfEngine'] = array('value' => $properties["id_gtf_engine"], 'type' => 'number');
+        if ($properties["nbr_order_max"] < 1)
+            $properties["nbr_order_max"] = 1;
+        $aParams['iNnbrOrderMax'] = array('value' => $properties["nbr_order_max"], 'type' => 'number');
+
+        $sEnErreur = 2;
+        
+        if (TesteHeureCreuse($properties["heure_creuse_min"], $properties["heure_creuse_max"])) { // On est en heure creuse (0 correspond à "Heure Creuse")
+            $oPDOResult = $oBd->executeWithParams($aSql[$properties["sgbd"]]["boucle_1"], $aParams);
+        } else { // On est PAS en heure creuse
+            $oPDOResult = $oBd->executeWithParams($aSql[$properties["sgbd"]]["boucle_2"], $aParams);
+        }
+        
+        while ($aDemande = $oBd->ligneSuivante($oPDOResult)) {
+            //test pour connaitre les nombres de tentatives de chaque demande
+            //if ($aDemande['attempt']>=1){    modif par og 26/04/13
+            if ($properties["max_attempt"] == '') {
+                $properties["max_attempt"] = 2;
+            }
+            if ($aDemande['attempt'] >= $properties["max_attempt"]) {
+                writeToLog(str_replace("[aDemande['order_id']]", $aDemande['order_id'], INFO_TOO_MANY_ORDER_ATTEMPT), $properties["engine_log_file"]);
+                $iStatut = 4;
+
+                /*
+                  //Mise à jour de la demande.
+                  $sDateTraitement = Date('Y-m-d H:i:s');
+                  $sSql = $aSql[$properties["sgbd"]]["update_demande"];
+                  $sSql = str_replace("[sSchemaGtf]", $properties["schema_gtf"], $sSql);
+                  $sSql = str_replace("[iStatut]", $iStatut, $sSql);
+                  $sSql = str_replace("[iNbSec]", 0, $sSql);
+                  $sSql = str_replace("[sMessage]", $sMessage, $sSql);
+                  $sSql = str_replace("[sDateTraitement]", $sDateTraitement, $sSql);
+                  $sSql = str_replace("[sResultat]", $sResultat, $sSql);
+                  $sSql = str_replace("[sLogFme]", $sLogFme, $sSql);
+
+                  $sSql = str_replace("[iOrderId]", $aDemande["order_id"], $sSql);
+                  $oPDOResult2 = $oBd->execute($sSql);
+                  // */
+
+                //Mise à jour de la demande V2
+                // Requete d'update de la demande
+                $aParams = array();
+                $aParams['sSchemaGtf'] = array('value' => $properties['schema_gtf'], 'type' => 'schema_name');
+                $aParams['iStatut'] = array('value' => $iStatut, 'type' => 'number');
+                $aParams['iNbSec'] = array('value' => 0, 'type' => 'number');
+                $aParams['sDateTraitement'] = array('value' => $sDateTraitement, 'type' => 'string');
+                $aParams['sResultat'] = array('value' => $sResultat, 'type' => 'string');
+                $aParams['sLogFme'] = array('value' => $sLogFme, 'type' => 'string');
+                $aParams['iOrderId'] = array('value' => $aDemande["order_id"], 'type' => 'number');
+                $oPDOResult2 = $oBd->executeWithParams($aSql[$properties["sgbd"]]["update_demande"], $aParams);
+
+                if ($oBd->erreurRencontree) {
+                    writeToLog(INFO_ORDER_UPDATE_ERROR . "(SQL : $sSql)", $properties["engine_log_file"]);
+                } else {
+                    writeToLog(INFO_ORDER_UPDATE, $properties["engine_log_file"]);
+                    // La demande passe en cours
+                    sendWebsocketMessage($properties['websocket_server'], $properties['websocket_port'], $properties['websocket_alias'], array(
+                        'action' => 'event',
+                        'service' => 'GtfEvents',
+                        'data' => array(
+                            'event' => 'order_started',
+                            'order' => array(
+                                'order_id' => $aDemande['order_id'],
+                                'order_status_id' => $aDemande['order_status_id'],
+                                'user_id' => $aDemande['user_id'],
+                                'workspace_id' => $aDemande['workspace_id']
+                            )
+                        )
+                    ));
+                }
+                $oPDOResult2 = $oBd->fermeResultat();
+            } else {
+
+                /*
+                  //Vérification des droits de l'utilsateur
+                  $sSql = $aSql[$properties["sgbd"]]["getLogin"];
+                  $sSql = str_replace("[sSchemaFramework]", $properties["schema_framework"], $sSql);
+                  $sSql = str_replace("[iUserId]", $aDemande['user_id'], $sSql);
+                  $oPDOResult2 = $oBd->execute($sSql);
+                  // */
+
+                //Vérification des droits de l'utilsateur
+                // Recuperation des login et droits de l'utilisateur en cour
+                $aParams = array();
+                $aParams['sSchemaFramework'] = array('value' => $properties["schema_framework"], 'type' => 'schema_name');
+                $aParams['iUserId'] = array('value' => $aDemande['user_id'], 'type' => 'number');
+                $oPDOResult2 = $oBd->executeWithParams($aSql[$properties["sgbd"]]["getLogin"], $aParams);
+
+                $aUser = $oBd->ligneSuivante($oPDOResult2);
+                $sGroupListId = getUserGroupsEngines($aUser["login"], $oBd, $properties["mixed_rights_management"]);
+                // Mise à jour du nombre de tentative dans la base
+                $iTentative = $aDemande['attempt'] + 1;
+                $sTable = $properties["schema_gtf"] . ".order";
+                $sChamp = "attempt";
+                $sWhere = "order_id";
+                $sListDemande = $aDemande['order_id'];
+                $oBd->updateLinkedTable($sTable, $sChamp, $sWhere, $sListDemande, $iTentative);
+
+                // Mise à jour de l'état de la demande de traitement
+                $oBd->updateLinkedTable($sTable, "order_status_id", $sWhere, $sListDemande, 5);
+
+                writeToLog(str_replace("[aDemande['order_id']]", $aDemande['order_id'], INFO_ORDER_PROCESSING), $properties["engine_log_file"]);
+                // OG 27/03/2013 for table job
+                $sBeginExecutionDate = Date('Y-m-d H:i:s');
+                $date = new DateTime();
+                $iTimeStampBegin = $date->getTimestamp(); // Pour calcul de la durée
+                // fin OG 27/03/2013 for job
+                // $sContenuMail = "";
+                $iNbTraitement = $iNbTraitement + 1;
+                $aUserToRefresh[$iNbTraitement] = $aDemande['user_id'];
+                $aUserToRefresh[$iNbTraitement] = $aDemande['user_id'];
+
+                /*
+                  //Vérification si l'utilisateur a les droits pour faire une demande de ce traitement.
+                  $sSql = $aSql[$properties["sgbd"]]["right_user"];
+                  $sSql = str_replace("[sSchemaGtf]", $properties["schema_gtf"], $sSql);
+                  $sSql = str_replace("[sGroupListId]", $sGroupListId, $sSql);
+                  $oPDOResult2 = $oBd->execute($sSql);
+                  // */
+
+                ///*
+                //Vérification si l'utilisateur a les droits pour faire une demande de ce traitement.
+                $aParams = array();
+                $aParams['sSchemaGtf'] = array('value' => $properties["schema_gtf"], 'type' => 'schema_name');
+                $aParams['sGroupListId'] = array('value' => str_replace(',', '|', $sGroupListId), 'type' => 'group');
+                $oPDOResult2 = $oBd->executeWithParams($aSql[$properties["sgbd"]]["right_user"], $aParams);
+                //*/
+
+                if ($oBd->erreurRencontree) {
+                    writeToLog(INFO_REQUEST_ERROR . $sSql, $properties["engine_log_file"]);
+                    writeToLog(INFO_PHP_ERROR, $properties["engine_log_file"]);
+                    $sMessage = "Erreur SQL.";
+                    // $sContenuMail = 'Votre demande de traitement "'.$aDemande['workspace_nom'].'" a échoué. Voici le message d\'erreur renvoyé : <br><font color="#FF0000">'.$sMessage.'</font><br>';
+                    $iStatut = $sEnErreur;
+                } else {
+                    if ($sGroupListId == "0") {
+                        $bAutorisationDemande = true;
+                    } else {
+                        $bAutorisationDemande = false;
+                        while ($aTraitementsAutorise = $oBd->ligneSuivante($oPDOResult2)) {
+
+                            if ($aTraitementsAutorise['workspace_id'] == $aDemande['workspace_id']) {
+                                $bAutorisationDemande = true;
+                            }
+                        }
+                    }
+                    if ($bAutorisationDemande == true) {
+                        if (class_exists("Traitement.class.inc") == false) {
+                            include_once ("Traitement.class.inc");
+                        }
+
+                        /*
+                          // recuperer le nom du fichier fmw a traiter
+                          $sSql = $aSql[$properties["sgbd"]]["select_traitement"];
+                          $sSql = str_replace("[sSchemaGtf]", $properties["schema_gtf"], $sSql);
+                          $sSql = str_replace("[iWorkspaceId]", $aDemande['workspace_id'], $sSql);
+                          $oPDOResult3 = $oBd->execute($sSql);
+                          // */
+
+                        ///*
+                        // recuperer le nom du fichier fmw a traiter
+                        $aParams = array();
+                        $aParams['sSchemaGtf'] = array('value' => $properties["schema_gtf"], 'type' => 'schema_name');
+                        $aParams['iWorkspaceId'] = array('value' => $aDemande['workspace_id'], 'type' => 'number');
+                        $oPDOResult3 = $oBd->executeWithParams($aSql[$properties["sgbd"]]["select_traitement"], $aParams);
+                        //*/
+
+                        $aTraitement = $oBd->ligneSuivante($oPDOResult3);
+                        $iEmailTemplateId = $aTraitement['email_template_id'];
+                        $oPDOResult3 = $oBd->fermeResultat();
+                        // $sSql = $aSql[$properties["sgbd"]]["select_transit_dir"];
+                        // $oPDOResult4 = $oBd->execute($sSql);
+                        // $aAction = $oBd->ligneSuivante ($oPDOResult4);
+                        // $properties["transit_dir"] = $aAction["value"];
+                        // $oPDOResult4 = $oBd->fermeResultat();
+                        //Lancement du traitement correspondant à la demande.
+                        $aLicence = getFmeLicence($properties['fme_path']);
+                        $bLicenceIsValid = $aLicence['valid'];
+                        $aLicence['valid'] = 1;
+                        if ($aLicence['valid'] == 1) {
+                            $sDateDebut = new DateTime(date("Y-m-d H:i:s"));
+                            $oTraitement = new Traitement($oBd, $aDemande['order_id'], $properties["engine_log_file"], $aDemande['wk_params'], $properties, $aDemande['workspace_id'] . "/fme/" . $aTraitement['fmw_file']);
+
+                            if (!$oTraitement->bErreur) {
+                                $sResultat = $oTraitement->Process();
+                                $sDateFin = new DateTime(date("Y-m-d H:i:s"));
+                                $sLogFme = $oTraitement->sLogFme;
+                            }
+                            //Gestion des erreurs.
+
+                            if ($oTraitement->bFmeCrash)
+                                $iStatut = 1;
+                            elseif ($oTraitement->bErreur) {
+                                if ($aTraitement["failed_action_id"] != "" && $oTraitement->sSource != "") {
+                                    $aSource = explode("/", $oTraitement->sSource);
+                                    $sSourceDirectory = $properties["upload_dir"] . $aSource[0];
+
+                                    if ($aTraitement["failed_action_id"] == 1) {
+                                        clearDir($sSourceDirectory);
+                                        writeToLog(INFO_DELETE_DIRECTORY . $sSourceDirectory . '.', $properties["engine_log_file"]);
+                                    } elseif ($aTraitement["failed_action_id"] == 2) {
+                                        /*
+                                          $sSql = $aSql[$properties["sgbd"]]["select_user"];
+                                          $sSql = str_replace("[iUserId]", $aDemande['user_id'], $sSql);
+                                          $sSql = str_replace("[sSchemaFramework]", $properties["schema_framework"], $sSql);
+                                          $oPDOResult2 = $oBd->execute($sSql);
+                                          // */
+                                        ///*
+                                        // Selection de l'utilisateur
+                                        $aParams = array();
+                                        $aParams['iUserId'] = array('value' => $aDemande['user_id'], 'type' => 'number');
+                                        $aParams['sSchemaFramework'] = array('value' => $properties["schema_framework"], 'type' => 'schema_name');
+                                        $oPDOResult2 = $oBd->executeWithParams($aSql[$properties["sgbd"]]["select_user"], $aParams);
+                                        //*/
+                                        if ($oBd->erreurRencontree) {
+                                            writeToLog(INFO_GET_USER_INFO_ERROR . $aDemande['user_id'] . ". (SQL = " . $sSql . ")", $properties["engine_log_file"]);
+                                        } else {
+                                            $aUser = $oBd->ligneSuivante($oPDOResult2);
+
+                                            $sUser = userToFolder($aUser["name"]);
+                                            if (file_exists($properties["transit_dir"])) {
+                                                if (!file_exists($properties["transit_dir"] . "/failed/")) {
+                                                    mkdir($properties["transit_dir"] . "/failed/");
+                                                }
+                                                if (!file_exists($properties["transit_dir"] . "/failed/" . $sUser)) {
+                                                    mkdir($properties["transit_dir"] . "/failed/" . $sUser);
+                                                }
+                                                if (!file_exists($properties["transit_dir"] . "/failed/" . $sUser . "/" . $aTraitement["workspace_id"])) {
+                                                    mkdir($properties["transit_dir"] . "/failed/" . $sUser . "/" . $aTraitement["workspace_id"]);
+                                                }
+                                                rename($sSourceDirectory, $properties["transit_dir"] . "/failed/" . $sUser . "/" . $aTraitement["workspace_id"] . "/" . $aDemande["order_id"]);
+                                                writeToLog(str_replace('[sSourceDirectory]', $sSourceDirectory, INFO_MOVING_FILE) . $properties["transit_dir"] . "/failed/" . $sUser . "/" . $aTraitement["workspace_id"] . "/" . $aDemande["order_id"] . '.', $properties["engine_log_file"]);
+                                            } else {
+                                                writeToLog(str_replace("[properties['transit_dir']]", $properties['transit_dir'], INFO_DIRECTORY_NOT_FOUND_ENGINE), $properties["engine_log_file"]);
+                                                $iStatut = $sEnErreur;
+                                            }
+                                        }
+                                    }
+                                }
+                                $sMessage = $oTraitement->sMessageErreur;
+                                $iStatut = $sEnErreur;
+                                $sResultat = '';
+                                // $sContenuMail = 'Votre demande de traitement "'.$aDemande['workspace_nom'].'" a échoué. Voici le message d\'erreur renvoyé : <br><font color="#FF0000">'.$sMessage.'</font><br>';
+                                // $sContenuMail .= "Contactez l'administrateur pour consulter le fichier de log du robot.<br>";
+                                $sLienLogFme = $sLogFme;
+                            } else {
+                                if ($aTraitement["success_action_id"] != "" && $oTraitement->sSource != "") {
+                                    $aSource = explode("/", $oTraitement->sSource);
+                                    $sSourceDirectory = $properties["upload_dir"] . $aSource[0];
+                                    if ($aTraitement["success_action_id"] == 1) {
+                                        clearDir($sSourceDirectory);
+                                        writeToLog(INFO_DELETE_DIRECTORY . $sSourceDirectory . '.', $properties["engine_log_file"]);
+                                    } elseif ($aTraitement["success_action_id"] == 2) {
+
+                                        /*
+                                          $sSql = $aSql[$properties["sgbd"]]["select_user"];
+                                          $sSql = str_replace("[iUserId]", $aDemande['user_id'], $sSql);
+                                          $sSql = str_replace("[sSchemaFramework]", $properties["schema_framework"], $sSql);
+                                          $oPDOResult2 = $oBd->execute($sSql);
+                                          // */
+                                        ///*
+                                        //Selection de l'utilisateur
+                                        $aParams = array();
+                                        $aParams['iUserId'] = array('value' => $aDemande['user_id'], 'type' => 'number');
+                                        $aParams['sSchemaFramework'] = array('value' => $properties["schema_framework"], 'type' => 'schema_name');
+                                        $oPDOResult2 = $oBd->executeWithParams($aSql[$properties["sgbd"]]["select_user"], $aParams);
+                                        //*/
+
+                                        if ($oBd->erreurRencontree) {
+                                            writeToLog(INFO_GET_USER_INFO_ERROR . $aDemande['user_id'] . ". (SQL = " . $sSql . ")", $properties["engine_log_file"]);
+                                        } else {
+                                            $aUser = $oBd->ligneSuivante($oPDOResult2);
+                 
+                                            $sUser = userToFolder($aUser["name"]);
+                                            if (file_exists($properties["transit_dir"])) {
+                                                if (!file_exists($properties["transit_dir"] . "/success/")) {
+                                                    mkdir($properties["transit_dir"] . "/success/");
+                                                }
+                                                if (!file_exists($properties["transit_dir"] . "/success/" . $sUser)) {
+                                                    mkdir($properties["transit_dir"] . "/success/" . $sUser);
+                                                }
+                                                if (!file_exists($properties["transit_dir"] . "/success/" . $sUser . "/" . $aTraitement["workspace_id"])) {
+                                                    mkdir($properties["transit_dir"] . "/success/" . $sUser . "/" . $aTraitement["workspace_id"]);
+                                                }
+                                                rename($sSourceDirectory, $properties["transit_dir"] . "/success/" . $sUser . "/" . $aTraitement["workspace_id"] . "/" . $aDemande["order_id"]);
+                                                writeToLog(str_replace('[sSourceDirectory]', $sSourceDirectory, INFO_MOVING_FILE) . $properties["transit_dir"] . "/success/" . $sUser . "/" . $aTraitement["workspace_id"] . "/" . $aDemande["order_id"] . '.', $properties["engine_log_file"]);
+                                            } else {
+                                                writeToLog(str_replace("[properties['transit_dir']]", $properties['transit_dir'], INFO_DIRECTORY_NOT_FOUND_ENGINE), $properties["engine_log_file"]);
+                                                $iStatut = $sEnErreur;
+                                            }
+                                        }
+                                    }
+                                }
+                                $sMessage = "";
+                                $iStatut = 3;
+                                // $sContenuMail = "Votre demande de traitement '".$aDemande['workspace_nom']."' a réussi.<br>";
+                                if ($sResultat != "") {
+                                    // $sContenuMail .= '<A href="'.$properties["url_export"]."/".$sResultat.'">Télécharger le résultat</A><br>';
+                                    $sLienResultat = $sResultat;
+                                }
+                                $sLienLogFme = $sLogFme;
+                            }
+                            unset($oTraitement);
+                        } else {
+                            $iTentative = $iTentative - 1;
+                            $sTable = $properties["schema_gtf"] . ".order";
+                            $sChamp = "attempt";
+                            $sWhere = "order_id";
+                            $sListDemande = $aDemande['order_id'];
+                            $oBd->updateLinkedTable($sTable, $sChamp, $sWhere, $sListDemande, $iTentative);
+                            writeToLog(INFO_INVALID_FME_LICENCE_FILE, $properties["engine_log_file"]);
+                            writeToLog(INFO_CONTACT_ADMINISTRATOR, $properties["engine_log_file"]);
+                            $sMessage = "Invalid FME licence file. ";
+                            // $sContenuMail = 'Votre demande de traitement "'.$aDemande['workspace_nom'].'" a échoué. Voici le message d\'erreur renvoyé : <br><font color="#FF0000">'.$sMessage.'</font><br>';
+                            $iStatut = 1;
+                            $sLienLogFme = 'Non disponible';
+                        }
+                    } else {
+                        writeToLog(INFO_NO_USER_GRANT . $aDemande['workspace_nom'] . ' n\'a pas été défini.', $properties["engine_log_file"]);
+                        writeToLog(INFO_CONTACT_ADMINISTRATOR, $properties["engine_log_file"]);
+                        $sMessage = "Vous n''avez pas les droits nécessaires pour réaliser ce traitement.";
+                        // $sContenuMail = 'Votre demande de traitement "'.$aDemande['workspace_nom'].'" a échoué. Voici le message d\'erreur renvoyé : <br><font color="#FF0000">'.$sMessage.'</font><br>';
+                        $iStatut = 6;
+
+                        if (file_exists($sLogFme)) {
+                            $sLienLogFme = $sLogFme;
+                        } else {
+                            $sLienLogFme = 'Non disponible';
+                        }
+                    }
+                }
+                $oPDOResult2 = $oBd->fermeResultat();
+
+                //Mise à jour de la demande.
+
+                if ($iStatut == 3) {
+                    /*
+                      $sSql = $aSql[$properties["sgbd"]]["update_message"];
+                      $sSql = str_replace("[sSchemaGtf]", $properties["schema_gtf"], $sSql);
+                      $sSql = str_replace("[iOrderId]", $aDemande["order_id"], $sSql);
+                      $oPDOResult2 = $oBd->execute($sSql);
+                      // */
+                    ///*
+                    // Mise a jour du message
+                    $aParams = array();
+                    $aParams['sSchemaGtf'] = array('value' => $properties["schema_gtf"], 'type' => 'schema_name');
+                    $aParams['iOrderId'] = array('value' => $aDemande["order_id"], 'type' => 'number');
+                    $oPDOResult2 = $oBd->executeWithParams($aSql[$properties["sgbd"]]["update_message"], $aParams);
+                    //*/
+                    if ($oBd->erreurRencontree) {
+                        writeToLog(INFO_TEST_REQUEST_ERROR . '(' . $oBd->getBDMessage() . ')', $properties["engine_log_file"]);
+                    }
+                    // Fin - OG 27/03/2013 for table job
+                    $oPDOResult2 = $oBd->fermeResultat();
+                }
+                if ($iStatut == 2 || $iStatut == 4) {
+
+                    /*
+                      $sSql = $aSql[$properties["sgbd"]]["delete_message"];
+                      $sSql = str_replace("[sSchemaGtf]", $properties["schema_gtf"], $sSql);
+                      $sSql = str_replace("[iOrderId]", $aDemande["order_id"], $sSql);
+                      $oPDOResult2 = $oBd->execute($sSql);
+                      // */
+                    ///*
+                    
+                    // Mise a jour du message
+                    $aParams = array();
+                    $aParams['sSchemaGtf'] = array('value' => $properties["schema_gtf"], 'type' => 'schema_name');
+                    $aParams['iOrderId'] = array('value' => $aDemande["order_id"], 'type' => 'number');
+                    $oPDOResult2 = $oBd->executeWithParams($aSql[$properties["sgbd"]]["update_message"], $aParams);
+                    //*/
+
+                    if ($oBd->erreurRencontree) {
+                        writeToLog(INFO_TEST_REQUEST_ERROR . '(' . $oBd->getBDMessage() . ')', $properties["engine_log_file"]);
+                    }
+                    // Fin - OG 27/03/2013 for table job
+                    $oPDOResult2 = $oBd->fermeResultat();
+                }
+                $sDateTraitement = Date('Y-m-d H:i:s');
+
+                /*
+                $sSql = $aSql[$properties["sgbd"]]["update_demande"];
+                $sSql = str_replace("[sSchemaGtf]", $properties["schema_gtf"], $sSql);
+                if ($iStatut != 1) {
+                    $timeFirst = strtotime(date_format($sDateDebut, 'Y-m-d H:i:s'));
+                    $timeSecond = strtotime(date_format($sDateFin, 'Y-m-d H:i:s'));
+                    $diff = $timeSecond - $timeFirst;
+                    $iNbSec = $diff;
+                } else {
+                    $iNbSec = "NULL";
+                }
+                // OG 27/03/2013 for table job
+                $date = new DateTime();
+                $iTimeStampEnd = $date->getTimestamp();
+                $iDelay = $iTimeStampEnd - $iTimeStampBegin;
+                $sSql = str_replace("[iNbSec]", $iDelay, $sSql);
+                $sSql = str_replace("[$iStatut]", $iStatut, $sSql);
+                /* $sSql = str_replace("[sMessage]", $sMessage, $sSql); *//*
+                $sSql = str_replace("[sDateTraitement]", $sDateTraitement, $sSql);
+                $sSql = str_replace("[sResultat]", utf8_encode($sResultat), $sSql);
+                $sSql = str_replace("[iOrderId]", $aDemande["order_id"], $sSql);
+                if ($sLogFme == "") {
+                    $sSql = str_replace("'[sLogFme]'", "NULL", $sSql);
+                } else {
+                    $sSql = str_replace("[sLogFme]", $sLogFme, $sSql);
+                }
+
+                $oPDOResult2 = $oBd->execute($sSql);
+                //*/
+
+                //*
+                // Mise a jour de la demande
+                  $aParams = array();
+                  $aParams['sSchemaGtf'] = array('value' => $properties["schema_gtf"], 'type' => 'schema_name');
+                  if ($iStatut != 1) {
+                  $timeFirst = strtotime(date_format($sDateDebut, 'Y-m-d H:i:s'));
+                  $timeSecond = strtotime(date_format($sDateFin, 'Y-m-d H:i:s'));
+                  $diff = $timeSecond - $timeFirst;
+                  $iNbSec = $diff;
+                  } else {
+                  $iNbSec = "NULL";
+                  }
+                  // OG 27/03/2013 for table job
+                  $date = new DateTime();
+                  $iTimeStampEnd = $date->getTimestamp();
+                  $iDelay = $iTimeStampEnd - $iTimeStampBegin;
+                  $aParams['iNbSec'] = array('value' => $iDelay, 'type' => 'number');
+                  $aParams['iStatut'] = array('value' => $iStatut, 'type' => 'number');
+                  $aParams['sDateTraitement'] = array('value' => $sDateTraitement, 'type' => 'string');
+                  $aParams['sResultat'] = array('value' =>  utf8_encode($sResultat), 'type' => 'string');
+                  $aParams['iOrderId'] = array('value' =>  $aDemande["order_id"], 'type' => 'number');
+                  if ($sLogFme == "") {
+                  $aParams['sLogFme'] = array('value' =>  "NULL", 'type' => 'string');
+                  } else {
+                  $aParams['sLogFme'] = array('value' =>  $sLogFme, 'type' => 'string');
+                  }
+
+                  $oPDOResult2 = $oBd->executeWithParams($aSql[$properties["sgbd"]]["update_demande"], $aParams);
+                  // */
+
+
+                if ($oBd->erreurRencontree) {
+                    writeToLog(INFO_ORDER_UPDATE_ERROR . '(' . $oBd->getBDMessage() . ')', $properties["engine_log_file"]);
+                } else {
+                    writeToLog(INFO_ORDER_UPDATE, $properties["engine_log_file"]);
+                    // La demande est terminée avec un résultat
+                    sendWebsocketMessage($properties['websocket_server'], $properties['websocket_port'], $properties['websocket_alias'], array(
+                        'action' => 'event',
+                        'service' => 'GtfEvents',
+                        'data' => array(
+                            'event' => 'order_finished_with_result',
+                            'order' => array(
+                                'order_id' => $aDemande['order_id'],
+                                'order_status_id' => $aDemande['order_status_id'],
+                                'user_id' => $aDemande['user_id'],
+                                'workspace_id' => $aDemande['workspace_id']
+                            )
+                        )
+                    ));
+                }
+                if ($iStatut != 1) {
+                    /*
+                      $sSql = $aSql[$properties["sgbd"]]["insertJob"];
+                      $sSql = str_replace("[sSchemaGtf]", $properties["schema_gtf"], $sSql);
+                      $sSql = str_replace("[iOrderId]", $aDemande["order_id"], $sSql);
+                      $sSql = str_replace("[iWorkspaceId]", $aDemande["workspace_id"], $sSql);
+                      $sSql = str_replace("[iUserId]", $aDemande['user_id'], $sSql);
+                      $sSql = str_replace("[sBeginExecutionDate]", $sBeginExecutionDate, $sSql);
+                      $sSql = str_replace("[iDelay]", $iDelay, $sSql);
+                      $sSql = str_replace("[iGtfEngineId]", $properties["id_gtf_engine"], $sSql);
+                      $sSql = str_replace("[iStatut]", $iStatut, $sSql);
+                      //writeToLog('|INFORM|PHP|Test requête OG : '.$sSql,$properties["engine_log_file"]);
+                      $oPDOResult2 = $oBd->execute($sSql);
+                      // */
+                    ///*
+                    // Insert de schemaGtf
+                    $aParams = array();
+                    $aParams['sSchemaGtf'] = array('value' => $properties["schema_gtf"], 'type' => 'schema_name');
+                    $aParams['iOrderId'] = array('value' => $aDemande["order_id"], 'type' => 'number');
+                    $aParams['iWorkspaceId'] = array('value' => $aDemande["workspace_id"], 'type' => 'number');
+                    $aParams['iUserId'] = array('value' => $aDemande['user_id'], 'type' => 'number');
+                    $aParams['sBeginExecutionDate'] = array('value' => $sBeginExecutionDate, 'type' => 'string');
+                    $aParams['iDelay'] = array('value' => $iDelay, 'type' => 'number');
+                    $aParams['iGtfEngineId'] = array('value' => $properties["id_gtf_engine"], 'type' => 'number');
+                    $aParams['iDelay'] = array('value' => $iDelay, 'type' => 'number');
+                    $aParams['iStatut'] = array('value' => $iStatut, 'type' => 'number');
+                    //writeToLog('|INFORM|PHP|Test requête OG : '.$sSql,$properties["engine_log_file"]);
+                    $oPDOResult2 = $oBd->executeWithParams($aSql[$properties["sgbd"]]["insertJob"], $aParams);
+                    //*/
+                    if ($oBd->erreurRencontree) {
+                        writeToLog(INFO_TEST_REQUEST_ERROR . '(' . $oBd->getBDMessage() . ')', $properties["engine_log_file"]);
+                    }
+                    // Fin - OG 27/03/2013 for table job
+                    $oPDOResult2 = $oBd->fermeResultat();
+                }
+                // Mise à jour de la demande si resultat est vide
+                if ($sResultat == "") {
+
+                    /*
+                      $sSql = $aSql[$properties["sgbd"]]["update_demande_resultat_null"];
+                      $sSql = str_replace("[sSchemaGtf]", $properties["schema_gtf"], $sSql);
+                      $sSql = str_replace("[iOrderId]", $aDemande["order_id"], $sSql);
+                      $oPDOResult2 = $oBd->execute($sSql);
+                      // */
+
+                    ///*
+                    // Mise a jour de la demande si resultat null
+                    $aParams = array();
+                    $aParams['sSchemaGtf'] = array('value' => $properties["schema_gtf"], 'type' => 'schema_name');
+                    $aParams['iOrderId'] = array('value' => $aDemande["order_id"], 'type' => 'number');
+                    $oPDOResult2 = $oBd->executeWithParams($aSql[$properties["sgbd"]]["update_demande_resultat_null"], $aParams);
+                    //*/
+
+                    if ($oBd->erreurRencontree) {
+                        writeToLog(INFO_ORDER_UPDATE_ERROR . ' (' . $oBd->getBDMessage() . ')', $properties["engine_log_file"]);
+                    } else {
+                        writeToLog(INFO_INFO_ORDER_UPDATE_NULL, $properties["engine_log_file"]);
+                        // La demande est terminée où en erreur
+                        sendWebsocketMessage($properties['websocket_server'], $properties['websocket_port'], $properties['websocket_alias'], array(
+                            'action' => 'event',
+                            'service' => 'GtfEvents',
+                            'data' => array(
+                                'event' => 'order_finished_or_error',
+                                'order' => array(
+                                    'order_id' => $aDemande['order_id'],
+                                    'order_status_id' => $aDemande['order_status_id'],
+                                    'user_id' => $aDemande['user_id'],
+                                    'workspace_id' => $aDemande['workspace_id']
+                                )
+                            )
+                        ));
+                    }
+                    $oPDOResult2 = $oBd->fermeResultat();
+                }
+
+                // Notification par e-mail.
+                $bMailToSend = false;
+                switch (strtoupper(trim($aDemande['email_option_id']))) {
+                    case 1:
+                        $bMailToSend = True;
+                        break;
+                    case 2:
+                        $bMailToSend = False;
+                        break;
+                    case 3:
+                        if ($iStatut == $sEnErreur) {
+                            $bMailToSend = True;
+                        }
+                        break;
+                    case 4:
+                        if ($iStatut != $sEnErreur) {
+                            $bMailToSend = True;
+                        }
+                        break;
+                    default:
+                        $bMailToSend = True;
+                }
+
+                // Licence invalide.
+                if ($iStatut == 2 && !$bLicenceIsValid) {
+                    // Mise à jour de l'état de la demande de traitement (en attente).
+                    $oBd->updateLinkedTable($properties["schema_gtf"] . ".order", "order_status_id", "order_id", $aDemande['order_id'], 1);
+                    // Licence invalide : 1 mail par jour max.
+                    $sToday = date('d/m/Y');
+                    $sMailLicenceFile = __DIR__ . '\mail_licence.txt';
+                    if (file_exists($sMailLicenceFile))
+                        if (file_get_contents($sMailLicenceFile) == $sToday)
+                            $bMailToSend = false;
+                    file_put_contents($sMailLicenceFile, $sToday);
+                    // Mise à jour du nombre de tentative dans la base.
+                    $oBd->updateLinkedTable($properties["schema_gtf"] . ".order", "attempt", "order_id", $aDemande['order_id'], 0);
+                }
+                
+                // Envoi du mail.
+                if ($bMailToSend == true) {
+                    /*
+                      $sSql = $aSql[$properties["sgbd"]]["select_user"];
+                      $sSql = str_replace("[iUserId]", $aDemande['user_id'], $sSql);
+                      $sSql = str_replace("[sSchemaFramework]", $properties["schema_framework"], $sSql);
+                      $oPDOResult2 = $oBd->execute($sSql);
+                      // */
+                    ///*
+                    
+                    //Mise a jour de la demande si resultat null
+                    /*
+                    $aParams = array();
+                    $aParams['iOrderId'] = array('value' => $aDemande['order_id'], 'type' => 'number');
+                    $aParams['sSchemaGtf'] = array('value' => $properties["schema_gtf"], 'type' => 'schema_name');
+                    $oPDOResult2 = $oBd->executeWithParams($aSql[$properties["sgbd"]]["update_demande_resultat_null"], $aParams);
+                    if ($oBd->erreurRencontree) {
+                        writeToLog(INFO_GET_USER_INFO_ERROR . $aDemande['user_id'] . ". (SQL = " . $sSql . ")", $properties["engine_log_file"]);
+                    } else {
+                    */
+                        // $aUser = $oBd->ligneSuivante ($oPDOResult2);
+                        // $sContenuMail = "Bonjour ".$aUser["name"].",<br><br><br>".$sContenuMail;
+                        // $sContenuMail .= "<br><br><cite><h6>Cet e-mail a été envoyé par un robot, merci de ne pas répondre.</h6></cite><br>";
+                        //	
+
+                        if (empty($iEmailTemplateId))
+                            $iEmailTemplateId = $properties['default_mail_model'];
+
+                        /*
+                          // Nom des moteurs GTF et FME
+                          $sSql = $aSql[$properties["sgbd"]]["get_gtf_engine_name"];
+                          $sSql = str_replace("[sSchemaGtf]", $properties["schema_gtf"], $sSql);
+                          $sSql = str_replace('[gtf_engine_id]', $aDemande['gtf_engine_id'], $sSql);
+                          $oPDOResult2 = $oBd->execute($sSql);
+                          // */
+                        ///*
+                        // Nom des moteurs GTF et FME
+                        $aParams = array();
+                        $aParams['sSchemaGtf'] = array('value' => $properties["schema_gtf"], 'type' => 'schema_name');
+                        $aParams['gtf_engine_id'] = array('value' => $aDemande['gtf_engine_id'], 'type' => 'number');
+                        $oPDOResult2 = $oBd->executeWithParams($sSql = $aSql[$properties["sgbd"]]["get_gtf_engine_name"], $aParams);
+                        //*/
+
+
+                        if ($oBd->erreurRencontree) {
+                            writeToErrorLog(ERROR_0001);
+                        } else
+                            $aRow = $oBd->ligneSuivante($oPDOResult2);
+
+                        // URL de téléchargement du résultat
+                        $sResultUrl = '';
+                        if ($sResultat != "")
+                            $sResultUrl = '<a href="' . $properties["url_export"] . "/gtf/" . $sResultat . '">Télécharger le résultat</a>';
+
+                        // Dates
+                        $sOrderDate = date_format(date_create($aDemande['order_date']), 'd/m/Y H:i:s');
+
+                        // Envoi du mail
+                        $aObjects = array();
+                        if (!empty($sMessage))
+                            $aObjects['error'] = $sMessage;
+                        $aObjects['oOrder'] = new OrderLib($oBd, $aDemande["order_id"], $properties, "v_order");
+                        $aObjects['oOrder']->formatOrderEmail();
+                        $oEmail = new Email($oBd, $iEmailTemplateId, $properties, $aObjects);
+                        if (!empty($oEmail->oEmailTemplate->name))
+                            $oEmail->send();
+                    //}
+                    $oPDOResult2 = $oBd->fermeResultat();
+                } else {
+                    // pas d'envoi de mail
+                    writeToLog(INFO_NO_MAIL_SEND, $properties["engine_log_file"]);
+                }
+            } //fin du if sur les tentatives
+            //fin de while	
+        }
+        if ($iNbTraitement >= 1) {
+            //Crée ou modifie le fichier de maj de l'application pour l'utilisateur.
+            writeToLog(INFO_END_ORDER_PROCESSING, $properties["engine_log_file"]);
+        }
+        $oPDOResult = $oBd->fermeResultat();
+    }
+} else {
+    writeToErrorLog(constant($ErrorLicense));
+}
+
+//Teste si le traitement est autorisé si la demande est en heure creuse.
+//retourne true si le traitement est autorisé, retourne false si le traitement n'est pas autorisé.
+function TesteHeureCreuse($sHeureMin, $sHeureMax) {
+    $sHeure = date('H');
+    $sMinute = date('i');
+    $aHeureMin = explode(":", $sHeureMin);
+    $aHeureMax = explode(":", $sHeureMax);
+    $bMax = false;
+    $bMin = false;
+    //Test de l'heure minimale.
+    if ($sHeure > $aHeureMin[0]) {
+        $bMin = true;
+    } else {
+        if ($sHeure == $aHeureMin[0] && $sMinute >= $aHeureMin[1]) {
+            $bMin = true;
+        }
+    }
+    //Test de l'heure maximale. 
+    if ($sHeure < $aHeureMax[0]) {
+        $bMax = true;
+    } else {
+        if (($aHeureMax[0] < $aHeureMin[0]) && ($sHeure < 24)) {
+            $bMax = true;
+        }
+        if ($sHeure == $aHeureMax[0] && $sMinute <= $aHeureMax[1]) {
+            $bMax = true;
+        }
+    }
+    if ($bMin && $bMax) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+?>
diff --git a/gtf.engine/gtf.engines/engine.sql.inc b/gtf.engine/gtf.engines/engine.sql.inc
new file mode 100755
index 0000000000000000000000000000000000000000..3a36a236f9eefc973449705b4cd9de69dee1e0b7
--- /dev/null
+++ b/gtf.engine/gtf.engines/engine.sql.inc
@@ -0,0 +1,17 @@
+<?php
+//Requête pour engine.php pgsql
+$aSql['pgsql']['boucle_1']='SELECT "order".*, rt_priority.priority_id, rt_priority.label_id as priorite_libelle_id, workspace.name as workspace_nom FROM ([sSchemaGtf]."order" LEFT JOIN [sSchemaGtf].rt_priority ON "order".priority_id = rt_priority.priority_id) LEFT JOIN [sSchemaGtf].workspace ON "order".workspace_id=workspace.workspace_id WHERE (order_status_id = 1 or order_status_id = 5) AND "order".period_id IS NULL AND "order".deleted IS not TRUE AND "order".gtf_engine_id=[iIdGtfEngine] AND "order".priority_id >= [iPriorityId] ORDER BY "order".priority_id ASC, "order".order_id ASC LIMIT [iNnbrOrderMax]';
+$aSql['pgsql']['boucle_2']='SELECT "order".*, rt_priority.priority_id, rt_priority.label_id as priorite_libelle_id, workspace.name as workspace_nom FROM ([sSchemaGtf]."order" LEFT JOIN [sSchemaGtf].rt_priority ON "order".priority_id = rt_priority.priority_id) LEFT JOIN [sSchemaGtf].workspace ON "order".workspace_id=workspace.workspace_id WHERE (order_status_id = 1 or order_status_id = 5) AND "order".period_id IS NULL AND "order".deleted IS not TRUE AND "order".gtf_engine_id=[iIdGtfEngine] AND "order".priority_id >  [iPriorityId] ORDER BY "order".priority_id ASC, "order".order_id ASC LIMIT [iNnbrOrderMax]';
+$aSql['pgsql']['right_user']='SELECT workspace."workspace_id" FROM [sSchemaGtf].workspace RIGHT JOIN [sSchemaGtf].workspace_group ON workspace.workspace_id = workspace_group.workspace_id  GROUP BY workspace."workspace_id", workspace_group."group_id" HAVING workspace_group."group_id" IN ([sGroupListId]) ORDER BY workspace."workspace_id" ASC';
+$aSql['pgsql']['update_demande']="UPDATE [sSchemaGtf].order SET length_sec = [iNbSec], order_status_id=[iStatut], execution_date=[sDateTraitement], result_url=[sResultat], log_url=[sLogFme] WHERE order_id=[iOrderId]";
+$aSql['pgsql']['update_demande_resultat_null']="UPDATE [sSchemaGtf].order SET result_url=NULL WHERE order_id=[iOrderId]";
+$aSql['pgsql']['select_user']='SELECT * FROM [sSchemaFramework].user WHERE "user_id"=[iUserId]';
+$aSql['pgsql']['select_traitement']='SELECT * FROM [sSchemaGtf].workspace WHERE workspace_id=[iWorkspaceId]';
+//$aSql['pgsql']['select_transit_dir']='SELECT value FROM [sSchemaGtf].property WHERE property=\'$properties["transit_dir"]\'';
+$aSql['pgsql']['select_fme_path']='select local_path as fme_path from [sSchemaGtf].gtf_engine, [sSchemaGtf].fme_engine where fme_engine.fme_engine_id = gtf_engine.fme_engine_id AND gtf_engine.gtf_engine_id = [gtf_engine_id]';
+$aSql['pgsql']['update_message']="UPDATE [sSchemaGtf].message SET status=1 WHERE order_id=[iOrderId]";
+$aSql['pgsql']['delete_message']="DELETE FROM [sSchemaGtf].message where order_id=[iOrderId]";
+$aSql['pgsql']['get_gtf_engine_name'] = 'SELECT gtf_engine.name AS gtf_engine_name,fme_engine.name AS fme_engine_name FROM [sSchemaGtf].gtf_engine,[sSchemaGtf].fme_engine WHERE gtf_engine.fme_engine_id=fme_engine.fme_engine_id AND gtf_engine_id=[gtf_engine_id]';
+$aSql['pgsql']["getLogin"] = 'SELECT "login" from [sSchemaFramework]."user" where user_id = [iUserId]';
+$aSql['pgsql']["insertJob"] = 'INSERT INTO [sSchemaGtf].job(order_id, workspace_id, "user_id", execution_date, length_sec, engine_id, order_status_id) VALUES ([iOrderId], [iWorkspaceId], [iUserId], [sBeginExecutionDate] , [iDelay], [iGtfEngineId], [iStatut])';
+?>
diff --git a/gtf.engine/gtf.engines/lang_engines/en-lang.inc b/gtf.engine/gtf.engines/lang_engines/en-lang.inc
new file mode 100755
index 0000000000000000000000000000000000000000..be577b8a73f3ac1d5a237a13e6597b69177e3c0d
--- /dev/null
+++ b/gtf.engine/gtf.engines/lang_engines/en-lang.inc
@@ -0,0 +1,7 @@
+<?php
+
+//Error Licence
+define('E001', "Orders unprocessed: Invalid lincense file");
+define('E002', "Orders unprocessed: Expired license file");
+define('E003', "Orders unprocessed: Number of the GTF engine upper than available engines");
+?>
\ No newline at end of file
diff --git a/gtf.engine/gtf.engines/lang_engines/fr-lang.inc b/gtf.engine/gtf.engines/lang_engines/fr-lang.inc
new file mode 100755
index 0000000000000000000000000000000000000000..7d5d50467c79c859e3bbc9b6426827a4d139e006
--- /dev/null
+++ b/gtf.engine/gtf.engines/lang_engines/fr-lang.inc
@@ -0,0 +1,8 @@
+<?php
+
+//Error Licence
+define('E001', "Demandes non trait�es : Fichier de licence invalide");
+define('E002', "Demandes non trait�es : Fichier de licence expir�");
+define('E003', "Demandes non trait�es : Num�ro du moteur GTF sup�rieur au nombre de moteurs disponibles");
+
+?>
\ No newline at end of file
diff --git a/gtf.engine/gtf.engines/php_engine_conf.inc b/gtf.engine/gtf.engines/php_engine_conf.inc
new file mode 100755
index 0000000000000000000000000000000000000000..6985372b36c29afb9c6db09e3c4867eb379ea49b
--- /dev/null
+++ b/gtf.engine/gtf.engines/php_engine_conf.inc
@@ -0,0 +1,4 @@
+<?php
+set_include_path(dirname($_SERVER["PHP_SELF"]). PATH_SEPARATOR .dirname($_SERVER["PHP_SELF"]).'/../vas/rest/conf'. PATH_SEPARATOR .dirname($_SERVER["PHP_SELF"]).'/../vas/rest/class');
+ini_set ('error_log', dirname($_SERVER["PHP_SELF"]).'/php/log/php.log');
+?>
\ No newline at end of file
diff --git a/gtf.engine/gtf.engines/properties_engine.inc b/gtf.engine/gtf.engines/properties_engine.inc
new file mode 100755
index 0000000000000000000000000000000000000000..faf47c8dec9ca0a95a8bc1dc4d39883301b1394f
--- /dev/null
+++ b/gtf.engine/gtf.engines/properties_engine.inc
@@ -0,0 +1,19 @@
+<?php
+require_once ("properties.inc");
+$properties["robot_root_dir"] = str_replace("\\","/",dirname($_SERVER["PHP_SELF"])); // Chemin du répertoire courant : gtf.engines
+if ($properties["id_gtf_engine"] != '') {
+	$subdir = '/engine_'.$properties["id_gtf_engine"];
+} else {
+	$subdir = '/subscription';
+}
+
+$properties["engine_log_home"] = $properties['vas_home']."/log/engines/".date($properties['log_period']).$subdir;
+$properties["debug_log_file"] = $properties["engine_log_home"]."/debug.log";
+$properties["engine_log_file"] = $properties["engine_log_home"]."/engine.log";
+$properties["notify_log_file"] = $properties["engine_log_home"]."/notify.log";
+$properties["sql_log_file"] = $properties["engine_log_home"]."/sql.log";
+$properties["subscription_log_file"] = $properties["engine_log_home"]."/subscription.log";
+$properties["error_log_file"] = $properties['vas_home']."/log/engines"."/error.log";
+
+$properties['web_server_name'] = 'https://dev.veremes.net';
+?>
\ No newline at end of file
diff --git a/gtf.engine/gtf.engines/regex2.dll b/gtf.engine/gtf.engines/regex2.dll
new file mode 100755
index 0000000000000000000000000000000000000000..f84a847a0de92fc59fa2ff8494ff700e62b87326
Binary files /dev/null and b/gtf.engine/gtf.engines/regex2.dll differ
diff --git a/gtf.engine/gtf.engines/string.inc b/gtf.engine/gtf.engines/string.inc
new file mode 100755
index 0000000000000000000000000000000000000000..24e8c0e4dad3153051f23879cd9a3c5e5e9c66b4
--- /dev/null
+++ b/gtf.engine/gtf.engines/string.inc
@@ -0,0 +1,59 @@
+<?php
+// subscription.php
+	define('INFO_BASE_CONNECTION_ERROR', '|FATAL |PHP|Connexion impossible a la base ');
+	define('INFO_BASE_CONNECT', '|INFORM|PHP|Connect to ');
+	define('INFO_SUBSCRIPTION_PROCESSING', '|INFORM|PHP|Processing subscription order_id= ');
+	define('INFO_REQUEST_ERROR', '|FATAL |PHP| Erreur lors de l éxécution de la requête : ');
+	define('INFO_PHP_ERROR', '|ERROR|PHP| .');
+	define('INFO_ORDER_CREATED', '|INFORM|PHP|Order [iNouvelId] has been created.');
+	define('INFO_ORDER_CREATION_ERROR', '|ERROR|PHP|Problème lors de la création d\'un nouvel enregistrement dans la table "demande"');
+	define('INFO_CHECK_SQL_LOG', '|FATAL |PHP|Consultez le log sql.');
+	define('INFO_NO_USER_GRANT', '|FATAL |PHP|L utilisateur n a pas les droits nécessaires pour réaliser un traitement :');
+	define('INFO_CONTACT_ADMINISTRATOR', '|ERROR|PHP|Contactez l\'administrateur.');
+	define('INFO_CHECK_ORDER_FILES', '***************** Vérification des fichiers présents pour la demande [aDemande["order_id"]] *******************');
+	define('INFO_CHECK_DIRECTORY', '|INFORM|PHP|Check directory ');
+	define('INFO_MOVE_DIRECTORY', '|INFORM|PHP|Move directory from ');
+	define('INFO_MOVE_FILE', '|INFORM|PHP|Move file ');
+	define('INFO_DIRECTORY_NOT_FOUND_SUBSCRIPTION', "|ERROR|PHP| Le dossier [sFolder] n'existe pas. Contactez l'administrateur et vérifiez le dossier configuré dans l'interface de configuration de surveillance des dossier");
+	define('INFO_ORDER_PERIOD_NOT_FOUND', "|ERROR|PHP| La période d'abonnement n°[iPeriodeId] n'existe pas. Contactez l'administrateur et vérifiez la période d'abonnement ajoutée dans l'utilitaire pycron");
+	define('INFO_END_ORDER_PROCESSING', '***************** Fin du traitement des demandes *******************');
+	
+// Traitement.class.inc
+	define('INFO_RESOURCES', '|INFORM|PHP| Ressources : robot.php, Traitement.class.inc, Paramètres = [sParams], Fmw = [this->sFmwFileName]');
+	define('INFO_NULL_ELEMENT', '|WARN  |PHP| Un élément est null lors de la création de la demande : ');
+	define('INFO_DB_PARAM', 'Params : [aValeurs[0]] - Valeur : ');
+	define('INFO_ERROR', '|ERROR|');
+	define('INFO_COMMAND_ERROR', '|ERROR|PHP| Erreur lors de l exécution de la commande : ');
+	define('INFO_INFORM', '|INFORM|');
+	define('INFO_SUCCESSFUL_TREATMENT', '|INFORM|PHP| Traitement réussi.');
+	define('INFO_FILE_COMPRESSION', '|INFORM|PHP| Compression des fichiers du répertoire [sZipDir] en zip.');
+	define('INFO_TREATMENT_FAILURE', '|FATAL |PHP| Treatment failure.');
+	define('INFO_FILES_COMPRESSION_FAILURE', '|ERROR|PHP| Impossible de zipper les fichiers du répertoire [sZipDir] vers [sZipFileDir] dans fichier ');
+	define('INFO_COMPRESSED_FILES', '|INFORM|PHP| Compressed files : ');
+	define('INFO_DECOMPRESSING_FILE', '|INFORM|PHP| Décompression du fichier ');
+	define('INFO_FILE_COMPRESSION_FAILURE', '|ERROR|PHP| Impossible de dézipper le fichier [sZipFile] vers ');
+	define('INFO_FILE_COMPRESSION_DIRECTORY', '|INFORM|PHP| Fichiers décompressés vers ');
+	define('INFO_VALID_DATA_SOURCE_FILE_EXTENSION', '|INFORM|PHP| Extension valide pour le fichier de la source de données : ');
+	define('INFO_OUTPUT_DATA_DIRECTORY', '|INFORM|PHP| Répertoire de sortie des données : ');
+	define('INFO_OUTPUT_DATA_FILE', '|INFORM|PHP| Fichier de sortie des données : ');
+	define('INFO_GTF_HOME', '|INFORM|PHP| GTF_HOME=');
+	define('INFO_FME_PATH', '|INFORM|PHP| FME_PATH=');
+	define('INFO_TREATMENT_COMMAND_LINE', '|INFORM|PHP| Ligne de commande exécutant le traitement : ');
+	define('INFO_NO_USE_PATTERN', '|INFORM|PHP| Utilisation des noms de fichier, sans utilisation des motifs');
+	define('INFO_USE_PATTERN', '|INFORM|PHP|  Utilisation des motifs ');
+	
+// engine.php
+	define('INFO_BASE_CONNECTION', '|INFORM|PHP| Connexion à la base de données ');
+	define('INFO_TOO_MANY_ORDER_ATTEMPT', "|INFORM|PHP| La demande [aDemande['order_id']] n'a pas été traitée suite à de trop nombreuses tentatives.");
+	define('INFO_ORDER_UPDATE_ERROR', '|ERROR|PHP| Impossible de mettre à jour la demande. ');
+	define('INFO_ORDER_UPDATE', '|INFORM|PHP| Mise à jour de la demande.');
+	define('INFO_ORDER_PROCESSING', "***************** Traitement de la demande [aDemande['order_id']] *******************");
+	define('INFO_DELETE_DIRECTORY', '|INFORM|PHP| Supression du dossier ');
+	define('INFO_GET_USER_INFO_ERROR', "|ERROR|PHP| Impossible de récupérer les informations sur l'utilisateur numéro ");
+	define('INFO_MOVING_FILE', '|INFORM|PHP| Déplacement du dossier [sSourceDirectory] vers le dossier ');
+	define('INFO_DIRECTORY_NOT_FOUND_ENGINE', "|ERROR|PHP| Le dossier [properties['transit_dir']] n'existe pas.");
+	define('INFO_INVALID_FME_LICENCE_FILE', '|FATAL |PHP| Invalid FME Licence file.');
+	define('INFO_TEST_REQUEST_ERROR', '|ERROR|PHP|Requête test en erreur. ');
+	define('INFO_INFO_ORDER_UPDATE_NULL', '|INFORM|PHP| Mise à jour de la demande (resultat null).');
+	define('INFO_NO_MAIL_SEND', "|INFORM|PHP| Aucun mail n'a été envoyé ");
+?>
\ No newline at end of file
diff --git a/gtf.engine/gtf.engines/subscription.bat b/gtf.engine/gtf.engines/subscription.bat
new file mode 100755
index 0000000000000000000000000000000000000000..f1830d76cc9f1ade733005ddb559e81b70133b3c
--- /dev/null
+++ b/gtf.engine/gtf.engines/subscription.bat
@@ -0,0 +1,5 @@
+@echo off
+set GTF_ENGINE_HOME=%~dp0
+set PHP_HOME=%GTF_ENGINE_HOME%php
+rem %1 correspond au param�tre pass� par pycron
+"%PHP_HOME%\php.exe" "%GTF_ENGINE_HOME%\subscription.php" %1
\ No newline at end of file
diff --git a/gtf.engine/gtf.engines/subscription.php b/gtf.engine/gtf.engines/subscription.php
new file mode 100755
index 0000000000000000000000000000000000000000..c12c25e37c1e5420fa297990d647fae3fce1ef97
--- /dev/null
+++ b/gtf.engine/gtf.engines/subscription.php
@@ -0,0 +1,359 @@
+<?php
+
+/**
+ * \file subscription.php
+ * \brief subscription.php \n \n Ce fichier contient un programme php.
+ *
+ * Ce programme permet de traiter les demandes d'abonnement de traitements.
+ *
+ * \author Laurent Panabieres <laurent.panabieres@veremes.com>
+ */
+//set_include_path(dirname($_SERVER["PHP_SELF"]).'/../gtf.client'.';'.dirname($_SERVER["PHP_SELF"]).'/php/lib');
+//ini_set ('writeToErrorLog', dirname($_SERVER["PHP_SELF"]).'/php/php.log');
+require_once ("php_engine_conf.inc");
+require_once ("gtf_lib/GtfFmwParser.class.inc");
+require_once ("vmlib/Vm.class.inc");
+require_once ("vmlib/phpUtil.inc");
+require_once("vmlib/dbUtil.inc");
+//require_once ("robot_properties.inc");
+//require_once ("engine_properties.inc");
+$properties["id_gtf_engine"] = "";
+require_once ("properties_engine.inc");
+require_once ("subscription.sql.inc");
+require_once ("vmlib/logUtil.inc");
+require_once("Ldap.class.inc");
+require_once 'vmlib/error.inc';
+require_once 'string.inc';
+
+//writeToLog('|INFO  |PHP| dump prop '. var_export($properties,true),$properties["subscription_log_file"]);
+
+/*
+  // Création du dossier journalier pour l'écriture du log
+  if (!is_dir($properties["engine_log_home"]. "/".date($properties["log_period"]))){
+  // Le dossier pour l'écritude du log n'existe pas, il est créé
+  if (!mkdir($properties["engine_log_home"]. "/".($properties["log_period"]), 0777, true)) {
+  writeToErrorLog(ERROR_0025.$properties["engine_log_home"]. "/".date($properties["log_period"]).'"');
+  }
+  }
+ */
+//Pas besoin de mot de passe pour le robot
+$oBd = new Vm($properties["login_scheduler"], $properties['password_scheduler'], $properties["database"], $properties["server"], $properties["port"], $properties["sgbd"], $properties["page_encoding"]);
+if ($oBd->erreurRencontree) {
+    writeToLog(INFO_BASE_CONNECTION_ERROR . $properties["database"], $properties["subscription_log_file"]);
+} else {
+    writeToLog(INFO_BASE_CONNECT . $properties["database"], $properties["subscription_log_file"]);
+    // Traitement des demandes d'abonnement.
+    $iNbTraitement = 0;
+    // Récupération de l'identifiant de la période d'abonnement qui est lancé !
+    $iPeriodeId = $_SERVER['argv'][1];
+    
+    /*
+    $sSql = $aSql[$properties["sgbd"]]["verif_period_id"];
+    $sSql = str_replace("[iOrderPeriodId]", $iPeriodeId, $sSql);
+    $sSql = str_replace("[sSchemaGtf]", $properties["schema_gtf"], $sSql);
+    $oPDOResult = $oBd->execute($sSql);
+    */
+    
+    // Récupération de l'identifiant de la période d'abonnement qui est lancé !
+    $aParams = array();
+    $aParams['iOrderPeriodId'] = array('value' => $iPeriodeId, 'type' => 'number');
+    $aParams['sSchemaGtf'] = array('value' => $properties["schema_gtf"], 'type' => 'schema_name');
+    $oPDOResult = $oBd->executeWithParams($aSql[$properties["sgbd"]]["verif_period_id"], $aParams);
+
+    if ($oBd->ligneSuivante($oPDOResult) != "") {
+        
+        /*
+        $sSql = $aSql[$properties["sgbd"]]["abonnement"];
+        $sSql = str_replace("[iOrderPeriodId]", $iPeriodeId, $sSql);
+        $sSql = str_replace("[sSchemaGtf]", $properties["schema_gtf"], $sSql);
+        $oPDOResult = $oBd->execute($sSql);
+         */
+        
+        // Recuperation des éléments de gestion des abonnements Gtf
+        $aParams = array();
+        $aParams['iOrderPeriodId'] = array('value' => $iPeriodeId, 'type' => 'number');
+        $aParams['sSchemaGtf'] = array('value' => $properties["schema_gtf"], 'type' => 'schema_name');
+        $oPDOResult = $oBd->executeWithParams($aSql[$properties["sgbd"]]["abonnement"], $aParams);
+        
+        while ($aDemande = $oBd->ligneSuivante($oPDOResult)) {
+            if (is_null($aDemande['order_date'])) {
+                $sDateTraitement = $aDemande['order_date'];
+            } else {
+                $sDateTraitement = $aDemande['execution_date'];
+            }
+            
+            /*
+            $sSql = $aSql[$properties["sgbd"]]["getLogin"];
+            $sSql = str_replace("[sSchemaFramework]", $properties["schema_framework"], $sSql);
+            $sSql = str_replace("[iUserId]", $aDemande['user_id'], $sSql);
+            $oPDOResult2 = $oBd->execute($sSql);
+            */
+            
+            // Récupération des information de connection de l'utilisateur et de ses droits
+            $aParams = array();
+            $aParams['sSchemaFramework'] = array('value' => $properties["schema_framework"], 'type' => 'schema_name');
+            $aParams['iUserId'] = array('value' => $aDemande['user_id'], 'type' => 'number');
+            $oPDOResult2 = $oBd->executeWithParams($aSql[$properties["sgbd"]]["getLogin"], $aParams);
+            
+            $aUser = $oBd->ligneSuivante($oPDOResult2);
+            $sGroupListId = getUserGroupsEngines($aUser["login"], $oBd, $properties["mixed_rights_management"]);
+            writeToLog(INFO_SUBSCRIPTION_PROCESSING . $aDemande["order_id"], $properties["subscription_log_file"]);
+            $iNbTraitement = $iNbTraitement + 1;
+            //Vérification si l'utilisateur a les droits pour faire une demande de ce traitement.
+            /*
+            $sSql = $aSql[$properties["sgbd"]]["right_user"];
+            $sSql = str_replace("[sSchemaGtf]", $properties["schema_gtf"], $sSql);
+            $sSql = str_replace("[sGroupListId]", $sGroupListId, $sSql);
+            $oPDOResult2 = $oBd->execute($sSql);
+            */
+            
+            // Verification des droits utilisateur sur la demande
+            $aParams = array();
+            $aParams['sSchemaGtf'] = array('value' => $properties["schema_gtf"], 'type' => 'schema_name');
+            $aParams['sGroupListId'] = array('value' => str_replace(',', '|', $sGroupListId), 'type' => 'group');
+            $oPDOResult2 = $oBd->executeWithParams($aSql[$properties["sgbd"]]["right_user"], $aParams);
+
+            if ($oBd->erreurRencontree) {
+                writeToLog(INFO_REQUEST_ERROR . $sSql, $properties["subscription_log_file"]);
+                writeToLog(INFO_PHP_ERROR, $properties["subscription_log_file"]);
+            } else {
+                if ($sGroupListId == "0") {
+                    $bAutorisationDemande = true;
+                } else {
+                    $bAutorisationDemande = false;
+                    while ($aTraitementsAutorise = $oBd->ligneSuivante($oPDOResult2)) {
+                        if ($aTraitementsAutorise['workspace_id'] == $aDemande['workspace_id']) {
+                            $bAutorisationDemande = true;
+                        }
+                    }
+                }
+                if ($bAutorisationDemande == true) {
+                    //Création d'une nouvelle demande.
+                    require_once("gtf_lib/gtf_object//Order.class.inc");
+                    $iNouvelId = $oBd->insert($properties["schema_gtf"], "order", Array("priority_id" => 1, "workspace_id" => $aDemande['workspace_id'], "order_status_id" => 1, "user_id" => $aDemande['user_id'], "period_id" => "", "order_date" => date("Y-m-d H:i:s"), "execution_date" => null, "wk_params" => $aDemande['wk_params'], "result_url" => "", "message" => "", "email_option_id" => $aDemande['email_option_id'], "gtf_engine_id" => $aDemande['gtf_engine_id'], "email_notifications" => $aDemande['email_notifications']), $properties["schema_gtf"] . ".seq_order", "order_id");
+                    $oOrder = new OrderLib($oBd, -1, $properties);
+                    $oOrder->getIdEngine($iNouvelId, "order", $aDemande['workspace_id']);
+                    $oOrder->update();
+                    if ($iNouvelId != "") {
+                        writeToLog(str_replace('[iNouvelId]', $iNouvelId, INFO_ORDER_CREATED), $properties["subscription_log_file"]);
+                        // L'abonnement crée une demande
+                        sendWebsocketMessage($properties['websocket_server'], $properties['websocket_port'], $properties['websocket_alias'], array(
+                            'action' => 'event',
+                            'service' => 'GtfEvents',
+                            'data' => array(
+                                'event' => 'subscription_creating_order',
+                                'order' => array(
+                                    'order_id' => $aDemande['order_id'],
+                                    'order_status_id' => $aDemande['order_status_id'],
+                                    'user_id' => $aDemande['user_id'],
+                                    'workspace_id' => $aDemande['workspace_id']
+                                )
+                            )
+                        ));
+                    } else {
+                        writeToLog(INFO_ORDER_CREATION_ERROR, $properties["subscription_log_file"]);
+                        writeToLog(INFO_CHECK_SQL_LOG, $properties["subscription_log_file"]);
+                    }
+                } else {
+                    writeToLog(INFO_NO_USER_GRANT . $aDemande['name'] . ' n\'as pas été définie.', $properties["subscription_log_file"]);
+                    writeToLog(INFO_CONTACT_ADMINISTRATOR, $properties["subscription_log_file"]);
+                    $iNouvelId = $oBd->update($properties["schema_gtf"], "order", Array("enabled" => FALSE), "order_id", $aDemande["order_id"], "");
+                }
+            }
+            $oPDOResult2 = $oBd->fermeResultat();
+        }
+        /*
+        $sSql = $aSql[$properties["sgbd"]]["dir_survey"];
+        $sSql = str_replace("[iOrderPeriodId]", $iPeriodeId, $sSql);
+        $sSql = str_replace("[sSchemaFramework]", $properties["schema_framework"], $sSql);
+        $sSql = str_replace("[sSchemaGtf]", $properties["schema_gtf"], $sSql);
+        writeToErrorLog($sSql);
+        $oPDOResult = $oBd->execute($sSql);
+        */
+        
+        $aParams = array();
+        $aParams['iOrderPeriodId'] = array('value' => $iPeriodeId, 'type' => 'number');
+        $aParams['sSchemaFramework'] = array('value' => $properties["schema_framework"], 'type' => 'schema_name');
+        $aParams['sSchemaGtf'] = array('value' => $properties["schema_gtf"], 'type' => 'schema_name');
+        $oPDOResult = $oBd->executeWithParams($aSql[$properties["sgbd"]]["dir_survey"], $aParams);
+        
+        while ($aDemande = $oBd->ligneSuivante($oPDOResult)) {
+            if (is_null($aDemande['order_date'])) {
+                $sDateTraitement = $aDemande['order_date'];
+            } else {
+                $sDateTraitement = $aDemande['execution_date'];
+            }
+            //writeToLog(str_replace('[aDemande["order_id"]]', $aDemande["order_id"], INFO_CHECK_ORDER_FILES), $properties["subscription_log_file"]); 
+            writeToLog(INFO_CHECK_DIRECTORY . $aDemande["condition"] . ' for survey order_id=' . $aDemande["order_id"], $properties["subscription_log_file"]);
+            //parcours du dossier de la condition de la demande
+            $sFolder = utf8_decode($aDemande["condition"]);
+            if (is_dir($sFolder)) {
+                $MyDirectory = opendir($sFolder);
+                while ($Entry = @readdir($MyDirectory)) {
+
+                    if ($Entry != '.' && $Entry != '..') {
+                        //deplacement vers le dossier upload en fonction du type
+                        $bCopie = false;
+                        $bIsFile = false;
+                        $sUnique = UniqFileName();
+                        if (is_dir($sFolder . '/' . $Entry)) {
+                            $bIsFile = false;
+                            $bCopie = rename($sFolder . "/" . $Entry, $properties["upload_dir"] . "/" . $sUnique);
+                            writeToLog(INFO_MOVE_DIRECTORY . $sFolder . "/" . $Entry . ' to ' . $properties["upload_dir"] . "/" . $sUnique, $properties["subscription_log_file"]);
+                        } else {
+                            $bIsFile = true;
+                            mkdir($properties["upload_dir"] . "/" . $sUnique);
+                            $bCopie = rename($sFolder . "/" . $Entry, $properties["upload_dir"] . "/" . $sUnique . "/" . $Entry);
+                            writeToLog(INFO_MOVE_FILE . $sFolder . "/" . $Entry . ' to ' . $properties["upload_dir"] . "/" . $sUnique . "/" . $Entry, $properties["subscription_log_file"]);
+                        }
+                        if ($bCopie) {
+                            //creation de la demande
+                            //Vérification si l'utilisateur a les droits pour faire une demande de ce traitement.
+                            /*
+                            $sSql = $aSql[$properties["sgbd"]]["getLogin"];
+                            $sSql = str_replace("[sSchemaFramework]", $properties["schema_framework"], $sSql);
+                            $sSql = str_replace("[iUserId]", $aDemande['user_id'], $sSql);
+                            $oPDOResult2 = $oBd->execute($sSql);
+                            */
+                            
+                            // Récupération des infos utilisateurs
+                            $aParams = array();
+                            $aParams['sSchemaFramework'] = array('value' => $properties["schema_framework"], 'type' => 'schema_name');
+                            $aParams['iUserId'] = array('value' => $aDemande['user_id'], 'type' => 'number');
+                            $oPDOResult2 = $oBd->executeWithParams($aSql[$properties["sgbd"]]["getLogin"], $aParams);
+
+                            $aUser = $oBd->ligneSuivante($oPDOResult2);
+                            $sGroupListId = getUserGroupsEngines($aUser["login"], $oBd, $properties["mixed_rights_management"]);
+                            /*
+                            $sSql = $aSql[$properties["sgbd"]]["right_user"];
+                            $sSql = str_replace("[sSchemaGtf]", $properties["schema_gtf"], $sSql);
+                            $sSql = str_replace("[sGroupListId]", $sGroupListId, $sSql);
+                            $oPDOResult2 = $oBd->execute($sSql);
+                            */
+                            
+                            // Vérification des droits de l'utilisateurs pour la demande
+                            $aParams = array();
+                            $aParams['sSchemaGtf'] = array('value' => $properties["schema_gtf"], 'type' => 'schema_name');
+                            $aParams['sGroupListId'] = array('value' => str_replace(',', '|', $sGroupListId), 'type' => 'group');
+                            $oPDOResult2 = $oBd->executeWithParams($aSql[$properties["sgbd"]]["right_user"], $aParams);
+
+                            if ($oBd->erreurRencontree) {
+                                writeToLog(INFO_REQUEST_ERROR . $sSql, $properties["subscription_log_file"]);
+                                writeToLog(INFO_PHP_ERROR, $properties["subscription_log_file"]);
+                            } else {
+                                if ($sGroupListId == "0") {
+                                    $bAutorisationDemande = true;
+                                } else {
+                                    $bAutorisationDemande = false;
+                                    while ($aTraitementsAutorise = $oBd->ligneSuivante($oPDOResult2)) {
+                                        if ($aTraitementsAutorise['workspace_id'] == $aDemande['workspace_id']) {
+                                            $bAutorisationDemande = true;
+                                        }
+                                    }
+                                }
+                                if ($bAutorisationDemande == true) {
+                                    //Création d'une nouvelle demande.
+                                    //writeToLog($properties["workspace_dir"],$properties["subscription_log_file"]);
+                                    $oGtfFmwParser = new GtfFmwParser($properties['vas_home'] . '/ws_data/gtf/workspace' . "/" . $aDemande['workspace_id'] . "/fme/" . $aDemande['fmw_file']);
+                                    $iNouvelId = "";
+
+                                    if ($bIsFile) {
+                                        $aDemande['wk_params'] = getParams($oGtfFmwParser, $sUnique . "/" . utf8_encode($Entry), $aDemande['wk_params']);
+                                    } else {
+                                        $aDemande['wk_params'] = getParams($oGtfFmwParser, $sUnique . "/", $aDemande['wk_params']);
+                                    }
+                                    require_once("gtf_lib/gtf_object/Order.class.inc");
+                                    $iNouvelId = $oBd->insert($properties["schema_gtf"], "order", Array("priority_id" => 1, "workspace_id" => $aDemande['workspace_id'], "order_status_id" => 1, "user_id" => $aDemande['user_id'], "period_id" => "", "order_date" => date("Y-m-d H:i:s"), "execution_date" => null, "wk_params" => $aDemande['wk_params'], "result_url" => "", "message" => "", "email_option_id" => $aDemande['email_option_id'], "gtf_engine_id" => $aDemande['gtf_engine_id'], "email_notifications" => $aDemande['email_notifications']), $properties["schema_gtf"] . ".seq_order", "order_id");
+                                    $oOrder = new OrderLib($oBd, -1, $properties);
+                                    $oOrder->getIdEngine($iNouvelId, "order", $aDemande['workspace_id']);
+                                    $oOrder->update();
+                                    if ($iNouvelId != "") {
+                                        writeToLog(str_replace('[iNouvelId]', $iNouvelId, INFO_ORDER_CREATED), $properties["subscription_log_file"]);
+                                        // La surveillance crée une demande
+                                        sendWebsocketMessage($properties['websocket_server'], $properties['websocket_port'], $properties['websocket_alias'], array(
+                                            'action' => 'event',
+                                            'service' => 'GtfEvents',
+                                            'data' => array(
+                                                'event' => 'survey_creating_order',
+                                                'order' => array(
+                                                    'order_id' => $aDemande['order_id'],
+                                                    'order_status_id' => $aDemande['order_status_id'],
+                                                    'user_id' => $aDemande['user_id'],
+                                                    'workspace_id' => $aDemande['workspace_id']
+                                                )
+                                            )
+                                        ));
+                                    } else {
+                                        writeToLog(INFO_ORDER_CREATION_ERROR, $properties["subscription_log_file"]);
+                                        writeToLog(INFO_CHECK_SQL_LOG, $properties["subscription_log_file"]);
+                                    }
+                                } else {
+                                    writeToLog(INFO_NO_USER_GRANT . $aDemande['name'] . ' n\'as pas été définie.', $properties["subscription_log_file"]);
+                                    writeToLog(INFO_CONTACT_ADMINISTRATOR, $properties["subscription_log_file"]);
+                                    $iNouvelId = $oBd->update($properties["schema_gtf"], "order", Array("enabled" => FALSE), "order_id", $aDemande["order_id"], "");
+                                }
+                            }
+                        }
+                    }
+                }
+            } else {
+                writeToLog(str_replace('[sFolder]', $sFolder, INFO_DIRECTORY_NOT_FOUND_SUBSCRIPTION), $properties["subscription_log_file"]);
+            }
+        }
+    } else {
+        writeToLog(str_replace('[iPeriodeId]', $iPeriodeId, INFO_ORDER_PERIOD_NOT_FOUND), $properties["subscription_log_file"]);
+    }
+
+    if ($iNbTraitement >= 1) {
+        //writeToLog(INFO_END_ORDER_PROCESSING, $properties["subscription_log_file"]);
+    }
+    $oPDOResult = $oBd->fermeResultat();
+}
+
+function getParams($oGtfFmwParser, $sNewSource, $sParams) {
+    $aTGui = array();
+    $sChaine = "";
+    $aParams = dbParamsAsArray($sParams);
+    foreach ($oGtfFmwParser->aGuiObject as $aGui) {
+        if ($aGui->sDefault_Macro != "") {
+            array_push($aTGui, $aGui);
+        }
+    }
+    foreach ($aTGui as $oGui) {
+        //Teste si le paramètre est une source
+        if ($oGui->bIsSource) {
+            writeToErrorLog($oGui->sDefault_Macro);
+            writeToErrorLog($sNewSource);
+            $aParams[$oGui->sDefault_Macro] = $sNewSource;
+        }
+    }
+    $aKeys = array_keys($aParams);
+
+    for ($i = 0; $i < count($aKeys); $i++) {
+        if ($sChaine == "") {
+            $sChaine = $aKeys[$i] . "=" . $aParams[$aKeys[$i]];
+        } else {
+            $sChaine .= "|" . $aKeys[$i] . "=" . $aParams[$aKeys[$i]];
+        }
+    }
+    //$sChaine = substr($sChaine, 0, -1)."\"";
+    return $sChaine;
+}
+
+function dbParamsAsArray($sAllParams) {
+    $aAllParams = Array();
+    //$aLigne = explode("|", $sAllParams);
+    $aLigne = stringExplode($sAllParams, "|", "\"", "\"");
+    foreach ($aLigne as $sValeur) {
+        $sValeur = str_replace("\"", "", $sValeur);
+        $aValeurs = explode("=", $sValeur);
+        if ($aValeurs[2] != "") {
+            $sTemp = $aValeurs[1] . "=" . $aValeurs[2];
+            $aValeurs[1] = $sTemp;
+        }
+        $aAllParams[$aValeurs[0]] = $aValeurs[1];
+    }
+    return $aAllParams;
+}
+
+?>
\ No newline at end of file
diff --git a/gtf.engine/gtf.engines/subscription.sql.inc b/gtf.engine/gtf.engines/subscription.sql.inc
new file mode 100755
index 0000000000000000000000000000000000000000..46786f56f4b581f40195a98f7317c6ae107a3859
--- /dev/null
+++ b/gtf.engine/gtf.engines/subscription.sql.inc
@@ -0,0 +1,8 @@
+<?php
+//Requête pour subscription.php pgsql
+$aSql['pgsql']['verif_period_id']='SELECT period_id, name FROM [sSchemaGtf].period WHERE period_id = [iOrderPeriodId]';
+$aSql['pgsql']['abonnement']='SELECT "order".*, workspace.*, period.cron_expression FROM ([sSchemaGtf].order LEFT JOIN [sSchemaGtf].workspace ON "order".workspace_id=workspace.workspace_id) LEFT JOIN [sSchemaGtf].period ON period.period_id = "order".period_id WHERE order_status_id = 1 AND "order".period_id = [iOrderPeriodId] AND "order".period_id IS NOT NULL AND "order".survey_id IS NULL AND "order"."enabled" = TRUE ';
+$aSql['pgsql']['dir_survey']='SELECT "order".*, workspace.*, period.cron_expression, REPLACE(inbox.name, \'$user\', "user"."login") || \'/\' || "order".condition as condition FROM ([sSchemaGtf].order LEFT JOIN [sSchemaFramework].user on "order".user_id = "user"."user_id" LEFT JOIN [sSchemaGtf].inbox on "order".inbox_id = inbox.inbox_id LEFT JOIN [sSchemaGtf].workspace ON "order".workspace_id=workspace.workspace_id) LEFT JOIN [sSchemaGtf].period ON period.period_id = "order".period_id WHERE order_status_id = 1 AND "order".period_id = [iOrderPeriodId] AND "order".period_id IS NOT NULL AND "order".survey_id = 1 AND "order"."enabled" = TRUE';
+$aSql['pgsql']['right_user']='SELECT workspace."workspace_id" FROM [sSchemaGtf].workspace RIGHT JOIN [sSchemaGtf].workspace_group ON workspace.workspace_id = workspace_group.workspace_id GROUP BY workspace."workspace_id", workspace_group."group_id" HAVING workspace_group."group_id" IN ([sGroupListId]) ORDER BY workspace."workspace_id" ASC';
+$aSql['pgsql']["getLogin"]='SELECT "login" FROM [sSchemaFramework]."user" WHERE user_id = [iUserId]';
+?>
\ No newline at end of file
diff --git a/gtf.engine/gtf.engines/tcl/Traitement.tcl b/gtf.engine/gtf.engines/tcl/Traitement.tcl
new file mode 100755
index 0000000000000000000000000000000000000000..84defdd90f71dd4f671d9b42610fe24d3070c1d8
--- /dev/null
+++ b/gtf.engine/gtf.engines/tcl/Traitement.tcl
@@ -0,0 +1,64 @@
+# Récupération des variables d'environnement
+set sEnginesDir [file dirname $argv0]/..
+
+set sGtfDir $env(GTF_HOME)
+set sFmePath \{$env(FME_PATH)\}
+
+# Lecture de la librairie tclUtil
+source "$sEnginesDir/tcl/tclUtil.tcl"
+
+# Récupération des parametres sous forme de variables TCL
+set lLParams [stringToParam [lindex $argv 0] "|" "="]
+set lParametre [lindex $lLParams 0]
+set lValeur [lindex $lLParams 1]
+
+set sFmwFileName [lindex $lValeur 0]
+set sRobotLogName [lindex $lValeur 1] 
+set sFmeLogName [lindex $lValeur 2] 
+
+set i 0
+set sFmeParam ""
+foreach sParam $lParametre {
+  if {$sParam!="LOG_ROBOT" && $sParam!="LOG_FILENAME" && $sParam!="FMWFILENAME"} then {
+	set valeur [lindex $lValeur $i]
+	
+	# Vérification de l'emplacement de la balise <space>
+	set iSpacePlace [string first <space> $valeur]
+	# Si la balise existe, elle est remplacée par un espace (ça permet de gérer les cas ou la source (ex : de type access) peut contenir plusieurs extensions (mdb, accdb)
+	if {$iSpacePlace > 0} then {
+		set valeur [string map {<space> \ } $valeur]
+	}
+ 	set sFmeParam "$sFmeParam --$sParam \{$valeur\}"
+  }
+	incr i 
+}
+
+# Création de nouvelles variables
+set sScriptPath $sGtfDir/$sFmwFileName
+
+# Ecriture des parametres du traitement FME dans le log
+set sLigne "$sFmePath {$sScriptPath} $sFmeParam -LOG_FILENAME {$sFmeLogName}"
+
+# Variable qui va permettre d'écrire la commande TCL dans un fichier avec un nom unique
+set rand [expr int([expr rand() * 100000])]
+
+set sCommandeFile "$sEnginesDir/tcl/$rand.tcl"
+
+# Permet de récupérer un guillement (ajouté pour Edgar)
+set sLigne [string map {<quote> \"} $sLigne] 
+# Permet de récupérer un backslash (ajouté pour Edgar)
+set sLigne [string map {<backslashes> \\} $sLigne]
+
+set fCommande [open $sCommandeFile w+]
+# subst -nobackslashes $sLigne -- ligne inutile. Mis en commentaire le 20/06/12 par L.P.	
+puts $fCommande $sLigne
+close $fCommande
+
+if [ catch { source "$sCommandeFile" } sErreurFME] {
+	puts stdout "1|$sErreurFME" 
+} else {
+	puts stdout "0|Traitement réalisé avec succés"
+}
+
+file delete -force $sCommandeFile
+
diff --git a/gtf.engine/gtf.engines/tcl/commande.tcl b/gtf.engine/gtf.engines/tcl/commande.tcl
new file mode 100755
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/gtf.engine/gtf.engines/tcl/tclUtil.tcl b/gtf.engine/gtf.engines/tcl/tclUtil.tcl
new file mode 100755
index 0000000000000000000000000000000000000000..873ec019c0f13dbaae06f4a35897d1e9d23bf454
--- /dev/null
+++ b/gtf.engine/gtf.engines/tcl/tclUtil.tcl
@@ -0,0 +1,50 @@
+# + ---------------------------------------------------------------------- +
+# + tclUtil.tcl                                                            +
+# + Fonction TCL qui peuvent �tre r�utilis�es                              +
+# + Veremes - Fabien Marty - Mai 2007                                      +
+# + ---------------------------------------------------------------------- +
+
+
+##
+#D�coupe une chaine et renvoie les �l�ments d'une liste 
+#contenant une liste des param�tres et une liste des valeurs.
+##
+
+proc stringToParam {sString sDelimited1 sDelimited2} {
+	set lParams [split $sString $sDelimited1]
+	
+	foreach sParam $lParams {
+		set lResult [split $sParam =]
+		set sParametre [lindex $lResult 0]
+		set iLength [llength $lResult]
+	
+		if  { $iLength > 2 } {
+		set i 1
+		 while {$i < $iLength} {
+			set sTemp [lindex $lResult $i]
+			append sValeur $sTemp =
+		  set i [incr i]
+		 }
+
+		set sValue [string trimright $sValeur =]
+		} else {
+
+		set sValue [lindex $lResult 1]
+		}
+	lappend lListeParam $sParametre
+	lappend lListeValue $sValue
+	}	
+ return  [list $lListeParam $lListeValue]
+}
+
+##
+#�criture dans le log de la chaine pass�e en param�tre. 
+##
+
+proc writeToLog {sLogName sString sType} {
+	set oLogFile [open $sLogName "a"]
+	set sHeure [clock seconds]
+	set sHeureFormat [clock format $sHeure -format "%d/%m/%Y %H:%M:%S" -gmt false]
+	puts $oLogFile "$sHeureFormat	|$sType|TCL| $sString"
+	close $oLogFile
+}
\ No newline at end of file
diff --git a/gtf.engine/gtf.messages/class/Action.class.inc b/gtf.engine/gtf.messages/class/Action.class.inc
new file mode 100755
index 0000000000000000000000000000000000000000..037a03a7e3c266d861d90a185f7435d40ea78b07
--- /dev/null
+++ b/gtf.engine/gtf.messages/class/Action.class.inc
@@ -0,0 +1,74 @@
+<?php
+require_once("vmlib/logUtil.inc");
+
+class Action {
+	protected $messageclass_action_id;
+	protected $aParams;
+	protected $oMessage;
+	protected $aProperties;
+	
+/***********************************************************
+  Récupère les paramètres de l'action d'un message
+	\$messageclass_action_id : id de l'actionclass
+	\$oMessage : objet du message
+	\$aParams :  paramètres de l'actionclass
+***********************************************************/
+	function __construct($messageclass_action_id, $oMessage, $aParams) {
+		$this->oMessage = $oMessage;
+		$this->messageclass_action_id = $messageclass_action_id;
+		$this->aProperties = $oMessage->aProperties;
+	// Application des paramètres
+		$this->setActionClassParameters($aParams);
+	}
+
+/*******************************************************
+*******************************************************/
+	function execute() {
+	}
+
+	function getError(){
+		writeToLog("You need to implement your action error controller", $properties["processMessage_log_file"], false);
+		writeToErrorLog("You need to implement your action error controller");
+		return true;
+	}
+
+/*******************************************************
+  
+  \$aParams : Tableau des paramètres définis en base
+*******************************************************/
+	function setActionClassParameters($aParams) {
+		if (!empty($aParams)) {
+			$this->aParams = array();
+			foreach($aParams as $sActionParam) {
+				list($sActionParamName, $sActionParamValue) = explode('=', $sActionParam);
+				eval('$this->aParams[\'' . $sActionParamName . '\'] = ' . $sActionParamValue . ';');
+			}
+			$this->aParams["token"] = $this->getToken($this->aProperties);
+		}
+	}
+
+	function getToken ($properties) {
+
+		if($properties['web_server_name'] === "[HTTP_HOST]"){
+			$properties['web_server_name'] = "https://localhost";
+		}
+		$sUrl = $properties['web_server_name'] . '/' . $properties['services_alias'] . '/vitis/privatetoken';
+		$postfields = array('user'=>$properties["login_bot"], 'password'=>$properties["pass_bot"]);
+
+		$oToken = json_decode($this->postCurlRequest ($sUrl, $postfields));
+		return $oToken->token;
+	}
+
+	function postCurlRequest ($sUrl, $postfields) {
+		$ch = curl_init($sUrl);
+		curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
+		curl_setopt($ch, CURLOPT_HTTPHEADER, array("Accept: application/json"));
+		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+		curl_setopt($ch, CURLOPT_POST, 1);
+		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+		curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
+		curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
+		return curl_exec($ch);
+	}
+}
+?>
diff --git a/gtf.engine/gtf.messages/class/BoAction.class.inc b/gtf.engine/gtf.messages/class/BoAction.class.inc
new file mode 100755
index 0000000000000000000000000000000000000000..46eb93548990a8edd405225d5f8f6ae29a2cd011
--- /dev/null
+++ b/gtf.engine/gtf.messages/class/BoAction.class.inc
@@ -0,0 +1,43 @@
+<?php
+require_once("vmlib/logUtil.inc");
+require_once("Action.class.inc");
+
+class BoAction Extends Action {
+	protected $oBusinessObject;
+	protected $bError;
+/**********************************************************
+  Class constructor
+	\$oBd : objet PDO
+	\$messageclass_action_id : id de l'actionclass
+	\$oMessage : Objet de la classe message
+	\$aParams :  paramètres de l'actionclass
+**********************************************************/
+	function __construct($oBd, $messageclass_action_id, $oMessage, $aParams, $properties) {
+		parent::__construct($messageclass_action_id, $oMessage, $aParams);
+		$iBoId = $oMessage->getBody($this->aParams['bo_id_attribute']);
+		if (!empty($iBoId)){
+			require_once($properties["vas_home"] ."/rest/ws/" . $this->aParams['module'] . "/" . $this->aParams['class'] . ".class.inc");
+			$aPath = array($this->aParams['module'], $this->aParams['class'], $iBoId);
+			$aValues = array($this->aParams['bo_id_attribute'] => $iBoId, "token" => $this->aParams['token']);
+
+			$this->oBusinessObject = new $this->aParams['class']($aPath, $aValues, $properties);
+			$this->oBusinessObject->oConnection->oBd = $oBd;
+			$this->bError = false;
+		} else {
+			$this->bError = true;
+		}
+	}
+
+/*******************************************************
+  Change le statut.
+*******************************************************/
+	function execute() {
+		$sTransitionMethod = $this->aParams['method'];
+		$this->oBusinessObject->$sTransitionMethod();
+	}
+
+	function getError() {
+		return $this->bError;
+	}
+}
+?>
diff --git a/gtf.engine/gtf.messages/class/EmailAction.class.inc b/gtf.engine/gtf.messages/class/EmailAction.class.inc
new file mode 100755
index 0000000000000000000000000000000000000000..fa4d14cb7da96e8092881f668c9d4a26ad196fed
--- /dev/null
+++ b/gtf.engine/gtf.messages/class/EmailAction.class.inc
@@ -0,0 +1,40 @@
+<?php
+require_once("vmlib/logUtil.inc");
+require_once("vmlib/Email.class.inc");
+require_once("Action.class.inc");
+
+class EmailAction Extends Action {
+	protected $oEmail;
+	protected $bError;
+/**********************************************************
+  - Récupère les paramètres de l'action d'un message
+  - Crée un objet de la classe "Email".
+  - Applique les paramètres 
+	\$oBd : objet PDO
+	\$messageclass_action_id : id de l'actionclass
+	\$oMessage : Objet de la classe message
+	\$aParams :  paramètres de l'actionclass
+**********************************************************/
+	function __construct($oBd, $messageclass_action_id, $oMessage, $aParams) {
+		parent::__construct($messageclass_action_id, $oMessage, $aParams);
+		$aObjects['oMessage'] = $oMessage;
+		$iEmailTemplateId = $this->aParams['template_id'];
+		if (empty($iEmailTemplateId))
+			$iEmailTemplateId = $oMessage->aProperties['default_mail_model'];
+		$this->oEmail = new Email($oBd, $iEmailTemplateId, $oMessage->aProperties, $aObjects);
+		$this->bError = false;
+	}
+
+/*******************************************************
+  Envoi un email.
+*******************************************************/
+	function execute() {
+		if (!empty($this->oEmail->oEmailTemplate->name))
+			$this->oEmail->send();
+	}
+
+	function getError() {
+		return $this->bError;
+	}
+}
+?>
diff --git a/gtf.engine/gtf.messages/class/Message.class.inc b/gtf.engine/gtf.messages/class/Message.class.inc
new file mode 100755
index 0000000000000000000000000000000000000000..59ad4a9ebbf6ca3c73a433a86ebbeb7f23039193
--- /dev/null
+++ b/gtf.engine/gtf.messages/class/Message.class.inc
@@ -0,0 +1,155 @@
+<?php
+/**
+* \class Message
+* \file Message.class.inc
+*/
+
+require_once("vmlib/logUtil.inc");
+
+class Message {
+	protected $message_id;
+	public $messageclass;
+	protected $creation_date;
+	protected $status;
+	protected $body;
+	protected $bo_class_name;
+	protected $bo_class;
+	protected $bo_id;
+	protected $sender;
+	protected $oBo;
+	protected $oBd;
+	protected $aBodyValue;
+	public $aProperties;
+	protected $aSql;
+
+	/**
+	* Class constructor
+	* \param $oBd Connection object.
+	* \param $message_id Message id.
+	* \param $aProperties Array of properties.
+	*/
+	function __construct($oBd, $message_id , $aProperties) {
+		require("Message.class.sql.inc");
+		$this->aProperties = $aProperties;
+		$this->oBd = $oBd;
+		$this->aSql = $aSql;
+		$sSql = $this->aSql[$oBd->sgbd]['getMessage'];
+		//$sSql = str_replace('[message_id]',$message_id , $sSql);
+		//$sSql = str_replace('[schema]',$aProperties['schema_gtf'] , $sSql);
+		$aParams = array(
+			"message_id" => array("value"=> $message_id, "type"=> 'number'),
+			"schema" => array("value"=> $aProperties['schema_gtf'], "type"=> 'column_name')
+			);
+		$oResult = $oBd->executeWithParams($sSql, $aParams);
+		if($oBd->erreurRencontree)
+			$sErrorMsg = $oBd->getBDMessage();
+		else {
+			if ($oBd->nombreLigne ($oResult) > 0) {
+				$oRow = $oBd->objetSuivant ($oResult);
+				$this->message_id = $oRow->message_id;
+				$this->messageclass = $oRow->messageclass;
+				$this->creation_date = $oRow->creation_date;
+				$this->status = $oRow->status;
+				$this->body = $oRow->body;
+				//$this->bo_class_name = $oRow->bo_class_name;
+				//$this->bo_id = $oRow->bo_id;
+				$this->sender = $oRow->sender;
+			// Extrait les paramètres pour les actions de body
+				if (!empty($this->body)) {
+					preg_match_all('/(.)+:(.)+/', $this->body, $aActionParams);
+					if (!empty($aActionParams[0])) {
+						foreach ($aActionParams[0] as $sActionParam) {
+							list($sIndex, $sValue) = explode(':', $sActionParam);
+							$this->aBodyValue[trim($sIndex)] = trim($sValue);
+						}
+					}
+				}
+			}
+		}
+		if (isset($sErrorMsg)){
+			writeToLog("The message " . $message_id . "encountered this error : " . $sErrorMsg, $properties["processMessage_log_file"], false);
+		}
+	}
+
+	/*
+	* function setProcessed
+	* \brief Change the status of a message.
+	* \param $processed boolean.
+	*/
+	function setProcessed($processed) {
+		if ($processed === true)
+                $this->status = 3; // Traité
+            else
+                $this->status = 2; // En erreur
+        }
+
+	/*
+	* function process
+	* \brief Executes all actions of the message.
+	*/
+	function process() {
+	// Liste des actions du message	
+		$sSql = $this->aSql['pgsql']['getMessageActions'];
+		//$sSql = str_replace("[messageclass]", $this->messageclass, $sSql);
+		//$sSql = str_replace("[schema]", $this->aProperties['schema_gtf'], $sSql);
+		$aParams = array(
+			"messageclass" => array("value"=> $this->messageclass, "type"=> 'string'),
+			"schema" => array("value"=> $this->aProperties['schema_gtf'], "type"=> 'column_name')
+			);
+		$oActionResult = $this->oBd->executeWithParams($sSql, $aParams);
+		if(!$this->oBd->erreurRencontree) {
+			if ($this->oBd->nombreLigne($oActionResult) > 0) {
+				while ($oActionRow = $this->oBd->objetSuivant ($oActionResult)) {
+					if (file_exists(__DIR__ . '/' . $oActionRow->actionclass . '.class.inc')) {
+						require_once __DIR__ . '/' . $oActionRow->actionclass . '.class.inc';
+						if (!empty($oActionRow->parameters))
+							$aParams = explode('|', $oActionRow->parameters);
+						$oAction = new $oActionRow->actionclass($this->oBd, $oActionRow->messageclass_action_id, $this, $aParams, $this->aProperties);
+						if($oAction->getError() == false){
+							$oAction->execute();
+						} else {
+							writeToLog("ERROR : cannot create action with this body's parameters", $properties["processMessage_log_file"], false);
+							throw new Exception("ERROR : cannot create action with this body's parameters");
+						}
+					}
+				}
+			}
+		}
+	}
+	
+	/*
+	* function getBody
+	* \param $key boolean.
+	* \return Returns the value of a parameter of action (or all the parameters and values).
+	*/
+	function getBody($key = null) {
+		if (is_null($key))
+			return $this->body;
+		else {
+			if (isset($this->aBodyValue[$key]))
+				return $this->aBodyValue[$key];
+			else
+				return null;
+		}
+	}
+
+	/*
+	* function update
+	* \brief Saves the settings of a message.
+	*/
+	function update() {
+	// Tous les paramètres sauf les tableaux et objets	
+		foreach (get_object_vars($this) as $sIndex => $value) {
+			if (!is_array($value) && !is_object($value)) {
+			// Le paramètre est une date ?	
+				/*if (strtotime($value) !== false)
+					$aValues[$sIndex] = "'$value'";
+				else*/
+					$aValues[$sIndex] = $value;
+			}
+		}
+		//error_log(print_r($this->oBd, true));
+		$this->oBd->update($this->aProperties['schema_gtf'], 'message', $aValues, 'message_id', $this->message_id, 'numeric');
+	}
+}
+?>
diff --git a/gtf.engine/gtf.messages/class/Message.class.sql.inc b/gtf.engine/gtf.messages/class/Message.class.sql.inc
new file mode 100755
index 0000000000000000000000000000000000000000..47a0f8e9d35285d7b987010d69d8850e88a887d1
--- /dev/null
+++ b/gtf.engine/gtf.messages/class/Message.class.sql.inc
@@ -0,0 +1,4 @@
+<?php
+	$aSql['pgsql']['getMessage'] = "SELECT * FROM [schema].message WHERE message_id = [message_id]";
+	$aSql['pgsql']['getMessageActions'] = "SELECT * FROM [schema].messageclass_action WHERE messageclass = [messageclass] ORDER BY index";
+?>
\ No newline at end of file
diff --git a/gtf.engine/gtf.messages/processMessages.bat b/gtf.engine/gtf.messages/processMessages.bat
new file mode 100755
index 0000000000000000000000000000000000000000..ae8efcb51a1f8fac481668670c5bad68f23a0272
--- /dev/null
+++ b/gtf.engine/gtf.messages/processMessages.bat
@@ -0,0 +1,5 @@
+@echo off
+set GTF_MESSAGE_HOME=%~dp0
+set PHP_HOME=%GTF_MESSAGE_HOME%..\gtf.engines\php
+rem %1 correspond au paramètre passé par pycron
+"%PHP_HOME%\php.exe" "%GTF_MESSAGE_HOME%processMessages.php" %1
diff --git a/gtf.engine/gtf.messages/processMessages.php b/gtf.engine/gtf.messages/processMessages.php
new file mode 100755
index 0000000000000000000000000000000000000000..bfa420081d3d60e0607bc66189a68a73444f1b1e
--- /dev/null
+++ b/gtf.engine/gtf.messages/processMessages.php
@@ -0,0 +1,173 @@
+<?php
+	session_start();
+	
+	require_once dirname($_SERVER['PHP_SELF']).'/../gtf.engines/php_engine_conf.inc';
+	require_once dirname($_SERVER['PHP_SELF']).'/../gtf.engines/properties_engine.inc';
+	
+	require_once("vmlib/BD.class.inc");
+	require_once("vmlib/Vm.class.inc"); 
+	require_once("processMessages.sql.inc");
+	require_once("class/Message.class.inc");
+
+	$sPidFile = __DIR__ . "/PID_processMessages.pid";
+
+	$oNow = new DateTime();
+	$properties["processMessage_log_file"] = $properties['log_directories'] ['Application'] . "/processMessage/log_" . $oNow->format('Y-m-d') . ".log";
+
+	processIsRunnning ($sPidFile, $properties);
+	createPidFile($sPidFile, $properties);
+
+	//journalisation des logs pour le mailReader aussi 
+	// instanciation d'un objet pour accéder à la base compte u_vitis
+	$oBd = new BD ($properties['login_scheduler'], $properties['password_scheduler'], $properties["database"], $properties["server"], $properties["port"], $properties["sgbd"], $properties["page_encoding"]);
+
+	$iMessages = 0;
+	$iMessagesTraite = 0;
+
+	if ($oBd->erreurRencontree)
+		writeToLog('can\'t connect to database ' . $properties["database"] . " on " . $properties["server"] . ":" . $properties["port"] , $properties["processMessage_log_file"], false);
+	else {
+		// Traitement des messages en attente.
+		$sSql = $aSql['pgsql']['getWaitingMessages'];
+
+		$aParams = array(
+			"messageclass_type" => array("value"=> 'action', "type"=> 'string'),
+			"schema" => array("value"=> $properties['schema_gtf'], "type"=> 'column_name')
+			);
+
+		$oMessageResult=$oBd->executeWithParams($sSql, $aParams);
+		if(!$oBd->erreurRencontree) {
+			$iMessages = $oBd->nombreLigne($oMessageResult);
+			if ($iMessages > 0) {
+                // fonction à appeler à la fin du script.
+                register_shutdown_function('shutdownCallBack', $oBd, $properties);
+                // Traitement des messages en attente.
+                while ($oMessageRow = $oBd->objetSuivant ($oMessageResult)) {
+                    $iMessageId = $oMessageRow->message_id;
+                    $oMessage = new Message($oBd, $oMessageRow->message_id, $properties);
+                    $iOrderId = $oMessage->getBody("order_id");
+					if (!empty($iOrderId)){
+						$sSql = $aSql['pgsql']['getOrderStatus'];;
+						$sSql = str_replace("[ORDER_ID]", $iOrderId, $sSql);
+						$oOrderResult=$oBd->execute($sSql);
+						if(!$oBd->erreurRencontree) {
+							$oOrderRow = $oBd->objetSuivant ($oOrderResult);
+							if ($oOrderRow->order_status_id == 3 ){
+								$oMessage->process();
+								$oMessage->setProcessed(true);
+							    $oMessage->update();
+							    $iMessagesTraite ++;
+							}else{
+								writeToLog("message " . $iMessageId . " : can't be processing for the moment because the linked GTF order is not completed or it status is not 'valid'", $properties["processMessage_log_file"], false);
+							}
+						} else {
+							$oMessage->setProcessed(false);
+							$oMessage->update();
+							writeToLog("message " . $iMessageId . " : can't be processing because we can't find the linked GTF order", $properties["processMessage_log_file"], false);
+						}
+					} else {
+						$oMessage->process();
+						$oMessage->setProcessed(true);
+						$oMessage->update();
+						$iMessagesTraite ++;
+					}
+                }
+			}
+		}else{
+			writeToLog($oBd->getBDMessage(), $properties["processMessage_log_file"], false);
+		}
+	}
+
+	writeToLog("Iteration of the process completed : " . $iMessages . "(". $iMessagesTraite ." as OK)", $properties["processMessage_log_file"], false);
+
+	unlink($sPidFile);
+        
+	/*
+	* function shutDownCallBack
+	*   @oBd Database connection object.
+	*   @properties
+	*/
+        function shutDownCallBack($oBd, $properties) {
+            $aError = error_get_last();
+            // Erreur fatale pendant le traitement d'un message ?
+            if ($aError['type'] & E_ERROR > 0) {
+                writeToLog("[ERROR] [PHP] while processing the message " . $GLOBALS['iMessageId'] . "check the main log file", $properties["processMessage_log_file"], false);
+                // Change le statut du message : "en erreur".
+                $oMessage = new Message($oBd, $GLOBALS['iMessageId'], $properties);
+                $oMessage->setProcessed(false);
+                $oMessage->update();
+                // Re-exécute le script (au cas où il resterait des messages non traités).
+                if(DIRECTORY_SEPARATOR === "/"){
+                	// if linux
+                	exec(__DIR__ . '/processMessages.sh');
+                } else {
+                	// if windows
+                	exec(__DIR__ . '\processMessages.bat');
+                }
+            }
+        }
+
+        function processIsRunnning ($sPidFile, $properties){
+			if (file_exists ($sPidFile)){
+				// récupération du fichier .pid
+				$sPid = file_get_contents($sPidFile);
+				
+				$bProcessIsRunning = true;
+				$sOsName = PHP_OS;
+				// detection de l'os pour savoir comment controler le PID
+				if (strtoupper(substr($sOsName, 0, 3)) === 'WIN') {
+			    	$bProcessIsRunning = windowsPidCheck($sPid);
+				} else {
+				    $bProcessIsRunning = linuxPidCheck($sPid);
+				}
+
+				if($bProcessIsRunning === false){
+					//si le fichier PID est présent mais que le PID n'existe pas sur le serveur
+					// on supprime le fichier .pid et on lance le mailReader 
+					writeToLog("previous process exited without cleaning pidfile, removing", $properties["processMessage_log_file"], false);
+					unlink($sPidFile);
+				} else {
+					//si le process tourne déjà on ferme le process courant
+					writeToLog("found a running instance of processMessages.php, exiting.", $properties["processMessage_log_file"], false);
+					exit(0);
+				}
+			}
+			return true;
+		}
+
+		function windowsPidCheck ($iPid){
+			// fonction pour controller si un pid existe sous windows
+			$processes = explode( "\n", shell_exec('tasklist.exe /fi "PID eq ' . $iPid . '"'));
+
+			foreach( $processes as $process ) {
+
+			     if( ! empty($process) && (strpos("===", $process ) === 0) ){
+			          continue;
+			     }
+
+			     $matches = array();
+			     preg_match("/(.*?)\s+(\d+).*$/", $process, $matches);
+
+			     if(count($matches) > 0){
+			     	return true;
+			     }
+			}
+			return false;
+		}
+
+		function linuxPidCheck ($iPid){
+			// fonction pour controller si un pid existe sous linux
+			return file_exists("/proc/" . $iPid);
+		}
+
+		function createPidFile($sPidFile , $properties){
+		   	$file = fopen($sPidFile, 'w');
+		   	
+		   	if($file){ 
+		   		writeToLog("PID file creation with pid : " . getmypid(), $properties["processMessage_log_file"], false);
+		   		fwrite($file, getmypid());
+			}
+
+		   	fclose($file);
+		}
+?>
\ No newline at end of file
diff --git a/gtf.engine/gtf.messages/processMessages.sh b/gtf.engine/gtf.messages/processMessages.sh
new file mode 100755
index 0000000000000000000000000000000000000000..89dadbfb61faff67c07e7a7c4918d45f7287a10e
--- /dev/null
+++ b/gtf.engine/gtf.messages/processMessages.sh
@@ -0,0 +1,5 @@
+@echo off
+set GTF_MESSAGE_HOME=%~dp0
+set PHP_HOME=%GTF_MESSAGE_HOME%..\gtf.engines\php
+#rem %1 correspond au paramètre passé par pycron
+"../gtf.engines/php/bin/php" "./processMessages.php" %1
\ No newline at end of file
diff --git a/gtf.engine/gtf.messages/processMessages.sql.inc b/gtf.engine/gtf.messages/processMessages.sql.inc
new file mode 100755
index 0000000000000000000000000000000000000000..6f4814573cb781855de841e3f8395d2cb12cf17a
--- /dev/null
+++ b/gtf.engine/gtf.messages/processMessages.sql.inc
@@ -0,0 +1,4 @@
+<?php
+	$aSql['pgsql']['getWaitingMessages']='SELECT message.message_id FROM [schema].message,[schema].messageclass WHERE status=1 AND message.messageclass=messageclass.messageclass AND lower(messageclass_type)=lower([messageclass_type]) ORDER BY message_id;';
+	$aSql['pgsql']['getOrderStatus']='SELECT order_status_id FROM s_gtf.order WHERE order_id = [ORDER_ID] LIMIT 1';
+?>
\ No newline at end of file