| @@ -1,13 +1,13 @@ | ||
| 1 | 1 | <?php |
| 2 | 2 | /** |
| 3 | 3 | * Session |
| 4 | 4 | * |
| 5 | - * @package Give | |
| 5 | + * @since 1.0 | |
| 6 | 6 | * @subpackage Classes/Give_Session |
| 7 | 7 | * @copyright Copyright (c) 2016, GiveWP |
| 8 | 8 | * @license https://opensource.org/licenses/gpl-license GNU Public License |
| 9 | - * @since 1.0 | |
| 9 | + * @package Give | |
| 10 | 10 | */ |
| 11 | 11 | |
| 12 | 12 | // Exit if accessed directly. |
| 13 | 13 | if ( ! defined( 'ABSPATH' ) ) { |
| @@ -24,9 +24,9 @@ | ||
| 24 | 24 | * @since 2.2.0 |
| 25 | 25 | * @access private |
| 26 | 26 | * @var Give_Session |
| 27 | 27 | */ |
| 28 | - static private $instance; | |
| 28 | + private static $instance; | |
| 29 | 29 | |
| 30 | 30 | /** |
| 31 | 31 | * Holds our session data |
| 32 | 32 | * |
| @@ -34,9 +34,9 @@ | ||
| 34 | 34 | * @access private |
| 35 | 35 | * |
| 36 | 36 | * @var array |
| 37 | 37 | */ |
| 38 | - private $session = array(); | |
| 38 | + private $session = []; | |
| 39 | 39 | |
| 40 | 40 | /** |
| 41 | 41 | * Holds our session data |
| 42 | 42 | * |
| @@ -176,19 +176,20 @@ | ||
| 176 | 176 | } else { |
| 177 | 177 | $this->generate_donor_id(); |
| 178 | 178 | } |
| 179 | 179 | |
| 180 | - add_action( 'give_process_donation_after_validation', array( $this, 'maybe_start_session' ) ); | |
| 180 | + add_action( 'give_process_donation_after_validation', [ $this, 'maybe_start_session' ] ); | |
| 181 | + add_action( 'wp_login', [ $this, 'startSessionWhenLoginAsWPUser' ], 10, 2 ); | |
| 181 | 182 | |
| 182 | - add_action( 'shutdown', array( $this, 'save_data' ), 20 ); | |
| 183 | - add_action( 'wp_logout', array( $this, 'destroy_session' ) ); | |
| 183 | + add_action( 'shutdown', [ $this, 'save_data' ], 20 ); | |
| 184 | + add_action( 'wp_logout', [ $this, 'destroy_session' ] ); | |
| 184 | 185 | |
| 185 | 186 | if ( ! is_user_logged_in() ) { |
| 186 | - add_filter( 'nonce_user_logged_out', array( $this, '__nonce_user_logged_out' ) ); | |
| 187 | + add_filter( 'nonce_user_logged_out', [$this, 'nonce_user_logged_out'] ); | |
| 187 | 188 | } |
| 188 | 189 | |
| 189 | 190 | // Remove old sessions. |
| 190 | - Give_Cron::add_daily_event( array( $this, '__cleanup_sessions' ) ); | |
| 191 | + Give_Cron::add_daily_event( [$this, 'cleanup_sessions'] ); | |
| 191 | 192 | } |
| 192 | 193 | |
| 193 | 194 | /** |
| 194 | 195 | * Get session data |
| @@ -198,9 +199,9 @@ | ||
| 198 | 199 | * |
| 199 | 200 | * @return array |
| 200 | 201 | */ |
| 201 | 202 | public function get_session_data() { |
| 202 | - return $this->has_session() ? (array) Give()->session_db->get_session( $this->donor_id, array() ) : array(); | |
| 203 | + return $this->has_session() ? (array) Give()->session_db->get_session( $this->donor_id, [] ) : []; | |
| 203 | 204 | } |
| 204 | 205 | |
| 205 | 206 | |
| 206 | 207 | /** |
| @@ -211,21 +212,23 @@ | ||
| 211 | 212 | * |
| 212 | 213 | * @return array |
| 213 | 214 | */ |
| 214 | 215 | public function get_session_cookie() { |
| 215 | - $session = array(); | |
| 216 | - $cookie_value = isset( $_COOKIE[ $this->cookie_name ] ) ? give_clean( $_COOKIE[ $this->cookie_name ] ) : $this->__handle_ajax_cookie(); // @codingStandardsIgnoreLine. | |
| 216 | + $session = []; | |
| 217 | + $cookie_value = isset( $_COOKIE[ $this->cookie_name ] ) ? give_clean( $_COOKIE[ $this->cookie_name ] ) : $this->handle_ajax_cookie(); // @codingStandardsIgnoreLine. | |
| 217 | 218 | |
| 218 | 219 | if ( empty( $cookie_value ) || ! is_string( $cookie_value ) ) { |
| 219 | 220 | return $session; |
| 220 | 221 | } |
| 221 | 222 | |
| 222 | - list( $donor_id, $session_expiration, $session_expiring, $cookie_hash ) = explode( '||', $cookie_value ); | |
| 223 | + [ $donor_id, $session_expiration, $session_expiring, $cookie_hash ] = explode( '||', $cookie_value ); | |
| 223 | 224 | |
| 224 | 225 | if ( empty( $donor_id ) ) { |
| 225 | 226 | return $session; |
| 226 | 227 | } |
| 227 | 228 | |
| 229 | + require_once ABSPATH . WPINC . '/pluggable.php'; | |
| 230 | + | |
| 228 | 231 | // Validate hash. |
| 229 | 232 | $to_hash = $donor_id . '|' . $session_expiration; |
| 230 | 233 | $hash = hash_hmac( 'md5', $to_hash, wp_hash( $to_hash ) ); |
| 231 | 234 | |
| @@ -239,9 +242,9 @@ | ||
| 239 | 242 | * @since 2.2.6 |
| 240 | 243 | */ |
| 241 | 244 | $cookie_data = apply_filters( |
| 242 | 245 | 'give_get_session_cookie', |
| 243 | - array( $donor_id, $session_expiration, $session_expiring, $cookie_hash ) | |
| 246 | + [ $donor_id, $session_expiration, $session_expiring, $cookie_hash ] | |
| 244 | 247 | ); |
| 245 | 248 | |
| 246 | 249 | return $cookie_data; |
| 247 | 250 | } |
| @@ -249,24 +252,26 @@ | ||
| 249 | 252 | |
| 250 | 253 | /** |
| 251 | 254 | * Load session cookie by ajax |
| 252 | 255 | * |
| 256 | + * @since 4.9.0 rename function - PHP 8 compatibility | |
| 253 | 257 | * @since 2.2.6 |
| 254 | 258 | * @access private |
| 255 | 259 | * |
| 256 | 260 | * @return array|bool|string |
| 257 | 261 | */ |
| 258 | - private function __handle_ajax_cookie(){ | |
| 262 | + private function handle_ajax_cookie() | |
| 263 | + { | |
| 259 | 264 | $cookie = false; |
| 260 | 265 | |
| 261 | 266 | // @see https://github.com/impress-org/give/issues/3705 |
| 262 | 267 | if ( |
| 263 | - empty( $cookie_value ) | |
| 268 | + empty( $cookie ) | |
| 264 | 269 | && wp_doing_ajax() |
| 265 | 270 | && isset( $_GET['action'] ) |
| 266 | 271 | && 'get_receipt' === $_GET['action'] |
| 267 | 272 | ) { |
| 268 | - $cookie = isset( $_GET[$this->cookie_name] ) ? give_clean( $_GET[$this->cookie_name] ) : false; | |
| 273 | + $cookie = isset( $_GET[ $this->cookie_name ] ) ? give_clean( $_GET[ $this->cookie_name ] ) : false; | |
| 269 | 274 | } |
| 270 | 275 | |
| 271 | 276 | return $cookie; |
| 272 | 277 | } |
| @@ -300,9 +305,9 @@ | ||
| 300 | 305 | * |
| 301 | 306 | * @param string $cookie_name Cookie name. |
| 302 | 307 | * @param string $cookie_type Cookie type session or nonce. |
| 303 | 308 | */ |
| 304 | - $this->cookie_name = apply_filters( | |
| 309 | + $this->cookie_name = apply_filters( | |
| 305 | 310 | 'give_session_cookie', |
| 306 | 311 | 'wp-give_session_' . COOKIEHASH, // Cookie name. |
| 307 | 312 | 'session' // Cookie type. |
| 308 | 313 | ); |
| @@ -314,16 +319,29 @@ | ||
| 314 | 319 | ); |
| 315 | 320 | } |
| 316 | 321 | |
| 317 | 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 | + /** | |
| 318 | 335 | * Get Session |
| 319 | 336 | * |
| 320 | 337 | * Retrieve session variable for a given session key. |
| 321 | 338 | * |
| 339 | + * @since 4.16.7.2 Restrict unserialize to prevent object instantiation. | |
| 322 | 340 | * @since 1.0 |
| 323 | 341 | * @access public |
| 324 | 342 | * |
| 325 | - * @param string $key Session key. | |
| 343 | + * @param string $key Session key. | |
| 326 | 344 | * @param mixed $default default value. |
| 327 | 345 | * |
| 328 | 346 | * @return string|array Session variable. |
| 329 | 347 | */ |
| @@ -329,9 +347,15 @@ | ||
| 329 | 347 | */ |
| 330 | 348 | public function get( $key, $default = false ) { |
| 331 | 349 | $key = sanitize_key( $key ); |
| 332 | 350 | |
| 333 | - return isset( $this->session[ $key ] ) ? maybe_unserialize( $this->session[ $key ] ) : $default; | |
| 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; | |
| 334 | 358 | } |
| 335 | 359 | |
| 336 | 360 | /** |
| 337 | 361 | * Set Session |
| @@ -338,10 +362,10 @@ | ||
| 338 | 362 | * |
| 339 | 363 | * @since 1.0 |
| 340 | 364 | * @access public |
| 341 | 365 | * |
| 342 | - * @param string $key Session key. | |
| 343 | - * @param mixed $value Session variable. | |
| 366 | + * @param string $key Session key. | |
| 367 | + * @param mixed $value Session variable. | |
| 344 | 368 | * |
| 345 | 369 | * @return string Session variable. |
| 346 | 370 | */ |
| 347 | 371 | public function set( $key, $value ) { |
| @@ -405,9 +429,9 @@ | ||
| 405 | 429 | * |
| 406 | 430 | * @return string|bool Formatted expiration date string. |
| 407 | 431 | */ |
| 408 | 432 | public function get_session_expiration() { |
| 409 | - return $this->has_session() ? $this->session_expiration :false; | |
| 433 | + return $this->has_session() ? $this->session_expiration : false; | |
| 410 | 434 | } |
| 411 | 435 | |
| 412 | 436 | /** |
| 413 | 437 | * Maybe Start Session |
| @@ -429,8 +453,27 @@ | ||
| 429 | 453 | } |
| 430 | 454 | } |
| 431 | 455 | |
| 432 | 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 | + /** | |
| 433 | 476 | * Generate a unique donor ID. |
| 434 | 477 | * |
| 435 | 478 | * Uses Portable PHP password hashing framework to generate a unique cryptographically strong ID. |
| 436 | 479 | * |
| @@ -454,20 +497,20 @@ | ||
| 454 | 497 | // Dirty if something changed - prevents saving nothing new. |
| 455 | 498 | if ( $this->session_data_changed && $this->has_session() ) { |
| 456 | 499 | global $wpdb; |
| 457 | 500 | |
| 458 | - Give()->session_db->__replace( | |
| 501 | + Give()->session_db->replace( | |
| 459 | 502 | Give()->session_db->table_name, |
| 460 | - array( | |
| 503 | + [ | |
| 461 | 504 | 'session_key' => $this->donor_id, |
| 462 | 505 | 'session_value' => maybe_serialize( $this->session ), |
| 463 | 506 | 'session_expiry' => $this->session_expiration, |
| 464 | - ), | |
| 465 | - array( | |
| 507 | + ], | |
| 508 | + [ | |
| 466 | 509 | '%s', |
| 467 | 510 | '%s', |
| 468 | 511 | '%d', |
| 469 | - ) | |
| 512 | + ] | |
| 470 | 513 | ); |
| 471 | 514 | |
| 472 | 515 | $this->session_data_changed = false; |
| 473 | 516 | } |
| @@ -479,14 +522,16 @@ | ||
| 479 | 522 | * @since 2.2.0 |
| 480 | 523 | * @access public |
| 481 | 524 | */ |
| 482 | 525 | public function destroy_session() { |
| 526 | + | |
| 527 | + give_setcookie( 'give_nl', '', time() - YEAR_IN_SECONDS, apply_filters( 'give_session_use_secure_cookie', false ) ); | |
| 483 | 528 | give_setcookie( $this->cookie_name, '', time() - YEAR_IN_SECONDS, apply_filters( 'give_session_use_secure_cookie', false ) ); |
| 484 | 529 | give_setcookie( $this->nonce_cookie_name, '', time() - YEAR_IN_SECONDS, apply_filters( 'give_session_use_secure_cookie', false ) ); |
| 485 | 530 | |
| 486 | 531 | Give()->session_db->delete_session( $this->donor_id ); |
| 487 | 532 | |
| 488 | - $this->session = array(); | |
| 533 | + $this->session = []; | |
| 489 | 534 | $this->session_data_changed = false; |
| 490 | 535 | |
| 491 | 536 | $this->generate_donor_id(); |
| 492 | 537 | } |
| @@ -498,9 +543,9 @@ | ||
| 498 | 543 | * @access public |
| 499 | 544 | * |
| 500 | 545 | * @return bool |
| 501 | 546 | */ |
| 502 | - public function is_delete_nonce_cookie(){ | |
| 547 | + public function is_delete_nonce_cookie() { | |
| 503 | 548 | $value = false; |
| 504 | 549 | |
| 505 | 550 | if ( Give()->session->has_session() ) { |
| 506 | 551 | $value = true; |
| @@ -538,8 +583,9 @@ | ||
| 538 | 583 | /** |
| 539 | 584 | * When a user is logged out, ensure they have a unique nonce by using the donor/session ID. |
| 540 | 585 | * Note: for internal logic only. |
| 541 | 586 | * |
| 587 | + * @since 4.9.0 rename function - PHP 8 compatibility | |
| 542 | 588 | * @since 2.2.0 |
| 543 | 589 | * @access public |
| 544 | 590 | * |
| 545 | 591 | * @param int $uid User ID. |
| @@ -545,9 +591,9 @@ | ||
| 545 | 591 | * @param int $uid User ID. |
| 546 | 592 | * |
| 547 | 593 | * @return string |
| 548 | 594 | */ |
| 549 | - public function __nonce_user_logged_out( $uid ) { | |
| 595 | + public function nonce_user_logged_out( $uid ) { | |
| 550 | 596 | return $this->has_session() && $this->donor_id ? $this->donor_id : $uid; |
| 551 | 597 | } |
| 552 | 598 | |
| 553 | 599 | |
| @@ -554,12 +600,13 @@ | ||
| 554 | 600 | /** |
| 555 | 601 | * Cleanup session data from the database and clear caches. |
| 556 | 602 | * Note: for internal logic only. |
| 557 | 603 | * |
| 604 | + * @since 4.9.0 rename function - PHP 8 compatibility | |
| 558 | 605 | * @since 2.2.0 |
| 559 | 606 | * @access public |
| 560 | 607 | */ |
| 561 | - public function __cleanup_sessions() { // @codingStandardsIgnoreLine | |
| 608 | + public function cleanup_sessions() { // @codingStandardsIgnoreLine | |
| 562 | 609 | Give()->session_db->delete_expired_sessions(); |
| 563 | 610 | } |
| 564 | 611 | |
| 565 | 612 | |
| @@ -568,12 +615,12 @@ | ||
| 568 | 615 | * |
| 569 | 616 | * Retrieve session ID. |
| 570 | 617 | * |
| 571 | 618 | * @since 1.0 |
| 619 | + * @return string Session ID. | |
| 572 | 620 | * @deprecated 2.2.0 |
| 573 | 621 | * @access public |
| 574 | 622 | * |
| 575 | - * @return string Session ID. | |
| 576 | 623 | */ |
| 577 | 624 | public function get_id() { |
| 578 | 625 | return $this->get_cookie_name( 'session' ); |
| 579 | 626 | } |
| @@ -584,12 +631,12 @@ | ||
| 584 | 631 | * Force the cookie expiration variant time to custom expiration option, less and hour. defaults to 23 hours |
| 585 | 632 | * (set_expiration_variant_time used in WP_Session). |
| 586 | 633 | * |
| 587 | 634 | * @since 1.0 |
| 635 | + * @return int | |
| 588 | 636 | * @deprecated 2.2.0 |
| 589 | 637 | * @access public |
| 590 | 638 | * |
| 591 | - * @return int | |
| 592 | 639 | */ |
| 593 | 640 | public function set_expiration_variant_time() { |
| 594 | 641 | |
| 595 | 642 | return ( ! empty( $this->exp_option ) ? ( intval( $this->exp_option ) - 3600 ) : 30 * 60 * 23 ); |
| @@ -601,16 +648,16 @@ | ||
| 601 | 648 | * Checks to see if the server supports PHP sessions or if the GIVE_USE_PHP_SESSIONS constant is defined. |
| 602 | 649 | * |
| 603 | 650 | * @since 1.0 |
| 604 | 651 | * @access public |
| 652 | + * @return bool $ret True if we are using PHP sessions, false otherwise. | |
| 605 | 653 | * @deprecated 2.2.0 |
| 606 | 654 | * |
| 607 | - * @return bool $ret True if we are using PHP sessions, false otherwise. | |
| 608 | 655 | */ |
| 609 | 656 | public function use_php_sessions() { |
| 610 | 657 | $ret = false; |
| 611 | 658 | |
| 612 | - give_doing_it_wrong( __FUNCTION__, __( 'We are using database session logic instead of PHP session', 'give' ), '2.2.0' ); | |
| 659 | + give_doing_it_wrong( __FUNCTION__, __( 'We are using database session logic instead of PHP session since GiveWP 2.2.0', 'give' ) ); | |
| 613 | 660 | |
| 614 | 661 | return (bool) apply_filters( 'give_use_php_sessions', $ret ); |
| 615 | 662 | } |
| 616 | 663 | |
| @@ -620,23 +667,23 @@ | ||
| 620 | 667 | * Determines if we should start sessions. |
| 621 | 668 | * |
| 622 | 669 | * @since 1.4 |
| 623 | 670 | * @access public |
| 671 | + * @return bool | |
| 624 | 672 | * @deprecated 2.2.0 |
| 625 | 673 | * |
| 626 | - * @return bool | |
| 627 | 674 | */ |
| 628 | 675 | public function should_start_session() { |
| 629 | 676 | |
| 630 | 677 | $start_session = true; |
| 631 | 678 | |
| 632 | - give_doing_it_wrong( __FUNCTION__, __( 'We are using database session logic instead of PHP session', 'give' ), '2.2.0' ); | |
| 679 | + give_doing_it_wrong( __FUNCTION__, __( 'We are using database session logic instead of PHP session since GiveWP 2.2.0', 'give' ) ); | |
| 633 | 680 | |
| 634 | - | |
| 635 | 681 | if ( ! empty( $_SERVER['REQUEST_URI'] ) ) { // @codingStandardsIgnoreLine |
| 636 | 682 | |
| 637 | 683 | $blacklist = apply_filters( |
| 638 | - 'give_session_start_uri_blacklist', array( | |
| 684 | + 'give_session_start_uri_blacklist', | |
| 685 | + [ | |
| 639 | 686 | 'feed', |
| 640 | 687 | 'feed', |
| 641 | 688 | 'feed/rss', |
| 642 | 689 | 'feed/rss2', |
| @@ -642,9 +689,9 @@ | ||
| 642 | 689 | 'feed/rss2', |
| 643 | 690 | 'feed/rdf', |
| 644 | 691 | 'feed/atom', |
| 645 | 692 | 'comments/feed/', |
| 646 | - ) | |
| 693 | + ] | |
| 647 | 694 | ); |
| 648 | 695 | $uri = ltrim( $_SERVER['REQUEST_URI'], '/' ); // // @codingStandardsIgnoreLine |
| 649 | 696 | $uri = untrailingslashit( $uri ); |
| 650 | 697 | if ( in_array( $uri, $blacklist, true ) ) { |