PageRenderTime 52ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/password-protected.php

https://bitbucket.org/paulwib/wordpress-plugin-mirrors-password-protected
PHP | 333 lines | 189 code | 49 blank | 95 comment | 47 complexity | e65a7b659f0847172f21f19a28127526 MD5 | raw file
  1. <?php
  2. /*
  3. Plugin Name: Password Protected
  4. Plugin URI: http://www.benhuson.co.uk/
  5. Description: A very simple way to quickly password protect your WordPress site with a single password. Integrates seamlessly into your WordPress privacy settings.
  6. Version: 1.4
  7. Author: Ben Huson
  8. Author URI: http://www.benhuson.co.uk/
  9. License: GPLv2
  10. */
  11. /*
  12. Copyright 2012 Ben Huson (email : ben@thewhiteroom.net)
  13. This program is free software; you can redistribute it and/or modify
  14. it under the terms of the GNU General Public License, version 2, as
  15. published by the Free Software Foundation.
  16. This program is distributed in the hope that it will be useful,
  17. but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. GNU General Public License for more details.
  20. You should have received a copy of the GNU General Public License
  21. along with this program; if not, write to the Free Software
  22. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  23. */
  24. /**
  25. * @todo Use wp_hash_password() ?
  26. */
  27. define( 'PASSWORD_PROTECTED_SUBDIR', '/' . str_replace( basename( __FILE__ ), '', plugin_basename( __FILE__ ) ) );
  28. define( 'PASSWORD_PROTECTED_URL', plugins_url( PASSWORD_PROTECTED_SUBDIR ) );
  29. define( 'PASSWORD_PROTECTED_DIR', plugin_dir_path( __FILE__ ) );
  30. global $Password_Protected;
  31. $Password_Protected = new Password_Protected();
  32. class Password_Protected {
  33. var $version = '1.4';
  34. var $admin = null;
  35. var $errors = null;
  36. /**
  37. * Constructor
  38. */
  39. function Password_Protected() {
  40. $this->errors = new WP_Error();
  41. register_activation_hook( __FILE__, array( &$this, 'install' ) );
  42. add_action( 'plugins_loaded', array( $this, 'load_plugin_textdomain' ) );
  43. add_action( 'init', array( $this, 'maybe_process_login' ), 1 );
  44. add_action( 'wp', array( $this, 'disable_feeds' ) );
  45. add_action( 'template_redirect', array( $this, 'maybe_show_login' ), 1 );
  46. add_filter( 'pre_option_password_protected_status', array( $this, 'allow_feeds' ) );
  47. add_filter( 'pre_option_password_protected_status', array( $this, 'allow_administrators' ) );
  48. if ( is_admin() ) {
  49. include_once( dirname( __FILE__ ) . '/admin/admin.php' );
  50. $this->admin = new Password_Protected_Admin();
  51. }
  52. }
  53. /**
  54. * I18n
  55. */
  56. function load_plugin_textdomain() {
  57. load_plugin_textdomain( 'password-protected', false, basename( dirname( __FILE__ ) ) . '/languages' );
  58. }
  59. /**
  60. * Is Active?
  61. */
  62. function is_active() {
  63. if ( (bool) get_option( 'password_protected_status' ) ) {
  64. if ( ! defined( 'DONOTCACHEPAGE' ) )
  65. define( 'DONOTCACHEPAGE', true );
  66. return true;
  67. }
  68. return false;
  69. }
  70. /**
  71. * Disable Feeds
  72. *
  73. * @todo An option/filter to prevent disabling of feeds.
  74. */
  75. function disable_feeds() {
  76. if ( $this->is_active() ) {
  77. add_action( 'do_feed', array( $this, 'disable_feed' ), 1 );
  78. add_action( 'do_feed_rdf', array( $this, 'disable_feed' ), 1 );
  79. add_action( 'do_feed_rss', array( $this, 'disable_feed' ), 1 );
  80. add_action( 'do_feed_rss2', array( $this, 'disable_feed' ), 1 );
  81. add_action( 'do_feed_atom', array( $this, 'disable_feed' ), 1 );
  82. }
  83. }
  84. /**
  85. * Disable Feed
  86. * @todo Make Translatable
  87. */
  88. function disable_feed() {
  89. wp_die( sprintf( __( 'Feeds are not available for this site. Please visit the <a href="%s">website</a>.', 'password-protected' ), get_bloginfo( 'url' ) ) );
  90. }
  91. /**
  92. * Allow Feeds
  93. */
  94. function allow_feeds( $bool ) {
  95. if ( is_feed() && (bool) get_option( 'password_protected_feeds' ) )
  96. return 0;
  97. return $bool;
  98. }
  99. /**
  100. * Allow Administrators
  101. */
  102. function allow_administrators( $bool ) {
  103. if ( ! is_admin() && current_user_can( 'manage_options' ) && (bool) get_option( 'password_protected_administrators' ) )
  104. return 0;
  105. return $bool;
  106. }
  107. /**
  108. * Maybe Process Login
  109. */
  110. function maybe_process_login() {
  111. if ( $this->is_active() && isset( $_REQUEST['password_protected_pwd'] ) ) {
  112. $password_protected_pwd = $_REQUEST['password_protected_pwd'];
  113. $pwd = get_option( 'password_protected_password' );
  114. // If correct password...
  115. if ( ( md5( $password_protected_pwd ) == $pwd && $pwd != '' ) || apply_filters( 'password_protected_process_login', false, $password_protected_pwd ) ) {
  116. $this->set_auth_cookie();
  117. if ( ! empty( $_REQUEST['redirect_to'] ) ) {
  118. wp_redirect( $_REQUEST['redirect_to'] );
  119. exit;
  120. }
  121. } else {
  122. // ... otherwise incorrect password
  123. $this->clear_auth_cookie();
  124. $this->errors->add( 'incorrect_password', __( 'Incorrect Password', 'password-protected' ) );
  125. }
  126. }
  127. // Log out
  128. if ( isset( $_REQUEST['password-protected'] ) && $_REQUEST['password-protected'] == 'logout' ) {
  129. $this->logout();
  130. $redirect_to = remove_query_arg( array( 'password-protected', 'redirect_to' ), ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
  131. $query = array(
  132. 'password-protected' => 'login',
  133. 'redirect_to' => urlencode( $redirect_to )
  134. );
  135. wp_redirect( add_query_arg( $query, home_url() ) );
  136. exit();
  137. }
  138. }
  139. /**
  140. * Maybe Show Login
  141. */
  142. function maybe_show_login() {
  143. // Don't show login if not enabled
  144. if ( ! $this->is_active() )
  145. return;
  146. // Logged in
  147. if ( $this->validate_auth_cookie() )
  148. return;
  149. // Show login form
  150. if ( isset( $_REQUEST['password-protected'] ) && 'login' == $_REQUEST['password-protected'] ) {
  151. include( dirname( __FILE__ ) . '/theme/login.php' );
  152. exit();
  153. } else {
  154. $query = array(
  155. 'password-protected' => 'login',
  156. 'redirect_to' => urlencode( ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] )
  157. );
  158. wp_redirect( add_query_arg( $query, home_url() ) );
  159. exit();
  160. }
  161. }
  162. /**
  163. * Get Site ID
  164. */
  165. function get_site_id() {
  166. global $blog_id;
  167. return 'bid_' . apply_filters( 'password_protected_blog_id', $blog_id );
  168. }
  169. /**
  170. * Logout
  171. */
  172. function logout() {
  173. $this->clear_auth_cookie();
  174. do_action( 'password_protected_logout' );
  175. }
  176. /**
  177. * Validate Auth Cookie
  178. */
  179. function validate_auth_cookie( $cookie = '', $scheme = '' ) {
  180. if ( ! $cookie_elements = $this->parse_auth_cookie( $cookie, $scheme ) ) {
  181. do_action( 'password_protected_auth_cookie_malformed', $cookie, $scheme );
  182. return false;
  183. }
  184. extract( $cookie_elements, EXTR_OVERWRITE );
  185. $expired = $expiration;
  186. // Allow a grace period for POST and AJAX requests
  187. if ( defined( 'DOING_AJAX' ) || 'POST' == $_SERVER['REQUEST_METHOD'] )
  188. $expired += 3600;
  189. // Quick check to see if an honest cookie has expired
  190. if ( $expired < time() ) {
  191. do_action('password_protected_auth_cookie_expired', $cookie_elements);
  192. return false;
  193. }
  194. $pass = md5( get_option( 'password_protected_password' ) );
  195. $pass_frag = substr( $pass, 8, 4 );
  196. $key = md5( $this->get_site_id() . $pass_frag . '|' . $expiration );
  197. $hash = hash_hmac( 'md5', $this->get_site_id() . '|' . $expiration, $key);
  198. if ( $hmac != $hash ) {
  199. do_action( 'password_protected_auth_cookie_bad_hash', $cookie_elements );
  200. return false;
  201. }
  202. if ( $expiration < time() ) // AJAX/POST grace period set above
  203. $GLOBALS['login_grace_period'] = 1;
  204. return true;
  205. }
  206. /**
  207. * Generate Auth Cookie
  208. */
  209. function generate_auth_cookie( $expiration, $scheme = 'auth' ) {
  210. $pass = md5( get_option( 'password_protected_password' ) );
  211. $pass_frag = substr( $pass, 8, 4 );
  212. $key = md5( $this->get_site_id() . $pass_frag . '|' . $expiration );
  213. $hash = hash_hmac( 'md5', $this->get_site_id() . '|' . $expiration, $key );
  214. $cookie = $this->get_site_id() . '|' . $expiration . '|' . $hash;
  215. return $cookie;
  216. }
  217. /**
  218. * Parse Auth Cookie
  219. */
  220. function parse_auth_cookie( $cookie = '', $scheme = '' ) {
  221. if ( empty( $cookie ) ) {
  222. $cookie_name = $this->cookie_name();
  223. if ( empty( $_COOKIE[$cookie_name] ) )
  224. return false;
  225. $cookie = $_COOKIE[$cookie_name];
  226. }
  227. $cookie_elements = explode( '|', $cookie );
  228. if ( count( $cookie_elements ) != 3 )
  229. return false;
  230. list( $site_id, $expiration, $hmac ) = $cookie_elements;
  231. return compact( 'site_id', 'expiration', 'hmac', 'scheme' );
  232. }
  233. /**
  234. * Set Auth Cookie
  235. * @todo
  236. */
  237. function set_auth_cookie( $remember = false, $secure = '') {
  238. if ( $remember ) {
  239. $expiration = $expire = time() + apply_filters( 'password_protected_auth_cookie_expiration', 1209600, $remember );
  240. } else {
  241. $expiration = time() + apply_filters( 'password_protected_auth_cookie_expiration', 172800, $remember );
  242. $expire = 0;
  243. }
  244. if ( '' === $secure )
  245. $secure = is_ssl();
  246. $secure_password_protected_cookie = apply_filters( 'password_protected_secure_password_protected_cookie', false, $secure );
  247. $password_protected_cookie = $this->generate_auth_cookie( $expiration, 'password_protected' );
  248. setcookie( $this->cookie_name(), $password_protected_cookie, $expire, COOKIEPATH, COOKIE_DOMAIN, $secure_password_protected_cookie, true );
  249. if ( COOKIEPATH != SITECOOKIEPATH )
  250. setcookie( $this->cookie_name(), $password_protected_cookie, $expire, SITECOOKIEPATH, COOKIE_DOMAIN, $secure_password_protected_cookie, true );
  251. }
  252. /**
  253. * Clear Auth Cookie
  254. */
  255. function clear_auth_cookie() {
  256. setcookie( $this->cookie_name(), ' ', time() - 31536000, COOKIEPATH, COOKIE_DOMAIN );
  257. setcookie( $this->cookie_name(), ' ', time() - 31536000, SITECOOKIEPATH, COOKIE_DOMAIN );
  258. }
  259. /**
  260. * Cookie Name
  261. */
  262. function cookie_name() {
  263. return $this->get_site_id() . '_password_protected_auth';
  264. }
  265. /**
  266. * Install
  267. */
  268. function install() {
  269. $old_version = get_option( 'password_protected_version' );
  270. // 1.1 - Upgrade to MD5
  271. if ( empty( $old_version ) || version_compare( '1.1', $old_version ) ) {
  272. $pwd = get_option( 'password_protected_password' );
  273. if ( ! empty( $pwd ) ) {
  274. $new_pwd = md5( $pwd );
  275. update_option( 'password_protected_password', $new_pwd );
  276. }
  277. }
  278. update_option( 'password_protected_version', $this->version );
  279. }
  280. }
  281. ?>