ring[] $hosts An array of allowed host names. * * @return string[] An array of allowed host names. */ add_filter( 'allowed_redirect_hosts', function ( array $hosts ) use ( $parsed_url ) { $hosts[] = $parsed_url; return $hosts; }, ); } wp_safe_redirect( $redirect_url ); } else { wp_safe_redirect( home_url( $this->get_model()->redirect_traffic_url ) ); } die; } if ( 'wp_page' === $this->get_model()->redirect_traffic ) { $id = $this->get_model()->redirect_traffic_page_id; $post = get_post( $id ); if ( is_object( $post ) ) { wp_safe_redirect( get_permalink( $post ) ); exit; } } // Handle user profile email change request. $this->handle_email_change_request(); wp_die( esc_html( $forbidden_message ) ); } /** * Safe way to get cached model. * * @return Model_Mask_Login */ private function get_model() { if ( is_object( $this->model ) ) { return $this->model; } return new Model_Mask_Login(); } /** * Provide data to the frontend via localized script. * * @param array $data Data collection is ready to passed. * * @return array Modified data array with added this controller data. */ public function script_data( array $data ): array { $data['mask_login'] = $this->data_frontend(); return $data; } /** * Redirects the user to the admin URL if the given URL is the home URL. * * @param string $url The URL to be redirected. * @param string $raw_url The raw URL. * @param object $user The user object. * * @return string The filtered URL after applying the 'defender_redirect_login' filter. */ public function redirect_login( $url, $raw_url, $user ) { if ( home_url() === $url ) { $url = admin_url(); } return apply_filters( 'defender_redirect_login', $url, $raw_url, $user ); } /** * Retrieves the site URL based on the provided parameters. * This function retrieves the site URL for the current or specified blog. If the blog ID is empty or not in a * multisite environment, it retrieves the site URL from the 'siteurl' option. Otherwise, it switches to the * specified blog, retrieves the site URL, and then restores the current blog. * * @param int|null $blog_id The blog ID in a multisite environment. Default is null. * @param string $path Additional path to append to the site URL. Default is an empty string. * @param string|null $scheme The scheme to use. Default is null. * * @return string The site URL with the specified parameters. */ private function get_site_url( $blog_id = null, $path = '', $scheme = null ) { if ( empty( $blog_id ) || ! is_multisite() ) { $url = get_option( 'siteurl' ); } else { switch_to_blog( $blog_id ); $url = get_option( 'siteurl' ); restore_current_blog(); } $url = set_url_scheme( $url, $scheme ); if ( $path && is_string( $path ) ) { $url .= '/' . ltrim( $path, '/' ); } /** * Filters the list of plugins for which 'site_url' filter should be skipped. * * @param array $plugins A list of plugin file paths relative to the plugin's directory. * * @since 4.1.0 */ $plugins = apply_filters( 'wd_mask_login_skip_site_url_filter', array( 'wp-ultimo/wp-ultimo.php' ) ); $skip_site_url_filter = false; if ( is_array( $plugins ) ) { foreach ( $plugins as $plugin ) { if ( is_plugin_active( $plugin ) || is_plugin_active_for_network( $plugin ) ) { $skip_site_url_filter = true; break; } } } if ( $skip_site_url_filter ) { return apply_filters( 'site_url', $url, $path, $scheme, $blog_id ); } else { return $url; } } /** * Removes settings for all submodules. */ public function remove_settings() { } /** * Delete all the data & the cache. */ public function remove_data() { } /** * Converts the current object state to an array. * * @return array The array representation of the object. */ public function to_array(): array { $model = new Model_Mask_Login(); [ $routes, $nonces ] = Route::export_routes( 'mask_login' ); return array( 'enabled' => $model->enabled, 'useable' => $model->is_active(), 'login_url' => $model->get_new_login_url(), 'endpoints' => $routes, 'nonces' => $nonces, ); } /** * Provides data for the dashboard widget. * * @return array An array of dashboard widget data. */ public function dashboard_widget(): array { $model = new Model_Mask_Login(); return array( 'model' => $model->export(), 'is_active' => $model->is_active(), 'is_mask_url_page_post_exists' => $model->is_mask_url_page_post_exists(), ); } /** * Provides data for the frontend. * * @return array An array of data for the frontend. */ public function data_frontend(): array { // Don't use cache because wrong url is displayed for forbidden slugs. $model = new Model_Mask_Login(); $data = array_merge( array( 'model' => $model->export(), 'is_active' => $model->is_active(), 'new_login_url' => $model->get_new_login_url(), 'notices' => $this->compatibility_notices, 'is_mask_url_empty' => $model->is_mask_url_empty(), 'is_mask_url_page_post_exists' => $model->is_mask_url_page_post_exists(), ), $this->dump_routes_and_nonces() ); if ( isset( $data['model']['redirect_traffic_page_id'] ) ) { $id = $data['model']['redirect_traffic_page_id']; $data['redirect_traffic_page_title'] = $id > 0 ? get_the_title( $id ) : ''; $data['redirect_traffic_page_url'] = $id > 0 ? get_the_permalink( $id ) : '#'; } return $data; } /** * Imports data into the model. * * @param array $data Data to be imported into the model. */ public function import_data( array $data ) { $model = $this->get_model(); $model->import( $data ); if ( $model->validate() ) { $model->save(); } } /** * Updates the welcome email for a specific site case. * * @param string $welcome_email The original welcome email content. * @param int $blog_id The ID of the site. * @param int $user_id The ID of the user. * @param string $password The user's password. * @param string $title The title of the welcome email. * @param array $meta Additional metadata for the welcome email. * * @return string The updated welcome email content. */ public function update_welcome_email_prosite_case( string $welcome_email, int $blog_id, int $user_id, string $password, string $title, array $meta ): string { $url = get_blogaddress_by_id( $blog_id ); $welcome_email = str_replace( $url . 'wp-login.php', $this->get_model()->get_new_login_url( rtrim( $url, '/' ) ), $welcome_email ); return $welcome_email; } /** * Updates the report logs link by adding a 'redirect_to' query parameter to the new login URL. * * @param string $logs_url The original logs URL. * @param string $email The email address. * * @return string The updated logs URL with the 'redirect_to' query parameter. */ public function update_report_logs_link( string $logs_url, string $email ): string { return add_query_arg( 'redirect_to', $logs_url, $this->get_model()->get_new_login_url() ); } /** * Replaces the password reset link in the given message with a new login URL that includes a token. * * @param string $message The original message containing the password reset link. * @param string $key The key used for the password reset link. * @param string $user_login The username of the user. * @param WP_User $user_data The user data. * * @return string The updated message with the new login URL. * @since 2.5.5 */ public function flywheel_change_password_message( string $message, string $key, string $user_login, WP_User $user_data ): string { $message = str_replace( network_site_url( "wp-login.php?action=rp&key=$key&login=" . rawurlencode( $user_login ), 'login' ), $this->get_model()->get_new_login_url( $this->get_site_url() ) . "?action=rp&key=$key&login=" . rawurlencode( $user_login ) . '&wd-ml-token=' . rawurlencode( $user_login ), $message ); return $message; } /** * Change redirect param of the link 'Lost your password?'. * * @param string $lostpassword_redirect The original redirect URL. * * @return string */ public function change_lostpassword_redirect( string $lostpassword_redirect ): string { return $this->get_model()->get_new_login_url( $this->get_site_url() ) . $this->get_permalink_separator() . 'checkemail=confirm'; } /** * Handle user profile email change request. * * @return void */ private function handle_email_change_request() { // If it is not for admin request. if ( ! is_admin() ) { return; } // If `IS_PROFILE_PAGE` constant is defined. if ( ! defined( 'IS_PROFILE_PAGE' ) ) { return; } // If request is not for profile page. if ( ! IS_PROFILE_PAGE ) { return; } // If query data is not set. $hash = defender_get_data_from_request( 'newuseremail', 'g' ); if ( ! isset( $hash ) ) { return; } global $wpdb; $like = '%' . $wpdb->esc_like( $hash ) . '%'; $meta_key = $wpdb->get_var( // phpcs:ignore WordPress.DB.DirectDatabaseQuery $wpdb->prepare( "SELECT meta_key FROM {$wpdb->usermeta} WHERE meta_value LIKE %s", $like ) ); // Hash not found. if ( '_new_email' !== $meta_key ) { return; } // Everything good, now redirect user to login page. $current_url = add_query_arg( defender_get_data_from_request( null, 'g' ), admin_url( 'profile.php' ) ); $redirect_url = esc_url( wp_login_url( $current_url ) ); wp_safe_redirect( $redirect_url ); die(); } /** * Exports strings. * * @return array An array of strings. */ public function export_strings(): array { return array( $this->get_model()->is_active() ? esc_html__( 'Active', 'wpdef' ) : esc_html__( 'Inactive', 'wpdef' ), ); } /** * Generates configuration strings based on the provided configuration and * whether the product is a pro version. * * @param array $config Configuration data. * @param bool $is_pro Indicates if the product is a pro version. * * @return array Returns an array of configuration strings. */ public function config_strings( array $config, bool $is_pro ): array { return array( $config['enabled'] ? esc_html__( 'Active', 'wpdef' ) : esc_html__( 'Inactive', 'wpdef' ), ); } /** * Support for the password reset page on various hosting. * * @return void */ public function handle_password_reset(): void { // Get the email link. $action = defender_get_data_from_request( 'action', 'g' ); $key = wp_unslash( defender_get_data_from_request( 'key', 'r' ) ); $login = wp_unslash( defender_get_data_from_request( 'login', 'r' ) ); $wd_ml_token = defender_get_data_from_request( 'wd-ml-token', 'g' ); if ( isset( $action, $key, $login, $wd_ml_token ) && 'rp' === $action && $login === $wd_ml_token ) { $user = check_password_reset_key( $key, $login ); if ( ! is_wp_error( $user ) ) { $value = sprintf( '%s:%s', $login, $key ); set_site_transient( 'wd-rp-' . COOKIEHASH, $value, 2 * MINUTE_IN_SECONDS ); wp_safe_redirect( remove_query_arg( array( 'key', 'login', 'wd-ml-token' ) ) ); exit; } } $value = get_site_transient( 'wd-rp-' . COOKIEHASH ); // Process the data and display the result. if ( isset( $action ) && in_array( $action, array( 'rp', 'resetpass' ), true ) && isset( $value ) && 0 < strpos( $value, ':' ) ) { [ $login, $key ] = explode( ':', wp_unslash( $value ), 2 ); $user = check_password_reset_key( $key, $login ); if ( 'resetpass' === $action ) { delete_site_transient( 'wd-rp-' . COOKIEHASH ); } if ( ! is_wp_error( $user ) ) { $this->render_partial( 'mask-login/reset', array( 'user' => $user, ) ); exit; } } } /** * Check if a path is allowed without login masking. * * @param string $path Path to check. * * @return bool * @since 2.6.4 */ private function is_allowed_path( string $path ): bool { // Admin post requests to admin-post.php should be allowed. $allowed = 'wp-admin/admin-post.php' === $path && ! empty( defender_get_data_from_request( 'action', 'r' ) ); /** * Filter to allow whitelisting paths from login masking. * * @param bool $allowed Is current path allowed?. * @param string $path Path to check. * * @since 2.6.4 */ return apply_filters( 'wd_mask_login_is_allowed_path', $allowed, $path ); } /** * An endpoint for fetching Post/Page. * * @param Request $request Request data. * * @return void * @since 2.7.1 * @defender_route */ public function get_posts( Request $request ): void { $data = $request->get_data( array( 'per_page' => array( 'type' => 'int', 'sanitize' => 'sanitize_text_field', ), 'search' => array( 'type' => 'string', 'sanitize' => 'sanitize_text_field', ), ) ); $per_page = $data['per_page'] ?? 50; $search = $data['search'] ?? ''; add_filter( 'posts_where', array( $this, 'posts_where_title' ), 10, 2 ); $post_query = new WP_Query( array( 'post_type' => array( 'page', 'post' ), 'posts_per_page' => $per_page, 'search_by_post_title' => $search, 'post_status' => 'publish', 'orderby' => 'title', 'order' => 'ASC', ) ); remove_filter( 'posts_where', array( $this, 'posts_where_title' ), 10 ); $posts_array = $post_query->posts; $data = array(); foreach ( $posts_array as $post ) { $data[] = array( 'id' => $post->ID, 'name' => $post->post_title, 'url' => get_the_permalink( $post->ID ), ); } wp_send_json_success( $data ); } /** * Filter the WHERE clause of the query. * * @param string $where The WHERE clause of the query. * @param WP_Query $wp_query The query object. * * @return string $where * @since 2.7.1 */ public function posts_where_title( string $where, WP_Query $wp_query ): string { global $wpdb; $search_term = $wp_query->get( 'search_by_post_title' ); if ( ! empty( $search_term ) ) { $where .= ' AND ' . $wpdb->posts . '.post_title LIKE \'%' . esc_sql( $wpdb->esc_like( $search_term ) ) . '%\''; } return $where; } /** * Change the admin URL for sub sites. * * @param string $url The original URL. * @param string $path The path of the URL. * @param mixed $blog_id The ID of the blog. * * @return string The modified URL. */ public function change_subsites_admin_url( string $url, string $path, $blog_id ): string { if ( empty( $path ) && ! empty( $blog_id ) ) { $mask_url = trim( $this->model->mask_url ); if ( ! empty( $mask_url ) && $this->check_if_domain_is_mapped( $url ) ) { $url = str_replace( 'wp-admin', $mask_url, untrailingslashit( $url ) ); } } return $url; } /** * Check if domain is mapped. * * @param string $url The URL. * * @return bool */ public function check_if_domain_is_mapped( string $url ): bool { $is_mapped = false; if ( ! empty( $url ) ) { $url_arr = wp_parse_url( $url ); $net_url_arr = wp_parse_url( network_site_url() ); if ( ! empty( $url_arr['host'] ) && ! empty( $net_url_arr['host'] ) && $this->get_domain_from_host( $url_arr['host'] ) !== $this->get_domain_from_host( $net_url_arr['host'] ) ) { $is_mapped = true; } } return $is_mapped; } /** * Extract domain from host. * * @param string $host The host. * * @return string */ public function get_domain_from_host( string $host ): string { $host = strtolower( trim( $host ) ); $count = substr_count( $host, '.' ); if ( 2 === $count ) { if ( strlen( explode( '.', $host )[1] ) > 3 ) { $host = explode( '.', $host, 2 )[1]; } } elseif ( $count > 2 ) { $host = $this->get_domain_from_host( explode( '.', $host, 2 )[1] ); } return $host; } /** * Update admin bar menu url to masked login url if domain is mapped. * * @param WP_Admin_Bar $admin_bar Admin bar object. * * @return void * @since 3.4.0 */ public function update_admin_bar_menu( WP_Admin_Bar $admin_bar ) { $mask_url = trim( $this->model->mask_url ); if ( empty( $mask_url ) ) { return; } $admin_bar_nodes = $admin_bar->get_nodes(); $needle = '/wp-admin/'; $length = strlen( $needle ); foreach ( $admin_bar_nodes as $nodes ) { if ( substr( $nodes->href, - $length ) === $needle && $this->check_if_domain_is_mapped( $nodes->href ) ) { $href = str_replace( 'wp-admin', $mask_url, untrailingslashit( $nodes->href ) ); $admin_bar->add_menu( array( 'id' => $nodes->id, 'href' => $href, ) ); } } } /** * Update my sites action url to masked login url if domain is mapped. * * @param string $actions The current action links. * @param object $user_blog The user blog object. * * @return string * @since 3.4.0 */ public function update_myblogs_blog_actions( string $actions, object $user_blog ): string { $mask_url = trim( $this->model->mask_url ); if ( empty( $mask_url ) ) { return $actions; } $admin_url = get_admin_url( $user_blog->userblog_id ); if ( $this->check_if_domain_is_mapped( $admin_url ) ) { $updated_admin_url = str_replace( 'wp-admin', $mask_url, untrailingslashit( $admin_url ) ); $actions = str_replace( $admin_url, $updated_admin_url, $actions ); } return $actions; } /** * Set locale on Mask Login page. * * @return void * @since 3.12.0 */ public function set_locale(): void { $this->service->set_locale(); } /** * Enable/disable module. * * @param Request $request Request object. * * @return Response * @defender_route * @since 3.12.0 */ public function toggle_module( Request $request ): Response { $data = $request->get_data( array( 'enabled' => array( 'type' => 'boolean', ), ) ); $this->model->enabled = $data['enabled']; $this->model->save(); Config_Hub_Helper::set_clear_active_flag(); if ( ! $this->model->enabled || ! $this->model->is_mask_url_page_post_exists() ) { return new Response( true, array_merge( array( 'message' => esc_html__( 'Your settings have been updated.', 'wpdef' ), 'auto_close' => true, ), $this->data_frontend() ) ); } return new Response( false, array( 'error' => esc_html__( 'A page already exists at this URL. Please enter a unique URL for your login area.', 'wpdef' ), ) ); } /** * Get permalink separator. * * @return string */ public function get_permalink_separator(): string { return $this->model->is_permalink_structure_empty() ? '&' : '?'; } }
Fatal error: Uncaught WPMU_DEV\Defender\Vendor\DI\NotFoundException: No entry or class found for 'WP_Defender\Controller\Mask_Login' in /var/www/html/gtisolution.com.br/web/wp-content/plugins/wp-defender/lib/packages/DI/Container.php:136 Stack trace: #0 /var/www/html/gtisolution.com.br/web/wp-content/plugins/wp-defender/src/traits/defender-bootstrap.php(372): WPMU_DEV\Defender\Vendor\DI\Container->get('WP_Defender\\Con...') #1 /var/www/html/gtisolution.com.br/web/wp-content/plugins/wp-defender/src/class-bootstrap.php(31): WP_Defender\Bootstrap->init_modules_common() #2 /var/www/html/gtisolution.com.br/web/wp-content/plugins/wp-defender/src/traits/defender-bootstrap.php(604): WP_Defender\Bootstrap->init_modules() #3 /var/www/html/gtisolution.com.br/web/wp-includes/class-wp-hook.php(324): WP_Defender\Bootstrap->WP_Defender\Traits\{closure}('') #4 /var/www/html/gtisolution.com.br/web/wp-includes/class-wp-hook.php(348): WP_Hook->apply_filters(NULL, Array) #5 /var/www/html/gtisolution.com.br/web/wp-includes/plugin.php(517): WP in /var/www/html/gtisolution.com.br/web/wp-content/plugins/wp-defender/lib/packages/DI/Container.php on line 136