Edit File by line
/home/barbar84/www/wp-conte.../plugins/updraftp...
File: backup.php
<?php
[0] Fix | Delete
[1] Fix | Delete
if (!defined('UPDRAFTPLUS_DIR')) die('No direct access allowed');
[2] Fix | Delete
[3] Fix | Delete
if (!class_exists('UpdraftPlus_PclZip')) require_once(UPDRAFTPLUS_DIR.'/includes/class-zip.php');
[4] Fix | Delete
[5] Fix | Delete
/**
[6] Fix | Delete
* This file contains code that is only needed/loaded when a backup is running
[7] Fix | Delete
*/
[8] Fix | Delete
class UpdraftPlus_Backup {
[9] Fix | Delete
[10] Fix | Delete
private $index = 0;
[11] Fix | Delete
[12] Fix | Delete
private $manifest_path;
[13] Fix | Delete
[14] Fix | Delete
private $zipfiles_added;
[15] Fix | Delete
[16] Fix | Delete
private $zipfiles_added_thisrun = 0;
[17] Fix | Delete
[18] Fix | Delete
public $zipfiles_dirbatched;
[19] Fix | Delete
[20] Fix | Delete
public $zipfiles_batched;
[21] Fix | Delete
[22] Fix | Delete
public $zipfiles_skipped_notaltered;
[23] Fix | Delete
[24] Fix | Delete
private $zip_split_every = 419430400; // 400MB
[25] Fix | Delete
[26] Fix | Delete
private $zip_last_ratio = 1;
[27] Fix | Delete
[28] Fix | Delete
private $whichone;
[29] Fix | Delete
[30] Fix | Delete
private $zip_basename = '';
[31] Fix | Delete
[32] Fix | Delete
private $backup_basename = '';
[33] Fix | Delete
[34] Fix | Delete
private $zipfiles_lastwritetime;
[35] Fix | Delete
[36] Fix | Delete
// 0 = unknown; false = failed
[37] Fix | Delete
public $binzip = 0;
[38] Fix | Delete
[39] Fix | Delete
private $dbhandle;
[40] Fix | Delete
[41] Fix | Delete
private $dbhandle_isgz;
[42] Fix | Delete
[43] Fix | Delete
// Array of entities => times
[44] Fix | Delete
private $altered_since = -1;
[45] Fix | Delete
[46] Fix | Delete
// Time for the current entity
[47] Fix | Delete
private $makezip_if_altered_since = -1;
[48] Fix | Delete
[49] Fix | Delete
private $excluded_extensions = false;
[50] Fix | Delete
[51] Fix | Delete
private $use_zip_object = 'UpdraftPlus_ZipArchive';
[52] Fix | Delete
[53] Fix | Delete
public $debug = false;
[54] Fix | Delete
[55] Fix | Delete
public $updraft_dir;
[56] Fix | Delete
[57] Fix | Delete
private $site_name;
[58] Fix | Delete
[59] Fix | Delete
private $wpdb_obj;
[60] Fix | Delete
[61] Fix | Delete
private $job_file_entities = array();
[62] Fix | Delete
[63] Fix | Delete
private $first_run = 0;
[64] Fix | Delete
[65] Fix | Delete
// Record of zip files created
[66] Fix | Delete
private $backup_files_array = array();
[67] Fix | Delete
[68] Fix | Delete
// Used when deciding to use the 'store' or 'deflate' zip storage method
[69] Fix | Delete
private $extensions_to_not_compress = array();
[70] Fix | Delete
[71] Fix | Delete
// Append to this any skipped tables
[72] Fix | Delete
private $skipped_tables;
[73] Fix | Delete
[74] Fix | Delete
// When initialised, a boolean
[75] Fix | Delete
public $last_storage_instance;
[76] Fix | Delete
[77] Fix | Delete
// The absolute upper limit that will be considered for a zip batch (in bytes)
[78] Fix | Delete
private $zip_batch_ceiling;
[79] Fix | Delete
[80] Fix | Delete
private $backup_excluded_patterns = array();
[81] Fix | Delete
[82] Fix | Delete
// Bytes of uncompressed data written since last open
[83] Fix | Delete
private $db_current_raw_bytes = 0;
[84] Fix | Delete
[85] Fix | Delete
private $table_prefix;
[86] Fix | Delete
[87] Fix | Delete
private $table_prefix_raw;
[88] Fix | Delete
[89] Fix | Delete
private $many_rows_warning = false;
[90] Fix | Delete
[91] Fix | Delete
private $expected_rows = false;
[92] Fix | Delete
[93] Fix | Delete
// @var Boolean
[94] Fix | Delete
private $try_split = false;
[95] Fix | Delete
[96] Fix | Delete
/**
[97] Fix | Delete
* Class constructor
[98] Fix | Delete
*
[99] Fix | Delete
* @param Array|String $backup_files - files to backup, or (string)'no'
[100] Fix | Delete
* @param Integer $altered_since - only backup files altered since this time (UNIX epoch time)
[101] Fix | Delete
*/
[102] Fix | Delete
public function __construct($backup_files, $altered_since = -1) {
[103] Fix | Delete
[104] Fix | Delete
global $updraftplus;
[105] Fix | Delete
[106] Fix | Delete
$this->site_name = $this->get_site_name();
[107] Fix | Delete
[108] Fix | Delete
// Decide which zip engine to begin with
[109] Fix | Delete
$this->debug = UpdraftPlus_Options::get_updraft_option('updraft_debug_mode');
[110] Fix | Delete
$this->updraft_dir = $updraftplus->backups_dir_location();
[111] Fix | Delete
$this->updraft_dir_realpath = realpath($this->updraft_dir);
[112] Fix | Delete
[113] Fix | Delete
require_once(UPDRAFTPLUS_DIR.'/includes/class-database-utility.php');
[114] Fix | Delete
[115] Fix | Delete
if ('no' === $backup_files) {
[116] Fix | Delete
$this->use_zip_object = 'UpdraftPlus_PclZip';
[117] Fix | Delete
return;
[118] Fix | Delete
}
[119] Fix | Delete
[120] Fix | Delete
$this->extensions_to_not_compress = array_unique(array_map('strtolower', array_map('trim', explode(',', UPDRAFTPLUS_ZIP_NOCOMPRESS))));
[121] Fix | Delete
[122] Fix | Delete
$this->backup_excluded_patterns = array(
[123] Fix | Delete
array(
[124] Fix | Delete
// all in one wp migration pattern: WP_PLUGIN_DIR/all-in-one-wp-migration/storage/*/*.wpress, `ai1wm-backups` folder in wp-content is already implicitly handled on the UDP settings with a `*backups` predefined exclusion rule for `others` directory
[125] Fix | Delete
'directory' => realpath(WP_PLUGIN_DIR).DIRECTORY_SEPARATOR.'all-in-one-wp-migration'.DIRECTORY_SEPARATOR.'storage',
[126] Fix | Delete
'regex' => '/.+\.wpress$/is',
[127] Fix | Delete
),
[128] Fix | Delete
);
[129] Fix | Delete
[130] Fix | Delete
$this->altered_since = $altered_since;
[131] Fix | Delete
[132] Fix | Delete
$resumptions_since_last_successful = $updraftplus->current_resumption - $updraftplus->last_successful_resumption;
[133] Fix | Delete
[134] Fix | Delete
// false means 'tried + failed'; whereas 0 means 'not yet tried'
[135] Fix | Delete
// Disallow binzip on OpenVZ when we're not sure there's plenty of memory
[136] Fix | Delete
if (0 === $this->binzip && (!defined('UPDRAFTPLUS_PREFERPCLZIP') || !UPDRAFTPLUS_PREFERPCLZIP) && (!defined('UPDRAFTPLUS_NO_BINZIP') || !UPDRAFTPLUS_NO_BINZIP) && ($updraftplus->current_resumption < 9 || $resumptions_since_last_successful < 2)) {
[137] Fix | Delete
[138] Fix | Delete
if (@file_exists('/proc/user_beancounters') && @file_exists('/proc/meminfo') && @is_readable('/proc/meminfo')) {// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
[139] Fix | Delete
$meminfo = @file_get_contents('/proc/meminfo', false, null, 0, 200);// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
[140] Fix | Delete
if (is_string($meminfo) && preg_match('/MemTotal:\s+(\d+) kB/', $meminfo, $matches)) {
[141] Fix | Delete
$memory_mb = $matches[1]/1024;
[142] Fix | Delete
// If the report is of a large amount, then we're probably getting the total memory on the hypervisor (this has been observed), and don't really know the VPS's memory
[143] Fix | Delete
$vz_log = "OpenVZ; reported memory: ".round($memory_mb, 1)." MB";
[144] Fix | Delete
if ($memory_mb < 1024 || $memory_mb > 8192) {
[145] Fix | Delete
$openvz_lowmem = true;
[146] Fix | Delete
$vz_log .= " (will not use BinZip)";
[147] Fix | Delete
}
[148] Fix | Delete
$updraftplus->log($vz_log);
[149] Fix | Delete
}
[150] Fix | Delete
}
[151] Fix | Delete
if (empty($openvz_lowmem)) {
[152] Fix | Delete
$updraftplus->log('Checking if we have a zip executable available');
[153] Fix | Delete
$binzip = $updraftplus->find_working_bin_zip();
[154] Fix | Delete
if (is_string($binzip)) {
[155] Fix | Delete
$updraftplus->log("Zip engine: found/will use a binary zip: $binzip");
[156] Fix | Delete
$this->binzip = $binzip;
[157] Fix | Delete
$this->use_zip_object = 'UpdraftPlus_BinZip';
[158] Fix | Delete
}
[159] Fix | Delete
}
[160] Fix | Delete
}
[161] Fix | Delete
[162] Fix | Delete
// In tests, PclZip was found to be 25% slower than ZipArchive
[163] Fix | Delete
if ('UpdraftPlus_PclZip' != $this->use_zip_object && empty($this->binzip) && ((defined('UPDRAFTPLUS_PREFERPCLZIP') && UPDRAFTPLUS_PREFERPCLZIP == true) || !class_exists('ZipArchive') || !class_exists('UpdraftPlus_ZipArchive') || (!extension_loaded('zip') && !method_exists('ZipArchive', 'AddFile')))) {
[164] Fix | Delete
global $updraftplus;
[165] Fix | Delete
$updraftplus->log("Zip engine: ZipArchive (a.k.a. php-zip) is not available or is disabled (will use PclZip (much slower) if needed)");
[166] Fix | Delete
$this->use_zip_object = 'UpdraftPlus_PclZip';
[167] Fix | Delete
}
[168] Fix | Delete
[169] Fix | Delete
$this->zip_batch_ceiling = (defined('UPDRAFTPLUS_ZIP_BATCH_CEILING') && UPDRAFTPLUS_ZIP_BATCH_CEILING > 104857600) ? UPDRAFTPLUS_ZIP_BATCH_CEILING : 200 * 1048576;
[170] Fix | Delete
[171] Fix | Delete
add_filter('updraftplus_exclude_file', array($this, 'backup_exclude_file'), 10, 2);
[172] Fix | Delete
[173] Fix | Delete
}
[174] Fix | Delete
[175] Fix | Delete
/**
[176] Fix | Delete
* Get a site name suitable for use in the backup filename
[177] Fix | Delete
*
[178] Fix | Delete
* @return String
[179] Fix | Delete
*/
[180] Fix | Delete
private function get_site_name() {
[181] Fix | Delete
// Get the blog name and rip out known-problematic characters. Remember that we may need to be able to upload this to any FTP server or cloud storage, where filename support may be unknown
[182] Fix | Delete
$site_name = str_replace('__', '_', preg_replace('/[^A-Za-z0-9_]/', '', str_replace(' ', '_', substr(get_bloginfo(), 0, 32))));
[183] Fix | Delete
if (!$site_name || preg_match('#^_+$#', $site_name)) {
[184] Fix | Delete
// Try again...
[185] Fix | Delete
$parsed_url = parse_url(home_url(), PHP_URL_HOST);
[186] Fix | Delete
$parsed_subdir = untrailingslashit(parse_url(home_url(), PHP_URL_PATH));
[187] Fix | Delete
if ($parsed_subdir && '/' != $parsed_subdir) $parsed_url .= str_replace(array('/', '\\'), '_', $parsed_subdir);
[188] Fix | Delete
$site_name = str_replace('__', '_', preg_replace('/[^A-Za-z0-9_]/', '', str_replace(' ', '_', substr($parsed_url, 0, 32))));
[189] Fix | Delete
if (!$site_name || preg_match('#^_+$#', $site_name)) $site_name = 'WordPress_Backup';
[190] Fix | Delete
}
[191] Fix | Delete
[192] Fix | Delete
// Allow an over-ride. Careful about introducing characters not supported by your filesystem or cloud storage.
[193] Fix | Delete
return apply_filters('updraftplus_blog_name', $site_name);
[194] Fix | Delete
}
[195] Fix | Delete
[196] Fix | Delete
/**
[197] Fix | Delete
* Public, because called from the 'More Files' add-on
[198] Fix | Delete
*
[199] Fix | Delete
* @param String|Array $create_from_dir Directory/ies to create the zip
[200] Fix | Delete
* @param String $whichone Entity being backed up (e.g. 'plugins', 'uploads')
[201] Fix | Delete
* @param String $backup_file_basename Name of backup file
[202] Fix | Delete
* @param Integer $index Index of zip in the sequence
[203] Fix | Delete
* @param Integer|Boolean $first_linked_index First linked index in the sequence, or false
[204] Fix | Delete
*
[205] Fix | Delete
* @return Boolean
[206] Fix | Delete
*/
[207] Fix | Delete
public function create_zip($create_from_dir, $whichone, $backup_file_basename, $index, $first_linked_index = false) {
[208] Fix | Delete
// Note: $create_from_dir can be an array or a string
[209] Fix | Delete
[210] Fix | Delete
if (function_exists('set_time_limit')) set_time_limit(UPDRAFTPLUS_SET_TIME_LIMIT);
[211] Fix | Delete
[212] Fix | Delete
$original_index = $index;
[213] Fix | Delete
[214] Fix | Delete
$this->index = $index;
[215] Fix | Delete
$this->first_linked_index = (false === $first_linked_index) ? 0 : $first_linked_index;
[216] Fix | Delete
$this->whichone = $whichone;
[217] Fix | Delete
[218] Fix | Delete
global $updraftplus;
[219] Fix | Delete
[220] Fix | Delete
$this->zip_split_every = max((int) $updraftplus->jobdata_get('split_every'), UPDRAFTPLUS_SPLIT_MIN)*1048576;
[221] Fix | Delete
[222] Fix | Delete
if ('others' != $whichone) $updraftplus->log("Beginning creation of dump of $whichone (split every: ".round($this->zip_split_every/1048576, 1)." MB)");
[223] Fix | Delete
[224] Fix | Delete
if (is_string($create_from_dir) && !file_exists($create_from_dir)) {
[225] Fix | Delete
$flag_error = true;
[226] Fix | Delete
$updraftplus->log("Does not exist: $create_from_dir");
[227] Fix | Delete
if ('mu-plugins' == $whichone) {
[228] Fix | Delete
if (!function_exists('get_mu_plugins')) include_once(ABSPATH.'wp-admin/includes/plugin.php');
[229] Fix | Delete
$mu_plugins = get_mu_plugins();
[230] Fix | Delete
if (count($mu_plugins) == 0) {
[231] Fix | Delete
$updraftplus->log("There appear to be no mu-plugins to backup. Will not raise an error.");
[232] Fix | Delete
$flag_error = false;
[233] Fix | Delete
}
[234] Fix | Delete
}
[235] Fix | Delete
if ($flag_error) $updraftplus->log(sprintf(__("%s - could not back this entity up; the corresponding directory does not exist (%s)", 'updraftplus'), $whichone, $create_from_dir), 'error');
[236] Fix | Delete
return false;
[237] Fix | Delete
}
[238] Fix | Delete
[239] Fix | Delete
$itext = empty($index) ? '' : $index+1;
[240] Fix | Delete
$base_path = $backup_file_basename.'-'.$whichone.$itext.'.zip';
[241] Fix | Delete
$full_path = $this->updraft_dir.'/'.$base_path;
[242] Fix | Delete
$time_now = time();
[243] Fix | Delete
[244] Fix | Delete
// This is compatible with filenames which indicate increments, as it is looking only for the current increment
[245] Fix | Delete
if (file_exists($full_path)) {
[246] Fix | Delete
// Gather any further files that may also exist
[247] Fix | Delete
$files_existing = array();
[248] Fix | Delete
while (file_exists($full_path)) {
[249] Fix | Delete
$files_existing[] = $base_path;
[250] Fix | Delete
$time_mod = (int) @filemtime($full_path);// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
[251] Fix | Delete
$updraftplus->log($base_path.": this file has already been created (age: ".round($time_now-$time_mod, 1)." s)");
[252] Fix | Delete
if ($time_mod > 100 && ($time_now - $time_mod) < 30) {
[253] Fix | Delete
UpdraftPlus_Job_Scheduler::terminate_due_to_activity($base_path, $time_now, $time_mod);
[254] Fix | Delete
}
[255] Fix | Delete
$index++;
[256] Fix | Delete
// This is compatible with filenames which indicate increments, as it is looking only for the current increment
[257] Fix | Delete
$base_path = $backup_file_basename.'-'.$whichone.($index+1).'.zip';
[258] Fix | Delete
$full_path = $this->updraft_dir.'/'.$base_path;
[259] Fix | Delete
}
[260] Fix | Delete
}
[261] Fix | Delete
[262] Fix | Delete
// Temporary file, to be able to detect actual completion (upon which, it is renamed)
[263] Fix | Delete
[264] Fix | Delete
// Jun-13 - be more aggressive in removing temporary files from earlier attempts - anything >=600 seconds old of this kind
[265] Fix | Delete
UpdraftPlus_Filesystem_Functions::clean_temporary_files('_'.$updraftplus->file_nonce."-$whichone", 600);
[266] Fix | Delete
[267] Fix | Delete
// Firstly, make sure that the temporary file is not already being written to - which can happen if a resumption takes place whilst an old run is still active
[268] Fix | Delete
$zip_name = $full_path.'.tmp';
[269] Fix | Delete
$time_mod = file_exists($zip_name) ? filemtime($zip_name) : 0;
[270] Fix | Delete
if (file_exists($zip_name) && $time_mod>100 && ($time_now-$time_mod)<30) {
[271] Fix | Delete
UpdraftPlus_Job_Scheduler::terminate_due_to_activity($zip_name, $time_now, $time_mod);
[272] Fix | Delete
}
[273] Fix | Delete
[274] Fix | Delete
if (file_exists($zip_name)) {
[275] Fix | Delete
$updraftplus->log("File exists ($zip_name), but was apparently not modified within the last 30 seconds, so we assume that any previous run has now terminated (time_mod=$time_mod, time_now=$time_now, diff=".($time_now-$time_mod).")");
[276] Fix | Delete
}
[277] Fix | Delete
[278] Fix | Delete
// Now, check for other forms of temporary file, which would indicate that some activity is going on (even if it hasn't made it into the main zip file yet)
[279] Fix | Delete
// Note: this doesn't catch PclZip temporary files
[280] Fix | Delete
$d = dir($this->updraft_dir);
[281] Fix | Delete
$match = '_'.$updraftplus->file_nonce."-".$whichone;
[282] Fix | Delete
while (false !== ($e = $d->read())) {
[283] Fix | Delete
if ('.' == $e || '..' == $e || !is_file($this->updraft_dir.'/'.$e)) continue;
[284] Fix | Delete
$ziparchive_match = preg_match("/$match(?:[0-9]*)\.zip\.tmp\.[A-Za-z0-9]+$/i", $e);
[285] Fix | Delete
$binzip_match = preg_match("/^zi([A-Za-z0-9]){6}$/", $e);
[286] Fix | Delete
$pclzip_match = preg_match("/^pclzip-[a-z0-9]+.(?:gz|tmp)$/", $e);
[287] Fix | Delete
if ($time_now-filemtime($this->updraft_dir.'/'.$e) < 30 && ($ziparchive_match || (0 != $updraftplus->current_resumption && ($binzip_match || $pclzip_match)))) {
[288] Fix | Delete
UpdraftPlus_Job_Scheduler::terminate_due_to_activity($this->updraft_dir.'/'.$e, $time_now, filemtime($this->updraft_dir.'/'.$e));
[289] Fix | Delete
}
[290] Fix | Delete
}
[291] Fix | Delete
@$d->close();// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
[292] Fix | Delete
clearstatcache();
[293] Fix | Delete
[294] Fix | Delete
if (isset($files_existing)) {
[295] Fix | Delete
// Because of zip-splitting, the mere fact that files exist is not enough to indicate that the entity is finished. For that, we need to also see that no subsequent file has been started.
[296] Fix | Delete
// Q. What if the previous runner died in between zips, and it is our job to start the next one? A. The next temporary file is created before finishing the former zip, so we are safe (and we are also safe-guarded by the updated value of the index being stored in the database).
[297] Fix | Delete
return $files_existing;
[298] Fix | Delete
}
[299] Fix | Delete
[300] Fix | Delete
$this->log_account_space();
[301] Fix | Delete
[302] Fix | Delete
$this->zip_microtime_start = microtime(true);
[303] Fix | Delete
[304] Fix | Delete
// The paths in the zip should then begin with '$whichone', having removed WP_CONTENT_DIR from the front
[305] Fix | Delete
$zipcode = $this->make_zipfile($create_from_dir, $backup_file_basename, $whichone);
[306] Fix | Delete
if (true !== $zipcode) {
[307] Fix | Delete
$updraftplus->log("ERROR: Zip failure: Could not create $whichone zip (".$this->index." / $index)");
[308] Fix | Delete
$updraftplus->log(sprintf(__("Could not create %s zip. Consult the log file for more information.", 'updraftplus'), $whichone), 'error');
[309] Fix | Delete
// The caller is required to update $index from $this->index
[310] Fix | Delete
return false;
[311] Fix | Delete
} else {
[312] Fix | Delete
$itext = empty($this->index) ? '' : $this->index+1;
[313] Fix | Delete
$full_path = $this->updraft_dir.'/'.$backup_file_basename.'-'.$whichone.$itext.'.zip';
[314] Fix | Delete
if (file_exists($full_path.'.tmp')) {
[315] Fix | Delete
if (@filesize($full_path.'.tmp') === 0) {// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
[316] Fix | Delete
$updraftplus->log("Did not create $whichone zip (".$this->index.") - not needed");
[317] Fix | Delete
@unlink($full_path.'.tmp');// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
[318] Fix | Delete
} else {
[319] Fix | Delete
[320] Fix | Delete
$checksum_description = '';
[321] Fix | Delete
[322] Fix | Delete
$checksums = $updraftplus->which_checksums();
[323] Fix | Delete
[324] Fix | Delete
foreach ($checksums as $checksum) {
[325] Fix | Delete
[326] Fix | Delete
$cksum = hash_file($checksum, $full_path.'.tmp');
[327] Fix | Delete
$updraftplus->jobdata_set($checksum.'-'.$whichone.$this->index, $cksum);
[328] Fix | Delete
if ($checksum_description) $checksum_description .= ', ';
[329] Fix | Delete
$checksum_description .= "$checksum: $cksum";
[330] Fix | Delete
[331] Fix | Delete
}
[332] Fix | Delete
[333] Fix | Delete
@rename($full_path.'.tmp', $full_path);// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
[334] Fix | Delete
$timetaken = max(microtime(true)-$this->zip_microtime_start, 0.000001);
[335] Fix | Delete
$kbsize = filesize($full_path)/1024;
[336] Fix | Delete
$rate = round($kbsize/$timetaken, 1);
[337] Fix | Delete
$updraftplus->log("Created $whichone zip (".$this->index.") - ".round($kbsize, 1)." KB in ".round($timetaken, 1)." s ($rate KB/s) ($checksum_description)");
[338] Fix | Delete
// We can now remove any left-over temporary files from this job
[339] Fix | Delete
}
[340] Fix | Delete
} elseif ($this->index > $original_index) {
[341] Fix | Delete
$updraftplus->log("Did not create $whichone zip (".$this->index.") - not needed (2)");
[342] Fix | Delete
// Added 12-Feb-2014 (to help multiple morefiles)
[343] Fix | Delete
$this->index--;
[344] Fix | Delete
} else {
[345] Fix | Delete
$updraftplus->log("Looked-for $whichone zip (".$this->index.") was not found (".basename($full_path).".tmp)", 'warning');
[346] Fix | Delete
}
[347] Fix | Delete
UpdraftPlus_Filesystem_Functions::clean_temporary_files('_'.$updraftplus->file_nonce."-$whichone", 0);
[348] Fix | Delete
}
[349] Fix | Delete
[350] Fix | Delete
// Remove cache list files as well, if there are any
[351] Fix | Delete
UpdraftPlus_Filesystem_Functions::clean_temporary_files('_'.$updraftplus->file_nonce."-$whichone", 0, true);
[352] Fix | Delete
[353] Fix | Delete
// Create the results array to send back (just the new ones, not any prior ones)
[354] Fix | Delete
$files_existing = array();
[355] Fix | Delete
$res_index = $original_index;
[356] Fix | Delete
for ($i = $original_index; $i<= $this->index; $i++) {
[357] Fix | Delete
$itext = empty($i) ? '' : ($i+1);
[358] Fix | Delete
$full_path = $this->updraft_dir.'/'.$backup_file_basename.'-'.$whichone.$itext.'.zip';
[359] Fix | Delete
if (file_exists($full_path)) {
[360] Fix | Delete
$files_existing[$res_index] = $backup_file_basename.'-'.$whichone.$itext.'.zip';
[361] Fix | Delete
}
[362] Fix | Delete
$res_index++;
[363] Fix | Delete
}
[364] Fix | Delete
return $files_existing;
[365] Fix | Delete
}
[366] Fix | Delete
[367] Fix | Delete
/**
[368] Fix | Delete
* This method is for calling outside of a cloud_backup() context. It constructs a list of services for which prune operations should be attempted, and then calls prune_retained_backups() if necessary upon them.
[369] Fix | Delete
*/
[370] Fix | Delete
public function do_prune_standalone() {
[371] Fix | Delete
global $updraftplus;
[372] Fix | Delete
[373] Fix | Delete
$services = (array) $updraftplus->just_one($updraftplus->jobdata_get('service'));
[374] Fix | Delete
[375] Fix | Delete
$prune_services = array();
[376] Fix | Delete
[377] Fix | Delete
foreach ($services as $service) {
[378] Fix | Delete
if ('none' === $service || '' == $service) continue;
[379] Fix | Delete
[380] Fix | Delete
$objname = "UpdraftPlus_BackupModule_${service}";
[381] Fix | Delete
if (!class_exists($objname) && file_exists(UPDRAFTPLUS_DIR.'/methods/'.$service.'.php')) {
[382] Fix | Delete
include_once(UPDRAFTPLUS_DIR.'/methods/'.$service.'.php');
[383] Fix | Delete
}
[384] Fix | Delete
if (class_exists($objname)) {
[385] Fix | Delete
$remote_obj = new $objname;
[386] Fix | Delete
$prune_services[$service]['all'] = array($remote_obj, null);
[387] Fix | Delete
} else {
[388] Fix | Delete
$updraftplus->log("Could not prune from service $service: remote method not found");
[389] Fix | Delete
}
[390] Fix | Delete
[391] Fix | Delete
}
[392] Fix | Delete
[393] Fix | Delete
if (!empty($prune_services)) $this->prune_retained_backups($prune_services);
[394] Fix | Delete
}
[395] Fix | Delete
[396] Fix | Delete
/**
[397] Fix | Delete
* Dispatch to the relevant function
[398] Fix | Delete
*
[399] Fix | Delete
* @param Array $backup_array List of archives for the backup
[400] Fix | Delete
*/
[401] Fix | Delete
public function cloud_backup($backup_array) {
[402] Fix | Delete
[403] Fix | Delete
global $updraftplus;
[404] Fix | Delete
[405] Fix | Delete
$services = (array) $updraftplus->just_one($updraftplus->jobdata_get('service'));
[406] Fix | Delete
$remote_storage_instances = $updraftplus->jobdata_get('remote_storage_instances', array());
[407] Fix | Delete
[408] Fix | Delete
// We need to make sure that the loop below actually runs
[409] Fix | Delete
if (empty($services)) $services = array('none');
[410] Fix | Delete
[411] Fix | Delete
$storage_objects_and_ids = UpdraftPlus_Storage_Methods_Interface::get_enabled_storage_objects_and_ids($services, $remote_storage_instances);
[412] Fix | Delete
[413] Fix | Delete
$total_instances_count = 0;
[414] Fix | Delete
[415] Fix | Delete
foreach ($storage_objects_and_ids as $service) {
[416] Fix | Delete
if ($service['object']->supports_feature('multi_options')) $total_instances_count += count($service['instance_settings']);
[417] Fix | Delete
}
[418] Fix | Delete
[419] Fix | Delete
$updraftplus->jobdata_set('jobstatus', 'clouduploading');
[420] Fix | Delete
[421] Fix | Delete
$updraftplus->register_wp_http_option_hooks();
[422] Fix | Delete
[423] Fix | Delete
$upload_status = $updraftplus->jobdata_get('uploading_substatus');
[424] Fix | Delete
if (!is_array($upload_status) || !isset($upload_status['t'])) {
[425] Fix | Delete
$upload_status = array('i' => 0, 'p' => 0, 't' => max(1, $total_instances_count)*count($backup_array));
[426] Fix | Delete
$updraftplus->jobdata_set('uploading_substatus', $upload_status);
[427] Fix | Delete
}
[428] Fix | Delete
[429] Fix | Delete
$do_prune = array();
[430] Fix | Delete
[431] Fix | Delete
// If there was no check-in last time, then attempt a different service first - in case a time-out on the attempted service leads to no activity and everything stopping
[432] Fix | Delete
if (count($services) >1 && $updraftplus->no_checkin_last_time) {
[433] Fix | Delete
$updraftplus->log('No check-in last time: will try a different remote service first');
[434] Fix | Delete
array_push($services, array_shift($services));
[435] Fix | Delete
// Make sure that the 'no worthwhile activity' detector isn't flumoxed by the starting of a new upload at 0%
[436] Fix | Delete
if ($updraftplus->current_resumption > 9) $updraftplus->jobdata_set('uploaded_lastreset', $updraftplus->current_resumption);
[437] Fix | Delete
if (1 == ($updraftplus->current_resumption % 2) && count($services)>2) array_push($services, array_shift($services));
[438] Fix | Delete
}
[439] Fix | Delete
[440] Fix | Delete
$errors_before_uploads = $updraftplus->error_count();
[441] Fix | Delete
[442] Fix | Delete
foreach ($services as $ind => $service) {
[443] Fix | Delete
try {
[444] Fix | Delete
$instance_id_count = 0;
[445] Fix | Delete
$total_instance_ids = ('none' !== $service && '' !== $service && $storage_objects_and_ids[$service]['object']->supports_feature('multi_options')) ? count($storage_objects_and_ids[$service]['instance_settings']) : 1;
[446] Fix | Delete
[447] Fix | Delete
// Used for logging by record_upload_chunk()
[448] Fix | Delete
$this->current_service = $service;
[449] Fix | Delete
[450] Fix | Delete
// Used when deciding whether to delete the local file
[451] Fix | Delete
$this->last_storage_instance = ($ind+1 >= count($services) && $instance_id_count+1 >= $total_instance_ids && $errors_before_uploads == $updraftplus->error_count()) ? true : false;
[452] Fix | Delete
$log_extra = $this->last_storage_instance ? ' (last)' : '';
[453] Fix | Delete
$updraftplus->log("Cloud backup selection (".($ind+1)."/".count($services)."): ".$service." with instance (".($instance_id_count+1)."/".$total_instance_ids.")".$log_extra);
[454] Fix | Delete
if (function_exists('set_time_limit')) @set_time_limit(UPDRAFTPLUS_SET_TIME_LIMIT);// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
[455] Fix | Delete
[456] Fix | Delete
if ('none' == $service || '' == $service) {
[457] Fix | Delete
$updraftplus->log('No remote despatch: user chose no remote backup service');
[458] Fix | Delete
// Still want to mark as "uploaded", to signal that nothing more needs doing. (Important on incremental runs with no cloud storage).
[459] Fix | Delete
foreach ($backup_array as $file) {
[460] Fix | Delete
if ($updraftplus->is_uploaded($file)) {
[461] Fix | Delete
$updraftplus->log("Already uploaded: $file");
[462] Fix | Delete
} else {
[463] Fix | Delete
$updraftplus->uploaded_file($file, true);
[464] Fix | Delete
}
[465] Fix | Delete
$fullpath = $this->updraft_dir.'/'.$file;
[466] Fix | Delete
if (file_exists($fullpath.'.list.tmp')) {
[467] Fix | Delete
$updraftplus->log("Deleting zip manifest ({$file}.list.tmp)");
[468] Fix | Delete
unlink($fullpath.'.list.tmp');
[469] Fix | Delete
}
[470] Fix | Delete
}
[471] Fix | Delete
$this->prune_retained_backups(array('none' => array('all' => array(null, null))));
[472] Fix | Delete
} elseif (!empty($storage_objects_and_ids[$service]['object']) && !$storage_objects_and_ids[$service]['object']->supports_feature('multi_options')) {
[473] Fix | Delete
$remote_obj = $storage_objects_and_ids[$service]['object'];
[474] Fix | Delete
[475] Fix | Delete
$do_prune = array_merge_recursive($do_prune, $this->upload_cloud($remote_obj, $service, $backup_array, ''));
[476] Fix | Delete
} elseif (!empty($storage_objects_and_ids[$service]['instance_settings'])) {
[477] Fix | Delete
foreach ($storage_objects_and_ids[$service]['instance_settings'] as $instance_id => $options) {
[478] Fix | Delete
[479] Fix | Delete
if ($instance_id_count > 0) {
[480] Fix | Delete
$this->last_storage_instance = ($ind+1 >= count($services) && $instance_id_count+1 >= $total_instance_ids && $errors_before_uploads == $updraftplus->error_count()) ? true : false;
[481] Fix | Delete
$log_extra = $this->last_storage_instance ? ' (last)' : '';
[482] Fix | Delete
$updraftplus->log("Cloud backup selection (".($ind+1)."/".count($services)."): ".$service." with instance (".($instance_id_count+1)."/".$total_instance_ids.")".$log_extra);
[483] Fix | Delete
}
[484] Fix | Delete
[485] Fix | Delete
// Used for logging by record_upload_chunk()
[486] Fix | Delete
$this->current_instance = $instance_id;
[487] Fix | Delete
[488] Fix | Delete
if (!isset($options['instance_enabled'])) $options['instance_enabled'] = 1;
[489] Fix | Delete
[490] Fix | Delete
// if $remote_storage_instances is not empty then we are looping over a list of instances the user wants to backup to so we want to ignore if the instance is enabled or not
[491] Fix | Delete
if (1 == $options['instance_enabled'] || !empty($remote_storage_instances)) {
[492] Fix | Delete
$remote_obj = $storage_objects_and_ids[$service]['object'];
[493] Fix | Delete
$remote_obj->set_options($options, true, $instance_id);
[494] Fix | Delete
$do_prune = array_merge_recursive($do_prune, $this->upload_cloud($remote_obj, $service, $backup_array, $instance_id));
[495] Fix | Delete
} else {
[496] Fix | Delete
$updraftplus->log("This instance id ($instance_id) is set as inactive.");
[497] Fix | Delete
}
[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