errors = new WP_Error();
register_activation_hook( __FILE__, array( &$this, 'install' ) );
add_action( 'plugins_loaded', array( $this, 'load_plugin_textdomain' ) );
add_filter( 'password_protected_is_active', array( $this, 'allow_ip_addresses' ) );
add_action( 'init', array( $this, 'disable_caching' ), 1 );
add_action( 'init', array( $this, 'maybe_process_logout' ), 1 );
add_action( 'init', array( $this, 'maybe_process_login' ), 1 );
add_action( 'wp', array( $this, 'disable_feeds' ) );
add_action( 'template_redirect', array( $this, 'maybe_show_login' ), -1 );
add_filter( 'pre_option_password_protected_status', array( $this, 'allow_feeds' ) );
add_filter( 'pre_option_password_protected_status', array( $this, 'allow_administrators' ) );
add_filter( 'pre_option_password_protected_status', array( $this, 'allow_users' ) );
add_filter( 'rest_authentication_errors', array( $this, 'only_allow_logged_in_rest_access' ) );
add_action( 'init', array( $this, 'compat' ) );
add_action( 'password_protected_login_messages', array( $this, 'login_messages' ) );
add_action( 'login_enqueue_scripts', array( $this, 'load_theme_stylesheet' ), 5 );
// Available from WordPress 4.3+
if ( function_exists( 'wp_site_icon' ) ) {
add_action( 'password_protected_login_head', 'wp_site_icon' );
}
add_shortcode( 'password_protected_logout_link', array( $this, 'logout_link_shortcode' ) );
include_once( dirname( __FILE__ ) . '/admin/admin-bar.php' );
if ( is_admin() ) {
include_once( dirname( __FILE__ ) . '/admin/admin-caching.php' );
include_once( dirname( __FILE__ ) . '/admin/admin.php' );
$this->admin_caching = new Password_Protected_Admin_Caching( $this );
$this->admin = new Password_Protected_Admin();
}
}
/**
* I18n
*/
public function load_plugin_textdomain() {
load_plugin_textdomain( 'password-protected', false, basename( dirname( __FILE__ ) ) . '/languages' );
}
/**
* Disable Page Caching
*/
public function disable_caching() {
if ( $this->is_active() && ! defined( 'DONOTCACHEPAGE' ) ) {
define( 'DONOTCACHEPAGE', true );
}
}
/**
* Is Active?
*
* @return boolean Is password protection active?
*/
public function is_active() {
global $wp_query;
// Always allow access to robots.txt
if ( isset( $wp_query ) && is_robots() ) {
return false;
}
if ( (bool) get_option( 'password_protected_status' ) ) {
$is_active = true;
} else {
$is_active = false;
}
$is_active = apply_filters( 'password_protected_is_active', $is_active );
if ( isset( $_GET['password-protected'] ) ) {
$is_active = true;
}
return $is_active;
}
/**
* Disable Feeds
*
* @todo An option/filter to prevent disabling of feeds.
*/
public function disable_feeds() {
if ( $this->is_active() ) {
add_action( 'do_feed', array( $this, 'disable_feed' ), 1 );
add_action( 'do_feed_rdf', array( $this, 'disable_feed' ), 1 );
add_action( 'do_feed_rss', array( $this, 'disable_feed' ), 1 );
add_action( 'do_feed_rss2', array( $this, 'disable_feed' ), 1 );
add_action( 'do_feed_atom', array( $this, 'disable_feed' ), 1 );
}
}
/**
* Disable Feed
*
* @todo Make Translatable
*/
public function disable_feed() {
wp_die( sprintf( __( 'Feeds are not available for this site. Please visit the website.', 'password-protected' ), get_bloginfo( 'url' ) ) );
}
/**
* Allow Feeds
*
* @param boolean $bool Allow feeds.
* @return boolean True/false.
*/
public function allow_feeds( $bool ) {
if ( is_feed() && (bool) get_option( 'password_protected_feeds' ) ) {
return 0;
}
return $bool;
}
/**
* Allow Administrators
*
* @param boolean $bool Allow administrators.
* @return boolean True/false.
*/
public function allow_administrators( $bool ) {
if ( ! is_admin() && current_user_can( 'manage_options' ) && (bool) get_option( 'password_protected_administrators' ) ) {
return 0;
}
return $bool;
}
/**
* Allow Users
*
* @param boolean $bool Allow administrators.
* @return boolean True/false.
*/
public function allow_users( $bool ) {
if ( ! is_admin() && is_user_logged_in() && (bool) get_option( 'password_protected_users' ) ) {
return 0;
}
return $bool;
}
/**
* Allow IP Addresses
*
* If user has a valid email address, return false to disable password protection.
*
* @param boolean $bool Allow IP addresses.
* @return boolean True/false.
*/
public function allow_ip_addresses( $bool ) {
$ip_addresses = $this->get_allowed_ip_addresses();
if ( isset( $_SERVER['REMOTE_ADDR'] ) && in_array( $_SERVER['REMOTE_ADDR'], $ip_addresses ) ) {
$bool = false;
}
return $bool;
}
/**
* Get Allowed IP Addresses
*
* @return array IP addresses.
*/
public function get_allowed_ip_addresses() {
return explode( "\n", get_option( 'password_protected_allowed_ip_addresses' ) );
}
/**
* Allow the remember me function
*
* @return. boolean
*/
public function allow_remember_me() {
return (bool) get_option( 'password_protected_remember_me' );
}
/**
* Encrypt Password
*
* @param string $password Password.
* @return string Encrypted password.
*/
public function encrypt_password( $password ) {
return md5( $password );
}
/**
* Maybe Process Logout
*/
public function maybe_process_logout() {
if ( isset( $_REQUEST['password-protected'] ) && $_REQUEST['password-protected'] == 'logout' ) {
$this->logout();
if ( isset( $_REQUEST['redirect_to'] ) ) {
$redirect_to = remove_query_arg( 'password-protected', esc_url_raw( $_REQUEST['redirect_to'], array( 'http', 'https' ) ) );
} else {
$redirect_to = home_url( '/' );
}
$this->safe_redirect( $redirect_to );
exit();
}
}
/**
* Maybe Process Login
*/
public function maybe_process_login() {
if ( $this->is_active() && isset( $_REQUEST['password_protected_pwd'] ) ) {
$password_protected_pwd = $_REQUEST['password_protected_pwd'];
$pwd = get_option( 'password_protected_password' );
// If correct password...
if ( ( hash_equals( $pwd, $this->encrypt_password( $password_protected_pwd ) ) && $pwd != '' ) || apply_filters( 'password_protected_process_login', false, $password_protected_pwd ) ) {
$remember = isset( $_REQUEST['password_protected_rememberme'] ) ? boolval( $_REQUEST['password_protected_rememberme'] ) : false;
if ( ! $this->allow_remember_me() ) {
$remember = false;
}
$this->set_auth_cookie( $remember );
$redirect_to = isset( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : '';
$redirect_to = apply_filters( 'password_protected_login_redirect', $redirect_to );
if ( ! empty( $redirect_to ) ) {
$this->safe_redirect( remove_query_arg( 'password-protected', $redirect_to ) );
exit;
} elseif ( isset( $_GET['password_protected_pwd'] ) ) {
$this->safe_redirect( remove_query_arg( 'password-protected' ) );
exit;
}
} else {
// ... otherwise incorrect password
$this->clear_auth_cookie();
$this->errors->add( 'incorrect_password', __( 'Incorrect Password', 'password-protected' ) );
}
}
}
/**
* Is User Logged In?
*
* @return boolean
*/
public function is_user_logged_in() {
return $this->is_active() && $this->validate_auth_cookie();
}
/**
* Maybe Show Login
*/
public function maybe_show_login() {
// Filter for adding exceptions.
$show_login = apply_filters( 'password_protected_show_login', $this->is_active() );
// Logged in
if ( $this->is_user_logged_in() ) {
$show_login = false;
}
if ( ! $show_login ) {
return;
}
// Show login form
if ( isset( $_REQUEST['password-protected'] ) && 'login' == $_REQUEST['password-protected'] ) {
$default_theme_file = locate_template( array( 'password-protected-login.php' ) );
if ( empty( $default_theme_file ) ) {
$default_theme_file = dirname( __FILE__ ) . '/theme/password-protected-login.php';
}
$theme_file = apply_filters( 'password_protected_theme_file', $default_theme_file );
if ( ! file_exists( $theme_file ) ) {
$theme_file = $default_theme_file;
}
load_template( $theme_file );
exit();
} else {
$redirect_to = add_query_arg( 'password-protected', 'login', home_url() );
// URL to redirect back to after login
$redirect_to_url = apply_filters( 'password_protected_login_redirect_url', ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
if ( ! empty( $redirect_to_url ) ) {
$redirect_to = add_query_arg( 'redirect_to', urlencode( $redirect_to_url ), $redirect_to );
}
nocache_headers();
wp_redirect( $redirect_to );
exit();
}
}
/**
* Get Site ID
*
* @return string Site ID.
*/
public function get_site_id() {
global $blog_id;
return 'bid_' . apply_filters( 'password_protected_blog_id', $blog_id );
}
/**
* Login URL
*
* @return string Login URL.
*/
public function login_url() {
return add_query_arg( 'password-protected', 'login', home_url( '/' ) );
}
/**
* Logout
*/
public function logout() {
$this->clear_auth_cookie();
do_action( 'password_protected_logout' );
}
/**
* Logout URL
*
* @param string $redirect_to Optional. Redirect URL.
* @return string Logout URL.
*/
public function logout_url( $redirect_to = '' ) {
$query = array(
'password-protected' => 'logout',
'redirect_to' => esc_url_raw( $redirect_to )
);
if ( empty( $query['redirect_to'] ) ) {
unset( $query['redirect_to'] );
}
return add_query_arg( $query, home_url() );
}
/**
* Logout Link
*
* @param array $args Link args.
* @return string HTML link tag.
*/
public function logout_link( $args = null ) {
// Only show if user is logged in
if ( ! $this->is_user_logged_in() ) {
return '';
}
$args = wp_parse_args( $args, array(
'redirect_to' => '',
'text' => __( 'Logout', 'password-protected' )
) );
if ( empty( $args['text'] ) ) {
$args['text'] = __( 'Logout', 'password-protected' );
}
return sprintf( '%s', esc_url( $this->logout_url( $args['redirect_to'] ) ), esc_html( $args['text'] ) );
}
/**
* Logout Link Shortcode
*
* @param array $args Link args.
* @return string HTML link tag.
*/
public function logout_link_shortcode( $atts, $content = null ) {
$atts = shortcode_atts( array(
'redirect_to' => '',
'text' => $content
), $atts, 'logout_link_shortcode' );
return $this->logout_link( $atts );
}
/**
* Get Hashed Password
*
* @return string Hashed password.
*/
public function get_hashed_password() {
return md5( get_option( 'password_protected_password' ) . wp_salt() );
}
/**
* Validate Auth Cookie
*
* @param string $cookie Cookie string.
* @param string $scheme Cookie scheme.
* @return boolean Validation successful?
*/
public function validate_auth_cookie( $cookie = '', $scheme = '' ) {
if ( ! $cookie_elements = $this->parse_auth_cookie( $cookie, $scheme ) ) {
do_action( 'password_protected_auth_cookie_malformed', $cookie, $scheme );
return false;
}
extract( $cookie_elements, EXTR_OVERWRITE );
$expired = $expiration;
// Allow a grace period for POST and AJAX requests
if ( defined( 'DOING_AJAX' ) || 'POST' == $_SERVER['REQUEST_METHOD'] ) {
$expired += 3600;
}
// Quick check to see if an honest cookie has expired
if ( $expired < current_time( 'timestamp' ) ) {
do_action('password_protected_auth_cookie_expired', $cookie_elements);
return false;
}
$key = md5( $this->get_site_id() . $this->get_hashed_password() . '|' . $expiration );
$hash = hash_hmac( 'md5', $this->get_site_id() . '|' . $expiration, $key);
if ( $hmac != $hash ) {
do_action( 'password_protected_auth_cookie_bad_hash', $cookie_elements );
return false;
}
if ( $expiration < current_time( 'timestamp' ) ) { // AJAX/POST grace period set above
$GLOBALS['login_grace_period'] = 1;
}
return true;
}
/**
* Generate Auth Cookie
*
* @param int $expiration Expiration time in seconds.
* @param string $scheme Cookie scheme.
* @return string Cookie.
*/
public function generate_auth_cookie( $expiration, $scheme = 'auth' ) {
$key = md5( $this->get_site_id() . $this->get_hashed_password() . '|' . $expiration );
$hash = hash_hmac( 'md5', $this->get_site_id() . '|' . $expiration, $key );
$cookie = $this->get_site_id() . '|' . $expiration . '|' . $hash;
return $cookie;
}
/**
* Parse Auth Cookie
*
* @param string $cookie Cookie string.
* @param string $scheme Cookie scheme.
* @return string Cookie string.
*/
public function parse_auth_cookie( $cookie = '', $scheme = '' ) {
if ( empty( $cookie ) ) {
$cookie_name = $this->cookie_name();
if ( empty( $_COOKIE[ $cookie_name ] ) ) {
return false;
}
$cookie = $_COOKIE[ $cookie_name ];
}
$cookie_elements = explode( '|', $cookie );
if ( count( $cookie_elements ) != 3 ) {
return false;
}
list( $site_id, $expiration, $hmac ) = $cookie_elements;
return compact( 'site_id', 'expiration', 'hmac', 'scheme' );
}
/**
* Set Auth Cookie
*
* @todo
*
* @param boolean $remember Remember logged in.
* @param string $secure Secure cookie.
*/
public function set_auth_cookie( $remember = false, $secure = '') {
if ( $remember ) {
$expiration_time = apply_filters( 'password_protected_auth_cookie_expiration', get_option( 'password_protected_remember_me_lifetime', 14 ) * DAY_IN_SECONDS, $remember );
$expiration = $expire = current_time( 'timestamp' ) + $expiration_time;
} else {
$expiration_time = apply_filters( 'password_protected_auth_cookie_expiration', DAY_IN_SECONDS * 20, $remember );
$expiration = current_time( 'timestamp' ) + $expiration_time;
$expire = 0;
}
if ( '' === $secure ) {
$secure = is_ssl();
}
$secure_password_protected_cookie = apply_filters( 'password_protected_secure_password_protected_cookie', false, $secure );
$password_protected_cookie = $this->generate_auth_cookie( $expiration, 'password_protected' );
setcookie( $this->cookie_name(), $password_protected_cookie, $expire, COOKIEPATH, COOKIE_DOMAIN, $secure_password_protected_cookie, true );
if ( COOKIEPATH != SITECOOKIEPATH ) {
setcookie( $this->cookie_name(), $password_protected_cookie, $expire, SITECOOKIEPATH, COOKIE_DOMAIN, $secure_password_protected_cookie, true );
}
}
/**
* Clear Auth Cookie
*/
public function clear_auth_cookie() {
setcookie( $this->cookie_name(), ' ', current_time( 'timestamp' ) - 31536000, COOKIEPATH, COOKIE_DOMAIN );
setcookie( $this->cookie_name(), ' ', current_time( 'timestamp' ) - 31536000, SITECOOKIEPATH, COOKIE_DOMAIN );
}
/**
* Cookie Name
*
* @return string Cookie name.
*/
public function cookie_name() {
/**
* Filters the cookie name
*/
return apply_filters( 'password_protected_cookie_name', $this->get_site_id() . '_password_protected_auth', $this );
}
/**
* Install
*/
public function install() {
$old_version = get_option( 'password_protected_version' );
// 1.1 - Upgrade to MD5
if ( empty( $old_version ) || version_compare( '1.1', $old_version ) ) {
$pwd = get_option( 'password_protected_password' );
if ( ! empty( $pwd ) ) {
$new_pwd = $this->encrypt_password( $pwd );
update_option( 'password_protected_password', $new_pwd );
}
}
update_option( 'password_protected_version', $this->version );
}
/**
* Compat
*
* Support for 3rd party plugins:
*
* - Login Logo https://wordpress.org/plugins/login-logo/
* - Uber Login Logo https://wordpress.org/plugins/uber-login-logo/
*/
public function compat() {
if ( class_exists( 'CWS_Login_Logo_Plugin' ) ) {
// Add support for Mark Jaquith's Login Logo plugin
add_action( 'password_protected_login_head', array( new CWS_Login_Logo_Plugin, 'login_head' ) );
} elseif ( class_exists( 'UberLoginLogo' ) ) {
// Add support for Uber Login Logo plugin
add_action( 'password_protected_login_head', array( 'UberLoginLogo', 'replaceLoginLogo' ) );
}
}
/**
* Login Messages
* Outputs messages and errors in the login template.
*/
public function login_messages() {
// Add message
$message = apply_filters( 'password_protected_login_message', '' );
if ( ! empty( $message ) ) {
echo $message . "\n";
}
if ( $this->errors->get_error_code() ) {
$errors = '';
$messages = '';
foreach ( $this->errors->get_error_codes() as $code ) {
$severity = $this->errors->get_error_data( $code );
foreach ( $this->errors->get_error_messages( $code ) as $error ) {
if ( 'message' == $severity ) {
$messages .= $error . '
';
} else {
$errors .= $error . '
';
}
}
}
if ( ! empty( $errors ) ) {
echo '