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