2 /*******************************************************************************
3 * Copyright (C) 2007 Easter-eggs
4 * http://ldapsaisie.labs.libre-entreprise.org
6 * Author: See AUTHORS file in top-level directory.
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.
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.
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.
21 ******************************************************************************/
24 * Gestion des sessions
26 * Cette classe gère les sessions d'utilisateurs.
28 * @author Benjamin Renard <brenard@easter-eggs.com>
32 // La configuration du serveur Ldap utilisé
33 public static $ldapServer = NULL;
35 // L'id du serveur Ldap utilisé
36 private static $ldapServerId = NULL;
39 private static $topDn = NULL;
41 // Le DN de l'utilisateur connecté
42 private static $dn = NULL;
44 // Le RDN de l'utilisateur connecté (son identifiant)
45 private static $rdn = NULL;
47 // Les LSprofiles de l'utilisateur
48 private static $LSprofiles = array();
50 // Les droits d'accès de l'utilisateur
51 private static $LSaccess = array();
53 // Les fichiers temporaires
54 private static $tmp_file = array();
56 // Langue et encodage actuel
57 private static $lang = NULL;
58 private static $encoding = NULL;
61 * Constante de classe non stockée en session
63 // Le template à afficher
64 private static $template = NULL;
66 // Les subDn des serveurs Ldap
67 private static $_subDnLdapServer = array();
70 private static $ajaxDisplay = false;
72 // Les fichiers JS à charger dans la page
73 private static $JSscripts = array();
75 // Les paramètres JS à communiquer dans la page
76 private static $_JSconfigParams = array();
78 // Les fichiers CSS à charger dans la page
79 private static $CssFiles = array();
81 // L'objet de l'utilisateur connecté
82 private static $LSuserObject = NULL;
84 // The LSauht object of the session
85 private static $LSauthObject = false;
87 // User LDAP credentials
88 private static $userLDAPcreds = false;
91 * Include un fichier PHP
93 * @author Benjamin Renard <brenard@easter-eggs.com>
95 * @retval true si tout c'est bien passé, false sinon
97 public static function includeFile($file) {
98 if (file_exists(LS_LOCAL_DIR.'/'.$file)) {
99 $file=LS_LOCAL_DIR.'/'.$file;
101 elseif (!file_exists($file)) {
104 if (defined('LSdebug') && constant('LSdebug')) {
105 return include_once($file);
108 return @include_once($file);
114 * Lancement de LSconfig
116 * @author Benjamin Renard <brenard@easter-eggs.com>
118 * @retval true si tout c'est bien passé, false sinon
120 private static function startLSconfig() {
121 if (self :: loadLSclass('LSconfig')) {
122 if (LSconfig :: start()) {
126 die("ERROR : Can't load configuration files.");
131 * Lancement et initialisation de Smarty
133 * @author Benjamin Renard <brenard@easter-eggs.com>
135 * @retval true si tout c'est bien passé, false sinon
137 private static function startLStemplate() {
138 if ( self :: loadLSclass('LStemplate') ) {
139 return LStemplate :: start(
141 'smarty_path' => LSconfig :: get('Smarty'),
142 'template_dir' => LS_TEMPLATES_DIR,
143 'image_dir' => LS_IMAGES_DIR,
144 'css_dir' => LS_CSS_DIR,
145 'compile_dir' => LS_TMP_DIR,
147 'debug_smarty' => (isset($_REQUEST['LStemplate_debug'])),
155 * Retourne le topDn de la session
157 * @author Benjamin Renard <brenard@easter-eggs.com>
159 * @retval string le topDn de la session
161 public static function getTopDn() {
162 if (!is_null(self :: $topDn)) {
163 return self :: $topDn;
166 return self :: getRootDn();
171 * Retourne le rootDn de la session
173 * @author Benjamin Renard <brenard@easter-eggs.com>
175 * @retval string le rootDn de la session
177 public static function getRootDn() {
178 return self :: $ldapServer['ldap_config']['basedn'];
182 * Initialisation de la gestion des erreurs
184 * Création de l'objet LSerror
186 * @author Benjamin Renard <brenard@easter-eggs.com
188 * @retval boolean true si l'initialisation a réussi, false sinon.
190 private static function startLSerror() {
191 if(!self :: loadLSclass('LSerror')) {
194 set_error_handler(array('LSerror','errorHandler'),E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED & ~E_WARNING);
195 self :: defineLSerrors();
200 * Chargement d'une classe d'LdapSaisie
202 * @param[in] $class Nom de la classe à charger (Exemple : LSpeople)
203 * @param[in] $type (Optionnel) Type de classe à charger (Exemple : LSobjects)
205 * @author Benjamin Renard <brenard@easter-eggs.com
207 * @retval boolean true si le chargement a réussi, false sinon.
209 public static function loadLSclass($class,$type='') {
210 if (class_exists($class))
214 return self :: includeFile(LS_CLASS_DIR .'class.'.$type.$class.'.php');
218 * Chargement d'un object LdapSaisie
220 * @param[in] $object Nom de l'objet à charger
222 * @retval boolean true si le chargement a réussi, false sinon.
224 public static function loadLSobject($object) {
225 if(class_exists($object)) {
229 self :: loadLSclass('LSldapObject');
230 if (!self :: loadLSclass($object,'LSobjects')) {
233 if (!self :: includeFile( LS_OBJECTS_DIR . 'config.LSobjects.'.$object.'.php' )) {
237 if (!LSconfig :: set("LSobjects.$object",$GLOBALS['LSobjects'][$object])) {
240 else if (isset($GLOBALS['LSobjects'][$object]['LSaddons'])){
241 if (is_array($GLOBALS['LSobjects'][$object]['LSaddons'])) {
242 foreach ($GLOBALS['LSobjects'][$object]['LSaddons'] as $addon) {
243 if (!self :: loadLSaddon($addon)) {
249 if (!self :: loadLSaddon($GLOBALS['LSobjects'][$object]['LSaddons'])) {
256 LSerror :: addErrorCode('LSsession_04',$object);
263 * Chargement d'un addons d'LdapSaisie
265 * @param[in] $addon Nom de l'addon à charger (Exemple : samba)
267 * @author Benjamin Renard <brenard@easter-eggs.com
269 * @retval boolean true si le chargement a réussi, false sinon.
271 public static function loadLSaddon($addon) {
272 if(self :: includeFile(LS_ADDONS_DIR .'LSaddons.'.$addon.'.php')) {
273 self :: includeFile(LS_CONF_DIR."LSaddons/config.LSaddons.".$addon.".php");
274 if (!call_user_func('LSaddon_'. $addon .'_support')) {
275 LSerror :: addErrorCode('LSsession_02',$addon);
284 * Chargement d'une classe d'authentification d'LdapSaisie
286 * @author Benjamin Renard <brenard@easter-eggs.com
288 * @retval boolean true si le chargement a reussi, false sinon.
290 public static function loadLSauth() {
291 if (self :: loadLSclass('LSauth')) {
295 LSerror :: addErrorCode('LSsession_05','LSauth');
301 * Chargement des addons LdapSaisie
303 * Chargement des LSaddons contenue dans la variable
304 * $GLOBALS['LSaddons']['loads']
306 * @retval boolean true si le chargement a réussi, false sinon.
308 public static function loadLSaddons() {
309 $conf=LSconfig :: get('LSaddons.loads');
310 if(!is_array($conf)) {
311 LSerror :: addErrorCode('LSsession_01',"LSaddons['loads']");
315 foreach ($conf as $addon) {
316 self :: loadLSaddon($addon);
326 public static function setLocale() {
327 if (isset($_REQUEST['lang'])) {
328 $lang = $_REQUEST['lang'];
330 elseif (isset($_SESSION['LSlang'])) {
331 $lang = $_SESSION['LSlang'];
333 elseif (isset(self :: $ldapServer['lang'])) {
334 $lang = self :: $ldapServer['lang'];
337 $lang = LSconfig :: get('lang');
340 if (isset($_REQUEST['encoding'])) {
341 $encoding = $_REQUEST['encoding'];
343 elseif (isset($_SESSION['LSencoding'])) {
344 $encoding = $_SESSION['LSencoding'];
346 elseif (isset(self :: $ldapServer['encoding'])) {
347 $encoding = self :: $ldapServer['encoding'];
350 $encoding = LSconfig :: get('encoding');
353 $_SESSION['LSlang']=$lang;
355 $_SESSION['LSencoding']=$encoding;
356 self :: $encoding=$encoding;
359 if (self :: localeExist($lang,$encoding)) {
361 $lang.='.'.$encoding;
363 setlocale(LC_ALL, $lang);
364 bindtextdomain(LS_TEXT_DOMAIN, LS_I18N_DIR);
365 textdomain(LS_TEXT_DOMAIN);
367 self :: includeFile(LS_I18N_DIR.'/'.$lang.'/lang.php');
369 foreach (listFiles(LS_LOCAL_DIR.'/'.LS_I18N_DIR.'/'.$lang,'/^lang.+\.php$/') as $file) {
370 include(LS_LOCAL_DIR.'/'.LS_I18N_DIR."/$lang/$file");
374 if ($encoding && $lang) {
375 $lang.='.'.$encoding;
377 LSdebug('La locale "'.$lang.'" n\'existe pas, utilisation de la locale par défaut.');
382 * Retourne la liste des langues disponibles
384 * @retval array Tableau/Liste des langues disponibles
386 public static function getLangList() {
387 $list=array('en_US');
388 if (self :: $encoding) {
389 $regex = '^([a-zA-Z_]*)\.'.self :: $encoding.'$';
392 $regex = '^([a-zA-Z_]*)$';
394 if ($handle = opendir(LS_I18N_DIR)) {
395 while (false !== ($file = readdir($handle))) {
396 if(is_dir(LS_I18N_DIR.'/'.$file)) {
397 if (ereg($regex,$file,$regs)) {
398 if (!in_array($regs[1],$list)) {
409 * Retourne la langue courante de la session
411 * @param[in] boolean Si true, le code langue retourné sera court
413 * @retval string La langue de la session
415 public static function getLang($short=false) {
417 return strtolower(self :: $lang[0].self :: $lang[1]);
419 return self :: $lang;
423 * Vérifie si une locale est disponible
425 * @param[in] $lang string La langue (Ex : fr_FR)
426 * @param[in] $encoding string L'encodage de caractère (Ex : UTF8)
428 * @retval boolean True si la locale est disponible, False sinon
430 public static function localeExist($lang,$encoding) {
431 if ( !$lang && !$encoding ) {
434 $locale=$lang.(($encoding)?'.'.$encoding:'');
435 if ($locale=='en_US.UTF8') {
438 return (is_dir(LS_I18N_DIR.'/'.$locale));
442 * Initialisation LdapSaisie
444 * @retval boolean True si l'initialisation à réussi, false sinon.
446 public static function initialize() {
448 if (!self :: startLSconfig()) {
452 self :: startLSerror();
453 self :: startLStemplate();
459 self :: loadLSaddons();
460 self :: loadLSauth();
462 catch (Exception $e) {
463 die('LSsession : fail to initialize session. Error : '.$e->getMessage());
469 * Initialisation de la session LdapSaisie
471 * Initialisation d'une LSsession :
472 * - Authentification et activation du mécanisme de session de LdapSaisie
473 * - ou Chargement des paramètres de la session à partir de la variable
474 * $_SESSION['LSsession'].
475 * - ou Destruction de la session en cas de $_GET['LSsession_logout'].
477 * @retval boolean True si l'initialisation à réussi (utilisateur authentifié), false sinon.
479 public static function startLSsession() {
480 if (!self :: initialize()) {
484 if(isset($_SESSION['LSsession']['dn']) && !isset($_GET['LSsession_recoverPassword'])) {
485 LSdebug('LSsession : Session existente');
486 // --------------------- Session existante --------------------- //
487 self :: $topDn = $_SESSION['LSsession']['topDn'];
488 self :: $dn = $_SESSION['LSsession']['dn'];
489 self :: $rdn = $_SESSION['LSsession']['rdn'];
490 self :: $ldapServerId = $_SESSION['LSsession']['ldapServerId'];
491 self :: $tmp_file = $_SESSION['LSsession']['tmp_file'];
492 self :: $userLDAPcreds = $_SESSION['LSsession']['userLDAPcreds'];
494 if ( self :: cacheLSprofiles() && !isset($_REQUEST['LSsession_refresh']) ) {
495 self :: setLdapServer(self :: $ldapServerId);
496 if (!LSauth :: start()) {
497 LSdebug("LSsession : can't start LSauth -> stop");
500 self :: $LSprofiles = $_SESSION['LSsession']['LSprofiles'];
501 self :: $LSaccess = $_SESSION['LSsession']['LSaccess'];
502 if (!self :: LSldapConnect())
506 self :: setLdapServer(self :: $ldapServerId);
507 if (!LSauth :: start()) {
508 LSdebug("LSsession : can't start LSauth -> stop");
511 if (!self :: LSldapConnect())
513 self :: loadLSprofiles();
516 if ( self :: cacheSudDn() && (!isset($_REQUEST['LSsession_refresh'])) ) {
517 self :: $_subDnLdapServer = ((isset($_SESSION['LSsession_subDnLdapServer']))?$_SESSION['LSsession_subDnLdapServer']:NULL);
520 if (!self :: loadLSobject(self :: $ldapServer['authObjectType'])) {
524 if (isset($_GET['LSsession_logout'])) {
528 if (is_array($_SESSION['LSsession']['tmp_file'])) {
529 self :: $tmp_file = $_SESSION['LSsession']['tmp_file'];
531 self :: deleteTmpFile();
532 unset($_SESSION['LSsession']);
534 self :: redirect('index.php');
538 if ( !self :: cacheLSprofiles() || isset($_REQUEST['LSsession_refresh']) ) {
539 self :: loadLSaccess();
542 LStemplate :: assign('LSsession_username',self :: getLSuserObject() -> getDisplayName());
544 if (isset ($_POST['LSsession_topDn']) && $_POST['LSsession_topDn']) {
545 if (self :: validSubDnLdapServer($_POST['LSsession_topDn'])) {
546 self :: $topDn = $_POST['LSsession_topDn'];
547 $_SESSION['LSsession']['topDn'] = $_POST['LSsession_topDn'];
555 // --------------------- Session inexistante --------------------- //
556 if (isset($_GET['LSsession_recoverPassword'])) {
559 // Session inexistante
560 if (isset($_POST['LSsession_ldapserver'])) {
561 self :: setLdapServer($_POST['LSsession_ldapserver']);
564 self :: setLdapServer(0);
567 // Connexion au serveur LDAP
568 if (self :: LSldapConnect()) {
571 if (isset($_POST['LSsession_topDn']) && $_POST['LSsession_topDn'] != '' ){
572 self :: $topDn = $_POST['LSsession_topDn'];
575 self :: $topDn = self :: $ldapServer['ldap_config']['basedn'];
577 $_SESSION['LSsession_topDn']=self :: $topDn;
579 if (!LSauth :: start()) {
580 LSdebug("LSsession : can't start LSauth -> stop");
584 if (isset($_GET['LSsession_recoverPassword'])) {
585 $recoveryPasswordInfos = self :: recoverPasswd(
586 $_REQUEST['LSsession_user'],
587 $_GET['recoveryHash']
591 $LSuserObject = LSauth :: forceAuthentication();
593 // Authentication successful
594 self :: $LSuserObject = $LSuserObject;
595 self :: $dn = $LSuserObject->getValue('dn');
596 self :: $rdn = $LSuserObject->getValue('rdn');
597 if (isset(self :: $ldapServer['useUserCredentials']) && self :: $ldapServer['useUserCredentials']) {
598 self :: $userLDAPcreds = LSauth :: getLDAPcredentials($LSuserObject);
599 if (!is_array(self :: $userLDAPcreds)) {
600 LSerror :: addErrorCode('LSsession_14');
601 self :: $userLDAPcreds = false;
604 if (!LSldap :: reconnectAs(self :: $userLDAPcreds['dn'],self :: $userLDAPcreds['pwd'])) {
605 LSerror :: addErrorCode('LSsession_15');
609 self :: loadLSprofiles();
610 self :: loadLSaccess();
611 LStemplate :: assign('LSsession_username',self :: getLSuserObject() -> getDisplayName());
612 $_SESSION['LSsession']=self :: getContextInfos();
618 LSerror :: addErrorCode('LSsession_09');
621 if (self :: $ldapServerId) {
622 LStemplate :: assign('ldapServerId',self :: $ldapServerId);
624 LStemplate :: assign('topDn',self :: $topDn);
625 if (isset($_GET['LSsession_recoverPassword'])) {
626 self :: displayRecoverPasswordForm($recoveryPasswordInfos);
628 elseif(LSauth :: displayLoginForm()) {
629 self :: displayLoginForm();
632 self :: setTemplate('blank.tpl');
633 LSerror :: addErrorCode('LSsession_10');
640 * Do recover password
642 * @param[in] $username string The submited username
643 * @param[in] $recoveryHash string The submited recoveryHash
645 * @retval array The recoveryPassword infos for template
647 private static function recoverPasswd($username,$recoveryHash) {
648 $recoveryPasswordInfos=array();
649 if ( self :: loadLSobject(self :: $ldapServer['authObjectType']) ) {
650 $authobject = new self :: $ldapServer['authObjectType']();
651 if (!empty($recoveryHash)) {
652 $filter=Net_LDAP2_Filter::create(
653 self :: $ldapServer['recoverPassword']['recoveryHashAttr'],
657 $result = $authobject -> listObjects($filter,self :: $topDn);
659 elseif (!empty($username)) {
660 $result = $authobject -> searchObject(
663 self :: $ldapServer['authObjectFilter']
667 return $recoveryPasswordInfos;
670 $nbresult=count($result);
673 LSdebug('hash/username incorrect');
674 LSerror :: addErrorCode('LSsession_06');
676 elseif ($nbresult>1) {
677 LSerror :: addErrorCode('LSsession_07');
680 $rdn = $result[0] -> getValue('rdn');
682 LSdebug('Recover : Id trouvé : '.$username);
683 if (self :: $ldapServer['recoverPassword']) {
684 if (self :: loadLSaddon('mail')) {
685 LSdebug('Récupération active');
687 $emailAddress = $user -> getValue(self :: $ldapServer['recoverPassword']['mailAttr']);
688 $emailAddress = $emailAddress[0];
690 if (checkEmail($emailAddress)) {
691 LSdebug('Email : '.$emailAddress);
692 self :: $dn = $user -> getDn();
694 // 1ère étape : envoie du recoveryHash
695 if (empty($recoveryHash)) {
696 $hash=self :: recoverPasswdFirstStep($user);
698 if (self :: recoverPasswdSendMail($emailAddress,1,$hash)) {
699 // Mail a bien été envoyé
700 $recoveryPasswordInfos['recoveryHashMail']=$emailAddress;
704 // 2nd étape : génération du mot de passe + envoie par mail
706 $pwd=self :: recoverPasswdSecondStep($user);
708 if (self :: recoverPasswdSendMail($emailAddress,2,$pwd)){
709 // Mail a bien été envoyé
710 $recoveryPasswordInfos['newPasswordMail']=$emailAddress;
716 LSerror :: addErrorCode('LSsession_19');
721 LSerror :: addErrorCode('LSsession_18');
725 return $recoveryPasswordInfos;
729 * Send recover password mail
731 * @param[in] $mail string The user's mail
732 * @param[in] $step integer The step
733 * @param[in] $info string The info for formatted message
735 * @retval boolean True on success or False
737 private static function recoverPasswdSendMail($mail,$step,$info) {
740 if (self :: $ldapServer['recoverPassword']['recoveryEmailSender']) {
741 $sendParams['From']=self :: $ldapServer['recoverPassword']['recoveryEmailSender'];
745 if ($_SERVER['HTTPS']=='on') {
746 $recovery_url='https://';
749 $recovery_url='http://';
751 $recovery_url .= $_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'].'&recoveryHash='.$info;
753 $subject = self :: $ldapServer['recoverPassword']['recoveryHashMail']['subject'];
755 self :: $ldapServer['recoverPassword']['recoveryHashMail']['msg'],
760 $subject = self :: $ldapServer['recoverPassword']['newPasswordMail']['subject'];
762 self :: $ldapServer['recoverPassword']['newPasswordMail']['msg'],
767 if (!sendMail($mail,$subject,$msg,$sendParams)) {
768 LSdebug("Problème durant l'envoie du mail");
769 LSerror :: addErrorCode('LSsession_20',4);
777 * Do first step of recovering password
779 * @param[in] $user LSldapObject The LSldapObject of the user
781 * @retval string|False The recory hash on success or False
783 private static function recoverPasswdFirstStep($user) {
785 $rdn=$user -> getValue('rdn');
787 $recovery_hash = md5($rdn . strval(time()) . strval(rand()));
789 $lostPasswdForm = $user -> getForm('lostPassword');
790 $lostPasswdForm -> setPostData(
792 self :: $ldapServer['recoverPassword']['recoveryHashAttr'] => $recovery_hash
797 if($lostPasswdForm -> validate()) {
798 if ($user -> updateData('lostPassword')) {
799 // recoveryHash de l'utilisateur mis à jour
800 return $recovery_hash;
803 // Erreur durant la mise à jour de l'objet
804 LSdebug("Erreur durant la mise à jour de l'objet");
805 LSerror :: addErrorCode('LSsession_20',6);
809 // Erreur durant la validation du formulaire de modification de perte de password
810 LSdebug("Erreur durant la validation du formulaire de modification de perte de password");
811 LSerror :: addErrorCode('LSsession_20',5);
817 * Do second step of recovering password
819 * @param[in] $user LSldapObject The LSldapObject of the user
821 * @retval string|False The new password on success or False
823 private static function recoverPasswdSecondStep($user) {
824 $attr=$user -> attrs[self :: $ldapServer['authObjectTypeAttrPwd']];
825 if ($attr instanceof LSattribute) {
826 $mdp = generatePassword(
827 $attr -> config['html_options']['chars'],
828 $attr -> config['html_options']['lenght']
830 LSdebug('Nvx mpd : '.$mdp);
831 $lostPasswdForm = $user -> getForm('lostPassword');
832 $lostPasswdForm -> setPostData(
834 self :: $ldapServer['recoverPassword']['recoveryHashAttr'] => array(''),
835 self :: $ldapServer['authObjectTypeAttrPwd'] => array($mdp)
839 if($lostPasswdForm -> validate()) {
840 if ($user -> updateData('lostPassword')) {
844 // Erreur durant la mise à jour de l'objet
845 LSdebug("Erreur durant la mise à jour de l'objet");
846 LSerror :: addErrorCode('LSsession_20',3);
850 // Erreur durant la validation du formulaire de modification de perte de password
851 LSdebug("Erreur durant la validation du formulaire de modification de perte de password");
852 LSerror :: addErrorCode('LSsession_20',2);
856 // l'attribut password n'existe pas
857 LSdebug("L'attribut password n'existe pas");
858 LSerror :: addErrorCode('LSsession_20',1);
864 * Retourne les informations du contexte
866 * @author Benjamin Renard <brenard@easter-eggs.com
868 * @retval array Tableau associatif des informations du contexte
870 private static function getContextInfos() {
872 'tmp_file' => self :: $tmp_file,
873 'topDn' => self :: $topDn,
875 'rdn' => self :: $rdn,
876 'userLDAPcreds' => self :: $userLDAPcreds,
877 'ldapServerId' => self :: $ldapServerId,
878 'ldapServer' => self :: $ldapServer,
879 'LSprofiles' => self :: $LSprofiles,
880 'LSaccess' => self :: $LSaccess
885 * Retourne l'objet de l'utilisateur connecté
887 * @author Benjamin Renard <brenard@easter-eggs.com
889 * @retval mixed L'objet de l'utilisateur connecté ou false si il n'a pas put
892 public static function getLSuserObject($dn=null) {
896 if (!self :: $LSuserObject) {
897 if (self :: loadLSobject(self :: $ldapServer['authObjectType'])) {
898 self :: $LSuserObject = new self :: $ldapServer['authObjectType']();
899 self :: $LSuserObject -> loadData(self :: $dn);
905 return self :: $LSuserObject;
909 * Retourne le DN de l'utilisateur connecté
911 * @author Benjamin Renard <brenard@easter-eggs.com
913 * @retval string Le DN de l'utilisateur connecté
915 public static function getLSuserObjectDn() {
920 * Modifie l'utilisateur connecté à la volé
922 * @param[in] $object Mixed L'objet Ldap du nouvel utilisateur
923 * le type doit correspondre à
924 * self :: $ldapServer['authObjectType']
926 * @retval boolean True en cas de succès, false sinon
928 public static function changeAuthUser($object) {
929 if ($object instanceof self :: $ldapServer['authObjectType']) {
930 self :: $dn = $object -> getDn();
931 $rdn = $object -> getValue('rdn');
936 self :: $LSuserObject = $object;
938 if(self :: loadLSprofiles()) {
939 self :: loadLSaccess();
940 $_SESSION['LSsession']=self :: getContextInfos();
948 * Définition du serveur Ldap de la session
950 * Définition du serveur Ldap de la session à partir de son ID dans
951 * le tableau LSconfig :: get('ldap_servers').
953 * @param[in] integer Index du serveur Ldap
955 * @retval boolean True sinon false.
957 public static function setLdapServer($id) {
958 $conf = LSconfig :: get("ldap_servers.$id");
959 if ( is_array($conf) ) {
960 self :: $ldapServerId = $id;
961 self :: $ldapServer = $conf;
963 self :: setGlobals();
972 * Connexion au serveur Ldap
974 * @retval boolean True sinon false.
976 public static function LSldapConnect() {
977 if (self :: $ldapServer) {
978 self :: includeFile(LSconfig :: get('NetLDAP2'));
979 if (!self :: loadLSclass('LSldap')) {
982 if (self :: $dn && isset(self :: $ldapServer['useUserCredentials']) && self :: $ldapServer['useUserCredentials']) {
983 LSldap :: reconnectAs(self :: $userLDAPcreds['dn'], self :: $userLDAPcreds['pwd'],self :: $ldapServer['ldap_config']);
986 LSldap :: connect(self :: $ldapServer['ldap_config']);
988 if (LSldap :: isConnected()) {
996 LSerror :: addErrorCode('LSsession_03');
1002 * Use this function to know if subDn is enabled for the curent LdapServer
1006 public static function subDnIsEnabled() {
1007 if (!isset(self :: $ldapServer['subDn'])) {
1010 if ( !is_array(self :: $ldapServer['subDn']) ) {
1017 * Retourne les sous-dns du serveur Ldap courant
1019 * @retval mixed Tableau des subDn, false si une erreur est survenue.
1021 public static function getSubDnLdapServer($login=false) {
1022 $login=(bool)$login;
1023 if (self :: cacheSudDn() && isset(self :: $_subDnLdapServer[self :: $ldapServerId][$login])) {
1024 return self :: $_subDnLdapServer[self :: $ldapServerId][$login];
1026 if (!self::subDnIsEnabled()) {
1030 foreach(self :: $ldapServer['subDn'] as $subDn_name => $subDn_config) {
1031 if ($login && isset($subDn_config['nologin']) && $subDn_config['nologin']) continue;
1032 if ($subDn_name == 'LSobject') {
1033 if (is_array($subDn_config)) {
1034 foreach($subDn_config as $LSobject_name => $LSoject_config) {
1035 if (isset($LSoject_config['basedn']) && !empty($LSoject_config['basedn'])) {
1036 $basedn = $LSoject_config['basedn'];
1039 $basedn = self::getRootDn();
1041 if (isset($LSoject_config['displayName']) && !empty($LSoject_config['displayName'])) {
1042 $displayName = $LSoject_config['displayName'];
1045 $displayName = NULL;
1047 if( self :: loadLSobject($LSobject_name) ) {
1048 if ($subdnobject = new $LSobject_name()) {
1049 $tbl_return = $subdnobject -> getSelectArray(NULL,$basedn,$displayName);
1050 if (is_array($tbl_return)) {
1051 $return=array_merge($return,$tbl_return);
1054 LSerror :: addErrorCode('LSsession_17',3);
1058 LSerror :: addErrorCode('LSsession_17',2);
1064 LSerror :: addErrorCode('LSsession_17',1);
1068 if ((isCompatibleDNs($subDn_config['dn'],self :: $ldapServer['ldap_config']['basedn']))&&($subDn_config['dn']!="")) {
1069 $return[$subDn_config['dn']] = __($subDn_name);
1073 if (self :: cacheSudDn()) {
1074 self :: $_subDnLdapServer[self :: $ldapServerId][$login]=$return;
1075 $_SESSION['LSsession_subDnLdapServer'] = self :: $_subDnLdapServer;
1081 * Retourne la liste de subDn du serveur Ldap utilise
1082 * trié par la profondeur dans l'arboressence (ordre décroissant)
1084 * @return array() Tableau des subDn trié
1086 public static function getSortSubDnLdapServer($login=false) {
1087 $subDnLdapServer = self :: getSubDnLdapServer($login);
1088 if (!$subDnLdapServer) {
1091 uksort($subDnLdapServer,"compareDn");
1092 return $subDnLdapServer;
1096 * Retourne les options d'une liste déroulante pour le choix du topDn
1097 * de connexion au serveur Ldap
1099 * Liste les subdn (self :: $ldapServer['subDn'])
1101 * @retval string Les options (<option>) pour la sélection du topDn.
1103 public static function getSubDnLdapServerOptions($selected=NULL,$login=false) {
1104 $list = self :: getSubDnLdapServer($login);
1108 foreach($list as $dn => $txt) {
1109 if ($selected && ($selected==$dn)) {
1110 $selected_txt = ' selected';
1115 $display.="<option value=\"".$dn."\"$selected_txt>".$txt."</option>\n";
1123 * Vérifie qu'un subDn est déclaré
1125 * @param[in] string Un subDn
1127 * @retval boolean True si le subDn existe, False sinon
1129 public static function validSubDnLdapServer($subDn) {
1130 $listTopDn = self :: getSubDnLdapServer();
1131 if(is_array($listTopDn)) {
1132 foreach($listTopDn as $dn => $txt) {
1142 * Test un couple LSobject/pwd
1144 * Test un bind sur le serveur avec le dn de l'objet et le mot de passe fourni.
1146 * @param[in] LSobject L'object "user" pour l'authentification
1147 * @param[in] string Le mot de passe à tester
1149 * @retval boolean True si l'authentification à réussi, false sinon.
1151 public static function checkUserPwd($object,$pwd) {
1152 return LSldap :: checkBind($object -> getValue('dn'),$pwd);
1156 * Affiche le formulaire de login
1158 * Défini les informations pour le template Smarty du formulaire de login.
1162 public static function displayLoginForm() {
1163 LStemplate :: assign('pagetitle',_('Connection'));
1164 if (isset($_GET['LSsession_logout'])) {
1165 LStemplate :: assign('loginform_action','index.php');
1168 LStemplate :: assign('loginform_action',$_SERVER['REQUEST_URI']);
1170 if (count(LSconfig :: get('ldap_servers'))==1) {
1171 LStemplate :: assign('loginform_ldapserver_style','style="display: none"');
1173 LStemplate :: assign('loginform_label_ldapserver',_('LDAP server'));
1174 $ldapservers_name=array();
1175 $ldapservers_index=array();
1176 foreach(LSconfig :: get('ldap_servers') as $id => $infos) {
1177 $ldapservers_index[]=$id;
1178 $ldapservers_name[]=__($infos['name']);
1180 LStemplate :: assign('loginform_ldapservers_name',$ldapservers_name);
1181 LStemplate :: assign('loginform_ldapservers_index',$ldapservers_index);
1183 LStemplate :: assign('loginform_label_level',_('Level'));
1184 LStemplate :: assign('loginform_label_user',_('Identifier'));
1185 LStemplate :: assign('loginform_label_pwd',_('Password'));
1186 LStemplate :: assign('loginform_label_submit',_('Connect'));
1187 LStemplate :: assign('loginform_label_recoverPassword',_('Forgot your password ?'));
1189 self :: setTemplate('login.tpl');
1190 self :: addJSscript('LSsession_login.js');
1194 * Affiche le formulaire de récupération de mot de passe
1196 * Défini les informations pour le template Smarty du formulaire de
1197 * récupération de mot de passe
1199 * @param[in] $infos array() Information sur le status du processus de
1200 * recouvrement de mot de passe
1204 public static function displayRecoverPasswordForm($recoveryPasswordInfos) {
1205 LStemplate :: assign('pagetitle',_('Recovery of your credentials'));
1206 LStemplate :: assign('recoverpasswordform_action','index.php?LSsession_recoverPassword');
1208 if (count(LSconfig :: get('ldap_servers'))==1) {
1209 LStemplate :: assign('recoverpasswordform_ldapserver_style','style="display: none"');
1212 LStemplate :: assign('recoverpasswordform_label_ldapserver',_('LDAP server'));
1213 $ldapservers_name=array();
1214 $ldapservers_index=array();
1215 foreach(LSconfig :: get('ldap_servers') as $id => $infos) {
1216 $ldapservers_index[]=$id;
1217 $ldapservers_name[]=$infos['name'];
1219 LStemplate :: assign('recoverpasswordform_ldapservers_name',$ldapservers_name);
1220 LStemplate :: assign('recoverpasswordform_ldapservers_index',$ldapservers_index);
1222 LStemplate :: assign('recoverpasswordform_label_user',_('Identifier'));
1223 LStemplate :: assign('recoverpasswordform_label_submit',_('Validate'));
1224 LStemplate :: assign('recoverpasswordform_label_back',_('Back'));
1226 $recoverpassword_msg = _('Please fill the identifier field to proceed recovery procedure');
1228 if (isset($recoveryPasswordInfos['recoveryHashMail'])) {
1229 $recoverpassword_msg = getFData(
1230 _("An email has been sent to %{mail}. " .
1231 "Please follow the instructions on it."),
1232 $recoveryPasswordInfos['recoveryHashMail']
1236 if (isset($recoveryPasswordInfos['newPasswordMail'])) {
1237 $recoverpassword_msg = getFData(
1238 _("Your new password has been sent to %{mail}. "),
1239 $recoveryPasswordInfos['newPasswordMail']
1243 LStemplate :: assign('recoverpassword_msg',$recoverpassword_msg);
1245 self :: setTemplate('recoverpassword.tpl');
1246 self :: addJSscript('LSsession_recoverPassword.js');
1250 * Défini le template Smarty à utiliser
1252 * Remarque : les fichiers de templates doivent se trouver dans le dossier
1255 * @param[in] string Le nom du fichier de template
1259 public static function setTemplate($template) {
1260 self :: $template = $template;
1264 * Ajoute un script JS au chargement de la page
1266 * Remarque : les scripts doivents être dans le dossier LS_JS_DIR.
1268 * @param[in] $script Le nom du fichier de script à charger.
1272 public static function addJSscript($file,$path=NULL) {
1277 self :: $JSscripts[$path.$file]=$script;
1281 * Ajouter un paramètre de configuration Javascript
1283 * @param[in] $name string Nom de la variable de configuration
1284 * @param[in] $val mixed Valeur de la variable de configuration
1288 public static function addJSconfigParam($name,$val) {
1289 self :: $_JSconfigParams[$name]=$val;
1293 * Ajoute une feuille de style au chargement de la page
1295 * @param[in] $script Le nom du fichier css à charger.
1299 public static function addCssFile($file,$path=NULL) {
1301 $file = $path.$file;
1304 $file = LStemplate :: getCSSPath($file);
1306 self :: $CssFiles[$file]=$file;
1310 * Affiche le template Smarty
1312 * Charge les dépendances et affiche le template Smarty
1316 public static function displayTemplate() {
1319 foreach ($GLOBALS['defaultJSscipts'] as $script) {
1320 $JSscript_txt.="<script src='".LS_JS_DIR.$script."' type='text/javascript'></script>\n";
1323 foreach (self :: $JSscripts as $script) {
1324 if (!$script['path']) {
1325 $script['path']=LS_JS_DIR;
1328 $script['path'].='/';
1330 $JSscript_txt.="<script src='".$script['path'].$script['file']."' type='text/javascript'></script>\n";
1333 $KAconf = LSconfig :: get('keepLSsessionActive');
1336 (!isset(self :: $ldapServer['keepLSsessionActive']))
1338 (!($KAconf === false))
1341 (self :: $ldapServer['keepLSsessionActive'])
1343 self :: addJSconfigParam('keepLSsessionActive',ini_get('session.gc_maxlifetime'));
1346 LStemplate :: assign('LSjsConfig',json_encode(self :: $_JSconfigParams));
1349 $JSscript_txt.="<script type='text/javascript'>LSdebug_active = 1;</script>\n";
1352 $JSscript_txt.="<script type='text/javascript'>LSdebug_active = 0;</script>\n";
1355 LStemplate :: assign('LSsession_js',$JSscript_txt);
1358 self :: addCssFile("LSdefault.css");
1359 if (isset($GLOBALS['defaultCSSfiles']) && is_array($GLOBALS['defaultCSSfiles'])) {
1360 foreach ($GLOBALS['defaultCSSfiles'] as $file) {
1361 self :: addCssFile($file);
1365 foreach (self :: $CssFiles as $file) {
1366 $Css_txt.="<link rel='stylesheet' type='text/css' href='".$file."' />\n";
1368 LStemplate :: assign('LSsession_css',$Css_txt);
1370 if (isset(self :: $LSaccess[self :: $topDn])) {
1371 LStemplate :: assign('LSaccess',self :: $LSaccess[self :: $topDn]);
1375 $listTopDn = self :: getSubDnLdapServer();
1376 if (is_array($listTopDn)) {
1378 LStemplate :: assign('label_level',self :: getSubDnLabel());
1379 LStemplate :: assign('_refresh',_('Refresh'));
1380 $LSsession_topDn_index = array();
1381 $LSsession_topDn_name = array();
1382 foreach($listTopDn as $index => $name) {
1383 $LSsession_topDn_index[] = $index;
1384 $LSsession_topDn_name[] = $name;
1386 LStemplate :: assign('LSsession_subDn_indexes',$LSsession_topDn_index);
1387 LStemplate :: assign('LSsession_subDn_names',$LSsession_topDn_name);
1388 LStemplate :: assign('LSsession_subDn',self :: $topDn);
1389 LStemplate :: assign('LSsession_subDnName',self :: getSubDnName());
1392 LStemplate :: assign('LSlanguages',self :: getLangList());
1393 LStemplate :: assign('LSlang',self :: $lang);
1394 LStemplate :: assign('LSencoding',self :: $encoding);
1395 LStemplate :: assign('lang_label',_('Language'));
1397 LStemplate :: assign('displayLogoutBtn',LSauth :: displayLogoutBtn());
1398 LStemplate :: assign('displaySelfAccess',LSauth :: displaySelfAccess());
1401 if((!empty($_SESSION['LSsession_infos']))&&(is_array($_SESSION['LSsession_infos']))) {
1402 $txt_infos="<ul>\n";
1403 foreach($_SESSION['LSsession_infos'] as $info) {
1404 $txt_infos.="<li>$info</li>\n";
1406 $txt_infos.="</ul>\n";
1407 LStemplate :: assign('LSinfos',$txt_infos);
1408 $_SESSION['LSsession_infos']=array();
1411 if (self :: $ajaxDisplay) {
1412 LStemplate :: assign('LSerror_txt',LSerror :: getErrors());
1413 LStemplate :: assign('LSdebug_txt',LSdebug_print(true));
1416 LSerror :: display();
1419 if (!self :: $template)
1420 self :: setTemplate('empty.tpl');
1422 LStemplate :: assign('connected_as',_("Connected as"));
1424 LStemplate :: display(self :: $template);
1428 * Défini que l'affichage se fera ou non via un retour Ajax
1430 * @param[in] $val boolean True pour que l'affichage se fasse par un retour
1434 public static function setAjaxDisplay($val=true) {
1435 self :: $ajaxDisplay = (boolean)$val;
1439 * Affiche un retour Ajax
1443 public static function displayAjaxReturn($data=array()) {
1444 if (isset($data['LSredirect']) && (!LSdebugDefined()) ) {
1445 echo json_encode($data);
1449 $data['LSjsConfig'] = self :: $_JSconfigParams;
1452 if((!empty($_SESSION['LSsession_infos']))&&(is_array($_SESSION['LSsession_infos']))) {
1453 $txt_infos="<ul>\n";
1454 foreach($_SESSION['LSsession_infos'] as $info) {
1455 $txt_infos.="<li>$info</li>\n";
1457 $txt_infos.="</ul>\n";
1458 $data['LSinfos'] = $txt_infos;
1459 $_SESSION['LSsession_infos']=array();
1462 if (LSerror :: errorsDefined()) {
1463 $data['LSerror'] = LSerror :: getErrors();
1466 if (isset($_REQUEST['imgload'])) {
1467 $data['imgload'] = $_REQUEST['imgload'];
1470 if (LSdebugDefined()) {
1471 $data['LSdebug'] = LSdebug_print(true,false);
1474 echo json_encode($data);
1478 * Retournne un template Smarty compilé
1480 * @param[in] string $template Le template à retourner
1481 * @param[in] array $variables Variables Smarty à assigner avant l'affichage
1483 * @retval string Le HTML compilé du template
1485 public static function fetchTemplate($template,$variables=array()) {
1486 foreach($variables as $name => $val) {
1487 LStemplate :: assign($name,$val);
1489 return LStemplate :: fetch($template);
1493 * Prend un tableau de LSobject et le réduit en utilisant un filtre de
1494 * recherche sur un autre type de LSobject.
1496 * Si une erreur est présente dans le tableau de définition du filtre, un
1497 * tableau vide est renvoyé.
1499 * @param[in] string $LSobject le type LSobject par défaut
1500 * @param[in] array $set tableau de LSobject
1501 * @param[in] array $filter_def définition du filtre de recherche pour la réduction
1502 * @param[in] string $basend basedn pour la recherche, null par défaut
1504 * @retval array le nouveau tableau de LSobject
1506 private static function reduceLdapSet($LSobject, $set, $filter_def, $basedn=null) {
1511 if (! isset($filter_def['filter']) &&
1512 (! isset($filter_def['attr']) ||
1513 ! isset($filter_def['attr_value']))) {
1514 LSdebug("Filtre de profil LSobject invalide " . var_export($filter_def, true));
1518 LSdebug('LSsession :: reducing set of');
1519 foreach ($set as $object) {
1520 LSdebug('LSsession :: -> ' . $object -> getDn());
1523 $LSobject = isset($filter_def['LSObject']) ? $filter_def['LSobject'] : $LSobject;
1524 LSdebug('LSobject :: ' . $LSobject);
1526 foreach ($set as $object) {
1527 if (isset($filter_def['filter'])) {
1528 $filters[] = $object -> getFData($filter_def['filter']);
1531 $value = $object -> getFData($filter_def['attr_value']);
1532 $filters[] = Net_LDAP2_Filter::create($filter_def['attr'], 'equals', $value);
1535 $filter = LSldap::combineFilters('or', $filters);
1537 'basedn' => isset($filter_def['basedn']) ? $filter_def['basedn'] : $basedn,
1538 'filter' => $filter,
1540 if (isset($filter_def['params']) && is_array($filter_def['params'])) {
1541 $params = array_merge($filter_def['params'],$params);
1543 $LSsearch = new LSsearch($LSobject,'LSsession :: loadLSprofiles',$params,true);
1544 $LSsearch -> run(false);
1546 $set = $LSsearch -> listObjects();
1547 LSdebug('LSsession :: reduced set to');
1548 foreach ($set as $object) {
1549 LSdebug('LSsession :: -> ' . $object -> getDn());
1555 * Charge les droits LS de l'utilisateur : uniquement du type LSobjects
1557 * @param[in] string $
1561 private static function loadLSprofilesLSobjects($profile, $LSobject, $listInfos) {
1562 if (! self :: loadLSclass('LSsearch')) {
1563 LSdebug('Impossible de charger la classe LSsearch');
1566 # we are gonna grow a set of objects progressively, we start from the user
1567 $set = array(self :: getLSuserObject());
1568 $basedn = isset($listInfos['basedn']) ? $listInfos['basedn'] : null;
1569 $LSobject = isset($listInfos['LSobject']) ? $listInfos['LSobject'] : $LSobject;
1571 if (isset($listInfos['filters']) && is_array($listInfos['filters'])) {
1572 foreach ($listInfos['filters'] as $filter_def) {
1573 $set = self :: reduceLdapSet($LSobject, $set, $filter_def, $basedn);
1576 if (isset($listInfos['filter']) || (isset($listInfos['attr']) && isset($listInfos['attr_value']))) {
1577 # support legacy profile definition
1578 $set = self :: reduceLdapSet($LSobject, $set, $listInfos, $basedn);
1582 foreach ($set as $object) {
1583 $DNs[] = $object -> getDn();
1585 if (!is_array(self :: $LSprofiles[$profile])) {
1586 self :: $LSprofiles[$profile]=$DNs;
1589 foreach($DNs as $dn) {
1590 if (!in_array($dn,self :: $LSprofiles[$profile])) {
1591 self :: $LSprofiles[$profile][] = $dn;
1598 * Charge les droits LS de l'utilisateur
1600 * @retval boolean True si le chargement à réussi, false sinon.
1602 private static function loadLSprofiles() {
1603 if (is_array(self :: $ldapServer['LSprofiles'])) {
1604 foreach (self :: $ldapServer['LSprofiles'] as $profile => $profileInfos) {
1605 if (is_array($profileInfos)) {
1606 foreach ($profileInfos as $topDn => $rightsInfos) {
1608 * If $topDn == 'LSobject', we search for each LSobject type to find
1609 * all items on witch the user will have powers.
1611 if ($topDn == 'LSobjects') {
1612 if (is_array($rightsInfos)) {
1613 foreach ($rightsInfos as $LSobject => $listInfos) {
1614 LSdebug('loading LSprofile ' . $profile . ' for LSobject ' . $LSobject . ' with params ' . var_export($listInfos, true));
1615 self :: loadLSprofilesLSobjects($profile, $LSobject, $listInfos);
1619 LSdebug('LSobjects => [] doit etre un tableau');
1623 if (is_array($rightsInfos)) {
1624 foreach($rightsInfos as $dn => $conf) {
1625 if ((isset($conf['attr'])) && (isset($conf['LSobject']))) {
1626 if( self :: loadLSobject($conf['LSobject']) ) {
1627 if ($object = new $conf['LSobject']()) {
1628 if ($object -> loadData($dn)) {
1629 $listDns=$object -> getValue($conf['attr']);
1630 $valKey = (isset($conf['attr_value']))?$conf['attr_value']:'%{dn}';
1631 $val = self :: getLSuserObject() -> getFData($valKey);
1632 if (is_array($listDns)) {
1633 if (in_array($val,$listDns)) {
1634 self :: $LSprofiles[$profile][] = $topDn;
1639 LSdebug('Impossible de chargé le dn : '.$dn);
1643 LSdebug('Impossible de créer l\'objet de type : '.$conf['LSobject']);
1648 if (self :: $dn == $dn) {
1649 self :: $LSprofiles[$profile][] = $topDn;
1655 if ( self :: $dn == $rightsInfos ) {
1656 self :: $LSprofiles[$profile][] = $topDn;
1659 } // fin else ($topDn == 'LSobjects')
1660 } // fin foreach($profileInfos)
1661 } // fin is_array($profileInfos)
1662 } // fin foreach LSprofiles
1663 LSdebug(self :: $LSprofiles);
1672 * Charge les droits d'accès de l'utilisateur pour construire le menu de l'interface
1676 private static function loadLSaccess() {
1678 if (isset(self :: $ldapServer['subDn']) && is_array(self :: $ldapServer['subDn'])) {
1679 foreach(self :: $ldapServer['subDn'] as $name => $config) {
1680 if ($name=='LSobject') {
1681 if (is_array($config)) {
1683 // Définition des subDns
1684 foreach($config as $objectType => $objectConf) {
1685 if (self :: loadLSobject($objectType)) {
1686 if ($subdnobject = new $objectType()) {
1687 $tbl = $subdnobject -> getSelectArray(NULL,self::getRootDn(),NULL,NULL,false);
1688 if (is_array($tbl)) {
1689 // Définition des accès
1691 if (is_array($objectConf['LSobjects'])) {
1692 foreach($objectConf['LSobjects'] as $type) {
1693 if (self :: loadLSobject($type)) {
1694 if (self :: canAccess($type)) {
1695 $access[$type] = LSconfig :: get('LSobjects.'.$type.'.label');
1700 foreach($tbl as $dn => $dn_name) {
1701 $LSaccess[$dn]=$access;
1710 if ((isCompatibleDNs(self :: $ldapServer['ldap_config']['basedn'],$config['dn']))&&($config['dn']!='')) {
1712 if (is_array($config['LSobjects'])) {
1713 foreach($config['LSobjects'] as $objectType) {
1714 if (self :: loadLSobject($objectType)) {
1715 if (self :: canAccess($objectType)) {
1716 $access[$objectType] = LSconfig :: get('LSobjects.'.$objectType.'.label');
1721 $LSaccess[$config['dn']]=$access;
1727 if(is_array(self :: $ldapServer['LSaccess'])) {
1729 foreach(self :: $ldapServer['LSaccess'] as $objectType) {
1730 if (self :: loadLSobject($objectType)) {
1731 if (self :: canAccess($objectType)) {
1732 $access[$objectType] = LSconfig :: get('LSobjects.'.$objectType.'.label');
1736 $LSaccess[self :: $topDn] = $access;
1739 if (LSauth :: displaySelfAccess()) {
1740 foreach($LSaccess as $dn => $access) {
1741 $LSaccess[$dn] = array_merge(
1743 'SELF' => 'My account'
1749 self :: $LSaccess = $LSaccess;
1750 $_SESSION['LSsession']['LSaccess'] = $LSaccess;
1754 * Dit si l'utilisateur est du profil pour le DN spécifié
1756 * @param[in] string $profile de l'objet
1757 * @param[in] string $dn DN de l'objet
1759 * @retval boolean True si l'utilisateur est du profil sur l'objet, false sinon.
1761 public static function isLSprofile($dn,$profile) {
1762 if (is_array(self :: $LSprofiles[$profile])) {
1763 foreach(self :: $LSprofiles[$profile] as $topDn) {
1767 else if ( isCompatibleDNs($dn,$topDn) ) {
1776 * Retourne qui est l'utilisateur par rapport à l'object
1778 * @param[in] string Le DN de l'objet
1780 * @retval string 'admin'/'self'/'user' pour Admin , l'utilisateur lui même ou un simple utilisateur
1782 public static function whoami($dn) {
1783 $retval = array('user');
1785 foreach(self :: $LSprofiles as $profile => $infos) {
1786 if(self :: isLSprofile($dn,$profile)) {
1791 if (self :: $dn == $dn) {
1799 * Retourne le droit de l'utilisateur à accèder à un objet
1801 * @param[in] string $LSobject Le type de l'objet
1802 * @param[in] string $dn Le DN de l'objet (le container_dn du type de l'objet par défaut)
1803 * @param[in] string $right Le type de droit d'accès à tester ('r'/'w')
1804 * @param[in] string $attr Le nom de l'attribut auquel on test l'accès
1806 * @retval boolean True si l'utilisateur a accès, false sinon
1808 public static function canAccess($LSobject,$dn=NULL,$right=NULL,$attr=NULL) {
1809 if (!self :: loadLSobject($LSobject)) {
1813 $whoami = self :: whoami($dn);
1814 if ($dn==self :: getLSuserObject() -> getValue('dn')) {
1815 if (!self :: in_menu('SELF')) {
1820 $obj = new $LSobject();
1822 if (!self :: in_menu($LSobject,$obj -> subDnValue)) {
1828 $objectdn=LSconfig :: get('LSobjects.'.$LSobject.'.container_dn').','.self :: $topDn;
1829 $whoami = self :: whoami($objectdn);
1832 // Pour un attribut particulier
1835 $attr=LSconfig :: get('LSobjects.'.$LSobject.'.rdn');
1837 if (!is_array(LSconfig :: get('LSobjects.'.$LSobject.'.attrs.'.$attr))) {
1842 foreach($whoami as $who) {
1843 $nr = LSconfig :: get('LSobjects.'.$LSobject.'.attrs.'.$attr.'.rights.'.$who);
1847 else if($nr == 'r') {
1854 if (($right=='r')||($right=='w')) {
1861 if ( ($r=='r') || ($r=='w') ) {
1868 // Pour un attribut quelconque
1869 $attrs_conf=LSconfig :: get('LSobjects.'.$LSobject.'.attrs');
1870 if (is_array($attrs_conf)) {
1871 if (($right=='r')||($right=='w')) {
1872 foreach($whoami as $who) {
1873 foreach ($attrs_conf as $attr_name => $attr_config) {
1874 if (isset($attr_config['rights'][$who]) && $attr_config['rights'][$who]==$right) {
1881 foreach($whoami as $who) {
1882 foreach ($attrs_conf as $attr_name => $attr_config) {
1883 if ( (isset($attr_config['rights'][$who])) && ( ($attr_config['rights'][$who]=='r') || ($attr_config['rights'][$who]=='w') ) ) {
1894 * Retourne le droit de l'utilisateur à editer à un objet
1896 * @param[in] string $LSobject Le type de l'objet
1897 * @param[in] string $dn Le DN de l'objet (le container_dn du type de l'objet par défaut)
1898 * @param[in] string $attr Le nom de l'attribut auquel on test l'accès
1900 * @retval boolean True si l'utilisateur a accès, false sinon
1902 public static function canEdit($LSobject,$dn=NULL,$attr=NULL) {
1903 return self :: canAccess($LSobject,$dn,'w',$attr);
1907 * Retourne le droit de l'utilisateur à supprimer un objet
1909 * @param[in] string $LSobject Le type de l'objet
1910 * @param[in] string $dn Le DN de l'objet (le container_dn du type de l'objet par défaut)
1912 * @retval boolean True si l'utilisateur a accès, false sinon
1914 public static function canRemove($LSobject,$dn) {
1915 return self :: canAccess($LSobject,$dn,'w','rdn');
1919 * Retourne le droit de l'utilisateur à créer un objet
1921 * @param[in] string $LSobject Le type de l'objet
1923 * @retval boolean True si l'utilisateur a accès, false sinon
1925 public static function canCreate($LSobject) {
1926 if (!self :: loadLSobject($LSobject)) {
1929 if (LSconfig :: get("LSobjects.$LSobject.disable_creation")) {
1932 return self :: canAccess($LSobject,NULL,'w','rdn');
1936 * Retourne le droit de l'utilisateur à gérer la relation d'objet
1938 * @param[in] string $dn Le DN de l'objet (le container_dn du type de l'objet par défaut)
1939 * @param[in] string $LSobject Le type de l'objet
1940 * @param[in] string $relationName Le nom de la relation avec l'objet
1941 * @param[in] string $right Le type de droit a vérifier ('r' ou 'w')
1943 * @retval boolean True si l'utilisateur a accès, false sinon
1945 public static function relationCanAccess($dn,$LSobject,$relationName,$right=NULL) {
1946 $relConf=LSconfig :: get('LSobjects.'.$LSobject.'.LSrelation.'.$relationName);
1947 if (!is_array($relConf))
1949 $whoami = self :: whoami($dn);
1951 if (($right=='w') || ($right=='r')) {
1953 foreach($whoami as $who) {
1954 $nr = ((isset($relConf['rights'][$who]))?$relConf['rights'][$who]:'');
1958 else if($nr == 'r') {
1970 foreach($whoami as $who) {
1971 if ((isset($relConf['rights'][$who])) && ( ($relConf['rights'][$who] == 'w') || ($relConf['rights'][$who] == 'r') ) ) {
1980 * Retourne le droit de l'utilisateur à modifier la relation d'objet
1982 * @param[in] string $dn Le DN de l'objet (le container_dn du type de l'objet par défaut)
1983 * @param[in] string $LSobject Le type de l'objet
1984 * @param[in] string $relationName Le nom de la relation avec l'objet
1986 * @retval boolean True si l'utilisateur a accès, false sinon
1988 public static function relationCanEdit($dn,$LSobject,$relationName) {
1989 return self :: relationCanAccess($dn,$LSobject,$relationName,'w');
1993 * Retourne le droit de l'utilisateur a executer une customAction
1995 * @param[in] string $dn Le DN de l'objet
1996 * @param[in] string $LSobject Le type de l'objet
1997 * @param[in] string $customActionName Le nom de la customAction
1999 * @retval boolean True si l'utilisateur peut executer cette customAction, false sinon
2001 public static function canExecuteCustomAction($dn,$LSobject,$customActionName) {
2002 $conf=LSconfig :: get('LSobjects.'.$LSobject.'.customActions.'.$customActionName);
2003 if (!is_array($conf))
2005 $whoami = self :: whoami($dn);
2007 if (isset($conf['rights']) && is_array($conf['rights'])) {
2008 foreach($whoami as $who) {
2009 if (in_array($who,$conf['rights'])) {
2019 * Retourne le droit de l'utilisateur a executer une customAction
2022 * @param[in] string $LSsearch L'objet LSsearch
2023 * @param[in] string $customActionName Le nom de la customAction
2025 * @retval boolean True si l'utilisateur peut executer cette customAction, false sinon
2027 public static function canExecuteLSsearchCustomAction($LSsearch,$customActionName) {
2028 $conf=LSconfig :: get('LSobjects.'.$LSsearch -> LSobject.'.LSsearch.customActions.'.$customActionName);
2029 if (!is_array($conf))
2031 $dn=$LSsearch -> basedn;
2032 if (is_null($dn)) $dn=self::getTopDn();
2034 $whoami = self :: whoami($dn);
2036 if (isset($conf['rights']) && is_array($conf['rights'])) {
2037 foreach($whoami as $who) {
2038 if (in_array($who,$conf['rights'])) {
2048 * Ajoute un fichier temporaire
2050 * @author Benjamin Renard <brenard@easter-eggs.com>
2054 public static function addTmpFile($value,$filePath) {
2055 $hash = mhash(MHASH_MD5,$value);
2056 self :: $tmp_file[$filePath] = $hash;
2057 $_SESSION['LSsession']['tmp_file'][$filePath] = $hash;
2061 * Retourne le chemin du fichier temporaire si l'existe
2063 * @author Benjamin Renard <brenard@easter-eggs.com>
2065 * @param[in] $value La valeur du fichier
2069 public static function tmpFileExist($value) {
2070 $hash = mhash(MHASH_MD5,$value);
2071 foreach(self :: $tmp_file as $filePath => $contentHash) {
2072 if ($hash == $contentHash) {
2080 * Retourne le chemin du fichier temporaire
2082 * Retourne le chemin du fichier temporaire qu'il créera à partir de la valeur
2083 * s'il n'existe pas déjà .
2085 * @author Benjamin Renard <brenard@easter-eggs.com>
2087 * @param[in] $value La valeur du fichier
2091 public static function getTmpFile($value) {
2092 $exist = self :: tmpFileExist($value);
2094 $img_path = LS_TMP_DIR .rand().'.tmp';
2095 $fp = fopen($img_path, "w");
2096 fwrite($fp, $value);
2098 self :: addTmpFile($value,$img_path);
2107 * Supprime les fichiers temporaires
2109 * @author Benjamin Renard <brenard@easter-eggs.com>
2113 public static function deleteTmpFile($filePath=NULL) {
2116 unset(self :: $tmp_file[$filePath]);
2117 unset($_SESSION['LSsession']['tmp_file'][$filePath]);
2120 foreach(self :: $tmp_file as $file => $content) {
2123 self :: $tmp_file = array();
2124 $_SESSION['LSsession']['tmp_file'] = array();
2129 * Retourne true si le cache des droits est activé
2131 * @author Benjamin Renard <brenard@easter-eggs.com>
2133 * @retval boolean True si le cache des droits est activé, false sinon.
2135 public static function cacheLSprofiles() {
2136 return ( (LSconfig :: get('cacheLSprofiles')) || (self :: $ldapServer['cacheLSprofiles']) );
2140 * Retourne true si le cache des subDn est activé
2142 * @author Benjamin Renard <brenard@easter-eggs.com>
2144 * @retval boolean True si le cache des subDn est activé, false sinon.
2146 public static function cacheSudDn() {
2147 return ( (LSconfig :: get('cacheSubDn')) || (self :: $ldapServer['cacheSubDn']));
2151 * Retourne true si le cache des recherches est activé
2153 * @author Benjamin Renard <brenard@easter-eggs.com>
2155 * @retval boolean True si le cache des recherches est activé, false sinon.
2157 public static function cacheSearch() {
2158 return ( (LSconfig :: get('cacheSearch')) || (self :: $ldapServer['cacheSearch']));
2162 * Retourne le label des niveaux pour le serveur ldap courant
2164 * @author Benjamin Renard <brenard@easter-eggs.com>
2166 * @retval string Le label des niveaux pour le serveur ldap dourant
2168 public static function getSubDnLabel() {
2169 return (self :: $ldapServer['subDnLabel']!='')?__(self :: $ldapServer['subDnLabel']):_('Level');
2173 * Retourne le nom du subDn
2175 * @param[in] $subDn string subDn
2177 * @retval string Le nom du subDn ou '' sinon
2179 public static function getSubDnName($subDn=false) {
2181 $subDn = self :: $topDn;
2183 if (self :: getSubDnLdapServer(false)) {
2184 if (isset(self :: $_subDnLdapServer[self :: $ldapServerId][false][$subDn])) {
2185 return self :: $_subDnLdapServer[self :: $ldapServerId][false][$subDn];
2192 * L'objet est t-il utilisé pour listé les subDnS
2194 * @param[in] $type string Le type d'objet
2196 * @retval boolean true si le type d'objet est un subDnObject, false sinon
2198 public static function isSubDnLSobject($type) {
2200 if (isset(self :: $ldapServer['subDn']['LSobject']) && is_array(self :: $ldapServer['subDn']['LSobject'])) {
2201 foreach(self :: $ldapServer['subDn']['LSobject'] as $key => $value) {
2211 * Indique si un type d'objet est dans le menu courant
2213 * @retval boolean true si le type d'objet est dans le menu, false sinon
2215 public static function in_menu($LSobject,$topDn=NULL) {
2217 $topDn=self :: $topDn;
2219 return isset(self :: $LSaccess[$topDn][$LSobject]);
2223 * Indique si le serveur LDAP courant a des subDn
2225 * @retval boolean true si le serveur LDAP courant a des subDn, false sinon
2227 public static function haveSubDn() {
2228 return (isset(self :: $ldapServer['subDn']) && is_array(self :: $ldapServer['subDn']));
2232 * Ajoute une information à afficher
2234 * @param[in] $msg string Le message à afficher
2238 public static function addInfo($msg) {
2239 $_SESSION['LSsession_infos'][]=$msg;
2243 * Redirection de l'utilisateur vers une autre URL
2245 * @param[in] $url string L'URL
2246 * @param[in] $exit boolean Si true, l'execution script s'arrête après la redirection
2250 public static function redirect($url,$exit=true) {
2251 LStemplate :: assign('url',$url);
2252 LStemplate :: display('redirect.tpl');
2259 * Retourne l'adresse mail d'emission configurée pour le serveur courant
2261 * @retval string Adresse mail d'emission
2263 public static function getEmailSender() {
2264 return self :: $ldapServer['emailSender'];
2268 * Ajout d'une information d'aide
2270 * @param[in] $group string Le nom du groupe d'infos dans lequels ajouter
2272 * @param[in] $infos array Tableau array(name => value) des infos
2276 public static function addHelpInfos($group,$infos) {
2277 if (is_array($infos)) {
2278 if (isset(self :: $_JSconfigParams['helpInfos'][$group]) && is_array(self :: $_JSconfigParams['helpInfos'][$group])) {
2279 self :: $_JSconfigParams['helpInfos'][$group] = array_merge(self :: $_JSconfigParams['helpInfos'][$group],$infos);
2282 self :: $_JSconfigParams['helpInfos'][$group] = $infos;
2288 * Défini les codes erreur relative à la classe LSsession
2292 private static function defineLSerrors() {
2296 LSerror :: defineError('LSsession_01',
2297 _("LSsession : The constant %{const} is not defined.")
2299 LSerror :: defineError('LSsession_02',
2300 _("LSsession : The %{addon} support is uncertain. Verify system compatibility and the add-on configuration.")
2302 LSerror :: defineError('LSsession_03',
2303 _("LSsession : LDAP server's configuration data are invalid. Can't connect.")
2305 LSerror :: defineError('LSsession_04',
2306 _("LSsession : Failed to load LSobject type %{type} : unknon type.")
2308 LSerror :: defineError('LSsession_05',
2309 _("LSsession : Failed to load LSclass %{class}.")
2311 LSerror :: defineError('LSsession_06',
2312 _("LSsession : Login or password incorrect.")
2314 LSerror :: defineError('LSsession_07',
2315 _("LSsession : Impossible to identify you : Duplication of identities.")
2317 LSerror :: defineError('LSsession_08',
2318 _("LSsession : Can't load class of authentification (%{class}).")
2320 LSerror :: defineError('LSsession_09',
2321 _("LSsession : Can't connect to LDAP server.")
2323 LSerror :: defineError('LSsession_10',
2324 _("LSsession : Impossible to authenticate you.")
2326 LSerror :: defineError('LSsession_11',
2327 _("LSsession : Your are not authorized to do this action.")
2329 LSerror :: defineError('LSsession_12',
2330 _("LSsession : Some informations are missing to display this page.")
2332 LSerror :: defineError('LSsession_13',
2333 _("LSsession : The function of the custom action %{name} does not exists or is not configured.")
2335 LSerror :: defineError('LSsession_14',
2336 _("LSsession : Fail to retreive user's LDAP credentials from LSauth.")
2338 LSerror :: defineError('LSsession_15',
2339 _("LSsession : Fail to reconnect to LDAP server with user's LDAP credentials.")
2341 LSerror :: defineError('LSsession_16',
2342 _("LSsession : No import/export format define for this object type.")
2344 LSerror :: defineError('LSsession_17',
2345 _("LSsession : Error during creation of list of levels. Contact administrators. (Code : %{code})")
2347 LSerror :: defineError('LSsession_18',
2348 _("LSsession : The password recovery is disabled for this LDAP server.")
2350 LSerror :: defineError('LSsession_19',
2351 _("LSsession : Some informations are missing to recover your password. Contact administrators.")
2353 LSerror :: defineError('LSsession_20',
2354 _("LSsession : Error during password recovery. Contact administrators.(Step : %{step})")
2356 // 21 : not yet used
2357 LSerror :: defineError('LSsession_22',
2358 _("LSsession : problem during initialisation.")
2363 * Ajax method when change ldapserver on login form
2365 * @param[in] $data array The return data address
2369 public static function ajax_onLdapServerChangedLogin(&$data) {
2370 if ( isset($_REQUEST['server']) ) {
2371 self :: setLdapServer($_REQUEST['server']);
2373 if ( self :: LSldapConnect() ) {
2374 if (session_id()=="") session_start();
2375 if (isset($_SESSION['LSsession_topDn'])) {
2376 $sel = $_SESSION['LSsession_topDn'];
2381 $list = self :: getSubDnLdapServerOptions($sel,true);
2382 if (is_string($list)) {
2383 $data['list_topDn'] = "<select name='LSsession_topDn' id='LSsession_topDn'>".$list."</select>";
2384 $data['subDnLabel'] = self :: getSubDnLabel();
2387 $data['recoverPassword'] = isset(self :: $ldapServer['recoverPassword']);
2392 * Ajax method when change ldapserver on recoverPassword form
2394 * @param[in] $data array The return data address
2398 public static function ajax_onLdapServerChangedRecoverPassword(&$data) {
2399 if ( isset($_REQUEST['server']) ) {
2400 self :: setLdapServer($_REQUEST['server']);
2401 $data=array('recoverPassword' => isset(self :: $ldapServer['recoverPassword']));
2406 * Set globals from the ldap server
2410 public static function setGlobals() {
2411 if ( isset(self :: $ldapServer['globals'])) {
2412 foreach(self :: $ldapServer['globals'] as $key => $value) {
2413 $GLOBALS[$key] = $value;