Restricted Site Access - Version 7.1.0

Version Description

Added * IP whitelist: Add a Comment field next to each IP address to help identify IP addresses added to the whitelist. * Add constants to force enable/disable restrictions. Set RSA_FORCE_RESTRICTION to true to force restriction or RSA_FORBID_RESTRICTION to disable restriction. RSA_FORCE_RESTRICTION will override RSA_FORBID_RESTRICTION if both are set.

Fixed * Disable individual site settings when network enforced mode is on to avoid confusion about why your settings are not being respected. * Correctly load admin JS. * Improve coding standards across plugin and introduce continuous integration linting against the WordPress coding standards. Update code to VIP Go coding standards.

Developers * Add unit tests accross plugin. Note that when the WP_TESTS_DOMAIN constant is set, plugin redirects are disabled. Only set this constant when running the tests. * Deploy plugin from GitHub to WordPress.org using GitHub Actions. * Add various GitHub community files.

Download this release

Release Info

Developer 10upbot
Plugin Icon 128x128 Restricted Site Access
Version 7.1.0
Comparing to
See all releases

Code changes from version 7.0.1 to 7.1.0

assets/js/settings.min.js CHANGED
@@ -1 +1 @@
1
- !function(a,b){"use strict";function c(a){if(""==b.trim(a))return!1;e.add_btn.attr("disabled","disabled");var c=b(d.querySelectorAll("#ip_list input")),f=0;for(c.length;f<c.length;f++)if(c[f].value==a)return b(c[f]).parent().effect("shake",600),e.add_btn.removeAttr("disabled"),!1;jQuery.post(ajaxurl,{action:"rsa_ip_check",ip_address:a},function(c){if(c)return b(e.new_ip.parentNode).effect("shake",600),e.add_btn.removeAttr("disabled"),!1;var d=e.empty_ip.clone().appendTo(e.ip_list_wrap);return d.children("input").val(a),d.removeAttr("id").slideDown(250),a==e.new_ip.value&&b(e.new_ip).val(""),e.add_btn.removeAttr("disabled"),!0})}var d=a.document,e={add_btn:"",new_ip:"",ip_list_wrap:"",empty_ip:"",restrict_radio:"",table:"",redirect_choice:"",message_choice:"",page_choice:"",redirect_fields:"",message_field:"",page_field:""};!function(){e.add_btn=b(d.getElementById("addip")),e.new_ip=d.getElementById("newip"),e.ip_list_wrap=d.getElementById("ip_list"),e.empty_ip=b(d.getElementById("ip_list_empty")),e.restrict_radio=d.getElementById("blog-restricted"),e.table=b(d.getElementById("rsa-send-to-login")).closest("table"),e.redirect_choice=d.getElementById("rsa-redirect-visitor"),e.message_choice=d.getElementById("rsa-display-message"),e.page_choice=d.getElementById("rsa-unblocked-page"),e.redirect_fields=b(d.querySelectorAll(".rsa_redirect_field")).closest("tr"),e.message_field=b(d.getElementById("rsa_message")).closest("tr"),e.page_field=b(d.getElementById("rsa_page")).closest("tr"),e.restrict_radio&&!e.restrict_radio.checked&&e.table.hide(),e.redirect_choice&&!e.redirect_choice.checked&&e.redirect_fields.hide(),e.message_choice&&!e.message_choice.checked&&e.message_field.hide(),e.page_choice&&!e.page_choice.checked&&e.page_field.hide(),b(d.querySelectorAll("#rsa_handle_fields input")).on("change",function(){e.redirect_choice.checked?e.redirect_fields.show():e.redirect_fields.hide(),e.message_choice.checked?e.message_field.show():e.message_field.hide(),e.page_choice.checked?e.page_field.show():e.page_field.hide()}),b(d.querySelectorAll(".option-site-visibility input")).on("change",function(){e.restrict_radio.checked?e.table.show():e.table.hide()}),e.add_btn.on("click",function(){c(e.new_ip.value)});var a=d.getElementById("rsa_myip");null!==a&&b(a).on("click",function(){c(b(this).data("myip"))}),b(e.ip_list_wrap).on("click",".remove_btn",function(){b(this.parentNode).slideUp(250,function(){b(this).remove()})})}()}(window,jQuery);
1
+ !function(a,b){"use strict";function c(a,c){if(""==b.trim(a))return!1;e.add_btn.attr("disabled","disabled");var f=b(d.querySelectorAll("#ip_list input")),g=0;for(f.length;g<f.length;g++)if(f[g].value==a)return b(f[g]).parent().effect("shake",600),e.add_btn.removeAttr("disabled"),!1;jQuery.post(ajaxurl,{action:"rsa_ip_check",ip_address:a,ip_address_comment:c,nonce:rsaAdmin.nonce},function(d){if(d)return b(e.new_ip.parentNode).effect("shake",600),e.add_btn.removeAttr("disabled"),!1;var f=e.empty_ip.clone().appendTo(e.ip_list_wrap);return f.children("input.ip").val(a),f.children("input.comment").val(c),f.removeAttr("id").slideDown(250),a==e.new_ip.value&&(b(e.new_ip).val(""),b(e.new_ip_comment).val("")),e.add_btn.removeAttr("disabled"),!0})}var d=a.document,e={add_btn:"",new_ip:"",ip_list_wrap:"",empty_ip:"",restrict_radio:"",table:"",redirect_choice:"",message_choice:"",page_choice:"",redirect_fields:"",message_field:"",page_field:""};!function(){e.add_btn=b(d.getElementById("addip")),e.new_ip=d.getElementById("newip"),e.new_ip_comment=d.getElementById("newipcomment"),e.ip_list_wrap=d.getElementById("ip_list"),e.empty_ip=b(d.getElementById("ip_list_empty")),e.restrict_radio=d.getElementById("blog-restricted"),e.table=b(d.getElementById("rsa-send-to-login")).closest("table"),e.redirect_choice=d.getElementById("rsa-redirect-visitor"),e.message_choice=d.getElementById("rsa-display-message"),e.page_choice=d.getElementById("rsa-unblocked-page"),e.redirect_fields=b(d.querySelectorAll(".rsa_redirect_field")).closest("tr"),e.message_field=b(d.getElementById("rsa_message")).closest("tr"),e.page_field=b(d.getElementById("rsa_page")).closest("tr"),e.restrict_radio&&!e.restrict_radio.checked&&e.table.hide(),e.redirect_choice&&!e.redirect_choice.checked&&e.redirect_fields.hide(),e.message_choice&&!e.message_choice.checked&&e.message_field.hide(),e.page_choice&&!e.page_choice.checked&&e.page_field.hide(),b(d.querySelectorAll("#rsa_handle_fields input")).on("change",function(){e.redirect_choice.checked?e.redirect_fields.show():e.redirect_fields.hide(),e.message_choice.checked?e.message_field.show():e.message_field.hide(),e.page_choice.checked?e.page_field.show():e.page_field.hide()}),b(d.querySelectorAll(".option-site-visibility input")).on("change",function(){e.restrict_radio.checked?e.table.show():e.table.hide()}),e.add_btn.on("click",function(){c(e.new_ip.value,e.new_ip_comment.value)});var a=d.getElementById("rsa_myip");null!==a&&b(a).on("click",function(){b(e.new_ip).val(b(this).data("myip"))}),b(e.ip_list_wrap).on("click",".remove_btn",function(){b(this.parentNode).slideUp(250,function(){b(this).remove()})})}()}(window,jQuery);
assets/js/src/settings.js CHANGED
@@ -29,6 +29,7 @@
29
 
30
  Cache.add_btn = $( document.getElementById( 'addip' ) );
31
  Cache.new_ip = document.getElementById( 'newip' );
 
32
  Cache.ip_list_wrap = document.getElementById( 'ip_list' );
33
  Cache.empty_ip = $( document.getElementById( 'ip_list_empty' ) );
34
  Cache.restrict_radio = document.getElementById( 'blog-restricted' );
@@ -87,13 +88,13 @@
87
  });
88
 
89
  Cache.add_btn.on('click',function(){
90
- add_ip( Cache.new_ip.value );
91
  });
92
 
93
  var myip_btn = document.getElementById( 'rsa_myip' );
94
  if ( null !== myip_btn ) {
95
  $( myip_btn ).on('click',function(){
96
- add_ip( $( this ).data( 'myip' ) );
97
  });
98
  }
99
 
@@ -103,7 +104,7 @@
103
 
104
  }
105
 
106
- function add_ip( ip ) {
107
  if ( $.trim( ip ) == '' ) {
108
  return false;
109
  }
@@ -121,18 +122,25 @@
121
  }
122
  }
123
 
124
- jQuery.post( ajaxurl, { action: 'rsa_ip_check', 'ip_address': ip }, function(response) {
 
 
 
 
 
125
  if ( response ) {
126
  $( Cache.new_ip.parentNode ).effect( 'shake', shake_speed );
127
  Cache.add_btn.removeAttr( 'disabled' );
128
  return false;
129
  } else {
130
  var new_ip = Cache.empty_ip.clone().appendTo( Cache.ip_list_wrap );
131
- new_ip.children( 'input' ).val( ip );
 
132
  new_ip.removeAttr( 'id' ).slideDown( 250 );
133
 
134
  if ( ip == Cache.new_ip.value ) {
135
  $( Cache.new_ip ).val( '' );
 
136
  }
137
  Cache.add_btn.removeAttr( 'disabled' );
138
 
29
 
30
  Cache.add_btn = $( document.getElementById( 'addip' ) );
31
  Cache.new_ip = document.getElementById( 'newip' );
32
+ Cache.new_ip_comment = document.getElementById( 'newipcomment' );
33
  Cache.ip_list_wrap = document.getElementById( 'ip_list' );
34
  Cache.empty_ip = $( document.getElementById( 'ip_list_empty' ) );
35
  Cache.restrict_radio = document.getElementById( 'blog-restricted' );
88
  });
89
 
90
  Cache.add_btn.on('click',function(){
91
+ add_ip( Cache.new_ip.value, Cache.new_ip_comment.value );
92
  });
93
 
94
  var myip_btn = document.getElementById( 'rsa_myip' );
95
  if ( null !== myip_btn ) {
96
  $( myip_btn ).on('click',function(){
97
+ $( Cache.new_ip ).val( $( this ).data( 'myip' ) );
98
  });
99
  }
100
 
104
 
105
  }
106
 
107
+ function add_ip( ip, comment ) {
108
  if ( $.trim( ip ) == '' ) {
109
  return false;
110
  }
122
  }
123
  }
124
 
125
+ jQuery.post( ajaxurl, {
126
+ action: 'rsa_ip_check',
127
+ 'ip_address': ip,
128
+ 'ip_address_comment': comment,
129
+ nonce: rsaAdmin.nonce
130
+ }, function(response) {
131
  if ( response ) {
132
  $( Cache.new_ip.parentNode ).effect( 'shake', shake_speed );
133
  Cache.add_btn.removeAttr( 'disabled' );
134
  return false;
135
  } else {
136
  var new_ip = Cache.empty_ip.clone().appendTo( Cache.ip_list_wrap );
137
+ new_ip.children( 'input.ip' ).val( ip );
138
+ new_ip.children( 'input.comment' ).val( comment );
139
  new_ip.removeAttr( 'id' ).slideDown( 250 );
140
 
141
  if ( ip == Cache.new_ip.value ) {
142
  $( Cache.new_ip ).val( '' );
143
+ $( Cache.new_ip_comment ).val( '' );
144
  }
145
  Cache.add_btn.removeAttr( 'disabled' );
146
 
readme.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: jakemgold, rcbth, 10up, thinkoomph, tlovett1
3
  Donate link: http://10up.com/plugins/restricted-site-access-wordpress/
4
  Tags: privacy, restricted, restrict, privacy, limited, permissions, security, block
5
  Requires at least: 4.6
6
- Tested up to: 4.9.8
7
- Stable tag: trunk
8
 
9
  Limit access to visitors who are logged in or allowed by IP addresses. Includes many options for handling blocked visitors.
10
 
@@ -108,6 +108,21 @@ define( 'RSA_IP_WHITELIST', '192.0.0.1|192.0.0.10' );
108
 
109
  == Changelog ==
110
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  = 7.0.1 =
112
  * Bug fix: Avoid redirect loop when the unrestricted page is set to be the static front page.
113
  * Bug fix: Fall back to the login screen if the unrestricted page is no longer published.
3
  Donate link: http://10up.com/plugins/restricted-site-access-wordpress/
4
  Tags: privacy, restricted, restrict, privacy, limited, permissions, security, block
5
  Requires at least: 4.6
6
+ Tested up to: 5.2
7
+ Stable tag: 7.1.0
8
 
9
  Limit access to visitors who are logged in or allowed by IP addresses. Includes many options for handling blocked visitors.
10
 
108
 
109
  == Changelog ==
110
 
111
+ = 7.1.0 =
112
+ **Added**
113
+ * IP whitelist: Add a Comment field next to each IP address to help identify IP addresses added to the whitelist.
114
+ * Add constants to force enable/disable restrictions. Set `RSA_FORCE_RESTRICTION` to `true` to force restriction or `RSA_FORBID_RESTRICTION` to disable restriction. `RSA_FORCE_RESTRICTION` will override `RSA_FORBID_RESTRICTION` if both are set.
115
+
116
+ **Fixed**
117
+ * Disable individual site settings when network enforced mode is on to avoid confusion about why your settings are not being respected.
118
+ * Correctly load admin JS.
119
+ * Improve coding standards across plugin and introduce continuous integration linting against the WordPress coding standards. Update code to VIP Go coding standards.
120
+
121
+ **Developers**
122
+ * Add unit tests accross plugin. Note that when the `WP_TESTS_DOMAIN` constant is set, plugin redirects are disabled. Only set this constant when running the tests.
123
+ * Deploy plugin from GitHub to WordPress.org using GitHub Actions.
124
+ * Add various GitHub community files.
125
+
126
  = 7.0.1 =
127
  * Bug fix: Avoid redirect loop when the unrestricted page is set to be the static front page.
128
  * Bug fix: Fall back to the login screen if the unrestricted page is no longer published.
restricted_site_access.php CHANGED
@@ -1,36 +1,63 @@
1
- <?php
2
  /**
3
  * Plugin Name: Restricted Site Access
4
  * Plugin URI: http://10up.com/plugins/restricted-site-access-wordpress/
5
  * 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: 7.0.1
7
  * Author: Jake Goldman, 10up, Oomph
8
  * Author URI: http://10up.com
9
  * License: GPLv2 or later
10
  * Text Domain: restricted-site-access
11
  */
12
 
13
- define( 'RSA_VERSION', '7.0.1' );
14
 
 
 
 
15
  class Restricted_Site_Access {
16
 
17
- private static $basename, $rsa_options;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
  private static $settings_page = 'reading';
19
 
 
 
 
 
 
20
  private static $fields;
21
 
22
  /**
23
  * Handles initializing this class and returning the singleton instance after it's been cached.
24
  *
25
- * @return null|Simple_page_Ordering
 
26
  */
27
  public static function get_instance() {
28
- // Store the instance locally to avoid private static replication
29
  static $instance = null;
30
 
31
  if ( null === $instance ) {
32
  $instance = new self();
33
- self::_add_actions();
34
  self::populate_fields_array();
35
  }
36
 
@@ -39,6 +66,8 @@ class Restricted_Site_Access {
39
 
40
  /**
41
  * An empty constructor
 
 
42
  */
43
  public function __construct() {
44
  /* Purposely do nothing here */ }
@@ -46,7 +75,7 @@ class Restricted_Site_Access {
46
  /**
47
  * Handles registering hooks that initialize this plugin.
48
  */
49
- public static function _add_actions() {
50
  self::$basename = plugin_basename( __FILE__ );
51
 
52
  add_action( 'parse_request', array( __CLASS__, 'restrict_access' ), 1 );
@@ -58,37 +87,58 @@ class Restricted_Site_Access {
58
  add_action( 'wpmu_new_blog', array( __CLASS__, 'set_defaults' ), 10, 6 );
59
  add_action( 'admin_enqueue_scripts', array( __CLASS__, 'enqueue_admin_script' ) );
60
  add_action( 'wp_ajax_rsa_notice_dismiss', array( __CLASS__, 'ajax_notice_dismiss' ) );
 
 
 
61
  }
62
 
 
 
 
63
  public static function ajax_notice_dismiss() {
64
- if ( ! check_ajax_referer( 'rsa_admin_nonce', 'nonce', false ) ) {
65
- wp_send_json_error();
66
- exit;
67
- }
68
 
69
- if ( RSA_IS_NETWORK ) {
70
- if ( ! is_super_admin() ) {
 
71
  wp_send_json_error();
72
  exit;
73
  }
74
- } else {
75
- if ( ! current_user_can( 'manage_options' ) ) {
76
- wp_send_json_error();
77
- exit;
 
 
 
 
 
 
 
78
  }
79
  }
80
-
81
  if ( RSA_IS_NETWORK ) {
82
  update_site_option( 'rsa_hide_page_cache_notice', true );
83
  } else {
84
  update_option( 'rsa_hide_page_cache_notice', true );
85
  }
86
 
87
- wp_send_json_success();
 
 
 
 
88
  }
89
 
90
  /**
91
- * Set RSA defaults for new site
 
 
 
 
 
 
 
92
  */
93
  public static function set_defaults( $blog_id, $user_id, $domain, $path, $site_id, $meta ) {
94
  if ( 'enforce' === self::get_network_mode() ) {
@@ -96,7 +146,7 @@ class Restricted_Site_Access {
96
  }
97
 
98
  $network_options = self::get_options( true );
99
- $blog_public = get_site_option( 'blog_public', 2 );
100
 
101
  switch_to_blog( $blog_id );
102
  update_option( 'rsa_options', self::sanitize_options( $network_options ) );
@@ -106,44 +156,46 @@ class Restricted_Site_Access {
106
 
107
  /**
108
  * Populate Restricted_Site_Access::$fields with internationalization-ready field information.
 
 
109
  */
110
  protected static function populate_fields_array() {
111
  self::$fields = array(
112
- 'approach' => array(
113
- 'default' => 1,
114
- 'label' => __( 'Handle restricted visitors', 'restricted-site-access' ),
115
- 'field' => 'settings_field_handling',
116
- ),
117
- 'message' => array(
118
- 'default' => _x( 'Access to this site is restricted.', 'default restriction message', 'restricted-site-access' ),
119
- 'label' => __( 'Restriction message', 'restricted-site-access' ),
120
- 'field' => 'settings_field_message',
121
- ),
122
- 'redirect_url' => array(
123
- 'default' => '',
124
- 'label' => __( 'Redirect web address', 'restricted-site-access' ),
125
- 'field' => 'settings_field_redirect',
126
- ),
127
- 'redirect_path' => array(
128
- 'default' => 0,
129
- 'label' => 'Redirect to same path',
130
- 'field' => 'settings_field_redirect_path',
131
- ),
132
- 'head_code' => array(
133
- 'default' => 302,
134
- 'label' => __( 'Redirection status code', 'restricted-site-access' ),
135
- 'field' => 'settings_field_redirect_code',
136
- ),
137
- 'page' => array(
138
- 'default' => 0,
139
- 'label' => __( 'Restricted notice page', 'restricted-site-access' ),
140
- 'field' => 'settings_field_rsa_page',
141
- ),
142
- 'allowed' => array(
143
- 'default' => array(),
144
- 'label' => __( 'Unrestricted IP addresses', 'restricted-site-access' ),
145
- 'field' => 'settings_field_allowed',
146
- ),
147
  );
148
  }
149
 
@@ -151,7 +203,7 @@ class Restricted_Site_Access {
151
  * Get current plugin network mode
152
  */
153
  private static function get_network_mode() {
154
- if ( RSA_IS_NETWORK ){
155
  return get_site_option( 'rsa_mode', 'default' );
156
  }
157
 
@@ -159,7 +211,9 @@ class Restricted_Site_Access {
159
  }
160
 
161
  /**
162
- * populate the option with defaults
 
 
163
  */
164
  public static function get_options( $network = false ) {
165
  $options = array();
@@ -170,8 +224,8 @@ class Restricted_Site_Access {
170
  $options = get_option( 'rsa_options' );
171
  }
172
 
173
- // Fill in defaults where values aren't set
174
- foreach( self::$fields as $field_name => $field_details ) {
175
  if ( ! isset( $options[ $field_name ] ) ) {
176
  $options[ $field_name ] = $field_details['default'];
177
  }
@@ -194,14 +248,9 @@ class Restricted_Site_Access {
194
 
195
  $blog_public = get_option( 'blog_public', 2 );
196
 
197
- //If rsa_mode==enforce we override the rsa_options
198
- if ( RSA_IS_NETWORK && 'enforce' === $mode ) {
199
- $blog_public = get_site_option( 'blog_public', 2 );
200
- }
201
-
202
  $user_check = self::user_can_access();
203
 
204
- $checks = is_admin() || $user_check || 2 !== (int) $blog_public || ( defined( 'WP_INSTALLING' ) && isset( $_GET['key'] ) );
205
 
206
  return ! $checks;
207
  }
@@ -247,15 +296,41 @@ class Restricted_Site_Access {
247
  }
248
 
249
  /**
250
- * Determine whether page should be restricted at point of request
251
  *
252
- * @param array $wp WordPress request
 
253
  */
254
  public static function restrict_access( $wp ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
255
  self::$rsa_options = self::get_options();
256
  $is_restricted = self::is_restricted();
257
 
258
- // Check to see if it's _not_ restricted
259
  if ( apply_filters( 'restricted_site_access_is_restricted', $is_restricted, $wp ) === false ) {
260
  return;
261
  }
@@ -268,12 +343,12 @@ class Restricted_Site_Access {
268
  $allowed_ips = array_merge( $allowed_ips, self::$rsa_options['allowed'] );
269
  }
270
 
271
- // check for the allow list, if its empty block everything
272
  if ( count( $allowed_ips ) > 0 ) {
273
  $remote_ip = self::get_client_ip_address();
274
 
275
- // iterate through the allow list
276
- foreach( $allowed_ips as $line ) {
277
  if ( self::ip_in_range( $remote_ip, $line ) ) {
278
 
279
  /**
@@ -295,97 +370,123 @@ class Restricted_Site_Access {
295
  }
296
 
297
  $rsa_restrict_approach = apply_filters( 'restricted_site_access_approach', self::$rsa_options['approach'] );
298
- do_action( 'restrict_site_access_handling', $rsa_restrict_approach, $wp ); // allow users to hook handling
299
 
300
  switch ( $rsa_restrict_approach ) {
301
- case 4:
302
  if ( ! empty( self::$rsa_options['page'] ) ) {
303
  $page = get_post( self::$rsa_options['page'] );
304
 
305
  // If the selected page isn't found or isn't published, fall back to default values.
306
  if ( ! $page || 'publish' !== $page->post_status ) {
307
- self::$rsa_options['head_code'] = 302;
308
- $current_path = empty( $_SERVER['REQUEST_URI'] ) ? home_url() : $_SERVER['REQUEST_URI'];
309
  self::$rsa_options['redirect_url'] = wp_login_url( $current_path );
310
  break;
311
  }
312
 
313
  // Are we already on the selected page?
314
- // There's a separate unpleasant conditional to match the page on front because of the way query vars are (not) filled at this point
315
- if (
316
- ( isset( $wp->query_vars['pagename'] ) && $wp->query_vars['pagename'] === $page->post_name )
317
- ||
318
- ( empty ( $wp->query_vars ) && 'page' === get_option( 'show_on_front' ) && (int) self::$rsa_options['page'] === (int) get_option( 'page_on_front' ) )
319
- ) {
 
 
 
 
 
 
 
 
 
 
 
 
320
  return;
321
  }
322
 
323
  self::$rsa_options['redirect_url'] = get_permalink( $page->ID );
324
  break;
325
  }
326
-
327
  case 3:
328
- $message = __( self::$rsa_options['message'], 'restricted-site-access' );
329
  $message .= "\n<!-- protected by Restricted Site Access http://10up.com/plugins/restricted-site-access-wordpress/ -->";
330
- $message = apply_filters( 'restricted_site_access_message', $message, $wp );
331
- wp_die( $message, get_bloginfo( 'name' ) . ' - Site Access Restricted', array( 'response' => 403 ) );
 
 
 
 
 
332
 
333
  case 2:
334
  if ( ! empty( self::$rsa_options['redirect_url'] ) ) {
335
  if ( ! empty( self::$rsa_options['redirect_path'] ) ) {
336
- self::$rsa_options['redirect_url'] = untrailingslashit( self::$rsa_options['redirect_url'] ) . $_SERVER['REQUEST_URI'];
337
  }
338
  break;
339
  }
340
-
341
  default:
342
- self::$rsa_options['head_code'] = 302;
343
- $current_path = empty( $_SERVER['REQUEST_URI'] ) ? home_url() : $_SERVER['REQUEST_URI'];
344
  self::$rsa_options['redirect_url'] = wp_login_url( $current_path );
345
  }
346
 
347
- $redirect_url = apply_filters( 'restricted_site_access_redirect_url', self::$rsa_options['redirect_url'], $wp );
348
  $redirect_code = apply_filters( 'restricted_site_access_head', self::$rsa_options['head_code'], $wp );
349
 
350
- wp_redirect( $redirect_url, $redirect_code );
351
- die;
 
 
352
  }
353
 
354
  /**
355
  * Admin only hooks
356
  */
357
  public static function admin_init() {
358
- // customize privacy message
359
  add_filter( 'privacy_on_link_text', array( __CLASS__, 'privacy_on_link_text' ) );
360
  add_filter( 'privacy_on_link_title', array( __CLASS__, 'privacy_on_link_title' ) );
361
 
362
- // customize privacy page
363
  add_action( 'load-options-' . self::$settings_page . '.php', array( __CLASS__, 'load_options_page' ) );
364
 
365
- // add new choice for blog privacy
366
  add_action( 'blog_privacy_selector', array( __CLASS__, 'blog_privacy_selector' ) );
367
 
368
- // settings for restricted site access
369
- register_setting( self::$settings_page, 'rsa_options', array( __CLASS__, 'sanitize_options' ) ); // array of fundamental options including ID and caching info
370
  add_settings_section( 'restricted-site-access', '', '__return_empty_string', self::$settings_page );
371
- foreach ( self::$fields as $field_name => $field_data ) {
372
- add_settings_field(
373
- $field_name,
374
- $field_data['label'],
375
- array( __CLASS__, $field_data['field'] ),
376
- self::$settings_page,
377
- 'restricted-site-access',
378
- array( 'class' => 'rsa-setting rsa-setting_' . esc_attr( $field_data['field'] ) )
379
- );
 
 
 
 
 
 
 
 
380
  }
381
 
382
  add_filter( 'plugin_action_links_' . self::$basename, array( __CLASS__, 'plugin_action_links' ) );
383
 
384
- //This is for Network Site Settings
385
- if ( RSA_IS_NETWORK && is_network_admin() ) {
386
  add_action( 'load-settings.php', array( __CLASS__, 'load_network_settings_page' ) );
387
  add_action( 'network_admin_notices', array( __CLASS__, 'page_cache_notice' ) );
388
-
389
  }
390
 
391
  add_action( 'admin_notices', array( __CLASS__, 'page_cache_notice' ) );
@@ -397,20 +498,20 @@ class Restricted_Site_Access {
397
  public static function show_network_settings() {
398
  $mode = self::get_network_mode();
399
  ?>
400
- <h2><?php _e( 'Restricted Site Access Settings', 'restricted-site-access' ); ?></h2>
401
- <table id="restricted-site-access-mode" class="option-site-visibility form-table">
402
  <tr>
403
- <th scope="row"><?php _e( 'Mode', 'restricted-site-access' ) ?></th>
404
  <td>
405
  <fieldset>
406
- <legend class="screen-reader-text"><?php _e( 'Mode', 'restricted-site-access' ) ?></legend>
407
- <label><input name="rsa_mode" type="radio" id="rsa-mode-default" value="default"<?php checked( $mode, 'default') ?> /> <?php _e( '<strong>Default</strong> to the settings below when creating a new site', 'restricted-site-access' ); ?></label><br />
408
- <label><input name="rsa_mode" type="radio" id="rsa-mode-enforce" value="enforce"<?php checked( $mode, 'enforce') ?> /> <?php _e( '<strong>Enforce</strong> the settings below across all sites', 'restricted-site-access' ); ?></label><br />
409
  </fieldset>
410
  </td>
411
  </tr>
412
- <tr>
413
- <th scope="row"><?php _e( 'Site Visibility', 'restricted-site-access' ) ?></th>
414
  <?php
415
  $blog_public = get_site_option( 'blog_public' );
416
 
@@ -420,23 +521,32 @@ class Restricted_Site_Access {
420
  ?>
421
  <td>
422
  <fieldset>
423
- <legend class="screen-reader-text"><span><?php _e( 'Site Visibility', 'restricted-site-access' ) ?></span></legend>
424
- <input id="blog-public" type="radio" name="blog_public" value="1" <?php checked( $blog_public, '1') ?>>
425
- <label for="blog-public"><?php _e( 'Allow search engines to index this site', 'restricted-site-access' ) ?></label><br>
426
- <input id="blog-norobots" type="radio" name="blog_public" value="0" <?php checked( $blog_public, '0') ?>>
427
- <label for="blog-norobots"><?php _e( 'Discourage search engines from indexing this site', 'restricted-site-access' ) ?></label>
428
- <p class="description"><?php _e( 'Note: Neither of these options blocks access to your site — it is up to search engines to honor your request.', 'restricted-site-access' ) ?></p>
429
  <p>
430
- <input id="blog-restricted" type="radio" name="blog_public" value="2" <?php checked( $blog_public, '2') ?>>
431
- <label for="blog-restricted"><?php _e( 'Restrict site access to visitors who are logged in or allowed by IP address', 'restricted-site-access' ) ?></label>
432
  </p>
433
  </fieldset>
434
  </td>
435
  </tr>
436
  </table>
 
 
 
 
 
 
 
 
 
437
  <table id="restricted-site-access" class="form-table">
438
  <tr>
439
- <th scope="row"><?php _e( 'Handle restricted visitors', 'restricted-site-access' ) ?></th>
440
  <td>
441
  <?php
442
  self::settings_field_handling();
@@ -444,7 +554,7 @@ class Restricted_Site_Access {
444
  </td>
445
  </tr>
446
  <tr>
447
- <th scope="row"><?php _e( 'Redirect web address', 'restricted-site-access' ) ?></th>
448
  <td>
449
  <?php
450
  self::settings_field_redirect();
@@ -452,7 +562,7 @@ class Restricted_Site_Access {
452
  </td>
453
  </tr>
454
  <tr>
455
- <th scope="row"><?php _e( 'Redirect to same path', 'restricted-site-access' ) ?></th>
456
  <td>
457
  <?php
458
  self::settings_field_redirect_path();
@@ -460,7 +570,7 @@ class Restricted_Site_Access {
460
  </td>
461
  </tr>
462
  <tr>
463
- <th scope="row"><?php _e( 'Redirection status code', 'restricted-site-access' ) ?></th>
464
  <td>
465
  <?php
466
  self::settings_field_redirect_code();
@@ -468,7 +578,7 @@ class Restricted_Site_Access {
468
  </td>
469
  </tr>
470
  <tr>
471
- <th scope="row"><?php _e( 'Restriction message', 'restricted-site-access' ) ?></th>
472
  <td>
473
  <?php
474
  self::settings_field_message();
@@ -476,7 +586,7 @@ class Restricted_Site_Access {
476
  </td>
477
  </tr>
478
  <tr>
479
- <th scope="row"><?php _e( 'Unrestricted IP addresses', 'restricted-site-access' ) ?></th>
480
  <td>
481
  <?php
482
  self::settings_field_allowed();
@@ -489,21 +599,23 @@ class Restricted_Site_Access {
489
  }
490
 
491
  /**
492
- * Handle Save Options for RSA Settings in Network Settings
493
  */
494
  public static function save_network_settings() {
495
  $options = array(
496
- 'rsa_mode', 'blog_public', 'rsa_options'
 
 
497
  );
498
 
499
  foreach ( $options as $option_name ) {
500
- if ( ! isset( $_POST[ $option_name ] ) ){
501
  continue;
502
  }
503
 
504
- switch ( $option_name ){
505
  case 'rsa_options':
506
- $value = self::sanitize_options( $_POST[ $option_name ] );
507
  break;
508
  case 'blog_public':
509
  $value = absint( $_POST[ $option_name ] );
@@ -518,53 +630,73 @@ class Restricted_Site_Access {
518
  }
519
 
520
  /**
521
- * Overrides text in the dashboard Right Now widget
522
  *
523
- * @param string $text
524
  *
525
  * @return string New text to show in widget
526
  */
527
  public static function privacy_on_link_text( $text ) {
528
- if ( 2 == get_option( 'blog_public' ) ) {
529
- $text = __( 'Public access to this site has been restricted.', 'restricted-site-access' );
530
  }
531
  return $text;
532
  }
533
 
534
  /**
535
- * Title attribute for link about site status on Right Now widget
536
  *
537
- * @param string $text
538
  *
539
  * @return string New title attribute
540
  */
541
  public static function privacy_on_link_title( $text ) {
542
- if ( 2 == get_option( 'blog_public' ) ) {
543
- $text = __( 'Restricted Site Access plug-in is blocking public access to this site.', 'restricted-site-access' );
544
  }
545
  return $text;
546
  }
547
 
 
 
 
548
  public static function enqueue_settings_script() {
549
- $js_path = plugin_dir_url( __FILE__ ) . 'assets/js/settings.min.js';
550
-
551
- if ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) {
552
- $js_path = plugin_dir_url( __FILE__ ) . 'assets/js/src/settings.js';
553
- }
554
-
555
- wp_enqueue_script( 'rsa-settings', $js_path, array( 'jquery-effects-shake' ), RSA_VERSION, true );
 
 
 
556
  }
557
 
 
 
 
558
  public static function enqueue_admin_script() {
559
- if ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) {
560
- wp_enqueue_script( 'rsa-admin', plugin_dir_url( __FILE__ ) . 'assets/js/src/admin.js', array( 'jquery' ), RSA_VERSION, true );
561
- } else {
562
- wp_enqueue_script( 'rsa-admin', plugin_dir_url( __FILE__ ) . 'assets/js/admin.min.js', array( 'jquery' ), RSA_VERSION, true );
563
- }
564
 
565
- wp_localize_script( 'rsa-admin', 'rsaAdmin', array(
566
- 'nonce' => wp_create_nonce( 'rsa_admin_nonce' ),
567
- ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
568
  }
569
 
570
  /**
@@ -575,6 +707,7 @@ class Restricted_Site_Access {
575
 
576
  add_action( 'admin_notices', array( __CLASS__, 'admin_notice' ) );
577
  add_action( 'admin_head', array( __CLASS__, 'admin_head' ) );
 
578
 
579
  add_filter( 'wp_dropdown_pages', array( __CLASS__, 'filter_page_dropdown' ), 10, 2 );
580
 
@@ -584,11 +717,13 @@ class Restricted_Site_Access {
584
  /**
585
  * Load needed scripts and assets on Network Settings page
586
  */
587
- public static function load_network_settings_page(){
588
  self::enqueue_settings_script();
589
 
590
  self::$rsa_options = self::get_options( true );
591
 
 
 
592
  add_action( 'wpmu_options', array( __CLASS__, 'show_network_settings' ) );
593
  add_action( 'update_wpmu_options', array( __CLASS__, 'save_network_settings' ) );
594
  }
@@ -597,24 +732,18 @@ class Restricted_Site_Access {
597
  * Customize admin notices to ensure user completes restriction setup properly
598
  */
599
  public static function admin_notice() {
600
- if( RSA_IS_NETWORK && 'enforce' === self::get_network_mode() ){
601
- $rsa_mode_message = __( 'Network visibility settings are currently enforced across all blogs on the network.', 'restricted-site-access' );
602
- echo '<div class="notice notice-warning"><p><strong>' . $rsa_mode_message . '</strong></p></div>';
603
- return;
604
- }
605
-
606
  if ( empty( self::$rsa_options['approach'] ) ) {
607
  return;
608
  }
609
 
610
- if ( 4 == self::$rsa_options['approach'] && empty( self::$rsa_options['page'] ) ) {
611
- $message = __( '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' );
612
- } elseif ( 2 == self::$rsa_options['approach'] && empty( self::$rsa_options['redirect_url'] ) ) {
613
- $message = __( 'Please enter the web address you would like to redirect restricted visitors to. If no address is entered, visitors will be redirected to the login screen.', 'restricted-site-access' );
614
  }
615
 
616
  if ( isset( $message ) ) {
617
- echo '<div class="notice notice-error"><p><strong>' . $message . '</strong></p></div>';
618
  }
619
  }
620
 
@@ -622,8 +751,10 @@ class Restricted_Site_Access {
622
  * Check if the page caching is on, and notify the admin
623
  */
624
  public static function page_cache_notice() {
625
- //If WP_CACHE is on we show notification
626
- if ( defined( 'WP_CACHE' ) && true === WP_CACHE ) {
 
 
627
 
628
  if ( RSA_IS_NETWORK ) {
629
  if ( get_site_option( 'rsa_hide_page_cache_notice' ) ) {
@@ -649,7 +780,7 @@ class Restricted_Site_Access {
649
  ?>
650
  <div data-rsa-notice="page-cache" class="notice notice-error is-dismissible">
651
  <p>
652
- <strong><?php _e( 'Page caching appears to be enabled. Restricted Site Access may not work as expected. <a href="https://wordpress.org/plugins/restricted-site-access/#faq">Learn more</a>.', 'restricted-site-access' ); ?></strong>
653
  </p>
654
  </div>
655
  <?php
@@ -657,7 +788,7 @@ class Restricted_Site_Access {
657
  }
658
 
659
  /**
660
- * Add restricted access help tab to screen
661
  */
662
  public static function admin_head() {
663
  $screen = get_current_screen();
@@ -675,8 +806,8 @@ class Restricted_Site_Access {
675
  _x( 'Allowed IP addresses', 'help topic', 'restricted-site-access' ),
676
  __( '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!', 'restricted-site-access' ),
677
  sprintf(
 
678
  '<a href="http://www.csgnetwork.com/ipinfocalc.html">%s</a>',
679
- /** translators: link to http://www.csgnetwork.com/ipinfocalc.html */
680
  __( 'Here is a handy calculator to check your prefix.', 'restricted-site-access' )
681
  ),
682
  __( 'The redirection fields are only used when "Handle restricted visitors" is set to "Redirect them to a specified web address".', 'restricted-site-access' )
@@ -700,32 +831,97 @@ class Restricted_Site_Access {
700
  __( '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' )
701
  );
702
 
703
- $screen->add_help_tab( array(
704
- 'id' => 'restricted-site-access',
705
- 'title' => _x( 'Restricted Site Acccess', 'help screen title', 'restricted-site-access' ),
706
- 'content' => implode( PHP_EOL, $content ),
707
- ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
708
  }
709
 
710
  /**
711
- * Add a new choice to the privacy selector
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
712
  */
713
  public static function blog_privacy_selector() {
714
  global $wp;
715
- $is_restricted = ( 2 == get_option( 'blog_public' ) );
716
  $is_restricted = apply_filters( 'restricted_site_access_is_restricted', $is_restricted, $wp );
717
- ?>
718
  <p>
719
  <input id="blog-restricted" type="radio" name="blog_public" value="2" <?php checked( $is_restricted ); ?> />
720
  <label for="blog-restricted"><?php esc_html_e( 'Restrict site access to visitors who are logged in or allowed by IP address', 'restricted-site-access' ); ?></label>
721
  </p>
722
- <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
723
  }
724
 
725
  /**
726
- * Sanitize RSA options
727
  *
728
- * @param array $input
729
  *
730
  * @return array Sanitized input
731
  */
@@ -739,9 +935,9 @@ class Restricted_Site_Access {
739
  $new_input['message'] = wp_kses( $input['message'], $allowedtags );
740
 
741
  $new_input['redirect_path'] = empty( $input['redirect_path'] ) ? 0 : 1;
742
- $new_input['head_code'] = in_array( (int) $input['head_code'], array( 301, 302, 307 ) ) ? (int) $input['head_code'] : self::$fields['head_code']['default'];
743
- $new_input['redirect_url'] = empty( $input['redirect_url'] ) ? '' : esc_url_raw( $input['redirect_url'], array( 'http', 'https' ) );
744
- $new_input['page'] = empty( $input['page'] ) ? 0 : (int) $input['page'];
745
 
746
  $new_input['allowed'] = array();
747
  if ( ! empty( $input['allowed'] ) && is_array( $input['allowed'] ) ) {
@@ -751,23 +947,31 @@ class Restricted_Site_Access {
751
  }
752
  }
753
  }
 
 
 
 
 
 
 
 
754
 
755
  return $new_input;
756
  }
757
 
758
  /**
759
- * Fieldset for choosing restriction handling
760
- *
761
- * @param $args
762
  */
763
- public static function settings_field_handling( $args = array() ) {
764
  if ( ! isset( self::$rsa_options['approach'] ) ) {
 
765
  self::$rsa_options['approach'] = 1;
 
766
  }
767
- ?>
768
  <fieldset id="rsa_handle_fields">
769
  <input id="rsa-send-to-login" name="rsa_options[approach]" type="radio" value="1" <?php checked( self::$rsa_options['approach'], 1 ); ?> />
770
- <label for="rsa-send-to-login"><?php esc_html_e( 'Send them to the WordPress login screen','restricted-site-access' ); ?></label>
771
  <br />
772
  <input id="rsa-redirect-visitor" name="rsa_options[approach]" type="radio" value="2" <?php checked( self::$rsa_options['approach'], 2 ); ?> />
773
  <label for="rsa-redirect-visitor"><?php esc_html_e( 'Redirect them to a specified web address', 'restricted-site-access' ); ?></label>
@@ -781,136 +985,146 @@ class Restricted_Site_Access {
781
  <label for="rsa-unblocked-page"><?php esc_html_e( 'Show them a page', 'restricted-site-access' ); ?></label>
782
  <?php endif; ?>
783
  </fieldset>
784
- <?php
785
  }
786
 
787
  /**
788
- * Fieldset for managing allowed IP addresses
789
- *
790
- * @param $args
791
  */
792
- public static function settings_field_allowed( $args = array() ) {
793
- ?>
794
  <div class="hide-if-no-js">
795
  <div id="ip_list">
796
- <div id="ip_list_empty" style="display: none;"><input type="text" name="rsa_options[allowed][]" value="" readonly="true" /> <a href="#remove" class="remove_btn"><?php echo esc_html( _x( 'Remove', 'remove IP address action', 'restricted-site-access' ) ); ?></a></div>
797
  <?php
798
- $ips = (array) self::$rsa_options['allowed'];
799
- foreach ( $ips as $ip ) {
800
- if ( ! empty( $ip ) ) {
801
- echo '<div><input type="text" name="rsa_options[allowed][]" value="' . esc_attr( $ip ) . '" readonly="true" /> <a href="#remove" class="remove_btn">' . esc_html_x( 'Remove', 'remove IP address action', 'restricted-site-access' ) . '</a></div>';
802
- }
803
  }
 
804
  ?>
805
  </div>
806
  <div>
807
- <input type="text" name="newip" id="newip" /> <input class="button" type="button" id="addip" value="<?php esc_attr_e( 'Add' ); ?>" />
808
- <p class="description" style="display: inline;"><label for="newip"><?php esc_html_e( 'Enter a single IP address or a range using a subnet prefix', 'restricted-site-access' ); ?></label></p>
809
- </div>
810
- <?php if ( ! empty( $_SERVER['REMOTE_ADDR'] ) ) { ?><input class="button" type="button" id="rsa_myip" value="<?php esc_attr_e( 'Add My Current IP Address', 'restricted-site-access' ); ?>" style="margin-top: 5px;" data-myip="<?php echo esc_attr( self::get_client_ip_address() ); ?>" /><br /><?php } ?>
 
 
 
 
 
 
 
 
811
  <div class="config_ips" style="margin-top: 10px;">
812
- <p class="description">
813
- <?php esc_html_e( 'IP addresses set by configuration', 'restricted-site-access' ); ?>
814
- </p>
815
- <?php
816
- $config_ips = self::get_config_ips();
817
  foreach ( $config_ips as $ip ) {
818
- printf(
819
- '<div><input type="text" value="%1$s" disabled="true" /></div>',
820
- esc_attr( $ip )
821
- );
822
  }
823
- ?>
 
824
  </div>
 
825
  </div>
826
  <p class="hide-if-js"><strong><?php esc_html_e( 'To manage IP addresses, you must use a JavaScript enabled browser.', 'restricted-site-access' ); ?></strong></p>
827
- <?php
828
  }
829
 
830
  /**
831
- * Field for custom message
832
- *
833
- * @param $args
834
  */
835
- public static function settings_field_message( $args = array() ) {
836
  if ( empty( self::$rsa_options['message'] ) ) {
837
- self::$rsa_options['message'] = __( 'Access to this site is restricted.', 'restricted-site-access' );
838
  }
839
 
840
- wp_editor( self::$rsa_options['message'], 'rsa_message', array(
841
- 'media_buttons' => false,
842
- 'textarea_name' => 'rsa_options[message]',
843
- 'textarea_rows' => 4,
844
- 'tinymce' => false,
845
- ) );
 
 
 
 
846
  }
847
 
848
  /**
849
- * Field for redirection
850
- *
851
- * @param $args
852
  */
853
- public static function settings_field_redirect( $args = array() ) {
854
  if ( ! isset( self::$rsa_options['redirect_url'] ) ) {
 
855
  self::$rsa_options['redirect_url'] = '';
 
856
  }
857
- ?>
858
  <input type="text" name="rsa_options[redirect_url]" id="redirect" class="rsa_redirect_field regular-text" value="<?php echo esc_attr( self::$rsa_options['redirect_url'] ); ?>" />
859
- <?php
860
  }
861
 
862
  /**
863
- * Field for redirect path option
864
- *
865
- * @param $args
866
  */
867
- public static function settings_field_redirect_path( $args = array() ) {
868
  if ( ! isset( self::$rsa_options['redirect_path'] ) ) {
 
869
  self::$rsa_options['redirect_path'] = 0;
 
870
  }
871
- ?>
872
- <fieldset><legend class="screen-reader-text"><span><?php _e( self::$rsa_options['redirect_path']['label'], 'restricted-site-access' ); ?></span></legend>
873
  <label for="redirect_path">
874
  <input type="checkbox" name="rsa_options[redirect_path]" value="1" id="redirect_path" class="rsa_redirect_field" <?php checked( self::$rsa_options['redirect_path'] ); ?> />
875
  <?php esc_html_e( 'Send restricted visitor to same path (relative URL) at the new web address', 'restricted-site-access' ); ?></label>
876
  </fieldset>
877
- <?php
878
  }
879
 
880
  /**
881
- * Field for specifying redirect code
882
- *
883
- * @param $args
884
  */
885
- public static function settings_field_redirect_code( $args = array() ) {
886
  if ( empty( self::$rsa_options['head_code'] ) ) {
 
887
  self::$rsa_options['head_code'] = 302;
 
888
  }
889
- ?>
890
  <select name="rsa_options[head_code]" id="redirect_code" class="rsa_redirect_field">
891
  <option value="301" <?php selected( self::$rsa_options['head_code'], 301 ); ?>><?php esc_html_e( '301 Permanent', 'restricted-site-access' ); ?></option>
892
  <option value="302" <?php selected( self::$rsa_options['head_code'], 302 ); ?>><?php esc_html_e( '302 Undefined', 'restricted-site-access' ); ?></option>
893
  <option value="307" <?php selected( self::$rsa_options['head_code'], 307 ); ?>><?php esc_html_e( '307 Temporary', 'restricted-site-access' ); ?></option>
894
  </select>
895
- <?php
896
  }
897
 
898
  /**
899
- * Field for choosing a page to redirect to
900
- *
901
- * @param $args
902
  */
903
- public static function settings_field_rsa_page( $args = array() ) {
904
  if ( ! isset( self::$rsa_options['page'] ) ) {
 
905
  self::$rsa_options['page'] = 0;
 
906
  }
907
 
908
- wp_dropdown_pages(array(
909
- 'selected' => self::$rsa_options['page'],
910
- 'show_option_none' => __( 'Select a page', 'restricted-site-access' ),
911
- 'name' => 'rsa_options[page]',
912
- 'id' => 'rsa_page',
913
- ));
 
 
914
  }
915
 
916
  /**
@@ -933,24 +1147,32 @@ class Restricted_Site_Access {
933
  }
934
 
935
  /**
936
- * Validate IP address entry on demand (AJAX)
 
 
937
  */
938
  public static function ajax_rsa_ip_check() {
939
- if ( empty( $_POST['ip_address'] ) || ! self::is_ip( stripslashes( $_POST['ip_address'] ) ) ) {
 
 
 
 
 
 
940
  die( '1' );
941
  }
942
  die;
943
  }
944
 
945
  /**
946
- * is it a valid IP address? v4/v6 with subnet range
947
  *
948
- * @param string $ip_address IP Address to check
949
  *
950
  * @return bool True if its a valid IP address.
951
  */
952
  public static function is_ip( $ip_address ) {
953
- // very basic validation of ranges
954
  if ( strpos( $ip_address, '/' ) ) {
955
  $ip_parts = explode( '/', $ip_address );
956
  if ( empty( $ip_parts[1] ) || ! is_numeric( $ip_parts[1] ) || strlen( $ip_parts[1] ) > 3 ) {
@@ -959,7 +1181,7 @@ class Restricted_Site_Access {
959
  $ip_address = $ip_parts[0];
960
  }
961
 
962
- // confirm IP part is a valid IPv6 or IPv4 IP
963
  if ( empty( $ip_address ) || ! inet_pton( stripslashes( $ip_address ) ) ) {
964
  return false;
965
  }
@@ -994,9 +1216,36 @@ class Restricted_Site_Access {
994
  }
995
 
996
  /**
997
- * Add settings link directing user to privacy page on plug-in page
998
  *
999
- * @param array $links Array of links for plugin actions
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1000
  *
1001
  * @return array
1002
  */
@@ -1004,14 +1253,16 @@ class Restricted_Site_Access {
1004
  $links[] = sprintf(
1005
  '<a href="options-%s.php">%s</a>',
1006
  esc_attr( self::$settings_page ),
1007
- __( 'Settings', 'settings page link', 'restricted-site-access' )
1008
  );
1009
 
1010
  return $links;
1011
  }
1012
 
1013
  /**
1014
- * activation of plugin: upgrades old versions, immediately sets privacy
 
 
1015
  */
1016
  public static function activation( $network_active ) {
1017
  if ( ! $network_active ) {
@@ -1020,7 +1271,9 @@ class Restricted_Site_Access {
1020
  }
1021
 
1022
  /**
1023
- * restore privacy option to default value upon deactivating
 
 
1024
  */
1025
  public static function deactivation( $network_active ) {
1026
  if ( $network_active ) {
@@ -1029,25 +1282,27 @@ class Restricted_Site_Access {
1029
  foreach ( $sites as $site ) {
1030
  switch_to_blog( $site->blog_id );
1031
 
1032
- if ( 2 == get_option( 'blog_public' ) ) {
1033
  update_option( 'blog_public', 1 );
1034
  }
1035
 
1036
  restore_current_blog();
1037
  }
1038
  } else {
1039
- if ( 2 == get_option( 'blog_public' ) ) {
1040
  update_option( 'blog_public', 1 );
1041
  }
1042
  }
1043
  }
1044
 
1045
  /**
1046
- * Determine if plugin is network activated
 
 
1047
  */
1048
  public static function is_network( $plugin ) {
1049
 
1050
- $plugins = get_site_option( 'active_sitewide_plugins');
1051
 
1052
  if ( is_multisite() && isset( $plugins[ $plugin ] ) ) {
1053
  return true;
@@ -1061,21 +1316,21 @@ class Restricted_Site_Access {
1061
  * Check if a given ip is in a network.
1062
  * Source: https://gist.github.com/tott/7684443
1063
  *
1064
- * @param string $ip IP to check in IPV4 format eg. 127.0.0.1
1065
- * @param string $range IP/CIDR netmask eg. 127.0.0.0/24, also 127.0.0.1 is accepted and /32 assumed
1066
  * @return boolean true if the ip is in this range / false if not.
1067
  */
1068
  public static function ip_in_range( $ip, $range ) {
1069
- if ( strpos( $range, '/' ) == false ) {
1070
  $range .= '/32';
1071
  }
1072
  // $range is in IP/CIDR format eg 127.0.0.1/24
1073
  list( $range, $netmask ) = explode( '/', $range, 2 );
1074
- $range_decimal = ip2long( $range );
1075
- $ip_decimal = ip2long( $ip );
1076
- $wildcard_decimal = pow( 2, ( 32 - $netmask ) ) - 1;
1077
- $netmask_decimal = ~ $wildcard_decimal;
1078
- return ( ( $ip_decimal & $netmask_decimal ) == ( $range_decimal & $netmask_decimal ) );
1079
  }
1080
 
1081
  /**
@@ -1084,27 +1339,29 @@ class Restricted_Site_Access {
1084
  * @return string
1085
  */
1086
  public static function get_client_ip_address() {
1087
- $ip = '';
1088
  $headers = array(
1089
- 'HTTP_CLIENT_IP',
1090
- 'HTTP_X_FORWARDED_FOR',
1091
- 'HTTP_X_FORWARDED',
1092
- 'HTTP_X_CLUSTER_CLIENT_IP',
1093
- 'HTTP_FORWARDED_FOR',
1094
- 'HTTP_FORWARDED',
1095
- 'REMOTE_ADDR',
1096
- );
1097
  foreach ( $headers as $key ) {
1098
 
1099
  if ( ! isset( $_SERVER[ $key ] ) ) {
1100
  continue;
1101
  }
1102
 
1103
- foreach ( explode( ',',
1104
- $_SERVER[ $key ] ) as $ip ) {
1105
- $ip = trim( $ip ); // just to be safe
 
 
1106
 
1107
- if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false ) {
1108
  return $ip;
1109
  }
1110
  }
@@ -1114,7 +1371,9 @@ class Restricted_Site_Access {
1114
  }
1115
  }
1116
 
1117
- define( 'RSA_IS_NETWORK', Restricted_Site_Access::is_network( plugin_basename( __FILE__ ) ) );
 
 
1118
 
1119
  Restricted_Site_Access::get_instance();
1120
 
@@ -1136,18 +1395,18 @@ function restricted_site_access_uninstall() {
1136
  foreach ( $sites as $site ) {
1137
  switch_to_blog( $site->blog_id );
1138
 
1139
- if ( 2 == get_option( 'blog_public' ) ) {
1140
  update_option( 'blog_public', 1 );
1141
  }
1142
- delete_option('rsa_options');
1143
 
1144
  restore_current_blog();
1145
  }
1146
  } else {
1147
- if ( 2 == get_option( 'blog_public' ) ) {
1148
  update_option( 'blog_public', 1 );
1149
  }
1150
- delete_option('rsa_options');
1151
  }
1152
  }
1153
 
@@ -1156,20 +1415,22 @@ register_uninstall_hook( __FILE__, 'restricted_site_access_uninstall' );
1156
  if ( ! function_exists( 'inet_pton' ) ) :
1157
 
1158
  /**
1159
- * inet_pton is not included in PHP < 5.3 on Windows (WP requires PHP 5.2)
1160
  *
1161
- * @param string $ip IP Address
1162
  *
1163
  * @return array|string
 
 
1164
  */
1165
  function inet_pton( $ip ) {
1166
  if ( strpos( $ip, '.' ) !== false ) {
1167
- // ipv4
1168
- $ip = pack( 'N',ip2long( $ip ) );
1169
  } elseif ( strpos( $ip, ':' ) !== false ) {
1170
- // ipv6
1171
- $ip = explode( ':', $ip );
1172
- $res = str_pad( '', (4 * (8 -count( $ip ))), '0000', STR_PAD_LEFT );
1173
  foreach ( $ip as $seg ) {
1174
  $res .= str_pad( $seg, 4, '0', STR_PAD_LEFT );
1175
  }
1
+ <?php // phpcs:disable WordPress.Files.FileName
2
  /**
3
  * Plugin Name: Restricted Site Access
4
  * Plugin URI: http://10up.com/plugins/restricted-site-access-wordpress/
5
  * 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: 7.1.0
7
  * Author: Jake Goldman, 10up, Oomph
8
  * Author URI: http://10up.com
9
  * License: GPLv2 or later
10
  * Text Domain: restricted-site-access
11
  */
12
 
13
+ define( 'RSA_VERSION', '7.1.0' );
14
 
15
+ /**
16
+ * Class responsible for all plugin funcitonality.
17
+ */
18
  class Restricted_Site_Access {
19
 
20
+ /**
21
+ * Plugin basename.
22
+ *
23
+ * @var array $basename The plugin base name.
24
+ */
25
+ private static $basename;
26
+
27
+ /**
28
+ * Plugin options.
29
+ *
30
+ * @var array $rsa_options The plugin options.
31
+ */
32
+ private static $rsa_options;
33
+
34
+ /**
35
+ * Settings page slug.
36
+ *
37
+ * @var array $settings_page The settings page slug.
38
+ */
39
  private static $settings_page = 'reading';
40
 
41
+ /**
42
+ * Settings fields.
43
+ *
44
+ * @var array $fields The plugin settings fields.
45
+ */
46
  private static $fields;
47
 
48
  /**
49
  * Handles initializing this class and returning the singleton instance after it's been cached.
50
  *
51
+ * @return null|Restricted_Site_Access
52
+ * @codeCoverageIgnore
53
  */
54
  public static function get_instance() {
55
+ // Store the instance locally to avoid private static replication.
56
  static $instance = null;
57
 
58
  if ( null === $instance ) {
59
  $instance = new self();
60
+ self::add_actions();
61
  self::populate_fields_array();
62
  }
63
 
66
 
67
  /**
68
  * An empty constructor
69
+ *
70
+ * @codeCoverageIgnore
71
  */
72
  public function __construct() {
73
  /* Purposely do nothing here */ }
75
  /**
76
  * Handles registering hooks that initialize this plugin.
77
  */
78
+ public static function add_actions() {
79
  self::$basename = plugin_basename( __FILE__ );
80
 
81
  add_action( 'parse_request', array( __CLASS__, 'restrict_access' ), 1 );
87
  add_action( 'wpmu_new_blog', array( __CLASS__, 'set_defaults' ), 10, 6 );
88
  add_action( 'admin_enqueue_scripts', array( __CLASS__, 'enqueue_admin_script' ) );
89
  add_action( 'wp_ajax_rsa_notice_dismiss', array( __CLASS__, 'ajax_notice_dismiss' ) );
90
+
91
+ add_filter( 'pre_option_blog_public', array( __CLASS__, 'pre_option_blog_public' ), 10, 1 );
92
+ add_filter( 'pre_site_option_blog_public', array( __CLASS__, 'pre_option_blog_public' ), 10, 1 );
93
  }
94
 
95
+ /**
96
+ * Ajax handler for dismissing the network controlled settings notice.
97
+ */
98
  public static function ajax_notice_dismiss() {
 
 
 
 
99
 
100
+ // @codeCoverageIgnoreStart
101
+ if ( ! defined( 'WP_TESTS_DOMAIN' ) ) {
102
+ if ( ! check_ajax_referer( 'rsa_admin_nonce', 'nonce', false ) ) {
103
  wp_send_json_error();
104
  exit;
105
  }
106
+
107
+ if ( RSA_IS_NETWORK ) {
108
+ if ( ! is_super_admin() ) {
109
+ wp_send_json_error();
110
+ exit;
111
+ }
112
+ } else {
113
+ if ( ! current_user_can( 'manage_options' ) ) {
114
+ wp_send_json_error();
115
+ exit;
116
+ }
117
  }
118
  }
119
+ // @codeCoverageIgnoreEnd
120
  if ( RSA_IS_NETWORK ) {
121
  update_site_option( 'rsa_hide_page_cache_notice', true );
122
  } else {
123
  update_option( 'rsa_hide_page_cache_notice', true );
124
  }
125
 
126
+ // @codeCoverageIgnoreStart
127
+ if ( ! defined( 'WP_TESTS_DOMAIN' ) ) {
128
+ wp_send_json_success();
129
+ }
130
+ // @codeCoverageIgnoreEnd
131
  }
132
 
133
  /**
134
+ * Set RSA defaults for new site.
135
+ *
136
+ * @param int $blog_id Blog ID.
137
+ * @param int $user_id User ID.
138
+ * @param string $domain Site domain.
139
+ * @param string $path Site path.
140
+ * @param int $site_id Site ID. Only relevant on multi-network installs.
141
+ * @param array $meta Meta data. Used to set initial site options.
142
  */
143
  public static function set_defaults( $blog_id, $user_id, $domain, $path, $site_id, $meta ) {
144
  if ( 'enforce' === self::get_network_mode() ) {
146
  }
147
 
148
  $network_options = self::get_options( true );
149
+ $blog_public = get_site_option( 'blog_public', 2 );
150
 
151
  switch_to_blog( $blog_id );
152
  update_option( 'rsa_options', self::sanitize_options( $network_options ) );
156
 
157
  /**
158
  * Populate Restricted_Site_Access::$fields with internationalization-ready field information.
159
+ *
160
+ * @codeCoverageIgnore
161
  */
162
  protected static function populate_fields_array() {
163
  self::$fields = array(
164
+ 'approach' => array(
165
+ 'default' => 1,
166
+ 'label' => esc_html__( 'Handle restricted visitors', 'restricted-site-access' ),
167
+ 'field' => 'settings_field_handling',
168
+ ),
169
+ 'message' => array(
170
+ 'default' => esc_html_x( 'Access to this site is restricted.', 'default restriction message', 'restricted-site-access' ),
171
+ 'label' => esc_html__( 'Restriction message', 'restricted-site-access' ),
172
+ 'field' => 'settings_field_message',
173
+ ),
174
+ 'redirect_url' => array(
175
+ 'default' => '',
176
+ 'label' => esc_html__( 'Redirect web address', 'restricted-site-access' ),
177
+ 'field' => 'settings_field_redirect',
178
+ ),
179
+ 'redirect_path' => array(
180
+ 'default' => 0,
181
+ 'label' => esc_html__( 'Redirect to same path', 'restricted-site-access' ),
182
+ 'field' => 'settings_field_redirect_path',
183
+ ),
184
+ 'head_code' => array(
185
+ 'default' => 302,
186
+ 'label' => esc_html__( 'Redirection status code', 'restricted-site-access' ),
187
+ 'field' => 'settings_field_redirect_code',
188
+ ),
189
+ 'page' => array(
190
+ 'default' => 0,
191
+ 'label' => esc_html__( 'Restricted notice page', 'restricted-site-access' ),
192
+ 'field' => 'settings_field_rsa_page',
193
+ ),
194
+ 'allowed' => array(
195
+ 'default' => array(),
196
+ 'label' => esc_html__( 'Unrestricted IP addresses', 'restricted-site-access' ),
197
+ 'field' => 'settings_field_allowed',
198
+ ),
199
  );
200
  }
201
 
203
  * Get current plugin network mode
204
  */
205
  private static function get_network_mode() {
206
+ if ( RSA_IS_NETWORK ) {
207
  return get_site_option( 'rsa_mode', 'default' );
208
  }
209
 
211
  }
212
 
213
  /**
214
+ * Populate the option with defaults.
215
+ *
216
+ * @param boolean $network Whther this is a network install. Default false.
217
  */
218
  public static function get_options( $network = false ) {
219
  $options = array();
224
  $options = get_option( 'rsa_options' );
225
  }
226
 
227
+ // Fill in defaults where values aren't set.
228
+ foreach ( self::$fields as $field_name => $field_details ) {
229
  if ( ! isset( $options[ $field_name ] ) ) {
230
  $options[ $field_name ] = $field_details['default'];
231
  }
248
 
249
  $blog_public = get_option( 'blog_public', 2 );
250
 
 
 
 
 
 
251
  $user_check = self::user_can_access();
252
 
253
+ $checks = is_admin() || $user_check || 2 !== (int) $blog_public || ( defined( 'WP_INSTALLING' ) && isset( $_GET['key'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
254
 
255
  return ! $checks;
256
  }
296
  }
297
 
298
  /**
299
+ * Redirects restricted requests.
300
  *
301
+ * @param array $wp WordPress request.
302
+ * @codeCoverageIgnore
303
  */
304
  public static function restrict_access( $wp ) {
305
+
306
+ $results = self::restrict_access_check( $wp );
307
+
308
+ if ( is_array( $results ) && ! empty( $results ) ) {
309
+
310
+ // Don't redirect during unit tests.
311
+ if ( ! empty( $results['url'] ) && ! defined( 'WP_TESTS_DOMAIN' ) ) {
312
+ wp_redirect( $results['url'], $results['code'] ); // phpcs:ignore WordPress.Security.SafeRedirect.wp_redirect_wp_redirect
313
+ die();
314
+ }
315
+
316
+ // Don't die during unit tests.
317
+ if ( ! empty( $results['die_message'] ) && ! defined( 'WP_TESTS_DOMAIN' ) ) {
318
+ wp_die( wp_kses_post( $results['die_message'] ), esc_html( $results['die_title'] ), array( 'response' => esc_html( $results['die_code'] ) ) );
319
+ }
320
+ }
321
+ }
322
+
323
+ /**
324
+ * Determine whether page should be restricted at point of request.
325
+ *
326
+ * @param array $wp WordPress The main WP request.
327
+ * @return array List of URL and code, otherwise empty.
328
+ */
329
+ public static function restrict_access_check( $wp ) {
330
  self::$rsa_options = self::get_options();
331
  $is_restricted = self::is_restricted();
332
 
333
+ // Check to see if it's _not_ restricted.
334
  if ( apply_filters( 'restricted_site_access_is_restricted', $is_restricted, $wp ) === false ) {
335
  return;
336
  }
343
  $allowed_ips = array_merge( $allowed_ips, self::$rsa_options['allowed'] );
344
  }
345
 
346
+ // check for the allow list, if its empty block everything.
347
  if ( count( $allowed_ips ) > 0 ) {
348
  $remote_ip = self::get_client_ip_address();
349
 
350
+ // iterate through the allow list.
351
+ foreach ( $allowed_ips as $line ) {
352
  if ( self::ip_in_range( $remote_ip, $line ) ) {
353
 
354
  /**
370
  }
371
 
372
  $rsa_restrict_approach = apply_filters( 'restricted_site_access_approach', self::$rsa_options['approach'] );
373
+ do_action( 'restrict_site_access_handling', $rsa_restrict_approach, $wp ); // allow users to hook handling.
374
 
375
  switch ( $rsa_restrict_approach ) {
376
+ case 4: // Show them a page.
377
  if ( ! empty( self::$rsa_options['page'] ) ) {
378
  $page = get_post( self::$rsa_options['page'] );
379
 
380
  // If the selected page isn't found or isn't published, fall back to default values.
381
  if ( ! $page || 'publish' !== $page->post_status ) {
382
+ self::$rsa_options['head_code'] = 302;
383
+ $current_path = empty( $_SERVER['REQUEST_URI'] ) ? home_url() : sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) );
384
  self::$rsa_options['redirect_url'] = wp_login_url( $current_path );
385
  break;
386
  }
387
 
388
  // Are we already on the selected page?
389
+ $on_selected_page = false;
390
+ if ( isset( $wp->query_vars['page_id'] ) && absint( $wp->query_vars['page_id'] ) === $page->ID ) {
391
+ $on_selected_page = true;
392
+ }
393
+
394
+ if ( ! $on_selected_page && ( isset( $wp->query_vars['pagename'] ) && $wp->query_vars['pagename'] === $page->post_name ) ) {
395
+ $on_selected_page = true;
396
+ }
397
+
398
+ // There's a separate unpleasant conditional to match the page on front because of the way query vars are (not) filled at this point.
399
+ if ( $on_selected_page
400
+ ||
401
+ (
402
+ empty( $wp->query_vars ) &&
403
+ 'page' === get_option( 'show_on_front' ) &&
404
+ (int) get_option( 'page_on_front' ) === (int) self::$rsa_options['page']
405
+ )
406
+ ) {
407
  return;
408
  }
409
 
410
  self::$rsa_options['redirect_url'] = get_permalink( $page->ID );
411
  break;
412
  }
413
+ // Fall thru to case 3 if case 2 not handled.
414
  case 3:
415
+ $message = esc_html( self::$rsa_options['message'] );
416
  $message .= "\n<!-- protected by Restricted Site Access http://10up.com/plugins/restricted-site-access-wordpress/ -->";
417
+ $message = apply_filters( 'restricted_site_access_message', $message, $wp );
418
+
419
+ return array(
420
+ 'die_message' => $message,
421
+ 'die_title' => esc_html( get_bloginfo( 'name' ) ) . ' - Site Access Restricted',
422
+ 'die_code' => 403,
423
+ );
424
 
425
  case 2:
426
  if ( ! empty( self::$rsa_options['redirect_url'] ) ) {
427
  if ( ! empty( self::$rsa_options['redirect_path'] ) ) {
428
+ self::$rsa_options['redirect_url'] = untrailingslashit( self::$rsa_options['redirect_url'] ) . sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) );
429
  }
430
  break;
431
  }
432
+ // No break, fall thru to default.
433
  default:
434
+ self::$rsa_options['head_code'] = 302;
435
+ $current_path = empty( $_SERVER['REQUEST_URI'] ) ? home_url() : sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) );
436
  self::$rsa_options['redirect_url'] = wp_login_url( $current_path );
437
  }
438
 
439
+ $redirect_url = apply_filters( 'restricted_site_access_redirect_url', self::$rsa_options['redirect_url'], $wp );
440
  $redirect_code = apply_filters( 'restricted_site_access_head', self::$rsa_options['head_code'], $wp );
441
 
442
+ return array(
443
+ 'url' => $redirect_url,
444
+ 'code' => $redirect_code,
445
+ );
446
  }
447
 
448
  /**
449
  * Admin only hooks
450
  */
451
  public static function admin_init() {
452
+ // customize privacy message.
453
  add_filter( 'privacy_on_link_text', array( __CLASS__, 'privacy_on_link_text' ) );
454
  add_filter( 'privacy_on_link_title', array( __CLASS__, 'privacy_on_link_title' ) );
455
 
456
+ // customize privacy page.
457
  add_action( 'load-options-' . self::$settings_page . '.php', array( __CLASS__, 'load_options_page' ) );
458
 
459
+ // add new choice for blog privacy.
460
  add_action( 'blog_privacy_selector', array( __CLASS__, 'blog_privacy_selector' ) );
461
 
462
+ // settings for restricted site access.
463
+ register_setting( self::$settings_page, 'rsa_options', array( __CLASS__, 'sanitize_options' ) ); // array of fundamental options including ID and caching info.
464
  add_settings_section( 'restricted-site-access', '', '__return_empty_string', self::$settings_page );
465
+
466
+ // Limit when additional settings fields show up.
467
+ if (
468
+ is_network_admin() || // Show on the network admin.
469
+ ( RSA_IS_NETWORK && 'enforce' !== self::get_network_mode() ) || // Show on single (network) site when not enforced at the network level.
470
+ ! RSA_IS_NETWORK // Show on single non-network sites.
471
+ ) {
472
+ foreach ( self::$fields as $field_name => $field_data ) {
473
+ add_settings_field(
474
+ $field_name,
475
+ $field_data['label'],
476
+ array( __CLASS__, $field_data['field'] ),
477
+ self::$settings_page,
478
+ 'restricted-site-access',
479
+ array( 'class' => 'rsa-setting rsa-setting_' . esc_attr( $field_data['field'] ) )
480
+ );
481
+ }
482
  }
483
 
484
  add_filter( 'plugin_action_links_' . self::$basename, array( __CLASS__, 'plugin_action_links' ) );
485
 
486
+ // This is for Network Site Settings.
487
+ if ( RSA_IS_NETWORK && is_network_admin() ) {
488
  add_action( 'load-settings.php', array( __CLASS__, 'load_network_settings_page' ) );
489
  add_action( 'network_admin_notices', array( __CLASS__, 'page_cache_notice' ) );
 
490
  }
491
 
492
  add_action( 'admin_notices', array( __CLASS__, 'page_cache_notice' ) );
498
  public static function show_network_settings() {
499
  $mode = self::get_network_mode();
500
  ?>
501
+ <h2><?php esc_html_e( 'Restricted Site Access Settings', 'restricted-site-access' ); ?></h2>
502
+ <table id="restricted-site-access-mode" class="form-table">
503
  <tr>
504
+ <th scope="row"><?php esc_html_e( 'Mode', 'restricted-site-access' ); ?></th>
505
  <td>
506
  <fieldset>
507
+ <legend class="screen-reader-text"><?php esc_html_e( 'Mode', 'restricted-site-access' ); ?></legend>
508
+ <label><input name="rsa_mode" type="radio" id="rsa-mode-default" value="default"<?php checked( $mode, 'default' ); ?> /> <?php esc_html_e( 'Default to the settings below when creating a new site', 'restricted-site-access' ); ?></label><br />
509
+ <label><input name="rsa_mode" type="radio" id="rsa-mode-enforce" value="enforce"<?php checked( $mode, 'enforce' ); ?> /> <?php esc_html_e( 'Enforce the settings below across all sites', 'restricted-site-access' ); ?></label><br />
510
  </fieldset>
511
  </td>
512
  </tr>
513
+ <tr class="option-site-visibility">
514
+ <th scope="row"><?php esc_html_e( 'Site Visibility', 'restricted-site-access' ); ?></th>
515
  <?php
516
  $blog_public = get_site_option( 'blog_public' );
517
 
521
  ?>
522
  <td>
523
  <fieldset>
524
+ <legend class="screen-reader-text"><span><?php esc_html_e( 'Site Visibility', 'restricted-site-access' ); ?></span></legend>
525
+ <input id="blog-public" type="radio" name="blog_public" value="1" <?php checked( $blog_public, '1' ); ?>>
526
+ <label for="blog-public"><?php esc_html_e( 'Allow search engines to index this site', 'restricted-site-access' ); ?></label><br>
527
+ <input id="blog-norobots" type="radio" name="blog_public" value="0" <?php checked( $blog_public, '0' ); ?>>
528
+ <label for="blog-norobots"><?php esc_html_e( 'Discourage search engines from indexing this site', 'restricted-site-access' ); ?></label>
529
+ <p class="description"><?php esc_html_e( 'Note: Neither of these options blocks access to your site — it is up to search engines to honor your request.', 'restricted-site-access' ); ?></p>
530
  <p>
531
+ <input id="blog-restricted" type="radio" name="blog_public" value="2" <?php checked( $blog_public, '2' ); ?>>
532
+ <label for="blog-restricted"><?php esc_html_e( 'Restrict site access to visitors who are logged in or allowed by IP address', 'restricted-site-access' ); ?></label>
533
  </p>
534
  </fieldset>
535
  </td>
536
  </tr>
537
  </table>
538
+ <?php
539
+ if ( ( defined( 'RSA_FORCE_RESTRICTION' ) && RSA_FORCE_RESTRICTION === true )
540
+ || ( defined( 'RSA_FORBID_RESTRICTION' ) && RSA_FORBID_RESTRICTION === true ) ) {
541
+ $message = __( 'Site visibility settings are currently enforced by code configuration.', 'restricted-site-access' );
542
+ ?>
543
+ <div class="notice notice-warning inline">
544
+ <p><strong><?php echo esc_html( $message ); ?></strong></p>
545
+ </div>
546
+ <?php } ?>
547
  <table id="restricted-site-access" class="form-table">
548
  <tr>
549
+ <th scope="row"><?php esc_html_e( 'Handle restricted visitors', 'restricted-site-access' ); ?></th>
550
  <td>
551
  <?php
552
  self::settings_field_handling();
554
  </td>
555
  </tr>
556
  <tr>
557
+ <th scope="row"><?php esc_html_e( 'Redirect web address', 'restricted-site-access' ); ?></th>
558
  <td>
559
  <?php
560
  self::settings_field_redirect();
562
  </td>
563
  </tr>
564
  <tr>
565
+ <th scope="row"><?php esc_html_e( 'Redirect to same path', 'restricted-site-access' ); ?></th>
566
  <td>
567
  <?php
568
  self::settings_field_redirect_path();
570
  </td>
571
  </tr>
572
  <tr>
573
+ <th scope="row"><?php esc_html_e( 'Redirection status code', 'restricted-site-access' ); ?></th>
574
  <td>
575
  <?php
576
  self::settings_field_redirect_code();
578
  </td>
579
  </tr>
580
  <tr>
581
+ <th scope="row"><?php esc_html_e( 'Restriction message', 'restricted-site-access' ); ?></th>
582
  <td>
583
  <?php
584
  self::settings_field_message();
586
  </td>
587
  </tr>
588
  <tr>
589
+ <th scope="row"><?php esc_html_e( 'Unrestricted IP addresses', 'restricted-site-access' ); ?></th>
590
  <td>
591
  <?php
592
  self::settings_field_allowed();
599
  }
600
 
601
  /**
602
+ * Handle Save Options for RSA Settings in Network Settings.
603
  */
604
  public static function save_network_settings() {
605
  $options = array(
606
+ 'rsa_mode',
607
+ 'blog_public',
608
+ 'rsa_options',
609
  );
610
 
611
  foreach ( $options as $option_name ) {
612
+ if ( ! isset( $_POST[ $option_name ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
613
  continue;
614
  }
615
 
616
+ switch ( $option_name ) {
617
  case 'rsa_options':
618
+ $value = self::sanitize_options( wp_unslash( $_POST[ $option_name ] ) ); // phpcs:ignore WordPress.Security.NonceVerification, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.VIP.ValidatedSanitizedInput.InputNotSanitized
619
  break;
620
  case 'blog_public':
621
  $value = absint( $_POST[ $option_name ] );
630
  }
631
 
632
  /**
633
+ * Overrides text in the dashboard Right Now widget.
634
  *
635
+ * @param string $text The text for the dashboard 'right now' widget.
636
  *
637
  * @return string New text to show in widget
638
  */
639
  public static function privacy_on_link_text( $text ) {
640
+ if ( 2 === (int) get_option( 'blog_public' ) ) {
641
+ $text = esc_html__( 'Public access to this site has been restricted.', 'restricted-site-access' );
642
  }
643
  return $text;
644
  }
645
 
646
  /**
647
+ * Title attribute for link about site status on Right Now widget.
648
  *
649
+ * @param string $text The title attribute.
650
  *
651
  * @return string New title attribute
652
  */
653
  public static function privacy_on_link_title( $text ) {
654
+ if ( 2 === (int) get_option( 'blog_public' ) ) {
655
+ $text = esc_html__( 'Restricted Site Access plug-in is blocking public access to this site.', 'restricted-site-access' );
656
  }
657
  return $text;
658
  }
659
 
660
+ /**
661
+ * Enqueue Settings page scripts.
662
+ */
663
  public static function enqueue_settings_script() {
664
+ $min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
665
+ $folder = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? 'src/' : '';
666
+
667
+ wp_enqueue_script(
668
+ 'rsa-settings',
669
+ plugin_dir_url( __FILE__ ) . 'assets/js/' . $folder . 'settings' . $min . '.js',
670
+ array( 'jquery-effects-shake' ),
671
+ RSA_VERSION,
672
+ true
673
+ );
674
  }
675
 
676
+ /**
677
+ * Enqueue wp-admin scripts.
678
+ */
679
  public static function enqueue_admin_script() {
680
+ $js_path = plugin_dir_url( __FILE__ ) . 'assets/js/admin.min.js';
 
 
 
 
681
 
682
+ $min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
683
+ $folder = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? 'src/' : '';
684
+
685
+ wp_enqueue_script(
686
+ 'rsa-admin',
687
+ plugin_dir_url( __FILE__ ) . 'assets/js/' . $folder . 'admin' . $min . '.js',
688
+ array( 'jquery' ),
689
+ RSA_VERSION,
690
+ true
691
+ );
692
+
693
+ wp_localize_script(
694
+ 'rsa-admin',
695
+ 'rsaAdmin',
696
+ array(
697
+ 'nonce' => wp_create_nonce( 'rsa_admin_nonce' ),
698
+ )
699
+ );
700
  }
701
 
702
  /**
707
 
708
  add_action( 'admin_notices', array( __CLASS__, 'admin_notice' ) );
709
  add_action( 'admin_head', array( __CLASS__, 'admin_head' ) );
710
+ add_action( 'admin_body_class', array( __CLASS__, 'admin_body_class' ) );
711
 
712
  add_filter( 'wp_dropdown_pages', array( __CLASS__, 'filter_page_dropdown' ), 10, 2 );
713
 
717
  /**
718
  * Load needed scripts and assets on Network Settings page
719
  */
720
+ public static function load_network_settings_page() {
721
  self::enqueue_settings_script();
722
 
723
  self::$rsa_options = self::get_options( true );
724
 
725
+ add_action( 'admin_body_class', array( __CLASS__, 'admin_body_class' ) );
726
+ add_action( 'admin_head', array( __CLASS__, 'admin_head' ) );
727
  add_action( 'wpmu_options', array( __CLASS__, 'show_network_settings' ) );
728
  add_action( 'update_wpmu_options', array( __CLASS__, 'save_network_settings' ) );
729
  }
732
  * Customize admin notices to ensure user completes restriction setup properly
733
  */
734
  public static function admin_notice() {
 
 
 
 
 
 
735
  if ( empty( self::$rsa_options['approach'] ) ) {
736
  return;
737
  }
738
 
739
+ if ( 4 === (int) self::$rsa_options['approach'] && empty( self::$rsa_options['page'] ) ) {
740
+ $message = esc_html__( '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' );
741
+ } elseif ( 2 === (int) self::$rsa_options['approach'] && empty( self::$rsa_options['redirect_url'] ) ) {
742
+ $message = esc_html__( 'Please enter the web address you would like to redirect restricted visitors to. If no address is entered, visitors will be redirected to the login screen.', 'restricted-site-access' );
743
  }
744
 
745
  if ( isset( $message ) ) {
746
+ echo '<div class="notice notice-error"><p><strong>' . esc_html( $message ) . '</strong></p></div>';
747
  }
748
  }
749
 
751
  * Check if the page caching is on, and notify the admin
752
  */
753
  public static function page_cache_notice() {
754
+ // If WP_CACHE is on we show notification.
755
+ $show_notification = apply_filters( 'restricted_site_access_show_page_cache_notice', defined( 'WP_CACHE' ) && true === WP_CACHE );
756
+
757
+ if ( $show_notification ) {
758
 
759
  if ( RSA_IS_NETWORK ) {
760
  if ( get_site_option( 'rsa_hide_page_cache_notice' ) ) {
780
  ?>
781
  <div data-rsa-notice="page-cache" class="notice notice-error is-dismissible">
782
  <p>
783
+ <strong><?php esc_html_e( 'Page caching appears to be enabled. Restricted Site Access may not work as expected. <a href="https://wordpress.org/plugins/restricted-site-access/#faq">Learn more</a>.', 'restricted-site-access' ); ?></strong>
784
  </p>
785
  </div>
786
  <?php
788
  }
789
 
790
  /**
791
+ * Add RSA help tab and a tiny amount of CSS to Reading options.
792
  */
793
  public static function admin_head() {
794
  $screen = get_current_screen();
806
  _x( 'Allowed IP addresses', 'help topic', 'restricted-site-access' ),
807
  __( '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!', 'restricted-site-access' ),
808
  sprintf(
809
+ /* translators: %s: link to http://www.csgnetwork.com/ipinfocalc.html */
810
  '<a href="http://www.csgnetwork.com/ipinfocalc.html">%s</a>',
 
811
  __( 'Here is a handy calculator to check your prefix.', 'restricted-site-access' )
812
  ),
813
  __( 'The redirection fields are only used when "Handle restricted visitors" is set to "Redirect them to a specified web address".', 'restricted-site-access' )
831
  __( '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' )
832
  );
833
 
834
+ $screen->add_help_tab(
835
+ array(
836
+ 'id' => 'restricted-site-access',
837
+ 'title' => esc_html_x( 'Restricted Site Acccess', 'help screen title', 'restricted-site-access' ),
838
+ 'content' => implode( PHP_EOL, $content ),
839
+ )
840
+ );
841
+ ?>
842
+ <style>
843
+ .rsa-enforced .option-site-visibility {
844
+ opacity: 0.5;
845
+ pointer-events: none;
846
+ }
847
+ </style>
848
+ <?php
849
+ }
850
+
851
+ /**
852
+ * Adds admin body classes to the Reading options screen.
853
+ *
854
+ * Adds `.rsa-network-enforced` if settings are network enforced.
855
+ *
856
+ * @param string $classes Space-separated list of classes to apply to the body element.
857
+ * @return string
858
+ */
859
+ public static function admin_body_class( $classes ) {
860
+ if ( self::is_enforced() ) {
861
+ $classes .= ' rsa-enforced';
862
+ }
863
+
864
+ return $classes;
865
  }
866
 
867
  /**
868
+ * Determines if site restriction is enforced either on a code or network level.
869
+ *
870
+ * Important: this is only meant for admin UI purposes.
871
+ *
872
+ * @return boolean
873
+ */
874
+ public static function is_enforced() {
875
+ if (
876
+ ( ! is_network_admin() && ( RSA_IS_NETWORK && 'enforce' === self::get_network_mode() ) ) ||
877
+ ( defined( 'RSA_FORCE_RESTRICTION' ) && RSA_FORCE_RESTRICTION === true ) ||
878
+ ( defined( 'RSA_FORBID_RESTRICTION' ) && RSA_FORBID_RESTRICTION === true )
879
+ ) {
880
+ return true;
881
+ }
882
+
883
+ return false;
884
+ }
885
+
886
+ /**
887
+ * Add a new choice to the privacy selector.
888
  */
889
  public static function blog_privacy_selector() {
890
  global $wp;
891
+ $is_restricted = ( 2 === (int) get_option( 'blog_public' ) );
892
  $is_restricted = apply_filters( 'restricted_site_access_is_restricted', $is_restricted, $wp );
893
+ ?>
894
  <p>
895
  <input id="blog-restricted" type="radio" name="blog_public" value="2" <?php checked( $is_restricted ); ?> />
896
  <label for="blog-restricted"><?php esc_html_e( 'Restrict site access to visitors who are logged in or allowed by IP address', 'restricted-site-access' ); ?></label>
897
  </p>
898
+ <?php
899
+ if ( self::is_enforced() ) {
900
+ // The network enforcement message takes precedence because it's more restrictive and technically still correct with the constants.
901
+ if ( RSA_IS_NETWORK && 'enforce' === self::get_network_mode() ) {
902
+ $message = __( 'Site visibility settings are currently enforced across all sites on the network.', 'restricted-site-access' );
903
+ } else {
904
+ $message = __( 'Site visibility settings are currently enforced by code configuration.', 'restricted-site-access' );
905
+ }
906
+ // Important note: the weird HTML structure below has to match where `blog_privacy_selector` is fired.
907
+ ?>
908
+ </fieldset>
909
+ </td>
910
+ </tr>
911
+ <tr class="rsa-network-enforced-warning">
912
+ <td colspan="2">
913
+ <fieldset>
914
+ <div class="notice notice-warning inline">
915
+ <p><strong><?php echo esc_html( $message ); ?></strong></p>
916
+ </div>
917
+ <?php
918
+ }
919
  }
920
 
921
  /**
922
+ * Sanitize RSA options.
923
  *
924
+ * @param array $input The options to sanitize.
925
  *
926
  * @return array Sanitized input
927
  */
935
  $new_input['message'] = wp_kses( $input['message'], $allowedtags );
936
 
937
  $new_input['redirect_path'] = empty( $input['redirect_path'] ) ? 0 : 1;
938
+ $new_input['head_code'] = in_array( (int) $input['head_code'], array( 301, 302, 307 ), true ) ? (int) $input['head_code'] : self::$fields['head_code']['default'];
939
+ $new_input['redirect_url'] = empty( $input['redirect_url'] ) ? '' : esc_url_raw( $input['redirect_url'], array( 'http', 'https' ) );
940
+ $new_input['page'] = empty( $input['page'] ) ? 0 : (int) $input['page'];
941
 
942
  $new_input['allowed'] = array();
943
  if ( ! empty( $input['allowed'] ) && is_array( $input['allowed'] ) ) {
947
  }
948
  }
949
  }
950
+ $new_input['comment'] = array();
951
+ if ( ! empty( $input['comment'] ) && is_array( $input['comment'] ) ) {
952
+ foreach ( $input['comment'] as $comment ) {
953
+ if ( is_scalar( $comment ) ) {
954
+ $new_input['comment'][] = sanitize_text_field( $comment );
955
+ }
956
+ }
957
+ }
958
 
959
  return $new_input;
960
  }
961
 
962
  /**
963
+ * Fieldset for choosing restriction handling.
 
 
964
  */
965
+ public static function settings_field_handling() {
966
  if ( ! isset( self::$rsa_options['approach'] ) ) {
967
+ // @codeCoverageIgnoreStart
968
  self::$rsa_options['approach'] = 1;
969
+ // @codeCoverageIgnoreEnd
970
  }
971
+ ?>
972
  <fieldset id="rsa_handle_fields">
973
  <input id="rsa-send-to-login" name="rsa_options[approach]" type="radio" value="1" <?php checked( self::$rsa_options['approach'], 1 ); ?> />
974
+ <label for="rsa-send-to-login"><?php esc_html_e( 'Send them to the WordPress login screen', 'restricted-site-access' ); ?></label>
975
  <br />
976
  <input id="rsa-redirect-visitor" name="rsa_options[approach]" type="radio" value="2" <?php checked( self::$rsa_options['approach'], 2 ); ?> />
977
  <label for="rsa-redirect-visitor"><?php esc_html_e( 'Redirect them to a specified web address', 'restricted-site-access' ); ?></label>
985
  <label for="rsa-unblocked-page"><?php esc_html_e( 'Show them a page', 'restricted-site-access' ); ?></label>
986
  <?php endif; ?>
987
  </fieldset>
988
+ <?php
989
  }
990
 
991
  /**
992
+ * Fieldset for managing allowed IP addresses.
 
 
993
  */
994
+ public static function settings_field_allowed() {
995
+ ?>
996
  <div class="hide-if-no-js">
997
  <div id="ip_list">
998
+ <div id="ip_list_empty" style="display: none;"><input type="text" name="rsa_options[allowed][]" class="ip code" value="" readonly="true" size="20" /> <input type="text" name="rsa_options[comment][]" value="" class="comment" size="20" /> <a href="#remove" class="remove_btn"><?php echo esc_html( _x( 'Remove', 'remove IP address action', 'restricted-site-access' ) ); ?></a></div>
999
  <?php
1000
+ $ips = (array) self::$rsa_options['allowed'];
1001
+ $comments = isset( self::$rsa_options['comment'] ) ? (array) self::$rsa_options['comment'] : array();
1002
+ foreach ( $ips as $key => $ip ) {
1003
+ if ( ! empty( $ip ) ) {
1004
+ echo '<div><input type="text" name="rsa_options[allowed][]" value="' . esc_attr( $ip ) . '" class="ip code" readonly="true" size="20" /> <input type="text" name="rsa_options[comment][]" value="' . ( isset( $comments[ $key + 1 ] ) ? esc_attr( wp_unslash( $comments[ $key + 1 ] ) ) : '' ) . '" size="20" /> <a href="#remove" class="remove_btn">' . esc_html_x( 'Remove', 'remove IP address action', 'restricted-site-access' ) . '</a></div>';
1005
  }
1006
+ }
1007
  ?>
1008
  </div>
1009
  <div>
1010
+ <input type="text" name="newip" id="newip" class="ip code" placeholder="<?php esc_attr_e( 'IP Address or Range' ); ?>" size="20" />
1011
+ <input type="text" name="newipcomment" id="newipcomment" placeholder="<?php esc_attr_e( 'Identify this entry' ); ?>" size="20" /> <input class="button" type="button" id="addip" value="<?php esc_attr_e( 'Add' ); ?>" />
1012
+ <p class="description"><label for="newip"><?php esc_html_e( 'Enter a single IP address or a range using a subnet prefix', 'restricted-site-access' ); ?></label></p>
1013
+ <?php if ( ! empty( $_SERVER['REMOTE_ADDR'] ) ) : ?>
1014
+ <input class="button" type="button" id="rsa_myip" value="<?php esc_attr_e( 'Add My Current IP Address', 'restricted-site-access' ); ?>" style="margin-top: 5px;" data-myip="<?php echo esc_attr( self::get_client_ip_address() ); ?>" /><br />
1015
+ <?php endif; ?>
1016
+ </div>
1017
+
1018
+ <?php
1019
+ $config_ips = self::get_config_ips();
1020
+ if ( ! empty( $config_ips ) ) :
1021
+ ?>
1022
  <div class="config_ips" style="margin-top: 10px;">
1023
+ <h4>
1024
+ <?php esc_html_e( 'Unrestricted IP addresses set by code configuration', 'restricted-site-access' ); ?>
1025
+ </h4>
1026
+ <ul class="ul-disc">
1027
+ <?php
1028
  foreach ( $config_ips as $ip ) {
1029
+ echo '<li><code>' . esc_attr( $ip ) . '</code></li>';
 
 
 
1030
  }
1031
+ ?>
1032
+ </ul>
1033
  </div>
1034
+ <?php endif; ?>
1035
  </div>
1036
  <p class="hide-if-js"><strong><?php esc_html_e( 'To manage IP addresses, you must use a JavaScript enabled browser.', 'restricted-site-access' ); ?></strong></p>
1037
+ <?php
1038
  }
1039
 
1040
  /**
1041
+ * Field for custom message.
 
 
1042
  */
1043
+ public static function settings_field_message() {
1044
  if ( empty( self::$rsa_options['message'] ) ) {
1045
+ self::$rsa_options['message'] = esc_html__( 'Access to this site is restricted.', 'restricted-site-access' );
1046
  }
1047
 
1048
+ wp_editor(
1049
+ self::$rsa_options['message'],
1050
+ 'rsa_message',
1051
+ array(
1052
+ 'media_buttons' => false,
1053
+ 'textarea_name' => 'rsa_options[message]',
1054
+ 'textarea_rows' => 4,
1055
+ 'tinymce' => false,
1056
+ )
1057
+ );
1058
  }
1059
 
1060
  /**
1061
+ * Field for redirection.
 
 
1062
  */
1063
+ public static function settings_field_redirect() {
1064
  if ( ! isset( self::$rsa_options['redirect_url'] ) ) {
1065
+ // @codeCoverageIgnoreStart
1066
  self::$rsa_options['redirect_url'] = '';
1067
+ // @codeCoverageIgnoreEnd
1068
  }
1069
+ ?>
1070
  <input type="text" name="rsa_options[redirect_url]" id="redirect" class="rsa_redirect_field regular-text" value="<?php echo esc_attr( self::$rsa_options['redirect_url'] ); ?>" />
1071
+ <?php
1072
  }
1073
 
1074
  /**
1075
+ * Field for redirect path option.
 
 
1076
  */
1077
+ public static function settings_field_redirect_path() {
1078
  if ( ! isset( self::$rsa_options['redirect_path'] ) ) {
1079
+ // @codeCoverageIgnoreStart
1080
  self::$rsa_options['redirect_path'] = 0;
1081
+ // @codeCoverageIgnoreEnd
1082
  }
1083
+ ?>
1084
+ <fieldset><legend class="screen-reader-text"><span><?php esc_html( self::$rsa_options['redirect_path']['label'] ); ?></span></legend>
1085
  <label for="redirect_path">
1086
  <input type="checkbox" name="rsa_options[redirect_path]" value="1" id="redirect_path" class="rsa_redirect_field" <?php checked( self::$rsa_options['redirect_path'] ); ?> />
1087
  <?php esc_html_e( 'Send restricted visitor to same path (relative URL) at the new web address', 'restricted-site-access' ); ?></label>
1088
  </fieldset>
1089
+ <?php
1090
  }
1091
 
1092
  /**
1093
+ * Field for specifying redirect code.
 
 
1094
  */
1095
+ public static function settings_field_redirect_code() {
1096
  if ( empty( self::$rsa_options['head_code'] ) ) {
1097
+ // @codeCoverageIgnoreStart
1098
  self::$rsa_options['head_code'] = 302;
1099
+ // @codeCoverageIgnoreEnd
1100
  }
1101
+ ?>
1102
  <select name="rsa_options[head_code]" id="redirect_code" class="rsa_redirect_field">
1103
  <option value="301" <?php selected( self::$rsa_options['head_code'], 301 ); ?>><?php esc_html_e( '301 Permanent', 'restricted-site-access' ); ?></option>
1104
  <option value="302" <?php selected( self::$rsa_options['head_code'], 302 ); ?>><?php esc_html_e( '302 Undefined', 'restricted-site-access' ); ?></option>
1105
  <option value="307" <?php selected( self::$rsa_options['head_code'], 307 ); ?>><?php esc_html_e( '307 Temporary', 'restricted-site-access' ); ?></option>
1106
  </select>
1107
+ <?php
1108
  }
1109
 
1110
  /**
1111
+ * Field for choosing a page to redirect to.
 
 
1112
  */
1113
+ public static function settings_field_rsa_page() {
1114
  if ( ! isset( self::$rsa_options['page'] ) ) {
1115
+ // @codeCoverageIgnoreStart
1116
  self::$rsa_options['page'] = 0;
1117
+ // @codeCoverageIgnoreEnd
1118
  }
1119
 
1120
+ wp_dropdown_pages(
1121
+ array(
1122
+ 'selected' => esc_html( self::$rsa_options['page'] ),
1123
+ 'show_option_none' => esc_html__( 'Select a page', 'restricted-site-access' ),
1124
+ 'name' => 'rsa_options[page]',
1125
+ 'id' => 'rsa_page',
1126
+ )
1127
+ );
1128
  }
1129
 
1130
  /**
1147
  }
1148
 
1149
  /**
1150
+ * Validate IP address entry on demand (AJAX).
1151
+ *
1152
+ * @codeCoverageIgnore
1153
  */
1154
  public static function ajax_rsa_ip_check() {
1155
+
1156
+ if ( ! check_ajax_referer( 'rsa_admin_nonce', 'nonce', false ) ) {
1157
+ wp_send_json_error();
1158
+ exit;
1159
+ }
1160
+
1161
+ if ( empty( $_POST['ip_address'] ) || ! self::is_ip( stripslashes( sanitize_text_field( wp_unslash( $_POST['ip_address'] ) ) ) ) ) {
1162
  die( '1' );
1163
  }
1164
  die;
1165
  }
1166
 
1167
  /**
1168
+ * Is it a valid IP address? v4/v6 with subnet range.
1169
  *
1170
+ * @param string $ip_address IP Address to check.
1171
  *
1172
  * @return bool True if its a valid IP address.
1173
  */
1174
  public static function is_ip( $ip_address ) {
1175
+ // very basic validation of ranges.
1176
  if ( strpos( $ip_address, '/' ) ) {
1177
  $ip_parts = explode( '/', $ip_address );
1178
  if ( empty( $ip_parts[1] ) || ! is_numeric( $ip_parts[1] ) || strlen( $ip_parts[1] ) > 3 ) {
1181
  $ip_address = $ip_parts[0];
1182
  }
1183
 
1184
+ // confirm IP part is a valid IPv6 or IPv4 IP.
1185
  if ( empty( $ip_address ) || ! inet_pton( stripslashes( $ip_address ) ) ) {
1186
  return false;
1187
  }
1216
  }
1217
 
1218
  /**
1219
+ * Short-circuit filter the `blog_public` option to match network if necessary.
1220
  *
1221
+ * This runs for both `get_option()` and `get_site_option()`,
1222
+ * hence the `doing_filter()` check.
1223
+ *
1224
+ * @param bool $value Value of `blog_public` option, typically false.
1225
+ * @return int
1226
+ */
1227
+ public static function pre_option_blog_public( $value ) {
1228
+ if ( 'pre_option_blog_public' === current_filter() && RSA_IS_NETWORK && 'enforce' === self::get_network_mode() ) {
1229
+ $value = get_site_option( 'blog_public', 2 );
1230
+ }
1231
+
1232
+ // Check if constant disallowing restriction is defined.
1233
+ if ( defined( 'RSA_FORBID_RESTRICTION' ) && RSA_FORBID_RESTRICTION === true ) {
1234
+ $value = 1;
1235
+ }
1236
+
1237
+ // Check if constant forcing restriction is defined.
1238
+ if ( defined( 'RSA_FORCE_RESTRICTION' ) && RSA_FORCE_RESTRICTION === true ) {
1239
+ $value = 2;
1240
+ }
1241
+
1242
+ return $value;
1243
+ }
1244
+
1245
+ /**
1246
+ * Add settings link directing user to privacy page on plug-in page.
1247
+ *
1248
+ * @param array $links Array of links for plugin actions.
1249
  *
1250
  * @return array
1251
  */
1253
  $links[] = sprintf(
1254
  '<a href="options-%s.php">%s</a>',
1255
  esc_attr( self::$settings_page ),
1256
+ esc_html__( 'Settings', 'restricted-site-access' )
1257
  );
1258
 
1259
  return $links;
1260
  }
1261
 
1262
  /**
1263
+ * Activation of plugin: upgrades old versions, immediately sets privacy.
1264
+ *
1265
+ * @param boolean $network_active Whether the plugin network active.
1266
  */
1267
  public static function activation( $network_active ) {
1268
  if ( ! $network_active ) {
1271
  }
1272
 
1273
  /**
1274
+ * Restore privacy option to default value upon deactivating.
1275
+ *
1276
+ * @param boolean $network_active Whether the plugin network active.
1277
  */
1278
  public static function deactivation( $network_active ) {
1279
  if ( $network_active ) {
1282
  foreach ( $sites as $site ) {
1283
  switch_to_blog( $site->blog_id );
1284
 
1285
+ if ( 2 === (int) get_option( 'blog_public' ) ) {
1286
  update_option( 'blog_public', 1 );
1287
  }
1288
 
1289
  restore_current_blog();
1290
  }
1291
  } else {
1292
+ if ( 2 === (int) get_option( 'blog_public' ) ) {
1293
  update_option( 'blog_public', 1 );
1294
  }
1295
  }
1296
  }
1297
 
1298
  /**
1299
+ * Determine if plugin is network activated.
1300
+ *
1301
+ * @param string $plugin The plugin slug to check.
1302
  */
1303
  public static function is_network( $plugin ) {
1304
 
1305
+ $plugins = get_site_option( 'active_sitewide_plugins' );
1306
 
1307
  if ( is_multisite() && isset( $plugins[ $plugin ] ) ) {
1308
  return true;
1316
  * Check if a given ip is in a network.
1317
  * Source: https://gist.github.com/tott/7684443
1318
  *
1319
+ * @param string $ip IP to check in IPV4 format eg. 127.0.0.1.
1320
+ * @param string $range IP/CIDR netmask eg. 127.0.0.0/24, also 127.0.0.1 is accepted and /32 assumed.
1321
  * @return boolean true if the ip is in this range / false if not.
1322
  */
1323
  public static function ip_in_range( $ip, $range ) {
1324
+ if ( strpos( $range, '/' ) === false ) {
1325
  $range .= '/32';
1326
  }
1327
  // $range is in IP/CIDR format eg 127.0.0.1/24
1328
  list( $range, $netmask ) = explode( '/', $range, 2 );
1329
+ $range_decimal = ip2long( $range );
1330
+ $ip_decimal = ip2long( $ip );
1331
+ $wildcard_decimal = pow( 2, ( 32 - $netmask ) ) - 1;
1332
+ $netmask_decimal = ~ $wildcard_decimal;
1333
+ return ( ( $ip_decimal & $netmask_decimal ) === ( $range_decimal & $netmask_decimal ) );
1334
  }
1335
 
1336
  /**
1339
  * @return string
1340
  */
1341
  public static function get_client_ip_address() {
1342
+ $ip = '';
1343
  $headers = array(
1344
+ 'HTTP_CLIENT_IP',
1345
+ 'HTTP_X_FORWARDED_FOR',
1346
+ 'HTTP_X_FORWARDED',
1347
+ 'HTTP_X_CLUSTER_CLIENT_IP',
1348
+ 'HTTP_FORWARDED_FOR',
1349
+ 'HTTP_FORWARDED',
1350
+ 'REMOTE_ADDR',
1351
+ );
1352
  foreach ( $headers as $key ) {
1353
 
1354
  if ( ! isset( $_SERVER[ $key ] ) ) {
1355
  continue;
1356
  }
1357
 
1358
+ foreach ( explode(
1359
+ ',',
1360
+ sanitize_text_field( wp_unslash( $_SERVER[ $key ] ) )
1361
+ ) as $ip ) {
1362
+ $ip = trim( $ip ); // just to be safe.
1363
 
1364
+ if ( filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) !== false ) {
1365
  return $ip;
1366
  }
1367
  }
1371
  }
1372
  }
1373
 
1374
+ if ( ! defined( 'RSA_IS_NETWORK' ) ) {
1375
+ define( 'RSA_IS_NETWORK', Restricted_Site_Access::is_network( plugin_basename( __FILE__ ) ) );
1376
+ }
1377
 
1378
  Restricted_Site_Access::get_instance();
1379
 
1395
  foreach ( $sites as $site ) {
1396
  switch_to_blog( $site->blog_id );
1397
 
1398
+ if ( 2 === (int) get_option( 'blog_public' ) ) {
1399
  update_option( 'blog_public', 1 );
1400
  }
1401
+ delete_option( 'rsa_options' );
1402
 
1403
  restore_current_blog();
1404
  }
1405
  } else {
1406
+ if ( 2 === (int) get_option( 'blog_public' ) ) {
1407
  update_option( 'blog_public', 1 );
1408
  }
1409
+ delete_option( 'rsa_options' );
1410
  }
1411
  }
1412
 
1415
  if ( ! function_exists( 'inet_pton' ) ) :
1416
 
1417
  /**
1418
+ * Inet_pton is not included in PHP < 5.3 on Windows (WP requires PHP 5.2).
1419
  *
1420
+ * @param string $ip IP Address.
1421
  *
1422
  * @return array|string
1423
+ *
1424
+ * @codeCoverageIgnore
1425
  */
1426
  function inet_pton( $ip ) {
1427
  if ( strpos( $ip, '.' ) !== false ) {
1428
+ // ipv4.
1429
+ $ip = pack( 'N', ip2long( $ip ) );
1430
  } elseif ( strpos( $ip, ':' ) !== false ) {
1431
+ // ipv6.
1432
+ $ip = explode( ':', $ip );
1433
+ $res = str_pad( '', ( 4 * ( 8 - count( $ip ) ) ), '0000', STR_PAD_LEFT );
1434
  foreach ( $ip as $seg ) {
1435
  $res .= str_pad( $seg, 4, '0', STR_PAD_LEFT );
1436
  }
wp-cli.php CHANGED
@@ -1,5 +1,4 @@
1
- <?php
2
-
3
  /**
4
  * Manages the Restricted Site Access plugin settings.
5
  *
@@ -17,18 +16,21 @@ class Restricted_Site_Access_CLI extends WP_CLI_Command {
17
 
18
  /**
19
  * Stored command positional arguments.
 
20
  * @var array
21
  */
22
  private $args;
23
 
24
  /**
25
  * Stored command associative arguments.
 
26
  * @var array
27
  */
28
  private $assoc_args;
29
 
30
  /**
31
  * Whether the command is operating on the network or a single site.
 
32
  * @var bool
33
  */
34
  private $is_network = false;
@@ -116,10 +118,13 @@ class Restricted_Site_Access_CLI extends WP_CLI_Command {
116
  // Handles disabling the plugin.
117
  if ( 'disable' === $mode ) {
118
  if ( 2 !== $blog_public ) {
119
- WP_CLI::success( sprintf(
120
- __( '%s already not under restricted access.', 'restricted-site-access' ),
121
- $this->update_text()
122
- ) );
 
 
 
123
  return;
124
  }
125
 
@@ -129,8 +134,11 @@ class Restricted_Site_Access_CLI extends WP_CLI_Command {
129
  update_option( 'blog_public', 1 );
130
  }
131
 
132
- WP_CLI::success( sprintf(
133
- __( '%s restrictions disabled.', 'restricted-site-access' ) ),
 
 
 
134
  $this->update_text()
135
  );
136
  return; // Exit.
@@ -151,22 +159,25 @@ class Restricted_Site_Access_CLI extends WP_CLI_Command {
151
  if ( 'login' === $mode ) {
152
  $options['approach'] = 1;
153
 
154
- } else if ( 'redirect' === $mode ) {
155
  $url = WP_CLI\Utils\get_flag_value( $assoc_args, 'redirect' );
156
  if ( ! $url ) {
157
  WP_CLI::error( __( 'Redirect URL required.', 'restricted-site-access' ) );
158
  }
159
 
160
  // Let WP-CLI validate the status code.
161
- $options = array_merge( $options, array(
162
- 'approach' => 2,
163
- 'redirect_url' => $url,
164
- 'head_code' => WP_CLI\Utils\get_flag_value( $assoc_args, 'status-code' ),
165
- 'redirect_path' => (int) WP_CLI\Utils\get_flag_value( $assoc_args, 'same-path', 0 ),
166
- ) );
 
 
 
167
 
168
  // End redirect mode.
169
- } else if ( 'message' === $mode ) {
170
  // Set default for message text.
171
  $message = WP_CLI\Utils\get_flag_value( $assoc_args, 'text' );
172
  if ( ! $message ) {
@@ -176,7 +187,7 @@ class Restricted_Site_Access_CLI extends WP_CLI_Command {
176
  $options['message'] = $message;
177
 
178
  // End message mode.
179
- } else if ( 'page' === $mode ) {
180
  // Validate page ID passed.
181
  $page_id = (int) WP_CLI\Utils\get_flag_value( $assoc_args, 'page' );
182
  if ( ! $page_id ) {
@@ -197,32 +208,39 @@ class Restricted_Site_Access_CLI extends WP_CLI_Command {
197
  // Send update messages.
198
  $success_msg = '';
199
  switch ( $mode ) {
200
- case 'login' :
 
201
  $success_msg = __( '%s redirecting visitors to login.', 'restricted-site-access' );
202
  break;
203
- case 'redirect' :
204
  $success_msg = sprintf(
 
205
  __( '%%s redirecting visitors to "%s"', 'restricted-site-access' ),
206
  $updated_options['redirect_url']
207
  );
208
  break;
209
- case 'message' :
 
210
  $success_msg = __( '%s showing message to visitors.', 'restricted-site-access' );
211
  break;
212
- case 'page' :
213
  $success_msg = sprintf(
 
214
  __( '%%s showing visitors page "%s"', 'restricted-site-access' ),
215
  get_the_title( $page )
216
  );
217
  break;
218
- default :
 
219
  $success_msg = __( '%s settings updated.', 'restricted-site-access' );
220
  }
221
 
222
- WP_CLI::success( sprintf(
223
- $success_msg,
224
- $this->update_text()
225
- ) );
 
 
226
  }
227
 
228
  /**
@@ -261,16 +279,22 @@ class Restricted_Site_Access_CLI extends WP_CLI_Command {
261
 
262
  // Sets mode and shows message.
263
  if ( $new_mode === $current_mode ) {
264
- WP_CLI::warning( sprintf(
265
- __( 'Mode is already set to %s.', 'restricted-site-access' ),
266
- $current_mode
267
- ) );
 
 
 
268
  } else {
269
  update_site_option( 'rsa_mode', sanitize_key( $new_mode ) );
270
- WP_CLI::success( sprintf(
271
- __( 'Set network mode to %s.', 'restricted-site-access' ),
272
- $new_mode
273
- ) );
 
 
 
274
  }
275
  }
276
 
@@ -364,10 +388,13 @@ class Restricted_Site_Access_CLI extends WP_CLI_Command {
364
 
365
  if ( 0 === count( $new_ips ) ) {
366
  // Only show a warning as this may be an automated process.
367
- WP_CLI::warning( sprintf(
368
- __( 'Provided IPs are already on %s whitelist.', 'restricted-site-access' ),
369
- $this->update_text( false )
370
- ) );
 
 
 
371
  return;
372
  }
373
 
@@ -375,17 +402,23 @@ class Restricted_Site_Access_CLI extends WP_CLI_Command {
375
  $options['allowed'] = array_merge( $this->get_current_ips( false ), $new_ips );
376
  $new_options = $this->update_options( $options );
377
 
378
- WP_CLI::success( sprintf(
379
- __( 'Added %1$s to %2$s whitelist.', 'restricted-site-access' ),
380
- implode( ', ', $new_ips ),
381
- $this->update_text( false )
382
- ) );
383
-
384
- WP_CLI::debug( sprintf(
385
- __( 'Current %2$s whitelisted IPs are: %1$s', 'restricted-site-access' ),
386
- implode( ', ', $new_options['allowed'] ),
387
- $this->update_text( false )
388
- ) );
 
 
 
 
 
 
389
  }
390
 
391
  /**
@@ -425,28 +458,37 @@ class Restricted_Site_Access_CLI extends WP_CLI_Command {
425
 
426
  if ( 0 === count( $removed_ips ) ) {
427
  // Only show warning as this may be an automated process.
428
- WP_CLI::warning( sprintf(
429
- __( 'Provided IPs are not on %s whitelist.', 'restricted-site-access' ),
430
- $this->update_text( false )
431
- ) );
 
 
 
432
  return;
433
  }
434
 
435
  // Updates the option.
436
  $options['allowed'] = array_diff( $current_ips, $removed_ips );
437
- $new_options = $this->update_options( $options );
438
-
439
- WP_CLI::success( sprintf(
440
- __( 'Removed IPs %1$s from %2$s whitelist.', 'restricted-site-access' ),
441
- implode( ', ', $removed_ips ),
442
- $this->update_text( false )
443
- ) );
444
-
445
- WP_CLI::debug( sprintf(
446
- __( 'Current %2$s whitelisted IPs are: %1$s', 'restricted-site-access' ),
447
- implode( ', ', $new_options['allowed'] ),
448
- $this->update_text( false )
449
- ) );
 
 
 
 
 
 
450
  }
451
 
452
  /**
@@ -482,13 +524,16 @@ class Restricted_Site_Access_CLI extends WP_CLI_Command {
482
 
483
  // Updates the option.
484
  $options['allowed'] = $valid_ips;
485
- $new_options = $this->update_options( $options );
486
 
487
- WP_CLI::success( sprintf(
488
- __( 'Set %2$s IP whitelist to %1$s.', 'restricted-site-access' ),
489
- implode( ', ', $new_options['allowed'] ),
490
- $this->update_text( false )
491
- ) );
 
 
 
492
  }
493
 
494
  /**
@@ -544,7 +589,7 @@ class Restricted_Site_Access_CLI extends WP_CLI_Command {
544
  * @return array The newly set options.
545
  */
546
  private function update_options( $new_options ) {
547
- $options = wp_parse_args( $new_options, $this->get_options() );
548
  $sanitized_options = Restricted_Site_Access::sanitize_options( $options );
549
  if ( $this->is_network ) {
550
  update_site_option( 'rsa_options', $sanitized_options );
1
+ <?php // phpcs:disable WordPress.Files.FileName
 
2
  /**
3
  * Manages the Restricted Site Access plugin settings.
4
  *
16
 
17
  /**
18
  * Stored command positional arguments.
19
+ *
20
  * @var array
21
  */
22
  private $args;
23
 
24
  /**
25
  * Stored command associative arguments.
26
+ *
27
  * @var array
28
  */
29
  private $assoc_args;
30
 
31
  /**
32
  * Whether the command is operating on the network or a single site.
33
+ *
34
  * @var bool
35
  */
36
  private $is_network = false;
118
  // Handles disabling the plugin.
119
  if ( 'disable' === $mode ) {
120
  if ( 2 !== $blog_public ) {
121
+ WP_CLI::success(
122
+ sprintf(
123
+ /* translators: %s: What the user is updating: "Site" or "Network". */
124
+ __( '%s already not under restricted access.', 'restricted-site-access' ),
125
+ $this->update_text()
126
+ )
127
+ );
128
  return;
129
  }
130
 
134
  update_option( 'blog_public', 1 );
135
  }
136
 
137
+ WP_CLI::success(
138
+ sprintf(
139
+ /* translators: %s: What the user is updating: "Site" or "Network". */
140
+ __( '%s restrictions disabled.', 'restricted-site-access' )
141
+ ),
142
  $this->update_text()
143
  );
144
  return; // Exit.
159
  if ( 'login' === $mode ) {
160
  $options['approach'] = 1;
161
 
162
+ } elseif ( 'redirect' === $mode ) {
163
  $url = WP_CLI\Utils\get_flag_value( $assoc_args, 'redirect' );
164
  if ( ! $url ) {
165
  WP_CLI::error( __( 'Redirect URL required.', 'restricted-site-access' ) );
166
  }
167
 
168
  // Let WP-CLI validate the status code.
169
+ $options = array_merge(
170
+ $options,
171
+ array(
172
+ 'approach' => 2,
173
+ 'redirect_url' => $url,
174
+ 'head_code' => WP_CLI\Utils\get_flag_value( $assoc_args, 'status-code' ),
175
+ 'redirect_path' => (int) WP_CLI\Utils\get_flag_value( $assoc_args, 'same-path', 0 ),
176
+ )
177
+ );
178
 
179
  // End redirect mode.
180
+ } elseif ( 'message' === $mode ) {
181
  // Set default for message text.
182
  $message = WP_CLI\Utils\get_flag_value( $assoc_args, 'text' );
183
  if ( ! $message ) {
187
  $options['message'] = $message;
188
 
189
  // End message mode.
190
+ } elseif ( 'page' === $mode ) {
191
  // Validate page ID passed.
192
  $page_id = (int) WP_CLI\Utils\get_flag_value( $assoc_args, 'page' );
193
  if ( ! $page_id ) {
208
  // Send update messages.
209
  $success_msg = '';
210
  switch ( $mode ) {
211
+ case 'login':
212
+ /* translators: %s: Context: "Site" or "Network". */
213
  $success_msg = __( '%s redirecting visitors to login.', 'restricted-site-access' );
214
  break;
215
+ case 'redirect':
216
  $success_msg = sprintf(
217
+ /* translators: %s: Context: "Site" or "Network". %s: Redirect URL. */
218
  __( '%%s redirecting visitors to "%s"', 'restricted-site-access' ),
219
  $updated_options['redirect_url']
220
  );
221
  break;
222
+ case 'message':
223
+ /* translators: %s: Context: "Site" or "Network". */
224
  $success_msg = __( '%s showing message to visitors.', 'restricted-site-access' );
225
  break;
226
+ case 'page':
227
  $success_msg = sprintf(
228
+ /* translators: %s: "Site" or "Network". %s: Page title. */
229
  __( '%%s showing visitors page "%s"', 'restricted-site-access' ),
230
  get_the_title( $page )
231
  );
232
  break;
233
+ default:
234
+ /* translators: %s: What the user is updating: "Site" or "Network". */
235
  $success_msg = __( '%s settings updated.', 'restricted-site-access' );
236
  }
237
 
238
+ WP_CLI::success(
239
+ sprintf(
240
+ $success_msg,
241
+ $this->update_text()
242
+ )
243
+ );
244
  }
245
 
246
  /**
279
 
280
  // Sets mode and shows message.
281
  if ( $new_mode === $current_mode ) {
282
+ WP_CLI::warning(
283
+ sprintf(
284
+ /* translators: %s: Network mode. */
285
+ __( 'Mode is already set to %s.', 'restricted-site-access' ),
286
+ $current_mode
287
+ )
288
+ );
289
  } else {
290
  update_site_option( 'rsa_mode', sanitize_key( $new_mode ) );
291
+ WP_CLI::success(
292
+ sprintf(
293
+ /* translators: %s: Network mode. */
294
+ __( 'Set network mode to %s.', 'restricted-site-access' ),
295
+ $new_mode
296
+ )
297
+ );
298
  }
299
  }
300
 
388
 
389
  if ( 0 === count( $new_ips ) ) {
390
  // Only show a warning as this may be an automated process.
391
+ WP_CLI::warning(
392
+ sprintf(
393
+ /* translators: %s: Context: "Site" or "Network". */
394
+ __( 'Provided IPs are already on %s whitelist.', 'restricted-site-access' ),
395
+ $this->update_text( false )
396
+ )
397
+ );
398
  return;
399
  }
400
 
402
  $options['allowed'] = array_merge( $this->get_current_ips( false ), $new_ips );
403
  $new_options = $this->update_options( $options );
404
 
405
+ WP_CLI::success(
406
+ sprintf(
407
+ /* translators: %1$s: IP addresses. %2$s: Context: "Site" or "Network". */
408
+ __( 'Added %1$s to %2$s whitelist.', 'restricted-site-access' ),
409
+ implode( ', ', $new_ips ),
410
+ $this->update_text( false )
411
+ )
412
+ );
413
+
414
+ WP_CLI::debug(
415
+ sprintf(
416
+ /* translators: %2$s: IP addresses. %1$s: Context: "Site" or "Network". */
417
+ __( 'Current %2$s whitelisted IPs are: %1$s', 'restricted-site-access' ),
418
+ implode( ', ', $new_options['allowed'] ),
419
+ $this->update_text( false )
420
+ )
421
+ );
422
  }
423
 
424
  /**
458
 
459
  if ( 0 === count( $removed_ips ) ) {
460
  // Only show warning as this may be an automated process.
461
+ WP_CLI::warning(
462
+ sprintf(
463
+ /* translators: %s: Context: "Site" or "Network". */
464
+ __( 'Provided IPs are not on %s whitelist.', 'restricted-site-access' ),
465
+ $this->update_text( false )
466
+ )
467
+ );
468
  return;
469
  }
470
 
471
  // Updates the option.
472
  $options['allowed'] = array_diff( $current_ips, $removed_ips );
473
+ $new_options = $this->update_options( $options );
474
+
475
+ WP_CLI::success(
476
+ sprintf(
477
+ /* translators: %1$s: IP addresses. %2$s: Context: "Site" or "Network". */
478
+ __( 'Removed IPs %1$s from %2$s whitelist.', 'restricted-site-access' ),
479
+ implode( ', ', $removed_ips ),
480
+ $this->update_text( false )
481
+ )
482
+ );
483
+
484
+ WP_CLI::debug(
485
+ sprintf(
486
+ /* translators: %2$s: IP addresses. %1$s: Context: "Site" or "Network". */
487
+ __( 'Current %2$s whitelisted IPs are: %1$s', 'restricted-site-access' ),
488
+ implode( ', ', $new_options['allowed'] ),
489
+ $this->update_text( false )
490
+ )
491
+ );
492
  }
493
 
494
  /**
524
 
525
  // Updates the option.
526
  $options['allowed'] = $valid_ips;
527
+ $new_options = $this->update_options( $options );
528
 
529
+ WP_CLI::success(
530
+ sprintf(
531
+ /* translators: %2$s: IPs to whitelist, %1$s: Context: "Site" or "Network". */
532
+ __( 'Set %2$s IP whitelist to %1$s.', 'restricted-site-access' ),
533
+ implode( ', ', $new_options['allowed'] ),
534
+ $this->update_text( false )
535
+ )
536
+ );
537
  }
538
 
539
  /**
589
  * @return array The newly set options.
590
  */
591
  private function update_options( $new_options ) {
592
+ $options = wp_parse_args( $new_options, $this->get_options() );
593
  $sanitized_options = Restricted_Site_Access::sanitize_options( $options );
594
  if ( $this->is_network ) {
595
  update_site_option( 'rsa_options', $sanitized_options );