Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upd. Code. Added psalm extension to check prepare. #442

Merged
merged 10 commits into from
Nov 21, 2024
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
"phpunit/phpunit": "^7.5",
"squizlabs/php_codesniffer": "3.*",
"phpcompatibility/php-compatibility": "@dev",
"yoast/phpunit-polyfills": "^1.0"
"yoast/phpunit-polyfills": "^1.0",
"glomberg/wpdb-unsafe-methods": "^1.0"
},
"scripts": {
"test": [
Expand Down
170 changes: 101 additions & 69 deletions inc/spbc-backups.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ function spbc_backup__rotate($type = 'signatures', $out = array('success' => tru
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
Expand Down Expand Up @@ -79,96 +81,126 @@ function spbc_backup__delete($direct_call = false, $backup_id = null)
return $output;
}

function spbc_backup__files_with_signatures($direct_call = false)
/**
* Make backup of files with signatures handler
* @return array<string, mixed>
*/
function spbc_backup__files_with_signatures_handler()
{
if ( ! $direct_call) {
spbc_check_ajax_referer('spbc_secret_nonce', 'security');
}

global $wpdb, $spbc;

$output = array('success' => true);

$files_to_backup = $wpdb->get_results('SELECT path, weak_spots FROM ' . SPBC_TBL_SCAN_FILES . ' WHERE weak_spots LIKE "%\"SIGNATURES\":%";', ARRAY_A);

if (is_array($files_to_backup) && count($files_to_backup)) {
$sql_query = 'INSERT INTO ' . SPBC_TBL_BACKUPED_FILES . ' (backup_id, real_path, back_path) VALUES';
$sql_data = array();
if (!is_array($files_to_backup) || !count($files_to_backup)) {
$output = array('success' => true);
return $output;
}

foreach ($files_to_backup as $file) {
$weak_spots = json_decode($file['weak_spots'], true);
$sql_data = array();
foreach ($files_to_backup as $file) {
$weak_spots = json_decode($file['weak_spots'], true);

if (!empty($weak_spots['SIGNATURES'])) {
$signtures_in_file = array();
foreach ($weak_spots['SIGNATURES'] as $signatures_in_string) {
$signtures_in_file = array_merge($signtures_in_file, array_diff($signatures_in_string, $signtures_in_file));
}
$signtures_in_file = implode(',', $signtures_in_file);
$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));
}
}

$signatures_with_cci = ! empty($signtures_in_file)
? $wpdb->get_results('SELECT * FROM ' . SPBC_TBL_SCAN_SIGNATURES . ' WHERE id IN (' . $signtures_in_file . ') AND cci IS NOT NULL')
: null;

// Backup only files which will be cured
if ($signatures_with_cci) {
if ( ! isset($backup_id)) {
// Adding new backup
$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');
}
if (empty($signtures_in_file)) {
continue;
}

$dir_name .= 'backup_' . $backup_id;
if ( ! is_dir($dir_name)) {
mkdir($dir_name);
file_put_contents($dir_name . '/index.php', '<?php');
}
}
$sql_signatures_placeholder = rtrim(str_repeat('%s,', count($signtures_in_file)), ',');
$sql_signatures = 'SELECT * FROM ' . SPBC_TBL_SCAN_SIGNATURES . " WHERE id IN ($sql_signatures_placeholder) AND cci IS NOT NULL;";
$signatures_with_cci = $wpdb->get_results($wpdb->prepare($sql_signatures, $signtures_in_file), ARRAY_A);

$result = spbc_backup__file($file['path'], $backup_id);
// Backup only files which will be cured
if (!$signatures_with_cci) {
continue;
}

if (empty($result['error'])) {
$sql_data[] = '(' . $backup_id . ',' . Helper::prepareParamForSQLQuery($file['path']) . ',' . Helper::prepareParamForSQLQuery($result) . ')';
} else {
// Mark the backup STOPPED while errors occurred
$wpdb->update(SPBC_TBL_BACKUPS, array('status' => 'STOPPED'), array('backup_id' => $backup_id));
$output = $result;
break;
}
// 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');
}
}

$backup_id = isset($backup_id) ? $backup_id : $spbc->data['scanner']['last_backup'];
$result = spbc_backup__file($file['path'], $backup_id);

// Writing backuped files to DB
if ( ! empty($sql_data) && ! isset($output['error'])) {
if ($wpdb->query($sql_query . implode(',', $sql_data) . ';') !== false) {
// Updating current backup status
if ($wpdb->update(SPBC_TBL_BACKUPS, array('status' => 'BACKUPED'), array('backup_id' => $backup_id)) !== false) {
$result = spbc_backup__rotate('signatures');
if (empty($result['error'])) {
$output = array('success' => true);
} else {
$output = array('error' => 'BACKUP_ROTATE: ' . substr($result['error'], 0, 1024));
}
} else {
$output = array('error' => 'DB_WRITE_ERROR: ' . substr($wpdb->last_error, 0, 1024));
}
} else {
$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));
}
if (empty($result['error'])) {
$sql_data[] = '(' . $backup_id . ',' . Helper::prepareParamForSQLQuery($file['path']) . ',' . Helper::prepareParamForSQLQuery($result) . ')';
} else {
$output = array('success' => true);
// Mark the backup STOPPED while errors occurred
$wpdb->update(SPBC_TBL_BACKUPS, array('status' => 'STOPPED'), array('backup_id' => $backup_id));
$output = $result;
break;
}
} else {
}

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) 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) {
Expand Down
Loading