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