Index: /Users/jeff/Sites/yumyum/sites/all/modules/path_redirect/path_redirect.module
===================================================================
--- /Users/jeff/Sites/yumyum/sites/all/modules/path_redirect/path_redirect.module	(revision 83)
+++ /Users/jeff/Sites/yumyum/sites/all/modules/path_redirect/path_redirect.module	(working copy)
@@ -23,14 +23,44 @@
  *
  */
 function path_redirect_init() {
-  // see if this page has a redirect path
+  // first we build an array of possible path entries for the current path
   $query = '';
   if (isset($_GET['q'])) {
-    $query = $_GET['q'];
+    $query = $_GET['q']; // the raw value
+  }
+  $paths[] = $query;
+  $utf = utf8_encode($query); // the utf8 version
+  if ($utf != $query) {
+    $paths[] = $utf;
   }
-  $r = db_fetch_object(db_query("SELECT redirect, query, fragment, type FROM {path_redirect} WHERE path = '%s' OR path = '%s'", $query, utf8_encode($query)));
+  // then we stick '<*>' in each position and add those to the possibilities
+  $args = explode('/', $query);
+  foreach($args as $key => $val) {
+    $temp = $args;
+    $temp[$key] = '<*>';
+    $temp_path = implode('/', $temp);
+    if (!in_array($temp_path, $paths)) {
+      $paths[] = implode('/', $temp);
+    }
+  }
+  // sanitize everything
+  foreach ($paths as $key => $val) {
+    $paths[$key] = db_escape_string($val);
+  }
+  $r = db_fetch_object(db_query("SELECT path, redirect, query, fragment, type FROM {path_redirect} WHERE path IN ('". implode("','", $paths) ."') LIMIT 1"));
   if ($r) {
-    // if there's a result found, do the redirect
+    if (strpos($r->path, '<*>') !== FALSE) {
+      //find the position of the wildcard
+      $rargs = explode('/', $r->path);
+      foreach ($rargs as $key => $val) {
+        if (strpos($val, '<*>') !== FALSE) {
+          $r->redirect = str_replace('<*>', $args[$key], $r->redirect);
+          $r->query = str_replace('<*>', $args[$key], $r->query);
+          $r->fragment = str_replace('<*>', $args[$key], $r->fragment);
+          break;
+        }
+      }
+    }
     drupal_goto($r->redirect, ($r->query ? $r->query: NULL), ($r->fragment ? $r->fragment : NULL), $r->type);
   }
 }
@@ -124,7 +154,8 @@
   $count = db_num_rows($result);
   $types = path_redirect_error_list();
   while ($r = db_fetch_object($result)) {
-    $path = drupal_get_path_alias($r->path);
+    $wildcard = strpos($r->path, '<*>') !== FALSE;
+    $path = $wildcard ? $r->path : drupal_get_path_alias($r->path);
     $redirect = drupal_get_path_alias($r->redirect);
     $query = $r->query ? "?$r->query" : '';
     $fragment = $r->fragment ? "#$r->fragment" : '';
@@ -132,7 +163,7 @@
       $path,
       check_url($redirect . $query . $fragment),
       $types[$r->type]['title'],
-      array('data' => l(t('test'), $r->path, array(), $r->query ? $r->query : NULL, $r->fragment ? $r->fragement : NULL)),
+      array('data' => $wildcard ? '' : l(t('test'), $r->path, array(), $r->query ? $r->query : NULL, $r->fragment ? $r->fragement : NULL)),
       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')),
     );
@@ -172,7 +203,9 @@
   $form['path'] = array(
     '#type' => 'textfield',
     '#title' => t('From'),
-    '#description' => t('Enter a Drupal path or path alias to redirect'),
+    '#description' => t('Enter a Drupal path or path alias to redirect. <br />
+      A single wildcard of <code>&lt;*&gt;</code> can be used as a distinct path segment 
+      (separated by <code>/</code>). <br />Example: <code>photos/&lt;*&gt;/large</code>'),
     '#default_value' => drupal_get_path_alias($edit['path']),
   );
   
@@ -181,7 +214,12 @@
     '#prefix' => '<div class="container-inline">',
     '#suffix' => '</div>',
     '#title' => t('To'),
-    '#description' => '<div style="display:block">'. t('Enter a Drupal path, path alias, or external URL to redirect to. Use %front to redirect to the front page.  Enter (optional) queries after "?" and (optional) anchor after "#". Most redirects will not contain queries or fragment anchors.', array('%front' => '<front>')) .'</div>',
+    '#description' => '<div style="display:block">'. t('Enter a Drupal path, path alias, 
+      or external URL to redirect to. Use %front to redirect to the front page.  Enter 
+      (optional) queries after "?" and (optional) anchor after "#". Most redirects will
+      not contain queries or fragment anchors.<br />
+      If you entered a wildcard in the <em>From</em> field, you can enter <code>&lt;*&gt;</code>
+      in any of these fields to have the value of the wildcard appear in the redirected path.', array('%front' => '<front>')) .'</div>',
   );
   
   $form['redirect']['redirect'] = array(
@@ -256,9 +294,23 @@
   elseif (strstr($form_values['path'], '?')) {
     form_set_error('path', t('You cannot currently include a query in your redirect <strong>from</strong> path.'));
   }
-  elseif (!valid_url($form_values['path'])) {
+  elseif (strpos($form_values['path'], '<*>') === FALSE && !valid_url($form_values['path'])) {
     form_set_error('path', t('The redirect <strong>from</strong> path does not appear valid. This must be a local Drupal path.'));
   }
+  elseif (strpos($form_values['path'], '<*>') !== FALSE) {
+    // if we've got a wildcard, let's make sure it's by itself
+    $args = explode('/', $form_values['path']);
+    foreach($args as $key => $val) {
+      if (strpos($val, '<*>')) {
+        $val = str_replace('<*>', '', $val);
+        if (strlen($val)) {
+          $args[$key] = '<*>';
+          form_set_error('path', t('Wildcards in the redirect <strong>from</strong> path must be separate URL segments delimeted by "/", for example: <em>user/<*>/edit</em>.<br />A valid path is: %path', array('%path' => implode('/', $args))));
+          break;
+        }
+      }
+    }
+  }
   
   if (!valid_url($form_values['redirect']) && !valid_url($form_values['redirect'], TRUE) && $form_values['redirect'] != '<front>') {
     form_set_error('redirect', t('The redirect <strong>to</strong> path does not appear valid.'));
