TaskFreak Configuration LDAP
Un développeur a mis en place des modifications du code source afin d'effectuer l'authentification sur un serveur LDAP. Un thread sur le forum officiel est disponible à l'adresse: http://forum.taskfreak.com/index.php?topic=1441.0
Celui ci n'est pas mis à disposition sous forme de zip, ou tar ou autre chose, et il faut télécharger les sources depuis le serveur SVN. Un fichier README.txt
est disponible décrivant la marche à suivre, mais celui ci étant validé pour les versions 0.6.1 et 0.6.2, l'installation sera réalisée manuellement pour une version 0.6.4.
Le fichier est également mis à disposition sur ce Wiki ici
Suite à cette installation, les informations de connexion seront validées sur l'annuaire, rendant le compte admin par défaut non disponible. Il faut donc s'assurer qu'il y a un compte déclaré, qui le soit également dans l'annuaire, et qui possède les droits d'administration. Sinon, les actions d'administration ne seront plus disponibles.
Sommaire
Votre avis
Current user rating: 74/100 (3 votes)
|
|
Composition
Le contenu complet à télécharger est:
+--- config.php +--- LICENCE.txt +--- README.txt +--- CHANGELOG.txt +--- patches | +--- apk_ldap-1.0.php | +--- user_form-1.1.patch | +--- config.php-0.6.2.patch | +--- tzn_user-1.4.patch +--- data | +--- db.sql | +--- icon.gif +--- modify | +--- include | | +--- config.php | | +--- html | | | +--- user_form.php | | +--- classes | | | +--- apk_ldap.php | | | +--- tzn_user.php
Le répertoire patches
contient les différentiels à appliqué à l'aide de la commande shell patch
et ne sont pas pris en compte dans le cadre de cette installation.
Dans le répertoire data
, le fichier db.sql
indique qu'aucune action sur la base de données n'est nécessaire.
Par conséquent, seul le contenu du répertoire modify
sera utilisé. Celui-ci reprend l'arborescence originale de l'application ainsi que les fichiers à modifier.
La mise en place de l'annuaire est en relation avec l'installation faite de OpenLDAP sur un serveur Ubuntu.
Mise en place
Fichier config.php
La première modification à apporter s'effectue sur le fichier include/config.php
afin de définir:
- L'utilisation d'un nouveau mode d'authentification
- Les paramètres de l'annuaire LDAP.
Les paramètres de l'annuaire mis en place sont:
Paramètre | Valeur |
---|---|
APK_LDAP_SERVER | localhost
TaskFreak étant installé sur la même machine que l'annuaire. |
APK_LDAP_BASEDN | ou=people,dc=ejnserver,dc=fr
Tous les utilisateurs sont déclarés sous cet ou. |
APK_LDAP_BINDDN | cn=admin,dc=ejnserver,dc=fr
Comptes administrateur de l'annuaire |
APK_LDAP_BINDPW | ADMIN_PASSWORD
Le mot de passe du compte défini dans ldap.bindDn. |
APK_LDAP_FILTER | (uid=%s)
Filtre appliqué afin d'identifier les utilisateurs sous la racine définie dans APK_LDAP_BASEDN. |
D'autre paramètres sont disponibles pour le comportement de la création automatique des comptes. Mais ceux ci ne sont pas utilisés.
Enfin, des paramètres permettent de définir le mapping des données des utilisateurs sous TaskFreak et la définition LDAP, dans la variable globale confLdapAttributesMapping
. Le mapping par défaut mis en place correspond à l'annuaire installé:
Propriété TaskFreak | Propriété LDAP |
---|---|
APK_LDAP_SERVER | localhost
TaskFreak étant installé sur la même machine que l'annuaire. |
firstName | givenName |
lastName | sn |
username | uid |
<?php
/****************************************************************************\
* TaskFreak! *
* multi user *
******************************************************************************
* Version: 0.6.4 *
* Authors: Stan Ozier <taskfreak@gmail.com> *
* License: http://www.gnu.org/licenses/gpl.txt (GPL) *
\****************************************************************************/
error_reporting(E_ALL ^ E_NOTICE ^ E_DEPRECATED);
define('TZN_DB_HOST','localhost');
#define('TZN_DB_USER','root'); // edit here
#define('TZN_DB_PASS',''); // edit here
#define('TZN_DB_BASE','taskfreak'); // edit here
define('TZN_DB_USER','taskfreak');
define('TZN_DB_PASS','TASKFREAK_ADMIN_PASSWORD');
define('TZN_DB_BASE','taskfreak');
define('TZN_DB_PREFIX','frk');
define('TZN_DB_CLASS','tzn_mysql.php');
define('TZN_DB_DEBUG',2);
define('TZN_DB_PERMANENT',0);
define('TZN_DEBUG',0);
define('TZN_SPECIALCHARS',2);
define('TZN_HTMLMODE','html');
define('TZN_BOOL_TRUE','<img src="images/check_yes.png" width="12" height="13" border="0" />');
define('TZN_BOOL_FALSE','<img src="images/check_no.png" width="12" height="13" border="0" />');
define('TZN_TZDEFAULT','user');
define('TZN_DATEFIELD','SQL');
define('TZN_TRANS_ID',1);
define('TZN_TRANS_STATUS',1);
define('TZN_DB_ASC_OFF','images/o_asc.png');
define('TZN_DB_ASC_ON','images/o_asc_on.png');
define('TZN_DB_DESC_OFF','images/o_desc.png');
define('TZN_DB_DESC_ON','images/o_desc_on.png');
define('TZN_DB_PAGING_OFF','');
define('TZN_DB_PAGING_ON','');
define('TZN_DB_PAGING_ENABLED','tznPagingEnabled');
define('TZN_DB_PAGING_DISABLED','tznPagingDisabled');
define('TZN_DB_ERROR_PAGE','error.php');
define('TZN_USER_ID_LENGTH',8); // length of room/user ID
define('TZN_USER_LOGIN','username');// Login mode = username OR email
define('TZN_USER_NAME_MIN',3); // minimum length for username
define('TZN_USER_NAME_MAX',10); // maximum length for username
define('TZN_USER_PASS_MIN',3); // minimum length for password
define('TZN_USER_PASS_MAX',10); // maximum length for password
define('TZN_USER_PASS_MODE',4);
define('TZN_FILE_RANDOM',false);
define('TZN_FILE_GD_VERSION',2);
define('TZN_FILE_GD_QUALITY',65);
if (@is_dir('./include')) {
define('PRJ_ROOT_PATH','./');
} else {
define('PRJ_ROOT_PATH','../');
}
define('PRJ_INCLUDE_PATH',PRJ_ROOT_PATH.'include/');
define('PRJ_CLASS_PATH',PRJ_INCLUDE_PATH.'classes/');
define('PRJ_WWW_PATH',PRJ_ROOT_PATH.'/');
define('TZN_FILE_ICONS_PATH',PRJ_WWW_PATH.'icons/');
define('TZN_FILE_ICONS_URL','icons/');
define('TZN_FILE_TEMP_PATH',PRJ_WWW_PATH.'temp/');
define('TZN_FILE_TEMP_URL','temp/');
define('TZN_FILE_UPLOAD_PATH',PRJ_WWW_PATH.'files/');
define('TZN_FILE_UPLOAD_URL','files/');
// uncomment the following if you have slashes added before quotes in submitted input
// define('TZN_MAGIC_FIX',TRUE);
define('PRJ_WWW_URL','http://'.$_SERVER['SERVER_NAME'].dirname($_SERVER['PHP_SELF']).'/');
// === TASKFREAK CUSTOMIZATION ================================
define('FRK_VERSION','0.6.4');
define('FRK_VERSION_RELEASE','2010-06-27');
define('FRK_MYSQL_VERSION_GT_4_1',FALSE);
// number of priority levels
define('FRK_PRIORITY_LEVELS',9); // 3, 5 or 9
// how many levels to get status at 100%
define('FRK_STATUS_LEVELS',5); // 1 to 5
// add column context
define('FRK_CONTEXT_ENABLE',TRUE); // TRUE or FALSE
// add description to tasks / todos
define('FRK_DESCRIPTION_ENABLE',TRUE); // TRUE OR FALSE
// default user's country
define('FRK_DEFAULT_COUNTRY','FR');
// charset (for unicode support)
define('FRK_CHARSET','UTF-8');
// use only if you have encoding/utf8 problems
define('TZN_FORCE_UTF-8',FALSE);
// authorize auto login
define('PRJ_AUTO_LOGIN',true);
// enable password reminder
define('PRJ_PASSWORD_REMINDER',false);
// enable registration process (0=no, 1=activation by admin, 2=user gets activation email)
define('PRJ_REGISTRATION',0);
// sort order by default (also used for RSS field)
define('FRK_DEFAULT_SORT_COLUMN','deadlineDate'); // deadlineDate, priority, project...
define('FRK_DEFAULT_SORT_ORDER',1); // 1 = Ascending, -1 = Descending
// language of the interface
define('FRK_DEFAULT_LANGUAGE','en'); // en, fr, it, de, nl, da, zh, pl
// TaskFreak! skin
define('FRK_DEFAULT_SKIN_FOLDER','redfreak'); // or bluefreak
// show own tasks or all users' tasks by default
define('FRK_DEFAULT_VIEW_OWN_TASKS',FALSE);
// limit number of tasks to show at once (applies to today's task view only)
define('FRK_DEFAULT_CURRENT_TASKS',0); // 0 = no limit
// includes tasks with no deadline by default or not
define('FRK_DEFAULT_NO_DEADLINE_TOO',TRUE); // TRUE or FALSE
// when task is marked as done, keep in task list for X days
define('FRK_DEFAULT_NO_DEADLINE_KEEP',0); // number of days
// deadline: displays day of the week (or tomorrow) or '1 day'
define('FRK_DEFAULT_DATEDIFF_MODE','day'); // day or diff or date
// deadline: displays 'tomorrow' for next day
define('FRK_DEFAULT_DATEDIFF_TOMORROW',TRUE); // TRUE or FALSE
// show full text (true) or icons (false)
define('FRK_DEFAULT_CONTEXT_LONG',FALSE); // TRUE or FALSE
// number of items in RSS file (set to 0 if you don't want to enable RSS)
define('FRK_DEFAULT_RSS_SIZE',8);
// show own tasks only, or all users' tasks in rss
define('FRK_DEFAULT_RSS_OWN_ONLY',FALSE);
// default visibility
define('FRK_DEFAULT_VISIBILITY',1); // 0 = public, 1 = internal, 2 = private
// default comment order
define('FRK_DEFAULT_COMMENT_ORDER','ASC');
// update deadline on completed
define('FRK_COMPLETE_DEADLINE',TRUE);
// US date format mm/dd (eg. 14th may = 5/14 vs. 14/5)
define('TZN_DATE_US_FORMAT',FALSE);
// do you need confirmation when setting task as completed (from task list)
define('FRK_CONFIRM_STATUS_CLOSE',TRUE);
// do not keep user connected (disable background ajax request)
define('FRK_DISCONNECT_ON_TIMEOUT',FALSE); // false = keep connected, true = kick out when session times out
// would the page reload for real every X minutes?
define('FRK_RELOAD_FOR_REAL',10);
// hide far future tasks (number of days)
define('FRK_DEFAULT_FAR_FUTURE_HIDE',0);
// === DATE FORMATS ===========================================
define("TZN_DATE_SHT","%d %b %y");
define("TZN_DATE_SHX","%a %d %b %y");
define("TZN_DATE_LNG","%d %B %Y");
define("TZN_DATE_LNX","%A %d %B %Y");
define("TZN_DATETIME_EUR","%d/%m/%y %H:%M");
define("TZN_DATETIME_USA","%m/%d/%y %I:%M%p");
define("TZN_DATETIME_SHT","%d %b %y %H:%M");
define("TZN_DATETIME_SHX","%a %d %b %y %H:%M");
define("TZN_DATETIME_LNG","%d %B %Y, %H:%M");
define("TZN_DATETIME_LNX","%A %d %B %Y, %H:%M");
// === CONTEXTS ===============================================
$GLOBALS['confContext'] = array(
1 => '#939',
2 => '#c33',
3 => '#66f',
4 => '#090',
5 => '#963',
6 => '#39c',
7 => '#3c9',
8 => '#999'
);
// === ACCESS RIGHTS ==========================================
// Change access rights settings with care.
// A switch with value 0 means right is not given
// A switch with value 1 means right is given
// Example #1: the 3rd switch on confProjectRights sets the right for a
// user to edit (modify) any comment to a task belonging to a project he's
// associated with.
// Example #2: the 10th switch in confGlobalRights sets the right for a user
// to change the status of any project, whatever he's associated with it or not
$GLOBALS['confProjectRights'] = array(
0 => '00000', // user not associated to project
1 => '100000000000000', // extern
2 => '110000000000000', // official
3 => '110001000000000', // member
4 => '111101111011000', // moderator
5 => '111111111111111' // leader
);
// These are rights of users associated with a specific project
// comments: 1:see all, 2:add new comment, 3:edit any, 4:delete any
// tasks : 6:create new, 7:edit any, 8:change status, 9:delete any, 10: view tasks
// project : 11:manage users, 12:change status, 13:edit info, 14:delete
$GLOBALS['confGlobalRights'] = array(
1 => '000000000000000', // guests
2 => '100000000011100', // intern
3 => '110000100111100', // manager
4 => '111111111111111' // administrator
);
// These are global rights of user over the entire application
// users: : 1:see all, 2:create new, 3:edit any, 4:delete any
// projects: 6:see all, 7:create new, 8:edit any, 9:delete any, 10:change status
// misc #1 : 11:create own tasks, 12:view internal tasks, 13:view public tasks
// misc #2 : 14:edit any task, 15:system settings
define('FRK_PROJECT_LEADER',count($GLOBALS['confProjectRights']) - 1); // don't touch this
<?php
/****************************************************************************\
* TaskFreak! *
* multi user *
******************************************************************************
* Version: 0.6.4 *
* Authors: Stan Ozier <taskfreak@gmail.com> *
* License: http://www.gnu.org/licenses/gpl.txt (GPL) *
\****************************************************************************/
error_reporting(E_ALL ^ E_NOTICE ^ E_DEPRECATED);
define('TZN_DB_HOST','localhost');
#define('TZN_DB_USER','root'); // edit here
#define('TZN_DB_PASS',''); // edit here
#define('TZN_DB_BASE','taskfreak'); // edit here
define('TZN_DB_USER','taskfreak');
define('TZN_DB_PASS','TASKFREAK_ADMIN_PASSWORD');
define('TZN_DB_BASE','taskfreak');
define('TZN_DB_PREFIX','frk');
define('TZN_DB_CLASS','tzn_mysql.php');
define('TZN_DB_DEBUG',2);
define('TZN_DB_PERMANENT',0);
define('TZN_DEBUG',0);
define('TZN_SPECIALCHARS',2);
define('TZN_HTMLMODE','html');
define('TZN_BOOL_TRUE','<img src="images/check_yes.png" width="12" height="13" border="0" />');
define('TZN_BOOL_FALSE','<img src="images/check_no.png" width="12" height="13" border="0" />');
define('TZN_TZDEFAULT','user');
define('TZN_DATEFIELD','SQL');
define('TZN_TRANS_ID',1);
define('TZN_TRANS_STATUS',1);
define('TZN_DB_ASC_OFF','images/o_asc.png');
define('TZN_DB_ASC_ON','images/o_asc_on.png');
define('TZN_DB_DESC_OFF','images/o_desc.png');
define('TZN_DB_DESC_ON','images/o_desc_on.png');
define('TZN_DB_PAGING_OFF','');
define('TZN_DB_PAGING_ON','');
define('TZN_DB_PAGING_ENABLED','tznPagingEnabled');
define('TZN_DB_PAGING_DISABLED','tznPagingDisabled');
define('TZN_DB_ERROR_PAGE','error.php');
define('TZN_USER_ID_LENGTH',8); // length of room/user ID
define('TZN_USER_LOGIN','username');// Login mode = username OR email
define('TZN_USER_NAME_MIN',3); // minimum length for username
define('TZN_USER_NAME_MAX',10); // maximum length for username
define('TZN_USER_PASS_MIN',3); // minimum length for password
define('TZN_USER_PASS_MAX',10); // maximum length for password
#define('TZN_USER_PASS_MODE',4);
define('TZN_USER_PASS_MODE',5);
define('TZN_FILE_RANDOM',false);
define('TZN_FILE_GD_VERSION',2);
define('TZN_FILE_GD_QUALITY',65);
if (@is_dir('./include')) {
define('PRJ_ROOT_PATH','./');
} else {
define('PRJ_ROOT_PATH','../');
}
define('PRJ_INCLUDE_PATH',PRJ_ROOT_PATH.'include/');
define('PRJ_CLASS_PATH',PRJ_INCLUDE_PATH.'classes/');
define('PRJ_WWW_PATH',PRJ_ROOT_PATH.'/');
define('TZN_FILE_ICONS_PATH',PRJ_WWW_PATH.'icons/');
define('TZN_FILE_ICONS_URL','icons/');
define('TZN_FILE_TEMP_PATH',PRJ_WWW_PATH.'temp/');
define('TZN_FILE_TEMP_URL','temp/');
define('TZN_FILE_UPLOAD_PATH',PRJ_WWW_PATH.'files/');
define('TZN_FILE_UPLOAD_URL','files/');
// uncomment the following if you have slashes added before quotes in submitted input
// define('TZN_MAGIC_FIX',TRUE);
define('PRJ_WWW_URL','http://'.$_SERVER['SERVER_NAME'].dirname($_SERVER['PHP_SELF']).'/');
// === TASKFREAK CUSTOMIZATION ================================
define('FRK_VERSION','0.6.4');
define('FRK_VERSION_RELEASE','2010-06-27');
define('FRK_MYSQL_VERSION_GT_4_1',FALSE);
// number of priority levels
define('FRK_PRIORITY_LEVELS',9); // 3, 5 or 9
// how many levels to get status at 100%
define('FRK_STATUS_LEVELS',5); // 1 to 5
// add column context
define('FRK_CONTEXT_ENABLE',TRUE); // TRUE or FALSE
// add description to tasks / todos
define('FRK_DESCRIPTION_ENABLE',TRUE); // TRUE OR FALSE
// default user's country
define('FRK_DEFAULT_COUNTRY','FR');
// charset (for unicode support)
define('FRK_CHARSET','UTF-8');
// use only if you have encoding/utf8 problems
define('TZN_FORCE_UTF-8',FALSE);
// authorize auto login
define('PRJ_AUTO_LOGIN',true);
// enable password reminder
define('PRJ_PASSWORD_REMINDER',false);
// enable registration process (0=no, 1=activation by admin, 2=user gets activation email)
define('PRJ_REGISTRATION',0);
// sort order by default (also used for RSS field)
define('FRK_DEFAULT_SORT_COLUMN','deadlineDate'); // deadlineDate, priority, project...
define('FRK_DEFAULT_SORT_ORDER',1); // 1 = Ascending, -1 = Descending
// language of the interface
define('FRK_DEFAULT_LANGUAGE','en'); // en, fr, it, de, nl, da, zh, pl
// TaskFreak! skin
define('FRK_DEFAULT_SKIN_FOLDER','redfreak'); // or bluefreak
// show own tasks or all users' tasks by default
define('FRK_DEFAULT_VIEW_OWN_TASKS',FALSE);
// limit number of tasks to show at once (applies to today's task view only)
define('FRK_DEFAULT_CURRENT_TASKS',0); // 0 = no limit
// includes tasks with no deadline by default or not
define('FRK_DEFAULT_NO_DEADLINE_TOO',TRUE); // TRUE or FALSE
// when task is marked as done, keep in task list for X days
define('FRK_DEFAULT_NO_DEADLINE_KEEP',0); // number of days
// deadline: displays day of the week (or tomorrow) or '1 day'
define('FRK_DEFAULT_DATEDIFF_MODE','day'); // day or diff or date
// deadline: displays 'tomorrow' for next day
define('FRK_DEFAULT_DATEDIFF_TOMORROW',TRUE); // TRUE or FALSE
// show full text (true) or icons (false)
define('FRK_DEFAULT_CONTEXT_LONG',FALSE); // TRUE or FALSE
// number of items in RSS file (set to 0 if you don't want to enable RSS)
define('FRK_DEFAULT_RSS_SIZE',8);
// show own tasks only, or all users' tasks in rss
define('FRK_DEFAULT_RSS_OWN_ONLY',FALSE);
// default visibility
define('FRK_DEFAULT_VISIBILITY',1); // 0 = public, 1 = internal, 2 = private
// default comment order
define('FRK_DEFAULT_COMMENT_ORDER','ASC');
// update deadline on completed
define('FRK_COMPLETE_DEADLINE',TRUE);
// US date format mm/dd (eg. 14th may = 5/14 vs. 14/5)
define('TZN_DATE_US_FORMAT',FALSE);
// do you need confirmation when setting task as completed (from task list)
define('FRK_CONFIRM_STATUS_CLOSE',TRUE);
// do not keep user connected (disable background ajax request)
define('FRK_DISCONNECT_ON_TIMEOUT',FALSE); // false = keep connected, true = kick out when session times out
// would the page reload for real every X minutes?
define('FRK_RELOAD_FOR_REAL',10);
// hide far future tasks (number of days)
define('FRK_DEFAULT_FAR_FUTURE_HIDE',0);
// === DATE FORMATS ===========================================
define("TZN_DATE_SHT","%d %b %y");
define("TZN_DATE_SHX","%a %d %b %y");
define("TZN_DATE_LNG","%d %B %Y");
define("TZN_DATE_LNX","%A %d %B %Y");
define("TZN_DATETIME_EUR","%d/%m/%y %H:%M");
define("TZN_DATETIME_USA","%m/%d/%y %I:%M%p");
define("TZN_DATETIME_SHT","%d %b %y %H:%M");
define("TZN_DATETIME_SHX","%a %d %b %y %H:%M");
define("TZN_DATETIME_LNG","%d %B %Y, %H:%M");
define("TZN_DATETIME_LNX","%A %d %B %Y, %H:%M");
// === CONTEXTS ===============================================
$GLOBALS['confContext'] = array(
1 => '#939',
2 => '#c33',
3 => '#66f',
4 => '#090',
5 => '#963',
6 => '#39c',
7 => '#3c9',
8 => '#999'
);
// === ACCESS RIGHTS ==========================================
// Change access rights settings with care.
// A switch with value 0 means right is not given
// A switch with value 1 means right is given
// Example #1: the 3rd switch on confProjectRights sets the right for a
// user to edit (modify) any comment to a task belonging to a project he's
// associated with.
// Example #2: the 10th switch in confGlobalRights sets the right for a user
// to change the status of any project, whatever he's associated with it or not
$GLOBALS['confProjectRights'] = array(
0 => '00000', // user not associated to project
1 => '100000000000000', // extern
2 => '110000000000000', // official
3 => '110001000000000', // member
4 => '111101111011000', // moderator
5 => '111111111111111' // leader
);
// These are rights of users associated with a specific project
// comments: 1:see all, 2:add new comment, 3:edit any, 4:delete any
// tasks : 6:create new, 7:edit any, 8:change status, 9:delete any, 10: view tasks
// project : 11:manage users, 12:change status, 13:edit info, 14:delete
$GLOBALS['confGlobalRights'] = array(
1 => '000000000000000', // guests
2 => '100000000011100', // intern
3 => '110000100111100', // manager
4 => '111111111111111' // administrator
);
// These are global rights of user over the entire application
// users: : 1:see all, 2:create new, 3:edit any, 4:delete any
// projects: 6:see all, 7:create new, 8:edit any, 9:delete any, 10:change status
// misc #1 : 11:create own tasks, 12:view internal tasks, 13:view public tasks
// misc #2 : 14:edit any task, 15:system settings
define('FRK_PROJECT_LEADER',count($GLOBALS['confProjectRights']) - 1); // don't touch this
// === LDAP AUTHENTICATION PLUGIN =============================
define("APK_LDAP_SERVER", "localhost") ;
define("APK_LDAP_BASEDN", "ou=people,dc=ejnserver,dc=fr" ) ;
define("APK_LDAP_BINDDN", "cn=admin,dc=ejnserver,dc=fr") ;
define("APK_LDAP_BINDPW", "LDAP_ADMIN_PASSWORD") ;
define("APK_LDAP_FILTER", "(uid=%s)" ) ;
define("APK_LDAP_SCOPE", "one" ) ;
define("APK_LDAP_VERSION", 3) ;
define("APK_LDAP_USESSL", false) ;
define("APK_LDAP_AUTO_USERCREATED", FALSE) ;
define("APK_LDAP_AUTO_USERENABLED", FALSE);
define("APK_LDAP_AUTO_USERLEVEL", 2); // guest=1, user=2, manager=3, admin=4
$GLOBALS['confLdapAttributesMapping'] = array(
'firstName' => 'givenName' ,
'lastName' => 'sn' ,
'email' => 'mail' ,
'username' => 'uid' ,
// 'title' => 'title' ,
// 'city' => 'l' ,
// 'countryId' => 'c' ,
) ;
Fichier tzn_user.php
Les modifications apportées dans ce fichier ajoutent le mode d'authentification sur un annuaire LDAP.
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* Tirzen Framework (TZN)
*
* This declares the common class from which any object from the TZN shall
* inherit. It is compatible with PHP versions 4 and 5.
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* This package is licensed under the LGPL License
* Copyright (C) 2005 Stan Ozier
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* @package Tirzen Framework MySQL database
* @author Stan Ozier <tech@tirzen.com>
* @copyright 2006-2010 - Stan Ozier
* @license http://www.gnu.org/licenses/lgpl.txt (LGPL)
* @link http://www.tirzen.com/tzn/
* @version 1.8
*/
/**
* TZN: Tirzen Framework (TZN)
*
* @package TZN-user
* @author Stan Ozier <stan@tirzen.net>
* @version 1.8 revision 3
*/
/* ------------------------------------------------------------------------ *\
define("TZN_USER_ID_LENGTH",8); // length of room/user ID
define("TZN_USER_LOGIN","username");// Login mode = username OR email
define("TZN_USER_NAME_MIN",3); // minimum length for username
define("TZN_USER_NAME_MAX",10); // maximum length for username
define("TZN_USER_PASS_MIN",3); // minimum length for password
define("TZN_USER_PASS_MAX",10); // maximum length for password
define("TZN_USER_PASS_MODE",3);
// 1 -> PHP crypt function
// 2 -> mySQL crypt
// 3 -> mySQL encode
// ALGO_NAME -> PHP mCrypt_ALGO_NAME
\* ------------------------------------------------------------------------ */
define('TZN_USER_NAME_REGEXP','/^[a-zA-Z0-9._-]+$/');
/**
* User Object - User common features
* @author Stan Ozier <stan@tirzen.net>
* @package tzn_user
* @version 1.8 revision 3
*/
/*
-TODO-
login: check expiration date
checkautologin: add level support
isLogged: add direct checking support (if already checked then return var)
move level to generic class
*/
class TznUser extends TznDb {
var $_logingOut;
// destroying session is not effective,
// so have to set this to true if loggin off
function TznUser($table) {
$this->_properties = array(
'id' => 'UID',
'username' => 'STR',
'password' => 'STR',
'salt' => 'STR',
'autoLogin' => 'BOL',
'timeZone' => 'INT',
'creationDate' => 'DTM',
'expirationDate' => 'DTE',
'lastLoginDate' => 'DTM',
'lastLoginAddress' => 'STR',
'lastChangeDate' => 'DTM',
'visits' => 'NUM',
'badAccess' => 'NUM',
'level' => 'LVL',
'enabled' => 'BOL',
);
$this->_table=$table;
$this->timeZone=0;
}
function qLoginTimeZone($name='tznUserTimeZone') {
$str = <<<EOS
<script type="text/javascript" language="javascript">
var tzo=(new Date().getTimezoneOffset()*60)*(-1);
document.write('<input type="hidden" name="$name" value="'+tzo+'" />');
</script>
EOS;
print $str;
}
function setLogin($username)
{
if ((strlen($username) < TZN_USER_NAME_MIN)
|| (strlen($username) > TZN_USER_NAME_MAX)) {
$this->_error["username"] =
$GLOBALS["langTznUser"]["user_name_limit1"]
.TZN_USER_NAME_MIN.$GLOBALS["langTznUser"]["user_name_limit2"]
.TZN_USER_NAME_MAX.$GLOBALS["langTznUser"]["user_name_limit3"];
return false;
} else if ($this->checkUnique("username",$username)) {
$this->_error["username"] =
$GLOBALS["langTznUser"]["user_name_exists"];
return false;
} else if (preg_match('/^[a-zA-Z0-9\-_]+$/', $username)) {
$this->username = $username;
return true;
} else {
$this->_error["username"] =
$GLOBALS["langTznUser"]["user_name_invalid"];
return false;
}
return true;
}
function setPassword($pass1, $pass2 = false,
$forceEmpty = false, $noEmptyError = false)
{
//echo ("setpass: [ $pass1 / $pass2 ]");
if ($pass1 || $forceEmpty) {
// a pass has been set
if (($pass2 !== false) && ($pass1 != $pass2)) {
// a confirmation has been set but is different
$this->_error["pass"] =
$GLOBALS["langTznUser"]["user_pass_mismatch"];
return false;
}
$this->salt = $this->getRdm(8,
'abcdefghijklmnopqrstuvwxyz'
.'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789');
if ($pass1) {
if ((strlen($pass1) >= TZN_USER_PASS_MIN)
&& (strlen($pass1) <= TZN_USER_PASS_MAX)) {
switch (TZN_USER_PASS_MODE) {
case 1:
$this->password = crypt($pass1 , $this->salt);
break;
case 2:
$this->password = "ENCRYPT('".$pass1."','"
.$this->salt."')";
break;
case 3:
$this->password = "ENCODE('".$pass1."','"
.$this->salt."')";
break;
case 4:
$this->password = "MD5('$pass1')";
break;
default:
$iv = mcrypt_create_iv (mcrypt_get_iv_size(MCRYPT_3DES
, MCRYPT_MODE_ECB), MCRYPT_RAND);
$crypttext = mcrypt_encrypt(TZN_USER_PASS_MODE, $this->_salt
, $pass1, MCRYPT_MODE_ECB, $iv);
$this->password = bin2hex($crypttext);
}
} else {
$this->_error["pass"] =
$GLOBALS["langTznUser"]["user_pass_limit1"]
.TZN_USER_PASS_MIN
.$GLOBALS["langTznUser"]["user_pass_limit2"]
.TZN_USER_PASS_MAX
.$GLOBALS["langTznUser"]["user_pass_limit3"];
return false;
}
} else {
$this->password = "";
}
return true;
} else {
if (!$forceEmpty && !$noEmptyError) {
$this->_error["pass"] =
$GLOBALS["langTznUser"]["user_pass_empty"];
return false;
}
return true;
}
}
function updatePassword() {
$this->update("password, salt, lastChangeDate");
}
function setLoginPassword($username, $pass1, $pass2 = false,
$forceEmpty = false)
{
//echo ("username = $username, pass = $pass1...");
$step1 = $this->setPassword($pass1, $pass2, $forceEmpty, false);
$step2 = $this->setLogin($username);
return ($step1 && $step2);
}
function updateLoginPassword() {
$this->update("username, password, salt, lastChangeDate");
}
function add() {
$this->setDtm('creationDate','NOW');
return parent::add();
}
function updateLevel() {
return $this->update("level,lastChangeDate");
}
function update($fields=null) {
$this->setDtm('lastChangeDate','NOW');
if ($fields && (!preg_match('/lastChangeDate/',$fields))) {
$fields .= ",lastChangeDate";
}
return parent::update($fields);
}
function zBadAccess() {
$strSql = "UPDATE ".$this->gTable()." SET"
." badAccess=badAccess+1"
." WHERE ".$this->getIdKey()." = '".$this->getUid()."'";
$this->getConnection();
$this->query($strSql);
}
function zCheckPassword($password) {
switch (TZN_USER_PASS_MODE) {
case 1:
if ($this->password == "") {
$this->password = crypt("", $this->salt);
}
if (crypt($password, $this->salt) != $this->password) {
// password invalid
$this->_error['login'] =
$GLOBALS["langTznUser"]["user_pass_invalid"];
$this->zBadAccess();
return false;
}
break;
case 2:
$password = addslashes($password); // sanitize for SQL
$strSql = "SELECT ENCRYPT('$password','".$this->salt
."') as passHash";
if ($result = $this->query($strSql)) {
if ($row = $result->rNext()) {
if ($row->passHash == $this->password) {
// password OK
break;
}
}
}
$this->_error['login'] =
$GLOBALS["langTznUser"]["user_pass_invalid"];
$this->zBadAccess();
return false; // error or password mismatch
break;
case 3:
$password = addslashes($password); // sanitize for SQL
$strSql = "SELECT ENCODE('$password','".$this->salt
."') as passHash";
if ($result = $this->query($strSql)) {
if ($row = $result->rNext()) {
if ($row->passHash == $this->password) {
// password OK
break;
}
}
}
$this->_error['login'] =
$GLOBALS["langTznUser"]["user_pass_invalid"];
$this->zBadAccess();
return false; // error or password mismatch
break;
case 4:
if (!$this->password && !$password) {
break;
}
$password = addslashes($password); // sanitize for SQL
$strSql = "SELECT MD5('$password') as passHash";
if ($result = $this->query($strSql)) {
if ($row = $result->rNext()) {
if ($row->passHash == $this->password) {
// password OK
break;
}
}
}
$this->_error['login'] =
$GLOBALS["langTznUser"]["user_pass_invalid"];
$this->zBadAccess();
return false; // error or password mismatch
break;
default:
for ($i = 0; $i < strlen($this->password); $i += 2) {
$passBin .= chr(hexdec(substr($s,$i,2)));
}
$iv = mcrypt_create_iv (mcrypt_get_iv_size (MCRYPT_3DES,
MCRYPT_MODE_ECB), MCRYPT_RAND);
if (mcrypt_decrypt (MCRYPT_3DES, $this->salt, $passBin,
MCRYPT_MODE_ECB, $iv) == $password)
{
break;
}
$this->_error['login'] =
$GLOBALS["langTznUser"]["user_pass_invalid"];
$this->zBadAccess();
return false;
break;
}
return true;
}
function _activateLogin($withLevel = true) {
if ($tz = $_REQUEST['tznUserTimeZone']) {
if ($this->getInt('timeZone') != $tz) {
$this->setInt('timeZone',$tz);
$updTz = ',timeZone';
}
}
// register session
$_SESSION["tznUserId"] = $this->id;
if ($withLevel) {
$_SESSION["tznUserLevel"] = $this->level;
} else {
$_SESSION["tznUserLevel"] = "0";
}
$_SESSION["tznUserTimeZone"] = $this->timeZone;
$_SESSION["tznUserName"] = $this->username;
$_SESSION["tznUserLastLogin"] = $this->lastLoginDate;
$_SESSION["tznUserLastAddress"] = $this->lastLoginAddress;
// update last login
$this->setDtm('lastLoginDate','NOW');
$this->lastLoginAddress = $_SERVER['REMOTE_ADDR'];
$this->badAccess = 0;
$this->visits++;
$this->update('lastLoginDate,lastLoginAddress,badAccess,visits'.$updTz);
}
function login($username, $password, $level=null) {
if ($username == '') {
$this->_error['login'] = $GLOBALS["langTznUser"]["user_name_empty"];
return false;
}
if (!preg_match(TZN_USER_NAME_REGEXP, $username)) {
$this->_error['login'] = $GLOBALS['langTznUser']['user_name_invalid'];
return false;
}
if ($this->loadByKey(TZN_USER_LOGIN,$username)) {
if (($level!=null) && (!$this->getLvl($level))) {
//Insufficient rights
$this->_error['login'] =
$GLOBALS["langTznUser"]["user_forbidden"];
}
if (!$this->enabled) {
//Account Disabled
$this->_error['login'] =
$GLOBALS["langTznUser"]["user_disabled"];
}
if (!$this->zCheckPassword($password)) {
$this->_error['login'] =
$GLOBALS["langTznUser"]["user_password_invalid"];
}
if (count($this->_error)) {
$this->zBadAccess();
return false;
}
} else {
$this->_error['login'] =
$GLOBALS["langTznUser"]["user_name_not_found"];
return false;
}
$this->_activateLogin();
return true;
}
function silentLogin($username, $password) {
if ($username == '') {
return false;
}
if ($this->loadByKey(TZN_USER_LOGIN,$username)) {
if (!$this->enabled) {
//Account Disabled
$this->_error['login'] =
$GLOBALS["langTznUser"]["user_disabled"];
}
if (!$this->zCheckPassword($password)) {
$this->_error['login'] =
$GLOBALS["langTznUser"]["user_password_invalid"];
}
} else {
$this->_error['login'] =
$GLOBALS["langTznUser"]["user_name_not_found"];
return false;
}
return (count($this->_error) == 0);
}
function checkAutoLogin($forReal=true) {
$cookieVal = $_COOKIE['autoLogin'];
if (empty($cookieVal)) {
return false;
}
$arrVal = explode(":",$cookieVal);
$id = $arrVal[0];
$salt = $arrVal[1];
if($this->loadByFilter($this->gTable().'.'.$this->getIdKey()."='".$id
."' AND ".$this->gTable().".salt='".$salt."'"))
{
if (!$forReal) {
return true;
}
setCookie('autoLogin',$this->id.":".$this->salt
,time()+(3600*24*30));
$this->_activateLogin();
return true;
} else {
return false;
}
}
function setAutoLogin() {
if (($this->id) && ($this->salt)) {
setCookie('autoLogin',$this->id.":".$this->salt
,time()+(3600*24*30));
$this->autoLogin = '1';
$this->update('autoLogin');
return true;
}
return false;
}
function resetAutoLogin() {
if ($this->id) {
setCookie('autoLogin');
if ($this->autoLogin) {
$this->autoLogin = "0";
$this->update("autoLogin");
}
return true;
}
return false;
}
function logout() {
$_SESSION = array();
// If it's desired to kill the session, also delete the session cookie.
// Note: This will destroy the session, and not just the session data!
if (isset($_COOKIE[session_name()])) {
setcookie(session_name(), '', time()-42000, '/');
}
// Finally, destroy the session.
@session_destroy();
// while you're at it, delete auto login
$this->resetAutoLogin();
// set internal variable
$this->_logingOut = true;
}
function isLogged($level=null) {
$lUserId = $_SESSION['tznUserId'];
if ($lUserId == 0 || empty($lUserId) || $this->_logingOut) {
return false;
} else {
$this->id = $lUserId;
$this->level = $_SESSION['tznUserLevel'];
$this->timeZone = $_SESSION['tznUserTimeZone'];
$this->username = $_SESSION['tznUserName'];
$this->lastLoginDate = $_SESSION['tznUserLastLogin'];
$this->lastLoginAddress = $_SESSION['tznUserLastAddress'];
if ($level) {
if ($this->getLvl($level)) {
return true;
} else {
return false;
}
} else {
return true;
}
}
}
function forgotPassword($key, $value) {
// type can be 'username' or 'email'
// forgotten password? Try to get it back or generate new one
if ($this->salt == "") {
if (!$this->loadByKey($key,$value)) {
// user not found
$this->_error['forgot'] = $key." not found";
return false;
}
}
switch (TZN_USER_PASS_MODE) {
case 1:
$newpass = $this->getRdm(6,"123456789");
$this->password = crypt($pass1 , $this->salt);
$this->updatePassword();
break;
case 2:
$newpass = $this->getRdm(6,"123456789");
$this->password = "ENCRYPT(\"".$pass1."\",\"".$this->salt."\")";
$this->updatePassword();
break;
case 3:
$strSql = "SELECT DECODE(password, '".$this->salt
."') as pass FROM ".$this->_table
." WHERE ".$this->getIdKey()."=".$this->id;
if ($result = $this->query($strSql)) {
if ($row = $result->nRow()) {
$this->password = $row->pass;
return $this->password;
}
}
$this->_error['forgot'] = "can not decode?";
return false;
break;
case 4:
$newpass = $this->getRdm(6,"123456789");
$this->password = "MD5('$newpass')";
$this->updatePassword();
break;
default:
$iv = mcrypt_create_iv (mcrypt_get_iv_size (MCRYPT_3DES,
MCRYPT_MODE_ECB), MCRYPT_RAND);
$this->password = mcrypt_decrypt (MCRYPT_3DES, $this->salt,
$passBin, MCRYPT_MODE_ECB, $iv);
return $this->password;
break;
}
return $newpass;
}
}
?>
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* Tirzen Framework (TZN)
*
* This declares the common class from which any object from the TZN shall
* inherit. It is compatible with PHP versions 4 and 5.
*
* THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* This package is licensed under the LGPL License
* Copyright (C) 2005 Stan Ozier
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* @package Tirzen Framework MySQL database
* @author Stan Ozier <tech@tirzen.com>
* @copyright 2006-2010 - Stan Ozier
* @license http://www.gnu.org/licenses/lgpl.txt (LGPL)
* @link http://www.tirzen.com/tzn/
* @version 1.8
*/
/**
* TZN: Tirzen Framework (TZN)
*
* @package TZN-user
* @author Stan Ozier <stan@tirzen.net>
* @version 1.8 revision 3
*/
/* ------------------------------------------------------------------------ *\
define("TZN_USER_ID_LENGTH",8); // length of room/user ID
define("TZN_USER_LOGIN","username");// Login mode = username OR email
define("TZN_USER_NAME_MIN",3); // minimum length for username
define("TZN_USER_NAME_MAX",10); // maximum length for username
define("TZN_USER_PASS_MIN",3); // minimum length for password
define("TZN_USER_PASS_MAX",10); // maximum length for password
define("TZN_USER_PASS_MODE",3);
// 1 -> PHP crypt function
// 2 -> mySQL crypt
// 3 -> mySQL encode
// ALGO_NAME -> PHP mCrypt_ALGO_NAME
\* ------------------------------------------------------------------------ */
define('TZN_USER_NAME_REGEXP','/^[a-zA-Z0-9._-]+$/');
/**
* User Object - User common features
* @author Stan Ozier <stan@tirzen.net>
* @package tzn_user
* @version 1.8 revision 3
*/
/*
-TODO-
login: check expiration date
checkautologin: add level support
isLogged: add direct checking support (if already checked then return var)
move level to generic class
*/
class TznUser extends TznDb {
var $_logingOut;
// destroying session is not effective,
// so have to set this to true if loggin off
function TznUser($table) {
$this->_properties = array(
'id' => 'UID',
'username' => 'STR',
'password' => 'STR',
'salt' => 'STR',
'autoLogin' => 'BOL',
'timeZone' => 'INT',
'creationDate' => 'DTM',
'expirationDate' => 'DTE',
'lastLoginDate' => 'DTM',
'lastLoginAddress' => 'STR',
'lastChangeDate' => 'DTM',
'visits' => 'NUM',
'badAccess' => 'NUM',
'level' => 'LVL',
'enabled' => 'BOL',
);
$this->_table=$table;
$this->timeZone=0;
}
function qLoginTimeZone($name='tznUserTimeZone') {
$str = <<<EOS
<script type="text/javascript" language="javascript">
var tzo=(new Date().getTimezoneOffset()*60)*(-1);
document.write('<input type="hidden" name="$name" value="'+tzo+'" />');
</script>
EOS;
print $str;
}
function setLogin($username)
{
if ((strlen($username) < TZN_USER_NAME_MIN)
|| (strlen($username) > TZN_USER_NAME_MAX)) {
$this->_error["username"] =
$GLOBALS["langTznUser"]["user_name_limit1"]
.TZN_USER_NAME_MIN.$GLOBALS["langTznUser"]["user_name_limit2"]
.TZN_USER_NAME_MAX.$GLOBALS["langTznUser"]["user_name_limit3"];
return false;
} else if ($this->checkUnique("username",$username)) {
$this->_error["username"] =
$GLOBALS["langTznUser"]["user_name_exists"];
return false;
} else if (preg_match('/^[a-zA-Z0-9\-_]+$/', $username)) {
$this->username = $username;
return true;
} else {
$this->_error["username"] =
$GLOBALS["langTznUser"]["user_name_invalid"];
return false;
}
return true;
}
function setPassword($pass1, $pass2 = false,
$forceEmpty = false, $noEmptyError = false)
{
//echo ("setpass: [ $pass1 / $pass2 ]");
if ($pass1 || $forceEmpty) {
// a pass has been set
if (($pass2 !== false) && ($pass1 != $pass2)) {
// a confirmation has been set but is different
$this->_error["pass"] =
$GLOBALS["langTznUser"]["user_pass_mismatch"];
return false;
}
$this->salt = $this->getRdm(8,
'abcdefghijklmnopqrstuvwxyz'
.'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789');
if ($pass1) {
if ((strlen($pass1) >= TZN_USER_PASS_MIN)
&& (strlen($pass1) <= TZN_USER_PASS_MAX)) {
switch (TZN_USER_PASS_MODE) {
case 1:
$this->password = crypt($pass1 , $this->salt);
break;
case 2:
$this->password = "ENCRYPT('".$pass1."','"
.$this->salt."')";
break;
case 3:
$this->password = "ENCODE('".$pass1."','"
.$this->salt."')";
break;
case 4:
$this->password = "MD5('$pass1')";
break;
case 5:
// $this->password = "MD5('$pass1')";
return false ;
break;
default:
$iv = mcrypt_create_iv (mcrypt_get_iv_size(MCRYPT_3DES
, MCRYPT_MODE_ECB), MCRYPT_RAND);
$crypttext = mcrypt_encrypt(TZN_USER_PASS_MODE, $this->_salt
, $pass1, MCRYPT_MODE_ECB, $iv);
$this->password = bin2hex($crypttext);
}
} else {
$this->_error["pass"] =
$GLOBALS["langTznUser"]["user_pass_limit1"]
.TZN_USER_PASS_MIN
.$GLOBALS["langTznUser"]["user_pass_limit2"]
.TZN_USER_PASS_MAX
.$GLOBALS["langTznUser"]["user_pass_limit3"];
return false;
}
} else {
$this->password = "";
}
return true;
} else {
if (!$forceEmpty && !$noEmptyError) {
$this->_error["pass"] =
$GLOBALS["langTznUser"]["user_pass_empty"];
return false;
}
return true;
}
}
function updatePassword() {
$this->update("password, salt, lastChangeDate");
}
function setLoginPassword($username, $pass1, $pass2 = false,
$forceEmpty = false)
{
//echo ("username = $username, pass = $pass1...");
$step1 = $this->setPassword($pass1, $pass2, $forceEmpty, false);
$step2 = $this->setLogin($username);
return ($step1 && $step2);
}
function updateLoginPassword() {
$this->update("username, password, salt, lastChangeDate");
}
function add() {
$this->setDtm('creationDate','NOW');
return parent::add();
}
function updateLevel() {
return $this->update("level,lastChangeDate");
}
function update($fields=null) {
$this->setDtm('lastChangeDate','NOW');
if ($fields && (!preg_match('/lastChangeDate/',$fields))) {
$fields .= ",lastChangeDate";
}
return parent::update($fields);
}
function zBadAccess() {
$strSql = "UPDATE ".$this->gTable()." SET"
." badAccess=badAccess+1"
." WHERE ".$this->getIdKey()." = '".$this->getUid()."'";
$this->getConnection();
$this->query($strSql);
}
function zCheckPassword($password) {
switch (TZN_USER_PASS_MODE) {
case 1:
if ($this->password == "") {
$this->password = crypt("", $this->salt);
}
if (crypt($password, $this->salt) != $this->password) {
// password invalid
$this->_error['login'] =
$GLOBALS["langTznUser"]["user_pass_invalid"];
$this->zBadAccess();
return false;
}
break;
case 2:
$password = addslashes($password); // sanitize for SQL
$strSql = "SELECT ENCRYPT('$password','".$this->salt
."') as passHash";
if ($result = $this->query($strSql)) {
if ($row = $result->rNext()) {
if ($row->passHash == $this->password) {
// password OK
break;
}
}
}
$this->_error['login'] =
$GLOBALS["langTznUser"]["user_pass_invalid"];
$this->zBadAccess();
return false; // error or password mismatch
break;
case 3:
$password = addslashes($password); // sanitize for SQL
$strSql = "SELECT ENCODE('$password','".$this->salt
."') as passHash";
if ($result = $this->query($strSql)) {
if ($row = $result->rNext()) {
if ($row->passHash == $this->password) {
// password OK
break;
}
}
}
$this->_error['login'] =
$GLOBALS["langTznUser"]["user_pass_invalid"];
$this->zBadAccess();
return false; // error or password mismatch
break;
case 4:
if (!$this->password && !$password) {
break;
}
$password = addslashes($password); // sanitize for SQL
$strSql = "SELECT MD5('$password') as passHash";
if ($result = $this->query($strSql)) {
if ($row = $result->rNext()) {
if ($row->passHash == $this->password) {
// password OK
break;
}
}
}
$this->_error['login'] =
$GLOBALS["langTznUser"]["user_pass_invalid"];
$this->zBadAccess();
return false; // error or password mismatch
break;
case 5:
if (!$this->password && !$password) {
break;
}
require_once dirname(__FILE__) . '/apk_ldap.php' ;
$ldap = new Apk_LdapConnection() ;
if ($ldap->connect())
{
$res = $ldap->authenticate($this->username, $password) ;
$ldap->disconnect() ;
}
return $res ;
break ;
default:
for ($i = 0; $i < strlen($this->password); $i += 2) {
$passBin .= chr(hexdec(substr($s,$i,2)));
}
$iv = mcrypt_create_iv (mcrypt_get_iv_size (MCRYPT_3DES,
MCRYPT_MODE_ECB), MCRYPT_RAND);
if (mcrypt_decrypt (MCRYPT_3DES, $this->salt, $passBin,
MCRYPT_MODE_ECB, $iv) == $password)
{
break;
}
$this->_error['login'] =
$GLOBALS["langTznUser"]["user_pass_invalid"];
$this->zBadAccess();
return false;
break;
}
return true;
}
function _activateLogin($withLevel = true) {
if ($tz = $_REQUEST['tznUserTimeZone']) {
if ($this->getInt('timeZone') != $tz) {
$this->setInt('timeZone',$tz);
$updTz = ',timeZone';
}
}
// register session
$_SESSION["tznUserId"] = $this->id;
if ($withLevel) {
$_SESSION["tznUserLevel"] = $this->level;
} else {
$_SESSION["tznUserLevel"] = "0";
}
$_SESSION["tznUserTimeZone"] = $this->timeZone;
$_SESSION["tznUserName"] = $this->username;
$_SESSION["tznUserLastLogin"] = $this->lastLoginDate;
$_SESSION["tznUserLastAddress"] = $this->lastLoginAddress;
// update last login
$this->setDtm('lastLoginDate','NOW');
$this->lastLoginAddress = $_SERVER['REMOTE_ADDR'];
$this->badAccess = 0;
$this->visits++;
$this->update('lastLoginDate,lastLoginAddress,badAccess,visits'.$updTz);
}
function login($username, $password, $level=null) {
if ($username == '') {
$this->_error['login'] = $GLOBALS["langTznUser"]["user_name_empty"];
return false;
}
if (!preg_match(TZN_USER_NAME_REGEXP, $username)) {
$this->_error['login'] = $GLOBALS['langTznUser']['user_name_invalid'];
return false;
}
if ($this->loadByKey(TZN_USER_LOGIN,$username)) {
if (($level!=null) && (!$this->getLvl($level))) {
//Insufficient rights
$this->_error['login'] =
$GLOBALS["langTznUser"]["user_forbidden"];
}
if (!$this->enabled) {
//Account Disabled
$this->_error['login'] =
$GLOBALS["langTznUser"]["user_disabled"];
}
if (!$this->zCheckPassword($password)) {
$this->_error['login'] =
$GLOBALS["langTznUser"]["user_password_invalid"];
}
if (count($this->_error)) {
$this->zBadAccess();
return false;
}
} else {
if (TZN_USER_PASS_MODE == '5')
{
// Security tricks, to avoid indefinite loops on user creation,
// we put a random value into $GLOBALS['confLdapAutoCreateStatus']
// and just test if this array key exists. If so, we already
if (array_key_exists('confLdapAutoCreateStatus', $GLOBALS))
{
return false ;
}
$GLOBALS['confLdapAutoCreateStatus'] = 0 ;
if ($this->autoCreateFromLdap($username,$password) === true)
{
return $this->login($username,$password,$level);
}
}
$this->_error['login'] =
$GLOBALS["langTznUser"]["user_name_not_found"];
return false;
}
$this->_activateLogin();
return true;
}
function silentLogin($username, $password) {
if ($username == '') {
return false;
}
if ($this->loadByKey(TZN_USER_LOGIN,$username)) {
if (!$this->enabled) {
//Account Disabled
$this->_error['login'] =
$GLOBALS["langTznUser"]["user_disabled"];
}
if (!$this->zCheckPassword($password)) {
$this->_error['login'] =
$GLOBALS["langTznUser"]["user_password_invalid"];
}
} else {
$this->_error['login'] =
$GLOBALS["langTznUser"]["user_name_not_found"];
return false;
}
return (count($this->_error) == 0);
}
function checkAutoLogin($forReal=true) {
$cookieVal = $_COOKIE['autoLogin'];
if (empty($cookieVal)) {
return false;
}
$arrVal = explode(":",$cookieVal);
$id = $arrVal[0];
$salt = $arrVal[1];
if($this->loadByFilter($this->gTable().'.'.$this->getIdKey()."='".$id
."' AND ".$this->gTable().".salt='".$salt."'"))
{
if (!$forReal) {
return true;
}
setCookie('autoLogin',$this->id.":".$this->salt
,time()+(3600*24*30));
$this->_activateLogin();
return true;
} else {
return false;
}
}
function setAutoLogin() {
if (($this->id) && ($this->salt)) {
setCookie('autoLogin',$this->id.":".$this->salt
,time()+(3600*24*30));
$this->autoLogin = '1';
$this->update('autoLogin');
return true;
}
return false;
}
function resetAutoLogin() {
if ($this->id) {
setCookie('autoLogin');
if ($this->autoLogin) {
$this->autoLogin = "0";
$this->update("autoLogin");
}
return true;
}
return false;
}
/**
* Check if we use LDAP authentication backend. If so, then trying
* to retrieve the user from the LDAP directory. If found, we auto
* create it into Taskfreak. Some attributes have to be defined
* previously into the LDAP directory.
* @return boolean
*/
function autoCreateFromLdap($username, $password)
{
if (!APK_LDAP_AUTO_USERCREATED)
{
return false ;
}
require_once dirname(__FILE__) . '/apk_ldap.php' ;
$ldap = new Apk_LdapConnection() ;
if ($ldap->connect())
{
$filter = $ldap->getFormatedFilter($username) ;
$usersdn = $ldap->searchDn($filter) ;
if (is_array($usersdn))
{
$userldap = $ldap->search($filter,
array_values($GLOBALS['confLdapAttributesMapping']),
$usersdn[0], 'base') ;
}
$ldap->disconnect() ;
}
if (sizeof($userldap)>1)
{
$userldap = $userldap[0] ;
foreach ($GLOBALS['confLdapAttributesMapping'] as $field => $attr)
{
$userdata[$field] = $userldap[strtolower($attr)][0] ;
}
if (!array_key_exists('countryId', $userdata))
{
$userdata['countryId'] = FRK_DEFAULT_COUNTRY ;
}
$objEditItem = new Member();
$objEditItem->initObjectProperties();
$objEditItem->setAuto($userdata);
$objEditItem->level = APK_LDAP_AUTO_USERLEVEL ;
$objEditItem->enabled = APK_LDAP_AUTO_USERCREATED ? '1' : '0' ;
$objEditItem->author->id = 1 ;
$objEditItem->password = $this->getRdm(
TZN_USER_PASS_MAX, "1234567890"
."abcdefghijklmnopqrstuvwxyz"
."ABCDEFGHIJKLMNOPQRSTUVWXYZ") ;
if ($objEditItem->add()>1)
{
return true ;
}
}
return false ;
}
function logout() {
$_SESSION = array();
// If it's desired to kill the session, also delete the session cookie.
// Note: This will destroy the session, and not just the session data!
if (isset($_COOKIE[session_name()])) {
setcookie(session_name(), '', time()-42000, '/');
}
// Finally, destroy the session.
@session_destroy();
// while you're at it, delete auto login
$this->resetAutoLogin();
// set internal variable
$this->_logingOut = true;
}
function isLogged($level=null) {
$lUserId = $_SESSION['tznUserId'];
if ($lUserId == 0 || empty($lUserId) || $this->_logingOut) {
return false;
} else {
$this->id = $lUserId;
$this->level = $_SESSION['tznUserLevel'];
$this->timeZone = $_SESSION['tznUserTimeZone'];
$this->username = $_SESSION['tznUserName'];
$this->lastLoginDate = $_SESSION['tznUserLastLogin'];
$this->lastLoginAddress = $_SESSION['tznUserLastAddress'];
if ($level) {
if ($this->getLvl($level)) {
return true;
} else {
return false;
}
} else {
return true;
}
}
}
function forgotPassword($key, $value) {
// type can be 'username' or 'email'
// forgotten password? Try to get it back or generate new one
if ($this->salt == "") {
if (!$this->loadByKey($key,$value)) {
// user not found
$this->_error['forgot'] = $key." not found";
return false;
}
}
switch (TZN_USER_PASS_MODE) {
case 1:
$newpass = $this->getRdm(6,"123456789");
$this->password = crypt($pass1 , $this->salt);
$this->updatePassword();
break;
case 2:
$newpass = $this->getRdm(6,"123456789");
$this->password = "ENCRYPT(\"".$pass1."\",\"".$this->salt."\")";
$this->updatePassword();
break;
case 3:
$strSql = "SELECT DECODE(password, '".$this->salt
."') as pass FROM ".$this->_table
." WHERE ".$this->getIdKey()."=".$this->id;
if ($result = $this->query($strSql)) {
if ($row = $result->nRow()) {
$this->password = $row->pass;
return $this->password;
}
}
$this->_error['forgot'] = "can not decode?";
return false;
break;
case 4:
$newpass = $this->getRdm(6,"123456789");
$this->password = "MD5('$newpass')";
$this->updatePassword();
break;
case 5:
$this->_error['forgot'] = "operation not allowed" ;
return false ;
break ;
default:
$iv = mcrypt_create_iv (mcrypt_get_iv_size (MCRYPT_3DES,
MCRYPT_MODE_ECB), MCRYPT_RAND);
$this->password = mcrypt_decrypt (MCRYPT_3DES, $this->salt,
$passBin, MCRYPT_MODE_ECB, $iv);
return $this->password;
break;
}
return $newpass;
}
}
?>
Fichier apk_ldap.php
Ce fichier est tout simplement ajouté car il n'existe pas. Des fonctions d'interrogations de l'annuaire y sont exposées.
Fichier user_form.php
La modification de ce fichier permet de changer l'apparence du formulaire de création d'un utilisateur.
<fieldset>
<legend><?php echo $langUser['information']; ?></legend>
<p><?php echo $langForm['compulsory_legend']; ?></p>
<table cellpadding="2" cellspacing="1" border="0" class="form">
<tr>
<th width="100"><?php echo $langUser['title']; ?>:</th>
<td><?php $objEditItem->qText('title','','width:50px'); ?> <small>Mr. Mrs. Ms. Dr. Pr. etc...</small></td>
</tr>
<tr>
<th><span class="compulsory"><?php echo $langUser['first_name']; ?></span>:</th>
<td><?php $objEditItem->qText('firstName','','width:250px'); ?></td>
</tr>
<tr>
<th><?php echo $langUser['middle_name']; ?>:</th>
<td><?php $objEditItem->qText('middleName','','width:250px'); ?></td>
</tr>
<tr>
<th><span class="compulsory"><?php echo $langUser['last_name']; ?></span>:</th>
<td><?php $objEditItem->qText('lastName','','width:250px'); ?></td>
</tr>
<tr>
<?php
if ($pUserIsLogged) {
?>
<th><?php echo $langUser['email']; ?>:</th>
<?php
} else {
?>
<th><span class="compulsory"><?php echo $langUser['email']; ?></span>:</th>
<?php
}
?>
<td><?php $objEditItem->qText('email','','width:250px'); ?></td>
</tr>
<tr>
<th><?php echo $langUser['city']; ?>:</th>
<td><?php $objEditItem->qText('city','','width:250px'); ?></td>
</tr>
<tr>
<th><?php echo $langUser['country']; ?>:</th>
<td><?php
$objCountryList->rReset();
$objCountryList->qSelect('countryId','name',$objEditItem->country->id,'','width:250px');
?></td>
</tr>
<tr>
<th><?php echo $langUser['state']; ?>:</th>
<td>
<?php
$objStateList->qSelect('stateCode',$objEditItem->stateCode,$GLOBALS['langUser']['state_us_only'],'width:250px');
$objEditItem->pError('stateCode');
?>
</td>
</tr>
</table>
</fieldset><br />
<fieldset>
<legend><?php echo $langUser['account']; ?></legend>
<p><?php echo $langUser['account_legend']; ?></p>
<table cellpadding="2" cellspacing="1" border="0" class="form">
<tr>
<th width="100"><span class="compulsory"><?php echo $langUser['username']; ?></span>:</th>
<td><?php $objEditItem->qText('username'); ?></td>
</tr>
<?php
if ($objEditItem->isLoaded()) {
?>
<tr>
<td colspan="2" align="center"><small><?php echo $langUser['password_legend']; ?></small></td>
</tr>
<?php
}
?>
<tr>
<th><span class="compulsory"><?php echo $langUser['password']; ?></span>:</th>
<td><input type="password" name="password1" /><?php
if ($strErr = $objEditItem->e('pass')) {
echo '<span class="tznError">'.$strErr.'</span>';
}
?></td>
</tr>
<tr>
<th><span class="compulsory"><?php echo $langUser['password_confirm']; ?></span>:</th>
<td><input type="password" name="password2" /></td>
</tr>
</table>
<?php
if ($pRegisterMessage) {
echo $pRegisterMessage;
}
if ($objUser->checkLevel(2) && ($objUser->id != $objEditItem->id)) {
// --- user is admin and is not editing himself -> edit user rights ---
?>
<p>
<span><?php $objEditItem->qCheckBox('enabled',$objEditItem->enabled,'','onClick="tE(gE(\'cust1\'))"'); ?> <label><?php echo $langUser['enabled_label']; ?></label></span>
<span id="cust1" style="display:<?php echo ($objEditItem->enabled)?'inline':'none'; ?>"><?php $objPositionList->qSelect('level',$objEditItem->level); ?></span>
</p>
<?php
}
?>
</fieldset>
<fieldset>
<legend><?php echo $langUser['information']; ?></legend>
<p><?php echo $langForm['compulsory_legend']; ?></p>
<table cellpadding="2" cellspacing="1" border="0" class="form">
<tr>
<th width="100"><?php echo $langUser['title']; ?>:</th>
<td><?php $objEditItem->qText('title','','width:50px'); ?> <small>Mr. Mrs. Ms. Dr. Pr. etc...</small></td>
</tr>
<tr>
<th><span class="compulsory"><?php echo $langUser['first_name']; ?></span>:</th>
<td><?php $objEditItem->qText('firstName','','width:250px'); ?></td>
</tr>
<tr>
<th><?php echo $langUser['middle_name']; ?>:</th>
<td><?php $objEditItem->qText('middleName','','width:250px'); ?></td>
</tr>
<tr>
<th><span class="compulsory"><?php echo $langUser['last_name']; ?></span>:</th>
<td><?php $objEditItem->qText('lastName','','width:250px'); ?></td>
</tr>
<tr>
<?php
if ($pUserIsLogged) {
?>
<th><?php echo $langUser['email']; ?>:</th>
<?php
} else {
?>
<th><span class="compulsory"><?php echo $langUser['email']; ?></span>:</th>
<?php
}
?>
<td><?php $objEditItem->qText('email','','width:250px'); ?></td>
</tr>
<tr>
<th><?php echo $langUser['city']; ?>:</th>
<td><?php $objEditItem->qText('city','','width:250px'); ?></td>
</tr>
<tr>
<th><?php echo $langUser['country']; ?>:</th>
<td><?php
$objCountryList->rReset();
$objCountryList->qSelect('countryId','name',$objEditItem->country->id,'','width:250px');
?></td>
</tr>
<tr>
<th><?php echo $langUser['state']; ?>:</th>
<td>
<?php
$objStateList->qSelect('stateCode',$objEditItem->stateCode,$GLOBALS['langUser']['state_us_only'],'width:250px');
$objEditItem->pError('stateCode');
?>
</td>
</tr>
</table>
</fieldset><br />
<?php if (TZN_USER_PASS_MODE != 5) { ?>
<fieldset>
<legend><?php echo $langUser['account']; ?></legend>
<p><?php echo $langUser['account_legend']; ?></p>
<table cellpadding="2" cellspacing="1" border="0" class="form">
<tr>
<th width="100"><span class="compulsory"><?php echo $langUser['username']; ?></span>:</th>
<td><?php $objEditItem->qText('username'); ?></td>
</tr>
<?php
if ($objEditItem->isLoaded()) {
?>
<tr>
<td colspan="2" align="center"><small><?php echo $langUser['password_legend']; ?></small></td>
</tr>
<?php
}
?>
<tr>
<th><span class="compulsory"><?php echo $langUser['password']; ?></span>:</th>
<td><input type="password" name="password1" /><?php
if ($strErr = $objEditItem->e('pass')) {
echo '<span class="tznError">'.$strErr.'</span>';
}
?></td>
</tr>
<tr>
<th><span class="compulsory"><?php echo $langUser['password_confirm']; ?></span>:</th>
<td><input type="password" name="password2" /></td>
</tr>
</table>
<?php
if ($pRegisterMessage) {
echo $pRegisterMessage;
}
if ($objUser->checkLevel(2) && ($objUser->id != $objEditItem->id)) {
// --- user is admin and is not editing himself -> edit user rights ---
?>
<p>
<span><?php $objEditItem->qCheckBox('enabled',$objEditItem->enabled,'','onClick="tE(gE(\'cust1\'))"'); ?> <label><?php echo $langUser['enabled_label']; ?></label></span>
<span id="cust1" style="display:<?php echo ($objEditItem->enabled)?'inline':'none'; ?>"><?php $objPositionList->qSelect('level',$objEditItem->level); ?></span>
</p>
<?php
}
?>
</fieldset>
<?php } ?>
Evolution
Sur le paramètre de recherche des utilisateurs, le filtre d'appartenance au groupe taskfreakUsers
. L'appartenance à ce groupe est modélisé à l'aide de l'overly memberOf
installé sur l'annuaire.
Pour cela, l'élément de configuration APK_LDAP_FILTER
dans le fichier config.php
est modifié avec la valeur (&(uid=%s)(memberof=cn=taskfreakUsers,ou=groups,dc=ejnserver,dc=fr))
// define("APK_LDAP_FILTER", "(uid=%s)" ) ;
define("APK_LDAP_FILTER", "(&(uid=%s)(memberof=cn=taskfreakUsers,ou=groups,dc=ejnserver,dc=fr))" ) ;