Edit File by line
/home/barbar84/www/wp-conte.../plugins/updraftp...
File: class-updraftplus.php
<?php
[0] Fix | Delete
[1] Fix | Delete
if (!defined('UPDRAFTPLUS_DIR')) die('No direct access allowed');
[2] Fix | Delete
[3] Fix | Delete
class UpdraftPlus {
[4] Fix | Delete
[5] Fix | Delete
public $version;
[6] Fix | Delete
[7] Fix | Delete
public $plugin_title = 'UpdraftPlus Backup/Restore';
[8] Fix | Delete
[9] Fix | Delete
// Choices will be shown in the admin menu in the order used here
[10] Fix | Delete
public $backup_methods = array(
[11] Fix | Delete
'updraftvault' => 'UpdraftPlus Vault',
[12] Fix | Delete
'dropbox' => 'Dropbox',
[13] Fix | Delete
's3' => 'Amazon S3',
[14] Fix | Delete
'cloudfiles' => 'Rackspace Cloud Files',
[15] Fix | Delete
'googledrive' => 'Google Drive',
[16] Fix | Delete
'onedrive' => 'Microsoft OneDrive',
[17] Fix | Delete
'ftp' => 'FTP',
[18] Fix | Delete
'azure' => 'Microsoft Azure',
[19] Fix | Delete
'sftp' => 'SFTP / SCP',
[20] Fix | Delete
'googlecloud' => 'Google Cloud',
[21] Fix | Delete
'backblaze' => 'Backblaze',
[22] Fix | Delete
'webdav' => 'WebDAV',
[23] Fix | Delete
's3generic' => 'S3-Compatible (Generic)',
[24] Fix | Delete
'openstack' => 'OpenStack (Swift)',
[25] Fix | Delete
'dreamobjects' => 'DreamObjects',
[26] Fix | Delete
'email' => 'Email'
[27] Fix | Delete
);
[28] Fix | Delete
[29] Fix | Delete
public $errors = array();
[30] Fix | Delete
[31] Fix | Delete
public $nonce;
[32] Fix | Delete
[33] Fix | Delete
public $file_nonce;
[34] Fix | Delete
[35] Fix | Delete
public $logfile_name = "";
[36] Fix | Delete
[37] Fix | Delete
public $logfile_handle = false;
[38] Fix | Delete
[39] Fix | Delete
public $backup_time;
[40] Fix | Delete
[41] Fix | Delete
public $job_time_ms;
[42] Fix | Delete
[43] Fix | Delete
public $opened_log_time;
[44] Fix | Delete
[45] Fix | Delete
private $backup_dir;
[46] Fix | Delete
[47] Fix | Delete
private $jobdata;
[48] Fix | Delete
[49] Fix | Delete
public $something_useful_happened = false;
[50] Fix | Delete
[51] Fix | Delete
public $have_addons = false;
[52] Fix | Delete
[53] Fix | Delete
// Used to schedule resumption attempts beyond the tenth, if needed
[54] Fix | Delete
public $current_resumption;
[55] Fix | Delete
[56] Fix | Delete
public $newresumption_scheduled = false;
[57] Fix | Delete
[58] Fix | Delete
public $resumption_scheduled_for_cleanup = false;
[59] Fix | Delete
[60] Fix | Delete
public $cpanel_quota_readable = false;
[61] Fix | Delete
[62] Fix | Delete
public $error_reporting_stop_when_logged = false;
[63] Fix | Delete
[64] Fix | Delete
private $combine_jobs_around;
[65] Fix | Delete
[66] Fix | Delete
// Used for reporting
[67] Fix | Delete
private $attachments;
[68] Fix | Delete
[69] Fix | Delete
private $remotestorage_extrainfo = array();
[70] Fix | Delete
[71] Fix | Delete
public $no_checkin_last_time;
[72] Fix | Delete
[73] Fix | Delete
/**
[74] Fix | Delete
* Class constructor
[75] Fix | Delete
*/
[76] Fix | Delete
public function __construct() {
[77] Fix | Delete
global $pagenow;
[78] Fix | Delete
// Initialisation actions - takes place on plugin load
[79] Fix | Delete
[80] Fix | Delete
if ($fp = fopen(UPDRAFTPLUS_DIR.'/updraftplus.php', 'r')) {
[81] Fix | Delete
$file_data = fread($fp, 1024);
[82] Fix | Delete
if (preg_match("/Version: ([\d\.]+)(\r|\n)/", $file_data, $matches)) {
[83] Fix | Delete
$this->version = $matches[1];
[84] Fix | Delete
}
[85] Fix | Delete
fclose($fp);
[86] Fix | Delete
}
[87] Fix | Delete
[88] Fix | Delete
$load_classes = array(
[89] Fix | Delete
'UpdraftPlus_Backup_History' => 'includes/class-backup-history.php',
[90] Fix | Delete
'UpdraftPlus_Encryption' => 'includes/class-updraftplus-encryption.php',
[91] Fix | Delete
'UpdraftPlus_Manipulation_Functions' => 'includes/class-manipulation-functions.php',
[92] Fix | Delete
'UpdraftPlus_Filesystem_Functions' => 'includes/class-filesystem-functions.php',
[93] Fix | Delete
'UpdraftPlus_Storage_Methods_Interface' => 'includes/class-storage-methods-interface.php',
[94] Fix | Delete
'UpdraftPlus_Job_Scheduler' => 'includes/class-job-scheduler.php',
[95] Fix | Delete
);
[96] Fix | Delete
[97] Fix | Delete
foreach ($load_classes as $class => $relative_path) {
[98] Fix | Delete
if (!class_exists($class)) include_once(UPDRAFTPLUS_DIR.'/'.$relative_path);
[99] Fix | Delete
}
[100] Fix | Delete
[101] Fix | Delete
// Create admin page
[102] Fix | Delete
add_action('init', array($this, 'handle_url_actions'));
[103] Fix | Delete
add_action('init', array($this, 'updraftplus_single_site_maintenance_init'));
[104] Fix | Delete
// Run earlier than default - hence earlier than other components
[105] Fix | Delete
// admin_menu runs earlier, and we need it because options.php wants to use $updraftplus_admin before admin_init happens
[106] Fix | Delete
add_action(apply_filters('updraft_admin_menu_hook', 'admin_menu'), array($this, 'admin_menu'), 9);
[107] Fix | Delete
// Not a mistake: admin-ajax.php calls only admin_init and not admin_menu
[108] Fix | Delete
add_action('admin_init', array($this, 'admin_menu'), 9);
[109] Fix | Delete
add_action('admin_init', array($this, 'wordpress_55_updates_potential_migration'));
[110] Fix | Delete
[111] Fix | Delete
// The two actions which we schedule upon
[112] Fix | Delete
add_action('updraft_backup', array($this, 'backup_files'));
[113] Fix | Delete
add_action('updraft_backup_database', array($this, 'backup_database'));
[114] Fix | Delete
[115] Fix | Delete
// The three actions that can be called from "Backup Now"
[116] Fix | Delete
add_action('updraft_backupnow_backup', array($this, 'backupnow_files'));
[117] Fix | Delete
add_action('updraft_backupnow_backup_database', array($this, 'backupnow_database'));
[118] Fix | Delete
add_action('updraft_backupnow_backup_all', array($this, 'backup_all'));
[119] Fix | Delete
[120] Fix | Delete
// backup_all as an action is legacy (Oct 2013) - there may be some people who wrote cron scripts to use it
[121] Fix | Delete
add_action('updraft_backup_all', array($this, 'backup_all'));
[122] Fix | Delete
[123] Fix | Delete
// This is our runs-after-backup event, whose purpose is to see if it succeeded or failed, and resume/mom-up etc.
[124] Fix | Delete
add_action('updraft_backup_resume', array($this, 'backup_resume'), 10, 3);
[125] Fix | Delete
[126] Fix | Delete
// If files + db are on different schedules but are scheduled for the same time, then combine them
[127] Fix | Delete
add_filter('schedule_event', array($this, 'schedule_event'));
[128] Fix | Delete
[129] Fix | Delete
add_action('plugins_loaded', array($this, 'plugins_loaded'));
[130] Fix | Delete
[131] Fix | Delete
// Since the WordPress version 5.5, we are no longer forcing an auto update by hooking the auto_update_plugin filter because WordPress does something different to its auto-update interface
[132] Fix | Delete
if (version_compare($this->get_wordpress_version(), '5.5', '<')) {
[133] Fix | Delete
// Auto update plugin
[134] Fix | Delete
add_filter('auto_update_plugin', array($this, 'maybe_auto_update_plugin'), 20, 2);
[135] Fix | Delete
}
[136] Fix | Delete
[137] Fix | Delete
// Prevent iThemes Security from telling people that they have no backups (and advertising them another product on that basis!)
[138] Fix | Delete
add_filter('itsec_has_external_backup', '__return_true', 999);
[139] Fix | Delete
add_filter('itsec_external_backup_link', array($this, 'itsec_external_backup_link'), 999);
[140] Fix | Delete
add_filter('itsec_scheduled_external_backup', array($this, 'itsec_scheduled_external_backup'), 999);
[141] Fix | Delete
[142] Fix | Delete
add_action('updraft_report_remotestorage_extrainfo', array($this, 'report_remotestorage_extrainfo'), 10, 3);
[143] Fix | Delete
[144] Fix | Delete
// Prevent people using WP < 5.5 upgrading from being baffled by WP's obscure error message. See: https://core.trac.wordpress.org/ticket/27196
[145] Fix | Delete
[146] Fix | Delete
if (version_compare($this->get_wordpress_version(), '5.4.99999999', '<')) {
[147] Fix | Delete
add_filter('upgrader_source_selection', array($this, 'upgrader_source_selection'), 10, 4);
[148] Fix | Delete
}
[149] Fix | Delete
[150] Fix | Delete
// register_deactivation_hook(__FILE__, array($this, 'deactivation'));
[151] Fix | Delete
if (!empty($_POST) && !empty($_GET['udm_action']) && 'vault_disconnect' == $_GET['udm_action'] && !empty($_POST['udrpc_message']) && !empty($_POST['reset_hash'])) {
[152] Fix | Delete
add_action('wp_loaded', array($this, 'wp_loaded_vault_disconnect'), 1);
[153] Fix | Delete
}
[154] Fix | Delete
[155] Fix | Delete
// Remove the notice on the Updates page that confuses users who already have backups installed
[156] Fix | Delete
if ('update-core.php' == $pagenow) {
[157] Fix | Delete
// added filter here instead of admin.php because the jetpack_just_in_time_msgs filter applied in init hook
[158] Fix | Delete
add_filter('jetpack_just_in_time_msgs', '__return_false', 20);
[159] Fix | Delete
}
[160] Fix | Delete
}
[161] Fix | Delete
[162] Fix | Delete
/**
[163] Fix | Delete
* Enables automatic updates for the plugin.
[164] Fix | Delete
*
[165] Fix | Delete
* @access public
[166] Fix | Delete
* @see __construct
[167] Fix | Delete
* @internal uses auto_update_plugin filter
[168] Fix | Delete
*
[169] Fix | Delete
* @param Bool $update Whether the item has automatic updates enabled
[170] Fix | Delete
* @param Object $item Object holding the asset to be updated
[171] Fix | Delete
* @return bool True of automatic updates enabled, false if not
[172] Fix | Delete
*/
[173] Fix | Delete
public function maybe_auto_update_plugin($update, $item) {
[174] Fix | Delete
if (!isset($item->plugin) || basename(UPDRAFTPLUS_DIR).'/updraftplus.php' !== $item->plugin) return $update;
[175] Fix | Delete
$option_auto_update_settings = (array) get_site_option('auto_update_plugins', array());
[176] Fix | Delete
return in_array($item->plugin, $option_auto_update_settings, true);
[177] Fix | Delete
}
[178] Fix | Delete
[179] Fix | Delete
/**
[180] Fix | Delete
* Called by the WP action updraft_report_remotestorage_extrainfo
[181] Fix | Delete
*
[182] Fix | Delete
* @param String $service
[183] Fix | Delete
* @param String $info_html - the HTML version of the extra info
[184] Fix | Delete
* @param String $info_plain - the plain text version of the extra info
[185] Fix | Delete
*/
[186] Fix | Delete
public function report_remotestorage_extrainfo($service, $info_html, $info_plain) {
[187] Fix | Delete
$this->remotestorage_extrainfo[$service] = array('pretty' => $info_html, 'plain' => $info_plain);
[188] Fix | Delete
}
[189] Fix | Delete
[190] Fix | Delete
/**
[191] Fix | Delete
* WP filter upgrader_source_selection. We use it to tweak the error message shown when an install of a new version is prevented by the existence of an existing version (i.e. us!), to give the user some actual useful information instead of WP's default.
[192] Fix | Delete
*
[193] Fix | Delete
* @param String $source File source location.
[194] Fix | Delete
* @param String $remote_source Remote file source location.
[195] Fix | Delete
* @param WP_Upgrader $upgrader_object WP_Upgrader instance.
[196] Fix | Delete
* @param Array $hook_extra Extra arguments passed to hooked filters.
[197] Fix | Delete
*
[198] Fix | Delete
* @return String - filtered value
[199] Fix | Delete
*/
[200] Fix | Delete
public function upgrader_source_selection($source, $remote_source, $upgrader_object, $hook_extra = array()) {// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found -- Filter use
[201] Fix | Delete
[202] Fix | Delete
static $been_here_already = false;
[203] Fix | Delete
[204] Fix | Delete
if ($been_here_already || !is_array($hook_extra) || empty($hook_extra['type']) || 'plugin' !== $hook_extra['type'] || empty($hook_extra['action']) || 'install' !== $hook_extra['action'] || empty($source) || 'updraftplus' !== basename(untrailingslashit($source)) || !class_exists('ReflectionObject')) return $source;
[205] Fix | Delete
[206] Fix | Delete
$been_here_already = true;
[207] Fix | Delete
[208] Fix | Delete
$reflect = new ReflectionObject($upgrader_object);
[209] Fix | Delete
[210] Fix | Delete
$properties = $reflect->getProperty('strings');
[211] Fix | Delete
[212] Fix | Delete
if (!$properties->isPublic() || !is_array($upgrader_object->strings) || empty($upgrader_object->strings['folder_exists'])) return $source;
[213] Fix | Delete
[214] Fix | Delete
$upgrader_object->strings['folder_exists'] .= ' '.__('A version of UpdraftPlus is already installed. WordPress will only allow you to install your new version after first de-installing the existing one. That is safe - all your settings and backups will be retained. So, go to the "Plugins" page, de-activate and de-install UpdraftPlus, and then try again.', 'updraftplus');
[215] Fix | Delete
[216] Fix | Delete
return $source;
[217] Fix | Delete
[218] Fix | Delete
}
[219] Fix | Delete
[220] Fix | Delete
/**
[221] Fix | Delete
* WordPress filter itsec_scheduled_external_backup - from iThemes Security
[222] Fix | Delete
*
[223] Fix | Delete
* @return Boolean - filtered value
[224] Fix | Delete
*/
[225] Fix | Delete
public function itsec_scheduled_external_backup() {
[226] Fix | Delete
return wp_next_scheduled('updraft_backup') ? true : false;
[227] Fix | Delete
}
[228] Fix | Delete
[229] Fix | Delete
/**
[230] Fix | Delete
* WordPress filter itsec_external_backup_link - from iThemes security
[231] Fix | Delete
*
[232] Fix | Delete
* @return String - filtered value
[233] Fix | Delete
*/
[234] Fix | Delete
public function itsec_external_backup_link() {
[235] Fix | Delete
return UpdraftPlus_Options::admin_page_url().'?page=updraftplus';
[236] Fix | Delete
}
[237] Fix | Delete
[238] Fix | Delete
/**
[239] Fix | Delete
* This method will disconnect UpdraftVault accounts.
[240] Fix | Delete
*
[241] Fix | Delete
* @return Array - returns the saved options if an error is encountered.
[242] Fix | Delete
*/
[243] Fix | Delete
public function wp_loaded_vault_disconnect() {
[244] Fix | Delete
$opts = UpdraftPlus_Storage_Methods_Interface::update_remote_storage_options_format('updraftvault');
[245] Fix | Delete
[246] Fix | Delete
if (is_wp_error($opts)) {
[247] Fix | Delete
if ('recursion' !== $opts->get_error_code()) {
[248] Fix | Delete
$msg = "UpdraftVault (".$opts->get_error_code()."): ".$opts->get_error_message();
[249] Fix | Delete
$this->log($msg);
[250] Fix | Delete
error_log("UpdraftPlus: $msg");
[251] Fix | Delete
}
[252] Fix | Delete
// The saved options had a problem; so, return the new ones
[253] Fix | Delete
return $opts;
[254] Fix | Delete
} elseif (!empty($opts['settings'])) {
[255] Fix | Delete
[256] Fix | Delete
foreach ($opts['settings'] as $storage_options) {
[257] Fix | Delete
if (!empty($storage_options['token']) && $storage_options['token']) {
[258] Fix | Delete
$site_id = $this->siteid();
[259] Fix | Delete
$hash = hash('sha256', $site_id.':::'.$storage_options['token']);
[260] Fix | Delete
if ($hash == $_POST['reset_hash']) {
[261] Fix | Delete
$this->log('This site has been remotely disconnected from UpdraftPlus Vault');
[262] Fix | Delete
include_once(UPDRAFTPLUS_DIR.'/methods/updraftvault.php');
[263] Fix | Delete
$vault = new UpdraftPlus_BackupModule_updraftvault();
[264] Fix | Delete
$vault->ajax_vault_disconnect();
[265] Fix | Delete
// Die, as the vault method has already sent output
[266] Fix | Delete
die;
[267] Fix | Delete
} else {
[268] Fix | Delete
$this->log('An invalid request was received to disconnect this site from UpdraftPlus Vault');
[269] Fix | Delete
}
[270] Fix | Delete
}
[271] Fix | Delete
echo json_encode(array('disconnected' => 0));
[272] Fix | Delete
}
[273] Fix | Delete
}
[274] Fix | Delete
die;
[275] Fix | Delete
}
[276] Fix | Delete
[277] Fix | Delete
/**
[278] Fix | Delete
* Gets an RPC object, and sets some defaults on it that we always want
[279] Fix | Delete
*
[280] Fix | Delete
* @param string $indicator_name indicator name
[281] Fix | Delete
* @return array
[282] Fix | Delete
*/
[283] Fix | Delete
public function get_udrpc($indicator_name = 'migrator.updraftplus.com') {
[284] Fix | Delete
if (!class_exists('UpdraftPlus_Remote_Communications')) include_once(apply_filters('updraftplus_class_udrpc_path', UPDRAFTPLUS_DIR.'/includes/class-udrpc.php', $this->version));
[285] Fix | Delete
$ud_rpc = new UpdraftPlus_Remote_Communications($indicator_name);
[286] Fix | Delete
$ud_rpc->set_can_generate(true);
[287] Fix | Delete
return $ud_rpc;
[288] Fix | Delete
}
[289] Fix | Delete
[290] Fix | Delete
/**
[291] Fix | Delete
* Ensure that the indicated phpseclib classes are available
[292] Fix | Delete
*
[293] Fix | Delete
* @param String|Array $classes - a class, or list of classes. There used to be a second parameter with paths to include; but this is now inferred from $classes; and there's no backwards compatibility problem because sending more parameters than are used is acceptable in PHP.
[294] Fix | Delete
*
[295] Fix | Delete
* @return Boolean|WP_Error
[296] Fix | Delete
*/
[297] Fix | Delete
public function ensure_phpseclib($classes = array()) {
[298] Fix | Delete
[299] Fix | Delete
$classes = (array) $classes;
[300] Fix | Delete
[301] Fix | Delete
$this->no_deprecation_warnings_on_php7();
[302] Fix | Delete
[303] Fix | Delete
$any_missing = false;
[304] Fix | Delete
[305] Fix | Delete
foreach ($classes as $cl) {
[306] Fix | Delete
if (!class_exists($cl)) $any_missing = true;
[307] Fix | Delete
}
[308] Fix | Delete
[309] Fix | Delete
if (!$any_missing) return true;
[310] Fix | Delete
[311] Fix | Delete
$ret = true;
[312] Fix | Delete
[313] Fix | Delete
// From phpseclib/phpseclib/phpseclib/bootstrap.php - we nullify it there, but log here instead
[314] Fix | Delete
if (extension_loaded('mbstring')) {
[315] Fix | Delete
// 2 - MB_OVERLOAD_STRING
[316] Fix | Delete
// @codingStandardsIgnoreLine
[317] Fix | Delete
if (ini_get('mbstring.func_overload') & 2) {
[318] Fix | Delete
// We go on to try anyway, in case the caller wasn't using an affected part of phpseclib
[319] Fix | Delete
// @codingStandardsIgnoreLine
[320] Fix | Delete
$ret = new WP_Error('mbstring_func_overload', 'Overloading of string functions using mbstring.func_overload is not supported by phpseclib.');
[321] Fix | Delete
}
[322] Fix | Delete
}
[323] Fix | Delete
[324] Fix | Delete
$phpseclib_dir = UPDRAFTPLUS_DIR.'/vendor/phpseclib/phpseclib/phpseclib';
[325] Fix | Delete
if (false === strpos(get_include_path(), $phpseclib_dir)) set_include_path(get_include_path().PATH_SEPARATOR.$phpseclib_dir);
[326] Fix | Delete
foreach ($classes as $cl) {
[327] Fix | Delete
$path = str_replace('_', '/', $cl);
[328] Fix | Delete
if (!class_exists($cl)) include_once($phpseclib_dir.'/'.$path.'.php');
[329] Fix | Delete
}
[330] Fix | Delete
[331] Fix | Delete
return $ret;
[332] Fix | Delete
}
[333] Fix | Delete
[334] Fix | Delete
/**
[335] Fix | Delete
* Ugly, but necessary to prevent debug output breaking the conversation when the user has debug turned on
[336] Fix | Delete
*/
[337] Fix | Delete
private function no_deprecation_warnings_on_php7() {
[338] Fix | Delete
// PHP_MAJOR_VERSION is defined in PHP 5.2.7+
[339] Fix | Delete
// We don't test for PHP > 7 because the specific deprecated element will be removed in PHP 8 - and so no warning should come anyway (and we shouldn't suppress other stuff until we know we need to).
[340] Fix | Delete
// @codingStandardsIgnoreLine
[341] Fix | Delete
if (defined('PHP_MAJOR_VERSION') && PHP_MAJOR_VERSION == 7) {
[342] Fix | Delete
$old_level = error_reporting();
[343] Fix | Delete
// @codingStandardsIgnoreLine
[344] Fix | Delete
$new_level = $old_level & ~E_DEPRECATED;
[345] Fix | Delete
if ($old_level != $new_level) error_reporting($new_level);
[346] Fix | Delete
$this->no_deprecation_warnings = true;
[347] Fix | Delete
}
[348] Fix | Delete
}
[349] Fix | Delete
[350] Fix | Delete
/**
[351] Fix | Delete
* Attempt to close the connection to the browser, optionally with some output sent first, whilst continuing execution
[352] Fix | Delete
*
[353] Fix | Delete
* @param String $txt - output to send
[354] Fix | Delete
*/
[355] Fix | Delete
public function close_browser_connection($txt = '') {
[356] Fix | Delete
// Close browser connection so that it can resume AJAX polling
[357] Fix | Delete
header('Content-Length: '.(empty($txt) ? '0' : 4+strlen($txt)));
[358] Fix | Delete
header('Connection: close');
[359] Fix | Delete
header('Content-Encoding: none');
[360] Fix | Delete
if (function_exists('session_id') && session_id()) session_write_close();
[361] Fix | Delete
echo "\r\n\r\n";
[362] Fix | Delete
echo $txt;
[363] Fix | Delete
// These two added - 19-Feb-15 - started being required on local dev machine, for unknown reason (probably some plugin that started an output buffer).
[364] Fix | Delete
$ob_level = ob_get_level();
[365] Fix | Delete
while ($ob_level > 0) {
[366] Fix | Delete
ob_end_flush();
[367] Fix | Delete
$ob_level--;
[368] Fix | Delete
}
[369] Fix | Delete
flush();
[370] Fix | Delete
if (function_exists('fastcgi_finish_request')) fastcgi_finish_request();
[371] Fix | Delete
}
[372] Fix | Delete
[373] Fix | Delete
/**
[374] Fix | Delete
* Returns the number of bytes free, if it can be detected; otherwise, false
[375] Fix | Delete
* Presently, we only detect CPanel. If you know of others, then feel free to contribute!
[376] Fix | Delete
*/
[377] Fix | Delete
public function get_hosting_disk_quota_free() {
[378] Fix | Delete
if (!@is_dir('/usr/local/cpanel') || $this->detect_safe_mode() || !function_exists('popen') || (!@is_executable('/usr/local/bin/perl') && !@is_executable('/usr/local/cpanel/3rdparty/bin/perl')) || (defined('UPDRAFTPLUS_SKIP_CPANEL_QUOTA_CHECK') && UPDRAFTPLUS_SKIP_CPANEL_QUOTA_CHECK)) return false;// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
[379] Fix | Delete
[380] Fix | Delete
$perl = (@is_executable('/usr/local/cpanel/3rdparty/bin/perl')) ? '/usr/local/cpanel/3rdparty/bin/perl' : '/usr/local/bin/perl';// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
[381] Fix | Delete
[382] Fix | Delete
$exec = "UPDRAFTPLUSKEY=updraftplus $perl ".UPDRAFTPLUS_DIR."/includes/get-cpanel-quota-usage.pl";
[383] Fix | Delete
[384] Fix | Delete
$handle = function_exists('popen') ? @popen($exec, 'r') : false; // phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
[385] Fix | Delete
if (!is_resource($handle)) return false;
[386] Fix | Delete
[387] Fix | Delete
$found = false;
[388] Fix | Delete
$lines = 0;
[389] Fix | Delete
while (false === $found && !feof($handle) && $lines<100) {
[390] Fix | Delete
$lines++;
[391] Fix | Delete
$w = fgets($handle);
[392] Fix | Delete
// Used, limit, remain
[393] Fix | Delete
if (preg_match('/RESULT: (\d+) (\d+) (\d+) /', $w, $matches)) {
[394] Fix | Delete
$found = true;
[395] Fix | Delete
}
[396] Fix | Delete
}
[397] Fix | Delete
$ret = pclose($handle);
[398] Fix | Delete
// The manual page for pclose() claims that only -1 indicates an error, but this is untrue
[399] Fix | Delete
if (false === $found || 0 != $ret) return false;
[400] Fix | Delete
[401] Fix | Delete
if ((int) $matches[2]<100 || ($matches[1] + $matches[3] != $matches[2])) return false;
[402] Fix | Delete
[403] Fix | Delete
$this->cpanel_quota_readable = true;
[404] Fix | Delete
[405] Fix | Delete
return $matches;
[406] Fix | Delete
}
[407] Fix | Delete
[408] Fix | Delete
/**
[409] Fix | Delete
* Fetch information about the most recently modified log file
[410] Fix | Delete
*
[411] Fix | Delete
* @return Array - lists the modification time, the full path to the log file, and the log's nonce (ID)
[412] Fix | Delete
*/
[413] Fix | Delete
public function last_modified_log() {
[414] Fix | Delete
$updraft_dir = $this->backups_dir_location();
[415] Fix | Delete
[416] Fix | Delete
$log_file = '';
[417] Fix | Delete
$mod_time = false;
[418] Fix | Delete
$nonce = '';
[419] Fix | Delete
[420] Fix | Delete
if ($handle = @opendir($updraft_dir)) {// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
[421] Fix | Delete
while (false !== ($entry = readdir($handle))) {
[422] Fix | Delete
// The latter match is for files created internally by zipArchive::addFile
[423] Fix | Delete
if (preg_match('/^log\.([a-z0-9]+)\.txt$/i', $entry, $matches)) {
[424] Fix | Delete
$mtime = filemtime($updraft_dir.'/'.$entry);
[425] Fix | Delete
if ($mtime > $mod_time) {
[426] Fix | Delete
$mod_time = $mtime;
[427] Fix | Delete
$log_file = $updraft_dir.'/'.$entry;
[428] Fix | Delete
$nonce = $matches[1];
[429] Fix | Delete
}
[430] Fix | Delete
}
[431] Fix | Delete
}
[432] Fix | Delete
@closedir($handle);// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
[433] Fix | Delete
}
[434] Fix | Delete
[435] Fix | Delete
return array($mod_time, $log_file, $nonce);
[436] Fix | Delete
}
[437] Fix | Delete
[438] Fix | Delete
/**
[439] Fix | Delete
* This function may get called multiple times, so write accordingly
[440] Fix | Delete
*/
[441] Fix | Delete
public function admin_menu() {
[442] Fix | Delete
// We are in the admin area: now load all that code
[443] Fix | Delete
global $updraftplus_admin;
[444] Fix | Delete
if (empty($updraftplus_admin)) include_once(UPDRAFTPLUS_DIR.'/admin.php');
[445] Fix | Delete
[446] Fix | Delete
if (isset($_GET['wpnonce']) && isset($_GET['page']) && isset($_GET['action']) && 'updraftplus' == $_GET['page'] && 'downloadlatestmodlog' == $_GET['action'] && wp_verify_nonce($_GET['wpnonce'], 'updraftplus_download')) {
[447] Fix | Delete
[448] Fix | Delete
list($mod_time, $log_file, $nonce) = $this->last_modified_log();// phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
[449] Fix | Delete
[450] Fix | Delete
if ($mod_time >0) {
[451] Fix | Delete
if (is_readable($log_file)) {
[452] Fix | Delete
header('Content-type: text/plain');
[453] Fix | Delete
readfile($log_file);
[454] Fix | Delete
exit;
[455] Fix | Delete
} else {
[456] Fix | Delete
add_action('all_admin_notices', array($this, 'show_admin_warning_unreadablelog'));
[457] Fix | Delete
}
[458] Fix | Delete
} else {
[459] Fix | Delete
add_action('all_admin_notices', array($this, 'show_admin_warning_nolog'));
[460] Fix | Delete
}
[461] Fix | Delete
}
[462] Fix | Delete
[463] Fix | Delete
}
[464] Fix | Delete
[465] Fix | Delete
/**
[466] Fix | Delete
* WP action http_api_curl
[467] Fix | Delete
*
[468] Fix | Delete
* @param Resource $handle A curl handle returned by curl_init()
[469] Fix | Delete
*
[470] Fix | Delete
* @return the handle (having potentially had some options set upon it)
[471] Fix | Delete
*/
[472] Fix | Delete
public function http_api_curl($handle) {
[473] Fix | Delete
if (defined('UPDRAFTPLUS_IPV4_ONLY') && UPDRAFTPLUS_IPV4_ONLY) {
[474] Fix | Delete
curl_setopt($handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
[475] Fix | Delete
}
[476] Fix | Delete
return $handle;
[477] Fix | Delete
}
[478] Fix | Delete
[479] Fix | Delete
/**
[480] Fix | Delete
* Used as a central location (to avoid repetition) to register or de-register hooks into the WP HTTP API
[481] Fix | Delete
*
[482] Fix | Delete
* @param Boolean $register - true to register, false to de-register
[483] Fix | Delete
*/
[484] Fix | Delete
public function register_wp_http_option_hooks($register = true) {
[485] Fix | Delete
if ($register) {
[486] Fix | Delete
add_filter('http_request_args', array($this, 'modify_http_options'));
[487] Fix | Delete
add_action('http_api_curl', array($this, 'http_api_curl'));
[488] Fix | Delete
} else {
[489] Fix | Delete
remove_filter('http_request_args', array($this, 'modify_http_options'));
[490] Fix | Delete
remove_action('http_api_curl', array($this, 'http_api_curl'));
[491] Fix | Delete
}
[492] Fix | Delete
}
[493] Fix | Delete
[494] Fix | Delete
/**
[495] Fix | Delete
* Used as a WordPress options filter (http_request_args)
[496] Fix | Delete
*
[497] Fix | Delete
* @param Array $opts - existing options
[498] Fix | Delete
*
[499] Fix | Delete
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function