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 / initializer.php
backup-backup / includes Last commit date
banner 11 months ago bodies 11 months ago check 11 months ago cli 11 months ago cron 11 months ago dashboard 11 months ago database 11 months ago external 11 months ago extracter 11 months ago htaccess 11 months ago notices 11 months ago progress 11 months ago scanner 11 months ago staging 11 months ago traits 11 months ago uploader 11 months ago zipper 11 months ago .htaccess 11 months ago activation.php 11 months ago ajax.php 11 months ago ajax_offline.php 11 months ago analyst.php 11 months ago backup-process.php 11 months ago class-backup-method-mananger.php 11 months ago cli-handler.php 11 months ago compatibility.php 11 months ago config.php 11 months ago constants.php 11 months ago initializer.php 11 months ago logger.php 11 months ago offline.php 11 months ago
initializer.php
1792 lines
1 <?php
2
3 // Namespace
4 namespace BMI\Plugin;
5
6 // Exit on direct access
7 if (!defined('ABSPATH')) {
8 exit;
9 }
10
11 // Require classes
12 require_once BMI_INCLUDES . '/logger.php';
13
14 // Alias for classes
15 use BMI\Plugin\BMI_Logger as Logger;
16 use BMI\Plugin\CRON\BMI_Crons as Crons;
17 use BMI\Plugin\Dashboard as Dashboard;
18 use BMI\Plugin\Scanner\BMI_BackupsScanner as Backups;
19 use BMI\Plugin\Heart\BMI_Backup_Heart as Bypasser;
20 use BMI\Plugin\Zipper\BMI_Zipper as Zipper;
21 use BMI\Plugin\Staging\BMI_Staging as Staging;
22 use BMI\Plugin\External\BMI_External_BackupBliss as BackupBliss;
23
24 // Uninstallator
25 if (!function_exists('bmi_uninstall_handler')) {
26 function bmi_uninstall_handler() {
27 require_once BMI_ROOT_DIR . '/uninstall.php';
28 }
29 }
30
31 /**
32 * Backup Migration Main Class
33 */
34 class Backup_Migration_Plugin {
35 public function initialize() {
36
37 // Determine which BMI version is used
38 add_action('wp_head', function () {
39 echo '<meta name="bmi-version" content="' . BMI_VERSION . '" />';
40 });
41
42 if (!file_exists(BMI_BACKUPS)) @mkdir(BMI_BACKUPS, 0755, true);
43 if (!file_exists(BMI_STAGING)) @mkdir(BMI_STAGING, 0755, true);
44
45 // Handle PHP CLI functions
46 if (defined('BMI_USING_CLI_FUNCTIONALITY') && BMI_USING_CLI_FUNCTIONALITY === true) {
47
48 // Below all WordPress functions and directives can be accessed
49 if (defined('BMI_CLI_FUNCTION')) {
50
51 if (BMI_CLI_FUNCTION == 'bmi_restore' && defined('BMI_CLI_ARGUMENT')) {
52
53 $_SERVER['HTTP_X_REQUESTED_WITH'] = 'xmlhttprequest';
54 $_POST['f'] = 'restore-backup';
55 if (defined('BMI_CLI_ARGUMENT_2')) {
56 $_POST['remote'] = BMI_CLI_ARGUMENT_2;
57 } else $_POST['remote'] = false;
58 $_POST['file'] = BMI_CLI_ARGUMENT;
59
60 $this->ajax(true);
61
62 } elseif (BMI_CLI_FUNCTION == 'bmi_backup' || BMI_CLI_FUNCTION == 'bmi_backup_cron') {
63
64 if (BMI_CLI_FUNCTION == 'bmi_backup_cron') {
65 define('BMI_DOING_SCHEDULED_BACKUP', true);
66 define('BMI_DOING_SCHEDULED_BACKUP_VIA_CLI', true);
67 }
68
69 $_SERVER['HTTP_X_REQUESTED_WITH'] = 'xmlhttprequest';
70 $_POST['f'] = 'create-backup';
71
72 $this->ajax(true);
73
74 } elseif (BMI_CLI_FUNCTION == 'bmi_quick_migration') {
75
76 $_SERVER['HTTP_X_REQUESTED_WITH'] = 'xmlhttprequest';
77 $_POST['f'] = 'download-backup';
78 $_POST['url'] = BMI_CLI_ARGUMENT;
79
80 $this->ajax(true);
81
82 }
83
84 }
85
86 return;
87
88 }
89
90 if (defined('BMI_RESTORE_SECRET') && defined('BMI_POST_CONTINUE_RESTORE') && constant('BMI_POST_CONTINUE_RESTORE') === true) {
91
92 if (!isset($_POST['bmi_restore_secret'])) exit;
93
94 // Check the secret
95 $bmi_secret_storage = BMI_TMP . DIRECTORY_SEPARATOR . '.restore_secret';
96 if (file_exists($bmi_secret_storage)) {
97 $bmi_saved_secret = file_get_contents($bmi_secret_storage);
98 if ($bmi_saved_secret === $_POST['bmi_restore_secret']) {
99 $bmi_continue_module = true;
100 } else exit;
101 } else exit;
102
103 $_SERVER['HTTP_X_REQUESTED_WITH'] = 'xmlhttprequest';
104 $_POST['f'] = 'continue_restore_process';
105
106 $this->ajax(true);
107
108 return;
109
110 }
111
112 // Hooks
113 register_deactivation_hook(BMI_ROOT_FILE, [&$this, 'deactivation']);
114 register_uninstall_hook(BMI_ROOT_FILE, 'bmi_uninstall_handler');
115
116 // File downloading
117 add_action('wp_loaded', [&$this, 'handle_downloading']);
118
119 // Additional actions
120 if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'GET') {
121 add_action('wp_loaded', [&$this, 'handle_after_actions'], 1000);
122 }
123 // Handle CRONs
124 add_action('bmi_do_backup_right_now', [&$this, 'handle_cron_backup']);
125 add_action('bmi_handle_cron_check', [&$this, 'handle_cron_check']);
126 add_action('wp_loaded', [&$this, 'handle_crons']);
127 add_action('wp_loaded', [&$this, 'include_offline']);
128 add_action('admin_notices', [&$this, 'incompatibility_notices']);
129
130 // Return if CRON time
131 if (function_exists('wp_doing_cron') && wp_doing_cron()) return;
132
133 // Check user permissions
134 $user = get_userdata(get_current_user_id());
135 if (!$user || !$user->roles) return;
136 if (!current_user_can('do_backups') && !in_array('administrator', (array) $user->roles)) return;
137
138 if (Dashboard\bmi_get_config('OTHER:PROMOTIONAL:DISPLAY') != 'true') {
139
140 // Include our cool banner
141 include_once BMI_INCLUDES . '/banner/misc.php';
142
143 // Review banner
144 if (!is_dir(WP_PLUGIN_DIR . '/backup-backup-pro')) {
145 if (!(class_exists('\Inisev\Subs\Inisev_Review') || class_exists('Inisev\Subs\Inisev_Review') || class_exists('Inisev_Review'))) {
146 require_once BMI_MODULES_DIR . 'review' . DIRECTORY_SEPARATOR . 'review.php';
147 }
148 $review_banner = new \Inisev\Subs\Inisev_Review(BMI_ROOT_FILE, BMI_ROOT_DIR, 'backup-backup', 'Backup & Migration', 'http://bit.ly/3vdk45L', 'backup-migration');
149 }
150
151 if (!(class_exists('\Inisev\Subs\New_BB_Banner') || class_exists('Inisev\Subs\New_BB_Banner') || class_exists('New_BB_Banner'))) {
152 require_once BMI_MODULES_DIR . 'new-bb-banner' . DIRECTORY_SEPARATOR . 'misc.php';
153 }
154 new \Inisev\Subs\New_BB_Banner(BMI_ROOT_FILE, BMI_ROOT_DIR, 'backup-backup', 'Backup & Migration', 'backup-migration');
155
156
157 // GDrive banner
158 if (!is_dir(WP_PLUGIN_DIR . '/backup-backup-pro')) {
159 if (!(class_exists('\Inisev\Subs\BMI_Banners_GDrive') || class_exists('Inisev\Subs\BMI_Banners_GDrive') || class_exists('BMI_Banners_GDrive'))) {
160 require_once BMI_MODULES_DIR . 'gdrivebanner' . DIRECTORY_SEPARATOR . 'misc.php';
161 }
162 $gdirve_banner = new \Inisev\Subs\BMI_Banners_GDrive('Backup & Migration', 'backup-migration');
163 }
164
165 }
166
167 // POST Logic
168 if ($_SERVER['REQUEST_METHOD'] === 'POST') {
169
170 // Register AJAX Handler
171 add_action('wp_ajax_backup_migration', [&$this, 'ajax']);
172
173 // Stop GET Registration
174 // return; // Commented because of conflicts with USM Icons
175
176 }
177
178 // Actions
179 add_action('admin_init', [&$this, 'admin_init_hook']);
180 add_action('admin_menu', [&$this, 'submenu']);
181 add_action('admin_notices', [&$this, 'admin_notices']);
182
183
184 // Settings action
185 add_filter('plugin_action_links_' . plugin_basename(BMI_ROOT_FILE), [&$this, 'settings_action']);
186
187 // Ignore below actions if those true
188 if (function_exists('wp_doing_ajax') && wp_doing_ajax()) {
189 return;
190 }
191
192 // Styles & scripts
193 add_action('admin_enqueue_scripts', [&$this, 'enqueue_styles']);
194 add_action('admin_enqueue_scripts', [&$this, 'enqueue_scripts']);
195
196 // External storage errors
197 add_action('bmi_external_errors', function() {
198 require_once BMI_INCLUDES . '/notices/backupbliss.php';
199 });
200
201 $upload_issue_notice = $this->backupbliss_space_issues();
202
203 if ($upload_issue_notice) {
204 add_action("admin_notices", function() use ($upload_issue_notice) {
205 $global_warning = true;
206 $error_message = $upload_issue_notice;
207 include BMI_INCLUDES . '/dashboard/modals/bb-warning-notice.php';
208 });
209 }
210
211 }
212
213 public function incompatibility_notices() {
214
215 if (strpos(home_url(), 'instawp') === false && strpos(home_url(), 'playground.wordpress') === false) return;
216
217 $environment = 'sandbox';
218 if (strpos(home_url(), 'instawp') !== false) $environment = 'InstaWP';
219 if (strpos(home_url(), 'playground.wordpress') !== false) $environment = 'WordPress Playground';
220
221 $class = 'notice notice-warning';
222 $message = __('We noticed that you are using %s, our plugin may not work in this environment, please use %s environment instead.', 'backup-backup');
223
224 printf('<div class="%s"><p><b>Backup Migration:</b> %s</p></div>',
225 esc_attr($class),
226 sprintf(
227 esc_html($message),
228 '<i>' . $environment . '</i>',
229 '<a href="https://tastewp.com" target="_blank">TasteWP</a>'
230 )
231 );
232 }
233
234 public static function randomString($max = 16) {
235
236 $bank = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
237 $bank .= 'abcdefghijklmnopqrstuvwxyz';
238 $bank .= '0123456789';
239
240 $str = str_shuffle($bank);
241
242 while (is_numeric($str[0])) {
243 $str = str_shuffle($bank);
244 }
245
246 $str = substr($str, 0, $max);
247
248 return $str;
249
250 }
251
252 public static function isFunctionEnabled($func) {
253
254 $disabled = explode(',', ini_get('disable_functions'));
255 $isDisabled = in_array($func, $disabled);
256 if (!$isDisabled && function_exists($func)) return true;
257 else return false;
258
259 }
260
261 /**
262 * hotFixPatches - Function which fixes things for "old" users
263 *
264 * @return void
265 */
266 public function hotfix_patches() {
267
268 if (!is_admin()) return;
269
270 $current_patch = get_option('bmi_hotfixes', array());
271 if (!in_array('BMI_D20_M07_01', $current_patch)) {
272
273 $current_directory = Dashboard\bmi_get_config('STORAGE::LOCAL::PATH');
274 if (basename($current_directory) == 'backup-migration') {
275
276 require_once BMI_INCLUDES . '/ajax.php';
277 $handler_a = new BMI_Ajax(true);
278
279 $handler_a->post['directory'] = dirname($current_directory) . DIRECTORY_SEPARATOR . 'backup-migration-' . $this->randomString(10);
280 $handler_a->post['access'] = Dashboard\bmi_get_config('STORAGE::DIRECT::URL');
281
282 $res_a = $handler_a->saveStorageConfig();
283 if (isset($res_a['status']) && $res_a['status'] == 'success') {
284
285 $current_patch[] = 'BMI_D20_M07_01';
286
287 }
288
289 } else {
290
291 $current_patch[] = 'BMI_D20_M07_01';
292
293 }
294
295 }
296
297 if (!in_array('BMI_D17_M12_Y21_02', $current_patch)) {
298
299 $current_splitting_value = Dashboard\bmi_get_config('OTHER:RESTORE:SPLITTING');
300 $current_query_size = Dashboard\bmi_get_config('OTHER:DB:QUERIES');
301
302 $current_query_size = intval($current_query_size);
303 if ($current_splitting_value == 'true' || $current_splitting_value === true) {
304 $current_splitting_value = true;
305 } else {
306 $current_splitting_value = false;
307 }
308
309 if ($current_splitting_value === false || $current_query_size != 300) {
310
311 $b_db_restore_splitting = true;
312 $b_db_query_size = '2000';
313
314 $error_b = 0;
315 if (!Dashboard\bmi_set_config('OTHER:RESTORE:SPLITTING', $b_db_restore_splitting)) {
316 $error_b++;
317 }
318 if (!Dashboard\bmi_set_config('OTHER:DB:QUERIES', $b_db_query_size)) {
319 $error_b++;
320 }
321
322 if ($error_b <= 0) {
323
324 $current_patch[] = 'BMI_D17_M12_Y21_02';
325
326 }
327
328 } else {
329
330 $current_patch[] = 'BMI_D17_M12_Y21_02';
331
332 }
333
334 }
335
336 if (!in_array('BMI_D13_M08_Y23_01', $current_patch)) {
337
338 $current_direct_download_value = Dashboard\bmi_get_config('OTHER:DOWNLOAD:DIRECT');
339
340 if ($current_direct_download_value === false || $current_direct_download_value == 'false') {
341
342 $error_b = 0;
343 if (!Dashboard\bmi_set_config('OTHER:DOWNLOAD:DIRECT', true)) $error_b++;
344 if ($error_b <= 0) $current_patch[] = 'BMI_D13_M08_Y23_01';
345
346 } else $current_patch[] = 'BMI_D13_M08_Y23_01';
347
348 }
349
350 update_option('bmi_hotfixes', $current_patch);
351
352 }
353
354 public function ajax($cli = false) {
355 if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest') {
356 if ((isset($_POST['token']) && $_POST['token'] == 'bmi' && isset($_POST['f']) && is_admin()) || $cli) {
357 try {
358
359 if (gettype($cli) != 'boolean') $cli = false;
360
361 // Extend execution time
362 if ($this->isFunctionEnabled('headers_sent') && $this->isFunctionEnabled('session_status')) {
363 if (!headers_sent() && session_status() === PHP_SESSION_DISABLED) {
364 if ($this->isFunctionEnabled('ignore_user_abort')) @ignore_user_abort(true);
365 if ($this->isFunctionEnabled('set_time_limit')) @set_time_limit(16000);
366 if ($this->isFunctionEnabled('ini_set')) {
367 @ini_set('max_execution_time', '259200');
368 @ini_set('max_input_time', '259200');
369 }
370 }
371 }
372
373 // May cause issues with auto login
374 // if (strlen(session_id()) > 0) session_write_close();
375
376 if ($this->isFunctionEnabled('register_shutdown_function')) {
377 register_shutdown_function([$this, 'execution_shutdown']);
378 }
379
380 // Require AJAX Handler
381 require_once BMI_INCLUDES . '/ajax.php';
382 $handler = new BMI_Ajax($cli);
383
384 } catch (\Exception $e) {
385
386 Logger::error('POST error:');
387 Logger::error($e);
388 if ($_POST['f'] == 'create-backup') {
389 $progress = &$GLOBALS['bmi_backup_progress'];
390 $this->handleErrorDuringBackup($e->getMessage(), $e->getFile(), $e->getLine(), $progress);
391 }
392 if ($_POST['f'] == 'restore-backup') {
393 $progress = &$GLOBALS['bmi_migration_progress'];
394 $this->handleErrorDuringRestore($e->getMessage(), $e->getFile(), $e->getLine(), $progress);
395 }
396
397 $this->res(['status' => 'error', 'error' => $e]);
398 exit;
399
400 } catch (\Throwable $e) {
401
402 Logger::error('POST error:');
403 Logger::error($e);
404 if ($_POST['f'] == 'create-backup') {
405 $progress = &$GLOBALS['bmi_backup_progress'];
406 $this->handleErrorDuringBackup($e->getMessage(), $e->getFile(), $e->getLine(), $progress);
407 }
408 if ($_POST['f'] == 'restore-backup') {
409 $progress = &$GLOBALS['bmi_migration_progress'];
410 $this->handleErrorDuringRestore($e->getMessage(), $e->getFile(), $e->getLine(), $progress);
411 }
412
413 $this->res(['status' => 'error', 'error' => $e]);
414 exit;
415
416 }
417 }
418 }
419 }
420
421 public function execution_shutdown() {
422 $err = error_get_last();
423
424 if (defined('BMI_USING_CLI_FUNCTIONALITY') && BMI_USING_CLI_FUNCTIONALITY === true) {
425 $lock_cli = BMI_BACKUPS . '/.migration_lock_cli';
426 $lock_cli_end = BMI_BACKUPS . '/.migration_lock_ended';
427 $cli_failed_lock = BMI_BACKUPS . '/.backup_lock_cli_failed';
428 $lock_cli_end_backup = BMI_BACKUPS . '/.backup_lock_cli_end';
429
430 if (file_exists($lock_cli)) @unlink($lock_cli);
431 if (file_exists($lock_cli_end)) @touch($lock_cli_end);
432 if (file_exists($cli_failed_lock)) @touch($cli_failed_lock);
433 if (file_exists($lock_cli_end_backup)) @touch($lock_cli_end_backup);
434 }
435
436 if ($err != null) {
437
438 $msg = $err['message'];
439 $file = $err['file'];
440 $line = $err['line'];
441 $type = $err['type'];
442
443 if ($type != '1' && ($type != E_ERROR && $type != E_CORE_ERROR && $type != E_COMPILE_ERROR && $type != E_USER_ERROR && $type != E_RECOVERABLE_ERROR)) {
444 Logger::error(__('There was an error before request shutdown (but it was not logged to backup/restore log)', 'backup-backup'));
445 Logger::error(__('Error message: ', 'backup-backup') . $msg);
446 Logger::error(__('Error file/line: ', 'backup-backup') . $file . '|' . $line);
447 Logger::error(__('Error handler: ', 'backup-backup') . 'init#01' . '|' . $type);
448 return;
449 }
450
451 if (isset($GLOBALS['bmi_error_handled']) && $GLOBALS['bmi_error_handled']) return;
452 if ($_POST['f'] == 'create-backup') {
453 Logger::error(__('There was an error during backup', 'backup-backup'));
454 Logger::error(__('Error message: ', 'backup-backup') . $msg);
455 Logger::error(__('Error file/line: ', 'backup-backup') . $file . '|' . $line);
456 Logger::error(__('Error handler: ', 'backup-backup') . 'init#02' . '|' . $type);
457 $progress = &$GLOBALS['bmi_backup_progress'];
458 if ($progress) {
459 $progress->log(__('Error message: ', 'backup-backup') . $msg, 'error');
460 $progress->log(__('You can get more pieces of information in troubleshooting log file.', 'backup-backup'), 'error');
461 }
462 $this->handleErrorDuringBackup($msg, $file, $line, $progress);
463
464 $fullPath = BMI_TMP . DIRECTORY_SEPARATOR;
465 array_map('unlink', glob($fullPath . '*.tmp'));
466 array_map('unlink', glob($fullPath . '*.gz'));
467 }
468
469 if ($_POST['f'] == 'restore-backup') {
470 Logger::error(__('There was an error during restore process', 'backup-backup'));
471 Logger::error(__('Error message: ', 'backup-backup') . $msg);
472 Logger::error(__('Error file/line: ', 'backup-backup') . $file . '|' . $line);
473 Logger::error(__('Error handler: ', 'backup-backup') . 'init#03' . '|' . $type);
474 $progress = &$GLOBALS['bmi_migration_progress'];
475 if ($progress) {
476 $progress->log(__('Error message: ', 'backup-backup') . $msg, 'error');
477 $progress->log(__('You can get more pieces of information in troubleshooting log file.', 'backup-backup'), 'error');
478 }
479 $this->handleErrorDuringRestore($msg, $file, $line, $progress);
480 }
481
482 $this->res(['status' => 'error', 'error' => $err]);
483 exit;
484 }
485 }
486
487 public function handleErrorDuringBackup($msg, $file, $line, &$progress) {
488 $backup = $GLOBALS['bmi_current_backup_name'];
489
490 Logger::log('Due to fatal error backup handled correctly (closed and removed).');
491 if ($progress) {
492 $progress->log(__('Something bad happened on PHP side.', 'backup-backup'), 'error');
493 $progress->log(__('Unfortunately we had to remove the backup (if partly created).', 'backup-backup'), 'error');
494 $progress->log(__('Error message: ', 'backup-backup') . $msg, 'error');
495 $progress->log(__('Error file/line: ', 'backup-backup') . $file . '|' . $line, 'error');
496 if (strpos($msg, 'execution time') !== false) {
497 $progress->log(__('Probably we could not increase the execution time, please edit your php.ini manually', 'backup-backup'), 'error');
498 }
499 }
500
501 $backup_path = BMI_BACKUPS . DIRECTORY_SEPARATOR . $backup;
502 $partial_backup_path = glob( BMI_BACKUPS . DIRECTORY_SEPARATOR . $backup . '.??????');
503 if (is_array($partial_backup_path) && count($partial_backup_path) > 0) {
504 foreach ($partial_backup_path as $key => $value) {
505 @unlink($value);
506 }
507 }
508 if (file_exists($backup_path)) @unlink($backup_path);
509 if (file_exists(BMI_BACKUPS . DIRECTORY_SEPARATOR . '.running')) @unlink(BMI_BACKUPS . DIRECTORY_SEPARATOR . '.running');
510 if (file_exists(BMI_BACKUPS . DIRECTORY_SEPARATOR . '.abort')) @unlink(BMI_BACKUPS . DIRECTORY_SEPARATOR . '.abort');
511
512 if ($progress) {
513 $progress->log(__("Aborting backup...", 'backup-backup'), 'step');
514 $progress->log('#002', 'END-CODE');
515 $progress->end();
516 }
517 }
518
519 public function handleErrorDuringRestore($msg, $file, $line, &$progress) {
520 Logger::log('There was fatal error during restore.');
521 if ($progress) {
522 $progress->log(__('Something bad happened on PHP side.', 'backup-backup'), 'error');
523 $progress->log(__('Error message: ', 'backup-backup') . $msg, 'error');
524 $progress->log(__('Error file/line: ', 'backup-backup') . $file . '|' . $line, 'error');
525 }
526 if (file_exists(BMI_BACKUPS . DIRECTORY_SEPARATOR . '.migration_lock')) @unlink(BMI_BACKUPS . DIRECTORY_SEPARATOR . '.migration_lock');
527 if ($progress) {
528 $progress->log(__("Aborting & unlocking restore process...", 'backup-backup'), 'step');
529 $progress->end();
530 }
531
532 $lock = BMI_BACKUPS . '/.migration_lock';
533 if (file_exists($lock)) @unlink($lock);
534 }
535
536 public function submenu() {
537
538 // Menu icon
539 $icon_url = $this->get_asset('images', 'logo-min.png');
540
541 // Main menu slug
542 $parentSlug = 'backup-migration';
543
544 // Content
545 $content = [$this, 'settings_page'];
546
547 // Main menu hook
548 add_menu_page('Backup Migration', '<span id="bmi-menu">Backup Migration</span>', 'read', $parentSlug, $content, $icon_url, 98);
549
550 // Remove default submenu by menu
551 remove_submenu_page($parentSlug, $parentSlug);
552
553 }
554
555 public function settings_action($links) {
556 $text = __('Manage', 'backup-backup');
557 $links['bmi-settings-link'] = '<a href="' . admin_url('/admin.php?page=backup-migration') . '">' . $text . '</a>';
558
559 return $links;
560 }
561
562 public function include_offline() {
563
564
565 // Handle offline tasks
566 if (!class_exists('BMI_Offline')) {
567
568 if (file_exists(BMI_INCLUDES . '/offline.php')) {
569 require_once BMI_INCLUDES . '/offline.php';
570 new BMI_Offline();
571 }
572 }
573
574 }
575
576 public function settings_page() {
577
578 // Set email if does not exist
579 if (!Dashboard\bmi_get_config('OTHER:EMAIL')) {
580 Dashboard\bmi_set_config('OTHER:EMAIL', get_bloginfo('admin_email'));
581 }
582
583 // Require The HTML
584 require_once BMI_INCLUDES . '/dashboard/settings.php';
585 }
586
587 public function backupbliss_space_issues() {
588 require_once BMI_INCLUDES . '/external/backupbliss.php';
589 $backupbliss = new BackupBliss();
590 $upload_issue_notice = false;
591 if ($backupbliss->canShowFailureWarnNotice()) {
592 $upload_issue_notice = $backupbliss->getNotice("upload_issue_space");
593 }
594 return $upload_issue_notice;
595 }
596
597 public function admin_init_hook() {
598 $this->hotfix_patches();
599 if (get_option('_bmi_redirect', false)) {
600 $this->fixLitespeed();
601 delete_option('_bmi_redirect');
602 wp_safe_redirect(admin_url('admin.php?page=backup-migration'));
603 }
604 }
605
606 public function admin_notices() {
607 if (get_current_screen()->id != 'toplevel_page_backup-migration' && get_option('bmi_display_email_issues', false)) {
608 ?>
609 <div class="notice notice-warning">
610 <p>
611 <?php _e('There was an error during automated backup, please', 'backup-backup'); ?>
612 <?php echo '<a href="' . admin_url('/admin.php?page=backup-migration') . '">' . __('check that.', 'backup-backup') . '</a>'; ?>
613 </p>
614 </div>
615 <?php
616 }
617 }
618
619 public function handle_crons() {
620 if (Dashboard\bmi_get_config('CRON:ENABLED') !== true) return;
621
622 $time = get_option('bmi_backup_check', 0);
623 if ((time() - $time) > 60) {
624 update_option('bmi_backup_check', time());
625
626 do_action('bmi_handle_cron_check');
627 }
628 }
629
630 /**
631 * Retrieves a list of active security plugins detected on the site.
632 *
633 * This function checks the list of currently active plugins and identifies
634 * common security plugins by their slugs. It returns a key-value array
635 * where keys are plugin slugs and values are their human-readable names.
636 *
637 * Supported plugins:
638 * - Wordfence
639 * - Sucuri Security
640 *
641 * @return array<string, string> Associative array of detected security plugins.
642 * Format: [ 'plugin_slug' => 'Plugin Name' ]
643 */
644 public static function get_active_security_plugins() {
645 $active_plugins = [];
646 $plugins = get_option('active_plugins', []);
647 if (is_array($plugins) && count($plugins) > 0) {
648 foreach ($plugins as $plugin) {
649 if (strpos($plugin, 'wordfence') !== false) {
650 $active_plugins['wordfence'] = 'Wordfence';
651 } elseif (strpos($plugin, 'security-ninja') !== false) {
652 $active_plugins['security-ninja'] = 'Security Ninja';
653 }
654 }
655 }
656 return $active_plugins;
657 }
658
659 public static function email_error($msg) {
660 Logger::log('Displaying some issues about email sending...');
661 update_option('bmi_display_email_issues', $msg);
662 }
663
664 public function backup_inproper_time($should_time) {
665 $plan_file = BMI_TMP . DIRECTORY_SEPARATOR . '.plan';
666 if (!file_exists($plan_file) || intval($should_time) < 1234567890) return;
667
668 $currentDate = date('Y-m-d');
669 if (get_option('bmi_last_email_notification', false) == $currentDate) {
670 return;
671 }
672
673 Logger::log('Sending notification about backup being late');
674 $email = Dashboard\bmi_get_config('OTHER:EMAIL') != false ? Dashboard\bmi_get_config('OTHER:EMAIL') : get_bloginfo('admin_email');
675 $subject = Dashboard\bmi_get_config('OTHER:EMAIL:TITLE');
676 $message = __("Automatic backup was not on time because there was no traffic on the site.", 'backup-backup') . "\n";
677 $message .= __("Backup was made on: ", 'backup-backup') . date('Y-m-d H:i:s') . __(', but should be on: ', 'backup-backup') . date('Y-m-d H:i:s', $should_time);
678 $message .= ' ' . __("(server time)", 'backup-backup');
679
680 Logger::debug($message);
681 if (!self::send_notification_mail($email, $subject, $message)) {
682 $issue = __("Couldn't send mail to you, please check server configuration.", 'backup-backup') . '<br>';
683 $issue .= '<b>' . __("Message you missed because of this: ", 'backup-backup') . '</b>' . $message;
684 self::email_error($issue);
685 }
686 }
687
688 public function handle_cron_check() {
689
690 if (Dashboard\bmi_get_config('CRON:ENABLED') !== true) return;
691
692 $now = time();
693 if (file_exists(BMI_TMP . DIRECTORY_SEPARATOR . '.last')) {
694 $last = @file_get_contents(BMI_TMP . DIRECTORY_SEPARATOR . '.last');
695 $last_status = explode('.', $last)[0];
696 $last_time = intval(explode('.', $last)[1]);
697 } else {
698 $last_time = 0;
699 $last_status = 0;
700 }
701
702 if (file_exists(BMI_TMP . DIRECTORY_SEPARATOR . '.plan')) {
703 $plan = intval(@file_get_contents(BMI_TMP . DIRECTORY_SEPARATOR . '.plan'));
704 if ($last_time < $plan && ((time() - $plan) > 7200)) {
705 if ($last_status !== '0') {
706 $this->backup_inproper_time($plan);
707 if (!wp_next_scheduled('bmi_do_backup_right_now')) {
708 wp_schedule_single_event(time(), 'bmi_do_backup_right_now');
709 }
710 }
711 }
712 }
713
714 }
715
716 public function get_next_cron($curr = false) {
717 if ($curr === false) {
718 $curr = time();
719 }
720
721 $time = Crons::calculate_date([
722 'type' => Dashboard\bmi_get_config('CRON:TYPE'),
723 'week' => Dashboard\bmi_get_config('CRON:WEEK'),
724 'day' => Dashboard\bmi_get_config('CRON:DAY'),
725 'hour' => Dashboard\bmi_get_config('CRON:HOUR'),
726 'minute' => Dashboard\bmi_get_config('CRON:MINUTE')
727 ], $curr);
728
729 return $time;
730 }
731
732 public function handle_cron_error($e) {
733 Logger::error(__("Automatic backup failed at time: ", 'backup-backup') . date('Y-m-d, H:i:s'));
734 if (is_object($e) || is_array($e)) {
735 Logger::error('Error: ' . $e->getMessage());
736 } else {
737 Logger::error('Error: ' . $e);
738 }
739
740 $notis = Dashboard\bmi_get_config('OTHER:EMAIL:NOTIS');
741 if (in_array($notis, [true, 'true'])) {
742 $email = Dashboard\bmi_get_config('OTHER:EMAIL') != false ? Dashboard\bmi_get_config('OTHER:EMAIL') : get_bloginfo('admin_email');
743 $subject = Dashboard\bmi_get_config('OTHER:EMAIL:TITLE');
744 $message = __("There was an error during automatic backup, please check the logs.", 'backup-backup');
745 if (is_string($e)) {
746 $message .= "\nError: " . $e;
747 }
748
749 self::send_notification_mail($email, $subject, $message);
750 }
751
752 if (file_exists(BMI_BACKUPS . '/.cron')) {
753 @unlink(BMI_BACKUPS . '/.cron');
754 }
755 }
756
757 public static function send_notification_mail($email, $subject, $message, $force = false) {
758
759 $currentDate = date('Y-m-d');
760 if (get_option('bmi_last_email_notification', false) == $currentDate && $force === false) {
761 Logger::log(__("Disallowing to send mail as today we already sent one.", 'backup-backup'));
762 return;
763 }
764
765 update_option('bmi_last_email_notification', $currentDate);
766
767 $email_fail = __("Could not send the email notification about that fail", 'backup-backup');
768
769 try {
770
771 if (wp_mail($email, $subject, $message)) {
772 Logger::log(__("Sent email notification to: ", 'backup-backup') . $email);
773
774 return true;
775 } else {
776 Logger::error($email_fail);
777 self::email_error(__("Couldn't send notification via email, please check the email and your server settings.", 'backup-backup'));
778
779 return false;
780 }
781
782 } catch (\Exception $e) {
783 Logger::error($email_fail);
784 self::email_error(__("Couldn't send notification via email due to error, please check plugin logs for more details.", 'backup-backup'));
785
786 return false;
787 } catch (\Throwable $e) {
788 Logger::error($email_fail);
789 self::email_error(__("Couldn't send notification via email due to error, please check plugin logs for more details.", 'backup-backup'));
790
791 return false;
792 }
793 }
794
795 public static function handle_after_cron() {
796 require_once BMI_INCLUDES . DIRECTORY_SEPARATOR . 'scanner' . DIRECTORY_SEPARATOR . 'backups.php';
797 $backups = new Backups();
798 $availableBackups = $backups->getAvailableBackups();
799 $list = $availableBackups['local'];
800
801 $cron_list = [];
802 $cron_dates = [];
803 $sortedMD5s = [];
804 foreach ($list as $key => $value) {
805 if ($list[$key][6] == true) {
806 if ($list[$key][5] == 'unlocked') {
807 $cron_list[$list[$key][1]] = $list[$key][0];
808 $cron_dates[] = $list[$key][1];
809 $sortedMD5s[] = [$list[$key][1], $list[$key][7]];
810 }
811 }
812 }
813
814 usort($cron_dates, function ($a, $b) {
815 return (strtotime($a) < strtotime($b)) ? -1 : 1;
816 });
817
818 $cron_dates = array_slice($cron_dates, 0, -(intval(Dashboard\bmi_get_config('CRON:KEEP'))));
819 foreach ($cron_dates as $key => $value) {
820 $name = $cron_list[$cron_dates[$key]];
821 $name = explode('#%&', $name)[1];
822 Logger::log(__("Removing backup due to keep rules: ", 'backup-backup') . $name);
823 @unlink(BMI_BACKUPS . DIRECTORY_SEPARATOR . $name);
824 }
825
826 // Auto External Removal
827 $sortedMD5s = [];
828 $externalStorages = ['gdrive', 'dropbox', 'onedrive', 'FTP', 'sftp', 'aws', 'wasabi', 'backupbliss'];
829 foreach ($externalStorages as $storage) {
830 if (isset($availableBackups['external'][$storage])) {
831 $storageList = $availableBackups['external'][$storage];
832 foreach ($storageList as $md5 => $data) {
833 if ($storageList[$md5][6] == true && $storageList[$md5][5] == 'unlocked') {
834 $sortedMD5s[] = [$storageList[$md5][1], $md5];
835 }
836 }
837 }
838 }
839 $sortedMD5s = array_intersect_key($sortedMD5s, array_unique(array_map('serialize', $sortedMD5s)));
840
841 usort($sortedMD5s, function ($a, $b) {
842 return (strtotime($a[0]) < strtotime($b[0])) ? -1 : 1;
843 });
844
845 $sortedMD5s = array_slice($sortedMD5s, 0, -(intval(Dashboard\bmi_get_config('CRON:KEEP'))));
846 foreach ($sortedMD5s as $index => $data) {
847 $md5 = $data[1];
848
849 do_action('bmi_premium_remove_backup_file', $md5);
850 do_action('bmi_premium_remove_backup_json_file', $md5 . '.json');
851 }
852 }
853
854 public function set_last_cron($status, $time) {
855 $file = BMI_TMP . DIRECTORY_SEPARATOR . '.last';
856 file_put_contents($file, $status . '.' . $time);
857 }
858
859 public function readFileSensitive($file) {
860 if (!file_exists($file)) {
861 echo '';
862 return;
863 }
864
865 $file = new \SplFileObject($file);
866 $file->seek($file->getSize());
867 $total_lines = $file->key() + 1;
868
869 $current_directory = Dashboard\bmi_get_config('STORAGE::LOCAL::PATH');
870 $backups_path = $this->fixSlashes($current_directory . DIRECTORY_SEPARATOR . 'backups');
871 $scanned_directory_all = array_diff(scandir($backups_path), ['..', '.']);
872 $scanned_directory = array_values(preg_grep('/((.*).zip)/i', $scanned_directory_all));
873
874 for ($i = 0; $i < $total_lines; ++$i) {
875
876 $file->seek($i);
877 $line = $this->escapeSensitive($file->current(), $current_directory, $scanned_directory);
878
879 echo $line;
880 unset($line);
881
882 }
883
884 }
885
886 public function escapeSensitive($line, $current_directory, $scanned_directory) {
887
888 global $table_prefix;
889
890 $dir_name = basename($current_directory);
891
892 $line = preg_replace('/\:\ ((.*)\.zip)/', ': *****.zip', $line);
893 $line = preg_replace('/(\"filename\":(.*)\.zip)\"/', '"filename": "*****.zip"', $line);
894 $line = preg_replace('/\"http(.*)\"/', '"***site_url***"', $line);
895 $line = preg_replace('/\:\ http(.*)\n/', ": ***site_url***\n", $line);
896 $line = preg_replace('/\"\d{10}\"/', '"***secret_login***"', $line);
897 $line = str_replace(ABSPATH, '***ABSPATH***/', $line);
898 $line = str_replace($dir_name, '***backup_path***', $line);
899 $line = str_replace($table_prefix, '***_', $line);
900 $line = preg_replace('/^(.*?&sk=).*$/', '$1***', $line);
901
902 for ($i = 0; $i < sizeof($scanned_directory); ++$i) {
903
904 $backup_name = $scanned_directory[$i];
905 $line = str_replace($backup_name, '***some_backup***', $line);
906
907 }
908
909 return $line;
910
911 }
912
913 public function handle_cron_backup() {
914
915 $plan_file = BMI_TMP . DIRECTORY_SEPARATOR . '.plan';
916 $last_file = BMI_TMP . DIRECTORY_SEPARATOR . '.last';
917
918 // Abort if disabled
919 if (Dashboard\bmi_get_config('CRON:ENABLED') !== true) {
920
921
922 if (file_exists($plan_file)) @unlink($plan_file);
923 if (file_exists($last_file)) @unlink($last_file);
924
925 return;
926
927 }
928
929 if (!file_exists($plan_file)) return;
930
931 // Planned time
932 $plan = intval(@file_get_contents(BMI_TMP . DIRECTORY_SEPARATOR . '.plan'));
933
934 // Check difference
935 if ((time() - $plan) > 3600) {
936 Logger::log('Backup failed to run on proper time, but running now.');
937 Logger::log('Planned time: ' . date('Y-m-d H:i:s', $plan));
938 $this->backup_inproper_time($plan);
939 }
940
941 // Now
942 $now = time();
943 $this->set_last_cron('0', $now);
944
945 // Extend execution time
946 if ($this->isFunctionEnabled('headers_sent') && $this->isFunctionEnabled('session_status')) {
947 if (!headers_sent() && session_status() === PHP_SESSION_DISABLED) {
948 if ($this->isFunctionEnabled('ignore_user_abort')) @ignore_user_abort(true);
949 if ($this->isFunctionEnabled('set_time_limit')) @set_time_limit(16000);
950 if ($this->isFunctionEnabled('ini_set')) {
951 @ini_set('max_execution_time', '259200');
952 @ini_set('max_input_time', '259200');
953 }
954 }
955 }
956
957 if (strlen(session_id()) > 0) session_write_close();
958
959 Logger::log(__("Automatic backup called at time: ", 'backup-backup') . date('Y-m-d, H:i:s'));
960
961 try {
962 require_once BMI_INCLUDES . '/ajax.php';
963 $isBackup = (file_exists(BMI_BACKUPS . '/.running') && (time() - filemtime(BMI_BACKUPS . '/.running')) <= 65) ? true : false;
964 $isCron = (file_exists(BMI_BACKUPS . '/.cron') && (time() - filemtime(BMI_BACKUPS . '/.cron')) <= 65) ? true : false;
965 if ($isCron) {
966 return;
967 }
968
969 if ($isBackup) {
970 $this->handle_cron_error(__("Could not make the backup: Backup already running, please wait till it complete.", 'backup-backup'));
971 $this->set_last_cron('2', $now);
972 } else {
973 touch(BMI_BACKUPS . '/.cron');
974
975 if (!defined('BMI_DOING_SCHEDULED_BACKUP')) {
976 define('BMI_DOING_SCHEDULED_BACKUP', true);
977 }
978
979 $handler = new BMI_Ajax();
980 $handler->resetLatestLogs();
981 $backup = $handler->prepareAndMakeBackup(true);
982
983 if ($backup['status'] == 'success') {
984 if (isset($backup['filename'])) {
985 Logger::log(__("Automatic backup successed: ", 'backup-backup') . $backup['filename']);
986 } else {
987 Logger::log(__("Automatic backup successed", 'backup-backup'));
988 }
989 $this->set_last_cron('1', $now);
990 } elseif ($backup['status'] == 'background') {
991 Logger::log(__('Scheduled backup is running in background: ', 'backup-backup') . $backup['filename']);
992 $this->set_last_cron('1', $now);
993 } elseif ($backup['status'] == 'msg') {
994 $this->handle_cron_error($backup['why']);
995 $this->set_last_cron('3', $now);
996 } else {
997 $this->handle_cron_error(__("Could not make the backup due to internal server error.", 'backup-backup'));
998 $this->set_last_cron('4', $now);
999 }
1000 }
1001 } catch (\Exception $e) {
1002 $this->handle_cron_error($e);
1003 $this->set_last_cron('5', $now);
1004 } catch (\Throwable $e) {
1005 $this->handle_cron_error($e);
1006 $this->set_last_cron('5', $now);
1007 }
1008
1009 $this->handle_after_cron();
1010
1011 if (file_exists(BMI_BACKUPS . '/.cron')) {
1012 @unlink(BMI_BACKUPS . '/.cron');
1013 }
1014 require_once BMI_INCLUDES . '/cron/handler.php';
1015 $time = $this->get_next_cron();
1016
1017 wp_clear_scheduled_hook('bmi_do_backup_right_now');
1018 wp_schedule_single_event($time, 'bmi_do_backup_right_now');
1019
1020 $file = BMI_TMP . DIRECTORY_SEPARATOR . '.plan';
1021 file_put_contents($file, $time);
1022 }
1023
1024 public function enqueue_scripts() {
1025
1026 // Global
1027 if (in_array(get_current_screen()->id, ['toplevel_page_backup-migration', 'plugins'])) { ?>
1028 <script type="text/javascript">
1029 let stars = '<?php echo plugin_dir_url(BMI_ROOT_FILE); ?>' + 'admin/images/stars.gif';
1030 let css_star = "background:url('" + stars + "')";
1031 document.addEventListener("DOMContentLoaded", function(event) {
1032 jQuery('[data-slug="backup-migration-pro"]').find('strong').html('<span>Backup Migration <b style="color: orange; ' + css_star + '">Pro</b></span>');
1033 jQuery('[data-slug="backup-backup-pro"]').find('strong').html('<span>Backup Migration <b style="color: orange; ' + css_star + '">Pro</b></span>');
1034 });
1035 </script>
1036 <?php }
1037
1038 // Only for BM Settings
1039 if (!in_array(get_current_screen()->id, ['toplevel_page_backup-migration', 'update-core', 'plugins', 'plugin-install', 'themes','customize', 'plugins-network', 'plugin-install-network', 'themes-network']) && $this->backupbliss_space_issues() === false) return;
1040 wp_enqueue_script('backup-migration-script', $this->get_asset('js', 'backup-migration.min.js'), ['jquery'], BMI_VERSION, true);
1041 wp_localize_script('backup-migration-script', 'bmiVariables', [
1042 'nonce' => wp_create_nonce('backup-migration-ajax'),
1043 'stgLoading' => __('Loading, please wait...', 'backup-backup'),
1044 'stgStagingDefaultName' => __('staging', 'backup-backup'),
1045 'urlCopies' => __('URL copied successfully', 'backup-backup'),
1046 'isBeforeUpdateEnabled' => dashboard\bmi_get_config('OTHER:TRIGGER:BEFORE:UPDATES') ? 'true' : 'false',
1047 'maxUploadSize' => $this->getMaxUploadSize()
1048 ]);
1049
1050 }
1051
1052 public function phpSizeToB($phpSize) {
1053
1054 $sSuffix = strtoupper(substr($phpSize, -1));
1055
1056 if (!in_array($sSuffix, array('P','T','G','M','K'))) {
1057 return (int) $phpSize;
1058 }
1059
1060 $iValue = substr($phpSize, 0, -1);
1061 switch ($sSuffix) {
1062 case 'P': $iValue *= 1024;
1063 case 'T': $iValue *= 1024;
1064 case 'G': $iValue *= 1024;
1065 case 'M': $iValue *= 1024;
1066 case 'K': $iValue *= 1024;
1067 break;
1068 }
1069
1070 return (int) $iValue;
1071
1072 }
1073
1074 public function getMaxUploadSize() {
1075 $ten = (10 * 1024 * 1024);
1076 $max = min($this->phpSizeToB(ini_get('post_max_size')), $this->phpSizeToB(ini_get('upload_max_filesize')), $ten);
1077 return intval($max / 1024 / 1024);
1078 }
1079
1080 public function enqueue_styles() {
1081
1082 // Global styles
1083 wp_enqueue_style('backup-migration-style-icon', $this->get_asset('css', 'bmi-plugin-icon.min.css'), [], BMI_VERSION);
1084
1085 // Only for BM Settings and Update Core page and if there's no backupbliss space issues do not include the stylesheet.
1086 if (!in_array(get_current_screen()->id, ['toplevel_page_backup-migration', 'update-core', 'plugins', 'plugin-install', 'themes','customize', 'plugins-network', 'plugin-install-network', 'themes-network']) && $this->backupbliss_space_issues() === false) return;
1087
1088 // Enqueue the style
1089 wp_enqueue_style('backup-migration-style', $this->get_asset('css', 'bmi-plugin.min.css'), [], BMI_VERSION);
1090
1091 }
1092
1093 public function handle_after_actions() {
1094
1095 // Handle After Migration actions
1096 $afterMigrationLock = BMI_TMP . DIRECTORY_SEPARATOR . '.migrationFinished';
1097 if (file_exists($afterMigrationLock)) {
1098 if (strpos(site_url(), 'tastewp') !== false) {
1099
1100 if (function_exists('wp_load_alloptions')) {
1101 wp_load_alloptions(true);
1102 }
1103
1104 update_option('__tastewp_redirection_performed', true);
1105 update_option('auto_smart_tastewp_redirect_performed', 1);
1106 update_option('tastewp_auto_activated', true);
1107 update_option('__tastewp_sub_requested', true);
1108
1109 }
1110
1111 unlink($afterMigrationLock);
1112 }
1113
1114 }
1115
1116 public function handle_downloading() {
1117 global $wpdb;
1118 @error_reporting(0);
1119 $autologin_file = BMI_BACKUPS . '/.autologin';
1120 $ip = '127.0.0.1';
1121 if (isset($_SERVER['HTTP_CLIENT_IP'])) {
1122 $ip = $_SERVER['HTTP_CLIENT_IP'];
1123 } else {
1124 if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
1125 $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
1126 }
1127 if ($ip === false) {
1128 if (isset($_SERVER['REMOTE_ADDR'])) $ip = $_SERVER['REMOTE_ADDR'];
1129 }
1130 }
1131 $allowed = ['BMI_BACKUP', 'BMI_BACKUP_LOGS', 'PROGRESS_LOGS', 'AFTER_RESTORE', 'CURL_BACKUP'];
1132 $get_bmi = !empty($_GET['backup-migration']) ? sanitize_text_field($_GET['backup-migration']) : false;
1133 $get_bid = !empty($_GET['backup-id']) ? sanitize_text_field($_GET['backup-id']) : false;
1134 $get_pid = !empty($_GET['progress-id']) ? sanitize_text_field($_GET['progress-id']) : false;
1135 $get_is_uncensored = !empty($_GET['uncensored']) ? sanitize_text_field($_GET['uncensored']) : false;
1136 $crons_enabled = !empty($_GET['crons']) ? sanitize_text_field($_GET['crons']) : false;
1137 $secret_key = !empty($_GET['sk']) ? sanitize_text_field($_GET['sk']) : false;
1138
1139 if (isset($get_bmi) && in_array($get_bmi, $allowed)) {
1140 if (isset($get_bid) && strlen($get_bid) > 0 && isset($secret_key) && $secret_key === Dashboard\bmi_get_config('REQUEST:SECRET')) {
1141 $type = $get_bmi;
1142
1143 if ($type == 'AFTER_RESTORE' && isset($get_pid)) {
1144 if (file_exists($autologin_file)) {
1145 $autoLoginMD = file_get_contents($autologin_file);
1146 $autoLoginMD = explode('_', $autoLoginMD);
1147 $aID = intval($autoLoginMD[0]);
1148 $aID2 = intval($autoLoginMD[0]) - 1;
1149 $aID3 = intval($autoLoginMD[0]) + 1;
1150 $aID4 = intval($autoLoginMD[0]) + 2;
1151 $aID5 = intval($autoLoginMD[0]) + 3;
1152 $aID6 = intval($autoLoginMD[0]) + 4;
1153 $aIP = $autoLoginMD[1];
1154 $aIZ = $autoLoginMD[2];
1155
1156 // Allow 1 second delay
1157 $timeIsProper = false;
1158 if ($aID === intval($get_bid)) $timeIsProper = true;
1159 if ($aID2 === intval($get_bid)) $timeIsProper = true;
1160 if ($aID3 === intval($get_bid)) $timeIsProper = true;
1161 if ($aID4 === intval($get_bid)) $timeIsProper = true;
1162 if ($aID5 === intval($get_bid)) $timeIsProper = true;
1163 if ($aID6 === intval($get_bid)) $timeIsProper = true;
1164
1165 if ($timeIsProper && $aIP === $ip && trim($aIZ) === $get_pid) {
1166 $query = new \WP_User_Query(['role' => 'Administrator', 'count_total' => false, 'fields' => 'all']);
1167 $sqlres = $wpdb->get_results($query->request);
1168
1169 if (sizeof($sqlres) > 0 && isset($sqlres[0]->ID) && isset($sqlres[0]->user_login)) {
1170
1171 $user = $sqlres[0];
1172 $adminID = $sqlres[0]->ID;
1173 $adminLogin = $sqlres[0]->user_login;
1174
1175 remove_all_actions('wp_login', -1000);
1176 wp_load_alloptions(true);
1177 clean_user_cache(get_current_user_id());
1178 clean_user_cache($adminID);
1179 wp_clear_auth_cookie();
1180 wp_set_current_user($adminID, $adminLogin);
1181 wp_set_auth_cookie($adminID, 1, is_ssl());
1182 do_action('wp_login', $adminLogin, $user);
1183 update_user_caches($user);
1184
1185 }
1186 $cronsEnabledParam = $crons_enabled ? "&crons=true" : "";
1187
1188 $url = admin_url('admin.php?page=backup-migration' . $cronsEnabledParam);
1189 header('Location: ' . $url);
1190
1191 @unlink($autologin_file);
1192 exit;
1193 }
1194 }
1195
1196 } else if ($type == 'BMI_BACKUP') {
1197 if (Dashboard\bmi_get_config('STORAGE::DIRECT::URL') === 'true' || current_user_can('administrator')) {
1198
1199 $backupname = $get_bid;
1200 $file = $this->fixSlashes(BMI_BACKUPS . DIRECTORY_SEPARATOR . $backupname);
1201
1202 $outsideDir = false;
1203 if (!(file_exists($file) && $this->fixSlashes(dirname($file)) == $this->fixSlashes(BMI_BACKUPS))) {
1204 $outsideDir = true;
1205 }
1206
1207 if ($outsideDir || strpos(strtolower(mime_content_type($file)), 'zip') === false) {
1208 header('HTTP/1.0 423 Locked');
1209 _e("Incorrect usage of the query request.", 'backup-backup');
1210 exit;
1211 }
1212
1213 if (Dashboard\bmi_get_config('OTHER:DOWNLOAD:DIRECT') == 'true') {
1214 if (file_exists(BMI_BACKUPS . DIRECTORY_SEPARATOR . '.htaccess')) @unlink(BMI_BACKUPS . DIRECTORY_SEPARATOR . '.htaccess');
1215 if (file_exists(dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . '.htaccess')) @unlink(dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . '.htaccess');
1216 $wpcontent = trailingslashit(WP_CONTENT_DIR);
1217 $wpcs = strlen($wpcontent);
1218 $url = $this->fixSlashes(content_url(substr($file, $wpcs)), '/');
1219 $path = wp_redirect($url);
1220 exit;
1221 }
1222
1223 // Prevent parent directory downloading
1224 if (ob_get_contents()) ob_end_clean();
1225
1226 if ($this->isFunctionEnabled('ignore_user_abort')) @ignore_user_abort(true);
1227 if ($this->isFunctionEnabled('set_time_limit')) @set_time_limit(16000);
1228 if ($this->isFunctionEnabled('headers_sent') && $this->isFunctionEnabled('session_status')) {
1229 if (!headers_sent() && session_status() === PHP_SESSION_DISABLED) {
1230 if ($this->isFunctionEnabled('ini_set')) {
1231 @ini_set('max_execution_time', '259200');
1232 @ini_set('max_input_time', '259200');
1233 @ini_set('memory_limit', '-1');
1234 if (@ini_get('zlib.output_compression')) {
1235 @ini_set('zlib.output_compression', 'Off');
1236 }
1237 }
1238 }
1239 }
1240
1241 if (strlen(session_id()) > 0) session_write_close();
1242
1243 $fp = @fopen($file, 'rb');
1244
1245 // header('X-Sendfile: ' . $file);
1246 // header('X-Sendfile-Type: X-Accel-Redirect');
1247 // header('X-Accel-Redirect: ' . $file);
1248 // header('X-Accel-Buffering: yes');
1249 header('Expires: 0');
1250 header('Pragma: public');
1251 header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
1252 header('Content-Disposition: attachment; filename="' . $backupname . '"');
1253 header('Content-Type: application/octet-stream');
1254 header('Content-Transfer-Encoding: binary');
1255 header('Content-Length: ' . filesize($file));
1256 header('Content-Description: File Transfer');
1257 http_response_code(200);
1258
1259 if (ob_get_level()) ob_end_clean();
1260
1261 fpassthru($fp);
1262 fclose($fp);
1263 exit;
1264
1265 } else {
1266 if (ob_get_contents()) ob_end_clean();
1267 header('HTTP/1.0 423 Locked');
1268 if (ob_get_level()) ob_end_clean();
1269 echo __("Backup download is restricted (allowed for admins only).", 'backup-backup');
1270 exit;
1271 }
1272 } else if ($type == 'BMI_BACKUP_LOGS') {
1273
1274 // Only Admin can download backup logs
1275 if (!(current_user_can('administrator') || current_user_can('do_backups'))) return;
1276
1277 if (ob_get_contents()) ob_end_clean();
1278 $backupname = $get_bid;
1279 $file = $this->fixSlashes(BMI_BACKUPS . DIRECTORY_SEPARATOR . $backupname);
1280
1281 // Prevent parent directory downloading
1282 if (file_exists($file) && $this->fixSlashes(dirname($file)) == $this->fixSlashes(BMI_BACKUPS)) {
1283 require_once BMI_INCLUDES . '/zipper/zipping.php';
1284
1285 $zipper = new Zipper();
1286 $logs = $zipper->getZipFileContentPlain($file, 'bmi_logs_this_backup.log');
1287 header('Content-Type: text/plain');
1288
1289 if ($logs) {
1290 header('Content-Disposition: attachment; filename="' . substr($backupname, 0, -4) . '.log"');
1291 http_response_code(200);
1292 if (ob_get_level()) ob_end_clean();
1293
1294 $logs = explode('\n', $logs);
1295 $current_directory = Dashboard\bmi_get_config('STORAGE::LOCAL::PATH');
1296 $backups_path = $this->fixSlashes($current_directory . DIRECTORY_SEPARATOR . 'backups');
1297 $scanned_directory_all = array_diff(scandir($backups_path), ['..', '.']);
1298 $scanned_directory = array_values(preg_grep('/((.*).zip)/i', $scanned_directory_all));
1299
1300 for ($i = 0; $i < sizeof($logs); ++$i) {
1301
1302 $line = $logs[$i];
1303 echo $this->escapeSensitive($line, $current_directory, $scanned_directory) . "\n";
1304
1305 }
1306
1307 exit;
1308 } else {
1309 if (ob_get_level()) ob_end_clean();
1310 header('HTTP/1.0 404 Not found');
1311 echo __("There was an error during getting logs, this file is not right log file.", 'backup-backup');
1312 exit;
1313 }
1314 }
1315
1316 } else if ($type == 'PROGRESS_LOGS') {
1317 $allowed_progress = [
1318 'latest_full.log',
1319 'latest.log',
1320 'latest_progress.log',
1321 'latest_migration_full.log',
1322 'latest_migration.log',
1323 'latest_migration_progress.log',
1324 'latest_staging_full.log',
1325 'latest_staging.log',
1326 'latest_staging_progress.log',
1327 'complete_logs.log'
1328 ];
1329 if (isset($get_pid) && in_array($get_pid, $allowed_progress)) {
1330
1331 $restricted_progress = ['complete_logs.log'];
1332 if (in_array($get_pid, $restricted_progress)) {
1333
1334 // Only Admin can download backup logs
1335 if (!(current_user_can('administrator') || current_user_can('do_backups'))) return;
1336
1337 }
1338
1339 header('Content-Type: text/plain');
1340 header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
1341 http_response_code(200);
1342 if (ob_get_contents()) ob_end_clean();
1343 if ($get_pid == 'complete_logs.log') {
1344 $file = BMI_CONFIG_DIR . DIRECTORY_SEPARATOR . 'complete_logs.log';
1345 if (ob_get_level()) ob_end_clean();
1346 $this->readFileSensitive($file);
1347 exit;
1348 } else if ($get_pid == 'latest_full.log') {
1349 $progress = dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . 'latest_progress.log';
1350 $logs = dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . 'latest.log';
1351 if ((file_exists($progress) && file_exists($logs) && ((time() - filemtime($progress)) < (60 * 1))) || current_user_can('administrator')) {
1352 if (ob_get_level()) ob_end_clean();
1353 readfile($progress);
1354 echo "\n";
1355 if (isset($get_is_uncensored) && $get_is_uncensored && current_user_can('administrator')) readfile($logs);
1356 else $this->readFileSensitive($logs);
1357 exit;
1358 } else {
1359 if (file_exists($progress) && !(time() - filemtime($progress)) < (60 * 1)) {
1360 if (ob_get_level()) ob_end_clean();
1361 echo __("Due to security reasons access to this file is disabled at this moment.", 'backup-backup') . "\n";
1362 echo __("Human readable: file expired.", 'backup-backup');
1363 exit;
1364 } else {
1365 if (ob_get_level()) ob_end_clean();
1366 echo '';
1367 exit;
1368 }
1369 }
1370 } else if ($get_pid == 'latest_migration_full.log') {
1371 $progress = dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . 'latest_migration_progress.log';
1372 $logs = dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . 'latest_migration.log';
1373 if ((file_exists($progress) && file_exists($logs) && ((time() - filemtime($progress)) < (60 * 1))) || current_user_can('administrator')) {
1374 if (ob_get_level()) ob_end_clean();
1375 readfile($progress);
1376 echo "\n";
1377 if (isset($get_is_uncensored) && $get_is_uncensored && current_user_can('administrator')) readfile($logs);
1378 else $this->readFileSensitive($logs);
1379 exit;
1380 } else {
1381 if (file_exists($progress) && !(time() - filemtime($progress)) < (60 * 1)) {
1382 if (ob_get_level()) ob_end_clean();
1383 echo __("Due to security reasons access to this file is disabled at this moment.", 'backup-backup') . "\n";
1384 echo __("Human readable: file expired.", 'backup-backup');
1385 exit;
1386 } else {
1387 if (ob_get_level()) ob_end_clean();
1388 echo '';
1389 exit;
1390 }
1391 }
1392 } else if ($get_pid == 'latest_staging_full.log') {
1393 $progress = BMI_STAGING . DIRECTORY_SEPARATOR . 'latest_staging_progress.log';
1394 $logs = BMI_STAGING . DIRECTORY_SEPARATOR . 'latest_staging.log';
1395 if ((file_exists($progress) && file_exists($logs) && ((time() - filemtime($progress)) < (60 * 1))) || current_user_can('administrator')) {
1396 if (ob_get_level()) ob_end_clean();
1397 readfile($progress);
1398 echo "\n";
1399 $this->readFileSensitive($logs);
1400 exit;
1401 } else {
1402 if (file_exists($progress) && !(time() - filemtime($progress)) < (60 * 1)) {
1403 if (ob_get_level()) ob_end_clean();
1404 echo __("Due to security reasons access to this file is disabled at this moment.", 'backup-backup') . "\n";
1405 echo __("Human readable: file expired.", 'backup-backup');
1406 exit;
1407 } else {
1408 if (ob_get_level()) ob_end_clean();
1409 echo '';
1410 exit;
1411 }
1412 }
1413 } else {
1414 $file = dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . $get_pid;
1415 if ($get_pid == 'latest_staging.log') $file = BMI_STAGING . DIRECTORY_SEPARATOR . $get_pid;
1416 if ($get_pid == 'latest_staging_progress.log') $file = BMI_STAGING . DIRECTORY_SEPARATOR . $get_pid;
1417 if (file_exists($file) && (((time() - filemtime($file)) < (60 * 1)) || current_user_can('administrator'))) {
1418 if (ob_get_level()) ob_end_clean();
1419
1420 if (isset($get_is_uncensored) && $get_is_uncensored && current_user_can('administrator')) readfile($file);
1421 else $this->readFileSensitive($file);
1422
1423 echo "\n";
1424 if ($get_pid == 'latest.log') $file = dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . 'latest_progress.log';
1425 if ($get_pid == 'latest_migration.log') $file = dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . 'latest_migration_progress.log';
1426 if ($get_pid == 'latest_staging.log') $file = BMI_STAGING . DIRECTORY_SEPARATOR . 'latest_staging_progress.log';
1427 echo __("[DOWNLOAD GENERATED] File downloaded on (server time): ", 'backup-backup') . date('Y-m-d H:i:s') . "\n";
1428 echo __("[DOWNLOAD GENERATED] Last update (seconds): ", 'backup-backup') . (time() - filemtime($file)) . __(" seconds ago ", 'backup-backup') . "\n";
1429 echo __("[DOWNLOAD GENERATED] Last update (date): ", 'backup-backup') . date('Y-m-d H:i:s', filemtime($file)) . " \n";
1430 exit;
1431 } else {
1432 if (file_exists($file) && !(time() - filemtime($file)) < (60 * 1)) {
1433 if (ob_get_level()) ob_end_clean();
1434 echo __("Due to security reasons access to this file is disabled at this moment.", 'backup-backup') . "\n";
1435 echo __("Human readable: file expired.", 'backup-backup');
1436 exit;
1437 } else {
1438 if (ob_get_level()) ob_end_clean();
1439 echo '';
1440 exit;
1441 }
1442 }
1443 }
1444 }
1445 } else if ($type == 'CURL_BACKUP') {
1446
1447 // We tried to use nonces here, but turns out that WordPress does not work well with generating nonces for cURL session.
1448 // We also tries to use cookiejar etc. but for researchers, this function is "verified" by process identy.
1449 // It's similarly safe as nonce, but it works in case we need, nonces gets rejected after second request.
1450 //
1451 // At the end, user who indeed would like to abuse this functionality, he can't do anything than helping the site owner.
1452 // Free browser will keep the process ongoing, user won't receive any details other than "success" - as long as the user know the process identy.
1453
1454 try {
1455
1456 // Load bypasser
1457 require_once BMI_INCLUDES . '/backup-process.php';
1458 $request = new Bypasser($get_bid, BMI_CONFIG_DIR, trailingslashit(WP_CONTENT_DIR), BMI_BACKUPS, trailingslashit(ABSPATH), plugin_dir_path(BMI_ROOT_FILE));
1459
1460 if (sizeof($request->remote_settings) === 0) return;
1461
1462 // Handle request
1463 $request->handle_batch();
1464 exit;
1465
1466 } catch (\Exception $e) {
1467
1468 error_log('There was an error with Backup Migration plugin: ' . $e->getMessage());
1469 Logger::error(__('Error handler: ', 'backup-backup') . 'ajax#01' . '|' . $e->getMessage());
1470 error_log(strval($e));
1471
1472 } catch (\Throwable $t) {
1473
1474 error_log('There was an error with Backup Migration plugin: ' . $t->getMessage());
1475 Logger::error(__('Error handler: ', 'backup-backup') . 'ajax#01' . '|' . $t->getMessage());
1476 error_log(strval($t));
1477
1478 }
1479
1480 }
1481 }
1482 }
1483 }
1484
1485 public function deactivation() {
1486 Logger::log(__("Plugin has been deactivated", 'backup-backup'));
1487 $this->revertLitespeed();
1488 }
1489
1490 public static function res($array) {
1491 $GLOBALS['BMI::RESPONSE::SENT'] = true;
1492 echo json_encode(Backup_Migration_Plugin::sanitize($array));
1493
1494 if (defined('BMI_USING_CLI_FUNCTIONALITY') && BMI_USING_CLI_FUNCTIONALITY === true) {
1495 Logger::log('CLI response:');
1496 Logger::log(json_encode(Backup_Migration_Plugin::sanitize($array)));
1497 }
1498
1499 exit;
1500 }
1501
1502 public static function getAvailableMemoryInBytes() {
1503
1504 $totalMemory = @ini_get('memory_limit');
1505 if ($totalMemory == -1) {
1506
1507 $totalMemory = 32 * 1024 * 1024;
1508
1509 } else {
1510
1511 if (strpos($totalMemory, 'M') !== false || strpos($totalMemory, 'm') !== false) {
1512 $totalMemory = intval($totalMemory) * 1024 * 1024;
1513 } else if (strpos($totalMemory, 'G') !== false || strpos($totalMemory, 'g') !== false) {
1514 $totalMemory = intval($totalMemory) * 1024 * 1024 * 1024;
1515 } else if (strpos($totalMemory, 'K') !== false || strpos($totalMemory, 'k') !== false) {
1516 $totalMemory = intval($totalMemory) * 1024;
1517 } else {
1518 $totalMemory = intval($totalMemory);
1519 }
1520
1521 }
1522
1523 $availableMemory = $totalMemory - memory_get_usage(true);
1524
1525 return $availableMemory;
1526
1527 }
1528
1529 public static function sanitize($data = []) {
1530 $array = [];
1531
1532 if (is_array($data) || is_object($data)) {
1533 foreach ($data as $key => $value) {
1534 $key = ((is_numeric($key))?intval($key):sanitize_text_field($key));
1535
1536 if (is_array($value) || is_object($value)) {
1537 $array[$key] = Backup_Migration_Plugin::sanitize($value);
1538 } else {
1539 $array[$key] = sanitize_text_field($value);
1540 }
1541 }
1542 } elseif (is_string($data)) {
1543 return sanitize_text_field($data);
1544 } elseif (is_bool($data)) {
1545 return $data;
1546 } elseif (is_null($data)) {
1547 return 'false';
1548 } else {
1549 Logger::log(__("Unknow AJAX Sanitize Type: ", 'backup-backup') . gettype($data));
1550 wp_die();
1551 }
1552
1553 return $array;
1554 }
1555
1556 public static function fixLitespeed() {
1557 $litepath = BMI_INCLUDES . DIRECTORY_SEPARATOR . 'htaccess' . DIRECTORY_SEPARATOR . '.litespeed';
1558 $htpath = ABSPATH . DIRECTORY_SEPARATOR . '.htaccess';
1559 if (!is_writable($htpath)) return ['status' => 'success'];
1560 if (file_exists($htpath)) {
1561 Backup_Migration_Plugin::revertLitespeed();
1562 $litespeed = @file_get_contents($litepath);
1563 $htaccess = @file_get_contents($htpath);
1564 $htaccess = explode("\n", $htaccess);
1565 $litespeed = explode("\n", $litespeed);
1566
1567 $hasAlready = false;
1568 for ($i = 0; $i < sizeof($htaccess); ++$i) {
1569 if (strpos($htaccess[$i], 'Backup Migration') !== false) {
1570 $hasAlready = true;
1571
1572 break;
1573 }
1574 }
1575
1576 if ($hasAlready) {
1577 return ['status' => 'success'];
1578 }
1579 $htaccess[] = '';
1580 for ($i = 0; $i < sizeof($litespeed); ++$i) {
1581 $htaccess[] = $litespeed[$i];
1582 }
1583
1584 file_put_contents($htpath, implode("\n", $htaccess));
1585 } else {
1586 copy($litepath, $htpath);
1587 }
1588
1589 return ['status' => 'success'];
1590 }
1591
1592 public static function revertLitespeed() {
1593 $htpath = ABSPATH . DIRECTORY_SEPARATOR . '.htaccess';
1594 $addline = true;
1595
1596 if (!is_writable($htpath)) return ['status' => 'success'];
1597 $htaccess = @file_get_contents($htpath);
1598 $htaccess = explode("\n", $htaccess);
1599 $htFilter = [];
1600
1601 for ($i = 0; $i < sizeof($htaccess); ++$i) {
1602 if (strpos($htaccess[$i], 'Backup Migration START')) {
1603 $addline = false;
1604
1605 continue;
1606 } elseif (strpos($htaccess[$i], 'Backup Migration END')) {
1607 $addline = true;
1608
1609 continue;
1610 } else {
1611 if ($addline == true) {
1612 $htFilter[] = $htaccess[$i];
1613 }
1614 }
1615 }
1616
1617 file_put_contents($htpath, trim(implode("\n", $htFilter)));
1618
1619 return ['status' => 'success'];
1620 }
1621
1622 public static function humanSize($bytes) {
1623 if (is_int($bytes)) {
1624 $label = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
1625 for ($i = 0; $bytes >= 1024 && $i < (count($label) - 1); $bytes /= 1024, $i++);
1626
1627 return (round($bytes, 2) . " " . $label[$i]);
1628 } else return $bytes;
1629 }
1630
1631 public static function fixSlashes($str, $slash = false) {
1632 // Old version
1633 // $str = str_replace('\\\\', DIRECTORY_SEPARATOR, $str);
1634 // $str = str_replace('\\', DIRECTORY_SEPARATOR, $str);
1635 // $str = str_replace('\/', DIRECTORY_SEPARATOR, $str);
1636 // $str = str_replace('/', DIRECTORY_SEPARATOR, $str);
1637
1638 // if ($str[strlen($str) - 1] == DIRECTORY_SEPARATOR) {
1639 // $str = substr($str, 0, -1);
1640 // }
1641
1642 // Since 1.3.2
1643 $protocol = '';
1644 if ($slash == false) $slash = DIRECTORY_SEPARATOR;
1645 if (substr($str, 0, 7) == 'http://') $protocol = 'http://';
1646 else if (substr($str, 0, 8) == 'https://') $protocol = 'https://';
1647
1648 $str = substr($str, strlen($protocol));
1649 $str = preg_replace('/[\\\\\/]+/', $slash, $str);
1650 $str = untrailingslashit($str);
1651
1652 return $protocol . $str;
1653 }
1654
1655 public static function canShareLogsOrShouldAsk() {
1656
1657 return 'not-allowed';
1658
1659 // REMOVED CODE:
1660 // $isAllowed = get_option('BMI_LOGS_SHARING_IS_ALLOWED', 'unknown');
1661 // $isAllowedConfig = Dashboard\bmi_get_config('LOGS::SHARING');
1662 //
1663 // if ($isAllowed == 'unknown' || empty($isAllowedConfig)) return 'ask';
1664 // else if ($isAllowed === 'yes' && $isAllowedConfig === 'yes') {
1665 // return 'allowed';
1666 // } else if ($isAllowed === 'no' && $isAllowedConfig === 'no') {
1667 // return 'not-allowed';
1668 // } else return 'ask';
1669
1670 }
1671
1672 public static function getRecentSize() {
1673 $folderNames = [ 'BACKUP:DATABASE' => 'database',
1674 "BACKUP:FILES::PLUGINS" => 'plugins',
1675 "BACKUP:FILES::UPLOADS" => 'uploads',
1676 "BACKUP:FILES::THEMES" => 'themes',
1677 "BACKUP:FILES::OTHERS" => 'contents_others',
1678 "BACKUP:FILES::WP" => 'wordpress'
1679 ];
1680
1681 $size = 0;
1682 foreach ($folderNames as $setting => $fileName) {
1683 if (Dashboard\bmi_get_config($setting) === 'true') {
1684 $size += get_transient('bmi_latest_size_' . $fileName);
1685 }
1686
1687 }
1688 return $size;
1689 }
1690
1691 public static function merge_arrays(&$array1, &$array2) {
1692 for ($i = 0; $i < sizeof($array2); ++$i) {
1693 $array1[] = $array2[$i];
1694 }
1695 }
1696
1697 public static function getDefaultDisabledPaths() {
1698 require_once BMI_INCLUDES . '/staging/controller.php';
1699 $staging = new Staging('..ajax..');
1700 $stagingSites = $staging->getStagingSites(true);
1701 $stagingSitesPaths = [];
1702 // Get all directory names of staging sites
1703 foreach ($stagingSites as $index => $site) {
1704
1705 // Convert every directory to their location path
1706 $stagingSitesPaths[] = '***ABSPATH***/' . $site['name'];
1707
1708 }
1709
1710 $ignored_paths_default = [
1711 BMI_CONFIG_DIR,
1712 BMI_BACKUPS,
1713 BMI_ROOT_DIR,
1714 constant('BMI_PRO_ROOT_DIR'),
1715 "***ABSPATH***/wp-content/ai1wm-backups",
1716 "***ABSPATH***/wp-content/ai1wm-backups-old",
1717 "***ABSPATH***/wp-content/mwp-download",
1718 "***ABSPATH***/wp-content/uploads/wp-clone",
1719 "***ABSPATH***/wp-content/updraft",
1720 "***ABSPATH***/wp-content/backups-dup-pro",
1721 "***ABSPATH***/wp-content/wpvividbackups",
1722 "***ABSPATH***/wp-content/backup-guard",
1723 "***ABSPATH***/wp-content/backuply",
1724 "***ABSPATH***/wp-content/backups-dup-lite",
1725 "***ABSPATH***/wp-content/uploads/backupbuddy_backups",
1726 "***ABSPATH***/wp-content/uploads/wp-file-manager-pro",
1727 "***ABSPATH***/wp-content/uploads/wp-file-manager",
1728 "***ABSPATH***/wp-content/plugins/akeebabackupwp",
1729 "***ABSPATH***/wp-content/uploads/jetbackup",
1730 "***ABSPATH***/wp-content/uploads/backup-guard",
1731 "***ABSPATH***/wp-content/uploads/wp-migrate-db",
1732 "***ABSPATH***/wp-content/uploads/wpforms/.htaccess.cpmh3129",
1733 "***ABSPATH***/wp-content/uploads/gravity_forms/.htaccess.cpmh3129",
1734 "***ABSPATH***/.htaccess.cpmh3129",
1735 "***ABSPATH***/logs/traffic.html/.md5sums",
1736 "***ABSPATH***/wp-config.php",
1737 "***ABSPATH***/wp-content/backup-migration-config.php",
1738 ];
1739 $ignored_paths = array_merge($ignored_paths_default, $stagingSitesPaths);
1740 array_walk($ignored_paths, function(&$path){
1741 $path = self::fixSlashes(str_replace('***ABSPATH***', ABSPATH, $path));
1742 });
1743 return $ignored_paths;
1744 }
1745
1746 private function get_asset($base = '', $asset = '') {
1747 return BMI_ASSETS . '/' . $base . '/' . $asset;
1748 }
1749
1750 /**
1751 * Extend the execution time for the plugin
1752 *
1753 * @return void
1754 */
1755 public static function extend_execution_time() {
1756 if (self::isFunctionEnabled('headers_sent') && self::isFunctionEnabled('session_status')) {
1757 if (!headers_sent() && session_status() === PHP_SESSION_DISABLED) {
1758 if (self::isFunctionEnabled('ignore_user_abort')) @ignore_user_abort(true);
1759 if (self::isFunctionEnabled('set_time_limit')) @set_time_limit(16000);
1760 if (self::isFunctionEnabled('ini_set')) {
1761 @ini_set('max_execution_time', '259200');
1762 @ini_set('max_input_time', '259200');
1763 }
1764 }
1765 }
1766 }
1767
1768 public static function getRetryAfterIfAvailable($ch, $response)
1769 {
1770 $phpVersion = phpversion();
1771 $curlVersion = curl_version();
1772 // Available as of PHP 8.2.0 and cURL 7.66.0
1773 if (version_compare($phpVersion, '8.2.0', '>=') && version_compare($curlVersion['version'], '7.66.0', '>=')) {
1774 $retryAfter = curl_getinfo($ch, CURLINFO_RETRY_AFTER);
1775 if ($retryAfter !== false) {
1776 return $retryAfter;
1777 }
1778 }else {
1779 $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
1780 $header = substr($response, 0, $header_size);
1781 $headers = explode("\r\n", $header);
1782 foreach ($headers as $h) {
1783 if (preg_match('/^Retry-After:\s+(\d+)/i', $h, $matches)) {
1784 return intval($matches[1]);
1785 }
1786 }
1787 }
1788 return false;
1789
1790 }
1791 }
1792