source: extensions/Password_Policy/include/functions.inc.php @ 27179

Last change on this file since 27179 was 27179, checked in by Eric, 10 years ago

Piwigo 2.6 compatibility:
Users management (users display, password renewal and unlocking accounts) recoded in plugin's admin panel

File size: 17.9 KB
Line 
1<?php
2
3load_language('plugin.lang', PP_PATH);
4
5/**
6 * Triggered on get_admin_plugin_menu_links
7 *
8 * Plugin's administration menu
9 */
10function PP_admin_menu($menu)
11{
12// +-----------------------------------------------------------------------+
13// |                      Getting plugin name                              |
14// +-----------------------------------------------------------------------+
15  $plugin =  PPInfos(PP_PATH);
16  $name = $plugin['name'];
17 
18  array_push($menu,
19    array(
20                'NAME' => $name,
21                'URL' => get_root_url().'admin.php?page=plugin-'.basename(PP_PATH)
22    )
23  );
24
25  return $menu;
26}
27
28
29/**
30 * Triggered on loc_begin_index
31 *
32 * Perform user logout after registration if account locked and redirection to profile page is password renewal is set
33 */
34function PP_Init()
35{
36  global $conf, $user;
37
38  include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
39
40  $conf_PP = unserialize($conf['PasswordPolicy']);
41
42  // Perfoming redirection for locked accounts
43  // -----------------------------------------
44  if (!is_a_guest() and $user['username'] != "16" and $user['username'] != "18")
45  {
46    // Perform user logout if user account is locked
47    if (
48          (isset($conf_PP['LOGFAILBLOCK']) and $conf_PP['LOGFAILBLOCK'] == 'true')
49          and PP_UsrBlock_Verif($user['username'])
50          //and (isset($userlocked) and $userlocked == 'true')
51          and !is_admin()
52          and !is_webmaster())
53    {
54      invalidate_user_cache();
55      logout_user();
56      if ($conf['guest_access'])
57      {
58        redirect(make_index_url().'?PP_msg=locked', 0);
59      }
60      else
61      {
62        redirect(get_root_url().'identification.php?PP_msg=locked' , 0);
63      }
64    }
65  }
66
67  // Performing redirection to profile page for password reset
68  // ---------------------------------------------------------
69  if ((isset($conf_PP['PWDRESET']) and $conf_PP['PWDRESET'] == 'true'))
70  {
71    $query ='
72SELECT user_id, status
73FROM '.USER_INFOS_TABLE.'
74WHERE user_id = '.$user['id'].'
75;';
76    $data = pwg_db_fetch_assoc(pwg_query($query));
77
78    if ($data['status'] <> "webmaster" and $data['status'] <> "generic") // Exclusion of specific accounts
79    {
80      if (PP_check_pwdreset($user['id']))
81      {
82        redirect(PHPWG_ROOT_PATH.'profile.php');
83      }
84    }
85  }
86
87
88}
89
90
91/**
92 * Triggered on init
93 *
94 * Displays messages on index page
95 */
96function PP_InitPage()
97{
98  global $conf, $template, $page, $lang, $errors;
99
100  load_language('plugin.lang', PP_PATH);
101
102  if( isset($_GET['PP_msg']))
103  {
104    PP_DisplayMsg();
105  }
106}
107
108
109/**
110 * Triggered on init
111 *
112 * Display a message according to $_GET['PP_msg']
113 */
114function PP_DisplayMsg()
115{
116  if (isset($_GET['PP_msg']))
117  {
118    global $user, $lang, $conf, $page;
119    $conf_PP = unserialize($conf['PasswordPolicy']);
120
121    // User account locked after x failed attempts
122    if (isset($conf_PP['USRLOCKEDTXT']) and !empty($conf_PP['USRLOCKEDTXT']) and $_GET['PP_msg']=="locked")
123    {
124      if (function_exists('get_user_language_desc'))// Extended Description [lang] feature
125      {
126        $custom_text = get_user_language_desc($conf_PP['USRLOCKEDTXT']);
127      }
128      else $custom_text = l10n($conf_PP['USRLOCKEDTXT']);
129
130      $page["errors"][]=$custom_text;
131    }
132  }
133}
134
135
136/**
137 * Triggered on login_failure in main.inc.php
138 * Count of login failures and lock account after x attempt
139 *
140 */
141function PP_log_fail($username)
142{
143  global $conf, $user;
144
145  include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
146
147  $conf_PP = unserialize($conf['PasswordPolicy']);
148
149  if (
150        (isset($conf_PP['NBLOGFAIL']) and $conf_PP['NBLOGFAIL'] <> 0)
151    and (isset($conf_PP['LOGFAILBLOCK']) and $conf_PP['LOGFAILBLOCK'] == 'true')
152    and !is_admin()
153    and !is_webmaster()
154    )
155  {
156    // If login failure then increments loginfailcount value in database
157    $query = '
158UPDATE '.USERS_TABLE.'
159SET PP_loginfailcount = PP_loginfailcount+1
160WHERE username = "'.stripslashes($username).'"
161LIMIT 1
162;';
163    pwg_query($query);
164
165    $query = '
166SELECT PP_loginfailcount
167FROM '.USERS_TABLE.'
168WHERE username = "'.stripslashes($username).'"
169;';
170
171    $datas = pwg_db_fetch_assoc(pwg_query($query));
172
173    // If number of failed logon exeeds $conf_PP['NBLOGFAIL'], set the account as locked
174    if (isset($datas['PP_loginfailcount']) and $datas['PP_loginfailcount'] >= $conf_PP['NBLOGFAIL'])
175    {
176      $query = '
177UPDATE '.USERS_TABLE.'
178SET PP_lock = "true"
179WHERE username = "'.stripslashes($username).'"
180LIMIT 1
181;';
182      pwg_query($query);
183
184    }
185  }
186}
187
188
189/**
190 * PP_user_list_pwdreset
191 * Adds a new feature in user_list to allow password reset for selected users by admin
192 *
193 */
194function PP_user_list_pwdreset($visible_user_list)
195{
196  global $template;
197 
198  load_language('plugin.lang', PP_PATH);
199
200  $user_ids = array();
201
202  foreach ($visible_user_list as $i => $user)
203  {
204    $user_ids[$i] = $user['id'];
205  }
206
207  $user_nums = array_flip($user_ids);
208
209  // Query to get information in database
210  // ------------------------------------
211  if (!empty($user_ids))
212  {
213    $query = '
214SELECT DISTINCT id, PP_pwdreset
215  FROM '.USERS_TABLE.'
216  WHERE id IN ('.implode(',', $user_ids).')
217;';
218    $result = pwg_query($query);
219
220    while ($row = pwg_db_fetch_assoc($result))
221    {
222      if ($row['PP_pwdreset'] == 'false')
223      {
224        $pwdreset = l10n('PP_PwdReset_Done');
225      }
226      else if ($row['PP_pwdreset'] == 'true')
227      {
228        $pwdreset = l10n('PP_PwdReset_Todo');
229      }
230      else $pwdreset = l10n('PP_PwdReset_NA');
231
232                  $visible_user_list[$user_nums[$row['id']]]['plugin_columns'][] = $pwdreset; // Shows users password state in user_list
233    }
234  }
235  return $visible_user_list;
236}
237
238
239/**
240 * PP_user_list_locked
241 * Adds a new feature in user_list to allow user unlocking by admin
242 *
243 */
244function PP_user_list_locked($visible_user_list)
245{
246  global $template;
247 
248  load_language('plugin.lang', PP_PATH);
249
250  $template->append('plugin_user_list_column_titles', l10n('PP_LockedUsers'));
251
252  $user_ids = array();
253
254  foreach ($visible_user_list as $i => $user)
255  {
256    $user_ids[$i] = $user['id'];
257  }
258
259  $user_nums = array_flip($user_ids);
260
261  // Query to get information in database
262  // ------------------------------------
263  if (!empty($user_ids))
264  {
265    $query = '
266SELECT DISTINCT id, PP_lock
267  FROM '.USERS_TABLE.'
268  WHERE id IN ('.implode(',', $user_ids).')
269;';
270    $result = pwg_query($query);
271
272    while ($row = pwg_db_fetch_assoc($result))
273    {
274      if ($row['PP_lock'] == 'false')
275      {
276        $LockedUser = '<img src="'.PP_PATH.'admin/template/icons/nolock.png" title="'.l10n('PP_User Not Locked').'" alt="'.l10n('PP_User Not Locked').'"/>';
277      }
278      else if ($row['PP_lock'] == 'true')
279      {
280        $LockedUser = '<img src="'.PP_PATH.'admin/template/icons/lock.png" title="'.l10n('PP_User Locked').'" alt="'.l10n('PP_User Locked').'"/>';
281      }
282      else $LockedUser = '<img src="'.PP_PATH.'admin/template/icons/nolock.png" title="'.l10n('PP_User Not Locked').'" alt="'.l10n('PP_User Not Locked').'"/>';
283
284                  $visible_user_list[$user_nums[$row['id']]]['plugin_columns'][] = $LockedUser; // Shows users account state in user_list
285    }
286  }
287  return $visible_user_list;
288}
289
290
291/**
292 * Triggered on register_user_check
293 *
294 * Additional controls on user registration check
295 */
296function PP_RegistrationCheck($errors, $user)
297{
298  global $conf;
299
300  // Exclusion of Adult_Content users
301  // --------------------------------
302  if ($user['username'] != "16" and $user['username'] != "18")
303  {
304    load_language('plugin.lang', PP_PATH);
305
306    $PasswordCheck = 0;
307
308    $conf_PP = unserialize($conf['PasswordPolicy']);
309
310    // Password enforcement control
311    // ----------------------------
312    if (isset($conf_PP['PASSWORDENF']) and $conf_PP['PASSWORDENF'] == 'true' and !empty($conf_PP['PASSWORD_SCORE']))
313    {
314      if (!empty($user['password']) and !is_admin())
315      {
316        $PasswordCheck = PP_testpassword($user['password']);
317
318        if ($PasswordCheck < $conf_PP['PASSWORD_SCORE'])
319        {
320          $message = get_l10n_args('PP_Error_Password_Need_Enforcement_%s', $PasswordCheck);
321          $lang['reg_err_pass'] = l10n_args($message).$conf_PP['PASSWORD_SCORE'];
322          array_push($errors, $lang['reg_err_pass']);
323        }
324      }
325      else if (!empty($user['password']) and is_admin() and isset($conf_PP['ADMINPASSWENF']) and $conf_PP['ADMINPASSWENF'] == 'true')
326      {
327        $PasswordCheck = PP_testpassword($user['password']);
328
329        if ($PasswordCheck < $conf_PP['PASSWORD_SCORE'])
330        {
331          $message = get_l10n_args('PP_Error_Password_Need_Enforcement_%s', $PasswordCheck);
332          $lang['reg_err_pass'] = l10n_args($message).$conf_PP['PASSWORD_SCORE'];
333          array_push($errors, $lang['reg_err_pass']);
334        }
335      }
336    }
337    return $errors;
338  }
339}
340
341
342/**
343 * Triggered on loc_begin_profile
344 */
345function PP_Profile_Init()
346{
347  global $conf, $user, $template;
348 
349  load_language('plugin.lang', PP_PATH);
350
351  $conf_PP = unserialize($conf['PasswordPolicy']);
352
353  // Special message display for password reset
354  // ------------------------------------------
355  if ((isset($conf_PP['PWDRESET']) and $conf_PP['PWDRESET'] == 'true'))
356  {
357    if (PP_check_pwdreset($user['id']))
358    {
359      $template->append('errors', l10n('PP_Password_Reset_Msg'));
360    }
361  }
362
363  // Controls on profile page submission
364  // -----------------------------------
365  if (isset($_POST['validate']) and !is_admin())
366  {
367    // Password reset control
368    // ----------------------
369    if (isset($conf_PP['PWDRESET']) and $conf_PP['PWDRESET'] == 'true' and PP_check_pwdreset($user['id']))
370    {
371      // if password not changed then pwdreset field = true else pwdreset field = false
372      // ------------------------------------------------------------------------------
373      if (!empty($_POST['use_new_pwd']))
374      {
375        $query = '
376UPDATE '.USERS_TABLE.'
377SET PP_pwdreset = "false"
378WHERE id = '.$user['id'].'
379LIMIT 1
380;';
381        pwg_query($query);
382      }
383    }
384
385    if (!empty($_POST['use_new_pwd']))
386    {
387      // Password enforcement control
388      // ----------------------------
389      if (isset($conf_PP['PASSWORDENF']) and $conf_PP['PASSWORDENF'] == 'true' and !empty($conf_PP['PASSWORD_SCORE']))
390      {
391        $PasswordCheck = PP_testpassword($_POST['use_new_pwd']);
392
393        if ($PasswordCheck < $conf_PP['PASSWORD_SCORE'])
394        {
395          $message = get_l10n_args('PP_Error_Password_Need_Enforcement_%s', $PasswordCheck);
396          $template->append('errors', l10n_args($message).$conf_PP['PASSWORD_SCORE']);
397          unset($_POST['use_new_pwd']);
398          unset($_POST['validate']);
399        }
400      }
401    }
402  }
403}
404
405
406/**
407 * PP_Set_PwdReset
408 * Action in user_list to set a password reset for a user
409 */
410function PP_Set_PwdReset($uid)
411{
412  $query ='
413UPDATE '.USERS_TABLE.'
414SET PP_pwdreset = "true"
415WHERE id = '.$uid.'
416LIMIT 1
417;';
418
419  pwg_query($query);
420}
421
422
423/**
424 * PP_check_pwdreset
425 * checks if a user id is registered as having already
426 * changed his password.
427 *
428 * @uid        : the user id
429 *
430 * @returns    : true or false whether the users has already changed his password
431 *
432 */
433function PP_check_pwdreset($uid)
434{
435  $query = '
436SELECT PP_pwdreset
437FROM '.USERS_TABLE.'
438WHERE id='.$uid.'
439;';
440
441  $result = pwg_db_fetch_assoc(pwg_query($query));
442
443  if($result['PP_pwdreset'] == 'true')
444  {
445    return true;
446  }
447  else return false; 
448}
449
450
451/**
452 * Returns a password's score for password complexity check
453 *
454 * @param : password filled by user
455 *
456 * @return : Score calculation
457 *
458 * Thanx to MathieuGut from http://m-gut.developpez.com
459 */
460function PP_testpassword($password) // $password given by user
461{
462
463  // Variables initiation
464  // --------------------
465  $points = 0;
466  $point_lowercase = 0;
467  $point_uppercase = 0;
468  $point_numbers = 0;
469  $point_characters = 0;
470
471  // Getting password lengh
472  // ----------------------
473  $length = strlen($password);
474
475  // Loop to read password characters
476  for($i = 0; $i < $length; $i++)
477  {
478    // Select each letters
479    // $i is 0 at first turn
480    // ---------------------
481    $letters = $password[$i];
482
483    if ($letters>='a' && $letters<='z')
484    {
485      // Adding 1 point to score for a lowercase
486      // ---------------------------------------
487                                $points = $points + 1;
488
489      // Adding bonus points for lowercase
490      // ---------------------------------
491                  $point_lowercase = 1;
492    }
493    else if ($letters>='A' && $letters <='Z')
494    {
495      // Adding 2 points to score for uppercase
496      // --------------------------------------
497      $points = $points + 2;
498
499      // Adding bonus points for uppercase
500      // ---------------------------------
501      $point_uppercase = 2;
502    }
503    else if ($letters>='0' && $letters<='9')
504    {
505      // Adding 3 points to score for numbers
506      // ------------------------------------
507      $points = $points + 3;
508
509      // Adding bonus points for numbers
510      // -------------------------------
511      $point_numbers = 3;
512    }
513    else
514    {
515      // Adding 5 points to score for special characters
516      // -----------------------------------------------
517      $points = $points + 5;
518               
519      // Adding bonus points for special characters
520      // ------------------------------------------
521      $point_characters = 5;
522    }
523  }
524
525  // Calculating the coefficient points/length
526  // -----------------------------------------
527  $step1 = $points / $length;
528
529  // Calculation of the diversity of character types...
530  // --------------------------------------------------
531  $step2 = $point_lowercase + $point_uppercase + $point_numbers + $point_characters;
532
533  // Multiplying the coefficient of diversity with that of the length
534  // ----------------------------------------------------------------
535  $score = $step1 * $step2;
536
537  // Multiplying the result by the length of the string
538  // --------------------------------------------------
539  $finalscore = $score * $length;
540
541  return $finalscore;
542}
543
544
545/**
546 * PP_UsrBlock_Verif
547 * Check if the user's account is locked
548 *
549 * @returns : True if account is locked else False
550 */
551function PP_UsrBlock_Verif($username)
552{
553  global $conf;
554
555  $query = '
556SELECT PP_Lock
557FROM '.USERS_TABLE.'
558WHERE username = "'.stripslashes($username).'"
559;';
560
561  $result = pwg_db_fetch_assoc(pwg_query($query));
562
563  if($result['PP_Lock'] == 'true')
564  {
565    return true;
566  }
567  else return false;
568}
569
570
571/**
572 * PP_unlock_user
573 * Action in user_list to unlock a user
574 */
575function PP_unlock_user($uid)
576{
577  // Reset PP_loginfailcount value to 0
578  $query ='
579UPDATE '.USERS_TABLE.'
580SET PP_loginfailcount = 0
581WHERE id = '.$uid.'
582LIMIT 1
583;';
584
585  pwg_query($query);
586 
587  // Set account as unlocked
588  $query ='
589UPDATE '.USERS_TABLE.'
590SET PP_lock = "false"
591WHERE id = '.$uid.'
592LIMIT 1
593;';
594
595  pwg_query($query);
596}
597
598
599/**
600 * Function called from PP_admin.php - Get all users to display the number of days since their last visit
601 *
602 * @return : List of users
603 *
604 */
605function pp_get_user_list()
606{
607  global $conf, $page;
608
609  $users = array();
610
611  // Search users with exclusion of Adult_Content generic users and guest user
612  // -------------------------------------------------------------------------
613  $query = '
614SELECT DISTINCT u.'.$conf['user_fields']['id'].' AS id,
615                u.'.$conf['user_fields']['username'].' AS username,
616                u.'.$conf['user_fields']['email'].' AS email,
617                ui.status
618FROM '.USERS_TABLE.' AS u
619  INNER JOIN '.USER_INFOS_TABLE.' AS ui
620    ON u.'.$conf['user_fields']['id'].' = ui.user_id
621WHERE u.username NOT LIKE "16"
622  AND u.username NOT LIKE "18"
623;';
624
625  $result = pwg_query($query);
626     
627  while ($row = pwg_db_fetch_assoc($result))
628  {
629    $user = $row;
630    array_push($users, $user);
631  }
632
633  $user_ids = array();
634  foreach ($users as $i => $user)
635  {
636    $user_ids[$i] = $user['id'];
637  }
638
639  return $users;
640}
641
642
643/**
644 * Function called from PP_admin.php to get the plugin version and name
645 *
646 * @param : plugin directory
647 *
648 * @return : plugin's version and name
649 *
650 */
651function PPInfos($dir)
652{
653  $path = $dir;
654
655  $plg_data = implode( '', file($path.'main.inc.php') );
656  if ( preg_match("|Plugin Name: (.*)|", $plg_data, $val) )
657  {
658    $plugin['name'] = trim( $val[1] );
659  }
660  if (preg_match("|Version: (.*)|", $plg_data, $val))
661  {
662    $plugin['version'] = trim($val[1]);
663  }
664  if ( preg_match("|Plugin URI: (.*)|", $plg_data, $val) )
665  {
666    $plugin['uri'] = trim($val[1]);
667  }
668  if ($desc = load_language('description.txt', $path.'/', array('return' => true)))
669  {
670    $plugin['description'] = trim($desc);
671  }
672  elseif ( preg_match("|Description: (.*)|", $plg_data, $val) )
673  {
674    $plugin['description'] = trim($val[1]);
675  }
676  if ( preg_match("|Author: (.*)|", $plg_data, $val) )
677  {
678    $plugin['author'] = trim($val[1]);
679  }
680  if ( preg_match("|Author URI: (.*)|", $plg_data, $val) )
681  {
682    $plugin['author uri'] = trim($val[1]);
683  }
684  if (!empty($plugin['uri']) and strpos($plugin['uri'] , 'extension_view.php?eid='))
685  {
686    list( , $extension) = explode('extension_view.php?eid=', $plugin['uri']);
687    if (is_numeric($extension)) $plugin['extension'] = $extension;
688  }
689// IMPORTANT SECURITY !
690// --------------------
691  $plugin = array_map('htmlspecialchars', $plugin);
692
693  return $plugin ;
694}
695
696
697/**
698 * Useful for debugging - 4 vars can be set
699 * Output result to log.txt file
700 *
701 */
702function PPLog($var1, $var2, $var3, $var4)
703{
704   $fo=fopen (PP_PATH.'log.txt','a') ;
705   fwrite($fo,"======================\n") ;
706   fwrite($fo,'le ' . date('D, d M Y H:i:s') . "\r\n");
707   fwrite($fo,$var1 ."\r\n") ;
708   fwrite($fo,$var2 ."\r\n") ;
709   fwrite($fo,$var3 ."\r\n") ;
710   fwrite($fo,$var4 ."\r\n") ;
711   fclose($fo) ;
712}
713?>
Note: See TracBrowser for help on using the repository browser.