diff --git a/client/javascript/app/controllers/htmlFormCtrl.js b/client/javascript/app/controllers/htmlFormCtrl.js
old mode 100755
new mode 100644
diff --git a/client/javascript/app/controllers/initCtrl.js b/client/javascript/app/controllers/initCtrl.js
old mode 100755
new mode 100644
index 48855c56c2092018d46d95c1faa98e94bc383767..70431eefb04a8ac083d1575ba2a078ca0641527f
--- a/client/javascript/app/controllers/initCtrl.js
+++ b/client/javascript/app/controllers/initCtrl.js
@@ -20,6 +20,7 @@ goog.require("vitis.modules.main");
 vitisApp.initCtrl = function ($scope, $log, $q, envSrvc, sessionSrvc, propertiesSrvc, userSrvc, $translate) {
     // Informe l'application que le contrôleur a été chargée.
     vitisApp.broadcast('appInitCtrlLoaded');
+
     /**
      * getMainTemplateUrl function.
      * Change le template de l'élément principal de l'application.
@@ -98,6 +99,43 @@ vitisApp.initCtrl = function ($scope, $log, $q, envSrvc, sessionSrvc, properties
         });
     };
 
+
+    /**
+     * connectFromUrl function.
+     * Connexion à l'application avec les identifiants passés dans l'url.
+     * @param {string} oConnexionId Identifiants de connexion
+     **/
+    $scope.$root["connectWithTokenUrl"] = function () {
+        $log.info("connectFromUrl");
+        // Demande de token pour l'utilisateur.
+        ajaxRequest({
+            "method": "POST",
+            "url": oClientProperties["web_server_name"] + "/" + oClientProperties["services_alias"] + "/" + sessionSrvc["web_service"] + "/" + sessionSrvc["web_service_controller"],
+            "scope": $scope,
+            "success": function (response) {
+                if (response["data"]["status"] == 1) {
+                    // Cache le message d'erreur.
+                    //$scope["hideErrorAlert"]();
+                    // Sauve les données du token.
+                    //sessionSrvc["token"] = oUrlParams['token'];
+                    sessionSrvc["validity_date"] = response["data"]["validity_date"];
+                    sessionStorage["session_token"] = sessionSrvc["token"];
+                    // Sauve les données de l'utilisateur.
+                    userSrvc["login"] = response["data"]["user"];
+                    userSrvc["id"] = parseInt(response["data"]["user_id"]);
+                    userSrvc["privileges"] = response["data"]["privileges"];
+                    sessionStorage["user_login"] = response["data"]["user"];
+                    sessionStorage["user_id"] = userSrvc["id"];
+                    sessionStorage["privileges"] = userSrvc["privileges"];
+                    sessionSrvc["saveSessionToLocalStorage"]();
+                    //
+                    deferred.resolve();
+                } else
+                    sessionSrvc["disconnect"]();
+            }
+        });
+    };
+
     // Sauve le nom de l'application (pour les modes de l'utilisateur)
     //sessionStorage["application"] = document.location.pathname.split("/").pop();
 
@@ -114,6 +152,14 @@ vitisApp.initCtrl = function ($scope, $log, $q, envSrvc, sessionSrvc, properties
     var deferred = $q.defer();
     var promise = deferred.promise;
 
+    if (goog.isDefAndNotNull(oUrlParams['token'])){
+        sessionStorage['session_token'] = oUrlParams['token'];
+        sessionSrvc["token"] = oUrlParams['token'];
+        sessionSrvc["saveSessionToLocalStorage"]();
+        $scope.$root["connectWithTokenUrl"]();
+    } else
+        deferred.resolve();
+
     // Connexion avec les identifiants passés dans l'url (si le cookie avec le token n'existe pas).
     var aUrlParamsKeys = Object.keys(oUrlParams);
     if (sessionSrvc["getAppLocalStorageItem"]("session_token") === null && aUrlParamsKeys.indexOf("login") !== -1 && aUrlParamsKeys.indexOf("password") !== -1)
diff --git a/client/javascript/app/controllers/loginCtrl.js b/client/javascript/app/controllers/loginCtrl.js
index 4e6e14618cdf92462865f9f573dbee866c13f221..a5456b97fd5b71d25c13cb4c0405b816fa331263 100644
--- a/client/javascript/app/controllers/loginCtrl.js
+++ b/client/javascript/app/controllers/loginCtrl.js
@@ -432,6 +432,7 @@ vitisApp.loginCtrl = function ($scope, $translate, $rootScope, $q, sessionSrvc,
                                 $translate([sConnectionErrorMessage]).then(function (translations) {
                                     sConnectionErrorMessage = translations[sConnectionErrorMessage];
                                     $scope["showErrorAlert"](sConnectionErrorMessage.replace('[IPAddress]', ipAddress));
+                        deferred.reject();
                                     sConnectionErrorMessage = undefined;
                                     deferred.reject();
                                 });
@@ -440,6 +441,12 @@ vitisApp.loginCtrl = function ($scope, $translate, $rootScope, $q, sessionSrvc,
                             case 18:
                                 sConnectionErrorMessage = "FORM_LOGIN_CONNECTION_ERROR_MISSING_PRIVILEGES";
                                 break;
+                            // Base de données injoignable.
+                            case 19:
+                                sConnectionErrorMessage = "FORM_LOGIN_CONNECTION_ERROR_UNREACHABLE_DATABASE";
+                                $scope["showErrorAlert"](sConnectionErrorMessage);
+                                deferred.reject();
+                                break;
                             default:
                                 sConnectionErrorMessage = "FORM_LOGIN_CONNECTION_ERROR";
                         }
diff --git a/client/javascript/app/script_client.js b/client/javascript/app/script_client.js
index 1f56beac66fa8b60adbae277624b4c216d4d7af5..02bda1b163d823f778c284e186dd91a290c803f2 100644
--- a/client/javascript/app/script_client.js
+++ b/client/javascript/app/script_client.js
@@ -1725,4 +1725,34 @@ vitisApp.on('appInitCtrlLoaded', function () {
         }
     });
     vitisApp.module.directive("appHideColumn", vitisApp.appHideColumn);
+    
+    /**
+     * addAjaxLoaderToElement function.
+     * Ajoute un loader Ajax à côté d'un élément HTML.
+     * @param {string} sElementId Id de l'élément html.
+     **/
+    angular.element(vitisApp.appMainDrtv).scope()["addAjaxLoaderToElement"] = function (sElementId) {
+        $log.info("addAjaxLoaderToElement");
+        var oElem = document.getElementById(sElementId);
+        if (oElem !== null) {
+            var oAjaxLoaderElem = document.createElement('span');
+            oAjaxLoaderElem.className = "icon-refresh form-glyphicon-refresh-animate";
+            oElem.parentNode.appendChild(oAjaxLoaderElem);
+        }
+    };
+    
+    /**
+     * removeAjaxLoaderFromElement function.
+     * Supprime un loader Ajax placé à côté d'un élément HTML.
+     * @param {string} sElementId Id de l'élément html.
+     **/
+    angular.element(vitisApp.appMainDrtv).scope()["removeAjaxLoaderFromElement"] = function (sElementId) {
+        $log.info("removeAjaxLoaderFromElement");
+        var oElem = document.getElementById(sElementId);
+        if (oElem !== null) {
+            var oAjaxLoaderElem = oElem.parentNode.querySelector(".form-glyphicon-refresh-animate");
+            if (oAjaxLoaderElem !== null)
+                oElem.parentNode.removeChild(oAjaxLoaderElem);
+        }
+    };
 });
diff --git a/client/javascript/externs/formReader/formReaderCtrl.js b/client/javascript/externs/formReader/formReaderCtrl.js
old mode 100755
new mode 100644
diff --git a/client/lang/lang-en.json b/client/lang/lang-en.json
index 349fcf07df20a59f918709e36e4db469d4cfcffb..0038b8111b023f79ac39954b3ddc1e892fbeeb59 100644
--- a/client/lang/lang-en.json
+++ b/client/lang/lang-en.json
@@ -7,6 +7,7 @@
     "FORM_LOGIN_CONNECTION_ERROR": "Connection failed. Incorrect user / password / domain or database not available",
     "FORM_LOGIN_CONNECTION_ERROR_FORBIDDEN_IP": "Connection failed. IP [IPAddress] forbiden",
     "FORM_LOGIN_CONNECTION_ERROR_MISSING_PRIVILEGES": "Connection failed. The user does not have the required privileges. Please contact your administrator.",
+    "FORM_LOGIN_CONNECTION_ERROR_UNREACHABLE_DATABASE": "The application is currently unavailable (database unreachable).",
     "FORM_LOGIN_REMEMBER_ME": "Remember connection?",
     "FORM_APP_STATUS_ERROR": "Unstable application",
     "FORM_VAS_STATUS_ERROR": "Unstable VAS",
diff --git a/client/lang/lang-fr.json b/client/lang/lang-fr.json
index 5c5eb178de24b151ef22b6b2e7c0701363bc0297..7dfe445bb0d0440f1fc6b9a0b41d979c21b9a308 100644
--- a/client/lang/lang-fr.json
+++ b/client/lang/lang-fr.json
@@ -7,6 +7,7 @@
     "FORM_LOGIN_CONNECTION_ERROR": "Connexion refusée. Utilisateur / Mot de passe / domaine incorrect ou base de données non disponible.",
     "FORM_LOGIN_CONNECTION_ERROR_FORBIDDEN_IP": "Connexion refusée. Adresse IP [IPAddress] non autorisée",
     "FORM_LOGIN_CONNECTION_ERROR_MISSING_PRIVILEGES": "Connexion refusée. L'utilisateur ne dispose pas des privilèges requis. Merci de contacter votre administrateur.",
+    "FORM_LOGIN_CONNECTION_ERROR_UNREACHABLE_DATABASE": "L'application est actuellement indisponible (base de données injoignable).",
     "FORM_LOGIN_REMEMBER_ME": "Se souvenir de moi ?",
     "FORM_APP_STATUS_ERROR": "Application instable",
     "FORM_VAS_STATUS_ERROR": "VAS instable",
diff --git a/client/less/htmlForm.less b/client/less/htmlForm.less
index 10480f56b30c5eefffc323ea0264d948b3675294..99e18c281d2a56bae257aa96f5758214cc3b46c9 100755
--- a/client/less/htmlForm.less
+++ b/client/less/htmlForm.less
@@ -595,3 +595,16 @@ form .checkbox {
 .timepicker-picker > table, .bootstrap-datetimepicker-widget .picker-switch .table-condensed {
     margin: auto
 }
+
+// Loader ajax pour un element de formulaire.
+.form-glyphicon-refresh-animate {
+    display: inline-block;
+    top: 3px !important;
+    left: 3px;
+    font-size: large;
+    font-weight: 800;
+    color: black;
+    -webkit-animation:spin 1.5s linear infinite;
+    -moz-animation:spin 1.5s linear infinite;
+    animation:spin 1.5s linear infinite;
+}
diff --git a/client/less/main.less b/client/less/main.less
old mode 100755
new mode 100644
diff --git a/client/modules/vitis/forms/configuration/configuration_vitis_configuration.json b/client/modules/vitis/forms/configuration/configuration_vitis_configuration.json
old mode 100755
new mode 100644
diff --git a/client/modules/vitis/forms/exploitation/exploitation_exploitation.json b/client/modules/vitis/forms/exploitation/exploitation_exploitation.json
new file mode 100755
index 0000000000000000000000000000000000000000..a7b4cde99ba8412476eb7ffe7a66a37f9c7c9bed
--- /dev/null
+++ b/client/modules/vitis/forms/exploitation/exploitation_exploitation.json
@@ -0,0 +1,160 @@
+{
+    "search":{
+            
+    },
+    "update":{
+        "name":"gtf_exploitation_shared_directory_update_form",
+        "title":"FORM_TITLE_EXPLOITATION_EXPLOITATION",
+        "initEvent":"initExploitationSharedDirectoryForm()",
+        "event":"",
+        "input_size":"xs",
+        "nb_cols":12,
+        "class":"project-directory-upload-form",
+        "rows":[
+            {
+                "class":"shared-directory-treeview",
+                "fields":[
+                    {
+                        "type":"treeview",
+                        "name":"shared_directory",
+                        "label":"",
+                        "required":false,
+                        "pattern":"",
+                        "nb_cols":12,
+                        "id":"shared_directory",
+                        "options":{
+                            "showBorder":false,
+                            "levels":0,
+                            "showCheckbox":true,
+                            "expandIcon":"glyphicon glyphicon-folder-close",
+                            "collapseIcon":"glyphicon glyphicon-folder-open",
+                            "highlightSelected":true,
+                            "multiSelect":false,
+                            "dataLoadingEvent": "sharedDirectoryTreeviewDataLoaded"
+                        }
+                    }
+                ]
+            },            
+            {
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-xs",
+                        "nb_cols":12,
+                        "buttons":[
+                            {
+                                "type":"button",
+                                "name":"btn_download_file",
+                                "glyphicon":"download",
+                                "class":"btn-primary btn-xs",
+                                "event":"downloadFile()",
+                                "tooltip": {
+                                        "title":"FORM_DOWNLOAD_FILE_EXPLOITATION_EXPLOITATION",
+                                        "placement": "bottom",
+                                        "trigger": "hover",
+                                        "container": "body"
+                                },
+                                "visible":false
+                            },
+                            {
+                                "type":"button",
+                                "name":"btn_refresh_treeview",
+                                "glyphicon":"refresh",
+                                "class":"btn-primary btn-xs",
+                                "event":"refreshExploitationSharedDirectoryTreeview()",
+                                "tooltip": {
+                                        "title":"FORM_RELOAD_DIRECTORY_EXPLOITATION_EXPLOITATION",
+                                        "placement": "bottom",
+                                        "trigger": "hover",
+                                        "container": "body"
+                                }
+                            },
+                            {
+                                "type":"button",
+                                "name":"btn_delete_file",
+                                "glyphicon":"trash",
+                                "class":"btn-primary btn-xs",
+                                "event":"deleteSharedDirectoryFiles()",
+                                "tooltip": {
+                                        "title":"FORM_DELETE_FILES_EXPLOITATION_EXPLOITATION",
+                                        "placement": "bottom",
+                                        "trigger": "hover"
+                                }
+                            }
+                        ]
+                    }
+                ]
+            },
+            {
+                "class":"form-field-inline",
+                "fields":[
+                    {
+                        "type":"upload",
+                        "name":"file",
+                        "label":"FORM_FILE_EXPLOITATION_EXPLOITATION",
+                        "nb_cols":4
+                    },
+                    {
+                        "type":"text",
+                        "name":"directory_name",
+                        "label":"FORM_DIRECTORY_EXPLOITATION_EXPLOITATION",
+                        "nb_cols":4
+                    }
+                ]
+            },
+            {
+                "class":"form-field-inline",
+                "fields":[
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-sm",
+                        "nb_cols":4,
+                        "buttons":[
+                            {
+                                "type":"button",
+                                "name":"btn_upload_file",
+                                "label":"FORM_UPLOAD_FMW_FILE_EXPLOITATION_EXPLOITATION",
+                                "event":"uploadSharedDirectoryFile()",
+                                "class":"btn-primary"
+                            }
+                        ]
+                    },
+                    {
+                        "type":"button",
+                        "class":"btn-ungroup btn-group-sm",
+                        "nb_cols":4,
+                        "buttons":[
+                            {
+                                "type":"button",
+                                "name":"btn_create_directory",
+                                "label":"FORM_BTN_CREATE_DIRECTORY_EXPLOITATION_EXPLOITATION",
+                                "event":"createSharedDirectoryFolder()",
+                                "class":"btn-primary"
+                            }
+                        ]
+                    }
+                ]
+            }
+        ]
+    },
+    "insert":{
+            
+    },
+    "display":{
+        "name":"gtf_exploitation_shared_directory_display_form",
+        "title":"FORM_TITLE_EXPLOITATION_EXPLOITATION",
+        "input_size":"xs",
+        "nb_cols":8,
+        "rows":[
+            {
+                "fields":[
+                    {
+                        "type":"hidden",
+                        "name":"fmw_file",
+                        "nb_cols":12
+                    }
+                ]
+            }
+        ]
+    }
+}
\ No newline at end of file
diff --git a/client/modules/vitis/forms/user/user_vitis_user.json b/client/modules/vitis/forms/user/user_vitis_user.json
old mode 100755
new mode 100644
diff --git a/client/modules/vitis/forms/users/users_vitis_users.json b/client/modules/vitis/forms/users/users_vitis_users.json
old mode 100755
new mode 100644
diff --git a/client/modules/vitis/javascript/script_module.js b/client/modules/vitis/javascript/script_module.js
old mode 100755
new mode 100644
index 1f0e99b41d538a838143044510f0016012a6f4ce..716b8de908bc4dfb057afe25e838d92aa2463531
--- a/client/modules/vitis/javascript/script_module.js
+++ b/client/modules/vitis/javascript/script_module.js
@@ -1211,7 +1211,9 @@ vitisApp.on('appMainDrtvLoaded', function () {
                     '</div>',
             link: function (scope, element, attrs) {
 
-                scope.textValue = (goog.isDefAndNotNull(attrs["hidevalue"])) ? "" : scope["row"]["entity"][scope["col"]["field"]] + "%";
+                scope.$watch("row.entity." + scope["col"]["field"], function(val){
+                    scope.textValue = (goog.isDefAndNotNull(attrs["hidevalue"])) ? "" : val + "%";
+                });
 
                 if (goog.isDefAndNotNull(attrs["mode"]))
                     element[0].firstChild.className = element[0].firstChild.className + " progress-bar-" + attrs["mode"];
@@ -1693,4 +1695,261 @@ vitisApp.on('appMainDrtvLoaded', function () {
         envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["tr_status_method"] = sMethod;
         // l'event submit du formulaire sera appelé après cette fonction 
     };
+    
+    /**
+     * loadVitisExploitation function.
+     * Chargement des sections du mode "exploitation".
+     **/
+    angular.element(vitisApp.appMainDrtv).scope()["loadVitisExploitation"] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var envSrvc = angular.element(vitisApp.appWorkspaceListDrtv).injector().get(["envSrvc"]);
+        //
+        $log.info("loadVitisExploitation");
+        // Passage en mode "Update" (pour afficher les sections).
+        envSrvc["sMode"] = "update";
+    };
+    
+    /**
+     * initExploitationSharedDirectoryForm function.
+     * Chargement de l'arborescence du répertoire partagé.
+     **/
+    angular.element(vitisApp.appMainDrtv).scope()["initExploitationSharedDirectoryForm"] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var $rootScope = angular.element(vitisApp.appMainDrtv).injector().get(["$rootScope"]);
+        var $timeout = angular.element(vitisApp.appMainDrtv).injector().get(["$timeout"]);
+        var formSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["formSrvc"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        //
+        $log.info("initExploitationSharedDirectoryForm");
+        // Attends la fin de l'affichage du 1er formulaire.
+        var clearListener = $rootScope.$on('formExtracted', function (event) {
+            // Supprime le "listener".
+            clearListener();
+            //
+            $timeout(function () {
+                $rootScope["loadExploitationSharedDirectoryTreeviewData"]().then(function(aNodes){
+                    $rootScope.$emit("sharedDirectoryTreeviewDataLoaded", aNodes);
+                });
+            });
+            // Huteur du treeview.
+            var oFormElementDefinition = formSrvc["getFormElementDefinition"]("shared_directory", envSrvc["sFormDefinitionName"]);
+            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é.
+     **/
+    angular.element(vitisApp.appMainDrtv).scope()["refreshExploitationSharedDirectoryTreeview"] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var $rootScope = angular.element(vitisApp.appMainDrtv).injector().get(["$rootScope"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        var formSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["formSrvc"]);
+        //
+        $log.info("refreshExploitationSharedDirectoryTreeview");
+        $rootScope["loadExploitationSharedDirectoryTreeviewData"]().then(function(aNodes){
+            var oFormElementDefinition = formSrvc["getFormElementDefinition"]("shared_directory", envSrvc["sFormDefinitionName"]);
+            var oTreeviewOptions = $("#" + oFormElementDefinition["id"] + "_treeview")["treeview"](true)["options"];
+            $("#" + oFormElementDefinition["id"] + "_treeview")["treeview"](true)["remove"]();
+            oTreeviewOptions["data"] = aNodes;
+            $("#" + oFormElementDefinition["id"] + "_treeview")["treeview"](oTreeviewOptions);
+            // Huteur du treeview.
+            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é.
+     **/
+    angular.element(vitisApp.appMainDrtv).scope()["loadExploitationSharedDirectoryTreeviewData"] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var $q = angular.element(vitisApp.appStatisticsFormDrtv).injector().get(["$q"]);
+        var propertiesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["propertiesSrvc"]);
+        //
+        $log.info("loadExploitationSharedDirectoryTreeviewData");
+        var deferred = $q.defer();
+        var promise = deferred.promise;
+        // Charge l'arborescence du répertoire partagé.
+        ajaxRequest({
+            "method": "GET",
+            "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vitis/exploitations/SharedDirectory",
+            "success": function(response) {
+                if (response["data"]["status"] === 1) {
+                    if (typeof (response["data"]) !== "undefined")
+                        deferred.resolve(response["data"]["tree"]["data"]);
+                }
+            }
+        });
+        return promise;
+    };
+    
+    /**
+     * deleteSharedDirectoryFiles function.
+     * Charge les données du treeview du répertoire partagé.
+     **/
+    angular.element(vitisApp.appMainDrtv).scope()["deleteSharedDirectoryFiles"] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var $rootScope = angular.element(vitisApp.appMainDrtv).injector().get(["$rootScope"]);
+        var $translate = angular.element(vitisApp.appMainDrtv).injector().get(["$translate"]);
+        var propertiesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["propertiesSrvc"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        var formSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["formSrvc"]);
+        //
+        $log.info("deleteSharedDirectoryFiles");
+        var oFormElementDefinition = formSrvc["getFormElementDefinition"]("shared_directory", envSrvc["sFormDefinitionName"]);
+        var aFileList = $("#" + oFormElementDefinition["id"] + "_treeview")["treeview"](true)["getChecked"]();
+        if (aFileList.length > 0) {
+            var oOptions = {
+                "className": "modal-warning",
+                "message": "CONFIRM_DELETE_FILES_EXPLOITATION_EXPLOITATION",
+                "callback": function(bResponse) {
+                    if (bResponse) {
+                        // Liste des fichiers et répertoires à supprimer.
+                        var aFilePathList = [];
+                        for (var i = 0; i < aFileList.length; i++) {
+                            if (typeof(aFileList[i]["path"]["nodes"] != "undefined"))
+                                aFilePathList.push(aFileList[i]["path"]);
+                            else
+                                aFilePathList.push(aFileList[i]["path"] + "/" + aFileList[i]["name"]);
+                        }
+                        // Suppression des fichiers et répertoires.
+                        ajaxRequest({
+                            "method": "DELETE",
+                            "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vitis/exploitations/SharedDirectory",
+                            "params": {
+                                "idList": aFilePathList.join("|")
+                            },
+                            "success": function(response) {
+                                if (response["data"]["status"] == 1) {
+                                    // Message et rechargement du treeview.
+                                    $translate("SUCCESSFUL_OPERATION").then(function (sTranslation) {
+                                        $.notify(sTranslation, "success");
+                                        $rootScope["refreshExploitationSharedDirectoryTreeview"]();
+                                    });
+                                }
+                                else {
+                                    // Affichage de la fenêtre modale d'erreur.
+                                    $rootScope["modalWindow"]("dialog", response["data"]["errorMessage"], {"className": "modal-danger"});
+                                }
+                            }
+                        });
+                    }
+                }
+            }
+            $rootScope["modalWindow"]("confirm", "", oOptions);
+        }
+    };
+    
+    /**
+     * createSharedDirectoryFolder function.
+     * Création d'un répertoire dans le répertoire partagé.
+     **/
+    angular.element(vitisApp.appMainDrtv).scope()["createSharedDirectoryFolder"] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var $translate = angular.element(vitisApp.appMainDrtv).injector().get(["$translate"]);
+        var $rootScope = angular.element(vitisApp.appMainDrtv).injector().get(["$rootScope"]);
+        var propertiesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["propertiesSrvc"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        var formSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["formSrvc"]);
+        //
+        $log.info("createSharedDirectoryFolder");
+        // Si un répertoire est sélectionné -> création à l'intérieur.
+        var sDirectoryPath = envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["directory_name"];
+        if (typeof(sDirectoryPath) == "string" && sDirectoryPath != "") {
+            var oFormElementDefinition = formSrvc["getFormElementDefinition"]("shared_directory", envSrvc["sFormDefinitionName"]);
+            var aFileList = $("#" + oFormElementDefinition["id"] + "_treeview")["treeview"](true)["getSelected"]();
+            if (aFileList.length > 0)
+                sDirectoryPath = aFileList[0]["path"] + "/" + sDirectoryPath;
+            //
+            var formData = new FormData();
+            formData.append("directory_path", sDirectoryPath);
+            ajaxRequest({
+                "method": "POST",
+                "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vitis/exploitations/SharedDirectory/Directory",
+                "data": formData,
+                "success": function(response) {
+                    if (response["data"]["status"] == 1) {
+                        // Message et rechargement du treeview.
+                        $translate("SUCCESSFUL_OPERATION").then(function (sTranslation) {
+                            $.notify(sTranslation, "success");
+                            $rootScope["refreshExploitationSharedDirectoryTreeview"]();
+                            var sFormElementName = envSrvc['oFormDefinition'][envSrvc['sFormDefinitionName']]['name'];
+                            document.querySelector("form[name='" + sFormElementName + "']").reset();
+                        });
+                    }
+                    else {
+                        // Affichage de la fenêtre modale d'erreur.
+                        $rootScope["modalWindow"]("dialog", response["data"]["errorMessage"], {"className": "modal-danger"});
+                    }
+                }
+            });
+        }
+        else {
+            // Affichage de la fenêtre modale d'erreur.
+            $rootScope["modalWindow"]("dialog", "FORM_NO_DIRECTORY_EXPLOITATION_EXPLOITATION", {"className": "modal-danger"});
+        }
+    };
+    
+    /**
+     * uploadSharedDirectoryFile function.
+     * Upload d'un fichier dans le répertoire partagé.
+     **/
+    angular.element(vitisApp.appMainDrtv).scope()["uploadSharedDirectoryFile"] = function () {
+        // Injection des services.
+        var $log = angular.element(vitisApp.appMainDrtv).injector().get(["$log"]);
+        var $translate = angular.element(vitisApp.appMainDrtv).injector().get(["$translate"]);
+        var $rootScope = angular.element(vitisApp.appMainDrtv).injector().get(["$rootScope"]);
+        var propertiesSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["propertiesSrvc"]);
+        var envSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["envSrvc"]);
+        var formSrvc = angular.element(vitisApp.appMainDrtv).injector().get(["formSrvc"]);
+        //
+        $log.info("uploadSharedDirectoryFile");
+        // Si un fichier est sélectionné -> upload.
+        var oFile = envSrvc["oFormValues"][envSrvc["sFormDefinitionName"]]["file"];
+        if (typeof(oFile) != "undefined" && oFile["aFiles"].length > 0) {
+            // Upload dans un répertoire.
+            var sDirectoryPath = "";
+            var oFormElementDefinition = formSrvc["getFormElementDefinition"]("shared_directory", envSrvc["sFormDefinitionName"]);
+            var aFileList = $("#" + oFormElementDefinition["id"] + "_treeview")["treeview"](true)["getSelected"]();
+            if (aFileList.length > 0)
+                sDirectoryPath = aFileList[0]["path"];
+            // Création du formdata.
+            var formData = new FormData();
+            formData.append("file", oFile["aFiles"][0]);
+            formData.append("directory_path", sDirectoryPath);
+            //
+            ajaxRequest({
+                "method": "POST",
+                "url": propertiesSrvc["web_server_name"] + "/" + propertiesSrvc["services_alias"] + "/vitis/exploitations/SharedDirectory/File",
+                "data": formData,
+                "success": function(response) {
+                    if (response["data"]["status"] == 1) {
+                        // Message, rechargement du treeview, vidage du formulaire.
+                        $translate("SUCCESSFUL_OPERATION").then(function (sTranslation) {
+                            $.notify(sTranslation, "success");
+                            $rootScope["refreshExploitationSharedDirectoryTreeview"]();
+                            var sFormElementName = envSrvc['oFormDefinition'][envSrvc['sFormDefinitionName']]['name'];
+                            document.querySelector("form[name='" + sFormElementName + "']").reset();
+                        });
+                    }
+                    else {
+                        // Affichage de la fenêtre modale d'erreur.
+                        $rootScope["modalWindow"]("dialog", response["data"]["errorMessage"], {"className": "modal-danger"});
+                    }
+                }
+            });
+        }
+        else {
+            // Affichage de la fenêtre modale d'erreur.
+            $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
old mode 100755
new mode 100644
index c8132242ba9258b6005e2fd7d9f502e8311efd72..dc98a487ebd474dde8d906521ce10687fd6b5a2f
--- a/client/modules/vitis/lang/lang-en.json
+++ b/client/modules/vitis/lang/lang-en.json
@@ -326,5 +326,21 @@
     "FORM_BILLINGGROUP_USERS_BILLINGGROUP": "Name",
     "FORM_DESCRIPTION_USERS_BILLINGGROUP": "Description",
     "FORM_AVAILABLE_USER_USERS_BILLINGGROUP": "Available users",
-    "FORM_LINKED_USER_USERS_BILLINGGROUP": "Users linked to group"
+    "FORM_LINKED_USER_USERS_BILLINGGROUP": "Users linked to group",
+    "" : "",
+    "FORM_TITLE_EXPLOITATION_EXPLOITATION" : "Shared directory",
+    "FORM_DOWNLOAD_FILE_EXPLOITATION_EXPLOITATION" : "Download file",
+    "FORM_RELOAD_DIRECTORY_EXPLOITATION_EXPLOITATION" : "Reload directory",
+    "FORM_DELETE_FILES_EXPLOITATION_EXPLOITATION" : "Delete files",
+    "FORM_UPLOAD_FMW_FILE_EXPLOITATION_EXPLOITATION" : "Upload",
+    "FORM_FILE_EXPLOITATION_EXPLOITATION" : "File to upload",
+    "CONFIRM_DELETE_FILES_EXPLOITATION_EXPLOITATION" : "Delete selected files and directories ?",
+    "FORM_CREATE_DIRECTORY_EXPLOITATION_EXPLOITATION" : "Create a directory",
+    "FORM_DIRECTORY_EXPLOITATION_EXPLOITATION" : "Name of the directory to create",
+    "FORM_BTN_UPLOAD_FILE_EXPLOITATION_EXPLOITATION" : "Upload",
+    "FORM_BTN_CREATE_DIRECTORY_EXPLOITATION_EXPLOITATION" : "Create",
+    "FORM_NO_DIRECTORY_EXPLOITATION_EXPLOITATION" : "Please specify a name for the directory to create",
+    "FORM_NO_FILE_EXPLOITATION_EXPLOITATION" : "Please select a file to upload",
+    "DIRECTORY_CREATION_ERROR_EXPLOITATION_EXPLOITATION" : "Directory creation error",
+    "FILE_UPLOAD_ERROR_EXPLOITATION_EXPLOITATION" : "File creation error"
 }
diff --git a/client/modules/vitis/lang/lang-fr.json b/client/modules/vitis/lang/lang-fr.json
old mode 100755
new mode 100644
index a25cbd86a472840b7cd34f0aeb4db57686e83610..c752c00a89122b4ccf90a5bb275a952f7ebfc775
--- a/client/modules/vitis/lang/lang-fr.json
+++ b/client/modules/vitis/lang/lang-fr.json
@@ -328,5 +328,21 @@
     "FORM_BILLINGGROUP_USERS_BILLINGGROUP": "Nom",
     "FORM_DESCRIPTION_USERS_BILLINGGROUP": "Description",
     "FORM_AVAILABLE_USER_USERS_BILLINGGROUP": "Utilisateurs disponibles",
-    "FORM_LINKED_USER_USERS_BILLINGGROUP": "Utilisateurs liés au groupe"
+    "FORM_LINKED_USER_USERS_BILLINGGROUP": "Utilisateurs liés au groupe",
+    "" : "",
+    "FORM_TITLE_EXPLOITATION_EXPLOITATION" : "Répertoire partagé",
+    "FORM_DOWNLOAD_FILE_EXPLOITATION_EXPLOITATION" : "Télécharger le fichier",
+    "FORM_RELOAD_DIRECTORY_EXPLOITATION_EXPLOITATION" : "Recharger le répertoire",
+    "FORM_DELETE_FILES_EXPLOITATION_EXPLOITATION" : "Supprimer les fichiers",
+    "FORM_UPLOAD_FMW_FILE_EXPLOITATION_EXPLOITATION" : "Uploader",
+    "FORM_FILE_EXPLOITATION_EXPLOITATION" : "Fichier à uploader",
+    "CONFIRM_DELETE_FILES_EXPLOITATION_EXPLOITATION" : "Supprimer les fichiers et répertoires sélectionnés ?",
+    "FORM_CREATE_DIRECTORY_EXPLOITATION_EXPLOITATION" : "Créer un dossier",
+    "FORM_DIRECTORY_EXPLOITATION_EXPLOITATION" : "Nom du dossier à créer",
+    "FORM_BTN_UPLOAD_FILE_EXPLOITATION_EXPLOITATION" : "Uploader",
+    "FORM_BTN_CREATE_DIRECTORY_EXPLOITATION_EXPLOITATION" : "Créer",
+    "FORM_NO_DIRECTORY_EXPLOITATION_EXPLOITATION" : "Veuiller spécifier un nom pour le dossier à créer",
+    "FORM_NO_FILE_EXPLOITATION_EXPLOITATION" : "Veuiller sélectionner un fichier à uploader",
+    "DIRECTORY_CREATION_ERROR_EXPLOITATION_EXPLOITATION" : "Erreur de création du dossier",
+    "FILE_UPLOAD_ERROR_EXPLOITATION_EXPLOITATION" : "Erreur pendant l'upload du fichier"
 }
diff --git a/client/modules/vitis/less/main.less b/client/modules/vitis/less/main.less
index 66adeeb6954871428c3685880d1a6a9bbb8ee302..bbfd6cb88daa780124cac53154b6278d493816d8 100755
--- a/client/modules/vitis/less/main.less
+++ b/client/modules/vitis/less/main.less
@@ -7,4 +7,5 @@
 @import 'updateConfiguration.less';
 @import 'users.less';
 @import 'activeDirectoryTree.less';
-@import 'webServiceHelp.less';
\ No newline at end of file
+@import 'webServiceHelp.less';
+@import 'sharedDirectory.less';
\ No newline at end of file
diff --git a/client/modules/vitis/less/sharedDirectory.less b/client/modules/vitis/less/sharedDirectory.less
new file mode 100755
index 0000000000000000000000000000000000000000..7672659599a8c4ad76d0f469e8114d4202d7a937
--- /dev/null
+++ b/client/modules/vitis/less/sharedDirectory.less
@@ -0,0 +1,3 @@
+.shared-directory-treeview .treeview {
+    overflow-y: auto;
+}
\ No newline at end of file
diff --git a/vas/rest/class/aws_lib/AmazonAWS.class.inc b/vas/rest/class/aws_lib/AmazonAWS.class.inc
old mode 100755
new mode 100644
index 67f30140fb630544249a97969ea0e7b51f7259c1..223a0534b6262627e65631e7905eb9256825f8b9
--- a/vas/rest/class/aws_lib/AmazonAWS.class.inc
+++ b/vas/rest/class/aws_lib/AmazonAWS.class.inc
@@ -13,6 +13,7 @@ Class AmazonAWS {
     public $sAwsRegion;
     public $aLastCurlRequestInfo;
     public $sHost;
+    public $sLogFilePath;   // Chemin optionnel vers le fichier de log pour Amazon S3.
     private $sAwsAccessKeyId;
     private $sAwsSecretAccessKey;
     private $sHashingAlgorithmString;
@@ -467,5 +468,18 @@ Class AmazonAWS {
     function generateAuthorizationHeader($sAlgorithm, $sCredentialScope, $sSignedHeaders, $sSignature) {
         return $sAlgorithm . ' Credential=' . $this->sAwsAccessKeyId . '/' . $sCredentialScope . ', SignedHeaders=' . $sSignedHeaders . ', Signature=' . $sSignature;
     }
+    
+    /**
+     * 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/vas/rest/class/aws_lib/AmazonS3.class.inc b/vas/rest/class/aws_lib/AmazonS3.class.inc
old mode 100755
new mode 100644
index f9bfdb4dcc555ceb4122ffec2b794e4a3180b82f..32c7ed76f933ba2499f7cfa63c4a943cb4fa6bd9
--- a/vas/rest/class/aws_lib/AmazonS3.class.inc
+++ b/vas/rest/class/aws_lib/AmazonS3.class.inc
@@ -102,9 +102,6 @@ Class AmazonS3 extends AmazonAWS {
         }
 
         $sFullUrl = $sMethod . ' ' . $sUrl . ' HTTP/1.1';
-
-        error_log($sFullUrl);
-
         return $this->generateAwsSignedHeaders($sFullUrl, $sBucketHost, self::API_COMPONENT_SERVICE, $aHeaders, $sRequestPayload, true, 'Now', true);
     }
 
@@ -171,8 +168,10 @@ Class AmazonS3 extends AmazonAWS {
         // Transfert cURL.
         $sRequestResult = $this->curlRequest($sUrl, $sMethod, null, $aHeaders);
         //
-        if ($this->aLastCurlRequestInfo['http_code'] != 200)
-            writeToErrorLog($sRequestResult);
+        if ($this->aLastCurlRequestInfo['http_code'] != 200) {
+            $this->writeToErrorLog($this->formatS3ErrorMessage($sRequestResult));
+            return false;
+        }
         else {
             if (!empty($sFilePath))
                 file_put_contents($sFilePath, $sRequestResult);
@@ -191,24 +190,23 @@ Class AmazonS3 extends AmazonAWS {
     function uploadFile($sBucket, $sKey, $sFilePath) {
         if (file_exists($sFilePath)) {
             $sFileName = pathinfo($sFilePath, PATHINFO_BASENAME);
-
             // Url vers le fichier.
             $sUrl = 'https://' . $sBucket . '.' . $this->sHost;
-
             // Génération des entêtes pour la requete.
             $aPostData = $this->generatePostData($sBucket, $sKey);
             $aPostData['Content-Type'] = mime_content_type($sFilePath);
             $aPostData['file'] = new CurlFile(realpath($sFilePath), $aPostData['Content-Type'], $sFileName);
-
             $aHeaders = array(
                 'Content-Type: multipart/form-data',
             );
-
             $sRequestResult = $this->curlRequest($sUrl, 'post', $aPostData, $aHeaders, true);
-
-            if ($this->aLastCurlRequestInfo['http_code'] != 204)
-                writeToErrorLog($sRequestResult);
+            if ($this->aLastCurlRequestInfo['http_code'] != 204) {
+                $this->writeToErrorLog($this->formatS3ErrorMessage($sRequestResult));
+                return false;
+            }
         }
+        else
+            return false;
     }
 
     /**
@@ -229,10 +227,12 @@ Class AmazonS3 extends AmazonAWS {
         $aHeaders = $this->generateS3requestHeaders($sMethod, $sUrl, $sBucket, array('Content-Type: application/x-www-form-urlencoded'), '');
         // Transfert cURL.
         $sRequestResult = $this->curlRequest($sUrl, $sMethod, null, $aHeaders);
-        //error_log($sRequestResult);
-        if ($this->aLastCurlRequestInfo['http_code'] != 200){
-            writeToErrorLog("ERROR: ScanDir can't scan this prefix or this bucket");
-        } else {
+        if ($this->aLastCurlRequestInfo['http_code'] != 200) {
+            $this->writeToErrorLog("ERROR: ScanDir can't scan this prefix or this bucket");
+            $this->writeToErrorLog($this->formatS3ErrorMessage($sRequestResult));
+            return false;
+        }
+        else {
             $oXMLContent= json_decode(json_encode(simplexml_load_string($sRequestResult)), true);
             $oFiles = $this->awsObjectListXmlToTree($oXMLContent, $bWithFileInfos);
         }
@@ -332,14 +332,44 @@ Class AmazonS3 extends AmazonAWS {
         // Transfert cURL.
         $sRequestResult = $this->curlRequest($sUrl, $sMethod, null, $aHeaders);
         
-        if ($this->aLastCurlRequestInfo['http_code'] != 200){
-            writeToErrorLog("ERROR: it's impossible to delete this key in this bucket");
-        } else {
+        if ($this->aLastCurlRequestInfo['http_code'] != 200) {
+            $this->writeToErrorLog("ERROR: it's impossible to delete this key in this bucket");
+            $this->writeToErrorLog($this->formatS3ErrorMessage($sRequestResult));
+        } else
             $bReturn = true;
-            error_log($sRequestResult);
-        }
 
         return $bReturn;
     }
+    
+    /**
+     * Convert an error message returned by s3 (xml to object).
+     * @param {string} $sXmlErrorMessage Error message returned by s3 (xml format).
+     * @return object S3 Error 
+     */
+    function getS3ErrorObject($sXmlErrorMessage) {
+        $oSimpleXmlElement = simplexml_load_string($sXmlErrorMessage);
+        if (is_object($oSimpleXmlElement)) {
+            $oErrorMessage = new stdClass();
+            foreach ($oSimpleXmlElement as $sProperty => $oValue) {
+                $oErrorMessage->$sProperty = $oValue->__toString();
+            }
+            return $oErrorMessage;
+        }
+        else
+            return false;
+    }
+    
+    /**
+     * Format an error message returned by s3.
+     * @param {string} $sXmlErrorMessage Error message returned by s3 (xml format).
+     * @return string Error message
+     */
+    function formatS3ErrorMessage($sXmlErrorMessage) {
+        $oErrorMessage = $this->getS3ErrorObject($sXmlErrorMessage);
+        if ($oErrorMessage !== false)
+            return ($oErrorMessage->Code . ' : ' . $oErrorMessage->Message);
+        else
+            return $sXmlErrorMessage;
+    }
 }
 ?>
\ No newline at end of file
diff --git a/vas/rest/class/vitis_lib/VitisError.class.inc b/vas/rest/class/vitis_lib/VitisError.class.inc
index 0d61f69fcd02cf3cf89e8758a57bb2723d85eef4..1c52cfaa95a3a0479a910281e35cde8f25376703 100644
--- a/vas/rest/class/vitis_lib/VitisError.class.inc
+++ b/vas/rest/class/vitis_lib/VitisError.class.inc
@@ -4,7 +4,7 @@ require_once(__DIR__."/DbClass.class.inc");
 
 class VitisError extends DbClass  {
 		
-    function __construct($iErrorId, $sMessage=""){
+    function __construct($iErrorId, $sErrorMessage="", $sMessage = ''){
 		$this->aFields['errorCode']=$iErrorId;	
 		switch ($iErrorId){
 			case 1 :
@@ -57,9 +57,17 @@ class VitisError extends DbClass  {
 			break;
 			case 18 :
 				$this->aFields['errorType']="Missing privileges";
+			case 17 :
+				$this->aFields['errorType']="The request returned an error";
+			break;
+			case 19 :
+				$this->aFields['errorType']="The database is unreachable";
 			break;
 		}
-		$this->aFields['errorMessage']=$sMessage; //Message renvoyé par la base de donnée
+		$this->aFields['errorMessage']=$sErrorMessage; //Message renvoyé par la base de donnée
+		// Message d'erreur additionnel.
+		if (!empty($sMessage))
+		    $this->aFields['message'] = $sMessage;
     }
 }
 ?>
\ No newline at end of file
diff --git a/vas/rest/class/vmlib/BD.class.inc b/vas/rest/class/vmlib/BD.class.inc
old mode 100755
new mode 100644
diff --git a/vas/rest/class/vmlib/error.inc b/vas/rest/class/vmlib/error.inc
old mode 100755
new mode 100644
index b36e043d301409462ee479bed0ea211463bb8a54..13db7b08ff362840fee0ef2bd2d8b84d0c63b52b
--- a/vas/rest/class/vmlib/error.inc
+++ b/vas/rest/class/vmlib/error.inc
@@ -19,6 +19,10 @@ define('ERROR_0008', "ERROR - Aucune méthode n'a permis d'affecté un moteur au
 // define('ERROR_0009', "ERROR - L'algorithme ne permet pas de retourner un numéro de moteur exploitable. Le numéro de moteur retourné n'est pas de type entier. Type de la valeur retournée par la méthode : ");
 // define('ERROR_0010', "ERROR - Le numéro du moteur retourné par l'algorithme n'existe pas dans la liste des moteurs disponible dans GTF.");
 define('ERROR_0011', "Erreur Le fichier [_FILES[sNomObjet][name]] n'est pas téléchargé sur le serveur");
+define('ERROR_0035', "Erreur de la suppression d'un processus d'une demande stoppée");
+define('ERROR_0036', "Erreur de la commande d'information d'un processus d'une demande stoppée");
+define('ERROR_0037', "Erreur pendant l'arrêt de la demande sur Fme Desktop.");
+define('ERROR_0038', "Erreur pendant l'arrêt de la demande sur Fme Server.");
 
 // veremap/DownloadMaj.class.inc
 define('ERROR_0012', "Unable to write file");
diff --git a/vas/rest/class/vmlib/logUtil.inc b/vas/rest/class/vmlib/logUtil.inc
old mode 100755
new mode 100644
index f1334250b8024768910a30fecc9ac5a58b72f681..d7474ff379d5a0cf1850ac78f8ab2f5712560450
--- a/vas/rest/class/vmlib/logUtil.inc
+++ b/vas/rest/class/vmlib/logUtil.inc
@@ -7,7 +7,7 @@
  * Fonctions de mise en place de logs
  *
  * \author Olivier Gayte <olivier.gayte@veremes.com>
- * \author Fr�d�ric Mauro
+ * \author Frédéric Mauro
  */
 /*
  * Variable globale stockant une erreur.
@@ -20,8 +20,8 @@ $sMessageLogError = "";
 $sFolderLib = "vmlib";
 /**
  * Converti une chaine ISO-8859-1 en UTF-8
- * \param $sString Cha�ne de caract�res � convertir.
- * \return une chaine encod�e en UTF-8
+ * \param $sString Chaîne de caractères à convertir.
+ * \return une chaine encodée en UTF-8
  */
 /* function Latin1ToUtf8($sString){ 
   if( mb_detect_encoding($sString,"UTF-8, ISO-8859-1")!="UTF-8" ){
@@ -52,22 +52,45 @@ function writeToLog($sString, $sFileName) {
         return false;
     global $properties, $sMessageLogError, $sFolderLib;
 
-    // Fred 05/06/2013 : 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)))
         return false;
- 
+
+    // Add Date and User informations before writing message in log file
     loadLang($sFolderLib, $properties["language"], $sFolderLib . "/");
     $sString = str_replace(chr(13), '[\n]', $sString);
     $sString = str_replace(chr(10), '[\n]', $sString);
-    $handle = fopen($sFileName, 'a');
     if(isset($_SESSION['ses_Login']) && isset($_SERVER['REMOTE_ADDR']) && isset($_SERVER['REMOTE_PORT'])){
         $sPrelog = date("d/n/Y H:i:s").' '.$_SESSION['ses_Login'].' '.$_SERVER['REMOTE_ADDR'] . ':' . $_SERVER['REMOTE_PORT'];
     } else {
         $sPrelog = date("d/n/Y H:i:s");
     }
-    if (fwrite($handle, $sPrelog . $properties["log_delim"] . $sString . CR . LF) === false) {
+
+    $sMessageLogtoWrite = $sPrelog . $properties["log_delim"] . $sString . CR . LF;
+
+    // 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);
+
+    if($iLogFileSize !== false){
+        // get size of log message
+        $iMessageLength = strlen($sMessageLogtoWrite);
+        $iTotalSizeKb = ($iLogFileSize + $iMessageLength) / 1024;
+        // compare with porperties log_size (maximum log size to open it through app in Kb)
+        if($iTotalSizeKb >= $properties['log_size'] - 1){
+            // Rename of the original file to split log and keep the possibility to read it through application
+            $sFileSplitName = str_replace(".log", "." . date("Y_m_d_U") . ".log", $sFileName);
+            if(!rename($sFileName, $sFileSplitName)){
+                $sMessageLogError = ERROR_IMPOSSIBLE_WRITE . $sFileName . ERROR_RIGHTS_ON_FILE . " (" . $sString . ").";
+            }
+        }
+    }
+
+    // create if needed and open log file to write log message inside. 
+    $handle = fopen($sFileName, 'a');
+    if (fwrite($handle, $sMessageLogtoWrite) === false) {
         fclose($handle);
         if (is_writable($sFileName)) {
             $sMessageLogError = ERROR_IMPOSSIBLE_WRITE . $sFileName . ERROR_RIGHTS_ON_FILE . " (" . $sString . ").";
diff --git a/vas/rest/class/vmlib/phpUtil.inc b/vas/rest/class/vmlib/phpUtil.inc
index 08c287ba00d806bb737927d08cdc2a9f5ca93229..dee4b832527ccda3d2af6ca01b50acc49085d063 100755
--- a/vas/rest/class/vmlib/phpUtil.inc
+++ b/vas/rest/class/vmlib/phpUtil.inc
@@ -203,9 +203,10 @@ function getFileName($sFullFileName) {
  *@file vmlib/phpUtil.inc
  *@param string $sFolder
  *@param string $sDestination
+ *@param string $sPassword
  *@return boolean
  */
-function createZip($sFolder, $sDestination, $sExtensionToExclude = '') {
+function createZip($sFolder, $sDestination, $sExtensionToExclude = '', $sPassword = '', $bDeleteFiles = false) {
     if (!empty($sExtensionToExclude)) {
         $aExtensionToExclude = explode('|', $sExtensionToExclude);
     } else {
@@ -222,6 +223,7 @@ function createZip($sFolder, $sDestination, $sExtensionToExclude = '') {
     $files = new RecursiveIteratorIterator(
             new RecursiveDirectoryIterator($sFolder), RecursiveIteratorIterator::LEAVES_ONLY
     );
+    $aCompressedFiles = array();
     foreach ($files as $name => $file) {
         if (!$file->isDir()) {
             $filePath = $file->getRealPath();
@@ -234,12 +236,23 @@ function createZip($sFolder, $sDestination, $sExtensionToExclude = '') {
             if (in_array($sExtension, $aExtensionToExclude)) {
                 continue;
             }
-            $zip->addFile($filePath, $relativePath);
+            if ($zip->addFile($filePath, $relativePath))
+                $aCompressedFiles[] = $filePath;
+            // Mot de passe.
+            if (!empty($sPassword))
+                $zip->setEncryptionName($oFileInfo->getFilename(), ZipArchive::EM_AES_256, $sPassword);
         }
     }
 
-    $zip->close();
-
+    if ($zip->close()) {
+        // Suppression des fichiers compressés.
+        if ($bDeleteFiles) {
+            foreach ($aCompressedFiles as $sFilePath) {
+                if (file_exists($sFilePath))
+                    unlink($sFilePath);
+            }
+        }
+    }
     return file_exists($sDestination);
 }
 
diff --git a/vas/rest/class/wab_lib/BusinessObject.class.inc b/vas/rest/class/wab_lib/BusinessObject.class.inc
index 34c24838743268ee7a5b0f40694ddb4094775403..36ae854ee3dd0789c11f938c6eba90dda09a36bf 100755
--- a/vas/rest/class/wab_lib/BusinessObject.class.inc
+++ b/vas/rest/class/wab_lib/BusinessObject.class.inc
@@ -21,7 +21,6 @@ class WabBusinessObject {
     protected $aSql = array();
     protected $bNoError = true;
     protected $sErrorMessage;
-    protected $aLastCurlRequestInfo = "";
 
     /*     * ****************************************************
       Class constructor
@@ -32,7 +31,7 @@ class WabBusinessObject {
 
     public function __construct($oBd, $aTableInfo, $aValues, $aProperties, $className, $iId = null) {
         require 'BusinessObject.class.sql.inc';
-        $this->aTableInfo = $aTableInfo;
+        //$this->aTableInfo = $aTableInfo;
         $this->oBd = $oBd;
         $this->aValues = $aValues;
         $this->aProperties = $aProperties;
@@ -41,12 +40,30 @@ class WabBusinessObject {
         $this->history = "";
     }
 
+    /*     * ****************************************************
+      Sauve l'action réalisé par l'utilisateur
+      \sEvent : action réalisé (changement de statut...)
+     * **************************************************** */
+
+    private function addHistoryEvent($sEvent) {
+        $this->history .= date('d/m/Y H:i') . ' | ' . $_SESSION['ses_Login'] . ' | ' . $sEvent . PHP_EOL;
+    }
 
-     /* *****************************************************
+    /*     * ****************************************************
       Change le statut
       \sStatus : statut
      * **************************************************** */
-
+/*
+    protected function setStatus($sStatus) {
+        // Mode insertion ?	
+        if (!empty($this->iId))
+            $this->bo_id = $this->iId;
+        //	
+        $this->status = $sStatus;
+        $this->addHistoryEvent($this->status);
+        $this->save();
+    }
+*/
     public function wabSetStatus($sSchema, $sTable, $sBoNameField, $mBoIdValue, $sStatusName, $sView = '') {
         require 'BusinessObject.class.sql.inc';
 
@@ -62,24 +79,20 @@ class WabBusinessObject {
           );
         $oResultat = $this->oBd->executeWithParams($aSQL["getStatusId"], $aParams);
 
-        //$this->status = $this->oBd->objetSuivant($oResultat)->status_id;
-		$oStatus = $this->oBd->objetSuivant($oResultat);
+        $this->status = $this->oBd->objetSuivant($oResultat)->status_id;
         // ajout historique
-        //$this->addHistoryEvent($this->status);
-        //$this->addHistoryEvent($oStatus->name);
-		// UPDATE dans la table avec le boName
+        $this->addHistoryEvent($this->status);
+        // UPDATE dans la table avec le boName
         $sSql = $aSQL["updateStatus"];
         $aParams = array(
           "SCHEMA" => array("value"=> $sSchema, "type"=> 'column_name'),
           "TABLE" => array("value"=> $sView, "type"=> 'column_name'),
-          "STATUS_ID" => array("value"=> $oStatus->status_id, "type"=> 'number'),
+          "STATUS_ID" => array("value"=> $this->status, "type"=> 'number'),
           "BOIDFIELD" => array("value"=> $sBoNameField, "type"=> 'column_name'),
           "BOID" => array("value"=> $mBoIdValue, "type"=> 'number')
           );
 
         $this->oBd->executeWithParams($sSql, $aParams);
-		
-		$this->aValues["status_id"] = $oStatus->status_id;
     }
 
     public function wabGetStatus($sSchema, $sTable, $sBoNameField, $mBoIdValue) {
@@ -96,28 +109,13 @@ class WabBusinessObject {
         $oResultat = $this->oBd->executeWithParams($sSql, $aParams);
         return $this->oBd->objetSuivant($oResultat)->name;
     }
-	
-	public function wabGetObject($sSchema, $sTable, $sBoNameField, $mBoIdValue){
-		require 'BusinessObject.class.sql.inc';
-		$aParams = array(
-          "SCHEMA" => array("value"=> $sSchema, "type"=> 'column_name'),
-          "TABLE" => array("value"=> $sTable, "type"=> 'column_name'),
-          "BOIDFIELD" => array("value"=> $sBoNameField, "type"=> 'column_name'),
-          "BOID" => array("value"=> $mBoIdValue, "type"=> 'number')
-          );
-
-        $oResultat = $this->oBd->executeWithParams($aSQL["getBoValues"], $aParams);
-		$oFields = (array) $this->oBd->objetSuivant($oResultat);
-		
-		return $oFields;
-	}
     /*     * ********************************************************************
       Ajoute une note
       \sLineAttribute : Champ de form. contenant la note à ajouter
       \sNoteAttribute : Champ de form. contenant l'historique des notes
      * ******************************************************************** */
 
-    public function addNote($sLineAttribute, $sNoteAttribute) {
+    protected function addNote($sLineAttribute, $sNoteAttribute) {
         if (!empty($this->aValues[$sLineAttribute])) {
             // Mode insertion ?
             if (!empty($this->iId))
@@ -223,10 +221,8 @@ class WabBusinessObject {
      * ******************************************************************** */
 
     function save() {
-        //$aValues = $this->getClassParameters();
-        //$this->oBd->update($this->aTableInfo['schema_name'], str_replace($this->aTableInfo["module"] . "_", "", $this->aTableInfo['name']), $aValues, $this->aTableInfo['id_field'], $this->bo_id, $this->aTableInfo['id_field_type']);
-		$aValues = $this->getClassParameters();
-        $this->oBd->update($this->aTableInfo['schema_name'], $this->aTableInfo['name'], $aValues, $this->aTableInfo['id_field'], $this->bo_id, $this->aTableInfo['id_field_type']);
+        $aValues = $this->getClassParameters();
+        $this->oBd->update($this->aTableInfo['schema_name'], str_replace($this->aTableInfo["module"] . "_", "", $this->aTableInfo['name']), $aValues, $this->aTableInfo['id_field'], $this->bo_id, $this->aTableInfo['id_field_type']);
     }
 
     /*     * ********************************************************************
@@ -257,38 +253,44 @@ class WabBusinessObject {
         
       $bNoError = true;
 
-      //get workspace id
-      $sSQL = "SELECT workspace_id FROM [SCHEMA_GTF].workspace WHERE key = [WK_KEY];";
-      $aParams = array(
-        "SCHEMA_GTF" => array('value'=> $this->aProperties["schema_gtf"], 'type' => 'column_name'),
-        "WK_KEY" => array('value'=> $sWorkspaceKey, 'type' => 'string'),
-      );
-      $oWK = $this->oBd->executeWithParams($sSQL, $aParams);
-      // oBd en erreur
-      $iWKid = $this->oBd->objetSuivant ($oWK)->workspace_id;
-      // Insertion de la demande
-      $sUrl = $this->aProperties['web_server_name'] . '/' . $this->aProperties['services_alias'] . '/gtf/userorders';
-      $postfields = array(
-      //'token'=>$sToken, 
-        'order_date' => date('Y-m-d'),
-        'workspace_id'=>$iWKid, 
-        'priority_id'=>$iPriorityId,
-        'email_option_id'=>$iEmailOptionId,
-        'wk_params'=>$sWkParams,
-        'xslstylesheet'=>$sXslStyleSheet
-      );
-        
-      if ( $sEmailNotifications != null){
-        $postfields['email_notifications'] = $sEmailNotifications;
+      if($properties['web_server_name'] === "[HTTP_HOST]"){
+        $properties['web_server_name'] = "https://localhost";
       }
-      
-      $oReturn = $this->contactCurrentApi("POST", 'gtf/userorders', $postfields , $sMode="json");
-	  
-	  error_log(print_r($oReturn, true));
 
-      if($oReturn === false){
+      // Get token  
+      $sToken = $this->getToken();
+
+      if ($sToken !== false) {
+
+        //get workspace id
+        $sSQL = "SELECT workspace_id FROM [SCHEMA_GTF].workspace WHERE key = [WK_KEY];";
+        $aParams = array(
+          "SCHEMA_GTF" => array('value'=> $this->aProperties["schema_gtf"], 'type' => 'column_name'),
+          "WK_KEY" => array('value'=> $sWorkspaceKey, 'type' => 'string'),
+        );
+        $oWK = $this->oBd->executeWithParams($sSQL, $aParams);
+        // oBd en erreur
+        $iWKid = $this->oBd->objetSuivant ($oWK)->workspace_id;
+        // Insertion de la demande
+        $sUrl = $this->aProperties['web_server_name'] . '/' . $this->aProperties['services_alias'] . '/gtf/userorders';
+        $postfields = array(
+          'token'=>$sToken, 
+          'order_date' => date('Y-m-d'),
+          'workspace_id'=>$iWKid, 
+          'priority_id'=>$iPriorityId,
+          'email_option_id'=>$iEmailOptionId,
+          'wk_params'=>$sWkParams,
+          'xslstylesheet'=>$sXslStyleSheet
+        );
+        
+        if ( $sEmailNotifications != null){
+          $postfields['email_notifications'] = $sEmailNotifications;
+        }
+
+        $oReturn = $this->postCurlRequest ($sUrl, $postfields);
+                 
+      } else
         $sErrorMsg = 'Error while performing a cURL session (' . __METHOD__ . ' (get token))';
-      }
 
       if ($sErrorMsg != '') {
         writeToErrorLog($sErrorMsg);
@@ -347,41 +349,32 @@ class WabBusinessObject {
       /Retour : string token
      * ******************************************************************** */
 
-    function getToken ($sServerRestUrl = '', $aAuthParams = null) {
-
-        if($this->aProperties['web_server_name'] === "[HTTP_HOST]"){
-          $this->aProperties['web_server_name'] = "https://localhost";
-        }
+    function getToken () {
 
-        if(empty($sServerRestUrl)){
-          $sServerRestUrl = $this->aProperties['web_server_name'] . '/' . $this->aProperties['services_alias'];
-        }
+      if($this->aProperties['web_server_name'] === "[HTTP_HOST]"){
+        $this->aProperties['web_server_name'] = "https://localhost";
+      }
+        $sUrl = $this->aProperties['web_server_name'] . '/' . $this->aProperties['services_alias'] . '/vitis/privatetoken';
 
-        $sUrl = $sServerRestUrl . '/vitis/privatetoken';
-		
-        if(!empty($aAuthParams)){
-          $postfields = $aAuthParams;
-        } else if(!empty($_SESSION["ses_Login"])){
+        if(!empty($_SESSION["ses_Login"])){
           $sUserPassword = trim(des(rtrim(utf8_decode($_SESSION['ses_Login'])), hexToString(rtrim($_SESSION['ses_Password'])), 0, 0, null));
           $postfields = array('user'=>$_SESSION["ses_Login"], 'password'=>$sUserPassword);
         } else {
           $postfields = array('user'=>$this->aProperties["login_bot"], 'password'=>$this->aProperties["pass_bot"]);
         }
 
-        //$oToken = json_decode($this->postCurlRequest ($sUrl, $postfields));
-        $oToken = json_decode($this->sendCurlRequest ("POST", $sUrl, json_encode($postfields), array("Accept: applicaton/json", "Content-Type: application/json")));
-		
+        $oToken = json_decode($this->postCurlRequest ($sUrl, $postfields));
         return $oToken->token;
     }
 
     /*     * ********************************************************************
-      envoi une requete curl en POST (DEPRECATED)
+      envoi une requete curl en POST
       \$sUrl : Url pour envoyer la requete
       \$postfields : array contenant les paramètres à envoyer
       /Retour : string token
      * ******************************************************************** */
     function postCurlRequest ($sUrl, $postfields) {
-		/*$ch = curl_init($sUrl);
+      $ch = curl_init($sUrl);
         curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
         curl_setopt($ch, CURLOPT_HTTPHEADER, array("Accept: application/json"));
         curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
@@ -389,153 +382,9 @@ class WabBusinessObject {
         curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
         curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
         curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
-        return curl_exec($ch);*/
-		$this->sendCurlRequest("POST", $sUrl, $postfield, array("Accept: application/json"));
-    }
-
-    function sendCurlRequest($sMethod, $sUrl, $aParams=array(), $aHeaders=array()){
-
-        $this->aLastCurlRequestInfo = '';
-        //
-        $ch = curl_init();
-        $sType = strtoupper($sMethod);
-        // Force la méthode de requête utilisée (GET, POST...).
-        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $sType);
-        // Url à utiliser.
-        if (($sType == 'GET' || $sType == 'DELETE') && !empty($aParams))
-            $sUrl .= '?' . http_build_query($aParams);
-        curl_setopt($ch, CURLOPT_URL, $sUrl);
-        // ajout des en-tête
-        curl_setopt($ch, CURLOPT_HTTPHEADER, $aHeaders);
-        // Retour sous forme de texte. 
-        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
-        // Requête POST PUT parameters.
-
-        if ($sType == 'POST' || $sType == 'PUT') {
-			if($sType == 'POST'){
-				curl_setopt($ch, CURLOPT_POST, true);
-			}
-            // Chaîne de requête en encodage URL.
-            //if (is_array($aParamsaParams) && !$bMultipartFormData)
-            //    $aParams = http_build_query($aParams);
-            // Données de la requête.
-            curl_setopt($ch, CURLOPT_POSTFIELDS, $aParams);
-            //
-            //curl_setopt($ch, CURLOPT_SAFE_UPLOAD, true);
-            // Entête pour la requête en POST.
-            //$aHeaders[] = 'Content-Type: application/x-www-form-urlencoded';
-        }
-
-        curl_setopt($ch, CURLINFO_HEADER_OUT, true);
-        curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
-        // 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_VERIFYHOST, false);
-        //
-        $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));
-        }
-        // Informations de la requête.
-        $aCurlInfo = curl_getinfo($ch);
-        $this->aLastCurlRequestInfo = $aCurlInfo;
-        
-        // Ferme la session CURL.
-        curl_close($ch);
-        return $output;
-    }
-
-    function contactCurrentApi($sMethod, $sUrlPath, $aParams=array(), $sMode="json", $aAuthParams = null){
-
-      if($this->aProperties['web_server_name'] === "[HTTP_HOST]"){
-          $this->aProperties['web_server_name'] = "https://localhost";
-        }
-
-      $sRestUrl = $this->aProperties['web_server_name'] . '/' . $this->aProperties['services_alias'];
-
-      $this->contactAnotherApi($sMethod, $sRestUrl, $sUrlPath, $aParams, $sMode, $aAuthParams);
+        return curl_exec($ch);
     }
 
-    function contactAnotherApi($sMethod, $sRestUrl, $sUrlPath, $aParams=array(), $sMode="json", $aAuthParams = null){
-        $mToken = $this->getToken($sRestUrl, $aAuthParams);
-		
-        $sUrl = $sRestUrl . "/" . $sUrlPath;
-
-        if($mToken !== false){
-
-            // modification des paramètres si besoin
-            $aSendParams = array();
-            $aHeaders = array("token: " . $mToken);
-
-            switch ($sMode) {
-                case 'json':
-                    $aSendParams = json_encode($aParams);
-                    $aHeaders[] = "Content-Type: application/json";
-                    $aHeaders[] = "Accept: application/json";
-                    break;
-                case 'query':
-                    $sUrl .= '?' . http_build_query($aParams);
-                    $aHeaders[] = "Accept: application/x-vm-json";
-                    break;
-                case 'urlencode':
-                    $aSendParams = http_build_query($aParams);
-                    $aHeaders[] = "Accept: application/x-www-form-urlencoded";
-                    break;
-                case 'formdata' :
-                    $aSendParams = $aParams;
-                    break;
-            }
-
-            $sOutput = $this->sendCurlRequest($sMethod, $sUrl, $aSendParams, $aHeaders);
-			error_log(print_r($this->aLastCurlRequestInfo, true));
-            return $sOutput;
-        } else {
-            writeToErrorLog("This user can't have a token on Calimap at URL : " . $sRestUrl);
-            return false;
-        }
-    }
-	
-	/**********************************************************************
-      Sauve l'historique deprecated
-    **********************************************************************/
-    function saveHistory() {
-        $aHistoryValues = array('bo_id' => $this->aValues["my_vitis_id"], 'login' => $_SESSION['ses_Login'], 'comment' => $this->status, 'date' => date('Y-m-d H:i:s'));
-        $this->oBd->insert($this->aTableInfo['schema_name'], 'history', $aHistoryValues, $this->aTableInfo['schema_name'] . '.history_history_id_seq', 'history_id');
-    }
-	/**********************************************************************
-      Sauve une note ou commentaire (history sert d'historique)
-    **********************************************************************/
-	function addHistoryLine($sComment, $sHistoryTable, $iBoId){
-		$sUser = 'u_scheduler';
-		if(isset($_SESSION['ses_Login']) && !empty($_SESSION['ses_Login'])){
-			$sUser = $_SESSION['ses_Login'];
-		}
-		
-		$aHistoryValues = array('bo_id' => $iBoId, 'login' => $sUser, 'comment' => $sComment, 'date' => date('Y-m-d H:i:s'));
-        $this->oBd->insert($this->aTableInfo['schema_name'], $sHistoryTable, $aHistoryValues, $this->aTableInfo['schema_name'] . '.seq_' . $sHistoryTable . "_id" , 'history_id');
-	}
-	
-	function commitNoteLine($sNoteLineField, $sNoteTable, $sBoTable, $sFieldId, $iBoId){
-		// get note line
-		$aFields = $this->wabGetObject($this->aTableInfo['schema_name'], $sBoTable, $sFieldId, $iBoId);
-		
-		if(!empty($aFields[$sNoteLineField])){
-			$sUser = 'u_scheduler';
-			if(isset($_SESSION['ses_Login']) && !empty($_SESSION['ses_Login'])){
-				$sUser = $_SESSION['ses_Login'];
-			}
-			$aNoteValues = array('bo_id' => $iBoId, 'login' => $sUser, 'comment' => $aFields[$sNoteLineField], 'date' => date('Y-m-d H:i:s'));
-			$this->oBd->insert($this->aTableInfo['schema_name'], $sNoteTable, $aNoteValues, $this->aTableInfo['schema_name'] . '.seq_' . $sNoteTable . "_id", 'history_id');
-		}
-		
-		// reset note line
-		$this->aValues[$sNoteLineField] = "";
-		$this->save();
-	}
-	
 }
 
 ?>
diff --git a/vas/rest/class/wab_lib/BusinessObject.class.sql.inc b/vas/rest/class/wab_lib/BusinessObject.class.sql.inc
index a18ed1f2df0594917c4cdf5ec15499b422dd2273..bf02e36db648547116d594e3689cc070a8d36fc8 100755
--- a/vas/rest/class/wab_lib/BusinessObject.class.sql.inc
+++ b/vas/rest/class/wab_lib/BusinessObject.class.sql.inc
@@ -1,6 +1,5 @@
 <?php
     $aSQL["getStatusId"] = 'SELECT * FROM [SCHEMA].rt_[TABLE]_status WHERE name = [STATUS_NAME]';
-	$aSQL["getBoValues"] = 'SELECT * FROM [SCHEMA].[TABLE] WHERE [TABLE].[BOIDFIELD]=[BOID]';
-    $aSQL["updateStatus"] = 'UPDATE [SCHEMA].[TABLE] SET status_id=[STATUS_ID] WHERE [TABLE].[BOIDFIELD]=[BOID]';
+    $aSQL["updateStatus"] = 'UPDATE [SCHEMA].v_[TABLE] SET status_id=[STATUS_ID] WHERE v_[TABLE].[BOIDFIELD]=[BOID]';
     $aSQL["getStatusName"] = 'SELECT name FROM [SCHEMA].rt_[TABLE]_status WHERE status_id = (SELECT status_id FROM [SCHEMA].[TABLE] WHERE [TABLE].[BOIDFIELD]=[BOID])';
 ?>
\ No newline at end of file
diff --git a/vas/rest/conf/properties.inc b/vas/rest/conf/properties.inc
old mode 100755
new mode 100644
diff --git a/vas/rest/conf/selected_properties.inc b/vas/rest/conf/selected_properties.inc
old mode 100755
new mode 100644
diff --git a/vas/rest/ws/vitis/Exploitations.class.inc b/vas/rest/ws/vitis/Exploitations.class.inc
new file mode 100755
index 0000000000000000000000000000000000000000..1703c2ce5b6eed19237293c8444271e3d0e4a709
--- /dev/null
+++ b/vas/rest/ws/vitis/Exploitations.class.inc
@@ -0,0 +1,362 @@
+<?php
+
+/**
+ * \file Exploitations.class.inc
+ * \class Exploitations
+ *
+ * \author Yoann Perollet <yoann.perollet@veremes.com>.
+ *
+ * 	\brief This file contains the Exploitations php class
+ *
+ * This class defines Rest Api to Vitis exploitations
+ * 
+ */
+require_once 'Vitis.class.inc';
+require_once __DIR__ . '/../../class/vitis_lib/Connection.class.inc';
+require_once(__DIR__ . '/../../class/vmlib/BdDataAccess.inc');
+
+class Exploitations extends Vitis {
+    /**
+     * @SWG\Definition(
+     *   definition="/exploitations",
+     *   allOf={
+     *     @SWG\Schema(ref="#/definitions/exploitations")
+     *   }
+     * )
+     * * @SWG\Tag(
+     *   name="Exploitations",
+     *   description="Operations about Exploitations"
+     * )
+     */
+
+    /**
+     * 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();
+    }
+
+    /**
+     * @SWG\Get(path="/exploitations/SharedDirectory",
+     *   tags={"Exploitations"},
+     *   summary="Get shared directory tree",
+     *   description="Request to get the shared directory tree",
+     *   operationId="GET",
+     *   produces={"application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/exploitations")
+     *     )
+     *  )
+     */
+
+    /**
+     * get Exploitations
+     * @return  Exploitations
+     */
+    function GET() {
+        // Arborescence du répertoire partagé.
+        if (strtolower($this->aPath[2]) == 'shareddirectory') {
+            $aTreeview = $this->getDirectoryTree($this->aProperties['shared_dir']);
+            if (!empty($aTreeview["data"][0]["nodes"]))
+                $this->aFields['tree']['data'] = $aTreeview["data"][0]["nodes"];
+            else
+                $this->aFields['tree']['data'] = [];
+        }
+        //
+        $aXmlRacineAttribute['status'] = 1;
+        $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        return $sMessage;
+    }
+
+    /**
+     * Get directory tree.
+     */
+    function getDirectoryTree($sDirectoryPath) {
+        $aReturn = array('status' => 1, 'message' => '');
+        // Création de l'arborescence des fichiers du répertoire.
+        if (!empty($sDirectoryPath)) {
+            $sDirectoryName = 'Downloads';
+            if (is_string($sDirectoryPath)) {
+                if (is_dir($sDirectoryPath)) {
+                    $aDirStructure = $this->getDirStructure($sDirectoryPath, $sDirectoryName, $sDirectoryName, "");
+                    $aTreeview["data"][] = $aDirStructure["data"];
+                    if (!empty($aDirStructure["files"])) {
+                        foreach ($aDirStructure["files"] as $aFiles) {
+                            $aTreeview["files"][] = $aFiles;
+                        }
+                    }
+                } else
+                    writeToErrorLog('scandir(' . $sDirectoryPath . '): failed to open dir');
+            }
+        }
+        return $aTreeview;
+    }
+
+    /*
+     * Retourne l'arborescence d'un répertoire formaté pour "bootstrap-treeview".
+     */
+
+    function getDirStructure($sDirectoryPath, $sSubDirectoryName, $sDirectoryName, $sFolder) {
+        $aFilteredDir['data'] = array('text' => $sSubDirectoryName, 'selectable' => true, 'path' => $sFolder . '/' . $sSubDirectoryName);
+        $aDir = scandir($sDirectoryPath);
+        // Les répertoires sont affichés avant les fichiers (idem windows).
+        $aSortedDir = array();
+        $aSortedFiles = array();
+        foreach ($aDir as $sName) {
+            $sPath = $sDirectoryPath . '/' . $sName;
+            $sFileType = filetype($sPath);
+            if ($sFileType == 'dir')
+                $aSortedDir[] = $sName;
+            else
+                $aSortedFiles[] = $sName;
+        }
+        sort($aSortedDir, SORT_STRING|SORT_FLAG_CASE);
+        sort($aSortedFiles, SORT_STRING|SORT_FLAG_CASE);
+        $aDir = array_merge($aSortedDir, $aSortedFiles);
+        //
+        if ($sSubDirectoryName !== $sDirectoryName)
+            $sFolder .= '/' . $sSubDirectoryName;
+
+        foreach ($aDir as $sName) {
+            $sPath = $sDirectoryPath . '/' . $sName;
+            $sFileType = filetype($sPath);
+            // Répertoire ?
+            if ($sFileType == 'dir') {
+                if ($sName != '.' && $sName != '..') {
+                    if (is_dir($sPath)) {
+                        $aDirStructure = $this->getDirStructure($sPath . '/', $sName, $sDirectoryName, $sFolder);
+                        //if (!empty($aDirStructure['data']['nodes'])) {
+                            // Structure du répertoire.
+                            $aFilteredDir['data']['nodes'][] = $aDirStructure['data'];
+                            // Liste des fichiers du répertoire.
+                            if (!empty($aDirStructure["files"])) {
+                                foreach ($aDirStructure["files"] as $aFiles) {
+                                    $aFilteredDir["files"][] = $aFiles;
+                                }
+                            }
+                        //}
+                    } else
+                        writeToErrorLog('scandir(' . $sPath . '): failed to open dir');
+                }
+            }
+            // fichier ?
+            if ($sFileType == 'file') {
+                // Taille + unité du fichier.
+                //$iFileSize = filesize($sPath);
+                $aFileInfos = stat($sPath);
+                $iFileSizeLabel = $aFileInfos['size'];
+                $aFileSizeUnity = array('o', 'Ko', 'Mo', 'Go', 'To');
+                $i = 0;
+                while ($iFileSizeLabel > 1024) {
+                    $iFileSizeLabel /= 1024;
+                    $i++;
+                }
+                // Sauve la structure du fichier pour le treeview.
+                $sFileLabel = $sName . ' (' . round($iFileSizeLabel) . ' ' . $aFileSizeUnity[$i] . ')';
+                $aFilteredDir['data']['nodes'][] = array(
+                    'folder' => $sFolder,
+                    'directory' => $sDirectoryName,
+                    'name' => $sName,
+                    'text' => $sFileLabel,
+                    'icon' => 'glyphicon glyphicon-file',
+                    'path' => str_replace('//', '/', $sFolder . '/' . '/' . $sName),
+                    //'tags' => array('<span class="glyphicon glyphicon-trash"></span>'),
+                    'size' => $aFileInfos['size'],
+                    'selectable' => false
+                );
+                // Sauve le nom et la date du fichier.
+                $aFilteredDir['files'][] = array(
+                    'path' => str_replace('//', '/', $sFolder . '/' . '/' . $sName),
+                    //'last_modif' => floor((time() - $aFileInfos['mtime']) / (24 * 3600))    // dernière modif. (Nb jours). 
+                );
+            }
+        }
+        return $aFilteredDir;
+    }
+    
+    /**
+     * @SWG\Post(path="/exploitations/SharedDirectory/Directory",
+     *   tags={"Exploitations"},
+     *   summary="Create directory",
+     *   description="Request to create a directory",
+     *   operationId="POST",
+     *   produces={"application/xml", "application/json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="formData",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *  @SWG\Parameter(
+     *     name="directory_path",
+     *     in="formData",
+     *     description="path of the directory",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/exploitations/SharedDirectory")
+     *    )
+     *  )
+     */
+
+    /**
+     * @SWG\Post(path="/exploitations/SharedDirectory/File",
+     *   tags={"Exploitations"},
+     *   summary="Ulpload file",
+     *   description="Request to upload a file",
+     *   operationId="POST",
+     *   produces={"application/xml", "application/json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="formData",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *  @SWG\Parameter(
+     *     name="directory_path",
+     *     in="formData",
+     *     description="path of the directory",
+     *     required=true,
+     *     type="string"
+     *   ),
+     *   @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/exploitations/SharedDirectory")
+     *    )
+     *  )
+     */
+    
+    /**
+     * insert user
+     * @return id of the user created
+     */
+    function POST() {
+        // Répertoire partagé.
+        if (strtolower($this->aPath[2]) == 'shareddirectory') {
+            // Création d'un répertoire.
+            if (strtolower($this->aPath[3]) == 'directory') {
+                if (!empty($this->aValues['directory_path'])) {
+                    if (mkdir($this->aProperties['shared_dir'] . '/' . $this->aValues['directory_path'])) {
+                        $aXmlRacineAttribute['status'] = 1;
+                        $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                    }
+                    else {
+                        $oError = new VitisError(1, 'DIRECTORY_CREATION_ERROR_EXPLOITATION_EXPLOITATION');
+                        $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                    }
+                }
+            }
+            // Upload d'un fichier.
+            else if (strtolower($this->aPath[3]) == 'file') {
+                if (!empty($_FILES["file"])) {
+                    if (!empty($this->aValues['directory_path']))
+                        $sFilePath = $this->aProperties['shared_dir'] . '/' . $this->aValues['directory_path'] . '/' . $_FILES["file"]["name"];
+                    else
+                        $sFilePath = $this->aProperties['shared_dir'] . '/' . $_FILES["file"]["name"];
+                    if (!move_uploaded_file($_FILES['file']['tmp_name'], $sFilePath)) {
+                        $oError = new VitisError(1, 'FILE_CREATION_ERROR_EXPLOITATION_EXPLOITATION');
+                        $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                    }
+                    else {
+                        $aXmlRacineAttribute['status'] = 1;
+                        $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                    }
+                }
+            }
+        }
+        return $sMessage;
+    }
+    
+    /**
+     * @SWG\Delete(path="/exploitations/SharedDirectory",
+     *   tags={"Exploitations"},
+     *   summary="delete shared directory files",
+     *   description="Request to delete shared directory files",
+     *   operationId="DELETE",
+     *   produces={"application/json", "application/x-vm-json"},
+     *   @SWG\Parameter(
+     *     name="token",
+     *     in="query",
+     *     description="user token",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * * @SWG\Parameter(
+     *     name="idList",
+     *     in="query",
+     *     description="path of the files",
+     *     required=true,
+     *     type="string"
+     *   ),
+     * @SWG\Response(
+     *         response=200,
+     *         description="Poprerties Response",
+     *         @SWG\Schema(ref="#/definitions/exploitations/SharedDirectory")
+     *     )
+     *  )
+     */
+
+    /**
+     * delete exploitation files
+     */
+    function DELETE() {
+        // Verify connection.
+        if (!empty($this->oConnection->oError)) {
+            $oError = $this->oConnection->oError;
+            $aXmlRacineAttribute['status'] = 0;
+            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            return $sMessage;
+        }
+        // Privilège "vitis_admin" requis.
+        if (!in_array('vitis_admin', $this->oConnection->aPrivileges)) {
+            $oError = new VitisError(1, "Rights problem : you don't have right to delete shared directory files");
+            $aXmlRacineAttribute['status'] = 0;
+            $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+            return $sMessage;
+        }
+        // Suppression des fichiers.
+        $aXmlRacineAttribute['status'] = 1;
+        $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+        if (!empty($this->aValues['idList'])) {
+            $aPathsToDelete = explode('|', $this->aValues['idList']);
+            $aDirToDelete = array();
+            foreach ($aPathsToDelete as $sPath) {
+                $sPath = str_replace('//', '/', $this->aProperties['shared_dir'] . $sPath);
+                if (file_exists($sPath)) {
+                    if (is_dir($sPath))
+                        array_unshift($aDirToDelete, $sPath);
+                    else
+                        unlink($sPath);
+                }
+            }
+        }
+        // Suppression des répertoires.
+        foreach ($aDirToDelete as $sPath) {
+            rmdir($sPath);
+        }
+        //
+        return $sMessage;
+    }
+}
+?>
\ No newline at end of file
diff --git a/vas/rest/ws/vitis/GenericQuerys.class.inc b/vas/rest/ws/vitis/GenericQuerys.class.inc
old mode 100755
new mode 100644
diff --git a/vas/rest/ws/vitis/Modes.class.inc b/vas/rest/ws/vitis/Modes.class.inc
old mode 100755
new mode 100644
index f9754ec0d4f3c9291507b34474333f70bcac1b52..c838ebe1c37627b79b3783a89d8f601904e94653
--- a/vas/rest/ws/vitis/Modes.class.inc
+++ b/vas/rest/ws/vitis/Modes.class.inc
@@ -34,8 +34,8 @@ class Modes extends Vitis {
      * 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) {
@@ -131,6 +131,11 @@ class Modes extends Vitis {
      */
     function GET() {
         if ($this->oConnection->oError == null) {
+            if (!empty($this->aProperties["public_token"]) && $this->aProperties["allow_public_connection"] === true){
+                if($this->aProperties["public_token"] === $this->aValues['token']){
+                    $this->aValues["filter"] = '{"relation": "AND","operators":[{"column": "mode_id","compare_operator": "<>","value": "user"}]}';
+                }
+            }
             if (isset($this->aValues['action']) && !empty($this->aValues['action'])) {
                 if ($this->aValues['action'] == 'getAll') {
                     $aReturn = $this->genericGet($this->aProperties['schema_framework'], "vm_mode_rolname", "mode_id", true);
diff --git a/vas/rest/ws/vitis/PrivateToken.class.inc b/vas/rest/ws/vitis/PrivateToken.class.inc
index 649dc10c0bc7100d38721af81cab49b19706eab2..8295dcb302800b3391b9833d953d442b1070f955 100644
--- a/vas/rest/ws/vitis/PrivateToken.class.inc
+++ b/vas/rest/ws/vitis/PrivateToken.class.inc
@@ -134,76 +134,85 @@ class PrivateToken extends Vitis {
         }
 
         if (!$bXMLError) {
-            //connect to database
-            $oBd = new BD($this->aValues["user"], $this->aValues["password"], $this->aProperties["database"], $this->aProperties["server"], $this->aProperties["port"], $this->aProperties["sgbd"], $this->aProperties["page_encoding"]);
-            $_SESSION["ses_Login"] = $this->aValues["user"];
-            $ciphertext = stringToHex(des($this->aValues["user"], $this->aValues["password"], 1, 0));
-            $_SESSION["ses_Password"] = $ciphertext;
-            $_SESSION["ses_Remember"] = false;
-            $_SESSION["ses_Date"] = date('Y-m-d H:i:s', time() + ($this->aValues['duration'] * 60));
-            if ($oBd->erreurRencontree) {
-                $oError = new VitisError(1, $oBd->sMessage);
+            // Teste si la base de données est joignable.
+            if (fsockopen($this->aProperties["server"], $this->aProperties["port"], $errno, $errstr) === false) {
+                $oError = new VitisError(19, "The database is unreachable");
                 $aXmlRacineAttribute['status'] = 0;
                 $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
-                $bXMLError = true;
-            } else {
-                // Privilège 'vitis_user' obligatoire.
-                $aParams['sLogin'] = array('value' => $this->aValues["user"], 'type' => 'string');
-                $oPDOresult = $oBd->executeWithParams($aSql['getUserConnectionPrivileges'], $aParams);
-                if ($oBd->nombreLigne($oPDOresult) == 0) {
-                    $oError = new VitisError(18, "No 'vitis_user' privilege.");
+                writeToErrorLog("ERROR : " . $errstr . ' ' . $this->aValues["user"] . "'.");
+            }
+            else {
+                //connect to database
+                $oBd = new BD($this->aValues["user"], $this->aValues["password"], $this->aProperties["database"], $this->aProperties["server"], $this->aProperties["port"], $this->aProperties["sgbd"], $this->aProperties["page_encoding"]);
+                $_SESSION["ses_Login"] = $this->aValues["user"];
+                $ciphertext = stringToHex(des($this->aValues["user"], $this->aValues["password"], 1, 0));
+                $_SESSION["ses_Password"] = $ciphertext;
+                $_SESSION["ses_Remember"] = false;
+                $_SESSION["ses_Date"] = date('Y-m-d H:i:s', time() + ($this->aValues['duration'] * 60));
+                if ($oBd->erreurRencontree) {
+                    $oError = new VitisError(1, $oBd->sMessage);
                     $aXmlRacineAttribute['status'] = 0;
                     $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
-                    writeToErrorLog("ERROR : No 'vitis_user' privilege for user '" . $this->aValues["user"] . "'.");
+                    $bXMLError = true;
                 } else {
-                    // L'utilisateur doit exister dans la table s_vitis.user
-                    $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
-                    $aParams['sLogin'] = array('value' => $_SESSION["ses_Login"], 'type' => 'string');
-                    $oPDOresult = $oBd->executeWithParams($aSql['checkUser'], $aParams);
+                    // Privilège 'vitis_user' obligatoire.
+                    $aParams['sLogin'] = array('value' => $this->aValues["user"], 'type' => 'string');
+                    $oPDOresult = $oBd->executeWithParams($aSql['getUserConnectionPrivileges'], $aParams);
                     if ($oBd->nombreLigne($oPDOresult) == 0) {
-                        $oError = new VitisError(1, 'The user ' . $_SESSION["ses_Login"] . ' does not exist');
+                    $oError = new VitisError(18, "No 'vitis_user' privilege.");
                         $aXmlRacineAttribute['status'] = 0;
                         $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
-                        writeToErrorLog('ERROR : The user ' . $_SESSION["ses_Login"] . ' does not exist.');
+                        writeToErrorLog("ERROR : No 'vitis_user' privilege for user '" . $this->aValues["user"] . "'.");
                     } else {
-                        //verify the ip from wich the user is connected
-                        $aParams = array();
+                        // L'utilisateur doit exister dans la table s_vitis.user
                         $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
                         $aParams['sLogin'] = array('value' => $_SESSION["ses_Login"], 'type' => 'string');
-                        $oPDOresult = $oBd->executeWithParams($aSql['checkIP'], $aParams);
-                        $aFields = $oBd->ligneSuivante($oPDOresult);
-                        $oMetadataAccess = new MetadataAccess($oBd, $_SESSION["ses_Login"], $_SESSION["ses_Password"], session_id(), $this->aProperties);
-                        $bAuthorizedIp = $oMetadataAccess->checkUserIp($_SERVER['REMOTE_ADDR']);
-                        if (!$bAuthorizedIp) {
-                            $oError = new VitisError(11, 'Connection to the database forbidden with the ip \'' . $_SERVER['REMOTE_ADDR'] . '\'.');
+                        $oPDOresult = $oBd->executeWithParams($aSql['checkUser'], $aParams);
+                        if ($oBd->nombreLigne($oPDOresult) == 0) {
+                            $oError = new VitisError(1, 'The user ' . $_SESSION["ses_Login"] . ' does not exist');
                             $aXmlRacineAttribute['status'] = 0;
                             $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
-                            $bXMLError = true;
-                            writeToErrorLog('ERROR : Connection to the database forbidden with the ip \'' . $_SERVER['REMOTE_ADDR'] . '\'.');
+                            writeToErrorLog('ERROR : The user ' . $_SESSION["ses_Login"] . ' does not exist.');
                         } else {
+                            //verify the ip from wich the user is connected
+                            $aParams = array();
+                            $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+                            $aParams['sLogin'] = array('value' => $_SESSION["ses_Login"], 'type' => 'string');
+                            $oPDOresult = $oBd->executeWithParams($aSql['checkIP'], $aParams);
+                            $aFields = $oBd->ligneSuivante($oPDOresult);
+                            $oMetadataAccess = new MetadataAccess($oBd, $_SESSION["ses_Login"], $_SESSION["ses_Password"], session_id(), $this->aProperties);
+                            $bAuthorizedIp = $oMetadataAccess->checkUserIp($_SERVER['REMOTE_ADDR']);
+                            if (!$bAuthorizedIp) {
+                                $oError = new VitisError(11, 'Connection to the database forbidden with the ip \'' . $_SERVER['REMOTE_ADDR'] . '\'.');
+                                $aXmlRacineAttribute['status'] = 0;
+                                $sMessage = $oError->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
+                                $bXMLError = true;
+                                writeToErrorLog('ERROR : Connection to the database forbidden with the ip \'' . $_SERVER['REMOTE_ADDR'] . '\'.');
+                            } else {
 
-                            error_log('session_id():' . session_id());
+                                error_log('session_id():' . session_id());
 
-                            $oConnection = new Connection(Array('token' => session_id()), $this->aProperties);
-                            $this->aFields['token'] = session_id();
-                            $this->aFields['user'] = $_SESSION["ses_Login"];
-                            $this->aFields['validity_date'] = date('Y-m-d H:i:s', time() + ($this->aValues['duration'] * 60));
-                            $this->aFields['user_id'] = $aFields['user_id'];
-                            $this->aFields['privileges'] = $oConnection->aPrivileges;
-                            if ($this->aValues['output'] === 'application/xml') {
-                                $this->aFields['privileges'] = implode(',', $this->aFields['privileges']);
+                                $oConnection = new Connection(Array('token' => session_id()), $this->aProperties);
+                                $this->aFields['token'] = session_id();
+                                $this->aFields['user'] = $_SESSION["ses_Login"];
+                                $this->aFields['validity_date'] = date('Y-m-d H:i:s', time() + ($this->aValues['duration'] * 60));
+                                $this->aFields['user_id'] = $aFields['user_id'];
+                                $this->aFields['privileges'] = $oConnection->aPrivileges;
+                                if ($this->aValues['output'] === 'application/xml') {
+                                    $this->aFields['privileges'] = implode(',', $this->aFields['privileges']);
+                                }
+                                $_SESSION["ses_user_id"] = $aFields['user_id'];
+                                $_SESSION["ses_restriction"] = $aFields['restriction'];
+                                $aXmlRacineAttribute['status'] = 1;
+                                $aParams = array();
+                                $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
+                                $aParams['user_id'] = array('value' => $aFields['user_id'], 'type' => 'number');
+                                $aParams['date'] = array('value' => gmdate('Y-m-d H:i:s'), 'type' => 'string');
+                                $oPDOresult = $oBd->executeWithParams($aSql['updateLastConnection'], $aParams);
+                                $sLogString = "connection" . $this->aProperties["log_delim"] . $_SESSION["ses_Login"] . $this->aProperties["log_delim"] . session_id();
+                                writeToLog($sLogString, $this->aProperties["connexion_log_file"]);
+                                $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
                             }
-                            $_SESSION["ses_user_id"] = $aFields['user_id'];
-                            $_SESSION["ses_restriction"] = $aFields['restriction'];
-                            $aXmlRacineAttribute['status'] = 1;
-                            $aParams = array();
-                            $aParams['sSchemaFramework'] = array('value' => $this->aProperties['schema_framework'], 'type' => 'schema_name');
-                            $aParams['user_id'] = array('value' => $aFields['user_id'], 'type' => 'number');
-                            $aParams['date'] = array('value' => gmdate('Y-m-d H:i:s'), 'type' => 'string');
-                            $oPDOresult = $oBd->executeWithParams($aSql['updateLastConnection'], $aParams);
-                            $sLogString = "connection" . $this->aProperties["log_delim"] . $_SESSION["ses_Login"] . $this->aProperties["log_delim"] . session_id();
-                            writeToLog($sLogString, $this->aProperties["connexion_log_file"]);
-                            $sMessage = $this->asDocument('', 'vitis', $this->aValues['sEncoding'], True, $aXmlRacineAttribute, $this->aValues['sSourceEncoding'], $this->aValues['output']);
                         }
                     }
                 }
diff --git a/vas/rest/ws/vitis/Vitis.class.inc b/vas/rest/ws/vitis/Vitis.class.inc
old mode 100755
new mode 100644
diff --git a/vas/rest/ws/vitis/VitisSection.class.inc b/vas/rest/ws/vitis/VitisSection.class.inc
index cd1e1840875aac99b320e6738dbeeb319528b0d4..1328958b8b1cf354a4bfa83ad2e96c06d3d89afb 100755
--- a/vas/rest/ws/vitis/VitisSection.class.inc
+++ b/vas/rest/ws/vitis/VitisSection.class.inc
@@ -30,7 +30,7 @@ class VitisSection extends Vitis {
      */
     function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
         parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
-        $this->aSelectedFields = Array("section_id", "tab_id", "event", "index", "label", "name", "link_table_name", "template", "ressource_id");
+        $this->aSelectedFields = Array("section_id", "tab_id", "event", "index", "label", "name", "link_table_name", "template", "ressource_id", "module_name");
     }
 
     /**
diff --git a/vas/rest/ws/vitis/VitisSections.class.inc b/vas/rest/ws/vitis/VitisSections.class.inc
index fb91cfe1ed733f0a04683f7921e7db9b9cf13dd0..3e7710cee087f81790610a140527bf029d79887e 100755
--- a/vas/rest/ws/vitis/VitisSections.class.inc
+++ b/vas/rest/ws/vitis/VitisSections.class.inc
@@ -45,7 +45,7 @@ class VitisSections extends Vitis {
      */
     function __construct($aPath, $aValues, $properties, $bShortcut = false, $oConnection = false) {
         parent::__construct($aPath, $aValues, $properties, $bShortcut, $oConnection);
-        $this->aSelectedFields = Array("section_id", "tab_id", "event", "index", "label", "name", "link_table_name", "template", "ressource_id", "tab_name", "mode_id");
+        $this->aSelectedFields = Array("section_id", "tab_id", "event", "index", "label", "name", "link_table_name", "template", "ressource_id", "tab_name", "mode_id", "module_name");
     }
 
     /**
diff --git a/vas/sql/sqlQueries.xml b/vas/sql/sqlQueries.xml
old mode 100755
new mode 100644