File: /home/nakedfoamlojoweb/www/wp-content/plugins/password-protect-page/public/class-ppw-public.php
<?php
/**
* The public-facing functionality of the plugin.
*
* @link https://passwordprotectwp.com
* @since 1.0.0
*
* @package Password_Protect_Page
* @subpackage Password_Protect_Page/public
*/
/**
* The public-facing functionality of the plugin.
*
* Defines the plugin name, version, and two examples hooks for how to
* enqueue the public-facing stylesheet and JavaScript.
*
* @package Password_Protect_Page
* @subpackage Password_Protect_Page/public
* @author BWPS <hello@preventdirectaccess.com>
*/
class PPW_Public {
/**
* The ID of this plugin.
*
* @since 1.0.0
* @access private
* @var string $plugin_name The ID of this plugin.
*/
private $plugin_name;
/**
* The version of this plugin.
*
* @since 1.0.0
* @access private
* @var string $version The current version of this plugin.
*/
private $version;
/**
* Class PPW_Password_Services
*
* @var PPW_Password_Services
*/
private $password_services;
/**
* Initialize the class and set its properties.
*
* @param string $plugin_name The name of the plugin.
* @param string $version The version of this plugin.
*
* @since 1.0.0
*/
public function __construct( $plugin_name, $version ) {
$this->plugin_name = $plugin_name;
$this->version = $version;
$this->password_services = new PPW_Password_Services();
}
/**
* Register the stylesheets and javascript for the public-facing side of the site.
*
* @since 1.0.0
*/
public function enqueue_assets() {
/**
* This function is provided for demonstration purposes only.
*
* An instance of this class should be passed to the run() function
* defined in Password_Protect_Page_Loader as all of the hooks are defined
* in that particular class.
*
* The Password_Protect_Page_Loader will then create the relationship
* between the defined hooks and the functions defined in this
* class.
*/
}
/**
* Filter before render content.
*
* @param string $content Content of post/page.
*
* @return mixed
* @deprecated Because we only use post_password_required to show login form.
* @since 1.2.2 Deprecated for function, we will remove it after 2 release.
*/
public function ppw_filter_content( $content ) {
if ( ! in_the_loop() ) {
return $content;
}
$post = get_post();
if ( is_null( $post ) ) {
return $content;
}
$post_id = $post->ID;
$is_pro_activate = apply_filters( PPW_Constants::HOOK_IS_PRO_ACTIVATE, false );
if ( $is_pro_activate ) {
return apply_filters( PPW_Constants::HOOK_CHECK_PASSWORD_BEFORE_RENDER_CONTENT, $content, $post_id );
}
return $this->ppw_free_content_filter( $content, $post_id );
}
/**
* Filter content for free version
*
* @param array $post_id Data from client.
* @param string $content Data from client.
*
* @return bool|string
* @deprecated
*
*/
private function ppw_free_content_filter( $content, $post_id ) {
// 1. Check page/post is protected.
$result = $this->password_services->is_protected_content( $post_id );
if ( false === $result ) {
return $content;
}
// 2. Check password in cookie.
$passwords = $result['passwords'];
if ( $this->password_services->is_valid_cookie( $post_id, $passwords, PPW_Constants::COOKIE_NAME ) ) {
return $content;
}
// 3. Form rendering.
if ( $result['has_global_passwords'] || ( $result['has_role_passwords'] && $result['has_current_role_password'] ) ) {
return ppw_core_render_login_form();
}
return '<p><strong>' . _e('This page is protected. Please try again or contact the website owner.', PPW_Constants::DOMAIN) . '</strong></p>';
}
/**
* Post class
*
* @param array $classes Classes.
*
* @return array
* @since 1.5.0 Mark deprecated function.
* @deprecated
*/
public function ppw_post_class( $classes ) {
$classes[] = PPW_Constants::CUSTOM_POST_CLASS;
return $classes;
}
/**
* Show custom login form which protected by PPW Plugin, it will replace default form of WordPress.
*
* @param string $output The password form HTML output.
*
* @return string The password form HTML output.
*
* @global WP_Post $post Post object
* @since 1.2.2 Init the_password_form
*/
public function ppw_the_password_form( $output ) {
$post = $GLOBALS['post'];
if ( empty( $post->ID ) || ! ppw_is_post_type_selected_in_setting( $post->post_type ) ) {
return $output;
}
$should_render_form = apply_filters( PPW_Constants::HOOK_SHOULD_RENDER_PASSWORD_FORM, true );
if ( ! $should_render_form ) {
return '';
}
return ppw_core_render_login_form();
}
/**
* Only render text in all page diff post/page custom post type which it is not have post_id input.
* Check a site is post/page or custom post type
* Use regex to check it is our password form then render text.
*
* @param string $content Content of the post.
*
* @return string
*/
public function ppw_the_content( $content ) {
// Do not handle on admin page.
if ( is_admin() ) {
return $content;
}
$is_show_excerpt = ppw_core_get_setting_type_bool_by_option_name( PPW_Constants::PROTECT_EXCERPT, PPW_Constants::MISC_OPTIONS );
if ( is_singular() && ! $is_show_excerpt ) {
return $content;
}
$post = get_post();
// Check post type is selected.
if ( ! $post || ! ppw_is_post_type_selected_in_setting( $post->post_type ) ) {
return $content;
}
// Check it is password form.
if ( post_password_required() ) {
return ppw_handle_protected_content( $post, $content, $is_show_excerpt );
}
return $content;
}
/**
* Register shortcodes
*/
public function register_shortcodes() {
$this->create_caps();
PPW_Shortcode::get_instance();
}
/**
* Create PPWP Capabilities.
*/
public function create_caps() {
global $wp_roles;
if ( ! class_exists( 'WP_Roles' ) ) {
return;
}
if ( ! isset( $wp_roles ) ) {
$wp_roles = new WP_Roles(); // @codingStandardsIgnoreLine
}
$capabilities = array(
'ppwp_manage_options'
);
foreach ( $capabilities as $cap ) {
$wp_roles->add_cap( 'administrator', $cap );
}
}
/**
* Check logic and hide pages/posts protected
*
* @param string $where The WHERE clause of the query.
* @param WP_Query $wp_query The WP_Query instance (passed by reference).
*
* @return string
*/
public function handle_hide_post_protected( $where, $wp_query ) {
if ( is_admin() ) {
return $where;
}
return $this->password_services->handle_hide_post_protected( $where, $wp_query );
}
/**
* Check logic and hide posts protected in recent post
*
* @param array $posts_args An array of arguments used to retrieve the recent posts.
*
* @return array
*/
public function handle_hide_post_protected_recent_post( $posts_args ) {
if ( is_admin() ) {
return $posts_args;
}
return $this->password_services->handle_hide_post_protected_recent_post( $posts_args );
}
/**
* Check logic and hide posts protected in next and previous post
*
* @param string $where The WHERE clause of the query.
*
* @return string
*/
public function handle_hide_post_protected_next_and_previous( $where ) {
if ( is_admin() ) {
return $where;
}
return $this->password_services->handle_hide_post_protected_next_and_previous( $where );
}
/**
* Check condition and exclude protected page in list page get by function get_pages
*
* @param array $pages List of pages to retrieve.
* @param array $param Array of get_pages() arguments.
*
* @return array
*/
public function handle_hide_page_protected( $pages, $param ) {
if ( is_admin() ) {
return $pages;
}
return $this->password_services->handle_hide_page_protected( $pages );
}
/**
* Check condition and exclude page/post protected in Yoast SEO XML Sitemaps
*
* @param array $ids List page_id/post_id exclude in Yoast SEO XML Sitemaps.
*
* @return array
*/
public function handle_hide_page_protected_yoast_seo_sitemaps( $ids ) {
if ( is_admin() ) {
return $ids;
}
return $this->password_services->handle_hide_page_protected_yoast_seo_sitemaps( $ids );
}
/**
* Validate login.
*/
public function ppw_core_validate_login() {
/**
* Should check request have parameter generated by PPF Form.
*/
if ( ! isset( $_GET['action'] ) || ! isset( $_GET['type'] ) || ! isset( $_GET[ PPW_Constants::CALL_BACK_URL_PARAM ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Processing form data without nonce verification. - Not verify nonce for password validate.
return;
}
if ( 'ppw_postpass' !== $_GET['action'] || 'individual' !== $_GET['type'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Processing form data without nonce verification. - Not verify nonce for password validate.
return;
}
if ( ! ppw_core_get_setting_type_bool_by_option_name( PPW_Constants::USE_CUSTOM_FORM_ACTION, PPW_Constants::MISC_OPTIONS ) ) {
return;
}
// It is post method and have post_password input from user.
if ( ! isset( $_POST['post_password'] ) ) {
wp_safe_redirect( $this->password_services->get_referer_url() );
exit();
}
// Get post_id from referer url if Post data is not exist post_id.
$post_id = ppw_get_post_id_from_request();
if ( empty( $post_id ) ) {
wp_safe_redirect( $this->password_services->get_referer_url() );
exit();
}
$password = wp_unslash( $_POST['post_password'] ); // phpcs:ignore -- not sanitize password because we allow all character.
$this->password_services->handle_after_enter_password_in_password_form( $post_id, $password );
}
/**
* Generate action URL.
*
* @param string $action_url Action URL.
*
* @return string Action URL after generated.
*/
public function ppw_core_get_ppf_action_url( $action_url ) {
$_get = wp_unslash( $_GET ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- We no need to handle nonce verification for render UI request.
if ( ! ppw_core_get_setting_type_bool_by_option_name( PPW_Constants::USE_CUSTOM_FORM_ACTION, PPW_Constants::MISC_OPTIONS ) ) {
return $action_url;
}
$callback_value = rawurlencode( apply_filters( PPW_Constants::HOOK_CALLBACK_URL, get_permalink() ) );
$url = add_query_arg(
array(
'action' => 'ppw_postpass',
'type' => 'individual',
PPW_Constants::CALL_BACK_URL_PARAM => $callback_value,
),
''
);
if ( isset( $_get['ppws'] ) ) {
$url = add_query_arg( 'ppws', $_get['ppws'], $url );
}
return $url;
}
/**
* Set cookie time for password.
*
* @param integer $time Expired time of a cookie.
*
* @return integer
*/
public function set_cookie_time( $time ) {
if ( ! isset( $_GET['ppws'] ) || '1' !== $_GET['ppws'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- We no need to handle nonce verification for set cookie function, because already handle in others password checking function.
return $time;
}
return 0;
}
/**
* Set cookie time for password.
*
* @param string $form_action Form action URL.
*
* @return integer
*/
public function set_sitewide_form_action( $form_action ) {
$_get = wp_unslash( $_GET ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- We no need to handle nonce verification for render UI function.
if ( isset( $_get['ppws'] ) ) {
$form_action = $form_action . '&ppws=' . $_get['ppws'];
}
return $form_action;
}
/**
* Handle access link with ppw_ac parameter and without encoding URL.
*/
public function handle_access_link() {
if ( ! isset( $_GET['ppw_ac'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- We no need to handle nonce verification for quick access link.
return;
}
if ( ! is_singular() ) {
return;
}
$password = wp_unslash( $_GET['ppw_ac'] ); // phpcs:ignore -- not sanitize password because we allow all character.
$post_id = get_the_ID();
$permalink = get_permalink( $post_id );
$current_url = apply_filters( 'ppwp_access_link', $permalink, $post_id );
$password_service = new PPW_Password_Services();
$is_valid = $password_service->is_valid_password_from_request( $post_id, $password );
if ( $is_valid ) {
// Bypass single password.
add_filter( 'post_password_required', '__return_false', 50 );
}
}
/**
* Validate password with "No Reload Page" Option.
*/
public function ppw_validate_password() {
if ( isset( $_POST['nonce'] ) && ! wp_verify_nonce( $_POST['nonce'], 'ppw_password_nonce' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.MissingUnslash -- We no need to sanitize here
wp_send_json(
array(
'success' => false,
'message' => 'Cookie nonce is invalid',
),
403
);
wp_die();
}
if ( ! isset( $_POST['post_password'] ) ) {
wp_send_json(
array(
'success' => false,
'message' => 'Password doest not exist',
),
400
);
wp_die();
}
if ( empty( $_POST['post_id'] ) ) {
wp_send_json(
array(
'success' => false,
'message' => 'Post ID is empty',
),
400
);
wp_die();
}
$post_id = absint( $_POST['post_id'] );
$password = wp_unslash( $_POST['post_password'] ); // phpcs:ignore -- we allow all value for password
// Not check password if post does not exist.
$post = get_post( $post_id );
if ( empty( $post ) ) {
wp_send_json(
array(
'success' => false,
'message' => 'Post not found',
),
400
);
wp_die();
}
// Check with recaptcha if user turn on this option.
$using_recaptcha = PPW_Recaptcha::get_instance()->using_single_recaptcha();
if ( $using_recaptcha && ! PPW_Recaptcha::get_instance()->is_valid_recaptcha() ) {
wp_send_json(
array(
'success' => false,
'message' => PPW_Recaptcha::get_instance()->get_error_message(),
),
400
);
wp_die();
}
$post_content = ppw_support_third_party_content_plugin( $post_id, $post->post_content );
$post_content = apply_filters( 'the_content', $post_content );
do_action( 'ppw_ajax_before_validate_password', $post_id, $password, $post_content );
$password_service = new PPW_Password_Services();
$is_valid = $password_service->is_valid_password_from_request( $post_id, $password );
if ( ! $is_valid ) {
wp_send_json(
array(
'success' => false,
'message' => ppw_core_get_error_msg( $post_id ),
),
400
);
wp_die();
}
wp_send_json(
array(
'success' => true,
'post_content' => '<div>' . do_shortcode( $post_content ) . '</div>',
'message' => 'The password you entered is correct',
),
200
);
wp_die();
}
/**
* Support our action to compatibility with Divi builder.
*
* @param array $actions Ajax Actions.
*
* @return array
*/
public function add_action_to_divi( $actions ) {
$actions[] = 'ppw_validate_password';
return $actions;
}
}