PluginProbe
Password Protected — Lock Entire Site, Pages, Posts, Categories, and Partial Content / 2.0
Password Protected — Lock Entire Site, Pages, Posts, Categories, and Partial Content v2.0
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, at password-protected.php

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