From adf7fa1fb980e1ac70b18c81d4e00f288e827c14 Mon Sep 17 00:00:00 2001
From: Bradley M. Froehle <brad.froehle@gmail.com>
Date: Tue, 29 Mar 2011 10:51:46 -0700
Subject: [PATCH] Issue #1051694 - Fix user login redirection.

---
 cas.module |  101 ++++++++++++++++++++++++++++++++++++------------------------
 1 files changed, 61 insertions(+), 40 deletions(-)

diff --git a/cas.module b/cas.module
index df659d1..2ab8e55 100644
--- a/cas.module
+++ b/cas.module
@@ -56,7 +56,6 @@ function cas_login_check() {
       // a valid session to complete the authentication process.
       drupal_session_start();
     }
-    cas_save_page();
     _cas_single_sign_out_save_ticket();  // We use this later for CAS 3 logoutRequests
 
     // Initialize phpCAS.
@@ -265,6 +264,15 @@ function cas_phpcas_init($force = FALSE) {
       break;
   }
 
+  // Set the service URL.
+  $options = array(
+    'query' => array(
+      'destination' => cas_login_destination(),
+    ),
+    'absolute' => TRUE,
+  );
+  phpCAS::setFixedServiceURL(url('cas', $options));
+
   // Allow other modules to call phpCAS routines. We do not call
   // drupal_alter() since there are no parameters to pass.
   module_invoke_all('cas_phpcas_alter');
@@ -499,27 +507,6 @@ function cas_user_load_by_name($cas_name, $alter = FALSE) {
 }
 
 /**
- * Saves the page that the user was on when login was requested or required
- */
-function cas_save_page() {
-  if (!isset($_SESSION['cas_goto'])) {
-    if (arg(0) == 'cas' && isset($_SERVER['HTTP_REFERER'])) {
-      //we're were destined to the CAS login page, so set
-      //the page to the referrer.
-      $_SESSION['cas_goto'] = $_SERVER['HTTP_REFERER'];
-    }
-    elseif (isset($_GET['q']) && $_GET['q'] != 'cas') {
-      //We're destined for another page, so save the group.
-      $_SESSION['cas_goto'] = $_GET['q'];
-    }
-    else {
-      // No idea where we are coming from or going to, so pick the front page.
-      $_SESSION['cas_goto'] = variable_get('site_frontpage', 'node');
-    }
-  }
-}
-
-/**
  * Redirects to appropriate page based on user settings.
  *
  * @param $cas_first_login
@@ -527,28 +514,57 @@ function cas_save_page() {
  *   configured 'Initial login landing page'.
  */
 function cas_login_page($cas_first_login = FALSE) {
-  global $user;
-  $destination = variable_get('site_frontpage', 'node');
+  $destination = '';
   // If it is the user's first CAS login and initial login redirection is enabled, go to the set page
   if ($cas_first_login && variable_get('cas_first_login', FALSE)) {
+    // Force redirection on the first login.
+    unset($_REQUEST['destination']);
     $destination = variable_get('cas_first_login_destination', '');
   }
-  elseif (isset($_REQUEST['destination'])) {
-    $destination = $_REQUEST['destination'];
-  }
-  elseif (isset($_SESSION['cas_goto'])) {
-    $destination = $_SESSION['cas_goto'];
-  }
-  unset($_SESSION['cas_goto']);
 
-  // Change the user/login and user/register urls to the users current page.
-  if ($destination == 'user/login' || $destination == 'user/register') {
-    $destination = 'user/' . $user->uid;
+  // drupal_goto() will prefer the destination in the query string,
+  // which should be set.
+  // @see drupal_login_destination().
+  drupal_goto($destination);
+}
+
+/**
+ * Prepare a destination string for use in combination with drupal_goto().
+ *
+ * Used to direct the user back to the referring page after completing the
+ * CAS login. This function prevents the login page from being returned because
+ * that page will give an access denied message to an authenticated user.
+ *
+ * @see user_login_destination().
+ */
+function cas_login_destination() {
+  $destination = user_login_destination();
+  $destination = preg_replace('/^destination=/', '', $destination);
+  $destination = urldecode($destination);
+
+  // We do not want to allow the destination to be 'cas' to avoid an access
+  // denied message.
+  if ($destination == 'cas') {
+    if (($referer_uri = referer_uri())) {
+      // Use the HTTP Referrer, if set. Unfortunately we need to strip the
+      // base path, as drupal_goto will not redirect to external paths passed
+      // by query string.
+      $base_url = $GLOBALS['base_url'] . '/';
+      if (strpos($referer_uri, $base_url) === 0) {
+        $destination = substr($referer_uri, strlen($base_url));
+      }
+      else {
+        // The URL appears not from our site.
+        $destination = '';
+      }
+    }
+    else {
+      // No HTTP Referer provided.
+      $destination = '';
+    }
   }
 
-  // Force redirection.
-  unset($_REQUEST['destination']);
-  drupal_goto($destination);
+  return $destination;
 }
 
 /**
@@ -819,7 +835,10 @@ function cas_form_alter(&$form, &$form_state, $form_id) {
           '#weight' => -1,
           '#description' => t(variable_get('cas_login_redir_message', CAS_LOGIN_REDIR_MESSAGE)),
         );
-        $form['cas.return_to'] = array('#type' => 'hidden', '#value' => 'cas');
+        $form['cas_destination'] = array(
+          '#type' => 'hidden',
+          '#value' => cas_login_destination(),
+        );
       }
       break;
 
@@ -937,8 +956,10 @@ function cas_login_validate($form, &$form_state) {
   if (!empty($form_state['values']['persistent_login'])) {
     $_SESSION['cas_remember'] = 1;
   }
-  $_REQUEST['destination'] = 'cas';
-  drupal_redirect_form($form, 'cas');
+
+  // Force redirection.
+  unset($_REQUEST['destination']);
+  drupal_goto('cas', array('destination' => $form_state['values']['cas_destination']));
 }
 
 /*
-- 
1.7.3.5

