From 842d6a9b3984e802d0759e85f82890f3ff0350b1 Mon Sep 17 00:00:00 2001 From: Dion Hulse Date: Tue, 31 Mar 2015 02:10:06 +0000 Subject: [PATCH] Add some logic into `wp_tempnam` to prevent it creating 'falsey' directory names that might get used elsewhere within WordPress. Although this logic looks a little strange at this low level, it's the best location within the Upgrades code for it to happen. Fixes #31811 git-svn-id: https://develop.svn.wordpress.org/trunk@31936 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-admin/includes/file.php | 34 ++++++++++++++++++++++++---------- tests/phpunit/tests/file.php | 20 ++++++++++++++++++++ 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/src/wp-admin/includes/file.php b/src/wp-admin/includes/file.php index 513b417487..622a86961d 100644 --- a/src/wp-admin/includes/file.php +++ b/src/wp-admin/includes/file.php @@ -141,17 +141,29 @@ function list_files( $folder = '', $levels = 100 ) { * @param string $dir Optional. Directory to store the file in. Default empty. * @return string a writable filename */ -function wp_tempnam($filename = '', $dir = '') { - if ( empty($dir) ) +function wp_tempnam( $filename = '', $dir = '' ) { + if ( empty( $dir ) ) { $dir = get_temp_dir(); - $filename = basename($filename); - if ( empty($filename) ) - $filename = time(); + } - $filename = preg_replace('|\..*$|', '.tmp', $filename); - $filename = $dir . wp_unique_filename($dir, $filename); - touch($filename); - return $filename; + if ( empty( $filename ) || '.' == $filename ) { + $filename = time(); + } + + // Use the basename of the given file without the extension as the name for the temporary directory + $temp_filename = basename( $filename ); + $temp_filename = preg_replace( '|\.[^.]*$|', '', $temp_filename ); + + // If the folder is falsey, use it's parent directory name instead + if ( ! $temp_filename ) { + return wp_tempnam( dirname( $filename ), $dir ); + } + + $temp_filename .= '.tmp'; + $temp_filename = $dir . wp_unique_filename( $dir, $temp_filename ); + touch( $temp_filename ); + + return $temp_filename; } /** @@ -627,8 +639,10 @@ function _unzip_file_ziparchive($file, $to, $needed_dirs = array() ) { // Create those directories if need be: foreach ( $needed_dirs as $_dir ) { - if ( ! $wp_filesystem->mkdir($_dir, FS_CHMOD_DIR) && ! $wp_filesystem->is_dir($_dir) ) // Only check to see if the Dir exists upon creation failure. Less I/O this way. + // Only check to see if the Dir exists upon creation failure. Less I/O this way. + if ( ! $wp_filesystem->mkdir( $_dir, FS_CHMOD_DIR ) && ! $wp_filesystem->is_dir( $_dir ) ) { return new WP_Error( 'mkdir_failed_ziparchive', __( 'Could not create directory.' ), substr( $_dir, strlen( $to ) ) ); + } } unset($needed_dirs); diff --git a/tests/phpunit/tests/file.php b/tests/phpunit/tests/file.php index 3c2fd8886d..a633970053 100644 --- a/tests/phpunit/tests/file.php +++ b/tests/phpunit/tests/file.php @@ -152,4 +152,24 @@ class Tests_File extends WP_UnitTestCase { unlink($this->dir . DIRECTORY_SEPARATOR . $filename); } + /** + * @dataProvider data_wp_tempnam_filenames + */ + function test_wp_tempnam( $case ) { + $file = wp_tempnam( $case ); + unlink( $file ); + + $this->assertNotEmpty( basename( basename( $file, '.tmp' ), '.zip' ) ); + } + function data_wp_tempnam_filenames() { + return array( + array( '0.zip' ), + array( '0.1.2.3.zip' ), + array( 'filename.zip' ), + array( 'directory/0.zip' ), + array( 'directory/filename.zip' ), + array( 'directory/0/0.zip' ), + ); + } + }