--- user.module	2005-03-31 07:47:28.000000000 +0200
+++ modules/user.module	2005-03-31 08:16:17.000000000 +0200
@@ -636,6 +636,8 @@ function user_menu($may_cache) {
       'callback' => 'user_page', 'access' => $user->uid == 0 && variable_get('user_register', 1), 'type' => MENU_LOCAL_TASK);
     $items[] = array('path' => 'user/password', 'title' => t('request new password'),
       'callback' => 'user_pass', 'access' => $user->uid == 0, 'type' => MENU_LOCAL_TASK);
+    $items[] = array('path' => 'user/newpassword', 'title' => t('directlogin'),
+      'callback' => 'user_pass_new', 'access' => $user->uid == 0, 'type' => MENU_CALLBACK);
     $items[] = array('path' => 'user/help', 'title' => t('help'),
       'callback' => 'user_help_page', 'type' => MENU_CALLBACK);
 
@@ -911,31 +913,31 @@ function user_pass() {
   }
   if ($account) {
     $from = variable_get('site_mail', ini_get('sendmail_from'));
-    $pass = user_password();
-
-    // Save new password:
-    user_save($account, array('pass' => $pass));
+    $timestamp = time();
+    $hashedpass = user_pass_rehash($account->pass, $timestamp, $account->changed);
+    // Generate one time login URL
+    $loginurl = "$base_url/user/newpassword/$account->uid/$timestamp/$hashedpass";
 
     // Mail new password:
-    $variables = array('%username' => $account->name, '%site' => variable_get('site_name', 'drupal'), '%password' => $pass, '%uri' => $base_url, '%uri_brief' => substr($base_url, strlen('http://')), '%mailto' => $account->mail, '%date' => format_date(time()), '%login_uri' => url('user', NULL, NULL, TRUE), '%edit_uri' => url('user/'. $account->uid .'/edit', NULL, NULL, TRUE));
+    $variables = array('%username' => $account->name, '%site' => variable_get('site_name', 'drupal'), '%login_url' => $loginurl, '%uri' => $base_url, '%uri_brief' => substr($base_url, strlen('http://')), '%mailto' => $account->mail, '%date' => format_date(time()), '%login_uri' => url('user', NULL, NULL, TRUE), '%edit_uri' => url('user/'. $account->uid .'/edit', NULL, NULL, TRUE));
     $subject = _user_mail_text('pass_subject', $variables);
     $body = _user_mail_text('pass_body', $variables);
     $headers = "From: $from\nReply-to: $from\nX-Mailer: Drupal\nReturn-path: $from\nErrors-to: $from";
     $mail_success = user_mail($account->mail, $subject, $body, $headers);
 
     if ($mail_success) {
-      watchdog('user', t('Password mailed to %name at %email.', array('%name' => '<em>'. $account->name .'</em>', '%email' => '<em>'. $account->mail .'</em>')));
-      drupal_set_message(t('Your password and further instructions have been sent to your e-mail address.'));
+      watchdog('user', t('Password change URL mailed to %name at %email.', array('%name' => '<em>'. $account->name .'</em>', '%email' => '<em>'. $account->mail .'</em>')));
+      drupal_set_message(t('Further instructions have been sent to your e-mail address.'));
     }
     else {
-      watchdog('user', t('Error mailing password to %name at %email.', array('%name' => '<em>'. $account->name .'</em>', '%email' => '<em>'. $account->mail .'</em>')), WATCHDOG_ERROR);
+      watchdog('user', t('Error mailing password changing instructions to %name at %email.', array('%name' => '<em>'. $account->name .'</em>', '%email' => '<em>'. $account->mail .'</em>')), WATCHDOG_ERROR);
       drupal_set_message(t('Unable to send mail. Please contact the site admin.'));
     }
     drupal_goto('user');
   }
   else {
     if ($edit) {
-      drupal_set_message(t('You must provider either a username or e-mail address.'), 'error');
+      drupal_set_message(t('You must provide either a username or e-mail address.'), 'error');
     }
     // Display form:
     $output = '<p>'. t('Enter your username <strong><em>or</em></strong> your e-mail address.') .'</p>';
@@ -946,6 +948,37 @@ function user_pass() {
   }
 }
 
+function user_pass_new($uid, $timestamp, $hashedpass) {
+  global $user;
+  $maxtime = 28800;
+  $currenttime = time();
+  if ($timestamp < $currenttime && $currenttime - $timestamp > $maxtime) {
+    drupal_set_message(t('You have tried to use a one time login URL which has expired. Please request a new one using the form below.'));
+    drupal_goto('user/password');
+  }
+  $account = user_load(array('uid' => $uid, 'status' => 1));
+  if(!$user->uid && !empty($account) && $timestamp > $account->changed && $timestamp < $currenttime &&
+      $hashedpass == user_pass_rehash($account->pass, $timestamp, $account->changed)) {
+    watchdog('user', t('One time auto login used for %name with timestamp %timestamp.', array('%name' => "<em>$account->name</em>", '%timestamp' => $timestamp)));
+    // Update the user table timestamp noting user has logged in.
+    // And this also makes this hased password a one-try-only login
+    db_query("UPDATE {users} SET changed = '%d' WHERE uid = %d", time(), $account->uid);
+    // Now we can set the new user
+    $user = $account;
+    // And proceed with normal login, going to user page
+    user_module_invoke('login', $edit, $user);
+    drupal_set_message(t('Please change your password.'));
+    drupal_goto('user/'. $user->uid .'/edit');
+  }
+  // Just deny access, no clues, no nothing
+  // Everything will be in the watchdog's URL for the admin to check
+  drupal_access_denied();
+}
+
+function user_pass_rehash($pass1, $timestamp, $lastlogin){
+  return md5($timestamp . $pass1 . $lastlogin);
+}
+
 function user_register($edit = array()) {
   global $user, $base_url;
 
@@ -1253,7 +1286,7 @@ function _user_mail_text($messageid, $va
       case 'pass_subject':
         return t('Replacement login information for %username at %site', $variables);
       case 'pass_body':
-        return t("%username,\n\nHere is your new password for %site. You may now login to %login_uri using the following username and password:\n\nusername: %username\npassword: %password\n\nAfter logging in, you may wish to change your password at %edit_uri", $variables);
+        return t("%username,\n\nHere is your new login information for %site. You may now login to %login_uri 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 eight hours. After logging in, you will be redirected to %edit_uri so you can change your password.", $variables);
     }
   }
 }
