Index: includes/bootstrap.inc===================================================================
RCS file: /cvs/drupal/drupal/includes/bootstrap.inc,v
retrieving revision 1.26
diff -u -r1.26 bootstrap.inc
--- includes/bootstrap.inc   9 Sep 2004 05:51:08 -0000 1.26
+++ includes/bootstrap.inc   13 Sep 2004 16:07:49 -0000
@@ -9,25 +9,42 @@
 /**
  * Locate the appropriate configuration file.
  *
- * Try finding a matching configuration file by stripping the website's
- * URI from left to right.  If no configuration file is found, return the
- * default value, "conf".
+ * Try finding a matching configuration directory by stripping the
+ * website's hostname from left to right and pathname from right to
+ * left.  If no configuration file is found, return a default value
+ * '$confdir/default'.  Example for a ficticious site installed at
+ * http://www.drupal.org/test:
+ *
+ * 1. www.drupal.org.test
+ * 2. drupal.org.test
+ * 3. www.drupal.org
+ * 4. drupal.org
+ * 5. default
  */
 function conf_init() {
-  $uri = $_SERVER['PHP_SELF'];
+  static $conf = '';
 
-  $file = strtolower(strtr($_SERVER['HTTP_HOST'] . substr($uri, 0, strrpos($uri, '/')), '/:', '..'));
+  if ($conf) {
+    return $conf;
+  }
 
-  while (strlen($file) > 4) {
-    if (file_exists('includes/'. $file .'.php')) {
-      return $file;
-    }
-    else {
-      $file = substr($file, strpos($file, '.') + 1);
+  $uri = explode('/', $_SERVER['PHP_SELF']);
+  $server = explode('.', $_SERVER['HTTP_HOST']);
+  $confdir = 'conf';
+
+  for ($i = count($uri) - 1; $i > 0; $i--) {
+    for ($j = count($server); $j > 1; $j--) {
+      $dir = implode('.', array_slice($server, -$j)) . implode('.', array_slice($uri, 0, $i));
+
+      if (file_exists("$confdir/$dir/config.php")) {
+        $conf = "$confdir/$dir";
+        return $conf;
+      }
     }
   }
 
-  return 'conf';
+  $conf = "$confdir/default";
+  return $conf;
 }
 
 /**
@@ -432,7 +449,7 @@
 unset($conf);
 $config = conf_init();
 
-include_once "includes/$config.php";
+include_once "$config/config.php";
 include_once 'includes/database.inc';
 include_once 'includes/session.inc';
 include_once 'includes/module.inc';
Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.388
diff -u -r1.388 common.inc
--- includes/common.inc 9 Sep 2004 13:36:00 -0000 1.388
+++ includes/common.inc 13 Sep 2004 16:07:49 -0000
@@ -1870,6 +1870,89 @@
   return $output;
 }
 
+/**
+ * Returns and optionally sets the filename for a system item (module,
+ * theme, etc.).  The filename, whether provided, cached, or retrieved
+ * from the database, is only returned if the file exists.
+ *
+ * @param $type
+ *   The type of the item (i.e. theme, theme_engine, module).
+ * @param $name
+ *   The name of the item for which the filename is requested.
+ * @param $filename
+ *   The filename of the item if it is to be set explicitly rather
+ *   than by consulting the database.
+ *
+ * @return
+ *   The filename of the requested item.
+ */
+function drupal_filename($type, $name, $filename = NULL) {
+  static $files = array();
+
+  if (!$files[$type]) {
+    $files[$type] = array();
+  }
+
+  if ($filename) {
+    $files[$type][$name] = $filename;
+  }
+  elseif (!$files[$type][$name]) {
+    $files[$type][$name] = db_result(db_query("SELECT filename FROM {system} WHERE name = '%s' AND type = '%s'", $name, $type));
+  }
+
+  if ($files[$type][$name] && !file_exists($files[$type][$name])) {
+    unset($files[$type][$name]);
+  }
+
+  return $files[$type][$name];
+}
+
+/**
+ * Returns the path to a system item (module/theme).
+ *
+ * @param $type
+ *   The type of the item (theme/module).
+ * @param $name
+ *   The name of the item for which the path is requested.
+ *
+ * @return
+ *   The path to the requested item.
+ */
+function drupal_path($type, $name) {
+  return dirname(drupal_filename($type, $name));
+}
+
+/**
+ * Includes a file with the provided type and name.  This prevents
+ * including a theme, engine, module, etc., more than once.
+ *
+ * @param $type
+ *   The type of item to load (i.e. theme, theme_engine, module).
+ * @param $name
+ *   The name of the item to load.
+ *
+ * @return
+ *   TRUE if the item is loaded or has already been loaded.
+ */
+function drupal_load($type, $name) {
+  static $files = array();
+
+  if ($file[$type][$name]) {
+    return TRUE;
+  }
+
+  $filename = drupal_filename($type, $name);
+
+  if ($filename) {
+    include_once($filename);
+    $files[$type][$name] = TRUE;
+
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
 include_once 'includes/theme.inc';
 include_once 'includes/pager.inc';
 include_once 'includes/menu.inc';
Index: includes/file.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/file.inc,v
retrieving revision 1.23
diff -u -r1.23 file.inc
--- includes/file.inc 9 Sep 2004 05:51:08 -0000 1.23
+++ includes/file.inc 13 Sep 2004 16:07:49 -0000
@@ -428,24 +428,47 @@
 }
 
 /**
- * Finds all files that match a given mask in a given directory. Searches
- * recursively.
+ * Finds all files that match a given mask in a given
+ * directory. Searches recursively.
+ *
+ * @param $dir
+ *   The base directory for the scan.
+ * @param $mask
+ *   The regular expression of the files to find.
+ * @param $nomask
+ *   An array of files/directories to ignore.
+ * @param $callback
+ *   The callback function to call for each match.
+ * @param $key
+ *   The key to be used for the returned array of files.  Possible
+ *   values are "filename", for the path starting with $dir,
+ *   "basename", for the basename of the file, and "name" for the name
+ *   of the file without an extension.
+ *
+ * @return
+ *   An associative array (keyed on the provided key) of objects with
+ *   "path", "basename", and "name" members corresponding to the
+ *   matching files.
  */
-function file_scan_directory($dir, $mask, $nomask = array('.', '..', 'CVS'), $callback = 0) {
+function file_scan_directory($dir, $mask, $nomask = array('.', '..', 'CVS'), $callback = 0, $key = "filename") {
   $files = array();
+  $key = (strstr('|filename|basename|name|', "|$key|") ? $key : 'filename');
   if (is_dir($dir) && $handle = opendir($dir)) {
     while ($file = readdir($handle)) {
       if (!in_array($file, $nomask)) {
         if (is_dir("$dir/$file")) {
-          $files = array_merge($files, file_scan_directory("$dir/$file", $mask, $nomask, $callback));
+          $files = array_merge($files, file_scan_directory("$dir/$file", $mask, $nomask, $callback, $key));
         }
         elseif (ereg($mask, $file)) {
-          $name = basename($file);
-          $files["$dir/$file"] = new stdClass();
-          $files["$dir/$file"]->filename = "$dir/$file";
-          $files["$dir/$file"]->name = substr($name, 0, strrpos($name, '.'));
+          $filename = "$dir/$file";
+          $basename = basename($file);
+          $name = substr($basename, 0, strrpos($basename, '.'));
+          $files[$$key] = new stdClass();
+          $files[$$key]->filename = $filename;
+          $files[$$key]->basename = $basename;
+          $files[$$key]->name = $name;
           if ($callback) {
-            $callback("$dir/$file");
+            $callback($filename);
           }
         }
       }
Index: includes/module.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/module.inc,v
retrieving revision 1.57
diff -u -r1.57 module.inc
--- includes/module.inc 9 Sep 2004 05:51:08 -0000 1.57
+++ includes/module.inc 13 Sep 2004 16:07:49 -0000
@@ -62,7 +62,6 @@
         $throttle = ($module->throttle && variable_get('throttle_level', 0) > 4);
         if (!$throttle) {
           $list[$module->name] = $module->name;
-          module_set_filename($module->name, $module->filename);
         }
       }
     }
@@ -72,85 +71,19 @@
 }
 
 /**
- * Set the filename of a module, for future loading through module_load()
- *
- * @param $module
- *   Name of the module which to specify the filename of.
- * @param $pa
- *   Filename of the module named $module.
- * @return
- *   Filename of module, if no $path has been specified.
- */
-function module_set_filename($module, $path = null) {
-  static $list;
-
-  if ($path) {
-    $list[$module] = $path;
-  }
-  else {
-    return $list[$module] ? $list[$module] : "modules/$module.module";
-  }
-}
-
-/**
- * Retrieve the filename of a module
- *
- * @param $module
- *   Name of the module which to retrieve the filename of.
- * @return
- *   Filename of module.
- */
-function module_get_filename($module) {
-  return module_set_filename($module);
-}
-
-/**
- * Retrieve the path of a module
- *
- * @param $module
- *   Name of the module which to retrieve the path of.
- * @return
- *   Path of module.
- */
-function module_get_path($module) {
-  return dirname(module_get_filename($module));
-}
-
-/**
- * Load a module into Drupal, but check first wether a module by the same name
- * has been loaded, and that the filename being included exists.
- * @param $module
- *   The name of the module to be loaded.
- * @return
- *   TRUE if the load was successfull.
- */
-function module_load($module) {
-  static $loaded = array();
-
-  if (!$loaded[$module]) {
-    $filename = module_get_filename($module);
-    if (file_exists($filename)) {
-      include_once($filename);
-      $loaded[$module] = $filename;
-      return true;
-    }
-  }
-  return false;
-}
-
-
-/**
  * Load all the modules that have been enabled in the system table.
  *
  * @return
- *   TRUE if all modules were loaded successfully
+ *   TRUE if all modules were loaded successfully.
  */
 function module_load_all() {
   $list = module_list();
-  $status = true;
+  $status = TRUE;
+
   foreach ($list as $module) {
-    $status = $status && module_load($module);
+    $status = $status && drupal_load('module', $module);
   }
+
   return $status;
 }
 
Index: includes/theme.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/theme.inc,v
retrieving revision 1.215
diff -u -r1.215 theme.inc
--- includes/theme.inc 9 Sep 2004 05:51:08 -0000  1.215
+++ includes/theme.inc 13 Sep 2004 16:07:49 -0000
@@ -61,7 +61,7 @@
   else {
     // File is a template/theme
     // Load its CSS, if it exists
-    if (file_exists($stylesheet = dirname($themes[$theme]->filename) .'/style.css')) {
+    if (file_exists($stylesheet = dirname($themes[$theme]->filename) . '/style.css')) {
       theme_add_style($stylesheet);
     }
   }
Index: modules/system.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/system.module,v
retrieving revision 1.173
diff -u -r1.173 system.module
--- modules/system.module 12 Sep 2004 17:18:36 -0000 1.173
+++ modules/system.module 13 Sep 2004 16:07:50 -0000
@@ -249,175 +249,144 @@
 }
 
 /**
- * Inventory theme engines and insert entries for them into the system table
- */
-function system_theme_engine_inventory($directory) {
-  $engines = array();
-
-  // Remove all theme engines from the system table
-  db_query('DELETE FROM {system} WHERE type = \'%s\'', 'theme_engine');
-
-  // Find theme engines in the directory and insert into database
-  $files = file_scan_directory($directory. '/engines', '\.engine$');
-
-  foreach ($files as $filename => $file) {
-    module_set_filename($file->name, $filename);
-    module_load($file->name);
-
-    $info->name = $file->name;
-    $info->filename = $file->filename;
-    $engines[$info->name] = $info;
-
-    db_query('INSERT INTO {system} (name, type, filename, status, throttle, bootstrap) VALUES (\'%s\', \'%s\', \'%s\', %d, %d, %d)', $info->name, 'theme_engine', $filename, 1, 0, 0);
-  }
-  return $engines;
-}
-
-/**
- * Retrieves an array of a particular type of files (specified by $type) in a particular $directory
- * and their current status in the system table.
- */
-function system_get_files($search, $type, $directory) {
-  // Find files in the directory.
-  $files = file_scan_directory($directory, $search);
-
-  return $files;
-}
-
-/**
  * Retrieves the current status of an array of files in the system table.
  */
 function system_get_files_database(&$files, $type) {
   // Extract current files from database.
-  $result = db_query('SELECT filename, type, status, throttle FROM {system} WHERE type = \'%s\'', $type);
+  $result = db_query("SELECT name, type, status, throttle FROM {system} WHERE type = '%s'", $type);
   while ($file = db_fetch_object($result)) {
-    if (is_object($files[$file->filename])) {
+    if (is_object($files[$file->name])) {
       foreach ($file as $key => $value) {
-        $files[$file->filename]->$key = $value;
+        if (!$files[$file->name]->$key) {
+          $files[$file->name]->$key = $value;
+        }
       }
     }
   }
 }
 
 /**
- * Obtains information about each theme in the $files array
- * Also updates the system table
+ * Collect data about all currently available themes
  */
-function system_obtain_theme_info($files, $directory) {
-  foreach ($files as $filename => $file) {
-    if ($file->theme) {
-      // file is a style
-      $info->description = $file->theme;
-      $info->style = TRUE;
-    }
-
-    if (strpos($filename, '.theme')) {
-      // file is a theme
-      module_set_filename($file->name, $filename);
-      module_load($file->name);
-      $info->description = '';
-      $info->prefix = basename($filename, '.theme');
-    }
-    elseif ($info->style && !$file->engine) {
-      $info->prefix = $info->description;
-    }
-    else {
-      // file is a template
-      $info->description = $info->style ? $info->description : $file->engine;
-      $info->template = TRUE;
-      $info->prefix = basename($file->engine, '.engine');
-    }
-
-    $info->filename = $filename;
-    $info->path = pathinfo($info->filename);
-    $info->name = str_replace(array($directory .'/'), '', $info->path['dirname']);
-    $info->shortname = basename($info->name);
-    $info->screenshot = dirname($info->filename) .'/screenshot.png';
+function system_theme_data() {
+  // Find themes
+  $themes = system_listing('\.theme$', 'themes');
 
-    $info->status = $file->status;
-
-    $themes[$info->name] = $info;
+  // Find theme engines
+  $engines = system_listing('\.engine$', 'themes/engines');
 
-    // Update the contents of the system table:
-    db_query('DELETE FROM {system} WHERE filename = \'%s\' AND type = \'%s\'', $info->filename, 'theme');
-    db_query('INSERT INTO {system} (name, description, type, filename, status, throttle, bootstrap) VALUES (\'%s\', \'%s\', \'%s\', \'%s\', %d, %d, %d)', $info->name, $info->description, 'theme', $info->filename, $info->status, 0, 0);
+  // can't iterate over array itself as it uses a copy of the array items
+  foreach (array_keys($themes) as $key) {
+    drupal_filename('theme', $themes[$key]->name, $themes[$key]->filename);
+    drupal_load('theme', $themes[$key]->name);
+    $themes[$key]->description = dirname($themes[$key]->filename);
+    $themes[$key]->owner = $themes[$key]->filename;
+    $themes[$key]->prefix = $key;
   }
-  return $themes;
-}
-
-/**
- * Collect data about all currently available themes
- */
-function system_theme_data($directory) {
-  // Find theme engines
-  $engines = system_theme_engine_inventory($directory);
 
-  // Get current list of themes and their present status in the system table.
-  $files = system_get_files('\.theme$', 'theme', $directory);
+  // Remove all theme engines from the system table
+  db_query("DELETE FROM {system} WHERE type = 'theme_engine'");
 
   // Add templates to the site listing
   foreach ($engines as $engine) {
-    foreach (call_user_func($engine->name .'_templates', $directory) as $template) {
-      $template_files[$template->filename] = $template;
-      $template_files[$template->filename]->engine = $engine->filename;
-      foreach ($files as $file) {
-        // do not double-insert templates with theme files in their directory
-        if (dirname($template->filename) == dirname($file->filename)) {
-          unset($template_files[$template->filename]);
-        }
-      }
+    drupal_filename('theme_engine', $engine->name, $engine->filename);
+    drupal_load('theme_engine', $engine->name);
+    db_query("INSERT INTO {system} (name, type, filename, status, throttle, bootstrap) VALUES ('%s', '%s', '%s', %d, %d, %d)", $engine->name, 'theme_engine', $engine->filename, 1, 0, 0);
+
+    foreach (call_user_func($engine->name . '_templates') as $template) {
+      $template->template = TRUE;
+      $template->name = basename(dirname($template->filename));
+      $template->basename = $template->name;
+      $template->description = dirname($template->filename);
+      $template->owner = $engine->filename;
+      $template->prefix = $engine->name;
+      $themes[$template->name] = $template;
     }
   }
-  $files = array_merge($files, $template_files);
 
   // Find styles in each theme's directory.
-  foreach ($files as $file) {
-    foreach (system_get_files("style.css$", 'theme', dirname($file->filename)) as $style) {
+  foreach ($themes as $theme) {
+    foreach (file_scan_directory(dirname($theme->filename), "style.css$") as $style) {
       // do not double-insert themes with css files in their directory
-      if (dirname($style->filename) != dirname($file->filename)) {
-        $style_files[$style->filename] = $style;
-        $path = pathinfo($file->filename);
-        $style_files[$style->filename]->theme = str_replace(array($directory .'/'), '', $path['dirname']);
-        if ($file->engine) {
-          $style_files[$style->filename]->engine = $file->engine;
-        }
+      if (dirname($style->filename) != dirname($theme->filename)) {
+        $style->style = TRUE;
+        $style->name = basename(dirname($style->filename));
+        $style->description = dirname($style->filename);
+        $style->owner = $theme->filename;
+        $style->prefix = $theme->name;
+        $themes[$style->name] = $style;
       }
     }
   }
-  $files = array_merge($files, $style_files);
 
   // Extract current files from database.
-  system_get_files_database($files, 'theme');
+  system_get_files_database($themes, 'theme');
 
-  // Build an array of information about each theme for use in displaying the selection table.
-  return system_obtain_theme_info($files, $directory);
+  db_query("DELETE FROM {system} WHERE type = 'theme'");
+
+  foreach ($themes as $theme) {
+    db_query("INSERT INTO {system} (name, description, type, filename, status, throttle, bootstrap) VALUES ('%s', '%s', '%s', '%s', %d, %d, %d)", $theme->name, $theme->owner, 'theme', $theme->filename, $theme->status, 0, 0);
+  }
+
+  return $themes;
+}
+
+/**
+ * Returns an array of files objects of the given type from both the
+ * site-wide directory (i.e. modules/) or site-specific directory
+ * (i.e. conf/somesite/modules/).  The array is keyed on the basename
+ * of the file, so if a file with the same name appears in both
+ * directories, the site-specific version shadows any other.
+ *
+ * @param $mask
+ *   The regular expression of the files to find.
+ * @param $directory
+ *   The subdirectory name in which the files are found.  For example,
+ *   'modules' will search in both modules/ and
+ *   conf/somesite/modules/.
+ *
+ * @return
+ *   An array of file objects of the specified type.
+ */
+function system_listing($mask, $directory, $key = 'name') {
+  $config = conf_init();
+  $searchdir = array($directory);
+  $files = array();
+
+  if (file_exists("$config/$directory")) {
+    $searchdir[] = "$config/$directory";
+  }
+
+  // Get current list of items
+  foreach ($searchdir as $dir) {
+    $files = array_merge($files, file_scan_directory($dir, $mask, array('.', '..', 'CVS'), 0, $key));
+  }
+
+  return $files;
 }
 
 /**
  * Generate a list of all the available theme/style combinations.
  */
 function system_theme_listing() {
-  $directory = 'themes';
-
-  $themes = system_theme_data($directory);
+  $themes = system_theme_data();
   ksort($themes);
 
-  foreach ($themes as $key => $info) {
+  foreach ($themes as $name => $info) {
+    $info->screenshot = dirname($info->filename) . '/screenshot.png';
     $row = array();
 
     // Screenshot column.
-    $row[] = file_exists($info->screenshot) ? theme('image', $info->screenshot, t('Screenshot for %theme theme', array('%theme' => $info->shortname)), '', 'class="screenshot"', false) : t('no screenshot');
+    $row[] = file_exists($info->screenshot) ? theme('image', $info->screenshot, t('Screenshot for %theme theme', array('%theme' => $info->name)), '', 'class="screenshot"', false) : t('no screenshot');
 
     // Information field.
-    $field = '<strong>'. $info->shortname .'</strong>';
-    $field .= '<br /><em>themes/'. $key .'</em>';
-    $row[] = $field;
+    $row[] = "<strong>$info->name</strong><br /><em>$info->description</em>";
 
     // enabled, default, and operations columns
-    $row[] = array('data' => form_checkbox('', 'status]['. $info->filename, 1, $info->status), 'align' => 'center');
-    $row[] = array('data' => form_radio('', 'theme_default', $info->filename, (variable_get('theme_default', 'bluemarine') == $key) ? 1 : 0), 'align' => 'center');
-    if (function_exists($info->prefix .'_settings') || function_exists($info->prefix .'_features')) {
-      $row[] = array('data' => l(t('configure'), 'admin/themes/settings/'. str_replace('/', '.', $key)), 'align' => 'center');
+    $row[] = array('data' => form_checkbox('', 'status]['. $info->name, 1, $info->status), 'align' => 'center');
+    $row[] = array('data' => form_radio('', 'theme_default', $info->name, (variable_get('theme_default', 'bluemarine') == $name) ? 1 : 0), 'align' => 'center');
+    if (function_exists($info->prefix . '_settings') || function_exists($info->prefix . '_features')) {
+      $row[] = array('data' => l(t('configure'), 'admin/themes/settings/' . str_replace('/', '.', preg_replace('<^.*themes/(.*)$>', '$1', $info->description))), 'align' => 'center');
     }
     else {
       $row[] = '';
@@ -435,28 +404,25 @@
  * Generate a list of all the available modules, as well as update the system list.
  */
 function system_module_listing() {
-  $directory = 'modules';
-
   // Get current list of modules
-  $files = system_get_files('\.module$', 'module', $directory);
+  $files = system_listing('\.module$', 'modules');
 
   // Extract current files from database.
   system_get_files_database($files, 'module');
 
   ksort($files);
 
-  $required = array('modules/admin.module', 'modules/block.module', 'modules/filter.module', 'modules/system.module', 'modules/user.module', 'modules/watchdog.module');
+  $required = array('admin', 'block', 'filter', 'system', 'user', 'watchdog');
   // the throttle mechanism requires additional modules always be enabled
-  $throttle_required = array_merge($required, array('modules/statistics.module', 'modules/throttle.module'));
+  $throttle_required = array_merge($required, array('statistics', 'throttle'));
 
   $header = array(t('Name'), t('Description'), t('Enabled'), t('Throttle'));
 
   foreach ($files as $filename => $file) {
-    module_set_filename($file->name, $filename);
-    module_load($file->name);
+    drupal_filename('module', $file->name, $file->filename);
+    drupal_load('module', $file->name);
 
-    $info->name = module_invoke($file->name, 'help', 'admin/modules#name') ? module_invoke($file->name, 'help', 'admin/modules#name') : $file->name;
-    $info->description = module_invoke($file->name, 'help', 'admin/modules#description');
+    $file->description = module_invoke($file->name, 'help', 'admin/modules#description');
     // log the critical hooks implemented by this module
     $bootstrap = 0;
     foreach (bootstrap_hooks() as $hook) {
@@ -467,11 +433,11 @@
     }
 
     // Update the contents of the system table:
-    db_query('DELETE FROM {system} WHERE filename = \'%s\' AND type = \'%s\'', $filename, 'module');
-    db_query('INSERT INTO {system} (name, description, type, filename, status, throttle, bootstrap) VALUES (\'%s\', \'%s\', \'%s\', \'%s\', %d, %d, %d)', $info->name, $info->description, 'module', $filename, $file->status, $file->throttle, $bootstrap);
+    db_query("DELETE FROM {system} WHERE name = '%s' AND type = '%s'", $file->name, 'module');
+    db_query("INSERT INTO {system} (name, description, type, filename, status, throttle, bootstrap) VALUES ('%s', '%s', '%s', '%s', %d, %d, %d)", $file->name, $file->description, 'module', $file->filename, $file->status, $file->throttle, $bootstrap);
 
-    $row = array($info->name, $info->description, array('data' => (in_array($filename, $required) ? form_hidden('status]['. $filename, 1) . t('required') : form_checkbox('', 'status]['. $filename, 1, $file->status)), 'align' => 'center'));
-    $row[] = array('data' => (in_array($filename, $throttle_required) ? form_hidden('throttle]['. $filename, 0) . t('required') : form_checkbox(NULL, 'throttle]['. $filename, 1, $file->throttle, NULL, module_exist('throttle') ? NULL : array('disabled' => 'disabled'))), 'align' => 'center');
+    $row = array($file->name, $file->description, array('data' => (in_array($file->name, $required) ? form_hidden('status]['. $file->name, 1) . t('required') : form_checkbox('', 'status]['. $file->name, 1, $file->status)), 'align' => 'center'));
+    $row[] = array('data' => (in_array($file->name, $throttle_required) ? form_hidden('throttle]['. $file->name, 0) . t('required') : form_checkbox(NULL, 'throttle]['. $file->name, 1, $file->throttle, NULL, module_exist('throttle') ? NULL : array('disabled' => 'disabled'))), 'align' => 'center');
     $rows[] = $row;
   }
 
@@ -487,18 +453,17 @@
 
   if ($op == t('Save configuration')) {
     db_query("UPDATE {system} SET status = 0 WHERE type = '%s'", $edit['type']);
-    foreach ($edit['status'] as $filename => $status) {
+    foreach ($edit['status'] as $name => $status) {
       // Make certain that the default theme is enabled to avoid user error
       if (($edit['type'] == 'theme') && ($edit['theme_default'] == $filename)) {
         $status = 1;
       }
 
-      db_query("UPDATE {system} SET status = %d, throttle = %d WHERE filename = '%s'", $status, $edit['throttle'][$filename], $filename);
+      db_query("UPDATE {system} SET status = %d, throttle = %d WHERE type = '%s' AND name = '%s'", $status, $edit['throttle'][$filename], $edit['type'], $name);
     }
+
     if ($edit['type'] == 'theme') {
-      $path = pathinfo($edit['theme_default']);
-      $name = str_replace(array('themes/'), '', $path['dirname']);
-      variable_set('theme_default', $name);
+      variable_set('theme_default', $edit['theme_default']);
     }
 
     cache_clear_all();
@@ -585,8 +550,8 @@
   if ($key) {
     $settings = theme_get_settings($key);
     $var = str_replace('/', '_', 'theme_'. $key .'_settings');
-    $themes = system_theme_data('themes');
-    $features = function_exists($themes[$key]->prefix .'_features') ? call_user_func($themes[$key]->prefix .'_features') : array();
+    $themes = system_theme_data();
+    $features = function_exists($themes[$key]->prefix . '_features') ? call_user_func($themes[$key]->prefix . '_features') : array();
   }
   else {
     $settings = theme_get_settings('');
Index: themes/engines/xtemplate/xtemplate.engine
===================================================================
RCS file: /cvs/drupal/drupal/themes/engines/xtemplate/xtemplate.engine,v
retrieving revision 1.6
diff -u -r1.6 xtemplate.engine
--- themes/engines/xtemplate/xtemplate.engine 9 Sep 2004 13:36:01 -0000 1.6
+++ themes/engines/xtemplate/xtemplate.engine 13 Sep 2004 16:07:50 -0000
@@ -10,15 +10,15 @@
 function xtemplate_init($template) {
   // We cannot use the theme() or path_to_theme() functions here
   if (!class_exists('XTemplate')) {
-    include_once('themes/engines/xtemplate/xtemplate.inc');
+    include_once(drupal_path('theme_engine', 'xtemplate') . '/xtemplate.inc');
   }
   $GLOBALS["xtemplate"] = new StdClass();
   $GLOBALS['xtemplate']->template = new XTemplate(basename($template->filename), dirname($template->filename));
   $GLOBALS['xtemplate']->template->SetNullBlock(' ');  // '' doesnt work!
 }
 
-function xtemplate_templates($directory) {
-  return file_scan_directory($directory, 'xtemplate.xtmpl$');
+function xtemplate_templates() {
+  return system_listing('^xtemplate\.xtmpl$', 'themes', 'filename');
 }
 
 function xtemplate_features() {
[zion:/www/drupal-cvs] root# 