Media: Keep PDF previews from overwriting files.

Since support for PDF previews were added in [38949], it's possible
that the generated image file could overwrite an existing image file
with the same name. This uses `wp_unique_filename()` to avoid this
issue and adds a '-pdf' identifier on the end of filenames.

Props gitlost, derosj, mikeschroder, joemcgill.
Fixes #39875. See #31050.

git-svn-id: https://develop.svn.wordpress.org/trunk@40130 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Joe McGill 2017-02-27 15:38:30 +00:00
parent 8e39edfdf6
commit 9848a4a466
2 changed files with 67 additions and 6 deletions

View File

@ -251,7 +251,15 @@ function wp_generate_attachment_metadata( $attachment_id, $file ) {
$editor = wp_get_image_editor( $file ); $editor = wp_get_image_editor( $file );
if ( ! is_wp_error( $editor ) ) { // No support for this type of file if ( ! is_wp_error( $editor ) ) { // No support for this type of file
$uploaded = $editor->save( $file, 'image/jpeg' ); /*
* PDFs may have the same file filename as JPEGs.
* Ensure the PDF preview image does not overwrite any JPEG images that already exist.
*/
$dirname = dirname( $file ) . '/';
$ext = '.' . pathinfo( $file, PATHINFO_EXTENSION );
$preview_file = $dirname . wp_unique_filename( $dirname, wp_basename( $file, $ext ) . '-pdf.jpg' );
$uploaded = $editor->save( $preview_file, 'image/jpeg' );
unset( $editor ); unset( $editor );
// Resize based on the full size image, rather than the source. // Resize based on the full size image, rather than the source.

View File

@ -18,6 +18,13 @@ class Tests_Image_Functions extends WP_UnitTestCase {
require_once( ABSPATH . WPINC . '/class-wp-image-editor-imagick.php' ); require_once( ABSPATH . WPINC . '/class-wp-image-editor-imagick.php' );
include_once( DIR_TESTDATA . '/../includes/mock-image-editor.php' ); include_once( DIR_TESTDATA . '/../includes/mock-image-editor.php' );
// Ensure no legacy / failed tests detritus.
$folder = '/tmp/wordpress-gsoc-flyer*.{jpg,pdf}';
foreach ( glob( $folder, GLOB_BRACE ) as $file ) {
unlink( $file );
}
} }
/** /**
@ -373,25 +380,25 @@ class Tests_Image_Functions extends WP_UnitTestCase {
$expected = array( $expected = array(
'sizes' => array( 'sizes' => array(
'thumbnail' => array( 'thumbnail' => array(
'file' => "wordpress-gsoc-flyer-116x150.jpg", 'file' => "wordpress-gsoc-flyer-pdf-116x150.jpg",
'width' => 116, 'width' => 116,
'height' => 150, 'height' => 150,
'mime-type' => "image/jpeg", 'mime-type' => "image/jpeg",
), ),
'medium' => array( 'medium' => array(
'file' => "wordpress-gsoc-flyer-232x300.jpg", 'file' => "wordpress-gsoc-flyer-pdf-232x300.jpg",
'width' => 232, 'width' => 232,
'height' => 300, 'height' => 300,
'mime-type' => "image/jpeg", 'mime-type' => "image/jpeg",
), ),
'large' => array( 'large' => array(
'file' => "wordpress-gsoc-flyer-791x1024.jpg", 'file' => "wordpress-gsoc-flyer-pdf-791x1024.jpg",
'width' => 791, 'width' => 791,
'height' => 1024, 'height' => 1024,
'mime-type' => "image/jpeg", 'mime-type' => "image/jpeg",
), ),
'full' => array( 'full' => array(
'file' => "wordpress-gsoc-flyer.jpg", 'file' => "wordpress-gsoc-flyer-pdf.jpg",
'width' => 1088, 'width' => 1088,
'height' => 1408, 'height' => 1408,
'mime-type' => "image/jpeg", 'mime-type' => "image/jpeg",
@ -403,6 +410,9 @@ class Tests_Image_Functions extends WP_UnitTestCase {
$this->assertSame( $expected, $metadata ); $this->assertSame( $expected, $metadata );
unlink( $test_file ); unlink( $test_file );
foreach ( $metadata['sizes'] as $size ) {
unlink ( '/tmp/' . $size['file'] );
}
} }
/** /**
@ -427,7 +437,7 @@ class Tests_Image_Functions extends WP_UnitTestCase {
add_filter( 'fallback_intermediate_image_sizes', array( $this, 'filter_fallback_intermediate_image_sizes' ), 10, 2 ); add_filter( 'fallback_intermediate_image_sizes', array( $this, 'filter_fallback_intermediate_image_sizes' ), 10, 2 );
$expected = array( $expected = array(
'file' => 'wordpress-gsoc-flyer-77x100.jpg', 'file' => 'wordpress-gsoc-flyer-pdf-77x100.jpg',
'width' => 77, 'width' => 77,
'height' => 100, 'height' => 100,
'mime-type' => 'image/jpeg', 'mime-type' => 'image/jpeg',
@ -441,6 +451,9 @@ class Tests_Image_Functions extends WP_UnitTestCase {
remove_filter( 'fallback_intermediate_image_sizes', array( $this, 'filter_fallback_intermediate_image_sizes' ), 10 ); remove_filter( 'fallback_intermediate_image_sizes', array( $this, 'filter_fallback_intermediate_image_sizes' ), 10 );
unlink( $test_file ); unlink( $test_file );
foreach ( $metadata['sizes'] as $size ) {
unlink ( '/tmp/' . $size['file'] );
}
} }
function filter_fallback_intermediate_image_sizes( $fallback_sizes, $metadata ) { function filter_fallback_intermediate_image_sizes( $fallback_sizes, $metadata ) {
@ -449,4 +462,44 @@ class Tests_Image_Functions extends WP_UnitTestCase {
return $fallback_sizes; return $fallback_sizes;
} }
/**
* Test PDF preview doesn't overwrite existing JPEG.
* @ticket 39875
*/
public function test_pdf_preview_doesnt_overwrite_existing_jpeg() {
// Dummy JPEGs.
$jpg1_path = '/tmp/test.jpg'; // Straight.
file_put_contents( $jpg1_path, 'asdf' );
$jpg2_path = '/tmp/test-pdf.jpg'; // With PDF marker.
file_put_contents( $jpg2_path, 'fdsa' );
// PDF with same name as JPEG.
$pdf_path = '/tmp/test.pdf';
copy( DIR_TESTDATA . '/images/wordpress-gsoc-flyer.pdf', $pdf_path );
$attachment_id = $this->factory->attachment->create_object( $pdf_path, 0, array(
'post_mime_type' => 'application/pdf',
) );
$metadata = wp_generate_attachment_metadata( $attachment_id, $pdf_path );
$preview_path = '/tmp/' . $metadata['sizes']['full']['file'];
// PDF preview didn't overwrite PDF.
$this->assertNotEquals( $pdf_path, $preview_path );
// PDF preview didn't overwrite JPG with same name.
$this->assertNotEquals( $jpg1_path, $preview_path );
$this->assertSame( 'asdf', file_get_contents( $jpg1_path ) );
// PDF preview didn't overwrite PDF preview with same name.
$this->assertNotEquals( $jpg2_path, $preview_path );
$this->assertSame( 'fdsa', file_get_contents( $jpg2_path ) );
// Cleanup.
unlink( $jpg1_path );
unlink( $jpg2_path );
unlink( $pdf_path );
foreach ( $metadata['sizes'] as $size ) {
unlink( '/tmp/' . $size['file'] );
}
}
} }