WordPress.org

Plugin Directory

Changeset 620554


Ignore:
Timestamp:
11/03/12 00:57:37 (18 months ago)
Author:
jakemgold
Message:
  • WordPress 3.5 compatibility (3.5 eliminated the Privacy settings panel in favor of a refreshed Reading panel)
  • Real validation (on the fly and on save) for IP address entries
  • "Restriction message" now supports simple HTML and is edited using WordPress's simple HTML tag editor
  • A bunch of visual refinements that conform better with WordPress 3.4 and newer (spacing, native "shake" effect on invalid entries just like the login form, etc.)
  • A bunch of under the hood refinements (e.g. playing nicer with current screen Help API)
Location:
restricted-site-access/trunk
Files:
1 added
1 deleted
6 edited

Legend:

Unmodified
Added
Removed
  • restricted-site-access/trunk/readme.txt

    r410785 r620554  
    11=== Restricted Site Access === 
    2 Contributors: jakemgold, rcbth 
    3 Donate link: http://www.get10up.com/plugins/restricted-site-access-wordpress/ 
    4 Tags: privacy, restricted, restrict, limited, permissions, security, block 
    5 Requires at least: 3.2 
    6 Tested up to: 3.2.1 
    7 Stable tag: 4.0 
     2Contributors: jakemgold, rcbth, 10up, thinkoomph 
     3Donate link: http://10up.com/plugins/restricted-site-access-wordpress/ 
     4Tags: privacy, restricted, restrict, privacy, limited, permissions, security, block 
     5Requires at least: 3.4 
     6Tested up to: 3.5 
     7Stable tag: 5.0 
    88 
    9 Limit access to visitors who are logged in or at specific IP addresses. Many options for handling blocked visitors. Great for Intranets, dev sites. 
     9Limit access to visitors who are logged in or allowed by IP addresses. Includes many options for handling blocked visitors. 
    1010 
    1111== Description == 
    1212 
    13 Limit access your site 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. A great solution for Extranets, publicly hosted Intranets, or parallel development / staging sites. 
     13Limit access your site to visitors who are logged in or accessing the site from a set of specified IP addresses. Send restricted visitors to the log in page, redirect them, or display a message or page. A great solution for Extranets, publicly hosted Intranets, or parallel development / staging sites. 
    1414 
    15 Adds a number of new configuration options to the Privacy settings panel. From this panel you can: 
     15Adds a number of new configuration options to the Reading (WordPress 3.5+) or Privacy (WordPress pre-3.5) settings panel. From this panel you can: 
    1616 
    17 1. Enable or disable site access restriction 
     171. Enable or disable site restriction 
    18181. Change the restriction behavior: send to login, redirect, display a message, display a page 
    19191. Add IP addresses to an unrestricted list, including ranges 
     
    26261. Install easily with the WordPress plugin control panel or manually download the plugin and upload the extracted folder to the `/wp-content/plugins/` directory 
    27271. Activate the plugin through the 'Plugins' menu in WordPress 
    28 1. Configure the plugin by going to the "Privacy" menu under "Settings" 
     281. Configure the plugin by going to the "Reading" menu (WP3.5+) or "Privacy" (earlier versions) under "Settings" 
    2929 
    3030== Frequently Asked Questions == 
     
    3232= How do I unrestrict specific pages or parts of my site? = 
    3333 
    34 Developers can use the `restricted_site_access_is_restricted` filter to override Restricted Site Access. Note that the restriction checks runs before WordPress executes any queries, so use the global `$wp` variable to investigate what the visitor is trying to load. 
     34Developers can use the `restricted_site_access_is_restricted` filter to override Restricted Site Access. Note that the restriction checks happens before WordPress executes any queries, so use the global `$wp` variable to investigate what the visitor is trying to load. 
    3535 
    3636For instance, to unblock an RSS feed, place the following PHP code in the theme's functions.php file or in a simple plug-in: 
     
    4949= How secure is this plug-in? = 
    5050 
    51 Users that are not logged in or allowed by IP address will not be able to browse your site. Restricted Site Access does not block access to your "real" files, so direct links to files in your uploads folder (for instance) are not blocked. It is also important to remember that IP addresses can be spoofed by hackers. Because Restricted Site Access runs as a plug-in, it is subject to general WordPress vulnerabilities. 
     51Users that are not logged in or allowed by IP address will not be able to browse your site. Restricted Site Access does not block access to your "real" files, so direct links to files in your uploads folder (for instance) are not blocked. It is also important to remember that IP addresses can be spoofed by hackers. Because Restricted Site Access runs as a plug-in, it is subject to  any WordPress vulnerabilities. 
    5252 
    5353Restricted Site Access is not meant to be a top secret data safe, but simply a reliable and convenient way to handle unwanted visitors. 
     
    5555== Screenshots == 
    5656 
    57 1. Screenshot of settings panel with simple Restricted Site Access option (send to login page). 
    58 1. Screenshot of settings panel with redirection method enabled, and confirming removal of an IP address from the exception list 
    59 1. Plenty of inline help! Looks and behaves like native WordPress functionality. 
    60 1. Restricted access mode turned off in the privacy settings panel 
     571. Screenshot of settings panel (WP 3.5) with simple Restricted Site Access option (send to login page). 
     581. Screenshot of settings panel (WP 3.5) with restriction message option enabled 
     591. Plenty of inline help! Looks and behaves like native WordPress help. 
    6160 
    6261== Changelog == 
     62 
     63= 5.0 = 
     64* WordPress 3.5 compatibility (3.5 eliminated the Privacy settings panel in favor of a refreshed Reading panel) 
     65* Real validation (on the fly and on save) for IP address entries 
     66* "Restriction message" now supports simple HTML and is edited using WordPress's simple HTML tag editor 
     67* A bunch of visual refinements that conform better with WordPress 3.4 and newer (spacing, native "shake" effect on invalid entries just like the login form, etc.) 
     68* A bunch of under the hood refinements (e.g. playing nicer with current screen Help API) 
    6369 
    6470= 4.0 = 
  • restricted-site-access/trunk/restricted-site-access.js

    r410785 r620554  
    1 // functions for dynamic IP address boxes 
    2  
    3 function add_ip(ip) { 
    4     if (!jQuery.trim(ip)) return false; 
    5      
    6     jQuery('#message').remove(); 
    7      
    8     var ip_used = false; 
    9     jQuery('#ip_list input').each(function(){ 
    10         if (jQuery(this).val() == ip) { 
    11             jQuery(this).animate( { marginLeft: '-45px' }, 250, 'swing', function(){ jQuery(this).animate( { marginLeft: '0px' }, 250, 'swing' ); } ); 
    12             ip_used = true; 
    13             return false;  
    14         } 
    15     }); 
    16     if (ip_used) return false; 
    17      
    18     jQuery('<span style="display: none;"><input type="text" name="rsa_options[allowed][]" value="'+ip+'" readonly="true" /><input type="button" class="button" onclick="remove_ip(this);" value="' + restricted_site_access_l10n.Remove + '" /> <span class="description">' + restricted_site_access_l10n.SaveChanges + '</span><br /></span>').appendTo('#ip_list').slideDown(); 
    19 } 
    20  
    21 function cancel_remove_ip(btnObj) { 
    22     jQuery(btnObj).siblings('.button-primary').removeClass('button-primary').val(restricted_site_access_l10n.Remove); 
    23     jQuery(btnObj).remove(); 
    24 } 
    25  
    26 function remove_ip(btnObj) { 
    27     var jbtnObj = jQuery(btnObj); 
    28     if ( jbtnObj.hasClass('button-primary') ) jbtnObj.parent().slideUp(250,function(){ jQuery(this).remove() }); 
    29     else jbtnObj.val(restricted_site_access_l10n.ConfirmRemove).addClass('button-primary').after('<input type="button" value="' + restricted_site_access_l10n.Cancel + '" class="button" onclick="cancel_remove_ip(this);" />'); 
    30 } 
    31  
    32 // hide and show relevant pieces 
    33 var rsa_table = jQuery('#rsa-send-to-login').closest('table'); 
    34 var rsa_redirect_fields = jQuery('.rsa_redirect_field').closest('tr'); 
    35 var rsa_messsage_field = jQuery('#rsa_message').closest('tr'); 
    36 var rsa_page_field = jQuery('#rsa_page').closest('tr'); 
    37  
    38 if ( jQuery('#blog-restricted:checked').length <= 0 ) rsa_table.hide(); 
    39 if ( jQuery('#rsa-redirect-visitor:checked').length <= 0 ) rsa_redirect_fields.hide(); 
    40 if ( jQuery('#rsa-display-message:checked').length <= 0 ) rsa_messsage_field.hide(); 
    41 if ( jQuery('#rsa-unblocked-page:checked').length <= 0 ) rsa_page_field.hide(); 
    42  
    43 jQuery('input[name="rsa_options[approach]"]').change(function(){ 
    44     if( jQuery('#rsa-redirect-visitor').is(':checked') ) rsa_redirect_fields.show(); 
    45     else rsa_redirect_fields.hide(); 
    46      
    47     if( jQuery('#rsa-display-message').is(':checked') ) rsa_messsage_field.show(); 
    48     else rsa_messsage_field.hide(); 
    49      
    50     if( jQuery('#rsa-unblocked-page').is(':checked') ) rsa_page_field.show(); 
    51     else rsa_page_field.hide(); 
    52 }); 
    53  
    54 jQuery('input[name="blog_public"]').change(function(){ 
    55     if( jQuery('#blog-restricted').is(':checked') ) rsa_table.show(); 
    56     else rsa_table.hide();   
    57 }); 
     1function add_ip(e){var t=600;if(restricted_site_access_l10n.wp_version<3.5)t=60;if(jQuery.trim(e)=="")return false;add_btn.attr("disabled","disabled");var n=jQuery("#ip_list input");for(var r=0,i=n.length;r<n.length;r++){if(n[r].value==e){jQuery(n[r]).parent().effect("shake",t);add_btn.removeAttr("disabled");return false}}jQuery.post(ajaxurl,{action:"rsa_ip_check",ip_address:e},function(n){if(n){jQuery("#newip").parent().effect("shake",t);add_btn.removeAttr("disabled");return false}else{jQuery('<div style="display: none;"><input type="text" name="rsa_options[allowed][]" value="'+e+'" readonly="true" /> <a href="#remove" onclick="remove_ip(this);">'+restricted_site_access_l10n.Remove+"</a></div>").appendTo("#ip_list").slideDown(250);if(e==jQuery("#newip").val())jQuery("#newip").val("");jQuery("#addip").removeAttr("disabled");return true}})}function remove_ip(e){jQuery(e).parent().slideUp(250,function(){jQuery(this).remove()})}var add_btn;jQuery(document).ready(function(e){add_btn=e("#addip");var t=e("#rsa-send-to-login").closest("table");var n=e(".rsa_redirect_field").closest("tr");var r=e("#rsa_message").closest("tr");var i=e("#rsa_page").closest("tr");if(!e("#blog-restricted").is(":checked"))t.hide();if(!e("#rsa-redirect-visitor").is(":checked"))n.hide();if(!e("#rsa-display-message").is(":checked"))r.hide();if(!e("#rsa-unblocked-page").is(":checked"))i.hide();e('input[name="rsa_options[approach]"]').change(function(){if(e("#rsa-redirect-visitor").is(":checked"))n.show();else n.hide();if(e("#rsa-display-message").is(":checked"))r.show();else r.hide();if(e("#rsa-unblocked-page").is(":checked"))i.show();else i.hide()});e('input[name="blog_public"]').change(function(){if(e("#blog-restricted").is(":checked"))t.show();else t.hide()})}) 
  • restricted-site-access/trunk/restricted_site_access.php

    r410785 r620554  
    22/** 
    33 Plugin Name: Restricted Site Access 
    4  Plugin URI: http://www.get10up.com/plugins/restricted-site-access-wordpress/ 
     4 Plugin URI: http://10up.com/plugins/restricted-site-access-wordpress/ 
    55 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. 
    6  Version: 4.0 
    7  Author: Jake Goldman (10up) 
    8  Author URI: http://www.get10up.com 
    9  
    10     Plugin: Copyright 2011 10up (email : jake@get10up.com) 
    11  
    12     This program is free software; you can redistribute it and/or modify 
    13     it under the terms of the GNU General Public License as published by 
    14     the Free Software Foundation; either version 2 of the License, or 
    15     (at your option) any later version. 
    16  
    17     This program is distributed in the hope that it will be useful, 
    18     but WITHOUT ANY WARRANTY; without even the implied warranty of 
    19     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
    20     GNU General Public License for more details. 
    21  
    22     You should have received a copy of the GNU General Public License 
    23     along with this program; if not, write to the Free Software 
    24     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
     6 Version: 5.0 
     7 Author: Jake Goldman, 10up, Oomph 
     8 Author URI: http://10up.com 
     9 License: GPLv2 or later 
    2510*/ 
    2611 
    27 class restricted_site_access { 
     12class Restricted_Site_Access { 
    2813     
    2914    private $rsa_options; 
    30      
     15    private $basename; 
     16    private $settings_page = 'privacy'; 
     17    private $fields = array( 
     18        'approach'      => array( 
     19            'default'   => 1, 
     20            'label'     => 'Handle restricted visitors', 
     21            'field'     => 'settings_field_handling', 
     22        ), 
     23        'message'       => array( 
     24            'default'   => 'Access to this site is restricted.', 
     25            'label'     => 'Restriction message', 
     26            'field'     => 'settings_field_message', 
     27        ), 
     28        'redirect_url'  => array( 
     29            'default'   => '', 
     30            'label'     => 'Redirect web address', 
     31            'field'     => 'settings_field_redirect', 
     32        ), 
     33        'redirect_path' => array( 
     34            'default'   => 0, 
     35            'label'     => 'Redirect to same path', 
     36            'field'     => 'settings_field_redirect_path', 
     37        ), 
     38        'head_code'     => array( 
     39            'default'   => 302, 
     40            'label'     => 'Redirection status code', 
     41            'field'     => 'settings_field_redirect_code', 
     42        ), 
     43        'page'          => array( 
     44            'default'   => 0, 
     45            'label'     => 'Restricted notice page', 
     46            'field'     => 'settings_field_rsa_page', 
     47        ), 
     48        'allowed'       => array( 
     49            'default'   => array(), 
     50            'label'     => 'Unrestricted IP addresses', 
     51            'field'     => 'settings_field_allowed', 
     52        ), 
     53    ); 
     54 
    3155    public function __construct() { 
    32         $this->rsa_options = get_option('rsa_options'); 
     56        $this->basename = plugin_basename( __FILE__ ); 
    3357         
    3458        add_action( 'parse_request', array( $this, 'restrict_access' ), 1 ); 
    35         add_action( 'admin_init', array( $this, 'admin_init' ) ); 
     59        add_action( 'admin_init', array( $this, 'admin_init' ), 1 ); 
    3660        add_action( 'init', array( $this, 'init' ) ); 
    37          
    38         register_activation_hook( __FILE__, array( $this, 'activation' ) ); 
    39         register_deactivation_hook( __FILE__, array( $this, 'deactivation' ) );  
    40     } 
    41      
    42     function init() { 
    43         load_plugin_textdomain( 'restricted-site-access', false, dirname( plugin_basename( __FILE__ ) ) . '/localization/' ); 
     61        add_action( 'wp_ajax_rsa_ip_check', array( $this, 'ajax_rsa_ip_check' ) ); 
     62 
     63        add_action( 'activate_' . $this->basename, array( $this, 'activation' ) ); 
     64        add_action( 'deactivate_' . $this->basename, array( $this, 'deactivation' ) ); 
     65    } 
     66     
     67    public function init() { 
     68        load_plugin_textdomain( 'restricted-site-access', false, dirname( $this->basename ) . '/localization/' ); 
     69    } 
     70 
     71    /** 
     72     * populate the option with defaults 
     73     */ 
     74    private function set_option_defaults() { 
     75        if ( ! empty( $this->rsa_options ) ) 
     76            return; 
     77 
     78        // set default options 
     79        $this->rsa_options = (array) get_option( 'rsa_options' ); 
     80        foreach( $this->fields as $field_name => $field_details ) { 
     81            if ( ! isset( $this->rsa_options[$field_name] ) ) 
     82                $this->rsa_options[$field_name] = $field_details['default']; 
     83        } 
    4484    } 
    4585     
     
    4787        remove_action( 'parse_request', array( $this, 'restrict_access' ), 1 ); // only need it the first time 
    4888         
    49         $is_restricted = ( is_admin() || is_user_logged_in() || get_option('blog_public') != 2 ) ? false : true; 
    50          
    51         if ( apply_filters( 'restricted_site_access_is_restricted', $is_restricted ) === false ) 
     89        $is_restricted = ( is_admin() || is_user_logged_in() || get_option( 'blog_public' ) != 2 ) ? false : true; 
     90        if ( apply_filters( 'restricted_site_access_is_restricted', $is_restricted, $wp ) === false ) 
    5291            return; 
    53          
    54         $rsa_options = $this->rsa_options; 
     92 
     93        $this->set_option_defaults(); 
    5594         
    5695        // check for the allow list, if its empty block everything 
    57         if( isset($rsa_options['allowed']) && ( $list = $rsa_options['allowed'] ) ) { 
    58              
     96        if ( $list = $this->rsa_options['allowed'] ) { 
    5997            $remote_ip = $_SERVER['REMOTE_ADDR'];  //save the remote ip 
    60             if( strpos($remote_ip, '.') ) $remote_ip = str_replace('::ffff:', '', $remote_ip); //handle dual-stack addresses 
    61             $remote_ip = inet_pton($remote_ip); //parse the remote ip 
     98            if ( strpos( $remote_ip, '.' ) ) 
     99                $remote_ip = str_replace( '::ffff:', '', $remote_ip ); //handle dual-stack addresses 
     100            $remote_ip = inet_pton( $remote_ip ); //parse the remote ip 
    62101             
    63102            // iterate through the allow list 
    64             foreach($list as $line) { 
    65                 list($ip, $mask) = explode('/', $line . '/128'); // get the ip and mask from the list 
     103            foreach( $list as $line ) { 
     104                list( $ip, $mask ) = explode( '/', $line . '/128' ); // get the ip and mask from the list 
    66105                 
    67                 $mask = str_repeat('f', $mask >> 2); //render the mask as bits, similar to info on the php.net man page discussion for inet_pton 
    68      
    69                 switch($mask % 4){ 
     106                $mask = str_repeat( 'f', $mask >> 2 ); //render the mask as bits, similar to info on the php.net man page discussion for inet_pton 
     107     
     108                switch( $mask % 4 ) { 
    70109                    case 1: 
    71110                        $mask .= '8'; 
     
    79118                } 
    80119                 
    81                 $mask = pack('H*', $mask); 
     120                $mask = pack( 'H*', $mask ); 
    82121     
    83122                // check if the masked versions match 
    84                 if((inet_pton($ip) & $mask) == ($remote_ip & $mask))  
     123                if ( ( inet_pton( $ip ) & $mask ) == ( $remote_ip & $mask ) ) 
    85124                    return; 
    86125            } 
    87126        } 
    88127         
    89         $rsa_restrict_approach = apply_filters( 'restricted_site_access_approach', $rsa_options['approach'] ); 
    90          
     128        $rsa_restrict_approach = apply_filters( 'restricted_site_access_approach', $this->rsa_options['approach'] ); 
    91129        do_action( 'restrict_site_access_handling', $rsa_restrict_approach ); // allow users to hook handling 
    92130         
    93131        switch( $rsa_restrict_approach ) { 
    94132            case 4: 
    95                 if ( ! empty( $rsa_options['page'] ) && ( $page = get_page( $rsa_options['page'] ) ) ) {                     
     133                if ( $this->rsa_options['page'] && ( $page_id = get_post_field( 'ID', $this->rsa_options['page'] ) ) ) { 
    96134                    unset( $wp->query_vars ); 
    97                     $wp->query_vars['page_id'] = $page->ID; 
     135                    $wp->query_vars['page_id'] = $page_id; 
    98136                    return; 
    99137                } 
    100138             
    101139            case 3: 
    102                 $message = empty($rsa_options['message']) ? __( "Access to this site is restricted.", 'restricted-site-access' ) : $rsa_options['message']; 
    103                 $message .= "\n<!-- access protected by Restricted Site Access plug-in | http://www.get10up.com/plugins/restricted-site-access-wordpress/ -->"; 
     140                $message = __( $this->rsa_options['message'], 'restricted-site-access' ); 
     141                $message .= "\n<!-- access protected by Restricted Site Access plug-in | http://10up.com/plugins/restricted-site-access-wordpress/ -->"; 
    104142                $message = apply_filters( 'restricted_site_access_message', $message ); 
    105143                 
    106                 wp_die( $message, get_bloginfo('name') . ' - Site Access Restricted' ); 
     144                wp_die( $message, get_bloginfo( 'name' ) . ' - Site Access Restricted' ); 
    107145                 
    108146            case 2: 
    109                 if ( ! empty($rsa_options['redirect_url']) ) { 
    110                     if( ! empty($rsa_options['redirect_path']) )  
    111                         $rsa_options['redirect_url'] .= $_SERVER["REQUEST_URI"];    // path 
    112                      
    113                     $rsa_redirect_url = $rsa_options['redirect_url'];                    
    114                     $rsa_redirect_head = empty($rsa_options['head_code']) ? 302 : (int) $rsa_options['head_code'];  // code 
    115                      
     147                if ( $this->rsa_options['redirect_url'] ) { 
     148                    if( ! empty( $this->rsa_options['redirect_path'] ) ) 
     149                        $this->rsa_options['redirect_url'] = untrailingslashit( $this->rsa_options['redirect_url'] ) . $_SERVER["REQUEST_URI"];     // path 
    116150                    break; 
    117151                } 
    118152                 
    119153            default: 
    120                 $rsa_redirect_head = 302; 
    121                 $rsa_redirect_url = wp_login_url( empty($_SERVER["REQUEST_URI"]) ? home_url() : $_SERVER["REQUEST_URI"] );       
    122         } 
    123          
    124         wp_redirect( apply_filters( 'restricted_site_access_redirect_url', $rsa_redirect_url ), apply_filters( 'restricted_site_access_head', $rsa_redirect_head ) ); 
    125         exit; 
     154                $this->rsa_options['redirect_path'] = 302; 
     155                $current_path = empty( $_SERVER["REQUEST_URI"] ) ? home_url() : $_SERVER["REQUEST_URI"]; 
     156                $this->rsa_options['redirect_url'] = wp_login_url( $current_path ); 
     157        } 
     158 
     159        $redirect_url = apply_filters( 'restricted_site_access_redirect_url', $this->rsa_options['redirect_url'] ); 
     160        $redirect_code = apply_filters( 'restricted_site_access_head', $this->rsa_options['redirect_path'] ); 
     161        wp_redirect( $redirect_url, $redirect_code ); 
     162        die; 
    126163    } 
    127164     
    128165    public function admin_init() { 
     166        if ( version_compare( floatval( get_bloginfo( 'version' ) ), '3.5', '>=' ) ) 
     167            $this->settings_page = 'reading'; 
     168 
    129169        // customize privacy message 
    130170        add_filter( 'privacy_on_link_text', array( $this, 'privacy_on_link_text' ) ); 
     
    132172         
    133173        // customize privacy page 
    134         add_action( 'load-options-privacy.php', array( $this, 'load_options_privacy' ) ); 
     174        add_action( 'load-options-' . $this->settings_page . '.php', array( $this, 'load_options_page' ) ); 
    135175         
    136176        // add new choice for blog privacy 
     
    138178         
    139179        // settings for restricted site access 
    140         register_setting( 'privacy', 'rsa_options', array( $this, 'sanitize_options' ) ); //array of fundamental options including ID and caching info 
    141         add_settings_section( 'restricted-site-access', '', '__return_false', 'privacy' ); 
    142         add_settings_field( 'approach', __('Handle restricted visitors', 'restricted-site-access'), array( $this, 'settings_field_handling' ), 'privacy', 'restricted-site-access' ); 
    143         add_settings_field( 'message', __('Restriction message', 'restricted-site-access'), array( $this, 'settings_field_message' ), 'privacy', 'restricted-site-access' ); 
    144         add_settings_field( 'redirect', __('Redirect web address', 'restricted-site-access'), array( $this, 'settings_field_redirect' ), 'privacy', 'restricted-site-access' ); 
    145         add_settings_field( 'redirect_path', __('Redirect to same path', 'restricted-site-access'), array( $this, 'settings_field_redirect_path' ), 'privacy', 'restricted-site-access' ); 
    146         add_settings_field( 'redirect_code', __('Redirection status code', 'restricted-site-access'), array( $this, 'settings_field_redirect_code' ), 'privacy', 'restricted-site-access' ); 
    147         add_settings_field( 'rsa_page', __('Restricted notice page', 'restricted-site-access'), array( $this, 'settings_field_rsa_page' ), 'privacy', 'restricted-site-access' ); 
    148         add_settings_field( 'allowed', __('Unrestricted IP addresses', 'restricted-site-access'), array( $this, 'settings_field_allowed' ), 'privacy', 'restricted-site-access' ); 
    149          
    150         add_filter( 'plugin_action_links_' . plugin_basename(__FILE__), array( $this, 'plugin_action_links' ) ); 
     180        register_setting( $this->settings_page, 'rsa_options', array( $this, 'sanitize_options' ) ); // array of fundamental options including ID and caching info 
     181        add_settings_section( 'restricted-site-access', '', '__return_false', $this->settings_page ); 
     182        foreach ( $this->fields as $field_name => $field_data ) { 
     183            add_settings_field( $field_name, __( $field_data['label'], 'restricted-site-access' ), array( $this, $field_data['field'] ), $this->settings_page, 'restricted-site-access' ); 
     184        } 
     185         
     186        add_filter( 'plugin_action_links_' . $this->basename, array( $this, 'plugin_action_links' ) ); 
    151187    } 
    152188     
    153189    public function privacy_on_link_text( $text ) { 
    154         if ( get_option('blog_public') == 2 )  
    155             $text = __('Public access to this site has been restricted.', 'restricted-site-access'); 
     190        if ( get_option( 'blog_public' ) == 2 ) 
     191            $text = __( 'Public access to this site has been restricted.', 'restricted-site-access' ); 
    156192         
    157193        return $text; 
     
    159195     
    160196    public function privacy_on_link_title( $text ) { 
    161         if ( get_option('blog_public') == 2 )  
    162             $text = __('Restricted Site Access plug-in is blocking public access to this site.', 'restricted-site-access'); 
     197        if ( get_option( 'blog_public' ) == 2 ) 
     198            $text = __( 'Restricted Site Access plug-in is blocking public access to this site.', 'restricted-site-access' ); 
    163199         
    164200        return $text; 
    165201    } 
    166202     
    167     public function load_options_privacy() { 
    168         wp_enqueue_script( 'restricted-site-access', plugin_dir_url( __FILE__ ) . 'restricted-site-access.js', array('jquery'), '3.3', true ); 
    169         add_filter( 'contextual_help', array( $this, 'contextual_help' ) ); 
     203    public function load_options_page() { 
     204        $dev = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '.dev' : ''; 
     205        wp_enqueue_script( 'restricted-site-access', plugin_dir_url( __FILE__ ) . 'restricted-site-access'.$dev.'.js', array('jquery-effects-shake'), '5.0', true ); 
     206        wp_localize_script( 'restricted-site-access', 'restricted_site_access_l10n', array( 
     207            'Remove' => __('Remove','restricted-site-access'), 
     208            'wp_version' => floatval( get_bloginfo( 'version' ) ), 
     209        ) ); 
     210 
    170211        add_action( 'admin_notices', array( $this, 'admin_notice' ) ); 
    171          
    172         $js_trans = array( 
    173             'SaveChanges' => __('Click "Save Changes" to save this IP address.','restricted-site-access'), 
    174             'Remove' => __('remove','restricted-site-access'), 
    175             'ConfirmRemove' => __('confirm removal','restricted-site-access'), 
    176             'Cancel' => __('cancel','restricted-site-access') 
    177         ); 
    178         wp_localize_script( 'restricted-site-access', 'restricted_site_access_l10n', $js_trans ); 
    179     } 
    180      
    181     function admin_notice() { 
     212        add_action( 'admin_head', array( $this, 'admin_head' ) ); 
     213 
     214        $this->set_option_defaults(); 
     215    } 
     216     
     217    public function admin_notice() { 
    182218        if ( empty( $this->rsa_options['approach'] ) ) 
    183219            return; 
     
    191227            echo '<div class="updated settings-error"><p>' . $message . '</p></div>'; 
    192228    } 
     229 
     230    public function admin_head() { 
     231        $screen = get_current_screen(); 
     232        $screen->add_help_tab( array( 
     233            'id'      => 'restricted-site-access', 
     234            'title'   => __('Restricted Site Acccess'), 
     235            'content' => ' 
     236                <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> 
     237                <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> 
     238                <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> 
     239                <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> 
     240                <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> 
     241                <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> 
     242            ', 
     243        ) ); 
     244    } 
    193245     
    194246    public function blog_privacy_selector() { 
    195247    ?> 
    196         <br /> 
    197         <input id="blog-restricted" type="radio" name="blog_public" value="2" <?php checked( '2', get_option('blog_public') ); ?> /> 
    198         <label for="blog-restricted"><?php _e('Restrict site access to visitors who are logged in or allowed by IP address', 'restricted-site-access'); ?></label> 
     248        <input id="blog-restricted" type="radio" name="blog_public" value="2" <?php checked( get_option( 'blog_public' ), 2 ); ?> /> 
     249        <label for="blog-restricted"><?php _e( 'Restrict site access to visitors who are logged in or allowed by IP address', 'restricted-site-access' ); ?></label> 
    199250    <?php 
    200251    } 
     
    203254        $new_input['approach'] = (int) $input['approach']; 
    204255        if ( $new_input['approach'] < 1 || $new_input['approach'] > 4 )  
    205             $new_input['approach'] = 1; 
    206          
     256            $new_input['approach'] = $this->fields['approach']['default']; 
     257 
     258        global $allowedtags; 
     259        $new_input['message'] = wp_kses( $input['message'], $allowedtags ); 
     260 
    207261        $new_input['redirect_path'] = empty( $input['redirect_path'] ) ? 0 : 1; 
    208         $new_input['head_code'] = in_array( (int) $input['head_code'], array(301,302,307) ) ? (int) $input['head_code'] : 302; 
    209         $new_input['message'] = trim( $input['message'] ); 
    210         $new_input['redirect_url'] = empty( $input['redirect_url'] ) ? '' : esc_url( $input['redirect_url'], array('http','https') ); 
    211         $new_input['page'] = empty( $input['page'] ) ? '' : (int) $input['page']; 
    212          
    213         $new_input['allowed'] = $input['allowed'];   // probably need regex at some point 
     262        $new_input['head_code'] = in_array( (int) $input['head_code'], array( 301, 302, 307 ) ) ? (int) $input['head_code'] : $this->fields['head_code']['default']; 
     263        $new_input['redirect_url'] = empty( $input['redirect_url'] ) ? '' : esc_url_raw( $input['redirect_url'], array('http','https') ); 
     264        $new_input['page'] = empty( $input['page'] ) ? 0 : (int) $input['page']; 
     265 
     266        $new_input['allowed'] = array(); 
     267        if ( !empty( $input['allowed'] ) && is_array( $input['allowed'] ) ) { 
     268            foreach( $input['allowed'] as $ip_address ) { 
     269                if ( $this->is_ip( $ip_address ) ) 
     270                    $new_input['allowed'][] = $ip_address; 
     271            } 
     272        } 
    214273         
    215274        return $new_input; 
     
    239298    ?> 
    240299        <div class="hide-if-no-js"> 
    241         <div id="ip_list"> 
    242         <?php 
    243             $ips = empty($this->rsa_options['allowed']) ? array() : $this->rsa_options['allowed']; 
    244                  
    245             foreach ($ips as $key => $ip) { 
    246                 if ( empty($ip) )  
    247                     continue; 
    248                      
    249                 echo '<span><input type="text" name="rsa_options[allowed][]" value="' . esc_attr($ip) . '" readonly="true" /><input type="button" class="button" onclick="remove_ip(this);" value="' . __('remove','restricted-site-access') . '" /><br /></span>'; 
    250             } 
    251         ?> 
    252         </div> 
    253         <input type="text" name="newip" id="newip" value="" /><input class="button" type="button" onclick="add_ip(jQuery('#newip').val());" value="<?php _e('add','restricted-site-access'); ?>" /> 
    254         <span class="description"><?php _e('Enter a single IP address or a range using a subnet prefix','restricted-site-access'); ?> (<a href="#" onclick="jQuery('#contextual-help-link').click(); return false;"><?php _e('help'); ?></a>)</span> 
    255         <br /> 
    256         <?php if ( ! empty($_SERVER['REMOTE_ADDR']) ) { ?> 
    257         <input class="button" type="button" onclick="add_ip('<?php echo $_SERVER['REMOTE_ADDR']; ?>');" value="<?php _e('add my current IP address','restricted-site-access'); ?>" style="margin: 5px 0;" /><br /> 
    258         <?php } ?> 
     300            <div id="ip_list"> 
     301            <?php 
     302                foreach ( (array) $this->rsa_options['allowed'] as $ip) { 
     303                    if ( empty( $ip ) ) 
     304                        continue; 
     305 
     306                    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>'; 
     307                } 
     308            ?> 
     309            </div> 
     310            <div> 
     311                <input type="text" name="newip" id="newip" /> <input class="button" type="button" id="addip" onclick="add_ip(jQuery('#newip').val());" value="<?php _e( 'Add' ); ?>" /> 
     312                <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> 
     313            </div> 
     314            <?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 } ?> 
    259315        </div> 
    260316        <p class="hide-if-js"><strong><?php _e('To manage IP addresses, you must use a JavaScript enabled browser.','restricted-site-access'); ?></strong></p> 
     
    265321        if ( empty($this->rsa_options['message']) ) 
    266322            $this->rsa_options['message'] = __('Access to this site is restricted.','restricted-site-access'); 
    267     ?> 
    268         <input type="text" name="rsa_options[message]" id="rsa_message" value="<?php echo esc_attr( $this->rsa_options['message'] ); ?>" class="regular-text" /> 
    269     <?php 
     323 
     324        wp_editor( $this->rsa_options['message'], 'rsa_message', array( 
     325            'media_buttons' => false, 
     326            'textarea_name' => 'rsa_options[message]', 
     327            'textarea_rows' => 4, 
     328            'tinymce'       => false, 
     329        ) ); 
    270330    } 
    271331     
     
    279339    ?> 
    280340        <input type="checkbox" name="rsa_options[redirect_path]" value="1" id="redirect_path" class="rsa_redirect_field" <?php @checked( $this->rsa_options['redirect_path'] ); ?> /> 
    281         <?php _e('Send restricted visitor to same path (relative URL) at the new web address','restricted-site-access'); ?> (<a href="#" onclick="jQuery('#contextual-help-link').click(); return false;"><?php _e('help'); ?></a>) 
     341        <?php _e( 'Send restricted visitor to same path (relative URL) at the new web address', 'restricted-site-access' ); ?> 
    282342    <?php 
    283343    } 
     
    288348    ?> 
    289349        <select name="rsa_options[head_code]" id="redirect_code" class="rsa_redirect_field"> 
    290             <option value="301" <?php selected( $this->rsa_options['head_code'], 301 ); ?>><?php _e('301 Permanent','restricted-site-access'); ?></option> 
    291             <option value="302" <?php selected( $this->rsa_options['head_code'], 302 ); ?>><?php _e('302 Undefined','restricted-site-access'); ?></option> 
    292             <option value="307" <?php selected( $this->rsa_options['head_code'], 307 ); ?>><?php _e('307 Temporary','restricted-site-access'); ?></option> 
     350            <option value="301" <?php selected( $this->rsa_options['head_code'], 301 ); ?>><?php _e( '301 Permanent', 'restricted-site-access' ); ?></option> 
     351            <option value="302" <?php selected( $this->rsa_options['head_code'], 302 ); ?>><?php _e( '302 Undefined', 'restricted-site-access' ); ?></option> 
     352            <option value="307" <?php selected( $this->rsa_options['head_code'], 307 ); ?>><?php _e( '307 Temporary', 'restricted-site-access' ); ?></option> 
    293353        </select> 
    294         <span class="description"><?php _e('HTTP status code sent to browser','restricted-site-access'); ?> (<a href="#" onclick="jQuery('#contextual-help-link').click(); return false;"><?php _e('help'); ?></a>)</span> 
     354        <span class="description"><?php _e( 'HTTP status code sent to browser', 'restricted-site-access' ); ?></span> 
    295355    <?php 
    296356    } 
     
    298358    public function settings_field_rsa_page( $args ) { 
    299359        wp_dropdown_pages(array(  
    300             'selected' => @$this->rsa_options['page'], 
     360            'selected' => $this->rsa_options['page'], 
    301361            'show_option_none' => 'Select a page', 
    302362            'name' => 'rsa_options[page]', 
     
    304364        )); 
    305365    } 
    306      
    307     /** 
    308      * special contextual help added to the privacy screen 
    309      */ 
    310     public function contextual_help( $text )  
    311     { 
    312         return $text . ' 
    313             <h5>Restricted Site Access</h5> 
    314             <p><a href="http://www.get10up.com/plugins/restricted-site-access-wordpress/" target="_blank">Restricted Site Access</a> ' . __('is a plug-in by','restricted-site-access') . ' <a href="http://www.get10up.com" target="_blank">Jake Goldman</a> (<a href="http://www.get10up.com/plugins/restricted-site-access-wordpress/" target="_blank">10up</a>) ' . __('that  allows you to restrict access to logged in users and a set of IP addresses.','restricted-site-access') . '</p> 
    315              
    316             <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>  
    317             <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> 
    318              
    319             <h5>' . __('Redirection Options','restricted-site-access') . '</h5> 
    320             <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> 
    321             <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> 
    322             <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> 
    323             <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> 
    324         ';   
    325     } 
    326      
     366 
     367    /** 
     368     * validate IP address entry on demand (AJAX) 
     369     */ 
     370    public function ajax_rsa_ip_check() { 
     371        if ( empty( $_POST['ip_address'] ) ) 
     372            die('1'); 
     373 
     374        if ( $this->is_ip( stripslashes( $_POST['ip_address'] ) ) ) 
     375            die; 
     376        else 
     377            die('1'); 
     378    } 
     379 
     380    /** 
     381     * is it a valid IP address? v4/v6 with subnet range 
     382     */ 
     383    public function is_ip( $ip_address ) { 
     384        // very basic validation of ranges 
     385        if ( strpos( $ip_address, '/' ) ) { 
     386            $ip_parts = explode( '/', $ip_address ); 
     387            if ( empty( $ip_parts[1] ) || !is_numeric( $ip_parts[1] ) || strlen( $ip_parts[1] ) > 3 ) 
     388                return false; 
     389            $ip_address = $ip_parts[0]; 
     390        } 
     391 
     392        // confirm IP part is a valid IPv6 or IPv4 IP 
     393        if ( empty( $ip_address ) || !inet_pton( stripslashes( $ip_address ) ) ) 
     394            return false; 
     395 
     396        return true; 
     397    } 
     398 
    327399    /** 
    328400     * add settings link directing user to privacy page on plug-in page 
    329401     */ 
    330402    public function plugin_action_links( $links ) { 
    331         $links[] = '<a href="options-privacy.php">'.__('Settings').'</a>';  
     403        $links[] = '<a href="options-' . $this->settings_page . '.php">' . __('Settings') . '</a>'; 
    332404        return $links;  
    333405    } 
     
    337409     */ 
    338410    public function activation() { 
    339         // if upgrading from pre-3.0, update the blog_public option, otherwise just set to 2 
    340         $blog_public = ( isset($this->rsa_options['active']) && ! $this->rsa_options['active'] ) ? 1 : 2; 
    341         update_option( 'blog_public', $blog_public );   // set blog visibility 
     411        update_option( 'blog_public', 2 ); 
    342412    } 
    343413     
     
    346416     */ 
    347417    public function deactivation() { 
    348         if ( get_option('blog_public') == 2 )  
     418        if ( get_option( 'blog_public' ) == 2 ) 
    349419            update_option( 'blog_public', 1 ); 
    350420    } 
    351421} 
    352422 
    353 $restricted_site_access = new restricted_site_access; 
     423$restricted_site_access = new Restricted_Site_Access; 
    354424 
    355425/** 
     
    365435    delete_option('rsa_options'); 
    366436} 
     437 
     438/** 
     439 * inet_pton is not included in PHP < 5.3 on Windows (WP requires PHP 5.2) 
     440 */ 
     441 
     442if ( ! function_exists( 'inet_pton' ) ) : 
     443 
     444    function inet_pton($ip) { 
     445        if (strpos($ip, '.') !== false) { 
     446            // ipv4 
     447            $ip = pack('N',ip2long($ip)); 
     448        } elseif (strpos($ip, ':') !== false) { 
     449            // ipv6 
     450            $ip = explode(':', $ip); 
     451            $res = str_pad('', (4*(8-count($ip))), '0000', STR_PAD_LEFT); 
     452            foreach ($ip as $seg) { 
     453                $res .= str_pad($seg, 4, '0', STR_PAD_LEFT); 
     454            } 
     455            $ip = pack('H'.strlen($res), $res); 
     456        } 
     457        return $ip; 
     458    } 
     459 
     460endif; 
Note: See TracChangeset for help on using the changeset viewer.