PluginProbe
Patchstack – WordPress & Plugins Security / 2.2.2
Patchstack – WordPress & Plugins Security v2.2.2
2.3.7 trunk 2.1.0 2.1.1 2.1.10 2.1.11 2.1.12 2.1.13 2.1.14 2.1.15 2.1.16 2.1.17 2.1.18 2.1.19 2.1.2 2.1.20 2.1.21 2.1.22 2.1.23 2.1.24 2.1.25 2.1.3 2.1.4 2.1.5 2.1.6 All 49 releases
patchstack / includes / admin / ajax.php

ajax.php in Patchstack – WordPress & Plugins Security 2.2.2, at includes/admin/ajax.php

198 lines 6.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 // Do not allow the file to be called directly.
4 if ( ! defined( 'ABSPATH' ) ) {
5 exit;
6 }
7
8 /**
9 * This class is used for any admin AJAX interactions.
10 */
11 class P_Admin_Ajax extends P_Core {
12
13 /**
14 * Add the actions required for AJAX interactions.
15 *
16 * @param Patchstack $core
17 * @return void
18 */
19 public function __construct( $core ) {
20 parent::__construct( $core );
21 if ( isset( $_POST['PatchstackNonce'] ) && current_user_can( 'manage_options' ) && wp_verify_nonce( $_POST['PatchstackNonce'], 'patchstack-nonce' ) ) {
22 // Log tables actions.
23 add_action( 'wp_ajax_patchstack_users_log_table', [ $this, 'users_log_table' ] );
24 add_action( 'wp_ajax_patchstack_firewall_log_table', [ $this, 'firewall_log_table' ] );
25
26 // License related actions.
27 add_action( 'wp_ajax_patchstack_activate_license', [ $this, 'activate_license' ] );
28
29 // Hide login related actions.
30 add_action( 'wp_ajax_patchstack_send_new_url_email', [ $this, 'send_new_url_email' ] );
31 }
32 }
33
34 /**
35 * Firewall logs pagination.
36 *
37 * @return array
38 */
39 public function firewall_log_table() {
40 if ( ! isset( $_POST['start'], $_POST['length'] ) || !ctype_digit( $_POST['start'] ) || !ctype_digit( $_POST['length'] ) ) {
41 exit;
42 }
43
44 // Pull all entries, given parameters.
45 global $wpdb;
46 $entries = $wpdb->get_results(
47 $wpdb->prepare(
48 "SELECT a.id, a.ip, a.flag, a.method, a.log_date, case when a.referer IS NULL or a.referer = '' then a.request_uri else a.referer end as referer, a.fid, b.description
49 FROM " . $wpdb->prefix . 'patchstack_firewall_log AS a
50 LEFT JOIN ' . $wpdb->prefix . 'patchstack_logic AS b ON b.id = a.fid
51 ORDER BY a.id DESC
52 LIMIT %d, %d
53 ',
54 [ wp_filter_nohtml_kses( $_POST['start'] ), wp_filter_nohtml_kses( $_POST['length'] ) ]
55 )
56 );
57
58 // Get total amount of rows.
59 $count = $wpdb->get_var( 'SELECT COUNT(id) FROM ' . $wpdb->prefix . 'patchstack_firewall_log' );
60 $firewall_rules = json_decode( get_option( 'patchstack_firewall_rules', '' ), true );
61 $firewall_rules_v3 = json_decode( get_option( 'patchstack_firewall_rules_v3', [] ), true );
62 $firewall_rules = array_merge($firewall_rules, $firewall_rules_v3);
63
64 // Modify data if necessary.
65 $list = [];
66 foreach ( $entries as $entry ) {
67 foreach ( $entry as $key => $value ) {
68 if ( ! in_array( $key, [ 'referer' ] ) ) {
69 $entry->$key = sanitize_textarea_field( $value );
70 }
71 }
72
73 // Attempt to find the block reason.
74 $reason = $wpdb->get_var( $wpdb->prepare( 'SELECT cname FROM ' . $wpdb->prefix . 'patchstack_logic WHERE id = %d LIMIT 1', [ $entry->fid ] ) );
75 if ( $reason ) {
76 $entry->fid = $reason;
77 } elseif ( $firewall_rules != '' ) {
78 foreach ( $firewall_rules as $rule ) {
79 if ( isset( $rule['title'], $rule['cat'] ) && '55' . $rule['id'] == $entry->fid ) {
80 $entry->fid = $rule['cat'];
81 $entry->description = $rule['title'];
82 }
83 }
84 } else {
85 $entry->fid = 'Unknown';
86 }
87
88 $list[] = $entry;
89 }
90
91 // Return output.
92 wp_send_json(
93 [
94 'data' => $list,
95 'recordsFiltered' => $count,
96 'recordsTotal' => $count
97 ]
98 );
99 }
100
101 /**
102 * Activity logs pagination.
103 *
104 * @return void
105 */
106 public function users_log_table() {
107 if ( ! isset( $_POST['start'], $_POST['length'] ) || !ctype_digit( $_POST['start'] ) || !ctype_digit( $_POST['length'] ) ) {
108 exit;
109 }
110
111 // Determine if searching?
112 global $wpdb;
113 $searching = false;
114 $likes = [];
115 if ( isset( $_POST['search'], $_POST['search']['value'] ) && $_POST['search']['value'] != '' ) {
116 $val = wp_filter_nohtml_kses( $_POST['search']['value'] );
117 $searching = true;
118 $columns = [ 'author', 'ip', 'object', 'object_name', 'action' ];
119 $search = 'WHERE 1=2 ';
120 foreach ( $columns as $column ) {
121 array_push( $likes, '%' . $wpdb->esc_like( $val ) . '%' );
122 $search .= 'OR ' . $column . ' LIKE %s';
123 }
124 }
125
126 $logs = $wpdb->get_results(
127 $wpdb->prepare(
128 'SELECT *
129 FROM ' . $wpdb->prefix . 'patchstack_event_log ' . ( $searching ? $search : '' ) . '
130 ORDER BY id DESC
131 LIMIT %d, %d
132 ',
133 array_merge( $likes, [ wp_filter_nohtml_kses( $_POST['start'] ), wp_filter_nohtml_kses( $_POST['length'] ) ] )
134 )
135 );
136
137 $count = $wpdb->get_var( $wpdb->prepare( 'SELECT COUNT(id) FROM ' . $wpdb->prefix . 'patchstack_event_log ' . ( $searching ? $search : '' ), $likes ) );
138
139 // Modify data if necessary.
140 $list = [];
141 foreach ( $logs as $log ) {
142 $list[] = $log;
143 }
144
145 // Return output.
146 wp_send_json(
147 [
148 'data' => $list,
149 'recordsFiltered' => $count,
150 'recordsTotal' => $count
151 ]
152 );
153 }
154
155 /**
156 * Test and activate a new license.
157 *
158 * @return void
159 */
160 public function activate_license() {
161 if ( ! isset( $_POST['key'] ) || strpos( $_POST['key'], '-' ) === false) {
162 wp_send_json(
163 [
164 'result' => 'error',
165 'error_message' => 'An invalid API key was provided.'
166 ]
167 );
168 }
169
170 // Since we have the keys combined into one now, split them up here.
171 $split = explode('-', $_POST['key']);
172 $secretkey = $split[0];
173 $clientid = $split[1];
174
175 // Test the new keys.
176 update_option( 'patchstack_api_token', '' );
177 $results = $this->plugin->activation->alter_license( wp_filter_nohtml_kses( $clientid ), wp_filter_nohtml_kses( $secretkey ), 'activate' );
178 if ( $results ) {
179 $response = $this->plugin->api->update_license_status();
180 $results['response'] = $response;
181 wp_send_json( $results );
182 }
183 }
184
185 /**
186 * Send an email to the current logged in user that contains the new admin page URL.
187 *
188 * @return void
189 */
190 public function send_new_url_email() {
191 global $current_user;
192 $subject = __( 'New Login URL', 'patchstack' );
193 $message = '<br /><br />Your login page is now here: <strong> <a href="' . get_site_url() . '/' . get_site_option( 'patchstack_rename_wp_login' ) . '">' . get_site_url() . '/' . get_site_option( 'patchstack_rename_wp_login' ) . '</strong></a>';
194 $email_sent = wp_mail( $current_user->user_email, $subject, $message );
195 die( $email_sent ? 'success' : 'fail' );
196 }
197 }
198