=== modified file 'modules/user/user.module' --- modules/user/user.module 2006-10-18 19:54:11 +0000 +++ modules/user/user.module 2006-10-19 17:34:34 +0000 @@ -702,8 +702,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); @@ -1108,7 +1110,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; } } @@ -1127,7 +1129,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) { @@ -1374,6 +1376,77 @@ 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)) { + drupal_set_message(t('Please check your new e-mail address for confirmation and follow the link provided to complete the 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 edit link that has expired. Please request a new one using the form below.'), 'error'); + drupal_goto('user/password'); + } + else if ($user->uid && $user->uid != $account->uid) { + drupal_set_message(t('The account identification numbers did not match.'), 'error'); + drupal_goto('user/'. $user->uid .'/edit'); + } + else if ($hash != user_email_rehash($account->pass, $new_mail)) { + drupal_set_message(t('There was a problem with this one time link. Please try again.'), 'error'); + drupal_goto('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 edit link which has either been used or is no longer valid. 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') { @@ -1525,6 +1598,10 @@ 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 this link 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 it is not used, your e-mail address change will not be processed.", $variables); } } }