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