diff -upr drupal-orig/.htaccess drupal-5.3/.htaccess
--- drupal-orig/.htaccess	2007-09-21 14:24:22.000000000 +0200
+++ drupal-5.3/.htaccess	2007-10-20 07:17:06.000000000 +0200
@@ -102,6 +102,9 @@ DirectoryIndex index.php
   RewriteCond %{REQUEST_FILENAME} !-f
   RewriteCond %{REQUEST_FILENAME} !-d
   RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]
+
+  # work around mod_dir + mod_cache not caching URLs with trailing slashes
+  RewriteRule ^$ index.php?q= [L,QSA]
 </IfModule>
 
 # $Id: .htaccess,v 1.81.2.3 2007/09/21 12:24:22 drumm Exp $
diff -upr drupal-orig/includes/bootstrap.inc drupal-5.3/includes/bootstrap.inc
--- drupal-orig/includes/bootstrap.inc	2007-07-26 21:16:45.000000000 +0200
+++ drupal-5.3/includes/bootstrap.inc	2008-02-11 01:53:47.000000000 +0100
@@ -453,6 +453,21 @@ function variable_del($name) {
 }
 
 /**
+ * Check if a page can be cached. Pages requested with the special
+ * header "X-Script-Chrome:" cannot be cached.
+ */
+function page_may_cache() {
+  global $user;
+  if ($user->uid)
+    return FALSE; /* only anon accesses are cached */
+  if ($_SERVER['REQUEST_METHOD'] != 'GET')
+    return FALSE; /* only GET requests can possibly be cached */
+  if (isset ($_SERVER['HTTP_X_SCRIPT_CHROME']))
+    return FALSE; /* X-Script-Chrome: header present */
+  return TRUE;
+}
+
+/**
  * Retrieve the current page from the cache.
  *
  * Note: we do not serve cached pages when status messages are waiting (from
@@ -463,7 +478,7 @@ function page_get_cache() {
 
   $cache = NULL;
 
-  if (!$user->uid && $_SERVER['REQUEST_METHOD'] == 'GET' && count(drupal_set_message()) == 0) {
+  if (page_may_cache() && count(drupal_set_message()) == 0) {
     $cache = cache_get($base_root . request_uri(), 'cache_page');
 
     if (empty($cache)) {
@@ -552,6 +567,18 @@ function drupal_page_cache_header($cache
   $if_modified_since = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? stripslashes($_SERVER['HTTP_IF_MODIFIED_SINCE']) : FALSE;
   $if_none_match = isset($_SERVER['HTTP_IF_NONE_MATCH']) ? stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) : FALSE;
 
+  // decide content caching for 200 and 304 responses
+  $anon_http_cache_seconds = variable_get ('anon_http_cache_seconds', 0);
+  if ($anon_http_cache_seconds) {
+    // allow RFC 2616 compliant HTTP content caching
+    header ('Expires: ' . gmdate ('D, d M Y H:i:s', time() + $anon_http_cache_seconds) . ' GMT');
+    header ('Cache-Control: ' . sprintf ("max-age=%d", $anon_http_cache_seconds));
+  } else {
+    // The following headers force validation of cache:
+    header("Expires: Sun, 19 Nov 1978 05:00:00 GMT");
+    header("Cache-Control: must-revalidate");
+  }
+
   if ($if_modified_since && $if_none_match
       && $if_none_match == $etag // etag must match
       && $if_modified_since == $last_modified) {  // if-modified-since must match
@@ -565,10 +592,6 @@ function drupal_page_cache_header($cache
   header("Last-Modified: $last_modified");
   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");
-
   // Determine if the browser accepts gzipped data.
   if (@strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') === FALSE && function_exists('gzencode')) {
     // Strip the gzip header and run uncompress.
diff -upr drupal-orig/includes/common.inc drupal-5.3/includes/common.inc
--- drupal-orig/includes/common.inc	2007-10-17 23:28:59.000000000 +0200
+++ drupal-5.3/includes/common.inc	2008-02-11 01:50:10.000000000 +0100
@@ -1877,7 +1877,7 @@ function _drupal_bootstrap_full() {
 function page_set_cache() {
   global $user, $base_root;
 
-  if (!$user->uid && $_SERVER['REQUEST_METHOD'] == 'GET' && count(drupal_get_messages(NULL, FALSE)) == 0) {
+  if (page_may_cache() && 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;
diff -upr drupal-orig/sites/default/settings.php drupal-5.3/sites/default/settings.php
--- drupal-orig/sites/default/settings.php	2007-07-09 06:28:12.000000000 +0200
+++ drupal-5.3/sites/default/settings.php	2008-02-11 02:12:08.000000000 +0100
@@ -161,5 +161,10 @@ ini_set('url_rewriter.tags',        '');
 #   'site_name' => 'My Drupal site',
 #   'theme_default' => 'minnelli',
 #   'anonymous' => 'Visitor',
+    /* setting anon_http_cache_seconds!=0 enables HTTP caching for anonymous
+     * page accesses. this will however affect updating of page counters
+     * and anonymous site access statistics.
+     */
+#   'anon_http_cache_seconds' => 3,
 # );
 
