Index: extensions/Password_Policy/admin.php
===================================================================
--- extensions/Password_Policy/admin.php	(revision 25028)
+++ extensions/Password_Policy/admin.php	(revision 25028)
@@ -0,0 +1,3 @@
+<?php
+  include(PP_PATH.'admin/PP_admin.php');
+?>
Index: extensions/Password_Policy/admin/PP_admin.php
===================================================================
--- extensions/Password_Policy/admin/PP_admin.php	(revision 25028)
+++ extensions/Password_Policy/admin/PP_admin.php	(revision 25028)
@@ -0,0 +1,105 @@
+<?php
+
+global $user, $lang, $conf, $errors;
+
+if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
+// +-----------------------------------------------------------------------+
+// | Check Access and exit when user status is not ok                      |
+// +-----------------------------------------------------------------------+
+check_status(ACCESS_ADMINISTRATOR);
+
+if (!defined('PP_PATH')) define('PP_PATH' , PHPWG_PLUGINS_PATH.basename(dirname(__FILE__)).'/');
+
+//ini_set('error_reporting', E_ALL);
+//ini_set('display_errors', true);
+
+include_once (PHPWG_ROOT_PATH.'/include/constants.php');
+
+load_language('plugin.lang', PP_PATH);
+
+
+// +-----------------------------------------------------------------------+
+// |                   Variables initialization                            |
+// +-----------------------------------------------------------------------+
+$page['global'] = array();
+$error = array();
+
+$PP_Password_Test_Score = 0;
+
+// +-----------------------------------------------------------------------+
+// |                      Getting plugin version                           |
+// +-----------------------------------------------------------------------+
+$plugin =  PPInfos(PP_PATH);
+$version = $plugin['version'];
+
+
+  if (isset($_POST['submit']) and isset($_POST['PP_Password_Enforced']) and isset($_POST['PP_AdminPassword_Enforced']) and isset($_POST['PP_PwdReset']))
+  {
+    // Save global PP configuration
+    // -----------------------------
+    $newconf_PP['PPVersion'] = $version;
+    $newconf_PP['PASSWORDENF'] = (isset($_POST['PP_Password_Enforced']) ? $_POST['PP_Password_Enforced'] : 'false');
+    $newconf_PP['PASSWORD_SCORE'] = (isset($_POST['PP_Password_Score']) ? $_POST['PP_Password_Score'] : '100');
+    $newconf_PP['ADMINPASSWENF'] = (isset($_POST['PP_AdminPassword_Enforced']) ? $_POST['PP_AdminPassword_Enforced'] : 'false');
+    $newconf_PP['PWDRESET'] = (isset($_POST['PP_PwdReset']) ? $_POST['PP_PwdReset'] : 'false');
+
+    $conf['PasswordPolicy'] = serialize($newconf_PP);
+
+    conf_update_param('PasswordPolicy', pwg_db_real_escape_string($conf['PasswordPolicy'])); 
+
+    array_push($page['infos'], l10n('PP_save_config'));
+  }
+
+  // Testing password enforcement
+  // ----------------------------
+  if (isset($_POST['PasswordTest']) and isset($_POST['PP_Password_Test']) and !empty($_POST['PP_Password_Test']))
+  {
+    $PP_Password_Test_Score = PP_testpassword($_POST['PP_Password_Test']);
+  }
+  else if (isset($_POST['PasswordTest']) and empty($_POST['PP_Password_Test']))
+  {
+    array_push($page['errors'], l10n('PP_reg_err_login3'));
+  }
+
+  $conf_PP = unserialize($conf['PasswordPolicy']);
+
+  // ------------------------------------------
+  // Template initialization for forms and data
+  // ------------------------------------------
+  $themeconf=$template->get_template_vars('themeconf');
+  $PP_theme=$themeconf['id'];
+
+  $template->assign(
+    array(
+            'PP_VERSION'                       => $version,
+            'PP_PATH'                          => PP_PATH,
+						'PP_PASSWORDENF_TRUE'              => $conf_PP['PASSWORDENF']=='true' ? 'checked="checked"' : '' ,
+						'PP_PASSWORDENF_FALSE'             => $conf_PP['PASSWORDENF']=='false' ? 'checked="checked"' : '' ,
+						'PP_PASSWORD_SCORE'                => $conf_PP['PASSWORD_SCORE'],
+            'PP_ADMINPASSWENF_TRUE'            => $conf_PP['ADMINPASSWENF']=='true' ? 'checked="checked"' : '' ,
+						'PP_ADMINPASSWENF_FALSE'           => $conf_PP['ADMINPASSWENF']=='false' ? 'checked="checked"' : '' ,
+            'PP_PWDRESET_TRUE'                 => $conf_PP['PWDRESET']=='true' ? 'checked="checked"' : '' ,
+            'PP_PWDRESET_FALSE'                => $conf_PP['PWDRESET']=='false' ? 'checked="checked"' : '' ,
+						'PP_PASSWORD_TEST_SCORE'           => $PP_Password_Test_Score,
+    )
+  );
+
+
+// +-----------------------------------------------------------------------+
+// |                             errors display                            |
+// +-----------------------------------------------------------------------+
+  if (isset ($errors) and count($errors) != 0)
+  {
+    $template->assign('errors',array());
+    foreach ($errors as $error)
+    {
+      array_push($page['errors'], $error);
+    }
+  }  
+
+// +-----------------------------------------------------------------------+
+// |                           templates display                           |
+// +-----------------------------------------------------------------------+
+  $template->set_filename('plugin_admin_content', dirname(__FILE__) . '/template/PP_admin.tpl');
+  $template->assign_var_from_handle('ADMIN_CONTENT', 'plugin_admin_content');
+?>
Index: extensions/Password_Policy/admin/index.php
===================================================================
--- extensions/Password_Policy/admin/index.php	(revision 25028)
+++ extensions/Password_Policy/admin/index.php	(revision 25028)
@@ -0,0 +1,33 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | PhpWebGallery - a PHP based picture gallery                           |
+// | Copyright (C) 2002-2003 Pierrick LE GALL - pierrick@phpwebgallery.net |
+// | Copyright (C) 2003-2007 PhpWebGallery Team - http://phpwebgallery.net |
+// +-----------------------------------------------------------------------+
+// | file          : $Id: index.php 1912 2007-03-16 06:30:07Z rub $
+// | last update   : $Date: 2007-03-16 07:30:07 +0100 (ven, 16 mar 2007) $
+// | last modifier : $Author: rub $
+// | revision      : $Revision: 1912 $
+// +-----------------------------------------------------------------------+
+// | This program is free software; you can redistribute it and/or modify  |
+// | it under the terms of the GNU General Public License as published by  |
+// | the Free Software Foundation                                          |
+// |                                                                       |
+// | This program 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      |
+// | General Public License for more details.                              |
+// |                                                                       |
+// | You should have received a copy of the GNU General Public License     |
+// | along with this program; if not, write to the Free Software           |
+// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
+// | USA.                                                                  |
+// +-----------------------------------------------------------------------+
+
+// Recursive call
+$url = '../';
+header( 'Request-URI: '.$url );
+header( 'Content-Location: '.$url );
+header( 'Location: '.$url );
+exit();
+?>
Index: extensions/Password_Policy/admin/template/PP_admin.tpl
===================================================================
--- extensions/Password_Policy/admin/template/PP_admin.tpl	(revision 25028)
+++ extensions/Password_Policy/admin/template/PP_admin.tpl	(revision 25028)
@@ -0,0 +1,85 @@
+{combine_script id='jquery' path='themes/default/js/jquery.min.js'}
+{combine_script id='jquery.cluetip' require='jquery' path='themes/default/js/plugins/jquery.cluetip.js'}
+
+{combine_css path= $PP_PATH|@cat:'admin/template/pp.css'}
+
+<script type="text/javascript">
+jQuery().ready(function()
+{ldelim}
+  jQuery('.cluetip').cluetip(
+  {ldelim}
+    width: 500,
+    splitTitle: '|'
+  {rdelim});
+{rdelim});
+</script>
+
+<div class="titrePage">
+  <h2>{'PP_Title_Tab'|@translate} {$PP_VERSION}<br/>{'PP_SubTitle1'|@translate}</h2>
+</div>
+
+<form method="post" action="" class="general">
+<fieldset>
+  <span class="cluetip" title="{'PP_Title1'|translate}|{'PP_restricTitle_d'|translate}">
+    {'PP_Title1'|@translate}
+  </span>
+
+  <ul>
+    <li>
+      <label class="cluetip" title="{'PP_Password_Enforced'|translate}|{'PP_passwTitle_d'|translate}">
+        {'PP_Password_Enforced'|@translate}
+      </label>
+
+      <label for="PP_Password_Enforced_false"><input id="PP_Password_Enforced_false" type="radio" value="false" {$PP_PASSWORDENF_FALSE} name="PP_Password_Enforced"/>
+        {'PP_Disable'|@translate}
+      </label>
+      <label for="PP_Password_Enforced_true"><input id="PP_Password_Enforced_true" type="radio" value="true" {$PP_PASSWORDENF_TRUE} name="PP_Password_Enforced"/>
+        {'PP_Password_Enforced_true'|@translate}&nbsp;
+        <input type="text" name="PP_Password_Score" value="{$PP_PASSWORD_SCORE}" size="5" style="text-align: center;"/>
+      </label>
+      <br />
+        {'PP_PasswordTest'|@translate}
+        <input class="cluetip" title="{'PP_passwtestTitle'|translate}|{'PP_passwtestTitle_d'|translate}" type="text" name="PP_Password_Test" value="{$PP_PASSWORD_TEST}" size="50" style="text-align: left;"/>
+        &nbsp;&nbsp;&nbsp;
+        <input class="submit" type="submit" value="{'PP_PasswordTest'|@translate}" name="PasswordTest"/>
+        &nbsp;&nbsp;&nbsp;{'PP_ScoreTest'|@translate}{$PP_PASSWORD_TEST_SCORE}
+      </li>
+
+      <ul>
+        <li>
+          <label class="cluetip" title="{'PP_AdminPassword_Enforced'|translate}|{'PP_passwadmTitle_d'|translate}">
+            {'PP_AdminPassword_Enforced'|@translate}
+          </label>
+
+          <label for="PP_AdminPassword_Enforced_false"><input id="PP_AdminPassword_Enforced_false" value="false" {$PP_ADMINPASSWENF_FALSE} name="PP_AdminPassword_Enforced" type="radio"/>
+            {'PP_Disable'|@translate}
+          </label>
+          <label for="PP_AdminPassword_Enforced_true"><input id="PP_AdminPassword_Enforced_true" value="true" {$PP_ADMINPASSWENF_TRUE} name="PP_AdminPassword_Enforced" type="radio"/>
+            {'PP_Enable'|@translate}
+          </label>            
+        </li>
+      </ul>
+
+      <li>
+        <label class="cluetip" title="{'PP_PwdReset'|translate}|{'PP_PwdResetTitle_d'|translate}">
+          {'PP_PwdReset'|@translate}
+        </label>
+
+        <label for="PP_PwdReset_false"><input id="PP_PwdReset_false" value="false" {$PP_PWDRESET_FALSE} name="PP_PwdReset" type="radio"/>
+          {'PP_Disable'|@translate}
+        </label>
+        <label for="PP_PwdReset_true"><input id="PP_PwdReset_true" value="true" {$PP_PWDRESET_TRUE} name="PP_PwdReset" type="radio"/>
+          {'PP_Enable'|@translate}
+        </label>
+      </li>
+    </ul>
+
+  <p>
+    <input class="submit" type="submit" value="{'PP_submit'|@translate}" name="submit" {$TAG_INPUT_ENABLED}/>
+  </p>
+</fieldset>
+</form>
+
+<fieldset>
+  {'PP_Support_txt'|@translate}
+</fieldset>
Index: extensions/Password_Policy/admin/template/index.php
===================================================================
--- extensions/Password_Policy/admin/template/index.php	(revision 25028)
+++ extensions/Password_Policy/admin/template/index.php	(revision 25028)
@@ -0,0 +1,33 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | PhpWebGallery - a PHP based picture gallery                           |
+// | Copyright (C) 2002-2003 Pierrick LE GALL - pierrick@phpwebgallery.net |
+// | Copyright (C) 2003-2007 PhpWebGallery Team - http://phpwebgallery.net |
+// +-----------------------------------------------------------------------+
+// | file          : $Id: index.php 1912 2007-03-16 06:30:07Z rub $
+// | last update   : $Date: 2007-03-16 07:30:07 +0100 (ven, 16 mar 2007) $
+// | last modifier : $Author: rub $
+// | revision      : $Revision: 1912 $
+// +-----------------------------------------------------------------------+
+// | This program is free software; you can redistribute it and/or modify  |
+// | it under the terms of the GNU General Public License as published by  |
+// | the Free Software Foundation                                          |
+// |                                                                       |
+// | This program 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      |
+// | General Public License for more details.                              |
+// |                                                                       |
+// | You should have received a copy of the GNU General Public License     |
+// | along with this program; if not, write to the Free Software           |
+// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
+// | USA.                                                                  |
+// +-----------------------------------------------------------------------+
+
+// Recursive call
+$url = '../';
+header( 'Request-URI: '.$url );
+header( 'Content-Location: '.$url );
+header( 'Location: '.$url );
+exit();
+?>
Index: extensions/Password_Policy/admin/template/pp.css
===================================================================
--- extensions/Password_Policy/admin/template/pp.css	(revision 25028)
+++ extensions/Password_Policy/admin/template/pp.css	(revision 25028)
@@ -0,0 +1,18 @@
+/* PP instructions */
+li {
+  margin-bottom: 15px;
+}
+
+label {
+    cursor: pointer;
+    display: list-item;
+    list-style: none outside none;
+}
+
+/* jQuery cluetip instructions */
+label.cluetip
+{
+  display: block;
+  font-weight: bold;
+  margin-bottom: 5px;
+}
Index: extensions/Password_Policy/changelog.txt.php
===================================================================
--- extensions/Password_Policy/changelog.txt.php	(revision 25028)
+++ extensions/Password_Policy/changelog.txt.php	(revision 25028)
@@ -0,0 +1,8 @@
+<?php
+/*
+Plugin Name: Password Policy
+** Change log **
+
+-- 2.5.0 : Initial release for Piwigo 2.5
+*/
+?>
Index: extensions/Password_Policy/include/functions.inc.php
===================================================================
--- extensions/Password_Policy/include/functions.inc.php	(revision 25028)
+++ extensions/Password_Policy/include/functions.inc.php	(revision 25028)
@@ -0,0 +1,532 @@
+<?php
+
+load_language('plugin.lang', PP_PATH);
+
+/**
+ * Triggered on get_admin_plugin_menu_links
+ * 
+ * Plugin's administration menu 
+ */
+function PP_admin_menu($menu)
+{
+// +-----------------------------------------------------------------------+
+// |                      Getting plugin name                              |
+// +-----------------------------------------------------------------------+
+  $plugin =  PPInfos(PP_PATH);
+  $name = $plugin['name'];
+  
+  array_push($menu,
+    array(
+    		'NAME' => $name,
+    		'URL' => get_root_url().'admin.php?page=plugin-'.basename(PP_PATH)
+    )
+  );
+
+  return $menu;
+}
+
+
+/**
+ * Triggered on loc_begin_index
+ * 
+ * Initiating GhostTracker - Perform user logout after registration if not validated
+ */
+function PP_Init()
+{
+  global $conf, $user;
+
+  include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
+
+  $conf_PP = unserialize($conf['PasswordPolicy']);
+
+  // Admins, Guests and Adult_Content users are excluded
+  // ---------------------------------------------------
+  if (!is_admin() and !is_a_guest() and $user['username'] != "16" and $user['username'] != "18")
+  {
+    // Perform user logout if user account is locked
+    if ((isset($conf_PP['LOGFAILBLOCK']) and $conf_PP['LOGFAILBLOCK'] == 'true')
+          and PP_UsrBlock_Verif($user['id'])
+          and !is_admin()
+          and !is_webmaster())
+    {
+      invalidate_user_cache();
+      logout_user();
+      if ( $conf['guest_access'] )
+      {
+        redirect( make_index_url().'?PP_msg=locked', 0);
+      }
+      else
+      {
+        redirect( get_root_url().'identification.php?PP_msg=locked' , 0);
+      }
+    }
+  }
+}
+
+
+/**
+ * Triggered on login_failure in main.inc.php
+ * Count of login failures and lock account after x attempt
+ *
+ */
+function PP_log_fail()
+{
+  global $conf, $user;
+
+  $conf_PP = unserialize($conf['PasswordPolicy']);
+
+  if (
+        (isset($conf_PP['NBLOGFAIL']) and $conf_PP['NBLOGFAIL'] <> 0)
+    and (isset($conf_PP['LOGFAILBLOCK']) and $conf_PP['LOGFAILBLOCK'] == 'true')
+    and !is_admin()
+    and !is_webmaster()
+    )
+  {
+    // If login failure then increments loginfailcount value in database
+    $query = '
+UPDATE '.USERS_TABLE.'
+SET PP_loginfailcount = PP_loginfailcount+1
+WHERE user_id = '.$userid.'
+LIMIT 1
+;';
+    pwg_query($query);
+
+    $query = '
+SELECT PP_loginfailcount
+FROM '.USERS_TABLE.'
+WHERE user_id = '.$userid.'
+;';
+
+    $datas = pwg_query($query);
+
+    // If number of failed logon exeeds 3, set the account as locked
+    if (isset($datas['PP_loginfailcount']) and $datas['PP_loginfailcount'] > $conf_PP['NBLOGFAIL'])
+    {
+      $query = '
+UPDATE '.USERS_TABLE.'
+SET PP_lock = "true"
+WHERE user_id = '.$userid.'
+LIMIT 1
+;';
+      pwg_query($query);
+    }
+  }
+}
+
+
+/**
+ * PP_loc_visible_user_list
+ * Adds a new feature in user_list to allow password reset for selected users by admin
+ * 
+ */
+function PP_loc_visible_user_list($visible_user_list)
+{
+  global $template;
+
+  $template->append('plugin_user_list_column_titles', l10n('PP_PwdReset'));
+
+  $user_ids = array();
+
+  foreach ($visible_user_list as $i => $user)
+  {
+    $user_ids[$i] = $user['id'];
+  }
+
+  $user_nums = array_flip($user_ids);
+
+  // Query to get information in database
+  // ------------------------------------
+  if (!empty($user_ids))
+  {
+    $query = '
+SELECT DISTINCT id, PP_pwdreset
+  FROM '.USERS_TABLE.'
+  WHERE id IN ('.implode(',', $user_ids).')
+;';
+    $result = pwg_query($query);
+
+    while ($row = pwg_db_fetch_assoc($result))
+    {
+      if ($row['PP_pwdreset'] == 'false')
+      {
+        $pwdreset = l10n('PP_PwdReset_Done');
+      }
+      else if ($row['PP_pwdreset'] == 'true')
+      {
+        $pwdreset = l10n('PP_PwdReset_Todo');
+      }
+      else $pwdreset = l10n('PP_PwdReset_NA');
+
+		  $visible_user_list[$user_nums[$row['id']]]['plugin_columns'][] = $pwdreset; // Shows users password state in user_list
+    }
+  }
+  return $visible_user_list;
+}
+
+
+/**
+ * Triggered on login_success
+ * 
+ * Redirects a visitor (except for admins, webmasters and generic statuses) to his profile.php page if password reset is needed
+ * 
+ */
+function PP_LoginTasks()
+{
+  global $conf, $user;
+
+  include_once(PHPWG_ROOT_PATH.'admin/include/functions.php');
+
+  $conf_PP = unserialize($conf['PasswordPolicy']);
+
+  // Performing redirection to profile page for password reset
+  // ---------------------------------------------------------
+  if ((isset($conf_PP['PWDRESET']) and $conf_PP['PWDRESET'] == 'true'))
+  {
+    $query ='
+SELECT user_id, status
+FROM '.USER_INFOS_TABLE.'
+WHERE user_id = '.$user['id'].'
+;';
+    $data = pwg_db_fetch_assoc(pwg_query($query));
+
+    if ($data['status'] <> "webmaster" and $data['status'] <> "generic") // Exclusion of specific accounts
+    {
+      if (PP_check_pwgreset($user['id']))
+      {
+        redirect(PHPWG_ROOT_PATH.'profile.php');
+      }
+    }
+  }
+}
+
+
+/**
+ * Triggered on register_user_check
+ * 
+ * Additional controls on user registration check
+ */
+function PP_RegistrationCheck($errors, $user)
+{
+  global $conf;
+
+  // Exclusion of Adult_Content users
+  // --------------------------------
+  if ($user['username'] != "16" and $user['username'] != "18")
+  {
+    load_language('plugin.lang', PP_PATH);
+
+    $PasswordCheck = 0;
+
+    $conf_PP = unserialize($conf['PasswordPolicy']);
+
+    // Password enforcement control
+    // ----------------------------
+    if (isset($conf_PP['PASSWORDENF']) and $conf_PP['PASSWORDENF'] == 'true' and !empty($conf_PP['PASSWORD_SCORE']))
+    {
+      if (!empty($user['password']) and !is_admin())
+      {
+        $PasswordCheck = PP_testpassword($user['password']);
+  
+        if ($PasswordCheck < $conf_PP['PASSWORD_SCORE'])
+        {
+          $message = get_l10n_args('PP_reg_err_login4_%s', $PasswordCheck);
+          $lang['reg_err_pass'] = l10n_args($message).$conf_PP['PASSWORD_SCORE'];
+          array_push($errors, $lang['reg_err_pass']);
+        }
+      }
+      else if (!empty($user['password']) and is_admin() and isset($conf_PP['ADMINPASSWENF']) and $conf_PP['ADMINPASSWENF'] == 'true')
+      {
+        $PasswordCheck = PP_testpassword($user['password']);
+  
+        if ($PasswordCheck < $conf_PP['PASSWORD_SCORE'])
+        {
+          $message = get_l10n_args('PP_reg_err_login4_%s', $PasswordCheck);
+          $lang['reg_err_pass'] = l10n_args($message).$conf_PP['PASSWORD_SCORE'];
+          array_push($errors, $lang['reg_err_pass']);
+        }
+      }
+    }
+  }
+}
+
+
+/**
+ * Triggered on loc_begin_profile
+ */
+function PP_Profile_Init()
+{
+  global $conf, $user, $template;
+
+  $conf_PP = unserialize($conf['PasswordPolicy']);
+
+  // Special message display for password reset
+  // ------------------------------------------
+  if ((isset($conf_PP['PWDRESET']) and $conf_PP['PWDRESET'] == 'true'))
+  {
+    if (PP_check_pwgreset($user['id']))
+    {
+      $template->append('errors', l10n('PP_Password_Reset_Msg'));
+    }
+  }
+
+  // Controls on profile page submission
+  // -----------------------------------
+  if (isset($_POST['validate']) and !is_admin())
+  {
+    // Password reset control
+    // ----------------------
+    if (isset($conf_PP['PWDRESET']) and $conf_PP['PWDRESET'] == 'true' and PP_check_pwgreset($user['id']))
+    {
+      // if password not changed then pwdreset field = true else pwdreset field = false
+      // ------------------------------------------------------------------------------
+      if (!empty($_POST['use_new_pwd']))
+      {
+        $query = '
+UPDATE '.USERS_TABLE.'
+SET PP_pwdreset = "false"
+WHERE id = '.$user['id'].'
+LIMIT 1
+;';
+        pwg_query($query);
+      }
+    }
+
+    if (!empty($_POST['use_new_pwd']))
+    {
+      // Password enforcement control
+      // ----------------------------
+      if (isset($conf_PP['PASSWORDENF']) and $conf_PP['PASSWORDENF'] == 'true' and !empty($conf_PP['PASSWORD_SCORE']))
+      {
+        $PasswordCheck = PP_testpassword($_POST['use_new_pwd']);
+
+        if ($PasswordCheck < $conf_PP['PASSWORD_SCORE'])
+        {
+          $message = get_l10n_args('PP_reg_err_login4_%s', $PasswordCheck);
+          $template->append('errors', l10n_args($message).$conf_PP['PASSWORD_SCORE']);
+          unset($_POST['use_new_pwd']);
+          unset($_POST['validate']);
+        }
+      }
+    }
+  }
+}
+
+
+/**
+ * PP_Set_PwdReset
+ * Action in user_list to set a password reset for a user
+ */
+function PP_Set_PwdReset($uid)
+{
+  $query ='
+UPDATE '.USERS_TABLE.'
+SET PP_pwdreset = "true"
+WHERE id = '.$uid.'
+LIMIT 1
+;';
+
+  pwg_query($query);
+}
+
+
+/**
+ * PP_check_pwdreset
+ * checks if a user id is registered as having already
+ * changed his password.
+ * 
+ * @uid        : the user id
+ * 
+ * @returns    : true or false whether the users has already changed his password
+ * 
+ */
+function PP_check_pwgreset($uid)
+{
+  $query = '
+SELECT PP_pwdreset
+FROM '.USERS_TABLE.'
+WHERE id='.$uid.'
+;';
+
+  $result = pwg_db_fetch_assoc(pwg_query($query));
+
+  if($result['PP_pwdreset'] == 'true')
+  {
+    return true;
+  }
+  else return false; 
+}
+
+
+/**
+ * Returns a password's score for password complexity check
+ *
+ * @param : password filled by user
+ * 
+ * @return : Score calculation
+ * 
+ * Thanx to MathieuGut from http://m-gut.developpez.com
+ */
+function PP_testpassword($password) // $password given by user
+{
+
+  // Variables initiation
+  // --------------------
+  $points = 0;
+  $point_lowercase = 0;
+  $point_uppercase = 0;
+  $point_numbers = 0;
+  $point_characters = 0;
+
+  // Getting password lengh
+  // ----------------------
+  $length = strlen($password);
+
+  // Loop to read password characters
+  for($i = 0; $i < $length; $i++)
+  {
+    // Select each letters
+    // $i is 0 at first turn
+    // ---------------------
+    $letters = $password[$i];
+
+    if ($letters>='a' && $letters<='z')
+    {
+      // Adding 1 point to score for a lowercase
+      // ---------------------------------------
+		  		$points = $points + 1;
+
+      // Adding bonus points for lowercase
+      // ---------------------------------
+		  $point_lowercase = 1;
+    }
+    else if ($letters>='A' && $letters <='Z')
+    {
+      // Adding 2 points to score for uppercase
+      // --------------------------------------
+      $points = $points + 2;
+
+      // Adding bonus points for uppercase
+      // ---------------------------------
+      $point_uppercase = 2;
+    }
+    else if ($letters>='0' && $letters<='9')
+    {
+      // Adding 3 points to score for numbers
+      // ------------------------------------
+      $points = $points + 3;
+
+      // Adding bonus points for numbers
+      // -------------------------------
+      $point_numbers = 3;
+    }
+    else
+    {
+      // Adding 5 points to score for special characters
+      // -----------------------------------------------
+      $points = $points + 5;
+		
+      // Adding bonus points for special characters
+      // ------------------------------------------
+      $point_characters = 5;
+    }
+  }
+
+  // Calculating the coefficient points/length
+  // -----------------------------------------
+  $step1 = $points / $length;
+
+  // Calculation of the diversity of character types...
+  // --------------------------------------------------
+  $step2 = $point_lowercase + $point_uppercase + $point_numbers + $point_characters;
+
+  // Multiplying the coefficient of diversity with that of the length
+  // ----------------------------------------------------------------
+  $score = $step1 * $step2;
+
+  // Multiplying the result by the length of the string
+  // --------------------------------------------------
+  $finalscore = $score * $length;
+
+  return $finalscore;
+}
+
+
+/**
+ * PP_UsrBlock_Verif
+ * Check if the user's account is locked
+ * 
+ * @returns : True if account is locked else False
+ */
+function PP_UsrBlock_Verif($user_id)
+{
+  global $conf;
+
+  $query = '
+SELECT PP_Lock
+FROM '.USERS_TABLE.'
+WHERE id='.$user_id.'
+;';
+
+  $result = pwg_db_fetch_assoc(pwg_query($query));
+
+  if($result['PP_Lock'] == 'true')
+  {
+    return true;
+  }
+  else return false;
+}
+
+
+/**
+ * Function called from PP_admin.php to get the plugin version and name
+ *
+ * @param : plugin directory
+ * 
+ * @return : plugin's version and name
+ * 
+ */
+function PPInfos($dir)
+{
+  $path = $dir;
+
+  $plg_data = implode( '', file($path.'main.inc.php') );
+  if ( preg_match("|Plugin Name: (.*)|", $plg_data, $val) )
+  {
+    $plugin['name'] = trim( $val[1] );
+  }
+  if (preg_match("|Version: (.*)|", $plg_data, $val))
+  {
+    $plugin['version'] = trim($val[1]);
+  }
+  if ( preg_match("|Plugin URI: (.*)|", $plg_data, $val) )
+  {
+    $plugin['uri'] = trim($val[1]);
+  }
+  if ($desc = load_language('description.txt', $path.'/', array('return' => true)))
+  {
+    $plugin['description'] = trim($desc);
+  }
+  elseif ( preg_match("|Description: (.*)|", $plg_data, $val) )
+  {
+    $plugin['description'] = trim($val[1]);
+  }
+  if ( preg_match("|Author: (.*)|", $plg_data, $val) )
+  {
+    $plugin['author'] = trim($val[1]);
+  }
+  if ( preg_match("|Author URI: (.*)|", $plg_data, $val) )
+  {
+    $plugin['author uri'] = trim($val[1]);
+  }
+  if (!empty($plugin['uri']) and strpos($plugin['uri'] , 'extension_view.php?eid='))
+  {
+    list( , $extension) = explode('extension_view.php?eid=', $plugin['uri']);
+    if (is_numeric($extension)) $plugin['extension'] = $extension;
+  }
+// IMPORTANT SECURITY !
+// --------------------
+  $plugin = array_map('htmlspecialchars', $plugin);
+
+  return $plugin ;
+}
+?>
Index: extensions/Password_Policy/include/index.php
===================================================================
--- extensions/Password_Policy/include/index.php	(revision 25028)
+++ extensions/Password_Policy/include/index.php	(revision 25028)
@@ -0,0 +1,33 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | PhpWebGallery - a PHP based picture gallery                           |
+// | Copyright (C) 2002-2003 Pierrick LE GALL - pierrick@phpwebgallery.net |
+// | Copyright (C) 2003-2007 PhpWebGallery Team - http://phpwebgallery.net |
+// +-----------------------------------------------------------------------+
+// | file          : $Id: index.php 1912 2007-03-16 06:30:07Z rub $
+// | last update   : $Date: 2007-03-16 07:30:07 +0100 (ven, 16 mar 2007) $
+// | last modifier : $Author: rub $
+// | revision      : $Revision: 1912 $
+// +-----------------------------------------------------------------------+
+// | This program is free software; you can redistribute it and/or modify  |
+// | it under the terms of the GNU General Public License as published by  |
+// | the Free Software Foundation                                          |
+// |                                                                       |
+// | This program 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      |
+// | General Public License for more details.                              |
+// |                                                                       |
+// | You should have received a copy of the GNU General Public License     |
+// | along with this program; if not, write to the Free Software           |
+// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
+// | USA.                                                                  |
+// +-----------------------------------------------------------------------+
+
+// Recursive call
+$url = '../';
+header( 'Request-URI: '.$url );
+header( 'Content-Location: '.$url );
+header( 'Location: '.$url );
+exit();
+?>
Index: extensions/Password_Policy/index.php
===================================================================
--- extensions/Password_Policy/index.php	(revision 25028)
+++ extensions/Password_Policy/index.php	(revision 25028)
@@ -0,0 +1,33 @@
+<?php
+// +-----------------------------------------------------------------------+
+// | PhpWebGallery - a PHP based picture gallery                           |
+// | Copyright (C) 2002-2003 Pierrick LE GALL - pierrick@phpwebgallery.net |
+// | Copyright (C) 2003-2007 PhpWebGallery Team - http://phpwebgallery.net |
+// +-----------------------------------------------------------------------+
+// | file          : $Id: index.php 1912 2007-03-16 06:30:07Z rub $
+// | last update   : $Date: 2007-03-16 07:30:07 +0100 (ven, 16 mar 2007) $
+// | last modifier : $Author: rub $
+// | revision      : $Revision: 1912 $
+// +-----------------------------------------------------------------------+
+// | This program is free software; you can redistribute it and/or modify  |
+// | it under the terms of the GNU General Public License as published by  |
+// | the Free Software Foundation                                          |
+// |                                                                       |
+// | This program 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      |
+// | General Public License for more details.                              |
+// |                                                                       |
+// | You should have received a copy of the GNU General Public License     |
+// | along with this program; if not, write to the Free Software           |
+// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
+// | USA.                                                                  |
+// +-----------------------------------------------------------------------+
+
+// Recursive call
+$url = '../';
+header( 'Request-URI: '.$url );
+header( 'Content-Location: '.$url );
+header( 'Location: '.$url );
+exit();
+?>
Index: extensions/Password_Policy/main.inc.php
===================================================================
--- extensions/Password_Policy/main.inc.php	(revision 25028)
+++ extensions/Password_Policy/main.inc.php	(revision 25028)
@@ -0,0 +1,235 @@
+<?php
+/*
+Plugin Name: Password Policy
+Version: 2.5.0
+Description: Renforcer la sécurité des mots de passe - Enforce password security
+Plugin URI: http://piwigo.org/ext/extension_view.php?eid=
+Author: Eric
+Author URI: http://www.infernoweb.net
+*/
+
+/* History:  PP_PATH.'Changelog.txt.php' */
+
+if (!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
+if (!defined('PP_PATH')) define('PP_PATH' , PHPWG_PLUGINS_PATH.basename(dirname(__FILE__)).'/');
+
+global $conf;
+
+include_once (PP_PATH.'include/functions.inc.php');
+
+load_language('plugin.lang', PP_PATH);
+$conf_PP = unserialize($conf['PasswordPolicy']);
+
+
+// Plugin administration panel
+// ---------------------------
+add_event_handler('get_admin_plugin_menu_links', 'PP_admin_menu');
+
+// Features and controls on user connexion
+// ---------------------------------------
+add_event_handler('loc_begin_index', 'PP_Init');
+
+// Check users registration
+// ------------------------
+add_event_handler('register_user_check', 'PP_RegistrationCheck', EVENT_HANDLER_PRIORITY_NEUTRAL, 2);
+
+if (script_basename() == 'profile')
+{
+  add_event_handler('loc_begin_profile', 'PP_Profile_Init');
+}
+
+// Redirection to profile page
+// ---------------------------
+add_event_handler('login_success', 'PP_LoginTasks',EVENT_HANDLER_PRIORITY_NEUTRAL, 1);
+
+// Add new feature in user_list - Password Reset
+// ---------------------------------------------
+if (isset($conf_PP['PWDRESET']) and $conf_PP['PWDRESET'] == 'true')
+{
+  // Add new column on user_list
+  // ---------------------------
+  add_event_handler('loc_visible_user_list', 'PP_loc_visible_user_list');
+
+  // Add prefilter on user_list
+  // --------------------------
+  add_event_handler('loc_begin_admin', 'PP_PwdReset_Action',60);
+
+  /**
+   * PP_PwdReset_Action - Triggered on PP_PwdReset_Action
+   * Handle password reset action in user_list.php
+   */
+  function PP_PwdReset_Action()
+  {
+    global $conf, $user, $template, $lang, $errors;
+
+    $page['errors'] = array();
+    $page['infos'] = array();
+    $page['filtered_users'] = array();
+
+    if (isset($_POST['pwdreset']))
+    {
+      $collection = array();
+
+      switch ($_POST['target'])
+      {
+        case 'all' :
+        {
+          foreach($page['filtered_users'] as $local_user)
+          {
+            array_push($collection, $local_user['id']);
+          }
+          break;
+        }
+        case 'selection' :
+        {
+          if (isset($_POST['selection']))
+          {
+            $collection = $_POST['selection'];
+          }
+          break;
+        }
+      }
+
+      if (count($collection) == 0)
+      {
+        array_push($page['errors'], l10n('Select at least one user'));
+      }
+    }
+
+    if (isset($_POST['pwdreset']) and count($collection) > 0)
+    {
+      if (in_array($conf['guest_id'], $collection))
+      {
+        array_push($page['errors'], l10n('PP_Guest cannot be pwdreset'));
+        $template->append('errors', l10n('PP_Guest cannot be pwdreset'));
+      }
+      if (($conf['guest_id'] != $conf['default_user_id']) and
+        in_array($conf['default_user_id'], $collection))
+      {
+        array_push($page['errors'], l10n('PP_Default user cannot be pwgreset'));
+        $template->append('errors', l10n('PP_Default user cannot be pwgreset'));
+      }
+      if (in_array($conf['webmaster_id'], $collection))
+      {
+        array_push($page['errors'], l10n('PP_Webmaster cannot be pwdreset'));
+        $template->append('errors', l10n('PP_Webmaster cannot be pwdreset'));
+      }
+      if (in_array($user['id'], $collection))
+      {
+        array_push($page['errors'], l10n('PP_You cannot pwdreset your account'));
+        $template->append('errors', l10n('PP_You cannot pwdreset your account'));
+      }
+
+      // Generic accounts exclusion (including Adult_Content generic users)
+      // ------------------------------------------------------------------
+      $query ='
+SELECT u.id
+FROM '.USERS_TABLE.' AS u
+INNER JOIN '.USER_INFOS_TABLE.' AS ui
+  ON u.id = ui.user_id
+WHERE ui.status = "generic"
+;';
+
+	    $result = pwg_query($query);
+
+      while ($row = pwg_db_fetch_assoc($result))
+      {
+        if (in_array($row['id'], $collection))
+        {
+          array_push($page['errors'], l10n('PP_Generic cannot be pwdreset'));
+          $errors = l10n('PP_Generic cannot be pwdreset');
+        }
+      }
+
+      // Admins accounts exclusion
+      // --------------------------
+      $query ='
+SELECT u.id
+FROM '.USERS_TABLE.' AS u
+INNER JOIN '.USER_INFOS_TABLE.' AS ui
+  ON u.id = ui.user_id
+WHERE ui.status = "admin"
+;';
+
+	    $result = pwg_query($query);
+
+      while ($row = pwg_db_fetch_assoc($result))
+      {
+        if (in_array($row['id'], $collection))
+        {
+          array_push($page['errors'], l10n('PP_Admins cannot be pwdreset'));
+          $errors = l10n('PP_Admins cannot be pwdreset');
+        }
+      }
+
+      $template->append('errors', $errors);
+
+      if (count($page['errors']) == 0)
+      {
+        if (isset($_POST['confirm_pwdreset']) and 1 == $_POST['confirm_pwdreset'])
+        {
+          foreach ($collection as $user_id)
+          {
+            PP_Set_PwdReset($user_id);
+          }
+          array_push(
+            $page['infos'],
+            l10n_dec(
+              'PP %d user pwdreseted', 'PP %d users pwdreseted',
+              count($collection)
+              )
+            );
+          $template->append('infos', l10n_dec(
+              'PP %d user pwdreseted', 'PP %d users pwdreseted',
+              count($collection)));
+          foreach ($page['filtered_users'] as $filter_key => $filter_user)
+          {
+            if (in_array($filter_user['id'], $collection))
+            {
+              unset($page['filtered_users'][$filter_key]);
+            }
+          }
+        }
+        else
+        {
+          array_push($page['errors'], l10n('PP_You need to confirm pwdreset'));
+          $template->append('errors', l10n('PP_You need to confirm pwdreset'));
+        }
+      }
+    }
+    $template->set_prefilter('user_list', 'PP_PwdReset_Prefilter');
+  }
+
+  /**
+   * PP_PwdReset_Prefilter
+   * Adds action field for password reset in user_list.tpl
+   */
+  function PP_PwdReset_Prefilter($content, &$smarty)
+  {
+    $search = '
+<fieldset>
+  <legend>{\'Deletions\'|@translate}</legend>
+  <label><input type="checkbox" name="confirm_deletion" value="1"> {\'confirm\'|@translate}</label>
+  <input class="submit" type="submit" value="{\'Delete selected users\'|@translate}" name="delete">
+</fieldset>
+';
+ 
+    $addon = '
+<fieldset>
+  <legend>{\'PP_PwdReset\'|@translate}</legend>
+  <label><input type="checkbox" name="confirm_pwdreset" value="1"> {\'confirm\'|@translate}</label>
+  <input class="submit" type="submit" value="{\'PP_Password reset selected users\'|@translate}" name="pwdreset">
+</fieldset>
+';
+
+    $replacement = $addon.$search;
+
+    return str_replace($search, $replacement, $content);
+  }
+}
+
+
+// Security option : Count of login failure and lock account after x attempt
+// -------------------------------------------------------------------------
+add_event_handler('login_failure', 'PP_log_fail');
+?>
Index: extensions/Password_Policy/maintain.inc.php
===================================================================
--- extensions/Password_Policy/maintain.inc.php	(revision 25028)
+++ extensions/Password_Policy/maintain.inc.php	(revision 25028)
@@ -0,0 +1,157 @@
+<?php
+
+if(!defined('PP_PATH'))
+{
+  define('PP_PATH' , PHPWG_PLUGINS_PATH.basename(dirname(__FILE__)).'/');
+}
+
+include_once (PP_PATH.'include/functions.inc.php');
+
+load_language('plugin.lang', PP_PATH);
+
+
+function plugin_install()
+{
+	global $conf;
+
+  // Set current plugin version in config table
+  // ------------------------------------------
+  $plugin =  PPInfos(PP_PATH);
+  $version = $plugin['version'];
+
+/* ****************************************************************** */
+/* **************** BEGIN - Data preparation in vars **************** */
+/* ****************************************************************** */
+
+  // Default global parameters for PasswordPolicy conf
+  // -------------------------------------------------
+  $defaultPP = array(
+    'PPVersion'                   => $version, // PasswordPolicy History version
+    'PASSWORDENF'                 => 'false',
+    'PASSWORD_SCORE'              => '100',
+    'ADMINPASSWENF'               => 'false',
+    'PWDRESET'                    => 'false',
+    'NBLOGFAIL'                   => '0',
+    'LOGFAILBLOCK'                => 'false',
+    'USRLOCKED'                   => l10n('PP_User_Account_Locked_Txt')
+  );
+
+/* **************************************************************** */
+/* **************** END - Data preparation in vars **************** */
+/* **************************************************************** */
+
+
+/* ***************************************************************************** */
+/* **************** BEGIN - Database actions and initialization **************** */
+/* ***************************************************************************** */
+
+  // Create PasswordPolicy conf if not already exists
+  // ------------------------------------------------
+	$query = '
+SELECT param
+  FROM '.CONFIG_TABLE.'
+WHERE param = "PasswordPolicy"
+;';
+  $count = pwg_db_num_rows(pwg_query($query));
+  
+  if ($count == 0)
+  {
+    $q = '
+INSERT INTO '.CONFIG_TABLE.' (param, value, comment)
+VALUES ("PasswordPolicy","'.pwg_db_real_escape_string(serialize($defaultPP)).'","Password Policy parameters")
+  ;';
+    pwg_query($q);
+  }
+
+  // Piwigo's native tables modifications for password reset function - Add pwdreset column if not already exists
+  // ------------------------------------------------------------------------------------------------------------
+  $query = '
+SHOW COLUMNS FROM '.USERS_TABLE.'
+LIKE "PP_pwdreset"
+;';
+  
+  $result = pwg_query($query);
+
+  if(!pwg_db_fetch_row($result))
+  {
+    $q = '
+ALTER TABLE '.USERS_TABLE.'
+ADD PP_pwdreset enum("true","false") 
+;';
+    pwg_query($q);
+  }
+
+  // Piwigo's native tables modifications for failed login attempts count
+  // --------------------------------------------------------------------
+  $query = '
+SHOW COLUMNS FROM '.USERS_TABLE.'
+LIKE "PP_loginfailcount"
+;';
+  
+  $result = pwg_query($query);
+
+  if(!pwg_db_fetch_row($result))
+  {
+    $q = '
+ALTER TABLE '.USERS_TABLE.'
+ADD PP_loginfailcount INT NULL DEFAULT NULL
+;';
+    pwg_query($q);
+  }
+
+  // Piwigo's native tables modifications for locked accounts
+  // --------------------------------------------------------
+  $query = '
+SHOW COLUMNS FROM '.USERS_TABLE.'
+LIKE "PP_lock"
+;';
+  
+  $result = pwg_query($query);
+
+  if(!pwg_db_fetch_row($result))
+  {
+    $q = '
+ALTER TABLE '.USERS_TABLE.'
+ADD PP_lock enum("true","false")
+;';
+    pwg_query($q);
+  }
+/* *************************************************************************** */
+/* **************** END - Database actions and initialization **************** */
+/* *************************************************************************** */
+}
+
+
+function plugin_uninstall()
+{
+  global $conf;
+
+  if (isset($conf['PasswordPolicy']))
+  {
+    $q = '
+DELETE FROM '.CONFIG_TABLE.'
+WHERE param="PasswordPolicy"
+;';
+
+    pwg_query($q);
+  }
+
+  $q = '
+ALTER TABLE '.USERS_TABLE.'
+DROP PP_pwdreset 
+;';
+  pwg_query($q);
+
+  $q = '
+ALTER TABLE '.USERS_TABLE.'
+DROP PP_loginfailcount 
+;';
+  pwg_query($q);
+
+  $q = '
+ALTER TABLE '.USERS_TABLE.'
+DROP PP_lock 
+;';
+  pwg_query($q);
+}
+?>
