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