This repository has been archived on 2026-10-23. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
aktiv-web/wp-content/plugins/restricted-site-access/restricted_site_access.php
T
2014-07-02 16:40:59 +02:00

460 lines
19 KiB
PHP

<?php
/**
Plugin Name: Restricted Site Access
Plugin URI: http://10up.com/plugins/restricted-site-access-wordpress/
Description: <strong>Limit access your site</strong> to visitors who are logged in or accessing the site from a set of specific IP addresses. Send restricted visitors to the log in page, redirect them, or display a message or page. <strong>Powerful control over redirection</strong>, including <strong>SEO friendly redirect headers</strong>. Great solution for Extranets, publicly hosted Intranets, or parallel development sites.
Version: 5.0.1
Author: Jake Goldman, 10up, Oomph
Author URI: http://10up.com
License: GPLv2 or later
*/
class Restricted_Site_Access {
private $rsa_options;
private $basename;
private $settings_page = 'privacy';
private $fields = array(
'approach' => array(
'default' => 1,
'label' => 'Handle restricted visitors',
'field' => 'settings_field_handling',
),
'message' => array(
'default' => 'Access to this site is restricted.',
'label' => 'Restriction message',
'field' => 'settings_field_message',
),
'redirect_url' => array(
'default' => '',
'label' => 'Redirect web address',
'field' => 'settings_field_redirect',
),
'redirect_path' => array(
'default' => 0,
'label' => 'Redirect to same path',
'field' => 'settings_field_redirect_path',
),
'head_code' => array(
'default' => 302,
'label' => 'Redirection status code',
'field' => 'settings_field_redirect_code',
),
'page' => array(
'default' => 0,
'label' => 'Restricted notice page',
'field' => 'settings_field_rsa_page',
),
'allowed' => array(
'default' => array(),
'label' => 'Unrestricted IP addresses',
'field' => 'settings_field_allowed',
),
);
public function __construct() {
$this->basename = plugin_basename( __FILE__ );
add_action( 'parse_request', array( $this, 'restrict_access' ), 1 );
add_action( 'admin_init', array( $this, 'admin_init' ), 1 );
add_action( 'init', array( $this, 'init' ) );
add_action( 'wp_ajax_rsa_ip_check', array( $this, 'ajax_rsa_ip_check' ) );
add_action( 'activate_' . $this->basename, array( $this, 'activation' ) );
add_action( 'deactivate_' . $this->basename, array( $this, 'deactivation' ) );
}
public function init() {
load_plugin_textdomain( 'restricted-site-access', false, dirname( $this->basename ) . '/localization/' );
}
/**
* populate the option with defaults
*/
private function set_option_defaults() {
if ( ! empty( $this->rsa_options ) )
return;
// set default options
$this->rsa_options = (array) get_option( 'rsa_options' );
foreach( $this->fields as $field_name => $field_details ) {
if ( ! isset( $this->rsa_options[$field_name] ) )
$this->rsa_options[$field_name] = $field_details['default'];
}
}
public function restrict_access( $wp ) {
remove_action( 'parse_request', array( $this, 'restrict_access' ), 1 ); // only need it the first time
$is_restricted = ( is_admin() || is_user_logged_in() || get_option( 'blog_public' ) != 2 || ( defined( 'WP_INSTALLING' ) && isset( $_GET['key'] ) ) ) ? false : true;
if ( apply_filters( 'restricted_site_access_is_restricted', $is_restricted, $wp ) === false )
return;
$this->set_option_defaults();
// check for the allow list, if its empty block everything
if ( $list = $this->rsa_options['allowed'] ) {
$remote_ip = $_SERVER['REMOTE_ADDR']; //save the remote ip
if ( strpos( $remote_ip, '.' ) )
$remote_ip = str_replace( '::ffff:', '', $remote_ip ); //handle dual-stack addresses
$remote_ip = inet_pton( $remote_ip ); //parse the remote ip
// iterate through the allow list
foreach( $list as $line ) {
list( $ip, $mask ) = explode( '/', $line . '/128' ); // get the ip and mask from the list
$mask = str_repeat( 'f', $mask >> 2 ); //render the mask as bits, similar to info on the php.net man page discussion for inet_pton
switch( $mask % 4 ) {
case 1:
$mask .= '8';
break;
case 2:
$mask .= 'c';
break;
case 3:
$mask .= 'e';
break;
}
$mask = pack( 'H*', $mask );
// check if the masked versions match
if ( ( inet_pton( $ip ) & $mask ) == ( $remote_ip & $mask ) )
return;
}
}
$rsa_restrict_approach = apply_filters( 'restricted_site_access_approach', $this->rsa_options['approach'] );
do_action( 'restrict_site_access_handling', $rsa_restrict_approach ); // allow users to hook handling
switch( $rsa_restrict_approach ) {
case 4:
if ( $this->rsa_options['page'] && ( $page_id = get_post_field( 'ID', $this->rsa_options['page'] ) ) ) {
unset( $wp->query_vars );
$wp->query_vars['page_id'] = $page_id;
return;
}
case 3:
$message = __( $this->rsa_options['message'], 'restricted-site-access' );
$message .= "\n<!-- access protected by Restricted Site Access plug-in | http://10up.com/plugins/restricted-site-access-wordpress/ -->";
$message = apply_filters( 'restricted_site_access_message', $message );
wp_die( $message, get_bloginfo( 'name' ) . ' - Site Access Restricted' );
case 2:
if ( $this->rsa_options['redirect_url'] ) {
if( ! empty( $this->rsa_options['redirect_path'] ) )
$this->rsa_options['redirect_url'] = untrailingslashit( $this->rsa_options['redirect_url'] ) . $_SERVER["REQUEST_URI"]; // path
break;
}
default:
$this->rsa_options['redirect_path'] = 302;
$current_path = empty( $_SERVER["REQUEST_URI"] ) ? home_url() : $_SERVER["REQUEST_URI"];
$this->rsa_options['redirect_url'] = wp_login_url( $current_path );
}
$redirect_url = apply_filters( 'restricted_site_access_redirect_url', $this->rsa_options['redirect_url'] );
$redirect_code = apply_filters( 'restricted_site_access_head', $this->rsa_options['redirect_path'] );
wp_redirect( $redirect_url, $redirect_code );
die;
}
public function admin_init() {
if ( version_compare( floatval( get_bloginfo( 'version' ) ), '3.5', '>=' ) )
$this->settings_page = 'reading';
// customize privacy message
add_filter( 'privacy_on_link_text', array( $this, 'privacy_on_link_text' ) );
add_filter( 'privacy_on_link_title', array( $this, 'privacy_on_link_title' ) );
// customize privacy page
add_action( 'load-options-' . $this->settings_page . '.php', array( $this, 'load_options_page' ) );
// add new choice for blog privacy
add_action( 'blog_privacy_selector', array( $this, 'blog_privacy_selector' ) );
// settings for restricted site access
register_setting( $this->settings_page, 'rsa_options', array( $this, 'sanitize_options' ) ); // array of fundamental options including ID and caching info
add_settings_section( 'restricted-site-access', '', '__return_false', $this->settings_page );
foreach ( $this->fields as $field_name => $field_data ) {
add_settings_field( $field_name, __( $field_data['label'], 'restricted-site-access' ), array( $this, $field_data['field'] ), $this->settings_page, 'restricted-site-access' );
}
add_filter( 'plugin_action_links_' . $this->basename, array( $this, 'plugin_action_links' ) );
}
public function privacy_on_link_text( $text ) {
if ( get_option( 'blog_public' ) == 2 )
$text = __( 'Public access to this site has been restricted.', 'restricted-site-access' );
return $text;
}
public function privacy_on_link_title( $text ) {
if ( get_option( 'blog_public' ) == 2 )
$text = __( 'Restricted Site Access plug-in is blocking public access to this site.', 'restricted-site-access' );
return $text;
}
public function load_options_page() {
$dev = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.dev' : '';
wp_enqueue_script( 'restricted-site-access', plugin_dir_url( __FILE__ ) . 'restricted-site-access'.$dev.'.js', array('jquery-effects-shake'), '5.0', true );
wp_localize_script( 'restricted-site-access', 'restricted_site_access_l10n', array(
'Remove' => __('Remove','restricted-site-access'),
'wp_version' => floatval( get_bloginfo( 'version' ) ),
) );
add_action( 'admin_notices', array( $this, 'admin_notice' ) );
add_action( 'admin_head', array( $this, 'admin_head' ) );
$this->set_option_defaults();
}
public function admin_notice() {
if ( empty( $this->rsa_options['approach'] ) )
return;
if ( $this->rsa_options['approach'] == 4 && empty( $this->rsa_options['page'] ) )
$message = '<strong>' . __( 'Please select the page you want to show restricted visitors. If no page is selected, WordPress will simply show a general restriction message.', 'restricted-site-access' ) . '</strong>';
elseif ( $this->rsa_options['approach'] == 2 && empty( $this->rsa_options['redirect_url'] ) )
$message = '<strong>' . __( 'Please enter the web address you would like to redirect restriced visitors to. If no address is entered, visitors will be redirected to the login screen.', 'restricted-site-access' ) . '</strong>';
if ( ! empty( $message ) )
echo '<div class="updated settings-error"><p>' . $message . '</p></div>';
}
public function admin_head() {
$screen = get_current_screen();
$screen->add_help_tab( array(
'id' => 'restricted-site-access',
'title' => __('Restricted Site Acccess'),
'content' => '
<p><strong>' . __('Handle restricted visitors','restricted-site-access') . '</strong> - ' . __('choose the method for handling visitors to your site that are restricted.','restricted-site-access') . '</p>
<p><strong>' . __('Allowed IP addresses','restricted-site-access') . '</strong> - ' . __('enter a single IP address (for example, 192.168.1.105) or an IP range using a network prefix (for example, 10.0.0.1/24). Enter your addresses carefully! Here\'s a','restricted-site-access') . ' <a href="http://www.csgnetwork.com/ipinfocalc.html" target="_blank">' . __('handy calculator','restricted-site-access') . '</a> ' . __('to check your prefix.','restricted-site-access') . '</p>
<p>' . __('The redirection fields are only used when "Handle restricted visitors" is set to "Redirect them to a specified web address".','restricted-site-access') . '</p>
<p><strong>' . __('Redirect web address','restricted-site-access') . '</strong> - ' . __('the web address of the site you want the visitor redirected to.','restricted-site-access') . '</p>
<p><strong>' . __('Redirect to same path','restricted-site-access') . '</strong> - ' . __('redirect the visitor to the same path (URI) entered at this site. Typically used when there are two, very similar sites at different public web addresses; for instance, a parallel development server accessible on the Internet but not intended for the public.','restricted-site-access') . '</p>
<p><strong>' . __('Redirection status code','restricted-site-access') . '</strong> - ' . __('redirect status codes can provide certain visitors, particularly search engines, more information about the nature of the redirect. A 301 redirect tells search engines that a page has moved permanently to the new location. 307 indicates a temporary redirect. 302 is an undefined redirect.','restricted-site-access') . '</p>
',
) );
}
public function blog_privacy_selector() {
?>
<input id="blog-restricted" type="radio" name="blog_public" value="2" <?php checked( get_option( 'blog_public' ), 2 ); ?> />
<label for="blog-restricted"><?php _e( 'Restrict site access to visitors who are logged in or allowed by IP address', 'restricted-site-access' ); ?></label>
<?php
}
public function sanitize_options( $input ) {
$new_input['approach'] = (int) $input['approach'];
if ( $new_input['approach'] < 1 || $new_input['approach'] > 4 )
$new_input['approach'] = $this->fields['approach']['default'];
global $allowedtags;
$new_input['message'] = wp_kses( $input['message'], $allowedtags );
$new_input['redirect_path'] = empty( $input['redirect_path'] ) ? 0 : 1;
$new_input['head_code'] = in_array( (int) $input['head_code'], array( 301, 302, 307 ) ) ? (int) $input['head_code'] : $this->fields['head_code']['default'];
$new_input['redirect_url'] = empty( $input['redirect_url'] ) ? '' : esc_url_raw( $input['redirect_url'], array('http','https') );
$new_input['page'] = empty( $input['page'] ) ? 0 : (int) $input['page'];
$new_input['allowed'] = array();
if ( !empty( $input['allowed'] ) && is_array( $input['allowed'] ) ) {
foreach( $input['allowed'] as $ip_address ) {
if ( $this->is_ip( $ip_address ) )
$new_input['allowed'][] = $ip_address;
}
}
return $new_input;
}
public function settings_field_handling( $args ) {
if ( !isset($this->rsa_options['approach']) )
$this->rsa_options['approach'] = 1;
?>
<fieldset>
<input id="rsa-send-to-login" name="rsa_options[approach]" type="radio" value="1" <?php checked( $this->rsa_options['approach'], 1 ); ?> />
<label for="rsa-send-to-login"><?php _e('Send them to the WordPress login screen','restricted-site-access'); ?></label>
<br />
<input id="rsa-redirect-visitor" name="rsa_options[approach]" type="radio" value="2" <?php checked( $this->rsa_options['approach'], 2 ); ?> />
<label for="rsa-redirect-visitor"><?php _e('Redirect them to a specified web address','restricted-site-access'); ?></label>
<br />
<input id="rsa-display-message" name="rsa_options[approach]" type="radio" value="3" <?php checked( $this->rsa_options['approach'], 3 ); ?> />
<label for="rsa-display-message"><?php _e('Show them a simple message','restricted-site-access'); ?></label>
<br />
<input id="rsa-unblocked-page" name="rsa_options[approach]" type="radio" value="4" <?php checked( $this->rsa_options['approach'], 4 ); ?> />
<label for="rsa-unblocked-page"><?php _e('Show them a specific WordPress page I\'ve created','restricted-site-access'); ?></label>
</fieldset>
<?php
}
public function settings_field_allowed( $args ) {
?>
<div class="hide-if-no-js">
<div id="ip_list">
<?php
foreach ( (array) $this->rsa_options['allowed'] as $ip) {
if ( empty( $ip ) )
continue;
echo '<div><input type="text" name="rsa_options[allowed][]" value="' . esc_attr( $ip ) . '" readonly="true" /> <a href="#remove" onclick="remove_ip(this);">' . __( 'Remove' ) . '</a></div>';
}
?>
</div>
<div>
<input type="text" name="newip" id="newip" /> <input class="button" type="button" id="addip" onclick="add_ip(jQuery('#newip').val());" value="<?php _e( 'Add' ); ?>" />
<label for="newip"><span class="description"><?php _e('Enter a single IP address or a range using a subnet prefix','restricted-site-access'); ?></span></label>
</div>
<?php if ( ! empty( $_SERVER['REMOTE_ADDR'] ) ) { ?><input class="button" type="button" onclick="add_ip('<?php echo esc_attr( $_SERVER['REMOTE_ADDR'] ); ?>');" value="<?php _e( 'Add My Current IP Address', 'restricted-site-access' ); ?>" style="margin-top: 5px;" /><br /><?php } ?>
</div>
<p class="hide-if-js"><strong><?php _e('To manage IP addresses, you must use a JavaScript enabled browser.','restricted-site-access'); ?></strong></p>
<?php
}
public function settings_field_message( $args ) {
if ( empty($this->rsa_options['message']) )
$this->rsa_options['message'] = __('Access to this site is restricted.','restricted-site-access');
wp_editor( $this->rsa_options['message'], 'rsa_message', array(
'media_buttons' => false,
'textarea_name' => 'rsa_options[message]',
'textarea_rows' => 4,
'tinymce' => false,
) );
}
public function settings_field_redirect( $args ) {
?>
<input type="text" name="rsa_options[redirect_url]" id="redirect" class="rsa_redirect_field regular-text" value="<?php echo @esc_attr( $this->rsa_options['redirect_url'] ); ?>" />
<?php
}
public function settings_field_redirect_path( $args ) {
?>
<input type="checkbox" name="rsa_options[redirect_path]" value="1" id="redirect_path" class="rsa_redirect_field" <?php @checked( $this->rsa_options['redirect_path'] ); ?> />
<?php _e( 'Send restricted visitor to same path (relative URL) at the new web address', 'restricted-site-access' ); ?>
<?php
}
public function settings_field_redirect_code( $args ) {
if ( empty($this->rsa_options['head_code']) )
$this->rsa_options['head_code'] = 302;
?>
<select name="rsa_options[head_code]" id="redirect_code" class="rsa_redirect_field">
<option value="301" <?php selected( $this->rsa_options['head_code'], 301 ); ?>><?php _e( '301 Permanent', 'restricted-site-access' ); ?></option>
<option value="302" <?php selected( $this->rsa_options['head_code'], 302 ); ?>><?php _e( '302 Undefined', 'restricted-site-access' ); ?></option>
<option value="307" <?php selected( $this->rsa_options['head_code'], 307 ); ?>><?php _e( '307 Temporary', 'restricted-site-access' ); ?></option>
</select>
<span class="description"><?php _e( 'HTTP status code sent to browser', 'restricted-site-access' ); ?></span>
<?php
}
public function settings_field_rsa_page( $args ) {
wp_dropdown_pages(array(
'selected' => $this->rsa_options['page'],
'show_option_none' => 'Select a page',
'name' => 'rsa_options[page]',
'id' => 'rsa_page'
));
}
/**
* validate IP address entry on demand (AJAX)
*/
public function ajax_rsa_ip_check() {
if ( empty( $_POST['ip_address'] ) )
die('1');
if ( $this->is_ip( stripslashes( $_POST['ip_address'] ) ) )
die;
else
die('1');
}
/**
* is it a valid IP address? v4/v6 with subnet range
*/
public function is_ip( $ip_address ) {
// very basic validation of ranges
if ( strpos( $ip_address, '/' ) ) {
$ip_parts = explode( '/', $ip_address );
if ( empty( $ip_parts[1] ) || !is_numeric( $ip_parts[1] ) || strlen( $ip_parts[1] ) > 3 )
return false;
$ip_address = $ip_parts[0];
}
// confirm IP part is a valid IPv6 or IPv4 IP
if ( empty( $ip_address ) || !inet_pton( stripslashes( $ip_address ) ) )
return false;
return true;
}
/**
* add settings link directing user to privacy page on plug-in page
*/
public function plugin_action_links( $links ) {
$links[] = '<a href="options-' . $this->settings_page . '.php">' . __('Settings') . '</a>';
return $links;
}
/**
* activation of plugin: upgrades old versions, immediately sets privacy
*/
public function activation() {
update_option( 'blog_public', 2 );
}
/**
* restore privacy option to default value upon deactivating
*/
public function deactivation() {
if ( get_option( 'blog_public' ) == 2 )
update_option( 'blog_public', 1 );
}
}
$restricted_site_access = new Restricted_Site_Access;
/**
* uninstall hook - remove options
*/
register_uninstall_hook( __FILE__, 'restricted_site_access_uninstall' );
function restricted_site_access_uninstall() {
if ( get_option('blog_public') == 2 )
update_option( 'blog_public', 1 );
delete_option('rsa_options');
}
/**
* inet_pton is not included in PHP < 5.3 on Windows (WP requires PHP 5.2)
*/
if ( ! function_exists( 'inet_pton' ) ) :
function inet_pton($ip) {
if (strpos($ip, '.') !== false) {
// ipv4
$ip = pack('N',ip2long($ip));
} elseif (strpos($ip, ':') !== false) {
// ipv6
$ip = explode(':', $ip);
$res = str_pad('', (4*(8-count($ip))), '0000', STR_PAD_LEFT);
foreach ($ip as $seg) {
$res .= str_pad($seg, 4, '0', STR_PAD_LEFT);
}
$ip = pack('H'.strlen($res), $res);
}
return $ip;
}
endif;