PluginProbe ʕ •ᴥ•ʔ
Admin and Site Enhancements (ASE) / 6.2.3
Admin and Site Enhancements (ASE) v6.2.3
9.1.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
566 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 $fail_count = 0;
78 $lockout_count = 0;
79 $last_fail_on = '';
80 }
81
82 // Initialize the global variable
83 $asenha_limit_login = array(
84 'ip_address' => $ip_address,
85 'request_uri' => sanitize_text_field( $_SERVER['REQUEST_URI'] ),
86 'ip_address_log' => $result,
87 'maybe_lockout' => false,
88 'extended_lockout' => false,
89 'within_lockout_period' => false,
90 'lockout_period' => 0,
91 'lockout_period_remaining' => 0,
92 'login_fails_allowed' => $login_fails_allowed,
93 'login_lockout_maxcount' => $login_lockout_maxcount,
94 'default_lockout_period' => 60 * 15,
95 'extended_lockout_period' => 24 * 60 * 60,
96 'change_login_url' => $change_login_url,
97 'custom_login_slug' => $custom_login_slug,
98 );
99
100 if ( !in_array( $ip_address, $ip_address_whitelist ) ) {
101 // IP is not whitelisted
102
103 if ( $result_count > 0 ) {
104 // IP address has been recorded in the database.
105 // Failed attempts have been recorded and fulfills lockout condition
106
107 if ( !empty($fail_count) && $fail_count % $login_fails_allowed == 0 ) {
108 $asenha_limit_login['maybe_lockout'] = true;
109 // Has reached max / gone beyond number of lockouts allowed?
110
111 if ( $lockout_count >= $login_lockout_maxcount ) {
112 $asenha_limit_login['extended_lockout'] = true;
113 $lockout_period = $asenha_limit_login['extended_lockout_period'];
114 } else {
115 $asenha_limit_login['extended_lockout'] = false;
116 $lockout_period = $asenha_limit_login['default_lockout_period'];
117 }
118
119 $asenha_limit_login['lockout_period'] = $lockout_period;
120 // User/visitor is still within the lockout period
121
122 if ( time() - $last_fail_on <= $asenha_limit_login['lockout_period'] ) {
123 $asenha_limit_login['within_lockout_period'] = true;
124 $asenha_limit_login['lockout_period_remaining'] = $asenha_limit_login['lockout_period'] - (time() - $last_fail_on);
125
126 if ( $asenha_limit_login['lockout_period_remaining'] <= 60 ) {
127 // Get remaining lockout period in minutes and seconds
128 $lockout_period_remaining = $asenha_limit_login['lockout_period_remaining'] . ' seconds';
129 } elseif ( $asenha_limit_login['lockout_period_remaining'] <= 60 * 60 ) {
130 // Get remaining lockout period in minutes and seconds
131 $lockout_period_remaining = $common_methods->seconds_to_period( $asenha_limit_login['lockout_period_remaining'], 'to-minutes-seconds' );
132 } elseif ( $asenha_limit_login['lockout_period_remaining'] > 60 * 60 && $asenha_limit_login['lockout_period_remaining'] <= 24 * 60 * 60 ) {
133 // Get remaining lockout period in minutes and seconds
134 $lockout_period_remaining = $common_methods->seconds_to_period( $asenha_limit_login['lockout_period_remaining'], 'to-hours-minutes-seconds' );
135 } elseif ( $asenha_limit_login['lockout_period_remaining'] > 24 * 60 * 60 ) {
136 // Get remaining lockout period in minutes and seconds
137 $lockout_period_remaining = $common_methods->seconds_to_period( $asenha_limit_login['lockout_period_remaining'], 'to-days-hours-minutes-seconds' );
138 }
139
140 $error = new WP_Error( 'ip_address_blocked', '<b>WARNING:</b> You\'ve been locked out. You can login again in ' . $lockout_period_remaining . '.' );
141 return $error;
142 } else {
143 // User/visitor is no longer within the lockout period
144 $asenha_limit_login['within_lockout_period'] = false;
145
146 if ( $lockout_count == $login_lockout_maxcount ) {
147 // Remove the DB log entry for the current IP address. i.e. release from extended lockout
148 $where = array(
149 'ip_address' => $ip_address,
150 );
151 $where_format = array( '%s' );
152 // Delete existing data in the database
153 $wpdb->delete( $table_name, $where, $where_format );
154 }
155
156 return $user_or_error;
157 }
158
159 } else {
160 $asenha_limit_login['maybe_lockout'] = false;
161 return $user_or_error;
162 }
163
164 } else {
165 // IP address has not been recorded in the database.
166 return $user_or_error;
167 }
168
169 } else {
170 // IP is whitelisted
171 return $user_or_error;
172 }
173
174 }
175
176 /**
177 * Disable login form inputs via CSS
178 *
179 * @since 2.5.0
180 */
181 public function maybe_hide_login_form()
182 {
183 global $asenha_limit_login ;
184
185 if ( isset( $asenha_limit_login ) && $asenha_limit_login['within_lockout_period'] ) {
186 // Hide logo, login form and the links below it
187 ?>
188 <style type="text/css">
189
190 body.login {
191 background:#f6d6d7;
192 }
193
194 #login h1,
195 #loginform,
196 #login #nav,
197 #backtoblog {
198 display: none;
199 }
200
201 @media screen and (max-height: 550px) {
202
203 #login {
204 padding: 80px 0 20px !important;
205 }
206
207 }
208
209 </style>
210 <?php
211 }
212
213 }
214
215 /**
216 * Log failed login attempts
217 *
218 * @since 2.5.0
219 */
220 public function log_failed_login( $username )
221 {
222 global $wpdb, $asenha_limit_login ;
223 $table_name = $wpdb->prefix . 'asenha_failed_logins';
224 // Check if the IP address has been used in a failed login attempt before, i.e. has it been recorded in the database?
225 $sql = $wpdb->prepare( "SELECT * FROM `" . $table_name . "` WHERE `ip_address` = %s", $asenha_limit_login['ip_address'] );
226 $result = $wpdb->get_results( $sql, ARRAY_A );
227 $result_count = count( $result );
228 // Update logged info for the IP address in the global variable
229 $asenha_limit_login['ip_address_log'] = $result;
230
231 if ( $result_count == 0 ) {
232 // IP address has not been recorded in the database.
233 $new_fail_count = 1;
234 $new_lockout_count = 0;
235 } else {
236 // IP address has been recorded in the database.
237 $new_fail_count = $result[0]['fail_count'] + 1;
238 $new_lockout_count = floor( ($result[0]['fail_count'] + 1) / $asenha_limit_login['login_fails_allowed'] );
239 }
240
241 // Get the URL where login failed, i.e. where brute force attack might be happening
242 // $login_url = ( ! empty( $_SERVER['HTTPS'] ) ? 'https://' : 'http://') . sanitize_text_field( $_SERVER['HTTP_HOST'] ) . sanitize_text_field( $_SERVER['REQUEST_URI'] );
243 // Time stamps
244 $unixtime = time();
245
246 if ( function_exists( 'wp_date' ) ) {
247 $datetime_wp = wp_date( 'Y-m-d H:i:s', $unixtime );
248 } else {
249 $datetime_wp = date_i18n( 'Y-m-d H:i:s', $unixtime );
250 }
251
252 $data = array(
253 'ip_address' => $asenha_limit_login['ip_address'],
254 'username' => $username,
255 'fail_count' => $new_fail_count,
256 'lockout_count' => $new_lockout_count,
257 'request_uri' => $asenha_limit_login['request_uri'],
258 'unixtime' => $unixtime,
259 'datetime_wp' => $datetime_wp,
260 'info' => '',
261 );
262 $data_format = array(
263 '%s',
264 // string
265 '%s',
266 // string
267 '%d',
268 // integer
269 '%d',
270 // integer
271 '%s',
272 // string
273 '%d',
274 // integer
275 '%s',
276 // string
277 '%s',
278 );
279
280 if ( $result_count == 0 ) {
281 // Insert into the database
282 $result = $wpdb->insert( $table_name, $data, $data_format );
283 } else {
284 // $options = get_option( ASENHA_SLUG_U );
285 // $login_fails_allowed = $options['login_fails_allowed'];
286 $fail_count = $result[0]['fail_count'];
287 $lockout_count = $result[0]['lockout_count'];
288 $last_fail_on = $result[0]['unixtime'];
289 $where = array(
290 'ip_address' => $asenha_limit_login['ip_address'],
291 );
292 $where_format = array( '%s' );
293 // Failed attempts have been recorded and fulfills lockout condition
294
295 if ( !empty($fail_count) && $fail_count % $asenha_limit_login['login_fails_allowed'] == 0 ) {
296 // Has reached max / gone beyond number of lockouts allowed?
297
298 if ( $lockout_count >= $asenha_limit_login['login_lockout_maxcount'] ) {
299 $asenha_limit_login['extended_lockout'] = true;
300 $lockout_period = $asenha_limit_login['extended_lockout_period'];
301 } else {
302 $asenha_limit_login['extended_lockout'] = false;
303 $lockout_period = $asenha_limit_login['default_lockout_period'];
304 }
305
306 $asenha_limit_login['lockout_period'] = $lockout_period;
307 // User/visitor is still within the lockout period
308
309 if ( time() - $last_fail_on <= $asenha_limit_login['lockout_period'] ) {
310 // Do nothing
311 } else {
312 if ( $lockout_count < $asenha_limit_login['login_lockout_maxcount'] ) {
313 // Update existing data in the database
314 $wpdb->update(
315 $table_name,
316 $data,
317 $where,
318 $data_format,
319 $where_format
320 );
321 }
322 }
323
324 } else {
325 // Update existing data in the database
326 $wpdb->update(
327 $table_name,
328 $data,
329 $where,
330 $data_format,
331 $where_format
332 );
333 }
334
335 }
336
337 }
338
339 /**
340 * Handle login errors
341 *
342 * @link https://developer.wordpress.org/reference/classes/wp_error/#methods
343 * @since 2.5.0
344 */
345 public function login_error_handler( $errors, $redirect_to )
346 {
347 global $asenha_limit_login ;
348
349 if ( is_wp_error( $errors ) ) {
350 $error_codes = $errors->get_error_codes();
351 foreach ( $error_codes as $error_code ) {
352
353 if ( $error_code == 'invalid_username' || $error_code == 'incorrect_password' ) {
354 // Remove default error messages that may give out valueable info to hackers
355 $errors->remove( 'invalid_username' );
356 // Outputs info that says username does not exist. May encourage login attempt with a different username instead.
357 $errors->remove( 'incorrect_password' );
358 // Outputs info that implies username exist. May encourage login attempt with a different password.
359 // Add a new error message that does not provide useful clues to hackers
360 $errors->add( 'invalid_username_or_incorrect_password', '<b>Error:</b> Invalid username or incorrect password.' );
361 // $errors->add( 'another_error_code', 'The error message.' );
362 }
363
364 }
365 }
366
367 return $errors;
368 }
369
370 /**
371 * Add login error message on top of the login form
372 *
373 * @since 2.5.0
374 */
375 public function add_failed_login_message( $message )
376 {
377 global $asenha_limit_login ;
378 if ( isset( $_REQUEST['failed_login'] ) && $_REQUEST['failed_login'] == 'true' ) {
379 if ( !$asenha_limit_login['within_lockout_period'] ) {
380 $message = '<div id="login_error"><b>Error:</b> Invalid username or incorrect password.</div>';
381 }
382 }
383 return $message;
384 }
385
386 /**
387 * Clear failed login attempts log after successful login
388 *
389 * @since 2.5.0
390 */
391 public function clear_failed_login_log()
392 {
393 global $wpdb, $asenha_limit_login ;
394 $table_name = $wpdb->prefix . 'asenha_failed_logins';
395 // Remove the DB log entry for the current IP address.
396 $where = array(
397 'ip_address' => $asenha_limit_login['ip_address'],
398 );
399 $where_format = array( '%s' );
400 $wpdb->delete( $table_name, $where, $where_format );
401 }
402
403 /**
404 * Obfuscate email address on the frontend using antispambot() native WP function
405 *
406 * @link: https://gist.github.com/eclarrrk/349360b52e8822b69cb6fc499722520f
407 * @since 5.5.0
408 */
409 public function obfuscate_string( $atts )
410 {
411 $atts = shortcode_atts( array(
412 'email' => '',
413 'display' => 'newline',
414 'link' => 'no',
415 'class' => '',
416 ), $atts );
417 $email = $atts['email'];
418 if ( !is_email( $email ) ) {
419 return;
420 }
421 // Reverse email address characters if not in Firefox, which has bug related to unicode-bidi CSS property
422 $http_user_agent = $_SERVER['HTTP_USER_AGENT'];
423
424 if ( false !== stripos( sanitize_text_field( $_SERVER['HTTP_USER_AGENT'] ), 'firefox' ) ) {
425 // Do nothing. Do not reverse characters.
426 $email_reversed = $email;
427 $email_rev_parts = explode( '@', $email_reversed );
428 $email_rev_parts = array( $email_rev_parts[0], $email_rev_parts[1] );
429 $css_bidi_styles = '';
430 } else {
431 $email_reversed = strrev( $email );
432 $email_rev_parts = explode( '@', $email_reversed );
433 $css_bidi_styles = 'unicode-bidi:bidi-override;';
434 }
435
436 $display = $atts['display'];
437
438 if ( 'newline' == $display ) {
439 $display_css = 'display:flex;justify-content:flex-end;';
440 } elseif ( 'inline' == $display ) {
441 $display_css = 'display:inline;';
442 }
443
444 $link = $atts['link'];
445 $class = $atts['class'];
446 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>';
447 }
448
449 /**
450 * If an author name is queried, decrypt it. Used by pre_get_posts action.
451 *
452 * @link https://plugins.trac.wordpress.org/browser/smart-user-slug-hider/tags/4.0.2/inc/class-smart-user-slug-hider.php
453 * @since 2.1.0
454 */
455 function alter_author_query( $query )
456 {
457 // Check if it's a query for author data, and that 'author_name' is not empty
458 if ( $query->is_author() && $query->query_vars['author_name'] != '' ) {
459 // Check for character(s) representing a hexadecimal digit
460
461 if ( ctype_xdigit( $query->query_vars['author_name'] ) ) {
462 // Get user by the decrypted user ID
463 $user = get_user_by( 'id', $this->decrypt( $query->query_vars['author_name'] ) );
464
465 if ( $user ) {
466 $query->set( 'author_name', $user->user_nicename );
467 } else {
468 // No user found
469 $query->is_404 = true;
470 $query->is_author = false;
471 $query->is_archive = false;
472 }
473
474 } else {
475 // No hexadecimal digit detected in URL, i.e. someone is trying to access URL with original author slug
476 $query->is_404 = true;
477 $query->is_author = false;
478 $query->is_archive = false;
479 }
480
481 }
482 return;
483 }
484
485 /**
486 * Replace author slug in author link to encrypted value. Used by author_link filter.
487 *
488 * @link https://plugins.trac.wordpress.org/browser/smart-user-slug-hider/tags/4.0.2/inc/class-smart-user-slug-hider.php
489 * @since 2.1.0
490 */
491 function alter_author_link( $link, $user_id, $author_slug )
492 {
493 $encrypted_author_slug = $this->encrypt( $user_id );
494 return str_replace( '/' . $author_slug, '/' . $encrypted_author_slug, $link );
495 }
496
497 /**
498 * Replace author slug in REST API /users/ endpoint to encrypted value. Used by rest_prepare_user filter.
499 *
500 * @link https://plugins.trac.wordpress.org/browser/smart-user-slug-hider/tags/4.0.2/inc/class-smart-user-slug-hider.php
501 * @since 2.1.0
502 */
503 function alter_json_users( $response, $user, $request )
504 {
505 $data = $response->get_data();
506 $data['slug'] = $this->encrypt( $data['id'] );
507 $response->set_data( $data );
508 return $response;
509 }
510
511 /**
512 * Helper function to return an encrypted user ID, which will then be used to replace the author slug.
513 *
514 * @link https://plugins.trac.wordpress.org/browser/smart-user-slug-hider/trunk/inc/class-smart-user-slug-hider.php
515 * @since 2.1.0
516 */
517 private function encrypt( $user_id )
518 {
519 // Returns encrypted encrypted author slug from user ID, e.g. encrypt user ID 3 to author slug 4e3062d8c8626a14
520 return bin2hex( openssl_encrypt(
521 base_convert( $user_id, 10, 36 ),
522 'DES-EDE3',
523 md5( ASENHA_URL ),
524 OPENSSL_RAW_DATA
525 ) );
526 }
527
528 /**
529 * Helper function to decrypt an (encrypted) author slug and returns the user ID
530 *
531 * @link https://plugins.trac.wordpress.org/browser/smart-user-slug-hider/trunk/inc/class-smart-user-slug-hider.php
532 * @since 2.1.0
533 */
534 private function decrypt( $encrypted_author_slug )
535 {
536 // Returns user ID, e.g. decrypts author slug 4e3062d8c8626a14 into user ID 3
537 return base_convert( openssl_decrypt(
538 pack( 'H*', $encrypted_author_slug ),
539 'DES-EDE3',
540 md5( ASENHA_URL ),
541 OPENSSL_RAW_DATA
542 ), 36, 10 );
543 }
544
545 /**
546 * Remove XML RPC link in head
547 *
548 * @since 6.2.2
549 */
550 public function remove_xmlrpc_link()
551 {
552 remove_action( 'wp_head', 'rsd_link' );
553 }
554
555 /**
556 * Disable the XML-RPC component
557 *
558 * @since 2.2.0
559 */
560 public function maybe_disable_xmlrpc( $data )
561 {
562 http_response_code( 403 );
563 exit( 'You don\'t have permission to access this file.' );
564 }
565
566 }