Index: modules/search/search.pages.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/search/search.pages.inc,v
retrieving revision 1.19
diff -u -r1.19 search.pages.inc
--- modules/search/search.pages.inc	1 May 2010 01:04:24 -0000	1.19
+++ modules/search/search.pages.inc	4 Jun 2010 21:57:38 -0000
@@ -9,16 +9,23 @@
 /**
  * Menu callback; presents the search form and/or search results.
  */
-function search_view($type = 'node') {
+function search_view($type = NULL) {
+  $type = _search_get_active_type($type);
+  if (!$type) {
+    drupal_set_message(t('Search is currently disabled.'), 'error');
+  }
+  $default = _search_get_active_type();
+
   // 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
   if (!isset($_POST['form_id'])) {
     $keys = search_get_keys();
-    if ($_GET['q'] != 'search' && $type == 'node' && !$keys) {
-      // Due to how search_menu() sets up the tabs, path search/node would
-      // display two sets of tabs. So instead, if there are no keywords and
-      // we're on the node tab, just redirect to the bare 'search' path.
+    if ($_GET['q'] != 'search' && $type == $default && !$keys) {
+      // Due to how search_menu() sets up the tabs, path search/node (or
+      // the default search module) would display two sets of tabs. So instead,
+      // if there are no keywords and we're on the default tab, just redirect to
+      // the bare 'search' path.
       drupal_goto('search');
     }
 
@@ -131,10 +138,9 @@
   $keys = $form_state['values']['processed_keys'];
   if ($keys == '') {
     form_set_error('keys', t('Please enter some keywords.'));
-    // Fall through to the drupal_goto() call.
+    // Fall through to the form redirect.
   }
 
-  $type = $form_state['values']['module'] ? $form_state['values']['module'] : 'node';
   $form_state['redirect'] = $form_state['action'] . '/' . $keys;
   return;
 }
Index: modules/search/search.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/search/search.module,v
retrieving revision 1.348
diff -u -r1.348 search.module
--- modules/search/search.module	9 May 2010 19:46:11 -0000	1.348
+++ modules/search/search.module	4 Jun 2010 21:57:38 -0000
@@ -269,6 +269,7 @@
 
   drupal_static_reset('search_get_info');
   if ($active = variable_get('search_active_modules', array('node', 'user'))) {
+    $default = _search_get_active_type();
     foreach (array_intersect_key(search_get_info(), array_flip($active)) as $module => $search_info) {
       $path = 'search/' . $search_info['path'];
       $items[$path] = array(
@@ -277,9 +278,9 @@
         'page arguments' => array($module),
         'access callback' => '_search_menu_access',
         'access arguments' => array($module),
-        'type' => $module == 'node' ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK,
+        'type' => $module == $default ? MENU_DEFAULT_LOCAL_TASK : MENU_LOCAL_TASK,
         'file' => 'search.pages.inc',
-        'weight' => $module == 'node' ? -10 : 0,
+        'weight' => $module == $default ? -10 : 0,
       );
       $items["$path/%menu_tail"] = array(
         'title' => $search_info['title'],
@@ -939,7 +940,8 @@
  *   The search string entered by the user, containing keywords for the search.
  * @param $type
  *   The type of search to render the node for. Must be the name of module
- *   which implements hook_search(). Defaults to 'node'.
+ *   which implements hook_search(). Defaults to 'node', or another active
+ *   module if node searching is disabled.
  * @param $prompt
  *   A piece of text to put before the form (e.g. "Enter your keywords")
  * @return
@@ -949,6 +951,12 @@
   // Add CSS
   drupal_add_css(drupal_get_path('module', 'search') . '/search.css', array('preprocess' => FALSE));
 
+  $type = _search_get_active_type($type);
+  if (!$type) {
+    form_set_error(NULL, t('Search is currently disabled.'), 'error');
+    return $form;
+  }
+
   if (!$action) {
     $action = 'search/' . $type;
   }
@@ -1043,11 +1051,24 @@
 }
 
 /**
- * Perform a standard search on the given keys, and return the formatted results.
+ * Performs a search by calling hook_search_execute().
+ *
+ * @param $keys
+ *   Keyword query to search on.
+ * @param $type
+ *   Search type (module) to search. If not supplied, uses the default search
+ *   type, which is 'node' if node searching is enabled, and another active
+ *   module if not.
+ *
+ * @return
+ *   Formatted search results. No return value if $keys are not supplied or
+ *   if the given search type is not active.
  */
-function search_data($keys = NULL, $type = 'node') {
+function search_data($keys = NULL, $type = NULL) {
+
+  $type = _search_get_active_type($type, FALSE);
 
-  if (isset($keys)) {
+  if (isset($keys) && $type) {
     if (module_hook($type, 'search_execute')) {
       $results = module_invoke($type, 'search_execute', $keys);
       if (module_hook($type, 'search_page')) {
@@ -1183,6 +1204,9 @@
   $text = preg_quote($text, '/');
 }
 
+/**
+ * Implements hook_forms().
+ */
 function search_forms() {
   $forms['search_block_form']= array(
     'callback' => 'search_box',
@@ -1190,3 +1214,58 @@
   );
   return $forms;
 }
+
+/**
+ * Returns an active search type, using the supplied type if possible.
+ *
+ * @param $type
+ *   Type (module name) of search to try to use.
+ * @param $override_allowed
+ *   TRUE if $type can be overridden (if supplied). FALSE if the function should
+ *   return FALSE if $type is inactive and supplied.
+ *
+ * @return
+ *   $type if that search module is currently active. If it is not currently
+ *   active and $override_allowed is TRUE, this function will return 'node' if
+ *   node searching is enabled, or the first active search module if not. In
+ *   all other cases, or if there is not an active module, returns FALSE;
+ */
+function _search_get_active_type($type = NULL, $override_allowed = TRUE) {
+  if (!isset($type)) {
+    $type = 'node';
+    $override_allowed = TRUE;
+  }
+
+  // Figure out which modules are active and have info hooks.
+  $search_hooks = search_get_info();
+  $types = array();
+  foreach (variable_get('search_active_modules', array('node', 'user')) as $module) {
+    if (isset($search_hooks[$module])) {
+      $types[] = $module;
+    }
+  }
+
+  if (!count($types)) {
+    // Nothing is active.
+    return FALSE;
+  }
+
+  if (in_array($type, $types)) {
+    // Requested type exists.
+    return $type;
+  }
+
+  if (!$override_allowed) {
+    // Don't want to override.
+    return FALSE;
+  }
+
+  // Try to use 'node'.
+  if (in_array('node', $types)) {
+    return 'node';
+  }
+
+  // Just use the first active search type.
+  return $types[0];
+}
+
Index: modules/search/search.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/search/search.test,v
retrieving revision 1.63
diff -u -r1.63 search.test
--- modules/search/search.test	12 May 2010 15:53:43 -0000	1.63
+++ modules/search/search.test	4 Jun 2010 21:57:38 -0000
@@ -888,6 +888,9 @@
  * Test config page.
  */
 class SearchConfigSettingsForm extends DrupalWebTestCase {
+  public $search_user;
+  public $search_node;
+
   public static function getInfo() {
     return array(
       'name' => 'Config settings form',
@@ -900,23 +903,26 @@
     parent::setUp('search');
 
     // Login as a user that can create and search content.
-    $this->drupalLogin($this->drupalCreateUser(array('search content', 'administer search', 'administer nodes', 'bypass node access')));
-  }
+    $this->search_user = $this->drupalCreateUser(array('search content', 'administer search', 'administer nodes', 'bypass node access', 'access user profiles', 'administer users'));
+    $this->drupalLogin($this->search_user);
 
-  /**
-   * Verify the search settings form.
-   */
-  function testSearchSettingsPage() {
     // Add a single piece of content and index it.
     $node = $this->drupalCreateNode();
+    $this->search_node = $node;
     // Link the node to itself to test that it's only indexed once.
     $langcode = LANGUAGE_NONE;
     $body_key = "body[$langcode][0][value]";
-    $edit[$body_key] = l($node->title, 'node/' . $node->nid);
+    $edit[$body_key] = l($node->title, 'node/' . $node->nid) . ' pizza sandwich';
     $this->drupalPost('node/' . $node->nid . '/edit', $edit, t('Save'));
 
     node_update_index();
     search_update_totals();
+  }
+
+  /**
+   * Verify the search settings form.
+   */
+  function testSearchSettingsPage() {
 
     // Test that the settings form displays the correct count of items left to index.
     $this->drupalGet('admin/config/search/settings');
@@ -930,6 +936,48 @@
     $this->drupalGet('admin/config/search/settings');
     $this->assertText(t('There is 1 item left to index.'));
   }
+
+  /**
+   * Verify that you can disable individual search modules.
+   */
+  function testSearchModuleDisabling() {
+    // Enable just user search.
+    $edit = array(
+      'search_active_modules[node]' => FALSE,
+      'search_active_modules[user]' => 'user',
+    );
+    $this->drupalPost('admin/config/search/settings', $edit, t('Save configuration'));
+
+    $this->drupalGet('search/user/' . $this->search_user->name);
+    $this->assertNoText('no results', 'User search is running');
+    $this->assertNoText('Content', 'Content search is not shown');
+    $this->assertText($this->search_user->mail, 'User search finds user');
+
+    // Enable just node search.
+    $edit = array(
+      'search_active_modules[node]' => 'node',
+      'search_active_modules[user]' => FALSE,
+    );
+    $this->drupalPost('admin/config/search/settings', $edit, t('Save configuration'));
+
+    $this->drupalGet('search/node/pizza');
+    $this->assertNoText('no results', 'Content search is running');
+    $this->assertNoText('User', 'User search is not shown');
+    $this->assertText($this->search_node->title, 'Node search finds node');
+
+    // Enable neither search.
+    $edit = array(
+      'search_active_modules[node]' => FALSE,
+      'search_active_modules[user]' => FALSE,
+    );
+    $this->drupalPost('admin/config/search/settings', $edit, t('Save configuration'));
+
+    $this->drupalGet('search');
+    $this->assertNoText('Content', 'Content search is not shown');
+    $this->assertNoText('User', 'User search is not shown');
+    $this->assertText(t('Search is currently disabled'), 'Disabled message shows');
+  }
+
 }
 
 /**
Index: modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.1277
diff -u -r1.1277 node.module
--- modules/node/node.module	31 May 2010 08:02:33 -0000	1.1277
+++ modules/node/node.module	4 Jun 2010 21:57:38 -0000
@@ -2558,7 +2558,7 @@
  * Implements hook_form_FORM_ID_alter().
  */
 function node_form_search_form_alter(&$form, $form_state) {
-  if ($form['module']['#value'] == 'node' && user_access('use advanced search')) {
+  if (isset($form['module']) && $form['module']['#value'] == 'node' && user_access('use advanced search')) {
     // Keyword boxes:
     $form['advanced'] = array(
       '#type' => 'fieldset',
