Index: includes/bootstrap.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/bootstrap.inc,v
retrieving revision 1.257
diff -u -9 -p -r1.257 bootstrap.inc
--- includes/bootstrap.inc	3 Dec 2008 14:51:53 -0000	1.257
+++ includes/bootstrap.inc	16 Dec 2008 18:54:15 -0000
@@ -748,25 +748,28 @@ function drupal_page_cache_header($cache
 
   // Send appropriate response:
   header("Last-Modified: " . gmdate(DATE_RFC1123, $cache->created));
   header("ETag: $etag");
 
   // The following headers force validation of cache:
   header("Expires: Sun, 19 Nov 1978 05:00:00 GMT");
   header("Cache-Control: must-revalidate");
 
-  if (variable_get('page_compression', TRUE)) {
+  if (variable_get('page_compression', TRUE) && extension_loaded('zlib')) {
     // Determine if the browser accepts gzipped data.
-    if (@strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') === FALSE && function_exists('gzencode')) {
+    if (@strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') === FALSE) {
       // Strip the gzip header and run uncompress.
       $cache->data = gzinflate(substr(substr($cache->data, 10), 0, -8));
     }
-    elseif (function_exists('gzencode')) {
+    else {
+      // $cache->data is already gzip'ed, so make sure zlib.output_compression
+      // does not compress it once more.
+      ini_set('zlib.output_compression', '0');
       header('Content-Encoding: gzip');
     }
   }
 
   // Send the original request's headers. We send them one after
   // another so PHP's header() function can deal with duplicate
   // headers.
   $headers = explode("\n", $cache->headers);
   foreach ($headers as $header) {
Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.837
diff -u -9 -p -r1.837 common.inc
--- includes/common.inc	12 Dec 2008 16:07:13 -0000	1.837
+++ includes/common.inc	16 Dec 2008 18:54:15 -0000
@@ -2909,29 +2909,20 @@ function _drupal_bootstrap_full() {
  * @see drupal_page_header
  */
 function page_set_cache() {
   global $user, $base_root;
 
   if (!$user->uid && ($_SERVER['REQUEST_METHOD'] == 'GET' || $_SERVER['REQUEST_METHOD'] == 'HEAD') && count(drupal_get_messages(NULL, FALSE)) == 0) {
     // This will fail in some cases, see page_get_cache() for the explanation.
     if ($data = ob_get_contents()) {
       $cache = TRUE;
-      if (variable_get('page_compression', TRUE) && function_exists('gzencode')) {
-        // We do not store the data in case the zlib mode is deflate.
-        // This should be rarely happening.
-        if (zlib_get_coding_type() == 'deflate') {
-          $cache = FALSE;
-        }
-        elseif (zlib_get_coding_type() == FALSE) {
-          $data = gzencode($data, 9, FORCE_GZIP);
-        }
-        // The remaining case is 'gzip' which means the data is
-        // already compressed and nothing left to do but to store it.
+      if (variable_get('page_compression', TRUE) && extension_loaded('zlib')) {
+        $data = gzencode($data, 9, FORCE_GZIP);
       }
       ob_end_flush();
       if ($cache && $data) {
         cache_set($base_root . request_uri(), $data, 'cache_page', CACHE_TEMPORARY, drupal_get_headers());
       }
     }
   }
 }
 
Index: modules/simpletest/drupal_web_test_case.php
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/drupal_web_test_case.php,v
retrieving revision 1.74
diff -u -9 -p -r1.74 drupal_web_test_case.php
--- modules/simpletest/drupal_web_test_case.php	13 Dec 2008 14:03:21 -0000	1.74
+++ modules/simpletest/drupal_web_test_case.php	16 Dec 2008 18:54:15 -0000
@@ -1128,19 +1128,19 @@ class DrupalWebTestCase {
   /**
    * Check for meta refresh tag and if found call drupalGet() recursively. This
    * function looks for the http-equiv attribute to be set to "Refresh"
    * and is case-sensitive.
    *
    * @return
    *   Either the new page content or FALSE.
    */
   protected function checkForMetaRefresh() {
-    if ($this->drupalGetContent() != '' && $this->parse()) {
+    if (strpos($this->drupalGetContent(), '<meta ') && $this->parse()) {
       $refresh = $this->xpath('//meta[@http-equiv="Refresh"]');
       if (!empty($refresh)) {
         // Parse the content attribute of the meta tag for the format:
         // "[delay]: URL=[page_to_redirect_to]".
         if (preg_match('/\d+;\s*URL=(?P<url>.*)/i', $refresh[0]['content'], $match)) {
           return $this->drupalGet($this->getAbsoluteUrl(decode_entities($match['url'])));
         }
       }
     }
Index: modules/simpletest/tests/bootstrap.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/bootstrap.test,v
retrieving revision 1.9
diff -u -9 -p -r1.9 bootstrap.test
--- modules/simpletest/tests/bootstrap.test	3 Dec 2008 14:51:53 -0000	1.9
+++ modules/simpletest/tests/bootstrap.test	16 Dec 2008 18:54:15 -0000
@@ -83,23 +83,27 @@ class BootstrapIPAddressTestCase extends
     $this->assertTrue(drupal_valid_http_host(), t('HTTP_HOST containing IPv6 loopback is valid'));
   }
 }
 
 class BootstrapPageCacheTestCase extends DrupalWebTestCase {
 
   function getInfo() {
     return array(
       'name' => t('Page cache test'),
-      'description' => t('Enable the page cache and test it with conditional HTTP requests.'),
+      'description' => t('Enable the page cache and test it with different HTTP requests.'),
       'group' => t('Bootstrap')
     );
   }
 
+  function setUp() {
+    parent::setUp('system_test');
+  }
+
   /**
    * Enable cache and examine HTTP headers.
    */
   function testPageCache() {
     variable_set('cache', CACHE_NORMAL);
 
     // Fill the cache.
     $this->drupalGet('');
 
@@ -126,18 +130,77 @@ class BootstrapPageCacheTestCase extends
     $this->assertTrue($this->drupalGetHeader('ETag'), t('An ETag header was sent, indicating that page was cached.'));
 
     $user = $this->drupalCreateUser();
     $this->drupalLogin($user);
     $this->drupalGet('', array(), array('If-Modified-Since: ' . $last_modified, 'If-None-Match: ' . $etag));
     $this->assertResponse(200, t('Conditional request returned 200 OK for authenticated user.'));
     $this->assertFalse($this->drupalGetHeader('ETag'), t('An ETag header was not sent, indicating that page was not cached.'));
   }
 
+  /**
+   * Test page compression when zlib.output_compression is disabled. The test
+   * should pass even if zlib.output_compression is enabled in php.ini,
+   * .htaccess or similar, or if compression is done outside PHP, e.g. by the
+   * mod_deflate Apache module.
+   */
+  function testPageCompression() {
+    variable_set('cache', CACHE_NORMAL);
+    // Disable zlib.output_compression in system_test_boot().
+    variable_set('zlib_output_compression', 'O');
+
+    // Fill the cache. The response is not compressed, unless compression is
+    // done outside PHP, e.g. by the mod_deflate Apache module.
+    $this->drupalGet('', array(), array('Accept-Encoding: gzip,deflate'));
+    $this->assertFalse($this->drupalGetHeader('ETag'), t('An ETag header was not sent, indicating that page was not cached.'));
+
+    // Verify that cached output is compressed.
+    $this->drupalGet('', array(), array('Accept-Encoding: gzip,deflate'));
+    $this->assertTrue($this->drupalGetHeader('ETag'), t('An ETag header was sent, indicating that page was cached.'));
+    $this->assertEqual($this->drupalGetHeader('Content-Encoding'), 'gzip', t('A Content-Encoding header was sent.'));
+    $this->assertTrue(strpos(gzinflate(substr($this->drupalGetContent(), 10, -8)), t('Welcome to your new Drupal website!')), t('Page was gzip compressed.'));
+
+    // Verify that a client with compression support gets an uncompressed page.
+    $this->drupalGet('');
+    $this->assertTrue($this->drupalGetHeader('ETag'), t('An ETag header was sent, indicating that page was cached.'));
+    $this->assertFalse($this->drupalGetHeader('Content-Encoding'), t('A Content-Encoding header was not sent.'));
+    $this->assertText(t('Welcome to your new Drupal website!'), t('Page was not compressed.'));
+
+    // Verify that a client without gzip support gets an uncompressed page.
+    $this->drupalGet('', array(), array('Accept-Encoding: deflate'));
+    $this->assertTrue($this->drupalGetHeader('ETag'), t('An ETag header was sent, indicating that page was cached.'));
+    $this->assertFalse($this->drupalGetHeader('Content-Encoding'), t('A Content-Encoding header was not sent.'));
+    $this->assertText(t('Welcome to your new Drupal website!'), t('Page was not compressed.'));
+  }
+
+  /**
+   * Test page compression when zlib.output_compression is enabled. Requires
+   * that zlib.output_compression is enabled in php.ini, .htaccess or similar.
+   */
+  function testPageCompressionWithZlibOutputCompression() {
+    // zlib.output_compression cannot be enabled at runtime, so this test can
+    // only run, if it has been enabled in php.ini, .htaccess or similar. See
+    // http://bugs.php.net/bug.php?id=33653
+    if (!ini_get('zlib.output_compression')) {
+      return;
+    }
+
+    variable_set('cache', CACHE_NORMAL);
+
+    // Fill the cache. Compression is done by zlib.output_compression.
+    $this->drupalGet('', array(), array('Accept-Encoding: deflate'));
+    $this->assertEqual($this->drupalGetHeader('Content-Encoding'), 'deflate', t('A Content-Encoding header was sent.'));
+
+    // Verify that output is gzip'ed, even though the cache was filled when
+    // zlib.output_compression was doing deflate compression.
+    $this->drupalGet('', array(), array('Accept-Encoding: gzip'));
+    $this->assertEqual($this->drupalGetHeader('Content-Encoding'), 'gzip', t('Page was compressed.'));
+    $this->assertTrue(strpos(gzinflate(substr($this->drupalGetContent(), 10, -8)), t('Welcome to your new Drupal website!')), t('Page was compressed.'));
+  }
 }
 
 class BootstrapVariableTestCase extends DrupalWebTestCase {
 
   function setUp() {
     parent::setUp('system_test');
   }
 
   function getInfo() {
Index: modules/simpletest/tests/system_test.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/system_test.module,v
retrieving revision 1.8
diff -u -9 -p -r1.8 system_test.module
--- modules/simpletest/tests/system_test.module	9 Dec 2008 11:09:26 -0000	1.8
+++ modules/simpletest/tests/system_test.module	16 Dec 2008 18:54:15 -0000
@@ -149,18 +149,23 @@ function system_test_modules_uninstalled
     drupal_set_message(t('hook_modules_uninstalled fired for aggregator'));
   }
 }
 
 /**
  * Implementation of hook_boot().
  */
 function system_test_boot() {
   watchdog('system_test', 'hook_boot');
+
+  $zlib_output_compression = variable_get('zlib_output_compression', NULL);
+  if ($zlib_output_compression !== NULL) {
+    ini_set('zlib.output_compression', $zlib_output_compression);
+  }
 }
 
 /**
  * Implementation of hook_init().
  */
 function system_test_init() {
   // Used by FrontPageTestCase to get the results of drupal_is_front_page().
   if (variable_get('front_page_output', 0) && drupal_is_front_page()) {
     drupal_set_message(t('On front page.'));
