PluginProbe ʕ •ᴥ•ʔ
GiveWP – Donation Plugin and Fundraising Platform / 3.19.3
GiveWP – Donation Plugin and Fundraising Platform v3.19.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 year ago api 3 years ago database 2 years ago deprecated 3 years ago donors 1 year ago emails 3 years ago forms 1 year ago frontend 6 years ago gateways 1 year ago libraries 2 years ago payments 1 year ago actions.php 5 years ago ajax-functions.php 2 years ago class-give-async-process.php 1 year ago class-give-background-updater.php 2 years ago class-give-cache-setting.php 2 years ago class-give-cache.php 3 years ago class-give-cli-commands.php 3 years ago class-give-comment.php 6 years ago class-give-cron.php 6 years ago class-give-donate-form.php 1 year ago class-give-donor.php 2 years ago class-give-email-access.php 5 years ago class-give-license-handler.php 1 year ago class-give-logging.php 5 years ago class-give-readme-parser.php 4 years ago class-give-roles.php 6 years ago class-give-scripts.php 2 years ago class-give-session.php 5 years 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 2 years ago country-functions.php 1 year ago currencies-list.php 3 years ago currency-functions.php 3 years ago error-tracking.php 6 years ago filters.php 3 years ago formatting.php 1 year ago install.php 2 years ago login-register.php 2 years ago misc-functions.php 1 year ago plugin-compatibility.php 6 years ago post-types.php 1 year ago price-functions.php 6 years ago process-donation.php 1 year ago setting-functions.php 6 years ago shortcodes.php 1 year ago template-functions.php 4 years ago user-functions.php 3 years ago
class-give-session.php
700 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 list( $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 2.2.6
257 * @access private
258 *
259 * @return array|bool|string
260 */
261 private function __handle_ajax_cookie() {
262 $cookie = false;
263
264 // @see https://github.com/impress-org/give/issues/3705
265 if (
266 empty( $cookie )
267 && wp_doing_ajax()
268 && isset( $_GET['action'] )
269 && 'get_receipt' === $_GET['action']
270 ) {
271 $cookie = isset( $_GET[ $this->cookie_name ] ) ? give_clean( $_GET[ $this->cookie_name ] ) : false;
272 }
273
274 return $cookie;
275 }
276
277
278 /**
279 * Check if session exist for specific session id
280 *
281 * @since 2.2.0
282 * @access public
283 *
284 * @return bool
285 */
286 public function has_session() {
287 return $this->has_cookie;
288 }
289
290 /**
291 * Set cookie name
292 *
293 * @since 2.2.0
294 * @access private
295 *
296 * @return void
297 */
298 private function set_cookie_name() {
299 /**
300 * Filter the cookie name
301 *
302 * @since 2.2.0
303 *
304 * @param string $cookie_name Cookie name.
305 * @param string $cookie_type Cookie type session or nonce.
306 */
307 $this->cookie_name = apply_filters(
308 'give_session_cookie',
309 'wp-give_session_' . COOKIEHASH, // Cookie name.
310 'session' // Cookie type.
311 );
312
313 $this->nonce_cookie_name = apply_filters(
314 'give_session_cookie',
315 'wp-give_session_reset_nonce_' . COOKIEHASH, // Cookie name.
316 'nonce' // Cookie type.
317 );
318 }
319
320 /**
321 * Get session donor id
322 *
323 * @since 2.10.0
324 * @access public
325 *
326 * @return int
327 */
328 public function get_donor_id() {
329 return $this->donor_id;
330 }
331
332 /**
333 * Get Session
334 *
335 * Retrieve session variable for a given session key.
336 *
337 * @since 1.0
338 * @access public
339 *
340 * @param string $key Session key.
341 * @param mixed $default default value.
342 *
343 * @return string|array Session variable.
344 */
345 public function get( $key, $default = false ) {
346 $key = sanitize_key( $key );
347
348 return isset( $this->session[ $key ] ) ? maybe_unserialize( $this->session[ $key ] ) : $default;
349 }
350
351 /**
352 * Set Session
353 *
354 * @since 1.0
355 * @access public
356 *
357 * @param string $key Session key.
358 * @param mixed $value Session variable.
359 *
360 * @return string Session variable.
361 */
362 public function set( $key, $value ) {
363 if ( $value !== $this->get( $key ) ) {
364 $this->session[ sanitize_key( $key ) ] = maybe_serialize( $value );
365 $this->session_data_changed = true;
366 }
367
368 return $this->session[ $key ];
369 }
370
371 /**
372 * Set Session Cookies
373 *
374 * Cookies are used to increase the session lifetime using the give setting. This is helpful for when a user closes
375 * their browser after making a donation and comes back to the site.
376 *
377 * @since 1.4
378 * @access public
379 *
380 * @param bool $set Flag to check if set cookie or not.
381 */
382 public function set_session_cookies( $set ) {
383 if ( $set ) {
384 $this->set_expiration_time();
385
386 $to_hash = $this->donor_id . '|' . $this->session_expiration;
387 $cookie_hash = hash_hmac( 'md5', $to_hash, wp_hash( $to_hash ) );
388 $cookie_value = $this->donor_id . '||' . $this->session_expiration . '||' . $this->session_expiring . '||' . $cookie_hash;
389 $this->has_cookie = true;
390
391 give_setcookie( $this->cookie_name, $cookie_value, $this->session_expiration, apply_filters( 'give_session_use_secure_cookie', false ) );
392 give_setcookie( $this->nonce_cookie_name, '1', $this->session_expiration, apply_filters( 'give_session_use_secure_cookie', false ) );
393 }
394 }
395
396 /**
397 * Set Cookie Expiration
398 *
399 * Force the cookie expiration time if set, default to 24 hours.
400 *
401 * @since 1.0
402 * @access public
403 *
404 * @return int
405 */
406 public function set_expiration_time() {
407 $this->session_expiring = time() + intval( apply_filters( 'give_session_expiring', ( $this->exp_option - 3600 ) ) ); // Default 11 Hours.
408 $this->session_expiration = time() + intval( apply_filters( 'give_session_expiration', $this->exp_option ) ); // Default 12 Hours.
409
410 return $this->session_expiration;
411 }
412
413 /**
414 * Get Session Expiration
415 *
416 * Looks at the session cookies and returns the expiration date for this session if applicable
417 *
418 * @since 2.2.0
419 * @access public
420 *
421 * @return string|bool Formatted expiration date string.
422 */
423 public function get_session_expiration() {
424 return $this->has_session() ? $this->session_expiration : false;
425 }
426
427 /**
428 * Maybe Start Session
429 *
430 * Starts a new session if one hasn't started yet.
431 *
432 * @since 2.2.0
433 * @access public
434 *
435 * @return void
436 */
437 public function maybe_start_session() {
438 if (
439 ! headers_sent()
440 && empty( $this->session )
441 && ! $this->has_cookie
442 ) {
443 $this->set_session_cookies( true );
444 }
445 }
446
447 /**
448 * Setup donor session when authorized by WP user credentials
449 *
450 * @since 2.7.0
451 *
452 * @param WP_User $wpUser
453 * @param string $wpUserLogin
454 */
455 public function startSessionWhenLoginAsWPUser( $wpUserLogin, $wpUser ) {
456
457 $donor = Give()->donors->get_donor_by( 'user_id', $wpUser->ID );
458
459 // Setup session only if donor exist for specific WP user.
460 if ( $donor ) {
461 $this->maybe_start_session();
462 $this->set( 'give_email', $donor->email );
463 }
464 }
465
466 /**
467 * Generate a unique donor ID.
468 *
469 * Uses Portable PHP password hashing framework to generate a unique cryptographically strong ID.
470 *
471 * @since 2.2.0
472 * @access public
473 */
474 public function generate_donor_id() {
475 require_once ABSPATH . 'wp-includes/class-phpass.php';
476
477 $hasher = new PasswordHash( 8, false );
478 $this->donor_id = md5( $hasher->get_random_bytes( 32 ) );
479 }
480
481 /**
482 * Save donor session data
483 *
484 * @since 2.2.0
485 * @access public
486 */
487 public function save_data() {
488 // Dirty if something changed - prevents saving nothing new.
489 if ( $this->session_data_changed && $this->has_session() ) {
490 global $wpdb;
491
492 Give()->session_db->__replace(
493 Give()->session_db->table_name,
494 [
495 'session_key' => $this->donor_id,
496 'session_value' => maybe_serialize( $this->session ),
497 'session_expiry' => $this->session_expiration,
498 ],
499 [
500 '%s',
501 '%s',
502 '%d',
503 ]
504 );
505
506 $this->session_data_changed = false;
507 }
508 }
509
510 /**
511 * Destroy all session data.
512 *
513 * @since 2.2.0
514 * @access public
515 */
516 public function destroy_session() {
517
518 give_setcookie( 'give_nl', '', time() - YEAR_IN_SECONDS, apply_filters( 'give_session_use_secure_cookie', false ) );
519 give_setcookie( $this->cookie_name, '', time() - YEAR_IN_SECONDS, apply_filters( 'give_session_use_secure_cookie', false ) );
520 give_setcookie( $this->nonce_cookie_name, '', time() - YEAR_IN_SECONDS, apply_filters( 'give_session_use_secure_cookie', false ) );
521
522 Give()->session_db->delete_session( $this->donor_id );
523
524 $this->session = [];
525 $this->session_data_changed = false;
526
527 $this->generate_donor_id();
528 }
529
530 /**
531 * Delete nonce cookie if generating fresh form html.
532 *
533 * @since 2.2.0
534 * @access public
535 *
536 * @return bool
537 */
538 public function is_delete_nonce_cookie() {
539 $value = false;
540
541 if ( Give()->session->has_session() ) {
542 $value = true;
543 }
544
545 return $value;
546 }
547
548 /**
549 * Get cookie names
550 *
551 * @since 2.2.0
552 * @access public
553 *
554 * @param string $type Nonce type.
555 *
556 * @return string Cookie name
557 */
558 public function get_cookie_name( $type = '' ) {
559 $name = '';
560
561 switch ( $type ) {
562 case 'nonce':
563 $name = $this->nonce_cookie_name;
564 break;
565
566 case 'session':
567 $name = $this->cookie_name;
568 break;
569 }
570
571 return $name;
572 }
573
574 /**
575 * When a user is logged out, ensure they have a unique nonce by using the donor/session ID.
576 * Note: for internal logic only.
577 *
578 * @since 2.2.0
579 * @access public
580 *
581 * @param int $uid User ID.
582 *
583 * @return string
584 */
585 public function __nonce_user_logged_out( $uid ) {
586 return $this->has_session() && $this->donor_id ? $this->donor_id : $uid;
587 }
588
589
590 /**
591 * Cleanup session data from the database and clear caches.
592 * Note: for internal logic only.
593 *
594 * @since 2.2.0
595 * @access public
596 */
597 public function __cleanup_sessions() { // @codingStandardsIgnoreLine
598 Give()->session_db->delete_expired_sessions();
599 }
600
601
602 /**
603 * Get Session ID
604 *
605 * Retrieve session ID.
606 *
607 * @since 1.0
608 * @return string Session ID.
609 * @deprecated 2.2.0
610 * @access public
611 *
612 */
613 public function get_id() {
614 return $this->get_cookie_name( 'session' );
615 }
616
617 /**
618 * Set Cookie Variant Time
619 *
620 * Force the cookie expiration variant time to custom expiration option, less and hour. defaults to 23 hours
621 * (set_expiration_variant_time used in WP_Session).
622 *
623 * @since 1.0
624 * @return int
625 * @deprecated 2.2.0
626 * @access public
627 *
628 */
629 public function set_expiration_variant_time() {
630
631 return ( ! empty( $this->exp_option ) ? ( intval( $this->exp_option ) - 3600 ) : 30 * 60 * 23 );
632 }
633
634 /**
635 * Starts a new session if one has not started yet.
636 *
637 * Checks to see if the server supports PHP sessions or if the GIVE_USE_PHP_SESSIONS constant is defined.
638 *
639 * @since 1.0
640 * @access public
641 * @return bool $ret True if we are using PHP sessions, false otherwise.
642 * @deprecated 2.2.0
643 *
644 */
645 public function use_php_sessions() {
646 $ret = false;
647
648 give_doing_it_wrong( __FUNCTION__, __( 'We are using database session logic instead of PHP session since GiveWP 2.2.0', 'give' ) );
649
650 return (bool) apply_filters( 'give_use_php_sessions', $ret );
651 }
652
653 /**
654 * Should Start Session
655 *
656 * Determines if we should start sessions.
657 *
658 * @since 1.4
659 * @access public
660 * @return bool
661 * @deprecated 2.2.0
662 *
663 */
664 public function should_start_session() {
665
666 $start_session = true;
667
668 give_doing_it_wrong( __FUNCTION__, __( 'We are using database session logic instead of PHP session since GiveWP 2.2.0', 'give' ) );
669
670 if ( ! empty( $_SERVER['REQUEST_URI'] ) ) { // @codingStandardsIgnoreLine
671
672 $blacklist = apply_filters(
673 'give_session_start_uri_blacklist',
674 [
675 'feed',
676 'feed',
677 'feed/rss',
678 'feed/rss2',
679 'feed/rdf',
680 'feed/atom',
681 'comments/feed/',
682 ]
683 );
684 $uri = ltrim( $_SERVER['REQUEST_URI'], '/' ); // // @codingStandardsIgnoreLine
685 $uri = untrailingslashit( $uri );
686 if ( in_array( $uri, $blacklist, true ) ) {
687 $start_session = false;
688 }
689 if ( false !== strpos( $uri, 'feed=' ) ) {
690 $start_session = false;
691 }
692 if ( is_admin() ) {
693 $start_session = false;
694 }
695 }
696
697 return apply_filters( 'give_start_session', $start_session );
698 }
699 }
700