PluginProbe
GiveWP – Donation Plugin and Fundraising Platform / 4.18.0
GiveWP – Donation Plugin and Fundraising Platform v4.18.0
4.18.0 4.17.0 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 All 257 releases
← All changes | includes/class-give-email-access.php +66 -15 2.3.0 → 4.18.0 View file →
@@ -3,9 +3,9 @@
3 3 * Email Access
4 4 *
5 5 * @package Give
6 6 * @subpackage Classes/Give_Email_Access
7 - * @copyright Copyright (c) 2016, WordImpress
7 + * @copyright Copyright (c) 2016, GiveWP
8 8 * @license https://opensource.org/licenses/gpl-license GNU Public License
9 9 * @since 1.4
10 10 */
11 11
@@ -104,13 +104,28 @@
104 104 * @access public
105 105 */
106 106 public function __construct() {
107 107
108 - // get it started
109 - add_action( 'init', array( $this, 'init' ) );
108 + // Get it started.
109 + add_action( 'wp', [ $this, 'setup' ] );
110 110 }
111 111
112 112 /**
113 + * Setup hooks
114 + *
115 + * @since 2.4.0
116 + */
117 + public function setup() {
118 +
119 + $is_email_access_on_page = apply_filters( 'give_is_email_access_on_page', give_is_success_page() || give_is_history_page() );
120 +
121 + if ( $is_email_access_on_page ) {
122 + // Get it started.
123 + add_action( 'wp', [ $this, 'init' ], 14 );
124 + }
125 + }
126 +
127 + /**
113 128 * Init
114 129 *
115 130 * Register defaults and filters
116 131 *
@@ -140,11 +155,10 @@
140 155 // Setup login.
141 156 $this->check_for_token();
142 157
143 158 if ( $this->token_exists ) {
144 - add_filter( 'give_can_view_receipt', '__return_true' );
145 159 add_filter( 'give_user_pending_verification', '__return_false' );
146 - add_filter( 'give_get_users_donations_args', array( $this, 'users_donations_args' ) );
160 + add_filter( 'give_get_users_donations_args', [ $this, 'users_donations_args' ] );
147 161 }
148 162
149 163 }
150 164
@@ -176,9 +190,8 @@
176 190 give_update_meta( $donor_id, '_give_email_throttle_count', 0 );
177 191 Give_Cache::set( $cache_key, true, $this->verify_throttle );
178 192 return false;
179 193 }
180 -
181 194 }
182 195
183 196 return true;
184 197 }
@@ -198,16 +211,17 @@
198 211 return apply_filters( 'give_email-access_email_notification', $donor_id, $email );
199 212 }
200 213
201 214 /**
202 - * Has the user authenticated?
215 + * This function is used to fetch the token value from query string or cookies based on availability.
203 216 *
204 - * @since 1.0
217 + * @since 4.16.7 Return an empty string for non-string token values.
218 + * @since 2.4.1
205 219 * @access public
206 220 *
207 - * @return bool
221 + * @return string
208 222 */
209 - public function check_for_token() {
223 + public function get_token() {
210 224
211 225 $token = isset( $_GET['give_nl'] ) ? give_clean( $_GET['give_nl'] ) : '';
212 226
213 227 // Check for cookie.
@@ -214,8 +228,23 @@
214 228 if ( empty( $token ) ) {
215 229 $token = isset( $_COOKIE['give_nl'] ) ? give_clean( $_COOKIE['give_nl'] ) : '';
216 230 }
217 231
232 + return is_string( $token ) ? $token : '';
233 + }
234 +
235 + /**
236 + * Has the user authenticated?
237 + *
238 + * @since 1.0
239 + * @access public
240 + *
241 + * @return bool
242 + */
243 + public function check_for_token() {
244 +
245 + $token = $this->get_token();
246 +
218 247 // Must have a token.
219 248 if ( ! empty( $token ) ) {
220 249
221 250 if ( ! $this->is_valid_token( $token ) ) {
@@ -224,10 +253,12 @@
224 253 }
225 254 }
226 255
227 256 // Set Receipt Access Session.
257 + Give()->session->maybe_start_session();
228 258 Give()->session->set( 'receipt_access', true );
229 259 $this->token_exists = true;
260 +
230 261 // Set cookie.
231 262 $lifetime = current_time( 'timestamp' ) + Give()->session->set_expiration_time();
232 263 @setcookie( 'give_nl', $token, $lifetime, COOKIEPATH, COOKIE_DOMAIN, false );
233 264
@@ -232,13 +263,16 @@
232 263 @setcookie( 'give_nl', $token, $lifetime, COOKIEPATH, COOKIE_DOMAIN, false );
233 264
234 265 return true;
235 266 }
267 +
268 + return false;
236 269 }
237 270
238 271 /**
239 272 * Is this a valid token?
240 273 *
274 + * @since 4.16.7 Only accept non-empty string tokens.
241 275 * @since 1.0
242 276 * @access public
243 277 *
244 278 * @param $token string The token.
@@ -248,8 +282,13 @@
248 282 public function is_valid_token( $token ) {
249 283
250 284 global $wpdb;
251 285
286 + // A crafted give_nl[]= parameter arrives as an array; reject non-string and empty tokens.
287 + if ( ! is_string( $token ) || '' === $token ) {
288 + return false;
289 + }
290 +
252 291 // Make sure token isn't expired.
253 292 $expires = date( 'Y-m-d H:i:s', time() - $this->token_expiration );
254 293
255 294 $email = $wpdb->get_var(
@@ -262,10 +301,13 @@
262 301 return true;
263 302 }
264 303
265 304 // Set error only if email access form isn't being submitted.
266 - if ( ! isset( $_POST['give_email'] ) && ! isset( $_POST['_wpnonce'] ) ) {
267 - give_set_error( 'give_email_token_expired', apply_filters( 'give_email_token_expired_message', __( 'Your access token has expired. Please request a new one below:', 'give' ) ) );
305 + if (
306 + ! isset( $_POST['give_email'] ) &&
307 + ! isset( $_POST['_wpnonce'] )
308 + ) {
309 + give_set_error( 'give_email_token_expired', apply_filters( 'give_email_token_expired_message', __( 'Your access token has expired. Please request a new one.', 'give' ) ) );
268 310 }
269 311
270 312 return false;
271 313
@@ -308,8 +350,10 @@
308 350
309 351 /**
310 352 * Is this a valid verify key?
311 353 *
354 + * @since 4.18.0 Verify keys expire with the same window as access tokens.
355 + * @since 4.16.7 Only accept non-empty string tokens.
312 356 * @since 1.0
313 357 * @access public
314 358 *
315 359 * @param $token string The token.
@@ -319,11 +363,20 @@
319 363 public function is_valid_verify_key( $token ) {
320 364 /* @var WPDB $wpdb */
321 365 global $wpdb;
322 366
367 + // A crafted give_nl[]= parameter arrives as an array; reject non-string and empty tokens.
368 + if ( ! is_string( $token ) || '' === $token ) {
369 + return false;
370 + }
371 +
372 + // A verify key expires with the same window as an access token, so a
373 + // key generated before that window can no longer be redeemed.
374 + $expires = date( 'Y-m-d H:i:s', time() - $this->token_expiration );
375 +
323 376 // See if the verify_key exists.
324 377 $row = $wpdb->get_row(
325 - $wpdb->prepare( "SELECT id, email FROM {$wpdb->donors} WHERE verify_key = %s LIMIT 1", $token )
378 + $wpdb->prepare( "SELECT id, email FROM {$wpdb->donors} WHERE verify_key = %s AND verify_throttle >= %s LIMIT 1", $token, $expires )
326 379 );
327 380
328 381 $now = date( 'Y-m-d H:i:s' );
329 382
@@ -355,9 +408,8 @@
355 408 * @return mixed
356 409 */
357 410 public function users_donations_args( $args ) {
358 411 $args['user'] = $this->token_email;
359 -
360 412 return $args;
361 413 }
362 414
363 415 /**
@@ -376,6 +428,5 @@
376 428
377 429 // Create columns in donors table.
378 430 $wpdb->query( "ALTER TABLE {$wpdb->donors} ADD `token` VARCHAR(255) CHARACTER SET utf8 NOT NULL, ADD `verify_key` VARCHAR(255) CHARACTER SET utf8 NOT NULL AFTER `token`, ADD `verify_throttle` DATETIME NOT NULL AFTER `verify_key`" );
379 431 }
380 -
381 432 }