From 8a42cfb37a16efd6904cdfaadbf8c7dd02d427aa Mon Sep 17 00:00:00 2001
From: sun <sun@unleashedmind.com>
Date: Sun, 24 Feb 2013 16:22:01 +0100
Subject: [PATCH 1/3] Fixed missing module dependencies.

---
 masquerade.info                              | 1 +
 masquerade_advanced/masquerade_advanced.info | 1 +
 2 files changed, 2 insertions(+)

diff --git a/masquerade.info b/masquerade.info
index 1779e6e..88b1887 100644
--- a/masquerade.info
+++ b/masquerade.info
@@ -2,4 +2,5 @@ name = Masquerade
 description = Allows privileged users to masquerade as another user.
 core = 8.x
 package = Development
+dependencies[] = user
 tags[] = admin
diff --git a/masquerade_advanced/masquerade_advanced.info b/masquerade_advanced/masquerade_advanced.info
index 6d6134a..6f923a5 100644
--- a/masquerade_advanced/masquerade_advanced.info
+++ b/masquerade_advanced/masquerade_advanced.info
@@ -3,5 +3,6 @@ description = Provides per-user masquerade access, blocks, and settings.
 core = 8.x
 package = Development
 configure = admin/config/people/masquerade
+dependencies[] = masquerade
 tags[] = admin
 tags[] = dev
-- 
1.7.11.msysgit.1


From 48dc6641d43f328a38cfd79f8e7b7aecea7c761a Mon Sep 17 00:00:00 2001
From: sun <sun@unleashedmind.com>
Date: Sun, 24 Feb 2013 17:12:43 +0100
Subject: [PATCH 2/3] - #1836516 by sun: Restored Masquerade block.

---
 .../Plugin/block/block/MasqueradeBlock.php         |  69 ++++++++
 lib/Drupal/masquerade/Tests/MasqueradeTest.php     |  13 +-
 masquerade.module                                  | 186 ++++++++-------------
 masquerade.routing.yml                             |   9 +
 masquerade_advanced/masquerade_advanced.module     |   4 +-
 5 files changed, 154 insertions(+), 127 deletions(-)
 create mode 100644 lib/Drupal/masquerade/Plugin/block/block/MasqueradeBlock.php
 create mode 100644 masquerade.routing.yml

diff --git a/lib/Drupal/masquerade/Plugin/block/block/MasqueradeBlock.php b/lib/Drupal/masquerade/Plugin/block/block/MasqueradeBlock.php
new file mode 100644
index 0000000..215c664
--- /dev/null
+++ b/lib/Drupal/masquerade/Plugin/block/block/MasqueradeBlock.php
@@ -0,0 +1,69 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\masquerade\Plugin\block\block\MasqueradeBlock.
+ */
+
+namespace Drupal\masquerade\Plugin\block\block;
+
+use Drupal\block\BlockBase;
+use Drupal\Core\Annotation\Plugin;
+use Drupal\Core\Annotation\Translation;
+
+/**
+ * Provides a 'Masquerade' block.
+ *
+ * @Plugin(
+ *   id = "masquerade",
+ *   subject = @Translation("Masquerade"),
+ *   module = "masquerade",
+ *   cache = false
+ * )
+ */
+class MasqueradeBlock extends BlockBase {
+
+  /**
+   * Overrides \Drupal\block\BlockBase::settings().
+   */
+  public function DISABLEDsettings() {
+    return array(
+      'block_count' => 10,
+    );
+  }
+
+  /**
+   * Overrides \Drupal\block\BlockBase::blockAccess().
+   */
+  public function blockAccess() {
+    return user_access('masquerade') && !isset($_SESSION['masquerading']);
+  }
+
+  /**
+   * Overrides \Drupal\block\BlockBase::blockForm().
+   */
+  public function DISABLEDblockForm($form, &$form_state) {
+    $form['block_count'] = array(
+      '#type' => 'select',
+      '#title' => t('Number of recent content items to display'),
+      '#default_value' => $this->configuration['block_count'],
+      '#options' => drupal_map_assoc(array(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25, 30)),
+    );
+    return $form;
+  }
+
+  /**
+   * Overrides \Drupal\block\BlockBase::blockSubmit().
+   */
+  public function DISABLEDblockSubmit($form, &$form_state) {
+    $this->configuration['block_count'] = $form_state['values']['block_count'];
+  }
+
+  /**
+   * Implements \Drupal\block\BlockBase::build().
+   */
+  public function build() {
+    return drupal_get_form('masquerade_block_form');
+  }
+
+}
diff --git a/lib/Drupal/masquerade/Tests/MasqueradeTest.php b/lib/Drupal/masquerade/Tests/MasqueradeTest.php
index ad63d2f..da27fb8 100644
--- a/lib/Drupal/masquerade/Tests/MasqueradeTest.php
+++ b/lib/Drupal/masquerade/Tests/MasqueradeTest.php
@@ -28,18 +28,13 @@ class MasqueradeTest extends WebTestBase {
 
   public function testMasquerade() {
     $admin_perms = array(
-      'administer masquerade',
-      'masquerade as user',
+      'masquerade',
     );
     $this->admin_user = $this->drupalCreateUser($admin_perms);
     $this->web_user = $this->drupalCreateUser();
 
     $this->drupalLogin($this->admin_user);
 
-    //test admin form
-    $this->drupalGet('admin/config/people/masquerade');
-    $this->assertResponse(200);
-
     //test switch
     $this->drupalGet('masquerade/switch/' . $this->web_user->uid);
     $this->assertResponse(403);
@@ -52,11 +47,11 @@ class MasqueradeTest extends WebTestBase {
     $this->assertText('You are now masquerading as ' . $this->web_user->name);
 
     //test unswitch
-    $this->drupalGet('masquerade/unswitch');
+    $this->drupalGet('unmasquerade');
     $this->assertResponse(403);
-    $this->drupalGet('masquerade/unswitch', array(
+    $this->drupalGet('unmasquerade', array(
       'query' => array(
-        'token' => $this->drupalGetToken('masquerade/unswitch'),
+        'token' => $this->drupalGetToken('unmasquerade'),
       ),
     ));
     $this->assertResponse(200);
diff --git a/masquerade.module b/masquerade.module
index 09f3011..76fc6b3 100644
--- a/masquerade.module
+++ b/masquerade.module
@@ -49,7 +49,7 @@ function masquerade_init() {
   if ($uid) {
     $_SESSION['masquerading'] = $uid;
   }
-  else {
+  elseif (isset($_SESSION['masquerading'])) {
     unset($_SESSION['masquerading']);
   }
 }
@@ -80,37 +80,34 @@ function masquerade_menu() {
     'page arguments' => array(2),
     'access callback' => 'masquerade_menu_access',
     'access arguments' => array('switch', 2),
+    // Invoke masquerade_translated_menu_link_alter() to append token.
+    'options' => array('alter' => TRUE),
   );
-  $items['masquerade/unswitch'] = array(
-    'title' => 'Switch back',
+
+  // @todo Core: It is not possible to add this link as user/unmasquerade.
+  $items['unmasquerade'] = array(
+    'title' => 'Unmasquerade',
     'page callback' => 'masquerade_switch_back_page',
     'access callback' => 'masquerade_menu_access',
-    'access arguments' => array('unswitch'),
+    'access arguments' => array('unmasquerade'),
+    'menu_name' => 'account',
+    'weight' => 9,
+    // Invoke masquerade_translated_menu_link_alter() to append token.
+    'options' => array('alter' => TRUE),
   );
+
+  // @todo Remove once drupal_valid_path() is fixed to find and access check
+  //   paths managed by the new routing system: http://drupal.org/node/1793520
+  // @see user_menu()
   $items['masquerade/autocomplete'] = array(
-    'page callback' => 'masquerade_autocomplete',
-    'access callback' => 'masquerade_menu_access',
-    'access arguments' => array('autocomplete'),
+    'page callback' => 'NOT_USED',
+    'access arguments' => array('masquerade'),
     'type' => MENU_CALLBACK,
   );
   return $items;
 }
 
 /**
- * Implements hook_menu_alter().
- *
- * We need to add a token to the Masquerade paths to protect against CSRF
- * attacks. Since menu items in Drupal do not support dynamic elements these
- * tokens need to be added during rendering via masquerade_translated_menu_link_alter().
- * Set the 'alter'-option to TRUE to make sure
- * the links get passed through masquerade_translated_menu_link_alter.
- */
-function masquerade_menu_alter(&$items) {
-  $items['masquerade/switch/%']['options']['alter'] = TRUE;
-  $items['masquerade/unswitch']['options']['alter'] = TRUE;
-}
-
-/**
  * Implements hook_translated_menu_link_alter().
  *
  * Dynamically add the CSRF protection token to the Masquerade menu items.
@@ -121,7 +118,7 @@ function masquerade_translated_menu_link_alter(&$item, $map) {
       $item['localized_options']['query']['token'] = drupal_get_token('masquerade/switch/' . $map[2]);
     }
     elseif ($item['page_callback'] == 'masquerade_switch_back_page') {
-      $item['localized_options']['query']['token'] = drupal_get_token('masquerade/unswitch');
+      $item['localized_options']['query']['token'] = drupal_get_token('unmasquerade');
     }
   }
 }
@@ -152,7 +149,7 @@ function masquerade_user_operations_masquerade(array $accounts) {
  * Determine if the current user has permission to switch users.
  *
  * @param string $type
- *   Either 'switch', 'unswitch', 'user', or 'autocomplete'.
+ *   Either 'switch', 'unmasquerade', 'user', or 'autocomplete'.
  *
  * @param object $uid
  *   An optional parameter indicating a specific uid to switch to.
@@ -162,11 +159,8 @@ function masquerade_user_operations_masquerade(array $accounts) {
  */
 function masquerade_menu_access($type, $uid = NULL) {
   switch ($type) {
-    case 'unswitch':
-      return isset($_SESSION['masquerading']) || arg(2) == 'menu-customize' || arg(2) == 'menu';
-
-    case 'autocomplete':
-      return isset($_SESSION['masquerading']) || user_access('masquerade');
+    case 'unmasquerade':
+      return isset($_SESSION['masquerading']);
 
     case 'switch':
       return !isset($_SESSION['masquerading']) && user_access('masquerade');
@@ -210,68 +204,26 @@ function masquerade_user_view($account, $view_mode, $langcode) {
 }
 
 /**
- * Implements hook_block_info().
- */
-function masquerade_block_info() {
-  $blocks['masquerade'] = array(
-    'info' => t('Masquerade'),
-    'cache' => DRUPAL_NO_CACHE,
-  );
-  return $blocks;
-}
-
-/**
- * Implements hook_block_view().
- */
-function masquerade_block_view($delta = '') {
-  $block = array();
-  switch ($delta) {
-    case 'masquerade':
-      if (isset($_SESSION['masquerading']) || user_access('masquerade')) {
-        $block['subject'] = t('Masquerade');
-        $block['content'] = drupal_get_form('masquerade_block_1');
-      }
-      break;
-  }
-  return $block;
-}
-
-/**
  * Masquerade block form.
  */
-function masquerade_block_1() {
-  global $user;
-  $quick_switch_links = array();
-  $markup_value = '';
-  if (isset($_SESSION['masquerading'])) {
-    $quick_switch_links[] = l(t('Switch back'), 'masquerade/unswitch', array('query' => array('token' => drupal_get_token('masquerade/unswitch'))));
-    $markup_value = t('You are masquerading as <a href="@user-url">%masq_as</a>.', array('@user-url' => url('user/' . $user->uid), '%masq_as' => $user->name));
-  }
-  else {
-    if (masquerade_menu_access('autocomplete')) {
-      $markup_value .= t('Enter the username to masquerade as.');
-      $form['masquerade_user_field'] = array(
-        '#prefix' => '<div class="container-inline">',
-        '#type' => 'textfield',
-        '#size' => '18',
-        '#default_value' => '',
-        '#autocomplete_path' => 'masquerade/autocomplete',
-        '#required' => TRUE,
-      );
-      $form['submit'] = array(
-        '#type' => 'submit',
-        '#value' => t('Go'),
-        '#suffix' => '</div>',
-      );
-    }
-  }
-  if ($quick_switch_links) {
-    $markup_value .= theme('item_list', array('items' => $quick_switch_links));
-  }
-  $form['masquerade_desc'] = array(
-    '#prefix' => '<div class="form-item"><div class="description">',
-    '#markup' => $markup_value,
-    '#suffix' => '</div></div>',
+function masquerade_block_form() {
+  $form['autocomplete'] = array(
+    '#type' => 'container',
+    '#attributes' => array('class' => array('container-inline')),
+  );
+  $form['autocomplete']['masquerade_as'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Username'),
+    '#title_display' => 'invisible',
+    '#required' => TRUE,
+    '#placeholder' => t('Masquerade as…'),
+    '#size' => '18',
+    '#autocomplete_path' => 'masquerade/autocomplete',
+  );
+  $form['autocomplete']['actions'] = array('#type' => 'actions');
+  $form['autocomplete']['actions']['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Switch'),
   );
   return $form;
 }
@@ -279,32 +231,44 @@ function masquerade_block_1() {
 /**
  * Masquerade block form validation.
  */
-function masquerade_block_1_validate($form, &$form_state) {
+function masquerade_block_form_validate($form, &$form_state) {
   global $user;
-  $name = $form_state['values']['masquerade_user_field'];
+
   if (isset($_SESSION['masquerading'])) {
-    form_set_error('masquerade_user_field', t('You are already masquerading. Please <a href="@unswitch">switch back</a> to your account to masquerade as another user.', array('@unswitch' => url('masquerade/unswitch', array('query' => array('token' => drupal_get_token('masquerade/unswitch')))))));
+    form_set_error('masquerade_as', t('You are masquerading already. Please <a href="@unmasquerade-url">switch back</a> to your account to masquerade as another user.', array(
+      '@unmasquerade-url' => url('unmasquerade', array(
+        'query' => array('token' => drupal_get_token('unmasquerade')),
+      )),
+    )));
+    return;
   }
 
-  $masq_user = user_load_by_name($name);
-  if (!$masq_user) {
-    form_set_error('masquerade_user_field', t('User %masq_as does not exist. Please enter a valid username.', array('%masq_as' => $form_state['values']['masquerade_user_field'])));
+  $name = $form_state['values']['masquerade_as'];
+  $target_user = user_load_by_name($name);
+  if (!$target_user) {
+    form_set_error('masquerade_as', t('The username %taret_user does not exist. Please enter a valid username.', array(
+      '%target_user' => $name,
+    )));
   }
-  elseif ($masq_user->uid == $user->uid) {
-    form_set_error('masquerade_user_field', t('You cannot masquerade as yourself. Please choose a different user to masquerade as.'));
+  elseif ($target_user->uid == $user->uid) {
+    form_set_error('masquerade_as', t('You cannot masquerade as yourself. Please choose a different user to masquerade as.'));
   }
-  elseif (variable_get('maintenance_mode', 0) && !user_access('access site in maintenance mode', $masq_user)) {
-    form_set_error('masquerade_user_field', t('It is not possible to masquerade in off-line mode as !user does not have the %config-perm permission. Please <a href="@site-maintenance">set the site status</a> to "online" to masquerade as !user.', array('!user' => theme('username', array('account' => $masq_user)), '%config-perm' => 'use the site in maintenance mode', '@site-maintenance' => url('admin/settings/site-maintenance'))));
+  elseif (variable_get('maintenance_mode', 0) && !user_access('access site in maintenance mode', $target_user)) {
+    form_set_error('masquerade_as', t('!user is not permitted to %permission. <a href="@maintenance-url">Disable maintenance mode</a> to masquerade as !user.', array(
+      '!user' => theme('username', array('account' => $target_user)),
+      '%permission' => t('Use the site in maintenance mode'),
+      '@maintenance-url' => url('admin/config/development/maintenance'),
+    )));
   }
   else {
-    $form_state['masquerade_target_user'] = $masq_user;
+    $form_state['masquerade_target_user'] = $target_user;
   }
 }
 
 /**
  * Masquerade block form submission.
  */
-function masquerade_block_1_submit($form, &$form_state) {
+function masquerade_block_form_submit($form, &$form_state) {
   if (!masquerade_switch_user($form_state['masquerade_target_user']->uid)) {
     throw new AccessDeniedHttpException();
   }
@@ -314,20 +278,6 @@ function masquerade_block_1_submit($form, &$form_state) {
 }
 
 /**
- * Returns JS array for Masquerade autocomplete fields.
- */
-function masquerade_autocomplete($string) {
-  $matches = array();
-  $result = db_query_range("SELECT name FROM {users} WHERE LOWER(name) LIKE LOWER(:string)", 0, 10, array(
-    ':string' => $string . '%',
-  ));
-  foreach ($result as $user) {
-    $matches[$user->name] = check_plain($user->name);
-  }
-  return new JsonResponse($matches);
-}
-
-/**
  * Page callback to switch users.
  */
 function masquerade_switch_user_page($uid) {
@@ -430,7 +380,7 @@ function masquerade_masquerade_access($user, $target_user) {
  */
 function masquerade_switch_back_page() {
   $token = drupal_container()->get('request')->query->get('token');
-  if (isset($token) && drupal_valid_token($token, 'masquerade/unswitch')) {
+  if (isset($token) && drupal_valid_token($token, 'unmasquerade')) {
     global $user;
     $olduser = $user;
     masquerade_switch_back();
@@ -447,10 +397,11 @@ function masquerade_switch_back_page() {
  */
 function masquerade_switch_back() {
   global $user;
-  $uid = db_query("SELECT m.uid_from FROM {masquerade} m WHERE m.sid = :sid AND m.uid_as = :uid_as ", array(
+  $uid = db_query('SELECT uid_from FROM {masquerade} WHERE sid = :sid AND uid_as = :uid_as', array(
     ':sid' => session_id(),
     ':uid_as' => $user->uid,
   ))->fetchField();
+
   // Clean-up session masquerate.
   db_delete('masquerade')
     ->condition('sid', session_id())
@@ -467,5 +418,8 @@ function masquerade_switch_back() {
   // Call all login hooks when switching back to original user.
   module_invoke_all('user_login', $user);
 
+  // Remove the masquerading flag from the user's session.
+  unset($_SESSION['masquerading']);
+
   watchdog('masquerade', 'User %user no longer masquerading as %masq_as.', array('%user' => $user->name, '%masq_as' => $oldname), WATCHDOG_INFO);
 }
diff --git a/masquerade.routing.yml b/masquerade.routing.yml
new file mode 100644
index 0000000..d03709d
--- /dev/null
+++ b/masquerade.routing.yml
@@ -0,0 +1,9 @@
+# Only difference to /user/autocomplete is the access permission; Users that are
+# allowed to masquerade do not necessarily need to have access to view user
+# profiles.
+masquerade_autocomplete:
+  pattern: '/masquerade/autocomplete'
+  defaults:
+    _controller: 'user.autocomplete_controller:autocompleteUser'
+  requirements:
+    _permission: 'masquerade'
diff --git a/masquerade_advanced/masquerade_advanced.module b/masquerade_advanced/masquerade_advanced.module
index de5fbab..b3e62bf 100644
--- a/masquerade_advanced/masquerade_advanced.module
+++ b/masquerade_advanced/masquerade_advanced.module
@@ -88,7 +88,7 @@ function masquerade_advanced_menu_alter(&$items) {
  * Determine if the current user has permission to switch users.
  *
  * @param string $type
- *   Either 'switch', 'unswitch', 'user', or 'autocomplete'.
+ *   Either 'switch' or 'user'.
  *
  * @param object $uid
  *   An optional parameter indicating a specific uid to switch to.
@@ -336,7 +336,7 @@ function masquerade_advanced_user_delete($account) {
 /**
  * Implements hook_form_FORMID_alter().
  */
-function masquerade_advanced_form_masquerade_block_1_alter(&$form, &$form_state) {
+function masquerade_advanced_form_masquerade_block_form_alter(&$form, &$form_state) {
   global $user;
 
   if (isset($_SESSION['masquerading'])) {
-- 
1.7.11.msysgit.1


From 26029f8539368d8527c5fde40dd29e140b1c6458 Mon Sep 17 00:00:00 2001
From: sun <sun@unleashedmind.com>
Date: Sun, 24 Feb 2013 18:05:54 +0100
Subject: [PATCH 3/3] - #1836516 by sun: Fixed tests via helper methods to
 work around drupalGetToken() core bug.

---
 lib/Drupal/masquerade/Tests/MasqueradeTest.php | 85 +++++++++++++++++++++-----
 1 file changed, 70 insertions(+), 15 deletions(-)

diff --git a/lib/Drupal/masquerade/Tests/MasqueradeTest.php b/lib/Drupal/masquerade/Tests/MasqueradeTest.php
index da27fb8..88f19fe 100644
--- a/lib/Drupal/masquerade/Tests/MasqueradeTest.php
+++ b/lib/Drupal/masquerade/Tests/MasqueradeTest.php
@@ -8,11 +8,14 @@
 namespace Drupal\masquerade\Tests;
 
 use Drupal\simpletest\WebTestBase;
+use Drupal\user\Plugin\Core\Entity\User;
 
 /**
  * Tests form permissions and user switching functionality.
  *
- * Requires Drupal core fix from http://drupal.org/node/1555862
+ * @todo Core: $this->session_id is reset to NULL upon every internal browser
+ *   request.
+ * @see http://drupal.org/node/1555862
  */
 class MasqueradeTest extends WebTestBase {
 
@@ -26,44 +29,96 @@ class MasqueradeTest extends WebTestBase {
     );
   }
 
-  public function testMasquerade() {
-    $admin_perms = array(
-      'masquerade',
-    );
-    $this->admin_user = $this->drupalCreateUser($admin_perms);
+  function testMasquerade() {
+    $this->admin_user = $this->drupalCreateUser(array('masquerade'));
     $this->web_user = $this->drupalCreateUser();
 
     $this->drupalLogin($this->admin_user);
 
-    //test switch
+    // Verify that a token is required.
+    $this->drupalGet('masquerade/switch/');
+    $this->assertResponse(404);
+    $this->drupalGet('masquerade/switch/0');
+    $this->assertResponse(403);
     $this->drupalGet('masquerade/switch/' . $this->web_user->uid);
     $this->assertResponse(403);
-    $this->drupalGet('masquerade/switch/' . $this->web_user->uid, array(
+
+    // Verify that the admin user is able to masquerade.
+    $this->masqueradeAs($this->web_user);
+
+    // Verify that a token is required to unmasquerade.
+    $this->drupalGet('unmasquerade');
+    $this->assertResponse(403);
+
+    // Verify that the web user cannot masquerade.
+    $this->drupalGet('masquerade/switch/' . $this->admin_user->uid, array(
       'query' => array(
-        'token' => $this->drupalGetToken('masquerade/switch/' . $this->web_user->uid),
+        'token' => $this->drupalGetToken('masquerade/switch/' . $this->admin_user->uid),
+      ),
+    ));
+    $this->assertResponse(403);
+
+    // Verify that the user can unmasquerade.
+    $this->unmasquerade($this->web_user);
+  }
+
+  /**
+   * Masquerades as another user.
+   *
+   * @param \Drupal\user\Plugin\Core\Entity\User $account
+   *   The user account to masquerade as.
+   */
+  protected function masqueradeAs(User $account) {
+    $this->drupalGet('masquerade/switch/' . $account->uid, array(
+      'query' => array(
+        'token' => $this->drupalGetToken('masquerade/switch/' . $account->uid),
       ),
     ));
     $this->assertResponse(200);
-    $this->assertText('You are now masquerading as ' . $this->web_user->name);
+    $this->assertText('You are now masquerading as ' . $account->name);
 
-    //test unswitch
-    $this->drupalGet('unmasquerade');
-    $this->assertResponse(403);
+    // Update the logged in user account.
+    // @see WebTestBase::drupalLogin()
+    if (isset($this->session_id)) {
+      $this->loggedInUser = $account;
+      $this->loggedInUser->session_id = $this->session_id;
+    }
+  }
+
+  /**
+   * Unmasquerades the current user.
+   *
+   * @param \Drupal\user\Plugin\Core\Entity\User $account
+   *   The user account to unmasquerade from.
+   */
+  protected function unmasquerade(User $account) {
     $this->drupalGet('unmasquerade', array(
       'query' => array(
         'token' => $this->drupalGetToken('unmasquerade'),
       ),
     ));
     $this->assertResponse(200);
-    $this->assertText('You are no longer masquerading as ' . $this->web_user->name);
+    $this->assertText('You are no longer masquerading as ' . $account->name);
+
+    // Update the logged in user account.
+    // @see WebTestBase::drupalLogin()
+    if (isset($this->session_id)) {
+      $this->loggedInUser = $account;
+      $this->loggedInUser->session_id = $this->session_id;
+    }
   }
 
   /**
+   * Stop-gap fix.
+   *
    * @see http://drupal.org/node/1555862
    */
   protected function drupalGetToken($value = '') {
     $private_key = drupal_get_private_key();
-    return drupal_hmac_base64($value, $this->session_id . $private_key . drupal_get_hash_salt());
+    // Use the session_id assigned by WebTestBase::drupalLogin() instead of
+    // $this->session_id until the core bug is fixed.
+    $session_id = isset($this->loggedInUser->session_id) ? $this->loggedInUser->session_id : '';
+    return drupal_hmac_base64($value, $session_id . $private_key . drupal_get_hash_salt());
   }
 }
 
-- 
1.7.11.msysgit.1

