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