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