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