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

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

1,024 lines 59.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // @codingStandardsIgnoreFile
3 /**
4 * Administrative menu pages.
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.5
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_pages'))
22 {
23 /**
24 * Administrative menu pages.
25 *
26 * @package s2Member\Menu_Pages
27 * @since 3.5
28 */
29 class c_ws_plugin__s2member_menu_pages
30 {
31 /**
32 * Pre-display errors.
33 *
34 * @package s2Member\Menu_Pages
35 * @since 111209
36 *
37 * @var array
38 */
39 public static $pre_display_errors = array();
40
41 /**
42 * Saves all options from any menu page.
43 *
44 * Can also be self-verified; and configured extensively with function parameters.
45 *
46 * @package s2Member\Menu_Pages
47 * @since 3.5
48 *
49 * @param null|array $new_options Optional. Force feed an array of new options. Defaults to ``$_POST`` vars.
50 * If ``$new_options`` are passed in, be SURE that you've already applied ``stripslashes_deep()``.
51 * @param bool $verified Optional. Defaults to false. If true, ``wp_verify_nonce()`` is skipped in this routine.
52 * @param bool $update_other Optional. Defaults to true. If false, other option-dependent routines will not be processed.
53 * @param bool|array $display_notices Optional. Defaults to true. Can be false, or an array of certain notices that can be displayed.
54 * @param bool|array $enqueue_notices Optional. Defaults to false. Can be true, or an array of certain notices that should be enqueued.
55 * @param bool $request_refresh Optional. Defaults to false. If true, resulting `success` notice will include a link to refresh the menu page.
56 *
57 * @return bool True if all s2Member options were updated successfully, else false.
58 */
59 public static function update_all_options($new_options = NULL, $verified = FALSE, $update_other = TRUE, $display_notices = TRUE, $enqueue_notices = FALSE, $request_refresh = FALSE)
60 {
61 $updated_all_options = FALSE; // Initializing this variable here makes it an available reference-variable to Hooks/Filters.
62
63 foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
64 do_action('ws_plugin__s2member_before_update_all_options', get_defined_vars()); // If you use this Hook, be sure to use ``wp_verify_nonce()``.
65 unset($__refs, $__v); // Housekeeping.
66
67 if($verified || (!empty($_POST['ws_plugin__s2member_options_save']) && ($nonce = $_POST['ws_plugin__s2member_options_save']) && wp_verify_nonce($nonce, 'ws-plugin--s2member-options-save')))
68 {
69 $options = $GLOBALS['WS_PLUGIN__']['s2member']['o']; // Acquire the full existing configuration options array here.
70
71 $new_options = (is_array($new_options)) ? $new_options : ((!empty($_POST) && is_array($_POST)) ? stripslashes_deep($_POST) : array());
72 $new_options = c_ws_plugin__s2member_utils_strings::trim_deep($new_options);
73
74 foreach($new_options as $key => $value) // Find all keys contained within ``$new_options`` matching `^ws_plugin__s2member_`.
75 if(strpos($key, 'ws_plugin__s2member_') === 0) // A relevant ``$new_options`` key matching `^ws_plugin__s2member_`?
76
77 if($key === 'ws_plugin__s2member_configured') // s2Member is now configured (according to these options)?
78 ($GLOBALS['WS_PLUGIN__']['s2member']['c']['configured'] = $value).update_option('ws_plugin__s2member_configured', $value);
79
80 else if(!is_array($value) || (is_array($value) && array_shift($value) === 'update-signal')) // Updating an array?
81 $options[preg_replace('/^'.preg_quote('ws_plugin__s2member_', '/').'/', '', $key)] = $value;
82
83 unset($key, $value); // Unset these utility variables now. This prevents bleeding vars into Hooks/Filters that are of no use.
84
85 foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
86 do_action('ws_plugin__s2member_during_update_all_options', get_defined_vars());
87 unset($__refs, $__v); // Housekeeping.
88
89 //260812 Keep the old s2Get option synchronized for rollback compatibility, while accepting legacy updates during the transition.
90 if(isset($new_options['ws_plugin__s2member_sc_s2get_userid_whitelist']) && !isset($new_options['ws_plugin__s2member_sc_user_fields_whitelist']))
91 $options['sc_user_fields_whitelist'] = $options['sc_s2get_userid_whitelist'];
92 if(isset($options['sc_user_fields_whitelist']))
93 $options['sc_s2get_userid_whitelist'] = $options['sc_user_fields_whitelist'];
94
95 $options = ws_plugin__s2member_configure_options_and_their_defaults(($options = array_merge($options, array('options_version' => (string)($options['options_version'] + 0.001)))));
96 update_option('ws_plugin__s2member_options', $options).((is_multisite() && is_main_site()) ? update_site_option('ws_plugin__s2member_options', $options) : NULL).update_option('ws_plugin__s2member_cache', array());
97
98 if($update_other === TRUE || in_array('auto_eot_system', (array)$update_other)) // Handle the Auto-EOT System now (enable/disable).
99 ($options['auto_eot_system_enabled'] == 1) ? c_ws_plugin__s2member_auto_eots::add_auto_eot_system() : c_ws_plugin__s2member_auto_eots::delete_auto_eot_system();
100
101 if(($display_notices === TRUE || in_array('success', (array)$display_notices)) && ($notice = '<strong>Options saved.'.(($request_refresh) ? ' Please <a href="'.esc_attr($_SERVER['REQUEST_URI']).'">refresh</a>.' : '').'</strong>'))
102 ($enqueue_notices === TRUE || in_array('success', (array)$enqueue_notices)) ? c_ws_plugin__s2member_admin_notices::enqueue_admin_notice($notice, '*:*') : c_ws_plugin__s2member_admin_notices::display_admin_notice($notice);
103
104 if(empty($_GET['page']) || $_GET['page'] !== 'ws-plugin--s2member-mms-ops') // Do NOT display page-conflict-warnings on the Main Multisite Configuration panel.
105 {
106 if(!$options['membership_options_page'] && ($display_notices === TRUE || in_array('page-conflict-warnings', (array)$display_notices)) && ($notice = '<strong>NOTE:</strong> s2Member security restrictions will NOT be enforced until you\'ve configured a Membership Options Page. See: <strong>s2Member → General Options → Membership Options Page</strong>.'))
107 ($enqueue_notices === TRUE || in_array('page-conflict-warnings', (array)$enqueue_notices)) ? c_ws_plugin__s2member_admin_notices::enqueue_admin_notice($notice, '*:*', TRUE) : c_ws_plugin__s2member_admin_notices::display_admin_notice($notice, TRUE);
108
109 if($options['login_welcome_page'] && $options['login_welcome_page'] === $options['membership_options_page'] && ($display_notices === TRUE || in_array('page-conflict-warnings', (array)$display_notices)) && ($notice = '<strong>s2Member:</strong> Your Login Welcome Page is the same as your Membership Options Page. Please correct this. See: <strong>s2Member → General Options → Login Welcome Page</strong>.'))
110 ($enqueue_notices === TRUE || in_array('page-conflict-warnings', (array)$enqueue_notices)) ? c_ws_plugin__s2member_admin_notices::enqueue_admin_notice($notice, '*:*', TRUE) : c_ws_plugin__s2member_admin_notices::display_admin_notice($notice, TRUE);
111
112 if($options['membership_options_page'] && (string)get_option('page_on_front') === $options['membership_options_page'] && ($display_notices === TRUE || in_array('page-conflict-warnings', (array)$display_notices)) && ($notice = '<strong>s2Member:</strong> Your Membership Options Page is currently configured as your Home Page (i.e., static page) for WordPress. This causes internal conflicts with s2Member. Your Membership Options Page MUST stand alone. Please correct this. See: <strong>WordPress → Reading Options</strong>. Or change: <strong>s2Member → General Options → Membership Options Page</strong>.'))
113 ($enqueue_notices === TRUE || in_array('page-conflict-warnings', (array)$enqueue_notices)) ? c_ws_plugin__s2member_admin_notices::enqueue_admin_notice($notice, '*:*', TRUE) : c_ws_plugin__s2member_admin_notices::display_admin_notice($notice, TRUE);
114
115 if($options['login_welcome_page'] && (string)get_option('page_on_front') === $options['login_welcome_page'] && ($display_notices === TRUE || in_array('page-conflict-warnings', (array)$display_notices)) && ($notice = '<strong>s2Member:</strong> Your Login Welcome Page is currently configured as your Home Page (i.e., static page) for WordPress. This causes internal conflicts with s2Member. Your Login Welcome Page MUST stand alone. Please correct this. See: <strong>WordPress → Reading Options</strong>. Or change: <strong>s2Member → General Options → Login Welcome Page</strong>.'))
116 ($enqueue_notices === TRUE || in_array('page-conflict-warnings', (array)$enqueue_notices)) ? c_ws_plugin__s2member_admin_notices::enqueue_admin_notice($notice, '*:*', TRUE) : c_ws_plugin__s2member_admin_notices::display_admin_notice($notice, TRUE);
117
118 if($options['membership_options_page'] && (string)get_option('page_for_posts') === $options['membership_options_page'] && ($display_notices === TRUE || in_array('page-conflict-warnings', (array)$display_notices)) && ($notice = '<strong>s2Member:</strong> Your Membership Options Page is currently configured as your Posts Page (i.e., static page) for WordPress. This causes internal conflicts with s2Member. Your Membership Options Page MUST stand alone. Please correct this. See: <strong>WordPress → Reading Options</strong>. Or change: <strong>s2Member → General Options → Membership Options Page</strong>.'))
119 ($enqueue_notices === TRUE || in_array('page-conflict-warnings', (array)$enqueue_notices)) ? c_ws_plugin__s2member_admin_notices::enqueue_admin_notice($notice, '*:*', TRUE) : c_ws_plugin__s2member_admin_notices::display_admin_notice($notice, TRUE);
120
121 if($options['login_welcome_page'] && (string)get_option('page_for_posts') === $options['login_welcome_page'] && ($display_notices === TRUE || in_array('page-conflict-warnings', (array)$display_notices)) && ($notice = '<strong>s2Member:</strong> Your Login Welcome Page is currently configured as your Posts Page (i.e., static page) for WordPress. This causes internal conflicts with s2Member. Your Login Welcome Page MUST stand alone. Please correct this. See: <strong>WordPress → Reading Options</strong>. Or change: <strong>s2Member → General Options → Login Welcome Page</strong>.'))
122 ($enqueue_notices === TRUE || in_array('page-conflict-warnings', (array)$enqueue_notices)) ? c_ws_plugin__s2member_admin_notices::enqueue_admin_notice($notice, '*:*', TRUE) : c_ws_plugin__s2member_admin_notices::display_admin_notice($notice, TRUE);
123
124 if($options['file_download_limit_exceeded_page'] && $options['file_download_limit_exceeded_page'] === $options['membership_options_page'] && ($display_notices === TRUE || in_array('page-conflict-warnings', (array)$display_notices)) && ($notice = '<strong>s2Member:</strong> Your Download Limit Exceeded Page is the same as your Membership Options Page. Please correct this. See: <strong>s2Member → Download Options</strong>.'))
125 ($enqueue_notices === TRUE || in_array('page-conflict-warnings', (array)$enqueue_notices)) ? c_ws_plugin__s2member_admin_notices::enqueue_admin_notice($notice, '*:*', TRUE) : c_ws_plugin__s2member_admin_notices::display_admin_notice($notice, TRUE);
126 }
127 $updated_all_options = TRUE; // Flag indicating this routine was processed successfully; and that all s2Member options have been updated successfully.
128 }
129 foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
130 do_action('ws_plugin__s2member_after_update_all_options', get_defined_vars());
131 unset($__refs, $__v); // Housekeeping.
132
133 return apply_filters('ws_plugin__s2member_update_all_options', (($updated_all_options) ? TRUE : FALSE), get_defined_vars());
134 }
135
136 /**
137 * Adds option menus / sub-menus.
138 *
139 * @package s2Member\Menu_Pages
140 * @since 3.5
141 *
142 * @attaches-to ``add_action('admin_menu');``
143 */
144 public static function add_admin_options()
145 {
146 do_action('ws_plugin__s2member_before_add_admin_options', get_defined_vars());
147
148 add_filter('plugin_action_links', 'c_ws_plugin__s2member_menu_pages::_add_settings_link', 10, 2);
149
150 if(apply_filters('ws_plugin__s2member_during_add_admin_options_create_menu_items', TRUE, get_defined_vars()))
151 {
152 if((is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site()) || apply_filters('ws_plugin__s2member_during_add_admin_options_clear_right_side', FALSE, get_defined_vars()))
153 $GLOBALS['WS_PLUGIN__']['s2member']['c']['menu_pages'] = array(); // Clear right side.
154
155 $menu = apply_filters('ws_plugin__s2member_during_add_admin_options_menu_slug', 'ws-plugin--s2member-start', get_defined_vars());
156
157 if(apply_filters('ws_plugin__s2member_during_add_admin_options_add_menu_page', TRUE, get_defined_vars()))
158 add_menu_page(((c_ws_plugin__s2member_utils_conds::pro_is_installed()) ? 's2Member (Pro)' : 's2Member'), ((c_ws_plugin__s2member_utils_conds::pro_is_installed()) ? 's2Member (Pro)' : 's2Member'),
159 'create_users', $menu, 'c_ws_plugin__s2member_menu_pages::start_page', $GLOBALS['WS_PLUGIN__']['s2member']['c']['dir_url'].'/src/images/brand-favicon.png');
160
161 if(apply_filters('ws_plugin__s2member_during_add_admin_options_add_start_page', TRUE, get_defined_vars()))
162 add_submenu_page($menu, 'Getting Started w/ s2Member', 'Getting Started', 'create_users', 'ws-plugin--s2member-start', 'c_ws_plugin__s2member_menu_pages::start_page');
163
164 if(apply_filters('ws_plugin__s2member_during_add_admin_options_add_help_page', !is_multisite () || !c_ws_plugin__s2member_utils_conds::is_multisite_farm () || is_main_site (), get_defined_vars()))
165 add_submenu_page($menu, 'Getting Help w/ s2Member', 'Getting Help', 'create_users', 'ws-plugin--s2member-help', 'c_ws_plugin__s2member_menu_pages::help_page');
166
167 if(apply_filters('ws_plugin__s2member_during_add_admin_options_add_divider_1', TRUE, get_defined_vars()))
168 add_submenu_page($menu, '', '<span style="display:block; margin:1px 0 1px -5px; padding:0; height:1px; line-height:1px; background:#CCCCCC;"></span>', 'create_users', '#');
169
170 if(apply_filters('ws_plugin__s2member_during_add_admin_options_add_mms_ops_page', (!is_multisite() || is_main_site()), get_defined_vars()))
171 add_submenu_page($menu, 's2Member Multisite Configuration', 'Multisite (Config)', 'create_users', 'ws-plugin--s2member-mms-ops', 'c_ws_plugin__s2member_menu_pages::mms_ops_page');
172
173 if(apply_filters('ws_plugin__s2member_during_add_admin_options_add_gen_ops_page', TRUE, get_defined_vars()))
174 add_submenu_page($menu, 's2Member General Options', 'General Options', 'create_users', 'ws-plugin--s2member-gen-ops', 'c_ws_plugin__s2member_menu_pages::gen_ops_page');
175
176 if(apply_filters('ws_plugin__s2member_during_add_admin_options_add_res_ops_page', TRUE, get_defined_vars()))
177 add_submenu_page($menu, 's2Member Restriction Options', 'Restriction Options', 'create_users', 'ws-plugin--s2member-res-ops', 'c_ws_plugin__s2member_menu_pages::res_ops_page');
178
179 if(apply_filters('ws_plugin__s2member_during_add_admin_options_add_down_ops_page', (!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site()), get_defined_vars()))
180 add_submenu_page($menu, 's2Member Download Options', 'Download Options', 'create_users', 'ws-plugin--s2member-down-ops', 'c_ws_plugin__s2member_menu_pages::down_ops_page');
181
182 if(apply_filters('ws_plugin__s2member_during_add_admin_options_add_divider_2', TRUE, get_defined_vars()))
183 add_submenu_page($menu, '', '<span style="display:block; margin:1px 0 1px -5px; padding:0; height:1px; line-height:1px; background:#CCCCCC;"></span>', 'create_users', '#');
184
185 if(apply_filters('ws_plugin__s2member_during_add_admin_options_add_paypal_ops_page', TRUE, get_defined_vars()))
186 add_submenu_page($menu, 's2Member PayPal Options', 'PayPal Options', 'create_users', 'ws-plugin--s2member-paypal-ops', 'c_ws_plugin__s2member_menu_pages::paypal_ops_page');
187
188 if(apply_filters('ws_plugin__s2member_during_add_admin_options_add_paypal_buttons_page', TRUE, get_defined_vars()))
189 add_submenu_page($menu, 's2Member PayPal Buttons', 'PayPal Buttons', 'create_users', 'ws-plugin--s2member-paypal-buttons', 'c_ws_plugin__s2member_menu_pages::paypal_buttons_page');
190
191 if(apply_filters('ws_plugin__s2member_during_add_admin_options_add_divider_3', TRUE, get_defined_vars()))
192 add_submenu_page($menu, '', '<span style="display:block; margin:1px 0 1px -5px; padding:0; height:1px; line-height:1px; background:#CCCCCC;"></span>', 'create_users', '#');
193
194 if(apply_filters('ws_plugin__s2member_during_add_admin_options_add_trk_ops_page', TRUE, get_defined_vars()))
195 add_submenu_page($menu, 's2Member API / Tracking', 'API / Tracking', 'create_users', 'ws-plugin--s2member-trk-ops', 'c_ws_plugin__s2member_menu_pages::trk_ops_page');
196
197 if(apply_filters('ws_plugin__s2member_during_add_admin_options_add_els_ops_page', TRUE, get_defined_vars()))
198 add_submenu_page($menu, 's2Member API / List Servers', 'API / List Servers', 'create_users', 'ws-plugin--s2member-els-ops', 'c_ws_plugin__s2member_menu_pages::els_ops_page');
199
200 if(apply_filters('ws_plugin__s2member_during_add_admin_options_add_api_ops_page', TRUE, get_defined_vars()))
201 add_submenu_page($menu, 's2Member API / Notifications', 'API / Notifications', 'create_users', 'ws-plugin--s2member-api-ops', 'c_ws_plugin__s2member_menu_pages::api_ops_page');
202
203 if(apply_filters('ws_plugin__s2member_during_add_admin_options_add_scripting_page', TRUE, get_defined_vars()))
204 add_submenu_page($menu, 's2Member API / Scripting', 'API / Scripting', 'create_users', 'ws-plugin--s2member-scripting', 'c_ws_plugin__s2member_menu_pages::scripting_page');
205
206 if(apply_filters('ws_plugin__s2member_during_add_admin_options_add_divider_4', TRUE, get_defined_vars()))
207 add_submenu_page($menu, '', '<span style="display:block; margin:1px 0 1px -5px; padding:0; height:1px; line-height:1px; background:#CCCCCC;"></span>', 'create_users', '#');
208
209 if(apply_filters('ws_plugin__s2member_during_add_admin_options_add_integrations_page', (!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site()), get_defined_vars()))
210 add_submenu_page($menu, 's2Member / Other Integrations', 'Other Integrations', 'create_users', 'ws-plugin--s2member-integrations', 'c_ws_plugin__s2member_menu_pages::integrations_page');
211
212 if(apply_filters('ws_plugin__s2member_during_add_admin_options_add_divider_5', TRUE, get_defined_vars()))
213 add_submenu_page($menu, '', '<span style="display:block; margin:1px 0 1px -5px; padding:0; height:1px; line-height:1px; background:#CCCCCC;"></span>', 'create_users', '#');
214
215 if(apply_filters('ws_plugin__s2member_during_add_admin_options_add_logs_page', (!is_multisite() || !c_ws_plugin__s2member_utils_conds::is_multisite_farm() || is_main_site()), get_defined_vars()))
216 add_submenu_page($menu, 's2Member Logs', 'Log Files (Debug)', 'create_users', 'ws-plugin--s2member-logs', 'c_ws_plugin__s2member_menu_pages::logs_page');
217
218 do_action('ws_plugin__s2member_during_add_admin_options_additional_pages', get_defined_vars());
219 }
220 do_action('ws_plugin__s2member_after_add_admin_options', get_defined_vars());
221 }
222
223 /**
224 * Adds network option menus / sub-menus.
225 *
226 * @package s2Member\Menu_Pages
227 * @since 3.5
228 *
229 * @attaches-to ``add_action('network_admin_menu');``
230 */
231 public static function add_network_admin_options()
232 {
233 do_action('ws_plugin__s2member_before_add_network_admin_options', get_defined_vars());
234
235 if(apply_filters('ws_plugin__s2member_during_add_network_admin_options_create_menu_items', TRUE, get_defined_vars()))
236 {
237 if((is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site()) || apply_filters('ws_plugin__s2member_during_add_network_admin_options_clear_right_side', FALSE, get_defined_vars()))
238 $GLOBALS['WS_PLUGIN__']['s2member']['c']['menu_pages'] = array(); // Clear right side.
239
240 $menu = 'ws-plugin--s2member-mms-ops'; // Used below for nesting additional sub-menu pages.
241
242 add_menu_page('s2Member', 's2Member', 'create_users', $menu, 'c_ws_plugin__s2member_menu_pages::mms_ops_page', $GLOBALS['WS_PLUGIN__']['s2member']['c']['dir_url'].'/src/images/brand-favicon.png');
243
244 add_submenu_page($menu, 's2Member Multisite (Configuration)', 'Multisite (Config)', 'create_users', 'ws-plugin--s2member-mms-ops', 'c_ws_plugin__s2member_menu_pages::mms_ops_page');
245
246 do_action('ws_plugin__s2member_during_add_network_admin_options_additional_pages', get_defined_vars());
247 }
248 do_action('ws_plugin__s2member_after_add_network_admin_options', get_defined_vars());
249 }
250
251 /**
252 * A sort of callback function to add the settings link.
253 *
254 * @package s2Member\Menu_Pages
255 * @since 3.5
256 *
257 * @attaches-to ``add_filter('plugin_action_links');``
258 *
259 * @param array $actions Expects an existing array of actions links, passed in by the Filter.
260 * @param string $plugin_file Expects path to a plugin file. We need to test against this for s2Member.
261 *
262 * @return array An array of links, Filtered by this routine.
263 */
264 public static function _add_settings_link($actions = array(), $plugin_file = '')
265 {
266 foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
267 do_action('_ws_plugin__s2member_before_add_settings_link', get_defined_vars());
268 unset($__refs, $__v); // Housekeeping.
269
270 if($plugin_file === $GLOBALS['WS_PLUGIN__']['s2member']['c']['plugin_basename'] && is_array($actions))
271 {
272 $settings = '<a href="'.esc_attr(admin_url('/admin.php?page=ws-plugin--s2member-gen-ops')).'">Settings</a>';
273 array_unshift($actions, apply_filters('ws_plugin__s2member_add_settings_link', $settings, get_defined_vars()));
274
275 foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
276 do_action('_ws_plugin__s2member_during_add_settings_link', get_defined_vars());
277 unset($__refs, $__v); // Housekeeping.
278 }
279 return apply_filters('_ws_plugin__s2member_add_settings_link', $actions, get_defined_vars());
280 }
281
282 /**
283 * Enqueue scripts for administrative menu pages.
284 *
285 * @package s2Member\Menu_Pages
286 * @since 3.5
287 *
288 * @attaches-to ``add_action('admin_print_scripts');``
289 */
290 public static function add_admin_scripts()
291 {
292 do_action('ws_plugin__s2member_before_add_admin_scripts', get_defined_vars());
293
294 if(!empty($_GET['page']) && preg_match('/ws-plugin--s2member-/', $_GET['page']))
295 {
296 wp_enqueue_script('jquery');
297 wp_enqueue_script('thickbox');
298 wp_enqueue_script('media-upload');
299 wp_enqueue_script('jquery-ui-core');
300 wp_enqueue_script('jquery-sprintf', $GLOBALS['WS_PLUGIN__']['s2member']['c']['dir_url'].'/src/includes/jquery/jquery.sprintf/jquery.sprintf.min.js', array('jquery'), c_ws_plugin__s2member_utilities::ver_checksum());
301 wp_enqueue_script('jquery-json-ps', $GLOBALS['WS_PLUGIN__']['s2member']['c']['dir_url'].'/src/includes/jquery/jquery.json-ps/jquery.json-ps.min.js', array('jquery'), c_ws_plugin__s2member_utilities::ver_checksum());
302 wp_enqueue_script('jquery-ui-effects', $GLOBALS['WS_PLUGIN__']['s2member']['c']['dir_url'].'/src/includes/jquery/jquery.ui-effects/jquery.ui-effects.min.js', array('jquery', 'jquery-ui-core'), c_ws_plugin__s2member_utilities::ver_checksum());
303 wp_enqueue_script('ws-plugin--s2member-menu-pages', admin_url('admin.php?ws_plugin__s2member_menu_pages_js='.urlencode(mt_rand()), is_ssl() ? 'https' : 'http'), array('jquery', 'thickbox', 'media-upload', 'jquery-sprintf', 'jquery-json-ps', 'jquery-ui-core', 'jquery-ui-effects', 'password-strength-meter'), c_ws_plugin__s2member_utilities::ver_checksum());
304
305 do_action('ws_plugin__s2member_during_add_admin_scripts', get_defined_vars());
306 }
307 do_action('ws_plugin__s2member_after_add_admin_scripts', get_defined_vars());
308 }
309
310 /**
311 * Enqueue styles for administrative menu pages.
312 *
313 * @package s2Member\Menu_Pages
314 * @since 3.5
315 *
316 * @attaches-to ``add_action('admin_print_styles');``
317 */
318 public static function add_admin_styles()
319 {
320 do_action('ws_plugin__s2member_before_add_admin_styles', get_defined_vars());
321
322 if(!empty($_GET['page']) && preg_match('/ws-plugin--s2member-/', $_GET['page']))
323 {
324 wp_enqueue_style('thickbox');
325 wp_enqueue_style('ws-plugin--s2member-menu-pages', admin_url('admin.php?ws_plugin__s2member_menu_pages_css='.urlencode(mt_rand()), is_ssl() ? 'https' : 'http'), array('thickbox'), c_ws_plugin__s2member_utilities::ver_checksum(), 'all');
326
327 do_action('ws_plugin__s2member_during_add_admin_styles', get_defined_vars());
328 }
329 do_action('ws_plugin__s2member_after_add_admin_styles', get_defined_vars());
330 }
331
332 /**
333 * Handles log file downloads.
334 *
335 * @package s2Member\Menu_Pages
336 * @since 120310
337 */
338 public static function log_file_downloader()
339 {
340 if(!current_user_can('create_users')) return;
341 if(is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site())
342 return; // We do NOT provide this functionality on Child Blogs of a Blog Farm Network.
343
344 if(!empty($_GET['ws_plugin__s2member_download_log_file']) && is_string($log_file = $_GET['ws_plugin__s2member_download_log_file']) && strpos($log_file, '..') === FALSE && strpos(basename($log_file), '.') !== 0)
345 if(!empty($_GET['ws_plugin__s2member_download_log_file_v']) && is_string($nonce = $_GET['ws_plugin__s2member_download_log_file_v']) && wp_verify_nonce($nonce, 'ws-plugin--s2member-download-log-file-v'))
346 {
347 $logs_dir = $GLOBALS['WS_PLUGIN__']['s2member']['c']['logs_dir'];
348
349 if(file_exists($logs_dir.'/'.$log_file))
350 $log_file_contents = file_get_contents($logs_dir.'/'.$log_file);
351 else $log_file_contents = '';
352
353 @set_time_limit(0);
354 @ini_set('memory_limit', apply_filters('admin_memory_limit', WP_MAX_MEMORY_LIMIT));
355
356 @ini_set('zlib.output_compression', 0);
357 if(function_exists('apache_setenv'))
358 @apache_setenv('no-gzip', '1');
359
360 while(@ob_end_clean()) ;
361
362 status_header(200); // 200 OK status header.
363
364 header('Content-Encoding: none');
365 header('Accept-Ranges: none');
366 header('Content-Type: text/plain; charset=UTF-8');
367 header('Content-Length: '.strlen($log_file_contents));
368 header('Expires: '.gmdate('D, d M Y H:i:s', strtotime('-1 week')).' GMT');
369 header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
370 header('Cache-Control: no-cache, must-revalidate, max-age=0');
371 header('Cache-Control: post-check=0, pre-check=0', FALSE);
372 header('Pragma: no-cache');
373
374 header('Content-Disposition: attachment; filename="'.$log_file.'"');
375
376 exit($log_file_contents); // Log file.
377 }
378 }
379
380 /**
381 * Handles log file downloads (in ZIP format).
382 *
383 * @package s2Member\Menu_Pages
384 * @since 120310
385 */
386 public static function logs_zip_downloader()
387 {
388 if(!current_user_can('create_users')) return;
389 if(is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site())
390 return; // We do NOT provide this functionality on Child Blogs of a Blog Farm Network.
391
392 if(!empty($_POST['ws_plugin__s2member_logs_download_zip']) && is_string($nonce = $_POST['ws_plugin__s2member_logs_download_zip']) && wp_verify_nonce($nonce, 'ws-plugin--s2member-logs-download-zip'))
393 {
394 $logs_dir = $GLOBALS['WS_PLUGIN__']['s2member']['c']['logs_dir'];
395 $s2member_logs_zip = $logs_dir.'/'.$_SERVER['HTTP_HOST'].'--s2member-logs.zip';
396
397 if(is_dir($logs_dir)) // Do we have a logs directory?
398 {
399 include_once ABSPATH.'wp-admin/includes/class-pclzip.php';
400
401 if(file_exists($s2member_logs_zip) && is_writable($s2member_logs_zip))
402 unlink($s2member_logs_zip);
403
404 $archive = new PclZip($s2member_logs_zip);
405 $archive->create($logs_dir, PCLZIP_OPT_REMOVE_ALL_PATH);
406 }
407 if(file_exists($s2member_logs_zip))
408 $s2member_logs_zip_size = filesize($s2member_logs_zip);
409 else $s2member_logs_zip_size = 0;
410
411 @set_time_limit(0);
412 @ini_set('memory_limit', apply_filters('admin_memory_limit', WP_MAX_MEMORY_LIMIT));
413
414 @ini_set('zlib.output_compression', 0);
415 if(function_exists('apache_setenv'))
416 @apache_setenv('no-gzip', '1');
417
418 while(@ob_end_clean()) ;
419
420 status_header(200); // 200 OK status header.
421
422 header('Content-Encoding: none');
423 header('Accept-Ranges: none');
424 header('Content-Type: application/zip');
425 header('Content-Length: '.$s2member_logs_zip_size);
426 header('Expires: '.gmdate('D, d M Y H:i:s', strtotime('-1 week')).' GMT');
427 header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
428 header('Cache-Control: no-cache, must-revalidate, max-age=0');
429 header('Cache-Control: post-check=0, pre-check=0', FALSE);
430 header('Pragma: no-cache');
431
432 header('Content-Disposition: attachment; filename="'.basename($s2member_logs_zip).'"');
433
434 if($s2member_logs_zip_size && is_resource($resource = fopen($s2member_logs_zip, 'rb')))
435 {
436 $_bytes_to_read = $s2member_logs_zip_size; // Total bytes we need to read for this file.
437
438 $chunk_size = apply_filters('ws_plugin__s2member_file_downloads_chunk_size', 2097152, get_defined_vars());
439
440 while($_bytes_to_read) // We have bytes to read here.
441 {
442 $_bytes_to_read -= ($_reading = ($_bytes_to_read > $chunk_size) ? $chunk_size : $_bytes_to_read);
443 echo fread($resource, $_reading); // Serve file in chunks (default chunk size is 2MB).
444 flush(); // Flush each chunk to the browser as it is served (avoids high memory consumption).
445 }
446 fclose($resource); // Close file resource handle.
447 unset($_bytes_to_read, $_reading); // Housekeeping.
448 }
449 exit; // Clean exit after serving file.
450 }
451 }
452
453 /**
454 * Archives existing log files and starts fresh with new logs.
455 *
456 * @package s2Member\Menu_Pages
457 * @since 120310
458 */
459 public static function archive_logs_start_fresh()
460 {
461 if(!current_user_can('create_users')) return;
462 if(is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site())
463 return; // We do NOT provide this functionality on Child Blogs of a Blog Farm Network.
464
465 if(!empty($_POST['ws_plugin__s2member_logs_archive_start_fresh']) && is_string($nonce = $_POST['ws_plugin__s2member_logs_archive_start_fresh']) && wp_verify_nonce($nonce, 'ws-plugin--s2member-logs-archive-start-fresh'))
466 {
467 if(is_dir($logs_dir = $GLOBALS['WS_PLUGIN__']['s2member']['c']['logs_dir']))
468 foreach(scandir($logs_dir) as $log_file) // Archive existing log files here.
469 {
470 if(preg_match('/\.log$/', $log_file) && stripos($log_file, '-ARCHIVED-') === FALSE)
471 if(is_file($log_dir_file = $logs_dir.'/'.$log_file) && is_writable($log_dir_file))
472 if(!rename($log_dir_file, preg_replace('/\.log$/i', '', $log_dir_file).'-ARCHIVED-'.date('m-d-Y').'-'.time().'.log'))
473 $error = TRUE;
474 }
475 if(!empty($error))
476 c_ws_plugin__s2member_admin_notices::display_admin_notice('Unknown error when attempting to archive log files. Please check directory permissions.', TRUE);
477 else c_ws_plugin__s2member_admin_notices::display_admin_notice('All log files have been archived succesfully.');
478 }
479 }
480
481 /**
482 * Deletes existing log files and starts fresh with new logs.
483 *
484 * @package s2Member\Menu_Pages
485 * @since 120312
486 */
487 public static function delete_logs_start_fresh()
488 {
489 if(!current_user_can('create_users')) return;
490 if(is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site())
491 return; // We do NOT provide this functionality on Child Blogs of a Blog Farm Network.
492
493 if(!empty($_POST['ws_plugin__s2member_logs_delete_start_fresh']) && is_string($nonce = $_POST['ws_plugin__s2member_logs_delete_start_fresh']) && wp_verify_nonce($nonce, 'ws-plugin--s2member-logs-delete-start-fresh'))
494 {
495 if(is_dir($logs_dir = $GLOBALS['WS_PLUGIN__']['s2member']['c']['logs_dir']))
496 foreach(scandir($logs_dir) as $log_file) // Delete existing log files here.
497 {
498 if(preg_match('/\.log$/', $log_file))
499 if(is_file($log_dir_file = $logs_dir.'/'.$log_file) && is_writable($log_dir_file))
500 if(!unlink($log_dir_file)) $error = TRUE;
501 }
502 if(!empty($error))
503 c_ws_plugin__s2member_admin_notices::display_admin_notice('Unknown error when attempting to delete log files. Please check directory permissions.', TRUE);
504 else c_ws_plugin__s2member_admin_notices::display_admin_notice('All log files have been deleted succesfully.');
505 }
506 }
507
508 /**
509 * Builds and handles the Getting Started page.
510 *
511 * @package s2Member\Menu_Pages
512 * @since 3.5
513 */
514 public static function start_page()
515 {
516 do_action('ws_plugin__s2member_before_start_page', get_defined_vars());
517
518 include_once dirname(dirname(__FILE__)).'/menu-pages/start.inc.php';
519
520 do_action('ws_plugin__s2member_after_start_page', get_defined_vars());
521 }
522
523 /**
524 * Builds and handles the Getting Help page.
525 *
526 * @package s2Member\Menu_Pages
527 * @since 151218
528 */
529 public static function help_page()
530 {
531 do_action('ws_plugin__s2member_before_help_page', get_defined_vars());
532
533 include_once dirname(dirname(__FILE__)).'/menu-pages/help.inc.php';
534
535 do_action('ws_plugin__s2member_after_help_page', get_defined_vars());
536 }
537
538 /**
539 * Builds and handles the Main Multisite Options page.
540 *
541 * @package s2Member\Menu_Pages
542 * @since 3.5
543 */
544 public static function mms_ops_page()
545 {
546 do_action('ws_plugin__s2member_before_mms_ops_page', get_defined_vars());
547
548 include_once dirname(dirname(__FILE__)).'/menu-pages/mms-ops.inc.php';
549
550 do_action('ws_plugin__s2member_after_mms_ops_page', get_defined_vars());
551 }
552
553 /**
554 * Builds and handles the General Options page.
555 *
556 * @package s2Member\Menu_Pages
557 * @since 3.5
558 */
559 public static function gen_ops_page()
560 {
561 do_action('ws_plugin__s2member_before_gen_ops_page', get_defined_vars());
562
563 c_ws_plugin__s2member_menu_pages::update_all_options();
564
565 include_once dirname(dirname(__FILE__)).'/menu-pages/gen-ops.inc.php';
566
567 do_action('ws_plugin__s2member_after_gen_ops_page', get_defined_vars());
568 }
569
570 /**
571 * Builds and handles the Restriction Options page.
572 *
573 * @package s2Member\Menu_Pages
574 * @since 3.5
575 */
576 public static function res_ops_page()
577 {
578 do_action('ws_plugin__s2member_before_res_ops_page', get_defined_vars());
579
580 c_ws_plugin__s2member_menu_pages::update_all_options();
581
582 include_once dirname(dirname(__FILE__)).'/menu-pages/res-ops.inc.php';
583
584 do_action('ws_plugin__s2member_after_res_ops_page', get_defined_vars());
585 }
586
587 /**
588 * Builds and handles the Paypal Options page.
589 *
590 * @package s2Member\Menu_Pages
591 * @since 3.5
592 */
593 public static function paypal_ops_page()
594 {
595 do_action('ws_plugin__s2member_before_paypal_ops_page', get_defined_vars());
596
597 c_ws_plugin__s2member_menu_pages::update_all_options();
598
599 $logs_dir = $GLOBALS['WS_PLUGIN__']['s2member']['c']['logs_dir'];
600
601 if(!is_dir($logs_dir) && is_writable(dirname(c_ws_plugin__s2member_utils_dirs::strip_dir_app_data($logs_dir))))
602 mkdir($logs_dir, 0777, TRUE).clearstatcache();
603
604 $htaccess = $GLOBALS['WS_PLUGIN__']['s2member']['c']['logs_dir'].'/.htaccess';
605 $htaccess_contents = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents($GLOBALS['WS_PLUGIN__']['s2member']['c']['logs_dir_htaccess'])));
606
607 if(is_dir($logs_dir) && is_writable($logs_dir) && !file_exists($htaccess))
608 file_put_contents($htaccess, $htaccess_contents).clearstatcache();
609
610 if($GLOBALS['WS_PLUGIN__']['s2member']['o']['gateway_debug_logs']) // Logging enabled?
611 {
612 if(!is_dir($logs_dir)) // If the security-enabled logs directory does not exist yet.
613 c_ws_plugin__s2member_admin_notices::display_admin_notice('The security-enabled logs directory (<code>'.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($logs_dir)).'</code>) does not exist. Please create this directory manually &amp; make it writable (chmod 777).', TRUE);
614
615 else if(!is_writable($logs_dir)) // If the logs directory is not writable yet.
616 c_ws_plugin__s2member_admin_notices::display_admin_notice('Permissions error. The security-enabled logs directory (<code>'.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($logs_dir)).'</code>) is not writable. Please make this directory writable (chmod 777).', TRUE);
617
618 if(!file_exists($htaccess)) // If the .htaccess file has not been created yet.
619 c_ws_plugin__s2member_admin_notices::display_admin_notice('The .htaccess protection file (<code>'.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($htaccess)).'</code>) does not exist. Please create this file manually. Inside your .htaccess file, add this:<br /><pre>'.esc_html($htaccess_contents).'</pre>', TRUE);
620
621 else if(!preg_match('/deny from all/i', file_get_contents($htaccess))) // Else if the .htaccess file does not offer the required protection.
622 c_ws_plugin__s2member_admin_notices::display_admin_notice('Unprotected. The .htaccess protection file (<code>'.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($htaccess)).'</code>) does not contain <code>deny from all</code>. Inside your .htaccess file, add this:<br /><pre>'.esc_html($htaccess_contents).'</pre>', TRUE);
623 }
624 include_once dirname(dirname(__FILE__)).'/menu-pages/paypal-ops.inc.php';
625
626 do_action('ws_plugin__s2member_after_paypal_ops_page', get_defined_vars());
627 }
628
629 /**
630 * Builds and handles the Download Options page.
631 *
632 * @package s2Member\Menu_Pages
633 * @since 3.5
634 */
635 public static function down_ops_page()
636 {
637 do_action('ws_plugin__s2member_before_down_ops_page', get_defined_vars());
638
639 c_ws_plugin__s2member_menu_pages::update_all_options();
640
641 if(!empty($_REQUEST['ws_plugin__s2member_cf_options_reset'])
642 && wp_verify_nonce($_REQUEST['ws_plugin__s2member_cf_options_reset'], 'ws-plugin--s2member-cf-options-reset')
643 )
644 {
645 c_ws_plugin__s2member_files_in::reset_aws_cf_config_values(); // A full CloudFront reset.
646 c_ws_plugin__s2member_admin_notices::display_admin_notice('Amazon CloudFront configuration reset successfully.');
647 }
648 $files_dir = $GLOBALS['WS_PLUGIN__']['s2member']['c']['files_dir'];
649
650 $htaccess = $GLOBALS['WS_PLUGIN__']['s2member']['c']['files_dir'].'/.htaccess';
651 $htaccess_contents = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents($GLOBALS['WS_PLUGIN__']['s2member']['c']['files_dir_htaccess'])));
652
653 $no_gzip_htaccess = ABSPATH.'.htaccess'; // Always located in the absolute root path for WordPress.
654 $no_gzip_htaccess_contents = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents($GLOBALS['WS_PLUGIN__']['s2member']['c']['files_no_gzip_htaccess'])));
655
656 if(!c_ws_plugin__s2member_files::no_gzip_rules_in_root_htaccess()) // If s2Member's GZIP exclusions do NOT yet exist in the root `.htaccess` file.
657 c_ws_plugin__s2member_files::write_no_gzip_into_root_htaccess().clearstatcache(); // Handle the root `.htaccess` file now.
658
659 if(!is_dir($files_dir) && is_writable(dirname(c_ws_plugin__s2member_utils_dirs::strip_dir_app_data($files_dir))))
660 mkdir($files_dir, 0777, TRUE).clearstatcache(); // Create this directory structure now.
661
662 if(is_dir($files_dir) && is_writable($files_dir) && !file_exists($htaccess)) // This file does NOT exist yet?
663 file_put_contents($htaccess, $htaccess_contents).clearstatcache(); // Create the `.htaccess` file now.
664
665 if(!c_ws_plugin__s2member_files::no_gzip_rules_in_root_htaccess()) // If s2Member's GZIP exclusions do NOT yet exist in the root `.htaccess` file.
666 c_ws_plugin__s2member_admin_notices::display_admin_notice('Possible GZIP conflict on server. Unable to write GZIP exclusions into root .htaccess file (<code>'.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($no_gzip_htaccess)).'</code>). Please read the panel below: <strong>Preventing GZIP Conflicts</strong>, and add this section yourself:<br /><pre>'.esc_html($no_gzip_htaccess_contents).'</pre>', TRUE);
667
668 if(!is_dir($files_dir)) // If the security-enabled files directory does not exist yet.
669 c_ws_plugin__s2member_admin_notices::display_admin_notice('The security-enabled files directory (<code>'.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($files_dir)).'</code>) does not exist. Please create this directory manually.', TRUE);
670
671 if(!file_exists($htaccess)) // If the `.htaccess` file has not been created yet.
672 c_ws_plugin__s2member_admin_notices::display_admin_notice('The .htaccess protection file (<code>'.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($htaccess)).'</code>) does not exist. Please create this file manually. Inside your .htaccess file, add this:<br /><pre>'.esc_html($htaccess_contents).'</pre>', TRUE);
673
674 else if(!preg_match('/deny from all/i', file_get_contents($htaccess))) // Else if the `.htaccess` file does not offer the required protection.
675 c_ws_plugin__s2member_admin_notices::display_admin_notice('Unprotected. The .htaccess protection file (<code>'.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($htaccess)).'</code>) does not contain <code>deny from all</code>. Inside your .htaccess file, add this:<br /><pre>'.esc_html($htaccess_contents).'</pre>', TRUE);
676
677 if(!empty($_POST['ws_plugin__s2member_amazon_cf_files_auto_configure_distros']) && ($nonce = $_POST['ws_plugin__s2member_amazon_cf_files_auto_configure_distros']) && wp_verify_nonce($nonce, 'ws-plugin--s2member-amazon-cf-files-auto-configure-distros'))
678 if(($amazon_cf_auto_configure_distros = c_ws_plugin__s2member_files_in::amazon_cf_auto_configure_distros()) && $amazon_cf_auto_configure_distros['success'])
679 c_ws_plugin__s2member_admin_notices::display_admin_notice('Amazon CloudFront Distributions auto-configured successfully. Please allow 30 minutes for initial propagation. <strong>Tip:</strong> If you try to stream over the RTMP protocol using something like the <code>[s2Stream /]</code> shortcode, and you keep getting an "ID Not Found" error while using JW Player; please note that it can <em>sometimes</em> take a full 24 hours for RTMP (i.e., streaming distributions) to begin working properly. This is because there are a few initialization routines that must complete on the AWS side when you first integrate with CloudFront. Please be patient.'.(($GLOBALS['WS_PLUGIN__']['s2member']['o']['amazon_cf_files_distro_downloads_cname']) ? '<br /><em>Downloads Distribution CNAME: <code>'.esc_html($GLOBALS['WS_PLUGIN__']['s2member']['o']['amazon_cf_files_distro_downloads_cname']).' &mdash;&raquo; '.esc_html($GLOBALS['WS_PLUGIN__']['s2member']['o']['amazon_cf_files_distro_downloads_dname']).'</code></em>' : '').(($GLOBALS['WS_PLUGIN__']['s2member']['o']['amazon_cf_files_distro_streaming_cname']) ? '<br /><em>Streaming Distribution CNAME: <code>'.esc_html($GLOBALS['WS_PLUGIN__']['s2member']['o']['amazon_cf_files_distro_streaming_cname']).' &mdash;&raquo; '.esc_html($GLOBALS['WS_PLUGIN__']['s2member']['o']['amazon_cf_files_distro_streaming_dname']).'</code></em>' : ''));
680 else // Else there was an error. We need to report this back to the site owner so they can understand what's going on.
681 (c_ws_plugin__s2member_menu_pages::$pre_display_errors['cf_files_auto_configure_distros'] = TRUE).c_ws_plugin__s2member_admin_notices::display_admin_notice('Unable to auto-configure Amazon CloudFront Distributions.<br />Error code: <code>'.esc_html($amazon_cf_auto_configure_distros['code']).'</code>. Error Message: <code>'.esc_html($amazon_cf_auto_configure_distros['message']).'</code>', TRUE);
682
683 if(!empty($_POST['ws_plugin__s2member_amazon_s3_files_auto_configure_acls']) && ($nonce = $_POST['ws_plugin__s2member_amazon_s3_files_auto_configure_acls']) && wp_verify_nonce($nonce, 'ws-plugin--s2member-amazon-s3-files-auto-configure-acls'))
684 if(($amazon_s3_auto_configure_acls = c_ws_plugin__s2member_files_in::amazon_s3_auto_configure_acls()) && $amazon_s3_auto_configure_acls['success'])
685 c_ws_plugin__s2member_admin_notices::display_admin_notice('Amazon S3 ACLs auto-configured successfully.');
686 else // Else there was an error. We need to report this back to the site owner so they can understand what's going on.
687 (c_ws_plugin__s2member_menu_pages::$pre_display_errors['s3_files_auto_configure_acls'] = TRUE).c_ws_plugin__s2member_admin_notices::display_admin_notice('Unable to auto-configure Amazon S3 ACLs.<br />Error code: <code>'.esc_html($amazon_s3_auto_configure_acls['code']).'</code>. Error Message: <code>'.esc_html($amazon_s3_auto_configure_acls['message']).'</code>', TRUE);
688
689 include_once dirname(dirname(__FILE__)).'/menu-pages/down-ops.inc.php';
690
691 do_action('ws_plugin__s2member_after_down_ops_page', get_defined_vars());
692 }
693
694 /**
695 * Builds and handles the API Tracking options page.
696 *
697 * @package s2Member\Menu_Pages
698 * @since 3.5
699 */
700 public static function trk_ops_page()
701 {
702 do_action('ws_plugin__s2member_before_trk_ops_page', get_defined_vars());
703
704 c_ws_plugin__s2member_menu_pages::update_all_options();
705
706 include_once dirname(dirname(__FILE__)).'/menu-pages/trk-ops.inc.php';
707
708 do_action('ws_plugin__s2member_after_trk_ops_page', get_defined_vars());
709 }
710
711 /**
712 * Builds and handles the API List Server options page.
713 *
714 * @package s2Member\Menu_Pages
715 * @since 3.5
716 */
717 public static function els_ops_page()
718 {
719 do_action('ws_plugin__s2member_before_els_ops_page', get_defined_vars());
720
721 c_ws_plugin__s2member_menu_pages::update_all_options();
722
723 include_once dirname(dirname(__FILE__)).'/menu-pages/els-ops.inc.php';
724
725 do_action('ws_plugin__s2member_after_els_ops_page', get_defined_vars());
726 }
727
728 /**
729 * Builds and handles the API Notifications page.
730 *
731 * @package s2Member\Menu_Pages
732 * @since 3.5
733 */
734 public static function api_ops_page()
735 {
736 do_action('ws_plugin__s2member_before_api_ops_page', get_defined_vars());
737
738 c_ws_plugin__s2member_menu_pages::update_all_options();
739
740 include_once dirname(dirname(__FILE__)).'/menu-pages/api-ops.inc.php';
741
742 do_action('ws_plugin__s2member_after_api_ops_page', get_defined_vars());
743 }
744
745 /**
746 * Builds and handles the PayPal Button Generator page.
747 *
748 * @package s2Member\Menu_Pages
749 * @since 3.5
750 */
751 public static function paypal_buttons_page()
752 {
753 do_action('ws_plugin__s2member_before_paypal_buttons_page', get_defined_vars());
754
755 if(!$GLOBALS['WS_PLUGIN__']['s2member']['o']['paypal_business'] || !$GLOBALS['WS_PLUGIN__']['s2member']['o']['paypal_merchant_id'] || !$GLOBALS['WS_PLUGIN__']['s2member']['o']['paypal_api_username'] || !$GLOBALS['WS_PLUGIN__']['s2member']['o']['paypal_api_password'] || !$GLOBALS['WS_PLUGIN__']['s2member']['o']['paypal_api_signature'])
756 c_ws_plugin__s2member_admin_notices::display_admin_notice('Please configure <strong>s2Member → PayPal Options</strong> first. Once all of your PayPal Options are configured; including your Email Address, Merchant ID, API Username, Password, and Signature; return to this page &amp; generate your PayPal Button(s).', TRUE);
757
758 include_once dirname(dirname(__FILE__)).'/menu-pages/paypal-buttons.inc.php';
759
760 do_action('ws_plugin__s2member_after_paypal_buttons_page', get_defined_vars());
761 }
762
763 /**
764 * Builds and handles the API Scripting page.
765 *
766 * @package s2Member\Menu_Pages
767 * @since 3.5
768 */
769 public static function scripting_page()
770 {
771 do_action('ws_plugin__s2member_before_scripting_page', get_defined_vars());
772
773 c_ws_plugin__s2member_menu_pages::update_all_options();
774
775 include_once dirname(dirname(__FILE__)).'/menu-pages/scripting.inc.php';
776
777 do_action('ws_plugin__s2member_after_scripting_page', get_defined_vars());
778 }
779
780 /**
781 * Builds and handles the Integrations page.
782 *
783 * @package s2Member\Menu_Pages
784 * @since 3.5
785 */
786 public static function integrations_page()
787 {
788 do_action('ws_plugin__s2member_before_integrations_page', get_defined_vars());
789
790 include_once dirname(dirname(__FILE__)).'/menu-pages/integrations.inc.php';
791
792 do_action('ws_plugin__s2member_after_integrations_page', get_defined_vars());
793 }
794
795 /**
796 * Builds and handles the Logs page.
797 *
798 * @package s2Member\Menu_Pages
799 * @since 120310
800 */
801 public static function logs_page()
802 {
803 do_action('ws_plugin__s2member_before_logs_page', get_defined_vars());
804
805 c_ws_plugin__s2member_menu_pages::update_all_options();
806 c_ws_plugin__s2member_menu_pages::archive_logs_start_fresh();
807 c_ws_plugin__s2member_menu_pages::delete_logs_start_fresh();
808
809 $logs_dir = $GLOBALS['WS_PLUGIN__']['s2member']['c']['logs_dir'];
810
811 if(!is_dir($logs_dir) && is_writable(dirname(c_ws_plugin__s2member_utils_dirs::strip_dir_app_data($logs_dir))))
812 mkdir($logs_dir, 0777, TRUE).clearstatcache();
813
814 $htaccess = $GLOBALS['WS_PLUGIN__']['s2member']['c']['logs_dir'].'/.htaccess';
815 $htaccess_contents = trim(c_ws_plugin__s2member_utilities::evl(file_get_contents($GLOBALS['WS_PLUGIN__']['s2member']['c']['logs_dir_htaccess'])));
816
817 if(is_dir($logs_dir) && is_writable($logs_dir) && !file_exists($htaccess))
818 file_put_contents($htaccess, $htaccess_contents).clearstatcache();
819
820 if(!is_dir($logs_dir)) // If the security-enabled logs directory does not exist yet.
821 c_ws_plugin__s2member_admin_notices::display_admin_notice('The security-enabled logs directory (<code>'.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($logs_dir)).'</code>) does not exist. Please create this directory manually &amp; make it writable (chmod 777).', TRUE);
822
823 else if(!is_writable($logs_dir)) // If the logs directory is not writable yet.
824 c_ws_plugin__s2member_admin_notices::display_admin_notice('Permissions error. The security-enabled logs directory (<code>'.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($logs_dir)).'</code>) is not writable. Please make this directory writable (chmod 777).', TRUE);
825
826 if(!file_exists($htaccess)) // If the .htaccess file has not been created yet.
827 c_ws_plugin__s2member_admin_notices::display_admin_notice('The .htaccess protection file (<code>'.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($htaccess)).'</code>) does not exist. Please create this file manually. Inside your .htaccess file, add this:<br /><pre>'.esc_html($htaccess_contents).'</pre>', TRUE);
828
829 else if(!preg_match('/deny from all/i', file_get_contents($htaccess))) // Else if the .htaccess file does not offer the required protection.
830 c_ws_plugin__s2member_admin_notices::display_admin_notice('Unprotected. The .htaccess protection file (<code>'.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($htaccess)).'</code>) does not contain <code>deny from all</code>. Inside your .htaccess file, add this:<br /><pre>'.esc_html($htaccess_contents).'</pre>', TRUE);
831
832 if(!$GLOBALS['WS_PLUGIN__']['s2member']['o']['gateway_debug_logs']) // Logging disabled?
833 c_ws_plugin__s2member_admin_notices::display_admin_notice('Logging is currently disabled by your configuration.');
834
835 include_once dirname(dirname(__FILE__)).'/menu-pages/logs.inc.php';
836
837 do_action('ws_plugin__s2member_after_logs_page', get_defined_vars());
838 }
839
840 /**
841 * Registers the Get Help panel across admin pages.
842 *
843 * @package s2Member\Menu_Pages
844 * @since 250824
845 *
846 * @attaches-to ``add_action('admin_menu');``
847 */
848 public static function get_help_panel() {
849 $hooks = array(
850 // Framework
851 'ws_plugin__s2member_during_api_ops_page_before_left_sections_form',
852 'ws_plugin__s2member_during_down_ops_page_before_left_sections_form',
853 'ws_plugin__s2member_during_els_ops_page_before_left_sections_form',
854 'ws_plugin__s2member_during_gen_ops_page_before_left_sections_form',
855 'ws_plugin__s2member_during_help_page_before_left_sections',
856 'ws_plugin__s2member_during_integrations_page_before_left_sections',
857 'ws_plugin__s2member_during_logs_page_before_left_sections',
858 'ws_plugin__s2member_during_paypal_buttons_page_before_left_sections',
859 'ws_plugin__s2member_during_paypal_ops_page_before_left_sections_form',
860 'ws_plugin__s2member_during_res_ops_page_before_left_sections_form',
861 'ws_plugin__s2member_during_scripting_page_before_left_sections',
862 'ws_plugin__s2member_during_start_page_before_left_sections',
863 'ws_plugin__s2member_during_trk_ops_page_before_left_sections_form',
864 // Pro
865 'ws_plugin__s2member_during_authnet_forms_page_before_left_sections',
866 'ws_plugin__s2member_during_authnet_ops_page_before_left_sections_form',
867 'ws_plugin__s2member_during_clickbank_buttons_page_before_left_sections',
868 'ws_plugin__s2member_during_clickbank_ops_page_before_left_sections_form',
869 'ws_plugin__s2member_during_coupon_codes_page_before_left_sections_form',
870 'ws_plugin__s2member_during_import_export_page_before_left_sections',
871 'ws_plugin__s2member_during_mms_ops_page_before_left_sections_form',
872 'ws_plugin__s2member_during_other_gateways_page_before_left_sections_form',
873 'ws_plugin__s2member_during_paypal_forms_page_before_left_sections',
874 'ws_plugin__s2member_during_stripe_forms_page_before_left_sections',
875 'ws_plugin__s2member_during_stripe_ops_page_before_left_sections_form',
876 );
877
878 foreach ($hooks as $hook) {
879 add_action($hook, 'c_ws_plugin__s2member_menu_pages::get_help_panel_load', 1, 1);
880 }
881 }
882
883 /**
884 * Renders the Get Help panel (computes $notice/$draft and includes template).
885 *
886 * @package s2Member\Menu_Pages
887 * @since 250824
888 *
889 * @param array $vars Optional vars passed by the hook (unused).
890 */
891 public static function get_help_panel_load($vars = array()) {
892 if (!current_user_can('manage_options')) return;
893
894 // Build notice (if POST).
895 $notice = array('type' => '', 'text' => '');
896 if (!empty($_POST['s2m_help_nonce']) && isset($_POST['s2m_help_submit']) && wp_verify_nonce($_POST['s2m_help_nonce'], 's2member_get_help')) {
897 $result = c_ws_plugin__s2member_menu_pages::get_help_mail();
898 if (!empty($result['ok'])) {
899 $notice = array('type' => 'success', 'text' => __('Thanks — your message was sent. You’ll receive a copy by email.', 's2member'));
900 $_POST = array(); // clear fields after success so defaults repopulate
901 } else {
902 $msg = isset($result['msg']) ? $result['msg'] : __('Sorry, your message could not be sent. Please try again.', 's2member');
903 $notice = array('type' => 'error', 'text' => $msg);
904 }
905 }
906
907 // Build draft (preserve POST on error; else defaults from current user).
908 $current = wp_get_current_user();
909 $draft = array(
910 'name' => is_object($current) ? trim($current->display_name) : '',
911 'email' => is_object($current) ? trim($current->user_email) : '',
912 'subject' => '',
913 'details' => '',
914 'meta' => home_url()."\n"
915 .'PHP v'.PHP_VERSION
916 .', WordPress v'.(isset($GLOBALS['wp_version']) ? $GLOBALS['wp_version'] : '')
917 .', s2Member v'.(defined('WS_PLUGIN__S2MEMBER_VERSION') ? WS_PLUGIN__S2MEMBER_VERSION : '')
918 .(defined('WS_PLUGIN__S2MEMBER_PRO_VERSION') ? ', Pro v'.WS_PLUGIN__S2MEMBER_PRO_VERSION : ''),
919 );
920
921 if (isset($_POST['name'])) $draft['name'] = wp_strip_all_tags(trim(wp_unslash($_POST['name'])));
922 if (isset($_POST['email'])) $draft['email'] = sanitize_email(trim(wp_unslash($_POST['email'])));
923 if (isset($_POST['subject'])) $draft['subject'] = sanitize_text_field(trim(wp_unslash($_POST['subject'])));
924 if (isset($_POST['details'])) $draft['details'] = trim(wp_unslash($_POST['details']));
925 if (isset($_POST['meta'])) $draft['meta'] = trim(wp_unslash($_POST['meta']));
926
927 // Include template (variables $draft and $notice are in scope for the include).
928 include_once dirname(dirname(__FILE__)).'/menu-pages/get-help-panel.inc.php';
929 }
930
931 /**
932 * Sends the Get Help email (simple contact form, Bcc user).
933 *
934 * @package s2Member\Menu_Pages
935 * @since 250824
936 *
937 * @return array Array like ['ok' => bool, 'msg' => string].
938 */
939 public static function get_help_mail() {
940 if (!current_user_can('manage_options')) {
941 return array('ok' => false, 'msg' => __('You do not have permission to send support requests from this page.', 's2member'));
942 }
943
944 $name = isset($_POST['name']) ? wp_strip_all_tags(trim(wp_unslash($_POST['name']))) : '';
945 $email = isset($_POST['email']) ? sanitize_email(trim(wp_unslash($_POST['email']))) : '';
946 $subject_in = isset($_POST['subject']) ? sanitize_text_field(trim(wp_unslash($_POST['subject']))) : '';
947 $details = isset($_POST['details']) ? trim(wp_unslash($_POST['details'])) : '';
948 $meta = isset($_POST['meta']) ? trim(wp_unslash($_POST['meta'])) : '';
949
950 $email = str_replace(array("\r", "\n"), '', $email); // header-injection safety
951 if (empty($email) || !is_email($email)) {
952 return array('ok' => false, 'msg' => __('Please provide a valid email address.', 's2member'));
953 }
954 if ($details === '') {
955 return array('ok' => false, 'msg' => __('Please describe how I can help.', 's2member'));
956 }
957
958 // Cap length and normalize body fields
959 $max_len = 100000;
960 if (strlen($details) > $max_len) $details = substr($details, 0, $max_len);
961 if (strlen($meta) > $max_len) $meta = substr($meta, 0, $max_len);
962
963 $details = str_replace(array("\r\n", "\r"), "\n", $details);
964 $meta = str_replace(array("\r\n", "\r"), "\n", $meta);
965 $message = $details."\n\n".$meta;
966
967 // Subject with fallback/prefix
968 $subject = (string) apply_filters('ws_plugin__s2member_get_help_subject', $subject_in);
969 $subject = str_replace(array("\r\n", "\r", "\n"), ' ', trim($subject));
970 $subject = ($subject === '') ? __('s2Member help request', 's2member') : 's2Member help: '.$subject;
971
972 // Sanitize display names
973 $name_hdr = str_replace(array("\r\n", "\r", "\n"), ' ', (string) $name);
974 $name_hdr = str_replace('"', "'", $name_hdr);
975
976 $sitename = wp_parse_url(home_url(), PHP_URL_HOST);
977 $sitename = is_string($sitename) ? strtolower($sitename) : '';
978 if (strpos($sitename, 'www.') === 0) $sitename = substr($sitename, 4);
979
980 $default_from_email = 'wordpress@'.$sitename;
981 $default_from_name = ($name_hdr !== '' ? $name_hdr : get_bloginfo('name'));
982
983 // Honor WP and s2 filters, then cleanup
984 $from_email = (string) apply_filters('wp_mail_from', $default_from_email);
985 $from_name = (string) apply_filters('wp_mail_from_name', $default_from_name);
986
987 $from_email = (string) apply_filters('ws_plugin__s2member_get_help_from_email', $from_email);
988 $from_name = (string) apply_filters('ws_plugin__s2member_get_help_from_name', $from_name);
989
990 $from_email = str_replace(array("\r", "\n"), '', $from_email);
991 $from_name = str_replace(array("\r\n", "\r", "\n"), ' ', $from_name);
992 $from_name = str_replace('"', "'", $from_name);
993
994 // Build headers
995 $from_line = '"'.$from_name.'" <'.$from_email.'>';
996 $user_line = ($name_hdr !== '' ? '"'.$name_hdr.'" ' : '').'<'.$email.'>';
997
998 $headers = array('Content-Type: text/plain; charset=UTF-8');
999 $headers[] = 'From: '.$from_line;
1000 $headers[] = 'Reply-To: '.$user_line;
1001 $headers[] = 'Bcc: '.$user_line;
1002 $headers[] = 'X-s2Member-Help: 1';
1003
1004 $headers = apply_filters('ws_plugin__s2member_get_help_headers', $headers, compact('name','email','subject','details','meta'));
1005
1006 // Recipient
1007 $to = (string) apply_filters('ws_plugin__s2member_get_help_mailbox', 'support@wpsharks.com');
1008 if (empty($to) || !is_email($to)) {
1009 return array('ok' => false, 'msg' => __('Support mailbox is not configured correctly.', 's2member'));
1010 }
1011
1012 $sent = wp_mail($to, $subject, $message, $headers);
1013
1014 if (!$sent) {
1015 if (defined('WP_DEBUG_LOG') && WP_DEBUG_LOG) {
1016 error_log('s2Member Get Help: wp_mail() returned false. To='.$to.' | Subject='.$subject);
1017 }
1018 return array('ok' => false, 'msg' => __('Email could not be sent (mail server issue). Please try again or contact us directly.', 's2member'));
1019 }
1020 return array('ok' => true, 'msg' => __('Thanks — your message was sent. You’ll receive a copy by email.', 's2member'));
1021 }
1022 }
1023 }
1024