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