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