Permit LSaddon to provide ajax callable function
[ldapsaisie.git] / public_html / includes / class / class.LSsession.php
index 4ad5c51..559dddf 100644 (file)
@@ -84,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
   *
@@ -133,18 +136,17 @@ class LSsession {
   */  
   private static function startLStemplate() {
     if ( self :: loadLSclass('LStemplate') ) {
-      $res = LStemplate :: start(
+      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'])),
         )
       );
-      self :: addJSconfigParam('LS_IMAGES_DIR',LStemplate :: getDefaultImageDirPath());
-      return $res;
     }
     return False;
   }
@@ -189,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;
   }
@@ -441,19 +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 :: startLSerror();
-    self :: startLStemplate();
-    
-    session_start();
-    
-    self :: setLocale();
-    
-    self :: loadLSaddons();
-    self :: loadLSauth();
     return true;
   }
 
@@ -476,11 +484,12 @@ class LSsession {
     if(isset($_SESSION['LSsession']['dn']) && !isset($_GET['LSsession_recoverPassword'])) {
       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 :: $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);
@@ -585,6 +594,18 @@ class LSsession {
             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());
@@ -852,6 +873,7 @@ class LSsession {
       'topDn' => self :: $topDn,
       'dn' => self :: $dn,
       'rdn' => self :: $rdn,
+      'userLDAPcreds' => self :: $userLDAPcreds,
       'ldapServerId' => self :: $ldapServerId,
       'ldapServer' => self :: $ldapServer,
       'LSprofiles' => self :: $LSprofiles,
@@ -938,6 +960,7 @@ class LSsession {
       self :: $ldapServerId = $id;
       self :: $ldapServer = $conf;
       self :: setLocale();
+      self :: setGlobals();
       return true;
     }
     else {
@@ -956,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;
       }
@@ -1264,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;
   }
 
  /**
@@ -1328,12 +1356,14 @@ class LSsession {
 
     // 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";
     }
     LStemplate :: assign('LSsession_css',$Css_txt);
   
@@ -1460,6 +1490,111 @@ class LSsession {
   }
   
   /**
+   * 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.
@@ -1476,28 +1611,8 @@ class LSsession {
             if ($topDn == 'LSobjects') {
               if (is_array($rightsInfos)) {
                 foreach ($rightsInfos as $LSobject => $listInfos) {
-                  if (self :: loadLSclass('LSsearch')) {
-                    if (isset($listInfos['filter'])) {
-                      $filter = self :: getLSuserObject() -> getFData($listInfos['filter']);
-                    }
-                    else {
-                      $filter = '('.$listInfos['attr'].'='.self :: getLSuserObject() -> getFData($listInfos['attr_value']).')';
-                    }
-                    
-                    $params = array (
-                      'basedn' => (isset($listInfos['basedn'])?$listInfos['basedn']:null),
-                      'filter' => $filter
-                    );
-                    
-                    if (isset($listInfos['params']) && is_array($listInfos['params'])) {
-                      $params = array_merge($listInfos['params'],$params);
-                    }
-                    
-                    $LSsearch = new LSsearch($LSobject,'LSsession :: loadLSprofiles',$params,true);
-                    $LSsearch -> run(false);
-                    
-                    self :: $LSprofiles[$profile] = $LSsearch -> listObjectsDn();
-                  }
+                  LSdebug('loading LSprofile ' . $profile . ' for LSobject ' . $LSobject . ' with params ' . var_export($listInfos, true));
+                  self :: loadLSprofilesLSobjects($profile, $LSobject, $listInfos);
                 }
               }
               else {
@@ -1901,6 +2016,35 @@ class LSsession {
   }
 
   /**
+   * 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>
@@ -2188,7 +2332,15 @@ class LSsession {
     LSerror :: defineError('LSsession_13',
     _("LSsession : The function of the custom action %{name} does not exists or is not configured.")
     );
-    // 14 -> 16 : not yet used
+    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})")
     );
@@ -2201,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.")
     );
@@ -2249,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;
+                       }
+               }
+       }
 }
 
 ?>