Skip to content

Commit 8f1faaa

Browse files
committed
Detect file extension from downloaded archives
1 parent 738c6d2 commit 8f1faaa

2 files changed

Lines changed: 71 additions & 3 deletions

File tree

features/core-download.feature

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,3 +556,40 @@ Feature: Download WordPress
556556
Success:
557557
"""
558558

559+
Scenario: Extracts provided tar.gz files
560+
Given an empty directory
561+
562+
When I run `wp core download https://downloads.wordpress.org/release/wordpress-7.0.tar.gz --force`
563+
Then the {RUN_DIR} directory should contain:
564+
"""
565+
index.php
566+
license.txt
567+
"""
568+
569+
Scenario: Extracts provided zip files
570+
Given an empty directory
571+
572+
When I run `wp core download https://downloads.wordpress.org/release/wordpress-7.0.zip --force`
573+
Then the {RUN_DIR} directory should contain:
574+
"""
575+
index.php
576+
license.txt
577+
"""
578+
579+
Scenario: Error when downloading an unsupported archive format
580+
Given an empty directory
581+
And that HTTP requests to http://example.com/unsupported.txt will respond with:
582+
"""
583+
HTTP/1.1 200 OK
584+
Content-Type: text/plain
585+
586+
This is not a zip or tarball file.
587+
"""
588+
589+
When I try `wp core download http://example.com/unsupported.txt --force`
590+
Then STDERR should contain:
591+
"""
592+
Error: Unsupported archive format. The downloaded file is not a valid zip or tar.gz archive.
593+
"""
594+
And the return code should be 1
595+

src/Core_Command.php

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -297,11 +297,11 @@ public function download( $args, $assoc_args ) {
297297
}
298298

299299
if ( ! $cache_file || $bad_cache ) {
300-
$temp = Utils\get_temp_dir() . uniqid( 'wp_' ) . ".{$extension}";
300+
$temp = Utils\get_temp_dir() . uniqid( 'wp_' ) . '.tmp';
301301
register_shutdown_function(
302-
function () use ( $temp ) {
302+
function () use ( &$temp ) {
303303
if ( file_exists( $temp ) ) {
304-
unlink( $temp );
304+
@unlink( $temp );
305305
}
306306
}
307307
);
@@ -322,6 +322,37 @@ function () use ( $temp ) {
322322
WP_CLI::error( "Couldn't access download URL (HTTP code {$response->status_code})." );
323323
}
324324

325+
$extension = '';
326+
if ( file_exists( $temp ) ) {
327+
$mime = function_exists( 'mime_content_type' ) ? mime_content_type( $temp ) : '';
328+
if ( 'application/zip' === $mime || 'application/x-zip-compressed' === $mime ) {
329+
$extension = 'zip';
330+
} elseif ( 'application/x-gzip' === $mime || 'application/gzip' === $mime ) {
331+
$extension = 'tar.gz';
332+
} else {
333+
// Fallback to magic bytes.
334+
$handle = @fopen( $temp, 'rb' );
335+
if ( $handle ) {
336+
$bytes = fread( $handle, 2 );
337+
fclose( $handle );
338+
if ( 'PK' === $bytes ) {
339+
$extension = 'zip';
340+
} elseif ( "\x1f\x8b" === $bytes ) {
341+
$extension = 'tar.gz';
342+
}
343+
}
344+
}
345+
}
346+
347+
if ( ! in_array( $extension, [ 'zip', 'tar.gz' ], true ) ) {
348+
WP_CLI::error( 'Unsupported archive format. The downloaded file is not a valid zip or tar.gz archive.' );
349+
}
350+
351+
$actual_temp = substr( $temp, 0, -4 ) . ".{$extension}";
352+
if ( rename( $temp, $actual_temp ) ) {
353+
$temp = $actual_temp;
354+
}
355+
325356
if ( 'nightly' !== $version ) {
326357
unset( $options['filename'] );
327358
/** @var \WpOrg\Requests\Response $md5_response */

0 commit comments

Comments
 (0)