=== 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('<p>This is a one-time login for %user_name and will expire on %expiration_date</p><p>Click on this button to login to the site and change your password.</p>', array('%user_name' => $account->name, '%expiration_date' => format_date($timestamp + $timeout))));
           $form['help'] = array('#value' => t('<p>This login can be used only once.</p>'));
           $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);
     }
   }
 }

