diff --git a/includes/admin/class-secure.php b/includes/admin/class-secure.php
index 89405b5f..65f8ec79 100644
--- a/includes/admin/class-secure.php
+++ b/includes/admin/class-secure.php
@@ -298,8 +298,8 @@ if ( ! class_exists( 'um\admin\Secure' ) ) {
array(
'id' => 'secure_allowed_redirect_hosts',
'type' => 'textarea',
- 'label' => __( 'Allowed hosts for redirect (one host per line)', 'ultimate-member' ),
- 'description' => __( 'Extend allowed hosts for redirects', 'ultimate-member' ),
+ 'label' => __( 'Allowed hosts for safe redirect (one host per line)', 'ultimate-member' ),
+ 'description' => __( 'Extend allowed hosts for frontend pages redirects', 'ultimate-member' ),
),
)
);
diff --git a/includes/admin/core/class-admin-settings.php b/includes/admin/core/class-admin-settings.php
index 349a5c2a..d8a7cb4e 100644
--- a/includes/admin/core/class-admin-settings.php
+++ b/includes/admin/core/class-admin-settings.php
@@ -962,6 +962,9 @@ if ( ! class_exists( 'um\admin\core\Admin_Settings' ) ) {
'secure_notify_admins_banned_accounts__interval' => array(
'sanitize' => 'key',
),
+ 'secure_allowed_redirect_hosts' => array(
+ 'sanitize' => 'textarea',
+ ),
)
);
diff --git a/includes/class-config.php b/includes/class-config.php
index 26259166..67a45e66 100644
--- a/includes/class-config.php
+++ b/includes/class-config.php
@@ -589,6 +589,7 @@ if ( ! class_exists( 'um\Config' ) ) {
'banned_capabilities' => array( 'manage_options', 'promote_users', 'level_10' ),
'secure_notify_admins_banned_accounts' => false,
'secure_notify_admins_banned_accounts__interval' => 'instant',
+ 'secure_allowed_redirect_hosts' => '',
);
add_filter( 'um_get_tabs_from_config', '__return_true' );
diff --git a/includes/core/class-login.php b/includes/core/class-login.php
index e4d2576d..c4b4af83 100644
--- a/includes/core/class-login.php
+++ b/includes/core/class-login.php
@@ -61,7 +61,22 @@ if ( ! class_exists( 'um\core\Login' ) ) {
}
if ( empty( $args['_wpnonce'] ) || ! wp_verify_nonce( $args['_wpnonce'], 'um_login_form' ) ) {
- // @todo add hookdocs
+ /**
+ * Filters URL for redirect if login form nonce isn't verified.
+ *
+ * @param {string} $error_url URL for redirect if login form nonce isn't verified.
+ *
+ * @return {string} URL for redirect.
+ *
+ * @since 2.0
+ * @hook um_login_invalid_nonce_redirect_url
+ *
+ * @example
Change URL for redirect if login form nonce isn't verified.
+ * function my_um_login_invalid_nonce_redirect_url( $error_url ) {
+ * return '{your_custom_url}';
+ * }
+ * add_filter( 'um_login_invalid_nonce_redirect_url', 'my_um_login_invalid_nonce_redirect_url' );
+ */
$url = apply_filters( 'um_login_invalid_nonce_redirect_url', add_query_arg( array( 'err' => 'invalid_nonce' ) ) );
um_safe_redirect( $url );
exit;
diff --git a/includes/core/class-logout.php b/includes/core/class-logout.php
index e93f6538..30999d41 100644
--- a/includes/core/class-logout.php
+++ b/includes/core/class-logout.php
@@ -79,29 +79,25 @@ if ( ! class_exists( 'um\core\Logout' ) ) {
wp_destroy_current_session();
wp_logout();
session_unset();
- exit( wp_safe_redirect( home_url() ) );
+ wp_safe_redirect( home_url() );
+ exit;
} else {
/**
- * UM hook
+ * Filters URL for redirect after logout.
*
- * @type filter
- * @title um_logout_redirect_url
- * @description Change redirect URL after logout
- * @input_vars
- * [{"var":"$url","type":"string","desc":"Redirect URL"},
- * {"var":"$id","type":"int","desc":"User ID"}]
- * @change_log
- * ["Since: 2.0"]
- * @usage
- *
- * @example
- * Change URL for redirect after logout.
+ * function my_logout_redirect_url( $logout_redirect_url, $user_id ) {
+ * return '{your_custom_url}';
* }
- * ?>
+ * add_filter( 'um_logout_redirect_url', 'my_logout_redirect_url', 10, 2 );
*/
$redirect_url = apply_filters( 'um_logout_redirect_url', um_user( 'logout_redirect_url' ), um_user( 'ID' ) );
wp_destroy_current_session();
@@ -111,7 +107,8 @@ if ( ! class_exists( 'um\core\Logout' ) ) {
}
} else {
add_filter( 'wp_safe_redirect_fallback', array( &$this, 'safe_redirect_default' ), 10, 2 );
- exit( wp_safe_redirect( home_url() ) );
+ wp_safe_redirect( home_url() );
+ exit;
}
}
diff --git a/includes/core/class-password.php b/includes/core/class-password.php
index 8c2f2167..c83b715b 100644
--- a/includes/core/class-password.php
+++ b/includes/core/class-password.php
@@ -239,7 +239,7 @@ if ( ! class_exists( 'um\core\Password' ) ) {
if ( isset( $_GET['hash'] ) && isset( $_GET['login'] ) ) {
$value = sprintf( '%s:%s', wp_unslash( $_GET['login'] ), wp_unslash( $_GET['hash'] ) );
$this->setcookie( $rp_cookie, $value );
-
+ // Not `um_safe_redirect()` because password-reset page is predefined page and is situated on the same host.
wp_safe_redirect( remove_query_arg( array( 'hash', 'login' ) ) );
exit;
}
diff --git a/includes/core/class-register.php b/includes/core/class-register.php
index f968dc72..de6c4fe6 100644
--- a/includes/core/class-register.php
+++ b/includes/core/class-register.php
@@ -55,7 +55,22 @@ if ( ! class_exists( 'um\core\Register' ) ) {
}
if ( empty( $args['_wpnonce'] ) || ! wp_verify_nonce( $args['_wpnonce'], 'um_register_form' ) ) {
- // @todo add hookdocs
+ /**
+ * Filters URL for redirect if register form nonce isn't verified.
+ *
+ * @param {string} $error_url URL for redirect if register form nonce isn't verified.
+ *
+ * @return {string} URL for redirect.
+ *
+ * @since 2.0
+ * @hook um_register_invalid_nonce_redirect_url
+ *
+ * @example Change URL for redirect if register form nonce isn't verified.
+ * function my_um_register_invalid_nonce_redirect_url( $error_url ) {
+ * return '{your_custom_url}';
+ * }
+ * add_filter( 'um_register_invalid_nonce_redirect_url', 'my_um_register_invalid_nonce_redirect_url' );
+ */
$url = apply_filters( 'um_register_invalid_nonce_redirect_url', add_query_arg( array( 'err' => 'invalid_nonce' ) ) );
um_safe_redirect( $url );
exit;
diff --git a/includes/core/um-actions-login.php b/includes/core/um-actions-login.php
index 947142bc..ff68968b 100644
--- a/includes/core/um-actions-login.php
+++ b/includes/core/um-actions-login.php
@@ -140,11 +140,13 @@ function um_submit_form_errors_hook_logincheck( $submitted_data, $form_data ) {
case 'awaiting_email_confirmation':
case 'rejected':
um_reset_user();
+ // Not `um_safe_redirect()` because UM()->permalinks()->get_current_url() is situated on the same host.
wp_safe_redirect( add_query_arg( 'err', esc_attr( $status ), UM()->permalinks()->get_current_url() ) );
exit;
}
if ( isset( $form_data['form_id'] ) && absint( $form_data['form_id'] ) === absint( UM()->shortcodes()->core_login_form() ) && UM()->form()->errors && ! isset( $_POST[ UM()->honeypot ] ) ) {
+ // Not `um_safe_redirect()` because predefined login page is situated on the same host.
wp_safe_redirect( um_get_core_page( 'login' ) );
exit;
}
@@ -224,12 +226,14 @@ function um_user_login( $submitted_data ) {
// Role redirect
$after_login = um_user( 'after_login' );
if ( empty( $after_login ) ) {
+ // Not `um_safe_redirect()` because predefined user profile page is situated on the same host.
wp_safe_redirect( um_user_profile_url() );
exit;
}
switch ( $after_login ) {
case 'redirect_admin':
+ // Not `um_safe_redirect()` because is redirected to wp-admin.
wp_safe_redirect( admin_url() );
exit;
case 'redirect_url':
@@ -255,10 +259,12 @@ function um_user_login( $submitted_data ) {
um_safe_redirect( $redirect_url );
exit;
case 'refresh':
+ // Not `um_safe_redirect()` because UM()->permalinks()->get_current_url() is situated on the same host.
wp_safe_redirect( UM()->permalinks()->get_current_url() );
exit;
case 'redirect_profile':
default:
+ // Not `um_safe_redirect()` because predefined user profile page is situated on the same host.
wp_safe_redirect( um_user_profile_url() );
exit;
}
diff --git a/includes/core/um-actions-profile.php b/includes/core/um-actions-profile.php
index 7a6944dc..f5b38c34 100644
--- a/includes/core/um-actions-profile.php
+++ b/includes/core/um-actions-profile.php
@@ -508,6 +508,7 @@ function um_user_edit_profile( $args, $form_data ) {
// Finally redirect to profile.
$url = um_user_profile_url( $user_id );
$url = apply_filters( 'um_update_profile_redirect_after', $url, $user_id, $args );
+ // Not `um_safe_redirect()` because predefined user profile page is situated on the same host.
wp_safe_redirect( um_edit_my_profile_cancel_uri( $url ) );
exit;
}
diff --git a/includes/core/um-actions-register.php b/includes/core/um-actions-register.php
index 89098d95..d8617175 100644
--- a/includes/core/um-actions-register.php
+++ b/includes/core/um-actions-register.php
@@ -146,32 +146,70 @@ add_action( 'um_registration_complete', 'um_send_registration_notification' );
function um_check_user_status( $user_id, $args, $form_data = null ) {
$status = um_user( 'account_status' );
/**
- * UM hook
+ * Fires after complete UM user registration.
+ * Where $status can be equal to 'approved', 'checkmail' or 'pending'.
*
- * @type action
- * @title um_post_registration_{$status}_hook
- * @description After complete UM user registration.
- * @input_vars
- * [{"var":"$user_id","type":"int","desc":"User ID"},
- * {"var":"$args","type":"array","desc":"Form data"}]
- * @change_log
- * ["Since: 2.0"]
- * @usage add_action( 'um_post_registration_{$status}_hook', 'function_name', 10, 2 );
- * @example
- * Make a custom action after complete UM user registration when user get an approved status.
+ * function my_um_post_registration( $user_id, $submitted_data, $form_data ) {
* // your code here
* }
- * ?>
+ * add_action( 'um_post_registration_approved_hook', 'my_um_post_registration', 10, 3 );
+ * @example Make a custom action after complete UM user registration when user requires email activation.
+ * function my_um_post_registration( $user_id, $submitted_data, $form_data ) {
+ * // your code here
+ * }
+ * add_action( 'um_post_registration_checkmail_hook', 'my_um_post_registration', 10, 3 );
+ * @example Make a custom action after complete UM user registration when user requires admin review.
+ * function my_um_post_registration( $user_id, $submitted_data, $form_data ) {
+ * // your code here
+ * }
+ * add_action( 'um_post_registration_pending_hook', 'my_um_post_registration', 10, 3 );
*/
- do_action( "um_post_registration_{$status}_hook", $user_id, $args );
+ do_action( "um_post_registration_{$status}_hook", $user_id, $args, $form_data );
if ( is_null( $form_data ) || is_admin() ) {
return;
}
- do_action( "track_{$status}_user_registration" );
+ /**
+ * Fires after complete UM user registration. Only for the frontend action which is run before autologin and redirects.
+ * Where $status can be equal to 'approved', 'checkmail' or 'pending'.
+ *
+ * @since 1.3.x
+ * @since 2.6.8 Added $user_id, $submitted_data, $form_data arguments.
+ *
+ * @hook track_{$status}_user_registration
+ *
+ * @param {int} $user_id User ID. Since 2.6.8
+ * @param {array} $submitted_data Registration form submitted data. Since 2.6.8
+ * @param {array} $form_data Form data. Since 2.6.8
+ *
+ * @example Make a custom action after complete UM user registration when user get an approved status.
+ * function my_um_post_registration( $user_id, $submitted_data, $form_data ) {
+ * // your code here
+ * }
+ * add_action( 'track_approved_user_registration', 'my_um_post_registration', 10, 3 );
+ * @example Make a custom action after complete UM user registration when user requires email activation.
+ * function my_um_post_registration( $user_id, $submitted_data, $form_data ) {
+ * // your code here
+ * }
+ * add_action( 'track_checkmail_user_registration', 'my_um_post_registration', 10, 3 );
+ * @example Make a custom action after complete UM user registration when user requires admin review.
+ * function my_um_post_registration( $user_id, $submitted_data, $form_data ) {
+ * // your code here
+ * }
+ * add_action( 'track_pending_user_registration', 'my_um_post_registration', 10, 3 );
+ */
+ do_action( "track_{$status}_user_registration", $user_id, $args, $form_data );
if ( 'approved' === $status ) {
// Check if user is logged in because there can be the customized way when through 'um_registration_for_loggedin_users' hook the registration is enabled for the logged-in users (e.g. Administrator).
@@ -182,72 +220,60 @@ function um_check_user_status( $user_id, $args, $form_data = null ) {
UM()->user()->generate_profile_slug( $user_id );
/**
- * UM hook
+ * Fires after complete UM user registration and autologin.
*
- * @type action
- * @title um_registration_after_auto_login
- * @description After complete UM user registration and autologin.
- * @input_vars
- * [{"var":"$user_id","type":"int","desc":"User ID"}]
- * @change_log
- * ["Since: 2.0"]
- * @usage add_action( 'um_registration_after_auto_login', 'function_name', 10, 1 );
- * @example
- * Make a custom action after complete UM user registration and autologin.
+ * function my_um_registration_after_auto_login( $user_id ) {
* // your code here
* }
- * ?>
+ * add_action( 'um_registration_after_auto_login', 'my_um_registration_after_auto_login' );
*/
do_action( 'um_registration_after_auto_login', $user_id );
// Priority redirect
if ( isset( $args['redirect_to'] ) ) {
um_safe_redirect( urldecode( $args['redirect_to'] ) );
- exit;
}
um_fetch_user( $user_id );
if ( 'redirect_url' === um_user( 'auto_approve_act' ) && '' !== um_user( 'auto_approve_url' ) ) {
- um_safe_redirect( um_user( 'auto_approve_url' ));
- exit;
+ um_safe_redirect( um_user( 'auto_approve_url' ) );
}
if ( 'redirect_profile' === um_user( 'auto_approve_act' ) ) {
+ // Not `um_safe_redirect()` because predefined user profile page is situated on the same host.
wp_safe_redirect( um_user_profile_url() );
exit;
}
} else {
if ( 'redirect_url' === um_user( $status . '_action' ) && '' !== um_user( $status . '_url' ) ) {
/**
- * UM hook
+ * Filters the redirect URL for pending user after registration.
*
- * @type filter
- * @title um_registration_pending_user_redirect
- * @description Change redirect URL for pending user after registration
- * @input_vars
- * [{"var":"$url","type":"string","desc":"Redirect URL"},
- * {"var":"$status","type":"string","desc":"User status"},
- * {"var":"$user_id","type":"int","desc":"User ID"}]
- * @change_log
- * ["Since: 2.0"]
- * @usage
- *
- * @example
- * Change redirect URL for pending user after registration.
* function my_registration_pending_user_redirect( $url, $status, $user_id ) {
* // your code here
* return $url;
* }
- * ?>
+ * add_filter( 'um_registration_pending_user_redirect', 'my_registration_pending_user_redirect', 10, 3 );
*/
$redirect_url = apply_filters( 'um_registration_pending_user_redirect', um_user( $status . '_url' ), $status, um_user( 'ID' ) );
-
um_safe_redirect( $redirect_url );
- exit;
}
if ( 'show_message' === um_user( $status . '_action' ) && '' !== um_user( $status . '_message' ) ) {
@@ -256,7 +282,7 @@ function um_check_user_status( $user_id, $args, $form_data = null ) {
// Add only priority role to URL.
$url = add_query_arg( 'um_role', esc_attr( um_user( 'role' ) ), $url );
$url = add_query_arg( 'um_form_id', esc_attr( $form_data['form_id'] ), $url );
-
+ // Not `um_safe_redirect()` because UM()->permalinks()->get_current_url() is situated on the same host.
wp_safe_redirect( $url );
exit;
}
@@ -714,6 +740,7 @@ function um_form_register_redirect() {
$page_id = UM()->options()->get( UM()->options()->get_core_page_id( 'register' ) );
$register_post = get_post( $page_id );
if ( ! empty( $register_post ) ) {
+ // Not `um_safe_redirect()` because predefined register page is situated on the same host.
wp_safe_redirect( get_permalink( $page_id ) );
exit();
}
diff --git a/includes/frontend/class-secure.php b/includes/frontend/class-secure.php
index d242c54a..fc5efe32 100644
--- a/includes/frontend/class-secure.php
+++ b/includes/frontend/class-secure.php
@@ -129,6 +129,7 @@ if ( ! class_exists( 'um\frontend\Secure' ) ) {
if ( UM()->options()->get( 'lock_register_forms' ) ) {
$login_url = add_query_arg( 'notice', 'maintenance', um_get_core_page( 'login' ) );
nocache_headers();
+ // Not `um_safe_redirect()` because predefined login page is situated on the same host.
wp_safe_redirect( $login_url );
exit;
}
@@ -144,6 +145,7 @@ if ( ! class_exists( 'um\frontend\Secure' ) ) {
$expired_password_reset = get_user_meta( um_user( 'ID' ), 'um_secure_has_reset_password', true );
if ( ! $expired_password_reset ) {
$login_url = add_query_arg( 'notice', 'expired_password', um_get_core_page( 'login' ) );
+ // Not `um_safe_redirect()` because predefined login page is situated on the same host.
wp_safe_redirect( $login_url );
exit;
}
@@ -241,6 +243,7 @@ if ( ! class_exists( 'um\frontend\Secure' ) ) {
$redirect = apply_filters( 'um_secure_blocked_user_redirect_immediately', true );
if ( $redirect ) {
$login_url = add_query_arg( 'err', 'inactive', um_get_core_page( 'login' ) );
+ // Not `um_safe_redirect()` because predefined login page is situated on the same host.
wp_safe_redirect( $login_url );
exit;
}
diff --git a/includes/um-short-functions.php b/includes/um-short-functions.php
index 7d1bbdb6..a8e1f5c4 100644
--- a/includes/um-short-functions.php
+++ b/includes/um-short-functions.php
@@ -2843,16 +2843,15 @@ function um_is_amp( $check_theme_support = true ) {
}
/**
- * UM safe redirect
+ * UM safe redirect. By default, you can be redirected only to WordPress installation Home URL. Fallback URL is wp-admin URL.
+ * But it can be changed through filters and extended by UM Setting "Allowed hosts for safe redirect (one host per line)" and filter `um_wp_safe_redirect_fallback`.
*
- * @since 2.6.9
+ * @since 2.6.8
*
* @param string $url redirect URL.
- *
- * @return string
*/
function um_safe_redirect( $url ) {
- add_filter( 'allowed_redirect_hosts', 'um_allowed_redirect_hosts', 10, 1 );
+ add_filter( 'allowed_redirect_hosts', 'um_allowed_redirect_hosts' );
add_filter( 'wp_safe_redirect_fallback', 'um_wp_safe_redirect_fallback', 10, 2 );
wp_safe_redirect( $url );
@@ -2862,21 +2861,19 @@ function um_safe_redirect( $url ) {
/**
* UM allowed hosts
*
- * @since 2.6.9
+ * @since 2.6.8
*
- * @param array $hosts allowed hosts.
+ * @param array $hosts Allowed hosts.
*
* @return array
*/
function um_allowed_redirect_hosts( $hosts ) {
- $hosts = UM()->options()->get( 'secure_allowed_redirect_hosts' );
-
- $hosts = explode( "\n", $hosts );
- $hosts = array_unique( $hosts );
+ $secure_hosts = UM()->options()->get( 'secure_allowed_redirect_hosts' );
+ $secure_hosts = explode( "\n", $secure_hosts );
+ $secure_hosts = array_unique( $secure_hosts );
$additional_hosts = array();
-
- foreach ( $hosts as $key => $host ) {
+ foreach ( $secure_hosts as $host ) {
if ( '' !== trim( $host ) ) {
$host = trim( $host );
$host = str_replace( array( 'http://', 'https://' ), '', $host );
@@ -2887,26 +2884,28 @@ function um_allowed_redirect_hosts( $hosts ) {
}
if ( strpos( $host, 'www.' ) !== false ) {
- if ( ! in_array( str_replace( array( 'www.' ), '', $host ), $additional_hosts, true ) ) {
- $additional_hosts[] = str_replace( array( 'www.' ), '', $host );
+ $strip_www = str_replace( 'www.', '', $host );
+ if ( ! in_array( $strip_www, $additional_hosts, true ) ) {
+ $additional_hosts[] = $strip_www;
}
} else {
- if ( ! in_array( 'www.' . $host, $additional_hosts, true ) ) {
- $additional_hosts[] = 'www.' . $host;
+ $added_www = 'www.' . $host;
+ if ( ! in_array( $added_www, $additional_hosts, true ) ) {
+ $additional_hosts[] = $added_www;
}
}
}
}
/**
- * Filters change allowed hosts.
+ * Filters change allowed hosts. When `wp_safe_redirect()` function is used for the Ultimate Member frontend redirects.
*
- * @since 2.6.9
+ * @since 2.6.8
* @hook um_allowed_redirect_hosts
*
- * @param {array} $additional_hosts allowed hosts.
- * @param {array} $hosts default hosts.
+ * @param {array} $additional_hosts Allowed hosts.
+ * @param {array} $hosts Default hosts.
*
- * @return {array} allowed hosts.
+ * @return {array} Allowed hosts.
*
* @example Change allowed hosts.
* function my_um_allowed_redirect_hosts( $additional_hosts, $hosts ) {
@@ -2916,33 +2915,32 @@ function um_allowed_redirect_hosts( $hosts ) {
* add_filter( 'um_allowed_redirect_hosts', 'my_um_allowed_redirect_hosts', 10, 2 );
*/
$additional_hosts = apply_filters( 'um_allowed_redirect_hosts', $additional_hosts, $hosts );
-
- $allowed_hosts = array_merge( $hosts, $additional_hosts );
-
- return $allowed_hosts;
+ return array_merge( $hosts, $additional_hosts );
}
/**
* UM fallback redirect URL
*
- * @since 2.6.9
+ * @since 2.6.8
*
- * @param string $url fallback URL.
- * @param string $status redirect status.
+ * @param string $url Fallback URL.
+ * @param string $status Redirect status.
*
* @return string
*/
function um_wp_safe_redirect_fallback( $url, $status ) {
/**
- * Filters change fallback URL.
+ * Filters change fallback URL. When `wp_safe_redirect()` function is used for the Ultimate Member frontend redirects.
+ * It's `home_url()` by default.
*
- * @since 2.6.9
+ * @since 2.6.8
* @hook um_wp_safe_redirect_fallback
*
- * @param {string} $url fallback URL.
- * @param {string} $status status.
+ * @param {string} $url UM Fallback URL.
+ * @param {string} $default_fallback Default fallback URL.
+ * @param {string} $status Redirect status.
*
- * @return {string} fallback URL.
+ * @return {string} Fallback URL.
*
* @example Change fallback URL.
* function my_um_wp_safe_redirect_fallback( $url, $status ) {
@@ -2951,7 +2949,5 @@ function um_wp_safe_redirect_fallback( $url, $status ) {
* }
* add_filter( 'um_wp_safe_redirect_fallback', 'my_um_wp_safe_redirect_fallback', 10, 2 );
*/
- $url = apply_filters( 'um_wp_safe_redirect_fallback', home_url( '/' ), $status );
-
- return $url;
+ return apply_filters( 'um_wp_safe_redirect_fallback', home_url( '/' ), $url, $status );
}
diff --git a/readme.txt b/readme.txt
index 5522615d..a3e229bf 100644
--- a/readme.txt
+++ b/readme.txt
@@ -166,7 +166,7 @@ No specific extensions are needed. But we highly recommended keep active these P
IMPORTANT: PLEASE UPDATE THE PLUGIN TO AT LEAST VERSION 2.6.7 IMMEDIATELY. VERSION 2.6.7 PATCHES SECURITY PRIVILEGE ESCALATION VULNERABILITY. PLEASE SEE [THIS ARTICLE](https://docs.ultimatemember.com/article/1866-security-incident-update-and-recommended-actions) FOR MORE INFORMATION
-= 2.6.8: July 14, 2023 =
+= 2.6.8: July 19, 2023 =
* Enhancements:
@@ -175,6 +175,7 @@ IMPORTANT: PLEASE UPDATE THE PLUGIN TO AT LEAST VERSION 2.6.7 IMMEDIATELY. VERSI
- Added: `um_edit_profile_url` hook for force changing user profile edit URL
- Added: Additional hook attributes to 'um_reset_password_errors_hook' and 'um_reset_password_process_hook'
- Added: $form_data attribute to 'um_before_save_registration_details' hook
+ - Added: `um_safe_redirect()` function for handle `wp_safe_redirect()` function with new the "Allowed hosts for safe redirect" setting
- Updated: [Hooks Documentation v2](https://ultimatemember.github.io/ultimatemember/hooks/)
* Bugfixes:
diff --git a/ultimate-member.php b/ultimate-member.php
index b71fb2e8..32a0ccba 100644
--- a/ultimate-member.php
+++ b/ultimate-member.php
@@ -3,7 +3,7 @@
Plugin Name: Ultimate Member
Plugin URI: http://ultimatemember.com/
Description: The easiest way to create powerful online communities and beautiful user profiles with WordPress
-Version: 2.6.8-rc.1
+Version: 2.6.8
Author: Ultimate Member
Author URI: http://ultimatemember.com/
Text Domain: ultimate-member