PluginProbe
s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions / 260917
s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions v260917
260917 260913 260909 260829 260814 260805 110710 110731 110812 110815 110912 110913 110915 110926 110927 111002 111003 111011 111017 111029 111105 111206 111216 111220 120213 All 189 releases
s2member / src / includes / menu-pages / res-ops.inc.php

res-ops.inc.php in s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions 260917, at src/includes/menu-pages/res-ops.inc.php

698 lines 57.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // @codingStandardsIgnoreFile
3 /**
4 * Menu page for the s2Member plugin (Restriction Options page).
5 *
6 * Copyright: © 2009-2011
7 * {@link http://websharks-inc.com/ WebSharks, Inc.}
8 * (coded in the USA)
9 *
10 * Released under the terms of the GNU General Public License.
11 * You should have received a copy of the GNU General Public License,
12 * along with this software. In the main directory, see: /licensing/
13 * If not, see: {@link http://www.gnu.org/licenses/}.
14 *
15 * @package s2Member\Menu_Pages
16 * @since 3.0
17 */
18 if(!defined('WPINC')) // MUST have WordPress.
19 exit ("Do not access this file directly.");
20
21 if(!class_exists("c_ws_plugin__s2member_menu_page_res_ops"))
22 {
23 /**
24 * Menu page for the s2Member plugin (Restriction Options page).
25 *
26 * @package s2Member\Menu_Pages
27 * @since 110531
28 */
29 class c_ws_plugin__s2member_menu_page_res_ops
30 {
31 public function __construct()
32 {
33 echo '<div class="wrap ws-menu-page">'."\n";
34
35 echo '<div class="wp-header-end"></div>'."\n";
36
37 echo '<div class="ws-menu-page-toolbox">'."\n";
38 c_ws_plugin__s2member_menu_pages_tb::display();
39 echo '</div>'."\n";
40
41 echo '<h2>Restriction Options</h2>'."\n";
42
43 echo '<table class="ws-menu-page-table">'."\n";
44 echo '<tbody class="ws-menu-page-table-tbody">'."\n";
45 echo '<tr class="ws-menu-page-table-tr">'."\n";
46 echo '<td class="ws-menu-page-table-l">'."\n";
47
48 do_action("ws_plugin__s2member_during_res_ops_page_before_left_sections_form", get_defined_vars());
49
50 echo '<form method="post" name="ws_plugin__s2member_options_form" id="ws-plugin--s2member-options-form" autocomplete="off">'."\n";
51 echo '<input type="hidden" name="ws_plugin__s2member_options_save" id="ws-plugin--s2member-options-save" value="'.esc_attr(wp_create_nonce("ws-plugin--s2member-options-save")).'" />'."\n";
52 echo '<input type="hidden" name="ws_plugin__s2member_configured" id="ws-plugin--s2member-configured" value="1" />'."\n";
53
54 do_action("ws_plugin__s2member_during_res_ops_page_before_left_sections", get_defined_vars());
55
56 if(apply_filters("ws_plugin__s2member_during_res_ops_page_during_left_sections_display_post_level_access", TRUE, get_defined_vars()))
57 {
58 do_action("ws_plugin__s2member_during_res_ops_page_during_left_sections_before_post_level_access", get_defined_vars());
59
60 echo '<div class="ws-menu-page-group" title="Post Access Restrictions">'."\n";
61
62 echo '<div class="ws-menu-page-section ws-plugin--s2member-post-level-access-section">'."\n";
63 echo '<h3>Post Level Access Restrictions (optional)</h3>'."\n";
64 echo '<p>Here you can specify Posts that are restricted to certain Membership Access Levels. s2Member also supports Custom <a href="https://s2member.com/r/wordpress-codex-post-types/" target="_blank" rel="external">Post Types</a> here. If you have a theme or plugin installed, which has enabled Custom Post Types <em>(i.e., Music/Videos or something else)</em>, you can put the IDs for those Posts here.</p>'."\n";
65 echo '<p><strong>What do I enter?</strong> Post IDs in comma-delimited format. Example: <code>1,2,3,84,8,21</code>. Or, you can type: <code>all</code> <em>(to protect all Posts, of any type)</em>. You can also include all Post IDs of a specific <a href="https://s2member.com/r/wordpress-codex-post-types/" target="_blank" rel="external">Post Type</a>. e.g., <code>1,2,3,all-newspapers</code> <em>(protects several Post IDs, and all Posts of type: <code>newspaper</code>)</em>.</p>'."\n";
66 echo '<p><em><strong>Note:</strong> Protecting individual Posts, <strong>only</strong> protects the Permalinks for those Posts. It is still possible for excerpts of protected content to be seen in search results generated by WordPress, feeds, and Archive views; such as your Home Page, inside a Category listing, or through other queries formulated by your theme. This is the intended functionality. Excerpts are a great way to "tease" public visitors. In other words, public visitors may have access to excerpts introduced by your theme, but any attempt to view the full Post (i.e., the Permalink) will result in an automatic redirect to your Membership Options Page; requiring registration.</em></p>'."\n";
67 echo '<p><em><strong>Note:</strong> If you would like to protect many Posts at once (including Archive views), you can use Category Level Restrictions, Tag Level Restrictions, or have a look down below at s2Member\'s options for "Alternative View Protection", which deals with search results, as well as feeds.</em></p>'."\n";
68 echo ((!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site()) && empty($GLOBALS["WS_PLUGIN__"]["wp_show_ids"])) ? '<p><em><strong>Tip:</strong> Can\'t find your Post IDs? Get <a href="https://s2member.com/r/wordpress-org-wp-show-ids/" target="_blank" rel="external">WP Show IDs</a>.</em></p>'."\n" : '';
69 do_action("ws_plugin__s2member_during_res_ops_page_during_left_sections_during_post_level_access", get_defined_vars());
70
71 echo '<table class="form-table">'."\n";
72 echo '<tbody>'."\n";
73
74 for($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
75 {
76 echo '<tr>'."\n";
77
78 echo '<th>'."\n";
79 echo '<label for="ws-plugin--s2member-level'.$n.'-posts">'."\n";
80 echo ($n === $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]) ? 'Posts That Require Highest Level #'.$n.':'."\n" : 'Posts That Require Level #'.$n.' Or Higher:'."\n";
81 echo '</label>'."\n";
82 echo '</th>'."\n";
83
84 echo '</tr>'."\n";
85 echo '<tr>'."\n";
86
87 echo '<td>'."\n";
88 echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_level'.$n.'_posts" id="ws-plugin--s2member-level'.$n.'-posts" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level".$n."_posts"]).'" />'."\n";
89 echo '</td>'."\n";
90
91 echo '</tr>'."\n";
92 }
93 echo '</tbody>'."\n";
94 echo '</table>'."\n";
95 echo '</div>'."\n";
96
97 echo '</div>'."\n";
98
99 do_action("ws_plugin__s2member_during_res_ops_page_during_left_sections_after_post_level_access", get_defined_vars());
100 }
101 if(apply_filters("ws_plugin__s2member_during_res_ops_page_during_left_sections_display_page_level_access", TRUE, get_defined_vars()))
102 {
103 do_action("ws_plugin__s2member_during_res_ops_page_during_left_sections_before_page_level_access", get_defined_vars());
104
105 echo '<div class="ws-menu-page-group" title="Page Access Restrictions">'."\n";
106
107 echo '<div class="ws-menu-page-section ws-plugin--s2member-page-level-access-section">'."\n";
108 echo '<h3>Page Level Access Restrictions (optional)</h3>'."\n";
109 echo '<p>Here you can specify Pages that are restricted to certain Membership Access Levels.</p>'."\n";
110 echo '<p><strong>What do I enter?</strong> Page IDs in comma-delimited format. Example: <code>1,2,3,34,8,21</code>. Or, you can type: <code>all</code> <em>(to protect all Pages)</em>.</p>'."\n";
111 echo ((!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site()) && empty($GLOBALS["WS_PLUGIN__"]["wp_show_ids"])) ? '<p><em><strong>Tip:</strong> Can\'t find your Page IDs? Get <a href="https://s2member.com/r/wordpress-org-wp-show-ids/" target="_blank" rel="external">WP Show IDs</a>.</em></p>'."\n" : '';
112 do_action("ws_plugin__s2member_during_res_ops_page_during_left_sections_during_page_level_access", get_defined_vars());
113
114 echo '<table class="form-table">'."\n";
115 echo '<tbody>'."\n";
116
117 for($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
118 {
119 echo '<tr>'."\n";
120
121 echo '<th>'."\n";
122 echo '<label for="ws-plugin--s2member-level'.$n.'-pages">'."\n";
123 echo ($n === $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]) ? 'Pages That Require Highest Level #'.$n.':'."\n" : 'Pages That Require Level #'.$n.' Or Higher:'."\n";
124 echo '</label>'."\n";
125 echo '</th>'."\n";
126
127 echo '</tr>'."\n";
128 echo '<tr>'."\n";
129
130 echo '<td>'."\n";
131 echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_level'.$n.'_pages" id="ws-plugin--s2member-level'.$n.'-pages" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level".$n."_pages"]).'" />'."\n";
132 echo '</td>'."\n";
133
134 echo '</tr>'."\n";
135 }
136 echo '</tbody>'."\n";
137 echo '</table>'."\n";
138 echo '</div>'."\n";
139
140 echo '</div>'."\n";
141
142 do_action("ws_plugin__s2member_during_res_ops_page_during_left_sections_after_page_level_access", get_defined_vars());
143 }
144 if(apply_filters("ws_plugin__s2member_during_res_ops_page_during_left_sections_display_tag_level_access", TRUE, get_defined_vars()))
145 {
146 do_action("ws_plugin__s2member_during_res_ops_page_during_left_sections_before_tag_level_access", get_defined_vars());
147
148 echo '<div class="ws-menu-page-group" title="Tag Access Restrictions">'."\n";
149
150 echo '<div class="ws-menu-page-section ws-plugin--s2member-tag-level-access-section">'."\n";
151 echo '<h3>Tag Level Access Restrictions (optional)</h3>'."\n";
152 echo '<p>Here you can specify Tags that are restricted to certain Membership Access Levels. This is similar to Category Level Access. When you restrict access to a Tag Archive, it also restricts access to any Post having that Tag; even if a Post has other Tags. <strong>Tip:</strong> Tags can be applied to any Post, without affecting your Category structure at all. If you\'d like to use Tags with Pages get the <a href="https://s2member.com/r/wordpress-org-tag-pages/" target="_blank" rel="external">Tag Pages</a> plugin.</p>'."\n";
153 echo '<p><strong>What do I enter?</strong> Tags in comma-delimited format. Example: <code>members, members only, free subscribers, premium</code>. Or, you can type: <code>all</code> <em>(to protect all Tags)</em>. <strong>Note:</strong> tags are caSe sensitive. The Tag <code>members only</code> is not the same as <code>Members Only</code>.</p>'."\n";
154 do_action("ws_plugin__s2member_during_res_ops_page_during_left_sections_during_tag_level_access", get_defined_vars());
155
156 echo '<table class="form-table">'."\n";
157 echo '<tbody>'."\n";
158
159 for($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
160 {
161 echo '<tr>'."\n";
162
163 echo '<th>'."\n";
164 echo '<label for="ws-plugin--s2member-level'.$n.'-ptags">'."\n";
165 echo ($n === $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]) ? 'Tags That Require Highest Level #'.$n.':'."\n" : 'Tags That Require Level #'.$n.' Or Higher:'."\n";
166 echo '</label>'."\n";
167 echo '</th>'."\n";
168
169 echo '</tr>'."\n";
170 echo '<tr>'."\n";
171
172 echo '<td>'."\n";
173 echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_level'.$n.'_ptags" id="ws-plugin--s2member-level'.$n.'-ptags" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level".$n."_ptags"]).'" />'."\n";
174 echo '</td>'."\n";
175
176 echo '</tr>'."\n";
177 }
178 echo '</tbody>'."\n";
179 echo '</table>'."\n";
180 echo '</div>'."\n";
181
182 echo '</div>'."\n";
183
184 do_action("ws_plugin__s2member_during_res_ops_page_during_left_sections_after_tag_level_access", get_defined_vars());
185 }
186 if(apply_filters("ws_plugin__s2member_during_res_ops_page_during_left_sections_display_category_level_access", TRUE, get_defined_vars()))
187 {
188 do_action("ws_plugin__s2member_during_res_ops_page_during_left_sections_before_category_level_access", get_defined_vars());
189
190 echo '<div class="ws-menu-page-group" title="Category Access Restrictions">'."\n";
191
192 echo '<div class="ws-menu-page-section ws-plugin--s2member-category-level-access-section">'."\n";
193 echo '<h3>Category Level Access Restrictions (optional)</h3>'."\n";
194 echo '<p>Here you can specify Categories that are restricted to certain Membership Access Levels. Category restrictions are a bit more complex. When you restrict access to a Category, it also restricts access to any child Categories it may have <em>(aka: sub-Categories)</em>. In other words, restricting a Category protects a Category Archive, all of its child Category Archives, and any Posts contained within the Category or its child Categories. This is a very powerful form of protection, so please be careful. It\'s very easy to protect too much content by accident.</p>'."\n";
195 echo '<p><strong>What do I enter?</strong> Category IDs in comma-delimited format. Example: <code>1,2,3,34,8,21</code>. Or, you can type: <code>all</code> <em>(to protect all Categories)</em>.</p>'."\n";
196 echo ((!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site()) && empty($GLOBALS["WS_PLUGIN__"]["wp_show_ids"])) ? '<p><em><strong>Tip:</strong> Can\'t find your Category IDs? Get <a href="https://s2member.com/r/wordpress-org-wp-show-ids/" target="_blank" rel="external">WP Show IDs</a>.</em></p>'."\n" : '';
197 do_action("ws_plugin__s2member_during_res_ops_page_during_left_sections_during_category_level_access", get_defined_vars());
198
199 echo '<table class="form-table">'."\n";
200 echo '<tbody>'."\n";
201
202 for($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
203 {
204 echo '<tr>'."\n";
205
206 echo '<th>'."\n";
207 echo '<label for="ws-plugin--s2member-level'.$n.'-catgs">'."\n";
208 echo ($n === $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]) ? 'Categories That Require Highest Level #'.$n.':'."\n" : 'Categories That Require Level #'.$n.' Or Higher:'."\n";
209 echo '</label>'."\n";
210 echo '</th>'."\n";
211
212 echo '</tr>'."\n";
213 echo '<tr>'."\n";
214
215 echo '<td>'."\n";
216 echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_level'.$n.'_catgs" id="ws-plugin--s2member-level'.$n.'-catgs" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level".$n."_catgs"]).'" />'."\n";
217 echo '</td>'."\n";
218
219 echo '</tr>'."\n";
220
221 echo '<tr>'."\n";
222 }
223 echo '</tbody>'."\n";
224 echo '</table>'."\n";
225 echo '</div>'."\n";
226
227 echo '</div>'."\n";
228
229 do_action("ws_plugin__s2member_during_res_ops_page_during_left_sections_after_category_level_access", get_defined_vars());
230 }
231 if(apply_filters("ws_plugin__s2member_during_res_ops_page_during_left_sections_display_uri_level_access", TRUE, get_defined_vars()))
232 {
233 do_action("ws_plugin__s2member_during_res_ops_page_during_left_sections_before_uri_level_access", get_defined_vars());
234
235 echo '<div class="ws-menu-page-group" title="URI Restrictions (typical w/BuddyPress)">'."\n";
236
237 echo '<div class="ws-menu-page-section ws-plugin--s2member-uri-level-access-section">'."\n";
238 echo '<h3>URI Level Access Restrictions (optional)</h3>'."\n";
239 echo '<p>Here you can specify URIs (or word fragments found in URIs) that are restricted to certain Membership Access Levels. Control over URIs is a little more complex. This section is intended for advanced webmasters only. A <code>REQUEST_URI</code> is the portion of a <code>URL</code> that comes immediately after the domain. This is a URL <code>http://www.example.com/path/to/file.php</code>, and this is the URI: <code>/path/to/file.php</code>. In other words, a <code>REQUEST_URI</code> is the full path to a real <em>(or virtual)</em> directory and/or file on your domain. s2Member can match a URI in whole, or in part.</p>'."\n";
240 echo '<p><strong>What do I enter?</strong> In the fields below, you can provide a list of URIs <strong>(one per line; i.e., line-delimited)</strong> that should be off-limits based on Membership Level. You can also use word fragments instead of a full URI. If a word fragment is found anywhere in the URI, it will be protected. Wildcards and other regex patterns are <em>not</em> supported here, and therefore you don\'t need to escape special characters or anything. Please note, depending on your caSe configuration option (as seen below), your exclusion patterns might be caSe sensitive. If you choose to make these caSe sensitive, you must be specific. The word fragment <code>some-path/</code> would not match a URI that contains <code>some-Path/</code>.</p>'."\n";
241 echo '<p><em><strong>Replacement Codes:</strong> A few <a href="#" onclick="alert(\'URI Replacement Codes:\\n\\n%%current_user_login%% = The current User\\\'s Username, lowercase (deprecated, please use %%current_user_nicename%%).\\n\\n%%current_user_nicename%% = The current User\\\'s Nicename in lowercase format (i.e., a cleaner version of the username for URLs; recommended for best compatibility).\\n\\n%%current_user_id%% = The current User\\\'s ID.\\n\\n%%current_user_level%% = The current User\\\'s s2Member Level.\\n\\n%%current_user_role%% = The current User\\\'s WordPress Role.'.((!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site()) ? '\\n\\n%%current_user_ccaps%% = The current User\\\'s Custom Capabilities.' : '').'\\n\\n%%current_user_logins%% = Number of times the current User has logged in.\\n\\nFor example, if you\\\'re using BuddyPress, and want to protect BuddyPress Groups, you could add URI protection, like this: /members/%%current_user_nicename%%/groups/\'); return false;">Replacement Codes</a> are also supported here.</em></p>'."\n";
242 echo '<p><em><strong>BuddyPress (and similar):</strong> URI Restrictions work great with plugins like BuddyPress that add new areas to your site (where those new areas are not necessarily a Post/Page/Tag/Category). In other words, anytime you\'d like to protect a specific feature offered by BuddyPress (or other plugins), you\'ll need to nail-down specific word fragments found in the URIs associated with those areas. For instance, with BuddyPress you might have something like: [<a href="#" onclick="alert(\'/members/\\n/groups/\\n/blogs/\\n/activity/\\n/messages/\\n/profile/\\n/friends/\\n/settings/\'); return false;">click for example</a>].</em></p>'."\n";
243 do_action("ws_plugin__s2member_during_res_ops_page_during_left_sections_during_uri_level_access", get_defined_vars());
244
245 echo '<table class="form-table">'."\n";
246 echo '<tbody>'."\n";
247 echo '<tr>'."\n";
248
249 echo '<th>'."\n";
250 echo '<label for="ws-plugin--s2member-ruris-case-sensitive">'."\n";
251 echo 'URI Restrictions caSe Sensitive?'."\n";
252 echo '</label>'."\n";
253 echo '</th>'."\n";
254
255 echo '</tr>'."\n";
256 echo '<tr>'."\n";
257
258 echo '<td>'."\n";
259 echo '<select name="ws_plugin__s2member_ruris_case_sensitive" id="ws-plugin--s2member-ruris-case-sensitive">'."\n";
260 echo '<option value="0"'.((!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["ruris_case_sensitive"]) ? ' selected="selected"' : '').'>No (caSe-insensitive; recommended)</option>'."\n";
261 echo '<option value="1"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["ruris_case_sensitive"]) ? ' selected="selected"' : '').'>Yes (caSe-sensitive; e.g., /some-path/ is not the same as /some-Path/)</option>'."\n";
262 echo '</select><br />'."\n";
263 echo 'Recommended setting: (<code>No; caSe-insensitive</code>)'."\n";
264 echo '</td>'."\n";
265
266 echo '</tr>'."\n";
267 echo '</tbody>'."\n";
268 echo '</table>'."\n";
269
270 echo '<div class="ws-menu-page-hr"></div>'."\n";
271
272 echo '<table class="form-table">'."\n";
273 echo '<tbody>'."\n";
274
275 for($n = 0; $n <= $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]; $n++)
276 {
277 echo '<tr>'."\n";
278
279 echo '<th>'."\n";
280 echo '<label for="ws-plugin--s2member-level'.$n.'-ruris">'."\n";
281 echo ($n === $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["levels"]) ? 'URIs That Require Highest Level #'.$n.':'."\n" : 'URIs That Require Level #'.$n.' Or Higher:'."\n";
282 echo '</label>'."\n";
283 echo '</th>'."\n";
284
285 echo '</tr>'."\n";
286 echo '<tr>'."\n";
287
288 echo '<td>'."\n";
289 echo '<textarea name="ws_plugin__s2member_level'.$n.'_ruris" id="ws-plugin--s2member-level'.$n.'-ruris" rows="3" wrap="off" spellcheck="false">'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level".$n."_ruris"]).'</textarea>'."\n";
290 echo '</td>'."\n";
291
292 echo '</tr>'."\n";
293 }
294 echo '</tbody>'."\n";
295 echo '</table>'."\n";
296 echo '</div>'."\n";
297
298 echo '</div>'."\n";
299
300 do_action("ws_plugin__s2member_during_res_ops_page_during_left_sections_after_uri_level_access", get_defined_vars());
301 }
302 if(apply_filters("ws_plugin__s2member_during_res_ops_page_during_left_sections_display_query_level_access", TRUE, get_defined_vars()))
303 {
304 do_action("ws_plugin__s2member_during_res_ops_page_during_left_sections_before_query_level_access", get_defined_vars());
305
306 echo '<div class="ws-menu-page-group" title="Alternative View Protection (feeds, search results, etc.)">'."\n";
307
308 echo '<div class="ws-menu-page-section ws-plugin--s2member-query-level-access-section">'."\n";
309 echo '<h3>Alternative View Protection (optional)</h3>'."\n";
310 echo '<p>s2Member protects Categories, Tags, Posts, Pages, Files, URIs &amp; more. However, even with all of those security restrictions, it\'s still possible for protected content excerpts to be seen through XML feeds, in search results generated by WordPress; and/or (depending on your theme), possibly in other Archive views; which might include things like: Posts by Author, Posts by Date, a list of featured items formulated by your theme; or even through other widgets/plugins adding functionality to your site. We refer to all of these collectively, as "Alternative Views".</p>'."\n";
311 echo '<p>Using the options below, you can tell s2Member to protect some (or all) of these "Alternative Views" by filtering WordPress database queries for you. s2Member can automatically hide protected content that is not available to the current User/Member. In other words, s2Member is capable of pre-filtering all database queries so that excerpts of protected content will not be allowed to slip through.</p>'."\n";
312 do_action("ws_plugin__s2member_during_res_ops_page_during_left_sections_during_uri_level_access", get_defined_vars());
313
314 echo '<table class="form-table">'."\n";
315 echo '<tbody>'."\n";
316 echo '<tr>'."\n";
317
318 echo '<th>'."\n";
319 echo '<label for="ws-plugin--s2member-filter-wp-query">'."\n";
320 echo 'Protect Alternative Views?'."\n";
321 echo '</label>'."\n";
322 echo '</th>'."\n";
323
324 echo '</tr>'."\n";
325 echo '<tr>'."\n";
326
327 echo '<td>'."\n";
328 echo '<div class="ws-menu-page-scrollbox" style="height:105px;">'."\n";
329 echo '<input type="hidden" name="ws_plugin__s2member_filter_wp_query[]" value="update-signal" />'."\n";
330 foreach(array("all" => "<strong>Filter ALL WordPress queries</strong>; protecting all Alternative Views.", "searches" => "&#9492;&#9472; Searches (hide protected content in search results)", "feeds" => "&#9492;&#9472; Feeds (hide protected content in standard XML/RSS/ATOM feeds)", "comment-feeds" => "&#9492;&#9472; Comment Feeds (hide comments associated with protected content, in comment feeds)", "nav-menus" => "&#9492;&#9472; Nav Menus (hide protected content in menus generated with <em>WordPress → Appearance → Menus</em>)", "pages" => "&#9492;&#9472; Pages (hide protected content in widgets that list Pages)") as $ws_plugin__s2member_temp_s_value => $ws_plugin__s2member_temp_s_label)
331 echo '<input type="checkbox" name="ws_plugin__s2member_filter_wp_query[]" id="ws-plugin--s2member-filter-wp-query-'.esc_attr(preg_replace("/[^a-z0-9_\-]/", "-", $ws_plugin__s2member_temp_s_value)).'" value="'.esc_attr($ws_plugin__s2member_temp_s_value).'"'.((in_array($ws_plugin__s2member_temp_s_value, $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["filter_wp_query"])) ? ' checked="checked"' : '').' /> <label for="ws-plugin--s2member-filter-wp-query-'.esc_attr(preg_replace("/[^a-z0-9_\-]/", "-", $ws_plugin__s2member_temp_s_value)).'">'.$ws_plugin__s2member_temp_s_label.'</label><br />'."\n";
332 echo '</div>'."\n";
333 echo '<strong>Attn Developers:</strong> Filters can be suppressed dynamically using this technique:<br />'."\n";
334 echo '<code><a href="https://s2member.com/r/wordpress-codex-query_posts/" target="_blank" rel="external">query_posts</a>("suppress_filters=true");</code><br />'."\n";
335 echo '<code><a href="https://s2member.com/r/wordpress-codex-get_posts/" target="_blank" rel="external">get_posts</a>()</code> auto-suppresses filters.<br />'."\n";
336 echo 'Also see <a href="https://s2member.com/r/s2member-codex-attach_s2member_query_filters/" target="_blank" rel="external">this article</a> in the s2Member Codex.'."\n";
337 echo '</td>'."\n";
338
339 echo '</tr>'."\n";
340 echo '</tbody>'."\n";
341 echo '</table>'."\n";
342 echo '</div>'."\n";
343
344 echo '</div>'."\n";
345
346 do_action("ws_plugin__s2member_during_res_ops_page_during_left_sections_after_query_level_access", get_defined_vars());
347 }
348 if(apply_filters("ws_plugin__s2member_during_res_ops_page_during_left_sections_display_conditionals", (!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site()), get_defined_vars()))
349 {
350 do_action("ws_plugin__s2member_during_res_ops_page_during_left_sections_before_conditionals", get_defined_vars());
351
352 echo '<div class="ws-menu-page-group" title="Simple Shortcode Conditionals (protect only parts of your content)">'."\n";
353
354 echo '<div class="ws-menu-page-section ws-plugin--s2member-conditionals-section">'."\n";
355 echo '<h3>Simple Shortcode Conditionals (optional; to protect only parts of your content)</h3>'."\n";
356 echo '<p>s2Member makes it very easy to protect entire Posts, Pages, Categories, Tags, URIs, etc. This can be accomplished here in your WordPress Dashboard, using one of the many tools made available on this page. Or, from your Post/Page editing station in WordPress. We consider this to be point-and-click functionality—very easy. However, s2Member also makes it possible for you to protect "parts" of a Post or Page. You can even get creative about what you display to certain Users/Members, based upon your own custom criteria. s2Member\'s Simple Shortcode Conditionals are the key to accomplishing this.</p>'."\n";
357 echo '<p>Please see this KB article to learn more about <code>[s2If /]</code>: <a href="http://www.s2member.com/kb/simple-shortcode-conditionals/" target="_blank" rel="external">s2Member Simple Shortcode Conditionals</a></p>'."\n";
358 do_action("ws_plugin__s2member_during_res_ops_page_during_left_sections_during_conditionals", get_defined_vars());
359 echo '</div>'."\n";
360
361 if((!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site()) && c_ws_plugin__s2member_utils_conds::pro_is_installed())
362 {
363 echo '<div class="ws-menu-page-hr"></div>'."\n";
364
365 echo '<h3>Arbitrary PHP Code via <code>[s2If php=&quot;&quot;]</code></h3>'."\n";
366 echo '<p>By default, the <code>[s2If]</code> Shortcode is limited to a specific set of Conditional Tags provided by WordPress and the s2Member plugin; e.g., <code>[s2If current_user_can(access_s2member_level1)]</code>; as one quick example. Arbitrary PHP code is not allowed with this syntax. However, a second syntax variation exists; where it <em>is</em> possible to use arbitrary PHP code (only if enabled below). The second syntax variation uses one <code>php</code> Shortcode Attribute to run a single conditional check; e.g., <code>[s2If php="is_user_logged_in() && current_user_can(\'access_s2member_ccap_music\')"]</code>. For developers, this has some obvious advantages. The code inside the <code>php</code> attribute is evaluated at runtime, so it\'s possible to accomplish more when necessary. Of course, you could also use a plugin like <a href="https://www.s2member.com/kb/ezphp-plugin/" target="_blank" rel="external">ezPHP</a> to accomplish the same thing (if you prefer).</p>'."\n";
367
368 echo '<table class="form-table">'."\n";
369 echo '<tbody>'."\n";
370 echo '<tr>'."\n";
371
372 echo '<th>'."\n";
373 echo '<label for="ws-plugin--s2member-sc-conds-allow-arbitrary-php">'."\n";
374 echo 'Allow Arbitrary PHP Code via the <code>[s2If php=&quot;&quot;]</code> Attribute?'."\n";
375 echo '</label>'."\n";
376 echo '</th>'."\n";
377
378 echo '</tr>'."\n";
379 echo '<tr>'."\n";
380
381 echo '<td>'."\n";
382 echo '<select name="ws_plugin__s2member_sc_conds_allow_arbitrary_php" id="ws-plugin--s2member-sc-conds-allow-arbitrary-php">'."\n";
383 echo '<option value="0"'.((!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sc_conds_allow_arbitrary_php"]) ? ' selected="selected"' : '').'>No (recommended for best security; e.g., on sites with multiple authors/editors)</option>'."\n";
384 echo '<option value="1"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sc_conds_allow_arbitrary_php"]) ? ' selected="selected"' : '').'>Yes (allow me to use PHP via the [s2If php=&quot;&quot;][/s2If] shortcode)</option>'."\n";
385 echo '</select>'."\n";
386 echo '</td>'."\n";
387
388 echo '</tr>'."\n";
389 echo '</tbody>'."\n";
390 echo '</table>'."\n";
391
392 //230813 Whitelist more conditional functions
393 echo '<div class="ws-menu-page-hr"></div>'."\n";
394
395 echo '<h3>Whitelist Additional Conditional Functions for <code>[s2If]</code></h3>'."\n";
396 echo '<p>Enter a comma-separated list of additional conditional functions you\'d like to whitelist for the <code>[s2If]</code> shortcode. These functions will be added to the existing set of <a href="https://s2member.com/kb-article/s2if-simple-shortcode-conditionals/#toc-5bb69568" target="_blank" rel="external">allowed functions</a>.</p>'."\n";
397
398 echo '<table class="form-table">'."\n";
399 echo '<tbody>'."\n";
400 echo '<tr>'."\n";
401
402 echo '<th>'."\n";
403 echo '<label for="ws-plugin--s2member-sc-conds-whitelist">'."\n";
404 echo 'Allowed Conditional Functions:'."\n";
405 echo '</label>'."\n";
406 echo '</th>'."\n";
407
408 echo '</tr>'."\n";
409 echo '<tr>'."\n";
410
411 echo '<td>'."\n";
412 echo '<input type="text" name="ws_plugin__s2member_sc_conds_whitelist" id="ws-plugin--s2member-sc-conds-whitelist" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sc_conds_whitelist"]).'" placeholder="" style="width:100%;" /><br />'."\n";
413 echo 'Ex: <code>get_user_field, my_custom_function</code><br />'."\n";
414 echo '</td>'."\n";
415
416 echo '</tr>'."\n";
417 echo '</tbody>'."\n";
418 echo '</table>'."\n";
419 }
420 echo '</div>'."\n";
421
422 do_action("ws_plugin__s2member_during_res_ops_page_during_left_sections_after_conditionals", get_defined_vars());
423 }
424 if(apply_filters("ws_plugin__s2member_during_res_ops_page_during_left_sections_display_sp_access", TRUE, get_defined_vars()))
425 {
426 do_action("ws_plugin__s2member_during_res_ops_page_during_left_sections_before_sp_access", get_defined_vars());
427
428 echo '<div class="ws-menu-page-group" title="Specific Post/Page Access Restrictions">'."\n";
429
430 echo '<div class="ws-menu-page-section ws-plugin--s2member-sp-access-section">'."\n";
431 echo '<h3>Specific Post/Page Access Restrictions (optional)</h3>'."\n";
432 echo '<p>s2Member now supports an additional layer of functionality that allows you to sell access to specific Posts/Pages that you\'ve created in WordPress. s2Member\'s "Specific Post/Page Access" works independently from Membership Level Access. That is, you can sell an unlimited number of Posts/Pages using "Buy Now" Buttons (or Pro-Forms; if you\'re running s2Member Pro)—your Customers will not be required to have a Membership Account with your site in order to receive access. If they are already a Member, that\'s fine, but they won\'t need to be.</p>'."\n";
433 echo '<p>In other words, Customers will not need to log in (or even have an account) to receive access to the Specific Post/Page they purchased access to. s2Member will immediately redirect the Customer to the Specific Post/Page after checkout is completed successfully. An email is also sent to the Customer with a link (see: <strong>s2Member → PayPal Options → Specific Post/Page Email</strong>). Authentication is handled automatically through self-expiring links, good for 72 hours by default.</p>'."\n";
434 echo '<p>Specific Post/Page Access is sort of like selling a product. Only, instead of shipping anything to the Customer, you just give them access to a specific Post/Page on your site; one that you created in WordPress. A Specific Post/Page that is protected by s2Member might contain a download link for your eBook, access to file &amp; music downloads, access to additional support services, and the list goes on. The possibilities with this are endless; as long as your digital product can be delivered through access to a WordPress Post/Page that you\'ve created.</p>'."\n";
435 echo '<p>Very simple. All you do is protect the Specific Post/Page IDs that are being sold on your site. Then, you can go to <strong>s2Member → PayPal Buttons → Specific Post/Page</strong> to generate "Buy Now" Buttons that you can insert into your WordPress Editor and make available on your site. The Button Generator for s2Member will even let you Package Additional Posts/Pages together into one transaction.</p>'."\n";
436 echo '<p><strong>What do I enter?</strong> Post/Page IDs in comma-delimited format. Example: <code>1,2,3,34,8,21</code>. <strong>Note:</strong> the word <code>all</code> does not work here. You must supply a list of Specific Post/Page IDs.</p>'."\n";
437 echo '<p><em><strong>Avoid Conflicts!</strong> Please be careful not to create a conflict with any of your other Access Restrictions. If you are going to sell Specific Post/Page Access you should enter specific Post/Page IDs that have not already been protected by other Restrictions (either directly or indirectly). In short, <strong>make sure that you haven\'t protected any of your Specific Posts/Pages with Member Level Access Restrictions already</strong>. If you configure s2Member in such as a way, that a Post/Page requires both Membership Level Access and Specific Post/Page Access too, you will create a conflict. Customers that purchase Specific Post/Page Access would be unable to access the Post/Page without also having a Membership.</em></p>'."\n";
438 echo ((!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site()) && empty($GLOBALS["WS_PLUGIN__"]["wp_show_ids"])) ? '<p><em><strong>Tip:</strong> Can\'t find your Post/Page IDs? Get <a href="https://s2member.com/r/wordpress-org-wp-show-ids/" target="_blank" rel="external">WP Show IDs</a>.</em></p>'."\n" : '';
439 do_action("ws_plugin__s2member_during_res_ops_page_during_left_sections_during_sp_access", get_defined_vars());
440
441 echo '<table class="form-table">'."\n";
442 echo '<tbody>'."\n";
443 echo '<tr>'."\n";
444
445 echo '<th>'."\n";
446 echo '<label for="ws-plugin--s2member-specific-ids">'."\n";
447 echo 'Specific Post/Page IDs Being Sold On Your Site:'."\n";
448 echo '</label>'."\n";
449 echo '</th>'."\n";
450
451 echo '</tr>'."\n";
452 echo '<tr>'."\n";
453
454 echo '<td>'."\n";
455 echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_specific_ids" id="ws-plugin--s2member-specific-ids" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["specific_ids"]).'" />'."\n";
456 echo '</td>'."\n";
457
458 echo '</tr>'."\n";
459 echo '</tbody>'."\n";
460 echo '</table>'."\n";
461 echo '</div>'."\n";
462
463 echo '</div>'."\n";
464
465 do_action("ws_plugin__s2member_during_res_ops_page_during_left_sections_after_sp_access", get_defined_vars());
466 }
467 if(apply_filters("ws_plugin__s2member_during_res_ops_page_during_left_sections_display_brute_force_restrictions", TRUE, get_defined_vars()))
468 {
469 do_action("ws_plugin__s2member_during_res_ops_page_during_left_sections_before_brute_force_restrictions", get_defined_vars());
470
471 echo '<div class="ws-menu-page-group" title="Brute Force IP/Login Restrictions">'."\n";
472
473 echo '<div class="ws-menu-page-section ws-plugin--s2member-brute-force-restrictions-section">'."\n";
474 echo '<h3>Brute Force IP/Login Restrictions (prevents username/password guessing)</h3>'."\n";
475 echo '<input type="button" id="ws-plugin--s2member-brute-force-restrictions-reset-button" value="Reset Brute Force Logs" class="ws-menu-page-right" style="min-width:175px;" />'."\n";
476 echo '<p>As with any Membership system, it is possible for someone to try and guess Username/Password combinations by attempting a <a href="https://s2member.com/r/wikipedia-brute-force-attack/" target="_blank" rel="external">Brute Force Attack</a>; whereby multiple/repeated logins are strategically attempted with various Username/Password combinations until a correct guess is made. It is not likely that you\'ll be attacked in this way, but it\'s still a good idea to protect your system; just in case somebody tries this. s2Member thwarts this behavior by monitoring failed login attempts that occur within a short period of time. Whenever s2Member detects an IP address <em>(i.e., a remote user)</em> that is consistently failing to enter a valid Username/Password, a temporary ban is created; preventing additional attempts from taking place for 30 minutes. This temporary ban, will only affect the offending IP address.</p>'."\n";
477 echo '<p><em><strong>Note:</strong> an empty IP address (associated with someone browsing anonymously) is also considered a unique IP address. This way it cannot circumvent s2Member\'s security.</em></p>'."\n";
478 do_action("ws_plugin__s2member_during_res_ops_page_during_left_sections_during_ip_restrictions", get_defined_vars());
479
480 echo '<table class="form-table">'."\n";
481 echo '<tbody>'."\n";
482 echo '<tr>'."\n";
483
484 echo '<th>'."\n";
485 echo '<label for="ws-plugin--s2member-max-failed-login-attempts">'."\n";
486 echo 'Maximum Failed Login Attempts:'."\n";
487 echo '</label>'."\n";
488 echo '</th>'."\n";
489
490 echo '</tr>'."\n";
491 echo '<tr>'."\n";
492
493 echo '<td>'."\n";
494 echo '<select name="ws_plugin__s2member_max_failed_login_attempts" id="ws-plugin--s2member-max-failed-login-attempts">'."\n";
495 $ws_plugin__s2member_temp_s = apply_filters("ws_plugin__s2member_track_failed_logins__exp_time", "30 minutes");
496 echo '<option value="1"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_failed_login_attempts"] == 1) ? ' selected="selected"' : '').'>Allow 1 failed login attempt ( then punish for '.$ws_plugin__s2member_temp_s.' )</option>'."\n";
497 echo '<option value="2"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_failed_login_attempts"] == 2) ? ' selected="selected"' : '').'>Allow 2 failed login attempts ( then punish for '.$ws_plugin__s2member_temp_s.' )</option>'."\n";
498 echo '<option value="3"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_failed_login_attempts"] == 3) ? ' selected="selected"' : '').'>Allow 3 failed login attempts ( then punish for '.$ws_plugin__s2member_temp_s.' )</option>'."\n";
499 echo '<option value="4"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_failed_login_attempts"] == 4) ? ' selected="selected"' : '').'>Allow 4 failed login attempts ( then punish for '.$ws_plugin__s2member_temp_s.' )</option>'."\n";
500 echo '<option value="5"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_failed_login_attempts"] == 5) ? ' selected="selected"' : '').'>Allow 5 failed login attempts ( then punish for '.$ws_plugin__s2member_temp_s.' )</option>'."\n";
501 echo '<option value="10"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_failed_login_attempts"] == 10) ? ' selected="selected"' : '').'>Allow 10 failed login attempts ( then punish for '.$ws_plugin__s2member_temp_s.' )</option>'."\n";
502 echo '<option value="20"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_failed_login_attempts"] == 20) ? ' selected="selected"' : '').'>Allow 20 failed login attempts ( then punish for '.$ws_plugin__s2member_temp_s.' )</option>'."\n";
503 echo '<option value="30"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_failed_login_attempts"] == 30) ? ' selected="selected"' : '').'>Allow 30 failed login attempts ( then punish for '.$ws_plugin__s2member_temp_s.' )</option>'."\n";
504 echo '<option value="40"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_failed_login_attempts"] == 40) ? ' selected="selected"' : '').'>Allow 40 failed login attempts ( then punish for '.$ws_plugin__s2member_temp_s.' )</option>'."\n";
505 echo '<option value="50"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_failed_login_attempts"] == 50) ? ' selected="selected"' : '').'>Allow 50 failed login attempts ( then punish for '.$ws_plugin__s2member_temp_s.' )</option>'."\n";
506 echo '<option value="75"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_failed_login_attempts"] == 75) ? ' selected="selected"' : '').'>Allow 75 failed login attempts ( then punish for '.$ws_plugin__s2member_temp_s.' )</option>'."\n";
507 echo '<option value="100"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_failed_login_attempts"] == 100) ? ' selected="selected"' : '').'>Allow 100 failed login attempts ( then punish for '.$ws_plugin__s2member_temp_s.' )</option>'."\n";
508 echo '<option value="0"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_failed_login_attempts"] == 0) ? ' selected="selected"' : '').'>Allow infinite failed logins (Brute Force Restrictions disabled)</option>'."\n";
509 echo '</select><br />'."\n";
510 echo 'When/if you change this, you should also <strong>Reset Brute Force Logs</strong> (click button above).'."\n";
511 echo (!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site()) ? '<br /><br />The default period of "30 minutes" could be modified through this WordPress Filter:<br /><code>ws_plugin__s2member_track_failed_logins__exp_time</code>'."\n" : '';
512 echo '</td>'."\n";
513
514 echo '</tr>'."\n";
515 echo '</tbody>'."\n";
516 echo '</table>'."\n";
517 echo '</div>'."\n";
518
519 echo '</div>'."\n";
520
521 do_action("ws_plugin__s2member_during_res_ops_page_during_left_sections_after_ip_restrictions", get_defined_vars());
522 }
523 if(apply_filters("ws_plugin__s2member_during_res_ops_page_during_left_sections_display_ip_restrictions", TRUE, get_defined_vars()))
524 {
525 do_action("ws_plugin__s2member_during_res_ops_page_during_left_sections_before_ip_restrictions", get_defined_vars());
526
527 echo '<div class="ws-menu-page-group" title="Unique IP Access Restrictions">'."\n";
528
529 echo '<div class="ws-menu-page-section ws-plugin--s2member-ip-restrictions-section">'."\n";
530 echo '<h3>Unique IP Access Restrictions (prevents username/link sharing)</h3>'."\n";
531 echo '<input type="button" id="ws-plugin--s2member-ip-restrictions-reset-button" value="Reset IP Restriction Logs" class="ws-menu-page-right" style="min-width:175px;" />'."\n";
532 echo '<p>As with any Membership system, it is possible for one Member to signup, and then share their Username with someone else; or even post it online for the whole world to see. This is known as Link Sharing (or Username Sharing). It is not likely that you\'ll be attacked in this way, but it\'s still a good idea to protect your system; just in case somebody tries this. s2Member\'s IP Restrictions work for Membership Level Access (i.e., account logins), Specific Post/Page Access, Registration Links, and other secure Entry Points. In all cases, the rules are simple. A single Username, Access Link, and/or Entry Point is only valid for a certain number of unique IP addresses. Once that limit is reached, s2Member assumes there has been a security breach. At that time, s2Member will create a temporary ban; preventing access to a Specific Post/Page, or to an account associated with a particular Username. This temporary ban will only affect the offending Link and/or Username associated with the security breach. You can fine-tune this behavior using the options below.</p>'."\n";
533 echo '<p><em><strong>Note:</strong> an empty IP address (associated with someone browsing anonymously) is also considered a unique IP address. This way it cannot circumvent s2Member\'s security.</em></p>'."\n";
534 echo '<p><em><strong>Note:</strong> This feature can work with or without <strong>Simultaneous Login Monitoring</strong> (Simultaneous Login Monitoring is an s2Member Pro feature). You can choose to implement both Unique IP Access Restrictions and Simultaneous Login Monitoring together, just one of them, or neither. It\'s a matter of preference. Simultaneous Login Monitoring has the added benefit of not being dependent upon IP address tracking—making it more user-friendly and reliable. Particularly in cases where you\'d like to support users who might travel a lot, have multiple devices, or be on ISPs that change their IP address frequently.</em></p>'."\n";
535 do_action("ws_plugin__s2member_during_res_ops_page_during_left_sections_during_ip_restrictions", get_defined_vars());
536
537 echo '<table class="form-table">'."\n";
538 echo '<tbody>'."\n";
539 echo '<tr>'."\n";
540
541 echo '<th>'."\n";
542 echo '<label for="ws-plugin--s2member-max-ip-restriction">'."\n";
543 echo 'Maximum Unique IP Addresses Allowed:'."\n";
544 echo '</label>'."\n";
545 echo '</th>'."\n";
546
547 echo '</tr>'."\n";
548 echo '<tr>'."\n";
549
550 echo '<td>'."\n";
551 echo '<select name="ws_plugin__s2member_max_ip_restriction" id="ws-plugin--s2member-max-ip-restriction">'."\n";
552 $ws_plugin__s2member_temp_s = apply_filters("ws_plugin__s2member_ip_restrictions__concurrency_time_per_ip", "30 days");
553 echo '<option value="1"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction"] == 1) ? ' selected="selected"' : '').'>Allow up to 1 unique IP per Customer ( every '.$ws_plugin__s2member_temp_s.' )</option>'."\n";
554 echo '<option value="2"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction"] == 2) ? ' selected="selected"' : '').'>Allow up to 2 different IPs per Customer ( every '.$ws_plugin__s2member_temp_s.' )</option>'."\n";
555 echo '<option value="3"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction"] == 3) ? ' selected="selected"' : '').'>Allow up to 3 different IPs per Customer ( every '.$ws_plugin__s2member_temp_s.' )</option>'."\n";
556 echo '<option value="4"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction"] == 4) ? ' selected="selected"' : '').'>Allow up to 4 different IPs per Customer ( every '.$ws_plugin__s2member_temp_s.' )</option>'."\n";
557 echo '<option value="5"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction"] == 5) ? ' selected="selected"' : '').'>Allow up to 5 different IPs per Customer ( every '.$ws_plugin__s2member_temp_s.' )</option>'."\n";
558 echo '<option value="10"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction"] == 10) ? ' selected="selected"' : '').'>Allow up to 10 different IPs per Customer ( every '.$ws_plugin__s2member_temp_s.' )</option>'."\n";
559 echo '<option value="20"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction"] == 20) ? ' selected="selected"' : '').'>Allow up to 20 different IPs per Customer ( every '.$ws_plugin__s2member_temp_s.' )</option>'."\n";
560 echo '<option value="30"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction"] == 30) ? ' selected="selected"' : '').'>Allow up to 30 different IPs per Customer ( every '.$ws_plugin__s2member_temp_s.' )</option>'."\n";
561 echo '<option value="40"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction"] == 40) ? ' selected="selected"' : '').'>Allow up to 40 different IPs per Customer ( every '.$ws_plugin__s2member_temp_s.' )</option>'."\n";
562 echo '<option value="50"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction"] == 50) ? ' selected="selected"' : '').'>Allow up to 50 different IPs per Customer ( every '.$ws_plugin__s2member_temp_s.' )</option>'."\n";
563 echo '<option value="75"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction"] == 75) ? ' selected="selected"' : '').'>Allow up to 75 different IPs per Customer ( every '.$ws_plugin__s2member_temp_s.' )</option>'."\n";
564 echo '<option value="100"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction"] == 100) ? ' selected="selected"' : '').'>Allow up to 100 different IPs per Customer ( every '.$ws_plugin__s2member_temp_s.' )</option>'."\n";
565 echo '<option value="0"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction"] == 0) ? ' selected="selected"' : '').'>Allow infinite IPs (all IP Restrictions are disabled)</option>'."\n";
566 echo '</select>'."\n";
567 echo (!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site()) ? '<br />The default period of "30 days" could be modified through this WordPress Filter:<br /><code>ws_plugin__s2member_ip_restrictions__concurrency_time_per_ip</code>'."\n" : '';
568 echo '</td>'."\n";
569
570 echo '</tr>'."\n";
571 echo '<tr>'."\n";
572
573 echo '<th>'."\n";
574 echo '<label for="ws-plugin--s2member-max-ip-restriction-time">'."\n";
575 echo 'Security Breach Timeout Period:'."\n";
576 echo '</label>'."\n";
577 echo '</th>'."\n";
578
579 echo '</tr>'."\n";
580 echo '<tr>'."\n";
581
582 echo '<td>'."\n";
583 echo '<select name="ws_plugin__s2member_max_ip_restriction_time" id="ws-plugin--s2member-max-ip-restriction-time">'."\n";
584 echo '<option value="300"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction_time"] == 300) ? ' selected="selected"' : '').'>If limit is exceeded (punish for 5 mins)</option>'."\n";
585 echo '<option value="900"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction_time"] == 900) ? ' selected="selected"' : '').'>If limit is exceeded (punish for 15 mins)</option>'."\n";
586 echo '<option value="1800"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction_time"] == 1800) ? ' selected="selected"' : '').'>If limit is exceeded (punish for 30 mins)</option>'."\n";
587 echo '<option value="3600"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction_time"] == 3600) ? ' selected="selected"' : '').'>If limit is exceeded (punish for 1 hour)</option>'."\n";
588 echo '<option value="7200"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction_time"] == 7200) ? ' selected="selected"' : '').'>If limit is exceeded (punish for 2 hours)</option>'."\n";
589 echo '<option value="14400"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction_time"] == 14400) ? ' selected="selected"' : '').'>If limit is exceeded (punish for 4 hours)</option>'."\n";
590 echo '<option value="21600"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction_time"] == 21600) ? ' selected="selected"' : '').'>If limit is exceeded (punish for 6 hours)</option>'."\n";
591 echo '<option value="28800"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction_time"] == 28800) ? ' selected="selected"' : '').'>If limit is exceeded (punish for 8 hours)</option>'."\n";
592 echo '<option value="43200"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction_time"] == 43200) ? ' selected="selected"' : '').'>If limit is exceeded (punish for 12 hours)</option>'."\n";
593 echo '<option value="86400"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction_time"] == 86400) ? ' selected="selected"' : '').'>If limit is exceeded (punish for 24 hours)</option>'."\n";
594 echo '<option value="172800"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction_time"] == 172800) ? ' selected="selected"' : '').'>If limit is exceeded (punish for 2 days)</option>'."\n";
595 echo '<option value="345600"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction_time"] == 345600) ? ' selected="selected"' : '').'>If limit is exceeded (punish for 4 days)</option>'."\n";
596 echo '<option value="604800"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction_time"] == 604800) ? ' selected="selected"' : '').'>If limit is exceeded (punish for 1 week)</option>'."\n";
597 echo '<option value="1209600"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction_time"] == 1209600) ? ' selected="selected"' : '').'>If limit is exceeded (punish for 2 weeks)</option>'."\n";
598 echo '<option value="2629743"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction_time"] == 2629743) ? ' selected="selected"' : '').'>If limit is exceeded (punish for 1 month)</option>'."\n";
599 echo '<option value="5259487"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction_time"] == 5259487) ? ' selected="selected"' : '').'>If limit is exceeded (punish for 2 months)</option>'."\n";
600 echo '<option value="7889231"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction_time"] == 7889231) ? ' selected="selected"' : '').'>If limit is exceeded (punish for 3 months)</option>'."\n";
601 echo '<option value="15778463"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction_time"] == 15778463) ? ' selected="selected"' : '').'>If limit is exceeded (punish for 6 months)</option>'."\n";
602 echo '<option value="31556926"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction_time"] == 31556926) ? ' selected="selected"' : '').'>If limit is exceeded (punish for 1 year)</option>'."\n";
603 echo '</select><br />'."\n";
604 echo 'When/if you change this, you should also <strong>Reset IP Restriction Logs</strong> (click button above).'."\n";
605 echo '</td>'."\n";
606
607 echo '</tr>'."\n";
608 echo '</tbody>'."\n";
609 echo '</table>'."\n";
610 echo '</div>'."\n";
611
612 echo '</div>'."\n";
613
614 do_action("ws_plugin__s2member_during_res_ops_page_during_left_sections_after_ip_restrictions", get_defined_vars());
615 }
616 if(apply_filters("ws_plugin__s2member_during_res_ops_page_during_left_sections_display_slogin_restrictions", c_ws_plugin__s2member_utils_conds::pro_is_installed(), get_defined_vars()))
617 {
618 do_action("ws_plugin__s2member_during_res_ops_page_during_left_sections_before_slogin_restrictions", get_defined_vars());
619
620 echo '<div class="ws-menu-page-group" title="Simultaneous Login Restrictions">'."\n";
621
622 echo '<div class="ws-menu-page-section ws-plugin--s2member-slogin-restrictions-section">'."\n";
623 echo '<h3>Simultaneous Login Restrictions (prevents username sharing)</h3>'."\n";
624 echo '<p>As with any Membership system, it is possible for one Member to signup, then share their Username with someone else; or even post it online for the whole world to see. This is known as Username Sharing. It is not likely that you\'ll be attacked in this way, but it\'s not a bad idea to protect your system; just in case somebody tries this.</p>'."\n";
625 echo '<p>s2Member\'s Simultaneous Login Monitoring (for Membership Access only) works with account logins (Usernames), to help you prevent a security issue. The rules are simple. A single Username can only have X number of simultaneous logins (as configured below). Once that limit is reached, s2Member assumes there has been a security breach. At that time, s2Member will create a temporary ban; preventing the offending Username from being able to log in until somebody else (who is already logged into the account) has logged-out; clearing the way for someone new.</p>'."\n";
626 echo '<p>This can be a tricky feature to configure, because most people do not click a "Logout" link when they are done with their account. This makes it challenging to know when someone is still logged-in, and when they\'re not. s2Member monitors simultaneous logins by updating a timer whenever someone actually logs in; and then again on each page view while they navigate the site. If there is no activity after X amount of time, s2Member\'s Simultaneous Login Monitor considers that person inactive, and will not include them in security checks until they log in again, or visit a new page on the site. You can configure the timeout period below. The default value is <code>30 minutes</code>.</p>'."\n";
627 echo '<p><em><strong>Note:</strong> This feature can work with or without <strong>Unique IP Restrictions</strong>. You can choose to implement both Unique IP Access Restrictions and Simultaneous Login Monitoring together, just one of them, or neither. It\'s a matter of preference. Simultaneous Login Monitoring has the added benefit of not being dependent upon IP address tracking—making it more user-friendly and reliable. Particularly in cases where you\'d like to support users who might travel a lot, have multiple devices, or be on ISPs that change their IP address frequently.</em></p>'."\n";
628 do_action("ws_plugin__s2member_during_res_ops_page_during_left_sections_during_slogin_restrictions", get_defined_vars());
629
630 echo '<table class="form-table">'."\n";
631 echo '<tbody>'."\n";
632 echo '<tr>'."\n";
633
634 echo '<th>'."\n";
635 echo '<label for="ws-plugin--s2member-max-simultaneous-logins">'."\n";
636 echo 'Max Simultaneous Logins Allowed; for each Username:'."\n";
637 echo '</label>'."\n";
638 echo '</th>'."\n";
639
640 echo '</tr>'."\n";
641 echo '<tr>'."\n";
642
643 echo '<td>'."\n";
644 echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_max_simultaneous_logins" id="ws-plugin--s2member-max-simultaneous-logins" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_simultaneous_logins"]).'" /><br />'."\n";
645 echo 'Examples: <code>0</code> (to disable this functionality), <code>1</code> (maximum of 1 login at a time), <code>2</code>, <code>3</code>, <code>10</code>, <code>20</code>, etc.<br />'."\n";
646 echo 'Suggestion: <code>3</code>—the chance to open your site in multiple browsers; but still prevents major security issues.<br />'."\n";
647 echo '</td>'."\n";
648
649 echo '</tr>'."\n";
650 echo '<tr>'."\n";
651
652 echo '<th>'."\n";
653 echo '<label for="ws-plugin--s2member-max-simultaneous-logins-timeout">'."\n";
654 echo 'Inactivity Timeout Period; this impacts Simultaneous Login Monitoring only.<br />'."\n";
655 echo 'Simultaneous Login Monitoring should assume a Username is logged-out after this amount of time:'."\n";
656 echo '</label>'."\n";
657 echo '</th>'."\n";
658
659 echo '</tr>'."\n";
660 echo '<tr>'."\n";
661
662 echo '<td>'."\n";
663 echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_max_simultaneous_logins_timeout" id="ws-plugin--s2member-max-simultaneous-logins-timeout" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_simultaneous_logins_timeout"]).'" /><br />'."\n";
664 echo 'Examples: <code>30 minutes</code>, <code>1 hour</code>, <code>2 hours</code>; anything compatible with PHP\'s <a href="https://s2member.com/r/php-net-strtotime/" target="_blank" rel="external">strtotime()</a>.<br />'."\n";
665 echo 'Recommended Setting: <code>30 minutes</code>; if they stop browsing the site, they\'re considered inactive.<br />'."\n";
666 echo '</td>'."\n";
667
668 echo '</tr>'."\n";
669 echo '</tbody>'."\n";
670 echo '</table>'."\n";
671 echo '</div>'."\n";
672
673 echo '</div>'."\n";
674
675 do_action("ws_plugin__s2member_during_res_ops_page_during_left_sections_after_slogin_restrictions", get_defined_vars());
676 }
677 do_action("ws_plugin__s2member_during_res_ops_page_after_left_sections", get_defined_vars());
678
679 echo '<p class="submit"><input type="submit" value="Save All Changes" /></p>'."\n";
680
681 echo '</form>'."\n";
682
683 echo '</td>'."\n";
684
685 echo '<td class="ws-menu-page-table-r">'."\n";
686 c_ws_plugin__s2member_menu_pages_rs::display();
687 echo '</td>'."\n";
688
689 echo '</tr>'."\n";
690 echo '</tbody>'."\n";
691 echo '</table>'."\n";
692
693 echo '</div>'."\n";
694 }
695 }
696 }
697 new c_ws_plugin__s2member_menu_page_res_ops ();
698