Skip to content

Commit cc32c8a

Browse files
authored
Merge pull request #186 from wp-cli/fix/disable-http-request-retry-by-default
2 parents 12bcc24 + c1b1187 commit cc32c8a

File tree

2 files changed

+64
-44
lines changed

2 files changed

+64
-44
lines changed

src/Core_Command.php

Lines changed: 46 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use WP_CLI\Iterators\Table as TableIterator;
66
use WP_CLI\Utils;
77
use WP_CLI\Formatter;
8+
use WP_CLI\WpOrgApi;
89

910
/**
1011
* Downloads, installs, updates, and manages a WordPress installation.
@@ -116,6 +117,9 @@ public function check_update( $_, $assoc_args ) {
116117
* [--force]
117118
* : Overwrites existing files, if present.
118119
*
120+
* [--insecure]
121+
* : Retry download without certificate validation if TLS handshake fails. Note: This makes the request vulnerable to a MITM attack.
122+
*
119123
* ## EXAMPLES
120124
*
121125
* $ wp core download --locale=nl_NL
@@ -153,8 +157,9 @@ public function download( $args, $assoc_args ) {
153157
WP_CLI::error( "'{$download_dir}' is not writable by current user." );
154158
}
155159

156-
$locale = Utils\get_flag_value( $assoc_args, 'locale', 'en_US' );
157-
$skip_content = Utils\get_flag_value( $assoc_args, 'skip-content' );
160+
$locale = (string) Utils\get_flag_value( $assoc_args, 'locale', 'en_US' );
161+
$skip_content = (bool) Utils\get_flag_value( $assoc_args, 'skip-content', false );
162+
$insecure = (bool) Utils\get_flag_value( $assoc_args, 'insecure', false );
158163

159164
$download_url = array_shift( $args );
160165
$from_url = ! empty( $download_url );
@@ -180,12 +185,17 @@ public function download( $args, $assoc_args ) {
180185

181186
$download_url = $this->get_download_url( $version, $locale, $extension );
182187
} else {
183-
$offer = $this->get_download_offer( $locale );
188+
try {
189+
$offer = ( new WpOrgApi( [ 'insecure' => $insecure ] ) )
190+
->get_core_download_offer( $locale );
191+
} catch ( Exception $exception ) {
192+
WP_CLI::error( $exception );
193+
}
184194
if ( ! $offer ) {
185195
WP_CLI::error( "The requested locale ({$locale}) was not found." );
186196
}
187-
$version = $offer->current;
188-
$download_url = $offer->download;
197+
$version = $offer['current'];
198+
$download_url = $offer['download'];
189199
if ( ! $skip_content ) {
190200
$download_url = str_replace( '.zip', '.tar.gz', $download_url );
191201
}
@@ -256,6 +266,7 @@ function () use ( $temp ) {
256266
$options = [
257267
'timeout' => 600, // 10 minutes ought to be enough for everybody
258268
'filename' => $temp,
269+
'insecure' => $insecure,
259270
];
260271

261272
$response = Utils\http_request( 'GET', $download_url, null, $headers, $options );
@@ -267,7 +278,8 @@ function () use ( $temp ) {
267278
}
268279

269280
if ( 'nightly' !== $version ) {
270-
$md5_response = Utils\http_request( 'GET', $download_url . '.md5' );
281+
unset( $options['filename'] );
282+
$md5_response = Utils\http_request( 'GET', $download_url . '.md5', null, [], $options );
271283
if ( $md5_response->status_code >= 200 && $md5_response->status_code < 300 ) {
272284
$md5_file = md5_file( $temp );
273285

@@ -299,37 +311,12 @@ function () use ( $temp ) {
299311
}
300312

301313
if ( $wordpress_present ) {
302-
$this->cleanup_extra_files( $from_version, $version, $locale );
314+
$this->cleanup_extra_files( $from_version, $version, $locale, $insecure );
303315
}
304316

305317
WP_CLI::success( 'WordPress downloaded.' );
306318
}
307319

308-
private static function read( $url ) {
309-
$headers = [ 'Accept' => 'application/json' ];
310-
$response = Utils\http_request( 'GET', $url, null, $headers, [ 'timeout' => 30 ] );
311-
if ( 200 === $response->status_code ) {
312-
return $response->body;
313-
} else {
314-
WP_CLI::error( "Couldn't fetch response from {$url} (HTTP code {$response->status_code})." );
315-
}
316-
}
317-
318-
private function get_download_offer( $locale ) {
319-
$out = self::read( 'https://api.wordpress.org/core/version-check/1.7/?locale=' . $locale );
320-
$out = function_exists( 'wp_json_decode' )
321-
? wp_json_decode( $out )
322-
: json_decode( $out );
323-
324-
$offer = $out->offers[0];
325-
326-
if ( $offer->locale !== $locale ) {
327-
return false;
328-
}
329-
330-
return $offer;
331-
}
332-
333320
/**
334321
* Checks if WordPress is installed.
335322
*
@@ -952,16 +939,20 @@ private static function find_var( $var_name, $code ) {
952939
/**
953940
* Security copy of the core function with Requests - Gets the checksums for the given version of WordPress.
954941
*
955-
* @param string $version Version string to query.
956-
* @param string $locale Locale to query.
942+
* @param string $version Version string to query.
943+
* @param string $locale Locale to query.
944+
* @param bool $insecure Whether to retry without certificate validation on TLS handshake failure.
957945
* @return string|array String message on failure. An array of checksums on success.
958946
*/
959-
private static function get_core_checksums( $version, $locale ) {
947+
private static function get_core_checksums( $version, $locale, $insecure ) {
960948
$query = http_build_query( compact( 'version', 'locale' ), null, '&' );
961949
$url = "https://api.wordpress.org/core/checksums/1.0/?{$query}";
962950

963-
$options = [ 'timeout' => 30 ];
964951
$headers = [ 'Accept' => 'application/json' ];
952+
$options = [
953+
'timeout' => 30,
954+
'insecure' => $insecure,
955+
];
965956

966957
$response = Utils\http_request( 'GET', $url, null, $headers, $options );
967958

@@ -1007,6 +998,9 @@ private static function get_core_checksums( $version, $locale ) {
1007998
* [--locale=<locale>]
1008999
* : Select which language you want to download.
10091000
*
1001+
* [--insecure]
1002+
* : Retry download without certificate validation if TLS handshake fails. Note: This makes the request vulnerable to a MITM attack.
1003+
*
10101004
* ## EXAMPLES
10111005
*
10121006
* # Update WordPress
@@ -1043,7 +1037,6 @@ public function update( $args, $assoc_args ) {
10431037
global $wp_version;
10441038

10451039
$update = null;
1046-
$from_api = null;
10471040
$upgrader = 'WP_CLI\\Core\\CoreUpgrader';
10481041

10491042
if ( 'trunk' === Utils\get_flag_value( $assoc_args, 'version' ) ) {
@@ -1094,7 +1087,7 @@ public function update( $args, $assoc_args ) {
10941087
list( $update ) = $from_api->updates;
10951088
}
10961089
}
1097-
} elseif ( \WP_CLI\Utils\wp_version_compare( $assoc_args['version'], '<' )
1090+
} elseif ( Utils\wp_version_compare( $assoc_args['version'], '<' )
10981091
|| 'nightly' === $assoc_args['version']
10991092
|| Utils\get_flag_value( $assoc_args, 'force' ) ) {
11001093

@@ -1133,9 +1126,10 @@ public function update( $args, $assoc_args ) {
11331126
}
11341127

11351128
$from_version = $wp_version;
1129+
$insecure = (bool) Utils\get_flag_value( $assoc_args, 'insecure', false );
11361130

11371131
$GLOBALS['wpcli_core_update_obj'] = $update;
1138-
$result = Utils\get_upgrader( $upgrader )->upgrade( $update );
1132+
$result = Utils\get_upgrader( $upgrader, $insecure )->upgrade( $update );
11391133
unset( $GLOBALS['wpcli_core_update_obj'] );
11401134

11411135
if ( is_wp_error( $result ) ) {
@@ -1153,8 +1147,8 @@ public function update( $args, $assoc_args ) {
11531147
$to_version = $wp_details['wp_version'];
11541148
}
11551149

1156-
$locale = Utils\get_flag_value( $assoc_args, 'locale', get_locale() );
1157-
$this->cleanup_extra_files( $from_version, $to_version, $locale );
1150+
$locale = (string) Utils\get_flag_value( $assoc_args, 'locale', get_locale() );
1151+
$this->cleanup_extra_files( $from_version, $to_version, $locale, $insecure );
11581152

11591153
WP_CLI::success( 'WordPress updated successfully.' );
11601154
}
@@ -1347,18 +1341,26 @@ private function get_updates( $assoc_args ) {
13471341
return array_values( $updates );
13481342
}
13491343

1350-
private function cleanup_extra_files( $version_from, $version_to, $locale ) {
1344+
/**
1345+
* Clean up extra files.
1346+
*
1347+
* @param string $version_from Starting version that the installation was updated from.
1348+
* @param string $version_to Target version that the installation is updated to.
1349+
* @param string $locale Locale of the installation.
1350+
* @param bool $insecure Whether to retry without certificate validation on TLS handshake failure.
1351+
*/
1352+
private function cleanup_extra_files( $version_from, $version_to, $locale, $insecure ) {
13511353
if ( ! $version_from || ! $version_to ) {
13521354
WP_CLI::warning( 'Failed to find WordPress version. Please cleanup files manually.' );
13531355
return;
13541356
}
13551357

1356-
$old_checksums = self::get_core_checksums( $version_from, $locale ?: 'en_US' );
1358+
$old_checksums = self::get_core_checksums( $version_from, $locale ?: 'en_US', $insecure );
13571359
if ( ! is_array( $old_checksums ) ) {
13581360
WP_CLI::warning( "{$old_checksums} Please cleanup files manually." );
13591361
return;
13601362
}
1361-
$new_checksums = self::get_core_checksums( $version_to, $locale ?: 'en_US' );
1363+
$new_checksums = self::get_core_checksums( $version_to, $locale ?: 'en_US', $insecure );
13621364
if ( ! is_array( $new_checksums ) ) {
13631365
WP_CLI::warning( "{$new_checksums} Please cleanup files manually." );
13641366
return;

src/WP_CLI/Core/CoreUpgrader.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,23 @@
1717
*/
1818
class CoreUpgrader extends DefaultCoreUpgrader {
1919

20+
/**
21+
* Whether to retry without certificate validation on TLS handshake failure.
22+
*
23+
* @var bool
24+
*/
25+
private $insecure;
26+
27+
/**
28+
* CoreUpgrader constructor.
29+
*
30+
* @param WP_Upgrader_Skin|null $skin
31+
*/
32+
public function __construct( $skin = null, $insecure = false ) {
33+
$this->insecure = $insecure;
34+
parent::__construct( $skin );
35+
}
36+
2037
/**
2138
* Caches the download, and uses cached if available.
2239
*
@@ -93,6 +110,7 @@ function () use ( $temp ) {
93110
'timeout' => 600, // 10 minutes ought to be enough for everybody.
94111
'filename' => $temp,
95112
'halt_on_error' => false,
113+
'insecure' => $this->insecure,
96114
];
97115

98116
$this->skin->feedback( 'downloading_package', $package );

0 commit comments

Comments
 (0)