s2Member Framework (Member Roles, Capabilities, Membership, PayPal Members) - Version 140909

Version Description

= v140909 =

(Maintenance Release) Upgrade immediately.

Download this release

Release Info

Developer JasWSInc
Plugin Icon 128x128 s2Member Framework (Member Roles, Capabilities, Membership, PayPal Members)
Version 140909
Comparing to
See all releases

Code changes from version 140816 to 140909

checksum.txt CHANGED
@@ -1 +1 @@
1
- fe5b4d8fea0ad64e6be257a6b6bba04c
1
+ 3ee3f832a3c7897fa64963d6ac416878
includes/classes/admin-lockouts.inc.php CHANGED
@@ -78,7 +78,7 @@ if(!class_exists('c_ws_plugin__s2member_admin_lockouts'))
78
  $id = 's2-site-name'; // Give this a special/unique ID.
79
  $title = wp_html_excerpt(get_bloginfo('name'), 42); // A brief excerpt.
80
  $title = ($title !== get_bloginfo('name')) ? trim($title).'…' : $title;
81
- $href = site_url('/'); // Change to front page.
82
 
83
  $wp_admin_bar->add_node(array('id' => $id, 'title' => $title, 'href' => $href));
84
  $wp_admin_bar->remove_node('site-name');
78
  $id = 's2-site-name'; // Give this a special/unique ID.
79
  $title = wp_html_excerpt(get_bloginfo('name'), 42); // A brief excerpt.
80
  $title = ($title !== get_bloginfo('name')) ? trim($title).'…' : $title;
81
+ $href = home_url('/'); // Change to front page.
82
 
83
  $wp_admin_bar->add_node(array('id' => $id, 'title' => $title, 'href' => $href));
84
  $wp_admin_bar->remove_node('site-name');
includes/classes/constants.inc.php CHANGED
@@ -1371,7 +1371,7 @@ if (!class_exists ("c_ws_plugin__s2member_constants"))
1371
  * @see `Dashboard -› s2Member -› General Options -› Profile Modifications`
1372
  */
1373
  if (!defined ("S2MEMBER_CURRENT_USER_PROFILE_MODIFICATION_PAGE_URL"))
1374
- define ("S2MEMBER_CURRENT_USER_PROFILE_MODIFICATION_PAGE_URL", ($c[] = (string)site_url ("/?s2member_profile=1")));
1375
  /**
1376
  * A URL, which leads to the Download Limit Exceeded Page; as configured by the site owner.
1377
  *
@@ -1859,7 +1859,7 @@ if (!class_exists ("c_ws_plugin__s2member_constants"))
1859
  * @see `Dashboard -› s2Member -› PayPal Options -› IPN Integration`
1860
  */
1861
  if (!defined ("S2MEMBER_PAYPAL_NOTIFY_URL"))
1862
- define ("S2MEMBER_PAYPAL_NOTIFY_URL", ($c[] = (string)site_url ("/?s2member_paypal_notify=1")));
1863
  /**
1864
  * Full URL to PayPal Auto-Return/PDT handler, provided by s2Member.
1865
  *
@@ -1887,7 +1887,7 @@ if (!class_exists ("c_ws_plugin__s2member_constants"))
1887
  * @see `Dashboard -› s2Member -› PayPal Options -› Auto-Return/PDT Integration`
1888
  */
1889
  if (!defined ("S2MEMBER_PAYPAL_RETURN_URL"))
1890
- define ("S2MEMBER_PAYPAL_RETURN_URL", ($c[] = (string)site_url ("/?s2member_paypal_return=1")));
1891
  /**
1892
  * PayPal Business Email Address; as configured by the site owner.
1893
  *
1371
  * @see `Dashboard -› s2Member -› General Options -› Profile Modifications`
1372
  */
1373
  if (!defined ("S2MEMBER_CURRENT_USER_PROFILE_MODIFICATION_PAGE_URL"))
1374
+ define ("S2MEMBER_CURRENT_USER_PROFILE_MODIFICATION_PAGE_URL", ($c[] = (string)home_url ("/?s2member_profile=1")));
1375
  /**
1376
  * A URL, which leads to the Download Limit Exceeded Page; as configured by the site owner.
1377
  *
1859
  * @see `Dashboard -› s2Member -› PayPal Options -› IPN Integration`
1860
  */
1861
  if (!defined ("S2MEMBER_PAYPAL_NOTIFY_URL"))
1862
+ define ("S2MEMBER_PAYPAL_NOTIFY_URL", ($c[] = (string)home_url ("/?s2member_paypal_notify=1")));
1863
  /**
1864
  * Full URL to PayPal Auto-Return/PDT handler, provided by s2Member.
1865
  *
1887
  * @see `Dashboard -› s2Member -› PayPal Options -› Auto-Return/PDT Integration`
1888
  */
1889
  if (!defined ("S2MEMBER_PAYPAL_RETURN_URL"))
1890
+ define ("S2MEMBER_PAYPAL_RETURN_URL", ($c[] = (string)home_url ("/?s2member_paypal_return=1")));
1891
  /**
1892
  * PayPal Business Email Address; as configured by the site owner.
1893
  *
includes/classes/files-in.inc.php CHANGED
@@ -350,7 +350,7 @@ if(!class_exists('c_ws_plugin__s2member_files_in'))
350
  $url .= (isset($req['file_remote'])) ? (($remote) ? '&s2member_file_remote=yes' : '&s2member_file_remote=no') : '';
351
  $url .= (isset($req['skip_confirmation'])) ? (($skip_confirmation) ? '&s2member_skip_confirmation=yes' : '&s2member_skip_confirmation=no') : '';
352
 
353
- $url = site_url('/?'.ltrim($url.'&s2member_file_download=/'.$_url_e_file, '&'));
354
  $url = ($ssl) ? preg_replace('/^https?/', 'https', $url) : preg_replace('/^https?/', 'http', $url);
355
 
356
  return apply_filters('ws_plugin__s2member_file_download_access_url', $url, get_defined_vars());
350
  $url .= (isset($req['file_remote'])) ? (($remote) ? '&s2member_file_remote=yes' : '&s2member_file_remote=no') : '';
351
  $url .= (isset($req['skip_confirmation'])) ? (($skip_confirmation) ? '&s2member_skip_confirmation=yes' : '&s2member_skip_confirmation=no') : '';
352
 
353
+ $url = home_url('/?'.ltrim($url.'&s2member_file_download=/'.$_url_e_file, '&'));
354
  $url = ($ssl) ? preg_replace('/^https?/', 'https', $url) : preg_replace('/^https?/', 'http', $url);
355
 
356
  return apply_filters('ws_plugin__s2member_file_download_access_url', $url, get_defined_vars());
includes/classes/login-customizations.inc.php CHANGED
@@ -119,6 +119,7 @@ if(!class_exists('c_ws_plugin__s2member_login_customizations'))
119
 
120
  $a[] = 'div#login form p { margin:2px 0 16px 0'.$i.'; }'; // Handles paragraph margins inside the form.
121
  $a[] = 'div#login form input[type="text"], div#login form input[type="email"], div#login form input[type="password"], div#login form textarea, div#login form select { margin:0'.$i.'; padding:3px'.$i.'; border-radius:3px'.$i.'; box-sizing:border-box'.$i.'; width:100%'.$i.'; background:#FBFBFB repeat scroll 0 0'.$i.'; border:1px solid #E5E5E5'.$i.'; font-size:'.$GLOBALS['WS_PLUGIN__']['s2member']['o']['login_reg_font_field_size'].$i.'; font-weight:normal'.$i.'; color:#333333'.$i.'; }';
 
122
  $a[] = 'div#login form label { cursor:pointer'.$i.'; } div#login form label.ws-plugin--s2member-custom-reg-field-op-l { opacity:0.7'.$i.'; font-size:90%'.$i.'; vertical-align:middle'.$i.'; }';
123
  $a[] = 'div#login form input[type="checkbox"], div#login form input[type="radio"] { margin:0 3px 0 0'.$i.'; vertical-align:middle'.$i.'; }';
124
  $a[] = 'div#login form input#ws-plugin--s2member-custom-reg-field-user-pass2[type="password"] { margin-top:5px'.$i.'; }';
119
 
120
  $a[] = 'div#login form p { margin:2px 0 16px 0'.$i.'; }'; // Handles paragraph margins inside the form.
121
  $a[] = 'div#login form input[type="text"], div#login form input[type="email"], div#login form input[type="password"], div#login form textarea, div#login form select { margin:0'.$i.'; padding:3px'.$i.'; border-radius:3px'.$i.'; box-sizing:border-box'.$i.'; width:100%'.$i.'; background:#FBFBFB repeat scroll 0 0'.$i.'; border:1px solid #E5E5E5'.$i.'; font-size:'.$GLOBALS['WS_PLUGIN__']['s2member']['o']['login_reg_font_field_size'].$i.'; font-weight:normal'.$i.'; color:#333333'.$i.'; }';
122
+ $a[] = '@supports (-moz-appearance: none){ div#login form select { font-size:'.min((integer)$GLOBALS['WS_PLUGIN__']['s2member']['o']['login_reg_font_field_size'], 15).'px'.$i.'; } }'; // Mozilla doesn't like the larger font size. This corrects that issue in Firefox.
123
  $a[] = 'div#login form label { cursor:pointer'.$i.'; } div#login form label.ws-plugin--s2member-custom-reg-field-op-l { opacity:0.7'.$i.'; font-size:90%'.$i.'; vertical-align:middle'.$i.'; }';
124
  $a[] = 'div#login form input[type="checkbox"], div#login form input[type="radio"] { margin:0 3px 0 0'.$i.'; vertical-align:middle'.$i.'; }';
125
  $a[] = 'div#login form input#ws-plugin--s2member-custom-reg-field-user-pass2[type="password"] { margin-top:5px'.$i.'; }';
includes/classes/menu-pages.inc.php CHANGED
@@ -299,7 +299,7 @@ if(!class_exists('c_ws_plugin__s2member_menu_pages'))
299
  wp_enqueue_script('jquery-sprintf', $GLOBALS['WS_PLUGIN__']['s2member']['c']['dir_url'].'/includes/jquery/jquery.sprintf/jquery.sprintf-min.js', array('jquery'), c_ws_plugin__s2member_utilities::ver_checksum());
300
  wp_enqueue_script('jquery-json-ps', $GLOBALS['WS_PLUGIN__']['s2member']['c']['dir_url'].'/includes/jquery/jquery.json-ps/jquery.json-ps-min.js', array('jquery'), c_ws_plugin__s2member_utilities::ver_checksum());
301
  wp_enqueue_script('jquery-ui-effects', $GLOBALS['WS_PLUGIN__']['s2member']['c']['dir_url'].'/includes/jquery/jquery.ui-effects/jquery.ui-effects-min.js', array('jquery', 'jquery-ui-core'), c_ws_plugin__s2member_utilities::ver_checksum());
302
- wp_enqueue_script('ws-plugin--s2member-menu-pages', site_url('/?ws_plugin__s2member_menu_pages_js='.urlencode(mt_rand())), 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());
303
 
304
  do_action('ws_plugin__s2member_during_add_admin_scripts', get_defined_vars());
305
  }
@@ -321,7 +321,7 @@ if(!class_exists('c_ws_plugin__s2member_menu_pages'))
321
  if(!empty($_GET['page']) && preg_match('/ws-plugin--s2member-/', $_GET['page']))
322
  {
323
  wp_enqueue_style('thickbox');
324
- wp_enqueue_style('ws-plugin--s2member-menu-pages', site_url('/?ws_plugin__s2member_menu_pages_css='.urlencode(mt_rand())), array('thickbox'), c_ws_plugin__s2member_utilities::ver_checksum(), 'all');
325
 
326
  do_action('ws_plugin__s2member_during_add_admin_styles', get_defined_vars());
327
  }
299
  wp_enqueue_script('jquery-sprintf', $GLOBALS['WS_PLUGIN__']['s2member']['c']['dir_url'].'/includes/jquery/jquery.sprintf/jquery.sprintf-min.js', array('jquery'), c_ws_plugin__s2member_utilities::ver_checksum());
300
  wp_enqueue_script('jquery-json-ps', $GLOBALS['WS_PLUGIN__']['s2member']['c']['dir_url'].'/includes/jquery/jquery.json-ps/jquery.json-ps-min.js', array('jquery'), c_ws_plugin__s2member_utilities::ver_checksum());
301
  wp_enqueue_script('jquery-ui-effects', $GLOBALS['WS_PLUGIN__']['s2member']['c']['dir_url'].'/includes/jquery/jquery.ui-effects/jquery.ui-effects-min.js', array('jquery', 'jquery-ui-core'), c_ws_plugin__s2member_utilities::ver_checksum());
302
+ wp_enqueue_script('ws-plugin--s2member-menu-pages', home_url('/?ws_plugin__s2member_menu_pages_js='.urlencode(mt_rand())), 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());
303
 
304
  do_action('ws_plugin__s2member_during_add_admin_scripts', get_defined_vars());
305
  }
321
  if(!empty($_GET['page']) && preg_match('/ws-plugin--s2member-/', $_GET['page']))
322
  {
323
  wp_enqueue_style('thickbox');
324
+ wp_enqueue_style('ws-plugin--s2member-menu-pages', home_url('/?ws_plugin__s2member_menu_pages_css='.urlencode(mt_rand())), array('thickbox'), c_ws_plugin__s2member_utilities::ver_checksum(), 'all');
325
 
326
  do_action('ws_plugin__s2member_during_add_admin_styles', get_defined_vars());
327
  }
includes/classes/profile-in.inc.php CHANGED
@@ -51,7 +51,7 @@ if(!class_exists('c_ws_plugin__s2member_profile_in'))
51
 
52
  echo '<body style="'.esc_attr(apply_filters('ws_plugin__s2member_profile_body_styles', "background:#FFFFFF; color:#333333; font-family:'Verdana', sans-serif; font-size:13px;", get_defined_vars())).'">'."\n";
53
 
54
- echo '<form method="post" name="ws_plugin__s2member_profile" id="ws-plugin--s2member-profile" action="'.esc_attr(site_url('/')).'">'."\n";
55
 
56
  foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
57
  do_action('ws_plugin__s2member_during_profile_before_table', get_defined_vars());
51
 
52
  echo '<body style="'.esc_attr(apply_filters('ws_plugin__s2member_profile_body_styles', "background:#FFFFFF; color:#333333; font-family:'Verdana', sans-serif; font-size:13px;", get_defined_vars())).'">'."\n";
53
 
54
+ echo '<form method="post" name="ws_plugin__s2member_profile" id="ws-plugin--s2member-profile" action="'.esc_attr(home_url('/')).'">'."\n";
55
 
56
  foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
57
  do_action('ws_plugin__s2member_during_profile_before_table', get_defined_vars());
includes/classes/querys.inc.php CHANGED
@@ -83,25 +83,29 @@ if(!class_exists('c_ws_plugin__s2member_querys'))
83
  *
84
  * @todo Make it possible to force filtering, even when used in combination with Query Conditionals and ``get_posts()``, which auto-supresses.
85
  * Or, perhaps strengthen the existing ``$force`` parameter in this regard.
 
 
86
  */
87
  public static function query_level_access(&$wp_query = NULL, $force = FALSE)
88
  {
89
  global $wpdb; // Global DB object reference.
90
  static $initial_query = TRUE; // Tracks the initial query.
91
- c_ws_plugin__s2member_querys::$current_wp_query = & $wp_query;
92
 
93
  foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
94
  do_action('ws_plugin__s2member_before_query_level_access', get_defined_vars());
95
  unset($__refs, $__v); // Housekeeping.
96
 
97
- c_ws_plugin__s2member_querys::_query_level_access_sys($wp_query); // Systematics.
 
 
98
 
99
  remove_filter('comment_feed_where', 'c_ws_plugin__s2member_querys::_query_level_access_coms', 100, 2);
100
  remove_filter('wp_get_nav_menu_items', 'c_ws_plugin__s2member_querys::_query_level_access_navs', 100);
101
 
102
  if(is_object($wpdb) && is_object($wp_query) && (($o = $GLOBALS['WS_PLUGIN__']['s2member']['o']['filter_wp_query']) || $force))
103
  {
104
- if(!is_admin() || c_ws_plugin__s2member_querys::_is_admin_ajax_search($wp_query))
105
  {
106
  $suppressing_filters = $wp_query->get('suppress_filters'); // Filter suppression on?
107
  if(!$suppressing_filters && $force // Forcing this routine bypasses all of these other conditionals. Works with API function ``attach_s2member_query_filters()``.
@@ -305,7 +309,7 @@ if(!class_exists('c_ws_plugin__s2member_querys'))
305
  public static function _query_level_access_navs($items = array())
306
  {
307
  global $wpdb; // Global DB object reference.
308
- $wp_query = & c_ws_plugin__s2member_querys::$current_wp_query;
309
 
310
  if(is_array($items) && !empty($items) && is_object($wpdb) && is_object($wp_query) && $wp_query->get('suppress_filters') !== 'n/a')
311
  {
@@ -403,7 +407,26 @@ if(!class_exists('c_ws_plugin__s2member_querys'))
403
  else if($GLOBALS['WS_PLUGIN__']['s2member']['o']['level'.$n.'_pages'] && !current_user_can('access_s2member_level'.$n))
404
  $excludes = array_merge($excludes, c_ws_plugin__s2member_utils_arrays::force_integers(preg_split('/['."\r\n\t".'\s;,]+/', $GLOBALS['WS_PLUGIN__']['s2member']['o']['level'.$n.'_pages'])));
405
  }
406
- return $excludes;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
407
  }
408
  }
409
  }
83
  *
84
  * @todo Make it possible to force filtering, even when used in combination with Query Conditionals and ``get_posts()``, which auto-supresses.
85
  * Or, perhaps strengthen the existing ``$force`` parameter in this regard.
86
+ *
87
+ * @see Workaround for bbPress and the `s` key. See: <http://bit.ly/1obLpv4>
88
  */
89
  public static function query_level_access(&$wp_query = NULL, $force = FALSE)
90
  {
91
  global $wpdb; // Global DB object reference.
92
  static $initial_query = TRUE; // Tracks the initial query.
93
+ c_ws_plugin__s2member_querys::$current_wp_query = &$wp_query;
94
 
95
  foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
96
  do_action('ws_plugin__s2member_before_query_level_access', get_defined_vars());
97
  unset($__refs, $__v); // Housekeeping.
98
 
99
+ if(is_object($wp_query) && !$wp_query->get('___s2_is_bbp_has_replies'))
100
+ // Workaround for bbPress and the `s` key. See: <http://bit.ly/1obLpv4>
101
+ c_ws_plugin__s2member_querys::_query_level_access_sys($wp_query); // Systematics.
102
 
103
  remove_filter('comment_feed_where', 'c_ws_plugin__s2member_querys::_query_level_access_coms', 100, 2);
104
  remove_filter('wp_get_nav_menu_items', 'c_ws_plugin__s2member_querys::_query_level_access_navs', 100);
105
 
106
  if(is_object($wpdb) && is_object($wp_query) && (($o = $GLOBALS['WS_PLUGIN__']['s2member']['o']['filter_wp_query']) || $force))
107
  {
108
+ if((!is_admin() || c_ws_plugin__s2member_querys::_is_admin_ajax_search($wp_query)) && !$wp_query->get('___s2_is_bbp_has_replies') /* See: <http://bit.ly/1obLpv4> */)
109
  {
110
  $suppressing_filters = $wp_query->get('suppress_filters'); // Filter suppression on?
111
  if(!$suppressing_filters && $force // Forcing this routine bypasses all of these other conditionals. Works with API function ``attach_s2member_query_filters()``.
309
  public static function _query_level_access_navs($items = array())
310
  {
311
  global $wpdb; // Global DB object reference.
312
+ $wp_query = &c_ws_plugin__s2member_querys::$current_wp_query;
313
 
314
  if(is_array($items) && !empty($items) && is_object($wpdb) && is_object($wp_query) && $wp_query->get('suppress_filters') !== 'n/a')
315
  {
407
  else if($GLOBALS['WS_PLUGIN__']['s2member']['o']['level'.$n.'_pages'] && !current_user_can('access_s2member_level'.$n))
408
  $excludes = array_merge($excludes, c_ws_plugin__s2member_utils_arrays::force_integers(preg_split('/['."\r\n\t".'\s;,]+/', $GLOBALS['WS_PLUGIN__']['s2member']['o']['level'.$n.'_pages'])));
409
  }
410
+ return apply_filters('_ws_plugin__s2member_query_level_access_list_pages', $excludes, get_defined_vars());
411
+ }
412
+
413
+ /**
414
+ * Flags a WP Query has being a `bbp_has_replies()` query.
415
+ *
416
+ * @package s2Member\Queries
417
+ * @since 140906
418
+ *
419
+ * @attaches-to ``add_filter('bbp_has_replies_query');``
420
+ *
421
+ * @param array $args Query arguments passed by the filter.
422
+ *
423
+ * @return array The array of ``$args``.
424
+ *
425
+ * @see Workaround for bbPress and the `s` key. See: <http://bit.ly/1obLpv4>
426
+ */
427
+ public static function _bbp_flag_has_replies($args)
428
+ {
429
+ return array_merge($args, array('___s2_is_bbp_has_replies' => TRUE));
430
  }
431
  }
432
  }
includes/classes/register-access.inc.php CHANGED
@@ -50,7 +50,7 @@ if (!class_exists ("c_ws_plugin__s2member_register_access"))
50
  {
51
  $register = c_ws_plugin__s2member_utils_encryption::encrypt ("subscr_gateway_subscr_id_custom_item_number_time:.:|:.:" . $subscr_gateway . ":.:|:.:" . $subscr_id . ":.:|:.:" . $custom . ":.:|:.:" . $item_number . ":.:|:.:" . strtotime ("now"));
52
 
53
- $register_link = site_url ("/?s2member_register=" . urlencode ($register)); // Generate long URL/link.
54
 
55
  if ($shrink && ($shorter_url = c_ws_plugin__s2member_utils_urls::shorten ($register_link)))
56
  $register_link = $shorter_url . "#" . $_SERVER["HTTP_HOST"];
50
  {
51
  $register = c_ws_plugin__s2member_utils_encryption::encrypt ("subscr_gateway_subscr_id_custom_item_number_time:.:|:.:" . $subscr_gateway . ":.:|:.:" . $subscr_id . ":.:|:.:" . $custom . ":.:|:.:" . $item_number . ":.:|:.:" . strtotime ("now"));
52
 
53
+ $register_link = home_url ("/?s2member_register=" . urlencode ($register)); // Generate long URL/link.
54
 
55
  if ($shrink && ($shorter_url = c_ws_plugin__s2member_utils_urls::shorten ($register_link)))
56
  $register_link = $shorter_url . "#" . $_SERVER["HTTP_HOST"];
includes/classes/registrations.inc.php CHANGED
@@ -692,13 +692,13 @@ if (!class_exists ("c_ws_plugin__s2member_registrations"))
692
  if (($transient = "s2m_" . md5 ("s2member_transient_ipn_subscr_payment_" . $subscr_id)) && is_array($subscr_payment = get_transient ($transient)) && !empty($subscr_payment["subscr_gateway"]))
693
  {
694
  $proxy = array("s2member_paypal_proxy" => stripslashes ((string)$subscr_payment["subscr_gateway"]), "s2member_paypal_proxy_verification" => c_ws_plugin__s2member_paypal_utilities::paypal_proxy_key_gen ());
695
- c_ws_plugin__s2member_utils_urls::remote (site_url ("/?s2member_paypal_notify=1"), array_merge(stripslashes_deep ($subscr_payment), $proxy), array("timeout" => 20));
696
  delete_transient ($transient); // This can be deleted now.
697
  }
698
  if (($transient = "s2m_" . md5 ("s2member_transient_ipn_subscr_eot_" . $subscr_id)) && is_array($subscr_eot = get_transient ($transient)) && !empty($subscr_eot["subscr_gateway"]))
699
  {
700
  $proxy = array("s2member_paypal_proxy" => stripslashes ((string)$subscr_eot["subscr_gateway"]), "s2member_paypal_proxy_verification" => c_ws_plugin__s2member_paypal_utilities::paypal_proxy_key_gen ());
701
- c_ws_plugin__s2member_utils_urls::remote (site_url ("/?s2member_paypal_notify=1"), array_merge(stripslashes_deep ($subscr_eot), $proxy), array("timeout" => 20));
702
  delete_transient ($transient); // This can be deleted now.
703
  }
704
  if (!headers_sent ()) // Only if headers are NOT yet sent. Here we establish both Signup and Payment Tracking Cookies.
692
  if (($transient = "s2m_" . md5 ("s2member_transient_ipn_subscr_payment_" . $subscr_id)) && is_array($subscr_payment = get_transient ($transient)) && !empty($subscr_payment["subscr_gateway"]))
693
  {
694
  $proxy = array("s2member_paypal_proxy" => stripslashes ((string)$subscr_payment["subscr_gateway"]), "s2member_paypal_proxy_verification" => c_ws_plugin__s2member_paypal_utilities::paypal_proxy_key_gen ());
695
+ c_ws_plugin__s2member_utils_urls::remote (home_url ("/?s2member_paypal_notify=1"), array_merge(stripslashes_deep ($subscr_payment), $proxy), array("timeout" => 20));
696
  delete_transient ($transient); // This can be deleted now.
697
  }
698
  if (($transient = "s2m_" . md5 ("s2member_transient_ipn_subscr_eot_" . $subscr_id)) && is_array($subscr_eot = get_transient ($transient)) && !empty($subscr_eot["subscr_gateway"]))
699
  {
700
  $proxy = array("s2member_paypal_proxy" => stripslashes ((string)$subscr_eot["subscr_gateway"]), "s2member_paypal_proxy_verification" => c_ws_plugin__s2member_paypal_utilities::paypal_proxy_key_gen ());
701
+ c_ws_plugin__s2member_utils_urls::remote (home_url ("/?s2member_paypal_notify=1"), array_merge(stripslashes_deep ($subscr_eot), $proxy), array("timeout" => 20));
702
  delete_transient ($transient); // This can be deleted now.
703
  }
704
  if (!headers_sent ()) // Only if headers are NOT yet sent. Here we establish both Signup and Payment Tracking Cookies.
includes/classes/sc-paypal-button-in.inc.php CHANGED
@@ -74,7 +74,7 @@ if (!class_exists ("c_ws_plugin__s2member_sc_paypal_button_in"))
74
 
75
  $code = trim (c_ws_plugin__s2member_utilities::evl (file_get_contents (dirname (dirname (__FILE__)) . "/templates/buttons/paypal-cancellation-button.php")));
76
  $code = preg_replace ("/%%images%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images")), $code);
77
- $code = preg_replace ("/%%wpurl%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (site_url ())), $code);
78
 
79
  $code = preg_replace ("/%%endpoint%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com")), $code);
80
  $code = preg_replace ("/%%paypal_business%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $code);
@@ -106,18 +106,18 @@ if (!class_exists ("c_ws_plugin__s2member_sc_paypal_button_in"))
106
 
107
  $attr["sp_ids_exp"] = /* Combined "sp:ids:expiration hours". */ "sp:" . $attr["ids"] . ":" . $attr["exp"];
108
 
109
- $success_return_url = /* s2Member handles this all by itself. However, it can be Filtered. */ site_url ("/?s2member_paypal_return=1");
110
  $success_return_url = apply_filters("ws_plugin__s2member_during_sc_paypal_button_success_return_url", $success_return_url, get_defined_vars ());
111
 
112
  $code = trim (c_ws_plugin__s2member_utilities::evl (file_get_contents (dirname (dirname (__FILE__)) . "/templates/buttons/paypal-sp-checkout-button.php")));
113
  $code = preg_replace ("/%%images%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images")), $code);
114
- $code = preg_replace ("/%%wpurl%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (site_url ())), $code);
115
 
116
  $code = preg_replace ("/%%endpoint%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com")), $code);
117
  $code = preg_replace ("/%%paypal_business%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $code);
118
  $code = preg_replace ("/%%paypal_merchant_id%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_merchant_id"])), $code);
119
  $code = preg_replace ("/%%cancel_return%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (home_url ("/"))), $code);
120
- $code = preg_replace ("/%%notify_url%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (site_url ("/?s2member_paypal_notify=1"))), $code);
121
  $code = preg_replace ("/%%return%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($success_return_url)), $code);
122
  $code = preg_replace ("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["custom"])), $code);
123
 
@@ -162,18 +162,18 @@ if (!class_exists ("c_ws_plugin__s2member_sc_paypal_button_in"))
162
  $attr["level_ccaps_eotper"] = ($attr["rr"] === "BN" && $attr["rt"] !== "L") ? $attr["level"] . ":" . $attr["ccaps"] . ":" . $attr["rp"] . " " . $attr["rt"] : $attr["level"] . ":" . $attr["ccaps"];
163
  $attr["level_ccaps_eotper"] = /* Clean any trailing separators from this string. */ rtrim ($attr["level_ccaps_eotper"], ":");
164
 
165
- $success_return_url = /* s2Member handles this all by itself. However, it can be Filtered. */ site_url ("/?s2member_paypal_return=1");
166
  $success_return_url = apply_filters("ws_plugin__s2member_during_sc_paypal_button_success_return_url", $success_return_url, get_defined_vars ());
167
 
168
  $code = trim (c_ws_plugin__s2member_utilities::evl (file_get_contents (dirname (dirname (__FILE__)) . "/templates/buttons/paypal-ccaps-checkout-button.php")));
169
  $code = preg_replace ("/%%images%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images")), $code);
170
- $code = preg_replace ("/%%wpurl%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (site_url ())), $code);
171
 
172
  $code = preg_replace ("/%%endpoint%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com")), $code);
173
  $code = preg_replace ("/%%paypal_business%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $code);
174
  $code = preg_replace ("/%%paypal_merchant_id%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_merchant_id"])), $code);
175
  $code = preg_replace ("/%%cancel_return%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (home_url ("/"))), $code);
176
- $code = preg_replace ("/%%notify_url%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (site_url ("/?s2member_paypal_notify=1"))), $code);
177
  $code = preg_replace ("/%%return%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($success_return_url)), $code);
178
  $code = preg_replace ("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["custom"])), $code);
179
 
@@ -222,20 +222,20 @@ if (!class_exists ("c_ws_plugin__s2member_sc_paypal_button_in"))
222
 
223
  $success_return_tra = array("ta" => $attr["ta"], "tp" => $attr["tp"], "tt" => $attr["tt"], "ra" => $attr["ra"], "rp" => $attr["rp"], "rt" => $attr["rt"], "rr" => $attr["rr"], "rrt" => $attr["rrt"], "rra" => $attr["rra"], "invoice" => $paypal_invoice_input_value, "checksum" => md5 ($paypal_invoice_input_value . $_SERVER["REMOTE_ADDR"] . $attr["level_ccaps_eotper"]));
224
 
225
- $success_return_url = /* s2Member handles this all by itself. However, it can be Filtered (see below). */ site_url ("/?s2member_paypal_return=1");
226
  $success_return_url = add_query_arg ("s2member_paypal_return_tra", urlencode (c_ws_plugin__s2member_utils_encryption::encrypt (serialize ($success_return_tra))), $success_return_url);
227
  $success_return_url = apply_filters("ws_plugin__s2member_during_sc_paypal_button_success_return_url", $success_return_url, get_defined_vars ());
228
 
229
  $code = trim (c_ws_plugin__s2member_utilities::evl (file_get_contents (dirname (dirname (__FILE__)) . "/templates/buttons/paypal-checkout-button.php")));
230
  $code = preg_replace ("/%%images%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images")), $code);
231
- $code = preg_replace ("/%%wpurl%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (site_url ())), $code);
232
 
233
  $code = preg_replace ("/%%endpoint%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com")), $code);
234
  $code = preg_replace ("/%%paypal_business%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $code);
235
  $code = preg_replace ("/%%paypal_merchant_id%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_merchant_id"])), $code);
236
  $code = preg_replace ("/%%level_label%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $attr["level"] . "_label"])), $code);
237
  $code = preg_replace ("/%%cancel_return%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (home_url ("/"))), $code); // This brings them back to Front Page.
238
- $code = preg_replace ("/%%notify_url%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (site_url ("/?s2member_paypal_notify=1"))), $code);
239
  $code = preg_replace ("/%%return%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($success_return_url)), $code);
240
  $code = preg_replace ("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["custom"])), $code);
241
  $code = preg_replace ("/%%level%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["level"])), $code);
74
 
75
  $code = trim (c_ws_plugin__s2member_utilities::evl (file_get_contents (dirname (dirname (__FILE__)) . "/templates/buttons/paypal-cancellation-button.php")));
76
  $code = preg_replace ("/%%images%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images")), $code);
77
+ $code = preg_replace ("/%%wpurl%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (home_url ())), $code);
78
 
79
  $code = preg_replace ("/%%endpoint%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com")), $code);
80
  $code = preg_replace ("/%%paypal_business%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $code);
106
 
107
  $attr["sp_ids_exp"] = /* Combined "sp:ids:expiration hours". */ "sp:" . $attr["ids"] . ":" . $attr["exp"];
108
 
109
+ $success_return_url = /* s2Member handles this all by itself. However, it can be Filtered. */ home_url ("/?s2member_paypal_return=1");
110
  $success_return_url = apply_filters("ws_plugin__s2member_during_sc_paypal_button_success_return_url", $success_return_url, get_defined_vars ());
111
 
112
  $code = trim (c_ws_plugin__s2member_utilities::evl (file_get_contents (dirname (dirname (__FILE__)) . "/templates/buttons/paypal-sp-checkout-button.php")));
113
  $code = preg_replace ("/%%images%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images")), $code);
114
+ $code = preg_replace ("/%%wpurl%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (home_url ())), $code);
115
 
116
  $code = preg_replace ("/%%endpoint%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com")), $code);
117
  $code = preg_replace ("/%%paypal_business%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $code);
118
  $code = preg_replace ("/%%paypal_merchant_id%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_merchant_id"])), $code);
119
  $code = preg_replace ("/%%cancel_return%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (home_url ("/"))), $code);
120
+ $code = preg_replace ("/%%notify_url%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (home_url ("/?s2member_paypal_notify=1"))), $code);
121
  $code = preg_replace ("/%%return%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($success_return_url)), $code);
122
  $code = preg_replace ("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["custom"])), $code);
123
 
162
  $attr["level_ccaps_eotper"] = ($attr["rr"] === "BN" && $attr["rt"] !== "L") ? $attr["level"] . ":" . $attr["ccaps"] . ":" . $attr["rp"] . " " . $attr["rt"] : $attr["level"] . ":" . $attr["ccaps"];
163
  $attr["level_ccaps_eotper"] = /* Clean any trailing separators from this string. */ rtrim ($attr["level_ccaps_eotper"], ":");
164
 
165
+ $success_return_url = /* s2Member handles this all by itself. However, it can be Filtered. */ home_url ("/?s2member_paypal_return=1");
166
  $success_return_url = apply_filters("ws_plugin__s2member_during_sc_paypal_button_success_return_url", $success_return_url, get_defined_vars ());
167
 
168
  $code = trim (c_ws_plugin__s2member_utilities::evl (file_get_contents (dirname (dirname (__FILE__)) . "/templates/buttons/paypal-ccaps-checkout-button.php")));
169
  $code = preg_replace ("/%%images%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images")), $code);
170
+ $code = preg_replace ("/%%wpurl%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (home_url ())), $code);
171
 
172
  $code = preg_replace ("/%%endpoint%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com")), $code);
173
  $code = preg_replace ("/%%paypal_business%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $code);
174
  $code = preg_replace ("/%%paypal_merchant_id%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_merchant_id"])), $code);
175
  $code = preg_replace ("/%%cancel_return%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (home_url ("/"))), $code);
176
+ $code = preg_replace ("/%%notify_url%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (home_url ("/?s2member_paypal_notify=1"))), $code);
177
  $code = preg_replace ("/%%return%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($success_return_url)), $code);
178
  $code = preg_replace ("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["custom"])), $code);
179
 
222
 
223
  $success_return_tra = array("ta" => $attr["ta"], "tp" => $attr["tp"], "tt" => $attr["tt"], "ra" => $attr["ra"], "rp" => $attr["rp"], "rt" => $attr["rt"], "rr" => $attr["rr"], "rrt" => $attr["rrt"], "rra" => $attr["rra"], "invoice" => $paypal_invoice_input_value, "checksum" => md5 ($paypal_invoice_input_value . $_SERVER["REMOTE_ADDR"] . $attr["level_ccaps_eotper"]));
224
 
225
+ $success_return_url = /* s2Member handles this all by itself. However, it can be Filtered (see below). */ home_url ("/?s2member_paypal_return=1");
226
  $success_return_url = add_query_arg ("s2member_paypal_return_tra", urlencode (c_ws_plugin__s2member_utils_encryption::encrypt (serialize ($success_return_tra))), $success_return_url);
227
  $success_return_url = apply_filters("ws_plugin__s2member_during_sc_paypal_button_success_return_url", $success_return_url, get_defined_vars ());
228
 
229
  $code = trim (c_ws_plugin__s2member_utilities::evl (file_get_contents (dirname (dirname (__FILE__)) . "/templates/buttons/paypal-checkout-button.php")));
230
  $code = preg_replace ("/%%images%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images")), $code);
231
+ $code = preg_replace ("/%%wpurl%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (home_url ())), $code);
232
 
233
  $code = preg_replace ("/%%endpoint%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com")), $code);
234
  $code = preg_replace ("/%%paypal_business%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $code);
235
  $code = preg_replace ("/%%paypal_merchant_id%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_merchant_id"])), $code);
236
  $code = preg_replace ("/%%level_label%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $attr["level"] . "_label"])), $code);
237
  $code = preg_replace ("/%%cancel_return%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (home_url ("/"))), $code); // This brings them back to Front Page.
238
+ $code = preg_replace ("/%%notify_url%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr (home_url ("/?s2member_paypal_notify=1"))), $code);
239
  $code = preg_replace ("/%%return%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($success_return_url)), $code);
240
  $code = preg_replace ("/%%custom%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["custom"])), $code);
241
  $code = preg_replace ("/%%level%%/", c_ws_plugin__s2member_utils_strings::esc_refs (esc_attr ($attr["level"])), $code);
includes/classes/security.inc.php CHANGED
@@ -1,86 +1,83 @@
1
  <?php
2
  /**
3
- * s2Member's Security Gate.
4
- *
5
- * Copyright: © 2009-2011
6
- * {@link http://www.websharks-inc.com/ WebSharks, Inc.}
7
- * (coded in the USA)
8
- *
9
- * Released under the terms of the GNU General Public License.
10
- * You should have received a copy of the GNU General Public License,
11
- * along with this software. In the main directory, see: /licensing/
12
- * If not, see: {@link http://www.gnu.org/licenses/}.
13
- *
14
- * @package s2Member\Security
15
- * @since 3.5
16
- */
17
- if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
18
- exit("Do not access this file directly.");
19
 
20
- if (!class_exists ("c_ws_plugin__s2member_security"))
 
 
 
 
 
 
 
 
21
  {
22
  /**
23
- * s2Member's Security Gate.
24
- *
25
- * @package s2Member\Security
26
- * @since 3.5
27
- */
28
- class c_ws_plugin__s2member_security
29
- {
30
- /**
31
- * s2Member's Security Gate (protects WordPress content).
32
- *
33
- * @package s2Member\Security
34
- * @since 3.5
35
- *
36
- * @attaches-to ``add_action("wp");``
37
- *
38
- * @return null May redirect a browser *(exiting script execution)*, when/if content is NOT available to the current User/Member.
39
- */
40
- public static function security_gate () // s2Member's Security Gate.
41
- {
42
- do_action("ws_plugin__s2member_before_security_gate", get_defined_vars ());
43
 
44
- if (is_category ()) // Categories & other inclusives.
45
- c_ws_plugin__s2member_catgs::check_catg_level_access ();
46
 
47
- else if (is_tag ()) // Post/Page Tags & other inclusives.
48
- c_ws_plugin__s2member_ptags::check_ptag_level_access ();
49
 
50
- else if (is_single ()) // All Posts & other inclusives.
51
- c_ws_plugin__s2member_posts::check_post_level_access ();
52
 
53
- else if (is_page ()) // All Pages & other inclusives.
54
- c_ws_plugin__s2member_pages::check_page_level_access ();
55
 
56
- else // Else, we simply look at URIs & other inclusives.
57
- c_ws_plugin__s2member_ruris::check_ruri_level_access ();
58
 
59
- do_action("ws_plugin__s2member_after_security_gate", get_defined_vars ());
 
60
 
61
- return /* Return for uniformity. */;
62
- }
63
- /**
64
- * s2Member's Security Gate (protects WordPress queries).
65
- *
66
- * @package s2Member\Security
67
- * @since 3.5
68
- *
69
- * @attaches-to ``add_action("pre_get_posts");``
70
- *
71
- * @param object $wp_query Global ``$wp_query``, by reference.
72
- * @return null May filter WordPress queries, by hiding protected content which is NOT available to the current User/Member.
73
- */
74
- public static function security_gate_query (&$wp_query = FALSE) // s2Member's Security Gate.
75
- {
76
- do_action("ws_plugin__s2member_before_security_gate_query", get_defined_vars ());
77
-
78
- c_ws_plugin__s2member_querys::query_level_access ($wp_query); // By reference.
79
 
80
- do_action("ws_plugin__s2member_after_security_gate_query", get_defined_vars ());
81
 
82
- return /* Return for uniformity. */;
83
- }
84
- }
85
  }
86
- ?>
1
  <?php
2
  /**
3
+ * s2Member's Security Gate.
4
+ *
5
+ * Copyright: © 2009-2011
6
+ * {@link http://www.websharks-inc.com/ WebSharks, Inc.}
7
+ * (coded in the USA)
8
+ *
9
+ * Released under the terms of the GNU General Public License.
10
+ * You should have received a copy of the GNU General Public License,
11
+ * along with this software. In the main directory, see: /licensing/
12
+ * If not, see: {@link http://www.gnu.org/licenses/}.
13
+ *
14
+ * @package s2Member\Security
15
+ * @since 3.5
16
+ */
17
+ if(realpath(__FILE__) === realpath($_SERVER['SCRIPT_FILENAME']))
18
+ exit('Do not access this file directly.');
19
 
20
+ if(!class_exists('c_ws_plugin__s2member_security'))
21
+ {
22
+ /**
23
+ * s2Member's Security Gate.
24
+ *
25
+ * @package s2Member\Security
26
+ * @since 3.5
27
+ */
28
+ class c_ws_plugin__s2member_security
29
  {
30
  /**
31
+ * s2Member's Security Gate (protects WordPress content).
32
+ *
33
+ * @package s2Member\Security
34
+ * @since 3.5
35
+ *
36
+ * @attaches-to ``add_action('wp');``
37
+ *
38
+ * @return null May redirect a browser *(exiting script execution)*, when/if content is NOT available to the current User/Member.
39
+ */
40
+ public static function security_gate() // s2Member's Security Gate.
41
+ {
42
+ do_action('ws_plugin__s2member_before_security_gate', get_defined_vars());
 
 
 
 
 
 
 
 
43
 
44
+ if(is_category()) // Categories & other inclusives.
45
+ c_ws_plugin__s2member_catgs::check_catg_level_access();
46
 
47
+ else if(is_tag()) // Post/Page Tags & other inclusives.
48
+ c_ws_plugin__s2member_ptags::check_ptag_level_access();
49
 
50
+ else if(is_single()) // All Posts & other inclusives.
51
+ c_ws_plugin__s2member_posts::check_post_level_access();
52
 
53
+ else if(is_page()) // All Pages & other inclusives.
54
+ c_ws_plugin__s2member_pages::check_page_level_access();
55
 
56
+ else // Else, we simply look at URIs & other inclusives.
57
+ c_ws_plugin__s2member_ruris::check_ruri_level_access();
58
 
59
+ do_action('ws_plugin__s2member_after_security_gate', get_defined_vars());
60
+ }
61
 
62
+ /**
63
+ * s2Member's Security Gate (protects WordPress queries).
64
+ *
65
+ * @package s2Member\Security
66
+ * @since 3.5
67
+ *
68
+ * @attaches-to ``add_action('pre_get_posts');``
69
+ *
70
+ * @param WP_Query $wp_query Global ``$wp_query``, by reference.
71
+ *
72
+ * @return null May filter WordPress queries, by hiding protected content which is NOT available to the current User/Member.
73
+ */
74
+ public static function security_gate_query(&$wp_query = NULL) // s2Member's Security Gate.
75
+ {
76
+ do_action('ws_plugin__s2member_before_security_gate_query', get_defined_vars());
 
 
 
77
 
78
+ c_ws_plugin__s2member_querys::query_level_access($wp_query); // By reference.
79
 
80
+ do_action('ws_plugin__s2member_after_security_gate_query', get_defined_vars());
81
+ }
 
82
  }
83
+ }
includes/classes/tracking-codes.inc.php CHANGED
@@ -57,7 +57,7 @@ if(!class_exists("c_ws_plugin__s2member_tracking_codes"))
57
  {
58
  delete_transient($transient); // Only display this ONE time. Delete transient immediately.
59
 
60
- echo '<img src="'.esc_attr(site_url("/?s2member_delete_tracking_cookie=1")).'" alt="." style="width:1px; height:1px; border:0;" />'."\n";
61
 
62
  foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
63
  do_action("ws_plugin__s2member_during_display_signup_tracking_codes", get_defined_vars());
@@ -102,7 +102,7 @@ if(!class_exists("c_ws_plugin__s2member_tracking_codes"))
102
  {
103
  delete_transient($transient); // Only display this ONE time. Delete transient immediately.
104
 
105
- echo '<img src="'.esc_attr(site_url("/?s2member_delete_tracking_cookie=1")).'" alt="." style="width:1px; height:1px; border:0;" />'."\n";
106
 
107
  foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
108
  do_action("ws_plugin__s2member_during_display_modification_tracking_codes", get_defined_vars());
@@ -147,7 +147,7 @@ if(!class_exists("c_ws_plugin__s2member_tracking_codes"))
147
  {
148
  delete_transient($transient); // Only display this ONE time. Delete transient immediately.
149
 
150
- echo '<img src="'.esc_attr(site_url("/?s2member_delete_tracking_cookie=1")).'" alt="." style="width:1px; height:1px; border:0;" />'."\n";
151
 
152
  foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
153
  do_action("ws_plugin__s2member_during_display_ccap_tracking_codes", get_defined_vars());
@@ -190,7 +190,7 @@ if(!class_exists("c_ws_plugin__s2member_tracking_codes"))
190
  {
191
  delete_transient($transient); // Only display this ONE time. Delete transient immediately.
192
 
193
- echo '<img src="'.esc_attr(site_url("/?s2member_delete_sp_tracking_cookie=1")).'" alt="." style="width:1px; height:1px; border:0;" />'."\n";
194
 
195
  foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
196
  do_action("ws_plugin__s2member_during_display_sp_tracking_codes", get_defined_vars());
57
  {
58
  delete_transient($transient); // Only display this ONE time. Delete transient immediately.
59
 
60
+ echo '<img src="'.esc_attr(home_url("/?s2member_delete_tracking_cookie=1")).'" alt="." style="width:1px; height:1px; border:0;" />'."\n";
61
 
62
  foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
63
  do_action("ws_plugin__s2member_during_display_signup_tracking_codes", get_defined_vars());
102
  {
103
  delete_transient($transient); // Only display this ONE time. Delete transient immediately.
104
 
105
+ echo '<img src="'.esc_attr(home_url("/?s2member_delete_tracking_cookie=1")).'" alt="." style="width:1px; height:1px; border:0;" />'."\n";
106
 
107
  foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
108
  do_action("ws_plugin__s2member_during_display_modification_tracking_codes", get_defined_vars());
147
  {
148
  delete_transient($transient); // Only display this ONE time. Delete transient immediately.
149
 
150
+ echo '<img src="'.esc_attr(home_url("/?s2member_delete_tracking_cookie=1")).'" alt="." style="width:1px; height:1px; border:0;" />'."\n";
151
 
152
  foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
153
  do_action("ws_plugin__s2member_during_display_ccap_tracking_codes", get_defined_vars());
190
  {
191
  delete_transient($transient); // Only display this ONE time. Delete transient immediately.
192
 
193
+ echo '<img src="'.esc_attr(home_url("/?s2member_delete_sp_tracking_cookie=1")).'" alt="." style="width:1px; height:1px; border:0;" />'."\n";
194
 
195
  foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
196
  do_action("ws_plugin__s2member_during_display_sp_tracking_codes", get_defined_vars());
includes/classes/utilities.inc.php CHANGED
@@ -147,7 +147,7 @@ if (!class_exists ("c_ws_plugin__s2member_utilities"))
147
  if ($v && file_exists (($template = dirname (dirname (__FILE__)) . "/templates/badges/s-badge.php")))
148
  {
149
  $badge = trim (c_ws_plugin__s2member_utilities::evl (file_get_contents ($template)));
150
- $badge = preg_replace ("/%%site_url%%/i", urlencode (site_url ()), preg_replace ("/%%v%%/i", (string)$v, $badge));
151
  $badge = preg_replace ("/%%no_cache%%/i", (($no_cache) ? "&amp;no_cache=" . urlencode (mt_rand (0, PHP_INT_MAX)) : ""), $badge);
152
  $badge = preg_replace ("/%%display_on_failure%%/i", (($display_on_failure) ? "&amp;display_on_failure=1" : ""), $badge);
153
  }
147
  if ($v && file_exists (($template = dirname (dirname (__FILE__)) . "/templates/badges/s-badge.php")))
148
  {
149
  $badge = trim (c_ws_plugin__s2member_utilities::evl (file_get_contents ($template)));
150
+ $badge = preg_replace ("/%%site_url%%/i", urlencode (home_url ()), preg_replace ("/%%v%%/i", (string)$v, $badge));
151
  $badge = preg_replace ("/%%no_cache%%/i", (($no_cache) ? "&amp;no_cache=" . urlencode (mt_rand (0, PHP_INT_MAX)) : ""), $badge);
152
  $badge = preg_replace ("/%%display_on_failure%%/i", (($display_on_failure) ? "&amp;display_on_failure=1" : ""), $badge);
153
  }
includes/classes/utils-conds.inc.php CHANGED
@@ -148,6 +148,11 @@ if(!class_exists("c_ws_plugin__s2member_utils_conds"))
148
  {
149
  $parse["path"] = (!empty($parse["path"])) ? ((strpos($parse["path"], "/") === 0) ? $parse["path"] : "/".$parse["path"]) : "/";
150
 
 
 
 
 
 
151
  if(empty($parse["host"]) || strcasecmp($parse["host"], c_ws_plugin__s2member_utils_urls::parse_url(site_url(), PHP_URL_HOST)) === 0)
152
  if($parse["path"] === "/" || rtrim($parse["path"], "/") === rtrim(c_ws_plugin__s2member_utils_urls::parse_url(site_url(), PHP_URL_PATH), "/"))
153
  if(get_option("permalink_structure") || (empty($_GET["post_id"]) && empty($_GET["page_id"]) && empty($_GET["p"])))
148
  {
149
  $parse["path"] = (!empty($parse["path"])) ? ((strpos($parse["path"], "/") === 0) ? $parse["path"] : "/".$parse["path"]) : "/";
150
 
151
+ if(empty($parse["host"]) || strcasecmp($parse["host"], c_ws_plugin__s2member_utils_urls::parse_url(home_url(), PHP_URL_HOST)) === 0)
152
+ if($parse["path"] === "/" || rtrim($parse["path"], "/") === rtrim(c_ws_plugin__s2member_utils_urls::parse_url(home_url(), PHP_URL_PATH), "/"))
153
+ if(get_option("permalink_structure") || (empty($_GET["post_id"]) && empty($_GET["page_id"]) && empty($_GET["p"])))
154
+ return true;
155
+
156
  if(empty($parse["host"]) || strcasecmp($parse["host"], c_ws_plugin__s2member_utils_urls::parse_url(site_url(), PHP_URL_HOST)) === 0)
157
  if($parse["path"] === "/" || rtrim($parse["path"], "/") === rtrim(c_ws_plugin__s2member_utils_urls::parse_url(site_url(), PHP_URL_PATH), "/"))
158
  if(get_option("permalink_structure") || (empty($_GET["post_id"]) && empty($_GET["page_id"]) && empty($_GET["p"])))
includes/classes/utils-gets.inc.php CHANGED
@@ -33,13 +33,18 @@ if(!class_exists('c_ws_plugin__s2member_utils_gets'))
33
  * @package s2Member\Utilities
34
  * @since 3.5
35
  *
36
- * @uses {@link http://codex.wordpress.org/Function_Reference/get_all_category_ids get_all_category_ids()}
37
  *
38
  * @return array Unique array of all Category IDs *(as integers)*.
39
  */
40
  public static function get_all_category_ids()
41
  {
42
- if(is_array($category_ids = get_all_category_ids())) // Use a WP function for this.
 
 
 
 
 
43
  $category_ids = c_ws_plugin__s2member_utils_arrays::force_integers((array)$category_ids);
44
 
45
  return (!empty($category_ids) && is_array($category_ids)) ? array_unique($category_ids) : array();
33
  * @package s2Member\Utilities
34
  * @since 3.5
35
  *
36
+ * @uses {@link http://codex.wordpress.org/Function_Reference/get_terms get_terms()}
37
  *
38
  * @return array Unique array of all Category IDs *(as integers)*.
39
  */
40
  public static function get_all_category_ids()
41
  {
42
+ if(!($category_ids = wp_cache_get('all_category_ids', 'category')))
43
+ {
44
+ $category_ids = get_terms('category', array('fields' => 'ids', 'get' => 'all'));
45
+ wp_cache_add('all_category_ids', $category_ids, 'category');
46
+ }
47
+ if(is_array($category_ids)) // Use a WP function for this.
48
  $category_ids = c_ws_plugin__s2member_utils_arrays::force_integers((array)$category_ids);
49
 
50
  return (!empty($category_ids) && is_array($category_ids)) ? array_unique($category_ids) : array();
includes/classes/utils-s2o.inc.php CHANGED
@@ -60,7 +60,7 @@ if (!class_exists ("c_ws_plugin__s2member_utils_s2o"))
60
  * @param string $o_file Location of calling `*-o.php` file.
61
  * @return str|bool WordPress settings, else false on failure.
62
  */
63
- public static function wp_settings_as ($wp_dir = FALSE, $o_file = FALSE)
64
  {
65
  if ($wp_dir && is_dir ($wp_dir) && is_readable (($wp_settings = $wp_dir . "/wp-settings.php")) && $o_file && file_exists ($o_file) && ($_wp_settings = trim (file_get_contents ($wp_settings))))
66
  {
60
  * @param string $o_file Location of calling `*-o.php` file.
61
  * @return str|bool WordPress settings, else false on failure.
62
  */
63
+ public static function wp_settings_as ($wp_dir = '', $o_file = '')
64
  {
65
  if ($wp_dir && is_dir ($wp_dir) && is_readable (($wp_settings = $wp_dir . "/wp-settings.php")) && $o_file && file_exists ($o_file) && ($_wp_settings = trim (file_get_contents ($wp_settings))))
66
  {
includes/classes/utils-urls.inc.php CHANGED
@@ -62,7 +62,7 @@ if(!class_exists("c_ws_plugin__s2member_utils_urls"))
62
  public static function bp_register_url()
63
  {
64
  if( /* If BuddyPress is installed. */c_ws_plugin__s2member_utils_conds::bp_is_installed())
65
- return site_url(((function_exists("bp_get_signup_slug")) ? bp_get_signup_slug()."/" : BP_REGISTER_SLUG."/"));
66
 
67
  return /* Default return false. */ false;
68
  }
62
  public static function bp_register_url()
63
  {
64
  if( /* If BuddyPress is installed. */c_ws_plugin__s2member_utils_conds::bp_is_installed())
65
+ return home_url(((function_exists("bp_get_signup_slug")) ? bp_get_signup_slug()."/" : BP_REGISTER_SLUG."/"));
66
 
67
  return /* Default return false. */ false;
68
  }
includes/classes/utils-users.inc.php CHANGED
@@ -14,10 +14,10 @@
14
  * @package s2Member\Utilities
15
  * @since 3.5
16
  */
17
- if(realpath(__FILE__) === realpath($_SERVER["SCRIPT_FILENAME"]))
18
- exit ("Do not access this file directly.");
19
 
20
- if(!class_exists("c_ws_plugin__s2member_utils_users"))
21
  {
22
  /**
23
  * User utilities.
@@ -61,19 +61,20 @@ if(!class_exists("c_ws_plugin__s2member_utils_users"))
61
  */
62
  public static function get_user_custom_with($subscr_txn_baid_cid_id = '', $os0 = '')
63
  {
64
- global $wpdb; /** @var wpdb $wpdb */
 
65
 
66
  if($subscr_txn_baid_cid_id && $os0) // This case includes some additional routines that can use the ``$os0`` value.
67
  {
68
  if(($q = $wpdb->get_row("SELECT `user_id` FROM `".$wpdb->usermeta."` WHERE (`meta_key` = '".$wpdb->prefix."s2member_subscr_id' OR `meta_key` = '".$wpdb->prefix."s2member_subscr_baid' OR `meta_key` = '".$wpdb->prefix."s2member_subscr_cid' OR `meta_key` = '".$wpdb->prefix."s2member_first_payment_txn_id') AND (`meta_value` = '".esc_sql($subscr_txn_baid_cid_id)."' OR `meta_value` = '".esc_sql($os0)."') LIMIT 1"))
69
  || ($q = $wpdb->get_row("SELECT `ID` AS `user_id` FROM `".$wpdb->users."` WHERE `ID` = '".esc_sql($os0)."' LIMIT 1"))
70
- ) if(($custom = get_user_option("s2member_custom", $q->user_id)))
71
  return $custom;
72
  }
73
  else if($subscr_txn_baid_cid_id) // Otherwise, if all we have is a Subscr./Txn. ID value.
74
  {
75
  if(($q = $wpdb->get_row("SELECT `user_id` FROM `".$wpdb->usermeta."` WHERE (`meta_key` = '".$wpdb->prefix."s2member_subscr_id' OR `meta_key` = '".$wpdb->prefix."s2member_subscr_baid' OR `meta_key` = '".$wpdb->prefix."s2member_subscr_cid' OR `meta_key` = '".$wpdb->prefix."s2member_first_payment_txn_id') AND `meta_value` = '".esc_sql($subscr_txn_baid_cid_id)."' LIMIT 1")))
76
- if(($custom = get_user_option("s2member_custom", $q->user_id)))
77
  return $custom;
78
  }
79
  return FALSE; // Otherwise, return false.
@@ -165,13 +166,13 @@ if(!class_exists("c_ws_plugin__s2member_utils_users"))
165
  || (!$user_id && !$subscr_txn_baid_cid_id && is_object($user = wp_get_current_user()) && !empty($user->ID) && ($user_id = $user->ID))
166
  )
167
  {
168
- $_subscr_baid = get_user_option("s2member_subscr_baid", $user_id);
169
- $_subscr_cid = get_user_option("s2member_subscr_cid", $user_id);
170
- $_subscr_id = get_user_option("s2member_subscr_id", $user_id);
171
 
172
  if($_subscr_id && (!$subscr_txn_baid_cid_id || $subscr_txn_baid_cid_id === $_subscr_id || $subscr_txn_baid_cid_id === $_subscr_baid || $subscr_txn_baid_cid_id === $_subscr_cid))
173
- if(is_array($ipn_signup_vars = get_user_option("s2member_ipn_signup_vars", $user_id)))
174
- if($ipn_signup_vars["subscr_id"] === $_subscr_id)
175
  return $ipn_signup_vars;
176
  }
177
  return FALSE; // Otherwise, return false.
@@ -223,7 +224,7 @@ if(!class_exists("c_ws_plugin__s2member_utils_users"))
223
  || (!func_num_args() && (!is_object($user = (is_user_logged_in()) ? wp_get_current_user() : FALSE) || empty($user->ID)))
224
  ) return FALSE; // The ``$user`` was passed in but is NOT an object; or nobody is logged in.
225
 
226
- return ($subscr_id = get_user_option("s2member_subscr_id", $user->ID)) ? $subscr_id : $user->ID;
227
  }
228
 
229
  /**
@@ -334,39 +335,42 @@ if(!class_exists("c_ws_plugin__s2member_utils_users"))
334
  else if(isset ($user->data->{$wpdb->prefix.$field_id}))
335
  return $user->data->{$wpdb->prefix.$field_id};
336
 
337
- else if(strcasecmp($field_id, "full_name") === 0)
338
- return trim($user->first_name." ".$user->last_name);
339
 
340
- else if(preg_match("/^(email|user_email)$/i", $field_id))
341
  return $user->user_email;
342
 
343
- else if(preg_match("/^(login|user_login)$/i", $field_id))
344
  return $user->user_login;
345
 
346
- else if(strcasecmp($field_id, "s2member_access_role") === 0)
 
 
 
347
  return c_ws_plugin__s2member_user_access::user_access_role($user);
348
 
349
- else if(strcasecmp($field_id, "s2member_access_level") === 0)
350
  return c_ws_plugin__s2member_user_access::user_access_level($user);
351
 
352
- else if(strcasecmp($field_id, "s2member_access_label") === 0)
353
  return c_ws_plugin__s2member_user_access::user_access_label($user);
354
 
355
- else if(strcasecmp($field_id, "s2member_access_ccaps") === 0)
356
  return c_ws_plugin__s2member_user_access::user_access_ccaps($user);
357
 
358
- else if(strcasecmp($field_id, "ip") === 0 && is_object($current_user) && !empty($current_user->ID) && $current_user->ID === ($user_id = $user->ID))
359
- return $_SERVER["REMOTE_ADDR"];
360
 
361
- else if(strcasecmp($field_id, "s2member_registration_ip") === 0 || strcasecmp($field_id, "reg_ip") === 0 || strcasecmp($field_id, "ip") === 0)
362
- return get_user_option("s2member_registration_ip", $user_id);
363
 
364
- else if(strcasecmp($field_id, "s2member_subscr_or_wp_id") === 0)
365
- return ($subscr_id = get_user_option("s2member_subscr_id", $user_id)) ? $subscr_id : $user_id;
366
 
367
- else if(is_array($fields = get_user_option("s2member_custom_fields", $user_id)))
368
- if(isset ($fields[preg_replace("/[^a-z0-9]/i", "_", strtolower($field_id))]))
369
- return $fields[preg_replace("/[^a-z0-9]/i", "_", strtolower($field_id))];
370
  }
371
  return FALSE; // Otherwise, return false.
372
  }
14
  * @package s2Member\Utilities
15
  * @since 3.5
16
  */
17
+ if(realpath(__FILE__) === realpath($_SERVER['SCRIPT_FILENAME']))
18
+ exit ('Do not access this file directly.');
19
 
20
+ if(!class_exists('c_ws_plugin__s2member_utils_users'))
21
  {
22
  /**
23
  * User utilities.
61
  */
62
  public static function get_user_custom_with($subscr_txn_baid_cid_id = '', $os0 = '')
63
  {
64
+ global $wpdb;
65
+ /** @var wpdb $wpdb */
66
 
67
  if($subscr_txn_baid_cid_id && $os0) // This case includes some additional routines that can use the ``$os0`` value.
68
  {
69
  if(($q = $wpdb->get_row("SELECT `user_id` FROM `".$wpdb->usermeta."` WHERE (`meta_key` = '".$wpdb->prefix."s2member_subscr_id' OR `meta_key` = '".$wpdb->prefix."s2member_subscr_baid' OR `meta_key` = '".$wpdb->prefix."s2member_subscr_cid' OR `meta_key` = '".$wpdb->prefix."s2member_first_payment_txn_id') AND (`meta_value` = '".esc_sql($subscr_txn_baid_cid_id)."' OR `meta_value` = '".esc_sql($os0)."') LIMIT 1"))
70
  || ($q = $wpdb->get_row("SELECT `ID` AS `user_id` FROM `".$wpdb->users."` WHERE `ID` = '".esc_sql($os0)."' LIMIT 1"))
71
+ ) if(($custom = get_user_option('s2member_custom', $q->user_id)))
72
  return $custom;
73
  }
74
  else if($subscr_txn_baid_cid_id) // Otherwise, if all we have is a Subscr./Txn. ID value.
75
  {
76
  if(($q = $wpdb->get_row("SELECT `user_id` FROM `".$wpdb->usermeta."` WHERE (`meta_key` = '".$wpdb->prefix."s2member_subscr_id' OR `meta_key` = '".$wpdb->prefix."s2member_subscr_baid' OR `meta_key` = '".$wpdb->prefix."s2member_subscr_cid' OR `meta_key` = '".$wpdb->prefix."s2member_first_payment_txn_id') AND `meta_value` = '".esc_sql($subscr_txn_baid_cid_id)."' LIMIT 1")))
77
+ if(($custom = get_user_option('s2member_custom', $q->user_id)))
78
  return $custom;
79
  }
80
  return FALSE; // Otherwise, return false.
166
  || (!$user_id && !$subscr_txn_baid_cid_id && is_object($user = wp_get_current_user()) && !empty($user->ID) && ($user_id = $user->ID))
167
  )
168
  {
169
+ $_subscr_baid = get_user_option('s2member_subscr_baid', $user_id);
170
+ $_subscr_cid = get_user_option('s2member_subscr_cid', $user_id);
171
+ $_subscr_id = get_user_option('s2member_subscr_id', $user_id);
172
 
173
  if($_subscr_id && (!$subscr_txn_baid_cid_id || $subscr_txn_baid_cid_id === $_subscr_id || $subscr_txn_baid_cid_id === $_subscr_baid || $subscr_txn_baid_cid_id === $_subscr_cid))
174
+ if(is_array($ipn_signup_vars = get_user_option('s2member_ipn_signup_vars', $user_id)))
175
+ if($ipn_signup_vars['subscr_id'] === $_subscr_id)
176
  return $ipn_signup_vars;
177
  }
178
  return FALSE; // Otherwise, return false.
224
  || (!func_num_args() && (!is_object($user = (is_user_logged_in()) ? wp_get_current_user() : FALSE) || empty($user->ID)))
225
  ) return FALSE; // The ``$user`` was passed in but is NOT an object; or nobody is logged in.
226
 
227
+ return ($subscr_id = get_user_option('s2member_subscr_id', $user->ID)) ? $subscr_id : $user->ID;
228
  }
229
 
230
  /**
335
  else if(isset ($user->data->{$wpdb->prefix.$field_id}))
336
  return $user->data->{$wpdb->prefix.$field_id};
337
 
338
+ else if(strcasecmp($field_id, 'full_name') === 0)
339
+ return trim($user->first_name.' '.$user->last_name);
340
 
341
+ else if(preg_match('/^(email|user_email)$/i', $field_id))
342
  return $user->user_email;
343
 
344
+ else if(preg_match('/^(login|user_login)$/i', $field_id))
345
  return $user->user_login;
346
 
347
+ else if(preg_match('/^(s2member_)?registration_time$/i', $field_id))
348
+ return $user->user_registered;
349
+
350
+ else if(strcasecmp($field_id, 's2member_access_role') === 0)
351
  return c_ws_plugin__s2member_user_access::user_access_role($user);
352
 
353
+ else if(strcasecmp($field_id, 's2member_access_level') === 0)
354
  return c_ws_plugin__s2member_user_access::user_access_level($user);
355
 
356
+ else if(strcasecmp($field_id, 's2member_access_label') === 0)
357
  return c_ws_plugin__s2member_user_access::user_access_label($user);
358
 
359
+ else if(strcasecmp($field_id, 's2member_access_ccaps') === 0)
360
  return c_ws_plugin__s2member_user_access::user_access_ccaps($user);
361
 
362
+ else if(strcasecmp($field_id, 'ip') === 0 && is_object($current_user) && !empty($current_user->ID) && $current_user->ID === ($user_id = $user->ID))
363
+ return $_SERVER['REMOTE_ADDR'];
364
 
365
+ else if(strcasecmp($field_id, 's2member_registration_ip') === 0 || strcasecmp($field_id, 'reg_ip') === 0 || strcasecmp($field_id, 'ip') === 0)
366
+ return get_user_option('s2member_registration_ip', $user_id);
367
 
368
+ else if(strcasecmp($field_id, 's2member_subscr_or_wp_id') === 0)
369
+ return ($subscr_id = get_user_option('s2member_subscr_id', $user_id)) ? $subscr_id : $user_id;
370
 
371
+ else if(is_array($fields = get_user_option('s2member_custom_fields', $user_id)))
372
+ if(isset ($fields[preg_replace('/[^a-z0-9]/i', '_', strtolower($field_id))]))
373
+ return $fields[preg_replace('/[^a-z0-9]/i', '_', strtolower($field_id))];
374
  }
375
  return FALSE; // Otherwise, return false.
376
  }
includes/hooks.inc.php CHANGED
@@ -55,6 +55,7 @@ add_action('init', 'c_ws_plugin__s2member_login_checks::monitor_simultaneous_log
55
  add_action('admin_init', 'c_ws_plugin__s2member_menu_pages::log_file_downloader');
56
  add_action('admin_init', 'c_ws_plugin__s2member_menu_pages::logs_zip_downloader');
57
 
 
58
  add_action('pre_get_posts', 'c_ws_plugin__s2member_security::security_gate_query', 100);
59
 
60
  add_action('wp', 'c_ws_plugin__s2member_ssl::check_force_ssl', 1);
55
  add_action('admin_init', 'c_ws_plugin__s2member_menu_pages::log_file_downloader');
56
  add_action('admin_init', 'c_ws_plugin__s2member_menu_pages::logs_zip_downloader');
57
 
58
+ add_filter('bbp_has_replies_query', 'c_ws_plugin__s2member_querys::_bbp_flag_has_replies');
59
  add_action('pre_get_posts', 'c_ws_plugin__s2member_security::security_gate_query', 100);
60
 
61
  add_action('wp', 'c_ws_plugin__s2member_ssl::check_force_ssl', 1);
includes/menu-pages/down-ops.inc.php CHANGED
@@ -64,7 +64,7 @@ if(!class_exists("c_ws_plugin__s2member_menu_page_down_ops"))
64
  echo '<div class="ws-menu-page-hr"></div>'."\n";
65
 
66
  echo '<p><strong>Upload restricted files to this security-enabled directory:</strong><br /><code>'.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])).'</code></p>'."\n";
67
- echo '<p>- Now, you can link to any protected file, using this special format:<br />&nbsp;&nbsp;<code>'.esc_html(site_url("/?s2member_file_download=example-file.zip")).'</code><br />&nbsp;&nbsp;<small><em><strong>s2member_file_download</strong> = file, relative to the /'.esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])).'/ directory. In other words, just the file name.</em></small></p>'."\n";
68
  echo '<p>- Or, use: <code>[s2File download="example-file.zip" /]</code> <em>(easier Shortcode if you prefer)</em><br />&nbsp;&nbsp;<small><em><strong>Shortcode equivalent:</strong> <code>[s2File /]</code> produces the entire URL for you, easier.</em></small></p>'."\n";
69
 
70
  echo '<div class="ws-menu-page-hr"></div>'."\n";
@@ -164,11 +164,11 @@ if(!class_exists("c_ws_plugin__s2member_menu_page_down_ops"))
164
 
165
  echo '<div class="ws-menu-page-hr"></div>'."\n";
166
 
167
- echo '<p>'.esc_html(site_url("/?s2member_file_download=example-file.zip")).'<code>&amp;s2member_file_download_key=&lt;?php echo s2member_file_download_key("example-file.zip"); ?&gt;</code><br />&nbsp;&nbsp;<small><em><strong>s2member_file_download_key</strong> = &lt;?php echo s2member_file_download_key("file, relative to the /'.esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])).'/ directory"); ?&gt;</em></small></p>'."\n";
168
 
169
  echo '<div class="ws-menu-page-hr"></div>'."\n";
170
 
171
- echo '<p>'.esc_html(site_url("/?s2member_file_download=example-file.zip")).'<code>&amp;s2member_file_download_key=[s2Key file_download="example-file.zip" /]</code><br />&nbsp;&nbsp;<small><em><strong>Shortcode equivalent:</strong> <code>[s2Key file_download="example-file.zip" /]</code></em></small></p>'."\n";
172
 
173
  echo '<div class="ws-menu-page-hr"></div>'."\n";
174
 
@@ -261,7 +261,7 @@ if(!class_exists("c_ws_plugin__s2member_menu_page_down_ops"))
261
  echo '<div class="ws-menu-page-hr"></div>'."\n";
262
 
263
  echo '<p><em><strong>Dev Note w/Technical Details:</strong> s2Member uses "Digitally Signed URLs", authenticated by the Amazon S3 API. Documented for developers <a href="http://docs.amazonwebservices.com/AmazonS3/latest/dev/index.html?RESTAuthentication.html" target="_blank" rel="external">here</a>. To put it simply, s2Member will generate Amazon S3 URLs (internally); which allow Customers temporary access to specific files inside your S3 Bucket. s2Member\'s Digitally Signed URLs leading to Amazon S3, give a Customer 24 hours to connect to the file inside your S3 Bucket. This connection period of 24 hours is largely irrelevant when used in combination with s2Member, because access is renewed for another 24 hours each time you make a file available to a User/Member, and they are authenticated by your configuration of s2Member. This connection period of 24 hours is just a secondary line of defense to further prevent the possibility of link sharing. If you need to change this connection timeout of <code>24 hours</code> for some reason (not likely), you can use this WordPress Filter: <code>ws_plugin__s2member_amazon_s3_file_expires_time</code>.</em></p>'."\n";
264
- echo '<p><em><strong>Linking To Protected Files:</strong> Nothing changes. s2Member\'s integration with Amazon S3 serves protected files through the same links that all s2Member site owners use. For example, you might use: <code>'.esc_html(site_url("/?s2member_file_download=example-file.zip")).'</code>, where <strong>s2member_file_download</strong> = the file, relative to the root of your Amazon S3 Bucket. In other words, just the file name in most cases. s2Member will redirect Users/Members to a digitally signed Amazon S3 URL, which allows them access to a particular file via Amazon S3. For further details, please review this section of your Dashboard: <code>s2Member -› Download Options -› Basic Download Restrictions</code>. Also see: <code>s2Member -› Download Options -› Advanced Mod-Rewrite Linkage</code>.</em></p>'."\n";
265
  echo '<p><em><strong>Content Type, Disposition &amp; Inline Files:</strong> The query string parameter <code>&amp;s2member_file_inline=yes</code> DOES work for files served directly through Amazon S3. s2Member DOES have control over the <code>Content-Type</code> and <code>Content-Disposition</code> headers for files being served through Amazon S3. However, Amazon CloudFront servers do NOT automatically determine the MIME type for the objects they serve. If you integrate both Amazon S3 and CloudFront, s2Member will NOT have control over headers. Therefore, when you upload a file to your Amazon S3 Bucket, you should set its Content-Type header. Again, with the Amazon S3/CloudFront combination, you MUST configure headers yourself (such as <code>Content-Type: video/webm</code>, or <code>Content-Disposition: inline|attachment</code>) that you want Amazon CloudFront to send for a particular file. It\'s quite easy. You do this by setting <code>Properties -› Metadata (i.e. headers)</code> on a per-file basis, from inside your Amazon S3 Management Console. In short, when you upload a file to your Amazon S3 Bucket, if you want that file to be served a certain way, be sure to configure its <code>Properties -› Metadata</code> accordingly.</em></p>'."\n";
266
 
267
  echo '<div class="ws-menu-page-hr"></div>'."\n";
@@ -349,7 +349,7 @@ if(!class_exists("c_ws_plugin__s2member_menu_page_down_ops"))
349
 
350
  echo '<p><em><strong>Dev Note w/Technical Details:</strong> s2Member\'s auto-configuration routines for Amazon CloudFront (below), are designed to create &amp; configure various components on your Amazon Web Services account, which are all requirements for you to <a href="http://docs.amazonwebservices.com/AmazonCloudFront/2010-11-01/DeveloperGuide/index.html?HowToPrivateContent.html" target="_blank" rel="external">serve protected files through the Amazon S3/CloudFront combination</a>. These components include: an Origin Access Identity, read permissions for the Origin Access Identity, and two private content Distributions. One private content Distribution for file downloads, and another private content Distribution for streaming media files; both connected to and sourced by your Amazon S3 Bucket. In addition, s2Member will automatically configure an ACL &amp; Policy (i.e. permissions) on your Amazon S3 Bucket to make sure your protected object/files are NOT available to the public.</em></p>'."\n";
351
  echo '<p><em><strong>Dev Note w/Technical Details:</strong> s2Member uses "Digitally Signed URLs", authenticated by the Amazon CloudFront API. Documented for developers <a href="http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/PrivateContent.html" target="_blank" rel="external">here</a>. To put it simply, s2Member will generate Amazon CloudFront URLs (internally); which allow Customers temporary access to specific files inside your S3 Bucket — via CloudFront Distributions. s2Member\'s Digitally Signed URLs leading to Amazon S3/CloudFront, give a Customer 24 hours to connect to the file inside your S3 Bucket. This connection period of 24 hours is largely irrelevant when used in combination with s2Member, because access is renewed for another 24 hours each time you make a file available to a User/Member, and they are authenticated by your configuration of s2Member. This connection period of 24 hours is just a secondary line of defense to further prevent the possibility of link sharing. If you need to change this connection timeout of <code>24 hours</code> for some reason (not likely), you can use this WordPress Filter: <code>ws_plugin__s2member_amazon_cf_file_expires_time</code>.</em></p>'."\n";
352
- echo '<p><em><strong>Linking To Protected Files:</strong> RTMP streams are special, but nothing else changes. s2Member\'s integration with Amazon S3/CloudFront serves protected files through the same links that all s2Member site owners use. For example, you might use: <code>'.esc_html(site_url("/?s2member_file_download=example-file.zip")).'</code>, where <strong>s2member_file_download</strong> = the file, relative to the root of your Amazon S3 Bucket. In other words, just the file name in most cases. s2Member will redirect Users/Members to a digitally signed Amazon CloudFront URL, which allows them access to a particular file via Amazon CloudFront. For further details, please review this section of your Dashboard: <code>s2Member -› Download Options -› Basic Download Restrictions</code>. Also see: <code>s2Member -› Download Options -› Advanced Mod-Rewrite Linkage</code>. If you\'re streaming audio/video files over the RTMP protocol, please review the section below: <code>JW Player &amp; RTMP Protocol Examples</code>.</em></p>'."\n";
353
  echo '<p><em><strong>Content Type, Disposition &amp; Inline Files:</strong> An IMPORTANT issue. The query string parameter <code>&amp;s2member_file_inline=yes</code> does NOTHING for files served via Amazon CloudFront. s2Member has NO control over the <code>Content-Type</code> and/or <code>Content-Disposition</code> headers for a file being served through Amazon CloudFront, and CloudFront servers do NOT automatically determine the MIME type for the objects they serve. Therefore, when you upload a file to your Amazon S3 Bucket, you should set its Content-Type header. That is, you MUST configure headers yourself (such as <code>Content-Type: video/webm</code>, or <code>Content-Disposition: inline|attachment</code>) that you want Amazon CloudFront to send for a particular file. It\'s quite easy. You do this by setting <code>Properties -› Metadata (i.e. headers)</code> on a per-file basis, from inside your Amazon S3 Management Console. In short, when you upload a file to your Amazon S3 Bucket, if you want that file to be served a certain way, be sure to configure its <code>Properties -› Metadata</code> accordingly.</em></p>'."\n";
354
  echo (stripos(PHP_OS, "win") === 0 && c_ws_plugin__s2member_utils_conds::is_localhost()) ? '<p><em><strong>Localhost Developers:</strong> s2Member\'s Amazon CloudFront integration requires the <a href="http://php.net/manual/en/function.openssl-sign.php" target="_blank" rel="external">openssl_sign()</a> function in PHP so it can digitially sign CloudFront URLs. This function is sometimes problematic on localhost servers such as WAMP &amp; EasyPHP. We recommend installing <a href="http://www.slproweb.com/products/Win32OpenSSL.html" target="_blank" rel="external">this lightweight alternative for Windows</a> while you\'re developing. s2Member will automatically find it here: <code>C:\OpenSSL-Win[32/64]\bin\openssl.exe</code>.'.((file_exists("c:\openssl-win32\bin\openssl.exe") || file_exists("c:\openssl-win64\bin\openssl.exe")) ? ' <strong class="ws-menu-page-hilite">( s2Member has detected that OpenSSL-Win[32/64] IS installed in the correct location, thank you! )</strong>' : ' <strong class="ws-menu-page-hilite">(s2Member has detected that OpenSSL-Win[32/64] is NOT currently available)</strong>').'</em></p>'."\n" : '';
355
 
@@ -393,7 +393,7 @@ if(!class_exists("c_ws_plugin__s2member_menu_page_down_ops"))
393
 
394
  echo '<td>'."\n";
395
  echo '<input type="hidden" name="ws_plugin__s2member_amazon_cf_files_private_key" id="ws-plugin--s2member-amazon-cf-files-private-key" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_private_key"]).'" data-s-prev-config-value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_private_key"]).'" />'."\n";
396
- echo '<textarea name="ws_plugin__s2member_amazon_cf_files_private_key_entry" id="ws-plugin--s2member-amazon-cf-files-private-key-entry" rows="3" wrap="off" spellcheck="false" class="monospace">'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_private_key"]).'</textarea><br />'."\n";
397
  echo 'See: <code>Amazon Web Services Account -› Security Credentials -› CloudFront Key Pairs</code><br />'."\n";
398
  echo '<em>* Note, s2Member needs your <strong>Private Key file</strong>, NOT your Public Key file.</em>'."\n";
399
  echo '</td>'."\n";
@@ -443,7 +443,7 @@ if(!class_exists("c_ws_plugin__s2member_menu_page_down_ops"))
443
 
444
  echo '<td>'."\n";
445
  echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_amazon_cf_files_distro_downloads_cname" id="ws-plugin--s2member-amazon-cf-files-downloads-distro-cname" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_downloads_cname"]).'" /><br />'."\n";
446
- echo 'Example: <code>s2-file-downloads.'.esc_html(c_ws_plugin__s2member_utils_urls::parse_url(site_url(), PHP_URL_HOST)).'</code>.<br />'."\n";
447
  echo '<em>* Optional, do NOT fill this in unless you know what you\'re doing. This requires DNS changes.</em>'."\n";
448
  echo '</td>'."\n";
449
 
@@ -461,7 +461,7 @@ if(!class_exists("c_ws_plugin__s2member_menu_page_down_ops"))
461
 
462
  echo '<td>'."\n";
463
  echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_amazon_cf_files_distro_streaming_cname" id="ws-plugin--s2member-amazon-cf-files-streaming-distro-cname" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_streaming_cname"]).'" /><br />'."\n";
464
- echo 'Example: <code>s2-streaming-files.'.esc_html(c_ws_plugin__s2member_utils_urls::parse_url(site_url(), PHP_URL_HOST)).'</code>.<br />'."\n";
465
  echo '<em>* Optional, do NOT fill this in unless you know what you\'re doing. This requires DNS changes.</em>'."\n";
466
  echo '</td>'."\n";
467
 
64
  echo '<div class="ws-menu-page-hr"></div>'."\n";
65
 
66
  echo '<p><strong>Upload restricted files to this security-enabled directory:</strong><br /><code>'.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])).'</code></p>'."\n";
67
+ echo '<p>- Now, you can link to any protected file, using this special format:<br />&nbsp;&nbsp;<code>'.esc_html(home_url("/?s2member_file_download=example-file.zip")).'</code><br />&nbsp;&nbsp;<small><em><strong>s2member_file_download</strong> = file, relative to the /'.esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])).'/ directory. In other words, just the file name.</em></small></p>'."\n";
68
  echo '<p>- Or, use: <code>[s2File download="example-file.zip" /]</code> <em>(easier Shortcode if you prefer)</em><br />&nbsp;&nbsp;<small><em><strong>Shortcode equivalent:</strong> <code>[s2File /]</code> produces the entire URL for you, easier.</em></small></p>'."\n";
69
 
70
  echo '<div class="ws-menu-page-hr"></div>'."\n";
164
 
165
  echo '<div class="ws-menu-page-hr"></div>'."\n";
166
 
167
+ echo '<p>'.esc_html(home_url("/?s2member_file_download=example-file.zip")).'<code>&amp;s2member_file_download_key=&lt;?php echo s2member_file_download_key("example-file.zip"); ?&gt;</code><br />&nbsp;&nbsp;<small><em><strong>s2member_file_download_key</strong> = &lt;?php echo s2member_file_download_key("file, relative to the /'.esc_html(c_ws_plugin__s2member_utils_dirs::basename_dir_app_data($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])).'/ directory"); ?&gt;</em></small></p>'."\n";
168
 
169
  echo '<div class="ws-menu-page-hr"></div>'."\n";
170
 
171
+ echo '<p>'.esc_html(home_url("/?s2member_file_download=example-file.zip")).'<code>&amp;s2member_file_download_key=[s2Key file_download="example-file.zip" /]</code><br />&nbsp;&nbsp;<small><em><strong>Shortcode equivalent:</strong> <code>[s2Key file_download="example-file.zip" /]</code></em></small></p>'."\n";
172
 
173
  echo '<div class="ws-menu-page-hr"></div>'."\n";
174
 
261
  echo '<div class="ws-menu-page-hr"></div>'."\n";
262
 
263
  echo '<p><em><strong>Dev Note w/Technical Details:</strong> s2Member uses "Digitally Signed URLs", authenticated by the Amazon S3 API. Documented for developers <a href="http://docs.amazonwebservices.com/AmazonS3/latest/dev/index.html?RESTAuthentication.html" target="_blank" rel="external">here</a>. To put it simply, s2Member will generate Amazon S3 URLs (internally); which allow Customers temporary access to specific files inside your S3 Bucket. s2Member\'s Digitally Signed URLs leading to Amazon S3, give a Customer 24 hours to connect to the file inside your S3 Bucket. This connection period of 24 hours is largely irrelevant when used in combination with s2Member, because access is renewed for another 24 hours each time you make a file available to a User/Member, and they are authenticated by your configuration of s2Member. This connection period of 24 hours is just a secondary line of defense to further prevent the possibility of link sharing. If you need to change this connection timeout of <code>24 hours</code> for some reason (not likely), you can use this WordPress Filter: <code>ws_plugin__s2member_amazon_s3_file_expires_time</code>.</em></p>'."\n";
264
+ echo '<p><em><strong>Linking To Protected Files:</strong> Nothing changes. s2Member\'s integration with Amazon S3 serves protected files through the same links that all s2Member site owners use. For example, you might use: <code>'.esc_html(home_url("/?s2member_file_download=example-file.zip")).'</code>, where <strong>s2member_file_download</strong> = the file, relative to the root of your Amazon S3 Bucket. In other words, just the file name in most cases. s2Member will redirect Users/Members to a digitally signed Amazon S3 URL, which allows them access to a particular file via Amazon S3. For further details, please review this section of your Dashboard: <code>s2Member -› Download Options -› Basic Download Restrictions</code>. Also see: <code>s2Member -› Download Options -› Advanced Mod-Rewrite Linkage</code>.</em></p>'."\n";
265
  echo '<p><em><strong>Content Type, Disposition &amp; Inline Files:</strong> The query string parameter <code>&amp;s2member_file_inline=yes</code> DOES work for files served directly through Amazon S3. s2Member DOES have control over the <code>Content-Type</code> and <code>Content-Disposition</code> headers for files being served through Amazon S3. However, Amazon CloudFront servers do NOT automatically determine the MIME type for the objects they serve. If you integrate both Amazon S3 and CloudFront, s2Member will NOT have control over headers. Therefore, when you upload a file to your Amazon S3 Bucket, you should set its Content-Type header. Again, with the Amazon S3/CloudFront combination, you MUST configure headers yourself (such as <code>Content-Type: video/webm</code>, or <code>Content-Disposition: inline|attachment</code>) that you want Amazon CloudFront to send for a particular file. It\'s quite easy. You do this by setting <code>Properties -› Metadata (i.e. headers)</code> on a per-file basis, from inside your Amazon S3 Management Console. In short, when you upload a file to your Amazon S3 Bucket, if you want that file to be served a certain way, be sure to configure its <code>Properties -› Metadata</code> accordingly.</em></p>'."\n";
266
 
267
  echo '<div class="ws-menu-page-hr"></div>'."\n";
349
 
350
  echo '<p><em><strong>Dev Note w/Technical Details:</strong> s2Member\'s auto-configuration routines for Amazon CloudFront (below), are designed to create &amp; configure various components on your Amazon Web Services account, which are all requirements for you to <a href="http://docs.amazonwebservices.com/AmazonCloudFront/2010-11-01/DeveloperGuide/index.html?HowToPrivateContent.html" target="_blank" rel="external">serve protected files through the Amazon S3/CloudFront combination</a>. These components include: an Origin Access Identity, read permissions for the Origin Access Identity, and two private content Distributions. One private content Distribution for file downloads, and another private content Distribution for streaming media files; both connected to and sourced by your Amazon S3 Bucket. In addition, s2Member will automatically configure an ACL &amp; Policy (i.e. permissions) on your Amazon S3 Bucket to make sure your protected object/files are NOT available to the public.</em></p>'."\n";
351
  echo '<p><em><strong>Dev Note w/Technical Details:</strong> s2Member uses "Digitally Signed URLs", authenticated by the Amazon CloudFront API. Documented for developers <a href="http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/PrivateContent.html" target="_blank" rel="external">here</a>. To put it simply, s2Member will generate Amazon CloudFront URLs (internally); which allow Customers temporary access to specific files inside your S3 Bucket — via CloudFront Distributions. s2Member\'s Digitally Signed URLs leading to Amazon S3/CloudFront, give a Customer 24 hours to connect to the file inside your S3 Bucket. This connection period of 24 hours is largely irrelevant when used in combination with s2Member, because access is renewed for another 24 hours each time you make a file available to a User/Member, and they are authenticated by your configuration of s2Member. This connection period of 24 hours is just a secondary line of defense to further prevent the possibility of link sharing. If you need to change this connection timeout of <code>24 hours</code> for some reason (not likely), you can use this WordPress Filter: <code>ws_plugin__s2member_amazon_cf_file_expires_time</code>.</em></p>'."\n";
352
+ echo '<p><em><strong>Linking To Protected Files:</strong> RTMP streams are special, but nothing else changes. s2Member\'s integration with Amazon S3/CloudFront serves protected files through the same links that all s2Member site owners use. For example, you might use: <code>'.esc_html(home_url("/?s2member_file_download=example-file.zip")).'</code>, where <strong>s2member_file_download</strong> = the file, relative to the root of your Amazon S3 Bucket. In other words, just the file name in most cases. s2Member will redirect Users/Members to a digitally signed Amazon CloudFront URL, which allows them access to a particular file via Amazon CloudFront. For further details, please review this section of your Dashboard: <code>s2Member -› Download Options -› Basic Download Restrictions</code>. Also see: <code>s2Member -› Download Options -› Advanced Mod-Rewrite Linkage</code>. If you\'re streaming audio/video files over the RTMP protocol, please review the section below: <code>JW Player &amp; RTMP Protocol Examples</code>.</em></p>'."\n";
353
  echo '<p><em><strong>Content Type, Disposition &amp; Inline Files:</strong> An IMPORTANT issue. The query string parameter <code>&amp;s2member_file_inline=yes</code> does NOTHING for files served via Amazon CloudFront. s2Member has NO control over the <code>Content-Type</code> and/or <code>Content-Disposition</code> headers for a file being served through Amazon CloudFront, and CloudFront servers do NOT automatically determine the MIME type for the objects they serve. Therefore, when you upload a file to your Amazon S3 Bucket, you should set its Content-Type header. That is, you MUST configure headers yourself (such as <code>Content-Type: video/webm</code>, or <code>Content-Disposition: inline|attachment</code>) that you want Amazon CloudFront to send for a particular file. It\'s quite easy. You do this by setting <code>Properties -› Metadata (i.e. headers)</code> on a per-file basis, from inside your Amazon S3 Management Console. In short, when you upload a file to your Amazon S3 Bucket, if you want that file to be served a certain way, be sure to configure its <code>Properties -› Metadata</code> accordingly.</em></p>'."\n";
354
  echo (stripos(PHP_OS, "win") === 0 && c_ws_plugin__s2member_utils_conds::is_localhost()) ? '<p><em><strong>Localhost Developers:</strong> s2Member\'s Amazon CloudFront integration requires the <a href="http://php.net/manual/en/function.openssl-sign.php" target="_blank" rel="external">openssl_sign()</a> function in PHP so it can digitially sign CloudFront URLs. This function is sometimes problematic on localhost servers such as WAMP &amp; EasyPHP. We recommend installing <a href="http://www.slproweb.com/products/Win32OpenSSL.html" target="_blank" rel="external">this lightweight alternative for Windows</a> while you\'re developing. s2Member will automatically find it here: <code>C:\OpenSSL-Win[32/64]\bin\openssl.exe</code>.'.((file_exists("c:\openssl-win32\bin\openssl.exe") || file_exists("c:\openssl-win64\bin\openssl.exe")) ? ' <strong class="ws-menu-page-hilite">( s2Member has detected that OpenSSL-Win[32/64] IS installed in the correct location, thank you! )</strong>' : ' <strong class="ws-menu-page-hilite">(s2Member has detected that OpenSSL-Win[32/64] is NOT currently available)</strong>').'</em></p>'."\n" : '';
355
 
393
 
394
  echo '<td>'."\n";
395
  echo '<input type="hidden" name="ws_plugin__s2member_amazon_cf_files_private_key" id="ws-plugin--s2member-amazon-cf-files-private-key" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_private_key"]).'" data-s-prev-config-value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_private_key"]).'" />'."\n";
396
+ echo '<textarea name="ws_plugin__s2member_amazon_cf_files_private_key_entry" id="ws-plugin--s2member-amazon-cf-files-private-key-entry" rows="3" wrap="off" spellcheck="false">'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_private_key"]).'</textarea><br />'."\n";
397
  echo 'See: <code>Amazon Web Services Account -› Security Credentials -› CloudFront Key Pairs</code><br />'."\n";
398
  echo '<em>* Note, s2Member needs your <strong>Private Key file</strong>, NOT your Public Key file.</em>'."\n";
399
  echo '</td>'."\n";
443
 
444
  echo '<td>'."\n";
445
  echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_amazon_cf_files_distro_downloads_cname" id="ws-plugin--s2member-amazon-cf-files-downloads-distro-cname" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_downloads_cname"]).'" /><br />'."\n";
446
+ echo 'Example: <code>s2-file-downloads.'.esc_html(c_ws_plugin__s2member_utils_urls::parse_url(home_url(), PHP_URL_HOST)).'</code>.<br />'."\n";
447
  echo '<em>* Optional, do NOT fill this in unless you know what you\'re doing. This requires DNS changes.</em>'."\n";
448
  echo '</td>'."\n";
449
 
461
 
462
  echo '<td>'."\n";
463
  echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_amazon_cf_files_distro_streaming_cname" id="ws-plugin--s2member-amazon-cf-files-streaming-distro-cname" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["amazon_cf_files_distro_streaming_cname"]).'" /><br />'."\n";
464
+ echo 'Example: <code>s2-streaming-files.'.esc_html(c_ws_plugin__s2member_utils_urls::parse_url(home_url(), PHP_URL_HOST)).'</code>.<br />'."\n";
465
  echo '<em>* Optional, do NOT fill this in unless you know what you\'re doing. This requires DNS changes.</em>'."\n";
466
  echo '</td>'."\n";
467
 
includes/menu-pages/els-ops.inc.php CHANGED
@@ -199,7 +199,7 @@ if(!class_exists("c_ws_plugin__s2member_menu_page_els_ops"))
199
  echo '<div class="ws-menu-page-group" title="AWeber Integration">'."\n";
200
 
201
  echo '<div class="ws-menu-page-section ws-plugin--s2member-aweber-section">'."\n";
202
- echo '<a href="http://www.s2member.com/aweber" target="_blank"><img src="'.esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]).'/images/aweber-logo.png" class="ws-menu-page-right screenshot" style="width:125px; height:125px; border:0;" alt="." /></a>'."\n";
203
  echo '<h3>AWeber List Server Integration (optional)</h3>'."\n";
204
  echo '<p>s2Member can be integrated with AWeber. AWeber is an email marketing service. Whether you\'re looking to get your first email campaign off the ground, or you\'re a seasoned veteran who wants to dig into advanced tools like detailed email web analytics, activity based segmentation, geo-targeting and broadcast split-testing, AWeber\'s got just what you need to make email marketing work for you.</p>'."\n";
205
  echo '<p>You can have your Members automatically subscribed to your AWeber marketing lists <em>(e.g. newsletters / auto-responders)</em>. You\'ll need an <a href="http://www.s2member.com/aweber" target="_blank" rel="external">AWeber account</a> and your <a href="#" onclick="alert(\'To obtain your AWeber List ID(s), log into your AWeber account. Click on the Lists tab. On that page you\\\'ll find a Unique List ID associated with each of your lists. AWeber sometimes refers to this as a List Name instead of a List ID.\'); return false;">AWeber List IDs</a>. You will ALSO need to configure a <a href="http://www.s2member.com/kb/aweber-email-parser-for-s2member/" target="_blank" rel="external">Custom Email Parser</a> inside your AWeber account.</p>'."\n";
199
  echo '<div class="ws-menu-page-group" title="AWeber Integration">'."\n";
200
 
201
  echo '<div class="ws-menu-page-section ws-plugin--s2member-aweber-section">'."\n";
202
+ echo '<a href="http://www.s2member.com/aweber" target="_blank"><img src="'.esc_attr($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"]).'/images/aweber-logo.png" class="ws-menu-page-right ws-menu-page-bordered" style="width:125px; height:125px; border:0;" alt="." /></a>'."\n";
203
  echo '<h3>AWeber List Server Integration (optional)</h3>'."\n";
204
  echo '<p>s2Member can be integrated with AWeber. AWeber is an email marketing service. Whether you\'re looking to get your first email campaign off the ground, or you\'re a seasoned veteran who wants to dig into advanced tools like detailed email web analytics, activity based segmentation, geo-targeting and broadcast split-testing, AWeber\'s got just what you need to make email marketing work for you.</p>'."\n";
205
  echo '<p>You can have your Members automatically subscribed to your AWeber marketing lists <em>(e.g. newsletters / auto-responders)</em>. You\'ll need an <a href="http://www.s2member.com/aweber" target="_blank" rel="external">AWeber account</a> and your <a href="#" onclick="alert(\'To obtain your AWeber List ID(s), log into your AWeber account. Click on the Lists tab. On that page you\\\'ll find a Unique List ID associated with each of your lists. AWeber sometimes refers to this as a List Name instead of a List ID.\'); return false;">AWeber List IDs</a>. You will ALSO need to configure a <a href="http://www.s2member.com/kb/aweber-email-parser-for-s2member/" target="_blank" rel="external">Custom Email Parser</a> inside your AWeber account.</p>'."\n";
includes/menu-pages/gen-ops.inc.php CHANGED
@@ -211,7 +211,7 @@ if(!class_exists("c_ws_plugin__s2member_menu_page_gen_ops"))
211
  echo '<div class="ws-menu-page-right">'.c_ws_plugin__s2member_utilities::s_badge_gen("1", TRUE, TRUE).'</div>'."\n";
212
  echo '<p>An s2Member Security Badge <em>(optional)</em>, can be used to express your site\'s concern for security; demonstrating to all Users/Members that your site <em>(and the s2Member software)</em>, takes security seriously. However, in order to qualify your site, you MUST generate a Security Encryption Key <em>(previous section)</em>, and then click "Save All Changes". Only then, will s2Member officially verify your installation <em>(verification occurs automatically)</em>.</p>'."\n";
213
  echo '<p>Once you\'ve <a href="http://www.s2member.com/kb/security-badges/" target="_blank" rel="external">properly configured all security aspects of s2Member</a>, your s2Member Security Badge will be verified. To see the "verified" version of your Security Badge, you might need to refresh your browser after saving all changes <em>(i.e. after you create a Security Encryption Key)</em>. Also, s2Member will NOT "verify" your site if you turn off Unique IP Restrictions, Brute Force Login Protection, or if your <code>/wp-config.php</code> file lacks <a href="http://codex.wordpress.org/Editing_wp-config.php#Security_Keys" target="_blank" rel="external">Security Keys</a> <em>(each at least 60 chars in length)</em>. In addition, it\'s NOT possible for s2Member to verify your Security Badge, if your site is in a <code>localhost</code> environment; i.e. not connected to the web.</p>'."\n";
214
- echo '<p><strong>How does s2Member know when my site is secure?</strong><br />If enabled below, an API call for "Security Badge Status", will allow web service connections to determine your status. Clicking <a href="'.esc_attr(site_url("/?s2member_s_badge_status=1")).'" target="_blank" rel="external">this link</a> will report <code>1</code> <em>(secure)</em>, <code>0</code> <em>(at risk)</em>, or <code>-</code> <em>(API disabled)</em>. Once all security considerations are satisfied, s2Member will report <code>1</code> <em>(secure)</em> for your installation. *Note, this simple API will NOT, and should not, report any other information. It will ONLY report the current status of your Security Badge, as determined by your installation of s2Member. When/if you install the s2Member Security Badge, s2Member will make a connection to your site "once per day", to test your status.</p>'."\n";
215
  do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_during_s_badge_wp_footer_code", get_defined_vars());
216
 
217
  echo '<table class="form-table">'."\n";
@@ -249,7 +249,7 @@ if(!class_exists("c_ws_plugin__s2member_menu_page_gen_ops"))
249
  echo '<tr>'."\n";
250
 
251
  echo '<td>'."\n";
252
- echo '<textarea name="ws_plugin__s2member_wp_footer_code" id="ws-plugin--s2member-wp-footer-code" rows="8" wrap="off" spellcheck="false" class="monospace">'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["wp_footer_code"]).'</textarea><br />'."\n";
253
  echo 'Any valid XHTML / JavaScript'.((is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site()) ? '' : ' (or even PHP)').' code will work just fine here.'."\n";
254
  echo '</td>'."\n";
255
 
@@ -324,7 +324,7 @@ if(!class_exists("c_ws_plugin__s2member_menu_page_gen_ops"))
324
  echo '<td>'."\n";
325
  echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_reg_email_support_link" id="ws-plugin--s2member-reg-email-support-link" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_support_link"]).'" /><br />'."\n";
326
  echo 'Ex: <code>mailto:support@your-domain.com</code> (<em>mailto link</em>).<br />'."\n";
327
- echo 'Or: <code>'.esc_html(site_url("/contact-us/")).'</code>.'."\n";
328
  echo '</td>'."\n";
329
 
330
  echo '</tr>'."\n";
@@ -1271,7 +1271,7 @@ if(!class_exists("c_ws_plugin__s2member_menu_page_gen_ops"))
1271
 
1272
  echo '<td>'."\n";
1273
  echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_login_redirection_override" id="ws-plugin--s2member-login-redirection-override" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_redirection_override"]).'" /><br />'."\n";
1274
- echo 'Or, you may configure a Special Redirection URL, if you prefer. You\'ll need to type in the full URL, starting with: <code>http://</code>. <em>A few <a href="#" onclick="alert(\'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 you want to redirect Members to their BuddyPress Profile page after logging in, you would setup a Special Redirection URL, like this: '.site_url("/members/%%current_user_nicename%%/profile/").'\\n\\nOr ... using %%current_user_level%%, you could have a separate Login Welcome Page for each Membership Level that you plan to offer. BuddyPress not required.\'); return false;">Replacement Codes</a> are also supported here.</em>'."\n";
1275
  echo '</td>'."\n";
1276
 
1277
  echo '</tr>'."\n";
@@ -1396,7 +1396,7 @@ if(!class_exists("c_ws_plugin__s2member_menu_page_gen_ops"))
1396
  echo '<h3>Giving Members The Ability To Modify Their Profile</h3>'."\n";
1397
  echo '<p>s2Member can be configured to redirect Members away from the <a href="'.esc_attr(admin_url("/profile.php")).'" target="_blank" rel="external">default Profile Editing Panel</a> that is built into WordPress. When/if a Member attempts to access the default Profile Editing Panel, they\'ll instead, be redirected to the Login Welcome Page that you\'ve configured through s2Member. <strong>Why would I redirect?</strong> Unless you\'ve made some drastic modifications to your WordPress installation, the default Profile Editing Panel that ships with WordPress, is NOT really suited for public access, even by a Member.</p>'."\n";
1398
  echo '<p>So instead of using this default Profile Editing Panel; s2Member creates an added layer of functionality, on top of WordPress. It does this by providing you <em>(as the site owner)</em>, with a special Shortcode: <code>[s2Member-Profile /]</code> that you can place into your Login Welcome Page, or any Post/Page for that matter <em>(even into a Text Widget)</em>. This Shortcode produces an Inline Profile Editing Form that supports all aspects of s2Member, including Password changes; and any Custom Registration/Profile Fields that you\'ve configured with s2Member.</p>'."\n";
1399
- echo '<p>Alternatively, s2Member also gives you the ability to send your Members to a <a href="'.esc_attr(site_url("/?s2member_profile=1")).'" target="_blank" rel="external">special Stand-Alone version</a>. This Stand-Alone version has been designed <em>(with a bare-bones format)</em>, intentionally. This makes it possible for you to <a href="#" onclick="if(!window.open(\''.site_url("/?s2member_profile=1").'\', \'_popup\', \'width=600,height=400,left=100,screenX=100,top=100,screenY=100,location=0,menubar=0,toolbar=0,status=0,scrollbars=1,resizable=1\')) alert(\'Please disable popup blockers and try again!\'); return false;" rel="external">open it up in a popup window</a>, or embed it into your Login Welcome Page using an IFRAME. Code samples are provided below.</p>'."\n";
1400
  echo (c_ws_plugin__s2member_utils_conds::bp_is_installed()) ? '<p><em><strong>BuddyPress:</strong> BuddyPress already provides Users/Members with a Profile Editing Panel, powered by your theme. If you\'ve configured Custom Registration/Profile Fields with s2Member, you can also enable s2Member\'s Profile Field integration with BuddyPress (recommended). For further details, see: <code>s2Member -› General Options -› Registration/Profile Fields</code>.</em></p>'."\n" : '';
1401
  do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_during_profile_modifications", get_defined_vars());
1402
 
@@ -1428,10 +1428,10 @@ if(!class_exists("c_ws_plugin__s2member_menu_page_gen_ops"))
1428
  echo '<div class="ws-menu-page-hr"></div>'."\n";
1429
 
1430
  echo '<p><strong>Shortcode (copy/paste)</strong>, for an Inline Profile Modification Form:<br />'."\n";
1431
- echo '<p><input type="text" autocomplete="off" value="'.format_to_edit('[s2Member-Profile /]').'" class="monospace" onclick="this.select ();" /></p>'."\n";
1432
 
1433
  echo '<p style="margin-top:20px;"><strong>Stand-Alone (copy/paste)</strong>, for popup window:</p>'."\n";
1434
- echo '<p><input type="text" autocomplete="off" value="'.format_to_edit(preg_replace("/\<\?php echo S2MEMBER_CURRENT_USER_PROFILE_MODIFICATION_PAGE_URL; \?\>/", c_ws_plugin__s2member_utils_strings::esc_refs(site_url("/?s2member_profile=1")), file_get_contents(dirname(__FILE__)."/code-samples/current-user-profile-modification-page-url-2-ops.x-php"))).'" class="monospace" onclick="this.select ();" /></p>'."\n";
1435
  echo '</div>'."\n";
1436
 
1437
  echo '</div>'."\n";
211
  echo '<div class="ws-menu-page-right">'.c_ws_plugin__s2member_utilities::s_badge_gen("1", TRUE, TRUE).'</div>'."\n";
212
  echo '<p>An s2Member Security Badge <em>(optional)</em>, can be used to express your site\'s concern for security; demonstrating to all Users/Members that your site <em>(and the s2Member software)</em>, takes security seriously. However, in order to qualify your site, you MUST generate a Security Encryption Key <em>(previous section)</em>, and then click "Save All Changes". Only then, will s2Member officially verify your installation <em>(verification occurs automatically)</em>.</p>'."\n";
213
  echo '<p>Once you\'ve <a href="http://www.s2member.com/kb/security-badges/" target="_blank" rel="external">properly configured all security aspects of s2Member</a>, your s2Member Security Badge will be verified. To see the "verified" version of your Security Badge, you might need to refresh your browser after saving all changes <em>(i.e. after you create a Security Encryption Key)</em>. Also, s2Member will NOT "verify" your site if you turn off Unique IP Restrictions, Brute Force Login Protection, or if your <code>/wp-config.php</code> file lacks <a href="http://codex.wordpress.org/Editing_wp-config.php#Security_Keys" target="_blank" rel="external">Security Keys</a> <em>(each at least 60 chars in length)</em>. In addition, it\'s NOT possible for s2Member to verify your Security Badge, if your site is in a <code>localhost</code> environment; i.e. not connected to the web.</p>'."\n";
214
+ echo '<p><strong>How does s2Member know when my site is secure?</strong><br />If enabled below, an API call for "Security Badge Status", will allow web service connections to determine your status. Clicking <a href="'.esc_attr(home_url("/?s2member_s_badge_status=1")).'" target="_blank" rel="external">this link</a> will report <code>1</code> <em>(secure)</em>, <code>0</code> <em>(at risk)</em>, or <code>-</code> <em>(API disabled)</em>. Once all security considerations are satisfied, s2Member will report <code>1</code> <em>(secure)</em> for your installation. *Note, this simple API will NOT, and should not, report any other information. It will ONLY report the current status of your Security Badge, as determined by your installation of s2Member. When/if you install the s2Member Security Badge, s2Member will make a connection to your site "once per day", to test your status.</p>'."\n";
215
  do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_during_s_badge_wp_footer_code", get_defined_vars());
216
 
217
  echo '<table class="form-table">'."\n";
249
  echo '<tr>'."\n";
250
 
251
  echo '<td>'."\n";
252
+ echo '<textarea name="ws_plugin__s2member_wp_footer_code" id="ws-plugin--s2member-wp-footer-code" rows="8" wrap="off" spellcheck="false">'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["wp_footer_code"]).'</textarea><br />'."\n";
253
  echo 'Any valid XHTML / JavaScript'.((is_multisite() && c_ws_plugin__s2member_utils_conds::is_multisite_farm() && !is_main_site()) ? '' : ' (or even PHP)').' code will work just fine here.'."\n";
254
  echo '</td>'."\n";
255
 
324
  echo '<td>'."\n";
325
  echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_reg_email_support_link" id="ws-plugin--s2member-reg-email-support-link" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_support_link"]).'" /><br />'."\n";
326
  echo 'Ex: <code>mailto:support@your-domain.com</code> (<em>mailto link</em>).<br />'."\n";
327
+ echo 'Or: <code>'.esc_html(home_url("/contact-us/")).'</code>.'."\n";
328
  echo '</td>'."\n";
329
 
330
  echo '</tr>'."\n";
1271
 
1272
  echo '<td>'."\n";
1273
  echo '<input type="text" autocomplete="off" name="ws_plugin__s2member_login_redirection_override" id="ws-plugin--s2member-login-redirection-override" value="'.format_to_edit($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_redirection_override"]).'" /><br />'."\n";
1274
+ echo 'Or, you may configure a Special Redirection URL, if you prefer. You\'ll need to type in the full URL, starting with: <code>http://</code>. <em>A few <a href="#" onclick="alert(\'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 you want to redirect Members to their BuddyPress Profile page after logging in, you would setup a Special Redirection URL, like this: '.home_url("/members/%%current_user_nicename%%/profile/").'\\n\\nOr ... using %%current_user_level%%, you could have a separate Login Welcome Page for each Membership Level that you plan to offer. BuddyPress not required.\'); return false;">Replacement Codes</a> are also supported here.</em>'."\n";
1275
  echo '</td>'."\n";
1276
 
1277
  echo '</tr>'."\n";
1396
  echo '<h3>Giving Members The Ability To Modify Their Profile</h3>'."\n";
1397
  echo '<p>s2Member can be configured to redirect Members away from the <a href="'.esc_attr(admin_url("/profile.php")).'" target="_blank" rel="external">default Profile Editing Panel</a> that is built into WordPress. When/if a Member attempts to access the default Profile Editing Panel, they\'ll instead, be redirected to the Login Welcome Page that you\'ve configured through s2Member. <strong>Why would I redirect?</strong> Unless you\'ve made some drastic modifications to your WordPress installation, the default Profile Editing Panel that ships with WordPress, is NOT really suited for public access, even by a Member.</p>'."\n";
1398
  echo '<p>So instead of using this default Profile Editing Panel; s2Member creates an added layer of functionality, on top of WordPress. It does this by providing you <em>(as the site owner)</em>, with a special Shortcode: <code>[s2Member-Profile /]</code> that you can place into your Login Welcome Page, or any Post/Page for that matter <em>(even into a Text Widget)</em>. This Shortcode produces an Inline Profile Editing Form that supports all aspects of s2Member, including Password changes; and any Custom Registration/Profile Fields that you\'ve configured with s2Member.</p>'."\n";
1399
+ echo '<p>Alternatively, s2Member also gives you the ability to send your Members to a <a href="'.esc_attr(home_url("/?s2member_profile=1")).'" target="_blank" rel="external">special Stand-Alone version</a>. This Stand-Alone version has been designed <em>(with a bare-bones format)</em>, intentionally. This makes it possible for you to <a href="#" onclick="if(!window.open(\''.home_url("/?s2member_profile=1").'\', \'_popup\', \'width=600,height=400,left=100,screenX=100,top=100,screenY=100,location=0,menubar=0,toolbar=0,status=0,scrollbars=1,resizable=1\')) alert(\'Please disable popup blockers and try again!\'); return false;" rel="external">open it up in a popup window</a>, or embed it into your Login Welcome Page using an IFRAME. Code samples are provided below.</p>'."\n";
1400
  echo (c_ws_plugin__s2member_utils_conds::bp_is_installed()) ? '<p><em><strong>BuddyPress:</strong> BuddyPress already provides Users/Members with a Profile Editing Panel, powered by your theme. If you\'ve configured Custom Registration/Profile Fields with s2Member, you can also enable s2Member\'s Profile Field integration with BuddyPress (recommended). For further details, see: <code>s2Member -› General Options -› Registration/Profile Fields</code>.</em></p>'."\n" : '';
1401
  do_action("ws_plugin__s2member_during_gen_ops_page_during_left_sections_during_profile_modifications", get_defined_vars());
1402
 
1428
  echo '<div class="ws-menu-page-hr"></div>'."\n";
1429
 
1430
  echo '<p><strong>Shortcode (copy/paste)</strong>, for an Inline Profile Modification Form:<br />'."\n";
1431
+ echo '<p><input type="text" autocomplete="off" value="'.format_to_edit('[s2Member-Profile /]').'" onclick="this.select ();" /></p>'."\n";
1432
 
1433
  echo '<p style="margin-top:20px;"><strong>Stand-Alone (copy/paste)</strong>, for popup window:</p>'."\n";
1434
+ echo '<p><input type="text" autocomplete="off" value="'.format_to_edit(preg_replace("/\<\?php echo S2MEMBER_CURRENT_USER_PROFILE_MODIFICATION_PAGE_URL; \?\>/", c_ws_plugin__s2member_utils_strings::esc_refs(home_url("/?s2member_profile=1")), file_get_contents(dirname(__FILE__)."/code-samples/current-user-profile-modification-page-url-2-ops.x-php"))).'" onclick="this.select ();" /></p>'."\n";
1435
  echo '</div>'."\n";
1436
 
1437
  echo '</div>'."\n";
includes/menu-pages/logs.inc.php CHANGED
@@ -1,351 +1,348 @@
1
  <?php
2
  /**
3
- * Menu page for the s2Member plugin (Logs page).
4
- *
5
- * Copyright: © 2009-2011
6
- * {@link http://www.websharks-inc.com/ WebSharks, Inc.}
7
- * (coded in the USA)
8
- *
9
- * Released under the terms of the GNU General Public License.
10
- * You should have received a copy of the GNU General Public License,
11
- * along with this software. In the main directory, see: /licensing/
12
- * If not, see: {@link http://www.gnu.org/licenses/}.
13
- *
14
- * @package s2Member\Menu_Pages
15
- * @since 130210
16
- */
17
  if(realpath(__FILE__) === realpath($_SERVER["SCRIPT_FILENAME"]))
18
  exit("Do not access this file directly.");
19
 
20
  if(!class_exists("c_ws_plugin__s2member_menu_page_logs"))
 
 
 
 
 
 
 
 
21
  {
22
- /**
23
- * Menu page for the s2Member plugin (Integrations page).
24
- *
25
- * @package s2Member\Menu_Pages
26
- * @since 110531
27
- */
28
- class c_ws_plugin__s2member_menu_page_logs
29
- {
30
- public function __construct()
31
- {
32
- echo '<div class="wrap ws-menu-page">'."\n";
33
 
34
- echo '<div class="ws-menu-page-toolbox">'."\n";
35
- c_ws_plugin__s2member_menu_pages_tb::display ();
36
- echo '</div>'."\n";
37
 
38
- echo '<h2>Log Files</h2>'."\n";
39
 
40
- echo '<table class="ws-menu-page-table">'."\n";
41
- echo '<tbody class="ws-menu-page-table-tbody">'."\n";
42
- echo '<tr class="ws-menu-page-table-tr">'."\n";
43
- echo '<td class="ws-menu-page-table-l">'."\n";
44
 
45
- do_action("ws_plugin__s2member_during_logs_page_before_left_sections", get_defined_vars());
46
 
47
- if (apply_filters("ws_plugin__s2member_during_logs_page_during_left_sections_display_help", true, get_defined_vars ()))
48
- {
49
- do_action("ws_plugin__s2member_during_logs_page_during_left_sections_before_help", get_defined_vars ());
50
 
51
- echo '<div class="ws-menu-page-group" title="Getting Help">' . "\n";
52
 
53
- echo '<div class="ws-menu-page-section ws-plugin--s2member-help">' . "\n";
54
- echo '<h3>Getting Help w/ s2Member (Troubleshooting)</h3>' . "\n";
55
- echo '<p>s2Member is pretty easy to setup and install initially. Most of the official documentation is right here in your Dashboard (i.e. there is a lot of inline documentation built into the software). That being said, it CAN take some time to master everything there is to know about s2Member\'s advanced features. If you need assistance with s2Member, please search the <a href="http://www.s2member.com/kb/" target="_blank" rel="external">s2Member Knowledge Base</a>, <a href="http://www.s2member.com/videos/" target="_blank" rel="external">Video Tutorials</a>, <a href="http://www.s2member.com/forums/" target="_blank" rel="external">Forums</a> and <a href="http://www.s2member.com/codex/" target="_blank" rel="external">Codex</a>. If you are planning to do something creative with s2Member, you might want to <a href="http://jobs.wordpress.net" target="_blank" rel="external">hire a freelance developer</a> to assist you.</p>' . "\n";
56
- echo '<p><strong>See also:</strong> <a href="http://www.s2member.com/kb/common-troubleshooting-tips/" target="_blank" rel="external">s2Member Troubleshooting Guide</a> (please read this first if you\'re having trouble).</p>'."\n";
57
 
58
- echo '<div class="ws-menu-page-hr"></div>' . "\n";
59
 
60
- echo '<h3>Testing Server Compatibility</h3>'."\n";
61
- echo '<p>Please download the <a href="http://www.s2member.com/r/server-check-tool/">s2Member Server Scanner</a>. Unzip, upload via FTP; then open in a browser for a full report.</p>'."\n";
62
 
63
- echo '<div class="ws-menu-page-hr"></div>' . "\n";
64
 
65
- echo '<h3>Troubleshooting Payment Gateway Integrations</h3>'."\n";
66
- echo '<p>Please use the s2Member Log Viewer (below). Log files can be very helpful.</p>'."\n";
67
 
68
- echo '<div class="ws-menu-page-hr"></div>' . "\n";
69
 
70
- echo '<h3>Search s2Member KB Articles, Forums, Codex and more<em>!</em></h3>'."\n";
71
- echo '<form method="get" action="http://www.s2member.com/quick-s.php" target="_blank" onsubmit="if(this.q.value === \'enter search terms...\') this.q.value = \'\';">'."\n";
72
- echo '<p><input type="text" name="q" value="enter search terms..." style="width:60%;" onfocus="if(this.value === \'enter search terms...\') this.value = \'\';" onblur="if(this.value === \'\') this.value = \'enter search terms...\';" /> <input type="submit" value="Search" style="font-size:120%; font-weight:normal;" /></p>'."\n";
73
- echo '</form>'."\n";
74
 
75
- do_action("ws_plugin__s2member_during_logs_page_during_left_sections_during_help", get_defined_vars ());
76
- echo '</div>' . "\n";
77
- echo '</div>' . "\n";
78
 
79
- do_action("ws_plugin__s2member_during_logs_page_during_left_sections_after_help", get_defined_vars ());
80
- }
 
 
 
81
 
82
- if(apply_filters("ws_plugin__s2member_during_logs_page_during_left_sections_display_log_settings", true, get_defined_vars()))
83
- {
84
- do_action("ws_plugin__s2member_during_logs_page_during_left_sections_before_log_settings", get_defined_vars());
85
 
86
- echo '<div class="ws-menu-page-group" title="Logging Configuration">'."\n";
87
- echo '<div class="ws-menu-page-section ws-plugin--s2member-log-settings-section">'."\n";
88
 
89
- echo '<h3>Logging Configuration</h3>'."\n";
 
 
 
90
 
91
- echo '<div class="info">'."\n";
92
- echo '<p style="font-size:110%; margin-top:0;"><span>We HIGHLY recommend that you enable logging during your initial testing phase. Logs produce lots of useful details that can help in debugging. Logs can help you find issues in your configuration and/or problems that occur during processing. Enable logging here, and then view your log files below; in the s2Member Log Viewer.</span></p>'."\n";
93
- echo '<p style="font-size:110%; margin-bottom:0;"><span class="ws-menu-page-error">However, it is VERY IMPORTANT to disable logging once you go live. Log files may contain personally identifiable information, credit card numbers, secret API credentials, passwords and/or other sensitive information. We STRONGLY suggest that logging be disabled on a live site (for security reasons).</span></p>'."\n";
94
- echo '</div>'."\n";
95
 
96
- echo '<div class="notice" style="margin-bottom:0;">'."\n";
97
- echo '<p style="font-size:110%; margin-bottom:0;"><span>Regarding s2Member Security Badges. If debug logging is enabled, your site will NOT qualify for an s2Member Security Badge until you disable logging (and you must ALSO download, and then delete any existing log files). For further details, please see KB Article: <a href="http://www.s2member.com/kb/security-badges/" target="_blank" rel="external">s2Member Security Badges</a>.</span></p>'."\n";
98
- echo '</div>'."\n";
99
 
100
- echo '<div class="ws-menu-page-hr"></div>'."\n";
101
 
102
- do_action("ws_plugin__s2member_during_logs_page_during_left_sections_during_log_settings", get_defined_vars());
 
103
 
104
- echo '<form method="post" name="ws_plugin__s2member_options_form" id="ws-plugin--s2member-options-form">' . "\n";
105
- 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";
 
106
 
107
- echo '<table class="form-table">' . "\n";
108
- echo '<tbody>' . "\n";
109
- echo '<tr>' . "\n";
 
 
110
 
111
- echo '<th>'."\n";
112
- echo '<label for="ws-plugin--s2member-gateway-debug-logs">'."\n";
113
- echo 'Enable Logging Routines?'."\n";
114
- echo '</label>'."\n";
115
- echo '</th>'."\n";
116
 
117
- echo '</tr>'."\n";
118
- echo '<tr>'."\n";
 
 
 
119
 
120
- echo '<td>'."\n";
121
- echo '<input type="radio" name="ws_plugin__s2member_gateway_debug_logs" id="ws-plugin--s2member-gateway-debug-logs-0" value="0"'.((!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["gateway_debug_logs"]) ? ' checked="checked"' : '').' /> <label for="ws-plugin--s2member-gateway-debug-logs-0">No</label> &nbsp;&nbsp;&nbsp; <input type="radio" name="ws_plugin__s2member_gateway_debug_logs" id="ws-plugin--s2member-gateway-debug-logs-1" value="1"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["gateway_debug_logs"]) ? ' checked="checked"' : '').' /> <label for="ws-plugin--s2member-gateway-debug-logs-1">Yes, enable debugging w/ HTTP, API, IPN &amp; Return Page logging (and List Server API logs too).</label><br />'."\n";
122
- echo '<em>This enables logging overall. Includes s2Member HTTP, API, IPN and Return Page logging. Also logs any List Server integrations.</em><br />'."\n";
123
- echo '<em>* Use only for debugging. This should NEVER be enabled on a live site.<br />* The log files are stored here: <code>'.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"])).'</code></em>'."\n";
124
- echo '</td>'."\n";
125
 
126
- echo '</tr>'."\n";
127
- echo '<tr>' . "\n";
 
 
 
128
 
129
- echo '<th>'."\n";
130
- echo '<label for="ws-plugin--s2member-gateway-debug-logs-extensive">'."\n";
131
- echo 'Enable Additional Logging Routines?'."\n";
132
- echo '</label>'."\n";
133
- echo '</th>'."\n";
134
 
135
- echo '</tr>'."\n";
136
- echo '<tr>'."\n";
 
 
137
 
138
- echo '<td>'."\n";
139
- echo '<input type="radio" name="ws_plugin__s2member_gateway_debug_logs_extensive" id="ws-plugin--s2member-gateway-debug-logs-extensive-0" value="0"'.((!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["gateway_debug_logs_extensive"]) ? ' checked="checked"' : '').' /> <label for="ws-plugin--s2member-gateway-debug-logs-extensive-0">No</label> &nbsp;&nbsp;&nbsp; <input type="radio" name="ws_plugin__s2member_gateway_debug_logs_extensive" id="ws-plugin--s2member-gateway-debug-logs-extensive-1" value="1"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["gateway_debug_logs_extensive"]) ? ' checked="checked"' : '').' /> <label for="ws-plugin--s2member-gateway-debug-logs-extensive-1">Yes, enable debugging w/ HTTP connection logging for ALL of WordPress.</label><br />'."\n";
140
- echo '<em>This enables HTTP connection logging for ALL of WordPress (quite extensive).<br />* Use only for debugging. This should NEVER be enabled on a live site.<br />* Creates the additional log file: <code>wp-http-api-debug.log</code></em>'."\n";
141
- echo '</td>'."\n";
142
 
143
- echo '</tr>'."\n";
144
- echo '</tbody>' . "\n";
145
- echo '</table>' . "\n";
146
 
147
- echo '<p class="submit" style="margin-top:20px;">'."\n";
148
- echo '<input type="submit" value="Update Logging Configuration" />'."\n";
149
- echo '</p>' . "\n";
150
 
151
- echo '</form>'."\n";
 
152
 
153
- echo '</div>'."\n";
154
- echo '</div>'."\n";
 
 
 
155
 
156
- do_action("ws_plugin__s2member_during_logs_page_during_left_sections_after_log_settings", get_defined_vars());
157
- }
158
 
159
- if(apply_filters("ws_plugin__s2member_during_logs_page_during_left_sections_display_logs", true, get_defined_vars()))
160
- {
161
- do_action("ws_plugin__s2member_during_logs_page_during_left_sections_before_logs", get_defined_vars());
162
 
163
- echo '<div class="ws-menu-page-group" title="Logs Viewer" default-state="open">'."\n";
164
 
165
- echo '<div class="ws-menu-page-section ws-plugin--s2member-logs-section">'."\n";
166
- echo '<h3>Debugging Tools/Tips &amp; Other Important Details (<a href="#" onclick="jQuery(\'div#ws-plugin--s2member-debugging-tips-details\').toggle(); return false;" class="ws-dotted-link">click here to toggle</a>)</h3>'."\n";
167
 
168
- echo '<div id="ws-plugin--s2member-debugging-tips-details" style="display:none;">'."\n";
 
 
 
169
 
170
- echo '<div class="ws-menu-page-hr"></div>' . "\n";
 
 
 
171
 
172
- echo '<form method="post" onsubmit="if(!confirm(\'Archive all existing log files?\n\nAll of your current log files will be archived (e.g. they will simply be renamed with an ARCHIVED tag &amp; date in their file name); and new log files will be created automatically the next time s2Member logs something on your installation.\n\nPlease click OK to confirm this action.\')) return false;">'."\n";
173
- echo '<input type="hidden" name="ws_plugin__s2member_logs_archive_start_fresh" value="'.esc_attr(wp_create_nonce ("ws-plugin--s2member-logs-archive-start-fresh")).'" />'."\n";
174
- echo '<input type="submit" value="Archive All Current Log Files" class="ws-menu-page-right ws-plugin--s2member-archive-logs-start-fresh-button" style="font-size:110%; font-weight:normal; clear:right; min-width:200px;" />'."\n";
175
- echo '</form>'."\n";
176
 
177
- echo '<form method="post" onsubmit="if(!confirm(\'Delete all existing log files?\n\nThis will permanently delete ALL of your existing log files (including any archived log files).\n\nPlease click OK to confirm this action.\')) return false;">'."\n";
178
- echo '<input type="hidden" name="ws_plugin__s2member_logs_delete_start_fresh" value="'.esc_attr(wp_create_nonce ("ws-plugin--s2member-logs-delete-start-fresh")).'" />'."\n";
179
- echo '<input type="submit" value="Permanently Delete All Log Files" class="ws-menu-page-right ws-plugin--s2member-delete-logs-start-fresh-button" style="font-size:110%; font-weight:normal; clear:right; min-width:200px;" />'."\n";
180
- echo '</form>'."\n";
 
181
 
182
- echo '<form method="post">'."\n";
183
- echo '<input type="hidden" name="ws_plugin__s2member_logs_download_zip" value="'.esc_attr(wp_create_nonce ("ws-plugin--s2member-logs-download-zip")).'" />'."\n";
184
- echo '<input type="submit" value="Download All Log Files (Zip File)" class="ws-menu-page-right ws-plugin--s2member-logs-download-zip-button" style="font-size:110%; font-weight:normal; clear:right; min-width:200px;" />'."\n";
185
- echo '</form>'."\n";
186
 
187
- echo '<p><strong>Debugging Tips:</strong> &nbsp;&nbsp; It is normal to see a few errors in your log files. This is because s2Member logs ALL of its communication with Payment Gateways. Everything — not just successes. With that in mind, there will be some failures that s2Member expects (to a certain extent); and s2Member deals with these gracefully. What you\'re looking for here, are things that jump right out at you as being a major issue (e.g. when s2Member makes a point of providing details to you in a log entry about problems that should be corrected on your installation). Please read carefully.</p>'."\n";
188
- echo '<p><strong>Test Transaction Tips:</strong> &nbsp;&nbsp; Generally speaking, it is best to run test transactions for yourself. Be sure to run your final test transactions against a live Payment Gateway that is NOT in Sandbox/Test Mode (<a href="#" onclick="alert(\'While some Payment Gateways make it possible for you to run test transactions in Sandbox/Test Mode, these are NOT a reliable way to test s2Member.\n\nOften times (particularly with PayPal) Sandbox/Test mode behaves somewhat differently — often with buggy behavior. This can really create frustration for site owners. Therefore, it is always a good idea to run low dollar test transactions against a live Payment Gateway.\n\nAlso, please be sure that you are NOT logged in as an Administrator when running test transactions. For most test transactions, you will want to be completely logged out of your site before completing checkout (just a new Customer would be). If you are testing an upgrade or downgrade (where you DO need to be logged-in), please do NOT attempt this under an Administrative account. s2Member will NOT upgrade/downgrade Administrative accounts — for security purposes.\'); return false;">click here for details</a>). After running test transactions, please review the log file entries pertaining to your transaction. Does s2Member report any major issues? If so, please read through any details that s2Member provides in the log file. If you need assistance, please <a href="http://www.s2member.com/quick-s.php" target="_blank" rel="external">search s2Member.com</a> for answers to common questions.</p>'."\n";
189
- echo '<p><strong>s2 Core Processors:</strong> &nbsp;&nbsp; It is normal to have a <code>paypay-ipn.log</code> and/or a <code>paypay-rtn.log</code> file at all times. Ultimately, all Payment Gateway integrations supported by s2Member pass through it\'s core PayPal processors; even if you\'ve integrated with another Payment Gateway. If you are having trouble, and you don\'t find any errors in your Payment Gateway log files, please check the <code>paypay-ipn.log</code> and <code>paypay-rtn.log</code> files too. Regarding s2Member Pro Forms... If you\'ve integrated s2Member Pro Forms, you will NOT have a <code>paypay-rtn.log</code> file, because that particular processor is not used with Pro Form integrations. However, you will have a <code>paypay-ipn.log</code> file, and you will need to make a point of inspecting this file to ensure there were no post-processing issues.</p>'."\n";
190
- echo '<p><strong>s2 HTTP API Logs:</strong> &nbsp;&nbsp; If s2Member is not behaving as expected, and you cannot find errors anywhere in your Payment Gateway log files (or with any core PayPal processors), please review your <code>s2-http-api-debug.log</code> file too. Look for any HTTP connections where s2Member is getting <code>403</code>, <code>404</code>, <code>503</code> errors from your server. This can sometimes happen due to <a href="http://www.s2member.com/kb/mod-security-random-503-403-errors/" target="_blank" rel="external">paranoid Mod Security configurations</a>, and it may require you to contact your hosting company for assistance.</p>'."\n";
191
- echo '<p style="font-style:italic;"><strong>Archived Log Files:</strong> &nbsp;&nbsp; All s2Member log files are stored here: <code>'.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"])).'</code>. Any log files that contain the word <code>ARCHIVED</code> in their name, are files that reached a size of more than 2MB, so s2Member archived them automatically to prevent any single log file from becoming too large. Archived log file names will also contain the date/time they were archived by s2Member. These archived log files typically contain much older (and possibly outdated) log entries.</p>'."\n";
192
 
193
- echo '<div class="ws-menu-page-hr"></div>' . "\n";
194
 
195
- echo '<h3>s2Member Log File Descriptions (for ALL possible log file names)</h3>'."\n";
 
 
 
 
196
 
197
- echo '<div class="ws-menu-page-hr"></div>' . "\n";
198
 
199
- echo '<ul class="ws-menu-page-li-margins">'."\n";
200
- foreach(c_ws_plugin__s2member_utils_logs::$log_file_descriptions as $_k => $_v)
201
- echo '<li style="font-family:\'Georgia\', serif;"><code><strong>'.esc_html(preg_replace('/^\/|\/$/', '', $_k)).'.log</strong></code> &nbsp;&nbsp; '.esc_html($_v["long"]).'</li>'."\n";
202
- unset($_k, $_v); // Housekeeping.
203
- echo '</ul>'."\n";
204
 
205
- echo '<div class="ws-menu-page-hr"></div>' . "\n";
206
 
207
- echo '</div>'."\n";
 
 
208
 
209
- do_action("ws_plugin__s2member_during_logs_page_during_left_sections_during_logs", get_defined_vars());
 
 
 
210
 
211
- $log_file_options = ""; // Initialize to an empty string.
212
- $view_log_file = (!empty($_POST["ws_plugin__s2member_log_file"])) ? esc_html($_POST["ws_plugin__s2member_log_file"]) : "";
213
- $logs_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"];
 
214
 
215
- if(is_dir($logs_dir)) // Do we have a logs directory on this installation?
 
216
  {
217
- $log_files = scandir($logs_dir); sort($log_files, SORT_STRING);
218
-
219
- $log_file_options .= '<optgroup label="Current Log Files">';
220
- foreach($log_files as $_log_file) // Build options for each current log file.
221
- {
222
- $_log_file_description = array("short" => "No description available.", "long" => "No description available.");
223
-
224
- foreach(c_ws_plugin__s2member_utils_logs::$log_file_descriptions as $_k => $_v)
225
- if(preg_match($_k, $_log_file))
226
- {
227
- $_log_file_description = $_v;
228
- break; // Stop here.
229
- }
230
- unset($_k, $_v); // Housekeeping.
231
-
232
- if(preg_match("/\.log$/", $_log_file) && stripos($_log_file, "-ARCHIVED-") === FALSE)
233
- $log_file_options .= '<option data-type="current" title="'.esc_attr($_log_file_description["long"]).'" value="'.esc_attr($_log_file).'"'.(($view_log_file === $_log_file) ? ' style="font-weight:bold;" selected="selected"' : '').'>'.esc_html($_log_file).' — '.esc_html($_log_file_description["short"]).'</option>';
234
- }
235
- unset($_log_file_description, $_log_file); // Housekeeping.
236
- $log_file_options .= '</optgroup>';
237
-
238
- if(stripos($log_file_options, '<option data-type="current"') === FALSE)
239
- $log_file_options .= '<option value="" disabled="disabled">— No current log files yet. —</option>';
240
-
241
- $log_file_options .= '<option value="" disabled="disabled"></option>';
242
-
243
- $log_file_options .= '<optgroup label="Archived Log Files">';
244
- foreach($log_files as $_log_file) // Build options for each ARCHIVED log file.
245
- {
246
- if(preg_match("/\.log$/", $_log_file) && stripos($_log_file, "-ARCHIVED-") !== FALSE)
247
- $log_file_options .= '<option data-type="archived" value="'.esc_attr($_log_file).'"'.(($view_log_file === $_log_file) ? ' style="font-weight:bold;" selected="selected"' : '').'>'.esc_html($_log_file).'</option>';
248
- }
249
- $log_file_options .= '</optgroup>';
250
-
251
- if(stripos($log_file_options, '<option data-type="archived"') === FALSE)
252
- $log_file_options .= '<option value="" disabled="disabled">— No log files archived yet. —</option>';
253
  }
254
- $log_file_options = '<option value="">— Choose a Log File to View —</option>'.
255
- '<option value="" disabled="disabled"></option>'.
256
- $log_file_options;
257
 
258
- echo '<form method="post" name="ws_plugin__s2member_log_viewer" id="ws-plugin--s2member-log-viewer">' . "\n";
 
 
 
 
259
 
260
- echo '<table class="form-table">' . "\n";
261
- echo '<tbody>' . "\n";
262
- echo '<tr>' . "\n";
263
 
264
- echo '<td style="width:80%;">' . "\n";
265
- echo '<select name="ws_plugin__s2member_log_file" id="ws-plugin--s2member-log-file">' . "\n";
266
- echo $log_file_options."\n";
267
- echo '</select>' . "\n";
268
- echo '</td>' . "\n";
269
 
270
- echo '<td style="width:20%; padding-left:5px;">' . "\n";
271
- echo '<input type="submit" value="View" style="font-size:120%; font-weight:normal;" />'."\n";
272
- echo '</td>' . "\n";
 
 
 
 
273
 
274
- echo '</tr>' . "\n";
275
- echo '</tbody>' . "\n";
276
- echo '</table>' . "\n";
 
 
 
277
 
278
- echo '<table class="form-table">' . "\n";
279
- echo '<tbody>' . "\n";
280
- echo '<tr>' . "\n";
281
 
282
- echo '<td>' . "\n";
 
 
283
 
284
- if($view_log_file && file_exists($logs_dir."/".$view_log_file) && filesize($logs_dir."/".$view_log_file))
285
- {
286
- $_log_file_description = array("short" => "", "long" => "");
 
 
287
 
288
- foreach(c_ws_plugin__s2member_utils_logs::$log_file_descriptions as $_k => $_v)
289
- if(preg_match($_k, $view_log_file))
290
- {
291
- $_log_file_description = $_v;
292
- break; // Stop here.
293
- }
294
- unset($_k, $_v); // Housekeeping.
295
 
296
- if(!empty($_log_file_description["long"])) // Do we have a description that we can display here?
297
- echo '<p style="clear:both; width:80%; font-family:\'Georgia\', serif; font-style:italic;"><strong>Description for <a href="'.esc_attr(add_query_arg(array("ws_plugin__s2member_download_log_file" => $view_log_file, "ws_plugin__s2member_download_log_file_v" => wp_create_nonce ("ws-plugin--s2member-download-log-file-v")))).'">'.esc_html($view_log_file).'</a></strong>: '.esc_html($_log_file_description["long"]).'</p>'."\n";
298
- unset($_log_file_description); // Just a little housekeeping here.
299
 
300
- echo '<p style="float:left; text-align:left;"><strong>Viewing:</strong> <a href="'.esc_attr(add_query_arg(array("ws_plugin__s2member_download_log_file" => $view_log_file, "ws_plugin__s2member_download_log_file_v" => wp_create_nonce ("ws-plugin--s2member-download-log-file-v")))).'">'.esc_html($view_log_file).'</a> (log entries oldest to newest)</p>'."\n";
301
- echo '<p style="float:right; text-align:right;">[ <a href="'.esc_attr(add_query_arg(array("ws_plugin__s2member_download_log_file" => $view_log_file, "ws_plugin__s2member_download_log_file_v" => wp_create_nonce ("ws-plugin--s2member-download-log-file-v")))).'"><strong>download file</strong></a> ]</p>'."\n";
302
- echo '<p style="margin-right:10px; float:right; text-align:right;"><a href="#" class="ws-plugin--s2member-log-file-viewport-toggle" style="text-decoration:none;">&#8659; expand viewport &#8659;</a></p>'."\n";
303
 
304
- echo '<textarea id="ws-plugin--s2member-log-file-viewer" rows="20" wrap="on" spellcheck="false" style="box-shadow:inset 0 0 5px rgba(0,0,0,0.5); background:#EEEEEE; color:#000000; overflow-y:scroll;" class="monospace">'.htmlspecialchars(file_get_contents($logs_dir."/".$view_log_file)).'</textarea>' . "\n";
305
 
306
- echo '<p style="float:left; text-align:left;"><strong>Viewing:</strong> <a href="'.esc_attr(add_query_arg(array("ws_plugin__s2member_download_log_file" => $view_log_file, "ws_plugin__s2member_download_log_file_v" => wp_create_nonce ("ws-plugin--s2member-download-log-file-v")))).'">'.esc_html($view_log_file).'</a> (log entries oldest to newest)</p>'."\n";
307
- echo '<p style="float:right; text-align:right;">[ <a href="'.esc_attr(add_query_arg(array("ws_plugin__s2member_download_log_file" => $view_log_file, "ws_plugin__s2member_download_log_file_v" => wp_create_nonce ("ws-plugin--s2member-download-log-file-v")))).'"><strong>download file</strong></a> ]</p>'."\n";
308
- echo '<p style="margin-right:10px; float:right; text-align:right;"><a href="#" class="ws-plugin--s2member-log-file-viewport-toggle" style="text-decoration:none;">&#8659; expand viewport &#8659;</a></p>'."\n";
309
- }
310
- else if($view_log_file && file_exists($logs_dir."/".$view_log_file))
311
- echo '<textarea id="ws-plugin--s2member-log-file-viewer" rows="20" wrap="on" spellcheck="false" style="box-shadow:inset 0 0 5px rgba(0,0,0,0.5); background:#EEEEEE; color:#000000; overflow-y:scroll; font-style:italic;" class="monospace">— Empty at this time —</textarea>' . "\n";
312
 
313
- else if($view_log_file && !file_exists($logs_dir."/".$view_log_file))
314
- echo '<textarea id="ws-plugin--s2member-log-file-viewer" rows="20" wrap="on" spellcheck="false" style="box-shadow:inset 0 0 5px rgba(0,0,0,0.5); background:#EEEEEE; color:#000000; overflow-y:scroll; font-style:italic;" class="monospace">— File no longer exists —</textarea>' . "\n";
 
 
 
 
 
315
 
316
- else // Display an empty textarea in this default scenario.
317
- echo '<textarea id="ws-plugin--s2member-log-file-viewer" rows="20" wrap="on" spellcheck="false" style="box-shadow:inset 0 0 5px rgba(0,0,0,0.5); background:#EEEEEE; color:#000000; overflow-y:scroll; font-style:italic;" class="monospace"></textarea>' . "\n";
 
318
 
319
- echo '</td>' . "\n";
 
 
320
 
321
- echo '</tr>' . "\n";
322
- echo '</tbody>' . "\n";
323
- echo '</table>' . "\n";
324
 
325
- echo '</form>'."\n";
 
 
 
 
 
326
 
327
- echo '</div>'."\n";
328
- echo '</div>'."\n";
329
 
330
- do_action("ws_plugin__s2member_during_logs_page_during_left_sections_after_logs", get_defined_vars());
331
- }
332
 
333
- do_action("ws_plugin__s2member_during_logs_page_after_left_sections", get_defined_vars());
334
 
335
- echo '</td>'."\n";
 
 
336
 
337
- echo '<td class="ws-menu-page-table-r">'."\n";
338
- c_ws_plugin__s2member_menu_pages_rs::display();
339
- echo '</td>'."\n";
340
 
341
- echo '</tr>'."\n";
342
- echo '</tbody>'."\n";
343
- echo '</table>'."\n";
344
 
345
- echo '</div>'."\n";
346
- }
347
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
348
  }
 
349
 
350
- new c_ws_plugin__s2member_menu_page_logs();
351
- ?>
1
  <?php
2
  /**
3
+ * Menu page for the s2Member plugin (Logs page).
4
+ *
5
+ * Copyright: © 2009-2011
6
+ * {@link http://www.websharks-inc.com/ WebSharks, Inc.}
7
+ * (coded in the USA)
8
+ *
9
+ * Released under the terms of the GNU General Public License.
10
+ * You should have received a copy of the GNU General Public License,
11
+ * along with this software. In the main directory, see: /licensing/
12
+ * If not, see: {@link http://www.gnu.org/licenses/}.
13
+ *
14
+ * @package s2Member\Menu_Pages
15
+ * @since 130210
16
+ */
17
  if(realpath(__FILE__) === realpath($_SERVER["SCRIPT_FILENAME"]))
18
  exit("Do not access this file directly.");
19
 
20
  if(!class_exists("c_ws_plugin__s2member_menu_page_logs"))
21
+ {
22
+ /**
23
+ * Menu page for the s2Member plugin (Integrations page).
24
+ *
25
+ * @package s2Member\Menu_Pages
26
+ * @since 110531
27
+ */
28
+ class c_ws_plugin__s2member_menu_page_logs
29
  {
30
+ public function __construct()
31
+ {
32
+ echo '<div class="wrap ws-menu-page">'."\n";
 
 
 
 
 
 
 
 
33
 
34
+ echo '<div class="ws-menu-page-toolbox">'."\n";
35
+ c_ws_plugin__s2member_menu_pages_tb::display();
36
+ echo '</div>'."\n";
37
 
38
+ echo '<h2>Log Files</h2>'."\n";
39
 
40
+ echo '<table class="ws-menu-page-table">'."\n";
41
+ echo '<tbody class="ws-menu-page-table-tbody">'."\n";
42
+ echo '<tr class="ws-menu-page-table-tr">'."\n";
43
+ echo '<td class="ws-menu-page-table-l">'."\n";
44
 
45
+ do_action("ws_plugin__s2member_during_logs_page_before_left_sections", get_defined_vars());
46
 
47
+ if(apply_filters("ws_plugin__s2member_during_logs_page_during_left_sections_display_help", TRUE, get_defined_vars()))
48
+ {
49
+ do_action("ws_plugin__s2member_during_logs_page_during_left_sections_before_help", get_defined_vars());
50
 
51
+ echo '<div class="ws-menu-page-group" title="Getting Help">'."\n";
52
 
53
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-help">'."\n";
54
+ echo '<h3>Getting Help w/ s2Member (Troubleshooting)</h3>'."\n";
55
+ echo '<p>s2Member is pretty easy to setup and install initially. Most of the official documentation is right here in your Dashboard (i.e. there is a lot of inline documentation built into the software). That being said, it CAN take some time to master everything there is to know about s2Member\'s advanced features. If you need assistance with s2Member, please search the <a href="http://www.s2member.com/kb/" target="_blank" rel="external">s2Member Knowledge Base</a>, <a href="http://www.s2member.com/videos/" target="_blank" rel="external">Video Tutorials</a>, <a href="http://www.s2member.com/forums/" target="_blank" rel="external">Forums</a> and <a href="http://www.s2member.com/codex/" target="_blank" rel="external">Codex</a>. If you are planning to do something creative with s2Member, you might want to <a href="http://jobs.wordpress.net" target="_blank" rel="external">hire a freelance developer</a> to assist you.</p>'."\n";
56
+ echo '<p><strong>See also:</strong> <a href="http://www.s2member.com/kb/common-troubleshooting-tips/" target="_blank" rel="external">s2Member Troubleshooting Guide</a> (please read this first if you\'re having trouble).</p>'."\n";
57
 
58
+ echo '<div class="ws-menu-page-hr"></div>'."\n";
59
 
60
+ echo '<h3>Testing Server Compatibility</h3>'."\n";
61
+ echo '<p>Please download the <a href="http://www.s2member.com/r/server-check-tool/">s2Member Server Scanner</a>. Unzip, upload via FTP; then open in a browser for a full report.</p>'."\n";
62
 
63
+ echo '<div class="ws-menu-page-hr"></div>'."\n";
64
 
65
+ echo '<h3>Troubleshooting Payment Gateway Integrations</h3>'."\n";
66
+ echo '<p>Please use the s2Member Log Viewer (below). Log files can be very helpful.</p>'."\n";
67
 
68
+ echo '<div class="ws-menu-page-hr"></div>'."\n";
69
 
70
+ echo '<h3>Search s2Member KB Articles, Forums, Codex and more<em>!</em></h3>'."\n";
71
+ echo '<form method="get" action="http://www.s2member.com/quick-s.php" target="_blank" onsubmit="if(this.q.value === \'enter search terms...\') this.q.value = \'\';">'."\n";
72
+ echo '<p><input type="text" name="q" value="enter search terms..." style="width:60%;" onfocus="if(this.value === \'enter search terms...\') this.value = \'\';" onblur="if(this.value === \'\') this.value = \'enter search terms...\';" /> <input type="submit" value="Search" style="font-size:120%; font-weight:normal;" /></p>'."\n";
73
+ echo '</form>'."\n";
74
 
75
+ do_action("ws_plugin__s2member_during_logs_page_during_left_sections_during_help", get_defined_vars());
76
+ echo '</div>'."\n";
77
+ echo '</div>'."\n";
78
 
79
+ do_action("ws_plugin__s2member_during_logs_page_during_left_sections_after_help", get_defined_vars());
80
+ }
81
+ if(apply_filters("ws_plugin__s2member_during_logs_page_during_left_sections_display_log_settings", TRUE, get_defined_vars()))
82
+ {
83
+ do_action("ws_plugin__s2member_during_logs_page_during_left_sections_before_log_settings", get_defined_vars());
84
 
85
+ echo '<div class="ws-menu-page-group" title="Logging Configuration">'."\n";
86
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-log-settings-section">'."\n";
 
87
 
88
+ echo '<h3>Logging Configuration</h3>'."\n";
 
89
 
90
+ echo '<div class="info">'."\n";
91
+ echo '<p style="font-size:110%; margin-top:0;"><span>We HIGHLY recommend that you enable logging during your initial testing phase. Logs produce lots of useful details that can help in debugging. Logs can help you find issues in your configuration and/or problems that occur during processing. Enable logging here, and then view your log files below, in the s2Member Log Viewer.</span></p>'."\n";
92
+ echo '<p style="font-size:110%; margin-bottom:0;"><span class="ws-menu-page-error">However, it is VERY IMPORTANT to disable logging once you go live. Log files may contain personally identifiable information, credit card numbers, secret API credentials, passwords and/or other sensitive information. We STRONGLY suggest that logging be disabled on a live site (for security reasons).</span></p>'."\n";
93
+ echo '</div>'."\n";
94
 
95
+ echo '<div class="notice" style="margin-bottom:0;">'."\n";
96
+ echo '<p style="font-size:110%; margin-bottom:0;"><span>Regarding s2Member Security Badges. If debug logging is enabled, your site will NOT qualify for an s2Member Security Badge until you disable logging (and you must ALSO download, and then delete any existing log files). For further details, please see KB Article: <a href="http://www.s2member.com/kb/security-badges/" target="_blank" rel="external">s2Member Security Badges</a>.</span></p>'."\n";
97
+ echo '</div>'."\n";
 
98
 
99
+ echo '<div class="ws-menu-page-hr"></div>'."\n";
 
 
100
 
101
+ do_action("ws_plugin__s2member_during_logs_page_during_left_sections_during_log_settings", get_defined_vars());
102
 
103
+ echo '<form method="post" name="ws_plugin__s2member_options_form" id="ws-plugin--s2member-options-form">'."\n";
104
+ 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";
105
 
106
+ echo '<table class="form-table">'."\n";
107
+ echo '<tbody>'."\n";
108
+ echo '<tr>'."\n";
109
 
110
+ echo '<th>'."\n";
111
+ echo '<label for="ws-plugin--s2member-gateway-debug-logs">'."\n";
112
+ echo 'Enable Logging Routines?'."\n";
113
+ echo '</label>'."\n";
114
+ echo '</th>'."\n";
115
 
116
+ echo '</tr>'."\n";
117
+ echo '<tr>'."\n";
 
 
 
118
 
119
+ echo '<td>'."\n";
120
+ echo '<input type="radio" name="ws_plugin__s2member_gateway_debug_logs" id="ws-plugin--s2member-gateway-debug-logs-0" value="0"'.((!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["gateway_debug_logs"]) ? ' checked="checked"' : '').' /> <label for="ws-plugin--s2member-gateway-debug-logs-0">No</label> &nbsp;&nbsp;&nbsp; <input type="radio" name="ws_plugin__s2member_gateway_debug_logs" id="ws-plugin--s2member-gateway-debug-logs-1" value="1"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["gateway_debug_logs"]) ? ' checked="checked"' : '').' /> <label for="ws-plugin--s2member-gateway-debug-logs-1">Yes, enable debugging w/ HTTP, API, IPN &amp; Return Page logging (and List Server API logs too).</label><br />'."\n";
121
+ echo '<em>This enables logging overall. Includes s2Member HTTP, API, IPN and Return Page logging. Also logs any List Server integrations.</em><br />'."\n";
122
+ echo '<em>* Use only for debugging. This should NEVER be enabled on a live site.<br />* The log files are stored here: <code>'.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"])).'</code></em>'."\n";
123
+ echo '</td>'."\n";
124
 
125
+ echo '</tr>'."\n";
126
+ echo '<tr>'."\n";
 
 
 
127
 
128
+ echo '<th>'."\n";
129
+ echo '<label for="ws-plugin--s2member-gateway-debug-logs-extensive">'."\n";
130
+ echo 'Enable Additional Logging Routines?'."\n";
131
+ echo '</label>'."\n";
132
+ echo '</th>'."\n";
133
 
134
+ echo '</tr>'."\n";
135
+ echo '<tr>'."\n";
 
 
 
136
 
137
+ echo '<td>'."\n";
138
+ echo '<input type="radio" name="ws_plugin__s2member_gateway_debug_logs_extensive" id="ws-plugin--s2member-gateway-debug-logs-extensive-0" value="0"'.((!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["gateway_debug_logs_extensive"]) ? ' checked="checked"' : '').' /> <label for="ws-plugin--s2member-gateway-debug-logs-extensive-0">No</label> &nbsp;&nbsp;&nbsp; <input type="radio" name="ws_plugin__s2member_gateway_debug_logs_extensive" id="ws-plugin--s2member-gateway-debug-logs-extensive-1" value="1"'.(($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["gateway_debug_logs_extensive"]) ? ' checked="checked"' : '').' /> <label for="ws-plugin--s2member-gateway-debug-logs-extensive-1">Yes, enable debugging w/ HTTP connection logging for ALL of WordPress.</label><br />'."\n";
139
+ echo '<em>This enables HTTP connection logging for ALL of WordPress (quite extensive).<br />* Use only for debugging. This should NEVER be enabled on a live site.<br />* Creates the additional log file: <code>wp-http-api-debug.log</code></em>'."\n";
140
+ echo '</td>'."\n";
141
 
142
+ echo '</tr>'."\n";
143
+ echo '</tbody>'."\n";
144
+ echo '</table>'."\n";
 
145
 
146
+ echo '<p class="submit" style="margin-top:20px;">'."\n";
147
+ echo '<input type="submit" value="Update Logging Configuration" />'."\n";
148
+ echo '</p>'."\n";
149
 
150
+ echo '</form>'."\n";
 
 
151
 
152
+ echo '</div>'."\n";
153
+ echo '</div>'."\n";
154
 
155
+ do_action("ws_plugin__s2member_during_logs_page_during_left_sections_after_log_settings", get_defined_vars());
156
+ }
157
+ if(apply_filters("ws_plugin__s2member_during_logs_page_during_left_sections_display_logs", TRUE, get_defined_vars()))
158
+ {
159
+ do_action("ws_plugin__s2member_during_logs_page_during_left_sections_before_logs", get_defined_vars());
160
 
161
+ echo '<div class="ws-menu-page-group" title="Logs Viewer" default-state="open">'."\n";
 
162
 
163
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-logs-section">'."\n";
164
+ echo '<h3>Debugging Tools/Tips &amp; Other Important Details (<a href="#" onclick="jQuery(\'div#ws-plugin--s2member-debugging-tips-details\').toggle(); return false;" class="ws-dotted-link">click here to toggle</a>)</h3>'."\n";
 
165
 
166
+ echo '<div id="ws-plugin--s2member-debugging-tips-details" style="display:none;">'."\n";
167
 
168
+ echo '<div class="ws-menu-page-hr"></div>'."\n";
 
169
 
170
+ echo '<form method="post" onsubmit="if(!confirm(\'Archive all existing log files?\n\nAll of your current log files will be archived (e.g. they will simply be renamed with an ARCHIVED tag &amp; date in their file name); and new log files will be created automatically the next time s2Member logs something on your installation.\n\nPlease click OK to confirm this action.\')) return false;">'."\n";
171
+ echo '<input type="hidden" name="ws_plugin__s2member_logs_archive_start_fresh" value="'.esc_attr(wp_create_nonce("ws-plugin--s2member-logs-archive-start-fresh")).'" />'."\n";
172
+ echo '<input type="submit" value="Archive All Current Log Files" class="ws-menu-page-right ws-plugin--s2member-archive-logs-start-fresh-button" style="font-size:110%; font-weight:normal; clear:right; min-width:200px;" />'."\n";
173
+ echo '</form>'."\n";
174
 
175
+ echo '<form method="post" onsubmit="if(!confirm(\'Delete all existing log files?\n\nThis will permanently delete ALL of your existing log files (including any archived log files).\n\nPlease click OK to confirm this action.\')) return false;">'."\n";
176
+ echo '<input type="hidden" name="ws_plugin__s2member_logs_delete_start_fresh" value="'.esc_attr(wp_create_nonce("ws-plugin--s2member-logs-delete-start-fresh")).'" />'."\n";
177
+ echo '<input type="submit" value="Permanently Delete All Log Files" class="ws-menu-page-right ws-plugin--s2member-delete-logs-start-fresh-button" style="font-size:110%; font-weight:normal; clear:right; min-width:200px;" />'."\n";
178
+ echo '</form>'."\n";
179
 
180
+ echo '<form method="post">'."\n";
181
+ echo '<input type="hidden" name="ws_plugin__s2member_logs_download_zip" value="'.esc_attr(wp_create_nonce("ws-plugin--s2member-logs-download-zip")).'" />'."\n";
182
+ echo '<input type="submit" value="Download All Log Files (Zip File)" class="ws-menu-page-right ws-plugin--s2member-logs-download-zip-button" style="font-size:110%; font-weight:normal; clear:right; min-width:200px;" />'."\n";
183
+ echo '</form>'."\n";
184
 
185
+ echo '<p><strong>Debugging Tips:</strong> &nbsp;&nbsp; It is normal to see a few errors in your log files. This is because s2Member logs ALL of its communication with Payment Gateways. Everything — not just successes. With that in mind, there will be some failures that s2Member expects (to a certain extent); and s2Member deals with these gracefully. What you\'re looking for here, are things that jump right out at you as being a major issue (e.g. when s2Member makes a point of providing details to you in a log entry about problems that should be corrected on your installation). Please read carefully.</p>'."\n";
186
+ echo '<p><strong>Test Transaction Tips:</strong> &nbsp;&nbsp; Generally speaking, it is best to run test transactions for yourself. Be sure to run your final test transactions against a live Payment Gateway that is NOT in Sandbox/Test Mode (<a href="#" onclick="alert(\'While some Payment Gateways make it possible for you to run test transactions in Sandbox/Test Mode, these are NOT a reliable way to test s2Member.\n\nOften times (particularly with PayPal) Sandbox/Test mode behaves somewhat differently — often with buggy behavior. This can really create frustration for site owners. Therefore, it is always a good idea to run low-dollar test transactions against a live Payment Gateway.\n\nAlso, please be sure that you are NOT logged in as an Administrator when running test transactions. For most test transactions, you will want to be completely logged out of your site before completing checkout (just like a new Customer would be). If you are testing an upgrade or downgrade (where you DO need to be logged-in), please do NOT attempt this under an Administrative account. s2Member will NOT upgrade/downgrade Administrative accounts — for security purposes.\'); return false;">click here for details</a>). After running test transactions, please review the log file entries pertaining to your transaction. Does s2Member report any major issues? If so, please read through any details that s2Member provides in the log file. If you need assistance, please <a href="http://www.s2member.com/quick-s.php" target="_blank" rel="external">search s2Member.com</a> for answers to common questions.</p>'."\n";
187
+ echo '<p><strong>s2 Core Processors:</strong> &nbsp;&nbsp; It is normal to have a <code>paypay-ipn.log</code> and/or a <code>paypay-rtn.log</code> file at all times. Ultimately, all Payment Gateway integrations supported by s2Member pass through it\'s core PayPal processors; even if you\'ve integrated with another Payment Gateway. If you are having trouble, and you don\'t find any errors in your Payment Gateway log files, please check the <code>paypay-ipn.log</code> and <code>paypay-rtn.log</code> files too. Regarding s2Member Pro Forms... If you\'ve integrated s2Member Pro Forms, you will NOT have a <code>paypay-rtn.log</code> file, because that particular processor is not used with Pro Form integrations. However, you will have a <code>paypay-ipn.log</code> file, and you will need to make a point of inspecting this file to ensure there were no post-processing issues.</p>'."\n";
188
+ echo '<p><strong>s2 HTTP API Logs:</strong> &nbsp;&nbsp; If s2Member is not behaving as expected, and you cannot find errors anywhere in your Payment Gateway log files (or with any core PayPal processors), please review your <code>s2-http-api-debug.log</code> file too. Look for any HTTP connections where s2Member is getting <code>403</code>, <code>404</code>, <code>503</code> errors from your server. This can sometimes happen due to <a href="http://www.s2member.com/kb/mod-security-random-503-403-errors/" target="_blank" rel="external">paranoid Mod Security configurations</a>, and it may require you to contact your hosting company for assistance.</p>'."\n";
189
+ echo '<p style="font-style:italic;"><strong>Archived Log Files:</strong> &nbsp;&nbsp; All s2Member log files are stored here: <code>'.esc_html(c_ws_plugin__s2member_utils_dirs::doc_root_path($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"])).'</code>. Any log files that contain the word <code>ARCHIVED</code> in their name, are files that reached a size of more than 2MB, so s2Member archived them automatically to prevent any single log file from becoming too large. Archived log file names will also contain the date/time they were archived by s2Member. These archived log files typically contain much older (and possibly outdated) log entries.</p>'."\n";
190
 
191
+ echo '<div class="ws-menu-page-hr"></div>'."\n";
 
 
 
192
 
193
+ echo '<h3>s2Member Log File Descriptions (for ALL possible log file names)</h3>'."\n";
 
 
 
 
194
 
195
+ echo '<div class="ws-menu-page-hr"></div>'."\n";
196
 
197
+ echo '<ul class="ws-menu-page-li-margins">'."\n";
198
+ foreach(c_ws_plugin__s2member_utils_logs::$log_file_descriptions as $_k => $_v)
199
+ echo '<li><code><strong>'.esc_html(preg_replace(array('/^\/|\/$/', '/\\\\+/'), '', $_k)).'.log</strong></code> &nbsp;&nbsp; '.esc_html($_v["long"]).'</li>'."\n";
200
+ unset($_k, $_v); // Housekeeping.
201
+ echo '</ul>'."\n";
202
 
203
+ echo '<div class="ws-menu-page-hr"></div>'."\n";
204
 
205
+ echo '</div>'."\n";
 
 
 
 
206
 
207
+ do_action("ws_plugin__s2member_during_logs_page_during_left_sections_during_logs", get_defined_vars());
208
 
209
+ $log_file_options = ""; // Initialize to an empty string.
210
+ $view_log_file = (!empty($_POST["ws_plugin__s2member_log_file"])) ? esc_html($_POST["ws_plugin__s2member_log_file"]) : "";
211
+ $logs_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"];
212
 
213
+ if(is_dir($logs_dir)) // Do we have a logs directory on this installation?
214
+ {
215
+ $log_files = scandir($logs_dir);
216
+ sort($log_files, SORT_STRING);
217
 
218
+ $log_file_options .= '<optgroup label="Current Log Files">';
219
+ foreach($log_files as $_log_file) // Build options for each current log file.
220
+ {
221
+ $_log_file_description = array("short" => "No description available.", "long" => "No description available.");
222
 
223
+ foreach(c_ws_plugin__s2member_utils_logs::$log_file_descriptions as $_k => $_v)
224
+ if(preg_match($_k, $_log_file))
225
  {
226
+ $_log_file_description = $_v;
227
+ break; // Stop here.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
228
  }
229
+ unset($_k, $_v); // Housekeeping.
 
 
230
 
231
+ if(preg_match("/\.log$/", $_log_file) && stripos($_log_file, "-ARCHIVED-") === FALSE)
232
+ $log_file_options .= '<option data-type="current" title="'.esc_attr($_log_file_description["long"]).'" value="'.esc_attr($_log_file).'"'.(($view_log_file === $_log_file) ? ' style="font-weight:bold;" selected="selected"' : '').'>'.esc_html($_log_file).' — '.esc_html($_log_file_description["short"]).'</option>';
233
+ }
234
+ unset($_log_file_description, $_log_file); // Housekeeping.
235
+ $log_file_options .= '</optgroup>';
236
 
237
+ if(stripos($log_file_options, '<option data-type="current"') === FALSE)
238
+ $log_file_options .= '<option value="" disabled="disabled">— No current log files yet. —</option>';
 
239
 
240
+ $log_file_options .= '<option value="" disabled="disabled"></option>';
 
 
 
 
241
 
242
+ $log_file_options .= '<optgroup label="Archived Log Files">';
243
+ foreach($log_files as $_log_file) // Build options for each ARCHIVED log file.
244
+ {
245
+ if(preg_match("/\.log$/", $_log_file) && stripos($_log_file, "-ARCHIVED-") !== FALSE)
246
+ $log_file_options .= '<option data-type="archived" value="'.esc_attr($_log_file).'"'.(($view_log_file === $_log_file) ? ' style="font-weight:bold;" selected="selected"' : '').'>'.esc_html($_log_file).'</option>';
247
+ }
248
+ $log_file_options .= '</optgroup>';
249
 
250
+ if(stripos($log_file_options, '<option data-type="archived"') === FALSE)
251
+ $log_file_options .= '<option value="" disabled="disabled">— No log files archived yet. —</option>';
252
+ }
253
+ $log_file_options = '<option value="">— Choose a Log File to View —</option>'.
254
+ '<option value="" disabled="disabled"></option>'.
255
+ $log_file_options;
256
 
257
+ echo '<form method="post" name="ws_plugin__s2member_log_viewer" id="ws-plugin--s2member-log-viewer">'."\n";
 
 
258
 
259
+ echo '<table class="form-table">'."\n";
260
+ echo '<tbody>'."\n";
261
+ echo '<tr>'."\n";
262
 
263
+ echo '<td style="width:80%;">'."\n";
264
+ echo '<select name="ws_plugin__s2member_log_file" id="ws-plugin--s2member-log-file">'."\n";
265
+ echo $log_file_options."\n";
266
+ echo '</select>'."\n";
267
+ echo '</td>'."\n";
268
 
269
+ echo '<td style="width:20%; padding-left:5px;">'."\n";
270
+ echo '<input type="submit" value="View" style="font-size:120%; font-weight:normal;" />'."\n";
271
+ echo '</td>'."\n";
 
 
 
 
272
 
273
+ echo '</tr>'."\n";
274
+ echo '</tbody>'."\n";
275
+ echo '</table>'."\n";
276
 
277
+ echo '<table class="form-table">'."\n";
278
+ echo '<tbody>'."\n";
279
+ echo '<tr>'."\n";
280
 
281
+ echo '<td>'."\n";
282
 
283
+ if($view_log_file && file_exists($logs_dir."/".$view_log_file) && filesize($logs_dir."/".$view_log_file))
284
+ {
285
+ $_log_file_description = array("short" => "", "long" => "");
 
 
 
286
 
287
+ foreach(c_ws_plugin__s2member_utils_logs::$log_file_descriptions as $_k => $_v)
288
+ if(preg_match($_k, $view_log_file))
289
+ {
290
+ $_log_file_description = $_v;
291
+ break; // Stop here.
292
+ }
293
+ unset($_k, $_v); // Housekeeping.
294
 
295
+ if(!empty($_log_file_description["long"])) // Do we have a description that we can display here?
296
+ echo '<p style="clear:both; width:80%; font-family:\'Georgia\', serif; font-style:italic;"><strong>Description for <a href="'.esc_attr(add_query_arg(array("ws_plugin__s2member_download_log_file" => $view_log_file, "ws_plugin__s2member_download_log_file_v" => wp_create_nonce("ws-plugin--s2member-download-log-file-v")))).'">'.esc_html($view_log_file).'</a></strong>: '.esc_html($_log_file_description["long"]).'</p>'."\n";
297
+ unset($_log_file_description); // Just a little housekeeping here.
298
 
299
+ echo '<p style="float:left; text-align:left;"><strong>Viewing:</strong> <a href="'.esc_attr(add_query_arg(array("ws_plugin__s2member_download_log_file" => $view_log_file, "ws_plugin__s2member_download_log_file_v" => wp_create_nonce("ws-plugin--s2member-download-log-file-v")))).'">'.esc_html($view_log_file).'</a> (log entries oldest to newest)</p>'."\n";
300
+ echo '<p style="float:right; text-align:right;">[ <a href="'.esc_attr(add_query_arg(array("ws_plugin__s2member_download_log_file" => $view_log_file, "ws_plugin__s2member_download_log_file_v" => wp_create_nonce("ws-plugin--s2member-download-log-file-v")))).'"><strong>download file</strong></a> ]</p>'."\n";
301
+ echo '<p style="margin-right:10px; float:right; text-align:right;"><a href="#" class="ws-plugin--s2member-log-file-viewport-toggle" style="text-decoration:none;">&#8659; expand viewport &#8659;</a></p>'."\n";
302
 
303
+ echo '<textarea id="ws-plugin--s2member-log-file-viewer" rows="20" wrap="on" spellcheck="false" style="box-shadow:inset 0 0 5px rgba(0,0,0,0.5); background:#EEEEEE; color:#000000; overflow-y:scroll;">'.htmlspecialchars(file_get_contents($logs_dir."/".$view_log_file)).'</textarea>'."\n";
 
 
304
 
305
+ echo '<p style="float:left; text-align:left;"><strong>Viewing:</strong> <a href="'.esc_attr(add_query_arg(array("ws_plugin__s2member_download_log_file" => $view_log_file, "ws_plugin__s2member_download_log_file_v" => wp_create_nonce("ws-plugin--s2member-download-log-file-v")))).'">'.esc_html($view_log_file).'</a> (log entries oldest to newest)</p>'."\n";
306
+ echo '<p style="float:right; text-align:right;">[ <a href="'.esc_attr(add_query_arg(array("ws_plugin__s2member_download_log_file" => $view_log_file, "ws_plugin__s2member_download_log_file_v" => wp_create_nonce("ws-plugin--s2member-download-log-file-v")))).'"><strong>download file</strong></a> ]</p>'."\n";
307
+ echo '<p style="margin-right:10px; float:right; text-align:right;"><a href="#" class="ws-plugin--s2member-log-file-viewport-toggle" style="text-decoration:none;">&#8659; expand viewport &#8659;</a></p>'."\n";
308
+ }
309
+ else if($view_log_file && file_exists($logs_dir."/".$view_log_file))
310
+ echo '<textarea id="ws-plugin--s2member-log-file-viewer" rows="20" wrap="on" spellcheck="false" style="box-shadow:inset 0 0 5px rgba(0,0,0,0.5); background:#EEEEEE; color:#000000; overflow-y:scroll; font-style:italic;">— Empty at this time —</textarea>'."\n";
311
 
312
+ else if($view_log_file && !file_exists($logs_dir."/".$view_log_file))
313
+ echo '<textarea id="ws-plugin--s2member-log-file-viewer" rows="20" wrap="on" spellcheck="false" style="box-shadow:inset 0 0 5px rgba(0,0,0,0.5); background:#EEEEEE; color:#000000; overflow-y:scroll; font-style:italic;">— File no longer exists —</textarea>'."\n";
314
 
315
+ else // Display an empty textarea in this default scenario.
316
+ echo '<textarea id="ws-plugin--s2member-log-file-viewer" rows="20" wrap="on" spellcheck="false" style="box-shadow:inset 0 0 5px rgba(0,0,0,0.5); background:#EEEEEE; color:#000000; overflow-y:scroll; font-style:italic;"></textarea>'."\n";
317
 
318
+ echo '</td>'."\n";
319
 
320
+ echo '</tr>'."\n";
321
+ echo '</tbody>'."\n";
322
+ echo '</table>'."\n";
323
 
324
+ echo '</form>'."\n";
 
 
325
 
326
+ echo '</div>'."\n";
327
+ echo '</div>'."\n";
 
328
 
329
+ do_action("ws_plugin__s2member_during_logs_page_during_left_sections_after_logs", get_defined_vars());
 
330
  }
331
+ do_action("ws_plugin__s2member_during_logs_page_after_left_sections", get_defined_vars());
332
+
333
+ echo '</td>'."\n";
334
+
335
+ echo '<td class="ws-menu-page-table-r">'."\n";
336
+ c_ws_plugin__s2member_menu_pages_rs::display();
337
+ echo '</td>'."\n";
338
+
339
+ echo '</tr>'."\n";
340
+ echo '</tbody>'."\n";
341
+ echo '</table>'."\n";
342
+
343
+ echo '</div>'."\n";
344
+ }
345
  }
346
+ }
347
 
348
+ new c_ws_plugin__s2member_menu_page_logs();
 
includes/menu-pages/menu-pages.css CHANGED
@@ -16,7 +16,6 @@
16
  * @since x.xx
17
  */
18
  @import url('//maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css');
19
-
20
  /*
21
  Alter WordPress wrap on s2Member menu pages.
22
  */
@@ -24,7 +23,6 @@ body[class*='s2member'] #wpwrap
24
  {
25
  background : #C7C7C7;
26
  }
27
-
28
  /*
29
  Align these with menu page.
30
  */
@@ -33,7 +31,6 @@ div.updated, div.error
33
  font-size : 120%;
34
  margin : 25px 25px 25px 5px;
35
  }
36
-
37
  /*
38
  These CSS selectors address common layout styles.
39
  */
@@ -49,6 +46,11 @@ div.ws-menu-page
49
  box-shadow : 0 0 8px 0 rgba(0, 0, 0, 0.2) !important;
50
  background : #FFFFFF url('<?php echo $i; ?>/trans-bg.png') repeat left top;
51
  }
 
 
 
 
 
52
  div.ws-menu-page a
53
  {
54
  color : #003E75;
@@ -125,7 +127,7 @@ div.ws-menu-page code
125
  border-radius : 3px;
126
  padding : 1px 5px 1px 5px;
127
  background : rgba(255, 255, 255, 0.25);
128
- font-family : 'Monaco', 'Menlo', 'Consolas', 'Courier New', monospace;
129
  }
130
  div.ws-menu-page pre.code
131
  {
@@ -164,27 +166,23 @@ div.ws-menu-page img
164
  {
165
  border : 0;
166
  }
167
- div.ws-menu-page img.screenshot
168
  {
169
- float : right;
170
- margin : 0 0 15px 25px;
171
-
172
- border-radius : 5px;
173
- border : 1px solid #AFAFAF;
174
-
175
- box-shadow : 0 0 5px 0 rgba(0, 0, 0, 0.2) inset, 0 0 1px 0 rgba(72, 155, 88, 0.2);
176
- background : #FFFFFF;
177
  padding : 10px;
 
 
 
178
  }
179
  div.ws-menu-page .ws-menu-page-right
180
  {
181
- float : right;
182
  margin-left : 25px;
 
183
  }
184
  div.ws-menu-page .ws-menu-page-left
185
  {
186
- float : left;
187
  margin-right : 25px;
 
188
  }
189
  div.ws-menu-page .ws-menu-page-center
190
  {
@@ -262,52 +260,79 @@ div.ws-menu-page .form-table td
262
  font-size : inherit;
263
  line-height : inherit;
264
  }
265
- div.ws-menu-page input:not([type='image']):not([type='button']):not([type='submit']):not([type='radio']):not([type='checkbox']),
266
- div.ws-menu-page input:not([type='image']):not([type='button']):not([type='submit']):not([type='radio']):not([type='checkbox']):focus,
267
  div.ws-menu-page select, div.ws-menu-page select:focus,
268
- div.ws-menu-page textarea, div.ws-menu-page textarea:focus
 
 
269
  {
 
270
  width : 100%;
271
- height : auto;
272
 
273
- margin : 0;
274
- padding : 5px;
275
  line-height : 1em;
276
- box-sizing : border-box;
277
- border : 1px solid rgba(13, 31, 47, 0.5);
278
 
279
- color : #FFFFFF;
280
- background : #73834B;
281
- box-shadow : 0 0 1px 0 rgba(0, 0, 0, 0.5) inset, 0 0 1px 1px rgba(223, 245, 165, 0.5);
 
 
 
 
 
282
  }
283
- div.ws-menu-page input:not([type='image']):not([type='button']):not([type='submit']):not([type='radio']):not([type='checkbox']):focus,
284
- div.ws-menu-page select:focus, div.ws-menu-page textarea:focus
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
285
  {
286
  background : #637041;
287
  }
288
  div.ws-menu-page input::-webkit-input-placeholder
289
  {
290
- color : rgba(255, 255, 255, 0.2);
291
- font-style : italic;
292
  padding-top : 3px;
 
 
293
  }
294
  div.ws-menu-page input::-moz-placeholder
295
  {
296
- color : rgba(255, 255, 255, 0.2);
297
- font-style : italic;
298
  padding-top : 3px;
 
 
299
  }
300
  div.ws-menu-page input:-moz-placeholder
301
  {
302
- color : rgba(255, 255, 255, 0.2);
303
- font-style : italic;
304
  padding-top : 3px;
 
 
305
  }
306
  div.ws-menu-page input:-ms-input-placeholder
307
  {
308
- color : rgba(255, 255, 255, 0.2);
309
- font-style : italic;
310
  padding-top : 3px;
 
 
311
  }
312
  div.ws-menu-page input[disabled],
313
  div.ws-menu-page select[disabled],
@@ -326,7 +351,7 @@ div.ws-menu-page input[type='submit']
326
 
327
  border-radius : 4px;
328
  border : 1px solid rgba(0, 0, 0, 0.5);
329
- box-shadow : 0 1px 1px 0 rgba(0, 0, 0, 0.25), -1px -1px 0 1px rgba(0, 0, 0, 0.2) inset, 1px 1px 0 1px rgba(255, 255, 255, 0.1) inset;
330
 
331
  margin : 0;
332
  box-sizing : border-box;
@@ -382,10 +407,10 @@ div.ws-menu-page .notice,
382
  div.ws-menu-page .warning,
383
  div.ws-menu-page .error
384
  {
 
385
  font-size : 120%;
386
  padding : 10px;
387
  margin : 0 0 25px 0;
388
- border-radius : 5px;
389
  }
390
  div.ws-menu-page .info
391
  {
@@ -425,7 +450,6 @@ div.ws-menu-page .clearfix:after
425
  {
426
  clear : both;
427
  }
428
-
429
  /*
430
  Tools and togglers.
431
  */
@@ -445,7 +469,7 @@ div.ws-menu-page div.ws-menu-page-groups-hide
445
 
446
  border-radius : 4px;
447
  border : 1px solid rgba(0, 0, 0, 0.5);
448
- box-shadow : 0 1px 1px 0 rgba(0, 0, 0, 0.25), -1px -1px 0 1px rgba(0, 0, 0, 0.2) inset, 1px 1px 0 1px rgba(255, 255, 255, 0.1) inset;
449
 
450
  margin : 0;
451
  box-sizing : border-box;
@@ -491,7 +515,6 @@ div.ws-menu-page div.ws-menu-page-toolbox > .links a
491
  margin : 0 10px 0 10px;
492
  text-decoration : none;
493
  }
494
-
495
  /*
496
  Specifically for the main layout table.
497
  These CSS selectors address common layout styles.
@@ -507,8 +530,7 @@ table.ws-menu-page-table .info,
507
  table.ws-menu-page-table .warning,
508
  table.ws-menu-page-table .error
509
  {
510
- font-size : 80%;
511
- padding : 5px;
512
  margin : 1em 0 1em 0;
513
  }
514
  table.ws-menu-page-table ul,
@@ -699,6 +721,10 @@ table.ws-menu-page-table div.ws-menu-page-r-group-header.open:after
699
  table.ws-menu-page-table div.ws-menu-page-group,
700
  table.ws-menu-page-table div.ws-menu-page-r-group
701
  {
 
 
 
 
702
  z-index : 0;
703
  position : relative;
704
  display : none;
@@ -795,7 +821,6 @@ table.ws-menu-page-table div.ws-menu-page-group table.form-table > tbody > tr >
795
  background : #73834B;
796
  box-shadow : 0 0 1px 0 rgba(0, 0, 0, 0.5) inset, 0 0 1px 1px rgba(223, 245, 165, 0.5);
797
  }
798
-
799
  /*
800
  Specifically for info pages with readme files.
801
  These CSS selectors address common layout styles.
@@ -833,7 +858,6 @@ div.ws-menu-page-readme > div.readme > div.section > div.content ol > li
833
  list-style : decimal outside;
834
  margin-bottom : 0;
835
  }
836
-
837
  /*
838
  Specifically for the right sidebar panel.
839
  - Specifically for the updates box.
16
  * @since x.xx
17
  */
18
  @import url('//maxcdn.bootstrapcdn.com/font-awesome/4.1.0/css/font-awesome.min.css');
 
19
  /*
20
  Alter WordPress wrap on s2Member menu pages.
21
  */
23
  {
24
  background : #C7C7C7;
25
  }
 
26
  /*
27
  Align these with menu page.
28
  */
31
  font-size : 120%;
32
  margin : 25px 25px 25px 5px;
33
  }
 
34
  /*
35
  These CSS selectors address common layout styles.
36
  */
46
  box-shadow : 0 0 8px 0 rgba(0, 0, 0, 0.2) !important;
47
  background : #FFFFFF url('<?php echo $i; ?>/trans-bg.png') repeat left top;
48
  }
49
+ div.ws-menu-page p,
50
+ div.ws-menu-page code
51
+ {
52
+ font-size : inherit;
53
+ }
54
  div.ws-menu-page a
55
  {
56
  color : #003E75;
127
  border-radius : 3px;
128
  padding : 1px 5px 1px 5px;
129
  background : rgba(255, 255, 255, 0.25);
130
+ font-family : 'Menlo', 'Monaco', 'Consolas', 'Courier New', monospace;
131
  }
132
  div.ws-menu-page pre.code
133
  {
166
  {
167
  border : 0;
168
  }
169
+ div.ws-menu-page img.ws-menu-page-bordered
170
  {
171
+ border-radius : 4px;
 
 
 
 
 
 
 
172
  padding : 10px;
173
+ background : #FFFFFF;
174
+ border : 1px solid #AFAFAF;
175
+ box-shadow : 0 0 2px 1px #D8D8D8 inset, 0 0 1px 1px rgba(223, 245, 165, 0.5);
176
  }
177
  div.ws-menu-page .ws-menu-page-right
178
  {