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

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