These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /*************************************************************************** |
||
3 | * for license information see LICENSE.md |
||
4 | * This class provides access to the login user data. Informations are |
||
5 | * stored in a cookie. |
||
6 | * Methods: |
||
7 | * verify() validate the login-session (automatically invoked) |
||
8 | * try_login() try to login with the given user/password |
||
9 | * logout() logout the user |
||
10 | * Properties: |
||
11 | * userid Integer 0 if no login, userid otherwise |
||
12 | * username String username or '' |
||
13 | * !! See also lib/login.class.php. !! |
||
14 | ***************************************************************************/ |
||
15 | |||
16 | use OcLegacy\Util\PasswordCrypt; |
||
17 | |||
18 | define('LOGIN_UNKNOWN_ERROR', -1); // unknown error occurred |
||
19 | define('LOGIN_OK', 0); // login succeeded |
||
20 | define('LOGIN_BADUSERPW', 1); // bad username or password |
||
21 | define('LOGIN_TOOMUCHLOGINS', 2); // too many logins in short time |
||
22 | define('LOGIN_USERNOTACTIVE', 3); // the userAccount locked |
||
23 | define('LOGIN_EMPTY_USERPASSWORD', 4); // given username/password was empty |
||
24 | define('LOGIN_LOGOUT_OK', 5); // logout was successful |
||
25 | |||
26 | // login times in seconds |
||
27 | define('LOGIN_TIME', 60 * 60); |
||
28 | define('LOGIN_TIME_PERMANENT', 90 * 24 * 60 * 60); |
||
29 | |||
30 | $login = new login(); |
||
31 | |||
32 | class login |
||
33 | { |
||
34 | /** |
||
35 | * @var int |
||
36 | */ |
||
37 | public $userid = 0; |
||
38 | /** |
||
39 | * @var mixed|string |
||
40 | */ |
||
41 | public $username = ''; |
||
42 | /** |
||
43 | * @var string |
||
44 | */ |
||
45 | public $lastlogin = ''; |
||
46 | /** |
||
47 | * @var bool |
||
48 | */ |
||
49 | public $permanent = false; |
||
50 | /** |
||
51 | * @var mixed|string |
||
52 | */ |
||
53 | public $sessionid = ''; |
||
54 | /** |
||
55 | * @var bool |
||
56 | */ |
||
57 | public $verified = false; |
||
58 | /** |
||
59 | * @var int |
||
60 | */ |
||
61 | public $admin = 0; |
||
62 | |||
63 | /** |
||
64 | * login constructor. |
||
65 | */ |
||
66 | View Code Duplication | public function __construct() |
|
67 | { |
||
68 | global $cookie; |
||
69 | |||
70 | // TODO good input evaluation |
||
71 | if ($cookie->is_set('userid') && $cookie->is_set('username')) { |
||
72 | $this->userid = (int) $cookie->get('userid'); |
||
73 | $this->username = $cookie->get('username'); |
||
74 | $this->permanent = (($cookie->get('permanent') + 0) == 1); |
||
75 | $this->lastlogin = $cookie->get('lastlogin'); |
||
76 | $this->sessionid = $cookie->get('sessionid'); |
||
77 | // $this->admin = $cookie->get('admin')+0; nonsense |
||
78 | $this->verified = false; |
||
79 | |||
80 | $this->verify(); |
||
81 | } else { |
||
82 | $this->pClear(); |
||
83 | } |
||
84 | } |
||
85 | |||
86 | View Code Duplication | public function pClear() |
|
87 | { |
||
88 | // set to no valid login |
||
89 | $this->userid = 0; |
||
90 | $this->username = ''; |
||
91 | $this->permanent = false; |
||
92 | $this->lastlogin = ''; |
||
93 | $this->sessionid = ''; |
||
94 | $this->admin = 0; |
||
95 | $this->verified = true; |
||
96 | |||
97 | $this->pStoreCookie(); |
||
98 | } |
||
99 | |||
100 | View Code Duplication | public function pStoreCookie() |
|
0 ignored issues
–
show
|
|||
101 | { |
||
102 | global $cookie; |
||
103 | $cookie->set('userid', (int) $this->userid); |
||
104 | $cookie->set('username', $this->username); |
||
105 | $cookie->set('permanent', ($this->permanent === true ? 1 : 0)); |
||
106 | $cookie->set('lastlogin', $this->lastlogin); |
||
107 | $cookie->set('sessionid', $this->sessionid); |
||
108 | } |
||
109 | |||
110 | /** |
||
111 | */ |
||
112 | public function verify() |
||
113 | { |
||
114 | global $opt; |
||
115 | |||
116 | if ($this->verified == true) { |
||
117 | return; |
||
118 | } |
||
119 | |||
120 | if ($this->userid == 0) { |
||
121 | $this->pClear(); |
||
122 | |||
123 | return; |
||
124 | } |
||
125 | |||
126 | if ($this->checkLoginsCount() === false) { |
||
127 | $this->pClear(); |
||
128 | |||
129 | return; |
||
130 | } |
||
131 | |||
132 | $min_lastlogin = date('Y-m-d H:i:s', time() - LOGIN_TIME); |
||
133 | $min_lastlogin_permanent = date('Y-m-d H:i:s', time() - LOGIN_TIME_PERMANENT); |
||
134 | |||
135 | $rs = sqlf( |
||
136 | " |
||
137 | SELECT |
||
138 | `sys_sessions`.`last_login`, |
||
139 | `user`.`admin`, |
||
140 | `user`.`username` |
||
141 | FROM &db.`sys_sessions`, &db.`user` |
||
142 | WHERE `sys_sessions`.`user_id`=`user`.`user_id` |
||
143 | AND `user`.`is_active_flag`= 1 |
||
144 | AND `sys_sessions`.`uuid`='&1' |
||
145 | AND `sys_sessions`.`user_id`='&2' |
||
146 | AND |
||
147 | ( |
||
148 | (`sys_sessions`.`permanent`=1 |
||
149 | AND `sys_sessions`.`last_login`>'&3') |
||
150 | OR |
||
151 | (`sys_sessions`.`permanent`=0 AND `sys_sessions`.`last_login`>'&4') |
||
152 | )", |
||
153 | $this->sessionid, |
||
154 | $this->userid, |
||
155 | $min_lastlogin_permanent, |
||
156 | $min_lastlogin |
||
157 | ); |
||
158 | |||
159 | // sys_session.last_login controls the automatic logout of users at the OC website. |
||
160 | // user.last_login gives the overall last login date, including OKAPI logins. |
||
161 | |||
162 | if ($rUser = sql_fetch_assoc($rs)) { |
||
163 | View Code Duplication | if ((($this->permanent == true) && (strtotime($rUser['last_login']) + LOGIN_TIME_PERMANENT / 2 < time())) || |
|
164 | (($this->permanent == false) && (strtotime($rUser['last_login']) + LOGIN_TIME / 2 < time())) |
||
165 | ) { |
||
166 | sqlf( |
||
167 | "UPDATE `sys_sessions` SET `sys_sessions`.`last_login`=NOW() |
||
168 | WHERE `sys_sessions`.`uuid`='&1' AND `sys_sessions`.`user_id`='&2'", |
||
169 | $this->sessionid, |
||
170 | $this->userid |
||
171 | ); |
||
172 | $rUser['last_login'] = date('Y-m-d H:i:s'); |
||
173 | } |
||
174 | |||
175 | if (isset($opt['template']['locale'])) { |
||
176 | sqlf( |
||
177 | "UPDATE `user` SET `last_login`=NOW(), `language`='&2', `language_guessed`=0, `domain`='&3' |
||
178 | WHERE `user_id`='&1'", |
||
179 | $this->userid, |
||
180 | $opt['template']['locale'], |
||
181 | $opt['page']['domain'] |
||
182 | ); |
||
183 | } else { |
||
184 | sqlf("UPDATE `user` SET `last_login`=NOW() WHERE `user_id`='&1'", $this->userid); |
||
185 | } |
||
186 | |||
187 | $this->lastlogin = $rUser['last_login']; |
||
188 | $this->username = $rUser['username']; |
||
189 | $this->admin = $rUser['admin']; |
||
190 | $this->verified = true; |
||
191 | } else { |
||
192 | // prevent brute force |
||
193 | sql("INSERT INTO `sys_logins` (`remote_addr`, `success`) VALUES ('&1', 0)", $_SERVER['REMOTE_ADDR']); |
||
194 | |||
195 | $this->pClear(); |
||
196 | } |
||
197 | sql_free_result($rs); |
||
198 | |||
199 | $this->pStoreCookie(); |
||
200 | } |
||
201 | |||
202 | /** |
||
203 | * @param $user |
||
204 | * @param $password |
||
205 | * @param $permanent |
||
206 | * @return int |
||
207 | */ |
||
208 | public function try_login($user, $password, $permanent) |
||
209 | { |
||
210 | if ($password == '') { |
||
211 | return LOGIN_EMPTY_USERPASSWORD; |
||
212 | } |
||
213 | |||
214 | $encryptedPassword = PasswordCrypt::encryptPassword($password); |
||
215 | |||
216 | return $this->try_login_encrypted($user, $encryptedPassword, $permanent); |
||
217 | } |
||
218 | |||
219 | /** |
||
220 | * @return bool |
||
221 | */ |
||
222 | public function checkLoginsCount() |
||
223 | { |
||
224 | global $opt; |
||
225 | |||
226 | // cleanup old entries |
||
227 | // (execute only every 50 search calls) |
||
228 | View Code Duplication | if (mt_rand(1, 50) === 1) { |
|
229 | sqlf("DELETE FROM `sys_logins` WHERE `date_created`<'&1'", date('Y-m-d H:i:s', time() - 3600)); |
||
230 | } |
||
231 | |||
232 | // check the number of logins in the last hour ... |
||
233 | $loginAttemptsCount = sqlf_value( |
||
234 | " |
||
235 | SELECT COUNT(*) `count` |
||
236 | FROM `sys_logins` |
||
237 | WHERE `remote_addr`='&1' |
||
238 | AND `date_created`>'&2'", |
||
239 | 0, |
||
240 | $_SERVER['REMOTE_ADDR'], |
||
241 | date('Y-m-d H:i:s', time() - 3600) |
||
242 | ); |
||
243 | |||
244 | return !($loginAttemptsCount > $opt['page']['max_logins_per_hour']); |
||
245 | } |
||
246 | |||
247 | /** |
||
248 | * @param $user |
||
249 | * @param $encryptedPassword |
||
250 | * @param $permanent |
||
251 | * @return int |
||
252 | */ |
||
253 | public function try_login_encrypted($user, $encryptedPassword, $permanent) |
||
254 | { |
||
255 | $this->pClear(); |
||
256 | |||
257 | if ($user == '' || $encryptedPassword == '') { |
||
258 | return LOGIN_EMPTY_USERPASSWORD; |
||
259 | } |
||
260 | |||
261 | if ($this->checkLoginsCount() == false) { |
||
262 | return LOGIN_TOOMUCHLOGINS; |
||
263 | } |
||
264 | |||
265 | // delete old sessions |
||
266 | $min_lastlogin_permanent = date('Y-m-d H:i:s', time() - LOGIN_TIME_PERMANENT); |
||
267 | sqlf("DELETE FROM `sys_sessions` WHERE `last_login`<'&1'", $min_lastlogin_permanent); |
||
268 | |||
269 | // compare $user with email and username, if both matches use email |
||
270 | $rsUser = sqlf( |
||
271 | "SELECT `user_id`, `username`, 2 AS `prio`, `is_active_flag`, `permanent_login_flag`, `admin` |
||
272 | FROM `user` WHERE `username`='&1' AND `password`='&2' |
||
273 | UNION |
||
274 | SELECT `user_id`, `username`, 1 AS `prio`, `is_active_flag`, `permanent_login_flag`, `admin` |
||
275 | FROM `user`WHERE `email`='&1' AND `password`='&2' ORDER BY `prio` ASC LIMIT 1", |
||
276 | $user, |
||
277 | $encryptedPassword |
||
278 | ); |
||
279 | $rUser = sql_fetch_assoc($rsUser); |
||
280 | sql_free_result($rsUser); |
||
281 | |||
282 | if ($permanent == null) { |
||
283 | $permanent = ($rUser['permanent_login_flag'] == 1); |
||
284 | } |
||
285 | |||
286 | if ($rUser) { |
||
287 | // ok, there is a valid login |
||
288 | if ($rUser['is_active_flag'] != 0) { |
||
289 | // begin session |
||
290 | $uuid = self::create_sessionid(); |
||
291 | sqlf( |
||
292 | "INSERT INTO `sys_sessions` (`uuid`, `user_id`, `permanent`) |
||
293 | VALUES ('&1', '&2', '&3')", |
||
294 | $uuid, |
||
295 | $rUser['user_id'], |
||
296 | ($permanent != false ? 1 : 0) |
||
297 | ); |
||
298 | $this->userid = (int) $rUser['user_id']; |
||
299 | $this->username = $rUser['username']; |
||
300 | $this->permanent = $permanent; |
||
301 | $this->lastlogin = date('Y-m-d H:i:s'); |
||
302 | $this->sessionid = $uuid; |
||
303 | $this->admin = $rUser['admin']; |
||
304 | $this->verified = true; |
||
305 | |||
306 | $retval = LOGIN_OK; |
||
307 | } else { |
||
308 | $retval = LOGIN_USERNOTACTIVE; |
||
309 | } |
||
310 | } else { |
||
311 | // sorry, bad login |
||
312 | $retval = LOGIN_BADUSERPW; |
||
313 | } |
||
314 | |||
315 | sqlf( |
||
316 | "INSERT INTO `sys_logins` (`remote_addr`, `success`) VALUES ('&1', '&2')", |
||
317 | $_SERVER['REMOTE_ADDR'], |
||
318 | ($rUser === false ? 0 : 1) |
||
319 | ); |
||
320 | |||
321 | // store to cookie |
||
322 | $this->pStoreCookie(); |
||
323 | |||
324 | return $retval; |
||
325 | } |
||
326 | |||
327 | /** |
||
328 | * login for cronjobs, command line tools ... |
||
329 | * |
||
330 | * @param $username |
||
331 | * @return bool |
||
332 | */ |
||
333 | public function system_login($username) |
||
334 | { |
||
335 | $this->pClear(); |
||
336 | if ($username != '') { |
||
337 | $rs = sql( |
||
338 | "SELECT `user_id`,`username`,`admin` FROM `user` |
||
339 | WHERE `username`='&1' AND `is_active_flag`", |
||
340 | $username |
||
341 | ); |
||
342 | if ($rUser = sql_fetch_assoc($rs)) { |
||
343 | $this->username = $rUser['username']; |
||
344 | $this->userid = (int) $rUser['user_id']; |
||
345 | $this->admin = $rUser['admin']; |
||
346 | $this->verified = true; |
||
347 | sqlf("UPDATE `user` SET `user`.`last_login`=NOW() WHERE `user`.`user_id`='&1'", $this->userid); |
||
348 | } |
||
349 | sql_free_result($rs); |
||
350 | } |
||
351 | |||
352 | return ($this->userid > 0); |
||
353 | } |
||
354 | |||
355 | /** |
||
356 | * @return string |
||
357 | */ |
||
358 | private static function create_sessionid() |
||
359 | { |
||
360 | return sprintf( |
||
361 | '%04x%04x-%04x-%04x-%04x-%04x%04x%04x', |
||
362 | mt_rand(0, 0xffff), |
||
363 | mt_rand(0, 0xffff), |
||
364 | mt_rand(0, 0xffff), |
||
365 | mt_rand(0, 0xffff), |
||
366 | mt_rand(0, 0xffff), |
||
367 | mt_rand(0, 0xffff), |
||
368 | mt_rand(0, 0xffff), |
||
369 | mt_rand(0, 0xffff) |
||
370 | ); |
||
371 | } |
||
372 | |||
373 | /** |
||
374 | * @return mixed|string |
||
375 | */ |
||
376 | public function getUserCountry() |
||
377 | { |
||
378 | global $opt, $cookie; |
||
379 | |||
380 | // language specified in cookie? |
||
381 | View Code Duplication | if ($cookie->is_set('usercountry')) { |
|
382 | $sCountry = $cookie->get('usercountry', null); |
||
383 | if ($sCountry != null) { |
||
384 | return $sCountry; |
||
385 | } |
||
386 | } |
||
387 | |||
388 | |||
389 | |||
390 | // user specified a country? |
||
391 | if ($this->userid != 0) { |
||
392 | $sCountry = sql_value("SELECT `country` FROM `user` WHERE `user_id`='&1'", null, $this->userid); |
||
393 | if ($sCountry != null) { |
||
394 | return $sCountry; |
||
395 | } |
||
396 | } |
||
397 | |||
398 | // default country of this language |
||
399 | // |
||
400 | // disabled: produces unexpected results on multi-domains without translation, |
||
401 | // and will confusingly switch country when switching language -- following 3.9.2015 |
||
402 | // |
||
403 | // if (isset($opt['locale'][$opt['template']['locale']]['country'])) |
||
404 | // return $opt['locale'][$opt['template']['locale']]['country']; |
||
405 | |||
406 | // default country of installation (or domain) |
||
407 | return $opt['template']['default']['country']; |
||
408 | } |
||
409 | |||
410 | public function logout() |
||
411 | { |
||
412 | if ($this->userid != 0) { |
||
413 | sqlf("DELETE FROM `sys_sessions` WHERE `uuid`='&1' AND `user_id`='&2'", $this->sessionid, $this->userid); |
||
414 | } |
||
415 | |||
416 | $this->pClear(); |
||
417 | } |
||
418 | |||
419 | /** |
||
420 | * @param int|bool $privilege |
||
421 | * @return bool |
||
422 | */ |
||
423 | View Code Duplication | public function hasAdminPriv($privilege = false) |
|
424 | { |
||
425 | if ($privilege === false) { |
||
426 | return $this->admin != 0; |
||
427 | } |
||
428 | |||
429 | return ($this->admin & $privilege) == $privilege; |
||
430 | } |
||
431 | |||
432 | /** |
||
433 | * @return bool |
||
434 | */ |
||
435 | public function listingAdmin() |
||
436 | { |
||
437 | global $opt; |
||
438 | |||
439 | return $this->hasAdminPriv(ADMIN_LISTING) && $opt['logic']['admin']['enable_listing_admins']; |
||
440 | } |
||
441 | |||
442 | /** |
||
443 | * @return bool |
||
444 | */ |
||
445 | public function logged_in() |
||
446 | { |
||
447 | return $this->userid > 0; |
||
448 | } |
||
449 | } |
||
450 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.