fix: GitHub updater requests never follow redirects, whatever other plugins set
HTTP Requests Manager (blocking modes) sets every request's redirection to 1 on http_request_args. The updater's no-redirect requests then followed GitHub's redirect: signed_address() lost the Location, so private updates failed (and the token went to the download host), and fetch_web()'s HEAD on releases/latest got 200 instead of a redirect. remote_no_redirect() holds redirection at 0 for that one URL at PHP_INT_MAX. Updater copy 1.0.1 (the GH#261 change had not raised it).
This commit is contained in:
1 parent
a04e1d63b3
commit
51ccabc24e
3 files changed
+37
-10
No files matched your search
@@ -2,6 +2,10 @@
|
||||
|
||||
Every change to WP Plugin Starter. readme.txt lists the latest version in short.
|
||||
|
||||
= Unreleased =
|
||||
* Fix: the shared GitHub updater (copy 1.0.1) could not update from private repositories on sites where another plugin raises every request's redirection count (HTTP Requests Manager in a blocking mode sets it to 1): GitHub's redirect was followed, so the signed download address was lost and the token went along to the download host. Its requests to GitHub now never follow redirects, whatever other plugins set. Public repositories' release checks had the same problem.
|
||||
* Fix: the shared GitHub updater's private downloads survive updaters that reset upgrader_pre_download (GPLVault Updater).
|
||||
|
||||
= 1.0.0 =
|
||||
* A fresh start, made from the parts every wpallstars plugin needs, taken from plugins in daily use: the settings screen with search, the Read Me tab, features as classes, replaced plugins, the shared GitHub updater, the release and check scripts, CI and the shared rules (STANDARDS.md, DEVELOPMENT.md, RELEASING.md). Earlier versions of this starter are retired; start again from this one.
|
||||
* New: scripts/rename-plugin.sh gives a copy of the starter its own names, and scripts/sync-core.sh keeps a plugin's core files the same as the starter's.
|
||||
@@ -212,13 +212,40 @@ final class WPAllStars_GitHub_Updater {
|
||||
$headers['Authorization'] = 'Bearer ' . $token;
|
||||
}
|
||||
// No redirects: the token must never travel to another address.
|
||||
return wp_safe_remote_get('https://api.github.com/repos/' . $repo . $path, array(
|
||||
return self::remote_no_redirect('GET', 'https://api.github.com/repos/' . $repo . $path, array(
|
||||
'timeout' => 10,
|
||||
'redirection' => 0,
|
||||
'headers' => $headers,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* A request that never follows a redirect, so the answer's Location can
|
||||
* be read and a token never travels to another address.
|
||||
*
|
||||
* Some plugins raise every request's redirection count (HTTP Requests
|
||||
* Manager sets it to 1), which would follow GitHub's redirect: the token
|
||||
* would go along and the Location would be lost. Only this request is
|
||||
* held at 0, after every other filter.
|
||||
*
|
||||
* @param string $method GET or HEAD.
|
||||
* @param string $url Address.
|
||||
* @param array $args Request arguments.
|
||||
* @return array|WP_Error
|
||||
*/
|
||||
private static function remote_no_redirect($method, $url, array $args) {
|
||||
$args['redirection'] = 0;
|
||||
$hold = function ($parsed_args, $request_url) use ($url) {
|
||||
if ($request_url === $url && is_array($parsed_args)) {
|
||||
$parsed_args['redirection'] = 0;
|
||||
}
|
||||
return $parsed_args;
|
||||
};
|
||||
add_filter('http_request_args', $hold, PHP_INT_MAX, 2);
|
||||
$response = 'HEAD' === $method ? wp_safe_remote_head($url, $args) : wp_safe_remote_get($url, $args);
|
||||
remove_filter('http_request_args', $hold, PHP_INT_MAX);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stored release answers.
|
||||
*
|
||||
@@ -316,10 +343,7 @@ final class WPAllStars_GitHub_Updater {
|
||||
*/
|
||||
private static function fetch_web($repo, $folder, $main) {
|
||||
// Redirects to the newest release that is not a draft or pre-release.
|
||||
$response = wp_safe_remote_head('https://github.com/' . $repo . '/releases/latest', array(
|
||||
'timeout' => 10,
|
||||
'redirection' => 0,
|
||||
));
|
||||
$response = self::remote_no_redirect('HEAD', 'https://github.com/' . $repo . '/releases/latest', array('timeout' => 10));
|
||||
if (is_wp_error($response)) {
|
||||
return $response;
|
||||
}
|
||||
@@ -346,7 +370,7 @@ final class WPAllStars_GitHub_Updater {
|
||||
// The release zip, by its usual name: {folder}-{version}.zip.
|
||||
$asset = null;
|
||||
$download = 'https://github.com/' . $repo . '/releases/download/' . rawurlencode($tag) . '/' . rawurlencode($folder . '-' . $version . '.zip');
|
||||
$head = wp_safe_remote_head($download, array('timeout' => 10, 'redirection' => 0));
|
||||
$head = self::remote_no_redirect('HEAD', $download, array('timeout' => 10));
|
||||
if (is_wp_error($head)) {
|
||||
return $head;
|
||||
}
|
||||
@@ -747,9 +771,8 @@ final class WPAllStars_GitHub_Updater {
|
||||
return null;
|
||||
}
|
||||
|
||||
$response = wp_safe_remote_get($package, array(
|
||||
$response = self::remote_no_redirect('GET', $package, array(
|
||||
'timeout' => 30,
|
||||
'redirection' => 0,
|
||||
'headers' => array(
|
||||
'Accept' => false !== strpos($package, '/releases/assets/') ? 'application/octet-stream' : 'application/vnd.github+json',
|
||||
'Authorization' => 'Bearer ' . $token,
|
||||
|
||||
@@ -27,7 +27,7 @@ if (!isset($GLOBALS['wpallstars_github_updater']) || !is_array($GLOBALS['wpallst
|
||||
$GLOBALS['wpallstars_github_updater'] = array();
|
||||
}
|
||||
// Version of this copy => its class file.
|
||||
$GLOBALS['wpallstars_github_updater']['1.0.0'] = __DIR__ . '/class-wpallstars-github-updater.php';
|
||||
$GLOBALS['wpallstars_github_updater']['1.0.1'] = __DIR__ . '/class-wpallstars-github-updater.php';
|
||||
|
||||
if (!function_exists('wpallstars_github_updater_load')) {
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user