PluginProbe
Patchstack – WordPress & Plugins Security / 2.2.11
Patchstack – WordPress & Plugins Security v2.2.11
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
← All changes | patchstack.php +65 -25 2.1.142.2.11 View file →
@@ -1,10 +1,11 @@
1 1 <?php
2 2 /**
3 3 * Plugin Name: Patchstack Security
4 - * Plugin URI: https://patchstack.com
4 + * Plugin URI: https://patchstack.com/?utm_medium=wp&utm_source=dashboard&utm_campaign=patchstack%20plugin
5 + * Author URI: https://patchstack.com/?utm_medium=wp&utm_source=dashboard&utm_campaign=patchstack%20plugin
5 6 * Description: Patchstack identifies security vulnerabilities in WordPress plugins, themes, and core.
6 - * Version: 2.1.14
7 + * Version: 2.2.11
7 8 * Author: Patchstack
8 9 * License: GPLv3
9 10 * Text Domain: patchstack
10 11 * Domain Path: /languages
@@ -32,9 +33,9 @@
32 33
33 34 // Set up our filename.
34 35 $file_name = strtolower( str_replace( '_', '-', substr( $class_name, strlen( 'P_' ) ) ) );
35 36 $dir = trailingslashit( dirname( __FILE__ ) ) . 'includes/';
36 - $target = array( $dir . $file_name . '.php', $dir . 'admin/' . str_replace( 'admin-', '', $file_name ) . '.php' );
37 + $target = [ $dir . $file_name . '.php', $dir . 'admin/' . str_replace( 'admin-', '', $file_name ) . '.php' ];
37 38
38 39 // Attempt each target and load if it exists.
39 40 foreach ( $target as $file ) {
40 41 if ( file_exists( $file ) ) {
@@ -57,9 +58,9 @@
57 58 * The plugin version.
58 59 *
59 60 * @var string
60 61 */
61 - const VERSION = '2.1.14';
62 + const VERSION = '2.2.11';
62 63
63 64 /**
64 65 * API URL of Patchstack to communicate with.
65 66 *
@@ -113,9 +114,9 @@
113 114 * Detailed activation error messages.
114 115 *
115 116 * @var array
116 117 */
117 - protected $activation_errors = array();
118 + protected $activation_errors = [];
118 119
119 120 /**
120 121 * Singleton instance of plugin.
121 122 *
@@ -142,9 +143,8 @@
142 143 protected $hide_login;
143 144 protected $listener;
144 145 protected $event_log;
145 146 protected $multisite;
146 - protected $notice;
147 147 protected $admin_ajax;
148 148 protected $admin_general;
149 149 protected $admin_menu;
150 150 protected $admin_options;
@@ -169,8 +169,13 @@
169 169 $this->basename = plugin_basename( __FILE__ );
170 170 $this->url = plugin_dir_url( __FILE__ );
171 171 $names = explode( '/', $this->basename );
172 172 $this->name = $names[0];
173 +
174 + // Define WP_CLI command.
175 + if ( defined( 'WP_CLI' ) && WP_CLI && method_exists('\WP_CLI', 'add_command')) {
176 + \WP_CLI::add_command( 'patchstack activate', [ $this, 'cli_activate' ] );
177 + }
173 178 }
174 179
175 180 /**
176 181 * Call the constructor of all the Patchstack related classes.
@@ -178,9 +183,9 @@
178 183 * @return void
179 184 */
180 185 public function plugin_classes() {
181 186 // Define the array of the classes.
182 - foreach ( array(
187 + foreach ( [
183 188 'admin_options' => 'P_Admin_Options',
184 189 'cron' => 'P_Cron',
185 190 'api' => 'P_Api',
186 191 'login' => 'P_Login',
@@ -190,20 +195,20 @@
190 195 'hacker_log' => 'P_Hacker_Log',
191 196 'upload' => 'P_Upload',
192 197 'rules' => 'P_Rules',
193 198 'hide_login' => 'P_Hide_Login',
194 - 'listener' => 'P_Listener',
195 199 'event_log' => 'P_Event_Log',
196 200 'activation' => 'P_Activation',
201 + 'listener' => 'P_Listener',
197 202 'multisite' => 'P_Multisite',
198 - 'notice' => 'P_Cookie_Notice',
199 203 'admin_ajax' => 'P_Admin_Ajax',
200 204 'admin_general' => 'P_Admin_General',
201 205 'admin_menu' => 'P_Admin_Menu',
202 - ) as $var => $class ) {
206 + ] as $var => $class ) {
203 207 $this->$var = new $class( $this );
204 208 }
205 209
210 + // Load firewall base functionality.
206 211 $this->firewall_base = new P_Firewall( true, $this, true );
207 212 }
208 213
209 214 /**
@@ -216,28 +221,63 @@
216 221 $this->activation->activate( $this );
217 222 }
218 223
219 224 /**
220 - * Deactivate the plugin.
225 + * Connects the Patchstack plugin to the API with the license id and secret key.
221 226 *
222 - * @return void
227 + * Returns an error if the connection was not successful.
228 + *
229 + * ## OPTIONS
230 + *
231 + * [<id>]
232 + * : The API client id.
233 + *
234 + * [<secret>]
235 + * : The API secret key.
236 + *
237 + * <secret-id>
238 + * : The API client id and secret key merged together, found in the App. E.g. 2b072e8b60402e30d481df351fc08183906254e0-123456
239 + *
240 + * ## EXAMPLES
241 + *
242 + * $ wp patchstack activate 123456 2b072e8b60402e30d481df351fc08183906254e0
243 + * Success: The Patchstack plugin has been successfully connected.
244 + *
245 + * or
246 + *
247 + * $ wp patchstack activate 2b072e8b60402e30d481df351fc08183906254e0-123456
248 + * Success: The Patchstack plugin has been successfully connected.
223 249 */
224 - public function deactivate() {
225 - $this->plugin_classes();
226 - $this->activation->deactivate();
250 + public function cli_activate( $args ) {
251 + // Handle both ways to activate the plugin.
252 + if ( count( $args ) === 1 && strpos( $args[0], '-' ) !== false ) {
253 + list( $secret, $id ) = explode( '-', $args[0] );
254 + } else {
255 + $id = isset( $args[0] ) ? trim( $args[0] ) : '';
256 + $secret = isset( $args[1] ) ? trim( $args[1] ) : '';
257 + }
258 +
259 + $result = $this->activation->alter_license( $id, $secret, 'activate' );
260 + if ( $result['result'] == 'error' ) {
261 + \WP_CLI::error( 'The Patchstack plugin could not be connected. Make sure the id and secret key are valid and that api.patchstack.com is not blocked.' );
262 + return;
263 + }
264 +
265 + \WP_CLI::success( 'The Patchstack plugin has been successfully connected.' );
227 266 }
228 267
229 268 /**
230 - * Boot Patchstack and its classes.
269 + * Deactivate the plugin.
231 270 *
232 271 * @return void
233 272 */
234 - public function hooks() {
235 - add_action( 'init', array( $this, 'init' ), ~PHP_INT_MAX );
273 + public function deactivate() {
274 + $this->plugin_classes();
275 + $this->activation->deactivate();
236 276 }
237 277
238 278 /**
239 - * Boot Patchstack
279 + * Boot Patchstack.
240 280 *
241 281 * @return void
242 282 */
243 283 public function init() {
@@ -254,9 +294,9 @@
254 294 if ( get_option( 'patchstack_api_token', '' ) == '' && get_option( 'patchstack_license_expiry', '' ) == '' ) {
255 295 $this->api->update_license_status();
256 296 }
257 297
258 - // Determine if the license is activated and not expired.
298 + // Run firewall if not disabled and license activated.
259 299 if ( get_option( 'patchstack_license_activated', 0 ) == 1 && get_option( 'patchstack_basic_firewall', 0 ) == 1 && get_option( 'patchstack_license_free', 0 ) == 0 ) {
260 300 $this->firewall = new P_Firewall( true, $this );
261 301 }
262 302 }
@@ -311,9 +351,9 @@
311 351 * @return void
312 352 */
313 353 function patchstack_uninstall() {
314 354 // Delete most of the Patchstack options.
315 - $options = array( 'patchstack_eventlog_lastid', 'patchstack_api_token', 'patchstack_dashboardlock', 'patchstack_pluginedit', 'patchstack_move_logs', 'patchstack_userenum', 'patchstack_basicscanblock', 'patchstack_hidewpcontent', 'patchstack_hidewpversionk', 'patchstack_prevent_default_file_access', 'patchstack_basic_firewall', 'patchstack_known_blacklist', 'patchstack_block_debug_log_access', 'patchstack_block_fake_bots', 'patchstack_index_views', 'patchstack_proxy_comment_posting', 'patchstack_bad_query_strings', 'patchstack_advanced_character_string_filter', 'patchstack_advanced_blacklist_firewall', 'patchstack_forbid_rfi', 'patchstack_image_hotlinking', 'patchstack_add_security_headers', 'patchstack_firewall_log_lastid', 'patchstack_user_log_lastid', 'patchstack_captcha_public_key', 'patchstack_captcha_private_key', 'patchstack_scan_interval', 'patchstack_scan_day', 'patchstack_scan_time', 'patchstack_hackers_log', 'patchstack_users_log', 'patchstack_visitors_log', 'external_updates-webarx', 'patchstack_wp_stats', 'patchstack_captcha_login_form', 'patchstack_license_activated', 'patchstack_license_expiry', 'patchstack_software_data_hash', 'patchstack_mv_wp_login', 'patchstack_rename_wp_login', 'patchstack_googledrive_backup_is_running', 'patchstack_googledrive_upload_state', 'patchstack_googledrive_access_token', 'patchstack_googledrive_refresh_token', 'patchstack_cron_offset', 'patchstack_htaccess_rules_hash' );
355 + $options = [ 'patchstack_eventlog_lastid', 'patchstack_api_token', 'patchstack_dashboardlock', 'patchstack_pluginedit', 'patchstack_move_logs', 'patchstack_userenum', 'patchstack_basicscanblock', 'patchstack_hidewpcontent', 'patchstack_hidewpversionk', 'patchstack_prevent_default_file_access', 'patchstack_basic_firewall', 'patchstack_known_blacklist', 'patchstack_block_debug_log_access', 'patchstack_block_fake_bots', 'patchstack_index_views', 'patchstack_proxy_comment_posting', 'patchstack_bad_query_strings', 'patchstack_advanced_character_string_filter', 'patchstack_advanced_blacklist_firewall', 'patchstack_forbid_rfi', 'patchstack_image_hotlinking', 'patchstack_add_security_headers', 'patchstack_firewall_log_lastid', 'patchstack_user_log_lastid', 'patchstack_captcha_public_key', 'patchstack_captcha_private_key', 'patchstack_scan_interval', 'patchstack_scan_day', 'patchstack_scan_time', 'patchstack_hackers_log', 'patchstack_users_log', 'patchstack_visitors_log', 'external_updates-webarx', 'patchstack_wp_stats', 'patchstack_captcha_login_form', 'patchstack_license_activated', 'patchstack_license_expiry', 'patchstack_software_data_hash', 'patchstack_mv_wp_login', 'patchstack_rename_wp_login', 'patchstack_googledrive_backup_is_running', 'patchstack_googledrive_upload_state', 'patchstack_googledrive_access_token', 'patchstack_googledrive_refresh_token', 'patchstack_cron_offset', 'patchstack_htaccess_rules_hash' ];
316 356 foreach ( $options as $option ) {
317 357 delete_option( $option );
318 358
319 359 if ( is_multisite() ) {
@@ -322,9 +362,9 @@
322 362 }
323 363
324 364 // Drop all Patchstack tables.
325 365 global $wpdb;
326 - $tables = array( 'patchstack_user_log', 'patchstack_visitor_log', 'patchstack_firewall_log', 'patchstack_file_hashes', 'patchstack_logic', 'patchstack_ip', 'patchstack_event_log' );
366 + $tables = [ 'patchstack_user_log', 'patchstack_visitor_log', 'patchstack_firewall_log', 'patchstack_file_hashes', 'patchstack_logic', 'patchstack_ip', 'patchstack_event_log' ];
327 367 foreach ( $tables as $table ) {
328 368 $wpdb->query( 'DROP TABLE IF EXISTS ' . $wpdb->prefix . $table );
329 369 }
330 370 }
@@ -341,10 +381,10 @@
341 381 }
342 382 }
343 383
344 384 // Kick it off.
345 -add_action( 'plugins_loaded', array( patchstack(), 'hooks' ) );
385 +add_action( 'plugins_loaded', [ patchstack(), 'init' ] );
346 386
347 387 // Activation and deactivation hooks.
348 -register_activation_hook( __FILE__, array( patchstack(), 'activate' ) );
349 -register_deactivation_hook( __FILE__, array( patchstack(), 'deactivate' ) );
388 +register_activation_hook( __FILE__, [ patchstack(), 'activate' ] );
389 +register_deactivation_hook( __FILE__, [ patchstack(), 'deactivate' ] );
350 390 register_uninstall_hook( __FILE__, 'patchstack_uninstall' );