This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * Email Access |
||
4 | * |
||
5 | * @package Give |
||
6 | * @subpackage Classes/Give_Email_Access |
||
7 | * @copyright Copyright (c) 2016, WordImpress |
||
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( 'init', array( $this, 'init' ) ); |
||
110 | } |
||
111 | |||
112 | /** |
||
113 | * Init |
||
114 | * |
||
115 | * Register defaults and filters |
||
116 | * |
||
117 | * @since 1.0 |
||
118 | * @access public |
||
119 | * |
||
120 | * @return void |
||
121 | */ |
||
122 | public function init() { |
||
123 | |||
124 | // Bail Out, if user is logged in. |
||
125 | if ( is_user_logged_in() ) { |
||
126 | return; |
||
127 | } |
||
128 | |||
129 | // Are db columns setup? |
||
130 | $column_exists = Give()->donors->does_column_exist( 'token' ); |
||
131 | if ( ! $column_exists ) { |
||
132 | $this->create_columns(); |
||
133 | } |
||
134 | |||
135 | // Timeouts. |
||
136 | $this->verify_throttle = apply_filters( 'give_nl_verify_throttle', 300 ); |
||
137 | $this->limit_throttle = apply_filters( 'give_nl_limit_throttle', 3 ); |
||
138 | $this->token_expiration = apply_filters( 'give_nl_token_expiration', 7200 ); |
||
139 | |||
140 | // Setup login. |
||
141 | $this->check_for_token(); |
||
142 | |||
143 | if ( $this->token_exists ) { |
||
144 | add_filter( 'give_can_view_receipt', '__return_true' ); |
||
145 | add_filter( 'give_user_pending_verification', '__return_false' ); |
||
146 | add_filter( 'give_get_users_donations_args', array( $this, 'users_donations_args' ) ); |
||
147 | } |
||
148 | |||
149 | } |
||
150 | |||
151 | /** |
||
152 | * Prevent email spamming. |
||
153 | * |
||
154 | * @param int $donor_id Donor ID. |
||
155 | * |
||
156 | * @since 1.0 |
||
157 | * @access public |
||
158 | * |
||
159 | * @return bool |
||
160 | */ |
||
161 | public function can_send_email( $donor_id ) { |
||
162 | |||
163 | $donor = Give()->donors->get_donor_by( 'id', $donor_id ); |
||
164 | |||
165 | if ( is_object( $donor ) ) { |
||
166 | |||
167 | $email_throttle_count = (int) give_get_meta( $donor_id, '_give_email_throttle_count', true ); |
||
168 | |||
169 | $cache_key = "give_cache_email_throttle_limit_exhausted_{$donor_id}"; |
||
170 | if ( |
||
171 | $email_throttle_count < $this->limit_throttle && |
||
172 | true !== Give_Cache::get( $cache_key ) |
||
173 | ) { |
||
174 | give_update_meta( $donor_id, '_give_email_throttle_count', $email_throttle_count + 1 ); |
||
175 | } else { |
||
176 | give_update_meta( $donor_id, '_give_email_throttle_count', 0 ); |
||
177 | Give_Cache::set( $cache_key, true, $this->verify_throttle ); |
||
178 | return false; |
||
179 | } |
||
0 ignored issues
–
show
introduced
by
![]() |
|||
180 | |||
181 | } |
||
182 | |||
183 | return true; |
||
184 | } |
||
185 | |||
186 | /** |
||
187 | * Send the user's token |
||
188 | * |
||
189 | * @param int $donor_id Donor id. |
||
190 | * @param string $email Donor email. |
||
191 | * |
||
192 | * @since 1.0 |
||
193 | * @access public |
||
194 | * |
||
195 | * @return bool |
||
196 | */ |
||
197 | public function send_email( $donor_id, $email ) { |
||
198 | return apply_filters( 'give_email-access_email_notification', $donor_id, $email ); |
||
199 | } |
||
200 | |||
201 | /** |
||
202 | * Has the user authenticated? |
||
203 | * |
||
204 | * @since 1.0 |
||
205 | * @access public |
||
206 | * |
||
207 | * @return bool |
||
208 | */ |
||
209 | public function check_for_token() { |
||
210 | |||
211 | $token = isset( $_GET['give_nl'] ) ? give_clean( $_GET['give_nl'] ) : ''; |
||
0 ignored issues
–
show
|
|||
212 | |||
213 | // Check for cookie. |
||
214 | if ( empty( $token ) ) { |
||
215 | $token = isset( $_COOKIE['give_nl'] ) ? give_clean( $_COOKIE['give_nl'] ) : ''; |
||
0 ignored issues
–
show
|
|||
216 | } |
||
217 | |||
218 | // Must have a token. |
||
219 | if ( ! empty( $token ) ) { |
||
220 | |||
221 | if ( ! $this->is_valid_token( $token ) ) { |
||
222 | if ( ! $this->is_valid_verify_key( $token ) ) { |
||
223 | return false; |
||
224 | } |
||
225 | } |
||
226 | |||
227 | // Set Receipt Access Session. |
||
228 | Give()->session->set( 'receipt_access', true ); |
||
229 | $this->token_exists = true; |
||
230 | // Set cookie. |
||
231 | $lifetime = current_time( 'timestamp' ) + Give()->session->set_expiration_time(); |
||
232 | @setcookie( 'give_nl', $token, $lifetime, COOKIEPATH, COOKIE_DOMAIN, false ); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
233 | |||
234 | return true; |
||
235 | } |
||
236 | } |
||
237 | |||
238 | /** |
||
239 | * Is this a valid token? |
||
240 | * |
||
241 | * @since 1.0 |
||
242 | * @access public |
||
243 | * |
||
244 | * @param $token string The token. |
||
245 | * |
||
246 | * @return bool |
||
247 | */ |
||
248 | public function is_valid_token( $token ) { |
||
249 | |||
250 | global $wpdb; |
||
251 | |||
252 | // Make sure token isn't expired. |
||
253 | $expires = date( 'Y-m-d H:i:s', time() - $this->token_expiration ); |
||
254 | |||
255 | $email = $wpdb->get_var( |
||
0 ignored issues
–
show
|
|||
256 | $wpdb->prepare( "SELECT email FROM {$wpdb->donors} WHERE verify_key = %s AND verify_throttle >= %s LIMIT 1", $token, $expires ) |
||
257 | ); |
||
258 | |||
259 | if ( ! empty( $email ) ) { |
||
260 | $this->token_email = $email; |
||
261 | $this->token = $token; |
||
262 | return true; |
||
263 | } |
||
264 | |||
265 | // Set error only if email access form isn't being submitted. |
||
266 | if ( ! isset( $_POST['give_email'] ) && ! isset( $_POST['_wpnonce'] ) ) { |
||
0 ignored issues
–
show
|
|||
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' ) ) ); |
||
268 | } |
||
269 | |||
270 | return false; |
||
271 | |||
272 | } |
||
273 | |||
274 | /** |
||
275 | * Add the verify key to DB |
||
276 | * |
||
277 | * @param int $donor_id Donor id. |
||
278 | * @param string $email Donor email. |
||
279 | * @param string $verify_key The verification key. |
||
280 | * |
||
281 | * @since 1.0 |
||
282 | * @access public |
||
283 | * |
||
284 | * @return void |
||
285 | */ |
||
286 | public function set_verify_key( $donor_id, $email, $verify_key ) { |
||
0 ignored issues
–
show
|
|||
287 | global $wpdb; |
||
288 | |||
289 | $now = date( 'Y-m-d H:i:s' ); |
||
290 | |||
291 | // Insert or update? |
||
292 | $row_id = (int) $wpdb->get_var( |
||
0 ignored issues
–
show
|
|||
293 | $wpdb->prepare( "SELECT id FROM {$wpdb->donors} WHERE id = %d LIMIT 1", $donor_id ) |
||
294 | ); |
||
295 | |||
296 | // Update. |
||
297 | if ( ! empty( $row_id ) ) { |
||
298 | $wpdb->query( |
||
0 ignored issues
–
show
|
|||
299 | $wpdb->prepare( "UPDATE {$wpdb->donors} SET verify_key = %s, verify_throttle = %s WHERE id = %d LIMIT 1", $verify_key, $now, $row_id ) |
||
300 | ); |
||
301 | } // Insert. |
||
302 | else { |
||
303 | $wpdb->query( |
||
0 ignored issues
–
show
|
|||
304 | $wpdb->prepare( "INSERT INTO {$wpdb->donors} ( verify_key, verify_throttle) VALUES (%s, %s)", $verify_key, $now ) |
||
305 | ); |
||
306 | } |
||
307 | } |
||
308 | |||
309 | /** |
||
310 | * Is this a valid verify key? |
||
311 | * |
||
312 | * @since 1.0 |
||
313 | * @access public |
||
314 | * |
||
315 | * @param $token string The token. |
||
316 | * |
||
317 | * @return bool |
||
318 | */ |
||
319 | public function is_valid_verify_key( $token ) { |
||
320 | /* @var WPDB $wpdb */ |
||
321 | global $wpdb; |
||
322 | |||
323 | // See if the verify_key exists. |
||
324 | $row = $wpdb->get_row( |
||
0 ignored issues
–
show
|
|||
325 | $wpdb->prepare( "SELECT id, email FROM {$wpdb->donors} WHERE verify_key = %s LIMIT 1", $token ) |
||
326 | ); |
||
327 | |||
328 | $now = date( 'Y-m-d H:i:s' ); |
||
329 | |||
330 | // Set token and remove verify key. |
||
331 | if ( ! empty( $row ) ) { |
||
332 | $wpdb->query( |
||
0 ignored issues
–
show
|
|||
333 | $wpdb->prepare( "UPDATE {$wpdb->donors} SET verify_key = '', token = %s, verify_throttle = %s WHERE id = %d LIMIT 1", $token, $now, $row->id ) |
||
334 | ); |
||
335 | |||
336 | $this->token_email = $row->email; |
||
337 | $this->token = $token; |
||
338 | |||
339 | return true; |
||
340 | } |
||
341 | |||
342 | return false; |
||
343 | } |
||
344 | |||
345 | /** |
||
346 | * Users donations args |
||
347 | * |
||
348 | * Force Give to find donations by email, not user ID. |
||
349 | * |
||
350 | * @since 1.0 |
||
351 | * @access public |
||
352 | * |
||
353 | * @param $args array User Donations arguments. |
||
354 | * |
||
355 | * @return mixed |
||
356 | */ |
||
357 | public function users_donations_args( $args ) { |
||
358 | $args['user'] = $this->token_email; |
||
359 | |||
360 | return $args; |
||
361 | } |
||
362 | |||
363 | /** |
||
364 | * Create required columns |
||
365 | * |
||
366 | * Create the necessary columns for email access |
||
367 | * |
||
368 | * @since 1.0 |
||
369 | * @access public |
||
370 | * |
||
371 | * @return void |
||
372 | */ |
||
373 | public function create_columns() { |
||
374 | |||
375 | global $wpdb; |
||
376 | |||
377 | // Create columns in donors table. |
||
378 | $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`" ); |
||
0 ignored issues
–
show
|
|||
379 | } |
||
380 | |||
381 | } |
||
382 |