diff --git a/CHANGELOG.md b/CHANGELOG.md index ba5552f..d3f952b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## 2.5.3 - 2022-06-17 +- Improved Settings HTML structure +- Added Note regarding compatibility with login designer within dashboard + +## 2.5.2 - 2022-05-26 +Made compatibility with [login designer](https://wp.org/plugins/login-designer); Now you can customize the password-protected screen with the customizer using login designer plugin. + ## [2.5] - 2021-09-01 ### Fixed diff --git a/README.md b/README.md index 2316c60..c76c031 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,7 @@ Features include: - Password protect your WordPress site with a single password. - Option to allow access to feeds. - Option to allow administrators access without entering password. -- Works with Mark Jaquith's [Login Logo](https://wordpress.org/plugins/login-logo/) plugin. -- Works with the [Uber Login Logo](https://wordpress.org/plugins/uber-login-logo/) plugin. +- *New* 👉 Now you can customize the whole password protected screen including the background, font, logo, color e.t.c. > Please note, this plugin works by setting a cookie to allow access to the site. If you are using a caching plugin or web hosting such as WP Engine that has in-built caching, you will need to configure the caching service to be disabled if the Password Protected cookie is set. @@ -73,6 +72,12 @@ If you would like to translate this plugin you can easily contribute at the [Tra Upgrade Notice -------------- +### 2.5.3 +- Improved Settings HTML structure +- Added Note regarding compatibility with login designer within dashboard + +### 2.5.2 +Made compatibility with [login designer](https://wp.org/plugins/login-designer); Now you can customize the password-protected screen with the customizer using login designer plugin. ### 2.5 Fixes robots tag for WordPress 5.7+ diff --git a/admin/admin-bar.php b/admin/admin-bar.php index 0375bc1..163d40d 100644 --- a/admin/admin-bar.php +++ b/admin/admin-bar.php @@ -36,7 +36,7 @@ public static function load() { public static function toolbar_item() { global $wp_admin_bar; - + if ( self::allow_current_user() ) { $wp_admin_bar->add_menu( array( diff --git a/admin/admin-caching.php b/admin/admin-caching.php index 0be3ac9..f230480 100644 --- a/admin/admin-caching.php +++ b/admin/admin-caching.php @@ -46,7 +46,7 @@ public function cache_settings_info() { // Caching Section add_settings_section( 'password_protected_compat_caching', - __( 'Caching', 'password-protected' ), + __( 'Having issue with Caching?', 'password-protected' ), array( $this, 'section_caching' ), 'password-protected-compat' ); diff --git a/admin/admin.php b/admin/admin.php index cbb971a..2e075a8 100644 --- a/admin/admin.php +++ b/admin/admin.php @@ -4,14 +4,14 @@ class Password_Protected_Admin { var $settings_page_id; var $options_group = 'password-protected'; + var $setting_tabs = array(); /** * Constructor */ public function __construct() { - global $wp_version; - + add_action( 'admin_init', array( $this, 'password_protected_register_setting_tabs' ) ); add_action( 'admin_init', array( $this, 'password_protected_settings' ), 5 ); add_action( 'admin_init', array( $this, 'add_privacy_policy' ) ); add_action( 'admin_menu', array( $this, 'admin_menu' ) ); @@ -20,16 +20,46 @@ public function __construct() { add_filter( 'plugin_row_meta', array( $this, 'plugin_row_meta' ), 10, 4 ); add_filter( 'plugin_action_links_password-protected/password-protected.php', array( $this, 'plugin_action_links' ) ); add_filter( 'pre_update_option_password_protected_password', array( $this, 'pre_update_option_password_protected_password' ), 10, 2 ); + add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) ); + } + + /** + * Password protected setting tabs + * customizable using filter hook + */ + public function password_protected_register_setting_tabs() { + $this->setting_tabs = array( + 'general' => 'General', + 'advanced' => 'Advanced', + 'help' => 'Help', + 'getpro' => 'Get Pro' + ); + if( $this->password_protected_pro_is_installed_and_activated() ) + unset( $this->setting_tabs['getpro'] ); + $this->setting_tabs = apply_filters( 'password_protected_setting_tabs', $this->setting_tabs ); } + /** + * Admin enqueue scripts. + * + * @param string $hooks Page Hook. + */ + public function admin_enqueue_scripts( $hooks ) { + + if ( 'settings_page_password-protected' === $hooks || 'toplevel_page_password-protected' === $hooks ) { + wp_enqueue_style( 'password-protected-page-script', PASSWORD_PROTECTED_URL . 'assets/css/admin.css', array(), '2.6.0' ); + wp_enqueue_script( 'password-protected-admin-script', PASSWORD_PROTECTED_URL . 'assets/js/admin.js', array('jquery'), '2.6.0' ); + } + } + /** * Add Privacy Policy */ public function add_privacy_policy() { if ( ! function_exists( 'wp_add_privacy_policy_content' ) ) { - return; + return 1; } $content = _x( 'The Password Protected plugin stores a cookie on successful password login containing a hashed version of the entered password. It does not store any information about the user. The cookie stored is named bid_n_password_protected_auth where n is the blog ID in a multisite network', 'privacy policy content', 'password-protected' ); @@ -42,9 +72,18 @@ public function add_privacy_policy() { * Admin Menu */ public function admin_menu() { - + $capability = apply_filters( 'password_protected_options_page_capability', 'manage_options' ); $this->settings_page_id = add_options_page( __( 'Password Protected', 'password-protected' ), __( 'Password Protected', 'password-protected' ), $capability, 'password-protected', array( $this, 'settings_page' ) ); + add_menu_page( + 'Password Protected', + 'Password Protected', + 'manage_options', + 'password-protected', + array( $this, 'pp_admin_menu_page_callback' ), + 'dashicons-lock', + 99 + ); add_action( 'load-' . $this->settings_page_id, array( $this, 'add_help_tabs' ), 20 ); } @@ -65,12 +104,96 @@ public function settings_page() { ?>

- + + +
+ +
+
+
+
+ + + + password_protected_render_tab_content( $tab ); ?> +
+
+ +
+
+
+ '; + settings_fields( 'password-protected' ); + do_settings_sections( 'password-protected' ); + submit_button(); + echo ''; + break; + + case 'advanced': + echo '
'; + settings_fields( 'password-protected-advanced' ); + do_action( 'password_protected_advanced_tab_content' ); + do_settings_fields( 'password-protected&tab=advanced', 'password-protected-advanced' ); + do_settings_sections( 'password-protected-advanced-tab' ); + Password_Protected_reCAPTCHA::recpatcha_screen(); + echo '
'; + break; + + case 'help': + ?> +
+ +
+ password_protected_get_pro_features(); + break; + + case $tab; + do_action( 'password_protected_tab_'.$tab.'_content' ); + break; + + default: + echo "Something went wrong! Please contact support."; + break; + } + } + /** * Add Help Tabs */ @@ -79,7 +202,7 @@ public function add_help_tabs() { global $wp_version; if ( version_compare( $wp_version, '3.3', '<' ) ) { - return; + return 1; } do_action( 'password_protected_help_tabs', get_current_screen() ); @@ -107,7 +230,7 @@ public function help_tabs( $current_screen ) { * Settings API */ public function password_protected_settings() { - + // general tab add_settings_section( 'password_protected', '', @@ -163,6 +286,58 @@ public function password_protected_settings() { 'password_protected' ); + // password protected advanced tab + add_settings_section( + 'password-protected-advanced-tab', + 'Password Protected Page description', + array( $this, 'password_protected_page_description' ), + 'password-protected&tab=advanced' + ); + + add_settings_field( + 'text-above-password', + __( 'Text Above Password Field', 'password-protected' ), + array( $this, 'password_protected_text_above_password' ), + 'password-protected&tab=advanced', + 'password-protected-advanced-tab' + ); + + add_settings_field( + 'text-below-password', + __( 'Text Below Password Field ', 'password-protected' ), + array( $this, 'password_protected_text_below_password' ), + 'password-protected&tab=advanced', + 'password-protected-advanced-tab' + ); + + // password protected help tab + add_settings_section( + 'password-protected-help', + '', + array( $this, 'password_protected_help_tab' ), + 'password-protected-help' + ); + + // sidebar login designer compatibity + if( !$this->login_designer_is_installed_and_activated() ) { + add_settings_section( + 'password-protected-login-designer', + '', + array( $this, 'login_designer_message' ), + 'password-protected-login-designer' + ); + } + + if( !$this->password_protected_pro_is_installed_and_activated() ) { + add_settings_section( + 'password-protected-try-pro', + '', + array( $this, 'password_protected_try_pro' ), + 'password-protected-try-pro' + ); + } + + // registering settings register_setting( $this->options_group, 'password_protected_status', 'intval' ); register_setting( $this->options_group, 'password_protected_feeds', 'intval' ); register_setting( $this->options_group, 'password_protected_rest', 'intval' ); @@ -172,7 +347,24 @@ public function password_protected_settings() { register_setting( $this->options_group, 'password_protected_allowed_ip_addresses', array( $this, 'sanitize_ip_addresses' ) ); register_setting( $this->options_group, 'password_protected_remember_me', 'boolval' ); register_setting( $this->options_group, 'password_protected_remember_me_lifetime', 'intval' ); + register_setting( $this->options_group.'-advanced', 'password_protected_text_above_password', array( 'type' => 'string' ) ); + register_setting( $this->options_group.'-advanced', 'password_protected_text_below_password', array( 'type' => 'string' ) ); + + } + /** + * Login Designer Message + */ + public function login_designer_message(){ + $image = plugin_dir_url( __DIR__ ) . "assets/images/login-designer-demo.gif"; + echo '
+

+ 🎨' . esc_attr__( 'Now you can customize your Password Protected screen with the', 'password-protected' ) . ' Login Designer plugin🌈 +

+ +

' . esc_attr__( '👉 Try it now! It\'s Free.', 'password-protected' ) . '

+ +
'; } /** @@ -182,7 +374,7 @@ public function password_protected_settings() { * @return string Sanitized password. */ public function sanitize_password_protected_password( $val ) { - + $old_val = get_option( 'password_protected_password' ); if ( is_array( $val ) ) { @@ -200,7 +392,8 @@ public function sanitize_password_protected_password( $val ) { } return get_option( 'password_protected_password' ); } - + + return $val; } @@ -242,8 +435,7 @@ private function validate_ip_address( $ip_address ) { */ public function password_protected_settings_section() { - echo '

' . __( 'Password protect your web site. Users will be asked to enter a password to view the site.', 'password-protected' ) . '
- ' . __( 'For more information about Password Protected settings, view the "Help" tab at the top of this page.', 'password-protected' ) . '

'; + return 1; } @@ -261,10 +453,10 @@ public function password_protected_status_field() { */ public function password_protected_permissions_field() { - echo ''; - echo ''; - echo ''; - echo ''; + echo '

'; + echo '

'; + echo '

'; + echo '

'; } @@ -273,8 +465,8 @@ public function password_protected_permissions_field() { */ public function password_protected_password_field() { - echo ' ' . __( 'If you would like to change the password type a new one. Otherwise leave this blank.', 'password-protected' ) . '
- ' . __( 'Type your new password again.', 'password-protected' ) . ''; + echo '

' . __( 'If you would like to change the password, type a new one. Otherwise, leave this blank.', 'password-protected' ) . '


+

' . __( 'Type your new password again.', 'password-protected' ) . '

'; } @@ -283,11 +475,11 @@ public function password_protected_password_field() { */ public function password_protected_allowed_ip_addresses_field() { - echo ''; + echo ''; echo '

' . esc_html__( 'Enter one IP address per line.', 'password-protected' ); if ( isset( $_SERVER['REMOTE_ADDR'] ) ) { - echo ' ' . esc_html( sprintf( __( 'Your IP is address %s.', 'password-protected' ), $_SERVER['REMOTE_ADDR'] ) ); + echo ' ' . esc_html( sprintf( __( 'Your IP address is %s.', 'password-protected' ), $_SERVER['REMOTE_ADDR'] ) ); } echo '

'; @@ -307,10 +499,54 @@ public function password_protected_remember_me_field() { */ public function password_protected_remember_me_lifetime_field() { - echo ''; + echo ''; } + /** + * Password Protected Page description + */ + public function password_protected_page_description() { + return 1; + } + + /** + * Password Protected text above passsword + */ + public function password_protected_text_above_password() { + echo ''; + } + + /** + * Password Protected below above passsword + */ + public function password_protected_text_below_password() { + echo ''; + } + + /** + * Help Tab text field + */ + public function password_protected_help_tab() { + echo '

' . __( 'Password protect your web site. Users will be asked to enter a password to view the site.', 'password-protected' ) . '
+ ' . __( 'For more information about Password Protected settings, view the "Help" tab at the top of this page.', 'password-protected' ) . '

'; + } + + /** + * Try pro sideabr + */ + public function password_protected_try_pro(){ + $image = plugin_dir_url( __DIR__ ) . "assets/images/login-designer-demo.gif"; + echo ' +
+

+ ' . esc_attr__( 'Looking for more options?', 'password-protected' ) . ' +

+

Click here to learn more about pro features

+

' . esc_attr__( '👉 Try Pro', 'password-protected' ) . '

+ +
'; + } /** * Pre-update 'password_protected_password' Option * @@ -366,7 +602,7 @@ public function plugin_row_meta( $plugin_meta, $plugin_file, $plugin_data, $stat */ public function plugin_action_links( $actions ) { - $actions[] = sprintf( '%s', admin_url( 'options-general.php?page=password-protected' ), __( 'Settings', 'password-protected' ) ); + $actions[] = sprintf( '%s', admin_url( 'admin.php?page=password-protected' ), __( 'Settings', 'password-protected' ) ); return $actions; } @@ -376,13 +612,13 @@ public function plugin_action_links( $actions ) { * Warns the user if they have enabled password protection but not entered a password */ public function password_protected_admin_notices() { - global $Password_Protected; // Check Support $screens = $this->plugin_screen_ids( array( 'dashboard', 'plugins' ) ); if ( $this->is_current_screen( $screens ) ) { $supported = $Password_Protected->is_plugin_supported(); + if ( is_wp_error( $supported ) ) { echo $this->admin_error_display( $supported->get_error_message( $supported->get_error_code() ) ); } @@ -392,9 +628,13 @@ public function password_protected_admin_notices() { if ( $this->is_current_screen( $this->plugin_screen_ids() ) ) { $status = get_option( 'password_protected_status' ); $pwd = get_option( 'password_protected_password' ); - + if ( (bool) $status && empty( $pwd ) ) { - echo $this->admin_error_display( __( 'You have enabled password protection but not yet set a password. Please set one below.', 'password-protected' ) ); + $error_message = __( 'You have enabled password protection but not yet set a password. Please set one below.', 'password-protected' ); + $error = apply_filters( 'password_protected_password_status_activation', $error_message ); + if( !empty( $error ) ) { + echo $this->admin_error_display( $error ); + } } if ( current_user_can( 'manage_options' ) && ( (bool) get_option( 'password_protected_administrators' ) || (bool) get_option( 'password_protected_users' ) ) ) { @@ -458,7 +698,7 @@ public function is_current_screen( $screen_id ) { public function plugin_screen_ids( $screen_id = '' ) { $screen_ids = array( 'options-' . $this->options_group, 'settings_page_' . $this->options_group ); - + array_push( $screen_ids, 'toplevel_page_'.$this->options_group ); if ( ! empty( $screen_id ) ) { if ( is_array( $screen_id ) ) { $screen_ids = array_merge( $screen_ids, $screen_id ); @@ -466,9 +706,58 @@ public function plugin_screen_ids( $screen_id = '' ) { $screen_ids[] = $screen_id; } } - + // toplevel_page_password-protected return $screen_ids; } + /** + * @return bool + * true if login designer is installed and activated otherwise false + */ + public function login_designer_is_installed_and_activated(): bool { + return class_exists( 'Login_Designer' ); + } + + /** + * @return bool + * true if password protected pro is installed and activated otherwise false + */ + public function password_protected_pro_is_installed_and_activated(): bool { + return class_exists( 'Password_Protected_Pro' ); + } + + /** + * @return void + * Display Pro Features + */ + public function password_protected_get_pro_features() { + ?> +
+
+
+
+

Pro Features

+
    +
  1. Option to exclude individual pages and posts.

  2. +
  3. Exclude specific post types.

  4. +
  5. Feature to limit password attempts for certain interval.

  6. +
  7. Ability to manage multiple passwords with the following options:

    +
      +
    1. Option to activate and deactivate manually.
    2. +
    3. Set the expiry date for each password.
    4. +
    5. Set the usage limit for each password.
    6. +
    +
  8. +
  9. Display activity log for each password attempt.

  10. +
+ + " class="get_pro_btn">Get Pro Now +
+
+
+
+ options_name ); + + if( empty($options) || !$options ) + $this->settings = $this->get_default_reCAPTCHA_settings(); + else + $this->settings = get_option( $this->options_name ); + + add_action( 'admin_init', array( $this, 'register_reCAPTCHA_settings' ), 6 ); + + add_action( 'password_protected_after_password_field', array( $this, 'add_recaptcha' ) ); + + add_filter( 'password_protected_verify_recaptcha', array( $this, 'verify_recaptcha' ) ); + } + + /** + * reCAPTCHA Default Settings + * + * @return array + * @since 2.6 + */ + private function get_default_reCAPTCHA_settings(): array { + return array( + 'enable' => 0, + 'version' => 'google_recaptcha_v2', + 'v2_site_key' => null, + 'v3_site_key' => null, + 'v2_secret_key' => null, + 'v3_secret_key' => null, + 'v3_score' => 0.3, + 'v3_badge' => 'bottomright', + 'v2_theme' => 'light' + ); + } + + /** + * reCAPTCHA Settings Info + * + * Displays information on the settings page for helping + * to configure Password Protected to work with Google reCAPTCHA v2 and v3. + * + * @since 2.6 + */ + + public function register_reCAPTCHA_settings() { + // reCAPTCHA Section + add_settings_section( + $this->options_group, + __( 'Google reCAPTCHA', 'password-protected' ), + array( $this, 'reCAPTCHA_section' ), + $this->tab + ); + + // Enable reCAPTCHA + add_settings_field( + 'password_protected_enable_recaptcha', + __( 'Enable reCAPTCHA ', 'password-protected' ), + array( $this, 'reCAPTCHA_enable' ), + $this->tab, + $this->options_group + ); + + // reCAPTCHA version v2/v3 + add_settings_field( + 'password_protected_recaptcha_settings', + __( 'Captcha Settings', 'password-protected' ), + array( $this, 'reCAPTCHA_setting' ), + $this->tab, + $this->options_group + ); + + // reCAPTCHA v2/v3 sitekey + add_settings_field( + 'password_protected_recaptcha_v2_site_key', + __( 'Site Key', 'password-protected' ), + array( $this, 'reCAPTCHA_site_key' ), + $this->tab, + $this->options_group + ); + + // reCAPTCHA v2/v3 secretkey + add_settings_field( + 'password_protected_recaptcha_v2_secret_key', + __( 'Secret Key', 'password-protected' ), + array( $this, 'reCAPTCHA_secret_key' ), + $this->tab, + $this->options_group + ); + + // reCAPTCHA v3 score + add_settings_field( + 'password_protected_recaptcha_score', + __( 'Score', 'password-protected' ), + array( $this, 'reCAPTCHA_score' ), + $this->tab, + $this->options_group + ); + + // reCAPTCHA v3 badgeposition + add_settings_field( + 'password_protected_recaptcha_badge_position', + __( 'Badge Position', 'password-protected' ), + array( $this, 'reCAPTCHA_badge_position' ), + $this->tab, + $this->options_group + ); + + // reCAPTCHA v2 theme + add_settings_field( + 'password_protected_recaptcha_theme', + __( 'Theme', 'password-protected' ), + array( $this, 'reCAPTCHA_theme' ), + $this->tab, + $this->options_group + ); + + // register settings in an array group. + register_setting( 'password-protected-advanced', $this->options_name, array( 'type' => 'array') ); + } + + /** + * reCAPTCHA Screen + * + *@since 2.6 + * + * @return void password protected reCAPTCHA settings + */ + public static function recpatcha_screen() { + do_settings_sections( 'password-protected&tab=advanced' ); + submit_button(); + } + + /** + * reCAPTCHA Section + * + * @return void password protected reCAPTCHA section + */ + public function reCAPTCHA_section() { + return 1; + } + + /** + * ENable reCAPTCHA + * + * @since 2.6 + * + * @return void password protected reCAPTCHA status field + */ + public function reCAPTCHA_enable() { + echo ''; + } + + /** + * reCAPTCHA Version + * + * @since 2.6 + * + * @return void password protected reCAPTCHA version field + */ + public function reCAPTCHA_setting() { + echo ' +
+ '; + } + + /** + * reCAPTCHA Site Key + * + * @since 2.6 + * + * @return void password protected v2/v3 sitekey field + */ + public function reCAPTCHA_site_key() { + + echo '
+ +

+ Enter Google reCAPTCHA v2 Site Key.  + + Click Here + +

+
'; + + echo '
+ +

+ Enter Google reCAPTCHA v3 Site Key.  + + Click Here + +

+
'; + } + + /** + * reCAPTCHA Secret Key + * + * @since 2.6 + * + * @return void password protected v2/v3 secretkey field + */ + public function reCAPTCHA_secret_key() { + + echo '
+ +

+ Enter Google reCAPTCHA v2 Secret Key.  + + Click Here + +

+
'; + echo '
+ +

+ Enter Google reCAPTCHA v3 Secret Key.  + + Click Here + +

+
'; + } + + /** + * reCAPTCHA V3 Score + * + * @since 2.6 + * + * @return void password protected v3 score field + */ + public function reCAPTCHA_score() { + echo '
+ +   + +   + +   + +   + +   +

Select Google Version 3 Score.

+
'; + } + + /** + * reCAPTCHA V3 Badge Position + * + * @since 2.6 + * + * @return void password protected v3 badgeposition field + */ + public function reCAPTCHA_badge_position() { + echo '
+ +    + +    + +
'; + } + + /** + * reCAPTCHA V2 Theme + * + * @since 2.6 + * + * @return void password protected v2 theme field + */ + public function reCAPTCHA_theme() { + echo ' +
+ +

Select Google reCAPTCHA Version 2 Theme.

'; + } + + /** + * Add reCAPTCHA on Password Protected Form + * + * @since 2.6 + * + * @return void password protected reCAPTCHA v2 OR v3 + */ + public function add_recaptcha() { + if( ! @$this->settings['enable'] ) + return; //recpatcha is disabled + + if( $this->settings['version'] === 'google_recaptcha_v2' ) + $this->display_recaptcha_v2(); + + if( $this->settings['version'] === 'google_recaptcha_v3' ) + $this->display_recaptcha_v3(); + } + + /** + * Diaplay reCAPTCHA V2 + * + * @since 2.6 + * + * @return void password protected reCAPTCHA v2 field + */ + public function display_recaptcha_v2() { + wp_enqueue_style( 'pp-recaptcha-style', plugin_dir_url( __DIR__ ) . "assets/css/recaptcha.css", array(), '2.6.0' ); + wp_enqueue_script( 'pp-recaptcha-api-v2', esc_url( 'https://www.google.com/recaptcha/api.js' ), array(), null ); + echo '
+
'; + } + + /** + * Diaplay reCAPTCHA V3 + * + * @since 2.6 + * + * @return void password protected reCAPTCHA v3 field + */ + public function display_recaptcha_v3() { + $grecaptcha_v3_site_key = isset( $this->settings['v3_site_key'] ) ? esc_attr( $this->settings['v3_site_key'] ) : ''; + $grecaptcha_v3_badge = isset( $this->settings['v3_badge'] ) ? esc_attr( $this->settings['v3_badge'] ) : 'bottomright'; + + $script = << + + settings['enable'] ) { + return $errors; // return errors + } + + if( $this->settings['version'] === 'google_recaptcha_v2' ) { + + $grecaptcha_v2_site_key = isset( $this->settings['v2_site_key'] ) ? esc_attr( $this->settings['v2_site_key'] ) : ''; + $grecaptcha_v2_secret_key = isset( $this->settings['v2_secret_key'] ) ? esc_attr( $this->settings['v2_secret_key'] ) : ''; + + if ( empty( $grecaptcha_v2_site_key ) || empty( $grecaptcha_v2_secret_key ) ) { + $errors->add( 001, 'Google reCaptcha keys not found.' ); + } + + if ( isset( $_POST['g-recaptcha-response'] ) && ! empty( $_POST['g-recaptcha-response'] ) ) { + $response = wp_remote_post( + 'https://www.google.com/recaptcha/api/siteverify', + array( + 'body' => array( + 'secret' => $grecaptcha_v2_secret_key, + 'response' => sanitize_text_field($_POST['g-recaptcha-response'] ), + ) + ) + ); + + $data = wp_remote_retrieve_body( $response ); + $data = json_decode( $data ); + + if ( isset( $data->{'error-codes'} ) && is_array( $data->{'error-codes'} ) && count( $data->{'error-codes'} ) ) { + foreach ( $data->{'error-codes'} as $index => $error_code ) { + $errors->add( $index, $error_code ); + } + } + + if ( isset( $data->success ) && true === $data->success ) { + return $errors; + } + } + $error_message = wp_kses( __( 'ERROR: Please confirm you are not a robot.', 'password-protected' ), array( 'strong' => array() ) ); + $errors->add( 'captcha_invalid', $error_message ); + + return $errors; + + } else if( $this->settings['version'] === 'google_recaptcha_v3' ) { + + $grecaptcha_v3_site_key = isset( $this->settings['v3_site_key'] ) ? esc_attr( $this->settings['v3_site_key'] ) : ''; + $grecaptcha_v3_secret_key = isset( $this->settings['v3_secret_key'] ) ? esc_attr( $this->settings['v3_secret_key'] ) : ''; + $grecaptcha_v3_score = isset( $this->settings['v3_score'] ) ? esc_attr( $this->settings['v3_score'] ) : '0.3'; + + if ( empty( $grecaptcha_v3_site_key ) || empty( $grecaptcha_v3_secret_key ) ) { + $errors->add( 001, 'Google reCaptcha keys not found.' ); + } + + if ( isset( $_POST['g-recaptcha-response'] ) && ! empty( $_POST['g-recaptcha-response'] ) ) { + $response = wp_remote_post( + 'https://www.google.com/recaptcha/api/siteverify', + array( + 'body' => array( + 'secret' => $grecaptcha_v3_secret_key, + 'response' => sanitize_text_field( $_POST['g-recaptcha-response'] ), + 'remoteip' => self::get_ip_address(), + ) + ) + ); + + $data = wp_remote_retrieve_body( $response ); + $data = json_decode( $data ); + + if ( isset( $data->{'error-codes'} ) && is_array( $data->{'error-codes'} ) && count( $data->{'error-codes'} ) ) { + foreach ( $data->{'error-codes'} as $index => $error_code ) { + $errors->add( $index, $error_code ); + } + } + + if ( isset( $data->success ) && true === $data->success ) { + $grecaptcha_v3_score = (float) $grecaptcha_v3_score; + if ( isset( $data->action ) && ( 'password_protected' === $data->action ) && isset( $data->score ) && $data->score >= $grecaptcha_v3_score ) { + return $errors; + } else { + $error_message = wp_kses( __( 'ERROR: Low Score ', 'password-protected' ) . ':' . esc_html( $data->score ) , array( 'strong' => array() ) ); + $errors->add( 002, $error_message ); + } + } + } + + return $errors; + } + + } + + /** + * Get IP Address + * + * @since 2.6 + * + * @return string client IP address + */ + private static function get_ip_address() { + $ipaddress = ''; + if (isset($_SERVER['HTTP_CLIENT_IP'])) + $ipaddress = sanitize_text_field( $_SERVER['HTTP_CLIENT_IP'] ); + else if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])) + $ipaddress = sanitize_text_field( $_SERVER['HTTP_X_FORWARDED_FOR'] ); + else if(isset($_SERVER['HTTP_X_FORWARDED'])) + $ipaddress = sanitize_text_field( $_SERVER['HTTP_X_FORWARDED'] ); + else if(isset($_SERVER['HTTP_FORWARDED_FOR'])) + $ipaddress = sanitize_text_field( $_SERVER['HTTP_FORWARDED_FOR'] ); + else if(isset($_SERVER['HTTP_FORWARDED'])) + $ipaddress = sanitize_text_field( $_SERVER['HTTP_FORWARDED'] ); + else if(isset($_SERVER['REMOTE_ADDR'])) + $ipaddress = sanitize_text_field( $_SERVER['REMOTE_ADDR'] ); + else + $ipaddress = 'UNKNOWN'; + return $ipaddress; + } + +} + diff --git a/assets/css/admin.css b/assets/css/admin.css new file mode 100644 index 0000000..1a80d45 --- /dev/null +++ b/assets/css/admin.css @@ -0,0 +1,78 @@ +#help-notice { + margin-top: 10px; +} + +#help-notice, #pp-sidebar-box { + background: white; + border: #9d9d9d 1px solid; + padding: 0px 20px; +} +.wrap-col-70 { + flex: 0 0 70%; + width: 70%; +} +.wrap-col-25 { + flex: 0 1 25%; +} +.wrap-row { + display: flex; + justify-content: space-between; +} +h2.nav-tab-wrapper { + display: inline-block; +} +div#pp-sidebar-box { + border: 3px dashed #c5c2c2; + border-radius: 10px; + margin-top: 9px; +} +#pp-sidebar-box { + line-height: 1.5; + word-spacing: 2px; +} +#pp-sidebar-box img.image { + width: 100%; +} +.pro-features { + font-size: 14px; + font-weight: 500; +} +.pro-tab-content { + color: #384d48; + position: relative; + background: #FFF; + padding: 20px; + margin: 20px 0; + border-radius: 6px; + box-shadow: 0px 0px 8px -2px rgb(0 0 0 / 30%); + -webkit-box-shadow: 0px 0px 8px -2px rgb(0 0 0 / 30%); + -moz-box-shadow: 0px 0px 8px -2px rgba(0,0,0, 0.3); + -ms-box-shadow: 0px 0px 8px -2px rgba(0,0,0, 0.3); + -o-box-shadow: 0px 0px 8px -2px rgba(0,0,0, 0.3); +} +a.get_pro_btn { + margin-top: 20px; + display: block; + background: #2271b1; + padding: 10px 20px; + color: #FFF; + text-decoration: none; + border-radius: 30px; + font-weight: bold; + font-size: 16px; + width: 105px; + text-align: center; +} +.pro_container p { + margin: 0; + font-size: 14px; +} +a.nav-tab.getpro.nav-tab { + background: #ffab4a; + color: white; + border-color: #ffab4a; +} + +input#password_protected_password_new, input#password_protected_password_confirm, input#password_protected_remember_me_lifetime, textarea#password_protected_allowed_ip_addresses { + width: 50% !important; +} \ No newline at end of file diff --git a/assets/css/recaptcha.css b/assets/css/recaptcha.css new file mode 100644 index 0000000..47d8194 --- /dev/null +++ b/assets/css/recaptcha.css @@ -0,0 +1,8 @@ +.g-recaptcha { + display: inline-block; + -webkit-transform: scale(.9); + transform: scale(.9); + -webkit-transform-origin: 0 0; + transform-origin: 0 0; + margin-bottom: 0.3rem; +} \ No newline at end of file diff --git a/assets/images/login-designer-demo.gif b/assets/images/login-designer-demo.gif new file mode 100644 index 0000000..5ab17ce Binary files /dev/null and b/assets/images/login-designer-demo.gif differ diff --git a/assets/js/admin.js b/assets/js/admin.js new file mode 100644 index 0000000..e15cb67 --- /dev/null +++ b/assets/js/admin.js @@ -0,0 +1,52 @@ +jQuery( document ).ready(function( $ ) { + + toggle_recaptcha_version( $ ); + set_recaptcha_version_fields( $ ); + +} ); + +function set_recaptcha_version_fields( $ ) { + var selected_version = $("input[name='password_protected_recaptcha[version]']:checked").val(); + if( selected_version == 'google_recaptcha_v2' ) { + hide_recaptcha_v3_fields( $ ); + } else { + hide_recaptcha_v2_fields( $ ); + } +} + +function toggle_recaptcha_version( $ ) { + $("input[name='password_protected_recaptcha[version]']").on('change', function() { + if( $(this).val() === 'google_recaptcha_v2' ) { + // hide v3 fields + hide_recaptcha_v3_fields( $ ); + + // show v2 fields + $("#pp_google_recaptcha_v2_site_key").parent('div').fadeIn(); + $("#pp_google_recaptcha_v2_secret_key").parent('div').fadeIn(); + $("input[name='password_protected_recaptcha[v2_theme]']").parent('label').parent('td').parent('tr').fadeIn(); + + } else { + // show v3 fields + $("#pp_google_recaptcha_v3_site_key").parent('div').fadeIn(); + $("#pp_google_recaptcha_v3_secret_key").parent('div').fadeIn(); + $("#pp_google_recpatcha_v3_score").parent('td').parent('tr').fadeIn(); + $("#pp_google_recpatcha_v3_badge").parent('td').parent('tr').fadeIn(); + + // hide v2 fields + hide_recaptcha_v2_fields( $ ); + } + }); +} + +function hide_recaptcha_v2_fields( $ ) { + $("#pp_google_recaptcha_v2_site_key").parent('div').hide(); + $("#pp_google_recaptcha_v2_secret_key").parent('div').hide(); + $("input[name='password_protected_recaptcha[v2_theme]']").parent('label').parent('td').parent('tr').hide(); +} + +function hide_recaptcha_v3_fields( $ ) { + $("#pp_google_recaptcha_v3_site_key").parent('div').hide(); + $("#pp_google_recaptcha_v3_secret_key").parent('div').hide(); + $("#pp_google_recpatcha_v3_score").parent('td').parent('tr').hide(); + $("#pp_google_recpatcha_v3_badge").parent('td').parent('tr').hide(); +} \ No newline at end of file diff --git a/password-protected.php b/password-protected.php index 293ea0b..d725729 100644 --- a/password-protected.php +++ b/password-protected.php @@ -3,13 +3,12 @@ Plugin Name: Password Protected Plugin URI: https://wordpress.org/plugins/password-protected/ Description: A very simple way to quickly password protect your WordPress site with a single password. Please note: This plugin does not restrict access to uploaded files and images and does not work with some caching setups. -Version: 2.5.1 +Version: 2.6.0 Author: WPExperts Text Domain: password-protected Author URI: https://wpexperts.io/ License: GPLv2 */ - /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2, as @@ -39,7 +38,7 @@ class Password_Protected { - var $version = '2.5.1'; + var $version = '2.6.0'; var $admin = null; var $errors = null; @@ -69,6 +68,9 @@ public function __construct() { add_action( 'password_protected_login_messages', array( $this, 'login_messages' ) ); add_action( 'login_enqueue_scripts', array( $this, 'load_theme_stylesheet' ), 5 ); + add_action('password_protected_above_password_field', array( $this, 'password_protected_above_password_field' )); + add_action('password_protected_below_password_field', array( $this, 'password_protected_below_password_field' )); + // Available from WordPress 4.3+ if ( function_exists( 'wp_site_icon' ) ) { add_action( 'password_protected_login_head', 'wp_site_icon' ); @@ -76,17 +78,21 @@ public function __construct() { add_shortcode( 'password_protected_logout_link', array( $this, 'logout_link_shortcode' ) ); - include_once( dirname( __FILE__ ) . '/admin/admin-bar.php' ); + 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' ); + + 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(); + $this->admin = new Password_Protected_Admin(); + } + include_once dirname( __FILE__ ) . '/admin/class-recaptcha.php'; + new Password_Protected_reCAPTCHA(); } @@ -171,7 +177,7 @@ public function disable_feed() { /** * Allow Feeds * - * @param boolean $bool Allow feeds. + * @param boolean $bool Allow feeds. * @return boolean True/false. */ public function allow_feeds( $bool ) { @@ -187,7 +193,7 @@ public function allow_feeds( $bool ) { /** * Allow Administrators * - * @param boolean $bool Allow administrators. + * @param boolean $bool Allow administrators. * @return boolean True/false. */ public function allow_administrators( $bool ) { @@ -203,7 +209,7 @@ public function allow_administrators( $bool ) { /** * Allow Users * - * @param boolean $bool Allow administrators. + * @param boolean $bool Allow administrators. * @return boolean True/false. */ public function allow_users( $bool ) { @@ -221,7 +227,7 @@ public function allow_users( $bool ) { * * If user has a valid email address, return false to disable password protection. * - * @param boolean $bool Allow IP addresses. + * @param boolean $bool Allow IP addresses. * @return boolean True/false. */ public function allow_ip_addresses( $bool ) { @@ -261,7 +267,7 @@ public function allow_remember_me() { /** * Encrypt Password * - * @param string $password Password. + * @param string $password Password. * @return string Encrypted password. */ public function encrypt_password( $password ) { @@ -274,8 +280,8 @@ public function encrypt_password( $password ) { * Maybe Process Logout */ public function maybe_process_logout() { - - if ( isset( $_REQUEST['password-protected'] ) && $_REQUEST['password-protected'] == 'logout' ) { + + if ( isset( $_REQUEST['password-protected'] ) && sanitize_text_field( $_REQUEST['password-protected'] ) == 'logout' ) { $this->logout(); @@ -298,41 +304,75 @@ public function maybe_process_logout() { 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; + + $password_protected_pwd = $_REQUEST['password_protected_pwd']; + $default_password = get_option( 'password_protected_password' ); + $pwd[] = $default_password; + + $pwd = array_filter( $pwd ); + + $this->errors = apply_filters( 'password_protected_verify_recaptcha', $this->errors ); + if( count( @$this->errors->errors ) > 0 ) return; + + $pwd = apply_filters( 'password_protected_passwords', $pwd ); + $auth = false; + + foreach( $pwd as $i => $p ) { + // If correct password... + if ( ( hash_equals( $p, $this->encrypt_password( $password_protected_pwd ) ) && $pwd != '' ) || apply_filters( 'password_protected_process_login', false, $password_protected_pwd ) ) { + // $auth = true; + $auth = apply_filters( 'password_protected_login_password_matched', $p, $this->errors ); + break; } + } + + $this->password_protected_process_login( $auth ); + + } - $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; - } + private function password_protected_process_login( bool $auth ) { + + if( $auth ) + $throttle = apply_filters( 'password_protected_check_for_throttling', true ); - } else { - // ... otherwise incorrect password - $this->clear_auth_cookie(); - $this->errors->add( 'incorrect_password', __( 'Incorrect Password', 'password-protected' ) ); + if( $auth && $throttle ) { + + do_action( 'password_protected_success_login_attempt' ); + $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'] ) ? esc_url($_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 { + $this->safe_redirect( site_url() ); + exit; + } + } else { + do_action( 'password_protected_failure_login_attempt' ); + + // ... otherwise incorrect password + $this->clear_auth_cookie(); + + $show_default_error = apply_filters( 'password_protected_throttling_error_messages', true ); + + if( $show_default_error ) + $this->errors->add( 'incorrect_password', __( 'Incorrect Password', 'password-protected' ) ); } - - } + } /** * Is User Logged In? @@ -350,20 +390,26 @@ public function is_user_logged_in() { */ public function maybe_show_login() { + if ( class_exists( 'Login_designer' ) ) { + if ( is_customize_preview() ) { + return 1; + } + } + // Filter for adding exceptions. $show_login = apply_filters( 'password_protected_show_login', $this->is_active() ); - + // Logged in - if ( $this->is_user_logged_in() ) { + if ( $this->is_user_logged_in() ) { $show_login = false; } - + if ( ! $show_login ) { - return; + return 1; } // Show login form - if ( isset( $_REQUEST['password-protected'] ) && 'login' == $_REQUEST['password-protected'] ) { + if ( isset( $_REQUEST['password-protected'] ) && 'login' == sanitize_text_field( $_REQUEST['password-protected'] ) ) { $default_theme_file = locate_template( array( 'password-protected-login.php' ) ); @@ -432,14 +478,14 @@ public function logout() { /** * Logout URL * - * @param string $redirect_to Optional. Redirect 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 ) + 'redirect_to' => esc_url_raw( $redirect_to ), ); if ( empty( $query['redirect_to'] ) ) { @@ -453,7 +499,7 @@ public function logout_url( $redirect_to = '' ) { /** * Logout Link * - * @param array $args Link args. + * @param array $args Link args. * @return string HTML link tag. */ public function logout_link( $args = null ) { @@ -463,10 +509,13 @@ public function logout_link( $args = null ) { return ''; } - $args = wp_parse_args( $args, array( - 'redirect_to' => '', - 'text' => __( 'Logout', 'password-protected' ) - ) ); + $args = wp_parse_args( + $args, + array( + 'redirect_to' => '', + 'text' => __( 'Logout', 'password-protected' ), + ) + ); if ( empty( $args['text'] ) ) { $args['text'] = __( 'Logout', 'password-protected' ); @@ -479,15 +528,19 @@ public function logout_link( $args = null ) { /** * Logout Link Shortcode * - * @param array $args Link args. + * @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' ); + $atts = shortcode_atts( + array( + 'redirect_to' => '', + 'text' => $content, + ), + $atts, + 'logout_link_shortcode' + ); return $this->logout_link( $atts ); @@ -507,8 +560,8 @@ public function get_hashed_password() { /** * Validate Auth Cookie * - * @param string $cookie Cookie string. - * @param string $scheme Cookie scheme. + * @param string $cookie Cookie string. + * @param string $scheme Cookie scheme. * @return boolean Validation successful? */ public function validate_auth_cookie( $cookie = '', $scheme = '' ) { @@ -529,12 +582,12 @@ public function validate_auth_cookie( $cookie = '', $scheme = '' ) { // Quick check to see if an honest cookie has expired if ( $expired < current_time( 'timestamp' ) ) { - do_action('password_protected_auth_cookie_expired', $cookie_elements); + 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); + $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 ); @@ -552,14 +605,14 @@ public function validate_auth_cookie( $cookie = '', $scheme = '' ) { /** * Generate Auth Cookie * - * @param int $expiration Expiration time in seconds. - * @param string $scheme Cookie scheme. + * @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 ); + $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; @@ -569,8 +622,8 @@ public function generate_auth_cookie( $expiration, $scheme = 'auth' ) { /** * Parse Auth Cookie * - * @param string $cookie Cookie string. - * @param string $scheme Cookie scheme. + * @param string $cookie Cookie string. + * @param string $scheme Cookie scheme. * @return string Cookie string. */ public function parse_auth_cookie( $cookie = '', $scheme = '' ) { @@ -604,18 +657,18 @@ public function parse_auth_cookie( $cookie = '', $scheme = '' ) { * * @todo * - * @param boolean $remember Remember logged in. - * @param string $secure Secure cookie. + * @param boolean $remember Remember logged in. + * @param string $secure Secure cookie. */ - public function set_auth_cookie( $remember = false, $secure = '') { + 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; + $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; + $expiration = current_time( 'timestamp' ) + $expiration_time; + $expire = 0; } if ( '' === $secure ) { @@ -623,7 +676,7 @@ public function set_auth_cookie( $remember = false, $secure = '') { } $secure_password_protected_cookie = apply_filters( 'password_protected_secure_password_protected_cookie', false, $secure ); - $password_protected_cookie = $this->generate_auth_cookie( $expiration, 'password_protected' ); + $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 ) { @@ -664,7 +717,7 @@ 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 ) ) { + if ( empty( $old_version ) || $old_version == '1.1' ) { $pwd = get_option( 'password_protected_password' ); if ( ! empty( $pwd ) ) { $new_pwd = $this->encrypt_password( $pwd ); @@ -689,7 +742,7 @@ 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' ) ); + add_action( 'password_protected_login_head', array( new CWS_Login_Logo_Plugin(), 'login_head' ) ); } elseif ( class_exists( 'UberLoginLogo' ) ) { @@ -714,7 +767,7 @@ public function login_messages() { if ( $this->errors->get_error_code() ) { - $errors = ''; + $errors = ''; $messages = ''; foreach ( $this->errors->get_error_codes() as $code ) { @@ -734,7 +787,6 @@ public function login_messages() { if ( ! empty( $messages ) ) { echo '

' . apply_filters( 'password_protected_login_messages', $messages ) . "

\n"; } - } } @@ -759,14 +811,13 @@ public function load_theme_stylesheet() { if ( ! empty( $located ) ) { $stylesheet_directory = trailingslashit( get_stylesheet_directory() ); - $template_directory = trailingslashit( get_template_directory() ); + $template_directory = trailingslashit( get_template_directory() ); if ( $stylesheet_directory == substr( $located, 0, strlen( $stylesheet_directory ) ) ) { wp_enqueue_style( 'password-protected-login', get_stylesheet_directory_uri() . '/' . $filename ); - } else if ( $template_directory == substr( $located, 0, strlen( $template_directory ) ) ) { + } elseif ( $template_directory == substr( $located, 0, strlen( $template_directory ) ) ) { wp_enqueue_style( 'password-protected-login', get_template_directory_uri() . '/' . $filename ); } - } } @@ -807,7 +858,7 @@ static function is_plugin_supported() { * Always allow logged in users who require REST API for Gutenberg * and other admin/plugin compatibility. * - * @param WP_REST_Request $access Full details about the request. + * @param WP_REST_Request $access Full details about the request. * @return WP_Error|boolean */ public function only_allow_logged_in_rest_access( $access ) { @@ -821,4 +872,24 @@ public function only_allow_logged_in_rest_access( $access ) { } + /** + * Print text above password field + * @return void. + */ + public function password_protected_above_password_field() { + $text = get_option('password_protected_text_above_password'); + if( !empty($text) ) + echo '
' . esc_attr( $text ) . '
'; + } + + /** + * Print text below password field + * @return void. + */ + public function password_protected_below_password_field() { + $text = get_option('password_protected_text_below_password'); + if( !empty($text) ) + echo '
' . esc_attr( $text ) . '
'; + } + } diff --git a/readme.txt b/readme.txt index 22cb6dd..1ce8197 100644 --- a/readme.txt +++ b/readme.txt @@ -2,32 +2,87 @@ Contributors: wpexpertsio Tags: password, protect, password protect, login Requires at least: 4.6 -Tested up to: 5.9.1 +Tested up to: 6.1.1 Requires PHP: 5.6 -Stable tag: 2.5.1 +Stable tag: 2.6.1 License: GPLv2 or later -A very simple way to quickly password protect your WordPress site with a single password. +The ultimate password protection plugin that protects your WordPress site with a single password. == Description == -A very simple way to quickly password protect your WordPress site with a single password. +Password Protected for WordPress allows you to secure your website with a single password. The ultimate password protection plugin protects your WordPress categories, posts, products, and more with the simplest of ease. -This plugin only protects your WordPress generated content. It **does not protect images or uploaded files** so if you enter and exact URL to in image file it will still be accessible. +Password Protected does not protect images or uploaded files, so if you enter an exact URL of an image file, it will still be accessible. -Features include: += Password Protected Features = -* Password protect your WordPress site with a single password. -* Option to allow access to feeds. -* Option to allow administrators access without entering password. -* Works with Mark Jaquith's [Login Logo](https://wordpress.org/plugins/login-logo/) plugin. -* Works with the [Uber Login Logo](https://wordpress.org/plugins/uber-login-logo/) plugin. +* Easy to set up - Password protect your WordPress site with a single password. +* Set a description - Display text (description or instructions) above or below the password field. +* reCaptcha v2/v3 - You can enable Google reCAPTCHA v2 or V3 to increase bot security measures. +* Allow administrators - Option to allow administrators access without entering the password. +* Allow logged-in users - Option to give logged-in users access to the website. +* Allow RSS Feeds - Option to allow access to feeds. +* Allow Rest API Access - Allow admin to access pages and posts. +* Customization - Customize the password-protected screen, including the background, font, logo, color, etc. > Please note, this plugin works by setting a cookie to allow access to the site. If you are using a caching plugin or web hosting such as WP Engine that has in-built caching, you will need to configure the caching service to be disabled if the Password Protected cookie is set. -= Translations = += Password Protected Pro = + +[Password Protected Pro](https://passwordwp.com/#pricing_sec) is equipped with powerful features that will take your WordPress website security to the next level. + +* Exclude page posts & post types - Option to exclude specific pages and post types from password protection. +* Limit login attempts - Limit the user’s attempts to enter a password for a specified interval. +* Lockdown time - Set a time (in minutes) during which users can not enter the password after their login attempts are limited. +* Usage limits - Set a usage limit after which a password can not be used. +* Status control - You can change the status of the password (Active, Deactivated, Expired). +* Manage multiple passwords - Edit, activate, deactivate, or delete passwords (individual or bulk action). +* Set Expiry Dates - Options to select the expiry date for specific passwords +* Activity Log Reports - View the Activity Logs of each user, including their IP address, browser, status, date, and time of password attempts. +* Priority Support - Our team of support professionals will make sure to handle your queries on high priority. + += Detect hackers and bots from abusing password protection with reCAPTCHA = +Google reCAPTCHA v2 or v3 empowers your WordPress website to prevent password abuse against automated software, bots, hackers, etc. This anti-spam tool will allow any real user to access your website easily. + += Password protect any post type = +You can include or exclude any post type from password protection. All of this can be done from the back end using a single password. + += Password protect your WordPress site with a single password = +Password Protected has the ability to secure your entire website with a single password. Everything from pages to posts will also be protected. + += Customize your login page using Login Designer for WordPress = +You password forms should match the theme and branding of your website. With Login Designer, you can add a logo, change the color and background of the form, and use other elemenets to improve the overall user experience. + +[Login Designer](https://wordpress.org/plugins/login-designer/) is the all-in-one WordPress plugin designed for styling custom login pages and giving you live-editing experience unlike any other. Why use Login Designer? Zero refreshes. Contextually displayed options and plugin settings. Custom event triggers. Context-aware previews. Powerful custom controls. Live editing… the list goes on. + += Display password protected content in RSS feeds = +You can allow RSS feeds to show a login page after which user accessing the feed can view the password protected content. Disabling the option will restrict any user's access to the website even if the RSS feed is public. -If you would like to translate this plugin you can easily contribute at the [Translating WordPress](https://translate.wordpress.org/projects/wp-plugins/password-protected/) page. The stable plugin needs to be 95% translated for a language file to be available to download/update via WordPress. += Password usage limits and complexities = +Limits users from entering the password using Password Protected’s Usage Limit counter. Password greater than that limit can not be applicable on the login page. + +Usage limits can also be restricted by setting a password expiry from the calendar settings. This prevents users from re-using any given password. Regular password changes mitigate the risk of any security breach. + +Limiting password attempts prevents security issues like the Brute Force attack, where hackers keep trying to guess your password until they get it right. A complimentary solution to this feature is the Lockdown Timer, which resets the user’s right to log in after exceeding their login attempt limit. + += Monitor and review activity logs for Password Protected = +Password Protected’s Activity Log is similar to an audit log that gives you a record of the events that have taken place on your website. To provide you with a better understanding, here is a list of the details you will find in the activity log: + +* Filter options for passwords used in a specific range (All-time, Today, Yesterday, This Week, This Month) +* IP addresses of the system from where the passwords were attempted. +* Country names from where the passwords were attempted. +* Browser names where the password was attempted. +* Status of the password attempts (successful or failed) + +The admin can also perform the search operation on the activity log. You can search by IP, Country, Browser, and Status. For e.g., searching Success will search all the passwords with successful attempts, and searching Failure will search all the orders with failed attempts. + += Documentation and support = +* Password Protected [Technical Documentation](https://passwordwp.com/documentation/) +* You can open a support ticket [here](https://objectsws.atlassian.net/servicedesk/customer/portal/18) + += Translations = +If you would like to translate this plugin, you can easily contribute to the [Translating WordPress](https://translate.wordpress.org/projects/wp-plugins/password-protected/) page. The stable plugin needs to be 95% translated for a language file to be available to download/update via WordPress. == Installation == @@ -80,9 +135,28 @@ If you would like to translate this plugin you can easily contribute at the [Tra == Screenshots == 1. Login page perfectly mimicks the WordPress login. -2. Password Protected settings page. +2. Login page with reCaptcha v3 +3. Login page with reCaptcha v2 +4. Password Protected general settings page. +4. Password Protected advanced settings page. == Changelog == +2.6.1 +- Fix – Parse error related to PHP version 7.2 + += 2.6.0 = +- Improved admin settings interface and introduced NEW tabs structure. +- NEW: Added Google Recaptcha v2 and v3 to make it more secure. +- NEW: Added Password Protected top-level admin menu for ease. +- NEW: Added option to add text above password Field. +- NEW: Added option to add text below password Field. + += 2.5.3 = +- Improved Settings HTML structure +- Added Note regarding compatibility with login designer within dashboard + += 2.5.2 = +- Made compatibility with [login designer](https://wp.org/plugins/login-designer); Now you can customize the password-protected screen with the customizer using login designer plugin. = 2.5.1 = - Fix - Author name conflict resolved diff --git a/theme/password-protected-login.php b/theme/password-protected-login.php index 866c67c..6ea0fe7 100644 --- a/theme/password-protected-login.php +++ b/theme/password-protected-login.php @@ -90,6 +90,8 @@ function wp_login_viewport_meta() { @@ -115,29 +120,31 @@ function wp_login_viewport_meta() {
-

- +

+

- + +

- + allow_remember_me() ) : ?>

- +

- +

+ +
@@ -153,5 +160,9 @@ function wp_login_viewport_meta() {
+ +
+ +