Changeset 43069 for branches/4.9
- Timestamp:
- 05/01/2018 11:33:17 PM (6 years ago)
- Location:
- branches/4.9
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/4.9
-
branches/4.9/src/wp-includes/user.php
r41714 r43069 2732 2732 } 2733 2733 } 2734 2735 /** 2736 * Send a confirmation request email to confirm an action. 2737 * 2738 * @since 5.0.0 2739 * 2740 * @param string $action_name Name of the action that is being confirmed. 2741 * @param string $action_description User facing description of the action they will be confirming. 2742 * @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. 2743 * 2744 * @return WP_ERROR|bool Will return true/false based on the success of sending the email, or a WP_Error object. 2745 */ 2746 function send_confirm_account_action_email( $action_name, $action_description = '', $email = '' ) { 2747 $action_name = sanitize_key( $action_name ); 2748 $action_description = wp_kses_post( $action_description ); 2749 2750 if ( empty( $action_name ) ) { 2751 return new WP_Error( 'invalid_action', __( 'Invalid action' ) ); 2752 } 2753 2754 if ( empty( $email ) ) { 2755 $user = wp_get_current_user(); 2756 $email = $user->ID ? $user->user_email : ''; 2757 } else { 2758 $user = false; 2759 } 2760 2761 $email = sanitize_email( $email ); 2762 2763 if ( ! is_email( $email ) ) { 2764 return new WP_Error( 'invalid_email', __( 'Invalid email address' ) ); 2765 } 2766 2767 if ( ! $user ) { 2768 $user = get_user_by( 'email', $email ); 2769 } 2770 2771 // We could be dealing with a registered user account, or a visitor. 2772 $is_registered_user = $user && ! is_wp_error( $user ); 2773 $uid = $is_registered_user ? $user->ID : hash( 'sha256', $email ); 2774 $confirm_key = get_confirm_account_action_key( $action_name, $email ); 2775 2776 if ( is_wp_error( $confirm_key ) ) { 2777 return $confirm_key; 2778 } 2779 2780 // Prepare the email content. 2781 if ( ! $action_description ) { 2782 $action_description = $action_name; 2783 } 2784 2785 /* translators: Do not translate DESCRIPTION, CONFIRM_URL, EMAIL, SITENAME, SITEURL: those are placeholders. */ 2786 $email_text = __( 2787 'Howdy, 2788 2789 An account linked to your email address has requested to perform 2790 the following action: 2791 2792 ###DESCRIPTION### 2793 2794 To confirm this action, please click on the following link: 2795 ###CONFIRM_URL### 2796 2797 You can safely ignore and delete this email if you do not want to 2798 take this action. 2799 2800 This email has been sent to ###EMAIL###. 2801 2802 Regards, 2803 All at ###SITENAME### 2804 ###SITEURL###' 2805 ); 2806 2807 $email_data = array( 2808 'action_name' => $action_name, 2809 'email' => $email, 2810 'description' => $action_description, 2811 'confirm_url' => add_query_arg( array( 2812 'action' => 'emailconfirm', 2813 'confirm_action' => $action_name, 2814 'uid' => $uid, 2815 'confirm_key' => $confirm_key, 2816 ), site_url( 'wp-login.php' ) ), 2817 'sitename' => is_multisite() ? get_site_option( 'site_name' ) : get_option( 'blogname' ), 2818 'siteurl' => network_home_url(), 2819 ); 2820 2821 /** 2822 * Filters the text of the email sent when an account action is attempted. 2823 * 2824 * The following strings have a special meaning and will get replaced dynamically: 2825 * ###USERNAME### The user's username, if the user has an account. Prefixed with single space. Otherwise left blank. 2826 * ###DESCRIPTION### Description of the action being performed so the user knows what the email is for. 2827 * ###CONFIRM_URL### The link to click on to confirm the account action. 2828 * ###EMAIL### The email we are sending to. 2829 * ###SITENAME### The name of the site. 2830 * ###SITEURL### The URL to the site. 2831 * 2832 * @param string $email_text Text in the email. 2833 * @param array $email_data { 2834 * Data relating to the account action email. 2835 * 2836 * @type string $action_name Name of the action being performed. 2837 * @type string $email The email address this is being sent to. 2838 * @type string $description Description of the action being performed so the user knows what the email is for. 2839 * @type string $confirm_url The link to click on to confirm the account action. 2840 * @type string $sitename The site name sending the mail. 2841 * @type string $siteurl The site URL sending the mail. 2842 * } 2843 */ 2844 $content = apply_filters( 'confirm_account_action_email_content', $email_text, $email_data ); 2845 2846 $content = str_replace( '###DESCRIPTION###', $email_data['description'], $content ); 2847 $content = str_replace( '###CONFIRM_URL###', esc_url_raw( $email_data['confirm_url'] ), $content ); 2848 $content = str_replace( '###EMAIL###', $email_data['email'], $content ); 2849 $content = str_replace( '###SITENAME###', wp_specialchars_decode( $email_data['sitename'], ENT_QUOTES ), $content ); 2850 $content = str_replace( '###SITEURL###', esc_url_raw( $email_data['siteurl'] ), $content ); 2851 2852 /* translators: %s Site name. */ 2853 return wp_mail( $email_data['email'], sprintf( __( '[%s] Confirm Account Action' ), wp_specialchars_decode( get_option( 'blogname' ), ENT_QUOTES ) ), $content ); 2854 } 2855 2856 /** 2857 * Creates, stores, then returns a confirmation key for an account action. 2858 * 2859 * @since 5.0.0 2860 * 2861 * @param string $action_name Name of the action this key is being generated for. 2862 * @param string $email User email address. This can be the address of a registered or non-registered user. 2863 * 2864 * @return string|WP_Error Confirmation key on success. WP_Error on error. 2865 */ 2866 function get_confirm_account_action_key( $action_name, $email ) { 2867 global $wp_hasher; 2868 2869 if ( ! is_email( $email ) ) { 2870 return new WP_Error( 'invalid_email', __( 'Invalid email address' ) ); 2871 } 2872 2873 if ( empty( $action_name ) ) { 2874 return new WP_Error( 'invalid_action', __( 'Invalid action' ) ); 2875 } 2876 2877 $user = get_user_by( 'email', $email ); 2878 2879 // We could be dealing with a registered user account, or a visitor. 2880 $is_registered_user = $user && ! is_wp_error( $user ); 2881 2882 // Generate something random for a confirmation key. 2883 $key = wp_generate_password( 20, false ); 2884 2885 // Now insert the key, hashed, into the DB. 2886 if ( empty( $wp_hasher ) ) { 2887 require_once ABSPATH . WPINC . '/class-phpass.php'; 2888 $wp_hasher = new PasswordHash( 8, true ); 2889 } 2890 2891 $hashed_key = $wp_hasher->HashPassword( $key ); 2892 2893 if ( $is_registered_user ) { 2894 $key_saved = (bool) update_user_meta( $user->ID, '_account_action_' . $action_name, implode( ':', array( time(), $hashed_key ) ) ); 2895 } else { 2896 $key_saved = (bool) update_site_option( '_account_action_' . hash( 'sha256', $email ) . '_' . $action_name, implode( ':', array( time(), $hashed_key, $email ) ) ); 2897 } 2898 2899 if ( false === $key_saved ) { 2900 return new WP_Error( 'no_confirm_account_action_key_update', __( 'Could not save confirm account action key to database.' ) ); 2901 } 2902 2903 return $key; 2904 } 2905 2906 /** 2907 * Checks if a key is valid and handles the action based on this. 2908 * 2909 * @since 5.0.0 2910 * 2911 * @param string $action_name Name of the action this key is being generated for. 2912 * @param string $key Key to confirm. 2913 * @param string $uid Email hash or user ID. 2914 * 2915 * @return array|WP_Error WP_Error on failure, action name and user email address on success. 2916 */ 2917 function check_confirm_account_action_key( $action_name, $key, $uid ) { 2918 global $wp_hasher; 2919 2920 if ( ! empty( $action_name ) && ! empty( $key ) && ! empty( $uid ) ) { 2921 $user = false; 2922 2923 if ( is_numeric( $uid ) ) { 2924 $user = get_user_by( 'id', absint( $uid ) ); 2925 } 2926 2927 // We could be dealing with a registered user account, or a visitor. 2928 $is_registered_user = $user && ! is_wp_error( $user ); 2929 $key_request_time = ''; 2930 $saved_key = ''; 2931 $email = ''; 2932 2933 if ( empty( $wp_hasher ) ) { 2934 require_once ABSPATH . WPINC . '/class-phpass.php'; 2935 $wp_hasher = new PasswordHash( 8, true ); 2936 } 2937 2938 // Get the saved key from the database. 2939 if ( $is_registered_user ) { 2940 $confirm_action_data = get_user_meta( $user->ID, '_account_action_' . $action_name, true ); 2941 $email = $user->user_email; 2942 2943 if ( false !== strpos( $confirm_action_data, ':' ) ) { 2944 list( $key_request_time, $saved_key ) = explode( ':', $confirm_action_data, 2 ); 2945 } 2946 } else { 2947 $confirm_action_data = get_site_option( '_account_action_' . $uid . '_' . $action_name, '' ); 2948 2949 if ( false !== strpos( $confirm_action_data, ':' ) ) { 2950 list( $key_request_time, $saved_key, $email ) = explode( ':', $confirm_action_data, 3 ); 2951 } 2952 } 2953 2954 if ( ! $saved_key ) { 2955 return new WP_Error( 'invalid_key', __( 'Invalid key' ) ); 2956 } 2957 2958 /** 2959 * Filters the expiration time of confirm keys. 2960 * 2961 * @param int $expiration The expiration time in seconds. 2962 */ 2963 $expiration_duration = apply_filters( 'account_action_expiration', DAY_IN_SECONDS ); 2964 $expiration_time = $key_request_time + $expiration_duration; 2965 2966 if ( $wp_hasher->CheckPassword( $key, $saved_key ) ) { 2967 if ( $expiration_time && time() < $expiration_time ) { 2968 $return = array( 2969 'action' => $action_name, 2970 'email' => $email, 2971 ); 2972 } else { 2973 $return = new WP_Error( 'expired_key', __( 'The confirmation email has expired.' ) ); 2974 } 2975 2976 // Clean up stored keys. 2977 if ( $is_registered_user ) { 2978 delete_user_meta( $user->ID, '_account_action_' . $action_name ); 2979 } else { 2980 delete_site_option( '_account_action_' . $uid . '_' . $action_name ); 2981 } 2982 2983 return $return; 2984 } 2985 } 2986 2987 return new WP_Error( 'invalid_key', __( 'Invalid key' ) ); 2988 } -
branches/4.9/src/wp-login.php
r42895 r43069 414 414 415 415 // validate action so as to default to the login screen 416 if ( !in_array( $action, array( 'postpass', 'logout', 'lostpassword', 'retrievepassword', 'resetpass', 'rp', 'register', 'login' ), true ) && false === has_filter( 'login_form_' . $action ) )416 if ( !in_array( $action, array( 'postpass', 'logout', 'lostpassword', 'retrievepassword', 'resetpass', 'rp', 'register', 'login', 'emailconfirm' ), true ) && false === has_filter( 'login_form_' . $action ) ) 417 417 $action = 'login'; 418 418 … … 838 838 839 839 break; 840 841 case 'emailconfirm' : 842 if ( isset( $_GET['confirm_action'], $_GET['confirm_key'], $_GET['uid'] ) ) { 843 $action_name = sanitize_key( wp_unslash( $_GET['confirm_action'] ) ); 844 $key = sanitize_text_field( wp_unslash( $_GET['confirm_key'] ) ); 845 $uid = sanitize_text_field( wp_unslash( $_GET['uid'] ) ); 846 $result = check_confirm_account_action_key( $action_name, $key, $uid ); 847 } else { 848 $result = new WP_Error( 'invalid_key', __( 'Invalid key' ) ); 849 } 850 851 if ( is_wp_error( $result ) ) { 852 /** 853 * Fires an action hook when the account action was not confirmed. 854 * 855 * After running this action hook the page will die. 856 * 857 * @param WP_Error $result Error object. 858 */ 859 do_action( 'account_action_failed', $result ); 860 861 wp_die( $result ); 862 } 863 864 /** 865 * Fires an action hook when the account action has been confirmed by the user. 866 * 867 * Using this you can assume the user has agreed to perform the action by 868 * clicking on the link in the confirmation email. 869 * 870 * After firing this action hook the page will redirect to wp-login a callback 871 * redirects or exits first. 872 * 873 * @param array $result { 874 * Data about the action which was confirmed. 875 * 876 * @type string $action Name of the action that was confirmed. 877 * @type string $email Email of the user who confirmed the action. 878 * } 879 */ 880 do_action( 'account_action_confirmed', $result ); 881 882 $message = '<p class="message">' . __( 'Action has been confirmed.' ) . '</p>'; 883 login_header( '', $message ); 884 login_footer(); 885 exit; 840 886 841 887 case 'login' :
Note: See TracChangeset
for help on using the changeset viewer.