diff -ur -x .svn logintoboggan/logintoboggan.module /home/sgifford/tmp/logintoboggan/logintoboggan.module
--- logintoboggan/logintoboggan.module	2009-05-07 03:04:43.000000000 +0000
+++ /home/sgifford/tmp/logintoboggan/logintoboggan.module	2009-05-08 04:48:22.000000000 +0000
@@ -237,7 +237,7 @@
  *
  * @ingroup logintoboggan_form
  */
-function logintoboggan_user_register_submit($form_id, $form_values) {
+function logintoboggan_user_register_submit($form_id, $form_values, &$ret = NULL) {
   global $base_url;
 
   $mail = $form_values['mail'];
@@ -279,7 +279,9 @@
   }
 
   $account = user_save('', array_merge($form_values, array('pass' => $pass, 'init' => $mail, 'roles' => $roles, 'status' => $status)));
-
+  if (isset($ret)) {
+    $ret['account'] = $account;
+  }
   watchdog('user', t('New user: %name %email.', array('%name' => $name, '%email' => "<$mail>")), WATCHDOG_NOTICE, l(t('edit'), 'user/'. $account->uid .'/edit'));
 
   $login_url = variable_get('user_register', 1) == 1 ? logintoboggan_eml_validate_url($account) : user_pass_reset_url($account);
@@ -330,7 +332,7 @@
   drupal_set_message($message);
 
   // where do we need to redirect after registration?
-  $redirect = _logintoboggan_process_redirect(variable_get('toboggan_redirect_on_register', ''), $account);
+  $redirect = _logintoboggan_process_redirect(variable_get('toboggan_redirect_on_register', ''), $account->uid);
 
   //log the user in if they created the account and immediate login is enabled.
   if($reg_pass_set) {
@@ -747,12 +749,15 @@
   return variable_get('toboggan_role', DRUPAL_AUTHENTICATED_RID);
 }
 
+define('LOGINTOBOGGAN_VALIDATE_EMAIL_OK', 0);
+define('LOGINTOBOGGAN_VALIDATE_EMAIL_FAILED', -1);
+define('LOGINTOBOGGAN_VALIDATE_EMAIL_REPEAT', 1);
+define('LOGINTOBOGGAN_VALIDATE_EMAIL_DENIED', 1);
 
 /**
- * Menu callback; process validate the e-mail address as a one time URL,
- * and redirects to the user page on success.
+ * Internal implementation of email validation.  Returns one of the statuses above.
  */
-function logintoboggan_validate_email($uid, $timestamp, $hashed_pass, $action = 'login') {
+function logintoboggan_validate_email_int($uid, $timestamp, $hashed_pass) {
 
   $current = time();
   $uid = (int) $uid;
@@ -767,7 +772,8 @@
       watchdog('user', t('E-mail validation URL used for %name with timestamp @timestamp.', array('%name' => $account->name, '@timestamp' => $timestamp)));
       // Update the user table noting user has logged in.
       // And this also makes this hashed password a one-time-only login.
-      db_query("UPDATE {users} SET login = '%d' WHERE uid = %d", time(), $account->uid);
+      if (!db_query("UPDATE {users} SET login = '%d' WHERE uid = %d", time(), $account->uid))
+	return LOGINTOBOGGAN_VALIDATE_EMAIL_FAILED;
 
       // Test here for a valid pre-auth -- if the pre-auth is set to the auth user, we
       // handle things a bit differently.
@@ -777,7 +783,9 @@
       // Remove the pre-auth role from the user, unless they haven't been approved yet.
       if ($account->status) {
         if ($pre_auth) {
-          db_query("DELETE FROM {users_roles} WHERE uid = %d AND rid = %d", $account->uid, $validating_id);
+          if (!db_query("DELETE FROM {users_roles} WHERE uid = %d AND rid = %d", $account->uid, $validating_id))
+	    return LOGINTOBOGGAN_VALIDATE_EMAIL_FAILED;
+
           // Since we're passing $account around to the update hook, remove
           // the pre-auth role from the roles array, and add in the auth user
           // role.
@@ -788,53 +796,94 @@
         $edit = array();
         $account->logintoboggan_email_validated = TRUE;
         user_module_invoke('update', $edit, $account);
+	
+	// user has new permissions, so we clear their menu cache
+	cache_clear_all($account->uid .':', 'cache_menu', TRUE);
+
+	return LOGINTOBOGGAN_VALIDATE_EMAIL_OK;
+      } else {
+	return LOGINTOBOGGAN_VALIDATE_EMAIL_DENIED;
       }
+      
+    }
+    else {
+      return LOGINTOBOGGAN_VALIDATE_EMAIL_REPEAT;
+    }
+  }
+
+  // Deny access, no more clues.
+  // Everything will be in the watchdog's URL for the administrator to check.
+  return LOGINTOBOGGAN_VALIDATE_EMAIL_DENIED;
+}
 
+/**
+ * Menu callback; process validate the e-mail address as a one time URL,
+ * and redirects to the user page on success.
+ */
+function logintoboggan_validate_email($uid, $timestamp, $hashed_pass, $action = 'login') {
+  $status = logintoboggan_validate_email_int($uid, $timestamp, $hashed_pass);
+  switch($status) {
+    case LOGINTOBOGGAN_VALIDATE_EMAIL_OK:
       // Where do we redirect after confirming the account?
-      $redirect = _logintoboggan_process_redirect(variable_get('toboggan_redirect_on_confirm', ''), $account);
+      $redirect = _logintoboggan_process_redirect(variable_get('toboggan_redirect_on_confirm', ''), $uid);
 
       switch ($action) {
         // Proceed with normal user login, as long as it's open registration and their
         // account hasn't been blocked.
         case 'login':
           // Only show the validated message if there's a valid pre-auth role.
+	  $validating_id = logintoboggan_validating_id();
+	  $pre_auth = $validating_id != DRUPAL_AUTHENTICATED_RID;
           if ($pre_auth) {
             drupal_set_message(t('You have successfully validated your e-mail address.'));
           }
-          if (!$account->status) {
-            drupal_set_message(t('Your account is currently blocked -- login cancelled.'), 'error');
-            drupal_goto('');
-          }
-          else {
-            drupal_goto(logintoboggan_process_login($account, $redirect));
-          }
+	  $account = user_load(array('uid' => $uid));
+	  drupal_goto(logintoboggan_process_login($account, $redirect));
           break;
         // Admin validation.
         case 'admin':
-          // user has new permissions, so we clear their menu cache
-          cache_clear_all($account->uid .':', 'cache_menu', TRUE);
-
-          drupal_set_message(t('You have successfully validated %user.', array('%user' => $account->name)));
-          drupal_goto("user/$account->uid/edit");
+          drupal_set_message(t('You have successfully validated UID %uid.', array('%uid' => $uid)));
+          drupal_goto("user/$uid/edit");
           break;
         // Catch all.
         default:
-          // user has new permissions, so we clear their menu cache
-          cache_clear_all($account->uid .':', 'cache_menu', TRUE);
-
-          drupal_set_message(t('You have successfully validated %user.', array('%user' => $account->name)));
+          drupal_set_message(t('You have successfully validated UID %uid.', array('%uid' => $uid)));
           drupal_goto('');
           break;
       }
-    }
-    else {
-      drupal_set_message(t("Sorry, you can only use your validation link once for security reasons. Please !login with your username and password instead now.", array('!login' => l(t('login'),'user/login'))),'error');
-    }
-  }
+      break;
 
-  // Deny access, no more clues.
-  // Everything will be in the watchdog's URL for the administrator to check.
-  drupal_access_denied();
+    case LOGINTOBOGGAN_VALIDATE_EMAIL_REPEAT:
+      global $user;
+      $msg = t("Your email address has already been validated.");
+
+      if (!$user->uid) {
+	# User is not logged in
+	$msg .= "  ".t("Please log in below.");
+      } else if ($user->uid != $uid) {
+	# User is logged in as a different user
+
+	$msg .= "  ".t("Please log in below.");
+
+	watchdog('user', 'Session closed for %name.', array('%name' => $user->name));
+
+	sess_regenerate();
+
+	module_invoke_all('user', 'logout', NULL, $user);
+	
+	// Load the anonymous user
+	$user = drupal_anonymous_user();
+      }
+
+      drupal_set_message($msg);
+      drupal_goto('user');
+      break;
+  default:
+    // Deny access, no more clues.
+    // Everything will be in the watchdog's URL for the administrator to check.
+    drupal_access_denied();
+    break;
+  }
 }
 
 /**
@@ -962,8 +1011,8 @@
   return (($_SERVER['HTTPS'] == 'on') ? 'https' : 'http');
 }
 
-function _logintoboggan_process_redirect($redirect, $account) {
-  $variables = array('%uid' => $account->uid);
+function _logintoboggan_process_redirect($redirect, $uid) {
+  $variables = array('%uid' => $uid);
   $redirect = strtr($redirect, $variables);
 
   return $redirect;
