Changeset 42791 for trunk/src/wp-includes/user.php
- Timestamp:
- 03/06/2018 11:46:44 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/user.php
r42774 r42791 1371 1371 /** 1372 1372 * Determines whether the given username exists. 1373 * 1373 * 1374 1374 * For more information on this and similar theme functions, check out 1375 * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ 1375 * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ 1376 1376 * Conditional Tags} article in the Theme Developer Handbook. 1377 1377 * … … 1401 1401 /** 1402 1402 * Determines whether the given email exists. 1403 * 1403 * 1404 1404 * For more information on this and similar theme functions, check out 1405 * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ 1405 * the {@link https://developer.wordpress.org/themes/basics/conditional-tags/ 1406 1406 * Conditional Tags} article in the Theme Developer Handbook. 1407 1407 * … … 2810 2810 } 2811 2811 } 2812 2813 /** 2814 * Send a confirmation request email to confirm an action. 2815 * 2816 * @since 5.0.0 2817 * 2818 * @param string $action_name Name of the action that is being confirmed. 2819 * @param string $action_description User facing description of the action they will be confirming. 2820 * @param string $email User email address. This can be the address of a registered or non-registered user. Defaults to logged in user email address. 2821 * 2822 * @return WP_ERROR|bool Will return true/false based on the success of sending the email, or a WP_Error object. 2823 */ 2824 function send_confirm_account_action_email( $action_name, $action_description = '', $email = '' ) { 2825 $action_name = sanitize_key( $action_name ); 2826 $action_description = wp_kses_post( $action_description ); 2827 2828 if ( empty( $action_name ) ) { 2829 return new WP_Error( 'invalid_action', __( 'Invalid action' ) ); 2830 } 2831 2832 if ( empty( $email ) ) { 2833 $user = wp_get_current_user(); 2834 $email = $user->ID ? $user->user_email : ''; 2835 } else { 2836 $user = false; 2837 } 2838 2839 $email = sanitize_email( $email ); 2840 2841 if ( ! is_email( $email ) ) { 2842 return new WP_Error( 'invalid_email', __( 'Invalid email address' ) ); 2843 } 2844 2845 if ( ! $user ) { 2846 $user = get_user_by( 'email', $email ); 2847 } 2848 2849 // We could be dealing with a registered user account, or a visitor. 2850 $is_registered_user = $user && ! is_wp_error( $user ); 2851 $uid = $is_registered_user ? $user->ID : hash( 'sha256', $email ); 2852 $confirm_key = get_confirm_account_action_key( $action_name, $email ); 2853 2854 if ( is_wp_error( $confirm_key ) ) { 2855 return $confirm_key; 2856 } 2857 2858 // Prepare the email content. 2859 if ( ! $action_description ) { 2860 $action_description = $action_name; 2861 } 2862 2863 /* translators: Do not translate DESCRIPTION, CONFIRM_URL, EMAIL, SITENAME, SITEURL: those are placeholders. */ 2864 $email_text = __( 2865 'Howdy, 2866 2867 An account linked to your email address has requested to perform 2868 the following action: 2869 2870 ###DESCRIPTION### 2871 2872 To confirm this action, please click on the following link: 2873 ###CONFIRM_URL### 2874 2875 You can safely ignore and delete this email if you do not want to 2876 take this action. 2877 2878 This email has been sent to ###EMAIL###. 2879 2880 Regards, 2881 All at ###SITENAME### 2882 ###SITEURL###' 2883 ); 2884 2885 $email_data = array( 2886 'action_name' => $action_name, 2887 'email' => $email, 2888 'description' => $action_description, 2889 'confirm_url' => add_query_arg( array( 2890 'action' => 'emailconfirm', 2891 'confirm_action' => $action_name, 2892 'uid' => $uid, 2893 'confirm_key' => $confirm_key, 2894 ), site_url( 'wp-login.php' ) ), 2895 'sitename' => is_multisite() ? get_site_option( 'site_name' ) : get_option( 'blogname' ), 2896 'siteurl' => network_home_url(), 2897 ); 2898 2899 /** 2900 * Filters the text of the email sent when an account action is attempted. 2901 * 2902 * The following strings have a special meaning and will get replaced dynamically: 2903 * ###USERNAME### The user's username, if the user has an account. Prefixed with single space. Otherwise left blank. 2904 * ###DESCRIPTION### Description of the action being performed so the user knows what the email is for. 2905 * ###CONFIRM_URL### The link to click on to confirm the account action. 2906 * ###EMAIL### The email we are sending to. 2907 * ###SITENAME### The name of the site. 2908 * ###SITEURL### The URL to the site. 2909 * 2910 * @param string $email_text Text in the email. 2911 * @param array $email_data { 2912 * Data relating to the account action email. 2913 * 2914 * @type string $action_name Name of the action being performed. 2915 * @type string $email The email address this is being sent to. 2916 * @type string $description Description of the action being performed so the user knows what the email is for. 2917 * @type string $confirm_url The link to click on to confirm the account action. 2918 * @type string $sitename The site name sending the mail. 2919 * @type string $siteurl The site URL sending the mail. 2920 * } 2921 */ 2922 $content = apply_filters( 'confirm_account_action_email_content', $email_text, $email_data ); 2923 2924 $content = str_replace( '###DESCRIPTION###', $email_data['description'], $content ); 2925 $content = str_replace( '###CONFIRM_URL###', esc_url_raw( $email_data['confirm_url'] ), $content ); 2926 $content = str_replace( '###EMAIL###', $email_data['email'], $content ); 2927 $content = str_replace( '###SITENAME###', wp_specialchars_decode( $email_data['sitename'], ENT_QUOTES ), $content ); 2928 $content = str_replace( '###SITEURL###', esc_url_raw( $email_data['siteurl'] ), $content ); 2929 2930 /* translators: %s Site name. */ 2931 return wp_mail( $email_data['email'], sprintf( __( '[%s] Confirm Account Action' ), wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ) ), $content ); 2932 } 2933 2934 /** 2935 * Creates, stores, then returns a confirmation key for an account action. 2936 * 2937 * @since 5.0.0 2938 * 2939 * @param string $action_name Name of the action this key is being generated for. 2940 * @param string $email User email address. This can be the address of a registered or non-registered user. 2941 * 2942 * @return string|WP_Error Confirmation key on success. WP_Error on error. 2943 */ 2944 function get_confirm_account_action_key( $action_name, $email ) { 2945 global $wp_hasher; 2946 2947 if ( ! is_email( $email ) ) { 2948 return new WP_Error( 'invalid_email', __( 'Invalid email address' ) ); 2949 } 2950 2951 if ( empty( $action_name ) ) { 2952 return new WP_Error( 'invalid_action', __( 'Invalid action' ) ); 2953 } 2954 2955 $user = get_user_by( 'email', $email ); 2956 2957 // We could be dealing with a registered user account, or a visitor. 2958 $is_registered_user = $user && ! is_wp_error( $user ); 2959 2960 // Generate something random for a confirmation key. 2961 $key = wp_generate_password( 20, false ); 2962 2963 // Now insert the key, hashed, into the DB. 2964 if ( empty( $wp_hasher ) ) { 2965 require_once ABSPATH . WPINC . '/class-phpass.php'; 2966 $wp_hasher = new PasswordHash( 8, true ); 2967 } 2968 2969 $hashed_key = $wp_hasher->HashPassword( $key ); 2970 2971 if ( $is_registered_user ) { 2972 $key_saved = (bool) update_user_meta( $user->ID, '_account_action_' . $action_name, implode( ':', array( time(), $hashed_key ) ) ); 2973 } else { 2974 $key_saved = (bool) update_site_option( '_account_action_' . hash( 'sha256', $email ) . '_' . $action_name, implode( ':', array( time(), $hashed_key, $email ) ) ); 2975 } 2976 2977 if ( false === $key_saved ) { 2978 return new WP_Error( 'no_confirm_account_action_key_update', __( 'Could not save confirm account action key to database.' ) ); 2979 } 2980 2981 return $key; 2982 } 2983 2984 /** 2985 * Checks if a key is valid and handles the action based on this. 2986 * 2987 * @since 5.0.0 2988 * 2989 * @param string $action_name Name of the action this key is being generated for. 2990 * @param string $key Key to confirm. 2991 * @param string $uid Email hash or user ID. 2992 * 2993 * @return array|WP_Error WP_Error on failure, action name and user email address on success. 2994 */ 2995 function check_confirm_account_action_key( $action_name, $key, $uid ) { 2996 global $wp_hasher; 2997 2998 if ( ! empty( $action_name ) && ! empty( $key ) && ! empty( $uid ) ) { 2999 $user = false; 3000 3001 if ( is_numeric( $uid ) ) { 3002 $user = get_user_by( 'id', absint( $uid ) ); 3003 } 3004 3005 // We could be dealing with a registered user account, or a visitor. 3006 $is_registered_user = $user && ! is_wp_error( $user ); 3007 $key_request_time = ''; 3008 $saved_key = ''; 3009 $email = ''; 3010 3011 if ( empty( $wp_hasher ) ) { 3012 require_once ABSPATH . WPINC . '/class-phpass.php'; 3013 $wp_hasher = new PasswordHash( 8, true ); 3014 } 3015 3016 // Get the saved key from the database. 3017 if ( $is_registered_user ) { 3018 $confirm_action_data = get_user_meta( $user->ID, '_account_action_' . $action_name, true ); 3019 $email = $user->user_email; 3020 3021 if ( false !== strpos( $confirm_action_data, ':' ) ) { 3022 list( $key_request_time, $saved_key ) = explode( ':', $confirm_action_data, 2 ); 3023 } 3024 } else { 3025 $confirm_action_data = get_site_option( '_account_action_' . $uid . '_' . $action_name, '' ); 3026 3027 if ( false !== strpos( $confirm_action_data, ':' ) ) { 3028 list( $key_request_time, $saved_key, $email ) = explode( ':', $confirm_action_data, 3 ); 3029 } 3030 } 3031 3032 if ( ! $saved_key ) { 3033 return new WP_Error( 'invalid_key', __( 'Invalid key' ) ); 3034 } 3035 3036 /** 3037 * Filters the expiration time of confirm keys. 3038 * 3039 * @param int $expiration The expiration time in seconds. 3040 */ 3041 $expiration_duration = apply_filters( 'account_action_expiration', DAY_IN_SECONDS ); 3042 $expiration_time = $key_request_time + $expiration_duration; 3043 3044 if ( $wp_hasher->CheckPassword( $key, $saved_key ) ) { 3045 if ( $expiration_time && time() < $expiration_time ) { 3046 $return = array( 3047 'action' => $action_name, 3048 'email' => $email, 3049 ); 3050 } else { 3051 $return = new WP_Error( 'expired_key', __( 'The confirmation email has expired.' ) ); 3052 } 3053 3054 // Clean up stored keys. 3055 if ( $is_registered_user ) { 3056 delete_user_meta( $user->ID, '_account_action_' . $action_name ); 3057 } else { 3058 delete_site_option( '_account_action_' . $uid . '_' . $action_name ); 3059 } 3060 3061 return $return; 3062 } 3063 } 3064 3065 return new WP_Error( 'invalid_key', __( 'Invalid key' ) ); 3066 }
Note: See TracChangeset
for help on using the changeset viewer.