lastStatusMsg = $custom_msg; //let's 'unset' the cookie setcookie( 'swpm-login-form-custom-msg', '', time() - 3600, COOKIEPATH, COOKIE_DOMAIN ); } $this->isLoggedIn = false; $this->userData = null; $this->protected = SwpmProtection::get_instance(); } private function init() { $valid = $this->validate(); //SwpmLog::log_auth_debug("init:". ($valid? "valid": "invalid"), true); if ( ! $valid ) { $this->authenticate(); } } public static function get_instance() { if ( empty( self::$_this ) ) { self::$_this = new SwpmAuth(); self::$_this->init(); } return self::$_this; } private function authenticate( $user = null, $pass = null ) { global $wpdb; $swpm_password = empty( $pass ) ? filter_input( INPUT_POST, 'swpm_password' ) : $pass; $swpm_user_name = empty( $user ) ? apply_filters( 'swpm_user_name', filter_input( INPUT_POST, 'swpm_user_name' ) ) : $user; if ( ! empty( $swpm_user_name ) && ! empty( $swpm_password ) ) { //SWPM member login request. //Trigger action hook that can be used to check stuff before the login request is processed by the plugin. $args = array( 'username' => $swpm_user_name, 'password' => $swpm_password, ); do_action( 'swpm_before_login_request_is_processed', $args ); //First, lets make sure this user is not already logged into the site as an "Admin" user. We don't want to override that admin login session. if ( current_user_can( 'administrator' ) ) { //This user is logged in as ADMIN then trying to do another login as a member. Stop the login request processing (we don't want to override your admin login session). $wp_profile_page = SIMPLE_WP_MEMBERSHIP_SITE_HOME_URL . '/wp-admin/profile.php'; $error_msg = ''; $error_msg .= '
' . SwpmUtils::_( 'Warning! Simple Membership plugin cannot process this login request to prevent you from getting logged out of WP Admin accidentally.' ) . '
'; $error_msg .= '' . SwpmUtils::_( 'Click here' ) . '' . SwpmUtils::_( ' to see the profile you are currently logged into in this browser.' ) . '
'; $error_msg .= '' . SwpmUtils::_( 'You are logged into the site as an ADMIN user in this browser. First, logout from WP Admin then you will be able to log in as a normal member.' ) . '
'; $error_msg .= '' . SwpmUtils::_( 'Alternatively, you can use a different browser (where you are not logged-in as ADMIN) to test the membership login.' ) . '
'; $error_msg .= '' . SwpmUtils::_( 'Your normal visitors or members will never see this message. This message is ONLY for ADMIN user.' ) . '
'; wp_die( $error_msg ); } //If captcha is present and validation failed, it returns an error string. If validation succeeds, it returns an empty string. $captcha_validation_output = apply_filters( 'swpm_validate_login_form_submission', '' ); if ( ! empty( $captcha_validation_output ) ) { $this->lastStatusMsg = SwpmUtils::_( 'Captcha validation failed on login form.' ); return; } if ( is_email( $swpm_user_name ) ) {//User is trying to log-in using an email address $email = sanitize_email( $swpm_user_name ); $query = $wpdb->prepare( 'SELECT user_name FROM ' . $wpdb->prefix . 'swpm_members_tbl WHERE email = %s', $email ); $username = $wpdb->get_var( $query ); if ( $username ) {//Found a user record $swpm_user_name = $username; //Grab the usrename value so it can be used in the authentication process. SwpmLog::log_auth_debug( 'Authentication request using email address: ' . $email . ', Found a user record with username: ' . $swpm_user_name, true ); } } //Lets process the request. Check username and password $user = sanitize_user( $swpm_user_name ); $pass = trim( $swpm_password ); SwpmLog::log_auth_debug( 'Authentication request - Username: ' . $swpm_user_name, true ); $query = 'SELECT * FROM ' . $wpdb->prefix . 'swpm_members_tbl WHERE user_name = %s'; $userData = $wpdb->get_row( $wpdb->prepare( $query, $user ) ); $this->userData = $userData; if ( ! $userData ) { $this->isLoggedIn = false; $this->userData = null; $this->lastStatusMsg = SwpmUtils::_( 'User Not Found.' ); return false; } $check = $this->check_password( $pass, $userData->password ); if ( ! $check ) { $this->isLoggedIn = false; $this->userData = null; $this->lastStatusMsg = SwpmUtils::_( 'Password Empty or Invalid.' ); return false; } if ( $this->check_constraints() ) { $rememberme = filter_input( INPUT_POST, 'rememberme' ); $remember = empty( $rememberme ) ? false : true; $this->set_cookie( $remember ); $this->isLoggedIn = true; $this->lastStatusMsg = 'Logged In.'; SwpmLog::log_auth_debug( 'Authentication successful for username: ' . $user . '. Executing swpm_login action hook.', true ); do_action( 'swpm_login', $user, $pass, $remember ); return true; } } return false; } private function check_constraints() { if ( empty( $this->userData ) ) { return false; } global $wpdb; $enable_expired_login = SwpmSettings::get_instance()->get_value( 'enable-expired-account-login', '' ); //Update the last accessed date and IP address for this login attempt. $wpdb->update(table, data, where, format, where format) $last_accessed_date = current_time( 'mysql' ); $last_accessed_ip = SwpmUtils::get_user_ip_address(); $wpdb->update( $wpdb->prefix . 'swpm_members_tbl', array( 'last_accessed' => $last_accessed_date, 'last_accessed_from_ip' => $last_accessed_ip, ), array( 'member_id' => $this->userData->member_id ), array( '%s', '%s' ), array( '%d' ) ); //Check the member's account status. $can_login = true; if ( $this->userData->account_state == 'inactive' && empty( $enable_expired_login ) ) { $this->lastStatusMsg = SwpmUtils::_( 'Account is inactive.' ); $can_login = false; } elseif ( ( $this->userData->account_state == 'expired' ) && empty( $enable_expired_login ) ) { $this->lastStatusMsg = SwpmUtils::_( 'Account has expired.' ); $can_login = false; } elseif ( $this->userData->account_state == 'pending' ) { $this->lastStatusMsg = SwpmUtils::_( 'Account is pending.' ); $can_login = false; } elseif ( $this->userData->account_state == 'activation_required' ) { $resend_email_url = add_query_arg( array( 'swpm_resend_activation_email' => '1', 'swpm_member_id' => $this->userData->member_id, ), get_home_url() ); $msg = sprintf( SwpmUtils::_( 'You need to activate your account. If you didn\'t receive an email then %s to resend the activation email.' ), '' . SwpmUtils::_( 'click here' ) . '' ); $this->lastStatusMsg = $msg; $can_login = false; } if ( ! $can_login ) { $this->isLoggedIn = false; $this->userData = null; return false; } if ( SwpmUtils::is_subscription_expired( $this->userData ) ) { if ( $this->userData->account_state == 'active' ) { $wpdb->update( $wpdb->prefix . 'swpm_members_tbl', array( 'account_state' => 'expired' ), array( 'member_id' => $this->userData->member_id ), array( '%s' ), array( '%d' ) ); } if ( empty( $enable_expired_login ) ) { $this->lastStatusMsg = SwpmUtils::_( 'Account has expired.' ); $this->isLoggedIn = false; $this->userData = null; return false; } } $this->permitted = SwpmPermission::get_instance( $this->userData->membership_level ); $this->lastStatusMsg = SwpmUtils::_( 'You are logged in as:' ) . $this->userData->user_name; $this->isLoggedIn = true; return true; } private function check_password( $plain_password, $hashed_pw ) { global $wp_hasher; if ( empty( $plain_password ) ) { return false; } if ( empty( $wp_hasher ) ) { require_once ABSPATH . 'wp-includes/class-phpass.php'; $wp_hasher = new PasswordHash( 8, true ); } return $wp_hasher->CheckPassword( $plain_password, $hashed_pw ); } public function match_password( $password ) { if ( ! $this->is_logged_in() ) { return false; } return $this->check_password( $password, $this->get( 'password' ) ); } public function login_to_swpm_using_wp_user( $user ) { if ( $this->isLoggedIn ) { return false; } $email = $user->user_email; $member = SwpmMemberUtils::get_user_by_email( $email ); if ( empty( $member ) ) { //There is no swpm profile with this email. return false; } $this->userData = $member; $this->isLoggedIn = true; $this->set_cookie(); SwpmLog::log_auth_debug( 'Member has been logged in using WP User object.', true ); $this->check_constraints(); return true; } public function login( $user, $pass, $remember = '', $secure = '' ) { SwpmLog::log_auth_debug( 'SwpmAuth::login()', true ); if ( $this->isLoggedIn ) { return; } if ( $this->authenticate( $user, $pass ) && $this->validate() ) { $this->set_cookie( $remember, $secure ); } else { $this->isLoggedIn = false; $this->userData = null; } return $this->lastStatusMsg; } public function logout() { if ( ! $this->isLoggedIn ) { return; } setcookie( SIMPLE_WP_MEMBERSHIP_AUTH, ' ', time() - YEAR_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN ); setcookie( SIMPLE_WP_MEMBERSHIP_SEC_AUTH, ' ', time() - YEAR_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN ); $this->userData = null; $this->isLoggedIn = false; $this->lastStatusMsg = SwpmUtils::_( 'Logged Out Successfully.' ); do_action( 'swpm_logout' ); } private function set_cookie( $remember = '', $secure = '' ) { if ( $remember ) { $expiration = time() + 1209600; //14 days $expire = $expiration + 43200; //12 hours grace period } else { $expiration = time() + 259200; //3 days. $expire = $expiration; //The minimum cookie expiration should be at least a few days. } $expire = apply_filters( 'swpm_auth_cookie_expiry_value', $expire ); setcookie( 'swpm_in_use', 'swpm_in_use', $expire, COOKIEPATH, COOKIE_DOMAIN ); $expiration_timestamp = SwpmUtils::get_expiration_timestamp( $this->userData ); $enable_expired_login = SwpmSettings::get_instance()->get_value( 'enable-expired-account-login', '' ); // make sure cookie doesn't live beyond account expiration date. // but if expired account login is enabled then ignore if account is expired $expiration = empty( $enable_expired_login ) ? min( $expiration, $expiration_timestamp ) : $expiration; $pass_frag = substr( $this->userData->password, 8, 4 ); $scheme = 'auth'; if ( ! $secure ) { $secure = is_ssl(); } $key = self::b_hash( $this->userData->user_name . $pass_frag . '|' . $expiration, $scheme ); $hash = hash_hmac( 'md5', $this->userData->user_name . '|' . $expiration, $key ); $auth_cookie = $this->userData->user_name . '|' . $expiration . '|' . $hash; $auth_cookie_name = $secure ? SIMPLE_WP_MEMBERSHIP_SEC_AUTH : SIMPLE_WP_MEMBERSHIP_AUTH; setcookie( $auth_cookie_name, $auth_cookie, $expire, COOKIEPATH, COOKIE_DOMAIN, $secure, true ); } private function validate() { $auth_cookie_name = is_ssl() ? SIMPLE_WP_MEMBERSHIP_SEC_AUTH : SIMPLE_WP_MEMBERSHIP_AUTH; if ( ! isset( $_COOKIE[ $auth_cookie_name ] ) || empty( $_COOKIE[ $auth_cookie_name ] ) ) { return false; } $cookie_elements = explode( '|', $_COOKIE[ $auth_cookie_name ] ); if ( count( $cookie_elements ) != 3 ) { return false; } //SwpmLog::log_auth_debug("validate() - " . $_COOKIE[$auth_cookie_name], true); list($username, $expiration, $hmac) = $cookie_elements; $expired = $expiration; // Allow a grace period for POST and AJAX requests if ( defined( 'DOING_AJAX' ) || 'POST' == $_SERVER['REQUEST_METHOD'] ) { $expired += HOUR_IN_SECONDS; } // Quick check to see if an honest cookie has expired if ( $expired < time() ) { $this->lastStatusMsg = SwpmUtils::_( 'Session Expired.' ); //do_action('auth_cookie_expired', $cookie_elements); SwpmLog::log_auth_debug( 'validate() - Session Expired', true ); return false; } global $wpdb; $query = ' SELECT * FROM ' . $wpdb->prefix . 'swpm_members_tbl WHERE user_name = %s'; $user = $wpdb->get_row( $wpdb->prepare( $query, $username ) ); if ( empty( $user ) ) { $this->lastStatusMsg = SwpmUtils::_( 'Invalid Username' ); return false; } $pass_frag = substr( $user->password, 8, 4 ); $key = self::b_hash( $username . $pass_frag . '|' . $expiration ); $hash = hash_hmac( 'md5', $username . '|' . $expiration, $key ); if ( $hmac != $hash ) { $this->lastStatusMsg = SwpmUtils::_( 'Please login again.' ); SwpmLog::log_auth_debug( 'validate() - Bad Hash', true ); do_action('swpm_validate_login_hash_mismatch'); wp_logout(); //Force logout of WP user session to clear the bad hash. return false; } if ( $expiration < time() ) { $GLOBALS['login_grace_period'] = 1; } $this->userData = $user; return $this->check_constraints(); } public static function b_hash( $data, $scheme = 'auth' ) { $salt = wp_salt( $scheme ) . 'j4H!B3TA,J4nIn4.'; return hash_hmac( 'md5', $data, $salt ); } public function is_logged_in() { return $this->isLoggedIn; } public function get( $key, $default = '' ) { if ( isset( $this->userData->$key ) ) { return $this->userData->$key; } if ( isset( $this->permitted->$key ) ) { return $this->permitted->$key; } if ( ! empty( $this->permitted ) ) { return $this->permitted->get( $key, $default ); } return $default; } public function get_message() { return $this->lastStatusMsg; } public function get_expire_date() { if ( $this->isLoggedIn ) { return SwpmUtils::get_formatted_expiry_date( $this->get( 'subscription_starts' ), $this->get( 'subscription_period' ), $this->get( 'subscription_duration_type' ) ); } return ''; } public function delete() { if ( ! $this->is_logged_in() ) { return; } $user_name = $this->get( 'user_name' ); $user_id = $this->get( 'member_id' ); $subscr_id = $this->get( 'subscr_id' ); $email = $this->get( 'email' ); $this->logout(); wp_clear_auth_cookie(); SwpmMembers::delete_swpm_user_by_id( $user_id ); SwpmMembers::delete_wp_user( $user_name ); } public function reload_user_data() { if ( ! $this->is_logged_in() ) { return; } global $wpdb; $query = 'SELECT * FROM ' . $wpdb->prefix . 'swpm_members_tbl WHERE member_id = %d'; $this->userData = $wpdb->get_row( $wpdb->prepare( $query, $this->userData->member_id ) ); } public function is_expired_account() { if ( ! $this->is_logged_in() ) { return null; } $account_status = $this->get( 'account_state' ); if ( $account_status == 'expired' || $account_status == 'inactive' ) { //Expired or Inactive accounts are both considered to be expired. return true; } return false; } }