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