Index: tests/search_by_page.test
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/search_by_page/tests/search_by_page.test,v
retrieving revision 1.1.2.26
diff -u -r1.1.2.26 search_by_page.test
--- tests/search_by_page.test	31 Dec 2010 18:17:05 -0000	1.1.2.26
+++ tests/search_by_page.test	28 Jan 2011 17:35:36 -0000
@@ -2898,3 +2898,87 @@
   }
 }
 
+/**
+ * Tests that Search by Page doesn't get fooled by page output.
+ */
+class SearchByPageOutputTest extends SearchByPageTester {
+
+  public $superuser;
+
+  public static function getInfo() {
+    return array(
+      'name' => t('Search by Page Output Tests'),
+      'description' => t('Test that page title, active trail, etc. do not affect search results display'),
+      'group' => t('Search by Page'),
+      'dependencies' => array('search', 'sbp_test', 'sbp_paths', 'dblog', 'search_by_page'),
+    );
+  }
+
+  public function setUp() {
+    parent::setUp('search', 'search_by_page', 'sbp_paths', 'sbp_test', 'dblog');
+
+    $this->setUpEnvironments();
+
+    $this->superuser = $this->drupalCreateUser(array('administer nodes',
+        'access content', 'administer content types', 'administer blocks',
+        'administer search', 'search content', 'administer search by page',
+        $this->searchPerm($this->envinfo1), 'access administration pages',
+        'administer site configuration', 'administer users',
+        'administer permissions', 'view test private content',
+        'access site reports'));
+
+    $this->drupalLogin($this->superuser);
+
+    // Set up indexing of pages.
+
+    $this->drupalPost('admin/settings/search_by_page/edit/' . $this->envid1,
+      array(
+        'button_label' => t('Search pages'),
+      ),
+      'Save configuration');
+
+    $path_add_path = 'admin/settings/search_by_page/edit/' . $this->envid1 .
+      '/paths/add';
+
+    $this->drupalPost($path_add_path,
+      array(
+        'path' => 'sbp_test_output_page',
+        'title' => t("Output page"),
+        'type' => t('Page'),
+        'snippet' => 'yes',
+        'role' => $this->getNewRoleID($this->superuser),
+      ),
+      'Create new indexed page');
+
+    cache_clear_all('variables', 'cache');
+    variable_init();
+
+    $this->doCronrun();
+    $this->drupalLogin($this->superuser);
+    $this->drupalGet('admin/reports/dblog');
+    $this->assertText(t('Cron run completed'), 'Log shows cron run completed');
+    $this->drupalLogout();
+  }
+
+  /**
+   * Tests that pages can be searched.
+   */
+  function testSearchPages() {
+
+    // Search and verify that the word "wrong" doesn't appear on the page.
+    // It would appear if some of the bad output got through. Also make
+    // sure that the correct output does appear.
+
+    $search_path = $this->envinfo1['page_path'];
+
+    $this->drupalLogin($this->superuser);
+    $this->drupalPost($search_path,
+      array('keys' => 'Trees'),
+      t('Search pages')
+    );
+
+    $this->assertText('Trees', "Found Trees on the search results page");
+    $this->assertText('Apple', "Found Apple on the search results page");
+    $this->assertNoText('Wrong', "Bad output did not make it to the results page");
+  }
+}
Index: tests/sbp_test.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/search_by_page/tests/sbp_test.module,v
retrieving revision 1.1.2.8
diff -u -r1.1.2.8 sbp_test.module
--- tests/sbp_test.module	22 May 2010 00:31:28 -0000	1.1.2.8
+++ tests/sbp_test.module	28 Jan 2011 17:35:35 -0000
@@ -85,7 +85,7 @@
  */
 function sbp_test_node_access_records( $node ) {
   // Only restrict access to nodes marked private
-  if ( $node->test_private ) {
+  if ( isset($node->test_private) && $node->test_private ) {
     $grants = array();
     $grants[] = array(
       'realm' => 'sbp_test',
@@ -109,6 +109,7 @@
  * Node Access Example module on drupal.org.
  */
 function sbp_test_node_grants($account, $op) {
+  $grants = array();
   if ($op == 'view' && user_access('view test private content', $account)) {
     $grants['sbp_test'] = array(888);
   }
@@ -131,9 +132,15 @@
       db_query('DELETE FROM {sbp_test_access} WHERE nid = %d', $node->nid);
       break;
     case 'insert':
+      if (!isset($node->test_private)) {
+        $node->test_private = FALSE;
+      }
       db_query('INSERT INTO {sbp_test_access} (nid, private) VALUES (%d, %d)', $node->nid, $node->test_private);
       break;
     case 'update':
+      if (!isset($node->test_private)) {
+        $node->test_private = FALSE;
+      }
       db_query('UPDATE {sbp_test_access} SET private = %d WHERE nid = %d', $node->test_private, $node->nid);
       break;
   }
@@ -209,6 +216,14 @@
     'type' => MENU_SUGGESTED_ITEM,
   );
 
+  $items['sbp_test_output_page'] = array(
+    'title' => 'Search by Page output Page',
+    'description' => 'Test content',
+    'page callback' => 'sbp_test_make_output_page',
+    'access arguments' => array( 'access content' ),
+    'type' => MENU_SUGGESTED_ITEM,
+  );
+
   return $items;
 }
 
@@ -245,7 +260,36 @@
     '<li>' . t( 'Apple' ) . '</li>' .
     '<li>' . t( 'Pear' ) . '</li>' .
     '</ul>';
+}
+
+/**
+ * Page callback function for path 'sbp_test_output_page'.
+ *
+ * This page intentionally does some things designed to screw up the
+ * Search by Page output:
+ * - Sets the page title.
+ * - Sets the breadcrumb.
+ * - Sets the active trail.
+ * - Prints some output instead of just returning output.
+ */
+function sbp_test_make_output_page() {
+
+  drupal_set_title('wrong page title');
+  print "wrong information printed";
+  drupal_set_breadcrumb(array(l('wrong breadcrumb', '<front>'), l('wrong breadcrumb 2', 'sbp_test_pub_page')));
+
+  $trail = menu_get_active_trail();
+  $i = 1;
+  foreach($trail as $item) {
+    $item['title'] = "wrong trail $i";
+    $i++;
+  }
+  menu_set_active_trail($trail);
 
+  return '<h2>' . t( 'Trees' ) . '</h2>' . '<ul>' .
+    '<li>' . t( 'Apple' ) . '</li>' .
+    '<li>' . t( 'Pear' ) . '</li>' .
+    '</ul>';
 }
 
 /**
Index: search_by_page.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/search_by_page/search_by_page.module,v
retrieving revision 1.1.2.43
diff -u -r1.1.2.43 search_by_page.module
--- search_by_page.module	31 Dec 2010 17:17:52 -0000	1.1.2.43
+++ search_by_page.module	28 Jan 2011 17:35:35 -0000
@@ -542,6 +542,9 @@
   // Index each page, but don't save sessions for the indexing users.
   session_save_session(FALSE);
 
+  // Make sure output from rendering pages does not screw up the cron run.
+  ob_start();
+
   $reasons = array(
     MENU_ACCESS_DENIED => t('access denied'),
     MENU_NOT_FOUND => t('not found'),
@@ -595,8 +598,8 @@
     }
 
     // Check for module override of content.
-    $content = $info['content'];
-    if (!isset($info['content'])) {
+    $content = (isset($info['content'])) ? $info['content'] : NULL;
+    if (!isset($content)) {
       // Mode didn't return content. Render the page to get it.
       // Separate path into main part and query.
       $parts = search_by_page_path_parts($item->page_path);
@@ -660,11 +663,12 @@
     }
   }
 
-  // Switch user back and rebuild permissions cache.
+  // Switch user back, rebuild permissions cache, flush output buffer.
   $user = $save_user;
   user_access('', $user, TRUE);
   $language = $save_language;
   session_save_session($save_sessions);
+  ob_end_clean();
 }
 
 /**
@@ -1410,13 +1414,19 @@
   // Let Search perform the actual search
   $stuff = do_search($keys, 'search_by_page', $join, $where, $args);
 
-  // Save global pager information and page title, because rendering
+  // Save global pager information, page title, etc. because rendering
   // can screw this up.
   $title = drupal_get_title();
   $tmp_parray = $pager_page_array[0];
   $tmp_ptotal = $pager_total[0];
   $tmp_itotal = $pager_total_items[0];
   $tmp_breadcrumb = drupal_get_breadcrumb();
+  $tmp_trail = menu_get_active_trail();
+
+  // Use PHP's output buffering to prevent any output during rendering.
+  // Some modules print things directly when rendering the page, which is
+  // not good practice, but so it goes.
+  ob_start();
 
   // Create array of formatted results for Search
 
@@ -1459,12 +1469,14 @@
     $results[] = $res;
   }
 
-  // Reset page title and pager stuff
+  // Reset page title and pager stuff, and clear the output buffer.
   drupal_set_title($title);
   $pager_page_array[0] = $tmp_parray;
   $pager_total[0] = $tmp_ptotal;
   $pager_total_items[0] = $tmp_itotal;
   drupal_set_breadcrumb($tmp_breadcrumb);
+  menu_set_active_trail($tmp_trail);
+  ob_end_clean();
 
   return $results;
 }
