PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 4.16.7.2
GiveWP – Donation Plugin and Fundraising Platform v4.16.7.2
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 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-session.php
give / includes Last commit date
admin 1 week ago api 3 years ago database 6 days ago deprecated 3 months ago donors 6 days ago emails 11 months ago forms 1 week ago frontend 6 years ago gateways 3 weeks ago libraries 11 months ago payments 6 days ago actions.php 3 weeks ago ajax-functions.php 2 months 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 1 week 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 7 months ago class-give-scripts.php 1 month ago class-give-session.php 6 days 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 11 months ago install.php 11 months ago login-register.php 6 days ago misc-functions.php 1 week ago plugin-compatibility.php 6 years ago post-types.php 1 year ago price-functions.php 6 years ago process-donation.php 6 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-session.php
711 lines
1 <?php
2 /**
3 * Session
4 *
5 * @since 1.0
6 * @subpackage Classes/Give_Session
7 * @copyright Copyright (c) 2016, GiveWP
8 * @license https://opensource.org/licenses/gpl-license GNU Public License
9 * @package Give
10 */
11
12 // Exit if accessed directly.
13 if ( ! defined( 'ABSPATH' ) ) {
14 exit;
15 }
16
17 /**
18 * Class Give_Session
19 */
20 class Give_Session {
21 /**
22 * Instance.
23 *
24 * @since 2.2.0
25 * @access private
26 * @var Give_Session
27 */
28 private static $instance;
29
30 /**
31 * Holds our session data
32 *
33 * @since 1.0
34 * @access private
35 *
36 * @var array
37 */
38 private $session = [];
39
40 /**
41 * Holds our session data
42 *
43 * @since 1.0
44 * @access private
45 *
46 * @var string
47 */
48 private $session_data_changed = false;
49
50 /**
51 * Cookie Name
52 *
53 * @since 1.0
54 * @access private
55 *
56 * @var string
57 */
58 private $cookie_name = '';
59
60 /**
61 * Donor Unique ID
62 *
63 * @since 1.0
64 * @access private
65 *
66 * @var string
67 */
68 private $donor_id = '';
69
70 /**
71 * Session expiring time
72 *
73 * @since 2.2.0
74 * @access private
75 *
76 * @var string
77 */
78 private $session_expiring = false;
79
80 /**
81 * Session expiration time
82 *
83 * @since 2.2.0
84 * @access private
85 *
86 * @var string
87 */
88 private $session_expiration = false;
89
90 /**
91 * Flag to check if donor has cookie or not
92 *
93 * @since 2.2.0
94 * @access private
95 *
96 * @var bool
97 */
98 private $has_cookie = false;
99
100 /**
101 * Expiration Time
102 *
103 * @since 1.0
104 * @access private
105 *
106 * @var int
107 */
108 private $exp_option = false;
109
110 /**
111 * Expiration Time
112 *
113 * @since 2.2.0
114 * @access private
115 *
116 * @var string
117 */
118 private $nonce_cookie_name = '';
119
120 /**
121 * Singleton pattern.
122 *
123 * @since 2.2.0
124 * @access private
125 */
126 private function __construct() {
127 }
128
129
130 /**
131 * Get instance.
132 *
133 * @since 2.2.0
134 * @access public
135 * @return Give_Session
136 */
137 public static function get_instance() {
138 if ( null === static::$instance ) {
139 self::$instance = new static();
140 self::$instance->__setup();
141 }
142
143 return self::$instance;
144 }
145
146 /**
147 * Setup
148 *
149 * @since 2.2.0
150 * @access public
151 */
152 private function __setup() { // @codingStandardsIgnoreLine
153 $this->exp_option = give_get_option( 'session_lifetime' );
154 $this->exp_option = ! empty( $this->exp_option )
155 ? $this->exp_option
156 : 30 * 60 * 24; // Default expiration time is 12 hours
157
158 $this->set_cookie_name();
159 $cookie = $this->get_session_cookie();
160
161 if ( ! empty( $cookie ) ) {
162 $this->donor_id = $cookie[0];
163 $this->session_expiration = $cookie[1];
164 $this->session_expiring = $cookie[2];
165 $this->has_cookie = true;
166
167 // Update session if its close to expiring.
168 if ( time() > $this->session_expiring ) {
169 $this->set_expiration_time();
170 Give()->session_db->update_session_timestamp( $this->donor_id, $this->session_expiration );
171 }
172
173 // Load session.
174 $this->session = $this->get_session_data();
175
176 } else {
177 $this->generate_donor_id();
178 }
179
180 add_action( 'give_process_donation_after_validation', [ $this, 'maybe_start_session' ] );
181 add_action( 'wp_login', [ $this, 'startSessionWhenLoginAsWPUser' ], 10, 2 );
182
183 add_action( 'shutdown', [ $this, 'save_data' ], 20 );
184 add_action( 'wp_logout', [ $this, 'destroy_session' ] );
185
186 if ( ! is_user_logged_in() ) {
187 add_filter( 'nonce_user_logged_out', [$this, 'nonce_user_logged_out'] );
188 }
189
190 // Remove old sessions.
191 Give_Cron::add_daily_event( [$this, 'cleanup_sessions'] );
192 }
193
194 /**
195 * Get session data
196 *
197 * @since 2.2.0
198 * @access public
199 *
200 * @return array
201 */
202 public function get_session_data() {
203 return $this->has_session() ? (array) Give()->session_db->get_session( $this->donor_id, [] ) : [];
204 }
205
206
207 /**
208 * Get session by session id
209 *
210 * @since 2.2.0
211 * @access public
212 *
213 * @return array
214 */
215 public function get_session_cookie() {
216 $session = [];
217 $cookie_value = isset( $_COOKIE[ $this->cookie_name ] ) ? give_clean( $_COOKIE[ $this->cookie_name ] ) : $this->handle_ajax_cookie(); // @codingStandardsIgnoreLine.
218
219 if ( empty( $cookie_value ) || ! is_string( $cookie_value ) ) {
220 return $session;
221 }
222
223 [ $donor_id, $session_expiration, $session_expiring, $cookie_hash ] = explode( '||', $cookie_value );
224
225 if ( empty( $donor_id ) ) {
226 return $session;
227 }
228
229 require_once ABSPATH . WPINC . '/pluggable.php';
230
231 // Validate hash.
232 $to_hash = $donor_id . '|' . $session_expiration;
233 $hash = hash_hmac( 'md5', $to_hash, wp_hash( $to_hash ) );
234
235 if ( empty( $cookie_hash ) || ! hash_equals( $hash, $cookie_hash ) ) {
236 return $session;
237 }
238
239 /**
240 * Filter the session cookie data
241 *
242 * @since 2.2.6
243 */
244 $cookie_data = apply_filters(
245 'give_get_session_cookie',
246 [ $donor_id, $session_expiration, $session_expiring, $cookie_hash ]
247 );
248
249 return $cookie_data;
250 }
251
252
253 /**
254 * Load session cookie by ajax
255 *
256 * @since 4.9.0 rename function - PHP 8 compatibility
257 * @since 2.2.6
258 * @access private
259 *
260 * @return array|bool|string
261 */
262 private function handle_ajax_cookie()
263 {
264 $cookie = false;
265
266 // @see https://github.com/impress-org/give/issues/3705
267 if (
268 empty( $cookie )
269 && wp_doing_ajax()
270 && isset( $_GET['action'] )
271 && 'get_receipt' === $_GET['action']
272 ) {
273 $cookie = isset( $_GET[ $this->cookie_name ] ) ? give_clean( $_GET[ $this->cookie_name ] ) : false;
274 }
275
276 return $cookie;
277 }
278
279
280 /**
281 * Check if session exist for specific session id
282 *
283 * @since 2.2.0
284 * @access public
285 *
286 * @return bool
287 */
288 public function has_session() {
289 return $this->has_cookie;
290 }
291
292 /**
293 * Set cookie name
294 *
295 * @since 2.2.0
296 * @access private
297 *
298 * @return void
299 */
300 private function set_cookie_name() {
301 /**
302 * Filter the cookie name
303 *
304 * @since 2.2.0
305 *
306 * @param string $cookie_name Cookie name.
307 * @param string $cookie_type Cookie type session or nonce.
308 */
309 $this->cookie_name = apply_filters(
310 'give_session_cookie',
311 'wp-give_session_' . COOKIEHASH, // Cookie name.
312 'session' // Cookie type.
313 );
314
315 $this->nonce_cookie_name = apply_filters(
316 'give_session_cookie',
317 'wp-give_session_reset_nonce_' . COOKIEHASH, // Cookie name.
318 'nonce' // Cookie type.
319 );
320 }
321
322 /**
323 * Get session donor id
324 *
325 * @since 2.10.0
326 * @access public
327 *
328 * @return int
329 */
330 public function get_donor_id() {
331 return $this->donor_id;
332 }
333
334 /**
335 * Get Session
336 *
337 * Retrieve session variable for a given session key.
338 *
339 * @since 4.16.7.2 Restrict unserialize to prevent object instantiation.
340 * @since 1.0
341 * @access public
342 *
343 * @param string $key Session key.
344 * @param mixed $default default value.
345 *
346 * @return string|array Session variable.
347 */
348 public function get( $key, $default = false ) {
349 $key = sanitize_key( $key );
350
351 if ( ! isset( $this->session[ $key ] ) ) {
352 return $default;
353 }
354
355 $value = $this->session[ $key ];
356
357 return is_serialized( $value ) ? unserialize( $value, [ 'allowed_classes' => false ] ) : $value;
358 }
359
360 /**
361 * Set Session
362 *
363 * @since 1.0
364 * @access public
365 *
366 * @param string $key Session key.
367 * @param mixed $value Session variable.
368 *
369 * @return string Session variable.
370 */
371 public function set( $key, $value ) {
372 if ( $value !== $this->get( $key ) ) {
373 $this->session[ sanitize_key( $key ) ] = maybe_serialize( $value );
374 $this->session_data_changed = true;
375 }
376
377 return $this->session[ $key ];
378 }
379
380 /**
381 * Set Session Cookies
382 *
383 * Cookies are used to increase the session lifetime using the give setting. This is helpful for when a user closes
384 * their browser after making a donation and comes back to the site.
385 *
386 * @since 1.4
387 * @access public
388 *
389 * @param bool $set Flag to check if set cookie or not.
390 */
391 public function set_session_cookies( $set ) {
392 if ( $set ) {
393 $this->set_expiration_time();
394
395 $to_hash = $this->donor_id . '|' . $this->session_expiration;
396 $cookie_hash = hash_hmac( 'md5', $to_hash, wp_hash( $to_hash ) );
397 $cookie_value = $this->donor_id . '||' . $this->session_expiration . '||' . $this->session_expiring . '||' . $cookie_hash;
398 $this->has_cookie = true;
399
400 give_setcookie( $this->cookie_name, $cookie_value, $this->session_expiration, apply_filters( 'give_session_use_secure_cookie', false ) );
401 give_setcookie( $this->nonce_cookie_name, '1', $this->session_expiration, apply_filters( 'give_session_use_secure_cookie', false ) );
402 }
403 }
404
405 /**
406 * Set Cookie Expiration
407 *
408 * Force the cookie expiration time if set, default to 24 hours.
409 *
410 * @since 1.0
411 * @access public
412 *
413 * @return int
414 */
415 public function set_expiration_time() {
416 $this->session_expiring = time() + intval( apply_filters( 'give_session_expiring', ( $this->exp_option - 3600 ) ) ); // Default 11 Hours.
417 $this->session_expiration = time() + intval( apply_filters( 'give_session_expiration', $this->exp_option ) ); // Default 12 Hours.
418
419 return $this->session_expiration;
420 }
421
422 /**
423 * Get Session Expiration
424 *
425 * Looks at the session cookies and returns the expiration date for this session if applicable
426 *
427 * @since 2.2.0
428 * @access public
429 *
430 * @return string|bool Formatted expiration date string.
431 */
432 public function get_session_expiration() {
433 return $this->has_session() ? $this->session_expiration : false;
434 }
435
436 /**
437 * Maybe Start Session
438 *
439 * Starts a new session if one hasn't started yet.
440 *
441 * @since 2.2.0
442 * @access public
443 *
444 * @return void
445 */
446 public function maybe_start_session() {
447 if (
448 ! headers_sent()
449 && empty( $this->session )
450 && ! $this->has_cookie
451 ) {
452 $this->set_session_cookies( true );
453 }
454 }
455
456 /**
457 * Setup donor session when authorized by WP user credentials
458 *
459 * @since 2.7.0
460 *
461 * @param WP_User $wpUser
462 * @param string $wpUserLogin
463 */
464 public function startSessionWhenLoginAsWPUser( $wpUserLogin, $wpUser ) {
465
466 $donor = Give()->donors->get_donor_by( 'user_id', $wpUser->ID );
467
468 // Setup session only if donor exist for specific WP user.
469 if ( $donor ) {
470 $this->maybe_start_session();
471 $this->set( 'give_email', $donor->email );
472 }
473 }
474
475 /**
476 * Generate a unique donor ID.
477 *
478 * Uses Portable PHP password hashing framework to generate a unique cryptographically strong ID.
479 *
480 * @since 2.2.0
481 * @access public
482 */
483 public function generate_donor_id() {
484 require_once ABSPATH . 'wp-includes/class-phpass.php';
485
486 $hasher = new PasswordHash( 8, false );
487 $this->donor_id = md5( $hasher->get_random_bytes( 32 ) );
488 }
489
490 /**
491 * Save donor session data
492 *
493 * @since 2.2.0
494 * @access public
495 */
496 public function save_data() {
497 // Dirty if something changed - prevents saving nothing new.
498 if ( $this->session_data_changed && $this->has_session() ) {
499 global $wpdb;
500
501 Give()->session_db->replace(
502 Give()->session_db->table_name,
503 [
504 'session_key' => $this->donor_id,
505 'session_value' => maybe_serialize( $this->session ),
506 'session_expiry' => $this->session_expiration,
507 ],
508 [
509 '%s',
510 '%s',
511 '%d',
512 ]
513 );
514
515 $this->session_data_changed = false;
516 }
517 }
518
519 /**
520 * Destroy all session data.
521 *
522 * @since 2.2.0
523 * @access public
524 */
525 public function destroy_session() {
526
527 give_setcookie( 'give_nl', '', time() - YEAR_IN_SECONDS, apply_filters( 'give_session_use_secure_cookie', false ) );
528 give_setcookie( $this->cookie_name, '', time() - YEAR_IN_SECONDS, apply_filters( 'give_session_use_secure_cookie', false ) );
529 give_setcookie( $this->nonce_cookie_name, '', time() - YEAR_IN_SECONDS, apply_filters( 'give_session_use_secure_cookie', false ) );
530
531 Give()->session_db->delete_session( $this->donor_id );
532
533 $this->session = [];
534 $this->session_data_changed = false;
535
536 $this->generate_donor_id();
537 }
538
539 /**
540 * Delete nonce cookie if generating fresh form html.
541 *
542 * @since 2.2.0
543 * @access public
544 *
545 * @return bool
546 */
547 public function is_delete_nonce_cookie() {
548 $value = false;
549
550 if ( Give()->session->has_session() ) {
551 $value = true;
552 }
553
554 return $value;
555 }
556
557 /**
558 * Get cookie names
559 *
560 * @since 2.2.0
561 * @access public
562 *
563 * @param string $type Nonce type.
564 *
565 * @return string Cookie name
566 */
567 public function get_cookie_name( $type = '' ) {
568 $name = '';
569
570 switch ( $type ) {
571 case 'nonce':
572 $name = $this->nonce_cookie_name;
573 break;
574
575 case 'session':
576 $name = $this->cookie_name;
577 break;
578 }
579
580 return $name;
581 }
582
583 /**
584 * When a user is logged out, ensure they have a unique nonce by using the donor/session ID.
585 * Note: for internal logic only.
586 *
587 * @since 4.9.0 rename function - PHP 8 compatibility
588 * @since 2.2.0
589 * @access public
590 *
591 * @param int $uid User ID.
592 *
593 * @return string
594 */
595 public function nonce_user_logged_out( $uid ) {
596 return $this->has_session() && $this->donor_id ? $this->donor_id : $uid;
597 }
598
599
600 /**
601 * Cleanup session data from the database and clear caches.
602 * Note: for internal logic only.
603 *
604 * @since 4.9.0 rename function - PHP 8 compatibility
605 * @since 2.2.0
606 * @access public
607 */
608 public function cleanup_sessions() { // @codingStandardsIgnoreLine
609 Give()->session_db->delete_expired_sessions();
610 }
611
612
613 /**
614 * Get Session ID
615 *
616 * Retrieve session ID.
617 *
618 * @since 1.0
619 * @return string Session ID.
620 * @deprecated 2.2.0
621 * @access public
622 *
623 */
624 public function get_id() {
625 return $this->get_cookie_name( 'session' );
626 }
627
628 /**
629 * Set Cookie Variant Time
630 *
631 * Force the cookie expiration variant time to custom expiration option, less and hour. defaults to 23 hours
632 * (set_expiration_variant_time used in WP_Session).
633 *
634 * @since 1.0
635 * @return int
636 * @deprecated 2.2.0
637 * @access public
638 *
639 */
640 public function set_expiration_variant_time() {
641
642 return ( ! empty( $this->exp_option ) ? ( intval( $this->exp_option ) - 3600 ) : 30 * 60 * 23 );
643 }
644
645 /**
646 * Starts a new session if one has not started yet.
647 *
648 * Checks to see if the server supports PHP sessions or if the GIVE_USE_PHP_SESSIONS constant is defined.
649 *
650 * @since 1.0
651 * @access public
652 * @return bool $ret True if we are using PHP sessions, false otherwise.
653 * @deprecated 2.2.0
654 *
655 */
656 public function use_php_sessions() {
657 $ret = false;
658
659 give_doing_it_wrong( __FUNCTION__, __( 'We are using database session logic instead of PHP session since GiveWP 2.2.0', 'give' ) );
660
661 return (bool) apply_filters( 'give_use_php_sessions', $ret );
662 }
663
664 /**
665 * Should Start Session
666 *
667 * Determines if we should start sessions.
668 *
669 * @since 1.4
670 * @access public
671 * @return bool
672 * @deprecated 2.2.0
673 *
674 */
675 public function should_start_session() {
676
677 $start_session = true;
678
679 give_doing_it_wrong( __FUNCTION__, __( 'We are using database session logic instead of PHP session since GiveWP 2.2.0', 'give' ) );
680
681 if ( ! empty( $_SERVER['REQUEST_URI'] ) ) { // @codingStandardsIgnoreLine
682
683 $blacklist = apply_filters(
684 'give_session_start_uri_blacklist',
685 [
686 'feed',
687 'feed',
688 'feed/rss',
689 'feed/rss2',
690 'feed/rdf',
691 'feed/atom',
692 'comments/feed/',
693 ]
694 );
695 $uri = ltrim( $_SERVER['REQUEST_URI'], '/' ); // // @codingStandardsIgnoreLine
696 $uri = untrailingslashit( $uri );
697 if ( in_array( $uri, $blacklist, true ) ) {
698 $start_session = false;
699 }
700 if ( false !== strpos( $uri, 'feed=' ) ) {
701 $start_session = false;
702 }
703 if ( is_admin() ) {
704 $start_session = false;
705 }
706 }
707
708 return apply_filters( 'give_start_session', $start_session );
709 }
710 }
711