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