recovery_pass.module in Recovery Password (Email New Password) 7
Same filename and directory in other branches
Alters default Drupal password recovery process by overriding default submit.
File
recovery_pass.moduleView source
<?php
/**
* @file
* Alters default Drupal password recovery process by overriding default submit.
*/
/**
* Implements hook_help().
*/
function recovery_pass_help($path, $arg) {
$output = '';
switch ($path) {
case 'admin/help#recovery_pass':
$output = file_get_contents(drupal_get_path('module', 'recovery_pass') . '/README.txt');
}
return $output;
}
/**
* Implements hook_ctools_plugin_api().
*/
function recovery_pass_ctools_plugin_api($owner, $api) {
if ($owner == 'services' && $api == 'services') {
return array(
'version' => 3,
'file' => 'recovery_pass.services.inc',
);
}
}
/**
* Implements hook_menu().
*/
function recovery_pass_menu() {
$items = array();
// Menu item for module configurations.
$items['admin/config/people/recovery-pass'] = array(
'title' => 'Recovery Password Configuration',
'description' => 'Configure email message to be sent to user for password recovery.',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'recovery_pass_config_form',
),
'access arguments' => array(
'administer users',
),
'file' => 'recovery_pass.admin.inc',
);
return $items;
}
/**
* Implements hook_form_FORM_ID_alter().
*/
function recovery_pass_form_user_pass_alter(&$form, &$form_state, $form_id) {
// Overrides default submit handler for user_pass form.
$form['#submit'] = array_diff($form['#submit'], array(
'user_pass_submit',
));
array_unshift($form['#submit'], 'recovery_pass_forgot_password_submit');
}
/**
* Custom submit handler to send password in recovery mail.
*/
function recovery_pass_forgot_password_submit($form, &$form_state) {
global $language;
$user = $form_state['values']['account'];
// Generate random password.
$random_password = user_password();
// Store Old Hash Password Temporarily.
if (!_recovery_pass_store_old_pass($user)) {
watchdog('recovery_pass', 'Error saving old password for user @id', array(
'@id' => $user->uid,
), WATCHDOG_NOTICE, 'link');
}
// Save new password.
user_save($user, array(
'pass' => $random_password,
), 'account');
// Retrive email body and subject.
$message = _recovery_pass_mail_text('email_text', $language, TRUE, $user);
if ($message) {
// Replace [user_new_password] placeholder with new password.
$message = str_replace("[user_new_password]", $random_password, $message);
}
$subject = _recovery_pass_mail_text('email_subject', $language, TRUE, $user);
if (module_exists("htmlmail")) {
// For html mail convert new lines to br.
$message = nl2br($message);
}
$params = array(
'body' => $message,
'subject' => $subject,
);
$to = $user->mail;
$from = variable_get('site_mail');
if (drupal_mail('recovery_pass', 'recovery_pass', $to, language_default(), $params, $from, TRUE)) {
drupal_set_message(t("Further instructions have been sent to your registered Email-id."), 'status', FALSE);
}
else {
drupal_set_message(t("Error Sending Recovery Mail. Please contact site administrator."), 'error', FALSE);
}
$form_state['redirect'] = variable_get('recovery_pass_fpass_redirect', 'user');
}
/**
* Temporarily stores old password in custom table for error message in future.
*/
function _recovery_pass_store_old_pass($user) {
// Update or Insert using db_merge() the old password.
$result = db_merge('recovery_pass')
->key(array(
'uid' => $user->uid,
))
->fields(array(
'uid' => (int) $user->uid,
'old_pass' => $user->pass,
'changed' => time(),
))
->execute();
if ($result) {
// Successfully saved old password.
return TRUE;
}
return FALSE;
}
/**
* Implements hook_mail().
*/
function recovery_pass_mail($key, &$message, $params) {
switch ($key) {
case 'recovery_pass':
// Mail parameters used for recovery mail.
$message['subject'] = $params['subject'];
$message['body'][] = $params['body'];
if (module_exists("htmlmail")) {
// For html mail.
$message['headers']['Content-Type'] = 'text/html; charset=UTF-8; format=flowed';
}
break;
}
}
/**
* Returns a mail string for a variable name.
*
* Used by recovery_pass_mail() and the settings forms to retrieve strings.
*/
function _recovery_pass_mail_text($key, $language = NULL, $replace = TRUE, $user = array()) {
$langcode = !empty($language) ? $language->language : NULL;
$text = '';
if ($admin_setting = variable_get('recovery_pass_' . $key, FALSE)) {
// An admin setting overrides the default string.
$text = $admin_setting;
}
else {
// No override, return default string.
switch ($key) {
case 'email_subject':
$text = t('Replacement login information for [user:name] at [site:name]', array(), array(
'langcode' => $langcode,
));
break;
case 'email_text':
$text = t("[user:name],\n\nA request to reset the password for your account has been made at [site:name].\n\nYour new password is [user_new_password].\n\n\n-- [site:name] team", array(), array(
'langcode' => $langcode,
));
break;
case 'old_pass_warning':
$text = t('You are using <strong>old password</strong>, your password was reset recently. New Password was sent to your registered email id.');
break;
}
}
if ($replace) {
// Token Replace the text.
return token_replace($text, array(
'user' => $user,
));
}
return $text;
}
/**
* Implements hook_form_alter().
*/
function recovery_pass_form_alter(&$form, &$form_state, $form_id) {
if (variable_get('recovery_pass_old_pass_show', 1)) {
switch ($form_id) {
case 'user_login_block':
case 'user_login':
// Extending default drupal login validators.
$insert = 'recovery_pass_user_login_validate';
$form['#validate'] = _recovery_pass_insert_array($form['#validate'], 1, $insert);
break;
}
}
}
/**
* To insert our validator at index 1 between the default validators.
*/
function _recovery_pass_insert_array($array, $index, $val) {
// Because this will be used one more time.
$size = count($array);
if (!is_int($index) || $index < 0 || $index > $size) {
return -1;
}
else {
$temp = array_slice($array, 0, $index);
$temp[] = $val;
return array_merge($temp, array_slice($array, $index, $size));
}
}
/**
* Custom Submit handler for user login form.
*
* Incase user tries to login using old pass then error msg is shown that pass
* has been reset, till user tries any other pass.
*/
function recovery_pass_user_login_validate($form, &$form_state) {
$input_password = trim($form_state['values']['pass']);
if (!empty($form_state['values']['name']) && !empty($input_password)) {
$account = db_query("SELECT uid,pass FROM {users} WHERE name = :name AND status = 1", array(
':name' => $form_state['values']['name'],
))
->fetchObject();
// Check uid exists in recovery_pass table.
$result = db_select('recovery_pass', 'r')
->fields('r', array(
'uid',
'old_pass',
))
->condition('uid', (int) $account->uid)
->execute()
->fetchAssoc();
if ($result) {
// If uid exists in table.
$old_password = $result['old_pass'];
// Match input password with password stored in recovery_pass table.
if (_recovery_pass_match_old_password($input_password, $old_password)) {
drupal_set_message(_recovery_pass_mail_text('old_pass_warning'), 'warning', FALSE);
}
else {
// Irrespective of the input password delete the entry.
$entry_deleted = db_delete('recovery_pass')
->condition('uid', $result['uid'])
->execute();
if (!$entry_deleted) {
watchdog('recovery_pass', 'Error deleting entry from recovery_table for user @id', array(
'@id' => $result['uid'],
), WATCHDOG_NOTICE, 'link');
}
}
}
}
}
/**
* Matches old password stored in recovery_pass table with user input password.
*/
function _recovery_pass_match_old_password($password, $old_password) {
// Allow alternate password hashing schemes.
require_once DRUPAL_ROOT . '/' . variable_get('password_inc', 'includes/password.inc');
if (substr($old_password, 0, 2) == 'U$') {
// This may be an updated password from user_update_7000(). Such hashes
// have 'U' added as the first character and need an extra md5().
$stored_hash = substr($old_password, 1);
$password = md5($password);
}
else {
$stored_hash = $old_password;
}
$type = substr($stored_hash, 0, 3);
switch ($type) {
case '$S$':
// A normal Drupal 7 password using sha512.
$hash = _password_crypt('sha512', $password, $stored_hash);
break;
case '$H$':
// phpBB3 uses "$H$" for the same thing as "$P$".
case '$P$':
// A phpass password generated using md5. This is an
// imported password or from an earlier Drupal version.
$hash = _password_crypt('md5', $password, $stored_hash);
break;
default:
return FALSE;
}
return $hash && $stored_hash == $hash;
}
/**
* Implements hook_cron().
*/
function recovery_pass_cron() {
$expiry_period = strtotime("-" . variable_get('recovery_pass_expiry_period', '1') . " week");
// Delete all records more created than one week ago.
$entry_deleted = db_delete('recovery_pass')
->condition('changed', $expiry_period, '<')
->execute();
if ($entry_deleted) {
watchdog('recovery_pass', 'Error deleting entry from recovery_table at cron time.', array(), WATCHDOG_NOTICE, 'link');
}
}
Functions
Name | Description |
---|---|
recovery_pass_cron | Implements hook_cron(). |
recovery_pass_ctools_plugin_api | Implements hook_ctools_plugin_api(). |
recovery_pass_forgot_password_submit | Custom submit handler to send password in recovery mail. |
recovery_pass_form_alter | Implements hook_form_alter(). |
recovery_pass_form_user_pass_alter | Implements hook_form_FORM_ID_alter(). |
recovery_pass_help | Implements hook_help(). |
recovery_pass_mail | Implements hook_mail(). |
recovery_pass_menu | Implements hook_menu(). |
recovery_pass_user_login_validate | Custom Submit handler for user login form. |
_recovery_pass_insert_array | To insert our validator at index 1 between the default validators. |
_recovery_pass_mail_text | Returns a mail string for a variable name. |
_recovery_pass_match_old_password | Matches old password stored in recovery_pass table with user input password. |
_recovery_pass_store_old_pass | Temporarily stores old password in custom table for error message in future. |