Index: includes/file.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/file.inc,v retrieving revision 1.145 diff -u -p -r1.145 file.inc --- includes/file.inc 16 Nov 2008 19:41:14 -0000 1.145 +++ includes/file.inc 29 Nov 2008 03:59:53 -0000 @@ -89,19 +89,26 @@ define('FILE_STATUS_PERMANENT', 1); * * @param $path A string containing the path of the file to generate URL for. * @return A string containing a URL that can be used to download the file. + * + * @deprecated This function is deprecated in favor of url(file_check_private($path)). */ function file_create_url($path) { - // Strip file_directory_path from $path. We only include relative paths in - // URLs. - if (strpos($path, file_directory_path() . '/') === 0) { + return url(file_check_private($path), array('absolute' => true)); +} + +/** + * All file paths should be checked with this function before links are output. + * If private files are in use, 'system/files/' will be prepended to the path. + * + * @param $path The file path, such as "sites/default/files/druplicon.png". + * @return The Drupal system path. + */ +function file_check_private($path) { + if (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PRIVATE) { $path = trim(substr($path, strlen(file_directory_path())), '\\/'); + $path = 'system/files/' . $path; } - switch (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC)) { - case FILE_DOWNLOADS_PUBLIC: - return $GLOBALS['base_url'] . '/' . file_directory_path() . '/' . str_replace('\\', '/', $path); - case FILE_DOWNLOADS_PRIVATE: - return url('system/files/' . $path, array('absolute' => TRUE)); - } + return $path; } /** Index: includes/common.inc =================================================================== RCS file: /cvs/drupal/drupal/includes/common.inc,v retrieving revision 1.831 diff -u -p -r1.831 common.inc --- includes/common.inc 23 Nov 2008 16:54:47 -0000 1.831 +++ includes/common.inc 29 Nov 2008 03:59:53 -0000 @@ -1554,7 +1554,7 @@ function url($path = NULL, array $option $prefix = empty($path) ? rtrim($options['prefix'], '/') : $options['prefix']; $path = drupal_urlencode($prefix . $path); - if ($clean_url) { + if ($clean_url || file_exists($path)) { // With Clean URLs. if ($options['query']) { return $base . $path . '?' . $options['query'] . $options['fragment']; Index: modules/simpletest/tests/file.test =================================================================== RCS file: /cvs/drupal/drupal/modules/simpletest/tests/file.test,v retrieving revision 1.14 diff -u -p -r1.14 file.test --- modules/simpletest/tests/file.test 27 Nov 2008 08:41:45 -0000 1.14 +++ modules/simpletest/tests/file.test 29 Nov 2008 03:59:53 -0000 @@ -1061,4 +1061,90 @@ class FileSaveDataTest extends FileHookT $file = file_save_data($contents, 'asdf.txt', FILE_EXISTS_ERROR); $this->assertFalse($file, t("Overwriting a file fails when FILE_EXISTS_ERROR is specified.")); } +} + +/** + * Test the url() and file_check_private() function. + * + */ +class FileURLTest extends FileTestCase { + + /** + * Preserve original file system settings. + * + */ + function setUp() { + parent::setUp('file_test'); + $this->file_directory_path = file_directory_path(); + $this->file_downloads = variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC); + } + + function tearDown() { + parent::tearDown(); + variable_set('file_directory_path', $this->file_directory_path); + variable_set('file_downloads', $this->file_downloads); + } + + function getInfo() { + return array( + 'name' => t('File URL creation'), + 'description' => t('Tests the creation of URLs linking to files'), + 'group' => t('File'), + ); + } + + function testPublicFiles() { + variable_set('file_directory_path', $this->file_directory_path); + variable_set('file_downloads', FILE_DOWNLOADS_PUBLIC); + $file = $this->createFile(); + + if (variable_get('clean_url', 0)) { + $this->assertEqual(file_check_private($file->filepath), file_directory_path() . '/' . basename($file->filepath)); + $this->assertEqual(url(file_check_private($file->filepath)), '/' . file_directory_path() . '/' . basename($file->filepath)); + $this->assertEqual(url(file_check_private($file->filepath), array('absolute' => TRUE)), $GLOBALS['base_url'] . '/' . file_directory_path() . '/' . basename($file->filepath)); + } + else { + $this->assertEqual(file_check_private($file->filepath), file_directory_path() . '/' . basename($file->filepath)); + $this->assertEqual(url(file_check_private($file->filepath)), '/' . file_directory_path() . '/' . basename($file->filepath)); + $this->assertEqual(url(file_check_private($file->filepath), array('absolute' => TRUE)), $GLOBALS['base_url'] . '/' . file_directory_path() . '/' . basename($file->filepath)); + } + } + + function testPrivateFilesInDocroot() { + variable_set('file_directory_path', $this->file_directory_path); + variable_set('file_downloads', FILE_DOWNLOADS_PRIVATE); + $file = $this->createFile(); + + if (variable_get('clean_url', 0)) { + $this->assertEqual(file_check_private($file->filepath), 'system/files/' . basename($file->filepath)); + $this->assertEqual(url(file_check_private($file->filepath)), '/system/files/' . basename($file->filepath)); + $this->assertEqual(url(file_check_private($file->filepath), array('absolute' => TRUE)), $GLOBALS['base_url'] . '/system/files/' . basename($file->filepath)); + } + else { + $script = (strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') === FALSE) ? 'index.php' : ''; + $this->assertEqual(file_check_private($file->filepath), 'system/files/' . basename($file->filepath)); + $this->assertEqual(url(file_check_private($file->filepath)), "/$script?q=" . 'system/files/' . basename($file->filepath)); + $this->assertEqual(url(file_check_private($file->filepath), array('absolute' => TRUE)), $GLOBALS['base_url'] . "/$script?q=" . 'system/files/' . basename($file->filepath)); + } + } + + function testPrivateFilesOutDocroot() { + // The assumption is that the temp directory is outside the DocumentRoot, exists, and is writeable + variable_set('file_directory_path', file_directory_temp(). '/' . uniqid() . '_files'); + variable_set('file_downloads', FILE_DOWNLOADS_PRIVATE); + mkdir(file_directory_path()); + $file = $this->createFile(); + + if (variable_get('clean_url', 0)) { + $this->assertEqual(file_check_private($file->filepath), 'system/files/' . basename($file->filepath)); + $this->assertEqual(url(file_check_private($file->filepath)), '/system/files/' . basename($file->filepath)); + $this->assertEqual(url(file_check_private($file->filepath), array('absolute' => TRUE)), $GLOBALS['base_url'] . '/system/files/' . basename($file->filepath)); + } + else { + $script = (strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') === FALSE) ? 'index.php' : ''; + $this->assertEqual(file_check_private($file->filepath), 'system/files/' . basename($file->filepath)); + $this->assertEqual(url(file_check_private($file->filepath)), "/$script?q=" . 'system/files/' . basename($file->filepath)); + $this->assertEqual(url(file_check_private($file->filepath), array('absolute' => TRUE)), $GLOBALS['base_url'] . "/$script?q=" . 'system/files/' . basename($file->filepath)); + } + } } \ No newline at end of file