Permit LSaddon to provide ajax callable function
[ldapsaisie.git] / public_html / includes / class / class.LSsession.php
index 1520ebf..559dddf 100644 (file)
@@ -50,9 +50,6 @@ class LSsession {
   // Les droits d'accès de l'utilisateur
   private static $LSaccess = array();
   
-  // Authentification parameters
-  private static $authParams = array();
-  
   // Les fichiers temporaires
   private static $tmp_file = array();
   
@@ -87,6 +84,9 @@ class LSsession {
   // The LSauht object of the session
   private static $LSauthObject = false;
 
+  // User LDAP credentials
+  private static $userLDAPcreds = false;
+
  /**
   * Include un fichier PHP
   *
@@ -95,7 +95,10 @@ class LSsession {
   * @retval true si tout c'est bien passé, false sinon
   */
   public static function includeFile($file) {
-    if (!file_exists($file)) {
+    if (file_exists(LS_LOCAL_DIR.'/'.$file)) {
+      $file=LS_LOCAL_DIR.'/'.$file;
+    }
+    elseif (!file_exists($file)) {
       return;
     }
     if (defined('LSdebug') && constant('LSdebug')) {
@@ -132,33 +135,20 @@ class LSsession {
   * @retval true si tout c'est bien passé, false sinon
   */  
   private static function startLStemplate() {
-    if ( self :: includeFile(LSconfig :: get('Smarty')) ) {
-      $GLOBALS['Smarty'] = new Smarty();
-      $GLOBALS['Smarty'] -> template_dir = LS_TEMPLATES_DIR;
-      $GLOBALS['Smarty'] -> compile_dir = LS_TMP_DIR;
-      
-      if (LSdebug) {
-        $GLOBALS['Smarty'] -> caching = 0;
-        // cache files are always regenerated
-        $GLOBALS['Smarty'] -> force_compile = TRUE;
-        // recompile template if it is changed
-        $GLOBALS['Smarty'] -> compile_check = TRUE;
-        if (isset($_REQUEST['debug_smarty'])) {
-          // debug smarty
-          $GLOBALS['Smarty'] -> debugging = true; 
-        }
-      }
-
-      $GLOBALS['Smarty'] -> register_function('getFData','smarty_getFData');
-      
-      $GLOBALS['Smarty'] -> assign('LS_CSS_DIR',LS_CSS_DIR);
-      $GLOBALS['Smarty'] -> assign('LS_IMAGES_DIR',LS_IMAGES_DIR);
-      
-      self :: addJSconfigParam('LS_IMAGES_DIR',LS_IMAGES_DIR);
-      return true;
+    if ( self :: loadLSclass('LStemplate') ) {
+      return LStemplate :: start(
+        array(
+          'smarty_path'  => LSconfig :: get('Smarty'),
+          'template_dir' => LS_TEMPLATES_DIR,
+          'image_dir'    => LS_IMAGES_DIR,
+          'css_dir'    => LS_CSS_DIR,
+          'compile_dir'  => LS_TMP_DIR,
+          'debug'        => LSdebug,
+          'debug_smarty' => (isset($_REQUEST['LStemplate_debug'])),
+        )
+      );
     }
-    die("ERROR : Can't load Smarty.");
-    return;
+    return False;
   }
   
  /**
@@ -201,6 +191,7 @@ class LSsession {
     if(!self :: loadLSclass('LSerror')) {
       return;
     }
+    set_error_handler(array('LSerror','errorHandler'),E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED & ~E_WARNING);
     self :: defineLSerrors();
     return true;
   }
@@ -292,23 +283,13 @@ class LSsession {
  /**
   * Chargement d'une classe d'authentification d'LdapSaisie
   *
-  * @param[in] $auth Nom de la classe d'authentification a charger (Exemple : HTTP)
-  *
   * @author Benjamin Renard <brenard@easter-eggs.com
   * 
   * @retval boolean true si le chargement a reussi, false sinon.
   */
-  public static function loadLSauth($auth=false) {
+  public static function loadLSauth() {
     if (self :: loadLSclass('LSauth')) {
-      if ($auth) {
-        if(self :: includeFile(LS_CLASS_DIR .'class.LSauth'.$auth.'.php')) {
-          self :: includeFile(LS_CONF_DIR."LSauth/config.LSauth".$auth.".php");
-          return true;
-        }
-      }
-      else {
-        return true;
-      } 
+      return true;
     }
     else {
       LSerror :: addErrorCode('LSsession_05','LSauth');
@@ -383,8 +364,10 @@ class LSsession {
       bindtextdomain(LS_TEXT_DOMAIN, LS_I18N_DIR);
       textdomain(LS_TEXT_DOMAIN);
       
-      if (is_file(LS_I18N_DIR.'/'.$lang.'/lang.php')) {
-        include(LS_I18N_DIR.'/'.$lang.'/lang.php');
+      self :: includeFile(LS_I18N_DIR.'/'.$lang.'/lang.php');
+
+      foreach (listFiles(LS_LOCAL_DIR.'/'.LS_I18N_DIR.'/'.$lang,'/^lang.+\.php$/') as $file) {
+        include(LS_LOCAL_DIR.'/'.LS_I18N_DIR."/$lang/$file");
       }
     }
     else {
@@ -461,18 +444,24 @@ class LSsession {
   * @retval boolean True si l'initialisation à réussi, false sinon.
   */
   public static function initialize() {
-    if (!self :: startLSconfig()) {
-      return;
+    try {
+      if (!self :: startLSconfig()) {
+        return;
+      }
+
+      self :: startLSerror();
+      self :: startLStemplate();
+
+      session_start();
+
+      self :: setLocale();
+
+      self :: loadLSaddons();
+      self :: loadLSauth();
+    }
+    catch (Exception $e) {
+      die('LSsession : fail to initialize session. Error : '.$e->getMessage());
     }
-    
-    self :: startLStemplate();
-    
-    session_start();
-    
-    self :: setLocale();
-    
-    self :: startLSerror();
-    self :: loadLSaddons();
     return true;
   }
 
@@ -493,16 +482,21 @@ class LSsession {
     }
     
     if(isset($_SESSION['LSsession']['dn']) && !isset($_GET['LSsession_recoverPassword'])) {
-      // Session existante
-      self :: $topDn        = $_SESSION['LSsession']['topDn'];
-      self :: $dn           = $_SESSION['LSsession']['dn'];
-      self :: $rdn          = $_SESSION['LSsession']['rdn'];
-      self :: $ldapServerId = $_SESSION['LSsession']['ldapServerId'];
-      self :: $tmp_file     = $_SESSION['LSsession']['tmp_file'];
-      self :: $authParams   = $_SESSION['LSsession']['authParams'];
+      LSdebug('LSsession : Session existente'); 
+      // --------------------- Session existante --------------------- //
+      self :: $topDn         = $_SESSION['LSsession']['topDn'];
+      self :: $dn            = $_SESSION['LSsession']['dn'];
+      self :: $rdn           = $_SESSION['LSsession']['rdn'];
+      self :: $ldapServerId  = $_SESSION['LSsession']['ldapServerId'];
+      self :: $tmp_file      = $_SESSION['LSsession']['tmp_file'];
+      self :: $userLDAPcreds = $_SESSION['LSsession']['userLDAPcreds'];
       
       if ( self :: cacheLSprofiles() && !isset($_REQUEST['LSsession_refresh']) ) {
         self :: setLdapServer(self :: $ldapServerId);
+        if (!LSauth :: start()) {
+          LSdebug("LSsession : can't start LSauth -> stop");
+          return;
+        }
         self :: $LSprofiles   = $_SESSION['LSsession']['LSprofiles'];
         self :: $LSaccess   = $_SESSION['LSsession']['LSaccess'];
         if (!self :: LSldapConnect())
@@ -510,6 +504,10 @@ class LSsession {
       }
       else {
         self :: setLdapServer(self :: $ldapServerId);
+        if (!LSauth :: start()) {
+          LSdebug("LSsession : can't start LSauth -> stop");
+          return;
+        }
         if (!self :: LSldapConnect())
           return;
         self :: loadLSprofiles();
@@ -524,10 +522,7 @@ class LSsession {
       }
       
       if (isset($_GET['LSsession_logout'])) {
-        $authObj = self :: getLSauthObject();
-        if ($authObj) {
-          $authObj -> logout();
-        }
+        LSauth :: logout();
         session_destroy();
         
         if (is_array($_SESSION['LSsession']['tmp_file'])) {
@@ -540,13 +535,11 @@ class LSsession {
         return;
       }
       
-      self :: getLSuserObject();
-      
       if ( !self :: cacheLSprofiles() || isset($_REQUEST['LSsession_refresh']) ) {
         self :: loadLSaccess();
       }
       
-      $GLOBALS['Smarty'] -> assign('LSsession_username',self :: getLSuserObject() -> getDisplayName());
+      LStemplate :: assign('LSsession_username',self :: getLSuserObject() -> getDisplayName());
       
       if (isset ($_POST['LSsession_topDn']) && $_POST['LSsession_topDn']) {
         if (self :: validSubDnLdapServer($_POST['LSsession_topDn'])) {
@@ -559,6 +552,7 @@ class LSsession {
       
     }
     else {
+      // --------------------- Session inexistante --------------------- //
       if (isset($_GET['LSsession_recoverPassword'])) {
         session_destroy();
       }
@@ -574,14 +568,19 @@ class LSsession {
       if (self :: LSldapConnect()) {
 
         // topDn
-        if ( $_POST['LSsession_topDn'] != '' ){
+        if (isset($_POST['LSsession_topDn']) && $_POST['LSsession_topDn'] != '' ){
           self :: $topDn = $_POST['LSsession_topDn'];
         }
         else {
           self :: $topDn = self :: $ldapServer['ldap_config']['basedn'];
         }
         $_SESSION['LSsession_topDn']=self :: $topDn;
-
+       
+        if (!LSauth :: start()) {
+          LSdebug("LSsession : can't start LSauth -> stop");
+          return;
+        }
+        
         if (isset($_GET['LSsession_recoverPassword'])) {
           $recoveryPasswordInfos = self :: recoverPasswd(
                                       $_REQUEST['LSsession_user'],
@@ -589,22 +588,29 @@ class LSsession {
                                    );
         }
         else {
-          $authObj=self :: getLSauthObject();
-          if ($authObj) {
-            if ($authObj -> getPostData()) {
-              $LSuserObject = $authObj -> authenticate();
-              if ($LSuserObject) {
-                // Authentication successful
-                self :: $LSuserObject = $LSuserObject;
-                self :: $dn = $LSuserObject->getValue('dn');
-                self :: $rdn = $LSuserObject->getValue('rdn');
-                self :: loadLSprofiles();
-                self :: loadLSaccess();
-                $GLOBALS['Smarty'] -> assign('LSsession_username',self :: getLSuserObject() -> getDisplayName());
-                $_SESSION['LSsession']=self :: getContextInfos();
-                return true;
+          $LSuserObject = LSauth :: forceAuthentication();
+          if ($LSuserObject) {
+            // Authentication successful
+            self :: $LSuserObject = $LSuserObject;
+            self :: $dn = $LSuserObject->getValue('dn');
+            self :: $rdn = $LSuserObject->getValue('rdn');
+            if (isset(self :: $ldapServer['useUserCredentials']) && self :: $ldapServer['useUserCredentials']) {
+              self :: $userLDAPcreds = LSauth :: getLDAPcredentials($LSuserObject);
+              if (!is_array(self :: $userLDAPcreds)) {
+                LSerror :: addErrorCode('LSsession_14');
+                self :: $userLDAPcreds = false;
+                return;
+              }
+              if (!LSldap :: reconnectAs(self :: $userLDAPcreds['dn'],self :: $userLDAPcreds['pwd'])) {
+                LSerror :: addErrorCode('LSsession_15');
+                return;
               }
             }
+            self :: loadLSprofiles();
+            self :: loadLSaccess();
+            LStemplate :: assign('LSsession_username',self :: getLSuserObject() -> getDisplayName());
+            $_SESSION['LSsession']=self :: getContextInfos();
+            return true;
           }
         }
       }
@@ -613,13 +619,13 @@ class LSsession {
       }
       
       if (self :: $ldapServerId) {
-        $GLOBALS['Smarty'] -> assign('ldapServerId',self :: $ldapServerId);
+        LStemplate :: assign('ldapServerId',self :: $ldapServerId);
       }
-      $GLOBALS['Smarty'] -> assign('topDn',self :: $topDn);
+      LStemplate :: assign('topDn',self :: $topDn);
       if (isset($_GET['LSsession_recoverPassword'])) {
         self :: displayRecoverPasswordForm($recoveryPasswordInfos);
       }
-      elseif(self :: $authParams['displayLoginForm']) {
+      elseif(LSauth :: displayLoginForm()) {
         self :: displayLoginForm();
       }
       else {
@@ -629,32 +635,6 @@ class LSsession {
       return;
     }
   }
-
-  /**
-   * Get LSauthObject
-   * 
-   * @retval LSauth object or false
-   **/
-  private static function getLSauthObject() {
-    if (!self :: $LSauthObject) {
-      if (self :: loadLSauth()) {
-        if (isset(self :: $ldapServer['LSauth']['method'])) {
-          $LSauthClass = 'LSauth'.self :: $ldapServer['LSauth']['method'];
-          if (!self :: loadLSauth(self :: $ldapServer['LSauth']['method'])) {
-            LSerror :: addErrorCode('LSsession_08',self :: $ldapServer['LSauth']['method']);
-            $LSauthClass = 'LSauth';
-          }
-        }
-        else {
-          $LSauthClass = 'LSauth';
-        }
-        
-        self :: $LSauthObject = new $LSauthClass();
-        self :: $authParams = self :: $LSauthObject->params;
-      }
-    }
-    return self :: $LSauthObject;
-  }     
   
   /**
    * Do recover password
@@ -893,11 +873,11 @@ class LSsession {
       'topDn' => self :: $topDn,
       'dn' => self :: $dn,
       'rdn' => self :: $rdn,
+      'userLDAPcreds' => self :: $userLDAPcreds,
       'ldapServerId' => self :: $ldapServerId,
       'ldapServer' => self :: $ldapServer,
       'LSprofiles' => self :: $LSprofiles,
-      'LSaccess' => self :: $LSaccess,
-      'authParams' => self :: $authParams
+      'LSaccess' => self :: $LSaccess
     );
   }
   
@@ -980,6 +960,7 @@ class LSsession {
       self :: $ldapServerId = $id;
       self :: $ldapServer = $conf;
       self :: setLocale();
+      self :: setGlobals();
       return true;
     }
     else {
@@ -998,7 +979,12 @@ class LSsession {
       if (!self :: loadLSclass('LSldap')) {
         return;
       }
-      LSldap :: connect(self :: $ldapServer['ldap_config']);
+      if (self :: $dn && isset(self :: $ldapServer['useUserCredentials']) && self :: $ldapServer['useUserCredentials']) {
+        LSldap :: reconnectAs(self :: $userLDAPcreds['dn'], self :: $userLDAPcreds['pwd'],self :: $ldapServer['ldap_config']);
+      }
+      else {
+        LSldap :: connect(self :: $ldapServer['ldap_config']);
+      }
       if (LSldap :: isConnected()) {
         return true;
       }
@@ -1032,25 +1018,27 @@ class LSsession {
   *
   * @retval mixed Tableau des subDn, false si une erreur est survenue.
   */
-  public static function getSubDnLdapServer() {
-    if (self :: cacheSudDn() && isset(self :: $_subDnLdapServer[self :: $ldapServerId])) {
-      return self :: $_subDnLdapServer[self :: $ldapServerId];
+  public static function getSubDnLdapServer($login=false) {
+    $login=(bool)$login;
+    if (self :: cacheSudDn() && isset(self :: $_subDnLdapServer[self :: $ldapServerId][$login])) {
+      return self :: $_subDnLdapServer[self :: $ldapServerId][$login];
     }
     if (!self::subDnIsEnabled()) {
       return;
     }
     $return=array();
     foreach(self :: $ldapServer['subDn'] as $subDn_name => $subDn_config) {
+      if ($login && isset($subDn_config['nologin']) && $subDn_config['nologin']) continue;
       if ($subDn_name == 'LSobject') {
         if (is_array($subDn_config)) {
           foreach($subDn_config as $LSobject_name => $LSoject_config) {
-            if ($LSoject_config['basedn']) {
+            if (isset($LSoject_config['basedn']) && !empty($LSoject_config['basedn'])) {
               $basedn = $LSoject_config['basedn'];
             }
             else {
               $basedn = self::getRootDn();
             }
-            if ($LSoject_config['displayName']) {
+            if (isset($LSoject_config['displayName']) && !empty($LSoject_config['displayName'])) {
               $displayName = $LSoject_config['displayName'];
             }
             else {
@@ -1083,7 +1071,7 @@ class LSsession {
       }
     }
     if (self :: cacheSudDn()) {
-      self :: $_subDnLdapServer[self :: $ldapServerId]=$return;
+      self :: $_subDnLdapServer[self :: $ldapServerId][$login]=$return;
       $_SESSION['LSsession_subDnLdapServer'] = self :: $_subDnLdapServer;
     }
     return $return;
@@ -1095,8 +1083,8 @@ class LSsession {
    * 
    * @return array() Tableau des subDn trié
    */  
-  public static function getSortSubDnLdapServer() {
-    $subDnLdapServer = self :: getSubDnLdapServer();
+  public static function getSortSubDnLdapServer($login=false) {
+    $subDnLdapServer = self :: getSubDnLdapServer($login);
     if (!$subDnLdapServer) {
       return array();
     }
@@ -1112,8 +1100,8 @@ class LSsession {
   *
   * @retval string Les options (<option>) pour la sélection du topDn.
   */
-  public static function getSubDnLdapServerOptions($selected=NULL) {
-    $list = self :: getSubDnLdapServer();
+  public static function getSubDnLdapServerOptions($selected=NULL,$login=false) {
+    $list = self :: getSubDnLdapServer($login);
     if ($list) {
       asort($list);
       $display='';
@@ -1172,31 +1160,31 @@ class LSsession {
   * @retval void
   */
   public static function displayLoginForm() {
-    $GLOBALS['Smarty'] -> assign('pagetitle',_('Connection'));
+    LStemplate :: assign('pagetitle',_('Connection'));
     if (isset($_GET['LSsession_logout'])) {
-      $GLOBALS['Smarty'] -> assign('loginform_action','index.php');
+      LStemplate :: assign('loginform_action','index.php');
     }
     else {
-      $GLOBALS['Smarty'] -> assign('loginform_action',$_SERVER['REQUEST_URI']);
+      LStemplate :: assign('loginform_action',$_SERVER['REQUEST_URI']);
     }
     if (count(LSconfig :: get('ldap_servers'))==1) {
-      $GLOBALS['Smarty'] -> assign('loginform_ldapserver_style','style="display: none"');
+      LStemplate :: assign('loginform_ldapserver_style','style="display: none"');
     }
-    $GLOBALS['Smarty'] -> assign('loginform_label_ldapserver',_('LDAP server'));
+    LStemplate :: assign('loginform_label_ldapserver',_('LDAP server'));
     $ldapservers_name=array();
     $ldapservers_index=array();
     foreach(LSconfig :: get('ldap_servers') as $id => $infos) {
       $ldapservers_index[]=$id;
       $ldapservers_name[]=__($infos['name']);
     }
-    $GLOBALS['Smarty'] -> assign('loginform_ldapservers_name',$ldapservers_name);
-    $GLOBALS['Smarty'] -> assign('loginform_ldapservers_index',$ldapservers_index);
+    LStemplate :: assign('loginform_ldapservers_name',$ldapservers_name);
+    LStemplate :: assign('loginform_ldapservers_index',$ldapservers_index);
 
-    $GLOBALS['Smarty'] -> assign('loginform_label_level',_('Level'));
-    $GLOBALS['Smarty'] -> assign('loginform_label_user',_('Identifier'));
-    $GLOBALS['Smarty'] -> assign('loginform_label_pwd',_('Password'));
-    $GLOBALS['Smarty'] -> assign('loginform_label_submit',_('Connect'));
-    $GLOBALS['Smarty'] -> assign('loginform_label_recoverPassword',_('Forgot your password ?'));
+    LStemplate :: assign('loginform_label_level',_('Level'));
+    LStemplate :: assign('loginform_label_user',_('Identifier'));
+    LStemplate :: assign('loginform_label_pwd',_('Password'));
+    LStemplate :: assign('loginform_label_submit',_('Connect'));
+    LStemplate :: assign('loginform_label_recoverPassword',_('Forgot your password ?'));
     
     self :: setTemplate('login.tpl');
     self :: addJSscript('LSsession_login.js');
@@ -1214,26 +1202,26 @@ class LSsession {
   * @retval void
   */
   public static function displayRecoverPasswordForm($recoveryPasswordInfos) {
-    $GLOBALS['Smarty'] -> assign('pagetitle',_('Recovery of your credentials'));
-    $GLOBALS['Smarty'] -> assign('recoverpasswordform_action','index.php?LSsession_recoverPassword');
+    LStemplate :: assign('pagetitle',_('Recovery of your credentials'));
+    LStemplate :: assign('recoverpasswordform_action','index.php?LSsession_recoverPassword');
     
     if (count(LSconfig :: get('ldap_servers'))==1) {
-      $GLOBALS['Smarty'] -> assign('recoverpasswordform_ldapserver_style','style="display: none"');
+      LStemplate :: assign('recoverpasswordform_ldapserver_style','style="display: none"');
     }
     
-    $GLOBALS['Smarty'] -> assign('recoverpasswordform_label_ldapserver',_('LDAP server'));
+    LStemplate :: assign('recoverpasswordform_label_ldapserver',_('LDAP server'));
     $ldapservers_name=array();
     $ldapservers_index=array();
     foreach(LSconfig :: get('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);
+    LStemplate :: assign('recoverpasswordform_ldapservers_name',$ldapservers_name);
+    LStemplate :: assign('recoverpasswordform_ldapservers_index',$ldapservers_index);
 
-    $GLOBALS['Smarty'] -> assign('recoverpasswordform_label_user',_('Identifier'));
-    $GLOBALS['Smarty'] -> assign('recoverpasswordform_label_submit',_('Validate'));
-    $GLOBALS['Smarty'] -> assign('recoverpasswordform_label_back',_('Back'));
+    LStemplate :: assign('recoverpasswordform_label_user',_('Identifier'));
+    LStemplate :: assign('recoverpasswordform_label_submit',_('Validate'));
+    LStemplate :: assign('recoverpasswordform_label_back',_('Back'));
     
     $recoverpassword_msg = _('Please fill the identifier field to proceed recovery procedure');
     
@@ -1252,7 +1240,7 @@ class LSsession {
       );
     }
     
-    $GLOBALS['Smarty'] -> assign('recoverpassword_msg',$recoverpassword_msg);
+    LStemplate :: assign('recoverpassword_msg',$recoverpassword_msg);
     
     self :: setTemplate('recoverpassword.tpl');
     self :: addJSscript('LSsession_recoverPassword.js');
@@ -1304,18 +1292,18 @@ class LSsession {
  /**
   * Ajoute une feuille de style au chargement de la page
   *
-  * Remarque : les scripts doivents Ãªtre dans le dossier LS_CSS_DIR.
-  *
   * @param[in] $script Le nom du fichier css Ã  charger.
   *
   * @retval void
   */
   public static function addCssFile($file,$path=NULL) {
-    $cssFile=array(
-      'file' => $file,
-      'path' => $path
-    );
-    self :: $CssFiles[$path.$file]=$cssFile;
+    if ($path) {
+      $file = $path.$file;
+    }
+    else {
+      $file = LStemplate :: getCSSPath($file);
+    }
+    self :: $CssFiles[$file]=$file;
   }
 
  /**
@@ -1355,7 +1343,7 @@ class LSsession {
       self :: addJSconfigParam('keepLSsessionActive',ini_get('session.gc_maxlifetime'));
     }
 
-    $GLOBALS['Smarty'] -> assign('LSjsConfig',json_encode(self :: $_JSconfigParams));
+    LStemplate :: assign('LSjsConfig',json_encode(self :: $_JSconfigParams));
     
     if (LSdebug) {
       $JSscript_txt.="<script type='text/javascript'>LSdebug_active = 1;</script>\n";
@@ -1364,47 +1352,50 @@ class LSsession {
       $JSscript_txt.="<script type='text/javascript'>LSdebug_active = 0;</script>\n";
     }
     
-    $GLOBALS['Smarty'] -> assign('LSsession_js',$JSscript_txt);
+    LStemplate :: assign('LSsession_js',$JSscript_txt);
 
     // Css
     self :: addCssFile("LSdefault.css");
+    if (isset($GLOBALS['defaultCSSfiles']) && is_array($GLOBALS['defaultCSSfiles'])) {
+      foreach ($GLOBALS['defaultCSSfiles'] as $file) {
+        self :: addCssFile($file);
+      }
+    }
     $Css_txt='';
     foreach (self :: $CssFiles as $file) {
-      if (!$file['path']) {
-        $file['path']=LS_CSS_DIR.'/';
-      }
-      $Css_txt.="<link rel='stylesheet' type='text/css' href='".$file['path'].$file['file']."' />\n";
+      $Css_txt.="<link rel='stylesheet' type='text/css' href='".$file."' />\n";
     }
-    $GLOBALS['Smarty'] -> assign('LSsession_css',$Css_txt);
+    LStemplate :: assign('LSsession_css',$Css_txt);
   
     if (isset(self :: $LSaccess[self :: $topDn])) {
-      $GLOBALS['Smarty'] -> assign('LSaccess',self :: $LSaccess[self :: $topDn]);
+      LStemplate :: assign('LSaccess',self :: $LSaccess[self :: $topDn]);
     }
     
     // Niveau
     $listTopDn = self :: getSubDnLdapServer();
     if (is_array($listTopDn)) {
       asort($listTopDn);
-      $GLOBALS['Smarty'] -> assign('label_level',self :: getSubDnLabel());
-      $GLOBALS['Smarty'] -> assign('_refresh',_('Refresh'));
+      LStemplate :: assign('label_level',self :: getSubDnLabel());
+      LStemplate :: assign('_refresh',_('Refresh'));
       $LSsession_topDn_index = array();
       $LSsession_topDn_name = array();
       foreach($listTopDn as $index => $name) {
         $LSsession_topDn_index[]  = $index;
         $LSsession_topDn_name[]   = $name;
       }
-      $GLOBALS['Smarty'] -> assign('LSsession_subDn_indexes',$LSsession_topDn_index);
-      $GLOBALS['Smarty'] -> assign('LSsession_subDn_names',$LSsession_topDn_name);
-      $GLOBALS['Smarty'] -> assign('LSsession_subDn',self :: $topDn);
-      $GLOBALS['Smarty'] -> assign('LSsession_subDnName',self :: getSubDnName());
+      LStemplate :: assign('LSsession_subDn_indexes',$LSsession_topDn_index);
+      LStemplate :: assign('LSsession_subDn_names',$LSsession_topDn_name);
+      LStemplate :: assign('LSsession_subDn',self :: $topDn);
+      LStemplate :: assign('LSsession_subDnName',self :: getSubDnName());
     }
     
-    $GLOBALS['Smarty'] -> assign('LSlanguages',self :: getLangList());
-    $GLOBALS['Smarty'] -> assign('LSlang',self :: $lang);
-    $GLOBALS['Smarty'] -> assign('LSencoding',self :: $encoding);
-    $GLOBALS['Smarty'] -> assign('lang_label',_('Language'));
+    LStemplate :: assign('LSlanguages',self :: getLangList());
+    LStemplate :: assign('LSlang',self :: $lang);
+    LStemplate :: assign('LSencoding',self :: $encoding);
+    LStemplate :: assign('lang_label',_('Language'));
     
-    $GLOBALS['Smarty'] -> assign('displayLogoutBtn',self :: $authParams['displayLogoutBtn']);
+    LStemplate :: assign('displayLogoutBtn',LSauth :: displayLogoutBtn());
+    LStemplate :: assign('displaySelfAccess',LSauth :: displaySelfAccess());
 
     // Infos
     if((!empty($_SESSION['LSsession_infos']))&&(is_array($_SESSION['LSsession_infos']))) {
@@ -1413,13 +1404,13 @@ class LSsession {
         $txt_infos.="<li>$info</li>\n";
       }
       $txt_infos.="</ul>\n";
-      $GLOBALS['Smarty'] -> assign('LSinfos',$txt_infos);
+      LStemplate :: assign('LSinfos',$txt_infos);
       $_SESSION['LSsession_infos']=array();
     }
     
     if (self :: $ajaxDisplay) {
-      $GLOBALS['Smarty'] -> assign('LSerror_txt',LSerror :: getErrors());
-      $GLOBALS['Smarty'] -> assign('LSdebug_txt',LSdebug_print(true));
+      LStemplate :: assign('LSerror_txt',LSerror :: getErrors());
+      LStemplate :: assign('LSdebug_txt',LSdebug_print(true));
     }
     else {
       LSerror :: display();
@@ -1428,9 +1419,9 @@ class LSsession {
     if (!self :: $template)
       self :: setTemplate('empty.tpl');
       
-    $GLOBALS['Smarty'] -> assign('connected_as',_("Connected as"));
+    LStemplate :: assign('connected_as',_("Connected as"));
     
-    $GLOBALS['Smarty'] -> display(self :: $template);
+    LStemplate :: display(self :: $template);
   }
   
  /**
@@ -1493,12 +1484,117 @@ class LSsession {
   */
   public static function fetchTemplate($template,$variables=array()) {
     foreach($variables as $name => $val) {
-      $GLOBALS['Smarty'] -> assign($name,$val);
+      LStemplate :: assign($name,$val);
     }
-    return $GLOBALS['Smarty'] -> fetch($template);
+    return LStemplate :: fetch($template);
   }
   
   /**
+   * Prend un tableau de LSobject et le réduit en utilisant un filtre de
+   * recherche sur un autre type de LSobject.
+   *
+   * Si une erreur est présente dans le tableau de définition du filtre, un
+   * tableau vide est renvoyé.
+   *
+   * @param[in] string $LSobject le type LSobject par défaut
+   * @param[in] array $set tableau de LSobject
+   * @param[in] array $filter_def définition du filtre de recherche pour la réduction
+   * @param[in] string $basend basedn pour la recherche, null par défaut
+   *
+   * @retval array le nouveau tableau de LSobject
+   */
+  private static function reduceLdapSet($LSobject, $set, $filter_def, $basedn=null) {
+    if (empty($set)) {
+      return array();
+    }
+
+    if (! isset($filter_def['filter']) &&
+          (! isset($filter_def['attr']) ||
+           ! isset($filter_def['attr_value']))) {
+      LSdebug("Filtre de profil LSobject invalide " . var_export($filter_def, true));
+      return array();
+    }
+
+    LSdebug('LSsession :: reducing set of');
+    foreach ($set as $object) {
+      LSdebug('LSsession :: -> ' . $object -> getDn());
+    }
+
+    $LSobject = isset($filter_def['LSObject']) ? $filter_def['LSobject'] : $LSobject;
+    LSdebug('LSobject :: ' . $LSobject);
+    $filters = array();
+    foreach ($set as $object) {
+      if (isset($filter_def['filter'])) {
+        $filters[] = $object -> getFData($filter_def['filter']);
+      }
+      else {
+        $value = $object -> getFData($filter_def['attr_value']);
+        $filters[] = Net_LDAP2_Filter::create($filter_def['attr'], 'equals', $value);
+      }
+    }
+    $filter = LSldap::combineFilters('or', $filters);
+    $params = array(
+      'basedn' => isset($filter_def['basedn']) ? $filter_def['basedn'] : $basedn,
+      'filter' => $filter,
+    );
+    if (isset($filter_def['params']) && is_array($filter_def['params'])) {
+      $params = array_merge($filter_def['params'],$params);
+    }
+    $LSsearch = new LSsearch($LSobject,'LSsession :: loadLSprofiles',$params,true);
+    $LSsearch -> run(false);
+
+    $set = $LSsearch -> listObjects();
+    LSdebug('LSsession :: reduced set to');
+    foreach ($set as $object) {
+      LSdebug('LSsession :: -> ' . $object -> getDn());
+    }
+    return $set;
+  }
+
+  /**
+   * Charge les droits LS de l'utilisateur : uniquement du type LSobjects
+   *
+   * @param[in] string $
+   *
+   * @retval void
+   */
+  private static function loadLSprofilesLSobjects($profile, $LSobject, $listInfos) {
+    if (! self :: loadLSclass('LSsearch')) {
+      LSdebug('Impossible de charger la classe LSsearch');
+      return;
+    }
+    # we are gonna grow a set of objects progressively, we start from the user
+    $set = array(self :: getLSuserObject());
+    $basedn = isset($listInfos['basedn']) ? $listInfos['basedn'] : null;
+    $LSobject = isset($listInfos['LSobject']) ? $listInfos['LSobject'] : $LSobject;
+
+    if (isset($listInfos['filters']) && is_array($listInfos['filters'])) {
+      foreach ($listInfos['filters'] as $filter_def) {
+        $set = self :: reduceLdapSet($LSobject, $set, $filter_def, $basedn);
+      }
+    }
+    if (isset($listInfos['filter']) || (isset($listInfos['attr']) && isset($listInfos['attr_value']))) {
+      # support legacy profile definition
+      $set = self :: reduceLdapSet($LSobject, $set, $listInfos, $basedn);
+    }
+
+    $DNs = [];
+    foreach ($set as $object) {
+      $DNs[] = $object -> getDn();
+    }
+    if (!is_array(self :: $LSprofiles[$profile])) {
+      self :: $LSprofiles[$profile]=$DNs;
+    }
+    else {
+      foreach($DNs as $dn) {
+        if (!in_array($dn,self :: $LSprofiles[$profile])) {
+          self :: $LSprofiles[$profile][] = $dn;
+        }
+      }
+    }
+  }
+
+  /**
    * Charge les droits LS de l'utilisateur
    * 
    * @retval boolean True si le chargement Ã  réussi, false sinon.
@@ -1515,28 +1611,8 @@ class LSsession {
             if ($topDn == 'LSobjects') {
               if (is_array($rightsInfos)) {
                 foreach ($rightsInfos as $LSobject => $listInfos) {
-                  if (self :: loadLSclass('LSsearch')) {
-                    if ($listInfos['filter']) {
-                      $filter = self :: getLSuserObject() -> getFData($listInfos['filter']);
-                    }
-                    else {
-                      $filter = '('.$listInfos['attr'].'='.self :: getLSuserObject() -> getFData($listInfos['attr_value']).')';
-                    }
-                    
-                    $params = array (
-                      'basedn' => $listInfos['basedn'],
-                      'filter' => $filter
-                    );
-                    
-                    if (is_array($listInfos['params'])) {
-                      $params = array_merge($listInfos['params'],$params);
-                    }
-                    
-                    $LSsearch = new LSsearch($LSobject,'LSsession :: loadLSprofiles',$params,true);
-                    $LSsearch -> run(false);
-                    
-                    $LSprofiles[$profile] = $LSsearch -> listObjectsDn();
-                  }
+                  LSdebug('loading LSprofile ' . $profile . ' for LSobject ' . $LSobject . ' with params ' . var_export($listInfos, true));
+                  self :: loadLSprofilesLSobjects($profile, $LSobject, $listInfos);
                 }
               }
               else {
@@ -1599,7 +1675,7 @@ class LSsession {
    */
   private static function loadLSaccess() {
     $LSaccess=array();
-    if (is_array(self :: $ldapServer['subDn'])) {
+    if (isset(self :: $ldapServer['subDn']) && is_array(self :: $ldapServer['subDn'])) {
       foreach(self :: $ldapServer['subDn'] as $name => $config) {
         if ($name=='LSobject') {
           if (is_array($config)) {
@@ -1660,15 +1736,16 @@ class LSsession {
         $LSaccess[self :: $topDn] = $access;
       }
     }
-    foreach($LSaccess as $dn => $access) {
-      $LSaccess[$dn] = array_merge(
-        array(
-          'SELF' => 'My account'
-        ),
-        $access
-      );
+    if (LSauth :: displaySelfAccess()) {
+      foreach($LSaccess as $dn => $access) {
+        $LSaccess[$dn] = array_merge(
+          array(
+            'SELF' => 'My account'
+          ),
+          $access
+        );
+      }
     }
-    
     self :: $LSaccess = $LSaccess;
     $_SESSION['LSsession']['LSaccess'] = $LSaccess;
   }
@@ -1794,7 +1871,7 @@ class LSsession {
       if (($right=='r')||($right=='w')) {
         foreach($whoami as $who) {
           foreach ($attrs_conf as $attr_name => $attr_config) {
-            if ($attr_config['rights'][$who]==$right) {
+            if (isset($attr_config['rights'][$who]) && $attr_config['rights'][$who]==$right) {
               return true;
             }
           }
@@ -1803,7 +1880,7 @@ class LSsession {
       else {
         foreach($whoami as $who) {
           foreach ($attrs_conf as $attr_name => $attr_config) {
-            if ( ($attr_config['rights'][$who]=='r') || ($attr_config['rights'][$who]=='w') ) {
+            if ( (isset($attr_config['rights'][$who])) && ( ($attr_config['rights'][$who]=='r') || ($attr_config['rights'][$who]=='w') ) ) {
               return true;
             }
           }
@@ -1874,7 +1951,7 @@ class LSsession {
     if (($right=='w') || ($right=='r')) {
       $r = 'n';
       foreach($whoami as $who) {
-        $nr = $relConf['rights'][$who];
+        $nr = ((isset($relConf['rights'][$who]))?$relConf['rights'][$who]:'');
         if($nr == 'w') {
           $r = 'w';
         }
@@ -1891,7 +1968,7 @@ class LSsession {
     }
     else {
       foreach($whoami as $who) {
-        if (($relConf['rights'][$who] == 'w') || ($relConf['rights'][$who] == 'r')) {
+        if ((isset($relConf['rights'][$who])) && ( ($relConf['rights'][$who] == 'w') || ($relConf['rights'][$who] == 'r') ) ) {
           return true;
         }
       }
@@ -1913,6 +1990,61 @@ class LSsession {
   }
 
   /**
+   * Retourne le droit de l'utilisateur a executer une customAction
+   * 
+   * @param[in] string $dn Le DN de l'objet
+   * @param[in] string $LSobject Le type de l'objet
+   * @param[in] string $customActionName Le nom de la customAction
+   *
+   * @retval boolean True si l'utilisateur peut executer cette customAction, false sinon
+   */
+  public static function canExecuteCustomAction($dn,$LSobject,$customActionName) {
+    $conf=LSconfig :: get('LSobjects.'.$LSobject.'.customActions.'.$customActionName);
+    if (!is_array($conf))
+      return;
+    $whoami = self :: whoami($dn);
+
+    if (isset($conf['rights']) && is_array($conf['rights'])) {
+      foreach($whoami as $who) {
+        if (in_array($who,$conf['rights'])) {
+          return True;
+        }
+      }
+    }
+    
+    return;
+  }
+
+  /**
+   * Retourne le droit de l'utilisateur a executer une customAction
+   * sur une recherche
+   *
+   * @param[in] string $LSsearch L'objet LSsearch
+   * @param[in] string $customActionName Le nom de la customAction
+   *
+   * @retval boolean True si l'utilisateur peut executer cette customAction, false sinon
+   */
+  public static function canExecuteLSsearchCustomAction($LSsearch,$customActionName) {
+    $conf=LSconfig :: get('LSobjects.'.$LSsearch -> LSobject.'.LSsearch.customActions.'.$customActionName);
+    if (!is_array($conf))
+      return;
+    $dn=$LSsearch -> basedn;
+    if (is_null($dn)) $dn=self::getTopDn();
+
+    $whoami = self :: whoami($dn);
+
+    if (isset($conf['rights']) && is_array($conf['rights'])) {
+      foreach($whoami as $who) {
+        if (in_array($who,$conf['rights'])) {
+          return True;
+        }
+      }
+    }
+
+    return;
+  }
+
+  /**
    * Ajoute un fichier temporaire
    * 
    * @author Benjamin Renard <brenard@easter-eggs.com>
@@ -2048,9 +2180,9 @@ class LSsession {
     if (!$subDn) {
       $subDn = self :: $topDn;
     }
-    if (self :: getSubDnLdapServer()) {
-      if (isset(self :: $_subDnLdapServer[self :: $ldapServerId][$subDn])) {
-        return self :: $_subDnLdapServer[self :: $ldapServerId][$subDn];
+    if (self :: getSubDnLdapServer(false)) {
+      if (isset(self :: $_subDnLdapServer[self :: $ldapServerId][false][$subDn])) {
+        return self :: $_subDnLdapServer[self :: $ldapServerId][false][$subDn];
       }
     }
     return '';
@@ -2065,7 +2197,7 @@ class LSsession {
    */
   public static function isSubDnLSobject($type) {
     $result = false;
-    if (is_array(self :: $ldapServer['subDn']['LSobject'])) {
+    if (isset(self :: $ldapServer['subDn']['LSobject']) && is_array(self :: $ldapServer['subDn']['LSobject'])) {
       foreach(self :: $ldapServer['subDn']['LSobject'] as $key => $value) {
         if ($key==$type) {
           $result=true;
@@ -2116,8 +2248,8 @@ class LSsession {
    * @retval void
    */  
   public static function redirect($url,$exit=true) {
-    $GLOBALS['Smarty'] -> assign('url',$url);
-    $GLOBALS['Smarty'] -> display('redirect.tpl');
+    LStemplate :: assign('url',$url);
+    LStemplate :: display('redirect.tpl');
     if ($exit) {
       exit();
     }
@@ -2143,7 +2275,7 @@ class LSsession {
    */
   public static function addHelpInfos($group,$infos) {
     if (is_array($infos)) {
-      if (is_array(self :: $_JSconfigParams['helpInfos'][$group])) {
+      if (isset(self :: $_JSconfigParams['helpInfos'][$group]) && is_array(self :: $_JSconfigParams['helpInfos'][$group])) {
         self :: $_JSconfigParams['helpInfos'][$group] = array_merge(self :: $_JSconfigParams['helpInfos'][$group],$infos);
       }
       else {
@@ -2197,7 +2329,18 @@ class LSsession {
     LSerror :: defineError('LSsession_12',
     _("LSsession : Some informations are missing to display this page.")
     );
-    // 13 -> 16 : not yet used
+    LSerror :: defineError('LSsession_13',
+    _("LSsession : The function of the custom action %{name} does not exists or is not configured.")
+    );
+    LSerror :: defineError('LSsession_14',
+    _("LSsession : Fail to retreive user's LDAP credentials from LSauth.")
+    );
+    LSerror :: defineError('LSsession_15',
+    _("LSsession : Fail to reconnect to LDAP server with user's LDAP credentials.")
+    );
+    LSerror :: defineError('LSsession_16',
+    _("LSsession : No import/export format define for this object type.")
+    );
     LSerror :: defineError('LSsession_17',
     _("LSsession : Error during creation of list of levels. Contact administrators. (Code : %{code})")
     );
@@ -2210,7 +2353,9 @@ class LSsession {
     LSerror :: defineError('LSsession_20',
     _("LSsession : Error during password recovery. Contact administrators.(Step : %{step})")
     );
-    // 21 : not yet used
+    LSerror :: defineError('LSsession_21',
+    _("LSsession : call function %{func} do not provided from LSaddon %{addon}.")
+    );
     LSerror :: defineError('LSsession_22',
     _("LSsession : problem during initialisation.")
     );
@@ -2228,14 +2373,14 @@ class LSsession {
       self :: setLdapServer($_REQUEST['server']);
       $data = array();
       if ( self :: LSldapConnect() ) {
-        session_start();
+        if (session_id()=="") session_start();
         if (isset($_SESSION['LSsession_topDn'])) {
           $sel = $_SESSION['LSsession_topDn'];
         }
         else {
           $sel = NULL;
         }
-        $list = self :: getSubDnLdapServerOptions($sel);
+        $list = self :: getSubDnLdapServerOptions($sel,true);
         if (is_string($list)) {
           $data['list_topDn'] = "<select name='LSsession_topDn' id='LSsession_topDn'>".$list."</select>";
           $data['subDnLabel'] = self :: getSubDnLabel();
@@ -2258,6 +2403,19 @@ class LSsession {
       $data=array('recoverPassword' => isset(self :: $ldapServer['recoverPassword']));
     }
   }
+
+       /**
+        * Set globals from the ldap server
+        *
+        * @retval void
+        */
+       public static function setGlobals() {
+               if ( isset(self :: $ldapServer['globals'])) {
+                       foreach(self :: $ldapServer['globals'] as $key => $value) {
+                               $GLOBALS[$key] = $value;
+                       }
+               }
+       }
 }
 
 ?>