PluginProbe ʕ •ᴥ•ʔ
Backup Migration / 1.3.3
Backup Migration v1.3.3
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
1483 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->log('#002', 'END-CODE');
445 $progress->end();
446 }
447 }
448
449 public function handleErrorDuringRestore($msg, $file, $line, &$progress) {
450 Logger::log('There was fatal error during restore.');
451 if ($progress) {
452 $progress->log(__('Something bad happened on PHP side.', 'backup-backup'), 'error');
453 $progress->log(__('Error message: ', 'backup-backup') . $msg, 'error');
454 $progress->log(__('Error file/line: ', 'backup-backup') . $file . '|' . $line, 'error');
455 }
456 if (file_exists(BMI_BACKUPS . DIRECTORY_SEPARATOR . '.migration_lock')) @unlink(BMI_BACKUPS . DIRECTORY_SEPARATOR . '.migration_lock');
457 if ($progress) {
458 $progress->log(__("Aborting & unlocking restore process...", 'backup-backup'), 'step');
459 $progress->end();
460 }
461
462 $lock = BMI_BACKUPS . '/.migration_lock';
463 if (file_exists($lock)) @unlink($lock);
464 }
465
466 public function submenu() {
467
468 // Menu icon
469 $icon_url = $this->get_asset('images', 'logo-min.png');
470
471 // Main menu slug
472 $parentSlug = 'backup-migration';
473
474 // Content
475 $content = [$this, 'settings_page'];
476
477 // Main menu hook
478 add_menu_page('Backup Migration', '<span id="bmi-menu">Backup Migration</span>', 'read', $parentSlug, $content, $icon_url, $position = 98);
479
480 // Remove default submenu by menu
481 remove_submenu_page($parentSlug, $parentSlug);
482
483 }
484
485 public function settings_action($links) {
486 $text = __('Manage', 'backup-backup');
487 $links['bmi-settings-link'] = '<a href="' . admin_url('/admin.php?page=backup-migration') . '">' . $text . '</a>';
488
489 return $links;
490 }
491
492 public function include_offline() {
493
494 // Prevent if there is no offline action required (save resources)
495 if (get_option('bmip_last', false) !== '1') return;
496
497 if (defined('BMI_PRO_INC')) {
498
499 // Handle offline tasks
500 if (!class_exists('BMI_Pro_Offline')) {
501 if (file_exists(BMI_PRO_INC . 'offline.php')) {
502 require_once BMI_PRO_INC . 'offline.php';
503 $offline = new BMI_Pro_Offline();
504 }
505 }
506
507 }
508
509 }
510
511 public function settings_page() {
512
513 // Set email if does not exist
514 if (!Dashboard\bmi_get_config('OTHER:EMAIL')) {
515 Dashboard\bmi_set_config('OTHER:EMAIL', get_bloginfo('admin_email'));
516 }
517
518 // Require The HTML
519 require_once BMI_INCLUDES . '/dashboard/settings.php';
520 }
521
522 public function admin_init_hook() {
523 $this->hotfix_patches();
524 if (get_option('_bmi_redirect', false)) {
525 $this->fixLitespeed();
526 delete_option('_bmi_redirect');
527 wp_safe_redirect(admin_url('admin.php?page=backup-migration'));
528 }
529 }
530
531 public function admin_notices() {
532 if (get_current_screen()->id != 'toplevel_page_backup-migration' && get_option('bmi_display_email_issues', false)) {
533 ?>
534 <div class="notice notice-warning">
535 <p>
536 <?php _e('There was an error during automated backup, please', 'backup-backup'); ?>
537 <?php echo '<a href="' . admin_url('/admin.php?page=backup-migration') . '">' . __('check that.', 'backup-backup') . '</a>'; ?>
538 </p>
539 </div>
540 <?php
541 }
542 }
543
544 public function handle_crons() {
545 if (Dashboard\bmi_get_config('CRON:ENABLED') !== true) return;
546
547 $time = get_option('bmi_backup_check', 0);
548 if ((time() - $time) > 60) {
549 update_option('bmi_backup_check', time());
550
551 do_action('bmi_handle_cron_check');
552 }
553 }
554
555 public function email_error($msg) {
556 Logger::log('Displaying some issues about email sending...');
557 update_option('bmi_display_email_issues', $msg);
558 }
559
560 public function backup_inproper_time($should_time) {
561 $plan_file = BMI_INCLUDES . '/htaccess/.plan';
562 if (!file_exists($plan_file) || intval($should_time) < 1234567890) return;
563
564 Logger::log('Sending notification about backup being late');
565 $email = Dashboard\bmi_get_config('OTHER:EMAIL') != false ? Dashboard\bmi_get_config('OTHER:EMAIL') : get_bloginfo('admin_email');
566 $subject = Dashboard\bmi_get_config('OTHER:EMAIL:TITLE');
567 $message = __("Automatic backup was not on time because there was no traffic on the site.", 'backup-backup') . "\n";
568 $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);
569 $message .= ' ' . __("(server time)", 'backup-backup');
570
571 Logger::debug($message);
572 if (!$this->send_notification_mail($email, $subject, $message)) {
573 $issue = __("Couldn't send mail to you, please check server configuration.", 'backup-backup') . '<br>';
574 $issue .= '<b>' . __("Message you missed because of this: ", 'backup-backup') . '</b>' . $message;
575 $this->email_error($issue);
576 }
577 }
578
579 public function handle_cron_check() {
580
581 if (Dashboard\bmi_get_config('CRON:ENABLED') !== true) return;
582
583 $now = time();
584 if (file_exists(BMI_INCLUDES . '/htaccess/.last')) {
585 $last = @file_get_contents(BMI_INCLUDES . '/htaccess/.last');
586 $last_status = explode('.', $last)[0];
587 $last_time = intval(explode('.', $last)[1]);
588 } else {
589 $last_time = 0;
590 $last_status = 0;
591 }
592
593 if (file_exists(BMI_INCLUDES . '/htaccess/.plan')) {
594 $plan = intval(@file_get_contents(BMI_INCLUDES . '/htaccess/.plan'));
595 if ($last_time < $plan && ((time() - $plan) > 3600)) {
596 if ($last_status !== '0') {
597 $this->backup_inproper_time($plan);
598 if (!wp_next_scheduled('bmi_do_backup_right_now')) {
599 wp_schedule_single_event(time(), 'bmi_do_backup_right_now');
600 }
601 }
602 }
603 }
604
605 }
606
607 public function get_next_cron($curr = false) {
608 if ($curr === false) {
609 $curr = time();
610 }
611
612 $time = Crons::calculate_date([
613 'type' => Dashboard\bmi_get_config('CRON:TYPE'),
614 'week' => Dashboard\bmi_get_config('CRON:WEEK'),
615 'day' => Dashboard\bmi_get_config('CRON:DAY'),
616 'hour' => Dashboard\bmi_get_config('CRON:HOUR'),
617 'minute' => Dashboard\bmi_get_config('CRON:MINUTE')
618 ], $curr);
619
620 return $time;
621 }
622
623 public function handle_cron_error($e) {
624 Logger::error(__("Automatic backup failed at time: ", 'backup-backup') . date('Y-m-d, H:i:s'));
625 if (is_object($e) || is_array($e)) {
626 Logger::error('Error: ' . $e->getMessage());
627 } else {
628 Logger::error('Error: ' . $e);
629 }
630
631 $notis = Dashboard\bmi_get_config('OTHER:EMAIL:NOTIS');
632 if (in_array($notis, [true, 'true'])) {
633 $email = Dashboard\bmi_get_config('OTHER:EMAIL') != false ? Dashboard\bmi_get_config('OTHER:EMAIL') : get_bloginfo('admin_email');
634 $subject = Dashboard\bmi_get_config('OTHER:EMAIL:TITLE');
635 $message = __("There was an error during automatic backup, please check the logs.", 'backup-backup');
636 if (is_string($e)) {
637 $message .= "\nError: " . $e;
638 }
639
640 $this->send_notification_mail($email, $subject, $message);
641 }
642
643 if (file_exists(BMI_BACKUPS . '/.cron')) {
644 @unlink(BMI_BACKUPS . '/.cron');
645 }
646 }
647
648 public function send_notification_mail($email, $subject, $message) {
649
650 $currentDate = date('Y-m-d');
651 if (get_option('bmi_last_email_notification', false) == $currentDate) {
652 Logger::log(__("Disallowing to send mail as today we already sent one.", 'backup-backup'));
653 return;
654 }
655
656 update_option('bmi_last_email_notification', $currentDate);
657
658 $email_fail = __("Could not send the email notification about that fail", 'backup-backup');
659
660 try {
661
662 if (wp_mail($email, $subject, $message)) {
663 Logger::log(__("Sent email notification to: ", 'backup-backup') . $email);
664
665 return true;
666 } else {
667 Logger::error($email_fail);
668 $this->email_error(__("Couldn't send notification via email, please check the email and your server settings.", 'backup-backup'));
669
670 return false;
671 }
672
673 } catch (\Exception $e) {
674 Logger::error($email_fail);
675 $this->email_error(__("Couldn't send notification via email due to error, please check plugin logs for more details.", 'backup-backup'));
676
677 return false;
678 } catch (\Throwable $e) {
679 Logger::error($email_fail);
680 $this->email_error(__("Couldn't send notification via email due to error, please check plugin logs for more details.", 'backup-backup'));
681
682 return false;
683 }
684 }
685
686 public function handle_after_cron() {
687 require_once BMI_INCLUDES . DIRECTORY_SEPARATOR . 'scanner' . DIRECTORY_SEPARATOR . 'backups.php';
688 $backups = new Backups();
689 $list = $backups->getAvailableBackups();
690 $list = $list['local'];
691
692 $cron_list = [];
693 $cron_dates = [];
694 foreach ($list as $key => $value) {
695 if ($list[$key][6] == true) {
696 if ($list[$key][5] == 'unlocked') {
697 $cron_list[$list[$key][1]] = $list[$key][0];
698 $cron_dates[] = $list[$key][1];
699 }
700 }
701 }
702
703 usort($cron_dates, function ($a, $b) {
704 return (strtotime($a) < strtotime($b)) ? -1 : 1;
705 });
706
707 $cron_dates = array_slice($cron_dates, 0, -(intval(Dashboard\bmi_get_config('CRON:KEEP'))));
708 foreach ($cron_dates as $key => $value) {
709 $name = $cron_list[$cron_dates[$key]];
710 Logger::log(__("Removing backup due to keep rules: ", 'backup-backup') . $name);
711 @unlink(BMI_BACKUPS . DIRECTORY_SEPARATOR . $name);
712 }
713 }
714
715 public function set_last_cron($status, $time) {
716 $file = BMI_INCLUDES . '/htaccess/.last';
717 file_put_contents($file, $status . '.' . $time);
718 }
719
720 public function readFileSensitive($file) {
721
722 if (!file_exists($file)) {
723 echo '';
724 return;
725 }
726
727 $file = new \SplFileObject($file);
728 $file->seek($file->getSize());
729 $total_lines = $file->key() + 1;
730
731 $current_directory = Dashboard\bmi_get_config('STORAGE::LOCAL::PATH');
732 $backups_path = $this->fixSlashes($current_directory . DIRECTORY_SEPARATOR . 'backups');
733 $scanned_directory_all = array_diff(scandir($backups_path), ['..', '.']);
734 $scanned_directory = array_values(preg_grep('/((.*).zip)/i', $scanned_directory_all));
735
736 for ($i = 0; $i < $total_lines; ++$i) {
737
738 $file->seek($i);
739 $line = $this->escapeSensitive($file->current(), $current_directory, $scanned_directory);
740
741 echo $line;
742 unset($line);
743
744 }
745
746 }
747
748 public function escapeSensitive($line, $current_directory, $scanned_directory) {
749
750 $dir_name = basename($current_directory);
751
752 $line = preg_replace('/\:\ ((.*)\.zip)/', ': *****.zip', $line);
753 $line = preg_replace('/(\"filename\":(.*)\.zip)\"/', '"filename": "*****.zip"', $line);
754 $line = preg_replace('/\"http(.*)\"/', '"***site_url***"', $line);
755 $line = preg_replace('/\:\ http(.*)\n/', ": ***site_url***\n", $line);
756 $line = preg_replace('/\"\d{10}\"/', '"***secret_login***"', $line);
757 $line = str_replace(ABSPATH, '***ABSPATH***/', $line);
758 $line = str_replace($dir_name, '***backup_path***', $line);
759
760 for ($i = 0; $i < sizeof($scanned_directory); ++$i) {
761
762 $backup_name = $scanned_directory[$i];
763 $line = str_replace($backup_name, '***some_backup***', $line);
764
765 }
766
767 return $line;
768
769 }
770
771 public function handle_cron_backup() {
772
773 $plan_file = BMI_INCLUDES . '/htaccess/.plan';
774 $last_file = BMI_INCLUDES . '/htaccess/.last';
775
776 // Abort if disabled
777 if (Dashboard\bmi_get_config('CRON:ENABLED') !== true) {
778
779
780 if (file_exists($plan_file)) @unlink($plan_file);
781 if (file_exists($last_file)) @unlink($last_file);
782
783 return;
784
785 }
786
787 if (!file_exists($plan_file)) return;
788
789 // Planned time
790 $plan = intval(@file_get_contents(BMI_INCLUDES . '/htaccess/.plan'));
791
792 // Check difference
793 if ((time() - $plan) > 3600) {
794 Logger::log('Backup failed to run on proper time, but running now.');
795 Logger::log('Planned time: ' . date('Y-m-d H:i:s', $plan));
796 $this->backup_inproper_time($plan);
797 }
798
799 // Now
800 $now = time();
801 $this->set_last_cron('0', $now);
802
803 // Extend execution time
804 if ($this->isFunctionEnabled('headers_sent') && $this->isFunctionEnabled('session_status')) {
805 if (!headers_sent() && session_status() === PHP_SESSION_DISABLED) {
806 if ($this->isFunctionEnabled('ignore_user_abort')) @ignore_user_abort(true);
807 if ($this->isFunctionEnabled('set_time_limit')) @set_time_limit(16000);
808 if ($this->isFunctionEnabled('ini_set')) {
809 @ini_set('max_execution_time', '259200');
810 @ini_set('max_input_time', '259200');
811 @ini_set('session.gc_maxlifetime', '1200');
812 }
813 }
814 }
815
816 if (strlen(session_id()) > 0) session_write_close();
817
818 Logger::log(__("Automatic backup called at time: ", 'backup-backup') . date('Y-m-d, H:i:s'));
819
820 try {
821 require_once BMI_INCLUDES . '/ajax.php';
822 $isBackup = (file_exists(BMI_BACKUPS . '/.running') && (time() - filemtime(BMI_BACKUPS . '/.running')) <= 65) ? true : false;
823 $isCron = (file_exists(BMI_BACKUPS . '/.cron') && (time() - filemtime(BMI_BACKUPS . '/.cron')) <= 65) ? true : false;
824 if ($isCron) {
825 return;
826 }
827
828 if ($isBackup) {
829 $this->handle_cron_error(__("Could not make the backup: Backup already running, please wait till it complete.", 'backup-backup'));
830 $this->set_last_cron('2', $now);
831 } else {
832 touch(BMI_BACKUPS . '/.cron');
833
834 if (!defined('BMI_DOING_SCHEDULED_BACKUP')) {
835 define('BMI_DOING_SCHEDULED_BACKUP', true);
836 }
837
838 $handler = new BMI_Ajax();
839 $handler->resetLatestLogs();
840 $backup = $handler->prepareAndMakeBackup(true);
841
842 if ($backup['status'] == 'success') {
843 Logger::log(__("Automatic backup successed: ", 'backup-backup') . $backup['filename']);
844 $this->handle_after_cron();
845 $this->set_last_cron('1', $now);
846 } elseif ($backup['status'] == 'msg') {
847 $this->handle_cron_error($backup['why']);
848 $this->set_last_cron('3', $now);
849 } else {
850 $this->handle_cron_error(__("Could not make the backup due to internal server error.", 'backup-backup'));
851 $this->set_last_cron('4', $now);
852 }
853 }
854 } catch (\Exception $e) {
855 $this->handle_cron_error($e);
856 $this->set_last_cron('5', $now);
857 } catch (\Throwable $e) {
858 $this->handle_cron_error($e);
859 $this->set_last_cron('5', $now);
860 }
861
862 if (file_exists(BMI_BACKUPS . '/.cron')) {
863 @unlink(BMI_BACKUPS . '/.cron');
864 }
865 require_once BMI_INCLUDES . '/cron/handler.php';
866 $time = $this->get_next_cron();
867
868 wp_clear_scheduled_hook('bmi_do_backup_right_now');
869 wp_schedule_single_event($time, 'bmi_do_backup_right_now');
870
871 $file = BMI_INCLUDES . '/htaccess/.plan';
872 file_put_contents($file, $time);
873 }
874
875 public function enqueue_scripts() {
876
877 // Global
878 if (in_array(get_current_screen()->id, ['toplevel_page_backup-migration', 'plugins'])) { ?>
879 <script type="text/javascript">
880 let stars = '<?php echo plugin_dir_url(BMI_ROOT_FILE); ?>' + 'admin/images/stars.gif';
881 let css_star = "background:url('" + stars + "')";
882 document.addEventListener("DOMContentLoaded", function(event) {
883 jQuery('[data-slug="backup-migration-pro"]').find('strong').html('<span>Backup Migration <b style="color: orange; ' + css_star + '">Pro</b></span>');
884 jQuery('[data-slug="backup-backup-pro"]').find('strong').html('<span>Backup Migration <b style="color: orange; ' + css_star + '">Pro</b></span>');
885 });
886 </script>
887 <?php }
888
889 // Only for BM Settings
890 if (get_current_screen()->id != 'toplevel_page_backup-migration') {
891 return;
892 }
893 wp_enqueue_script('backup-migration-script', $this->get_asset('js', 'backup-migration.min.js'), ['jquery'], BMI_VERSION, true);
894 wp_localize_script('backup-migration-script', 'bmiVariables', [
895 'nonce' => wp_create_nonce('backup-migration-ajax'),
896 'stgLoading' => __('Loading, please wait...', 'backup-backup'),
897 'stgStagingDefaultName' => __('staging', 'backup-backup'),
898 'urlCopies' => __('URL copied successfully', 'backup-backup'),
899 'maxUploadSize' => $this->getMaxUploadSize()
900 ], true);
901
902 }
903
904 public function phpSizeToB($phpSize) {
905
906 $sSuffix = strtoupper(substr($phpSize, -1));
907
908 if (!in_array($sSuffix, array('P','T','G','M','K'))) {
909 return (int) $phpSize;
910 }
911
912 $iValue = substr($phpSize, 0, -1);
913 switch ($sSuffix) {
914 case 'P': $iValue *= 1024;
915 case 'T': $iValue *= 1024;
916 case 'G': $iValue *= 1024;
917 case 'M': $iValue *= 1024;
918 case 'K': $iValue *= 1024;
919 break;
920 }
921
922 return (int) $iValue;
923
924 }
925
926 public function getMaxUploadSize() {
927 $ten = (10 * 1024 * 1024);
928 $max = min($this->phpSizeToB(ini_get('post_max_size')), $this->phpSizeToB(ini_get('upload_max_filesize')), $ten);
929 return ($max / 1024 / 1024);
930 }
931
932 public function enqueue_styles() {
933
934 // Global styles
935 wp_enqueue_style('backup-migration-style-icon', $this->get_asset('css', 'bmi-plugin-icon.min.css'), [], BMI_VERSION);
936
937 // Only for BM Settings
938 if (get_current_screen()->id != 'toplevel_page_backup-migration') return;
939
940 // Enqueue the style
941 wp_enqueue_style('backup-migration-style', $this->get_asset('css', 'bmi-plugin.min.css'), [], BMI_VERSION);
942
943 }
944
945 public function handle_after_actions() {
946
947 // Handle After Migration actions
948 $afterMigrationLock = BMI_INCLUDES . DIRECTORY_SEPARATOR . 'htaccess' . DIRECTORY_SEPARATOR . '.migrationFinished';
949 if (file_exists($afterMigrationLock)) {
950 if (strpos(site_url(), 'tastewp') !== false) {
951
952 if (function_exists('wp_load_alloptions')) {
953 wp_load_alloptions(true);
954 }
955
956 update_option('__tastewp_redirection_performed', true);
957 update_option('auto_smart_tastewp_redirect_performed', 1);
958 update_option('tastewp_auto_activated', true);
959 update_option('__tastewp_sub_requested', true);
960
961 }
962
963 unlink($afterMigrationLock);
964 }
965
966 }
967
968 public function handle_downloading() {
969 global $wpdb;
970 @error_reporting(0);
971 $autologin_file = BMI_BACKUPS . '/.autologin';
972 $ip = '127.0.0.1';
973 if (isset($_SERVER['HTTP_CLIENT_IP'])) {
974 $ip = $_SERVER['HTTP_CLIENT_IP'];
975 } else {
976 if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
977 $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
978 }
979 if ($ip === false) {
980 if (isset($_SERVER['REMOTE_ADDR'])) $ip = $_SERVER['REMOTE_ADDR'];
981 }
982 }
983 $allowed = ['BMI_BACKUP', 'BMI_BACKUP_LOGS', 'PROGRESS_LOGS', 'AFTER_RESTORE'];
984 $get_bmi = !empty($_GET['backup-migration']) ? sanitize_text_field($_GET['backup-migration']) : false;
985 $get_bid = !empty($_GET['backup-id']) ? sanitize_text_field($_GET['backup-id']) : false;
986 $get_pid = !empty($_GET['progress-id']) ? sanitize_text_field($_GET['progress-id']) : false;
987
988 if (isset($get_bmi) && in_array($get_bmi, $allowed)) {
989 if (isset($get_bid) && strlen($get_bid) > 0) {
990 $type = $get_bmi;
991
992 if ($type == 'AFTER_RESTORE' && isset($get_pid)) {
993 if (file_exists($autologin_file)) {
994 $autoLoginMD = file_get_contents($autologin_file);
995 $autoLoginMD = explode('_', $autoLoginMD);
996 $aID = intval($autoLoginMD[0]);
997 $aID2 = intval($autoLoginMD[0]) - 1;
998 $aID3 = intval($autoLoginMD[0]) + 1;
999 $aID4 = intval($autoLoginMD[0]) + 2;
1000 $aID5 = intval($autoLoginMD[0]) + 3;
1001 $aID6 = intval($autoLoginMD[0]) + 4;
1002 $aIP = $autoLoginMD[1];
1003 $aIZ = $autoLoginMD[2];
1004
1005 // Allow 1 second delay
1006 $timeIsProper = false;
1007 if ($aID === intval($get_bid)) $timeIsProper = true;
1008 if ($aID2 === intval($get_bid)) $timeIsProper = true;
1009 if ($aID3 === intval($get_bid)) $timeIsProper = true;
1010 if ($aID4 === intval($get_bid)) $timeIsProper = true;
1011 if ($aID5 === intval($get_bid)) $timeIsProper = true;
1012 if ($aID6 === intval($get_bid)) $timeIsProper = true;
1013
1014 if ($timeIsProper && $aIP === $ip && trim($aIZ) === $get_pid) {
1015 $query = new \WP_User_Query(['role' => 'Administrator', 'count_total' => false, 'fields' => ['ID', 'user_login']]);
1016 $sqlres = $wpdb->get_results($query->request);
1017
1018 if (sizeof($sqlres) > 0 && isset($sqlres[0]->ID) && isset($sqlres[0]->user_login)) {
1019
1020 $user = $sqlres[0];
1021 $adminID = $sqlres[0]->ID;
1022 $adminLogin = $sqlres[0]->user_login;
1023
1024 remove_all_actions('wp_login', -1000);
1025 wp_load_alloptions(true);
1026 clean_user_cache(get_current_user_id());
1027 clean_user_cache($adminID);
1028 wp_clear_auth_cookie();
1029 wp_set_current_user($adminID, $adminLogin);
1030 wp_set_auth_cookie($adminID, 1, is_ssl());
1031 do_action('wp_login', $adminLogin, $user);
1032 update_user_caches($user);
1033
1034 }
1035
1036 $url = admin_url('admin.php?page=backup-migration');
1037 header('Location: ' . $url);
1038
1039 @unlink($autologin_file);
1040 exit;
1041 }
1042 }
1043
1044 } else if ($type == 'BMI_BACKUP') {
1045 if (Dashboard\bmi_get_config('STORAGE::DIRECT::URL') === 'true' || current_user_can('administrator')) {
1046
1047 $backupname = $get_bid;
1048 $file = $this->fixSlashes(BMI_BACKUPS . DIRECTORY_SEPARATOR . $backupname);
1049
1050 if (Dashboard\bmi_get_config('OTHER:DOWNLOAD:DIRECT') == 'true') {
1051 if (file_exists(BMI_BACKUPS . DIRECTORY_SEPARATOR . '.htaccess')) @unlink(BMI_BACKUPS . DIRECTORY_SEPARATOR . '.htaccess');
1052 if (file_exists(dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . '.htaccess')) @unlink(dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . '.htaccess');
1053 $wpcontent = trailingslashit(WP_CONTENT_DIR);
1054 $wpcs = strlen($wpcontent);
1055 $url = $this->fixSlashes(content_url(substr($file, $wpcs)), '/');
1056 $path = wp_redirect($url);
1057 exit;
1058 }
1059
1060 // Prevent parent directory downloading
1061 if (file_exists($file) && $this->fixSlashes(dirname($file)) == $this->fixSlashes(BMI_BACKUPS)) {
1062 if (ob_get_contents()) ob_end_clean();
1063
1064 if ($this->isFunctionEnabled('ignore_user_abort')) @ignore_user_abort(true);
1065 if ($this->isFunctionEnabled('set_time_limit')) @set_time_limit(16000);
1066 if ($this->isFunctionEnabled('headers_sent') && $this->isFunctionEnabled('session_status')) {
1067 if (!headers_sent() && session_status() === PHP_SESSION_DISABLED) {
1068 if ($this->isFunctionEnabled('ini_set')) {
1069 @ini_set('max_execution_time', '259200');
1070 @ini_set('max_input_time', '259200');
1071 @ini_set('session.gc_maxlifetime', '1200');
1072 @ini_set('memory_limit', '-1');
1073 if (@ini_get('zlib.output_compression')) {
1074 @ini_set('zlib.output_compression', 'Off');
1075 }
1076 }
1077 }
1078 }
1079
1080 if (strlen(session_id()) > 0) session_write_close();
1081
1082 $fp = @fopen($file, 'rb');
1083
1084 // header('X-Sendfile: ' . $file);
1085 // header('X-Sendfile-Type: X-Accel-Redirect');
1086 // header('X-Accel-Redirect: ' . $file);
1087 // header('X-Accel-Buffering: yes');
1088 header('Expires: 0');
1089 header('Pragma: public');
1090 header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
1091 header('Content-Disposition: attachment; filename="' . $backupname . '"');
1092 header('Content-Type: application/octet-stream');
1093 header('Content-Transfer-Encoding: binary');
1094 header('Content-Length: ' . filesize($file));
1095 header('Content-Description: File Transfer');
1096 http_response_code(200);
1097
1098 if (ob_get_level()) ob_end_clean();
1099
1100 fpassthru($fp);
1101 fclose($fp);
1102 exit;
1103 }
1104 } else {
1105 if (ob_get_contents()) ob_end_clean();
1106 header('HTTP/1.0 423 Locked');
1107 if (ob_get_level()) ob_end_clean();
1108 echo __("Backup download is restricted (allowed for admins only).", 'backup-backup');
1109 exit;
1110 }
1111 } elseif ($type == 'BMI_BACKUP_LOGS') {
1112
1113 // Only Admin can download backup logs
1114 if (!(current_user_can('administrator') || current_user_can('do_backups'))) return;
1115
1116 if (ob_get_contents()) ob_end_clean();
1117 $backupname = $get_bid;
1118 $file = $this->fixSlashes(BMI_BACKUPS . DIRECTORY_SEPARATOR . $backupname);
1119
1120 // Prevent parent directory downloading
1121 if (file_exists($file) && $this->fixSlashes(dirname($file)) == $this->fixSlashes(BMI_BACKUPS)) {
1122 require_once BMI_INCLUDES . '/zipper/zipping.php';
1123
1124 $zipper = new Zipper();
1125 $logs = $zipper->getZipFileContentPlain($file, 'bmi_logs_this_backup.log');
1126 header('Content-Type: text/plain');
1127
1128 if ($logs) {
1129 header('Content-Disposition: attachment; filename="' . substr($backupname, 0, -4) . '.log"');
1130 http_response_code(200);
1131 if (ob_get_level()) ob_end_clean();
1132
1133 $logs = explode('\n', $logs);
1134 $current_directory = Dashboard\bmi_get_config('STORAGE::LOCAL::PATH');
1135 $backups_path = $this->fixSlashes($current_directory . DIRECTORY_SEPARATOR . 'backups');
1136 $scanned_directory_all = array_diff(scandir($backups_path), ['..', '.']);
1137 $scanned_directory = array_values(preg_grep('/((.*).zip)/i', $scanned_directory_all));
1138
1139 for ($i = 0; $i < sizeof($logs); ++$i) {
1140
1141 $line = $logs[$i];
1142 echo $this->escapeSensitive($line, $current_directory, $scanned_directory) . "\n";
1143
1144 }
1145
1146 exit;
1147 } else {
1148 if (ob_get_level()) ob_end_clean();
1149 header('HTTP/1.0 404 Not found');
1150 echo __("There was an error during getting logs, this file is not right log file.", 'backup-backup');
1151 exit;
1152 }
1153 }
1154
1155 } elseif ($type == 'PROGRESS_LOGS') {
1156 $allowed_progress = [
1157 'latest_full.log',
1158 'latest.log',
1159 'latest_progress.log',
1160 'latest_migration_full.log',
1161 'latest_migration.log',
1162 'latest_migration_progress.log',
1163 'latest_staging_full.log',
1164 'latest_staging.log',
1165 'latest_staging_progress.log',
1166 'complete_logs.log'
1167 ];
1168 if (isset($get_pid) && in_array($get_pid, $allowed_progress)) {
1169
1170 $restricted_progress = ['complete_logs.log'];
1171 if (in_array($get_pid, $restricted_progress)) {
1172
1173 // Only Admin can download backup logs
1174 if (!(current_user_can('administrator') || current_user_can('do_backups'))) return;
1175
1176 }
1177
1178 header('Content-Type: text/plain');
1179 header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
1180 http_response_code(200);
1181 if (ob_get_contents()) ob_end_clean();
1182 if ($get_pid == 'complete_logs.log') {
1183 $file = BMI_CONFIG_DIR . DIRECTORY_SEPARATOR . 'complete_logs.log';
1184 if (ob_get_level()) ob_end_clean();
1185 $this->readFileSensitive($file);
1186 exit;
1187 } else if ($get_pid == 'latest_full.log') {
1188 $progress = dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . 'latest_progress.log';
1189 $logs = dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . 'latest.log';
1190 if ((file_exists($progress) && file_exists($logs) && ((time() - filemtime($progress)) < (60 * 5))) || current_user_can('administrator')) {
1191 if (ob_get_level()) ob_end_clean();
1192 readfile($progress);
1193 echo "\n";
1194 $this->readFileSensitive($logs);
1195 exit;
1196 } else {
1197 if (file_exists($progress) && !(time() - filemtime($progress)) < (60 * 5)) {
1198 if (ob_get_level()) ob_end_clean();
1199 echo __("Due to security reasons access to this file is disabled at this moment.", 'backup-backup') . "\n";
1200 echo __("Human readable: file expired.", 'backup-backup');
1201 exit;
1202 } else {
1203 if (ob_get_level()) ob_end_clean();
1204 echo '';
1205 exit;
1206 }
1207 }
1208 } else if ($get_pid == 'latest_migration_full.log') {
1209 $progress = dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . 'latest_migration_progress.log';
1210 $logs = dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . 'latest_migration.log';
1211 if ((file_exists($progress) && file_exists($logs) && ((time() - filemtime($progress)) < (60 * 5))) || current_user_can('administrator')) {
1212 if (ob_get_level()) ob_end_clean();
1213 readfile($progress);
1214 echo "\n";
1215 $this->readFileSensitive($logs);
1216 exit;
1217 } else {
1218 if (file_exists($progress) && !(time() - filemtime($progress)) < (60 * 5)) {
1219 if (ob_get_level()) ob_end_clean();
1220 echo __("Due to security reasons access to this file is disabled at this moment.", 'backup-backup') . "\n";
1221 echo __("Human readable: file expired.", 'backup-backup');
1222 exit;
1223 } else {
1224 if (ob_get_level()) ob_end_clean();
1225 echo '';
1226 exit;
1227 }
1228 }
1229 } else if ($get_pid == 'latest_staging_full.log') {
1230 $progress = BMI_STAGING . DIRECTORY_SEPARATOR . 'latest_staging_progress.log';
1231 $logs = BMI_STAGING . DIRECTORY_SEPARATOR . 'latest_staging.log';
1232 if ((file_exists($progress) && file_exists($logs) && ((time() - filemtime($progress)) < (60 * 5))) || current_user_can('administrator')) {
1233 if (ob_get_level()) ob_end_clean();
1234 readfile($progress);
1235 echo "\n";
1236 $this->readFileSensitive($logs);
1237 exit;
1238 } else {
1239 if (file_exists($progress) && !(time() - filemtime($progress)) < (60 * 5)) {
1240 if (ob_get_level()) ob_end_clean();
1241 echo __("Due to security reasons access to this file is disabled at this moment.", 'backup-backup') . "\n";
1242 echo __("Human readable: file expired.", 'backup-backup');
1243 exit;
1244 } else {
1245 if (ob_get_level()) ob_end_clean();
1246 echo '';
1247 exit;
1248 }
1249 }
1250 } else {
1251 $file = dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . $get_pid;
1252 if ($get_pid == 'latest_staging.log') $file = BMI_STAGING . DIRECTORY_SEPARATOR . $get_pid;
1253 if ($get_pid == 'latest_staging_progress.log') $file = BMI_STAGING . DIRECTORY_SEPARATOR . $get_pid;
1254 if (file_exists($file) && (((time() - filemtime($file)) < (60 * 5)) || current_user_can('administrator'))) {
1255 if (ob_get_level()) ob_end_clean();
1256
1257 $this->readFileSensitive($file);
1258
1259 echo "\n";
1260 if ($get_pid == 'latest.log') $file = dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . 'latest_progress.log';
1261 if ($get_pid == 'latest_migration.log') $file = dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . 'latest_migration_progress.log';
1262 if ($get_pid == 'latest_staging.log') $file = BMI_STAGING . DIRECTORY_SEPARATOR . 'latest_staging_progress.log';
1263 echo __("[DOWNLOAD GENERATED] File downloaded on (server time): ", 'backup-backup') . date('Y-m-d H:i:s') . "\n";
1264 echo __("[DOWNLOAD GENERATED] Last update (seconds): ", 'backup-backup') . (time() - filemtime($file)) . __(" seconds ago ", 'backup-backup') . "\n";
1265 echo __("[DOWNLOAD GENERATED] Last update (date): ", 'backup-backup') . date('Y-m-d H:i:s', filemtime($file)) . " \n";
1266 exit;
1267 } else {
1268 if (file_exists($file) && !(time() - filemtime($file)) < (60 * 5)) {
1269 if (ob_get_level()) ob_end_clean();
1270 echo __("Due to security reasons access to this file is disabled at this moment.", 'backup-backup') . "\n";
1271 echo __("Human readable: file expired.", 'backup-backup');
1272 exit;
1273 } else {
1274 if (ob_get_level()) ob_end_clean();
1275 echo '';
1276 exit;
1277 }
1278 }
1279 }
1280 exit;
1281 }
1282 }
1283 }
1284 }
1285 }
1286
1287 public function deactivation() {
1288 Logger::log(__("Plugin has been deactivated", 'backup-backup'));
1289 $this->revertLitespeed();
1290 }
1291
1292 public static function res($array) {
1293 echo json_encode(Backup_Migration_Plugin::sanitize($array));
1294
1295 if (defined('BMI_USING_CLI_FUNCTIONALITY') && BMI_USING_CLI_FUNCTIONALITY === true) {
1296 Logger::log('CLI response:');
1297 Logger::log(json_encode(Backup_Migration_Plugin::sanitize($array)));
1298 }
1299
1300 exit;
1301 }
1302
1303 public static function getAvailableMemoryInBytes() {
1304
1305 $totalMemory = @ini_get('memory_limit');
1306 if ($totalMemory == -1) {
1307
1308 $totalMemory = 32 * 1024 * 1024;
1309
1310 } else {
1311
1312 if (strpos($totalMemory, 'M') !== false || strpos($totalMemory, 'm') !== false) {
1313 $totalMemory = intval($totalMemory) * 1024 * 1024;
1314 } else if (strpos($totalMemory, 'G') !== false || strpos($totalMemory, 'g') !== false) {
1315 $totalMemory = intval($totalMemory) * 1024 * 1024 * 1024;
1316 } else if (strpos($totalMemory, 'K') !== false || strpos($totalMemory, 'k') !== false) {
1317 $totalMemory = intval($totalMemory) * 1024;
1318 } else {
1319 $totalMemory = intval($totalMemory);
1320 }
1321
1322 }
1323
1324 $availableMemory = $totalMemory - memory_get_usage(true);
1325
1326 return $availableMemory;
1327
1328 }
1329
1330 public static function sanitize($data = []) {
1331 $array = [];
1332
1333 if (is_array($data) || is_object($data)) {
1334 foreach ($data as $key => $value) {
1335 $key = ((is_numeric($key))?intval($key):sanitize_text_field($key));
1336
1337 if (is_array($value) || is_object($value)) {
1338 $array[$key] = Backup_Migration_Plugin::sanitize($value);
1339 } else {
1340 $array[$key] = sanitize_text_field($value);
1341 }
1342 }
1343 } elseif (is_string($data)) {
1344 return sanitize_text_field($data);
1345 } elseif (is_bool($data)) {
1346 return $data;
1347 } elseif (is_null($data)) {
1348 return 'false';
1349 } else {
1350 Logger::log(__("Unknow AJAX Sanitize Type: ", 'backup-backup') . gettype($data));
1351 wp_die();
1352 }
1353
1354 return $array;
1355 }
1356
1357 public static function fixLitespeed() {
1358 $litepath = BMI_INCLUDES . DIRECTORY_SEPARATOR . 'htaccess' . DIRECTORY_SEPARATOR . '.litespeed';
1359 $htpath = ABSPATH . DIRECTORY_SEPARATOR . '.htaccess';
1360 if (!is_writable($htpath)) return ['status' => 'success'];
1361 if (file_exists($htpath)) {
1362 Backup_Migration_Plugin::revertLitespeed();
1363 $litespeed = @file_get_contents($litepath);
1364 $htaccess = @file_get_contents($htpath);
1365 $htaccess = explode("\n", $htaccess);
1366 $litespeed = explode("\n", $litespeed);
1367
1368 $hasAlready = false;
1369 for ($i = 0; $i < sizeof($htaccess); ++$i) {
1370 if (strpos($htaccess[$i], 'Backup Migration') !== false) {
1371 $hasAlready = true;
1372
1373 break;
1374 }
1375 }
1376
1377 if ($hasAlready) {
1378 return ['status' => 'success'];
1379 }
1380 $htaccess[] = '';
1381 for ($i = 0; $i < sizeof($litespeed); ++$i) {
1382 $htaccess[] = $litespeed[$i];
1383 }
1384
1385 file_put_contents($htpath, implode("\n", $htaccess));
1386 } else {
1387 copy($litepath, $htpath);
1388 }
1389
1390 return ['status' => 'success'];
1391 }
1392
1393 public static function revertLitespeed() {
1394 $htpath = ABSPATH . DIRECTORY_SEPARATOR . '.htaccess';
1395 $addline = true;
1396
1397 if (!is_writable($htpath)) return ['status' => 'success'];
1398 $htaccess = @file_get_contents($htpath);
1399 $htaccess = explode("\n", $htaccess);
1400 $htFilter = [];
1401
1402 for ($i = 0; $i < sizeof($htaccess); ++$i) {
1403 if (strpos($htaccess[$i], 'Backup Migration START')) {
1404 $addline = false;
1405
1406 continue;
1407 } elseif (strpos($htaccess[$i], 'Backup Migration END')) {
1408 $addline = true;
1409
1410 continue;
1411 } else {
1412 if ($addline == true) {
1413 $htFilter[] = $htaccess[$i];
1414 }
1415 }
1416 }
1417
1418 file_put_contents($htpath, trim(implode("\n", $htFilter)));
1419
1420 return ['status' => 'success'];
1421 }
1422
1423 public static function humanSize($bytes) {
1424 if (is_int($bytes)) {
1425 $label = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
1426 for ($i = 0; $bytes >= 1024 && $i < (count($label) - 1); $bytes /= 1024, $i++);
1427
1428 return (round($bytes, 2) . " " . $label[$i]);
1429 } else return $bytes;
1430 }
1431
1432 public static function fixSlashes($str, $slash = false) {
1433 // Old version
1434 // $str = str_replace('\\\\', DIRECTORY_SEPARATOR, $str);
1435 // $str = str_replace('\\', DIRECTORY_SEPARATOR, $str);
1436 // $str = str_replace('\/', DIRECTORY_SEPARATOR, $str);
1437 // $str = str_replace('/', DIRECTORY_SEPARATOR, $str);
1438
1439 // if ($str[strlen($str) - 1] == DIRECTORY_SEPARATOR) {
1440 // $str = substr($str, 0, -1);
1441 // }
1442
1443 // Since 1.3.2
1444 $protocol = '';
1445 if ($slash == false) $slash = DIRECTORY_SEPARATOR;
1446 if (substr($str, 0, 7) == 'http://') $protocol = 'http://';
1447 else if (substr($str, 0, 8) == 'https://') $protocol = 'https://';
1448
1449 $str = substr($str, strlen($protocol));
1450 $str = preg_replace('/[\\\\\/]+/', $slash, $str);
1451 $str = untrailingslashit($str);
1452
1453 return $protocol . $str;
1454 }
1455
1456 public static function canShareLogsOrShouldAsk() {
1457
1458 return 'not-allowed';
1459
1460 // REMOVED CODE:
1461 // $isAllowed = get_option('BMI_LOGS_SHARING_IS_ALLOWED', 'unknown');
1462 // $isAllowedConfig = Dashboard\bmi_get_config('LOGS::SHARING');
1463 //
1464 // if ($isAllowed == 'unknown' || empty($isAllowedConfig)) return 'ask';
1465 // else if ($isAllowed === 'yes' && $isAllowedConfig === 'yes') {
1466 // return 'allowed';
1467 // } else if ($isAllowed === 'no' && $isAllowedConfig === 'no') {
1468 // return 'not-allowed';
1469 // } else return 'ask';
1470
1471 }
1472
1473 public static function merge_arrays(&$array1, &$array2) {
1474 for ($i = 0; $i < sizeof($array2); ++$i) {
1475 $array1[] = $array2[$i];
1476 }
1477 }
1478
1479 private function get_asset($base = '', $asset = '') {
1480 return BMI_ASSETS . '/' . $base . '/' . $asset;
1481 }
1482 }
1483