=== modified file 'includes/menu.inc'
--- includes/menu.inc	2007-01-31 21:55:37 +0000
+++ includes/menu.inc	2007-02-06 09:39:09 +0000
@@ -172,22 +172,35 @@ define('MENU_SITE_OFFLINE', 4);
  */
 
 /**
+ * @Name Menu operations
+ * @{
+ * Menu helper possible operations.
+ */
+
+define('MENU_HANDLE_REQUEST', 0);
+define('MENU_RENDER_LINK', 1);
+
+/**
+ * @} End of "Menu helper directions
+ */
+
+/**
  * Returns the ancestors (and relevant placeholders) for any given path.
  *
  * For example, the ancestors of node/12345/edit are:
  *
  * node/12345/edit
- * node/12345/%
- * node/%/edit
- * node/%/%
+ * node/12345/[]
+ * node/[]/edit
+ * node/[]/[]
  * node/12345
- * node/%
+ * node/[]
  * node
  *
  * To generate these, we will use binary numbers. Each bit represents a
  * part of the path. If the bit is 1, then it represents the original
  * value while 0 means wildcard. If the path is node/12/edit/foo
- * then the 1011 bitstring represents node/%/edit/foo where % means that
+ * then the 1011 bitstring represents node/[]/edit/foo where [] means that
  * any argument matches that part.
  *
  * @param $parts
@@ -195,7 +208,7 @@ define('MENU_SITE_OFFLINE', 4);
  *   array('node', '12345', 'edit').
  * @return
  *   An array which contains the ancestors and placeholders. Placeholders
- *   simply contain as many %s as the ancestors.
+ *   simply contain as many '%s' as the ancestors.
  */
 function menu_get_ancestors($parts) {
   $n1 = count($parts);
@@ -212,7 +225,7 @@ function menu_get_ancestors($parts) {
         $current .= $parts[$length - $j];
       }
       else {
-        $current .= '%';
+        $current .= '[]';
       }
       if ($j) {
         $current .= '/';
@@ -273,10 +286,10 @@ function menu_unserialize($data, $map) {
  *   with keys like title, access callback, access arguments etc.
  */
 function menu_set_item($path, $item) {
-  menu_get_item($path, TRUE, $item);
+  menu_get_item($path, $item);
 }
 
-function menu_get_item($path = NULL, $execute = TRUE, $item = NULL) {
+function menu_get_item($path = NULL, $item = NULL) {
   static $items;
   if (!isset($path)) {
     $path = $_GET['q'];
@@ -289,14 +302,13 @@ function menu_get_item($path = NULL, $ex
     $parts = array_slice($map, 0, 6);
     list($ancestors, $placeholders) = menu_get_ancestors($parts);
     if ($item = db_fetch_object(db_query_range('SELECT * FROM {menu} WHERE path IN ('. implode (',', $placeholders) .') ORDER BY fit DESC', $ancestors, 0, 1))) {
-      $item->access = _menu_access($item, $map);
+      list($item->access, $map) = _menu_access($item, $map);
       if ($map === FALSE) {
         $items[$path] = FALSE;
         return FALSE;
       }
-      if ($execute) {
-        $item->page_arguments = array_merge(menu_unserialize($item->page_arguments, $map), array_slice($parts, $item->number_parts));
-      }
+      $item->map = $map;
+      $item->page_arguments = array_merge(menu_unserialize($item->page_arguments, $map), array_slice($parts, $item->number_parts));
     }
     $items[$path] = $item;
   }
@@ -313,24 +325,78 @@ function menu_execute_active_handler() {
   return MENU_NOT_FOUND;
 }
 
-function _menu_access($item, &$map) {
-  if ($item->map_callback) {
-    $map = call_user_func_array($item->map_callback, array_merge(array($map), unserialize($item->map_arguments)));
-    if ($map === FALSE) {
-      return FALSE;
+/**
+ * Handles dynamic path translation and menu access control.
+ *
+ * When a user arrives on a page such as node/5, this function determines
+ * what "5" corresponds to, by inspecting the page's menu path definition,
+ * node/[node_from_arg]. This will call node_form_arg(MENU_HANDLE_REQUEST, 5)
+ * and get back the corresponding node object.
+ *
+ * It also works in reverse, to allow the display of tabs and menu items which
+ * contain these dynamic arguments, translating node/[node_from_arg] to node/5.
+ * This operation is called MENU_RENDER_LINK.
+ *
+ * @param $item
+ *   A menu item object
+ * @param $map
+ *   An array of path arguments (ex: array('node', 5))
+ * @param $operation
+ *   The path translation operation to perform:
+ *   - MENU_HANDLE_REQUEST: An incoming page reqest; map with appropriate callback.
+ *   - MENU_RENDER_LINK: Render an internal path as a link.
+ * @return
+ *   Returns an array. The first value is the access, the second is the map
+ *   with objects loaded where appropriate and the third is the path ready for
+ *   printing.
+ */
+function _menu_access($item, $map, $operation = MENU_HANDLE_REQUEST) {
+  $path = '';
+
+  // Check if there are dynamic arguments in the path that need to be calculated.
+  if ($item->functions) {
+    $functions = unserialize($item->functions);
+    $path_map = ($operation == MENU_HANDLE_REQUEST) ? $map : explode('/', $item->path);
+    foreach ($functions as $index => $function) {
+      // Translate place-holders into real values.
+      if ($operation != MENU_HANDLE_REQUEST) {
+        $return = $function($operation, !empty($map[$index]) ? $map[$index] : '');
+        if (!empty($map[$index]) || $return) {
+          $path_map[$index] = $return;
+        }
+      }
+      // We now have a real path regardless of operation, map it.
+      $return = $function(MENU_HANDLE_REQUEST, !empty($path_map[$index]) ? $path_map[$index] : '');
+      // If callback returned an error, trigger 404.
+      if ($return === FALSE) {
+        return array(FALSE, FALSE, '');
+      }
+      $map[$index] = $return;
+    }
+    if ($operation != MENU_HANDLE_REQUEST) {
+      // Re-join the path with the new replacement value.
+      $path = implode('/', $path_map);
     }
   }
+  else {
+    $path = $item->path;
+  }
+
+  // Determine access callback, which will decide whether or not the current user has
+  // access to this path.
   $callback = $item->access_callback;
+  // Check for a TRUE or FALSE value.
   if (is_numeric($callback)) {
-    return $callback;
+    return array($callback, $map, $path);
   }
   $arguments = menu_unserialize($item->access_arguments, $map);
   // As call_user_func_array is quite slow and user_access is a very common
   // callback, it is worth making a special case for it.
   if ($callback == 'user_access') {
-    return (count($arguments) == 1) ? user_access($arguments[0]) : user_access($arguments[0], $arguments[1]);
+    $access = (count($arguments) == 1) ? user_access($arguments[0]) : user_access($arguments[0], $arguments[1]);
+    return array($access, $map, $path);
   }
-  return call_user_func_array($callback, $arguments);
+  return array(call_user_func_array($callback, $arguments), $map, $path);
 }
 
 /**
@@ -346,12 +412,13 @@ function _menu_tree($result = NULL, $dep
   static $original_map;
   $remnant = array('link' => '', 'has_children' => FALSE);
   $tree = '';
+  $map = arg(NULL);
   while ($item = db_fetch_object($result)) {
-    $map = arg(NULL, $item->path);
-    if (!_menu_access($item, $map)) {
+    list($access, , $path) = _menu_access($item, $map, MENU_RENDER_LINK);
+    if (!$access) {
       continue;
     }
-    $menu_link = array('link' => $item->menu_link, 'has_children' => $item->has_children);
+    $menu_link = array('link' => l($item->title, $path), 'has_children' => $item->has_children);
     if ($item->depth > $depth) {
       list($remnant, $menu) = _menu_tree($result, $item->depth, $menu_link);
       $tree .= theme('menu_tree', $link, $menu);
@@ -430,47 +497,80 @@ function menu_rebuild() {
     $function($menu);
   }
   $mid = 1;
-  // First pass.
+  // First pass: separate callbacks from pathes, making pathes ready for
+  // matching. Calculate fitness, and fill some default values.
   foreach ($menu as $path => $item) {
-    $item = &$menu[$path];
     $parts = explode('/', $path, 6);
     $number_parts = count($parts);
-    // We store the highest index of parts here to save some work in the weight
+    // We store the highest index of parts here to save some work in the fit
     // calculation loop.
     $slashes = $number_parts - 1;
-    // If there is no %, it fits maximally.
-    if (strpos($path, '%') === FALSE) {
+    $fit = 0;
+    $functions = array();
+    // extract functions
+    foreach ($parts as $k => $part) {
+      if (preg_match('/\[([a-z_]*)\]/', $part, $matches) && (!$matches[1] || function_exists($matches[1]))) {
+        if ($matches[1]) {
+          $functions[$k] = $matches[1];
+        }
+        $parts[$k] = '[]';
+      }
+      else {
+        $fit |=  1 << ($slashes - $k);
+      }
+    }
+    $functions = empty($functions) ? '' : serialize($functions);
+    $item['functions'] = $functions;
+    // If there is no [], it fits maximally.
+    if (!$fit) {
       $fit = (1 << $number_parts) - 1;
+      $move = FALSE;
     }
     else {
-      // We need to calculate the fitness.
-      $fit = 0;
-      foreach ($parts as $k => $part) {
-        // ($part != '%') is the bit we want and we shift it to its place
-        // by shifting to left by ($slashes - $k) bits.
-        $fit |=  ($part != '%') << ($slashes - $k);
-      }
+      $move = TRUE;
     }
-    if (!isset($item['_visible'])) {
-      $item['_visible'] = (!isset($item['type']) || ($item['type'] & MENU_VISIBLE_IN_TREE)) ? 1 : 0;
+    $item += array(
+      'title' => '',
+      'weight' => 0,
+      'type' => MENU_NORMAL_ITEM,
+      'functions' => $functions,
+      '_number_parts' => $number_parts,
+      '_parts' => $parts,
+      '_fit' => $fit,
+      '_mid' => $mid++,
+    );
+    $item += array(
+      '_visible' => (bool)($item['type'] & MENU_VISIBLE_IN_TREE),
+      '_tab' => (bool)($item['type'] & MENU_IS_LOCAL_TASK),
+    );
+    if ($move) {
+      $new_path = implode('/', $item['_parts']);
+      unset($menu[$path]);
     }
-    $depth = 1;
-    if (!isset($item['_mid'])) {
-      $item['_mid'] = $mid++;
+    else {
+      $new_path = $path;
     }
+    $menu[$new_path] = $item;
+  }
+  // Second pass: find visible parents and prepare for sorting.
+  foreach ($menu as $path => $item) {
+    $item = &$menu[$path];
+    $number_parts = $item['_number_parts'];
     $parents = array($item['_mid']);
+    if ($item['_visible'] && isset($item['parent'])) {
+      $parent_parts = explode('/', $item['parent'], 6);
+      $slashes = count($parent_parts) - 1;
+    }
+    else {
+      $parent_parts = $item['_parts'];
+      $slashes = $number_parts -1;
+    }
+    $depth = 1;
     for ($i = $slashes; $i; $i--) {
-      $parent_path = implode('/', array_slice($parts, 0, $i));
+      $parent_path = implode('/', array_slice($parent_parts, 0, $i));
       // We need to calculate depth to be able to sort. depth needs visibility.
       if (isset($menu[$parent_path])) {
         $parent = &$menu[$parent_path];
-        // It's possible that the parent was not processed yet.
-        if (!isset($parent['_mid'])) {
-          $parent['_mid'] = $mid++;
-        }
-        if (!isset($parent['_visible'])) {
-          $parent['_visible'] = (!isset($parent['type']) || ($parent['type'] & MENU_VISIBLE_IN_TREE)) ? 1 : 0;
-        }
         if ($item['_visible'] && $parent['_visible']) {
           $parent['_has_children'] = 1;
           $depth++;
@@ -487,22 +587,16 @@ function menu_rebuild() {
     $parents = implode(',', array_reverse($parents));
     // Store variables and set defaults.
     $item += array(
-      '_fit' => $fit,
-      '_number_parts' => $number_parts,
-      '_parts' => $parts,
       '_pid' => 0,
-      '_depth' => $depth,
+      '_depth' => $item['_visible'] ? $depth : $number_parts,
       '_parents' => $parents,
       '_has_children' => 0,
-      'title' => '',
-      'weight' => 0,
-      'type' => MENU_NORMAL_ITEM,
     );
-    $sort[$path] = ($item['_visible'] ? $depth : $number_parts) . sprintf('%05d', $item['weight']) . $item['title'];
+    $sort[$path] = $item['_depth'] . sprintf('%05d', $item['weight']) . $item['title'];
     unset($item);
   }
   array_multisort($sort, $menu);
-  // Second pass: calculate ancestors, vancode and store into the database.
+  // Third pass: calculate ancestors, vancode and store into the database.
   foreach ($menu as $path => $item) {
     $item = &$menu[$path];
     for ($i = $item['_number_parts'] - 1; $i; $i--) {
@@ -512,7 +606,7 @@ function menu_rebuild() {
         // If a callback is not found, we try to find the first parent that
         // has this callback. When found, its callback argument will also be
         // copied but only if there is none in the current item.
-        foreach (array('access', 'map', 'page') as $type) {
+        foreach (array('access', 'page') as $type) {
           if (!isset($item["$type callback"]) && isset($parent["$type callback"])) {
             $item["$type callback"] = $parent["$type callback"];
             if (!isset($item["$type arguments"]) && isset($parent["$type arguments"])) {
@@ -525,9 +619,6 @@ function menu_rebuild() {
     if (!isset($item['access callback'])) {
       $menu[$path]['access callback'] = isset($item['access arguments']) ? 'user_access' : 0;
     }
-    if (!isset($item['map callback']) && isset($item['map arguments'])) {
-      $item['map callback'] = 'menu_map';
-    }
     if (is_bool($item['access callback'])) {
       $item['access callback'] = intval($item['access callback']);
     }
@@ -538,42 +629,38 @@ function menu_rebuild() {
       }
       $vancode = $prefix . int2vancode($next[$prefix]++);
       $menu[$path]['_prefix'] = $vancode .'.';
-      $link = l($item['title'], $path, isset($item['attributes']) ? $item['attributes'] : array(), isset($item['query']) ? $item['query'] : NULL, isset($item['fragment']) ? $item['fragment'] : NULL);
     }
     else {
       $vancode = '';
-      $link = '';
     }
-    $tab = ($item['type'] & MENU_IS_LOCAL_TASK) ? 1 : 0;
-    $default_tab = $item['type'] == MENU_DEFAULT_LOCAL_TASK;
-    if (!isset($item['parent'])) {
-      if ($tab) {
+    if ($item['_tab']) {
+      if (!isset($item['parent'])) {
         $item['parent'] = implode('/', array_slice($item['_parts'], 0, $item['_number_parts'] - 1));
       }
-      else {
-        $item['parent'] = $path;
-      }
+    }
+    else {
+      // Non-tab items specified the parent for visible links, and it's
+      // stored in parents, parent stores the tab parent.
+      $item['parent'] = $path;
     }
     $insert_item = $item + array(
       'access arguments' => array(),
       'access callback' => '',
       'page arguments' => array(),
       'page callback' => '',
-      'map arguments' => array(),
-      'map callback' => '',
     );
     db_query("INSERT INTO {menu} (
-      mid, pid, path,
-      access_callback, access_arguments, page_callback, page_arguments, map_callback, map_arguments, fit,
-      number_parts, vancode, menu_link, visible, parents, depth, has_children, tab, default_tab, title, parent)
-      VALUES (%d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', '%s', %d, '%s', %d, %d, %d, %d, '%s', '%s')",
-      $insert_item['_mid'], $insert_item['_pid'], $path, $insert_item['access callback'],
-      serialize($insert_item['access arguments']), $insert_item['page callback'],
-      serialize($insert_item['page arguments']), $insert_item['map callback'],
-      serialize($insert_item['map arguments']), $insert_item['_fit'],
-      $insert_item['_number_parts'], $vancode .'+', $link, $insert_item['_visible'],
-      $insert_item['_parents'], $insert_item['_depth'], $insert_item['_has_children'],
-      $tab, $default_tab, $insert_item['title'], $insert_item['parent']);
+      mid, pid, path, functions,
+      access_callback, access_arguments, page_callback, page_arguments, fit,
+      number_parts, vancode, visible, parents, depth, has_children, tab, title, parent, type)
+      VALUES (%d, %d, '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', %d, '%s', %d, %d, %d, '%s', '%s', '%s')",
+      $insert_item['_mid'], $insert_item['_pid'], $path, $item['functions'],
+      $insert_item['access callback'], serialize($insert_item['access arguments']),
+      $insert_item['page callback'], serialize($insert_item['page arguments']),
+      $insert_item['_fit'], $insert_item['_number_parts'], $vancode .'+',
+      $insert_item['_visible'], $insert_item['_parents'], $insert_item['_depth'],
+      $insert_item['_has_children'], $item['_tab'], $insert_item['title'],
+      $insert_item['parent'], $insert_item['type']);
     unset($item);
   }
 }
@@ -590,32 +677,89 @@ function menu_primary_links() {
 function menu_secondary_links() {
 }
 
-function menu_primary_local_tasks() {
-  $router_item = menu_get_item();
-  $result = db_query("SELECT * FROM {menu} WHERE parent = '%s' AND tab = 1 ORDER BY vancode", $router_item->parent);
-  $tabs = array();
-  while ($item = db_fetch_object($result)) {
-    $map = explode('/', $item->path);
-    foreach ($map as $key => $value) {
-      if ($value == '%') {
-        $map[$key] = arg($key);
+/**
+ * Collects the local tasks (tabs) for a given level.
+ *
+ * @param $level
+     The level of tasks you ask for. Primary tasks are 0, secondary are 1...
+ * @return
+ *   An array of links to the tabs.
+ */
+function menu_local_tasks($level = 0) {
+  static $tabs = array(), $parents = array(), $parents_done = array();
+  if (empty($tabs)) {
+    $router_item = menu_get_item();
+    $map = arg(NULL);
+    do {
+      // Tabs are router items that have the same parent. If there is a new
+      // parent, let's add it the queue.
+      if (!empty($router_item->parent)) {
+        $parents[] = $router_item->parent;
+        // Do not add the same item twice.
+        $router_item->parent = '';
+      }
+      $parent = array_shift($parents);
+      // Do not process the same parent twice.
+      if (isset($parents_done[$parent])) {
+        continue;
+      }
+      // This loads all the tabs.
+      $result = db_query("SELECT * FROM {menu} WHERE parent = '%s' AND tab = 1 ORDER BY vancode", $parent);
+      $tabs_current = array();
+      unset($next_router_item);
+      while ($item = db_fetch_object($result)) {
+        // This call changes the path from for example user/[] to user/123 and
+        // also determines whether we are allowed to access it.
+        list($access, , $path) = _menu_access($item, $map, MENU_RENDER_LINK);
+        if ($access) {
+          // MENU_DEFAULT_LOCAL_TASK links to its parent.
+          $link = l($item->title, $item->type == MENU_DEFAULT_LOCAL_TASK ? substr($path, 0, strrpos($path, '/')) : $path);
+          $depth = $item->depth;
+          // We check for the active tab.
+          if ($item->path == $router_item->path || (!$router_item->tab && $item->type == MENU_DEFAULT_LOCAL_TASK) || $path == $_GET['q']) {
+            $tabs_current[] = array('class' => 'active', 'data' => $link);
+            if ($item->parent) {
+              // Let's try to find the router item one level up.
+              $next_router_item = db_fetch_object(db_query("SELECT path, tab, parent FROM {menu} WHERE path = '%s'", $item->parent));
+            }
+            // We will need to inspect one level down.
+            $parents[] = $item->path;
+          }
+          else {
+            $tabs_current[] = $link;
+          }
+        }
       }
-    }
-    $path = implode('/', $map);
-    if (_menu_access($item, $map, TRUE)) {
-      $link = l($item->title, $path);
-      if ((!$router_item->tab && $item->default_tab) || ($path == $_GET['q'])) {
-        $tabs[] = array('class' => 'active', 'data' => $link);
+      // If there are tabs, let's add them
+      if ($tabs_current) {
+        $tabs[$depth] = $tabs_current;
+      }
+      $parents_done[$parent] = TRUE;
+      if (isset($next_router_item)) {
+        $router_item = $next_router_item;
       }
       else {
-        $tabs[] = $link;
+        unset($router_item);
       }
-    }
+    } while ($parents);
+    // Sort by depth
+    ksort($tabs);
+    // Remove the depth, we are interested only in their relative placement.
+    $tabs = array_values($tabs);
+  }
+  return isset($tabs[$level]) ? $tabs[$level] : array();
+}
+
+function menu_primary_local_tasks() {
+  if ($tasks = menu_local_tasks()) {
+    return theme('item_list', $tasks, NULL, 'ul', array('class' => 'tabs primary'));
   }
-  return theme('item_list', $tabs, NULL, 'ul', array('class' => 'tabs primary'));
 }
 
 function menu_secondary_local_tasks() {
+  if ($tasks = menu_local_tasks(1)) {
+    return theme('item_list', $tasks, NULL, 'ul', array('class' => 'tabs secondary'));
+  }
 }
 
 function menu_set_active_item() {
@@ -631,4 +775,4 @@ function menu_get_active_breadcrumb() {
 function menu_get_active_title() {
   $item = menu_get_item();
   return $item->title;
-}
\ No newline at end of file
+}

=== modified file 'index.php'
--- index.php	2006-12-12 09:32:18 +0000
+++ index.php	2007-02-05 23:41:48 +0000
@@ -34,4 +34,4 @@ elseif (isset($return)) {
 
 }
 
-drupal_page_footer();
\ No newline at end of file
+drupal_page_footer();

=== modified file 'modules/aggregator/aggregator.module'
--- modules/aggregator/aggregator.module	2007-01-31 21:26:55 +0000
+++ modules/aggregator/aggregator.module	2007-02-05 15:09:55 +0000
@@ -51,19 +51,17 @@ function aggregator_menu() {
     'type' => MENU_LOCAL_TASK,
     'parent' => 'admin/content/aggregator',
   );
-  $items['admin/content/aggregator/remove/%'] = array(
+  $items['admin/content/aggregator/remove/[aggregator_feed_from_arg]'] = array(
     'title' => t('Remove items'),
     'page callback' => 'aggregator_admin_remove_feed',
     'page arguments' => array(4),
-    'map arguments' => array('aggregator_get_feed', 4),
     'access arguments' => array('administer news feeds'),
     'type' => MENU_CALLBACK,
   );
-  $items['admin/content/aggregator/update/%'] = array(
+  $items['admin/content/aggregator/update/[aggregator_feed_from_arg]'] = array(
     'title' => t('Update items'),
     'page callback' => 'aggregator_admin_refresh_feed',
     'page arguments' => array(4),
-    'map arguments' => array('aggregator_get_feed', 4),
     'access arguments' => array('administer news feeds'),
     'type' => MENU_CALLBACK,
   );
@@ -137,24 +135,23 @@ function aggregator_menu() {
       'weight' => 1,
     );
   }
-  $items['aggregator/sources/%'] = array(
+  $items['aggregator/sources/[aggregator_feed_from_arg]'] = array(
     'page callback' => 'aggregator_page_source',
-    'map arguments' => array('aggregator_get_feed', 2),
     'type' => MENU_CALLBACK,
   );
-  $items['aggregator/sources/%/view'] = array(
+  $items['aggregator/sources/[aggregator_feed_from_arg]/view'] = array(
     'title' => t('View'),
     'type' => MENU_DEFAULT_LOCAL_TASK,
     'weight' => -10,
   );
-  $items['aggregator/sources/%/categorize'] = array(
+  $items['aggregator/sources/[aggregator_feed_from_arg]/categorize'] = array(
     'title' => t('Categorize'),
     'page callback' => 'drupal_get_form',
     'page arguments' => array('aggregator_page_source'),
     'access arguments' => array('administer news feeds'),
     'type' => MENU_LOCAL_TASK,
   );
-  $items['aggregator/sources/%/configure'] = array(
+  $items['aggregator/sources/[aggregator_feed_from_arg]/configure'] = array(
     'title' => t('Configure'),
     'page callback' => 'drupal_get_form',
     'page arguments' => array('aggregator_form_feed', 2),
@@ -162,20 +159,18 @@ function aggregator_menu() {
     'type' => MENU_LOCAL_TASK,
     'weight' => 1,
   );
-  $items['admin/content/aggregator/edit/feed/%'] = array(
+  $items['admin/content/aggregator/edit/feed/[aggregator_feed_from_arg]'] = array(
     'title' => t('Edit feed'),
     'page callback' => 'drupal_get_form',
     'page arguments' => array('aggregator_form_feed', 5),
     'access arguments' => array('administer news feeds'),
-    'map arguments' => array('aggregator_get_feed', 5),
     'type' => MENU_CALLBACK,
   );
-  $items['admin/content/aggregator/edit/category/%'] = array(
+  $items['admin/content/aggregator/edit/category/[aggregator_category_from_arg]'] = array(
     'title' => t('Edit category'),
     'page callback' => 'drupal_get_form',
     'page arguments' => array('aggregator_form_category', 5),
     'access arguments' => array('administer news feeds'),
-    'map arguments' => array('aggregator_get_category', 5),
     'type' => MENU_CALLBACK,
   );
 
@@ -186,6 +181,20 @@ function aggregator_init() {
   drupal_add_css(drupal_get_path('module', 'aggregator') .'/aggregator.css');
 }
 
+function aggregator_feed_from_arg($operation, $arg) {
+  if ($operation == MENU_HANDLE_REQUEST) {
+    return is_numeric($arg) ? aggregator_get_feed($arg) : FALSE;
+  }
+  return $arg;
+}
+
+function aggregator_category_from_arg($operation, $arg) {
+  if ($operation == MENU_HANDLE_REQUEST) {
+    return is_numeric($arg) ? aggregator_get_category($arg) : FALSE;
+  }
+  return $arg;
+}
+
 function aggregator_admin_settings() {
   $items = array(0 => t('none')) + drupal_map_assoc(array(3, 5, 10, 15, 20, 25), '_aggregator_items');
   $period = drupal_map_assoc(array(3600, 10800, 21600, 32400, 43200, 86400, 172800, 259200, 604800, 1209600, 2419200, 4838400, 9676800), 'format_interval');
@@ -1035,7 +1044,7 @@ function aggregator_page_last() {
  */
 function aggregator_page_source() {
   $feed = db_fetch_object(db_query('SELECT * FROM {aggregator_feed} WHERE fid = %d', arg(2)));
-  drupal_set_title($feed->title);
+  drupal_set_title(check_plain($feed->title));
   $info = theme('aggregator_feed', $feed);
 
   return _aggregator_page_list('SELECT * FROM {aggregator_item} WHERE fid = '. $feed->fid .' ORDER BY timestamp DESC, iid DESC', arg(3), $info);

=== modified file 'modules/blog/blog.module'
--- modules/blog/blog.module	2007-01-31 15:49:22 +0000
+++ modules/blog/blog.module	2007-02-05 15:09:55 +0000
@@ -105,6 +105,9 @@ function blog_feed_last() {
  * Menu callback; displays a Drupal page containing recent blog entries.
  */
 function blog_page($a = NULL, $b = NULL) {
+  if (is_object($a)) {
+    $a = $a->uid;
+  }
 
   if (is_numeric($a)) { // $a is a user ID
     if ($b == 'feed') {
@@ -256,7 +259,7 @@ function blog_menu() {
     'access arguments' => array('access content'),
     'type' => MENU_SUGGESTED_ITEM,
   );
-  $items['blog/%'] = array(
+  $items['blog/[user_from_arg]'] = array(
     'title' => t('My blog'),
     'page arguments' => array(1),
     'access arguments' => array('edit own blog'),

=== modified file 'modules/book/book.module'
--- modules/book/book.module	2007-01-31 15:49:22 +0000
+++ modules/book/book.module	2007-02-05 15:09:55 +0000
@@ -109,18 +109,17 @@ function book_menu() {
     'access arguments' => array('access content'),
     'type' => MENU_SUGGESTED_ITEM,
   );
-  $items['book/export/%/%'] = array(
+  $items['book/export/[]/[]'] = array(
     'page callback' => 'book_export',
     'page arguments' => array(2, 3),
     'type' => MENU_CALLBACK,
   );
-  $items['node/%/outline'] = array(
+  $items['node/[node_from_arg]/outline'] = array(
     'title' => t('Outline'),
     'page callback' => 'drupal_get_form',
     'page arguments' => array('book_outline', 1),
     'access callback' => '_book_outline_access',
     'access arguments' => array(1),
-    'map arguments' => array('node_load', 1),
     'type' => MENU_LOCAL_TASK,
     'weight' => 2,
   );

=== modified file 'modules/comment/comment.module'
--- modules/comment/comment.module	2007-01-31 15:49:22 +0000
+++ modules/comment/comment.module	2007-02-05 15:09:55 +0000
@@ -195,15 +195,14 @@ function comment_menu() {
     'access arguments' => array('post comments'),
     'type' => MENU_CALLBACK,
   );
-  $items['comment/reply'] = array(
+  $items['comment/reply/[node_from_arg]'] = array(
     'title' => t('Reply to comment'),
     'page callback' => 'comment_reply',
     'access callback' => 'node_access',
     'access arguments' => array('view', 2),
-    'map arguments' => array('node_load', 2),
     'type' => MENU_CALLBACK,
   );
-  $items['node/%/%'] = array(
+  $items['node/[node_from_arg]/[]'] = array(
     'title' => t('View'),
     'page callback' => 'node_page_view',
     'page arguments' => array(1, 2),

=== modified file 'modules/contact/contact.module'
--- modules/contact/contact.module	2007-01-31 15:49:22 +0000
+++ modules/contact/contact.module	2007-02-05 15:09:55 +0000
@@ -84,14 +84,13 @@ function contact_menu() {
     'access arguments' => array('access site-wide contact form'),
     'type' => MENU_SUGGESTED_ITEM,
   );
-  $items['user/%/contact'] = array(
+  $items['user/[user_from_arg]/contact'] = array(
     'title' => t('Contact'),
     'page callback' => 'contact_user_page',
     'page arguments' => array(1),
     'type' => MENU_LOCAL_TASK,
     'access callback' => '_contact_user_tab_access',
     'access arguments' => array(1),
-    'map arguments' => array('user_load', 1),
     'weight' => 2,
   );
   return $items;

=== modified file 'modules/filter/filter.module'
--- modules/filter/filter.module	2007-01-31 15:49:22 +0000
+++ modules/filter/filter.module	2007-02-05 15:09:55 +0000
@@ -81,26 +81,25 @@ function filter_menu() {
     'access callback' => TRUE,
     'type' => MENU_SUGGESTED_ITEM,
   );
-  $items['admin/settings/filters/%'] = array(
+  $items['admin/settings/filters/[filter_from_arg]'] = array(
     'type' => MENU_CALLBACK,
     'page arguments' => array('filter_admin_format_form', 3),
     'access arguments' => array('administer filters'),
-    'map arguments' => array('filter_formats', 3),
   );
 
-  $items['admin/settings/filters/%/list'] = array(
+  $items['admin/settings/filters/[filter_from_arg]/list'] = array(
     'title' => t('View'),
     'page arguments' => array('filter_admin_format_form', 3),
     'type' => MENU_DEFAULT_LOCAL_TASK,
     'weight' => 0,
   );
-  $items['admin/settings/filters/%/configure'] = array(
+  $items['admin/settings/filters/[filter_from_arg]/configure'] = array(
     'title' => t('Configure'),
     'page arguments' => array('filter_admin_configure', 3),
     'type' => MENU_LOCAL_TASK,
     'weight' => 1,
   );
-  $items['admin/settings/filters/%/order'] = array(
+  $items['admin/settings/filters/[filter_from_arg]/order'] = array(
     'title' => t('Rearrange'),
     'page arguments' => array('filter_admin_order', 3),
     'type' => MENU_LOCAL_TASK,
@@ -109,6 +108,13 @@ function filter_menu() {
   return $items;
 }
 
+function filter_from_arg($operation, $arg) {
+  if ($operation == MENU_HANDLE_REQUEST) {
+    return is_numeric($arg) ? filter_formats($arg) : FALSE;
+  }
+  return $arg;
+}
+
 /**
  * Implementation of hook_perm().
  */

=== modified file 'modules/forum/forum.module'
--- modules/forum/forum.module	2007-02-01 21:44:36 +0000
+++ modules/forum/forum.module	2007-02-05 15:09:55 +0000
@@ -75,19 +75,21 @@ function forum_menu() {
     'type' => MENU_LOCAL_TASK,
     'parent' => 'admin/content/forum',
   );
-  $items['admin/content/forum/edit'] = array(
+  $items['admin/content/forum/edit/[forum_from_arg]'] = array(
     'page callback' => 'forum_form_main',
-    'map arguments' => array('_forum_get_term', 5, array()),
     'type' => MENU_CALLBACK,
   );
-  $items['admin/content/forum/edit/container/%'] = array(
+  $items['admin/content/forum/edit/container/[forum_from_arg]'] = array(
     'title' => t('Edit container'),
+    'page callback' => 'forum_form_main', 
     'page arguments' => array('container', 5),
+    'type' => MENU_CALLBACK,
   );
-  $items['admin/content/forum/edit/forum/%'] = array(
+  $items['admin/content/forum/edit/forum/[forum_from_arg]'] = array(
     'title' => t('Edit forum'),
     'page callback' => 'forum_form_main',
     'page arguments' => array('forum', 5),
+    'type' => MENU_CALLBACK,
   );
   return $items;
 }
@@ -96,8 +98,11 @@ function forum_init() {
   drupal_add_css(drupal_get_path('module', 'forum') .'/forum.css');
 }
 
-function _forum_get_term($tid) {
-  return (array)taxonomy_get_term($tid);
+function forum_from_arg($operation, $tid) {
+  if ($operation == MENU_HANDLE_REQUEST) {
+    return is_numeric($tid) ? (array)taxonomy_get_term($tid) : FALSE;
+  }
+  return $tid;
 }
 
 /**

=== modified file 'modules/locale/locale.module'
--- modules/locale/locale.module	2007-01-31 21:26:55 +0000
+++ modules/locale/locale.module	2007-02-05 15:09:55 +0000
@@ -97,13 +97,13 @@ function locale_menu() {
     'type' => MENU_CALLBACK,
   );
   // String related callbacks
-  $items['admin/settings/locale/string/edit/%'] = array(
+  $items['admin/settings/locale/string/edit/[]'] = array(
     'title' => t('Edit string'),
     'page callback' => 'drupal_get_form',
     'page arguments' => array('locale_admin_string_edit', 5),
     'type' => MENU_CALLBACK,
   );
-  $items['admin/settings/locale/string/delete/%'] = array(
+  $items['admin/settings/locale/string/delete/[]'] = array(
     'title' => t('Delete string'),
     'page callback' => 'locale_admin_string_delete',
     'page arguments' => array(5),

=== modified file 'modules/node/node.module'
--- modules/node/node.module	2007-01-31 15:49:22 +0000
+++ modules/node/node.module	2007-02-05 15:09:55 +0000
@@ -1166,33 +1166,32 @@ function node_menu() {
 
     }
   }
-  $items['node/%'] = array(
+  $items['node/[node_from_arg]'] = array(
     'title' => t('View'),
     'page callback' => 'node_page_view',
     'page arguments' => array(1),
     'access callback' => 'node_access',
     'access arguments' => array('view', 1),
-    'map arguments' => array('node_load', 1),
     'type' => MENU_CALLBACK);
-  $items['node/%/view'] = array(
+  $items['node/[node_from_arg]/view'] = array(
     'title' => t('View'),
     'type' => MENU_DEFAULT_LOCAL_TASK,
     'weight' => -10);
-  $items['node/%/edit'] = array(
+  $items['node/[node_from_arg]/edit'] = array(
     'title' => t('Edit'),
     'page callback' => 'node_page_edit',
     'page arguments' => array(1),
     'access arguments' => array('update', 1),
     'weight' => 1,
     'type' => MENU_LOCAL_TASK);
-  $items['node/%/delete'] = array(
+  $items['node/[node_from_arg]/delete'] = array(
     'title' => t('Delete'),
     'page callback' => 'drupal_get_form',
     'page arguments' => array('node_delete_confirm', 1),
     'access arguments' => array('delete', 1),
     'weight' => 1,
     'type' => MENU_CALLBACK);
-  $items['node/%/revisions'] = array(
+  $items['node/[node_from_arg]/revisions'] = array(
     'title' => t('Revisions'),
     'page callback' => 'node_revisions',
     'access callback' => '_node_revision_access',
@@ -1210,6 +1209,13 @@ function node_init() {
   drupal_add_css(drupal_get_path('module', 'node') .'/node.css');
 }
 
+function node_from_arg($direction, $arg) {
+  if ($direction == MENU_HANDLE_REQUEST) {
+    return is_numeric($arg) ? node_load($arg) : FALSE;
+  }
+  return $arg;
+}
+
 function node_last_changed($nid) {
   $node = db_fetch_object(db_query('SELECT changed FROM {node} WHERE nid = %d', $nid));
   return ($node->changed);
@@ -2464,7 +2470,7 @@ function node_update_index() {
  */
 function node_form_alter($form_id, &$form) {
   // Advanced node search form
-  if ($form_id == 'search_form' && arg(1) == 'node' && user_access('use advanced search')) {
+  if ($form_id == 'search_form' && $form['module']['#value'] == 'node' && user_access('use advanced search')) {
     // Keyword boxes:
     $form['advanced'] = array(
       '#type' => 'fieldset',

=== modified file 'modules/poll/poll.module'
--- modules/poll/poll.module	2007-01-24 14:48:35 +0000
+++ modules/poll/poll.module	2007-02-05 15:09:56 +0000
@@ -239,14 +239,14 @@ function poll_menu() {
     'type' => MENU_SUGGESTED_ITEM,
   );
 
-  $items['poll/cancel/%'] = array(
+  $items['poll/cancel/[node_from_arg]'] = array(
     'title' => t('Cancel'),
     'page callback' => 'poll_cancel',
     'page arguments' => array(2),
     'access arguments' => array('cancel own vote'),
     'type' => MENU_CALLBACK,
   );
-  $items['node/%/votes'] = array(
+  $items['node/[node_from_arg]/votes'] = array(
     'title' => t('Votes'),
     'page callback' => 'poll_votes',
     'access callback' => '_poll_menu_access',
@@ -254,7 +254,7 @@ function poll_menu() {
     'weight' => 3,
     'type' => MENU_LOCAL_TASK,
   );
-  $items['node/%/results'] = array(
+  $items['node/[node_from_arg]/results'] = array(
     'title' => t('Results'),
     'page callback' => 'poll_results',
     'access callback' => '_poll_menu_access',

=== modified file 'modules/search/search.module'
--- modules/search/search.module	2007-01-31 21:26:55 +0000
+++ modules/search/search.module	2007-02-05 15:09:56 +0000
@@ -140,7 +140,6 @@ function search_menu() {
   $items['search'] = array(
     'title' => t('Search'),
     'page callback' => 'search_view',
-    'page arguments' => array('node'),
     'access arguments' => array('search content'),
     'type' => MENU_SUGGESTED_ITEM,
   );
@@ -167,13 +166,14 @@ function search_menu() {
   );
 
   foreach (module_implements('search') as $name) {
-    $items['search/'. $name] = array(
+    $items['search/'. $name .'/[search_get_keys]'] = array(
       'title' => module_invoke($name, 'search', 'name', TRUE),
       'page callback' => 'search_view',
       'page arguments' => array($name),
       'access callback' => '_search_menu',
       'access arguments' => array($name),
       'type' => $name == 'node' ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK,
+      'parent' => 'search',
     );
   }
   return $items;
@@ -882,16 +882,21 @@ function do_search($keywords, $type, $jo
  * Helper function for grabbing search keys.
  */
 function search_get_keys() {
-  // Extract keys as remainder of path
-  // Note: support old GET format of searches for existing links.
-  $path = explode('/', $_GET['q'], 3);
-  return count($path) == 3 ? $path[2] : $_REQUEST['keys'];
+  static $return;
+  if (!isset($return)) {
+    // Extract keys as remainder of path
+    // Note: support old GET format of searches for existing links.
+    $path = explode('/', $_GET['q'], 3);
+    $keys = empty($_REQUEST['keys']) ? '' : $_REQUEST['keys'];
+    $return = count($path) == 3 ? $path[2] : $keys;
+  }
+  return $return;
 }
 
 /**
  * Menu callback; presents the search form and/or search results.
  */
-function search_view($type = '') {
+function search_view($type = 'node') {
   // Search form submits with POST but redirects to GET. This way we can keep
   // the search query URL clean as a whistle:
   // search/type/keyword+keyword
@@ -905,6 +910,7 @@ function search_view($type = '') {
 
     $keys = search_get_keys();
     // Only perform search if there is non-whitespace search term:
+    $results = '';
     if (trim($keys)) {
       // Log the search keys:
       watchdog('search', t('%keys (@type).', array('%keys' => $keys, '@type' => module_invoke($type, 'search', 'name'))), WATCHDOG_NOTICE, l(t('results'), 'search/'. $type .'/'. $keys));

=== modified file 'modules/statistics/statistics.module'
--- modules/statistics/statistics.module	2007-01-31 15:49:22 +0000
+++ modules/statistics/statistics.module	2007-02-05 15:09:56 +0000
@@ -126,7 +126,7 @@ function statistics_menu() {
     'page callback' => 'statistics_top_referrers',
     'access arguments' => array('access statistics'),
   );
-  $items['admin/logs/access/%'] = array(
+  $items['admin/logs/access/[]'] = array(
     'title' => t('Details'),
     'description' => t('View access log.'),
     'page callback' => 'statistics_access_log',
@@ -143,14 +143,15 @@ function statistics_menu() {
     'type' => MENU_NORMAL_ITEM,
     'weight' => 3,
   );
-  $items['user/%/track/navigation'] = array(
+  $items['user/[user_from_arg]/track/navigation'] = array(
     'title' => t('Track page visits'),
     'page callback' => 'statistics_user_tracker',
+    'access callback' => 'user_access',
     'access arguments' => array('access statistics'),
     'type' => MENU_LOCAL_TASK,
     'weight' => 2,
   );
-  $items['node/%/track'] = array(
+  $items['node/[node_from_arg]/track'] = array(
     'title' => t('Track'),
     'page callback' => 'statistics_node_tracker',
     'access callback' => 'user_access',

=== modified file 'modules/system/system.install'
--- modules/system/system.install	2007-01-31 21:26:55 +0000
+++ modules/system/system.install	2007-02-05 15:09:56 +0000
@@ -327,31 +327,31 @@ function system_install() {
       ) /*!40100 DEFAULT CHARACTER SET UTF8 */ ");
 
       db_query("CREATE TABLE {menu} (
+        mid int NOT NULL default '0',
+        pid int NOT NULL default '0',
         path varchar(255) NOT NULL default '',
+        functions varchar(255) NOT NULL default '',
         access_callback varchar(255) NOT NULL default '',
         access_arguments text,
         page_callback varchar(255) NOT NULL default '',
         page_arguments text,
-        map_callback varchar(255) NOT NULL default '',
-        map_arguments text,
         fit int NOT NULL default '0',
         number_parts int NOT NULL default '0',
         vancode varchar(255) NOT NULL default '',
-        mid int NOT NULL default '0',
-        pid int NOT NULL default '0',
         visible int NOT NULL default '0',
-        menu_link varchar(255) NOT NULL default '',
         parents varchar(255) NOT NULL default '',
         depth int NOT NULL default '0',
         has_children int NOT NULL default '0',
         tab int NOT NULL default 0,
         title varchar(255) NOT NULL default '',
-        default_tab int NOT NULL default '0',
         parent varchar(255) NOT NULL default '',
+        type int NOT NULL default 0,
         PRIMARY KEY  (path),
         KEY vancode (vancode),
         KEY fit (fit),
-        KEY visible (visible)
+        KEY visible (visible),
+        KEY pid (pid),
+        KEY parent (parent)
       ) /*!40100 DEFAULT CHARACTER SET UTF8 */ ");
 
       db_query("CREATE TABLE {node} (
@@ -802,30 +802,30 @@ function system_install() {
         mid int NOT NULL default '0',
         pid int NOT NULL default '0',
         path varchar(255) NOT NULL default '',
+        functions varchar(255) NOT NULL default '',
         access_callback varchar(255) NOT NULL default '',
         access_arguments text,
         page_callback varchar(255) NOT NULL default '',
         page_arguments text,
-        map_callback varchar(255) NOT NULL default '',
-        map_arguments text,
-        fit int NOT NULL default 0,
-        number_parts int NOT NULL default 0,
+        fit int NOT NULL default '0',
+        number_parts int NOT NULL default '0',
         vancode varchar(255) NOT NULL default '',
         visible int NOT NULL default '0',
-        menu_link varchar(255) NOT NULL default '',
         parents varchar(255) NOT NULL default '',
         depth int NOT NULL default '0',
         has_children int NOT NULL default '0',
-        tab int NOT NULL default '0',
+        tab int NOT NULL default 0,
         title varchar(255) NOT NULL default '',
-        default_tab int NOT NULL default '0',
         parent varchar(255) NOT NULL default '',
+        type int NOT NULL default 0,
         PRIMARY KEY (path)
       )");
 
       db_query("CREATE INDEX {menu}_vancode_idx ON {menu} (vancode)");
       db_query("CREATE INDEX {menu}_fit_idx ON {menu} (fit)");
       db_query("CREATE INDEX {menu}_visible_idx ON {menu} (visible)");
+      db_query("CREATE INDEX {menu}_parent_idx ON {menu} (parent)");
+      db_query("CREATE INDEX {menu}_pid_idx ON {menu} (parent)");
 
       db_query("CREATE TABLE {node} (
         nid serial CHECK (nid >= 0),

=== modified file 'modules/taxonomy/taxonomy.module'
--- modules/taxonomy/taxonomy.module	2007-01-31 21:26:55 +0000
+++ modules/taxonomy/taxonomy.module	2007-02-05 15:09:56 +0000
@@ -91,7 +91,7 @@ function taxonomy_menu() {
     'parent' => 'admin/content/taxonomy',
   );
 
-  $items['admin/content/taxonomy/edit/vocabulary/%'] = array(
+  $items['admin/content/taxonomy/edit/vocabulary/[taxonomy_vocabulary_from_arg]'] = array(
     'title' => t('Edit vocabulary'),
     'page callback' => 'taxonomy_admin_vocabulary_edit',
     'page arguments' => array(5),
@@ -117,32 +117,39 @@ function taxonomy_menu() {
     'access arguments' => array('access content'),
     'type' => MENU_CALLBACK,
   );
-  $items['admin/content/taxonomy/%'] = array(
+  $items['admin/content/taxonomy/[taxonomy_vocabulary_from_arg]'] = array(
     'title' => t('List terms'),
     'page callback' => 'taxonomy_overview_terms',
     'page arguments' => array(3),
     'access arguments' => array('administer taxonomy'),
-    'map arguments' => array('taxonomy_get_vocabulary', 3),
     'type' => MENU_CALLBACK,
   );
 
-  $items['admin/content/taxonomy/%/list'] = array(
+  $items['admin/content/taxonomy/[taxonomy_vocabulary_from_arg]/list'] = array(
     'title' => t('List'),
     'type' => MENU_DEFAULT_LOCAL_TASK,
     'weight' => -10,
   );
 
-  $items['admin/content/taxonomy/%/add/term'] = array(
+  $items['admin/content/taxonomy/[taxonomy_vocabulary_from_arg]/add/term'] = array(
     'title' => t('Add term'),
     'page callback' => 'drupal_get_form',
     'page arguments' => array('taxonomy_form_term', 3),
     'type' => MENU_LOCAL_TASK,
-    'parent' => 'admin/content/taxonomy/%',
+    'parent' => 'admin/content/taxonomy/[taxonomy_vocabulary_from_arg]',
   );
 
   return $items;
 }
 
+function taxonomy_vocabulary_from_arg($operation, $arg) {
+  if ($operation == MENU_HANDLE_REQUEST) {
+    return is_numeric($arg) ? taxonomy_get_vocabulary($arg) : FALSE;
+  }
+  return $arg;
+}
+
+
 /**
  * List and manage vocabularies.
  */
@@ -1388,14 +1395,11 @@ function taxonomy_term_page($str_tids = 
 /**
  * Page to edit a vocabulary.
  */
-function taxonomy_admin_vocabulary_edit($vid = NULL) {
+function taxonomy_admin_vocabulary_edit($vocabulary) {
   if ($_POST['op'] == t('Delete') || $_POST['confirm']) {
-    return drupal_get_form('taxonomy_vocabulary_confirm_delete', $vid);
-  }
-  if ($vocabulary = (array)taxonomy_get_vocabulary($vid)) {
-    return drupal_get_form('taxonomy_form_vocabulary', $vocabulary);
+    return drupal_get_form('taxonomy_vocabulary_confirm_delete', $vocabulary->vid);
   }
-  return drupal_not_found();
+  return drupal_get_form('taxonomy_form_vocabulary', (array)$vocabulary);
 }
 
 /**

=== modified file 'modules/tracker/tracker.module'
--- modules/tracker/tracker.module	2007-01-24 14:48:35 +0000
+++ modules/tracker/tracker.module	2007-02-05 15:09:56 +0000
@@ -35,18 +35,22 @@ function tracker_menu() {
     'type' => MENU_DEFAULT_LOCAL_TASK,
     'access callback' => 'user_is_logged_in',
   );
-  $items['tracker/%'] = array(
+
+  $items['tracker/[user_current]'] = array(
     'title' => t('My recent posts'),
     'type' => MENU_LOCAL_TASK,
     'access callback' => 'user_is_logged_in',
+    'access arguments' => array(1),
   );
-  $items['user/%/track'] = array(
+
+  $items['user/[user_from_arg]/track'] = array(
     'title' => t('Track'),
     'page callback' => 'tracker_track_user',
+    'access callback' => 'user_access',
     'access arguments' => array('access content'),
     'type' => MENU_LOCAL_TASK,
   );
-  $items['user/%/track/posts'] = array(
+  $items['user/[user_from_arg]/track/posts'] = array(
     'title' => t('Track posts'),
     'type' => MENU_DEFAULT_LOCAL_TASK,
   );

=== modified file 'modules/user/user.module'
--- modules/user/user.module	2007-02-02 15:25:25 +0000
+++ modules/user/user.module	2007-02-05 23:40:31 +0000
@@ -730,11 +730,15 @@ function user_menu() {
   );
 
   // Registration and login pages.
-  $items['user/login'] = array(
+  $items['user'] = array(
     'title' => t('Log in'),
     'page callback' => 'drupal_get_form',
     'page arguments' => array('user_login'),
     'access callback' => 'user_is_anonymous',
+  );
+
+  $items['user/login'] = array(
+    'title' => t('Log in'),
     'type' => MENU_DEFAULT_LOCAL_TASK,
   );
 
@@ -753,7 +757,7 @@ function user_menu() {
     'access callback' => 'user_is_anonymous',
     'type' => MENU_LOCAL_TASK,
   );
-  $items['user/reset/%/%/%'] = array(
+  $items['user/reset/[]/[]/[]'] = array(
     'title' => t('Reset password'),
     'page callback' => 'drupal_get_form',
     'page arguments' => array('user_pass_reset', 2, 3, 4),
@@ -857,7 +861,6 @@ function user_menu() {
       'page callback' => 'user_admin',
       'page arguments' => array('search'),
       'access arguments' => array('administer users'),
-      'type' => MENU_NORMAL_ITEM,
     );
   }
 
@@ -868,32 +871,22 @@ function user_menu() {
     'weight' => 10,
   );
 
-  $items['user'] = array(
-    'title' => t('My account'),
-    'page callback' => 'user_view',
-    'page arguments' => array(1),
-    'access callback' => 'user_view_access',
-    'access arguments' => array(1),
-    'map callback' => 'user_load_self',
-  );
-
-  $items['user/%'] = array(
+  $items['user/[user_current]'] = array(
     'title' => t('My account'),
     'page callback' => 'user_view',
     'page arguments' => array(1),
     'access callback' => 'user_view_access',
     'access arguments' => array(1),
-    'map arguments' => array('user_load', 1),
-    'type' => MENU_CALLBACK,
+    'parent' => '',
   );
 
-  $items['user/%/view'] = array(
+  $items['user/[user_from_arg]/view'] = array(
     'title' => t('View'),
     'type' => MENU_DEFAULT_LOCAL_TASK,
     'weight' => -10,
   );
 
-  $items['user/%/delete'] = array(
+  $items['user/[user_from_arg]/delete'] = array(
     'title' => t('Delete'),
     'page callback' => 'user_edit',
     'access callback' => 'user_access',
@@ -901,7 +894,7 @@ function user_menu() {
     'type' => MENU_CALLBACK,
   );
 
-  $items['user/%/edit'] = array(
+  $items['user/[user_from_arg]/edit'] = array(
     'title' => t('Edit'),
     'page callback' => 'drupal_get_form',
     'page arguments' => array('user_edit'),
@@ -913,7 +906,7 @@ function user_menu() {
   $empty_account = new stdClass();
   if (($categories = _user_categories($empty_account)) && (count($categories) > 1)) {
     foreach ($categories as $key => $category) {
-      $items['user/%/edit/'. $category['name']] = array(
+      $items['user/[user_from_arg]/edit/'. $category['name']] = array(
         'title' => $category['title'],
         'page arguments' => array('user_edit', 3),
         'type' => $category['name'] == 'account' ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK,
@@ -928,6 +921,20 @@ function user_init() {
   drupal_add_css(drupal_get_path('module', 'user') .'/user.css', 'module');
 }
 
+function user_from_arg($operation, $arg) {
+  if ($operation == MENU_HANDLE_REQUEST) {
+    return is_numeric($arg) ? user_load($arg) : FALSE;
+  }
+  return $arg;
+}
+
+function user_current($operation, $arg) {
+  if ($operation == MENU_HANDLE_REQUEST) {
+    return is_numeric($arg) ? user_load($arg) : FALSE;
+  }
+  return $GLOBALS['user']->uid;
+}
+
 /**
  * Accepts an user object, $account, or a DA name and returns an associative
  * array of modules and DA names. Called at external login.
@@ -1588,6 +1595,7 @@ function user_edit_submit($form_id, $for
 function user_view($account) {
   global $user;
 
+  drupal_set_title(check_plain($account->name));
   // Retrieve and merge all profile fields:
   $fields = array();
   foreach (module_list() as $module) {

=== modified file 'modules/watchdog/watchdog.module'
--- modules/watchdog/watchdog.module	2007-01-31 15:49:22 +0000
+++ modules/watchdog/watchdog.module	2007-02-05 15:09:56 +0000
@@ -49,7 +49,7 @@ function watchdog_menu() {
     'page callback' => 'watchdog_top',
     'page arguments' => array('access denied'),
   );
-  $items['admin/logs/event/%'] = array(
+  $items['admin/logs/event/[]'] = array(
     'title' => t('Details'),
     'page callback' => 'watchdog_event',
     'page arguments' => array(3),

