PluginProbe
Password Protected — Lock Entire Site, Pages, Posts, Categories, and Partial Content / 2.0.3
Password Protected — Lock Entire Site, Pages, Posts, Categories, and Partial Content v2.0.3
2.8.4 2.8.3 2.8.2 2.8.1 trunk 1.0 1.1 1.2 1.2.1 1.2.2 1.3 1.4 1.5 1.6 1.6.1 1.6.2 1.7 1.7.1 1.7.2 1.8 1.9 2.0 2.0.1 2.0.2 2.0.3 All 63 releases
password-protected / password-protected.php

password-protected.php in Password Protected — Lock Entire Site, Pages, Posts, Categories, and Partial Content 2.0.3, at password-protected.php

768 lines 19.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /*
4 Plugin Name: Password Protected
5 Plugin URI: https://wordpress.org/plugins/password-protected/
6 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 on WP Engine or with some caching setups.
7 Version: 2.0.3
8 Author: Ben Huson
9 Text Domain: password-protected
10 Author URI: http://github.com/benhuson/password-protected/
11 License: GPLv2
12 */
13
14 /*
15 Copyright 2012 Ben Huson (email : ben@thewhiteroom.net)
16
17 This program is free software; you can redistribute it and/or modify
18 it under the terms of the GNU General Public License, version 2, as
19 published by the Free Software Foundation.
20
21 This program is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU General Public License for more details.
25
26 You should have received a copy of the GNU General Public License
27 along with this program; if not, write to the Free Software
28 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 */
30
31 /**
32 * @todo Use wp_hash_password() ?
33 * @todo Remember me
34 */
35
36 define( 'PASSWORD_PROTECTED_SUBDIR', '/' . str_replace( basename( __FILE__ ), '', plugin_basename( __FILE__ ) ) );
37 define( 'PASSWORD_PROTECTED_URL', plugins_url( PASSWORD_PROTECTED_SUBDIR ) );
38 define( 'PASSWORD_PROTECTED_DIR', plugin_dir_path( __FILE__ ) );
39
40 global $Password_Protected;
41 $Password_Protected = new Password_Protected();
42
43 class Password_Protected {
44
45 var $version = '2.0.3';
46 var $admin = null;
47 var $errors = null;
48
49 /**
50 * Constructor
51 */
52 public function __construct() {
53
54 $this->errors = new WP_Error();
55
56 register_activation_hook( __FILE__, array( &$this, 'install' ) );
57
58 add_action( 'plugins_loaded', array( $this, 'load_plugin_textdomain' ) );
59
60 add_filter( 'password_protected_is_active', array( $this, 'allow_ip_addresses' ) );
61
62 add_action( 'init', array( $this, 'disable_caching' ), 1 );
63 add_action( 'init', array( $this, 'maybe_process_logout' ), 1 );
64 add_action( 'init', array( $this, 'maybe_process_login' ), 1 );
65 add_action( 'wp', array( $this, 'disable_feeds' ) );
66 add_action( 'template_redirect', array( $this, 'maybe_show_login' ), -1 );
67 add_filter( 'pre_option_password_protected_status', array( $this, 'allow_feeds' ) );
68 add_filter( 'pre_option_password_protected_status', array( $this, 'allow_administrators' ) );
69 add_filter( 'pre_option_password_protected_status', array( $this, 'allow_users' ) );
70 add_action( 'init', array( $this, 'compat' ) );
71 add_action( 'password_protected_login_messages', array( $this, 'login_messages' ) );
72 add_action( 'login_enqueue_scripts', array( $this, 'load_theme_stylesheet' ), 5 );
73
74 add_shortcode( 'password_protected_logout_link', array( $this, 'logout_link_shortcode' ) );
75
76 if ( is_admin() ) {
77 include_once( dirname( __FILE__ ) . '/admin/admin.php' );
78 $this->admin = new Password_Protected_Admin();
79 }
80
81 }
82
83 /**
84 * I18n
85 */
86 public function load_plugin_textdomain() {
87
88 load_plugin_textdomain( 'password-protected', false, basename( dirname( __FILE__ ) ) . '/languages' );
89
90 }
91
92 /**
93 * Disable Page Caching
94 */
95 public function disable_caching() {
96
97 if ( $this->is_active() && ! defined( 'DONOTCACHEPAGE' ) ) {
98 define( 'DONOTCACHEPAGE', true );
99 }
100
101 }
102
103 /**
104 * Is Active?
105 *
106 * @return boolean Is password protection active?
107 */
108 public function is_active() {
109
110 global $wp_query;
111
112 // Always allow access to robots.txt
113 if ( isset( $wp_query ) && is_robots() ) {
114 return false;
115 }
116
117 if ( (bool) get_option( 'password_protected_status' ) ) {
118 $is_active = true;
119 } else {
120 $is_active = false;
121 }
122
123 $is_active = apply_filters( 'password_protected_is_active', $is_active );
124
125 if ( isset( $_GET['password-protected'] ) ) {
126 $is_active = true;
127 }
128
129 return $is_active;
130
131 }
132
133 /**
134 * Disable Feeds
135 *
136 * @todo An option/filter to prevent disabling of feeds.
137 */
138 public function disable_feeds() {
139
140 if ( $this->is_active() ) {
141 add_action( 'do_feed', array( $this, 'disable_feed' ), 1 );
142 add_action( 'do_feed_rdf', array( $this, 'disable_feed' ), 1 );
143 add_action( 'do_feed_rss', array( $this, 'disable_feed' ), 1 );
144 add_action( 'do_feed_rss2', array( $this, 'disable_feed' ), 1 );
145 add_action( 'do_feed_atom', array( $this, 'disable_feed' ), 1 );
146 }
147
148 }
149
150 /**
151 * Disable Feed
152 *
153 * @todo Make Translatable
154 */
155 public function disable_feed() {
156
157 wp_die( sprintf( __( 'Feeds are not available for this site. Please visit the <a href="%s">website</a>.', 'password-protected' ), get_bloginfo( 'url' ) ) );
158
159 }
160
161 /**
162 * Allow Feeds
163 *
164 * @param boolean $bool Allow feeds.
165 * @return boolean True/false.
166 */
167 public function allow_feeds( $bool ) {
168
169 if ( is_feed() && (bool) get_option( 'password_protected_feeds' ) ) {
170 return 0;
171 }
172
173 return $bool;
174
175 }
176
177 /**
178 * Allow Administrators
179 *
180 * @param boolean $bool Allow administrators.
181 * @return boolean True/false.
182 */
183 public function allow_administrators( $bool ) {
184
185 if ( ! is_admin() && current_user_can( 'manage_options' ) && (bool) get_option( 'password_protected_administrators' ) ) {
186 return 0;
187 }
188
189 return $bool;
190
191 }
192
193 /**
194 * Allow Users
195 *
196 * @param boolean $bool Allow administrators.
197 * @return boolean True/false.
198 */
199 public function allow_users( $bool ) {
200
201 if ( ! is_admin() && is_user_logged_in() && (bool) get_option( 'password_protected_users' ) ) {
202 return 0;
203 }
204
205 return $bool;
206
207 }
208
209 /**
210 * Allow IP Addresses
211 *
212 * If user has a valid email address, return false to disable password protection.
213 *
214 * @param boolean $bool Allow IP addresses.
215 * @return boolean True/false.
216 */
217 public function allow_ip_addresses( $bool ) {
218
219 $ip_addresses = $this->get_allowed_ip_addresses();
220
221 if ( in_array( $_SERVER['REMOTE_ADDR'], $ip_addresses ) ) {
222 $bool = false;
223 }
224
225 return $bool;
226
227 }
228
229 /**
230 * Get Allowed IP Addresses
231 *
232 * @return array IP addresses.
233 */
234 public function get_allowed_ip_addresses() {
235
236 return explode( "\n", get_option( 'password_protected_allowed_ip_addresses' ) );
237
238 }
239
240 /**
241 * Encrypt Password
242 *
243 * @param string $password Password.
244 * @return string Encrypted password.
245 */
246 public function encrypt_password( $password ) {
247
248 return md5( $password );
249
250 }
251
252 /**
253 * Maybe Process Logout
254 */
255 public function maybe_process_logout() {
256
257 if ( isset( $_REQUEST['password-protected'] ) && $_REQUEST['password-protected'] == 'logout' ) {
258
259 $this->logout();
260
261 if ( isset( $_REQUEST['redirect_to'] ) ) {
262 $redirect_to = esc_url_raw( $_REQUEST['redirect_to'], array( 'http', 'https' ) );
263 } else {
264 $redirect_to = home_url( '/' );
265 }
266
267 $this->safe_redirect( $redirect_to );
268 exit();
269
270 }
271
272 }
273
274 /**
275 * Maybe Process Login
276 */
277 public function maybe_process_login() {
278
279 if ( $this->is_active() && isset( $_REQUEST['password_protected_pwd'] ) ) {
280 $password_protected_pwd = $_REQUEST['password_protected_pwd'];
281 $pwd = get_option( 'password_protected_password' );
282
283 // If correct password...
284 if ( ( $this->encrypt_password( $password_protected_pwd ) == $pwd && $pwd != '' ) || apply_filters( 'password_protected_process_login', false, $password_protected_pwd ) ) {
285
286 $this->set_auth_cookie();
287 $redirect_to = isset( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : '';
288 $redirect_to = apply_filters( 'password_protected_login_redirect', $redirect_to );
289
290 if ( ! empty( $redirect_to ) ) {
291 $this->safe_redirect( $redirect_to );
292 exit;
293 }
294
295 } else {
296
297 // ... otherwise incorrect password
298 $this->clear_auth_cookie();
299 $this->errors->add( 'incorrect_password', __( 'Incorrect Password', 'password-protected' ) );
300
301 }
302
303 }
304
305 }
306
307 /**
308 * Is User Logged In?
309 *
310 * @return boolean
311 */
312 public function is_user_logged_in() {
313
314 return $this->is_active() && $this->validate_auth_cookie();
315
316 }
317
318 /**
319 * Maybe Show Login
320 */
321 public function maybe_show_login() {
322
323 // Don't show login if not enabled
324 if ( ! $this->is_active() ) {
325 return;
326 }
327
328 // Logged in
329 if ( $this->is_user_logged_in() ) {
330 return;
331 }
332
333 // Show login form
334 if ( isset( $_REQUEST['password-protected'] ) && 'login' == $_REQUEST['password-protected'] ) {
335
336 $default_theme_file = locate_template( array( 'password-protected-login.php' ) );
337
338 if ( empty( $default_theme_file ) ) {
339 $default_theme_file = dirname( __FILE__ ) . '/theme/password-protected-login.php';
340 }
341
342 $theme_file = apply_filters( 'password_protected_theme_file', $default_theme_file );
343 if ( ! file_exists( $theme_file ) ) {
344 $theme_file = $default_theme_file;
345 }
346
347 load_template( $theme_file );
348 exit();
349
350 } else {
351
352 $redirect_to = add_query_arg( 'password-protected', 'login', home_url() );
353
354 // URL to redirect back to after login
355 $redirect_to_url = apply_filters( 'password_protected_login_redirect_url', ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
356 if ( ! empty( $redirect_to_url ) ) {
357 $redirect_to = add_query_arg( 'redirect_to', urlencode( $redirect_to_url ), $redirect_to );
358 }
359
360 wp_redirect( $redirect_to );
361 exit();
362
363 }
364 }
365
366 /**
367 * Get Site ID
368 *
369 * @return string Site ID.
370 */
371 public function get_site_id() {
372
373 global $blog_id;
374 return 'bid_' . apply_filters( 'password_protected_blog_id', $blog_id );
375
376 }
377
378 /**
379 * Login URL
380 *
381 * @return string Login URL.
382 */
383 public function login_url() {
384
385 return add_query_arg( 'password-protected', 'login', home_url( '/' ) );
386
387 }
388
389 /**
390 * Logout
391 */
392 public function logout() {
393
394 $this->clear_auth_cookie();
395 do_action( 'password_protected_logout' );
396
397 }
398
399 /**
400 * Logout URL
401 *
402 * @param string $redirect_to Optional. Redirect URL.
403 * @return string Logout URL.
404 */
405 public function logout_url( $redirect_to = '' ) {
406
407 $query = array(
408 'password-protected' => 'logout',
409 'redirect_to' => esc_url_raw( $redirect_to )
410 );
411
412 if ( empty( $query['redirect_to'] ) ) {
413 unset( $query['redirect_to'] );
414 }
415
416 return add_query_arg( $query, home_url() );
417
418 }
419
420 /**
421 * Logout Link
422 *
423 * @param array $args Link args.
424 * @return string HTML link tag.
425 */
426 public function logout_link( $args = null ) {
427
428 // Only show if user is logged in
429 if ( ! $this->is_user_logged_in() ) {
430 return '';
431 }
432
433 $args = wp_parse_args( $args, array(
434 'redirect_to' => '',
435 'text' => __( 'Logout', 'password-protected' )
436 ) );
437
438 if ( empty( $args['text'] ) ) {
439 $args['text'] = __( 'Logout', 'password-protected' );
440 }
441
442 return sprintf( '<a href="%s">%s</a>', esc_url( $this->logout_url( $args['redirect_to'] ) ), esc_html( $args['text'] ) );
443
444 }
445
446 /**
447 * Logout Link Shortcode
448 *
449 * @param array $args Link args.
450 * @return string HTML link tag.
451 */
452 public function logout_link_shortcode( $atts, $content = null ) {
453
454 $atts = shortcode_atts( array(
455 'redirect_to' => '',
456 'text' => $content
457 ), $atts, 'logout_link_shortcode' );
458
459 return $this->logout_link( $atts );
460
461 }
462
463 /**
464 * Get Hashed Password
465 *
466 * @return string Hashed password.
467 */
468 public function get_hashed_password() {
469
470 return md5( get_option( 'password_protected_password' ) . wp_salt() );
471
472 }
473
474 /**
475 * Validate Auth Cookie
476 *
477 * @param string $cookie Cookie string.
478 * @param string $scheme Cookie scheme.
479 * @return boolean Validation successful?
480 */
481 public function validate_auth_cookie( $cookie = '', $scheme = '' ) {
482
483 if ( ! $cookie_elements = $this->parse_auth_cookie( $cookie, $scheme ) ) {
484 do_action( 'password_protected_auth_cookie_malformed', $cookie, $scheme );
485 return false;
486 }
487
488 extract( $cookie_elements, EXTR_OVERWRITE );
489
490 $expired = $expiration;
491
492 // Allow a grace period for POST and AJAX requests
493 if ( defined( 'DOING_AJAX' ) || 'POST' == $_SERVER['REQUEST_METHOD'] ) {
494 $expired += 3600;
495 }
496
497 // Quick check to see if an honest cookie has expired
498 if ( $expired < current_time( 'timestamp' ) ) {
499 do_action('password_protected_auth_cookie_expired', $cookie_elements);
500 return false;
501 }
502
503 $key = md5( $this->get_site_id() . $this->get_hashed_password() . '|' . $expiration );
504 $hash = hash_hmac( 'md5', $this->get_site_id() . '|' . $expiration, $key);
505
506 if ( $hmac != $hash ) {
507 do_action( 'password_protected_auth_cookie_bad_hash', $cookie_elements );
508 return false;
509 }
510
511 if ( $expiration < current_time( 'timestamp' ) ) { // AJAX/POST grace period set above
512 $GLOBALS['login_grace_period'] = 1;
513 }
514
515 return true;
516
517 }
518
519 /**
520 * Generate Auth Cookie
521 *
522 * @param int $expiration Expiration time in seconds.
523 * @param string $scheme Cookie scheme.
524 * @return string Cookie.
525 */
526 public function generate_auth_cookie( $expiration, $scheme = 'auth' ) {
527
528 $key = md5( $this->get_site_id() . $this->get_hashed_password() . '|' . $expiration );
529 $hash = hash_hmac( 'md5', $this->get_site_id() . '|' . $expiration, $key );
530 $cookie = $this->get_site_id() . '|' . $expiration . '|' . $hash;
531
532 return $cookie;
533
534 }
535
536 /**
537 * Parse Auth Cookie
538 *
539 * @param string $cookie Cookie string.
540 * @param string $scheme Cookie scheme.
541 * @return string Cookie string.
542 */
543 public function parse_auth_cookie( $cookie = '', $scheme = '' ) {
544
545 if ( empty( $cookie ) ) {
546 $cookie_name = $this->cookie_name();
547
548 if ( empty( $_COOKIE[$cookie_name] ) ) {
549 return false;
550 }
551 $cookie = $_COOKIE[$cookie_name];
552 }
553
554 $cookie_elements = explode( '|', $cookie );
555 if ( count( $cookie_elements ) != 3 ) {
556 return false;
557 }
558
559 list( $site_id, $expiration, $hmac ) = $cookie_elements;
560
561 return compact( 'site_id', 'expiration', 'hmac', 'scheme' );
562
563 }
564
565 /**
566 * Set Auth Cookie
567 *
568 * @todo
569 *
570 * @param boolean $remember Remember logged in.
571 * @param string $secure Secure cookie.
572 */
573 public function set_auth_cookie( $remember = false, $secure = '') {
574
575 if ( $remember ) {
576 $expiration = $expire = current_time( 'timestamp' ) + apply_filters( 'password_protected_auth_cookie_expiration', 1209600, $remember );
577 } else {
578 $expiration = current_time( 'timestamp' ) + apply_filters( 'password_protected_auth_cookie_expiration', 172800, $remember );
579 $expire = 0;
580 }
581
582 if ( '' === $secure ) {
583 $secure = is_ssl();
584 }
585
586 $secure_password_protected_cookie = apply_filters( 'password_protected_secure_password_protected_cookie', false, $secure );
587 $password_protected_cookie = $this->generate_auth_cookie( $expiration, 'password_protected' );
588
589 setcookie( $this->cookie_name(), $password_protected_cookie, $expire, COOKIEPATH, COOKIE_DOMAIN, $secure_password_protected_cookie, true );
590 if ( COOKIEPATH != SITECOOKIEPATH ) {
591 setcookie( $this->cookie_name(), $password_protected_cookie, $expire, SITECOOKIEPATH, COOKIE_DOMAIN, $secure_password_protected_cookie, true );
592 }
593
594 }
595
596 /**
597 * Clear Auth Cookie
598 */
599 public function clear_auth_cookie() {
600
601 setcookie( $this->cookie_name(), ' ', current_time( 'timestamp' ) - 31536000, COOKIEPATH, COOKIE_DOMAIN );
602 setcookie( $this->cookie_name(), ' ', current_time( 'timestamp' ) - 31536000, SITECOOKIEPATH, COOKIE_DOMAIN );
603
604 }
605
606 /**
607 * Cookie Name
608 *
609 * @return string Cookie name.
610 */
611 public function cookie_name() {
612
613 return $this->get_site_id() . '_password_protected_auth';
614
615 }
616
617 /**
618 * Install
619 */
620 public function install() {
621
622 $old_version = get_option( 'password_protected_version' );
623
624 // 1.1 - Upgrade to MD5
625 if ( empty( $old_version ) || version_compare( '1.1', $old_version ) ) {
626 $pwd = get_option( 'password_protected_password' );
627 if ( ! empty( $pwd ) ) {
628 $new_pwd = $this->encrypt_password( $pwd );
629 update_option( 'password_protected_password', $new_pwd );
630 }
631 }
632
633 update_option( 'password_protected_version', $this->version );
634
635 }
636
637 /**
638 * Compat
639 *
640 * Support for 3rd party plugins:
641 *
642 * - Login Logo http://wordpress.org/extend/plugins/login-logo/
643 * - Uber Login Logo http://wordpress.org/plugins/uber-login-logo/
644 */
645 public function compat() {
646
647 if ( class_exists( 'CWS_Login_Logo_Plugin' ) ) {
648
649 // Add support for Mark Jaquith's Login Logo plugin
650 add_action( 'password_protected_login_head', array( new CWS_Login_Logo_Plugin, 'login_head' ) );
651
652 } elseif ( class_exists( 'UberLoginLogo' ) ) {
653
654 // Add support for Uber Login Logo plugin
655 add_action( 'password_protected_login_head', array( 'UberLoginLogo', 'replaceLoginLogo' ) );
656
657 }
658
659 }
660
661 /**
662 * Login Messages
663 * Outputs messages and errors in the login template.
664 */
665 public function login_messages() {
666
667 // Add message
668 $message = apply_filters( 'password_protected_login_message', '' );
669 if ( ! empty( $message ) ) {
670 echo $message . "\n";
671 }
672
673 if ( $this->errors->get_error_code() ) {
674
675 $errors = '';
676 $messages = '';
677
678 foreach ( $this->errors->get_error_codes() as $code ) {
679 $severity = $this->errors->get_error_data( $code );
680 foreach ( $this->errors->get_error_messages( $code ) as $error ) {
681 if ( 'message' == $severity ) {
682 $messages .= ' ' . $error . "<br />\n";
683 } else {
684 $errors .= ' ' . $error . "<br />\n";
685 }
686 }
687 }
688
689 if ( ! empty( $errors ) ) {
690 echo '<div id="login_error">' . apply_filters( 'password_protected_login_errors', $errors ) . "</div>\n";
691 }
692 if ( ! empty( $messages ) ) {
693 echo '<p class="message">' . apply_filters( 'password_protected_login_messages', $messages ) . "</p>\n";
694 }
695
696 }
697
698 }
699
700 /**
701 * Load Theme Stylesheet
702 *
703 * Check wether a 'password-protected-login.css' stylesheet exists in your theme
704 * and if so loads it.
705 *
706 * Works with child themes.
707 *
708 * Possible to specify a different file in the theme folder via the
709 * 'password_protected_stylesheet_file' filter (allows for theme subfolders).
710 */
711 public function load_theme_stylesheet() {
712
713 $filename = apply_filters( 'password_protected_stylesheet_file', 'password-protected-login.css' );
714
715 $located = locate_template( $filename );
716
717 if ( ! empty( $located ) ) {
718
719 $stylesheet_directory = trailingslashit( get_stylesheet_directory() );
720 $template_directory = trailingslashit( get_template_directory() );
721
722 if ( $stylesheet_directory == substr( $located, 0, strlen( $stylesheet_directory ) ) ) {
723 wp_enqueue_style( 'password-protected-login', get_stylesheet_directory_uri() . '/' . $filename );
724 } else if ( $template_directory == substr( $located, 0, strlen( $template_directory ) ) ) {
725 wp_enqueue_style( 'password-protected-login', get_template_directory_uri() . '/' . $filename );
726 }
727
728 }
729
730 }
731
732 /**
733 * Safe Redirect
734 *
735 * Ensure the redirect is to the same site or pluggable list of allowed domains.
736 * If invalid will redirect to ...
737 * Based on the WordPress wp_safe_redirect() function.
738 */
739 public function safe_redirect( $location, $status = 302 ) {
740
741 $location = wp_sanitize_redirect( $location );
742 $location = wp_validate_redirect( $location, home_url() );
743
744 wp_redirect( $location, $status );
745
746 }
747
748 /**
749 * Is Plugin Supported?
750 *
751 * Check to see if there are any known reasons why this plugin may not work in
752 * the user's hosting environment.
753 *
754 * @return boolean
755 */
756 static function is_plugin_supported() {
757
758 // WP Engine
759 if ( class_exists( 'WPE_API', false ) ) {
760 return new WP_Error( 'PASSWORD_PROTECTED_SUPPORT', __( 'The Password Protected plugin does not work with WP Engine hosting. Please disable it.', 'password-protected' ) );
761 }
762
763 return true;
764
765 }
766
767 }
768