wb-2_10_x / branches / main / framework / Login.php @ 10
1 |
<?php
|
---|---|
2 |
/**
|
3 |
*
|
4 |
* @category framework
|
5 |
* @package backend login
|
6 |
* @author Ryan Djurovich, WebsiteBaker Project
|
7 |
* @copyright WebsiteBaker Org. e.V.
|
8 |
* @link http://websitebaker.org/
|
9 |
* @license http://www.gnu.org/licenses/gpl.html
|
10 |
* @platform WebsiteBaker 2.8.3
|
11 |
* @requirements PHP 5.3.6 and higher
|
12 |
* @version $Id: Login.php 2 2017-07-02 15:14:29Z Manuela $
|
13 |
* @filesource $HeadURL: svn://isteam.dynxs.de/wb/2.10.x/branches/main/framework/Login.php $
|
14 |
* @lastmodified $Date: 2017-07-02 17:14:29 +0200 (Sun, 02 Jul 2017) $
|
15 |
*
|
16 |
*/
|
17 |
/* -------------------------------------------------------- */
|
18 |
// Must include code to stop this file being accessed directly
|
19 |
if(!defined('WB_PATH')) { |
20 |
require_once(dirname(__FILE__).'/globalExceptionHandler.php'); |
21 |
throw new IllegalFileException(); |
22 |
} |
23 |
/* -------------------------------------------------------- */
|
24 |
define('LOGIN_CLASS_LOADED', true); |
25 |
|
26 |
// Load the other required class files if they are not already loaded
|
27 |
require_once(WB_PATH."/framework/class.admin.php"); |
28 |
// Get WB version
|
29 |
require_once(ADMIN_PATH.'/interface/version.php'); |
30 |
|
31 |
class Login extends admin { |
32 |
|
33 |
const PASS_CHARS = '[\,w!#$%&*+\-.:=?@\|]'; |
34 |
const USER_CHARS = '[a-z0-9&\-.=@_]'; |
35 |
|
36 |
protected $aConfig = array(); |
37 |
protected $oDb = null; |
38 |
protected $oTrans = null; |
39 |
|
40 |
public function __construct($config_array) { |
41 |
// Get language vars
|
42 |
/* global $MESSAGE, $database; */
|
43 |
$this->oDb = $GLOBALS['database']; |
44 |
$this->oTrans = $GLOBALS['MESSAGE']; |
45 |
parent::__construct();
|
46 |
// Get configuration values
|
47 |
while(list($key, $value) = each($config_array)) { |
48 |
// $this->{(strtolower($key))} = $value;
|
49 |
$this->aConfig[strtolower($key)] = $value; |
50 |
} |
51 |
if (!isset($this->frontend)) { $this->frontend = false; } |
52 |
if (!isset($this->redirect_url)) { $this->redirect_url = ''; } |
53 |
|
54 |
// calculate redirect URL
|
55 |
// begin new routine
|
56 |
$sProtokol = ((!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] == 'off' ) ? 'http' : 'https') . '://';; |
57 |
$sInstallFolderRel = dirname(dirname($_SERVER['SCRIPT_NAME'])); |
58 |
$sServerUrl = $sProtokol.$_SERVER['HTTP_HOST'].($_SERVER['SERVER_PORT'] == 80 ? '' : $_SERVER['SERVER_PORT'].':').'/'.$sInstallFolderRel; |
59 |
// end new routine
|
60 |
/*
|
61 |
$aRedirecthUrl = null;
|
62 |
$sServerUrl = $_SERVER['SERVER_NAME'];
|
63 |
$aServerUrl = $this->mb_parse_url(WB_URL);
|
64 |
$sServerScheme = isset($_SERVER['REQUEST_SCHEME']) ? $_SERVER['REQUEST_SCHEME'] : isset($aServerUrl['scheme']) ? $aServerUrl['scheme'] : ' http';
|
65 |
$sServerPath = $_SERVER['SCRIPT_NAME'];
|
66 |
*/
|
67 |
|
68 |
// If the url is blank, set it to the default url
|
69 |
$this->url = @$this->get_post('url')?:@$this->get_post('redirect')?:$this->default_url; |
70 |
/*
|
71 |
if ( !$this->frontend ){ $this->redirect_url = ( @$this->url ? : '' );}
|
72 |
if ( $this->frontend ){ $this->url = ( @$this->redirect_url ? : null );}
|
73 |
*/
|
74 |
if (preg_match('/%0d|%0a|\s/i', $this->url)) { |
75 |
throw new Exception('Warning: possible intruder detected on login'); |
76 |
} |
77 |
/*
|
78 |
$aUrl = $this->mb_parse_url( $this->url );
|
79 |
if ($this->redirect_url!='') {
|
80 |
$aRedirecthUrl = $this->mb_parse_url( $this->redirect_url );
|
81 |
$this->redirect_url = isset($aRedirecthUrl['host']) &&($sServerUrl==$aRedirecthUrl['host']) ? $this->redirect_url:$sServerScheme.'://'.$sServerUrl;
|
82 |
$this->url = $this->redirect_url;
|
83 |
}
|
84 |
$this->url = isset($aRedirecthUrl['host']) &&($sServerUrl==$aUrl['host']) ? $this->url:ADMIN_URL.'/start/index.php';
|
85 |
if(strlen($this->url) < 2) {
|
86 |
$aDefaultUrl = $this->mb_parse_url( $this->default_url );
|
87 |
$this->default_url = isset($aDefaultUrl['host']) &&($sServerUrl==$aDefaultUrl['host']) ? $this->default_url:$sServerScheme.'://'.$sServerUrl;
|
88 |
$this->url = $this->default_url;
|
89 |
}
|
90 |
*/
|
91 |
// get username & password and validate it
|
92 |
$username_fieldname = (string)$this->get_post('username_fieldname'); |
93 |
$username_fieldname = (preg_match('/^_?[a-z][\w]+$/i', $username_fieldname) ? $username_fieldname : 'username'); |
94 |
$sUsername = strtolower(trim((string)$this->get_post($username_fieldname))); |
95 |
$this->username = (preg_match( |
96 |
'/^'.self::USER_CHARS.'{'.$this->min_username_len.','.$this->max_username_len.'}$/is', |
97 |
$sUsername
|
98 |
) ? $sUsername : ''); |
99 |
$password_fieldname = (string)$this->get_post('password_fieldname'); |
100 |
$password_fieldname = (preg_match('/^_?[a-z][\w]+$/i', $password_fieldname) ? $password_fieldname : 'password'); |
101 |
|
102 |
if ($this->username) { |
103 |
/** @TODO implement crypting */
|
104 |
$this->password = md5(trim((string)$this->get_post($password_fieldname))); |
105 |
// Figure out if the "remember me" option has been checked
|
106 |
$this->remember = (@$_POST['remember'] == 'true' ? true : false); |
107 |
// try to authenticate
|
108 |
$bSuccess = false; |
109 |
if (!($bSuccess = $this->is_authenticated())) { |
110 |
if ($this->is_remembered()) { |
111 |
$sql = 'SELECT * FROM `'.TABLE_PREFIX.'users` ' |
112 |
. 'WHERE `user_id`='.$this->get_safe_remember_key(); |
113 |
if (($oUsers = $this->oDb->query($sql))) { |
114 |
if (($aUser = $oUsers->fetchRow(MYSQLI_ASSOC))) { |
115 |
$this->username = $aUser['username']; |
116 |
$this->password = $aUser['password']; |
117 |
// Check if the user exists (authenticate them)
|
118 |
$bSuccess = $this->authenticate(); |
119 |
} |
120 |
} |
121 |
} else {
|
122 |
// Check if the user exists (authenticate them)
|
123 |
$bSuccess = $this->authenticate(); |
124 |
} |
125 |
} |
126 |
if ($bSuccess) { |
127 |
// Authentication successful
|
128 |
$this->send_header($this->url); |
129 |
} else {
|
130 |
$this->message = $this->_oTrans->MESSAGE_LOGIN_AUTHENTICATION_FAILED; |
131 |
$this->increase_attemps();
|
132 |
} |
133 |
} else {
|
134 |
$this->message = $this->_oTrans->MESSAGE_LOGIN_BOTH_BLANK; |
135 |
$this->display_login();
|
136 |
} |
137 |
} |
138 |
|
139 |
public function __isset($name) |
140 |
{ |
141 |
return isset($this->aConfig[$name]); |
142 |
} |
143 |
|
144 |
public function __set($name, $value) |
145 |
{ |
146 |
return $this->aConfig[$name] = $value; |
147 |
} |
148 |
|
149 |
public function __get ($name){ |
150 |
$retval = null; |
151 |
if ($this->__isset($name)) { |
152 |
$retval = $this->aConfig[$name]; |
153 |
} |
154 |
return $retval; |
155 |
} |
156 |
|
157 |
// Authenticate the user (check if they exist in the database)
|
158 |
public function authenticate() |
159 |
{ |
160 |
// Get user information
|
161 |
$loginname = ( preg_match('/^'.self::USER_CHARS.'+$/s',$this->username) ? $this->username : '0'); |
162 |
$aSettings = array(); |
163 |
$aSettings['SYSTEM_PERMISSIONS'] = array(); |
164 |
$aSettings['MODULE_PERMISSIONS'] = array(); |
165 |
$aSettings['TEMPLATE_PERMISSIONS'] = array(); |
166 |
$bRetval = false; |
167 |
|
168 |
$sql = 'SELECT * FROM `'.TABLE_PREFIX.'users` ' |
169 |
. 'WHERE `username`=\''.$this->oDb->escapeString($loginname).'\''; |
170 |
if (($oUser = $this->oDb->query($sql))) { |
171 |
if (($aUser = $oUser->fetchRow(MYSQLI_ASSOC))) { |
172 |
if (
|
173 |
$aUser['password'] == $this->password && |
174 |
$aUser['active'] == 1 |
175 |
) { |
176 |
// valide authentcation !!
|
177 |
$user_id = $aUser['user_id']; |
178 |
$this->user_id = $user_id; |
179 |
$aSettings['USER_ID'] = $user_id; |
180 |
$aSettings['GROUP_ID'] = $aUser['group_id']; |
181 |
$aSettings['GROUPS_ID'] = $aUser['groups_id']; |
182 |
$aSettings['USERNAME'] = $aUser['username']; |
183 |
$aSettings['DISPLAY_NAME'] = $aUser['display_name']; |
184 |
$aSettings['EMAIL'] = $aUser['email']; |
185 |
$aSettings['HOME_FOLDER'] = $aUser['home_folder']; |
186 |
// Run remember function if needed
|
187 |
if($this->remember == true) { $this->remember($this->user_id); } |
188 |
// Set language
|
189 |
if($aUser['language'] != '') { |
190 |
$aSettings['LANGUAGE'] = $aUser['language']; |
191 |
} |
192 |
// Set timezone
|
193 |
if($aUser['timezone'] != '-72000') { |
194 |
$aSettings['TIMEZONE'] = $aUser['timezone']; |
195 |
} else {
|
196 |
// Set a session var so apps can tell user is using default tz
|
197 |
$aSettings['USE_DEFAULT_TIMEZONE'] = true; |
198 |
} |
199 |
// Set date format
|
200 |
if($aUser['date_format'] != '') { |
201 |
$aSettings['DATE_FORMAT'] = $aUser['date_format']; |
202 |
} else {
|
203 |
// Set a session var so apps can tell user is using default date format
|
204 |
$aSettings['USE_DEFAULT_DATE_FORMAT'] = true; |
205 |
} |
206 |
// Set time format
|
207 |
if($aUser['time_format'] != '') { |
208 |
$aSettings['TIME_FORMAT'] = $aUser['time_format']; |
209 |
} else {
|
210 |
// Set a session var so apps can tell user is using default time format
|
211 |
$aSettings['USE_DEFAULT_TIME_FORMAT'] = true; |
212 |
} |
213 |
// Get group information
|
214 |
$aSettings['GROUP_NAME'] = array(); |
215 |
$bOnlyAdminGroup = $this->ami_group_member('1') && (sizeof($aGroupsIds) == 1); |
216 |
$sql = 'SELECT * FROM `'.TABLE_PREFIX.'groups` ' |
217 |
. 'WHERE `group_id` IN ('.$aUser['groups_id'].',0) ' |
218 |
. 'ORDER BY `group_id`';
|
219 |
|
220 |
if (($oGroups = $this->oDb->query($sql))) { |
221 |
while (($aGroup = $oGroups->fetchRow( MYSQLI_ASSOC ))) { |
222 |
$aSettings['GROUP_NAME'][$aGroup['group_id']] = $aGroup['name']; |
223 |
// collect system_permissions (additively)
|
224 |
$aSettings['SYSTEM_PERMISSIONS'] = array_merge( |
225 |
$aSettings['SYSTEM_PERMISSIONS'], |
226 |
explode(',', $aGroup['system_permissions']) |
227 |
); |
228 |
// collect module_permission (subtractive)
|
229 |
if (!sizeof($aSettings['MODULE_PERMISSIONS'])) { |
230 |
$aSettings['MODULE_PERMISSIONS'] = explode(',', $aGroup['module_permissions']); |
231 |
} else {
|
232 |
$aSettings['MODULE_PERMISSIONS'] = array_intersect( |
233 |
$aSettings['MODULE_PERMISSIONS'], |
234 |
preg_split('/\s*[,;\|\+]/', $aGroup['module_permissions'], -1, PREG_SPLIT_NO_EMPTY) |
235 |
); |
236 |
} |
237 |
// collect template_permission (subtractive)
|
238 |
if (!sizeof($aSettings['TEMPLATE_PERMISSIONS'])) { |
239 |
$aSettings['TEMPLATE_PERMISSIONS'] = explode(',', $aGroup['template_permissions']); |
240 |
} else {
|
241 |
$aSettings['TEMPLATE_PERMISSIONS'] = array_intersect( |
242 |
$aSettings['TEMPLATE_PERMISSIONS'], |
243 |
preg_split('/\s*[,;\|\+]/', $aGroup['template_permissions'], -1, PREG_SPLIT_NO_EMPTY) |
244 |
); |
245 |
} |
246 |
} |
247 |
} |
248 |
// Update the users table with current ip and timestamp
|
249 |
$sRemoteAddress = @$_SERVER['REMOTE_ADDR'] ?: 'unknown'; |
250 |
$sql = 'UPDATE `'.TABLE_PREFIX.'users` ' |
251 |
. 'SET `login_when`='.time().', ' |
252 |
. '`login_ip`=\''.$sRemoteAddress.'\' ' |
253 |
. 'WHERE `user_id`=\''.$user_id.'\''; |
254 |
$this->oDb->query($sql); |
255 |
$bRetval = true; |
256 |
} |
257 |
} |
258 |
} |
259 |
// merge settings into $_SESSION and overwrite older one values
|
260 |
$_SESSION = array_merge($_SESSION, $aSettings); |
261 |
// Return if the user exists or not
|
262 |
return $bRetval; |
263 |
} |
264 |
|
265 |
// Increase the count for login attemps
|
266 |
protected function increase_attemps() |
267 |
{ |
268 |
$_SESSION['ATTEMPS'] = (isset($_SESSION['ATTEMPS']) ? $_SESSION['ATTEMPS']++ : 0); |
269 |
$this->display_login();
|
270 |
} |
271 |
|
272 |
|
273 |
public function getMessage ( ) { |
274 |
return $this->message; |
275 |
} |
276 |
|
277 |
// Function to set a "remembering" cookie for the user - removed
|
278 |
protected function remember($user_id) |
279 |
{ |
280 |
return true; |
281 |
} |
282 |
|
283 |
// Function to check if a user has been remembered - removed
|
284 |
protected function is_remembered() |
285 |
{ |
286 |
return false; |
287 |
} |
288 |
|
289 |
// Display the login screen
|
290 |
protected function display_login() { |
291 |
// Get language vars
|
292 |
global $MESSAGE; |
293 |
global $MENU; |
294 |
global $TEXT; |
295 |
|
296 |
$Trans = $GLOBALS['oTrans']; |
297 |
$ThemeName = (defined('DEFAULT_THEME')?DEFAULT_THEME:'DefaultTheme'); |
298 |
$Trans->enableAddon('templates\\'.$ThemeName); |
299 |
$aLang = $Trans->getLangArray(); |
300 |
// If attemps more than allowed, warn the user
|
301 |
if($this->get_session('ATTEMPS') > $this->max_attemps) { |
302 |
$this->warn();
|
303 |
} |
304 |
// Show the login form
|
305 |
if($this->frontend != true) { |
306 |
// require_once(WB_PATH.'/include/phplib/template.inc');
|
307 |
$aWebsiteTitle['value'] = WEBSITE_TITLE; |
308 |
$sql = 'SELECT `value` FROM `'.TABLE_PREFIX.'settings` ' |
309 |
. 'WHERE `name`=\'website_title\'';
|
310 |
if ($get_title = $this->oDb->query($sql)){ |
311 |
$aWebsiteTitle= $get_title->fetchRow( MYSQLI_ASSOC ); |
312 |
} |
313 |
// Setup template object, parse vars to it, then parse it
|
314 |
$template = new Template(dirname($this->correct_theme_source($this->template_file))); |
315 |
$template->set_file('page', $this->template_file); |
316 |
$template->set_block('page', 'mainBlock', 'main'); |
317 |
$template->set_var('DISPLAY_REMEMBER_ME', ($this->remember_me_option ? '' : 'display: none;')); |
318 |
|
319 |
$template->set_var(
|
320 |
array(
|
321 |
'ACTION_URL' => $this->login_url, |
322 |
'ATTEMPS' => $this->get_session('ATTEMPS'), |
323 |
'USERNAME' => $this->username, |
324 |
'USERNAME_FIELDNAME' => $this->username_fieldname, |
325 |
'PASSWORD_FIELDNAME' => $this->password_fieldname, |
326 |
'MESSAGE' => $this->message, |
327 |
'INTERFACE_DIR_URL' => ADMIN_URL.'/interface', |
328 |
'MAX_USERNAME_LEN' => $this->max_username_len, |
329 |
'MAX_PASSWORD_LEN' => $this->max_password_len, |
330 |
'ADMIN_URL' => ADMIN_URL, |
331 |
'WB_URL' => WB_URL, |
332 |
'URL' => $this->redirect_url, |
333 |
'THEME_URL' => THEME_URL, |
334 |
'VERSION' => VERSION, |
335 |
'REVISION' => REVISION, |
336 |
'LANGUAGE' => strtolower(LANGUAGE), |
337 |
'FORGOTTEN_DETAILS_APP' => $this->forgotten_details_app, |
338 |
'WEBSITE_TITLE' => ($aWebsiteTitle['value']), |
339 |
'TEXT_ADMINISTRATION' => $TEXT['ADMINISTRATION'], |
340 |
// 'TEXT_FORGOTTEN_DETAILS' => $Trans->TEXT_FORGOTTEN_DETAILS,
|
341 |
'TEXT_USERNAME' => $TEXT['USERNAME'], |
342 |
'TEXT_PASSWORD' => $TEXT['PASSWORD'], |
343 |
'TEXT_REMEMBER_ME' => $TEXT['REMEMBER_ME'], |
344 |
'TEXT_LOGIN' => $TEXT['LOGIN'], |
345 |
'TEXT_SAVE' => $TEXT['SAVE'], |
346 |
'TEXT_RESET' => $TEXT['RESET'], |
347 |
'TEXT_HOME' => $TEXT['HOME'], |
348 |
'PAGES_DIRECTORY' => PAGES_DIRECTORY, |
349 |
'SECTION_LOGIN' => $MENU['LOGIN'], |
350 |
'LOGIN_DISPLAY_HIDDEN' => !$this->is_authenticated() ? 'hidden' : '', |
351 |
'LOGIN_DISPLAY_NONE' => !$this->is_authenticated() ? 'none' : '', |
352 |
'LOGIN_LINK' => $_SERVER['SCRIPT_NAME'], |
353 |
'LOGIN_ICON' => 'login', |
354 |
'START_ICON' => 'blank', |
355 |
'URL_HELP' => 'http://wiki.websitebaker.org/', |
356 |
) |
357 |
); |
358 |
$template->set_var($aLang); |
359 |
$template->set_var('CHARSET', (defined('DEFAULT_CHARSET') ? DEFAULT_CHARSET : 'utf-8')); |
360 |
$template->parse('main', 'mainBlock', false); |
361 |
$template->pparse('output', 'page'); |
362 |
} |
363 |
} |
364 |
|
365 |
// sanities the REMEMBER_KEY cookie to avoid SQL injection
|
366 |
protected function get_safe_remember_key() |
367 |
{ |
368 |
$iMatches = 0; |
369 |
if (isset($_COOKIE['REMEMBER_KEY'])) { |
370 |
$sRetval = preg_replace('/^([0-9]{11})_([0-9a-f]{11})$/i', '\1\2', $_COOKIE['REMEMBER_KEY'], -1, $iMatches); |
371 |
} |
372 |
return ($iMatches ? $sRetval : ''); |
373 |
} |
374 |
|
375 |
// Warn user that they have had to many login attemps
|
376 |
protected function warn() |
377 |
{ |
378 |
// header('Location: '.$this->warning_url);
|
379 |
$this->send_header($this->warning_url); |
380 |
exit;
|
381 |
} |
382 |
|
383 |
} |