Edit File by line
/home/barbar84/www/wp-conte.../plugins/updraftp...
File: backup.php
} elseif (!empty($this->excluded_prefixes) && $this->is_entity_excluded_by_prefix($e)) {
[3000] Fix | Delete
$updraftplus->log("Entity excluded by configuration option (prefix): $use_stripped");
[3001] Fix | Delete
} elseif (!empty($this->excluded_wildcards) && $this->is_entity_excluded_by_wildcards($use_stripped)) {
[3002] Fix | Delete
$updraftplus->log("Entity excluded by configuration option (wildcards): $use_stripped");
[3003] Fix | Delete
} elseif (apply_filters('updraftplus_exclude_file', false, $deref, $use_stripped)) {
[3004] Fix | Delete
$updraftplus->log("Entity excluded by filter: $use_stripped");
[3005] Fix | Delete
} elseif (is_readable($deref)) {
[3006] Fix | Delete
$mtime = filemtime($deref);
[3007] Fix | Delete
if ($mtime > 0 && $mtime > $if_altered_since) {
[3008] Fix | Delete
$this->zipfiles_batched[$deref] = $use_path_when_storing.'/'.$e;
[3009] Fix | Delete
$this->makezip_recursive_batchedbytes += @filesize($deref);// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
[3010] Fix | Delete
// @touch($zipfile);
[3011] Fix | Delete
} else {
[3012] Fix | Delete
$this->zipfiles_skipped_notaltered[$deref] = $use_path_when_storing.'/'.$e;
[3013] Fix | Delete
}
[3014] Fix | Delete
} else {
[3015] Fix | Delete
$updraftplus->log("$deref: unreadable file (de-referenced from the link $e in $fullpath)");
[3016] Fix | Delete
$updraftplus->log(sprintf(__("%s: unreadable file - could not be backed up"), $deref), 'warning');
[3017] Fix | Delete
}
[3018] Fix | Delete
} elseif (is_dir($deref)) {
[3019] Fix | Delete
$this->makezip_recursive_add($deref, $use_path_when_storing.'/'.$e, $original_fullpath, $startlevels, $exclude);
[3020] Fix | Delete
}
[3021] Fix | Delete
} elseif (is_file($fullpath.'/'.$e)) {
[3022] Fix | Delete
$use_stripped = $stripped_storage_path.'/'.$e;
[3023] Fix | Delete
if (false !== ($fkey = array_search($use_stripped, $exclude))) {
[3024] Fix | Delete
$updraftplus->log("Entity excluded by configuration option: $use_stripped");
[3025] Fix | Delete
unset($exclude[$fkey]);
[3026] Fix | Delete
} elseif (!empty($this->excluded_extensions) && $this->is_entity_excluded_by_extension($e)) {
[3027] Fix | Delete
$updraftplus->log("Entity excluded by configuration option (extension): $use_stripped");
[3028] Fix | Delete
} elseif (!empty($this->excluded_prefixes) && $this->is_entity_excluded_by_prefix($e)) {
[3029] Fix | Delete
$updraftplus->log("Entity excluded by configuration option (prefix): $use_stripped");
[3030] Fix | Delete
} elseif (!empty($this->excluded_wildcards) && $this->is_entity_excluded_by_wildcards($use_stripped)) {
[3031] Fix | Delete
$updraftplus->log("Entity excluded by configuration option (wildcards): $use_stripped");
[3032] Fix | Delete
} elseif (apply_filters('updraftplus_exclude_file', false, $fullpath.'/'.$e)) {
[3033] Fix | Delete
$updraftplus->log("Entity excluded by filter: $use_stripped");
[3034] Fix | Delete
} elseif (is_readable($fullpath.'/'.$e)) {
[3035] Fix | Delete
$mtime = filemtime($fullpath.'/'.$e);
[3036] Fix | Delete
if ($mtime > 0 && $mtime > $if_altered_since) {
[3037] Fix | Delete
$this->zipfiles_batched[$fullpath.'/'.$e] = $use_path_when_storing.'/'.$e;
[3038] Fix | Delete
$this->makezip_recursive_batchedbytes += @filesize($fullpath.'/'.$e);// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
[3039] Fix | Delete
} else {
[3040] Fix | Delete
$this->zipfiles_skipped_notaltered[$fullpath.'/'.$e] = $use_path_when_storing.'/'.$e;
[3041] Fix | Delete
}
[3042] Fix | Delete
} else {
[3043] Fix | Delete
$updraftplus->log("$fullpath/$e: unreadable file");
[3044] Fix | Delete
$updraftplus->log(sprintf(__("%s: unreadable file - could not be backed up", 'updraftplus'), $use_path_when_storing.'/'.$e), 'warning', "unrfile-$e");
[3045] Fix | Delete
}
[3046] Fix | Delete
} elseif (is_dir($fullpath.'/'.$e)) {
[3047] Fix | Delete
$use_stripped = $stripped_storage_path.'/'.$e;
[3048] Fix | Delete
if ('wpcore' == $this->whichone && 'updraft' == $e && basename($use_path_when_storing) == 'wp-content' && (!defined('UPDRAFTPLUS_WPCORE_INCLUDE_UPDRAFT_DIRS') || !UPDRAFTPLUS_WPCORE_INCLUDE_UPDRAFT_DIRS)) {
[3049] Fix | Delete
// This test, of course, won't catch everything - it just aims to make things better by default
[3050] Fix | Delete
$updraftplus->log("Directory excluded for looking like a sub-site's internal UpdraftPlus directory (enable by defining UPDRAFTPLUS_WPCORE_INCLUDE_UPDRAFT_DIRS): ".$use_path_when_storing.'/'.$e);
[3051] Fix | Delete
} elseif (!empty($this->excluded_wildcards) && $this->is_entity_excluded_by_wildcards($use_stripped)) {
[3052] Fix | Delete
$updraftplus->log("Entity excluded by configuration option (wildcards): $use_stripped");
[3053] Fix | Delete
} else {
[3054] Fix | Delete
// no need to add_empty_dir here, as it gets done when we recurse
[3055] Fix | Delete
$this->makezip_recursive_add($fullpath.'/'.$e, $use_path_when_storing.'/'.$e, $original_fullpath, $startlevels, $exclude);
[3056] Fix | Delete
}
[3057] Fix | Delete
}
[3058] Fix | Delete
}
[3059] Fix | Delete
closedir($dir_handle);
[3060] Fix | Delete
} else {
[3061] Fix | Delete
$updraftplus->log("Unexpected: path ($use_path_when_storing) fails both is_file() and is_dir()");
[3062] Fix | Delete
}
[3063] Fix | Delete
[3064] Fix | Delete
return true;
[3065] Fix | Delete
[3066] Fix | Delete
}
[3067] Fix | Delete
[3068] Fix | Delete
/**
[3069] Fix | Delete
* Get a list of excluded extensions
[3070] Fix | Delete
*
[3071] Fix | Delete
* @param Array $exclude - settings passed in
[3072] Fix | Delete
*
[3073] Fix | Delete
* @return Array
[3074] Fix | Delete
*/
[3075] Fix | Delete
private function get_excluded_extensions($exclude) {
[3076] Fix | Delete
if (!is_array($exclude)) $exclude = array();
[3077] Fix | Delete
$exclude_extensions = array();
[3078] Fix | Delete
foreach ($exclude as $ex) {
[3079] Fix | Delete
if (preg_match('/^ext:(.+)$/i', $ex, $matches)) {
[3080] Fix | Delete
$exclude_extensions[] = strtolower($matches[1]);
[3081] Fix | Delete
}
[3082] Fix | Delete
}
[3083] Fix | Delete
[3084] Fix | Delete
if (defined('UPDRAFTPLUS_EXCLUDE_EXTENSIONS')) {
[3085] Fix | Delete
$exclude_from_define = explode(',', UPDRAFTPLUS_EXCLUDE_EXTENSIONS);
[3086] Fix | Delete
foreach ($exclude_from_define as $ex) {
[3087] Fix | Delete
$exclude_extensions[] = strtolower(trim($ex));
[3088] Fix | Delete
}
[3089] Fix | Delete
}
[3090] Fix | Delete
[3091] Fix | Delete
return $exclude_extensions;
[3092] Fix | Delete
}
[3093] Fix | Delete
[3094] Fix | Delete
/**
[3095] Fix | Delete
* Get a list of excluded prefixes
[3096] Fix | Delete
*
[3097] Fix | Delete
* @param Array $exclude - settings passed in
[3098] Fix | Delete
*
[3099] Fix | Delete
* @return Array - each is listed in lower case
[3100] Fix | Delete
*/
[3101] Fix | Delete
private function get_excluded_prefixes($exclude) {
[3102] Fix | Delete
if (!is_array($exclude)) $exclude = array();
[3103] Fix | Delete
$exclude_prefixes = array();
[3104] Fix | Delete
foreach ($exclude as $pref) {
[3105] Fix | Delete
if (preg_match('/^prefix:(.+)$/i', $pref, $matches)) {
[3106] Fix | Delete
$exclude_prefixes[] = strtolower($matches[1]);
[3107] Fix | Delete
}
[3108] Fix | Delete
}
[3109] Fix | Delete
return $exclude_prefixes;
[3110] Fix | Delete
}
[3111] Fix | Delete
[3112] Fix | Delete
/**
[3113] Fix | Delete
* List all the wildcard patterns from the given excluded items
[3114] Fix | Delete
*
[3115] Fix | Delete
* @param Array $exclude the list of excluded items which may contain not just wildcard patterns but also specific file/directory names as well
[3116] Fix | Delete
*
[3117] Fix | Delete
* $exclude argument may contains data in an array format like below:
[3118] Fix | Delete
* [
[3119] Fix | Delete
* "snapshots" // definitely not a wildcard parttern, this could be directories/files named `snapshots` which are located in the root/parent directory
[3120] Fix | Delete
* "2021/03/image.jpg", // not a wildcard parttern, this could be files/directories named `image.jpg` which are located in the 2021/03/ directory
[3121] Fix | Delete
* "ext:zip", // not a wildcard pattern, this is to exclude all files that end with `zip` extension
[3122] Fix | Delete
* "prefix:file-", // not a wildcard pattern, this is to exclude all files that begin with `file-` prefix
[3123] Fix | Delete
* "2021/04", // not a wildcard pattern, this is to exclude all files/directories which are located in the 2021/04 directory
[3124] Fix | Delete
* "backup*", // wildcard pattern that excludes all files/directories beginning with `backup` in the root/parent directory
[3125] Fix | Delete
* "2021/*optimise*", // wildcard pattern that excludes all files/directories that have `optimise` anywhere in their names in the `2021` directory
[3126] Fix | Delete
* "2021/04/*.tmp" // wildcard pattern that excludes all files/directories ending with `optimise` anywhere in their names in the `2021/04` directory
[3127] Fix | Delete
* ]
[3128] Fix | Delete
*
[3129] Fix | Delete
* @return Array an array of wilcard patterns
[3130] Fix | Delete
*
[3131] Fix | Delete
* After the $exclude has gone through the regex parsing step, only excluded items containing valid wildcard patterns got captured and will return them in an array in a format like below:
[3132] Fix | Delete
*
[3133] Fix | Delete
* [
[3134] Fix | Delete
* [
[3135] Fix | Delete
* "directory_path" => "",
[3136] Fix | Delete
* "pattern" => "backup*"
[3137] Fix | Delete
* ],
[3138] Fix | Delete
* [
[3139] Fix | Delete
* "directory_path" => "2021\",
[3140] Fix | Delete
* "pattern" => "*optimise*"
[3141] Fix | Delete
* ],
[3142] Fix | Delete
* [
[3143] Fix | Delete
* "directory_path" => "2021\04\",
[3144] Fix | Delete
* "pattern" => "*.tmp"
[3145] Fix | Delete
* ]
[3146] Fix | Delete
* ]
[3147] Fix | Delete
*/
[3148] Fix | Delete
private function get_excluded_wildcards($exclude) {
[3149] Fix | Delete
if (!is_array($exclude)) $exclude = array();
[3150] Fix | Delete
$excluded_wildcards = array();
[3151] Fix | Delete
foreach ($exclude as $wch) {
[3152] Fix | Delete
// https://regex101.com/r/dMFI0P/1/
[3153] Fix | Delete
if (preg_match('#(.*(?<!\\\)/)?(.*?(?<!\\\)\*.*)#i', $wch, $matches)) {
[3154] Fix | Delete
// the regex will make sure only excluded items containing valid wildcard patterns get captured, it will lookup for asterisk char(s) at the very end of the string right after the last path separator (if any). e.g. foo/bar/b*a*z
[3155] Fix | Delete
$excluded_wildcards[] = array(
[3156] Fix | Delete
// in case the excluded item has doubled separators (e.g. dir1//dir2//file) or if the user added a directory separator at the beginning then trim and/or replace them
[3157] Fix | Delete
'directory_path' => preg_replace(array('/^[\/\s]*/', '/\/\/*/', '/[\/\s]*$/'), array('', '/', ''), $matches[1]),
[3158] Fix | Delete
'pattern' => $matches[2]
[3159] Fix | Delete
);
[3160] Fix | Delete
}
[3161] Fix | Delete
}
[3162] Fix | Delete
return $excluded_wildcards;
[3163] Fix | Delete
}
[3164] Fix | Delete
[3165] Fix | Delete
/**
[3166] Fix | Delete
* Check whether or not the given entity(file/directory) is excluded from the backup by matching it against a set of wildcard patterns
[3167] Fix | Delete
*
[3168] Fix | Delete
* @param String $entity the file/directory's stripped path
[3169] Fix | Delete
* @return Boolean true if the entity is excluded, false otherwise
[3170] Fix | Delete
*/
[3171] Fix | Delete
private function is_entity_excluded_by_wildcards($entity) {
[3172] Fix | Delete
$entity_basename = untrailingslashit($entity);
[3173] Fix | Delete
$entity_basename = substr_replace($entity_basename, '', 0, (false === strrpos($entity_basename, '/') ? 0 : strrpos($entity_basename, '/') + 1));
[3174] Fix | Delete
foreach ($this->excluded_wildcards as $wch) {
[3175] Fix | Delete
if (!is_array($wch) || empty($wch)) continue;
[3176] Fix | Delete
if (substr_replace($entity, '', (int) strrpos($entity, '/'), strlen($entity) - (int) strrpos($entity, '/')) !== $wch['directory_path']) continue;
[3177] Fix | Delete
if ('*' == substr($wch['pattern'], -1, 1) && '*' == substr($wch['pattern'], 0, 1) && strlen($wch['pattern']) > 2) {
[3178] Fix | Delete
$wch['pattern'] = substr($wch['pattern'], 1, strlen($wch['pattern'])-2);
[3179] Fix | Delete
$wch['pattern'] = str_replace('\*', '*', $wch['pattern']);
[3180] Fix | Delete
if (strpos($entity_basename, $wch['pattern']) !== false) return true;
[3181] Fix | Delete
} elseif ('*' == substr($wch['pattern'], -1, 1) && strlen($wch['pattern']) > 1) {
[3182] Fix | Delete
$wch['pattern'] = substr($wch['pattern'], 0, strlen($wch['pattern'])-1);
[3183] Fix | Delete
$wch['pattern'] = str_replace('\*', '*', $wch['pattern']);
[3184] Fix | Delete
if (substr($entity_basename, 0, strlen($wch['pattern'])) == $wch['pattern']) return true;
[3185] Fix | Delete
} elseif ('*' == substr($wch['pattern'], 0, 1) && strlen($wch['pattern']) > 1) {
[3186] Fix | Delete
$wch['pattern'] = substr($wch['pattern'], 1);
[3187] Fix | Delete
$wch['pattern'] = str_replace('\*', '*', $wch['pattern']);
[3188] Fix | Delete
if (strlen($entity_basename) >= strlen($wch['pattern']) && substr($entity_basename, strlen($wch['pattern'])*-1) == $wch['pattern']) return true;
[3189] Fix | Delete
}
[3190] Fix | Delete
}
[3191] Fix | Delete
return false;
[3192] Fix | Delete
}
[3193] Fix | Delete
[3194] Fix | Delete
private function is_entity_excluded_by_extension($entity) {
[3195] Fix | Delete
foreach ($this->excluded_extensions as $ext) {
[3196] Fix | Delete
if (!$ext) continue;
[3197] Fix | Delete
$eln = strlen($ext);
[3198] Fix | Delete
if (strtolower(substr($entity, -$eln, $eln)) == $ext) return true;
[3199] Fix | Delete
}
[3200] Fix | Delete
return false;
[3201] Fix | Delete
}
[3202] Fix | Delete
[3203] Fix | Delete
private function is_entity_excluded_by_prefix($entity) {
[3204] Fix | Delete
$entity = basename($entity);
[3205] Fix | Delete
foreach ($this->excluded_prefixes as $pref) {
[3206] Fix | Delete
if (!$pref) continue;
[3207] Fix | Delete
$eln = strlen($pref);
[3208] Fix | Delete
if (strtolower(substr($entity, 0, $eln)) == $pref) return true;
[3209] Fix | Delete
}
[3210] Fix | Delete
return false;
[3211] Fix | Delete
}
[3212] Fix | Delete
[3213] Fix | Delete
private function unserialize_gz_cache_file($file) {
[3214] Fix | Delete
if (!$whandle = gzopen($file, 'r')) return false;
[3215] Fix | Delete
global $updraftplus;
[3216] Fix | Delete
$emptimes = 0;
[3217] Fix | Delete
$var = '';
[3218] Fix | Delete
while (!gzeof($whandle)) {
[3219] Fix | Delete
$bytes = @gzread($whandle, 1048576);// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
[3220] Fix | Delete
if (empty($bytes)) {
[3221] Fix | Delete
$emptimes++;
[3222] Fix | Delete
$updraftplus->log("Got empty gzread ($emptimes times)");
[3223] Fix | Delete
if ($emptimes>2) return false;
[3224] Fix | Delete
} else {
[3225] Fix | Delete
$var .= $bytes;
[3226] Fix | Delete
}
[3227] Fix | Delete
}
[3228] Fix | Delete
gzclose($whandle);
[3229] Fix | Delete
return unserialize($var);
[3230] Fix | Delete
}
[3231] Fix | Delete
[3232] Fix | Delete
/**
[3233] Fix | Delete
* Make Zip File.
[3234] Fix | Delete
*
[3235] Fix | Delete
* @param Array|String $source Caution: $source is allowed to be an array, not just a filename
[3236] Fix | Delete
* @param String $backup_file_basename Name of backup file
[3237] Fix | Delete
* @param String $whichone Backup entity type (e.g. 'plugins')
[3238] Fix | Delete
* @param Boolean $retry_on_error Set to retry upon error
[3239] Fix | Delete
* @return Boolean
[3240] Fix | Delete
*/
[3241] Fix | Delete
private function make_zipfile($source, $backup_file_basename, $whichone, $retry_on_error = true) {
[3242] Fix | Delete
[3243] Fix | Delete
global $updraftplus;
[3244] Fix | Delete
[3245] Fix | Delete
$original_index = $this->index;
[3246] Fix | Delete
[3247] Fix | Delete
$itext = (empty($this->index)) ? '' : ($this->index+1);
[3248] Fix | Delete
$destination_base = $backup_file_basename.'-'.$whichone.$itext.'.zip.tmp';
[3249] Fix | Delete
// $destination is the temporary file (ending in .tmp)
[3250] Fix | Delete
$destination = $this->updraft_dir.'/'.$destination_base;
[3251] Fix | Delete
[3252] Fix | Delete
// When to prefer PCL:
[3253] Fix | Delete
// - We were asked to
[3254] Fix | Delete
// - No zip extension present and no relevant method present
[3255] Fix | Delete
// The zip extension check is not redundant, because method_exists segfaults some PHP installs, leading to support requests
[3256] Fix | Delete
[3257] Fix | Delete
// We need meta-info about $whichone
[3258] Fix | Delete
$backupable_entities = $updraftplus->get_backupable_file_entities(true, false);
[3259] Fix | Delete
// This is only used by one corner-case in BinZip
[3260] Fix | Delete
// $this->make_zipfile_source = (isset($backupable_entities[$whichone])) ? $backupable_entities[$whichone] : $source;
[3261] Fix | Delete
$this->make_zipfile_source = (is_array($source) && isset($backupable_entities[$whichone])) ? (('uploads' == $whichone) ? dirname($backupable_entities[$whichone]) : $backupable_entities[$whichone]) : dirname($source);
[3262] Fix | Delete
[3263] Fix | Delete
$this->existing_files = array();
[3264] Fix | Delete
// Used for tracking compression ratios
[3265] Fix | Delete
$this->existing_files_rawsize = 0;
[3266] Fix | Delete
$this->existing_zipfiles_size = 0;
[3267] Fix | Delete
[3268] Fix | Delete
// Enumerate existing files
[3269] Fix | Delete
// Usually first_linked_index is zero; the exception being with more files, where previous zips' contents are irrelevant
[3270] Fix | Delete
for ($j = $this->first_linked_index; $j <= $this->index; $j++) {
[3271] Fix | Delete
$jtext = (0 == $j) ? '' : $j+1;
[3272] Fix | Delete
// This is, in a non-obvious way, compatible with filenames which indicate increments
[3273] Fix | Delete
// $j does not need to start at zero; it should start at the index which the current entity split at. However, this is not directly known, and can only be deduced from examining the filenames. And, for other indexes from before the current increment, the searched-for filename won't exist (even if there is no cloud storage). So, this indirectly results in the desired outcome when we start from $j=0.
[3274] Fix | Delete
$examine_zip = $this->updraft_dir.'/'.$backup_file_basename.'-'.$whichone.$jtext.'.zip'.(($j == $this->index) ? '.tmp' : '');
[3275] Fix | Delete
[3276] Fix | Delete
// This comes from https://wordpress.org/support/topic/updraftplus-not-moving-all-files-to-remote-server - where it appears that the jobdata's record of the split was done (i.e. database write), but the *earlier* rename of the .tmp file was not done (i.e. I/O lost). i.e. In theory, this should be impossible; but, the sychnronicity apparently cannot be fully relied upon in some setups. The check for the index being one behind is being conservative - there's no inherent reason why it couldn't be done for other indexes.
[3277] Fix | Delete
// Note that in this 'impossible' case, no backup data was being lost - the design still ensures that the on-disk backup is fine. The problem was a gap in the sequence numbering of the zip files, leading to user confusion.
[3278] Fix | Delete
// Other examples of this appear to be in HS#1001 and #1047
[3279] Fix | Delete
if ($j != $this->index && !file_exists($examine_zip)) {
[3280] Fix | Delete
$alt_examine_zip = $this->updraft_dir.'/'.$backup_file_basename.'-'.$whichone.$jtext.'.zip'.(($j == $this->index - 1) ? '.tmp' : '');
[3281] Fix | Delete
if ($alt_examine_zip != $examine_zip && file_exists($alt_examine_zip) && is_readable($alt_examine_zip) && filesize($alt_examine_zip)>0) {
[3282] Fix | Delete
$updraftplus->log("Looked-for zip file not found; but non-zero .tmp zip was, despite not being current index ($j != ".$this->index." - renaming zip (assume previous resumption's IO was lost before kill)");
[3283] Fix | Delete
if (rename($alt_examine_zip, $examine_zip)) {
[3284] Fix | Delete
clearstatcache();
[3285] Fix | Delete
} else {
[3286] Fix | Delete
$updraftplus->log("Rename failed - backup zips likely to not have sequential numbers (does not affect backup integrity, but can cause user confusion)");
[3287] Fix | Delete
}
[3288] Fix | Delete
}
[3289] Fix | Delete
}
[3290] Fix | Delete
[3291] Fix | Delete
// If the file exists, then we should grab its index of files inside, and sizes
[3292] Fix | Delete
// Then, when we come to write a file, we should check if it's already there, and only add if it is not
[3293] Fix | Delete
if (file_exists($examine_zip) && is_readable($examine_zip) && filesize($examine_zip) > 0) {
[3294] Fix | Delete
[3295] Fix | Delete
// Do not use (which also means do not create) a manifest if the file is still a .tmp file, since this may not be complete. If we are in this place in the code from a resumption, creating a manifest here will mean the manifest becomes out-of-date if further files are added.
[3296] Fix | Delete
$this->populate_existing_files_list($examine_zip, substr($examine_zip, -4, 4) === '.zip');
[3297] Fix | Delete
[3298] Fix | Delete
// try_split is true if there have been no check-ins recently - or if it needs to be split anyway
[3299] Fix | Delete
if ($j == $this->index) {
[3300] Fix | Delete
if ($this->try_split) {
[3301] Fix | Delete
if (filesize($examine_zip) > 50*1048576) {
[3302] Fix | Delete
// We could, as a future enhancement, save this back to the job data, if we see a case that needs it
[3303] Fix | Delete
$this->zip_split_every = max(
[3304] Fix | Delete
(int) $this->zip_split_every/2,
[3305] Fix | Delete
UPDRAFTPLUS_SPLIT_MIN*1048576,
[3306] Fix | Delete
min(filesize($examine_zip)-1048576, $this->zip_split_every)
[3307] Fix | Delete
);
[3308] Fix | Delete
$updraftplus->jobdata_set('split_every', (int) ($this->zip_split_every/1048576));
[3309] Fix | Delete
$updraftplus->log("No check-in on last two runs; bumping index and reducing zip split to: ".round($this->zip_split_every/1048576, 1)." MB");
[3310] Fix | Delete
$do_bump_index = true;
[3311] Fix | Delete
}
[3312] Fix | Delete
unset($this->try_split);
[3313] Fix | Delete
} elseif (filesize($examine_zip) > $this->zip_split_every) {
[3314] Fix | Delete
$updraftplus->log(sprintf("Zip size is at/near split limit (%s MB / %s MB) - bumping index (from: %d)", filesize($examine_zip), round($this->zip_split_every/1048576, 1), $this->index));
[3315] Fix | Delete
$do_bump_index = true;
[3316] Fix | Delete
}
[3317] Fix | Delete
}
[3318] Fix | Delete
[3319] Fix | Delete
} elseif (file_exists($examine_zip)) {
[3320] Fix | Delete
$updraftplus->log("Zip file already exists, but is not readable or was zero-sized; will remove: ".basename($examine_zip));
[3321] Fix | Delete
@unlink($examine_zip);// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
[3322] Fix | Delete
}
[3323] Fix | Delete
}
[3324] Fix | Delete
[3325] Fix | Delete
$this->zip_last_ratio = ($this->existing_files_rawsize > 0) ? ($this->existing_zipfiles_size/$this->existing_files_rawsize) : 1;
[3326] Fix | Delete
[3327] Fix | Delete
$this->zipfiles_added = 0;
[3328] Fix | Delete
$this->zipfiles_added_thisrun = 0;
[3329] Fix | Delete
$this->zipfiles_dirbatched = array();
[3330] Fix | Delete
$this->zipfiles_batched = array();
[3331] Fix | Delete
$this->zipfiles_skipped_notaltered = array();
[3332] Fix | Delete
$this->zipfiles_lastwritetime = time();
[3333] Fix | Delete
$this->zip_basename = $this->updraft_dir.'/'.$backup_file_basename.'-'.$whichone;
[3334] Fix | Delete
[3335] Fix | Delete
if (!empty($do_bump_index)) $this->bump_index();
[3336] Fix | Delete
[3337] Fix | Delete
$error_occurred = false;
[3338] Fix | Delete
[3339] Fix | Delete
// Store this in its original form
[3340] Fix | Delete
$this->source = $source;
[3341] Fix | Delete
[3342] Fix | Delete
// Reset. This counter is used only with PcLZip, to decide if it's better to do it all-in-one
[3343] Fix | Delete
$this->makezip_recursive_batchedbytes = 0;
[3344] Fix | Delete
if (!is_array($source)) $source = array($source);
[3345] Fix | Delete
[3346] Fix | Delete
$exclude = $updraftplus->get_exclude($whichone);
[3347] Fix | Delete
[3348] Fix | Delete
$files_enumerated_at = $updraftplus->jobdata_get('files_enumerated_at');
[3349] Fix | Delete
if (!is_array($files_enumerated_at)) $files_enumerated_at = array();
[3350] Fix | Delete
$files_enumerated_at[$whichone] = time();
[3351] Fix | Delete
$updraftplus->jobdata_set('files_enumerated_at', $files_enumerated_at);
[3352] Fix | Delete
[3353] Fix | Delete
$this->makezip_if_altered_since = is_array($this->altered_since) ? (isset($this->altered_since[$whichone]) ? $this->altered_since[$whichone] : -1) : -1;
[3354] Fix | Delete
[3355] Fix | Delete
// Reset
[3356] Fix | Delete
$got_uploads_from_cache = false;
[3357] Fix | Delete
[3358] Fix | Delete
// Uploads: can/should we get it back from the cache?
[3359] Fix | Delete
// || 'others' == $whichone
[3360] Fix | Delete
if (('uploads' == $whichone || 'others' == $whichone) && function_exists('gzopen') && function_exists('gzread')) {
[3361] Fix | Delete
$use_cache_files = false;
[3362] Fix | Delete
$cache_file_base = $this->zip_basename.'-cachelist-'.$this->makezip_if_altered_since;
[3363] Fix | Delete
// Cache file suffixes: -zfd.gz.tmp, -zfb.gz.tmp, -info.tmp, (possible)-zfs.gz.tmp
[3364] Fix | Delete
if (file_exists($cache_file_base.'-zfd.gz.tmp') && file_exists($cache_file_base.'-zfb.gz.tmp') && file_exists($cache_file_base.'-info.tmp')) {
[3365] Fix | Delete
// Cache files exist; shall we use them?
[3366] Fix | Delete
$mtime = filemtime($cache_file_base.'-zfd.gz.tmp');
[3367] Fix | Delete
// Require < 30 minutes old
[3368] Fix | Delete
if (time() - $mtime < 1800) {
[3369] Fix | Delete
$use_cache_files = true;
[3370] Fix | Delete
}
[3371] Fix | Delete
$any_failures = false;
[3372] Fix | Delete
if ($use_cache_files) {
[3373] Fix | Delete
$var = $this->unserialize_gz_cache_file($cache_file_base.'-zfd.gz.tmp');
[3374] Fix | Delete
if (is_array($var)) {
[3375] Fix | Delete
$this->zipfiles_dirbatched = $var;
[3376] Fix | Delete
$var = $this->unserialize_gz_cache_file($cache_file_base.'-zfb.gz.tmp');
[3377] Fix | Delete
if (is_array($var)) {
[3378] Fix | Delete
$this->zipfiles_batched = $var;
[3379] Fix | Delete
if (file_exists($cache_file_base.'-info.tmp')) {
[3380] Fix | Delete
$var = maybe_unserialize(file_get_contents($cache_file_base.'-info.tmp'));
[3381] Fix | Delete
if (is_array($var) && isset($var['makezip_recursive_batchedbytes'])) {
[3382] Fix | Delete
$this->makezip_recursive_batchedbytes = $var['makezip_recursive_batchedbytes'];
[3383] Fix | Delete
if (file_exists($cache_file_base.'-zfs.gz.tmp')) {
[3384] Fix | Delete
$var = $this->unserialize_gz_cache_file($cache_file_base.'-zfs.gz.tmp');
[3385] Fix | Delete
if (is_array($var)) {
[3386] Fix | Delete
$this->zipfiles_skipped_notaltered = $var;
[3387] Fix | Delete
} else {
[3388] Fix | Delete
$any_failures = true;
[3389] Fix | Delete
}
[3390] Fix | Delete
} else {
[3391] Fix | Delete
$this->zipfiles_skipped_notaltered = array();
[3392] Fix | Delete
}
[3393] Fix | Delete
} else {
[3394] Fix | Delete
$any_failures = true;
[3395] Fix | Delete
}
[3396] Fix | Delete
}
[3397] Fix | Delete
} else {
[3398] Fix | Delete
$any_failures = true;
[3399] Fix | Delete
}
[3400] Fix | Delete
} else {
[3401] Fix | Delete
$any_failures = true;
[3402] Fix | Delete
}
[3403] Fix | Delete
if ($any_failures) {
[3404] Fix | Delete
$updraftplus->log("Failed to recover file lists from existing cache files");
[3405] Fix | Delete
// Reset it all
[3406] Fix | Delete
$this->zipfiles_skipped_notaltered = array();
[3407] Fix | Delete
$this->makezip_recursive_batchedbytes = 0;
[3408] Fix | Delete
$this->zipfiles_batched = array();
[3409] Fix | Delete
$this->zipfiles_dirbatched = array();
[3410] Fix | Delete
} else {
[3411] Fix | Delete
$updraftplus->log("File lists recovered from cache files; sizes: ".count($this->zipfiles_batched).", ".count($this->zipfiles_batched).", ".count($this->zipfiles_skipped_notaltered).")");
[3412] Fix | Delete
$got_uploads_from_cache = true;
[3413] Fix | Delete
}
[3414] Fix | Delete
}
[3415] Fix | Delete
}
[3416] Fix | Delete
}
[3417] Fix | Delete
[3418] Fix | Delete
$time_counting_began = time();
[3419] Fix | Delete
[3420] Fix | Delete
$this->excluded_extensions = $this->get_excluded_extensions($exclude);
[3421] Fix | Delete
$this->excluded_prefixes = $this->get_excluded_prefixes($exclude);
[3422] Fix | Delete
$this->excluded_wildcards = $this->get_excluded_wildcards($exclude);
[3423] Fix | Delete
[3424] Fix | Delete
foreach ($source as $element) {
[3425] Fix | Delete
// makezip_recursive_add($fullpath, $use_path_when_storing, $original_fullpath, $startlevels = 1, $exclude_array)
[3426] Fix | Delete
if ('uploads' == $whichone) {
[3427] Fix | Delete
if (empty($got_uploads_from_cache)) {
[3428] Fix | Delete
$dirname = dirname($element);
[3429] Fix | Delete
$basename = $this->basename($element);
[3430] Fix | Delete
$add_them = $this->makezip_recursive_add($element, basename($dirname).'/'.$basename, $element, 2, $exclude);
[3431] Fix | Delete
} else {
[3432] Fix | Delete
$add_them = true;
[3433] Fix | Delete
}
[3434] Fix | Delete
} else {
[3435] Fix | Delete
if (empty($got_uploads_from_cache)) {
[3436] Fix | Delete
$add_them = $this->makezip_recursive_add($element, $this->basename($element), $element, 1, $exclude);
[3437] Fix | Delete
} else {
[3438] Fix | Delete
$add_them = true;
[3439] Fix | Delete
}
[3440] Fix | Delete
}
[3441] Fix | Delete
if (is_wp_error($add_them) || false === $add_them) $error_occurred = true;
[3442] Fix | Delete
}
[3443] Fix | Delete
[3444] Fix | Delete
$time_counting_ended = time();
[3445] Fix | Delete
[3446] Fix | Delete
// Cache the file scan, if it looks like it'll be useful
[3447] Fix | Delete
// We use gzip to reduce the size as on hosts which limit disk I/O, the cacheing may make things worse
[3448] Fix | Delete
// || 'others' == $whichone
[3449] Fix | Delete
if (('uploads' == $whichone || 'others' == $whichone) && !$error_occurred && function_exists('gzopen') && function_exists('gzwrite')) {
[3450] Fix | Delete
$cache_file_base = $this->zip_basename.'-cachelist-'.$this->makezip_if_altered_since;
[3451] Fix | Delete
[3452] Fix | Delete
// Just approximate - we're trying to avoid an otherwise-unpredictable PHP fatal error. Cacheing only happens if file enumeration took a long time - so presumably there are very many.
[3453] Fix | Delete
$memory_needed_estimate = 0;
[3454] Fix | Delete
foreach ($this->zipfiles_batched as $k => $v) {
[3455] Fix | Delete
$memory_needed_estimate += strlen($k)+strlen($v)+12;
[3456] Fix | Delete
}
[3457] Fix | Delete
[3458] Fix | Delete
// We haven't bothered to check if we just fetched the files from cache, as that shouldn't take a long time and so shouldn't trigger this
[3459] Fix | Delete
// Let us suppose we need 15% overhead for gzipping
[3460] Fix | Delete
[3461] Fix | Delete
$memory_limit = ini_get('memory_limit');
[3462] Fix | Delete
$memory_usage = round(@memory_get_usage(false)/1048576, 1);// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
[3463] Fix | Delete
$memory_usage2 = round(@memory_get_usage(true)/1048576, 1);// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
[3464] Fix | Delete
[3465] Fix | Delete
if ($time_counting_ended-$time_counting_began > 20 && $updraftplus->verify_free_memory($memory_needed_estimate*0.15) && $whandle = gzopen($cache_file_base.'-zfb.gz.tmp', 'w')) {
[3466] Fix | Delete
$updraftplus->log("File counting took a long time (".($time_counting_ended - $time_counting_began)."s); will attempt to cache results (memory_limit: $memory_limit (used: ${memory_usage}M | ${memory_usage2}M), estimated uncompressed bytes: ".round($memory_needed_estimate/1024, 1)." Kb)");
[3467] Fix | Delete
[3468] Fix | Delete
$buf = 'a:'.count($this->zipfiles_batched).':{';
[3469] Fix | Delete
foreach ($this->zipfiles_batched as $file => $add_as) {
[3470] Fix | Delete
$k = addslashes($file);
[3471] Fix | Delete
$v = addslashes($add_as);
[3472] Fix | Delete
$buf .= 's:'.strlen($k).':"'.$k.'";s:'.strlen($v).':"'.$v.'";';
[3473] Fix | Delete
if (strlen($buf) > 1048576) {
[3474] Fix | Delete
gzwrite($whandle, $buf, strlen($buf));
[3475] Fix | Delete
$buf = '';
[3476] Fix | Delete
}
[3477] Fix | Delete
}
[3478] Fix | Delete
$buf .= '}';
[3479] Fix | Delete
$final = gzwrite($whandle, $buf);
[3480] Fix | Delete
unset($buf);
[3481] Fix | Delete
[3482] Fix | Delete
if (!$final) {
[3483] Fix | Delete
@unlink($cache_file_base.'-zfb.gz.tmp');// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
[3484] Fix | Delete
@gzclose($whandle);// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
[3485] Fix | Delete
} else {
[3486] Fix | Delete
gzclose($whandle);
[3487] Fix | Delete
if (!empty($this->zipfiles_skipped_notaltered)) {
[3488] Fix | Delete
if ($shandle = gzopen($cache_file_base.'-zfs.gz.tmp', 'w')) {
[3489] Fix | Delete
if (!gzwrite($shandle, serialize($this->zipfiles_skipped_notaltered))) {
[3490] Fix | Delete
$aborted_on_skipped = true;
[3491] Fix | Delete
}
[3492] Fix | Delete
gzclose($shandle);
[3493] Fix | Delete
} else {
[3494] Fix | Delete
$aborted_on_skipped = true;
[3495] Fix | Delete
}
[3496] Fix | Delete
}
[3497] Fix | Delete
if (!empty($aborted_on_skipped)) {
[3498] Fix | Delete
@unlink($cache_file_base.'-zfs.gz.tmp');// phpcs:ignore Generic.PHP.NoSilencedErrors.Discouraged
[3499] Fix | Delete
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function