PluginProbe ʕ •ᴥ•ʔ
Backup Migration / 1.3.2
Backup Migration v1.3.2
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 .htaccess 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
1482 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 (isset($_SERVER['REQUEST_METHOD']) && $_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 'maxUploadSize' => $this->getMaxUploadSize()
899 ], true);
900
901 }
902
903 public function phpSizeToB($phpSize) {
904
905 $sSuffix = strtoupper(substr($phpSize, -1));
906
907 if (!in_array($sSuffix, array('P','T','G','M','K'))) {
908 return (int) $phpSize;
909 }
910
911 $iValue = substr($phpSize, 0, -1);
912 switch ($sSuffix) {
913 case 'P': $iValue *= 1024;
914 case 'T': $iValue *= 1024;
915 case 'G': $iValue *= 1024;
916 case 'M': $iValue *= 1024;
917 case 'K': $iValue *= 1024;
918 break;
919 }
920
921 return (int) $iValue;
922
923 }
924
925 public function getMaxUploadSize() {
926 $ten = (10 * 1024 * 1024);
927 $max = min($this->phpSizeToB(ini_get('post_max_size')), $this->phpSizeToB(ini_get('upload_max_filesize')), $ten);
928 return ($max / 1024 / 1024);
929 }
930
931 public function enqueue_styles() {
932
933 // Global styles
934 wp_enqueue_style('backup-migration-style-icon', $this->get_asset('css', 'bmi-plugin-icon.min.css'), [], BMI_VERSION);
935
936 // Only for BM Settings
937 if (get_current_screen()->id != 'toplevel_page_backup-migration') return;
938
939 // Enqueue the style
940 wp_enqueue_style('backup-migration-style', $this->get_asset('css', 'bmi-plugin.min.css'), [], BMI_VERSION);
941
942 }
943
944 public function handle_after_actions() {
945
946 // Handle After Migration actions
947 $afterMigrationLock = BMI_INCLUDES . DIRECTORY_SEPARATOR . 'htaccess' . DIRECTORY_SEPARATOR . '.migrationFinished';
948 if (file_exists($afterMigrationLock)) {
949 if (strpos(site_url(), 'tastewp') !== false) {
950
951 if (function_exists('wp_load_alloptions')) {
952 wp_load_alloptions(true);
953 }
954
955 update_option('__tastewp_redirection_performed', true);
956 update_option('auto_smart_tastewp_redirect_performed', 1);
957 update_option('tastewp_auto_activated', true);
958 update_option('__tastewp_sub_requested', true);
959
960 }
961
962 unlink($afterMigrationLock);
963 }
964
965 }
966
967 public function handle_downloading() {
968 global $wpdb;
969 @error_reporting(0);
970 $autologin_file = BMI_BACKUPS . '/.autologin';
971 $ip = '127.0.0.1';
972 if (isset($_SERVER['HTTP_CLIENT_IP'])) {
973 $ip = $_SERVER['HTTP_CLIENT_IP'];
974 } else {
975 if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
976 $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
977 }
978 if ($ip === false) {
979 if (isset($_SERVER['REMOTE_ADDR'])) $ip = $_SERVER['REMOTE_ADDR'];
980 }
981 }
982 $allowed = ['BMI_BACKUP', 'BMI_BACKUP_LOGS', 'PROGRESS_LOGS', 'AFTER_RESTORE'];
983 $get_bmi = !empty($_GET['backup-migration']) ? sanitize_text_field($_GET['backup-migration']) : false;
984 $get_bid = !empty($_GET['backup-id']) ? sanitize_text_field($_GET['backup-id']) : false;
985 $get_pid = !empty($_GET['progress-id']) ? sanitize_text_field($_GET['progress-id']) : false;
986
987 if (isset($get_bmi) && in_array($get_bmi, $allowed)) {
988 if (isset($get_bid) && strlen($get_bid) > 0) {
989 $type = $get_bmi;
990
991 if ($type == 'AFTER_RESTORE' && isset($get_pid)) {
992 if (file_exists($autologin_file)) {
993 $autoLoginMD = file_get_contents($autologin_file);
994 $autoLoginMD = explode('_', $autoLoginMD);
995 $aID = intval($autoLoginMD[0]);
996 $aID2 = intval($autoLoginMD[0]) - 1;
997 $aID3 = intval($autoLoginMD[0]) + 1;
998 $aID4 = intval($autoLoginMD[0]) + 2;
999 $aID5 = intval($autoLoginMD[0]) + 3;
1000 $aID6 = intval($autoLoginMD[0]) + 4;
1001 $aIP = $autoLoginMD[1];
1002 $aIZ = $autoLoginMD[2];
1003
1004 // Allow 1 second delay
1005 $timeIsProper = false;
1006 if ($aID === intval($get_bid)) $timeIsProper = true;
1007 if ($aID2 === intval($get_bid)) $timeIsProper = true;
1008 if ($aID3 === intval($get_bid)) $timeIsProper = true;
1009 if ($aID4 === intval($get_bid)) $timeIsProper = true;
1010 if ($aID5 === intval($get_bid)) $timeIsProper = true;
1011 if ($aID6 === intval($get_bid)) $timeIsProper = true;
1012
1013 if ($timeIsProper && $aIP === $ip && trim($aIZ) === $get_pid) {
1014 $query = new \WP_User_Query(['role' => 'Administrator', 'count_total' => false, 'fields' => ['ID', 'user_login']]);
1015 $sqlres = $wpdb->get_results($query->request);
1016
1017 if (sizeof($sqlres) > 0 && isset($sqlres[0]->ID) && isset($sqlres[0]->user_login)) {
1018
1019 $user = $sqlres[0];
1020 $adminID = $sqlres[0]->ID;
1021 $adminLogin = $sqlres[0]->user_login;
1022
1023 remove_all_actions('wp_login', -1000);
1024 wp_load_alloptions(true);
1025 clean_user_cache(get_current_user_id());
1026 clean_user_cache($adminID);
1027 wp_clear_auth_cookie();
1028 wp_set_current_user($adminID, $adminLogin);
1029 wp_set_auth_cookie($adminID, 1, is_ssl());
1030 do_action('wp_login', $adminLogin, $user);
1031 update_user_caches($user);
1032
1033 }
1034
1035 $url = admin_url('admin.php?page=backup-migration');
1036 header('Location: ' . $url);
1037
1038 @unlink($autologin_file);
1039 exit;
1040 }
1041 }
1042
1043 } else if ($type == 'BMI_BACKUP') {
1044 if (Dashboard\bmi_get_config('STORAGE::DIRECT::URL') === 'true' || current_user_can('administrator')) {
1045
1046 $backupname = $get_bid;
1047 $file = $this->fixSlashes(BMI_BACKUPS . DIRECTORY_SEPARATOR . $backupname);
1048
1049 if (Dashboard\bmi_get_config('OTHER:DOWNLOAD:DIRECT') == 'true') {
1050 if (file_exists(BMI_BACKUPS . DIRECTORY_SEPARATOR . '.htaccess')) @unlink(BMI_BACKUPS . DIRECTORY_SEPARATOR . '.htaccess');
1051 if (file_exists(dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . '.htaccess')) @unlink(dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . '.htaccess');
1052 $wpcontent = trailingslashit(WP_CONTENT_DIR);
1053 $wpcs = strlen($wpcontent);
1054 $url = $this->fixSlashes(content_url(substr($file, $wpcs)), '/');
1055 $path = wp_redirect($url);
1056 exit;
1057 }
1058
1059 // Prevent parent directory downloading
1060 if (file_exists($file) && $this->fixSlashes(dirname($file)) == $this->fixSlashes(BMI_BACKUPS)) {
1061 if (ob_get_contents()) ob_end_clean();
1062
1063 if ($this->isFunctionEnabled('ignore_user_abort')) @ignore_user_abort(true);
1064 if ($this->isFunctionEnabled('set_time_limit')) @set_time_limit(16000);
1065 if ($this->isFunctionEnabled('headers_sent') && $this->isFunctionEnabled('session_status')) {
1066 if (!headers_sent() && session_status() === PHP_SESSION_DISABLED) {
1067 if ($this->isFunctionEnabled('ini_set')) {
1068 @ini_set('max_execution_time', '259200');
1069 @ini_set('max_input_time', '259200');
1070 @ini_set('session.gc_maxlifetime', '1200');
1071 @ini_set('memory_limit', '-1');
1072 if (@ini_get('zlib.output_compression')) {
1073 @ini_set('zlib.output_compression', 'Off');
1074 }
1075 }
1076 }
1077 }
1078
1079 if (strlen(session_id()) > 0) session_write_close();
1080
1081 $fp = @fopen($file, 'rb');
1082
1083 // header('X-Sendfile: ' . $file);
1084 // header('X-Sendfile-Type: X-Accel-Redirect');
1085 // header('X-Accel-Redirect: ' . $file);
1086 // header('X-Accel-Buffering: yes');
1087 header('Expires: 0');
1088 header('Pragma: public');
1089 header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
1090 header('Content-Disposition: attachment; filename="' . $backupname . '"');
1091 header('Content-Type: application/octet-stream');
1092 header('Content-Transfer-Encoding: binary');
1093 header('Content-Length: ' . filesize($file));
1094 header('Content-Description: File Transfer');
1095 http_response_code(200);
1096
1097 if (ob_get_level()) ob_end_clean();
1098
1099 fpassthru($fp);
1100 fclose($fp);
1101 exit;
1102 }
1103 } else {
1104 if (ob_get_contents()) ob_end_clean();
1105 header('HTTP/1.0 423 Locked');
1106 if (ob_get_level()) ob_end_clean();
1107 echo __("Backup download is restricted (allowed for admins only).", 'backup-backup');
1108 exit;
1109 }
1110 } elseif ($type == 'BMI_BACKUP_LOGS') {
1111
1112 // Only Admin can download backup logs
1113 if (!(current_user_can('administrator') || current_user_can('do_backups'))) return;
1114
1115 if (ob_get_contents()) ob_end_clean();
1116 $backupname = $get_bid;
1117 $file = $this->fixSlashes(BMI_BACKUPS . DIRECTORY_SEPARATOR . $backupname);
1118
1119 // Prevent parent directory downloading
1120 if (file_exists($file) && $this->fixSlashes(dirname($file)) == $this->fixSlashes(BMI_BACKUPS)) {
1121 require_once BMI_INCLUDES . '/zipper/zipping.php';
1122
1123 $zipper = new Zipper();
1124 $logs = $zipper->getZipFileContentPlain($file, 'bmi_logs_this_backup.log');
1125 header('Content-Type: text/plain');
1126
1127 if ($logs) {
1128 header('Content-Disposition: attachment; filename="' . substr($backupname, 0, -4) . '.log"');
1129 http_response_code(200);
1130 if (ob_get_level()) ob_end_clean();
1131
1132 $logs = explode('\n', $logs);
1133 $current_directory = Dashboard\bmi_get_config('STORAGE::LOCAL::PATH');
1134 $backups_path = $this->fixSlashes($current_directory . DIRECTORY_SEPARATOR . 'backups');
1135 $scanned_directory_all = array_diff(scandir($backups_path), ['..', '.']);
1136 $scanned_directory = array_values(preg_grep('/((.*).zip)/i', $scanned_directory_all));
1137
1138 for ($i = 0; $i < sizeof($logs); ++$i) {
1139
1140 $line = $logs[$i];
1141 echo $this->escapeSensitive($line, $current_directory, $scanned_directory) . "\n";
1142
1143 }
1144
1145 exit;
1146 } else {
1147 if (ob_get_level()) ob_end_clean();
1148 header('HTTP/1.0 404 Not found');
1149 echo __("There was an error during getting logs, this file is not right log file.", 'backup-backup');
1150 exit;
1151 }
1152 }
1153
1154 } elseif ($type == 'PROGRESS_LOGS') {
1155 $allowed_progress = [
1156 'latest_full.log',
1157 'latest.log',
1158 'latest_progress.log',
1159 'latest_migration_full.log',
1160 'latest_migration.log',
1161 'latest_migration_progress.log',
1162 'latest_staging_full.log',
1163 'latest_staging.log',
1164 'latest_staging_progress.log',
1165 'complete_logs.log'
1166 ];
1167 if (isset($get_pid) && in_array($get_pid, $allowed_progress)) {
1168
1169 $restricted_progress = ['complete_logs.log'];
1170 if (in_array($get_pid, $restricted_progress)) {
1171
1172 // Only Admin can download backup logs
1173 if (!(current_user_can('administrator') || current_user_can('do_backups'))) return;
1174
1175 }
1176
1177 header('Content-Type: text/plain');
1178 header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
1179 http_response_code(200);
1180 if (ob_get_contents()) ob_end_clean();
1181 if ($get_pid == 'complete_logs.log') {
1182 $file = BMI_CONFIG_DIR . DIRECTORY_SEPARATOR . 'complete_logs.log';
1183 if (ob_get_level()) ob_end_clean();
1184 $this->readFileSensitive($file);
1185 exit;
1186 } else if ($get_pid == 'latest_full.log') {
1187 $progress = dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . 'latest_progress.log';
1188 $logs = dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . 'latest.log';
1189 if ((file_exists($progress) && file_exists($logs) && ((time() - filemtime($progress)) < (60 * 5))) || current_user_can('administrator')) {
1190 if (ob_get_level()) ob_end_clean();
1191 readfile($progress);
1192 echo "\n";
1193 $this->readFileSensitive($logs);
1194 exit;
1195 } else {
1196 if (file_exists($progress) && !(time() - filemtime($progress)) < (60 * 5)) {
1197 if (ob_get_level()) ob_end_clean();
1198 echo __("Due to security reasons access to this file is disabled at this moment.", 'backup-backup') . "\n";
1199 echo __("Human readable: file expired.", 'backup-backup');
1200 exit;
1201 } else {
1202 if (ob_get_level()) ob_end_clean();
1203 echo '';
1204 exit;
1205 }
1206 }
1207 } else if ($get_pid == 'latest_migration_full.log') {
1208 $progress = dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . 'latest_migration_progress.log';
1209 $logs = dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . 'latest_migration.log';
1210 if ((file_exists($progress) && file_exists($logs) && ((time() - filemtime($progress)) < (60 * 5))) || current_user_can('administrator')) {
1211 if (ob_get_level()) ob_end_clean();
1212 readfile($progress);
1213 echo "\n";
1214 $this->readFileSensitive($logs);
1215 exit;
1216 } else {
1217 if (file_exists($progress) && !(time() - filemtime($progress)) < (60 * 5)) {
1218 if (ob_get_level()) ob_end_clean();
1219 echo __("Due to security reasons access to this file is disabled at this moment.", 'backup-backup') . "\n";
1220 echo __("Human readable: file expired.", 'backup-backup');
1221 exit;
1222 } else {
1223 if (ob_get_level()) ob_end_clean();
1224 echo '';
1225 exit;
1226 }
1227 }
1228 } else if ($get_pid == 'latest_staging_full.log') {
1229 $progress = BMI_STAGING . DIRECTORY_SEPARATOR . 'latest_staging_progress.log';
1230 $logs = BMI_STAGING . DIRECTORY_SEPARATOR . 'latest_staging.log';
1231 if ((file_exists($progress) && file_exists($logs) && ((time() - filemtime($progress)) < (60 * 5))) || current_user_can('administrator')) {
1232 if (ob_get_level()) ob_end_clean();
1233 readfile($progress);
1234 echo "\n";
1235 $this->readFileSensitive($logs);
1236 exit;
1237 } else {
1238 if (file_exists($progress) && !(time() - filemtime($progress)) < (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 } else {
1250 $file = dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . $get_pid;
1251 if ($get_pid == 'latest_staging.log') $file = BMI_STAGING . DIRECTORY_SEPARATOR . $get_pid;
1252 if ($get_pid == 'latest_staging_progress.log') $file = BMI_STAGING . DIRECTORY_SEPARATOR . $get_pid;
1253 if (file_exists($file) && (((time() - filemtime($file)) < (60 * 5)) || current_user_can('administrator'))) {
1254 if (ob_get_level()) ob_end_clean();
1255
1256 $this->readFileSensitive($file);
1257
1258 echo "\n";
1259 if ($get_pid == 'latest.log') $file = dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . 'latest_progress.log';
1260 if ($get_pid == 'latest_migration.log') $file = dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . 'latest_migration_progress.log';
1261 if ($get_pid == 'latest_staging.log') $file = BMI_STAGING . DIRECTORY_SEPARATOR . 'latest_staging_progress.log';
1262 echo __("[DOWNLOAD GENERATED] File downloaded on (server time): ", 'backup-backup') . date('Y-m-d H:i:s') . "\n";
1263 echo __("[DOWNLOAD GENERATED] Last update (seconds): ", 'backup-backup') . (time() - filemtime($file)) . __(" seconds ago ", 'backup-backup') . "\n";
1264 echo __("[DOWNLOAD GENERATED] Last update (date): ", 'backup-backup') . date('Y-m-d H:i:s', filemtime($file)) . " \n";
1265 exit;
1266 } else {
1267 if (file_exists($file) && !(time() - filemtime($file)) < (60 * 5)) {
1268 if (ob_get_level()) ob_end_clean();
1269 echo __("Due to security reasons access to this file is disabled at this moment.", 'backup-backup') . "\n";
1270 echo __("Human readable: file expired.", 'backup-backup');
1271 exit;
1272 } else {
1273 if (ob_get_level()) ob_end_clean();
1274 echo '';
1275 exit;
1276 }
1277 }
1278 }
1279 exit;
1280 }
1281 }
1282 }
1283 }
1284 }
1285
1286 public function deactivation() {
1287 Logger::log(__("Plugin has been deactivated", 'backup-backup'));
1288 $this->revertLitespeed();
1289 }
1290
1291 public static function res($array) {
1292 echo json_encode(Backup_Migration_Plugin::sanitize($array));
1293
1294 if (defined('BMI_USING_CLI_FUNCTIONALITY') && BMI_USING_CLI_FUNCTIONALITY === true) {
1295 Logger::log('CLI response:');
1296 Logger::log(json_encode(Backup_Migration_Plugin::sanitize($array)));
1297 }
1298
1299 exit;
1300 }
1301
1302 public static function getAvailableMemoryInBytes() {
1303
1304 $totalMemory = @ini_get('memory_limit');
1305 if ($totalMemory == -1) {
1306
1307 $totalMemory = 32 * 1024 * 1024;
1308
1309 } else {
1310
1311 if (strpos($totalMemory, 'M') !== false || strpos($totalMemory, 'm') !== false) {
1312 $totalMemory = intval($totalMemory) * 1024 * 1024;
1313 } else if (strpos($totalMemory, 'G') !== false || strpos($totalMemory, 'g') !== false) {
1314 $totalMemory = intval($totalMemory) * 1024 * 1024 * 1024;
1315 } else if (strpos($totalMemory, 'K') !== false || strpos($totalMemory, 'k') !== false) {
1316 $totalMemory = intval($totalMemory) * 1024;
1317 } else {
1318 $totalMemory = intval($totalMemory);
1319 }
1320
1321 }
1322
1323 $availableMemory = $totalMemory - memory_get_usage(true);
1324
1325 return $availableMemory;
1326
1327 }
1328
1329 public static function sanitize($data = []) {
1330 $array = [];
1331
1332 if (is_array($data) || is_object($data)) {
1333 foreach ($data as $key => $value) {
1334 $key = ((is_numeric($key))?intval($key):sanitize_text_field($key));
1335
1336 if (is_array($value) || is_object($value)) {
1337 $array[$key] = Backup_Migration_Plugin::sanitize($value);
1338 } else {
1339 $array[$key] = sanitize_text_field($value);
1340 }
1341 }
1342 } elseif (is_string($data)) {
1343 return sanitize_text_field($data);
1344 } elseif (is_bool($data)) {
1345 return $data;
1346 } elseif (is_null($data)) {
1347 return 'false';
1348 } else {
1349 Logger::log(__("Unknow AJAX Sanitize Type: ", 'backup-backup') . gettype($data));
1350 wp_die();
1351 }
1352
1353 return $array;
1354 }
1355
1356 public static function fixLitespeed() {
1357 $litepath = BMI_INCLUDES . DIRECTORY_SEPARATOR . 'htaccess' . DIRECTORY_SEPARATOR . '.litespeed';
1358 $htpath = ABSPATH . DIRECTORY_SEPARATOR . '.htaccess';
1359 if (!is_writable($htpath)) return ['status' => 'success'];
1360 if (file_exists($htpath)) {
1361 Backup_Migration_Plugin::revertLitespeed();
1362 $litespeed = @file_get_contents($litepath);
1363 $htaccess = @file_get_contents($htpath);
1364 $htaccess = explode("\n", $htaccess);
1365 $litespeed = explode("\n", $litespeed);
1366
1367 $hasAlready = false;
1368 for ($i = 0; $i < sizeof($htaccess); ++$i) {
1369 if (strpos($htaccess[$i], 'Backup Migration') !== false) {
1370 $hasAlready = true;
1371
1372 break;
1373 }
1374 }
1375
1376 if ($hasAlready) {
1377 return ['status' => 'success'];
1378 }
1379 $htaccess[] = '';
1380 for ($i = 0; $i < sizeof($litespeed); ++$i) {
1381 $htaccess[] = $litespeed[$i];
1382 }
1383
1384 file_put_contents($htpath, implode("\n", $htaccess));
1385 } else {
1386 copy($litepath, $htpath);
1387 }
1388
1389 return ['status' => 'success'];
1390 }
1391
1392 public static function revertLitespeed() {
1393 $htpath = ABSPATH . DIRECTORY_SEPARATOR . '.htaccess';
1394 $addline = true;
1395
1396 if (!is_writable($htpath)) return ['status' => 'success'];
1397 $htaccess = @file_get_contents($htpath);
1398 $htaccess = explode("\n", $htaccess);
1399 $htFilter = [];
1400
1401 for ($i = 0; $i < sizeof($htaccess); ++$i) {
1402 if (strpos($htaccess[$i], 'Backup Migration START')) {
1403 $addline = false;
1404
1405 continue;
1406 } elseif (strpos($htaccess[$i], 'Backup Migration END')) {
1407 $addline = true;
1408
1409 continue;
1410 } else {
1411 if ($addline == true) {
1412 $htFilter[] = $htaccess[$i];
1413 }
1414 }
1415 }
1416
1417 file_put_contents($htpath, trim(implode("\n", $htFilter)));
1418
1419 return ['status' => 'success'];
1420 }
1421
1422 public static function humanSize($bytes) {
1423 if (is_int($bytes)) {
1424 $label = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
1425 for ($i = 0; $bytes >= 1024 && $i < (count($label) - 1); $bytes /= 1024, $i++);
1426
1427 return (round($bytes, 2) . " " . $label[$i]);
1428 } else return $bytes;
1429 }
1430
1431 public static function fixSlashes($str, $slash = false) {
1432 // Old version
1433 // $str = str_replace('\\\\', DIRECTORY_SEPARATOR, $str);
1434 // $str = str_replace('\\', DIRECTORY_SEPARATOR, $str);
1435 // $str = str_replace('\/', DIRECTORY_SEPARATOR, $str);
1436 // $str = str_replace('/', DIRECTORY_SEPARATOR, $str);
1437
1438 // if ($str[strlen($str) - 1] == DIRECTORY_SEPARATOR) {
1439 // $str = substr($str, 0, -1);
1440 // }
1441
1442 // Since 1.3.2
1443 $protocol = '';
1444 if ($slash == false) $slash = DIRECTORY_SEPARATOR;
1445 if (substr($str, 0, 7) == 'http://') $protocol = 'http://';
1446 else if (substr($str, 0, 8) == 'https://') $protocol = 'https://';
1447
1448 $str = substr($str, strlen($protocol));
1449 $str = preg_replace('/[\\\\\/]+/', $slash, $str);
1450 $str = untrailingslashit($str);
1451
1452 return $protocol . $str;
1453 }
1454
1455 public static function canShareLogsOrShouldAsk() {
1456
1457 return 'not-allowed';
1458
1459 // REMOVED CODE:
1460 // $isAllowed = get_option('BMI_LOGS_SHARING_IS_ALLOWED', 'unknown');
1461 // $isAllowedConfig = Dashboard\bmi_get_config('LOGS::SHARING');
1462 //
1463 // if ($isAllowed == 'unknown' || empty($isAllowedConfig)) return 'ask';
1464 // else if ($isAllowed === 'yes' && $isAllowedConfig === 'yes') {
1465 // return 'allowed';
1466 // } else if ($isAllowed === 'no' && $isAllowedConfig === 'no') {
1467 // return 'not-allowed';
1468 // } else return 'ask';
1469
1470 }
1471
1472 public static function merge_arrays(&$array1, &$array2) {
1473 for ($i = 0; $i < sizeof($array2); ++$i) {
1474 $array1[] = $array2[$i];
1475 }
1476 }
1477
1478 private function get_asset($base = '', $asset = '') {
1479 return BMI_ASSETS . '/' . $base . '/' . $asset;
1480 }
1481 }
1482