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