diff --git a/trunk/conf/LSobjects/config.LSobjects.LSeepeople.php b/trunk/conf/LSobjects/config.LSobjects.LSeepeople.php
index c3c72aeb..f5f6dc8f 100644
--- a/trunk/conf/LSobjects/config.LSobjects.LSeepeople.php
+++ b/trunk/conf/LSobjects/config.LSobjects.LSeepeople.php
@@ -257,7 +257,8 @@ $GLOBALS['LSobjects']['LSeepeople'] = array (
       'required' => 1,
       'check_data' => array (
         'email' => array(
-          'msg' => _("L'adresse e-mail entrée n'est pas valide.")
+          'msg' => _("L'adresse e-mail entrée n'est pas valide."),
+          'param' => array('checkDomain' => false)
         ),
       ),
       'rights' => array(
@@ -293,100 +294,6 @@ $GLOBALS['LSobjects']['LSeepeople'] = array (
         'Mlle' => 'Mlle'
       )
     ),
-    'maildrop' => array (
-      'label' => _('Mail indésirable'),
-      'ldap_type' => 'ascii',
-      'html_type' => 'text',
-      'multiple' => true,
-      'check_data' => array (
-        'email' => array(
-          'msg' => _("L'adresse e-mail entrée n'est pas valide.")
-        ),
-      ),
-      'rights' => array(
-        'self' => 'w',
-        'admin' => 'w'
-      ),
-      'view' => 1,
-      'form' => array (
-        'modify' => 1,
-      )
-    ),
-    'vacationActive' => array (
-      'label' => _('Réponse automatique'),
-      'ldap_type' => 'ascii',
-      'html_type' => 'select_list',
-      'default_value' => '',
-      'check_data' => array (
-        'email' => array(
-          'msg' => _("L'adresse e-mail entrée n'est pas valide.")
-        ),
-      ),
-      'rights' => array(
-        'self' => 'w',
-        'admin' => 'w',
-        'user' => 'r'
-      ),
-      'view' => 1,
-      'form' => array (
-        'modify' => 1,
-      ),
-      'possible_values' => array(
-        '' => 'Non',
-        '%{uid}@autoreponse.example.fr' => 'Oui'
-      )
-    ),
-    'vacationInfo' => array (
-      'label' => _('Message en reponse'),
-      'ldap_type' => 'ascii',
-      'html_type' => 'textarea',
-      'multiple' => true,
-      'rights' => array(
-        'self' => 'w',
-        'admin' => 'w'
-      ),
-      'view' => 1,
-      'form' => array (
-        'modify' => 1,
-      )
-    ),
-    'vacationForward' => array (
-      'label' => _('Transfert de mail'),
-      'ldap_type' => 'ascii',
-      'html_type' => 'text',
-      'check_data' => array (
-        'email' => array(
-          'msg' => _("L'adresse e-mail entrée n'est pas valide.")
-        ),
-      ),
-      'rights' => array(
-        'self' => 'w',
-        'user' => 'r',
-        'admin' => 'w'
-      ),
-      'view' => 1,
-      'form' => array (
-        'modify' => 1,
-      )
-    ),
-    'mailQuota' => array (
-      'label' => _('Quota boite mail'),
-      'ldap_type' => 'ascii',
-      'html_type' => 'text',
-      'check_data' => array (
-        'numeric' => array(
-          'msg' => _("Le quota de l'adresse mail entrée n'est pas valide.")
-        ),
-      ),
-      'rights' => array(
-        'self' => 'r',
-        'admin' => 'w'
-      ),
-      'view' => 1,
-      'form' => array (
-        'modify' => 1,
-      )
-    ),
     'description' => array (
       'label' => _('Description'),
       'ldap_type' => 'ascii',
@@ -423,7 +330,21 @@ $GLOBALS['LSobjects']['LSeepeople'] = array (
       ),
       'form' => array (
         'modify' => 1,
-        'create' => 1
+        'create' => 1,
+        'lostPassword' => 1
+      )
+    ),
+    'lsRecoveryHash' => array (
+      'label' => _('Hash de recouvrement du mot de passe'),
+      'ldap_type' => 'ascii',
+      'html_type' => 'text',
+      'required' => 0,
+      'form' => array (
+        'lostPassword' => 1
+      ),
+      'rights' => array(
+        'self' => 'w',
+        'admin' => 'w'
       )
     ),
     'sambaLMPassword' => array (
diff --git a/trunk/conf/config.error_code.php b/trunk/conf/config.error_code.php
index eb37f6f2..968a84f6 100644
--- a/trunk/conf/config.error_code.php
+++ b/trunk/conf/config.error_code.php
@@ -43,11 +43,11 @@ $GLOBALS['LSerror_code'] = array (
     'level' => 'c'
   ),
   4 => array (
-    'msg' => _("LSldap : Erreur durant la récupération de l'entrée Ldap."),
+    'msg' => _("LSldap : Erreur durant la récupération de l'entrée Ldap."),
     'level' => 'c'
   ),
   5 => array (
-    'msg' => _("LSldap : Erreur durant la mise à jour de l'entrée Ldap (DN : %{dn})."),
+    'msg' => _("LSldap : Erreur durant la mise à jour de l'entrée Ldap (DN : %{dn})."),
     'level' => 'c'
   ),
   6 => array (
@@ -73,43 +73,43 @@ $GLOBALS['LSerror_code'] = array (
     'level' => 'c'
   ),
   25 => array (
-    'msg' => _("LSldapObject : Des données de configuration sont manquant pour la validation de l'attribut %{attr} de l'objet %{obj}."),
+    'msg' => _("LSldapObject : Des données de configuration sont manquant pour la validation de l'attribut %{attr} de l'objet %{obj}."),
     'level' => 'c'
   ),
   26 => array (
-    'msg' => _("LSldapObject : Erreur de configuration : L'objet %{obj} ne possède pas d'attribut %{attr}."),
+    'msg' => _("LSldapObject : Erreur de configuration : L'objet %{obj} ne possède pas d'attribut %{attr}."),
     'level' => 'c'
   ),
   27 => array (
-    'msg' => _("LSldapObject : La fonction %{func} devant être executée avant l'enregistrement n'existe pas."),
+    'msg' => _("LSldapObject : La fonction %{func} devant être executée avant l'enregistrement n'existe pas."),
     'level' => 'c'
   ),
   28 => array (
-    'msg' => _("LSldapObject : L'execution de la fonction %{func} devant être executée avant l'enregistrement a échouée."),
+    'msg' => _("LSldapObject : L'execution de la fonction %{func} devant être executée avant l'enregistrement a échouée."),
     'level' => 'c'
   ),
   29 => array (
-    'msg' => _("LSldapObject : La fonction %{func} devant être executée après l'enregistrement n'existe pas."),
+    'msg' => _("LSldapObject : La fonction %{func} devant être executée après l'enregistrement n'existe pas."),
     'level' => 'c'
   ),
   30 => array (
-    'msg' => _("LSldapObject : L'execution de la fonction %{func} devant être executée après l'enregistrement a échouée."),
+    'msg' => _("LSldapObject : L'execution de la fonction %{func} devant être executée après l'enregistrement a échouée."),
     'level' => 'c'
   ),
   31 => array (
-    'msg' => _("LSldapObject : Il manque des informations de configuration du type d'objet %{obj} pour la création du nouveau DN."),
+    'msg' => _("LSldapObject : Il manque des informations de configuration du type d'objet %{obj} pour la création du nouveau DN."),
     'level' => 'c'
   ),
   32 => array (
-    'msg' => _("LSldapObject : L'attribut %{attr} de l'objet n'est pas encore définis. Il est impossible de generer un nouveau DN."),
+    'msg' => _("LSldapObject : L'attribut %{attr} de l'objet n'est pas encore définis. Il est impossible de generer un nouveau DN."),
     'level' => 'c'
   ),
   33 => array (
-    'msg' => _("LSldapObject : Sans DN, l'objet n'a put être modifié."),
+    'msg' => _("LSldapObject : Sans DN, l'objet n'a put être modifié."),
     'level' => 'c'
   ),
   34 => array (
-    'msg' => _("LSldapObject : L'attribut %{attr_depend} dépendant de l'attribut %{attr} n'existe pas."),
+    'msg' => _("LSldapObject : L'attribut %{attr_depend} dépendant de l'attribut %{attr} n'existe pas."),
     'level' => 'w'
   ),
   35 => array (
@@ -127,11 +127,11 @@ $GLOBALS['LSerror_code'] = array (
     'level' => 'c'
   ),
   43 => array (
-    'msg' => _("LSattribute : La règle %{rule} pour valider l'attribut %{attr} est inconnue."),
+    'msg' => _("LSattribute : La règle %{rule} pour valider l'attribut %{attr} est inconnue."),
     'level' => 'c'
   ),
   44 => array (
-    'msg' => _("LSattribute : Les données de configuration pour vérifié l'attribut %{attr} sont incorrects."),
+    'msg' => _("LSattribute : Les données de configuration pour vérifié l'attribut %{attr} sont incorrects."),
     'level' => 'c'
   ),
   45 => array (
@@ -139,43 +139,43 @@ $GLOBALS['LSerror_code'] = array (
     'level' => 'c'
   ),
   46 => array (
-    'msg' => _("LSattribute : La valeur de l'attribut %{attr} ne peut pas être générée."),
+    'msg' => _("LSattribute : La valeur de l'attribut %{attr} ne peut pas être générée."),
     'level' => 'c'
   ),
   47 => array (
-    'msg' => _("LSattribute : La valeur de l'attribut %{attr} n'a pas put être générée."),
+    'msg' => _("LSattribute : La valeur de l'attribut %{attr} n'a pas put être générée."),
     'level' => 'c'
   ),
   48 => array (
-    'msg' => _("LSattribute : La génération de l'attribut %{attr} n'a pas retourné une valeur correcte."),
+    'msg' => _("LSattribute : La génération de l'attribut %{attr} n'a pas retourné une valeur correcte."),
     'level' => 'c'
   ),
 
   // LSattr_html
   101 => array (
-    'msg' => _("LSattr_html : La fonction addToForm() du type html de l'attribut %{attr} n'est pas définie."),
+    'msg' => _("LSattr_html : La fonction addToForm() du type html de l'attribut %{attr} n'est pas définie."),
     'level' => 'c'
   ),
   102 => array (
-    'msg' => _("LSattr_html_select_list : Des données de configuration sont manquante pour la génération de la liste deroulante de l'attribut %{attr}."),
+    'msg' => _("LSattr_html_select_list : Des données de configuration sont manquante pour la génération de la liste deroulante de l'attribut %{attr}."),
     'level' => 'c'
   ),
   103 => array (
-    'msg' => _("LSattr_html_%{type} : Les données multiples ne sont pas gérés pour ce type d'attribut."),
+    'msg' => _("LSattr_html_%{type} : Les données multiples ne sont pas gérés pour ce type d'attribut."),
     'level' => 'c'
   ),
 
   // LSform
   201 => array(
-    'msg' => _("LSform : Erreur durant la recupération des valeurs du formulaire."),
+    'msg' => _("LSform : Erreur durant la recupération des valeurs du formulaire."),
     'level' => 'c'
   ),
   202 => array(
-    'msg' => _("LSform : Erreur durant la récupération de la valeur du formulaire du champ '%{element}'."),
+    'msg' => _("LSform : Erreur durant la récupération de la valeur du formulaire du champ '%{element}'."),
     'level' => 'c'
   ),
   203 => array(
-    'msg' => _("LSform : Les données du champ %{element} ne sont pas valides."),
+    'msg' => _("LSform : Les données du champ %{element} ne sont pas valides."),
     'level' => 'c'
   ),
   204 => array(
@@ -187,16 +187,16 @@ $GLOBALS['LSerror_code'] = array (
     'level' => 'c'
   ),
   206 => array(
-    'msg' => _("LSform : Erreur durant la création de l'élement '%{element}'."),
+    'msg' => _("LSform : Erreur durant la création de l'élement '%{element}'."),
     'level' => 'c'
   ),
   207 => array(
-    'msg' => _("LSform : Aucune valeur de rentrée pour le champs '%{element}'."),
+    'msg' => _("LSform : Aucune valeur de rentrée pour le champs '%{element}'."),
     'level' => 'c'
   ),
 
   301 => array(
-    'msg' => _("LSformRule : Aucune regex n'a été fournis pour la validation des données."),
+    'msg' => _("LSformRule : Aucune regex n'a été fournis pour la validation des données."),
     'level' => 'w'
   ),
   
@@ -208,15 +208,15 @@ $GLOBALS['LSerror_code'] = array (
 
   // LSsession
   1001 => array (
-    'msg' => _("LSsession : La constante %{const} n'est pas définie."),
+    'msg' => _("LSsession : La constante %{const} n'est pas définie."),
     'level' => 'c'
   ),
   1002 => array (
-    'msg' => _("LSsession : Le support %{addon} n'est pas assuré. Vérifier la compatibilité du système et la configuration de l'addon"),
+    'msg' => _("LSsession : Le support %{addon} n'est pas assuré. Vérifier la compatibilité du système et la configuration de l'addon"),
     'level' => 'c'
   ),
   1003 => array (
-    'msg' => _("LSsession : Données de configuration du serveur LDAP invalide. Impossible d'établir une connexion."),
+    'msg' => _("LSsession : Données de configuration du serveur LDAP invalide. Impossible d'établir une connexion."),
     'level' => 'c'
   ),
   1004 => array (
@@ -232,7 +232,7 @@ $GLOBALS['LSerror_code'] = array (
     'level' => 'c'
   ),
   1007 => array (
-    'msg' => _("LSsession : Impossible de vous identifier : Duplication d'authentité."),
+    'msg' => _("LSsession : Impossible de vous identifier : Duplication d'authentité."),
     'level' => 'c'
   ),
   1008 => array (
@@ -248,7 +248,7 @@ $GLOBALS['LSerror_code'] = array (
     'level' => 'c'
   ),
   1011 => array (
-    'msg' => _("LSsession : Vous n'êtes pas authorisé à effectuer cette action."),
+    'msg' => _("LSsession : Vous n'êtes pas authorisé à effectuer cette action."),
     'level' => 'c'
   ),
   1012 => array (
@@ -260,7 +260,7 @@ $GLOBALS['LSerror_code'] = array (
     'level' => 'c'
   ),
   1014 => array (
-    'msg' => _("LSrelations : La fonction de mise à jour pour la relation %{relation} est inconnu."),
+    'msg' => _("LSrelations : La fonction de mise à jour pour la relation %{relation} est inconnu."),
     'level' => 'c'
   ),
   1015 => array (
@@ -274,6 +274,18 @@ $GLOBALS['LSerror_code'] = array (
   1017 => array (
     'msg' => _("LSsession : Impossible de créer correctement la liste des niveaux. Vérifier la configuration."),
     'level' => 'c'
+  ),
+  1018 => array (
+    'msg' => _("LSsession : La récupération de mot de passe est désactivée pour ce serveur LDAP."),
+    'level' => 'c'
+  ),
+  1019 => array (
+    'msg' => _("LSsession : Des informations sont manquantes pour la récupération de votre mot de passe. Contactez l'administrateur du système."),
+    'level' => 'c'
+  ),
+  1020 => array (
+    'msg' => _("LSsession : Erreur durant la récupération de votre mot de passe. Contactez l'administrateur du système."),
+    'level' => 'c'
   )
 );
 ?>
diff --git a/trunk/conf/config.inc.php b/trunk/conf/config.inc.php
index 546b8340..db231479 100644
--- a/trunk/conf/config.inc.php
+++ b/trunk/conf/config.inc.php
@@ -34,7 +34,7 @@ $GLOBALS['LSconfig'] = array(
             'port'     => 389,
             'version'  => 3,
             'starttls' => false,
-        'binddn'   => 'uid=eeggs,ou=people,o=ls',
+        'binddn'   => 'uid=ldapsaisie,ou=sysaccounts,o=ls',
         'bindpw'   => 'toto',
         'basedn'   => 'o=ls',
         'options'  => array(),
@@ -55,6 +55,21 @@ $GLOBALS['LSconfig'] = array(
         'cacheLSrights' => false,
       'authobject' => 'LSeepeople',
       'authobject_pwdattr' => 'userPassword',
+      'recoverPassword' => array(
+        'mailAttr' => 'mail',
+        'passwordAttr' => 'userPassword',
+        'recoveryHashAttr' => 'lsRecoveryHash',
+        'recoveryEmailSender' => 'noreply-recover@lsexample.net',
+        'recoveryHashMail' => array(
+          'subject' => 'LSexample : Récupération de votre mot de passe.',
+          'msg' => "Pour poursuivre le processus de récupération de votre mot de passe,\nmerci de cliquer de vous rendre à l'adresse suivante :\n%{url}"
+        ),
+        'newPasswordMail' => array(
+          'subject' => 'LSexample : Votre nouveau mot de passe.',
+          'msg' => "Votre nouveau mot de passe : %{mdp}"
+        )
+      ),
+      'emailSender' => 'noreply@lsexample.net',
       'LSobjects' => array (
         'LSeepeople',
         'LSeegroup',
diff --git a/trunk/includes/class/class.LSform.php b/trunk/includes/class/class.LSform.php
index ab5d91aa..ec2fac2b 100644
--- a/trunk/includes/class/class.LSform.php
+++ b/trunk/includes/class/class.LSform.php
@@ -266,6 +266,35 @@ class LSform {
     return;
   }
 
+  /**
+   * Défini arbitrairement des données en POST
+   * 
+   * @author Benjamin Renard <brenard@easter-eggs.com>
+   * 
+   * @param[in] $data array('attr' => array(values)) Tableau des données du formulaire
+   * @param[in] $consideredAsSubmit Définie si on force le formualaire comme envoyer
+   * 
+   * @retval boolean true si les données ont été définies, false sinon
+   */
+  function setPostData($data,$consideredAsSubmit=false) {
+    if (is_array($data)) {
+      foreach($data as $key => $values) {
+        if (!is_array($values)) {
+          $values = array($values);
+        }
+        $_POST[$key] = $values;
+      }
+      
+      if ($consideredAsSubmit) {
+        $_POST['validate']='LSform';
+        $_POST['idForm']=$this -> idForm;
+      }
+      
+      return true;
+    }
+    return;
+  }
+
   /**
    * Récupère les valeurs postées dans le formulaire
    *
diff --git a/trunk/includes/class/class.LSformElement_password.php b/trunk/includes/class/class.LSformElement_password.php
index 971611bb..b6661af8 100644
--- a/trunk/includes/class/class.LSformElement_password.php
+++ b/trunk/includes/class/class.LSformElement_password.php
@@ -96,7 +96,7 @@ class LSformElement_password extends LSformElement {
     }
     else {
       if (empty($this -> values)) {
-        $return['html'] = _('Aucunes valeur definie');
+        $return['html'] = _('Aucune valeur definie');
       }
       else {
         $return['html'] = "********";
@@ -107,25 +107,7 @@ class LSformElement_password extends LSformElement {
   }
   
   function generatePassword() {
-    if (isset($this -> params['html_options']['chars'])) {
-      $chars=$this -> params['html_options']['chars'];
-    }
-    else {
-      $chars='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-';
-    }
-    $nbChars=strlen($chars);
-    
-    if (isset($this -> params['html_options']['lenght'])) {
-      $lenght=$this -> params['html_options']['lenght'];
-    }
-    else {
-      $lenght=8;
-    }
-    $retVal='';
-    for($i=0;$i<$lenght;$i++){
-      $retVal.=$chars[rand(0,$nbChars-1)];
-    }
-    return $retVal;
+    return generatePassword($this -> params['html_options']['chars'],$this -> params['html_options']['lenght']);
   }
 }
   
diff --git a/trunk/includes/class/class.LSformElement_text.php b/trunk/includes/class/class.LSformElement_text.php
index 0032e7fb..ca362ddb 100644
--- a/trunk/includes/class/class.LSformElement_text.php
+++ b/trunk/includes/class/class.LSformElement_text.php
@@ -59,7 +59,7 @@ class LSformElement_text extends LSformElement {
     else {
       $return['html'] = "<ul class='LSform'>\n";
       if (empty($this -> values)) {
-        $return['html'] .= "<li>"._('Aucunes valeur definie')."</li>\n";
+        $return['html'] .= "<li>"._('Aucune valeur definie')."</li>\n";
       }
       else {
         foreach ($this -> values as $value) {
diff --git a/trunk/includes/class/class.LSformElement_textarea.php b/trunk/includes/class/class.LSformElement_textarea.php
index 7ac64f19..4034370b 100644
--- a/trunk/includes/class/class.LSformElement_textarea.php
+++ b/trunk/includes/class/class.LSformElement_textarea.php
@@ -57,7 +57,7 @@ class LSformElement_textarea extends LSformElement {
     }
     else {
       if (empty($this -> values)) {
-        $return['html'].="<li class='LSform'>"._('Aucunes valeur definie')."</li>\n";
+        $return['html'].="<li class='LSform'>"._('Aucune valeur definie')."</li>\n";
       }
       else {
         foreach ($this -> values as $value) {
diff --git a/trunk/includes/class/class.LSformRule_email.php b/trunk/includes/class/class.LSformRule_email.php
index cf2b1040..40a292c4 100644
--- a/trunk/includes/class/class.LSformRule_email.php
+++ b/trunk/includes/class/class.LSformRule_email.php
@@ -38,20 +38,7 @@ class LSformRule_email extends LSformRule {
    * @return boolean true si la valeur est valide, false sinon
    */
   function validate($value,$option=array(),$formElement) {
-   $regex = '/^((\"[^\"\f\n\r\t\v\b]+\")|([\w\!\#\$\%\&\'\*\+\-\~\/\^\`\|\{\}]+(\.[\w\!\#\$\%\&\'\*\+\-\~\/\^\`\|\{\}]+)*))@((\[(((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9])))\])|(((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9])))|((([A-Za-z0-9\-])+\.)+[A-Za-z\-]+))$/';
-
-    if (!preg_match($regex, $value)) {
-      return false;
-    }
-
-    if ($option['params']['checkDomain'] && function_exists('checkdnsrr')) {
-      $tokens = explode('@', $email);
-      if (!(checkdnsrr($tokens[1], 'MX') || checkdnsrr($tokens[1], 'A'))) {
-      return false;
-      }
-    }
-
-    return true;
+    return checkEmail($value,$option['param']['checkDomain']);
   }
 
 }
diff --git a/trunk/includes/class/class.LSsession.php b/trunk/includes/class/class.LSsession.php
index 6b4f30fc..adfcc3ed 100644
--- a/trunk/includes/class/class.LSsession.php
+++ b/trunk/includes/class/class.LSsession.php
@@ -25,7 +25,7 @@ define('LS_DEFAULT_CONF_DIR','conf');
 /**
  * Gestion des sessions
  *
- * Cette classe gère les sessions d'utilisateurs.
+ * Cette classe gère les sessions d'utilisateurs.
  *
  * @author Benjamin Renard <brenard@easter-eggs.com>
  */
@@ -67,11 +67,11 @@ class LSsession {
  /**
   * Chargement de la configuration
   *
-  * Chargement des fichiers de configuration et création de l'objet Smarty.
+  * Chargement des fichiers de configuration et création de l'objet Smarty.
   *
   * @author Benjamin Renard <brenard@easter-eggs.com>
   *
-  * @retval true si tout c'est bien passé, false sinon
+  * @retval true si tout c'est bien passé, false sinon
   */
   function loadConfig() {
     if (loadDir($this -> confDir, '^config\..*\.php$')) {
@@ -93,11 +93,11 @@ class LSsession {
  /**
   * Initialisation de la gestion des erreurs
   *
-  * Création de l'objet LSerror
+  * Création de l'objet LSerror
   *
   * @author Benjamin Renard <brenard@easter-eggs.com
   *
-  * @retval boolean true si l'initialisation a réussi, false sinon.
+  * @retval boolean true si l'initialisation a réussi, false sinon.
   */
   function startLSerror() {
     if(!$this -> loadLSclass('LSerror'))
@@ -109,12 +109,12 @@ class LSsession {
  /**
   * Chargement d'une classe d'LdapSaisie
   *
-  * @param[in] $class Nom de la classe à charger (Exemple : LSeepeople)
-  * @param[in] $type (Optionnel) Type de classe à charger (Exemple : LSobjects)
+  * @param[in] $class Nom de la classe à charger (Exemple : LSeepeople)
+  * @param[in] $type (Optionnel) Type de classe à charger (Exemple : LSobjects)
   *
   * @author Benjamin Renard <brenard@easter-eggs.com
   * 
-  * @retval boolean true si le chargement a réussi, false sinon.
+  * @retval boolean true si le chargement a réussi, false sinon.
   */
   function loadLSclass($class,$type='') {
     if (class_exists($class))
@@ -127,9 +127,9 @@ class LSsession {
  /**
   * Chargement d'un object LdapSaisie
   *
-  * @param[in] $object Nom de l'objet à charger
+  * @param[in] $object Nom de l'objet à charger
   *
-  * @retval boolean true si le chargement a réussi, false sinon.
+  * @retval boolean true si le chargement a réussi, false sinon.
   */
   function loadLSobject($object) {
     $this -> loadLSclass('LSldapObject');
@@ -148,7 +148,7 @@ class LSsession {
   * Chargement des LSobjects contenue dans la variable
   * $this -> ldapServer['LSobjects']
   *
-  * @retval boolean true si le chargement a réussi, false sinon.
+  * @retval boolean true si le chargement a réussi, false sinon.
   */
   function loadLSobjects() {
 
@@ -170,11 +170,11 @@ class LSsession {
  /**
   * Chargement d'un addons d'LdapSaisie
   *
-  * @param[in] $addon Nom de l'addon à charger (Exemple : samba)
+  * @param[in] $addon Nom de l'addon à charger (Exemple : samba)
   *
   * @author Benjamin Renard <brenard@easter-eggs.com
   * 
-  * @retval boolean true si le chargement a réussi, false sinon.
+  * @retval boolean true si le chargement a réussi, false sinon.
   */
   function loadLSaddon($addon) {
     return require_once LS_ADDONS_DIR .'LSaddons.'.$addon.'.php';
@@ -186,7 +186,7 @@ class LSsession {
   * Chargement des LSaddons contenue dans la variable
   * $GLOBALS['LSaddons']['loads']
   *
-  * @retval boolean true si le chargement a réussi, false sinon.
+  * @retval boolean true si le chargement a réussi, false sinon.
   */
   function loadLSaddons() {
     if(!is_array($GLOBALS['LSaddons']['loads'])) {
@@ -207,19 +207,19 @@ class LSsession {
   * Initialisation de la session LdapSaisie
   *
   * Initialisation d'une LSsession :
-  * - Authentification et activation du mécanisme de session de LdapSaisie
-  * - ou Chargement des paramètres de la session à partir de la variable 
+  * - Authentification et activation du mécanisme de session de LdapSaisie
+  * - ou Chargement des paramètres de la session à partir de la variable 
   *   $_SESSION['LSsession'].
   * - ou Destruction de la session en cas de $_GET['LSsession_logout'].
   *
-  * @retval boolean True si l'initialisation à réussi (utilisateur authentifié), false sinon.
+  * @retval boolean True si l'initialisation à réussi (utilisateur authentifié), false sinon.
   */
   function startLSsession() {
       $this -> loadLSaddons();
       session_start();
 
-      // Déconnexion
-      if (isset($_GET['LSsession_logout'])) {
+      // Déconnexion
+      if (isset($_GET['LSsession_logout'])||isset($_GET['LSsession_recoverPassword'])) {
         session_destroy();
         
         if (is_array($_SESSION['LSsession']['tmp_file'])) {
@@ -229,7 +229,11 @@ class LSsession {
         unset($_SESSION['LSsession']);
       }
       
-
+      // Récupération de mot de passe
+      if (isset($_GET['recoveryHash'])) {
+        $_POST['LSsession_user'] = 'a determiner plus tard';
+      }
+      
       if(isset($_SESSION['LSsession'])) {
         // Session existante
         $this -> confDir      = $_SESSION['LSsession']['confDir'];
@@ -272,6 +276,7 @@ class LSsession {
       }
       else {
         // Session inexistante
+        $recoveryPasswordInfos=array();
 
         if (isset($_POST['LSsession_user'])) {
           if (isset($_POST['LSsession_ldapserver'])) {
@@ -297,32 +302,178 @@ class LSsession {
 
             if ( $this -> loadLSobject($this -> ldapServer['authobject']) ) {
               $authobject = new $this -> ldapServer['authobject']();
-              $result = $authobject -> searchObject($_POST['LSsession_user'],$this -> topDn);
-              $nbresult=count($result);
+              $find=true;
+              if (isset($_GET['recoveryHash'])) {
+                $filter=$this -> ldapServer['recoverPassword']['recoveryHashAttr']."=".$_GET['recoveryHash'];
+                $result = $authobject -> listObjects($filter,$this -> topDn);
+                $nbresult=count($result);
+                if ($nbresult==1) {
+                  $_POST['LSsession_user'] = $result[0] -> getValue('rdn');
+                  $find=false;
+                }
+              }
+              if ($find) {
+                $result = $authobject -> searchObject($_POST['LSsession_user'],$this -> topDn);
+                $nbresult=count($result);
+              }
               if ($nbresult==0) {
                 // identifiant incorrect
                 debug('identifiant incorrect');
                 $GLOBALS['LSerror'] -> addErrorCode(1006);
               }
               else if ($nbresult>1) {
-                // duplication d'authentité
+                // duplication d'authentité
                 $GLOBALS['LSerror'] -> addErrorCode(1007);
               }
               else {
-                if ( $this -> checkUserPwd($result[0],$_POST['LSsession_pwd']) ) {
-                  // Authentification réussi
-                  $this -> LSuserObject = $result[0];
-                  $this -> dn = $result[0]->getValue('dn');
-                  $this -> rdn = $_POST['LSsession_user'];
-                  $this -> loadLSrights();
-                  $this -> loadLSaccess();
-                  $GLOBALS['Smarty'] -> assign('LSsession_username',$this -> LSuserObject -> getDisplayValue());
-                  $_SESSION['LSsession']=get_object_vars($this);
-                  return true;
+                if (isset($_GET['LSsession_recoverPassword'])) {
+                  debug('Recover : Id trouvé');
+                  if ($this -> ldapServer['recoverPassword']) {
+                    debug('Récupération active');
+                    $user=$result[0];
+                    $emailAddress = $user -> getValue($this -> ldapServer['recoverPassword']['mailAttr']);
+                    
+                    // Header des mails
+                    $headers="Content-Type: text/plain; charset=UTF-8; format=flowed";
+                    if ($this -> ldapServer['recoverPassword']['recoveryEmailSender']) {
+                      $headers.="\nFrom: ".$this -> ldapServer['recoverPassword']['recoveryEmailSender'];
+                    }
+                    else if($this -> ldapServer['emailSender']) {
+                      $headers.="\nFrom: ".$this -> ldapServer['emailSender'];
+                    }
+                    
+                    if (checkEmail($emailAddress)) {
+                      debug('Email : '.$emailAddress);
+                      $this -> dn = $user -> getDn();
+                      // 1ère étape : envoie du recoveryHash
+                      if (!isset($_GET['recoveryHash'])) {
+                        // Generer un hash
+                        $recovery_hash = md5($user -> getValue('rdn') . strval(time()) . strval(rand()));
+                        
+                        $lostPasswdForm = $user -> getForm('lostPassword');
+                        $lostPasswdForm -> setPostData(
+                          array(
+                            $this -> ldapServer['recoverPassword']['recoveryHashAttr'] => $recovery_hash
+                          )
+                          ,true
+                        );
+                        
+                        if($lostPasswdForm -> validate()) {
+                          if ($user -> updateData('lostPassword')) {
+                            // recoveryHash de l'utilisateur mis à jour
+                            if ($_SERVER['HTTPS']=='on') {
+                              $recovery_url='https://';
+                            }
+                            else {
+                              $recovery_url='http://';
+                            }
+                            $recovery_url .= $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'].'&recoveryHash='.$recovery_hash;
+
+                            if (
+                              mail(
+                                $emailAddress,
+                                $this -> ldapServer['recoverPassword']['recoveryHashMail']['subject'],
+                                getFData($this -> ldapServer['recoverPassword']['recoveryHashMail']['msg'],$recovery_url),
+                                $headers
+                              )
+                            ){
+                              // Mail a bien été envoyé
+                              $recoveryPasswordInfos['recoveryHashMail']=$emailAddress;
+                            }
+                            else {
+                              // Problème durant l'envoie du mail
+                              debug("Problème durant l'envoie du mail");
+                              $GLOBALS['LSerror'] -> addErrorCode(1020);
+                            }
+                          }
+                          else {
+                            // Erreur durant la mise à jour de l'objet
+                            debug("Erreur durant la mise à jour de l'objet");
+                            $GLOBALS['LSerror'] -> addErrorCode(1020);
+                          }
+                        }
+                        else {
+                          // Erreur durant la validation du formulaire de modification de perte de password
+                          debug("Erreur durant la validation du formulaire de modification de perte de password");
+                          $GLOBALS['LSerror'] -> addErrorCode(1020);
+                        }
+                      }
+                      // 2nd étape : génération du mot de passe + envoie par mail
+                      else {
+                        $attr=$user -> attrs[$this -> ldapServer['recoverPassword']['passwordAttr']];
+                        if ($attr instanceof LSattribute) {
+                          $mdp = generatePassword($attr -> config['html_options']['chars'],$attr -> config['html_options']['lenght']);
+                          debug('Nvx mpd : '.$mdp);
+                          $lostPasswdForm = $user -> getForm('lostPassword');
+                          $lostPasswdForm -> setPostData(
+                            array(
+                              $this -> ldapServer['recoverPassword']['recoveryHashAttr'] => array(''),
+                              $this -> ldapServer['recoverPassword']['passwordAttr'] => array($mdp)
+                            )
+                            ,true
+                          );
+                          if($lostPasswdForm -> validate()) {
+                            if ($user -> updateData('lostPassword')) {
+                              if (
+                                mail(
+                                  $emailAddress,
+                                  $this -> ldapServer['recoverPassword']['newPasswordMail']['subject'],
+                                  getFData($this -> ldapServer['recoverPassword']['newPasswordMail']['msg'],$mdp),
+                                  $headers
+                                )
+                              ){
+                                // Mail a bien été envoyé
+                                $recoveryPasswordInfos['newPasswordMail']=$emailAddress;
+                              }
+                              else {
+                                // Problème durant l'envoie du mail
+                                debug("Problème durant l'envoie du mail");
+                                $GLOBALS['LSerror'] -> addErrorCode(1020);
+                              }
+                            }
+                            else {
+                              // Erreur durant la mise à jour de l'objet
+                              debug("Erreur durant la mise à jour de l'objet");
+                              $GLOBALS['LSerror'] -> addErrorCode(1020);
+                            }
+                          }
+                          else {
+                            // Erreur durant la validation du formulaire de modification de perte de password
+                            debug("Erreur durant la validation du formulaire de modification de perte de password");
+                            $GLOBALS['LSerror'] -> addErrorCode(1020);
+                          }
+                        }
+                        else {
+                          // l'attribut password n'existe pas
+                          debug("L'attribut password n'existe pas");
+                          $GLOBALS['LSerror'] -> addErrorCode(1020);
+                        }
+                      }
+                    }
+                    else {
+                      $GLOBALS['LSerror'] -> addErrorCode(1019);
+                    }
+                  }
+                  else {
+                    $GLOBALS['LSerror'] -> addErrorCode(1018);
+                  }
                 }
                 else {
-                  $GLOBALS['LSerror'] -> addErrorCode(1006);
-                  debug('mdp incorrect');
+                  if ( $this -> checkUserPwd($result[0],$_POST['LSsession_pwd']) ) {
+                    // Authentification réussi
+                    $this -> LSuserObject = $result[0];
+                    $this -> dn = $result[0]->getValue('dn');
+                    $this -> rdn = $_POST['LSsession_user'];
+                    $this -> loadLSrights();
+                    $this -> loadLSaccess();
+                    $GLOBALS['Smarty'] -> assign('LSsession_username',$this -> LSuserObject -> getDisplayValue());
+                    $_SESSION['LSsession']=get_object_vars($this);
+                    return true;
+                  }
+                  else {
+                    $GLOBALS['LSerror'] -> addErrorCode(1006);
+                    debug('mdp incorrect');
+                  }
                 }
               }
             }
@@ -338,15 +489,20 @@ class LSsession {
           $GLOBALS['Smarty'] -> assign('ldapServerId',$this -> ldapServerId);
         }
         $GLOBALS['Smarty'] -> assign('topDn',$this -> topDn);
-        $this -> displayLoginForm();
+        if (isset($_GET['LSsession_recoverPassword'])) {
+          $this -> displayRecoverPasswordForm($recoveryPasswordInfos);
+        }
+        else {
+          $this -> displayLoginForm();
+        }
         return;
       }
   }
 
  /**
-  * Définition du serveur Ldap de la session
+  * Définition du serveur Ldap de la session
   *
-  * Définition du serveur Ldap de la session à partir de son ID dans 
+  * Définition du serveur Ldap de la session à partir de son ID dans 
   * le tableau $GLOBALS['LSconfig']['ldap_servers'].
   *
   * @param[in] integer Index du serveur Ldap
@@ -440,12 +596,12 @@ class LSsession {
   }
 
  /**
-  * Retourne les options d'une liste déroulante pour le choix du topDn
+  * Retourne les options d'une liste déroulante pour le choix du topDn
   * de connexion au serveur Ldap
   *
   * Liste les subdn ($this ->ldapServer['subDn'])
   *
-  * @retval string Les options (<option>) pour la sélection du topDn.
+  * @retval string Les options (<option>) pour la sélection du topDn.
   */
   function getSubDnLdapServerOptions($selected=NULL) {
     $list = $this -> getSubDnLdapServer();
@@ -483,9 +639,9 @@ class LSsession {
   * Test un bind sur le serveur avec le dn de l'objet et le mot de passe fourni.
   *
   * @param[in] LSobject L'object "user" pour l'authentification
-  * @param[in] string Le mot de passe à tester
+  * @param[in] string Le mot de passe à tester
   *
-  * @retval boolean True si l'authentification à réussi, false sinon.
+  * @retval boolean True si l'authentification à réussi, false sinon.
   */
   function checkUserPwd($object,$pwd) {
     return $GLOBALS['LSldap'] -> checkBind($object -> getValue('dn'),$pwd);
@@ -494,7 +650,7 @@ class LSsession {
  /**
   * Affiche le formulaire de login
   *
-  * Défini les informations pour le template Smarty du formulaire de login.
+  * Défini les informations pour le template Smarty du formulaire de login.
   *
   * @retval void
   */
@@ -523,12 +679,72 @@ class LSsession {
     $GLOBALS['Smarty'] -> assign('loginform_label_user',_('Identifiant'));
     $GLOBALS['Smarty'] -> assign('loginform_label_pwd',_('Mot de passe'));
     $GLOBALS['Smarty'] -> assign('loginform_label_submit',_('Connexion'));
-
+    $GLOBALS['Smarty'] -> assign('loginform_label_lostpassword',_('Mot de passe oublié ?'));
+    
+    $this -> setTemplate('login.tpl');
     $this -> addJSscript('LSsession_login.js');
   }
 
  /**
-  * Défini le template Smarty à utiliser
+  * Affiche le formulaire de récupération de mot de passe
+  *
+  * Défini les informations pour le template Smarty du formulaire de 
+  * récupération de mot de passe
+  * 
+  * @param[in] $infos array() Information sur le status du processus de 
+  *                           recouvrement de mot de passe
+  *
+  * @retval void
+  */
+  function displayRecoverPasswordForm($recoveryPasswordInfos) {
+    $GLOBALS['Smarty'] -> assign('pagetitle',_('Récupération de votre mot de passe'));
+    $GLOBALS['Smarty'] -> assign('recoverpasswordform_action','index.php?LSsession_recoverPassword');
+    
+    if (count($GLOBALS['LSconfig']['ldap_servers'])==1) {
+      $GLOBALS['Smarty'] -> assign('recoverpasswordform_ldapserver_style','style="display: none"');
+    }
+    
+    $GLOBALS['Smarty'] -> assign('recoverpasswordform_label_ldapserver',_('Serveur LDAP'));
+    $ldapservers_name=array();
+    $ldapservers_index=array();
+    foreach($GLOBALS['LSconfig']['ldap_servers'] as $id => $infos) {
+      $ldapservers_index[]=$id;
+      $ldapservers_name[]=$infos['name'];
+    }
+    $GLOBALS['Smarty'] -> assign('recoverpasswordform_ldapservers_name',$ldapservers_name);
+    $GLOBALS['Smarty'] -> assign('recoverpasswordform_ldapservers_index',$ldapservers_index);
+
+    $GLOBALS['Smarty'] -> assign('recoverpasswordform_label_user',_('Identifiant'));
+    $GLOBALS['Smarty'] -> assign('recoverpasswordform_label_submit',_('Valider'));
+    $GLOBALS['Smarty'] -> assign('recoverpasswordform_label_back',_('Retour'));
+    
+    if (isset($recoveryPasswordInfos['recoveryHashMail'])) {
+      $GLOBALS['Smarty'] -> assign(
+        'recoverpassword_msg',
+        getFData(
+          _("Un mail vient de vous être envoyé à l'adresse %{mail}. " .
+          "Merci de suivre les indications contenus dans ce mail."),
+          $recoveryPasswordInfos['recoveryHashMail']
+        )
+      );
+    }
+    
+    if (isset($recoveryPasswordInfos['newPasswordMail'])) {
+      $GLOBALS['Smarty'] -> assign(
+        'recoverpassword_msg',
+        getFData(
+          _("Votre nouveau mot de passe vient de vous être envoyé à l'adresse %{mail}. "),
+          $recoveryPasswordInfos['newPasswordMail']
+        )
+      );
+    }
+    
+    $this -> setTemplate('recoverpassword.tpl');
+    $this -> addJSscript('LSsession_recoverpassword.js');
+  }
+
+ /**
+  * Défini le template Smarty à utiliser
   *
   * Remarque : les fichiers de templates doivent se trouver dans le dossier 
   * templates/.
@@ -544,9 +760,9 @@ class LSsession {
  /**
   * Ajoute un script JS au chargement de la page
   *
-  * Remarque : les scripts doivents être dans le dossier LS_JS_DIR.
+  * Remarque : les scripts doivents être dans le dossier LS_JS_DIR.
   *
-  * @param[in] $script Le nom du fichier de script à charger.
+  * @param[in] $script Le nom du fichier de script à charger.
   *
   * @retval void
   */
@@ -559,9 +775,9 @@ class LSsession {
  /**
   * Ajoute une feuille de style au chargement de la page
   *
-  * Remarque : les scripts doivents être dans le dossiers templates/css/.
+  * Remarque : les scripts doivents être dans le dossiers templates/css/.
   *
-  * @param[in] $script Le nom du fichier css à charger.
+  * @param[in] $script Le nom du fichier css à charger.
   *
   * @retval void
   */
@@ -572,7 +788,7 @@ class LSsession {
  /**
   * Affiche le template Smarty
   *
-  * Charge les dépendances et affiche le template Smarty
+  * Charge les dépendances et affiche le template Smarty
   *
   * @retval void
   */
@@ -631,7 +847,7 @@ class LSsession {
   /**
    * Charge les droits LS de l'utilisateur
    * 
-   * @retval boolean True si le chargement à réussi, false sinon.
+   * @retval boolean True si le chargement à réussi, false sinon.
    **/
   function loadLSrights() {
     if (is_array($this -> ldapServer['LSadmins'])) {
@@ -650,11 +866,11 @@ class LSsession {
                     }
                   }
                   else {
-                    debug('Impossible de chargé le dn : '.$dn);
+                    debug('Impossible de chargé le dn : '.$dn);
                   }
                 }
                 else {
-                  debug('Impossible de créer l\'objet de type : '.$conf['LSobject']);
+                  debug('Impossible de créer l\'objet de type : '.$conf['LSobject']);
                 }
               }
               else {
@@ -682,7 +898,7 @@ class LSsession {
   }
   
   /**
-   * Charge les droits d'accès de l'utilisateur pour construire le menu de l'interface
+   * Charge les droits d'accès de l'utilisateur pour construire le menu de l'interface
    *
    * @retval void
    */
@@ -710,7 +926,7 @@ class LSsession {
   }
   
   /**
-   * Dit si l'utilisateur est admin de le DN spécifié
+   * Dit si l'utilisateur est admin de le DN spécifié
    *
    * @param[in] string DN de l'objet
    * 
@@ -729,11 +945,11 @@ class LSsession {
   }
   
   /**
-   * Retourne qui est l'utilisateur par rapport à l'object
+   * Retourne qui est l'utilisateur par rapport à l'object
    *
    * @param[in] string Le DN de l'objet
    * 
-   * @retval string 'admin'/'self'/'user' pour Admin , l'utilisateur lui même ou un simple utilisateur
+   * @retval string 'admin'/'self'/'user' pour Admin , l'utilisateur lui même ou un simple utilisateur
    */
   function whoami($dn) {
     if ($this -> isAdmin($dn)) {
@@ -748,14 +964,14 @@ class LSsession {
   }
   
   /**
-   * Retourne le droit de l'utilisateur à accèder à un objet
+   * Retourne le droit de l'utilisateur à accèder à un objet
    * 
    * @param[in] string $LSobject Le type de l'objet
-   * @param[in] string $dn Le DN de l'objet (le container_dn du type de l'objet par défaut)
-   * @param[in] string $right Le type de droit d'accès à tester ('r'/'w')
-   * @param[in] string $attr Le nom de l'attribut auquel on test l'accès
+   * @param[in] string $dn Le DN de l'objet (le container_dn du type de l'objet par défaut)
+   * @param[in] string $right Le type de droit d'accès à tester ('r'/'w')
+   * @param[in] string $attr Le nom de l'attribut auquel on test l'accès
    *
-   * @retval boolean True si l'utilisateur a accès, false sinon
+   * @retval boolean True si l'utilisateur a accès, false sinon
    */
   function canAccess($LSobject,$dn=NULL,$right=NULL,$attr=NULL) {
     if (!$this -> loadLSobject($LSobject))
@@ -812,49 +1028,49 @@ class LSsession {
   }
   
   /**
-   * Retourne le droit de l'utilisateur à editer à un objet
+   * Retourne le droit de l'utilisateur à editer à un objet
    * 
    * @param[in] string $LSobject Le type de l'objet
-   * @param[in] string $dn Le DN de l'objet (le container_dn du type de l'objet par défaut)
-   * @param[in] string $attr Le nom de l'attribut auquel on test l'accès
+   * @param[in] string $dn Le DN de l'objet (le container_dn du type de l'objet par défaut)
+   * @param[in] string $attr Le nom de l'attribut auquel on test l'accès
    *
-   * @retval boolean True si l'utilisateur a accès, false sinon
+   * @retval boolean True si l'utilisateur a accès, false sinon
    */
   function canEdit($LSobject,$dn=NULL,$attr=NULL) {
     return $this -> canAccess($LSobject,$dn,'w',$attr);
   }
 
   /**
-   * Retourne le droit de l'utilisateur à supprimer un objet
+   * Retourne le droit de l'utilisateur à supprimer un objet
    * 
    * @param[in] string $LSobject Le type de l'objet
-   * @param[in] string $dn Le DN de l'objet (le container_dn du type de l'objet par défaut)
+   * @param[in] string $dn Le DN de l'objet (le container_dn du type de l'objet par défaut)
    *
-   * @retval boolean True si l'utilisateur a accès, false sinon
+   * @retval boolean True si l'utilisateur a accès, false sinon
    */  
   function canRemove($LSobject,$dn) {
     return $this -> canAccess($LSobject,$dn,'w','rdn');
   }
   
   /**
-   * Retourne le droit de l'utilisateur à créer un objet
+   * Retourne le droit de l'utilisateur à créer un objet
    * 
    * @param[in] string $LSobject Le type de l'objet
    *
-   * @retval boolean True si l'utilisateur a accès, false sinon
+   * @retval boolean True si l'utilisateur a accès, false sinon
    */    
   function canCreate($LSobject) {
     return $this -> canAccess($LSobject,NULL,'w','rdn');
   }
   
   /**
-   * Retourne le droit de l'utilisateur à gérer la relation d'objet
+   * Retourne le droit de l'utilisateur à gérer la relation d'objet
    * 
-   * @param[in] string $dn Le DN de l'objet (le container_dn du type de l'objet par défaut)
+   * @param[in] string $dn Le DN de l'objet (le container_dn du type de l'objet par défaut)
    * @param[in] string $relationName Le nom de la relation avec l'objet
-   * @param[in] string $right Le type de droit a vérifier ('r' ou 'w')
+   * @param[in] string $right Le type de droit a vérifier ('r' ou 'w')
    *
-   * @retval boolean True si l'utilisateur a accès, false sinon
+   * @retval boolean True si l'utilisateur a accès, false sinon
    */
   function relationCanAccess($dn,$relationName,$right=NULL) {
     $LSobject=$this -> LSuserObject -> getType();
@@ -876,12 +1092,12 @@ class LSsession {
   }
 
   /**
-   * Retourne le droit de l'utilisateur à modifier la relation d'objet
+   * Retourne le droit de l'utilisateur à modifier la relation d'objet
    * 
-   * @param[in] string $dn Le DN de l'objet (le container_dn du type de l'objet par défaut)
+   * @param[in] string $dn Le DN de l'objet (le container_dn du type de l'objet par défaut)
    * @param[in] string $relationName Le nom de la relation avec l'objet
    *
-   * @retval boolean True si l'utilisateur a accès, false sinon
+   * @retval boolean True si l'utilisateur a accès, false sinon
    */  
   function relationCanEdit($dn,$relationName) {
     return $this -> relationCanAccess($dn,$relationName,'w');
@@ -922,8 +1138,8 @@ class LSsession {
   /**
    * Retourne le chemin du fichier temporaire
    * 
-   * Retourne le chemin du fichier temporaire qu'il créera à partir de la valeur
-   * s'il n'existe pas déjà.
+   * Retourne le chemin du fichier temporaire qu'il créera à partir de la valeur
+   * s'il n'existe pas déjà.
    * 
    * @author Benjamin Renard <brenard@easter-eggs.com>
    * 
diff --git a/trunk/includes/functions.php b/trunk/includes/functions.php
index 5325f35c..d82efecd 100644
--- a/trunk/includes/functions.php
+++ b/trunk/includes/functions.php
@@ -112,7 +112,7 @@ function return_data($data) {
 
 function debug($data,$get=true) {
   if ($get) {
-    if (is_array($data)) {
+    if (is_array($data)||is_object($data)) {
       $GLOBALS['LSdebug']['fields'][]=$data;
     }
     else {
@@ -126,7 +126,7 @@ function debug_print($return=false) {
   if (( $GLOBALS['LSdebug']['fields'] ) && ( $GLOBALS['LSdebug']['active'] )) {
     $txt='<ul>';
     foreach($GLOBALS['LSdebug']['fields'] as $debug) {
-      if (is_array($debug)) {
+      if (is_array($debug)||is_object($debug)) {
         $txt.='<li><pre>'.print_r($debug,true).'</pre></li>';
       }
       else {
@@ -135,11 +135,11 @@ function debug_print($return=false) {
     }
     $txt.='</ul>';
     $GLOBALS['Smarty'] -> assign('LSdebug',$txt);
-		if ($return) {
-			return $txt;
-		}
+    if ($return) {
+      return $txt;
+    }
   }
-	return;
+  return;
 }
 
   /**
@@ -223,5 +223,40 @@ function debug_print($return=false) {
     }
     return $basedn;
   }
+  
+  function checkEmail($value,$checkDns=true) {
+    $regex = '/^((\"[^\"\f\n\r\t\v\b]+\")|([\w\!\#\$\%\&\'\*\+\-\~\/\^\`\|\{\}]+(\.[\w\!\#\$\%\&\'\*\+\-\~\/\^\`\|\{\}]+)*))@((\[(((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9])))\])|(((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9])))|((([A-Za-z0-9\-])+\.)+[A-Za-z\-]+))$/';
+
+    if (!preg_match($regex, $value)) {
+      debug('checkEmail : regex fail');
+      return false;
+    }
+
+    if ($checkDns && function_exists('checkdnsrr')) {
+      $tokens = explode('@', $value);
+      if (!(checkdnsrr($tokens[1], 'MX') || checkdnsrr($tokens[1], 'A'))) {
+        debug('checkEmail : DNS fail');
+        return false;
+      }
+    }
+
+    return true;
+  }
+  
+  function generatePassword($chars=NULL,$lenght=NULL) {
+    if (!$chars) {
+      $chars='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-';
+    }
+    $nbChars=strlen($chars);
+    
+    if (!$lenght) {
+      $lenght=8;
+    }
+    $retVal='';
+    for($i=0;$i<$lenght;$i++){
+      $retVal.=$chars[rand(0,$nbChars-1)];
+    }
+    return $retVal;
+  }
 
 ?>
diff --git a/trunk/includes/js/LSsession_login.js b/trunk/includes/js/LSsession_login.js
index 7c8ae58b..c663b436 100644
--- a/trunk/includes/js/LSsession_login.js
+++ b/trunk/includes/js/LSsession_login.js
@@ -43,6 +43,7 @@ var LSsession_login = new Class({
         }
         if (data.LSerror) {
           varLSdefault.displayError(data.LSerror);
+          this.loginformLevelHide();
           return;
         }
         if (data.list_topDn) {
@@ -53,18 +54,20 @@ var LSsession_login = new Class({
           });
         }
         else {
-          $$('.loginform-level').each(function(el) {
-            el.setStyle('display','none');
-          });
+          this.loginformLevelHide();
         }
       }
       else {
-        $$('.loginform-level').each(function(el) {
-          el.setStyle('display','none');
-        });
-        $('LSsession_topDn').empty();
+        this.loginformLevelHide();
       }
       this.enableInput();
+    },
+    
+    loginformLevelHide: function(){
+      $$('.loginform-level').each(function(el) {
+        el.setStyle('display','none');
+      });
+      $('LSsession_topDn').empty();
     }
 });
 window.addEvent(window.ie ? 'load' : 'domready', function() {
diff --git a/trunk/index.php b/trunk/index.php
index bac52e99..d5125a6c 100644
--- a/trunk/index.php
+++ b/trunk/index.php
@@ -33,9 +33,6 @@ if($LSsession -> startLSsession()) {
   // Template
   $GLOBALS['LSsession'] -> setTemplate('accueil.tpl');
 }
-else {
-  $GLOBALS['LSsession'] -> setTemplate('login.tpl');
-}
 
 // Affichage des retours d'erreurs
 $GLOBALS['LSsession'] -> displayTemplate();
diff --git a/trunk/lsexample/ls.schema b/trunk/lsexample/ls.schema
index 452f74a3..c2becb96 100644
--- a/trunk/lsexample/ls.schema
+++ b/trunk/lsexample/ls.schema
@@ -1,175 +1,48 @@
-# Easter-eggs OID: 1.3.6.1.4.1.10650
-# 1.3.6.1.4.1.10650.2            LDAP OID
-# 1.3.6.1.4.1.10650.3            Customers OID
-# 
-# 1.3.6.1.4.1.10650.2.1          Ldap Attributes
-# 1.3.6.1.4.1.10650.2.1.1        Admin sys Ldap Attributes
-# 1.3.6.1.4.1.10650.2.1.2        Dev Ldap Attributes
-# 1.3.6.1.4.1.10650.2.1.3        Global Attributes
-# 1.3.6.1.4.1.10650.2.2          Ldap Objectclass
-# 1.3.6.1.4.1.10650.2.2.1        Admin sys Ldap Objectclass
-# 1.3.6.1.4.1.10650.2.2.2        Dev Ldap Objectclass
-# 1.3.6.1.4.1.10650.2.2.3        Global OC
+# LdapSaisie - LDAP Schema - Example
+# Web Site : http://ldapsaisie.labs.libre-entreprise.org
+objectIdentifier EeRoot                 1.3.6.1.4.1.10650
+objectIdentifier LeRoot                 EeRoot:4
+objectIdentifier LsRoot                 LeRoot:10000
+objectIdentifier LsLDAP                 LsRoot:2
+objectIdentifier LsLDAPAttribute        LsLDAP:1
+objectIdentifier LsLDAPObjectClass      LsLDAP:2
 
-# Ost
-# 1.3.6.1.4.1.10650.3.1127.2.1 Ldap attributes
-# 1.3.6.1.4.1.10650.3.1127.2.2 Ldap OC
-
-
-# <Ee attributes>
-attributetype (1.3.6.1.4.1.10650.2.1.1.1
-  NAME 'eeallowedservices'
+# <Ls attributes>
+attributetype (LsLDAPAttribute:1
+  NAME 'lsAllowedServices'
   DESC 'List of allowed services'
   EQUALITY caseIgnoreMatch
   SUBSTR caseIgnoreSubstringsMatch
   SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
 
-# </Ee attributes>
-
-# <From qmail schema>
-attributetype ( 1.3.6.1.4.1.7914.1.2.1.4 NAME 'mailAlternateAddress'
-        SUBSTR caseIgnoreSubstringsMatch
-        DESC 'Secondary (alias) mailaddresses for the same user'
-        EQUALITY caseIgnoreIA5Match
-        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
-
-attributetype ( 1.3.6.1.4.1.7914.1.2.1.7 NAME 'mailForwardingAddress'
-        DESC 'Address(es) to forward all incoming messages to.'
-        EQUALITY caseIgnoreIA5Match
-        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
-
-# </From qmail schema>
-
-# <From courier.schema>
-attributetype ( 1.3.6.1.4.1.10018.1.1.1 NAME 'mailbox'
-        DESC 'The absolute path to the mailbox for a mail account in a non-default location'
-        EQUALITY caseExactIA5Match
-        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
-
-
-attributetype ( 1.3.6.1.4.1.10018.1.1.4 NAME 'maildrop'
-        DESC 'RFC822 Mailbox - mail alias'
-        EQUALITY caseIgnoreIA5Match
-        SUBSTR caseIgnoreIA5SubstringsMatch
-        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
-# </From courier.schema>
-
-# <From postfix>
-attributetype ( 1.3.6.1.4.1.7914.1.2.1.5 NAME 'mailQuota'
-        DESC 'The amount of space the user can use until all further messages get bounced.'
-        SYNTAX 1.3.6.1.4.1.1466.115.121.1.44
-        SINGLE-VALUE )
-# </From postfix>
-
-# <From gnarwl>
-# Original
-#attributetype ( 1.3.6.1.4.1.11048.1.1.1.1
-#       NAME 'vacationActive'
-#       SINGLE-VALUE
-#       EQUALITY booleanMatch
-#       DESC 'A flag, for marking the user as being away'
-#       SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )
-
-# Ee
-attributetype ( 1.3.6.1.4.1.11048.1.1.1.1
-        NAME 'vacationActive'
-        SINGLE-VALUE
-        DESC 'Equal to uid@autoreponse.foo.bar, for marking the user as being away'
-        EQUALITY caseIgnoreIA5Match
-        SUBSTR caseIgnoreIA5SubstringsMatch
-        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
-
-attributetype ( 1.3.6.1.4.1.11048.1.1.1.3
-        NAME 'vacationInfo'
-        SINGLE-VALUE
-        SYNTAX 1.3.6.1.4.1.1466.115.121.1.40
-        DESC 'Absentee note to leave behind, while on vacation'
-        EQUALITY octetStringMatch )
-
-attributetype ( 1.3.6.1.4.1.11048.1.1.1.4
-        NAME 'vacationStart'
-        SINGLE-VALUE
-        SYNTAX 1.3.6.1.4.1.1466.115.121.1.40
-        DESC 'Beginning of vacation'
-        EQUALITY octetStringMatch )
-
-# Original
-#attributetype ( 1.3.6.1.4.1.11048.1.1.1.5
-#       NAME 'vacationEnd'
-#       SINGLE-VALUE
-#       SYNTAX 1.3.6.1.4.1.1466.115.121.1.40
-#       DESC 'End of vacation'
-#       EQUALITY octetStringMatch )
-
-# Ee
-attributetype ( 1.3.6.1.4.1.11048.1.1.1.5
-        NAME 'vacationEnd'
-        SINGLE-VALUE
-        SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
-        DESC 'End of vacation'
-        ORDERING generalizedTimeOrderingMatch
-        EQUALITY generalizedTimeMatch )
-
-attributetype (1.3.6.1.4.1.11048.1.1.1.10
-        NAME 'vacationForward'
-        EQUALITY caseIgnoreIA5Match
-        SUBSTR caseIgnoreIA5SubstringsMatch
-        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256}
-        DESC 'Where to forward mails to, while on vacation' )
-
-# </From gnarwl>
-
-## Objectclasses
-# LS people
-objectclass (1.3.6.1.4.1.10650.3.1127.2.2.1
+attributetype ( LsLDAPAttribute:2 NAME 'lsRecoveryHash'
+  DESC 'Password Recover Hash'
+  EQUALITY caseIgnoreMatch
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
+# </Ls attributes>
+        
+# <Ls Objectclass>
+objectclass (LsLDAPObjectClass:1
   NAME 'lspeople'
   DESC 'LS people Objectclass'
   STRUCTURAL
   MUST ( uid $ cn )
-  MAY ( jpegPhoto $ sn $ givenName $ postalAddress $ postalCode $ l $ st $ c $ telephoneNumber $ mobile $ fax $ mail $ mailalternateaddress $ personalTitle $ description $ userPassword $ eeallowedservices $ mailforwardingaddress $ maildrop $ mailquota $ mailbox $ vacationActive $ vacationInfo $ vacationEnd $ vacationForward ))
+  MAY ( jpegPhoto $ sn $ givenName $ postalAddress $ postalCode $ l $ st $ c $
+        telephoneNumber $ mobile $ fax $ mail $ personalTitle $ description $
+        userPassword $ lsallowedservices $ lsRecoveryHash ))
 
-# LS Alias
-objectclass (1.3.6.1.4.1.10650.3.1127.2.2.2
-  NAME 'lsalias'
-  DESC 'LS alias Objectclass'
-  STRUCTURAL
-  MUST ( mail $ maildrop )
-  MAY  ( mailalternateaddress $ description ))
-
-# LS group
-objectclass (1.3.6.1.4.1.10650.3.1127.2.2.3
+objectclass (LsLDAPObjectClass:3
   NAME 'lsgroup'
   DESC 'LS group Objectclass'
   STRUCTURAL
   MUST ( cn )
   MAY ( uniquemember $ description ))
 
-# LS system account
-objectclass (1.3.6.1.4.1.10650.3.1127.2.2.4
+objectclass (LsLDAPObjectClass:4
   NAME 'lssysaccount'
   DESC 'LS system account Objectclass'
   STRUCTURAL
   MUST ( uid )
-  MAY (userpassword $ description))
-
-# Ost mailbox
-objectclass (1.3.6.1.4.1.10650.3.1127.2.2.5
-  NAME 'lsmailbox'
-  DESC 'LS custom mailbox Objectclass'
-  STRUCTURAL
-  MUST ( uid )
-  MAY ( userPassword $ description $ eeallowedservices $ maildrop $ mailbox $ mail $ mailalternateaddress $ mailforwardingaddress $ mailquota ))
-
-# Ost computer
-objectclass (1.3.6.1.4.1.10650.3.1127.2.2.6
-  NAME 'lscomputer'
-  DESC 'LS computer Objectclass'
-  STRUCTURAL
-  MUST ( uid ))
-
-# Ost samba domains
-objectclass (1.3.6.1.4.1.10650.3.1127.2.2.8
-  NAME 'lssambadomain'
-  DESC 'LS samba domain Objectclass'
-  STRUCTURAL) 
+  MAY (userPassword $ description))
+# </Ls Objectclass>
 
diff --git a/trunk/lsexample/lsexample.ldif b/trunk/lsexample/lsexample.ldif
index 05fb9f00..5a6c3711 100644
--- a/trunk/lsexample/lsexample.ldif
+++ b/trunk/lsexample/lsexample.ldif
@@ -3,110 +3,39 @@ objectClass: top
 objectClass: organization
 o: ls
 structuralObjectClass: organization
-entryUUID: 2229e388-825b-1029-838c-b10e837060e0
-creatorsName: cn=anonymous
-modifiersName: cn=anonymous
-createTimestamp: 20050706111624Z
-modifyTimestamp: 20050706111624Z
-entryCSN: 20050706111624.000000Z#000001#000#000000
 
 dn: ou=sysaccounts,o=ls
 objectClass: top
 objectClass: organizationalUnit
 ou: sysaccounts
 structuralObjectClass: organizationalUnit
-entryUUID: 2238a738-825b-1029-838d-b10e837060e0
-creatorsName: cn=anonymous
-modifiersName: cn=anonymous
-createTimestamp: 20050706111624Z
-modifyTimestamp: 20050706111624Z
-entryCSN: 20050706111624.000000Z#000002#000#000000
 
-dn: ou=people,o=ls
+dn: uid=mail,ou=sysaccounts,o=ls
 objectClass: top
-objectClass: organizationalUnit
-ou: people
-structuralObjectClass: organizationalUnit
-entryUUID: 223b67e8-825b-1029-838e-b10e837060e0
-creatorsName: cn=anonymous
-modifiersName: cn=anonymous
-createTimestamp: 20050706111624Z
-modifyTimestamp: 20050706111624Z
-entryCSN: 20050706111624.000000Z#000003#000#000000
+objectClass: lssysaccount
+uid: mail
+structuralObjectClass: lssysaccount
+userPassword: toto
 
-dn: ou=mailboxes,o=ls
+dn: uid=samba,ou=sysaccounts,o=ls
 objectClass: top
-objectClass: organizationalUnit
-ou: mailboxes
-structuralObjectClass: organizationalUnit
-entryUUID: 2240f622-825b-1029-8390-b10e837060e0
-creatorsName: cn=anonymous
-modifiersName: cn=anonymous
-createTimestamp: 20050706111624Z
-modifyTimestamp: 20050706111624Z
-entryCSN: 20050706111624.000000Z#000005#000#000000
+objectClass: lssysaccount
+uid: samba
+structuralObjectClass: lssysaccount
+userPassword: toto
 
-dn: ou=aliases,o=ls
+dn: uid=ldapsaisie,ou=sysaccounts,o=ls
 objectClass: top
-objectClass: organizationalUnit
-ou: aliases
-structuralObjectClass: organizationalUnit
-entryUUID: 2243b88a-825b-1029-8391-b10e837060e0
-creatorsName: cn=anonymous
-modifiersName: cn=anonymous
-createTimestamp: 20050706111624Z
-modifyTimestamp: 20050706111624Z
-entryCSN: 20050706111624.000000Z#000006#000#000000
-
-dn: ou=computers,o=ls
-objectClass: top
-objectClass: organizationalUnit
-ou: computers
-structuralObjectClass: organizationalUnit
-entryUUID: 22468588-825b-1029-8392-b10e837060e0
-creatorsName: cn=anonymous
-modifiersName: cn=anonymous
-createTimestamp: 20050706111624Z
-modifyTimestamp: 20050706111624Z
-entryCSN: 20050706111624.000000Z#000007#000#000000
-
-dn: ou=sambadomains,o=ls
-objectClass: top
-objectClass: organizationalUnit
-ou: sambadomains
-structuralObjectClass: organizationalUnit
-entryUUID: 224cf30a-825b-1029-8394-b10e837060e0
-creatorsName: cn=anonymous
-modifiersName: cn=anonymous
-createTimestamp: 20050706111624Z
-modifyTimestamp: 20050706111624Z
-entryCSN: 20050706111624.000000Z#000009#000#000000
-
-dn: sambaDomainName=LS_NT,ou=sambadomains,o=ls
-objectClass: top
-objectClass: lssambadomain
-objectClass: sambaDomain
-sambaDomainName: LS_NT
-sambaSID: S-1-5-21-2421470416-3566881284-3047381809
-structuralObjectClass: lssambadomain
-entryUUID: 2250d4ac-825b-1029-8395-b10e837060e0
-creatorsName: cn=anonymous
-modifiersName: cn=anonymous
-createTimestamp: 20050706111624Z
-modifyTimestamp: 20050706111624Z
-entryCSN: 20050706111624.000000Z#00000a#000#000000
+objectClass: lssysaccount
+uid: ldapsaisie
+structuralObjectClass: lssysaccount
+userPassword: toto
 
 dn: ou=groups,o=ls
 objectClass: top
 objectClass: organizationalUnit
 ou: groups
 structuralObjectClass: organizationalUnit
-entryUUID: 224947d2-825b-1029-8393-b10e837060e0
-creatorsName: cn=anonymous
-modifiersName: cn=anonymous
-createTimestamp: 20050706111624Z
-modifyTimestamp: 20050706111624Z
-entryCSN: 20050706111624.000000Z#000008#000#000000
 
 dn: cn=adminldap,ou=groups,o=ls
 objectClass: top
@@ -118,91 +47,81 @@ gidNumber: 70000
 sambaSID: S-1-5-21-2421470416-3566881284-3047381809-70000
 sambaGroupType: 2
 structuralObjectClass: lsgroup
-entryUUID: 226bb240-825b-1029-8396-b10e837060e0
-creatorsName: cn=anonymous
-createTimestamp: 20050706111625Z
 uniqueMember: uid=eeggs,ou=people,o=ls
-entryCSN: 20080211142717.746402Z#000000#000#000000
-modifiersName: uid=eeggs,ou=people,o=ls
-modifyTimestamp: 20080211142717Z
 
-dn: uid=mail,ou=sysaccounts,o=ls
+dn: cn=invite,ou=groups,o=ls
 objectClass: top
-objectClass: lssysaccount
-uid: mail
-structuralObjectClass: lssysaccount
-userPassword: toto
-entryUUID: 22958d72-825b-1029-839c-b10e837060e0
-creatorsName: cn=anonymous
-modifiersName: cn=anonymous
-createTimestamp: 20050706111625Z
-modifyTimestamp: 20050706111625Z
-entryCSN: 20050706111625.000000Z#000007#000#000000
+objectClass: lsgroup
+objectClass: posixGroup
+objectClass: sambaGroupMapping
+cn: invite
+gidNumber: 101009
+sambaSID: S-1-5-21-2421470416-3566881284-3047381809-203019
+sambaGroupType: 2
+structuralObjectClass: lsgroup
 
-dn: uid=ftp,ou=sysaccounts,o=ls
+dn: cn=ls,ou=groups,o=ls
 objectClass: top
-objectClass: lssysaccount
-uid: ftp
-structuralObjectClass: lssysaccount
-userPassword: toto
-entryUUID: 22a46608-825b-1029-839d-b10e837060e0
-creatorsName: cn=anonymous
-modifiersName: cn=anonymous
-createTimestamp: 20050706111625Z
-modifyTimestamp: 20050706111625Z
-entryCSN: 20050706111625.000000Z#000008#000#000000
+objectClass: lsgroup
+objectClass: posixGroup
+objectClass: sambaGroupMapping
+cn: ls
+gidNumber: 102001
+sambaSID: S-1-5-21-2421470416-3566881284-3047381809-205003
+sambaGroupType: 2
+structuralObjectClass: lsgroup
+uniqueMember: uid=secretariat,ou=people,o=ls
 
-dn: uid=http,ou=sysaccounts,o=ls
+dn: cn=informatique,ou=groups,o=ls
 objectClass: top
-objectClass: lssysaccount
-uid: http
-structuralObjectClass: lssysaccount
-userPassword: toto
-entryUUID: 22a7274e-825b-1029-839e-b10e837060e0
-creatorsName: cn=anonymous
-modifiersName: cn=anonymous
-createTimestamp: 20050706111625Z
-modifyTimestamp: 20050706111625Z
-entryCSN: 20050706111625.000000Z#000009#000#000000
+objectClass: lsgroup
+objectClass: posixGroup
+objectClass: sambaGroupMapping
+gidNumber: 102009
+sambaSID: S-1-5-21-2421470416-3566881284-3047381809-205019
+sambaGroupType: 2
+structuralObjectClass: lsgroup
+cn: informatique
+uniqueMember: uid=eeggs,ou=people,o=ls
 
-dn: uid=samba,ou=sysaccounts,o=ls
+dn: cn=direction,ou=groups,o=ls
 objectClass: top
-objectClass: lssysaccount
-uid: samba
-structuralObjectClass: lssysaccount
-entryUUID: 22a9f44c-825b-1029-839f-b10e837060e0
-creatorsName: cn=anonymous
-createTimestamp: 20050706111625Z
-userPassword: toto
-entryCSN: 20050706115506.000000Z#000001#000#000000
-modifiersName: uid=eeggs,ou=people,o=ls
-modifyTimestamp: 20050706115506Z
+objectClass: lsgroup
+objectClass: posixGroup
+objectClass: sambaGroupMapping
+cn: direction
+gidNumber: 102007
+sambaSID: S-1-5-21-2421470416-3566881284-3047381809-205015
+sambaGroupType: 2
+structuralObjectClass: lsgroup
 
-dn: uid=ldapsaisie,ou=sysaccounts,o=ls
+dn: cn=administratif,ou=groups,o=ls
 objectClass: top
-objectClass: lssysaccount
-uid: ldapsaisie
-structuralObjectClass: lssysaccount
-userPassword: toto
-entryUUID: 22acb6aa-825b-1029-83a0-b10e837060e0
-creatorsName: cn=anonymous
-modifiersName: cn=anonymous
-createTimestamp: 20050706111625Z
-modifyTimestamp: 20050706111625Z
-entryCSN: 20050706111625.000000Z#00000b#000#000000
+objectClass: lsgroup
+objectClass: posixGroup
+objectClass: sambaGroupMapping
+cn: administratif
+gidNumber: 102005
+sambaSID: S-1-5-21-2421470416-3566881284-3047381809-205011
+sambaGroupType: 2
+structuralObjectClass: lsgroup
 
-dn: uid=nss,ou=sysaccounts,o=ls
+dn: cn=communication,ou=groups,o=ls
 objectClass: top
-objectClass: lssysaccount
-uid: nss
-structuralObjectClass: lssysaccount
-entryUUID: 22b06d40-825b-1029-83a1-b10e837060e0
-creatorsName: cn=anonymous
-createTimestamp: 20050706111625Z
-userPassword: toto
-entryCSN: 20050706115152.000000Z#000001#000#000000
-modifiersName: uid=eeggs,ou=people,o=ls
-modifyTimestamp: 20050706115152Z
+objectClass: lsgroup
+objectClass: posixGroup
+objectClass: sambaGroupMapping
+cn: communication
+gidNumber: 102003
+sambaSID: S-1-5-21-2421470416-3566881284-3047381809-205007
+sambaGroupType: 2
+structuralObjectClass: lsgroup
+
+dn: ou=people,o=ls
+objectClass: top
+objectClass: organizationalUnit
+ou: people
+structuralObjectClass: organizationalUnit
 
 dn: uid=eeggs,ou=people,o=ls
 objectClass: top
@@ -213,35 +132,22 @@ uid: eeggs
 uidNumber: 100000
 sambaSID: S-1-5-21-2421470416-3566881284-3047381809-201000
 structuralObjectClass: lspeople
-entryUUID: 22b70a42-825b-1029-83a3-b10e837060e0
-creatorsName: cn=anonymous
-createTimestamp: 20050706111625Z
 gidNumber: 102009
 mail: eeggs@ldapsaisie.biz
 facsimileTelephoneNumber: 030000000
-vacationInfo: Je suis absent pour le moment
-vacationEnd: 20070101000000Z
-vacationForward: brenard@easter-eggs.com
-eeallowedservices: MAIL
-eeallowedservices: FTP
+lsallowedservices: MAIL
+lsallowedservices: FTP
 description: Utilisateur test Easter-eggs
 cn: Easter Eggs
 sambaPrimaryGroupSID: S-1-5-21-2421470416-3566881284-3047381809-205019
-mailbox: eeggs/
 personalTitle: M.
 userPassword: toto
 sambaLMPassword: AAD3B435B51404EEAAD3B435B51404EE
 sambaNTPassword: 31D6CFE0D16AE931B73C59D7E0C089C0
-mailQuota: 5
 homeDirectory: /home/eeggs
 loginShell: /bin/false
 givenName: Easter
-maildrop: eeggs@ldapsaisie.biz
-vacationActive:
 sn: Eggs
-entryCSN: 20080211134602.394624Z#000000#000#000000
-modifiersName: uid=eeggs,ou=people,o=ls
-modifyTimestamp: 20080211134602Z
 
 dn: uid=invite,ou=people,o=ls
 objectClass: top
@@ -260,22 +166,13 @@ userPassword: toto
 sambaAcctFlags: [U          ]
 sambaPrimaryGroupSID: S-1-5-21-2421470416-3566881284-3047381809-203019
 sambaSID: S-1-5-21-2421470416-3566881284-3047381809-203024
-mailbox: invite/
-mailQuota: 52428800
-eeallowedservices: MAIL
-eeallowedservices: SAMBA
-eeallowedservices: FTP
+lsallowedservices: MAIL
+lsallowedservices: SAMBA
+lsallowedservices: FTP
 mail: invite@ldapsaisie.biz
-maildrop: invite@ldapsaisie.biz
 structuralObjectClass: lspeople
-entryUUID: 233dd144-825b-1029-9a9d-8f6e2b792dd2
-creatorsName: cn=anonymous
-createTimestamp: 20050706111626Z
 sambaNTPassword: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 sambaLMPassword: NO PASSWORDXXXXXXXXXXXXXXXXXXXXX
-entryCSN: 20050706133832.000000Z#000008#000#000000
-modifiersName: uid=eeggs,ou=people,o=ls
-modifyTimestamp: 20050706133832Z
 
 dn: uid=hmartin,ou=people,o=ls
 objectClass: top
@@ -289,30 +186,19 @@ uidNumber: 101022
 sambaAcctFlags: [U          ]
 sambaSID: S-1-5-21-2421470416-3566881284-3047381809-203044
 structuralObjectClass: lspeople
-entryUUID: 234393a4-825b-1029-9a9f-8f6e2b792dd2
-creatorsName: cn=anonymous
-createTimestamp: 20050706111626Z
 givenName: Henri
 sn: MARTIN
 gidNumber: 102001
 mail: henri.martin@ldapsaisie.biz
-maildrop: henri.martin@ldapsaisie.biz
-mailAlternateAddress: hmartin@ldapsaisie.biz
-vacationEnd: 20060101000000Z
-mailQuota: 52428800
-eeallowedservices: MAIL
-eeallowedservices: SAMBA
-eeallowedservices: FTP
+lsallowedservices: MAIL
+lsallowedservices: SAMBA
+lsallowedservices: FTP
 cn: Henri MARTIN
 sambaPrimaryGroupSID: S-1-5-21-2421470416-3566881284-3047381809-205003
-mailbox: hmartin/
 personalTitle: M.
 userPassword: toto
 sambaLMPassword: AAD3B435B51404EEAAD3B435B51404EE
 sambaNTPassword: 31D6CFE0D16AE931B73C59D7E0C089C0
-entryCSN: 20080211164417.161923Z#000000#000#000000
-modifiersName: uid=eeggs,ou=people,o=ls
-modifyTimestamp: 20080211164417Z
 
 dn: uid=secretariat,ou=people,o=ls
 objectClass: top
@@ -327,27 +213,17 @@ userPassword: toto
 sambaAcctFlags: [U          ]
 sambaSID: S-1-5-21-2421470416-3566881284-3047381809-203072
 structuralObjectClass: lspeople
-entryUUID: 239920bc-825b-1029-9abb-8f6e2b792dd2
-creatorsName: cn=anonymous
-createTimestamp: 20050706111627Z
 sambaNTPassword: 8DB716B655D71DF6BD056A41B22B9EA9
 sambaLMPassword: 6CE56DC112C920EF0F5E44C88BF9DC39
 givenName: Secretariat
 sn: Secretariat
 gidNumber: 70513
 mail: secretariat@ldapsaisie.biz
-maildrop: secretariat@ldapsaisie.biz
-vacationEnd: 20050101000000Z
-mailQuota: 52428800
-eeallowedservices: MAIL
-eeallowedservices: SAMBA
-eeallowedservices: FTP
+lsallowedservices: MAIL
+lsallowedservices: SAMBA
+lsallowedservices: FTP
 cn: Secretariat Secretariat
-mailbox: secretariat/
 sambaPrimaryGroupSID: S-1-5-21-2421470416-3566881284-3047381809-513
-entryCSN: 20050706144306.000000Z#000001#000#000000
-modifiersName: uid=eeggs,ou=people,o=ls
-modifyTimestamp: 20050706144306Z
 
 dn: uid=ls,ou=people,o=ls
 objectClass: top
@@ -364,192 +240,15 @@ sambaLMPassword: 6E72264E11F708C0AAD3B435B51404EE
 sambaNTPassword: 8D9B9B87EE8C0423691F4F0E00C5BDE1
 sambaSID: S-1-5-21-2421470416-3566881284-3047381809-203136
 structuralObjectClass: lspeople
-entryUUID: 23afa346-825b-1029-9ac3-8f6e2b792dd2
-creatorsName: cn=anonymous
-createTimestamp: 20050706111627Z
 givenName: _
 sn: LdapSaisie
 gidNumber: 102001
 mail: ls@ldapsaisie.biz
-maildrop: ls@ldapsaisie.biz
-vacationEnd: 20060101000000Z
-mailQuota: 52428800
-eeallowedservices: MAIL
-eeallowedservices: SAMBA
-eeallowedservices: FTP
+lsallowedservices: MAIL
+lsallowedservices: SAMBA
+lsallowedservices: FTP
 cn: LS
 sambaPrimaryGroupSID: S-1-5-21-2421470416-3566881284-3047381809-205003
-mailbox: ls/
-entryCSN: 20061212145541.000000Z#000001#000#000000
-modifiersName: uid=catbo,ou=people,o=ls
-modifyTimestamp: 20061212145541Z
-
-dn: cn=invite,ou=groups,o=ls
-objectClass: top
-objectClass: lsgroup
-objectClass: posixGroup
-objectClass: sambaGroupMapping
-cn: invite
-gidNumber: 101009
-sambaSID: S-1-5-21-2421470416-3566881284-3047381809-203019
-sambaGroupType: 2
-structuralObjectClass: lsgroup
-entryUUID: 2425636a-825b-1029-9ae1-8f6e2b792dd2
-creatorsName: cn=anonymous
-createTimestamp: 20050706111628Z
-entryCSN: 20070308165544.000000Z#000000#000#000000
-modifiersName: uid=eeggs,ou=people,o=ls
-modifyTimestamp: 20070308165544Z
-
-dn: cn=ls,ou=groups,o=ls
-objectClass: top
-objectClass: lsgroup
-objectClass: posixGroup
-objectClass: sambaGroupMapping
-cn: ls
-gidNumber: 102001
-sambaSID: S-1-5-21-2421470416-3566881284-3047381809-205003
-sambaGroupType: 2
-structuralObjectClass: lsgroup
-entryUUID: 242bef1e-825b-1029-9ae3-8f6e2b792dd2
-creatorsName: cn=anonymous
-createTimestamp: 20050706111628Z
-uniqueMember: uid=secretariat,ou=people,o=ls
-entryCSN: 20080211142555.171664Z#000000#000#000000
-modifiersName: uid=eeggs,ou=people,o=ls
-modifyTimestamp: 20080211142555Z
-
-dn: cn=informatique,ou=groups,o=ls
-objectClass: top
-objectClass: lsgroup
-objectClass: posixGroup
-objectClass: sambaGroupMapping
-gidNumber: 102009
-sambaSID: S-1-5-21-2421470416-3566881284-3047381809-205019
-sambaGroupType: 2
-structuralObjectClass: lsgroup
-entryUUID: 2438d9d6-825b-1029-9ae7-8f6e2b792dd2
-creatorsName: cn=anonymous
-createTimestamp: 20050706111628Z
-cn: informatique
-uniqueMember: uid=eeggs,ou=people,o=ls
-entryCSN: 20070309093000.000000Z#000000#000#000000
-modifiersName: uid=eeggs,ou=people,o=ls
-modifyTimestamp: 20070309093000Z
-
-dn: cn=direction,ou=groups,o=ls
-objectClass: top
-objectClass: lsgroup
-objectClass: posixGroup
-objectClass: sambaGroupMapping
-cn: direction
-gidNumber: 102007
-sambaSID: S-1-5-21-2421470416-3566881284-3047381809-205015
-sambaGroupType: 2
-structuralObjectClass: lsgroup
-entryUUID: 243f7a34-825b-1029-9ae9-8f6e2b792dd2
-creatorsName: cn=anonymous
-createTimestamp: 20050706111628Z
-entryCSN: 20070309093009.000000Z#000000#000#000000
-modifiersName: uid=eeggs,ou=people,o=ls
-modifyTimestamp: 20070309093009Z
-
-dn: cn=administratif,ou=groups,o=ls
-objectClass: top
-objectClass: lsgroup
-objectClass: posixGroup
-objectClass: sambaGroupMapping
-cn: administratif
-gidNumber: 102005
-sambaSID: S-1-5-21-2421470416-3566881284-3047381809-205011
-sambaGroupType: 2
-structuralObjectClass: lsgroup
-entryUUID: 245e0cb0-825b-1029-9af4-8f6e2b792dd2
-creatorsName: cn=anonymous
-createTimestamp: 20050706111628Z
-entryCSN: 20070308180424.000000Z#000001#000#000000
-modifiersName: uid=eeggs,ou=people,o=ls
-modifyTimestamp: 20070308180424Z
-
-dn: cn=communication,ou=groups,o=ls
-objectClass: top
-objectClass: lsgroup
-objectClass: posixGroup
-objectClass: sambaGroupMapping
-cn: communication
-gidNumber: 102003
-sambaSID: S-1-5-21-2421470416-3566881284-3047381809-205007
-sambaGroupType: 2
-structuralObjectClass: lsgroup
-entryUUID: 2460db34-825b-1029-9af5-8f6e2b792dd2
-creatorsName: cn=anonymous
-createTimestamp: 20050706111628Z
-entryCSN: 20070308180413.000000Z#000000#000#000000
-modifiersName: uid=eeggs,ou=people,o=ls
-modifyTimestamp: 20070308180413Z
-
-dn: uid=spam,ou=mailboxes,o=ls
-uid: spam
-userPassword: toto
-mailQuota: 104857600
-eeallowedservices: MAIL
-mail: spam@ldapsaisie.biz
-maildrop: spam@ldapsaisie.biz
-mailbox: spam/
-objectClass: top
-objectClass: lsmailbox
-structuralObjectClass: lsmailbox
-entryUUID: c88b9eb4-8301-1029-9567-dda2c03231d0
-creatorsName: uid=eeggs,ou=people,o=ls
-createTimestamp: 20050707070920Z
-entryCSN: 20050707070920.000000Z#000001#000#000000
-modifiersName: uid=eeggs,ou=people,o=ls
-modifyTimestamp: 20050707070920Z
-
-dn: uid=virus,ou=mailboxes,o=ls
-uid: virus
-userPassword: toto
-mailbox: virus/
-objectClass: top
-objectClass: lsmailbox
-structuralObjectClass: lsmailbox
-entryUUID: 974dac8c-8303-1029-9569-dda2c03231d0
-creatorsName: uid=eeggs,ou=people,o=ls
-createTimestamp: 20050707072216Z
-mailQuota: 104857600
-eeallowedservices: MAIL
-mail: virus@ldapsaisie.biz
-maildrop: virus@ldapsaisie.biz
-entryCSN: 20050707072249.000000Z#000001#000#000000
-modifiersName: uid=eeggs,ou=people,o=ls
-modifyTimestamp: 20050707072249Z
-
-dn: uid=gnarwl,ou=sysaccounts,o=ls
-objectClass: top
-objectClass: lssysaccount
-uid: gnarwl
-structuralObjectClass: lssysaccount
-entryUUID: f55954e0-fdcc-1029-9d72-de06c303d7ef
-creatorsName: uid=eeggs,ou=people,o=ls
-createTimestamp: 20051210133105Z
-userPassword: toto
-entryCSN: 20051210133237.000000Z#000001#000#000000
-modifiersName: uid=eeggs,ou=people,o=ls
-modifyTimestamp: 20051210133237Z
-
-dn: mail=informatique@ldapsaisie.biz,ou=aliases,o=ls
-objectClass: top
-objectClass: lsalias
-structuralObjectClass: lsalias
-entryUUID: 081e6612-fdd0-1029-9d73-de06c303d7ef
-creatorsName: uid=eeggs,ou=people,o=ls
-createTimestamp: 20051210135305Z
-mail: informatique@ldapsaisie.biz
-description: Service Informatique
-maildrop: eeggs@ldapsaisie.biz
-entryCSN: 20051210141428.000000Z#000001#000#000000
-modifiersName: uid=eeggs,ou=people,o=ls
-modifyTimestamp: 20051210141428Z
 
 dn: uid=erwpa,ou=people,o=ls
 uid: erwpa
@@ -563,42 +262,16 @@ homeDirectory: /home/erwpa
 loginShell: /bin/false
 sambaSID: S-1-5-21-2421470416-3566881284-3047381809-203164
 structuralObjectClass: lspeople
-entryUUID: aa7fcb30-b1a3-102a-875e-dcce935f6f2c
 sn: PAGEARD
 gidNumber: 102009
 mail: erwan.page@ldapsaisie.biz
-maildrop: erwan.page@ldapsaisie.biz
-vacationEnd: 20060101000000Z
-eeallowedservices: MAIL
-eeallowedservices: SAMBA
-eeallowedservices: FTP
+lsallowedservices: MAIL
+lsallowedservices: SAMBA
+lsallowedservices: FTP
 cn: Erwan PAGE
 sambaPrimaryGroupSID: S-1-5-21-2421470416-3566881284-3047381809-205019
-mailbox: erwpa/
 personalTitle: M.
 givenName: Erwan
 userPassword: toto
 sambaLMPassword: BAC14D04669EE1D1AAD3B435B51404EE
 sambaNTPassword: FBBF55D0EF0E34D39593F55C5F2CA5F2
-entryCSN: 20080211170049.821887Z#000000#000#000000
-modifiersName: uid=eeggs,ou=people,o=ls
-modifyTimestamp: 20080211170049Z
-
-dn: cn=test,ou=groups,o=ls
-cn: test
-description: test BR
-objectClass: top
-objectClass: lsgroup
-objectClass: sambaGroupMapping
-objectClass: posixGroup
-sambaGroupType: 2
-gidNumber: 102012
-sambaSID: 42
-structuralObjectClass: lsgroup
-entryUUID: 91b290d2-6117-102b-9c6f-91889acd20dc
-creatorsName: uid=eeggs,ou=people,o=ls
-createTimestamp: 20070307164933Z
-entryCSN: 20070308165811.000000Z#000000#000#000000
-modifiersName: uid=eeggs,ou=people,o=ls
-modifyTimestamp: 20070308165811Z
-
diff --git a/trunk/lsexample/permissions-ls.conf b/trunk/lsexample/permissions-ls.conf
index 908ef33d..b2cf8723 100644
--- a/trunk/lsexample/permissions-ls.conf
+++ b/trunk/lsexample/permissions-ls.conf
@@ -1,208 +1,94 @@
 ## Racine
 access to dn.regex="^o=ls$" attrs="entry,children,objectclass"
-	by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
-	by users read
-	by * read
-
-## Sysaccounts
-### Ajout d'entrees par les admins
-access to dn.regex="^ou=sysaccounts,o=ls$" attrs="children"
-	by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
-	by users read
-	by * none
-
-access to dn.regex="^uid=[^,]+,ou=sysaccounts,o=ls$" attrs="entry,objectclass"
-	by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
-	by users read
-	by * none
-
-### Les admins peuvent modifier le mot de passe, les autres peuvent s'en servir pour l'authentification
-access to dn.regex="^uid=[^,]+,ou=sysaccounts,o=ls$" attrs="userPassword"
-	by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
-	by anonymous auth
-	by * none
-	
-### Les admins peuvent modifier tous les attributs, les autres ne voient rien
-access to dn.regex="^uid=[^,]+,ou=sysaccounts,o=ls$"
-	by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
-	by * none
-
-## Aliases
-### Ajout d'entrees par les admins
-access to dn.regex="^ou=aliases,o=ls$" attrs="children,objectclass"
-	by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
-	by * read
-
-access to dn.regex="^mail=[^,]+,ou=aliases,o=ls$" attrs="entry,objectclass"
-	by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
-	by * read
-
-### Les admins peuvent modifier tous les attributs, tout le monde peut voir
-access to dn.regex="^mail=[^,]+,ou=aliases,o=ls$"
-	by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
-	by * read
-
-## Mailboxes
-### Ajout d'entrees par les admins
-access to dn.regex="^ou=mailboxes,o=ls$" attrs="children,objectclass"
-	by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
-	by * read
-
-access to dn.regex="^uid=[^,]+,ou=mailboxes,o=ls$" attrs="entry,objectclass"
-	by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
-	by * read
-
-### Les admins peuvent modifier le mot de passe, les autres peuvent s'en servir pour l'authentification
-access to dn.regex="^uid=[^,]+,ou=mailboxes,o=ls$" attrs="userPassword"
-	by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
-	by anonymous auth
-	by * none
-	
-### Les admins peuvent modifier ces attributs, l'appli mail le voir, les autres aucun droits
-access to dn.regex="^uid=[^,]+,ou=mailboxes,o=ls$" attrs="mailbox,mailforwardingaddress"
-	by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
-	by dn="uid=mail,ou=sysaccounts,o=ls" read
-	by * none
-
-### Les admins peuvent modifier ces attributs, les authentifies peuvent les voir
-access to dn.regex="^uid=[^,]+,ou=mailboxes,o=ls$" attrs="uid,description,mail,mailalternateaddress,mailquota,eeallowedservices"
-	by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
-	by * read
+  by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
+  by dn="uid=ldapsaisie,ou=sysaccounts,o=ls" write
+  by users read
+  by * read
 
 ## Groups
 ### Ajout d'entrees par les admins
 access to dn.regex="^ou=groups,o=ls$" attrs="children,objectclass"
-	by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
-	by users read
-	by * none
+  by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
+  by dn="uid=ldapsaisie,ou=sysaccounts,o=ls" write
+  by users read
+  by * none
 
 access to dn.regex="^cn=[^,]+,ou=groups,o=ls$" attrs="entry,objectclass"
-	by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
-	by users read
-	by * none
+  by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
+  by dn="uid=ldapsaisie,ou=sysaccounts,o=ls" write
+  by users read
+  by * none
 
 ### Les admins peuvent tout modifier, les authentifies peuvent tout voir
 access to dn.regex="^cn=[^,]+,ou=groups,o=ls$"
-	by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
-	by users read
-	by * none
+  by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
+  by dn="uid=ldapsaisie,ou=sysaccounts,o=ls" write
+  by users read
+  by * none
 
 
 ## Peoples
 ### Ajout d'entrees par les admins
 access to dn.regex="^ou=people,o=ls$" attrs="children,objectclass"
-	by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
-	by users read
-	by * read
+  by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
+  by dn="uid=ldapsaisie,ou=sysaccounts,o=ls" write
+  by users read
+  by * read
 
 access to dn.regex="^uid=[^,]+,ou=people,o=ls$" attrs="entry,objectclass"
-	by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
-	by users read
-	by * read
+  by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
+  by dn="uid=ldapsaisie,ou=sysaccounts,o=ls" write
+  by users read
+  by * read
 
 
 ### Les admins peuvent modifier le mot de passe, samba le mettre à jour, les autres peuvent s'en servir pour l'authentification
 access to dn.regex="^uid=[^,]+,ou=people,o=ls$" attrs="userPassword"
-	by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
-	by dn="uid=samba,ou=sysaccounts,o=ls" write
-	by self write
-	by anonymous auth
-	by * none
-	
-### Les admins peuvent modifier ces attributs, l'appli mail les voir, les autres aucun droits
-access to dn.regex="^uid=[^,]+,ou=people,o=ls$" attrs="mailbox"
-	by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
-	by dn="uid=mail,ou=sysaccounts,o=ls" read
-	by * none
+  by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
+  by dn="uid=samba,ou=sysaccounts,o=ls" write
+  by dn="uid=ldapsaisie,ou=sysaccounts,o=ls" write
+  by self write
+  by anonymous auth
+  by * none
+
+access to dn.regex="^uid=[^,]+,ou=sysaccounts,o=ls$" attrs="userPassword"
+  by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
+  by dn="uid=ldapsaisie,ou=sysaccounts,o=ls" write
+  by anonymous auth
+  by * none
 
 ### Les admins peuvent modifier ces attributs, les authentifies peuvent les voir
-access to dn.regex="^uid=[^,]+,ou=people,o=ls$" attrs="uid,mailquota,eeallowedservices,uidNumber,gidNumber,homeDirectory,loginShell,sambaSID,sambaAcctFlags,sambaPrimaryGroupSID"
-	by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
-	by users read
-	by * none
-
-### Les admins peuvent modifier ces attributs, le proprio aussi, gnarwl peut les modifier et mail les voir
-access to dn.regex="^uid=[^,]+,ou=people,o=ls$" attrs="mailforwardingaddress"
-	by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
-	by dn="uid=gnarwl,ou=sysaccounts,o=ls" write
-	by self write
-	by dn="uid=mail,ou=sysaccounts,o=ls" read
-	by * none
-
-### Les admins peuvent modifier ces attributs, le proprio aussi, les authentifies peuvent les voir, gnarwl peut les modifier
-access to dn.regex="^uid=[^,]+,ou=people,o=ls$" attrs="vacationActive"
-	by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
-	by dn="uid=gnarwl,ou=sysaccounts,o=ls" write
-	by self write
-	by users read
-	by * none
-
-### Les admins peuvent modifier ces attributs, le proprio aussi, mail et gnarwl peuvent les voir
-access to dn.regex="^uid=[^,]+,ou=people,o=ls$" attrs="vacationForward"
-	by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
-	by self write
-	by dn="uid=mail,ou=sysaccounts,o=ls" read
-	by dn="uid=gnarwl,ou=sysaccounts,o=ls" read
-	by * none
+access to dn.regex="^uid=[^,]+,ou=people,o=ls$" attrs="uid,lsallowedservices,uidNumber,gidNumber,homeDirectory,loginShell,sambaSID,sambaAcctFlags,sambaPrimaryGroupSID"
+  by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
+  by dn="uid=ldapsaisie,ou=sysaccounts,o=ls" write
+  by users read
+  by * none
 
 ### Les admins peuvent modifier ces attributs, le proprio aussi, samba aussi
 access to dn.regex="^uid=[^,]+,ou=people,o=ls$" attrs="sambaLMPassword,sambaNTPassword"
-	by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
-	by dn="uid=samba,ou=sysaccounts,o=ls" write
-	by self write
-	by * none
+  by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
+  by dn="uid=ldapsaisie,ou=sysaccounts,o=ls" write
+  by dn="uid=samba,ou=sysaccounts,o=ls" write
+  by self write
+  by * none
 
 ### Les admins peuvent modifier ces attributs, le proprio aussi, les authentifies peuvent les voir
-access to dn.regex="^uid=[^,]+,ou=people,o=ls$" attrs="c,cn,jpegPhoto,personalTitle,sn,givenName,postalAddress,postalCode,l,st,telephoneNumber,mobile,fax,mail,mailalternateaddress,maildrop,description,vacationInfo,vacationEnd"
-	by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
-	by self write
-	by users read
-	by * read
-
-## Computers
-### Ajout d'entrees par les admins
-access to dn.regex="^ou=computers,o=ls$" attrs="children,objectclass"
-	by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
-	by dn="uid=samba,ou=sysaccounts,o=ls" write
-	by users read
-	by * none
-
-access to dn.regex="^uid=[^,]+,ou=computers,o=ls$" attrs="entry,objectclass"
-	by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
-	by dn="uid=samba,ou=sysaccounts,o=ls" write
-	by users read
-	by * none
-
-
-### Les admins peuvent modifier ces attributs, samba peut les voir
-access to dn.regex="^uid=[^,]+,ou=computers,o=ls$" attrs="sambaLMPassword,sambaNTPassword"
-	by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
-	by dn="uid=samba,ou=sysaccounts,o=ls" write
-	by * none
-
-### Les admins peuvent modifier ces attributs, les authentifiés peuvent les voir
-access to dn.regex="^uid=[^,]+,ou=computers,o=ls$" attrs="cn,uid,uidNumber,gidNumber,homeDirectory,sambaSID,sambaPrimaryGroupSID,sambaAcctFlags,sambaPwdCanChange,sambaPwdMustChange,sambaPwdLastSet"
-	by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
-	by dn="uid=samba,ou=sysaccounts,o=ls" write
-	by users read
-	by * none
-
+access to dn.regex="^uid=[^,]+,ou=people,o=ls$" attrs="c,cn,jpegPhoto,personalTitle,sn,givenName,postalAddress,postalCode,l,st,telephoneNumber,mobile,fax,mail,description"
+  by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
+  by dn="uid=ldapsaisie,ou=sysaccounts,o=ls" write
+  by self write
+  by users read
+  by * read
 
 ## Les authentifies peuvent voir les noeuds et les admins peuvent en ajouter
 access to * attrs="entry"
-	by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
-	by users read
-	by * none
-
-## SambaDomains
-### Ajout d'entrees par les admins
-access to dn.regex="^ou=sambadomains,o=ls$"
-	by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
-	by dn="uid=samba,ou=sysaccounts,o=ls" read
-	by users read
-	by * none
+  by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
+  by dn="uid=ldapsaisie,ou=sysaccounts,o=ls" write
+  by users read
+  by * none
 
 ## Le reste
 access to *
-	by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
-	by * none
+  by group/lsgroup/uniqueMember="cn=adminldap,ou=groups,o=ls" write
+  by dn="uid=ldapsaisie,ou=sysaccounts,o=ls" write
+  by * none
diff --git a/trunk/lsexample/slapd.conf b/trunk/lsexample/slapd.conf
index a1c47915..5098dc2c 100644
--- a/trunk/lsexample/slapd.conf
+++ b/trunk/lsexample/slapd.conf
@@ -1,3 +1,4 @@
+# LSexample - Config
 include		/etc/ldap/schema/ls.schema
 
 
@@ -14,10 +15,9 @@ index objectClass eq
 index uid pres,eq
 index uidNumber eq
 index gidNumber eq
-index eeallowedservices eq
+index lsallowedservices eq
 index cn pres,eq
 index mail pres,eq
-index mailalternateaddress pres,eq
 index sambasid eq
 index sambaDomainName eq
 index memberUid eq
diff --git a/trunk/templates/css/login.css b/trunk/templates/css/login.css
index b8373749..d3e839be 100644
--- a/trunk/templates/css/login.css
+++ b/trunk/templates/css/login.css
@@ -53,3 +53,11 @@ dl.loginform {
   float:                  right;
   margin-left:            1em;
 }
+
+#LSsession_lostPassword {
+  float:                  right;
+  font-size:              0.8em;
+  text-decoration:        none;
+  color:                  #69c;
+  font-weight:            bold;
+}
diff --git a/trunk/templates/css/recoverpassword.css b/trunk/templates/css/recoverpassword.css
new file mode 100644
index 00000000..ec9b0027
--- /dev/null
+++ b/trunk/templates/css/recoverpassword.css
@@ -0,0 +1,60 @@
+#recoverpasswordform-logo {
+  float:                  left;
+}
+
+div.recoverpasswordform {
+  margin:                 auto;
+  margin-top:             10%;
+  border:                 1px solid #69c;
+  padding:                1em;
+  width:                  30em;
+  background:             transparent url(../images/login_fd.png) no-repeat scroll 98% 98%;
+}
+
+dl.recoverpasswordform {
+  margin:                 0;
+  padding:                0;
+}
+
+.recoverpasswordform dt {
+  position:               relative;
+  left:                   0;
+  top:                    1.1em;
+  width:                  8em;
+  font-weight:            bold;
+  font-size:              0.9em;
+}
+
+.recoverpasswordform dd {
+  margin:                 0 0 0 9em;
+  padding:                0 0 0em 0em;
+}
+
+.recoverpasswordform input, .recoverpasswordform select {
+  border:                 1px inset #ccc;
+  width:                  13em;
+}
+
+.recoverpasswordform input[type='submit'] {
+  border:                 1px outset #ccc;
+  width:                  11em;
+  margin:                 1em;
+}
+
+#loading_zone {
+  float:                  right;
+  margin-left:            1em;
+}
+
+#recoverpassword_msg {
+  text-align:             center;
+  font-weight:            bold;
+}
+
+#recoverpassword_back {
+  float:                  right;
+  font-size:              0.8em;
+  text-decoration:        none;
+  color:                  #69c;
+  font-weight:            bold;
+}
diff --git a/trunk/templates/login.tpl b/trunk/templates/login.tpl
index 85480292..b46e80d1 100644
--- a/trunk/templates/login.tpl
+++ b/trunk/templates/login.tpl
@@ -2,6 +2,7 @@
  "http://www.w3.org/TR/html4/loose.dtd">
 <html>
   <head>
+    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
     <title>LdapSaisie{if $pagetitle != ''} - {$pagetitle}{/if}</title>
     <link rel="stylesheet" type="text/css" href="templates/css/login.css" media="screen" title="Normal" />
     {$LSsession_css}
@@ -33,6 +34,7 @@
   <dd><input type='submit' value='{$loginform_label_submit}' /></dd>
 </dl>
 </form>
+<a href='index.php?LSsession_recoverPassword' id='LSsession_lostPassword'>{$loginform_label_lostpassword}</a>
 </div>
 </body>
 </html>
diff --git a/trunk/templates/recoverpassword.tpl b/trunk/templates/recoverpassword.tpl
new file mode 100644
index 00000000..8b5332b6
--- /dev/null
+++ b/trunk/templates/recoverpassword.tpl
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+  <head>
+    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+    <title>LdapSaisie{if $pagetitle != ''} - {$pagetitle}{/if}</title>
+    <link rel="stylesheet" type="text/css" href="templates/css/recoverpassword.css" media="screen" title="Normal" />
+    {$LSsession_css}
+    {$LSsession_js}
+  </head>
+<body>
+<div id='LSerror'>
+{$LSerrors}
+</div>
+<div id='LSdebug'>
+  <a href='#' id='LSdebug_hidden'>X</a> 
+  <div id='LSdebug_infos'>{if $LSdebug != ''}{$LSdebug}{/if}</div>
+</div>
+<div class='recoverpasswordform'>
+<img src='templates/images/logo.png' alt='Logo' id='recoverpasswordform_logo' />
+<div id='loading_zone'></div>
+<form action='{$recoverpasswordform_action}' method='post'>
+<dl class='recoverpasswordform'>
+  <dt {$recoverpasswordform_ldapserver_style}>{$recoverpasswordform_label_ldapserver}</dt>
+  <dd {$recoverpasswordform_ldapserver_style}>
+    <select name='LSsession_ldapserver' id='LSsession_ldapserver'>{html_options values=$recoverpasswordform_ldapservers_index output=$recoverpasswordform_ldapservers_name selected=$ldapServerId}</select>
+  </dd>
+  <dt>{$recoverpasswordform_label_user}</dt>
+  <dd><input type='text' name='LSsession_user' /></dd>
+  <dd><input type='submit' value='{$recoverpasswordform_label_submit}' /></dd>
+</dl>
+</form>
+
+{if recoverpassword_msg!=''}
+  <p id='recoverpassword_msg'>{$recoverpassword_msg}</p>
+{/if}
+
+<a href='index.php' id='recoverpassword_back'>{$recoverpasswordform_label_back}</a>
+</div>
+</body>
+</html>