PluginProbe ʕ •ᴥ•ʔ
Admin and Site Enhancements (ASE) / 6.5.1
Admin and Site Enhancements (ASE) v6.5.1
9.1.0 9.0.2 9.0.1 9.0.0 8.9.2 8.9.1 8.9.0 8.8.8 8.8.7 8.8.6 8.8.5 8.8.4 8.8.3 8.8.2 8.8.1 8.8.0 8.7.3 8.7.2 8.7.1 8.2.1 8.2.2 8.2.3 8.3.0 8.3.1 8.3.2 8.4.0 8.4.1 8.4.2 8.5.0 8.5.1 8.5.2 8.6.0 8.6.1 8.6.2 8.7.0 5.0.1 5.0.2 5.0.2.1 5.0.2.2 5.0.2.3 5.0.2.4 5.1.0 5.2.0 5.2.1 5.2.10 5.2.11 5.2.2 5.2.3 5.2.4 5.2.5 5.2.6 5.2.7 5.2.8 5.2.9 5.3.0 5.3.1 5.3.2 5.4.0 5.4.1 5.5.0 5.5.1 5.5.2 5.6.0 5.6.1 5.6.2 5.7.0 5.7.1 5.8.0 5.8.1 6.0.0 6.0.3 6.0.4 6.0.5 6.0.5.1 6.0.6 6.0.7 6.0.8.1 6.1.0 6.1.3 6.2.0 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.2.6 6.2.7 6.3.0 6.3.1 6.3.2 6.4.0 6.5.0 6.5.1 6.6.0 6.7.0 6.8.0 6.8.2 6.8.3 6.9.0 6.9.1 6.9.10 6.9.11 6.9.12 6.9.13.1 6.9.13.2 6.9.2 6.9.3 6.9.4 6.9.5 6.9.6 6.9.7 6.9.8 6.9.9 7.0.0 7.0.2 7.0.2.1 7.0.2.2 7.0.2.3 7.0.3 7.1.0 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2.0 7.2.1 7.3.0 7.3.1 7.3.2 7.3.3 7.4.0 7.4.2 7.4.4 7.4.5 7.4.6 7.4.7 7.4.8 7.5.0 7.5.1 7.5.2 7.5.3 7.5.4 7.6.0 7.6.1 7.6.1.1 7.6.10 7.6.11 7.6.2 7.6.3 7.6.4 7.6.5 7.6.6 7.6.7 7.6.7.1 7.6.8 7.6.9 7.7.0 7.8.0 7.8.1 7.8.10 7.8.11 7.8.12 7.8.13 7.8.14 7.8.15 7.8.16 7.8.17 7.8.18 7.8.2 7.8.3 7.8.4 7.8.5 7.8.5.1 7.8.6 7.8.7 7.8.8 7.8.9 7.9.0 7.9.1 7.9.10 7.9.11 7.9.2 7.9.3 7.9.4 7.9.5 7.9.6 7.9.7 7.9.8 7.9.9 8.0.0 8.0.1 8.0.2 8.0.3 8.0.4 8.0.5 8.0.6 8.0.7 8.0.8 8.1.0 8.1.1 8.1.2 8.1.3 8.1.4 8.2.0 trunk 1.0.0 1.1.0 1.2.0 1.3.0 1.4.0 1.5.0 1.6.0 1.7.0 1.8.0 1.9.0 2.0.0 2.1.0 2.2.0 2.3.0 2.4.0 2.5.0 2.6.0 2.7.0 2.8.0 2.8.1 2.8.2 2.8.3 2.9.0 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.1.0 3.2.0 3.3.0 3.4.0 3.5.0 3.6.1 3.7.0 3.8.0 3.9.0 3.9.1 3.9.2 4.0.0 4.0.1 4.1.0 4.2.0 4.2.1 4.2.2 4.3.0 4.3.1 4.4.0 4.5.0 4.6.0 4.7.0 4.7.1 4.7.2 4.7.3 4.7.4 4.8.0 4.8.1 4.8.2 4.8.3 4.9.0 4.9.1 4.9.2 4.9.3 5.0.0
admin-site-enhancements / classes / class-security.php
admin-site-enhancements / classes Last commit date
class-activation.php 2 years ago class-admin-interface.php 2 years ago class-common-methods.php 2 years ago class-content-management.php 2 years ago class-custom-code.php 2 years ago class-deactivation.php 2 years ago class-disable-components.php 2 years ago class-login-logout.php 2 years ago class-optimizations.php 2 years ago class-security.php 2 years ago class-settings-fields-render.php 2 years ago class-settings-sanitization.php 2 years ago class-settings-sections-fields.php 2 years ago class-utilities.php 2 years ago
class-security.php
574 lines
1 <?php
2
3 namespace ASENHA\Classes;
4
5 use WP_Error ;
6 /**
7 * Class related to Security features
8 *
9 * @since 1.4.0
10 */
11 class Security
12 {
13 /**
14 * Maybe allow login if not locked out. Should return WP_Error object if not allowed to login.
15 *
16 * @since 2.5.0
17 */
18 public function maybe_allow_login( $user_or_error, $username, $password )
19 {
20 global $wpdb, $asenha_limit_login ;
21 $table_name = $wpdb->prefix . 'asenha_failed_logins';
22 // Maybe create table if it does not exist yet, e.g. upgraded from previous version of plugin, so, no activation methods are fired
23 $query = $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $table_name ) );
24
25 if ( $wpdb->get_var( $query ) === $table_name ) {
26 // Table already exists, do nothing.
27 } else {
28 $activation = new Activation();
29 $activation->create_failed_logins_log_table();
30 }
31
32 // Get values from options needed to do various checks
33 $options = get_option( ASENHA_SLUG_U, array() );
34 $login_fails_allowed = $options['login_fails_allowed'];
35 $login_lockout_maxcount = $options['login_lockout_maxcount'];
36 $ip_address_whitelist_raw = ( isset( $options['limit_login_attempts_ip_whitelist'] ) ? explode( PHP_EOL, $options['limit_login_attempts_ip_whitelist'] ) : array() );
37 $ip_address_whitelist = array();
38 if ( !empty($ip_address_whitelist_raw) ) {
39 foreach ( $ip_address_whitelist_raw as $ip_address ) {
40 $ip_address_whitelist[] = trim( $ip_address );
41 }
42 }
43 $change_login_url = $options['change_login_url'];
44 $custom_login_slug = $options['custom_login_slug'];
45 // Instantiate object to access common methods
46 $common_methods = new Common_Methods();
47 // Get user/visitor IP address
48 $ip_address = $common_methods->get_user_ip_address();
49
50 if ( !in_array( $ip_address, $ip_address_whitelist ) ) {
51 // IP is not whitelisted
52 // Check if IP address has failed login attempts recorded in the DB log
53 $sql = $wpdb->prepare( "SELECT * FROM `" . $table_name . "` Where `ip_address` = %s", $ip_address );
54 $result = $wpdb->get_results( $sql, ARRAY_A );
55 $result_count = count( $result );
56
57 if ( $result_count > 0 ) {
58 // IP address has been recorded in the database.
59 // Custom Login URL is enabled
60
61 if ( array_key_exists( 'change_login_url', $options ) && $options['change_login_url'] ) {
62 $fail_count = $result[0]['fail_count'];
63 } else {
64 $fail_count = $result[0]['fail_count'] + 1;
65 }
66
67 $lockout_count = $result[0]['lockout_count'];
68 $last_fail_on = $result[0]['unixtime'];
69 } else {
70 $fail_count = 0;
71 $lockout_count = 0;
72 $last_fail_on = '';
73 }
74
75 } else {
76 // IP is whitelisted
77 $result = array();
78 $fail_count = 0;
79 $lockout_count = 0;
80 $last_fail_on = '';
81 }
82
83 // Initialize the global variable
84 $asenha_limit_login = array(
85 'ip_address' => $ip_address,
86 'request_uri' => sanitize_text_field( $_SERVER['REQUEST_URI'] ),
87 'ip_address_log' => $result,
88 'maybe_lockout' => false,
89 'extended_lockout' => false,
90 'within_lockout_period' => false,
91 'lockout_period' => 0,
92 'lockout_period_remaining' => 0,
93 'login_fails_allowed' => $login_fails_allowed,
94 'login_lockout_maxcount' => $login_lockout_maxcount,
95 'default_lockout_period' => 60 * 15,
96 'extended_lockout_period' => 24 * 60 * 60,
97 'change_login_url' => $change_login_url,
98 'custom_login_slug' => $custom_login_slug,
99 );
100
101 if ( !in_array( $ip_address, $ip_address_whitelist ) ) {
102 // IP is not whitelisted
103
104 if ( $result_count > 0 ) {
105 // IP address has been recorded in the database.
106 // Failed attempts have been recorded and fulfills lockout condition
107
108 if ( !empty($fail_count) && $fail_count % $login_fails_allowed == 0 ) {
109 $asenha_limit_login['maybe_lockout'] = true;
110 // Has reached max / gone beyond number of lockouts allowed?
111
112 if ( $lockout_count >= $login_lockout_maxcount ) {
113 $asenha_limit_login['extended_lockout'] = true;
114 $lockout_period = $asenha_limit_login['extended_lockout_period'];
115 } else {
116 $asenha_limit_login['extended_lockout'] = false;
117 $lockout_period = $asenha_limit_login['default_lockout_period'];
118 }
119
120 $asenha_limit_login['lockout_period'] = $lockout_period;
121 // User/visitor is still within the lockout period
122
123 if ( time() - $last_fail_on <= $asenha_limit_login['lockout_period'] ) {
124 $asenha_limit_login['within_lockout_period'] = true;
125 $asenha_limit_login['lockout_period_remaining'] = $asenha_limit_login['lockout_period'] - (time() - $last_fail_on);
126
127 if ( $asenha_limit_login['lockout_period_remaining'] <= 60 ) {
128 // Get remaining lockout period in minutes and seconds
129 $lockout_period_remaining = $asenha_limit_login['lockout_period_remaining'] . ' seconds';
130 } elseif ( $asenha_limit_login['lockout_period_remaining'] <= 60 * 60 ) {
131 // Get remaining lockout period in minutes and seconds
132 $lockout_period_remaining = $common_methods->seconds_to_period( $asenha_limit_login['lockout_period_remaining'], 'to-minutes-seconds' );
133 } elseif ( $asenha_limit_login['lockout_period_remaining'] > 60 * 60 && $asenha_limit_login['lockout_period_remaining'] <= 24 * 60 * 60 ) {
134 // Get remaining lockout period in minutes and seconds
135 $lockout_period_remaining = $common_methods->seconds_to_period( $asenha_limit_login['lockout_period_remaining'], 'to-hours-minutes-seconds' );
136 } elseif ( $asenha_limit_login['lockout_period_remaining'] > 24 * 60 * 60 ) {
137 // Get remaining lockout period in minutes and seconds
138 $lockout_period_remaining = $common_methods->seconds_to_period( $asenha_limit_login['lockout_period_remaining'], 'to-days-hours-minutes-seconds' );
139 }
140
141 $error = new WP_Error( 'ip_address_blocked', '<b>WARNING:</b> You\'ve been locked out. You can login again in ' . $lockout_period_remaining . '.' );
142 return $error;
143 } else {
144 // User/visitor is no longer within the lockout period
145 $asenha_limit_login['within_lockout_period'] = false;
146
147 if ( $lockout_count == $login_lockout_maxcount ) {
148 // Remove the DB log entry for the current IP address. i.e. release from extended lockout
149 $where = array(
150 'ip_address' => $ip_address,
151 );
152 $where_format = array( '%s' );
153 // Delete existing data in the database
154 $wpdb->delete( $table_name, $where, $where_format );
155 }
156
157 return $user_or_error;
158 }
159
160 } else {
161 $asenha_limit_login['maybe_lockout'] = false;
162 return $user_or_error;
163 }
164
165 } else {
166 // IP address has not been recorded in the database.
167 return $user_or_error;
168 }
169
170 } else {
171 // IP is whitelisted
172 return $user_or_error;
173 }
174
175 }
176
177 /**
178 * Disable login form inputs via CSS
179 *
180 * @since 2.5.0
181 */
182 public function maybe_hide_login_form()
183 {
184 global $asenha_limit_login ;
185
186 if ( isset( $asenha_limit_login['within_lockout_period'] ) && $asenha_limit_login['within_lockout_period'] ) {
187 // Hide logo, login form and the links below it
188 ?>
189 <style type="text/css">
190
191 body.login {
192 background:#f6d6d7;
193 }
194
195 #login h1,
196 #loginform,
197 #login #nav,
198 #backtoblog,
199 .language-switcher {
200 display: none;
201 }
202
203 @media screen and (max-height: 550px) {
204
205 #login {
206 padding: 80px 0 20px !important;
207 }
208
209 }
210
211 </style>
212 <?php
213 }
214
215 }
216
217 /**
218 * Log failed login attempts
219 *
220 * @since 2.5.0
221 */
222 public function log_failed_login( $username )
223 {
224 global $wpdb, $asenha_limit_login ;
225 $table_name = $wpdb->prefix . 'asenha_failed_logins';
226 // Check if the IP address has been used in a failed login attempt before, i.e. has it been recorded in the database?
227 $sql = $wpdb->prepare( "SELECT * FROM `" . $table_name . "` WHERE `ip_address` = %s", $asenha_limit_login['ip_address'] );
228 $result = $wpdb->get_results( $sql, ARRAY_A );
229 $result_count = count( $result );
230 // Update logged info for the IP address in the global variable
231 $asenha_limit_login['ip_address_log'] = $result;
232
233 if ( $result_count == 0 ) {
234 // IP address has not been recorded in the database.
235 $new_fail_count = 1;
236 $new_lockout_count = 0;
237 } else {
238 // IP address has been recorded in the database.
239 $new_fail_count = $result[0]['fail_count'] + 1;
240 $new_lockout_count = floor( ($result[0]['fail_count'] + 1) / $asenha_limit_login['login_fails_allowed'] );
241 }
242
243 // Get the URL where login failed, i.e. where brute force attack might be happening
244 // $login_url = ( ! empty( $_SERVER['HTTPS'] ) ? 'https://' : 'http://') . sanitize_text_field( $_SERVER['HTTP_HOST'] ) . sanitize_text_field( $_SERVER['REQUEST_URI'] );
245 // Time stamps
246 $unixtime = time();
247
248 if ( function_exists( 'wp_date' ) ) {
249 $datetime_wp = wp_date( 'Y-m-d H:i:s', $unixtime );
250 } else {
251 $datetime_wp = date_i18n( 'Y-m-d H:i:s', $unixtime );
252 }
253
254 $data = array(
255 'ip_address' => $asenha_limit_login['ip_address'],
256 'username' => $username,
257 'fail_count' => $new_fail_count,
258 'lockout_count' => $new_lockout_count,
259 'request_uri' => $asenha_limit_login['request_uri'],
260 'unixtime' => $unixtime,
261 'datetime_wp' => $datetime_wp,
262 'info' => '',
263 );
264 $data_format = array(
265 '%s',
266 // string
267 '%s',
268 // string
269 '%d',
270 // integer
271 '%d',
272 // integer
273 '%s',
274 // string
275 '%d',
276 // integer
277 '%s',
278 // string
279 '%s',
280 );
281
282 if ( $result_count == 0 ) {
283 // Insert into the database
284 $result = $wpdb->insert( $table_name, $data, $data_format );
285 } else {
286 // $options = get_option( ASENHA_SLUG_U );
287 // $login_fails_allowed = $options['login_fails_allowed'];
288 $fail_count = $result[0]['fail_count'];
289 $lockout_count = $result[0]['lockout_count'];
290 $last_fail_on = $result[0]['unixtime'];
291 $where = array(
292 'ip_address' => $asenha_limit_login['ip_address'],
293 );
294 $where_format = array( '%s' );
295 // Failed attempts have been recorded and fulfills lockout condition
296
297 if ( !empty($fail_count) && $fail_count % $asenha_limit_login['login_fails_allowed'] == 0 ) {
298 // Has reached max / gone beyond number of lockouts allowed?
299
300 if ( $lockout_count >= $asenha_limit_login['login_lockout_maxcount'] ) {
301 $asenha_limit_login['extended_lockout'] = true;
302 $lockout_period = $asenha_limit_login['extended_lockout_period'];
303 } else {
304 $asenha_limit_login['extended_lockout'] = false;
305 $lockout_period = $asenha_limit_login['default_lockout_period'];
306 }
307
308 $asenha_limit_login['lockout_period'] = $lockout_period;
309 // User/visitor is still within the lockout period
310
311 if ( time() - $last_fail_on <= $asenha_limit_login['lockout_period'] ) {
312 // Do nothing
313 } else {
314 if ( $lockout_count < $asenha_limit_login['login_lockout_maxcount'] ) {
315 // Update existing data in the database
316 $wpdb->update(
317 $table_name,
318 $data,
319 $where,
320 $data_format,
321 $where_format
322 );
323 }
324 }
325
326 } else {
327 // Update existing data in the database
328 $wpdb->update(
329 $table_name,
330 $data,
331 $where,
332 $data_format,
333 $where_format
334 );
335 }
336
337 }
338
339 }
340
341 /**
342 * Handle login errors
343 *
344 * @link https://developer.wordpress.org/reference/classes/wp_error/#methods
345 * @since 2.5.0
346 */
347 public function login_error_handler( $errors, $redirect_to )
348 {
349 global $asenha_limit_login ;
350
351 if ( is_wp_error( $errors ) ) {
352 $error_codes = $errors->get_error_codes();
353 foreach ( $error_codes as $error_code ) {
354
355 if ( $error_code == 'invalid_username' || $error_code == 'incorrect_password' ) {
356 // Remove default error messages that may give out valueable info to hackers
357 $errors->remove( 'invalid_username' );
358 // Outputs info that says username does not exist. May encourage login attempt with a different username instead.
359 $errors->remove( 'incorrect_password' );
360 // Outputs info that implies username exist. May encourage login attempt with a different password.
361 // Add a new error message that does not provide useful clues to hackers
362 $errors->add( 'invalid_username_or_incorrect_password', '<b>Error:</b> Invalid username or incorrect password.' );
363 // $errors->add( 'another_error_code', 'The error message.' );
364 }
365
366 }
367 }
368
369 return $errors;
370 }
371
372 /**
373 * Add login error message on top of the login form
374 *
375 * @since 2.5.0
376 */
377 public function add_failed_login_message( $message )
378 {
379 global $asenha_limit_login ;
380 if ( isset( $_REQUEST['failed_login'] ) && $_REQUEST['failed_login'] == 'true' ) {
381 if ( isset( $asenha_limit_login['within_lockout_period'] ) && !$asenha_limit_login['within_lockout_period'] ) {
382 $message = '<div id="login_error"><b>Error:</b> Invalid username or incorrect password.</div>';
383 }
384 }
385 return $message;
386 }
387
388 /**
389 * Clear failed login attempts log after successful login
390 *
391 * @since 2.5.0
392 */
393 public function clear_failed_login_log()
394 {
395 global $wpdb, $asenha_limit_login ;
396 $table_name = $wpdb->prefix . 'asenha_failed_logins';
397 $ip_address = ( isset( $asenha_limit_login['ip_address'] ) ? $asenha_limit_login['ip_address'] : '' );
398 // Remove the DB log entry for the current IP address.
399 $where = array(
400 'ip_address' => $ip_address,
401 );
402 $where_format = array( '%s' );
403 $wpdb->delete( $table_name, $where, $where_format );
404 }
405
406 /**
407 * Obfuscate email address on the frontend using antispambot() native WP function
408 *
409 * @link: https://gist.github.com/eclarrrk/349360b52e8822b69cb6fc499722520f
410 * @since 5.5.0
411 */
412 public function obfuscate_string( $atts )
413 {
414 $atts = shortcode_atts( array(
415 'email' => '',
416 'subject' => '',
417 'display' => 'newline',
418 'link' => 'no',
419 'class' => '',
420 ), $atts );
421 $email = $atts['email'];
422 if ( !is_email( $email ) ) {
423 return;
424 }
425 // Reverse email address characters if not in Firefox, which has bug related to unicode-bidi CSS property
426 $http_user_agent = ( isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : 'generic' );
427
428 if ( false !== stripos( sanitize_text_field( $_SERVER['HTTP_USER_AGENT'] ), 'firefox' ) ) {
429 // Do nothing. Do not reverse characters.
430 $email_reversed = $email;
431 $email_rev_parts = explode( '@', $email_reversed );
432 $email_rev_parts = array( $email_rev_parts[0], $email_rev_parts[1] );
433 $css_bidi_styles = '';
434 } else {
435 $email_reversed = strrev( $email );
436 $email_rev_parts = explode( '@', $email_reversed );
437 $css_bidi_styles = 'unicode-bidi:bidi-override;';
438 }
439
440 $display = $atts['display'];
441
442 if ( 'newline' == $display ) {
443 $display_css = 'display:flex;justify-content:flex-end;';
444 } elseif ( 'inline' == $display ) {
445 $display_css = 'display:inline;';
446 }
447
448 $subject = $atts['subject'];
449 if ( !empty($subject) ) {
450 $subject = '?subject=' . $subject;
451 }
452 $link = $atts['link'];
453 $class = $atts['class'];
454 return '<div style="display:inline;' . esc_attr( $css_bidi_styles ) . ';direction:rtl;" class="' . esc_attr( $class ) . '">' . esc_html( $email_rev_parts[0] ) . '<span style="display:none;">obfsctd</span>&#64;' . esc_html( $email_rev_parts[1] ) . '</div>';
455 }
456
457 /**
458 * If an author name is queried, decrypt it. Used by pre_get_posts action.
459 *
460 * @link https://plugins.trac.wordpress.org/browser/smart-user-slug-hider/tags/4.0.2/inc/class-smart-user-slug-hider.php
461 * @since 2.1.0
462 */
463 function alter_author_query( $query )
464 {
465 // Check if it's a query for author data, and that 'author_name' is not empty
466 if ( $query->is_author() && $query->query_vars['author_name'] != '' ) {
467 // Check for character(s) representing a hexadecimal digit
468
469 if ( ctype_xdigit( $query->query_vars['author_name'] ) ) {
470 // Get user by the decrypted user ID
471 $user = get_user_by( 'id', $this->decrypt( $query->query_vars['author_name'] ) );
472
473 if ( $user ) {
474 $query->set( 'author_name', $user->user_nicename );
475 } else {
476 // No user found
477 $query->is_404 = true;
478 $query->is_author = false;
479 $query->is_archive = false;
480 }
481
482 } else {
483 // No hexadecimal digit detected in URL, i.e. someone is trying to access URL with original author slug
484 $query->is_404 = true;
485 $query->is_author = false;
486 $query->is_archive = false;
487 }
488
489 }
490 return;
491 }
492
493 /**
494 * Replace author slug in author link to encrypted value. Used by author_link filter.
495 *
496 * @link https://plugins.trac.wordpress.org/browser/smart-user-slug-hider/tags/4.0.2/inc/class-smart-user-slug-hider.php
497 * @since 2.1.0
498 */
499 function alter_author_link( $link, $user_id, $author_slug )
500 {
501 $encrypted_author_slug = $this->encrypt( $user_id );
502 return str_replace( '/' . $author_slug, '/' . $encrypted_author_slug, $link );
503 }
504
505 /**
506 * Replace author slug in REST API /users/ endpoint to encrypted value. Used by rest_prepare_user filter.
507 *
508 * @link https://plugins.trac.wordpress.org/browser/smart-user-slug-hider/tags/4.0.2/inc/class-smart-user-slug-hider.php
509 * @since 2.1.0
510 */
511 function alter_json_users( $response, $user, $request )
512 {
513 $data = $response->get_data();
514 $data['slug'] = $this->encrypt( $data['id'] );
515 $response->set_data( $data );
516 return $response;
517 }
518
519 /**
520 * Helper function to return an encrypted user ID, which will then be used to replace the author slug.
521 *
522 * @link https://plugins.trac.wordpress.org/browser/smart-user-slug-hider/trunk/inc/class-smart-user-slug-hider.php
523 * @since 2.1.0
524 */
525 private function encrypt( $user_id )
526 {
527 // Returns encrypted encrypted author slug from user ID, e.g. encrypt user ID 3 to author slug 4e3062d8c8626a14
528 return bin2hex( openssl_encrypt(
529 base_convert( $user_id, 10, 36 ),
530 'DES-EDE3',
531 md5( ASENHA_URL ),
532 OPENSSL_RAW_DATA
533 ) );
534 }
535
536 /**
537 * Helper function to decrypt an (encrypted) author slug and returns the user ID
538 *
539 * @link https://plugins.trac.wordpress.org/browser/smart-user-slug-hider/trunk/inc/class-smart-user-slug-hider.php
540 * @since 2.1.0
541 */
542 private function decrypt( $encrypted_author_slug )
543 {
544 // Returns user ID, e.g. decrypts author slug 4e3062d8c8626a14 into user ID 3
545 return base_convert( openssl_decrypt(
546 pack( 'H*', $encrypted_author_slug ),
547 'DES-EDE3',
548 md5( ASENHA_URL ),
549 OPENSSL_RAW_DATA
550 ), 36, 10 );
551 }
552
553 /**
554 * Remove XML RPC link in head
555 *
556 * @since 6.2.2
557 */
558 public function remove_xmlrpc_link()
559 {
560 remove_action( 'wp_head', 'rsd_link' );
561 }
562
563 /**
564 * Disable the XML-RPC component
565 *
566 * @since 2.2.0
567 */
568 public function maybe_disable_xmlrpc( $data )
569 {
570 http_response_code( 403 );
571 exit( 'You don\'t have permission to access this file.' );
572 }
573
574 }