PluginProbe
GiveWP – Donation Plugin and Fundraising Platform / 4.16.9
GiveWP – Donation Plugin and Fundraising Platform v4.16.9
4.16.9 4.16.8.1 4.16.8 4.16.7.2 4.16.7.1 4.16.7 4.16.6.1 4.16.6 4.16.5.1 4.16.5 4.16.4 4.16.3 4.16.2 4.16.1 4.16.0 4.15.5 4.15.4 4.15.3 4.15.2 4.15.1 4.15.0 2.3.0 2.3.1 2.3.2 2.30.0 All 255 releases
← All changes | includes/process-donation.php +90 -59 4.16.64.16.9 View file →
@@ -23,10 +23,11 @@
23 23 *
24 24 * Handles the donation form process.
25 25 *
26 26 * @access private
27 - * @since 4.16.6 Bail early when the form ID is not a give_forms post or is a Visual Form Builder (v3) form.
28 - * @since 3.16.1 Use give_maybe_safe_unserialize() on $user_info data
27 + * @since 4.16.7.2 Reject serialized data in name fields before storing donation data.
28 + * @since 4.16.6 Bail early when the form ID is not a give_forms post or is a Visual Form Builder (v3) form.
29 + * @since 3.16.1 Use give_maybe_safe_unserialize() on $user_info data
29 30 * @since 1.0
30 31 *
31 32 * @throws ReflectionException Exception Handling.
32 33 *
@@ -162,8 +163,21 @@
162 163 'last_name' => $user['user_last'],
163 164 'address' => $user['address'],
164 165 ];
165 166
167 + // Reject serialized data in name fields.
168 + $serialized_keys = array_filter(
169 + $user_info,
170 + static function ( $value ) {
171 + return is_string( $value ) && \Give\Helpers\Utils::isSerialized( $value );
172 + }
173 + );
174 +
175 + if ( ! empty( $serialized_keys ) ) {
176 + give_set_error( 'give_serialized_user_info', esc_html__( 'Name fields cannot contain serialized data.', 'give' ) );
177 + return;
178 + }
179 +
166 180 $auth_key = defined( 'AUTH_KEY' ) ? AUTH_KEY : '';
167 181
168 182 // Donation form ID.
169 183 $form_id = isset( $post_data['give-form-id'] ) ? absint( $post_data['give-form-id'] ) : 0;
@@ -196,9 +210,9 @@
196 210 $purchase_key
197 211 );
198 212
199 213 // Setup donation information.
200 - $user_info = array_map('\Give\Helpers\Utils::maybeSafeUnserialize', stripslashes_deep( $user_info ));
214 + $user_info = stripslashes_deep( $user_info );
201 215 $donation_data = [
202 216 'price' => $price,
203 217 'purchase_key' => $purchase_key,
204 218 'user_email' => $user['user_email'],
@@ -323,8 +337,9 @@
323 337 /**
324 338 * Process the checkout login form
325 339 *
326 340 * @access private
341 + * @since 4.16.7 Require a valid nonce before processing the login form.
327 342 * @since 1.0
328 343 *
329 344 * @return void
330 345 */
@@ -329,12 +344,23 @@
329 344 * @return void
330 345 */
331 346 function give_process_form_login() {
332 347
333 - $is_ajax = ! empty( $_POST['give_ajax'] ) ? give_clean( $_POST['give_ajax'] ) : 0; // WPCS: input var ok, sanitization ok, CSRF ok.
334 - $referrer = wp_get_referer();
335 - $user_data = give_donation_form_validate_user_login();
348 + $is_ajax = ! empty( $_POST['give_ajax'] ) ? give_clean( $_POST['give_ajax'] ) : 0; // WPCS: input var ok, sanitization ok, CSRF ok.
349 + $referrer = wp_get_referer();
336 350
351 + // Default to no user until the login form is validated.
352 + $user_data = [
353 + 'user_id' => - 1,
354 + ];
355 +
356 + // Require a valid nonce before processing the login form.
357 + if ( empty( $_POST['give_login_nonce'] ) || ! wp_verify_nonce( $_POST['give_login_nonce'], 'give-login-nonce' ) ) {
358 + give_set_error( 'invalid_nonce', __( 'Your session has expired. Please reload the page and try again.', 'give' ) );
359 + } else {
360 + $user_data = give_donation_form_validate_user_login();
361 + }
362 +
337 363 if ( give_get_errors() || $user_data['user_id'] < 1 ) {
338 364 if ( $is_ajax ) {
339 365 /**
340 366 * Fires when AJAX sends back errors from the donation form.
@@ -345,8 +371,9 @@
345 371 do_action( 'give_ajax_donation_errors' );
346 372 $message = ob_get_contents();
347 373 ob_end_clean();
348 374 wp_send_json_error( $message );
375 + return;
349 376 } else {
350 377 wp_safe_redirect( $referrer );
351 378 exit;
352 379 }
@@ -860,8 +887,9 @@
860 887 /**
861 888 * Donation Form Validate Logged In User.
862 889 *
863 890 * @access private
891 + * @since 4.16.7.2 Sanitize first and last name values when falling back to stored user data.
864 892 * @since 1.0
865 893 *
866 894 * @return array
867 895 */
@@ -895,13 +923,13 @@
895 923 'user_email' => ! empty( $post_data['give_email'] )
896 924 ? sanitize_email( $post_data['give_email'] )
897 925 : $user_data->user_email,
898 926 'user_first' => ! empty( $post_data['give_first'] )
899 - ? $post_data['give_first']
900 - : $user_data->first_name,
927 + ? give_clean( $post_data['give_first'] )
928 + : give_clean( $user_data->first_name ),
901 929 'user_last' => ! empty( $post_data['give_last'] )
902 - ? $post_data['give_last']
903 - : $user_data->last_name,
930 + ? give_clean( $post_data['give_last'] )
931 + : give_clean( $user_data->last_name ),
904 932 ];
905 933
906 934 // Validate essential form fields.
907 935 give_donation_form_validate_name_fields( $post_data );
@@ -997,8 +1025,9 @@
997 1025 /**
998 1026 * Donation Form Validate User Login
999 1027 *
1000 1028 * @access private
1029 + * @since 4.16.7 Authenticate via wp_authenticate() and return a single generic error.
1001 1030 * @since 1.0
1002 1031 *
1003 1032 * @return array
1004 1033 */
@@ -1020,61 +1049,55 @@
1020 1049 return $valid_user_data;
1021 1050 }
1022 1051
1023 1052 $give_user_login = strip_tags( $post_data['give_user_login'] );
1024 - if ( is_email( $give_user_login ) ) {
1025 - // Get the user data by email.
1026 - $user_data = get_user_by( 'email', $give_user_login );
1027 - } else {
1028 - // Get the user data by login.
1029 - $user_data = get_user_by( 'login', $give_user_login );
1053 +
1054 + // Bailout, if Password is empty.
1055 + if ( empty( $post_data['give_user_pass'] ) ) {
1056 + give_set_error( 'password_empty', __( 'Enter a password.', 'give' ) );
1057 + return $valid_user_data;
1030 1058 }
1031 1059
1032 - // Check if user exists.
1033 - if ( $user_data ) {
1060 + // Authenticate through WordPress's login machinery so its authentication
1061 + // hooks, password checks, and failed-login actions all apply.
1062 + $user_data = wp_authenticate( $give_user_login, $post_data['give_user_pass'] );
1034 1063
1035 - // Get password.
1036 - $user_pass = ! empty( $post_data['give_user_pass'] ) ? $post_data['give_user_pass'] : false;
1064 + if ( is_wp_error( $user_data ) ) {
1037 1065
1038 - // Check user_pass.
1039 - if ( $user_pass ) {
1066 + $core_auth_error_codes = [
1067 + 'incorrect_password',
1068 + 'invalid_username',
1069 + 'invalid_email',
1070 + 'empty_username',
1071 + 'empty_password',
1072 + ];
1040 1073
1041 - // Check if password is valid.
1042 - if ( ! wp_check_password( $user_pass, $user_data->user_pass, $user_data->ID ) ) {
1074 + if ( in_array( $user_data->get_error_code(), $core_auth_error_codes, true ) ) {
1075 + // A single generic message for an unknown login and a wrong password.
1076 + $error_message = __( 'The login/password does not match or is incorrect.', 'give' );
1077 + } else {
1078 + // Any other error comes from an authentication hook; surface its message.
1079 + $error_message = wp_strip_all_tags( $user_data->get_error_message() );
1043 1080
1044 - $current_page_url = site_url() . '/' . get_page_uri();
1081 + if ( '' === $error_message ) {
1082 + $error_message = __( 'The login/password does not match or is incorrect.', 'give' );
1083 + }
1084 + }
1045 1085
1046 - // Incorrect password.
1047 - give_set_error(
1048 - 'password_incorrect',
1049 - sprintf(
1050 - '%1$s <a href="%2$s">%3$s</a>',
1051 - __( 'The password you entered is incorrect.', 'give' ),
1052 - wp_lostpassword_url( $current_page_url ),
1053 - __( 'Reset Password', 'give' )
1054 - )
1055 - );
1086 + give_set_error( 'invalid_credentials', $error_message );
1056 1087
1057 - } else {
1088 + return $valid_user_data;
1089 + }
1058 1090
1059 - // Repopulate the valid user data array.
1060 - $valid_user_data = [
1061 - 'user_id' => $user_data->ID,
1062 - 'user_login' => $user_data->user_login,
1063 - 'user_email' => $user_data->user_email,
1064 - 'user_first' => $user_data->first_name,
1065 - 'user_last' => $user_data->last_name,
1066 - 'user_pass' => $user_pass,
1067 - ];
1068 - }
1069 - } else {
1070 - // Empty password.
1071 - give_set_error( 'password_empty', __( 'Enter a password.', 'give' ) );
1072 - }
1073 - } else {
1074 - // No username.
1075 - give_set_error( 'username_incorrect', __( 'The username you entered does not exist.', 'give' ) );
1076 - } // End if().
1091 + // Repopulate the valid user data array.
1092 + $valid_user_data = [
1093 + 'user_id' => $user_data->ID,
1094 + 'user_login' => $user_data->user_login,
1095 + 'user_email' => $user_data->user_email,
1096 + 'user_first' => $user_data->first_name,
1097 + 'user_last' => $user_data->last_name,
1098 + 'user_pass' => $post_data['give_user_pass'],
1099 + ];
1077 1100
1078 1101 return $valid_user_data;
1079 1102 }
1080 1103
@@ -1665,11 +1688,12 @@
1665 1688 * Validates and checks if name fields are valid or not.
1666 1689 *
1667 1690 * @param array $post_data List of post data.
1668 1691 *
1669 - * @since 3.16.5 Check if "give_title" is set to prevent PHP warnings
1670 - * @since 3.16.4 Add additional validation for company name field
1671 - * @since 3.16.3 Add additional validations for name title prefix field
1692 + * @since 4.16.7.2 Validate last name field even when omitted.
1693 + * @since 3.16.5 Check if "give_title" is set to prevent PHP warnings
1694 + * @since 3.16.4 Add additional validation for company name field
1695 + * @since 3.16.3 Add additional validations for name title prefix field
1672 1696 * @since 2.1
1673 1697 *
1674 1698 * @return void
1675 1699 */
@@ -1689,11 +1713,18 @@
1689 1713 give_set_error( 'invalid_name_title', esc_html__( 'The name title prefix field is not valid.', 'give' ) );
1690 1714 }
1691 1715
1692 1716 $is_alpha_first_name = ( ! is_email( $post_data['give_first'] ) && ! preg_match( '~[0-9]~', $post_data['give_first'] ) );
1693 - $is_alpha_last_name = ( ! is_email( $post_data['give_last'] ) && ! preg_match( '~[0-9]~', $post_data['give_last'] ) );
1717 +
1718 + $lastName = isset( $post_data['give_last'] ) ? $post_data['give_last'] : '';
1719 + $is_alpha_last_name = ( ! is_email( $lastName ) && ! preg_match( '~[0-9]~', $lastName ) );
1720 +
1694 1721 $is_alpha_title = ( isset($post_data['give_title']) && ! is_email( $post_data['give_title'] ) && ! preg_match( '~[0-9]~', $post_data['give_title'] ) );
1695 1722
1696 - if (!$is_alpha_first_name || ( ! empty( $post_data['give_last'] ) && ! $is_alpha_last_name) || ( ! empty( $post_data['give_title'] ) && ! $is_alpha_title) ) {
1723 + if ( ! $is_alpha_first_name || ( ! empty( $lastName ) && ! $is_alpha_last_name ) || ( ! empty( $post_data['give_title'] ) && ! $is_alpha_title ) ) {
1697 1724 give_set_error( 'invalid_name', esc_html__( 'The First Name and Last Name fields cannot contain an email address or numbers.', 'give' ) );
1725 + }
1726 +
1727 + if ( give_is_last_name_required( $formId ) && empty( $lastName ) ) {
1728 + give_set_error( 'invalid_last_name', esc_html__( 'Please enter your last name.', 'give' ) );
1698 1729 }
1699 1730 }