PluginProbe
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) / 1.8.11.1
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) v1.8.11.1
1.8.13.1 1.8.13 1.8.12.3 1.8.12.2 1.8.12.1 1.8.12 1.8.11.3 1.8.11.2 1.8.11.1 1.8.11 1.6.6 1.6.60 1.6.7 1.6.8 1.6.9 1.7.0 1.7.0.1 1.7.0.11 1.7.0.12 1.7.0.14 1.7.0.2 1.7.0.3 1.7.0.5 1.7.0.6 1.7.0.7 All 212 releases
charitable / includes / forms / class-charitable-reset-password-form.php

class-charitable-reset-password-form.php in Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) 1.8.11.1, at includes/forms/class-charitable-reset-password-form.php

268 lines 6.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Class that manages the display and processing of the reset password form.
4 *
5 * @package Charitable/Classes/Charitable_Reset_Password_Form
6 * @version 1.5.1
7 * @author Rafe Colton, David Bisset
8 * @copyright Copyright (c) 2023, WP Charitable LLC
9 * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
10 */
11 if ( ! defined( 'ABSPATH' ) ) {
12 exit;
13 }
14
15 if ( ! class_exists( 'Charitable_Reset_Password_Form' ) ) :
16
17 /**
18 * Charitable_Reset_Password_Form
19 *
20 * @since 1.4.0
21 */
22 class Charitable_Reset_Password_Form extends Charitable_Form {
23
24 /**
25 * @since 1.4.0
26 *
27 * @var string
28 */
29 protected $nonce_action = 'charitable_reset_password';
30
31 /**
32 * @since 1.4.0
33 *
34 * @var string
35 */
36 protected $nonce_name = '_charitable_reset_password_nonce';
37
38 /**
39 * Form action.
40 *
41 * @since 1.4.0
42 *
43 * @var string
44 */
45 protected $form_action = 'reset_password';
46
47 /**
48 * Reset key.
49 *
50 * @since 1.4.0
51 *
52 * @var string|null
53 */
54 protected $key;
55
56 /**
57 * Form action.
58 *
59 * @since 1.4.0
60 *
61 * @var string|null
62 */
63 protected $login;
64
65 /**
66 * Whether the reset key is available.
67 *
68 * @since 1.5.0
69 *
70 * @var boolean
71 */
72 protected $has_key;
73
74 /**
75 * Create class object.
76 *
77 * @since 1.4.0
78 *
79 * @param array $args User-defined shortcode attributes.
80 */
81 public function __construct( $args = array() ) {
82 $this->id = uniqid();
83 $this->has_key = $this->parse_reset_key();
84
85 /* For backwards-compatibility */
86 add_action( 'charitable_form_field', array( $this, 'render_field' ), 10, 6 );
87 }
88
89 /**
90 * Return whether the reset key is set correctly.
91 *
92 * If this returns false, the password reset will always fail so we avoid
93 * displaying the form at all.
94 *
95 * @since 1.5.0
96 *
97 * @return boolean
98 */
99 public function has_key() {
100 return $this->has_key;
101 }
102
103 /**
104 * Retrieve hidden fields.
105 *
106 * @since 1.5.0
107 *
108 * @return array
109 */
110 public function get_hidden_fields() {
111 $fields = parent::get_hidden_fields();
112 $fields['key'] = $this->key;
113 $fields['login'] = array(
114 'value' => $this->login,
115 'autocomplete' => 'off',
116 );
117 return $fields;
118 }
119
120 /**
121 * Reset password fields to be displayed.
122 *
123 * @since 1.4.0
124 *
125 * @return array
126 */
127 public function get_fields() {
128 if ( ! $this->has_key ) {
129 return array();
130 }
131
132 $fields = apply_filters( 'charitable_reset_password_fields', array(
133 'pass1' => array(
134 'label' => __( 'New Password', 'charitable' ),
135 'type' => 'password',
136 'required' => true,
137 'priority' => 10,
138 'attrs' => array(
139 'size' => 20,
140 'autocomplete' => 'off',
141 ),
142 ),
143 'pass2' => array(
144 'label' => __( 'Repeat New Password', 'charitable' ),
145 'type' => 'password',
146 'required' => true,
147 'priority' => 11,
148 'attrs' => array(
149 'size' => 20,
150 'autocomplete' => 'off',
151 ),
152 ),
153 ) );
154
155 uasort( $fields, 'charitable_priority_sort' );
156
157 return $fields;
158 }
159
160 /**
161 * Reset the password.
162 *
163 * @since 1.4.0
164 * @version 1.8.9.1
165 *
166 * @return bool|WP_Error True: when finish. WP_Error on error
167 */
168 public static function reset_password() {
169 $form = new Charitable_Reset_Password_Form();
170
171 if ( ! $form->validate_nonce() || ! $form->validate_honeypot() ) {
172 charitable_get_notices()->add_error( __( 'Unfortunately, we were unable to verify your form submission. Please reload the page and try again.', 'charitable' ) );
173 return;
174 }
175
176 // phpcs:disable WordPress.Security.NonceVerification.Missing
177 /* The key and login must be set. */
178 if ( ! isset( $_POST['key'] ) || ! isset( $_POST['login'] ) ) {
179 charitable_get_notices()->add_error( '<strong>ERROR:</strong> Invalid reset key.', 'charitable' );
180 return;
181 }
182
183 $key = sanitize_text_field( wp_unslash( $_POST['key'] ) );
184 $login = sanitize_text_field( wp_unslash( $_POST['login'] ) );
185
186 $user = check_password_reset_key( $key, $login );
187
188 if ( is_wp_error( $user ) ) {
189 charitable_get_notices()->add_errors_from_wp_error( $user );
190 return;
191 }
192
193 /* One of the passwords was not set. */
194 if ( ! isset( $_POST['pass1'] ) || ! isset( $_POST['pass2'] ) ) {
195 charitable_get_notices()->add_error( '<strong>ERROR:</strong> You must enter both passwords.', 'charitable' );
196 return;
197 }
198
199 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Password fields should not be sanitized
200 $pass1 = wp_unslash( $_POST['pass1'] );
201 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Password fields should not be sanitized
202 $pass2 = wp_unslash( $_POST['pass2'] );
203
204 /* The passwords do not match. */
205 if ( $pass1 != $pass2 ) {
206 charitable_get_notices()->add_error( __( '<strong>ERROR:</strong> The two passwords you entered don\'t match.', 'charitable' ) );
207 return;
208 }
209
210 /* Parameter checks OK, reset password */
211 reset_password( $user, $pass1 );
212 // phpcs:enable WordPress.Security.NonceVerification.Missing
213
214 charitable_get_notices()->add_success( __( 'Your password was successfully changed.', 'charitable' ) );
215
216 charitable_get_session()->add_notices();
217
218 wp_safe_redirect( charitable_get_permalink( 'login_page' ) );
219
220 exit();
221 }
222
223 /**
224 * Get the reset key and login from the cookie.
225 *
226 * @since 1.4.0
227 * @since 1.5.0 Returns a boolean to indicate whether the key and login are available.
228 * @version 1.8.9.1
229 *
230 * @return boolean True if the reset key is found. False otherwise.
231 */
232 protected function parse_reset_key() {
233 $this->key = null;
234 $this->login = null;
235
236 if ( ! isset( $_COOKIE[ 'wp-resetpass-' . COOKIEHASH ] ) ) {
237 charitable_get_notices()->add_error( __( 'Missing password reset key.', 'charitable' ) );
238 return false;
239 }
240
241 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized,WordPress.Security.ValidatedSanitizedInput.MissingUnslash
242 $cookie = $_COOKIE[ 'wp-resetpass-' . COOKIEHASH ];
243
244 if ( ! strpos( $cookie, ':' ) ) {
245 charitable_get_notices()->add_error( __( 'Missing password reset key.', 'charitable' ) );
246 return false;
247 }
248
249 $cookie_parts = explode( ':', wp_unslash( $cookie ), 2 );
250 list( $login, $key ) = array_map( 'sanitize_text_field', $cookie_parts );
251 $user = check_password_reset_key( $key, $login );
252
253 if ( is_wp_error( $user ) ) {
254 charitable_get_notices()->add_errors_from_wp_error( $user );
255 Charitable_User_Management::get_instance()->set_reset_cookie();
256 return false;
257 }
258
259 /* Reset key / login is correct, display reset password form with hidden key / login values */
260 $this->key = $key;
261 $this->login = $login;
262
263 return true;
264 }
265 }
266
267 endif;
268