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