Commit a4954415 authored by Dries's avatar Dries

- Patch #777830 by Wim Leers: file_create_url() does not support...

- Patch #777830 by Wim Leers: file_create_url() does not support protocol-relative nor root-relative file URLs.
parent 8b087124
......@@ -343,9 +343,21 @@ function file_create_url($uri) {
$scheme = file_uri_scheme($uri);
if (!$scheme) {
// If this is not a properly formatted stream, then it is a shipped file.
// Therefor, return the URI with the base URL prepended.
return $GLOBALS['base_url'] . '/' . $uri;
// Allow for:
// - root-relative URIs (e.g. /foo.jpg in http://example.com/foo.jpg)
// - protocol-relative URIs (e.g. //bar.jpg, which is expanded to
// http://example.com/bar.jpg by the browser when viewing a page over
// HTTP and to https://example.com/bar.jpg when viewing a HTTPS page)
// Both types of relative URIs are characterized by a leading slash, hence
// we can use a single check.
if (drupal_substr($uri, 0, 1) == '/') {
return $uri;
}
else {
// If this is not a properly formatted stream, then it is a shipped file.
// Therefor, return the URI with the base URL prepended.
return $GLOBALS['base_url'] . '/' . $uri;
}
}
elseif ($scheme == 'http' || $scheme == 'https') {
// Check for http so that we don't have to implement getExternalUrl() for
......
......@@ -2022,7 +2022,6 @@ class FileURLRewritingTest extends FileTestCase {
function setUp() {
parent::setUp('file_test');
variable_set('file_test_hook_file_url_alter', TRUE);
}
/**
......@@ -2031,12 +2030,33 @@ class FileURLRewritingTest extends FileTestCase {
function testShippedFileURL() {
// Test generating an URL to a shipped file (i.e. a file that is part of
// Drupal core, a module or a theme, for example a JavaScript file).
// Test alteration of file URLs to use a CDN.
variable_set('file_test_hook_file_url_alter', 'cdn');
$filepath = 'misc/jquery.js';
$url = file_create_url($filepath);
$this->assertEqual(FILE_URL_TEST_CDN_1 . '/' . $filepath, $url, t('Correctly generated a CDN URL for a shipped file.'));
$filepath = 'misc/favicon.ico';
$url = file_create_url($filepath);
$this->assertEqual(FILE_URL_TEST_CDN_2 . '/' . $filepath, $url, t('Correctly generated a CDN URL for a shipped file.'));
// Test alteration of file URLs to use root-relative URLs.
variable_set('file_test_hook_file_url_alter', 'root-relative');
$filepath = 'misc/jquery.js';
$url = file_create_url($filepath);
$this->assertEqual(base_path() . '/' . $filepath, $url, t('Correctly generated a root-relative URL for a shipped file.'));
$filepath = 'misc/favicon.ico';
$url = file_create_url($filepath);
$this->assertEqual(base_path() . '/' . $filepath, $url, t('Correctly generated a root-relative URL for a shipped file.'));
// Test alteration of file URLs to use protocol-relative URLs.
variable_set('file_test_hook_file_url_alter', 'protocol-relative');
$filepath = 'misc/jquery.js';
$url = file_create_url($filepath);
$this->assertEqual(FILE_URL_TEST_CDN_1 . '/' . $filepath, $url, t('Correctly generated a URL for a shipped file.'));
$this->assertEqual('/' . base_path() . '/' . $filepath, $url, t('Correctly generated a protocol-relative URL for a shipped file.'));
$filepath = 'misc/favicon.ico';
$url = file_create_url($filepath);
$this->assertEqual(FILE_URL_TEST_CDN_2 . '/' . $filepath, $url, t('Correctly generated a URL for a shipped file.'));
$this->assertEqual('/' . base_path() . '/' . $filepath, $url, t('Correctly generated a protocol-relative URL for a shipped file.'));
}
/**
......@@ -2044,9 +2064,24 @@ class FileURLRewritingTest extends FileTestCase {
*/
function testPublicCreatedFileURL() {
// Test generating an URL to a created file.
// Test alteration of file URLs to use a CDN.
variable_set('file_test_hook_file_url_alter', 'cdn');
$file = $this->createFile();
$url = file_create_url($file->uri);
$this->assertEqual(FILE_URL_TEST_CDN_2 . '/' . file_directory_path() . '/' . $file->filename, $url, t('Correctly generated a CDN URL for a created file.'));
// Test alteration of file URLs to use root-relative URLs.
variable_set('file_test_hook_file_url_alter', 'root-relative');
$file = $this->createFile();
$url = file_create_url($file->uri);
$this->assertEqual(base_path() . '/' . file_directory_path() . '/' . $file->filename, $url, t('Correctly generated a root-relative URL for a created file.'));
// Test alteration of file URLs to use a protocol-relative URLs.
variable_set('file_test_hook_file_url_alter', 'protocol-relative');
$file = $this->createFile();
$url = file_create_url($file->uri);
$this->assertEqual(FILE_URL_TEST_CDN_2 . '/' . file_directory_path() . '/' . $file->filename, $url, t('Correctly generated a URL for a created file.'));
$this->assertEqual('/' . base_path() . '/' . file_directory_path() . '/' . $file->filename, $url, t('Correctly generated a protocol-relative URL for a created file.'));
}
}
......
......@@ -286,41 +286,90 @@ function file_test_file_delete($file) {
function file_test_file_url_alter(&$uri) {
// Only run this hook when this variable is set. Otherwise, we'd have to add
// another hidden test module just for this hook.
if (!variable_get('file_test_hook_file_url_alter', FALSE)) {
$alter_mode = variable_get('file_test_hook_file_url_alter', FALSE);
if (!$alter_mode) {
return;
}
$cdn_extensions = array('css', 'js', 'gif', 'jpg', 'jpeg', 'png');
// Most CDNs don't support private file transfers without a lot of hassle,
// so don't support this in the common case.
$schemes = array('public');
$scheme = file_uri_scheme($uri);
// Only serve shipped files and public created files from the CDN.
if (!$scheme || in_array($scheme, $schemes)) {
// Shipped files.
if (!$scheme) {
$path = $uri;
}
// Public created files.
else {
$wrapper = file_stream_wrapper_get_instance_by_scheme($scheme);
$path = $wrapper->getDirectoryPath() . '/' . file_uri_target($uri);
// Test alteration of file URLs to use a CDN.
elseif ($alter_mode == 'cdn') {
$cdn_extensions = array('css', 'js', 'gif', 'jpg', 'jpeg', 'png');
// Most CDNs don't support private file transfers without a lot of hassle,
// so don't support this in the common case.
$schemes = array('public');
$scheme = file_uri_scheme($uri);
// Only serve shipped files and public created files from the CDN.
if (!$scheme || in_array($scheme, $schemes)) {
// Shipped files.
if (!$scheme) {
$path = $uri;
}
// Public created files.
else {
$wrapper = file_stream_wrapper_get_instance_by_scheme($scheme);
$path = $wrapper->getDirectoryPath() . '/' . file_uri_target($uri);
}
// Clean up Windows paths.
$path = str_replace('\\', '/', $path);
// Serve files with one of the CDN extensions from CDN 1, all others from
// CDN 2.
$pathinfo = pathinfo($path);
if (array_key_exists('extension', $pathinfo) && in_array($pathinfo['extension'], $cdn_extensions)) {
$uri = FILE_URL_TEST_CDN_1 . '/' . $path;
}
else {
$uri = FILE_URL_TEST_CDN_2 . '/' . $path;
}
}
// Clean up Windows paths.
$path = str_replace('\\', '/', $path);
// Serve files with one of the CDN extensions from CDN 1, all others from
// CDN 2.
$pathinfo = pathinfo($path);
if (array_key_exists('extension', $pathinfo) && in_array($pathinfo['extension'], $cdn_extensions)) {
$uri = FILE_URL_TEST_CDN_1 . '/' . $path;
}
// Test alteration of file URLs to use root-relative URLs.
elseif ($alter_mode == 'root-relative') {
// Only serve shipped files and public created files with root-relative
// URLs.
$scheme = file_uri_scheme($uri);
if (!$scheme || $scheme == 'public') {
// Shipped files.
if (!$scheme) {
$path = $uri;
}
// Public created files.
else {
$wrapper = file_stream_wrapper_get_instance_by_scheme($scheme);
$path = $wrapper->getDirectoryPath() . '/' . file_uri_target($uri);
}
// Clean up Windows paths.
$path = str_replace('\\', '/', $path);
// Generate a root-relative URL.
$uri = base_path() . '/' . $path;
}
else {
$uri = FILE_URL_TEST_CDN_2 . '/' . $path;
}
// Test alteration of file URLs to use protocol-relative URLs.
elseif ($alter_mode == 'protocol-relative') {
// Only serve shipped files and public created files with protocol-relative
// URLs.
$scheme = file_uri_scheme($uri);
if (!$scheme || $scheme == 'public') {
// Shipped files.
if (!$scheme) {
$path = $uri;
}
// Public created files.
else {
$wrapper = file_stream_wrapper_get_instance_by_scheme($scheme);
$path = $wrapper->getDirectoryPath() . '/' . file_uri_target($uri);
}
// Clean up Windows paths.
$path = str_replace('\\', '/', $path);
// Generate a protocol-relative URL.
$uri = '/' . base_path() . '/' . $path;
}
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment