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