PluginProbe ʕ •ᴥ•ʔ
UpdraftPlus: WP Backup & Migration Plugin / 1.11.26
UpdraftPlus: WP Backup & Migration Plugin v1.11.26
1.26.4 1.26.3 1.9.19 1.9.25 1.9.26 1.9.30 1.9.31 1.9.32 1.9.4 1.9.40 1.9.41 1.9.42 1.9.43 1.9.44 1.9.45 1.9.46 1.9.5 1.9.50 1.9.51 1.9.60 1.9.62 1.9.63 1.9.64 1.11.12 1.4.8 1.11.15 1.4.9 1.11.17 1.5.16 1.11.18 1.5.20 1.11.2 1.5.21 1.11.20 1.5.22 1.11.23 1.5.5 1.11.24 1.5.6 1.11.25 1.5.7 1.11.26 1.5.8 1.11.27 1.5.9 1.11.28 1.6.1 1.11.3 1.6.17 1.11.4 1.6.2 1.11.5 1.6.46 1.11.8 1.7.0 1.11.9 1.7.1 1.12.0 1.7.18 1.12.1 1.7.20 1.12.12 1.7.3 1.12.13 1.7.34 1.12.15 1.7.35 1.12.17 1.7.39 1.12.2 1.7.40 1.12.20 1.7.41 1.12.23 1.8.1 1.12.24 1.8.11 1.12.25 1.8.12 1.12.28 1.8.13 1.12.29 1.8.2 1.12.30 1.8.5 1.12.32 1.8.8 1.12.34 1.9.0 1.12.35 1.9.13 1.12.37 1.9.15 1.12.39 1.9.17 1.12.4 1.12.40 1.12.6 1.13.1 1.13.11 1.13.12 1.13.15 1.13.16 1.13.2 1.13.3 1.13.4 1.13.5 1.13.6 1.13.7 1.13.8 1.13.9 1.14.10 1.14.11 1.14.12 1.14.13 1.14.2 1.14.3 1.14.4 1.14.5 1.14.7 1.14.9 1.15.0 1.15.2 1.15.3 1.15.5 1.15.6 1.15.7 1.16.0 1.16.10 1.16.11 1.16.12 1.16.13 1.16.14 1.16.15 1.16.16 1.16.17 1.16.20 1.16.21 1.16.22 1.16.23 1.16.24 1.16.25 1.16.26 1.16.28 1.16.29 1.16.32 1.16.34 1.16.35 1.16.36 1.16.37 1.16.4 1.16.40 1.16.41 1.16.42 1.16.43 1.16.44 1.16.45 1.16.46 1.16.47 1.16.48 1.16.49 1.16.5 1.16.50 1.16.51 1.16.53 1.16.55 1.16.56 1.16.59 1.16.6 1.16.60 1.16.61 1.16.62 1.16.63 1.16.64 1.16.65 1.16.66 1.16.67 1.16.68 1.16.69 1.16.7 1.16.8 1.16.9 1.2.0 1.2.1 1.2.10 1.2.11 1.2.12 1.2.14 1.2.15 1.2.16 1.2.17 1.2.19 1.2.2 1.2.20 1.2.24 1.2.25 1.2.26 1.2.27 1.2.28 1.2.29 1.2.3 1.2.30 1.2.31 1.2.33 1.2.35 1.2.36 1.2.38 1.2.39 1.2.4 1.2.40 1.2.41 1.2.42 1.2.43 1.2.44 1.2.45 1.2.46 1.2.5 1.2.7 1.2.8 1.2.9 1.22.1 1.22.10 1.22.11 1.22.12 1.22.14 1.22.15 1.22.16 1.22.17 1.22.18 1.22.19 1.22.20 1.22.21 1.22.22 1.22.23 1.22.24 1.22.3 1.22.4 1.22.5 1.22.6 1.22.7 1.22.8 1.22.9 1.23.1 1.23.10 1.23.11 1.23.12 1.23.13 1.23.15 1.23.16 1.23.2 1.23.3 1.23.4 1.23.5 1.23.6 1.23.7 1.23.8 1.23.9 1.24.1 1.24.10 1.24.11 1.24.12 1.24.2 trunk 1.24.3 0.7.4 1.24.4 0.7.7 1.24.5 0.8.28 1.24.6 0.8.29 1.24.7 0.8.30 1.24.8 0.8.31 1.24.9 0.8.32 1.25.1 0.8.33 1.25.2 0.8.36 1.25.3 0.8.37 1.25.5 0.8.50 1.25.6 0.8.51 1.25.7 0.9.1 1.25.8 0.9.10 1.25.9 0.9.11 1.26.1 0.9.12 1.26.2 0.9.2 1.3.10 0.9.20 1.3.12 0.9.21 1.3.14 0.9.22 1.3.15 1.0.10 1.3.17 1.0.11 1.3.18 1.0.12 1.3.19 1.0.15 1.3.2 1.0.16 1.3.20 1.0.18 1.3.22 1.0.20 1.3.23 1.0.3 1.3.24 1.0.4 1.3.25 1.0.5 1.3.3 1.0.6 1.3.4 1.0.7 1.3.6 1.0.8 1.3.7 1.0.9 1.3.8 1.1.0 1.3.9 1.1.10 1.4.0 1.1.11 1.4.10 1.1.12 1.4.11 1.1.13 1.4.12 1.1.14 1.4.13 1.1.15 1.4.14 1.1.16 1.4.15 1.1.17 1.4.2 1.1.2 1.4.27 1.1.3 1.4.28 1.1.5 1.4.29 1.1.6 1.4.30 1.1.8 1.4.4 1.1.9 1.4.48 1.10.1 1.4.5 1.10.3 1.4.6 1.11.1 1.4.7
updraftplus / class-zip.php
updraftplus Last commit date
addons 13 years ago css 10 years ago images 10 years ago includes 10 years ago languages 10 years ago methods 10 years ago vendor 10 years ago admin.php 10 years ago backup.php 10 years ago class-updraftplus.php 10 years ago class-zip.php 10 years ago clean-composer.sh 10 years ago composer.json 10 years ago composer.lock 10 years ago example-decrypt.php 10 years ago index.html 10 years ago options.php 10 years ago readme.txt 10 years ago restorer.php 10 years ago updraftplus.php 10 years ago
class-zip.php
326 lines
1 <?php
2
3 if (!defined ('ABSPATH')) die('No direct access allowed');
4
5 if (class_exists('ZipArchive')):
6 # We just add a last_error variable for comaptibility with our UpdraftPlus_PclZip object
7 class UpdraftPlus_ZipArchive extends ZipArchive {
8 public $last_error = 'Unknown: ZipArchive does not return error messages';
9 }
10 endif;
11
12 class UpdraftPlus_BinZip extends UpdraftPlus_PclZip {
13
14 private $binzip;
15
16 public function __construct() {
17 global $updraftplus_backup;
18 $this->binzip = $updraftplus_backup->binzip;
19 if (!is_string($this->binzip)) {
20 $this->last_error = "No binary zip was found";
21 return false;
22 }
23 return parent::__construct();
24 }
25
26 public function addFile($file, $add_as) {
27
28 global $updraftplus;
29 # Get the directory that $add_as is relative to
30 $base = $updraftplus->str_lreplace($add_as, '', $file);
31
32 if ($file == $base) {
33 // Shouldn't happen; but see: https://bugs.php.net/bug.php?id=62119
34 $updraftplus->log("File skipped due to unexpected name mismatch (locale: ".setlocale(LC_CTYPE, "0")."): $file", 'notice', false, true);
35 } else {
36 $rdirname = untrailingslashit($base);
37 # Note: $file equals $rdirname/$add_as
38 $this->addfiles[$rdirname][] = $add_as;
39 }
40
41 }
42
43 # The standard zip binary cannot list; so we use PclZip for that
44 # Do the actual write-out - it is assumed that close() is where this is done. Needs to return true/false
45 public function close() {
46
47 if (empty($this->pclzip)) {
48 $this->last_error = 'Zip file was not opened';
49 return false;
50 }
51
52 global $updraftplus, $updraftplus_backup;
53 $updraft_dir = $updraftplus->backups_dir_location();
54
55 $activity = false;
56
57 # BinZip does not like zero-sized zip files
58 if (file_exists($this->path) && 0 == filesize($this->path)) @unlink($this->path);
59
60 $descriptorspec = array(
61 0 => array('pipe', 'r'),
62 1 => array('pipe', 'w'),
63 2 => array('pipe', 'w')
64 );
65 $exec = $this->binzip;
66 if (defined('UPDRAFTPLUS_BINZIP_OPTS') && UPDRAFTPLUS_BINZIP_OPTS) $exec .= ' '.UPDRAFTPLUS_BINZIP_OPTS;
67 $exec .= " -v -@ ".escapeshellarg($this->path);
68
69 $last_recorded_alive = time();
70 $something_useful_happened = $updraftplus->something_useful_happened;
71 $orig_size = file_exists($this->path) ? filesize($this->path) : 0;
72 $last_size = $orig_size;
73 clearstatcache();
74
75 $added_dirs_yet = false;
76
77 # If there are no files to add, but there are empty directories, then we need to make sure the directories actually get added
78 if (0 == count($this->addfiles) && 0 < count($this->adddirs)) {
79 $dir = realpath($updraftplus_backup->make_zipfile_source);
80 $this->addfiles[$dir] = '././.';
81 }
82 // Loop over each destination directory name
83 foreach ($this->addfiles as $rdirname => $files) {
84
85 $process = proc_open($exec, $descriptorspec, $pipes, $rdirname);
86
87 if (!is_resource($process)) {
88 $updraftplus->log('BinZip error: proc_open failed');
89 $this->last_error = 'BinZip error: proc_open failed';
90 return false;
91 }
92
93 if (!$added_dirs_yet) {
94 # Add the directories - (in fact, with binzip, non-empty directories automatically have their entries added; but it doesn't hurt to add them explicitly)
95 foreach ($this->adddirs as $dir) {
96 fwrite($pipes[0], $dir."/\n");
97 }
98 $added_dirs_yet=true;
99 }
100
101 $read = array($pipes[1], $pipes[2]);
102 $except = null;
103
104 if (!is_array($files) || 0 == count($files)) {
105 fclose($pipes[0]);
106 $write = array();
107 } else {
108 $write = array($pipes[0]);
109 }
110
111 while ((!feof($pipes[1]) || !feof($pipes[2]) || (is_array($files) && count($files)>0)) && false !== ($changes = @stream_select($read, $write, $except, 0, 200000))) {
112
113 if (is_array($write) && in_array($pipes[0], $write) && is_array($files) && count($files)>0) {
114 $file = array_pop($files);
115 // Send the list of files on stdin
116 fwrite($pipes[0], $file."\n");
117 if (0 == count($files)) fclose($pipes[0]);
118 }
119
120 if (is_array($read) && in_array($pipes[1], $read)) {
121 $w = fgets($pipes[1]);
122 // Logging all this really slows things down; use debug to mitigate
123 if ($w && $updraftplus_backup->debug) $updraftplus->log("Output from zip: ".trim($w), 'debug');
124 if (time() > $last_recorded_alive + 5) {
125 $updraftplus->record_still_alive();
126 $last_recorded_alive = time();
127 }
128 if (file_exists($this->path)) {
129 $new_size = @filesize($this->path);
130 if (!$something_useful_happened && $new_size > $orig_size + 20) {
131 $updraftplus->something_useful_happened();
132 $something_useful_happened = true;
133 }
134 clearstatcache();
135 # Log when 20% bigger or at least every 50Mb
136 if ($new_size > $last_size*1.2 || $new_size > $last_size + 52428800) {
137 $updraftplus->log(basename($this->path).sprintf(": size is now: %.2f Mb", round($new_size/1048576,1)));
138 $last_size = $new_size;
139 }
140 }
141 }
142
143 if (is_array($read) && in_array($pipes[2], $read)) {
144 $last_error = fgets($pipes[2]);
145 if (!empty($last_error)) $this->last_error = rtrim($last_error);
146 }
147
148 // Re-set
149 $read = array($pipes[1], $pipes[2]);
150 $write = (is_array($files) && count($files) >0) ? array($pipes[0]) : array();
151 $except = null;
152
153 }
154
155 fclose($pipes[1]);
156 fclose($pipes[2]);
157
158 $ret = proc_close($process);
159
160 if ($ret != 0 && $ret != 12) {
161 if ($ret < 128) {
162 $updraftplus->log("Binary zip: error (code: $ret - look it up in the Diagnostics section of the zip manual at http://www.info-zip.org/mans/zip.html for interpretation... and also check that your hosting account quota is not full)");
163 } else {
164 $updraftplus->log("Binary zip: error (code: $ret - a code above 127 normally means that the zip process was deliberately killed ... and also check that your hosting account quota is not full)");
165 }
166 if (!empty($w) && !$updraftplus_backup->debug) $updraftplus->log("Last output from zip: ".trim($w), 'debug');
167 return false;
168 }
169
170 unset($this->addfiles[$rdirname]);
171 }
172
173 return true;
174 }
175
176 }
177
178 # A ZipArchive compatibility layer, with behaviour sufficient for our usage of ZipArchive
179 class UpdraftPlus_PclZip {
180
181 protected $pclzip;
182 protected $path;
183 protected $addfiles;
184 protected $adddirs;
185 private $statindex;
186 private $include_mtime = false;
187 public $last_error;
188
189 public function __construct() {
190 $this->addfiles = array();
191 $this->adddirs = array();
192 // Put this in a non-backed-up, writeable location, to make sure that huge temporary files aren't created and then added to the backup - and that we have somewhere writable
193 global $updraftplus;
194 if (!defined('PCLZIP_TEMPORARY_DIR')) define('PCLZIP_TEMPORARY_DIR', trailingslashit($updraftplus->backups_dir_location()));
195 }
196
197 # Used to include mtime in statindex (by default, not done - to save memory; probably a bit paranoid)
198 public function ud_include_mtime() {
199 $this->include_mtime = true;
200 }
201
202 public function __get($name) {
203 if ($name != 'numFiles') return null;
204
205 if (empty($this->pclzip)) return false;
206
207 $statindex = $this->pclzip->listContent();
208
209 if (empty($statindex)) {
210 $this->statindex=array();
211 return 0;
212 }
213
214 $result = array();
215 foreach ($statindex as $i => $file) {
216 if (!isset($statindex[$i]['folder']) || 0 == $statindex[$i]['folder']) {
217 $result[] = $file;
218 }
219 unset($statindex[$i]);
220 }
221
222 $this->statindex=$result;
223
224 return count($this->statindex);
225
226 }
227
228 public function statIndex($i) {
229 if (empty($this->statindex[$i])) return array('name' => null, 'size' => 0);
230 $v = array('name' => $this->statindex[$i]['filename'], 'size' => $this->statindex[$i]['size']);
231 if ($this->include_mtime) $v['mtime'] = $this->statindex[$i]['mtime'];
232 return $v;
233 }
234
235 public function open($path, $flags = 0) {
236 if(!class_exists('PclZip')) include_once(ABSPATH.'/wp-admin/includes/class-pclzip.php');
237 if(!class_exists('PclZip')) {
238 $this->last_error = "No PclZip class was found";
239 return false;
240 }
241
242 # Route around PHP bug (exact version with the problem not known)
243 $ziparchive_create_match = (version_compare(PHP_VERSION, '5.2.12', '>') && defined('ZIPARCHIVE::CREATE')) ? ZIPARCHIVE::CREATE : 1;
244
245 if ($flags == $ziparchive_create_match && file_exists($path)) @unlink($path);
246
247 $this->pclzip = new PclZip($path);
248 if (empty($this->pclzip)) {
249 $this->last_error = 'Could not get a PclZip object';
250 return false;
251 }
252
253 # Make the empty directory we need to implement addEmptyDir()
254 global $updraftplus;
255 $updraft_dir = $updraftplus->backups_dir_location();
256 if (!is_dir($updraft_dir.'/emptydir') && !mkdir($updraft_dir.'/emptydir')) {
257 $this->last_error = "Could not create empty directory ($updraft_dir/emptydir)";
258 return false;
259 }
260
261 $this->path = $path;
262
263 return true;
264
265 }
266
267 # Do the actual write-out - it is assumed that close() is where this is done. Needs to return true/false
268 public function close() {
269 if (empty($this->pclzip)) {
270 $this->last_error = 'Zip file was not opened';
271 return false;
272 }
273
274 global $updraftplus;
275 $updraft_dir = $updraftplus->backups_dir_location();
276
277 $activity = false;
278
279 # Add the empty directories
280 foreach ($this->adddirs as $dir) {
281 if (false == $this->pclzip->add($updraft_dir.'/emptydir', PCLZIP_OPT_REMOVE_PATH, $updraft_dir.'/emptydir', PCLZIP_OPT_ADD_PATH, $dir)) {
282 $this->last_error = $this->pclzip->errorInfo(true);
283 return false;
284 }
285 $activity = true;
286 }
287
288 foreach ($this->addfiles as $rdirname => $adirnames) {
289 foreach ($adirnames as $adirname => $files) {
290 if (false == $this->pclzip->add($files, PCLZIP_OPT_REMOVE_PATH, $rdirname, PCLZIP_OPT_ADD_PATH, $adirname)) {
291 $this->last_error = $this->pclzip->errorInfo(true);
292 return false;
293 }
294 $activity = true;
295 }
296 unset($this->addfiles[$rdirname]);
297 }
298
299 $this->pclzip = false;
300 $this->addfiles = array();
301 $this->adddirs = array();
302
303 clearstatcache();
304 if ($activity && filesize($this->path) < 50) {
305 $this->last_error = "Write failed - unknown cause (check your file permissions)";
306 return false;
307 }
308
309 return true;
310 }
311
312 # Note: basename($add_as) is irrelevant; that is, it is actually basename($file) that will be used. But these are always identical in our usage.
313 public function addFile($file, $add_as) {
314 # Add the files. PclZip appears to do the whole (copy zip to temporary file, add file, move file) cycle for each file - so batch them as much as possible. We have to batch by dirname(). On a test with 1000 files of 25Kb each in the same directory, this reduced the time needed on that directory from 120s to 15s (or 5s with primed caches).
315 $rdirname = dirname($file);
316 $adirname = dirname($add_as);
317 $this->addfiles[$rdirname][$adirname][] = $file;
318 }
319
320 # PclZip doesn't have a direct way to do this
321 public function addEmptyDir($dir) {
322 $this->adddirs[] = $dir;
323 }
324
325 }
326