- Modification des templates :
[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
25 /**
26  * Gestion des sessions
27  *
28  * Cette classe gère les sessions d'utilisateurs.
29  *
30  * @author Benjamin Renard <brenard@easter-eggs.com>
31  */
32 class LSsession {
33
34   var $confDir = NULL;
35   var $ldapServer = NULL;
36   var $ldapServerId = NULL;
37   var $topDn = NULL;
38   var $LSuserObject = NULL;
39   var $dn = NULL;
40   var $rdn = NULL;
41   var $JSscripts = array();
42   var $CssFiles = array();
43   var $template = NULL;
44   var $LSrights = array (
45     'topDn_admin' => array ()
46   );
47   var $LSaccess = array();
48   var $tmp_file = array();
49   var $_subDnLdapServer = array();
50   var $ajaxDisplay = false;
51
52   /**
53    * Constructeur
54    *
55    * @author Benjamin Renard <brenard@easter-eggs.com>
56    *
57    * @retval void
58    */
59   function LSsession ($configDir=LS_DEFAULT_CONF_DIR) {
60     $this -> confDir = $configDir;
61     if ($this -> loadConfig()) {
62       $this -> startLSerror();
63     }
64     else {
65       return;
66     }
67   }
68
69  /**
70   * Chargement de la configuration
71   *
72   * Chargement des fichiers de configuration et création de l'objet Smarty.
73   *
74   * @author Benjamin Renard <brenard@easter-eggs.com>
75   *
76   * @retval true si tout c'est bien passé, false sinon
77   */
78   function loadConfig() {
79     if (loadDir($this -> confDir, '^config\..*\.php$')) {
80       if ( include_once $GLOBALS['LSconfig']['Smarty'] ) {
81         $GLOBALS['Smarty'] = new Smarty();
82         return true;
83       }
84       else {
85         die($GLOBALS['LSerror_code'][1008]['msg']);
86         return;
87       }
88       return true;
89     }
90     else {
91       return;
92     }
93   }
94
95  /**
96   * Initialisation de la gestion des erreurs
97   *
98   * Création de l'objet LSerror
99   *
100   * @author Benjamin Renard <brenard@easter-eggs.com
101   *
102   * @retval boolean true si l'initialisation a réussi, false sinon.
103   */
104   function startLSerror() {
105     if(!$this -> loadLSclass('LSerror'))
106       return;
107     $GLOBALS['LSerror'] = new LSerror();
108     return true;
109   }
110
111  /**
112   * Chargement d'une classe d'LdapSaisie
113   *
114   * @param[in] $class Nom de la classe Ã  charger (Exemple : LSeepeople)
115   * @param[in] $type (Optionnel) Type de classe Ã  charger (Exemple : LSobjects)
116   *
117   * @author Benjamin Renard <brenard@easter-eggs.com
118   * 
119   * @retval boolean true si le chargement a réussi, false sinon.
120   */
121   function loadLSclass($class,$type='') {
122     if (class_exists($class))
123       return true;
124     if($type!='')
125       $type=$type.'.';
126     return include_once LS_CLASS_DIR .'class.'.$type.$class.'.php';
127   }
128
129  /**
130   * Chargement d'un object LdapSaisie
131   *
132   * @param[in] $object Nom de l'objet Ã  charger
133   *
134   * @retval boolean true si le chargement a réussi, false sinon.
135   */
136   function loadLSobject($object) {
137     $this -> loadLSclass('LSldapObject');
138     if (!$this -> loadLSclass($object,'LSobjects')) {
139       return;
140     }
141     if (!require_once( LS_OBJECTS_DIR . 'config.LSobjects.'.$object.'.php' )) {
142       return;
143     }
144     return true;
145   }
146
147  /**
148   * Chargement des objects LdapSaisie
149   *
150   * Chargement des LSobjects contenue dans la variable
151   * $this -> ldapServer['LSobjects']
152   *
153   * @retval boolean true si le chargement a réussi, false sinon.
154   */
155   function loadLSobjects() {
156
157     $this -> loadLSclass('LSldapObject');
158
159     if(!is_array($this -> ldapServer['LSobjects'])) {
160       $GLOBALS['LSerror'] -> addErrorCode(1001,"LSobjects['loads']");
161       return;
162     }
163
164     foreach ($this -> ldapServer['LSobjects'] as $object) {
165       if ( !$this -> loadLSobject($object) ) {
166         return;
167       }
168     }
169     return true;
170   }
171
172  /**
173   * Chargement d'un addons d'LdapSaisie
174   *
175   * @param[in] $addon Nom de l'addon Ã  charger (Exemple : samba)
176   *
177   * @author Benjamin Renard <brenard@easter-eggs.com
178   * 
179   * @retval boolean true si le chargement a réussi, false sinon.
180   */
181   function loadLSaddon($addon) {
182     return require_once LS_ADDONS_DIR .'LSaddons.'.$addon.'.php';
183   }
184
185  /**
186   * Chargement des addons LdapSaisie
187   *
188   * Chargement des LSaddons contenue dans la variable
189   * $GLOBALS['LSaddons']['loads']
190   *
191   * @retval boolean true si le chargement a réussi, false sinon.
192   */
193   function loadLSaddons() {
194     if(!is_array($GLOBALS['LSaddons']['loads'])) {
195       $GLOBALS['LSerror'] -> addErrorCode(1001,"LSaddons['loads']");
196       return;
197     }
198
199     foreach ($GLOBALS['LSaddons']['loads'] as $addon) {
200       $this -> loadLSaddon($addon);
201       if (!call_user_func('LSaddon_'. $addon .'_support')) {
202         $GLOBALS['LSerror'] -> addErrorCode(1002,$addon);
203       }
204     }
205     return true;
206   }
207
208  /**
209   * Initialisation de la session LdapSaisie
210   *
211   * Initialisation d'une LSsession :
212   * - Authentification et activation du mécanisme de session de LdapSaisie
213   * - ou Chargement des paramètres de la session Ã  partir de la variable 
214   *   $_SESSION['LSsession'].
215   * - ou Destruction de la session en cas de $_GET['LSsession_logout'].
216   *
217   * @retval boolean True si l'initialisation Ã  réussi (utilisateur authentifié), false sinon.
218   */
219   function startLSsession() {
220       $this -> loadLSaddons();
221       session_start();
222
223       // Déconnexion
224       if (isset($_GET['LSsession_logout'])||isset($_GET['LSsession_recoverPassword'])) {
225         session_destroy();
226         
227         if (is_array($_SESSION['LSsession']['tmp_file'])) {
228           $this -> tmp_file = $_SESSION['LSsession']['tmp_file'];
229         }
230         $this -> deleteTmpFile();
231         unset($_SESSION['LSsession']);
232       }
233       
234       // Récupération de mot de passe
235       if (isset($_GET['recoveryHash'])) {
236         $_POST['LSsession_user'] = 'a determiner plus tard';
237       }
238       
239       if(isset($_SESSION['LSsession'])) {
240         // Session existante
241         $this -> confDir      = $_SESSION['LSsession']['confDir'];
242         $this -> topDn        = $_SESSION['LSsession']['topDn'];
243         $this -> dn           = $_SESSION['LSsession']['dn'];
244         $this -> rdn          = $_SESSION['LSsession']['rdn'];
245         $this -> ldapServerId = $_SESSION['LSsession']['ldapServerId'];
246         $this -> tmp_file     = $_SESSION['LSsession']['tmp_file'];
247         
248         if ( $this -> cacheLSrights() ) {
249           $this -> ldapServer = $_SESSION['LSsession']['ldapServer'];
250           $this -> LSrights   = $_SESSION['LSsession']['LSrights'];
251           $this -> LSaccess   = $_SESSION['LSsession']['LSaccess'];
252           if (!$this -> LSldapConnect())
253             return;
254           $this -> loadLSobjects();
255         }
256         else {
257           $this -> setLdapServer($this -> ldapServerId);
258           if (!$this -> LSldapConnect())
259             return;
260           $this -> loadLSobjects();
261           $this -> loadLSrights();
262         }
263         
264         if ( $this -> cacheSudDn() && (!isset($_REQUEST['LSsession_topDn_refresh'])) ) {
265           $this -> _subDnLdapServer = $_SESSION['LSsession_subDnLdapServer'];
266         }
267         
268         $this -> loadLSobject($this -> ldapServer['authobject']);
269         $this -> LSuserObject = new $this -> ldapServer['authobject']();
270         $this -> LSuserObject -> loadData($this -> dn);
271         $this -> loadLSaccess();
272         $GLOBALS['Smarty'] -> assign('LSsession_username',$this -> LSuserObject -> getDisplayValue());
273         
274         if ($_POST['LSsession_topDn']) {
275           if ($this -> validSubDnLdapServer($_POST['LSsession_topDn'])) {
276             $this -> topDn = $_POST['LSsession_topDn'];
277             $_SESSION['LSsession']['topDn'] = $_POST['LSsession_topDn'];
278           } // end if
279         } // end if
280         
281         return true;
282         
283       }
284       else {
285         // Session inexistante
286         $recoveryPasswordInfos=array();
287
288         if (isset($_POST['LSsession_user'])) {
289           if (isset($_POST['LSsession_ldapserver'])) {
290             $this -> setLdapServer($_POST['LSsession_ldapserver']);
291           }
292           else {
293             $this -> setLdapServer(0);
294           }
295           
296           $this -> loadLSobjects();
297
298           // Connexion au serveur LDAP
299               if ($this -> LSldapConnect()) {
300
301             // topDn
302             if ( $_POST['LSsession_topDn'] != '' ){
303               $this -> topDn = $_POST['LSsession_topDn'];
304             }
305             else {
306               $this -> topDn = $this -> ldapServer['ldap_config']['basedn'];
307             }
308             $_SESSION['LSsession_topDn']=$this -> topDn;
309
310             if ( $this -> loadLSobject($this -> ldapServer['authobject']) ) {
311               $authobject = new $this -> ldapServer['authobject']();
312               $find=true;
313               if (isset($_GET['recoveryHash'])) {
314                 $filter=$this -> ldapServer['recoverPassword']['recoveryHashAttr']."=".$_GET['recoveryHash'];
315                 $result = $authobject -> listObjects($filter,$this -> topDn);
316                 $nbresult=count($result);
317                 if ($nbresult==1) {
318                   $_POST['LSsession_user'] = $result[0] -> getValue('rdn');
319                   $find=false;
320                 }
321               }
322               if ($find) {
323                 $result = $authobject -> searchObject($_POST['LSsession_user'],$this -> topDn);
324                 $nbresult=count($result);
325               }
326               if ($nbresult==0) {
327                 // identifiant incorrect
328                 debug('identifiant incorrect');
329                 $GLOBALS['LSerror'] -> addErrorCode(1006);
330               }
331               else if ($nbresult>1) {
332                 // duplication d'authentité
333                 $GLOBALS['LSerror'] -> addErrorCode(1007);
334               }
335               else {
336                 if (isset($_GET['LSsession_recoverPassword'])) {
337                   debug('Recover : Id trouvé');
338                   if ($this -> ldapServer['recoverPassword']) {
339                     debug('Récupération active');
340                     $user=$result[0];
341                     $emailAddress = $user -> getValue($this -> ldapServer['recoverPassword']['mailAttr']);
342                     
343                     // Header des mails
344                     $headers="Content-Type: text/plain; charset=UTF-8; format=flowed";
345                     if ($this -> ldapServer['recoverPassword']['recoveryEmailSender']) {
346                       $headers.="\nFrom: ".$this -> ldapServer['recoverPassword']['recoveryEmailSender'];
347                     }
348                     else if($this -> ldapServer['emailSender']) {
349                       $headers.="\nFrom: ".$this -> ldapServer['emailSender'];
350                     }
351                     
352                     if (checkEmail($emailAddress)) {
353                       debug('Email : '.$emailAddress);
354                       $this -> dn = $user -> getDn();
355                       // 1ère étape : envoie du recoveryHash
356                       if (!isset($_GET['recoveryHash'])) {
357                         // Generer un hash
358                         $recovery_hash = md5($user -> getValue('rdn') . strval(time()) . strval(rand()));
359                         
360                         $lostPasswdForm = $user -> getForm('lostPassword');
361                         $lostPasswdForm -> setPostData(
362                           array(
363                             $this -> ldapServer['recoverPassword']['recoveryHashAttr'] => $recovery_hash
364                           )
365                           ,true
366                         );
367                         
368                         if($lostPasswdForm -> validate()) {
369                           if ($user -> updateData('lostPassword')) {
370                             // recoveryHash de l'utilisateur mis à jour
371                             if ($_SERVER['HTTPS']=='on') {
372                               $recovery_url='https://';
373                             }
374                             else {
375                               $recovery_url='http://';
376                             }
377                             $recovery_url .= $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'].'&recoveryHash='.$recovery_hash;
378
379                             if (
380                               mail(
381                                 $emailAddress,
382                                 $this -> ldapServer['recoverPassword']['recoveryHashMail']['subject'],
383                                 getFData($this -> ldapServer['recoverPassword']['recoveryHashMail']['msg'],$recovery_url),
384                                 $headers
385                               )
386                             ){
387                               // Mail a bien été envoyé
388                               $recoveryPasswordInfos['recoveryHashMail']=$emailAddress;
389                             }
390                             else {
391                               // Problème durant l'envoie du mail
392                               debug("Problème durant l'envoie du mail");
393                               $GLOBALS['LSerror'] -> addErrorCode(1020);
394                             }
395                           }
396                           else {
397                             // Erreur durant la mise à jour de l'objet
398                             debug("Erreur durant la mise à jour de l'objet");
399                             $GLOBALS['LSerror'] -> addErrorCode(1020);
400                           }
401                         }
402                         else {
403                           // Erreur durant la validation du formulaire de modification de perte de password
404                           debug("Erreur durant la validation du formulaire de modification de perte de password");
405                           $GLOBALS['LSerror'] -> addErrorCode(1020);
406                         }
407                       }
408                       // 2nd étape : génération du mot de passe + envoie par mail
409                       else {
410                         $attr=$user -> attrs[$this -> ldapServer['authobject_pwdattr']];
411                         if ($attr instanceof LSattribute) {
412                           $mdp = generatePassword($attr -> config['html_options']['chars'],$attr -> config['html_options']['lenght']);
413                           debug('Nvx mpd : '.$mdp);
414                           $lostPasswdForm = $user -> getForm('lostPassword');
415                           $lostPasswdForm -> setPostData(
416                             array(
417                               $this -> ldapServer['recoverPassword']['recoveryHashAttr'] => array(''),
418                               $this -> ldapServer['authobject_pwdattr'] => array($mdp)
419                             )
420                             ,true
421                           );
422                           if($lostPasswdForm -> validate()) {
423                             if ($user -> updateData('lostPassword')) {
424                               if (
425                                 mail(
426                                   $emailAddress,
427                                   $this -> ldapServer['recoverPassword']['newPasswordMail']['subject'],
428                                   getFData($this -> ldapServer['recoverPassword']['newPasswordMail']['msg'],$mdp),
429                                   $headers
430                                 )
431                               ){
432                                 // Mail a bien été envoyé
433                                 $recoveryPasswordInfos['newPasswordMail']=$emailAddress;
434                               }
435                               else {
436                                 // Problème durant l'envoie du mail
437                                 debug("Problème durant l'envoie du mail");
438                                 $GLOBALS['LSerror'] -> addErrorCode(1020);
439                               }
440                             }
441                             else {
442                               // Erreur durant la mise à jour de l'objet
443                               debug("Erreur durant la mise à jour de l'objet");
444                               $GLOBALS['LSerror'] -> addErrorCode(1020);
445                             }
446                           }
447                           else {
448                             // Erreur durant la validation du formulaire de modification de perte de password
449                             debug("Erreur durant la validation du formulaire de modification de perte de password");
450                             $GLOBALS['LSerror'] -> addErrorCode(1020);
451                           }
452                         }
453                         else {
454                           // l'attribut password n'existe pas
455                           debug("L'attribut password n'existe pas");
456                           $GLOBALS['LSerror'] -> addErrorCode(1020);
457                         }
458                       }
459                     }
460                     else {
461                       $GLOBALS['LSerror'] -> addErrorCode(1019);
462                     }
463                   }
464                   else {
465                     $GLOBALS['LSerror'] -> addErrorCode(1018);
466                   }
467                 }
468                 else {
469                   if ( $this -> checkUserPwd($result[0],$_POST['LSsession_pwd']) ) {
470                     // Authentification réussi
471                     $this -> LSuserObject = $result[0];
472                     $this -> dn = $result[0]->getValue('dn');
473                     $this -> rdn = $_POST['LSsession_user'];
474                     $this -> loadLSrights();
475                     $this -> loadLSaccess();
476                     $GLOBALS['Smarty'] -> assign('LSsession_username',$this -> LSuserObject -> getValue('rdn'));
477                     $_SESSION['LSsession']=get_object_vars($this);
478                     return true;
479                   }
480                   else {
481                     $GLOBALS['LSerror'] -> addErrorCode(1006);
482                     debug('mdp incorrect');
483                   }
484                 }
485               }
486             }
487             else {
488               $GLOBALS['LSerror'] -> addErrorCode(1010);
489             }
490           }
491           else {
492             $GLOBALS['LSerror'] -> addErrorCode(1009);
493           }
494         }
495         if ($this -> ldapServerId) {
496           $GLOBALS['Smarty'] -> assign('ldapServerId',$this -> ldapServerId);
497         }
498         $GLOBALS['Smarty'] -> assign('topDn',$this -> topDn);
499         if (isset($_GET['LSsession_recoverPassword'])) {
500           $this -> displayRecoverPasswordForm($recoveryPasswordInfos);
501         }
502         else {
503           $this -> displayLoginForm();
504         }
505         return;
506       }
507   }
508
509  /**
510   * Définition du serveur Ldap de la session
511   *
512   * Définition du serveur Ldap de la session Ã  partir de son ID dans 
513   * le tableau $GLOBALS['LSconfig']['ldap_servers'].
514   *
515   * @param[in] integer Index du serveur Ldap
516   *
517   * @retval boolean True sinon false.
518   */
519   function setLdapServer($id) {
520     if ( isset($GLOBALS['LSconfig']['ldap_servers'][$id]) ) {
521       $this -> ldapServerId = $id;
522       $this -> ldapServer=$GLOBALS['LSconfig']['ldap_servers'][$id];
523       return true;
524     }
525     else {
526       return;
527     }
528   }
529
530  /**
531   * Connexion au serveur Ldap
532   *
533   * @retval boolean True sinon false.
534   */
535   function LSldapConnect() {
536     if ($this -> ldapServer) {
537       include_once($GLOBALS['LSconfig']['NetLDAP2']);
538       if (!$this -> loadLSclass('LSldap'))
539         return;
540         $GLOBALS['LSldap'] = new LSldap($this -> ldapServer['ldap_config']);
541         if ($GLOBALS['LSldap'] -> isConnected())
542           return true;
543         else
544           return;
545       return $GLOBALS['LSldap'] = new LSldap($this -> ldapServer['ldap_config']);
546     }
547     else {
548       $GLOBALS['LSerror'] -> addErrorCode(1003);
549       return;
550     }
551   }
552
553  /**
554   * Retourne les sous-dns du serveur Ldap courant
555   *
556   * @retval mixed Tableau des subDn, false si une erreur est survenue.
557   */
558   function getSubDnLdapServer() {
559     if ($this -> cacheSudDn() && isset($this -> _subDnLdapServer[$this -> ldapServerId])) {
560       return $this -> _subDnLdapServer[$this -> ldapServerId];
561     }
562     if ( is_array($this ->ldapServer['subDn']) ) {
563       $return=array();
564       foreach($this ->ldapServer['subDn'] as $subDn_name => $subDn_config) {
565         if ($subDn_name == 'LSobject') {
566           if (is_array($subDn_config)) {
567             foreach($subDn_config as $LSobject_name => $LSoject_topDn) {
568               if ($LSoject_topDn) {
569                 $topDn = $LSoject_topDn;
570               }
571               else {
572                 $topDn = NULL;
573               }
574               if( $this -> loadLSobject($LSobject_name) ) {
575                 if ($subdnobject = new $LSobject_name()) {
576                   $tbl_return = $subdnobject -> getSelectArray($topDn);
577                   if (is_array($tbl_return)) {
578                     $return=array_merge($return,$tbl_return);
579                   }
580                   else {
581                     $GLOBALS['LSerror'] -> addErrorCode(1017);
582                   }
583                 }
584                 else {
585                   $GLOBALS['LSerror'] -> addErrorCode(1017);
586                 }
587               }
588               else {
589                 $GLOBALS['LSerror'] -> addErrorCode(1004,$LSobject_name);
590               }
591             }
592           }
593           else {
594             $GLOBALS['LSerror'] -> addErrorCode(1017);
595           }
596         }
597         else {
598           $return[$subDn_config] = $subDn_name;
599         }
600       }
601       if ($this -> cacheSudDn()) {
602         $this -> _subDnLdapServer[$this -> ldapServerId]=$return;
603         $_SESSION['LSsession_subDnLdapServer'] = $this -> _subDnLdapServer;
604       }
605       return $return;
606     }
607     else {
608       return;
609     }
610   }
611   
612   /**
613    * Retourne la liste de subDn du serveur Ldap utilise
614    * trié par la profondeur dans l'arboressence (ordre décroissant)
615    * 
616    * @return array() Tableau des subDn trié
617    */  
618   function getSortSubDnLdapServer() {
619     if(isset($_SESSION['LSsession']['LSview_subDnLdapServer']) && $this -> cacheSudDn()) {
620       return $_SESSION['LSsession']['LSview_subDnLdapServer'];
621     }
622     $subDnLdapServer = $this  -> getSubDnLdapServer();
623     uksort($subDnLdapServer,"compareDn");
624     $_SESSION['LSsession']['LSview_subDnLdapServer']=$subDnLdapServer;
625     return $subDnLdapServer;
626   }
627
628  /**
629   * Retourne les options d'une liste déroulante pour le choix du topDn
630   * de connexion au serveur Ldap
631   *
632   * Liste les subdn ($this ->ldapServer['subDn'])
633   *
634   * @retval string Les options (<option>) pour la sélection du topDn.
635   */
636   function getSubDnLdapServerOptions($selected=NULL) {
637     $list = $this -> getSubDnLdapServer();
638     if ($list) {
639       $display='';
640       foreach($list as $dn => $txt) {
641         if ($selected && ($selected==$dn)) {
642           $selected_txt = ' selected';
643         }
644         else {
645           $selected_txt = '';
646         }
647         $display.="<option value=\"".$dn."\"$selected_txt>".$txt."</option>\n"; 
648       }
649       return $display;
650     }
651     return;
652   }
653
654   function validSubDnLdapServer($subDn) {
655     $listTopDn = $this -> getSubDnLdapServer();
656     if(is_array($listTopDn)) {
657       foreach($listTopDn as $dn => $txt) {
658         if ($subDn==$dn) {
659           return true;
660         } // end if
661       } // end foreach
662     } // end if
663     return;
664   }
665
666  /**
667   * Test un couple LSobject/pwd
668   *
669   * Test un bind sur le serveur avec le dn de l'objet et le mot de passe fourni.
670   *
671   * @param[in] LSobject L'object "user" pour l'authentification
672   * @param[in] string Le mot de passe Ã  tester
673   *
674   * @retval boolean True si l'authentification Ã  réussi, false sinon.
675   */
676   function checkUserPwd($object,$pwd) {
677     return $GLOBALS['LSldap'] -> checkBind($object -> getValue('dn'),$pwd);
678   }
679
680  /**
681   * Affiche le formulaire de login
682   *
683   * Défini les informations pour le template Smarty du formulaire de login.
684   *
685   * @retval void
686   */
687   function displayLoginForm() {
688     $GLOBALS['Smarty'] -> assign('pagetitle',_('Connexion'));
689     if (isset($_GET['LSsession_logout'])) {
690       $GLOBALS['Smarty'] -> assign('loginform_action','index.php');
691     }
692     else {
693       $GLOBALS['Smarty'] -> assign('loginform_action',$_SERVER['REQUEST_URI']);
694     }
695     if (count($GLOBALS['LSconfig']['ldap_servers'])==1) {
696       $GLOBALS['Smarty'] -> assign('loginform_ldapserver_style','style="display: none"');
697     }
698     $GLOBALS['Smarty'] -> assign('loginform_label_ldapserver',_('Serveur LDAP'));
699     $ldapservers_name=array();
700     $ldapservers_index=array();
701     foreach($GLOBALS['LSconfig']['ldap_servers'] as $id => $infos) {
702       $ldapservers_index[]=$id;
703       $ldapservers_name[]=$infos['name'];
704     }
705     $GLOBALS['Smarty'] -> assign('loginform_ldapservers_name',$ldapservers_name);
706     $GLOBALS['Smarty'] -> assign('loginform_ldapservers_index',$ldapservers_index);
707
708     $GLOBALS['Smarty'] -> assign('loginform_label_level',_('Niveau'));
709     $GLOBALS['Smarty'] -> assign('loginform_label_user',_('Identifiant'));
710     $GLOBALS['Smarty'] -> assign('loginform_label_pwd',_('Mot de passe'));
711     $GLOBALS['Smarty'] -> assign('loginform_label_submit',_('Connexion'));
712     $GLOBALS['Smarty'] -> assign('loginform_label_lostpassword',_('Mot de passe oublié ?'));
713     
714     $this -> setTemplate('login.tpl');
715     $this -> addJSscript('LSsession_login.js');
716   }
717
718  /**
719   * Affiche le formulaire de récupération de mot de passe
720   *
721   * Défini les informations pour le template Smarty du formulaire de 
722   * récupération de mot de passe
723   * 
724   * @param[in] $infos array() Information sur le status du processus de 
725   *                           recouvrement de mot de passe
726   *
727   * @retval void
728   */
729   function displayRecoverPasswordForm($recoveryPasswordInfos) {
730     $GLOBALS['Smarty'] -> assign('pagetitle',_('Récupération de votre mot de passe'));
731     $GLOBALS['Smarty'] -> assign('recoverpasswordform_action','index.php?LSsession_recoverPassword');
732     
733     if (count($GLOBALS['LSconfig']['ldap_servers'])==1) {
734       $GLOBALS['Smarty'] -> assign('recoverpasswordform_ldapserver_style','style="display: none"');
735     }
736     
737     $GLOBALS['Smarty'] -> assign('recoverpasswordform_label_ldapserver',_('Serveur LDAP'));
738     $ldapservers_name=array();
739     $ldapservers_index=array();
740     foreach($GLOBALS['LSconfig']['ldap_servers'] as $id => $infos) {
741       $ldapservers_index[]=$id;
742       $ldapservers_name[]=$infos['name'];
743     }
744     $GLOBALS['Smarty'] -> assign('recoverpasswordform_ldapservers_name',$ldapservers_name);
745     $GLOBALS['Smarty'] -> assign('recoverpasswordform_ldapservers_index',$ldapservers_index);
746
747     $GLOBALS['Smarty'] -> assign('recoverpasswordform_label_user',_('Identifiant'));
748     $GLOBALS['Smarty'] -> assign('recoverpasswordform_label_submit',_('Valider'));
749     $GLOBALS['Smarty'] -> assign('recoverpasswordform_label_back',_('Retour'));
750     
751     if (isset($recoveryPasswordInfos['recoveryHashMail'])) {
752       $GLOBALS['Smarty'] -> assign(
753         'recoverpassword_msg',
754         getFData(
755           _("Un mail vient de vous être envoyé à l'adresse %{mail}. " .
756           "Merci de suivre les indications contenus dans ce mail."),
757           $recoveryPasswordInfos['recoveryHashMail']
758         )
759       );
760     }
761     
762     if (isset($recoveryPasswordInfos['newPasswordMail'])) {
763       $GLOBALS['Smarty'] -> assign(
764         'recoverpassword_msg',
765         getFData(
766           _("Votre nouveau mot de passe vient de vous être envoyé à l'adresse %{mail}. "),
767           $recoveryPasswordInfos['newPasswordMail']
768         )
769       );
770     }
771     
772     $this -> setTemplate('recoverpassword.tpl');
773     $this -> addJSscript('LSsession_recoverpassword.js');
774   }
775
776  /**
777   * Défini le template Smarty Ã  utiliser
778   *
779   * Remarque : les fichiers de templates doivent se trouver dans le dossier 
780   * templates/.
781   *
782   * @param[in] string Le nom du fichier de template
783   *
784   * @retval void
785   */
786   function setTemplate($template) {
787     $this -> template = $template;
788   }
789
790  /**
791   * Ajoute un script JS au chargement de la page
792   *
793   * Remarque : les scripts doivents Ãªtre dans le dossier LS_JS_DIR.
794   *
795   * @param[in] $script Le nom du fichier de script Ã  charger.
796   *
797   * @retval void
798   */
799   function addJSscript($script) {
800     if (in_array($script, $this -> JSscripts))
801       return;
802     $this -> JSscripts[]=$script;
803   }
804
805  /**
806   * Ajoute une feuille de style au chargement de la page
807   *
808   * Remarque : les scripts doivents Ãªtre dans le dossiers templates/css/.
809   *
810   * @param[in] $script Le nom du fichier css Ã  charger.
811   *
812   * @retval void
813   */
814   function addCssFile($file) {
815     $this -> CssFiles[]=$file;
816   }
817
818  /**
819   * Affiche le template Smarty
820   *
821   * Charge les dépendances et affiche le template Smarty
822   *
823   * @retval void
824   */
825   function displayTemplate() {
826     // JS
827     $JSscript_txt='';
828     foreach ($GLOBALS['defaultJSscipts'] as $script) {
829       $JSscript_txt.="<script src='".LS_JS_DIR.$script."' type='text/javascript'></script>\n";
830     }
831
832     foreach ($this -> JSscripts as $script) {
833       $JSscript_txt.="<script src='".LS_JS_DIR.$script."' type='text/javascript'></script>\n";
834     }
835     
836     if ($GLOBALS['LSdebug']['active']) {
837       $JSscript_txt.="<script type='text/javascript'>LSdebug_active = 1;</script>\n";
838     }
839     else {
840       $JSscript_txt.="<script type='text/javascript'>LSdebug_active = 0;</script>\n";
841     }
842     
843     $GLOBALS['Smarty'] -> assign('LSsession_js',$JSscript_txt);
844
845     // Css
846     $Css_txt="<link rel='stylesheet' type='text/css' href='templates/css/LSdefault.css' />\n";
847     $Css_txt="<link rel='stylesheet' type='text/css' href='templates/css/LSdefault.css' />\n";
848     foreach ($this -> CssFiles as $file) {
849       $Css_txt.="<link rel='stylesheet' type='text/css' href='templates/css/$file' />\n";
850     }
851     $GLOBALS['Smarty'] -> assign('LSsession_css',$Css_txt);
852
853     $GLOBALS['Smarty'] -> assign('LSaccess',$this -> LSaccess);
854     
855     // Niveau
856     $listTopDn = $this -> getSubDnLdapServer();
857     if (is_array($listTopDn)) {
858       $GLOBALS['Smarty'] -> assign('label_level',$this -> getLevelLabel());
859       $GLOBALS['Smarty'] -> assign('_refresh',_('Rafraîchir'));
860       $LSsession_topDn_index = array();
861       $LSsession_topDn_name = array();
862       foreach($listTopDn as $index => $name) {
863         $LSsession_topDn_index[]  = $index;
864         $LSsession_topDn_name[]   = $name;
865       }
866       $GLOBALS['Smarty'] -> assign('LSsession_subDn_indexes',$LSsession_topDn_index);
867       $GLOBALS['Smarty'] -> assign('LSsession_subDn_names',$LSsession_topDn_name);
868       $GLOBALS['Smarty'] -> assign('LSsession_subDn',$this -> topDn);
869       $GLOBALS['Smarty'] -> assign('LSsession_subDnName',$this -> getSubDnName());
870     }
871     
872     if ($this -> ajaxDisplay) {
873       $GLOBALS['Smarty'] -> assign('error_txt',json_encode($GLOBALS['LSerror']->getErrors()));
874       $GLOBALS['Smarty'] -> assign('debug_txt',json_encode(debug_print(true)));
875     }
876     else {
877       $GLOBALS['LSerror'] -> display();
878       debug_print();
879     }
880     if (!$this -> template)
881       $this -> setTemplate('empty.tpl');
882     $GLOBALS['Smarty'] -> display($this -> template);
883   }
884   
885   /**
886    * Charge les droits LS de l'utilisateur
887    * 
888    * @retval boolean True si le chargement Ã  réussi, false sinon.
889    **/
890   function loadLSrights() {
891     if (is_array($this -> ldapServer['LSadmins'])) {
892       foreach ($this -> ldapServer['LSadmins'] as $topDn => $adminsInfos) {
893         if (is_array($adminsInfos)) {
894           foreach($adminsInfos as $dn => $conf) {
895             if ((isset($conf['attr'])) && (isset($conf['LSobject']))) {
896               if( $this -> loadLSobject($conf['LSobject']) ) {
897                 if ($object = new $conf['LSobject']()) {
898                   if ($object -> loadData($dn)) {
899                     $listDns=$object -> getValue($conf['attr']);
900                     if (is_array($listDns)) {
901                       if (in_array($this -> dn,$listDns)) {
902                         $this -> LSrights['topDn_admin'][] = $topDn;
903                       }
904                     }
905                   }
906                   else {
907                     debug('Impossible de chargé le dn : '.$dn);
908                   }
909                 }
910                 else {
911                   debug('Impossible de créer l\'objet de type : '.$conf['LSobject']);
912                 }
913               }
914               else {
915                 $GLOBALS['LSerror'] -> addErrorCode(1004,$conf['LSobject']);
916               }
917             }
918             else {
919               if ($this -> dn == $dn) {
920                 $this -> LSrights['topDn_admin'][] = $topDn;
921               }
922             }
923           }
924         }
925         else {
926           if ( $this -> dn == $adminsInfos ) {
927             $this -> LSrights['topDn_admin'][] = $topDn;
928           }
929         }
930       }
931       return true;
932     }
933     else {
934       return;
935     }
936   }
937   
938   /**
939    * Charge les droits d'accès de l'utilisateur pour construire le menu de l'interface
940    *
941    * @retval void
942    */
943   function loadLSaccess() {
944     if ($this -> canAccess($this -> LSuserObject -> getType(),$this -> dn)) {
945       $LSaccess = array(
946         'SELF' => array(
947           'label' => _('Mon compte'),
948           'DNs' => $this -> dn
949         )
950       );
951     }
952     else {
953       $LSaccess = array();
954     }
955     foreach ($GLOBALS['LSobjects'] as $objecttype => $objectconf) {
956       if ($this -> canAccess($objecttype) ) {
957         $LSaccess[$objecttype] = array (
958           'label' => $objectconf['label'],
959           'Dns' => 'All'
960         );
961       }
962     }
963     $this -> LSaccess = $LSaccess;
964   }
965   
966   /**
967    * Dit si l'utilisateur est admin de le DN spécifié
968    *
969    * @param[in] string DN de l'objet
970    * 
971    * @retval boolean True si l'utilisateur est admin sur l'objet, false sinon.
972    */
973   function isAdmin($dn) {
974     foreach($this -> LSrights['topDn_admin'] as $topDn_admin) {
975       if($dn == $topDn_admin) {
976         return true;
977       }
978       else if ( isCompatibleDNs($dn,$topDn_admin) ) {
979         return true;
980       }
981     }
982     return;
983   }
984   
985   /**
986    * Retourne qui est l'utilisateur par rapport Ã  l'object
987    *
988    * @param[in] string Le DN de l'objet
989    * 
990    * @retval string 'admin'/'self'/'user' pour Admin , l'utilisateur lui même ou un simple utilisateur
991    */
992   function whoami($dn) {
993     if ($this -> isAdmin($dn)) {
994       return 'admin';
995     }
996     
997     if ($this -> dn == $dn) {
998       return 'self';
999     }
1000     
1001     return 'user';
1002   }
1003   
1004   /**
1005    * Retourne le droit de l'utilisateur Ã  accèder Ã  un objet
1006    * 
1007    * @param[in] string $LSobject Le type de l'objet
1008    * @param[in] string $dn Le DN de l'objet (le container_dn du type de l'objet par défaut)
1009    * @param[in] string $right Le type de droit d'accès Ã  tester ('r'/'w')
1010    * @param[in] string $attr Le nom de l'attribut auquel on test l'accès
1011    *
1012    * @retval boolean True si l'utilisateur a accès, false sinon
1013    */
1014   function canAccess($LSobject,$dn=NULL,$right=NULL,$attr=NULL) {
1015     if (!$this -> loadLSobject($LSobject))
1016       return;
1017     if ($dn) {
1018       $whoami = $this -> whoami($dn);
1019     }
1020     else {
1021       $objectdn=$GLOBALS['LSobjects'][$LSobject]['container_dn'].','.$this -> topDn;
1022       $whoami = $this -> whoami($objectdn);
1023     }
1024     
1025     // Pour un attribut particulier
1026     if ($attr) {
1027       if ($attr=='rdn') {
1028         $attr=$GLOBALS['LSobjects'][$LSobject]['rdn'];
1029       }
1030       if (!isset($GLOBALS['LSobjects'][$LSobject]['attrs'][$attr])) {
1031         return;
1032       }
1033       
1034       if (($right=='r')||($right=='w')) {
1035         if ($GLOBALS['LSobjects'][$LSobject]['attrs'][$attr]['rights'][$whoami]==$right) {
1036           return true;
1037         }
1038         return;
1039       }
1040       else {
1041         if ( ($GLOBALS['LSobjects'][$LSobject]['attrs'][$attr]['rights'][$whoami]=='r') || ($GLOBALS['LSobjects'][$LSobject]['attrs'][$attr]['rights'][$whoami]=='w') ) {
1042           return true;
1043         }
1044         return;
1045       }
1046     }
1047     
1048     // Pour un attribut quelconque
1049     if (is_array($GLOBALS['LSobjects'][$LSobject]['attrs'])) {
1050       if (($right=='r')||($right=='w')) {
1051         foreach ($GLOBALS['LSobjects'][$LSobject]['attrs'] as $attr_name => $attr_config) {
1052           if ($attr_config['rights'][$whoami]==$right) {
1053             return true;
1054           }
1055         }
1056       }
1057       else {
1058         foreach ($GLOBALS['LSobjects'][$LSobject]['attrs'] as $attr_name => $attr_config) {
1059           if ( ($attr_config['rights'][$whoami]=='r') || ($attr_config['rights'][$whoami]=='w') ) {
1060             return true;
1061           }
1062         }
1063       }
1064     }
1065     return;
1066   }
1067   
1068   /**
1069    * Retourne le droit de l'utilisateur Ã  editer Ã  un objet
1070    * 
1071    * @param[in] string $LSobject Le type de l'objet
1072    * @param[in] string $dn Le DN de l'objet (le container_dn du type de l'objet par défaut)
1073    * @param[in] string $attr Le nom de l'attribut auquel on test l'accès
1074    *
1075    * @retval boolean True si l'utilisateur a accès, false sinon
1076    */
1077   function canEdit($LSobject,$dn=NULL,$attr=NULL) {
1078     return $this -> canAccess($LSobject,$dn,'w',$attr);
1079   }
1080
1081   /**
1082    * Retourne le droit de l'utilisateur Ã  supprimer un objet
1083    * 
1084    * @param[in] string $LSobject Le type de l'objet
1085    * @param[in] string $dn Le DN de l'objet (le container_dn du type de l'objet par défaut)
1086    *
1087    * @retval boolean True si l'utilisateur a accès, false sinon
1088    */  
1089   function canRemove($LSobject,$dn) {
1090     return $this -> canAccess($LSobject,$dn,'w','rdn');
1091   }
1092   
1093   /**
1094    * Retourne le droit de l'utilisateur Ã  créer un objet
1095    * 
1096    * @param[in] string $LSobject Le type de l'objet
1097    *
1098    * @retval boolean True si l'utilisateur a accès, false sinon
1099    */    
1100   function canCreate($LSobject) {
1101     return $this -> canAccess($LSobject,NULL,'w','rdn');
1102   }
1103   
1104   /**
1105    * Retourne le droit de l'utilisateur Ã  gérer la relation d'objet
1106    * 
1107    * @param[in] string $dn Le DN de l'objet (le container_dn du type de l'objet par défaut)
1108    * @param[in] string $relationName Le nom de la relation avec l'objet
1109    * @param[in] string $right Le type de droit a vérifier ('r' ou 'w')
1110    *
1111    * @retval boolean True si l'utilisateur a accès, false sinon
1112    */
1113   function relationCanAccess($dn,$relationName,$right=NULL) {
1114     $LSobject=$this -> LSuserObject -> getType();
1115     if (!isset($GLOBALS['LSobjects'][$LSobject]['relations'][$relationName]))
1116       return;
1117     $whoami = $this -> whoami($dn);
1118
1119     if (($right=='w') || ($right=='r')) {
1120       if ($GLOBALS['LSobjects'][$LSobject]['relations'][$relationName]['rights'][$whoami] == $right) {
1121         return true;
1122       }
1123     }
1124     else {
1125       if (($GLOBALS['LSobjects'][$LSobject]['relations'][$relationName]['rights'][$whoami] == 'w') || ($GLOBALS['LSobjects'][$LSobject]['relations'][$relationName]['rights'][$whoami] == 'r')) {
1126         return true;
1127       }
1128     }
1129     return;
1130   }
1131
1132   /**
1133    * Retourne le droit de l'utilisateur Ã  modifier la relation d'objet
1134    * 
1135    * @param[in] string $dn Le DN de l'objet (le container_dn du type de l'objet par défaut)
1136    * @param[in] string $relationName Le nom de la relation avec l'objet
1137    *
1138    * @retval boolean True si l'utilisateur a accès, false sinon
1139    */  
1140   function relationCanEdit($dn,$relationName) {
1141     return $this -> relationCanAccess($dn,$relationName,'w');
1142   }
1143
1144   /**
1145    * Ajoute un fichier temporaire
1146    * 
1147    * @author Benjamin Renard <brenard@easter-eggs.com>
1148    * 
1149    * @retval void
1150    **/
1151   function addTmpFile($value,$filePath) {
1152     $hash = mhash(MHASH_MD5,$value);
1153     $this -> tmp_file[$filePath] = $hash;
1154     $_SESSION['LSsession']['tmp_file'][$filePath] = $hash;
1155   }
1156   
1157   /**
1158    * Retourne le chemin du fichier temporaire si l'existe
1159    * 
1160    * @author Benjamin Renard <brenard@easter-eggs.com>
1161    * 
1162    * @param[in] $value La valeur du fichier
1163    * 
1164    * @retval mixed 
1165    **/
1166   function tmpFileExist($value) {
1167     $hash = mhash(MHASH_MD5,$value);
1168     foreach($this -> tmp_file as $filePath => $contentHash) {
1169       if ($hash == $contentHash) {
1170         return $filePath;
1171       }
1172     }
1173     return false;
1174   }
1175   
1176   /**
1177    * Retourne le chemin du fichier temporaire
1178    * 
1179    * Retourne le chemin du fichier temporaire qu'il créera Ã  partir de la valeur
1180    * s'il n'existe pas déjà.
1181    * 
1182    * @author Benjamin Renard <brenard@easter-eggs.com>
1183    * 
1184    * @param[in] $value La valeur du fichier
1185    * 
1186    * @retval mixed 
1187    **/
1188   function getTmpFile($value) {
1189     $exist = $this -> tmpFileExist($value);
1190     if (!$exist) {
1191       $img_path = LS_TMP_DIR .rand().'.tmp';
1192       $fp = fopen($img_path, "w");
1193       fwrite($fp, $value);
1194       fclose($fp);
1195       $this -> addTmpFile($value,$img_path);
1196       return $img_path;
1197     }
1198     else {
1199       return $exist;
1200     }
1201   }
1202   
1203   /**
1204    * Supprime les fichiers temporaires
1205    * 
1206    * @author Benjamin Renard <brenard@easter-eggs.com>
1207    * 
1208    * @retval void
1209    **/
1210   function deleteTmpFile($filePath=NULL) {
1211     if ($filePath) {
1212         @unlink($filePath);
1213         unset($this -> tmp_file[$filePath]);
1214         unset($_SESSION['LSsession']['tmp_file'][$filePath]);
1215     }
1216     else {
1217       foreach($this -> tmp_file as $file => $content) {
1218         @unlink($file);
1219       }
1220       $this -> tmp_file = array();
1221       $_SESSION['LSsession']['tmp_file'] = array();
1222     }
1223   }
1224
1225   /**
1226    * Retourne true si le cache des droits est activé
1227    *
1228    * @author Benjamin Renard <brenard@easter-eggs.com>
1229    * 
1230    * @retval boolean True si le cache des droits est activé, false sinon.
1231    */
1232   function cacheLSrights() {
1233     return ( ($GLOBALS['LSconfig']['cacheLSrights']) || ($this -> ldapServer['cacheLSrights']) );
1234   }
1235
1236   /**
1237    * Retourne true si le cache des subDn est activé
1238    *
1239    * @author Benjamin Renard <brenard@easter-eggs.com>
1240    * 
1241    * @retval boolean True si le cache des subDn est activé, false sinon.
1242    */
1243   function cacheSudDn() {
1244     return (($GLOBALS['LSconfig']['cacheSubDn']) || ($this -> ldapServer['cacheSubDn']));
1245   }
1246   
1247   /**
1248    * Retourne true si le cache des recherches est activé
1249    *
1250    * @author Benjamin Renard <brenard@easter-eggs.com>
1251    * 
1252    * @retval boolean True si le cache des recherches est activé, false sinon.
1253    */
1254   function cacheSearch() {
1255     return (($GLOBALS['LSconfig']['cacheSearch']) || ($this -> ldapServer['cacheSearch']));
1256   }
1257   
1258   /**
1259    * Retourne le label des niveaux pour le serveur ldap courant
1260    * 
1261    * @author Benjamin Renard <brenard@easter-eggs.com>
1262    * 
1263    * @retval string Le label des niveaux pour le serveur ldap dourant
1264    */
1265   function getLevelLabel() {
1266     return ($this -> ldapServer['levelLabel']!='')?$this -> ldapServer['levelLabel']:_('Niveau');
1267   }
1268   
1269   /**
1270    * Retourne le nom du subDn
1271    * 
1272    * @param[in] $subDn string subDn
1273    * 
1274    * @return string Le nom du subDn ou '' sinon
1275    */
1276   function getSubDnName($subDn=false) {
1277     if (!$subDn) {
1278       $subDn = $this -> topDn;
1279     }
1280     if ($this -> getSubDnLdapServer()) {
1281       if (isset($this -> _subDnLdapServer[$this -> ldapServerId][$subDn])) {
1282         return $this -> _subDnLdapServer[$this -> ldapServerId][$subDn];
1283       }
1284     }
1285     return '';
1286   }
1287
1288 }
1289
1290 ?>