LSaddon / view : permit to hide a LSaddon view in menu
[ldapsaisie.git] / public_html / includes / class / class.LSsession.php
1 <?php
2 /*******************************************************************************
3  * Copyright (C) 2007 Easter-eggs
4  * http://ldapsaisie.labs.libre-entreprise.org
5  *
6  * Author: See AUTHORS file in top-level directory.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License version 2
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20
21 ******************************************************************************/
22
23 /** 
24  * Gestion des sessions
25  *
26  * Cette classe gère les sessions d'utilisateurs.
27  *
28  * @author Benjamin Renard <brenard@easter-eggs.com>
29  */
30 class LSsession {
31
32   // La configuration du serveur Ldap utilisé
33   public static $ldapServer = NULL;
34   
35   // L'id du serveur Ldap utilisé
36   private static $ldapServerId = NULL;
37   
38   // Le topDn courant
39   private static $topDn = NULL;
40   
41   // Le DN de l'utilisateur connecté
42   private static $dn = NULL;
43   
44   // Le RDN de l'utilisateur connecté (son identifiant)
45   private static $rdn = NULL;
46   
47   // Les LSprofiles de l'utilisateur
48   private static $LSprofiles = array();
49   
50   // Les droits d'accès de l'utilisateur
51   private static $LSaccess = array();
52
53   // LSaddons views
54   private static $LSaddonsViews = array();
55   private static $LSaddonsViewsAccess = array();
56   
57   // Les fichiers temporaires
58   private static $tmp_file = array();
59   
60   // Langue et encodage actuel
61   private static $lang = NULL;
62   private static $encoding = NULL;
63   
64   /*
65    * Constante de classe non stockée en session
66    */
67   // Le template à afficher
68   private static $template = NULL;
69   
70   // Les subDn des serveurs Ldap
71   private static $_subDnLdapServer = array();
72   
73   // Affichage Ajax
74   private static $ajaxDisplay = false;
75
76   // Les fichiers JS à charger dans la page
77   private static $JSscripts = array();
78   
79   // Les paramètres JS à communiquer dans la page
80   private static $_JSconfigParams = array();
81   
82   // Les fichiers CSS à charger dans la page
83   private static $CssFiles = array();
84
85   // L'objet de l'utilisateur connecté
86   private static $LSuserObject = NULL;
87   
88   // The LSauht object of the session
89   private static $LSauthObject = false;
90
91   // User LDAP credentials
92   private static $userLDAPcreds = false;
93
94  /**
95   * Include un fichier PHP
96   *
97   * @author Benjamin Renard <brenard@easter-eggs.com>
98   *
99   * @retval true si tout c'est bien passé, false sinon
100   */
101   public static function includeFile($file) {
102     if (file_exists(LS_LOCAL_DIR.'/'.$file)) {
103       $file=LS_LOCAL_DIR.'/'.$file;
104     }
105     elseif (!file_exists($file)) {
106       return;
107     }
108     if (defined('LSdebug') && constant('LSdebug')) {
109       return include_once($file);
110     }
111     else {
112       return @include_once($file);
113     }
114     return;
115   }
116
117  /**
118   * Lancement de LSconfig
119   *
120   * @author Benjamin Renard <brenard@easter-eggs.com>
121   *
122   * @retval true si tout c'est bien passé, false sinon
123   */
124   private static function startLSconfig() {
125     if (self :: loadLSclass('LSconfig')) {
126       if (LSconfig :: start()) {
127         return true;
128       }
129     }
130     die("ERROR : Can't load configuration files.");
131     return;
132   }
133
134  /**
135   * Lancement et initialisation de Smarty
136   *
137   * @author Benjamin Renard <brenard@easter-eggs.com>
138   *
139   * @retval true si tout c'est bien passé, false sinon
140   */  
141   private static function startLStemplate() {
142     if ( self :: loadLSclass('LStemplate') ) {
143       return LStemplate :: start(
144         array(
145           'smarty_path'  => LSconfig :: get('Smarty'),
146           'template_dir' => LS_TEMPLATES_DIR,
147           'image_dir'    => LS_IMAGES_DIR,
148           'css_dir'    => LS_CSS_DIR,
149           'compile_dir'  => LS_TMP_DIR,
150           'debug'        => LSdebug,
151           'debug_smarty' => (isset($_REQUEST['LStemplate_debug'])),
152         )
153       );
154     }
155     return False;
156   }
157   
158  /**
159   * Retourne le topDn de la session
160   *
161   * @author Benjamin Renard <brenard@easter-eggs.com>
162   *
163   * @retval string le topDn de la session
164   */
165   public static function getTopDn() {
166     if (!is_null(self :: $topDn)) {
167       return self :: $topDn;
168     }
169     else {
170       return self :: getRootDn();
171     }
172   }
173   
174  /**
175   * Retourne le rootDn de la session
176   *
177   * @author Benjamin Renard <brenard@easter-eggs.com>
178   *
179   * @retval string le rootDn de la session
180   */
181   public static function getRootDn() {
182     return self :: $ldapServer['ldap_config']['basedn'];
183   }
184
185  /**
186   * Initialisation de la gestion des erreurs
187   *
188   * Création de l'objet LSerror
189   *
190   * @author Benjamin Renard <brenard@easter-eggs.com
191   *
192   * @retval boolean true si l'initialisation a réussi, false sinon.
193   */
194   private static function startLSerror() {
195     if(!self :: loadLSclass('LSerror')) {
196       return;
197     }
198     set_error_handler(array('LSerror','errorHandler'),E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED & ~E_WARNING);
199     self :: defineLSerrors();
200     return true;
201   }
202
203  /**
204   * Chargement d'une classe d'LdapSaisie
205   *
206   * @param[in] $class Nom de la classe Ã  charger (Exemple : LSpeople)
207   * @param[in] $type (Optionnel) Type de classe Ã  charger (Exemple : LSobjects)
208   *
209   * @author Benjamin Renard <brenard@easter-eggs.com
210   * 
211   * @retval boolean true si le chargement a réussi, false sinon.
212   */
213   public static function loadLSclass($class,$type='') {
214     if (class_exists($class))
215       return true;
216     if($type!='')
217       $type=$type.'.';
218     return self :: includeFile(LS_CLASS_DIR .'class.'.$type.$class.'.php');
219   }
220
221  /**
222   * Chargement d'un object LdapSaisie
223   *
224   * @param[in] $object Nom de l'objet Ã  charger
225   *
226   * @retval boolean true si le chargement a réussi, false sinon.
227   */
228   public static function loadLSobject($object) {
229     if(class_exists($object)) {
230       return true;
231     }
232     $error = 0;
233     self :: loadLSclass('LSldapObject');
234     if (!self :: loadLSclass($object,'LSobjects')) {
235       $error = 1;
236     }
237     if (!self :: includeFile( LS_OBJECTS_DIR . 'config.LSobjects.'.$object.'.php' )) {
238       $error = 1;
239     }
240     else {
241       if (!LSconfig :: set("LSobjects.$object",$GLOBALS['LSobjects'][$object])) {
242         $error = 1;
243       }
244       else if (isset($GLOBALS['LSobjects'][$object]['LSaddons'])){
245         if (is_array($GLOBALS['LSobjects'][$object]['LSaddons'])) {
246           foreach ($GLOBALS['LSobjects'][$object]['LSaddons'] as $addon) {
247             if (!self :: loadLSaddon($addon)) {
248               $error = 1;
249             }
250           }
251         }
252         else {
253           if (!self :: loadLSaddon($GLOBALS['LSobjects'][$object]['LSaddons'])) {
254             $error = 1;
255           }
256         } 
257       }
258     }
259     if ($error) {
260       LSerror :: addErrorCode('LSsession_04',$object);
261       return;
262     }
263     return true;
264   }
265
266  /**
267   * Chargement d'un addons d'LdapSaisie
268   *
269   * @param[in] $addon Nom de l'addon Ã  charger (Exemple : samba)
270   *
271   * @author Benjamin Renard <brenard@easter-eggs.com
272   * 
273   * @retval boolean true si le chargement a réussi, false sinon.
274   */
275   public static function loadLSaddon($addon) {
276     if(self :: includeFile(LS_ADDONS_DIR .'LSaddons.'.$addon.'.php')) {
277       self :: includeFile(LS_CONF_DIR."LSaddons/config.LSaddons.".$addon.".php");
278       if (!call_user_func('LSaddon_'. $addon .'_support')) {
279         LSerror :: addErrorCode('LSsession_02',$addon);
280         return;
281       }
282       return true;
283     }
284     return;
285   }
286
287  /**
288   * Chargement d'une classe d'authentification d'LdapSaisie
289   *
290   * @author Benjamin Renard <brenard@easter-eggs.com
291   * 
292   * @retval boolean true si le chargement a reussi, false sinon.
293   */
294   public static function loadLSauth() {
295     if (self :: loadLSclass('LSauth')) {
296       return true;
297     }
298     else {
299       LSerror :: addErrorCode('LSsession_05','LSauth');
300     }
301     return;
302   }
303
304  /**
305   * Chargement des addons LdapSaisie
306   *
307   * Chargement des LSaddons contenue dans la variable
308   * $GLOBALS['LSaddons']['loads']
309   *
310   * @retval boolean true si le chargement a réussi, false sinon.
311   */
312   public static function loadLSaddons() {
313     $conf=LSconfig :: get('LSaddons.loads');
314     if(!is_array($conf)) {
315       LSerror :: addErrorCode('LSsession_01',"LSaddons['loads']");
316       return;
317     }
318
319     foreach ($conf as $addon) {
320       self :: loadLSaddon($addon);
321     }
322     return true;
323   }
324
325  /**
326   * Défini la locale
327   * 
328   * @retval void
329   */
330   public static function setLocale($lang=null,$encoding=null) {
331     if (is_null($lang)) {
332       if (isset($_REQUEST['lang'])) {
333         $lang = $_REQUEST['lang'];
334       }
335       elseif (isset($_SESSION['LSlang'])) {
336         $lang = $_SESSION['LSlang'];
337       }
338       elseif (isset(self :: $ldapServer['lang'])) {
339         $lang = self :: $ldapServer['lang'];
340       }
341       else {
342         $lang = LSconfig :: get('lang');
343       }
344     }
345     
346     if (is_null($enconding)) {
347       if (isset($_REQUEST['encoding'])) {
348         $encoding = $_REQUEST['encoding'];
349       }
350       elseif (isset($_SESSION['LSencoding'])) {
351         $encoding = $_SESSION['LSencoding'];
352       }
353       elseif (isset(self :: $ldapServer['encoding'])) {
354         $encoding = self :: $ldapServer['encoding'];
355       }
356       else {
357         $encoding = LSconfig :: get('encoding');
358       }
359     }
360     
361     $_SESSION['LSlang']=$lang;
362     self :: $lang=$lang;
363     $_SESSION['LSencoding']=$encoding;
364     self :: $encoding=$encoding;
365     
366
367     if (self :: localeExist($lang,$encoding)) {
368       if ($encoding) {
369         $lang.='.'.$encoding;
370       }
371       setlocale(LC_ALL, $lang);
372       bindtextdomain(LS_TEXT_DOMAIN, LS_I18N_DIR);
373       textdomain(LS_TEXT_DOMAIN);
374       
375       self :: includeFile(LS_I18N_DIR.'/'.$lang.'/lang.php');
376
377       foreach (listFiles(LS_LOCAL_DIR.'/'.LS_I18N_DIR.'/'.$lang,'/^lang.+\.php$/') as $file) {
378         include(LS_LOCAL_DIR.'/'.LS_I18N_DIR."/$lang/$file");
379       }
380     }
381     else {
382       if ($encoding && $lang) {
383         $lang.='.'.$encoding;
384       }
385       LSdebug('La locale "'.$lang.'" n\'existe pas, utilisation de la locale par défaut.');
386     }
387   }
388   
389  /**
390   * Retourne la liste des langues disponibles
391   * 
392   * @retval array Tableau/Liste des langues disponibles
393   **/ 
394   public static function getLangList() {
395     $list=array('en_US');
396     if (self :: $encoding) {
397       $regex = '^([a-zA-Z_]*)\.'.self :: $encoding.'$';
398     }
399     else {
400       $regex = '^([a-zA-Z_]*)$';
401     }
402     if ($handle = opendir(LS_I18N_DIR)) {
403       while (false !== ($file = readdir($handle))) {
404         if(is_dir(LS_I18N_DIR.'/'.$file)) {
405           if (ereg($regex,$file,$regs)) {
406             if (!in_array($regs[1],$list)) {
407               $list[]=$regs[1];
408             }
409           }
410         }
411       }
412     }
413     return $list;
414   }
415
416  /**
417   * Retourne la langue courante de la session
418   * 
419   * @param[in] boolean Si true, le code langue retourné sera court
420   * 
421   * @retval string La langue de la session
422   **/
423   public static function getLang($short=false) {
424     if ($short) {
425       return strtolower(self :: $lang[0].self :: $lang[1]);
426     }
427     return self :: $lang;
428   }
429   
430  /**
431   * Vérifie si une locale est disponible
432   * 
433   * @param[in] $lang string La langue (Ex : fr_FR)
434   * @param[in] $encoding string L'encodage de caractère (Ex : UTF8)
435   * 
436   * @retval boolean True si la locale est disponible, False sinon
437   **/
438   public static function localeExist($lang,$encoding) {
439     if ( !$lang && !$encoding ) {
440       return;
441     }
442     $locale=$lang.(($encoding)?'.'.$encoding:'');
443     if ($locale=='en_US.UTF8') {
444       return true;
445     }
446     return (is_dir(LS_I18N_DIR.'/'.$locale));
447   }
448
449  /**
450   * Initialisation LdapSaisie
451   *
452   * @param[in] $lang string La langue (Ex : fr_FR / Optionnel)
453   * @param[in] $encoding string L'encodage de caractère (Ex : UTF8 / Optionnel)
454   *
455   * @retval boolean True si l'initialisation à réussi, false sinon.
456   */
457   public static function initialize($lang=null,$encoding=null) {
458     try {
459       if (!self :: startLSconfig()) {
460         return;
461       }
462
463       self :: startLSerror();
464       self :: startLStemplate();
465
466       session_start();
467
468       self :: setLocale($lang,$encoding);
469
470       self :: loadLSaddons();
471       self :: loadLSauth();
472     }
473     catch (Exception $e) {
474       die('LSsession : fail to initialize session. Error : '.$e->getMessage());
475     }
476     return true;
477   }
478
479  /**
480   * Initialisation de la session LdapSaisie
481   *
482   * Initialisation d'une LSsession :
483   * - Authentification et activation du mécanisme de session de LdapSaisie
484   * - ou Chargement des paramètres de la session Ã  partir de la variable 
485   *   $_SESSION['LSsession'].
486   * - ou Destruction de la session en cas de $_GET['LSsession_logout'].
487   *
488   * @retval boolean True si l'initialisation Ã  réussi (utilisateur authentifié), false sinon.
489   */
490   public static function startLSsession() {
491     if (!self :: initialize()) {
492       return;
493     }
494     
495     if(isset($_SESSION['LSsession']['dn']) && !isset($_GET['LSsession_recoverPassword'])) {
496       LSdebug('LSsession : Session existente'); 
497       // --------------------- Session existante --------------------- //
498       self :: $topDn         = $_SESSION['LSsession']['topDn'];
499       self :: $dn            = $_SESSION['LSsession']['dn'];
500       self :: $rdn           = $_SESSION['LSsession']['rdn'];
501       self :: $ldapServerId  = $_SESSION['LSsession']['ldapServerId'];
502       self :: $tmp_file      = $_SESSION['LSsession']['tmp_file'];
503       self :: $userLDAPcreds = $_SESSION['LSsession']['userLDAPcreds'];
504       
505       if ( self :: cacheLSprofiles() && !isset($_REQUEST['LSsession_refresh']) ) {
506         self :: setLdapServer(self :: $ldapServerId);
507         if (!LSauth :: start()) {
508           LSdebug("LSsession : can't start LSauth -> stop");
509           return;
510         }
511         self :: $LSprofiles   = $_SESSION['LSsession']['LSprofiles'];
512         self :: $LSaccess   = $_SESSION['LSsession']['LSaccess'];
513         self :: $LSaddonsViewsAccess   = $_SESSION['LSsession']['LSaddonsViewsAccess'];
514         if (!self :: LSldapConnect())
515           return;
516       }
517       else {
518         self :: setLdapServer(self :: $ldapServerId);
519         if (!LSauth :: start()) {
520           LSdebug("LSsession : can't start LSauth -> stop");
521           return;
522         }
523         if (!self :: LSldapConnect())
524           return;
525         self :: loadLSprofiles();
526       }
527       
528       if ( self :: cacheSudDn() && (!isset($_REQUEST['LSsession_refresh'])) ) {
529         self :: $_subDnLdapServer = ((isset($_SESSION['LSsession_subDnLdapServer']))?$_SESSION['LSsession_subDnLdapServer']:NULL);
530       }
531       
532       if (!self :: loadLSobject(self :: $ldapServer['authObjectType'])) {
533         return;
534       }
535       
536       if (isset($_GET['LSsession_logout'])) {
537         LSauth :: logout();
538         session_destroy();
539         
540         if (is_array($_SESSION['LSsession']['tmp_file'])) {
541           self :: $tmp_file = $_SESSION['LSsession']['tmp_file'];
542         }
543         self :: deleteTmpFile();
544         unset($_SESSION['LSsession']);
545         
546         self :: redirect('index.php');
547         return;
548       }
549       
550       if ( !self :: cacheLSprofiles() || isset($_REQUEST['LSsession_refresh']) ) {
551         self :: loadLSprofiles();
552         self :: loadLSaccess();
553         self :: loadLSaddonsViewsAccess();
554         $_SESSION['LSsession']=self :: getContextInfos();
555       }
556       
557       LStemplate :: assign('LSsession_username',self :: getLSuserObject() -> getDisplayName());
558       
559       if (isset ($_POST['LSsession_topDn']) && $_POST['LSsession_topDn']) {
560         if (self :: validSubDnLdapServer($_POST['LSsession_topDn'])) {
561           self :: $topDn = $_POST['LSsession_topDn'];
562           $_SESSION['LSsession']['topDn'] = $_POST['LSsession_topDn'];
563         } // end if
564       } // end if
565       
566       return true;
567       
568     }
569     else {
570       // --------------------- Session inexistante --------------------- //
571       if (isset($_GET['LSsession_recoverPassword'])) {
572         session_destroy();
573       }
574       // Session inexistante
575       if (isset($_POST['LSsession_ldapserver'])) {
576         self :: setLdapServer($_POST['LSsession_ldapserver']);
577       }
578       else {
579         self :: setLdapServer(0);
580       }
581       
582       // Connexion au serveur LDAP
583       if (self :: LSldapConnect()) {
584
585         // topDn
586         if (isset($_POST['LSsession_topDn']) && $_POST['LSsession_topDn'] != '' ){
587           self :: $topDn = $_POST['LSsession_topDn'];
588         }
589         else {
590           self :: $topDn = self :: $ldapServer['ldap_config']['basedn'];
591         }
592         $_SESSION['LSsession_topDn']=self :: $topDn;
593        
594         if (!LSauth :: start()) {
595           LSdebug("LSsession : can't start LSauth -> stop");
596           return;
597         }
598         
599         if (isset($_GET['LSsession_recoverPassword'])) {
600           $recoveryPasswordInfos = self :: recoverPasswd(
601                                       $_REQUEST['LSsession_user'],
602                                       $_GET['recoveryHash']
603                                    );
604         }
605         else {
606           $LSuserObject = LSauth :: forceAuthentication();
607           if ($LSuserObject) {
608             // Authentication successful
609             self :: $LSuserObject = $LSuserObject;
610             self :: $dn = $LSuserObject->getValue('dn');
611             self :: $rdn = $LSuserObject->getValue('rdn');
612             if (isset(self :: $ldapServer['useUserCredentials']) && self :: $ldapServer['useUserCredentials']) {
613               self :: $userLDAPcreds = LSauth :: getLDAPcredentials($LSuserObject);
614               if (!is_array(self :: $userLDAPcreds)) {
615                 LSerror :: addErrorCode('LSsession_14');
616                 self :: $userLDAPcreds = false;
617                 return;
618               }
619               if (!LSldap :: reconnectAs(self :: $userLDAPcreds['dn'],self :: $userLDAPcreds['pwd'])) {
620                 LSerror :: addErrorCode('LSsession_15');
621                 return;
622               }
623             }
624             self :: loadLSprofiles();
625             self :: loadLSaccess();
626             self :: loadLSaddonsViewsAccess();
627             LStemplate :: assign('LSsession_username',self :: getLSuserObject() -> getDisplayName());
628             $_SESSION['LSsession']=self :: getContextInfos();
629             return true;
630           }
631         }
632       }
633       else {
634         LSerror :: addErrorCode('LSsession_09');
635       }
636       
637       if (self :: $ldapServerId) {
638         LStemplate :: assign('ldapServerId',self :: $ldapServerId);
639       }
640       LStemplate :: assign('topDn',self :: $topDn);
641       if (isset($_GET['LSsession_recoverPassword'])) {
642         self :: displayRecoverPasswordForm($recoveryPasswordInfos);
643       }
644       elseif(LSauth :: displayLoginForm()) {
645         self :: displayLoginForm();
646       }
647       else {
648         self :: setTemplate('blank.tpl');
649         LSerror :: addErrorCode('LSsession_10');
650       }
651       return;
652     }
653   }
654   
655   /**
656    * Do recover password
657    * 
658    * @param[in] $username string The submited username
659    * @param[in] $recoveryHash string The submited recoveryHash
660    * 
661    * @retval array The recoveryPassword infos for template
662    **/
663   private static function recoverPasswd($username,$recoveryHash) {
664     $recoveryPasswordInfos=array();
665     if ( self :: loadLSobject(self :: $ldapServer['authObjectType']) ) {
666       $authobject = new self :: $ldapServer['authObjectType']();
667       if (!empty($recoveryHash)) {
668         $filter=Net_LDAP2_Filter::create(
669           self :: $ldapServer['recoverPassword']['recoveryHashAttr'],
670           'equals',
671           $recoveryHash
672         );
673         $result = $authobject -> listObjects($filter,self :: $topDn);
674       }
675       elseif (!empty($username)) {
676         $result = $authobject -> searchObject(
677                     $username,
678                     self :: $topDn,
679                     self :: $ldapServer['authObjectFilter']
680                   );
681       }
682       else {
683         return $recoveryPasswordInfos;
684       }
685       
686       $nbresult=count($result);
687       
688       if ($nbresult==0) {
689         LSdebug('hash/username incorrect');
690         LSerror :: addErrorCode('LSsession_06');  
691       }
692       elseif ($nbresult>1) {
693         LSerror :: addErrorCode('LSsession_07');
694       }
695       else {
696         $rdn = $result[0] -> getValue('rdn');
697         $username = $rdn[0];
698         LSdebug('Recover : Id trouvé : '.$username);
699         if (self :: $ldapServer['recoverPassword']) {
700           if (self :: loadLSaddon('mail')) {
701             LSdebug('Récupération active');
702             $user=$result[0];
703             $emailAddress = $user -> getValue(self :: $ldapServer['recoverPassword']['mailAttr']);
704             $emailAddress = $emailAddress[0];
705             
706             if (checkEmail($emailAddress)) {
707               LSdebug('Email : '.$emailAddress);
708               self :: $dn = $user -> getDn();
709               
710               // 1ère étape : envoie du recoveryHash
711               if (empty($recoveryHash)) {
712                 $hash=self :: recoverPasswdFirstStep($user);
713                 if ($hash) {
714                   if (self :: recoverPasswdSendMail($emailAddress,1,$hash)) {
715                     // Mail a bien été envoyé
716                     $recoveryPasswordInfos['recoveryHashMail']=$emailAddress;
717                   }
718                 }
719               }
720               // 2nd étape : génération du mot de passe + envoie par mail
721               else {
722                 $pwd=self :: recoverPasswdSecondStep($user);
723                 if ($pwd) {
724                   if (self :: recoverPasswdSendMail($emailAddress,2,$pwd)){
725                     // Mail a bien été envoyé
726                     $recoveryPasswordInfos['newPasswordMail']=$emailAddress;
727                   }
728                 }
729               }
730             }
731             else {
732               LSerror :: addErrorCode('LSsession_19');
733             }
734           }
735         }
736         else {
737           LSerror :: addErrorCode('LSsession_18');
738         }
739       }
740     }
741     return $recoveryPasswordInfos;
742   }
743   
744   /**
745    * Send recover password mail
746    * 
747    * @param[in] $mail string The user's mail
748    * @param[in] $step integer The step
749    * @param[in] $info string The info for formatted message
750    * 
751    * @retval boolean True on success or False
752    **/
753   private static function recoverPasswdSendMail($mail,$step,$info) {
754     // Header des mails
755     $sendParams=array();
756     if (self :: $ldapServer['recoverPassword']['recoveryEmailSender']) {
757       $sendParams['From']=self :: $ldapServer['recoverPassword']['recoveryEmailSender'];
758     }
759     
760     if ($step==1) {
761       if ($_SERVER['HTTPS']=='on') {
762         $recovery_url='https://';
763       }
764       else {
765         $recovery_url='http://';
766       }
767       $recovery_url .= $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'].'&recoveryHash='.$info;
768       
769       $subject = self :: $ldapServer['recoverPassword']['recoveryHashMail']['subject'];
770       $msg = getFData(
771         self :: $ldapServer['recoverPassword']['recoveryHashMail']['msg'],
772         $recovery_url
773       );
774     }
775     else {
776       $subject = self :: $ldapServer['recoverPassword']['newPasswordMail']['subject'];
777       $msg = getFData(
778         self :: $ldapServer['recoverPassword']['newPasswordMail']['msg'],
779         $info
780       );
781     }
782     
783     if (!sendMail($mail,$subject,$msg,$sendParams)) {
784       LSdebug("Problème durant l'envoie du mail");
785       LSerror :: addErrorCode('LSsession_20',4);
786       return;
787     }
788     return true;
789   }
790   
791   
792   /**
793    * Do first step of recovering password
794    * 
795    * @param[in] $user LSldapObject The LSldapObject of the user
796    * 
797    * @retval string|False The recory hash on success or False
798    **/
799   private static function recoverPasswdFirstStep($user) {
800     // Generer un hash
801     $rdn=$user -> getValue('rdn');
802     $rdn = $rdn[0];
803     $recovery_hash = md5($rdn . strval(time()) . strval(rand()));
804     
805     $lostPasswdForm = $user -> getForm('lostPassword');
806     $lostPasswdForm -> setPostData(
807       array(
808         self :: $ldapServer['recoverPassword']['recoveryHashAttr'] => $recovery_hash
809       )
810       ,true
811     );
812       
813     if($lostPasswdForm -> validate()) {
814       if ($user -> updateData('lostPassword')) {
815         // recoveryHash de l'utilisateur mis à jour
816         return $recovery_hash;
817       }
818       else {
819         // Erreur durant la mise à jour de l'objet
820         LSdebug("Erreur durant la mise à jour de l'objet");
821         LSerror :: addErrorCode('LSsession_20',6);
822       }
823     }
824     else {
825       // Erreur durant la validation du formulaire de modification de perte de password
826       LSdebug("Erreur durant la validation du formulaire de modification de perte de password");
827       LSerror :: addErrorCode('LSsession_20',5);
828     }
829     return;
830   }
831
832   /**
833    * Do second step of recovering password
834    * 
835    * @param[in] $user LSldapObject The LSldapObject of the user
836    * 
837    * @retval string|False The new password on success or False
838    **/
839   private static function recoverPasswdSecondStep($user) {
840     $attr=$user -> attrs[self :: $ldapServer['authObjectTypeAttrPwd']];
841     if ($attr instanceof LSattribute) {
842       $mdp = generatePassword(
843        $attr -> config['html_options']['chars'],
844        $attr -> config['html_options']['lenght']
845       );
846       LSdebug('Nvx mpd : '.$mdp);
847       $lostPasswdForm = $user -> getForm('lostPassword');
848       $lostPasswdForm -> setPostData(
849         array(
850           self :: $ldapServer['recoverPassword']['recoveryHashAttr'] => array(''),
851           self :: $ldapServer['authObjectTypeAttrPwd'] => array($mdp)
852         )
853         ,true
854       );
855       if($lostPasswdForm -> validate()) {
856         if ($user -> updateData('lostPassword')) {
857           return $mdp;
858         }
859         else {
860           // Erreur durant la mise à jour de l'objet
861           LSdebug("Erreur durant la mise à jour de l'objet");
862           LSerror :: addErrorCode('LSsession_20',3);
863         }
864       }
865       else {
866         // Erreur durant la validation du formulaire de modification de perte de password
867         LSdebug("Erreur durant la validation du formulaire de modification de perte de password");
868         LSerror :: addErrorCode('LSsession_20',2);
869       }
870     }
871     else {
872       // l'attribut password n'existe pas
873       LSdebug("L'attribut password n'existe pas");
874       LSerror :: addErrorCode('LSsession_20',1);
875     }
876     return;
877   }
878   
879  /**
880   * Retourne les informations du contexte
881   *
882   * @author Benjamin Renard <brenard@easter-eggs.com
883   * 
884   * @retval array Tableau associatif des informations du contexte
885   */
886   private static function getContextInfos() {
887     return array(
888       'tmp_file' => self :: $tmp_file,
889       'topDn' => self :: $topDn,
890       'dn' => self :: $dn,
891       'rdn' => self :: $rdn,
892       'userLDAPcreds' => self :: $userLDAPcreds,
893       'ldapServerId' => self :: $ldapServerId,
894       'ldapServer' => self :: $ldapServer,
895       'LSprofiles' => self :: $LSprofiles,
896       'LSaccess' => self :: $LSaccess,
897       'LSaddonsViewsAccess' => self :: $LSaddonsViewsAccess
898     );
899   }
900   
901   /**
902   * Retourne l'objet de l'utilisateur connecté
903   *
904   * @author Benjamin Renard <brenard@easter-eggs.com
905   * 
906   * @retval mixed L'objet de l'utilisateur connecté ou false si il n'a pas put
907   *               être créé
908   */
909   public static function getLSuserObject($dn=null) {
910     if ($dn) {
911       self :: $dn = $dn;
912     }
913     if (!self :: $LSuserObject) {
914       if (self :: loadLSobject(self :: $ldapServer['authObjectType'])) {
915         self :: $LSuserObject = new self :: $ldapServer['authObjectType']();
916         self :: $LSuserObject -> loadData(self :: $dn);
917       }
918       else {
919         return;
920       }
921     }
922     return self :: $LSuserObject;
923   }
924   
925  /**
926   * Retourne le DN de l'utilisateur connecté
927   *
928   * @author Benjamin Renard <brenard@easter-eggs.com
929   * 
930   * @retval string Le DN de l'utilisateur connecté
931   */
932   public static function getLSuserObjectDn() {
933     return self :: $dn;
934   }
935
936  /**
937   * Modifie l'utilisateur connecté à la volé
938   * 
939   * @param[in] $object Mixed  L'objet Ldap du nouvel utilisateur
940   *                           le type doit correspondre à
941   *                           self :: $ldapServer['authObjectType']
942   * 
943   * @retval boolean True en cas de succès, false sinon
944   */
945  public static function changeAuthUser($object) {
946   if ($object instanceof self :: $ldapServer['authObjectType']) {
947     self :: $dn = $object -> getDn();
948     $rdn = $object -> getValue('rdn');
949     if(is_array($rdn)) {
950       $rdn = $rdn[0];
951     }
952     self :: $rdn = $rdn;
953     self :: $LSuserObject = $object;
954     
955     if(self :: loadLSprofiles()) {
956       self :: loadLSaccess();
957       self :: loadLSaddonsViewsAccess();
958       $_SESSION['LSsession']=self :: getContextInfos();
959       return true;
960     }
961   }
962   return;
963  }
964
965  /**
966   * Définition du serveur Ldap de la session
967   *
968   * Définition du serveur Ldap de la session Ã  partir de son ID dans 
969   * le tableau LSconfig :: get('ldap_servers').
970   *
971   * @param[in] integer Index du serveur Ldap
972   *
973   * @retval boolean True sinon false.
974   */
975   public static function setLdapServer($id) {
976     $conf = LSconfig :: get("ldap_servers.$id");
977     if ( is_array($conf) ) {
978       self :: $ldapServerId = $id;
979       self :: $ldapServer = $conf;
980       self :: setLocale();
981       self :: setGlobals();
982       return true;
983     }
984     else {
985       return;
986     }
987   }
988
989  /**
990   * Connexion au serveur Ldap
991   *
992   * @retval boolean True sinon false.
993   */
994   public static function LSldapConnect() {
995     if (self :: $ldapServer) {
996       self :: includeFile(LSconfig :: get('NetLDAP2'));
997       if (!self :: loadLSclass('LSldap')) {
998         return;
999       }
1000       if (self :: $dn && isset(self :: $ldapServer['useUserCredentials']) && self :: $ldapServer['useUserCredentials']) {
1001         LSldap :: reconnectAs(self :: $userLDAPcreds['dn'], self :: $userLDAPcreds['pwd'],self :: $ldapServer['ldap_config']);
1002       }
1003       else {
1004         LSldap :: connect(self :: $ldapServer['ldap_config']);
1005       }
1006       if (LSldap :: isConnected()) {
1007         return true;
1008       }
1009       else {
1010         return;
1011       }
1012     }
1013     else {
1014       LSerror :: addErrorCode('LSsession_03');
1015       return;
1016     }
1017   }
1018
1019   /**
1020    * Use this function to know if subDn is enabled for the curent LdapServer
1021    * 
1022    * @retval boolean
1023    **/
1024   public static function subDnIsEnabled() {
1025     if (!isset(self :: $ldapServer['subDn'])) {
1026       return;
1027     }
1028     if ( !is_array(self :: $ldapServer['subDn']) ) {
1029       return;
1030     }
1031     return true;
1032   }
1033
1034  /**
1035   * Retourne les sous-dns du serveur Ldap courant
1036   *
1037   * @retval mixed Tableau des subDn, false si une erreur est survenue.
1038   */
1039   public static function getSubDnLdapServer($login=false) {
1040     $login=(bool)$login;
1041     if (self :: cacheSudDn() && isset(self :: $_subDnLdapServer[self :: $ldapServerId][$login])) {
1042       return self :: $_subDnLdapServer[self :: $ldapServerId][$login];
1043     }
1044     if (!self::subDnIsEnabled()) {
1045       return;
1046     }
1047     $return=array();
1048     foreach(self :: $ldapServer['subDn'] as $subDn_name => $subDn_config) {
1049       if ($login && isset($subDn_config['nologin']) && $subDn_config['nologin']) continue;
1050       if ($subDn_name == 'LSobject') {
1051         if (is_array($subDn_config)) {
1052           foreach($subDn_config as $LSobject_name => $LSoject_config) {
1053             if (isset($LSoject_config['basedn']) && !empty($LSoject_config['basedn'])) {
1054               $basedn = $LSoject_config['basedn'];
1055             }
1056             else {
1057               $basedn = self::getRootDn();
1058             }
1059             if (isset($LSoject_config['displayName']) && !empty($LSoject_config['displayName'])) {
1060               $displayName = $LSoject_config['displayName'];
1061             }
1062             else {
1063               $displayName = NULL;
1064             }
1065             if( self :: loadLSobject($LSobject_name) ) {
1066               if ($subdnobject = new $LSobject_name()) {
1067                 $tbl_return = $subdnobject -> getSelectArray(NULL,$basedn,$displayName);
1068                 if (is_array($tbl_return)) {
1069                   $return=array_merge($return,$tbl_return);
1070                 }
1071                 else {
1072                   LSerror :: addErrorCode('LSsession_17',3);
1073                 }
1074               }
1075               else {
1076                 LSerror :: addErrorCode('LSsession_17',2);
1077               }
1078             }
1079           }
1080         }
1081         else {
1082           LSerror :: addErrorCode('LSsession_17',1);
1083         }
1084       }
1085       else {
1086         if ((isCompatibleDNs($subDn_config['dn'],self :: $ldapServer['ldap_config']['basedn']))&&($subDn_config['dn']!="")) {
1087           $return[$subDn_config['dn']] = __($subDn_name);
1088         }
1089       }
1090     }
1091     if (self :: cacheSudDn()) {
1092       self :: $_subDnLdapServer[self :: $ldapServerId][$login]=$return;
1093       $_SESSION['LSsession_subDnLdapServer'] = self :: $_subDnLdapServer;
1094     }
1095     return $return;
1096   }
1097   
1098   /**
1099    * Retourne la liste de subDn du serveur Ldap utilise
1100    * trié par la profondeur dans l'arboressence (ordre décroissant)
1101    * 
1102    * @return array() Tableau des subDn trié
1103    */  
1104   public static function getSortSubDnLdapServer($login=false) {
1105     $subDnLdapServer = self :: getSubDnLdapServer($login);
1106     if (!$subDnLdapServer) {
1107       return array();
1108     }
1109     uksort($subDnLdapServer,"compareDn");
1110     return $subDnLdapServer;
1111   }
1112
1113  /**
1114   * Retourne les options d'une liste déroulante pour le choix du topDn
1115   * de connexion au serveur Ldap
1116   *
1117   * Liste les subdn (self :: $ldapServer['subDn'])
1118   *
1119   * @retval string Les options (<option>) pour la sélection du topDn.
1120   */
1121   public static function getSubDnLdapServerOptions($selected=NULL,$login=false) {
1122     $list = self :: getSubDnLdapServer($login);
1123     if ($list) {
1124       asort($list);
1125       $display='';
1126       foreach($list as $dn => $txt) {
1127         if ($selected && ($selected==$dn)) {
1128           $selected_txt = ' selected';
1129         }
1130         else {
1131           $selected_txt = '';
1132         }
1133         $display.="<option value=\"".$dn."\"$selected_txt>".$txt."</option>\n"; 
1134       }
1135       return $display;
1136     }
1137     return;
1138   }
1139
1140  /**
1141   * Vérifie qu'un subDn est déclaré
1142   *
1143   * @param[in] string Un subDn
1144   * 
1145   * @retval boolean True si le subDn existe, False sinon
1146   */
1147   public static function validSubDnLdapServer($subDn) {
1148     $listTopDn = self :: getSubDnLdapServer();
1149     if(is_array($listTopDn)) {
1150       foreach($listTopDn as $dn => $txt) {
1151         if ($subDn==$dn) {
1152           return true;
1153         } // end if
1154       } // end foreach
1155     } // end if
1156     return;
1157   }
1158
1159  /**
1160   * Test un couple LSobject/pwd
1161   *
1162   * Test un bind sur le serveur avec le dn de l'objet et le mot de passe fourni.
1163   *
1164   * @param[in] LSobject L'object "user" pour l'authentification
1165   * @param[in] string Le mot de passe Ã  tester
1166   *
1167   * @retval boolean True si l'authentification Ã  réussi, false sinon.
1168   */
1169   public static function checkUserPwd($object,$pwd) {
1170     return LSldap :: checkBind($object -> getValue('dn'),$pwd);
1171   }
1172
1173  /**
1174   * Affiche le formulaire de login
1175   *
1176   * Défini les informations pour le template Smarty du formulaire de login.
1177   *
1178   * @retval void
1179   */
1180   public static function displayLoginForm() {
1181     LStemplate :: assign('pagetitle',_('Connection'));
1182     if (isset($_GET['LSsession_logout'])) {
1183       LStemplate :: assign('loginform_action','index.php');
1184     }
1185     else {
1186       LStemplate :: assign('loginform_action',$_SERVER['REQUEST_URI']);
1187     }
1188     if (count(LSconfig :: get('ldap_servers'))==1) {
1189       LStemplate :: assign('loginform_ldapserver_style','style="display: none"');
1190     }
1191     LStemplate :: assign('loginform_label_ldapserver',_('LDAP server'));
1192     $ldapservers_name=array();
1193     $ldapservers_index=array();
1194     foreach(LSconfig :: get('ldap_servers') as $id => $infos) {
1195       $ldapservers_index[]=$id;
1196       $ldapservers_name[]=__($infos['name']);
1197     }
1198     LStemplate :: assign('loginform_ldapservers_name',$ldapservers_name);
1199     LStemplate :: assign('loginform_ldapservers_index',$ldapservers_index);
1200
1201     LStemplate :: assign('loginform_label_level',_('Level'));
1202     LStemplate :: assign('loginform_label_user',_('Identifier'));
1203     LStemplate :: assign('loginform_label_pwd',_('Password'));
1204     LStemplate :: assign('loginform_label_submit',_('Connect'));
1205     LStemplate :: assign('loginform_label_recoverPassword',_('Forgot your password ?'));
1206     
1207     self :: setTemplate('login.tpl');
1208     self :: addJSscript('LSsession_login.js');
1209   }
1210
1211  /**
1212   * Affiche le formulaire de récupération de mot de passe
1213   *
1214   * Défini les informations pour le template Smarty du formulaire de 
1215   * récupération de mot de passe
1216   * 
1217   * @param[in] $infos array() Information sur le status du processus de 
1218   *                           recouvrement de mot de passe
1219   *
1220   * @retval void
1221   */
1222   public static function displayRecoverPasswordForm($recoveryPasswordInfos) {
1223     LStemplate :: assign('pagetitle',_('Recovery of your credentials'));
1224     LStemplate :: assign('recoverpasswordform_action','index.php?LSsession_recoverPassword');
1225     
1226     if (count(LSconfig :: get('ldap_servers'))==1) {
1227       LStemplate :: assign('recoverpasswordform_ldapserver_style','style="display: none"');
1228     }
1229     
1230     LStemplate :: assign('recoverpasswordform_label_ldapserver',_('LDAP server'));
1231     $ldapservers_name=array();
1232     $ldapservers_index=array();
1233     foreach(LSconfig :: get('ldap_servers') as $id => $infos) {
1234       $ldapservers_index[]=$id;
1235       $ldapservers_name[]=$infos['name'];
1236     }
1237     LStemplate :: assign('recoverpasswordform_ldapservers_name',$ldapservers_name);
1238     LStemplate :: assign('recoverpasswordform_ldapservers_index',$ldapservers_index);
1239
1240     LStemplate :: assign('recoverpasswordform_label_user',_('Identifier'));
1241     LStemplate :: assign('recoverpasswordform_label_submit',_('Validate'));
1242     LStemplate :: assign('recoverpasswordform_label_back',_('Back'));
1243     
1244     $recoverpassword_msg = _('Please fill the identifier field to proceed recovery procedure');
1245     
1246     if (isset($recoveryPasswordInfos['recoveryHashMail'])) {
1247       $recoverpassword_msg = getFData(
1248         _("An email has been sent to  %{mail}. " .
1249         "Please follow the instructions on it."),
1250         $recoveryPasswordInfos['recoveryHashMail']
1251       );
1252     }
1253     
1254     if (isset($recoveryPasswordInfos['newPasswordMail'])) {
1255       $recoverpassword_msg = getFData(
1256         _("Your new password has been sent to %{mail}. "),
1257         $recoveryPasswordInfos['newPasswordMail']
1258       );
1259     }
1260     
1261     LStemplate :: assign('recoverpassword_msg',$recoverpassword_msg);
1262     
1263     self :: setTemplate('recoverpassword.tpl');
1264     self :: addJSscript('LSsession_recoverPassword.js');
1265   }
1266
1267  /**
1268   * Défini le template Smarty Ã  utiliser
1269   *
1270   * Remarque : les fichiers de templates doivent se trouver dans le dossier 
1271   * templates/.
1272   *
1273   * @param[in] string Le nom du fichier de template
1274   *
1275   * @retval void
1276   */
1277   public static function setTemplate($template) {
1278     self :: $template = $template;
1279   }
1280
1281  /**
1282   * Ajoute un script JS au chargement de la page
1283   *
1284   * Remarque : les scripts doivents Ãªtre dans le dossier LS_JS_DIR.
1285   *
1286   * @param[in] $script Le nom du fichier de script Ã  charger.
1287   *
1288   * @retval void
1289   */
1290   public static function addJSscript($file,$path=NULL) {
1291     $script=array(
1292       'file' => $file,
1293       'path' => $path
1294     );
1295     self :: $JSscripts[$path.$file]=$script;
1296   }
1297
1298  /**
1299   * Ajouter un paramètre de configuration Javascript
1300   * 
1301   * @param[in] $name string Nom de la variable de configuration
1302   * @param[in] $val mixed Valeur de la variable de configuration
1303   *
1304   * @retval void
1305   */
1306   public static function addJSconfigParam($name,$val) {
1307     self :: $_JSconfigParams[$name]=$val;
1308   }
1309
1310  /**
1311   * Ajoute une feuille de style au chargement de la page
1312   *
1313   * @param[in] $script Le nom du fichier css Ã  charger.
1314   *
1315   * @retval void
1316   */
1317   public static function addCssFile($file,$path=NULL) {
1318     if ($path) {
1319       $file = $path.$file;
1320     }
1321     else {
1322       $file = LStemplate :: getCSSPath($file);
1323     }
1324     self :: $CssFiles[$file]=$file;
1325   }
1326
1327  /**
1328   * Affiche le template Smarty
1329   *
1330   * Charge les dépendances et affiche le template Smarty
1331   *
1332   * @retval void
1333   */
1334   public static function displayTemplate() {
1335     // JS
1336     $JSscript_txt='';
1337     foreach ($GLOBALS['defaultJSscipts'] as $script) {
1338       $JSscript_txt.="<script src='".LS_JS_DIR.$script."' type='text/javascript'></script>\n";
1339     }
1340
1341     foreach (self :: $JSscripts as $script) {
1342       if (!$script['path']) {
1343         $script['path']=LS_JS_DIR;
1344       }
1345       else {
1346         $script['path'].='/';
1347       }
1348       $JSscript_txt.="<script src='".$script['path'].$script['file']."' type='text/javascript'></script>\n";
1349     }
1350
1351     $KAconf = LSconfig :: get('keepLSsessionActive');
1352     if ( 
1353           (
1354             (!isset(self :: $ldapServer['keepLSsessionActive']))
1355             &&
1356             (!($KAconf === false))
1357           )
1358           ||
1359           (self :: $ldapServer['keepLSsessionActive'])
1360         ) {
1361       self :: addJSconfigParam('keepLSsessionActive',ini_get('session.gc_maxlifetime'));
1362     }
1363
1364     LStemplate :: assign('LSjsConfig',json_encode(self :: $_JSconfigParams));
1365     
1366     if (LSdebug) {
1367       $JSscript_txt.="<script type='text/javascript'>LSdebug_active = 1;</script>\n";
1368     }
1369     else {
1370       $JSscript_txt.="<script type='text/javascript'>LSdebug_active = 0;</script>\n";
1371     }
1372     
1373     LStemplate :: assign('LSsession_js',$JSscript_txt);
1374
1375     // Css
1376     self :: addCssFile("LSdefault.css");
1377     if (isset($GLOBALS['defaultCSSfiles']) && is_array($GLOBALS['defaultCSSfiles'])) {
1378       foreach ($GLOBALS['defaultCSSfiles'] as $file) {
1379         self :: addCssFile($file);
1380       }
1381     }
1382     $Css_txt='';
1383     foreach (self :: $CssFiles as $file) {
1384       $Css_txt.="<link rel='stylesheet' type='text/css' href='".$file."' />\n";
1385     }
1386     LStemplate :: assign('LSsession_css',$Css_txt);
1387   
1388     if (isset(self :: $LSaccess[self :: $topDn])) {
1389       LStemplate :: assign('LSaccess',self :: $LSaccess[self :: $topDn]);
1390     }
1391     LStemplate :: assign('LSaddonsViewsAccess',self :: $LSaddonsViewsAccess);
1392     
1393     // Niveau
1394     $listTopDn = self :: getSubDnLdapServer();
1395     if (is_array($listTopDn)) {
1396       asort($listTopDn);
1397       LStemplate :: assign('label_level',self :: getSubDnLabel());
1398       LStemplate :: assign('_refresh',_('Refresh'));
1399       $LSsession_topDn_index = array();
1400       $LSsession_topDn_name = array();
1401       foreach($listTopDn as $index => $name) {
1402         $LSsession_topDn_index[]  = $index;
1403         $LSsession_topDn_name[]   = $name;
1404       }
1405       LStemplate :: assign('LSsession_subDn_indexes',$LSsession_topDn_index);
1406       LStemplate :: assign('LSsession_subDn_names',$LSsession_topDn_name);
1407       LStemplate :: assign('LSsession_subDn',self :: $topDn);
1408       LStemplate :: assign('LSsession_subDnName',self :: getSubDnName());
1409     }
1410     
1411     LStemplate :: assign('LSlanguages',self :: getLangList());
1412     LStemplate :: assign('LSlang',self :: $lang);
1413     LStemplate :: assign('LSencoding',self :: $encoding);
1414     LStemplate :: assign('lang_label',_('Language'));
1415     
1416     LStemplate :: assign('displayLogoutBtn',LSauth :: displayLogoutBtn());
1417     LStemplate :: assign('displaySelfAccess',LSauth :: displaySelfAccess());
1418
1419     // Infos
1420     if((!empty($_SESSION['LSsession_infos']))&&(is_array($_SESSION['LSsession_infos']))) {
1421       $txt_infos="<ul>\n";
1422       foreach($_SESSION['LSsession_infos'] as $info) {
1423         $txt_infos.="<li>$info</li>\n";
1424       }
1425       $txt_infos.="</ul>\n";
1426       LStemplate :: assign('LSinfos',$txt_infos);
1427       $_SESSION['LSsession_infos']=array();
1428     }
1429     
1430     if (self :: $ajaxDisplay) {
1431       LStemplate :: assign('LSerror_txt',LSerror :: getErrors());
1432       LStemplate :: assign('LSdebug_txt',LSdebug_print(true));
1433     }
1434     else {
1435       LSerror :: display();
1436       LSdebug_print();
1437     }
1438     if (!self :: $template)
1439       self :: setTemplate('empty.tpl');
1440       
1441     LStemplate :: assign('connected_as',_("Connected as"));
1442     
1443     LStemplate :: display(self :: $template);
1444   }
1445   
1446  /**
1447   * Défini que l'affichage se fera ou non via un retour Ajax
1448   * 
1449   * @param[in] $val boolean True pour que l'affichage se fasse par un retour
1450   *                         Ajax, false sinon
1451   * @retval void
1452   */
1453   public static function setAjaxDisplay($val=true) {
1454     self :: $ajaxDisplay = (boolean)$val;
1455   }
1456   
1457  /**
1458   * Affiche un retour Ajax
1459   *
1460   * @retval void
1461   */
1462   public static function displayAjaxReturn($data=array()) {
1463     if (isset($data['LSredirect']) && (!LSdebugDefined()) ) {
1464       echo json_encode($data);
1465       return;
1466     }
1467     
1468     $data['LSjsConfig'] = self :: $_JSconfigParams;
1469     
1470     // Infos
1471     if((!empty($_SESSION['LSsession_infos']))&&(is_array($_SESSION['LSsession_infos']))) {
1472       $txt_infos="<ul>\n";
1473       foreach($_SESSION['LSsession_infos'] as $info) {
1474         $txt_infos.="<li>$info</li>\n";
1475       }
1476       $txt_infos.="</ul>\n";
1477       $data['LSinfos'] = $txt_infos;
1478       $_SESSION['LSsession_infos']=array();
1479     }
1480     
1481     if (LSerror :: errorsDefined()) {
1482       $data['LSerror'] = LSerror :: getErrors();
1483     }
1484
1485     if (isset($_REQUEST['imgload'])) {
1486       $data['imgload'] = $_REQUEST['imgload'];
1487     }
1488
1489     if (LSdebugDefined()) {
1490       $data['LSdebug'] = LSdebug_print(true,false);
1491     }
1492
1493     echo json_encode($data);  
1494   }
1495  
1496  /**
1497   * Retournne un template Smarty compilé
1498   *
1499   * @param[in] string $template Le template à retourner
1500   * @param[in] array $variables Variables Smarty à assigner avant l'affichage
1501   * 
1502   * @retval string Le HTML compilé du template
1503   */
1504   public static function fetchTemplate($template,$variables=array()) {
1505     foreach($variables as $name => $val) {
1506       LStemplate :: assign($name,$val);
1507     }
1508     return LStemplate :: fetch($template);
1509   }
1510   
1511   /**
1512    * Prend un tableau de LSobject et le réduit en utilisant un filtre de
1513    * recherche sur un autre type de LSobject.
1514    *
1515    * Si une erreur est présente dans le tableau de définition du filtre, un
1516    * tableau vide est renvoyé.
1517    *
1518    * @param[in] string $LSobject le type LSobject par défaut
1519    * @param[in] array $set tableau de LSobject
1520    * @param[in] array $filter_def définition du filtre de recherche pour la réduction
1521    * @param[in] string $basend basedn pour la recherche, null par défaut
1522    *
1523    * @retval array le nouveau tableau de LSobject
1524    */
1525   private static function reduceLdapSet($LSobject, $set, $filter_def, $basedn=null) {
1526     if (empty($set)) {
1527       return array();
1528     }
1529
1530     if (! isset($filter_def['filter']) &&
1531           (! isset($filter_def['attr']) ||
1532            ! isset($filter_def['attr_value']))) {
1533       LSdebug("Filtre de profil LSobject invalide " . var_export($filter_def, true));
1534       return array();
1535     }
1536
1537     LSdebug('LSsession :: reducing set of');
1538     foreach ($set as $object) {
1539       LSdebug('LSsession :: -> ' . $object -> getDn());
1540     }
1541
1542     $LSobject = isset($filter_def['LSObject']) ? $filter_def['LSobject'] : $LSobject;
1543     LSdebug('LSobject :: ' . $LSobject);
1544     $filters = array();
1545     foreach ($set as $object) {
1546       if (isset($filter_def['filter'])) {
1547         $filters[] = $object -> getFData($filter_def['filter']);
1548       }
1549       else {
1550         $value = $object -> getFData($filter_def['attr_value']);
1551         $filters[] = Net_LDAP2_Filter::create($filter_def['attr'], 'equals', $value);
1552       }
1553     }
1554     $filter = LSldap::combineFilters('or', $filters);
1555     $params = array(
1556       'basedn' => isset($filter_def['basedn']) ? $filter_def['basedn'] : $basedn,
1557       'filter' => $filter,
1558     );
1559     if (isset($filter_def['params']) && is_array($filter_def['params'])) {
1560       $params = array_merge($filter_def['params'],$params);
1561     }
1562     $LSsearch = new LSsearch($LSobject,'LSsession :: loadLSprofiles',$params,true);
1563     $LSsearch -> run(false);
1564
1565     $set = $LSsearch -> listObjects();
1566     LSdebug('LSsession :: reduced set to');
1567     foreach ($set as $object) {
1568       LSdebug('LSsession :: -> ' . $object -> getDn());
1569     }
1570     return $set;
1571   }
1572
1573   /**
1574    * Charge les droits LS de l'utilisateur : uniquement du type LSobjects
1575    *
1576    * @param[in] string $
1577    *
1578    * @retval void
1579    */
1580   private static function loadLSprofilesLSobjects($profile, $LSobject, $listInfos) {
1581     if (! self :: loadLSclass('LSsearch')) {
1582       LSdebug('Impossible de charger la classe LSsearch');
1583       return;
1584     }
1585     # we are gonna grow a set of objects progressively, we start from the user
1586     $set = array(self :: getLSuserObject());
1587     $basedn = isset($listInfos['basedn']) ? $listInfos['basedn'] : null;
1588     $LSobject = isset($listInfos['LSobject']) ? $listInfos['LSobject'] : $LSobject;
1589
1590     if (isset($listInfos['filters']) && is_array($listInfos['filters'])) {
1591       foreach ($listInfos['filters'] as $filter_def) {
1592         $set = self :: reduceLdapSet($LSobject, $set, $filter_def, $basedn);
1593       }
1594     }
1595     if (isset($listInfos['filter']) || (isset($listInfos['attr']) && isset($listInfos['attr_value']))) {
1596       # support legacy profile definition
1597       $set = self :: reduceLdapSet($LSobject, $set, $listInfos, $basedn);
1598     }
1599
1600     $DNs = [];
1601     foreach ($set as $object) {
1602       $DNs[] = $object -> getDn();
1603     }
1604     if (!is_array(self :: $LSprofiles[$profile])) {
1605       self :: $LSprofiles[$profile]=$DNs;
1606     }
1607     else {
1608       foreach($DNs as $dn) {
1609         if (!in_array($dn,self :: $LSprofiles[$profile])) {
1610           self :: $LSprofiles[$profile][] = $dn;
1611         }
1612       }
1613     }
1614   }
1615
1616   /**
1617    * Charge les droits LS de l'utilisateur
1618    * 
1619    * @retval boolean True si le chargement Ã  réussi, false sinon.
1620    **/
1621   private static function loadLSprofiles() {
1622     if (is_array(self :: $ldapServer['LSprofiles'])) {
1623       foreach (self :: $ldapServer['LSprofiles'] as $profile => $profileInfos) {
1624         if (is_array($profileInfos)) {
1625           foreach ($profileInfos as $topDn => $rightsInfos) {
1626             /*
1627              * If $topDn == 'LSobject', we search for each LSobject type to find
1628              * all items on witch the user will have powers.
1629              */
1630             if ($topDn == 'LSobjects') {
1631               if (is_array($rightsInfos)) {
1632                 foreach ($rightsInfos as $LSobject => $listInfos) {
1633                   LSdebug('loading LSprofile ' . $profile . ' for LSobject ' . $LSobject . ' with params ' . var_export($listInfos, true));
1634                   self :: loadLSprofilesLSobjects($profile, $LSobject, $listInfos);
1635                 }
1636               }
1637               else {
1638                 LSdebug('LSobjects => [] doit etre un tableau');
1639               }
1640             }
1641             else {
1642               if (is_array($rightsInfos)) {
1643                 foreach($rightsInfos as $dn => $conf) {
1644                   if ((isset($conf['attr'])) && (isset($conf['LSobject']))) {
1645                     if( self :: loadLSobject($conf['LSobject']) ) {
1646                       if ($object = new $conf['LSobject']()) {
1647                         if ($object -> loadData($dn)) {
1648                           $listDns=$object -> getValue($conf['attr']);
1649                           $valKey = (isset($conf['attr_value']))?$conf['attr_value']:'%{dn}';
1650                           $val = self :: getLSuserObject() -> getFData($valKey);
1651                           if (is_array($listDns)) {
1652                             if (in_array($val,$listDns)) {
1653                               self :: $LSprofiles[$profile][] = $topDn;
1654                             }
1655                           }
1656                         }
1657                         else {
1658                           LSdebug('Impossible de chargé le dn : '.$dn);
1659                         }
1660                       }
1661                       else {
1662                         LSdebug('Impossible de créer l\'objet de type : '.$conf['LSobject']);
1663                       }
1664                     }
1665                   }
1666                   else {
1667                     if (self :: $dn == $dn) {
1668                       self :: $LSprofiles[$profile][] = $topDn;
1669                     }
1670                   }
1671                 }
1672               }
1673               else {
1674                 if ( self :: $dn == $rightsInfos ) {
1675                   self :: $LSprofiles[$profile][] = $topDn;
1676                 }
1677               }
1678             } // fin else ($topDn == 'LSobjects')
1679           } // fin foreach($profileInfos)
1680         } // fin is_array($profileInfos)
1681       } // fin foreach LSprofiles
1682       LSdebug(self :: $LSprofiles);
1683       return true;
1684     }
1685     else {
1686       return;
1687     }
1688   }
1689   
1690   /**
1691    * Charge les droits d'accès de l'utilisateur pour construire le menu de l'interface
1692    *
1693    * @retval void
1694    */
1695   private static function loadLSaccess() {
1696     $LSaccess=array();
1697     if (isset(self :: $ldapServer['subDn']) && is_array(self :: $ldapServer['subDn'])) {
1698       foreach(self :: $ldapServer['subDn'] as $name => $config) {
1699         if ($name=='LSobject') {
1700           if (is_array($config)) {
1701
1702             // Définition des subDns 
1703             foreach($config as $objectType => $objectConf) {
1704               if (self :: loadLSobject($objectType)) {
1705                 if ($subdnobject = new $objectType()) {
1706                   $tbl = $subdnobject -> getSelectArray(NULL,self::getRootDn(),NULL,NULL,false);
1707                   if (is_array($tbl)) {
1708                     // Définition des accès
1709                     $access=array();
1710                     if (is_array($objectConf['LSobjects'])) {
1711                       foreach($objectConf['LSobjects'] as $type) {
1712                         if (self :: loadLSobject($type)) {
1713                           if (self :: canAccess($type)) {
1714                             $access[$type] = LSconfig :: get('LSobjects.'.$type.'.label');
1715                           }
1716                         }
1717                       }
1718                     }
1719                     foreach($tbl as $dn => $dn_name) {
1720                       $LSaccess[$dn]=$access;
1721                     }
1722                   }
1723                 }
1724               }
1725             }
1726           }
1727         }
1728         else {
1729           if ((isCompatibleDNs(self :: $ldapServer['ldap_config']['basedn'],$config['dn']))&&($config['dn']!='')) {
1730             $access=array();
1731             if (is_array($config['LSobjects'])) {
1732               foreach($config['LSobjects'] as $objectType) {
1733                 if (self :: loadLSobject($objectType)) {
1734                   if (self :: canAccess($objectType)) {
1735                     $access[$objectType] = LSconfig :: get('LSobjects.'.$objectType.'.label');
1736                   }
1737                 }
1738               }
1739             }
1740             $LSaccess[$config['dn']]=$access;
1741           }
1742         }
1743       }
1744     }
1745     else {
1746       if(is_array(self :: $ldapServer['LSaccess'])) {
1747         $access=array();
1748         foreach(self :: $ldapServer['LSaccess'] as $objectType) {
1749           if (self :: loadLSobject($objectType)) {
1750             if (self :: canAccess($objectType)) {
1751                 $access[$objectType] = LSconfig :: get('LSobjects.'.$objectType.'.label');
1752             }
1753           }
1754         }
1755         $LSaccess[self :: $topDn] = $access;
1756       }
1757     }
1758     if (LSauth :: displaySelfAccess()) {
1759       foreach($LSaccess as $dn => $access) {
1760         $LSaccess[$dn] = array_merge(
1761           array(
1762             'SELF' => 'My account'
1763           ),
1764           $access
1765         );
1766       }
1767     }
1768     self :: $LSaccess = $LSaccess;
1769     $_SESSION['LSsession']['LSaccess'] = $LSaccess;
1770   }
1771
1772   /**
1773    * Load user access to LSaddons views
1774    *
1775    * @retval void
1776    */
1777   private static function loadLSaddonsViewsAccess() {
1778     $LSaddonsViewsAccess=array();
1779     foreach (self :: $LSaddonsViews as $addon => $conf) {
1780       foreach ($conf as $viewId => $viewConf) {
1781         if (self :: canAccessLSaddonView($addon,$viewId)) {
1782           $LSaddonsViewsAccess[]=array (
1783             'LSaddon' => $addon,
1784             'id' => $viewId,
1785             'label' => $viewConf['label'],
1786             'showInMenu' => $viewConf['showInMenu']
1787           );
1788         }
1789       }
1790     }
1791     self :: $LSaddonsViewsAccess = $LSaddonsViewsAccess;
1792     $_SESSION['LSsession']['LSaddonsViewsAccess'] = $LSaddonsViewsAccess;
1793   }
1794
1795
1796   /**
1797    * Dit si l'utilisateur est du profil pour le DN spécifié
1798    *
1799    * @param[in] string $profile de l'objet
1800    * @param[in] string $dn DN de l'objet
1801    * 
1802    * @retval boolean True si l'utilisateur est du profil sur l'objet, false sinon.
1803    */
1804   public static function isLSprofile($dn,$profile) {
1805     if (is_array(self :: $LSprofiles[$profile])) {
1806       foreach(self :: $LSprofiles[$profile] as $topDn) {
1807         if($dn == $topDn) {
1808           return true;
1809         }
1810         else if ( isCompatibleDNs($dn,$topDn) ) {
1811           return true;
1812         }
1813       }
1814     }
1815     return;
1816   }
1817   
1818   /**
1819    * Retourne qui est l'utilisateur par rapport Ã  l'object
1820    *
1821    * @param[in] string Le DN de l'objet
1822    * 
1823    * @retval string 'admin'/'self'/'user' pour Admin , l'utilisateur lui même ou un simple utilisateur
1824    */
1825   public static function whoami($dn) {
1826     $retval = array('user');
1827     
1828     foreach(self :: $LSprofiles as $profile => $infos) {
1829       if(self :: isLSprofile($dn,$profile)) {
1830        $retval[]=$profile;
1831       }
1832     }
1833     
1834     if (self :: $dn == $dn) {
1835       $retval[]='self';
1836     }
1837     
1838     return $retval;
1839   }
1840   
1841   /**
1842    * Retourne le droit de l'utilisateur Ã  accèder Ã  un objet
1843    * 
1844    * @param[in] string $LSobject Le type de l'objet
1845    * @param[in] string $dn Le DN de l'objet (le container_dn du type de l'objet par défaut)
1846    * @param[in] string $right Le type de droit d'accès Ã  tester ('r'/'w')
1847    * @param[in] string $attr Le nom de l'attribut auquel on test l'accès
1848    *
1849    * @retval boolean True si l'utilisateur a accès, false sinon
1850    */
1851   public static function canAccess($LSobject,$dn=NULL,$right=NULL,$attr=NULL) {
1852     if (!self :: loadLSobject($LSobject)) {
1853       return;
1854     }
1855     if ($dn) {
1856       $whoami = self :: whoami($dn);
1857       if ($dn==self :: getLSuserObject() -> getValue('dn')) {
1858         if (!self :: in_menu('SELF')) {
1859           return;
1860         }
1861       }
1862       else {
1863         $obj = new $LSobject();
1864         $obj -> dn = $dn;
1865         if (!self :: in_menu($LSobject,$obj -> subDnValue)) {
1866           return;
1867         }
1868       }
1869     }
1870     else {
1871       $objectdn=LSconfig :: get('LSobjects.'.$LSobject.'.container_dn').','.self :: $topDn;
1872       $whoami = self :: whoami($objectdn);
1873     }
1874     
1875     // Pour un attribut particulier
1876     if ($attr) {
1877       if ($attr=='rdn') {
1878         $attr=LSconfig :: get('LSobjects.'.$LSobject.'.rdn');
1879       }
1880       if (!is_array(LSconfig :: get('LSobjects.'.$LSobject.'.attrs.'.$attr))) {
1881         return;
1882       }
1883
1884       $r = 'n';
1885       foreach($whoami as $who) {
1886         $nr = LSconfig :: get('LSobjects.'.$LSobject.'.attrs.'.$attr.'.rights.'.$who);
1887         if($nr == 'w') {
1888           $r = 'w';
1889         }
1890         else if($nr == 'r') {
1891           if ($r=='n') {
1892             $r='r';
1893           }
1894         }
1895       }
1896       
1897       if (($right=='r')||($right=='w')) {
1898         if ($r==$right) {
1899           return true;
1900         }
1901         return;
1902       }
1903       else {
1904         if ( ($r=='r') || ($r=='w') ) {
1905           return true;
1906         }
1907         return;
1908       }
1909     }
1910     
1911     // Pour un attribut quelconque
1912     $attrs_conf=LSconfig :: get('LSobjects.'.$LSobject.'.attrs');
1913     if (is_array($attrs_conf)) {
1914       if (($right=='r')||($right=='w')) {
1915         foreach($whoami as $who) {
1916           foreach ($attrs_conf as $attr_name => $attr_config) {
1917             if (isset($attr_config['rights'][$who]) && $attr_config['rights'][$who]==$right) {
1918               return true;
1919             }
1920           }
1921         }
1922       }
1923       else {
1924         foreach($whoami as $who) {
1925           foreach ($attrs_conf as $attr_name => $attr_config) {
1926             if ( (isset($attr_config['rights'][$who])) && ( ($attr_config['rights'][$who]=='r') || ($attr_config['rights'][$who]=='w') ) ) {
1927               return true;
1928             }
1929           }
1930         }
1931       }
1932     }
1933     return;
1934   }
1935   
1936   /**
1937    * Retourne le droit de l'utilisateur Ã  editer Ã  un objet
1938    * 
1939    * @param[in] string $LSobject Le type de l'objet
1940    * @param[in] string $dn Le DN de l'objet (le container_dn du type de l'objet par défaut)
1941    * @param[in] string $attr Le nom de l'attribut auquel on test l'accès
1942    *
1943    * @retval boolean True si l'utilisateur a accès, false sinon
1944    */
1945   public static function canEdit($LSobject,$dn=NULL,$attr=NULL) {
1946     return self :: canAccess($LSobject,$dn,'w',$attr);
1947   }
1948
1949   /**
1950    * Retourne le droit de l'utilisateur Ã  supprimer un objet
1951    * 
1952    * @param[in] string $LSobject Le type de l'objet
1953    * @param[in] string $dn Le DN de l'objet (le container_dn du type de l'objet par défaut)
1954    *
1955    * @retval boolean True si l'utilisateur a accès, false sinon
1956    */  
1957   public static function canRemove($LSobject,$dn) {
1958     return self :: canAccess($LSobject,$dn,'w','rdn');
1959   }
1960   
1961   /**
1962    * Retourne le droit de l'utilisateur Ã  créer un objet
1963    * 
1964    * @param[in] string $LSobject Le type de l'objet
1965    *
1966    * @retval boolean True si l'utilisateur a accès, false sinon
1967    */    
1968   public static function canCreate($LSobject) {
1969     if (!self :: loadLSobject($LSobject)) {
1970       return;
1971     }
1972     if (LSconfig :: get("LSobjects.$LSobject.disable_creation")) {
1973       return;
1974     }
1975     return self :: canAccess($LSobject,NULL,'w','rdn');
1976   }
1977   
1978   /**
1979    * Retourne le droit de l'utilisateur Ã  gérer la relation d'objet
1980    * 
1981    * @param[in] string $dn Le DN de l'objet (le container_dn du type de l'objet par défaut)
1982    * @param[in] string $LSobject Le type de l'objet
1983    * @param[in] string $relationName Le nom de la relation avec l'objet
1984    * @param[in] string $right Le type de droit a vérifier ('r' ou 'w')
1985    *
1986    * @retval boolean True si l'utilisateur a accès, false sinon
1987    */
1988   public static function relationCanAccess($dn,$LSobject,$relationName,$right=NULL) {
1989     $relConf=LSconfig :: get('LSobjects.'.$LSobject.'.LSrelation.'.$relationName);
1990     if (!is_array($relConf))
1991       return;
1992     $whoami = self :: whoami($dn);
1993
1994     if (($right=='w') || ($right=='r')) {
1995       $r = 'n';
1996       foreach($whoami as $who) {
1997         $nr = ((isset($relConf['rights'][$who]))?$relConf['rights'][$who]:'');
1998         if($nr == 'w') {
1999           $r = 'w';
2000         }
2001         else if($nr == 'r') {
2002           if ($r=='n') {
2003             $r='r';
2004           }
2005         }
2006       }
2007       
2008       if ($r == $right) {
2009         return true;
2010       }
2011     }
2012     else {
2013       foreach($whoami as $who) {
2014         if ((isset($relConf['rights'][$who])) && ( ($relConf['rights'][$who] == 'w') || ($relConf['rights'][$who] == 'r') ) ) {
2015           return true;
2016         }
2017       }
2018     }
2019     return;
2020   }
2021
2022   /**
2023    * Retourne le droit de l'utilisateur Ã  modifier la relation d'objet
2024    * 
2025    * @param[in] string $dn Le DN de l'objet (le container_dn du type de l'objet par défaut)
2026    * @param[in] string $LSobject Le type de l'objet
2027    * @param[in] string $relationName Le nom de la relation avec l'objet
2028    *
2029    * @retval boolean True si l'utilisateur a accès, false sinon
2030    */  
2031   public static function relationCanEdit($dn,$LSobject,$relationName) {
2032     return self :: relationCanAccess($dn,$LSobject,$relationName,'w');
2033   }
2034
2035   /**
2036    * Retourne le droit de l'utilisateur a executer une customAction
2037    * 
2038    * @param[in] string $dn Le DN de l'objet
2039    * @param[in] string $LSobject Le type de l'objet
2040    * @param[in] string $customActionName Le nom de la customAction
2041    *
2042    * @retval boolean True si l'utilisateur peut executer cette customAction, false sinon
2043    */
2044   public static function canExecuteCustomAction($dn,$LSobject,$customActionName) {
2045     $conf=LSconfig :: get('LSobjects.'.$LSobject.'.customActions.'.$customActionName);
2046     if (!is_array($conf))
2047       return;
2048     $whoami = self :: whoami($dn);
2049
2050     if (isset($conf['rights']) && is_array($conf['rights'])) {
2051       foreach($whoami as $who) {
2052         if (in_array($who,$conf['rights'])) {
2053           return True;
2054         }
2055       }
2056     }
2057     
2058     return;
2059   }
2060
2061   /**
2062    * Retourne le droit de l'utilisateur a executer une customAction
2063    * sur une recherche
2064    *
2065    * @param[in] string $LSsearch L'objet LSsearch
2066    * @param[in] string $customActionName Le nom de la customAction
2067    *
2068    * @retval boolean True si l'utilisateur peut executer cette customAction, false sinon
2069    */
2070   public static function canExecuteLSsearchCustomAction($LSsearch,$customActionName) {
2071     $conf=LSconfig :: get('LSobjects.'.$LSsearch -> LSobject.'.LSsearch.customActions.'.$customActionName);
2072     if (!is_array($conf))
2073       return;
2074     $dn=$LSsearch -> basedn;
2075     if (is_null($dn)) $dn=self::getTopDn();
2076
2077     $whoami = self :: whoami($dn);
2078
2079     if (isset($conf['rights']) && is_array($conf['rights'])) {
2080       foreach($whoami as $who) {
2081         if (in_array($who,$conf['rights'])) {
2082           return True;
2083         }
2084       }
2085     }
2086
2087     return;
2088   }
2089
2090   /**
2091    * Return user right to access to a LSaddon view
2092    *
2093    * @param[in] string $LSaddon The LSaddon
2094    * @param[in] string $viewId The LSaddon view ID
2095    *
2096    * @retval boolean True if user is allowed, false otherwise
2097    */
2098   public static function canAccessLSaddonView($LSaddon,$viewId) {
2099     if (self :: loadLSaddon($LSaddon)) {
2100       if (!isset(self :: $LSaddonsViews[$LSaddon]) || !isset(self :: $LSaddonsViews[$LSaddon][$viewId]))
2101       return;
2102       if (!is_array(self :: $LSaddonsViews[$LSaddon][$viewId]['allowedLSprofiles'])) {
2103         return true;
2104       }
2105       $whoami = self :: whoami(self :: $topDn);
2106
2107       if (isset(self :: $LSaddonsViews[$LSaddon][$viewId]['allowedLSprofiles']) && is_array(self :: $LSaddonsViews[$LSaddon][$viewId]['allowedLSprofiles'])) {
2108         foreach($whoami as $who) {
2109           if (in_array($who,self :: $LSaddonsViews[$LSaddon][$viewId]['allowedLSprofiles'])) {
2110             return True;
2111           }
2112         }
2113       }
2114     }
2115     return;
2116   }
2117
2118
2119   /**
2120    * Ajoute un fichier temporaire
2121    * 
2122    * @author Benjamin Renard <brenard@easter-eggs.com>
2123    * 
2124    * @retval void
2125    **/
2126   public static function addTmpFile($value,$filePath) {
2127     $hash = mhash(MHASH_MD5,$value);
2128     self :: $tmp_file[$filePath] = $hash;
2129     $_SESSION['LSsession']['tmp_file'][$filePath] = $hash;
2130   }
2131   
2132   /**
2133    * Retourne le chemin du fichier temporaire si l'existe
2134    * 
2135    * @author Benjamin Renard <brenard@easter-eggs.com>
2136    * 
2137    * @param[in] $value La valeur du fichier
2138    * 
2139    * @retval mixed 
2140    **/
2141   public static function tmpFileExist($value) {
2142     $hash = mhash(MHASH_MD5,$value);
2143     foreach(self :: $tmp_file as $filePath => $contentHash) {
2144       if ($hash == $contentHash) {
2145         return $filePath;
2146       }
2147     }
2148     return false;
2149   }
2150   
2151   /**
2152    * Retourne le chemin du fichier temporaire
2153    * 
2154    * Retourne le chemin du fichier temporaire qu'il créera Ã  partir de la valeur
2155    * s'il n'existe pas déjà.
2156    * 
2157    * @author Benjamin Renard <brenard@easter-eggs.com>
2158    * 
2159    * @param[in] $value La valeur du fichier
2160    * 
2161    * @retval mixed 
2162    **/
2163   public static function getTmpFile($value) {
2164     $exist = self :: tmpFileExist($value);
2165     if (!$exist) {
2166       $img_path = LS_TMP_DIR .rand().'.tmp';
2167       $fp = fopen($img_path, "w");
2168       fwrite($fp, $value);
2169       fclose($fp);
2170       self :: addTmpFile($value,$img_path);
2171       return $img_path;
2172     }
2173     else {
2174       return $exist;
2175     }
2176   }
2177   
2178   /**
2179    * Supprime les fichiers temporaires
2180    * 
2181    * @author Benjamin Renard <brenard@easter-eggs.com>
2182    * 
2183    * @retval void
2184    **/
2185   public static function deleteTmpFile($filePath=NULL) {
2186     if ($filePath) {
2187         @unlink($filePath);
2188         unset(self :: $tmp_file[$filePath]);
2189         unset($_SESSION['LSsession']['tmp_file'][$filePath]);
2190     }
2191     else {
2192       foreach(self :: $tmp_file as $file => $content) {
2193         @unlink($file);
2194       }
2195       self :: $tmp_file = array();
2196       $_SESSION['LSsession']['tmp_file'] = array();
2197     }
2198   }
2199
2200   /**
2201    * Retourne true si le cache des droits est activé
2202    *
2203    * @author Benjamin Renard <brenard@easter-eggs.com>
2204    * 
2205    * @retval boolean True si le cache des droits est activé, false sinon.
2206    */
2207   public static function cacheLSprofiles() {
2208     return ( (LSconfig :: get('cacheLSprofiles')) || (self :: $ldapServer['cacheLSprofiles']) );
2209   }
2210
2211   /**
2212    * Retourne true si le cache des subDn est activé
2213    *
2214    * @author Benjamin Renard <brenard@easter-eggs.com>
2215    * 
2216    * @retval boolean True si le cache des subDn est activé, false sinon.
2217    */
2218   public static function cacheSudDn() {
2219     return ( (LSconfig :: get('cacheSubDn')) || (self :: $ldapServer['cacheSubDn']));
2220   }
2221   
2222   /**
2223    * Retourne true si le cache des recherches est activé
2224    *
2225    * @author Benjamin Renard <brenard@easter-eggs.com>
2226    * 
2227    * @retval boolean True si le cache des recherches est activé, false sinon.
2228    */
2229   public static function cacheSearch() {
2230     return ( (LSconfig :: get('cacheSearch')) || (self :: $ldapServer['cacheSearch']));
2231   }
2232   
2233   /**
2234    * Retourne le label des niveaux pour le serveur ldap courant
2235    * 
2236    * @author Benjamin Renard <brenard@easter-eggs.com>
2237    * 
2238    * @retval string Le label des niveaux pour le serveur ldap dourant
2239    */
2240   public static function getSubDnLabel() {
2241     return (self :: $ldapServer['subDnLabel']!='')?__(self :: $ldapServer['subDnLabel']):_('Level');
2242   }
2243   
2244   /**
2245    * Retourne le nom du subDn
2246    * 
2247    * @param[in] $subDn string subDn
2248    * 
2249    * @retval string Le nom du subDn ou '' sinon
2250    */
2251   public static function getSubDnName($subDn=false) {
2252     if (!$subDn) {
2253       $subDn = self :: $topDn;
2254     }
2255     if (self :: getSubDnLdapServer(false)) {
2256       if (isset(self :: $_subDnLdapServer[self :: $ldapServerId][false][$subDn])) {
2257         return self :: $_subDnLdapServer[self :: $ldapServerId][false][$subDn];
2258       }
2259     }
2260     return '';
2261   }
2262
2263   /**
2264    * L'objet est t-il utilisé pour listé les subDnS
2265    * 
2266    * @param[in] $type string Le type d'objet
2267    * 
2268    * @retval boolean true si le type d'objet est un subDnObject, false sinon
2269    */
2270   public static function isSubDnLSobject($type) {
2271     $result = false;
2272     if (isset(self :: $ldapServer['subDn']['LSobject']) && is_array(self :: $ldapServer['subDn']['LSobject'])) {
2273       foreach(self :: $ldapServer['subDn']['LSobject'] as $key => $value) {
2274         if ($key==$type) {
2275           $result=true;
2276         }
2277       }
2278     }
2279     return $result;
2280   }
2281   
2282   /**
2283    * Indique si un type d'objet est dans le menu courant
2284    * 
2285    * @retval boolean true si le type d'objet est dans le menu, false sinon
2286    */
2287   public static function in_menu($LSobject,$topDn=NULL) {
2288     if (!$topDn) {
2289       $topDn=self :: $topDn;
2290     }
2291     return isset(self :: $LSaccess[$topDn][$LSobject]);
2292   }
2293   
2294   /**
2295    * Indique si le serveur LDAP courant a des subDn
2296    * 
2297    * @retval boolean true si le serveur LDAP courant a des subDn, false sinon
2298    */
2299   public static function haveSubDn() {
2300     return (isset(self :: $ldapServer['subDn']) && is_array(self :: $ldapServer['subDn']));
2301   }
2302
2303   /**
2304    * Ajoute une information à afficher
2305    * 
2306    * @param[in] $msg string Le message à afficher
2307    * 
2308    * @retval void
2309    */
2310   public static function addInfo($msg) {
2311     $_SESSION['LSsession_infos'][]=$msg;
2312   }
2313   
2314   /**
2315    * Redirection de l'utilisateur vers une autre URL
2316    * 
2317    * @param[in] $url string L'URL
2318    * @param[in] $exit boolean Si true, l'execution script s'arrête après la redirection
2319    * 
2320    * @retval void
2321    */  
2322   public static function redirect($url,$exit=true) {
2323     LStemplate :: assign('url',$url);
2324     LStemplate :: display('redirect.tpl');
2325     if ($exit) {
2326       exit();
2327     }
2328   }
2329   
2330   /**
2331    * Retourne l'adresse mail d'emission configurée pour le serveur courant
2332    * 
2333    * @retval string Adresse mail d'emission
2334    */
2335   public static function getEmailSender() {
2336     return self :: $ldapServer['emailSender'];  
2337   }
2338   
2339   /**
2340    * Ajout d'une information d'aide
2341    * 
2342    * @param[in] $group string Le nom du groupe d'infos dans lequels ajouter
2343    *                          celle-ci
2344    * @param[in] $infos array  Tableau array(name => value) des infos
2345    * 
2346    * @retval void
2347    */
2348   public static function addHelpInfos($group,$infos) {
2349     if (is_array($infos)) {
2350       if (isset(self :: $_JSconfigParams['helpInfos'][$group]) && is_array(self :: $_JSconfigParams['helpInfos'][$group])) {
2351         self :: $_JSconfigParams['helpInfos'][$group] = array_merge(self :: $_JSconfigParams['helpInfos'][$group],$infos);
2352       }
2353       else {
2354         self :: $_JSconfigParams['helpInfos'][$group] = $infos;
2355       }
2356     }
2357   }
2358   
2359  /**
2360   * Défini les codes erreur relative à la classe LSsession
2361   * 
2362   * @retval void
2363   */  
2364   private static function defineLSerrors() {
2365     /*
2366      * Error Codes
2367      */
2368     LSerror :: defineError('LSsession_01',
2369     _("LSsession : The constant %{const} is not defined.")
2370     );
2371     LSerror :: defineError('LSsession_02',
2372     _("LSsession : The %{addon} support is uncertain. Verify system compatibility and the add-on configuration.")
2373     );
2374     LSerror :: defineError('LSsession_03',
2375     _("LSsession : LDAP server's configuration data are invalid. Can't connect.")
2376     );
2377     LSerror :: defineError('LSsession_04',
2378     _("LSsession : Failed to load LSobject type %{type} : unknon type.")
2379     );
2380     LSerror :: defineError('LSsession_05',
2381     _("LSsession : Failed to load LSclass %{class}.")
2382     );
2383     LSerror :: defineError('LSsession_06',
2384     _("LSsession : Login or password incorrect.")
2385     );
2386     LSerror :: defineError('LSsession_07',
2387     _("LSsession : Impossible to identify you : Duplication of identities.")
2388     );
2389     LSerror :: defineError('LSsession_08',
2390     _("LSsession : Can't load class of authentification (%{class}).")
2391     );
2392     LSerror :: defineError('LSsession_09',
2393     _("LSsession : Can't connect to LDAP server.")
2394     );
2395     LSerror :: defineError('LSsession_10',
2396     _("LSsession : Impossible to authenticate you.")
2397     );
2398     LSerror :: defineError('LSsession_11',
2399     _("LSsession : Your are not authorized to do this action.")
2400     );
2401     LSerror :: defineError('LSsession_12',
2402     _("LSsession : Some informations are missing to display this page.")
2403     );
2404     LSerror :: defineError('LSsession_13',
2405     _("LSsession : The function of the custom action %{name} does not exists or is not configured.")
2406     );
2407     LSerror :: defineError('LSsession_14',
2408     _("LSsession : Fail to retreive user's LDAP credentials from LSauth.")
2409     );
2410     LSerror :: defineError('LSsession_15',
2411     _("LSsession : Fail to reconnect to LDAP server with user's LDAP credentials.")
2412     );
2413     LSerror :: defineError('LSsession_16',
2414     _("LSsession : No import/export format define for this object type.")
2415     );
2416     LSerror :: defineError('LSsession_17',
2417     _("LSsession : Error during creation of list of levels. Contact administrators. (Code : %{code})")
2418     );
2419     LSerror :: defineError('LSsession_18',
2420     _("LSsession : The password recovery is disabled for this LDAP server.")
2421     );
2422     LSerror :: defineError('LSsession_19',
2423     _("LSsession : Some informations are missing to recover your password. Contact administrators.")
2424     );
2425     LSerror :: defineError('LSsession_20',
2426     _("LSsession : Error during password recovery. Contact administrators.(Step : %{step})")
2427     );
2428     LSerror :: defineError('LSsession_21',
2429     _("LSsession : call function %{func} do not provided from LSaddon %{addon}.")
2430     );
2431     LSerror :: defineError('LSsession_22',
2432     _("LSsession : problem during initialisation.")
2433     );
2434     LSerror :: defineError('LSsession_23',
2435     _("LSsession : view function %{func} for LSaddon %{addon} doet not exist.")
2436     );
2437   }
2438
2439   /**
2440    * Ajax method when change ldapserver on login form
2441    * 
2442    * @param[in] $data array The return data address
2443    * 
2444    * @retval void
2445    **/
2446   public static function ajax_onLdapServerChangedLogin(&$data) {  
2447     if ( isset($_REQUEST['server']) ) {
2448       self :: setLdapServer($_REQUEST['server']);
2449       $data = array();
2450       if ( self :: LSldapConnect() ) {
2451         if (session_id()=="") session_start();
2452         if (isset($_SESSION['LSsession_topDn'])) {
2453           $sel = $_SESSION['LSsession_topDn'];
2454         }
2455         else {
2456           $sel = NULL;
2457         }
2458         $list = self :: getSubDnLdapServerOptions($sel,true);
2459         if (is_string($list)) {
2460           $data['list_topDn'] = "<select name='LSsession_topDn' id='LSsession_topDn'>".$list."</select>";
2461           $data['subDnLabel'] = self :: getSubDnLabel();
2462         }
2463       }
2464       $data['recoverPassword'] = isset(self :: $ldapServer['recoverPassword']);
2465     }
2466   }
2467   
2468   /**
2469    * Ajax method when change ldapserver on recoverPassword form
2470    * 
2471    * @param[in] $data array The return data address
2472    * 
2473    * @retval void
2474    **/
2475   public static function ajax_onLdapServerChangedRecoverPassword(&$data) {  
2476     if ( isset($_REQUEST['server']) ) {
2477       self :: setLdapServer($_REQUEST['server']);
2478       $data=array('recoverPassword' => isset(self :: $ldapServer['recoverPassword']));
2479     }
2480   }
2481
2482   /**
2483    * Set globals from the ldap server
2484    *
2485    * @retval void
2486    */
2487   public static function setGlobals() {
2488     if ( isset(self :: $ldapServer['globals'])) {
2489       foreach(self :: $ldapServer['globals'] as $key => $value) {
2490         $GLOBALS[$key] = $value;
2491       }
2492     }
2493   }
2494
2495   /**
2496    * Register a LSaddon view
2497    *
2498    * @param[in] $LSaddon string The LSaddon
2499    * @param[in] $viewId string The view ID
2500    * @param[in] $label string The view's label
2501    * @param[in] $viewFunction string The view's function name
2502    * @param[in] $allowedLSprofiles array|null Array listing allowed profiles.
2503    *                                          If null, no access control will
2504    *                                          be done for this view.
2505    * @param[in] $showInMenu boolean Show (or not) this view in menu
2506    *
2507    * @retval bool True is the view have been registred, false otherwise
2508    **/
2509   public static function registerLSaddonView($LSaddon,$viewId,$label,$viewFunction,$allowedLSprofiles=null,$showInMenu=True) {
2510     if (function_exists($viewFunction)) {
2511       $func = new ReflectionFunction($viewFunction);
2512       if (basename($func->getFileName())=="LSaddons.$LSaddon.php") {
2513         self :: $LSaddonsViews[$LSaddon][$viewId]=array (
2514           'LSaddon' => $LSaddon,
2515           'label' => $label,
2516           'function' => $viewFunction,
2517           'allowedLSprofiles' => $allowedLSprofiles,
2518           'showInMenu' => (bool)$showInMenu
2519         );
2520         return True;
2521       }
2522       else {
2523         LSerror :: addErrorCode('LSsession_21',array('func' => $func -> getName(),'addon' => $addon));
2524       }
2525     }
2526     else {
2527       LSerror :: addErrorCode('LSsession_23',array('func' => $viewFunction,'addon' => $LSaddon));
2528     }
2529     return False;
2530   }
2531
2532   /**
2533    * Show LSaddon view
2534    *
2535    * @param[in] $LSaddon string The LSaddon
2536    * @param[in] $viewId string The view ID
2537    *
2538    * @retval void
2539    **/
2540   public static function showLSaddonView($LSaddon,$viewId) {
2541     if (self :: canAccessLSaddonView($LSaddon,$viewId)) {
2542       call_user_func(self :: $LSaddonsViews[$LSaddon][$viewId]['function']);
2543     }
2544   }
2545 }