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

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