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

456 lines 13.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: http://wordpress.org/extend/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.7.2
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.7.1';
46 var $admin = null;
47 var $errors = null;
48
49 /**
50 * Constructor
51 */
52 function Password_Protected() {
53 $this->errors = new WP_Error();
54 register_activation_hook( __FILE__, array( &$this, 'install' ) );
55 add_action( 'plugins_loaded', array( $this, 'load_plugin_textdomain' ) );
56 add_action( 'init', array( $this, 'disable_caching' ), 1 );
57 add_action( 'init', array( $this, 'maybe_process_login' ), 1 );
58 add_action( 'wp', array( $this, 'disable_feeds' ) );
59 add_action( 'template_redirect', array( $this, 'maybe_show_login' ), 1 );
60 add_filter( 'pre_option_password_protected_status', array( $this, 'allow_feeds' ) );
61 add_filter( 'pre_option_password_protected_status', array( $this, 'allow_administrators' ) );
62 add_filter( 'pre_option_password_protected_status', array( $this, 'allow_users' ) );
63 if ( is_admin() ) {
64 include_once( dirname( __FILE__ ) . '/admin/admin.php' );
65 $this->admin = new Password_Protected_Admin();
66 }
67 }
68
69 /**
70 * I18n
71 */
72 function load_plugin_textdomain() {
73 load_plugin_textdomain( 'password-protected', false, basename( dirname( __FILE__ ) ) . '/languages' );
74 }
75
76 /**
77 * Disable Page Caching
78 */
79 function disable_caching() {
80 if ( $this->is_active() && ! defined( 'DONOTCACHEPAGE' ) ) {
81 define( 'DONOTCACHEPAGE', true );
82 }
83 }
84
85 /**
86 * Is Active?
87 *
88 * @return boolean Is password protection active?
89 */
90 function is_active() {
91 global $wp_query;
92
93 // Always allow access to robots.txt
94 if ( isset( $wp_query ) && is_robots() ) {
95 return false;
96 }
97
98 if ( (bool) get_option( 'password_protected_status' ) ) {
99 return true;
100 }
101 return false;
102 }
103
104 /**
105 * Disable Feeds
106 *
107 * @todo An option/filter to prevent disabling of feeds.
108 */
109 function disable_feeds() {
110 if ( $this->is_active() ) {
111 add_action( 'do_feed', array( $this, 'disable_feed' ), 1 );
112 add_action( 'do_feed_rdf', array( $this, 'disable_feed' ), 1 );
113 add_action( 'do_feed_rss', array( $this, 'disable_feed' ), 1 );
114 add_action( 'do_feed_rss2', array( $this, 'disable_feed' ), 1 );
115 add_action( 'do_feed_atom', array( $this, 'disable_feed' ), 1 );
116 }
117 }
118
119 /**
120 * Disable Feed
121 *
122 * @todo Make Translatable
123 */
124 function disable_feed() {
125 wp_die( sprintf( __( 'Feeds are not available for this site. Please visit the <a href="%s">website</a>.', 'password-protected' ), get_bloginfo( 'url' ) ) );
126 }
127
128 /**
129 * Allow Feeds
130 *
131 * @param boolean $bool Allow feeds.
132 * @return boolean True/false.
133 */
134 function allow_feeds( $bool ) {
135 if ( is_feed() && (bool) get_option( 'password_protected_feeds' ) ) {
136 return 0;
137 }
138 return $bool;
139 }
140
141 /**
142 * Allow Administrators
143 *
144 * @param boolean $bool Allow administrators.
145 * @return boolean True/false.
146 */
147 function allow_administrators( $bool ) {
148 if ( ! is_admin() && current_user_can( 'manage_options' ) && (bool) get_option( 'password_protected_administrators' ) ) {
149 return 0;
150 }
151 return $bool;
152 }
153
154 /**
155 * Allow Users
156 *
157 * @param boolean $bool Allow administrators.
158 * @return boolean True/false.
159 */
160 function allow_users( $bool ) {
161 if ( ! is_admin() && current_user_can( 'manage_options' ) && (bool) get_option( 'password_protected_users' ) ) {
162 return 0;
163 }
164 return $bool;
165 }
166
167 /**
168 * Encrypt Password
169 *
170 * @param string $password Password.
171 * @return string Encrypted password.
172 */
173 function encrypt_password( $password ) {
174 return md5( $password );
175 }
176
177 /**
178 * Maybe Process Login
179 */
180 function maybe_process_login() {
181 if ( $this->is_active() && isset( $_REQUEST['password_protected_pwd'] ) ) {
182 $password_protected_pwd = $_REQUEST['password_protected_pwd'];
183 $pwd = get_option( 'password_protected_password' );
184 // If correct password...
185 if ( ( $this->encrypt_password( $password_protected_pwd ) == $pwd && $pwd != '' ) || apply_filters( 'password_protected_process_login', false, $password_protected_pwd ) ) {
186 $this->set_auth_cookie();
187 $redirect_to = isset( $_REQUEST['redirect_to'] ) ? $_REQUEST['redirect_to'] : '';
188 $redirect_to = apply_filters( 'password_protected_login_redirect', $redirect_to );
189 if ( ! empty( $redirect_to ) ) {
190 $this->safe_redirect( $redirect_to );
191 exit;
192 }
193 } else {
194 // ... otherwise incorrect password
195 $this->clear_auth_cookie();
196 $this->errors->add( 'incorrect_password', __( 'Incorrect Password', 'password-protected' ) );
197 }
198 }
199
200 // Log out
201 if ( isset( $_REQUEST['password-protected'] ) && $_REQUEST['password-protected'] == 'logout' ) {
202 $this->logout();
203 if ( isset( $_REQUEST['redirect_to'] ) ) {
204 $redirect_to = esc_url_raw( $_REQUEST['redirect_to'], array( 'http', 'https' ) );
205 wp_redirect( $redirect_to );
206 exit();
207 }
208 $redirect_to = remove_query_arg( array( 'password-protected', 'redirect_to' ), ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
209 $query = array(
210 'password-protected' => 'login',
211 'redirect_to' => urlencode( $redirect_to )
212 );
213 wp_redirect( add_query_arg( $query, home_url() ) );
214 exit();
215 }
216 }
217
218 /**
219 * Maybe Show Login
220 */
221 function maybe_show_login() {
222
223 // Don't show login if not enabled
224 if ( ! $this->is_active() ) {
225 return;
226 }
227
228 // Logged in
229 if ( $this->validate_auth_cookie() ) {
230 return;
231 }
232
233 // Show login form
234 if ( isset( $_REQUEST['password-protected'] ) && 'login' == $_REQUEST['password-protected'] ) {
235 $default_theme_file = dirname( __FILE__ ) . '/theme/login.php';
236 $theme_file = apply_filters( 'password_protected_theme_file', $default_theme_file );
237 if ( ! file_exists( $theme_file ) ) {
238 $theme_file = $default_theme_file;
239 }
240 include( $theme_file );
241 exit();
242 } else {
243 $query = array(
244 'password-protected' => 'login',
245 'redirect_to' => urlencode( ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] )
246 );
247 wp_redirect( add_query_arg( $query, home_url() ) );
248 exit();
249 }
250 }
251
252 /**
253 * Get Site ID
254 *
255 * @return string Site ID.
256 */
257 function get_site_id() {
258 global $blog_id;
259 return 'bid_' . apply_filters( 'password_protected_blog_id', $blog_id );
260 }
261
262 /**
263 * Logout
264 */
265 function logout() {
266 $this->clear_auth_cookie();
267 do_action( 'password_protected_logout' );
268 }
269
270 /**
271 * Validate Auth Cookie
272 *
273 * @param string $cookie Cookie string.
274 * @param string $scheme Cookie scheme.
275 * @return boolean Validation successful?
276 */
277 function validate_auth_cookie( $cookie = '', $scheme = '' ) {
278 if ( ! $cookie_elements = $this->parse_auth_cookie( $cookie, $scheme ) ) {
279 do_action( 'password_protected_auth_cookie_malformed', $cookie, $scheme );
280 return false;
281 }
282 extract( $cookie_elements, EXTR_OVERWRITE );
283
284 $expired = $expiration;
285
286 // Allow a grace period for POST and AJAX requests
287 if ( defined( 'DOING_AJAX' ) || 'POST' == $_SERVER['REQUEST_METHOD'] ) {
288 $expired += 3600;
289 }
290
291 // Quick check to see if an honest cookie has expired
292 if ( $expired < time() ) {
293 do_action('password_protected_auth_cookie_expired', $cookie_elements);
294 return false;
295 }
296
297 $pass = md5( get_option( 'password_protected_password' ) );
298 $pass_frag = substr( $pass, 8, 4 );
299
300 $key = md5( $this->get_site_id() . $pass_frag . '|' . $expiration );
301 $hash = hash_hmac( 'md5', $this->get_site_id() . '|' . $expiration, $key);
302
303 if ( $hmac != $hash ) {
304 do_action( 'password_protected_auth_cookie_bad_hash', $cookie_elements );
305 return false;
306 }
307
308 if ( $expiration < time() ) { // AJAX/POST grace period set above
309 $GLOBALS['login_grace_period'] = 1;
310 }
311
312 return true;
313 }
314
315 /**
316 * Generate Auth Cookie
317 *
318 * @param int $expiration Expiration time in seconds.
319 * @param string $scheme Cookie scheme.
320 * @return string Cookie.
321 */
322 function generate_auth_cookie( $expiration, $scheme = 'auth' ) {
323 $pass = md5( get_option( 'password_protected_password' ) );
324 $pass_frag = substr( $pass, 8, 4 );
325
326 $key = md5( $this->get_site_id() . $pass_frag . '|' . $expiration );
327 $hash = hash_hmac( 'md5', $this->get_site_id() . '|' . $expiration, $key );
328 $cookie = $this->get_site_id() . '|' . $expiration . '|' . $hash;
329
330 return $cookie;
331 }
332
333 /**
334 * Parse Auth Cookie
335 *
336 * @param string $cookie Cookie string.
337 * @param string $scheme Cookie scheme.
338 * @return string Cookie string.
339 */
340 function parse_auth_cookie( $cookie = '', $scheme = '' ) {
341 if ( empty( $cookie ) ) {
342 $cookie_name = $this->cookie_name();
343
344 if ( empty( $_COOKIE[$cookie_name] ) ) {
345 return false;
346 }
347 $cookie = $_COOKIE[$cookie_name];
348 }
349
350 $cookie_elements = explode( '|', $cookie );
351 if ( count( $cookie_elements ) != 3 ) {
352 return false;
353 }
354
355 list( $site_id, $expiration, $hmac ) = $cookie_elements;
356
357 return compact( 'site_id', 'expiration', 'hmac', 'scheme' );
358 }
359
360 /**
361 * Set Auth Cookie
362 *
363 * @todo
364 *
365 * @param boolean $remember Remember logged in.
366 * @param string $secure Secure cookie.
367 */
368 function set_auth_cookie( $remember = false, $secure = '') {
369 if ( $remember ) {
370 $expiration = $expire = time() + apply_filters( 'password_protected_auth_cookie_expiration', 1209600, $remember );
371 } else {
372 $expiration = time() + apply_filters( 'password_protected_auth_cookie_expiration', 172800, $remember );
373 $expire = 0;
374 }
375
376 if ( '' === $secure ) {
377 $secure = is_ssl();
378 }
379
380 $secure_password_protected_cookie = apply_filters( 'password_protected_secure_password_protected_cookie', false, $secure );
381 $password_protected_cookie = $this->generate_auth_cookie( $expiration, 'password_protected' );
382
383 setcookie( $this->cookie_name(), $password_protected_cookie, $expire, COOKIEPATH, COOKIE_DOMAIN, $secure_password_protected_cookie, true );
384 if ( COOKIEPATH != SITECOOKIEPATH ) {
385 setcookie( $this->cookie_name(), $password_protected_cookie, $expire, SITECOOKIEPATH, COOKIE_DOMAIN, $secure_password_protected_cookie, true );
386 }
387 }
388
389 /**
390 * Clear Auth Cookie
391 */
392 function clear_auth_cookie() {
393 setcookie( $this->cookie_name(), ' ', time() - 31536000, COOKIEPATH, COOKIE_DOMAIN );
394 setcookie( $this->cookie_name(), ' ', time() - 31536000, SITECOOKIEPATH, COOKIE_DOMAIN );
395 }
396
397 /**
398 * Cookie Name
399 *
400 * @return string Cookie name.
401 */
402 function cookie_name() {
403 return $this->get_site_id() . '_password_protected_auth';
404 }
405
406 /**
407 * Install
408 */
409 function install() {
410 $old_version = get_option( 'password_protected_version' );
411
412 // 1.1 - Upgrade to MD5
413 if ( empty( $old_version ) || version_compare( '1.1', $old_version ) ) {
414 $pwd = get_option( 'password_protected_password' );
415 if ( ! empty( $pwd ) ) {
416 $new_pwd = $this->encrypt_password( $pwd );
417 update_option( 'password_protected_password', $new_pwd );
418 }
419 }
420
421 update_option( 'password_protected_version', $this->version );
422 }
423
424 /**
425 * Safe Redirect
426 *
427 * Ensure the redirect is to the same site or pluggable list of allowed domains.
428 * If invalid will redirect to ...
429 * Based on the WordPress wp_safe_redirect() function.
430 */
431 function safe_redirect( $location, $status = 302 ) {
432 $location = wp_sanitize_redirect( $location );
433 $location = wp_validate_redirect( $location, home_url() );
434 wp_redirect( $location, $status );
435 }
436
437 /**
438 * Is Plugin Supported?
439 *
440 * Check to see if there are any known reasons why this plugin may not work in
441 * the user's hosting environment.
442 *
443 * @return boolean
444 */
445 static function is_plugin_supported() {
446
447 // WP Engine
448 if ( class_exists( 'WPE_API', false ) ) {
449 return new WP_Error( 'PASSWORD_PROTECTED_SUPPORT', __( 'The Password Protected plugin does not work with WP Engine hosting. Please disable it.', 'password-protected' ) );
450 }
451
452 return true;
453 }
454
455 }
456