PluginProbe ʕ •ᴥ•ʔ
Backup Migration / 1.4.9
Backup Migration v1.4.9
2.1.6 2.1.5.2 trunk 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.6.1 1.4.7 1.4.8 1.4.9 1.4.9.1 2.0.0 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.5.1
backup-backup / includes / scanner / backups.php
backup-backup / includes / scanner Last commit date
backups.php 11 months ago files.php 11 months ago
backups.php
247 lines
1 <?php
2
3 // Namespace
4 namespace BMI\Plugin\Scanner;
5
6 // Use
7 use BMI\Plugin\BMI_Logger AS Logger;
8 use BMI\Plugin\Zipper\BMI_Zipper AS Zipper;
9 use BMI\Plugin\Zipper\Zip AS Zip;
10 use BMI\Plugin\External\BMI_External_Storage as ExternalStorage;
11
12 // Exit on direct access
13 if (!defined('ABSPATH')) exit;
14
15 /**
16 * Main Backup Scanner Logic
17 */
18 class BMI_BackupsScanner {
19
20 public function scanBackupDir($path) {
21
22 $files = [];
23 $dirs = new \DirectoryIterator($path);
24 foreach ($dirs as $fileInfo) {
25
26 if ($fileInfo->isDot()) continue;
27 if ($fileInfo->isFile()) {
28 if (in_array($fileInfo->getExtension(), ['zip', 'tar', 'tar.gz', 'gz', 'rar', '7zip', '7z'])) {
29
30 $files[] = array(
31 'filename' => $fileInfo->getFilename(),
32 'path' => $path,
33 'size' => $fileInfo->getSize()
34 );
35
36 } else if (strlen($fileInfo->getExtension()) == 6) { // Remove old partial backups e.g. abcdef.zip.g1wdas
37 $extentions = explode('.', $fileInfo->getFilename());
38 if (in_array($extentions[count($extentions) - 2],['zip', 'tar', 'tar.gz', 'gz', 'rar', '7zip', '7z'])) {
39 if (!file_exists(BMI_BACKUPS . DIRECTORY_SEPARATOR . '.running')) {
40 @unlink($path . DIRECTORY_SEPARATOR . $fileInfo->getFilename());
41 }
42 }
43 } else if ($fileInfo->getFilename() == '.space_check') {
44 if (filemtime(BMI_BACKUPS . DIRECTORY_SEPARATOR . '.space_check') < time() - 2 * MINUTE_IN_SECONDS) {
45 @unlink($path . DIRECTORY_SEPARATOR . $fileInfo->getFilename());
46 }
47 }
48 }
49
50 }
51
52 return $files;
53
54 }
55
56 public function removeOldCache() {
57 $md5_file_summary_path = BMI_BACKUPS . DIRECTORY_SEPARATOR. 'md5summary.php';
58
59 $md5summary = [];
60 if (file_exists($md5_file_summary_path)) {
61 $md5summary = file_get_contents($md5_file_summary_path);
62 $md5summary = substr($md5summary, 18, -2);
63 if (is_serialized($md5summary)) {
64 $md5summary = maybe_unserialize($md5summary);
65 }
66 }
67
68 foreach ($md5summary as $backupName => $md5files) {
69 foreach ($md5files as $index => $md5) {
70 if (!file_exists(BMI_BACKUPS . DIRECTORY_SEPARATOR . $backupName)) {
71 if (file_exists(BMI_BACKUPS . DIRECTORY_SEPARATOR . $md5 . '.json')) {
72 @unlink(BMI_BACKUPS . DIRECTORY_SEPARATOR . $md5 . '.json');
73 }
74 unset($md5summary[$backupName][$index]);
75 }
76 }
77
78 if (sizeof($md5summary[$backupName]) == 0) {
79 unset($md5summary[$backupName]);
80 }
81 }
82
83 $cacheMd5String = "<?php exit; \$x = '" . serialize($md5summary) . "';";
84 file_put_contents($md5_file_summary_path, $cacheMd5String);
85 }
86
87 public function getManifestFromZip($zip_path, &$zipper) {
88
89 if (!file_exists($zip_path)) return false;
90
91 // Get manifest content
92 $md5_file_summary_path = BMI_BACKUPS . DIRECTORY_SEPARATOR. 'md5summary.php';
93 $zip_modification_time = filemtime($zip_path);
94 $zip_name = basename($zip_path);
95
96 $md5summary = [];
97 if (file_exists($md5_file_summary_path)) {
98 $md5summary = file_get_contents($md5_file_summary_path);
99 $md5summary = substr($md5summary, 18, -2);
100 if (is_serialized($md5summary)) {
101 $md5summary = maybe_unserialize($md5summary);
102 }
103 }
104
105 if (is_string($md5summary)) {
106 @unlink($md5_file_summary_path);
107 }
108
109 $md5s = [];
110 $cached_md5 = false;
111 if (isset($md5summary[$zip_name])) {
112
113 $md5s = $md5summary[$zip_name];
114 $latest = 0;
115 $latest_md5 = false;
116 for ($i = 0; $i < sizeof($md5s); ++$i) {
117 $md5_file_path = BMI_BACKUPS . DIRECTORY_SEPARATOR . $md5s[$i] . '.json';
118 if (file_exists($md5_file_path)) {
119 $ftime = filemtime($md5_file_path);
120 if ($ftime > $latest) {
121 $latest = $ftime;
122 $latest_md5 = $md5s[$i];
123 }
124 }
125 }
126
127 if ($latest_md5 != false) {
128 $cached_md5 = $latest_md5;
129 }
130
131 } else {
132
133 if ($zip_name) $md5summary[$zip_name] = [];
134 else return false;
135
136 }
137
138 if ($cached_md5 != false) {
139 $zip_md5 = $cached_md5;
140 $md5_file_path = BMI_BACKUPS . DIRECTORY_SEPARATOR. $cached_md5 . '.json';
141 } else {
142 $zip_md5 = md5_file($zip_path);
143 $md5_file_path = BMI_BACKUPS . DIRECTORY_SEPARATOR. $zip_md5 . '.json';
144 if (!in_array($zip_md5, $md5summary[$zip_name])) {
145 $md5summary[$zip_name][] = $zip_md5;
146 }
147 }
148
149 $res = array();
150 if (file_exists($md5_file_path)) {
151 $manifest = json_decode(file_get_contents($md5_file_path));
152 } else {
153 $manifest = $zipper->getZipFileContent($zip_path, 'bmi_backup_manifest.json');
154 }
155
156 if ($manifest) {
157
158 $res[] = $manifest->name . '#%&' . $zip_name;
159 $res[] = $manifest->date;
160 $res[] = $manifest->files;
161 $res[] = $manifest->manifest;
162 $res[] = @filesize($zip_path);
163 if (!isset($manifest->is_locked)) {
164 $manifest->is_locked = $zipper->is_locked_zip($zip_path) ? 'locked' : 'unlocked';
165 $res[] = $manifest->is_locked;
166 } else {
167 $res[] = $manifest->is_locked;
168 }
169 $res[] = $manifest->cron;
170 $res[] = $zip_md5;
171 $res[] = sanitize_text_field($manifest->domain);
172
173 if (!file_exists($md5_file_path)) {
174 $manifest->abspath = $manifest->config->ABSPATH;
175 $manifest->table_prefix = $manifest->config->table_prefix;
176 unset($manifest->config);
177 file_put_contents($md5_file_path, json_encode($manifest));
178 } else touch($md5_file_path);
179
180 $cacheMd5String = "<?php exit; \$x = '" . serialize($md5summary) . "';";
181 file_put_contents($md5_file_summary_path, $cacheMd5String);
182
183 return $res;
184
185 } else return false;
186
187 }
188
189 public function getAvailableBackups($scope = "all") {
190
191 // Require Universal Zip Library
192 require_once BMI_INCLUDES . '/zipper/zipping.php';
193 $zipper = new Zipper();
194
195 // Scan for manifests
196 $manifests = array();
197 $backups = array();
198 $external = array();
199 $ongoing = get_option('bmip_to_be_uploaded', [
200 'current_upload' => [],
201 'queue' => [],
202 'failed' => []
203 ]);
204
205 if (file_exists(BMI_BACKUPS))
206 $backups = $this->scanBackupDir(BMI_BACKUPS);
207
208 // $start = time();
209 // $maxTime = ini_get('max_execution_time');
210
211 for ($i = 0; $i < sizeof($backups); ++$i) {
212
213 // $filestart = time();
214
215 $backup = $backups[$i];
216 if (!file_exists($backup['path'])) continue;
217 $path = $backup['path'] . '/' . $backup['filename'];
218
219 $manifest = $this->getManifestFromZip($path, $zipper);
220 if ($manifest) $manifests[$backup['filename']] = $manifest;
221 else{
222 if (!file_exists(BMI_BACKUPS . '/.running')) @unlink($path); // Prevents deletion of running backups
223 }
224
225 // $fileend = $filestart - time();
226 // $totalTime = $start - time();
227
228 // if ($totalTime + $fileend > $maxTime) break;
229
230 }
231
232 if ($scope == "local") {
233 return [ 'local' => $manifests ];
234 }
235
236 require_once BMI_INCLUDES . '/external/controller.php';
237 $externalStorage = new ExternalStorage();
238 $external = $externalStorage->getExternalBackups();
239
240 $this->removeOldCache();
241
242 return [ 'local' => $manifests, 'external' => $external, 'ongoing' => $ongoing ];
243
244 }
245
246 }
247