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
