From 9c28fddcb94a026ad7ada6a0162979fc2a37d357 Mon Sep 17 00:00:00 2001
From: ArmandBahi <armand.bahi@veremes.com>
Date: Tue, 16 Oct 2018 17:39:02 +0200
Subject: [PATCH] Update from SVN

---
 web_service/class/gtf_lib/FmeCloud.class.inc  |  73 ++-
 .../class/gtf_lib/FmeCloudForGtf.class.inc    |   2 +-
 web_service/class/gtf_lib/FmeServer.class.inc | 540 ++++++++++++++----
 .../gtf_lib/gtf_object/Category.class.inc     |   0
 .../gtf_lib/gtf_object/FmeEngine.class.inc    |   0
 .../gtf_lib/gtf_object/GtfEngine.class.inc    |   0
 .../class/gtf_lib/gtf_object/Order.class.inc  |   0
 .../class/gtf_lib/gtf_object/User.class.inc   |   0
 .../gtf_lib/gtf_object/Workspace.class.inc    |   0
 .../gtf_lib/imap_reader/ImapConnection.php    |   0
 .../class/gtf_lib/imap_reader/MailBox.php     |   0
 .../class/gtf_lib/imap_reader/MailStruct.php  |  11 +-
 web_service/class/gtf_lib/phpUtility.inc      |  35 ++
 web_service/conf/properties.inc               |   2 +
 web_service/conf/properties_server.inc        |   1 +
 web_service/conf/selected_properties.inc      |  16 +-
 web_service/sql/maj.sql                       |   8 +-
 web_service/sql/sqlQueries.xml                | 238 +++++++-
 web_service/ws/FmeEngine.class.inc            |  76 ++-
 web_service/ws/FmeEngines.class.inc           | 362 ++++++++++--
 web_service/ws/Gtf.class.sql.inc              |  12 +
 web_service/ws/Instance.class.inc             |  59 +-
 web_service/ws/Message.class.inc              |   2 +-
 web_service/ws/Messages.class.inc             |   6 +-
 web_service/ws/Order.class.inc                |   3 +-
 web_service/ws/Orders.class.inc               | 446 ++++++++++++++-
 web_service/ws/SchemaGroup.class.inc          |  73 +++
 web_service/ws/SchemaGroups.class.inc         | 184 ++++++
 web_service/ws/SchemaGroups.class.sql.inc     |   7 +
 web_service/ws/Subscription.class.inc         |   2 +-
 web_service/ws/Subscriptions.class.inc        |   6 +-
 web_service/ws/Survey.class.inc               |   2 +-
 web_service/ws/Surveys.class.inc              |   6 +-
 web_service/ws/UserOrder.class.inc            |   2 +-
 web_service/ws/UserOrders.class.inc           |   9 +-
 web_service/ws/UserSubscription.class.inc     |   2 +-
 web_service/ws/UserSubscriptions.class.inc    |   4 +-
 web_service/ws/UserSurvey.class.inc           |   2 +-
 web_service/ws/UserSurveys.class.inc          |   4 +-
 web_service/ws/Workspace.class.inc            |  16 +-
 web_service/ws/Workspaces.class.inc           |  40 +-
 .../ws_data/gtf/workspace/S3Downloader.fmw    | 265 +++++++++
 .../ws_data/gtf/workspace/S3Uploader.fmw      | 274 +++++++++
 43 files changed, 2495 insertions(+), 295 deletions(-)
 mode change 100755 => 100644 web_service/class/gtf_lib/FmeServer.class.inc
 mode change 100755 => 100644 web_service/class/gtf_lib/gtf_object/Category.class.inc
 mode change 100755 => 100644 web_service/class/gtf_lib/gtf_object/FmeEngine.class.inc
 mode change 100755 => 100644 web_service/class/gtf_lib/gtf_object/GtfEngine.class.inc
 mode change 100755 => 100644 web_service/class/gtf_lib/gtf_object/Order.class.inc
 mode change 100755 => 100644 web_service/class/gtf_lib/gtf_object/User.class.inc
 mode change 100755 => 100644 web_service/class/gtf_lib/gtf_object/Workspace.class.inc
 mode change 100644 => 100755 web_service/class/gtf_lib/imap_reader/ImapConnection.php
 mode change 100644 => 100755 web_service/class/gtf_lib/imap_reader/MailBox.php
 mode change 100644 => 100755 web_service/class/gtf_lib/imap_reader/MailStruct.php
 mode change 100755 => 100644 web_service/conf/properties.inc
 mode change 100755 => 100644 web_service/conf/selected_properties.inc
 mode change 100755 => 100644 web_service/sql/maj.sql
 mode change 100755 => 100644 web_service/sql/sqlQueries.xml
 mode change 100755 => 100644 web_service/ws/FmeEngine.class.inc
 mode change 100755 => 100644 web_service/ws/FmeEngines.class.inc
 mode change 100755 => 100644 web_service/ws/Gtf.class.sql.inc
 mode change 100755 => 100644 web_service/ws/Order.class.inc
 create mode 100755 web_service/ws/SchemaGroup.class.inc
 create mode 100755 web_service/ws/SchemaGroups.class.inc
 create mode 100755 web_service/ws/SchemaGroups.class.sql.inc
 mode change 100644 => 100755 web_service/ws/Workspace.class.inc
 mode change 100644 => 100755 web_service/ws/Workspaces.class.inc
 create mode 100755 web_service/ws_data/gtf/workspace/S3Downloader.fmw
 create mode 100755 web_service/ws_data/gtf/workspace/S3Uploader.fmw

diff --git a/web_service/class/gtf_lib/FmeCloud.class.inc b/web_service/class/gtf_lib/FmeCloud.class.inc
index 2c6ba612..fc8eaec6 100755
--- a/web_service/class/gtf_lib/FmeCloud.class.inc
+++ b/web_service/class/gtf_lib/FmeCloud.class.inc
@@ -1,9 +1,17 @@
 <?php
 require_once("vmlib/logUtil.inc");
 
+/**
+ * \file FmeCloud.php
+ * \brief Main class to use Fme Cloud services.
+ *
+ * \author Frederic Carretero <frederic.carretero@veremes.com>
+ */
+
 Class FmeCloud {
     public $sUrl;
     public $aLastCurlRequestInfo;
+    public $sLogFilePath;   // Chemin optionnel vers le fichier de log pour Fme Cloud.
     private $sToken;
     
     /**
@@ -104,9 +112,18 @@ Class FmeCloud {
         $sUrl = $this->sUrl;
         // Url vers le service d'information.
         $sUrl = $this->sUrl . '/v1/' . $sService;
-        echo $sUrl . PHP_EOL;
         // Transfert cURL
-        return json_decode($this->curlRequest($sUrl, $sMethod, $aData));
+        $sRequestResponse = $this->curlRequest($sUrl, $sMethod, $aData);
+        if ($this->aLastCurlRequestInfo['http_code'] >= 400) {
+            $oRequestResponse = json_decode($sRequestResponse);
+            if (is_object($oRequestResponse) && !empty($oRequestResponse->exception) && !empty($oRequestResponse->exception->message))
+                $this->writeToErrorLog('|' . $sService . '|' . ' ' . $oRequestResponse->message);
+            else
+                $this->writeToErrorLog('|' . $sService . '|' . ' ' . $sRequestResponse);
+            return false;
+        }
+        else
+            return json_decode($sRequestResponse);
     }
     
     /**
@@ -119,9 +136,18 @@ Class FmeCloud {
         $sUrl = $this->sUrl;
         // Url vers le service d'information.
         $sUrl = $this->sUrl . '/v1/instances/' . $iId . '/start';
-        echo $sUrl . PHP_EOL;
         // Transfert cURL
-        return json_decode($this->curlRequest($sUrl, 'PUT'));
+        $sRequestResponse = $this->curlRequest($sUrl, 'PUT');
+        if ($this->aLastCurlRequestInfo['http_code'] >= 400) {
+            $oRequestResponse = json_decode($sRequestResponse);
+            if (is_object($oRequestResponse) && !empty($oRequestResponse->exception) && !empty($oRequestResponse->exception->message))
+                $this->writeToErrorLog($oRequestResponse->exception->message);
+            else
+                $this->writeToErrorLog($sRequestResponse);
+            return false;
+        }
+        else
+            return json_decode($sRequestResponse);
     }
     
     /**
@@ -134,9 +160,18 @@ Class FmeCloud {
         $sUrl = $this->sUrl;
         // Url vers le service d'information.
         $sUrl = $this->sUrl . '/v1/instances/' . $iId . '/pause';
-        echo $sUrl . PHP_EOL;
         // Transfert cURL
-        return json_decode($this->curlRequest($sUrl, 'PUT'));
+        $sRequestResponse = $this->curlRequest($sUrl, 'PUT');
+        if ($this->aLastCurlRequestInfo['http_code'] >= 400) {
+            $oRequestResponse = json_decode($sRequestResponse);
+            if (is_object($oRequestResponse) && !empty($oRequestResponse->exception) && !empty($oRequestResponse->exception->message))
+                $this->writeToErrorLog($oRequestResponse->exception->message);
+            else
+                $this->writeToErrorLog($sRequestResponse);
+            return false;
+        }
+        else
+            return json_decode($sRequestResponse);
     }
     
     /**
@@ -149,9 +184,31 @@ Class FmeCloud {
         $sUrl = $this->sUrl;
         // Url vers le service d'information.
         $sUrl = $this->sUrl . '/v1/instances/' . $iId . '/credentials';
-        echo $sUrl . PHP_EOL;
         // Transfert cURL
-        return json_decode($this->curlRequest($sUrl, 'GET'));
+        $sRequestResponse = $this->curlRequest($sUrl, 'GET');
+        if ($this->aLastCurlRequestInfo['http_code'] >= 400) {
+            $oRequestResponse = json_decode($sRequestResponse);
+            if (is_object($oRequestResponse) && !empty($oRequestResponse->exception) && !empty($oRequestResponse->exception->message))
+                $this->writeToErrorLog($oRequestResponse->exception->message);
+            else
+                $this->writeToErrorLog($sRequestResponse);
+            return false;
+        }
+        else
+            return json_decode($sRequestResponse);
+    }
+    
+    /**
+     * Write a message to the error log file.
+     * @param {string} $sMessage Message to write to the log file.
+     */
+    function writeToErrorLog($sMessage) {
+        $aDebugBacktrace = debug_backtrace();
+        $sLogMessage = '|ERROR|' . $aDebugBacktrace[1]['class'] . '::' . $aDebugBacktrace[1]['function'] . '| ' . $sMessage;
+        if (empty($this->sLogFilePath))
+            writeToErrorLog($sLogMessage);
+        else
+            writeToLog($sLogMessage, $this->sLogFilePath);
     }
 }
 ?>
\ No newline at end of file
diff --git a/web_service/class/gtf_lib/FmeCloudForGtf.class.inc b/web_service/class/gtf_lib/FmeCloudForGtf.class.inc
index da2e8793..b0f5a1eb 100755
--- a/web_service/class/gtf_lib/FmeCloudForGtf.class.inc
+++ b/web_service/class/gtf_lib/FmeCloudForGtf.class.inc
@@ -1,5 +1,5 @@
 <?php
-require 'gtf_lib/AmazonApiGateway.class.inc';
+require 'aws_lib/AmazonApiGateway.class.inc';
 
 Class FmeCloudForGtf extends AmazonApiGateway {
     public $sGtfInstanceId; // Id de l'instance de GTF.
diff --git a/web_service/class/gtf_lib/FmeServer.class.inc b/web_service/class/gtf_lib/FmeServer.class.inc
old mode 100755
new mode 100644
index e05b1bf7..dd483395
--- a/web_service/class/gtf_lib/FmeServer.class.inc
+++ b/web_service/class/gtf_lib/FmeServer.class.inc
@@ -1,11 +1,25 @@
 <?php
 require_once("vmlib/logUtil.inc");
 
+/**
+ * \file FmeServer.php
+ * \brief Main class to use Fme Server services.
+ *
+ * \author Frederic Carretero <frederic.carretero@veremes.com>
+ */
+
 Class FmeServer {
+    const CURL_CONNECTION_TIMEOUT = 0;
+    const CURL_TIMEOUT = 360;
+    const INFO_FME_SERVER_JOB_CANCELED = '|INFORM|PHP| Le traitement a été annulé sur Fme Server';
+    const INFO_FME_SERVER_JOB_STOPPED = '|INFORM|PHP| Le traitement a été arrêté sur Fme Server';
+    const INFO_FME_SERVER_JOB_REMOVED = '|INFORM|PHP| Le traitement a été supprimé sur Fme Server';
+    
     public $sUrl;
     public $sTimeUnit;
     public $iExpiration;
     public $aLastCurlRequestInfo;
+    public $sLogFilePath;   // Chemin optionnel vers le fichier de log pour Fme Server.
     private $sUser;
     private $sPassword;
     private $sToken;
@@ -46,7 +60,13 @@ Class FmeServer {
             'update' => $this->bUpdate
         );
         // Transfert cURL
-        $this->sToken = $this->curlRequest($sUrl, 'post', $aRequestData);
+        $sRequestResponse = $this->curlRequest($sUrl, 'post', $aRequestData);
+        if ($this->aLastCurlRequestInfo['http_code'] != 200) {
+            $this->writeToErrorLog($sRequestResponse);
+            $this->sToken = false;
+        }
+        else
+            $this->sToken = $sRequestResponse;
         return $this->sToken;
     }
     
@@ -91,8 +111,10 @@ Class FmeServer {
         if (!empty($this->sToken))
             $aHeaders[] = 'Authorization: fmetoken token=' . $this->sToken; // Token obligatoire pour éxécuter la requête.
         curl_setopt($ch, CURLOPT_HTTPHEADER, $aHeaders);
-        // Durée max. de la requête.
-        //curl_setopt($ch, CURLOPT_TIMEOUT, 120);
+        // Le nombre de secondes à attendre durant la tentative de connexion.
+        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, self::CURL_CONNECTION_TIMEOUT);
+        // Le temps maximum d'exécution de la fonction cURL (secondes).
+        curl_setopt($ch, CURLOPT_TIMEOUT, self::CURL_TIMEOUT);
         // Exécute la session CURL.
         // Log.
         /*
@@ -104,13 +126,16 @@ Class FmeServer {
         curl_setopt($ch, CURLINFO_HEADER_OUT, true);
         // Curl error: SSL certificate problem: unable to get local issuer certificate
         // Curl error n°60
-        curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, false);      
+        curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, false);
+        // Curl error: SSL: no alternative certificate subject name matches target host name '52.205.208.184' (si utilisation de l'adresse ip et non )
+        // Curl error n°51
+        curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
         //
         $output = curl_exec($ch);
         // Erreur de la requête CURL.
         if(curl_errno($ch)) {
-            writeToErrorLog('Curl error: ' . curl_error($ch));
-            writeToErrorLog('Curl error n°' . curl_errno($ch));
+            $this->writeToErrorLog('Curl error: ' . curl_error($ch));
+            $this->writeToErrorLog('Curl error n°' . curl_errno($ch));
         }
         // Informations de la requête.
         $aCurlInfo = curl_getinfo($ch);
@@ -133,42 +158,78 @@ Class FmeServer {
      * @param {array} $aData Data of the Curl request.
      * @return Request result
      */
-    function serviceRequest($sService, $sMethod = 'get', $aData = array()) {
+    function serviceRequest($sService, $sMethod = 'get', $aData = array(), $bWriteToErrorLog = true) {
         // Demande de token.
         $this->getToken();
-        // Url vers le serveur fme.
-        $sUrl = $this->sUrl;
-        // Url vers le service d'information.
-        $sUrl = $this->sUrl . '/fmerest/v3/' . $sService;
-        // Transfert cURL
-        return json_decode($this->curlRequest($sUrl, $sMethod, $aData));
+        if ($this->sToken !== false) {
+            // Url vers le serveur fme.
+            $sUrl = $this->sUrl;
+            // Url vers le service d'information.
+            $sUrl = $this->sUrl . '/fmerest/v3/' . $sService;
+            // Transfert cURL
+            $sRequestResponse = $this->curlRequest($sUrl, $sMethod, $aData);
+            if ($this->aLastCurlRequestInfo['http_code'] >= 400) {
+                if ($bWriteToErrorLog) {
+                    $oRequestResponse = json_decode($sRequestResponse);
+                    if (is_object($oRequestResponse) && !empty($oRequestResponse->message))
+                        $this->writeToErrorLog('|' . $sService . '|' . ' ' . $oRequestResponse->message);
+                    else
+                        $this->writeToErrorLog('|' . $sService . '|' . ' ' . $sRequestResponse);
+                }
+                return false;
+            }
+            else
+                return json_decode($sRequestResponse);
+        }
+        else
+            return false;
     }
     
     /**
      * Upload a file
      * @param {string} $sFilePath Path of the file to upload.
      * @param {string} $sServiceUrl Url of the web service to upload the file.
+     * @param {string} $sFileName Name of the created file.
      * @return Request result
      */
-    function uploadFile($sServiceUrl, $sFilePath) {
+    function uploadFile($sServiceUrl, $sFilePath, $sFileName = '') {
         if (file_exists($sFilePath)) {
             // Demande de token.
             $this->getToken();
-            // Nom du fichier.
-            $sFileName = pathinfo($sFilePath, PATHINFO_BASENAME);
-            // Type MIME du fichier.
-            //$finfo = finfo_open(FILEINFO_MIME_TYPE);            
-            // Crée un objet CURLFile.
-            //$oCfile = new CURLFile($sFilePath, finfo_file($finfo, $sFilePath), $sFileName);
-            //finfo_close($finfo);
-            // Entêtes de la requête Curl.
-            $aRequestHeaders = array(
-                'Content-Type: application/octet-stream',
-                'Content-Disposition: attachment; filename="' . $sFileName . '"',
-                //'Content-Length: ' . filesize($sFilePath)
-            );
-            //
-            return json_decode($this->curlRequest($sServiceUrl, 'post', file_get_contents($sFilePath), $aRequestHeaders));
+            if ($this->sToken !== false) {
+                // Nom du fichier.
+                if (empty($sFileName))
+                    $sFileName = pathinfo($sFilePath, PATHINFO_BASENAME);
+                // Type MIME du fichier.
+                //$finfo = finfo_open(FILEINFO_MIME_TYPE);            
+                // Crée un objet CURLFile.
+                //$oCfile = new CURLFile($sFilePath, finfo_file($finfo, $sFilePath), $sFileName);
+                //finfo_close($finfo);
+                // Entêtes de la requête Curl.
+                $aRequestHeaders = array(
+                    'Content-Type: application/octet-stream',
+                    'Content-Disposition: attachment; filename="' . $sFileName . '"',
+                    //'Content-Length: ' . filesize($sFilePath)
+                );
+                //
+                $sRequestResponse = $this->curlRequest($sServiceUrl, 'post', file_get_contents($sFilePath), $aRequestHeaders);
+                if ($this->aLastCurlRequestInfo['http_code'] >= 400) {
+                    $oRequestResponse = json_decode($sRequestResponse);
+                    if (is_object($oRequestResponse) && !empty($oRequestResponse->message))
+                        $this->writeToErrorLog($oRequestResponse->message);
+                    else
+                        $this->writeToErrorLog($sRequestResponse);
+                    return false;
+                }
+                else
+                    return json_decode($sRequestResponse);
+            }
+            else
+                return false;
+        }
+        else {
+            $this->writeToErrorLog('The file does not exist (' . $sFilePath . ')');
+            return false;
         }
     }
     
@@ -184,32 +245,94 @@ Class FmeServer {
     function uploadResourceFile($sFilePath, $sResource, $sPath, $bCreateDirectories = false, $bOverwrite = false) {
         // Demande de token.
         $this->getToken();
-        // Url du service de ressources.
-        $sUrl = $this->sUrl . '/fmerest/v3/resources/connections/' . $sResource . '/filesys/' . $sPath;
-        $sUrl .= '?createDirectories=' . var_export($bCreateDirectories, true) . '&overwrite=' . var_export($bOverwrite, true);
-        return $this->uploadFile($sUrl, $sFilePath);
+        if ($this->sToken !== false) {
+            // Url du service de ressources.
+            $sUrl = $this->sUrl . '/fmerest/v3/resources/connections/' . $sResource . '/filesys/' . $sPath;
+            $sUrl .= '?createDirectories=' . var_export($bCreateDirectories, true) . '&overwrite=' . var_export($bOverwrite, true);
+            return $this->uploadFile($sUrl, $sFilePath);
+        }
+        else
+            return false;
     }
     
     /**
-     * Upload a file to the resource connection
+     * Publish a file to a repository
      * @param {string} $sFilePath Path of the file to upload.
      * @param {string} $sRepository Name of the repository.
      * @param {boolean} $bOverwrite Overwrite the file if it already exists.
+     * @param {string} $sRepositoryFileName File name in the repository.
      * @return Request result
      */
-    function uploadWorkspaceFile($sFilePath, $sRepository, $bOverwrite = false) {
+    function uploadWorkspaceFile($sFilePath, $sRepository, $bOverwrite = false, $sRepositoryFileName = '') {
         // Demande de token.
         $this->getToken();
-        // Supprime le fichier s'il existe déja.
-        if ($bOverwrite) {
+        if ($this->sToken !== false) {
+            // Vérification de l'existence du fichier.
+            $bUploadFile = true;
+            if (!empty($sRepositoryFileName))
+                $sSourceFileName = $sRepositoryFileName;
+            else
+                $sSourceFileName = pathinfo($sFilePath, PATHINFO_BASENAME);
+            $this->serviceRequest('repositories/' . $sRepository . '/items/' . $sSourceFileName, 'get', null, false);
+            // Supprime le fichier s'il existe déja.
+            if ($this->aLastCurlRequestInfo['http_code'] == 200) {
+                if ($bOverwrite) {
+                    if ($this->serviceRequest('repositories/' . $sRepository . '/items/' . $sSourceFileName, 'delete') === false)
+                        return false;
+                }
+                else
+                    $bUploadFile = false;
+            }
+            //Upload du fichier.
+            if ($bUploadFile) {
+                $sUrl = $this->sUrl . '/fmerest/v3/repositories/' . $sRepository . '/items';
+                return $this->uploadFile($sUrl, $sFilePath, $sRepositoryFileName);
+            }
+        }
+        else
+            return false;
+    }
+    
+    /**
+     * Upload a resource to a repository item
+     * @param {string} $sFilePath Path of the file to upload.
+     * @param {string} $sRepository Name of the repository.
+     * @param {string} $sItem Name of the repository item.
+     * @param {boolean} $bOverwrite Overwrite the file if it already exists.
+     * @return Request result
+     */
+    function uploadWorkspaceResourceFile($sFilePath, $sRepository, $sItem, $bOverwrite = false) {
+        // Demande de token.
+        $this->getToken();
+        if ($this->sToken !== false) {
+            $bUploadFile = true;
             $sFileName = pathinfo($sFilePath, PATHINFO_BASENAME);
-            $this->serviceRequest('repositories/' . $sRepository . '/items/' . $sFileName);
-            if ($this->aLastCurlRequestInfo['http_code'] == 200)
-                $this->serviceRequest('repositories/' . $sRepository . '/items/' . $sFileName, 'delete');
+            // Télécharge la liste des ressources complémentaires du projet.
+            $aResources = $this->serviceRequest('repositories/' . $sRepository . '/items/' . $sItem . '/resources', 'get');
+            if ($aResources !== false) {
+                // Vérification de l'existence du fichier.
+                foreach ($aResources as $oResource) {
+                    // Supprime le fichier s'il existe déja.
+                    if ($oResource->name == $sFileName) {
+                        if ($bOverwrite) {
+                            if ($this->serviceRequest('repositories/' . $sRepository . '/items/' . $sItem . '/resources/' . $sFileName, 'delete') === false)
+                                return false;
+                        }
+                        else
+                            $bUploadFile = false;
+                    }
+                }
+            }
+            else
+                return false;
+            // Upload du fichier.
+            if ($bUploadFile) {
+                $sUrl = $this->sUrl . '/fmerest/v3/repositories/' . $sRepository . '/items/' . $sItem . '/resources';
+                return $this->uploadFile($sUrl, $sFilePath);
+            }
         }
-        // Url du service vers le dépôt spécifié.
-        $sUrl = $this->sUrl . '/fmerest/v3/repositories/' . $sRepository . '/items';
-        return $this->uploadFile($sUrl, $sFilePath);
+        else
+            return false;
     }
     
     /**
@@ -221,10 +344,25 @@ Class FmeServer {
     function getWorkspaceParams($sRepository, $sWorkspace) {
         // Demande de token.
         $this->getToken();
-        // Url du service vers le traitement (fichier.fmw) spécifié.
-        $sUrl = $this->sUrl . '/fmerest/v3/repositories/' . $sRepository . '/items/' . $sWorkspace;
-        // Transfert cURL.
-        return json_decode($this->curlRequest($sUrl, 'get'));
+        if ($this->sToken !== false) {
+            // Url du service vers le traitement (fichier.fmw) spécifié.
+            $sUrl = $this->sUrl . '/fmerest/v3/repositories/' . $sRepository . '/items/' . $sWorkspace;
+            // Transfert cURL.
+            $sRequestResponse = $this->curlRequest($sUrl, 'get');
+            if ($this->aLastCurlRequestInfo['http_code'] >= 400) {
+                $oRequestResponse = json_decode($sRequestResponse);
+                if (is_object($oRequestResponse) && !empty($oRequestResponse->message))
+                    $this->writeToErrorLog($oRequestResponse->message);
+                else
+                    $this->writeToErrorLog($sRequestResponse);
+                return false;
+            }
+            else
+                return json_decode($sRequestResponse);
+            
+        }
+        else
+            return false;
     }
     
     /**
@@ -238,15 +376,33 @@ Class FmeServer {
     function submitJob($sRepository, $sWorkspace, $aParams, $bAsync = false) {
         // Demande de token.
         $this->getToken();
-        // Url du service vers le traitement (fichier.fmw) spécifié.
-        if ($bAsync)
-            $sUrl = $this->sUrl . '/fmerest/v3/transformations/submit/' . $sRepository . '/' . $sWorkspace;
+        if ($this->sToken !== false) {
+            // Url du service vers le traitement (fichier.fmw) spécifié.
+            if ($bAsync)
+                $sUrl = $this->sUrl . '/fmerest/v3/transformations/submit/' . $sRepository . '/' . $sWorkspace;
+            else
+                $sUrl = $this->sUrl . '/fmerest/v3/transformations/transact/' . $sRepository . '/' . $sWorkspace;
+            // Données au format json.
+            $aHeaders = array('Content-Type: application/json');
+            // Transfert cURL.
+            $sRequestResponse = $this->curlRequest($sUrl, 'post', json_encode($aParams), $aHeaders);
+            $oRequestResponse = json_decode($sRequestResponse);
+            if ($this->aLastCurlRequestInfo['http_code'] >= 400) {
+                if (is_object($oRequestResponse)) {
+                    if (empty($oRequestResponse->id)) {
+                        $this->writeToErrorLog($oRequestResponse->message);
+                        return false;
+                    }
+                    else
+                        $this->writeToErrorLog($oRequestResponse->statusMessage);
+                }
+                else
+                    $this->writeToErrorLog($sRequestResponse);
+            }
+            return $oRequestResponse;
+        }
         else
-            $sUrl = $this->sUrl . '/fmerest/v3/transformations/transact/' . $sRepository . '/' . $sWorkspace;
-        // Données au format json.
-        $aHeaders = array('Content-Type: application/json');
-        // Transfert cURL.
-        return json_decode($this->curlRequest($sUrl, 'post', json_encode($aParams), $aHeaders));
+            return false;
     }
     
     /**
@@ -259,23 +415,37 @@ Class FmeServer {
     function downloadResourceFile($sResource, $sPath, $sFilePath = null) {
         // Demande de token.
         $this->getToken();
-        // Url du service vers le traitement (fichier.fmw) spécifié.
-        $sUrl = $this->sUrl . '/fmerest/v3/resources/connections/' . $sResource . '/filesys/' . $sPath;
-        // Obligatoire pour récupérer le contenu du fichier.
-        $aHeaders = array('Accept: application/octet-stream');
-        // Données de la requête.
-        /*
-        $aRequestData = array (
-            'accept' => 'contents',
-            'disposition' => 'inline'
-        );
-        */
-        // Transfert cURL.
-        $sFileContent = $this->curlRequest($sUrl, 'get', null, $aHeaders);
-        if (!empty($sFilePath))
-            file_put_contents($sFilePath, $sFileContent);
+        if ($this->sToken !== false) {
+            // Url du service vers le traitement (fichier.fmw) spécifié.
+            $sUrl = $this->sUrl . '/fmerest/v3/resources/connections/' . $sResource . '/filesys/' . $sPath;
+            // Obligatoire pour récupérer le contenu du fichier.
+            $aHeaders = array('Accept: application/octet-stream');
+            // Données de la requête.
+            /*
+            $aRequestData = array (
+                'accept' => 'contents',
+                'disposition' => 'inline'
+            );
+            */
+            // Transfert cURL.
+            $sRequestResponse = $this->curlRequest($sUrl, 'get', null, $aHeaders);
+            if ($this->aLastCurlRequestInfo['http_code'] >= 400) {
+                $oRequestResponse = json_decode($sRequestResponse);
+                if (is_object($oRequestResponse) && !empty($oRequestResponse->message))
+                    $this->writeToErrorLog($oRequestResponse->message);
+                else
+                    $this->writeToErrorLog($sRequestResponse);
+                return false;
+            }
+            else {
+                if (!empty($sFilePath))
+                    file_put_contents($sFilePath, $sRequestResponse);
+                else
+                    return $sRequestResponse;
+            }
+        }
         else
-            return $sFileContent;
+            return false;
     }
     
     /**
@@ -286,16 +456,30 @@ Class FmeServer {
     function getJobLog($sJobId, $sFilePath = '') {
         // Demande de token.
         $this->getToken();
-        // Url du service vers le traitement (fichier.fmw) spécifié.
-        $sUrl = $this->sUrl . '/fmerest/v3/transformations/jobs/id/' . $sJobId . '/log';
-        // Obligatoire pour récupérer le contenu du fichier.
-        $aHeaders = array('Accept: text/plain');
-        // Transfert cURL.
-        $sFileContent = $this->curlRequest($sUrl, 'get', null, $aHeaders);
-        if (!empty($sFilePath))
-            file_put_contents($sFilePath, $sFileContent);
+        if ($this->sToken !== false) {
+            // Url du service vers le traitement (fichier.fmw) spécifié.
+            $sUrl = $this->sUrl . '/fmerest/v3/transformations/jobs/id/' . $sJobId . '/log';
+            // Obligatoire pour récupérer le contenu du fichier.
+            $aHeaders = array('Accept: text/plain');
+            // Transfert cURL.
+            $sRequestResponse = $this->curlRequest($sUrl, 'get', null, $aHeaders);
+            if ($this->aLastCurlRequestInfo['http_code'] >= 400) {
+                $oRequestResponse = json_decode($sRequestResponse);
+                if (is_object($oRequestResponse) && !empty($oRequestResponse->message))
+                    $this->writeToErrorLog($oRequestResponse->message);
+                else
+                    $this->writeToErrorLog($sRequestResponse);
+                return false;
+            }
+            else {
+                if (!empty($sFilePath))
+                    file_put_contents($sFilePath, $sRequestResponse);
+                else
+                    return $sRequestResponse;
+            }
+        }
         else
-            return $sFileContent;
+            return false;
     }
     
     /**
@@ -307,16 +491,20 @@ Class FmeServer {
     function createRepository($sRepository, $sDescription) {
         // Demande de token.
         $this->getToken();
-        // Crée le dépot s'il n'existe pas déja.
-        $aRequestResult = $this->serviceRequest('repositories/' . $sRepository);
-        if ($this->aLastCurlRequestInfo['http_code'] == 404) {
-            $aRequestData = array (
-                'name' => $sRepository,
-                'description' => $sDescription
-            );
-            $aRequestResult = $this->serviceRequest('repositories', 'post', $aRequestData);
+        if ($this->sToken !== false) {
+            // Crée le dépot s'il n'existe pas déja.
+            $aRequestResult = $this->serviceRequest('repositories/' . $sRepository, 'get', null, false);
+            if ($this->aLastCurlRequestInfo['http_code'] == 404) {
+                $aRequestData = array (
+                    'name' => $sRepository,
+                    'description' => $sDescription
+                );
+                $aRequestResult = $this->serviceRequest('repositories', 'post', $aRequestData);
+            }
+            return $aRequestResult;
         }
-        return $aRequestResult;
+        else
+            return false;
     }
     
     /**
@@ -330,18 +518,22 @@ Class FmeServer {
     function uploadResourceFileFromS3($aS3Params, $sRepository, $sResource, $sPath) {
         // Demande de token.
         $this->getToken();
-        //
-        $aJobParams = array(
-            'publishedParameters' => array(
-                array('name' => 'access_key_id', 'value' => $aS3Params['access_key_id']),
-                array('name' => 'secret_access_key', 'value' => $aS3Params['secret_access_key']),
-                array('name' => 'bucket_name', 'value' => $aS3Params['bucket_name']),
-                array('name' => 'object_key', 'value' => $aS3Params['object_key']),
-                array('name' => 'target_file', 'value' => '$(' . $sResource . ')/' . $sPath . '/' . pathinfo($aS3Params['object_key'], PATHINFO_BASENAME))
-            )
-        );
-        $oJobResult = $this->submitJob($sRepository, 'S3Downloader.fmw', $aJobParams);
-        return $oJobResult;
+        if ($this->sToken !== false) {
+            //
+            $aJobParams = array(
+                'publishedParameters' => array(
+                    array('name' => 'access_key_id', 'value' => $aS3Params['access_key_id']),
+                    array('name' => 'secret_access_key', 'value' => $aS3Params['secret_access_key']),
+                    array('name' => 'bucket_name', 'value' => $aS3Params['bucket_name']),
+                    array('name' => 'object_key', 'value' => $aS3Params['object_key']),
+                    array('name' => 'target_file', 'value' => '$(' . $sResource . ')/' . $sPath . '/' . pathinfo($aS3Params['object_key'], PATHINFO_BASENAME))
+                )
+            );
+            $oJobResult = $this->submitJob($sRepository, 'S3Downloader.fmw', $aJobParams);
+            return $oJobResult;
+        }
+        else
+            return false;
     }
     
     /**
@@ -354,15 +546,19 @@ Class FmeServer {
     function createResourceConnectionDirectory($sResource, $sPath, $DirectoryName) {
         // Demande de token.
         $this->getToken();
-        // Crée le répertoire s'il n'existe pas déja.
-        $aRequestResult = $this->serviceRequest('resources/connections/' . $sResource . '/filesys/' . $sPath . '/' . $DirectoryName);
-        if ($this->aLastCurlRequestInfo['http_code'] == 404) {
-            $aRequestData = array (
-                'directoryname' => $DirectoryName
-            );
-            $aRequestResult = $this->serviceRequest('resources/connections/' . $sResource . '/filesys/' . $sPath, 'post', $aRequestData);
+        if ($this->sToken !== false) {
+            // Crée le répertoire s'il n'existe pas déja.
+            $aRequestResult = $this->serviceRequest('resources/connections/' . $sResource . '/filesys/' . $sPath . '/' . $DirectoryName, 'get', null, false);
+            if ($this->aLastCurlRequestInfo['http_code'] == 404) {
+                $aRequestData = array (
+                    'directoryname' => $DirectoryName
+                );
+                $aRequestResult = $this->serviceRequest('resources/connections/' . $sResource . '/filesys/' . $sPath, 'post', $aRequestData);
+            }
+            return $aRequestResult;
         }
-        return $aRequestResult;
+        else
+            return false;
     }
     
     /**
@@ -372,10 +568,24 @@ Class FmeServer {
     function getInfo() {
         // Demande de token.
         $this->getToken();
-        // Url du web service info.
-        $sUrl = $this->sUrl . '/fmerest/v3/info';
-        // Transfert cURL.
-        return json_decode($this->curlRequest($sUrl, 'get'));
+        if ($this->sToken !== false) {
+            // Url du web service info.
+            $sUrl = $this->sUrl . '/fmerest/v3/info';
+            // Transfert cURL.
+            $sRequestResponse = $this->curlRequest($sUrl, 'get');
+            if ($this->aLastCurlRequestInfo['http_code'] >= 400) {
+                $oRequestResponse = json_decode($sRequestResponse);
+                if (is_object($oRequestResponse) && !empty($oRequestResponse->message))
+                    $this->writeToErrorLog($oRequestResponse->message);
+                else
+                    $this->writeToErrorLog($sRequestResponse);
+                return false;
+            }
+            else
+                return json_decode($sRequestResponse);
+        }
+        else
+            return false;
     }
     
     /**
@@ -385,10 +595,106 @@ Class FmeServer {
     function getLicenceStatus() {
         // Demande de token.
         $this->getToken();
-        // Url du web service info.
-        $sUrl = $this->sUrl . '/fmerest/v3/licensing/license/status';
-        // Transfert cURL.
-        return json_decode($this->curlRequest($sUrl, 'get'));
+        if ($this->sToken !== false) {
+            // Url du web service info.
+            $sUrl = $this->sUrl . '/fmerest/v3/licensing/license/status';
+            // Transfert cURL.
+            $sRequestResponse = $this->curlRequest($sUrl, 'get');
+            if ($this->aLastCurlRequestInfo['http_code'] >= 400) {
+                $this->writeToErrorLog($sRequestResponse);
+                return false;
+            }
+            else
+                return json_decode($sRequestResponse);
+        }
+        else
+            return false;
+    }
+    
+    /**
+     * Write a message to the error log file.
+     * @param {string} $sMessage Message to write to the log file.
+     */
+    function writeToErrorLog($sMessage) {
+        $aDebugBacktrace = debug_backtrace();
+        $sLogMessage = '|ERROR|' . $aDebugBacktrace[1]['class'] . '::' . $aDebugBacktrace[1]['function'] . '| ' . $sMessage;
+        if (empty($this->sLogFilePath))
+            writeToErrorLog($sLogMessage);
+        else
+            writeToLog($sLogMessage, $this->sLogFilePath);
+    }
+    
+    /**
+     * Delete a job.
+     * @param {number} $iJobId The id of the job.
+     * @return Request result
+     */
+    function deleteJob($iJobId) {
+        // Demande de token.
+        $this->getToken();
+        if ($this->sToken !== false) {
+            // Annule une demande en attente ou arrête une demande en cours.
+            if ($this->stopJob($iJobId) !== false) {
+                // Supprime définitivement la demande sur Fme Server.
+                if ($this->serviceRequest('transformations/jobs/completed/' . $iJobId, 'delete') !== false)
+                    writeToLog(self::INFO_FME_SERVER_JOB_REMOVED . " (job id $iJobId).", $this->sLogFilePath);
+                else
+                    return false;
+            }
+        }
+        else
+            return false;
+    }
+    
+    /**
+     * Cancel a queued job.
+     * @param {number} $iJobId The id of the job.
+     * @return Request result
+     */
+    function cancelJob($iJobId) {
+        // Demande de token.
+        $this->getToken();
+        if ($this->sToken !== false) {
+            // Annule le traitement.
+            if ($this->serviceRequest('transformations/jobs/queued/' . $iJobId, 'delete') !== false)
+                writeToLog(self::INFO_FME_SERVER_JOB_CANCELED . " (job id $iJobId).", $this->sLogFilePath);
+            else
+                return false;
+        }
+        else
+            return false;
+    }
+    
+    /**
+     * Stop a queued or running job.
+     * @param {number} $iJobId The id of the job.
+     * @return Request result
+     */
+    function stopJob($iJobId) {
+        // Demande de token.
+        $this->getToken();
+        if ($this->sToken !== false) {
+            $oJobLog = $this->serviceRequest('transformations/jobs/id/' . $iJobId);
+            if ($oJobLog !== false) {
+                // Annule une demande en attente ou arrête une demande en cours.
+                $aQueuedStatus = array('SUBMITTED', 'QUEUED', 'DELAYED', 'PAUSED');
+                $aRunningStatus = array('IN_PROCESS', 'PULLED');
+                $aStoppedStatus = array('DELETED', 'ABORTED', 'FME_FAILURE', 'JOB_FAILURE', 'SUCCESS');
+                if (in_array($oJobLog->status, $aQueuedStatus))
+                    $this->cancelJob($iJobId);
+                else if (!in_array($oJobLog->status, $aStoppedStatus)){
+                    // Annule le traitement.
+                    if ($this->serviceRequest('transformations/jobs/running/' . $iJobId, 'delete') !== false)
+                        writeToLog(self::INFO_FME_SERVER_JOB_STOPPED . " (job id $iJobId).", $this->sLogFilePath);
+                    else
+                        return false;
+                }
+            }
+            else
+                return false;
+        }
+        else
+            return false;
     }
 }
 ?>
\ No newline at end of file
diff --git a/web_service/class/gtf_lib/gtf_object/Category.class.inc b/web_service/class/gtf_lib/gtf_object/Category.class.inc
old mode 100755
new mode 100644
diff --git a/web_service/class/gtf_lib/gtf_object/FmeEngine.class.inc b/web_service/class/gtf_lib/gtf_object/FmeEngine.class.inc
old mode 100755
new mode 100644
diff --git a/web_service/class/gtf_lib/gtf_object/GtfEngine.class.inc b/web_service/class/gtf_lib/gtf_object/GtfEngine.class.inc
old mode 100755
new mode 100644
diff --git a/web_service/class/gtf_lib/gtf_object/Order.class.inc b/web_service/class/gtf_lib/gtf_object/Order.class.inc
old mode 100755
new mode 100644
diff --git a/web_service/class/gtf_lib/gtf_object/User.class.inc b/web_service/class/gtf_lib/gtf_object/User.class.inc
old mode 100755
new mode 100644
diff --git a/web_service/class/gtf_lib/gtf_object/Workspace.class.inc b/web_service/class/gtf_lib/gtf_object/Workspace.class.inc
old mode 100755
new mode 100644
diff --git a/web_service/class/gtf_lib/imap_reader/ImapConnection.php b/web_service/class/gtf_lib/imap_reader/ImapConnection.php
old mode 100644
new mode 100755
diff --git a/web_service/class/gtf_lib/imap_reader/MailBox.php b/web_service/class/gtf_lib/imap_reader/MailBox.php
old mode 100644
new mode 100755
diff --git a/web_service/class/gtf_lib/imap_reader/MailStruct.php b/web_service/class/gtf_lib/imap_reader/MailStruct.php
old mode 100644
new mode 100755
index 5f79b22e..b45ce29d
--- a/web_service/class/gtf_lib/imap_reader/MailStruct.php
+++ b/web_service/class/gtf_lib/imap_reader/MailStruct.php
@@ -100,13 +100,20 @@ class MailStruct {
         foreach ($aPart as $oPart) {
            if ($oPart["part_object"]->encoding == 3 || $oPart["part_object"]->encoding == 4) {
                 $sMimeType = $this->oConnection->getMimeType($oPart["part_object"]);
+
+                //$this->sBody = $this->oConnection->getPart($this->iUid, $oPart["part_object"]->encoding, $oPart["part_number"]);
+
                if ($sMimeType === "TEXT/HTML") {
-                   $this->sBody = $this->oConnection->getPart($this->iUid, $oPart["part_object"]->encoding, $oPart["part_number"]);
+                    //error_log(print_r($oPart, true));
+                    $this->sBody = $this->convertToUtf8($this->oConnection->getPart($this->iUid, $oPart["part_object"]->encoding, $oPart["part_number"]));
                    $this->bIsHTML = true;
                } else if($sMimeType === "TEXT/PLAIN"){
-                    $this->sBody = $this->oConnection->getPart($this->iUid, $oPart["part_object"]->encoding, $oPart["part_number"]);
+                    //error_log(print_r($oPart, true));
+                    $this->sBody = $this->convertToUtf8($this->oConnection->getPart($this->iUid, $oPart["part_object"]->encoding, $oPart["part_number"]));
                     $this->bIsHTML = false;
                }
+               //error_log($this->sBody);
+               //error_log(mb_detect_encoding($this->sBody));
             } 
         }
     }
diff --git a/web_service/class/gtf_lib/phpUtility.inc b/web_service/class/gtf_lib/phpUtility.inc
index 13f6f5ce..e44481c9 100755
--- a/web_service/class/gtf_lib/phpUtility.inc
+++ b/web_service/class/gtf_lib/phpUtility.inc
@@ -292,4 +292,39 @@ function getFmeLicence($fmepath)
 function array_iunique($aArray){
     return array_intersect_key($aArray, array_unique(array_map("StrToLower",$aArray)));
 }
+
+/**
+ * Generate a GTF instance id.
+ * @return GTF instance id
+ */
+function generateGtfInstanceId() {
+    $aOutput = array();
+    $iReturnStatus = 1;
+    if (strtolower(substr(PHP_OS, 0, 3)) == 'win') {
+        // Paramètres à concaténer pour un identifiant unique par machine.
+        $aCommands = array(
+            'NICCONFIG',    // cartes réseaux (adresses MAC)
+            'CPU',  // modèle, vitesse, id...
+            'DISKDRIVE',    // N° de série...
+            'MEMORYCHIP',
+            'CDROM',    // Lecteur DVD...
+            'path win32_VideoController',   // Carte vidéo
+            'IDECONTROLLER',
+            'SCSICONTROLLER',
+            'DESKTOPMONITOR',
+            'LOGON',
+            'NETLOGIN'
+        );
+        $sCommandLine = 'wmic '. implode(' & wmic ', $aCommands);
+        exec($sCommandLine, $aOutput, $iReturnStatus);
+    }
+    else if (strtolower(substr(PHP_OS, 0, 5)) == 'linux') {
+        $aLinuxCommand = array('lscpu', 'lspci', 'df', 'free', 'ip a', 'cat /var/lib/dbus/machine-id'); // , 'sudo cat /sys/class/dmi/id/product_uuid'
+        foreach ($aLinuxCommand as $sCommand) {
+            exec($sCommand, $aOutput, $iReturnStatus);
+        }
+        $aOutput['ses_Login'] = $_SESSION['ses_Login'];
+    }
+    return 'GTF_' . hash_hmac('sha256', implode(chr(20), $aOutput), uniqid('', true));
+}
 ?>
\ No newline at end of file
diff --git a/web_service/conf/properties.inc b/web_service/conf/properties.inc
old mode 100755
new mode 100644
index e24cac58..ff978e12
--- a/web_service/conf/properties.inc
+++ b/web_service/conf/properties.inc
@@ -6,4 +6,6 @@ $properties['heure_creuse_min'] = '19:30';
 $properties['heure_creuse_max'] = '08:30';
 $properties['nbr_order_max'] = 10;
 $properties['max_attempt'] = 2;
+$properties['connectionStringExternalIp'] = '52.47.201.61';
+$properties['connectionStringExternalPort'] = 5432;
 ?>
\ No newline at end of file
diff --git a/web_service/conf/properties_server.inc b/web_service/conf/properties_server.inc
index 87791cf6..6ff1a41e 100755
--- a/web_service/conf/properties_server.inc
+++ b/web_service/conf/properties_server.inc
@@ -3,4 +3,5 @@ $properties['schema_gtf'] = 's_gtf';
 $properties['gtf_doc_alias'] = 'gtf_doc';
 $properties['login_scheduler'] = 'u_scheduler';
 $properties['password_scheduler'] = '[PASSWORD_SCHEDULER]';
+$properties['application_name'] = 'gtf[ENV]';
 ?>
\ No newline at end of file
diff --git a/web_service/conf/selected_properties.inc b/web_service/conf/selected_properties.inc
old mode 100755
new mode 100644
index 9de194fd..8f07f5c1
--- a/web_service/conf/selected_properties.inc
+++ b/web_service/conf/selected_properties.inc
@@ -15,7 +15,12 @@ $aAdminFields = Array(
     'pycron_dir',
     'login_scheduler',
     'password_scheduler',
-    'gtf_doc_alias'
+    'gtf_doc_alias',
+    'application_name',
+    'fme_cloud_api_url',
+    'gtf_instance_id',
+    'connectionStringExternalIp',
+    'connectionStringExternalPort'
 );
 $aUserFields = Array(
     'schema_gtf',
@@ -32,9 +37,14 @@ $aUserFields = Array(
     'pycron_dir',
     'login_scheduler',
     'password_scheduler',
-    'gtf_doc_alias'
+    'gtf_doc_alias',
+    'application_name',
+    'fme_cloud_api_url',
+    'gtf_instance_id',
+    'connectionStringExternalIp',
+    'connectionStringExternalPort'
 );
 
 $properties['aAdminFields'] = array_merge($properties['aAdminFields'], $aAdminFields);
 $properties['aUserFields'] = array_merge($properties['aUserFields'], $aUserFields);
-?>
\ No newline at end of file
+?>
diff --git a/web_service/sql/maj.sql b/web_service/sql/maj.sql
old mode 100755
new mode 100644
index f24bccb7..1ed5dac1
--- a/web_service/sql/maj.sql
+++ b/web_service/sql/maj.sql
@@ -71,4 +71,10 @@ INSERT INTO s_vitis.vm_table_field (table_field_id, name, sortable, resizeable,
 -- Libellé du champ "type" de moteur FME.
 UPDATE s_vitis.vm_tab SET event = 'loadList(null, {"lang": ""})' WHERE name ='gtf_fme_engine';
 -- 
-UPDATE s_vitis.vm_table_field SET width = 200 WHERE label_id = 'gtf_128';
\ No newline at end of file
+UPDATE s_vitis.vm_table_field SET width = 200 WHERE label_id = 'gtf_128';
+
+-- Anthony le 18/09/2018 14:43
+ALTER TABLE s_gtf.fme_engine ADD COLUMN useexternaldbconnection boolean DEFAULT FALSE;
+CREATE OR REPLACE VIEW s_gtf.v_fme_engine AS SELECT fme_engine.fme_engine_id, fme_engine.name, fme_engine.server_id, fme_engine.local_path, server.hostname AS server_name, fme_engine.server_url, fme_engine.login, fme_engine.password, fme_engine.fme_engine_type_id, fme_engine.s3_access_key_id, fme_engine.s3_secret_access_key, fme_engine.fme_cloud_api_token, v_fme_engine_type.fme_engine_type_label, v_fme_engine_type.lang, fme_engine.s3_region, fme_engine.iam_access_key_id, fme_engine.iam_secret_access_key, fme_engine.fme_server_instance_name, fme_engine.fme_server_s3_bucket, useexternaldbconnection FROM s_gtf.fme_engine LEFT JOIN s_gtf.server ON fme_engine.server_id = server.server_id LEFT JOIN s_gtf.v_fme_engine_type ON fme_engine.fme_engine_type_id::text = v_fme_engine_type.fme_engine_type_id::text;
+CREATE OR REPLACE RULE insert_v_fme_engine AS ON INSERT TO s_gtf.v_fme_engine DO INSTEAD  INSERT INTO s_gtf.fme_engine (fme_engine_id, name, server_id, local_path, server_url, login, password, fme_engine_type_id, s3_access_key_id, s3_secret_access_key, fme_cloud_api_token, s3_region, iam_access_key_id, iam_secret_access_key, fme_server_instance_name, fme_server_s3_bucket, useexternaldbconnection) VALUES (new.fme_engine_id, new.name, new.server_id, new.local_path, new.server_url, new.login, new.password, new.fme_engine_type_id, new.s3_access_key_id, new.s3_secret_access_key, new.fme_cloud_api_token, new.s3_region, new.iam_access_key_id, new.iam_secret_access_key, new.fme_server_instance_name, new.fme_server_s3_bucket, new.useexternaldbconnection);
+CREATE OR REPLACE RULE update_v_fme_engine AS ON UPDATE TO s_gtf.v_fme_engine DO INSTEAD  UPDATE s_gtf.fme_engine SET fme_engine_id = new.fme_engine_id, name = new.name, server_id = new.server_id, local_path = new.local_path, server_url = new.server_url, login = new.login, password = new.password, fme_engine_type_id = new.fme_engine_type_id, s3_access_key_id = new.s3_access_key_id, s3_secret_access_key = new.s3_secret_access_key, fme_cloud_api_token = new.fme_cloud_api_token, s3_region = new.s3_region, iam_access_key_id = new.iam_access_key_id, iam_secret_access_key = new.iam_secret_access_key, fme_server_instance_name = new.fme_server_instance_name, fme_server_s3_bucket = new.fme_server_s3_bucket, useexternaldbconnection = new.useexternaldbconnection WHERE fme_engine.fme_engine_id = new.fme_engine_id;
diff --git a/web_service/sql/sqlQueries.xml b/web_service/sql/sqlQueries.xml
old mode 100755
new mode 100644
index e23e9532..86530ce4
--- a/web_service/sql/sqlQueries.xml
+++ b/web_service/sql/sqlQueries.xml
@@ -1626,13 +1626,13 @@
                             UPDATE s_vitis.vm_tab SET event='loadList("showSupervisionRecap()");' WHERE label_id='gtf_60' AND "name"='gtf_order';
                             UPDATE s_vitis.vm_table_field SET template = '<div data-app-duration-calculator="row.entity[col.field]" style="height: 100%; padding: 5px;"></div>' WHERE name = 'length_sec' AND ressource_id = 'gtf/orders';
                             CREATE OR REPLACE VIEW s_gtf.v_order_fast AS SELECT "order".order_id, "order".priority_id, "order".workspace_id, workspace.key AS workspace_key, workspace.name AS label_name, "order".order_status_id, "order".user_id, "user".login, "order".period_id, period.name AS order_period_libelle, "order".wk_params, "order".result_url, "order".order_date, "order".log_url, "order".execution_date, "order".attempt, "order".email_notifications, "order".email_option_id, "order".deleted, "order".gtf_engine_id, "order".length_sec, gtf_engine.name FROM s_gtf."order" LEFT JOIN s_gtf.workspace ON "order".workspace_id = workspace.workspace_id LEFT JOIN s_gtf.period ON "order".period_id = period.period_id LEFT JOIN s_vitis."user" ON "user".user_id = "order".user_id LEFT JOIN s_gtf.rt_priority ON "order".priority_id = rt_priority.priority_id LEFT JOIN s_gtf.rt_email_option ON "order".email_option_id = rt_email_option.email_option_id LEFT JOIN s_gtf.rt_order_status ON "order".order_status_id = rt_order_status.order_status_id LEFT JOIN s_gtf.gtf_engine ON "order".gtf_engine_id = gtf_engine.gtf_engine_id WHERE "order".period_id IS NULL;
-							ALTER TABLE s_gtf.v_order_fast OWNER TO u_vitis;
-							GRANT SELECT ON TABLE s_gtf.v_order_fast TO gtf_user;
-							GRANT ALL ON TABLE s_gtf.v_order_fast TO u_vitis;
-							GRANT SELECT ON TABLE s_gtf.v_order_fast TO gtf_author;
-							GRANT ALL ON TABLE s_gtf.v_order_fast TO gtf_admin;
-							CREATE OR REPLACE VIEW s_gtf.v_supervision_status AS SELECT count(v_order_fast.order_id) AS nb_order_id, v_order_fast.order_status_id AS filter, 'order'::text AS table_name FROM s_gtf.v_order_fast GROUP BY v_order_fast.order_status_id UNION SELECT count(v_subscription.order_id) AS nb_order_id, CASE WHEN v_subscription.enabled IS TRUE THEN 1 ELSE 0 END AS filter, 'subscription'::text AS table_name FROM s_gtf.v_subscription WHERE v_subscription.lang::text = 'fr'::text GROUP BY v_subscription.enabled UNION SELECT count(v_survey.order_id) AS nb_order_id, CASE WHEN v_survey.enabled IS TRUE THEN 1 ELSE 0 END AS filter, 'survey'::text AS table_name FROM s_gtf.v_survey WHERE v_survey.lang::text = 'fr'::text GROUP BY v_survey.enabled;
-							CREATE OR REPLACE VIEW s_gtf.v_workspace AS SELECT workspace.workspace_id, workspace.name, workspace.owner, workspace.creation_date, workspace.description, workspace.subscription, workspace.fmw_file, workspace.category_id, workspace.success_action_id, workspace.failed_action_id, workspace.survey, workspace.form_type, workspace.legal_terms_conditions, workspace.last_save_date, workspace.last_save_build, workspace.file_encoding, workspace.title, workspace.requirements, workspace.history, workspace.usage, workspace.key, workspace.email_template_id, workspace.locked, workspace.tag, "user".login, category.name AS category_name, CASE WHEN t.nb_demandes IS NULL THEN 0::bigint ELSE t.nb_demandes END AS nb_demande, email_template.name AS email_template FROM s_gtf.workspace LEFT JOIN s_vitis."user" ON workspace.owner = "user".user_id LEFT JOIN s_gtf.category ON workspace.category_id = category.category_id LEFT JOIN s_gtf.email_template ON workspace.email_template_id = email_template.email_template_id LEFT JOIN (SELECT count(*) AS nb_demandes, v_order_fast.workspace_id FROM s_gtf.v_order_fast GROUP BY v_order_fast.workspace_id) t ON workspace.workspace_id = t.workspace_id;
+                            ALTER TABLE s_gtf.v_order_fast OWNER TO u_vitis;
+                            GRANT SELECT ON TABLE s_gtf.v_order_fast TO gtf_user;
+                            GRANT ALL ON TABLE s_gtf.v_order_fast TO u_vitis;
+                            GRANT SELECT ON TABLE s_gtf.v_order_fast TO gtf_author;
+                            GRANT ALL ON TABLE s_gtf.v_order_fast TO gtf_admin;
+                            CREATE OR REPLACE VIEW s_gtf.v_supervision_status AS SELECT count(v_order_fast.order_id) AS nb_order_id, v_order_fast.order_status_id AS filter, 'order'::text AS table_name FROM s_gtf.v_order_fast GROUP BY v_order_fast.order_status_id UNION SELECT count(v_subscription.order_id) AS nb_order_id, CASE WHEN v_subscription.enabled IS TRUE THEN 1 ELSE 0 END AS filter, 'subscription'::text AS table_name FROM s_gtf.v_subscription WHERE v_subscription.lang::text = 'fr'::text GROUP BY v_subscription.enabled UNION SELECT count(v_survey.order_id) AS nb_order_id, CASE WHEN v_survey.enabled IS TRUE THEN 1 ELSE 0 END AS filter, 'survey'::text AS table_name FROM s_gtf.v_survey WHERE v_survey.lang::text = 'fr'::text GROUP BY v_survey.enabled;
+                            CREATE OR REPLACE VIEW s_gtf.v_workspace AS SELECT workspace.workspace_id, workspace.name, workspace.owner, workspace.creation_date, workspace.description, workspace.subscription, workspace.fmw_file, workspace.category_id, workspace.success_action_id, workspace.failed_action_id, workspace.survey, workspace.form_type, workspace.legal_terms_conditions, workspace.last_save_date, workspace.last_save_build, workspace.file_encoding, workspace.title, workspace.requirements, workspace.history, workspace.usage, workspace.key, workspace.email_template_id, workspace.locked, workspace.tag, "user".login, category.name AS category_name, CASE WHEN t.nb_demandes IS NULL THEN 0::bigint ELSE t.nb_demandes END AS nb_demande, email_template.name AS email_template FROM s_gtf.workspace LEFT JOIN s_vitis."user" ON workspace.owner = "user".user_id LEFT JOIN s_gtf.category ON workspace.category_id = category.category_id LEFT JOIN s_gtf.email_template ON workspace.email_template_id = email_template.email_template_id LEFT JOIN (SELECT count(*) AS nb_demandes, v_order_fast.workspace_id FROM s_gtf.v_order_fast GROUP BY v_order_fast.workspace_id) t ON workspace.workspace_id = t.workspace_id;
                             -- Frédéric le 19/04/2018 16:27
                             UPDATE s_vitis.vm_tab SET event='loadList(''showSupervisionRecap()'',{"lang": ""});' WHERE label_id='gtf_60' AND "name"='gtf_order';
                             UPDATE s_vitis.vm_tab SET event='loadList("showSupervisionRecap();refreshWorkspaceListByPeriod();")' WHERE label_id='gtf_262' AND "name"='gtf_message';
@@ -1644,7 +1644,6 @@
                             GRANT SELECT ON TABLE s_gtf.v_supervision_status TO gtf_user;
                             GRANT SELECT ON TABLE s_gtf.v_supervision_status TO gtf_author;
                             UPDATE s_vitis.vm_table_field SET template = '<div data-app-message-status-icon-column="{{row.entity[col.field]}}"></div>' WHERE label_id = 'gtf_277';
-
                             -- Frédéric le 20/04/2018 14:47
                             GRANT ALL ON TABLE s_gtf."message" TO gtf_scheduler;
                             
@@ -1768,10 +1767,233 @@
                             CREATE OR REPLACE RULE insert_v_user_order AS ON INSERT TO s_gtf.v_user_order DO INSTEAD  INSERT INTO s_gtf."order" (order_id, priority_id, workspace_id, user_id, wk_params, result_url, log_url, execution_date, attempt, email_notifications, email_option_id, deleted, gtf_engine_id, order_date) VALUES (new.order_id, new.priority_id, new.workspace_id, new.user_id, new.wk_params, new.result_url, new.log_url, new.execution_date, new.attempt, new.email_notifications, new.email_option_id, false, new.gtf_engine_id, new.order_date);
                             CREATE OR REPLACE RULE insert_v_user_subscription AS ON INSERT TO s_gtf.v_user_subscription DO INSTEAD  INSERT INTO s_gtf."order" (order_id, workspace_id, user_id, period_id, execution_date, wk_params, result_url, email_option_id, email_notifications, gtf_engine_id, enabled, order_date) VALUES (new.order_id, new.workspace_id, new.user_id, new.period_id, new.execution_date, new.wk_params, new.result_url, new.email_option_id, new.email_notifications, new.gtf_engine_id, new.enabled, new.order_date);
                             CREATE OR REPLACE RULE insert_v_user_survey AS ON INSERT TO s_gtf.v_user_survey DO INSTEAD  INSERT INTO s_gtf."order" (order_id, workspace_id, user_id, enabled, period_id, execution_date, wk_params, result_url, email_option_id, email_notifications, gtf_engine_id, survey_id, condition, inbox_id, order_date) VALUES (new.order_id, new.workspace_id, new.user_id, new.enabled, new.period_id, new.execution_date, new.wk_params, new.result_url, new.email_option_id, new.email_notifications, new.gtf_engine_id, new.survey_id, CASE WHEN new.condition IS NULL THEN ''::character varying ELSE new.condition END, new.inbox_id, new.order_date);
+                            
                             -- Frédéric le 15/05/2018 16:15
                             UPDATE s_vitis.vm_tab SET event='loadList("showSupervisionRecap()");' WHERE label_id='gtf_60' AND "name"='gtf_order';
+                            
+                            -- Frédéric le 15/06/2018 09:15
+                            ALTER TABLE s_gtf.workspace ADD COLUMN dataencrypt boolean DEFAULT FALSE;
+                            CREATE OR REPLACE VIEW s_gtf.v_workspace AS SELECT workspace.workspace_id, workspace.name, workspace.owner, workspace.creation_date, workspace.description, workspace.subscription, workspace.fmw_file, workspace.category_id, workspace.success_action_id, workspace.failed_action_id, workspace.survey, workspace.form_type, workspace.legal_terms_conditions, workspace.last_save_date, workspace.last_save_build, workspace.file_encoding, workspace.title, workspace.requirements, workspace.history, workspace.usage, workspace.key, workspace.email_template_id, workspace.locked, workspace.tag, "user".login, category.name AS category_name, CASE WHEN t.nb_demandes IS NULL THEN 0::bigint ELSE t.nb_demandes END AS nb_demande, email_template.name AS email_template, workspace.dataencrypt FROM s_gtf.workspace LEFT JOIN s_vitis."user" ON workspace.owner = "user".user_id LEFT JOIN s_gtf.category ON workspace.category_id = category.category_id LEFT JOIN s_gtf.email_template ON workspace.email_template_id = email_template.email_template_id LEFT JOIN (SELECT count(*) AS nb_demandes, v_order_fast.workspace_id FROM s_gtf.v_order_fast GROUP BY v_order_fast.workspace_id) t ON workspace.workspace_id = t.workspace_id;                                
+                            
+                            -- Frédéric le 20/06/2018 14:36
+                            INSERT INTO s_gtf.email_template (email_template_id, name, subject, "body", "to", cc, cci, code, use_advanced, rt_emailcontext_id, attachment) VALUES (-1, 'default_secretkey', 'Notification de clé secrète pour le traitement [order_id]', '<p>order.user.email = [order.user.email]</p> <p> </p> <p> </p> <p>Bonjour [owner_name],</p> <p>Le traitement est terminé.</p> <p>Vous pouvez télécharger le résultat sur :</p> <p>user_email] = [user_email]</p> <p>user] = [user]</p> <p>log = [log_url]</p> <p> </p> <p> </p> <p> </p> <p> </p> <p> </p> <p> </p>', 'tot@veremes.com', NULL, NULL, E'$logo = $this->aProperties[''ws_data_dir'']."/gtf/gtf.png";\n$base64 = base64_encode(file_get_contents($logo));\n$image = ''<img src="data:image/png;base64,''.$base64.''">'';\n$this->to = '''' . $this->aObjects["oOrder"]->getUser()->aFields[''email''] . '''';\n$this->cc = '''' . $this->aObjects["oOrder"]->aFields[''email_notifications''] . '''';\n$this->cci = '''';\n$this->subject = ''[GTF]-'' . $this->aObjects["oOrder"]->getWorkspace()->aFields[''name''] . '''';\n$this->body = $image.''<p>Bonjour,</p>'';\n$this->subject = ''[GTF]-'' . $this->aObjects["oOrder"]->getWorkspace()->aFields[''name''] . '' - Votre clé secrète'';\n$this->body .= ''<p>Votre clé secrète pour la demande n°'' . $this->aObjects["oOrder"]->aFields[''order_id''] . '' du traitement <strong>'' . $this->aObjects["oOrder"]->getWorkspace()->aFields[''name''] . ''</strong> :<br/>'' . $this->aObjects["oOrder"]->sSecretKey . ''<br/>'';\n$this->body .= ''<p><span style="color: #808080;font-size: smaller;"> Ce message a été envoyé par un automate. Merci de ne pas y répondre.</span></p>'';\n', true, 'gtf', NULL);
+
+                            -- Frédéric le 21/06/2018 10:08
+                            UPDATE s_gtf.email_template SET code = E'$logo = $this->aProperties[''ws_data_dir'']."/gtf/gtf.png";\n$base64 = base64_encode(file_get_contents($logo));\n$image = ''<img src="data:image/png;base64,''.$base64.''">'';\n$this->to = '''' . $this->aObjects["oOrder"]->getUser()->aFields[''email''] . '''';\n$this->cc = '''' . $this->aObjects["oOrder"]->aFields[''email_notifications''] . '''';\n$this->cci = '''';\n$this->subject = ''[GTF]-'' . $this->aObjects["oOrder"]->getWorkspace()->aFields[''name''] . '''';\n$this->body = $image.''<p>Bonjour,</p>'';\nif ($this->aObjects["oOrder"]->aFields[''order_status_id''] == 3) {\n	$this->subject = ''[GTF]-'' . $this->aObjects["oOrder"]->getWorkspace()->aFields[''name''] . '' - Traitement réussi'';\n    $this->body .= ''<p>Votre demande n°'' . $this->aObjects["oOrder"]->aFields[''order_id''] . '' pour le traitement <strong>'' . $this->aObjects["oOrder"]->getWorkspace()->aFields[''name''] . ''</strong> a bien été exécutée.<br/>'';\n	// Si le résultat est crypté : pas de pièce jointe ou de lien de téléchargement.\n	if ($aObjects[''oOrder'']->aFields[''bDataEncrypt'']) {\n        $this->body .= ''Le résultat est disponible en vous connectant à l\\''application :<p><a href="'' . $aObjects[''oOrder'']->aFields[''sApplicationUrl''] . ''">'' . $aObjects[''oOrder'']->aFields[''sApplicationUrl''] . ''</a></p>'';\n	}\n    else if($this->aObjects["oOrder"]->aFields[''result_file''] != ''''){\n		// les résultats de moins de 5 Mo sont envoyés en pièce jointe\n        if (filesize($this->aObjects["oOrder"]->aFields[''result_file''])> (5*1024*1024)){\n            $this->body .= ''Le résultat est disponible par téléchargement :<p><a href="'' . $this->aObjects["oOrder"]->aFields[''result_url''] . ''">Télécharger le résultat</a></p>'';\n        } else {\n            $this->body .= ''<p>Le résultat est disponible en pièce jointe</p>'';\n            $this->aAttachments[0] = $this->aObjects["oOrder"]->aFields[''result_file''];\n        }\n    }\n} else {\n	$this->subject = ''[GTF]-'' . $this->aObjects["oOrder"]->getWorkspace()->aFields[''name''] . '' - Echec du traitement'';\n    $this->body .= ''<p>Votre demande n°'' . $this->aObjects["oOrder"]->aFields[''order_id''] . '' pour le traitement <strong>'' . $this->aObjects["oOrder"]->getWorkspace()->aFields[''name''] . ''</strong> n\\''a pu être exécutée correctement suite à une erreur.<br/> Veuillez contactez votre administrateur.<br/>'';\n    $this->aAttachments[0] = $this->aObjects["oOrder"]->aFields[''log_file''];\n}\n$this->body .= ''<p><span style="color: #808080;font-size: smaller;"> Ce message a été envoyé par un automate. Merci de ne pas y répondre.</span></p>'';\n' WHERE email_template_id = 1;
+
+                            -- Frédéric le 21/06/2018 12:15
+                            ALTER TABLE s_gtf.workspace ADD COLUMN usepersonaldata boolean DEFAULT FALSE;
+                            
+                            -- Frédéric le 21/06/2018 14:00
+                            CREATE OR REPLACE VIEW s_gtf.v_workspace AS SELECT workspace.workspace_id, workspace.name, workspace.owner, workspace.creation_date, workspace.description, workspace.subscription, workspace.fmw_file, workspace.category_id, workspace.success_action_id, workspace.failed_action_id, workspace.survey, workspace.form_type, workspace.legal_terms_conditions, workspace.last_save_date, workspace.last_save_build, workspace.file_encoding, workspace.title, workspace.requirements, workspace.history, workspace.usage, workspace.key, workspace.email_template_id, workspace.locked, workspace.tag, "user".login, category.name AS category_name, CASE WHEN t.nb_demandes IS NULL THEN 0::bigint ELSE t.nb_demandes END AS nb_demande, email_template.name AS email_template, workspace.dataencrypt, workspace.usepersonaldata FROM s_gtf.workspace LEFT JOIN s_vitis."user" ON workspace.owner = "user".user_id LEFT JOIN s_gtf.category ON workspace.category_id = category.category_id LEFT JOIN s_gtf.email_template ON workspace.email_template_id = email_template.email_template_id LEFT JOIN (SELECT count(*) AS nb_demandes, v_order_fast.workspace_id FROM s_gtf.v_order_fast GROUP BY v_order_fast.workspace_id) t ON workspace.workspace_id = t.workspace_id;                                
+                           
+                            -- Frédéric le 25/06/2018 10:54
+                            ALTER TABLE s_gtf.workspace ADD COLUMN unitcost float;
+                            ALTER TABLE s_gtf.workspace ADD COLUMN costpersecond float;
+                            CREATE OR REPLACE VIEW s_gtf.v_workspace AS SELECT workspace.workspace_id, workspace.name, workspace.owner, workspace.creation_date, workspace.description, workspace.subscription, workspace.fmw_file, workspace.category_id, workspace.success_action_id, workspace.failed_action_id, workspace.survey, workspace.form_type, workspace.legal_terms_conditions, workspace.last_save_date, workspace.last_save_build, workspace.file_encoding, workspace.title, workspace.requirements, workspace.history, workspace.usage, workspace.key, workspace.email_template_id, workspace.locked, workspace.tag, "user".login, category.name AS category_name, CASE WHEN t.nb_demandes IS NULL THEN 0::bigint ELSE t.nb_demandes END AS nb_demande, email_template.name AS email_template, workspace.dataencrypt, workspace.usepersonaldata, workspace.unitcost, workspace.costpersecond FROM s_gtf.workspace LEFT JOIN s_vitis."user" ON workspace.owner = "user".user_id LEFT JOIN s_gtf.category ON workspace.category_id = category.category_id LEFT JOIN s_gtf.email_template ON workspace.email_template_id = email_template.email_template_id LEFT JOIN (SELECT count(*) AS nb_demandes, v_order_fast.workspace_id FROM s_gtf.v_order_fast GROUP BY v_order_fast.workspace_id) t ON workspace.workspace_id = t.workspace_id;        
+
+                            -- Anthony le 10/07/2018 17:00
+                            INSERT INTO s_gtf.actionclass (actionclass, label) VALUES ('SMSAction', '<p>Notification d''envoi de SMS</p>');
+                            
+                            -- Frédéric le 18/07/2018 14:45
+                            ALTER TABLE s_gtf.order ADD COLUMN minexecdate timestamp with time zone;
+                            
+                            INSERT INTO s_vitis.vm_string (string, string_id) VALUES ('Champ minexecdate de l''onglet gtf_user_order', 'gtf_327');
+                            INSERT INTO s_vitis.vm_string (string, string_id) VALUES ('Champ minexecdate de l''onglet gtf_order', 'gtf_328');
+                            INSERT INTO s_vitis.vm_translation (translation_id, lang, translation) VALUES ('gtf_327', 'fr', 'Date de planification');
+                            INSERT INTO s_vitis.vm_translation (translation_id, lang, translation) VALUES ('gtf_327', 'en', 'Planning date');
+                            INSERT INTO s_vitis.vm_translation (translation_id, lang, translation) VALUES ('gtf_328', 'fr', 'Date de planification');
+                            INSERT INTO s_vitis.vm_translation (translation_id, lang, translation) VALUES ('gtf_328', 'en', 'Planning date');
+                            INSERT INTO s_vitis.vm_table_field (table_field_id, name, sortable, resizeable, index, width, align, label_id, module, ressource_id, template, tab_id) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'minexecdate', true, true, 9, 120, 'left', 'gtf_327', NULL, 'gtf/userorders', '<div data-app-format-date-column="{{row.entity[col.field]}}"></div>', (select tab_id from s_vitis.vm_tab where name = 'gtf_user_order'));
+                            INSERT INTO s_vitis.vm_table_field (table_field_id, name, sortable, resizeable, index, width, align, label_id, module, ressource_id, template, tab_id) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'minexecdate', true, true, 9, 120, 'left', 'gtf_328', NULL, 'gtf/orders', '<div data-app-format-date-column="{{row.entity[col.field]}}"></div>', (select tab_id from s_vitis.vm_tab where name = 'gtf_order'));
+                            
+                            ALTER TABLE s_gtf.message ADD COLUMN minexecdate timestamp with time zone;
+                            INSERT INTO s_vitis.vm_string (string, string_id) VALUES ('Champ minexecdate de l''onglet gtf_message', 'gtf_329');
+                            INSERT INTO s_vitis.vm_translation (translation_id, lang, translation) VALUES ('gtf_329', 'fr', 'Date de planification');
+                            INSERT INTO s_vitis.vm_translation (translation_id, lang, translation) VALUES ('gtf_329', 'en', 'Planning date');
+                            INSERT INTO s_vitis.vm_table_field (table_field_id, name, sortable, resizeable, index, width, align, label_id, module, ressource_id, template, tab_id) VALUES ((select nextval('s_vitis.seq_vm'::regclass)), 'minexecdate', true, true, 6, 120, 'left', 'gtf_329', NULL, 'gtf/messages', '<div data-app-format-date-column="{{row.entity[col.field]}}"></div>', (select tab_id from s_vitis.vm_tab where name = 'gtf_message'));
+                            
+                            -- Frédéric le 19/07/2018 10:53
+                            CREATE OR REPLACE VIEW s_gtf.v_message AS SELECT message.message_id, message.messageclass, message.creation_date, message.body, message.sender, messageclass.messageclass_type, message.status, message.minexecdate FROM s_gtf.message LEFT JOIN s_gtf.messageclass ON message.messageclass::text = messageclass.messageclass::text;
+
+                            -- Frédéric le 20/07/2018 12:23
+                            CREATE OR REPLACE VIEW s_gtf.v_order AS SELECT "order".order_id, "order".priority_id, "order".workspace_id, workspace.key AS workspace_key, workspace.name AS label_name, "order".order_status_id, "order".user_id, "user".login, "order".period_id, period.name AS order_period_libelle, "order".wk_params, "order".result_url, "order".order_date, "order".log_url, "order".execution_date, "order".attempt, "order".email_notifications, "order".email_option_id, "order".deleted, "order".gtf_engine_id, s_gtf.s2hms("order".length_sec) AS length_sec, priority_translation.translation AS priority_label, email_option_translation.translation AS email_option_label, priority_translation.lang, gtf_engine.name, order_status_translation.translation AS order_status_label, timezone("user".timezone_id::text, "order".minexecdate) AS minexecdate FROM s_gtf."order" LEFT JOIN s_gtf.workspace ON "order".workspace_id = workspace.workspace_id LEFT JOIN s_gtf.period ON "order".period_id = period.period_id LEFT JOIN s_vitis."user" ON "user".user_id = "order".user_id LEFT JOIN s_gtf.rt_priority ON "order".priority_id = rt_priority.priority_id LEFT JOIN s_vitis.vm_translation priority_translation ON rt_priority.label_id::text = priority_translation.translation_id::text LEFT JOIN s_gtf.rt_email_option ON "order".email_option_id = rt_email_option.email_option_id LEFT JOIN s_vitis.vm_translation email_option_translation ON rt_email_option.label_id::text = email_option_translation.translation_id::text LEFT JOIN s_gtf.rt_order_status ON "order".order_status_id = rt_order_status.order_status_id LEFT JOIN s_vitis.vm_translation order_status_translation ON rt_order_status.label_id::text = order_status_translation.translation_id::text AND priority_translation.lang::text = order_status_translation.lang::text LEFT JOIN s_gtf.gtf_engine ON "order".gtf_engine_id = gtf_engine.gtf_engine_id WHERE "order".period_id IS NULL AND priority_translation.lang::text = email_option_translation.lang::text;
+                            CREATE OR REPLACE VIEW s_gtf.v_order_fast AS SELECT "order".order_id, "order".priority_id, "order".workspace_id, workspace.key AS workspace_key, workspace.name AS label_name, "order".order_status_id, "order".user_id, "user".login, "order".period_id, period.name AS order_period_libelle, "order".wk_params, "order".result_url, "order".order_date, "order".log_url, "order".execution_date, "order".attempt, "order".email_notifications, "order".email_option_id, "order".deleted, "order".gtf_engine_id, "order".length_sec, gtf_engine.name, timezone("user".timezone_id::text, "order".minexecdate) AS minexecdate FROM s_gtf."order" LEFT JOIN s_gtf.workspace ON "order".workspace_id = workspace.workspace_id LEFT JOIN s_gtf.period ON "order".period_id = period.period_id LEFT JOIN s_vitis."user" ON "user".user_id = "order".user_id LEFT JOIN s_gtf.rt_priority ON "order".priority_id = rt_priority.priority_id LEFT JOIN s_gtf.rt_email_option ON "order".email_option_id = rt_email_option.email_option_id LEFT JOIN s_gtf.rt_order_status ON "order".order_status_id = rt_order_status.order_status_id LEFT JOIN s_gtf.gtf_engine ON "order".gtf_engine_id = gtf_engine.gtf_engine_id WHERE "order".period_id IS NULL;
+                            CREATE OR REPLACE VIEW s_gtf.v_user_order AS SELECT "order".order_id, "order".priority_id, workspace.key AS workspace_key, "order".workspace_id, workspace.name, "order".order_status_id, "order".user_id, "order".wk_params, "order".result_url, "order".order_date, "order".log_url, "order".execution_date, "order".attempt, "order".email_notifications, "order".email_option_id, "order".deleted, "order".gtf_engine_id, s_gtf.s2hms("order".length_sec) AS length_sec, workspace.name AS workspace_name, priority_translation.translation AS priority_label, email_option_translation.translation AS email_option_label, priority_translation.lang, order_status_translation.lang AS order_status_lang, order_status_translation.translation AS order_status_label, timezone("user".timezone_id::text, "order".minexecdate) AS minexecdate FROM s_gtf."order" LEFT JOIN s_gtf.workspace ON "order".workspace_id = workspace.workspace_id LEFT JOIN s_gtf.rt_priority ON "order".priority_id = rt_priority.priority_id LEFT JOIN s_gtf.rt_order_status ON "order".order_status_id = rt_order_status.order_status_id LEFT JOIN s_vitis.vm_translation priority_translation ON rt_priority.label_id::text = priority_translation.translation_id::text LEFT JOIN s_gtf.rt_email_option ON "order".email_option_id = rt_email_option.email_option_id LEFT JOIN s_vitis.vm_translation email_option_translation ON rt_email_option.label_id::text = email_option_translation.translation_id::text LEFT JOIN s_vitis.vm_translation order_status_translation ON rt_order_status.label_id::text = order_status_translation.translation_id::text LEFT JOIN s_vitis."user" ON "user".user_id = "order".user_id WHERE "order".user_id::text ~ similar_escape((( SELECT "user".user_id FROM s_vitis."user" WHERE "user".login::name = "current_user"()))::text, NULL::text) AND "order".period_id IS NULL AND "order".deleted IS NOT TRUE AND priority_translation.lang::text = email_option_translation.lang::text AND priority_translation.lang::text = order_status_translation.lang::text;
+                            CREATE OR REPLACE RULE insert_v_user_order AS ON INSERT TO s_gtf.v_user_order DO INSTEAD  INSERT INTO s_gtf."order" (order_id, priority_id, workspace_id, user_id, wk_params, result_url, log_url, execution_date, attempt, email_notifications, email_option_id, deleted, gtf_engine_id, order_date, minexecdate) VALUES (new.order_id, new.priority_id, new.workspace_id, new.user_id, new.wk_params, new.result_url, new.log_url, new.execution_date, new.attempt, new.email_notifications, new.email_option_id, false, new.gtf_engine_id, new.order_date, new.minexecdate);
+
+                            -- Frédéric le 20/07/2018 15:30
+                            ALTER TABLE s_gtf.job ALTER COLUMN execution_date TYPE timestamp with time zone;
+                            DROP VIEW s_gtf.v_supervision_status;
+                            DROP VIEW s_gtf.v_subscription;
+                            DROP VIEW s_gtf.v_survey;
+                            DROP VIEW s_gtf.v_user_subscription;
+                            DROP VIEW s_gtf.v_user_survey;
+                            DROP VIEW s_gtf.v_order;
+                            DROP VIEW s_gtf.v_author_workspace;
+                            DROP VIEW s_gtf.v_workspace;
+                            DROP VIEW s_gtf.v_user_order;
+                            DROP VIEW s_gtf.v_order_fast;
+
+                            ALTER TABLE s_gtf.order ALTER COLUMN order_date TYPE timestamp with time zone;
+                            ALTER TABLE s_gtf.order ALTER COLUMN execution_date TYPE timestamp with time zone;
+                            ALTER TABLE s_gtf.workspace ALTER COLUMN last_save_date TYPE timestamp with time zone;
+                            ALTER TABLE s_gtf.workspace ALTER COLUMN creation_date TYPE timestamp with time zone;
+
+                            CREATE OR REPLACE VIEW s_gtf.v_user_order AS SELECT "order".order_id, "order".priority_id, workspace.key AS workspace_key, "order".workspace_id, workspace.name, "order".order_status_id, "order".user_id, "order".wk_params, "order".result_url, "order".order_date, "order".log_url, "order".execution_date, "order".attempt, "order".email_notifications, "order".email_option_id, "order".deleted, "order".gtf_engine_id, s_gtf.s2hms("order".length_sec) AS length_sec, workspace.name AS workspace_name, priority_translation.translation AS priority_label, email_option_translation.translation AS email_option_label, priority_translation.lang, order_status_translation.lang AS order_status_lang, order_status_translation.translation AS order_status_label, "order".minexecdate FROM s_gtf."order" LEFT JOIN s_gtf.workspace ON "order".workspace_id = workspace.workspace_id LEFT JOIN s_gtf.rt_priority ON "order".priority_id = rt_priority.priority_id LEFT JOIN s_gtf.rt_order_status ON "order".order_status_id = rt_order_status.order_status_id LEFT JOIN s_vitis.vm_translation priority_translation ON rt_priority.label_id::text = priority_translation.translation_id::text LEFT JOIN s_gtf.rt_email_option ON "order".email_option_id = rt_email_option.email_option_id LEFT JOIN s_vitis.vm_translation email_option_translation ON rt_email_option.label_id::text = email_option_translation.translation_id::text LEFT JOIN s_vitis.vm_translation order_status_translation ON rt_order_status.label_id::text = order_status_translation.translation_id::text LEFT JOIN s_vitis."user" ON "user".user_id = "order".user_id WHERE "order".user_id::text ~ similar_escape((( SELECT user_1.user_id FROM s_vitis."user" user_1 WHERE user_1.login::name = "current_user"()))::text, NULL::text) AND "order".period_id IS NULL AND "order".deleted IS NOT TRUE AND priority_translation.lang::text = email_option_translation.lang::text AND priority_translation.lang::text = order_status_translation.lang::text;
+                            ALTER TABLE s_gtf.v_user_order OWNER TO u_vitis;
+                            GRANT ALL ON TABLE s_gtf.v_user_order TO gtf_admin;
+                            GRANT ALL ON TABLE s_gtf.v_user_order TO gtf_user;
+                            GRANT SELECT ON TABLE s_gtf.v_user_order TO gtf_author;
+                            CREATE OR REPLACE RULE delete_v_user_order AS ON DELETE TO s_gtf.v_user_order DO INSTEAD  UPDATE s_gtf."order" SET deleted = true WHERE "order".order_id = old.order_id;
+                            CREATE OR REPLACE RULE insert_v_user_order AS ON INSERT TO s_gtf.v_user_order DO INSTEAD  INSERT INTO s_gtf."order" (order_id, priority_id, workspace_id, user_id, wk_params, result_url, log_url, execution_date, attempt, email_notifications, email_option_id, deleted, gtf_engine_id, order_date, minexecdate) VALUES (new.order_id, new.priority_id, new.workspace_id, new.user_id, new.wk_params, new.result_url, new.log_url, new.execution_date, new.attempt, new.email_notifications, new.email_option_id, false, new.gtf_engine_id, new.order_date, new.minexecdate);
+
+                            CREATE OR REPLACE VIEW s_gtf.v_order_fast AS SELECT "order".order_id, "order".priority_id, "order".workspace_id, workspace.key AS workspace_key, workspace.name AS label_name, "order".order_status_id, "order".user_id, "user".login, "order".period_id, period.name AS order_period_libelle, "order".wk_params, "order".result_url, "order".order_date, "order".log_url, "order".execution_date, "order".attempt, "order".email_notifications, "order".email_option_id, "order".deleted, "order".gtf_engine_id, "order".length_sec, gtf_engine.name, "order".minexecdate FROM s_gtf."order" LEFT JOIN s_gtf.workspace ON "order".workspace_id = workspace.workspace_id LEFT JOIN s_gtf.period ON "order".period_id = period.period_id LEFT JOIN s_vitis."user" ON "user".user_id = "order".user_id LEFT JOIN s_gtf.rt_priority ON "order".priority_id = rt_priority.priority_id LEFT JOIN s_gtf.rt_email_option ON "order".email_option_id = rt_email_option.email_option_id LEFT JOIN s_gtf.rt_order_status ON "order".order_status_id = rt_order_status.order_status_id LEFT JOIN s_gtf.gtf_engine ON "order".gtf_engine_id = gtf_engine.gtf_engine_id WHERE "order".period_id IS NULL;
+                            ALTER TABLE s_gtf.v_order_fast OWNER TO u_vitis;
+                            GRANT SELECT ON TABLE s_gtf.v_order_fast TO gtf_user;
+                            GRANT SELECT ON TABLE s_gtf.v_order_fast TO gtf_author;
+                            GRANT ALL ON TABLE s_gtf.v_order_fast TO gtf_admin;
+
+                            CREATE OR REPLACE VIEW s_gtf.v_workspace AS SELECT workspace.workspace_id, workspace.name, workspace.owner, workspace.creation_date, workspace.description, workspace.subscription, workspace.fmw_file, workspace.category_id, workspace.success_action_id, workspace.failed_action_id, workspace.survey, workspace.form_type, workspace.legal_terms_conditions, workspace.last_save_date, workspace.last_save_build, workspace.file_encoding, workspace.title, workspace.requirements, workspace.history, workspace.usage, workspace.key, workspace.email_template_id, workspace.locked, workspace.tag, "user".login, category.name AS category_name, CASE WHEN t.nb_demandes IS NULL THEN 0::bigint ELSE t.nb_demandes END AS nb_demande, email_template.name AS email_template, workspace.dataencrypt, workspace.usepersonaldata, workspace.unitcost, workspace.costpersecond FROM s_gtf.workspace LEFT JOIN s_vitis."user" ON workspace.owner = "user".user_id LEFT JOIN s_gtf.category ON workspace.category_id = category.category_id LEFT JOIN s_gtf.email_template ON workspace.email_template_id = email_template.email_template_id LEFT JOIN ( SELECT count(*) AS nb_demandes, v_order_fast.workspace_id FROM s_gtf.v_order_fast GROUP BY v_order_fast.workspace_id) t ON workspace.workspace_id = t.workspace_id;
+                            ALTER TABLE s_gtf.v_workspace OWNER TO u_vitis;
+                            GRANT ALL ON TABLE s_gtf.v_workspace TO gtf_admin;
+                            GRANT SELECT ON TABLE s_gtf.v_workspace TO gtf_user;
+                            GRANT SELECT ON TABLE s_gtf.v_workspace TO gtf_author;
+
+                            CREATE OR REPLACE VIEW s_gtf.v_author_workspace AS SELECT v_workspace.workspace_id, v_workspace.name, v_workspace.owner, v_workspace.creation_date, v_workspace.description, v_workspace.subscription, v_workspace.fmw_file, v_workspace.category_id, v_workspace.success_action_id, v_workspace.failed_action_id, v_workspace.survey, v_workspace.form_type, v_workspace.legal_terms_conditions, v_workspace.last_save_date, v_workspace.last_save_build, v_workspace.file_encoding, v_workspace.title, v_workspace.requirements, v_workspace.history, v_workspace.usage, v_workspace.key, v_workspace.email_template_id, v_workspace.locked, v_workspace.tag, v_workspace.login, v_workspace.category_name, v_workspace.nb_demande, v_workspace.email_template, v_workspace.dataencrypt FROM s_gtf.v_workspace WHERE v_workspace.login::name::text = "current_user"()::text;
+                            ALTER TABLE s_gtf.v_author_workspace OWNER TO u_vitis;
+                            GRANT ALL ON TABLE s_gtf.v_author_workspace TO gtf_user;
+                            GRANT ALL ON TABLE s_gtf.v_author_workspace TO gtf_admin;
+                            GRANT ALL ON TABLE s_gtf.v_author_workspace TO gtf_author;
+
+                            CREATE OR REPLACE VIEW s_gtf.v_order AS SELECT "order".order_id, "order".priority_id, "order".workspace_id, workspace.key AS workspace_key, workspace.name AS label_name, "order".order_status_id, "order".user_id, "user".login, "order".period_id, period.name AS order_period_libelle, "order".wk_params, "order".result_url, "order".order_date, "order".log_url, "order".execution_date, "order".attempt, "order".email_notifications, "order".email_option_id, "order".deleted, "order".gtf_engine_id, s_gtf.s2hms("order".length_sec) AS length_sec, priority_translation.translation AS priority_label, email_option_translation.translation AS email_option_label, priority_translation.lang, gtf_engine.name, order_status_translation.translation AS order_status_label, "order".minexecdate FROM s_gtf."order" LEFT JOIN s_gtf.workspace ON "order".workspace_id = workspace.workspace_id LEFT JOIN s_gtf.period ON "order".period_id = period.period_id LEFT JOIN s_vitis."user" ON "user".user_id = "order".user_id LEFT JOIN s_gtf.rt_priority ON "order".priority_id = rt_priority.priority_id LEFT JOIN s_vitis.vm_translation priority_translation ON rt_priority.label_id::text = priority_translation.translation_id::text LEFT JOIN s_gtf.rt_email_option ON "order".email_option_id = rt_email_option.email_option_id LEFT JOIN s_vitis.vm_translation email_option_translation ON rt_email_option.label_id::text = email_option_translation.translation_id::text LEFT JOIN s_gtf.rt_order_status ON "order".order_status_id = rt_order_status.order_status_id LEFT JOIN s_vitis.vm_translation order_status_translation ON rt_order_status.label_id::text = order_status_translation.translation_id::text AND priority_translation.lang::text = order_status_translation.lang::text LEFT JOIN s_gtf.gtf_engine ON "order".gtf_engine_id = gtf_engine.gtf_engine_id WHERE "order".period_id IS NULL AND priority_translation.lang::text = email_option_translation.lang::text;
+                            ALTER TABLE s_gtf.v_order OWNER TO u_vitis;
+                            GRANT ALL ON TABLE s_gtf.v_order TO gtf_admin;
+                            GRANT SELECT ON TABLE s_gtf.v_order TO gtf_user;
+                            GRANT SELECT ON TABLE s_gtf.v_order TO gtf_author;
+                            CREATE OR REPLACE RULE delete_v_order AS ON DELETE TO s_gtf.v_order DO INSTEAD  DELETE FROM s_gtf."order" WHERE "order".order_id = old.order_id;
+
+                            CREATE OR REPLACE VIEW s_gtf.v_subscription AS SELECT "order".order_id, "order".priority_id, "order".workspace_id, workspace.key AS workspace_key, "order".enabled, workspace.name AS label_name, "order".order_status_id, "order".user_id, "user".login, "order".period_id, period.name AS order_period_libelle, "order".wk_params, "order".result_url, "order".order_date, "order".log_url, "order".execution_date, "order".attempt, "order".email_notifications, "order".email_option_id, "order".deleted, "order".gtf_engine_id, email_option_translation.translation AS notification, email_option_translation.lang FROM s_gtf."order" LEFT JOIN s_gtf.workspace ON "order".workspace_id = workspace.workspace_id LEFT JOIN s_gtf.period ON "order".period_id = period.period_id LEFT JOIN s_vitis."user" ON "user".user_id = "order".user_id LEFT JOIN s_gtf.rt_email_option ON "order".email_option_id = rt_email_option.email_option_id LEFT JOIN s_vitis.vm_translation email_option_translation ON rt_email_option.label_id::text = email_option_translation.translation_id::text WHERE "order".period_id IS NOT NULL AND "order".survey_id IS NULL;
+                            ALTER TABLE s_gtf.v_subscription OWNER TO u_vitis;
+                            GRANT ALL ON TABLE s_gtf.v_subscription TO gtf_user;
+                            GRANT ALL ON TABLE s_gtf.v_subscription TO gtf_admin;
+                            GRANT ALL ON TABLE s_gtf.v_subscription TO gtf_author;
+                            CREATE OR REPLACE RULE delete_v_subscription AS ON DELETE TO s_gtf.v_subscription DO INSTEAD  DELETE FROM s_gtf."order" WHERE "order".order_id = old.order_id;
+
+                            CREATE OR REPLACE VIEW s_gtf.v_survey AS SELECT "order".order_id, workspace.key AS workspace_key, "order".priority_id, "order".workspace_id, "order".enabled, workspace.name AS label_name, "order".order_status_id, "order".user_id, "user".login, "order".period_id, period.name AS order_period_libelle, "order".wk_params, "order".result_url, "order".order_date, "order".log_url, "order".execution_date, "order".attempt, "order".email_notifications, "order".email_option_id, "order".deleted, "order".gtf_engine_id, "order".survey_id, "order".condition, inbox.alias AS warehouse_name, email_option_translation.translation AS notification, email_option_translation.lang, survey_type_translation.translation AS survey_name FROM s_gtf."order" LEFT JOIN s_gtf.workspace ON "order".workspace_id = workspace.workspace_id LEFT JOIN s_gtf.period ON "order".period_id = period.period_id LEFT JOIN s_vitis."user" ON "user".user_id = "order".user_id LEFT JOIN s_gtf.inbox ON "order".inbox_id = inbox.inbox_id LEFT JOIN s_gtf.rt_email_option ON "order".email_option_id = rt_email_option.email_option_id LEFT JOIN s_vitis.vm_translation email_option_translation ON rt_email_option.label_id::text = email_option_translation.translation_id::text LEFT JOIN s_gtf.rt_survey_type ON "order".survey_id = rt_survey_type.survey_id LEFT JOIN s_vitis.vm_translation survey_type_translation ON rt_survey_type.label_id::text = survey_type_translation.translation_id::text WHERE "order".period_id IS NOT NULL AND "order".survey_id = 1 AND email_option_translation.lang::text = survey_type_translation.lang::text;
+                            ALTER TABLE s_gtf.v_survey OWNER TO u_vitis;
+                            GRANT ALL ON TABLE s_gtf.v_survey TO gtf_user;
+                            GRANT ALL ON TABLE s_gtf.v_survey TO gtf_admin;
+                            GRANT ALL ON TABLE s_gtf.v_survey TO gtf_author;
+                            CREATE OR REPLACE RULE delete_v_survey AS ON DELETE TO s_gtf.v_survey DO INSTEAD  DELETE FROM s_gtf."order" WHERE "order".order_id = old.order_id;
+
+                            CREATE OR REPLACE VIEW s_gtf.v_supervision_status AS SELECT count(v_order.order_id) AS nb_order_id, v_order.order_status_id AS filter, 'order'::text AS table_name FROM s_gtf.v_order WHERE v_order.lang::text = 'fr'::text GROUP BY v_order.order_status_id UNION SELECT count(v_subscription.order_id) AS nb_order_id, CASE WHEN v_subscription.enabled IS TRUE THEN 1 ELSE 0 END AS filter, 'subscription'::text AS table_name FROM s_gtf.v_subscription WHERE v_subscription.lang::text = 'fr'::text GROUP BY v_subscription.enabled UNION SELECT count(v_survey.order_id) AS nb_order_id, CASE WHEN v_survey.enabled IS TRUE THEN 1 ELSE 0 END AS filter, 'survey'::text AS table_name FROM s_gtf.v_survey WHERE v_survey.lang::text = 'fr'::text GROUP BY v_survey.enabled UNION SELECT count(message.message_id) AS nb_order_id, message.status AS filter, 'message'::text AS table_name FROM s_gtf.message GROUP BY message.status;
+                            ALTER TABLE s_gtf.v_supervision_status OWNER TO u_vitis;
+                            GRANT ALL ON TABLE s_gtf.v_supervision_status TO gtf_admin;
+                            GRANT SELECT ON TABLE s_gtf.v_supervision_status TO gtf_user;
+                            GRANT SELECT ON TABLE s_gtf.v_supervision_status TO gtf_author;
+
+                            CREATE OR REPLACE VIEW s_gtf.v_user_survey AS SELECT "order".order_id, workspace.key AS workspace_key, "order".workspace_id, workspace.name AS label_name, "order".enabled, "order".order_status_id, "order".user_id, "order".period_id, "order".order_date, "order".execution_date, "order".wk_params, "order".result_url, "order".email_option_id, "order".email_notifications, "order".gtf_engine_id, "order".survey_id, "order".condition, "order".inbox_id, inbox.alias AS name, workspace.name AS workspace_name, "order".survey_id AS monitoring_type, email_option_translation.translation AS notification, email_option_translation.lang, period.name AS order_period_libelle, survey_type_translation.translation AS survey_name FROM s_gtf."order" LEFT JOIN s_gtf.workspace ON "order".workspace_id = workspace.workspace_id LEFT JOIN s_gtf.rt_email_option ON "order".email_option_id = rt_email_option.email_option_id LEFT JOIN s_vitis.vm_translation email_option_translation ON rt_email_option.label_id::text = email_option_translation.translation_id::text LEFT JOIN s_gtf.period ON "order".period_id = period.period_id LEFT JOIN s_gtf.inbox ON "order".inbox_id = inbox.inbox_id LEFT JOIN s_gtf.rt_survey_type ON "order".survey_id = rt_survey_type.survey_id LEFT JOIN s_vitis.vm_translation survey_type_translation ON rt_survey_type.label_id::text = survey_type_translation.translation_id::text WHERE "order".user_id::text ~ similar_escape((( SELECT "user".user_id FROM s_vitis."user" WHERE "user".login::name = "current_user"()))::text, NULL::text) AND "order".period_id IS NOT NULL AND "order".survey_id = 1 AND email_option_translation.lang::text = survey_type_translation.lang::text;
+                            ALTER TABLE s_gtf.v_user_survey OWNER TO u_vitis;
+                            GRANT ALL ON TABLE s_gtf.v_user_survey TO gtf_user;
+                            GRANT ALL ON TABLE s_gtf.v_user_survey TO gtf_admin;
+                            GRANT ALL ON TABLE s_gtf.v_user_survey TO gtf_author;
+                            COMMENT ON COLUMN s_gtf.v_user_survey.label_name IS 'Deprecated';
+                            COMMENT ON COLUMN s_gtf.v_user_survey.survey_id IS 'Deprecated';
+
+                            CREATE OR REPLACE RULE delete_v_user_survey AS ON DELETE TO s_gtf.v_user_survey DO INSTEAD  DELETE FROM s_gtf."order" WHERE "order".order_id = old.order_id;
+                            CREATE OR REPLACE RULE insert_v_user_survey AS ON INSERT TO s_gtf.v_user_survey DO INSTEAD  INSERT INTO s_gtf."order" (order_id, workspace_id, user_id, enabled, period_id, execution_date, wk_params, result_url, email_option_id, email_notifications, gtf_engine_id, survey_id, condition, inbox_id, order_date) VALUES (new.order_id, new.workspace_id, new.user_id, new.enabled, new.period_id, new.execution_date, new.wk_params, new.result_url, new.email_option_id, new.email_notifications, new.gtf_engine_id, new.survey_id, CASE WHEN new.condition IS NULL THEN ''::character varying ELSE new.condition END, new.inbox_id, new.order_date);
+                            CREATE OR REPLACE RULE update_v_user_survey AS ON UPDATE TO s_gtf.v_user_survey DO INSTEAD  UPDATE s_gtf."order" SET order_id = new.order_id, workspace_id = new.workspace_id, enabled = new.enabled, order_status_id = new.order_status_id, user_id = new.user_id, period_id = new.period_id, order_date = new.order_date, execution_date = new.execution_date, wk_params = new.wk_params, result_url = new.result_url, email_option_id = new.email_option_id, email_notifications = new.email_notifications, gtf_engine_id = new.gtf_engine_id, survey_id = new.survey_id, condition = CASE WHEN new.condition IS NULL THEN ''::character varying ELSE new.condition END, inbox_id = new.inbox_id WHERE "order".order_id = new.order_id;
+                            CREATE OR REPLACE VIEW s_gtf.v_user_subscription AS SELECT "order".order_id, "order".workspace_id, workspace.key AS workspace_key, "order".enabled, workspace.name AS label_name, "order".order_status_id, "order".user_id, "order".period_id, "order".order_date, "order".execution_date, "order".wk_params, "order".result_url, "order".email_option_id, "order".email_notifications, "order".gtf_engine_id, workspace.name AS workspace_name, email_option_translation.translation AS notification, period.name AS order_period_libelle, email_option_translation.lang FROM s_gtf."order" LEFT JOIN s_gtf.workspace ON "order".workspace_id = workspace.workspace_id LEFT JOIN s_gtf.rt_email_option ON "order".email_option_id = rt_email_option.email_option_id LEFT JOIN s_vitis.vm_translation email_option_translation ON rt_email_option.label_id::text = email_option_translation.translation_id::text LEFT JOIN s_gtf.period ON "order".period_id = period.period_id WHERE "order".user_id::text ~ similar_escape((( SELECT "user".user_id FROM s_vitis."user" WHERE "user".login::name = "current_user"()))::text, NULL::text) AND "order".period_id IS NOT NULL AND "order".survey_id IS NULL;
+
+                            ALTER TABLE s_gtf.v_user_subscription OWNER TO u_vitis;
+                            GRANT ALL ON TABLE s_gtf.v_user_subscription TO gtf_user;
+                            GRANT ALL ON TABLE s_gtf.v_user_subscription TO gtf_admin;
+                            GRANT ALL ON TABLE s_gtf.v_user_subscription TO gtf_author;
+                            COMMENT ON COLUMN s_gtf.v_user_subscription.label_name IS 'Deprecated';
+
+                            CREATE OR REPLACE RULE delete_v_user_subscription AS ON DELETE TO s_gtf.v_user_subscription DO INSTEAD  DELETE FROM s_gtf."order" WHERE "order".order_id = old.order_id;
+                            CREATE OR REPLACE RULE insert_v_user_subscription AS ON INSERT TO s_gtf.v_user_subscription DO INSTEAD  INSERT INTO s_gtf."order" (order_id, workspace_id, user_id, period_id, execution_date, wk_params, result_url, email_option_id, email_notifications, gtf_engine_id, enabled, order_date) VALUES (new.order_id, new.workspace_id, new.user_id, new.period_id, new.execution_date, new.wk_params, new.result_url, new.email_option_id, new.email_notifications, new.gtf_engine_id, new.enabled, new.order_date);
+                            CREATE OR REPLACE RULE update_v_user_subscription AS ON UPDATE TO s_gtf.v_user_subscription DO INSTEAD  UPDATE s_gtf."order" SET workspace_id = new.workspace_id, enabled = new.enabled, order_status_id = new.order_status_id, period_id = new.period_id, execution_date = new.execution_date, wk_params = new.wk_params, email_option_id = new.email_option_id, email_notifications = new.email_notifications WHERE "order".order_id = new.order_id;
+
+                            -- Frédéric le 23/07/2018 16:54
+                            UPDATE s_vitis.vm_table_field SET template = NULL WHERE tab_id = (select tab_id from s_vitis.vm_tab where name = 'gtf_user_order') AND name = 'order_date';
+                            UPDATE s_vitis.vm_table_field SET template = NULL WHERE tab_id = (select tab_id from s_vitis.vm_tab where name = 'gtf_user_survey') AND name = 'execution_date';
+                            UPDATE s_vitis.vm_table_field SET template = NULL WHERE tab_id = (select tab_id from s_vitis.vm_tab where name = 'gtf_user_subscription') AND name = 'order_date';
+                            UPDATE s_vitis.vm_table_field SET template = NULL WHERE tab_id = (select tab_id from s_vitis.vm_tab where name = 'gtf_subscription') AND name = 'order_date';
+                            UPDATE s_vitis.vm_table_field SET template = NULL WHERE tab_id = (select tab_id from s_vitis.vm_tab where name = 'gtf_survey') AND name = 'order_date';
+                            UPDATE s_vitis.vm_table_field SET template = NULL WHERE tab_id = (select tab_id from s_vitis.vm_tab where name = 'gtf_message') AND name = 'creation_date';
+                            UPDATE s_vitis.vm_table_field SET template = NULL WHERE tab_id = (select tab_id from s_vitis.vm_tab where name = 'gtf_order') AND name = 'order_date';
+                            UPDATE s_vitis.vm_table_field SET template = NULL WHERE tab_id = (select tab_id from s_vitis.vm_tab where name = 'gtf_user_survey') AND name = 'order_date';
+                            UPDATE s_vitis.vm_table_field SET template = NULL WHERE tab_id = (select tab_id from s_vitis.vm_tab where name = 'gtf_user_order') AND name = 'minexecdate';
+                            UPDATE s_vitis.vm_table_field SET template = NULL WHERE tab_id = (select tab_id from s_vitis.vm_tab where name = 'gtf_order') AND name = 'minexecdate';
+                            UPDATE s_vitis.vm_table_field SET template = NULL WHERE tab_id = (select tab_id from s_vitis.vm_tab where name = 'gtf_message') AND name = 'minexecdate';
+
+                            -- Frédéric le 26/07/2018 14:23
+                            DELETE FROM s_vitis.vm_table_field WHERE tab_id = (select tab_id from s_vitis.vm_tab where name = 'gtf_user_order') AND name = 'priority_label';
+
+                            -- Anthony le 08/08/2018
+                            -- Ajout de workspace.key dans la vue v_user_workspace
+                            CREATE OR REPLACE VIEW s_gtf.v_user_workspace AS SELECT DISTINCT workspace.workspace_id, workspace.name, workspace.description, workspace.subscription, workspace.fmw_file, workspace.category_id, workspace.survey, workspace_group.group_id, workspace.key FROM s_gtf.workspace, s_gtf.workspace_group WHERE workspace.workspace_id = workspace_group.workspace_id ORDER BY workspace.workspace_id, workspace.name, workspace.description, workspace.subscription, workspace.fmw_file;
+                            -- Correction suite à discussion avec Yoann un gtf_user ne doit pas pouvoir lister tous les projets
+							REVOKE ALL ON s_gtf.v_workspace FROM gtf_user;
                           ]]>
                     </code>
                 </query>
+                <query>
+					<type>update</type>
+					<version>2018.02.01</version>
+                    <code>
+                        <![CDATA[ 
+                            -- Frédéric le 10/09/2018 12:00
+                            ALTER TABLE s_gtf.fme_engine ADD COLUMN fme_server_instance_name character varying(50);
+                            CREATE OR REPLACE VIEW s_gtf.v_fme_engine AS SELECT fme_engine.fme_engine_id, fme_engine.name, fme_engine.server_id, fme_engine.local_path, server.hostname AS server_name, fme_engine.server_url, fme_engine.login, fme_engine.password, fme_engine.fme_engine_type_id, fme_engine.s3_access_key_id, fme_engine.s3_secret_access_key, fme_engine.fme_cloud_api_token, v_fme_engine_type.fme_engine_type_label, v_fme_engine_type.lang, fme_engine.s3_region, fme_engine.iam_access_key_id, fme_engine.iam_secret_access_key, fme_engine.fme_server_instance_name FROM s_gtf.fme_engine LEFT JOIN s_gtf.server ON fme_engine.server_id = server.server_id LEFT JOIN s_gtf.v_fme_engine_type ON fme_engine.fme_engine_type_id::text = v_fme_engine_type.fme_engine_type_id::text;
+                            CREATE OR REPLACE RULE insert_v_fme_engine AS ON INSERT TO s_gtf.v_fme_engine DO INSTEAD  INSERT INTO s_gtf.fme_engine (fme_engine_id, name, server_id, local_path, server_url, login, password, fme_engine_type_id, s3_access_key_id, s3_secret_access_key, fme_cloud_api_token, s3_region, iam_access_key_id, iam_secret_access_key, fme_server_instance_name) VALUES (new.fme_engine_id, new.name, new.server_id, new.local_path, new.server_url, new.login, new.password, new.fme_engine_type_id, new.s3_access_key_id, new.s3_secret_access_key, new.fme_cloud_api_token, new.s3_region, new.iam_access_key_id, new.iam_secret_access_key, new.fme_server_instance_name);
+                            CREATE OR REPLACE RULE update_v_fme_engine AS ON UPDATE TO s_gtf.v_fme_engine DO INSTEAD  UPDATE s_gtf.fme_engine SET fme_engine_id = new.fme_engine_id, name = new.name, server_id = new.server_id, local_path = new.local_path, server_url = new.server_url, login = new.login, password = new.password, fme_engine_type_id = new.fme_engine_type_id, s3_access_key_id = new.s3_access_key_id, s3_secret_access_key = new.s3_secret_access_key, fme_cloud_api_token = new.fme_cloud_api_token, s3_region = new.s3_region, iam_access_key_id = new.iam_access_key_id, iam_secret_access_key = new.iam_secret_access_key, fme_server_instance_name = new.fme_server_instance_name WHERE fme_engine.fme_engine_id = new.fme_engine_id;
+
+                            -- Frédéric le 12/09/2018 15:15
+                            ALTER TABLE s_gtf.workspace ADD COLUMN version integer DEFAULT 0;
+                            CREATE FUNCTION s_gtf.update_workspace_version() RETURNS trigger    LANGUAGE plpgsql    AS $$  BEGIN  SELECT INTO new.version version + 1 FROM s_gtf.workspace WHERE workspace.workspace_id = new.workspace_id; return New;  END; $$;
+                            ALTER FUNCTION s_gtf.update_workspace_version() OWNER TO u_vitis;
+                            CREATE TRIGGER before_update_workspace BEFORE UPDATE ON s_gtf.workspace FOR EACH ROW EXECUTE PROCEDURE s_gtf.update_workspace_version();
+
+                            -- Frédéric le 13/09/2018 11:30
+                            ALTER TABLE s_gtf.fme_engine ADD COLUMN fme_server_s3_bucket character varying(50);
+                            CREATE OR REPLACE VIEW s_gtf.v_fme_engine AS SELECT fme_engine.fme_engine_id, fme_engine.name, fme_engine.server_id, fme_engine.local_path, server.hostname AS server_name, fme_engine.server_url, fme_engine.login, fme_engine.password, fme_engine.fme_engine_type_id, fme_engine.s3_access_key_id, fme_engine.s3_secret_access_key, fme_engine.fme_cloud_api_token, v_fme_engine_type.fme_engine_type_label, v_fme_engine_type.lang, fme_engine.s3_region, fme_engine.iam_access_key_id, fme_engine.iam_secret_access_key, fme_engine.fme_server_instance_name, fme_engine.fme_server_s3_bucket FROM s_gtf.fme_engine LEFT JOIN s_gtf.server ON fme_engine.server_id = server.server_id LEFT JOIN s_gtf.v_fme_engine_type ON fme_engine.fme_engine_type_id::text = v_fme_engine_type.fme_engine_type_id::text;
+                            CREATE OR REPLACE RULE insert_v_fme_engine AS ON INSERT TO s_gtf.v_fme_engine DO INSTEAD  INSERT INTO s_gtf.fme_engine (fme_engine_id, name, server_id, local_path, server_url, login, password, fme_engine_type_id, s3_access_key_id, s3_secret_access_key, fme_cloud_api_token, s3_region, iam_access_key_id, iam_secret_access_key, fme_server_instance_name, fme_server_s3_bucket) VALUES (new.fme_engine_id, new.name, new.server_id, new.local_path, new.server_url, new.login, new.password, new.fme_engine_type_id, new.s3_access_key_id, new.s3_secret_access_key, new.fme_cloud_api_token, new.s3_region, new.iam_access_key_id, new.iam_secret_access_key, new.fme_server_instance_name, new.fme_server_s3_bucket);
+                            CREATE OR REPLACE RULE update_v_fme_engine AS ON UPDATE TO s_gtf.v_fme_engine DO INSTEAD  UPDATE s_gtf.fme_engine SET fme_engine_id = new.fme_engine_id, name = new.name, server_id = new.server_id, local_path = new.local_path, server_url = new.server_url, login = new.login, password = new.password, fme_engine_type_id = new.fme_engine_type_id, s3_access_key_id = new.s3_access_key_id, s3_secret_access_key = new.s3_secret_access_key, fme_cloud_api_token = new.fme_cloud_api_token, s3_region = new.s3_region, iam_access_key_id = new.iam_access_key_id, iam_secret_access_key = new.iam_secret_access_key, fme_server_instance_name = new.fme_server_instance_name, fme_server_s3_bucket = new.fme_server_s3_bucket WHERE fme_engine.fme_engine_id = new.fme_engine_id;
+
+                            -- Anthony le 18/09/2018 14:43
+                            ALTER TABLE s_gtf.fme_engine ADD COLUMN useexternaldbconnection boolean DEFAULT FALSE;
+                            DROP VIEW s_gtf.v_fme_engine;
+                            CREATE OR REPLACE VIEW s_gtf.v_fme_engine AS SELECT fme_engine.fme_engine_id, fme_engine.name, fme_engine.server_id, fme_engine.local_path, server.hostname AS server_name, fme_engine.server_url, fme_engine.login, fme_engine.password, fme_engine.fme_engine_type_id, fme_engine.s3_access_key_id, fme_engine.s3_secret_access_key, fme_engine.fme_cloud_api_token, v_fme_engine_type.fme_engine_type_label, v_fme_engine_type.lang, fme_engine.s3_region, fme_engine.iam_access_key_id, fme_engine.iam_secret_access_key, fme_engine.fme_server_instance_name, fme_engine.fme_server_s3_bucket, useexternaldbconnection FROM s_gtf.fme_engine LEFT JOIN s_gtf.server ON fme_engine.server_id = server.server_id LEFT JOIN s_gtf.v_fme_engine_type ON fme_engine.fme_engine_type_id::text = v_fme_engine_type.fme_engine_type_id::text;
+                            ALTER TABLE s_gtf.v_fme_engine OWNER TO u_vitis;
+							GRANT SELECT ON TABLE s_gtf.v_fme_engine TO gtf_user;
+							GRANT ALL ON TABLE s_gtf.v_fme_engine TO u_vitis;
+							GRANT SELECT ON TABLE s_gtf.v_fme_engine TO gtf_author;
+							GRANT ALL ON TABLE s_gtf.v_fme_engine TO gtf_admin;
+                            CREATE OR REPLACE RULE insert_v_fme_engine AS ON INSERT TO s_gtf.v_fme_engine DO INSTEAD  INSERT INTO s_gtf.fme_engine (fme_engine_id, name, server_id, local_path, server_url, login, password, fme_engine_type_id, s3_access_key_id, s3_secret_access_key, fme_cloud_api_token, s3_region, iam_access_key_id, iam_secret_access_key, fme_server_instance_name, fme_server_s3_bucket, useexternaldbconnection) VALUES (new.fme_engine_id, new.name, new.server_id, new.local_path, new.server_url, new.login, new.password, new.fme_engine_type_id, new.s3_access_key_id, new.s3_secret_access_key, new.fme_cloud_api_token, new.s3_region, new.iam_access_key_id, new.iam_secret_access_key, new.fme_server_instance_name, new.fme_server_s3_bucket, new.useexternaldbconnection);
+                            CREATE OR REPLACE RULE update_v_fme_engine AS ON UPDATE TO s_gtf.v_fme_engine DO INSTEAD  UPDATE s_gtf.fme_engine SET fme_engine_id = new.fme_engine_id, name = new.name, server_id = new.server_id, local_path = new.local_path, server_url = new.server_url, login = new.login, password = new.password, fme_engine_type_id = new.fme_engine_type_id, s3_access_key_id = new.s3_access_key_id, s3_secret_access_key = new.s3_secret_access_key, fme_cloud_api_token = new.fme_cloud_api_token, s3_region = new.s3_region, iam_access_key_id = new.iam_access_key_id, iam_secret_access_key = new.iam_secret_access_key, fme_server_instance_name = new.fme_server_instance_name, fme_server_s3_bucket = new.fme_server_s3_bucket, useexternaldbconnection = new.useexternaldbconnection WHERE fme_engine.fme_engine_id = new.fme_engine_id;
+                            CREATE OR REPLACE RULE delete_v_fme_engine AS ON DELETE TO s_gtf.v_fme_engine DO INSTEAD DELETE FROM s_gtf.fme_engine WHERE fme_engine.fme_engine_id = old.fme_engine_id;
+
+                            -- Frédéric le 01/10/2018 16:30
+                            ALTER TABLE s_gtf."order" ADD COLUMN pid integer DEFAULT NULL;
+
+                            -- Frédéric le 04/10/2018 11:30
+                            UPDATE s_vitis.vm_table_button SET event = 'deleteGtfOrders' WHERE tab_id=(select tab_id from s_vitis.vm_tab where name = 'gtf_order') AND label_id='gtf_136';
+                            
+                            
+                            -- Frédéric le 11/10/2018 15:00
+                            INSERT INTO s_vitis.vm_string (string, string_id) VALUES ('Bouton d''arrêt d''une demande en cours table_button_id = 43', 'gtf_330');
+                            INSERT INTO s_vitis.vm_translation (translation_id, lang, translation) VALUES ('gtf_330', 'fr', 'Stopper le processus');
+                            INSERT INTO s_vitis.vm_translation (translation_id, lang, translation) VALUES ('gtf_330', 'en', 'Stop the process');
+                            INSERT INTO s_vitis.vm_table_button (button_class, table_button_id, event, label_id, ressource_id, tab_id) VALUES ('stopOrderProcessFlexigrid', (select nextval('s_vitis.seq_vm'::regclass)), 'stopOrderProcess', 'gtf_330', 'gtf/orders', (select tab_id from s_vitis.vm_tab where name = 'gtf_order'));
+                            INSERT INTO s_vitis.vm_string (string, string_id) VALUES ('"Order_status_id 7 de la table tr_order_staus (Stoppé)', 'gtf_331');
+                            INSERT INTO s_vitis.vm_translation (translation_id, lang, translation) VALUES ('gtf_331', 'fr', 'Stoppé');
+                            INSERT INTO s_vitis.vm_translation (translation_id, lang, translation) VALUES ('gtf_331', 'en', 'Stopped');
+                            INSERT INTO s_gtf.rt_order_status (order_status_id, label_id) VALUES (7, 'gtf_331');
+						]]>
+                    </code>
+                </query>
             </queriesCollection>
 </sqlQueries>
\ No newline at end of file
diff --git a/web_service/ws/FmeEngine.class.inc b/web_service/ws/FmeEngine.class.inc
old mode 100755
new mode 100644
index f51d5b2e..4e93af18
--- a/web_service/ws/FmeEngine.class.inc
+++ b/web_service/ws/FmeEngine.class.inc
@@ -28,7 +28,7 @@ class FmeEngine extends GTF {
      */
     function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
         parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
-        $this->aSelectedFields = Array("fme_engine_id", "name", "server_id", "local_path", "server_name", "fme_engine_type_id", "server_url", "login", "password", "s3_access_key_id", "s3_secret_access_key", "fme_cloud_api_token", "fme_engine_type_label", "s3_region", "iam_access_key_id", "iam_secret_access_key");
+        $this->aSelectedFields = Array("fme_engine_id", "name", "server_id", "local_path", "server_name", "fme_engine_type_id", "server_url", "login", "password", "s3_access_key_id", "s3_secret_access_key", "fme_cloud_api_token", "fme_engine_type_label", "s3_region", "iam_access_key_id", "iam_secret_access_key", 'fme_server_instance_name', 'fme_server_s3_bucket', "useexternaldbconnection");
     }
 
     /**
@@ -68,6 +68,80 @@ class FmeEngine extends GTF {
      *  )
      */
 
+    /**
+     * @SWG\Get(path="/fmeengines/{fme_engine_id}/instances/{instance_name}", 
+     *   tags={"FmeEngines"},
+     *   summary="Get Fme Server instance",
+     *   description="Request to get an instance of Fme Server on Fme Cloud",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="fme_engine_id",
+     *     in="path",
+     *     description="user id",
+     *     required=true,
+     *     type="integer",
+     *     format="int32"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="instance_name",
+     *     in="path",
+     *     description="name of the fme server instance",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/fmeengines")
+     *     )
+     *  )
+     */
+
+    /**
+     * @SWG\Get(path="/fmeengines/{fme_engine_id}/instances/{instance_name}/info", 
+     *   tags={"FmeEngines"},
+     *   summary="Get Fme Server instance information",
+     *   description="Request to get the FME Server build number and version on Fme Cloud",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="fme_engine_id",
+     *     in="path",
+     *     description="user id",
+     *     required=true,
+     *     type="integer",
+     *     format="int32"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="instance_name",
+     *     in="path",
+     *     description="name of the fme server instance",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/fmeengines")
+     *     )
+     *  )
+     */
+    
     /**
      * get informations about mode
      */
diff --git a/web_service/ws/FmeEngines.class.inc b/web_service/ws/FmeEngines.class.inc
old mode 100755
new mode 100644
index b62eff43..1ef27ae6
--- a/web_service/ws/FmeEngines.class.inc
+++ b/web_service/ws/FmeEngines.class.inc
@@ -15,6 +15,8 @@ require_once 'Gtf.class.inc';
 require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
 require_once 'FmeEngine.class.inc';
 require_once __DIR__ . '/../../class/vmlib/BdDataAccess.inc';
+require_once 'gtf_lib/FmeCloud.class.inc';
+require_once 'gtf_lib/FmeServer.class.inc';
 
 class FmeEngines extends GTF {
     /**
@@ -40,7 +42,7 @@ class FmeEngines extends GTF {
      */
     function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
         parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
-        $this->aSelectedFields = Array("fme_engine_id", "name", "server_id", "local_path", "server_name", "fme_engine_type_id", "server_url", "login", "password", "s3_access_key_id", "s3_secret_access_key", "fme_cloud_api_token", "fme_engine_type_label", "s3_region", "iam_access_key_id", "iam_secret_access_key");
+        $this->aSelectedFields = Array("fme_engine_id", "name", "server_id", "local_path", "server_name", "fme_engine_type_id", "server_url", "login", "password", "s3_access_key_id", "s3_secret_access_key", "fme_cloud_api_token", "fme_engine_type_label", "s3_region", "iam_access_key_id", "iam_secret_access_key", 'fme_server_instance_name', 'fme_server_s3_bucket', "useexternaldbconnection");
     }
 
     /**
@@ -120,7 +122,7 @@ class FmeEngines extends GTF {
      *   summary="Get FmeEngine test",
      *   description="Request to get FmeEnginetest by id",
      *   operationId="GET",
-     *   produces={"application/xml", "application/json"},
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
      *   @SWG\Parameter(
      *     name="token",
      *     in="query",
@@ -156,17 +158,31 @@ class FmeEngines extends GTF {
      * @return  FmeEngines
      */
     function GET() {
-        $aReturn = $this->genericGet($this->aProperties['schema_gtf'], "v_fme_engine", "fme_engine_id");
-        if (!empty($this->aPath[3]) && $this->aPath[3] == 'Test') {
-            if ($aReturn['sStatus'] == 1) {
-                // Test de validité de la licence FME.
-                $this->testFmeLicence();
-                $aXmlRacineAttribute['status'] = 1;
-                $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        // Instance FME Server sur Fme Cloud.
+        if (!empty($this->aPath[3]) && $this->aPath[3] == 'instances') {
+            if (empty($this->aPath[5])) {
+                $sMessage = $this->getFmeServerInstance($this->aPath[2], $this->aPath[4], $oFmeCloud);
+                return $sMessage;
+            }
+            else {
+                if ($this->aPath[5] == 'info')
+                    $sMessage = $this->getFmeServerInstanceInfo($this->aPath[2], $this->aPath[4]);
                 return $sMessage;
             }
-        } else
-            return $aReturn['sMessage'];
+        }
+        else {
+            $aReturn = $this->genericGet($this->aProperties['schema_gtf'], "v_fme_engine", "fme_engine_id");
+            if (!empty($this->aPath[3]) && $this->aPath[3] == 'Test') {
+                if ($aReturn['sStatus'] == 1) {
+                    // Test de validité de la licence FME.
+                    $this->testFmeLicence();
+                    $aXmlRacineAttribute['status'] = 1;
+                    $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                    return $sMessage;
+                }
+            } else
+                return $aReturn['sMessage'];
+        }
     }
 
     /**
@@ -175,7 +191,7 @@ class FmeEngines extends GTF {
      *   summary="Add FmeEngine",
      *   description="Request to add fmeengine",
      *   operationId="POST",
-     *   produces={"application/xml", "application/json"},
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
      *   @SWG\Parameter(
      *     name="token",
      *     in="formData",
@@ -236,7 +252,7 @@ class FmeEngines extends GTF {
      *   summary="Update FmeEngine",
      *   description="Request to update FmeEngine",
      *   operationId="PUT",
-     *   produces={"application/xml", "application/json"},
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
      *   @SWG\Parameter(
      *     name="token",
      *     in="query",
@@ -281,20 +297,108 @@ class FmeEngines extends GTF {
      *     )
      *  )
      */
+    
+    /**
+     * @SWG\Put(path="/fmeengines/{fme_engine_id}/instances/{instance_name}/start",
+     *   tags={"FmeEngines"},
+     *   summary="Start Fme Server instance",
+     *   description="Request to start an instance of Fme Server on Fme Cloud",
+     *   operationId="PUT",
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="fme_engine_id",
+     *     in="path",
+     *     description="id of the fme engine",
+     *     required=true,
+     *     type="integer",
+     *     format = "int32"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="instance_name",
+     *     in="path",
+     *     description="name of the fme server instance",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/fmeengines")
+     *     )
+     *  )
+     */
 
+    /**
+     * @SWG\Put(path="/fmeengines/{fme_engine_id}/instances/{instance_name}/pause",
+     *   tags={"FmeEngines"},
+     *   summary="Pause Fme Server instance",
+     *   description="Request to pause an instance of Fme Server on Fme Cloud",
+     *   operationId="PUT",
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="fme_engine_id",
+     *     in="path",
+     *     description="id of the fme engine",
+     *     required=true,
+     *     type="integer",
+     *     format = "int32"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="instance_name",
+     *     in="path",
+     *     description="name of the fme server instance",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/fmeengines")
+     *     )
+     *  )
+     */
+    
     /**
      * update fmeengine
      * @return id of the fmeengine if ok error object if ko
      */
     function PUT() {
-        $aReturn = $this->genericPut($this->aProperties['schema_gtf'], 'v_fme_engine', 'fme_engine_id');
-        if ($aReturn['sStatus'] == 1) {
-            $aXmlRacineAttribute['status'] = 1;
-            $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
-            $oFmeEngine = new FmeEngine($this->aPath, $this->aValues, $this->aProperties, $this->oConnection);
-            $oFmeEngine->GET();
-        } else {
-            $sMessage = $aReturn['sMessage'];
+        if (!empty($this->aPath[3])) {
+            if ($this->aPath[3] == 'instances') {
+                switch($this->aPath[5]) {
+                    case 'start':
+                        $sMessage = $this->startFmeServerInstance($this->aPath[2], $this->aPath[4]);
+                        break;
+                    case 'pause':
+                        $sMessage = $this->pauseFmeServerInstance($this->aPath[2], $this->aPath[4]);
+                        break;
+                }
+            }
+        }
+        else {
+            $aReturn = $this->genericPut($this->aProperties['schema_gtf'], 'v_fme_engine', 'fme_engine_id');
+            if ($aReturn['sStatus'] == 1) {
+                $aXmlRacineAttribute['status'] = 1;
+                $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                $oFmeEngine = new FmeEngine($this->aPath, $this->aValues, $this->aProperties, $this->oConnection);
+                $oFmeEngine->GET();
+            } else {
+                $sMessage = $aReturn['sMessage'];
+            }
         }
         return $sMessage;
     }
@@ -305,7 +409,7 @@ class FmeEngines extends GTF {
      *   summary="delete FmeEngine",
      *   description="Request to delete FmeEngine",
      *   operationId="DELETE",
-     *   produces={"application/xml", "application/json"},
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
      *   @SWG\Parameter(
      *     name="token",
      *     in="query",
@@ -333,7 +437,7 @@ class FmeEngines extends GTF {
      *   summary="delete FmeEngine",
      *   description="Request to delete FmeEngine",
      *   operationId="DELETE",
-     *   produces={"application/xml", "application/json"},
+     *   produces={"application/xml", "application/json", "application/x-vm-json"},
      *   @SWG\Parameter(
      *     name="token",
      *     in="query",
@@ -430,33 +534,203 @@ class FmeEngines extends GTF {
                 $this->getFmeLicence($this->aObjects[0]->aFields["local_path"]);
             break;
             case 'fme_server':
-                require 'gtf_lib/FmeServer.class.inc';
                 $oFmeServer = new FmeServer($this->aObjects[0]->aFields['server_url'], $this->aObjects[0]->aFields['login'], $this->aObjects[0]->aFields['password'], 'day', 1);
                 $oFmeServerLicenceStatus = $oFmeServer->getLicenceStatus();
-                $this->aObjects[0]->aFields['exists'] = true;
-                if ($oFmeServerLicenceStatus->isLicenseExpired === true)
-                    $this->aObjects[0]->aFields['expired'] = true;
-                else if ($oFmeServerLicenceStatus->isLicensed === false)
-                    $this->aObjects[0]->aFields['valid'] = false;
+                if ($oFmeServerLicenceStatus === false) {
+                    $this->aObjects[0]->aFields['exists'] = true;
+                    $this->aObjects[0]->aFields['request_error'] = true;
+                }
+                else if (empty($oFmeServerLicenceStatus))
+                    $this->aObjects[0]->aFields['exists'] = false;
                 else {
-                    // Info sur la licence de FME Server.
-                    //$this->aObjects[0]->aFields['exists'] = true;
-                    $this->aObjects[0]->aFields['valid'] = true;
-                    $sExpiryDate = $oFmeServerLicenceStatus->expiryDate;
-                    if (!empty($sExpiryDate))
-                        $sExpiryDate = substr($sExpiryDate, 6, 2) . '/' . substr($sExpiryDate, 4, 2) . '/' . substr($sExpiryDate, 0, 4);
-                    $this->aObjects[0]->aFields['validity'] = $sExpiryDate;
-                    // Info sur FME Server.
-                    $oFmeServerInfo = $oFmeServer->getInfo();
-                    $this->aObjects[0]->aFields['version'] = $oFmeServerInfo->build;
-                    $this->aObjects[0]->aFields['type'] = $oFmeServerInfo->version;
-                    $this->aObjects[0]->aFields['host'] = parse_url($this->aObjects[0]->aFields['server_url'], PHP_URL_HOST);
+                    $this->aObjects[0]->aFields['exists'] = true;
+                    if ($oFmeServerLicenceStatus->isLicenseExpired === true)
+                        $this->aObjects[0]->aFields['expired'] = true;
+                    else if ($oFmeServerLicenceStatus->isLicensed === false)
+                        $this->aObjects[0]->aFields['valid'] = false;
+                    else {
+                        // Info sur la licence de FME Server.
+                        //$this->aObjects[0]->aFields['exists'] = true;
+                        $this->aObjects[0]->aFields['valid'] = true;
+                        $sExpiryDate = $oFmeServerLicenceStatus->expiryDate;
+                        if (!empty($sExpiryDate))
+                            $sExpiryDate = substr($sExpiryDate, 6, 2) . '/' . substr($sExpiryDate, 4, 2) . '/' . substr($sExpiryDate, 0, 4);
+                        $this->aObjects[0]->aFields['validity'] = $sExpiryDate;
+                        // Info sur FME Server.
+                        $oFmeServerInfo = $oFmeServer->getInfo();
+                        $this->aObjects[0]->aFields['version'] = $oFmeServerInfo->build;
+                        $this->aObjects[0]->aFields['type'] = $oFmeServerInfo->version;
+                        $this->aObjects[0]->aFields['host'] = parse_url($this->aObjects[0]->aFields['server_url'], PHP_URL_HOST);
+                    }
                 }
             break;
-            case 'fme_cloud':
-                error_log(print_r($this->aObjects[0]->aFields, true));
-            break;
         }
     }
+
+    /**
+     * Get a Fme Server instance on Fme Cloud.
+     * @param {number} $iFmeEngineId Id of a Fme Engine.
+     * @param {string} $sFmeServerInstanceName Name of a Fme Server instance on Fme Cloud.
+     */
+    function getFmeServerInstance($iFmeEngineId, $sFmeServerInstanceName, &$oFmeCloud = null, &$aFmeEngine = array()) {
+        require $this->sRessourcesFile;
+        $iErrorId = 17;
+        $sErrorMessage = '';
+        // Paramètres du moteur Fme.
+        $aParams = array();
+        $aParams['sSchemaGtf'] = array('value' => $this->aProperties['schema_gtf'], 'type' => 'schema_name');
+        $aParams['fme_engine_id'] = array('value' => $iFmeEngineId, 'type' => 'number');
+        $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['getFmeEngine'], $aParams);
+        if ($this->oConnection->oBd->enErreur()) {
+            $iErrorId = 1;
+            $sErrorMessage = $this->oConnection->oBd->getBDMessage();
+        }
+        else if ($this->oConnection->oBd->nombreLigne($oPDOresult) > 0) {
+            $aFmeEngine = $this->oConnection->oBd->ligneSuivante($oPDOresult);
+            $oFmeCloud = new FmeCloud($aFmeEngine['server_url'], $aFmeEngine['fme_cloud_api_token']);
+            // Liste des occurrences de FME Server.
+            $aFmeServerInstances = $oFmeCloud->serviceRequest('instances');
+            if (!empty($aFmeServerInstances)) {
+                foreach($aFmeServerInstances as $oInstance) {
+                    if ($oInstance->name == $sFmeServerInstanceName)
+                        $oFmeServerInstance = $oInstance;
+                }
+                if (empty($oFmeServerInstance))
+                    $sErrorMessage = 'L\'instance FME Server "' . $sFmeServerInstanceName . '" n\'existe pas.';
+                else {
+                    $this->aFields['instance'] = $oFmeServerInstance;
+                }
+            }
+            else
+                $sErrorMessage ='Aucune instance FME Server n\'est disponible.';
+        }
+        else
+            $sErrorMessage = 'Le moteur FME spécifiée n\'existe pas.';
+        // Message de retour pour l'API Rest.
+        if (empty($sErrorMessage)) {
+            $aXmlRacineAttribute['status'] = 1;
+            $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        }
+        else {
+            $oError = new VitisError($iErrorId, $sErrorMessage);
+            $aXmlRacineAttribute['status'] = 0;
+            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        }
+        return $sMessage;
+    }
+
+    
+    /**
+     * Start a Fme Server instance on Fme Cloud.
+     * @param {number} $iFmeEngineId Id of a Fme Engine.
+     * @param {string} $sFmeServerInstanceName Name of a Fme Server instance on Fme Cloud.
+     */
+    function startFmeServerInstance($iFmeEngineId, $sFmeServerInstanceName) {
+        $sMessage = $this->getFmeServerInstance($iFmeEngineId, $sFmeServerInstanceName, $oFmeCloud);
+        $oReturn = json_decode($sMessage);
+        if ($oReturn->status == 1) {
+            // Démarrage de l'occurence si elle est en pause.
+            if ($oReturn->instance->state == 'PAUSED') {
+                if ($oFmeCloud->startInstance($oReturn->instance->id) === false)
+                    $sErrorMessage = 'L\'instance Fme Server n\'a pu être démarrée.' ;
+                else {
+                    $oFmeServerInstance = $oFmeCloud->serviceRequest('instances/' . $oReturn->instance->id);
+                    if ($oFmeServerInstance === false)
+                        $sErrorMessage = 'Erreur pendant le démarrage de l\'instance Fme Server.';
+                    else
+                        $this->aFields = array('instance' => $oFmeServerInstance);
+                }
+            }
+            else if ($oReturn->instance->state == 'RUNNING')
+                $sErrorMessage = 'L\'instance Fme Server est déja en cours d\'exécution.';
+            else if ($oReturn->instance->state == 'executing_action')
+                $sErrorMessage = 'Une action est en cours d\'exéution sur L\'instance Fme Server.';
+            else
+                $sErrorMessage = $oReturn->instance->state;
+            // Message de retour pour l'API Rest.
+            if (empty($sErrorMessage)) {
+                $aXmlRacineAttribute['status'] = 1;
+                $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            }
+            else {
+                $oError = new VitisError(17, $sErrorMessage);
+                $aXmlRacineAttribute['status'] = 0;
+                $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            }
+        }
+        return $sMessage;
+    }
+    
+    /**
+     * Pause a Fme Server instance on Fme Cloud.
+     * @param {number} $iFmeEngineId Id of a Fme Engine.
+     * @param {string} $sFmeServerInstanceName Name of a Fme Server instance on Fme Cloud.
+     */
+    function pauseFmeServerInstance($iFmeEngineId, $sFmeServerInstanceName) {
+        $sMessage = $this->getFmeServerInstance($iFmeEngineId, $sFmeServerInstanceName, $oFmeCloud);
+        $oReturn = json_decode($sMessage);
+        if ($oReturn->status == 1) {
+            // Mise en pause de l'occurence si elle est en cours d'éxecution.
+            if ($oReturn->instance->state == 'RUNNING') {
+                if ($oFmeCloud->pauseInstance($oReturn->instance->id) === false)
+                    $sErrorMessage = 'L\'instance Fme Server n\'a pu être arrêtée.' ;
+                else {
+                    $oFmeServerInstance = $oFmeCloud->serviceRequest('instances/' . $oReturn->instance->id);
+                    if ($oFmeServerInstance === false) 
+                        $sErrorMessage = 'Erreur pendant l\'arrêt de l\'instance Fme Server.';
+                    else
+                        $this->aFields = array('instance' => $oFmeServerInstance);
+                }
+            }
+            else if ($oReturn->instance->state == 'PAUSED')
+                $sErrorMessage = 'L\'instance Fme Server est déja à l\'arrêt';
+            else if ($oReturn->instance->state == 'executing_action')
+                $sErrorMessage = 'Une action est en cours d\'exécution sur L\'instance Fme Server.';
+            else
+                $sErrorMessage = $oReturn->instance->state;
+            // Message de retour pour l'API Rest.
+            if (empty($sErrorMessage)) {
+                $aXmlRacineAttribute['status'] = 1;
+                $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            }
+            else {
+                $oError = new VitisError(17, $sErrorMessage);
+                $aXmlRacineAttribute['status'] = 0;
+                $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            }
+        }
+        return $sMessage;
+    }
+    
+    /**
+     * Get Fme Server instance information on Fme Cloud.
+     * @param {number} $iFmeEngineId Id of a Fme Engine.
+     * @param {string} $sFmeServerInstanceName Name of a Fme Server instance on Fme Cloud.
+     */
+    function getFmeServerInstanceInfo($iFmeEngineId, $sFmeServerInstanceName) {
+        $sMessage = $this->getFmeServerInstance($iFmeEngineId, $sFmeServerInstanceName, $oFmeCloud, $aFmeEngine);
+        $oReturn = json_decode($sMessage);
+        if ($oReturn->status == 1) {
+            $oFmeServer = new FmeServer('https://' . $oReturn->instance->public_ip, $aFmeEngine['login'], $aFmeEngine['password'], 'day', 1);
+            $oInstanceInfo = $oFmeServer->getInfo();
+            if ($oInstanceInfo === false)
+                $sErrorMessage = 'Erreur pendant la requête de demande d\'information sur l\'instance Fme Server';
+            else {
+                $oInstanceInfo->host = $oReturn->instance->instance_url;
+                $this->aFields = array('info' => $oInstanceInfo);
+            }
+            // Message de retour pour l'API Rest.
+            if (empty($sErrorMessage)) {
+                $aXmlRacineAttribute['status'] = 1;
+                $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            }
+            else {
+                $oError = new VitisError(17, $sErrorMessage);
+                $aXmlRacineAttribute['status'] = 0;
+                $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            }
+        }
+        return $sMessage;
+    }
 }
 ?>
\ No newline at end of file
diff --git a/web_service/ws/Gtf.class.sql.inc b/web_service/ws/Gtf.class.sql.inc
old mode 100755
new mode 100644
index 0b57c593..724684fd
--- a/web_service/ws/Gtf.class.sql.inc
+++ b/web_service/ws/Gtf.class.sql.inc
@@ -23,6 +23,16 @@ $aSql['desactivateOrder'] = 'UPDATE [sSchemaGtf].order SET enabled = FALSE WHERE
 $aSql['getOrderPathFiles'] = 'SELECT log_url,result_url FROM [sSchemaGtf].v_order WHERE order_id = [order_id]';
 $aSql['getOrderWorkspace'] = 'SELECT workspace_id FROM [sSchemaGtf].v_order WHERE order_id = [order_id] LIMIT 1';
 $aSql['getOrderEngineStatus'] = 'SELECT gtf_engine.enabled FROM [sSchemaGtf]."order" LEFT JOIN [sSchemaGtf].gtf_engine ON "order".gtf_engine_id = gtf_engine.gtf_engine_id WHERE order_id = [order_id]';
+$aSql['getRunningOrders'] = 'SELECT order_id, gtf_engine_id FROM [sSchemaGtf]."order" WHERE order_status_id IN (1, 5)';
+$aSql['updateOrderStatus'] = 'UPDATE [sSchemaGtf].order SET order_status_id = [order_status_id] WHERE order_id = [order_id]';
+//$aSql['getOrdersToDelete'] = 'SELECT order_id, gtf_engine_id, order_status_id FROM [sSchemaGtf]."order" WHERE order_id IN([idList])';
+$aSql['getOrdersToDelete'] = 'SELECT fme_engine.fme_engine_type_id, "order".order_id, "order".gtf_engine_id, "order".order_status_id FROM [sSchemaGtf].order, [sSchemaGtf].gtf_engine, [sSchemaGtf].fme_engine WHERE gtf_engine.gtf_engine_id = "order".gtf_engine_id AND fme_engine.fme_engine_id = gtf_engine.fme_engine_id AND order_id IN([idList])';
+//$aSql['getOrderFmeEngine'] = 'SELECT fme_engine.fme_engine_type_id, fme_engine.server_url, fme_engine.login, fme_engine.password, fme_engine.fme_cloud_api_token, fme_engine.fme_server_instance_name, server.engines_home, v_order.gtf_engine_id FROM [sSchemaGtf].v_order, [sSchemaGtf].gtf_engine, [sSchemaGtf].fme_engine, [sSchemaGtf].server WHERE gtf_engine.gtf_engine_id = v_order.gtf_engine_id AND fme_engine.fme_engine_id = gtf_engine.fme_engine_id AND server.server_id = fme_engine.server_id AND order_id = [iOrderId] LIMIT 1';
+$aSql['getGtfEngineHomeFromOrderId'] = 'SELECT engines_home, "order".gtf_engine_id, "order".order_id FROM [sSchemaGtf]."server", [sSchemaGtf].gtf_engine, [sSchemaGtf]."order" WHERE gtf_engine.server_id = "server".server_id AND gtf_engine.gtf_engine_id = "order".gtf_engine_id AND order_id = [order_id]';
+$aSql['getGtfEngineHomeFromEngineId'] = 'SELECT engines_home, "order".gtf_engine_id, "order".order_id FROM [sSchemaGtf]."server", [sSchemaGtf].gtf_engine, [sSchemaGtf]."order" WHERE gtf_engine.server_id = "server".server_id AND gtf_engine.gtf_engine_id = "order".gtf_engine_id AND gtf_engine.gtf_engine_id = [iGtfEngineId]';
+$aSql['getFmeServerOrder'] = 'SELECT fme_engine.fme_engine_type_id, fme_engine.server_url, fme_engine.login, fme_engine.password, fme_engine.fme_cloud_api_token, fme_engine.fme_server_instance_name, "order".gtf_engine_id, "order".pid, server.engines_home, "order".log_url FROM [sSchemaGtf].order, [sSchemaGtf].gtf_engine, [sSchemaGtf].fme_engine, [sSchemaGtf].server WHERE gtf_engine.gtf_engine_id = "order".gtf_engine_id AND fme_engine.fme_engine_id = gtf_engine.fme_engine_id AND server.server_id = fme_engine.server_id AND order_id = [order_id] LIMIT 1';
+$aSql['getOrderPid'] = 'SELECT fme_engine.fme_engine_type_id, "order".gtf_engine_id, "order".pid FROM [sSchemaGtf]."order", [sSchemaGtf].gtf_engine, [sSchemaGtf].fme_engine, [sSchemaGtf].server WHERE gtf_engine.gtf_engine_id = "order".gtf_engine_id AND fme_engine.fme_engine_id = gtf_engine.fme_engine_id AND server.server_id = fme_engine.server_id AND order_id = [order_id] LIMIT 1';
+$aSql['getOrderFmeEngineType'] = 'SELECT fme_engine.fme_engine_type_id FROM [sSchemaGtf]."order", [sSchemaGtf].gtf_engine, [sSchemaGtf].fme_engine WHERE gtf_engine.gtf_engine_id = "order".gtf_engine_id AND fme_engine.fme_engine_id = gtf_engine.fme_engine_id AND order_id = [order_id] LIMIT 1';
 // UserSubscriptions
 $aSql['setSubscriptionEngineId'] = 'UPDATE [sSchemaGtf].subscription SET gtf_engine_id=[gtf_engine_id] WHERE subscription_id=[subscription_id]';
 $aSql['getUserSubscriptions'] = "SELECT order_id, label_name, CASE when v_user_subscription.enabled IS TRUE THEN '<img src=''./images/true.png'' />' ELSE '<img src=''./images/false.png'' />' END as enabled, order_date, '<img src=''./images/wk_params.png''  onmouseover=''loadTooltip(event,0,0,\"White\",\"#' || order_id || '\", \"' || replace(replace(replace(replace(wk_params,'\r\n', '<br/>'),'\\','\\\\'), '\"', '\\\"'),'''', '&#39;') || '\" )'' onmouseout=''unshow()''/>'  as wk_params, period.name as order_period_libelle, v_user_subscription.email_option_id, label_id, CASE WHEN email_notifications IS NOT NULL then '<img src=''./images/enveloppe.png'' onmouseover=''showTooltip(event,500,0,\"White\",\"#' || order_id || '\", \"' || replace(email_notifications, ';', '<br>') || '\" )'' onmouseout=''unshow()''/>' END as email_notifications, translation_email_notification.translation as notification FROM [sSchemaGtf].v_user_subscription LEFT JOIN [sSchemaGtf].period ON period.period_id = v_user_subscription.period_id LEFT JOIN [sSchemaGtf].rt_email_option on rt_email_option.email_option_id = v_user_subscription.email_option_id LEFT JOIN [sSchemaFramework].vm_translation translation_email_notification ON rt_email_option.label_id = translation_email_notification.translation_id WHERE translation_email_notification.lang = '[sLang]'";
@@ -56,4 +66,6 @@ $aSql['checkUserWorkspace'] = 'SELECT * FROM [sSchemaGtf].v_user_workspace WHERE
 // Workspaces
 $aSql['getWorkspaceLastSaveData'] = 'SELECT last_save_date, last_save_build FROM [sSchemaGtf].workspace WHERE workspace_id=[workspace_id]';
 $aSql['checkWorkspaceName'] = 'SELECT workspace_id FROM [sSchemaGtf].workspace WHERE name=[name]';
+// FmeEngines
+$aSql['getFmeEngine'] = 'SELECT * FROM [sSchemaGtf].fme_engine WHERE fme_engine_id = [fme_engine_id]';
 ?>
diff --git a/web_service/ws/Instance.class.inc b/web_service/ws/Instance.class.inc
index 6d6909fe..996c28c5 100755
--- a/web_service/ws/Instance.class.inc
+++ b/web_service/ws/Instance.class.inc
@@ -13,6 +13,7 @@
 require_once 'Gtf.class.inc';
 require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
 require_once __DIR__ . '/../../class/vmlib/BdDataAccess.inc';
+require_once ("gtf_lib/phpUtility.inc");
 
 class Instance extends GTF {
     /**
@@ -38,19 +39,20 @@ class Instance extends GTF {
      */
     function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
         parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
-        $this->aSelectedFields = Array('priority_id', 'priority_label');
+        $this->aSelectedFields = Array('instance_id');
     }
 
     /**
-     * @SWG\Get(path="/instance/calculate",
+     * @SWG\Post(path="/instance/generate",
      *   tags={"Instance"},
-     *   summary="Get instance id",
-     *   description="Request to get instance id",
-     *   operationId="GET",
+     *   summary="Generate a GTF instance id",
+     *   description="Request to generate a new instance id for GTF",
+     *   operationId="POST",
      *   produces={"application/xml", "application/json", "application/x-vm-json"},
+     *   consumes= { "multipart/form-data"},
      *   @SWG\Parameter(
      *     name="token",
-     *     in="query",
+     *     in="formData",
      *     description="user token",
      *     required=true,
      *     type="string"
@@ -64,45 +66,16 @@ class Instance extends GTF {
      */
 
     /**
-     * get Instance
-     * @return  Instance
+     * Generate a GTF instance
+     * @return id of the workspace created
      */
-    function GET() {
-        if (!empty($this->aPath[2])) {
-            if ($this->aPath[2] == 'calculate') {
-            }
+    function POST() {
+        if ($this->aPath[2] == 'generate') {
+            $this->aFields['instance_id'] = generateGtfInstanceId();
+            $aXmlRacineAttribute['status'] = 1;
+            $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            return $sMessage;
         }
-        $this->calculateGtfInstanceId();
-        $aXmlRacineAttribute['status'] = 1;
-        $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
-        return $sMessage;
     }
-    
-    /**
-     * Calculating a GTF instance id.
-     */
-    function calculateGtfInstanceId() {
-        $aOutput = array();
-        $iReturnStatus = 1;
-        if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
-            // Paramètres à concaténer pour un identifiant unique par machine.
-            $aCommands = array(
-                'NICCONFIG',    // cartes réseaux (adresses MAC)
-                'CPU',  // modèle, vitesse, id...
-                'DISKDRIVE',    // N° de série...
-                'MEMORYCHIP',
-                'CDROM',    // Lecteur DVD...
-                'path win32_VideoController',   // Carte vidéo
-                'IDECONTROLLER',
-                'SCSICONTROLLER',
-                'DESKTOPMONITOR',
-                'LOGON',
-                'NETLOGIN'
-            );
-            $sCommandLine = 'wmic '. implode(' & wmic ', $aCommands);
-        }
-        exec($sCommandLine, $aOutput, $iReturnStatus);
-        $this->aFields['instance_id'] = hash_hmac('sha256', implode(chr(20), $aOutput), uniqid('', true));
-    }    
 }
 ?>
\ No newline at end of file
diff --git a/web_service/ws/Message.class.inc b/web_service/ws/Message.class.inc
index 115aebd4..062dd634 100755
--- a/web_service/ws/Message.class.inc
+++ b/web_service/ws/Message.class.inc
@@ -28,7 +28,7 @@ class Message extends GTF {
      */
     function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
         parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
-        $this->aSelectedFields = Array('message_id', 'messageclass', 'creation_date', 'body', 'sender', 'messageclass_type', 'status');
+        $this->aSelectedFields = Array('message_id', 'messageclass', $this->getDateSelectedFields('creation_date', 'yeartosecond'), 'body', 'sender', 'messageclass_type', 'status', $this->getDateSelectedFields('minexecdate', 'yeartosecond'));
     }
 
     /**
diff --git a/web_service/ws/Messages.class.inc b/web_service/ws/Messages.class.inc
index 92a71bdf..b53ab2fc 100755
--- a/web_service/ws/Messages.class.inc
+++ b/web_service/ws/Messages.class.inc
@@ -34,13 +34,13 @@ class Messages extends GTF {
      * construct
      * @param type $aPath url of the request
      * @param type $aValues parameters of the request
-     * @param type $properties properties
-     * @param type $bShortcut false to reinit variables
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
      * @param type $oConnection connection object
      */
     function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
         parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
-        $this->aSelectedFields = Array('message_id', 'messageclass', 'creation_date', 'body', 'sender', 'messageclass_type', 'status');
+        $this->aSelectedFields = Array('message_id', 'messageclass', $this->getDateSelectedFields('creation_date', 'yeartosecond'), 'body', 'sender', 'messageclass_type', 'status', $this->getDateSelectedFields('minexecdate', 'yeartosecond'));
     }
 
     /**
diff --git a/web_service/ws/Order.class.inc b/web_service/ws/Order.class.inc
old mode 100755
new mode 100644
index 8bc3193b..4888332c
--- a/web_service/ws/Order.class.inc
+++ b/web_service/ws/Order.class.inc
@@ -15,7 +15,6 @@ require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
  * 
  */
 class Order extends GTF {
-
     public $oError;
 
     /**
@@ -28,7 +27,7 @@ class Order extends GTF {
      */
     function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
         parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
-        $this->aSelectedFields = Array("order_id", "priority_id", "workspace_id", "workspace_key", "label_name", "order_status_id", "user_id", "login", "period_id", "order_period_libelle", "wk_params", "result_url", "order_date", "log_url", "execution_date", "attempt", "email_notifications", "email_option_id", "deleted", "gtf_engine_id", "length_sec", "priority_label", "email_option_label");
+        $this->aSelectedFields = Array("order_id", "priority_id", "workspace_id", "workspace_key", "label_name", "order_status_id", "user_id", "login", "period_id", "order_period_libelle", "wk_params", "result_url", $this->getDateSelectedFields('order_date', 'yeartosecond'), "log_url", $this->getDateSelectedFields('execution_date', 'yeartosecond'), "attempt", "email_notifications", "email_option_id", "deleted", "gtf_engine_id", "length_sec", "email_option_label", $this->getDateSelectedFields('minexecdate', 'yeartosecond'));
     }
 
     /**
diff --git a/web_service/ws/Orders.class.inc b/web_service/ws/Orders.class.inc
index 53ce8af5..352904e1 100644
--- a/web_service/ws/Orders.class.inc
+++ b/web_service/ws/Orders.class.inc
@@ -15,6 +15,8 @@ require_once 'Gtf.class.inc';
 require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
 require_once 'Order.class.inc';
 require_once __DIR__ . '/../../class/vmlib/BdDataAccess.inc';
+require_once 'gtf_lib/FmeServer.class.inc';
+require_once 'gtf_lib/FmeCloud.class.inc';
 
 class Orders extends GTF {
     /**
@@ -40,7 +42,7 @@ class Orders extends GTF {
      */
     function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
         parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
-        $this->aSelectedFields = Array("order_id", "priority_id", "workspace_id", "workspace_key", "label_name", "order_status_id", "user_id", "login", "period_id", "order_period_libelle", "wk_params", "result_url", "to_char(order_date, 'YYYY-MM-DD HH24:MI:SS') as order_date", "log_url", "to_char(execution_date, 'YYYY-MM-DD HH24:MI:SS') as execution_date", "attempt", "email_notifications", "email_option_id", "deleted", "gtf_engine_id", "length_sec", "priority_label", "email_option_label", "order_status_label", "concat(gtf_engine_id, ' - ', name) as name");
+        $this->aSelectedFields = Array("order_id", "priority_id", "workspace_id", "workspace_key", "label_name", "order_status_id", "user_id", "login", "period_id", "order_period_libelle", "wk_params", "result_url", $this->getDateSelectedFields('order_date', 'yeartosecond'), "log_url", $this->getDateSelectedFields('execution_date', 'yeartosecond'), "attempt", "email_notifications", "email_option_id", "deleted", "gtf_engine_id", "length_sec", "email_option_label", "order_status_label", "concat(gtf_engine_id, ' - ', name) as name", $this->getDateSelectedFields('minexecdate', 'yeartosecond'));
     }
 
     /**
@@ -116,19 +118,47 @@ class Orders extends GTF {
      *  )
      */
 
+    /**
+     * @SWG\Get(path="/orders/running",
+     *   tags={"Orders"},
+     *   summary="Get running orders",
+     *   description="Request to get all the running orders",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Properties Response",
+     *         @SWG\Schema(ref="#/definitions/orders")
+     *     )
+     *  )
+     */
+    
     /**
      * get Orders
      * @return  Orders
      */
     function GET() {
-        if (in_array('gtf_admin', $this->oConnection->aPrivileges) || in_array('gtf_author', $this->oConnection->aPrivileges))
-            $aReturn = $this->genericGet($this->aProperties['schema_gtf'], "v_order_fast", "order_id");
+        if (!empty($this->aPath[2]) && $this->aPath[2] == "running")
+            $sMessage = $this->getRunningOrders();
         else {
-            $oError = new VitisError(12, "You don't have the rights to get orders");
-            $aXmlRacineAttribute['status'] = 0;
-            $aReturn['sMessage'] = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            if (in_array('gtf_admin', $this->oConnection->aPrivileges))
+                $aReturn = $this->genericGet($this->aProperties['schema_gtf'], "v_order_fast", "order_id");
+            else {
+                $oError = new VitisError(12, "You don't have the rights to get orders");
+                $aXmlRacineAttribute['status'] = 0;
+                $aReturn = array();
+                $aReturn['sMessage'] = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            }
+            $sMessage = $aReturn['sMessage'];
         }
-        return $aReturn['sMessage'];
+        return $sMessage;
     }
 
     /**
@@ -252,19 +282,62 @@ class Orders extends GTF {
      *  )
      */
 
+    /**
+     * @SWG\Put(path="/orders/{order_id}/stop",
+     *   tags={"Orders"},
+     *   summary="Stop order",
+     *   description="Request to stop an order",
+     *   operationId="PUT",
+     *   produces={"application/xml", "application/json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Parameter(
+     *     name="order_id",
+     *     in="path",
+     *     description="Order id",
+     *     required=true,
+     *     type="integer",
+     *     format = "int32"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/orders")
+     *     )
+     *  )
+     */
+    
     /**
      * update order
      */
     function PUT() {
         if (!empty($this->aPath[2])) {
-            if ($this->aPath[2] == "gtfengine")
-                $aReturn = $this->setOrderGtfEngine();
-            else if ($this->aPath[2] == "reset")
-                $aReturn = $this->resetOrder();
-            else if ($this->aPath[2] == "activate")
-                $aReturn = $this->activateOrder();
-            else if ($this->aPath[2] == "desactivate")
-                $aReturn = $this->desactivateOrder();
+            if (!empty($this->aPath[3])) {
+                // Arrêt d'une demande en cours.
+                if ($this->aPath[3] == 'stop')
+                    $aReturn = $this->stopFmeOrder($this->aValues["my_vitis_id"]);
+            }
+            else {
+                switch ($this->aPath[2]) {
+                    case 'gtfengine':
+                        $aReturn = $this->setOrderGtfEngine();
+                        break;
+                    case 'reset':
+                        $aReturn = $this->resetOrder();
+                        break;
+                    case 'activate':
+                        $aReturn = $this->activateOrder();
+                        break;
+                    case 'desactivate':
+                        $aReturn = $this->desactivateOrder();
+                        break;
+                }
+            }
             $aXmlRacineAttribute['status'] = $aReturn['status'];
             if ($aReturn['status'] == 1)
                 $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
@@ -411,6 +484,9 @@ class Orders extends GTF {
                 $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
             }
         } else {
+            // Stoppe les demandes en cours (Fme Server -> supprime le traitement et le répertoire des données).
+            $this->deleteFmeOrders();
+            //
             $aReturn = $this->genericDelete($this->aProperties['schema_gtf'], 'order', 'order_id');
             $sMessage = $aReturn['sMessage'];
         }
@@ -465,6 +541,20 @@ class Orders extends GTF {
      */
     function resetOrder() {
         require $this->sRessourcesFile;
+        // Supprime l'ancien résultat.
+        $aParams['sSchemaGtf'] = array('value' => $this->aProperties['schema_gtf'], 'type' => 'schema_name');
+        $aParams['idList'] = array('value' => $this->aValues['idList'], 'type' => 'group');
+        $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['getOrders'], $aParams);
+        if ($this->oConnection->oBd->enErreur())
+            $aReturn = array('status' => 0, 'message' => $this->oConnection->oBd->getBDMessage(), 'error_code' => 1);
+        else {
+            while ($aDemande = $this->oConnection->oBd->ligneSuivante($oPDOresult)) {
+                $aFolder = explode("/", $aDemande['log_url']);
+                $sFolder = $this->aProperties['dir_export'] . "/gtf/" . $aFolder[0];
+                clearDir($sFolder);
+            }
+        }
+        // Réinitialise la demande.
         $aOrderId = explode('|', $this->aValues['idList']);
         foreach ($aOrderId as $iOrderId) {
             // Vérifie si le moteur déja assigné est actif.
@@ -529,7 +619,6 @@ class Orders extends GTF {
      * \param $sTable Name of the table.
      * \param $iWorkspaceId Identifier of the treatment.
      */
-
     function getIdEngine($iUserOrderId, $sTable, $iWorkspaceId) {
         require $this->sRessourcesFile;
         // Récupération de l'algorithme
@@ -588,5 +677,330 @@ class Orders extends GTF {
         }
         return $iEngine;
     }
+    
+    /**
+     * function getRunningOrders
+     */
+    function getRunningOrders() {
+        require $this->sRessourcesFile;
+        // Liste des demandes.
+        $aParams = array();
+        $aParams['sSchemaGtf'] = array('value' => $this->aProperties['schema_gtf'], 'type' => 'schema_name');
+        $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['getRunningOrders'], $aParams);
+        if ($this->oConnection->oBd->enErreur()) {
+            $oError = new VitisError(1, $this->oConnection->oBd->getBDMessage());
+            $aXmlRacineAttribute['status'] = 0;
+            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        }
+        else {
+            $aOrders = array();
+            while ($aOrder = $this->oConnection->oBd->ligneSuivante($oPDOresult))
+                $aOrders['orders'][] = $aOrder['order_id'];
+            $this->aFields = $aOrders;
+            $aXmlRacineAttribute['status'] = 1;
+            $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        }
+        return $sMessage;
+    }
+    
+    /**
+     * function deleteFmeOrders
+     */
+    function deleteFmeOrders() {
+        require $this->sRessourcesFile;
+        // Infos des demandes à supprimer.
+        $aParams['sSchemaGtf'] = array('value' => $this->aProperties['schema_gtf'], 'type' => 'schema_name');
+        $aParams['idList'] = array('value' => $this->aValues['idList'], 'type' => 'group');
+        $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['getOrdersToDelete'], $aParams);
+        if (!$this->oConnection->oBd->enErreur()) {
+            while ($aDemande = $this->oConnection->oBd->ligneSuivante($oPDOresult)) {
+                $aRunningJob = array();
+                if ($aDemande['order_status_id'] == 5) {
+                    // Paramètres de la demande si c'est un traitement asynchrone sur Fme server.
+                    if ($aDemande['fme_engine_type_id'] != "desktop") {
+                        $aRunningJobs = $this->getFmeServerRunningJobs($aDemande['gtf_engine_id']);
+                        $aRunningJob = $this->getFmeServerRunningJob($aDemande['order_id'], $aRunningJobs);
+                    }
+                    // Stoppe la demande en cours.
+                    $this->stopFmeOrder($aDemande['order_id']);
+                }
+                // Supprime le traitement sur Fme Server.
+                if ($aDemande['fme_engine_type_id'] != "desktop")
+                    $this->deleteFmeServerOrder($aDemande['order_id'], $aDemande['gtf_engine_id'], $aRunningJob);
+            }
+        }
+    }
+    
+    /**
+     * function deleteFmeServerOrder
+     * \param $iOrderId Id of the Gtf order.
+     * \param $iGtfEngineId Id of the Gtf engine.
+     * \param $aRunningJob A running job on Fme Server.
+     */
+    function deleteFmeServerOrder($iOrderId, $iGtfEngineId, $aRunningJob = array()) {
+        $sEngineLogFilePath = $this->aProperties['vas_home'] . '/log/engines/' . date($this->aProperties['log_period']) . '/engine_' . $iGtfEngineId . '/engine.log';
+        if (!empty($aRunningJob)) {
+            // Demande en cours -> informations de connexion sur Fme Server dans la liste des traitements asynchrones.
+            $sFmeServerUrl = $aRunningJob['fme_server_url'];
+            $sLogin = $aRunningJob['login'];
+            $sPassword = $aRunningJob['password'];
+            $sResource = $aRunningJob['resource'];
+            $sPath = $aRunningJob['path'];
+            $iJobId = $aRunningJob['job_id'];
+        }
+        else {
+            // Demande en attente ou terminée -> informations de connexion sur Fme Server dans la base.
+            require $this->sRessourcesFile;
+            $aParams = array();
+            $aParams['sSchemaGtf'] = array('value' => $this->aProperties['schema_gtf'], 'type' => 'schema_name');
+            $aParams['order_id'] = array('value' => $iOrderId, 'type' => 'number');
+            $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['getFmeServerOrder'], $aParams);
+            if (!$this->oConnection->oBd->enErreur()) {
+                $aOrder = $this->oConnection->oBd->ligneSuivante($oPDOresult);
+                require $aOrder['engines_home'] . '/' . 'string.inc';
+                // Si Fme Cloud -> l'instance de Fme Server doit être démarrée.
+                if ($aOrder['fme_engine_type_id'] == 'fme_cloud') {
+                    // Ip de l'instance Fme Server.
+                    $oFmeCloud = new FmeCloud($aOrder['server_url'], $aOrder['fme_cloud_api_token']);
+                    $oFmeCloud->sLogFilePath = $sEngineLogFilePath;
+                    // Adresse Ip publique de l'instance de FME Server.
+                    $aFmeServerInstances = $oFmeCloud->serviceRequest('instances');
+                    if (!empty($aFmeServerInstances)) {
+                        foreach($aFmeServerInstances as $oInstance) {
+                            if ($oInstance->name == $aOrder['fme_server_instance_name'])
+                                $oFmeServerInstance = $oInstance;
+                        }
+                        if (empty($oFmeServerInstance)) {
+                            // Aucune instace active.
+                            writeToLog(INFO_FME_CLOUD_INSTANCE_NOT_FOUND, $sEngineLogFilePath);
+                        }
+                        else {
+                            // Statut de l'instance.
+                            writeToLog(INFO_FME_CLOUD_INSTANCE_STATUS . $oFmeServerInstance->state, $sEngineLogFilePath);
+                            $sFmeServerUrl = 'https://' . $oFmeServerInstance->public_ip;
+                            // Pas de suppression possible si l'instance n'est pas démarrée.
+                            if ($oFmeServerInstance->state != "RUNNING")
+                                return false;
+                        }
+                    }
+                }
+                $sLogin = $aOrder['login'];
+                $sPassword = $aOrder['password'];
+                $sResource = 'FME_SHAREDRESOURCE_TEMP';
+                if (!empty($aOrder['log_url']))
+                    $sPath = dirname($this->aProperties["gtf_instance_id"] . '/' . pathinfo($aOrder['log_url'], PATHINFO_DIRNAME));
+                $iJobId = $aOrder['pid'];
+            }
+        }
+        // Suppression du traitement et du répertoire sur Fme Server.
+        if (!empty($sFmeServerUrl) && !empty($sLogin) && !empty($sPassword)) {
+            $oFmeServer = new FmeServer($sFmeServerUrl, $sLogin, $sPassword);
+            $oFmeServer->sLogFilePath = $sEngineLogFilePath;
+            if (!empty($iJobId))
+                if ($oFmeServer->deleteJob($iJobId) === false)
+                    return false;
+            // Supprime le répertoire des ressources de la demande sur Fme Server.
+            if (!empty($sResource) && !empty($sPath))
+                if ($oFmeServer->serviceRequest('resources/connections/' . $sResource . '/filesys/' . $sPath, 'delete') === false)
+                    return false;
+        }
+    }
+    
+    /**
+     * function stopFmeOrder
+     * \param $iOrderId Id of the Gtf order.
+     */
+    function stopFmeOrder($iOrderId) {
+        require $this->sRessourcesFile;
+        // Informations de la demande à stopper.
+        $aParams = array();
+        $aParams['sSchemaGtf'] = array('value' => $this->aProperties['schema_gtf'], 'type' => 'schema_name');
+        $aParams['order_id'] = array('value' => $iOrderId, 'type' => 'number');
+        $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['getOrderFmeEngineType'], $aParams);
+        if (!$this->oConnection->oBd->enErreur()) {
+            $aOrder = $this->oConnection->oBd->ligneSuivante($oPDOresult);
+            if ($aOrder['fme_engine_type_id'] == 'desktop') {
+                if ($this->stopFmeDesktopOrderProcess($iOrderId) === false)
+                    $sErrorMessage = ERROR_0037;
+            }
+            else {
+                if ($this->stopFmeServerOrder($iOrderId) === false)
+                    $sErrorMessage = ERROR_0038;
+            }
+            // Message de retour pour l'API Rest.
+            if (empty($sErrorMessage)) {
+                $aReturn = array('status' => 1, 'message' => '');
+                // Mise à jour du statut de la demande (stoppé).
+                $aParams = array();
+                $aParams['sSchemaGtf'] = array('value' => $this->aProperties['schema_gtf'], 'type' => 'schema_name');
+                $aParams['order_id'] = array('value' => $iOrderId, 'type' => 'number');
+                $aParams['order_status_id'] = array('value' => 7, 'type' => 'number');
+                $this->oConnection->oBd->executeWithParams($aSql['updateOrderStatus'], $aParams);
+            }
+            else
+                $aReturn = array('status' => 0, 'message' => $sErrorMessage, 'error_code' => 17);
+            return $aReturn;
+        }
+    }
+    
+    /**
+     * function stopFmeDesktopOrderProcess
+     * \param $iOrderId Id of the Gtf order.
+     */
+    function stopFmeDesktopOrderProcess($iOrderId) {
+        require $this->sRessourcesFile;
+        $aParams = array();
+        $aParams['sSchemaGtf'] = array('value' => $this->aProperties['schema_gtf'], 'type' => 'schema_name');
+        $aParams['order_id'] = array('value' => $iOrderId, 'type' => 'number');
+        $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['getGtfEngineHomeFromOrderId'], $aParams);
+        if (!$this->oConnection->oBd->enErreur()) {
+            $aGtfEngineHome = $this->oConnection->oBd->ligneSuivante($oPDOresult);
+            $sPidFilePath = $aGtfEngineHome['engines_home'] . '/' . 'pid_' . $aGtfEngineHome['gtf_engine_id'] . '.txt';
+            if (file_exists($sPidFilePath)) {
+                $iPid = file_get_contents($sPidFilePath);
+                if (is_numeric($iPid)) {
+                    if (strtolower(substr(PHP_OS, 0, 3)) == 'win') {
+                        // Supprime le processus "engine.exe".
+                        $this->killProcess($iPid);
+                        // Tue tous les processus liés à une demande et un traitement sur Fme Desktop.
+                        $aProcessName = array('cmd.exe', 'php.exe', 'cmd.exe', 'fme.exe');
+                        foreach ($aProcessName as $sProcessName) {
+                            $iPid = $this->getChildProcess($iPid, $sProcessName);
+                            if ($iPid !== false)
+                                $this->killProcess($iPid);
+                        }
+                    }
+                    else {
+                        // Supprime tous les processus enfants.
+                        $aResult = array();
+                        $sResultCommande = exec('pkill -9 -P ' . $iPid, $aResult, $iResult);
+                        // Supprime le processus du moteur.
+                        $this->killProcess($iPid);
+                    }
+                }
+                // Suppression du fichier contenant le pid du processus "engine.exe".
+                unlink($sPidFilePath);
+            }
+        }
+    }    
+    
+    /**
+     * function killProcess
+     * \param $iPid Id of the process.
+     */
+    function killProcess($iPid) {
+        $aResult = array();
+        if (strtolower(substr(PHP_OS, 0, 3)) == 'win')
+            $sResultCommande = exec('taskkill /PID ' . $iPid . ' /F', $aResult, $iResult);
+        else
+            $sResultCommande = exec('kill ' . $iPid, $aResult, $iResult);
+        // Log si erreur.
+        if ($iResult !== 0)
+            writeToErrorLog(ERROR_0035 . ' (pid = ' . $iPid . ').');
+    }
+    
+    /**
+     * function getChildProcess
+     * \param $iParentPid Id of the parent process.
+     * \param $sProcessName Name of the process.
+     */
+    function getChildProcess($iParentPid, $sProcessName) {
+        $aResult = array();
+        if (strtolower(substr(PHP_OS, 0, 3)) == 'win')
+            $sResultCommande = exec('wmic process where "ParentProcessId=' . $iParentPid . ' AND Name=\'' . $sProcessName . '\'" get ProcessId', $aResult, $iResult);
+        //else
+            //$sResultCommande = exec('' . $iParentPid, $aResult, $iResult);
+            //ps -o ppid=
+        // Log si erreur.
+        if ($iResult !== 0)
+            writeToErrorLog(ERROR_0036 . ' (pid = ' . $iPid . ').');
+        else if ($iResult == 0 && !empty($aResult) && is_numeric($aResult[1]))
+            return $aResult[1];
+        else
+            return false;
+    }
+    
+    /**
+     * function stopFmeServerOrder
+     * \param $iOrderId Id of the Gtf order.
+     */
+    function stopFmeServerOrder($iOrderId) {
+        require $this->sRessourcesFile;
+        // Récupère le répertoire des moteurs de GTF.
+        $aParams = array();
+        $aParams['sSchemaGtf'] = array('value' => $this->aProperties['schema_gtf'], 'type' => 'schema_name');
+        $aParams['order_id'] = array('value' => $iOrderId, 'type' => 'number');
+        $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['getGtfEngineHomeFromOrderId'], $aParams);
+        if (!$this->oConnection->oBd->enErreur()) {
+            $aGtfEngineHome = $this->oConnection->oBd->ligneSuivante($oPDOresult);
+            // Stoppe le traitement sur Fme Server.
+            $sAsyncOrdersFilePath = $aGtfEngineHome['engines_home'] . '/' . 'gtf_engine' . $aGtfEngineHome['gtf_engine_id'] . '_jobid.txt';
+            if (file_exists($sAsyncOrdersFilePath)) {
+                $aRunningJobs = unserialize(file_get_contents($sAsyncOrdersFilePath));
+                $aRunningJob = $this->getFmeServerRunningJob($iOrderId, $aRunningJobs);
+                if ($aRunningJob !== false && !empty($aRunningJob['job_id'])) {
+                    $sEngineLogFilePath = $this->aProperties['vas_home'] . '/log/engines/' . date($this->aProperties['log_period']) . '/engine_' . $aGtfEngineHome['gtf_engine_id'] . '/engine.log';
+                    $oFmeServer = new FmeServer($aRunningJob['fme_server_url'], $aRunningJob['login'], $aRunningJob['password'], 'day', 1);
+                    $oFmeServer->sLogFilePath = $sEngineLogFilePath;
+                    $oFmeServer->stopJob($aRunningJob['job_id']);
+                    // Supprime le traitement dans la liste des demandes asynchrones.
+                    $iJobIndex = null;
+                    foreach ($aRunningJobs as $iIndex => $aRunningJob) {
+                        if ($aRunningJob['order_id'] == $iOrderId) {
+                            $iJobIndex = $iIndex;
+                            break;
+                        }
+                    }
+                    if ($iJobIndex !== null) {
+                        // Sauve la liste des demandes asynchrones en cours.
+                        $aRunningJob = array_splice($aRunningJobs, $iJobIndex, 1)[0];
+                        if (empty($aRunningJobs))
+                            unlink($sAsyncOrdersFilePath);
+                        else
+                            file_put_contents($sAsyncOrdersFilePath, serialize($aRunningJobs));
+                        // Log.
+                        require $aGtfEngineHome['engines_home'] . '/' . 'string.inc';
+                        writeToLog(INFO_FME_SERVER_ASYNCHRONOUS_JOB_REMOVED_FROM_LIST . " (demande $iOrderId).", $sEngineLogFilePath);
+                    }
+                }
+            }
+        }
+    }
+    
+    /**
+     * Retourne les infos d'un traitement asynchrones en cours d'exécution.
+     * @param {number} $iOrderId I de la demande en cours.
+     * @param {array} $aRunningJobs Tableau contenant la liste des traitements asynchrones en cours d'exécution.
+     * return array
+     */
+    function getFmeServerRunningJob($iOrderId, $aRunningJobs) {
+        foreach ($aRunningJobs as $aRunningJob) {
+            if ($aRunningJob['order_id'] == $iOrderId)
+                return $aRunningJob;
+        }
+        return false;
+    }
+    
+    /**
+     * Retourne la liste des traitements asynchrones en cours d'exécution d'un moteur GTF.
+     * @param {number} $iGtfEngineId Id du moteur GTF.
+     * return array
+     */
+    function getFmeServerRunningJobs($iGtfEngineId) {
+        require $this->sRessourcesFile;
+        // Récupère le répertoire des moteurs de GTF.
+        $aRunningJobs = array();
+        $aParams = array();
+        $aParams['sSchemaGtf'] = array('value' => $this->aProperties['schema_gtf'], 'type' => 'schema_name');
+        $aParams['iGtfEngineId'] = array('value' => $iGtfEngineId, 'type' => 'number');
+        $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['getGtfEngineHomeFromEngineId'], $aParams);
+        if (!$this->oConnection->oBd->enErreur()) {
+            $aGtfEngineHome = $this->oConnection->oBd->ligneSuivante($oPDOresult);
+            $sAsyncOrdersFilePath = $aGtfEngineHome['engines_home'] . '/' . 'gtf_engine' . $aGtfEngineHome['gtf_engine_id'] . '_jobid.txt';
+            if (file_exists($sAsyncOrdersFilePath))
+                $aRunningJobs = unserialize(file_get_contents($sAsyncOrdersFilePath));
+        }
+        return $aRunningJobs;
+    }
 }
 ?>
\ No newline at end of file
diff --git a/web_service/ws/SchemaGroup.class.inc b/web_service/ws/SchemaGroup.class.inc
new file mode 100755
index 00000000..42639729
--- /dev/null
+++ b/web_service/ws/SchemaGroup.class.inc
@@ -0,0 +1,73 @@
+<?php
+
+require_once 'Gtf.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+
+/**
+ * \file SchemaGroup.class.inc
+ * \class SchemaGroup
+ *
+ * \author Sofian Pujo <Sofian.pujo@veremes.com>.
+ *
+ * 	\brief This file contains the SchemaGroup php class
+ *
+ * This class defines operation for one SchemaGroup
+ * 
+ */
+class SchemaGroup extends GTF {
+
+    public $oError;
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
+        $this->aSelectedFields = Array('group_id', 'schema_group_id', 'schema', 'id_schema');
+    }
+
+    /**
+     * get SchemaGroup
+     * @return  SchemaGroup
+     */
+    function GET() {
+        $this->aFields = $this->getFields($this->aProperties['schema_contraintes'], "schema", "id_schema");
+        $this->getSchemas();
+    }
+    
+    /**
+     *  get schemas of group
+     */
+    function getSchemas() {
+        $this->sRessourcesFile = "ws/gtf/SchemaGroups.class.sql.inc";
+        require $this->sRessourcesFile;
+        if (in_array("id_schema", $this->aSelectedFields)) {             
+            $aParams['sSchemaContraintes'] = array('value' => $this->aProperties['schema_contraintes'], 'type' => 'schema_name');
+            $aParams['group_id'] = array('value' => $this->aValues['my_vitis_id'], 'type' => 'number');
+            //Requête pour récupérer les schémas
+            $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['getSchemas'], $aParams);
+            $sListSchemaId = "";
+            $aListSchemaName = array();
+            //Formation du tableau pour les schémas
+            while ($aLigne = $this->oConnection->oBd->ligneSuivante($oPDOresult)) {
+                if ($sListSchemaId == "") {
+                    $sListSchemaId = $aLigne["id_schema"];
+                } else {
+                    $sListSchemaId .= "|" . $aLigne["id_schema"];
+                }
+                $aListSchemaName[] = $aLigne["name"];
+            }
+            $oPDOresult = $this->oConnection->oBd->fermeResultat();
+            $this->aFields['group_schema'] = $sListSchemaId;
+            $this->aFields['group_schema_label'] = implode(',', $aListSchemaName);
+        }
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/web_service/ws/SchemaGroups.class.inc b/web_service/ws/SchemaGroups.class.inc
new file mode 100755
index 00000000..d2894070
--- /dev/null
+++ b/web_service/ws/SchemaGroups.class.inc
@@ -0,0 +1,184 @@
+<?php
+
+/**
+ * \file SchemaGroups.class.inc
+ * \class SchemaGroups
+ *
+ * \author Sofian Pujo <sofian.pujo@veremes.com>.
+ *
+ * 	\brief This file contains the SchemaGroups php class
+ *
+ * This class defines Rest Api to Gtf schemagroups
+ * 
+ */
+require_once 'Gtf.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+require_once 'SchemaGroup.class.inc';
+require_once __DIR__ . '/../../class/vmlib/BdDataAccess.inc';
+
+class SchemaGroups extends GTF {
+    /**
+     * @SWG\Definition(
+     *   definition="/schemagroups",
+     *   allOf={
+     *     @SWG\Schema(ref="#/definitions/schemagroups")
+     *   }
+     * )
+     * * @SWG\Tag(
+     *   name="SchemaGroups",
+     *   description="Operations about SchemaGroups"
+     * )
+     */
+
+    /**
+     * construct
+     * @param type $aPath url of the request
+     * @param type $aValues parameters of the request
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
+     * @param type $oConnection connection object
+     */
+    function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
+        parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
+        $this->aSelectedFields = Array('group_id', 'id_schema', 'schema_group_id', 'schema');
+    }
+
+    /**
+     * @SWG\Get(path="/schemagroups",
+     *   tags={"SchemaGroups"},
+     *   summary="Get SchemaGroups",
+     *   description="Request to get SchemaGroups",
+     *   operationId="GET",
+     *   produces={"application/xml", "application/json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *  @SWG\Parameter(
+     *     name="order_by",
+     *     in="query",
+     *     description="list of ordering fields",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="sort_order",
+     *     in="query",
+     *     description="sort order",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="limit",
+     *     in="query",
+     *     description="number of element",
+     *     required=false,
+     *     type="integer",
+     *     format="int32"
+     *   ),
+     * @SWG\Parameter(
+     *     name="offset",
+     *     in="query",
+     *     description="index of first element",
+     *     required=false,
+     *     type="string",
+     *     format="int32"
+     *   ),
+     * @SWG\Parameter(
+     *     name="attributs",
+     *     in="query",
+     *     description="list of attributs",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="filter",
+     *     in="query",
+     *     description="filter results",
+     *     required=false,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="distinct",
+     *     in="query",
+     *     description="delete duplicates",
+     *     required=false,
+     *     type="boolean"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/schemagroups")
+     *     )
+     *  )
+     */
+
+    /**
+     * get SchemaGroups
+     * @return  SchemaGroups
+     */
+    function GET() {
+        $aReturn = $this->genericGet($this->aProperties['schema_contraintes'], "v_schema_group", "id_schema");
+        return $aReturn['sMessage'];
+    }
+    
+    /**
+     * @SWG\Put(path="/schemagroups",
+     *   tags={"SchemaGroups"},
+     *   summary="Put SchemaGroups",
+     *   description="Request to Put SchemaGroups",
+     *   operationId="Put",
+     *   produces={"application/xml", "application/json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Parameter(
+     *     name="distinct",
+     *     in="query",
+     *     description="delete duplicates",
+     *     required=false,
+     *     type="boolean"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/schemagroups")
+     *     )
+     *  )
+     */
+
+    /**
+     * Put SchemaGroups
+     * @return  SchemaGroups
+     */
+    function PUT() {
+        
+        $this->sRessourcesFile = "ws/gtf/SchemaGroups.class.sql.inc";
+        require $this->sRessourcesFile;
+        $aReturn = $this->genericPut($this->aProperties['schema_contraintes'], 'v_schema_group', 'id_schema');
+        //Suppression de tous les schémas dans la table
+        $this->oConnection->oBd->delete($this->aProperties['schema_contraintes'], 'v_schema_group', 'group_id', $this->aValues["my_vitis_id"]);
+        
+        if (!empty($this->aValues['group_schema'])) {
+                $aSchemas = explode('|', $this->aValues['group_schema']);
+                foreach ($aSchemas as $iSchemaId) {
+                    $aParams['sSchemaContraintes'] = array('value' => $this->aProperties['schema_contraintes'], 'type' => 'schema_name');
+                    $aParams['group_id'] = array('value' => $this->aValues['my_vitis_id'], 'type' => 'number');
+                    $aParams['id_schema'] = array('value' => $iSchemaId, 'type' => 'string');
+                    //Enregistrement des schémas dans la table
+                    $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['insertGroupSchema'], $aParams);
+                }
+            }
+        return $aReturn['sMessage'];
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/web_service/ws/SchemaGroups.class.sql.inc b/web_service/ws/SchemaGroups.class.sql.inc
new file mode 100755
index 00000000..48ed4cd4
--- /dev/null
+++ b/web_service/ws/SchemaGroups.class.sql.inc
@@ -0,0 +1,7 @@
+<?php
+
+//Définition des requêtes de l'api Vitis
+$aSql['insertGroupSchema'] = "INSERT INTO [sSchemaContraintes].v_schema_group(id_schema, group_id, schema_group_id) VALUES([id_schema], [group_id], nextval('[sSchemaContraintes].seq_qualigeo'))";
+$aSql['getSchemas'] = "SELECT id_schema FROM [sSchemaContraintes].v_schema_group WHERE group_id = [group_id]";
+$aSql['getAllSchemas'] = "SELECT DISTINCT id_schema FROM [sSchemaContraintes].schema";
+?>
diff --git a/web_service/ws/Subscription.class.inc b/web_service/ws/Subscription.class.inc
index b1331067..ad609a4b 100755
--- a/web_service/ws/Subscription.class.inc
+++ b/web_service/ws/Subscription.class.inc
@@ -28,7 +28,7 @@ class Subscription extends GTF {
      */
     function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
         parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
-        $this->aSelectedFields = Array('order_id', 'priority_id', 'workspace_id', 'workspace_key', 'enabled', 'label_name', 'order_status_id', 'user_id', 'login', 'period_id', 'order_period_libelle', 'wk_params', 'result_url', 'order_date', 'log_url', 'execution_date', 'attempt', 'email_notifications', 'email_option_id', 'deleted', 'gtf_engine_id', 'notification');
+        $this->aSelectedFields = Array('order_id', 'priority_id', 'workspace_id', 'workspace_key', 'enabled', 'label_name', 'order_status_id', 'user_id', 'login', 'period_id', 'order_period_libelle', 'wk_params', 'result_url', $this->getDateSelectedFields('order_date', 'yeartosecond'), 'log_url', $this->getDateSelectedFields('execution_date', 'yeartosecond'), 'attempt', 'email_notifications', 'email_option_id', 'deleted', 'gtf_engine_id', 'notification');
     }
 
     /**
diff --git a/web_service/ws/Subscriptions.class.inc b/web_service/ws/Subscriptions.class.inc
index b1dd3e12..e7a060f0 100755
--- a/web_service/ws/Subscriptions.class.inc
+++ b/web_service/ws/Subscriptions.class.inc
@@ -34,13 +34,13 @@ class Subscriptions extends GTF {
      * construct
      * @param type $aPath url of the request
      * @param type $aValues parameters of the request
-     * @param type $properties properties
-     * @param type $bShortcut false to reinit variables
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
      * @param type $oConnection connection object
      */
     function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
         parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
-        $this->aSelectedFields = Array('order_id', 'priority_id', 'workspace_id', 'workspace_key', 'enabled', 'label_name', 'order_status_id', 'user_id', 'login', 'period_id', 'order_period_libelle', 'wk_params', 'result_url', 'order_date', 'log_url', 'execution_date', 'attempt', 'email_notifications', 'email_option_id', 'deleted', 'gtf_engine_id', 'notification');
+        $this->aSelectedFields = Array('order_id', 'priority_id', 'workspace_id', 'workspace_key', 'enabled', 'label_name', 'order_status_id', 'user_id', 'login', 'period_id', 'order_period_libelle', 'wk_params', 'result_url', $this->getDateSelectedFields('order_date', 'yeartosecond'), 'log_url', $this->getDateSelectedFields('execution_date', 'yeartosecond'), 'attempt', 'email_notifications', 'email_option_id', 'deleted', 'gtf_engine_id', 'notification');
     }
 
     /**
diff --git a/web_service/ws/Survey.class.inc b/web_service/ws/Survey.class.inc
index ca6356aa..33b1dd88 100755
--- a/web_service/ws/Survey.class.inc
+++ b/web_service/ws/Survey.class.inc
@@ -28,7 +28,7 @@ class Survey extends GTF {
      */
     function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
         parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
-        $this->aSelectedFields = Array('order_id', 'workspace_key', 'priority_id', 'workspace_id', 'enabled', 'label_name', 'order_status_id', 'user_id', 'login', 'period_id', 'order_period_libelle', 'wk_params', 'result_url', 'order_date', 'log_url', 'execution_date', 'attempt', 'email_notifications', 'email_option_id', 'deleted', 'gtf_engine_id', 'survey_id', 'condition', 'warehouse_name', 'notification', 'survey_name');
+        $this->aSelectedFields = Array('order_id', 'workspace_key', 'priority_id', 'workspace_id', 'enabled', 'label_name', 'order_status_id', 'user_id', 'login', 'period_id', 'order_period_libelle', 'wk_params', 'result_url', $this->getDateSelectedFields('order_date', 'yeartosecond'), 'log_url', $this->getDateSelectedFields('execution_date', 'yeartosecond'), 'attempt', 'email_notifications', 'email_option_id', 'deleted', 'gtf_engine_id', 'survey_id', 'condition', 'warehouse_name', 'notification', 'survey_name');
     }
 
     /**
diff --git a/web_service/ws/Surveys.class.inc b/web_service/ws/Surveys.class.inc
index 48c01bea..e9996e48 100755
--- a/web_service/ws/Surveys.class.inc
+++ b/web_service/ws/Surveys.class.inc
@@ -34,13 +34,13 @@ class Surveys extends GTF {
      * construct
      * @param type $aPath url of the request
      * @param type $aValues parameters of the request
-     * @param type $properties properties
-     * @param type $bShortcut false to reinit variables
+     * @param type $properties properties
+     * @param type $bShortcut false to reinit variables
      * @param type $oConnection connection object
      */
     function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
         parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
-        $this->aSelectedFields = Array('order_id', 'workspace_key', 'priority_id', 'workspace_id', 'enabled', 'label_name', 'order_status_id', 'user_id', 'login', 'period_id', 'order_period_libelle', 'wk_params', 'result_url', 'order_date', 'log_url', 'execution_date', 'attempt', 'email_notifications', 'email_option_id', 'deleted', 'gtf_engine_id', 'survey_id', 'condition', 'warehouse_name', 'notification', 'survey_name', "name || '/' || condition as full_condition");
+        $this->aSelectedFields = Array('order_id', 'workspace_key', 'priority_id', 'workspace_id', 'enabled', 'label_name', 'order_status_id', 'user_id', 'login', 'period_id', 'order_period_libelle', 'wk_params', 'result_url', $this->getDateSelectedFields('order_date', 'yeartosecond'), 'log_url', $this->getDateSelectedFields('execution_date', 'yeartosecond'), 'attempt', 'email_notifications', 'email_option_id', 'deleted', 'gtf_engine_id', 'survey_id', 'condition', 'warehouse_name', 'notification', 'survey_name', "name || '/' || condition as full_condition");
     }
 
     /**
diff --git a/web_service/ws/UserOrder.class.inc b/web_service/ws/UserOrder.class.inc
index 23299a5f..41e89d68 100755
--- a/web_service/ws/UserOrder.class.inc
+++ b/web_service/ws/UserOrder.class.inc
@@ -28,7 +28,7 @@ class UserOrder extends GTF {
      */
     function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
         parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
-        $this->aSelectedFields = Array("order_id", "priority_id", "workspace_key", "workspace_id", "name", "order_status_id", "user_id", "wk_params", "result_url", "order_date", "log_url", "execution_date", "attempt", "email_notifications", "email_option_id", "deleted", "gtf_engine_id", "length_sec", "workspace_name", "priority_label");
+        $this->aSelectedFields = Array("order_id", "priority_id", "workspace_key", "workspace_id", "name", "order_status_id", "user_id", "wk_params", "result_url", $this->getDateSelectedFields('order_date', 'yeartosecond'), "log_url", $this->getDateSelectedFields('execution_date', 'yeartosecond'), "attempt", "email_notifications", "email_option_id", "deleted", "gtf_engine_id", "length_sec", "workspace_name", $this->getDateSelectedFields('minexecdate', 'yeartosecond'));
     }
 
     /**
diff --git a/web_service/ws/UserOrders.class.inc b/web_service/ws/UserOrders.class.inc
index 584b9bba..a078bc21 100755
--- a/web_service/ws/UserOrders.class.inc
+++ b/web_service/ws/UserOrders.class.inc
@@ -41,7 +41,7 @@ class UserOrders extends GTF {
      */
     function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
         parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
-        $this->aSelectedFields = Array("order_id", "priority_id", "workspace_key", "workspace_id", "name", "order_status_id", "user_id", "wk_params", "result_url", "to_char(order_date, 'YYYY-MM-DD HH24:MI:SS') as order_date", "log_url", "to_char(execution_date, 'YYYY-MM-DD HH24:MI:SS') as execution_date", "attempt", "email_notifications", "email_option_id", "deleted", "gtf_engine_id", "length_sec", "workspace_name", "priority_label", "email_option_label", "order_status_label");
+        $this->aSelectedFields = Array("order_id", "priority_id", "workspace_key", "workspace_id", "name", "order_status_id", "user_id", "wk_params", "result_url", $this->getDateSelectedFields('order_date', 'yeartosecond'), "log_url", $this->getDateSelectedFields('execution_date', 'yeartosecond'), "attempt", "email_notifications", "email_option_id", "deleted", "gtf_engine_id", "length_sec", "workspace_name", "email_option_label", "order_status_label", $this->getDateSelectedFields('minexecdate', 'yeartosecond'));
     }
 
     /**
@@ -185,7 +185,12 @@ class UserOrders extends GTF {
      * @return id of the user's userorder created
      */
     function POST() {
-        $this->aValues['order_date'] = date('Y-m-d H:i:s');
+        $this->aValues['order_date'] = gmdate('Y-m-d H:i:s');
+        $this->aValues['priority_id'] = 1;
+        if (!empty($this->aValues['minexecdate']))
+            $this->aValues['minexecdate'] = gmdate('Y-m-d H:i:00', date_timestamp_get(date_create_from_format('d/m/Y H:i', $this->aValues['minexecdate'])));
+        else
+            $this->aValues['minexecdate'] = null;
         if (!empty($_SESSION['ses_user_id']))
             $this->aValues['user_id'] = $_SESSION['ses_user_id'];
         if (!empty($this->aValues['email_notifications']))
diff --git a/web_service/ws/UserSubscription.class.inc b/web_service/ws/UserSubscription.class.inc
index 9897c961..acc45dbc 100755
--- a/web_service/ws/UserSubscription.class.inc
+++ b/web_service/ws/UserSubscription.class.inc
@@ -28,7 +28,7 @@ class UserSubscription extends GTF {
      */
     function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
         parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
-        $this->aSelectedFields = Array('order_id', 'workspace_id', 'workspace_key', 'enabled', 'label_name', 'order_status_id', 'user_id', 'period_id', 'order_date', 'execution_date', 'wk_params', 'result_url', 'email_option_id', 'email_notifications', 'gtf_engine_id', 'workspace_name', 'notification', 'order_period_libelle');
+        $this->aSelectedFields = Array('order_id', 'workspace_id', 'workspace_key', 'enabled', 'label_name', 'order_status_id', 'user_id', 'period_id', $this->getDateSelectedFields('order_date', 'yeartosecond'), $this->getDateSelectedFields('execution_date', 'yeartosecond'), 'wk_params', 'result_url', 'email_option_id', 'email_notifications', 'gtf_engine_id', 'workspace_name', 'notification', 'order_period_libelle');
     }
 
     /**
diff --git a/web_service/ws/UserSubscriptions.class.inc b/web_service/ws/UserSubscriptions.class.inc
index bb44deea..0e161b76 100755
--- a/web_service/ws/UserSubscriptions.class.inc
+++ b/web_service/ws/UserSubscriptions.class.inc
@@ -40,7 +40,7 @@ class UserSubscriptions extends GTF {
      */
     function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
         parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
-        $this->aSelectedFields = Array('order_id', 'workspace_id', 'workspace_key', 'enabled', 'label_name', 'order_status_id', 'user_id', 'period_id', 'order_date', 'execution_date', 'wk_params', 'result_url', 'email_option_id', 'email_notifications', 'gtf_engine_id', 'workspace_name', 'notification', 'order_period_libelle');
+        $this->aSelectedFields = Array('order_id', 'workspace_id', 'workspace_key', 'enabled', 'label_name', 'order_status_id', 'user_id', 'period_id', $this->getDateSelectedFields('order_date', 'yeartosecond'), $this->getDateSelectedFields('execution_date', 'yeartosecond'), 'wk_params', 'result_url', 'email_option_id', 'email_notifications', 'gtf_engine_id', 'workspace_name', 'notification', 'order_period_libelle');
     }
 
     /**
@@ -214,7 +214,7 @@ class UserSubscriptions extends GTF {
      * @return id of the user's usersubscription created
      */
     function POST() {
-        $this->aValues['order_date'] = date('Y-m-d H:i:s');
+        $this->aValues['order_date'] = gmdate('Y-m-d H:i:s');
         $this->aValues['user_id'] = $_SESSION['ses_user_id'];
         // Si token public -> id du compte public.
         if ($this->aValues['token'] == $this->aProperties['public_token']) {
diff --git a/web_service/ws/UserSurvey.class.inc b/web_service/ws/UserSurvey.class.inc
index 8abb3057..3aa38652 100755
--- a/web_service/ws/UserSurvey.class.inc
+++ b/web_service/ws/UserSurvey.class.inc
@@ -28,7 +28,7 @@ class UserSurvey extends GTF {
      */
     function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
         parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
-        $this->aSelectedFields = Array('order_id', 'workspace_key', 'workspace_id', 'label_name', 'enabled', 'order_status_id', 'user_id', 'period_id', 'order_date', 'execution_date', 'wk_params', 'result_url', 'email_option_id', 'email_notifications', 'gtf_engine_id', 'survey_id', 'condition', 'inbox_id', 'name', 'workspace_name', 'monitoring_type', 'notification', 'order_period_libelle', 'survey_name');
+        $this->aSelectedFields = Array('order_id', 'workspace_key', 'workspace_id', 'label_name', 'enabled', 'order_status_id', 'user_id', 'period_id', $this->getDateSelectedFields('order_date', 'yeartosecond'), $this->getDateSelectedFields('execution_date', 'yeartosecond'), 'wk_params', 'result_url', 'email_option_id', 'email_notifications', 'gtf_engine_id', 'survey_id', 'condition', 'inbox_id', 'name', 'workspace_name', 'monitoring_type', 'notification', 'order_period_libelle', 'survey_name');
     }
 
     /**
diff --git a/web_service/ws/UserSurveys.class.inc b/web_service/ws/UserSurveys.class.inc
index f17e377d..939d601f 100755
--- a/web_service/ws/UserSurveys.class.inc
+++ b/web_service/ws/UserSurveys.class.inc
@@ -41,7 +41,7 @@ class UserSurveys extends GTF {
     function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
         parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
         $login = $_SESSION['ses_Login'];
-        $this->aSelectedFields = Array('order_id', 'workspace_key', 'workspace_id', 'label_name', 'enabled', 'order_status_id', 'user_id', 'period_id', 'order_date', 'execution_date', 'wk_params', 'result_url', 'email_option_id', 'email_notifications', 'gtf_engine_id', 'survey_id', 'condition', 'inbox_id', 'name', 'workspace_name', 'monitoring_type', 'notification', 'order_period_libelle', 'survey_name', "replace(name, '\$user', '$login') || '/' || condition as full_condition");
+        $this->aSelectedFields = Array('order_id', 'workspace_key', 'workspace_id', 'label_name', 'enabled', 'order_status_id', 'user_id', 'period_id', $this->getDateSelectedFields('order_date', 'yeartosecond'), $this->getDateSelectedFields('execution_date', 'yeartosecond'), 'wk_params', 'result_url', 'email_option_id', 'email_notifications', 'gtf_engine_id', 'survey_id', 'condition', 'inbox_id', 'name', 'workspace_name', 'monitoring_type', 'notification', 'order_period_libelle', 'survey_name', "replace(name, '\$user', '$login') || '/' || condition as full_condition");
     }
 
     /**
@@ -238,7 +238,7 @@ class UserSurveys extends GTF {
      * @return id of the user's usersurvey created
      */
     function POST() {
-        $this->aValues['order_date'] = date('Y-m-d H:i:s');
+        $this->aValues['order_date'] = gmdate('Y-m-d H:i:s');
         $this->aValues['user_id'] = $_SESSION['ses_user_id'];
         // Si token public -> id du compte public.
         if ($this->aValues['token'] == $this->aProperties['public_token']) {
diff --git a/web_service/ws/Workspace.class.inc b/web_service/ws/Workspace.class.inc
old mode 100644
new mode 100755
index 6f1dda6a..d0950ec9
--- a/web_service/ws/Workspace.class.inc
+++ b/web_service/ws/Workspace.class.inc
@@ -28,7 +28,7 @@ class Workspace extends GTF {
      */
     function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
         parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
-        $this->aSelectedFields = Array('workspace_id', 'name', 'owner', 'creation_date', 'description', 'subscription', 'category_id', 'success_action_id', 'failed_action_id', 'survey', 'form_type', 'legal_terms_conditions', 'last_save_date', 'last_save_build', 'file_encoding', 'title', 'requirements', 'history', 'usage', 'key', 'email_template_id', 'locked', 'tag', 'groups', 'login', 'category_name', 'email_template', 'fmw_file');
+        $this->aSelectedFields = Array('workspace_id', 'name', 'owner', $this->getDateSelectedFields('creation_date', 'yeartosecond'), 'description', 'subscription', 'category_id', 'success_action_id', 'failed_action_id', 'survey', 'form_type', 'legal_terms_conditions', $this->getDateSelectedFields('last_save_date', 'yeartosecond'), 'last_save_build', 'file_encoding', 'title', 'requirements', 'history', 'usage', 'key', 'email_template_id', 'locked', 'tag', 'groups', 'login', 'category_name', 'email_template', 'fmw_file', 'dataencrypt', 'usepersonaldata', 'unitcost', 'costpersecond');
     }
 
     /**
@@ -196,23 +196,23 @@ class Workspace extends GTF {
                 $sJs = "";
                 $sCss = "";
                 if (is_dir($sDirName . "/form")) {
-                    if ($dh = opendir($sDirName . "/form")) {
+                    if ($dh = opendir($sDirName . "/form/ressources")) {
                         while (($file = readdir($dh)) !== false) {
                             $sName = explode(".", $file);
                             if ($sName[1] == "js") {
-                                // $pFileJS = fopen($sDirName . "/form/Subform.js", "r");
-                                // $iSize = filesize($sDirName . "/form/Subform.js");
+                                // $pFileJS = fopen($sDirName . "/form/ressources/Subform.js", "r");
+                                // $iSize = filesize($sDirName . "/form/ressources/Subform.js");
                                 // $sJs = fread($pFileJS, $iSize);
                                 // fclose($pFileJS);
 
-                                $sJs = $this->aProperties['web_server_name'] . '/' . $this->aProperties['ws_data_alias'] . "/gtf/workspace/" . (string) $this->aValues["my_vitis_id"] . "/form/Subform.js";
+                                $sJs = $this->aProperties['web_server_name'] . '/' . $this->aProperties['ws_data_alias'] . "/gtf/workspace/" . (string) $this->aValues["my_vitis_id"] . "/form/ressources/Subform.js";
                             }
                             if ($sName[1] == "css") {
-                                /* $pFileCSS = fopen($sDirName . "/form/Subform.css", "r");
-                                  $iSize = filesize($sDirName . "/form/Subform.css");
+                                /* $pFileCSS = fopen($sDirName . "/form/ressources/Subform.css", "r");
+                                  $iSize = filesize($sDirName . "/form/ressources/Subform.css");
                                   $sCss = fread($pFileCSS, $iSize);
                                   fclose($pFileCSS); */
-                                $sCss = $this->aProperties['web_server_name'] . '/' . $this->aProperties['ws_data_alias'] . "/gtf/workspace/" . (string) $this->aValues["my_vitis_id"] . "/form/Subform.css";
+                                $sCss = $this->aProperties['web_server_name'] . '/' . $this->aProperties['ws_data_alias'] . "/gtf/workspace/" . (string) $this->aValues["my_vitis_id"] . "/form/ressources/Subform.css";
                             }
                         }
                         closedir($dh);
diff --git a/web_service/ws/Workspaces.class.inc b/web_service/ws/Workspaces.class.inc
old mode 100644
new mode 100755
index d69eebd7..879b9378
--- a/web_service/ws/Workspaces.class.inc
+++ b/web_service/ws/Workspaces.class.inc
@@ -42,7 +42,7 @@ class Workspaces extends GTF {
      */
     function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
         parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
-        $this->aSelectedFields = Array('workspace_id', 'name', 'fmw_file', 'owner', 'creation_date', 'description', 'subscription', 'category_id', 'success_action_id', 'failed_action_id', 'survey', 'form_type', 'legal_terms_conditions', 'last_save_date', 'last_save_build', 'file_encoding', 'title', 'requirements', 'history', 'usage', 'key', 'email_template_id', 'locked', 'tag', 'login', 'category_name', 'nb_demande', 'email_template');
+        $this->aSelectedFields = Array('workspace_id', 'name', 'fmw_file', 'owner', $this->getDateSelectedFields('creation_date', 'yeartosecond'), 'description', 'subscription', 'category_id', 'success_action_id', 'failed_action_id', 'survey', 'form_type', 'legal_terms_conditions', $this->getDateSelectedFields('last_save_date', 'yeartosecond'), 'last_save_build', 'file_encoding', 'title', 'requirements', 'history', 'usage', 'key', 'email_template_id', 'locked', 'tag', 'login', 'category_name', 'nb_demande', 'email_template', 'dataencrypt', 'usepersonaldata');
     }
 
     /**
@@ -345,7 +345,7 @@ class Workspaces extends GTF {
                 $aParams['sFileName'] = array('value' => str_replace(".fmw", "", str_replace(".fme", "", $_FILES['fmw_file']['name'][$i])), 'type' => 'string');
                 $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['getWorkspaceId'], $aParams);
                 if ($aWorkspace = $this->oConnection->oBd->ligneSuivante($oPDOresult)) {
-                    $this->aValues['name'] = str_replace(".fmw", "", str_replace(".fme", "", $_FILES['fmw_file']['name'][$i])) . date("Ymd-His") . rand(0, 100);
+                    $this->aValues['name'] = str_replace(".fmw", "", str_replace(".fme", "", $_FILES['fmw_file']['name'][$i])) . gmdate("Ymd-His") . rand(0, 100);
                 } else {
                     $this->aValues['name'] = str_replace(".fmw", "", str_replace(".fme", "", $_FILES['fmw_file']['name'][$i]));
                 }
@@ -357,7 +357,7 @@ class Workspaces extends GTF {
                 $this->aValues['tag'] = 'default';
                 $this->aValues['survey'] = 'FALSE';
                 $this->aValues['form_type'] = 'default';
-                $this->aValues['creation_date'] = date("Y-m-d");
+                $this->aValues['creation_date'] = gmdate("Y-m-d H:i:s");
                 // Id de l'utilisateur connecté.
                 $aParams = array();
                 $aParams['sSchemaFramework'] = array('value' => $this->aProperties["schema_framework"], 'type' => 'schema_name');
@@ -439,7 +439,7 @@ class Workspaces extends GTF {
                 $aParams['sFileName'] = array('value' => str_replace(".fmw", "", str_replace(".fme", "", $_FILES['fmw_file']['name'])), 'type' => 'string');
                 $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['getWorkspaceId'], $aParams);
                 if ($aWorkspace = $this->oConnection->oBd->ligneSuivante($oPDOresult)) {
-                    $this->aValues['name'] = str_replace(".fmw", "", str_replace(".fme", "", $_FILES['fmw_file']['name'])) . date("Ymd-His") . rand(0, 100);
+                    $this->aValues['name'] = str_replace(".fmw", "", str_replace(".fme", "", $_FILES['fmw_file']['name'])) . gmdate("Ymd-His") . rand(0, 100);
                 } else {
                     $this->aValues['name'] = str_replace(".fmw", "", str_replace(".fme", "", $_FILES['fmw_file']['name']));
                 }
@@ -456,7 +456,7 @@ class Workspaces extends GTF {
                     $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
                 }          
                 else {
-                    $this->aValues['creation_date'] = date('Y-m-d');
+                    $this->aValues['creation_date'] = gmdate('Y-m-d H:i:s');
                     // Création de la clé du projet.
                     $bExistKey = false;
                     while ($bExistKey == false) {
@@ -483,7 +483,7 @@ class Workspaces extends GTF {
                                 $this->aValues["comp_file"] = $_FILES["comp_file"]["name"]; //si pas de zip la chaine est vide
                             $aExt = explode(".", $this->aValues["fmw_file"]);
                             if ($aExt[count($aExt) - 1] == "fmw") {
-                                $this->aValues['creation_date'] = date('Y-m-d');
+                                $this->aValues['creation_date'] = gmdate('Y-m-d H:i:s');
                                 $this->aValues['owner'] = $_SESSION["ses_user_id"];
                                 $this->aValues['form_type'] = 'custom';
                                 if ($this->aValues["name"] == "") {
@@ -495,7 +495,7 @@ class Workspaces extends GTF {
                                         $sFilename = $sFilename . $aExt[$i];
                                     }
                                     if (!$this->oConnection->oBd->enErreur() && $this->oConnection->oBd->nombreLigne($oPDOresult) > 0) {
-                                        $this->aValues['name'] = $sFilename . date("Ymd-His") . rand(0, 100);
+                                        $this->aValues['name'] = $sFilename . gmdate("Ymd-His") . rand(0, 100);
                                     } else {
                                         $this->aValues['name'] = $sFilename;
                                     }
@@ -792,32 +792,32 @@ class Workspaces extends GTF {
                         $pFile = fopen($sDirName . "/form/WSubform.json", "w");
                         if (fwrite($pFile, $this->aValues["Json"]) == FALSE) {
                             if ($fJson == FALSE) {
-                                writeToErrorLog("Subform.json can't be opened : " . $sDirName . "/form/Subform.json" . "(Workspaces.class.inc : verify the property workspace_dir)");
+                                writeToErrorLog("Subform.json can't be opened : " . $sDirName . "/form/ressources/Subform.json" . "(Workspaces.class.inc : verify the property workspace_dir)");
                             } else {
-                                writeToErrorLog("Subform.json can't be writed : " . $sDirName . "/form/Subform.json" . "(Workspaces.class.inc : verify the folder's rights)");
+                                writeToErrorLog("Subform.json can't be writed : " . $sDirName . "/form/ressources/Subform.json" . "(Workspaces.class.inc : verify the folder's rights)");
                             }
                         }
                         fclose($pFile);
 
                         if ($this->aValues["Js"] != "") {
-                            $pFileJS = fopen($sDirName . "/form/Subform.js", "w+");
+                            $pFileJS = fopen($sDirName . "/form/ressources/Subform.js", "w+");
                             if (fwrite($pFileJS, $this->aValues["Js"]) == FALSE) {
                                 if ($pFileJS == FALSE) {
-                                    writeToErrorLog("Subform.js can't be opened : " . $sDirName . "/form/Subform.js" . "(Workspaces.class.inc : verify the property workspace_dir)");
+                                    writeToErrorLog("Subform.js can't be opened : " . $sDirName . "/form/ressources/Subform.js" . "(Workspaces.class.inc : verify the property workspace_dir)");
                                 } else {
-                                    writeToErrorLog("Subform.js can't be writed : " . $sDirName . "/form/Subform.js" . "(Workspaces.class.inc : verify the folder's rights)");
+                                    writeToErrorLog("Subform.js can't be writed : " . $sDirName . "/form/ressources/Subform.js" . "(Workspaces.class.inc : verify the folder's rights)");
                                 }
                             }
                             fclose($pFileJS);
                         }
 
                         if ($this->aValues["Css"] != "") {
-                            $pFileCSS = fopen($sDirName . "/form/Subform.css", "w+");
+                            $pFileCSS = fopen($sDirName . "/form/ressources/Subform.css", "w+");
                             if (fwrite($pFileCSS, $this->aValues["Css"]) == FALSE) {
                                 if ($pFileCSS == FALSE) {
-                                    writeToErrorLog("Subform.css can't be opened : " . $sDirName . "/form/Subform.css" . "(Workspaces.class.inc : verify the property workspace_dir)");
+                                    writeToErrorLog("Subform.css can't be opened : " . $sDirName . "/form/ressources/Subform.css" . "(Workspaces.class.inc : verify the property workspace_dir)");
                                 } else {
-                                    writeToErrorLog("Subform.css can't be writed : " . $sDirName . "/form/Subform.css" . "(Workspaces.class.inc : verify the folder's rights)");
+                                    writeToErrorLog("Subform.css can't be writed : " . $sDirName . "/form/ressources/Subform.css" . "(Workspaces.class.inc : verify the folder's rights)");
                                 }
                             }
                             fclose($pFileCSS);
@@ -879,9 +879,9 @@ class Workspaces extends GTF {
                             $fJson = fopen($sDirName . "/form/DSubform.json", "w");
                             if (fwrite($fJson, json_encode($aJson)) == FALSE) {
                                 if ($fJson == FALSE) {
-                                    writeToErrorLog("Subform.json can't be opened : " . $sDirName . "/form/Subform.json" . "(Workspaces.class.inc : verify the property workspace_dir)");
+                                    writeToErrorLog("Subform.json can't be opened : " . $sDirName . "/form/ressources/Subform.json" . "(Workspaces.class.inc : verify the property workspace_dir)");
                                 } else {
-                                    writeToErrorLog("Subform.json can't be writed : " . $sDirName . "/form/Subform.json" . "(Workspaces.class.inc : verify the folder's rights)");
+                                    writeToErrorLog("Subform.json can't be writed : " . $sDirName . "/form/ressources/Subform.json" . "(Workspaces.class.inc : verify the folder's rights)");
                                 }
                             }
                             fclose($fJson);
@@ -892,7 +892,7 @@ class Workspaces extends GTF {
                             // Récupère les anciens paramètres.
                             $oFmwParser->getBdMetadata($this->oConnection->oBd, $this->aValues["my_vitis_id"]);
                             // Mise à jour des paramètres du nouveau fichier dans la base.
-                            $oFmwParser->sSaveDate = date('Y-m-d G:i:s');
+                            $oFmwParser->sSaveDate = gmdate('Y-m-d G:i:s');
                             $oFmwParser->updateMetadata($this->oConnection->oBd, $this->aValues["my_vitis_id"]);
                         }
                     } else {
@@ -1047,7 +1047,7 @@ class Workspaces extends GTF {
                 if ($aReturn['status'] == 1) {
                     $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
                 } else {
-                    $oError = new VitisError($aReturn['error_code'], $aReturn['message']);
+                    $oError = new VitisError(1, 'LICENSE_FILE_INSTALL_ERROR_CONFIGURATION_CONFIGURATION_GTF_LICENSE');
                     $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
                 }
             } elseif ($this->aPath[3] == "DeleteWidgetFile") {
@@ -1218,7 +1218,7 @@ class Workspaces extends GTF {
         $oPDOresult = $this->oConnection->oBd->executeWithParams($aSql['getWorkspaceLastSaveData'], $aParams);
         if (!$this->oConnection->oBd->enErreur()) {
             $aRow = $this->oConnection->oBd->ligneSuivante($oPDOresult);
-            $oObject->sSaveDate = date('Y-m-d G:i:s');
+            $oObject->sSaveDate = gmdate('Y-m-d G:i:s');
             $oObject->sSaveBuild = $aRow['last_save_build'];
         }
         // Mise à jour du projet en base.
diff --git a/web_service/ws_data/gtf/workspace/S3Downloader.fmw b/web_service/ws_data/gtf/workspace/S3Downloader.fmw
new file mode 100755
index 00000000..66a5a476
--- /dev/null
+++ b/web_service/ws_data/gtf/workspace/S3Downloader.fmw
@@ -0,0 +1,265 @@
+#! <?xml version="1.0" encoding="UTF-8" ?>
+#! <WORKSPACE
+#    
+#    
+#    Command-line to run this workspace:
+#    
+#    
+#    "C:\Program Files\FME_2016\fme.exe" "E:\_Docs\GTF moteur serveur\S3Downloader.fmw"
+#          --access_key_id ""
+#          --secret_access_key ""
+#          --bucket_name ""
+#          --object_key ""
+#          --target_file ""
+#    
+#    
+#!   WARN_INVALID_XFORM_PARAM="Yes"
+#!   FME_STROKE_MAX_DEVIATION="0"
+#!   PYTHON_COMPATIBILITY="27"
+#!   DESTINATION_ROUTING_FILE=""
+#!   DOC_TOP_LEFT="326.779 -965.635"
+#!   USAGE=""
+#!   DOC_EXTENTS="613.376 1e-05"
+#!   LOG_FILE=""
+#!   DESTINATION="NONE"
+#!   LOG_MAX_RECORDED_FEATURES="200"
+#!   ZOOM_SCALE="100"
+#!   REQUIREMENTS=""
+#!   SOURCE="NONE"
+#!   LAST_SAVE_DATE="2018-01-12T15:26:20"
+#!   FME_SERVER_SERVICES=""
+#!   FME_GEOMETRY_HANDLING="Enhanced"
+#!   FME_DOCUMENT_PRIORGUID=""
+#!   FME_DOCUMENT_GUID="644dd7ca-a79d-48e7-ad7d-33a0a3cac007"
+#!   FME_REPROJECTION_ENGINE="FME"
+#!   END_TCL=""
+#!   MULTI_WRITER_DATASET_ORDER="BY_ID"
+#!   VIEW_POSITION="-100.001 0"
+#!   TITLE=""
+#!   REQUIREMENTS_KEYWORD=""
+#!   MAX_LOG_FEATURES="200"
+#!   LEGAL_TERMS_CONDITIONS=""
+#!   EXPLICIT_BOOKMARK_ORDER="false"
+#!   DESCRIPTION=""
+#!   WORKSPACE_VERSION="1"
+#!   END_PYTHON=""
+#!   FME_IMPLICIT_CSMAP_REPROJECTION_MODE="Auto"
+#!   SOURCE_ROUTING_FILE=""
+#!   ATTR_TYPE_ENCODING="SDF"
+#!   REDIRECT_TERMINATORS="NONE"
+#!   BEGIN_PYTHON=""
+#!   FME_BUILD_NUM="16485"
+#!   IGNORE_READER_FAILURE="No"
+#!   HISTORY=""
+#!   PASSWORD=""
+#!   SHOW_ANNOTATIONS="true"
+#!   BEGIN_TCL=""
+#!   CATEGORY=""
+#!   SHOW_INFO_NODES="true"
+#!   LAST_SAVE_BUILD="FME(R) 2016.1.0.0 (20160404 - Build 16485 - WIN64)"
+#! >
+#! <DATASETS>
+#! </DATASETS>
+#! <DATA_TYPES>
+#! </DATA_TYPES>
+#! <GEOM_TYPES>
+#! </GEOM_TYPES>
+#! <FEATURE_TYPES>
+#! </FEATURE_TYPES>
+#! <FMESERVER>
+#! </FMESERVER>
+#! <GLOBAL_PARAMETERS>
+#! <GLOBAL_PARAMETER
+#!   GUI_LINE="GUI TEXT_OR_ATTR access_key_id Access key ID:"
+#!   DEFAULT_VALUE=""
+#!   IS_STAND_ALONE="true"
+#! />
+#! <GLOBAL_PARAMETER
+#!   GUI_LINE="GUI TEXT_OR_ATTR secret_access_key Secret access key:"
+#!   DEFAULT_VALUE=""
+#!   IS_STAND_ALONE="true"
+#! />
+#! <GLOBAL_PARAMETER
+#!   GUI_LINE="GUI TEXT_OR_ATTR bucket_name Bucket name:"
+#!   DEFAULT_VALUE=""
+#!   IS_STAND_ALONE="true"
+#! />
+#! <GLOBAL_PARAMETER
+#!   GUI_LINE="GUI TEXT_OR_ATTR object_key Object key:"
+#!   DEFAULT_VALUE=""
+#!   IS_STAND_ALONE="true"
+#! />
+#! <GLOBAL_PARAMETER
+#!   GUI_LINE="GUI TEXT_OR_ATTR target_file Target file:"
+#!   DEFAULT_VALUE=""
+#!   IS_STAND_ALONE="true"
+#! />
+#! </GLOBAL_PARAMETERS>
+#! <COMMENTS>
+#! </COMMENTS>
+#! <CONSTANTS>
+#! </CONSTANTS>
+#! <BOOKMARKS>
+#! </BOOKMARKS>
+#! <TRANSFORMERS>
+#! <TRANSFORMER
+#!   IDENTIFIER="1"
+#!   TYPE="S3Downloader"
+#!   VERSION="1"
+#!   POSITION="940.155 -965.635"
+#!   BOUNDING_RECT="940.155 -965.635 -1 -1"
+#!   ORDER="5e+14"
+#!   PARMS_EDITED="true"
+#!   ENABLED="true"
+#!   LAST_PARM_EDIT="16485"
+#! >
+#!     <OUTPUT_FEAT NAME="OUTPUT"/>
+#!     <FEAT_COLLAPSED COLLAPSED="0"/>
+#!     <XFORM_ATTR ATTR_NAME="_creation_instance" IS_USER_CREATED="false" FEAT_INDEX="0" />
+#!     <OUTPUT_FEAT NAME="&lt;REJECTED&gt;"/>
+#!     <FEAT_COLLAPSED COLLAPSED="1"/>
+#!     <XFORM_ATTR ATTR_NAME="_creation_instance" IS_USER_CREATED="false" FEAT_INDEX="1" />
+#!     <XFORM_ATTR ATTR_NAME="download_s3_error" IS_USER_CREATED="false" FEAT_INDEX="1" />
+#!     <XFORM_PARM PARM_NAME="XFORMER_NAME" PARM_VALUE="S3Downloader"/>
+#!     <XFORM_PARM PARM_NAME="S3_ERROR_ATTRIBUTE" PARM_VALUE="download_s3_error"/>
+#!     <XFORM_PARM PARM_NAME="S3_BUCKET_NAME" PARM_VALUE="$(bucket_name)"/>
+#!     <XFORM_PARM PARM_NAME="S3_FILE_OR_ATTRIBUTE" PARM_VALUE="File"/>
+#!     <XFORM_PARM PARM_NAME="S3_OBJECT_KEY" PARM_VALUE="$(object_key)"/>
+#!     <XFORM_PARM PARM_NAME="S3_TARGET_FILE" PARM_VALUE="$(target_file)"/>
+#!     <XFORM_PARM PARM_NAME="S3_AWS_CREDENTIALS" PARM_VALUE=""/>
+#!     <XFORM_PARM PARM_NAME="TRANSFORMER_GROUP" PARM_VALUE=""/>
+#!     <XFORM_PARM PARM_NAME="OUTPUT_OPTIONS" PARM_VALUE=""/>
+#!     <XFORM_PARM PARM_NAME="S3_DOWNLOAD_OPTIONS" PARM_VALUE=""/>
+#!     <XFORM_PARM PARM_NAME="S3_SECRET_ACCESS_KEY" PARM_VALUE="$(secret_access_key)"/>
+#!     <XFORM_PARM PARM_NAME="S3_ACCESS_KEY_ID" PARM_VALUE="$(access_key_id)"/>
+#!     <XFORM_PARM PARM_NAME="S3_TARGET_ATTRIBUTE" PARM_VALUE="&lt;Unused&gt;"/>
+#! </TRANSFORMER>
+#! <TRANSFORMER
+#!   IDENTIFIER="2"
+#!   TYPE="Creator"
+#!   VERSION="5"
+#!   POSITION="326.779 -965.635"
+#!   BOUNDING_RECT="326.779 -965.635 -1 -1"
+#!   ORDER="5e+14"
+#!   PARMS_EDITED="false"
+#!   ENABLED="true"
+#!   LAST_PARM_EDIT="16485"
+#! >
+#!     <OUTPUT_FEAT NAME="CREATED"/>
+#!     <FEAT_COLLAPSED COLLAPSED="0"/>
+#!     <XFORM_ATTR ATTR_NAME="_creation_instance" IS_USER_CREATED="false" FEAT_INDEX="0" />
+#!     <XFORM_PARM PARM_NAME="GEOM" PARM_VALUE="&lt;lt&gt;?xml&lt;space&gt;version=&lt;quote&gt;1.0&lt;quote&gt;&lt;space&gt;encoding=&lt;quote&gt;US_ASCII&lt;quote&gt;&lt;space&gt;standalone=&lt;quote&gt;no&lt;quote&gt;&lt;space&gt;?&lt;gt&gt;&lt;lt&gt;geometry&lt;space&gt;dimension=&lt;quote&gt;2&lt;quote&gt;&lt;gt&gt;&lt;lt&gt;null&lt;solidus&gt;&lt;gt&gt;&lt;lt&gt;&lt;solidus&gt;geometry&lt;gt&gt;"/>
+#!     <XFORM_PARM PARM_NAME="XFORMER_NAME" PARM_VALUE="Creator"/>
+#!     <XFORM_PARM PARM_NAME="PARAMETERS_GROUP" PARM_VALUE=""/>
+#!     <XFORM_PARM PARM_NAME="COORDS" PARM_VALUE="&lt;Unused&gt;"/>
+#!     <XFORM_PARM PARM_NAME="ATEND" PARM_VALUE="no"/>
+#!     <XFORM_PARM PARM_NAME="TRANSFORMER_GROUP" PARM_VALUE=""/>
+#!     <XFORM_PARM PARM_NAME="CRE_ATTR" PARM_VALUE="_creation_instance"/>
+#!     <XFORM_PARM PARM_NAME="GEOMTYPE" PARM_VALUE="Geometry Object"/>
+#!     <XFORM_PARM PARM_NAME="COORDSYS" PARM_VALUE=""/>
+#!     <XFORM_PARM PARM_NAME="NUM" PARM_VALUE="1"/>
+#! </TRANSFORMER>
+#! </TRANSFORMERS>
+#! <FEAT_LINKS>
+#! <FEAT_LINK
+#!   IDENTIFIER="3"
+#!   SOURCE_NODE="2"
+#!   TARGET_NODE="1"
+#!   SOURCE_PORT_DESC="fo 0 CREATED"
+#!   TARGET_PORT_DESC="fi 0 "
+#!   ENABLED="true"
+#!   EXECUTION_IDX="0"
+#!   HIDDEN="false"
+#!   EXTRA_POINTS=""
+#! />
+#! </FEAT_LINKS>
+#! <BREAKPOINTS>
+#! </BREAKPOINTS>
+#! <ATTR_LINKS>
+#! </ATTR_LINKS>
+#! <SUBDOCUMENTS>
+#! </SUBDOCUMENTS>
+#! <LOOKUP_TABLES>
+#! </LOOKUP_TABLES>
+#! </WORKSPACE>
+FME_PYTHON_VERSION 27
+DEFAULT_MACRO access_key_id 
+GUI TEXT access_key_id Access key ID:
+DEFAULT_MACRO secret_access_key 
+GUI TEXT secret_access_key Secret access key:
+DEFAULT_MACRO bucket_name 
+GUI TEXT bucket_name Bucket name:
+DEFAULT_MACRO object_key 
+GUI TEXT object_key Object key:
+DEFAULT_MACRO target_file 
+GUI TEXT target_file Target file:
+INCLUDE [ if {{$(access_key_id)} == {}} { puts_real {Parameter 'access_key_id' must be given a value.}; exit 1; }; ]
+INCLUDE [ if {{$(secret_access_key)} == {}} { puts_real {Parameter 'secret_access_key' must be given a value.}; exit 1; }; ]
+INCLUDE [ if {{$(bucket_name)} == {}} { puts_real {Parameter 'bucket_name' must be given a value.}; exit 1; }; ]
+INCLUDE [ if {{$(object_key)} == {}} { puts_real {Parameter 'object_key' must be given a value.}; exit 1; }; ]
+INCLUDE [ if {{$(target_file)} == {}} { puts_real {Parameter 'target_file' must be given a value.}; exit 1; }; ]
+#! START_HEADER
+#! START_WB_HEADER
+READER_TYPE NULL
+READER_KEYWORD NULL_SOURCE
+NULL_SOURCE_DATASET null
+
+WRITER_TYPE NULL
+WRITER_KEYWORD NULL_DEST
+NULL_DEST_DATASET null
+#! END_WB_HEADER
+
+#! START_WB_HEADER
+#! END_WB_HEADER
+
+#! END_HEADER
+
+LOG_FILENAME "$(FME_MF_DIR)S3Downloader.log"
+LOG_APPEND NO
+LOG_MAX_FEATURES 200
+LOG_MAX_RECORDED_FEATURES 200
+FME_REPROJECTION_ENGINE FME
+FME_IMPLICIT_CSMAP_REPROJECTION_MODE Auto
+FME_GEOMETRY_HANDLING Enhanced
+FME_STROKE_MAX_DEVIATION 0
+LOG_FILTER_MASK -1
+# -------------------------------------------------------------------------
+
+MULTI_READER_CONTINUE_ON_READER_FAILURE No
+
+# -------------------------------------------------------------------------
+
+MACRO WORKSPACE_NAME S3Downloader
+MACRO FME_VIEWER_APP fmedatainspector
+DEFAULT_MACRO WB_CURRENT_CONTEXT
+# -------------------------------------------------------------------------
+
+Tcl2 proc Creator_CoordSysRemover {} {   global FME_CoordSys;   set FME_CoordSys {}; }
+MACRO Creator_XML     NOT_ACTIVATED
+MACRO Creator_CLASSIC NOT_ACTIVATED
+MACRO Creator_2D3D    2D_GEOMETRY
+MACRO Creator_COORDS  <Unused>
+INCLUDE [ if { {Geometry Object} == {Geometry Object} } {            puts {MACRO Creator_XML *} } ]
+INCLUDE [ if { {Geometry Object} == {2D Coordinate List} } {            puts {MACRO Creator_2D3D 2D_GEOMETRY};            puts {MACRO Creator_CLASSIC *} } ]
+INCLUDE [ if { {Geometry Object} == {3D Coordinate List} } {            puts {MACRO Creator_2D3D 3D_GEOMETRY};            puts {MACRO Creator_CLASSIC *} } ]
+INCLUDE [ if { {Geometry Object} == {2D Min/Max Box} } {            set comment {                We need to turn the COORDS which are                    minX minY maxX maxY                into a full polygon list of coordinates            };            set splitCoords [split [string trim {<Unused>}]];            if { [llength $splitCoords] > 4} {               set trimmedCoords {};               foreach item $splitCoords { if { $item != {} } {lappend trimmedCoords $item} };               set splitCoords $trimmedCoords;            };            if { [llength $splitCoords] != 4 } {                error {Creator: Coordinate list is expected to be a space delimited list of four numbers as 'minx miny maxx maxy' - `<Unused>' is invalid};            };            set minX [lindex $splitCoords 0];            set minY [lindex $splitCoords 1];            set maxX [lindex $splitCoords 2];            set maxY [lindex $splitCoords 3];            puts "MACRO Creator_COORDS $minX $minY $minX $maxY $maxX $maxY $maxX $minY $minX $minY";            puts {MACRO Creator_2D3D 2D_GEOMETRY};            puts {MACRO Creator_CLASSIC *} } ]
+FACTORY_DEF $(Creator_XML) CreationFactory    FACTORY_NAME Creator_XML_Creator    CREATE_AT_END no    OUTPUT FEATURE_TYPE _____CREATED______        @Geometry(FROM_ENCODED_STRING,<lt>?xml<space>version=<quote>1.0<quote><space>encoding=<quote>US_ASCII<quote><space>standalone=<quote>no<quote><space>?<gt><lt>geometry<space>dimension=<quote>2<quote><gt><lt>null<solidus><gt><lt><solidus>geometry<gt>)
+FACTORY_DEF $(Creator_CLASSIC) CreationFactory    FACTORY_NAME Creator_CLASSIC_Creator    $(Creator_2D3D) $(Creator_COORDS)    CREATE_AT_END no    OUTPUT FEATURE_TYPE _____CREATED______
+FACTORY_DEF * TeeFactory    FACTORY_NAME Creator_Cloner    INPUT FEATURE_TYPE _____CREATED______    NUMBER_OF_COPIES 1    COPY_NUMBER_ATTRIBUTE "_creation_instance"    OUTPUT FEATURE_TYPE Creator_CREATED        @Tcl2(Creator_CoordSysRemover)        @CoordSys()        fme_feature_type Creator
+
+FACTORY_DEF * BranchingFactory   FACTORY_NAME "Creator_CREATED Brancher -1 3"   INPUT FEATURE_TYPE Creator_CREATED   TARGET_FACTORY "$(WB_CURRENT_CONTEXT)_CREATOR_BRANCH_TARGET"   OUTPUT PASSED FEATURE_TYPE *     @RemoveAttributes("Creator_CREATED Brancher -1 3".BranchingFactory.Count)
+# -------------------------------------------------------------------------
+FACTORY_DEF * TeeFactory   FACTORY_NAME "$(WB_CURRENT_CONTEXT)_CREATOR_BRANCH_TARGET"   INPUT FEATURE_TYPE *  OUTPUT FEATURE_TYPE *
+# -------------------------------------------------------------------------
+
+FACTORY_DEF * COM.safe.fme.factory.S3Factory    FACTORY_NAME S3Downloader       INPUT  FEATURE_TYPE Creator_CREATED    S3_MODE S3_GET    S3_ACCESS_KEY_ID "@EvaluateExpression(FDIV,STRING,$(access_key_id$encode),S3Downloader)"    S3_SECRET_ACCESS_KEY "@EvaluateExpression(FDIV,STRING,$(secret_access_key$encode),S3Downloader)"    S3_BUCKET_NAME "@EvaluateExpression(FDIV,STRING,$(bucket_name$encode),S3Downloader)"    S3_OBJECT_KEY "@EvaluateExpression(FDIV,STRING,$(object_key$encode),S3Downloader)"    S3_TARGET_FILE "@EvaluateExpression(FDIV,STRING,$(target_file$encode),S3Downloader)"    S3_ERROR_ATTRIBUTE "download_s3_error"    OUTPUT OUTPUT FEATURE_TYPE S3Downloader_OUTPUT    OUTPUT REJECTED FEATURE_TYPE S3Downloader_<REJECTED>
+
+FACTORY_DEF * TeeFactory   FACTORY_NAME "S3Downloader OUTPUT Output Nuker"   INPUT FEATURE_TYPE S3Downloader_OUTPUT
+FACTORY_DEF * TeeFactory   FACTORY_NAME "S3Downloader <REJECTED> Output Nuker"   INPUT FEATURE_TYPE S3Downloader_<REJECTED>
+# -------------------------------------------------------------------------
+
+FACTORY_DEF * RoutingFactory FACTORY_NAME "Destination Feature Type Routing Correlator"   COMMAND_PARM_EVALUATION SINGLE_PASS   INPUT FEATURE_TYPE *   FEATURE_TYPE_ATTRIBUTE __wb_out_feat_type__   OUTPUT ROUTED FEATURE_TYPE *    OUTPUT NOT_ROUTED FEATURE_TYPE __nuke_me__ @Tcl2("FME_StatMessage 818059 [FME_GetAttribute fme_template_feature_type] 818060 818061 fme_warn")
+# -------------------------------------------------------------------------
+
+FACTORY_DEF * TeeFactory   FACTORY_NAME "Final Output Nuker"   INPUT FEATURE_TYPE __nuke_me__
+
diff --git a/web_service/ws_data/gtf/workspace/S3Uploader.fmw b/web_service/ws_data/gtf/workspace/S3Uploader.fmw
new file mode 100755
index 00000000..b548676c
--- /dev/null
+++ b/web_service/ws_data/gtf/workspace/S3Uploader.fmw
@@ -0,0 +1,274 @@
+#! <?xml version="1.0" encoding="UTF-8" ?>
+#! <WORKSPACE
+#    
+#    
+#    Command-line to run this workspace:
+#    
+#    
+#    "C:\Program Files\FME_2016\fme.exe" "E:\_Docs\GTF moteur serveur\S3Uploader.fmw"
+#          --access_key_id ""
+#          --secret_access_key ""
+#          --source_file ""
+#          --bucket_name ""
+#          --object_key ""
+#    
+#    
+#!   MAX_LOG_FEATURES="200"
+#!   DOC_EXTENTS="682.126 1e-05"
+#!   IGNORE_READER_FAILURE="No"
+#!   LOG_FILE=""
+#!   DOC_TOP_LEFT="689.283 -1018.76"
+#!   HISTORY=""
+#!   WARN_INVALID_XFORM_PARAM="Yes"
+#!   END_TCL=""
+#!   FME_STROKE_MAX_DEVIATION="0"
+#!   LAST_SAVE_DATE="2018-01-12T16:55:32"
+#!   FME_DOCUMENT_GUID="4cc242b9-d06a-47c4-b931-eebc2cdb107d"
+#!   BEGIN_TCL=""
+#!   CATEGORY=""
+#!   USAGE=""
+#!   FME_SERVER_SERVICES=""
+#!   SOURCE="NONE"
+#!   SHOW_ANNOTATIONS="true"
+#!   DESCRIPTION=""
+#!   REQUIREMENTS=""
+#!   FME_GEOMETRY_HANDLING="Enhanced"
+#!   REDIRECT_TERMINATORS="NONE"
+#!   WORKSPACE_VERSION="1"
+#!   BEGIN_PYTHON=""
+#!   FME_REPROJECTION_ENGINE="FME"
+#!   SOURCE_ROUTING_FILE=""
+#!   FME_IMPLICIT_CSMAP_REPROJECTION_MODE="Auto"
+#!   LEGAL_TERMS_CONDITIONS=""
+#!   MULTI_WRITER_DATASET_ORDER="BY_ID"
+#!   ZOOM_SCALE="100"
+#!   VIEW_POSITION="-59.3756 0"
+#!   END_PYTHON=""
+#!   FME_BUILD_NUM="16485"
+#!   PASSWORD=""
+#!   ATTR_TYPE_ENCODING="SDF"
+#!   TITLE=""
+#!   SHOW_INFO_NODES="true"
+#!   DESTINATION="NONE"
+#!   REQUIREMENTS_KEYWORD=""
+#!   EXPLICIT_BOOKMARK_ORDER="false"
+#!   LAST_SAVE_BUILD="FME(R) 2016.1.0.0 (20160404 - Build 16485 - WIN64)"
+#!   DESTINATION_ROUTING_FILE=""
+#!   PYTHON_COMPATIBILITY="27"
+#!   FME_DOCUMENT_PRIORGUID=""
+#!   LOG_MAX_RECORDED_FEATURES="200"
+#! >
+#! <DATASETS>
+#! </DATASETS>
+#! <DATA_TYPES>
+#! </DATA_TYPES>
+#! <GEOM_TYPES>
+#! </GEOM_TYPES>
+#! <FEATURE_TYPES>
+#! </FEATURE_TYPES>
+#! <FMESERVER>
+#! </FMESERVER>
+#! <GLOBAL_PARAMETERS>
+#! <GLOBAL_PARAMETER
+#!   GUI_LINE="GUI TEXT_OR_ATTR access_key_id Access key ID:"
+#!   DEFAULT_VALUE=""
+#!   IS_STAND_ALONE="true"
+#! />
+#! <GLOBAL_PARAMETER
+#!   GUI_LINE="GUI TEXT_OR_ATTR secret_access_key Secret access key:"
+#!   DEFAULT_VALUE=""
+#!   IS_STAND_ALONE="true"
+#! />
+#! <GLOBAL_PARAMETER
+#!   GUI_LINE="GUI MULTIFILE_OR_ATTR source_file All_Files(*)|* Source filename:"
+#!   DEFAULT_VALUE=""
+#!   IS_STAND_ALONE="true"
+#! />
+#! <GLOBAL_PARAMETER
+#!   GUI_LINE="GUI TEXT_OR_ATTR bucket_name Bucket name:"
+#!   DEFAULT_VALUE=""
+#!   IS_STAND_ALONE="true"
+#! />
+#! <GLOBAL_PARAMETER
+#!   GUI_LINE="GUI TEXT_OR_ATTR object_key Object key:"
+#!   DEFAULT_VALUE=""
+#!   IS_STAND_ALONE="true"
+#! />
+#! </GLOBAL_PARAMETERS>
+#! <COMMENTS>
+#! </COMMENTS>
+#! <CONSTANTS>
+#! </CONSTANTS>
+#! <BOOKMARKS>
+#! </BOOKMARKS>
+#! <TRANSFORMERS>
+#! <TRANSFORMER
+#!   IDENTIFIER="1"
+#!   TYPE="S3Uploader"
+#!   VERSION="3"
+#!   POSITION="1371.41 -1018.76"
+#!   BOUNDING_RECT="1371.41 -1018.76 -1 -1"
+#!   ORDER="5e+14"
+#!   PARMS_EDITED="true"
+#!   ENABLED="true"
+#!   LAST_PARM_EDIT="16485"
+#! >
+#!     <OUTPUT_FEAT NAME="OUTPUT"/>
+#!     <FEAT_COLLAPSED COLLAPSED="0"/>
+#!     <XFORM_ATTR ATTR_NAME="_creation_instance" IS_USER_CREATED="false" FEAT_INDEX="0" />
+#!     <XFORM_ATTR ATTR_NAME="_s3_object_uri" IS_USER_CREATED="false" FEAT_INDEX="0" />
+#!     <OUTPUT_FEAT NAME="&lt;REJECTED&gt;"/>
+#!     <FEAT_COLLAPSED COLLAPSED="1"/>
+#!     <XFORM_ATTR ATTR_NAME="_creation_instance" IS_USER_CREATED="false" FEAT_INDEX="1" />
+#!     <XFORM_ATTR ATTR_NAME="_s3_error" IS_USER_CREATED="false" FEAT_INDEX="1" />
+#!     <XFORM_PARM PARM_NAME="S3_OUTPUT_OPTIONS" PARM_VALUE=""/>
+#!     <XFORM_PARM PARM_NAME="S3_URI_ATTRIBUTE" PARM_VALUE="_s3_object_uri"/>
+#!     <XFORM_PARM PARM_NAME="S3_FILE_DATA_GROUP" PARM_VALUE=""/>
+#!     <XFORM_PARM PARM_NAME="S3_CANNED_ACL" PARM_VALUE="Private"/>
+#!     <XFORM_PARM PARM_NAME="S3_FOLDER_GROUP" PARM_VALUE=""/>
+#!     <XFORM_PARM PARM_NAME="S3_FILE_OR_DATA" PARM_VALUE="File"/>
+#!     <XFORM_PARM PARM_NAME="S3_ERROR_ATTRIBUTE" PARM_VALUE="_s3_error"/>
+#!     <XFORM_PARM PARM_NAME="S3_DATA_FILE" PARM_VALUE="$(source_file)"/>
+#!     <XFORM_PARM PARM_NAME="S3_BUCKET_NAME" PARM_VALUE="$(bucket_name)"/>
+#!     <XFORM_PARM PARM_NAME="TRANSFORMER_GROUP" PARM_VALUE=""/>
+#!     <XFORM_PARM PARM_NAME="S3_ACCESS_KEY_ID" PARM_VALUE="$(access_key_id)"/>
+#!     <XFORM_PARM PARM_NAME="S3_OBJECT_KEY" PARM_VALUE="$(object_key)"/>
+#!     <XFORM_PARM PARM_NAME="S3_UPLOAD_OPTIONS" PARM_VALUE=""/>
+#!     <XFORM_PARM PARM_NAME="S3_DATA_SOURCE" PARM_VALUE=""/>
+#!     <XFORM_PARM PARM_NAME="S3_SECRET_ACCESS_KEY" PARM_VALUE="$(secret_access_key)"/>
+#!     <XFORM_PARM PARM_NAME="S3_AWS_CREDENTIALS" PARM_VALUE=""/>
+#!     <XFORM_PARM PARM_NAME="S3_DATA" PARM_VALUE="&lt;Unused&gt;"/>
+#!     <XFORM_PARM PARM_NAME="XFORMER_NAME" PARM_VALUE="S3Uploader"/>
+#!     <XFORM_PARM PARM_NAME="S3_UPLOAD_CONTENT_TYPE" PARM_VALUE=""/>
+#!     <XFORM_PARM PARM_NAME="S3_INCLUDE_SUBFOLDERS" PARM_VALUE="&lt;Unused&gt;"/>
+#!     <XFORM_PARM PARM_NAME="S3_DATA_FOLDER" PARM_VALUE="&lt;Unused&gt;"/>
+#! </TRANSFORMER>
+#! <TRANSFORMER
+#!   IDENTIFIER="2"
+#!   TYPE="Creator"
+#!   VERSION="5"
+#!   POSITION="689.283 -1018.76"
+#!   BOUNDING_RECT="689.283 -1018.76 -1 -1"
+#!   ORDER="5e+14"
+#!   PARMS_EDITED="false"
+#!   ENABLED="true"
+#!   LAST_PARM_EDIT="16485"
+#! >
+#!     <OUTPUT_FEAT NAME="CREATED"/>
+#!     <FEAT_COLLAPSED COLLAPSED="0"/>
+#!     <XFORM_ATTR ATTR_NAME="_creation_instance" IS_USER_CREATED="false" FEAT_INDEX="0" />
+#!     <XFORM_PARM PARM_NAME="GEOMTYPE" PARM_VALUE="Geometry Object"/>
+#!     <XFORM_PARM PARM_NAME="COORDS" PARM_VALUE="&lt;Unused&gt;"/>
+#!     <XFORM_PARM PARM_NAME="CRE_ATTR" PARM_VALUE="_creation_instance"/>
+#!     <XFORM_PARM PARM_NAME="PARAMETERS_GROUP" PARM_VALUE=""/>
+#!     <XFORM_PARM PARM_NAME="NUM" PARM_VALUE="1"/>
+#!     <XFORM_PARM PARM_NAME="GEOM" PARM_VALUE="&lt;lt&gt;?xml&lt;space&gt;version=&lt;quote&gt;1.0&lt;quote&gt;&lt;space&gt;encoding=&lt;quote&gt;US_ASCII&lt;quote&gt;&lt;space&gt;standalone=&lt;quote&gt;no&lt;quote&gt;&lt;space&gt;?&lt;gt&gt;&lt;lt&gt;geometry&lt;space&gt;dimension=&lt;quote&gt;2&lt;quote&gt;&lt;gt&gt;&lt;lt&gt;null&lt;solidus&gt;&lt;gt&gt;&lt;lt&gt;&lt;solidus&gt;geometry&lt;gt&gt;"/>
+#!     <XFORM_PARM PARM_NAME="XFORMER_NAME" PARM_VALUE="Creator"/>
+#!     <XFORM_PARM PARM_NAME="TRANSFORMER_GROUP" PARM_VALUE=""/>
+#!     <XFORM_PARM PARM_NAME="COORDSYS" PARM_VALUE=""/>
+#!     <XFORM_PARM PARM_NAME="ATEND" PARM_VALUE="no"/>
+#! </TRANSFORMER>
+#! </TRANSFORMERS>
+#! <FEAT_LINKS>
+#! <FEAT_LINK
+#!   IDENTIFIER="3"
+#!   SOURCE_NODE="2"
+#!   TARGET_NODE="1"
+#!   SOURCE_PORT_DESC="fo 0 CREATED"
+#!   TARGET_PORT_DESC="fi 0 "
+#!   ENABLED="true"
+#!   EXECUTION_IDX="0"
+#!   HIDDEN="false"
+#!   EXTRA_POINTS=""
+#! />
+#! </FEAT_LINKS>
+#! <BREAKPOINTS>
+#! </BREAKPOINTS>
+#! <ATTR_LINKS>
+#! </ATTR_LINKS>
+#! <SUBDOCUMENTS>
+#! </SUBDOCUMENTS>
+#! <LOOKUP_TABLES>
+#! </LOOKUP_TABLES>
+#! </WORKSPACE>
+FME_PYTHON_VERSION 27
+DEFAULT_MACRO access_key_id 
+GUI TEXT access_key_id Access key ID:
+DEFAULT_MACRO secret_access_key 
+GUI TEXT secret_access_key Secret access key:
+DEFAULT_MACRO source_file 
+GUI MULTIFILE source_file All_Files(*)|* Source filename:
+DEFAULT_MACRO bucket_name 
+GUI TEXT bucket_name Bucket name:
+DEFAULT_MACRO object_key 
+GUI TEXT object_key Object key:
+INCLUDE [ if {{$(access_key_id)} == {}} { puts_real {Parameter 'access_key_id' must be given a value.}; exit 1; }; ]
+INCLUDE [ if {{$(secret_access_key)} == {}} { puts_real {Parameter 'secret_access_key' must be given a value.}; exit 1; }; ]
+INCLUDE [ if {{$(source_file)} == {}} { puts_real {Parameter 'source_file' must be given a value.}; exit 1; }; ]
+INCLUDE [ if {{$(bucket_name)} == {}} { puts_real {Parameter 'bucket_name' must be given a value.}; exit 1; }; ]
+INCLUDE [ if {{$(object_key)} == {}} { puts_real {Parameter 'object_key' must be given a value.}; exit 1; }; ]
+#! START_HEADER
+#! START_WB_HEADER
+READER_TYPE NULL
+READER_KEYWORD NULL_SOURCE
+NULL_SOURCE_DATASET null
+
+WRITER_TYPE NULL
+WRITER_KEYWORD NULL_DEST
+NULL_DEST_DATASET null
+#! END_WB_HEADER
+
+#! START_WB_HEADER
+#! END_WB_HEADER
+
+#! END_HEADER
+
+LOG_FILENAME "$(FME_MF_DIR)S3Uploader.log"
+LOG_APPEND NO
+LOG_MAX_FEATURES 200
+LOG_MAX_RECORDED_FEATURES 200
+FME_REPROJECTION_ENGINE FME
+FME_IMPLICIT_CSMAP_REPROJECTION_MODE Auto
+FME_GEOMETRY_HANDLING Enhanced
+FME_STROKE_MAX_DEVIATION 0
+LOG_FILTER_MASK -1
+# -------------------------------------------------------------------------
+
+MULTI_READER_CONTINUE_ON_READER_FAILURE No
+
+# -------------------------------------------------------------------------
+
+MACRO WORKSPACE_NAME S3Uploader
+MACRO FME_VIEWER_APP fmedatainspector
+DEFAULT_MACRO WB_CURRENT_CONTEXT
+# -------------------------------------------------------------------------
+
+Tcl2 proc Creator_CoordSysRemover {} {   global FME_CoordSys;   set FME_CoordSys {}; }
+MACRO Creator_XML     NOT_ACTIVATED
+MACRO Creator_CLASSIC NOT_ACTIVATED
+MACRO Creator_2D3D    2D_GEOMETRY
+MACRO Creator_COORDS  <Unused>
+INCLUDE [ if { {Geometry Object} == {Geometry Object} } {            puts {MACRO Creator_XML *} } ]
+INCLUDE [ if { {Geometry Object} == {2D Coordinate List} } {            puts {MACRO Creator_2D3D 2D_GEOMETRY};            puts {MACRO Creator_CLASSIC *} } ]
+INCLUDE [ if { {Geometry Object} == {3D Coordinate List} } {            puts {MACRO Creator_2D3D 3D_GEOMETRY};            puts {MACRO Creator_CLASSIC *} } ]
+INCLUDE [ if { {Geometry Object} == {2D Min/Max Box} } {            set comment {                We need to turn the COORDS which are                    minX minY maxX maxY                into a full polygon list of coordinates            };            set splitCoords [split [string trim {<Unused>}]];            if { [llength $splitCoords] > 4} {               set trimmedCoords {};               foreach item $splitCoords { if { $item != {} } {lappend trimmedCoords $item} };               set splitCoords $trimmedCoords;            };            if { [llength $splitCoords] != 4 } {                error {Creator: Coordinate list is expected to be a space delimited list of four numbers as 'minx miny maxx maxy' - `<Unused>' is invalid};            };            set minX [lindex $splitCoords 0];            set minY [lindex $splitCoords 1];            set maxX [lindex $splitCoords 2];            set maxY [lindex $splitCoords 3];            puts "MACRO Creator_COORDS $minX $minY $minX $maxY $maxX $maxY $maxX $minY $minX $minY";            puts {MACRO Creator_2D3D 2D_GEOMETRY};            puts {MACRO Creator_CLASSIC *} } ]
+FACTORY_DEF $(Creator_XML) CreationFactory    FACTORY_NAME Creator_XML_Creator    CREATE_AT_END no    OUTPUT FEATURE_TYPE _____CREATED______        @Geometry(FROM_ENCODED_STRING,<lt>?xml<space>version=<quote>1.0<quote><space>encoding=<quote>US_ASCII<quote><space>standalone=<quote>no<quote><space>?<gt><lt>geometry<space>dimension=<quote>2<quote><gt><lt>null<solidus><gt><lt><solidus>geometry<gt>)
+FACTORY_DEF $(Creator_CLASSIC) CreationFactory    FACTORY_NAME Creator_CLASSIC_Creator    $(Creator_2D3D) $(Creator_COORDS)    CREATE_AT_END no    OUTPUT FEATURE_TYPE _____CREATED______
+FACTORY_DEF * TeeFactory    FACTORY_NAME Creator_Cloner    INPUT FEATURE_TYPE _____CREATED______    NUMBER_OF_COPIES 1    COPY_NUMBER_ATTRIBUTE "_creation_instance"    OUTPUT FEATURE_TYPE Creator_CREATED        @Tcl2(Creator_CoordSysRemover)        @CoordSys()        fme_feature_type Creator
+
+FACTORY_DEF * BranchingFactory   FACTORY_NAME "Creator_CREATED Brancher -1 3"   INPUT FEATURE_TYPE Creator_CREATED   TARGET_FACTORY "$(WB_CURRENT_CONTEXT)_CREATOR_BRANCH_TARGET"   OUTPUT PASSED FEATURE_TYPE *     @RemoveAttributes("Creator_CREATED Brancher -1 3".BranchingFactory.Count)
+# -------------------------------------------------------------------------
+FACTORY_DEF * TeeFactory   FACTORY_NAME "$(WB_CURRENT_CONTEXT)_CREATOR_BRANCH_TARGET"   INPUT FEATURE_TYPE *  OUTPUT FEATURE_TYPE *
+# -------------------------------------------------------------------------
+
+FACTORY_DEF * COM.safe.fme.factory.S3Factory    FACTORY_NAME S3Uploader       INPUT  FEATURE_TYPE Creator_CREATED    S3_MODE S3_PUT    S3_ACCESS_KEY_ID "@EvaluateExpression(FDIV,STRING,$(access_key_id$encode),S3Uploader)"    S3_SECRET_ACCESS_KEY "@EvaluateExpression(FDIV,STRING,$(secret_access_key$encode),S3Uploader)"    S3_BUCKET_NAME "@EvaluateExpression(FDIV,STRING,$(bucket_name$encode),S3Uploader)"    S3_OBJECT_KEY "@EvaluateExpression(FDIV,STRING,$(object_key$encode),S3Uploader)"    S3_DATA_FILE "@EvaluateExpression(FDIV,STRING,$(source_file$encode),S3Uploader)"    S3_CANNED_ACL "Private"    S3_URI_ATTRIBUTE "_s3_object_uri"    S3_ERROR_ATTRIBUTE "_s3_error"    OUTPUT OUTPUT FEATURE_TYPE S3Uploader_OUTPUT    OUTPUT REJECTED FEATURE_TYPE S3Uploader_<REJECTED>
+
+FACTORY_DEF * TeeFactory   FACTORY_NAME "S3Uploader OUTPUT Output Nuker"   INPUT FEATURE_TYPE S3Uploader_OUTPUT
+FACTORY_DEF * TeeFactory   FACTORY_NAME "S3Uploader <REJECTED> Output Nuker"   INPUT FEATURE_TYPE S3Uploader_<REJECTED>
+# -------------------------------------------------------------------------
+
+FACTORY_DEF * RoutingFactory FACTORY_NAME "Destination Feature Type Routing Correlator"   COMMAND_PARM_EVALUATION SINGLE_PASS   INPUT FEATURE_TYPE *   FEATURE_TYPE_ATTRIBUTE __wb_out_feat_type__   OUTPUT ROUTED FEATURE_TYPE *    OUTPUT NOT_ROUTED FEATURE_TYPE __nuke_me__ @Tcl2("FME_StatMessage 818059 [FME_GetAttribute fme_template_feature_type] 818060 818061 fme_warn")
+# -------------------------------------------------------------------------
+
+FACTORY_DEF * TeeFactory   FACTORY_NAME "Final Output Nuker"   INPUT FEATURE_TYPE __nuke_me__
+
-- 
GitLab