Current File : /home/n742ef5/royalanteam.com/wp-content/plugins/security-malware-firewall/inc/spbc-backups.php |
<?php
use CleantalkSP\SpbctWP\Helpers\Helper;
function spbc_backup__rotate($type = 'signatures', $out = array('success' => true))
{
global $wpdb;
$result = $wpdb->get_row('SELECT COUNT(*) as cnt FROM ' . SPBC_TBL_BACKUPS . ' WHERE type = ' . Helper::prepareParamForSQLQuery(strtoupper($type)), OBJECT);
if ($result->cnt > 10) {
// suppress because data is already prepared in Helper::prepareParamForSQLQuery method
// @psalm-suppress WpdbUnsafeMethodsIssue
$result = $wpdb->get_results(
'SELECT backup_id'
. ' FROM ' . SPBC_TBL_BACKUPS
. ' WHERE datetime < ('
. 'SELECT datetime'
. ' FROM ' . SPBC_TBL_BACKUPS
. ' WHERE type = ' . Helper::prepareParamForSQLQuery(strtoupper($type))
. ' ORDER BY datetime DESC'
. ' LIMIT 9,1)'
);
if ($result && count($result)) {
foreach ($result as $backup) {
$result = spbc_backup__delete(true, $backup->backup_id);
if ( ! empty($result['error'])) {
$out = array('error' => 'BACKUP_DELETE: ' . substr($result['error'], 0, 1024));
}
}
}
}
return $out;
}
function spbc_backup__delete($direct_call = false, $backup_id = null)
{
global $wpdb;
if (!$direct_call) {
spbc_check_ajax_referer('spbc_secret_nonce', 'security');
}
$backup_id = !$direct_call && !empty($_POST['backup_id']) ? (int)$_POST['backup_id'] : $backup_id;
if (is_dir(SPBC_PLUGIN_DIR . 'backups/backup_' . $backup_id)) {
// Deleting backup files
foreach (glob(SPBC_PLUGIN_DIR . 'backups/backup_' . $backup_id . '/*') as $filename) {
if (!unlink($filename)) {
$output = array('error' => 'FILE_DELETE_ERROR: ' . substr($filename, 0, 1024));
break;
}
}
if (empty($output['error'])) {
if (rmdir(SPBC_PLUGIN_DIR . 'backups/backup_' . $backup_id)) {
if (false !== $wpdb->delete(SPBC_TBL_BACKUPED_FILES, array('backup_id' => $backup_id), array('%d'))) {
if (false !== $wpdb->delete(SPBC_TBL_BACKUPS, array('backup_id' => $backup_id), array('%d'))) {
$output = array(
'html' => '<td ' . (isset($_POST['cols']) ? "colspan='{$_POST['cols']}'" : '') . '>Backup deleted</td>',
'success' => true,
'color' => 'black',
'background' => 'rgba(240, 110, 110, 0.7)',
);
} else {
$output = array('error' => 'DELETING_BACKUP_DB_ERROR: ' . substr($wpdb->last_error, 0, 1024));
}
} else {
$output = array('error' => 'DELETING_BACKUP_FILES_DB_ERROR: ' . substr($wpdb->last_error, 0, 1024));
}
} else {
$output = array('error' => 'DIRECTORY_DELETE_ERROR: ' . substr(SPBC_PLUGIN_DIR . 'backups/backup_' . $backup_id, 0, 1024));
}
}
} else {
$output = array('comment' => 'DIRECTORY_NOT_EXISTS: ' . substr(SPBC_PLUGIN_DIR . 'backups/backup_' . $backup_id, 0, 1024));
}
if (!$direct_call) {
wp_send_json($output);
}
return $output;
}
/**
* Make backup of files with signatures handler
* @return array<string, mixed>
*/
function spbc_backup__files_with_signatures_handler()
{
global $wpdb, $spbc;
$output = array('success' => true);
$files_to_backup = $wpdb->get_results('SELECT path, weak_spots, checked_heuristic, checked_signatures, status, severity FROM ' . SPBC_TBL_SCAN_FILES . ' WHERE weak_spots LIKE "%\"SIGNATURES\":%";', ARRAY_A);
if (!is_array($files_to_backup) || !count($files_to_backup)) {
$output = array('success' => true);
return $output;
}
$sql_data = array();
foreach ($files_to_backup as $file) {
if (spbc_file_has_backup($file['path'])) {
continue;
}
$weak_spots = json_decode($file['weak_spots'], true);
$signtures_in_file = array();
if (!empty($weak_spots['SIGNATURES'])) {
foreach ($weak_spots['SIGNATURES'] as $signatures_in_string) {
$signtures_in_file = array_merge($signtures_in_file, array_diff($signatures_in_string, $signtures_in_file));
}
}
if (empty($signtures_in_file)) {
continue;
}
// Adding new backup batch
if ( ! isset($backup_id)) {
$wpdb->insert(SPBC_TBL_BACKUPS, array('type' => 'SIGNATURES', 'datetime' => date('Y-m-d H:i:s')));
$backup_id = $wpdb->insert_id;
$spbc->data['scanner']['last_backup'] = $backup_id;
$spbc->save('data');
$dir_name = SPBC_PLUGIN_DIR . 'backups/';
if ( ! is_dir($dir_name)) {
mkdir($dir_name);
file_put_contents($dir_name . 'index.php', '<?php');
}
$dir_name .= 'backup_' . $backup_id;
if ( ! is_dir($dir_name)) {
mkdir($dir_name);
file_put_contents($dir_name . '/index.php', '<?php');
}
}
$result = spbc_backup__file($file['path'], $backup_id);
$backup_prev_results_state = json_encode($file);
$backup_prev_results_state = $backup_prev_results_state === false ? 'ERROR' : $backup_prev_results_state;
if (empty($result['error'])) {
$sql_data[] = '('
. $backup_id . ','
. Helper::prepareParamForSQLQuery($file['path']) . ','
. Helper::prepareParamForSQLQuery($result) . ','
. Helper::prepareParamForSQLQuery($backup_prev_results_state)
. ')';
} else {
// Mark the backup STOPPED while errors occurred
$wpdb->update(SPBC_TBL_BACKUPS, array('status' => 'STOPPED'), array('backup_id' => $backup_id));
$output = $result;
break;
}
}
if (empty($sql_data) || isset($output['error'])) {
$output = array('success' => true);
return $output;
}
$backup_id = isset($backup_id) ? $backup_id : $spbc->data['scanner']['last_backup'];
// Writing backuped files to DB
$sql_query = 'INSERT INTO ' . SPBC_TBL_BACKUPED_FILES . ' (backup_id, real_path, back_path, backup_prev_results_state) VALUES';
// suppress because data is already prepared in Helper::prepareParamForSQLQuery method
// @psalm-suppress WpdbUnsafeMethodsIssue
$result = $wpdb->query($sql_query . implode(',', $sql_data) . ';');
if ($result === false) {
$wpdb->update(SPBC_TBL_BACKUPS, array('status' => 'STOPPED'), array('backup_id' => $backup_id));
$output = array('error' => 'DB_WRITE_ERROR: ' . substr($wpdb->last_error, 0, 1024));
return $output;
}
// Updating current backup status
$result = $wpdb->update(SPBC_TBL_BACKUPS, array('status' => 'BACKUPED'), array('backup_id' => $backup_id));
if ($result === false) {
$output = array('error' => 'DB_WRITE_ERROR: ' . substr($wpdb->last_error, 0, 1024));
return $output;
}
$result = spbc_backup__rotate('signatures');
if (!empty($result['error'])) {
$output = array('error' => 'BACKUP_ROTATE: ' . substr($result['error'], 0, 1024));
return $output;
}
$output = array('success' => true);
return $output;
}
/**
* Make backup of files with signatures
* @return array<string, mixed>
*/
function spbc_backup__files_with_signatures($direct_call = false)
{
if ( ! $direct_call) {
spbc_check_ajax_referer('spbc_secret_nonce', 'security');
}
$output = spbc_backup__files_with_signatures_handler();
$output['end'] = 1;
if (!$direct_call) {
wp_send_json($output);
}
return $output;
}
function spbc_backup__file($filename, $backup_id)
{
global $spbc;
$file_path = spbc_get_root_path() . $filename;
if (file_exists($file_path)) {
if (is_readable($file_path)) {
$backup_path = '/wp-content/plugins/security-malware-firewall/backups/backup_'
. $backup_id
. '/' . str_replace('/', '__', str_replace('\\', '__', $filename))
. '.' . hash('sha256', $filename . $spbc->data['salt']);
if (copy($file_path, spbc_get_root_path() . $backup_path)) {
$output = $backup_path;
} else {
$output = array('error' => 'COPY_FAILED');
}
} else {
$output = array('error' => 'FILE_NOT_READABLE');
}
} else {
$output = array('error' => 'FILE_NOT_EXISTS');
}
return $output;
}
function spbc_rollback($direct_call = false, $backup_id = null)
{
if ( ! $direct_call) {
spbc_check_ajax_referer('spbc_secret_nonce', 'security');
}
$backup_id = ! $direct_call && ! empty($_POST['backup_id']) ? (int) $_POST['backup_id'] : $backup_id;
global $wpdb;
$files_to_rollback = $wpdb->get_results('SELECT real_path, back_path FROM ' . SPBC_TBL_BACKUPED_FILES . ' WHERE backup_id = ' . $backup_id . ';', ARRAY_A);
if (is_array($files_to_rollback) && count($files_to_rollback)) {
$wpdb->update(SPBC_TBL_BACKUPS, array('status' => 'ROLLBACK'), array('backup_id' => $backup_id));
foreach ($files_to_rollback as $file) {
$result = spbc_rollback__file($file['back_path'], $file['real_path']);
if ( ! empty($result['error'])) {
$output = $result;
break;
}
}
if (empty($output['error'])) {
if ($wpdb->delete(SPBC_TBL_BACKUPED_FILES, array('backup_id' => $backup_id), array('%d'))) {
if ($wpdb->delete(SPBC_TBL_BACKUPS, array('backup_id' => $backup_id), array('%d'))) {
rmdir(spbc_get_root_path() . '/wp-content/plugins/security-malware-firewall/backups/backup_' . $backup_id);
$output = array(
'html' => '<td ' . (isset($_POST['cols']) ? "colspan='{$_POST['cols']}'" : '') . '>Rollback succeeded</td>',
'success' => true,
'color' => 'black',
'background' => 'rgba(110, 240, 110, 0.7)',
);
} else {
$output = array('error' => 'DELETING_BACKUP_DB_WRITE_ERROR: ' . substr($wpdb->last_error, 0, 1024));
}
} else {
$output = array('error' => 'DELETING_BACKUP_FILES_DB_WRITE_ERROR: ' . substr($wpdb->last_error, 0, 1024));
}
} else {
$output = array('error' => 'FILE_BACKUP_ERROR: ' . $output['error'] . 'FILE: ' . $file['back_path']);
}
} else {
$output = array('error' => 'BACKUP_NOT_FOUND');
}
if (!$direct_call) {
wp_send_json($output);
}
return $output;
}
function spbc_rollback__file($back_path, $real_path)
{
$back_path = spbc_get_root_path() . $back_path;
$real_path = spbc_get_root_path() . $real_path;
if (file_exists($back_path)) {
if (is_writable($back_path)) {
if (is_dir(dirname($real_path))) {
if (copy($back_path, $real_path)) {
unlink($back_path);
$output = array('success' => true);
} else {
$output = array('error' => 'COPY_FAILED');
}
} else {
$output = array('error' => 'REAL_FILE_DIR_NOT_EXISTS');
}
} else {
$output = array('error' => 'BACKUPED_FILE_NOT_WRITABLE');
}
} else {
$output = array('error' => 'BACKUPED_FILE_NOT_EXISTS');
}
return $output;
}
function spbc_backups_count_found()
{
global $wpdb;
$count = $wpdb->get_results(
'SELECT COUNT(*) FROM ' . SPBC_TBL_BACKUPS,
OBJECT_K
);
return $count ? key($count) : 0;
}
function spbc_file_has_backup($real_path)
{
global $spbc, $wpdb;
$real_path = $spbc->is_windows ? str_replace('/', '\\', $real_path) : $real_path;
$query = 'SELECT * FROM ' . SPBC_TBL_BACKUPED_FILES;
$result = $wpdb->get_results($query, ARRAY_A);
foreach ($result as $row) {
if ($row['real_path'] === $real_path) {
return true;
}
}
return false;
}