diff --git a/client/javascript/externs/formReader/formReaderDrtv.js b/client/javascript/externs/formReader/formReaderDrtv.js
index 182f3e27cbd7f575cec1ac9de34cd4543ecf81c1..7764774d42b8e94d95a855d92806dc03b85b10bd 100644
--- a/client/javascript/externs/formReader/formReaderDrtv.js
+++ b/client/javascript/externs/formReader/formReaderDrtv.js
@@ -456,6 +456,31 @@ formReader.formReaderDirective = function ($q, formReaderService, propertiesSrvc
                     isOnTab = true;
                 }
 
+                // Visible au travers une fonction ou un ternaire
+                if (typeof (oField["dynamic_disabled"]) !== "undefined") {
+                    if (formReaderService["isFunctionCall"](oField["dynamic_disabled"])) {
+                        oField["disabled"] = formReaderService["callFunction"](oField["dynamic_disabled"]);
+                    } else if(formReaderService["isTernaryString"](oField["dynamic_disabled"])) {
+                        try {
+                            oField["disabled"] = scope.$eval(oField["dynamic_disabled"]);
+                        } catch (e) {
+                            oField["disabled"] = false;
+                        }
+                    } else if(formReaderService["isCustomTernaryString"](oField["dynamic_disabled"], true)) {
+                        try {
+                            oField["disabled"] = scope.$eval(formReaderService["translateCustomTernaryString"](oField["dynamic_disabled"], true, scope['oFormValues'], scope['sFormDefinitionName']));
+                        } catch (e) {
+                            oField["disabled"] = false;
+                        }
+                    } else if (goog.isBoolean(oField["dynamic_disabled"])) {
+                        oField["disabled"] = oField["dynamic_disabled"];
+                    } else if (oField["dynamic_disabled"] == true || oField["dynamic_disabled"] == false || oField["dynamic_disabled"] == "true" || oField["dynamic_disabled"] == "false") {
+                        oField["disabled"] = oField["dynamic_disabled"];
+                    } else {
+                        oField["disabled"] = false;
+                    }
+                }
+
                 // Wab
                 if (this['useWab']()) {
                     var isOnWab = false;
@@ -1414,7 +1439,7 @@ formReader.appFormFieldSpecificParamsDrtv = function ($timeout, $translate, prop
                     break;
                 case "password":
                     // Désactivation de l'auto complétion des champs de mot de passe (ne pas afficher ceux sauvegardés par le navigateur).
-                    if (typeof (scope["field"]["autocomplete"]) === "undefined" || scope["field"]["autocomplete"] === false) {
+                    if (scope["field"]["autocomplete"] === false) {
                         element[0].readOnly = true;
                         // Attend la fin de l'affichage du 1er formulaire.
                         if (document.getElementById("FormBuilder") === null) {
diff --git a/client/javascript/externs/studio/lang/lang-en.json b/client/javascript/externs/studio/lang/lang-en.json
index a470fad3b6802063ae4d04acc82522a5394c05f4..c3d167a28767bc4e60ca074febd447cf47663b1b 100755
--- a/client/javascript/externs/studio/lang/lang-en.json
+++ b/client/javascript/externs/studio/lang/lang-en.json
@@ -162,7 +162,9 @@
                 "Value": "Value",
                 "ValueHelp": "Use a complex expression to link this field value with an other field value ex : \"= int({{puissance}}) + int({{portee}})\"",
                 "Visible": "Visible",
-                "VisibleHelp": "Use a complex expression to show/hide this field from others field values ex : \"= {{id_com}} == 75000\", ex : \"= int({{puissance}}) + int({{portee}}) == 1000\""
+                "VisibleHelp": "Use a complex expression to show/hide this field from others field values ex : \"= {{id_com}} == 75000\", ex : \"= int({{puissance}}) + int({{portee}}) == 1000\"",
+                "Visible": "Lock",
+                "VisibleHelp": "Use a complex expression to enable/disable this field from others field values ex : \"= {{id_com}} == 75000\", ex : \"= int({{puissance}}) + int({{portee}}) == 1000\""
             },
             "BusinessObject": {
                 "BusinessObject": "Business object",
diff --git a/client/javascript/externs/studio/lang/lang-fr.json b/client/javascript/externs/studio/lang/lang-fr.json
index 479588c5c2089f36182e3d2ca7fb3932bed7c72b..f3b4bae33fbf56b4a081d0c1c88a901b4906f620 100755
--- a/client/javascript/externs/studio/lang/lang-fr.json
+++ b/client/javascript/externs/studio/lang/lang-fr.json
@@ -168,7 +168,9 @@
                 "Value": "Valeur",
                 "ValueHelp": "Pour mettre à jour la valeur d'un champ en fonction d'un autre, utilisez une expression complexe utilisant les valeurs du formulaire ex : \"= int({{puissance}}) + int({{portee}})\"",
                 "Visible": "Visible",
-                "VisibleHelp": "Pour afficher/cacher le champ en fonction d'un autre, utilisez une expression complexe utilisant les valeurs du formulaire ex : \"= {{id_com}} == 75000\", ex : \"= int({{puissance}}) + int({{portee}}) == 1000\""
+                "VisibleHelp": "Pour afficher/cacher le champ en fonction d'un autre, utilisez une expression complexe utilisant les valeurs du formulaire ex : \"= {{id_com}} == 75000\", ex : \"= int({{puissance}}) + int({{portee}}) == 1000\"",
+                "Disabled": "Verrou",
+                "DisabledHelp": "Pour activer/désactiver le champ en fonction d'un autre, utilisez une expression complexe utilisant les valeurs du formulaire ex : \"= {{id_com}} == 75000\", ex : \"= int({{puissance}}) + int({{portee}}) == 1000\""
             },
             "BusinessObject": {
                 "BusinessObject": "Objet métier",
diff --git a/client/javascript/externs/studio/templates/ElementForm.html b/client/javascript/externs/studio/templates/ElementForm.html
index bb828ebde46b3ea9c5429e4e5aadcf6be1ab4355..34c2f5408907b14c1fa3ff72734b9a8e34c43bbe 100755
--- a/client/javascript/externs/studio/templates/ElementForm.html
+++ b/client/javascript/externs/studio/templates/ElementForm.html
@@ -2221,6 +2221,47 @@
                                     data-app-helper-icon
                                     data-text="{{::ctrl.text.Component.General.VisibleHelp}}">
                     </div>
+                    <!-- Champ désactivé -->
+                    <div ng-if="model.type != 'title'&&
+                                model.type != 'offset'&&
+                                model.type != 'subtitle'&&
+                                model.type != 'label'&&
+                                model.type != 'captcha'&&
+                                model.type != 'tinymce'&&
+                                model.type != 'hidden'&&
+                                model.type != 'slider'&&
+                                model.type != 'editable_double_select'&&
+                                model.type != 'map_bing'&&
+                                model.type != 'map_osm'&&
+                                model.type != 'map_vmap'&&
+                                model.type != 'map_workbench'&&
+                                model.type != 'codemirror'&&
+                                model.type != 'color_picker'&&
+                                model.type != 'hr'&&
+                                model.type != 'image'&&
+                                model.type != 'imageurl'&&
+                                model.type != 'image_wsdata'&&
+                                model.type != 'tab'&&
+                                model.type != 'link'&&
+                                model.type != 'linklabel'&&
+                                model.type != 'linkurl'&&
+                                model.type != 'ui_grid'&&
+                                model.type != 'bo_grid'&&
+                                model.type != 'section_grid'&&
+                                model.type != 'treeview'&&
+                                model.type != 'foldermanager'&&
+                                model.type != 'iframe'"
+                        class="input-group element-margin input-group-xs">
+                        <span id="Element_Form_dynamic_disabled_label" class="input-group-addon">{{::ctrl.text.Component.General.Disabled}}</span>
+                        <input ng-disabled="locker"
+                                    ng-model="model.dynamic_disabled"
+                                    id="Element_Form_dynamic_disabled_input"
+                                    type="text"
+                                    class="form-control"
+                                    aria-describedby="Element_Form_disabled_label"
+                                    data-app-helper-icon
+                                    data-text="{{::ctrl.text.Component.General.DisabledHelp}}">
+                    </div>
                 </div>
             </div>
         </form>
diff --git a/client/modules/vitis/forms/user/user_vitis_user.json b/client/modules/vitis/forms/user/user_vitis_user.json
index a5dacd7e5ccd46a776a8381a46c298adce8ab53f..6f550c0bd851c4a256a832dd97f7b8ef1d7a0a2c 100644
--- a/client/modules/vitis/forms/user/user_vitis_user.json
+++ b/client/modules/vitis/forms/user/user_vitis_user.json
@@ -139,7 +139,7 @@
                         "type": "radio",
                         "name": "dataencrypt",
                         "label": "FORM_DATAENCRYPT_USER_USER",
-                        "nb_cols": 5,
+                        "nb_cols": 3,
                         "options": {
                             "choices": [
                                 {
@@ -162,12 +162,19 @@
                         "nb_cols": 1
                     },
                     {
-                        "type": "text",
+                        "type": "password",
                         "name": "secretkey",
                         "label": "FORM_SECRETKEY_USER_USER",
                         "required": false,
                         "pattern": "^[^\t\r\n]+$",
-                        "nb_cols": 6
+                        "visible": "= {{dataencrypt}} === true",
+                        "tooltip": {
+                                "title":"",
+                                "content":"FORM_DATAENCRYPT_TOOLTIP_USER_USER",
+                                "container": "body",
+                                "html": true
+                        },
+                        "nb_cols": 8
                     }
                 ]
             },
diff --git a/client/modules/vitis/forms/users/users_vitis_users.json b/client/modules/vitis/forms/users/users_vitis_users.json
index 75f99967c8366a5853363dc0a88ac414c5408fe6..39aa385fab9aadd53d3a3194c903da6c631e32e8 100644
--- a/client/modules/vitis/forms/users/users_vitis_users.json
+++ b/client/modules/vitis/forms/users/users_vitis_users.json
@@ -503,6 +503,7 @@
                         "name":"login",
                         "label":"FORM_LOGIN_USERS_USER",
                         "required":true,
+                        "pattern":"^[^@]+$",
                         "nb_cols":12
                     }
                 ]
@@ -645,8 +646,7 @@
                             "parameters":{
                                 "order_by":"billinggroup"
                             }
-                        },
-                        "default_value": -1
+                        }
                     }
                 ]
             },
diff --git a/client/modules/vitis/javascript/script_module.js b/client/modules/vitis/javascript/script_module.js
index 716b8de908bc4dfb057afe25e838d92aa2463531..b15867c294f4eb7a6c96f0103c68d1c1af9c2b04 100644
--- a/client/modules/vitis/javascript/script_module.js
+++ b/client/modules/vitis/javascript/script_module.js
@@ -34,13 +34,11 @@ vitisApp.on('appMainDrtvLoaded', function () {
         // Cryptage de la clé secrète.
         var oFormValues = envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]];
         oFormValues['encrypted_secretkey'] = "";
-        if (oFormValues['dataencrypt'] === true && (goog.isDefAndNotNull(oFormValues['secretkey']) && oFormValues['secretkey'] != "" && oFormValues['secretkey'].substr(0, 2) !== "0x")) {
+        if ((goog.isDefAndNotNull(oFormValues['secretkey']) && oFormValues['secretkey'] != "" && oFormValues['secretkey'].substr(0, 2) !== "0x")) {
             var key = oFormValues['login'];
             var ciphertext = des(key, oFormValues['secretkey'], 1, 0);
             oFormValues['encrypted_secretkey'] = stringToHex(ciphertext);
         }
-        else if (oFormValues['dataencrypt'] === false)
-            oFormValues['secretkey'] = "";
         // Changement de mot de passe ?
         var oPasswordInput = document.querySelector("form[name='" + envSrvc["oFormDefinition"][envSrvc["sFormDefinitionName"]]["name"] + "'] input[name='password']");
         var oPasswordConfirmInput = document.querySelector("form[name='" + envSrvc["oFormDefinition"][envSrvc["sFormDefinitionName"]]["name"] + "'] input[name='password_confirm']");
@@ -101,7 +99,7 @@ vitisApp.on('appMainDrtvLoaded', function () {
             }
         }
         // Décryptage de la clé secrète.
-        if (oFormValues['dataencrypt'] === true && (goog.isDefAndNotNull(oFormValues['secretkey']) && oFormValues['secretkey'] != "" && oFormValues['secretkey'].substr(0, 2) === "0x")) {
+        if ((goog.isDefAndNotNull(oFormValues['secretkey']) && oFormValues['secretkey'] != "" && oFormValues['secretkey'].substr(0, 2) === "0x")) {
             var key = oFormValues['login'];
             // Décrypte et Suprimme les caractères "NULL".
             oFormValues['secretkey'] = des(key, hexToString(oFormValues['secretkey']), 0, 0).replace(/\x00/g, "");
@@ -284,7 +282,7 @@ vitisApp.on('appMainDrtvLoaded', function () {
             link: function (scope, element, attrs) {
                 // 1er affichage ou tri de la liste : maj de la mise en forme.
                 var clearObserver = attrs.$observe("appUserRoleColumn", function (value) {
-                    // Si le champ est vide : supprime l'icône.  
+                    // Si le champ est vide : supprime l'icône.
                     if (scope["row"]["entity"][scope["col"]["field"]] === null || scope["row"]["entity"][scope["col"]["field"]] === "")
                         element[0].className = "";
                     else {
@@ -700,35 +698,33 @@ vitisApp.on('appMainDrtvLoaded', function () {
                 }
             }
             // Chargement de la clé secrète (le web service vitis/users ne doit pas la retourner).
-            if (oFormValues['dataencrypt'] === true) {
-                var oUrlParams = {
-                    "schema": "s_vitis",
-                    "table": "user",
-                    "filter": {
-                        "relation": "AND",
-                        "operators": [{
-                                "column": "user_id",
-                                "compare_operator": "=",
-                                "value": oFormValues["user_id"]
-                            }]
-                    },
-                    "attributs": "secretkey"
-                };
-                ajaxRequest({
-                    "method": "GET",
-                    "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vitis/genericquerys/user",
-                    "params": oUrlParams,
-                    "success": function (response) {
-                        if (response["data"]["status"] != 0) {
-                            // Décryptage de la clé secrète.
-                            var oUserSecretKey = envSrvc["extractWebServiceData"]("genericquerys", response["data"])[0];
-                            if (goog.isDefAndNotNull(oUserSecretKey['secretkey']) && oUserSecretKey['secretkey'] != "" && oUserSecretKey['secretkey'].substr(0, 2) === "0x") {
-                                oFormValues['secretkey'] = des (oFormValues['login'], hexToString(oUserSecretKey['secretkey']), 0, 0).replace(/\x00/g, "");
-                            }
-                        }
-                    }
-                });
-            }
+              var oUrlParams = {
+                  "schema": "s_vitis",
+                  "table": "user",
+                  "filter": {
+                      "relation": "AND",
+                      "operators": [{
+                              "column": "user_id",
+                              "compare_operator": "=",
+                              "value": oFormValues["user_id"]
+                          }]
+                  },
+                  "attributs": "secretkey"
+              };
+              ajaxRequest({
+                  "method": "GET",
+                  "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vitis/genericquerys/user",
+                  "params": oUrlParams,
+                  "success": function (response) {
+                      if (response["data"]["status"] != 0) {
+                          // Décryptage de la clé secrète.
+                          var oUserSecretKey = envSrvc["extractWebServiceData"]("genericquerys", response["data"])[0];
+                          if (goog.isDefAndNotNull(oUserSecretKey['secretkey']) && oUserSecretKey['secretkey'] != "" && oUserSecretKey['secretkey'].substr(0, 2) === "0x") {
+                              oFormValues['secretkey'] = des (oFormValues['login'], hexToString(oUserSecretKey['secretkey']), 0, 0).replace(/\x00/g, "");
+                          }
+                      }
+                  }
+              });
         });
     };
 
@@ -1693,9 +1689,9 @@ vitisApp.on('appMainDrtvLoaded', function () {
 
         envSrvc["oFormDefinition"][envSrvc["sFormDefinitionName"]]["rows"].push(aMethodFields);
         envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["tr_status_method"] = sMethod;
-        // l'event submit du formulaire sera appelé après cette fonction 
+        // l'event submit du formulaire sera appelé après cette fonction
     };
-    
+
     /**
      * loadVitisExploitation function.
      * Chargement des sections du mode "exploitation".
@@ -1709,7 +1705,7 @@ vitisApp.on('appMainDrtvLoaded', function () {
         // Passage en mode "Update" (pour afficher les sections).
         envSrvc["sMode"] = "update";
     };
-    
+
     /**
      * initExploitationSharedDirectoryForm function.
      * Chargement de l'arborescence du répertoire partagé.
@@ -1738,7 +1734,7 @@ vitisApp.on('appMainDrtvLoaded', function () {
             document.getElementById(oFormElementDefinition["id"] + "_treeview").style.height = document.getElementById("container_mode_exploitation").clientHeight - 221 + "px";
         });
     };
-    
+
     /**
      * refreshExploitationSharedDirectoryTreeview function.
      * Recharge les données du treeview du répertoire partagé.
@@ -1761,7 +1757,7 @@ vitisApp.on('appMainDrtvLoaded', function () {
             document.getElementById(oFormElementDefinition["id"] + "_treeview").style.height = document.getElementById("container_mode_exploitation").parentElement.clientHeight - 221 + "px";
         });
     };
-    
+
     /**
      * loadExploitationSharedDirectoryTreeviewData function.
      * Charge les données du treeview du répertoire partagé.
@@ -1788,7 +1784,7 @@ vitisApp.on('appMainDrtvLoaded', function () {
         });
         return promise;
     };
-    
+
     /**
      * deleteSharedDirectoryFiles function.
      * Charge les données du treeview du répertoire partagé.
@@ -1846,7 +1842,7 @@ vitisApp.on('appMainDrtvLoaded', function () {
             $rootScope["modalWindow"]("confirm", "", oOptions);
         }
     };
-    
+
     /**
      * createSharedDirectoryFolder function.
      * Création d'un répertoire dans le répertoire partagé.
@@ -1897,7 +1893,7 @@ vitisApp.on('appMainDrtvLoaded', function () {
             $rootScope["modalWindow"]("dialog", "FORM_NO_DIRECTORY_EXPLOITATION_EXPLOITATION", {"className": "modal-danger"});
         }
     };
-    
+
     /**
      * uploadSharedDirectoryFile function.
      * Upload d'un fichier dans le répertoire partagé.
@@ -1952,4 +1948,4 @@ vitisApp.on('appMainDrtvLoaded', function () {
             $rootScope["modalWindow"]("dialog", "FORM_NO_FILE_EXPLOITATION_EXPLOITATION", {"className": "modal-danger"});
         }
     };
-});
\ No newline at end of file
+});
diff --git a/client/modules/vitis/lang/lang-en.json b/client/modules/vitis/lang/lang-en.json
index dc98a487ebd474dde8d906521ce10687fd6b5a2f..c59597f57237e1b798a09f72cfd22bf7a37df7ce 100644
--- a/client/modules/vitis/lang/lang-en.json
+++ b/client/modules/vitis/lang/lang-en.json
@@ -152,6 +152,7 @@
     "FORM_PHONE_USER_USER" : "Telephone number (for SMS) in international E.164 format (+33 6 xx xx xx xx)",
     "FORM_TIMEZONE_ID_USER_USER" : "Time Zone",
     "FORM_FORMATDATE_ID_USER_USER" : "Date display format",
+    "FORM_DATAENCRYPT_TOOLTIP_USER_USER" : "The results produced by GTF will be encrypted using the \"AES 256\" algorithm, you will need a suitable tool to open these files. (ex: 7zip)",
     "": "",
     "USER_ROLE_TOOLTIP_TITLE_USERS_USER": "Description",
     "USER_ROLE_ADMIN_TOOLTIP_CONTENT_USERS_USER": "Administrator",
diff --git a/client/modules/vitis/lang/lang-fr.json b/client/modules/vitis/lang/lang-fr.json
index 9a882aa04bad00781d3d5434d5ee6f052a6bd3c3..79046043a1a90eaa5a8371a65f29302db4121f47 100644
--- a/client/modules/vitis/lang/lang-fr.json
+++ b/client/modules/vitis/lang/lang-fr.json
@@ -147,13 +147,14 @@
     "FORM_INFORMATIONS_USER_USER": "Informations",
     "FORM_NEW_PASSWORD_USER_USER": "Nouveau mot de passe",
     "ACCOUNT_UNSUBSCRIBE" : "Désactiver votre compte",
-    "FORM_DATAENCRYPT_USER_USER" : "Cryptage des données",
-    "FORM_SECRETKEY_USER_USER" : "Clé secrète",
+    "FORM_DATAENCRYPT_USER_USER" : "Cryptage des documents générés",
+    "FORM_SECRETKEY_USER_USER" : "Clé de chiffrement",
     "FORM_BILLINGGROUP_ID_USERS_USER" : "Groupe de facturation",
     "FORM_ACCEPTNOTIFICATION_USER_USER" : "Acceptez-vous de recevoir des notifications par SMS ?",
     "FORM_PHONE_USER_USER" : "N° de téléphone (pour SMS) au format international E.164 (+33 6 xx xx xx xx)",
     "FORM_TIMEZONE_ID_USER_USER" : "Fuseau horaire",
     "FORM_FORMATDATE_ID_USER_USER" : "Format d'affichage des dates",
+    "FORM_DATAENCRYPT_TOOLTIP_USER_USER" : "Le cryptage des données entraîne le chiffrement avec l’algorithme AES-256 des jeux de données générés par GTF et téléchargeables. Si la clef de chiffrement personnelle n'est pas définie, une clé est générée aléatoirement à chaque traitement et envoyée à l'utilisateur avec le mail optionnel de notification. Cette clef ne peut pas être retrouvée et le message ne peut pas être renvoyé. Les utilisateurs doivent donc demander a être notifiés de la fin du traitement (fonctionnement par défaut) si leur clé de chiffrement n'est pas définie.",
     "": "",
     "USER_ROLE_TOOLTIP_TITLE_USERS_USER": "Description",
     "USER_ROLE_ADMIN_TOOLTIP_CONTENT_USERS_USER": "Administrateur",
diff --git a/vas/rest/class/vmlib/Email.class.inc b/vas/rest/class/vmlib/Email.class.inc
index 509b60691830e6382bdddb1c7dee04aaff7cb9a0..4260ed0c899f58844595e31d5b8c033d6df5a81b 100755
--- a/vas/rest/class/vmlib/Email.class.inc
+++ b/vas/rest/class/vmlib/Email.class.inc
@@ -1,11 +1,13 @@
 <?php
 
 require_once ("vmlib/logUtil.inc");
+require_once ("vmlib/phpUtil.inc");
 //require_once ("PEAR/Mail.php");
 //require_once ("PEAR/Mail/mime.php");
 require_once ("vmlib/EmailTemplate.class.inc");
 
 require_once 'vmlib/error.inc';
+require_once 'vmlib/files/Files_manager.class.inc';
 
 use PHPMailer\PHPMailer\PHPMailer;
 use PHPMailer\PHPMailer\Exception;
@@ -35,6 +37,7 @@ class Email {
     public $oEmailTemplate;
     public $aValues;
     protected $logFileName;
+    protected $oFilesManager;
 
     /*     * ****************************************************
 
@@ -52,6 +55,7 @@ class Email {
         $this->oBd = $oBd;
         $this->aProperties = $aProperties;
         $this->aObjects = $aObjects;
+        $this->oFilesManager = new Files_manager($aProperties);
         $this->xMailer = array('PHP/' => phpversion());
         //$this->from = $this->aProperties['nickname_sender'] . '<' . $this->aProperties['mail_sender'] . '>';
         //$this->replyTo = '<>';
@@ -141,7 +145,7 @@ class Email {
       return $sErrorMessage;
       } */
 
-    /** 
+    /**
 	*Load an email from an external structure.
 	*@param $aMailstruct Structure of the email.
 	*	$aMailstruct = [
@@ -163,7 +167,7 @@ class Email {
         $this->subject = $aMailstruct["subject"];
         $this->body = $aMailstruct["body"];
         $this->aAttachments = $aMailstruct["aAttachments"];
-        
+
         if(isset($aMailstruct["bUseHTML"])){
             $this->bUseHTML = $aMailstruct["bUseHTML"];
         }
@@ -176,7 +180,7 @@ class Email {
         $this->cci = str_replace(';', ',', $aMailstruct["cci"]);
         //error_log(print_r("end", true));
     }
-	
+
 	/**
 	*Load an email from a template gtf.
 	*@param $iTemplateId Id of the template
@@ -189,7 +193,7 @@ class Email {
                 // Si édition simple : génère le code de l'email
                 if (!$this->oEmailTemplate->use_advanced)
                     $this->oEmailTemplate->code = $this->oEmailTemplate->generateCode();
-                //	
+                //
                 eval($this->oEmailTemplate->code);
             }
             $this->to = str_replace(chr(13), ',', $this->to);
@@ -208,7 +212,7 @@ class Email {
     function send() {
         $mail = new PHPMailer(null);                                    // create instance with try catch
         $sErrorMessage = null;
-
+        $sTmpDir = $this->aProperties['extract_dir'] . "/email/" . getUniqRandomId();
         $mail->isSMTP();                                                // Set mailer to use SMTP
         //$mail->SMTPDebug = 3;                                         // debugger level (3 all with connection)
         $mail->Debugoutput = function($str, $level) {
@@ -274,15 +278,24 @@ class Email {
         if($this->bUseHTML){
             $this->body = '<html><body>' . $this->body . '</body></html>';
         }
-        
+
         $mail->Body = /* utf8_decode */($this->body);
         //error_log("body");
-        // Pièce jointe ?   
+        // Pièce jointe ?
         if (is_array($this->aAttachments) && !empty($this->aAttachments)) {
             foreach ($this->aAttachments as $sAttachment) {
-                if (file_exists($sAttachment)) {
+                if ($this->oFilesManager->oFileInterface->file_exists($sAttachment)) {
+                    if($this->aProperties['filesystem'] !== 'fs'){
+                        $sTmpFile = $sTmpDir . "/" . $this->oFilesManager->oFileInterface->getFileName($sAttachment);
+                        if(!$this->oFilesManager->oLocalInterface->is_dir($sTmpDir)){
+                            $this->oFilesManager->oLocalInterface->mkdir($sTmpDir, 0777, true);
+                        }
+                        $this->oFilesManager->oFileInterface->copyDistantToLocal($sAttachment, $sTmpFile);
+                        $mail->addAttachment($sTmpFile);
+                    } else {
+                        $mail->addAttachment($sAttachment);
+                    }
                     //$mail->addAttachment($path, $name, $encoding = 'base64', $type = 'application/octet-stream');
-                    $mail->addAttachment($sAttachment);
                 }
             }
         }
@@ -318,6 +331,10 @@ class Email {
                     $imap->saveMessageInSent($mail->getSentMIMEMessage(), "");
                 }
             }
+
+            if($this->oFilesManager->oLocalInterface->is_dir($sTmpDir)){
+                $this->oFilesManager->oLocalInterface->clearDir($sTmpDir);
+            }
         }
 
         return $sErrorMessage;
diff --git a/vas/rest/class/vmlib/files/Files.interface.inc b/vas/rest/class/vmlib/files/Files.interface.inc
index 0f347ce14fc4056098b39fc9f4aa61e350cd2978..b744ad08148e90c066bb4628b3b33998ab29c0c1 100644
--- a/vas/rest/class/vmlib/files/Files.interface.inc
+++ b/vas/rest/class/vmlib/files/Files.interface.inc
@@ -20,6 +20,7 @@ interface Files{
     public function unlink ($sFilePath, $mContext = null);
     public function filemtime ($sFilePath);
     public function filemtime_formated ($sFilePath, $sFormat);
+    public function mime_content_type ($sFilePath);
     // Veremes functions
     public function getFileInfos ($sFilePath);
     public function getProxyPassUrl ($sFilePath);
diff --git a/vas/rest/class/vmlib/files/Files_common.class.inc b/vas/rest/class/vmlib/files/Files_common.class.inc
index 4e2ee795f0d83814e81a58c580273765c14671b4..3bbe268b163d0be05f355ac5caaebc68086a8aa4 100644
--- a/vas/rest/class/vmlib/files/Files_common.class.inc
+++ b/vas/rest/class/vmlib/files/Files_common.class.inc
@@ -18,7 +18,7 @@ abstract class Files_common {
      */
     public function extension($sPath) {
         $aTemp = explode(".", $sPath);
-        $sString = strtolower($aTemp[count($aTemp) - 1]);
+        $sString = strtolower(end($aTemp));
         return $sString;
     }
 
@@ -135,6 +135,74 @@ abstract class Files_common {
             return false;
         }
     }
+    /**
+     *This method return the mime type of a file.
+     * For any missing type check this website https://www.sitepoint.com/mime-types-complete-list/
+     *@file vmlib/phpUtil.inc
+     *@param $sString Full name of a file.
+     *@return Retourne une chaine.
+     */
+    function mime_content_type($sFilePath) {
+        $aMimeTypes = array(
+            'txt' => 'text/plain',
+            'log' => 'text/plain',
+            'htm' => 'text/html',
+            'html' => 'text/html',
+            'php' => 'text/html',
+            'css' => 'text/css',
+            'js' => 'application/javascript',
+            'json' => 'application/json',
+            'xml' => 'application/xml',
+            'swf' => 'application/x-shockwave-flash',
+            'flv' => 'video/x-flv',
+            // images
+            'png' => 'image/png',
+            'jpe' => 'image/jpeg',
+            'jpeg' => 'image/jpeg',
+            'jpg' => 'image/jpeg',
+            'gif' => 'image/gif',
+            'bmp' => 'image/bmp',
+            'ico' => 'image/vnd.microsoft.icon',
+            'tiff' => 'image/tiff',
+            'tif' => 'image/tiff',
+            'svg' => 'image/svg+xml',
+            'svgz' => 'image/svg+xml',
+            // archives
+            'zip' => 'application/zip',
+            'rar' => 'application/x-rar-compressed',
+            'exe' => 'application/x-msdownload',
+            'msi' => 'application/x-msdownload',
+            'cab' => 'application/vnd.ms-cab-compressed',
+            // audio/video
+            'mp3' => 'audio/mpeg',
+            'qt' => 'video/quicktime',
+            'mov' => 'video/quicktime',
+            // adobe
+            'pdf' => 'application/pdf',
+            'psd' => 'image/vnd.adobe.photoshop',
+            'ai' => 'application/postscript',
+            'eps' => 'application/postscript',
+            'ps' => 'application/postscript',
+            // ms office
+            'doc' => 'application/msword',
+            'rtf' => 'application/rtf',
+            'xls' => 'application/vnd.ms-excel',
+            'ppt' => 'application/vnd.ms-powerpoint',
+            // open office
+            'odt' => 'application/vnd.oasis.opendocument.text',
+            'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
+            // other
+            '3dm' => 'x-world/x-3dmf',
+            '3dmf' => 'x-world/x-3dmf'
+        );
+
+        $sExt = strtolower($this->extension($sFilePath));
+        if (array_key_exists($sExt, $aMimeTypes)) {
+            return $aMimeTypes[$sExt];
+        } else {
+            return 'application/octet-stream';
+        }
+    }
 }
 
 ?>
diff --git a/vas/rest/class/vmlib/files/Files_manager.class.inc b/vas/rest/class/vmlib/files/Files_manager.class.inc
index 45bd24da6628ff19170bce17975e4922c4142d08..df8a89bcac44e25f15f3aa2dc9f91c906791b541 100644
--- a/vas/rest/class/vmlib/files/Files_manager.class.inc
+++ b/vas/rest/class/vmlib/files/Files_manager.class.inc
@@ -21,7 +21,7 @@ class Files_manager{
     private $oProperties;
     public $oLocalInterface;
 
-    private static $sFolderLib = "vmlib";
+    private $sFolderLib = "vmlib";
 
     function __construct($oProperties){
         $this->oProperties = $oProperties;
@@ -116,7 +116,7 @@ class Files_manager{
                     if (in_array($sFileExtension, $aExtension[$sFileType])) {
                         $bAllowUpload = true;
                     } else {
-                        foreach ($aExtensionPicture as $sValue) {
+                        foreach ($aExtension[$sFileType] as $sValue) {
                             $sFormat .= " " . $sValue;
                         }
                         writeToErrorLog(ERROR_FILE . $aFileValues['name']  . ERROR_NOT_FILE . $sFileType);
@@ -687,7 +687,7 @@ class Files_manager{
         $sTmpFile = $aFileStruct['tmp_name'];
 
         $sFileContent =  file_get_contents($sTmpFile);
-        $this->$oLocalInterface->file_put_contents($sFilePath, $sFileContent);
+        $this->oLocalInterface->file_put_contents($sFilePath, $sFileContent);
         unlink($sTmpFile);
     }
 }
diff --git a/vas/rest/class/vmlib/files/Local_files.class.inc b/vas/rest/class/vmlib/files/Local_files.class.inc
index 4c0e4a03aea5722e53467c4efab08db71d0ff43a..ed9febd5c0bb42d10bbbdc78d70a241e8ce0af71 100644
--- a/vas/rest/class/vmlib/files/Local_files.class.inc
+++ b/vas/rest/class/vmlib/files/Local_files.class.inc
@@ -155,6 +155,14 @@ class Local_files extends Files_common implements Files{
     public function filemtime_formated($sFilePath, $sFormat){
         return date ($sFormat, $this->filemtime($sFilePath));
     }
+    /**
+     *return the mime type of a file.
+     *@param string $sFilePath File's path.
+     *@return string|boolean content type on sucess or false if the process encounter an error.
+     */
+    public function mime_content_type($sFilePath){
+        return parent::mime_content_type ($sFilePath);
+    }
     /**
      *return the metadata structure of a file.
      *@param string $sFilePath File's path.
@@ -287,15 +295,15 @@ class Local_files extends Files_common implements Files{
      *@return boolean true if it's ok, false else.
      */
     public function copyDirectory($sDirPathSrc, $sDirPathDest){
-        $dir = opendir($src);
-        @mkdir($dst);
+        $dir = opendir($sDirPathSrc);
+        @mkdir($sDirPathDest);
         while(false !== ( $file = readdir($dir)) ) {
             if (( $file != '.' ) && ( $file != '..' )) {
-                if ( is_dir($src . '/' . $file) ) {
-                    $this->copyDirectory($src . '/' . $file,$dst . '/' . $file);
+                if ( is_dir($sDirPathSrc . '/' . $file) ) {
+                    $this->copyDirectory($sDirPathSrc . '/' . $file,$sDirPathDest . '/' . $file);
                 }
                 else {
-                    copy($src . '/' . $file,$dst . '/' . $file);
+                    copy($sDirPathSrc . '/' . $file,$sDirPathDest . '/' . $file);
                 }
             }
         }
diff --git a/vas/rest/class/vmlib/files/S3_files.class.inc b/vas/rest/class/vmlib/files/S3_files.class.inc
index 5b641eab8edcb6f2a04095a82010a4ee3ce20953..fd16f7559686e386b894494771237494fc7a6c6f 100644
--- a/vas/rest/class/vmlib/files/S3_files.class.inc
+++ b/vas/rest/class/vmlib/files/S3_files.class.inc
@@ -34,7 +34,7 @@ class S3_files extends Files_common implements Files{
             'debug' => false
         ));
     }
-    
+
     /**
      *parse vitis properties ti extract bucket name and bucket prefix.
      *@private
@@ -115,18 +115,29 @@ class S3_files extends Files_common implements Files{
         if (strpos($sFilePath, '/') === 0)
             $sFilePath = substr($sFilePath, 1);
 
+        $sPath = '';
+        if (empty($sData)){
+            $sPath = $this->oProperties['extract_dir'] . "/" . getUniqRandomId();
+            $sData = fopen($sPath, 'w+');
+        }
+
         try {
             $this->oS3Client->putObject(array(
                 'Bucket' => $sBucket,
                 'Key'    => $sFilePath,
-                'Body'   => $sData,
-            )
-        );
+                'Body'   => $sData
+                )
+            );
         }catch (Aws\S3\Exception\S3Exception $e){
             writeToErrorLog($e->getMessage());
             return false;
         }
-        return strlen($sData);
+        if(!empty($sPath)){
+            @unlink($sPath);
+            return 1;
+        }else{
+            return strlen($sData);
+        }
     }
     /**
      *read a file and return content in a string.
@@ -392,6 +403,14 @@ class S3_files extends Files_common implements Files{
     public function filemtime_formated ($sFilePath, $sFormat){
         return date ($sFormat, $this->filemtime($sFilePath));
     }
+    /**
+     *return the mime type of a file.
+     *@param string $sFilePath File's path.
+     *@return string|boolean content type on sucess or false if the process encounter an error.
+     */
+    public function mime_content_type ($sFilePath){
+        return parent::mime_content_type($sFilePath);
+    }
     /**
      *return the metadata structure of a file.
      *@param string $sFilePath File's path.
@@ -424,8 +443,7 @@ class S3_files extends Files_common implements Files{
      */
     public function getProxyPassUrl ($sFilePath){
         $sEtag = $this->getFileEtag($sFilePath);
-        list($sBucket, $sPrefix) = $this->getBucketConst();
-        $sFilePath = str_replace($this->oProperties["vas_home"], $sPrefix , $sFilePath);
+
         $date = new DateTime();
         $sDataUrl = $this->oProperties['web_server_name'] . "/" . $this->oProperties['services_alias'] . "/vitis/FileDownloader?key=[KEY]&eTag=[ETAG]&d=" . $date->getTimestamp();
 
@@ -513,17 +531,32 @@ class S3_files extends Files_common implements Files{
                'Prefix' => $sListPrefix
            ));
 
+           $aPathScan = explode("/", $sListPrefix);
+           $iPrefixPathCount = count($aPathScan);
+
            if ($aList["KeyCount"] > 1){
-               return true;
+               for($i = 0; $i <  $aList["KeyCount"]; $i ++){
+                   $aPathKey = explode("/", $aList["Contents"][$i]["Key"]);
+                   $iKeyCount = count($aPathKey);
+                   if ($iKeyCount > $iPrefixPathCount){
+                       if($aPathKey[$iPrefixPathCount - 1] === $aPathScan[$iPrefixPathCount - 1]){
+                            return true;
+                        }
+                   }
+               }
+               return false;
            } else if ($aList["KeyCount"] == 1){
-               $iPrefixPathCount = count(explode("/", $sListPrefix));
-               $iKeyCount = count(explode("/", $aList["Contents"][0]["Key"]));
+               $aPathKey = explode("/", $aList["Contents"][0]["Key"]);
+               $iKeyCount = count($aPathKey);
                if ($iKeyCount > $iPrefixPathCount){
-                   return true;
+                   if($aPathKey[$iPrefixPathCount - 1] === $aPathScan[$iPrefixPathCount - 1]){
+                        return true;
+                    }else{
+                        return false;
+                    }
                } else {
                    return false;
                }
-
            } else {
                return false;
            }
diff --git a/vas/rest/class/vmlib/logUtil.inc b/vas/rest/class/vmlib/logUtil.inc
index d7474ff379d5a0cf1850ac78f8ab2f5712560450..65af87db78ef8eabde4b88d17c0e089d6f9d1936 100644
--- a/vas/rest/class/vmlib/logUtil.inc
+++ b/vas/rest/class/vmlib/logUtil.inc
@@ -23,7 +23,7 @@ $sFolderLib = "vmlib";
  * \param $sString Chaîne de caractères à convertir.
  * \return une chaine encodée en UTF-8
  */
-/* function Latin1ToUtf8($sString){ 
+/* function Latin1ToUtf8($sString){
   if( mb_detect_encoding($sString,"UTF-8, ISO-8859-1")!="UTF-8" ){
   return  iconv("ISO-8859-1","UTF-8",$sString);
   }
@@ -52,7 +52,7 @@ function writeToLog($sString, $sFileName) {
         return false;
     global $properties, $sMessageLogError, $sFolderLib;
 
-    // Si le répertoire de log n'existe pas : création	
+    // Si le répertoire de log n'existe pas : création
     if (!is_dir(dirname($sFileName)))
         mkdir(dirname($sFileName), 0777, true);
     if (empty(pathinfo($sFileName, PATHINFO_EXTENSION)))
@@ -72,7 +72,10 @@ function writeToLog($sString, $sFileName) {
 
     // Rename old file if greater than porperties log_size (maximum log size to open it through app in Kb)
     // Get size of Log file in bytes
-    $iLogFileSize = filesize($sFileName);
+    $iLogFileSize = false;
+    if(file_exists($sFileName)){
+        $iLogFileSize = filesize($sFileName);
+    }
 
     if($iLogFileSize !== false){
         // get size of log message
@@ -88,7 +91,7 @@ function writeToLog($sString, $sFileName) {
         }
     }
 
-    // create if needed and open log file to write log message inside. 
+    // create if needed and open log file to write log message inside.
     $handle = fopen($sFileName, 'a');
     if (fwrite($handle, $sMessageLogtoWrite) === false) {
         fclose($handle);
@@ -195,4 +198,4 @@ function writeToFile($sString, $sFileName) {
     }
 }
 
-?>
\ No newline at end of file
+?>
diff --git a/vas/rest/ws/vitis/FileDownloader.class.inc b/vas/rest/ws/vitis/FileDownloader.class.inc
index c9564a93f201b3076778f047b1f9ffe47fcf00e0..b0389482b92c17eab61dcc9e59cd4cbd65d3c7b0 100755
--- a/vas/rest/ws/vitis/FileDownloader.class.inc
+++ b/vas/rest/ws/vitis/FileDownloader.class.inc
@@ -83,207 +83,69 @@ class FileDownloader extends Vitis {
      * @return  $sMessage Json or blob
      */
     function GET() {
+        session_write_close();
         $sMessage = array("status" => 0, "sMessage" => "");
         $bReturnFile = true;
         // si un paramètre est manquant on coupe
         if ((!empty($this->aValues["key"])) && (!empty($this->aValues["eTag"]))){
-            $sPath = "";
-            if ($this->aProperties["filesystem"] == 's3'){
-                $sPath = $this->aProperties['extract_dir'] . "/" . getUniqRandomId();
-                // traitement du bucket et de ses sous-dossiers
-                $sBucket = $this->aProperties['fileS3UploaderBucket'];
-                $sPrefix = "";
-                // Suppression du slash de début de ligne.
-                if (strpos($this->aValues["key"], '/') === 0)
-                $this->aValues["key"] = substr($this->aValues["key"], 1);
-                //
-                if (strpos($sBucket, "/") > -1){
-                    $aBucket = explode("/", $sBucket );
-                    $sBucket = $aBucket[0];
-                    $sPrefix = implode("/", array_slice($aBucket, 1));
-                }
-                // Création du client S3
-                $s3 = new Aws\S3\S3Client(array(
-                    'version'=>'latest',
-                    'region'=> $this->aProperties['fileS3UploaderRegion'],
-                    'profile'=> $this->aProperties['fileS3UploaderProfil'],
-                    'debug' => false
-                ));
-                if(strpos($this->aValues['key'], $sPrefix) === 0 || $sPrefix == ''){
-                    // récupération du fichier sur le serveur pour le téléchargement si le Etag correspond avec celui de s3
-                    try{
-                        $s3->getObject(array(
-                            'Bucket' => $sBucket,
-                            'Key' => $this->aValues['key'],
-                            'IfMatch' => $this->aValues['eTag'],
-                            'SaveAs' => $sPath
-                        ));
-                    }catch(Aws\S3\Exception\S3Exception $e){
-                        error_log($e->getMessage());
-                        $bReturnFile = false;
-                        $sMessage = array("status" => 0, "sMessage" => "This file doesn't exist or the Etag doesn't match");
-                    }
-                } else {
-                    $bReturnFile = false;
-                    $sMessage = array("status" => 0, "sMessage" => "You can't access to this object");
-                }
-
-            } else {
-                // modification de $sPath pour aller chercher le fichier dans ws_data
-                if (strpos($this->aValues["key"], 'ws_data') === 0){
-                    $sPath = str_replace('ws_data', $this->aProperties['ws_data_dir'], $this->aValues["key"]);
-                } else if (strpos($this->aValues["key"], 'public') === 0){
-                    $sPath = str_replace('public', $this->aProperties['dir_export'], $this->aValues["key"]);
-                } else if (strpos($this->aValues["key"], 'upload') === 0){
-                    $sPath = str_replace('upload', $this->aProperties['upload_dir'], $this->aValues["key"]);
-                } else if (strpos($this->aValues["key"], 'shared') === 0){
-                    $sPath = str_replace('shared', $properties['vas_home'] . '/shared', $this->aValues["key"]);
-                } else {
-                    $bReturnFile = false;
-                    $sMessage = array("status" => 0, "sMessage" => "This directory can't be replaced by our replacer");
-                }
-                // check eTag
-                if (file_exists($sPath)) {
-                    $sEtag = sha1(file_get_contents($sPath), false);
-                    if ($sEtag != $this->aValues['eTag']){
-                        $bReturnFile = false;
-                        $sMessage = array("status" => 0, "sMessage" => "This file doesn't exist or the Etag doesn't match");
-                        http_response_code(404);
-                    }
-                } else {
-                    $bReturnFile = false;
-                    $sMessage = array("status" => 0, "sMessage" => "This file doesn't exist or the Etag doesn't match");
-                    http_response_code(404);
-                }
-            }
-
-            if($bReturnFile){
-                session_write_close();
-                $sFilename = explode("/", $this->aValues["key"]);
-                $sFilename = end($sFilename);
-                $sMessage = $this->getFile($sPath, $sFilename);
-            }
-
-        } else {
-            $sMessage = array("status" => 0, "sMessage" => "Missing Parameter");
-        }
-
-        return json_encode($sMessage);
-    }
-
-    function getFile($sFilePath, $sFileName) {
-
-        // Utilisation thumnail
-        if ($this->aValues["thumbnail"] === 'true') {
-            $sMinFilePath = $sFilePath;
-            $aMinFilePath = explode('.', $sMinFilePath);
-            array_pop($aMinFilePath);
-            array_push($aMinFilePath, 'min');
-            array_push($aMinFilePath, 'jpg');
-            $sMinFilePath = implode('.', $aMinFilePath);
-            if (file_exists($sMinFilePath)) {
-                $sFilePath = $sMinFilePath;
-            }
-        }
-
-        if ($this->aValues["thumbnail"] === 'true' && $this->aValues["type"] === 'document') {
-            header("Content-disposition: attachment; filename=\"" . rawurlencode($sFileName) . "\"");
-            return array("status" => 1, "fileName" => $sFileName);
-        }
-
-        // Le fichier existe ?
-        if (file_exists($sFilePath)) {
-            $sContentType = $this->getMime($sFilePath);
-            header("Content-Type: " . $sContentType);
-            header("Content-disposition: attachment; filename=\"" . rawurlencode($sFileName) . "\"");
-            header('Content-Length: ' . filesize($sFilePath));
-            if ($sContentType === "application/octet-stream") {
-                header("Content-Transfer-Encoding: Binary");
-            }
-            readfile($sFilePath);
-        }
-    }
-
-    function getMime($sFilePath, $mode=0){
-
-        $mime_types = array(
-
-            'txt' => 'text/plain',
-            'htm' => 'text/html',
-            'html' => 'text/html',
-            'php' => 'text/html',
-            'css' => 'text/css',
-            'js' => 'application/javascript',
-            'json' => 'application/json',
-            'xml' => 'application/xml',
-            'swf' => 'application/x-shockwave-flash',
-            'flv' => 'video/x-flv',
-
-            // images
-            'png' => 'image/png',
-            'jpe' => 'image/jpeg',
-            'jpeg' => 'image/jpeg',
-            'jpg' => 'image/jpeg',
-            'gif' => 'image/gif',
-            'bmp' => 'image/bmp',
-            'ico' => 'image/vnd.microsoft.icon',
-            'tiff' => 'image/tiff',
-            'tif' => 'image/tiff',
-            'svg' => 'image/svg+xml',
-            'svgz' => 'image/svg+xml',
-
-            // archives
-            'zip' => 'application/zip',
-            'rar' => 'application/x-rar-compressed',
-            'exe' => 'application/x-msdownload',
-            'msi' => 'application/x-msdownload',
-            'cab' => 'application/vnd.ms-cab-compressed',
-
-            // audio/video
-            'mp3' => 'audio/mpeg',
-            'qt' => 'video/quicktime',
-            'mov' => 'video/quicktime',
-
-            // adobe
-            'pdf' => 'application/pdf',
-            'psd' => 'image/vnd.adobe.photoshop',
-            'ai' => 'application/postscript',
-            'eps' => 'application/postscript',
-            'ps' => 'application/postscript',
-
-            // ms office
-            'doc' => 'application/msword',
-            'rtf' => 'application/rtf',
-            'xls' => 'application/vnd.ms-excel',
-            'ppt' => 'application/vnd.ms-powerpoint',
-            'docx' => 'application/msword',
-            'xlsx' => 'application/vnd.ms-excel',
-            'pptx' => 'application/vnd.ms-powerpoint',
-
-
-            // open office
-            'odt' => 'application/vnd.oasis.opendocument.text',
-            'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
-        );
-
-        $ext = explode('.', $sFilePath);
-        $ext = array_pop($ext);
-        $ext = strtolower($ext);
-
-        if(function_exists('mime_content_type') && $mode == 0){
-            $mimetype = mime_content_type($sFilePath);
-            return $mimetype;
-
-        }elseif(function_exists('finfo_open') && $mode == 0){
-            $finfo = finfo_open(FILEINFO_MIME);
-            $mimetype = finfo_file($finfo, $sFilePath);
-            finfo_close($finfo);
-            return $mimetype;
-        }elseif(array_key_exists($ext, $mime_types)){
-            return $mime_types[$ext];
-        }else {
-            return 'application/octet-stream';
-        }
+          $sPath = "";
+
+          if (strpos($this->aValues["key"], 'ws_data') === 0){
+            $sPath = str_replace('ws_data', $this->aProperties['ws_data_dir'], $this->aValues["key"]);
+          } else if (strpos($this->aValues["key"], 'public') === 0){
+            $sPath = str_replace('public', $this->aProperties['dir_export'], $this->aValues["key"]);
+          } else if (strpos($this->aValues["key"], 'upload') === 0){
+            $sPath = str_replace('upload', $this->aProperties['upload_dir'], $this->aValues["key"]);
+          } else if (strpos($this->aValues["key"], 'shared') === 0){
+            $sPath = str_replace('shared', $properties['vas_home'] . '/shared', $this->aValues["key"]);
+          } else {
+            $sMessage = array("status" => 0, "sMessage" => "This directory can't be replaced by our replacer");
+            return json_encode($sMessage);
+          }
+
+          if($this->oFilesManager->oFileInterface->file_exists($sPath)){
+              if($this->oFilesManager->oFileInterface->getFileEtag($sPath) === $this->aValues["eTag"]){
+                  $sFileName = $this->oFilesManager->getFileName($sPath);
+                  $sContentType = $this->oFilesManager->oFileInterface->mime_content_type($sPath);
+
+                  // Utilisation thumnail
+                  if ($this->aValues["thumbnail"] === 'true') {
+                      $sMinFilePath = $sPath;
+                      $aMinFilePath = explode('.', $sMinFilePath);
+                      array_pop($aMinFilePath);
+                      array_push($aMinFilePath, 'min');
+                      array_push($aMinFilePath, 'jpg');
+                      $sMinFilePath = implode('.', $aMinFilePath);
+                      if ($this->oFilesManager->oFileInterface->file_exists($sMinFilePath)) {
+                          $sPath = $sMinFilePath;
+                      }
+                  }
+
+                  if ($this->aValues["thumbnail"] === 'true' && $this->aValues["type"] === 'document') {
+                      header("Content-disposition: attachment; filename=\"" . rawurlencode($sFileName) . "\"");
+                      return array("status" => 1, "fileName" => $sFileName);
+                  }
+
+                  header("Content-Type: " . $sContentType);
+                  if (in_array($sContentType, array("text/plain", 'application/pdf', 'text/html'))){
+                      header("Content-disposition: inline; filename=\"" . rawurlencode($sFileName) . "\"");
+                  } else {
+                      header("Content-disposition: attachment; filename=\"" . rawurlencode($sFileName) . "\"");
+                  }
+                  header('Content-Length: ' . $this->oFilesManager->oFileInterface->filesize($sPath));
+                  if ($sContentType === "application/octet-stream") {
+                    header("Content-Transfer-Encoding: Binary");
+                  }
+                  $this->oFilesManager->oFileInterface->readfile($sPath);
+              } else {
+                  $sMessage = array("status" => 0, "sMessage" => "This file doesn't exist or the Etag doesn't match");
+                  return json_encode($sMessage);
+              }
+          } else {
+              $sMessage = array("status" => 0, "sMessage" => "This file doesn't exist or the Etag doesn't match");
+              return json_encode($sMessage);
+          }
+      }
     }
 }
 
diff --git a/vas/rest/ws/vitis/Users.class.inc b/vas/rest/ws/vitis/Users.class.inc
index 56ec511d7a516ff8aba5dce2358a5c15e95c5444..85fa8078684d68a54cb2458929d12413413de62a 100755
--- a/vas/rest/ws/vitis/Users.class.inc
+++ b/vas/rest/ws/vitis/Users.class.inc
@@ -416,10 +416,7 @@ class Users extends Vitis {
             $sLogin = mb_strtolower($this->aValues["login"], 'UTF-8');
             $sLogin = str_replace(array('à', 'â', 'ä', 'á', 'ã', 'å', 'î', 'ï', 'ì', 'í', 'ô', 'ö', 'ò', 'ó', 'õ', 'ø', 'ù', 'û', 'ü', 'ú', 'é', 'è', 'ê', 'ë', 'ç', 'ÿ', 'ñ'), array('a', 'a', 'a', 'a', 'a', 'a', 'i', 'i', 'i', 'i', 'o', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u', 'e', 'e', 'e', 'e', 'c', 'y', 'n',), $sLogin);
             unset($this->aValues['login']);
-            if (!empty($this->aValues['encrypted_secretkey']))
-                $this->aValues['secretkey'] = $this->aValues['encrypted_secretkey'];
-            else
-                $this->aValues['secretkey'] = null;
+            $this->aValues['secretkey'] = $this->aValues['encrypted_secretkey'];
             $aReturn = $this->genericPut($this->aProperties['schema_framework'], 'v_user', 'user_id');
             $aXmlRacineAttribute['status'] = $aReturn['sStatus'];
             $sMessage = $aReturn['sMessage'];
diff --git a/vas/sql/sqlQueries.xml b/vas/sql/sqlQueries.xml
index 131ae69f427361a1b80dc1a59aa57106e0385884..ad70051512d7ab830bb6e8b9a007d4e3ea0f6a35 100644
--- a/vas/sql/sqlQueries.xml
+++ b/vas/sql/sqlQueries.xml
@@ -955,5 +955,15 @@
 				]]>
 			</code>
 		</query>
+		<query>
+			<type>update</type>
+			<version>2019.01.01</version>
+			<code>
+				<![CDATA[
+					-- Frédéric le 14/02/2019 à 15:53
+				 ALTER TABLE s_vitis."user" ALTER COLUMN billinggroup_id drop default;
+				]]>
+			</code>
+		</query>
 	</queriesCollection>
 </sqlQueries>
diff --git a/vas/util/vitis.fs_migration.php b/vas/util/vitis.fs_migration.php
new file mode 100644
index 0000000000000000000000000000000000000000..c15ca9b5659c02dd5e7c567f5417bee586c8fded
--- /dev/null
+++ b/vas/util/vitis.fs_migration.php
@@ -0,0 +1,42 @@
+<?php
+
+require_once dirname($_SERVER['PHP_SELF']).'/../rest/conf/properties.inc';
+
+//require_once ("vmlib/phpUtil.inc");
+require_once ("vmlib/logUtil.inc");
+require_once ("vmlib/files/Files_manager.class.inc");
+
+$oNow = new DateTime();
+
+$sVasPath = $properties["vas_home"];
+$sLogPath = $properties['vas_home']."/log/util/fs_migration/report_". $oNow->format('Y-m-d')  . ".log";
+
+$aPathMigration = array($sVasPath."/ws_data", $sVasPath."/public", $sVasPath."/upload", $sVasPath."/shared");
+$aPathMigrationExclude = array($sVasPath."/ws_data/vm4ms", $sVasPath."/ws_data/mapfileSection.txt", $sVasPath."/ws_data/mapfileZone.txt");
+
+writeToLog("Lancement du script de migration", $sLogPath, false);
+writeToLog("Copie des répertoires locaux sur le système de fichier distant " . $properties["filesystem"] , $sLogPath, false);
+
+$oFilesManager = new Files_manager($properties);
+
+for ($i =0 ; $i < count($aPathMigration); $i++){
+    if ($oFilesManager->oLocalInterface->is_dir($aPathMigration[$i])){
+        writeToLog("Copie du chemin local " . $aPathMigration[$i] . " vers le système distant", $sLogPath, false);
+        if($oFilesManager->oFileInterface->copyDirLocalToDistant($aPathMigration[$i], $aPathMigration[$i])){
+            writeToLog("Copie du dossier " . $aPathMigration[$i] . " effectué, verifiez et exécutez la commande linux : rm -rf " . $aPathMigration[$i]. " | windows : rmdir /s /q " . $aPathMigration[$i], $sLogPath, false);
+        } else {
+            writeToLog("erreur lors de la copie du chemin local " . $aPathMigration[$i] . " vers le système distant", $sLogPath, false);
+        }
+    }
+}
+
+
+for ($i =0 ; $i < count($aPathMigrationExclude); $i++){
+    if ($oFilesManager->oFileInterface->is_dir($aPathMigrationExclude[$i])){
+        writeToLog("Supression du chemin " . $aPathMigrationExclude[$i] . " sur le système distant", $sLogPath, false);
+        if(!$oFilesManager->oFileInterface->clearDir($aPathMigrationExclude[$i])){
+            writeToLog("erreur lors de la suppression du chemin distant " . $aPathMigrationExclude[$i], $sLogPath, false);
+        }
+    }
+}
+?>