diff --git includes/file.inc includes/file.inc
index 04d41e1..19c534f 100644
--- includes/file.inc
+++ includes/file.inc
@@ -34,7 +34,7 @@ DrupalStreamWrapperRegistry::register('temp',    'DrupalTempStreamWrapper');
  * - filename - Name of the file with no path components. This may differ from
  *   the basename of the filepath if the file is renamed to avoid overwriting
  *   an existing file.
- * - filepath - Path of the file relative to Drupal root.
+ * - uri - URI of the file.
  * - filemime - The file's MIME type.
  * - filesize - The size of the file in bytes.
  * - status - A bitmapped field indicating the status of the file. The first 8
@@ -45,7 +45,9 @@ DrupalStreamWrapperRegistry::register('temp',    'DrupalTempStreamWrapper');
  */
 
 /**
- * Flag to indicate that the 'public' file download method is enabled.
+ * Flag to indicate that the 'public' file download method is enabled (DEPRECATED).
+ *
+ * TODO: Deprecated, cleanup.
  *
  * When using this method, files are available from a regular HTTP request,
  * which provides no additional access restrictions.
@@ -53,7 +55,9 @@ DrupalStreamWrapperRegistry::register('temp',    'DrupalTempStreamWrapper');
 define('FILE_DOWNLOADS_PUBLIC', 1);
 
 /**
- * Flag to indicate that the 'private' file download method is enabled.
+ * Flag to indicate that the 'private' file download method is enabled (DEPRECATED).
+ *
+ * TODO: Deprecated, cleanup.
  *
  * When using this method, all file requests are served by Drupal, during which
  * access-control checking can be performed.
@@ -96,18 +100,24 @@ define('FILE_STATUS_PERMANENT', 1);
 /**
  * Create the download path to a file.
  *
- * @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.
+ * @param $uri
+ *   A string containing the URI of the file to generate a URL for.
+ * @return
+ *   A string containing a URL that can be used to download the file.
  */
-function file_create_url($path) {
-  // Strip file_directory_path from $path. We only include relative paths in
-  // URLs.
-  $path = file_directory_strip($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));
+function file_create_url($uri) {
+  // Flat out check for http so that we don't have to actually implement getExternalUrl()
+  // for the http wrapper.
+  if (DrupalStreamWrapperRegistry::getStreamScheme($uri) == 'http') {
+    // This is already a somewhat properly formatted URL, so do nothing and return.
+    return $uri;
+  }
+
+  if ($wrapper = DrupalStreamWrapperRegistry::getInstanceByUri($uri)) {
+    return $wrapper->getExternalUrl();
+  }
+  else {
+    return FALSE;
   }
 }
 
@@ -115,33 +125,50 @@ function file_create_url($path) {
  * Make sure the destination is a complete path and resides in the file system
  * directory, if it is not prepend the file system directory.
  *
- * @param $destination
- *   A string containing the path to verify. If this value is omitted, Drupal's
- *   'files' directory will be used.
+ * @param $uri
+ *   A string containing the URI to verify. If this value is omitted,
+ *   Drupal's public files directory will be used [public://].
+ * @param $stream
+ *   TRUE indicates that $uri should be a stream and a valid scheme is
+ *   required. FALSE indicates that $uri should be treated as a normal
+ *   path.
  * @return
- *   A string containing the path to file, with file system directory appended
- *   if necessary, or FALSE if the path is invalid (i.e. outside the configured
- *   'files' or temp directories).
+ *   Returns a string containing the path to the stream. If the URI is
+ *   invalid (i.e. outside a valid filesystem directory), FALSE will be
+ *   returned.
  */
-function file_create_path($destination = NULL) {
-  $file_path = file_directory_path();
-  if (is_null($destination)) {
-    return $file_path;
+function file_create_path($uri = NULL, $stream = TRUE) {
+  // If URI is omitted, use Drupal's public files directory [public://].
+  if (is_null($uri)) {
+    return SCHEME_PUBLIC;
   }
-  // file_check_location() checks whether the destination is inside the Drupal
-  // files directory.
-  if (file_check_location($destination, $file_path)) {
-    return $destination;
+
+  if ($scheme  = DrupalStreamWrapperRegistry::getValidStreamScheme($uri)) {
+    // The URI contains a valid stream scheme.
+    $file_path = $scheme . '://';
   }
-  // Check if the destination is instead inside the Drupal temporary files
-  // directory.
-  elseif (file_check_location($destination, file_directory_temp())) {
-    return $destination;
+  elseif ($stream) {
+    // The URI must contain a valid scheme.
+    $file_path = SCHEME_PUBLIC . $uri;
+    $uri       = SCHEME_PUBLIC . $uri;
   }
-  // Not found, try again with prefixed directory path.
-  elseif (file_check_location($file_path . '/' . $destination, $file_path)) {
-    return $file_path . '/' . $destination;
+  else {
+    /**
+     * Normal paths must still fall within a directory managed by a registered
+     * stream wrapper for security reasons. We'll assume public:// for now.
+     * TODO: Search all registered wrapper paths for a valid match.
+     */
+    $file_path = file_directory_path(SCHEME_PUBLIC);
   }
+
+  // Check if the destination is inside the specified path.
+  if ($path = file_check_location($uri, $file_path)) {
+    return $path;
+  }
+  elseif (file_check_location($file_path . '/' . $uri, $file_path)) {
+    return $file_path . '/' . $uri;
+  }
+
   // File not found.
   return FALSE;
 }
@@ -152,8 +179,8 @@ function file_create_path($destination = NULL) {
  * Directories need to have execute permissions to be considered a directory by
  * FTP servers, etc.
  *
- * @param $directory
- *   A string containing the name of a directory path.
+ * @param &$directory
+ *   A string reference containing the name of a directory path.
  * @param $mode
  *   A bitmask to indicate if the directory should be created if it does
  *   not exist (FILE_CREATE_DIRECTORY) or made writable if it is read-only
@@ -164,10 +191,14 @@ function file_create_path($destination = NULL) {
  *   specify a writable directory. If it can't be made to work, a form error
  *   will be set preventing them from saving the settings.
  * @return
- *   FALSE when directory not found, or TRUE when directory exists.
+ *   Returns TRUE if the directory exists and is wriable. Otherwise, FALSE
+ *   is returned.
  */
 function file_check_directory(&$directory, $mode = 0, $form_item = NULL) {
-  $directory = rtrim($directory, '/\\');
+  if (!DrupalStreamWrapperRegistry::getValidStreamScheme($directory)) {
+    // Only trim if we're not dealing with a stream.
+    $directory = rtrim($directory, '/\\');
+  }
 
   // Check if directory exists.
   if (!is_dir($directory)) {
@@ -198,10 +229,21 @@ function file_check_directory(&$directory, $mode = 0, $form_item = NULL) {
     }
   }
 
-  if ((file_directory_path() == $directory || file_directory_temp() == $directory) && !is_file("$directory/.htaccess")) {
+  // Security SA_2006_06 compliance
+  if (DrupalStreamWrapperRegistry::getValidStreamScheme($directory)) {
+    $htaccess_path = $directory . '.htaccess';
+  }
+  else {
+    $htaccess_path = $directory . '/.htaccess';
+  }
+
+  // Try creating the .htaccess file if it's missing from the public, private, or temp directories.
+  if ((file_directory_path('public') == $directory || file_directory_path('private') == $directory || file_directory_path('temp') == $directory) ||
+       $directory == SCHEME_PUBLIC || $directory == SCHEME_PRIVATE || $directory == SCHEME_TEMP && !is_file("$directory/.htaccess")) {
+
     $htaccess_lines = "SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006\nOptions None\nOptions +FollowSymLinks";
-    if (file_put_contents("$directory/.htaccess", $htaccess_lines)) {
-      drupal_chmod("$directory/.htaccess");
+    if (file_put_contents($htaccess_path, $htaccess_lines)) {
+      drupal_chmod($htaccess_path);
     }
     else {
       $variables = array('%directory' => $directory, '!htaccess' => '<br />' . nl2br(check_plain($htaccess_lines)));
@@ -248,10 +290,13 @@ function file_check_path(&$path) {
  * @code
  *   // Returns FALSE:
  *   file_check_location('/www/example.com/files/../../../etc/passwd', '/www/example.com/files');
+ *
+ *   // Returns TRUE:
+ *   file_check_location('public://dir1/../example.txt', 'public://');
  * @endcode
  *
  * @param $source
- *   A string set to the file to check.
+ *   A string set to the file to check. May be a literal path or a stream wrapper URI.
  * @param $directory
  *   A string where the file should be located.
  * @return
@@ -259,19 +304,29 @@ function file_check_path(&$path) {
  *   path of the source.
  */
 function file_check_location($source, $directory = '') {
-  $check = drupal_realpath($source);
-  if ($check) {
-    $source = $check;
+  $original_source = $source;
+  $abs_pathname    = drupal_realpath($source);
+
+  if ($abs_pathname) {
+    $source = $abs_pathname;
   }
   else {
-    // This file does not yet exist.
-    $source = drupal_realpath(drupal_dirname($source)) . '/' . basename($source);
+    // The file does not exist yet.
+    if ($scheme = DrupalStreamWrapperRegistry::getValidStreamScheme($source)) {
+      // We're dealing with a valid stream wrapper.
+      $source = drupal_realpath(file_directory_path($scheme)) . '/' . basename($source);
+    }
+    else {
+      $source = drupal_realpath(dirname($source)) . '/' . basename($source);
+    }
   }
+
   $directory = drupal_realpath($directory);
   if ($directory && strpos($source, $directory) !== 0) {
     return FALSE;
   }
-  return $source;
+
+  return $original_source;
 }
 
 /**
@@ -280,16 +335,16 @@ function file_check_location($source, $directory = '') {
  * @param $fids
  *   An array of file IDs.
  * @param $conditions
- *   An array of conditions to match against the {files} table. These
+ *   An array of conditions to match against the {file} table. These
  *   should be supplied in the form array('field_name' => 'field_value').
  * @return
- *  An array of file objects, indexed by fid.
+ *   Returns an array of file objects, indexed by fid.
  *
  * @see hook_file_load()
  * @see file_load()
  */
 function file_load_multiple($fids = array(), $conditions = array()) {
-  $query = db_select('files', 'f')->fields('f');
+  $query = db_select('file', 'f')->fields('f');
 
   // If the $fids array is populated, add those to the query.
   if ($fids) {
@@ -348,15 +403,15 @@ function file_load($fid) {
 function file_save($file) {
   $file = (object)$file;
   $file->timestamp = REQUEST_TIME;
-  $file->filesize = filesize($file->filepath);
+  $file->filesize = filesize($file->uri);
 
   if (empty($file->fid)) {
-    drupal_write_record('files', $file);
+    drupal_write_record('file', $file);
     // Inform modules about the newly added file.
     module_invoke_all('file_insert', $file);
   }
   else {
-    drupal_write_record('files', $file, 'fid');
+    drupal_write_record('file', $file, 'fid');
     // Inform modules that the file has been updated.
     module_invoke_all('file_update', $file);
   }
@@ -382,9 +437,9 @@ function file_save($file) {
  * @param $source
  *   A file object.
  * @param $destination
- *   A string containing the destination that $source should be copied to. This
- *   can be a complete file path, a directory path or, if this value is omitted,
- *   Drupal's 'files' directory will be used.
+ *   A string containing the destination that $source should be copied to. This 
+ *   should a stream wrapped URI. If this value is omitted, Drupal's public files
+ *   directory will be used [public://].
  * @param $replace
  *   Replace behavior when the destination file already exists:
  *   - FILE_EXISTS_REPLACE - Replace the existing file. If a managed file with
@@ -402,14 +457,14 @@ function file_save($file) {
 function file_copy($source, $destination = NULL, $replace = FILE_EXISTS_RENAME) {
   $source = (object)$source;
 
-  if ($filepath = file_unmanaged_copy($source->filepath, $destination, $replace)) {
+  if ($uri = file_unmanaged_copy($source->uri, $destination, $replace)) {
     $file = clone $source;
     $file->fid = NULL;
-    $file->filepath = $filepath;
-    $file->filename = basename($filepath);
+    $file->uri = $uri;
+    $file->filename = basename($uri);
     // If we are replacing an existing file re-use its database record.
     if ($replace == FILE_EXISTS_REPLACE) {
-      $existing_files = file_load_multiple(array(), array('filepath' => $filepath));
+      $existing_files = file_load_multiple(array(), array('uri' => $uri));
       if (count($existing_files)) {
         $existing = reset($existing_files);
         $file->fid = $existing->fid;
@@ -434,7 +489,6 @@ function file_copy($source, $destination = NULL, $replace = FILE_EXISTS_RENAME)
 
 /**
  * Copy a file to a new location without calling any hooks or making any
- * changes to the database.
  *
  * This is a powerful function that in many ways performs like an advanced
  * version of copy().
@@ -462,7 +516,9 @@ function file_copy($source, $destination = NULL, $replace = FILE_EXISTS_RENAME)
  * @see file_copy()
  */
 function file_unmanaged_copy($source, $destination = NULL, $replace = FILE_EXISTS_RENAME) {
-  $original_source = $source;
+  $stream = TRUE; // TRUE: Handle this operation as a stream. FALSE: as a normal path
+
+  $original_source      = $source;
   $original_destination = $destination;
 
   $source = drupal_realpath($source);
@@ -471,9 +527,15 @@ function file_unmanaged_copy($source, $destination = NULL, $replace = FILE_EXIST
     return FALSE;
   }
 
-  $proposed_destination = file_create_path($destination);
+  // If $source and $destination do not contain a scheme we're dealing with a normal path.
+  if (!DrupalStreamWrapperRegistry::getValidStreamScheme($source) &&
+      !DrupalStreamWrapperRegistry::getValidStreamScheme($destination)) {
+    $stream = FALSE;
+  }
+
+  $proposed_destination = file_create_path($destination, $stream);
   $directory = $proposed_destination;
-  $basename = file_check_path($directory);
+  $basename  = file_check_path($directory);
 
   // Make sure we at least have a valid directory.
   if ($basename === FALSE) {
@@ -484,7 +546,8 @@ function file_unmanaged_copy($source, $destination = NULL, $replace = FILE_EXIST
   // If the destination file is not specified then use the filename of the
   // source file.
   $basename = $basename ? $basename : basename($source);
-  $destination = file_destination($directory . '/' . $basename, $replace);
+  $destination = file_destination($directory . '/'. $basename, $replace);
+  DrupalStreamWrapperRegistry::normalizeUri($destination);
 
   if ($destination === FALSE) {
     drupal_set_message(t('The specified file %file could not be copied because a file by that name already exists in the destination %directory.', array('%file' => $source, '%directory' => $proposed_destination)), 'error');
@@ -493,7 +556,7 @@ function file_unmanaged_copy($source, $destination = NULL, $replace = FILE_EXIST
   // Make sure source and destination filenames are not the same, makes no
   // sense to copy it if they are. In fact copying the file will most likely
   // result in a 0 byte file. Which is bad. Real bad.
-  if ($source == drupal_realpath($destination)) {
+  if (drupal_realpath($source) == drupal_realpath($destination)) {
     drupal_set_message(t('The specified file %file was not copied because it would overwrite itself.', array('%file' => $source)), 'error');
     return FALSE;
   }
@@ -581,14 +644,14 @@ function file_destination($destination, $replace) {
 function file_move($source, $destination = NULL, $replace = FILE_EXISTS_RENAME) {
   $source = (object)$source;
 
-  if ($filepath = file_unmanaged_move($source->filepath, $destination, $replace)) {
+  if ($uri = file_unmanaged_move($source->uri, $destination, $replace)) {
     $delete_source = FALSE;
 
     $file = clone $source;
-    $file->filepath = $filepath;
+    $file->uri = $uri;
     // If we are replacing an existing file re-use its database record.
     if ($replace == FILE_EXISTS_REPLACE) {
-      $existing_files = file_load_multiple(array(), array('filepath' => $filepath));
+      $existing_files = file_load_multiple(array(), array('uri' => $uri));
       if (count($existing_files)) {
         $existing = reset($existing_files);
         $delete_source = TRUE;
@@ -657,7 +720,7 @@ function file_unmanaged_move($source, $destination = NULL, $replace = FILE_EXIST
  * @param $alerts
  *   Whether alerts (watchdog, drupal_set_message()) should be displayed.
  * @return
- *   $filename The potentially modified $filename.
+ *   Returns the potentially modified file name.
  */
 function file_munge_filename($filename, $extensions, $alerts = TRUE) {
   $original = $filename;
@@ -718,7 +781,15 @@ function file_unmunge_filename($filename) {
  *   of $basename.
  */
 function file_create_filename($basename, $directory) {
-  $destination = $directory . '/' . $basename;
+  // Are we dealing with a stream?
+  if (DrupalStreamWrapperRegistry::getValidStreamScheme($directory)) {
+    $separator = '';
+  }
+  else {
+    $separator = '/';
+  }
+
+  $destination = $directory . $separator . $basename;
 
   if (file_exists($destination)) {
     // Destination file already exists, generate an alternative.
@@ -734,7 +805,7 @@ function file_create_filename($basename, $directory) {
 
     $counter = 0;
     do {
-      $destination = $directory . '/' . $name . '_' . $counter++ . $ext;
+      $destination = $directory . $separator . $name . '_' . $counter++ . $ext;
     } while (file_exists($destination));
   }
 
@@ -777,8 +848,8 @@ function file_delete($file, $force = FALSE) {
 
   // Make sure the file is deleted before removing its row from the
   // database, so UIs can still find the file in the database.
-  if (file_unmanaged_delete($file->filepath)) {
-    db_delete('files')->condition('fid', $file->fid)->execute();
+  if (file_unmanaged_delete($file->uri)) {
+    db_delete('file')->condition('fid', $file->fid)->execute();
     return TRUE;
   }
   return FALSE;
@@ -869,7 +940,7 @@ function file_unmanaged_delete_recursive($path) {
  *   An integer containing the number of bytes used.
  */
 function file_space_used($uid = NULL, $status = FILE_STATUS_PERMANENT) {
-  $query = db_select('files', 'f');
+  $query = db_select('file', 'f');
   // Use separate placeholders for the status to avoid a bug in some versions
   // of PHP. @see http://drupal.org/node/352956
   $query->where('f.status & :status1 = :status2', array(':status1' => $status, ':status2' => $status));
@@ -883,9 +954,9 @@ function file_space_used($uid = NULL, $status = FILE_STATUS_PERMANENT) {
 /**
  * Saves a file upload to a new location.
  *
- * The file will be added to the files table as a temporary file. Temporary
- * files are periodically cleaned. To make the file a permanent file call
- * assign the status and use file_save() to save it.
+ * The file will be added to the {file} table as a temporary file. Temporary
+ * files are periodically cleaned. To make the file a permanent file, assign
+ * the status and use file_save() to save the changes.
  *
  * @param $source
  *   A string specifying the name of the upload field to save.
@@ -958,14 +1029,14 @@ function file_save_upload($source, $validators = array(), $destination = FALSE,
   $file->uid      = $user->uid;
   $file->status   = 0;
   $file->filename = file_munge_filename(trim(basename($_FILES['files']['name'][$source]), '.'), $extensions);
-  $file->filepath = $_FILES['files']['tmp_name'][$source];
+  $file->uri      = $_FILES['files']['tmp_name'][$source];
   $file->filemime = file_get_mimetype($file->filename);
   $file->filesize = $_FILES['files']['size'][$source];
 
   // Rename potentially executable files, to help prevent exploits.
   if (preg_match('/\.(php|pl|py|cgi|asp|js)$/i', $file->filename) && (substr($file->filename, -4) != '.txt')) {
     $file->filemime = 'text/plain';
-    $file->filepath .= '.txt';
+    $file->uri .= '.txt';
     $file->filename .= '.txt';
   }
 
@@ -976,7 +1047,7 @@ function file_save_upload($source, $validators = array(), $destination = FALSE,
   }
 
   $file->source = $source;
-  $file->destination = file_destination(file_create_path($destination . '/' . $file->filename), $replace);
+  $file->destination = file_destination(file_create_path($destination . $file->filename), $replace);
   // If file_destination() returns FALSE then $replace == FILE_EXISTS_ERROR and
   // there's an existing file so we need to bail.
   if ($file->destination === FALSE) {
@@ -1005,19 +1076,19 @@ function file_save_upload($source, $validators = array(), $destination = FALSE,
   // Move uploaded files from PHP's upload_tmp_dir to Drupal's temporary
   // directory. This overcomes open_basedir restrictions for future file
   // operations.
-  $file->filepath = $file->destination;
-  if (!move_uploaded_file($_FILES['files']['tmp_name'][$source], $file->filepath)) {
+  $file->uri = $file->destination;
+  if (!move_uploaded_file($_FILES['files']['tmp_name'][$source], $file->uri)) {
     form_set_error($source, t('File upload error. Could not move uploaded file.'));
-    watchdog('file', 'Upload error. Could not move uploaded file %file to destination %destination.', array('%file' => $file->filename, '%destination' => $file->filepath));
+    watchdog('file', 'Upload error. Could not move uploaded file %file to destination %destination.', array('%file' => $file->filename, '%destination' => $file->uri));
     return FALSE;
   }
 
   // Set the permissions on the new file.
-  drupal_chmod($file->filepath);
+  drupal_chmod($file->uri);
 
   // If we are replacing an existing file re-use its database record.
   if ($replace == FILE_EXISTS_REPLACE) {
-    $existing_files = file_load_multiple(array(), array('filepath' => $file->filepath));
+    $existing_files = file_load_multiple(array(), array('uri' => $file->uri));
     if (count($existing_files)) {
       $existing = reset($existing_files);
       $file->fid = $existing->fid;
@@ -1162,7 +1233,7 @@ function file_validate_size($file, $file_limit = 0, $user_limit = 0) {
 function file_validate_is_image($file) {
   $errors = array();
 
-  $info = image_get_info($file->filepath);
+  $info = image_get_info($file->uri);
   if (!$info || empty($info['extension'])) {
     $errors[] = t('Only JPEG, PNG and GIF images are allowed.');
   }
@@ -1198,13 +1269,13 @@ function file_validate_image_resolution($file, $maximum_dimensions = 0, $minimum
   $errors = array();
 
   // Check first that the file is an image.
-  if ($info = image_get_info($file->filepath)) {
+  if ($info = image_get_info($file->uri)) {
     if ($maximum_dimensions) {
       // Check that it is smaller than the given dimensions.
       list($width, $height) = explode('x', $maximum_dimensions);
       if ($info['width'] > $width || $info['height'] > $height) {
         // Try to resize the image to fit the dimensions.
-        if ($image = image_load($file->filepath)) {
+        if ($image = image_load($file->uri)) {
           image_scale($image, $width, $height);
           image_save($image);
           $file->filesize = $image->info['file_size'];
@@ -1253,18 +1324,18 @@ function file_validate_image_resolution($file, $maximum_dimensions = 0, $minimum
 function file_save_data($data, $destination = NULL, $replace = FILE_EXISTS_RENAME) {
   global $user;
 
-  if ($filepath = file_unmanaged_save_data($data, $destination, $replace)) {
+  if ($uri = file_unmanaged_save_data($data, $destination, $replace)) {
     // Create a file object.
     $file = new stdClass();
     $file->fid = NULL;
-    $file->filepath = $filepath;
-    $file->filename = basename($filepath);
-    $file->filemime = file_get_mimetype($file->filepath);
+    $file->uri = $uri;
+    $file->filename = basename($uri);
+    $file->filemime = file_get_mimetype($file->uri);
     $file->uid      = $user->uid;
     $file->status  |= FILE_STATUS_PERMANENT;
     // If we are replacing an existing file re-use its database record.
     if ($replace == FILE_EXISTS_REPLACE) {
-      $existing_files = file_load_multiple(array(), array('filepath' => $filepath));
+      $existing_files = file_load_multiple(array(), array('uri' => $uri));
       if (count($existing_files)) {
         $existing = reset($existing_files);
         $file->fid = $existing->fid;
@@ -1287,7 +1358,7 @@ function file_save_data($data, $destination = NULL, $replace = FILE_EXISTS_RENAM
  * making any changes to the database.
  *
  * This function is identical to file_save_data() except the file will not be
- * saved to the files table and none of the file_* hooks will be called.
+ * saved to the {file} table and none of the file_* hooks will be called.
  *
  * @param $data
  *   A string containing the contents of the file.
@@ -1366,11 +1437,11 @@ function file_transfer($source, $headers) {
 function file_download() {
   // Merge remainder of arguments from GET['q'], into relative file path.
   $args = func_get_args();
-  $filepath = implode('/', $args);
+  $filepath = SCHEME_PRIVATE . implode('/', $args);
 
   // Maintain compatibility with old ?file=paths saved in node bodies.
   if (isset($_GET['file'])) {
-    $filepath =  $_GET['file'];
+    $filepath = SCHEME_PRIVATE . $_GET['file'];
   }
 
   if (file_exists(file_create_path($filepath))) {
@@ -1430,32 +1501,33 @@ function file_scan_directory($dir, $mask, $options = array(), $depth = 0) {
     'nomask' => '/(\.\.?|CVS)$/',
     'callback' => 0,
     'recurse' => TRUE,
-    'key' => 'filepath',
+    'key' => 'uri',
     'min_depth' => 0,
   );
 
-  $options['key'] = in_array($options['key'], array('filepath', 'filename', 'name')) ? $options['key'] : 'filepath';
+  $options['key'] = in_array($options['key'], array('uri', 'filename', 'name')) ? $options['key'] : 'uri';
   $files = array();
   if (is_dir($dir) && $handle = opendir($dir)) {
     while (FALSE !== ($filename = readdir($handle))) {
       if (!preg_match($options['nomask'], $filename) && $filename[0] != '.') {
-        $filepath = "$dir/$filename";
-        if (is_dir($filepath) && $options['recurse']) {
+        $uri = "$dir/$filename";
+        DrupalStreamWrapperRegistry::normalizeUri($uri);
+        if (is_dir($uri) && $options['recurse']) {
           // Give priority to files in this folder by merging them in after any subdirectory files.
-          $files = array_merge(file_scan_directory($filepath, $mask, $options, $depth + 1), $files);
+          $files = array_merge(file_scan_directory($uri, $mask, $options, $depth + 1), $files);
         }
         elseif ($depth >= $options['min_depth'] && preg_match($mask, $filename)) {
           // Always use this match over anything already set in $files with the
           // same $$options['key'].
           $file = (object) array(
-            'filepath' => $filepath,
+            'uri' => $uri,
             'filename' => $filename,
             'name' => pathinfo($filename, PATHINFO_FILENAME),
           );
           $key = $options['key'];
           $files[$file->$key] = $file;
           if ($options['callback']) {
-            $options['callback']($filepath);
+            $options['callback']($uri);
           }
         }
       }
@@ -1474,47 +1546,35 @@ function file_scan_directory($dir, $mask, $options = array(), $depth = 0) {
  *   A string containing a temp directory.
  */
 function file_directory_temp() {
-  $temporary_directory = variable_get('file_directory_temp');
-
-  if (is_null($temporary_directory)) {
-    $directories = array();
-
-    // Has PHP been set with an upload_tmp_dir?
-    if (ini_get('upload_tmp_dir')) {
-      $directories[] = ini_get('upload_tmp_dir');
-    }
-
-    // Operating system specific dirs.
-    if (substr(PHP_OS, 0, 3) == 'WIN') {
-      $directories[] = 'c:/windows/temp';
-      $directories[] = 'c:/winnt/temp';
-    }
-    else {
-      $directories[] = '/tmp';
-    }
-
-    foreach ($directories as $directory) {
-      if (!$temporary_directory && is_dir($directory)) {
-        $temporary_directory = $directory;
-      }
-    }
-
-    // if a directory has been found, use it, otherwise default to 'files/tmp'
-    $temporary_directory = $temporary_directory ? $temporary_directory : file_directory_path() . '/tmp';
-    variable_set('file_directory_temp', $temporary_directory);
-  }
-
-  return $temporary_directory;
+  return file_directory_path('temp');
 }
 
 /**
- * Determine the default 'files' directory.
+ * Determines the base path of a given wrapper.
+ *
+ * This function will return the base path of a stream by providing a scheme.
+ * A stream is referenced as: scheme://target.
+ * For example, a scheme of public might return sites/all/default/files
+ * or temp might return /tmp.
+ *
+ * Compatibility: only stream wrappers.
+ * @see http://drupal.org/node/515192
  *
+ * @param $scheme
+ *   A string representing the scheme of a stream. For legacy code, the public
+ *   wrapper is assumed if this is not provided.
+ *   A stream is referenced as: scheme://target.
  * @return
- *   A string containing the path to Drupal's 'files' directory.
+ *   A string containing the base path of a stream. FALSE is returned if the scheme
+ *   is invalid or a wrapper could not be instantiated.
  */
-function file_directory_path() {
-  return variable_get('file_directory_path', conf_path() . '/files');
+function file_directory_path($scheme = SCHEME_PUBLIC) {
+  if (isset($scheme) && $wrapper = DrupalStreamWrapperRegistry::getInstanceByScheme($scheme)) {
+    return $wrapper->getDirectoryPath();
+  }
+  else {
+    return FALSE;
+  }
 }
 
 /**
diff --git includes/install.inc includes/install.inc
index 6b19741..3438a4b 100644
--- includes/install.inc
+++ includes/install.inc
@@ -216,9 +216,9 @@ function drupal_detect_database_types() {
   // file for the driver explicitly.
 
   foreach (file_scan_directory(DRUPAL_ROOT . '/includes/database', '/^[a-z]*$/i', array('recurse' => FALSE)) as $file) {
-    include_once "{$file->filepath}/install.inc";
-    include_once "{$file->filepath}/database.inc";
-    $drivers[$file->filename] = $file->filepath;
+    include_once "{$file->uri}/install.inc";
+    include_once "{$file->uri}/database.inc";
+    $drivers[$file->filename] = $file->uri;
   }
 
   foreach ($drivers as $driver => $file) {
@@ -863,7 +863,7 @@ function st($string, $args = array()) {
     $filename = 'profiles/' . $profile . '/translations/' . $install_locale . '.po';
     if (file_exists(DRUPAL_ROOT . '/' . $filename)) {
       require_once DRUPAL_ROOT . '/includes/locale.inc';
-      $file = (object) array('filepath' => $filename);
+      $file = (object) array('uri' => $filename);
       _locale_import_read_po('mem-store', $file);
       $locale_strings = _locale_import_one_string('mem-report');
     }
@@ -914,7 +914,7 @@ function drupal_check_profile($profile) {
   // Collect requirement testing results
   $requirements = array();
   foreach ($installs as $install) {
-    require_once DRUPAL_ROOT . '/' . $install->filepath;
+    require_once DRUPAL_ROOT . '/' . $install->uri;
     $function = $install->name . '_requirements';
     if (function_exists($function)) {
       $requirements = array_merge($requirements, $function('install'));
@@ -954,7 +954,7 @@ function drupal_check_module($module) {
   // Include install file
   $install = drupal_get_install_files(array($module));
   if (isset($install[$module])) {
-    require_once DRUPAL_ROOT . '/' . $install[$module]->filepath;
+    require_once DRUPAL_ROOT . '/' . $install[$module]->uri;
 
     // Check requirements
     $requirements = module_invoke($module, 'requirements', 'install');
diff --git includes/locale.inc includes/locale.inc
index f756ea9..eaf32cf 100644
--- includes/locale.inc
+++ includes/locale.inc
@@ -1225,7 +1225,7 @@ function _locale_import_po($file, $langcode, $mode, $group = NULL) {
  */
 function _locale_import_read_po($op, $file, $mode = NULL, $lang = NULL, $group = 'default') {
 
-  $fd = fopen($file->filepath, "rb"); // File will get closed by PHP on return
+  $fd = fopen($file->uri, "rb"); // File will get closed by PHP on return
   if (!$fd) {
     _locale_import_message('The translation import failed, because the file %filename could not be read.', $file);
     return FALSE;
@@ -2652,7 +2652,7 @@ function _locale_batch_build($files, $finished = NULL, $components = array()) {
     $operations = array();
     foreach ($files as $file) {
       // We call _locale_batch_import for every batch operation.
-      $operations[] = array('_locale_batch_import', array($file->filepath));
+      $operations[] = array('_locale_batch_import', array($file->uri));
     }
     $batch = array(
       'operations'    => $operations,
@@ -2684,7 +2684,7 @@ function _locale_batch_import($filepath, &$context) {
   // The filename is either {langcode}.po or {prefix}.{langcode}.po, so
   // we can extract the language code to use for the import from the end.
   if (preg_match('!(/|\.)([^\./]+)\.po$!', $filepath, $langcode)) {
-    $file = (object) array('filename' => basename($filepath), 'filepath' => $filepath);
+    $file = (object) array('filename' => basename($filepath), 'uri' => $filepath);
     _locale_import_read_po('db-store', $file, LOCALE_IMPORT_KEEP, $langcode[2]);
     $context['results'][] = $filepath;
   }
diff --git includes/module.inc includes/module.inc
index 1ffdf2f..a7da6e5 100644
--- includes/module.inc
+++ includes/module.inc
@@ -501,7 +501,7 @@ function drupal_required_modules() {
   $files = drupal_system_listing('/\.info$/', 'modules', 'name', 0);
   $required = array();
   foreach ($files as $name => $file) {
-    $info = drupal_parse_info_file($file->filepath);
+    $info = drupal_parse_info_file($file->uri);
     if (!empty($info) && !empty($info['required']) && $info['required']) {
       $required[] = $name;
     }
diff --git includes/registry.inc includes/registry.inc
index 77948d4..e0820ea 100644
--- includes/registry.inc
+++ includes/registry.inc
@@ -43,7 +43,7 @@ function _registry_rebuild() {
   // Get the list of files we are going to parse.
   $files = array();
   foreach ($modules as &$module) {
-    $dir = dirname($module->filepath);
+    $dir = dirname($module->uri);
 
     // Store the module directory for use in hook_registry_files_alter().
     $module->dir = $dir;
diff --git includes/theme.inc includes/theme.inc
index 02779ff..4467a05 100644
--- includes/theme.inc
+++ includes/theme.inc
@@ -967,7 +967,7 @@ function drupal_find_theme_templates($cache, $extension, $path) {
   $files = drupal_system_listing($regex, $path, 'name', 0);
   foreach ($files as $template => $file) {
     // Ignore sub-theme templates for the current theme.
-    if (strpos($file->filepath, str_replace($subtheme_paths, '', $file->filepath)) !== 0) {
+    if (strpos($file->uri, str_replace($subtheme_paths, '', $file->uri)) !== 0) {
       continue;
     }
     // Chop off the remaining extensions if there are any. $template already
@@ -982,7 +982,7 @@ function drupal_find_theme_templates($cache, $extension, $path) {
     if (isset($cache[$hook])) {
       $templates[$hook] = array(
         'template' => $template,
-        'path' => dirname($file->filepath),
+        'path' => dirname($file->uri),
       );
     }
     // Ensure that the pattern is maintained from base themes to its sub-themes.
@@ -1008,7 +1008,7 @@ function drupal_find_theme_templates($cache, $extension, $path) {
           // Put the underscores back in for the hook name and register this pattern.
           $templates[strtr($file, '-', '_')] = array(
             'template' => $file,
-            'path' => dirname($files[$match]->filepath),
+            'path' => dirname($files[$match]->uri),
             'arguments' => $info['arguments'],
           );
         }
diff --git install.php install.php
index 472edfc..35381c1 100644
--- install.php
+++ install.php
@@ -421,7 +421,7 @@ function install_select_profile() {
   // Don't need to choose profile if only one available.
   if (sizeof($profiles) == 1) {
     $profile = array_pop($profiles);
-    require_once $profile->filepath;
+    require_once $profile->uri;
     return $profile->name;
   }
   elseif (sizeof($profiles) > 1) {
@@ -453,7 +453,7 @@ function install_select_profile_form(&$form_state, $profile_files) {
   $names = array();
 
   foreach ($profile_files as $profile) {
-    include_once DRUPAL_ROOT . '/' . $profile->filepath;
+    include_once DRUPAL_ROOT . '/' . $profile->uri;
     
     $details = install_profile_info($profile->name);
     $profiles[$profile->name] = $details;
diff --git modules/aggregator/aggregator.admin.inc modules/aggregator/aggregator.admin.inc
index 7397c5d..6165ffb 100644
--- modules/aggregator/aggregator.admin.inc
+++ modules/aggregator/aggregator.admin.inc
@@ -297,7 +297,7 @@ function aggregator_form_opml_validate($form, &$form_state) {
 function aggregator_form_opml_submit($form, &$form_state) {
   $data = '';
   if ($file = file_save_upload('upload')) {
-    $data = file_get_contents($file->filepath);
+    $data = file_get_contents($file->uri);
   }
   else {
     $response = drupal_http_request($form_state['values']['remote']);
diff --git modules/aggregator/aggregator.test modules/aggregator/aggregator.test
index 820357e..87340a0 100644
--- modules/aggregator/aggregator.test
+++ modules/aggregator/aggregator.test
@@ -239,7 +239,7 @@ EOF;
 </opml>
 EOF;
 
-    $path = file_directory_path() . '/empty-opml.xml';
+    $path = SCHEME_PUBLIC . '/empty-opml.xml';
     return file_unmanaged_save_data($opml, $path);
   }
 
diff --git modules/blogapi/blogapi.module modules/blogapi/blogapi.module
index 17d1542..069bbb7 100644
--- modules/blogapi/blogapi.module
+++ modules/blogapi/blogapi.module
@@ -472,13 +472,16 @@ function blogapi_metaweblog_new_media_object($blogid, $username, $password, $fil
 
   $row = new stdClass();
   $row->uid = $user->uid;
-  $row->filepath = $file;
+  $row->uri = $file;
   $row->filesize = $filesize;
 
   drupal_write_record('blogapi_files', $row);
 
   // Return the successful result.
-  return array('url' => file_create_url($file), 'struct');
+  // TODO: Don't assume public.
+  $uri = SCHEME_PUBLIC . "/$file";
+  DrupalStreamWrapperRegistry::normalizeUri($uri);
+  return array('url' => file_create_url($uri), 'struct');
 }
 /**
  * Blogging API callback. Returns a list of the taxonomy terms that can be
diff --git modules/blogapi/blogapi.test modules/blogapi/blogapi.test
index 6a74004..dd3d68c 100644
--- modules/blogapi/blogapi.test
+++ modules/blogapi/blogapi.test
@@ -70,7 +70,7 @@ class BlogAPITestCase extends DrupalWebTestCase {
 
     // Upload file.
     $file = current($this->drupalGetTestFiles('text'));
-    $file_contents = file_get_contents($file->filepath);
+    $file_contents = file_get_contents($file->uri);
     $file = array();
     $file['name'] = $this->randomName() . '.txt';
     $file['type'] = 'text';
diff --git modules/image/image.module modules/image/image.module
index 5adb4b6..d36d034 100644
--- modules/image/image.module
+++ modules/image/image.module
@@ -219,7 +219,7 @@ function image_file_download($filepath) {
  */
 function image_file_move($file, $source) {
   // Delete any image derivatives at the original image path.
-  image_path_flush($file->filepath);
+  image_path_flush($file->uri);
 }
 
 /**
@@ -227,7 +227,7 @@ function image_file_move($file, $source) {
  */
 function image_file_delete($file) {
   // Delete any image derivatives of this image.
-  image_path_flush($file->filepath);
+  image_path_flush($file->uri);
 }
 
 /**
@@ -237,7 +237,6 @@ function image_file_delete($file) {
  *   The Drupal file path to the original image.
  */
 function image_path_flush($path) {
-  $path = file_directory_strip($path);
   $styles = image_styles();
   foreach ($styles as $style) {
     if ($path = file_create_path('styles/' . $style['name'] . '/' . $path)) {
@@ -426,8 +425,11 @@ function image_style_generate() {
   $args = func_get_args();
   $style = array_shift($args);
   $style_name = $style['name'];
+  $scheme = array_shift($args);
   $path = implode('/', $args);
 
+  $path = $scheme . '://' . $path;
+
   $source = file_create_path($path);
   $path_md5 = md5($path);
   $destination = image_style_path($style['name'], $path);
@@ -521,6 +523,7 @@ function image_style_create_derivative($style, $source, $destination) {
  *   An image style array.
  */
 function image_style_flush($style) {
+  // TODO: Don't assume public
   $style_directory = drupal_realpath(file_directory_path() . '/styles/' . $style['name']);
   if (is_dir($style_directory)) {
     file_unmanaged_delete_recursive($style_directory);
@@ -547,7 +550,7 @@ function image_style_flush($style) {
  *
  * This function is the default image generation method. It returns a URL for
  * an image that can be used in an <img> tag. When the browser requests the
- * image at image/generate/[style_name]/[path] the image is generated if it does
+ * image at image/generate/[style_name]/[scheme]/[path] the image is generated if it does
  * not already exist and then served to the browser. This allows each image to
  * have its own PHP instance (and memory limit) for generation of the new image.
  *
@@ -575,9 +578,12 @@ function image_style_url($style_name, $path) {
   // Set a cache entry to grant access to this style/image path. This will be
   // checked by image_style_generate().
   cache_set('access:' . $style_name . ':' . md5($path), 1, 'cache_image', REQUEST_TIME + 600);
+  
+  $scheme = DrupalStreamWrapperRegistry::getStreamScheme($path);
+  $target = DrupalStreamWrapperRegistry::getStreamTarget($path);
 
   // Generate a callback path for the image.
-  $url = url('image/generate/' . $style_name . '/' . $path, array('absolute' => TRUE));
+  $url = url('image/generate/' . $style_name . '/' . $scheme . '/' . $target, array('absolute' => TRUE));
   return $url;
 }
 
@@ -596,7 +602,8 @@ function image_style_url($style_name, $path) {
  * @see image_style_url()
  */
 function image_style_path($style_name, $path) {
-  return file_directory_path() . '/styles/' . $style_name . '/' . file_directory_strip($path);
+  // TODO: Don't assume public
+  return SCHEME_PUBLIC . 'styles/' . $style_name . '/' . DrupalStreamWrapperRegistry::getStreamTarget($path);
 }
 
 /**
@@ -795,7 +802,7 @@ function theme_image_style($style_name, $path, $alt = '', $title = '', $attribut
   if (!file_exists($style_path)) {
     $style_path = image_style_url($style_name, $path);
   }
-  return theme('image', $style_path, $alt, $title, $attributes, $getsize);
+  return theme('image', file_create_url($style_path), $alt, $title, $attributes, $getsize);
 }
 
 /**
diff --git modules/image/image.test modules/image/image.test
index e1fa6da..bf5336f 100644
--- modules/image/image.test
+++ modules/image/image.test
@@ -47,6 +47,7 @@ class ImageStylesPathAndUrlUnitTest extends DrupalWebTestCase {
     parent::setUp();
 
     $this->style_name = 'style_foo';
+    $this->scheme     = 'public';
     image_style_save(array('name' => $this->style_name));
 
     // Create the directories for the styles.
@@ -55,8 +56,8 @@ class ImageStylesPathAndUrlUnitTest extends DrupalWebTestCase {
 
     // Create a working copy of the file.
     $file = reset($this->drupalGetTestFiles('image'));
-    $this->image_info = image_get_info($file->filepath);
-    $this->image_filepath = file_unmanaged_copy($file->filepath, NULL, FILE_EXISTS_RENAME);
+    $this->image_info = image_get_info($file->uri);
+    $this->image_filepath = file_unmanaged_copy($file->uri, NULL, FILE_EXISTS_RENAME);
     $this->assertNotIdentical(FALSE, $this->image_filepath, t('Created the without generated image file.'));
   }
 
@@ -65,7 +66,7 @@ class ImageStylesPathAndUrlUnitTest extends DrupalWebTestCase {
    */
   function testImageStylePath() {
     $actual = image_style_path($this->style_name, $this->image_filepath);
-    $expected = file_directory_path() . '/styles/' . $this->style_name . '/' . basename($this->image_filepath);
+    $expected = $this->scheme . '://styles/' . $this->style_name . '/' . basename($this->image_filepath);
     $this->assertEqual($actual, $expected, t('Got the path for a file.'));
   }
 
@@ -75,9 +76,9 @@ class ImageStylesPathAndUrlUnitTest extends DrupalWebTestCase {
   function testImageStyleUrl() {
     // Get the URL of a file that has not been generated yet and try to access
     // it before image_style_url has been called.
-    $generated_path = file_directory_path() . '/styles/' . $this->style_name . '/' . basename($this->image_filepath);
+    $generated_path = $this->scheme . '://styles/' . $this->style_name . '/' . basename($this->image_filepath);
     $this->assertFalse(file_exists($generated_path), t('Generated file does not exist.'));
-    $expected_generate_url = url('image/generate/' . $this->style_name . '/' . $this->image_filepath, array('absolute' => TRUE));
+    $expected_generate_url = url('image/generate/' . $this->style_name . '/' . $this->scheme . '/' . DrupalStreamWrapperRegistry::getStreamTarget($this->image_filepath), array('absolute' => TRUE));
     $this->drupalGet($expected_generate_url);
     $this->assertResponse(403, t('Access to generate URL was denied.'));
 
@@ -111,6 +112,21 @@ class ImageStylesPathAndUrlUnitTest extends DrupalWebTestCase {
     $this->assertEqual($this->drupalGetHeader('Content-Type'), $this->image_info['mime_type'], t('Expected Content-Type was reported.'));
     $this->assertEqual($this->drupalGetHeader('Content-Length'), $this->image_info['file_size'], t('Expected Content-Length was reported.'));
   }
+
+  /**
+   * Test image_style_generate_url().
+   */
+  function testImageStyleGenerateUrl() {
+    // Test it with no generated file.
+    $actual = image_style_generate_url($this->style_name, $this->image_without_generated);
+    $expected = url('image/generate/' . $this->style_name . '/' . $this->scheme . '/' . DrupalStreamWrapperRegistry::getStreamTarget($this->image_without_generated), array('absolute' => TRUE));
+    $this->assertEqual($actual, $expected, t('Got the generate URL for a non-existent file.'));
+
+    // Now test it with a generated file.
+    $actual = image_style_generate_url($this->style_name, $this->image_with_generated);
+    $expected = file_create_url(image_style_path($this->style_name, $this->image_with_generated));
+    $this->assertEqual($actual, $expected, t('Got the download URL for an existing file.'));
+  }
 }
 
 /**
diff --git modules/node/node.api.php modules/node/node.api.php
index da1e627..4afc2a6 100644
--- modules/node/node.api.php
+++ modules/node/node.api.php
@@ -677,7 +677,7 @@ function hook_prepare($node) {
   if ($file = file_check_upload($field_name)) {
     $file = file_save_upload($field_name, _image_filename($file->filename, NULL, TRUE));
     if ($file) {
-      if (!image_get_info($file->filepath)) {
+      if (!image_get_info($file->uri)) {
         form_set_error($field_name, t('Uploaded file is not a valid image'));
         return;
       }
@@ -685,7 +685,7 @@ function hook_prepare($node) {
     else {
       return;
     }
-    $node->images['_original'] = $file->filepath;
+    $node->images['_original'] = $file->uri;
     _image_build_derivatives($node, TRUE);
     $node->new_file = TRUE;
   }
diff --git modules/simpletest/drupal_web_test_case.php modules/simpletest/drupal_web_test_case.php
index 1c61f5e..2541cab 100644
--- modules/simpletest/drupal_web_test_case.php
+++ modules/simpletest/drupal_web_test_case.php
@@ -501,6 +501,20 @@ abstract class DrupalTestCase {
 }
 
 /**
+ * Drupal simpletest (simpletest://) stream wrapper class.
+ *
+ * Provides support for the simpletest directory created within the public
+ * files directory.
+ */
+class DrupalSimpleTestStreamWrapper extends DrupalPublicStreamWrapper {
+  public function getDirectoryPath() {
+    global $simpletest_stream_wrapper_path;
+    // This gets set just before registering our stream wrapper.
+    return $simpletest_stream_wrapper_path;
+  }
+}
+
+/**
  * Test case for Drupal unit tests.
  *
  * These tests can not access the database nor files. Calling any Drupal
@@ -527,7 +541,7 @@ class DrupalUnitTestCase extends DrupalTestCase {
 
     // Generate temporary prefixed database to ensure that tests have a clean starting point.
     $db_prefix = Database::getConnection()->prefixTables('{simpletest' . mt_rand(1000, 1000000) . '}');
-    $conf['file_directory_path'] = $this->originalFileDirectory . '/' . $db_prefix;
+    $conf['stream_public_path'] = $this->originalFileDirectory . '/' . $db_prefix;
 
     // If locale is enabled then t() will try to access the database and
     // subsequently will fail as the database is not accessible.
@@ -542,7 +556,7 @@ class DrupalUnitTestCase extends DrupalTestCase {
   function tearDown() {
     global $db_prefix, $conf;
     if (preg_match('/simpletest\d+/', $db_prefix)) {
-      $conf['file_directory_path'] = $this->originalFileDirectory;
+      $conf['stream_public_path'] = $this->originalFileDirectory;
       // Return the database prefix to the original.
       $db_prefix = $this->originalPrefix;
       // Restore modules if necessary.
@@ -795,15 +809,15 @@ class DrupalWebTestCase extends DrupalTestCase {
     // Make sure type is valid.
     if (in_array($type, array('binary', 'html', 'image', 'javascript', 'php', 'sql', 'text'))) {
       // Use original file directory instead of one created during setUp().
-      $path = $this->originalFileDirectory . '/simpletest';
+      $path = 'simpletest://';
       $files = file_scan_directory($path, '/' . $type . '\-.*/');
 
       // If size is set then remove any files that are not of that size.
       if ($size !== NULL) {
         foreach ($files as $file) {
-          $stats = stat($file->filepath);
+          $stats = stat($file->uri);
           if ($stats['size'] != $size) {
-            unset($files[$file->filepath]);
+            unset($files[$file->uri]);
           }
         }
       }
@@ -816,7 +830,7 @@ class DrupalWebTestCase extends DrupalTestCase {
    * Compare two files based on size and file name.
    */
   protected function drupalCompareFiles($file1, $file2) {
-    $compare_size = filesize($file1->filepath) - filesize($file2->filepath);
+    $compare_size = filesize($file1->uri) - filesize($file2->uri);
     if ($compare_size) {
       // Sort by file size.
       return $compare_size;
@@ -1011,13 +1025,19 @@ class DrupalWebTestCase extends DrupalTestCase {
    *   List of modules to enable for the duration of the test.
    */
   protected function setUp() {
-    global $db_prefix, $user, $language;
+    global $db_prefix, $user, $language, $simpletest_stream_wrapper_path;
 
     // Store necessary current values before switching to prefixed database.
     $this->originalLanguage = $language;
     $this->originalLanguageDefault = variable_get('language_default');
     $this->originalPrefix = $db_prefix;
     $this->originalFileDirectory = file_directory_path();
+
+    $simpletest_stream_wrapper_path = $this->originalFileDirectory .'/simpletest';
+
+    // Register our simpletest:// stream wrapper.
+    DrupalStreamWrapperRegistry::register('simpletest',  'DrupalSimpleTestStreamWrapper');
+
     $clean_url_original = variable_get('clean_url', 0);
 
     // Generate temporary prefixed database to ensure that tests have a clean starting point.
@@ -1085,11 +1105,18 @@ class DrupalWebTestCase extends DrupalTestCase {
     // default mail handler.
     variable_set('smtp_library', drupal_get_path('module', 'simpletest') . '/drupal_web_test_case.php');
 
-    // Use temporary files directory with the same prefix as database.
-    variable_set('file_directory_path', $this->originalFileDirectory . '/simpletest/' . substr($db_prefix, 10));
-    $directory = file_directory_path();
-    // Create the files directory.
+    // Use temporary directories
+    $public_files_directory  = $this->originalFileDirectory . '/' . $db_prefix;
+    $private_files_directory = $public_files_directory . '/private';
+
+    // Set path variables
+    variable_set('stream_public_path', $public_files_directory);
+    variable_set('stream_private_path', $private_files_directory);
+
+    // Create the directories
+    $directory = file_directory_path(SCHEME_PUBLIC);
     file_check_directory($directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
+    file_check_directory($private_files_directory, FILE_CREATE_DIRECTORY);
 
     // Log fatal errors.
     ini_set('log_errors', 1);
@@ -1131,7 +1158,7 @@ class DrupalWebTestCase extends DrupalTestCase {
    * and reset the database prefix.
    */
   protected function tearDown() {
-    global $db_prefix, $user, $language;
+    global $db_prefix, $user, $language, $simpletest_stream_wrapper_path;
 
     $emailCount = count(variable_get('simpletest_emails', array()));
     if ($emailCount) {
@@ -1140,9 +1167,14 @@ class DrupalWebTestCase extends DrupalTestCase {
     }
 
     if (preg_match('/simpletest\d+/', $db_prefix)) {
+      // Unregister our simpletest:// stream wrapper.
+      DrupalStreamWrapperRegistry::unregister('simpletest');
+      // Remove our temporary variable.
+      unset($simpletest_stream_wrapper_path);
+
       // Delete temporary files directory and reset files directory path.
       file_unmanaged_delete_recursive(file_directory_path());
-      variable_set('file_directory_path', $this->originalFileDirectory);
+      variable_set('stream_public_path', $this->originalFileDirectory);
 
       // Remove all prefixed tables (all the tables in the schema).
       $schema = drupal_get_schema(NULL, TRUE);
diff --git modules/simpletest/simpletest.install modules/simpletest/simpletest.install
index 33e94e5..7bd38f5 100644
--- modules/simpletest/simpletest.install
+++ modules/simpletest/simpletest.install
@@ -43,7 +43,7 @@ function simpletest_install() {
     // the test files back easily.
     if (count($files) > count(file_scan_directory($path, '/(html|image|javascript|php|sql)-.*/'))) {
       foreach ($files as $file) {
-        file_unmanaged_copy($file->filepath, $path, FILE_EXISTS_REPLACE);
+        file_unmanaged_copy($file->uri, $path, FILE_EXISTS_REPLACE);
       }
       $generated = TRUE;
     }
@@ -117,7 +117,7 @@ function simpletest_uninstall() {
   $path = file_directory_path() . '/simpletest';
   $files = file_scan_directory($path, '/.*/');
   foreach ($files as $file) {
-    file_unmanaged_delete($file->filepath);
+    file_unmanaged_delete($file->uri);
   }
   rmdir($path);
 }
diff --git modules/simpletest/simpletest.module modules/simpletest/simpletest.module
index 9b75410..21675ae 100644
--- modules/simpletest/simpletest.module
+++ modules/simpletest/simpletest.module
@@ -225,7 +225,7 @@ function simpletest_log_read($test_id) {
   $last_prefix = substr($last_prefix, 10);
 
   $test_class = db_result(db_query('SELECT test_class FROM {simpletest} WHERE test_id = :test_id ORDER BY message_id', array(':test_id' => $test_id)));
-  $log = file_directory_path() . "/simpletest/$last_prefix/error.log";
+  $log = SCHEME_PUBLIC . "simpletest/$last_prefix/error.log";
   if (file_exists($log)) {
     foreach (file($log) as $line) {
       if (preg_match('/PHP Fatal error: (.*?) in (.*) on line (\d+)/', $line, $match)) {
@@ -372,12 +372,12 @@ function simpletest_clean_database() {
  * Find all leftover temporary directories and remove them.
  */
 function simpletest_clean_temporary_directories() {
-  $directory = file_directory_path() . '/simpletest';
+  $directory = file_directory_path(SCHEME_PUBLIC);
   $files = scandir($directory);
   $count = 0;
   foreach ($files as $file) {
-    $path = "$directory/$file";
-    if (is_dir($path) && is_numeric($file)) {
+    $path = file_directory_path(SCHEME_PUBLIC) . '/' . $file;
+    if (is_dir($path) && preg_match('/^simpletest\d+/', $file)) {
       file_unmanaged_delete_recursive($path);
       $count++;
     }
diff --git modules/simpletest/simpletest.test modules/simpletest/simpletest.test
index b974ab9..c0aa9bf 100644
--- modules/simpletest/simpletest.test
+++ modules/simpletest/simpletest.test
@@ -1,6 +1,22 @@
 <?php
 // $Id: simpletest.test,v 1.26 2009-07-13 21:51:41 webchick Exp $
 
+class SimpleTestStreamWrapperTest extends DrupalWebTestCase {
+  public static function getInfo() {
+    return array(
+      'name' => t('SimpleTest Stream Wrapper functionality'),
+      'description' => t('Test SimpleTest\'s stream wrapper, ensuring the folder (defaulting
+                          to /sites/default/files/streamwrapper) exists.'),
+      'group' => t('SimpleTest')
+    );
+  }
+
+  function testSimpleTestFolderExists() {
+    $dir = 'simpletest://';
+    $this->assertTrue(file_check_directory($dir), t('The base simpletest stream wrapper folder exists.'));
+  }
+}
+
 class SimpleTestFunctionalTest extends DrupalWebTestCase {
   /**
    * The results array that has been parsed by getTestResults().
diff --git modules/simpletest/tests/file.test modules/simpletest/tests/file.test
index 2282b66..59b483c 100644
--- modules/simpletest/tests/file.test
+++ modules/simpletest/tests/file.test
@@ -90,7 +90,7 @@ class FileTestCase extends DrupalWebTestCase {
     $this->assertEqual($before->fid, $after->fid, t('File id is the same: %file1 == %file2.', array('%file1' => $before->fid, '%file2' => $after->fid)), 'File unchanged');
     $this->assertEqual($before->uid, $after->uid, t('File owner is the same: %file1 == %file2.', array('%file1' => $before->uid, '%file2' => $after->uid)), 'File unchanged');
     $this->assertEqual($before->filename, $after->filename, t('File name is the same: %file1 == %file2.', array('%file1' => $before->filename, '%file2' => $after->filename)), 'File unchanged');
-    $this->assertEqual($before->filepath, $after->filepath, t('File path is the same: %file1 == %file2.', array('%file1' => $before->filepath, '%file2' => $after->filepath)), 'File unchanged');
+    $this->assertEqual($before->uri, $after->uri, t('File path is the same: %file1 == %file2.', array('%file1' => $before->uri, '%file2' => $after->uri)), 'File unchanged');
     $this->assertEqual($before->filemime, $after->filemime, t('File MIME type is the same: %file1 == %file2.', array('%file1' => $before->filemime, '%file2' => $after->filemime)), 'File unchanged');
     $this->assertEqual($before->filesize, $after->filesize, t('File size is the same: %file1 == %file2.', array('%file1' => $before->filesize, '%file2' => $after->filesize)), 'File unchanged');
     $this->assertEqual($before->status, $after->status, t('File status is the same: %file1 == %file2.', array('%file1' => $before->status, '%file2' => $after->status)), 'File unchanged');
@@ -106,7 +106,7 @@ class FileTestCase extends DrupalWebTestCase {
    */
   function assertDifferentFile($file1, $file2) {
     $this->assertNotEqual($file1->fid, $file2->fid, t('Files have different ids: %file1 != %file2.', array('%file1' => $file1->fid, '%file2' => $file2->fid)), 'Different file');
-    $this->assertNotEqual($file1->filepath, $file2->filepath, t('Files have different paths: %file1 != %file2.', array('%file1' => $file1->filepath, '%file2' => $file2->filepath)), 'Different file');
+    $this->assertNotEqual($file1->uri, $file2->uri, t('Files have different paths: %file1 != %file2.', array('%file1' => $file1->uri, '%file2' => $file2->uri)), 'Different file');
   }
 
   /**
@@ -119,7 +119,7 @@ class FileTestCase extends DrupalWebTestCase {
    */
   function assertSameFile($file1, $file2) {
     $this->assertEqual($file1->fid, $file2->fid, t('Files have the same ids: %file1 == %file2.', array('%file1' => $file1->fid, '%file2-fid' => $file2->fid)), 'Same file');
-    $this->assertEqual($file1->filepath, $file2->filepath, t('Files have the same path: %file1 == %file2.', array('%file1' => $file1->filepath, '%file2' => $file2->filepath)), 'Same file');
+    $this->assertEqual($file1->uri, $file2->uri, t('Files have the same path: %file1 == %file2.', array('%file1' => $file1->uri, '%file2' => $file2->uri)), 'Same file');
   }
 
   /**
@@ -188,38 +188,42 @@ class FileTestCase extends DrupalWebTestCase {
    * Create a file and save it to the files table and assert that it occurs
    * correctly.
    *
-   * @param $filepath
+   * @param $path
    *   Optional string specifying the file path. If none is provided then a
-   *   randomly named file will be created in the site's files directory.
+   *   randomly named file will be created.
    * @param $contents
    *   Optional contents to save into the file. If a NULL value is provided an
    *   arbitrary string will be used.
+   * @param $scheme
+   *   Optionaly string indicating the stream scheme to use. Drupal core includes
+   *   public://, private://, and temp://. The public:// wrapper is the default.
    * @return
    *   File object.
    */
-  function createFile($filepath = NULL, $contents = NULL) {
-    if (is_null($filepath)) {
-      $filepath = file_directory_path() . '/' . $this->randomName();
+  function createFile($path = NULL, $contents = NULL, $scheme = SCHEME_PUBLIC) {
+    if (is_null($path)) {
+      $path = $this->randomName();
     }
+    $path = $scheme . $path;
 
     if (is_null($contents)) {
       $contents = "file_put_contents() doesn't seem to appreciate empty strings so let's put in some data.";
     }
 
-    file_put_contents($filepath, $contents);
-    $this->assertTrue(is_file($filepath), t('The test file exists on the disk.'), 'Create test file');
+    file_put_contents($path, $contents);
+    $this->assertTrue(is_file($path), t('The test file exists on the disk.'), 'Create test file');
 
     $file = new stdClass();
-    $file->filepath = $filepath;
-    $file->filename = basename($file->filepath);
-    $file->filemime = 'text/plain';
-    $file->uid = 1;
+    $file->uri       = $path;
+    $file->filename  = basename($file->uri);
+    $file->filemime  = 'text/plain';
+    $file->uid       = 1;
     $file->timestamp = REQUEST_TIME;
-    $file->filesize = filesize($file->filepath);
-    $file->status = 0;
+    $file->filesize  = filesize($file->uri);
+    $file->status    = 0;
     // Write the record directly rather than calling file_save() so we don't
     // invoke the hooks.
-    $this->assertNotIdentical(drupal_write_record('files', $file), FALSE, t('The file was added to the database.'), 'Create test file');
+    $this->assertNotIdentical(drupal_write_record('file', $file), FALSE, t('The file was added to the database.'), 'Create test file');
 
     return $file;
   }
@@ -313,16 +317,16 @@ class FileSpaceUsedTest extends FileTestCase {
     parent::setUp();
 
     // Create records for a couple of users with different sizes.
-    drupal_write_record('files', $file = array('uid' => 2, 'filesize' => 50, 'status' => FILE_STATUS_PERMANENT));
-    drupal_write_record('files', $file = array('uid' => 2, 'filesize' => 20, 'status' => FILE_STATUS_PERMANENT));
-    drupal_write_record('files', $file = array('uid' => 3, 'filesize' => 100, 'status' => FILE_STATUS_PERMANENT));
-    drupal_write_record('files', $file = array('uid' => 3, 'filesize' => 200, 'status' => FILE_STATUS_PERMANENT));
+    drupal_write_record('file', $file = array('uid' => 2, 'uri' => 'public://example1.txt', 'filesize' => 50, 'status' => FILE_STATUS_PERMANENT));
+    drupal_write_record('file', $file = array('uid' => 2, 'uri' => 'public://example2.txt', 'filesize' => 20, 'status' => FILE_STATUS_PERMANENT));
+    drupal_write_record('file', $file = array('uid' => 3, 'uri' => 'public://example3.txt', 'filesize' => 100, 'status' => FILE_STATUS_PERMANENT));
+    drupal_write_record('file', $file = array('uid' => 3, 'uri' => 'public://example4.txt', 'filesize' => 200, 'status' => FILE_STATUS_PERMANENT));
 
     // Now create some with other statuses. These values were chosen arbitrarily
     // for the sole purpose of testing that bitwise operators were used
     // correctly on the field.
-    drupal_write_record('files', $file = array('uid' => 2, 'filesize' => 1, 'status' => 2 | 8));
-    drupal_write_record('files', $file = array('uid' => 3, 'filesize' => 3, 'status' => 2 | 4));
+    drupal_write_record('file', $file = array('uid' => 2, 'uri' => 'public://example5.txt', 'filesize' => 1, 'status' => 2 | 8));
+    drupal_write_record('file', $file = array('uid' => 3, 'uri' => 'public://example6.txt', 'filesize' => 3, 'status' => 2 | 4));
   }
 
   /**
@@ -373,12 +377,12 @@ class FileValidatorTest extends DrupalWebTestCase {
     parent::setUp();
 
     $this->image = new stdClass();
-    $this->image->filepath = 'misc/druplicon.png';
-    $this->image->filename = basename($this->image->filepath);
+    $this->image->uri = 'misc/druplicon.png';
+    $this->image->filename = basename($this->image->uri);
 
     $this->non_image = new stdClass();
-    $this->non_image->filepath = 'misc/jquery.js';
-    $this->non_image->filename = basename($this->non_image->filepath);
+    $this->non_image->uri = 'misc/jquery.js';
+    $this->non_image->filename = basename($this->non_image->uri);
   }
 
   /**
@@ -399,11 +403,11 @@ class FileValidatorTest extends DrupalWebTestCase {
    *  This ensures a specific file is actually an image.
    */
   function testFileValidateIsImage() {
-    $this->assertTrue(file_exists($this->image->filepath), t('The image being tested exists.'), 'File');
+    $this->assertTrue(file_exists($this->image->uri), t('The image being tested exists.'), 'File');
     $errors = file_validate_is_image($this->image);
     $this->assertEqual(count($errors), 0, t('No error reported for our image file.'), 'File');
 
-    $this->assertTrue(file_exists($this->non_image->filepath), t('The non-image being tested exists.'), 'File');
+    $this->assertTrue(file_exists($this->non_image->uri), t('The non-image being tested exists.'), 'File');
     $errors = file_validate_is_image($this->non_image);
     $this->assertEqual(count($errors), 1, t('An error reported for our non-image file.'), 'File');
   }
@@ -434,12 +438,12 @@ class FileValidatorTest extends DrupalWebTestCase {
       // Copy the image so that the original doesn't get resized.
       $temp_dir = file_directory_temp();
       copy(drupal_realpath('misc/druplicon.png'), drupal_realpath($temp_dir) . '/druplicon.png');
-      $this->image->filepath = $temp_dir . '/druplicon.png';
+      $this->image->uri = $temp_dir . '/druplicon.png';
 
       $errors = file_validate_image_resolution($this->image, '10x5');
       $this->assertEqual(count($errors), 0, t('No errors should be reported when an oversized image can be scaled down.'), 'File');
 
-      $info = image_get_info($this->image->filepath);
+      $info = image_get_info($this->image->uri);
       $this->assertTrue($info['width'] <= 10, t('Image scaled to correct width.'), 'File');
       $this->assertTrue($info['height'] <= 5, t('Image scaled to correct height.'), 'File');
 
@@ -536,13 +540,13 @@ class FileUnmanagedSaveDataTest extends FileTestCase {
     // No filename.
     $filepath = file_unmanaged_save_data($contents);
     $this->assertTrue($filepath, t('Unnamed file saved correctly.'));
-    $this->assertEqual(file_directory_path(), dirname($filepath), t("File was placed in Drupal's files directory."));
+    $this->assertEqual(file_directory_path(SCHEME_PUBLIC), file_directory_path(DrupalStreamWrapperRegistry::getStreamScheme($filepath)), t("File was placed in Drupal's files directory."));
     $this->assertEqual($contents, file_get_contents(drupal_realpath($filepath)), t('Contents of the file are correct.'));
 
     // Provide a filename.
     $filepath = file_unmanaged_save_data($contents, 'asdf.txt', FILE_EXISTS_REPLACE);
     $this->assertTrue($filepath, t('Unnamed file saved correctly.'));
-    $this->assertEqual(file_directory_path(), drupal_dirname($filepath), t("File was placed in Drupal's files directory."));
+    $this->assertEqual(file_directory_path(SCHEME_PUBLIC), drupal_dirname($filepath), t("File was placed in Drupal's files directory."));
     $this->assertEqual('asdf.txt', basename($filepath), t('File was named correctly.'));
     $this->assertEqual($contents, file_get_contents(drupal_realpath($filepath)), t('Contents of the file are correct.'));
     $this->assertFilePermissions($filepath, variable_get('file_chmod_file', 0664));
@@ -577,14 +581,14 @@ class FileSaveUploadTest extends FileHookTestCase {
     $this->drupalLogin($account);
 
     $this->image = current($this->drupalGetTestFiles('image'));
-    $this->assertTrue(is_file($this->image->filepath), t("The file we're going to upload exists."));
+    $this->assertTrue(is_file($this->image->uri), t("The file we're going to upload exists."));
 
-    $this->maxFidBefore = db_query('SELECT MAX(fid) AS fid FROM {files}')->fetchField();
+    $this->maxFidBefore = db_query('SELECT MAX(fid) AS fid FROM {file}')->fetchField();
 
     // Upload with replace to gurantee there's something there.
     $edit = array(
       'file_test_replace' => FILE_EXISTS_REPLACE,
-      'files[file_test_upload]' => drupal_realpath($this->image->filepath)
+      'files[file_test_upload]' => drupal_realpath($this->image->uri)
     );
     $this->drupalPost('file-test/upload', $edit, t('Submit'));
     $this->assertResponse(200, t('Received a 200 response for posted test file.'));
@@ -600,7 +604,7 @@ class FileSaveUploadTest extends FileHookTestCase {
    * Test the file_save_upload() function.
    */
   function testNormal() {
-    $max_fid_after = db_query('SELECT MAX(fid) AS fid FROM {files}')->fetchField();
+    $max_fid_after = db_query('SELECT MAX(fid) AS fid FROM {file}')->fetchField();
     $this->assertTrue($max_fid_after > $this->maxFidBefore, t('A new file was created.'));
     $file1 = file_load($max_fid_after);
     $this->assertTrue($file1, t('Loaded the file.'));
@@ -609,13 +613,13 @@ class FileSaveUploadTest extends FileHookTestCase {
     file_test_reset();
 
     // Upload a second file.
-    $max_fid_before = db_query('SELECT MAX(fid) AS fid FROM {files}')->fetchField();
+    $max_fid_before = db_query('SELECT MAX(fid) AS fid FROM {file}')->fetchField();
     $image2 = current($this->drupalGetTestFiles('image'));
-    $edit = array('files[file_test_upload]' => drupal_realpath($image2->filepath));
+    $edit = array('files[file_test_upload]' => drupal_realpath($image2->uri));
     $this->drupalPost('file-test/upload', $edit, t('Submit'));
     $this->assertResponse(200, t('Received a 200 response for posted test file.'));
     $this->assertRaw(t('You WIN!'));
-    $max_fid_after = db_query('SELECT MAX(fid) AS fid FROM {files}')->fetchField();
+    $max_fid_after = db_query('SELECT MAX(fid) AS fid FROM {file}')->fetchField();
 
     // Check that the correct hooks were called.
     $this->assertFileHooksCalled(array('validate', 'insert'));
@@ -636,7 +640,7 @@ class FileSaveUploadTest extends FileHookTestCase {
   function testExistingRename() {
     $edit = array(
       'file_test_replace' => FILE_EXISTS_RENAME,
-      'files[file_test_upload]' => drupal_realpath($this->image->filepath)
+      'files[file_test_upload]' => drupal_realpath($this->image->uri)
     );
     $this->drupalPost('file-test/upload', $edit, t('Submit'));
     $this->assertResponse(200, t('Received a 200 response for posted test file.'));
@@ -652,7 +656,7 @@ class FileSaveUploadTest extends FileHookTestCase {
   function testExistingReplace() {
     $edit = array(
       'file_test_replace' => FILE_EXISTS_REPLACE,
-      'files[file_test_upload]' => drupal_realpath($this->image->filepath)
+      'files[file_test_upload]' => drupal_realpath($this->image->uri)
     );
     $this->drupalPost('file-test/upload', $edit, t('Submit'));
     $this->assertResponse(200, t('Received a 200 response for posted test file.'));
@@ -668,7 +672,7 @@ class FileSaveUploadTest extends FileHookTestCase {
   function testExistingError() {
     $edit = array(
       'file_test_replace' => FILE_EXISTS_ERROR,
-      'files[file_test_upload]' => drupal_realpath($this->image->filepath)
+      'files[file_test_upload]' => drupal_realpath($this->image->uri)
     );
     $this->drupalPost('file-test/upload', $edit, t('Submit'));
     $this->assertResponse(200, t('Received a 200 response for posted test file.'));
@@ -748,12 +752,12 @@ class FileDirectoryTest extends FileTestCase {
   }
 
   /**
-   * Check file_directory_path() and file_directory_temp().
+   * Check file_directory_path('public').
    */
   function testFileDirectoryPath() {
     // Directory path.
-    $path = variable_get('file_directory_path', conf_path() . '/files');
-    $this->assertEqual($path, file_directory_path(), t('Properly returns the stored file directory path.'), 'File');
+    $path = variable_get('stream_public_path', conf_path() . '/files');
+    $this->assertEqual($path, file_directory_path('public'), t('Properly returns the stored file directory path.'), 'File');
   }
 
   /**
@@ -881,15 +885,15 @@ class FileScanDirectoryTest extends FileTestCase {
 
     // Check the first file.
     $file = reset($all_files);
-    $this->assertEqual(key($all_files), $file->filepath, t('Correct array key was used for the first returned file.'));
-    $this->assertEqual($file->filepath, $this->path . '/javascript-1.txt', t('First file name was set correctly.'));
+    $this->assertEqual(key($all_files), $file->uri, t('Correct array key was used for the first returned file.'));
+    $this->assertEqual($file->uri, $this->path . '/javascript-1.txt', t('First file name was set correctly.'));
     $this->assertEqual($file->filename, 'javascript-1.txt', t('First basename was set correctly'));
     $this->assertEqual($file->name, 'javascript-1', t('First name was set correctly.'));
 
     // Check the second file.
     $file = next($all_files);
-    $this->assertEqual(key($all_files), $file->filepath, t('Correct array key was used for the second returned file.'));
-    $this->assertEqual($file->filepath, $this->path . '/javascript-2.script', t('Second file name was set correctly.'));
+    $this->assertEqual(key($all_files), $file->uri, t('Correct array key was used for the second returned file.'));
+    $this->assertEqual($file->uri, $this->path . '/javascript-2.script', t('Second file name was set correctly.'));
     $this->assertEqual($file->filename, 'javascript-2.script', t('Second basename was set correctly'));
     $this->assertEqual($file->name, 'javascript-2', t('Second name was set correctly.'));
   }
@@ -1002,8 +1006,8 @@ class FileUnmanagedDeleteTest extends FileTestCase {
     $file = $this->createFile();
 
     // Delete a regular file
-    $this->assertTrue(file_unmanaged_delete($file->filepath), t('Deleted worked.'));
-    $this->assertFalse(file_exists($file->filepath), t('Test file has actually been deleted.'));
+    $this->assertTrue(file_unmanaged_delete($file->uri), t('Deleted worked.'));
+    $this->assertFalse(file_exists($file->uri), t('Test file has actually been deleted.'));
   }
 
   /**
@@ -1125,16 +1129,16 @@ class FileUnmanagedMoveTest extends FileTestCase {
     $file = $this->createFile();
 
     // Moving to a new name.
-    $desired_filepath = file_directory_path() . '/' . $this->randomName();
-    $new_filepath = file_unmanaged_move($file->filepath, $desired_filepath, FILE_EXISTS_ERROR);
+    $desired_filepath = SCHEME_PUBLIC . $this->randomName();
+    $new_filepath = file_unmanaged_move($file->uri, $desired_filepath, FILE_EXISTS_ERROR);
     $this->assertTrue($new_filepath, t('Move was successful.'));
     $this->assertEqual($new_filepath, $desired_filepath, t('Returned expected filepath.'));
     $this->assertTrue(file_exists($new_filepath), t('File exists at the new location.'));
-    $this->assertFalse(file_exists($file->filepath), t('No file remains at the old location.'));
+    $this->assertFalse(file_exists($file->uri), t('No file remains at the old location.'));
     $this->assertFilePermissions($new_filepath, variable_get('file_chmod_file', 0664));
 
     // Moving with rename.
-    $desired_filepath = file_directory_path() . '/' . $this->randomName();
+    $desired_filepath = SCHEME_PUBLIC . $this->randomName();
     $this->assertTrue(file_exists($new_filepath), t('File exists before moving.'));
     $this->assertTrue(file_put_contents($desired_filepath, ' '), t('Created a file so a rename will have to happen.'));
     $newer_filepath = file_unmanaged_move($new_filepath, $desired_filepath, FILE_EXISTS_RENAME);
@@ -1145,6 +1149,7 @@ class FileUnmanagedMoveTest extends FileTestCase {
     $this->assertFilePermissions($newer_filepath, variable_get('file_chmod_file', 0664));
 
     // TODO: test moving to a directory (rather than full directory/file path)
+    // TODO: test creating and moving normal files (rather than streams)
   }
 
   /**
@@ -1164,14 +1169,14 @@ class FileUnmanagedMoveTest extends FileTestCase {
     $file = $this->createFile();
 
     // Move the file onto itself without renaming shouldn't make changes.
-    $new_filepath = file_unmanaged_move($file->filepath, $file->filepath, FILE_EXISTS_REPLACE);
+    $new_filepath = file_unmanaged_move($file->uri, $file->uri, FILE_EXISTS_REPLACE);
     $this->assertFalse($new_filepath, t('Moving onto itself without renaming fails.'));
-    $this->assertTrue(file_exists($file->filepath), t('File exists after moving onto itself.'));
+    $this->assertTrue(file_exists($file->uri), t('File exists after moving onto itself.'));
 
     // Move the file onto itself with renaming will result in a new filename.
-    $new_filepath = file_unmanaged_move($file->filepath, $file->filepath, FILE_EXISTS_RENAME);
+    $new_filepath = file_unmanaged_move($file->uri, $file->uri, FILE_EXISTS_RENAME);
     $this->assertTrue($new_filepath, t('Moving onto itself with renaming works.'));
-    $this->assertFalse(file_exists($file->filepath), t('Original file has been removed.'));
+    $this->assertFalse(file_exists($file->uri), t('Original file has been removed.'));
     $this->assertTrue(file_exists($new_filepath), t('File exists after moving onto itself.'));
   }
 }
@@ -1197,25 +1202,26 @@ class FileUnmanagedCopyTest extends FileTestCase {
     $file = $this->createFile();
 
     // Copying to a new name.
-    $desired_filepath = file_directory_path() . '/' . $this->randomName();
-    $new_filepath = file_unmanaged_copy($file->filepath, $desired_filepath, FILE_EXISTS_ERROR);
+    $desired_filepath = SCHEME_PUBLIC . $this->randomName();
+    $new_filepath = file_unmanaged_copy($file->uri, $desired_filepath, FILE_EXISTS_ERROR);
     $this->assertTrue($new_filepath, t('Copy was successful.'));
     $this->assertEqual($new_filepath, $desired_filepath, t('Returned expected filepath.'));
-    $this->assertTrue(file_exists($file->filepath), t('Original file remains.'));
+    $this->assertTrue(file_exists($file->uri), t('Original file remains.'));
     $this->assertTrue(file_exists($new_filepath), t('New file exists.'));
     $this->assertFilePermissions($new_filepath, variable_get('file_chmod_file', 0664));
 
     // Copying with rename.
-    $desired_filepath = file_directory_path() . '/' . $this->randomName();
+    $desired_filepath = SCHEME_PUBLIC . $this->randomName();
     $this->assertTrue(file_put_contents($desired_filepath, ' '), t('Created a file so a rename will have to happen.'));
-    $newer_filepath = file_unmanaged_copy($file->filepath, $desired_filepath, FILE_EXISTS_RENAME);
+    $newer_filepath = file_unmanaged_copy($file->uri, $desired_filepath, FILE_EXISTS_RENAME);
     $this->assertTrue($newer_filepath, t('Copy was successful.'));
     $this->assertNotEqual($newer_filepath, $desired_filepath, t('Returned expected filepath.'));
-    $this->assertTrue(file_exists($file->filepath), t('Original file remains.'));
+    $this->assertTrue(file_exists($file->uri), t('Original file remains.'));
     $this->assertTrue(file_exists($newer_filepath), t('New file exists.'));
     $this->assertFilePermissions($newer_filepath, variable_get('file_chmod_file', 0664));
 
     // TODO: test copying to a directory (rather than full directory/file path)
+    // TODO: test copying normal files using normal paths (rather than only streams)
   }
 
   /**
@@ -1237,28 +1243,28 @@ class FileUnmanagedCopyTest extends FileTestCase {
     $file = $this->createFile();
 
     // Copy the file onto itself with renaming works.
-    $new_filepath = file_unmanaged_copy($file->filepath, $file->filepath, FILE_EXISTS_RENAME);
+    $new_filepath = file_unmanaged_copy($file->uri, $file->uri, FILE_EXISTS_RENAME);
     $this->assertTrue($new_filepath, t('Copying onto itself with renaming works.'));
-    $this->assertNotEqual($new_filepath, $file->filepath, t('Copied file has a new name.'));
-    $this->assertTrue(file_exists($file->filepath), t('Original file exists after copying onto itself.'));
+    $this->assertNotEqual($new_filepath, $file->uri, t('Copied file has a new name.'));
+    $this->assertTrue(file_exists($file->uri), t('Original file exists after copying onto itself.'));
     $this->assertTrue(file_exists($new_filepath), t('Copied file exists after copying onto itself.'));
     $this->assertFilePermissions($new_filepath, variable_get('file_chmod_file', 0664));
 
     // Copy the file onto itself without renaming fails.
-    $new_filepath = file_unmanaged_copy($file->filepath, $file->filepath, FILE_EXISTS_ERROR);
+    $new_filepath = file_unmanaged_copy($file->uri, $file->uri, FILE_EXISTS_ERROR);
     $this->assertFalse($new_filepath, t('Copying onto itself without renaming fails.'));
-    $this->assertTrue(file_exists($file->filepath), t('File exists after copying onto itself.'));
+    $this->assertTrue(file_exists($file->uri), t('File exists after copying onto itself.'));
 
     // Copy the file into same directory without renaming fails.
-    $new_filepath = file_unmanaged_copy($file->filepath, dirname($file->filepath), FILE_EXISTS_ERROR);
+    $new_filepath = file_unmanaged_copy($file->uri, drupal_dirname($file->uri), FILE_EXISTS_ERROR);
     $this->assertFalse($new_filepath, t('Copying onto itself fails.'));
-    $this->assertTrue(file_exists($file->filepath), t('File exists after copying onto itself.'));
+    $this->assertTrue(file_exists($file->uri), t('File exists after copying onto itself.'));
 
     // Copy the file into same directory with renaming works.
-    $new_filepath = file_unmanaged_copy($file->filepath, dirname($file->filepath), FILE_EXISTS_RENAME);
+    $new_filepath = file_unmanaged_copy($file->uri, drupal_dirname($file->uri), FILE_EXISTS_RENAME);
     $this->assertTrue($new_filepath, t('Copying into same directory works.'));
-    $this->assertNotEqual($new_filepath, $file->filepath, t('Copied file has a new name.'));
-    $this->assertTrue(file_exists($file->filepath), t('Original file exists after copying onto itself.'));
+    $this->assertNotEqual($new_filepath, $file->uri, t('Copied file has a new name.'));
+    $this->assertTrue(file_exists($file->uri), t('Original file exists after copying onto itself.'));
     $this->assertTrue(file_exists($new_filepath), t('Copied file exists after copying onto itself.'));
     $this->assertFilePermissions($new_filepath, variable_get('file_chmod_file', 0664));
   }
@@ -1283,10 +1289,10 @@ class FileDeleteTest extends FileHookTestCase {
     $file = $this->createFile();
 
     // Check that deletion removes the file and database record.
-    $this->assertTrue(is_file($file->filepath), t("File exists."));
+    $this->assertTrue(is_file($file->uri), t("File exists."));
     $this->assertIdentical(file_delete($file), TRUE, t("Delete worked."));
     $this->assertFileHooksCalled(array('references', 'delete'));
-    $this->assertFalse(file_exists($file->filepath), t("Test file has actually been deleted."));
+    $this->assertFalse(file_exists($file->uri), t("Test file has actually been deleted."));
     $this->assertFalse(file_load($file->fid), t('File was removed from the database.'));
 
     // TODO: implement hook_file_references() in file_test.module and report a
@@ -1313,7 +1319,7 @@ class FileMoveTest extends FileHookTestCase {
   function testNormal() {
     $contents = $this->randomName(10);
     $source = $this->createFile(NULL, $contents);
-    $desired_filepath = file_directory_path() . '/' . $this->randomName();
+    $desired_filepath = SCHEME_PUBLIC . $this->randomName();
 
     // Clone the object so we don't have to worry about the function changing
     // our reference copy.
@@ -1321,8 +1327,8 @@ class FileMoveTest extends FileHookTestCase {
 
     // Check the return status and that the contents changed.
     $this->assertTrue($result, t('File moved sucessfully.'));
-    $this->assertFalse(file_exists($source->filepath));
-    $this->assertEqual($contents, file_get_contents($result->filepath), t('Contents of file correctly written.'));
+    $this->assertFalse(file_exists($source->uri));
+    $this->assertEqual($contents, file_get_contents($result->uri), t('Contents of file correctly written.'));
 
     // Check that the correct hooks were called.
     $this->assertFileHooksCalled(array('move', 'update'));
@@ -1349,12 +1355,12 @@ class FileMoveTest extends FileHookTestCase {
 
     // Clone the object so we don't have to worry about the function changing
     // our reference copy.
-    $result = file_move(clone $source, $target->filepath, FILE_EXISTS_RENAME);
+    $result = file_move(clone $source, $target->uri, FILE_EXISTS_RENAME);
 
     // Check the return status and that the contents changed.
     $this->assertTrue($result, t('File moved sucessfully.'));
-    $this->assertFalse(file_exists($source->filepath));
-    $this->assertEqual($contents, file_get_contents($result->filepath), t('Contents of file correctly written.'));
+    $this->assertFalse(file_exists($source->uri));
+    $this->assertEqual($contents, file_get_contents($result->uri), t('Contents of file correctly written.'));
 
     // Check that the correct hooks were called.
     $this->assertFileHooksCalled(array('move', 'update'));
@@ -1369,7 +1375,7 @@ class FileMoveTest extends FileHookTestCase {
     // Compare the source and results.
     $loaded_source = file_load($source->fid, TRUE);
     $this->assertEqual($loaded_source->fid, $result->fid, t("Returned file's id matches the source."));
-    $this->assertNotEqual($loaded_source->filepath, $source->filepath, t("Returned file path has changed from the original."));
+    $this->assertNotEqual($loaded_source->uri, $source->uri, t("Returned file path has changed from the original."));
   }
 
   /**
@@ -1384,11 +1390,11 @@ class FileMoveTest extends FileHookTestCase {
 
     // Clone the object so we don't have to worry about the function changing
     // our reference copy.
-    $result = file_move(clone $source, $target->filepath, FILE_EXISTS_REPLACE);
+    $result = file_move(clone $source, $target->uri, FILE_EXISTS_REPLACE);
 
     // Look at the results.
-    $this->assertEqual($contents, file_get_contents($result->filepath), t('Contents of file were overwritten.'));
-    $this->assertFalse(file_exists($source->filepath));
+    $this->assertEqual($contents, file_get_contents($result->uri), t('Contents of file were overwritten.'));
+    $this->assertFalse(file_exists($source->uri));
     $this->assertTrue($result, t('File moved sucessfully.'));
 
     // Check that the correct hooks were called.
@@ -1414,9 +1420,9 @@ class FileMoveTest extends FileHookTestCase {
 
     // Copy the file over itself. Clone the object so we don't have to worry
     // about the function changing our reference copy.
-    $result = file_move(clone $source, $source->filepath, FILE_EXISTS_REPLACE);
+    $result = file_move(clone $source, $source->uri, FILE_EXISTS_REPLACE);
     $this->assertFalse($result, t('File move failed.'));
-    $this->assertEqual($contents, file_get_contents($source->filepath), t('Contents of file were not altered.'));
+    $this->assertEqual($contents, file_get_contents($source->uri), t('Contents of file were not altered.'));
 
     // Check that no hooks were called while failing.
     $this->assertFileHooksCalled(array());
@@ -1438,12 +1444,12 @@ class FileMoveTest extends FileHookTestCase {
 
     // Clone the object so we don't have to worry about the function changing
     // our reference copy.
-    $result = file_move(clone $source, $target->filepath, FILE_EXISTS_ERROR);
+    $result = file_move(clone $source, $target->uri, FILE_EXISTS_ERROR);
 
     // Check the return status and that the contents did not change.
     $this->assertFalse($result, t('File move failed.'));
-    $this->assertTrue(file_exists($source->filepath));
-    $this->assertEqual($contents, file_get_contents($target->filepath), t('Contents of file were not altered.'));
+    $this->assertTrue(file_exists($source->uri));
+    $this->assertEqual($contents, file_get_contents($target->uri), t('Contents of file were not altered.'));
 
     // Check that no hooks were called while failing.
     $this->assertFileHooksCalled(array());
@@ -1472,25 +1478,25 @@ class FileCopyTest extends FileHookTestCase {
    * Test file copying in the normal, base case.
    */
   function testNormal() {
-    $contents = $this->randomName(10);
-    $source = $this->createFile(NULL, $contents);
-    $desired_filepath = file_directory_path() . '/' . $this->randomName();
+    $contents    = $this->randomName(10);
+    $source      = $this->createFile(NULL, $contents);
+    $desired_uri = SCHEME_PUBLIC . $this->randomName();
 
     // Clone the object so we don't have to worry about the function changing
     // our reference copy.
-    $result = file_copy(clone $source, $desired_filepath, FILE_EXISTS_ERROR);
+    $result = file_copy(clone $source, $desired_uri, FILE_EXISTS_ERROR);
 
     // Check the return status and that the contents changed.
     $this->assertTrue($result, t('File copied sucessfully.'));
-    $this->assertEqual($contents, file_get_contents($result->filepath), t('Contents of file were copied correctly.'));
+    $this->assertEqual($contents, file_get_contents($result->uri), t('Contents of file were copied correctly.'));
 
     // Check that the correct hooks were called.
     $this->assertFileHooksCalled(array('copy', 'insert'));
 
     $this->assertDifferentFile($source, $result);
-    $this->assertEqual($result->filepath, $desired_filepath, t('The copied file object has the desired filepath.'));
-    $this->assertTrue(file_exists($source->filepath), t('The original file still exists.'));
-    $this->assertTrue(file_exists($result->filepath), t('The copied file exists.'));
+    $this->assertEqual($result->uri, $desired_uri, t('The copied file object has the desired filepath.'));
+    $this->assertTrue(file_exists($source->uri), t('The original file still exists.'));
+    $this->assertTrue(file_exists($result->uri), t('The copied file exists.'));
 
     // Reload the file from the database and check that the changes were
     // actually saved.
@@ -1503,18 +1509,18 @@ class FileCopyTest extends FileHookTestCase {
   function testExistingRename() {
     // Setup a file to overwrite.
     $contents = $this->randomName(10);
-    $source = $this->createFile(NULL, $contents);
-    $target = $this->createFile();
+    $source   = $this->createFile(NULL, $contents);
+    $target   = $this->createFile();
     $this->assertDifferentFile($source, $target);
 
     // Clone the object so we don't have to worry about the function changing
     // our reference copy.
-    $result = file_copy(clone $source, $target->filepath, FILE_EXISTS_RENAME);
+    $result = file_copy(clone $source, $target->uri, FILE_EXISTS_RENAME);
 
     // Check the return status and that the contents changed.
     $this->assertTrue($result, t('File copied sucessfully.'));
-    $this->assertEqual($contents, file_get_contents($result->filepath), t('Contents of file were copied correctly.'));
-    $this->assertNotEqual($result->filepath, $source->filepath, t('Returned file path has changed from the original.'));
+    $this->assertEqual($contents, file_get_contents($result->uri), t('Contents of file were copied correctly.'));
+    $this->assertNotEqual($result->uri, $source->uri, t('Returned file path has changed from the original.'));
 
     // Check that the correct hooks were called.
     $this->assertFileHooksCalled(array('copy', 'insert'));
@@ -1549,11 +1555,11 @@ class FileCopyTest extends FileHookTestCase {
 
     // Clone the object so we don't have to worry about the function changing
     // our reference copy.
-    $result = file_copy(clone $source, $target->filepath, FILE_EXISTS_REPLACE);
+    $result = file_copy(clone $source, $target->uri, FILE_EXISTS_REPLACE);
 
     // Check the return status and that the contents changed.
     $this->assertTrue($result, t('File copied sucessfully.'));
-    $this->assertEqual($contents, file_get_contents($result->filepath), t('Contents of file were overwritten.'));
+    $this->assertEqual($contents, file_get_contents($result->uri), t('Contents of file were overwritten.'));
     $this->assertDifferentFile($source, $result);
 
     // Check that the correct hooks were called.
@@ -1587,11 +1593,11 @@ class FileCopyTest extends FileHookTestCase {
 
     // Clone the object so we don't have to worry about the function changing
     // our reference copy.
-    $result = file_copy(clone $source, $target->filepath, FILE_EXISTS_ERROR);
+    $result = file_copy(clone $source, $target->uri, FILE_EXISTS_ERROR);
 
     // Check the return status and that the contents were not changed.
     $this->assertFalse($result, t('File copy failed.'));
-    $this->assertEqual($contents, file_get_contents($target->filepath), t('Contents of file were not altered.'));
+    $this->assertEqual($contents, file_get_contents($target->uri), t('Contents of file were not altered.'));
 
     // Check that the correct hooks were called.
     $this->assertFileHooksCalled(array());
@@ -1623,10 +1629,10 @@ class FileLoadTest extends FileHookTestCase {
   }
 
   /**
-   * Try to load a non-existent file by filepath.
+   * Try to load a non-existent file by URI.
    */
   function testLoadMissingFilepath() {
-    $this->assertFalse(reset(file_load_multiple(array(), array('filepath' => 'misc/druplicon.png'))), t("Try to load a file that doesn't exist in the database fails."));
+    $this->assertFalse(reset(file_load_multiple(array(), array('uri' => 'foobar://misc/druplicon.png'))), t("Try to load a file that doesn't exist in the database fails."));
     $this->assertFileHooksCalled(array());
   }
 
@@ -1643,21 +1649,13 @@ class FileLoadTest extends FileHookTestCase {
    */
   function testSingleValues() {
     // Create a new file object from scratch so we know the values.
-    $file = array(
-      'uid' => 1,
-      'filename' => 'druplicon.png',
-      'filepath' => 'misc/druplicon.png',
-      'filemime' => 'image/png',
-      'timestamp' => 1,
-      'status' => FILE_STATUS_PERMANENT,
-    );
-    $file = file_save($file);
+    $file = $this->createFile('druplicon.txt', NULL, 'public://');
 
     $by_fid_file = file_load($file->fid);
     $this->assertFileHookCalled('load');
     $this->assertTrue(is_object($by_fid_file), t('file_load() returned an object.'));
     $this->assertEqual($by_fid_file->fid, $file->fid, t("Loading by fid got the same fid."), 'File');
-    $this->assertEqual($by_fid_file->filepath, $file->filepath, t("Loading by fid got the correct filepath."), 'File');
+    $this->assertEqual($by_fid_file->uri, $file->uri, t("Loading by fid got the correct filepath."), 'File');
     $this->assertEqual($by_fid_file->filename, $file->filename, t("Loading by fid got the correct filename."), 'File');
     $this->assertEqual($by_fid_file->filemime, $file->filemime, t("Loading by fid got the correct MIME type."), 'File');
     $this->assertEqual($by_fid_file->status, $file->status, t("Loading by fid got the correct status."), 'File');
@@ -1669,19 +1667,11 @@ class FileLoadTest extends FileHookTestCase {
    */
   function testMultiple() {
     // Create a new file object.
-    $file = array(
-      'uid' => 1,
-      'filename' => 'druplicon.png',
-      'filepath' => 'misc/druplicon.png',
-      'filemime' => 'image/png',
-      'timestamp' => 1,
-      'status' => FILE_STATUS_PERMANENT,
-    );
-    $file = file_save($file);
+    $file = $this->createFile('druplicon.txt', NULL, 'public://');
 
     // Load by path.
     file_test_reset();
-    $by_path_files = file_load_multiple(array(), array('filepath' => $file->filepath));
+    $by_path_files = file_load_multiple(array(), array('uri' => $file->uri));
     $this->assertFileHookCalled('load');
     $this->assertEqual(1, count($by_path_files), t('file_load_multiple() returned an array of the correct size.'));
     $by_path_file = reset($by_path_files);
@@ -1695,7 +1685,7 @@ class FileLoadTest extends FileHookTestCase {
     $this->assertEqual(1, count($by_fid_files), t('file_load_multiple() returned an array of the correct size.'));
     $by_fid_file = reset($by_fid_files);
     $this->assertTrue($by_fid_file->file_test['loaded'], t('file_test_file_load() was able to modify the file during load.'));
-    $this->assertEqual($by_fid_file->filepath, $file->filepath, t("Loading by fid got the correct filepath."), 'File');
+    $this->assertEqual($by_fid_file->uri, $file->uri, t("Loading by fid got the correct filepath."), 'File');
   }
 }
 
@@ -1715,13 +1705,15 @@ class FileSaveTest extends FileHookTestCase {
     // Create a new file object.
     $file = array(
       'uid' => 1,
-      'filename' => 'druplicon.png',
-      'filepath' => 'misc/druplicon.png',
-      'filemime' => 'image/png',
+      'filename'  => 'druplicon.txt',
+      'uri'       => 'public://druplicon.txt',
+      'filemime'  => 'text/plain',
       'timestamp' => 1,
-      'status' => FILE_STATUS_PERMANENT,
+      'status'    => FILE_STATUS_PERMANENT,
     );
-    $file = (object) $file;
+    $file = (object)$file;
+
+    file_put_contents($file->uri, 'hello world');
 
     // Save it, inserting a new record.
     $saved_file = file_save($file);
@@ -1731,10 +1723,10 @@ class FileSaveTest extends FileHookTestCase {
 
     $this->assertNotNull($saved_file, t("Saving the file should give us back a file object."), 'File');
     $this->assertTrue($saved_file->fid > 0, t("A new file ID is set when saving a new file to the database."), 'File');
-    $loaded_file = db_query('SELECT * FROM {files} f WHERE f.fid = :fid', array(':fid' => $saved_file->fid))->fetch(PDO::FETCH_OBJ);
+    $loaded_file = db_query('SELECT * FROM {file} f WHERE f.fid = :fid', array(':fid' => $saved_file->fid))->fetch(PDO::FETCH_OBJ);
     $this->assertNotNull($loaded_file, t("Record exists in the database."));
     $this->assertEqual($loaded_file->status, $file->status, t("Status was saved correctly."));
-    $this->assertEqual($saved_file->filesize, filesize($file->filepath), t("File size was set correctly."), 'File');
+    $this->assertEqual($saved_file->filesize, filesize($file->uri), t("File size was set correctly."), 'File');
     $this->assertTrue($saved_file->timestamp > 1, t("File size was set correctly."), 'File');
 
 
@@ -1748,7 +1740,7 @@ class FileSaveTest extends FileHookTestCase {
 
     $this->assertEqual($resaved_file->fid, $saved_file->fid, t("The file ID of an existing file is not changed when updating the database."), 'File');
     $this->assertTrue($resaved_file->timestamp >= $saved_file->timestamp, t("Timestamp didn't go backwards."), 'File');
-    $loaded_file = db_query('SELECT * FROM {files} f WHERE f.fid = :fid', array(':fid' => $saved_file->fid))->fetch(PDO::FETCH_OBJ);
+    $loaded_file = db_query('SELECT * FROM {file} f WHERE f.fid = :fid', array(':fid' => $saved_file->fid))->fetch(PDO::FETCH_OBJ);
     $this->assertNotNull($loaded_file, t("Record still exists in the database."), 'File');
     $this->assertEqual($loaded_file->status, $saved_file->status, t("Status was saved correctly."));
   }
@@ -1815,9 +1807,9 @@ class FileSaveDataTest extends FileHookTestCase {
     $result = file_save_data($contents);
     $this->assertTrue($result, t('Unnamed file saved correctly.'));
 
-    $this->assertEqual(file_directory_path(), dirname($result->filepath), t("File was placed in Drupal's files directory."));
-    $this->assertEqual($result->filename, basename($result->filepath), t("Filename was set to the file's basename."));
-    $this->assertEqual($contents, file_get_contents($result->filepath), t('Contents of the file are correct.'));
+    $this->assertEqual(file_directory_path(SCHEME_PUBLIC), file_directory_path(DrupalStreamWrapperRegistry::getStreamScheme($result->uri)), t("File was placed in Drupal's files directory."));
+    $this->assertEqual($result->filename, basename($result->uri), t("Filename was set to the file's basename."));
+    $this->assertEqual($contents, file_get_contents($result->uri), t('Contents of the file are correct.'));
     $this->assertEqual($result->filemime, 'application/octet-stream', t('A MIME type was set.'));
     $this->assertEqual($result->status, FILE_STATUS_PERMANENT, t("The file's status was set to permanent."));
 
@@ -1834,12 +1826,12 @@ class FileSaveDataTest extends FileHookTestCase {
   function testWithFilename() {
     $contents = $this->randomName(8);
 
-    $result = file_save_data($contents, 'asdf.txt');
+    $result = file_save_data($contents, SCHEME_PUBLIC . 'asdf.txt');
     $this->assertTrue($result, t('Unnamed file saved correctly.'));
 
-    $this->assertEqual(file_directory_path(), dirname($result->filepath), t("File was placed in Drupal's files directory."));
-    $this->assertEqual('asdf.txt', basename($result->filepath), t('File was named correctly.'));
-    $this->assertEqual($contents, file_get_contents($result->filepath), t('Contents of the file are correct.'));
+    $this->assertEqual(file_directory_path(SCHEME_PUBLIC), file_directory_path(DrupalStreamWrapperRegistry::getStreamScheme($result->uri)), t("File was placed in Drupal's files directory."));
+    $this->assertEqual('asdf.txt', basename($result->uri), t('File was named correctly.'));
+    $this->assertEqual($contents, file_get_contents($result->uri), t('Contents of the file are correct.'));
     $this->assertEqual($result->filemime, 'text/plain', t('A MIME type was set.'));
     $this->assertEqual($result->status, FILE_STATUS_PERMANENT, t("The file's status was set to permanent."));
 
@@ -1858,12 +1850,12 @@ class FileSaveDataTest extends FileHookTestCase {
     $existing = $this->createFile();
     $contents = $this->randomName(8);
 
-    $result = file_save_data($contents, $existing->filepath, FILE_EXISTS_RENAME);
+    $result = file_save_data($contents, $existing->uri, FILE_EXISTS_RENAME);
     $this->assertTrue($result, t("File saved sucessfully."));
 
-    $this->assertEqual(file_directory_path(), dirname($result->filepath), t("File was placed in Drupal's files directory."));
+    $this->assertEqual(file_directory_path(SCHEME_PUBLIC), file_directory_path(DrupalStreamWrapperRegistry::getStreamScheme($result->uri)), t("File was placed in Drupal's files directory."));
     $this->assertEqual($result->filename, $existing->filename, t("Filename was set to the basename of the source, rather than that of the renamed file."));
-    $this->assertEqual($contents, file_get_contents($result->filepath), t("Contents of the file are correct."));
+    $this->assertEqual($contents, file_get_contents($result->uri), t("Contents of the file are correct."));
     $this->assertEqual($result->filemime, 'application/octet-stream', t("A MIME type was set."));
     $this->assertEqual($result->status, FILE_STATUS_PERMANENT, t("The file's status was set to permanent."));
 
@@ -1886,12 +1878,12 @@ class FileSaveDataTest extends FileHookTestCase {
     $existing = $this->createFile();
     $contents = $this->randomName(8);
 
-    $result = file_save_data($contents, $existing->filepath, FILE_EXISTS_REPLACE);
+    $result = file_save_data($contents, $existing->uri, FILE_EXISTS_REPLACE);
     $this->assertTrue($result, t('File saved sucessfully.'));
 
-    $this->assertEqual(file_directory_path(), dirname($result->filepath), t("File was placed in Drupal's files directory."));
+    $this->assertEqual(file_directory_path(SCHEME_PUBLIC), file_directory_path(DrupalStreamWrapperRegistry::getStreamScheme($result->uri)), t("File was placed in Drupal's files directory."));
     $this->assertEqual($result->filename, $existing->filename, t('Filename was set to the basename of the existing file, rather than preserving the original name.'));
-    $this->assertEqual($contents, file_get_contents($result->filepath), t('Contents of the file are correct.'));
+    $this->assertEqual($contents, file_get_contents($result->uri), t('Contents of the file are correct.'));
     $this->assertEqual($result->filemime, 'application/octet-stream', t('A MIME type was set.'));
     $this->assertEqual($result->status, FILE_STATUS_PERMANENT, t("The file's status was set to permanent."));
 
@@ -1913,9 +1905,9 @@ class FileSaveDataTest extends FileHookTestCase {
     $existing = $this->createFile(NULL, $contents);
 
     // Check the overwrite error.
-    $result = file_save_data('asdf', $existing->filepath, FILE_EXISTS_ERROR);
+    $result = file_save_data('asdf', $existing->uri, FILE_EXISTS_ERROR);
     $this->assertFalse($result, t('Overwriting a file fails when FILE_EXISTS_ERROR is specified.'));
-    $this->assertEqual($contents, file_get_contents($existing->filepath), t('Contents of existing file were unchanged.'));
+    $this->assertEqual($contents, file_get_contents($existing->uri), t('Contents of existing file were unchanged.'));
 
     // Check that no hooks were called while failing.
     $this->assertFileHooksCalled(array());
@@ -1946,11 +1938,10 @@ class FileDownloadTest extends FileTestCase {
    */
   function testPrivateFileTransfer() {
     // Set file downloads to private so handler functions get called.
-    variable_set('file_downloads', FILE_DOWNLOADS_PRIVATE);
 
     // Create a file.
-    $file = $this->createFile();
-    $url = file_create_url($file->filename);
+    $file = $this->createFile(NULL, NULL, 'private://');
+    $url  = file_create_url($file->uri);
 
     // Set file_test access header to allow the download.
     file_test_set_return('download', array('x-foo' => 'Bar'));
@@ -1965,7 +1956,7 @@ class FileDownloadTest extends FileTestCase {
     $this->assertResponse(403, t('Correctly denied access to a file when file_test sets the header to -1.'));
 
     // Try non-existent file.
-    $url = file_create_url($this->randomName());
+    $url = file_create_url('private://' . $this->randomName());
     $this->drupalHead($url);
     $this->assertResponse(404, t('Correctly returned 404 response for a non-existent file.'));
   }
@@ -2048,6 +2039,8 @@ class FileMimeTypeTest extends DrupalWebTestCase {
    * Test mapping of mimetypes from filenames.
    */
   public function testFileMimeTypeDetection() {
+    $prefix = 'simpletest://';
+
     $test_case = array(
       'test.jar' => 'application/java-archive',
       'test.jpeg' => 'image/jpeg',
diff --git modules/simpletest/tests/file_test.module modules/simpletest/tests/file_test.module
index 06aa4ad..b75741c 100644
--- modules/simpletest/tests/file_test.module
+++ modules/simpletest/tests/file_test.module
@@ -57,7 +57,7 @@ function _file_test_form_submit(&$form, &$form_state) {
   $file = file_save_upload('file_test_upload', array('file_validate_is_image' => array()), FALSE, $form_state['values']['file_test_replace']);
   if ($file) {
     $form_state['values']['file_test_upload'] = $file;
-    drupal_set_message(t('File @filepath was uploaded.', array('@filepath' => $file->filepath)));
+    drupal_set_message(t('File @filepath was uploaded.', array('@filepath' => $file->uri)));
     drupal_set_message(t('You WIN!'));
   }
   elseif ($file === FALSE) {
diff --git modules/system/image.gd.inc modules/system/image.gd.inc
index 91f5296..ba25ed3 100644
--- modules/system/image.gd.inc
+++ modules/system/image.gd.inc
@@ -254,6 +254,11 @@ function image_gd_load(stdClass $image) {
  * @see image_save()
  */
 function image_gd_save(stdClass $image, $destination) {
+  // Convert URI to a normal path because PHP apparently has some gaps in stream wrapper support.
+  if ($wrapper = DrupalStreamWrapperRegistry::getInstanceByUri($destination)) {
+    $destination = $wrapper->getInternalUri();
+  }
+  
   $extension = str_replace('jpg', 'jpeg', $image->info['extension']);
   $function = 'image' . $extension;
   if (!function_exists($function)) {
diff --git modules/system/system.admin.inc modules/system/system.admin.inc
index f2507e3..8e6c159 100644
--- modules/system/system.admin.inc
+++ modules/system/system.admin.inc
@@ -315,7 +315,7 @@ function system_themes_form_submit($form, &$form_state) {
  */
 function system_theme_settings(&$form_state, $key = '') {
   $directory_path = file_directory_path();
-  file_check_directory($directory_path, FILE_CREATE_DIRECTORY, 'file_directory_path');
+  file_check_directory($directory_path, FILE_CREATE_DIRECTORY, 'stream_public_path');
 
   // Default settings are defined in theme_get_settings() in includes/theme.inc
   if ($key) {
@@ -339,7 +339,7 @@ function system_theme_settings(&$form_state, $key = '') {
     // The image was saved using file_save_upload() and was added to the
     // files table as a temporary file. We'll make a copy and let the garbage
     // collector delete the original upload.
-    if ($filepath = file_unmanaged_copy($file->filepath, $filename, FILE_EXISTS_REPLACE)) {
+    if ($filepath = file_unmanaged_copy($file->uri, $filename, FILE_EXISTS_REPLACE)) {
       $_POST['default_logo'] = 0;
       $_POST['logo_path'] = $filepath;
       $_POST['toggle_logo'] = 1;
@@ -354,7 +354,7 @@ function system_theme_settings(&$form_state, $key = '') {
     // The image was saved using file_save_upload() and was added to the
     // files table as a temporary file. We'll make a copy and let the garbage
     // collector delete the original upload.
-    if ($filepath = file_unmanaged_copy($file->filepath, $filename, FILE_EXISTS_REPLACE)) {
+    if ($filepath = file_unmanaged_copy($file->uri, $filename, FILE_EXISTS_REPLACE)) {
       $_POST['default_favicon'] = 0;
       $_POST['favicon_path'] = $filepath;
       $_POST['toggle_favicon'] = 1;
@@ -1382,30 +1382,39 @@ function system_clear_cache_submit($form, &$form_state) {
  */
 function system_file_system_settings() {
 
-  $form['file_directory_path'] = array(
+  $form['stream_public_path'] = array(
     '#type' => 'textfield',
-    '#title' => t('File system path'),
+    '#title' => t('Public file system path'),
     '#default_value' => file_directory_path(),
     '#maxlength' => 255,
-    '#description' => t('A file system path where the files will be stored. This directory must exist and be writable by Drupal. If the download method is set to public, this directory must be relative to the Drupal installation directory and be accessible over the web. If the download method is set to private, this directory should not be accessible over the web. Changing this location will modify all download paths and may cause unexpected problems on an existing site.'),
+    '#description' => t('A local file system path where public files will be stored. This directory must exist and be writable by Drupal. This directory must be relative to the Drupal installation directory and be accessible over the web.'),
     '#after_build' => array('system_check_directory'),
   );
 
-  $form['file_directory_temp'] = array(
+  $form['stream_private_path'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Private file system path'),
+    '#default_value' => file_directory_path('private'),
+    '#maxlength' => 255,
+    '#description' => t('A local file system path where private files will be stored. This directory must exist and be writable by Drupal. This directory should not be accessible over the web.'),
+    '#after_build' => array('system_check_directory'),
+  );
+
+  $form['stream_temp_path'] = array(
     '#type' => 'textfield',
     '#title' => t('Temporary directory'),
     '#default_value' => file_directory_temp(),
     '#maxlength' => 255,
-    '#description' => t('A file system path where uploaded files will be stored during previews.'),
+    '#description' => t('A local file system path where temporary files will be stored. This directory should not be accessible over the web.'),
     '#after_build' => array('system_check_directory'),
   );
 
   $form['file_downloads'] = array(
     '#type' => 'radios',
-    '#title' => t('Download method'),
+    '#title' => t('Default download method'),
     '#default_value' => FILE_DOWNLOADS_PUBLIC,
     '#options' => array(FILE_DOWNLOADS_PUBLIC => t('Public - files are available using HTTP directly.'), FILE_DOWNLOADS_PRIVATE => t('Private - files are transferred by Drupal.')),
-    '#description' => t('Choose the <em>Public download</em> method unless you wish to enforce fine-grained access controls over file downloads. Changing the download method will modify all download paths and may cause unexpected problems on an existing site.')
+    '#description' => t('This setting is simply used as the preferred download method. The download method will ultimately be determined by the URI of a file.')
   );
 
   return system_settings_form($form, TRUE);
diff --git modules/system/system.api.php modules/system/system.api.php
index 5c828fe..783fa6d 100644
--- modules/system/system.api.php
+++ modules/system/system.api.php
@@ -1328,7 +1328,8 @@ 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 = :filepath", array('filepath' => $filepath));
+  // TODO: This will need to be updated because of wrappers.
+  $result = db_query("SELECT f.* FROM {file} f INNER JOIN {upload} u ON f.fid = u.fid WHERE uri = :uri", array('uri' => $filepath));
   foreach ($result as $file) {
     if (!user_access('view uploaded files')) {
       return -1;
diff --git modules/system/system.install modules/system/system.install
index 2a15af8..231aa28 100644
--- modules/system/system.install
+++ modules/system/system.install
@@ -712,7 +712,10 @@ function system_schema() {
   $schema['cache_registry'] = $schema['cache'];
   $schema['cache_registry']['description'] = 'Cache table for the code registry system to remember what code files need to be loaded on any given page.';
 
-  $schema['files'] = array(
+  /*
+    TODO: Update the master record when removing the status column.
+  */
+  $schema['file'] = array(
     'description' => 'Stores information for uploaded files.',
     'fields' => array(
       'fid' => array(
@@ -735,7 +738,7 @@ function system_schema() {
         'not null' => TRUE,
         'default' => '',
       ),
-      'filepath' => array(
+      'uri' => array(
         'description' => 'Path of the file relative to Drupal root.',
         'type' => 'varchar',
         'length' => 255,
@@ -775,6 +778,9 @@ function system_schema() {
       'status' => array('status'),
       'timestamp' => array('timestamp'),
     ),
+    'unique keys' => array(
+      'uri' => array('uri'),
+    ),
     'primary key' => array('fid'),
     'foreign keys' => array(
       'uid' => array('users' => 'uid'),
@@ -2241,6 +2247,86 @@ function system_update_7029() {
 }
 
 /**
+ * Create the {file} with the unique key on the filepath.
+ */
+function system_update_7030() {
+
+  /*
+    TODO Update the update record when removing the status column
+  */
+
+  $schema['file'] = array(
+    'description' => 'Stores information for uploaded files.',
+    'fields' => array(
+      'fid' => array(
+        'description' => 'File ID.',
+        'type' => 'serial',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+      ),
+      'uid' => array(
+        'description' => 'The {user}.uid of the user who is associated with the file.',
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'filename' => array(
+        'description' => 'Name of the file with no path components. This may differ from the basename of the filepath if the file is renamed to avoid overwriting an existing file.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'uri' => array(
+        'description' => 'URI of file.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'filemime' => array(
+        'description' => "The file's MIME type.",
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'filesize' => array(
+        'description' => 'The size of the file in bytes.',
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'status' => array(
+        'description' => 'A bitmapped field indicating the status of the file the least sigifigant bit indicates temporary (1) or permanent (0). Temporary files older than DRUPAL_MAXIMUM_TEMP_FILE_AGE will be removed during a cron run.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'timestamp' => array(
+        'description' => 'UNIX timestamp for when the file was added.',
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+    ),
+    'indexes' => array(
+      'uid' => array('uid'),
+      'status' => array('status'),
+      'timestamp' => array('timestamp'),
+    ),
+    'unique keys' => array(
+      'uri' => array('uri'),
+    ),
+    'primary key' => array('fid'),
+  );
+  db_create_table($ret, 'file', $schema['file']);
+}
+
+/**
  * @} End of "defgroup updates-6.x-to-7.x"
  * The next series of updates should start at 8000.
  */
diff --git modules/system/system.module modules/system/system.module
index 8b7cff7..2725393 100644
--- modules/system/system.module
+++ modules/system/system.module
@@ -1662,7 +1662,7 @@ function system_get_files_database(&$files, $type) {
   $result = db_query("SELECT filename, name, type, status, schema_version, weight FROM {system} WHERE type = :type", array(':type' => $type));
   foreach ($result as $file) {
     if (isset($files[$file->name]) && is_object($files[$file->name])) {
-      $file->filepath = $file->filename;
+      $file->uri = $file->filename;
       foreach ($file as $key => $value) {
         if (!isset($files[$file->name]->key)) {
           $files[$file->name]->$key = $value;
@@ -1738,7 +1738,7 @@ function system_update_files_database(&$files, $type) {
     }
     else {
       $query->values(array(
-        'filename' => $file->filepath,
+        'filename' => $file->uri,
         'name' => $file->name,
         'type' => $type,
         'owner' => isset($file->owner) ? $file->owner : '',
@@ -1776,7 +1776,7 @@ function _system_get_module_data() {
   // Read info files for each module.
   foreach ($modules as $key => $module) {
     // Look for the info file.
-    $module->info = drupal_parse_info_file(dirname($module->filepath) . '/' . $module->name . '.info');
+    $module->info = drupal_parse_info_file(dirname($module->uri) . '/' . $module->name . '.info');
 
     // Skip modules that don't provide info.
     if (empty($module->info)) {
@@ -1857,8 +1857,8 @@ function _system_get_theme_data() {
     $sub_themes = array();
     // Read info files for each theme
     foreach ($themes as $key => $theme) {
-      $themes[$key]->filename = $theme->filepath;
-      $themes[$key]->info = drupal_parse_info_file($theme->filepath) + $defaults;
+      $themes[$key]->filename = $theme->uri;
+      $themes[$key]->info = drupal_parse_info_file($theme->uri) + $defaults;
 
       // Invoke hook_system_info_alter() to give installed modules a chance to
       // modify the data in the .info files if necessary.
@@ -1868,7 +1868,7 @@ function _system_get_theme_data() {
         $sub_themes[] = $key;
       }
       if (empty($themes[$key]->info['engine'])) {
-        $filename = dirname($themes[$key]->filepath) . '/' . $themes[$key]->name . '.theme';
+        $filename = dirname($themes[$key]->uri) . '/' . $themes[$key]->name . '.theme';
         if (file_exists($filename)) {
           $themes[$key]->owner = $filename;
           $themes[$key]->prefix = $key;
@@ -1877,7 +1877,7 @@ function _system_get_theme_data() {
       else {
         $engine = $themes[$key]->info['engine'];
         if (isset($engines[$engine])) {
-          $themes[$key]->owner = $engines[$engine]->filepath;
+          $themes[$key]->owner = $engines[$engine]->uri;
           $themes[$key]->prefix = $engines[$engine]->name;
           $themes[$key]->template = TRUE;
         }
@@ -1888,7 +1888,7 @@ function _system_get_theme_data() {
       if (isset($themes[$key]->info['stylesheets'])) {
         foreach ($themes[$key]->info['stylesheets'] as $media => $stylesheets) {
           foreach ($stylesheets as $stylesheet) {
-            $pathed_stylesheets[$media][$stylesheet] = dirname($themes[$key]->filepath) . '/' . $stylesheet;
+            $pathed_stylesheets[$media][$stylesheet] = dirname($themes[$key]->uri) . '/' . $stylesheet;
           }
         }
       }
@@ -1898,13 +1898,13 @@ function _system_get_theme_data() {
       $scripts = array();
       if (isset($themes[$key]->info['scripts'])) {
         foreach ($themes[$key]->info['scripts'] as $script) {
-          $scripts[$script] = dirname($themes[$key]->filepath) . '/' . $script;
+          $scripts[$script] = dirname($themes[$key]->uri) . '/' . $script;
         }
       }
       $themes[$key]->info['scripts'] = $scripts;
       // Give the screenshot proper path information.
       if (!empty($themes[$key]->info['screenshot'])) {
-        $themes[$key]->info['screenshot'] = dirname($themes[$key]->filepath) . '/' . $themes[$key]->info['screenshot'];
+        $themes[$key]->info['screenshot'] = dirname($themes[$key]->uri) . '/' . $themes[$key]->info['screenshot'];
       }
     }
 
@@ -2259,7 +2259,7 @@ function system_cron() {
   // Remove temporary files that are older than DRUPAL_MAXIMUM_TEMP_FILE_AGE.
   // Use separate placeholders for the status to avoid a bug in some versions
   // of PHP. See http://drupal.org/node/352956
-  $result = db_query('SELECT fid FROM {files} WHERE status & :permanent1 <> :permanent2 AND timestamp < :timestamp', array(
+  $result = db_query('SELECT fid FROM {file} WHERE status & :permanent1 <> :permanent2 AND timestamp < :timestamp', array(
     ':permanent1' => FILE_STATUS_PERMANENT,
     ':permanent2' => FILE_STATUS_PERMANENT,
     ':timestamp' => REQUEST_TIME - DRUPAL_MAXIMUM_TEMP_FILE_AGE
@@ -2267,7 +2267,7 @@ function system_cron() {
   foreach ($result as $row) {
     if ($file = file_load($row->fid)) {
       if (!file_delete($file)) {
-        watchdog('file system', 'Could not delete temporary file "%path" during garbage collection', array('%path' => $file->filepath), WATCHDOG_ERROR);
+        watchdog('file system', 'Could not delete temporary file "%path" during garbage collection', array('%path' => $file->uri), WATCHDOG_ERROR);
       }
     }
   }
diff --git modules/system/system.test modules/system/system.test
index c75644c..3c6e4d8 100644
--- modules/system/system.test
+++ modules/system/system.test
@@ -339,41 +339,41 @@ class CronRunTestCase extends DrupalWebTestCase {
 
     // Temporary file that is older than DRUPAL_MAXIMUM_TEMP_FILE_AGE.
     $temp_old = file_save_data('');
-    db_update('files')
+    db_update('file')
       ->fields(array(
         'status' => 0,
         'timestamp' => 1,
       ))
       ->condition('fid', $temp_old->fid)
       ->execute();
-    $this->assertTrue(file_exists($temp_old->filepath), t('Old temp file was created correctly.'));
+    $this->assertTrue(file_exists($temp_old->uri), t('Old temp file was created correctly.'));
 
     // Temporary file that is less than DRUPAL_MAXIMUM_TEMP_FILE_AGE.
     $temp_new = file_save_data('');
-    db_update('files')
+    db_update('file')
       ->fields(array('status' => 0))
       ->condition('fid', $temp_new->fid)
       ->execute();
-    $this->assertTrue(file_exists($temp_new->filepath), t('New temp file was created correctly.'));
+    $this->assertTrue(file_exists($temp_new->uri), t('New temp file was created correctly.'));
 
     // Permanent file that is older than DRUPAL_MAXIMUM_TEMP_FILE_AGE.
     $perm_old = file_save_data('');
-    db_update('files')
+    db_update('file')
       ->fields(array('timestamp' => 1))
       ->condition('fid', $temp_old->fid)
       ->execute();
-    $this->assertTrue(file_exists($perm_old->filepath), t('Old permanent file was created correctly.'));
+    $this->assertTrue(file_exists($perm_old->uri), t('Old permanent file was created correctly.'));
 
     // Permanent file that is newer than DRUPAL_MAXIMUM_TEMP_FILE_AGE.
     $perm_new = file_save_data('');
-    $this->assertTrue(file_exists($perm_new->filepath), t('New permanent file was created correctly.'));
+    $this->assertTrue(file_exists($perm_new->uri), t('New permanent file was created correctly.'));
 
     // Run cron and then ensure that only the old, temp file was deleted.
     $this->assertTrue(drupal_cron_run(), t('Cron ran successfully.'));
-    $this->assertFalse(file_exists($temp_old->filepath), t('Old temp file was correctly removed.'));
-    $this->assertTrue(file_exists($temp_new->filepath), t('New temp file was correctly ignored.'));
-    $this->assertTrue(file_exists($perm_old->filepath), t('Old permanent file was correctly ignored.'));
-    $this->assertTrue(file_exists($perm_new->filepath), t('New permanent file was correctly ignored.'));
+    $this->assertFalse(file_exists($temp_old->uri), t('Old temp file was correctly removed.'));
+    $this->assertTrue(file_exists($temp_new->uri), t('New temp file was correctly ignored.'));
+    $this->assertTrue(file_exists($perm_old->uri), t('Old permanent file was correctly ignored.'));
+    $this->assertTrue(file_exists($perm_new->uri), t('New permanent file was correctly ignored.'));
   }
 }
 
diff --git modules/update/update.compare.inc modules/update/update.compare.inc
index 65f77d0..fa71bba 100644
--- modules/update/update.compare.inc
+++ modules/update/update.compare.inc
@@ -80,7 +80,7 @@ function _update_process_info_list(&$projects, $list, $project_type) {
     // which is left alone by tar and correctly set to the time the .info file
     // was unpacked.
     if (!isset($file->info['_info_file_ctime'])) {
-      $info_filename = dirname($file->filepath) . '/' . $file->name . '.info';
+      $info_filename = dirname($file->uri) . '/' . $file->name . '.info';
       $file->info['_info_file_ctime'] = filectime($info_filename);
     }
 
diff --git modules/upload/upload.install modules/upload/upload.install
index 0fa9d05..14ccd85 100644
--- modules/upload/upload.install
+++ modules/upload/upload.install
@@ -43,7 +43,7 @@ function upload_schema() {
         'unsigned' => TRUE,
         'not null' => TRUE,
         'default' => 0,
-        'description' => 'Primary Key: The {files}.fid.',
+        'description' => 'Primary Key: The {file}.fid.',
       ),
       'nid' => array(
         'type' => 'int',
@@ -98,3 +98,58 @@ function upload_schema() {
 }
 
 
+/**
+ * Migrate upload module files from {files} to {file}.
+ */
+function upload_update_7000(&$sandbox) {
+  $ret = array();
+
+  /*
+    TODO: Fix the updates. This is broken. See http://drupal.org/node/329301#comment-1404336
+    Also note new DB structure http://drupal.org/node/227232#comment-1683976
+  */
+
+  if (!isset($sandbox['progress'])) {
+    // Initialize batch update information.
+    $sandbox['progress'] = 0;
+    $sandbox['last_fid_processed'] = -1;
+    $sandbox['max'] = db_query("SELECT COUNT(DISTINCT u.fid) FROM {upload} u")->fetchField();
+  }
+
+  // As a batch operation move records from {files} into the {file} table.
+  $limit = 500;
+  $result = db_query_range("SELECT DISTINCT u.fid FROM {upload} u ORDER BY u.vid", array(), 0, $limit);
+  foreach ($result as $record) {
+    $old_file = db_query('SELECT f.* FROM {files} f WHERE f.fid = :fid', array(':fid' => $record->fid))->fetch(PDO::FETCH_OBJ);
+    if (!$old_file) {
+      continue;
+    }
+
+    $new_file = db_query('SELECT f.* FROM {files} f WHERE f.filepath = :filepath', array(':filepath' => $old_file->uri))->fetch(PDO::FETCH_OBJ);
+    if (!$new_file) {
+      // Re-save the file into the new {file} table.
+      $new_file = clone $old_file;
+      drupal_write_record('file', $new_file);
+    }
+
+    // If the fid has changed we need to update the {upload} record to use the
+    // new id.
+    if (!empty($new_file->fid) && ($new_file->fid != $old_file->fid)) {
+      db_update('upload')
+        ->fields(array('fid' => $new_file->fid))
+        ->condition('fid', $old_file->fid)
+        ->execute();
+    }
+
+    // Update our progress information for the batch update.
+    $sandbox['progress']++;
+    $sandbox['last_fid_processed'] = $old_file->fid;
+  }
+
+  // Indicate our current progress to the batch update system. If there's no
+  // max value then there's nothing to update and we're finished.
+  $ret['#finished'] = empty($sandbox['max']) ? 1 : ($sandbox['progress'] / $sandbox['max']);
+
+  return $ret;
+}
+
diff --git modules/upload/upload.module modules/upload/upload.module
index ee019f1..0316db3 100644
--- modules/upload/upload.module
+++ modules/upload/upload.module
@@ -151,7 +151,7 @@ function _upload_file_limits($user) {
  */
 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();
+  $file = db_query("SELECT f.*, u.nid FROM {file} f INNER JOIN {upload} u ON f.fid = u.fid WHERE uri = :path", array(':path' => $filepath))->fetchObject();
 
   if ($file && user_access('view uploaded files') && ($node = node_load($file->nid)) && node_access('view', $node)) {
     return array(
@@ -182,7 +182,7 @@ function upload_node_form_submit(&$form, &$form_state) {
   );
 
   // Save new file uploads.
-  if (user_access('upload files') && ($file = file_save_upload('upload', $validators, file_directory_path()))) {
+  if (user_access('upload files') && ($file = file_save_upload('upload', $validators, SCHEME_PUBLIC))) {
     $file->list = variable_get('upload_list_default', 1);
     $file->description = $file->filename;
     $file->weight = 0;
@@ -244,6 +244,7 @@ function upload_form_alter(&$form, $form_state, $form_id) {
 
       // Make sure necessary directories for upload.module exist and are
       // writable before displaying the attachment form.
+      // TODO: Add private stream wrapper functionality
       $path = file_directory_path();
       $temp = file_directory_temp();
       // Note: pass by reference
@@ -372,7 +373,7 @@ function upload_node_view($node, $build_mode) {
       $node->rss_elements[] = array(
         'key' => 'enclosure',
         'attributes' => array(
-          'url' => file_create_url($file->filepath),
+          'url' => file_create_url($file->uri),
           'length' => $file->filesize,
           'type' => $file->filemime
         )
@@ -443,7 +444,7 @@ function theme_upload_attachments($elements) {
   foreach ($elements['#files'] as $file) {
     $file = (object)$file;
     if ($file->list && empty($file->remove)) {
-      $href = file_create_url($file->filepath);
+      $href = file_create_url($file->uri);
       $text = $file->description ? $file->description : $file->filename;
       $rows[] = array(l($text, $href), format_size($file->filesize));
     }
@@ -472,7 +473,7 @@ function upload_space_used($uid) {
  *   The amount of disk space used by uploaded files in bytes.
  */
 function upload_total_space_used() {
-  return db_query('SELECT SUM(f.filesize) FROM {files} f INNER JOIN {upload} u ON f.fid = u.fid')->fetchField();
+  return db_query('SELECT SUM(f.filesize) FROM {file} f INNER JOIN {upload} u ON f.fid = u.fid')->fetchField();
 }
 
 function upload_save($node) {
@@ -543,13 +544,13 @@ function _upload_form($node) {
       $file = (object)$file;
       $key = $file->fid;
 
-      $form['files'][$key]['description'] = array('#type' => 'textfield', '#default_value' => !empty($file->description) ? $file->description : $file->filename, '#maxlength' => 256, '#description' => '<small>' . file_create_url($file->filepath) . '</small>');
+      $form['files'][$key]['description'] = array('#type' => 'textfield', '#default_value' => !empty($file->description) ? $file->description : $file->filename, '#maxlength' => 256, '#description' => '<small>' . file_create_url($file->uri) . '</small>');
       $form['files'][$key]['size'] = array('#markup' => format_size($file->filesize));
       $form['files'][$key]['remove'] = array('#type' => 'checkbox', '#default_value' => !empty($file->remove));
       $form['files'][$key]['list'] = array('#type' => 'checkbox',  '#default_value' => $file->list);
       $form['files'][$key]['weight'] = array('#type' => 'weight', '#delta' => count($node->files), '#default_value' => $file->weight);
       $form['files'][$key]['filename'] = array('#type' => 'value',  '#value' => $file->filename);
-      $form['files'][$key]['filepath'] = array('#type' => 'value',  '#value' => $file->filepath);
+      $form['files'][$key]['uri'] = array('#type' => 'value',  '#value' => $file->uri);
       $form['files'][$key]['filemime'] = array('#type' => 'value',  '#value' => $file->filemime);
       $form['files'][$key]['filesize'] = array('#type' => 'value',  '#value' => $file->filesize);
       $form['files'][$key]['fid'] = array('#type' => 'value',  '#value' => $file->fid);
diff --git modules/upload/upload.test modules/upload/upload.test
index 2ea1e93..1eeaad1 100644
--- modules/upload/upload.test
+++ modules/upload/upload.test
@@ -45,7 +45,7 @@ class UploadTestCase extends DrupalWebTestCase {
     // Create a node and attempt to attach files.
     $node = $this->drupalCreateNode();
     $text_files = $this->drupalGetTestFiles('text');
-    $files = array(current($text_files)->filepath, next($text_files)->filepath);
+    $files = array(current($text_files)->uri, next($text_files)->uri);
 
     $this->uploadFile($node, $files[0]);
     $this->uploadFile($node, $files[1]);
@@ -86,7 +86,9 @@ class UploadTestCase extends DrupalWebTestCase {
       $this->assertRaw(t('Page %title has been updated.', array('%title' => $node->title)), 'File deleted successfully.');
 
       $this->assertNoText($new_name, $new_name . ' not found on node.');
-      $this->drupalGet($base_url . '/' . file_directory_path() . '/' . $upload->description, array('external' => TRUE));
+      $uri = SCHEME_PUBLIC . $upload->description;
+      $external_uri = DrupalStreamWrapperRegistry::getInstanceByUri($uri)->getExternalUrl();
+      $this->drupalGet($external_uri, array('external' => TRUE));
       $this->assertResponse(array(404), 'Uploaded ' . $upload->description . ' is not accessible.');
     }
     else {
@@ -119,17 +121,17 @@ class UploadTestCase extends DrupalWebTestCase {
     $text_file = current($this->drupalGetTestFiles('text'));
     // Select a file that's less than the 1MB upload limit so we only test one
     // limit at a time.
-    $this->uploadFile($node, $text_file->filepath, FALSE);
+    $this->uploadFile($node, $text_file->uri, FALSE);
     // Test the error message in two steps in case there are additional errors
     // that change the error message's format.
-    $this->assertRaw(t('The specified file %name could not be uploaded.', array('%name' => $text_file->filename)), t('File %filepath was not allowed to be uploaded', array('%filepath' => $text_file->filepath)));
+    $this->assertRaw(t('The specified file %name could not be uploaded.', array('%name' => $text_file->filename)), t('File %filepath was not allowed to be uploaded', array('%filepath' => $text_file->uri)));
     $this->assertRaw(t('Only files with the following extensions are allowed: %files-allowed.', array('%files-allowed' => $settings['upload_extensions'])), t('File extension cited as reason for failure'));
 
     // Attempt to upload .html file when .html is only extension allowed.
     $html_files = array_values($this->drupalGetTestFiles('html'));
     // Use the HTML file with the .html extension, $html_files[0] has a .txt
     // extension.
-    $html_file = $html_files[1]->filepath;
+    $html_file = $html_files[1]->uri;
     $this->uploadFile($node, $html_file);
     $this->assertNoRaw(t('The specified file %name could not be uploaded.', array('%name' => basename($html_file))), t('File ' . $html_file . ' was allowed to be uploaded'));
   }
@@ -139,7 +141,7 @@ class UploadTestCase extends DrupalWebTestCase {
    */
   function testLimit() {
     $files = $this->drupalGetTestFiles('text', 1310720); // 1 MB.
-    $file = current($files)->filepath;
+    $file = current($files)->uri;
 
     $admin_user = $this->drupalCreateUser(array('administer site configuration'));
     $web_user = $this->drupalCreateUser(array('access content', 'edit own page content', 'upload files', 'view uploaded files'));
@@ -206,7 +208,7 @@ class UploadTestCase extends DrupalWebTestCase {
    */
   function checkUploadedFile($filename) {
     global $base_url;
-    $file = file_directory_path() . '/' . $filename;
+    $file = SCHEME_PUBLIC . $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.'));
diff --git modules/user/user.install modules/user/user.install
index 7a63b2f..77ef792 100644
--- modules/user/user.install
+++ modules/user/user.install
@@ -184,7 +184,7 @@ function user_schema() {
         'type' => 'int',
         'not null' => TRUE,
         'default' => 0,
-        'description' => "Foreign key: {files}.fid of user's picture.",
+        'description' => "Foreign key: {file}.fid of user's picture.",
       ),
       'init' => array(
         'type' => 'varchar',
@@ -405,7 +405,7 @@ function user_update_7003() {
 }
 
 /**
- * Add the user's pictures to the {files} table and make them managed files.
+ * Add the user's pictures to the {file} table and make them managed files.
  */
 function user_update_7004(&$sandbox) {
   $ret = array();
@@ -414,7 +414,7 @@ function user_update_7004(&$sandbox) {
     'type' => 'int',
     'not null' => TRUE,
     'default' => 0,
-    'description' => t("Foriegn key: {files}.fid of user's picture."),
+    'description' => t("Foriegn key: {file}.fid of user's picture."),
   );
 
   if (!isset($sandbox['progress'])) {
@@ -428,13 +428,13 @@ function user_update_7004(&$sandbox) {
     // Initialize batch update information.
     $sandbox['progress'] = 0;
     $sandbox['last_user_processed'] = -1;
-    $sandbox['max'] = db_query("SELECT COUNT(*) FROM {users} WHERE picture <> ''")->fetchField();
+    $sandbox['max'] = db_query("SELECT COUNT(*) FROM {user} WHERE picture <> ''")->fetchField();
   }
 
-  // As a batch operation move the photos into the {files} table and update the
+  // As a batch operation move the photos into the {file} table and update the
   // {users} records.
   $limit = 500;
-  $result = db_query_range("SELECT uid, picture FROM {users} WHERE picture <> '' AND uid > :uid ORDER BY uid", array(':uid' => $sandbox['last_user_processed']), 0, $limit);
+  $result = db_query_range("SELECT uid, picture FROM {user} WHERE picture <> '' AND uid > :uid ORDER BY uid", array(':uid' => $sandbox['last_user_processed']), 0, $limit);
   foreach ($result as $user) {
     // Don't bother adding files that don't exist.
     if (!file_exists($user->picture)) {
@@ -442,16 +442,16 @@ function user_update_7004(&$sandbox) {
     }
 
     // Check if the file already exists.
-    $files = file_load_multiple(array(), array('filepath' => $user->picture));
+    $files = file_load_multiple(array(), array('uri' => $user->picture));
     if (count($files)) {
       $file = reset($files);
     }
     else {
       // Create a file object.
       $file = new stdClass();
-      $file->filepath = $user->picture;
-      $file->filename = basename($file->filepath);
-      $file->filemime = file_get_mimetype($file->filepath);
+      $file->uri      = $user->picture;
+      $file->filename = basename($file->uri);
+      $file->filemime = file_get_mimetype($file->uri);
       $file->uid      = $user->uid;
       $file->status   = FILE_STATUS_PERMANENT;
       $file = file_save($file);
@@ -474,8 +474,8 @@ function user_update_7004(&$sandbox) {
   // When we're finished, drop the old picture field and rename the new one to
   // replace it.
   if (isset($ret['#finished']) && $ret['#finished'] == 1) {
-    db_drop_field($ret, 'users', 'picture');
-    db_change_field($ret, 'users', 'picture_fid', 'picture', $picture_field);
+    db_drop_field($ret, 'user', 'picture');
+    db_change_field($ret, 'user', 'picture_fid', 'picture', $picture_field);
   }
 
   return $ret;
diff --git modules/user/user.module modules/user/user.module
index 0567b35..90ecfac 100644
--- modules/user/user.module
+++ modules/user/user.module
@@ -404,7 +404,8 @@ function user_save($account, $edit = array(), $category = 'account') {
       // If the picture is a temporary file move it to its final location and
       // make it permanent.
       if (($picture->status & FILE_STATUS_PERMANENT) == 0) {
-        $info = image_get_info($picture->filepath);
+        $info = image_get_info($picture->uri);
+        // TODO: Lookup a private/public setting. Or user_picture_path should include private:// or public://.
         $destination = file_create_path(variable_get('user_picture_path', 'pictures') . '/picture-' . $account->uid . '.' . $info['extension']);
         if ($picture = file_move($picture, $destination, FILE_EXISTS_REPLACE)) {
           $picture->status |= FILE_STATUS_PERMANENT;
@@ -1167,8 +1168,8 @@ function template_preprocess_user_picture(&$variables) {
       if (is_numeric($account->picture)) {
         $account->picture = file_load($account->picture);
       }
-      if (!empty($account->picture->filepath)) {
-        $filepath = $account->picture->filepath;
+      if (!empty($account->picture->uri)) {
+        $filepath = $account->picture->uri;
       }
     }
     elseif (variable_get('user_picture_default', '')) {
diff --git modules/user/user.test modules/user/user.test
index f365f14..36c309a 100644
--- modules/user/user.test
+++ modules/user/user.test
@@ -517,11 +517,15 @@ class UserPictureTestCase extends DrupalWebTestCase {
     $this->user = $this->drupalCreateUser();
 
     // Test if directories specified in settings exist in filesystem.
-    $file_dir = file_directory_path();
-    $file_check = file_check_directory($file_dir, FILE_CREATE_DIRECTORY, 'file_directory_path');
+    $file_dir = SCHEME_PUBLIC;
+    $file_check = file_check_directory($file_dir, FILE_CREATE_DIRECTORY, 'stream_public_path');
+
+    /*
+      TODO: Add capability to store photos publicly or privately, but tests will be the same.
+    */
 
     $picture_dir = variable_get('user_picture_path', 'pictures');
-    $picture_path = $file_dir . '/' . $picture_dir;
+    $picture_path = $file_dir . $picture_dir;
 
     $pic_check = file_check_directory($picture_path, FILE_CREATE_DIRECTORY, 'user_picture_path');
     $this->_directory_test = is_writable($picture_path);
@@ -550,7 +554,7 @@ class UserPictureTestCase extends DrupalWebTestCase {
         $this->drupalLogin($this->user);
 
         $image = current($this->drupalGetTestFiles('image'));
-        $info = image_get_info($image->filepath);
+        $info = image_get_info($image->uri);
 
         // Set new variables: invalid dimensions, valid filesize (0 = no limit).
         $test_dim = ($info['width'] - 10) . 'x' . ($info['height'] - 10);
@@ -587,7 +591,7 @@ class UserPictureTestCase extends DrupalWebTestCase {
         // Images are sorted first by size then by name. We need an image
         // bigger than 1 KB so we'll grab the last one.
         $image = end($this->drupalGetTestFiles('image'));
-        $info = image_get_info($image->filepath);
+        $info = image_get_info($image->uri);
 
         // Set new variables: valid dimensions, invalid filesize.
         $test_dim = ($info['width'] + 10) . 'x' . ($info['height'] + 10);
@@ -600,7 +604,7 @@ class UserPictureTestCase extends DrupalWebTestCase {
         // Test that the upload failed and that the correct reason was cited.
         $text = t('The specified file %filename could not be uploaded.', array('%filename' => $image->filename));
         $this->assertRaw($text, t('Upload failed.'));
-        $text = t('The file is %filesize exceeding the maximum file size of %maxsize.', array('%filesize' => format_size(filesize($image->filepath)), '%maxsize' => format_size($test_size * 1024)));
+        $text = t('The file is %filesize exceeding the maximum file size of %maxsize.', array('%filesize' => format_size(filesize($image->uri)), '%maxsize' => format_size($test_size * 1024)));
         $this->assertRaw($text, t('File size cited as reason for failure.'));
 
         // Check if file is not uploaded.
@@ -622,7 +626,7 @@ class UserPictureTestCase extends DrupalWebTestCase {
         $this->drupalLogin($this->user);
 
         $image = current($this->drupalGetTestFiles('image'));
-        $info = image_get_info($image->filepath);
+        $info = image_get_info($image->uri);
 
         // Set new variables: invalid dimensions, valid filesize (0 = no limit).
         $test_dim = ($info['width'] - 10) . 'x' . ($info['height'] - 10);
@@ -655,7 +659,7 @@ class UserPictureTestCase extends DrupalWebTestCase {
         $this->drupalLogin($this->user);
 
         $image = current($this->drupalGetTestFiles('image'));
-        $info = image_get_info($image->filepath);
+        $info = image_get_info($image->uri);
 
         // Set new variables: valid dimensions, invalid filesize.
         $test_dim = ($info['width'] + 10) . 'x' . ($info['height'] + 10);
@@ -668,7 +672,7 @@ class UserPictureTestCase extends DrupalWebTestCase {
         // Test that the upload failed and that the correct reason was cited.
         $text = t('The specified file %filename could not be uploaded.', array('%filename' => $image->filename));
         $this->assertRaw($text, t('Upload failed.'));
-        $text = t('The file is %filesize exceeding the maximum file size of %maxsize.', array('%filesize' => format_size(filesize($image->filepath)), '%maxsize' => format_size($test_size * 1024)));
+        $text = t('The file is %filesize exceeding the maximum file size of %maxsize.', array('%filesize' => format_size(filesize($image->uri)), '%maxsize' => format_size($test_size * 1024)));
         $this->assertRaw($text, t('File size cited as reason for failure.'));
 
         // Check if file is not uploaded.
@@ -687,7 +691,7 @@ class UserPictureTestCase extends DrupalWebTestCase {
       $this->drupalLogin($this->user);
 
       $image = current($this->drupalGetTestFiles('image'));
-      $info = image_get_info($image->filepath);
+      $info = image_get_info($image->uri);
 
       // Set new variables: valid dimensions, valid filesize (0 = no limit).
       $test_dim = ($info['width'] + 10) . 'x' . ($info['height'] + 10);
@@ -698,7 +702,7 @@ class UserPictureTestCase extends DrupalWebTestCase {
 
       // Check if image is displayed in user's profile page.
       $this->drupalGet('user');
-      $this->assertRaw($pic_path, t("Image is displayed in user's profile page"));
+      $this->assertRaw(DrupalStreamWrapperRegistry::getStreamTarget($pic_path), t("Image is displayed in user's profile page"));
 
       // Check if file is located in proper directory.
       $this->assertTrue(is_file($pic_path), t('File is located in proper directory'));
@@ -706,12 +710,12 @@ class UserPictureTestCase extends DrupalWebTestCase {
   }
 
   function saveUserPicture($image) {
-    $edit = array('files[picture_upload]' => drupal_realpath($image->filepath));
+    $edit = array('files[picture_upload]' => drupal_realpath($image->uri));
     $this->drupalPost('user/' . $this->user->uid . '/edit', $edit, t('Save'));
 
-    $img_info = image_get_info($image->filepath);
+    $img_info    = image_get_info($image->uri);
     $picture_dir = variable_get('user_picture_path', 'pictures');
-    $pic_path = file_directory_path() . '/' . $picture_dir . '/picture-' . $this->user->uid . '.' . $img_info['extension'];
+    $pic_path    = SCHEME_PUBLIC . $picture_dir . '/picture-' . $this->user->uid . '.' . $img_info['extension'];
 
     return $pic_path;
   }
