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