<?php

namespace WPSecurityNinja\Plugin;

if ( ! function_exists( 'add_action' ) ) {
	die( 'Please don\'t open this file directly!' );
}

if ( defined( 'ABSPATH' ) && ! class_exists( __NAMESPACE__ . '\SecNin_Rename_WP_Login' ) ) {

	class SecNin_Rename_WP_Login {

		const DEFAULT_SLUG = 'my-login';
		private static $wp_login_php;

		public static $default_login_url = 'my-login';

		private static function basename() {
			// Set in security-ninja.php
			return WF_SN_PLUGIN_BASENAME;
		}

		private static function path() {
			return trailingslashit( __DIR__ );
		}

		/**
		 * use_trailing_slashes.
		 *
		 * @author  Unknown
		 * @since   v0.0.1
		 * @version v1.0.0  Friday, October 22nd, 2021.
		 * @access  private static
		 * @return  string
		 */
		private static function use_trailing_slashes() {
			return '/' === substr( get_option( 'permalink_structure' ), -1, 1 );
		}

		/**
		 * user_trailingslashit.
		 *
		 * @author  Unknown
		 * @since   v0.0.1
		 * @version v1.0.0  Friday, October 22nd, 2021.
		 * @access  private static
		 * @param   mixed   $string
		 * @return  mixed
		 */
		private static function user_trailingslashit( $string ) {
			return self::use_trailing_slashes() ? trailingslashit( $string ) : untrailingslashit( $string );
		}

		/**
		 * forbidden_slugs.
		 *
		 * @author  Unknown
		 * @since   v0.0.1
		 * @version v1.0.0  Sunday, October 24th, 2021.
		 * @access  public static
		 * @return  mixed
		 */
		public static function forbidden_slugs() {
			$wp = new \WP();
			return array_merge( $wp->public_query_vars, $wp->private_query_vars, array( 'wp-admin', 'wp-login' ) );
		}
		/**
		 * wp_template_loader.
		 *
		 * @author  Unknown
		 * @since   v0.0.1
		 * @version v1.0.0  Friday, October 22nd, 2021.
		 * @version v1.0.1  Monday, August 4th, 2025.
		 * @access  private static
		 * @return  void
		 */
		private static function wp_template_loader() {
			// Show proper error message instead of loading theme template
			// This provides better security by not revealing the custom login URL
			wp_die(
				'Access Denied: Unauthorized access to the admin area is prohibited.',
				'Access Denied',
				array( 'response' => 403 )
			);
		}

		/**
		 * new_login_slug.
		 *
		 * @since v0.0.1
		 * @access public
		 * @return string|false Custom login slug, or false when not configured.
		 */
		public static function new_login_slug() {
			$settings = wf_sn_cf::get_options();

			if ( ! empty( $settings['change_login_url'] ) && ! empty( $settings['new_login_url'] ) ) {
				return $settings['new_login_url'];
			}
			return false;
		}

		/**
		 * Expected request path for the custom login URL (handles subdirectory installs).
		 *
		 * @since 5.287
		 * @return string Path such as /my-login or /subdir/my-login; empty when not configured.
		 */
		private static function get_custom_login_path() {
			$slug = self::new_login_slug();
			if ( ! $slug ) {
				return '';
			}

			$home_path = wp_parse_url( home_url( '/' ), PHP_URL_PATH );
			if ( ! is_string( $home_path ) ) {
				$home_path = '';
			}
			$home_path = untrailingslashit( $home_path );
			if ( '' === $home_path || '/' === $home_path ) {
				return '/' . $slug;
			}

			return $home_path . '/' . $slug;
		}

		/**
		 * Request path from REQUEST_URI (no query string).
		 *
		 * @since 5.287
		 * @return string
		 */
		private static function get_request_path() {
			$request_uri = isset( $_SERVER['REQUEST_URI'] ) ? wp_unslash( $_SERVER['REQUEST_URI'] ) : '';
			$path        = wp_parse_url( $request_uri, PHP_URL_PATH );

			return is_string( $path ) ? $path : '';
		}

		/**
		 * Whether a URL path matches the configured login slug (home/site paths + basename).
		 *
		 * @since 5.287
		 * @param string $path Request path.
		 * @return bool
		 */
		private static function path_matches_login_slug( $path ) {
			$slug = self::new_login_slug();
			if ( ! $slug || ! is_string( $path ) || '' === $path ) {
				return false;
			}

			$path = untrailingslashit( $path );

			$candidates = array( untrailingslashit( self::get_custom_login_path() ) );

			$site_base = wp_parse_url( site_url( '/' ), PHP_URL_PATH );
			if ( is_string( $site_base ) ) {
				$site_base = untrailingslashit( $site_base );
				if ( '' === $site_base || '/' === $site_base ) {
					$candidates[] = '/' . $slug;
				} else {
					$candidates[] = $site_base . '/' . $slug;
				}
			}

			if ( in_array( $path, $candidates, true ) ) {
				return true;
			}

			return basename( $path ) === $slug;
		}

		/**
		 * Whether the current front-end request targets the custom login slug.
		 *
		 * Path-style URLs (/my-login/) are always recognized so they match the admin Preview link,
		 * including when permalink structure is "Plain" (?slug).
		 *
		 * @since 5.287
		 * @return bool
		 */
		private static function is_custom_login_request() {
			$slug = self::new_login_slug();
			if ( ! $slug ) {
				return false;
			}

			if ( isset( $_GET[ $slug ] ) ) {
				return true;
			}

			return self::path_matches_login_slug( self::get_request_path() );
		}

		/**
		 * Whether the request URI targets wp-admin (with or without trailing slash).
		 *
		 * @since 5.287
		 * @param string $request_uri Raw REQUEST_URI.
		 * @return bool
		 */
		private static function is_wp_admin_uri( $request_uri ) {
			$path = wp_parse_url( $request_uri, PHP_URL_PATH );
			if ( ! is_string( $path ) || '' === $path ) {
				return false;
			}

			$path       = untrailingslashit( $path );
			$admin_path = wp_parse_url( admin_url(), PHP_URL_PATH );
			if ( ! is_string( $admin_path ) ) {
				return false;
			}
			$admin_path = untrailingslashit( $admin_path );

			if ( $path === $admin_path ) {
				return true;
			}

			$prefix = $admin_path . '/';

			return substr( $path, 0, strlen( $prefix ) ) === $prefix;
		}

		/**
		 * new_login_url.
		 *
		 * @since v0.0.1
		 * @access public
		 * @param string|null $scheme Optional URL scheme.
		 * @return string
		 */
		public static function new_login_url( $scheme = null ) {
			if ( get_option( 'permalink_structure' ) ) {
				return self::user_trailingslashit( home_url( '/', $scheme ) . self::new_login_slug() );
			} else {
				return home_url( '/', $scheme ) . '?' . self::new_login_slug();
			}
		}

		/**
		 * __construct.
		 *
		 * @author  Unknown
		 * @since   v0.0.1
		 * @version v1.0.0  Monday, October 18th, 2021.
		 * @access  public
		 * @return  void
		 */
		public function __construct() {

			add_action( 'admin_notices', array( __NAMESPACE__ . '\\SecNin_Rename_WP_Login', 'admin_notices' ) );
			add_action( 'network_admin_notices', array( __NAMESPACE__ . '\\SecNin_Rename_WP_Login', 'admin_notices' ) );
			if ( is_multisite() && ! function_exists( 'is_plugin_active_for_network' ) ) {
				require_once ABSPATH . '/wp-admin/includes/plugin.php';
			}

			add_action( 'plugins_loaded', array( __NAMESPACE__ . '\\SecNin_Rename_WP_Login', 'handle_login_routing' ), 0 );
			add_action( 'init', array( __NAMESPACE__ . '\\SecNin_Rename_WP_Login', 'handle_login_routing' ), 1 );
			add_action( 'wp_loaded', array( __NAMESPACE__ . '\\SecNin_Rename_WP_Login', 'wp_loaded' ) );
			add_action( 'template_redirect', array( __NAMESPACE__ . '\\SecNin_Rename_WP_Login', 'maybe_serve_login_on_404' ), 0 );
			add_filter( 'site_url', array( __NAMESPACE__ . '\\SecNin_Rename_WP_Login', 'site_url' ), 10, 4 );
			add_filter( 'network_site_url', array( __NAMESPACE__ . '\\SecNin_Rename_WP_Login', 'network_site_url' ), 10, 3 );
			add_filter( 'wp_redirect', array( __NAMESPACE__ . '\\SecNin_Rename_WP_Login', 'wp_redirect' ), 10, 2 );
			add_filter( 'site_option_welcome_email', array( __NAMESPACE__ . '\\SecNin_Rename_WP_Login', 'welcome_email' ) );

			add_action( 'init', array( __NAMESPACE__ . '\\SecNin_Rename_WP_Login', 'admin_gate_init' ), 0 );
			add_action( 'template_redirect', array( __NAMESPACE__ . '\\SecNin_Rename_WP_Login', 'admin_access_control' ), 1 );
		}

		/**
		 * Whether the current request may bypass Rename Login wp-admin blocking.
		 *
		 * Reuses Cloud Firewall temporary-login detection for supported plugins.
		 *
		 * @author  Lars Koudal
		 * @since   5.284
		 * @access  private static
		 * @return  bool
		 */
		private static function is_allowed_autologin_request() {
			$allowed = false;

			if ( class_exists( __NAMESPACE__ . '\Wf_sn_cf' ) && method_exists( __NAMESPACE__ . '\Wf_sn_cf', 'is_temporary_login_link' ) ) {
				$allowed = \WPSecurityNinja\Plugin\Wf_sn_cf::is_temporary_login_link();
			}

			/**
			 * Filter whether Rename Login should allow the current request through wp-admin gates.
			 *
			 * @param bool $allowed Whether the request is allowed.
			 */
			return (bool) apply_filters( 'securityninja_rename_login_allow_autologin', $allowed );
		}

		/**
		 * Whether the current request targets wp-admin/admin-post.php.
		 *
		 * @since 5.285
		 * @access private static
		 * @return bool
		 */
		private static function is_admin_post_request() {
			if ( ! isset( $_SERVER['REQUEST_URI'] ) ) {
				return false;
			}

			$uri_path = wp_parse_url( wp_unslash( $_SERVER['REQUEST_URI'] ), PHP_URL_PATH );
			if ( ! is_string( $uri_path ) ) {
				return false;
			}

			$admin_post_path = wp_parse_url( admin_url( 'admin-post.php' ), PHP_URL_PATH );
			if ( ! is_string( $admin_post_path ) ) {
				return false;
			}

			return untrailingslashit( $uri_path ) === untrailingslashit( $admin_post_path );
		}

		/**
		 * Whether an unauthenticated admin-post request should bypass Rename Login wp-admin gates.
		 *
		 * Allows only actions registered for logged-out users via admin_post_nopriv_{$action}.
		 *
		 * @since 5.285
		 * @access private static
		 * @return bool
		 */
		private static function is_allowed_public_admin_post_request() {
			if ( ! self::is_admin_post_request() ) {
				return false;
			}

			if ( ! isset( $_REQUEST['action'] ) ) {
				return false;
			}

			$action = sanitize_key( wp_unslash( $_REQUEST['action'] ) );
			if ( '' === $action ) {
				return false;
			}

			return has_action( 'admin_post_nopriv_' . $action ) !== false;
		}

		/**
		 * Whether the current request may bypass Rename Login wp-admin blocking.
		 *
		 * @since 5.285
		 * @access private static
		 * @return bool
		 */
		private static function should_bypass_wp_admin_gate() {
			if ( self::is_allowed_autologin_request() ) {
				return true;
			}

			if ( self::is_allowed_public_admin_post_request() ) {
				return true;
			}

			// admin-post.php is validated by WordPress core after plugins load; do not block early at init.
			if ( self::is_admin_post_request() ) {
				return true;
			}

			return false;
		}

		/**
		 * Admin access control - blocks unauthorized wp-admin access
		 *
		 * @author  Lars Koudal
		 * @since   v0.0.1
		 * @version v1.0.0  Monday, August 4th, 2025.
		 * @version v1.0.1  Monday, August 4th, 2025.
		 * @version v1.0.2  Monday, August 4th, 2025.
		 * @access  public static
		 * @return  void
		 */
		public static function admin_access_control() {
			if ( ! self::is_active() ) {
				return;
			}

			// Check if we're accessing wp-admin and user is not authenticated
			// Also check if we're not doing AJAX, cron, or REST API requests
			if ( is_admin() && ! wp_doing_ajax() && ! wp_doing_cron() && ! defined( 'REST_REQUEST' ) ) {

				// Use a more robust authentication check
				$current_user     = wp_get_current_user();
				$is_authenticated = $current_user->exists() && $current_user->ID > 0;

				// Also check for valid auth cookies as a backup
				if ( ! $is_authenticated ) {
					$auth_cookie = wp_parse_auth_cookie( '', 'logged_in' );
					if ( $auth_cookie && ! empty( $auth_cookie['username'] ) ) {
						$is_authenticated = true;
					}
				}

				// Only block if user is not authenticated
				if ( ! $is_authenticated ) {
					if ( self::should_bypass_wp_admin_gate() ) {
						return;
					}

					$current_user_ip = \WPSecurityNinja\Plugin\Wf_sn_cf::get_user_ip();
					$ua_string       = '';
					if ( isset( $_SERVER['HTTP_USER_AGENT'] ) ) {
						$ua_string = sanitize_text_field( $_SERVER['HTTP_USER_AGENT'] );
					}

					$request_uri = isset( $_SERVER['REQUEST_URI'] ) ? $_SERVER['REQUEST_URI'] : '';

					// Check if visitor is blocked (country blocks, IP bans, etc.) before showing admin protection
					// This ensures redirect URL setting works for blocked visitors accessing wp-admin
					if ( class_exists( __NAMESPACE__ . '\Wf_sn_cf' ) ) {
						$cf_options = \WPSecurityNinja\Plugin\Wf_sn_cf::get_options();

						// Only check blocking if firewall is active
						if ( isset( $cf_options['active'] ) && 1 === (int) $cf_options['active'] ) {
							$reason = \WPSecurityNinja\Plugin\Wf_sn_cf::is_banned_ip( $current_user_ip );

							if ( $reason ) {
								// Check if this is a country-based ban
								$is_country_ban = ( strpos( $reason, 'Country is blocked' ) !== false );

								// Special handling for country bans with login-only mode
								// If "Only block these countries from login functionality" is enabled:
								// - Country-blocked users can view the site
								// - But they should see admin protection message (NOT redirect) when accessing wp-admin
								if ( $is_country_ban && isset( $cf_options['countryblock_loginonly'] ) && $cf_options['countryblock_loginonly'] ) {
									// Country blocking is login-only mode - show admin protection message, don't redirect.
									$fall_through = true;
								} elseif ( $is_country_ban ) {
									// Country ban without login-only mode - block from entire site
									$should_block = true;
									if ( $should_block ) {
										\WPSecurityNinja\Plugin\Wf_sn_cf::update_blocked_count( $current_user_ip );

										$data = array(
											'user_agent'  => $ua_string,
											'ip'          => $current_user_ip,
											'reason'      => $reason,
											'request_uri' => $request_uri,
										);

										// Log the event BEFORE calling kill_request() (following existing pattern)
										wf_sn_el_modules::log_event( 'security_ninja', 'do_init_action', 'Blocked.', $data, null, $current_user_ip );
										wp_clear_auth_cookie();
										\WPSecurityNinja\Plugin\Wf_sn_cf::kill_request( $current_user_ip, $reason, null, true );
										exit();
									}
								} else {
									// For other ban types (IP bans, global blocks, etc.) - block /wp-admin/
									$should_block = true;
									if ( $should_block ) {
										\WPSecurityNinja\Plugin\Wf_sn_cf::update_blocked_count( $current_user_ip );

										$data = array(
											'user_agent'  => $ua_string,
											'ip'          => $current_user_ip,
											'reason'      => $reason,
											'request_uri' => $request_uri,
										);

										// Log the event BEFORE calling kill_request() (following existing pattern)
										wf_sn_el_modules::log_event( 'security_ninja', 'do_init_action', 'Blocked.', $data, null, $current_user_ip );

										wp_clear_auth_cookie();
										\WPSecurityNinja\Plugin\Wf_sn_cf::kill_request( $current_user_ip, $reason, null, true );
										exit();
									}
								}
							}
						}
					}

					// If not blocked, show admin protection message
					$extraarr = array(
						'ip'          => $current_user_ip,
						'user_agent'  => $ua_string,
						'request_uri' => $request_uri,
					);

					// Log the unauthorized access attempt
					wf_sn_el_modules::log_event( 'security_ninja', 'attempted_access_to_wp_admin_url', 'User tried to visit wp-admin URL', $extraarr );

					// Show generic error message without revealing the custom login URL
					wp_die(
						'Access Denied: Unauthorized access to the admin area is prohibited.',
						'Access Denied',
						array( 'response' => 403 )
					);
				}
			}
		}

		/**
		 * admin_gate_init - block unauthenticated access to wp-admin early (before core redirect)
		 *
		 * @author  Lars Koudal
		 * @since   v0.0.1
		 * @version v1.0.0  Wednesday, August 27th, 2025.
		 * @access  public static
		 * @return  void
		 */
		public static function admin_gate_init() {
			if ( ! self::is_active() ) {
				return;
			}
			// Skip AJAX/CRON/REST/CLI
			if ( wp_doing_ajax() || wp_doing_cron() || defined( 'REST_REQUEST' ) || defined( 'WP_CLI' ) ) {
				return;
			}

			// Detect direct admin requests early
			$uri = isset( $_SERVER['REQUEST_URI'] ) ? wp_unslash( $_SERVER['REQUEST_URI'] ) : '';
			if ( $uri && self::is_wp_admin_uri( $uri ) ) {
				if ( ! is_user_logged_in() ) {
					if ( self::should_bypass_wp_admin_gate() ) {
						return;
					}

					$current_user_ip = \WPSecurityNinja\Plugin\Wf_sn_cf::get_user_ip();
					$ua_string       = '';
					if ( isset( $_SERVER['HTTP_USER_AGENT'] ) ) {
						$ua_string = sanitize_text_field( $_SERVER['HTTP_USER_AGENT'] );
					}

					// Check if visitor is blocked (country blocks, IP bans, etc.) before showing admin protection
					// This ensures redirect URL setting works for blocked visitors accessing wp-admin
					if ( class_exists( __NAMESPACE__ . '\Wf_sn_cf' ) ) {
						$cf_options = \WPSecurityNinja\Plugin\Wf_sn_cf::get_options();

						// Only check blocking if firewall is active
						if ( isset( $cf_options['active'] ) && 1 === (int) $cf_options['active'] ) {
							$reason = \WPSecurityNinja\Plugin\Wf_sn_cf::is_banned_ip( $current_user_ip );

							if ( $reason ) {
								// Check if this is a country-based ban
								$is_country_ban = ( strpos( $reason, 'Country is blocked' ) !== false );

								// Special handling for country bans with login-only mode
								// If "Only block these countries from login functionality" is enabled:
								// - Country-blocked users can view the site
								// - But they should see admin protection message (NOT redirect) when accessing wp-admin
								if ( $is_country_ban && isset( $cf_options['countryblock_loginonly'] ) && $cf_options['countryblock_loginonly'] ) {
									// Country blocking is login-only mode - show admin protection message, don't redirect.
									$fall_through = true;
								} elseif ( $is_country_ban ) {
									// Country ban without login-only mode - block from entire site
									$should_block = true;
									if ( $should_block ) {
										\WPSecurityNinja\Plugin\Wf_sn_cf::update_blocked_count( $current_user_ip );

										$data = array(
											'user_agent'  => $ua_string,
											'ip'          => $current_user_ip,
											'reason'      => $reason,
											'request_uri' => $uri,
										);

										// Log the event BEFORE calling kill_request() (following existing pattern)
										wf_sn_el_modules::log_event( 'security_ninja', 'do_init_action', 'Blocked.', $data, null, $current_user_ip );
										wp_clear_auth_cookie();
										\WPSecurityNinja\Plugin\Wf_sn_cf::kill_request( $current_user_ip, $reason, null, true );
										exit();
									}
								} else {
									// For other ban types (IP bans, global blocks, etc.) - block /wp-admin/
									$should_block = true;
									if ( $should_block ) {
										\WPSecurityNinja\Plugin\Wf_sn_cf::update_blocked_count( $current_user_ip );

										$data = array(
											'user_agent'  => $ua_string,
											'ip'          => $current_user_ip,
											'reason'      => $reason,
											'request_uri' => $uri,
										);

										// Log the event BEFORE calling kill_request() (following existing pattern)
										wf_sn_el_modules::log_event( 'security_ninja', 'do_init_action', 'Blocked.', $data, null, $current_user_ip );
										wp_clear_auth_cookie();
										\WPSecurityNinja\Plugin\Wf_sn_cf::kill_request( $current_user_ip, $reason, null, true );
										exit();
									}
								}
							}
						}
					}

					// If not blocked, show admin protection message
					$extraarr = array(
						'ip'          => $current_user_ip,
						'user_agent'  => $ua_string,
						'request_uri' => $uri,
					);
					wf_sn_el_modules::log_event( 'security_ninja', 'attempted_access_to_wp_admin_url', 'User tried to visit wp-admin URL', $extraarr );
					wp_die(
						'Access Denied: Unauthorized access to the admin area is prohibited.',
						'Access Denied',
						array( 'response' => 403 )
					);
				}
			}
		}

		/**
		 * Whether Rename Login is enabled (Login Protection settings; Cloud Firewall active is not required).
		 *
		 * @since   v0.0.1
		 * @access  private static
		 * @return  bool
		 */
		private static function is_active() {
			if ( ! class_exists( __NAMESPACE__ . '\wf_sn_cf' ) ) {
				return false;
			}

			return false !== self::new_login_slug();
		}

		/**
		 * admin_notices.
		 *
		 * @author  Lars Koudal
		 * @since   v0.0.1
		 * @version v1.0.0  Friday, March 11th, 2022.
		 * @access  public static
		 * @return  void
		 */
		public static function admin_notices() {
			global $pagenow;
			if ( ! self::is_active() ) {
				return;
			}
			if ( \PAnD::is_admin_notice_active( 'wf-sn-notice-newlogin-forever' ) ) {
				if ( ! is_network_admin() && 'options-permalink.php' === $pagenow && isset( $_GET['settings-updated'] ) ) {
					/* translators: %s: login URL */
					echo '<div data-dismissible="wf-sn-notice-newlogin-forever" class="secnin-notice notice notice-success is-dismissible"><p>' . sprintf( esc_html__( 'Your login page is now here: %s. Bookmark this page!', 'security-ninja' ), '<strong><a href="' . esc_url( self::new_login_url() ) . '">' . esc_html( esc_url( self::new_login_url() ) ) . '</a></strong>' ) . '</p></div>';
				}
			}
		}

		/**
		 * Route custom login slug and block direct wp-login.php access.
		 *
		 * @since v0.0.1
		 * @return void
		 */
		public static function handle_login_routing() {
			global $pagenow;

			if ( ! self::is_active() ) {
				return;
			}

			remove_action( 'template_redirect', 'wp_redirect_admin_locations', 1000 );

			$request_uri = isset( $_SERVER['REQUEST_URI'] ) ? wp_unslash( $_SERVER['REQUEST_URI'] ) : '';
			$request     = wp_parse_url( $request_uri );
			$path        = isset( $request['path'] ) ? $request['path'] : '';

			if (
				! is_multisite() && (
					strpos( $request_uri, 'wp-signup' ) !== false ||
					strpos( $request_uri, 'wp-activate' ) !== false
				)
			) {
				wp_die( 'Not activated.' );
			}

			// Only intercept direct access to wp-login.php, not WordPress core redirects
			// Check if this is a direct request to wp-login.php (not a redirect)
			$is_direct_access = (
				strpos( $request_uri, 'wp-login.php' ) !== false ||
				( ! empty( $path ) && untrailingslashit( $path ) === site_url( 'wp-login', 'relative' ) )
			);

			// Don't intercept if this is admin, AJAX, cron, or if there's a redirect happening
			if ( $is_direct_access && ! is_admin() && ! wp_doing_ajax() && ! wp_doing_cron() && ! defined( 'DOING_AUTOSAVE' ) ) {
				// Check if this might be a WordPress core redirect (has referer from wp-admin)
				$referer = wp_get_referer();
				if ( $referer && strpos( $referer, 'wp-admin' ) !== false ) {
					// This is likely a WordPress core redirect from wp-admin to wp-login.php
					// Don't intercept it - let WordPress handle the redirect
					return;
				}

				// This is a direct access to wp-login.php - intercept it
				self::$wp_login_php     = true;
				$_SERVER['REQUEST_URI'] = self::user_trailingslashit( '/' . str_repeat( '-/', 10 ) );
				$pagenow                = 'index.php';
			} elseif ( self::is_custom_login_request() ) {
				$pagenow = 'wp-login.php';
			}
		}

		/**
		 * wp_loaded.
		 *
		 * @author  Unknown
		 * @since   v0.0.1
		 * @version v1.0.0  Monday, October 18th, 2021.
		 * @access  public
		 * @return  void
		 */
		public static function wp_loaded() {
			global $pagenow;

			if ( ! self::is_active() ) {
				return;
			}

			$request_uri = isset( $_SERVER['REQUEST_URI'] ) ? wp_unslash( $_SERVER['REQUEST_URI'] ) : '';
			$request     = wp_parse_url( $request_uri );
			$path        = isset( $request['path'] ) ? $request['path'] : '';

			if (
				'wp-login.php' === $pagenow &&
				self::user_trailingslashit( $path ) !== $path &&
				get_option( 'permalink_structure' )
			) {
				wp_safe_redirect( self::user_trailingslashit( self::new_login_url() ) . ( ! empty( $_SERVER['QUERY_STRING'] ) ? '?' . $_SERVER['QUERY_STRING'] : '' ) );
				die;
			} elseif ( self::$wp_login_php ) {
				$referer       = wp_get_referer();
				$referer_path  = ( $referer && strpos( $referer, 'wp-activate.php' ) !== false ) ? parse_url( $referer, PHP_URL_PATH ) : '';
				$referer_query = ( $referer && strpos( $referer, 'wp-activate.php' ) !== false ) ? parse_url( $referer, PHP_URL_QUERY ) : '';
				if ( ! empty( $referer_query ) && ! empty( $referer_path ) && 'wp-activate.php' === basename( $referer_path ) ) {
					$referer_args = array();
					parse_str( $referer_query, $referer_args );

					$activation_key = ! empty( $referer_args['key'] ) ? sanitize_text_field( $referer_args['key'] ) : '';
					$result         = ! empty( $activation_key ) ? wpmu_activate_signup( $activation_key ) : null;
					if (
						$result &&
						is_wp_error( $result ) && (
							'already_active' === $result->get_error_code() ||
							'blog_taken' === $result->get_error_code()
						)
					) {
						wp_safe_redirect( self::new_login_url() . ( ! empty( $_SERVER['QUERY_STRING'] ) ? '?' . $_SERVER['QUERY_STRING'] : '' ) );
						die;
					}
				}

				$current_user_ip = \WPSecurityNinja\Plugin\Wf_sn_cf::get_user_ip();
				$ua_string       = '';
				if ( isset( $_SERVER['HTTP_USER_AGENT'] ) ) {
					$ua_string = sanitize_text_field( $_SERVER['HTTP_USER_AGENT'] );
				}
				$extraarr = array(
					'ip'         => $current_user_ip,
					'user_agent' => $ua_string,
				);

				wf_sn_el_modules::log_event( 'security_ninja', 'attempted_access_to_wplogin_php', 'User tried to visit wp-login.php', $extraarr );

				self::wp_template_loader();
			} elseif ( 'wp-login.php' === $pagenow ) {
				global $error, $interim_login, $action, $user_login;

				@require_once ABSPATH . 'wp-login.php';

				die;
			}
		}

		/**
		 * Fallback: serve wp-login when WordPress already resolved the request as a 404.
		 *
		 * @since 5.287
		 * @return void
		 */
		public static function maybe_serve_login_on_404() {
			if ( ! self::is_active() || ! is_404() ) {
				return;
			}

			if ( ! self::is_custom_login_request() ) {
				return;
			}

			global $pagenow;
			$pagenow = 'wp-login.php';

			require_once ABSPATH . 'wp-login.php';
			exit;
		}

		/**
		 * site_url.
		 *
		 * @author  Unknown
		 * @since   v0.0.1
		 * @version v1.0.0  Monday, May 2nd, 2022.
		 * @access  public static
		 * @param   mixed   $url
		 * @param   mixed   $path
		 * @param   mixed   $scheme
		 * @param   mixed   $blog_id
		 * @return  mixed
		 */
		public static function site_url( $url, $path, $scheme, $blog_id ) {
			if ( ! self::is_active() ) {
				return $url;
			}
			return self::filter_wp_login_php( $url, $scheme );
		}

		/**
		 * network_site_url.
		 *
		 * @author  Unknown
		 * @since   v0.0.1
		 * @version v1.0.0  Monday, May 2nd, 2022.
		 * @access  public static
		 * @param   mixed   $url
		 * @param   mixed   $path
		 * @param   mixed   $scheme
		 * @return  mixed
		 */
		public static function network_site_url( $url, $path, $scheme ) {
			if ( ! self::is_active() ) {
				return $url;
			}
			return self::filter_wp_login_php( $url, $scheme );
		}

		/**
		 * wp_redirect.
		 *
		 * @author  Unknown
		 * @since   v0.0.1
		 * @version v1.0.0  Monday, May 2nd, 2022.
		 * @version v1.0.1  Monday, August 4th, 2025.
		 * @access  public static
		 * @param   mixed   $location
		 * @param   mixed   $status
		 * @return  mixed
		 */
		public static function wp_redirect( $location, $status ) {
			if ( ! self::is_active() ) {
				return $location;
			}
			// Only filter wp-login.php URLs, not wp-admin redirects
			// This prevents redirect loops and maintains security through obscurity
			if ( strpos( $location, 'wp-login.php' ) !== false ) {
				return self::filter_wp_login_php( $location );
			}

			return $location;
		}

		/**
		 * filter_wp_login_php.
		 *
		 * @author  Unknown
		 * @since   v0.0.1
		 * @version v1.0.0  Monday, October 18th, 2021.
		 * @access  public
		 * @param   mixed   $url
		 * @param   mixed   $scheme Default: null
		 * @return  mixed
		 */
		public static function filter_wp_login_php( $url, $scheme = null ) {
			if ( strpos( $url, 'wp-login.php' ) !== false ) {
				if ( is_ssl() ) {
					$scheme = 'https';
				}

				$args = explode( '?', $url );

				if ( isset( $args[1] ) ) {
					parse_str( $args[1], $args );
					$url = add_query_arg( $args, self::new_login_url( $scheme ) );
				} else {
					$url = self::new_login_url( $scheme );
				}
			}

			return $url;
		}

		/**
		 * Change the welcome email on Multisite
		 *
		 * @author  Unknown
		 * @since   v0.0.1
		 * @version v1.0.0  Monday, October 18th, 2021.
		 * @access  public
		 * @param   mixed   $value
		 * @return  mixed
		 */
		public static function welcome_email( $value ) {
			$settings = wf_sn_cf::get_options();
			if ( isset( $settings['change_login_url'] ) && $settings['change_login_url'] && ( '' !== $settings['new_login_url'] ) ) {
				return str_replace( 'wp-login.php', trailingslashit( self::new_login_slug() ), $value );
			}
			return $value;
		}
	}

	new SecNin_Rename_WP_Login();
}
