=== modified file 'modules/user/user.module' --- modules/user/user.module 2006-10-26 23:25:45 +0000 +++ modules/user/user.module 2006-10-27 14:50:00 +0000 @@ -704,8 +704,10 @@ function user_menu($may_cache) { 'callback' => 'drupal_get_form', 'callback arguments' => array('user_register'), 'access' => !$user->uid && variable_get('user_register', 1), 'type' => MENU_LOCAL_TASK); $items[] = array('path' => 'user/password', 'title' => t('Request new password'), 'callback' => 'drupal_get_form', 'callback arguments' => array('user_pass'), 'access' => !$user->uid, 'type' => MENU_LOCAL_TASK); - $items[] = array('path' => 'user/reset', 'title' => t('Reset password'), + $items[] = array('path' => 'user/reset-password', 'title' => t('Reset password'), 'callback' => 'drupal_get_form', 'callback arguments' => array('user_pass_reset'), 'access' => TRUE, 'type' => MENU_CALLBACK); + $items[] = array('path' => 'user/change-mail', 'title' => t('Change e-mail'), + 'callback' => 'user_change_mail', 'access' => TRUE, 'type' => MENU_CALLBACK); $items[] = array('path' => 'user/help', 'title' => t('Help'), 'callback' => 'user_help_page', 'type' => MENU_CALLBACK); @@ -1116,7 +1118,7 @@ function user_pass_reset($uid, $timestam $form['message'] = array('#value' => t('

This is a one-time login for %user_name and will expire on %expiration_date

Click on this button to login to the site and change your password.

', array('%user_name' => $account->name, '%expiration_date' => format_date($timestamp + $timeout)))); $form['help'] = array('#value' => t('

This login can be used only once.

')); $form['submit'] = array('#type' => 'submit', '#value' => t('Log in')); - $form['#action'] = url("user/reset/$uid/$timestamp/$hashed_pass/login"); + $form['#action'] = url("user/reset-password/$uid/$timestamp/$hashed_pass/login"); return $form; } } @@ -1135,7 +1137,7 @@ function user_pass_reset($uid, $timestam function user_pass_reset_url($account) { $timestamp = time(); - return url("user/reset/$account->uid/$timestamp/".user_pass_rehash($account->pass, $timestamp, $account->login), NULL, NULL, TRUE); + return url("user/reset-password/$account->uid/$timestamp/". user_pass_rehash($account->pass, $timestamp, $account->login), NULL, NULL, TRUE); } function user_pass_rehash($password, $timestamp, $login) { @@ -1382,6 +1384,89 @@ function _user_edit_submit($uid, &$edit) if (isset($edit['roles'])) { $edit['roles'] = array_filter($edit['roles']); } + if ($user->mail != $edit['mail'] && !user_access('administer users')) { + $timestamp = time(); + $pass = $edit['pass'] ? md5($edit['pass']) : $user->pass; + $hash = user_email_rehash($pass, $edit['mail']); + $url = url("user/change-mail/$user->uid/$timestamp/". $edit['mail'] ."/$hash", NULL, NULL, TRUE); + $variables = array('!username' => $user->name, '!site' => variable_get('site_name', 'drupal'), '!email_url' => $url); + $subject = _user_mail_text('mail_change_subject', $variables); + $body = _user_mail_text('mail_change_body', $variables); + $from = variable_get('site_mail', ini_get('sendmail_from')); + if ($mail_success = drupal_mail('user_change_mail', $edit['mail'], $subject, $body, $from)) { + $body = _user_mail_text('mail_change_original_body', $variables); + drupal_mail('user_change_mail_original', $user->mail, $subject, $body, $from); + drupal_set_message(t('You will receive a confirmation e-mail at your new e-mail address shortly. You must follow the link provided in that e-mail within one day in order to complete your change.')); + } + unset($edit['mail']); + } +} + +function user_email_rehash($pass, $mail) { + return md5($pass . $mail); +} + +/** + * Menu callback; process one time email change confirm and redirects to the user page on success. + */ +function user_change_mail($uid, $timestamp, $new_mail, $hash, $action = '') { + global $user; + + $account = user_load(array('uid' => $uid)); + + // Time out, in seconds, until login URL expires. 24 hours = 86400 seconds. + $timeout = 86400; + $current = time(); + // Some redundant checks for extra security ? + if ($timestamp < $current && $account = user_load(array('uid' => $uid, 'status' => 1)) ) { + if ($current - $timestamp > $timeout) { + drupal_set_message(t('You have tried to use a one-time e-mail change link for %account that has expired--your change of e-mail request was not completed. Please visit your account edit page if you wish to attempt the change again.', array('%account' => $account->name)), 'error'); + if ($account->uid == $user->uid) { + drupal_goto("user/$account->uid/edit"); + } + else { + drupal_goto(''); + } + } + else if ($user->uid && $user->uid != $account->uid) { + drupal_set_message(t('You are currently logged in as %user, and are attempting to confirm an e-mail change for %account, which is not allowed. Please log in as %account and initiate a new change of e-mail request.', array('%user' => $user->name, '%account' => $account->name)), 'error'); + drupal_goto(''); + } + else if ($hash != user_email_rehash($account->pass, $new_mail)) { + drupal_set_message(t('There was a problem verifying your change of e-mail request--please visit your account edit page and attempt the change again'), 'error'); + if ($user->uid) { + drupal_goto("user/$user->uid/edit"); + } + else { + drupal_goto('user/login', "destination=user/$user->uid/edit"); + } + } + else if ($timestamp > $account->login && $timestamp < $current) { + watchdog('user', t('User %name used one-time e-mail change link at time %timestamp.', array('%name' => $account->name, '%timestamp' => $timestamp))); + db_query("UPDATE {users} SET mail = '%s' WHERE uid = %d", $new_mail, $account->uid); + drupal_set_message(t('Your e-mail address is now %mail.', array('%mail' => $new_mail))); + if ($user->uid) { + drupal_goto('user/' . $user->uid); + } + else { + drupal_goto('user'); + } + } + else { + drupal_set_message(t('You have tried to use a one-time e-mail change link which has either been used or has expired. Please request a new one.'), 'error'); + if ($user->uid) { + drupal_goto('user/'. $user->uid .'/edit'); + } + else { + drupal_goto('user/login', 'destination=user/'. $user->uid .'/edit'); + } + } + } + else { + // Deny access, no more clues. + // Everything will be in the watchdog's URL for the administrator to check. + drupal_access_denied(); + } } function user_edit($category = 'account') { @@ -1533,6 +1618,12 @@ function _user_mail_text($messageid, $va return t('Replacement login information for !username at !site', $variables); case 'pass_body': return t("!username,\n\nA request to reset the password for your account has been made at !site.\n\nYou may now log in to !uri_brief clicking on this link or copying and pasting it in your browser:\n\n!login_url\n\nThis is a one-time login, so it can be used only once. It expires after one day and nothing will happen if it's not used.\n\nAfter logging in, you will be redirected to !edit_uri so you can change your password.", $variables); + case 'mail_change_subject': + return t('E-mail change information for !username at !site', $variables); + case 'mail_change_body': + return t("!username,\n\nA request to change your e-mail address has been made at !site. You need to verify the change by clicking on the link below or copying and pasting it in your browser:\n\n!email_url\n\nThis is a one-time URL, so it can be used only once. It expires after one day. If not used, your e-mail address at !site will not change.", $variables); + case 'mail_change_original_body': + return t("!username,\n\nA request to change your e-mail address has been made at !site. In order to complete the change you will need to follow the instructions sent to your new e-mail address within one day.", $variables); } } }