PluginProbe ʕ •ᴥ•ʔ
Backup Migration / 1.3.8
Backup Migration v1.3.8
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
1514 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 $outsideDir = false;
1072 if (!(file_exists($file) && $this->fixSlashes(dirname($file)) == $this->fixSlashes(BMI_BACKUPS))) {
1073 $outsideDir = true;
1074 }
1075
1076 if (strpos(strtolower(mime_content_type($file)), 'zip') === false || $outsideDir) {
1077 header('HTTP/1.0 423 Locked');
1078 _e("Incorrect usage of the query request.", 'backup-backup');
1079 exit;
1080 }
1081
1082 if (Dashboard\bmi_get_config('OTHER:DOWNLOAD:DIRECT') == 'true') {
1083 if (file_exists(BMI_BACKUPS . DIRECTORY_SEPARATOR . '.htaccess')) @unlink(BMI_BACKUPS . DIRECTORY_SEPARATOR . '.htaccess');
1084 if (file_exists(dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . '.htaccess')) @unlink(dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . '.htaccess');
1085 $wpcontent = trailingslashit(WP_CONTENT_DIR);
1086 $wpcs = strlen($wpcontent);
1087 $url = $this->fixSlashes(content_url(substr($file, $wpcs)), '/');
1088 $path = wp_redirect($url);
1089 exit;
1090 }
1091
1092 // Prevent parent directory downloading
1093 if (ob_get_contents()) ob_end_clean();
1094
1095 if ($this->isFunctionEnabled('ignore_user_abort')) @ignore_user_abort(true);
1096 if ($this->isFunctionEnabled('set_time_limit')) @set_time_limit(16000);
1097 if ($this->isFunctionEnabled('headers_sent') && $this->isFunctionEnabled('session_status')) {
1098 if (!headers_sent() && session_status() === PHP_SESSION_DISABLED) {
1099 if ($this->isFunctionEnabled('ini_set')) {
1100 @ini_set('max_execution_time', '259200');
1101 @ini_set('max_input_time', '259200');
1102 @ini_set('session.gc_maxlifetime', '1200');
1103 @ini_set('memory_limit', '-1');
1104 if (@ini_get('zlib.output_compression')) {
1105 @ini_set('zlib.output_compression', 'Off');
1106 }
1107 }
1108 }
1109 }
1110
1111 if (strlen(session_id()) > 0) session_write_close();
1112
1113 $fp = @fopen($file, 'rb');
1114
1115 // header('X-Sendfile: ' . $file);
1116 // header('X-Sendfile-Type: X-Accel-Redirect');
1117 // header('X-Accel-Redirect: ' . $file);
1118 // header('X-Accel-Buffering: yes');
1119 header('Expires: 0');
1120 header('Pragma: public');
1121 header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
1122 header('Content-Disposition: attachment; filename="' . $backupname . '"');
1123 header('Content-Type: application/octet-stream');
1124 header('Content-Transfer-Encoding: binary');
1125 header('Content-Length: ' . filesize($file));
1126 header('Content-Description: File Transfer');
1127 http_response_code(200);
1128
1129 if (ob_get_level()) ob_end_clean();
1130
1131 fpassthru($fp);
1132 fclose($fp);
1133 exit;
1134
1135 } else {
1136 if (ob_get_contents()) ob_end_clean();
1137 header('HTTP/1.0 423 Locked');
1138 if (ob_get_level()) ob_end_clean();
1139 echo __("Backup download is restricted (allowed for admins only).", 'backup-backup');
1140 exit;
1141 }
1142 } elseif ($type == 'BMI_BACKUP_LOGS') {
1143
1144 // Only Admin can download backup logs
1145 if (!(current_user_can('administrator') || current_user_can('do_backups'))) return;
1146
1147 if (ob_get_contents()) ob_end_clean();
1148 $backupname = $get_bid;
1149 $file = $this->fixSlashes(BMI_BACKUPS . DIRECTORY_SEPARATOR . $backupname);
1150
1151 // Prevent parent directory downloading
1152 if (file_exists($file) && $this->fixSlashes(dirname($file)) == $this->fixSlashes(BMI_BACKUPS)) {
1153 require_once BMI_INCLUDES . '/zipper/zipping.php';
1154
1155 $zipper = new Zipper();
1156 $logs = $zipper->getZipFileContentPlain($file, 'bmi_logs_this_backup.log');
1157 header('Content-Type: text/plain');
1158
1159 if ($logs) {
1160 header('Content-Disposition: attachment; filename="' . substr($backupname, 0, -4) . '.log"');
1161 http_response_code(200);
1162 if (ob_get_level()) ob_end_clean();
1163
1164 $logs = explode('\n', $logs);
1165 $current_directory = Dashboard\bmi_get_config('STORAGE::LOCAL::PATH');
1166 $backups_path = $this->fixSlashes($current_directory . DIRECTORY_SEPARATOR . 'backups');
1167 $scanned_directory_all = array_diff(scandir($backups_path), ['..', '.']);
1168 $scanned_directory = array_values(preg_grep('/((.*).zip)/i', $scanned_directory_all));
1169
1170 for ($i = 0; $i < sizeof($logs); ++$i) {
1171
1172 $line = $logs[$i];
1173 echo $this->escapeSensitive($line, $current_directory, $scanned_directory) . "\n";
1174
1175 }
1176
1177 exit;
1178 } else {
1179 if (ob_get_level()) ob_end_clean();
1180 header('HTTP/1.0 404 Not found');
1181 echo __("There was an error during getting logs, this file is not right log file.", 'backup-backup');
1182 exit;
1183 }
1184 }
1185
1186 } elseif ($type == 'PROGRESS_LOGS') {
1187 $allowed_progress = [
1188 'latest_full.log',
1189 'latest.log',
1190 'latest_progress.log',
1191 'latest_migration_full.log',
1192 'latest_migration.log',
1193 'latest_migration_progress.log',
1194 'latest_staging_full.log',
1195 'latest_staging.log',
1196 'latest_staging_progress.log',
1197 'complete_logs.log'
1198 ];
1199 if (isset($get_pid) && in_array($get_pid, $allowed_progress)) {
1200
1201 $restricted_progress = ['complete_logs.log'];
1202 if (in_array($get_pid, $restricted_progress)) {
1203
1204 // Only Admin can download backup logs
1205 if (!(current_user_can('administrator') || current_user_can('do_backups'))) return;
1206
1207 }
1208
1209 header('Content-Type: text/plain');
1210 header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
1211 http_response_code(200);
1212 if (ob_get_contents()) ob_end_clean();
1213 if ($get_pid == 'complete_logs.log') {
1214 $file = BMI_CONFIG_DIR . DIRECTORY_SEPARATOR . 'complete_logs.log';
1215 if (ob_get_level()) ob_end_clean();
1216 $this->readFileSensitive($file);
1217 exit;
1218 } else if ($get_pid == 'latest_full.log') {
1219 $progress = dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . 'latest_progress.log';
1220 $logs = dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . 'latest.log';
1221 if ((file_exists($progress) && file_exists($logs) && ((time() - filemtime($progress)) < (60 * 1))) || current_user_can('administrator')) {
1222 if (ob_get_level()) ob_end_clean();
1223 readfile($progress);
1224 echo "\n";
1225 $this->readFileSensitive($logs);
1226 exit;
1227 } else {
1228 if (file_exists($progress) && !(time() - filemtime($progress)) < (60 * 1)) {
1229 if (ob_get_level()) ob_end_clean();
1230 echo __("Due to security reasons access to this file is disabled at this moment.", 'backup-backup') . "\n";
1231 echo __("Human readable: file expired.", 'backup-backup');
1232 exit;
1233 } else {
1234 if (ob_get_level()) ob_end_clean();
1235 echo '';
1236 exit;
1237 }
1238 }
1239 } else if ($get_pid == 'latest_migration_full.log') {
1240 $progress = dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . 'latest_migration_progress.log';
1241 $logs = dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . 'latest_migration.log';
1242 if ((file_exists($progress) && file_exists($logs) && ((time() - filemtime($progress)) < (60 * 1))) || current_user_can('administrator')) {
1243 if (ob_get_level()) ob_end_clean();
1244 readfile($progress);
1245 echo "\n";
1246 $this->readFileSensitive($logs);
1247 exit;
1248 } else {
1249 if (file_exists($progress) && !(time() - filemtime($progress)) < (60 * 1)) {
1250 if (ob_get_level()) ob_end_clean();
1251 echo __("Due to security reasons access to this file is disabled at this moment.", 'backup-backup') . "\n";
1252 echo __("Human readable: file expired.", 'backup-backup');
1253 exit;
1254 } else {
1255 if (ob_get_level()) ob_end_clean();
1256 echo '';
1257 exit;
1258 }
1259 }
1260 } else if ($get_pid == 'latest_staging_full.log') {
1261 $progress = BMI_STAGING . DIRECTORY_SEPARATOR . 'latest_staging_progress.log';
1262 $logs = BMI_STAGING . DIRECTORY_SEPARATOR . 'latest_staging.log';
1263 if ((file_exists($progress) && file_exists($logs) && ((time() - filemtime($progress)) < (60 * 1))) || current_user_can('administrator')) {
1264 if (ob_get_level()) ob_end_clean();
1265 readfile($progress);
1266 echo "\n";
1267 $this->readFileSensitive($logs);
1268 exit;
1269 } else {
1270 if (file_exists($progress) && !(time() - filemtime($progress)) < (60 * 1)) {
1271 if (ob_get_level()) ob_end_clean();
1272 echo __("Due to security reasons access to this file is disabled at this moment.", 'backup-backup') . "\n";
1273 echo __("Human readable: file expired.", 'backup-backup');
1274 exit;
1275 } else {
1276 if (ob_get_level()) ob_end_clean();
1277 echo '';
1278 exit;
1279 }
1280 }
1281 } else {
1282 $file = dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . $get_pid;
1283 if ($get_pid == 'latest_staging.log') $file = BMI_STAGING . DIRECTORY_SEPARATOR . $get_pid;
1284 if ($get_pid == 'latest_staging_progress.log') $file = BMI_STAGING . DIRECTORY_SEPARATOR . $get_pid;
1285 if (file_exists($file) && (((time() - filemtime($file)) < (60 * 1)) || current_user_can('administrator'))) {
1286 if (ob_get_level()) ob_end_clean();
1287
1288 $this->readFileSensitive($file);
1289
1290 echo "\n";
1291 if ($get_pid == 'latest.log') $file = dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . 'latest_progress.log';
1292 if ($get_pid == 'latest_migration.log') $file = dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . 'latest_migration_progress.log';
1293 if ($get_pid == 'latest_staging.log') $file = BMI_STAGING . DIRECTORY_SEPARATOR . 'latest_staging_progress.log';
1294 echo __("[DOWNLOAD GENERATED] File downloaded on (server time): ", 'backup-backup') . date('Y-m-d H:i:s') . "\n";
1295 echo __("[DOWNLOAD GENERATED] Last update (seconds): ", 'backup-backup') . (time() - filemtime($file)) . __(" seconds ago ", 'backup-backup') . "\n";
1296 echo __("[DOWNLOAD GENERATED] Last update (date): ", 'backup-backup') . date('Y-m-d H:i:s', filemtime($file)) . " \n";
1297 exit;
1298 } else {
1299 if (file_exists($file) && !(time() - filemtime($file)) < (60 * 1)) {
1300 if (ob_get_level()) ob_end_clean();
1301 echo __("Due to security reasons access to this file is disabled at this moment.", 'backup-backup') . "\n";
1302 echo __("Human readable: file expired.", 'backup-backup');
1303 exit;
1304 } else {
1305 if (ob_get_level()) ob_end_clean();
1306 echo '';
1307 exit;
1308 }
1309 }
1310 }
1311 exit;
1312 }
1313 }
1314 }
1315 }
1316 }
1317
1318 public function deactivation() {
1319 Logger::log(__("Plugin has been deactivated", 'backup-backup'));
1320 $this->revertLitespeed();
1321 }
1322
1323 public static function res($array) {
1324 echo json_encode(Backup_Migration_Plugin::sanitize($array));
1325
1326 if (defined('BMI_USING_CLI_FUNCTIONALITY') && BMI_USING_CLI_FUNCTIONALITY === true) {
1327 Logger::log('CLI response:');
1328 Logger::log(json_encode(Backup_Migration_Plugin::sanitize($array)));
1329 }
1330
1331 exit;
1332 }
1333
1334 public static function getAvailableMemoryInBytes() {
1335
1336 $totalMemory = @ini_get('memory_limit');
1337 if ($totalMemory == -1) {
1338
1339 $totalMemory = 32 * 1024 * 1024;
1340
1341 } else {
1342
1343 if (strpos($totalMemory, 'M') !== false || strpos($totalMemory, 'm') !== false) {
1344 $totalMemory = intval($totalMemory) * 1024 * 1024;
1345 } else if (strpos($totalMemory, 'G') !== false || strpos($totalMemory, 'g') !== false) {
1346 $totalMemory = intval($totalMemory) * 1024 * 1024 * 1024;
1347 } else if (strpos($totalMemory, 'K') !== false || strpos($totalMemory, 'k') !== false) {
1348 $totalMemory = intval($totalMemory) * 1024;
1349 } else {
1350 $totalMemory = intval($totalMemory);
1351 }
1352
1353 }
1354
1355 $availableMemory = $totalMemory - memory_get_usage(true);
1356
1357 return $availableMemory;
1358
1359 }
1360
1361 public static function sanitize($data = []) {
1362 $array = [];
1363
1364 if (is_array($data) || is_object($data)) {
1365 foreach ($data as $key => $value) {
1366 $key = ((is_numeric($key))?intval($key):sanitize_text_field($key));
1367
1368 if (is_array($value) || is_object($value)) {
1369 $array[$key] = Backup_Migration_Plugin::sanitize($value);
1370 } else {
1371 $array[$key] = sanitize_text_field($value);
1372 }
1373 }
1374 } elseif (is_string($data)) {
1375 return sanitize_text_field($data);
1376 } elseif (is_bool($data)) {
1377 return $data;
1378 } elseif (is_null($data)) {
1379 return 'false';
1380 } else {
1381 Logger::log(__("Unknow AJAX Sanitize Type: ", 'backup-backup') . gettype($data));
1382 wp_die();
1383 }
1384
1385 return $array;
1386 }
1387
1388 public static function fixLitespeed() {
1389 $litepath = BMI_INCLUDES . DIRECTORY_SEPARATOR . 'htaccess' . DIRECTORY_SEPARATOR . '.litespeed';
1390 $htpath = ABSPATH . DIRECTORY_SEPARATOR . '.htaccess';
1391 if (!is_writable($htpath)) return ['status' => 'success'];
1392 if (file_exists($htpath)) {
1393 Backup_Migration_Plugin::revertLitespeed();
1394 $litespeed = @file_get_contents($litepath);
1395 $htaccess = @file_get_contents($htpath);
1396 $htaccess = explode("\n", $htaccess);
1397 $litespeed = explode("\n", $litespeed);
1398
1399 $hasAlready = false;
1400 for ($i = 0; $i < sizeof($htaccess); ++$i) {
1401 if (strpos($htaccess[$i], 'Backup Migration') !== false) {
1402 $hasAlready = true;
1403
1404 break;
1405 }
1406 }
1407
1408 if ($hasAlready) {
1409 return ['status' => 'success'];
1410 }
1411 $htaccess[] = '';
1412 for ($i = 0; $i < sizeof($litespeed); ++$i) {
1413 $htaccess[] = $litespeed[$i];
1414 }
1415
1416 file_put_contents($htpath, implode("\n", $htaccess));
1417 } else {
1418 copy($litepath, $htpath);
1419 }
1420
1421 return ['status' => 'success'];
1422 }
1423
1424 public static function revertLitespeed() {
1425 $htpath = ABSPATH . DIRECTORY_SEPARATOR . '.htaccess';
1426 $addline = true;
1427
1428 if (!is_writable($htpath)) return ['status' => 'success'];
1429 $htaccess = @file_get_contents($htpath);
1430 $htaccess = explode("\n", $htaccess);
1431 $htFilter = [];
1432
1433 for ($i = 0; $i < sizeof($htaccess); ++$i) {
1434 if (strpos($htaccess[$i], 'Backup Migration START')) {
1435 $addline = false;
1436
1437 continue;
1438 } elseif (strpos($htaccess[$i], 'Backup Migration END')) {
1439 $addline = true;
1440
1441 continue;
1442 } else {
1443 if ($addline == true) {
1444 $htFilter[] = $htaccess[$i];
1445 }
1446 }
1447 }
1448
1449 file_put_contents($htpath, trim(implode("\n", $htFilter)));
1450
1451 return ['status' => 'success'];
1452 }
1453
1454 public static function humanSize($bytes) {
1455 if (is_int($bytes)) {
1456 $label = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
1457 for ($i = 0; $bytes >= 1024 && $i < (count($label) - 1); $bytes /= 1024, $i++);
1458
1459 return (round($bytes, 2) . " " . $label[$i]);
1460 } else return $bytes;
1461 }
1462
1463 public static function fixSlashes($str, $slash = false) {
1464 // Old version
1465 // $str = str_replace('\\\\', DIRECTORY_SEPARATOR, $str);
1466 // $str = str_replace('\\', DIRECTORY_SEPARATOR, $str);
1467 // $str = str_replace('\/', DIRECTORY_SEPARATOR, $str);
1468 // $str = str_replace('/', DIRECTORY_SEPARATOR, $str);
1469
1470 // if ($str[strlen($str) - 1] == DIRECTORY_SEPARATOR) {
1471 // $str = substr($str, 0, -1);
1472 // }
1473
1474 // Since 1.3.2
1475 $protocol = '';
1476 if ($slash == false) $slash = DIRECTORY_SEPARATOR;
1477 if (substr($str, 0, 7) == 'http://') $protocol = 'http://';
1478 else if (substr($str, 0, 8) == 'https://') $protocol = 'https://';
1479
1480 $str = substr($str, strlen($protocol));
1481 $str = preg_replace('/[\\\\\/]+/', $slash, $str);
1482 $str = untrailingslashit($str);
1483
1484 return $protocol . $str;
1485 }
1486
1487 public static function canShareLogsOrShouldAsk() {
1488
1489 return 'not-allowed';
1490
1491 // REMOVED CODE:
1492 // $isAllowed = get_option('BMI_LOGS_SHARING_IS_ALLOWED', 'unknown');
1493 // $isAllowedConfig = Dashboard\bmi_get_config('LOGS::SHARING');
1494 //
1495 // if ($isAllowed == 'unknown' || empty($isAllowedConfig)) return 'ask';
1496 // else if ($isAllowed === 'yes' && $isAllowedConfig === 'yes') {
1497 // return 'allowed';
1498 // } else if ($isAllowed === 'no' && $isAllowedConfig === 'no') {
1499 // return 'not-allowed';
1500 // } else return 'ask';
1501
1502 }
1503
1504 public static function merge_arrays(&$array1, &$array2) {
1505 for ($i = 0; $i < sizeof($array2); ++$i) {
1506 $array1[] = $array2[$i];
1507 }
1508 }
1509
1510 private function get_asset($base = '', $asset = '') {
1511 return BMI_ASSETS . '/' . $base . '/' . $asset;
1512 }
1513 }
1514