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