PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / trunk
GiveWP – Donation Plugin and Fundraising Platform vtrunk
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 2.31.0 2.31.1 2.32.0 2.33.0 2.33.1 2.33.2 2.33.3 2.33.4 2.33.5 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.4.7 2.5.0 2.5.1 2.5.10 2.5.11 2.5.12 2.5.13 2.5.2 2.5.3 2.5.4 2.5.5 2.5.6 2.5.7 2.5.8 2.5.9 2.6.0 2.6.1 2.6.2 2.6.3 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.8.0 2.8.1 2.9.0 2.9.1 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.10.0 3.11.0 3.12.0 3.12.1 3.12.2 3.12.3 3.13.0 3.14.0 3.14.1 3.14.2 3.15.0 3.15.1 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.16.5 3.17.0 3.17.1 3.17.2 3.18.0 3.19.0 3.19.1 3.19.2 3.19.3 3.19.4 3.2.0 3.2.1 3.2.2 3.20.0 3.21.0 3.21.1 3.22.0 3.22.1 3.22.2 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.5.1 3.6.0 3.6.1 3.6.2 3.7.0 3.8.0 3.9.0 4.0.0 4.1.0 4.1.1 4.10.0 4.10.1 4.11.0 4.12.0 4.13.0 4.13.1 4.13.2 4.14.0 4.14.1 4.14.2 4.14.3 4.14.4 4.14.5 4.14.6 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.1 4.7.0 4.7.1 4.8.0 4.8.1 4.9.0 trunk 1.9.0 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.2 2.11.3 2.12.0 2.12.1 2.12.2 2.12.3 2.13.0 2.13.1 2.13.2 2.13.3 2.13.4 2.14.0 2.15.0 2.16.0 2.16.1 2.17.0 2.17.1 2.17.3 2.18.0 2.18.1 2.19.1 2.19.2 2.19.3 2.19.4 2.19.5 2.19.6 2.19.7 2.19.8 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.20.0 2.20.1 2.20.2 2.21.0 2.21.1 2.21.2 2.21.3 2.21.4 2.22.0 2.22.1 2.22.2 2.22.3 2.23.0 2.23.1 2.23.2 2.24.0 2.24.1 2.24.2 2.25.0 2.25.1 2.25.2 2.25.3 2.26.0 2.27.0 2.27.1 2.27.2 2.27.3 2.28.0 2.29.0 2.29.1 2.29.2
give / includes / class-give-email-access.php
give / includes Last commit date
admin 3 days ago api 3 years ago database 2 weeks ago deprecated 3 months ago donors 6 months ago emails 11 months ago forms 3 days ago frontend 6 years ago gateways 2 weeks ago libraries 11 months ago payments 1 month ago actions.php 2 weeks ago ajax-functions.php 1 month ago class-give-async-process.php 2 years ago class-give-background-updater.php 11 months ago class-give-cache-setting.php 1 year ago class-give-cache.php 11 months ago class-give-cli-commands.php 1 year ago class-give-comment.php 11 months ago class-give-cron.php 11 months ago class-give-donate-form.php 2 years ago class-give-donor.php 2 years ago class-give-email-access.php 3 days ago class-give-license-handler.php 3 months ago class-give-logging.php 11 months ago class-give-readme-parser.php 4 years ago class-give-roles.php 6 months ago class-give-scripts.php 1 month ago class-give-session.php 11 months ago class-give-stats.php 6 years ago class-give-template-loader.php 6 years ago class-give-tooltips.php 6 years ago class-give-translation.php 4 years ago class-notices.php 11 months ago country-functions.php 9 months ago currencies-list.php 9 months ago currency-functions.php 4 years ago error-tracking.php 6 years ago filters.php 11 months ago formatting.php 10 months ago install.php 11 months ago login-register.php 2 weeks ago misc-functions.php 3 days ago plugin-compatibility.php 6 years ago post-types.php 1 year ago price-functions.php 6 years ago process-donation.php 3 days ago setting-functions.php 7 years ago shortcodes.php 1 year ago template-functions.php 1 year ago user-functions.php 4 years ago
class-give-email-access.php
428 lines
1 <?php
2 /**
3 * Email Access
4 *
5 * @package Give
6 * @subpackage Classes/Give_Email_Access
7 * @copyright Copyright (c) 2016, GiveWP
8 * @license https://opensource.org/licenses/gpl-license GNU Public License
9 * @since 1.4
10 */
11
12 // Exit if accessed directly.
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit;
15 }
16
17 /**
18 * Give_Email_Access class
19 *
20 * This class handles email access, allowing donors access to their donation w/o logging in;
21 *
22 * Based on the work from Matt Gibbs - https://github.com/FacetWP/edd-no-logins
23 *
24 * @since 1.0
25 */
26 class Give_Email_Access {
27
28 /**
29 * Token exists
30 *
31 * @since 1.0
32 * @access public
33 *
34 * @var bool
35 */
36 public $token_exists = false;
37
38 /**
39 * Token email
40 *
41 * @since 1.0
42 * @access public
43 *
44 * @var bool
45 */
46 public $token_email = false;
47
48 /**
49 * Token
50 *
51 * @since 1.0
52 * @access public
53 *
54 * @var bool
55 */
56 public $token = false;
57
58 /**
59 * Error
60 *
61 * @since 1.0
62 * @access public
63 *
64 * @var string
65 */
66 public $error = '';
67
68 /**
69 * Verify throttle
70 *
71 * @since 1.0
72 * @access public
73 *
74 * @var
75 */
76 public $verify_throttle;
77
78 /**
79 * Limit throttle
80 *
81 * @since 1.8.17
82 * @access public
83 *
84 * @var
85 */
86 public $limit_throttle;
87
88 /**
89 * Verify expiration
90 *
91 * @since 1.0
92 * @access private
93 *
94 * @var string
95 */
96 private $token_expiration;
97
98 /**
99 * Class Constructor
100 *
101 * Set up the Give Email Access Class.
102 *
103 * @since 1.0
104 * @access public
105 */
106 public function __construct() {
107
108 // Get it started.
109 add_action( 'wp', [ $this, 'setup' ] );
110 }
111
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 /**
128 * Init
129 *
130 * Register defaults and filters
131 *
132 * @since 1.0
133 * @access public
134 *
135 * @return void
136 */
137 public function init() {
138
139 // Bail Out, if user is logged in.
140 if ( is_user_logged_in() ) {
141 return;
142 }
143
144 // Are db columns setup?
145 $column_exists = Give()->donors->does_column_exist( 'token' );
146 if ( ! $column_exists ) {
147 $this->create_columns();
148 }
149
150 // Timeouts.
151 $this->verify_throttle = apply_filters( 'give_nl_verify_throttle', 300 );
152 $this->limit_throttle = apply_filters( 'give_nl_limit_throttle', 3 );
153 $this->token_expiration = apply_filters( 'give_nl_token_expiration', 7200 );
154
155 // Setup login.
156 $this->check_for_token();
157
158 if ( $this->token_exists ) {
159 add_filter( 'give_user_pending_verification', '__return_false' );
160 add_filter( 'give_get_users_donations_args', [ $this, 'users_donations_args' ] );
161 }
162
163 }
164
165 /**
166 * Prevent email spamming.
167 *
168 * @param int $donor_id Donor ID.
169 *
170 * @since 1.0
171 * @access public
172 *
173 * @return bool
174 */
175 public function can_send_email( $donor_id ) {
176
177 $donor = Give()->donors->get_donor_by( 'id', $donor_id );
178
179 if ( is_object( $donor ) ) {
180
181 $email_throttle_count = (int) give_get_meta( $donor_id, '_give_email_throttle_count', true );
182
183 $cache_key = "give_cache_email_throttle_limit_exhausted_{$donor_id}";
184 if (
185 $email_throttle_count < $this->limit_throttle &&
186 true !== Give_Cache::get( $cache_key )
187 ) {
188 give_update_meta( $donor_id, '_give_email_throttle_count', $email_throttle_count + 1 );
189 } else {
190 give_update_meta( $donor_id, '_give_email_throttle_count', 0 );
191 Give_Cache::set( $cache_key, true, $this->verify_throttle );
192 return false;
193 }
194 }
195
196 return true;
197 }
198
199 /**
200 * Send the user's token
201 *
202 * @param int $donor_id Donor id.
203 * @param string $email Donor email.
204 *
205 * @since 1.0
206 * @access public
207 *
208 * @return bool
209 */
210 public function send_email( $donor_id, $email ) {
211 return apply_filters( 'give_email-access_email_notification', $donor_id, $email );
212 }
213
214 /**
215 * This function is used to fetch the token value from query string or cookies based on availability.
216 *
217 * @since 4.16.7 Return an empty string for non-string token values.
218 * @since 2.4.1
219 * @access public
220 *
221 * @return string
222 */
223 public function get_token() {
224
225 $token = isset( $_GET['give_nl'] ) ? give_clean( $_GET['give_nl'] ) : '';
226
227 // Check for cookie.
228 if ( empty( $token ) ) {
229 $token = isset( $_COOKIE['give_nl'] ) ? give_clean( $_COOKIE['give_nl'] ) : '';
230 }
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
247 // Must have a token.
248 if ( ! empty( $token ) ) {
249
250 if ( ! $this->is_valid_token( $token ) ) {
251 if ( ! $this->is_valid_verify_key( $token ) ) {
252 return false;
253 }
254 }
255
256 // Set Receipt Access Session.
257 Give()->session->maybe_start_session();
258 Give()->session->set( 'receipt_access', true );
259 $this->token_exists = true;
260
261 // Set cookie.
262 $lifetime = current_time( 'timestamp' ) + Give()->session->set_expiration_time();
263 @setcookie( 'give_nl', $token, $lifetime, COOKIEPATH, COOKIE_DOMAIN, false );
264
265 return true;
266 }
267
268 return false;
269 }
270
271 /**
272 * Is this a valid token?
273 *
274 * @since 4.16.7 Only accept non-empty string tokens.
275 * @since 1.0
276 * @access public
277 *
278 * @param $token string The token.
279 *
280 * @return bool
281 */
282 public function is_valid_token( $token ) {
283
284 global $wpdb;
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
291 // Make sure token isn't expired.
292 $expires = date( 'Y-m-d H:i:s', time() - $this->token_expiration );
293
294 $email = $wpdb->get_var(
295 $wpdb->prepare( "SELECT email FROM {$wpdb->donors} WHERE verify_key = %s AND verify_throttle >= %s LIMIT 1", $token, $expires )
296 );
297
298 if ( ! empty( $email ) ) {
299 $this->token_email = $email;
300 $this->token = $token;
301 return true;
302 }
303
304 // Set error only if email access form isn't being submitted.
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' ) ) );
310 }
311
312 return false;
313
314 }
315
316 /**
317 * Add the verify key to DB
318 *
319 * @param int $donor_id Donor id.
320 * @param string $email Donor email.
321 * @param string $verify_key The verification key.
322 *
323 * @since 1.0
324 * @access public
325 *
326 * @return void
327 */
328 public function set_verify_key( $donor_id, $email, $verify_key ) {
329 global $wpdb;
330
331 $now = date( 'Y-m-d H:i:s' );
332
333 // Insert or update?
334 $row_id = (int) $wpdb->get_var(
335 $wpdb->prepare( "SELECT id FROM {$wpdb->donors} WHERE id = %d LIMIT 1", $donor_id )
336 );
337
338 // Update.
339 if ( ! empty( $row_id ) ) {
340 $wpdb->query(
341 $wpdb->prepare( "UPDATE {$wpdb->donors} SET verify_key = %s, verify_throttle = %s WHERE id = %d LIMIT 1", $verify_key, $now, $row_id )
342 );
343 } // Insert.
344 else {
345 $wpdb->query(
346 $wpdb->prepare( "INSERT INTO {$wpdb->donors} ( verify_key, verify_throttle) VALUES (%s, %s)", $verify_key, $now )
347 );
348 }
349 }
350
351 /**
352 * Is this a valid verify key?
353 *
354 * @since 4.16.7 Only accept non-empty string tokens.
355 * @since 1.0
356 * @access public
357 *
358 * @param $token string The token.
359 *
360 * @return bool
361 */
362 public function is_valid_verify_key( $token ) {
363 /* @var WPDB $wpdb */
364 global $wpdb;
365
366 // A crafted give_nl[]= parameter arrives as an array; reject non-string and empty tokens.
367 if ( ! is_string( $token ) || '' === $token ) {
368 return false;
369 }
370
371 // See if the verify_key exists.
372 $row = $wpdb->get_row(
373 $wpdb->prepare( "SELECT id, email FROM {$wpdb->donors} WHERE verify_key = %s LIMIT 1", $token )
374 );
375
376 $now = date( 'Y-m-d H:i:s' );
377
378 // Set token and remove verify key.
379 if ( ! empty( $row ) ) {
380 $wpdb->query(
381 $wpdb->prepare( "UPDATE {$wpdb->donors} SET verify_key = '', token = %s, verify_throttle = %s WHERE id = %d LIMIT 1", $token, $now, $row->id )
382 );
383
384 $this->token_email = $row->email;
385 $this->token = $token;
386
387 return true;
388 }
389
390 return false;
391 }
392
393 /**
394 * Users donations args
395 *
396 * Force Give to find donations by email, not user ID.
397 *
398 * @since 1.0
399 * @access public
400 *
401 * @param $args array User Donations arguments.
402 *
403 * @return mixed
404 */
405 public function users_donations_args( $args ) {
406 $args['user'] = $this->token_email;
407 return $args;
408 }
409
410 /**
411 * Create required columns
412 *
413 * Create the necessary columns for email access
414 *
415 * @since 1.0
416 * @access public
417 *
418 * @return void
419 */
420 public function create_columns() {
421
422 global $wpdb;
423
424 // Create columns in donors table.
425 $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`" );
426 }
427 }
428