PluginProbe ʕ •ᴥ•ʔ
SiteGuard WP Plugin / 1.8.7
SiteGuard WP Plugin v1.8.7
1.8.7 1.8.6 1.8.6-beta1 1.8.6-beta2 1.8.4 1.8.5 1.8.3 1.8.2 1.8.1 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.2 1.2.0 1.2.1 1.2.2 1.2.3 1.4.3 1.5.0 1.5.1 1.5.2 1.6.0 1.6.1 1.7.0 1.7.1 1.7.10 1.7.11 1.7.12 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 1.8.0-beta1 1.8.0-beta2 1.8.0-beta3 1.8.0-beta4
siteguard / admin / siteguard-menu-rename-login.php
siteguard / admin Last commit date
siteguard-login-history-table.php 1 month ago siteguard-menu-admin-filter.php 1 month ago siteguard-menu-author-query.php 2 weeks ago siteguard-menu-captcha.php 1 month ago siteguard-menu-dashboard.php 1 month ago siteguard-menu-fail-once.php 1 month ago siteguard-menu-init.php 1 month ago siteguard-menu-login-alert.php 1 month ago siteguard-menu-login-history.php 1 month ago siteguard-menu-login-lock.php 1 month ago siteguard-menu-protect-xmlrpc.php 1 month ago siteguard-menu-rename-login.php 2 weeks ago siteguard-menu-same-error.php 1 month ago siteguard-menu-updates-notify.php 1 month ago siteguard-menu-waf-tuning-support.php 1 month ago siteguard-waf-exclude-rule-table.php 1 month ago
siteguard-menu-rename-login.php
360 lines
1 <?php
2
3 class SiteGuard_Menu_Rename_Login extends SiteGuard_Base {
4 const OPT_NAME_FEATURE = 'renamelogin_enable';
5 const OPT_NAME_FEATURE_REDIRECT = 'redirect_enable';
6 const OPT_NAME_RENAME_LOGIN_PATH = 'renamelogin_path';
7 const OPT_NAME_OLD_LOGIN_PATH = 'oldlogin_path';
8 const OPT_NAME_STUB = 'renamelogin_stub';
9 const OPT_NAME_RESCUE = 'rescue_enable';
10
11 private static $pre_processed = false;
12 private static $pre_errors = array();
13 private static $pre_slug_value = null;
14
15 function __construct() {
16 $this->render_page();
17 }
18
19 private static function get_disallowed_slugs() {
20 $disallowed = array();
21 $files = scandir( ABSPATH );
22 if ( false === $files ) {
23 return array();
24 }
25
26 foreach ( $files as $file ) {
27 // Ignore dot files, current and parent directories.
28 if ( '.' === $file[0] ) {
29 continue;
30 }
31
32 if ( is_dir( ABSPATH . $file ) ) {
33 $disallowed[] = $file;
34 } else {
35 // For files, use the name without extension.
36 $disallowed[] = pathinfo( $file, PATHINFO_FILENAME );
37 }
38 }
39 return array_unique( $disallowed );
40 }
41
42 private static function stub_abs_path( $slug ) {
43 $slug = trim( (string) $slug, '/' );
44 if ( $slug === '' ) {
45 $slug = 'login'; }
46 return trailingslashit( ABSPATH ) . $slug . '.php';
47 }
48
49 public static function pre_handle_post() {
50 if ( ! isset( $_POST['update'] ) || ! check_admin_referer( 'siteguard-menu-rename-login-submit' ) ) {
51 return;
52 }
53
54 self::$pre_processed = true;
55 global $siteguard_config, $siteguard_rename_login;
56
57 $error = false;
58 $errors = siteguard_check_multisite();
59 if ( is_wp_error( $errors ) ) {
60 self::$pre_errors[] = $errors->get_error_message();
61 $error = true;
62 }
63
64 $posted_feature = isset( $_POST[ self::OPT_NAME_FEATURE ] ) ? sanitize_text_field( $_POST[ self::OPT_NAME_FEATURE ] ) : '';
65 if ( false === $error && ( '0' !== $posted_feature && '1' !== $posted_feature ) ) {
66 self::$pre_errors[] = esc_html__( 'ERROR: Invalid input value.', 'siteguard' );
67 $error = true;
68 }
69
70 if ( false === $error ) {
71 $posted_slug = sanitize_text_field( $_POST[ self::OPT_NAME_RENAME_LOGIN_PATH ] );
72 if ( 1 !== preg_match( '/^[a-zA-Z0-9_-]+$/', $posted_slug ) ) {
73 self::$pre_errors[] = esc_html__( 'Only letters, numbers, hyphens, and underscores can be used for the login path.', 'siteguard' );
74 self::$pre_slug_value = stripslashes( $posted_slug );
75 $error = true;
76 }
77
78 if ( false === $error && strlen( $posted_slug ) < 4 ) {
79 self::$pre_errors[] = esc_html__( 'The new login path must be at least 4 characters long.', 'siteguard' );
80 self::$pre_slug_value = stripslashes( $posted_slug );
81 $error = true;
82 }
83
84 if ( false === $error ) {
85 $current_slug = $siteguard_config->get( self::OPT_NAME_RENAME_LOGIN_PATH );
86 if ( $posted_slug !== $current_slug ) {
87 $disallowed_slugs = self::get_disallowed_slugs();
88 if ( in_array( $posted_slug, $disallowed_slugs, true ) ) {
89 /* translators: %s: slug */
90 self::$pre_errors[] = sprintf( esc_html__( '%s cannot be used for the new login path because it conflicts with an existing file or directory in the WordPress root.', 'siteguard' ), '<code>' . esc_html( $posted_slug ) . '</code>' );
91 self::$pre_slug_value = stripslashes( $posted_slug );
92 $error = true;
93 }
94 }
95 }
96 }
97
98 if ( false === $error ) {
99 $old_feature = $siteguard_config->get( self::OPT_NAME_FEATURE );
100 $old_feature_redirect = $siteguard_config->get( self::OPT_NAME_FEATURE_REDIRECT );
101 $old_rename_login_path = $siteguard_config->get( self::OPT_NAME_RENAME_LOGIN_PATH );
102 $old_old_login_path = $siteguard_config->get( self::OPT_NAME_OLD_LOGIN_PATH );
103 $old_rescue = $siteguard_config->get( self::OPT_NAME_RESCUE );
104
105 $new_feature = $posted_feature;
106 $new_feature_redirect = isset( $_POST[ self::OPT_NAME_FEATURE_REDIRECT ] ) ? '1' : '0';
107 $new_rename_login_path = $posted_slug;
108 $new_rescue = isset( $_POST[ self::OPT_NAME_RESCUE ] ) ? '1' : '0';
109
110 $siteguard_config->set( self::OPT_NAME_FEATURE, $new_feature );
111 $siteguard_config->set( self::OPT_NAME_FEATURE_REDIRECT, $new_feature_redirect );
112 $siteguard_config->set( self::OPT_NAME_RENAME_LOGIN_PATH, $new_rename_login_path );
113 $siteguard_config->set( self::OPT_NAME_OLD_LOGIN_PATH, $old_rename_login_path );
114 $siteguard_config->set( self::OPT_NAME_RESCUE, $new_rescue );
115 $siteguard_config->update();
116
117 $result = true;
118 if ( '0' === $new_feature ) {
119 $result = $siteguard_rename_login->feature_off();
120 } else {
121 $result = $siteguard_rename_login->feature_on();
122 $stub_required = ! $siteguard_rename_login->can_use_htaccess();
123 $stub_file = self::stub_abs_path( $new_rename_login_path );
124 $stub_fail = (bool) get_transient( SiteGuard_RenameLogin::STUB_WRITE_FAIL_TRANSIENT );
125
126 if ( false === $result || ( $stub_required && ( $stub_fail || ! file_exists( $stub_file ) ) ) ) {
127 $siteguard_config->set( self::OPT_NAME_FEATURE, $old_feature );
128 $siteguard_config->set( self::OPT_NAME_FEATURE_REDIRECT, $old_feature_redirect );
129 $siteguard_config->set( self::OPT_NAME_RENAME_LOGIN_PATH, $old_rename_login_path );
130 $siteguard_config->set( self::OPT_NAME_OLD_LOGIN_PATH, $old_old_login_path );
131 $siteguard_config->set( self::OPT_NAME_RESCUE, $old_rescue );
132 $siteguard_config->update();
133 SiteGuard_RenameLogin::feature_off();
134 $result = false;
135
136 if ( $stub_required || $stub_fail ) {
137 self::$pre_errors[] = esc_html__( 'ERROR: Failed to enable. WordPress cannot create the required file in the site root.', 'siteguard' )
138 . ' ' . esc_html__( 'Please check that the WordPress root directory is writable, or contact your hosting provider.', 'siteguard' );
139 } else {
140 self::$pre_errors[] = esc_html__( 'ERROR: Failed to update settings. Please try again.', 'siteguard' );
141 }
142 } elseif ( '1' === $new_feature ) {
143 $siteguard_rename_login->send_notify();
144 }
145
146 if ( $stub_fail ) {
147 delete_transient( SiteGuard_RenameLogin::STUB_WRITE_FAIL_TRANSIENT );
148 }
149 }
150
151 if ( true === $result ) {
152 wp_safe_redirect( admin_url( 'admin.php?page=siteguard_rename_login&updated=1' ) );
153 exit;
154 }
155 }
156 }
157
158 private function current_mode_description() {
159 global $siteguard_config;
160
161 if ( '1' === $siteguard_config->get( self::OPT_NAME_FEATURE ) ) {
162 $slug = trim( (string) $siteguard_config->get( self::OPT_NAME_RENAME_LOGIN_PATH ), '/' );
163 $stub_on = ( SITEGUARD_RENAME_MODE_STUB === $siteguard_config->get( self::OPT_NAME_STUB ) );
164 $loginurl = rtrim( site_url(), '/' ) . '/' . ( $stub_on ? ( $slug . '.php' ) : $slug );
165 if ( $stub_on ) {
166 $reason = $this->stub_reason_text();
167 return sprintf(
168 '%s <code>%s</code><br>%s%s',
169 esc_html__( 'Login URL:', 'siteguard' ),
170 esc_url( $loginurl ),
171 esc_html__( 'The login URL ends with .php because this server does not support .htaccess.', 'siteguard' ),
172 '' !== $reason ? '<br>' . $reason : ''
173 );
174 } else {
175 return sprintf(
176 '%s <code>%s</code>',
177 esc_html__( 'Login URL:', 'siteguard' ),
178 esc_url( $loginurl )
179 );
180 }
181 }
182 $loginurl = rtrim( site_url(), '/' ) . '/wp-login.php';
183 return sprintf(
184 '%s <code>%s</code><br>%s',
185 esc_html__( 'Login URL:', 'siteguard' ),
186 $loginurl,
187 esc_html__( 'This feature is currently off.', 'siteguard' )
188 );
189 }
190
191 /**
192 * Human-readable explanation of why stub (.php) mode was chosen, based on the
193 * reason recorded by SiteGuard_RenameLogin::feature_on(). Returns '' when no
194 * reason is available. The returned string may contain pre-escaped HTML.
195 */
196 private function stub_reason_text() {
197 global $siteguard_config;
198 $reason = $siteguard_config->get( self::OPT_NAME_STUB . '_reason' );
199 if ( ! is_array( $reason ) || empty( $reason['code'] ) ) {
200 return '';
201 }
202 $url = isset( $reason['url'] ) ? '<code>' . esc_html( $reason['url'] ) . '</code>' : '';
203 switch ( $reason['code'] ) {
204 case 'nginx':
205 return esc_html__( 'Reason: the server is Nginx, which does not use .htaccess.', 'siteguard' );
206 case 'server_software':
207 return esc_html__( 'Reason: the server is not Apache/LiteSpeed, so .htaccess is not used.', 'siteguard' );
208 case 'not_writable':
209 return esc_html__( 'Reason: the .htaccess file (or the WordPress directory) is not writable.', 'siteguard' );
210 case 'mkdir':
211 return esc_html__( 'Reason: a temporary test directory could not be created in the WordPress directory (check write permission).', 'siteguard' );
212 case 'write':
213 return esc_html__( 'Reason: the temporary test files could not be written.', 'siteguard' );
214 case 'htaccess_ignored':
215 return sprintf(
216 /* translators: %s: test URL */
217 esc_html__( 'Reason: the .htaccess file is present but the server is ignoring it (for example AllowOverride is set to None, or mod_rewrite is not enabled for this directory), so the rewrite for %s had no effect.', 'siteguard' ),
218 $url
219 );
220 case 'wp_error':
221 return sprintf(
222 /* translators: 1: test URL, 2: error message */
223 esc_html__( 'Reason: the self-test request to %1$s failed (%2$s). The server may be unable to reach its own URL (loopback).', 'siteguard' ),
224 $url,
225 esc_html( isset( $reason['detail'] ) ? $reason['detail'] : '' )
226 );
227 case 'http_status':
228 $status = (int) ( isset( $reason['status'] ) ? $reason['status'] : 0 );
229 if ( 401 === $status || 403 === $status ) {
230 $hint = esc_html__( 'It may be blocked by an access restriction such as Basic authentication or an IP restriction.', 'siteguard' );
231 } elseif ( 404 === $status ) {
232 $hint = esc_html__( 'The test URL was not found, for example because WordPress is installed in a subdirectory so the self-test URL does not map to it, or the request is routed elsewhere.', 'siteguard' );
233 } elseif ( 429 === $status || 503 === $status ) {
234 $hint = esc_html__( 'The request was rate-limited or temporarily blocked. This is usually a server-side rate limit or anti-bot/access-control protection (separate from .htaccess), not a sign that .htaccess is broken. Try again after a short while.', 'siteguard' );
235 } elseif ( $status >= 300 && $status < 400 ) {
236 $hint = esc_html__( 'The request was redirected (for example HTTP to HTTPS, or a canonical redirect).', 'siteguard' );
237 } else {
238 $hint = '';
239 }
240 return sprintf(
241 /* translators: 1: test URL, 2: HTTP status code */
242 esc_html__( 'Reason: the self-test request to %1$s returned HTTP %2$s instead of 200.', 'siteguard' ),
243 $url,
244 esc_html( (string) $status )
245 ) . ( '' !== $hint ? ' ' . $hint : '' );
246 case 'bad_body':
247 return sprintf(
248 /* translators: %s: test URL */
249 esc_html__( 'Reason: the self-test request to %s did not return the expected result; the .htaccess rewrite did not take effect (it may be disabled by AllowOverride or overridden by another rule).', 'siteguard' ),
250 $url
251 );
252 }
253 return '';
254 }
255
256 function render_page() {
257 global $siteguard_config;
258
259 $opt_val_feature = $siteguard_config->get( self::OPT_NAME_FEATURE );
260 $opt_val_feature_redirect = $siteguard_config->get( self::OPT_NAME_FEATURE_REDIRECT );
261 $opt_val_rename_login_path = ( null !== self::$pre_slug_value )
262 ? self::$pre_slug_value
263 : $siteguard_config->get( self::OPT_NAME_RENAME_LOGIN_PATH );
264 $opt_val_rescue = $siteguard_config->get( self::OPT_NAME_RESCUE );
265
266 foreach ( self::$pre_errors as $msg ) {
267 echo '<div class="error settings-error"><p><strong>' . wp_kses_post( $msg ) . '</strong></p></div>';
268 }
269
270 echo '<div class="wrap">';
271 echo '<img src="' . SITEGUARD_URL_PATH . 'images/sg_wp_plugin_logo_40.png" alt="SiteGuard Logo" />';
272 echo '<h2>' . esc_html__( 'Rename Login', 'siteguard' ) . '</h2>';
273
274 if ( isset( $_GET['updated'] ) && '1' === $_GET['updated'] ) {
275 echo '<div class="updated"><p><strong>';
276 esc_html_e( 'Options saved.', 'siteguard' );
277 echo '</strong></p></div>';
278 }
279
280 echo '<div class="notice notice-info" style="padding:8px 12px;margin-top:10px;">' . wp_kses_post( $this->current_mode_description() ) . '</div>';
281
282 $documentation_link = '<a href="' . esc_url( __( 'https://www.jp-secure.com/siteguard_wp_plugin_en/howto/rename_login/', 'siteguard' ) ) . '" target="_blank">' . esc_html__( 'online documentation', 'siteguard' ) . '</a>';
283 echo '<div class="siteguard-description">'
284 . sprintf(
285 /* translators: %1$s: Link to the online documentation. */
286 esc_html__( 'See the %1$s.', 'siteguard' ),
287 $documentation_link
288 )
289 . '</div>';
290 ?>
291 <form name="form1" method="post" action="">
292 <table class="form-table">
293 <tr>
294 <th scope="row" colspan="2">
295 <ul class="siteguard-radios">
296 <li>
297 <input type="radio" name="<?php echo self::OPT_NAME_FEATURE; ?>" id="<?php echo self::OPT_NAME_FEATURE . '_on'; ?>" value="1" <?php checked( $opt_val_feature, '1' ); ?> >
298 <label for="<?php echo self::OPT_NAME_FEATURE . '_on'; ?>"><?php echo esc_html_e( 'ON', 'siteguard' ); ?></label>
299 </li><li>
300 <input type="radio" name="<?php echo self::OPT_NAME_FEATURE; ?>" id="<?php echo self::OPT_NAME_FEATURE . '_off'; ?>" value="0" <?php checked( $opt_val_feature, '0' ); ?> >
301 <label for="<?php echo self::OPT_NAME_FEATURE . '_off'; ?>"><?php echo esc_html_e( 'OFF', 'siteguard' ); ?></label>
302 </li>
303 </ul>
304 <?php
305 echo '<p class="description">';
306 esc_html_e( 'Works automatically on most servers. If activation fails, please check file permissions or contact your hosting provider.', 'siteguard' );
307 echo '</p>';
308 ?>
309 </th>
310 </tr><tr>
311 <th scope="row"><label for="<?php echo self::OPT_NAME_RENAME_LOGIN_PATH; ?>"><?php esc_html_e( 'New Login Path', 'siteguard' ); ?></label></th>
312 <td>
313 <?php
314 $stub_on = ( SITEGUARD_RENAME_MODE_STUB === $siteguard_config->get( self::OPT_NAME_STUB ) );
315 echo esc_url( site_url() ) . '/';
316 ?>
317 <input type="text" name="<?php echo self::OPT_NAME_RENAME_LOGIN_PATH; ?>" id="<?php echo self::OPT_NAME_RENAME_LOGIN_PATH; ?>" value="<?php echo esc_attr( $opt_val_rename_login_path ); ?>" >
318 <?php
319 if ( '1' === $opt_val_feature && $stub_on ) {
320 echo '.php';
321 }
322 echo '<p class="description">';
323 if ( $stub_on ) {
324 esc_html_e( 'The actual login URL will include .php at the end.', 'siteguard' );
325 } else {
326 esc_html_e( 'Letters, numbers, hyphens, and underscores only.', 'siteguard' );
327 }
328 echo '</p>';
329 ?>
330 </td>
331 </tr><tr>
332 <th scope="row"><?php esc_html_e( 'Option', 'siteguard' ); ?></th>
333 <td>
334 <p>
335 <input type="checkbox" name="<?php echo self::OPT_NAME_FEATURE_REDIRECT; ?>" id="<?php echo self::OPT_NAME_FEATURE_REDIRECT; ?>" value="1" <?php checked( $opt_val_feature_redirect, '1' ); ?> >
336 <label for="<?php echo self::OPT_NAME_FEATURE_REDIRECT; ?>"><?php esc_html_e( 'Do not redirect from the admin page to the login page.', 'siteguard' ); ?></label>
337 </p>
338 <p>
339 <input type="checkbox" name="<?php echo self::OPT_NAME_RESCUE; ?>" id="<?php echo self::OPT_NAME_RESCUE; ?>" value="1" <?php checked( $opt_val_rescue, '1' ); ?> >
340 <label for="<?php echo self::OPT_NAME_RESCUE; ?>"><?php echo esc_html__( 'Enable login rescue', 'siteguard' ); ?> (<code><?php echo esc_url( add_query_arg( 'siteguard_rescue', '1', site_url( '/' ) ) ); ?></code>)</label>
341 <br><span class="description"><?php esc_html_e( 'Users can request the current login URL by solving a CAPTCHA. For security, a confirmation is always shown regardless of whether the address exists.', 'siteguard' ); ?></span>
342 </p>
343 </td>
344 </tr>
345 </table>
346 <input type="hidden" name="update" value="Y">
347 <div class="siteguard-description">
348 <?php esc_html_e( 'This protects your site by changing the login page URL, making it harder for automated attacks to find it. The default URL is “login_&lt;5 random digits&gt;” and can be customized.', 'siteguard' ); ?>
349 </div>
350 <hr />
351 <?php
352 wp_nonce_field( 'siteguard-menu-rename-login-submit' );
353 submit_button();
354 ?>
355 </form>
356 </div>
357 <?php
358 }
359 }
360