Files
User A0264400 a766acdc90 first commit
2026-04-01 23:20:16 +03:00

254 lines
6.6 KiB
PHP

<?php
if (!defined('ABSPATH')) die('Access denied.');
if (!class_exists('AIOWPSecurity_Ajax')) :
class AIOWPSecurity_Ajax {
private $commands_object;
private $nonce;
private $subaction;
private $data;
private $results;
/**
* Constructor
*/
private function __construct() {
if (!class_exists('AIOWPSecurity_Commands')) include_once(AIO_WP_SECURITY_PATH.'/classes/wp-security-commands.php');
$this->commands_object = new AIOWPSecurity_Commands();
add_action('wp_ajax_aios_ajax', array($this, 'handle_ajax_requests'));
add_action('wp_ajax_nopriv_get_antibot_keys', array($this->commands_object, 'get_antibot_keys'));
}
/**
* Return singleton instance
*
* @return AIOWPSecurity_Ajax Returns AIOWPSecurity_Ajax object
*/
public static function get_instance() {
static $instance = null;
if (null === $instance) {
$instance = new self();
}
return $instance;
}
/**
* Handles ajax requests
*
* @return void
*/
public function handle_ajax_requests() {
$this->set_nonce();
$this->set_subaction();
$this->set_data();
$result = AIOWPSecurity_Utility_Permissions::check_nonce_and_user_cap($this->nonce, 'wp-security-ajax-nonce');
if (is_wp_error($result)) {
wp_send_json(array(
'result' => false,
'error_code' => $result->get_error_code(),
'error_message' => $result->get_error_message(),
));
}
if (is_multisite() && !current_user_can('manage_network_options')) {
if (!$this->is_valid_multisite_command()) {
$this->send_invalid_multisite_command_error_response();
}
}
if ($this->is_invalid_command()) {
$this->add_invalid_command_error_log_entry();
$this->set_invalid_command_error_response();
} else {
$this->execute_command();
$this->set_error_response_on_wp_error();
$this->maybe_set_results_as_null();
}
$this->json_encode_results();
$json_last_error = json_last_error();
if ($json_last_error) {
$this->set_error_response_on_json_encode_error($json_last_error);
}
echo $this->results; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Variable is an array containing escaped data.
die;
}
/**
* Sets nonce property value
*
* @return void
*/
private function set_nonce() {
// phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput -- It's the actual nonce. It does not need sanitizing.
$this->nonce = empty($_POST['nonce']) ? '' : $_POST['nonce'];
}
/**
* Sets subaction property value
*
* @return void
*/
private function set_subaction() {
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce already checked.
$this->subaction = empty($_POST['subaction']) ? '' : sanitize_text_field(wp_unslash($_POST['subaction']));
}
/**
* Sets data property value
*
* @return void
*/
private function set_data() {
// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce already checked.
$this->data = isset($_POST['data']) ? wp_unslash($_POST['data']) : null;
}
/**
* Checks whether it is multisite setup and command is valid multisite command
*
* @return bool
*/
private function is_valid_multisite_command() {
/**
* Filters the commands allowed to the sub site admins. Other commands are only available to network admin. Only used in a multisite context.
*/
$allowed_commands = apply_filters('aios_multisite_allowed_commands', array(
'delete_audit_log',
'delete_locked_ip_record',
'clear_debug_logs',
'unlock_ip',
'blocked_ip_list_unblock_ip',
'lock_ip',
'dismiss_notice',
));
return in_array($this->subaction, $allowed_commands);
}
/**
* Sends the invalid multisite command error response
*
* @return void
*/
private function send_invalid_multisite_command_error_response() {
wp_send_json(array(
'result' => false,
'error_code' => 'update_failed',
'error_message' => __('Options can only be saved by network admin', 'all-in-one-wp-security-and-firewall')
));
}
/**
* Checks if applied ajax command is an invalid command or not
*
* @return bool Returns true if ajax command is an invalid command, false otherwise
*/
private function is_invalid_command() {
return !is_callable(array($this->commands_object, $this->subaction));
}
/**
* Log an error message for invalid ajax command
*
* @return void
*/
private function add_invalid_command_error_log_entry() {
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Part of error reporting.
error_log("AIOS: ajax_handler: no such command (" . $this->subaction . ")");
}
/**
* Set `results` property with error response array for invalid ajax command
*
* @return void
*/
private function set_invalid_command_error_response() {
$this->results = array(
'result' => false,
'error_code' => 'command_not_found',
/* translators: %s: Subaction */
'error_message' => sprintf(__('The command "%s" was not found', 'all-in-one-wp-security-and-firewall'), $this->subaction)
);
}
/**
* Execute the ajax command
*
* @return void
*/
private function execute_command() {
$this->results = call_user_func(array($this->commands_object, $this->subaction), $this->data);
}
/**
* Set `results` property with error message
*
* @return void
*/
private function set_error_response_on_wp_error() {
if (is_wp_error($this->results)) {
$this->results = array(
'result' => false,
'error_code' => $this->results->get_error_code(),
'error_message' => $this->results->get_error_message(),
'error_data' => $this->results->get_error_data(),
);
}
}
/**
* Set `results` property to null, if it is not yet set
*
* @return void
*/
private function maybe_set_results_as_null() {
// if nothing was returned for some reason, set as result null.
if (empty($this->results)) {
$this->results = array(
'result' => null
);
}
}
/**
* Sets `results` property with json encode error
*
* @param int $json_last_error
*
* @return void
*/
private function set_error_response_on_json_encode_error($json_last_error) {
$this->results = array(
'result' => false,
'error_code' => $json_last_error,
'error_message' => 'json_encode error : ' . $json_last_error,
'error_data' => '',
);
$this->results = wp_json_encode($this->results);
}
/**
* Json encode the `results` property value
*
* @return void
*/
private function json_encode_results() {
$this->results = wp_json_encode($this->results);
}
}
endif;