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