PluginProbe ʕ •ᴥ•ʔ
Backup Migration / 1.4.2
Backup Migration v1.4.2
2.1.6 2.1.5.2 trunk 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.6.1 1.4.7 1.4.8 1.4.9 1.4.9.1 2.0.0 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.5.1
backup-backup / includes / initializer.php
backup-backup / includes Last commit date
banner 2 years ago check 2 years ago cli 2 years ago cron 2 years ago dashboard 2 years ago database 2 years ago extracter 2 years ago htaccess 2 years ago progress 2 years ago scanner 2 years ago staging 2 years ago uploader 2 years ago zipper 2 years ago .htaccess 2 years ago activation.php 2 years ago ajax.php 2 years ago analyst.php 2 years ago 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 middleware-backup-proxy.php 2 years ago restore-batching.php 2 years ago
initializer.php
1518 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 if (!file_exists($file)) {
740 echo '';
741 return;
742 }
743
744 $file = new \SplFileObject($file);
745 $file->seek($file->getSize());
746 $total_lines = $file->key() + 1;
747
748 $current_directory = Dashboard\bmi_get_config('STORAGE::LOCAL::PATH');
749 $backups_path = $this->fixSlashes($current_directory . DIRECTORY_SEPARATOR . 'backups');
750 $scanned_directory_all = array_diff(scandir($backups_path), ['..', '.']);
751 $scanned_directory = array_values(preg_grep('/((.*).zip)/i', $scanned_directory_all));
752
753 for ($i = 0; $i < $total_lines; ++$i) {
754
755 $file->seek($i);
756 $line = $this->escapeSensitive($file->current(), $current_directory, $scanned_directory);
757
758 echo $line;
759 unset($line);
760
761 }
762
763 }
764
765 public function escapeSensitive($line, $current_directory, $scanned_directory) {
766
767 global $table_prefix;
768
769 $dir_name = basename($current_directory);
770
771 $line = preg_replace('/\:\ ((.*)\.zip)/', ': *****.zip', $line);
772 $line = preg_replace('/(\"filename\":(.*)\.zip)\"/', '"filename": "*****.zip"', $line);
773 $line = preg_replace('/\"http(.*)\"/', '"***site_url***"', $line);
774 $line = preg_replace('/\:\ http(.*)\n/', ": ***site_url***\n", $line);
775 $line = preg_replace('/\"\d{10}\"/', '"***secret_login***"', $line);
776 $line = str_replace(ABSPATH, '***ABSPATH***/', $line);
777 $line = str_replace($dir_name, '***backup_path***', $line);
778 $line = str_replace($table_prefix, '***prefix***', $line);
779
780 for ($i = 0; $i < sizeof($scanned_directory); ++$i) {
781
782 $backup_name = $scanned_directory[$i];
783 $line = str_replace($backup_name, '***some_backup***', $line);
784
785 }
786
787 return $line;
788
789 }
790
791 public function handle_cron_backup() {
792
793 $plan_file = BMI_TMP . DIRECTORY_SEPARATOR . '.plan';
794 $last_file = BMI_TMP . DIRECTORY_SEPARATOR . '.last';
795
796 // Abort if disabled
797 if (Dashboard\bmi_get_config('CRON:ENABLED') !== true) {
798
799
800 if (file_exists($plan_file)) @unlink($plan_file);
801 if (file_exists($last_file)) @unlink($last_file);
802
803 return;
804
805 }
806
807 if (!file_exists($plan_file)) return;
808
809 // Planned time
810 $plan = intval(@file_get_contents(BMI_TMP . DIRECTORY_SEPARATOR . '.plan'));
811
812 // Check difference
813 if ((time() - $plan) > 3600) {
814 Logger::log('Backup failed to run on proper time, but running now.');
815 Logger::log('Planned time: ' . date('Y-m-d H:i:s', $plan));
816 $this->backup_inproper_time($plan);
817 }
818
819 // Now
820 $now = time();
821 $this->set_last_cron('0', $now);
822
823 // Extend execution time
824 if ($this->isFunctionEnabled('headers_sent') && $this->isFunctionEnabled('session_status')) {
825 if (!headers_sent() && session_status() === PHP_SESSION_DISABLED) {
826 if ($this->isFunctionEnabled('ignore_user_abort')) @ignore_user_abort(true);
827 if ($this->isFunctionEnabled('set_time_limit')) @set_time_limit(16000);
828 if ($this->isFunctionEnabled('ini_set')) {
829 @ini_set('max_execution_time', '259200');
830 @ini_set('max_input_time', '259200');
831 @ini_set('session.gc_maxlifetime', '1200');
832 }
833 }
834 }
835
836 if (strlen(session_id()) > 0) session_write_close();
837
838 Logger::log(__("Automatic backup called at time: ", 'backup-backup') . date('Y-m-d, H:i:s'));
839
840 try {
841 require_once BMI_INCLUDES . '/ajax.php';
842 $isBackup = (file_exists(BMI_BACKUPS . '/.running') && (time() - filemtime(BMI_BACKUPS . '/.running')) <= 65) ? true : false;
843 $isCron = (file_exists(BMI_BACKUPS . '/.cron') && (time() - filemtime(BMI_BACKUPS . '/.cron')) <= 65) ? true : false;
844 if ($isCron) {
845 return;
846 }
847
848 if ($isBackup) {
849 $this->handle_cron_error(__("Could not make the backup: Backup already running, please wait till it complete.", 'backup-backup'));
850 $this->set_last_cron('2', $now);
851 } else {
852 touch(BMI_BACKUPS . '/.cron');
853
854 if (!defined('BMI_DOING_SCHEDULED_BACKUP')) {
855 define('BMI_DOING_SCHEDULED_BACKUP', true);
856 }
857
858 $handler = new BMI_Ajax();
859 $handler->resetLatestLogs();
860 $backup = $handler->prepareAndMakeBackup(true);
861
862 if ($backup['status'] == 'success') {
863 if (isset($backup['filename'])) {
864 Logger::log(__("Automatic backup successed: ", 'backup-backup') . $backup['filename']);
865 } else {
866 Logger::log(__("Automatic backup successed", 'backup-backup'));
867 }
868 $this->set_last_cron('1', $now);
869 } elseif ($backup['status'] == 'msg') {
870 $this->handle_cron_error($backup['why']);
871 $this->set_last_cron('3', $now);
872 } else {
873 $this->handle_cron_error(__("Could not make the backup due to internal server error.", 'backup-backup'));
874 $this->set_last_cron('4', $now);
875 }
876 }
877 } catch (\Exception $e) {
878 $this->handle_cron_error($e);
879 $this->set_last_cron('5', $now);
880 } catch (\Throwable $e) {
881 $this->handle_cron_error($e);
882 $this->set_last_cron('5', $now);
883 }
884
885 $this->handle_after_cron();
886
887 if (file_exists(BMI_BACKUPS . '/.cron')) {
888 @unlink(BMI_BACKUPS . '/.cron');
889 }
890 require_once BMI_INCLUDES . '/cron/handler.php';
891 $time = $this->get_next_cron();
892
893 wp_clear_scheduled_hook('bmi_do_backup_right_now');
894 wp_schedule_single_event($time, 'bmi_do_backup_right_now');
895
896 $file = BMI_TMP . DIRECTORY_SEPARATOR . '.plan';
897 file_put_contents($file, $time);
898 }
899
900 public function enqueue_scripts() {
901
902 // Global
903 if (in_array(get_current_screen()->id, ['toplevel_page_backup-migration', 'plugins'])) { ?>
904 <script type="text/javascript">
905 let stars = '<?php echo plugin_dir_url(BMI_ROOT_FILE); ?>' + 'admin/images/stars.gif';
906 let css_star = "background:url('" + stars + "')";
907 document.addEventListener("DOMContentLoaded", function(event) {
908 jQuery('[data-slug="backup-migration-pro"]').find('strong').html('<span>Backup Migration <b style="color: orange; ' + css_star + '">Pro</b></span>');
909 jQuery('[data-slug="backup-backup-pro"]').find('strong').html('<span>Backup Migration <b style="color: orange; ' + css_star + '">Pro</b></span>');
910 });
911 </script>
912 <?php }
913
914 // Only for BM Settings
915 if (get_current_screen()->id != 'toplevel_page_backup-migration') {
916 return;
917 }
918 wp_enqueue_script('backup-migration-script', $this->get_asset('js', 'backup-migration.min.js'), ['jquery'], BMI_VERSION, true);
919 wp_localize_script('backup-migration-script', 'bmiVariables', [
920 'nonce' => wp_create_nonce('backup-migration-ajax'),
921 'stgLoading' => __('Loading, please wait...', 'backup-backup'),
922 'stgStagingDefaultName' => __('staging', 'backup-backup'),
923 'urlCopies' => __('URL copied successfully', 'backup-backup'),
924 'maxUploadSize' => $this->getMaxUploadSize()
925 ], true);
926
927 }
928
929 public function phpSizeToB($phpSize) {
930
931 $sSuffix = strtoupper(substr($phpSize, -1));
932
933 if (!in_array($sSuffix, array('P','T','G','M','K'))) {
934 return (int) $phpSize;
935 }
936
937 $iValue = substr($phpSize, 0, -1);
938 switch ($sSuffix) {
939 case 'P': $iValue *= 1024;
940 case 'T': $iValue *= 1024;
941 case 'G': $iValue *= 1024;
942 case 'M': $iValue *= 1024;
943 case 'K': $iValue *= 1024;
944 break;
945 }
946
947 return (int) $iValue;
948
949 }
950
951 public function getMaxUploadSize() {
952 $ten = (10 * 1024 * 1024);
953 $max = min($this->phpSizeToB(ini_get('post_max_size')), $this->phpSizeToB(ini_get('upload_max_filesize')), $ten);
954 return ($max / 1024 / 1024);
955 }
956
957 public function enqueue_styles() {
958
959 // Global styles
960 wp_enqueue_style('backup-migration-style-icon', $this->get_asset('css', 'bmi-plugin-icon.min.css'), [], BMI_VERSION);
961
962 // Only for BM Settings
963 if (get_current_screen()->id != 'toplevel_page_backup-migration') return;
964
965 // Enqueue the style
966 wp_enqueue_style('backup-migration-style', $this->get_asset('css', 'bmi-plugin.min.css'), [], BMI_VERSION);
967
968 }
969
970 public function handle_after_actions() {
971
972 // Handle After Migration actions
973 $afterMigrationLock = BMI_TMP . DIRECTORY_SEPARATOR . '.migrationFinished';
974 if (file_exists($afterMigrationLock)) {
975 if (strpos(site_url(), 'tastewp') !== false) {
976
977 if (function_exists('wp_load_alloptions')) {
978 wp_load_alloptions(true);
979 }
980
981 update_option('__tastewp_redirection_performed', true);
982 update_option('auto_smart_tastewp_redirect_performed', 1);
983 update_option('tastewp_auto_activated', true);
984 update_option('__tastewp_sub_requested', true);
985
986 }
987
988 unlink($afterMigrationLock);
989 }
990
991 }
992
993 public function handle_downloading() {
994 global $wpdb;
995 @error_reporting(0);
996 $autologin_file = BMI_BACKUPS . '/.autologin';
997 $ip = '127.0.0.1';
998 if (isset($_SERVER['HTTP_CLIENT_IP'])) {
999 $ip = $_SERVER['HTTP_CLIENT_IP'];
1000 } else {
1001 if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
1002 $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
1003 }
1004 if ($ip === false) {
1005 if (isset($_SERVER['REMOTE_ADDR'])) $ip = $_SERVER['REMOTE_ADDR'];
1006 }
1007 }
1008 $allowed = ['BMI_BACKUP', 'BMI_BACKUP_LOGS', 'PROGRESS_LOGS', 'AFTER_RESTORE'];
1009 $get_bmi = !empty($_GET['backup-migration']) ? sanitize_text_field($_GET['backup-migration']) : false;
1010 $get_bid = !empty($_GET['backup-id']) ? sanitize_text_field($_GET['backup-id']) : false;
1011 $get_pid = !empty($_GET['progress-id']) ? sanitize_text_field($_GET['progress-id']) : false;
1012
1013 if (isset($get_bmi) && in_array($get_bmi, $allowed)) {
1014 if (isset($get_bid) && strlen($get_bid) > 0) {
1015 $type = $get_bmi;
1016
1017 if ($type == 'AFTER_RESTORE' && isset($get_pid)) {
1018 if (file_exists($autologin_file)) {
1019 $autoLoginMD = file_get_contents($autologin_file);
1020 $autoLoginMD = explode('_', $autoLoginMD);
1021 $aID = intval($autoLoginMD[0]);
1022 $aID2 = intval($autoLoginMD[0]) - 1;
1023 $aID3 = intval($autoLoginMD[0]) + 1;
1024 $aID4 = intval($autoLoginMD[0]) + 2;
1025 $aID5 = intval($autoLoginMD[0]) + 3;
1026 $aID6 = intval($autoLoginMD[0]) + 4;
1027 $aIP = $autoLoginMD[1];
1028 $aIZ = $autoLoginMD[2];
1029
1030 // Allow 1 second delay
1031 $timeIsProper = false;
1032 if ($aID === intval($get_bid)) $timeIsProper = true;
1033 if ($aID2 === intval($get_bid)) $timeIsProper = true;
1034 if ($aID3 === intval($get_bid)) $timeIsProper = true;
1035 if ($aID4 === intval($get_bid)) $timeIsProper = true;
1036 if ($aID5 === intval($get_bid)) $timeIsProper = true;
1037 if ($aID6 === intval($get_bid)) $timeIsProper = true;
1038
1039 if ($timeIsProper && $aIP === $ip && trim($aIZ) === $get_pid) {
1040 $query = new \WP_User_Query(['role' => 'Administrator', 'count_total' => false, 'fields' => 'all']);
1041 $sqlres = $wpdb->get_results($query->request);
1042
1043 if (sizeof($sqlres) > 0 && isset($sqlres[0]->ID) && isset($sqlres[0]->user_login)) {
1044
1045 $user = $sqlres[0];
1046 $adminID = $sqlres[0]->ID;
1047 $adminLogin = $sqlres[0]->user_login;
1048
1049 remove_all_actions('wp_login', -1000);
1050 wp_load_alloptions(true);
1051 clean_user_cache(get_current_user_id());
1052 clean_user_cache($adminID);
1053 wp_clear_auth_cookie();
1054 wp_set_current_user($adminID, $adminLogin);
1055 wp_set_auth_cookie($adminID, 1, is_ssl());
1056 do_action('wp_login', $adminLogin, $user);
1057 update_user_caches($user);
1058
1059 }
1060
1061 $url = admin_url('admin.php?page=backup-migration');
1062 header('Location: ' . $url);
1063
1064 @unlink($autologin_file);
1065 exit;
1066 }
1067 }
1068
1069 } else if ($type == 'BMI_BACKUP') {
1070 if (Dashboard\bmi_get_config('STORAGE::DIRECT::URL') === 'true' || current_user_can('administrator')) {
1071
1072 $backupname = $get_bid;
1073 $file = $this->fixSlashes(BMI_BACKUPS . DIRECTORY_SEPARATOR . $backupname);
1074
1075 $outsideDir = false;
1076 if (!(file_exists($file) && $this->fixSlashes(dirname($file)) == $this->fixSlashes(BMI_BACKUPS))) {
1077 $outsideDir = true;
1078 }
1079
1080 if (strpos(strtolower(mime_content_type($file)), 'zip') === false || $outsideDir) {
1081 header('HTTP/1.0 423 Locked');
1082 _e("Incorrect usage of the query request.", 'backup-backup');
1083 exit;
1084 }
1085
1086 if (Dashboard\bmi_get_config('OTHER:DOWNLOAD:DIRECT') == 'true') {
1087 if (file_exists(BMI_BACKUPS . DIRECTORY_SEPARATOR . '.htaccess')) @unlink(BMI_BACKUPS . DIRECTORY_SEPARATOR . '.htaccess');
1088 if (file_exists(dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . '.htaccess')) @unlink(dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . '.htaccess');
1089 $wpcontent = trailingslashit(WP_CONTENT_DIR);
1090 $wpcs = strlen($wpcontent);
1091 $url = $this->fixSlashes(content_url(substr($file, $wpcs)), '/');
1092 $path = wp_redirect($url);
1093 exit;
1094 }
1095
1096 // Prevent parent directory downloading
1097 if (ob_get_contents()) ob_end_clean();
1098
1099 if ($this->isFunctionEnabled('ignore_user_abort')) @ignore_user_abort(true);
1100 if ($this->isFunctionEnabled('set_time_limit')) @set_time_limit(16000);
1101 if ($this->isFunctionEnabled('headers_sent') && $this->isFunctionEnabled('session_status')) {
1102 if (!headers_sent() && session_status() === PHP_SESSION_DISABLED) {
1103 if ($this->isFunctionEnabled('ini_set')) {
1104 @ini_set('max_execution_time', '259200');
1105 @ini_set('max_input_time', '259200');
1106 @ini_set('session.gc_maxlifetime', '1200');
1107 @ini_set('memory_limit', '-1');
1108 if (@ini_get('zlib.output_compression')) {
1109 @ini_set('zlib.output_compression', 'Off');
1110 }
1111 }
1112 }
1113 }
1114
1115 if (strlen(session_id()) > 0) session_write_close();
1116
1117 $fp = @fopen($file, 'rb');
1118
1119 // header('X-Sendfile: ' . $file);
1120 // header('X-Sendfile-Type: X-Accel-Redirect');
1121 // header('X-Accel-Redirect: ' . $file);
1122 // header('X-Accel-Buffering: yes');
1123 header('Expires: 0');
1124 header('Pragma: public');
1125 header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
1126 header('Content-Disposition: attachment; filename="' . $backupname . '"');
1127 header('Content-Type: application/octet-stream');
1128 header('Content-Transfer-Encoding: binary');
1129 header('Content-Length: ' . filesize($file));
1130 header('Content-Description: File Transfer');
1131 http_response_code(200);
1132
1133 if (ob_get_level()) ob_end_clean();
1134
1135 fpassthru($fp);
1136 fclose($fp);
1137 exit;
1138
1139 } else {
1140 if (ob_get_contents()) ob_end_clean();
1141 header('HTTP/1.0 423 Locked');
1142 if (ob_get_level()) ob_end_clean();
1143 echo __("Backup download is restricted (allowed for admins only).", 'backup-backup');
1144 exit;
1145 }
1146 } elseif ($type == 'BMI_BACKUP_LOGS') {
1147
1148 // Only Admin can download backup logs
1149 if (!(current_user_can('administrator') || current_user_can('do_backups'))) return;
1150
1151 if (ob_get_contents()) ob_end_clean();
1152 $backupname = $get_bid;
1153 $file = $this->fixSlashes(BMI_BACKUPS . DIRECTORY_SEPARATOR . $backupname);
1154
1155 // Prevent parent directory downloading
1156 if (file_exists($file) && $this->fixSlashes(dirname($file)) == $this->fixSlashes(BMI_BACKUPS)) {
1157 require_once BMI_INCLUDES . '/zipper/zipping.php';
1158
1159 $zipper = new Zipper();
1160 $logs = $zipper->getZipFileContentPlain($file, 'bmi_logs_this_backup.log');
1161 header('Content-Type: text/plain');
1162
1163 if ($logs) {
1164 header('Content-Disposition: attachment; filename="' . substr($backupname, 0, -4) . '.log"');
1165 http_response_code(200);
1166 if (ob_get_level()) ob_end_clean();
1167
1168 $logs = explode('\n', $logs);
1169 $current_directory = Dashboard\bmi_get_config('STORAGE::LOCAL::PATH');
1170 $backups_path = $this->fixSlashes($current_directory . DIRECTORY_SEPARATOR . 'backups');
1171 $scanned_directory_all = array_diff(scandir($backups_path), ['..', '.']);
1172 $scanned_directory = array_values(preg_grep('/((.*).zip)/i', $scanned_directory_all));
1173
1174 for ($i = 0; $i < sizeof($logs); ++$i) {
1175
1176 $line = $logs[$i];
1177 echo $this->escapeSensitive($line, $current_directory, $scanned_directory) . "\n";
1178
1179 }
1180
1181 exit;
1182 } else {
1183 if (ob_get_level()) ob_end_clean();
1184 header('HTTP/1.0 404 Not found');
1185 echo __("There was an error during getting logs, this file is not right log file.", 'backup-backup');
1186 exit;
1187 }
1188 }
1189
1190 } elseif ($type == 'PROGRESS_LOGS') {
1191 $allowed_progress = [
1192 'latest_full.log',
1193 'latest.log',
1194 'latest_progress.log',
1195 'latest_migration_full.log',
1196 'latest_migration.log',
1197 'latest_migration_progress.log',
1198 'latest_staging_full.log',
1199 'latest_staging.log',
1200 'latest_staging_progress.log',
1201 'complete_logs.log'
1202 ];
1203 if (isset($get_pid) && in_array($get_pid, $allowed_progress)) {
1204
1205 $restricted_progress = ['complete_logs.log'];
1206 if (in_array($get_pid, $restricted_progress)) {
1207
1208 // Only Admin can download backup logs
1209 if (!(current_user_can('administrator') || current_user_can('do_backups'))) return;
1210
1211 }
1212
1213 header('Content-Type: text/plain');
1214 header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
1215 http_response_code(200);
1216 if (ob_get_contents()) ob_end_clean();
1217 if ($get_pid == 'complete_logs.log') {
1218 $file = BMI_CONFIG_DIR . DIRECTORY_SEPARATOR . 'complete_logs.log';
1219 if (ob_get_level()) ob_end_clean();
1220 $this->readFileSensitive($file);
1221 exit;
1222 } else if ($get_pid == 'latest_full.log') {
1223 $progress = dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . 'latest_progress.log';
1224 $logs = dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . 'latest.log';
1225 if ((file_exists($progress) && file_exists($logs) && ((time() - filemtime($progress)) < (60 * 1))) || current_user_can('administrator')) {
1226 if (ob_get_level()) ob_end_clean();
1227 readfile($progress);
1228 echo "\n";
1229 $this->readFileSensitive($logs);
1230 exit;
1231 } else {
1232 if (file_exists($progress) && !(time() - filemtime($progress)) < (60 * 1)) {
1233 if (ob_get_level()) ob_end_clean();
1234 echo __("Due to security reasons access to this file is disabled at this moment.", 'backup-backup') . "\n";
1235 echo __("Human readable: file expired.", 'backup-backup');
1236 exit;
1237 } else {
1238 if (ob_get_level()) ob_end_clean();
1239 echo '';
1240 exit;
1241 }
1242 }
1243 } else if ($get_pid == 'latest_migration_full.log') {
1244 $progress = dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . 'latest_migration_progress.log';
1245 $logs = dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . 'latest_migration.log';
1246 if ((file_exists($progress) && file_exists($logs) && ((time() - filemtime($progress)) < (60 * 1))) || current_user_can('administrator')) {
1247 if (ob_get_level()) ob_end_clean();
1248 readfile($progress);
1249 echo "\n";
1250 $this->readFileSensitive($logs);
1251 exit;
1252 } else {
1253 if (file_exists($progress) && !(time() - filemtime($progress)) < (60 * 1)) {
1254 if (ob_get_level()) ob_end_clean();
1255 echo __("Due to security reasons access to this file is disabled at this moment.", 'backup-backup') . "\n";
1256 echo __("Human readable: file expired.", 'backup-backup');
1257 exit;
1258 } else {
1259 if (ob_get_level()) ob_end_clean();
1260 echo '';
1261 exit;
1262 }
1263 }
1264 } else if ($get_pid == 'latest_staging_full.log') {
1265 $progress = BMI_STAGING . DIRECTORY_SEPARATOR . 'latest_staging_progress.log';
1266 $logs = BMI_STAGING . DIRECTORY_SEPARATOR . 'latest_staging.log';
1267 if ((file_exists($progress) && file_exists($logs) && ((time() - filemtime($progress)) < (60 * 1))) || current_user_can('administrator')) {
1268 if (ob_get_level()) ob_end_clean();
1269 readfile($progress);
1270 echo "\n";
1271 $this->readFileSensitive($logs);
1272 exit;
1273 } else {
1274 if (file_exists($progress) && !(time() - filemtime($progress)) < (60 * 1)) {
1275 if (ob_get_level()) ob_end_clean();
1276 echo __("Due to security reasons access to this file is disabled at this moment.", 'backup-backup') . "\n";
1277 echo __("Human readable: file expired.", 'backup-backup');
1278 exit;
1279 } else {
1280 if (ob_get_level()) ob_end_clean();
1281 echo '';
1282 exit;
1283 }
1284 }
1285 } else {
1286 $file = dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . $get_pid;
1287 if ($get_pid == 'latest_staging.log') $file = BMI_STAGING . DIRECTORY_SEPARATOR . $get_pid;
1288 if ($get_pid == 'latest_staging_progress.log') $file = BMI_STAGING . DIRECTORY_SEPARATOR . $get_pid;
1289 if (file_exists($file) && (((time() - filemtime($file)) < (60 * 1)) || current_user_can('administrator'))) {
1290 if (ob_get_level()) ob_end_clean();
1291
1292 $this->readFileSensitive($file);
1293
1294 echo "\n";
1295 if ($get_pid == 'latest.log') $file = dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . 'latest_progress.log';
1296 if ($get_pid == 'latest_migration.log') $file = dirname(BMI_BACKUPS) . DIRECTORY_SEPARATOR . 'backups' . DIRECTORY_SEPARATOR . 'latest_migration_progress.log';
1297 if ($get_pid == 'latest_staging.log') $file = BMI_STAGING . DIRECTORY_SEPARATOR . 'latest_staging_progress.log';
1298 echo __("[DOWNLOAD GENERATED] File downloaded on (server time): ", 'backup-backup') . date('Y-m-d H:i:s') . "\n";
1299 echo __("[DOWNLOAD GENERATED] Last update (seconds): ", 'backup-backup') . (time() - filemtime($file)) . __(" seconds ago ", 'backup-backup') . "\n";
1300 echo __("[DOWNLOAD GENERATED] Last update (date): ", 'backup-backup') . date('Y-m-d H:i:s', filemtime($file)) . " \n";
1301 exit;
1302 } else {
1303 if (file_exists($file) && !(time() - filemtime($file)) < (60 * 1)) {
1304 if (ob_get_level()) ob_end_clean();
1305 echo __("Due to security reasons access to this file is disabled at this moment.", 'backup-backup') . "\n";
1306 echo __("Human readable: file expired.", 'backup-backup');
1307 exit;
1308 } else {
1309 if (ob_get_level()) ob_end_clean();
1310 echo '';
1311 exit;
1312 }
1313 }
1314 }
1315 exit;
1316 }
1317 }
1318 }
1319 }
1320 }
1321
1322 public function deactivation() {
1323 Logger::log(__("Plugin has been deactivated", 'backup-backup'));
1324 $this->revertLitespeed();
1325 }
1326
1327 public static function res($array) {
1328 echo json_encode(Backup_Migration_Plugin::sanitize($array));
1329
1330 if (defined('BMI_USING_CLI_FUNCTIONALITY') && BMI_USING_CLI_FUNCTIONALITY === true) {
1331 Logger::log('CLI response:');
1332 Logger::log(json_encode(Backup_Migration_Plugin::sanitize($array)));
1333 }
1334
1335 exit;
1336 }
1337
1338 public static function getAvailableMemoryInBytes() {
1339
1340 $totalMemory = @ini_get('memory_limit');
1341 if ($totalMemory == -1) {
1342
1343 $totalMemory = 32 * 1024 * 1024;
1344
1345 } else {
1346
1347 if (strpos($totalMemory, 'M') !== false || strpos($totalMemory, 'm') !== false) {
1348 $totalMemory = intval($totalMemory) * 1024 * 1024;
1349 } else if (strpos($totalMemory, 'G') !== false || strpos($totalMemory, 'g') !== false) {
1350 $totalMemory = intval($totalMemory) * 1024 * 1024 * 1024;
1351 } else if (strpos($totalMemory, 'K') !== false || strpos($totalMemory, 'k') !== false) {
1352 $totalMemory = intval($totalMemory) * 1024;
1353 } else {
1354 $totalMemory = intval($totalMemory);
1355 }
1356
1357 }
1358
1359 $availableMemory = $totalMemory - memory_get_usage(true);
1360
1361 return $availableMemory;
1362
1363 }
1364
1365 public static function sanitize($data = []) {
1366 $array = [];
1367
1368 if (is_array($data) || is_object($data)) {
1369 foreach ($data as $key => $value) {
1370 $key = ((is_numeric($key))?intval($key):sanitize_text_field($key));
1371
1372 if (is_array($value) || is_object($value)) {
1373 $array[$key] = Backup_Migration_Plugin::sanitize($value);
1374 } else {
1375 $array[$key] = sanitize_text_field($value);
1376 }
1377 }
1378 } elseif (is_string($data)) {
1379 return sanitize_text_field($data);
1380 } elseif (is_bool($data)) {
1381 return $data;
1382 } elseif (is_null($data)) {
1383 return 'false';
1384 } else {
1385 Logger::log(__("Unknow AJAX Sanitize Type: ", 'backup-backup') . gettype($data));
1386 wp_die();
1387 }
1388
1389 return $array;
1390 }
1391
1392 public static function fixLitespeed() {
1393 $litepath = BMI_INCLUDES . DIRECTORY_SEPARATOR . 'htaccess' . DIRECTORY_SEPARATOR . '.litespeed';
1394 $htpath = ABSPATH . DIRECTORY_SEPARATOR . '.htaccess';
1395 if (!is_writable($htpath)) return ['status' => 'success'];
1396 if (file_exists($htpath)) {
1397 Backup_Migration_Plugin::revertLitespeed();
1398 $litespeed = @file_get_contents($litepath);
1399 $htaccess = @file_get_contents($htpath);
1400 $htaccess = explode("\n", $htaccess);
1401 $litespeed = explode("\n", $litespeed);
1402
1403 $hasAlready = false;
1404 for ($i = 0; $i < sizeof($htaccess); ++$i) {
1405 if (strpos($htaccess[$i], 'Backup Migration') !== false) {
1406 $hasAlready = true;
1407
1408 break;
1409 }
1410 }
1411
1412 if ($hasAlready) {
1413 return ['status' => 'success'];
1414 }
1415 $htaccess[] = '';
1416 for ($i = 0; $i < sizeof($litespeed); ++$i) {
1417 $htaccess[] = $litespeed[$i];
1418 }
1419
1420 file_put_contents($htpath, implode("\n", $htaccess));
1421 } else {
1422 copy($litepath, $htpath);
1423 }
1424
1425 return ['status' => 'success'];
1426 }
1427
1428 public static function revertLitespeed() {
1429 $htpath = ABSPATH . DIRECTORY_SEPARATOR . '.htaccess';
1430 $addline = true;
1431
1432 if (!is_writable($htpath)) return ['status' => 'success'];
1433 $htaccess = @file_get_contents($htpath);
1434 $htaccess = explode("\n", $htaccess);
1435 $htFilter = [];
1436
1437 for ($i = 0; $i < sizeof($htaccess); ++$i) {
1438 if (strpos($htaccess[$i], 'Backup Migration START')) {
1439 $addline = false;
1440
1441 continue;
1442 } elseif (strpos($htaccess[$i], 'Backup Migration END')) {
1443 $addline = true;
1444
1445 continue;
1446 } else {
1447 if ($addline == true) {
1448 $htFilter[] = $htaccess[$i];
1449 }
1450 }
1451 }
1452
1453 file_put_contents($htpath, trim(implode("\n", $htFilter)));
1454
1455 return ['status' => 'success'];
1456 }
1457
1458 public static function humanSize($bytes) {
1459 if (is_int($bytes)) {
1460 $label = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
1461 for ($i = 0; $bytes >= 1024 && $i < (count($label) - 1); $bytes /= 1024, $i++);
1462
1463 return (round($bytes, 2) . " " . $label[$i]);
1464 } else return $bytes;
1465 }
1466
1467 public static function fixSlashes($str, $slash = false) {
1468 // Old version
1469 // $str = str_replace('\\\\', DIRECTORY_SEPARATOR, $str);
1470 // $str = str_replace('\\', DIRECTORY_SEPARATOR, $str);
1471 // $str = str_replace('\/', DIRECTORY_SEPARATOR, $str);
1472 // $str = str_replace('/', DIRECTORY_SEPARATOR, $str);
1473
1474 // if ($str[strlen($str) - 1] == DIRECTORY_SEPARATOR) {
1475 // $str = substr($str, 0, -1);
1476 // }
1477
1478 // Since 1.3.2
1479 $protocol = '';
1480 if ($slash == false) $slash = DIRECTORY_SEPARATOR;
1481 if (substr($str, 0, 7) == 'http://') $protocol = 'http://';
1482 else if (substr($str, 0, 8) == 'https://') $protocol = 'https://';
1483
1484 $str = substr($str, strlen($protocol));
1485 $str = preg_replace('/[\\\\\/]+/', $slash, $str);
1486 $str = untrailingslashit($str);
1487
1488 return $protocol . $str;
1489 }
1490
1491 public static function canShareLogsOrShouldAsk() {
1492
1493 return 'not-allowed';
1494
1495 // REMOVED CODE:
1496 // $isAllowed = get_option('BMI_LOGS_SHARING_IS_ALLOWED', 'unknown');
1497 // $isAllowedConfig = Dashboard\bmi_get_config('LOGS::SHARING');
1498 //
1499 // if ($isAllowed == 'unknown' || empty($isAllowedConfig)) return 'ask';
1500 // else if ($isAllowed === 'yes' && $isAllowedConfig === 'yes') {
1501 // return 'allowed';
1502 // } else if ($isAllowed === 'no' && $isAllowedConfig === 'no') {
1503 // return 'not-allowed';
1504 // } else return 'ask';
1505
1506 }
1507
1508 public static function merge_arrays(&$array1, &$array2) {
1509 for ($i = 0; $i < sizeof($array2); ++$i) {
1510 $array1[] = $array2[$i];
1511 }
1512 }
1513
1514 private function get_asset($base = '', $asset = '') {
1515 return BMI_ASSETS . '/' . $base . '/' . $asset;
1516 }
1517 }
1518