diff -Npur page_manager_redirect2/page_manager_redirect.info page_manager_redirect/page_manager_redirect.info
--- page_manager_redirect2/page_manager_redirect.info	1970-01-01 01:00:00.000000000 +0100
+++ page_manager_redirect/page_manager_redirect.info	2010-06-07 09:24:08.000000000 +0100
@@ -0,0 +1,4 @@
+name = Page Manager Redirect
+description = Adds a new variant type to page manager, to redirect to a specified URL
+dependencies[] = page_manager
+core = 6.x
\ No newline at end of file
diff -Npur page_manager_redirect2/pages/task_handlers/redirect_context.inc page_manager_redirect/pages/task_handlers/redirect_context.inc
--- page_manager_redirect2/pages/task_handlers/redirect_context.inc	1970-01-01 01:00:00.000000000 +0100
+++ page_manager_redirect/pages/task_handlers/redirect_context.inc	2010-06-07 09:24:55.000000000 +0100
@@ -0,0 +1,533 @@
+<?php
+/**
+ * @file
+ *
+ * This is the task handler plugin to handle page redirecting based on context.
+ */
+
+// Plugin definition
+$plugin = array(
+  // is a 'context' handler type, meaning it supports the API of the
+  // context handlers provided by ctools context plugins.
+  'handler type' => 'context',
+  'visible' => TRUE, // may be added up front.
+
+  // Administrative fields.
+  'title' => t('Redirect'),
+  'admin summary' =>'page_manager_redirect_redirect_context_admin_summary',
+  'admin title' => 'page_manager_redirect_redirect_context_title',
+  'admin css' => array(
+    panels_get_path('css/panels_admin.css'),
+  ),
+  'admin js' => array(
+    panels_get_path('js/layout.js'),
+  ),
+  'operations' => array(
+    'settings' => array(
+      'title' => t('Settings'),
+      'description' => t('Change general settings about this variant.'),
+      'form' => 'page_manager_redirect_redirect_context_edit_settings',
+    ),
+    'criteria' => array(
+      'title' => t('Selection rules'),
+      'description' => t('Control the criteria used to decide whether or not this variant is used.'),
+      'ajax' => FALSE,
+      'form' => array(
+        'order' => array(
+          'form' => t('Selection rules'),
+        ),
+        'forms' => array(
+          'form' => array(
+            'include' => drupal_get_path('module', 'ctools') . '/includes/context-task-handler.inc',
+            'form id' => 'ctools_context_handler_edit_criteria',
+          ),
+        ),
+      ),
+    ),
+    'context' => array(
+      'title' => t('Contexts'),
+      'ajax' => FALSE,
+      'description' => t('Add additional context objects to this variant that can be used by the content.'),
+      'form' => array(
+        'order' => array(
+          'form' => t('Context'),
+        ),
+        'forms' => array(
+          'form' => array(
+            'include' => drupal_get_path('module', 'ctools') . '/includes/context-task-handler.inc',
+            'form id' => 'ctools_context_handler_edit_context',
+          ),
+        ),
+      ),
+    ),
+    'preview' => array(
+      'title' => t('Preview'),
+      'description' => t('Get a preview of what this variant will look like.'),
+      'form' => 'page_manager_redirect_redirect_context_edit_preview',
+      'ajax' => FALSE,
+      'silent' => TRUE,
+      'form info' => array('finish text' => t('Preview')),
+    ),
+  ),
+
+  // Callback to render the data.
+  'render' => 'page_manager_redirect_redirect_context_render',
+
+  // Various callbacks for operations performed on the handler to ensure
+  // related data is updated properly.
+  'save' => 'page_manager_redirect_redirect_context_save',
+  'delete' => 'page_manager_redirect_redirect_context_delete',
+  'export' => 'page_manager_redirect_redirect_context_export',
+  'clone' => 'page_manager_redirect_redirect_context_clone',
+
+  'add features' => array(
+    'criteria' => t('Selection rules'),
+    'context' => t('Contexts'),
+  ),
+  // Where to go when finished.
+  'add finish' => 'settings',
+
+  'required forms' => array(
+    'settings' => t('Configure settings'),
+  ),
+
+  'edit forms' => array(
+    'criteria' => t('Selection rules'),
+    'settings' => t('Settings'),
+    'context' => t('Contexts'),
+  ),
+  'forms' => array(
+    'settings' => array(
+      'form id' => 'page_manager_redirect_redirect_context_edit_settings',
+    ),
+    'context' => array(
+      'include' => drupal_get_path('module', 'ctools') . '/includes/context-task-handler.inc',
+      'form id' => 'ctools_context_handler_edit_context',
+    ),
+    'criteria' => array(
+      'include' => drupal_get_path('module', 'ctools') . '/includes/context-task-handler.inc',
+      'form id' => 'ctools_context_handler_edit_criteria',
+    ),
+  ),
+  'default conf' => array(
+    'title' => t('Redirect'),
+    'contexts' => array(),
+    'relationships' => array(),
+  ),
+);
+
+/**
+ * Get the display for a task handler.
+ *
+ * There are three methods that the display can be found.
+ * - In the database. $handler->conf['did'] will be set in this case,
+ *   and $handler->conf['display'] won't be.
+ * - In $handler->conf['display'], with $handler->conf['did'] empty. This
+ *   will be true for a default/imported task handler as well as a handler
+ *   that has just been created but has not yet been saved.
+ * - in $handler->conf['display'] with $handler->conf['did' populated. This
+ *   simply means that the display has been modified and is awaiting
+ *   save. The modified one should always be used for editing purposes.
+ * - If none of the above is true, then a new display needs to be created
+ *   for the handler and pla
+ */
+function &page_manager_redirect_redirect_context_get_display(&$handler) {
+  if (isset($handler->conf['display'])) {
+    if (!isset($handler->conf['display']->redirect)) {
+      $handler->conf['display']->redirect = page_manager_redirect_redirect_context_get_redirection($handler);
+    }
+    return $handler->conf['display'];
+  }
+
+  if (isset($handler->conf['did'])) {
+    $handler->conf['display'] = panels_load_display($handler->conf['did']);
+
+    // Check for a valid display. If no valid display can be loaded, something
+    // is wrong and we'll create a new one.
+    if (!empty($handler->conf['display'])) {
+      if (!isset($handler->conf['display']->redirect)) {
+        $handler->conf['display']->redirect = page_manager_redirect_redirect_context_get_redirection($handler);
+      }
+      return $handler->conf['display'];
+    }
+  }
+
+  $handler->conf['display'] = panels_new_display();
+  $handler->conf['display']->redirect = page_manager_redirect_redirect_context_get_redirection($handler);
+
+  return $handler->conf['display'];
+}
+
+function page_manager_redirect_redirect_context_get_redirection($handler) {
+  return array(
+    'path' => $handler->conf['path'],
+    'query' => $handler->conf['query'],
+    'fragment' => $handler->conf['fragment'],
+  );
+}
+
+/**
+ * Check selection rules and, if passed, render the contexts.
+ *
+ * We must first check to ensure the node is of a type we're allowed
+ * to render. If not, decline to render it by returning NULL.
+ */
+function page_manager_redirect_redirect_context_render($handler, $base_contexts, $args, $test = TRUE) {
+  // Go through arguments and see if they match.
+  ctools_include('context');
+  ctools_include('context-task-handler');
+  // Add my contexts
+  $contexts = ctools_context_handler_get_handler_contexts($base_contexts, $handler);
+
+  // Test.
+  if ($test && !ctools_context_handler_select($handler, $contexts)) {
+    return;
+  }
+
+  if (isset($handler->handler)) {
+    ctools_context_handler_pre_render($handler, $contexts, $args);
+  }
+
+  // Load the display
+  $display = page_manager_redirect_redirect_context_get_display($handler);
+
+  $display->context = $contexts;
+  $display->args = $args;
+
+  // With an argument, this actually sets the display.
+  panels_get_current_page_display($display);
+
+  $info = array(
+    'content' => page_manager_redirect_redirect_context_render_display($display),
+  );
+
+  $info['title'] = panels_display_get_title($display); /** TODO: Check this returns something appropriate. **/
+
+  return $info;
+}
+
+/**
+ * Callback to allow the handler to react to being saved.
+ *
+ * When a handler with a display is saved, two things have to happen.
+ * First, we have to save the display so that it becomes a real display,
+ * not the fake one we started with. Second, we have to cache
+ * any CSS that the display is using. This CSS can get re-cached
+ * later if the file disappears, but it's imperative that we do it here
+ * to make sure that old, dirty CSS cache gets removed.
+ */
+function page_manager_redirect_redirect_context_save(&$handler, $update) {
+  // Only save the display if we believe it has been modified.
+  if (isset($handler->conf['display'])) {
+    panels_save_display($handler->conf['display']);
+    $handler->conf['did'] = $handler->conf['display']->did;
+    unset($handler->conf['display']);
+  }
+}
+
+/**
+ * Special handling for exporting a panel task handler.
+ *
+ * When a panel is exported, we need to export the display separately
+ * rather than just letting its object be unpacked, which does not work
+ * very well.
+ */
+function page_manager_redirect_redirect_context_export(&$handler, $indent) {
+  $display = page_manager_redirect_redirect_context_get_display($handler);
+  foreach (array('display', 'did') as $item) {
+    if (isset($handler->conf[$item])) {
+      unset($handler->conf[$item]);
+    }
+  }
+
+  $output = panels_export_display($display, $indent);
+  $output .= $indent . '$handler->conf[\'display\'] = $display' . ";\n";
+  return $output;
+}
+
+/**
+ * When a handler is cloned, we have to clone the display.
+ */
+  function page_manager_redirect_redirect_context_clone(&$handler) {
+  $old_display = page_manager_redirect_redirect_context_get_display($handler);
+  $code = panels_export_display($old_display);
+  eval($code);
+  foreach (array('display', 'did') as $item) {
+    if (isset($handler->conf[$item])) {
+      unset($handler->conf[$item]);
+    }
+  }
+  $display->did = 'new';
+  $handler->conf['display'] = $display;
+}
+
+/**
+ * Callback to delete the display when a handler is deleted.
+ */
+function page_manager_redirect_redirect_context_delete(&$handler) {
+  if (!empty($handler->conf['did'])) {
+    panels_delete_display($handler->conf['did']);
+  }
+}
+
+/**
+ * Set up a title for the panel based upon the selection rules.
+ */
+function page_manager_redirect_redirect_context_title($handler, $task, $subtask) {
+  if (isset($handler->conf['title'])) {
+    return check_plain($handler->conf['title']);
+  }
+  else {
+    return t('Redirect');
+  }
+}
+
+/**
+ * Provide a nice little summary of what's in a panel.
+ *
+ * The task handler manager provides a summary of a given handler in a
+ * collapsible div. This callback provides that. For Redirects, we
+ * provide a summary of the redirect on one side, and
+ * a summary of the contexts in use on the other.
+ */
+function page_manager_redirect_redirect_context_admin_summary($handler, $task, $subtask, $page, $show_title = TRUE) {
+  $task_name = page_manager_make_task_name($task['name'], $subtask['name']);
+  $output = '';
+
+  $display = page_manager_redirect_redirect_context_get_display($handler);
+
+  panels_load_include('plugins');
+  ctools_include('context');
+  ctools_include('context-task-handler');
+
+  // Get the operations
+  $operations = page_manager_get_operations($page);
+
+  // Get operations for just this handler.
+  $operations = $operations['handlers']['children'][$handler->name]['children']['actions']['children'];
+  $args = array('handlers', $handler->name, 'actions');
+  $rendered_operations = page_manager_render_operations($page, $operations, array(), array('class' => 'actions'), 'actions', $args);
+
+  $plugin = page_manager_get_task_handler($handler->handler);
+
+  $object = ctools_context_handler_get_task_object($task, $subtask, $handler);
+  $display->context = ctools_context_load_contexts($object, TRUE);
+
+  $access = ctools_access_group_summary(!empty($handler->conf['access']) ? $handler->conf['access'] : array(), $display->context);
+  if ($access) {
+    $access = t('This panel will be selected if @conditions.', array('@conditions' => $access));
+  }
+  else {
+    $access = t('This panel will always be selected.');
+  }
+
+  $rows = array();
+
+  $type = $handler->type == t('Default') ? t('In code') : $handler->type;
+  $rows[] = array(
+    array('class' => t('page-summary-label'), 'data' => t('Storage')),
+    array('class' => t('page-summary-data'), 'data' => $type),
+    array('class' => t('page-summary-operation'), 'data' => ''),
+  );
+
+  if (!empty($handler->disabled)) {
+    $link = l(t('Enable'), page_manager_edit_url($task_name, array('handlers', $handler->name, 'actions', 'enable')));
+    $text = t('Disabled');
+  }
+  else {
+    $link = l(t('Disable'), page_manager_edit_url($task_name, array('handlers', $handler->name, 'actions', 'disable')));
+    $text = t('Enabled');
+  }
+
+  $rows[] = array(
+    array('class' => t('page-summary-label'), 'data' => t('Status')),
+    array('class' => t('page-summary-data'), 'data' => $text),
+    array('class' => t('page-summary-operation'), 'data' => $link),
+  );
+
+  $link = l(t('Edit'), page_manager_edit_url($task_name, array('handlers', $handler->name, 'criteria')));
+  $rows[] = array(
+    array('class' => t('page-summary-label'), 'data' => t('Selection rule')),
+    array('class' => t('page-summary-data'), 'data' => $access),
+    array('class' => t('page-summary-operation'), 'data' => $link),
+  );
+
+  $link = l(t('Edit'), page_manager_edit_url($task_name, array('handlers', $handler->name, 'settings')));
+  $options = array('query' => $handler->conf['query'], 'fragment' => $handler->conf['fragment']);
+  $url = url($handler->conf['path'], $options);
+  $url_linked = l(check_plain($url), $handler->conf['path'], $options);
+
+  $rows[] = array(
+    array('class' => t('page-summary-label'), 'data' => t('Redirect URL')),
+    array('class' => t('page-summary-data'), 'data' => $url_linked),
+    array('class' => t('page-summary-operation'), 'data' => $link),
+  );
+
+  $info = theme('table', array(), $rows, array('class' => 'page-manager-handler-summary'));
+
+  $title = $handler->conf['title'];
+  if ($title != t('Redirect')) {
+    $title = t('Redirect: @title', array('@title' => $title));
+  }
+
+  $output .= '<div class="clear-block">';
+  if ($show_title) {
+  $output .= '<div class="handler-title clear-block">';
+    $output .= '<div class="actions handler-actions">' . $rendered_operations['actions'] . '</div>';
+    $output .= '<span class="title-label">' . $title . '</span>';
+  }
+
+  $output .= '</div>';
+  $output .= $info;
+  $output .= '</div>';
+
+  return $output;
+}
+
+// --------------------------------------------------------------------------
+// Forms
+
+/**
+ * General notes about forms: The handler is automatically cached by the form
+ * wizard, so anything we store on $form_state['handler'] anywhere will get
+ * saved and appear on the next form. The cache is a 'working' cache and
+ * if the user hits cancel on any page of the multi-page wizard, all
+ * changes since the last 'update/finish' click will be flushed away.
+ *
+ * Many of the Panels forms call through to the real Panels cousins. These
+ * forms are smart enough to know that they're being wrapped in another
+ * form and act appropriately. Some of them are so smart that we just let
+ * their submit and validate handlers do the work rather than writing
+ * additional ones here.
+ */
+
+/**
+ * General settings for the panel
+ */
+function page_manager_redirect_redirect_context_edit_settings(&$form, &$form_state) {
+  $conf = $form_state['handler']->conf;
+  $form['conf']['title'] = array(
+    '#type' => 'textfield',
+    '#default_value' => $conf['title'],
+    '#title' => t('Administrative title'),
+    '#description' => t('Administrative title of this variant.'),
+  );
+
+  $form['conf']['contexts'] = array(
+    '#type' => 'markup',
+    '#value' => '<p>You may use context keywords in the fields below. Refer to the Contexts tab for details of these. <br />You may surround keywords with spaces to delimit them. For example: <em>filters=tid:<strong> %term:tid </strong>type:news</em>.</p>'
+  );
+
+  $form['conf']['path'] = array(
+    '#type' => 'textfield',
+    '#default_value' => $conf['path'],
+    '#title' => t('URL path to redirect to'),
+    '#description' => t('A Drupal path or a full URL that the user will be redirected if this variant is selected. Include the protocol (e.g. <em>http://</em>) for full URLs.'),
+  );
+
+  $form['conf']['query'] = array(
+    '#type' => 'textfield',
+    '#default_value' => $conf['query'],
+    '#title' => t('Query string'),
+    '#description' => t('A query string component for the redirection, if any.'),
+  );
+
+  $form['conf']['fragment'] = array(
+    '#type' => 'textfield',
+    '#default_value' => $conf['fragment'],
+    '#title' => t('Anchor name'),
+    '#description' => t('A destination fragment identifier for the redirection. This may mark a place on a page to skip to (e.g. <em>#section3</em>)'),
+  );
+}
+
+/**
+ * Submit handler for general settings form.
+ */
+function page_manager_redirect_redirect_context_edit_settings_submit(&$form, &$form_state) {
+  $form_state['handler']->conf['title'] = $form_state['values']['title'];
+  $form_state['handler']->conf['path'] = $form_state['values']['path'];
+  $form_state['handler']->conf['query'] = $form_state['values']['query'];
+  $form_state['handler']->conf['fragment'] = $form_state['values']['fragment'];
+}
+
+/**
+ * Form to show a nice preview.
+ */
+function page_manager_redirect_redirect_context_edit_preview(&$form, &$form_state) {
+  ctools_include('context');
+  ctools_include('context-task-handler');
+
+  $contexts = ctools_context_handler_get_all_contexts($form_state['task'], $form_state['subtask'], $form_state['handler']);
+  $form['preview'] = array();
+  ctools_context_replace_form($form['preview'], $contexts);
+
+  // automatically preview if there are no argument placeholders.
+  if (empty($form['preview'])) {
+    $display = page_manager_redirect_redirect_context_get_display($form_state['handler']);
+    $display->context = $contexts;
+    $output = page_manager_redirect_redirect_context_render_display($display, TRUE);
+    if (isset($form['buttons'])) {
+      unset($form['buttons']);
+    }
+  }
+  else {
+    $form['preview']['#tree'] = TRUE;
+    $form_state['contexts'] = $contexts;
+  }
+
+  if (!empty($output)) {
+    $form['output'] = array(
+      '#value' => $output,
+    );
+  }
+
+  $form_state['do not cache'] = TRUE;
+}
+
+/**
+ * Display a preview upon submit if arguments were needed.
+ */
+function page_manager_redirect_redirect_context_edit_preview_submit(&$form, &$form_state) {
+  $display = page_manager_redirect_redirect_context_get_display($form_state['handler']);
+  $display->context = ctools_context_replace_placeholders($form_state['contexts'], $form_state['values']['preview']);
+
+  $form_state['content'] = page_manager_redirect_redirect_context_render_display($display, TRUE); // Instead of panels_render_display().
+  $form_state['redirect'] = FALSE;
+  $form_state['rerender'] = TRUE;
+}
+
+/**
+ * 'Render' a redirect display by simply redirecting.
+ *
+ * if $incoming_content is NULL, default content will be applied. Use
+ * an empty string to indicate no content.
+ * @render
+ * @ingroup hook_invocations
+ */
+function page_manager_redirect_redirect_context_render_display(&$display, $preview = FALSE) {
+  panels_load_include('display-render');
+  panels_load_include('plugins');
+  ctools_include('context');
+
+  if (is_array($display->redirect)) {
+    foreach ($display->redirect as $part => $value) {
+      $replaced = check_plain(ctools_context_keyword_substitute($value, array(), $display->context));
+      // Remove spaces - this will allow spaces to be used to delimit the context 'tokens' that need to be replaced!
+      $display->redirect[$part] = str_replace(' ', '', $replaced);
+    }
+  }
+
+  if ($preview) {
+    $options = array('query' => $display->redirect['query'], 'fragment' => $display->redirect['fragment']);
+    $url = url($display->redirect['path'], $options);
+    $url_linked = l(check_plain($url), $display->redirect['path'], $options);
+
+    $output = '<p>The user will be redirected to:</p>';
+    $output .= '<p>' . $url_linked . '</p>';
+
+    return $output;
+  }
+  else {
+    drupal_goto($display->redirect['path'], $display->redirect['query'], $display->redirect['fragment']);
+  }
+}
