PluginProbe
Patchstack – WordPress & Plugins Security / 2.1.9
Patchstack – WordPress & Plugins Security v2.1.9
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 / activation.php

activation.php in Patchstack – WordPress & Plugins Security 2.1.9, at includes/activation.php

350 lines 12.1 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 to activate and deactivate the plugin.
10 * Additionally, we use it to run migrations.
11 */
12 class P_Activation extends P_Core {
13
14 /**
15 * Add the actions required for the activation.
16 *
17 * @param Patchstack $core
18 * @return void
19 */
20 public function __construct( $core ) {
21 parent::__construct( $core );
22 add_action( 'activated_plugin', array( $this, 'redirect_activation' ), 10, 2 );
23 }
24
25 /**
26 * Redirect the user to our settings page after plugin activation.
27 *
28 * @param string $plugin The plugin that is activated.
29 * @param boolean $network_activation If a network wide activation. (multisite)
30 * @return void
31 */
32 public function redirect_activation( $plugin, $network_activation ) {
33 if ( $plugin == $this->plugin->basename ) {
34
35 // In case of multisite, we want to redirect the user to a different page.
36 if ( $network_activation ) {
37 wp_safe_redirect( network_admin_url( 'admin.php?page=patchstack-multisite-settings&tab=multisite&activated=1' ) );
38 } else {
39 wp_safe_redirect( admin_url( 'admin.php?page=' . $this->plugin->name . '&activated=1' ) );
40 }
41 exit;
42 }
43 }
44
45 /**
46 * Check if the plugin meets requirements and disable it if they are not present.
47 *
48 * @return boolean
49 */
50 public function check_requirements() {
51 if ( $this->meets_requirements() ) {
52 return true;
53 }
54
55 // Add a dashboard notice.
56 add_action( 'all_admin_notices', array( $this, 'requirements_not_met_notice' ) );
57 return false;
58 }
59
60 /**
61 * Check that all plugin requirements are met.
62 *
63 * @return boolean
64 */
65 public function meets_requirements() {
66 // Check to see if we can access the API.
67 $response = wp_remote_request(
68 $this->plugin->api_url,
69 array(
70 'method' => 'GET',
71 'timeout' => 10,
72 'redirection' => 5,
73 )
74 );
75
76 // Check if we can access the API.
77 if ( is_wp_error( $response ) ) {
78 $this->activation_errors[] = 'We were unable to contact our API server. Please contact your host and ask them to make sure that outgoing connections to api.webarxsecurity.com and api.patchstack.com are not blocked.<br />Additional error message to give to your host: ' . $response->get_error_message();
79 return false;
80 }
81
82 // Do checks for required classes / functions or similar.
83 // Add detailed messages to $this->activation_errors array.
84 if ( version_compare( phpversion(), '5.3.0', '<' ) ) {
85 $this->activation_errors[] = 'Please update the PHP version on your host to at least 5.3.0. Ask your host if you do not know what this means.';
86 return false;
87 }
88
89 global $wp_version;
90 if ( version_compare( $wp_version, '4.3.0', '<' ) ) {
91 $this->activation_errors[] = 'Please upgrade your WordPress site to at least 4.3.0.';
92 return false;
93 }
94
95 return true;
96 }
97
98 /**
99 * Adds a notice to the dashboard if the plugin requirements are not met.
100 *
101 * @return void
102 */
103 public function requirements_not_met_notice() {
104 // Deactivate the plugin.
105 deactivate_plugins( $this->plugin->basename );
106
107 // Compile default message.
108 $default_message = __( 'Patchstack could not be activated due to a conflict. See below for information regarding the conflict.<br />', 'patchstack' );
109
110 // Print the errors on the screen.
111 echo wp_kses_post( $default_message );
112 echo wp_kses_post( implode( '<br />', $this->activation_errors ) );
113 }
114
115 /**
116 * Activate the plugin.
117 *
118 * @param Patchstack $core
119 * @return void
120 */
121 public function activate( $core ) {
122 // Bail early if requirements are not met.
123 if ( ! $this->check_requirements() ) {
124 $this->requirements_not_met_notice();
125 exit;
126 }
127
128 // Check if the webarx/webarx.php plugin is present, if so, remove it.
129 if ( is_dir( WP_PLUGIN_DIR . '/webarx' ) ) {
130
131 // Migrate all current options to the new prefix.
132 global $wpdb;
133 $exists = $wpdb->get_var( "SELECT COUNT(*) FROM " . $wpdb->prefix . "options WHERE option_name = 'webarx_api_token'" );
134
135 // Move over the options.
136 if ( !is_null( $exists ) && $exists >= 1 ) {
137 $wpdb->query( 'INSERT IGNORE INTO ' . $wpdb->prefix . "options (option_name, option_value, autoload) SELECT REPLACE(option_name, 'webarx_', 'patchstack_') as option_name, option_value, autoload FROM " . $wpdb->prefix . "options WHERE option_name like 'webarx_%'" );
138 $wpdb->query( 'UPDATE ' . $wpdb->prefix . 'options AS a SET option_value = (SELECT option_value FROM ' . $wpdb->prefix . "options WHERE option_name = REPLACE(a.option_name, 'patchstack_', 'webarx_')) WHERE option_name LIKE 'patchstack_%'" );
139 }
140
141 // Deactivate the plugin.
142 include_once ABSPATH . 'wp-admin/includes/plugin.php';
143 deactivate_plugins( array( 'webarx/webarx.php' ) );
144 update_option( 'patchstack_license_free', '0' );
145 }
146
147 // Make sure any rewrite functionality has been loaded.
148 $this->migrate();
149 add_option( 'patchstack_first_activated', '1' );
150
151 // Activate the license.
152 if ( $this->plugin->client_id != 'PATCHSTACK_CLIENT_ID' && $this->plugin->private_key != 'PATCHSTACK_PRIVATE_KEY' ) {
153 $this->alter_license( $this->plugin->client_id, $this->plugin->private_key, 'activate' );
154 } elseif ( get_option( 'patchstack_clientid', false ) != false && get_option( 'patchstack_secretkey', false ) != false ) {
155 $this->alter_license( get_option( 'patchstack_clientid' ), get_option( 'patchstack_secretkey' ), 'activate' );
156 } else {
157 update_option( 'patchstack_license_free', '1' );
158 }
159
160 // Update firewall status after activating plugin
161 $api = new P_Api( $core );
162 $token = $api->get_access_token();
163 if ( ! empty( $token ) ) {
164 $api->update_firewall_status( array( 'status' => 1 ) );
165 $api->update_url( array( 'plugin_url' => get_option( 'siteurl' ) ) );
166 }
167
168 // Immediately send software data to our server to set firewall as enabled.
169 // Also immediately download the whitelist file and the firewall rules.
170 do_action( 'patchstack_send_software_data' );
171 if ( get_option( 'patchstack_license_free', 0 ) != 1 ) {
172 do_action( 'patchstack_post_firewall_rules' );
173 do_action( 'patchstack_post_dynamic_firewall_rules' );
174 }
175
176 // One time actions should be placed here.
177 $this->plugin->hardening->delete_readme();
178 }
179
180 /**
181 * Used to activate an individual license on multisite/network.
182 *
183 * @param object $site
184 * @param array $license
185 * @return void
186 */
187 public function activate_multisite_license( $site, $license ) {
188 // Build the Patchstack tables on the site.
189 $this->migrate( null, $site->id );
190
191 // Add the options to given site.
192 foreach ( $this->plugin->admin_options->options as $name => $value ) {
193 add_blog_option( $site->id, $name, $value );
194 }
195
196 // Set the client id and secret key.
197 update_blog_option( $site->id, 'patchstack_clientid', $license['id'] );
198 update_blog_option( $site->id, 'patchstack_secretkey', $license['secret'] );
199 $this->plugin->api->blog_id = $site->id;
200
201 // Activate the license and update firewall status after activating the plugin.
202 $token = $this->plugin->api->get_access_token( $license['id'], $license['secret'], true );
203 if ( ! empty( $token ) ) {
204 $this->plugin->api->update_firewall_status( array( 'status' => $this->get_option( 'patchstack_basic_firewall' ) == 1 ) );
205 $this->plugin->api->update_url( array( 'plugin_url' => get_blog_option( $site->id, 'siteurl' ) ) );
206
207 // If we have an access token, tell our API that the firewall is activated
208 // and the current URL of the site.
209 update_blog_option( $site->id, 'patchstack_license_activated', '1' );
210 $this->plugin->api->update_license_status();
211
212 // This will trigger the software synchronization action.
213 wp_remote_get( get_site_url( $site->id ), array( 'sslverify' => false ) );
214 }
215
216 // Make sure to switch back to the current blog id.
217 $this->plugin->api->blog_id = get_current_blog_id();
218 }
219
220 /**
221 * Build the required Patchstack tables.
222 *
223 * @param null|string $ver The version to upgrade to.
224 * @param null|integer $site_id The blog id to perform the upgrades on.
225 * @return void
226 */
227 public function migrate( $ver = null, $site_id = null ) {
228 global $wpdb;
229 require_once ABSPATH . 'wp-admin/includes/upgrade.php';
230 $charset_collate = $wpdb->get_charset_collate();
231 $prefix = $site_id != null ? $wpdb->get_blog_prefix( $site_id ) : $wpdb->prefix;
232
233 // The following conditions will only execute if Patchstack is installed because of an update
234 // and if we need to perform migrations.
235 if ( $ver !== null && file_exists( dirname( __FILE__ ) . '/migrations/v' . str_replace( '.', '', $ver ) . '.php' ) ) {
236 require_once dirname( __FILE__ ) . '/migrations/v' . str_replace( '.', '', $ver ) . '.php';
237 return;
238 }
239
240 // Require the base migration.
241 require_once dirname( __FILE__ ) . '/migrations/base.php';
242 }
243
244 /**
245 * Check if the database version of the plugin is running behind.
246 * If so, run the migrations up until the latest version.
247 *
248 * @return void
249 */
250 public function migrate_check() {
251 // Only perform migrations if we have any to execute.
252 $versions = array('3.0.0');
253 if ( count( $versions ) == 0 ) {
254 return;
255 }
256
257 // Get current database version and run the migrations.
258 $db_version = get_option( 'patchstack_db_version', false );
259 foreach ( $versions as $version ) {
260 if ( version_compare( $db_version, $version, '<' ) ) {
261 $this->migrate( $version );
262 }
263 }
264 }
265
266 /**
267 * Perform cleanup when the plugin is deactivated.
268 *
269 * @return void
270 */
271 public function deactivate() {
272 // Update firewall status after de-activating plugin
273 $api = new P_Api( $this );
274 $token = $api->get_access_token();
275 if ( ! empty( $token ) ) {
276 $api->update_firewall_status( array( 'status' => 0 ) );
277 }
278
279 // Clear all Patchstack scheduled tasks.
280 $tasks = array( 'patchstack_zip_backup', 'patchstack_send_software_data', 'patchstack_send_hacker_logs', 'patchstack_send_visitor_logs', 'patchstack_send_event_logs', 'patchstack_reset_blocked_attacks', 'patchstack_post_firewall_rules', 'patchstack_post_firewall_htaccess_rules', 'patchstack_post_dynamic_firewall_rules', 'patchstack_update_license_status', 'patchstack_update_plugins', 'patchstack_send_ping', 'puc_cron_check_updates-webarx' );
281 foreach ( $tasks as $task ) {
282 wp_clear_scheduled_hook( $task );
283 }
284
285 // Cleanup the .htaccess file.
286 $this->plugin->htaccess->cleanup_htaccess_file();
287 }
288
289 /**
290 * Activate or deactivate a license on the current site.
291 *
292 * @param integer $id
293 * @param string $secret
294 * @param string $action
295 * @return array
296 */
297 public function alter_license( $id, $secret, $action ) {
298 // Store current keys in tmp variable so in case it fails, we can set it back.
299 $tmp_id = get_option( 'patchstack_clientid' );
300 $tmp_key = get_option( 'patchstack_secretkey' );
301 update_option( 'patchstack_clientid', $id );
302 update_option( 'patchstack_secretkey', $secret );
303
304 // Activate the license.
305 if ( $action == 'activate' ) {
306 $api_result = $this->plugin->api->get_access_token( $id, $secret, true );
307
308 // Valid result?
309 if ( ! $api_result ) {
310 update_option( 'patchstack_clientid', $tmp_id );
311 update_option( 'patchstack_secretkey', $tmp_key );
312 return array(
313 'result' => 'error',
314 'message' => 'Cannot activate license!',
315 );
316 }
317
318 // If we have an access token, tell our API that the firewall is activated
319 // and the current URL of the site.
320 update_option( 'patchstack_license_activated', '1' );
321 $this->plugin->api->update_license_status();
322 $token = $this->plugin->api->get_access_token();
323 if ( ! empty( $token ) ) {
324 do_action( 'patchstack_send_software_data' );
325 if ( get_option( 'patchstack_license_free', 0 ) != 1 ) {
326 do_action( 'patchstack_post_firewall_rules' );
327 do_action( 'patchstack_post_dynamic_firewall_rules' );
328 }
329
330 $this->plugin->api->update_firewall_status( array( 'status' => $this->get_option( 'patchstack_basic_firewall' ) == 1 ) );
331 $this->plugin->api->update_url( array( 'plugin_url' => get_option( 'siteurl' ) ) );
332 }
333 return array(
334 'result' => 'success',
335 'message' => 'License activated!',
336 );
337 }
338
339 // Deactivate the license.
340 if ( $action == 'deactivate' ) {
341 update_option( 'patchstack_api_token', '' );
342 update_option( 'patchstack_license_activated', '0' );
343 return array(
344 'result' => 'success',
345 'message' => 'License deactivated!',
346 );
347 }
348 }
349 }
350