diff --git a/doc/LdapSaisie.docbook b/doc/LdapSaisie.docbook index 2aa1f492..e7ea84eb 100644 --- a/doc/LdapSaisie.docbook +++ b/doc/LdapSaisie.docbook @@ -22,6 +22,7 @@ book SYSTEM "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" + ]> @@ -53,5 +54,7 @@ book SYSTEM "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" &conf; +&api; + &contrib; diff --git a/doc/api/api.docbook b/doc/api/api.docbook new file mode 100644 index 00000000..3cea96ac --- /dev/null +++ b/doc/api/api.docbook @@ -0,0 +1,435 @@ + + +API + + Depuis la version 4.0, LdapSaisie offre une API visant à permettre de faire + les mêmes choses que ce qu'il est possible d'accomplir via l'interface web. L'idée + n'est bien entendue pas de se substituer systématiquement à la possibilité de se + connecter directement à l'annuaire, mais plutôt d'offrir une API web pour l'intégration + d'outil préférant ce mode d'interaction, ou encore, pour exposer des méthodes accès aux + données de l'annuaire tout en profitant des logiques métiers implémentées/configurées + dans LdapSaisie : validation syntaxique et d'unicité, règle de génération et + d'interdépendances des attributs, déclencheurs, ... + + Cette API est actuellement dans une phase de test et n'offre pas encore + toutes les fonctionnalités proposées dans l'interface web. Elle est vouée à évoluer pour + intégrer petit à petit un maximum de fonctionnalités. Des contributions à ce sujet seront + plus qu'appréciée ! + + + Authentification + + L'authentification à l'API utilise le même composant LSauth que + lors d'une authentification à l'interface web, cependant, ce composant s'adapte pour + prendre en compte de mode de connexion. Par défaut, la méthode d'authentification utilisée + sera &LSauthMethod_HTTP; et permettra de se connecter en spécifiant le nom d'utilisateur + et le mot de l'utilisateur cherchant à se connecter via une authentification basique HTTP. + + + Il est à noter que tous les types d'utilisateur ne peuvent pas forcément + utiliser l'API : le paramètre api_access doit être explicitement + positionné à True dans la configuration + du serveur LDAP. + + Une fois connecté, l'utilisateur endossera les droits associés à ses &LSprofiles;, + tout comme un utilisateur connecté à l'interface web. + + + + Méthodes exposées + + Les URLs des méthodes de l'API ont été construites par mimétisme sur celle de l'interface + web et sous la racine web api/. Par ailleurs, un numéro de version d'API a + été insérée dans chacune d'elles afin d'anticiper toutes évolutions futures majeures nécéssitants + de conserver une rétrocompatibilité avec les anciennes versions de l'API. + + Toutes les méthodes retournent des informations au format JSON et accepte le paramètre + pretty permettant d'obtenir un retour plus facilement lisible. Les chaines de + caractères échangées doivent par ailleurs être encodées en UTF-8. On trouvera par ailleurs dans + le retour JSON : + + + success + Booléen précisant si l'action demandée a correctement été exécutée. + + + + + messages + Ce tableau pourra être présent et lister les messages d'informations générées + par l'action demandée. Il s'agira des mêmes messages que ceux affichés dans l'interface web + lorsque les actions équivalentes y sont faites. + + + + errors + Ce tableau pourra être présent et lister les messages d'erreurs générées + par l'action demandée. + + + + + Les messages d'informations et d'erreurs générées par l'application sont traduites dans + la langue courante qui peut être spécifiée via le paramètre lang accepté par toutes + les méthodes (exemple : fr_FR ou en_US). + + Lorsqu'une méthode cible un type d'objets, voir un objet en particulier, ces informations seront + transmises dans l'URL appelée. Si le type d'objet ou l'objet demandé est introuvable, une erreur HTTP + 404 sera générée. + + + + Liste des méthodes exposées + + + /api/1.0/object/[object type] + + Cette méthode permet de rechercher/lister les informations d'un type d'objets de + l'annuaire en particulier. Le type de l'objet est précisé dans l'URL et doit être encodé en + conséquence. Par mimétisme du comportement de l'interface web, la recherche est paginée et + accepte des paramètres similaires en plus de paramètre plus appropriés à un fonctionnement + programmatique : + + Paramètres acceptés + + + filter + Permet de spécifier un filtre de recherche LDAP personnalisé. Celui-ci + sera combiné avec les paramètres propres au type d'objets recherchés et aux autres + paramètres spécifiés (pattern par exemple). + Pour le moment, seuls les filtres simples du type attribut=valeur + sont acceptés ici. + + + + + predefinedFilter + Permet de spécifier un des filtres de recherche LDAP prédéfinis dans la + configuration du type d'objet. + + + + pattern + Permet de spécifier un mot clé de recherche, comme proposé dans + l'interface web. + + + + approx + Booléen permettant d'activer/désactiver la recherche approximative + sur le mot clé. Les valeurs acceptées sont 1 ou 0. + + + + + basedn + Permet de spécifier une base de recherche personnalisé pour la recherche. + + + + + subDn + Dans le cas d'un serveur LDAP configuré avec des + sous-niveaux de connexion, permet de spécifier le sous-niveau pour la recherche. + + + + + scope + Permet de spécifier l'étendue de la recherche dans l'annuaire. Valeurs acceptées: + sub, one et base. + + + + + recursive + Booléen permettant d'activer/désactiver la recherche recursive, c'est à dire une + recherche à la racine de l'annuaire (ou du sous-niveau de connexion) + avec une étendue de recherche maximale. Les valeurs acceptées sont 1 ou + 0. + + + + displayFormat + Permet de spécifier un &LSformat; personnalisé pour le nom des objets dans le résultat + de recherche. + + + + extraDisplayedColumns + Booléen permettant d'activer le retour des colonnes personnalisées dans le résultat + de recherche. Les valeurs acceptées sont 1 ou 0. + + + + + attributes + Liste des attributs supplémentaires que devra retourner la recherche. + Attention, ici ce sont les valeurs brutes des attributs qui seront retournées et + par forcément les valeurs telle que retournées habituellement. + + + + + sortBy + Permet de préciser sur quelle information le résultat de recherche doit être + trié. Valeurs acceptées : displayName, subDn ou un des noms + des colonnes personnalisées. + + + + sortDirection + Permet de préciser l'ordre de tri du résultat de recherche. Valeurs acceptées : + ASC (A-Z) ou DESC (Z-A). + + + + page + Permet de préciser la page du résultat de recherche. + + + + nbObjectsByPage + Permet de préciser le nombre maximum d'objets retournés par page du résultat de + recherche. + + + + all + Permet de réclamer le résultat complet de la recherche (désactivation + de la pagination). Seul la présence de ce paramètre suffit à activer ce comportement, sa + valeur n'a pas d'importance. + + + + withoutCache + Booléen permettant de désactiver l'utilisation du cache. Les valeurs acceptées + sont 1 ou 0. + + + + + Exemple + + + + + + + /api/1.0/object/[object type]/[dn] + + Cette méthode permet de récupérer les informations d'un objet de l'annuaire au format + JSON. Le type de l'objet et son DN sont précisés dans l'URL et doivent être encodés en + conséquence. + + Exemple + + + + + + + + /api/1.0/object/[object type]/create + + Cette méthode permet de créer un objet dans l'annuaire. Le type de l'objet qui sera créé est + précisé dans l'URL et doit être encodé en conséquence. Les informations de l'objet doivent est + transmises au format x-www-form-urlencoded. Elles peuvent également être au + format multipart/form-data, en particulier si votre requête contient une image. + Par mimétisme avec l'interface web, seuls les attributs prévus dans le formulaire de création du + type d'objet peuvent être passées ici. De la même manière, les attributs non-spécifiés ici, pouront + être auto-générés en accord avec leur configuration et la requête sera acceptée uniquement si tous les + attributs obligatoires y sont spécifiés ou s'ils peuvent être auto-générés. + Le format et la syntaxe des valeurs des attributs dépends de leur type HTML. Ainsi, par exemple, + un attribut de type HTML boolean acceptera comme valeurs possibles yes + ou no. Pour plus de détails sur le type de valeur acceptée par un type + d'attribut HTML en particulier, consultez sa documentation. Vous pouvez également analyser le code de + la méthode getPostData() de la classe PHP correspondante. + Si l'application détecte un souci avec les informations transmises pour les attributs, un tableau + fields_errors sera présent dans la réponse JSON et contiendra pour chacun des attributs + problématique, un tableau des messages d'erreurs générées par l'application. + Si le type d'objet en prévoit, vous pouvez également utiliser un + masque de saisie via le paramètre + dataEntryForm. + + Exemple + + + + + + + /api/1.0/object/[object type]/[dn]/modify + + Cette méthode permet de modifier un objet dans l'annuaire. Le type de l'objet et son DN sont + précisés dans l'URL et doivent être encodés en conséquence. Les informations de l'objet à modifier + doivent être transmises au même format que pour la méthode create (voir ci-dessus). + Comme pour cette dernière, seuls les attributs prévus dans le formulaire de modification du type + d'objet peuvent être passées ici et la réponse JSON pourra contenir un tableau fields_errors + contenant les erreurs générées par l'application au sujet des valeurs transmises pour les + attributs. + + Exemple + + + + + + + /api/1.0/object/[object type]/[dn]/remove + + Cette méthode permet de supprimer un objet dans l'annuaire. Le type de l'objet et son DN sont + précisés dans l'URL et doivent être encodés en conséquence. + + Exemple + + + + + + + /api/1.0/object/[object type]/[dn]/relation/[relation] + + Cette méthode permet de gérer les objets en relation avec un objet en particulier de + l'annuaire. Le type de l'objet, son DN et le nom de la relation sont précisés dans l'URL et + doivent être encodés en conséquence. Cette méthode accepte les paramètres add + et remove permettant de lister le ou les DN d'objet(s) à + respectivement ajouter ou supprimer parmis les objets actuellement en relation avec l'objet + spécifié. Si aucun DN n'est spécifié comme devant être ajouté ou supprimé, la méthode + retournera simplement les DN des objets en relation. En cas de modification demandée, la + méthode retournera la nouvelle liste des DNs des objets en relation, quel que soit le résultat + de l'opération de mise à jour. + + Exemple + + + + + + + + + + diff --git a/doc/conf/LSauthMethod/LSauthMethod.entities.xml b/doc/conf/LSauthMethod/LSauthMethod.entities.xml index 82c51520..8bc0cefb 100644 --- a/doc/conf/LSauthMethod/LSauthMethod.entities.xml +++ b/doc/conf/LSauthMethod/LSauthMethod.entities.xml @@ -3,6 +3,4 @@ - - - +LSauthMethod_HTTP"> diff --git a/doc/conf/LSauthMethod/LSauthMethod_HTTP.docbook b/doc/conf/LSauthMethod/LSauthMethod_HTTP.docbook index 476a9eb6..95aaa997 100644 --- a/doc/conf/LSauthMethod/LSauthMethod_HTTP.docbook +++ b/doc/conf/LSauthMethod/LSauthMethod_HTTP.docbook @@ -1,19 +1,32 @@ LSauthMethod_HTTP Cette &LSauthMethod; est utilisée pour gérer l'authentification - via les variables d'environnements définies suite à une authentification - gérée par le serveur HTTP. En &php;, ces informations sont consultables - via les variables $_SERVER['PHP_AUTH_USER'] et - $_SERVER['PHP_AUTH_PW']. Si la variable - $_SERVER['PHP_AUTH_USER'] est présente, une recherche - dans l'annuaire est effectué pour trouver l'utilisateur correspondant. - L'authentification réussie uniquement si un et un seul utilisateur est - retourné par la recherche et si une authentification auprès de l'annuaire - LDAP réussie à l'aide du DN de l'objet LDAP trouvé et du mot de passe issu - de la variable $_SERVER['PHP_AUTH_PW']. + via les variables d'environnements définies suite à une authentification, + potentiellement déléguée au serveur web. + Cette méthode récupère dans l'environment d'exécution PHP, le nom + d'utilisateur et le mot de passe de l'utilisateur connecté. À partir du + nom d'utilisateur, une recherche dans l'annuaire sera effectuée pour + trouver l'utilisateur correspondant. L'authentification sera réussie + uniquement si un et un seul utilisateur est retourné par la recherche et + si une authentification auprès de l'annuaire LDAP réussie à l'aide du DN + de l'objet LDAP trouvé et du mot de passe fourni. + + En cas d'authentification déléguée au serveur web, il est + possible de désactiver la vérification du mot de passe via le paramètre + LSAUTHMETHOD_HTTP_TRUST_WITHOUT_PASSWORD_CHALLENGE + (voir ci-dessous). + + Les variables d'environnements utilisées pour authentifier l'utilisateur + connecté dépendent de la méthode configurée via la constante + LSAUTHMETHOD_HTTP_METHOD (voir ci-dessous). Si ces variables ne sont + pas disponibles, une erreur HTTP 403 sera générée pour réclamer une + authentification à l'utilisateur. + + Cette &LSauthMethod; supporte le mode API et il s'agit de la + méthode utilisée par défaut dans ce mode. Cette librairie peut être configurée en éditant le fichier de - configiration + configuration conf/LSauth/config.LSauthMethod_HTTP.php. @@ -25,6 +38,9 @@ // Don't check HTTP server's login/password by LDAP authentication challenge //define('LSAUTHMETHOD_HTTP_TRUST_WITHOUT_PASSWORD_CHALLENGE',true); + +// Authentication realm (API mode only) +//define('LSAUTHMETHOD_HTTP_API_REALM', ___('LdapSaisie API - Authentication required')); @@ -43,7 +59,7 @@ LSAUTHMETHOD_HTTP_METHOD - Permet de définir la méthode utilisée par le serveur HTTP pour passer + Permet de définir la méthode utilisée par le serveur web pour passer à PHP l'identifiant de l'utilisateur connecté et son mot de passe. Cette constance peut pendre les valeurs suivantes : @@ -51,7 +67,7 @@ PHP_PASS - Dans cette méthode, le serveur HTTP défini les variables + Dans cette méthode, le serveur web défini les variables d'environnement PHP_AUTH_USER et PHP_AUTH_PW. Cette méthode est la méthode par défaut et convient en cas d'utilisation de mod_php. @@ -61,7 +77,7 @@ REMOTE_USER - Dans cette méthode, le serveur HTTP défini la variable + Dans cette méthode, le serveur web défini la variable d'environnement REMOTE_USER. Cette variable ne contient que l'identifiant de l'utilisateur connecté. Cette méthode ne peut donc être utilisée que conjointement avec l'activation du paramètre @@ -73,12 +89,12 @@ AUTHORIZATION - Dans cette méthode, le serveur HTTP passe le contenu de l'entête + Dans cette méthode, le serveur web passe le contenu de l'entête HTTP Authorization dans la variable d'environnement HTTP_AUTHORIZATION. Cette méthode convient en cas d' utilisation de PHP en mode CGI ou encore via PHP-FPM. Pour utiliser cette méthode, il faudra adapter la configuration du - serveur HTTP. Par exemple, pour Apache HTTPd, vous pouvez utiliser le + serveur web. Par exemple, pour Apache HTTPd, vous pouvez utiliser le module rewrite et la règle de réécriture suivante : @@ -104,5 +120,15 @@ + + LSAUTHMETHOD_HTTP_REALM + + Domaine d'authentification (reaml) utilisé pour + réclamer l'authentification de l'utilisateur (facultatif). + Pour que le message soit traduit, utilisez la fonction + ___() (voir exemple). + + + diff --git a/doc/conf/srv-ldap.docbook b/doc/conf/srv-ldap.docbook index 130c3a9e..21bc2740 100644 --- a/doc/conf/srv-ldap.docbook +++ b/doc/conf/srv-ldap.docbook @@ -19,11 +19,14 @@ serveur LDAP. 'useUserCredentials' => [boolean], 'LSauth' => array ( 'method' => [LSauth method], + 'api_method' => [LSauth method], 'LSobjects' => array( '[object type 1]', '[object type 2]' => array( 'filter' => '[LDAP filter]', 'password_attribute' => '[attribute name]', + 'web_access' => [booléen], + 'api_access' => [booléen], ) ) ), @@ -120,6 +123,18 @@ serveur LDAP. + + api_method + + Nom de la méthode d'authentification &LSauthMethod; à utilisée lors d'une connexion à + l'API. Exemple : pour utiliser la classe LSauthMethod_HTTP, la valeur de ce + paramètre sera HTTP. Paramètre facultatif, méthode par défaut : + HTTP. + Toutes les &LSauthMethod; ne supportent pas forcément le mode API. + + + + LSobjects @@ -151,6 +166,22 @@ serveur LDAP. + + web_access + + Permet de définir si ce type d'objet à le droit d'utiliser l'interface web (facultatif, + par défaut : True). + + + + + api_access + + Permet de définir si ce type d'objet à le droit d'utiliser l'API (facultatif, + par défaut : False). + + + diff --git a/src/conf/LSauth/config.LSauthMethod_HTTP.php b/src/conf/LSauth/config.LSauthMethod_HTTP.php index 9cb3cdcd..95933995 100644 --- a/src/conf/LSauth/config.LSauthMethod_HTTP.php +++ b/src/conf/LSauth/config.LSauthMethod_HTTP.php @@ -49,3 +49,6 @@ // Remote logout URL (in SSO context for instance) //define('LSAUTHMETHOD_HTTP_LOGOUT_REMOTE_URL', 'https://idp.domain.tld/logout'); + +// Authentication realm +//define('LSAUTHMETHOD_HTTP_REALM', ___('LdapSaisie - Authentication required')); diff --git a/src/conf/config.inc.php b/src/conf/config.inc.php index 3bdbcbe6..68907fdf 100644 --- a/src/conf/config.inc.php +++ b/src/conf/config.inc.php @@ -50,12 +50,16 @@ $GLOBALS['LSconfig'] = array( ), 'LSauth' => array ( //'method' => 'basic', // Auth method : basic(default), HTTP, CAS or anonymous + //'api_method' => 'HTTP', // Auth method that must support API mode : HTTP(default) or anonymous 'LSobjects' => array( 'LSpeople' => array( 'filter' => '(|(uid=%{user})(mail=%{user}))', 'password_attribute' => 'userPassword', + 'api_access' => false, ), - 'LSsysaccount', + 'LSsysaccount' => array( + 'api_access' => true, + ) ), //'allow_multi_match' => false, // Allow username multiple match (default: false) ), diff --git a/src/includes/class/class.LSauth.php b/src/includes/class/class.LSauth.php index 3ded7a2c..9c051193 100644 --- a/src/includes/class/class.LSauth.php +++ b/src/includes/class/class.LSauth.php @@ -34,6 +34,7 @@ class LSauth extends LSlog_staticLoggerClass { static private $authData=NULL; static private $authObject=NULL; static private $config=array(); + static private $method=NULL; static private $provider=NULL; static private $params = array ( @@ -52,21 +53,28 @@ class LSauth extends LSlog_staticLoggerClass { self :: log_debug('Failed to load LSauthMethod class'); return; } - if (!isset(self :: $config['method'])) { - self :: $config['method']='basic'; - } - $class='LSauthMethod_'.self :: $config['method']; + $api_mode = LSsession :: get('api_mode'); + if ($api_mode) + self :: $method = self :: getConfig('api_method', 'HTTP'); + else + self :: $method = self :: getConfig('method', 'basic'); + $class = "LSauthMethod_".self :: $method; self :: log_debug('provider -> '.$class); if (LSsession :: loadLSclass($class)) { + if ($api_mode && !$class :: apiModeSupported()) { + LSerror :: addErrorCode('LSauth_08', self :: $method); + return; + } self :: $provider = new $class(); if (!self :: $provider) { - LSerror :: addErrorCode('LSauth_05',self :: $config['method']); + LSerror :: addErrorCode('LSauth_05', self :: $method); + return; } self :: log_debug('Provider Started !'); return true; } else { - LSerror :: addErrorCode('LSauth_04',self :: $config['method']); + LSerror :: addErrorCode('LSauth_04', self :: $method); return; } } @@ -107,19 +115,21 @@ class LSauth extends LSlog_staticLoggerClass { public static function getAuthObjectTypes() { $objTypes = array(); foreach(self :: getConfig('LSobjects', array()) as $objType => $objParams) { + if (!self :: checkAuthObjectTypeAccess($objType)) + continue; if (is_int($objType) && is_string($objParams)) { - // We just have the object type $objTypes[$objParams] = array('filter' => null, 'password_attribute' => 'userPassword'); continue; } + $objTypes[$objType] = array( 'filter' => self :: getConfig("LSobjects.$objType.filter", null, 'string'), 'password_attribute' => self :: getConfig("LSobjects.$objType.password_attribute", 'userPassword', 'string'), ); } - // For retro-compatibility, also retreived old parameters: + // For retro-compatibility, also retreived old parameters (excepted in API mode): $oldAuthObjectType = LSconfig :: get('authObjectType', null, 'string', LSsession :: $ldapServer); - if ($oldAuthObjectType && !array_key_exists($oldAuthObjectType, $objTypes)) { + if ($oldAuthObjectType && !array_key_exists($oldAuthObjectType, $objTypes) && self :: checkAuthObjectTypeAccess($oldAuthObjectType)) { $objTypes[$oldAuthObjectType] = array( 'filter' => LSconfig :: get('authObjectFilter', null, 'string', LSsession :: $ldapServer), 'password_attribute' => LSconfig :: get('authObjectTypeAttrPwd', 'userPassword', 'string', LSsession :: $ldapServer), @@ -128,6 +138,22 @@ class LSauth extends LSlog_staticLoggerClass { return $objTypes; } + + /** + * Check if the specified auth object type have acces to LdapSaisie (on the current mode) + * + * @param[in] $objType string The LSobject type + * + * @return boolean True if specified auth object type have acces to LdapSaisie, False otherwise + */ + public static function checkAuthObjectTypeAccess($objType) { + // Check Web/API access rights + if (LSsession :: get('api_mode')) { + return self :: getConfig("LSobjects.$objType.api_access", false, 'bool'); + } + return self :: getConfig("LSobjects.$objType.web_access", true, 'bool'); + } + /** * Retreived LSobjects corresponding to a username * @@ -299,3 +325,6 @@ ___("LSauth : Not correctly initialized.") LSerror :: defineError('LSauth_07', ___("LSauth : Failed to get authentication informations from provider.") ); +LSerror :: defineError('LSauth_08', +___("LSauth : Method %{method} configured doesn't support API mode.") +); diff --git a/src/includes/class/class.LSauthMethod.php b/src/includes/class/class.LSauthMethod.php index fc571fca..e02f5bca 100644 --- a/src/includes/class/class.LSauthMethod.php +++ b/src/includes/class/class.LSauthMethod.php @@ -29,7 +29,10 @@ LSsession :: loadLSclass('LSlog_staticLoggerClass'); */ class LSauthMethod extends LSlog_staticLoggerClass { - var $authData = array(); + protected $authData = array(); + + // Boolean flag to specify if this LSauthMethod support API mode + protected static $api_mode_supported = false; public function __construct() { // Load config (without warning if not found) @@ -115,4 +118,13 @@ class LSauthMethod extends LSlog_staticLoggerClass { return false; } + /** + * Check API mode support of this method + * + * @retval boolean True if API mode is support, false otherwise + */ + static public function apiModeSupported() { + return static :: $api_mode_supported; + } + } diff --git a/src/includes/class/class.LSauthMethod_HTTP.php b/src/includes/class/class.LSauthMethod_HTTP.php index 8201a333..14933ee6 100644 --- a/src/includes/class/class.LSauthMethod_HTTP.php +++ b/src/includes/class/class.LSauthMethod_HTTP.php @@ -29,6 +29,9 @@ LSsession :: loadLSclass('LSauthMethod_basic'); */ class LSauthMethod_HTTP extends LSauthMethod_basic { + // Boolean flag to specify if this LSauthMethod support API mode + protected static $api_mode_supported = true; + public function __construct() { parent :: __construct(); LSauth :: disableLoginForm(); @@ -53,6 +56,7 @@ class LSauthMethod_HTTP extends LSauthMethod_basic { self :: log_debug('HTTP method to retreive auth data is "'.LSAUTHMETHOD_HTTP_METHOD.'"'); } + $missing_info = null; switch(constant('LSAUTHMETHOD_HTTP_METHOD')) { case 'AUTHORIZATION': if (isset($_SERVER['HTTP_AUTHORIZATION']) && !empty($_SERVER['HTTP_AUTHORIZATION'])) { @@ -62,11 +66,12 @@ class LSauthMethod_HTTP extends LSauthMethod_basic { 'username' => $authData[0], 'password' => $authData[1], ); + return $this -> authData; } - return $this -> authData; + else + self :: log_warning("Fail to decode and parse $missing_info environment variable."); } - else - LSerror :: addErrorCode('LSauthMethod_HTTP_01', 'HTTP_AUTHORIZATION'); + $missing_info = 'HTTP_AUTHORIZATION'; break; case 'REMOTE_USER': if (isset($_SERVER['REMOTE_USER']) && !empty($_SERVER['REMOTE_USER'])) { @@ -76,8 +81,7 @@ class LSauthMethod_HTTP extends LSauthMethod_basic { ); return $this -> authData; } - else - LSerror :: addErrorCode('LSauthMethod_HTTP_01', 'REMOTE_USER'); + $missing_info = 'REMOTE_USER'; break; case 'PHP_AUTH': default: @@ -88,10 +92,20 @@ class LSauthMethod_HTTP extends LSauthMethod_basic { ); return $this -> authData; } - else - LSerror :: addErrorCode('LSauthMethod_HTTP_01', 'PHP_AUTH_USER'); + $missing_info = 'PHP_AUTH_USER'; } - return; + self :: log_warning("$missing_info variable not available in environment, trigger 403 error."); + + // Auth data not available, trigger HTTP 403 error + if (defined('LSAUTHMETHOD_HTTP_REALM') && constant('LSAUTHMETHOD_HTTP_REALM')) + $realm = __(LSAUTHMETHOD_HTTP_REALM); + else + $realm = _('LdapSaisie - Authentication required'); + header('WWW-Authenticate: Basic realm="'.$realm.'", charset="UTF-8"'); + header('HTTP/1.0 401 Unauthorized'); + LSerror :: addErrorCode(null, $realm); + LSsession :: displayAjaxReturn(); + exit(); } /** diff --git a/src/includes/class/class.LSauthMethod_anonymous.php b/src/includes/class/class.LSauthMethod_anonymous.php index 2cd7eabb..4f35c42d 100644 --- a/src/includes/class/class.LSauthMethod_anonymous.php +++ b/src/includes/class/class.LSauthMethod_anonymous.php @@ -27,6 +27,9 @@ */ class LSauthMethod_anonymous extends LSauthMethod { + // Boolean flag to specify if this LSauthMethod support API mode + protected static $api_mode_supported = true; + public function __construct() { LSauth :: disableLoginForm(); LSauth :: disableSelfAccess(); diff --git a/src/includes/class/class.LSerror.php b/src/includes/class/class.LSerror.php index 42f126fa..57f9cd25 100644 --- a/src/includes/class/class.LSerror.php +++ b/src/includes/class/class.LSerror.php @@ -123,13 +123,17 @@ class LSerror { * * @retvat string Le texte des erreurs */ - public static function getErrors() { + public static function getErrors($raw=false) { if(!empty($_SESSION['LSerror'])) { - $txt = ''; - foreach ($_SESSION['LSerror'] as $error) - $txt .= $error."
\n"; + if ($raw) + $return = $_SESSION['LSerror']; + else { + $return = ''; + foreach ($_SESSION['LSerror'] as $error) + $return .= $error."
\n"; + } self :: resetError(); - return $txt; + return $return; } return; } diff --git a/src/includes/class/class.LSform.php b/src/includes/class/class.LSform.php index 6ac7c9a5..89d7d8f4 100644 --- a/src/includes/class/class.LSform.php +++ b/src/includes/class/class.LSform.php @@ -52,6 +52,10 @@ class LSform extends LSlog_staticLoggerClass { var $warnings = array(); + var $api_mode = false; + + private $submited = false; + /** * Constructeur * @@ -64,7 +68,7 @@ class LSform extends LSlog_staticLoggerClass { * * @retval void */ - public function __construct(&$ldapObject, $idForm, $submit=NULL){ + public function __construct(&$ldapObject, $idForm, $submit=NULL, $api_mode=false){ $this -> idForm = $idForm; if (!$submit) { $this -> submit = _("Validate"); @@ -72,6 +76,7 @@ class LSform extends LSlog_staticLoggerClass { else { $this -> submit = $submit; } + $this -> api_mode = $api_mode; $this -> ldapObject =& $ldapObject; $this -> config = $ldapObject -> getConfig('LSform'); LSsession :: loadLSclass('LSformElement'); @@ -428,11 +433,22 @@ class LSform extends LSlog_staticLoggerClass { * @retval boolean true si la saisie du formulaire est présente en POST, false sinon */ public function isSubmit() { + if ($this -> submited) + return true; if( (isset($_POST['validate']) && ($_POST['validate']=='LSform')) && (isset($_POST['idForm']) && ($_POST['idForm'] == $this -> idForm)) ) return true; return; } + /** + * Set form as submited + * + * @retval void + */ + public function setSubmited() { + $this -> submited = true; + } + /** * Défini arbitrairement des données en POST * diff --git a/src/includes/class/class.LSformElement.php b/src/includes/class/class.LSformElement.php index a2f068ed..2e9e6699 100644 --- a/src/includes/class/class.LSformElement.php +++ b/src/includes/class/class.LSformElement.php @@ -403,4 +403,18 @@ class LSformElement extends LSlog_staticLoggerClass { $opts[] = $opt; } + /** + * Retreive value as return in API response + * + * @retval mixed API value(s) or null/empty array if no value + */ + public function getApiValue() { + if ($this -> isMultiple()) { + return ensureIsArray($this -> values); + } + if (!$this -> values) + return null; + return $this -> values[0]; + } + } diff --git a/src/includes/class/class.LSformElement_date.php b/src/includes/class/class.LSformElement_date.php index 2ed346aa..2c0cb9e4 100644 --- a/src/includes/class/class.LSformElement_date.php +++ b/src/includes/class/class.LSformElement_date.php @@ -223,9 +223,14 @@ class LSformElement_date extends LSformElement { return true; } $values = self :: getData($_POST, $this -> name); - $special_values = self :: getData($_POST, $this -> name.'__special_value'); self :: log_trace($this." -> getPostData(): values=".varDump($values)); - self :: log_trace($this." -> getPostData(): special_values=".varDump($special_values)); + if ($this -> form -> api_mode) { + $special_values = false; + } + else { + $special_values = self :: getData($_POST, $this -> name.'__special_value'); + self :: log_trace($this." -> getPostData(): special_values=".varDump($special_values)); + } if (!is_array($values) && !is_array($special_values)) { self :: log_trace($this." -> getPostData(): not in POST data"); if ($onlyIfPresent) { diff --git a/src/includes/class/class.LSformElement_image.php b/src/includes/class/class.LSformElement_image.php index ee36519c..3470d3fb 100644 --- a/src/includes/class/class.LSformElement_image.php +++ b/src/includes/class/class.LSformElement_image.php @@ -163,4 +163,21 @@ class LSformElement_image extends LSformElement { } return _("An unknown error occured sending this file."); } + + /** + * Retreive value as return in API response + * + * @retval mixed API value(s) or null/empty array if no value + */ + public function getApiValue() { + if ($this -> isMultiple()) { + $values = array(); + for ($i=0; $i < count($this -> values); $i++) + $values[] = base64_encode($this -> values[0]); + return $values; + } + if (!$this -> values) + return null; + return base64_encode($this -> values[0]); + } } diff --git a/src/includes/class/class.LSformElement_jsonCompositeAttribute.php b/src/includes/class/class.LSformElement_jsonCompositeAttribute.php index f4a89058..86cba193 100644 --- a/src/includes/class/class.LSformElement_jsonCompositeAttribute.php +++ b/src/includes/class/class.LSformElement_jsonCompositeAttribute.php @@ -66,6 +66,29 @@ class LSformElement_jsonCompositeAttribute extends LSformElement { */ var $components = array(); + /** + * Parse values + * + * @retval array Parsed values + */ + private function parseValues() { + self :: log_trace('values: '.varDump($this -> values)); + $parseValues=array(); + foreach($this -> values as $val) { + $decodedValue = json_decode($val, true); + self :: log_trace('decoded value: '.varDump($decodedValue)); + if (is_array($decodedValue)) { + $parseValue = array('value' => $val); + foreach($decodedValue as $c => $cvalue) { + $parseValue[$c] = $this -> translateComponentValue($c,$cvalue); + } + $parseValues[] = $parseValue; + } + } + self :: log_trace('parsed values: '.varDump($parseValues)); + return $parseValues; + } + /** * Retourne les infos d'affichage de l'élément * @@ -76,25 +99,9 @@ class LSformElement_jsonCompositeAttribute extends LSformElement { public function getDisplay(){ $return = $this -> getLabelInfos(); - $parseValues=array(); - $invalidValues=array(); - foreach($this -> values as $val) { - $decodedValue=json_decode($val, true); - if (is_array($decodedValue)) { - $parseValue=array('value' => $val); - foreach($decodedValue as $c => $cvalue) { - $parseValue[$c]=$this -> translateComponentValue($c,$cvalue); - } - $parseValues[]=$parseValue; - } - else { - $invalidValues[]=$val; - } - } - $return['html'] = $this -> fetchTemplate(NULL, array( - 'parseValues' => $parseValues, + 'parseValues' => $this -> parseValues(), 'fullWidth' => $this -> getParam('html_options.fullWidth', false, 'bool'), ) ); @@ -181,7 +188,14 @@ class LSformElement_jsonCompositeAttribute extends LSformElement { protected function getSelectListComponentPossibleValues($c) { if (!isset($this -> _cache_getSelectListComponentPossibleValues[$c])) { if (!LSsession :: loadLSclass('LSattr_html_select_list')) return; - $this -> _cache_getSelectListComponentPossibleValues[$c]=LSattr_html_select_list :: _getPossibleValues($this -> components[$c]['options'], $this -> name, $this->attr_html->attribute->ldapObject); + $this -> _cache_getSelectListComponentPossibleValues[$c] = LSattr_html_select_list :: _getPossibleValues( + $this -> components[$c]['options'], + $this -> name, + $this->attr_html->attribute->ldapObject + ); + self :: log_trace( + "Component $c possible values: ".varDump($this -> _cache_getSelectListComponentPossibleValues[$c]) + ); } return $this -> _cache_getSelectListComponentPossibleValues[$c]; } @@ -194,7 +208,7 @@ class LSformElement_jsonCompositeAttribute extends LSformElement { * * @retval array **/ - protected function getSelectListComponentValueLabel($c,$value) { + protected function getSelectListComponentValueLabel($c, $value) { if ($this -> getSelectListComponentPossibleValues($c)) { foreach ($this -> _cache_getSelectListComponentPossibleValues[$c] as $v => $label) { if (is_array($label)) { @@ -205,6 +219,7 @@ class LSformElement_jsonCompositeAttribute extends LSformElement { if ($v == $value) return $label; } } + self :: log_trace("No label found for value '$value'"); return; } @@ -225,78 +240,241 @@ class LSformElement_jsonCompositeAttribute extends LSformElement { return true; } - $return[$this -> name]=array(); - if (is_array($_POST[$this -> name.'__values_uuid'])) { - foreach ($_POST[$this -> name.'__values_uuid'] as $uuid) { - $value=array(); - $parseValue=array(); - $errors=array(); - $unemptyComponents=array(); + // Extract value form POST data + $parseValues = array(); + // API mode + if ($this -> form -> api_mode) { + $json_values = $this -> getData($_POST, $this -> name); + if (!is_array($json_values) || empty($json_values)) { + self :: log_trace($this." -> getPostData(): not in POST data"); + return true; + } - foreach ($this -> components as $c => $cconf) { - if (isset($_POST[$this -> name.'__'.$c.'__'.$uuid])) { - if (!is_array($_POST[$this -> name.'__'.$c.'__'.$uuid])) - $_POST[$this -> name.'__'.$c.'__'.$uuid] = array($_POST[$this -> name.'__'.$c.'__'.$uuid]); - - $parseValue[$c]=array(); - foreach($_POST[$this -> name.'__'.$c.'__'.$uuid] as $val) { - if (empty($val)) - continue; - $parseValue[$c][] = $val; - if ($cconf['type']=='select_list') { - if (!$this -> getSelectListComponentValueLabel($c, $val)) { - $errors[]=getFData(_('Invalid value "%{value}" for component %{component}.'),array('value' => $val, 'component' => __($cconf['label']))); - } - } - if (isset($cconf['check_data']) && is_array($cconf['check_data'])) { - foreach($cconf['check_data'] as $ruleType => $rconf) { - $className='LSformRule_'.$ruleType; - if (LSsession::loadLSclass($className)) { - $r=new $className(); - if (!$r -> validate($val,$rconf,$this)) { - if (isset($rconf['msg'])) { - $errors[]=getFData(__($rconf['msg']),__($cconf['label'])); - } - else { - $errors[]=getFData(_('Invalid value "%{value}" for component %{component}.'),array('value' => $val, 'component' => __($cconf['label']))); - } - } - } - else { - $errors[]=getFData(_("Can't validate value of component %{c}."),__($cconf['label'])); - } - } - } - } - - if (empty($parseValue[$c])) - continue; - - if (!isset($cconf['multiple']) || !$cconf['multiple']) { - $parseValue[$c] = $parseValue[$c][0]; - } - - $unemptyComponents[]=$c; - $value[$c]=$parseValue[$c]; - } + $json_value_count = 0; + foreach($json_values as $json_value) { + $json_value_count += 1; + $input_value = json_decode($json_value, true); + if (!is_array($input_value)) { + $this -> form -> setElementError( + $this -> attr_html, + getFData(_('Fail to decode JSON value #%{idx}.'), $json_value_count) + ); + continue; } - if (!empty($unemptyComponents)) { - // Check required components - foreach ($this -> components as $c => $cconf) { - if ($cconf['required'] && !isset($value[$c])) { - $errors[]=getFData(_('Component %{c} must be defined'),__($cconf['label'])); - continue; + $parseValue = array(); + $unemptyComponents = array(); + + foreach (array_keys($this -> components) as $c) { + if (!isset($input_value[$c])) + continue; + if ($this -> getComponentConfig($c, 'multiple', false, 'bool')) { + $parseValue[$c] = array(); + if (is_array($input_value[$c])) { + foreach($input_value[$c] as $val) { + if (is_empty($val)) + continue; + $parseValue[$c][] = $val; + } } } - foreach($errors as $e) { - $this -> form -> setElementError($this -> attr_html,$e); + else { + $parseValue[$c] = $input_value[$c]; } - $return[$this -> name][]=json_encode($value); + + if (is_empty($parseValue[$c])) { + unset($parseValue[$c]); + continue; + } + $unemptyComponents[] = $c; } + + // Ignore empty value from form + if (empty($unemptyComponents)) + continue; + + $parseValues[] = $parseValue; } } + elseif (is_array($_POST[$this -> name.'__values_uuid'])) { + // HTML form mode + foreach ($_POST[$this -> name.'__values_uuid'] as $uuid) { + $parseValue = array(); + $unemptyComponents = array(); + + foreach (array_keys($this -> components) as $c) { + if (!isset($_POST[$this -> name.'__'.$c.'__'.$uuid])) + continue; + $parseValue[$c] = array(); + foreach($_POST[$this -> name.'__'.$c.'__'.$uuid] as $val) { + if (empty($val)) + continue; + $parseValue[$c][] = $val; + } + + if (empty($parseValue[$c])) { + unset($parseValue[$c]); + continue; + } + if (!$this -> getComponentConfig($c, 'multiple', false, 'bool')) { + $parseValue[$c] = $parseValue[$c][0]; + } + $unemptyComponents[] = $c; + } + + // Ignore empty value from form + if (empty($unemptyComponents)) + continue; + + $parseValues[] = $parseValue; + } + } + + // Check extracted values + foreach ($parseValues as $parseValue) { + // Check component value + foreach ($parseValue as $c => $value) + $this -> checkComponentValues($c, $value); + + // Check required components + foreach (array_keys($this -> components) as $c) { + if ($this -> getComponentConfig($c, 'required', false, 'bool') && !isset($parseValue[$c])) { + $this -> form -> setElementError( + $this -> attr_html, + getFData( + _('Component %{c} must be defined'), + __($this -> getComponentConfig($c, 'label')) + ) + ); + } + } + $return[$this -> name][] = json_encode($parseValue); + } + return true; } + /** + * Check one component's values + * + * @param[] $c The component name + * @param[] $value The values of the component + * + * @retval void + **/ + private function checkComponentValues($c, $value) { + if ($this -> getComponentConfig($c, 'multiple', false, 'bool')) { + foreach ($value as $val) { + $this -> checkComponentValue($c, $val); + } + } + else + $this -> checkComponentValue($c, $value); + } + + /** + * Check one component's value + * + * @param[] $c The component name + * @param[] $value The value to check + * + * @retval void + **/ + private function checkComponentValue($c, $value) { + $label = __($this -> getComponentConfig($c, 'label')); + + // select_list components : check values + if ($this -> getComponentConfig($c, 'type') == 'select_list') { + if (!$this -> getSelectListComponentValueLabel($c, $value)) { + $this -> form -> setElementError( + $this -> attr_html, + getFData( + _('Invalid value "%{value}" for component %{component}.'), + array('value' => $value, 'component' => $label) + ) + ); + } + } + + // Apply check data rules + foreach($this -> getComponentConfig($c, 'check_data', array(), 'array') as $ruleType => $rconf) { + $className = 'LSformRule_'.$ruleType; + if (LSsession::loadLSclass($className)) { + $r = new $className(); + if (!$r -> validate($value, $rconf, $this)) { + if (isset($rconf['msg'])) { + $this -> form -> setElementError( + $this -> attr_html, + getFData(__($rconf['msg']), $label) + ); + } + else { + $this -> form -> setElementError( + $this -> attr_html, + getFData( + _('Invalid value "%{value}" for component %{component}.'), + array('value' => $value, 'component' => $label) + ) + ); + } + } + } + else { + $this -> form -> setElementError( + $this -> attr_html, + getFData(_("Can't validate value of component %{c}."), $label) + ); + } + } + } + + /** + * Return a configuration parameter for a specific component (or default value) + * + * @param[] $component The component name + * @param[] $param The configuration parameter + * @param[] $default The default value (default : null) + * @param[] $cast Cast resulting value in specific type (default : disabled) + * + * @retval mixed The configuration parameter value or default value if not set + **/ + public function getComponentConfig($component, $param, $default=null, $cast=null) { + return LSconfig :: get( + $param, $default, $cast, + (array_key_exists($component, $this -> components)?$this -> components[$component]:array()) + ); + } + + /** + * Retreive value as return in API response + * + * @retval mixed API value(s) or null/empty array if no value + */ + public function getApiValue() { + $values = array(); + foreach(ensureIsArray($this -> values) as $value) { + $decodedValue = json_decode($value, true); + if (is_array($decodedValue)) { + $parsedValue = array(); + foreach(array_keys($this -> components) as $c) { + if (!isset($decodedValue[$c])) + continue; + if ($this -> getComponentConfig($c, 'multiple', false, 'bool')) { + $parsedValue[$c] = ensureIsArray($decodedValue[$c]); + } + else { + $parsedValue[$c] = $decodedValue[$c]; + } + } + $values[] = $parsedValue; + } + } + if ($this -> isMultiple()) { + return $values; + } + if (!$values) + return null; + return $values[0]; + } + } diff --git a/src/includes/class/class.LSformElement_labeledValue.php b/src/includes/class/class.LSformElement_labeledValue.php index 88506e20..4bb29b94 100644 --- a/src/includes/class/class.LSformElement_labeledValue.php +++ b/src/includes/class/class.LSformElement_labeledValue.php @@ -117,26 +117,48 @@ class LSformElement_labeledValue extends LSformElement { if($this -> isFreeze()) { return true; } - if (isset($_POST[$this -> name."_labels"]) && isset($_POST[$this -> name."_values"])) { - $return[$this -> name] = array(); + // Extract value form POST data + $values = array(); + // API mode + if ($this -> form -> api_mode) { + if (isset($_POST[$this -> name])) { + foreach(ensureIsArray($_POST[$this -> name]) as $val) { + if (is_empty($val)) + continue; + $parseValue = self :: parseValue($val); + if (isset($parseValue['label']) && isset($parseValue['value'])) { + $values[] = '['.$parseValue['label'].']'.$parseValue['value']; + } + else { + $this -> form -> setElementError( + $this -> attr_html, + getFData(_('Invalid value : "%{value}".'), $val) + ); + } + } + } + } + elseif (isset($_POST[$this -> name."_labels"]) && isset($_POST[$this -> name."_values"])) { $_POST[$this -> name."_labels"] = ensureIsArray($_POST[$this -> name."_labels"]); $_POST[$this -> name."_values"] = ensureIsArray($_POST[$this -> name."_values"]); foreach($_POST[$this -> name."_labels"] as $key => $label) { $val = $_POST[$this -> name."_values"][$key]; if (!empty($label) && !is_empty($val)) { - $return[$this -> name][$key] = "[$label]$val"; + $values[$key] = "[$label]$val"; } } - return true; + } + + if ($values) { + $return[$this -> name] = $values; } elseif ($onlyIfPresent) { self :: log_debug($this -> name.": not in POST data => ignore it"); - return true; } else { $return[$this -> name] = array(); - return true; } + return true; } } diff --git a/src/includes/class/class.LSformElement_mailQuota.php b/src/includes/class/class.LSformElement_mailQuota.php index 0d60ae73..cad40a60 100644 --- a/src/includes/class/class.LSformElement_mailQuota.php +++ b/src/includes/class/class.LSformElement_mailQuota.php @@ -41,6 +41,41 @@ class LSformElement_mailQuota extends LSformElement { 1000000000 => 'Go' ); + /** + * Parse one value + * + * @param[in] $value string The value to parse + * + * @retval array Parsed value + */ + public function parseValue($value) { + if (preg_match('/^([0-9]+)'.$this -> getSuffix().'$/',$value,$regs)) { + $infos = array( + 'size' => $regs[1], + ); + if ($infos['size'] == 0) { + return array( + 'size' => 0, + 'valueSize' => 0, + 'valueSizeFact' => 1, + 'valueTxt' => "0", + ); + } + krsort($this -> sizeFacts, SORT_NUMERIC); + foreach($this -> sizeFacts as $fact => $unit) { + if ($infos['size'] >= $fact) { + $infos['valueSize'] = round($infos['size'] / $fact, 2); + $infos['valueSizeFact'] = $fact; + $infos['valueTxt'] = $infos['valueSize'].$unit; + break; + } + } + ksort($this -> sizeFacts, SORT_NUMERIC); + return $infos; + } + return false; + } + /** * Retourne les infos d'affichage de l'élément * @@ -54,26 +89,9 @@ class LSformElement_mailQuota extends LSformElement { $quotas=array(); foreach ($this -> values as $value) { - if (preg_match('/([0-9]*)/'.$this -> getSuffix(),$value,$regs)) { - $infos = array( - 'size' => $regs[1] - ); - if ($infos['size'] >= 1000000000) { - $infos['valueSizeFact']=1000000000; - } - else if ($infos['size'] >= 1000000) { - $infos['valueSizeFact']=1000000; - } - else if ($infos['size'] >= 1000) { - $infos['valueSizeFact']=1000; - } - else { - $infos['valueSizeFact']=1; - } - $infos['valueSize'] = $infos['size'] / $infos['valueSizeFact']; - $infos['valueTxt'] = $infos['valueSize'].$this ->sizeFacts[$infos['valueSizeFact']]; - - $quotas[$value] = $infos; + $parsed_value = $this -> parseValue($value); + if ($parsed_value) { + $quotas[$value] = $parsed_value; } else { $quotas[$value] = array( @@ -137,36 +155,69 @@ class LSformElement_mailQuota extends LSformElement { if($this -> isFreeze()) { return true; } - if (isset($_POST[$this -> name.'_size'])) { - $return[$this -> name]=array(); + $values = array(); + if ($this -> form -> api_mode) { + if (isset($_POST[$this -> name])) { + foreach(ensureIsArray($_POST[$this -> name]) as $value) { + if ($this -> parseValue($value) !== false) { + $values[] = $value; + } + else { + $this -> form -> setElementError( + $this -> attr_html, + getFData(_('Invalid value : "%{value}".'), $value) + ); + } + } + } + } + elseif (isset($_POST[$this -> name.'_size'])) { $_POST[$this -> name.'_size'] = ensureIsArray($_POST[$this -> name.'_size']); if(isset($_POST[$this -> name.'_sizeFact']) && !is_array($_POST[$this -> name.'_sizeFact'])) { $_POST[$this -> name.'_sizeFact'] = array($_POST[$this -> name.'_sizeFact']); } foreach($_POST[$this -> name.'_size'] as $key => $val) { - if (!empty($val)) { - $f = 1; - if (isset($_POST[$this -> name.'_sizeFact'][$key]) && ($_POST[$this -> name.'_sizeFact'][$key]!=1)) { - $f = $_POST[$this -> name.'_sizeFact'][$key]; - } - $return[$this -> name][$key] = ($val*$f).$this->getSuffix(); + if (empty($val)) + continue; + $f = 1; + if (isset($_POST[$this -> name.'_sizeFact'][$key]) && ($_POST[$this -> name.'_sizeFact'][$key]!=1)) { + $f = $_POST[$this -> name.'_sizeFact'][$key]; } + $values[$key] = ($val*$f).$this->getSuffix(); } - return true; } - // Accept raw value to make import easier - elseif (isset($_POST[$this -> name])) { - $return[$this -> name]=$_POST[$this -> name]; - return true; + + if ($values) { + $return[$this -> name] = $values; } elseif ($onlyIfPresent) { self :: log_debug($this -> name.": not in POST data => ignore it"); - return true; } else { $return[$this -> name] = array(); - return true; } + return true; + } + + /** + * Retreive value as return in API response + * + * @retval mixed API value(s) or null/empty array if no value + */ + public function getApiValue() { + $values = array(); + foreach(ensureIsArray($this -> values) as $value) { + $parsed_value = $this -> parseValue($value); + if (is_array($parsed_value)) { + $values[] = $parsed_value['size']; + } + } + if ($this -> isMultiple()) { + return $values; + } + if (!$values) + return null; + return $values[0]; } } diff --git a/src/includes/class/class.LSformElement_maildir.php b/src/includes/class/class.LSformElement_maildir.php index fae4fd73..6fa8e1f2 100644 --- a/src/includes/class/class.LSformElement_maildir.php +++ b/src/includes/class/class.LSformElement_maildir.php @@ -89,7 +89,7 @@ class LSformElement_maildir extends LSformElement_text { $retval = parent :: getPostData($return); // Si une valeur est recupérée - if ($retval&&$_POST['LSformElement_maildir_'.$this -> name.'_do']) { + if ($retval && !$this -> form -> api_mode && $_POST['LSformElement_maildir_'.$this -> name.'_do']) { $cur = $this -> form -> ldapObject -> attrs[$this -> name] -> getValue(); $cur=$cur[0]; $new = $return[$this -> name][0]; diff --git a/src/includes/class/class.LSformElement_password.php b/src/includes/class/class.LSformElement_password.php index 393f4996..b2710ade 100644 --- a/src/includes/class/class.LSformElement_password.php +++ b/src/includes/class/class.LSformElement_password.php @@ -62,7 +62,7 @@ class LSformElement_password extends LSformElement { return true; } - if ($this -> getParam('html_options.confirmInput', False, 'bool')) { + if (!$this -> form -> api_mode && $this -> getParam('html_options.confirmInput', False, 'bool')) { $confirm_data = self :: getData($_POST, $this -> name . '_confirm'); $confirmed = false; if (!is_array($confirm_data)) { diff --git a/src/includes/class/class.LSformElement_quota.php b/src/includes/class/class.LSformElement_quota.php index 66d5bf99..5034f21e 100644 --- a/src/includes/class/class.LSformElement_quota.php +++ b/src/includes/class/class.LSformElement_quota.php @@ -38,9 +38,46 @@ class LSformElement_quota extends LSformElement { 1 => 'o', 1024 => 'Ko', 1048576 => 'Mo', - 1073741824 => 'Go' + 1073741824 => 'Go', + 1099511627776 => 'To', ); + + /** + * Parse one value + * + * @param[in] $value string The value to parse + * + * @retval array Parsed value + */ + public function parseValue($value) { + if (preg_match('/^([0-9]+)$/', $value, $regs)) { + $infos = array( + 'size' => ceil($regs[1]/$this -> getFactor()), + ); + if ($infos['size'] == 0) { + return array( + 'size' => 0, + 'valueSize' => 0, + 'valueSizeFact' => 1, + 'valueTxt' => "0", + ); + } + krsort($this -> sizeFacts, SORT_NUMERIC); + foreach($this -> sizeFacts as $fact => $unit) { + if ($infos['size'] >= $fact) { + $infos['valueSize'] = round($infos['size'] / $fact, 2); + $infos['valueSizeFact'] = $fact; + $infos['valueTxt'] = $infos['valueSize'].$unit; + break; + } + } + ksort($this -> sizeFacts, SORT_NUMERIC); + return $infos; + } + return false; + } + /** * Retourne les infos d'affichage de l'élément * @@ -54,26 +91,9 @@ class LSformElement_quota extends LSformElement { $quotas=array(); foreach ($this -> values as $value) { - if (preg_match('/^([0-9]*)$/',$value,$regs)) { - $infos = array( - 'size' => ceil($regs[1]/$this -> getFactor()) - ); - if ($infos['size'] >= 1073741824) { - $infos['valueSizeFact']=1073741824; - } - else if ($infos['size'] >= 1048576) { - $infos['valueSizeFact']=1048576; - } - else if ($infos['size'] >= 1024) { - $infos['valueSizeFact']=1024; - } - else { - $infos['valueSizeFact']=1; - } - $infos['valueSize'] = $infos['size'] / $infos['valueSizeFact']; - $infos['valueTxt'] = $infos['valueSize'].$this ->sizeFacts[$infos['valueSizeFact']]; - - $quotas[$value] = $infos; + $parsed_value = $this -> parseValue($value); + if ($parsed_value) { + $quotas[$value] = $parsed_value; } else { $quotas[$value] = array( @@ -128,36 +148,71 @@ class LSformElement_quota extends LSformElement { if($this -> isFreeze()) { return true; } - if (isset($_POST[$this -> name.'_size'])) { - $return[$this -> name]=array(); + $values = array(); + if ($this -> form -> api_mode) { + if (isset($_POST[$this -> name])) { + foreach(ensureIsArray($_POST[$this -> name]) as $value) { + $values[] = ceil($value*$this -> getFactor()); + } + } + } + elseif (isset($_POST[$this -> name.'_size'])) { $_POST[$this -> name.'_size'] = ensureIsArray($_POST[$this -> name.'_size']); if(isset($_POST[$this -> name.'_sizeFact']) && !is_array($_POST[$this -> name.'_sizeFact'])) { $_POST[$this -> name.'_sizeFact'] = array($_POST[$this -> name.'_sizeFact']); } foreach($_POST[$this -> name.'_size'] as $key => $val) { - if (!empty($val)) { - $f = 1; - if (isset($_POST[$this -> name.'_sizeFact'][$key]) && ($_POST[$this -> name.'_sizeFact'][$key]!=1)) { - $f = $_POST[$this -> name.'_sizeFact'][$key]; - } - $val=preg_replace('/,/','.',$val); - $return[$this -> name][$key] = ceil(ceil(($val*$f)*$this -> getFactor())); + if (empty($val)) + continue; + $f = 1; + if (isset($_POST[$this -> name.'_sizeFact'][$key]) && ($_POST[$this -> name.'_sizeFact'][$key]!=1)) { + $f = $_POST[$this -> name.'_sizeFact'][$key]; } + $val = preg_replace('/,/', '.', $val); + $values[$key] = ceil(ceil(($val*$f)*$this -> getFactor())); } - return true; + } + + if ($values) { + $return[$this -> name] = $values; } elseif ($onlyIfPresent) { self :: log_debug($this -> name.": not in POST data => ignore it"); - return true; } else { $return[$this -> name] = array(); - return true; } + return true; } + /** + * Retreive factor value + * + * @retval integer Factor value + */ private function getFactor() { - return $this -> getParam('html_options.factor', 1); + return $this -> getParam('html_options.factor', 1, 'int'); + } + + /** + * Retreive value as return in API response + * + * @retval mixed API value(s) or null/empty array if no value + */ + public function getApiValue() { + $values = array(); + foreach(ensureIsArray($this -> values) as $value) { + $parsed_value = $this -> parseValue($value); + if (is_array($parsed_value)) { + $values[] = $parsed_value['size']; + } + } + if ($this -> isMultiple()) { + return $values; + } + if (!$values) + return null; + return $values[0]; } } diff --git a/src/includes/class/class.LSformElement_supannCompositeAttribute.php b/src/includes/class/class.LSformElement_supannCompositeAttribute.php index 18e5ddfe..0b1f591f 100644 --- a/src/includes/class/class.LSformElement_supannCompositeAttribute.php +++ b/src/includes/class/class.LSformElement_supannCompositeAttribute.php @@ -184,8 +184,8 @@ class LSformElement_supannCompositeAttribute extends LSformElement { * @retval boolean true si la valeur est présente en POST, false sinon */ public function getPostData(&$return, $onlyIfPresent=false) { - if ($onlyIfPresent) { - self :: log_warning("getPostData : does not support \$onlyIfPresent mode => Post data ignored"); + if ($onlyIfPresent || $this -> form -> api_mode) { + self :: log_warning("getPostData : does not support \$onlyIfPresent / API mode => Post data ignored"); return true; } diff --git a/src/includes/class/class.LSformElement_valueWithUnit.php b/src/includes/class/class.LSformElement_valueWithUnit.php index c80337f3..66d53d91 100644 --- a/src/includes/class/class.LSformElement_valueWithUnit.php +++ b/src/includes/class/class.LSformElement_valueWithUnit.php @@ -157,43 +157,70 @@ class LSformElement_valueWithUnit extends LSformElement { if($this -> isFreeze()) { return true; } - $return[$this -> name]=array(); - if (isset($_POST[$this -> name.'_valueWithUnit'])) { - $_POST[$this -> name.'_valueWithUnit'] = ensureIsArray($_POST[$this -> name.'_valueWithUnit']); - if(isset($_POST[$this -> name.'_unitFact']) && !is_array($_POST[$this -> name.'_unitFact'])) { - $_POST[$this -> name.'_unitFact'] = array($_POST[$this -> name.'_unitFact']); - } - foreach($_POST[$this -> name.'_valueWithUnit'] as $key => $val) { - if (!empty($val)) { - $f = 1; - if (isset($_POST[$this -> name.'_unitFact'][$key]) && ($_POST[$this -> name.'_unitFact'][$key]!=1)) { - $f = $_POST[$this -> name.'_unitFact'][$key]; - } - if ($this -> getParam('html_options.store_integer')) { - if ($this -> getParam('html_options.round_down')) { - $return[$this -> name][$key] = floor($val*$f); - } - else { - $return[$this -> name][$key] = ceil($val*$f); - } - } - else { - $return[$this -> name][$key] = ($val*$f); - } + + if ($this -> form -> api_mode) { + if (isset($_POST[$this -> name]) && $_POST[$this -> name]) { + $return[$this -> name] = array(); + foreach(ensureIsArray($_POST[$this -> name]) as $value) { + if ($this -> getParam('html_options.store_integer')) { + $value = ($this -> getParam('html_options.round_down')?floor($value):ceil($value)); + } + $return[$this -> name][] = $value; } } } - if (isset($_POST[$this -> name])) { - $_POST[$this -> name] = ensureIsArray($_POST[$this -> name]); - $return[$this -> name] = array_merge($return[$this -> name], $_POST[$this -> name]); - } - if (isset($_POST[$this -> name.'_value'])) { - $_POST[$this -> name.'_value'] = ensureIsArray($_POST[$this -> name.'_value']); - $return[$this -> name] = array_merge($return[$this -> name], $_POST[$this -> name.'_value']); + else { + $return[$this -> name] = array(); + if (isset($_POST[$this -> name.'_valueWithUnit'])) { + $_POST[$this -> name.'_valueWithUnit'] = ensureIsArray($_POST[$this -> name.'_valueWithUnit']); + if(isset($_POST[$this -> name.'_unitFact']) && !is_array($_POST[$this -> name.'_unitFact'])) { + $_POST[$this -> name.'_unitFact'] = array($_POST[$this -> name.'_unitFact']); + } + foreach($_POST[$this -> name.'_valueWithUnit'] as $key => $val) { + if (empty($val)) + continue; + $f = 1; + if (isset($_POST[$this -> name.'_unitFact'][$key]) && ($_POST[$this -> name.'_unitFact'][$key]!=1)) { + $f = $_POST[$this -> name.'_unitFact'][$key]; + } + if ($this -> getParam('html_options.store_integer')) { + $return[$this -> name][$key] = ( + $this -> getParam('html_options.round_down')? + floor($val*$f): + ceil($val*$f) + ); + } + else { + $return[$this -> name][$key] = ($val*$f); + } + } + } + + if (isset($_POST[$this -> name.'_value'])) { + $_POST[$this -> name.'_value'] = ensureIsArray($_POST[$this -> name.'_value']); + $return[$this -> name] = array_merge($return[$this -> name], $_POST[$this -> name.'_value']); + } } return true; } + /** + * Retreive value as return in API response + * + * @retval mixed API value(s) or null/empty array if no value + */ + public function getApiValue() { + $values = array(); + foreach (ensureIsArray($this -> values) as $value) + if (preg_match('/^([0-9]*)$/', $value, $regs)) + $values[] = intval($regs[1]); + if ($this -> isMultiple()) { + return $values; + } + if (!$values) + return null; + return $values[0]; + } } /* diff --git a/src/includes/class/class.LSformRule_rlcMemberDetails.php b/src/includes/class/class.LSformRule_rlcMemberDetails.php new file mode 100644 index 00000000..52f26674 --- /dev/null +++ b/src/includes/class/class.LSformRule_rlcMemberDetails.php @@ -0,0 +1,86 @@ + + */ +class LSformRule_rlcMemberDetails extends LSformRule { + + // Validate values one by one or all together + public const validate_one_by_one = False; + + /** + * Validate rlcMemberDetails attribute value + * + * @param string $values The value to validate + * @param array $options Validation options + * @param object $formElement The related formElement object + * + * @return boolean true if the value is valide, false if not + */ + public static function validate($value, $options=array(), &$formElement) { + $members = array(); + foreach($value as $json_value) { + if (is_empty($json_value)) { + self :: log_error("validate($json_value): Empty value are not authorized"); + return false; + } + $v = json_decode($json_value); + if (is_null($v)) { + self :: log_error("validate($json_value): fail to decode JSON value"); + return false; + } + + if (!isset($v->role) || is_empty($v->role) || !isset($v->uid) || is_empty($v->uid)) { + self :: log_error("validate($json_value): invalid value (no uid or role)"); + return false; + } + + if (!in_array($v->role, array('facilitator', 'governing_board_referent', 'contributor', 'observer'))) { + self :: log_error("validate($json_value): invalid role $v->role"); + return false; + } + + if (!array_key_exists($v->role, $members)) + $members[$v->role] = array(); + if (in_array($v->uid, $members[$v->role])) { + self :: log_error("validate($json_value): member $v->uid duplicated as $v->role"); + return false; + } + $members[$v->role][] = $v->uid; + } + self :: log_debug("validate(): members: ".print_r($members, true)); + foreach (array('facilitator', 'governing_board_referent', 'contributor') as $role) { + if (!array_key_exists($role, $members)) { + self :: log_error("validate(): no $role"); + return false; + } + } + if (count($members['governing_board_referent']) > 1) { + self :: log_error("validate(): more than one governing_board_referent found"); + return false; + } + return True; + } +} diff --git a/src/includes/class/class.LSimport.php b/src/includes/class/class.LSimport.php index 40a84410..cf4a341d 100644 --- a/src/includes/class/class.LSimport.php +++ b/src/includes/class/class.LSimport.php @@ -170,8 +170,8 @@ class LSimport { $globalErrors=array(); // Instanciate an LSobject $object = new $LSobject(); - // Instanciate a creation LSform - $form = $object -> getForm('create'); + // Instanciate a creation LSform (in API mode) + $form = $object -> getForm('create', null, true); // Set form data from inputed data if ($form -> setPostData($objData,true)) { // Validate form @@ -204,8 +204,8 @@ class LSimport { // Instanciate a new LSobject and load data from it's DN $object = new $LSobject(); if ($object -> loadData($dn)) { - // Instanciate a modify form - $form = $object -> getForm('modify'); + // Instanciate a modify form (in API mode) + $form = $object -> getForm('modify', null, true); // Set form data from inputed data if ($form -> setPostData($objData,true)) { // Validate form diff --git a/src/includes/class/class.LSldapObject.php b/src/includes/class/class.LSldapObject.php index 6e8636ba..1a294f2d 100644 --- a/src/includes/class/class.LSldapObject.php +++ b/src/includes/class/class.LSldapObject.php @@ -199,22 +199,22 @@ class LSldapObject extends LSlog_staticLoggerClass { } /** - * Construit un formulaire de l'objet + * Constuct a form for this object * - * Cette méthode construit un formulaire LSform à partir de la configuration de l'objet - * et de chaque attribut. + * This method create a LSform from the object and its attributes configurations. * - * @param[in] $idForm [required] Identifiant du formulaire a créer - * @param[in] $load DN d'un objet similaire dont la valeur des attribut doit être chargé dans le formulaire. + * @param[in] $idForm string Form identifier (required) + * @param[in] $load string DN of a similar object. If defined, attributes values of this object will be loaded in the form. + * @param[in] $api_mode boolean Enable API mode (defaut: false) * * @author Benjamin Renard * - * @retval LSform Le formulaire crée + * @retval LSform The created LSform object */ - public function getForm($idForm,$load=NULL) { + public function getForm($idForm, $load=NULL, $api_mode=false) { LSsession :: loadLSclass('LSform'); - $LSform = new LSform($this,$idForm); - $this -> forms[$idForm] = array($LSform,$load); + $LSform = new LSform($this, $idForm, null, $api_mode); + $this -> forms[$idForm] = array($LSform, $load); if ($load) { $type = $this -> getType(); @@ -1890,6 +1890,9 @@ class LSldapObject extends LSlog_staticLoggerClass { } return false; } + elseif ($key=='type') { + return $this -> getType(); + } // Unknown key, log warning self :: log_warning("__get($key): invalid property requested\n".LSlog :: get_debug_backtrace_context()); } @@ -2460,8 +2463,8 @@ class LSldapObject extends LSlog_staticLoggerClass { if (is_null($objType) || empty($attrs_values)) LScli :: usage('You must provide LSobject type, DN and at least one change.'); - // Instanciate a create LSform - $form = $obj -> getForm('create'); + // Instanciate a create LSform (in API mode) + $form = $obj -> getForm('create', null, true); // Check all changed attributes are in modify form and are'nn freezed foreach ($attrs_values as $attr => $value) { @@ -2559,7 +2562,7 @@ class LSldapObject extends LSlog_staticLoggerClass { elseif ($objType && class_exists($objType)) { LScli :: need_ldap_con(); $obj = new $objType(); - $form = $obj -> getForm('create'); + $form = $obj -> getForm('create', null, true); // Instanciate create form in API mode $form -> autocomplete_attrs_values($opts, $comp_word); } @@ -2639,8 +2642,8 @@ class LSldapObject extends LSlog_staticLoggerClass { return True; } - // Instanciate a modify LSform - $form = $obj -> getForm('modify'); + // Instanciate a modify LSform (in API mode) + $form = $obj -> getForm('modify', null, true); // Check all changed attributes are in modify form and are'nn freezed foreach ($changes as $attr => $value) { @@ -2742,7 +2745,7 @@ class LSldapObject extends LSlog_staticLoggerClass { self :: log_error("Fail to load object $dn data from LDAP"); } else { - $form = $obj -> getForm('modify'); + $form = $obj -> getForm('modify', null, True); // Instanciate modify form in API mode $form -> autocomplete_attrs_values($opts, $comp_word); } } diff --git a/src/includes/class/class.LSsearch.php b/src/includes/class/class.LSsearch.php index c7ffe9a1..ddc70831 100644 --- a/src/includes/class/class.LSsearch.php +++ b/src/includes/class/class.LSsearch.php @@ -1181,7 +1181,8 @@ class LSsearch extends LSlog_staticLoggerClass { $params = array ( 'basedn', 'sortBy', - 'sortDirection' + 'sortDirection', + 'attributes', ); if ($key=='LSobject') { return $this -> LSobject; @@ -1266,7 +1267,7 @@ class LSsearch extends LSlog_staticLoggerClass { return $this -> getHash(); } else { - throw new Exception('Incorrect property !'); + throw new Exception("Incorrect property '$key'!"); } } diff --git a/src/includes/class/class.LSsession.php b/src/includes/class/class.LSsession.php index 836a3ce7..96306a65 100644 --- a/src/includes/class/class.LSsession.php +++ b/src/includes/class/class.LSsession.php @@ -99,6 +99,9 @@ class LSsession { // List of currently loaded LSaddons private static $loadedAddons = array(); + // API mode + private static $api_mode = false; + /** * Get session info by key * @@ -128,6 +131,8 @@ class LSsession { return self :: globalSearch(); case 'email_sender': return self :: getEmailSender(); + case 'api_mode': + return boolval(self :: $api_mode); } return null; } @@ -1608,6 +1613,8 @@ class LSsession { * @retval void */ public static function displayTemplate() { + if (self :: $api_mode) + return self :: displayAjaxReturn(); $KAconf = LSconfig :: get('keepLSsessionActive'); if ( ( @@ -1671,54 +1678,79 @@ class LSsession { } /** - * Défini que l'affichage se fera ou non via un retour Ajax + * Set Ajax display mode + * + * @param[in] $val boolean True to enable Ajax display mode (optional, default: true) * - * @param[in] $val boolean True pour que l'affichage se fasse par un retour - * Ajax, false sinon * @retval void */ public static function setAjaxDisplay($val=true) { self :: $ajaxDisplay = (boolean)$val; } + /** + * Check if Ajax display mode is enabled + * + * @retval boolean True if Ajax display mode is enabled, False otherwise + */ + public static function getAjaxDisplay() { + return (boolean)self :: $ajaxDisplay; + } + /** * Affiche un retour Ajax * * @retval void */ - public static function displayAjaxReturn($data=array()) { + public static function displayAjaxReturn($data=array(), $pretty=false) { if (isset($data['LSredirect']) && (!LSdebugDefined()) ) { echo json_encode($data); return; } - if (class_exists('LStemplate')) + if (!self :: $api_mode && class_exists('LStemplate')) $data['LSjsConfig'] = LStemplate :: getJSconfigParam(); // Infos if((!empty($_SESSION['LSsession_infos']))&&(is_array($_SESSION['LSsession_infos']))) { - $txt_infos="\n"; - $data['LSinfos'] = $txt_infos; $_SESSION['LSsession_infos']=array(); } if (LSerror :: errorsDefined()) { - $data['LSerror'] = LSerror :: getErrors(); + $data[(self :: $api_mode?'errors':'LSerror')] = LSerror :: getErrors(self :: $api_mode); } - if (isset($_REQUEST['imgload'])) { + if (!self :: $api_mode && isset($_REQUEST['imgload'])) { $data['imgload'] = $_REQUEST['imgload']; } - if (LSdebugDefined()) { + if (!self :: $api_mode && LSdebugDefined()) { $data['LSdebug'] = LSdebug_print(true,false); } - echo json_encode($data); + echo json_encode($data, (($pretty||isset($_REQUEST['pretty']))?JSON_PRETTY_PRINT:0)); + } + + /** + * Set API mode + * + * @param[in] $val boolean True to enable API mode (optional, default: true) + * + * @retval void + */ + public static function setApiMode($val=true) { + self :: $api_mode = (boolean)$val; } /** @@ -2306,6 +2338,22 @@ class LSsession { return self :: canAccess($LSobject,NULL,'w','rdn'); } + /** + * Check user right to compute the result of a LSformat + * + * @param[in] $LSformat string The LSformat string to check + * @param[in] $LSobject string The LSobject type + * @param[in] $dn string The LSobject DN (optional, default: the container_dn of the LSobject type) + * + * @retval boolean True is user can compute the result of the LSformat, False otherwise + */ + public static function canComputeLSformat($LSformat, $LSobject, $dn=NULL) { + foreach (getFieldInFormat($LSformat) as $attr) + if (!self :: canAccess($LSobject, $dn, 'r', $attr)) + return false; + return true; + } + /** * Retourne le droit de l'utilisateur à gérer la relation d'objet * diff --git a/src/includes/class/class.LStemplate.php b/src/includes/class/class.LStemplate.php index d581bf07..a8bbff60 100644 --- a/src/includes/class/class.LStemplate.php +++ b/src/includes/class/class.LStemplate.php @@ -455,10 +455,22 @@ class LStemplate extends LSlog_staticLoggerClass { * @retval void **/ public static function fatal_error($error=null) { - self :: assign('pagetitle', _("A fatal error occured.")); - self :: assign('error', _("A fatal error occured. If problem persist, please contact support.")); - self :: assign('details', $error); - self :: display("error.tpl"); + http_response_code(500); + if (LSsession :: get('api_mode')) { + $errors = array(_("A fatal error occured. If problem persist, please contact support.")); + if ($error) + $errors[] = $error; + echo json_encode( + array('errors' => $errors, 'success' => false), + (isset($_REQUEST['pretty'])?JSON_PRETTY_PRINT:0) + ); + } + else { + self :: assign('pagetitle', _("A fatal error occured.")); + self :: assign('error', _("A fatal error occured. If problem persist, please contact support.")); + self :: assign('details', $error); + self :: display("error.tpl"); + } exit(); } diff --git a/src/includes/class/class.LSurl.php b/src/includes/class/class.LSurl.php index a848bc04..93ce4f37 100644 --- a/src/includes/class/class.LSurl.php +++ b/src/includes/class/class.LSurl.php @@ -61,21 +61,23 @@ class LSurl extends LSlog_staticLoggerClass { * @param[in] $handler callable The URL pattern handler (must be callable, required) * @param[in] $authenticated boolean Permit to define if this URL is accessible only for authenticated users (optional, default: true) * @param[in] $override boolean Allow override if a command already exists with the same name (optional, default: false) + * @param[in] $api_mode boolean Enable API mode (optional, default: false) **/ - public static function add_handler($pattern, $handler=null, $authenticated=true, $override=true) { + public static function add_handler($pattern, $handler=null, $authenticated=true, $override=true, $api_mode=false) { if (is_array($pattern)) { if (is_null($handler)) foreach($pattern as $p => $h) - self :: add_handlers($p, $h, $override); + self :: add_handler($p, $h, $override, $api_mode); else foreach($pattern as $p) - self :: add_handlers($p, $handler, $override); + self :: add_handler($p, $handler, $override, $api_mode); } else { if (!isset(self :: $patterns[$pattern])) { self :: $patterns[$pattern] = array( 'handler' => $handler, 'authenticated' => $authenticated, + 'api_mode' => $api_mode, ); } elseif ($override) { @@ -83,6 +85,7 @@ class LSurl extends LSlog_staticLoggerClass { self :: $patterns[$pattern] = array( 'handler' => $handler, 'authenticated' => $authenticated, + 'api_mode' => $api_mode, ); } else { @@ -128,12 +131,15 @@ class LSurl extends LSlog_staticLoggerClass { self :: redirect($default_url); exit(); } - self :: log_debug("Current URL match with no pattern. Use error 404 handler."); + // Error 404 + $api_mode = (strpos($current_url, 'api/') === 0); + self :: log_debug("Current URL match with no pattern. Use error 404 handler (API mode=$api_mode)."); return new LSurlRequest( $current_url, array( 'handler' => array('LSurl', 'error_404'), 'authenticated' => false, + 'api_mode' => $api_mode, ) ); } @@ -228,9 +234,17 @@ class LSurl extends LSlog_staticLoggerClass { * @retval void **/ public static function error_404($request=null) { - LStemplate :: assign('error', _("The requested page was not found.")); - LSsession :: setTemplate('error.tpl'); - LSsession :: displayTemplate(); + http_response_code(404); + $error = _("The requested page was not found."); + if (LSsession :: getAjaxDisplay() || ($request && $request->api_mode)) { + LSerror :: addErrorCode(null, $error); + LSsession :: displayAjaxReturn(); + } + else { + LStemplate :: assign('error', $error); + LSsession :: setTemplate('error.tpl'); + LSsession :: displayTemplate(); + } } /** @@ -249,7 +263,9 @@ class LSurl extends LSlog_staticLoggerClass { self :: log_fatal(_("This request could not be handled.")); } - if (class_exists('LStemplate')) + if ($request -> api_mode) + LSsession :: setApiMode(); + elseif (class_exists('LStemplate')) LStemplate :: assign('request', $request); // Check authentication (if need) diff --git a/src/includes/class/class.LSurlRequest.php b/src/includes/class/class.LSurlRequest.php index cbb9e94f..e5a60e0c 100644 --- a/src/includes/class/class.LSurlRequest.php +++ b/src/includes/class/class.LSurlRequest.php @@ -37,6 +37,9 @@ class LSurlRequest extends LSlog_staticLoggerClass { // Request need authentication ? private $authenticated = true; + // API mode enabled ? + private $api_mode = false; + // Parameters detected on requested URL private $url_params = array(); @@ -44,6 +47,7 @@ class LSurlRequest extends LSlog_staticLoggerClass { $this -> current_url = $current_url; $this -> handler = $handler_infos['handler']; $this -> authenticated = (isset($handler_infos['authenticated'])?boolval($handler_infos['authenticated']):true); + $this -> api_mode = (isset($handler_infos['api_mode'])?boolval($handler_infos['api_mode']):false); $this -> url_params = $url_params; } @@ -61,6 +65,8 @@ class LSurlRequest extends LSlog_staticLoggerClass { return $this -> handler; if ($key == 'authenticated') return $this -> authenticated; + if ($key == 'api_mode') + return $this -> api_mode; if ($key == 'referer') return $this -> get_referer(); if (array_key_exists($key, $this->url_params)) { diff --git a/src/includes/routes.php b/src/includes/routes.php index 5b6729c3..7554692e 100644 --- a/src/includes/routes.php +++ b/src/includes/routes.php @@ -354,11 +354,12 @@ LSurl :: add_handler('#^tmp/(?P[^/]+)$#', 'handle_tmp_file'); * @param[in] $request LSurlRequest The request * @param[in] $instanciate boolean Instanciate and return an object (optional, default: true) * @param[in] $check_access callable|null Permit to specify check access method (optional, default: LSsession :: canAccess()) + * @param[in] $api_mode boolean Enable API mode (optional, default: false) * * @retval LSobject|boolean The instanciated LSobject (or True if $instanciate=false), or False * on error/access refused */ -function get_LSobject_from_request($request, $instanciate=true, $check_access=null) { +function get_LSobject_from_request($request, $instanciate=true, $check_access=null, $api_mode=false) { $LSobject = $request -> LSobject; $dn = (isset($request -> dn)?$request -> dn:null); @@ -367,7 +368,7 @@ function get_LSobject_from_request($request, $instanciate=true, $check_access=nu $check_access = array('LSsession', 'canAccess'); // Handle SELF redirect - if ( $LSobject == 'SELF' ) { + if ( !$api_mode && $LSobject == 'SELF' ) { $LSobject = LSsession :: getLSuserObject() -> getType(); $dn = LSsession :: getLSuserObjectDn(); LSurl :: redirect("object/$LSobject/".urlencode($dn)); @@ -377,13 +378,19 @@ function get_LSobject_from_request($request, $instanciate=true, $check_access=nu if ($dn) { if (!call_user_func($check_access, $LSobject, $dn)) { LSerror :: addErrorCode('LSsession_11'); - LSsession :: displayTemplate(); + if ($api_mode) + LSsession :: displayAjaxReturn(); + else + LSsession :: displayTemplate(); return false; } } else if (!LSsession :: in_menu($LSobject) && !call_user_func($check_access, $LSobject)) { LSerror :: addErrorCode('LSsession_11'); - LSsession :: displayTemplate(); + if ($api_mode) + LSsession :: displayAjaxReturn(); + else + LSsession :: displayTemplate(); return false; } @@ -1469,3 +1476,429 @@ function handle_old_addon_view($request) { LSurl :: redirect(); } LSurl :: add_handler('#^addon_view\.php#', 'handle_old_addon_view', false); + +/* + * API + */ + +/* + * LSobject API view helper to retreive LSobject from request + * + * Just a wrapper on get_LSobject_from_request() helper function to + * correctly set parameters for API context. + * + * See get_LSobject_from_request() for details. + * + * @param[in] $request LSurlRequest The request + * @param[in] $instanciate boolean Instanciate and return an object (optional, default: true) + * @param[in] $check_access callable|null Permit to specify check access method (optional, default: see get_LSobject_from_request()) + * + * @retval LSobject|boolean The instanciated LSobject (or True if $instanciate=false), or False + * on error/access refused + */ +function get_LSobject_from_API_request($request, $instanciate=true, $check_access=null) { + return get_LSobject_from_request($request, $instanciate, $check_access, true); +} + + /* + * Handle API LSobject search + * + * @param[in] $request LSurlRequest The request + * + * @retval void + **/ +function handle_api_LSobject_search($request) { + LSsession :: setAjaxDisplay(); + $object = get_LSobject_from_API_request($request); + if (!$object) + return; + + $LSobject = $object -> getType(); + + if (!LSsession :: loadLSclass('LSsearch')) { + LSsession :: addErrorCode('LSsession_05', 'LSsearch'); + LSsession :: displayAjaxReturn(); + return false; + } + + // Instanciate a LSsearch + $search = new LSsearch($LSobject, 'api', null, isset($_REQUEST['reset'])); + $search -> setParam('onlyAccessible', True); + if (!$search -> setParamsFromRequest()) { + LSsession :: displayAjaxReturn(); + return; + } + + // Run search + if (!$search -> run()) + LSlog :: fatal('Fail to run search.'); + + $all = isset($_REQUEST['all']); + + if ($all) { + $entries = $search -> listEntries(); + if (!is_array($entries)) + LSlog :: fatal("Fail to retreive search result"); + } + else { + // Retrieve page + $page_nb = (isset($_REQUEST['page'])?(int)$_REQUEST['page']:0); + $page = $search -> getPage($page_nb); + + /* + * $page = array( + * 'nb' => $page, + * 'nbPages' => 1, + * 'list' => array(), + * 'total' => $this -> total + * ); + */ + + // Check page + if (!is_array($page) || $page_nb > $page['nbPages']) + LSlog :: fatal("Fail to retreive page #$page_nb."); + } + + // Handle JSON output + $data = array( + 'success' => true, + 'objects' => array(), + 'total' => $search -> total, + ); + if (!$all) { + $data['page'] = $page['nb'] + 1; + $data['nbPages'] = $page['nbPages']; + } + foreach(($all?$entries:$page['list']) as $obj) { + $data['objects'][$obj -> dn] = array( + 'name' => $obj -> displayName, + ); + if ($search -> displaySubDn) + $data['objects'][$obj -> dn][$search -> label_level] = $obj -> subDn; + if ($search -> extraDisplayedColumns) { + foreach ($search -> visibleExtraDisplayedColumns as $cid => $conf) { + $data['objects'][$obj -> dn][$conf['label']] = $obj -> $cid; + } + } + foreach ($search -> attributes as $attr) { + if (LSsession :: canAccess($LSobject, $obj -> dn, 'r', $attr)) + $data['objects'][$obj -> dn][$attr] = $obj -> $attr; + } + } + LSsession :: displayAjaxReturn($data); +} +LSurl :: add_handler('#^api/1.0/object/(?P[^/]+)/?$#', 'handle_api_LSobject_search', true, false, true); + +/* + * Handle API LSobject create request + * + * @param[in] $request LSurlRequest The request + * + * @retval void +**/ +function handle_api_LSobject_create($request) { + LSsession :: setAjaxDisplay(); + $object = get_LSobject_from_API_request( + $request, + true, // instanciate object + array('LSsession', 'canCreate') // Check access method + ); + + if (!$object) + return; + + $data = array('success' => false); + $LSobject = $object -> getType(); + $form = $object -> getForm('create', null, true); // Create form in API mode + + if (isset($_REQUEST['dataEntryForm'])) { + $form -> applyDataEntryForm((string)$_REQUEST['dataEntryForm']); + } + $form -> setSubmited(); + + if ($form->validate(true)) { + // Data update for LDAP object + if ($object -> updateData('create')) { + $data['success'] = true; + $data['type'] = $object -> getType(); + $data['dn'] = $object -> getDn(); + $data['name'] = $object -> getDisplayName(); + LSsession :: addInfo(_("Object has been added.")); + } + else { + $data['fields_errors'] = $form -> getErrors(); + } + } + else if ($form -> definedError()) { + $data['fields_errors'] = $form -> getErrors(); + } + LSsession :: displayAjaxReturn($data); +} +LSurl :: add_handler('#^api/1.0/object/(?P[^/]+)/create/?$#', 'handle_api_LSobject_create', true, false, true); + +/* + * Handle API LSobject show request + * + * @param[in] $request LSurlRequest The request + * + * @retval void +**/ +function handle_api_LSobject_show($request) { + LSsession :: setAjaxDisplay(); + $object = get_LSobject_from_API_request($request); + if (!$object) + return; + + $data = array( + 'success' => true, + 'dn' => $object -> getDn(), + 'type' => $object -> getType(), + 'name' => $object -> getDisplayName(), + 'attributes' => array(), + 'relations' => array(), + ); + + $view = $object -> getView(); + foreach($view -> elements as $element) { + $data['attributes'][$element -> name] = $element -> getApiValue(); + } + + if (LSsession :: loadLSclass('LSrelation')) { + foreach ($object -> getConfig('LSrelation', array(), 'array') as $rel_name => $rel_conf) { + $data['relations'][$rel_name] = array(); + $relation = new LSrelation($object, $rel_name); + $list = $relation -> listRelatedObjects(); + if (is_array($list)) { + foreach($list as $o) { + $data['relations'][$rel_name][$o -> getDn()] = $o -> getDisplayName(NULL,true); + } + } + else { + LSlog :: error("Fail to load related objects."); + } + } + } + LSsession :: displayAjaxReturn($data); +} +LSurl :: add_handler('#^api/1.0/object/(?P[^/]+)/?(?P[^/]+)/?$#', 'handle_api_LSobject_show', true, false, true); + +/* + * Handle API LSobject modify request + * + * @param[in] $request LSurlRequest The request + * + * @retval void +**/ +function handle_api_LSobject_modify($request) { + LSsession :: setAjaxDisplay(); + $object = get_LSobject_from_API_request( + $request, + true, // instanciate object + array('LSsession', 'canEdit') // Check access method + ); + if (!$object) + return; + + $data = array( + 'dn' => $object -> getDn(), + 'type' => $object -> getType(), + 'name' => $object -> getDisplayName(), + 'success' => false, + ); + $form = $object -> getForm('modify', null, true); // Create form in API mode + $form -> setSubmited(); + + if ($form->validate(true)) { + // Update LDAP object data + if ($object -> updateData('modify')) { + // Update successful + if (LSerror::errorsDefined()) { + LSsession :: addInfo(_("The object has been partially modified.")); + } + else { + LSsession :: addInfo(_("The object has been modified successfully.")); + $data['success'] = true; + } + } + elseif ($form -> definedError()) { + $data['fields_errors'] = $form -> getErrors(); + } + } + else if ($form -> definedError()) { + $data['fields_errors'] = $form -> getErrors(); + } + LSsession :: displayAjaxReturn($data); +} +LSurl :: add_handler('#^api/1.0/object/(?P[^/]+)/(?P[^/]+)/modify/?$#', 'handle_api_LSobject_modify', true, false, true); + +/* + * Handle API LSobject remove request + * + * @param[in] $request LSurlRequest The request + * + * @retval void +**/ +function handle_api_LSobject_remove($request) { + LSsession :: setAjaxDisplay(); + $object = get_LSobject_from_API_request( + $request, + true, // instanciate object + array('LSsession', 'canRemove') // Check access method + ); + if (!$object) + return; + + $data = array( + 'dn' => $object -> getDn(), + 'type' => $object -> getType(), + 'name' => $object -> getDisplayName(), + 'success' => false, + ); + + // Remove object (if validated) + if ($object -> remove()) { + LSsession :: addInfo(getFData(_('%{objectname} has been successfully deleted.'), $data['name'])); + $data['success'] = true; + } + else { + LSerror :: addErrorCode('LSldapObject_15', $objectname); + } + LSsession :: displayAjaxReturn($data); +} +LSurl :: add_handler('#^api/1.0/object/(?P[^/]+)/(?P[^/]+)/remove/?$#', 'handle_api_LSobject_remove', true, false, true); + +/* + * Handle API LSobject relation request + * + * @param[in] $request LSurlRequest The request + * + * @retval void +**/ +function handle_api_LSobject_relation($request) { + LSsession :: setAjaxDisplay(); + $object = get_LSobject_from_API_request( + $request, + true, // instanciate object + ); + if (!$object) + return; + + $LSobject = $object -> getType(); + + // Handle relation URL parameter + $relationName = $request -> relation; + if (!is_array($object -> getConfig("LSrelation.$relationName"))) { + LSlog :: log_error("LSobject $LSobject have no relation '$relationName'."); + LSsession :: displayAjaxReturn(); + return false; + } + + // Check user access to this relation + if ( + (isset($_REQUEST['add']) || isset($_REQUEST['remove'])) && + !LSsession :: relationCanEdit($object -> dn, $LSobject, $relationName) + ) { + LSerror :: addErrorCode('LSsession_11'); + LSsession :: displayAjaxReturn(); + return false; + } + + // Load LSrelation PHP class (with warning) + if (!LSsession :: loadLSclass('LSrelation', null, true)) { + LSsession :: displayAjaxReturn(); + return false; + } + + $relation = new LSrelation($object, $relationName); + + $data = array( + 'dn' => $object -> getDn(), + 'type' => $object -> getType(), + 'name' => $object -> getDisplayName(), + 'relation' => $relationName, + 'success' => false, + ); + $warnings = array(); + + // List current related objects + $list = $relation -> listRelatedObjects(); + $listDns = array(); + if (is_array($list)) { + foreach($list as $o) { + $listDns[] = $o -> getDn(); + } + } + LSlog :: debug("Current related object(s): ".varDump($listDns)); + + // Keep a copy of initial related objects list + $initialListDns = $listDns; + + // Handle add + $relatedLSobject = $object -> getConfig("LSrelation.$relationName.LSobject"); + $search = new LSsearch( + $relatedLSobject, + "LSrelation.api.$LSobject.$relationName", + array( + 'scope' => 'base', + ) + ); + if (isset($_REQUEST['add'])) { + foreach (ensureIsArray($_REQUEST['add']) as $dn) { + $dn = urldecode($dn); + // Check if DN is already in relation + if (in_array($dn, $listDns)) { + LSlog :: debug("LSobject $relatedLSobject $dn is already in relation with ".$object -> getDn()."."); + continue; + } + + // Check DN refer to a related object + $search -> setParam('basedn', $dn); + $search -> run(false); + $result = $search -> listObjectsDn(); + if (!is_array($result) || count($result) != 1) { + $warnings[] = "No $relatedLSobject found for DN $dn"; + } + $listDns[] = $dn; + } + } + + if (isset($_REQUEST['remove'])) { + // Handle remove + foreach (ensureIsArray($_REQUEST['remove']) as $dn) { + $dn = urldecode($dn); + $found = false; + while(true) { + $key = array_search($dn, $listDns); + if ($key === false) break; + $found = true; + unset($listDns[$key]); + } + if (!$found) + LSlog :: debug("LSobject $relatedLSobject $dn is not in relation with ".$object -> getDn()."."); + } + } + + // Add new related objects list in result + $data['relatedObjects'] = array_values($listDns); + + if ($warnings) { + LSerror :: addErrorCode(false, "Some problems detected on requested changes."); + $data['warnings'] = $warnings; + } + else if ($initialListDns == $listDns) { + LSsession :: addInfo('No changes done.'); + $data['success'] = true; + } + else { + LSlog :: debug("New related object(s) list: ".varDump($listDns)); + if ($relation -> updateRelations($listDns)) { + LSsession :: addInfo('Objects in relation updated.'); + $data['success'] = true; + } + else { + LSerror :: addErrorCode(false, "Fail to update objects in relation"); + } + } + LSsession :: displayAjaxReturn($data); +} +LSurl :: add_handler('#^api/1.0/object/(?P[^/]+)/(?P[^/]+)/relation/(?P[^/]+)/?$#', 'handle_api_LSobject_relation', true, false, true); diff --git a/src/lang/fr_FR.UTF8/LC_MESSAGES/ldapsaisie.mo b/src/lang/fr_FR.UTF8/LC_MESSAGES/ldapsaisie.mo index f4600759..e5523434 100644 Binary files a/src/lang/fr_FR.UTF8/LC_MESSAGES/ldapsaisie.mo and b/src/lang/fr_FR.UTF8/LC_MESSAGES/ldapsaisie.mo differ diff --git a/src/lang/fr_FR.UTF8/LC_MESSAGES/ldapsaisie.po b/src/lang/fr_FR.UTF8/LC_MESSAGES/ldapsaisie.po index e0cebba9..1a02949f 100644 --- a/src/lang/fr_FR.UTF8/LC_MESSAGES/ldapsaisie.po +++ b/src/lang/fr_FR.UTF8/LC_MESSAGES/ldapsaisie.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: LdapSaisie\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: \n" -"PO-Revision-Date: 2020-12-16 17:41+0100\n" +"PO-Revision-Date: 2021-02-03 14:37+0100\n" "Last-Translator: Benjamin Renard \n" "Language-Team: LdapSaisie \n" @@ -18,7 +18,7 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-SourceCharset: utf-8\n" "X-Poedit-Basepath: /var/www/ldapsaisie/trunk\n" -"X-Generator: Poedit 2.2.1\n" +"X-Generator: Poedit 2.4.2\n" #: /home/brenard/dev/ldapsaisie_clean3/src/includes/addons/LSaddons.samba.php:27 msgid "SAMBA Support: Unable to load smbHash class." @@ -429,67 +429,71 @@ msgstr "" msgid "Your message has been sent successfully." msgstr "Votre message a bien été envoyé." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformRule.php:51 -msgid "LSformRule_%{type} : Parameter %{param} is not found." +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformRule.php:84 +msgid "LSformRule_%{type}: Parameter %{param} is not found." msgstr "LSformRule_%{type} : Le paramètre %{param} n'est pas défini." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:195 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformRule.php:87 +msgid "LSformRule: Unknown rule type %{type}." +msgstr "LSformRule : Type de règle %{type} inconnu." + +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:196 msgid "Error creating object on LDAP server." msgstr "Une erreur est survenue en création cet objet dans l'annuaire LDAP." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:221 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:222 msgid "Error updating object on LDAP server." msgstr "" "Une erreur est survenue en mettant à jour cet objet dans l'annuaire LDAP." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:227 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:228 msgid "Error validating update form." msgstr "Une erreur est survenue en validant le formulaire de mise à jour." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:232 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:233 msgid "Failed to set post data on update form." msgstr "Impossible de définir les données dans le formulaire de mise à jours." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:237 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:238 msgid "" "Failed to load existing object %{dn} from LDAP server. Can't update object." msgstr "" "Impossible de charger l'objet existant %{dn} depuis l'annuaire LDAP. " "Impossible de mettre à jour cet objet." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:242 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:243 msgid "An object already exist on LDAP server with DN %{dn}." msgstr "Un objet existe déjà dans l'annuaire LDAP avec le DN %{dn}." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:246 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:247 msgid "Failed to generate DN for this object." msgstr "Impossible de générer le DN de cet objet." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:250 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:251 msgid "Failed to validate object data." msgstr "Impossible de valider les données de l'objet." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:256 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:257 msgid "Error validating creation form." msgstr "Une erreur est survenue en validant le formulaire de création." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:261 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:262 msgid "Failed to set post data on creation form." msgstr "Impossible de définir les données dans le formulaire de création." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:320 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:321 msgid "LSimport : Post data not found or not completed." msgstr "LSimport : les données transmises sont introuvables ou incomplètes." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:323 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:324 msgid "LSimport : object type invalid." msgstr "LSimport : type d'objet invalide." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:326 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:327 msgid "LSimport : input/output format %{format} invalid." msgstr "LSimport : Le format d'entrée/sortie %{format} est invalide." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:329 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:330 msgid "LSimport : Fail to initialize input/output driver" msgstr "LSimport : Impossible d'initialiser le pilote d'entrée/sortie" @@ -507,10 +511,10 @@ msgstr "Confirmez-vous votre choix ?" #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSconfirmBox.php:37 #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsmoothbox.php:39 -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:70 -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:611 -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1233 -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1375 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:74 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:618 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1240 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1382 #: templates/default/recoverpassword.tpl:21 msgid "Validate" msgstr "Valider" @@ -519,7 +523,7 @@ msgstr "Valider" msgid "Cancel" msgstr "Annuler" -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauthMethod_anonymous.php:69 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauthMethod_anonymous.php:72 msgid "" "LSauthMethod_anonymous : You must define the LSAUTHMETHOD_ANONYMOUS_USER " "contant in the configuration file." @@ -531,13 +535,18 @@ msgstr "" msgid "Attribute" msgstr "Attribut" -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_mailQuota.php:80 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_mailQuota.php:98 #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_valueWithUnit.php:108 -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_quota.php:80 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_quota.php:100 #: templates/default/LSformElement_mailQuota_field.tpl:17 msgid "Incorrect value" msgstr "Valeur incorrecte" +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_mailQuota.php:168 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_labeledValue.php:135 +msgid "Invalid value : \"%{value}\"." +msgstr "Valeur invalide : \"%{value}\"." + #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattr_ldap_sambaAcctFlags.php:136 msgid "Account types" msgstr "Types de comptes" @@ -622,7 +631,7 @@ msgstr "Affichier la clé en entier." msgid "Unknown type" msgstr "Type inconnu" -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_valueWithUnit.php:203 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_valueWithUnit.php:230 msgid "" "LSformElement_valueWithUnit : Units configuration data are missing for the " "attribute %{attr}." @@ -650,10 +659,10 @@ msgstr "" #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_select_object.php:68 #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_supannLabeledValue.php:62 #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearchEntry.php:174 -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:993 -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1161 -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1246 -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1388 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1000 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1168 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1253 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1395 msgid "Modify" msgstr "Modifier" @@ -671,7 +680,7 @@ msgid "No result" msgstr "Aucun résultat" #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_supannCompositeAttribute.php:209 -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_jsonCompositeAttribute.php:288 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_jsonCompositeAttribute.php:345 msgid "Component %{c} must be defined" msgstr "Le composant %{c} est obligatoire" @@ -686,7 +695,7 @@ msgid "Unparsable value for component %{c}." msgstr "Valeur du composant %{c} non-analysable." #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_supannCompositeAttribute.php:247 -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_jsonCompositeAttribute.php:266 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_jsonCompositeAttribute.php:425 msgid "Can't validate value of component %{c}." msgstr "Impossible de valider la valeur du composant %{c}." @@ -750,21 +759,22 @@ msgstr "" msgid "Smarty - An exception occured fetching template '%{template}'" msgstr "Smarty - Un erreur est survenue en générant le modèle '%{template}'." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LStemplate.php:458 -msgid "A fatal error occured." -msgstr "Une erreur fatale est survenue." - -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LStemplate.php:459 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LStemplate.php:460 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LStemplate.php:470 msgid "A fatal error occured. If problem persist, please contact support." msgstr "" "Une erreur irrécupérable est survenue. Si le problème persiste, merci de " "contacter le support." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LStemplate.php:657 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LStemplate.php:469 +msgid "A fatal error occured." +msgstr "Une erreur fatale est survenue." + +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LStemplate.php:669 msgid "LStemplate : Template %{file} not found." msgstr "LStemplate : le template %{file} est introuvable." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LStemplate.php:660 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LStemplate.php:672 msgid "" "LStemplate : Fail to execute trigger %{callable} on event %{event} : is not " "callable." @@ -772,7 +782,7 @@ msgstr "" "LStemplate : Échec d'exécution du déclencheur %{callable} lors de événement " "%{event} : il n'est pas un callable." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LStemplate.php:663 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LStemplate.php:675 msgid "" "LStemplate : Error during the execution of the trigger %{callable} on event " "%{event}." @@ -868,11 +878,11 @@ msgstr "" "LSformRule_differentPassword : Les autres attributs mots de passe doivent " "utiliser LSattr_ldap :: password. Ce n'est pas le cas de l'attribut %{attr}." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:261 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:266 msgid "The value of field %{label} is invalid." msgstr "La valeur du champ %{label} est incorrecte." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:715 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:720 msgid "" "LSattribute : Attribute %{attr} : LDAP or HTML types unknow (LDAP = %{ldap} " "& HTML = %{html})." @@ -880,7 +890,7 @@ msgstr "" "LSattribute : Attribut %{attr} : Les types LDAP ou HTML sont inconnus (LDAP " "= %{ldap} & HTML = %{html})." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:718 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:723 msgid "" "LSattribute : The function %{func} to display the attribute %{attr} is " "unknow." @@ -888,14 +898,14 @@ msgstr "" "LSattribute : La fonction %{func} pour afficher l'attribut %{attr} est " "inconnue." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:721 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:726 msgid "" "LSattribute : The rule %{rule} to validate the attribute %{attr} is unknow." msgstr "" "LSattribute : La règle %{rule} de validation de l'attribut %{attr} n'existe " "pas." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:724 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:729 msgid "" "LSattribute : Configuration data to verify the attribute %{attr} are " "incorrect." @@ -903,22 +913,22 @@ msgstr "" "LSattribute : Les données de configuration pour vérifier l'attribut %{attr} " "sont incorrecte." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:727 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:732 msgid "" "LSattribute : The function %{func} to save the attribute %{attr} is unknow." msgstr "" "LSattribute : La fonction %{func} pour sauvegarder l'attribut %{attr} est " "inconnue." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:730 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:735 msgid "LSattribute : The value of the attribute %{attr} can't be generated." msgstr "LSattribute : La valeur de l'attribut %{attr} ne peut être générée." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:733 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:738 msgid "LSattribute : Generation of the attribute %{attr} failed." msgstr "LSattribute : La génération de l'attribut %{attr} a échouée." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:736 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:741 msgid "" "LSattribute : Generation of the attribute %{attr} did not return a correct " "value." @@ -926,7 +936,7 @@ msgstr "" "LSattribute : La génération de l'attribut %{attr} n'a pas retournée de " "valeur correcte." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:739 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:744 msgid "" "LSattribute : The attr_%{type} of the attribute %{name} is not yet defined." msgstr "" @@ -963,48 +973,48 @@ msgstr "" msgid "Clear" msgstr "Nettoyer" -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:1419 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:1424 msgid "Connection" msgstr "Connexion" -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:1441 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:1446 msgid "Recovery of your credentials" msgstr "Récupération de votre mot de passe" -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:1450 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:1455 msgid "Please fill the identifier field to proceed recovery procedure" msgstr "" "Merci d'entrer votre identifiant pour poursuivre la procédure de récupération" -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:1455 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:1460 msgid "" "An email has been sent to %{mail}. Please follow the instructions on it." msgstr "" "Un e-mail vient de vous être envoyé à l'adresse %{mail}. Merci de suivre les " "indications qu'il contient." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:1464 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:1469 msgid "Your new password has been sent to %{mail}." msgstr "Votre nouveau mot de passe vous a été envoyé à l'adresse %{mail}." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:1633 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:1640 #: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:156 -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:455 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:462 #: templates/default/select.tpl:29 msgid "Refresh" msgstr "Rafraîchir" -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2645 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2713 #: templates/default/select.tpl:20 templates/default/recoverpassword.tpl:17 #: templates/default/login.tpl:16 msgid "Level" msgstr "Niveau" -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2803 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2871 msgid "LSsession : The constant '%{const}' is not defined." msgstr "LSsession : La constante '%{const}' n'est pas définie." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2806 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2874 msgid "" "LSsession : The addon '%{addon}' support is uncertain. Verify system " "compatibility and the add-on configuration." @@ -1012,53 +1022,53 @@ msgstr "" "LSsession : Le support de l'addon '%{addon}' est incertain. Vérifiez la " "compatibilité du système et la configuration de l'add-on." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2809 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2877 msgid "" "LSsession : LDAP server's configuration data are invalid. Can't connect." msgstr "" "LSsession : Les données de configuration du serveur LDAP sont invalide. " "Impossible de s'y connecter." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2812 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2880 msgid "LSsession : Failed to load LSobject type '%{type}' : unknon type." msgstr "" "LSsession : Impossible de charger le type d'LSobject '%{type}' : type " "inconnu." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2815 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2883 msgid "LSsession : Failed to load LSclass '%{class}'." msgstr "LSsession : Impossible de charger la LSclass '%{class}'." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2818 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2886 msgid "LSsession : Login or password incorrect." msgstr "LSsession : Identifiant ou mot de passe incorrects." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2821 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2889 msgid "LSsession : Impossible to identify you : Duplication of identities." msgstr "LSsession : Impossible de vous identifier : Duplication d'identité." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2824 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2892 msgid "LSsession : Can't load class of authentification (%{class})." msgstr "" "LSsession : Impossible de charger la classe d'authentification (%{class})." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2827 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2895 msgid "LSsession : Can't connect to LDAP server." msgstr "LSsession : Impossible de se connecter au serveur LDAP." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2830 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2898 msgid "LSsession : Impossible to authenticate you." msgstr "LSsession : Impossible de vous identifier." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2833 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2901 msgid "LSsession : Your are not authorized to do this action." msgstr "LSsession : Vous n'êtes pas autorisé à faire cette action." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2836 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2904 msgid "LSsession : Some informations are missing to display this page." msgstr "LSsession : Des informations sont manquant pour afficher cette page." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2839 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2907 msgid "" "LSsession : The function '%{function}' of the custom action " "'%{customAction}' does not exists or is not configured." @@ -1066,24 +1076,24 @@ msgstr "" "LSsession : La fonction '%{function}' de l'action personnalisée " "'%{customAction}' n'existe pas ou n'est pas configurée." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2842 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2910 msgid "LSsession : Fail to retreive user's LDAP credentials from LSauth." msgstr "" "LSsession : Erreur en récupérant les identifiants LDAP de l'utilisateur " "depuis LSauth." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2845 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2913 msgid "" "LSsession : Fail to reconnect to LDAP server with user's LDAP credentials." msgstr "" "LSsession : Impossible de se reconnecter au serveur LDAP avec les " "identifiants de l'utilisateur." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2848 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2916 msgid "LSsession : No import/export format define for this object type." msgstr "LSsession : Aucun format d'entrée/sortie définie pour ce type d'objet." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2851 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2919 msgid "" "LSsession : Error during creation of list of levels. Contact administrators. " "(Code : %{code})" @@ -1091,13 +1101,13 @@ msgstr "" "LSsession : Erreur durant la création de la liste des niveaux. Contacter les " "administrateurs. (Code : %{type})" -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2854 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2922 msgid "LSsession : The password recovery is disabled for this LDAP server." msgstr "" "LSsession : La récupération de mot de passe est désactivée pour ce serveur " "LDAP." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2857 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2925 msgid "" "LSsession : Some informations are missing to recover your password. Contact " "administrators." @@ -1105,7 +1115,7 @@ msgstr "" "LSsession : Des informations sont manques pour pouvoir récupérer votre mot " "de passe. Contacter les administrateurs." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2860 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2928 msgid "" "LSsession : Error during password recovery. Contact administrators.(Step : " "%{step})" @@ -1113,7 +1123,7 @@ msgstr "" "LSsession : Erreur durant la récupération de votre mot de passe. Contacter " "les administrateurs. (Etape : %{step})" -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2863 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2931 msgid "" "LSsession : The function '%{func}' configured for the view '%{view}' of the " "LSaddon '%{addon}' is not declared in the LSaddon file." @@ -1121,7 +1131,7 @@ msgstr "" "LSsession : la fonction '%{func}' configurée pour la vue '%{view}' du " "LSaddon '%{addon}' n'est pas déclaré dans le fichier du LSaddon." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2867 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2935 msgid "" "LSsession : The function '%{func}' configured for the view '%{view}' of the " "LSaddon '%{addon}' doesn't exist." @@ -1129,11 +1139,11 @@ msgstr "" "LSsession : la fonction '%{func}' configurée pour la vue '%{view}' du " "LSaddon '%{addon}' n'existe pas." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2870 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2938 msgid "LSsession : invalid related object's DN pass in parameter." msgstr "LSsession : DN d'objet en relation incorrect dans les paramètres." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2873 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2941 msgid "" "LSsession : the LSaddon %{addon} keep using old-style addon view URL. Please " "upgrade it." @@ -1141,7 +1151,7 @@ msgstr "" "LSsession : le LSaddon %{addon} utilise toujours l'ancien type d'URL de " "vues. Merci de le mettre à jour." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2876 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2944 msgid "" "LSsession : You have been redirect from an old-style URL %{url}. Please " "upgrade this link." @@ -1149,7 +1159,7 @@ msgstr "" "LSsession : Vous avez été redirigé depuis une ancienne URL %{url}. Merci de " "le mettre à jour ce lien." -#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2879 +#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2947 msgid "" "LSsession : You always seem to use %{old} in your custom code: Please " "upgrade it and use %{new}.
\n"
@@ -1165,21 +1175,21 @@ msgstr ""
 msgid "The attribute %{attr} is not valid."
 msgstr "L'attribut %{attr} n'est pas valide."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2940
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3035
 msgid "LSldapObject : Object type unknown."
 msgstr "LSldapObject : Type d'objet inconnu."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2943
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3038
 msgid "LSldapObject : Update form is not defined for the object %{obj}."
 msgstr ""
 "LSldapObject : Le formulaire de mise à jour n'est pas défini pour l'objet "
 "%{obj}."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2946
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3041
 msgid "LSldapObject : No form exists for the object %{obj}."
 msgstr "LSldapObject : Aucun formulaire n'existe pour l'objet %{obj}"
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2949
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3044
 msgid ""
 "LSldapObject : The function %{func} to validate the attribute %{attr} the "
 "object %{obj} is unknow."
@@ -1187,7 +1197,7 @@ msgstr ""
 "LSldapObject : La fonction %{func} pour valider l'attribut %{attr} de "
 "l'objet %{obj} est inconnu."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2952
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3047
 msgid ""
 "LSldapObject : Configuration data are missing to validate the attribute "
 "%{attr} of the object %{obj}."
@@ -1195,7 +1205,7 @@ msgstr ""
 "LSldapObject : Des données de configurations sont manquant pour pouvoir "
 "valider l'attribut %{attr} de l'objet %{obj}."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2956
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3051
 msgid ""
 "LSldapObject : The function %{func} to be executed on the object event "
 "%{event} doesn't exist."
@@ -1203,14 +1213,14 @@ msgstr ""
 "LSldapObject : La fonction %{func} devant être exécutée lors de l'évènement "
 "%{event} de l'objet n'existe pas."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2959
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3054
 msgid ""
 "LSldapObject : The %{func} execution on the object event %{event} failed."
 msgstr ""
 "LSldapObject : L'exécution de la fonction %{func} lors de l'évènement "
 "%{event} de l'objet a échouée."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2963
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3058
 msgid ""
 "LSldapObject : Class %{class}, which method %{meth} to be executed on the "
 "object event %{event}, doesn't exist."
@@ -1218,7 +1228,7 @@ msgstr ""
 "La classe %{class}, contenant la méthode %{meth} devant être exécutée lors "
 "de l'évènement %{event} de l'objet, n'existe pas."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2966
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3061
 msgid ""
 "LSldapObject : Method %{meth} within %{class} class to be executed on object "
 "event %{event}, doesn't exist."
@@ -1226,7 +1236,7 @@ msgstr ""
 "LSldapObject : La méthode %{meth} de la classe %{class} devant être exécutée "
 "lors de l'évènement %{event} de l'objet n'existe pas."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2969
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3064
 msgid ""
 "LSldapObject : Error during execute %{meth} method within %{class} class, to "
 "be executed on object event %{event}."
@@ -1234,7 +1244,7 @@ msgstr ""
 "LSldapObject : Erreur durant l'exécution de la méthode %{meth} de la classe "
 "%{class} devant être exécutée lors de l'évènement %{event} de l'objet."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2973
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3068
 msgid ""
 "LSldapObject : Some configuration data of the object type %{obj} are missing "
 "to generate the DN of the new object."
@@ -1242,7 +1252,7 @@ msgstr ""
 "LSldapObject : Des informations de configuration du type d'objet %{obj} sont "
 "manquantes pour la génération du DN du nouvel objet."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2976
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3071
 msgid ""
 "LSldapObject : The attibute %{attr} of the object is not yet defined. Can't "
 "generate DN."
@@ -1250,11 +1260,11 @@ msgstr ""
 "LSldapObjet : L'attribut %{attr} de l'objet n'est pas encore défini. "
 "Impossible de générer le DN."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2979
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3074
 msgid "LSldapObject : Without DN, the object could not be changed."
 msgstr "LSldapObject : Sans DN, l'objet ne peut pas être modifié."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2982
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3077
 msgid ""
 "LSldapObject : The attribute %{attr_depend} depending on the attribute "
 "%{attr} doesn't exist."
@@ -1262,39 +1272,39 @@ msgstr ""
 "LSldapObject : L'attritbut %{attr_depend} dépendant de l'attribut %{attr} "
 "n'existe pas."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2985
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3080
 msgid "LSldapObject : Error during deleting the object %{objectname}."
 msgstr "LSldapObject : Erreur durant la suppression de l'objet %{objectname}"
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2989
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3084
 msgid ""
 "LSldapObject : Error during actions to be executed before renaming the objet."
 msgstr ""
 "LSldapObject : Erreur durant les actions devant être exécutée avant de "
 "renommer l'objet."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2992
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3087
 msgid ""
 "LSldapObject : Error during actions to be executed after renaming the objet."
 msgstr ""
 "LSldapObject : Erreur durant les actions devant être exécutée après avoir "
 "renommé l'objet."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2996
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3091
 msgid ""
 "LSldapObject : Error during actions to be executed before deleting the objet."
 msgstr ""
 "LSldapObject : Erreur durant les actions devant être exécutée avant de "
 "supprimer l'objet."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2999
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3094
 msgid ""
 "LSldapObject : Error during actions to be executed after deleting the objet."
 msgstr ""
 "LSldapObject : Erreur durant les actions devant être exécutée après avoir "
 "supprimé l'objet."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3003
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3098
 msgid ""
 "LSldapObject : Error during the actions to be executed before creating the "
 "object."
@@ -1302,7 +1312,7 @@ msgstr ""
 "LSldapObject : Erreur durant les actions devant être exécutée avant de créer "
 "l'objet."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3006
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3101
 msgid ""
 "LSldapObject : Error during the actions to be executed after creating the "
 "object. It was created anyway."
@@ -1310,7 +1320,7 @@ msgstr ""
 "LSldapObject : Erreur durant les actions devant être exécutées après la "
 "création de l'objet. Il a tout de même été créé."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3010
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3105
 msgid ""
 "LSldapObject : The function %{func} to be executed before creating the "
 "object doesn't exist."
@@ -1318,7 +1328,7 @@ msgstr ""
 "LSldapObject : La fonction %{func} devant être exécutée avant la création de "
 "l'objet n'existe pas."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3013
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3108
 msgid ""
 "LSldapObject : Error executing the function %{func} to be execute after "
 "deleting the object."
@@ -1326,7 +1336,7 @@ msgstr ""
 "LSldapObject : Erreur durant l'exécution de la fonction %{func} devant être "
 "exécutée après la suppression de l'objet."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3016
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3111
 msgid ""
 "LSldapObject : The function %{func} to be executed after deleting the object "
 "doesn't exist."
@@ -1334,7 +1344,7 @@ msgstr ""
 "LSldapObject : La fonction %{func} devant être exécutée après la suppression "
 "de l'objet n'existe pas."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3019
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3114
 msgid ""
 "LSldapObject : Error executing the function %{func} to be execute after "
 "creating the object."
@@ -1342,7 +1352,7 @@ msgstr ""
 "LSldapObject : Erreur durant l'exécution de la fonction %{func} devant être "
 "exécutée après la création de l'objet."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3023
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3118
 msgid ""
 "LSldapObject : %{func} function, to be executed on object event %{event}, "
 "doesn't exist."
@@ -1350,7 +1360,7 @@ msgstr ""
 "LSldapObject : La fonction %{func}, devant être exécutée lors de l'évènement "
 "%{event} de l'objet, n'existe pas."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3026
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3121
 msgid ""
 "LSldapObject : Error during the execution of %{func} function on object "
 "event %{event}."
@@ -1358,7 +1368,7 @@ msgstr ""
 "LSldapObject : Erreur durant l'exécution de la fonction %{func} lors de "
 "l'évènement %{event} de l'objet."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3030
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3125
 msgid ""
 "LSldapObject : %{meth} method, to be executed on object event %{event}, "
 "doesn't exist."
@@ -1366,7 +1376,7 @@ msgstr ""
 "LSldapObject : La méthode %{meth}, devant être exécutée lors de l'évènement "
 "%{event} de l'objet, n'existe pas."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3033
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3128
 msgid ""
 "LSldapObject : Error during execution of %{meth} method on object event "
 "%{event}."
@@ -1374,13 +1384,13 @@ msgstr ""
 "LSldapObject : Erreur durant l'exécution de la méthode %{meth} lors de "
 "l'évènement %{event} de l'objet."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3036
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3131
 msgid "LSldapObject : Error during generate LDAP filter for %{LSobject}."
 msgstr ""
 "LSldapObject : Erreur durant la génération du filtre LDAP de l'objet "
 "%{LSobject}."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3040
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3135
 msgid ""
 "LSldapObject : Error during execution of the custom action %{customAction} "
 "on %{objectname}."
@@ -1388,22 +1398,22 @@ msgstr ""
 "LSldapObject : Erreur durant l'exécution de l'action personnalisée "
 "%{customAction} sur l'objet %{objectname}."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3044
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3139
 msgid "LSldapObject : Fail to retrieve container DN."
 msgstr "LSldapObject : Impossible de récupérer le DN parent."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3047
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3142
 msgid ""
 "LSldapObject : The function %{func} to generate container DN is not callable."
 msgstr ""
 "LSldapObject : La fonction %{func} pour générer le DN parent n'est pas "
 "exécutable."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3050
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3145
 msgid "LSldapObject : Error during generating container DN : %{error}"
 msgstr "LSldapObject : Erreur durant la génération du DN parent : %{error}."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3053
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3148
 msgid ""
 "LSldapObject : An LDAP object with the same DN as generated for this new one "
 "already exists. Please verify your configuration."
@@ -1411,7 +1421,7 @@ msgstr ""
 "LSldapObject : Un objet LDAP avec le même DN que celui généré pour ce nouvel "
 "objet existe déjà. Merci de vérifier votre configuration."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3058
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3153
 msgid ""
 "LSrelation : Some parameters are missing in the call of methods to handle "
 "standard relations (Method : %{meth})."
@@ -1427,34 +1437,38 @@ msgstr ""
 "LSformRule_password : Regex invalide configurée : %{regex}. Vous devez "
 "utiliser des regex de type PCRE (commencant par le caractère '/')."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldap.php:543
-msgid "LSldap : Error during the LDAP server connection (%{msg})."
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldap.php:581
+msgid "LSldap: Error during the LDAP server connection (%{msg})."
 msgstr "LSldap : Erreur durant la connexion au serveur LDAP (%{msg})."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldap.php:546
-msgid "LSldap : Error during the LDAP search (%{msg})."
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldap.php:584
+msgid "LSldap: Error during the LDAP search (%{msg})."
 msgstr "LSldap : Erreur pendant la recherche LDAP (%{msg})."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldap.php:549
-msgid "LSldap : Object type unknown."
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldap.php:587
+msgid "LSldap: Object type unknown."
 msgstr "LSldap : Type d'objet inconnu."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldap.php:552
-msgid "LSldap : Error while fetching the LDAP entry."
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldap.php:590
+msgid "LSldap: Error while fetching the LDAP entry."
 msgstr "LSldap : Erreur durant la récupération de l'entrée LDAP."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldap.php:555
-msgid "LSldap : Error while changing the LDAP entry (DN : %{dn})."
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldap.php:593
+msgid "LSldap: Error while changing the LDAP entry (DN : %{dn})."
 msgstr "LSldap : Erreur durant la modification de l'entrée LDAP (DN : %{dn})."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldap.php:558
-msgid "LSldap : Error while deleting empty attributes."
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldap.php:596
+msgid "LSldap: Error while deleting empty attributes."
 msgstr "LSldap : Erreur durant la suppression des attributs vides."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldap.php:561
-msgid "LSldap : Error while changing the DN of the object."
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldap.php:599
+msgid "LSldap: Error while changing the DN of the object."
 msgstr "LSldap : Erreur pendant la modification du DN de l'objet."
 
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldap.php:602
+msgid "LSldap: LDAP server base DN not configured."
+msgstr "LSldap : Le base DN du serveur LDAP n'est pas configuré."
+
 #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSrelation.php:331
 msgid "listing related objects"
 msgstr "énumaration des objets liés"
@@ -1485,12 +1499,12 @@ msgid "Warning"
 msgstr "Attention"
 
 #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSrelation.php:644
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:243
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:248
 #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_select_object.php:69
 #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_select_object.php:85
 #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearchEntry.php:190
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1009
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1153
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1016
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1160
 msgid "Delete"
 msgstr "Supprimer"
 
@@ -1500,8 +1514,8 @@ msgid "No object."
 msgstr "Aucun objet."
 
 #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSrelation.php:712
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:442
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:938
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:449
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:945
 msgid "New"
 msgstr "Nouveau"
 
@@ -1690,23 +1704,23 @@ msgstr ""
 "des constantes suivantes : LSAUTH_CAS_SERVER_SSL_CACERT ou "
 "LSAUTH_CAS_SERVER_NO_SSL_VALIDATION"
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:121
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:126
 msgid "Add a field to add another values."
 msgstr "Ajouter une autre valeur à ce champ."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:122
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:127
 msgid "Delete this field."
 msgstr "Supprimer cette valeur."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:224
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:607
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:229
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:614
 msgid "Do you really want to execute custom action %{title} on this search ?"
 msgstr ""
 "Êtes-vous vraiment sûre de vouloir exécuter l'action personnalisée %{title} "
 "sur cette recherche ?"
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:230
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1369
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:235
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1376
 msgid ""
 "Do you really want to execute custom action %{customAction} on "
 "%{objectname} ?"
@@ -1714,53 +1728,53 @@ msgstr ""
 "Êtes-vous vraiment sûre de vouloir exécuter l'action personnalisée "
 "%{customAction} sur %{objectname} ?"
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:241
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:246
 msgid "Do you really want to delete \"%{name}\"?"
 msgstr "Voulez-vous vraiment supprimer \"%{name}\" ?"
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:242
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:247
 msgid "Caution"
 msgstr "Attention"
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:296
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:301
 msgid "%{label} attribute data is not valid."
 msgstr "Les données de l'attribut %{label} sont incorrectes."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:379
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:384
 msgid "Mandatory field"
 msgstr "Champ obligatoire"
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:855
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:873
 msgid "LSform : Error during the recovery of the values of the form."
 msgstr "LSform : Erreur durant la récupération des valeurs du formulaire."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:858
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:876
 msgid ""
 "LSform : Error durring the recovery of the value of the field '%{element}'."
 msgstr ""
 "LSform : Erreur durant la recupération de la valeur du champ %{element}."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:865
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:883
 msgid "LSform : The field %{element} doesn't exist."
 msgstr "LSform : Le champ %{element} n'existe pas."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:868
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:886
 msgid "LSfom : Field type unknow (%{type})."
 msgstr "LSform : Type de champ inconnu (%{type})."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:871
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:889
 msgid "LSform : Error during the creation of the element '%{element}'."
 msgstr "LSform : Erreur durant la création de l'élément %{element}."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:874
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:892
 msgid "LSform : The data entry form %{name} doesn't exist."
 msgstr "LSform : Le masque de saisie %{name} n'existe pas."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:877
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:895
 msgid "LSform : The data entry form %{name} is not correctly configured."
 msgstr "LSform : Le masque de saisie %{name} n'est pas correctement configuré."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:880
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:898
 msgid ""
 "LSform : The element %{name}, listed as displayed in data entry form "
 "configuration, doesn't exist."
@@ -1805,27 +1819,27 @@ msgstr "Ajout rapide"
 msgid "Display advanced search and selection panel."
 msgstr "Afficher la fenêtre de recherche et de sélection étendue."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSurl.php:105
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSurl.php:108
 msgid "Fail to determine the requested URL."
 msgstr "Impossible de déterminer l'URL demandée."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSurl.php:109
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSurl.php:112
 msgid "No URL patterns configured !"
 msgstr "Aucun modèle d'URL configuré !"
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSurl.php:210
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSurl.php:216
 msgid "Fail to determine the requested URL (loop detected)."
 msgstr "Impossible de déterminer l'URL demandée (boucle détectée)."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSurl.php:231
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSurl.php:238
 msgid "The requested page was not found."
 msgstr "La page demandée est introuvable."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSurl.php:249
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSurl.php:263
 msgid "This request could not be handled."
 msgstr "Cette requête ne peut être traitée."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSurl.php:266
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSurl.php:282
 msgid "This request could not be processed correctly."
 msgstr "Cette requête ne peut être traitée correctement."
 
@@ -1834,7 +1848,11 @@ msgstr "Cette requête ne peut être traitée correctement."
 msgid "Invalid value"
 msgstr "Valeur invalide"
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauthMethod_HTTP.php:136
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauthMethod_HTTP.php:103
+msgid "LdapSaisie - Authentication required"
+msgstr "LdapSaisie - Authentification requise"
+
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauthMethod_HTTP.php:150
 msgid "LSauthMethod_HTTP : the %{var} environnement variable is missing."
 msgstr "LSauthMethod_HTTP : la variable d'environnement %{var} est manquante."
 
@@ -1851,8 +1869,8 @@ msgid "Display RSS stack."
 msgstr "Afficher la file RSS."
 
 #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattr_ldap_password.php:100
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:567
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1319
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:574
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1326
 msgid "undefined"
 msgstr "non-définie"
 
@@ -1872,39 +1890,43 @@ msgstr ""
 "LSattr_ldap_password : La fonction d'encodage %{function} n'est pas "
 "disponible. Le mot de passe sera stocké en clair."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauth.php:282
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauth.php:308
 msgid "LSauth : Login or password incorrect."
 msgstr "LSauth : Identifiant ou mot de passe incorrects."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauth.php:285
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauth.php:311
 msgid "LSauth : Impossible to identify you : Duplication of identities."
 msgstr "LSauth : Impossible de vous identifier : Duplication d'identité."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauth.php:288
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauth.php:314
 msgid "LSauth : Could not load type of identifiable objects %{type}."
 msgstr "LSauth : Impossible de charger le type d'objets identifiables %{type}."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauth.php:291
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauth.php:317
 msgid "LSauth : Can't load authentication method %{method}."
 msgstr ""
 "LSauth : Impossible de charger la méthode d'authentification %{method}."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauth.php:294
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauth.php:320
 msgid "LSauth : Failed to build the authentication provider %{method}."
 msgstr ""
 "LSauth : Impossible de construire le gestionnaire d'authentification "
 "%{method}."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauth.php:297
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauth.php:323
 msgid "LSauth : Not correctly initialized."
 msgstr "LSauth : Mauvaise initialisation."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauth.php:300
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauth.php:326
 msgid "LSauth : Failed to get authentication informations from provider."
 msgstr ""
 "LSauth : Impossible de récupérer les informations authentification auprès du "
 "gestionnaire."
 
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauth.php:329
+msgid "LSauth : Method %{method} configured doesn't support API mode."
+msgstr "LSauth : La méthode %{method} configurée ne supporte pas le mode API."
+
 #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_supannEtuInscription.php:41
 msgid "Organism"
 msgstr "Etablissement"
@@ -1950,39 +1972,39 @@ msgstr "Étape"
 msgid "Pedagogical element"
 msgstr "Élement pédagogique"
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1143
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1200
 msgid "Actions"
 msgstr "Actions"
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1146
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1203
 #: templates/default/global_search.tpl:16
 msgid "This search didn't get any result."
 msgstr "Cette recherche n'a retournée aucun résultat."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1711
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1842
 msgid "LSsearch : Invalid filter : %{filter}."
 msgstr "LSsearch : Filtre invalide : %{filter}."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1714
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1845
 msgid "LSsearch : Invalid basedn : %{basedn}."
 msgstr "LSsearch : Base DN invalide."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1717
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1848
 msgid "LSsearch : Invalid value for %{param} parameter."
 msgstr "LSsearch : La valeur du paramètre %{param} est incorrecte."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1720
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1851
 msgid ""
 "LSsearch : Invalid size limit. Must be an integer greater or equal to 0."
 msgstr ""
 "LSsearch : Limite de taille de recherche invalide. Elle doit être un entier "
 "supérieur ou égal à 0."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1723
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1854
 msgid "LSsearch : Invalid parameter %{attr}. Must be an boolean."
 msgstr "LSsearch : Paramètre %{param} invalide. Il doit être un booléen."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1726
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1857
 msgid ""
 "LSsearch : Invalid parameter attributes. Must be an string or an array of "
 "strings."
@@ -1990,13 +2012,13 @@ msgstr ""
 "LSsearch : Paramètre 'attributes' invalide. Il doit être une chaîne de "
 "caractères ou un tableau de chaînes de caractères."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1729
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1860
 msgid "LSsearch : Can't build attributes list for make filter."
 msgstr ""
 "LSsearch : Impossible de construire la liste des attributs pour faire le "
 "filtre."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1732
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1863
 msgid ""
 "LSsearch : Error building filter with attribute '%{attr}' and pattern "
 "'%{pattern}'"
@@ -2004,34 +2026,34 @@ msgstr ""
 "LSsearch : Problème en construisant le filtre avec l'attribut '%{attr}' et "
 "le mot clé '%{pattern}'"
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1735
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1866
 msgid "LSsearch : Error combining filters."
 msgstr "LSsearch : Problème en combinant les filtres."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1738
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1869
 msgid "LSsearch : Invalid pattern."
 msgstr "LSsearch : Mot clé invalide."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1741
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1872
 msgid "LSsearch : Invalid attribute %{attr} in parameters."
 msgstr "LSsearch : Attribut %{attr} incorrect dans les paramètres."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1744
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1875
 msgid "LSsearch : Error during the search."
 msgstr "LSsearch : Erreur pendant la recherche."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1747
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1878
 msgid "LSsearch : Error sorting the search."
 msgstr "LSsearch : Erreur pendant le trie de la recherche."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1750
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1881
 msgid ""
 "LSsearch : The function of the custum information %{name} is not callable."
 msgstr ""
 "LSsearch : La fonction de l'information personnalisée %{name} n'est pas "
 "exécutable."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1753
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1884
 msgid ""
 "LSsearch : Invalid predefinedFilter for LSobject type %{type} : %{label} "
 "(filter : %{filter})."
@@ -2039,13 +2061,13 @@ msgstr ""
 "LSsearch : PredefinedFilter invalide pour le type d'LSobject %{type} : "
 "%{label} (filtre : %{filter})."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1756
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1887
 msgid "LSsearch : Error during execution of the custom action %{customAction}."
 msgstr ""
 "LSldapObject : Erreur durant l'exécution de l'action personnalisée "
 "%{customAction}."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1759
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1890
 msgid "LSsearch : Invalid search pattern."
 msgstr "LSsearch : Mot clé de recherche invalide."
 
@@ -2165,8 +2187,12 @@ msgstr ""
 "LSformRule_inarray : Les valeurs possibles n'ont pas été configurées pour "
 "valider les données."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_jsonCompositeAttribute.php:248
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_jsonCompositeAttribute.php:261
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_jsonCompositeAttribute.php:260
+msgid "Fail to decode JSON value #%{idx}."
+msgstr "Impossible de décoder la valeur JSON #%{idx}."
+
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_jsonCompositeAttribute.php:392
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_jsonCompositeAttribute.php:415
 msgid "Invalid value \"%{value}\" for component %{component}."
 msgstr "Valeur invalide pour le composant %{component} : \"%{value}\"."
 
@@ -2230,23 +2256,23 @@ msgstr "Erreurs"
 msgid "Stop"
 msgstr "Stop"
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSerror.php:154
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSerror.php:158
 msgid "Unknown error"
 msgstr "Erreur inconnue"
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSerror.php:209
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSerror.php:213
 msgid "Unknown error : %{error}"
 msgstr "Erreur inconnu : %{error}"
 
 #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearchEntry.php:166
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1145
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1238
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1380
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1152
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1245
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1387
 msgid "View"
 msgstr "Voir"
 
 #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearchEntry.php:182
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1001
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1008
 msgid "Copy"
 msgstr "Copier"
 
@@ -2276,70 +2302,74 @@ msgstr "Accueil"
 msgid "You must provide pattern for global search."
 msgstr "Vous devez fournir un mot clé pour les recherches globales."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:448
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:796
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:455
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:803
 msgid "Import"
 msgstr "Importer"
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:460
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:467
 msgid "Reset"
 msgstr "Réinitialiser"
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:498
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:505
 #: templates/default/select.tpl:28 templates/default/global_search.tpl:6
 msgid "Search"
 msgstr "Rechercher"
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:499
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:506
 #: templates/default/select.tpl:31
 msgid "Approximative search"
 msgstr "Recherche approximative"
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:500
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:507
 #: templates/default/select.tpl:32
 msgid "Recursive search"
 msgstr "Recherche récursive"
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:586
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:593
 msgid ""
 "The custom action %{title} have been successfully execute on this search."
 msgstr ""
 "L'action personnalisée %{title} a été correctement exécutée sur cette "
 "recherche."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:897
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:904
 msgid "Data entry form"
 msgstr "Masque de saisie"
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:903
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:910
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1626
 msgid "Object has been added."
 msgstr "L'objet a été ajouté."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1040
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1047
 msgid "My account"
 msgstr "Mon compte"
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1103
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1110
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1716
 msgid "The object has been partially modified."
 msgstr "L'objet a été partiellement modifié."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1106
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1113
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1719
 msgid "The object has been modified successfully."
 msgstr "L'objet a bien été modifié."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1221
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1228
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1760
 msgid "%{objectname} has been successfully deleted."
 msgstr "%{objectname} a bien été supprimé."
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1230
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1237
 msgid "Deleting : %{objectname}"
 msgstr "Suppression : %{objectname}"
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1231
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1238
 msgid "Do you really want to delete %{displayName} ?"
 msgstr "Voulez-vous vraiment supprimer %{displayName} ?"
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1341
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1348
 msgid ""
 "The custom action %{customAction} have been successfully execute on "
 "%{objectname}."
diff --git a/src/lang/ldapsaisie.pot b/src/lang/ldapsaisie.pot
index e86d6707..d6abf8c5 100644
--- a/src/lang/ldapsaisie.pot
+++ b/src/lang/ldapsaisie.pot
@@ -352,64 +352,68 @@ msgstr ""
 msgid "Your message has been sent successfully."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformRule.php:51
-msgid "LSformRule_%{type} : Parameter %{param} is not found."
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformRule.php:84
+msgid "LSformRule_%{type}: Parameter %{param} is not found."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:195
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformRule.php:87
+msgid "LSformRule: Unknown rule type %{type}."
+msgstr ""
+
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:196
 msgid "Error creating object on LDAP server."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:221
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:222
 msgid "Error updating object on LDAP server."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:227
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:228
 msgid "Error validating update form."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:232
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:233
 msgid "Failed to set post data on update form."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:237
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:238
 msgid ""
 "Failed to load existing object %{dn} from LDAP server. Can't update object."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:242
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:243
 msgid "An object already exist on LDAP server with DN %{dn}."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:246
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:247
 msgid "Failed to generate DN for this object."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:250
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:251
 msgid "Failed to validate object data."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:256
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:257
 msgid "Error validating creation form."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:261
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:262
 msgid "Failed to set post data on creation form."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:320
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:321
 msgid "LSimport : Post data not found or not completed."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:323
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:324
 msgid "LSimport : object type invalid."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:326
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:327
 msgid "LSimport : input/output format %{format} invalid."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:329
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSimport.php:330
 msgid "LSimport : Fail to initialize input/output driver"
 msgstr ""
 
@@ -427,10 +431,10 @@ msgstr ""
 
 #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSconfirmBox.php:37
 #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsmoothbox.php:39
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:70
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:611
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1233
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1375
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:74
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:618
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1240
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1382
 #: templates/default/recoverpassword.tpl:21
 msgid "Validate"
 msgstr ""
@@ -439,7 +443,7 @@ msgstr ""
 msgid "Cancel"
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauthMethod_anonymous.php:69
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauthMethod_anonymous.php:72
 msgid ""
 "LSauthMethod_anonymous : You must define the LSAUTHMETHOD_ANONYMOUS_USER "
 "contant in the configuration file."
@@ -449,13 +453,18 @@ msgstr ""
 msgid "Attribute"
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_mailQuota.php:80
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_mailQuota.php:98
 #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_valueWithUnit.php:108
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_quota.php:80
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_quota.php:100
 #: templates/default/LSformElement_mailQuota_field.tpl:17
 msgid "Incorrect value"
 msgstr ""
 
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_mailQuota.php:168
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_labeledValue.php:135
+msgid "Invalid value : \"%{value}\"."
+msgstr ""
+
 #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattr_ldap_sambaAcctFlags.php:136
 msgid "Account types"
 msgstr ""
@@ -534,7 +543,7 @@ msgstr ""
 msgid "Unknown type"
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_valueWithUnit.php:203
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_valueWithUnit.php:230
 msgid ""
 "LSformElement_valueWithUnit : Units configuration data are missing for the "
 "attribute %{attr}."
@@ -556,10 +565,10 @@ msgstr ""
 #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_select_object.php:68
 #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_supannLabeledValue.php:62
 #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearchEntry.php:174
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:993
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1161
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1246
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1388
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1000
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1168
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1253
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1395
 msgid "Modify"
 msgstr ""
 
@@ -577,7 +586,7 @@ msgid "No result"
 msgstr ""
 
 #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_supannCompositeAttribute.php:209
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_jsonCompositeAttribute.php:288
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_jsonCompositeAttribute.php:345
 msgid "Component %{c} must be defined"
 msgstr ""
 
@@ -592,7 +601,7 @@ msgid "Unparsable value for component %{c}."
 msgstr ""
 
 #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_supannCompositeAttribute.php:247
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_jsonCompositeAttribute.php:266
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_jsonCompositeAttribute.php:425
 msgid "Can't validate value of component %{c}."
 msgstr ""
 
@@ -650,25 +659,26 @@ msgstr ""
 msgid "Smarty - An exception occured fetching template '%{template}'"
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LStemplate.php:458
-msgid "A fatal error occured."
-msgstr ""
-
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LStemplate.php:459
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LStemplate.php:460
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LStemplate.php:470
 msgid "A fatal error occured. If problem persist, please contact support."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LStemplate.php:657
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LStemplate.php:469
+msgid "A fatal error occured."
+msgstr ""
+
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LStemplate.php:669
 msgid "LStemplate : Template %{file} not found."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LStemplate.php:660
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LStemplate.php:672
 msgid ""
 "LStemplate : Fail to execute trigger %{callable} on event %{event} : is not "
 "callable."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LStemplate.php:663
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LStemplate.php:675
 msgid ""
 "LStemplate : Error during the execution of the trigger %{callable} on event "
 "%{event}."
@@ -739,53 +749,53 @@ msgid ""
 "LSattr_ldap :: password. It's not the case of the attribure %{attr}."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:261
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:266
 msgid "The value of field %{label} is invalid."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:715
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:720
 msgid ""
 "LSattribute : Attribute %{attr} : LDAP or HTML types unknow (LDAP = %{ldap} "
 "& HTML = %{html})."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:718
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:723
 msgid ""
 "LSattribute : The function %{func} to display the attribute %{attr} is "
 "unknow."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:721
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:726
 msgid ""
 "LSattribute : The rule %{rule} to validate the attribute %{attr} is unknow."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:724
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:729
 msgid ""
 "LSattribute : Configuration data to verify the attribute %{attr} are "
 "incorrect."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:727
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:732
 msgid ""
 "LSattribute : The function %{func} to save the attribute %{attr} is unknow."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:730
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:735
 msgid "LSattribute : The value of the attribute %{attr} can't be generated."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:733
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:738
 msgid "LSattribute : Generation of the attribute %{attr} failed."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:736
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:741
 msgid ""
 "LSattribute : Generation of the attribute %{attr} did not return a correct "
 "value."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:739
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattribute.php:744
 msgid ""
 "LSattribute : The attr_%{type} of the attribute %{name} is not yet defined."
 msgstr ""
@@ -816,161 +826,161 @@ msgstr ""
 msgid "Clear"
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:1419
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:1424
 msgid "Connection"
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:1441
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:1446
 msgid "Recovery of your credentials"
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:1450
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:1455
 msgid "Please fill the identifier field to proceed recovery procedure"
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:1455
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:1460
 msgid ""
 "An email has been sent to  %{mail}. Please follow the instructions on it."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:1464
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:1469
 msgid "Your new password has been sent to %{mail}."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:1633
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:1640
 #: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:156
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:455
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:462
 #: templates/default/select.tpl:29
 msgid "Refresh"
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2645
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2713
 #: templates/default/select.tpl:20 templates/default/recoverpassword.tpl:17
 #: templates/default/login.tpl:16
 msgid "Level"
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2803
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2871
 msgid "LSsession : The constant '%{const}' is not defined."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2806
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2874
 msgid ""
 "LSsession : The addon '%{addon}' support is uncertain. Verify system "
 "compatibility and the add-on configuration."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2809
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2877
 msgid ""
 "LSsession : LDAP server's configuration data are invalid. Can't connect."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2812
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2880
 msgid "LSsession : Failed to load LSobject type '%{type}' : unknon type."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2815
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2883
 msgid "LSsession : Failed to load LSclass '%{class}'."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2818
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2886
 msgid "LSsession : Login or password incorrect."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2821
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2889
 msgid "LSsession : Impossible to identify you : Duplication of identities."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2824
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2892
 msgid "LSsession : Can't load class of authentification (%{class})."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2827
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2895
 msgid "LSsession : Can't connect to LDAP server."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2830
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2898
 msgid "LSsession : Impossible to authenticate you."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2833
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2901
 msgid "LSsession : Your are not authorized to do this action."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2836
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2904
 msgid "LSsession : Some informations are missing to display this page."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2839
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2907
 msgid ""
 "LSsession : The function '%{function}' of the custom action "
 "'%{customAction}' does not exists or is not configured."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2842
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2910
 msgid "LSsession : Fail to retreive user's LDAP credentials from LSauth."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2845
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2913
 msgid ""
 "LSsession : Fail to reconnect to LDAP server with user's LDAP credentials."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2848
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2916
 msgid "LSsession : No import/export format define for this object type."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2851
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2919
 msgid ""
 "LSsession : Error during creation of list of levels. Contact administrators. "
 "(Code : %{code})"
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2854
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2922
 msgid "LSsession : The password recovery is disabled for this LDAP server."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2857
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2925
 msgid ""
 "LSsession : Some informations are missing to recover your password. Contact "
 "administrators."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2860
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2928
 msgid ""
 "LSsession : Error during password recovery. Contact administrators.(Step : "
 "%{step})"
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2863
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2931
 msgid ""
 "LSsession : The function '%{func}' configured for the view '%{view}' of the "
 "LSaddon '%{addon}' is not declared in the LSaddon file."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2867
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2935
 msgid ""
 "LSsession : The function '%{func}' configured for the view '%{view}' of the "
 "LSaddon '%{addon}' doesn't exist."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2870
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2938
 msgid "LSsession : invalid related object's DN pass in parameter."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2873
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2941
 msgid ""
 "LSsession : the LSaddon %{addon} keep using old-style addon view URL. Please "
 "upgrade it."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2876
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2944
 msgid ""
 "LSsession : You have been redirect from an old-style URL %{url}. Please "
 "upgrade this link."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2879
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsession.php:2947
 msgid ""
 "LSsession : You always seem to use %{old} in your custom code: Please "
 "upgrade it and use %{new}.
\n"
@@ -982,195 +992,195 @@ msgstr ""
 msgid "The attribute %{attr} is not valid."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2940
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3035
 msgid "LSldapObject : Object type unknown."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2943
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3038
 msgid "LSldapObject : Update form is not defined for the object %{obj}."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2946
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3041
 msgid "LSldapObject : No form exists for the object %{obj}."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2949
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3044
 msgid ""
 "LSldapObject : The function %{func} to validate the attribute %{attr} the "
 "object %{obj} is unknow."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2952
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3047
 msgid ""
 "LSldapObject : Configuration data are missing to validate the attribute "
 "%{attr} of the object %{obj}."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2956
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3051
 msgid ""
 "LSldapObject : The function %{func} to be executed on the object event "
 "%{event} doesn't exist."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2959
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3054
 msgid ""
 "LSldapObject : The %{func} execution on the object event %{event} failed."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2963
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3058
 msgid ""
 "LSldapObject : Class %{class}, which method %{meth} to be executed on the "
 "object event %{event}, doesn't exist."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2966
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3061
 msgid ""
 "LSldapObject : Method %{meth} within %{class} class to be executed on object "
 "event %{event}, doesn't exist."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2969
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3064
 msgid ""
 "LSldapObject : Error during execute %{meth} method within %{class} class, to "
 "be executed on object event %{event}."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2973
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3068
 msgid ""
 "LSldapObject : Some configuration data of the object type %{obj} are missing "
 "to generate the DN of the new object."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2976
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3071
 msgid ""
 "LSldapObject : The attibute %{attr} of the object is not yet defined. Can't "
 "generate DN."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2979
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3074
 msgid "LSldapObject : Without DN, the object could not be changed."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2982
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3077
 msgid ""
 "LSldapObject : The attribute %{attr_depend} depending on the attribute "
 "%{attr} doesn't exist."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2985
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3080
 msgid "LSldapObject : Error during deleting the object %{objectname}."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2989
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3084
 msgid ""
 "LSldapObject : Error during actions to be executed before renaming the objet."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2992
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3087
 msgid ""
 "LSldapObject : Error during actions to be executed after renaming the objet."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2996
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3091
 msgid ""
 "LSldapObject : Error during actions to be executed before deleting the objet."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:2999
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3094
 msgid ""
 "LSldapObject : Error during actions to be executed after deleting the objet."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3003
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3098
 msgid ""
 "LSldapObject : Error during the actions to be executed before creating the "
 "object."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3006
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3101
 msgid ""
 "LSldapObject : Error during the actions to be executed after creating the "
 "object. It was created anyway."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3010
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3105
 msgid ""
 "LSldapObject : The function %{func} to be executed before creating the "
 "object doesn't exist."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3013
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3108
 msgid ""
 "LSldapObject : Error executing the function %{func} to be execute after "
 "deleting the object."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3016
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3111
 msgid ""
 "LSldapObject : The function %{func} to be executed after deleting the object "
 "doesn't exist."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3019
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3114
 msgid ""
 "LSldapObject : Error executing the function %{func} to be execute after "
 "creating the object."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3023
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3118
 msgid ""
 "LSldapObject : %{func} function, to be executed on object event %{event}, "
 "doesn't exist."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3026
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3121
 msgid ""
 "LSldapObject : Error during the execution of %{func} function on object "
 "event %{event}."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3030
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3125
 msgid ""
 "LSldapObject : %{meth} method, to be executed on object event %{event}, "
 "doesn't exist."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3033
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3128
 msgid ""
 "LSldapObject : Error during execution of %{meth} method on object event "
 "%{event}."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3036
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3131
 msgid "LSldapObject : Error during generate LDAP filter for %{LSobject}."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3040
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3135
 msgid ""
 "LSldapObject : Error during execution of the custom action %{customAction} "
 "on %{objectname}."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3044
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3139
 msgid "LSldapObject : Fail to retrieve container DN."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3047
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3142
 msgid ""
 "LSldapObject : The function %{func} to generate container DN is not callable."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3050
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3145
 msgid "LSldapObject : Error during generating container DN : %{error}"
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3053
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3148
 msgid ""
 "LSldapObject : An LDAP object with the same DN as generated for this new one "
 "already exists. Please verify your configuration."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3058
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldapObject.php:3153
 msgid ""
 "LSrelation : Some parameters are missing in the call of methods to handle "
 "standard relations (Method : %{meth})."
@@ -1182,32 +1192,36 @@ msgid ""
 "(begining by '/' caracter)."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldap.php:543
-msgid "LSldap : Error during the LDAP server connection (%{msg})."
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldap.php:581
+msgid "LSldap: Error during the LDAP server connection (%{msg})."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldap.php:546
-msgid "LSldap : Error during the LDAP search (%{msg})."
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldap.php:584
+msgid "LSldap: Error during the LDAP search (%{msg})."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldap.php:549
-msgid "LSldap : Object type unknown."
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldap.php:587
+msgid "LSldap: Object type unknown."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldap.php:552
-msgid "LSldap : Error while fetching the LDAP entry."
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldap.php:590
+msgid "LSldap: Error while fetching the LDAP entry."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldap.php:555
-msgid "LSldap : Error while changing the LDAP entry (DN : %{dn})."
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldap.php:593
+msgid "LSldap: Error while changing the LDAP entry (DN : %{dn})."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldap.php:558
-msgid "LSldap : Error while deleting empty attributes."
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldap.php:596
+msgid "LSldap: Error while deleting empty attributes."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldap.php:561
-msgid "LSldap : Error while changing the DN of the object."
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldap.php:599
+msgid "LSldap: Error while changing the DN of the object."
+msgstr ""
+
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSldap.php:602
+msgid "LSldap: LDAP server base DN not configured."
 msgstr ""
 
 #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSrelation.php:331
@@ -1240,12 +1254,12 @@ msgid "Warning"
 msgstr ""
 
 #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSrelation.php:644
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:243
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:248
 #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_select_object.php:69
 #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_select_object.php:85
 #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearchEntry.php:190
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1009
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1153
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1016
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1160
 msgid "Delete"
 msgstr ""
 
@@ -1255,8 +1269,8 @@ msgid "No object."
 msgstr ""
 
 #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSrelation.php:712
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:442
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:938
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:449
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:945
 msgid "New"
 msgstr ""
 
@@ -1409,72 +1423,72 @@ msgid ""
 "LSAUTH_CAS_SERVER_SSL_CACERT or LSAUTH_CAS_SERVER_NO_SSL_VALIDATION"
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:121
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:126
 msgid "Add a field to add another values."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:122
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:127
 msgid "Delete this field."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:224
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:607
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:229
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:614
 msgid "Do you really want to execute custom action %{title} on this search ?"
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:230
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1369
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:235
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1376
 msgid ""
 "Do you really want to execute custom action %{customAction} on "
 "%{objectname} ?"
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:241
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:246
 msgid "Do you really want to delete \"%{name}\"?"
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:242
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:247
 msgid "Caution"
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:296
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:301
 msgid "%{label} attribute data is not valid."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:379
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:384
 msgid "Mandatory field"
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:855
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:873
 msgid "LSform : Error during the recovery of the values of the form."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:858
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:876
 msgid ""
 "LSform : Error durring the recovery of the value of the field '%{element}'."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:865
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:883
 msgid "LSform : The field %{element} doesn't exist."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:868
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:886
 msgid "LSfom : Field type unknow (%{type})."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:871
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:889
 msgid "LSform : Error during the creation of the element '%{element}'."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:874
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:892
 msgid "LSform : The data entry form %{name} doesn't exist."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:877
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:895
 msgid "LSform : The data entry form %{name} is not correctly configured."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:880
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSform.php:898
 msgid ""
 "LSform : The element %{name}, listed as displayed in data entry form "
 "configuration, doesn't exist."
@@ -1511,27 +1525,27 @@ msgstr ""
 msgid "Display advanced search and selection panel."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSurl.php:105
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSurl.php:108
 msgid "Fail to determine the requested URL."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSurl.php:109
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSurl.php:112
 msgid "No URL patterns configured !"
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSurl.php:210
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSurl.php:216
 msgid "Fail to determine the requested URL (loop detected)."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSurl.php:231
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSurl.php:238
 msgid "The requested page was not found."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSurl.php:249
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSurl.php:263
 msgid "This request could not be handled."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSurl.php:266
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSurl.php:282
 msgid "This request could not be processed correctly."
 msgstr ""
 
@@ -1540,7 +1554,11 @@ msgstr ""
 msgid "Invalid value"
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauthMethod_HTTP.php:136
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauthMethod_HTTP.php:103
+msgid "LdapSaisie - Authentication required"
+msgstr ""
+
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauthMethod_HTTP.php:150
 msgid "LSauthMethod_HTTP : the %{var} environnement variable is missing."
 msgstr ""
 
@@ -1557,8 +1575,8 @@ msgid "Display RSS stack."
 msgstr ""
 
 #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSattr_ldap_password.php:100
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:567
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1319
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:574
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1326
 msgid "undefined"
 msgstr ""
 
@@ -1574,34 +1592,38 @@ msgid ""
 "password will be stored in clear text."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauth.php:282
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauth.php:308
 msgid "LSauth : Login or password incorrect."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauth.php:285
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauth.php:311
 msgid "LSauth : Impossible to identify you : Duplication of identities."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauth.php:288
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauth.php:314
 msgid "LSauth : Could not load type of identifiable objects %{type}."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauth.php:291
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauth.php:317
 msgid "LSauth : Can't load authentication method %{method}."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauth.php:294
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauth.php:320
 msgid "LSauth : Failed to build the authentication provider %{method}."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauth.php:297
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauth.php:323
 msgid "LSauth : Not correctly initialized."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauth.php:300
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauth.php:326
 msgid "LSauth : Failed to get authentication informations from provider."
 msgstr ""
 
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSauth.php:329
+msgid "LSauth : Method %{method} configured doesn't support API mode."
+msgstr ""
+
 #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_supannEtuInscription.php:41
 msgid "Organism"
 msgstr ""
@@ -1647,88 +1669,88 @@ msgstr ""
 msgid "Pedagogical element"
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1143
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1200
 msgid "Actions"
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1146
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1203
 #: templates/default/global_search.tpl:16
 msgid "This search didn't get any result."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1711
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1842
 msgid "LSsearch : Invalid filter : %{filter}."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1714
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1845
 msgid "LSsearch : Invalid basedn : %{basedn}."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1717
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1848
 msgid "LSsearch : Invalid value for %{param} parameter."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1720
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1851
 msgid ""
 "LSsearch : Invalid size limit. Must be an integer greater or equal to 0."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1723
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1854
 msgid "LSsearch : Invalid parameter %{attr}. Must be an boolean."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1726
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1857
 msgid ""
 "LSsearch : Invalid parameter attributes. Must be an string or an array of "
 "strings."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1729
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1860
 msgid "LSsearch : Can't build attributes list for make filter."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1732
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1863
 msgid ""
 "LSsearch : Error building filter with attribute '%{attr}' and pattern "
 "'%{pattern}'"
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1735
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1866
 msgid "LSsearch : Error combining filters."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1738
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1869
 msgid "LSsearch : Invalid pattern."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1741
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1872
 msgid "LSsearch : Invalid attribute %{attr} in parameters."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1744
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1875
 msgid "LSsearch : Error during the search."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1747
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1878
 msgid "LSsearch : Error sorting the search."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1750
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1881
 msgid ""
 "LSsearch : The function of the custum information %{name} is not callable."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1753
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1884
 msgid ""
 "LSsearch : Invalid predefinedFilter for LSobject type %{type} : %{label} "
 "(filter : %{filter})."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1756
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1887
 msgid "LSsearch : Error during execution of the custom action %{customAction}."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1759
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearch.php:1890
 msgid "LSsearch : Invalid search pattern."
 msgstr ""
 
@@ -1829,8 +1851,12 @@ msgid ""
 "data."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_jsonCompositeAttribute.php:248
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_jsonCompositeAttribute.php:261
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_jsonCompositeAttribute.php:260
+msgid "Fail to decode JSON value #%{idx}."
+msgstr ""
+
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_jsonCompositeAttribute.php:392
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSformElement_jsonCompositeAttribute.php:415
 msgid "Invalid value \"%{value}\" for component %{component}."
 msgstr ""
 
@@ -1889,23 +1915,23 @@ msgstr ""
 msgid "Stop"
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSerror.php:154
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSerror.php:158
 msgid "Unknown error"
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSerror.php:209
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSerror.php:213
 msgid "Unknown error : %{error}"
 msgstr ""
 
 #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearchEntry.php:166
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1145
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1238
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1380
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1152
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1245
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1387
 msgid "View"
 msgstr ""
 
 #: /home/brenard/dev/ldapsaisie_clean3/src/includes/class/class.LSsearchEntry.php:182
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1001
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1008
 msgid "Copy"
 msgstr ""
 
@@ -1931,68 +1957,72 @@ msgstr ""
 msgid "You must provide pattern for global search."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:448
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:796
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:455
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:803
 msgid "Import"
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:460
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:467
 msgid "Reset"
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:498
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:505
 #: templates/default/select.tpl:28 templates/default/global_search.tpl:6
 msgid "Search"
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:499
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:506
 #: templates/default/select.tpl:31
 msgid "Approximative search"
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:500
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:507
 #: templates/default/select.tpl:32
 msgid "Recursive search"
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:586
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:593
 msgid ""
 "The custom action %{title} have been successfully execute on this search."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:897
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:904
 msgid "Data entry form"
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:903
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:910
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1626
 msgid "Object has been added."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1040
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1047
 msgid "My account"
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1103
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1110
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1716
 msgid "The object has been partially modified."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1106
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1113
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1719
 msgid "The object has been modified successfully."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1221
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1228
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1760
 msgid "%{objectname} has been successfully deleted."
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1230
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1237
 msgid "Deleting : %{objectname}"
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1231
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1238
 msgid "Do you really want to delete %{displayName} ?"
 msgstr ""
 
-#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1341
+#: /home/brenard/dev/ldapsaisie_clean3/src/includes/routes.php:1348
 msgid ""
 "The custom action %{customAction} have been successfully execute on "
 "%{objectname}."