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