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