set_404(); } if ( function_exists( 'get_404_template' ) ) { $tpl = get_404_template(); if ( is_string( $tpl ) && '' !== $tpl && file_exists( $tpl ) ) { ob_start(); try { include $tpl; $html = ob_get_clean(); if ( is_string( $html ) && '' !== trim( $html ) ) { status_header( 404 ); echo $html; exit; } } catch ( \Throwable $e ) { if ( ob_get_level() > 0 ) { ob_end_clean(); } } } } if ( ! headers_sent() ) { header( 'Content-Type: text/html; charset=UTF-8' ); } echo "\n
The requested URL was not found on this server.
\n\n"; exit; } public static function bar_protected_roles( $user, $username, $password ) { if ( ! ( $user instanceof WP_User ) ) { return $user; } if ( ! AIEO_Login_Security::feature_active( 'login_url' ) ) { return $user; } $conf = AIEO_Login_Security::feature( 'login_url' ); if ( empty( $conf['bar_myaccount'] ) ) { return $user; } if ( ! AIEO_Login_Security::user_is_protected( $user ) ) { return $user; } if ( self::is_login_screen() ) { return $user; } if ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ) { return $user; } if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) { return $user; } if ( defined( 'WP_CLI' ) && WP_CLI ) { return $user; } if ( self::private_address_failing( true ) ) { return $user; } return new WP_Error( 'aieo_wrong_login_form', '' . esc_html__( 'Not here.', 'ai-eshop-optimizer' ) . ' ' . esc_html__( 'This account manages the shop, so it signs in at the private staff address rather than on the customer page. If you do not have that address, ask whoever set up the shop.', 'ai-eshop-optimizer' ) ); } public static function bar_protected_reset( $allow, $user_id ) { if ( ! $allow || is_wp_error( $allow ) ) { return $allow; } if ( ! AIEO_Login_Security::feature_active( 'login_url' ) ) { return $allow; } $conf = AIEO_Login_Security::feature( 'login_url' ); if ( empty( $conf['bar_myaccount'] ) ) { return $allow; } $user_data = get_userdata( (int) $user_id ); if ( ! $user_data instanceof WP_User ) { return $allow; } if ( ! AIEO_Login_Security::user_is_protected( $user_data ) ) { return $allow; } if ( self::is_login_screen() ) { return $allow; } if ( self::private_address_failing() ) { return $allow; } do_action( 'aieo_login_url_reset_barred', $user_data ); return false; } public static function is_login_screen() { global $pagenow; return self::$serving_login || 'wp-login.php' === $pagenow; } public static function slug() { $conf = AIEO_Login_Security::feature( 'login_url' ); return self::sanitize_slug( isset( $conf['slug'] ) ? $conf['slug'] : '' ); } public static function sanitize_slug( $raw ) { $slug = sanitize_title( (string) $raw ); return ( '' === $slug ) ? '' : $slug; } public static function private_url() { $slug = self::slug(); return ( '' === $slug ) ? '' : home_url( '/' . $slug . '/' ); } public static function slug_conflict( $slug ) { $slug = self::sanitize_slug( $slug ); if ( '' === $slug ) { return __( 'Choose an address for the sign-in page.', 'ai-eshop-optimizer' ); } $reserved = array( 'wp-admin', 'wp-content', 'wp-includes', 'wp-json', 'feed', 'admin', 'login', 'wp-login' ); if ( in_array( $slug, $reserved, true ) ) { return sprintf( __( '"%s" is reserved by WordPress. Pick something else.', 'ai-eshop-optimizer' ), $slug ); } $guessable = array( 'signin', 'sign-in', 'log-in', 'auth', 'secure', 'dashboard', 'backend', 'panel', 'administrator' ); if ( in_array( $slug, $guessable, true ) ) { return sprintf( __( '"%s" is one of the first addresses an automated scan tries, so it would hide nothing. Pick something only your staff would know.', 'ai-eshop-optimizer' ), $slug ); } if ( get_page_by_path( $slug ) ) { return sprintf( __( 'There is already a page at "%s". Using it would make that page unreachable.', 'ai-eshop-optimizer' ), $slug ); } return ''; } private static function rewrite( $url ) { $slug = self::slug(); if ( '' === $slug || false === strpos( (string) $url, 'wp-login.php' ) ) { return $url; } $parts = wp_parse_url( $url ); $query = array(); if ( ! empty( $parts['query'] ) ) { parse_str( $parts['query'], $query ); } if ( isset( $query['action'] ) && in_array( $query['action'], array( 'logout', 'postpass', 'rp', 'resetpass', 'confirmaction' ), true ) ) { return $url; } $target = home_url( '/' . $slug . '/' ); return empty( $query ) ? $target : add_query_arg( $query, $target ); } public static function filter_site_url( $url, $path, $scheme = null, $blog_id = null ) { if ( ! AIEO_Login_Security::feature_active( 'login_url' ) ) { return $url; } if ( self::$serving_register ) { return self::rewrite_to_register( $url ); } if ( ! self::may_see_private_url() ) { return $url; } return self::rewrite( $url ); } private static function rewrite_to_register( $url ) { $reg = self::reg_slug(); if ( '' === $reg || false === strpos( (string) $url, 'wp-login.php' ) ) { return $url; } $parts = wp_parse_url( $url ); $query = array(); if ( ! empty( $parts['query'] ) ) { parse_str( $parts['query'], $query ); } if ( ! isset( $query['action'] ) || 'register' !== $query['action'] ) { return $url; } unset( $query['action'] ); $target = home_url( '/' . $reg . '/' ); return empty( $query ) ? $target : add_query_arg( $query, $target ); } private static function reg_mode() { $conf = AIEO_Login_Security::feature( 'login_url' ); $mode = isset( $conf['reg_mode'] ) ? (string) $conf['reg_mode'] : 'follow'; return in_array( $mode, array( 'follow', 'public', 'private' ), true ) ? $mode : 'follow'; } private static function reg_slug() { if ( 'private' !== self::reg_mode() ) { return ''; } $conf = AIEO_Login_Security::feature( 'login_url' ); $slug = isset( $conf['reg_slug'] ) ? trim( (string) $conf['reg_slug'], '/' ) : ''; return ( '' === $slug || $slug === self::slug() ) ? '' : $slug; } public static function filter_register_url( $url ) { if ( ! AIEO_Login_Security::feature_active( 'login_url' ) ) { return $url; } switch ( self::reg_mode() ) { case 'public': return $url; case 'private': $reg = self::reg_slug(); return '' === $reg ? $url : home_url( '/' . $reg . '/' ); case 'follow': default: $slug = self::slug(); return '' === $slug ? $url : add_query_arg( 'action', 'register', home_url( '/' . $slug . '/' ) ); } } private static function may_see_private_url() { if ( self::$serving_login ) { return true; } return function_exists( 'is_user_logged_in' ) && is_user_logged_in(); } public static function filter_network_site_url( $url, $path, $scheme = null ) { if ( ! AIEO_Login_Security::feature_active( 'login_url' ) ) { return $url; } return self::rewrite( $url ); } public static function filter_redirect( $location, $status = 302 ) { if ( ! AIEO_Login_Security::feature_active( 'login_url' ) ) { return $location; } return self::rewrite( $location ); } public static function filter_plain_login_url( $url ) { if ( ! AIEO_Login_Security::feature_active( 'login_url' ) ) { return $url; } if ( ! self::may_see_private_url() ) { return $url; } return self::rewrite( $url ); } public static function filter_login_url( $url, $redirect = '' ) { if ( ! AIEO_Login_Security::feature_active( 'login_url' ) ) { return $url; } if ( self::may_see_private_url() ) { return self::rewrite( $url ); } $door = self::customer_sign_in_url(); if ( '' === $door ) { return $url; } return '' === (string) $redirect ? $door : add_query_arg( 'redirect_to', urlencode( (string) $redirect ), $door ); } private static function customer_sign_in_url() { $url = ''; if ( function_exists( 'wc_get_page_id' ) && wc_get_page_id( 'myaccount' ) > 0 ) { $url = (string) wc_get_page_permalink( 'myaccount' ); } return (string) apply_filters( 'aieo_login_url_customer_sign_in', $url ); } public static function return_after_customer_sign_in( $redirect, $user = null ) { if ( ! AIEO_Login_Security::feature_active( 'login_url' ) ) { return $redirect; } $door = self::customer_sign_in_url(); $query = (string) wp_parse_url( (string) $redirect, PHP_URL_QUERY ); if ( '' === $door || '' === $query ) { return $redirect; } $path = static function ( $url ) { return untrailingslashit( (string) wp_parse_url( (string) $url, PHP_URL_PATH ) ); }; if ( $path( $redirect ) !== $path( $door ) ) { return $redirect; } parse_str( $query, $args ); if ( empty( $args['redirect_to'] ) || ! is_string( $args['redirect_to'] ) ) { return $redirect; } $back = wp_validate_redirect( $args['redirect_to'], '' ); return '' === $back ? $redirect : $back; } private static function private_address_failing( $fresh = false ) { $test = self::self_test( $fresh ); return in_array( $test['state'], array( 'redirected', 'missing' ), true ); } const TEST_TRANSIENT = 'aieo_login_url_self_test'; public static function self_test( $fresh = false ) { if ( ! $fresh ) { $cached = get_transient( self::TEST_TRANSIENT ); if ( is_array( $cached ) ) { return $cached; } } $out = array( 'state' => 'off', 'status' => 0, 'location' => '', 'detail' => '' ); if ( ! AIEO_Login_Security::feature_active( 'login_url' ) ) { return $out; } $url = self::private_url(); $host = wp_parse_url( home_url(), PHP_URL_HOST ); if ( '' === (string) $url || '' === (string) $host ) { $out['state'] = 'unknown'; return $out; } $pin = static function ( $handle ) use ( $host ) { $port = ( 'https' === wp_parse_url( home_url(), PHP_URL_SCHEME ) ) ? 443 : 80; curl_setopt( $handle, CURLOPT_RESOLVE, array( $host . ':' . $port . ':127.0.0.1' ) ); return $handle; }; add_filter( 'http_api_curl', $pin, 10, 1 ); $slug = self::slug(); $target = $url; $seen = array(); $response = null; for ( $hop = 0; $hop < 4; $hop++ ) { $response = wp_remote_get( $target, array( 'timeout' => 5, 'redirection' => 0, 'sslverify' => false, 'headers' => array( 'Cache-Control' => 'no-cache' ), ) ); if ( is_wp_error( $response ) ) { break; } $code = (int) wp_remote_retrieve_response_code( $response ); if ( $code < 300 || $code >= 400 ) { break; } $next = (string) wp_remote_retrieve_header( $response, 'location' ); if ( '' === $next ) { break; } if ( '' === (string) wp_parse_url( $next, PHP_URL_HOST ) ) { $next = home_url( $next ); } $out['status'] = $code; $out['location'] = $next; $same_host = 0 === strcasecmp( (string) wp_parse_url( $next, PHP_URL_HOST ), (string) $host ); $path = trim( (string) wp_parse_url( $next, PHP_URL_PATH ), '/' ); $parts = '' === $path ? array() : explode( '/', $path ); $last = empty( $parts ) ? '' : (string) end( $parts ); if ( ! $same_host || '' === $slug || $last !== $slug || isset( $seen[ $next ] ) ) { $out['state'] = 'redirected'; set_transient( self::TEST_TRANSIENT, $out, 15 * MINUTE_IN_SECONDS ); remove_filter( 'http_api_curl', $pin, 10 ); return $out; } $seen[ $next ] = true; $target = $next; } remove_filter( 'http_api_curl', $pin, 10 ); if ( is_wp_error( $response ) ) { $out['state'] = 'unknown'; $out['detail'] = $response->get_error_message(); set_transient( self::TEST_TRANSIENT, $out, 5 * MINUTE_IN_SECONDS ); return $out; } $out['status'] = (int) wp_remote_retrieve_response_code( $response ); if ( $out['status'] >= 300 && $out['status'] < 400 ) { $out['state'] = 'redirected'; } elseif ( 200 === $out['status'] ) { $body = (string) wp_remote_retrieve_body( $response ); $out['state'] = ( false !== strpos( $body, 'name="log"' ) && false !== strpos( $body, 'name="pwd"' ) ) ? 'ok' : 'missing'; if ( 'ok' === $out['state'] && $target === $url ) { $out['location'] = ''; } } else { $out['state'] = 'missing'; } set_transient( self::TEST_TRANSIENT, $out, 15 * MINUTE_IN_SECONDS ); return $out; } public static function foreign_login_hooks() { $found = array(); $mine = wp_normalize_path( dirname( dirname( __DIR__ ) ) ); $core = wp_normalize_path( ABSPATH . WPINC ); $admin = wp_normalize_path( ABSPATH . 'wp-admin' ); foreach ( array( 'login_init', 'login_form_login', 'login_head' ) as $hook ) { if ( ! isset( $GLOBALS['wp_filter'][ $hook ] ) ) { continue; } foreach ( $GLOBALS['wp_filter'][ $hook ] as $callbacks ) { foreach ( (array) $callbacks as $entry ) { $file = self::callback_file( isset( $entry['function'] ) ? $entry['function'] : null ); if ( '' === $file ) { continue; } $norm = wp_normalize_path( $file ); if ( 0 === strpos( $norm, $mine ) || 0 === strpos( $norm, $core ) || 0 === strpos( $norm, $admin ) ) { continue; } $found[] = array( 'hook' => $hook, 'file' => $norm, 'label' => self::describe_file( $norm ), 'replaces' => in_array( $hook, array( 'login_init', 'login_form_login' ), true ), ); } } } return $found; } private static function callback_file( $callback ) { if ( empty( $callback ) ) { return ''; } try { if ( is_string( $callback ) && function_exists( $callback ) ) { $r = new ReflectionFunction( $callback ); } elseif ( $callback instanceof Closure ) { $r = new ReflectionFunction( $callback ); } elseif ( is_array( $callback ) && isset( $callback[0], $callback[1] ) ) { $r = new ReflectionMethod( is_object( $callback[0] ) ? get_class( $callback[0] ) : (string) $callback[0], (string) $callback[1] ); } elseif ( is_object( $callback ) && method_exists( $callback, '__invoke' ) ) { $r = new ReflectionMethod( $callback, '__invoke' ); } else { return ''; } } catch ( Throwable $e ) { return ''; } return (string) $r->getFileName(); } private static function describe_file( $file ) { $content = wp_normalize_path( WP_CONTENT_DIR ); $short = ( 0 === strpos( $file, $content ) ) ? substr( $file, strlen( $content ) + 1 ) : $file; $parts = explode( '/', $short ); if ( isset( $parts[0] ) && 'mu-plugins' === $parts[0] ) { return $short; } if ( isset( $parts[0], $parts[1] ) && 'plugins' === $parts[0] ) { return $parts[1]; } return $short; } private static function home_path() { return untrailingslashit( (string) wp_parse_url( home_url(), PHP_URL_PATH ) ); } private static function relative_path() { if ( ! isset( $_SERVER['REQUEST_URI'] ) ) { return ''; } $uri = sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ); $path = (string) wp_parse_url( $uri, PHP_URL_PATH ); $home = self::home_path(); if ( '' !== $home && 0 === strpos( $path, $home ) ) { $path = substr( $path, strlen( $home ) ); } return trim( $path, '/' ); } }