Index: modules/user/user.module =================================================================== RCS file: /cvs/drupal/drupal/modules/user/user.module,v retrieving revision 1.977 diff -u -9 -p -r1.977 user.module --- modules/user/user.module 20 Apr 2009 04:41:35 -0000 1.977 +++ modules/user/user.module 23 Apr 2009 21:13:11 -0000 @@ -808,19 +808,19 @@ function user_perm() { /** * Implementation of hook_file_download(). * * Ensure that user pictures (avatars) are always downloadable. */ function user_file_download($filepath) { if (strpos($filepath, variable_get('user_picture_path', 'pictures') . '/picture-') === 0) { $info = image_get_info(file_create_path($filepath)); - return array('Content-type: ' . $info['mime_type']); + return array('Content-Type' => $info['mime_type']); } } /** * Implementation of hook_file_references(). */ function user_file_references($file) { // Determine if the file is used by this module. $count = db_query('SELECT COUNT(*) FROM {users} WHERE picture = :fid', array(':fid' => $file->fid))->fetchField(); Index: modules/system/system.api.php =================================================================== RCS file: /cvs/drupal/drupal/modules/system/system.api.php,v retrieving revision 1.27 diff -u -9 -p -r1.27 system.api.php --- modules/system/system.api.php 21 Apr 2009 05:07:08 -0000 1.27 +++ modules/system/system.api.php 23 Apr 2009 21:13:11 -0000 @@ -1243,20 +1243,20 @@ function hook_file_delete($file) { function hook_file_download($filepath) { // Check if the file is controlled by the current module. $filepath = file_create_path($filepath); $result = db_query("SELECT f.* FROM {files} f INNER JOIN {upload} u ON f.fid = u.fid WHERE filepath = '%s'", $filepath); if ($file = db_fetch_object($result)) { if (!user_access('view uploaded files')) { return -1; } return array( - 'Content-Type: ' . $file->filemime, - 'Content-Length: ' . $file->filesize, + 'Content-Type' => $file->filemime, + 'Content-Length' => $file->filesize, ); } } /** * Check installation requirements and do status reporting. * * This hook has two closely related uses, determined by the $phase argument: * checking installation requirements ($phase == 'install') Index: sites/default/default.settings.php =================================================================== RCS file: /cvs/drupal/drupal/sites/default/default.settings.php,v retrieving revision 1.23 diff -u -9 -p -r1.23 default.settings.php --- sites/default/default.settings.php 19 Apr 2009 19:10:08 -0000 1.23 +++ sites/default/default.settings.php 23 Apr 2009 21:13:11 -0000 @@ -270,18 +270,37 @@ $conf = array( * in the X-Forwarded-For headers only if Remote IP address is one of * these, that is the request reaches the web server from one of your * reverse proxies. Otherwise, the client could directly connect to * your web server spoofing the X-Forwarded-For headers. */ # 'reverse_proxy_addresses' => array('a.b.c.d', ...), // Leave the comma here. ); /** + * Page caching: + * + * By default, Drupal sends a "Vary: Cookie" HTTP header for anonymous page + * views. This tells a HTTP proxy that it may return a page from its local + * cache without contacting the web server, if the user sends the same Cookie + * header as the user who originally requested the cached page. Without "Vary: + * Cookie", authenticated users would also be served the anonymous page from + * the cache. If the site has mostly anonymous users except a few known + * editors/administrators, the Vary header can be omitted. This allows for + * better caching in HTTP proxies (including reverse proxies), i.e. even if + * clients send different cookies, they still get content served from the cache + * if aggressive caching is enabled and the minimum cache time is non-zero. + * However, authenticated users should access the site directly (i.e. not use an + * HTTP proxy, and bypass the reverse proxy if one is used) in order to avoid + * getting cached pages from the proxy. + */ +# $conf['omit_vary_cookie'] = TRUE; + +/** * String overrides: * * To override specific strings on your site with or without enabling locale * module, add an entry to this list. This functionality allows you to change * a small number of your site's default English language interface strings. * * Remove the leading hash signs to enable. */ # $conf['locale_custom_strings_en'] = array( Index: includes/common.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/common.inc,v retrieving revision 1.878 diff -u -9 -p -r1.878 common.inc --- includes/common.inc 22 Apr 2009 09:45:02 -0000 1.878 +++ includes/common.inc 23 Apr 2009 21:13:12 -0000 @@ -3021,20 +3021,26 @@ function page_set_cache() { global $user, $base_root; if (page_get_cache(FALSE)) { $cache_page = TRUE; $cache = (object) array( 'cid' => $base_root . request_uri(), 'data' => ob_get_clean(), 'expire' => CACHE_TEMPORARY, 'created' => REQUEST_TIME, - 'headers' => drupal_get_header(), + 'headers' => array(), ); + // Restore preferred header names based on the lower-case names returned + // by drupal_get_header(). + $header_names = _drupal_set_preferred_header_name(); + foreach (drupal_get_header() as $name_lower => $value) { + $cache->headers[$header_names[$name_lower]] = $value; + } 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_page = FALSE; } elseif (zlib_get_coding_type() == FALSE) { $cache->data = gzencode($cache->data, 9, FORCE_GZIP); } Index: includes/bootstrap.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/bootstrap.inc,v retrieving revision 1.276 diff -u -9 -p -r1.276 bootstrap.inc --- includes/bootstrap.inc 22 Apr 2009 09:45:02 -0000 1.276 +++ includes/bootstrap.inc 23 Apr 2009 21:13:12 -0000 @@ -762,37 +762,37 @@ function drupal_set_header($name = NULL, $headers = &drupal_static(__FUNCTION__, array()); if (!isset($name)) { return $headers; } // Save status codes using the special key ":status". if (preg_match('/^\d{3} /', $name)) { $value = $name; - $name = ':status'; + $name = $name_lower = ':status'; } else { - _drupal_set_preferred_header_name($name); - $name = strtolower($name); + $name_lower = strtolower($name); } + _drupal_set_preferred_header_name($name); if (!isset($value)) { - $headers[$name] = FALSE; + $headers[$name_lower] = FALSE; } - elseif (isset($headers[$name]) && $append) { + elseif (isset($headers[$name_lower]) && $append) { // Multiple headers with identical names may be combined using comma (RFC // 2616, section 4.2). - $headers[$name] .= ',' . $value; + $headers[$name_lower] .= ',' . $value; } else { - $headers[$name] = $value; + $headers[$name_lower] = $value; } - drupal_send_headers(array($name => $headers[$name]), TRUE); + drupal_send_headers(array($name => $headers[$name_lower]), TRUE); } /** * Get the HTTP response headers for the current page. * * @param $name * An HTTP header name. If omitted, all headers are returned as name/value * pairs. If an array value is FALSE, the header has been unset. * @return Index: modules/upload/upload.module =================================================================== RCS file: /cvs/drupal/drupal/modules/upload/upload.module,v retrieving revision 1.232 diff -u -9 -p -r1.232 upload.module --- modules/upload/upload.module 11 Apr 2009 22:19:45 -0000 1.232 +++ modules/upload/upload.module 23 Apr 2009 21:13:12 -0000 @@ -150,20 +150,20 @@ function _upload_file_limits($user) { /** * Implementation of hook_file_download(). */ function upload_file_download($filepath) { $filepath = file_create_path($filepath); $file = db_query("SELECT f.*, u.nid FROM {files} f INNER JOIN {upload} u ON f.fid = u.fid WHERE filepath = :path", array(':path' => $filepath))->fetchObject(); if ($file && user_access('view uploaded files') && ($node = node_load($file->nid)) && node_access('view', $node)) { return array( - 'Content-Type: ' . $file->filemime, - 'Content-Length: ' . $file->filesize, + 'Content-Type' => $file->filemime, + 'Content-Length' => $file->filesize, ); } else { return -1; } } /** * Save new uploads and store them in the session to be associated to the node Index: modules/upload/upload.test =================================================================== RCS file: /cvs/drupal/drupal/modules/upload/upload.test,v retrieving revision 1.16 diff -u -9 -p -r1.16 upload.test --- modules/upload/upload.test 22 Apr 2009 09:57:10 -0000 1.16 +++ modules/upload/upload.test 23 Apr 2009 21:13:12 -0000 @@ -45,18 +45,23 @@ class UploadTestCase extends DrupalWebTe $this->uploadFile($node, $files[1]); // Check to see that uploaded file is listed in detail page and actually accessible. $this->assertText(basename($files[0]), basename($files[0]) . ' found on node.'); $this->assertText(basename($files[1]), basename($files[1]) . ' found on node.'); $this->checkUploadedFile(basename($files[0])); $this->checkUploadedFile(basename($files[1])); + // Check that files are also accessible when using private files. + variable_set('file_downloads', FILE_DOWNLOADS_PRIVATE); + $this->checkUploadedFile(basename($files[0])); + $this->checkUploadedFile(basename($files[1])); + // Assure that the attachment link appears on teaser view and has correct count. $node = node_load($node->nid); $teaser = drupal_render(node_build($node, TRUE)); $this->assertTrue(strpos($teaser, format_plural(2, '1 attachment', '@count attachments')), 'Attachments link found on node teaser.'); // Fetch db record and use fid to rename and delete file. $upload = db_fetch_object(db_query('SELECT fid, description FROM {upload} WHERE nid = %d', array($node->nid))); if ($upload) { // Rename file. @@ -189,21 +194,22 @@ class UploadTestCase extends DrupalWebTe } /** * Check that uploaded file is accessible and verify the contents against the original. * * @param string $filename Name of file to verify. */ function checkUploadedFile($filename) { global $base_url; - $file = realpath(file_directory_path() . '/' . $filename); - $this->drupalGet($base_url . '/' . file_directory_path() . '/' . $filename, array('external' => TRUE)); + $file = file_directory_path() . '/' . $filename; + $this->drupalGet(file_create_url($file), array('external' => TRUE)); $this->assertResponse(array(200), 'Uploaded ' . $filename . ' is accessible.'); + $this->assertTrue(strpos($this->drupalGetHeader('Content-Type'), 'text/plain') === 0, t('MIME type is text/plain.')); $this->assertEqual(file_get_contents($file), $this->drupalGetContent(), 'Uploaded contents of ' . $filename . ' verified.'); // Verify file actually is readable and writeable by PHP. $this->assertTrue(is_readable($file), t('Uploaded file is readable.')); $this->assertTrue(is_writeable($file), t('Uploaded file is writeable.')); } /** * Get the role id of the 'simpletest' role associated with a SimpleTest test user. *