--- path_redirect.module	2008-01-19 13:51:06.000000000 -0600
+++ path_redirect.module	2008-01-21 15:58:07.000000000 -0600
@@ -33,7 +33,10 @@ function path_redirect_init() {
     $query = preg_replace('/^q=([^&]*).*$/', '\1', $_SERVER['QUERY_STRING']);
   }
   $r = db_fetch_object(db_query("SELECT redirect, query, fragment, type FROM {path_redirect} WHERE path = '%s' OR path = '%s'", $query, utf8_encode($query)));
-  if ($r) {
+  if ($r && variable_get('path_redirect_allow_bypass', 0) && $_GET['redirect'] !== 'no') {
+    if (variable_get('path_redirect_nodeapi_enabled', 0)) {
+      drupal_set_message(t('This page has been moved. You may want to update your bookmarks.'));
+    }
     if (function_exists('drupal_goto')) {
       // if there's a result found, do the redirect
       unset($_REQUEST['destination']);
@@ -44,6 +47,9 @@ function path_redirect_init() {
       path_redirect_goto($r->redirect, ($r->query ? $r->query: NULL), ($r->fragment ? $r->fragment : NULL), $r->type);
     }
   }
+  else if ($r && variable_get('path_redirect_allow_bypass', 0) && $_GET['redirect'] === 'no') {
+    drupal_set_message(t('This page is redirected to:'). ' <code>'.  l($r->redirect, $r->redirect, ($r->query ? $r->query: NULL), ($r->fragment ? $r->fragment : NULL)). '</code>');
+  }
 }
 
 /**
@@ -75,6 +81,14 @@ function path_redirect_menu($may_cache) 
       'weight' => 2,
       'type' => MENU_LOCAL_TASK,
     );
+    $items[] = array(
+      'path' => 'admin/settings/path_redirect',
+      'title' => t('URL redirects'),
+      'access' => $access,
+      'callback' => 'drupal_get_form',
+      'callback arguments' => 'path_redirect_settings',
+      'description' => t('Configure behavior for URL redirects.'),
+    );
   }
   else {
     if (arg(0) == 'admin' && arg(1) == 'build' && arg(2) == 'path_redirect' && arg(3) == 'edit') {
@@ -151,7 +165,7 @@ function path_redirect_admin($rid = FALS
       $path,
       check_url($redirect . $query . $fragment),
       $types[$r->type]['title'],
-      array('data' => l(t('test'), $r->path, array())),
+      array('data' => l(t('test'), $r->path)),
       array('data' => l(t('edit'), 'admin/build/path_redirect/edit/'. $r->rid)),
       array('data' => l(t('delete'), 'admin/build/path_redirect/edit/'. $r->rid .'/delete')),
     );
@@ -384,6 +398,143 @@ function path_redirect_delete_confirm_su
   drupal_goto('admin/build/path_redirect');
 }
 
+function path_redirect_settings() {
+  $form['path_redirect_nodeapi_enabled'] = array(
+    '#type' => 'radios',
+    '#title' => t('Enable on edit pages'),
+    '#default_value' => variable_get('path_redirect_nodeapi_enabled', 0),
+    '#options' => array(t('Disabled'), t('Enabled')),
+    '#description' => t('Enable management of URL redirects directly on content editing pages.'),
+  );
+
+  $form['path_redirect_redirect_warning'] = array(
+    '#type' => 'radios',
+    '#title' => t('Warn on redirect'),
+    '#default_value' => variable_get('path_redirect_redirect_warning', 0),
+    '#options' => array(t('Disabled'), t('Enabled')),
+    '#description' => t('Display an error message to users when a redirect takes place.'),
+  );
+
+  $form['path_redirect_allow_bypass'] = array(
+    '#type' => 'radios',
+    '#title' => t('Allow bypassing'),
+    '#default_value' => variable_get('path_redirect_allow_bypass', 0),
+    '#options' => array(t('Disabled'), t('Enabled')),
+    '#description' => t('Allow users to bypass redirects by appending <code>?redirect=no</code> to the URL.'),
+  );
+
+  return system_settings_form($form);
+}
+
+function path_redirect_form_alter($form_id, &$form) {
+  if (variable_get('path_redirect_nodeapi_enabled', 0) && isset($form['#id']) && $form['#id'] == 'node-form' && user_access('administer redirects')) {
+    $form['redirects'] = array(
+      '#type' => 'fieldset',
+      '#access' => user_access('administer redirects'),
+      '#title' => t('URL redirects'),
+      '#collapsible' => TRUE,
+      '#collapsed' => !db_num_rows(path_redirect_node_redirects($form['#node']->nid)),
+      '#prefix' => '<div class="url-redirects">',
+      '#suffix' => '</div>',
+      '#weight' => 31,
+    );
+    $form['redirects']['list'] = _path_redirect_node_form_list($form['#node']);
+    $form['redirects']['path_redirect_add'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Add a redirect from'),
+      '#description' => t('Path from which to redirect to this node.'),
+      '#maxlength' => 255,
+      '#size' => 42,
+    );
+  }
+}
+
+function path_redirect_node_redirects($nid) {
+  return db_query("
+    SELECT rid, path, redirect, type
+    FROM {path_redirect} pr LEFT JOIN {url_alias} ua ON pr.redirect = ua.dst
+    WHERE pr.redirect = 'node/%s' OR ua.src = 'node/%s'
+    ORDER BY pr.path", $nid, $nid);
+}
+
+function _path_redirect_node_form_list($node) {
+  $form['#theme'] = 'path_redirect_node_form_list';
+  if(!empty($node->nid)) {
+    $result = db_query("
+      SELECT rid, path, redirect, type
+      FROM {path_redirect} pr LEFT JOIN {url_alias} ua ON pr.redirect = ua.dst
+      WHERE pr.redirect = 'node/%s' OR ua.src = 'node/%s'
+      ORDER BY pr.path", $node->nid, $node->nid);
+    if ($result) {
+      $types = path_redirect_error_list();
+      while ($redirect = db_fetch_object($result)) {
+        $form['redirects'][$redirect->rid]['path'] = array(
+          '#value' => $redirect->path,
+        );
+        $form['redirects'][$redirect->rid]['redirect'] = array(
+          '#value' => $redirect->redirect,
+        );
+        $form['redirects'][$redirect->rid]['type'] = array(
+          '#value' => '<span title="'.$types[$redirect->type]['title'].'">'.$redirect->type.'</span>',
+        );
+        $form['redirects'][$redirect->rid]['test'] = array(
+          '#value' => l(t('test'), $redirect->path),
+        );
+        $form['redirects'][$redirect->rid]['edit'] = array(
+          '#value' => l(t('edit'), 'admin/build/path_redirect/edit/'. $redirect->rid),
+        );
+        $form['redirects'][$redirect->rid]['delete'] = array(
+          '#value' => l(t('delete'), 'admin/build/path_redirect/edit/'. $redirect->rid .'/delete'),
+        );
+      }
+    }
+  }
+  return $form;
+}
+
+function theme_path_redirect_node_form_list(&$form) {
+  if (count(element_children($form['redirects']))) {
+    $header = array(t('From'), t('To'), t('Type'), array('data' => t('Operations'), 'colspan' => 3));
+    foreach (element_children($form['redirects']) as $key) {
+      $rows[] = array(
+        drupal_render($form['redirects'][$key]['path']),
+        drupal_render($form['redirects'][$key]['redirect']),
+        drupal_render($form['redirects'][$key]['type']),
+        drupal_render($form['redirects'][$key]['test']),
+        drupal_render($form['redirects'][$key]['edit']),
+        drupal_render($form['redirects'][$key]['delete']),
+      );
+    }
+    return theme('table', $header, $rows);
+  }
+}
+
+function path_redirect_nodeapi(&$node, $op, $arg) {
+  if (user_access('administer redirects')) {
+    switch ($op) {
+      case 'validate':
+        if (db_result(db_query("SELECT COUNT(rid) FROM {path_redirect} WHERE path = '%s' AND redirect != '%s' AND redirect != '%s'", $node->path_redirect_add, "node/$node->nid", $node->path))) {
+          form_set_error('path_redirect_add', t('The path is already redirected elsewhere.'));
+        }
+        break;
+      case 'load':
+        break;
+      case 'update':
+      case 'insert':
+        if ($node->path_redirect_add) {
+          path_redirect_save(array(
+            'path' => $node->path_redirect_add,
+            'redirect' => $node->path ? $node->path : 'node/'. $node->nid,
+            'type' => 301,
+          ));
+        }
+        break;
+      case 'delete':
+        break;
+    }
+  }
+}
+
 /**
  * This is a copy of drupal_goto() redesigned for use during the bootstrap
  */
