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