diff options
Diffstat (limited to 'includes/file.inc')
-rw-r--r-- | includes/file.inc | 63 |
1 files changed, 50 insertions, 13 deletions
diff --git a/includes/file.inc b/includes/file.inc index 40e8349a0..7fd6c71c9 100644 --- a/includes/file.inc +++ b/includes/file.inc @@ -770,7 +770,7 @@ function file_copy(stdClass $source, $destination = NULL, $replace = FILE_EXISTS $file = clone $source; $file->fid = NULL; $file->uri = $uri; - $file->filename = basename($uri); + $file->filename = drupal_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('uri' => $uri)); @@ -783,7 +783,7 @@ function file_copy(stdClass $source, $destination = NULL, $replace = FILE_EXISTS // If we are renaming around an existing file (rather than a directory), // use its basename for the filename. elseif ($replace == FILE_EXISTS_RENAME && is_file($destination)) { - $file->filename = basename($destination); + $file->filename = drupal_basename($destination); } $file = file_save($file); @@ -828,6 +828,10 @@ function file_valid_uri($uri) { * is reported. * - If file already exists in $destination either the call will error out, * replace the file or rename the file based on the $replace parameter. + * - Provides a fallback using realpaths if the move fails using stream + * wrappers. This can occur because PHP's copy() function does not properly + * support streams if safe_mode or open_basedir are enabled. See + * https://bugs.php.net/bug.php?id=60456 * * @param $source * A string specifying the filepath or URI of the source file. @@ -867,14 +871,14 @@ function file_unmanaged_copy($source, $destination = NULL, $replace = FILE_EXIST // Build a destination URI if necessary. if (!isset($destination)) { - $destination = file_build_uri(basename($source)); + $destination = file_build_uri(drupal_basename($source)); } // Prepare the destination directory. if (file_prepare_directory($destination)) { // The destination is already a directory, so append the source basename. - $destination = file_stream_wrapper_uri_normalize($destination . '/' . basename($source)); + $destination = file_stream_wrapper_uri_normalize($destination . '/' . drupal_basename($source)); } else { // Perhaps $destination is a dir/file? @@ -907,8 +911,12 @@ function file_unmanaged_copy($source, $destination = NULL, $replace = FILE_EXIST file_ensure_htaccess(); // Perform the copy operation. if (!@copy($source, $destination)) { - watchdog('file', 'The specified file %file could not be copied to %destination.', array('%file' => $source, '%destination' => $destination), WATCHDOG_ERROR); - return FALSE; + // If the copy failed and realpaths exist, retry the operation using them + // instead. + if ($real_source === FALSE || $real_destination === FALSE || !@copy($real_source, $real_destination)) { + watchdog('file', 'The specified file %file could not be copied to %destination.', array('%file' => $source, '%destination' => $destination), WATCHDOG_ERROR); + return FALSE; + } } // Set the permissions on the new file. @@ -950,7 +958,7 @@ function file_destination($destination, $replace) { break; case FILE_EXISTS_RENAME: - $basename = basename($destination); + $basename = drupal_basename($destination); $directory = drupal_dirname($destination); $destination = file_create_filename($basename, $directory); break; @@ -1025,7 +1033,7 @@ function file_move(stdClass $source, $destination = NULL, $replace = FILE_EXISTS // If we are renaming around an existing file (rather than a directory), // use its basename for the filename. elseif ($replace == FILE_EXISTS_RENAME && is_file($destination)) { - $file->filename = basename($destination); + $file->filename = drupal_basename($destination); } $file = file_save($file); @@ -1138,7 +1146,7 @@ function file_munge_filename($filename, $extensions, $alerts = TRUE) { } /** - * Undo the effect of upload_munge_filename(). + * Undo the effect of file_munge_filename(). * * @param $filename * String with the filename to be unmunged. @@ -1443,7 +1451,7 @@ function file_save_upload($source, $validators = array(), $destination = FALSE, $file = new stdClass(); $file->uid = $user->uid; $file->status = 0; - $file->filename = trim(basename($_FILES['files']['name'][$source]), '.'); + $file->filename = trim(drupal_basename($_FILES['files']['name'][$source]), '.'); $file->uri = $_FILES['files']['tmp_name'][$source]; $file->filemime = file_get_mimetype($file->filename); $file->filesize = $_FILES['files']['size'][$source]; @@ -1841,7 +1849,7 @@ function file_save_data($data, $destination = NULL, $replace = FILE_EXISTS_RENAM $file = new stdClass(); $file->fid = NULL; $file->uri = $uri; - $file->filename = basename($uri); + $file->filename = drupal_basename($uri); $file->filemime = file_get_mimetype($file->uri); $file->uid = $user->uid; $file->status = FILE_STATUS_PERMANENT; @@ -1857,7 +1865,7 @@ function file_save_data($data, $destination = NULL, $replace = FILE_EXISTS_RENAM // If we are renaming around an existing file (rather than a directory), // use its basename for the filename. elseif ($replace == FILE_EXISTS_RENAME && is_file($destination)) { - $file->filename = basename($destination); + $file->filename = drupal_basename($destination); } return file_save($file); @@ -2267,6 +2275,35 @@ function drupal_dirname($uri) { } /** + * Gets the filename from a given path. + * + * PHP's basename() does not properly support streams or filenames beginning + * with a non-US-ASCII character. + * + * @see http://bugs.php.net/bug.php?id=37738 + * @see basename() + * + * @ingroup php_wrappers + */ +function drupal_basename($uri, $suffix = NULL) { + $separators = '/'; + if (DIRECTORY_SEPARATOR != '/') { + // For Windows OS add special separator. + $separators .= DIRECTORY_SEPARATOR; + } + // Remove right-most slashes when $uri points to directory. + $uri = rtrim($uri, $separators); + // Returns the trailing part of the $uri starting after one of the directory + // separators. + $filename = preg_match('@[^' . preg_quote($separators, '@') . ']+$@', $uri, $matches) ? $matches[0] : ''; + // Cuts off a suffix from the filename. + if ($suffix) { + $filename = preg_replace('@' . preg_quote($suffix, '@') . '$@', '', $filename); + } + return $filename; +} + +/** * Creates a directory using Drupal's default mode. * * PHP's mkdir() does not respect Drupal's default permissions mode. If a mode @@ -2362,7 +2399,7 @@ function drupal_tempnam($directory, $prefix) { $wrapper = file_stream_wrapper_get_instance_by_scheme($scheme); if ($filename = tempnam($wrapper->getDirectoryPath(), $prefix)) { - return $scheme . '://' . basename($filename); + return $scheme . '://' . drupal_basename($filename); } else { return FALSE; |