File "hostinger-auto-updates.php"
Full Path: /home/u798092620/domains/disabilitynewsafrica.org/public_html/mu-plugins/hostinger-auto-updates.php
File size: 10.8 KB
MIME-type: text/x-php
Charset: utf-8
<?php
/**
* Plugin Name: Hostinger Smart Auto Updates
* Plugin URI: https://www.hostinger.com
* Description: Faster and more secure updates for your themes, plugins, and core files. Managed entirely by Hostinger.
* Version: 1.0.8
* Author: Hostinger
* Author URI: https://www.hostinger.com
* License: GPL-2.0-or-later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain: hostinger-auto-updates
* Domain Path: /languages
* Requires at least: 5.0
* Requires PHP: 7.4
* Network: true
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
/**
* Disable automatic updates
*/
add_filter( 'automatic_updater_disabled', '__return_true' ); // Core updates
add_filter( 'auto_update_theme', '__return_false' ); // Theme updates
add_filter( 'auto_update_plugin', '__return_false' ); // Plugin updates
/**
* Endpoints used to serve package downloads and the WordPress.org API.
*/
if ( ! defined( 'HOSTINGER_LOCAL_DOWNLOAD_BASE' ) ) {
define( 'HOSTINGER_LOCAL_DOWNLOAD_BASE', 'http://127.0.0.1:7777/hsub_downloads' );
}
if ( ! defined( 'HOSTINGER_CDN_DOWNLOAD_HOST' ) ) {
define( 'HOSTINGER_CDN_DOWNLOAD_HOST', 'wpdownloads.hostinger.io' );
}
if ( ! defined( 'HOSTINGER_API_PROXY_HOST' ) ) {
define( 'HOSTINGER_API_PROXY_HOST', 'wpapi.hostinger.io' );
}
/**
* Timeout cap for the local hop, in seconds.
*/
if ( ! defined( 'HOSTINGER_LOCAL_DOWNLOAD_TIMEOUT' ) ) {
define( 'HOSTINGER_LOCAL_DOWNLOAD_TIMEOUT', 30 );
}
/**
* Anything smaller than this is an error page, not a package.
*/
if ( ! defined( 'HOSTINGER_MIN_PACKAGE_BYTES' ) ) {
define( 'HOSTINGER_MIN_PACKAGE_BYTES', 1024 );
}
/**
* Build the ordered list of endpoints to try for a downloads.wordpress.org URL.
*/
if ( ! function_exists( 'hostinger_download_tiers' ) ) {
function hostinger_download_tiers( $url ) {
$parts = wp_parse_url( $url );
$path = isset( $parts['path'] ) ? $parts['path'] : '/';
if ( ! empty( $parts['query'] ) ) {
$path .= '?' . $parts['query'];
}
$tiers = [];
if ( ! defined( 'HOSTINGER_DISABLE_LOCAL_PROXY' ) || ! HOSTINGER_DISABLE_LOCAL_PROXY ) {
$tiers['local'] = untrailingslashit( HOSTINGER_LOCAL_DOWNLOAD_BASE ) . $path;
}
$tiers['hcdn'] = str_replace( 'downloads.wordpress.org', HOSTINGER_CDN_DOWNLOAD_HOST, $url );
if ( ! defined( 'HOSTINGER_DISABLE_ORIGIN_FALLBACK' ) || ! HOSTINGER_DISABLE_ORIGIN_FALLBACK ) {
$tiers['wporg'] = $url;
}
/**
* Filter the download tiers.
*/
return apply_filters( 'hostinger_download_tiers', $tiers, $url );
}
}
/**
* Adjust request arguments for the loopback hop.
*/
if ( ! function_exists( 'hostinger_prepare_local_request_args' ) ) {
function hostinger_prepare_local_request_args( $args ) {
// download_url() goes through wp_safe_remote_get(), which sets
// reject_unsafe_urls. wp_http_validate_url() rejects 127.0.0.0/8, so the
// loopback hop would fail before a socket was ever opened. The public
// tiers keep the check.
$args['reject_unsafe_urls'] = false;
$timeout = isset( $args['timeout'] ) ? (int) $args['timeout'] : 0;
if ( $timeout <= 0 || $timeout > HOSTINGER_LOCAL_DOWNLOAD_TIMEOUT ) {
$args['timeout'] = HOSTINGER_LOCAL_DOWNLOAD_TIMEOUT;
}
if ( empty( $args['headers'] ) || is_array( $args['headers'] ) ) {
$headers = empty( $args['headers'] ) ? [] : $args['headers'];
$headers['Accept-Encoding'] = 'identity';
$args['headers'] = $headers;
}
return $args;
}
}
/**
* Whether the requested path looks like a zip archive.
*/
if ( ! function_exists( 'hostinger_url_is_zip' ) ) {
function hostinger_url_is_zip( $url ) {
$path = (string) wp_parse_url( $url, PHP_URL_PATH );
return strtolower( substr( $path, -4 ) ) === '.zip';
}
}
/**
* Read the first bytes of a file.
*/
if ( ! function_exists( 'hostinger_read_file_head' ) ) {
function hostinger_read_file_head( $file, $length ) {
$handle = @fopen( $file, 'rb' );
if ( ! $handle ) {
return '';
}
$head = (string) fread( $handle, $length );
fclose( $handle );
return $head;
}
}
/**
* Decide whether a tier actually returned a usable package.
*/
if ( ! function_exists( 'hostinger_inspect_response' ) ) {
function hostinger_inspect_response( $response, $args, $url ) {
$result = [
'ok' => false,
'code' => 0,
'reason' => '',
];
if ( is_wp_error( $response ) ) {
$result['reason'] = $response->get_error_message();
return $result;
}
$result['code'] = (int) wp_remote_retrieve_response_code( $response );
if ( $result['code'] !== 200 ) {
$result['reason'] = 'unexpected response code';
return $result;
}
if ( ! empty( $args['stream'] ) && ! empty( $args['filename'] ) && file_exists( $args['filename'] ) ) {
clearstatcache( true, $args['filename'] );
$bytes = (int) filesize( $args['filename'] );
$head = hostinger_read_file_head( $args['filename'], 2 );
} else {
$body = wp_remote_retrieve_body( $response );
$bytes = strlen( $body );
$head = substr( $body, 0, 2 );
}
if ( $bytes < HOSTINGER_MIN_PACKAGE_BYTES ) {
$result['reason'] = 'response too small to be a package';
return $result;
}
if ( hostinger_url_is_zip( $url ) && $head !== 'PK' ) {
$result['reason'] = 'response is not a zip archive';
return $result;
}
$result['ok'] = true;
return $result;
}
}
/**
* Empty the streaming target so a partial body cannot leak into the next tier.
*/
if ( ! function_exists( 'hostinger_reset_stream_target' ) ) {
function hostinger_reset_stream_target( $args ) {
if ( empty( $args['stream'] ) || empty( $args['filename'] ) || ! file_exists( $args['filename'] ) ) {
return;
}
$handle = @fopen( $args['filename'], 'w' );
if ( $handle ) {
fclose( $handle );
}
}
}
/**
* Fetch a package, walking the cache chain until one tier returns something usable.
*/
if ( ! function_exists( 'hostinger_fetch_package' ) ) {
function hostinger_fetch_package( $args, $url ) {
$response = new WP_Error( 'hostinger_no_download_tier', 'No download endpoint available.' );
$inspection = null;
foreach ( hostinger_download_tiers( $url ) as $tier => $tier_url ) {
$request_args = ( $tier === 'local' ) ? hostinger_prepare_local_request_args( $args ) : $args;
$response = wp_remote_request( $tier_url, $request_args );
$inspection = hostinger_inspect_response( $response, $args, $url );
if ( $inspection['ok'] ) {
return $response;
}
hostinger_reset_stream_target( $args );
}
if ( ! is_wp_error( $response ) && is_array( $inspection ) ) {
return new WP_Error(
'hostinger_package_download_failed',
sprintf( 'Package download failed: %s (HTTP %d).', $inspection['reason'], $inspection['code'] )
);
}
return $response;
}
}
/**
* Send WordPress.org API traffic through Hostinger's proxy.
*/
if ( ! function_exists( 'hostinger_fetch_api' ) ) {
function hostinger_fetch_api( $args, $url ) {
$proxy_url = str_replace( 'api.wordpress.org', HOSTINGER_API_PROXY_HOST, $url );
return wp_remote_request( $proxy_url, $args );
}
}
/**
* Use Hostinger's cache chain for WordPress.org API and download requests.
*/
if ( ! function_exists( 'hostinger_use_proxy_services' ) ) {
function hostinger_use_proxy_services( $response_override, $args, $url ) {
static $in_flight = false;
if ( $in_flight ) {
return $response_override;
}
$host = strtolower( (string) wp_parse_url( $url, PHP_URL_HOST ) );
if ( $host !== 'downloads.wordpress.org' && $host !== 'api.wordpress.org' ) {
return $response_override;
}
$in_flight = true;
try {
if ( $host === 'downloads.wordpress.org' ) {
return hostinger_fetch_package( $args, $url );
}
return hostinger_fetch_api( $args, $url );
} finally {
$in_flight = false;
}
}
}
add_filter( 'pre_http_request', 'hostinger_use_proxy_services', 10, 3 );
/**
* Keep loopback requests off a configured HTTP proxy.
*/
if ( ! function_exists( 'hostinger_bypass_proxy_for_local_cache' ) ) {
function hostinger_bypass_proxy_for_local_cache( $send, $uri, $check, $home ) {
// WP_HTTP_Proxy exempts 'localhost' and the site host, but not 127.0.0.1,
// so on a server with WP_PROXY_HOST set the local cache hop would be sent
// to the proxy.
$local_host = wp_parse_url( HOSTINGER_LOCAL_DOWNLOAD_BASE, PHP_URL_HOST );
if ( ! empty( $check['host'] ) && ! empty( $local_host ) && $check['host'] === $local_host ) {
return false;
}
return $send;
}
}
add_filter( 'pre_http_send_through_proxy', 'hostinger_bypass_proxy_for_local_cache', 10, 4 );
/**
* Modify the default auto-update tests.
*/
if ( ! function_exists( 'hostinger_change_default_autoupdates_test' ) ) {
function hostinger_change_default_autoupdates_test( $tests ) {
// Remove default auto-update tests
unset( $tests['async']['background_updates'] );
unset( $tests['direct']['plugin_theme_auto_updates'] );
// Add a new test to indicate Hostinger manages updates
$tests['direct']['hostinger_plugin_theme_auto_updates'] = [
'label' => __( 'Auto-updates managed by Hostinger' ),
'test' => function () {
$result = [
'label' => __( 'Automatic updates managed by Hostinger' ),
'status' => 'good',
'badge' => [
'label' => __( 'Security' ),
'color' => 'blue',
],
'description' => __( 'Automatic updates ensure your site is always running the latest and most secure versions of WordPress, plugins, and themes.' ),
'actions' => '',
'test' => 'hostinger_managed_updates',
];
return $result;
},
];
return $tests;
}
}
add_filter( 'site_status_tests', 'hostinger_change_default_autoupdates_test' );