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