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

Version Description

  • (s2Member) Bug fix / File Downloads. Use of PHP's fread() function has been updated to stream_get_contents() with a 2MB chunk size in order to satisfy the needs of site owners delivering VERY large files ( 500MB+ ) though simulated HTTP streams "inline". For instance, an MP4 video file into a FlowPlayer/JWPlayer or another Flash-based application. In addition, s2Member is now capable of output buffering its chunked file delivery, making it possible for s2Member to deliver VERY large files through most shared hosting platforms without needing to upgrade to a private server.
  • (s2Member) Bug fix / BuddyPress. Bug fix. New filter added in support of BuddyPress on a Multisite installation. add_filter ("bp_signup_usermeta", "ws_plugin__s2member_ms_process_signup_meta");
  • (s2Member) Bug fix / BuddyPress. Improved detection of BuddyPress activation/registration slugs using BP_ACTIVATION_SLUG, BP_REGISTER_SLUG in conjunction with improved routing of $usermeta data inside /s2member/includes/functions/config-user-registration.inc.php. This resolves an issue where s2Member was not properly applying Membership Levels ( e.g. an s2 Role ) with BuddyPress installed on a Multisite Network.
  • (s2Member) Custom Registration Fields. s2Member's API Notifications now support custom Replacement Codes for any Custom Registration Fields that you've configured with s2Member. This makes it easier for developers to integrate 3rd party services, because s2Member's API Notifications can now be configured to send additional information that may include data entered by your Customer into a Custom Registration Field. Also, s2Member still supports the custom="domain|cv1|cv2|cv3|etc..." Attribute in your Shortcode too. For full details, check your Dashboard under: s2Member -> API Notifications.
  • (s2Member) Improved documentation on various Replacement Codes available for s2Member. There are also some new Replacement Codes made available in various sections/integrations.
  • (s2Member) In WordPress, when you list all Users, you will find a search box in the upper right-hand corner of the screen. This search box now has the ability to find Members by Username, Display Name, Nickname, s2Member / Paid Subscr. ID, Custom String, and ANY Custom Registration Field value.
  • (s2Member) Advanced Content Dripping. A new PHP/API Constant has been made available for Content Dripping S2MEMBER_CURRENT_USER_PAID_REGISTRATION_DAYS ( note the addition of "PAID" ). Also, s2Member v3.3 includes an entirely new/alternative method for Dripping Content, using a new API Function called s2member_registration_time ([level]). You will find all of the information/documentation on this topic inside your Dashboard under: s2Member -> API Scripting -> Content Dripping. s2Member now has the ability to provide you with information about when a Member pays you at each specific Membership Level. That being said, there IS an issue with this... The new function s2member_registration_time () will NOT return data correctly for existing Members that paid you prior to you upgrading to s2Member v3.3+. This is because s2Member did NOT record all of this information in previous versions. So it can't give you what it doesn't have on any of your existing Members. Please check the forums for workarounds.
  • (s2Member) API Constants. s2Member v3.3 includes some new API Constants related to PayPal and PayPal Pro integration. Such as the configured PayPal API Username, Password, Signature, etc. These will make it easier for other extensions to be built on top of s2Member should the need arise.
  • (s2Member/s2Member Pro) Documentation updated throughout. Some minor wording changes were required here-and-there in order to prevent confusion with all of s2Member Pro's new Gateway integrations.
  • (s2Member/s2Member Pro) All of s2Member's Button Generators now give you the ability to set a Trial Period and a separate Trial Billing Amount. So instead of just offering a 100% free Trial Period, you can now offer an Initial Period at one price, but have the Subscription billed later at a different Regular Recurring rate.
  • (s2Member Pro) New configuration panel added to s2Member Pro. The new Other Gateways panel allows you to enable/disable other Payment Gateways that have been integrated with s2Member Pro.
  • (s2Member Pro) Google Checkout. s2Member Pro has been integrated with Google for Direct Payments and also for Recurring Billing. In order to take advantage of this new integration method, you will need to have a copy of s2Member Pro, and a Google Checkout Account. A Google Checkout account is free.
  • (s2Member Pro) ClickBank. s2Member Pro has now been integrated with ClickBank for Direct Payments and also for Recurring Billing. In order to take advantage of this new integration method, you will need to have a copy of s2Member Pro, and a ClickBank Merchant Account. Otherwise, you can just use the PayPal Standard integration that comes with the free version of s2Member.
  • (s2Member Pro) AliPay. s2Member Pro has been integrated with AliPay for Direct Payments. In order to take advantage of this new integration method, you will need to have an AliPay Merchant Account with Direct Pay enabled ( aka: -- ). This can sometimes take a couple of days to acquire. Once you've been approved at AliPay, you'll be given a Partner ID, and a Security Code; which you'll need to configure inside your s2Member -> AliPay Options.
  • (s2Member Pro) PayPal Pro integration with s2Member Pro, now supports Coupon Codes that can be configured to ONLY apply to (ta) Trial Amounts, or (ra) Regular Amounts. For further details and examples, please check your Dashboard under: s2Member -> Coupon Codes.
  • (s2Member Pro) PayPal Pro Forms with s2Member Pro, can now be configured to recur at these new intervals: Bi-Weekly, Bi-Monthly, and Quarterly recurring cycles.
  • (s2Member Pro) Documentation. New documentation on ALL of s2Member's Shortcode Attributes for Pro Forms, Standard Shortcodes, and other Payment Gateways; is now included inside your Dashboard. For each Payment Gateway that you enable, there will be a Button Generator available in the s2Member Menu panel. At the bottom of each Button Generating station, you'll find a detailed examination of s2Member's Shortcode Attributes. This should make s2Member even easier for developers to integrate.
  • (s2Member Pro) AliPay chinese documentation added to the /s2member-pro/extras/ folder in case developers would like to review the technical aspects. This is NOT required though.
Download this release

Release Info

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

Code changes from version 3.2.9 to 3.3

Files changed (91) hide show
  1. images/promos/shots/03_screenshot-1200x.jpg +0 -0
  2. images/promos/shots/04_screenshot-1200x.jpg +0 -0
  3. images/promos/shots/10_screenshot-1200x.jpg +0 -0
  4. images/promos/shots/11_screenshot-1200x.jpg +0 -0
  5. images/promos/shots/12_screenshot-1200x.jpg +0 -0
  6. images/promos/shots/13_screenshot-1200x.jpg +0 -0
  7. images/promos/shots/14_screenshot-1200x.jpg +0 -0
  8. images/promos/shots/15_screenshot-1200x.jpg +0 -0
  9. images/promos/shots/16_screenshot-1200x.jpg +0 -0
  10. images/promos/shots/17_screenshot-1200x.jpg +0 -0
  11. images/promos/shots/18_screenshot-1200x.jpg +0 -0
  12. images/promos/shots/19_screenshot-1200x.jpg +0 -0
  13. images/promos/shots/20_screenshot-1200x.jpg +0 -0
  14. images/promos/shots/21_screenshot-1200x.jpg +0 -0
  15. images/promos/shots/22_screenshot-1200x.jpg +0 -0
  16. images/promos/shots/23_screenshot-1200x.jpg +0 -0
  17. images/promos/shots/24_screenshot-1200x.jpg +0 -0
  18. images/promos/shots/25_screenshot-1200x.jpg +0 -0
  19. images/promos/shots/26_screenshot-1200x.jpg +0 -0
  20. images/promos/shots/27_screenshot-1200x.jpg +0 -0
  21. includes/dropins/bridges/_s2member-bbpress-bridge.php +8 -14
  22. includes/functions/api-functions.inc.php +35 -0
  23. includes/functions/auto-eots.inc.php +38 -15
  24. includes/functions/catg-level-access.inc.php +5 -5
  25. includes/functions/config-user-registration.inc.php +86 -30
  26. includes/functions/constants.inc.php +12 -11
  27. includes/functions/css-js-w-globals.inc.php +2 -0
  28. includes/functions/file-download-access.inc.php +47 -35
  29. includes/functions/force-ssl.inc.php +1 -1
  30. includes/functions/ip-restrictions.inc.php +5 -4
  31. includes/functions/is-systematic.inc.php +5 -5
  32. includes/functions/list-servers.inc.php +3 -5
  33. includes/functions/login-redirection.inc.php +9 -5
  34. includes/functions/membership-options.inc.php +7 -3
  35. includes/functions/menu-pages.inc.php +3 -3
  36. includes/functions/nocache.inc.php +1 -0
  37. includes/functions/page-level-access.inc.php +10 -10
  38. includes/functions/paypal-button.inc.php +37 -19
  39. includes/functions/paypal-utilities.inc.php +126 -30
  40. includes/functions/post-level-access.inc.php +10 -10
  41. includes/functions/ptag-level-access.inc.php +7 -7
  42. includes/functions/register-access.inc.php +2 -2
  43. includes/functions/registration-times.inc.php +66 -0
  44. includes/functions/ruri-level-access.inc.php +4 -2
  45. includes/functions/separates/paypal-notify.inc.php +461 -261
  46. includes/functions/separates/paypal-return.inc.php +31 -15
  47. includes/functions/sp-access.inc.php +1 -1
  48. includes/functions/tracking-codes.inc.php +2 -2
  49. includes/functions/translations.inc.php +2 -2
  50. includes/functions/user-access-level.inc.php +3 -3
  51. includes/functions/user-access-role.inc.php +36 -0
  52. includes/functions/user-deletions.inc.php +27 -6
  53. includes/functions/users-list.inc.php +88 -9
  54. includes/functions/utilities.inc.php +1 -1
  55. includes/hooks.inc.php +6 -3
  56. includes/menu-pages/api-ops.inc.php +90 -46
  57. includes/menu-pages/bridges.inc.php +8 -8
  58. includes/menu-pages/code-samples/current-user-custom.php +1 -1
  59. includes/menu-pages/code-samples/current-user-paid-registration-days-dripping.php +23 -0
  60. includes/menu-pages/code-samples/current-user-paid-registration-days.php +28 -0
  61. includes/menu-pages/code-samples/current-user-paid-registration-time.php +7 -0
  62. includes/menu-pages/code-samples/current-user-registration-days-dripping.php +0 -23
  63. includes/menu-pages/code-samples/current-user-registration-days.php +6 -6
  64. includes/menu-pages/code-samples/current-user-subscr-id.php +2 -2
  65. includes/menu-pages/code-samples/paypal-pdt-identity-token.php +7 -0
  66. includes/menu-pages/code-samples/s2member-paid-registration-time-examples.php +31 -0
  67. includes/menu-pages/code-samples/s2member-paid-registration-time.php +18 -0
  68. includes/menu-pages/down-ops.inc.php +5 -5
  69. includes/menu-pages/els-ops.inc.php +10 -10
  70. includes/menu-pages/menu-pages-s-min.js +1 -1
  71. includes/menu-pages/menu-pages-s.js +144 -134
  72. includes/menu-pages/mms-options.inc.php +9 -9
  73. includes/menu-pages/options.inc.php +5 -6
  74. includes/menu-pages/paypal-buttons.inc.php +114 -33
  75. includes/menu-pages/paypal-ops.inc.php +25 -25
  76. includes/menu-pages/scripting.inc.php +41 -11
  77. includes/menu-pages/start.inc.php +3 -3
  78. includes/menu-pages/trk-ops.inc.php +13 -13
  79. includes/s2member-min.js +1 -1
  80. includes/s2member.js +7 -5
  81. includes/syscon.inc.php +9 -13
  82. includes/templates/buttons/paypal-cancellation-button.html +1 -1
  83. includes/templates/buttons/paypal-checkout-button.html +2 -2
  84. includes/templates/buttons/paypal-sp-checkout-button.html +2 -2
  85. includes/templates/options/paypal-currencies.html +187 -24
  86. includes/templates/options/paypal-membership-regular-terms.html +2 -0
  87. includes/templates/shortcodes/paypal-cancellation-button-shortcode.html +1 -1
  88. includes/templates/shortcodes/paypal-checkout-button-shortcode.html +1 -1
  89. includes/templates/shortcodes/paypal-sp-checkout-button-shortcode.html +1 -1
  90. readme.txt +40 -14
  91. s2member.php +10 -4
images/promos/shots/03_screenshot-1200x.jpg CHANGED
Binary file
images/promos/shots/04_screenshot-1200x.jpg CHANGED
Binary file
images/promos/shots/10_screenshot-1200x.jpg CHANGED
Binary file
images/promos/shots/11_screenshot-1200x.jpg CHANGED
Binary file
images/promos/shots/12_screenshot-1200x.jpg CHANGED
Binary file
images/promos/shots/13_screenshot-1200x.jpg CHANGED
Binary file
images/promos/shots/14_screenshot-1200x.jpg CHANGED
Binary file
images/promos/shots/15_screenshot-1200x.jpg ADDED
Binary file
images/promos/shots/16_screenshot-1200x.jpg ADDED
Binary file
images/promos/shots/17_screenshot-1200x.jpg ADDED
Binary file
images/promos/shots/18_screenshot-1200x.jpg ADDED
Binary file
images/promos/shots/19_screenshot-1200x.jpg ADDED
Binary file
images/promos/shots/20_screenshot-1200x.jpg ADDED
Binary file
images/promos/shots/21_screenshot-1200x.jpg ADDED
Binary file
images/promos/shots/22_screenshot-1200x.jpg ADDED
Binary file
images/promos/shots/23_screenshot-1200x.jpg ADDED
Binary file
images/promos/shots/24_screenshot-1200x.jpg ADDED
Binary file
images/promos/shots/25_screenshot-1200x.jpg ADDED
Binary file
images/promos/shots/26_screenshot-1200x.jpg ADDED
Binary file
images/promos/shots/27_screenshot-1200x.jpg ADDED
Binary file
includes/dropins/bridges/_s2member-bbpress-bridge.php CHANGED
@@ -27,7 +27,7 @@ Tags: membership, members, member, register, signup, paypal, pay pal, s2member,
27
  Direct access denial.
28
  */
29
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
30
- exit("Do not access this file directly.");
31
  /*
32
  Filled by the s2Member installer. Or you can set this manually.
33
  - If this is NOT set, it defaults to 0 = ( Free Subscribers ).
@@ -46,15 +46,9 @@ function ws_plugin__s2member_bridge_bbpress_roles () /* On-the-fly. */
46
  /**/
47
  if (is_object ($user = bb_get_current_user ()) && $user->ID) /* Logged in? */
48
  /**/
49
- if (empty ($user->roles)) /* Only when no bbPress® Role has been assigned yet. */
50
  /**/
51
- foreach ($user->$wp_capabilities as $wp_cap => $v) /* Check ^s2member_level[1-4]+ */
52
- /**/
53
- if (preg_match ("/^s2member_level[0-4]$/", $wp_cap)) /* An s2Member Role? */
54
- {
55
- bb_give_user_default_role($user);
56
- break; /* Now a Member! */
57
- }
58
  }
59
  /*
60
  Deny all access to the bbPress® registration page.
@@ -85,7 +79,7 @@ function ws_plugin__s2member_bridge_bbpress_access () /* Check Access. */
85
  wp_redirect($url); /* Referred locally. Let's go back to the Front Page. */
86
  /**/
87
  else /* Otherwise, trigger the Membership Options Page + s2member_level_req = $min. */
88
- wp_redirect($url . "/?s2member_membership_options_page=1&s2member_level_req=" . urlencode ($min));
89
  /**/
90
  exit ();
91
  }
@@ -97,9 +91,9 @@ function ws_plugin__s2member_bridge_bbpress_access () /* Check Access. */
97
  /**/
98
  if (preg_match ("/^(subscriber|s2member_level[0-4])$/", $wp_cap)) /* Subscribers and/or s2Member Roles. */
99
  /**/
100
- if (($wp_cap === "subscriber" && $min > 0) || ($level = preg_replace ("/[^0-9]/", "", $wp_cap)) < $min)
101
  /**/
102
- if ($url = bb_get_option ("wp_siteurl")) /* WordPress® is integrated? */
103
  {
104
  $bbPress = bb_get_option ("uri"); /* bbPress® location. */
105
  /**/
@@ -107,7 +101,7 @@ function ws_plugin__s2member_bridge_bbpress_access () /* Check Access. */
107
  wp_redirect($url); /* Referred locally. Let's go back to the Front Page. */
108
  /**/
109
  else /* Otherwise, trigger the Membership Options Page + s2member_level_req = $min. */
110
- wp_redirect($url . "/?s2member_membership_options_page=1&s2member_level_req=" . urlencode ($min));
111
  /**/
112
  exit ();
113
  }
@@ -117,7 +111,7 @@ function ws_plugin__s2member_bridge_bbpress_access () /* Check Access. */
117
  {
118
  if ($url = bb_get_option ("wp_siteurl")) /* The Front Page on the WordPress® installation. */
119
  {
120
- wp_redirect($url . "/?s2member_membership_options_page=1&s2member_level_req=" . urlencode ($min));
121
  exit (); /* Membership Options Page + s2member_level_req = $min. */
122
  }
123
  }
27
  Direct access denial.
28
  */
29
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
30
+ exit ("Do not access this file directly.");
31
  /*
32
  Filled by the s2Member installer. Or you can set this manually.
33
  - If this is NOT set, it defaults to 0 = ( Free Subscribers ).
46
  /**/
47
  if (is_object ($user = bb_get_current_user ()) && $user->ID) /* Logged in? */
48
  /**/
49
+ if (empty ($user->roles)) /* Only if/when no bbPress® Role is assigned. */
50
  /**/
51
+ bb_give_user_default_role($user); /* Assign a default Role. */
 
 
 
 
 
 
52
  }
53
  /*
54
  Deny all access to the bbPress® registration page.
79
  wp_redirect($url); /* Referred locally. Let's go back to the Front Page. */
80
  /**/
81
  else /* Otherwise, trigger the Membership Options Page + s2member_level_req = $min. */
82
+ wp_redirect ($url . "/?s2member_membership_options_page=1&s2member_seeking=bbpress&s2member_level_req=" . urlencode ($min));
83
  /**/
84
  exit ();
85
  }
91
  /**/
92
  if (preg_match ("/^(subscriber|s2member_level[0-4])$/", $wp_cap)) /* Subscribers and/or s2Member Roles. */
93
  /**/
94
+ if (($wp_cap === "subscriber" && $min > 0) || ($level = preg_replace ("/^s2member_level/", "", $wp_cap)) < $min)
95
  /**/
96
+ if ($url = bb_get_option ("wp_siteurl")) /* Only if WordPress® is fully integrated? */
97
  {
98
  $bbPress = bb_get_option ("uri"); /* bbPress® location. */
99
  /**/
101
  wp_redirect($url); /* Referred locally. Let's go back to the Front Page. */
102
  /**/
103
  else /* Otherwise, trigger the Membership Options Page + s2member_level_req = $min. */
104
+ wp_redirect ($url . "/?s2member_membership_options_page=1&s2member_seeking=bbpress&s2member_level_req=" . urlencode ($min));
105
  /**/
106
  exit ();
107
  }
111
  {
112
  if ($url = bb_get_option ("wp_siteurl")) /* The Front Page on the WordPress® installation. */
113
  {
114
+ wp_redirect ($url . "/?s2member_membership_options_page=1&s2member_seeking=bbpress&s2member_level_req=" . urlencode ($min));
115
  exit (); /* Membership Options Page + s2member_level_req = $min. */
116
  }
117
  }
includes/functions/api-functions.inc.php CHANGED
@@ -430,6 +430,41 @@ if (!function_exists ("s2member_file_download_key"))
430
  }
431
  }
432
  /*
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
433
  Retrieves a Custom Field value.
434
  $field_id - required argument.
435
  $user_id - defaults to current user.
430
  }
431
  }
432
  /*
433
+ Retrieves a Registration Time.
434
+ $user_id defaults to the current user; if logged in.
435
+ */
436
+ if (!function_exists ("s2member_registration_time"))
437
+ {
438
+ function s2member_registration_time ($user_id = FALSE)
439
+ {
440
+ return ws_plugin__s2member_registration_time ($user_id);
441
+ }
442
+ }
443
+ /*
444
+ Retrieves a Paid Registration Time.
445
+
446
+ The $level argument is optional. It defaults to the first/initial Paid Registration Time, regardless of Level#.
447
+ Or you could do this: s2member_paid_registration_time("level1"); which will give you the Registration Time at Level #1.
448
+ If a User/Member has never paid for Level #1 ( i.e. they signed up at Level#2 ), the function will return 0.
449
+
450
+ Here are some other examples:
451
+ $time = s2member_registration_time (); // ... first registration time ( free or otherwise ).
452
+ $time = s2member_paid_registration_time (); // ... first "paid" registration and/or upgrade time.
453
+ $time = s2member_paid_registration_time ("level1"); // ... first "paid" registration or upgrade time at Level#1.
454
+ $time = s2member_paid_registration_time ("level2"); // ... first "paid" registration or upgrade time at Level#2.
455
+ $time = s2member_paid_registration_time ("level3"); // ... first "paid" registration or upgrade time at Level#3.
456
+ $time = s2member_paid_registration_time ("level4"); // ... first "paid" registration or upgrade time at Level#4.
457
+
458
+ The argument $user_id defaults to the current user; if logged in.
459
+ */
460
+ if (!function_exists ("s2member_paid_registration_time"))
461
+ {
462
+ function s2member_paid_registration_time ($level = FALSE, $user_id = FALSE)
463
+ {
464
+ return ws_plugin__s2member_paid_registration_time ($level, $user_id);
465
+ }
466
+ }
467
+ /*
468
  Retrieves a Custom Field value.
469
  $field_id - required argument.
470
  $user_id - defaults to current user.
includes/functions/auto-eots.inc.php CHANGED
@@ -12,7 +12,7 @@ If not, see: <http://www.gnu.org/licenses/>.
12
  Direct access denial.
13
  */
14
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
15
- exit("Do not access this file directly.");
16
  /*
17
  Function processed by WP-Cron. This handles Auto-EOTs.
18
 
@@ -51,8 +51,9 @@ if (!function_exists ("ws_plugin__s2member_auto_eot_system"))
51
  {
52
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_eot_behavior"] === "demote")
53
  {
54
- $subscr_id = get_user_option ("s2member_subscr_id", $user_id);
55
  $custom = get_user_option ("s2member_custom", $user_id);
 
 
56
  /**/
57
  $demotion_role = ws_plugin__s2member_force_demotion_role ("subscriber");
58
  $user->set_role ($demotion_role); /* Defaults to Free Subscriber. */
@@ -63,6 +64,10 @@ if (!function_exists ("ws_plugin__s2member_auto_eot_system"))
63
  /**/
64
  delete_user_option ($user_id, "s2member_custom");
65
  delete_user_option ($user_id, "s2member_subscr_id");
 
 
 
 
66
  delete_user_option ($user_id, "s2member_last_payment_time");
67
  delete_user_option ($user_id, "s2member_auto_eot_time");
68
  /**/
@@ -81,15 +86,22 @@ if (!function_exists ("ws_plugin__s2member_auto_eot_system"))
81
  if (($url = preg_replace ("/%%user_email%%/i", ws_plugin__s2member_esc_ds (urlencode ($user->user_email)), $url)))
82
  if (($url = preg_replace ("/%%user_login%%/i", ws_plugin__s2member_esc_ds (urlencode ($user->user_login)), $url)))
83
  if (($url = preg_replace ("/%%user_id%%/i", ws_plugin__s2member_esc_ds (urlencode ($user_id)), $url)))
84
- /**/
85
- if (($url = trim ($url))) /* Empty? */
86
- ws_plugin__s2member_remote($url);
 
 
 
 
 
 
87
  }
88
  /**/
89
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["eot_del_notification_recipients"] && is_array ($cv = preg_split ("/\|/", $custom)))
90
  {
91
  $msg = $sbj = "( s2Member / API Notification Email ) - EOT/Deletion";
92
  $msg .= "\n\n"; /* Spacing in the message body. */
 
93
  $msg .= "subscr_id: %%subscr_id%%\n";
94
  $msg .= "user_first_name: %%user_first_name%%\n";
95
  $msg .= "user_last_name: %%user_last_name%%\n";
@@ -97,6 +109,11 @@ if (!function_exists ("ws_plugin__s2member_auto_eot_system"))
97
  $msg .= "user_email: %%user_email%%\n";
98
  $msg .= "user_login: %%user_login%%\n";
99
  $msg .= "user_id: %%user_id%%\n";
 
 
 
 
 
100
  $msg .= "cv0: %%cv0%%\n";
101
  $msg .= "cv1: %%cv1%%\n";
102
  $msg .= "cv2: %%cv2%%\n";
@@ -114,13 +131,19 @@ if (!function_exists ("ws_plugin__s2member_auto_eot_system"))
114
  if (($msg = preg_replace ("/%%user_email%%/i", ws_plugin__s2member_esc_ds ($user->user_email), $msg)))
115
  if (($msg = preg_replace ("/%%user_login%%/i", ws_plugin__s2member_esc_ds ($user->user_login), $msg)))
116
  if (($msg = preg_replace ("/%%user_id%%/i", ws_plugin__s2member_esc_ds ($user_id), $msg)))
117
- /**/
118
- foreach (ws_plugin__s2member_trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["eot_del_notification_recipients"])) as $recipient)
 
 
 
119
  /**/
120
- ($recipient) ? mail ($recipient, $sbj, apply_filters ("ws_plugin__s2member_eot_del_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
 
 
 
121
  }
122
  /**/
123
- eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
124
  do_action ("ws_plugin__s2member_during_auto_eot_system_during_demote", get_defined_vars ());
125
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
126
  }
@@ -135,14 +158,14 @@ if (!function_exists ("ws_plugin__s2member_auto_eot_system"))
135
  /**/
136
  else /* Otherwise, we can actually delete them. */
137
  /* This will automatically trigger `eot_del_notification_urls` as well. */
138
- wp_delete_user($user_id); /* `ws_plugin__s2member_handle_user_deletions()` */
139
  /**/
140
- eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
141
  do_action ("ws_plugin__s2member_during_auto_eot_system_during_delete", get_defined_vars ());
142
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
143
  }
144
  /**/
145
- eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
146
  do_action ("ws_plugin__s2member_during_auto_eot_system", get_defined_vars ());
147
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
148
  }
@@ -151,7 +174,7 @@ if (!function_exists ("ws_plugin__s2member_auto_eot_system"))
151
  }
152
  }
153
  /**/
154
- eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
155
  do_action ("ws_plugin__s2member_after_auto_eot_system", get_defined_vars ());
156
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
157
  /**/
@@ -220,8 +243,8 @@ if (!function_exists ("ws_plugin__s2member_delete_auto_eot_system"))
220
  /**/
221
  if (function_exists ("wp_cron"))
222
  {
223
- wp_clear_scheduled_hook("s2member_auto_eot_system"); /* This is for backward compatibility. */
224
- wp_clear_scheduled_hook("ws_plugin__s2member_auto_eot_system__schedule"); /* Since v3.0.3. */
225
  /**/
226
  return apply_filters ("ws_plugin__s2member_delete_auto_eot_system", true, get_defined_vars ());
227
  }
12
  Direct access denial.
13
  */
14
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
15
+ exit ("Do not access this file directly.");
16
  /*
17
  Function processed by WP-Cron. This handles Auto-EOTs.
18
 
51
  {
52
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_eot_behavior"] === "demote")
53
  {
 
54
  $custom = get_user_option ("s2member_custom", $user_id);
55
+ $subscr_id = get_user_option ("s2member_subscr_id", $user_id);
56
+ $fields = get_user_option ("s2member_custom_fields", $user_id);
57
  /**/
58
  $demotion_role = ws_plugin__s2member_force_demotion_role ("subscriber");
59
  $user->set_role ($demotion_role); /* Defaults to Free Subscriber. */
64
  /**/
65
  delete_user_option ($user_id, "s2member_custom");
66
  delete_user_option ($user_id, "s2member_subscr_id");
67
+ /**/
68
+ if (!apply_filters ("ws_plugin__s2member_preserve_paid_registration_times", true, get_defined_vars ()))
69
+ delete_user_option ($user_id, "s2member_paid_registration_times");
70
+ /**/
71
  delete_user_option ($user_id, "s2member_last_payment_time");
72
  delete_user_option ($user_id, "s2member_auto_eot_time");
73
  /**/
86
  if (($url = preg_replace ("/%%user_email%%/i", ws_plugin__s2member_esc_ds (urlencode ($user->user_email)), $url)))
87
  if (($url = preg_replace ("/%%user_login%%/i", ws_plugin__s2member_esc_ds (urlencode ($user->user_login)), $url)))
88
  if (($url = preg_replace ("/%%user_id%%/i", ws_plugin__s2member_esc_ds (urlencode ($user_id)), $url)))
89
+ {
90
+ if (is_array ($fields) && !empty ($fields))
91
+ foreach ($fields as $var => $val) /* Custom Registration Fields. */
92
+ if (! ($url = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", ws_plugin__s2member_esc_ds (urlencode (maybe_serialize ($val))), $url)))
93
+ break;
94
+ /**/
95
+ if (($url = trim (preg_replace ("/%%(.+?)%%/i", "", $url))))
96
+ ws_plugin__s2member_remote ($url);
97
+ }
98
  }
99
  /**/
100
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["eot_del_notification_recipients"] && is_array ($cv = preg_split ("/\|/", $custom)))
101
  {
102
  $msg = $sbj = "( s2Member / API Notification Email ) - EOT/Deletion";
103
  $msg .= "\n\n"; /* Spacing in the message body. */
104
+ /**/
105
  $msg .= "subscr_id: %%subscr_id%%\n";
106
  $msg .= "user_first_name: %%user_first_name%%\n";
107
  $msg .= "user_last_name: %%user_last_name%%\n";
109
  $msg .= "user_email: %%user_email%%\n";
110
  $msg .= "user_login: %%user_login%%\n";
111
  $msg .= "user_id: %%user_id%%\n";
112
+ /**/
113
+ if (is_array ($fields) && !empty ($fields))
114
+ foreach ($fields as $var => $val)
115
+ $msg .= $var . ": %%" . $var . "%%\n";
116
+ /**/
117
  $msg .= "cv0: %%cv0%%\n";
118
  $msg .= "cv1: %%cv1%%\n";
119
  $msg .= "cv2: %%cv2%%\n";
131
  if (($msg = preg_replace ("/%%user_email%%/i", ws_plugin__s2member_esc_ds ($user->user_email), $msg)))
132
  if (($msg = preg_replace ("/%%user_login%%/i", ws_plugin__s2member_esc_ds ($user->user_login), $msg)))
133
  if (($msg = preg_replace ("/%%user_id%%/i", ws_plugin__s2member_esc_ds ($user_id), $msg)))
134
+ {
135
+ if (is_array ($fields) && !empty ($fields))
136
+ foreach ($fields as $var => $val) /* Custom Registration Fields. */
137
+ if (! ($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", ws_plugin__s2member_esc_ds (maybe_serialize ($val)), $msg)))
138
+ break;
139
  /**/
140
+ if (($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg))))
141
+ foreach (ws_plugin__s2member_trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["eot_del_notification_recipients"])) as $recipient)
142
+ ($recipient) ? wp_mail ($recipient, apply_filters ("ws_plugin__s2member_eot_del_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_eot_del_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
143
+ }
144
  }
145
  /**/
146
+ eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
147
  do_action ("ws_plugin__s2member_during_auto_eot_system_during_demote", get_defined_vars ());
148
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
149
  }
158
  /**/
159
  else /* Otherwise, we can actually delete them. */
160
  /* This will automatically trigger `eot_del_notification_urls` as well. */
161
+ wp_delete_user ($user_id); /* `ws_plugin__s2member_handle_user_deletions()` */
162
  /**/
163
+ eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
164
  do_action ("ws_plugin__s2member_during_auto_eot_system_during_delete", get_defined_vars ());
165
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
166
  }
167
  /**/
168
+ eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
169
  do_action ("ws_plugin__s2member_during_auto_eot_system", get_defined_vars ());
170
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
171
  }
174
  }
175
  }
176
  /**/
177
+ eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
178
  do_action ("ws_plugin__s2member_after_auto_eot_system", get_defined_vars ());
179
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
180
  /**/
243
  /**/
244
  if (function_exists ("wp_cron"))
245
  {
246
+ wp_clear_scheduled_hook ("s2member_auto_eot_system"); /* This is for backward compatibility. */
247
+ wp_clear_scheduled_hook ("ws_plugin__s2member_auto_eot_system__schedule"); /* Since v3.0.3. */
248
  /**/
249
  return apply_filters ("ws_plugin__s2member_delete_auto_eot_system", true, get_defined_vars ());
250
  }
includes/functions/catg-level-access.inc.php CHANGED
@@ -45,7 +45,7 @@ if (!function_exists ("ws_plugin__s2member_check_catg_level_access"))
45
  /**/
46
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_redirection_override"] && ($login_redirection_uri = ws_plugin__s2member_login_redirection_uri ($current_user)) && preg_match ("/^" . preg_quote ($login_redirection_uri, "/") . "$/", $_SERVER["REQUEST_URI"]) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level0")))
47
  {
48
- wp_redirect (add_query_arg ("s2member_level_req", 0, get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
49
  exit ();
50
  }
51
  else if (!ws_plugin__s2member_is_systematic_use_page ()) /* Do NOT protect Systematics. However, there is 1 exception above ^. */
@@ -54,13 +54,13 @@ if (!function_exists ("ws_plugin__s2member_check_catg_level_access"))
54
  {
55
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_catgs"] === "all" && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
56
  {
57
- wp_redirect (add_query_arg ("s2member_level_req", $i, get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
58
  exit ();
59
  }
60
  /**/
61
  else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_catgs"] && in_array ($cat_id, ($catgs = preg_split ("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_catgs"]))) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
62
  {
63
- wp_redirect (add_query_arg ("s2member_level_req", $i, get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
64
  exit ();
65
  }
66
  /**/
@@ -68,7 +68,7 @@ if (!function_exists ("ws_plugin__s2member_check_catg_level_access"))
68
  foreach (preg_split ("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_catgs"]) as $catg)
69
  if ($catg && cat_is_ancestor_of ($catg, $cat_id) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
70
  {
71
- wp_redirect (add_query_arg ("s2member_level_req", $i, get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
72
  exit ();
73
  }
74
  }
@@ -79,7 +79,7 @@ if (!function_exists ("ws_plugin__s2member_check_catg_level_access"))
79
  foreach (preg_split ("/[\r\n\t]+/", ws_plugin__s2member_fill_ruri_level_access_rc_vars ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_ruris"], $current_user)) as $str)
80
  if ($str && preg_match ("/" . preg_quote ($str, "/") . "/", $_SERVER["REQUEST_URI"]) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
81
  {
82
- wp_redirect (add_query_arg ("s2member_level_req", $i, get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
83
  exit ();
84
  }
85
  }
45
  /**/
46
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_redirection_override"] && ($login_redirection_uri = ws_plugin__s2member_login_redirection_uri ($current_user)) && preg_match ("/^" . preg_quote ($login_redirection_uri, "/") . "$/", $_SERVER["REQUEST_URI"]) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level0")))
47
  {
48
+ wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "catg-" . $cat_id, "s2member_level_req" => "0")), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
49
  exit ();
50
  }
51
  else if (!ws_plugin__s2member_is_systematic_use_page ()) /* Do NOT protect Systematics. However, there is 1 exception above ^. */
54
  {
55
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_catgs"] === "all" && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
56
  {
57
+ wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "catg-" . $cat_id, "s2member_level_req" => $i)), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
58
  exit ();
59
  }
60
  /**/
61
  else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_catgs"] && in_array ($cat_id, ($catgs = preg_split ("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_catgs"]))) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
62
  {
63
+ wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "catg-" . $cat_id, "s2member_level_req" => $i)), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
64
  exit ();
65
  }
66
  /**/
68
  foreach (preg_split ("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_catgs"]) as $catg)
69
  if ($catg && cat_is_ancestor_of ($catg, $cat_id) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
70
  {
71
+ wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "catg-" . $cat_id, "s2member_level_req" => $i)), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
72
  exit ();
73
  }
74
  }
79
  foreach (preg_split ("/[\r\n\t]+/", ws_plugin__s2member_fill_ruri_level_access_rc_vars ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_ruris"], $current_user)) as $str)
80
  if ($str && preg_match ("/" . preg_quote ($str, "/") . "/", $_SERVER["REQUEST_URI"]) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
81
  {
82
+ wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "catg-" . $cat_id, "s2member_level_req" => $i)), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
83
  exit ();
84
  }
85
  }
includes/functions/config-user-registration.inc.php CHANGED
@@ -18,6 +18,7 @@ Function that adds hidden fields to POST vars on signup.
18
  Attach to: add_filter("signup_hidden_fields");
19
 
20
  This can ONLY be fired through wp-signup.php on the front-side.
 
21
  */
22
  if (!function_exists ("ws_plugin__s2member_ms_process_signup_hidden_fields"))
23
  {
@@ -26,7 +27,7 @@ if (!function_exists ("ws_plugin__s2member_ms_process_signup_hidden_fields"))
26
  do_action ("ws_plugin__s2member_before_ms_process_signup_hidden_fields", get_defined_vars ());
27
  /**/
28
  if (is_multisite ()) /* This event should ONLY be processed with Multisite Networking, on a Blog Farm. */
29
- if (ws_plugin__s2member_is_multisite_farm () && is_main_site () && preg_match ("/\/wp-signup\.php/", $_SERVER["REQUEST_URI"]) && $_POST["stage"] === "validate-user-signup")
30
  {
31
  foreach ((array)ws_plugin__s2member_trim_deep (stripslashes_deep ($_POST)) as $key => $value)
32
  if (preg_match ("/^ws_plugin__s2member_(custom_reg_field|user_new)_/", $key))
@@ -42,6 +43,7 @@ if (!function_exists ("ws_plugin__s2member_ms_process_signup_hidden_fields"))
42
  /*
43
  Function that adds customs fields to $meta on signup.
44
  Attach to: add_filter("add_signup_meta");
 
45
 
46
  This can be fired through wp-signup.php on the front-side,
47
  or possibly through user-new.php in the admin.
@@ -57,7 +59,7 @@ if (!function_exists ("ws_plugin__s2member_ms_process_signup_meta"))
57
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
58
  /**/
59
  if (is_multisite ()) /* This event should ONLY be processed with Multisite Networking. Either in the admin, or on a Blog Farm through wp-signup.php. */
60
- if ((is_admin () && $pagenow === "user-new.php") || (ws_plugin__s2member_is_multisite_farm () && is_main_site () && preg_match ("/\/wp-signup\.php/", $_SERVER["REQUEST_URI"]) && preg_match ("/^validate-(user|blog)-signup$/", $_POST["stage"])))
61
  {
62
  ws_plugin__s2member_email_config (); /* Configures From: header that will be used in notifications. */
63
  /**/
@@ -83,8 +85,9 @@ However, a Super Admin CAN trigger this event by adding a new User through the U
83
  ~ If they choose to bypass activation; an activation IS fired immediately. Otherwise, it's delayed.
84
  - via user-new.php.
85
 
86
- So this function may get fired inside the admin panel ( user-new.php ).
87
- Or also during an actual activation; through wp-activate.php.
 
88
  */
89
  if (!function_exists ("ws_plugin__s2member_configure_user_on_ms_user_activation"))
90
  {
@@ -97,7 +100,7 @@ if (!function_exists ("ws_plugin__s2member_configure_user_on_ms_user_activation"
97
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
98
  /**/
99
  if (is_multisite ()) /* This event should ONLY be processed with Multisite Networking. */
100
- if ((is_admin () && $pagenow === "user-new.php") || (!is_admin () && preg_match ("/\/wp-activate\.php/", $_SERVER["REQUEST_URI"])))
101
  {
102
  ws_plugin__s2member_configure_user_registration ($user_id, $password, $meta["s2member_ms_signup_meta"]);
103
  delete_user_meta ($user_id, "s2member_ms_signup_meta");
@@ -116,7 +119,8 @@ This does NOT fire for a Super Admin managing Network Blogs.
116
  ~ Actually they do; BUT it's blocked by the routine below.
117
  Which is good. A Super Admin should NOT trigger this event.
118
 
119
- This function should ONLY be fired through wp-activate.php.
 
120
  */
121
  if (!function_exists ("ws_plugin__s2member_configure_user_on_ms_blog_activation"))
122
  {
@@ -127,7 +131,7 @@ if (!function_exists ("ws_plugin__s2member_configure_user_on_ms_blog_activation"
127
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
128
  /**/
129
  if (is_multisite ()) /* This event should ONLY be processed with Multisite Networking. */
130
- if (!is_admin () && preg_match ("/\/wp-activate\.php/", $_SERVER["REQUEST_URI"])) /* ONLY `wp-activate.php`. */
131
  {
132
  ws_plugin__s2member_configure_user_registration ($user_id, $password, $meta["s2member_ms_signup_meta"]);
133
  delete_user_meta ($user_id, "s2member_ms_signup_meta");
@@ -172,9 +176,10 @@ if (!function_exists ("ws_plugin__s2member_configure_user_registration"))
172
  && (is_array ($_POST = ws_plugin__s2member_trim_deep (stripslashes_deep ($_POST))) || is_array (ws_plugin__s2member_trim_deep (stripslashes_deep ($meta))))/**/
173
  /**/
174
  /* These negative matches are designed to prevent this routine from running under certain conditions; where we need to wait for `wpmu_activate_user|blog` instead. */
175
- && ! (is_admin () && is_multisite () && $pagenow === "user-new.php" && isset ($_POST["noconfirmation"]) && is_super_admin () && empty ($meta))/**/
176
- && ! (preg_match ("/\/wp-activate\.php/", $_SERVER["REQUEST_URI"]) && empty ($meta)) /* If activating; we MUST have a meta array. */
177
- /* The $meta array is ONLY filled by hand-offs from `wpmu_activate_user|blog`. So this is how we check for these events. */
 
178
  /**/
179
  && $user_id && is_object ($user = new WP_User ($user_id)) && $user->ID && ($processed = true)) /* Process only once. */
180
  {
@@ -187,16 +192,16 @@ if (!function_exists ("ws_plugin__s2member_configure_user_registration"))
187
  if (!is_admin () && ($_POST["ws_plugin__s2member_custom_reg_field_s2member_custom"] || $_POST["ws_plugin__s2member_custom_reg_field_s2member_subscr_id"] || $_POST["ws_plugin__s2member_custom_reg_field_s2member_ccaps"] || $_POST["ws_plugin__s2member_custom_reg_field_s2member_auto_eot_time"] || $_POST["ws_plugin__s2member_custom_reg_field_s2member_notes"]))
188
  exit ("s2Member security violation. You attempted to POST variables that will NOT be trusted!");
189
  /**/
190
- $_pm = array_merge ((array)$_POST, (array)$meta); /* Merge these two data sources together now. However, ALWAYS after the security routine above ^. */
191
  /**/
192
  if (!is_admin () /* Only run this particular routine whenever a Member [1-4] is registering themselves with cookies. */
193
  && ($subscr_id = ws_plugin__s2member_decrypt ($_COOKIE["s2member_subscr_id"])) && preg_match ("/^" . preg_quote (preg_replace ("/\:([0-9]+)$/", "", $_SERVER["HTTP_HOST"]), "/") . "/i", ($custom = ws_plugin__s2member_decrypt ($_COOKIE["s2member_custom"]))) && preg_match ("/^[1-4](\:|$)([a-z_0-9,]+)?(\:)?([0-9]+ [A-Z])?$/", ($level = ws_plugin__s2member_decrypt ($_COOKIE["s2member_level"])))/**/
194
  && (!$usermeta = $wpdb->get_row ("SELECT `user_id` FROM `" . $wpdb->usermeta . "` WHERE `meta_key` = '" . $wpdb->prefix . "s2member_subscr_id' AND `meta_value` = '" . $wpdb->escape ($subscr_id) . "' LIMIT 1")))
195
  /* ^ This is for security ^ It checks the database to make sure the User/Member has not already registered in the past, with the same Paid Subscr. ID. */
196
  { /*
197
- This routine could be processed through `wp-login.php?action=register` - OR - through `wp-activate.php`.
 
198
  If processed through `wp-activate.php`, it could've originated inside the admin, via `user-new.php`.
199
- This may also be processed through BuddyPress, or another plugin calling `user_register`.
200
  */
201
  $processed = "yes"; /* Mark this as yes, to indicate that a routine was processed. */
202
  /**/
@@ -287,23 +292,32 @@ if (!function_exists ("ws_plugin__s2member_configure_user_registration"))
287
  /**/
288
  if (($transient = md5 ("s2member_transient_ipn_subscr_payment_" . $subscr_id)) && is_array ($subscr_payment = get_transient ($transient)))
289
  {
290
- $proxy = array ("s2member_paypal_notify" => "1", "s2member_paypal_proxy" => "s2member_transient_ipn_subscr_payment");
291
- ws_plugin__s2member_remote (add_query_arg ($proxy, get_bloginfo ("wpurl")), stripslashes_deep ($subscr_payment), array ("timeout" => 20));
292
- delete_transient($transient);
293
  }
294
  /**/
295
  setcookie ("s2member_signup_tracking", ws_plugin__s2member_encrypt ($subscr_id), time () + 31556926, "/");
296
  /**/
 
 
 
 
 
 
 
 
297
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
 
298
  do_action ("ws_plugin__s2member_during_configure_user_registration_front_side", get_defined_vars ());
299
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
300
  }
301
  /**/
302
  else if (!is_admin ()) /* Otherwise, if we are NOT inside the Dashboard during the creation of this account. */
303
  { /*
304
- This routine could be processed through `wp-login.php?action=register` - OR - through `wp-activate.php`.
 
305
  If processed through `wp-activate.php`, it could've originated inside the admin, via `user-new.php`.
306
- This may also be processed through BuddyPress, or another plugin calling `user_register`.
307
  */
308
  $processed = "yes"; /* Mark this as yes, to indicate that a routine was processed. */
309
  /**/
@@ -400,14 +414,23 @@ if (!function_exists ("ws_plugin__s2member_configure_user_registration"))
400
  /**/
401
  update_user_option ($user_id, "s2member_custom_fields", $fields);
402
  /**/
 
 
 
 
 
 
 
 
403
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
 
404
  do_action ("ws_plugin__s2member_during_configure_user_registration_front_side", get_defined_vars ());
405
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
406
  }
407
  /**/
408
  else if (is_admin () && $pagenow === "user-new.php") /* Else, if we're on this page. */
409
  { /*
410
- This routine can ONLY be processed through `user-new.php` inside the Dashboard.
411
  */
412
  $processed = "yes"; /* Mark this as yes, to indicate that a routine was processed. */
413
  /**/
@@ -495,6 +518,14 @@ if (!function_exists ("ws_plugin__s2member_configure_user_registration"))
495
  /**/
496
  update_user_option ($user_id, "s2member_custom_fields", $fields);
497
  /**/
 
 
 
 
 
 
 
 
498
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
499
  do_action ("ws_plugin__s2member_during_configure_user_registration_admin_side", get_defined_vars ());
500
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
@@ -502,8 +533,6 @@ if (!function_exists ("ws_plugin__s2member_configure_user_registration"))
502
  /**/
503
  if ($processed === "yes") /* If registration was processed by one of the routines above. */
504
  {
505
- ws_plugin__s2member_process_list_servers ($level, $email, $fname, $lname, $ip, $opt_in);
506
- /**/
507
  if ($urls = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["registration_notification_urls"])
508
  /**/
509
  foreach (preg_split ("/[\r\n\t]+/", $urls) as $url) /* Notify each of the urls. */
@@ -518,14 +547,21 @@ if (!function_exists ("ws_plugin__s2member_configure_user_registration"))
518
  if (($url = preg_replace ("/%%user_login%%/i", ws_plugin__s2member_esc_ds (urlencode ($login)), $url)))
519
  if (($url = preg_replace ("/%%user_pass%%/i", ws_plugin__s2member_esc_ds (urlencode ($pass)), $url)))
520
  if (($url = preg_replace ("/%%user_id%%/i", ws_plugin__s2member_esc_ds (urlencode ($user_id)), $url)))
521
- /**/
522
- if (($url = trim ($url))) /* Empty? */
523
- ws_plugin__s2member_remote($url);
 
 
 
 
 
 
524
  /**/
525
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["registration_notification_recipients"])
526
  {
527
  $msg = $sbj = "( s2Member / API Notification Email ) - Registration";
528
  $msg .= "\n\n"; /* Spacing in the message body. */
 
529
  $msg .= "role: %%role%%\n";
530
  $msg .= "level: %%level%%\n";
531
  $msg .= "user_first_name: %%user_first_name%%\n";
@@ -535,6 +571,11 @@ if (!function_exists ("ws_plugin__s2member_configure_user_registration"))
535
  $msg .= "user_login: %%user_login%%\n";
536
  $msg .= "user_pass: %%user_pass%%\n";
537
  $msg .= "user_id: %%user_id%%\n";
 
 
 
 
 
538
  $msg .= "cv0: %%cv0%%\n";
539
  $msg .= "cv1: %%cv1%%\n";
540
  $msg .= "cv2: %%cv2%%\n";
@@ -556,10 +597,16 @@ if (!function_exists ("ws_plugin__s2member_configure_user_registration"))
556
  if (($msg = preg_replace ("/%%user_login%%/i", ws_plugin__s2member_esc_ds ($login), $msg)))
557
  if (($msg = preg_replace ("/%%user_pass%%/i", ws_plugin__s2member_esc_ds ($pass), $msg)))
558
  if (($msg = preg_replace ("/%%user_id%%/i", ws_plugin__s2member_esc_ds ($user_id), $msg)))
559
- /**/
560
- foreach (ws_plugin__s2member_trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["registration_notification_recipients"])) as $recipient)
 
 
 
561
  /**/
562
- ($recipient) ? mail ($recipient, $sbj, apply_filters ("ws_plugin__s2member_registration_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
 
 
 
563
  }
564
  /**/
565
  if ($url = $GLOBALS["ws_plugin__s2member_registration_return_url"])
@@ -574,9 +621,18 @@ if (!function_exists ("ws_plugin__s2member_configure_user_registration"))
574
  if (($url = preg_replace ("/%%user_login%%/i", ws_plugin__s2member_esc_ds (urlencode ($login)), $url)))
575
  if (($url = preg_replace ("/%%user_pass%%/i", ws_plugin__s2member_esc_ds (urlencode ($pass)), $url)))
576
  if (($url = preg_replace ("/%%user_id%%/i", ws_plugin__s2member_esc_ds (urlencode ($user_id)), $url)))
577
- /**/
578
- if (($url = trim ($url))) /* Empty? ... Otherwise, re-fill. */
579
- $GLOBALS["ws_plugin__s2member_registration_return_url"] = $url;
 
 
 
 
 
 
 
 
 
580
  /**/
581
  setcookie ("s2member_subscr_id", "", time () + 31556926, "/");
582
  setcookie ("s2member_custom", "", time () + 31556926, "/");
18
  Attach to: add_filter("signup_hidden_fields");
19
 
20
  This can ONLY be fired through wp-signup.php on the front-side.
21
+ Or through `/register` via BuddyPress.
22
  */
23
  if (!function_exists ("ws_plugin__s2member_ms_process_signup_hidden_fields"))
24
  {
27
  do_action ("ws_plugin__s2member_before_ms_process_signup_hidden_fields", get_defined_vars ());
28
  /**/
29
  if (is_multisite ()) /* This event should ONLY be processed with Multisite Networking, on a Blog Farm. */
30
+ if (ws_plugin__s2member_is_multisite_farm () && is_main_site () && ( (preg_match ("/\/wp-signup\.php/", $_SERVER["REQUEST_URI"]) && $_POST["stage"] === "validate-user-signup") || (defined ("BP_VERSION") && preg_match ("/\/" . preg_quote (BP_REGISTER_SLUG, "/") . "/", $_SERVER["REQUEST_URI"]))))
31
  {
32
  foreach ((array)ws_plugin__s2member_trim_deep (stripslashes_deep ($_POST)) as $key => $value)
33
  if (preg_match ("/^ws_plugin__s2member_(custom_reg_field|user_new)_/", $key))
43
  /*
44
  Function that adds customs fields to $meta on signup.
45
  Attach to: add_filter("add_signup_meta");
46
+ Attach to: add_filter("bp_signup_usermeta");
47
 
48
  This can be fired through wp-signup.php on the front-side,
49
  or possibly through user-new.php in the admin.
59
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
60
  /**/
61
  if (is_multisite ()) /* This event should ONLY be processed with Multisite Networking. Either in the admin, or on a Blog Farm through wp-signup.php. */
62
+ if ((is_admin () && $pagenow === "user-new.php") || (ws_plugin__s2member_is_multisite_farm () && is_main_site () && ( (preg_match ("/\/wp-signup\.php/", $_SERVER["REQUEST_URI"]) && preg_match ("/^validate-(user|blog)-signup$/", $_POST["stage"])) || (defined ("BP_VERSION") && preg_match ("/\/" . preg_quote (BP_REGISTER_SLUG, "/") . "/", $_SERVER["REQUEST_URI"])))))
63
  {
64
  ws_plugin__s2member_email_config (); /* Configures From: header that will be used in notifications. */
65
  /**/
85
  ~ If they choose to bypass activation; an activation IS fired immediately. Otherwise, it's delayed.
86
  - via user-new.php.
87
 
88
+ So this function may get fired inside the admin panel ( `user-new.php` ).
89
+ Or also during an actual activation; through `wp-activate.php`.
90
+ Or also during an actual activation; through `/activate` via BuddyPress.
91
  */
92
  if (!function_exists ("ws_plugin__s2member_configure_user_on_ms_user_activation"))
93
  {
100
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
101
  /**/
102
  if (is_multisite ()) /* This event should ONLY be processed with Multisite Networking. */
103
+ if ((is_admin () && $pagenow === "user-new.php") || (!is_admin () && preg_match ("/\/wp-activate\.php/", $_SERVER["REQUEST_URI"])) || (!is_admin () && defined ("BP_VERSION") && preg_match ("/\/" . preg_quote (BP_ACTIVATION_SLUG, "/") . "/", $_SERVER["REQUEST_URI"])))
104
  {
105
  ws_plugin__s2member_configure_user_registration ($user_id, $password, $meta["s2member_ms_signup_meta"]);
106
  delete_user_meta ($user_id, "s2member_ms_signup_meta");
119
  ~ Actually they do; BUT it's blocked by the routine below.
120
  Which is good. A Super Admin should NOT trigger this event.
121
 
122
+ This function should ONLY be fired through `wp-activate.php`.
123
+ Or also through `/activate` via BuddyPress.
124
  */
125
  if (!function_exists ("ws_plugin__s2member_configure_user_on_ms_blog_activation"))
126
  {
131
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
132
  /**/
133
  if (is_multisite ()) /* This event should ONLY be processed with Multisite Networking. */
134
+ if ((!is_admin () && preg_match ("/\/wp-activate\.php/", $_SERVER["REQUEST_URI"])) || (!is_admin () && defined ("BP_VERSION") && preg_match ("/\/" . preg_quote (BP_ACTIVATION_SLUG, "/") . "/", $_SERVER["REQUEST_URI"])))
135
  {
136
  ws_plugin__s2member_configure_user_registration ($user_id, $password, $meta["s2member_ms_signup_meta"]);
137
  delete_user_meta ($user_id, "s2member_ms_signup_meta");
176
  && (is_array ($_POST = ws_plugin__s2member_trim_deep (stripslashes_deep ($_POST))) || is_array (ws_plugin__s2member_trim_deep (stripslashes_deep ($meta))))/**/
177
  /**/
178
  /* These negative matches are designed to prevent this routine from running under certain conditions; where we need to wait for `wpmu_activate_user|blog` instead. */
179
+ && ! (is_admin () && is_multisite () && $pagenow === "user-new.php" && isset ($_POST["noconfirmation"]) && is_super_admin () && func_num_args () !== 3)/**/
180
+ && ! (preg_match ("/\/wp-activate\.php/", $_SERVER["REQUEST_URI"]) && func_num_args () !== 3) /* If activating; we MUST have a $meta arg to proceed. */
181
+ && ! (defined ("BP_VERSION") && preg_match ("/\/" . preg_quote (BP_ACTIVATION_SLUG, "/") . "/", $_SERVER["REQUEST_URI"]) && func_num_args () !== 3)
182
+ /* The $meta argument is ONLY passed in by hand-offs from `wpmu_activate_user|blog`. So this is how we check for these events. */
183
  /**/
184
  && $user_id && is_object ($user = new WP_User ($user_id)) && $user->ID && ($processed = true)) /* Process only once. */
185
  {
192
  if (!is_admin () && ($_POST["ws_plugin__s2member_custom_reg_field_s2member_custom"] || $_POST["ws_plugin__s2member_custom_reg_field_s2member_subscr_id"] || $_POST["ws_plugin__s2member_custom_reg_field_s2member_ccaps"] || $_POST["ws_plugin__s2member_custom_reg_field_s2member_auto_eot_time"] || $_POST["ws_plugin__s2member_custom_reg_field_s2member_notes"]))
193
  exit ("s2Member security violation. You attempted to POST variables that will NOT be trusted!");
194
  /**/
195
+ $_pm = array_merge ((array)$_POST, (array)$meta); /* Merge these two data sources together now; ALWAYS after the security routine above ^. */
196
  /**/
197
  if (!is_admin () /* Only run this particular routine whenever a Member [1-4] is registering themselves with cookies. */
198
  && ($subscr_id = ws_plugin__s2member_decrypt ($_COOKIE["s2member_subscr_id"])) && preg_match ("/^" . preg_quote (preg_replace ("/\:([0-9]+)$/", "", $_SERVER["HTTP_HOST"]), "/") . "/i", ($custom = ws_plugin__s2member_decrypt ($_COOKIE["s2member_custom"]))) && preg_match ("/^[1-4](\:|$)([a-z_0-9,]+)?(\:)?([0-9]+ [A-Z])?$/", ($level = ws_plugin__s2member_decrypt ($_COOKIE["s2member_level"])))/**/
199
  && (!$usermeta = $wpdb->get_row ("SELECT `user_id` FROM `" . $wpdb->usermeta . "` WHERE `meta_key` = '" . $wpdb->prefix . "s2member_subscr_id' AND `meta_value` = '" . $wpdb->escape ($subscr_id) . "' LIMIT 1")))
200
  /* ^ This is for security ^ It checks the database to make sure the User/Member has not already registered in the past, with the same Paid Subscr. ID. */
201
  { /*
202
+ This routine could be processed through `wp-login.php?action=register`, `wp-activate.php`, or `/activate` via BuddyPress`.
203
+ This may also be processed through a standard BuddyPress installation, or another plugin calling `user_register`.
204
  If processed through `wp-activate.php`, it could've originated inside the admin, via `user-new.php`.
 
205
  */
206
  $processed = "yes"; /* Mark this as yes, to indicate that a routine was processed. */
207
  /**/
292
  /**/
293
  if (($transient = md5 ("s2member_transient_ipn_subscr_payment_" . $subscr_id)) && is_array ($subscr_payment = get_transient ($transient)))
294
  {
295
+ $proxy = array ("s2member_paypal_notify" => "1", "s2member_paypal_proxy" => "s2member_transient_ipn_subscr_payment", "s2member_paypal_proxy_verification" => ws_plugin__s2member_paypal_proxy_key_gen ());
296
+ ws_plugin__s2member_remote (add_query_arg (urlencode_deep ($proxy), get_bloginfo ("wpurl")), stripslashes_deep ($subscr_payment), array ("timeout" => 20));
297
+ delete_transient ($transient);
298
  }
299
  /**/
300
  setcookie ("s2member_signup_tracking", ws_plugin__s2member_encrypt ($subscr_id), time () + 31556926, "/");
301
  /**/
302
+ if ($level > 0) /* We ONLY process this if they are higher than Level#0. */
303
+ {
304
+ $pr_times = get_user_option ("s2member_paid_registration_times", $user_id);
305
+ $pr_times["level"] = (!$pr_times["level"]) ? time () : $pr_times["level"]; /* Preserve. */
306
+ $pr_times["level" . $level] = (!$pr_times["level" . $level]) ? time () : $pr_times["level" . $level];
307
+ update_user_option ($user_id, "s2member_paid_registration_times", $pr_times); /* Update now. */
308
+ }
309
+ /**/
310
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
311
+ do_action ("ws_plugin__s2member_during_configure_user_registration_front_side_paid", get_defined_vars ());
312
  do_action ("ws_plugin__s2member_during_configure_user_registration_front_side", get_defined_vars ());
313
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
314
  }
315
  /**/
316
  else if (!is_admin ()) /* Otherwise, if we are NOT inside the Dashboard during the creation of this account. */
317
  { /*
318
+ This routine could be processed through `wp-login.php?action=register`, `wp-activate.php`, or `/activate` via BuddyPress`.
319
+ This may also be processed through a standard BuddyPress installation, or another plugin calling `user_register`.
320
  If processed through `wp-activate.php`, it could've originated inside the admin, via `user-new.php`.
 
321
  */
322
  $processed = "yes"; /* Mark this as yes, to indicate that a routine was processed. */
323
  /**/
414
  /**/
415
  update_user_option ($user_id, "s2member_custom_fields", $fields);
416
  /**/
417
+ if ($level > 0) /* We ONLY process this if they are higher than Level#0. */
418
+ {
419
+ $pr_times = get_user_option ("s2member_paid_registration_times", $user_id);
420
+ $pr_times["level"] = (!$pr_times["level"]) ? time () : $pr_times["level"]; /* Preserve. */
421
+ $pr_times["level" . $level] = (!$pr_times["level" . $level]) ? time () : $pr_times["level" . $level];
422
+ update_user_option ($user_id, "s2member_paid_registration_times", $pr_times); /* Update now. */
423
+ }
424
+ /**/
425
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
426
+ do_action ("ws_plugin__s2member_during_configure_user_registration_front_side_free", get_defined_vars ());
427
  do_action ("ws_plugin__s2member_during_configure_user_registration_front_side", get_defined_vars ());
428
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
429
  }
430
  /**/
431
  else if (is_admin () && $pagenow === "user-new.php") /* Else, if we're on this page. */
432
  { /*
433
+ This routine can ONLY be processed through `user-new.php` inside the backend Dashboard.
434
  */
435
  $processed = "yes"; /* Mark this as yes, to indicate that a routine was processed. */
436
  /**/
518
  /**/
519
  update_user_option ($user_id, "s2member_custom_fields", $fields);
520
  /**/
521
+ if ($level > 0) /* We ONLY process this if they are higher than Level#0. */
522
+ {
523
+ $pr_times = get_user_option ("s2member_paid_registration_times", $user_id);
524
+ $pr_times["level"] = (!$pr_times["level"]) ? time () : $pr_times["level"]; /* Preserve. */
525
+ $pr_times["level" . $level] = (!$pr_times["level" . $level]) ? time () : $pr_times["level" . $level];
526
+ update_user_option ($user_id, "s2member_paid_registration_times", $pr_times); /* Update now. */
527
+ }
528
+ /**/
529
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
530
  do_action ("ws_plugin__s2member_during_configure_user_registration_admin_side", get_defined_vars ());
531
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
533
  /**/
534
  if ($processed === "yes") /* If registration was processed by one of the routines above. */
535
  {
 
 
536
  if ($urls = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["registration_notification_urls"])
537
  /**/
538
  foreach (preg_split ("/[\r\n\t]+/", $urls) as $url) /* Notify each of the urls. */
547
  if (($url = preg_replace ("/%%user_login%%/i", ws_plugin__s2member_esc_ds (urlencode ($login)), $url)))
548
  if (($url = preg_replace ("/%%user_pass%%/i", ws_plugin__s2member_esc_ds (urlencode ($pass)), $url)))
549
  if (($url = preg_replace ("/%%user_id%%/i", ws_plugin__s2member_esc_ds (urlencode ($user_id)), $url)))
550
+ {
551
+ if (is_array ($fields) && !empty ($fields))
552
+ foreach ($fields as $var => $val) /* Custom Registration Fields. */
553
+ if (! ($url = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", ws_plugin__s2member_esc_ds (urlencode (maybe_serialize ($val))), $url)))
554
+ break;
555
+ /**/
556
+ if (($url = trim (preg_replace ("/%%(.+?)%%/i", "", $url))))
557
+ ws_plugin__s2member_remote ($url);
558
+ }
559
  /**/
560
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["registration_notification_recipients"])
561
  {
562
  $msg = $sbj = "( s2Member / API Notification Email ) - Registration";
563
  $msg .= "\n\n"; /* Spacing in the message body. */
564
+ /**/
565
  $msg .= "role: %%role%%\n";
566
  $msg .= "level: %%level%%\n";
567
  $msg .= "user_first_name: %%user_first_name%%\n";
571
  $msg .= "user_login: %%user_login%%\n";
572
  $msg .= "user_pass: %%user_pass%%\n";
573
  $msg .= "user_id: %%user_id%%\n";
574
+ /**/
575
+ if (is_array ($fields) && !empty ($fields))
576
+ foreach ($fields as $var => $val)
577
+ $msg .= $var . ": %%" . $var . "%%\n";
578
+ /**/
579
  $msg .= "cv0: %%cv0%%\n";
580
  $msg .= "cv1: %%cv1%%\n";
581
  $msg .= "cv2: %%cv2%%\n";
597
  if (($msg = preg_replace ("/%%user_login%%/i", ws_plugin__s2member_esc_ds ($login), $msg)))
598
  if (($msg = preg_replace ("/%%user_pass%%/i", ws_plugin__s2member_esc_ds ($pass), $msg)))
599
  if (($msg = preg_replace ("/%%user_id%%/i", ws_plugin__s2member_esc_ds ($user_id), $msg)))
600
+ {
601
+ if (is_array ($fields) && !empty ($fields))
602
+ foreach ($fields as $var => $val) /* Custom Registration Fields. */
603
+ if (! ($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", ws_plugin__s2member_esc_ds (maybe_serialize ($val)), $msg)))
604
+ break;
605
  /**/
606
+ if (($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg))))
607
+ foreach (ws_plugin__s2member_trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["registration_notification_recipients"])) as $recipient)
608
+ ($recipient) ? wp_mail ($recipient, apply_filters ("ws_plugin__s2member_registration_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_registration_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
609
+ }
610
  }
611
  /**/
612
  if ($url = $GLOBALS["ws_plugin__s2member_registration_return_url"])
621
  if (($url = preg_replace ("/%%user_login%%/i", ws_plugin__s2member_esc_ds (urlencode ($login)), $url)))
622
  if (($url = preg_replace ("/%%user_pass%%/i", ws_plugin__s2member_esc_ds (urlencode ($pass)), $url)))
623
  if (($url = preg_replace ("/%%user_id%%/i", ws_plugin__s2member_esc_ds (urlencode ($user_id)), $url)))
624
+ {
625
+ if (is_array ($fields) && !empty ($fields))
626
+ foreach ($fields as $var => $val) /* Custom Registration Fields. */
627
+ if (! ($url = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", ws_plugin__s2member_esc_ds (urlencode (maybe_serialize ($val))), $url)))
628
+ break;
629
+ /**/
630
+ if (($url = trim ($url))) /* Preserve remaining Replacements. */
631
+ /* Because the parent routine may perform replacements too. */
632
+ $GLOBALS["ws_plugin__s2member_registration_return_url"] = $url;
633
+ }
634
+ /**/
635
+ ws_plugin__s2member_process_list_servers ($role, $level, $email, $fname, $lname, $ip, $opt_in, $user_id);
636
  /**/
637
  setcookie ("s2member_subscr_id", "", time () + 31556926, "/");
638
  setcookie ("s2member_custom", "", time () + 31556926, "/");
includes/functions/constants.inc.php CHANGED
@@ -12,7 +12,7 @@ If not, see: <http://www.gnu.org/licenses/>.
12
  Direct access denial.
13
  */
14
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
15
- exit("Do not access this file directly.");
16
  /*
17
  Define several API Constants for s2Member.
18
  Note that these are duplicated into the JavaScript API as well.
@@ -27,29 +27,29 @@ if (!function_exists ("ws_plugin__s2member_constants"))
27
  $links = ws_plugin__s2member_constant_links ();
28
  $level = ws_plugin__s2member_user_access_level ();
29
  $file_downloads = ws_plugin__s2member_user_downloads ();
30
- /**/
31
  $current_user = (is_user_logged_in ()) ? wp_get_current_user () : false;
32
- /**/
33
  $subscr_id = ($current_user) ? get_user_option ("s2member_subscr_id", $current_user->ID) : "";
34
  $custom = ($current_user) ? get_user_option ("s2member_custom", $current_user->ID) : "";
35
  $custom_fields = ($current_user) ? get_user_option ("s2member_custom_fields", $current_user->ID) : array ();
36
- /**/
37
  $login_redirection_url = ws_plugin__s2member_login_redirection_url ($current_user);
38
  /**/
39
- eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
40
  do_action ("ws_plugin__s2member_during_constants", get_defined_vars ());
41
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
42
  /**/
43
- define ("S2MEMBER_VERSION", ($c[] = WS_PLUGIN__S2MEMBER_VERSION)); /* Available since 3.0. */
44
  /**/
45
  define ("S2MEMBER_CURRENT_USER_IS_LOGGED_IN", ($c[] = (($current_user) ? true : false)));
46
- define ("S2MEMBER_CURRENT_USER_IS_LOGGED_IN_AS_MEMBER", ($c[] = (($current_user && $level >= 1) ? true : false)));
47
  define ("S2MEMBER_CURRENT_USER_ACCESS_LEVEL", ($c[] = (int)$level));
48
  define ("S2MEMBER_CURRENT_USER_ACCESS_LABEL", ($c[] = (string)$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $level . "_label"]));
49
  define ("S2MEMBER_CURRENT_USER_SUBSCR_ID", ($c[] = (($current_user) ? (($subscr_id) ? (string)$subscr_id : (string)$current_user->ID) : "")));
50
  define ("S2MEMBER_CURRENT_USER_CUSTOM", ($c[] = (string)$custom));
51
- define ("S2MEMBER_CURRENT_USER_REGISTRATION_TIME", ($c[] = (($current_user) ? (int)strtotime ($current_user->user_registered) : 0)));
52
- define ("S2MEMBER_CURRENT_USER_REGISTRATION_DAYS", ($c[] = (($current_user) ? (int)floor ((strtotime ("now") - strtotime ($current_user->user_registered)) / 86400) : 0)));
 
 
53
  define ("S2MEMBER_CURRENT_USER_DISPLAY_NAME", ($c[] = (($current_user) ? (string)$current_user->display_name : "")));
54
  define ("S2MEMBER_CURRENT_USER_FIRST_NAME", ($c[] = (($current_user) ? (string)$current_user->first_name : "")));
55
  define ("S2MEMBER_CURRENT_USER_LAST_NAME", ($c[] = (($current_user) ? (string)$current_user->last_name : "")));
@@ -60,7 +60,7 @@ if (!function_exists ("ws_plugin__s2member_constants"))
60
  define ("S2MEMBER_CURRENT_USER_FIELDS", ($c[] = (($current_user) ? json_encode (array_merge (array ("id" => S2MEMBER_CURRENT_USER_ID, "ip" => S2MEMBER_CURRENT_USER_IP, "email" => S2MEMBER_CURRENT_USER_EMAIL, "login" => S2MEMBER_CURRENT_USER_LOGIN, "first_name" => S2MEMBER_CURRENT_USER_FIRST_NAME, "last_name" => S2MEMBER_CURRENT_USER_LAST_NAME, "display_name" => S2MEMBER_CURRENT_USER_DISPLAY_NAME, "subscr_id" => S2MEMBER_CURRENT_USER_SUBSCR_ID, "custom" => S2MEMBER_CURRENT_USER_CUSTOM), (array)$custom_fields)) : json_encode (array ()))));
61
  /**/
62
  define ("S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED", ($c[] = (int)$file_downloads["allowed"]));
63
- define ("S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_IS_UNLIMITED", ($c[] = (($file_downloads["allowed"] >= 999999999) ? true : false)));
64
  define ("S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY", ($c[] = (int)$file_downloads["currently"]));
65
  define ("S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS", ($c[] = (int)$file_downloads["allowed_days"]));
66
  /**/
@@ -100,8 +100,9 @@ if (!function_exists ("ws_plugin__s2member_constants"))
100
  /**/
101
  define ("S2MEMBER_PAYPAL_NOTIFY_URL", ($c[] = get_bloginfo ("wpurl") . "/?s2member_paypal_notify=1"));
102
  define ("S2MEMBER_PAYPAL_RETURN_URL", ($c[] = get_bloginfo ("wpurl") . "/?s2member_paypal_return=1"));
103
- define ("S2MEMBER_PAYPAL_ENDPOINT", ($c[] = (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com")));
104
  define ("S2MEMBER_PAYPAL_BUSINESS", ($c[] = (string)$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"]));
 
105
  /**/
106
  define ("S2MEMBER_CURRENT_USER_VALUE_FOR_PP_ON0", ($c[] = ((S2MEMBER_CURRENT_USER_SUBSCR_ID) ? "Updating Subscr. ID" : "")));
107
  define ("S2MEMBER_CURRENT_USER_VALUE_FOR_PP_OS0", ($c[] = ((S2MEMBER_CURRENT_USER_VALUE_FOR_PP_ON0) ? S2MEMBER_CURRENT_USER_SUBSCR_ID : "")));
12
  Direct access denial.
13
  */
14
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
15
+ exit ("Do not access this file directly.");
16
  /*
17
  Define several API Constants for s2Member.
18
  Note that these are duplicated into the JavaScript API as well.
27
  $links = ws_plugin__s2member_constant_links ();
28
  $level = ws_plugin__s2member_user_access_level ();
29
  $file_downloads = ws_plugin__s2member_user_downloads ();
 
30
  $current_user = (is_user_logged_in ()) ? wp_get_current_user () : false;
 
31
  $subscr_id = ($current_user) ? get_user_option ("s2member_subscr_id", $current_user->ID) : "";
32
  $custom = ($current_user) ? get_user_option ("s2member_custom", $current_user->ID) : "";
33
  $custom_fields = ($current_user) ? get_user_option ("s2member_custom_fields", $current_user->ID) : array ();
34
+ $paid_registration_times = ($current_user) ? get_user_option ("s2member_paid_registration_times", $current_user->ID) : array ();
35
  $login_redirection_url = ws_plugin__s2member_login_redirection_url ($current_user);
36
  /**/
37
+ eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
38
  do_action ("ws_plugin__s2member_during_constants", get_defined_vars ());
39
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
40
  /**/
41
+ define ("S2MEMBER_VERSION", ($c[] = WS_PLUGIN__S2MEMBER_VERSION)); /* Since 3.0. */
42
  /**/
43
  define ("S2MEMBER_CURRENT_USER_IS_LOGGED_IN", ($c[] = (($current_user) ? true : false)));
44
+ define ("S2MEMBER_CURRENT_USER_IS_LOGGED_IN_AS_MEMBER", ($c[] = ( ($current_user && $level >= 1) ? true : false)));
45
  define ("S2MEMBER_CURRENT_USER_ACCESS_LEVEL", ($c[] = (int)$level));
46
  define ("S2MEMBER_CURRENT_USER_ACCESS_LABEL", ($c[] = (string)$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $level . "_label"]));
47
  define ("S2MEMBER_CURRENT_USER_SUBSCR_ID", ($c[] = (($current_user) ? (($subscr_id) ? (string)$subscr_id : (string)$current_user->ID) : "")));
48
  define ("S2MEMBER_CURRENT_USER_CUSTOM", ($c[] = (string)$custom));
49
+ define ("S2MEMBER_CURRENT_USER_REGISTRATION_TIME", ($c[] = ( ($current_user && $current_user->user_registered) ? (int)strtotime ($current_user->user_registered) : 0)));
50
+ define ("S2MEMBER_CURRENT_USER_PAID_REGISTRATION_TIME", ($c[] = ( ($current_user && (int)$paid_registration_times["level"]) ? (int)$paid_registration_times["level"] : 0)));
51
+ define ("S2MEMBER_CURRENT_USER_PAID_REGISTRATION_DAYS", ($c[] = ( ($current_user && (int)$paid_registration_times["level"]) ? (int)floor ((strtotime ("now") - (int)$paid_registration_times["level"]) / 86400) : 0)));
52
+ define ("S2MEMBER_CURRENT_USER_REGISTRATION_DAYS", ($c[] = ( ($current_user && $current_user->user_registered) ? (int)floor ((strtotime ("now") - strtotime ($current_user->user_registered)) / 86400) : 0)));
53
  define ("S2MEMBER_CURRENT_USER_DISPLAY_NAME", ($c[] = (($current_user) ? (string)$current_user->display_name : "")));
54
  define ("S2MEMBER_CURRENT_USER_FIRST_NAME", ($c[] = (($current_user) ? (string)$current_user->first_name : "")));
55
  define ("S2MEMBER_CURRENT_USER_LAST_NAME", ($c[] = (($current_user) ? (string)$current_user->last_name : "")));
60
  define ("S2MEMBER_CURRENT_USER_FIELDS", ($c[] = (($current_user) ? json_encode (array_merge (array ("id" => S2MEMBER_CURRENT_USER_ID, "ip" => S2MEMBER_CURRENT_USER_IP, "email" => S2MEMBER_CURRENT_USER_EMAIL, "login" => S2MEMBER_CURRENT_USER_LOGIN, "first_name" => S2MEMBER_CURRENT_USER_FIRST_NAME, "last_name" => S2MEMBER_CURRENT_USER_LAST_NAME, "display_name" => S2MEMBER_CURRENT_USER_DISPLAY_NAME, "subscr_id" => S2MEMBER_CURRENT_USER_SUBSCR_ID, "custom" => S2MEMBER_CURRENT_USER_CUSTOM), (array)$custom_fields)) : json_encode (array ()))));
61
  /**/
62
  define ("S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED", ($c[] = (int)$file_downloads["allowed"]));
63
+ define ("S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_IS_UNLIMITED", ($c[] = ( ($file_downloads["allowed"] >= 999999999) ? true : false)));
64
  define ("S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY", ($c[] = (int)$file_downloads["currently"]));
65
  define ("S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS", ($c[] = (int)$file_downloads["allowed_days"]));
66
  /**/
100
  /**/
101
  define ("S2MEMBER_PAYPAL_NOTIFY_URL", ($c[] = get_bloginfo ("wpurl") . "/?s2member_paypal_notify=1"));
102
  define ("S2MEMBER_PAYPAL_RETURN_URL", ($c[] = get_bloginfo ("wpurl") . "/?s2member_paypal_return=1"));
103
+ define ("S2MEMBER_PAYPAL_ENDPOINT", ($c[] = ( ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com")));
104
  define ("S2MEMBER_PAYPAL_BUSINESS", ($c[] = (string)$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"]));
105
+ define ("S2MEMBER_PAYPAL_PDT_IDENTITY_TOKEN", ($c[] = (string)$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_identity_token"]));
106
  /**/
107
  define ("S2MEMBER_CURRENT_USER_VALUE_FOR_PP_ON0", ($c[] = ((S2MEMBER_CURRENT_USER_SUBSCR_ID) ? "Updating Subscr. ID" : "")));
108
  define ("S2MEMBER_CURRENT_USER_VALUE_FOR_PP_OS0", ($c[] = ((S2MEMBER_CURRENT_USER_VALUE_FOR_PP_ON0) ? S2MEMBER_CURRENT_USER_SUBSCR_ID : "")));
includes/functions/css-js-w-globals.inc.php CHANGED
@@ -129,6 +129,8 @@ if (!function_exists ("ws_plugin__s2member_js_w_globals"))
129
  $g .= "S2MEMBER_CURRENT_USER_SUBSCR_ID = '" . ws_plugin__s2member_esc_sq (S2MEMBER_CURRENT_USER_SUBSCR_ID) . "',";
130
  $g .= "S2MEMBER_CURRENT_USER_CUSTOM = '" . ws_plugin__s2member_esc_sq (S2MEMBER_CURRENT_USER_CUSTOM) . "',";
131
  $g .= "S2MEMBER_CURRENT_USER_REGISTRATION_TIME = " . S2MEMBER_CURRENT_USER_REGISTRATION_TIME . ",";
 
 
132
  $g .= "S2MEMBER_CURRENT_USER_REGISTRATION_DAYS = " . S2MEMBER_CURRENT_USER_REGISTRATION_DAYS . ",";
133
  $g .= "S2MEMBER_CURRENT_USER_DISPLAY_NAME = '" . ws_plugin__s2member_esc_sq (S2MEMBER_CURRENT_USER_DISPLAY_NAME) . "',";
134
  $g .= "S2MEMBER_CURRENT_USER_FIRST_NAME = '" . ws_plugin__s2member_esc_sq (S2MEMBER_CURRENT_USER_FIRST_NAME) . "',";
129
  $g .= "S2MEMBER_CURRENT_USER_SUBSCR_ID = '" . ws_plugin__s2member_esc_sq (S2MEMBER_CURRENT_USER_SUBSCR_ID) . "',";
130
  $g .= "S2MEMBER_CURRENT_USER_CUSTOM = '" . ws_plugin__s2member_esc_sq (S2MEMBER_CURRENT_USER_CUSTOM) . "',";
131
  $g .= "S2MEMBER_CURRENT_USER_REGISTRATION_TIME = " . S2MEMBER_CURRENT_USER_REGISTRATION_TIME . ",";
132
+ $g .= "S2MEMBER_CURRENT_USER_PAID_REGISTRATION_TIME = " . S2MEMBER_CURRENT_USER_PAID_REGISTRATION_TIME . ",";
133
+ $g .= "S2MEMBER_CURRENT_USER_PAID_REGISTRATION_DAYS = " . S2MEMBER_CURRENT_USER_PAID_REGISTRATION_DAYS . ",";
134
  $g .= "S2MEMBER_CURRENT_USER_REGISTRATION_DAYS = " . S2MEMBER_CURRENT_USER_REGISTRATION_DAYS . ",";
135
  $g .= "S2MEMBER_CURRENT_USER_DISPLAY_NAME = '" . ws_plugin__s2member_esc_sq (S2MEMBER_CURRENT_USER_DISPLAY_NAME) . "',";
136
  $g .= "S2MEMBER_CURRENT_USER_FIRST_NAME = '" . ws_plugin__s2member_esc_sq (S2MEMBER_CURRENT_USER_FIRST_NAME) . "',";
includes/functions/file-download-access.inc.php CHANGED
@@ -12,7 +12,7 @@ If not, see: <http://www.gnu.org/licenses/>.
12
  Direct access denial.
13
  */
14
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
15
- exit("Do not access this file directly.");
16
  /*
17
  Function determines the max period in days for download access.
18
  Returns number of days, where 0 means no access to files has been allowed.
@@ -35,7 +35,7 @@ if (!function_exists ("ws_plugin__s2member_max_download_period"))
35
  if ($days = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_file_downloads_allowed_days"])
36
  $max = ($max < $days) ? $days : $max;
37
  /**/
38
- return apply_filters ("ws_plugin__s2member_max_download_period", (($max > 365) ? 365 : (int)$max), get_defined_vars ());
39
  }
40
  }
41
  /*
@@ -47,7 +47,7 @@ if (!function_exists ("ws_plugin__s2member_user_downloads"))
47
  {
48
  function ws_plugin__s2member_user_downloads ($not_counting_this_particular_file = false, $log = null)
49
  {
50
- eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
51
  do_action ("ws_plugin__s2member_before_user_downloads", get_defined_vars ());
52
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
53
  /**/
@@ -140,42 +140,42 @@ if (!function_exists ("ws_plugin__s2member_check_file_download_access"))
140
  /**/
141
  $_GET["s2member_file_download_key"] = (!$_GET["s2member_file_download_key"] && $_GET["s2member_free_file_download_key"]) ? $_GET["s2member_free_file_download_key"] : $_GET["s2member_file_download_key"];
142
  /**/
143
- if (!$excluded && (!$_GET["s2member_file_download_key"] || ($_GET["s2member_file_download_key"] && !($file_download_key_is_valid = ($_GET["s2member_file_download_key"] === ws_plugin__s2member_file_download_key ($_GET["s2member_file_download"]) || $_GET["s2member_file_download_key"] === ws_plugin__s2member_file_download_key ($_GET["s2member_file_download"], "cache-compatible"))))))
144
  {
145
  $_GET["s2member_file_download"] = trim ($_GET["s2member_file_download"], "/"); /* Trim slashes after Key comparison. */
146
  /**/
147
  if (!file_exists ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"] . "/" . $_GET["s2member_file_download"]))
148
  {
149
- header("HTTP/1.0 404 Not Found"); /* The file does NOT even exist. */
150
- exit("404: Sorry, file not found. Please contact Support for assistance.");
151
  }
152
  else if ($_GET["s2member_file_download_key"] && !$file_download_key_is_valid) /* Was an invalid Key passed in? */
153
  {
154
- header("HTTP/1.0 503 Service Temporarily Unavailable"); /* Invalid Download Keys are handled separately. */
155
- exit("503 ( Invalid Key ): Sorry, your access to this file has expired. Please contact Support for assistance.");
156
  }
157
  else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]) /* Is a Membership Options Page configured? */
158
  /* This file will be processed WITHOUT a Download Key, using Membership Level Access ( w/ possible Custom Capabilities ). */
159
  {
160
  if (($file_download_access_is_allowed = $min_level_4_downloads = ws_plugin__s2member_min_level_4_downloads ()) === false)
161
  {
162
- header("HTTP/1.0 503 Service Temporarily Unavailable"); /* File downloads are NOT yet configured? */
163
- exit("503: Sorry, file downloads are NOT enabled yet. Please contact Support for assistance. If you are the site owner, please configure `s2Member -> Download Options`.");
164
  }
165
  /**/
166
- else if (!($current_user = (is_user_logged_in ()) ? wp_get_current_user () : false) /* NOT logged in? */
167
- && wp_redirect (add_query_arg (array ("s2member_level_req" => (string)$min_level_4_downloads, "s2member_file_download_req" => $_GET["s2member_file_download"]), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]))) !== "nill")
168
  exit ();
169
  /**/
170
  else if ((!is_array ($file_downloads = ws_plugin__s2member_user_downloads ()) || !$file_downloads["allowed"] || !$file_downloads["allowed_days"])/**/
171
- && wp_redirect (add_query_arg (array ("s2member_file_download_req" => $_GET["s2member_file_download"]), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_limit_exceeded_page"]))) !== "nill")
172
  exit ();
173
  /**/
174
  else if (preg_match ("/^access[_\-]s2member[_\-]level([0-4])\//", $_GET["s2member_file_download"], $m))
175
  {
176
  $level_req = $m[1]; /* Which Level does this require? */
177
  if (!$current_user->has_cap ("access_s2member_level" . $level_req) /* Does the User have access to this Level? */
178
- && wp_redirect (add_query_arg (array ("s2member_level_req" => $level_req, "s2member_file_download_req" => $_GET["s2member_file_download"]), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]))) !== "nill")
179
  exit ();
180
  }
181
  /**/
@@ -183,7 +183,7 @@ if (!function_exists ("ws_plugin__s2member_check_file_download_access"))
183
  {
184
  $ccap_req = preg_replace ("/-/", "_", $m[1]); /* Which Capability does this require? */
185
  if (!$current_user->has_cap ("access_s2member_ccap_" . $ccap_req) /* Does the User have access to this Custom Capability? */
186
- && wp_redirect (add_query_arg (array ("s2member_ccap_req" => $ccap_req, "s2member_file_download_req" => $_GET["s2member_file_download"]), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]))) !== "nill")
187
  exit ();
188
  }
189
  /**/
@@ -196,7 +196,7 @@ if (!function_exists ("ws_plugin__s2member_check_file_download_access"))
196
  {
197
  if (strtotime ($file_download_access_log_entry["date"]) < strtotime ("-" . $max_days_logged . " days"))
198
  {
199
- unset($file_download_access_log[$file_download_access_log_entry_key]);
200
  $file_download_access_arc[] = $file_download_access_log_entry;
201
  }
202
  else if (strtotime ($file_download_access_log_entry["date"]) >= strtotime ("-" . $file_downloads["allowed_days"] . " days"))
@@ -209,7 +209,7 @@ if (!function_exists ("ws_plugin__s2member_check_file_download_access"))
209
  }
210
  /**/
211
  if (!$already_downloaded && $previous_file_downloads >= $file_downloads["allowed"] /* They have NOT already downloaded this file, and they're over their limit. */
212
- && wp_redirect (add_query_arg (array ("s2member_file_download_req" => $_GET["s2member_file_download"]), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_limit_exceeded_page"]))) !== "nill")
213
  exit ();
214
  /**/
215
  if (!$already_downloaded) /* Only add this file to the log if they have not already downloaded it. */
@@ -225,8 +225,8 @@ if (!function_exists ("ws_plugin__s2member_check_file_download_access"))
225
  /**/
226
  if (!file_exists ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"] . "/" . $_GET["s2member_file_download"]))
227
  {
228
- header("HTTP/1.0 404 Not Found"); /* The file does NOT even exist. */
229
- exit("404: Sorry, file not found. Please contact Support for assistance.");
230
  }
231
  }
232
  /*
@@ -235,35 +235,47 @@ if (!function_exists ("ws_plugin__s2member_check_file_download_access"))
235
  $mimetypes = parse_ini_file (dirname (dirname (dirname (__FILE__))) . "/includes/mime-types.ini");
236
  $pathinfo = pathinfo ($file = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"] . "/" . $_GET["s2member_file_download"]);
237
  $extension = strtolower ($pathinfo["extension"]); /* Convert file extension to lowercase format for MIME type lookup. */
238
- $inline = (in_array ($extension, preg_split ("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_inline_extensions"]))) ? true : false;
239
  $mimetype = ($mimetypes[$extension]) ? $mimetypes[$extension] : "application/octet-stream"; /* Lookup MIME type. */
240
  $basename = $pathinfo["basename"]; /* The actual file name, including its extension. */
241
  $length = filesize ($file); /* The overall file size, in bytes. */
242
  /**/
243
- eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
244
  do_action ("ws_plugin__s2member_during_file_download_access", get_defined_vars ());
245
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
246
  /*
247
- Now send the file to the browser.
248
- Be sure to turn off output compression.
249
  */
250
- set_time_limit(0); /* Make time. */
251
  ini_set ("zlib.output_compression", 0);
252
  /**/
253
- header("Content-Encoding: none");
254
- header("Content-Type: " . $mimetype);
255
- header("Content-Length: " . $length);
 
256
  /**/
257
  if (!$inline) /* If not inline, we default to serving the file as an attachment. */
258
- header('Content-Disposition: attachment; filename="' . $basename . '"');
259
  /**/
260
- header("Expires: " . gmdate ("D, d M Y H:i:s", strtotime ("-1 week")) . " GMT");
261
- header("Last-Modified: " . gmdate ("D, d M Y H:i:s") . " GMT");
262
- header("Cache-Control: no-cache, must-revalidate, max-age=0");
263
  header ("Cache-Control: post-check=0, pre-check=0", false);
264
- header("Pragma: no-cache");
265
  /**/
266
- ob_clean () . flush () . readfile ($file);
 
 
 
 
 
 
 
 
 
 
 
267
  /**/
268
  exit ();
269
  }
@@ -283,7 +295,7 @@ if (!function_exists ("ws_plugin__s2member_file_download_key"))
283
  {
284
  function ws_plugin__s2member_file_download_key ($file = FALSE, $cache_compatible = FALSE)
285
  {
286
- eval('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
287
  do_action ("ws_plugin__s2member_before_file_download_key", get_defined_vars ());
288
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
289
  /**/
@@ -291,7 +303,7 @@ if (!function_exists ("ws_plugin__s2member_file_download_key"))
291
  $key = md5 (ws_plugin__s2member_xencrypt ($salt)); /* Creates a site-specific/xencrytped hash of the salt.
292
  /**/
293
  if (!$cache_compatible) /* Disallow caching. */
294
- ws_plugin__s2member_nocache_constants(true);
295
  /**/
296
  return apply_filters ("ws_plugin__s2member_file_download_key", $key, get_defined_vars ());
297
  }
12
  Direct access denial.
13
  */
14
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
15
+ exit ("Do not access this file directly.");
16
  /*
17
  Function determines the max period in days for download access.
18
  Returns number of days, where 0 means no access to files has been allowed.
35
  if ($days = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_file_downloads_allowed_days"])
36
  $max = ($max < $days) ? $days : $max;
37
  /**/
38
+ return apply_filters ("ws_plugin__s2member_max_download_period", ( ($max > 365) ? 365 : (int)$max), get_defined_vars ());
39
  }
40
  }
41
  /*
47
  {
48
  function ws_plugin__s2member_user_downloads ($not_counting_this_particular_file = false, $log = null)
49
  {
50
+ eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
51
  do_action ("ws_plugin__s2member_before_user_downloads", get_defined_vars ());
52
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
53
  /**/
140
  /**/
141
  $_GET["s2member_file_download_key"] = (!$_GET["s2member_file_download_key"] && $_GET["s2member_free_file_download_key"]) ? $_GET["s2member_free_file_download_key"] : $_GET["s2member_file_download_key"];
142
  /**/
143
+ if (!$excluded && (!$_GET["s2member_file_download_key"] || ($_GET["s2member_file_download_key"] && ! ($file_download_key_is_valid = ($_GET["s2member_file_download_key"] === ws_plugin__s2member_file_download_key ($_GET["s2member_file_download"]) || $_GET["s2member_file_download_key"] === ws_plugin__s2member_file_download_key ($_GET["s2member_file_download"], "cache-compatible"))))))
144
  {
145
  $_GET["s2member_file_download"] = trim ($_GET["s2member_file_download"], "/"); /* Trim slashes after Key comparison. */
146
  /**/
147
  if (!file_exists ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"] . "/" . $_GET["s2member_file_download"]))
148
  {
149
+ header ("HTTP/1.0 404 Not Found"); /* The file does NOT even exist. */
150
+ exit ("404: Sorry, file not found. Please contact Support for assistance.");
151
  }
152
  else if ($_GET["s2member_file_download_key"] && !$file_download_key_is_valid) /* Was an invalid Key passed in? */
153
  {
154
+ header ("HTTP/1.0 503 Service Temporarily Unavailable"); /* Invalid Download Keys are handled separately. */
155
+ exit ("503 ( Invalid Key ): Sorry, your access to this file has expired. Please contact Support for assistance.");
156
  }
157
  else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]) /* Is a Membership Options Page configured? */
158
  /* This file will be processed WITHOUT a Download Key, using Membership Level Access ( w/ possible Custom Capabilities ). */
159
  {
160
  if (($file_download_access_is_allowed = $min_level_4_downloads = ws_plugin__s2member_min_level_4_downloads ()) === false)
161
  {
162
+ header ("HTTP/1.0 503 Service Temporarily Unavailable"); /* File downloads are NOT yet configured? */
163
+ exit ("503: Sorry, file downloads are NOT enabled yet. Please contact Support for assistance. If you are the site owner, please configure `s2Member -> Download Options`.");
164
  }
165
  /**/
166
+ else if (! ($current_user = (is_user_logged_in ()) ? wp_get_current_user () : false) /* NOT logged in? */
167
+ && wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "file-" . $_GET["s2member_file_download"], "s2member_level_req" => (string)$min_level_4_downloads)), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]))) !== "nill")
168
  exit ();
169
  /**/
170
  else if ((!is_array ($file_downloads = ws_plugin__s2member_user_downloads ()) || !$file_downloads["allowed"] || !$file_downloads["allowed_days"])/**/
171
+ && wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "file-" . $_GET["s2member_file_download"])), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_limit_exceeded_page"]))) !== "nill")
172
  exit ();
173
  /**/
174
  else if (preg_match ("/^access[_\-]s2member[_\-]level([0-4])\//", $_GET["s2member_file_download"], $m))
175
  {
176
  $level_req = $m[1]; /* Which Level does this require? */
177
  if (!$current_user->has_cap ("access_s2member_level" . $level_req) /* Does the User have access to this Level? */
178
+ && wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "file-" . $_GET["s2member_file_download"], "s2member_level_req" => $level_req)), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]))) !== "nill")
179
  exit ();
180
  }
181
  /**/
183
  {
184
  $ccap_req = preg_replace ("/-/", "_", $m[1]); /* Which Capability does this require? */
185
  if (!$current_user->has_cap ("access_s2member_ccap_" . $ccap_req) /* Does the User have access to this Custom Capability? */
186
+ && wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "file-" . $_GET["s2member_file_download"], "s2member_ccap_req" => $ccap_req)), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]))) !== "nill")
187
  exit ();
188
  }
189
  /**/
196
  {
197
  if (strtotime ($file_download_access_log_entry["date"]) < strtotime ("-" . $max_days_logged . " days"))
198
  {
199
+ unset ($file_download_access_log[$file_download_access_log_entry_key]);
200
  $file_download_access_arc[] = $file_download_access_log_entry;
201
  }
202
  else if (strtotime ($file_download_access_log_entry["date"]) >= strtotime ("-" . $file_downloads["allowed_days"] . " days"))
209
  }
210
  /**/
211
  if (!$already_downloaded && $previous_file_downloads >= $file_downloads["allowed"] /* They have NOT already downloaded this file, and they're over their limit. */
212
+ && wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "file-" . $_GET["s2member_file_download"])), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_limit_exceeded_page"]))) !== "nill")
213
  exit ();
214
  /**/
215
  if (!$already_downloaded) /* Only add this file to the log if they have not already downloaded it. */
225
  /**/
226
  if (!file_exists ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"] . "/" . $_GET["s2member_file_download"]))
227
  {
228
+ header ("HTTP/1.0 404 Not Found"); /* The file does NOT even exist. */
229
+ exit ("404: Sorry, file not found. Please contact Support for assistance.");
230
  }
231
  }
232
  /*
235
  $mimetypes = parse_ini_file (dirname (dirname (dirname (__FILE__))) . "/includes/mime-types.ini");
236
  $pathinfo = pathinfo ($file = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"] . "/" . $_GET["s2member_file_download"]);
237
  $extension = strtolower ($pathinfo["extension"]); /* Convert file extension to lowercase format for MIME type lookup. */
238
+ $inline = ($_GET["s2member_file_inline"] || in_array ($extension, preg_split ("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_inline_extensions"]))) ? true : false;
239
  $mimetype = ($mimetypes[$extension]) ? $mimetypes[$extension] : "application/octet-stream"; /* Lookup MIME type. */
240
  $basename = $pathinfo["basename"]; /* The actual file name, including its extension. */
241
  $length = filesize ($file); /* The overall file size, in bytes. */
242
  /**/
243
+ eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
244
  do_action ("ws_plugin__s2member_during_file_download_access", get_defined_vars ());
245
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
246
  /*
247
+ Send the file to the browser in chunks ( in support of larger files ).
248
+ Be sure to turn off output compression, as it DOES get in the way.
249
  */
250
+ set_time_limit (0); /* Unlimited. */
251
  ini_set ("zlib.output_compression", 0);
252
  /**/
253
+ header ("Accept-Ranges: none");
254
+ header ("Content-Encoding: none");
255
+ header ("Content-Type: " . $mimetype);
256
+ header ("Content-Length: " . $length);
257
  /**/
258
  if (!$inline) /* If not inline, we default to serving the file as an attachment. */
259
+ header ('Content-Disposition: attachment; filename="' . $basename . '"');
260
  /**/
261
+ header ("Expires: " . gmdate ("D, d M Y H:i:s", strtotime ("-1 week")) . " GMT");
262
+ header ("Last-Modified: " . gmdate ("D, d M Y H:i:s") . " GMT");
263
+ header ("Cache-Control: no-cache, must-revalidate, max-age=0");
264
  header ("Cache-Control: post-check=0, pre-check=0", false);
265
+ header ("Pragma: no-cache");
266
  /**/
267
+ if ($length && ($stream = fopen ($file, "rb")))
268
+ {
269
+ @ob_end_clean (); /* End/clean any existing output buffer. */
270
+ /**/
271
+ while (strlen ($data = stream_get_contents ($stream, 2097152)))
272
+ {
273
+ echo $data; /* In 2MB chunks. */
274
+ @ob_end_flush () . @flush ();
275
+ }
276
+ /**/
277
+ fclose ($stream);
278
+ }
279
  /**/
280
  exit ();
281
  }
295
  {
296
  function ws_plugin__s2member_file_download_key ($file = FALSE, $cache_compatible = FALSE)
297
  {
298
+ eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
299
  do_action ("ws_plugin__s2member_before_file_download_key", get_defined_vars ());
300
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
301
  /**/
303
  $key = md5 (ws_plugin__s2member_xencrypt ($salt)); /* Creates a site-specific/xencrytped hash of the salt.
304
  /**/
305
  if (!$cache_compatible) /* Disallow caching. */
306
+ ws_plugin__s2member_nocache_constants (true);
307
  /**/
308
  return apply_filters ("ws_plugin__s2member_file_download_key", $key, get_defined_vars ());
309
  }
includes/functions/force-ssl.inc.php CHANGED
@@ -92,7 +92,7 @@ if (!function_exists ("ws_plugin__s2member_check_force_ssl"))
92
  if (_ws_plugin__s2member_force_ssl_port && _ws_plugin__s2member_force_ssl_host && _ws_plugin__s2member_force_ssl_host_port) /* Do we ALSO need port conversions? */
93
  $c = preg_replace ("/\/" . preg_quote (_ws_plugin__s2member_force_ssl_host, "/") . "(\:[0-9]+)?\//i", "/" . _ws_plugin__s2member_force_ssl_host_port . "/", $c);
94
  /**/
95
- return $c; /* Return string with conversions. */
96
  }
97
  /**/
98
  ob_start ("_ws_plugin__s2member_force_ssl_buffer");
92
  if (_ws_plugin__s2member_force_ssl_port && _ws_plugin__s2member_force_ssl_host && _ws_plugin__s2member_force_ssl_host_port) /* Do we ALSO need port conversions? */
93
  $c = preg_replace ("/\/" . preg_quote (_ws_plugin__s2member_force_ssl_host, "/") . "(\:[0-9]+)?\//i", "/" . _ws_plugin__s2member_force_ssl_host_port . "/", $c);
94
  /**/
95
+ return (strtolower ($m[1]) === "link" && preg_match ("/['\"]alternate['\"]/i", $m[0])) ? $m[0] : $c; /* Return string with conversions. */
96
  }
97
  /**/
98
  ob_start ("_ws_plugin__s2member_force_ssl_buffer");
includes/functions/ip-restrictions.inc.php CHANGED
@@ -47,7 +47,7 @@ if (!function_exists ("ws_plugin__s2member_ip_restrictions_ok"))
47
  /**/
48
  if (get_transient ($transient_security_breach)) /* Has this restriction already been breached? */
49
  {
50
- ws_plugin__s2member_nocache_constants (true) . wp_clear_auth_cookie ();
51
  /**/
52
  do_action ("ws_plugin__s2member_during_ip_restrictions_ok_no", get_defined_vars ());
53
  /**/
@@ -61,9 +61,10 @@ if (!function_exists ("ws_plugin__s2member_ip_restrictions_ok"))
61
  }
62
  else if (count ($entries) > $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction"])
63
  {
64
- ws_plugin__s2member_nocache_constants (true) . wp_clear_auth_cookie ();
65
  /**/
66
- set_transient ($transient_security_breach, 1, $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction_time"]);
 
67
  /**/
68
  do_action ("ws_plugin__s2member_during_ip_restrictions_ok_no", get_defined_vars ());
69
  /**/
@@ -75,7 +76,7 @@ if (!function_exists ("ws_plugin__s2member_ip_restrictions_ok"))
75
  /**/
76
  exit ();
77
  }
78
- else /* OK, this looks legitimate. Continue updating the Transient array of IP addresses. */
79
  {
80
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
81
  do_action ("ws_plugin__s2member_during_ip_restrictions_ok_yes", get_defined_vars ());
47
  /**/
48
  if (get_transient ($transient_security_breach)) /* Has this restriction already been breached? */
49
  {
50
+ ws_plugin__s2member_nocache_constants(true) . wp_clear_auth_cookie ();
51
  /**/
52
  do_action ("ws_plugin__s2member_during_ip_restrictions_ok_no", get_defined_vars ());
53
  /**/
61
  }
62
  else if (count ($entries) > $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction"])
63
  {
64
+ ws_plugin__s2member_nocache_constants(true) . wp_clear_auth_cookie ();
65
  /**/
66
+ set_transient ($transient_security_breach, 1, /* Lock down. */
67
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["max_ip_restriction_time"]);
68
  /**/
69
  do_action ("ws_plugin__s2member_during_ip_restrictions_ok_no", get_defined_vars ());
70
  /**/
76
  /**/
77
  exit ();
78
  }
79
+ else /* OK, this looks legitimate. Apply Filters here and return true. */
80
  {
81
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
82
  do_action ("ws_plugin__s2member_during_ip_restrictions_ok_yes", get_defined_vars ());
includes/functions/is-systematic.inc.php CHANGED
@@ -12,7 +12,7 @@ If not, see: <http://www.gnu.org/licenses/>.
12
  Direct access denial.
13
  */
14
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
15
- exit("Do not access this file directly.");
16
  /*
17
  Function that determines whether we are on a Systematic Use Page.
18
  */
@@ -30,15 +30,15 @@ if (!function_exists ("ws_plugin__s2member_is_systematic_use_page"))
30
  {
31
  return ($is_systematic = apply_filters ("ws_plugin__s2member_is_systematic_use_page", true, get_defined_vars ()));
32
  }
33
- else if (preg_match ("/^CLI$/i", PHP_SAPI))
34
  {
35
  return ($is_systematic = apply_filters ("ws_plugin__s2member_is_systematic_use_page", true, get_defined_vars ()));
36
  }
37
- else if ($_SERVER["REMOTE_ADDR"] === $_SERVER["SERVER_ADDR"] && !preg_match ("/^localhost(\:[0-9]+)?$/i", $_SERVER["HTTP_HOST"]))
38
  {
39
  return ($is_systematic = apply_filters ("ws_plugin__s2member_is_systematic_use_page", true, get_defined_vars ()));
40
  }
41
- else if (preg_match ("/\/wp-(signup|register|activate|login)\.php/", $_SERVER["REQUEST_URI"]))
42
  {
43
  return ($is_systematic = apply_filters ("ws_plugin__s2member_is_systematic_use_page", true, get_defined_vars ()));
44
  }
@@ -85,7 +85,7 @@ if (!function_exists ("ws_plugin__s2member_is_systematic_use_specific_page"))
85
  {
86
  return ($is_systematic = apply_filters ("ws_plugin__s2member_is_systematic_use_specific_page", true, get_defined_vars ()));
87
  }
88
- else if ($uri && preg_match ("/\/wp-(signup|register|activate|login)\.php/", $uri))
89
  {
90
  return ($is_systematic = apply_filters ("ws_plugin__s2member_is_systematic_use_specific_page", true, get_defined_vars ()));
91
  }
12
  Direct access denial.
13
  */
14
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
15
+ exit ("Do not access this file directly.");
16
  /*
17
  Function that determines whether we are on a Systematic Use Page.
18
  */
30
  {
31
  return ($is_systematic = apply_filters ("ws_plugin__s2member_is_systematic_use_page", true, get_defined_vars ()));
32
  }
33
+ else if (preg_match ("/^CLI$/i", PHP_SAPI)) /* CLI = Command Line. Normally indicates a running cron job. */
34
  {
35
  return ($is_systematic = apply_filters ("ws_plugin__s2member_is_systematic_use_page", true, get_defined_vars ()));
36
  }
37
+ else if ($_SERVER["REMOTE_ADDR"] === $_SERVER["SERVER_ADDR"] && !preg_match ("/^localhost(\:[0-9]+)?$/i", $_SERVER["HTTP_HOST"]) && (!defined ("LOCALHOST") || !LOCALHOST))
38
  {
39
  return ($is_systematic = apply_filters ("ws_plugin__s2member_is_systematic_use_page", true, get_defined_vars ()));
40
  }
41
+ else if (preg_match ("/\/wp-(signup|register|activate|login)\.php/", $_SERVER["REQUEST_URI"]) || (defined ("BP_VERSION") && preg_match ("/\/(" . preg_quote (BP_REGISTER_SLUG, "/") . "|" . preg_quote (BP_ACTIVATION_SLUG, "/") . ")/", $_SERVER["REQUEST_URI"])))
42
  {
43
  return ($is_systematic = apply_filters ("ws_plugin__s2member_is_systematic_use_page", true, get_defined_vars ()));
44
  }
85
  {
86
  return ($is_systematic = apply_filters ("ws_plugin__s2member_is_systematic_use_specific_page", true, get_defined_vars ()));
87
  }
88
+ else if ($uri && (preg_match ("/\/wp-(signup|register|activate|login)\.php/", $uri) || (defined ("BP_VERSION") && preg_match ("/\/(" . preg_quote (BP_REGISTER_SLUG, "/") . "|" . preg_quote (BP_ACTIVATION_SLUG, "/") . ")/", $_SERVER["REQUEST_URI"]))))
89
  {
90
  return ($is_systematic = apply_filters ("ws_plugin__s2member_is_systematic_use_specific_page", true, get_defined_vars ()));
91
  }
includes/functions/list-servers.inc.php CHANGED
@@ -35,7 +35,7 @@ Function that process list server integrations for s2Member.
35
  */
36
  if (!function_exists ("ws_plugin__s2member_process_list_servers"))
37
  {
38
- function ws_plugin__s2member_process_list_servers ($level = FALSE, $email = FALSE, $fname = FALSE, $lname = FALSE, $ip = FALSE, $opt_in = FALSE)
39
  {
40
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
41
  do_action ("ws_plugin__s2member_before_process_list_servers", get_defined_vars ());
@@ -52,15 +52,13 @@ if (!function_exists ("ws_plugin__s2member_process_list_servers"))
52
  $MCAPI = new NC_MCAPI ($mailchimp_api_key); /* MailChimp® API class. */
53
  /**/
54
  foreach (preg_split ("/[\r\n\t\s;,]+/", $mailchimp_list_ids) as $mailchimp_list_id)
55
- $MCAPI->listSubscribe ($mailchimp_list_id, $email, array ("FNAME" => $fname, "LNAME" => $lname, "OPTINIP" => $ip));
56
  }
57
  /**/
58
  if (($aweber_list_ids = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $level . "_aweber_list_ids"]))
59
  {
60
  foreach (preg_split ("/[\r\n\t\s;,]+/", $aweber_list_ids) as $aweber_list_id)
61
- @mail ($aweber_list_id . "@aweber.com", "s2Member Subscription Request",/**/
62
- "s2Member Subscription Request\ns2Member w/ PayPal Email ID\nEMail Address: " . $email . "\nBuyer: " . $fname . " " . $lname . "\nFull Name: " . $fname . " " . $lname . "\nFirst Name: " . $fname . "\nLast Name: " . $lname . "\nIP Address: " . $ip . "\nLevel: " . $level . "\n - end.",/**/
63
- "From: \"" . preg_replace ("/\"/", "", $fname . " " . $lname) . "\" <" . $email . ">\r\nContent-Type: text/plain; charset=utf-8");
64
  }
65
  /**/
66
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
35
  */
36
  if (!function_exists ("ws_plugin__s2member_process_list_servers"))
37
  {
38
+ function ws_plugin__s2member_process_list_servers ($role = FALSE, $level = FALSE, $email = FALSE, $fname = FALSE, $lname = FALSE, $ip = FALSE, $opt_in = FALSE, $user_id = FALSE)
39
  {
40
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
41
  do_action ("ws_plugin__s2member_before_process_list_servers", get_defined_vars ());
52
  $MCAPI = new NC_MCAPI ($mailchimp_api_key); /* MailChimp® API class. */
53
  /**/
54
  foreach (preg_split ("/[\r\n\t\s;,]+/", $mailchimp_list_ids) as $mailchimp_list_id)
55
+ $MCAPI->listSubscribe ($mailchimp_list_id, $email, apply_filters ("ws_plugin__s2member_mailchimp_array", array ("FNAME" => $fname, "LNAME" => $lname, "OPTINIP" => $ip), get_defined_vars ()));
56
  }
57
  /**/
58
  if (($aweber_list_ids = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $level . "_aweber_list_ids"]))
59
  {
60
  foreach (preg_split ("/[\r\n\t\s;,]+/", $aweber_list_ids) as $aweber_list_id)
61
+ wp_mail ($aweber_list_id . "@aweber.com", apply_filters ("ws_plugin__s2member_aweber_sbj", "s2Member Subscription Request", get_defined_vars ()), apply_filters ("ws_plugin__s2member_aweber_msg", "s2Member Subscription Request\ns2Member w/ PayPal Email ID\nEMail Address: " . $email . "\nBuyer: " . $fname . " " . $lname . "\nFull Name: " . $fname . " " . $lname . "\nFirst Name: " . $fname . "\nLast Name: " . $lname . "\nIP Address: " . $ip . "\nUser ID: " . $user_id . "\nRole: " . $role . "\nLevel: " . $level . "\n - end.", get_defined_vars ()), "From: \"" . preg_replace ("/\"/", "", $fname . " " . $lname) . "\" <" . $email . ">\r\nContent-Type: text/plain; charset=utf-8");
 
 
62
  }
63
  /**/
64
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
includes/functions/login-redirection.inc.php CHANGED
@@ -29,24 +29,26 @@ if (!function_exists ("ws_plugin__s2member_login_redirect"))
29
  /* This additional check was added in case wp_signon() fires this event with empty $_POST credentials.
30
  In this rare case, we can check to see if WordPress® is remembering a previously logged in User. */
31
  /**/
32
- if (!is_object ($user = new WP_User ($username)) || ! ($user_id = $user->ID) || !$user->has_cap ("edit_posts"))
 
33
  {
34
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
35
  do_action ("ws_plugin__s2member_during_login_redirect", get_defined_vars ());
36
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
37
  /**/
38
- if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_password"] && function_exists ("ws_plugin__s2member_generate_password"))
39
  {
40
  delete_user_setting ("default_password_nag"); /* setcookie() */
41
  update_user_option ($user_id, "default_password_nag", false, true);
42
  }
43
  /**/
44
- if (strtolower ($username) === "demo" || ws_plugin__s2member_ip_restrictions_ok ($_SERVER["REMOTE_ADDR"], strtolower ($username)))
45
  {
46
  if ($special_redirection_url = ws_plugin__s2member_login_redirection_url ($user))
47
- wp_redirect ($special_redirection_url);
48
  /**/
49
- else wp_redirect (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"]));
 
50
  }
51
  /**/
52
  exit ();
@@ -90,10 +92,12 @@ if (!function_exists ("ws_plugin__s2member_fill_login_redirect_rc_vars"))
90
  $user_login = (is_object ($user)) ? strtolower ($user->user_login) : "";
91
  $user_id = (is_object ($user)) ? (string)$user->ID : "";
92
  $user_level = (string)ws_plugin__s2member_user_access_level ($user);
 
93
  /**/
94
  $url = preg_replace ("/%%current_user_login%%/i", ws_plugin__s2member_esc_ds ($user_login), $url);
95
  $url = preg_replace ("/%%current_user_id%%/i", ws_plugin__s2member_esc_ds ($user_id), $url);
96
  $url = preg_replace ("/%%current_user_level%%/i", ws_plugin__s2member_esc_ds ($user_level), $url);
 
97
  /**/
98
  return apply_filters ("ws_plugin__s2member_fill_login_redirect_rc_vars", $url, get_defined_vars ());
99
  }
29
  /* This additional check was added in case wp_signon() fires this event with empty $_POST credentials.
30
  In this rare case, we can check to see if WordPress® is remembering a previously logged in User. */
31
  /**/
32
+ if (!is_object ($user = new WP_User ($username)) || ! ($user_id = $user->ID) || !$user->has_cap ("edit_posts")/**/
33
+ /* Now give Filters a chance also. */ || apply_filters ("ws_plugin__s2member_login_redirect", false, get_defined_vars ()))
34
  {
35
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
36
  do_action ("ws_plugin__s2member_during_login_redirect", get_defined_vars ());
37
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
38
  /**/
39
+ if ($username && $user && $user_id && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_password"] && function_exists ("ws_plugin__s2member_generate_password"))
40
  {
41
  delete_user_setting ("default_password_nag"); /* setcookie() */
42
  update_user_option ($user_id, "default_password_nag", false, true);
43
  }
44
  /**/
45
+ if (!$username || !$user || !$user_id || strtolower ($username) === "demo" || ws_plugin__s2member_ip_restrictions_ok ($_SERVER["REMOTE_ADDR"], strtolower ($username)))
46
  {
47
  if ($special_redirection_url = ws_plugin__s2member_login_redirection_url ($user))
48
+ wp_redirect($special_redirection_url);
49
  /**/
50
+ else
51
+ wp_redirect (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"]));
52
  }
53
  /**/
54
  exit ();
92
  $user_login = (is_object ($user)) ? strtolower ($user->user_login) : "";
93
  $user_id = (is_object ($user)) ? (string)$user->ID : "";
94
  $user_level = (string)ws_plugin__s2member_user_access_level ($user);
95
+ $user_role = (string)ws_plugin__s2member_user_access_role ($user);
96
  /**/
97
  $url = preg_replace ("/%%current_user_login%%/i", ws_plugin__s2member_esc_ds ($user_login), $url);
98
  $url = preg_replace ("/%%current_user_id%%/i", ws_plugin__s2member_esc_ds ($user_id), $url);
99
  $url = preg_replace ("/%%current_user_level%%/i", ws_plugin__s2member_esc_ds ($user_level), $url);
100
+ $url = preg_replace ("/%%current_user_role%%/i", ws_plugin__s2member_esc_ds ($user_role), $url);
101
  /**/
102
  return apply_filters ("ws_plugin__s2member_fill_login_redirect_rc_vars", $url, get_defined_vars ());
103
  }
includes/functions/membership-options.inc.php CHANGED
@@ -12,7 +12,7 @@ If not, see: <http://www.gnu.org/licenses/>.
12
  Direct access denial.
13
  */
14
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
15
- exit("Do not access this file directly.");
16
  /*
17
  This forces a redirection to the Membership Options Page for s2Member.
18
  This can be used by 3rd party applications that are not aware of which
@@ -31,8 +31,12 @@ if (!function_exists ("ws_plugin__s2member_membership_options_page"))
31
  /**/
32
  if ($_GET["s2member_membership_options_page"] && !is_page ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]))
33
  {
34
- $_GET["s2member_level_req"] = (strlen ($_GET["s2member_level_req"])) ? $_GET["s2member_level_req"] : "0";
35
- wp_redirect(add_query_arg ("s2member_level_req", $_GET["s2member_level_req"], get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
 
 
 
 
36
  exit ();
37
  }
38
  /**/
12
  Direct access denial.
13
  */
14
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
15
+ exit ("Do not access this file directly.");
16
  /*
17
  This forces a redirection to the Membership Options Page for s2Member.
18
  This can be used by 3rd party applications that are not aware of which
31
  /**/
32
  if ($_GET["s2member_membership_options_page"] && !is_page ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]))
33
  {
34
+ $query_args = array (); /* Initialize array. */
35
+ foreach ($_GET as $var => $val) /* Include any s2member_ vars. */
36
+ if (preg_match ("/^s2member_/", $var) && $var !== "s2member_membership_options_page")
37
+ $query_args[$var] = $val;
38
+ /**/
39
+ wp_redirect (add_query_arg (urlencode_deep ($query_args), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
40
  exit ();
41
  }
42
  /**/
includes/functions/menu-pages.inc.php CHANGED
@@ -20,7 +20,7 @@ Options can also be passed in directly.
20
  */
21
  if (!function_exists ("ws_plugin__s2member_update_all_options"))
22
  {
23
- function ws_plugin__s2member_update_all_options ($new_options = FALSE, $verified = FALSE, $update_other = TRUE, $display_notices = TRUE, $enqueue_notices = FALSE)
24
  {
25
  do_action ("ws_plugin__s2member_before_update_all_options", get_defined_vars ()); /* If you use this Hook, be sure to use `wp_verify_nonce()`. */
26
  /**/
@@ -57,7 +57,7 @@ if (!function_exists ("ws_plugin__s2member_update_all_options"))
57
  if ($update_other === true || in_array ("auto_eot_system", (array)$update_other)) /* Handle the Auto-EOT System now ( enable/disable ). */
58
  ($options["auto_eot_system_enabled"] == 1) ? ws_plugin__s2member_add_auto_eot_system () : ws_plugin__s2member_delete_auto_eot_system ();
59
  /**/
60
- if (($display_notices === true || in_array ("success", (array)$display_notices)) && ($notice = '<strong>Options saved.</strong>'))
61
  ($enqueue_notices === true || in_array ("success", (array)$enqueue_notices)) ? ws_plugin__s2member_enqueue_admin_notice ($notice) : ws_plugin__s2member_display_admin_notice ($notice);
62
  /**/
63
  if (!$options["membership_options_page"] && ($display_notices === true || in_array ("page-conflict-warnings", (array)$display_notices)) && ($notice = '<strong>NOTE:</strong> s2Member security restrictions will NOT be enforced until you\'ve configured a Membership Options Page. See: <code>s2Member -> General Options -> Membership Options Page</code>.'))
@@ -390,7 +390,7 @@ if (!function_exists ("ws_plugin__s2member_paypal_ops_page"))
390
  if (is_dir ($logs_dir) && is_writable ($logs_dir) && !file_exists ($htaccess))
391
  file_put_contents ($htaccess, "deny from all") . clearstatcache ();
392
  /**/
393
- if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_debug"]) /* If logging is enabled. */
394
  {
395
  if (!is_dir ($logs_dir)) /* If the security-enabled logs directory does not exist yet. */
396
  ws_plugin__s2member_display_admin_notice ("The security-enabled logs directory ( <code>" . preg_replace ("/^" . preg_quote ($_SERVER["DOCUMENT_ROOT"], "/") . "/", "", $logs_dir) . "</code> ) does not exist. Please create this directory manually &amp; make it writable ( chmod 777 ).", true);
20
  */
21
  if (!function_exists ("ws_plugin__s2member_update_all_options"))
22
  {
23
+ function ws_plugin__s2member_update_all_options ($new_options = FALSE, $verified = FALSE, $update_other = TRUE, $display_notices = TRUE, $enqueue_notices = FALSE, $request_refresh = FALSE)
24
  {
25
  do_action ("ws_plugin__s2member_before_update_all_options", get_defined_vars ()); /* If you use this Hook, be sure to use `wp_verify_nonce()`. */
26
  /**/
57
  if ($update_other === true || in_array ("auto_eot_system", (array)$update_other)) /* Handle the Auto-EOT System now ( enable/disable ). */
58
  ($options["auto_eot_system_enabled"] == 1) ? ws_plugin__s2member_add_auto_eot_system () : ws_plugin__s2member_delete_auto_eot_system ();
59
  /**/
60
+ if (($display_notices === true || in_array ("success", (array)$display_notices)) && ($notice = '<strong>Options saved.' . (($request_refresh) ? ' Please <a href="' . esc_attr ($_SERVER["REQUEST_URI"]) . '">refresh</a>.' : '') . '</strong>'))
61
  ($enqueue_notices === true || in_array ("success", (array)$enqueue_notices)) ? ws_plugin__s2member_enqueue_admin_notice ($notice) : ws_plugin__s2member_display_admin_notice ($notice);
62
  /**/
63
  if (!$options["membership_options_page"] && ($display_notices === true || in_array ("page-conflict-warnings", (array)$display_notices)) && ($notice = '<strong>NOTE:</strong> s2Member security restrictions will NOT be enforced until you\'ve configured a Membership Options Page. See: <code>s2Member -> General Options -> Membership Options Page</code>.'))
390
  if (is_dir ($logs_dir) && is_writable ($logs_dir) && !file_exists ($htaccess))
391
  file_put_contents ($htaccess, "deny from all") . clearstatcache ();
392
  /**/
393
+ if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["gateway_debug_logs"]) /* Logging enabled? */
394
  {
395
  if (!is_dir ($logs_dir)) /* If the security-enabled logs directory does not exist yet. */
396
  ws_plugin__s2member_display_admin_notice ("The security-enabled logs directory ( <code>" . preg_replace ("/^" . preg_quote ($_SERVER["DOCUMENT_ROOT"], "/") . "/", "", $logs_dir) . "</code> ) does not exist. Please create this directory manually &amp; make it writable ( chmod 777 ).", true);
includes/functions/nocache.inc.php CHANGED
@@ -55,6 +55,7 @@ These additional supplemental routines, include:
55
  - ws_plugin__s2member_check_page_level_access()
56
  - ws_plugin__s2member_ip_restrictions_ok()
57
  - ws_plugin__s2member_file_download_key()
 
58
  */
59
  if (!function_exists ("ws_plugin__s2member_nocache_constants"))
60
  {
55
  - ws_plugin__s2member_check_page_level_access()
56
  - ws_plugin__s2member_ip_restrictions_ok()
57
  - ws_plugin__s2member_file_download_key()
58
+ - Button/Shortcode Generators also call this.
59
  */
60
  if (!function_exists ("ws_plugin__s2member_nocache_constants"))
61
  {
includes/functions/page-level-access.inc.php CHANGED
@@ -44,17 +44,17 @@ if (!function_exists ("ws_plugin__s2member_check_page_level_access"))
44
  /**/
45
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"] && $page_id == $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"] && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level0")) && $page_id != $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])
46
  {
47
- wp_redirect (add_query_arg ("s2member_level_req", 0, get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
48
  exit ();
49
  }
50
  else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_redirection_override"] && ($login_redirection_uri = ws_plugin__s2member_login_redirection_uri ($current_user)) && preg_match ("/^" . preg_quote ($login_redirection_uri, "/") . "$/", $_SERVER["REQUEST_URI"]) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level0")) && $page_id != $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])
51
  {
52
- wp_redirect (add_query_arg ("s2member_level_req", 0, get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
53
  exit ();
54
  }
55
  else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_limit_exceeded_page"] && $page_id == $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_limit_exceeded_page"] && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level0")) && $page_id != $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])
56
  {
57
- wp_redirect (add_query_arg ("s2member_level_req", 0, get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
58
  exit ();
59
  }
60
  else if (!ws_plugin__s2member_is_systematic_use_page ()) /* Never restrict Systematic Use Pages. However, there are 3 exceptions above ^. */
@@ -63,13 +63,13 @@ if (!function_exists ("ws_plugin__s2member_check_page_level_access"))
63
  {
64
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_pages"] === "all" && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
65
  {
66
- wp_redirect (add_query_arg ("s2member_level_req", $i, get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
67
  exit ();
68
  }
69
  /**/
70
  else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_pages"] && in_array ($page_id, preg_split ("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_pages"])) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
71
  {
72
- wp_redirect (add_query_arg ("s2member_level_req", $i, get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
73
  exit ();
74
  }
75
  }
@@ -80,13 +80,13 @@ if (!function_exists ("ws_plugin__s2member_check_page_level_access"))
80
  {
81
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_ptags"] === "all" && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
82
  {
83
- wp_redirect (add_query_arg ("s2member_level_req", $i, get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
84
  exit ();
85
  }
86
  /**/
87
  else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_ptags"] && has_tag (preg_split ("/[\r\n\t;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_ptags"])) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
88
  {
89
- wp_redirect (add_query_arg ("s2member_level_req", $i, get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
90
  exit ();
91
  }
92
  }
@@ -98,7 +98,7 @@ if (!function_exists ("ws_plugin__s2member_check_page_level_access"))
98
  foreach (preg_split ("/[\r\n\t]+/", ws_plugin__s2member_fill_ruri_level_access_rc_vars ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_ruris"], $current_user)) as $str)
99
  if ($str && preg_match ("/" . preg_quote ($str, "/") . "/", $_SERVER["REQUEST_URI"]) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
100
  {
101
- wp_redirect (add_query_arg ("s2member_level_req", $i, get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
102
  exit ();
103
  }
104
  }
@@ -107,13 +107,13 @@ if (!function_exists ("ws_plugin__s2member_check_page_level_access"))
107
  foreach ($ccaps_req as $ccap) /* The $current_user MUST satisfy ALL Custom Capability requirements. Stored as a serialized array. */
108
  if (strlen ($ccap) && (!$current_user || !$current_user->has_cap ("access_s2member_ccap_" . $ccap)))
109
  {
110
- wp_redirect (add_query_arg ("s2member_ccap_req", $ccap, get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
111
  exit ();
112
  }
113
  /**/
114
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["specific_ids"] && in_array ($page_id, preg_split ("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["specific_ids"])) && ws_plugin__s2member_nocache_constants (true) !== "nill" && !ws_plugin__s2member_sp_access ($page_id))
115
  {
116
- wp_redirect (add_query_arg ("s2member_sp_req", $page_id, get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
117
  exit ();
118
  }
119
  }
44
  /**/
45
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"] && $page_id == $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"] && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level0")) && $page_id != $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])
46
  {
47
+ wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "page-" . $page_id, "s2member_level_req" => "0")), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
48
  exit ();
49
  }
50
  else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_redirection_override"] && ($login_redirection_uri = ws_plugin__s2member_login_redirection_uri ($current_user)) && preg_match ("/^" . preg_quote ($login_redirection_uri, "/") . "$/", $_SERVER["REQUEST_URI"]) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level0")) && $page_id != $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])
51
  {
52
+ wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "page-" . $page_id, "s2member_level_req" => "0")), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
53
  exit ();
54
  }
55
  else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_limit_exceeded_page"] && $page_id == $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_limit_exceeded_page"] && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level0")) && $page_id != $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])
56
  {
57
+ wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "page-" . $page_id, "s2member_level_req" => "0")), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
58
  exit ();
59
  }
60
  else if (!ws_plugin__s2member_is_systematic_use_page ()) /* Never restrict Systematic Use Pages. However, there are 3 exceptions above ^. */
63
  {
64
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_pages"] === "all" && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
65
  {
66
+ wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "page-" . $page_id, "s2member_level_req" => $i)), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
67
  exit ();
68
  }
69
  /**/
70
  else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_pages"] && in_array ($page_id, preg_split ("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_pages"])) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
71
  {
72
+ wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "page-" . $page_id, "s2member_level_req" => $i)), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
73
  exit ();
74
  }
75
  }
80
  {
81
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_ptags"] === "all" && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
82
  {
83
+ wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "page-" . $page_id, "s2member_level_req" => $i)), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
84
  exit ();
85
  }
86
  /**/
87
  else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_ptags"] && has_tag (preg_split ("/[\r\n\t;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_ptags"])) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
88
  {
89
+ wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "page-" . $page_id, "s2member_level_req" => $i)), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
90
  exit ();
91
  }
92
  }
98
  foreach (preg_split ("/[\r\n\t]+/", ws_plugin__s2member_fill_ruri_level_access_rc_vars ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_ruris"], $current_user)) as $str)
99
  if ($str && preg_match ("/" . preg_quote ($str, "/") . "/", $_SERVER["REQUEST_URI"]) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
100
  {
101
+ wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "page-" . $page_id, "s2member_level_req" => $i)), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
102
  exit ();
103
  }
104
  }
107
  foreach ($ccaps_req as $ccap) /* The $current_user MUST satisfy ALL Custom Capability requirements. Stored as a serialized array. */
108
  if (strlen ($ccap) && (!$current_user || !$current_user->has_cap ("access_s2member_ccap_" . $ccap)))
109
  {
110
+ wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "page-" . $page_id, "s2member_ccap_req" => $ccap)), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
111
  exit ();
112
  }
113
  /**/
114
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["specific_ids"] && in_array ($page_id, preg_split ("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["specific_ids"])) && ws_plugin__s2member_nocache_constants (true) !== "nill" && !ws_plugin__s2member_sp_access ($page_id))
115
  {
116
+ wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "page-" . $page_id, "s2member_sp_req" => $page_id)), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
117
  exit ();
118
  }
119
  }
includes/functions/paypal-button.inc.php CHANGED
@@ -16,14 +16,6 @@ if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
16
  /*
17
  Function that handles the Shortcode for [s2Member-PayPal-Button /].
18
  Attach to: add_shortcode("s2Member-PayPal-Button");
19
-
20
- [s2Member-PayPal-Button level="1" ccaps="" desc="" ps="paypal" cc="USD" ns="1" custom="www.domain.com" ta="0" tp="0" tt="D" ra="0.01" rp="1" rt="M" rr="1" image="default" /]
21
- [s2Member-PayPal-Button page="0" exp="72" desc="Specific Post/Page Access" ps="paypal" cc="USD" ns="1" custom="www.domain.com" ra="0.01" sp="1" image="default" /]
22
- The image="" attribute will be used as a custom image; when provided; and not equal to "default".
23
-
24
- - PayPal® Cancellation Buttons are identified by cancel="1".
25
- - PayPal® Specific Post/Page Buttons are identified by sp="1".
26
- - PayPal® Modification Buttons are identified by modify="1".
27
  */
28
  if (!function_exists ("ws_plugin__s2member_sc_paypal_button"))
29
  {
@@ -33,15 +25,17 @@ if (!function_exists ("ws_plugin__s2member_sc_paypal_button"))
33
  do_action ("ws_plugin__s2member_before_sc_paypal_button", get_defined_vars ());
34
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
35
  /**/
 
 
36
  $attr = ws_plugin__s2member_trim_quot_deep ((array)$attr); /* Force array, and fix &quot; in attrs. */
37
  /**/
38
- $attr["tt"] = strtoupper ($attr["tt"]); /* Term lengths absolutely must be provided in upper-case format. */
39
- $attr["rt"] = strtoupper ($attr["rt"]); /* Term lengths absolutely must be provided in upper-case format. */
40
- $attr["rr"] = strtoupper ($attr["rr"]); /* Must be provided in upper-case format. Numerical, or BN value. */
41
- $attr["ccaps"] = strtolower ($attr["ccaps"]); /* Custom Capabilities must be typed in lower-case format. */
42
- $attr["rr"] = ($attr["rt"] === "L") ? "BN" : $attr["rr"]; /* Lifetime Subscriptions require Buy Now. */
43
  /**/
44
- $attr = shortcode_atts (array ("ids" => "0", "exp" => "72", "level" => "1", "ccaps" => "", "desc" => "", "ps" => "paypal", "cc" => "USD", "ns" => "1", "custom" => $_SERVER["HTTP_HOST"], "ta" => "", "tp" => "0", "tt" => "D", "ra" => "0.01", "rp" => "1", "rt" => "M", "rr" => "1", "modify" => "0", "cancel" => "0", "sp" => "0", "image" => "default"), $attr);
 
 
 
 
45
  /**/
46
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
47
  do_action ("ws_plugin__s2member_before_sc_paypal_button_after_shortcode_atts", get_defined_vars ());
@@ -49,11 +43,19 @@ if (!function_exists ("ws_plugin__s2member_sc_paypal_button"))
49
  /**/
50
  if ($attr["cancel"]) /* This is a special routine for Cancellation Buttons. Cancellation Buttons use a different template. */
51
  {
 
 
52
  $code = trim (file_get_contents (dirname (dirname (__FILE__)) . "/templates/buttons/paypal-cancellation-button.html"));
 
 
 
53
  $code = preg_replace ("/%%endpoint%%/", ws_plugin__s2member_esc_ds (esc_attr (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com")), $code);
54
  $code = preg_replace ("/%%paypal_business%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $code);
55
  /**/
56
- $code = ($attr["image"] && $attr["image"] !== "default") ? preg_replace ('/ src\="(.*?)"/', ' src="' . ws_plugin__s2member_esc_ds (esc_attr ($attr["image"])) . '"', $code) : $code;
 
 
 
57
  /**/
58
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
59
  do_action ("ws_plugin__s2member_during_sc_paypal_cancellation_button", get_defined_vars ());
@@ -62,15 +64,20 @@ if (!function_exists ("ws_plugin__s2member_sc_paypal_button"))
62
  /**/
63
  else if ($attr["sp"]) /* This is a special routine for Specific Post/Page Buttons. Specific Post/Page Buttons use a different template. */
64
  {
 
 
65
  $attr["sp_ids_exp"] = "sp:" . $attr["ids"] . ":" . $attr["exp"]; /* Combined "sp:ids:expiration hours". */
66
  /**/
67
  $code = trim (file_get_contents (dirname (dirname (__FILE__)) . "/templates/buttons/paypal-sp-checkout-button.html"));
 
 
 
68
  $code = preg_replace ("/%%endpoint%%/", ws_plugin__s2member_esc_ds (esc_attr (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com")), $code);
69
  $code = preg_replace ("/%%paypal_business%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $code);
70
  $code = preg_replace ("/%%cancel_return%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("url"))), $code);
71
  $code = preg_replace ("/%%notify_url%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl") . "/?s2member_paypal_notify=1")), $code);
72
  $code = preg_replace ("/%%return%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl") . "/?s2member_paypal_return=1")), $code);
73
- $code = preg_replace ("/%%domain%%/", ws_plugin__s2member_esc_ds (esc_attr ($_SERVER["HTTP_HOST"])), $code);
74
  /**/
75
  $code = preg_replace ('/ name\="no_shipping" value\="(.*?)"/', ' name="no_shipping" value="' . ws_plugin__s2member_esc_ds (esc_attr ($attr["ns"])) . '"', $code);
76
  $code = preg_replace ('/ name\="item_name" value\="(.*?)"/', ' name="item_name" value="' . ws_plugin__s2member_esc_ds (esc_attr ($attr["desc"])) . '"', $code);
@@ -80,7 +87,10 @@ if (!function_exists ("ws_plugin__s2member_sc_paypal_button"))
80
  $code = preg_replace ('/ name\="custom" value\="(.*?)"/', ' name="custom" value="' . ws_plugin__s2member_esc_ds (esc_attr ($attr["custom"])) . '"', $code);
81
  $code = preg_replace ('/ name\="amount" value\="(.*?)"/', ' name="amount" value="' . ws_plugin__s2member_esc_ds (esc_attr ($attr["ra"])) . '"', $code);
82
  /**/
83
- $code = ($attr["image"] && $attr["image"] !== "default") ? preg_replace ('/ src\="(.*?)"/', ' src="' . ws_plugin__s2member_esc_ds (esc_attr ($attr["image"])) . '"', $code) : $code;
 
 
 
84
  /**/
85
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
86
  do_action ("ws_plugin__s2member_during_sc_paypal_sp_button", get_defined_vars ());
@@ -88,19 +98,24 @@ if (!function_exists ("ws_plugin__s2member_sc_paypal_button"))
88
  }
89
  else /* Otherwise, we'll process this Button normally, using the Membership routines. Also handles Modification Buttons. */
90
  {
 
 
91
  $attr["desc"] = (!$attr["desc"]) ? $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $attr["level"] . "_label"] : $attr["desc"];
92
  /**/
93
  $attr["level_ccaps_eotper"] = ($attr["rr"] === "BN" && $attr["rt"] !== "L") ? $attr["level"] . ":" . $attr["ccaps"] . ":" . $attr["rp"] . " " . $attr["rt"] : $attr["level"] . ":" . $attr["ccaps"];
94
  $attr["level_ccaps_eotper"] = rtrim ($attr["level_ccaps_eotper"], ":"); /* Clean any trailing separators from this string. */
95
  /**/
96
  $code = trim (file_get_contents (dirname (dirname (__FILE__)) . "/templates/buttons/paypal-checkout-button.html"));
 
 
 
97
  $code = preg_replace ("/%%endpoint%%/", ws_plugin__s2member_esc_ds (esc_attr (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com")), $code);
98
  $code = preg_replace ("/%%paypal_business%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $code);
99
  $code = preg_replace ("/%%level_label%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $attr["level"] . "_label"])), $code);
100
  $code = preg_replace ("/%%cancel_return%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("url"))), $code); /* This brings them back to Front Page. */
101
  $code = preg_replace ("/%%notify_url%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl") . "/?s2member_paypal_notify=1")), $code);
102
  $code = preg_replace ("/%%return%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl") . "/?s2member_paypal_return=1")), $code);
103
- $code = preg_replace ("/%%domain%%/", ws_plugin__s2member_esc_ds (esc_attr ($_SERVER["HTTP_HOST"])), $code);
104
  $code = preg_replace ("/%%level%%/", ws_plugin__s2member_esc_ds (esc_attr ($attr["level"])), $code);
105
  /**/
106
  $code = preg_replace ('/ \<\!--(\<input type\="hidden" name\="(amount|src|sra|a1|p1|t1|a3|p3|t3)" value\="(.*?)" \/\>)--\>/', " $1", $code);
@@ -128,7 +143,10 @@ if (!function_exists ("ws_plugin__s2member_sc_paypal_button"))
128
  $code = preg_replace ('/ name\="p3" value\="(.*?)"/', ' name="p3" value="' . ws_plugin__s2member_esc_ds (esc_attr ($attr["rp"])) . '"', $code);
129
  $code = preg_replace ('/ name\="t3" value\="(.*?)"/', ' name="t3" value="' . ws_plugin__s2member_esc_ds (esc_attr ($attr["rt"])) . '"', $code);
130
  /**/
131
- $code = ($attr["image"] && $attr["image"] !== "default") ? preg_replace ('/ src\="(.*?)"/', ' src="' . ws_plugin__s2member_esc_ds (esc_attr ($attr["image"])) . '"', $code) : $code;
 
 
 
132
  /**/
133
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
134
  ($attr["modify"]) ? do_action ("ws_plugin__s2member_during_sc_paypal_modification_button", get_defined_vars ()) : do_action ("ws_plugin__s2member_during_sc_paypal_button", get_defined_vars ());
16
  /*
17
  Function that handles the Shortcode for [s2Member-PayPal-Button /].
18
  Attach to: add_shortcode("s2Member-PayPal-Button");
 
 
 
 
 
 
 
 
19
  */
20
  if (!function_exists ("ws_plugin__s2member_sc_paypal_button"))
21
  {
25
  do_action ("ws_plugin__s2member_before_sc_paypal_button", get_defined_vars ());
26
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
27
  /**/
28
+ ws_plugin__s2member_nocache_constants(true); /* No caching on pages that contain this Button. */
29
+ /**/
30
  $attr = ws_plugin__s2member_trim_quot_deep ((array)$attr); /* Force array, and fix &quot; in attrs. */
31
  /**/
32
+ $attr = shortcode_atts (array ("ids" => "0", "exp" => "72", "level" => "1", "ccaps" => "", "desc" => "", "ps" => "paypal", "cc" => "USD", "ns" => "1", "custom" => $_SERVER["HTTP_HOST"], "ta" => "0", "tp" => "0", "tt" => "D", "ra" => "0.01", "rp" => "1", "rt" => "M", "rr" => "1", "modify" => "0", "cancel" => "0", "sp" => "0", "image" => "default", "output" => "button"), $attr);
 
 
 
 
33
  /**/
34
+ $attr["tt"] = strtoupper ($attr["tt"]); /* Term lengths absolutely must be provided in upper-case format. Only perform this modification after running shortcode_atts(). */
35
+ $attr["rt"] = strtoupper ($attr["rt"]); /* Term lengths absolutely must be provided in upper-case format. Only perform this modification after running shortcode_atts(). */
36
+ $attr["rr"] = strtoupper ($attr["rr"]); /* Must be provided in upper-case format. Numerical, or BN value. Only perform this modification after running shortcode_atts(). */
37
+ $attr["ccaps"] = strtolower ($attr["ccaps"]); /* Custom Capabilities must be typed in lower-case format. Only perform this modification after running shortcode_atts(). */
38
+ $attr["rr"] = ($attr["rt"] === "L") ? "BN" : $attr["rr"]; /* Lifetime Subscriptions require Buy Now. Only perform this modification after running shortcode_atts(). */
39
  /**/
40
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
41
  do_action ("ws_plugin__s2member_before_sc_paypal_button_after_shortcode_atts", get_defined_vars ());
43
  /**/
44
  if ($attr["cancel"]) /* This is a special routine for Cancellation Buttons. Cancellation Buttons use a different template. */
45
  {
46
+ $default_image = "https://www.paypal.com/en_US/i/btn/btn_unsubscribe_LG.gif"; /* Default Image. */
47
+ /**/
48
  $code = trim (file_get_contents (dirname (dirname (__FILE__)) . "/templates/buttons/paypal-cancellation-button.html"));
49
+ $code = preg_replace ("/%%images%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images")), $code);
50
+ $code = preg_replace ("/%%wpurl%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl"))), $code);
51
+ /**/
52
  $code = preg_replace ("/%%endpoint%%/", ws_plugin__s2member_esc_ds (esc_attr (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com")), $code);
53
  $code = preg_replace ("/%%paypal_business%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $code);
54
  /**/
55
+ $code = ($attr["image"] && $attr["image"] !== "default") ? preg_replace ('/ src\="(.*?)"/', ' src="' . ws_plugin__s2member_esc_ds (esc_attr ($attr["image"])) . '"', $code) : preg_replace ('/ src\="(.*?)"/', ' src="' . ws_plugin__s2member_esc_ds (esc_attr ($default_image)) . '"', $code);
56
+ /**/
57
+ $code = ($attr["output"] === "anchor") ? $code : $code; /* Cancellation Buttons are already in anchor format; Button format is not used in Cancellations. */
58
+ $code = ($attr["output"] === "url") ? "https://" . ( ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com") . "/cgi-bin/webscr?cmd=_subscr-find&alias=" . urlencode ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"]) : $code;
59
  /**/
60
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
61
  do_action ("ws_plugin__s2member_during_sc_paypal_cancellation_button", get_defined_vars ());
64
  /**/
65
  else if ($attr["sp"]) /* This is a special routine for Specific Post/Page Buttons. Specific Post/Page Buttons use a different template. */
66
  {
67
+ $default_image = "https://www.paypal.com/en_US/i/btn/btn_xpressCheckout.gif"; /* Default Image. */
68
+ /**/
69
  $attr["sp_ids_exp"] = "sp:" . $attr["ids"] . ":" . $attr["exp"]; /* Combined "sp:ids:expiration hours". */
70
  /**/
71
  $code = trim (file_get_contents (dirname (dirname (__FILE__)) . "/templates/buttons/paypal-sp-checkout-button.html"));
72
+ $code = preg_replace ("/%%images%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images")), $code);
73
+ $code = preg_replace ("/%%wpurl%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl"))), $code);
74
+ /**/
75
  $code = preg_replace ("/%%endpoint%%/", ws_plugin__s2member_esc_ds (esc_attr (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com")), $code);
76
  $code = preg_replace ("/%%paypal_business%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $code);
77
  $code = preg_replace ("/%%cancel_return%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("url"))), $code);
78
  $code = preg_replace ("/%%notify_url%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl") . "/?s2member_paypal_notify=1")), $code);
79
  $code = preg_replace ("/%%return%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl") . "/?s2member_paypal_return=1")), $code);
80
+ $code = preg_replace ("/%%custom%%/", ws_plugin__s2member_esc_ds (esc_attr ($_SERVER["HTTP_HOST"])), $code);
81
  /**/
82
  $code = preg_replace ('/ name\="no_shipping" value\="(.*?)"/', ' name="no_shipping" value="' . ws_plugin__s2member_esc_ds (esc_attr ($attr["ns"])) . '"', $code);
83
  $code = preg_replace ('/ name\="item_name" value\="(.*?)"/', ' name="item_name" value="' . ws_plugin__s2member_esc_ds (esc_attr ($attr["desc"])) . '"', $code);
87
  $code = preg_replace ('/ name\="custom" value\="(.*?)"/', ' name="custom" value="' . ws_plugin__s2member_esc_ds (esc_attr ($attr["custom"])) . '"', $code);
88
  $code = preg_replace ('/ name\="amount" value\="(.*?)"/', ' name="amount" value="' . ws_plugin__s2member_esc_ds (esc_attr ($attr["ra"])) . '"', $code);
89
  /**/
90
+ $code = ($attr["image"] && $attr["image"] !== "default") ? preg_replace ('/ src\="(.*?)"/', ' src="' . ws_plugin__s2member_esc_ds (esc_attr ($attr["image"])) . '"', $code) : preg_replace ('/ src\="(.*?)"/', ' src="' . ws_plugin__s2member_esc_ds (esc_attr ($default_image)) . '"', $code);
91
+ /**/
92
+ $code = ($attr["output"] === "anchor") ? '<a href="' . ws_plugin__s2member_form_whips_2_url ($code) . '"><img src="' . ( ($attr["image"] && $attr["image"] !== "default") ? esc_attr ($attr["image"]) : esc_attr ($default_image)) . '" style="width:auto; height:auto; border:0;" alt="PayPal®" /></a>' : $code;
93
+ $code = ($attr["output"] === "url") ? ws_plugin__s2member_form_whips_2_url ($code) : $code;
94
  /**/
95
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
96
  do_action ("ws_plugin__s2member_during_sc_paypal_sp_button", get_defined_vars ());
98
  }
99
  else /* Otherwise, we'll process this Button normally, using the Membership routines. Also handles Modification Buttons. */
100
  {
101
+ $default_image = "https://www.paypal.com/en_US/i/btn/btn_xpressCheckout.gif"; /* Default PayPal® Image. */
102
+ /**/
103
  $attr["desc"] = (!$attr["desc"]) ? $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $attr["level"] . "_label"] : $attr["desc"];
104
  /**/
105
  $attr["level_ccaps_eotper"] = ($attr["rr"] === "BN" && $attr["rt"] !== "L") ? $attr["level"] . ":" . $attr["ccaps"] . ":" . $attr["rp"] . " " . $attr["rt"] : $attr["level"] . ":" . $attr["ccaps"];
106
  $attr["level_ccaps_eotper"] = rtrim ($attr["level_ccaps_eotper"], ":"); /* Clean any trailing separators from this string. */
107
  /**/
108
  $code = trim (file_get_contents (dirname (dirname (__FILE__)) . "/templates/buttons/paypal-checkout-button.html"));
109
+ $code = preg_replace ("/%%images%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images")), $code);
110
+ $code = preg_replace ("/%%wpurl%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl"))), $code);
111
+ /**/
112
  $code = preg_replace ("/%%endpoint%%/", ws_plugin__s2member_esc_ds (esc_attr (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com")), $code);
113
  $code = preg_replace ("/%%paypal_business%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $code);
114
  $code = preg_replace ("/%%level_label%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $attr["level"] . "_label"])), $code);
115
  $code = preg_replace ("/%%cancel_return%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("url"))), $code); /* This brings them back to Front Page. */
116
  $code = preg_replace ("/%%notify_url%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl") . "/?s2member_paypal_notify=1")), $code);
117
  $code = preg_replace ("/%%return%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl") . "/?s2member_paypal_return=1")), $code);
118
+ $code = preg_replace ("/%%custom%%/", ws_plugin__s2member_esc_ds (esc_attr ($_SERVER["HTTP_HOST"])), $code);
119
  $code = preg_replace ("/%%level%%/", ws_plugin__s2member_esc_ds (esc_attr ($attr["level"])), $code);
120
  /**/
121
  $code = preg_replace ('/ \<\!--(\<input type\="hidden" name\="(amount|src|sra|a1|p1|t1|a3|p3|t3)" value\="(.*?)" \/\>)--\>/', " $1", $code);
143
  $code = preg_replace ('/ name\="p3" value\="(.*?)"/', ' name="p3" value="' . ws_plugin__s2member_esc_ds (esc_attr ($attr["rp"])) . '"', $code);
144
  $code = preg_replace ('/ name\="t3" value\="(.*?)"/', ' name="t3" value="' . ws_plugin__s2member_esc_ds (esc_attr ($attr["rt"])) . '"', $code);
145
  /**/
146
+ $code = ($attr["image"] && $attr["image"] !== "default") ? preg_replace ('/ src\="(.*?)"/', ' src="' . ws_plugin__s2member_esc_ds (esc_attr ($attr["image"])) . '"', $code) : preg_replace ('/ src\="(.*?)"/', ' src="' . ws_plugin__s2member_esc_ds (esc_attr ($default_image)) . '"', $code);
147
+ /**/
148
+ $code = ($attr["output"] === "anchor") ? '<a href="' . ws_plugin__s2member_form_whips_2_url ($code) . '"><img src="' . ( ($attr["image"] && $attr["image"] !== "default") ? esc_attr ($attr["image"]) : esc_attr ($default_image)) . '" style="width:auto; height:auto; border:0;" alt="PayPal®" /></a>' : $code;
149
+ $code = ($attr["output"] === "url") ? ws_plugin__s2member_form_whips_2_url ($code) : $code;
150
  /**/
151
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
152
  ($attr["modify"]) ? do_action ("ws_plugin__s2member_during_sc_paypal_modification_button", get_defined_vars ()) : do_action ("ws_plugin__s2member_during_sc_paypal_button", get_defined_vars ());
includes/functions/paypal-utilities.inc.php CHANGED
@@ -31,36 +31,35 @@ if (!function_exists ("ws_plugin__s2member_paypal_postvars"))
31
  {
32
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
33
  /**/
34
- if ($_GET["tx"]) /* PDT ( Payment Data Transfer ) with Auto-Return. */
35
  {
36
- if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_identity_token"])
 
 
 
 
 
 
37
  {
38
- $postback["tx"] = $_GET["tx"];
39
- $postback["cmd"] = "_notify-synch";
40
- $postback["at"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_identity_token"];
41
- /**/
42
- $endpoint = ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com";
43
- /**/
44
- if (preg_match ("/^SUCCESS/i", ($response = trim (ws_plugin__s2member_remote ("https://" . $endpoint . "/cgi-bin/webscr", $postback, array ("timeout" => 20))))))
45
  {
46
- foreach (preg_split ("/[\r\n]+/", preg_replace ("/^SUCCESS/i", "", $response)) as $varline)
47
- {
48
- list ($key, $value) = preg_split ("/\=/", $varline, 2);
49
- if (strlen ($key = trim ($key)) && strlen ($value = trim ($value)))
50
- $postvars[$key] = trim (stripslashes (urldecode ($value)));
51
- }
52
- /**/
53
- return apply_filters ("ws_plugin__s2member_paypal_postvars", $postvars, get_defined_vars ());
54
  }
55
- else /* Nope. */
56
- return false;
57
  }
58
  else /* Nope. */
59
  return false;
60
  }
61
- else if (is_array ($postvars = stripslashes_deep ($_POST)))
62
  {
63
- $postback = $postvars;
 
 
 
 
64
  $postback["cmd"] = "_notify-validate";
65
  /**/
66
  $postvars = ws_plugin__s2member_trim_deep ($postvars);
@@ -68,7 +67,7 @@ if (!function_exists ("ws_plugin__s2member_paypal_postvars"))
68
  $endpoint = ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com";
69
  /**/
70
  if ($_GET["s2member_paypal_proxy"] && $_GET["s2member_paypal_proxy_verification"] === ws_plugin__s2member_paypal_proxy_key_gen ())
71
- return apply_filters ("ws_plugin__s2member_paypal_postvars", $postvars, get_defined_vars ());
72
  /**/
73
  else if (strtolower (trim (ws_plugin__s2member_remote ("https://" . $endpoint . "/cgi-bin/webscr", $postback, array ("timeout" => 20)))) === "verified")
74
  return apply_filters ("ws_plugin__s2member_paypal_postvars", $postvars, get_defined_vars ());
@@ -256,17 +255,17 @@ if (!function_exists ("ws_plugin__s2member_paypal_auto_eot_time"))
256
  $p3_time = $p3_days * 86400;
257
  }
258
  /**/
259
- if (!$last_payment_time) /* If no payment yet.
260
- EOT after p1, if there was a p1. Otherwise, now + 1 day grace. */
261
  {
262
  $auto_eot_time = $registration_time + $p1_time + 86400;
263
  }
264
- /* Else if p1, and last payment was within p1, last + p1 + 1 day grace. */
265
  else if ($p1_time && $last_payment_time <= $registration_time + $p1_time)
266
  {
267
  $auto_eot_time = $last_payment_time + $p1_time + 86400;
268
  }
269
- else /* Otherwise, the EOT comes after last payment + p3 + 1 day grace. */
270
  {
271
  $auto_eot_time = $last_payment_time + $p3_time + 86400;
272
  }
@@ -338,22 +337,109 @@ if (!function_exists ("ws_plugin__s2member_paypal_std_term"))
338
  Function converts a term [D,W,M,Y,L,Day,Week,Month,Year,Lifetime] into Daily, Weekly, Monthly, Yearly, Lifetime.
339
  This function can also handle "Period Term" combinations. Where the Period will be stripped automatically before conversion.
340
  For example, "1 D", would become, just "Daily". Another example, "3 Y" would become "Yearly"; and "1 L", would become "Lifetime".
 
341
  */
342
  if (!function_exists ("ws_plugin__s2member_paypal_term_cycle"))
343
  {
344
- function ws_plugin__s2member_paypal_term_cycle ($term_or_period_term = FALSE)
345
  {
346
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
347
  do_action ("ws_plugin__s2member_before_paypal_term_cycle", get_defined_vars ());
348
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
349
  /**/
350
- $paypal_term_cycles = array ("D" => "Daily", "W" => "Weekly", "M" => "Monthly", "Y" => "Yearly", "L" => "Lifetime", "DAY" => "Daily", "WEEK" => "Weekly", "MONTH" => "Monthly", "YEAR" => "Yearly", "Lifetime" => "Lifetime");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
351
  /**/
352
- $term_cycle = $paypal_term_cycles[strtoupper (preg_replace ("/^(.+?) /", "", $term_or_period_term))];
353
  return apply_filters ("ws_plugin__s2member_paypal_term_cycle", $term_cycle, get_defined_vars ());
354
  }
355
  }
356
  /*
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
357
  Parse/validate item_name from either an array with recurring_payment_id, or use an existing string.
358
  */
359
  if (!function_exists ("ws_plugin__s2member_paypal_pro_subscr_id"))
@@ -449,6 +535,7 @@ Pro API with PROFILEREFERENCE|rp_invoice_id, or parse/validate an existing strin
449
  to make sure it is a valid "period term" combination.
450
 
451
  Note: This will also convert "1 Day", into "1 D".
 
452
  */
453
  if (!function_exists ("ws_plugin__s2member_paypal_pro_period1"))
454
  {
@@ -474,6 +561,10 @@ if (!function_exists ("ws_plugin__s2member_paypal_pro_period1"))
474
  {
475
  list ($num, $span) = preg_split ("/ /", $period1, 2);
476
  /**/
 
 
 
 
477
  if (strlen ($span) !== 1) /* Convert to Standard format. */
478
  $span = ws_plugin__s2member_paypal_std_term ($span);
479
  /**/
@@ -493,7 +584,8 @@ Pro API with PROFILEREFERENCE|rp_invoice_id, or parse/validate an existing strin
493
  to make sure it is a valid "period term" combination.
494
 
495
  Note: This will also convert "1 Day", into "1 D".
496
- Note: The regular period can never be less than 1 day ( 1 D ).
 
497
  */
498
  if (!function_exists ("ws_plugin__s2member_paypal_pro_period3"))
499
  {
@@ -519,6 +611,10 @@ if (!function_exists ("ws_plugin__s2member_paypal_pro_period3"))
519
  {
520
  list ($num, $span) = preg_split ("/ /", $period3, 2);
521
  /**/
 
 
 
 
522
  if (strlen ($span) !== 1) /* Convert to Standard format. */
523
  $span = ws_plugin__s2member_paypal_std_term ($span);
524
  /**/
31
  {
32
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
33
  /**/
34
+ if ($_GET["tx"] && !$_GET["s2member_paypal_proxy"]) /* Auto-Return w/PDT. */
35
  {
36
+ $postback["tx"] = $_GET["tx"];
37
+ $postback["cmd"] = "_notify-synch";
38
+ $postback["at"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_identity_token"];
39
+ /**/
40
+ $endpoint = ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com";
41
+ /**/
42
+ if (preg_match ("/^SUCCESS/i", ($response = trim (ws_plugin__s2member_remote ("https://" . $endpoint . "/cgi-bin/webscr", $postback, array ("timeout" => 20))))))
43
  {
44
+ foreach (preg_split ("/[\r\n]+/", preg_replace ("/^SUCCESS/i", "", $response)) as $varline)
 
 
 
 
 
 
45
  {
46
+ list ($key, $value) = preg_split ("/\=/", $varline, 2);
47
+ if (strlen ($key = trim ($key)) && strlen ($value = trim ($value)))
48
+ $postvars[$key] = trim (stripslashes (urldecode ($value)));
 
 
 
 
 
49
  }
50
+ /**/
51
+ return apply_filters ("ws_plugin__s2member_paypal_postvars", $postvars, get_defined_vars ());
52
  }
53
  else /* Nope. */
54
  return false;
55
  }
56
+ else if (is_array ($postvars = stripslashes_deep ($_REQUEST)))
57
  {
58
+ foreach ($postvars as $key => $value)
59
+ if (preg_match ("/^s2member_/", $key))
60
+ unset ($postvars[$key]);
61
+ /**/
62
+ $postback = $postvars; /* Copy. */
63
  $postback["cmd"] = "_notify-validate";
64
  /**/
65
  $postvars = ws_plugin__s2member_trim_deep ($postvars);
67
  $endpoint = ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com";
68
  /**/
69
  if ($_GET["s2member_paypal_proxy"] && $_GET["s2member_paypal_proxy_verification"] === ws_plugin__s2member_paypal_proxy_key_gen ())
70
+ return apply_filters ("ws_plugin__s2member_paypal_postvars", array_merge ($postvars, array ("proxy_verified" => $_GET["s2member_paypal_proxy"])), get_defined_vars ());
71
  /**/
72
  else if (strtolower (trim (ws_plugin__s2member_remote ("https://" . $endpoint . "/cgi-bin/webscr", $postback, array ("timeout" => 20)))) === "verified")
73
  return apply_filters ("ws_plugin__s2member_paypal_postvars", $postvars, get_defined_vars ());
255
  $p3_time = $p3_days * 86400;
256
  }
257
  /**/
258
+ if (!$last_payment_time) /* If there's been no payment yet.
259
+ After p1, if there was a p1. Otherwise, reg. time + 1 day grace. */
260
  {
261
  $auto_eot_time = $registration_time + $p1_time + 86400;
262
  }
263
+ /* Else if p1, and last payment within p1, last + p1 + 1 day grace. */
264
  else if ($p1_time && $last_payment_time <= $registration_time + $p1_time)
265
  {
266
  $auto_eot_time = $last_payment_time + $p1_time + 86400;
267
  }
268
+ else /* Otherwise, after last payment + p3 + 1 day grace. */
269
  {
270
  $auto_eot_time = $last_payment_time + $p3_time + 86400;
271
  }
337
  Function converts a term [D,W,M,Y,L,Day,Week,Month,Year,Lifetime] into Daily, Weekly, Monthly, Yearly, Lifetime.
338
  This function can also handle "Period Term" combinations. Where the Period will be stripped automatically before conversion.
339
  For example, "1 D", would become, just "Daily". Another example, "3 Y" would become "Yearly"; and "1 L", would become "Lifetime".
340
+ Recurring examples: "2 W", becomes "Bi-Weekly", "3 M" becomes Quarterly, and "2 M" becomes "Bi-Monthly".
341
  */
342
  if (!function_exists ("ws_plugin__s2member_paypal_term_cycle"))
343
  {
344
+ function ws_plugin__s2member_paypal_term_cycle ($term_or_period_term = FALSE, $directive = "recurring")
345
  {
346
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
347
  do_action ("ws_plugin__s2member_before_paypal_term_cycle", get_defined_vars ());
348
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
349
  /**/
350
+ if ($directive === "recurring") /* recurring = Daily, Weekly, Bi-Weekly, Monthly, Bi-Monthly, Quarterly, Yearly, Lifetime. */
351
+ {
352
+ $paypal_term_cycles = array ("D" => "Daily", "W" => "Weekly", "M" => "Monthly", "Y" => "Yearly", "L" => "Lifetime", "DAY" => "Daily", "WEEK" => "Weekly", "MONTH" => "Monthly", "YEAR" => "Yearly", "Lifetime" => "Lifetime");
353
+ $term_cycle = $paypal_term_cycles[strtoupper (preg_replace ("/^(.+?) /", "", $term_or_period_term))];
354
+ $term_cycle = (strtoupper ($term_or_period_term) === "2 W") ? "Bi-Weekly" : $term_cycle;
355
+ $term_cycle = (strtoupper ($term_or_period_term) === "2 M") ? "Bi-Monthly" : $term_cycle;
356
+ $term_cycle = (strtoupper ($term_or_period_term) === "3 M") ? "Quarterly" : $term_cycle;
357
+ }
358
+ else if ($directive === "singular") /* singular = Day, Week, Month, Year, Lifetime. */
359
+ {
360
+ $paypal_term_cycles = array ("D" => "Day", "W" => "Week", "M" => "Month", "Y" => "Year", "L" => "Lifetime", "DAY" => "Day", "WEEK" => "Week", "MONTH" => "Month", "YEAR" => "Year", "Lifetime" => "Lifetime");
361
+ $term_cycle = $paypal_term_cycles[strtoupper (preg_replace ("/^(.+?) /", "", $term_or_period_term))];
362
+ }
363
+ else if ($directive === "plural") /* plural = Days, Weeks, Months, Years, Lifetimes. */
364
+ {
365
+ $paypal_term_cycles = array ("D" => "Days", "W" => "Weeks", "M" => "Months", "Y" => "Years", "L" => "Lifetimes", "DAY" => "Days", "WEEK" => "Weeks", "MONTH" => "Months", "YEAR" => "Years", "Lifetime" => "Lifetimes");
366
+ $term_cycle = $paypal_term_cycles[strtoupper (preg_replace ("/^(.+?) /", "", $term_or_period_term))];
367
+ }
368
  /**/
 
369
  return apply_filters ("ws_plugin__s2member_paypal_term_cycle", $term_cycle, get_defined_vars ());
370
  }
371
  }
372
  /*
373
+ Function accepts a period, term, and recurring flag.
374
+ Returns a full term explanation.
375
+ Example: 2 months.
376
+ */
377
+ if (!function_exists ("ws_plugin__s2member_paypal_period_term"))
378
+ {
379
+ function ws_plugin__s2member_paypal_period_term ($period_term = FALSE, $recurring = FALSE)
380
+ {
381
+ eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
382
+ do_action ("ws_plugin__s2member_before_paypal_period_term", get_defined_vars ());
383
+ unset ($__refs, $__v); /* Unset defined __refs, __v. */
384
+ /**/
385
+ list ($period, $term) = preg_split ("/ /", ($period_term = strtoupper ($period_term)), 2);
386
+ $recurring = (strtoupper ($recurring) === "BN") ? (int)0 : (int)$recurring;
387
+ /**/
388
+ $cycle_recurring = ws_plugin__s2member_paypal_term_cycle ($period_term, "recurring");
389
+ $cycle_singular = ws_plugin__s2member_paypal_term_cycle ($period_term, "singular");
390
+ $cycle_plural = ws_plugin__s2member_paypal_term_cycle ($period_term, "plural");
391
+ /**/
392
+ if ($recurring && in_array ($period_term, array ("1 D", "1 W", "2 W", "1 M", "2 M", "3 M", "1 Y")))
393
+ $period_term = strtolower ($cycle_recurring); /* Results in an "ly" ending. */
394
+ /**/
395
+ else if ($recurring) /* Otherwise, it's recurring; but NOT an "ly" ending. */
396
+ $period_term = strtolower ("every " . $period . " " . $cycle_plural);
397
+ /**/
398
+ else if (strtoupper ($term) === "L") /* One-payment for lifetime access. */
399
+ $period_term = "lifetime"; /* Lifetime only. */
400
+ /**/
401
+ else /* Otherwise, this is NOT recurring. Results in X days/weeks/months/years/lifetime. */
402
+ $period_term = strtolower ($period . " " . ( ($period <> 1) ? $cycle_plural : $cycle_singular));
403
+ /**/
404
+ return apply_filters ("ws_plugin__s2member_paypal_period_term", $period_term, get_defined_vars ());
405
+ }
406
+ }
407
+ /*
408
+ Function accepts a billing amount, period, term, and recurring flag.
409
+ Returns a full billing term explanation.
410
+ Example: 1.00 for 2 months.
411
+ */
412
+ if (!function_exists ("ws_plugin__s2member_paypal_amount_period_term"))
413
+ {
414
+ function ws_plugin__s2member_paypal_amount_period_term ($amount = FALSE, $period_term = FALSE, $recurring = FALSE)
415
+ {
416
+ eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
417
+ do_action ("ws_plugin__s2member_before_paypal_amount_period_term", get_defined_vars ());
418
+ unset ($__refs, $__v); /* Unset defined __refs, __v. */
419
+ /**/
420
+ list ($period, $term) = preg_split ("/ /", ($period_term = strtoupper ($period_term)), 2);
421
+ $recurring = (strtoupper ($recurring) === "BN") ? (int)0 : (int)$recurring;
422
+ /**/
423
+ $cycle_recurring = ws_plugin__s2member_paypal_term_cycle ($period_term, "recurring");
424
+ $cycle_singular = ws_plugin__s2member_paypal_term_cycle ($period_term, "singular");
425
+ $cycle_plural = ws_plugin__s2member_paypal_term_cycle ($period_term, "plural");
426
+ /**/
427
+ if ($recurring && in_array ($period_term, array ("1 D", "1 W", "2 W", "1 M", "2 M", "3 M", "1 Y")))
428
+ $amount_period_term = number_format ($amount, 2, ".", "") . " / " . strtolower ($cycle_recurring);
429
+ /**/
430
+ else if ($recurring) /* Otherwise, it's recurring; but NOT an "ly" ending. */
431
+ $amount_period_term = number_format ($amount, 2, ".", "") . " " . strtolower ("every " . $period . " " . $cycle_plural);
432
+ /**/
433
+ else if (strtoupper ($term) === "L") /* One-payment for lifetime access. */
434
+ $amount_period_term = number_format ($amount, 2, ".", ""); /* Price only. */
435
+ /**/
436
+ else /* Otherwise, this is NOT recurring. Results in 0.00 for X days/weeks/months/years/lifetime. */
437
+ $amount_period_term = number_format ($amount, 2, ".", "") . " for " . strtolower ($period . " " . ( ($period <> 1) ? $cycle_plural : $cycle_singular));
438
+ /**/
439
+ return apply_filters ("ws_plugin__s2member_paypal_amount_period_term", $amount_period_term, get_defined_vars ());
440
+ }
441
+ }
442
+ /*
443
  Parse/validate item_name from either an array with recurring_payment_id, or use an existing string.
444
  */
445
  if (!function_exists ("ws_plugin__s2member_paypal_pro_subscr_id"))
535
  to make sure it is a valid "period term" combination.
536
 
537
  Note: This will also convert "1 Day", into "1 D".
538
+ Note: This will also convert "1 SemiMonth", into "2 W".
539
  */
540
  if (!function_exists ("ws_plugin__s2member_paypal_pro_period1"))
541
  {
561
  {
562
  list ($num, $span) = preg_split ("/ /", $period1, 2);
563
  /**/
564
+ if (strtoupper ($span) === "SEMIMONTH")
565
+ if (is_numeric ($num) && $num >= 1)
566
+ eval ('$num = "2"; $span = "W";');
567
+ /**/
568
  if (strlen ($span) !== 1) /* Convert to Standard format. */
569
  $span = ws_plugin__s2member_paypal_std_term ($span);
570
  /**/
584
  to make sure it is a valid "period term" combination.
585
 
586
  Note: This will also convert "1 Day", into "1 D".
587
+ Note: This will also convert "1 SemiMonth", into "2 W".
588
+ Note: The Regular Period can never be less than 1 day ( 1 D ).
589
  */
590
  if (!function_exists ("ws_plugin__s2member_paypal_pro_period3"))
591
  {
611
  {
612
  list ($num, $span) = preg_split ("/ /", $period3, 2);
613
  /**/
614
+ if (strtoupper ($span) === "SEMIMONTH")
615
+ if (is_numeric ($num) && $num >= 1)
616
+ eval ('$num = "2"; $span = "W";');
617
+ /**/
618
  if (strlen ($span) !== 1) /* Convert to Standard format. */
619
  $span = ws_plugin__s2member_paypal_std_term ($span);
620
  /**/
includes/functions/post-level-access.inc.php CHANGED
@@ -44,7 +44,7 @@ if (!function_exists ("ws_plugin__s2member_check_post_level_access"))
44
  /**/
45
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_redirection_override"] && ($login_redirection_uri = ws_plugin__s2member_login_redirection_uri ($current_user)) && preg_match ("/^" . preg_quote ($login_redirection_uri, "/") . "$/", $_SERVER["REQUEST_URI"]) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level0")))
46
  {
47
- wp_redirect (add_query_arg ("s2member_level_req", 0, get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
48
  exit ();
49
  }
50
  else if (!ws_plugin__s2member_is_systematic_use_page ()) /* Do NOT protect Systematics. However, there is 1 exception above ^. */
@@ -53,13 +53,13 @@ if (!function_exists ("ws_plugin__s2member_check_post_level_access"))
53
  {
54
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_posts"] === "all" && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
55
  {
56
- wp_redirect (add_query_arg ("s2member_level_req", $i, get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
57
  exit ();
58
  }
59
  /**/
60
  else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_posts"] && in_array ($post_id, preg_split ("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_posts"])) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
61
  {
62
- wp_redirect (add_query_arg ("s2member_level_req", $i, get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
63
  exit ();
64
  }
65
  }
@@ -68,13 +68,13 @@ if (!function_exists ("ws_plugin__s2member_check_post_level_access"))
68
  {
69
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_catgs"] === "all" && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
70
  {
71
- wp_redirect (add_query_arg ("s2member_level_req", $i, get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
72
  exit ();
73
  }
74
  /**/
75
  else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_catgs"] && (in_category (($catgs = preg_split ("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_catgs"])), $post_id) || ws_plugin__s2member_in_descendant_category ($catgs, $post_id)) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
76
  {
77
- wp_redirect (add_query_arg ("s2member_level_req", $i, get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
78
  exit ();
79
  }
80
  }
@@ -85,13 +85,13 @@ if (!function_exists ("ws_plugin__s2member_check_post_level_access"))
85
  {
86
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_ptags"] === "all" && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
87
  {
88
- wp_redirect (add_query_arg ("s2member_level_req", $i, get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
89
  exit ();
90
  }
91
  /**/
92
  else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_ptags"] && has_tag (preg_split ("/[\r\n\t;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_ptags"])) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
93
  {
94
- wp_redirect (add_query_arg ("s2member_level_req", $i, get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
95
  exit ();
96
  }
97
  }
@@ -103,7 +103,7 @@ if (!function_exists ("ws_plugin__s2member_check_post_level_access"))
103
  foreach (preg_split ("/[\r\n\t]+/", ws_plugin__s2member_fill_ruri_level_access_rc_vars ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_ruris"], $current_user)) as $str)
104
  if ($str && preg_match ("/" . preg_quote ($str, "/") . "/", $_SERVER["REQUEST_URI"]) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
105
  {
106
- wp_redirect (add_query_arg ("s2member_level_req", $i, get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
107
  exit ();
108
  }
109
  }
@@ -112,13 +112,13 @@ if (!function_exists ("ws_plugin__s2member_check_post_level_access"))
112
  foreach ($ccaps_req as $ccap) /* The $current_user MUST satisfy ALL Custom Capability requirements. Stored as a serialized array. */
113
  if (strlen ($ccap) && (!$current_user || !$current_user->has_cap ("access_s2member_ccap_" . $ccap)))
114
  {
115
- wp_redirect (add_query_arg ("s2member_ccap_req", $ccap, get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
116
  exit ();
117
  }
118
  /**/
119
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["specific_ids"] && in_array ($post_id, preg_split ("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["specific_ids"])) && ws_plugin__s2member_nocache_constants (true) !== "nill" && !ws_plugin__s2member_sp_access ($post_id))
120
  {
121
- wp_redirect (add_query_arg ("s2member_sp_req", $post_id, get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
122
  exit ();
123
  }
124
  }
44
  /**/
45
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_redirection_override"] && ($login_redirection_uri = ws_plugin__s2member_login_redirection_uri ($current_user)) && preg_match ("/^" . preg_quote ($login_redirection_uri, "/") . "$/", $_SERVER["REQUEST_URI"]) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level0")))
46
  {
47
+ wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "post-" . $post_id, "s2member_level_req" => "0")), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
48
  exit ();
49
  }
50
  else if (!ws_plugin__s2member_is_systematic_use_page ()) /* Do NOT protect Systematics. However, there is 1 exception above ^. */
53
  {
54
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_posts"] === "all" && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
55
  {
56
+ wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "post-" . $post_id, "s2member_level_req" => $i)), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
57
  exit ();
58
  }
59
  /**/
60
  else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_posts"] && in_array ($post_id, preg_split ("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_posts"])) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
61
  {
62
+ wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "post-" . $post_id, "s2member_level_req" => $i)), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
63
  exit ();
64
  }
65
  }
68
  {
69
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_catgs"] === "all" && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
70
  {
71
+ wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "post-" . $post_id, "s2member_level_req" => $i)), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
72
  exit ();
73
  }
74
  /**/
75
  else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_catgs"] && (in_category (($catgs = preg_split ("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_catgs"])), $post_id) || ws_plugin__s2member_in_descendant_category ($catgs, $post_id)) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
76
  {
77
+ wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "post-" . $post_id, "s2member_level_req" => $i)), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
78
  exit ();
79
  }
80
  }
85
  {
86
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_ptags"] === "all" && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
87
  {
88
+ wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "post-" . $post_id, "s2member_level_req" => $i)), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
89
  exit ();
90
  }
91
  /**/
92
  else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_ptags"] && has_tag (preg_split ("/[\r\n\t;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_ptags"])) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
93
  {
94
+ wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "post-" . $post_id, "s2member_level_req" => $i)), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
95
  exit ();
96
  }
97
  }
103
  foreach (preg_split ("/[\r\n\t]+/", ws_plugin__s2member_fill_ruri_level_access_rc_vars ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_ruris"], $current_user)) as $str)
104
  if ($str && preg_match ("/" . preg_quote ($str, "/") . "/", $_SERVER["REQUEST_URI"]) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
105
  {
106
+ wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "post-" . $post_id, "s2member_level_req" => $i)), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
107
  exit ();
108
  }
109
  }
112
  foreach ($ccaps_req as $ccap) /* The $current_user MUST satisfy ALL Custom Capability requirements. Stored as a serialized array. */
113
  if (strlen ($ccap) && (!$current_user || !$current_user->has_cap ("access_s2member_ccap_" . $ccap)))
114
  {
115
+ wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "post-" . $post_id, "s2member_ccap_req" => $ccap)), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
116
  exit ();
117
  }
118
  /**/
119
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["specific_ids"] && in_array ($post_id, preg_split ("/[\r\n\t\s;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["specific_ids"])) && ws_plugin__s2member_nocache_constants (true) !== "nill" && !ws_plugin__s2member_sp_access ($post_id))
120
  {
121
+ wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "post-" . $post_id, "s2member_sp_req" => $post_id)), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
122
  exit ();
123
  }
124
  }
includes/functions/ptag-level-access.inc.php CHANGED
@@ -32,19 +32,19 @@ if (!function_exists ("ws_plugin__s2member_check_ptag_level_access"))
32
  {
33
  function ws_plugin__s2member_check_ptag_level_access ()
34
  {
35
- global $post; /* get_the_ID() is NOT available outside The Loop. */
36
  /**/
37
  do_action ("ws_plugin__s2member_before_check_ptag_level_access", get_defined_vars ());
38
  /**/
39
  $excluded = apply_filters ("ws_plugin__s2member_check_ptag_level_access_excluded", false, get_defined_vars ());
40
  /**/
41
- if (!$excluded && is_tag () && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]) /* Check? */
42
  {
43
  $current_user = (is_user_logged_in ()) ? wp_get_current_user () : false; /* Get the current User's object. */
44
  /**/
45
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_redirection_override"] && ($login_redirection_uri = ws_plugin__s2member_login_redirection_uri ($current_user)) && preg_match ("/^" . preg_quote ($login_redirection_uri, "/") . "$/", $_SERVER["REQUEST_URI"]) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level0")))
46
  {
47
- wp_redirect (add_query_arg ("s2member_level_req", 0, get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
48
  exit ();
49
  }
50
  else if (!ws_plugin__s2member_is_systematic_use_page ()) /* Do NOT protect Systematics. However, there is 1 exception above ^. */
@@ -53,13 +53,13 @@ if (!function_exists ("ws_plugin__s2member_check_ptag_level_access"))
53
  {
54
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_ptags"] === "all" && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
55
  {
56
- wp_redirect (add_query_arg ("s2member_level_req", $i, get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
57
  exit ();
58
  }
59
  /**/
60
- else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_ptags"] && is_tag (preg_split ("/[\r\n\t;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_ptags"])) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
61
  {
62
- wp_redirect (add_query_arg ("s2member_level_req", $i, get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
63
  exit ();
64
  }
65
  }
@@ -70,7 +70,7 @@ if (!function_exists ("ws_plugin__s2member_check_ptag_level_access"))
70
  foreach (preg_split ("/[\r\n\t]+/", ws_plugin__s2member_fill_ruri_level_access_rc_vars ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_ruris"], $current_user)) as $str)
71
  if ($str && preg_match ("/" . preg_quote ($str, "/") . "/", $_SERVER["REQUEST_URI"]) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
72
  {
73
- wp_redirect (add_query_arg ("s2member_level_req", $i, get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
74
  exit ();
75
  }
76
  }
32
  {
33
  function ws_plugin__s2member_check_ptag_level_access ()
34
  {
35
+ global $wp_query, $post; /* get_the_ID() is NOT available outside The Loop. */
36
  /**/
37
  do_action ("ws_plugin__s2member_before_check_ptag_level_access", get_defined_vars ());
38
  /**/
39
  $excluded = apply_filters ("ws_plugin__s2member_check_ptag_level_access_excluded", false, get_defined_vars ());
40
  /**/
41
+ if (!$excluded && is_tag () && is_object ($tag = $wp_query->get_queried_object ()) && ($tag_id = $tag->term_id) && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])
42
  {
43
  $current_user = (is_user_logged_in ()) ? wp_get_current_user () : false; /* Get the current User's object. */
44
  /**/
45
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_redirection_override"] && ($login_redirection_uri = ws_plugin__s2member_login_redirection_uri ($current_user)) && preg_match ("/^" . preg_quote ($login_redirection_uri, "/") . "$/", $_SERVER["REQUEST_URI"]) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level0")))
46
  {
47
+ wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "ptag-" . $tag_id, "s2member_level_req" => "0")), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
48
  exit ();
49
  }
50
  else if (!ws_plugin__s2member_is_systematic_use_page ()) /* Do NOT protect Systematics. However, there is 1 exception above ^. */
53
  {
54
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_ptags"] === "all" && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
55
  {
56
+ wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "ptag-" . $tag_id, "s2member_level_req" => $i)), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
57
  exit ();
58
  }
59
  /**/
60
+ else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_ptags"] && (is_tag ($tags = preg_split ("/[\r\n\t;,]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_ptags"])) || in_array ($tag_id, $tags)) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
61
  {
62
+ wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "ptag-" . $tag_id, "s2member_level_req" => $i)), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
63
  exit ();
64
  }
65
  }
70
  foreach (preg_split ("/[\r\n\t]+/", ws_plugin__s2member_fill_ruri_level_access_rc_vars ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_ruris"], $current_user)) as $str)
71
  if ($str && preg_match ("/" . preg_quote ($str, "/") . "/", $_SERVER["REQUEST_URI"]) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
72
  {
73
+ wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "ptag-" . $tag_id, "s2member_level_req" => $i)), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
74
  exit ();
75
  }
76
  }
includes/functions/register-access.inc.php CHANGED
@@ -27,7 +27,7 @@ if (!function_exists ("ws_plugin__s2member_register_link_gen"))
27
  if ($subscr_id && $custom && $item_number) /* Must have all of these. */
28
  {
29
  $register = ws_plugin__s2member_encrypt ("subscr_id_custom_item_number_time:.:|:.:" . $subscr_id . ":.:|:.:" . $custom . ":.:|:.:" . $item_number . ":.:|:.:" . strtotime ("now"));
30
- $register_link = add_query_arg ("s2member_register", $register, get_bloginfo ("wpurl") . "/");
31
  /**/
32
  if ($shrink && ($tinyurl = ws_plugin__s2member_remote ("http://tinyurl.com/api-create.php?url=" . rawurlencode ($register_link))))
33
  return apply_filters ("ws_plugin__s2member_register_link_gen", $tinyurl, get_defined_vars ()); /* tinyURL is easier to work with. */
@@ -71,7 +71,7 @@ if (!function_exists ("ws_plugin__s2member_register"))
71
  else /* Otherwise, this is NOT a Multisite install. Or it is, but the Super Administrator is NOT selling Blog creation. */
72
  {
73
  echo '<script type="text/javascript">' . "\n";
74
- echo "window.location = '" . esc_js (add_query_arg ("action", "register", wp_login_url ())) . "';";
75
  echo '</script>' . "\n";
76
  }
77
  }
27
  if ($subscr_id && $custom && $item_number) /* Must have all of these. */
28
  {
29
  $register = ws_plugin__s2member_encrypt ("subscr_id_custom_item_number_time:.:|:.:" . $subscr_id . ":.:|:.:" . $custom . ":.:|:.:" . $item_number . ":.:|:.:" . strtotime ("now"));
30
+ $register_link = add_query_arg ("s2member_register", urlencode ($register), get_bloginfo ("wpurl") . "/");
31
  /**/
32
  if ($shrink && ($tinyurl = ws_plugin__s2member_remote ("http://tinyurl.com/api-create.php?url=" . rawurlencode ($register_link))))
33
  return apply_filters ("ws_plugin__s2member_register_link_gen", $tinyurl, get_defined_vars ()); /* tinyURL is easier to work with. */
71
  else /* Otherwise, this is NOT a Multisite install. Or it is, but the Super Administrator is NOT selling Blog creation. */
72
  {
73
  echo '<script type="text/javascript">' . "\n";
74
+ echo "window.location = '" . esc_js (add_query_arg ("action", urlencode ("register"), wp_login_url ())) . "';";
75
  echo '</script>' . "\n";
76
  }
77
  }
includes/functions/registration-times.inc.php ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Copyright: © 2009 WebSharks, Inc. ( coded in the USA )
4
+ <mailto:support@websharks-inc.com> <http://www.websharks-inc.com/>
5
+
6
+ Released under the terms of the GNU General Public License.
7
+ You should have received a copy of the GNU General Public License,
8
+ along with this software. In the main directory, see: /licensing/
9
+ If not, see: <http://www.gnu.org/licenses/>.
10
+ */
11
+ /*
12
+ Direct access denial.
13
+ */
14
+ if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
15
+ exit ("Do not access this file directly.");
16
+ /*
17
+ Retrieves a Registration Time.
18
+ $user_id defaults to the current user; if logged in.
19
+ */
20
+ if (!function_exists ("ws_plugin__s2member_registration_time"))
21
+ {
22
+ function ws_plugin__s2member_registration_time ($user_id = FALSE)
23
+ {
24
+ $user = ($user_id) ? new WP_User ($user_id) : ( (is_user_logged_in ()) ? wp_get_current_user () : false);
25
+ /**/
26
+ if (is_object ($user) && ($user_id = $user->ID) && $user->user_registered)
27
+ {
28
+ return apply_filters ("ws_plugin__s2member_registration_time", strtotime ($user->user_registered), get_defined_vars ());
29
+ }
30
+ else /* Else we return a default value of 0, because there is insufficient data. */
31
+ return apply_filters ("ws_plugin__s2member_registration_time", 0, get_defined_vars ());
32
+ }
33
+ }
34
+ /*
35
+ Retrieves a Paid Registration Time.
36
+
37
+ The $level argument is optional. It defaults to the first/initial Paid Registration Time, regardless of Level#.
38
+ Or you could do this: s2member_paid_registration_time("level1"); which will give you the Registration Time at Level #1.
39
+ If a User/Member has never paid for Level #1 ( i.e. they signed up at Level#2 ), the function will return 0.
40
+
41
+ Here are some other examples:
42
+ $time = ws_plugin__s2member_registration_time (); // ... first registration time ( free or otherwise ).
43
+ $time = ws_plugin__s2member_paid_registration_time (); // ... first "paid" registration and/or upgrade time.
44
+ $time = ws_plugin__s2member_paid_registration_time ("level1"); // ... first "paid" registration or upgrade time at Level#1.
45
+ $time = ws_plugin__s2member_paid_registration_time ("level2"); // ... first "paid" registration or upgrade time at Level#2.
46
+ $time = ws_plugin__s2member_paid_registration_time ("level3"); // ... first "paid" registration or upgrade time at Level#3.
47
+ $time = ws_plugin__s2member_paid_registration_time ("level4"); // ... first "paid" registration or upgrade time at Level#4.
48
+
49
+ The argument $user_id defaults to the current user; if logged in.
50
+ */
51
+ if (!function_exists ("ws_plugin__s2member_paid_registration_time"))
52
+ {
53
+ function ws_plugin__s2member_paid_registration_time ($level = FALSE, $user_id = FALSE)
54
+ {
55
+ $level = (!strlen ($level)) ? "level" : "level" . preg_replace ("/[^0-9]/", "", $level);
56
+ $user = ($user_id) ? new WP_User ($user_id) : ( (is_user_logged_in ()) ? wp_get_current_user () : false);
57
+ /**/
58
+ if ($level && is_object ($user) && ($user_id = $user->ID) && is_array ($pr_times = get_user_option ("s2member_paid_registration_times", $user_id)))
59
+ {
60
+ return apply_filters ("ws_plugin__s2member_paid_registration_time", (int)$pr_times[$level], get_defined_vars ());
61
+ }
62
+ else /* Else we return a default value of 0, because there is insufficient data. */
63
+ return apply_filters ("ws_plugin__s2member_paid_registration_time", 0, get_defined_vars ());
64
+ }
65
+ }
66
+ ?>
includes/functions/ruri-level-access.inc.php CHANGED
@@ -42,7 +42,7 @@ if (!function_exists ("ws_plugin__s2member_check_ruri_level_access"))
42
  /**/
43
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_redirection_override"] && ($login_redirection_uri = ws_plugin__s2member_login_redirection_uri ($current_user)) && preg_match ("/^" . preg_quote ($login_redirection_uri, "/") . "$/", $_SERVER["REQUEST_URI"]) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level0")))
44
  {
45
- wp_redirect (add_query_arg ("s2member_level_req", 0, get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
46
  exit ();
47
  }
48
  else if (!ws_plugin__s2member_is_systematic_use_page ()) /* Do NOT protect Systematics. However, there is 1 exception above ^. */
@@ -53,7 +53,7 @@ if (!function_exists ("ws_plugin__s2member_check_ruri_level_access"))
53
  foreach (preg_split ("/[\r\n\t]+/", ws_plugin__s2member_fill_ruri_level_access_rc_vars ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_ruris"], $current_user)) as $str)
54
  if ($str && preg_match ("/" . preg_quote ($str, "/") . "/", $_SERVER["REQUEST_URI"]) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
55
  {
56
- wp_redirect (add_query_arg ("s2member_level_req", $i, get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
57
  exit ();
58
  }
59
  }
@@ -136,10 +136,12 @@ if (!function_exists ("ws_plugin__s2member_fill_ruri_level_access_rc_vars"))
136
  $user_login = (is_object ($user)) ? strtolower ($user->user_login) : "";
137
  $user_id = (is_object ($user)) ? (string)$user->ID : "";
138
  $user_level = (string)ws_plugin__s2member_user_access_level ($user);
 
139
  /**/
140
  $uris = preg_replace ("/%%current_user_login%%/i", ws_plugin__s2member_esc_ds ($user_login), $uris);
141
  $uris = preg_replace ("/%%current_user_id%%/i", ws_plugin__s2member_esc_ds ($user_id), $uris);
142
  $uris = preg_replace ("/%%current_user_level%%/i", ws_plugin__s2member_esc_ds ($user_level), $uris);
 
143
  /**/
144
  return apply_filters ("ws_plugin__s2member_fill_ruri_level_access_rc_vars", $uris, get_defined_vars ());
145
  }
42
  /**/
43
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_redirection_override"] && ($login_redirection_uri = ws_plugin__s2member_login_redirection_uri ($current_user)) && preg_match ("/^" . preg_quote ($login_redirection_uri, "/") . "$/", $_SERVER["REQUEST_URI"]) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level0")))
44
  {
45
+ wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "ruri-" . base64_encode ($_SERVER["REQUEST_URI"]), "s2member_level_req" => "0")), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
46
  exit ();
47
  }
48
  else if (!ws_plugin__s2member_is_systematic_use_page ()) /* Do NOT protect Systematics. However, there is 1 exception above ^. */
53
  foreach (preg_split ("/[\r\n\t]+/", ws_plugin__s2member_fill_ruri_level_access_rc_vars ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $i . "_ruris"], $current_user)) as $str)
54
  if ($str && preg_match ("/" . preg_quote ($str, "/") . "/", $_SERVER["REQUEST_URI"]) && ws_plugin__s2member_nocache_constants (true) !== "nill" && (!$current_user || !current_user_can ("access_s2member_level" . $i)))
55
  {
56
+ wp_redirect (add_query_arg (urlencode_deep (array ("s2member_seeking" => "ruri-" . base64_encode ($_SERVER["REQUEST_URI"]), "s2member_level_req" => $i)), get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"])));
57
  exit ();
58
  }
59
  }
136
  $user_login = (is_object ($user)) ? strtolower ($user->user_login) : "";
137
  $user_id = (is_object ($user)) ? (string)$user->ID : "";
138
  $user_level = (string)ws_plugin__s2member_user_access_level ($user);
139
+ $user_role = (string)ws_plugin__s2member_user_access_role ($user);
140
  /**/
141
  $uris = preg_replace ("/%%current_user_login%%/i", ws_plugin__s2member_esc_ds ($user_login), $uris);
142
  $uris = preg_replace ("/%%current_user_id%%/i", ws_plugin__s2member_esc_ds ($user_id), $uris);
143
  $uris = preg_replace ("/%%current_user_level%%/i", ws_plugin__s2member_esc_ds ($user_level), $uris);
144
+ $uris = preg_replace ("/%%current_user_role%%/i", ws_plugin__s2member_esc_ds ($user_role), $uris);
145
  /**/
146
  return apply_filters ("ws_plugin__s2member_fill_ruri_level_access_rc_vars", $uris, get_defined_vars ());
147
  }
includes/functions/separates/paypal-notify.inc.php CHANGED
@@ -31,23 +31,24 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
31
  {
32
  function s__ws_plugin__s2member_paypal_notify ()
33
  {
34
- include_once ABSPATH . "wp-admin/includes/admin.php";
35
- /**/
36
  global $current_site, $current_blog; /* For Multisite support. */
37
  /**/
38
  do_action ("ws_plugin__s2member_before_paypal_notify", get_defined_vars ());
39
  /**/
40
- if ($_GET["s2member_paypal_notify"] && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])
41
  {
42
- if (is_array ($paypal = ws_plugin__s2member_paypal_postvars ())) /* Verify PayPal® POST vars. */
 
 
43
  {
44
  $paypal["s2member_log"][] = "IPN received on: " . date ("D M j, Y g:i:s a T");
45
- $paypal["s2member_log"][] = "s2Member POST vars verified through a POST back to PayPal®.";
 
46
  /**/
47
  $payment_status_issues = "/^(failed|denied|expired|refunded|partially_refunded|reversed|reversal|canceled_reversal|voided)$/i";
48
  /**/
49
  $paypal["custom"] = (!$paypal["custom"]) ? ws_plugin__s2member_paypal_custom ($paypal["recurring_payment_id"]) : $paypal["custom"];
50
- /* Notifications following the PayPal® Pro format for recurring payments, do NOT carry the "custom" value, so we do a lookup.
51
  This is only crucial for one IPN call in Standard Integration: `txn_type=recurring_payment_suspended_due_to_max_failed_payment`.
52
  In Pro Integrations, we just need to make sure the "custom" field is assigned for each account during on-site checkout.
53
  This way the "custom" value will always be available when it needs to be; for both Standard and Pro services. */
@@ -196,13 +197,13 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
196
  {
197
  $processing = $during = true; /* Yes, we ARE processing this. */
198
  /**/
199
- $sbj = preg_replace ("/%%sp_access_url%%/i", ws_plugin__s2member_esc_ds ($sp_access_url), $GLOBALS["WS_PLUGIN__"]["s2member"]["o"][ ( ($_GET["s2member_paypal_proxy"] === "s2member-pro-module") ? "pro_" : "") . "sp_email_subject"]);
200
  $sbj = preg_replace ("/%%sp_access_exp%%/i", ws_plugin__s2member_esc_ds (ws_plugin__s2member_approx_time_difference (time (), strtotime ("+" . $paypal["hours"] . " hours"))), $sbj);
201
  /**/
202
- $msg = preg_replace ("/%%sp_access_url%%/i", ws_plugin__s2member_esc_ds ($sp_access_url), $GLOBALS["WS_PLUGIN__"]["s2member"]["o"][ ( ($_GET["s2member_paypal_proxy"] === "s2member-pro-module") ? "pro_" : "") . "sp_email_message"]);
203
  $msg = preg_replace ("/%%sp_access_exp%%/i", ws_plugin__s2member_esc_ds (ws_plugin__s2member_approx_time_difference (time (), strtotime ("+" . $paypal["hours"] . " hours"))), $msg);
204
  /**/
205
- $rec = preg_replace ("/%%sp_access_url%%/i", ws_plugin__s2member_esc_ds ($sp_access_url), $GLOBALS["WS_PLUGIN__"]["s2member"]["o"][ ( ($_GET["s2member_paypal_proxy"] === "s2member-pro-module") ? "pro_" : "") . "sp_email_recipients"]);
206
  $rec = preg_replace ("/%%sp_access_exp%%/i", ws_plugin__s2member_esc_ds (ws_plugin__s2member_approx_time_difference (time (), strtotime ("+" . $paypal["hours"] . " hours"))), $rec);
207
  /**/
208
  if (($rec = preg_replace ("/%%cv([0-9]+)%%/ei", 'trim($cv[$1])', $rec)) && ($rec = preg_replace ("/%%txn_id%%/i", ws_plugin__s2member_esc_ds ($paypal["txn_id"]), $rec)))
@@ -211,30 +212,28 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
211
  if (($rec = preg_replace ("/%%first_name%%/i", ws_plugin__s2member_esc_dq (ws_plugin__s2member_esc_ds ($paypal["first_name"])), $rec)) && ($rec = preg_replace ("/%%last_name%%/i", ws_plugin__s2member_esc_dq (ws_plugin__s2member_esc_ds ($paypal["last_name"])), $rec)))
212
  if (($rec = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_dq (ws_plugin__s2member_esc_ds (trim ($paypal["first_name"] . " " . $paypal["last_name"]))), $rec))) /* **NOTE** ws_plugin__s2member_esc_dq() is applied here. ( ex. "N\"ame" <email> ). */
213
  if (($rec = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds ($paypal["payer_email"]), $rec)))
214
- if (($recipients = preg_split ("/;+/", $rec))) /* Here we break the recipients into an array. */
215
- /**/
216
- if (($sbj = preg_replace ("/%%cv([0-9]+)%%/ei", 'trim($cv[$1])', $sbj)) && ($sbj = preg_replace ("/%%txn_id%%/i", ws_plugin__s2member_esc_ds ($paypal["txn_id"]), $sbj)))
217
- if (($sbj = preg_replace ("/%%amount%%/i", ws_plugin__s2member_esc_ds ($paypal["mc_gross"]), $sbj))) /* Full amount of the payment, before fee is subtracted. */
218
- if (($sbj = preg_replace ("/%%item_number%%/i", ws_plugin__s2member_esc_ds ($paypal["item_number"]), $sbj)) && ($sbj = preg_replace ("/%%item_name%%/i", ws_plugin__s2member_esc_ds ($paypal["item_name"]), $sbj)))
219
- if (($sbj = preg_replace ("/%%first_name%%/i", ws_plugin__s2member_esc_ds ($paypal["first_name"]), $sbj)) && ($sbj = preg_replace ("/%%last_name%%/i", ws_plugin__s2member_esc_ds ($paypal["last_name"]), $sbj)))
220
- if (($sbj = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $sbj)))
221
- if (($sbj = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds ($paypal["payer_email"]), $sbj)))
222
- /**/
223
- if (($msg = preg_replace ("/%%cv([0-9]+)%%/ei", 'trim($cv[$1])', $msg)) && ($msg = preg_replace ("/%%txn_id%%/i", ws_plugin__s2member_esc_ds ($paypal["txn_id"]), $msg)))
224
- if (($msg = preg_replace ("/%%amount%%/i", ws_plugin__s2member_esc_ds ($paypal["mc_gross"]), $msg))) /* Full amount of the payment, before fee is subtracted. */
225
- if (($msg = preg_replace ("/%%item_number%%/i", ws_plugin__s2member_esc_ds ($paypal["item_number"]), $msg)) && ($msg = preg_replace ("/%%item_name%%/i", ws_plugin__s2member_esc_ds ($paypal["item_name"]), $msg)))
226
- if (($msg = preg_replace ("/%%first_name%%/i", ws_plugin__s2member_esc_ds ($paypal["first_name"]), $msg)) && ($msg = preg_replace ("/%%last_name%%/i", ws_plugin__s2member_esc_ds ($paypal["last_name"]), $msg)))
227
- if (($msg = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $msg)))
228
- if (($msg = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds ($paypal["payer_email"]), $msg)))
229
- /**/
230
- if (($sbj = trim ($sbj)) && ($msg = trim ($msg))) /* Make sure they are not empty. */
231
- {
232
- foreach (ws_plugin__s2member_trim_deep ($recipients) as $recipient) /* Go through the full list of recipients. */
233
- /**/
234
- ($recipient) ? mail ($recipient, $sbj, $msg, "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
235
- /**/
236
- $paypal["s2member_log"][] = "Specific Post/Page Confirmation Email sent to: " . implode ("; ", $recipients) . ".";
237
- }
238
  /**/
239
  if ($processing && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sp_sale_notification_urls"])
240
  {
@@ -248,8 +247,8 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
248
  if (($url = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (urlencode (trim ($paypal["first_name"] . " " . $paypal["last_name"]))), $url)))
249
  if (($url = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["payer_email"])), $url)))
250
  /**/
251
- if (($url = trim ($url))) /* Empty? */
252
- ws_plugin__s2member_remote($url);
253
  /**/
254
  $paypal["s2member_log"][] = "Specific Post/Page ~ Sale Notification URLs have been processed.";
255
  }
@@ -258,6 +257,7 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
258
  {
259
  $msg = $sbj = "( s2Member / API Notification Email ) - Specific Post/Page ~ Sale";
260
  $msg .= "\n\n"; /* Spacing in the message body. */
 
261
  $msg .= "sp_access_url: %%sp_access_url%%\n";
262
  $msg .= "sp_access_exp: %%sp_access_exp%%\n";
263
  $msg .= "amount: %%amount%%\n";
@@ -287,14 +287,14 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
287
  if (($msg = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $msg)))
288
  if (($msg = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds ($paypal["payer_email"]), $msg)))
289
  /**/
290
- foreach (ws_plugin__s2member_trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sp_sale_notification_recipients"])) as $recipient)
291
- /**/
292
- ($recipient) ? mail ($recipient, $sbj, apply_filters ("ws_plugin__s2member_sp_sale_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
293
  /**/
294
  $paypal["s2member_log"][] = "Specific Post/Page ~ Sale Notification Emails have been processed.";
295
  }
296
  /**/
297
- if ($processing && ($url = $paypal["proxy_return_url"])) /* A proxy is requesting a return URL for this transaction? */
298
  {
299
  if (($url = preg_replace ("/%%cv([0-9]+)%%/ei", 'urlencode(trim($cv[$1]))', $url)) && ($url = preg_replace ("/%%sp_access_url%%/i", ws_plugin__s2member_esc_ds (rawurlencode ($sp_access_url)), $url)))
300
  if (($url = preg_replace ("/%%sp_access_exp%%/i", ws_plugin__s2member_esc_ds (urlencode (ws_plugin__s2member_approx_time_difference (time (), strtotime ("+" . $paypal["hours"] . " hours")))), $url)))
@@ -304,8 +304,9 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
304
  if (($url = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (urlencode (trim ($paypal["first_name"] . " " . $paypal["last_name"]))), $url)))
305
  if (($url = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["payer_email"])), $url)))
306
  /**/
307
- if (($url = trim ($url))) /* Empty? */
308
- $paypal["proxy_return_url"] = $url;
 
309
  /**/
310
  $paypal["s2member_log"][] = "Specific Post/Page Return, a Proxy Return URL is ready.";
311
  }
@@ -318,7 +319,7 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
318
  if (($code = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $code)))
319
  if (($code = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds ($paypal["payer_email"]), $code)))
320
  /**/
321
- if (($code = trim ($code))) /* Make sure it is not empty. This gets stored into a Transient Queue. */
322
  {
323
  $paypal["s2member_log"][] = "Storing Specific Post/Page Tracking Codes into a Transient Queue for s2Member. These will be processed on-site.";
324
  set_transient (md5 ("s2member_transient_sp_tracking_codes_" . $paypal["txn_id"]), $code, 43200);
@@ -359,20 +360,20 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
359
  /**/
360
  if (preg_match ("/^web_accept$/i", $paypal["txn_type"])) /* Conversions for Lifetime & Fixed-Term sales. */
361
  {
362
- $paypal["period3"] = ($paypal["eotper"]) ? $paypal["eotper"] : "1 L"; /* This defaults to exactly 1 Lifetime. */
363
  $paypal["mc_amount3"] = $paypal["mc_gross"]; /* The "Buy Now" amount. */
364
  }
365
  /**/
366
- $paypal["initial_term"] = $paypal["period1"] ? $paypal["period1"] : "0 D"; /* Do not allow the initial period to be empty. Defaults to 0 D. */
367
- $paypal["initial"] = (isset ($paypal["mc_amount1"]) && preg_match ("/^[1-9]/", $paypal["period1"])) ? $paypal["mc_amount1"] : $paypal["mc_amount3"];
368
- $paypal["regular"] = $paypal["mc_amount3"]; /* This is the regular payment amount that is charged to the customer. Always required by PayPal. */
369
  $paypal["regular_term"] = $paypal["period3"]; /* This is just set to keep a standard; this way both initial_term & regular_term are available. */
370
- $paypal["recurring"] = ($paypal["recurring"]) ? $paypal["mc_amount3"] : "0"; /* If non-recurring, this should be zero, otherwise regular. */
371
  /*
372
  New Subscription with advanced update vars ( option_name1, option_selection1 ).
373
  */
374
  if (preg_match ("/(updat|upgrad)/i", $paypal["option_name1"]) && $paypal["option_selection1"]) /* This is an advanced way to handle Subscription update modifications. */
375
- /* This advanced method is required whenever a Subscription that is already completed, or was never setup to recur in the first place needs to be modified. PayPal will not allow the
376
  modify=1|2 parameter to be used in those scenarios, because technically there is nothing to update. The only thing that actually needs to be updated is the account. */
377
  {
378
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
@@ -388,6 +389,8 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
388
  {
389
  $processing = $modifying = $during = true; /* Yes, we ARE processing this. */
390
  /**/
 
 
391
  $user->set_role ("s2member_level" . $paypal["level"]);
392
  /**/
393
  foreach ($user->allcaps as $cap => $cap_enabled)
@@ -409,11 +412,16 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
409
  else /* Otherwise, we need to clear the eot time. */
410
  delete_user_option ($user_id, "s2member_auto_eot_time");
411
  /**/
 
 
 
 
 
412
  ws_plugin__s2member_clear_user_note_lines ($user_id, "/^Demoted by s2Member\:/");
413
  /**/
414
  $paypal["s2member_log"][] = "s2Member Level/Capabilities updated w/ advanced update routines.";
415
  /**/
416
- mail ($paypal["payer_email"], "Thank You! Your membership has been updated.", "Thank You! Your membership has been updated to:\n" . $paypal["item_name"] . "\n\nYou'll need to log back in now.\n" . wp_login_url (), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8");
417
  /**/
418
  $paypal["s2member_log"][] = "Modification Confirmation Email sent to Customer, with a URL that provides them with a way to log back in.";
419
  /**/
@@ -450,49 +458,47 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
450
  {
451
  $processing = $during = true; /* Yes, we ARE processing this. */
452
  /**/
453
- $sbj = preg_replace ("/%%registration_url%%/i", ws_plugin__s2member_esc_ds ($registration_url), $GLOBALS["WS_PLUGIN__"]["s2member"]["o"][ ( ($_GET["s2member_paypal_proxy"] === "s2member-pro-module") ? "pro_" : "") . "signup_email_subject"]);
454
- $msg = preg_replace ("/%%registration_url%%/i", ws_plugin__s2member_esc_ds ($registration_url), $GLOBALS["WS_PLUGIN__"]["s2member"]["o"][ ( ($_GET["s2member_paypal_proxy"] === "s2member-pro-module") ? "pro_" : "") . "signup_email_message"]);
455
- $rec = preg_replace ("/%%registration_url%%/i", ws_plugin__s2member_esc_ds ($registration_url), $GLOBALS["WS_PLUGIN__"]["s2member"]["o"][ ( ($_GET["s2member_paypal_proxy"] === "s2member-pro-module") ? "pro_" : "") . "signup_email_recipients"]);
456
  /**/
457
  if (($rec = preg_replace ("/%%cv([0-9]+)%%/ei", 'trim($cv[$1])', $rec)) && ($rec = preg_replace ("/%%subscr_id%%/i", ws_plugin__s2member_esc_ds ($paypal["subscr_id"]), $rec)))
458
  if (($rec = preg_replace ("/%%initial%%/i", ws_plugin__s2member_esc_ds ($paypal["initial"]), $rec)) && ($rec = preg_replace ("/%%regular%%/i", ws_plugin__s2member_esc_ds ($paypal["regular"]), $rec)))
459
  if (($rec = preg_replace ("/%%initial_term%%/i", ws_plugin__s2member_esc_ds ($paypal["initial_term"]), $rec)) && ($rec = preg_replace ("/%%regular_term%%/i", ws_plugin__s2member_esc_ds ($paypal["regular_term"]), $rec)))
460
- if (($rec = preg_replace ("/%%initial_cycle%%/i", ws_plugin__s2member_esc_ds (ws_plugin__s2member_paypal_term_cycle ($paypal["initial_term"])), $rec)) && ($rec = preg_replace ("/%%regular_cycle%%/i", ws_plugin__s2member_esc_ds (ws_plugin__s2member_paypal_term_cycle ($paypal["regular_term"])), $rec)))
461
- if (($rec = preg_replace ("/%%recurring%%/i", ws_plugin__s2member_esc_ds ($paypal["recurring"]), $rec)) && ($rec = preg_replace ("/%%recurring\/regular_cycle%%/i", ws_plugin__s2member_esc_ds (( ($paypal["recurring"]) ? $paypal["recurring"] . " / " . ws_plugin__s2member_paypal_term_cycle ($paypal["regular_term"]) : "0 / non-recurring")), $rec)))
462
  if (($rec = preg_replace ("/%%item_number%%/i", ws_plugin__s2member_esc_ds ($paypal["item_number"]), $rec)) && ($rec = preg_replace ("/%%item_name%%/i", ws_plugin__s2member_esc_ds ($paypal["item_name"]), $rec)))
463
  if (($rec = preg_replace ("/%%first_name%%/i", ws_plugin__s2member_esc_dq (ws_plugin__s2member_esc_ds ($paypal["first_name"])), $rec)) && ($rec = preg_replace ("/%%last_name%%/i", ws_plugin__s2member_esc_dq (ws_plugin__s2member_esc_ds ($paypal["last_name"])), $rec)))
464
  if (($rec = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_dq (ws_plugin__s2member_esc_ds (trim ($paypal["first_name"] . " " . $paypal["last_name"]))), $rec))) /* **NOTE** ws_plugin__s2member_esc_dq() is applied here. ( ex. "N\"ame" <email> ). */
465
  if (($rec = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds ($paypal["payer_email"]), $rec)))
466
- if (($recipients = preg_split ("/;+/", $rec))) /* Here we break the recipients into an array. */
467
- /**/
468
- if (($sbj = preg_replace ("/%%cv([0-9]+)%%/ei", 'trim($cv[$1])', $sbj)) && ($sbj = preg_replace ("/%%subscr_id%%/i", ws_plugin__s2member_esc_ds ($paypal["subscr_id"]), $sbj)))
469
- if (($sbj = preg_replace ("/%%initial%%/i", ws_plugin__s2member_esc_ds ($paypal["initial"]), $sbj)) && ($sbj = preg_replace ("/%%regular%%/i", ws_plugin__s2member_esc_ds ($paypal["regular"]), $sbj)))
470
- if (($sbj = preg_replace ("/%%initial_term%%/i", ws_plugin__s2member_esc_ds ($paypal["initial_term"]), $sbj)) && ($sbj = preg_replace ("/%%regular_term%%/i", ws_plugin__s2member_esc_ds ($paypal["regular_term"]), $sbj)))
471
- if (($sbj = preg_replace ("/%%initial_cycle%%/i", ws_plugin__s2member_esc_ds (ws_plugin__s2member_paypal_term_cycle ($paypal["initial_term"])), $sbj)) && ($sbj = preg_replace ("/%%regular_cycle%%/i", ws_plugin__s2member_esc_ds (ws_plugin__s2member_paypal_term_cycle ($paypal["regular_term"])), $sbj)))
472
- if (($sbj = preg_replace ("/%%recurring%%/i", ws_plugin__s2member_esc_ds ($paypal["recurring"]), $sbj)) && ($sbj = preg_replace ("/%%recurring\/regular_cycle%%/i", ws_plugin__s2member_esc_ds (( ($paypal["recurring"]) ? $paypal["recurring"] . " / " . ws_plugin__s2member_paypal_term_cycle ($paypal["regular_term"]) : "0 / non-recurring")), $sbj)))
473
- if (($sbj = preg_replace ("/%%item_number%%/i", ws_plugin__s2member_esc_ds ($paypal["item_number"]), $sbj)) && ($sbj = preg_replace ("/%%item_name%%/i", ws_plugin__s2member_esc_ds ($paypal["item_name"]), $sbj)))
474
- if (($sbj = preg_replace ("/%%first_name%%/i", ws_plugin__s2member_esc_ds ($paypal["first_name"]), $sbj)) && ($sbj = preg_replace ("/%%last_name%%/i", ws_plugin__s2member_esc_ds ($paypal["last_name"]), $sbj)))
475
- if (($sbj = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $sbj)))
476
- if (($sbj = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds ($paypal["payer_email"]), $sbj)))
477
- /**/
478
- if (($msg = preg_replace ("/%%cv([0-9]+)%%/ei", 'trim($cv[$1])', $msg)) && ($msg = preg_replace ("/%%subscr_id%%/i", ws_plugin__s2member_esc_ds ($paypal["subscr_id"]), $msg)))
479
- if (($msg = preg_replace ("/%%initial%%/i", ws_plugin__s2member_esc_ds ($paypal["initial"]), $msg)) && ($msg = preg_replace ("/%%regular%%/i", ws_plugin__s2member_esc_ds ($paypal["regular"]), $msg)))
480
- if (($msg = preg_replace ("/%%initial_term%%/i", ws_plugin__s2member_esc_ds ($paypal["initial_term"]), $msg)) && ($msg = preg_replace ("/%%regular_term%%/i", ws_plugin__s2member_esc_ds ($paypal["regular_term"]), $msg)))
481
- if (($msg = preg_replace ("/%%initial_cycle%%/i", ws_plugin__s2member_esc_ds (ws_plugin__s2member_paypal_term_cycle ($paypal["initial_term"])), $msg)) && ($msg = preg_replace ("/%%regular_cycle%%/i", ws_plugin__s2member_esc_ds (ws_plugin__s2member_paypal_term_cycle ($paypal["regular_term"])), $msg)))
482
- if (($msg = preg_replace ("/%%recurring%%/i", ws_plugin__s2member_esc_ds ($paypal["recurring"]), $msg)) && ($msg = preg_replace ("/%%recurring\/regular_cycle%%/i", ws_plugin__s2member_esc_ds (( ($paypal["recurring"]) ? $paypal["recurring"] . " / " . ws_plugin__s2member_paypal_term_cycle ($paypal["regular_term"]) : "0 / non-recurring")), $msg)))
483
- if (($msg = preg_replace ("/%%item_number%%/i", ws_plugin__s2member_esc_ds ($paypal["item_number"]), $msg)) && ($msg = preg_replace ("/%%item_name%%/i", ws_plugin__s2member_esc_ds ($paypal["item_name"]), $msg)))
484
- if (($msg = preg_replace ("/%%first_name%%/i", ws_plugin__s2member_esc_ds ($paypal["first_name"]), $msg)) && ($msg = preg_replace ("/%%last_name%%/i", ws_plugin__s2member_esc_ds ($paypal["last_name"]), $msg)))
485
- if (($msg = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $msg)))
486
- if (($msg = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds ($paypal["payer_email"]), $msg)))
487
- /**/
488
- if (($sbj = trim ($sbj)) && ($msg = trim ($msg))) /* Make sure they are not empty. */
489
- {
490
- foreach (ws_plugin__s2member_trim_deep ($recipients) as $recipient) /* Go through the full list of recipients. */
491
- /**/
492
- ($recipient) ? mail ($recipient, $sbj, $msg, "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
493
- /**/
494
- $paypal["s2member_log"][] = "Signup Confirmation Email sent to: " . implode ("; ", $recipients) . ".";
495
- }
496
  /**/
497
  if ($processing && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["signup_notification_urls"] && is_array ($cv = preg_split ("/\|/", $paypal["custom"])))
498
  {
@@ -506,8 +512,8 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
506
  if (($url = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (urlencode (trim ($paypal["first_name"] . " " . $paypal["last_name"]))), $url)))
507
  if (($url = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["payer_email"])), $url)))
508
  /**/
509
- if (($url = trim ($url))) /* Empty? */
510
- ws_plugin__s2member_remote($url);
511
  /**/
512
  $paypal["s2member_log"][] = "Signup Notification URLs have been processed.";
513
  }
@@ -516,6 +522,7 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
516
  {
517
  $msg = $sbj = "( s2Member / API Notification Email ) - Signup";
518
  $msg .= "\n\n"; /* Spacing in the message body. */
 
519
  $msg .= "subscr_id: %%subscr_id%%\n";
520
  $msg .= "initial: %%initial%%\n";
521
  $msg .= "regular: %%regular%%\n";
@@ -547,9 +554,9 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
547
  if (($msg = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $msg)))
548
  if (($msg = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds ($paypal["payer_email"]), $msg)))
549
  /**/
550
- foreach (ws_plugin__s2member_trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["signup_notification_recipients"])) as $recipient)
551
- /**/
552
- ($recipient) ? mail ($recipient, $sbj, apply_filters ("ws_plugin__s2member_signup_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
553
  /**/
554
  $paypal["s2member_log"][] = "Signup Notification Emails have been processed.";
555
  }
@@ -564,7 +571,7 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
564
  if (($code = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $code)))
565
  if (($code = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds ($paypal["payer_email"]), $code)))
566
  /**/
567
- if (($code = trim ($code))) /* Make sure it is not empty. This gets stored into a Transient Queue. */
568
  {
569
  $paypal["s2member_log"][] = "Storing Signup Tracking Codes into a Transient Queue for s2Member. These will be processed on-site.";
570
  set_transient (md5 ("s2member_transient_signup_tracking_codes_" . $paypal["subscr_id"]), $code, 43200);
@@ -585,80 +592,159 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
585
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
586
  }
587
  /**/
588
- if ($processing && ($url = $paypal["proxy_return_url"])) /* A proxy is requesting a return URL for this transaction? */
589
  {
590
- if (($url = preg_replace ("/%%cv([0-9]+)%%/ei", 'urlencode(trim($cv[$1]))', $url)) && ($url = preg_replace ("/%%subscr_id%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["subscr_id"])), $url)))
591
- if (($url = preg_replace ("/%%initial%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["initial"])), $url)) && ($url = preg_replace ("/%%regular%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["regular"])), $url)) && ($url = preg_replace ("/%%recurring%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["recurring"])), $url)))
592
- if (($url = preg_replace ("/%%initial_term%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["initial_term"])), $url)) && ($url = preg_replace ("/%%regular_term%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["regular_term"])), $url)))
593
- if (($url = preg_replace ("/%%item_number%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["item_number"])), $url)) && ($url = preg_replace ("/%%item_name%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["item_name"])), $url)))
594
- if (($url = preg_replace ("/%%first_name%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["first_name"])), $url)) && ($url = preg_replace ("/%%last_name%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["last_name"])), $url)))
595
- if (($url = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (urlencode (trim ($paypal["first_name"] . " " . $paypal["last_name"]))), $url)))
596
- if (($url = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["payer_email"])), $url)))
597
- if (($url = preg_replace ("/%%modification%%/i", ws_plugin__s2member_esc_ds (urlencode ((int)$modifying)), $url)))
598
- /* The modification variable indicates whether this was a modification, or a new signup. */
599
- if (($url = trim ($url))) /* Empty? */
600
- $paypal["proxy_return_url"] = $url;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
601
  /**/
602
  $paypal["s2member_log"][] = "Subscr. Return ( modification=" . (int)$modifying . " ), a Proxy Return URL is ready.";
603
  }
604
  /**/
605
- if ($processing && preg_match ("/^web_accept$/i", $paypal["txn_type"]) && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["payment_notification_urls"] && is_array ($cv = preg_split ("/\|/", $paypal["custom"])))
606
  {
607
- foreach (preg_split ("/[\r\n\t]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["payment_notification_urls"]) as $url)
608
- /**/
609
- if (($url = preg_replace ("/%%cv([0-9]+)%%/ei", 'urlencode(trim($cv[$1]))', $url)) && ($url = preg_replace ("/%%subscr_id%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["subscr_id"])), $url)))
610
- if (($url = preg_replace ("/%%subscr_payment%%/i", ws_plugin__s2member_esc_ds (urlencode ("0")), $url)) && ($url = preg_replace ("/%%subscr_payment_user_id%%/i", ws_plugin__s2member_esc_ds (urlencode ("")), $url)))
611
- if (($url = preg_replace ("/%%amount%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["mc_gross"])), $url)) && ($url = preg_replace ("/%%txn_id%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["txn_id"])), $url)))
612
- if (($url = preg_replace ("/%%item_number%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["item_number"])), $url)) && ($url = preg_replace ("/%%item_name%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["item_name"])), $url)))
613
- if (($url = preg_replace ("/%%first_name%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["first_name"])), $url)) && ($url = preg_replace ("/%%last_name%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["last_name"])), $url)))
614
- if (($url = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (urlencode (trim ($paypal["first_name"] . " " . $paypal["last_name"]))), $url)))
615
- if (($url = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["payer_email"])), $url)))
616
- /**/
617
- if (($url = trim ($url))) /* Empty? */
618
- ws_plugin__s2member_remote($url);
619
  /**/
620
- $paypal["s2member_log"][] = "Payment Notification URLs have been processed.";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
621
  }
622
- /**/
623
- if ($processing && preg_match ("/^web_accept$/i", $paypal["txn_type"]) && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["payment_notification_recipients"] && is_array ($cv = preg_split ("/\|/", $paypal["custom"])))
624
  {
625
- $msg = $sbj = "( s2Member / API Notification Email ) - Payment";
626
- $msg .= "\n\n"; /* Spacing in the message body. */
627
- $msg .= "subscr_id: %%subscr_id%%\n";
628
- $msg .= "subscr_payment: %%subscr_payment%%\n";
629
- $msg .= "subscr_payment_user_id: %%subscr_payment_user_id%%\n";
630
- $msg .= "amount: %%amount%%\n";
631
- $msg .= "txn_id: %%txn_id%%\n";
632
- $msg .= "item_number: %%item_number%%\n";
633
- $msg .= "item_name: %%item_name%%\n";
634
- $msg .= "first_name: %%first_name%%\n";
635
- $msg .= "last_name: %%last_name%%\n";
636
- $msg .= "full_name: %%full_name%%\n";
637
- $msg .= "payer_email: %%payer_email%%\n";
638
- $msg .= "cv0: %%cv0%%\n";
639
- $msg .= "cv1: %%cv1%%\n";
640
- $msg .= "cv2: %%cv2%%\n";
641
- $msg .= "cv3: %%cv3%%\n";
642
- $msg .= "cv4: %%cv4%%\n";
643
- $msg .= "cv5: %%cv5%%\n";
644
- $msg .= "cv6: %%cv6%%\n";
645
- $msg .= "cv7: %%cv7%%\n";
646
- $msg .= "cv8: %%cv8%%\n";
647
- $msg .= "cv9: %%cv9%%";
648
  /**/
649
- if (($msg = preg_replace ("/%%cv([0-9]+)%%/ei", 'trim($cv[$1])', $msg)) && ($msg = preg_replace ("/%%subscr_id%%/i", ws_plugin__s2member_esc_ds ($paypal["subscr_id"]), $msg)))
650
- if (($msg = preg_replace ("/%%subscr_payment%%/i", ws_plugin__s2member_esc_ds ("0"), $msg)) && ($msg = preg_replace ("/%%subscr_payment_user_id%%/i", ws_plugin__s2member_esc_ds (""), $msg)))
651
- if (($msg = preg_replace ("/%%amount%%/i", ws_plugin__s2member_esc_ds ($paypal["mc_gross"]), $msg)) && ($msg = preg_replace ("/%%txn_id%%/i", ws_plugin__s2member_esc_ds ($paypal["txn_id"]), $msg)))
652
- if (($msg = preg_replace ("/%%item_number%%/i", ws_plugin__s2member_esc_ds ($paypal["item_number"]), $msg)) && ($msg = preg_replace ("/%%item_name%%/i", ws_plugin__s2member_esc_ds ($paypal["item_name"]), $msg)))
653
- if (($msg = preg_replace ("/%%first_name%%/i", ws_plugin__s2member_esc_ds ($paypal["first_name"]), $msg)) && ($msg = preg_replace ("/%%last_name%%/i", ws_plugin__s2member_esc_ds ($paypal["last_name"]), $msg)))
654
- if (($msg = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $msg)))
655
- if (($msg = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds ($paypal["payer_email"]), $msg)))
656
- /**/
657
- foreach (ws_plugin__s2member_trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["payment_notification_recipients"])) as $recipient)
658
- /**/
659
- ($recipient) ? mail ($recipient, $sbj, apply_filters ("ws_plugin__s2member_payment_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
660
  /**/
661
- $paypal["s2member_log"][] = "Payment Notification Emails have been processed.";
 
662
  }
663
  /**/
664
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
@@ -666,7 +752,7 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
666
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
667
  }
668
  /*
669
- Recurring payment profile creation.
670
  This is not really necessary. It is only here because this txn_type could
671
  be necessary in a future release of s2Member. For now, it's just a fill-in.
672
  These Hooks/Filters will remain, so you can use them now; if you need to.
@@ -718,6 +804,8 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
718
  {
719
  $processing = $modifying = $during = true; /* Yes, we ARE processing this. */
720
  /**/
 
 
721
  $user->set_role ("s2member_level" . $paypal["level"]);
722
  /**/
723
  foreach ($user->allcaps as $cap => $cap_enabled)
@@ -736,11 +824,16 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
736
  /**/
737
  delete_user_option ($user_id, "s2member_auto_eot_time");
738
  /**/
 
 
 
 
 
739
  ws_plugin__s2member_clear_user_note_lines ($user_id, "/^Demoted by s2Member\:/");
740
  /**/
741
  $paypal["s2member_log"][] = "s2Member Level/Capabilities updated on Subscription modification.";
742
  /**/
743
- mail ($paypal["payer_email"], "Thank You! Your membership has been updated.", "Thank You! Your membership has been updated to:\n" . $paypal["item_name"] . "\n\nYou'll need to log back in now.\n" . wp_login_url (), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8");
744
  /**/
745
  $paypal["s2member_log"][] = "Modification Confirmation Email sent to Customer, with a URL that provides them with a way to log back in.";
746
  /**/
@@ -791,24 +884,43 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
791
  {
792
  $processing = $during = true; /* Yes, we ARE processing this. */
793
  /**/
794
- update_user_option ($user_id, "s2member_last_payment_time", time ());
 
 
 
 
 
795
  /**/
796
- $paypal["s2member_log"][] = "Updated Last Payment Time for this Member.";
 
 
797
  /**/
798
  if ($processing && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["payment_notification_urls"] && is_array ($cv = preg_split ("/\|/", $paypal["custom"])))
799
  {
800
  foreach (preg_split ("/[\r\n\t]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["payment_notification_urls"]) as $url)
801
  /**/
802
  if (($url = preg_replace ("/%%cv([0-9]+)%%/ei", 'urlencode(trim($cv[$1]))', $url)) && ($url = preg_replace ("/%%subscr_id%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["subscr_id"])), $url)))
803
- if (($url = preg_replace ("/%%subscr_payment%%/i", ws_plugin__s2member_esc_ds (urlencode ("1")), $url)) && ($url = preg_replace ("/%%subscr_payment_user_id%%/i", ws_plugin__s2member_esc_ds (urlencode ($user_id)), $url)))
804
- if (($url = preg_replace ("/%%amount%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["mc_gross"])), $url)) && ($url = preg_replace ("/%%txn_id%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["txn_id"])), $url)))
805
- if (($url = preg_replace ("/%%item_number%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["item_number"])), $url)) && ($url = preg_replace ("/%%item_name%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["item_name"])), $url)))
806
- if (($url = preg_replace ("/%%first_name%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["first_name"])), $url)) && ($url = preg_replace ("/%%last_name%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["last_name"])), $url)))
807
- if (($url = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (urlencode (trim ($paypal["first_name"] . " " . $paypal["last_name"]))), $url)))
808
- if (($url = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["payer_email"])), $url)))
809
- /**/
810
- if (($url = trim ($url))) /* Empty? */
811
- ws_plugin__s2member_remote($url);
 
 
 
 
 
 
 
 
 
 
 
 
812
  /**/
813
  $paypal["s2member_log"][] = "Payment Notification URLs have been processed.";
814
  }
@@ -817,9 +929,8 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
817
  {
818
  $msg = $sbj = "( s2Member / API Notification Email ) - Payment";
819
  $msg .= "\n\n"; /* Spacing in the message body. */
 
820
  $msg .= "subscr_id: %%subscr_id%%\n";
821
- $msg .= "subscr_payment: %%subscr_payment%%\n";
822
- $msg .= "subscr_payment_user_id: %%subscr_payment_user_id%%\n";
823
  $msg .= "amount: %%amount%%\n";
824
  $msg .= "txn_id: %%txn_id%%\n";
825
  $msg .= "item_number: %%item_number%%\n";
@@ -828,6 +939,18 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
828
  $msg .= "last_name: %%last_name%%\n";
829
  $msg .= "full_name: %%full_name%%\n";
830
  $msg .= "payer_email: %%payer_email%%\n";
 
 
 
 
 
 
 
 
 
 
 
 
831
  $msg .= "cv0: %%cv0%%\n";
832
  $msg .= "cv1: %%cv1%%\n";
833
  $msg .= "cv2: %%cv2%%\n";
@@ -840,16 +963,28 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
840
  $msg .= "cv9: %%cv9%%";
841
  /**/
842
  if (($msg = preg_replace ("/%%cv([0-9]+)%%/ei", 'trim($cv[$1])', $msg)) && ($msg = preg_replace ("/%%subscr_id%%/i", ws_plugin__s2member_esc_ds ($paypal["subscr_id"]), $msg)))
843
- if (($msg = preg_replace ("/%%subscr_payment%%/i", ws_plugin__s2member_esc_ds ("1"), $msg)) && ($msg = preg_replace ("/%%subscr_payment_user_id%%/i", ws_plugin__s2member_esc_ds ($user_id), $msg)))
844
- if (($msg = preg_replace ("/%%amount%%/i", ws_plugin__s2member_esc_ds ($paypal["mc_gross"]), $msg)) && ($msg = preg_replace ("/%%txn_id%%/i", ws_plugin__s2member_esc_ds ($paypal["txn_id"]), $msg)))
845
- if (($msg = preg_replace ("/%%item_number%%/i", ws_plugin__s2member_esc_ds ($paypal["item_number"]), $msg)) && ($msg = preg_replace ("/%%item_name%%/i", ws_plugin__s2member_esc_ds ($paypal["item_name"]), $msg)))
846
- if (($msg = preg_replace ("/%%first_name%%/i", ws_plugin__s2member_esc_ds ($paypal["first_name"]), $msg)) && ($msg = preg_replace ("/%%last_name%%/i", ws_plugin__s2member_esc_ds ($paypal["last_name"]), $msg)))
847
- if (($msg = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $msg)))
848
- if (($msg = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds ($paypal["payer_email"]), $msg)))
849
- /**/
850
- foreach (ws_plugin__s2member_trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["payment_notification_recipients"])) as $recipient)
851
- /**/
852
- ($recipient) ? mail ($recipient, $sbj, apply_filters ("ws_plugin__s2member_payment_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
 
 
 
 
 
 
 
 
 
 
 
 
853
  /**/
854
  $paypal["s2member_log"][] = "Payment Notification Emails have been processed.";
855
  }
@@ -862,7 +997,7 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
862
  {
863
  $paypal["s2member_log"][] = "Skipping this IPN response, for now. The Subscr. ID is not associated with a registered Member.";
864
  $paypal["s2member_log"][] = "Storing this IPN response into a Transient Queue for s2Member. This will be re-processed when registration occurs.";
865
- set_transient (md5 ("s2member_transient_ipn_subscr_payment_" . $paypal["subscr_id"]), $_POST, 43200);
866
  }
867
  /**/
868
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
@@ -931,6 +1066,8 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
931
  {
932
  if (!$user->has_cap ("administrator")) /* Do NOT process this routine on Administrators. */
933
  {
 
 
934
  if (!get_user_option ("s2member_auto_eot_time", $user_id)) /* Respect existing. */
935
  {
936
  $processing = $during = true; /* Yes, we ARE processing this. */
@@ -949,68 +1086,86 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
949
  {
950
  $paypal["s2member_log"][] = "Ignoring Cancellation. An Auto-EOT Time is already set for this Member. An s2Member API Notification will still be processed however.";
951
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
952
  }
953
  else
954
  {
955
  $paypal["s2member_log"][] = "Ignoring Cancellation. The existing User ID is associated with an Administrator. Stopping here. Otherwise, an Administrator could lose access.";
956
  }
957
- /**/
958
- if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["cancellation_notification_urls"] && is_array ($cv = preg_split ("/\|/", $paypal["custom"])))
959
- {
960
- foreach (preg_split ("/[\r\n\t]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["cancellation_notification_urls"]) as $url) /* Handle Cancellation Notifications. */
961
- /**/
962
- if (($url = preg_replace ("/%%cv([0-9]+)%%/ei", 'urlencode(trim($cv[$1]))', $url)) && ($url = preg_replace ("/%%subscr_id%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["subscr_id"])), $url)))
963
- if (($url = preg_replace ("/%%item_number%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["item_number"])), $url)) && ($url = preg_replace ("/%%item_name%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["item_name"])), $url)))
964
- if (($url = preg_replace ("/%%user_first_name%%/i", ws_plugin__s2member_esc_ds (urlencode ($user->first_name)), $url)) && ($url = preg_replace ("/%%user_last_name%%/i", ws_plugin__s2member_esc_ds (urlencode ($user->last_name)), $url)))
965
- if (($url = preg_replace ("/%%user_full_name%%/i", ws_plugin__s2member_esc_ds (urlencode (trim ($user->first_name . " " . $user->last_name))), $url)))
966
- if (($url = preg_replace ("/%%user_email%%/i", ws_plugin__s2member_esc_ds (urlencode ($user->user_email)), $url)))
967
- if (($url = preg_replace ("/%%user_login%%/i", ws_plugin__s2member_esc_ds (urlencode ($user->user_login)), $url)))
968
- if (($url = preg_replace ("/%%user_id%%/i", ws_plugin__s2member_esc_ds (urlencode ($user_id)), $url)))
969
- /**/
970
- if (($url = trim ($url))) /* Empty? */
971
- ws_plugin__s2member_remote($url);
972
- /**/
973
- $paypal["s2member_log"][] = "Cancellation Notification URLs have been processed.";
974
- }
975
- /**/
976
- if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["cancellation_notification_recipients"] && is_array ($cv = preg_split ("/\|/", $paypal["custom"])))
977
- {
978
- $msg = $sbj = "( s2Member / API Notification Email ) - Cancellation";
979
- $msg .= "\n\n"; /* Spacing in the message body. */
980
- $msg .= "subscr_id: %%subscr_id%%\n";
981
- $msg .= "item_number: %%item_number%%\n";
982
- $msg .= "item_name: %%item_name%%\n";
983
- $msg .= "user_first_name: %%user_first_name%%\n";
984
- $msg .= "user_last_name: %%user_last_name%%\n";
985
- $msg .= "user_full_name: %%user_full_name%%\n";
986
- $msg .= "user_email: %%user_email%%\n";
987
- $msg .= "user_login: %%user_login%%\n";
988
- $msg .= "user_id: %%user_id%%\n";
989
- $msg .= "cv0: %%cv0%%\n";
990
- $msg .= "cv1: %%cv1%%\n";
991
- $msg .= "cv2: %%cv2%%\n";
992
- $msg .= "cv3: %%cv3%%\n";
993
- $msg .= "cv4: %%cv4%%\n";
994
- $msg .= "cv5: %%cv5%%\n";
995
- $msg .= "cv6: %%cv6%%\n";
996
- $msg .= "cv7: %%cv7%%\n";
997
- $msg .= "cv8: %%cv8%%\n";
998
- $msg .= "cv9: %%cv9%%";
999
- /**/
1000
- if (($msg = preg_replace ("/%%cv([0-9]+)%%/ei", 'trim($cv[$1])', $msg)) && ($msg = preg_replace ("/%%subscr_id%%/i", ws_plugin__s2member_esc_ds ($paypal["subscr_id"]), $msg)))
1001
- if (($msg = preg_replace ("/%%item_number%%/i", ws_plugin__s2member_esc_ds ($paypal["item_number"]), $msg)) && ($msg = preg_replace ("/%%item_name%%/i", ws_plugin__s2member_esc_ds ($paypal["item_name"]), $msg)))
1002
- if (($msg = preg_replace ("/%%user_first_name%%/i", ws_plugin__s2member_esc_ds ($user->first_name), $msg)) && ($msg = preg_replace ("/%%user_last_name%%/i", ws_plugin__s2member_esc_ds ($user->last_name), $msg)))
1003
- if (($msg = preg_replace ("/%%user_full_name%%/i", ws_plugin__s2member_esc_ds (trim ($user->first_name . " " . $user->last_name)), $msg)))
1004
- if (($msg = preg_replace ("/%%user_email%%/i", ws_plugin__s2member_esc_ds ($user->user_email), $msg)))
1005
- if (($msg = preg_replace ("/%%user_login%%/i", ws_plugin__s2member_esc_ds ($user->user_login), $msg)))
1006
- if (($msg = preg_replace ("/%%user_id%%/i", ws_plugin__s2member_esc_ds ($user_id), $msg)))
1007
- /**/
1008
- foreach (ws_plugin__s2member_trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["cancellation_notification_recipients"])) as $recipient)
1009
- /**/
1010
- ($recipient) ? mail ($recipient, $sbj, apply_filters ("ws_plugin__s2member_cancellation_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
1011
- /**/
1012
- $paypal["s2member_log"][] = "Cancellation Notification Emails have been processed.";
1013
- }
1014
  }
1015
  else
1016
  {
@@ -1058,8 +1213,8 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
1058
  $is_refund = (preg_match ("/^refunded$/i", $paypal["payment_status"]) && $paypal["parent_txn_id"]);
1059
  $is_reversal = (preg_match ("/^(reversed|reversal)$/i", $paypal["payment_status"]) && $paypal["parent_txn_id"]);
1060
  $is_reversal = (!$is_reversal) ? (preg_match ("/^new_case$/i", $paypal["txn_type"]) && preg_match ("/^chargeback$/i", $paypal["case_type"])) : $is_reversal;
1061
- $is_refund_or_reversal = ($is_refund || $is_reversal); /* If any of the previous tests evaluated to true; it's a Refund or Reversal. */
1062
- $is_delayed_eot = (preg_match ("/^subscr_eot$/i", $paypal["txn_type"]) && preg_match ("/^I-/i", $paypal["subscr_id"])); /* Delayed? */
1063
  /**/
1064
  if ($is_refund_or_reversal)
1065
  $paypal["s2member_log"][] = "s2Member txn_type identified as [empty or irrelevant] w/ payment_status (refunded|reversed|reversal) - or - new_case w/ case_type (chargeback).";
@@ -1068,6 +1223,8 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
1068
  /**/
1069
  if (($user_id = ws_plugin__s2member_paypal_user_id ($paypal["subscr_id"])) && is_object ($user = new WP_User ($user_id)) && $user->ID)
1070
  {
 
 
1071
  if ( /* Here we take action, BUT based on Auto EOT Behavior options; as configured by the Site Owner. */
1072
  (!$is_refund_or_reversal && !$is_delayed_eot && !get_user_option ("s2member_auto_eot_time", $user_id))/**/
1073
  || ($is_refund_or_reversal && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["triggers_immediate_eot"] === "refunds,reversals")/**/
@@ -1111,9 +1268,15 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
1111
  if (($url = preg_replace ("/%%user_email%%/i", ws_plugin__s2member_esc_ds (urlencode ($user->user_email)), $url)))
1112
  if (($url = preg_replace ("/%%user_login%%/i", ws_plugin__s2member_esc_ds (urlencode ($user->user_login)), $url)))
1113
  if (($url = preg_replace ("/%%user_id%%/i", ws_plugin__s2member_esc_ds (urlencode ($user_id)), $url)))
1114
- /**/
1115
- if (($url = trim ($url))) /* Empty? */
1116
- ws_plugin__s2member_remote($url);
 
 
 
 
 
 
1117
  /**/
1118
  $paypal["s2member_log"][] = "EOT/Deletion Notification URLs have been processed.";
1119
  }
@@ -1122,6 +1285,7 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
1122
  {
1123
  $msg = $sbj = "( s2Member / API Notification Email ) - EOT/Deletion";
1124
  $msg .= "\n\n"; /* Spacing in the message body. */
 
1125
  $msg .= "subscr_id: %%subscr_id%%\n";
1126
  $msg .= "user_first_name: %%user_first_name%%\n";
1127
  $msg .= "user_last_name: %%user_last_name%%\n";
@@ -1129,6 +1293,11 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
1129
  $msg .= "user_email: %%user_email%%\n";
1130
  $msg .= "user_login: %%user_login%%\n";
1131
  $msg .= "user_id: %%user_id%%\n";
 
 
 
 
 
1132
  $msg .= "cv0: %%cv0%%\n";
1133
  $msg .= "cv1: %%cv1%%\n";
1134
  $msg .= "cv2: %%cv2%%\n";
@@ -1146,10 +1315,16 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
1146
  if (($msg = preg_replace ("/%%user_email%%/i", ws_plugin__s2member_esc_ds ($user->user_email), $msg)))
1147
  if (($msg = preg_replace ("/%%user_login%%/i", ws_plugin__s2member_esc_ds ($user->user_login), $msg)))
1148
  if (($msg = preg_replace ("/%%user_id%%/i", ws_plugin__s2member_esc_ds ($user_id), $msg)))
1149
- /**/
1150
- foreach (ws_plugin__s2member_trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["eot_del_notification_recipients"])) as $recipient)
 
 
 
1151
  /**/
1152
- ($recipient) ? mail ($recipient, $sbj, apply_filters ("ws_plugin__s2member_eot_del_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
 
 
 
1153
  /**/
1154
  $paypal["s2member_log"][] = "EOT/Deletion Notification Emails have been processed.";
1155
  }
@@ -1171,7 +1346,7 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
1171
  /**/
1172
  else /* Otherwise, we can actually delete them. */
1173
  /* This will automatically trigger `eot_del_notification_urls` as well. */
1174
- wp_delete_user($user_id); /* `ws_plugin__s2member_handle_user_deletions()` */
1175
  /**/
1176
  $paypal["s2member_log"][] = "This Member's account has been " . ( (is_multisite ()) ? "removed" : "deleted") . ".";
1177
  /**/
@@ -1261,9 +1436,15 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
1261
  if (($url = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (urlencode (trim ($paypal["first_name"] . " " . $paypal["last_name"]))), $url)))
1262
  if (($url = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["payer_email"])), $url)))
1263
  if (($url = preg_replace ("/%%user_id%%/i", ws_plugin__s2member_esc_ds (urlencode ($user_id)), $url)))
1264
- /**/
1265
- if (($url = trim ($url))) /* Empty? */
1266
- ws_plugin__s2member_remote($url);
 
 
 
 
 
 
1267
  /**/
1268
  $paypal["s2member_log"][] = "Refund/Reversal Notification URLs have been processed.";
1269
  }
@@ -1272,6 +1453,7 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
1272
  {
1273
  $msg = $sbj = "( s2Member / API Notification Email ) - Refund/Reversal";
1274
  $msg .= "\n\n"; /* Spacing in the message body. */
 
1275
  $msg .= "subscr_id: %%subscr_id%%\n";
1276
  $msg .= "parent_txn_id: %%parent_txn_id%%\n";
1277
  $msg .= "item_number: %%item_number%%\n";
@@ -1283,6 +1465,11 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
1283
  $msg .= "full_name: %%full_name%%\n";
1284
  $msg .= "payer_email: %%payer_email%%\n";
1285
  $msg .= "user_id: %%user_id%%\n";
 
 
 
 
 
1286
  $msg .= "cv0: %%cv0%%\n";
1287
  $msg .= "cv1: %%cv1%%\n";
1288
  $msg .= "cv2: %%cv2%%\n";
@@ -1301,10 +1488,16 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
1301
  if (($msg = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $msg)))
1302
  if (($msg = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds ($paypal["payer_email"]), $msg)))
1303
  if (($msg = preg_replace ("/%%user_id%%/i", ws_plugin__s2member_esc_ds ($user_id), $msg)))
1304
- /**/
1305
- foreach (ws_plugin__s2member_trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["ref_rev_notification_recipients"])) as $recipient)
 
 
 
1306
  /**/
1307
- ($recipient) ? mail ($recipient, $sbj, apply_filters ("ws_plugin__s2member_ref_rev_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
 
 
 
1308
  /**/
1309
  $paypal["s2member_log"][] = "Refund/Reversal Notification Emails have been processed.";
1310
  }
@@ -1363,8 +1556,8 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
1363
  if (($url = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (urlencode (trim ($paypal["first_name"] . " " . $paypal["last_name"]))), $url)))
1364
  if (($url = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["payer_email"])), $url)))
1365
  /**/
1366
- if (($url = trim ($url))) /* Empty? */
1367
- ws_plugin__s2member_remote($url);
1368
  /**/
1369
  $paypal["s2member_log"][] = "Specific Post/Page ~ Refund/Reversal Notification URLs have been processed.";
1370
  }
@@ -1373,6 +1566,7 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
1373
  {
1374
  $msg = $sbj = "( s2Member / API Notification Email ) - Specific Post/Page ~ Refund/Reversal";
1375
  $msg .= "\n\n"; /* Spacing in the message body. */
 
1376
  $msg .= "parent_txn_id: %%parent_txn_id%%\n";
1377
  $msg .= "item_number: %%item_number%%\n";
1378
  $msg .= "item_name: %%item_name%%\n";
@@ -1400,9 +1594,9 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
1400
  if (($msg = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $msg)))
1401
  if (($msg = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds ($paypal["payer_email"]), $msg)))
1402
  /**/
1403
- foreach (ws_plugin__s2member_trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sp_ref_rev_notification_recipients"])) as $recipient)
1404
- /**/
1405
- ($recipient) ? mail ($recipient, $sbj, apply_filters ("ws_plugin__s2member_sp_ref_rev_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
1406
  /**/
1407
  $paypal["s2member_log"][] = "Specific Post/Page ~ Refund/Reversal Notification Emails have been processed.";
1408
  }
@@ -1417,7 +1611,7 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
1417
  }
1418
  else
1419
  {
1420
- $paypal["s2member_log"][] = "Ignoring this IPN request. The txn_type/status does not require any action on the part of s2Member.";
1421
  }
1422
  }
1423
  else /* Else a custom conditional has been applied by Filters. */
@@ -1450,14 +1644,19 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
1450
  $paypal["s2member_log"][] = "Unable to verify POST vars. Possibly caused by a fraudulent request. If this error continues, please run IPN tests against your server from a PayPal® Sandbox account. They provide special diagnostic tools to assist you.";
1451
  $paypal["s2member_log"][] = "If you're absolutely SURE that your PayPal® configuration is valid, you may want to run some tests on your server, just to be sure \$_POST variables are populated, and that your server is able to connect to PayPal® over an HTTPS connection.";
1452
  $paypal["s2member_log"][] = "s2Member uses the WP_Http class for remote connections; which will try to use cURL first, and then fall back on the FOPEN method when cURL is not available. On a Windows® server, you may have to disable your cURL extension. Instead, set allow_url_fopen = yes in your php.ini file. The cURL extension (usually) does NOT support SSL connections on a Windows® server.";
1453
- $paypal["s2member_log"][] = var_export ($_POST, true); /* Recording _POST vars for analysis and debugging. */
1454
  }
1455
  /*
1456
- Add IPN proxy identification ( when available ) to the $paypal array for log reporting.
1457
  */
1458
  if ($_GET["s2member_paypal_proxy"]) /* For proxy identification. */
1459
  $paypal["s2member_paypal_proxy"] = $_GET["s2member_paypal_proxy"];
1460
  /*
 
 
 
 
 
1461
  Also add IPN proxy self-verification ( when available ) to the $paypal array.
1462
  */
1463
  if ($_GET["s2member_paypal_proxy_verification"]) /* Proxy identification w/verification. */
@@ -1470,7 +1669,7 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
1470
  $log4 = (is_multisite () && !is_main_site ()) ? ($_log4 = $current_blog->domain . $current_blog->path) . "\n" . $log4 : $log4;
1471
  $log2 = (is_multisite () && !is_main_site ()) ? "paypal-ipn-4-" . trim (preg_replace ("/[^a-z0-9]/i", "-", $_log4), "-") . ".log" : "paypal-ipn.log";
1472
  /**/
1473
- if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_debug"]) /* Append to log? */
1474
  if (is_dir ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"]))
1475
  if (is_writable ($logs_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"]))
1476
  file_put_contents ($logs_dir . "/" . $log2, $log4 . "\n" . var_export ($paypal, true) . "\n\n", FILE_APPEND);
@@ -1479,7 +1678,8 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_notify"))
1479
  do_action ("ws_plugin__s2member_during_paypal_notify", get_defined_vars ());
1480
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
1481
  /**/
1482
- exit ($paypal["proxy_return_url"]); /* Return, if/when applicable. */
 
1483
  }
1484
  /**/
1485
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
31
  {
32
  function s__ws_plugin__s2member_paypal_notify ()
33
  {
 
 
34
  global $current_site, $current_blog; /* For Multisite support. */
35
  /**/
36
  do_action ("ws_plugin__s2member_before_paypal_notify", get_defined_vars ());
37
  /**/
38
+ if ($_GET["s2member_paypal_notify"] && ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"] || $_GET["s2member_paypal_proxy"]))
39
  {
40
+ include_once ABSPATH . "wp-admin/includes/admin.php"; /* Get administrative functions. */
41
+ /**/
42
+ if (is_array ($paypal = ws_plugin__s2member_paypal_postvars ()) && ($_paypal = $paypal)) /* Verify POST vars. */
43
  {
44
  $paypal["s2member_log"][] = "IPN received on: " . date ("D M j, Y g:i:s a T");
45
+ $paypal["s2member_log"][] = "s2Member POST vars verified " . /* Indicate Proxy Key. */
46
+ ( ($postvars["proxy_verified"]) ? "with a Proxy Key" : "through a POST back to PayPal®.");
47
  /**/
48
  $payment_status_issues = "/^(failed|denied|expired|refunded|partially_refunded|reversed|reversal|canceled_reversal|voided)$/i";
49
  /**/
50
  $paypal["custom"] = (!$paypal["custom"]) ? ws_plugin__s2member_paypal_custom ($paypal["recurring_payment_id"]) : $paypal["custom"];
51
+ /* Notifications following the PayPal® Pro format for Recurring Payments, do NOT carry the "custom" value, so we do a lookup.
52
  This is only crucial for one IPN call in Standard Integration: `txn_type=recurring_payment_suspended_due_to_max_failed_payment`.
53
  In Pro Integrations, we just need to make sure the "custom" field is assigned for each account during on-site checkout.
54
  This way the "custom" value will always be available when it needs to be; for both Standard and Pro services. */
197
  {
198
  $processing = $during = true; /* Yes, we ARE processing this. */
199
  /**/
200
+ $sbj = preg_replace ("/%%sp_access_url%%/i", ws_plugin__s2member_esc_ds ($sp_access_url), $GLOBALS["WS_PLUGIN__"]["s2member"]["o"][ ( (preg_match ("/pro-emails/", $_GET["s2member_paypal_proxy_use"])) ? "pro_" : "") . "sp_email_subject"]);
201
  $sbj = preg_replace ("/%%sp_access_exp%%/i", ws_plugin__s2member_esc_ds (ws_plugin__s2member_approx_time_difference (time (), strtotime ("+" . $paypal["hours"] . " hours"))), $sbj);
202
  /**/
203
+ $msg = preg_replace ("/%%sp_access_url%%/i", ws_plugin__s2member_esc_ds ($sp_access_url), $GLOBALS["WS_PLUGIN__"]["s2member"]["o"][ ( (preg_match ("/pro-emails/", $_GET["s2member_paypal_proxy_use"])) ? "pro_" : "") . "sp_email_message"]);
204
  $msg = preg_replace ("/%%sp_access_exp%%/i", ws_plugin__s2member_esc_ds (ws_plugin__s2member_approx_time_difference (time (), strtotime ("+" . $paypal["hours"] . " hours"))), $msg);
205
  /**/
206
+ $rec = preg_replace ("/%%sp_access_url%%/i", ws_plugin__s2member_esc_ds ($sp_access_url), $GLOBALS["WS_PLUGIN__"]["s2member"]["o"][ ( (preg_match ("/pro-emails/", $_GET["s2member_paypal_proxy_use"])) ? "pro_" : "") . "sp_email_recipients"]);
207
  $rec = preg_replace ("/%%sp_access_exp%%/i", ws_plugin__s2member_esc_ds (ws_plugin__s2member_approx_time_difference (time (), strtotime ("+" . $paypal["hours"] . " hours"))), $rec);
208
  /**/
209
  if (($rec = preg_replace ("/%%cv([0-9]+)%%/ei", 'trim($cv[$1])', $rec)) && ($rec = preg_replace ("/%%txn_id%%/i", ws_plugin__s2member_esc_ds ($paypal["txn_id"]), $rec)))
212
  if (($rec = preg_replace ("/%%first_name%%/i", ws_plugin__s2member_esc_dq (ws_plugin__s2member_esc_ds ($paypal["first_name"])), $rec)) && ($rec = preg_replace ("/%%last_name%%/i", ws_plugin__s2member_esc_dq (ws_plugin__s2member_esc_ds ($paypal["last_name"])), $rec)))
213
  if (($rec = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_dq (ws_plugin__s2member_esc_ds (trim ($paypal["first_name"] . " " . $paypal["last_name"]))), $rec))) /* **NOTE** ws_plugin__s2member_esc_dq() is applied here. ( ex. "N\"ame" <email> ). */
214
  if (($rec = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds ($paypal["payer_email"]), $rec)))
215
+ /**/
216
+ if (($sbj = preg_replace ("/%%cv([0-9]+)%%/ei", 'trim($cv[$1])', $sbj)) && ($sbj = preg_replace ("/%%txn_id%%/i", ws_plugin__s2member_esc_ds ($paypal["txn_id"]), $sbj)))
217
+ if (($sbj = preg_replace ("/%%amount%%/i", ws_plugin__s2member_esc_ds ($paypal["mc_gross"]), $sbj))) /* Full amount of the payment, before fee is subtracted. */
218
+ if (($sbj = preg_replace ("/%%item_number%%/i", ws_plugin__s2member_esc_ds ($paypal["item_number"]), $sbj)) && ($sbj = preg_replace ("/%%item_name%%/i", ws_plugin__s2member_esc_ds ($paypal["item_name"]), $sbj)))
219
+ if (($sbj = preg_replace ("/%%first_name%%/i", ws_plugin__s2member_esc_ds ($paypal["first_name"]), $sbj)) && ($sbj = preg_replace ("/%%last_name%%/i", ws_plugin__s2member_esc_ds ($paypal["last_name"]), $sbj)))
220
+ if (($sbj = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $sbj)))
221
+ if (($sbj = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds ($paypal["payer_email"]), $sbj)))
222
+ /**/
223
+ if (($msg = preg_replace ("/%%cv([0-9]+)%%/ei", 'trim($cv[$1])', $msg)) && ($msg = preg_replace ("/%%txn_id%%/i", ws_plugin__s2member_esc_ds ($paypal["txn_id"]), $msg)))
224
+ if (($msg = preg_replace ("/%%amount%%/i", ws_plugin__s2member_esc_ds ($paypal["mc_gross"]), $msg))) /* Full amount of the payment, before fee is subtracted. */
225
+ if (($msg = preg_replace ("/%%item_number%%/i", ws_plugin__s2member_esc_ds ($paypal["item_number"]), $msg)) && ($msg = preg_replace ("/%%item_name%%/i", ws_plugin__s2member_esc_ds ($paypal["item_name"]), $msg)))
226
+ if (($msg = preg_replace ("/%%first_name%%/i", ws_plugin__s2member_esc_ds ($paypal["first_name"]), $msg)) && ($msg = preg_replace ("/%%last_name%%/i", ws_plugin__s2member_esc_ds ($paypal["last_name"]), $msg)))
227
+ if (($msg = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $msg)))
228
+ if (($msg = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds ($paypal["payer_email"]), $msg)))
229
+ /**/
230
+ if (($recipients = preg_split ("/;+/", preg_replace ("/%%(.+?)%%/i", "", $rec))) && ($sbj = trim (preg_replace ("/%%(.+?)%%/i", "", $sbj))) && ($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg))))
231
+ {
232
+ foreach (ws_plugin__s2member_trim_deep ($recipients) as $recipient) /* Go through the full list of recipients. */
233
+ ($recipient) ? wp_mail ($recipient, apply_filters ("ws_plugin__s2member_sp_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_sp_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
234
+ /**/
235
+ $paypal["s2member_log"][] = "Specific Post/Page Confirmation Email sent to: " . implode ("; ", $recipients) . ".";
236
+ }
 
 
237
  /**/
238
  if ($processing && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sp_sale_notification_urls"])
239
  {
247
  if (($url = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (urlencode (trim ($paypal["first_name"] . " " . $paypal["last_name"]))), $url)))
248
  if (($url = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["payer_email"])), $url)))
249
  /**/
250
+ if (($url = trim (preg_replace ("/%%(.+?)%%/i", "", $url))))
251
+ ws_plugin__s2member_remote ($url);
252
  /**/
253
  $paypal["s2member_log"][] = "Specific Post/Page ~ Sale Notification URLs have been processed.";
254
  }
257
  {
258
  $msg = $sbj = "( s2Member / API Notification Email ) - Specific Post/Page ~ Sale";
259
  $msg .= "\n\n"; /* Spacing in the message body. */
260
+ /**/
261
  $msg .= "sp_access_url: %%sp_access_url%%\n";
262
  $msg .= "sp_access_exp: %%sp_access_exp%%\n";
263
  $msg .= "amount: %%amount%%\n";
287
  if (($msg = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $msg)))
288
  if (($msg = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds ($paypal["payer_email"]), $msg)))
289
  /**/
290
+ if (($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg))))
291
+ foreach (ws_plugin__s2member_trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sp_sale_notification_recipients"])) as $recipient)
292
+ ($recipient) ? wp_mail ($recipient, apply_filters ("ws_plugin__s2member_sp_sale_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_sp_sale_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
293
  /**/
294
  $paypal["s2member_log"][] = "Specific Post/Page ~ Sale Notification Emails have been processed.";
295
  }
296
  /**/
297
+ if ($processing && ($url = $_GET["s2member_paypal_proxy_return_url"])) /* A proxy is requesting a return URL for this transaction? */
298
  {
299
  if (($url = preg_replace ("/%%cv([0-9]+)%%/ei", 'urlencode(trim($cv[$1]))', $url)) && ($url = preg_replace ("/%%sp_access_url%%/i", ws_plugin__s2member_esc_ds (rawurlencode ($sp_access_url)), $url)))
300
  if (($url = preg_replace ("/%%sp_access_exp%%/i", ws_plugin__s2member_esc_ds (urlencode (ws_plugin__s2member_approx_time_difference (time (), strtotime ("+" . $paypal["hours"] . " hours")))), $url)))
304
  if (($url = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (urlencode (trim ($paypal["first_name"] . " " . $paypal["last_name"]))), $url)))
305
  if (($url = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["payer_email"])), $url)))
306
  /**/
307
+ if (($url = trim ($url))) /* Preserve Remaining replacements. */
308
+ /* Because the parent routine may perform replacements too. */
309
+ $paypal["s2member_paypal_proxy_return_url"] = $url;
310
  /**/
311
  $paypal["s2member_log"][] = "Specific Post/Page Return, a Proxy Return URL is ready.";
312
  }
319
  if (($code = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $code)))
320
  if (($code = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds ($paypal["payer_email"]), $code)))
321
  /**/
322
+ if (($code = trim (preg_replace ("/%%(.+?)%%/i", "", $code)))) /* This gets stored into a Transient Queue. */
323
  {
324
  $paypal["s2member_log"][] = "Storing Specific Post/Page Tracking Codes into a Transient Queue for s2Member. These will be processed on-site.";
325
  set_transient (md5 ("s2member_transient_sp_tracking_codes_" . $paypal["txn_id"]), $code, 43200);
360
  /**/
361
  if (preg_match ("/^web_accept$/i", $paypal["txn_type"])) /* Conversions for Lifetime & Fixed-Term sales. */
362
  {
363
+ $paypal["period3"] = ($paypal["eotper"]) ? $paypal["eotper"] : "1 L"; /* 1 Lifetime. */
364
  $paypal["mc_amount3"] = $paypal["mc_gross"]; /* The "Buy Now" amount. */
365
  }
366
  /**/
367
+ $paypal["initial_term"] = ($paypal["period1"]) ? $paypal["period1"] : "0 D"; /* Defaults to "0 D" ( Zero Days ). */
368
+ $paypal["initial"] = (strlen ($paypal["mc_amount1"])) ? $paypal["mc_amount1"] : $paypal["mc_amount3"]; /* Initial Amount that was just charged. */
369
+ $paypal["regular"] = $paypal["mc_amount3"]; /* This is the Regular Payment Amount that is charged to the customer. Always required by PayPal®. */
370
  $paypal["regular_term"] = $paypal["period3"]; /* This is just set to keep a standard; this way both initial_term & regular_term are available. */
371
+ $paypal["recurring"] = ($paypal["recurring"]) ? $paypal["mc_amount3"] : "0"; /* If non-recurring, this should be zero, otherwise Regular. */
372
  /*
373
  New Subscription with advanced update vars ( option_name1, option_selection1 ).
374
  */
375
  if (preg_match ("/(updat|upgrad)/i", $paypal["option_name1"]) && $paypal["option_selection1"]) /* This is an advanced way to handle Subscription update modifications. */
376
+ /* This advanced method is required whenever a Subscription that is already completed, or was never setup to recur in the first place needs to be modified. PayPal® will not allow the
377
  modify=1|2 parameter to be used in those scenarios, because technically there is nothing to update. The only thing that actually needs to be updated is the account. */
378
  {
379
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
389
  {
390
  $processing = $modifying = $during = true; /* Yes, we ARE processing this. */
391
  /**/
392
+ $fields = get_user_option ("s2member_custom_fields", $user_id);
393
+ /**/
394
  $user->set_role ("s2member_level" . $paypal["level"]);
395
  /**/
396
  foreach ($user->allcaps as $cap => $cap_enabled)
412
  else /* Otherwise, we need to clear the eot time. */
413
  delete_user_option ($user_id, "s2member_auto_eot_time");
414
  /**/
415
+ $pr_times = get_user_option ("s2member_paid_registration_times", $user_id);
416
+ $pr_times["level"] = (!$pr_times["level"]) ? time () : $pr_times["level"]; /* Preserves existing. */
417
+ $pr_times["level" . $paypal["level"]] = (!$pr_times["level" . $paypal["level"]]) ? time () : $pr_times["level" . $paypal["level"]];
418
+ update_user_option ($user_id, "s2member_paid_registration_times", $pr_times); /* Update now. */
419
+ /**/
420
  ws_plugin__s2member_clear_user_note_lines ($user_id, "/^Demoted by s2Member\:/");
421
  /**/
422
  $paypal["s2member_log"][] = "s2Member Level/Capabilities updated w/ advanced update routines.";
423
  /**/
424
+ wp_mail ($paypal["payer_email"], apply_filters ("ws_plugin__s2member_modification_email_sbj", "Thank you! Your account has been updated.", get_defined_vars ()), apply_filters ("ws_plugin__s2member_modification_email_msg", "Thank you! You've been updated to:\n" . $paypal["item_name"] . "\n\nPlease log back in now.\n" . wp_login_url (), get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8");
425
  /**/
426
  $paypal["s2member_log"][] = "Modification Confirmation Email sent to Customer, with a URL that provides them with a way to log back in.";
427
  /**/
458
  {
459
  $processing = $during = true; /* Yes, we ARE processing this. */
460
  /**/
461
+ $sbj = preg_replace ("/%%registration_url%%/i", ws_plugin__s2member_esc_ds ($registration_url), $GLOBALS["WS_PLUGIN__"]["s2member"]["o"][ ( (preg_match ("/pro-emails/", $_GET["s2member_paypal_proxy_use"])) ? "pro_" : "") . "signup_email_subject"]);
462
+ $msg = preg_replace ("/%%registration_url%%/i", ws_plugin__s2member_esc_ds ($registration_url), $GLOBALS["WS_PLUGIN__"]["s2member"]["o"][ ( (preg_match ("/pro-emails/", $_GET["s2member_paypal_proxy_use"])) ? "pro_" : "") . "signup_email_message"]);
463
+ $rec = preg_replace ("/%%registration_url%%/i", ws_plugin__s2member_esc_ds ($registration_url), $GLOBALS["WS_PLUGIN__"]["s2member"]["o"][ ( (preg_match ("/pro-emails/", $_GET["s2member_paypal_proxy_use"])) ? "pro_" : "") . "signup_email_recipients"]);
464
  /**/
465
  if (($rec = preg_replace ("/%%cv([0-9]+)%%/ei", 'trim($cv[$1])', $rec)) && ($rec = preg_replace ("/%%subscr_id%%/i", ws_plugin__s2member_esc_ds ($paypal["subscr_id"]), $rec)))
466
  if (($rec = preg_replace ("/%%initial%%/i", ws_plugin__s2member_esc_ds ($paypal["initial"]), $rec)) && ($rec = preg_replace ("/%%regular%%/i", ws_plugin__s2member_esc_ds ($paypal["regular"]), $rec)))
467
  if (($rec = preg_replace ("/%%initial_term%%/i", ws_plugin__s2member_esc_ds ($paypal["initial_term"]), $rec)) && ($rec = preg_replace ("/%%regular_term%%/i", ws_plugin__s2member_esc_ds ($paypal["regular_term"]), $rec)))
468
+ if (($rec = preg_replace ("/%%initial_cycle%%/i", ws_plugin__s2member_esc_ds (ws_plugin__s2member_paypal_period_term ($paypal["initial_term"])), $rec)) && ($rec = preg_replace ("/%%regular_cycle%%/i", ws_plugin__s2member_esc_ds (ws_plugin__s2member_paypal_period_term ($paypal["regular_term"], $paypal["recurring"])), $rec)))
469
+ if (($rec = preg_replace ("/%%recurring%%/i", ws_plugin__s2member_esc_ds ($paypal["recurring"]), $rec)) && ($rec = preg_replace ("/%%recurring\/regular_cycle%%/i", ws_plugin__s2member_esc_ds (( ($paypal["recurring"]) ? $paypal["recurring"] . " / " . ws_plugin__s2member_paypal_period_term ($paypal["regular_term"], true) : "0 / non-recurring")), $rec)))
470
  if (($rec = preg_replace ("/%%item_number%%/i", ws_plugin__s2member_esc_ds ($paypal["item_number"]), $rec)) && ($rec = preg_replace ("/%%item_name%%/i", ws_plugin__s2member_esc_ds ($paypal["item_name"]), $rec)))
471
  if (($rec = preg_replace ("/%%first_name%%/i", ws_plugin__s2member_esc_dq (ws_plugin__s2member_esc_ds ($paypal["first_name"])), $rec)) && ($rec = preg_replace ("/%%last_name%%/i", ws_plugin__s2member_esc_dq (ws_plugin__s2member_esc_ds ($paypal["last_name"])), $rec)))
472
  if (($rec = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_dq (ws_plugin__s2member_esc_ds (trim ($paypal["first_name"] . " " . $paypal["last_name"]))), $rec))) /* **NOTE** ws_plugin__s2member_esc_dq() is applied here. ( ex. "N\"ame" <email> ). */
473
  if (($rec = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds ($paypal["payer_email"]), $rec)))
474
+ /**/
475
+ if (($sbj = preg_replace ("/%%cv([0-9]+)%%/ei", 'trim($cv[$1])', $sbj)) && ($sbj = preg_replace ("/%%subscr_id%%/i", ws_plugin__s2member_esc_ds ($paypal["subscr_id"]), $sbj)))
476
+ if (($sbj = preg_replace ("/%%initial%%/i", ws_plugin__s2member_esc_ds ($paypal["initial"]), $sbj)) && ($sbj = preg_replace ("/%%regular%%/i", ws_plugin__s2member_esc_ds ($paypal["regular"]), $sbj)))
477
+ if (($sbj = preg_replace ("/%%initial_term%%/i", ws_plugin__s2member_esc_ds ($paypal["initial_term"]), $sbj)) && ($sbj = preg_replace ("/%%regular_term%%/i", ws_plugin__s2member_esc_ds ($paypal["regular_term"]), $sbj)))
478
+ if (($sbj = preg_replace ("/%%initial_cycle%%/i", ws_plugin__s2member_esc_ds (ws_plugin__s2member_paypal_period_term ($paypal["initial_term"])), $sbj)) && ($sbj = preg_replace ("/%%regular_cycle%%/i", ws_plugin__s2member_esc_ds (ws_plugin__s2member_paypal_period_term ($paypal["regular_term"], $paypal["recurring"])), $sbj)))
479
+ if (($sbj = preg_replace ("/%%recurring%%/i", ws_plugin__s2member_esc_ds ($paypal["recurring"]), $sbj)) && ($sbj = preg_replace ("/%%recurring\/regular_cycle%%/i", ws_plugin__s2member_esc_ds (( ($paypal["recurring"]) ? $paypal["recurring"] . " / " . ws_plugin__s2member_paypal_period_term ($paypal["regular_term"], true) : "0 / non-recurring")), $sbj)))
480
+ if (($sbj = preg_replace ("/%%item_number%%/i", ws_plugin__s2member_esc_ds ($paypal["item_number"]), $sbj)) && ($sbj = preg_replace ("/%%item_name%%/i", ws_plugin__s2member_esc_ds ($paypal["item_name"]), $sbj)))
481
+ if (($sbj = preg_replace ("/%%first_name%%/i", ws_plugin__s2member_esc_ds ($paypal["first_name"]), $sbj)) && ($sbj = preg_replace ("/%%last_name%%/i", ws_plugin__s2member_esc_ds ($paypal["last_name"]), $sbj)))
482
+ if (($sbj = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $sbj)))
483
+ if (($sbj = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds ($paypal["payer_email"]), $sbj)))
484
+ /**/
485
+ if (($msg = preg_replace ("/%%cv([0-9]+)%%/ei", 'trim($cv[$1])', $msg)) && ($msg = preg_replace ("/%%subscr_id%%/i", ws_plugin__s2member_esc_ds ($paypal["subscr_id"]), $msg)))
486
+ if (($msg = preg_replace ("/%%initial%%/i", ws_plugin__s2member_esc_ds ($paypal["initial"]), $msg)) && ($msg = preg_replace ("/%%regular%%/i", ws_plugin__s2member_esc_ds ($paypal["regular"]), $msg)))
487
+ if (($msg = preg_replace ("/%%initial_term%%/i", ws_plugin__s2member_esc_ds ($paypal["initial_term"]), $msg)) && ($msg = preg_replace ("/%%regular_term%%/i", ws_plugin__s2member_esc_ds ($paypal["regular_term"]), $msg)))
488
+ if (($msg = preg_replace ("/%%initial_cycle%%/i", ws_plugin__s2member_esc_ds (ws_plugin__s2member_paypal_period_term ($paypal["initial_term"])), $msg)) && ($msg = preg_replace ("/%%regular_cycle%%/i", ws_plugin__s2member_esc_ds (ws_plugin__s2member_paypal_period_term ($paypal["regular_term"], $paypal["recurring"])), $msg)))
489
+ if (($msg = preg_replace ("/%%recurring%%/i", ws_plugin__s2member_esc_ds ($paypal["recurring"]), $msg)) && ($msg = preg_replace ("/%%recurring\/regular_cycle%%/i", ws_plugin__s2member_esc_ds (( ($paypal["recurring"]) ? $paypal["recurring"] . " / " . ws_plugin__s2member_paypal_period_term ($paypal["regular_term"], true) : "0 / non-recurring")), $msg)))
490
+ if (($msg = preg_replace ("/%%item_number%%/i", ws_plugin__s2member_esc_ds ($paypal["item_number"]), $msg)) && ($msg = preg_replace ("/%%item_name%%/i", ws_plugin__s2member_esc_ds ($paypal["item_name"]), $msg)))
491
+ if (($msg = preg_replace ("/%%first_name%%/i", ws_plugin__s2member_esc_ds ($paypal["first_name"]), $msg)) && ($msg = preg_replace ("/%%last_name%%/i", ws_plugin__s2member_esc_ds ($paypal["last_name"]), $msg)))
492
+ if (($msg = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $msg)))
493
+ if (($msg = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds ($paypal["payer_email"]), $msg)))
494
+ /**/
495
+ if (($recipients = preg_split ("/;+/", preg_replace ("/%%(.+?)%%/i", "", $rec))) && ($sbj = trim (preg_replace ("/%%(.+?)%%/i", "", $sbj))) && ($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg))))
496
+ {
497
+ foreach (ws_plugin__s2member_trim_deep ($recipients) as $recipient) /* Go through the full list of recipients. */
498
+ ($recipient) ? wp_mail ($recipient, apply_filters ("ws_plugin__s2member_signup_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_signup_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
499
+ /**/
500
+ $paypal["s2member_log"][] = "Signup Confirmation Email sent to: " . implode ("; ", $recipients) . ".";
501
+ }
 
 
502
  /**/
503
  if ($processing && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["signup_notification_urls"] && is_array ($cv = preg_split ("/\|/", $paypal["custom"])))
504
  {
512
  if (($url = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (urlencode (trim ($paypal["first_name"] . " " . $paypal["last_name"]))), $url)))
513
  if (($url = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["payer_email"])), $url)))
514
  /**/
515
+ if (($url = trim (preg_replace ("/%%(.+?)%%/i", "", $url))))
516
+ ws_plugin__s2member_remote ($url);
517
  /**/
518
  $paypal["s2member_log"][] = "Signup Notification URLs have been processed.";
519
  }
522
  {
523
  $msg = $sbj = "( s2Member / API Notification Email ) - Signup";
524
  $msg .= "\n\n"; /* Spacing in the message body. */
525
+ /**/
526
  $msg .= "subscr_id: %%subscr_id%%\n";
527
  $msg .= "initial: %%initial%%\n";
528
  $msg .= "regular: %%regular%%\n";
554
  if (($msg = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $msg)))
555
  if (($msg = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds ($paypal["payer_email"]), $msg)))
556
  /**/
557
+ if (($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg))))
558
+ foreach (ws_plugin__s2member_trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["signup_notification_recipients"])) as $recipient)
559
+ ($recipient) ? wp_mail ($recipient, apply_filters ("ws_plugin__s2member_signup_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_signup_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
560
  /**/
561
  $paypal["s2member_log"][] = "Signup Notification Emails have been processed.";
562
  }
571
  if (($code = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $code)))
572
  if (($code = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds ($paypal["payer_email"]), $code)))
573
  /**/
574
+ if (($code = trim (preg_replace ("/%%(.+?)%%/i", "", $code)))) /* This gets stored into a Transient Queue. */
575
  {
576
  $paypal["s2member_log"][] = "Storing Signup Tracking Codes into a Transient Queue for s2Member. These will be processed on-site.";
577
  set_transient (md5 ("s2member_transient_signup_tracking_codes_" . $paypal["subscr_id"]), $code, 43200);
592
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
593
  }
594
  /**/
595
+ if ($processing && ($url = $_GET["s2member_paypal_proxy_return_url"]) && is_array ($cv = preg_split ("/\|/", $paypal["custom"]))) /* A proxy is requesting a return URL for this transaction? */
596
  {
597
+ if (($user_id && is_object ($user) && $user->ID) || ( ($user_id = ws_plugin__s2member_paypal_user_id ($paypal["subscr_id"], $paypal["option_selection1"])) && is_object ($user = new WP_User ($user_id)) && $user->ID))
598
+ {
599
+ $fields = get_user_option ("s2member_custom_fields", $user_id); /* These will be needed below. */
600
+ /**/
601
+ if (($url = preg_replace ("/%%cv([0-9]+)%%/ei", 'urlencode(trim($cv[$1]))', $url)) && ($url = preg_replace ("/%%subscr_id%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["subscr_id"])), $url)))
602
+ if (($url = preg_replace ("/%%initial%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["initial"])), $url)) && ($url = preg_replace ("/%%regular%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["regular"])), $url)) && ($url = preg_replace ("/%%recurring%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["recurring"])), $url)))
603
+ if (($url = preg_replace ("/%%initial_term%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["initial_term"])), $url)) && ($url = preg_replace ("/%%regular_term%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["regular_term"])), $url)))
604
+ if (($url = preg_replace ("/%%item_number%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["item_number"])), $url)) && ($url = preg_replace ("/%%item_name%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["item_name"])), $url)))
605
+ if (($url = preg_replace ("/%%first_name%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["first_name"])), $url)) && ($url = preg_replace ("/%%last_name%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["last_name"])), $url)))
606
+ if (($url = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (urlencode (trim ($paypal["first_name"] . " " . $paypal["last_name"]))), $url)))
607
+ if (($url = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["payer_email"])), $url)))
608
+ if (($url = preg_replace ("/%%modification%%/i", ws_plugin__s2member_esc_ds (urlencode ((int)$modifying)), $url)))
609
+ {
610
+ if (($url = preg_replace ("/%%user_first_name%%/i", ws_plugin__s2member_esc_ds (urlencode ($user->first_name)), $url)) && ($url = preg_replace ("/%%user_last_name%%/i", ws_plugin__s2member_esc_ds (urlencode ($user->last_name)), $url)))
611
+ if (($url = preg_replace ("/%%user_full_name%%/i", ws_plugin__s2member_esc_ds (urlencode (trim ($user->first_name . " " . $user->last_name))), $url)))
612
+ if (($url = preg_replace ("/%%user_email%%/i", ws_plugin__s2member_esc_ds (urlencode ($user->user_email)), $url)))
613
+ if (($url = preg_replace ("/%%user_login%%/i", ws_plugin__s2member_esc_ds (urlencode ($user->user_login)), $url)))
614
+ if (($url = preg_replace ("/%%user_id%%/i", ws_plugin__s2member_esc_ds (urlencode ($user_id)), $url)))
615
+ {
616
+ if (is_array ($fields) && !empty ($fields))
617
+ foreach ($fields as $var => $val) /* Custom Registration Fields. */
618
+ if (! ($url = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", ws_plugin__s2member_esc_ds (urlencode (maybe_serialize ($val))), $url)))
619
+ break;
620
+ /**/
621
+ if (($url = trim ($url))) /* Preserve remaining replacements. */
622
+ /* Because the parent routine may perform replacements too. */
623
+ $paypal["s2member_paypal_proxy_return_url"] = $url;
624
+ }
625
+ }
626
+ }
627
  /**/
628
  $paypal["s2member_log"][] = "Subscr. Return ( modification=" . (int)$modifying . " ), a Proxy Return URL is ready.";
629
  }
630
  /**/
631
+ if ($processing && preg_match ("/^web_accept$/i", $paypal["txn_type"]) && ( ($user_id && is_object ($user) && $user->ID) || ( ($user_id = ws_plugin__s2member_paypal_user_id ($paypal["subscr_id"], $paypal["option_selection1"])) && is_object ($user = new WP_User ($user_id)) && $user->ID)))
632
  {
633
+ $paypal["s2member_log"][] = "User exists. Handling `payment` for Subscription via (web_accept).";
634
+ /**/
635
+ $pr_times = get_user_option ("s2member_paid_registration_times", $user_id);
636
+ $pr_times["level"] = (!$pr_times["level"]) ? time () : $pr_times["level"]; /* Preserves existing. */
637
+ $pr_times["level" . $paypal["level"]] = (!$pr_times["level" . $paypal["level"]]) ? time () : $pr_times["level" . $paypal["level"]];
638
+ update_user_option ($user_id, "s2member_paid_registration_times", $pr_times); /* Update now. */
639
+ /**/
640
+ update_user_option ($user_id, "s2member_last_payment_time", time ()); /* Also update the last payment time. */
641
+ /**/
642
+ $fields = get_user_option ("s2member_custom_fields", $user_id); /* These will be needed in the routines below. */
 
 
643
  /**/
644
+ if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["payment_notification_urls"] && is_array ($cv = preg_split ("/\|/", $paypal["custom"])))
645
+ {
646
+ foreach (preg_split ("/[\r\n\t]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["payment_notification_urls"]) as $url)
647
+ /**/
648
+ if (($url = preg_replace ("/%%cv([0-9]+)%%/ei", 'urlencode(trim($cv[$1]))', $url)) && ($url = preg_replace ("/%%subscr_id%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["subscr_id"])), $url)))
649
+ if (($url = preg_replace ("/%%amount%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["mc_gross"])), $url)) && ($url = preg_replace ("/%%txn_id%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["txn_id"])), $url)))
650
+ if (($url = preg_replace ("/%%item_number%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["item_number"])), $url)) && ($url = preg_replace ("/%%item_name%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["item_name"])), $url)))
651
+ if (($url = preg_replace ("/%%first_name%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["first_name"])), $url)) && ($url = preg_replace ("/%%last_name%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["last_name"])), $url)))
652
+ if (($url = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (urlencode (trim ($paypal["first_name"] . " " . $paypal["last_name"]))), $url)))
653
+ if (($url = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["payer_email"])), $url)))
654
+ {
655
+ if (($url = preg_replace ("/%%user_first_name%%/i", ws_plugin__s2member_esc_ds (urlencode ($user->first_name)), $url)) && ($url = preg_replace ("/%%user_last_name%%/i", ws_plugin__s2member_esc_ds (urlencode ($user->last_name)), $url)))
656
+ if (($url = preg_replace ("/%%user_full_name%%/i", ws_plugin__s2member_esc_ds (urlencode (trim ($user->first_name . " " . $user->last_name))), $url)))
657
+ if (($url = preg_replace ("/%%user_email%%/i", ws_plugin__s2member_esc_ds (urlencode ($user->user_email)), $url)))
658
+ if (($url = preg_replace ("/%%user_login%%/i", ws_plugin__s2member_esc_ds (urlencode ($user->user_login)), $url)))
659
+ if (($url = preg_replace ("/%%user_id%%/i", ws_plugin__s2member_esc_ds (urlencode ($user_id)), $url)))
660
+ {
661
+ if (is_array ($fields) && !empty ($fields))
662
+ foreach ($fields as $var => $val) /* Custom Registration Fields. */
663
+ if (! ($url = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", ws_plugin__s2member_esc_ds (urlencode (maybe_serialize ($val))), $url)))
664
+ break;
665
+ /**/
666
+ if (($url = trim (preg_replace ("/%%(.+?)%%/i", "", $url))))
667
+ ws_plugin__s2member_remote ($url);
668
+ }
669
+ }
670
+ /**/
671
+ $paypal["s2member_log"][] = "Payment Notification URLs have been processed.";
672
+ }
673
+ /**/
674
+ if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["payment_notification_recipients"] && is_array ($cv = preg_split ("/\|/", $paypal["custom"])))
675
+ {
676
+ $msg = $sbj = "( s2Member / API Notification Email ) - Payment";
677
+ $msg .= "\n\n"; /* Spacing in the message body. */
678
+ /**/
679
+ $msg .= "subscr_id: %%subscr_id%%\n";
680
+ $msg .= "amount: %%amount%%\n";
681
+ $msg .= "txn_id: %%txn_id%%\n";
682
+ $msg .= "item_number: %%item_number%%\n";
683
+ $msg .= "item_name: %%item_name%%\n";
684
+ $msg .= "first_name: %%first_name%%\n";
685
+ $msg .= "last_name: %%last_name%%\n";
686
+ $msg .= "full_name: %%full_name%%\n";
687
+ $msg .= "payer_email: %%payer_email%%\n";
688
+ /**/
689
+ $msg .= "user_first_name: %%user_first_name%%\n";
690
+ $msg .= "user_last_name: %%user_last_name%%\n";
691
+ $msg .= "user_full_name: %%user_full_name%%\n";
692
+ $msg .= "user_email: %%user_email%%\n";
693
+ $msg .= "user_login: %%user_login%%\n";
694
+ $msg .= "user_id: %%user_id%%\n";
695
+ /**/
696
+ if (is_array ($fields) && !empty ($fields))
697
+ foreach ($fields as $var => $val)
698
+ $msg .= $var . ": %%" . $var . "%%\n";
699
+ /**/
700
+ $msg .= "cv0: %%cv0%%\n";
701
+ $msg .= "cv1: %%cv1%%\n";
702
+ $msg .= "cv2: %%cv2%%\n";
703
+ $msg .= "cv3: %%cv3%%\n";
704
+ $msg .= "cv4: %%cv4%%\n";
705
+ $msg .= "cv5: %%cv5%%\n";
706
+ $msg .= "cv6: %%cv6%%\n";
707
+ $msg .= "cv7: %%cv7%%\n";
708
+ $msg .= "cv8: %%cv8%%\n";
709
+ $msg .= "cv9: %%cv9%%";
710
+ /**/
711
+ if (($msg = preg_replace ("/%%cv([0-9]+)%%/ei", 'trim($cv[$1])', $msg)) && ($msg = preg_replace ("/%%subscr_id%%/i", ws_plugin__s2member_esc_ds ($paypal["subscr_id"]), $msg)))
712
+ if (($msg = preg_replace ("/%%amount%%/i", ws_plugin__s2member_esc_ds ($paypal["mc_gross"]), $msg)) && ($msg = preg_replace ("/%%txn_id%%/i", ws_plugin__s2member_esc_ds ($paypal["txn_id"]), $msg)))
713
+ if (($msg = preg_replace ("/%%item_number%%/i", ws_plugin__s2member_esc_ds ($paypal["item_number"]), $msg)) && ($msg = preg_replace ("/%%item_name%%/i", ws_plugin__s2member_esc_ds ($paypal["item_name"]), $msg)))
714
+ if (($msg = preg_replace ("/%%first_name%%/i", ws_plugin__s2member_esc_ds ($paypal["first_name"]), $msg)) && ($msg = preg_replace ("/%%last_name%%/i", ws_plugin__s2member_esc_ds ($paypal["last_name"]), $msg)))
715
+ if (($msg = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $msg)))
716
+ if (($msg = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds ($paypal["payer_email"]), $msg)))
717
+ {
718
+ if (($msg = preg_replace ("/%%user_first_name%%/i", ws_plugin__s2member_esc_ds ($user->first_name), $msg)) && ($msg = preg_replace ("/%%user_last_name%%/i", ws_plugin__s2member_esc_ds ($user->last_name), $msg)))
719
+ if (($msg = preg_replace ("/%%user_full_name%%/i", ws_plugin__s2member_esc_ds (trim ($user->first_name . " " . $user->last_name)), $msg)))
720
+ if (($msg = preg_replace ("/%%user_email%%/i", ws_plugin__s2member_esc_ds ($user->user_email), $msg)))
721
+ if (($msg = preg_replace ("/%%user_login%%/i", ws_plugin__s2member_esc_ds ($user->user_login), $msg)))
722
+ if (($msg = preg_replace ("/%%user_id%%/i", ws_plugin__s2member_esc_ds ($user_id), $msg)))
723
+ {
724
+ if (is_array ($fields) && !empty ($fields))
725
+ foreach ($fields as $var => $val) /* Custom Registration Fields. */
726
+ if (! ($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", ws_plugin__s2member_esc_ds (maybe_serialize ($val)), $msg)))
727
+ break;
728
+ /**/
729
+ if (($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg))))
730
+ foreach (ws_plugin__s2member_trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["payment_notification_recipients"])) as $recipient)
731
+ ($recipient) ? wp_mail ($recipient, apply_filters ("ws_plugin__s2member_payment_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_payment_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
732
+ }
733
+ }
734
+ /**/
735
+ $paypal["s2member_log"][] = "Payment Notification Emails have been processed.";
736
+ }
737
  }
738
+ else if ($processing && preg_match ("/^web_accept$/i", $paypal["txn_type"]))
 
739
  {
740
+ $ipn = array ("txn_type" => "subscr_payment");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
741
  /**/
742
+ foreach ($paypal as $var => $val)
743
+ if (in_array ($var, array ("subscr_id", "txn_id", "custom", "mc_gross", "mc_currency", "tax", "payer_email", "first_name", "last_name", "item_name", "item_number")))
744
+ $ipn[$var] = $val;
 
 
 
 
 
 
 
 
745
  /**/
746
+ $paypal["s2member_log"][] = "Creating an IPN response for `subscr_payment`. This will go into a Transient Queue for s2Member; and be processed during registration.";
747
+ set_transient (md5 ("s2member_transient_ipn_subscr_payment_" . $paypal["subscr_id"]), $ipn, 43200);
748
  }
749
  /**/
750
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
752
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
753
  }
754
  /*
755
+ Recurring Payment Profile creation.
756
  This is not really necessary. It is only here because this txn_type could
757
  be necessary in a future release of s2Member. For now, it's just a fill-in.
758
  These Hooks/Filters will remain, so you can use them now; if you need to.
804
  {
805
  $processing = $modifying = $during = true; /* Yes, we ARE processing this. */
806
  /**/
807
+ $fields = get_user_option ("s2member_custom_fields", $user_id);
808
+ /**/
809
  $user->set_role ("s2member_level" . $paypal["level"]);
810
  /**/
811
  foreach ($user->allcaps as $cap => $cap_enabled)
824
  /**/
825
  delete_user_option ($user_id, "s2member_auto_eot_time");
826
  /**/
827
+ $pr_times = get_user_option ("s2member_paid_registration_times", $user_id);
828
+ $pr_times["level"] = (!$pr_times["level"]) ? time () : $pr_times["level"]; /* Preserves existing. */
829
+ $pr_times["level" . $paypal["level"]] = (!$pr_times["level" . $paypal["level"]]) ? time () : $pr_times["level" . $paypal["level"]];
830
+ update_user_option ($user_id, "s2member_paid_registration_times", $pr_times); /* Update now. */
831
+ /**/
832
  ws_plugin__s2member_clear_user_note_lines ($user_id, "/^Demoted by s2Member\:/");
833
  /**/
834
  $paypal["s2member_log"][] = "s2Member Level/Capabilities updated on Subscription modification.";
835
  /**/
836
+ wp_mail ($paypal["payer_email"], apply_filters ("ws_plugin__s2member_modification_email_sbj", "Thank you! Your account has been updated.", get_defined_vars ()), apply_filters ("ws_plugin__s2member_modification_email_msg", "Thank you! You've been updated to:\n" . $paypal["item_name"] . "\n\nPlease log back in now.\n" . wp_login_url (), get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8");
837
  /**/
838
  $paypal["s2member_log"][] = "Modification Confirmation Email sent to Customer, with a URL that provides them with a way to log back in.";
839
  /**/
884
  {
885
  $processing = $during = true; /* Yes, we ARE processing this. */
886
  /**/
887
+ $pr_times = get_user_option ("s2member_paid_registration_times", $user_id);
888
+ $pr_times["level"] = (!$pr_times["level"]) ? time () : $pr_times["level"]; /* Preserves existing. */
889
+ $pr_times["level" . $paypal["level"]] = (!$pr_times["level" . $paypal["level"]]) ? time () : $pr_times["level" . $paypal["level"]];
890
+ update_user_option ($user_id, "s2member_paid_registration_times", $pr_times); /* Update now. */
891
+ /**/
892
+ update_user_option ($user_id, "s2member_last_payment_time", time ()); /* Also update last payment time. */
893
  /**/
894
+ $paypal["s2member_log"][] = "Updated Payment Times for this Member."; /* Flag this action in the log. */
895
+ /**/
896
+ $fields = get_user_option ("s2member_custom_fields", $user_id); /* These will be needed in the routines below. */
897
  /**/
898
  if ($processing && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["payment_notification_urls"] && is_array ($cv = preg_split ("/\|/", $paypal["custom"])))
899
  {
900
  foreach (preg_split ("/[\r\n\t]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["payment_notification_urls"]) as $url)
901
  /**/
902
  if (($url = preg_replace ("/%%cv([0-9]+)%%/ei", 'urlencode(trim($cv[$1]))', $url)) && ($url = preg_replace ("/%%subscr_id%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["subscr_id"])), $url)))
903
+ if (($url = preg_replace ("/%%amount%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["mc_gross"])), $url)) && ($url = preg_replace ("/%%txn_id%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["txn_id"])), $url)))
904
+ if (($url = preg_replace ("/%%item_number%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["item_number"])), $url)) && ($url = preg_replace ("/%%item_name%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["item_name"])), $url)))
905
+ if (($url = preg_replace ("/%%first_name%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["first_name"])), $url)) && ($url = preg_replace ("/%%last_name%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["last_name"])), $url)))
906
+ if (($url = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (urlencode (trim ($paypal["first_name"] . " " . $paypal["last_name"]))), $url)))
907
+ if (($url = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["payer_email"])), $url)))
908
+ {
909
+ if (($url = preg_replace ("/%%user_first_name%%/i", ws_plugin__s2member_esc_ds (urlencode ($user->first_name)), $url)) && ($url = preg_replace ("/%%user_last_name%%/i", ws_plugin__s2member_esc_ds (urlencode ($user->last_name)), $url)))
910
+ if (($url = preg_replace ("/%%user_full_name%%/i", ws_plugin__s2member_esc_ds (urlencode (trim ($user->first_name . " " . $user->last_name))), $url)))
911
+ if (($url = preg_replace ("/%%user_email%%/i", ws_plugin__s2member_esc_ds (urlencode ($user->user_email)), $url)))
912
+ if (($url = preg_replace ("/%%user_login%%/i", ws_plugin__s2member_esc_ds (urlencode ($user->user_login)), $url)))
913
+ if (($url = preg_replace ("/%%user_id%%/i", ws_plugin__s2member_esc_ds (urlencode ($user_id)), $url)))
914
+ {
915
+ if (is_array ($fields) && !empty ($fields))
916
+ foreach ($fields as $var => $val) /* Custom Registration Fields. */
917
+ if (! ($url = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", ws_plugin__s2member_esc_ds (urlencode (maybe_serialize ($val))), $url)))
918
+ break;
919
+ /**/
920
+ if (($url = trim (preg_replace ("/%%(.+?)%%/i", "", $url))))
921
+ ws_plugin__s2member_remote ($url);
922
+ }
923
+ }
924
  /**/
925
  $paypal["s2member_log"][] = "Payment Notification URLs have been processed.";
926
  }
929
  {
930
  $msg = $sbj = "( s2Member / API Notification Email ) - Payment";
931
  $msg .= "\n\n"; /* Spacing in the message body. */
932
+ /**/
933
  $msg .= "subscr_id: %%subscr_id%%\n";
 
 
934
  $msg .= "amount: %%amount%%\n";
935
  $msg .= "txn_id: %%txn_id%%\n";
936
  $msg .= "item_number: %%item_number%%\n";
939
  $msg .= "last_name: %%last_name%%\n";
940
  $msg .= "full_name: %%full_name%%\n";
941
  $msg .= "payer_email: %%payer_email%%\n";
942
+ /**/
943
+ $msg .= "user_first_name: %%user_first_name%%\n";
944
+ $msg .= "user_last_name: %%user_last_name%%\n";
945
+ $msg .= "user_full_name: %%user_full_name%%\n";
946
+ $msg .= "user_email: %%user_email%%\n";
947
+ $msg .= "user_login: %%user_login%%\n";
948
+ $msg .= "user_id: %%user_id%%\n";
949
+ /**/
950
+ if (is_array ($fields) && !empty ($fields))
951
+ foreach ($fields as $var => $val)
952
+ $msg .= $var . ": %%" . $var . "%%\n";
953
+ /**/
954
  $msg .= "cv0: %%cv0%%\n";
955
  $msg .= "cv1: %%cv1%%\n";
956
  $msg .= "cv2: %%cv2%%\n";
963
  $msg .= "cv9: %%cv9%%";
964
  /**/
965
  if (($msg = preg_replace ("/%%cv([0-9]+)%%/ei", 'trim($cv[$1])', $msg)) && ($msg = preg_replace ("/%%subscr_id%%/i", ws_plugin__s2member_esc_ds ($paypal["subscr_id"]), $msg)))
966
+ if (($msg = preg_replace ("/%%amount%%/i", ws_plugin__s2member_esc_ds ($paypal["mc_gross"]), $msg)) && ($msg = preg_replace ("/%%txn_id%%/i", ws_plugin__s2member_esc_ds ($paypal["txn_id"]), $msg)))
967
+ if (($msg = preg_replace ("/%%item_number%%/i", ws_plugin__s2member_esc_ds ($paypal["item_number"]), $msg)) && ($msg = preg_replace ("/%%item_name%%/i", ws_plugin__s2member_esc_ds ($paypal["item_name"]), $msg)))
968
+ if (($msg = preg_replace ("/%%first_name%%/i", ws_plugin__s2member_esc_ds ($paypal["first_name"]), $msg)) && ($msg = preg_replace ("/%%last_name%%/i", ws_plugin__s2member_esc_ds ($paypal["last_name"]), $msg)))
969
+ if (($msg = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $msg)))
970
+ if (($msg = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds ($paypal["payer_email"]), $msg)))
971
+ {
972
+ if (($msg = preg_replace ("/%%user_first_name%%/i", ws_plugin__s2member_esc_ds ($user->first_name), $msg)) && ($msg = preg_replace ("/%%user_last_name%%/i", ws_plugin__s2member_esc_ds ($user->last_name), $msg)))
973
+ if (($msg = preg_replace ("/%%user_full_name%%/i", ws_plugin__s2member_esc_ds (trim ($user->first_name . " " . $user->last_name)), $msg)))
974
+ if (($msg = preg_replace ("/%%user_email%%/i", ws_plugin__s2member_esc_ds ($user->user_email), $msg)))
975
+ if (($msg = preg_replace ("/%%user_login%%/i", ws_plugin__s2member_esc_ds ($user->user_login), $msg)))
976
+ if (($msg = preg_replace ("/%%user_id%%/i", ws_plugin__s2member_esc_ds ($user_id), $msg)))
977
+ {
978
+ if (is_array ($fields) && !empty ($fields))
979
+ foreach ($fields as $var => $val) /* Custom Registration Fields. */
980
+ if (! ($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", ws_plugin__s2member_esc_ds (maybe_serialize ($val)), $msg)))
981
+ break;
982
+ /**/
983
+ if (($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg))))
984
+ foreach (ws_plugin__s2member_trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["payment_notification_recipients"])) as $recipient)
985
+ ($recipient) ? wp_mail ($recipient, apply_filters ("ws_plugin__s2member_payment_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_payment_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
986
+ }
987
+ }
988
  /**/
989
  $paypal["s2member_log"][] = "Payment Notification Emails have been processed.";
990
  }
997
  {
998
  $paypal["s2member_log"][] = "Skipping this IPN response, for now. The Subscr. ID is not associated with a registered Member.";
999
  $paypal["s2member_log"][] = "Storing this IPN response into a Transient Queue for s2Member. This will be re-processed when registration occurs.";
1000
+ set_transient (md5 ("s2member_transient_ipn_subscr_payment_" . $paypal["subscr_id"]), $_paypal, 43200);
1001
  }
1002
  /**/
1003
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
1066
  {
1067
  if (!$user->has_cap ("administrator")) /* Do NOT process this routine on Administrators. */
1068
  {
1069
+ $fields = get_user_option ("s2member_custom_fields", $user_id);
1070
+ /**/
1071
  if (!get_user_option ("s2member_auto_eot_time", $user_id)) /* Respect existing. */
1072
  {
1073
  $processing = $during = true; /* Yes, we ARE processing this. */
1086
  {
1087
  $paypal["s2member_log"][] = "Ignoring Cancellation. An Auto-EOT Time is already set for this Member. An s2Member API Notification will still be processed however.";
1088
  }
1089
+ /**/
1090
+ if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["cancellation_notification_urls"] && is_array ($cv = preg_split ("/\|/", $paypal["custom"])))
1091
+ {
1092
+ foreach (preg_split ("/[\r\n\t]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["cancellation_notification_urls"]) as $url) /* Handle Cancellation Notifications. */
1093
+ /**/
1094
+ if (($url = preg_replace ("/%%cv([0-9]+)%%/ei", 'urlencode(trim($cv[$1]))', $url)) && ($url = preg_replace ("/%%subscr_id%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["subscr_id"])), $url)))
1095
+ if (($url = preg_replace ("/%%item_number%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["item_number"])), $url)) && ($url = preg_replace ("/%%item_name%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["item_name"])), $url)))
1096
+ if (($url = preg_replace ("/%%user_first_name%%/i", ws_plugin__s2member_esc_ds (urlencode ($user->first_name)), $url)) && ($url = preg_replace ("/%%user_last_name%%/i", ws_plugin__s2member_esc_ds (urlencode ($user->last_name)), $url)))
1097
+ if (($url = preg_replace ("/%%user_full_name%%/i", ws_plugin__s2member_esc_ds (urlencode (trim ($user->first_name . " " . $user->last_name))), $url)))
1098
+ if (($url = preg_replace ("/%%user_email%%/i", ws_plugin__s2member_esc_ds (urlencode ($user->user_email)), $url)))
1099
+ if (($url = preg_replace ("/%%user_login%%/i", ws_plugin__s2member_esc_ds (urlencode ($user->user_login)), $url)))
1100
+ if (($url = preg_replace ("/%%user_id%%/i", ws_plugin__s2member_esc_ds (urlencode ($user_id)), $url)))
1101
+ {
1102
+ if (is_array ($fields) && !empty ($fields))
1103
+ foreach ($fields as $var => $val) /* Custom Registration Fields. */
1104
+ if (! ($url = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", ws_plugin__s2member_esc_ds (urlencode (maybe_serialize ($val))), $url)))
1105
+ break;
1106
+ /**/
1107
+ if (($url = trim (preg_replace ("/%%(.+?)%%/i", "", $url))))
1108
+ ws_plugin__s2member_remote ($url);
1109
+ }
1110
+ /**/
1111
+ $paypal["s2member_log"][] = "Cancellation Notification URLs have been processed.";
1112
+ }
1113
+ /**/
1114
+ if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["cancellation_notification_recipients"] && is_array ($cv = preg_split ("/\|/", $paypal["custom"])))
1115
+ {
1116
+ $msg = $sbj = "( s2Member / API Notification Email ) - Cancellation";
1117
+ $msg .= "\n\n"; /* Spacing in the message body. */
1118
+ /**/
1119
+ $msg .= "subscr_id: %%subscr_id%%\n";
1120
+ $msg .= "item_number: %%item_number%%\n";
1121
+ $msg .= "item_name: %%item_name%%\n";
1122
+ $msg .= "user_first_name: %%user_first_name%%\n";
1123
+ $msg .= "user_last_name: %%user_last_name%%\n";
1124
+ $msg .= "user_full_name: %%user_full_name%%\n";
1125
+ $msg .= "user_email: %%user_email%%\n";
1126
+ $msg .= "user_login: %%user_login%%\n";
1127
+ $msg .= "user_id: %%user_id%%\n";
1128
+ /**/
1129
+ if (is_array ($fields) && !empty ($fields))
1130
+ foreach ($fields as $var => $val)
1131
+ $msg .= $var . ": %%" . $var . "%%\n";
1132
+ /**/
1133
+ $msg .= "cv0: %%cv0%%\n";
1134
+ $msg .= "cv1: %%cv1%%\n";
1135
+ $msg .= "cv2: %%cv2%%\n";
1136
+ $msg .= "cv3: %%cv3%%\n";
1137
+ $msg .= "cv4: %%cv4%%\n";
1138
+ $msg .= "cv5: %%cv5%%\n";
1139
+ $msg .= "cv6: %%cv6%%\n";
1140
+ $msg .= "cv7: %%cv7%%\n";
1141
+ $msg .= "cv8: %%cv8%%\n";
1142
+ $msg .= "cv9: %%cv9%%";
1143
+ /**/
1144
+ if (($msg = preg_replace ("/%%cv([0-9]+)%%/ei", 'trim($cv[$1])', $msg)) && ($msg = preg_replace ("/%%subscr_id%%/i", ws_plugin__s2member_esc_ds ($paypal["subscr_id"]), $msg)))
1145
+ if (($msg = preg_replace ("/%%item_number%%/i", ws_plugin__s2member_esc_ds ($paypal["item_number"]), $msg)) && ($msg = preg_replace ("/%%item_name%%/i", ws_plugin__s2member_esc_ds ($paypal["item_name"]), $msg)))
1146
+ if (($msg = preg_replace ("/%%user_first_name%%/i", ws_plugin__s2member_esc_ds ($user->first_name), $msg)) && ($msg = preg_replace ("/%%user_last_name%%/i", ws_plugin__s2member_esc_ds ($user->last_name), $msg)))
1147
+ if (($msg = preg_replace ("/%%user_full_name%%/i", ws_plugin__s2member_esc_ds (trim ($user->first_name . " " . $user->last_name)), $msg)))
1148
+ if (($msg = preg_replace ("/%%user_email%%/i", ws_plugin__s2member_esc_ds ($user->user_email), $msg)))
1149
+ if (($msg = preg_replace ("/%%user_login%%/i", ws_plugin__s2member_esc_ds ($user->user_login), $msg)))
1150
+ if (($msg = preg_replace ("/%%user_id%%/i", ws_plugin__s2member_esc_ds ($user_id), $msg)))
1151
+ {
1152
+ if (is_array ($fields) && !empty ($fields))
1153
+ foreach ($fields as $var => $val) /* Custom Registration Fields. */
1154
+ if (! ($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", ws_plugin__s2member_esc_ds (maybe_serialize ($val)), $msg)))
1155
+ break;
1156
+ /**/
1157
+ if (($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg))))
1158
+ foreach (ws_plugin__s2member_trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["cancellation_notification_recipients"])) as $recipient)
1159
+ ($recipient) ? wp_mail ($recipient, apply_filters ("ws_plugin__s2member_cancellation_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_cancellation_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
1160
+ }
1161
+ /**/
1162
+ $paypal["s2member_log"][] = "Cancellation Notification Emails have been processed.";
1163
+ }
1164
  }
1165
  else
1166
  {
1167
  $paypal["s2member_log"][] = "Ignoring Cancellation. The existing User ID is associated with an Administrator. Stopping here. Otherwise, an Administrator could lose access.";
1168
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1169
  }
1170
  else
1171
  {
1213
  $is_refund = (preg_match ("/^refunded$/i", $paypal["payment_status"]) && $paypal["parent_txn_id"]);
1214
  $is_reversal = (preg_match ("/^(reversed|reversal)$/i", $paypal["payment_status"]) && $paypal["parent_txn_id"]);
1215
  $is_reversal = (!$is_reversal) ? (preg_match ("/^new_case$/i", $paypal["txn_type"]) && preg_match ("/^chargeback$/i", $paypal["case_type"])) : $is_reversal;
1216
+ $is_refund_or_reversal = ($is_refund || $is_reversal); /* If either of the previous tests above evaluated to true; it's obviously a Refund or Reversal. */
1217
+ $is_delayed_eot = (preg_match ("/^(subscr_eot|recurring_payment_expired)$/i", $paypal["txn_type"]) && preg_match ("/^I-/i", $paypal["subscr_id"]));
1218
  /**/
1219
  if ($is_refund_or_reversal)
1220
  $paypal["s2member_log"][] = "s2Member txn_type identified as [empty or irrelevant] w/ payment_status (refunded|reversed|reversal) - or - new_case w/ case_type (chargeback).";
1223
  /**/
1224
  if (($user_id = ws_plugin__s2member_paypal_user_id ($paypal["subscr_id"])) && is_object ($user = new WP_User ($user_id)) && $user->ID)
1225
  {
1226
+ $fields = get_user_option ("s2member_custom_fields", $user_id); /* These will be needed below. */
1227
+ /**/
1228
  if ( /* Here we take action, BUT based on Auto EOT Behavior options; as configured by the Site Owner. */
1229
  (!$is_refund_or_reversal && !$is_delayed_eot && !get_user_option ("s2member_auto_eot_time", $user_id))/**/
1230
  || ($is_refund_or_reversal && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["triggers_immediate_eot"] === "refunds,reversals")/**/
1268
  if (($url = preg_replace ("/%%user_email%%/i", ws_plugin__s2member_esc_ds (urlencode ($user->user_email)), $url)))
1269
  if (($url = preg_replace ("/%%user_login%%/i", ws_plugin__s2member_esc_ds (urlencode ($user->user_login)), $url)))
1270
  if (($url = preg_replace ("/%%user_id%%/i", ws_plugin__s2member_esc_ds (urlencode ($user_id)), $url)))
1271
+ {
1272
+ if (is_array ($fields) && !empty ($fields))
1273
+ foreach ($fields as $var => $val) /* Custom Registration Fields. */
1274
+ if (! ($url = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", ws_plugin__s2member_esc_ds (urlencode (maybe_serialize ($val))), $url)))
1275
+ break;
1276
+ /**/
1277
+ if (($url = trim (preg_replace ("/%%(.+?)%%/i", "", $url))))
1278
+ ws_plugin__s2member_remote ($url);
1279
+ }
1280
  /**/
1281
  $paypal["s2member_log"][] = "EOT/Deletion Notification URLs have been processed.";
1282
  }
1285
  {
1286
  $msg = $sbj = "( s2Member / API Notification Email ) - EOT/Deletion";
1287
  $msg .= "\n\n"; /* Spacing in the message body. */
1288
+ /**/
1289
  $msg .= "subscr_id: %%subscr_id%%\n";
1290
  $msg .= "user_first_name: %%user_first_name%%\n";
1291
  $msg .= "user_last_name: %%user_last_name%%\n";
1293
  $msg .= "user_email: %%user_email%%\n";
1294
  $msg .= "user_login: %%user_login%%\n";
1295
  $msg .= "user_id: %%user_id%%\n";
1296
+ /**/
1297
+ if (is_array ($fields) && !empty ($fields))
1298
+ foreach ($fields as $var => $val)
1299
+ $msg .= $var . ": %%" . $var . "%%\n";
1300
+ /**/
1301
  $msg .= "cv0: %%cv0%%\n";
1302
  $msg .= "cv1: %%cv1%%\n";
1303
  $msg .= "cv2: %%cv2%%\n";
1315
  if (($msg = preg_replace ("/%%user_email%%/i", ws_plugin__s2member_esc_ds ($user->user_email), $msg)))
1316
  if (($msg = preg_replace ("/%%user_login%%/i", ws_plugin__s2member_esc_ds ($user->user_login), $msg)))
1317
  if (($msg = preg_replace ("/%%user_id%%/i", ws_plugin__s2member_esc_ds ($user_id), $msg)))
1318
+ {
1319
+ if (is_array ($fields) && !empty ($fields))
1320
+ foreach ($fields as $var => $val) /* Custom Registration Fields. */
1321
+ if (! ($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", ws_plugin__s2member_esc_ds (maybe_serialize ($val)), $msg)))
1322
+ break;
1323
  /**/
1324
+ if (($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg))))
1325
+ foreach (ws_plugin__s2member_trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["eot_del_notification_recipients"])) as $recipient)
1326
+ ($recipient) ? wp_mail ($recipient, apply_filters ("ws_plugin__s2member_eot_del_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_eot_del_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
1327
+ }
1328
  /**/
1329
  $paypal["s2member_log"][] = "EOT/Deletion Notification Emails have been processed.";
1330
  }
1346
  /**/
1347
  else /* Otherwise, we can actually delete them. */
1348
  /* This will automatically trigger `eot_del_notification_urls` as well. */
1349
+ wp_delete_user ($user_id); /* `ws_plugin__s2member_handle_user_deletions()` */
1350
  /**/
1351
  $paypal["s2member_log"][] = "This Member's account has been " . ( (is_multisite ()) ? "removed" : "deleted") . ".";
1352
  /**/
1436
  if (($url = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (urlencode (trim ($paypal["first_name"] . " " . $paypal["last_name"]))), $url)))
1437
  if (($url = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["payer_email"])), $url)))
1438
  if (($url = preg_replace ("/%%user_id%%/i", ws_plugin__s2member_esc_ds (urlencode ($user_id)), $url)))
1439
+ {
1440
+ if (is_array ($fields) && !empty ($fields))
1441
+ foreach ($fields as $var => $val) /* Custom Registration Fields. */
1442
+ if (! ($url = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", ws_plugin__s2member_esc_ds (urlencode (maybe_serialize ($val))), $url)))
1443
+ break;
1444
+ /**/
1445
+ if (($url = trim (preg_replace ("/%%(.+?)%%/i", "", $url))))
1446
+ ws_plugin__s2member_remote ($url);
1447
+ }
1448
  /**/
1449
  $paypal["s2member_log"][] = "Refund/Reversal Notification URLs have been processed.";
1450
  }
1453
  {
1454
  $msg = $sbj = "( s2Member / API Notification Email ) - Refund/Reversal";
1455
  $msg .= "\n\n"; /* Spacing in the message body. */
1456
+ /**/
1457
  $msg .= "subscr_id: %%subscr_id%%\n";
1458
  $msg .= "parent_txn_id: %%parent_txn_id%%\n";
1459
  $msg .= "item_number: %%item_number%%\n";
1465
  $msg .= "full_name: %%full_name%%\n";
1466
  $msg .= "payer_email: %%payer_email%%\n";
1467
  $msg .= "user_id: %%user_id%%\n";
1468
+ /**/
1469
+ if (is_array ($fields) && !empty ($fields))
1470
+ foreach ($fields as $var => $val)
1471
+ $msg .= $var . ": %%" . $var . "%%\n";
1472
+ /**/
1473
  $msg .= "cv0: %%cv0%%\n";
1474
  $msg .= "cv1: %%cv1%%\n";
1475
  $msg .= "cv2: %%cv2%%\n";
1488
  if (($msg = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $msg)))
1489
  if (($msg = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds ($paypal["payer_email"]), $msg)))
1490
  if (($msg = preg_replace ("/%%user_id%%/i", ws_plugin__s2member_esc_ds ($user_id), $msg)))
1491
+ {
1492
+ if (is_array ($fields) && !empty ($fields))
1493
+ foreach ($fields as $var => $val) /* Custom Registration Fields. */
1494
+ if (! ($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", ws_plugin__s2member_esc_ds (maybe_serialize ($val)), $msg)))
1495
+ break;
1496
  /**/
1497
+ if (($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg))))
1498
+ foreach (ws_plugin__s2member_trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["ref_rev_notification_recipients"])) as $recipient)
1499
+ ($recipient) ? wp_mail ($recipient, apply_filters ("ws_plugin__s2member_ref_rev_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_ref_rev_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
1500
+ }
1501
  /**/
1502
  $paypal["s2member_log"][] = "Refund/Reversal Notification Emails have been processed.";
1503
  }
1556
  if (($url = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (urlencode (trim ($paypal["first_name"] . " " . $paypal["last_name"]))), $url)))
1557
  if (($url = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds (urlencode ($paypal["payer_email"])), $url)))
1558
  /**/
1559
+ if (($url = trim (preg_replace ("/%%(.+?)%%/i", "", $url))))
1560
+ ws_plugin__s2member_remote ($url);
1561
  /**/
1562
  $paypal["s2member_log"][] = "Specific Post/Page ~ Refund/Reversal Notification URLs have been processed.";
1563
  }
1566
  {
1567
  $msg = $sbj = "( s2Member / API Notification Email ) - Specific Post/Page ~ Refund/Reversal";
1568
  $msg .= "\n\n"; /* Spacing in the message body. */
1569
+ /**/
1570
  $msg .= "parent_txn_id: %%parent_txn_id%%\n";
1571
  $msg .= "item_number: %%item_number%%\n";
1572
  $msg .= "item_name: %%item_name%%\n";
1594
  if (($msg = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $msg)))
1595
  if (($msg = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds ($paypal["payer_email"]), $msg)))
1596
  /**/
1597
+ if (($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg))))
1598
+ foreach (ws_plugin__s2member_trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sp_ref_rev_notification_recipients"])) as $recipient)
1599
+ ($recipient) ? wp_mail ($recipient, apply_filters ("ws_plugin__s2member_sp_ref_rev_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_sp_ref_rev_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
1600
  /**/
1601
  $paypal["s2member_log"][] = "Specific Post/Page ~ Refund/Reversal Notification Emails have been processed.";
1602
  }
1611
  }
1612
  else
1613
  {
1614
+ $paypal["s2member_log"][] = "Ignoring this IPN request. The txn_type/status does NOT require any action on the part of s2Member.";
1615
  }
1616
  }
1617
  else /* Else a custom conditional has been applied by Filters. */
1644
  $paypal["s2member_log"][] = "Unable to verify POST vars. Possibly caused by a fraudulent request. If this error continues, please run IPN tests against your server from a PayPal® Sandbox account. They provide special diagnostic tools to assist you.";
1645
  $paypal["s2member_log"][] = "If you're absolutely SURE that your PayPal® configuration is valid, you may want to run some tests on your server, just to be sure \$_POST variables are populated, and that your server is able to connect to PayPal® over an HTTPS connection.";
1646
  $paypal["s2member_log"][] = "s2Member uses the WP_Http class for remote connections; which will try to use cURL first, and then fall back on the FOPEN method when cURL is not available. On a Windows® server, you may have to disable your cURL extension. Instead, set allow_url_fopen = yes in your php.ini file. The cURL extension (usually) does NOT support SSL connections on a Windows® server.";
1647
+ $paypal["s2member_log"][] = var_export ($_REQUEST, true); /* Recording _POST + _GET vars for analysis and debugging. */
1648
  }
1649
  /*
1650
+ Add IPN proxy ( when available ) to the $paypal array.
1651
  */
1652
  if ($_GET["s2member_paypal_proxy"]) /* For proxy identification. */
1653
  $paypal["s2member_paypal_proxy"] = $_GET["s2member_paypal_proxy"];
1654
  /*
1655
+ Add IPN proxy use vars ( when available ) to the $paypal array.
1656
+ */
1657
+ if ($_GET["s2member_paypal_proxy_use"]) /* For proxy specifications. */
1658
+ $paypal["s2member_paypal_proxy_use"] = $_GET["s2member_paypal_proxy_use"];
1659
+ /*
1660
  Also add IPN proxy self-verification ( when available ) to the $paypal array.
1661
  */
1662
  if ($_GET["s2member_paypal_proxy_verification"]) /* Proxy identification w/verification. */
1669
  $log4 = (is_multisite () && !is_main_site ()) ? ($_log4 = $current_blog->domain . $current_blog->path) . "\n" . $log4 : $log4;
1670
  $log2 = (is_multisite () && !is_main_site ()) ? "paypal-ipn-4-" . trim (preg_replace ("/[^a-z0-9]/i", "-", $_log4), "-") . ".log" : "paypal-ipn.log";
1671
  /**/
1672
+ if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["gateway_debug_logs"])
1673
  if (is_dir ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"]))
1674
  if (is_writable ($logs_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"]))
1675
  file_put_contents ($logs_dir . "/" . $log2, $log4 . "\n" . var_export ($paypal, true) . "\n\n", FILE_APPEND);
1678
  do_action ("ws_plugin__s2member_during_paypal_notify", get_defined_vars ());
1679
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
1680
  /**/
1681
+ header ("HTTP/1.0 200 OK"); /* Send a 200 OK status header. */
1682
+ exit ($paypal["s2member_paypal_proxy_return_url"]); /* Return. */
1683
  }
1684
  /**/
1685
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
includes/functions/separates/paypal-return.inc.php CHANGED
@@ -26,12 +26,13 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_return"))
26
  /**/
27
  do_action ("ws_plugin__s2member_before_paypal_return", get_defined_vars ());
28
  /**/
29
- if ($_GET["s2member_paypal_return"] && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])
30
  {
31
- if (is_array ($paypal = ws_plugin__s2member_paypal_postvars ())) /* Verify PayPal® POST vars. */
32
  {
33
  $paypal["s2member_log"][] = "Return-Data received on: " . date ("D M j, Y g:i:s a T");
34
- $paypal["s2member_log"][] = "s2Member POST vars verified through a POST back to PayPal®.";
 
35
  /**/
36
  $payment_status_issues = "/^(failed|denied|expired|refunded|partially_refunded|reversed|reversal|canceled_reversal|voided)$/i";
37
  /**/
@@ -78,7 +79,7 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_return"))
78
  if (($code = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $code)))
79
  if (($code = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds ($paypal["payer_email"]), $code)))
80
  /**/
81
- if (($code = trim ($code))) /* Make sure it is not empty. This gets stored into a Transient Queue. */
82
  {
83
  $paypal["s2member_log"][] = "Storing Specific Post/Page Tracking Codes into a Transient Queue for s2Member. These will be processed on-site.";
84
  set_transient (md5 ("s2member_transient_sp_tracking_codes_" . $paypal["txn_id"]), $code, 43200);
@@ -169,6 +170,11 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_return"))
169
  else /* Otherwise, we need to clear the eot time. */
170
  delete_user_option ($user_id, "s2member_auto_eot_time");
171
  /**/
 
 
 
 
 
172
  ws_plugin__s2member_clear_user_note_lines ($user_id, "/^Demoted by s2Member\:/");
173
  /**/
174
  $paypal["s2member_log"][] = "s2Member Level/Capabilities updated w/ advanced update routines.";
@@ -180,8 +186,8 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_return"))
180
  $paypal["s2member_log"][] = "Redirecting Customer to the Login Page. They need to log back in after this modification.";
181
  /**/
182
  echo '<script type="text/javascript">' . "\n";
183
- echo "alert('Thank You! Your membership has been updated to:\\n\\n" . esc_js ($paypal["item_name"]) . "\\n\\nYou\\'ll need to log back in now.');" . "\n";
184
- echo "window.location = '" . wp_login_url () . "';" . "\n";
185
  echo '</script>' . "\n";
186
  }
187
  else
@@ -240,15 +246,15 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_return"))
240
  if (is_multisite () && ws_plugin__s2member_is_multisite_farm () && is_main_site ())
241
  {
242
  echo '<script type="text/javascript">' . "\n";
243
- echo "alert('Thank You! Your account has been approved.\\nThe next step is to Register.\\n\\nPlease click OK to Register now.');" . "\n";/**/
244
  echo "window.location = '" . esc_js (apply_filters ("wp_signup_location", get_bloginfo ("wpurl") . "/wp-signup.php")) . "';" . "\n";
245
  echo '</script>' . "\n";
246
  }
247
  else /* Otherwise, this is NOT a Multisite install. Or it is, but the Super Administrator is NOT selling Blog creation. */
248
  {
249
  echo '<script type="text/javascript">' . "\n";
250
- echo "alert('Thank You! Your account has been approved.\\nThe next step is to Register a Username.\\n\\nPlease click OK to Register now.');" . "\n";/**/
251
- echo "window.location = '" . esc_js (add_query_arg ("action", "register", wp_login_url ())) . "';" . "\n";
252
  echo '</script>' . "\n";
253
  }
254
  /**/
@@ -300,6 +306,11 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_return"))
300
  /**/
301
  delete_user_option ($user_id, "s2member_auto_eot_time");
302
  /**/
 
 
 
 
 
303
  ws_plugin__s2member_clear_user_note_lines ($user_id, "/^Demoted by s2Member\:/");
304
  /**/
305
  $paypal["s2member_log"][] = "s2Member Level/Capabilities updated on Subscription modification.";
@@ -311,7 +322,7 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_return"))
311
  $paypal["s2member_log"][] = "Redirecting Customer to the Login Page. They need to log back in after this modification.";
312
  /**/
313
  echo '<script type="text/javascript">' . "\n";
314
- echo "alert('Thank You! Your membership has been updated to:\\n\\n" . esc_js ($paypal["item_name"]) . "\\n\\nYou\\'ll need to log back in now.');" . "\n";
315
  echo "window.location = '" . esc_js (wp_login_url ()) . "';";
316
  echo '</script>' . "\n";
317
  }
@@ -370,7 +381,7 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_return"))
370
  echo '</script>' . "\n";
371
  }
372
  }
373
- else if (!isset ($_GET["tx"]) && (empty ($_POST) || $_POST["auth"]))
374
  {
375
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
376
  do_action ("ws_plugin__s2member_during_paypal_return_before_no_return_data", get_defined_vars ());
@@ -385,7 +396,7 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_return"))
385
  $paypal["s2member_log"][] = "Redirecting Customer to the Home Page.";
386
  /**/
387
  echo '<script type="text/javascript">' . "\n";
388
- echo "alert('Thank You! ( please check your email ).\\n\\n* Note: It can take ( up to 15 minutes ) for Email Confirmation. If you don\'t receive email confirmation in the next 15 minutes, please contact Support.');" . "\n";
389
  echo ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "alert('** Sandbox Mode ** You will probably NOT receive this Email Confirmation in Sandbox Mode. Sandbox addresses are usually bogus ( for testing ).');" . "\n" : "";
390
  echo "window.location = '" . esc_js (get_bloginfo ("url")) . "';";
391
  echo '</script>' . "\n";
@@ -399,7 +410,7 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_return"))
399
  $paypal["s2member_log"][] = "Unable to verify POST vars. This is most likely related to an invalid PayPal® configuration. Please check: s2Member -> PayPal® Options.";
400
  $paypal["s2member_log"][] = "If you're absolutely SURE that your PayPal® configuration is valid, you may want to run some tests on your server, just to be sure \$_POST variables are populated, and that your server is able to connect to PayPal® over an HTTPS connection.";
401
  $paypal["s2member_log"][] = "s2Member uses the WP_Http class for remote connections; which will try to use cURL first, and then fall back on the FOPEN method when cURL is not available. On a Windows® server, you may have to disable your cURL extension. Instead, set allow_url_fopen = yes in your php.ini file. The cURL extension (usually) does NOT support SSL connections on a Windows® server.";
402
- $paypal["s2member_log"][] = var_export ($_POST, true); /* Recording _POST vars for analysis and debugging. */
403
  /**/
404
  $paypal["s2member_log"][] = "Redirecting Customer to the Login Page, due to an error that occurred.";
405
  /**/
@@ -409,11 +420,16 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_return"))
409
  echo '</script>' . "\n";
410
  }
411
  /*
412
- Add RTN proxy identification ( when available ) to the $paypal array for log reporting.
413
  */
414
  if ($_GET["s2member_paypal_proxy"]) /* For proxy identification. */
415
  $paypal["s2member_paypal_proxy"] = $_GET["s2member_paypal_proxy"];
416
  /*
 
 
 
 
 
417
  Also add RTN proxy self-verification ( when available ) to the $paypal array.
418
  */
419
  if ($_GET["s2member_paypal_proxy_verification"]) /* Proxy identification w/verification. */
@@ -426,7 +442,7 @@ if (!function_exists ("s__ws_plugin__s2member_paypal_return"))
426
  $log4 = (is_multisite () && !is_main_site ()) ? ($_log4 = $current_blog->domain . $current_blog->path) . "\n" . $log4 : $log4;
427
  $log2 = (is_multisite () && !is_main_site ()) ? "paypal-rtn-4-" . trim (preg_replace ("/[^a-z0-9]/i", "-", $_log4), "-") . ".log" : "paypal-rtn.log";
428
  /**/
429
- if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_debug"]) /* Append to log? */
430
  if (is_dir ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"])) /* Dir exists? */
431
  if (is_writable ($logs_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"]))
432
  file_put_contents ($logs_dir . "/" . $log2, $log4 . "\n" . var_export ($paypal, true) . "\n\n", FILE_APPEND);
26
  /**/
27
  do_action ("ws_plugin__s2member_before_paypal_return", get_defined_vars ());
28
  /**/
29
+ if ($_GET["s2member_paypal_return"] && ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"] || $_GET["s2member_paypal_proxy"]))
30
  {
31
+ if (is_array ($paypal = ws_plugin__s2member_paypal_postvars ()) && ($_paypal = $paypal)) /* Verify POST vars. */
32
  {
33
  $paypal["s2member_log"][] = "Return-Data received on: " . date ("D M j, Y g:i:s a T");
34
+ $paypal["s2member_log"][] = "s2Member POST vars verified " . /* Indicate Proxy Key. */
35
+ ( ($postvars["proxy_verified"]) ? "with a Proxy Key" : "through a POST back to PayPal®.");
36
  /**/
37
  $payment_status_issues = "/^(failed|denied|expired|refunded|partially_refunded|reversed|reversal|canceled_reversal|voided)$/i";
38
  /**/
79
  if (($code = preg_replace ("/%%full_name%%/i", ws_plugin__s2member_esc_ds (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $code)))
80
  if (($code = preg_replace ("/%%payer_email%%/i", ws_plugin__s2member_esc_ds ($paypal["payer_email"]), $code)))
81
  /**/
82
+ if (($code = trim (preg_replace ("/%%(.+?)%%/i", "", $code)))) /* This gets stored into a Transient Queue. */
83
  {
84
  $paypal["s2member_log"][] = "Storing Specific Post/Page Tracking Codes into a Transient Queue for s2Member. These will be processed on-site.";
85
  set_transient (md5 ("s2member_transient_sp_tracking_codes_" . $paypal["txn_id"]), $code, 43200);
170
  else /* Otherwise, we need to clear the eot time. */
171
  delete_user_option ($user_id, "s2member_auto_eot_time");
172
  /**/
173
+ $pr_times = get_user_option ("s2member_paid_registration_times", $user_id);
174
+ $pr_times["level"] = (!$pr_times["level"]) ? time () : $pr_times["level"]; /* Preserves existing. */
175
+ $pr_times["level" . $paypal["level"]] = (!$pr_times["level" . $paypal["level"]]) ? time () : $pr_times["level" . $paypal["level"]];
176
+ update_user_option ($user_id, "s2member_paid_registration_times", $pr_times); /* Update now. */
177
+ /**/
178
  ws_plugin__s2member_clear_user_note_lines ($user_id, "/^Demoted by s2Member\:/");
179
  /**/
180
  $paypal["s2member_log"][] = "s2Member Level/Capabilities updated w/ advanced update routines.";
186
  $paypal["s2member_log"][] = "Redirecting Customer to the Login Page. They need to log back in after this modification.";
187
  /**/
188
  echo '<script type="text/javascript">' . "\n";
189
+ echo "alert('Thank you! You\\'ve been updated to:\\n\\n" . esc_js ($paypal["item_name"]) . "\\n\\nPlease log back in now.');" . "\n";
190
+ echo "window.location = '" . esc_js (wp_login_url ()) . "';" . "\n";
191
  echo '</script>' . "\n";
192
  }
193
  else
246
  if (is_multisite () && ws_plugin__s2member_is_multisite_farm () && is_main_site ())
247
  {
248
  echo '<script type="text/javascript">' . "\n";
249
+ echo "alert('Thank you! Your account has been approved.\\nThe next step is to Register.\\n\\nPlease click OK to Register now.');" . "\n";/**/
250
  echo "window.location = '" . esc_js (apply_filters ("wp_signup_location", get_bloginfo ("wpurl") . "/wp-signup.php")) . "';" . "\n";
251
  echo '</script>' . "\n";
252
  }
253
  else /* Otherwise, this is NOT a Multisite install. Or it is, but the Super Administrator is NOT selling Blog creation. */
254
  {
255
  echo '<script type="text/javascript">' . "\n";
256
+ echo "alert('Thank you! Your account has been approved.\\nThe next step is to Register a Username.\\n\\nPlease click OK to Register now.');" . "\n";/**/
257
+ echo "window.location = '" . esc_js (add_query_arg ("action", urlencode ("register"), wp_login_url ())) . "';" . "\n";
258
  echo '</script>' . "\n";
259
  }
260
  /**/
306
  /**/
307
  delete_user_option ($user_id, "s2member_auto_eot_time");
308
  /**/
309
+ $pr_times = get_user_option ("s2member_paid_registration_times", $user_id);
310
+ $pr_times["level"] = (!$pr_times["level"]) ? time () : $pr_times["level"]; /* Preserves existing. */
311
+ $pr_times["level" . $paypal["level"]] = (!$pr_times["level" . $paypal["level"]]) ? time () : $pr_times["level" . $paypal["level"]];
312
+ update_user_option ($user_id, "s2member_paid_registration_times", $pr_times); /* Update now. */
313
+ /**/
314
  ws_plugin__s2member_clear_user_note_lines ($user_id, "/^Demoted by s2Member\:/");
315
  /**/
316
  $paypal["s2member_log"][] = "s2Member Level/Capabilities updated on Subscription modification.";
322
  $paypal["s2member_log"][] = "Redirecting Customer to the Login Page. They need to log back in after this modification.";
323
  /**/
324
  echo '<script type="text/javascript">' . "\n";
325
+ echo "alert('Thank you! You\\'ve been updated to:\\n\\n" . esc_js ($paypal["item_name"]) . "\\n\\nPlease log back in now.');" . "\n";
326
  echo "window.location = '" . esc_js (wp_login_url ()) . "';";
327
  echo '</script>' . "\n";
328
  }
381
  echo '</script>' . "\n";
382
  }
383
  }
384
+ else if ((!isset ($_GET["tx"]) && (empty ($_POST) || $_POST["auth"])) || preg_match ("/ty-email/", $_GET["s2member_paypal_proxy_use"]))
385
  {
386
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
387
  do_action ("ws_plugin__s2member_during_paypal_return_before_no_return_data", get_defined_vars ());
396
  $paypal["s2member_log"][] = "Redirecting Customer to the Home Page.";
397
  /**/
398
  echo '<script type="text/javascript">' . "\n";
399
+ echo "alert('Thank you! ( please check your email ).\\n\\n* Note: It can take ( up to 15 minutes ) for Email Confirmation. If you don\'t receive email confirmation in the next 15 minutes, please contact Support.');" . "\n";
400
  echo ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "alert('** Sandbox Mode ** You will probably NOT receive this Email Confirmation in Sandbox Mode. Sandbox addresses are usually bogus ( for testing ).');" . "\n" : "";
401
  echo "window.location = '" . esc_js (get_bloginfo ("url")) . "';";
402
  echo '</script>' . "\n";
410
  $paypal["s2member_log"][] = "Unable to verify POST vars. This is most likely related to an invalid PayPal® configuration. Please check: s2Member -> PayPal® Options.";
411
  $paypal["s2member_log"][] = "If you're absolutely SURE that your PayPal® configuration is valid, you may want to run some tests on your server, just to be sure \$_POST variables are populated, and that your server is able to connect to PayPal® over an HTTPS connection.";
412
  $paypal["s2member_log"][] = "s2Member uses the WP_Http class for remote connections; which will try to use cURL first, and then fall back on the FOPEN method when cURL is not available. On a Windows® server, you may have to disable your cURL extension. Instead, set allow_url_fopen = yes in your php.ini file. The cURL extension (usually) does NOT support SSL connections on a Windows® server.";
413
+ $paypal["s2member_log"][] = var_export ($_REQUEST, true); /* Recording _POST + _GET vars for analysis and debugging. */
414
  /**/
415
  $paypal["s2member_log"][] = "Redirecting Customer to the Login Page, due to an error that occurred.";
416
  /**/
420
  echo '</script>' . "\n";
421
  }
422
  /*
423
+ Add RTN proxy ( when available ) to the $paypal array.
424
  */
425
  if ($_GET["s2member_paypal_proxy"]) /* For proxy identification. */
426
  $paypal["s2member_paypal_proxy"] = $_GET["s2member_paypal_proxy"];
427
  /*
428
+ Add IPN proxy use vars ( when available ) to the $paypal array.
429
+ */
430
+ if ($_GET["s2member_paypal_proxy_use"]) /* For proxy specifications. */
431
+ $paypal["s2member_paypal_proxy_use"] = $_GET["s2member_paypal_proxy_use"];
432
+ /*
433
  Also add RTN proxy self-verification ( when available ) to the $paypal array.
434
  */
435
  if ($_GET["s2member_paypal_proxy_verification"]) /* Proxy identification w/verification. */
442
  $log4 = (is_multisite () && !is_main_site ()) ? ($_log4 = $current_blog->domain . $current_blog->path) . "\n" . $log4 : $log4;
443
  $log2 = (is_multisite () && !is_main_site ()) ? "paypal-rtn-4-" . trim (preg_replace ("/[^a-z0-9]/i", "-", $_log4), "-") . ".log" : "paypal-rtn.log";
444
  /**/
445
+ if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["gateway_debug_logs"]) /* Append to log? */
446
  if (is_dir ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"])) /* Dir exists? */
447
  if (is_writable ($logs_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"]))
448
  file_put_contents ($logs_dir . "/" . $log2, $log4 . "\n" . var_export ($paypal, true) . "\n\n", FILE_APPEND);
includes/functions/sp-access.inc.php CHANGED
@@ -27,7 +27,7 @@ if (!function_exists ("ws_plugin__s2member_sp_access_link_gen"))
27
  if (($sp_ids = preg_replace ("/[^0-9;,]/", "", $sp_ids)) && ($leading_id = preg_replace ("/^([0-9]+)(.*?)$/", "$1", $sp_ids)) && $hours)
28
  {
29
  $sp_access = ws_plugin__s2member_encrypt ("sp_time_hours:.:|:.:" . $sp_ids . ":.:|:.:" . strtotime ("now") . ":.:|:.:" . $hours);
30
- $sp_access_link = add_query_arg ("s2member_sp_access", $sp_access, get_permalink ($leading_id));
31
  /**/
32
  if ($shrink && ($tinyurl = ws_plugin__s2member_remote ("http://tinyurl.com/api-create.php?url=" . rawurlencode ($sp_access_link))))
33
  return apply_filters ("ws_plugin__s2member_sp_access_link_gen", $tinyurl, get_defined_vars ()); /* tinyURL is recommended. */
27
  if (($sp_ids = preg_replace ("/[^0-9;,]/", "", $sp_ids)) && ($leading_id = preg_replace ("/^([0-9]+)(.*?)$/", "$1", $sp_ids)) && $hours)
28
  {
29
  $sp_access = ws_plugin__s2member_encrypt ("sp_time_hours:.:|:.:" . $sp_ids . ":.:|:.:" . strtotime ("now") . ":.:|:.:" . $hours);
30
+ $sp_access_link = add_query_arg ("s2member_sp_access", urlencode ($sp_access), get_permalink ($leading_id));
31
  /**/
32
  if ($shrink && ($tinyurl = ws_plugin__s2member_remote ("http://tinyurl.com/api-create.php?url=" . rawurlencode ($sp_access_link))))
33
  return apply_filters ("ws_plugin__s2member_sp_access_link_gen", $tinyurl, get_defined_vars ()); /* tinyURL is recommended. */
includes/functions/tracking-codes.inc.php CHANGED
@@ -39,7 +39,7 @@ if (!function_exists ("ws_plugin__s2member_display_signup_tracking_codes"))
39
  {
40
  delete_transient ($transient); /* Only display this ONE time. Delete transient immediately. */
41
  /**/
42
- echo '<img src="' . add_query_arg ("s2member_delete_signup_tracking_cookie", "1", get_bloginfo ("wpurl")) . '" alt="." style="width:1px; height:1px; border:0;" />' . "\n";
43
  /**/
44
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
45
  do_action ("ws_plugin__s2member_during_display_signup_tracking_codes", get_defined_vars ());
@@ -103,7 +103,7 @@ if (!function_exists ("ws_plugin__s2member_display_sp_tracking_codes"))
103
  {
104
  delete_transient ($transient); /* Only display this ONE time. Delete transient immediately. */
105
  /**/
106
- echo '<img src="' . add_query_arg ("s2member_delete_sp_tracking_cookie", "1", get_bloginfo ("wpurl")) . '" alt="." style="width:1px; height:1px; border:0;" />' . "\n";
107
  /**/
108
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
109
  do_action ("ws_plugin__s2member_during_display_sp_tracking_codes", get_defined_vars ());
39
  {
40
  delete_transient ($transient); /* Only display this ONE time. Delete transient immediately. */
41
  /**/
42
+ echo '<img src="' . add_query_arg ("s2member_delete_signup_tracking_cookie", urlencode ("1"), get_bloginfo ("wpurl")) . '" alt="." style="width:1px; height:1px; border:0;" />' . "\n";
43
  /**/
44
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
45
  do_action ("ws_plugin__s2member_during_display_signup_tracking_codes", get_defined_vars ());
103
  {
104
  delete_transient ($transient); /* Only display this ONE time. Delete transient immediately. */
105
  /**/
106
+ echo '<img src="' . add_query_arg ("s2member_delete_sp_tracking_cookie", urlencode ("1"), get_bloginfo ("wpurl")) . '" alt="." style="width:1px; height:1px; border:0;" />' . "\n";
107
  /**/
108
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
109
  do_action ("ws_plugin__s2member_during_display_sp_tracking_codes", get_defined_vars ());
includes/functions/translations.inc.php CHANGED
@@ -57,10 +57,10 @@ if (!function_exists ("ws_plugin__s2member_translation_mangler"))
57
  $current_user_blogs = ($current_user_blogs >= 0) ? $current_user_blogs : 0;
58
  /**/
59
  if ($current_user_blogs >= 1) /* So here they already have at least 1 Blog. This message works fine. */
60
- $translated = apply_filters ("ws_plugin__s2member_translation_mangler", "Welcome back, %s. By filling out the form below, you can <strong>add another site to your account</strong>. You may create up to " . $blogs_allowed . " site" . ( ($blogs_allowed < 1 || $blogs_allowed > 1) ? "s" : "") . "; but please write responsibly<em>!</em>", get_defined_vars ());
61
  /**/
62
  else /* Otherwise, we need a different message. One that is NOT confusing to a new Customer. */
63
- $translated = apply_filters ("ws_plugin__s2member_translation_mangler", "Hi %s. By filling out the form below, you can <strong>add a site to your account</strong>. You may create up to " . $blogs_allowed . " site" . ( ($blogs_allowed < 1 || $blogs_allowed > 1) ? "s" : "") . "; but please write responsibly<em>!</em>", get_defined_vars ());
64
  }
65
  }
66
  }
57
  $current_user_blogs = ($current_user_blogs >= 0) ? $current_user_blogs : 0;
58
  /**/
59
  if ($current_user_blogs >= 1) /* So here they already have at least 1 Blog. This message works fine. */
60
+ $translated = apply_filters ("ws_plugin__s2member_translation_mangler", "By filling out the form below, you can <strong>add another site to your account</strong>." . ( ($blogs_allowed > 1) ? "<br />You may create up to " . $blogs_allowed . " site" . ( ($blogs_allowed < 1 || $blogs_allowed > 1) ? "s" : "") . "." : ""), get_defined_vars ());
61
  /**/
62
  else /* Otherwise, we need a different message. One that is NOT confusing to a new Customer. */
63
+ $translated = apply_filters ("ws_plugin__s2member_translation_mangler", "By filling out the form below, you can <strong>add a site to your account</strong>." . ( ($blogs_allowed > 1) ? "<br />You may create up to " . $blogs_allowed . " site" . ( ($blogs_allowed < 1 || $blogs_allowed > 1) ? "s" : "") . "." : ""), get_defined_vars ());
64
  }
65
  }
66
  }
includes/functions/user-access-level.inc.php CHANGED
@@ -12,7 +12,7 @@ If not, see: <http://www.gnu.org/licenses/>.
12
  Direct access denial.
13
  */
14
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
15
- exit("Do not access this file directly.");
16
  /*
17
  Function for determing the Access Level of a User/Member.
18
 
@@ -30,10 +30,10 @@ if (!function_exists ("ws_plugin__s2member_user_access_level"))
30
  {
31
  $user = (func_num_args () && is_object ($user)) ? $user : false;
32
  /**/
33
- if ((func_num_args () && !$user) || (!$user && !((is_user_logged_in ()) ? wp_get_current_user () : false)))
34
  {
35
  return apply_filters ("ws_plugin__s2member_user_access_level", -1, get_defined_vars ());
36
- /* Return of -1, means $user was passed in, but is NOT an object; or nobody is logged in. */
37
  }
38
  else if (($user && $user->has_cap ("access_s2member_level4")) || (!$user && current_user_can ("access_s2member_level4")))
39
  {
12
  Direct access denial.
13
  */
14
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
15
+ exit ("Do not access this file directly.");
16
  /*
17
  Function for determing the Access Level of a User/Member.
18
 
30
  {
31
  $user = (func_num_args () && is_object ($user)) ? $user : false;
32
  /**/
33
+ if ((func_num_args () && !$user) || (!$user && ! ( (is_user_logged_in ()) ? wp_get_current_user () : false)))
34
  {
35
  return apply_filters ("ws_plugin__s2member_user_access_level", -1, get_defined_vars ());
36
+ /* Return of -1, means $user was passed in but is NOT an object; or nobody is logged in. */
37
  }
38
  else if (($user && $user->has_cap ("access_s2member_level4")) || (!$user && current_user_can ("access_s2member_level4")))
39
  {
includes/functions/user-access-role.inc.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Copyright: © 2009 WebSharks, Inc. ( coded in the USA )
4
+ <mailto:support@websharks-inc.com> <http://www.websharks-inc.com/>
5
+
6
+ Released under the terms of the GNU General Public License.
7
+ You should have received a copy of the GNU General Public License,
8
+ along with this software. In the main directory, see: /licensing/
9
+ If not, see: <http://www.gnu.org/licenses/>.
10
+ */
11
+ /*
12
+ Direct access denial.
13
+ */
14
+ if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
15
+ exit ("Do not access this file directly.");
16
+ /*
17
+ Function for determing the Access Role of a User/Member.
18
+ If $user is NOT passed in, check the current User/Member.
19
+ If $user IS passed in, this function will check a specific $user.
20
+ */
21
+ if (!function_exists ("ws_plugin__s2member_user_access_role"))
22
+ {
23
+ function ws_plugin__s2member_user_access_role ($user = FALSE)
24
+ {
25
+ $user = (func_num_args () && is_object ($user)) ? $user : false;
26
+ /**/
27
+ if ((func_num_args () && !$user) || (!$user && (! ($user = (is_user_logged_in ()) ? wp_get_current_user () : false) || !$user->roles[0])))
28
+ {
29
+ return apply_filters ("ws_plugin__s2member_user_access_role", "", get_defined_vars ());
30
+ /* Return of "", means $user was passed in but is NOT an object; or nobody is logged in, or they have to Role. */
31
+ }
32
+ else /* Else we return the first role in their array of assigned WordPress Roles. */
33
+ return apply_filters ("ws_plugin__s2member_user_access_role", $user->roles[0], get_defined_vars ());
34
+ }
35
+ }
36
+ ?>
includes/functions/user-deletions.inc.php CHANGED
@@ -74,9 +74,12 @@ if (!function_exists ("ws_plugin__s2member_handle_user_deletions"))
74
  {
75
  $custom = get_user_option ("s2member_custom", $user_id); /* An EOT Notification is triggered, EVEN if this is empty. */
76
  $subscr_id = get_user_option ("s2member_subscr_id", $user_id); /* And also, EVEN if this is empty. */
 
77
  /**/
78
  delete_user_option ($user_id, "s2member_custom"); /* Now we can remove these User options ( for this Blog ). */
79
  delete_user_option ($user_id, "s2member_subscr_id"); /* The `wpmu_delete_user` Hook also handles this. */
 
 
80
  delete_user_option ($user_id, "s2member_last_payment_time");
81
  delete_user_option ($user_id, "s2member_auto_eot_time");
82
  delete_user_option ($user_id, "s2member_notes");
@@ -94,15 +97,22 @@ if (!function_exists ("ws_plugin__s2member_handle_user_deletions"))
94
  if (($url = preg_replace ("/%%user_email%%/i", ws_plugin__s2member_esc_ds (urlencode ($user->user_email)), $url)))
95
  if (($url = preg_replace ("/%%user_login%%/i", ws_plugin__s2member_esc_ds (urlencode ($user->user_login)), $url)))
96
  if (($url = preg_replace ("/%%user_id%%/i", ws_plugin__s2member_esc_ds (urlencode ($user_id)), $url)))
97
- /**/
98
- if (($url = trim ($url))) /* Empty? */
99
- ws_plugin__s2member_remote ($url);
 
 
 
 
 
 
100
  }
101
  /**/
102
  if (is_object ($user = new WP_User ($user_id)) && $user->ID && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["eot_del_notification_recipients"] && is_array ($cv = preg_split ("/\|/", $custom)))
103
  {
104
  $msg = $sbj = "( s2Member / API Notification Email ) - EOT/Deletion";
105
  $msg .= "\n\n"; /* Spacing in the message body. */
 
106
  $msg .= "subscr_id: %%subscr_id%%\n";
107
  $msg .= "user_first_name: %%user_first_name%%\n";
108
  $msg .= "user_last_name: %%user_last_name%%\n";
@@ -110,6 +120,11 @@ if (!function_exists ("ws_plugin__s2member_handle_user_deletions"))
110
  $msg .= "user_email: %%user_email%%\n";
111
  $msg .= "user_login: %%user_login%%\n";
112
  $msg .= "user_id: %%user_id%%\n";
 
 
 
 
 
113
  $msg .= "cv0: %%cv0%%\n";
114
  $msg .= "cv1: %%cv1%%\n";
115
  $msg .= "cv2: %%cv2%%\n";
@@ -127,10 +142,16 @@ if (!function_exists ("ws_plugin__s2member_handle_user_deletions"))
127
  if (($msg = preg_replace ("/%%user_email%%/i", ws_plugin__s2member_esc_ds ($user->user_email), $msg)))
128
  if (($msg = preg_replace ("/%%user_login%%/i", ws_plugin__s2member_esc_ds ($user->user_login), $msg)))
129
  if (($msg = preg_replace ("/%%user_id%%/i", ws_plugin__s2member_esc_ds ($user_id), $msg)))
130
- /**/
131
- foreach (ws_plugin__s2member_trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["eot_del_notification_recipients"])) as $recipient)
 
 
 
132
  /**/
133
- ($recipient) ? mail ($recipient, $sbj, apply_filters ("ws_plugin__s2member_eot_del_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
 
 
 
134
  }
135
  /**/
136
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
74
  {
75
  $custom = get_user_option ("s2member_custom", $user_id); /* An EOT Notification is triggered, EVEN if this is empty. */
76
  $subscr_id = get_user_option ("s2member_subscr_id", $user_id); /* And also, EVEN if this is empty. */
77
+ $fields = get_user_option ("s2member_custom_fields", $user_id); /* Used in API Notifications. */
78
  /**/
79
  delete_user_option ($user_id, "s2member_custom"); /* Now we can remove these User options ( for this Blog ). */
80
  delete_user_option ($user_id, "s2member_subscr_id"); /* The `wpmu_delete_user` Hook also handles this. */
81
+ /**/
82
+ delete_user_option ($user_id, "s2member_paid_registration_times");
83
  delete_user_option ($user_id, "s2member_last_payment_time");
84
  delete_user_option ($user_id, "s2member_auto_eot_time");
85
  delete_user_option ($user_id, "s2member_notes");
97
  if (($url = preg_replace ("/%%user_email%%/i", ws_plugin__s2member_esc_ds (urlencode ($user->user_email)), $url)))
98
  if (($url = preg_replace ("/%%user_login%%/i", ws_plugin__s2member_esc_ds (urlencode ($user->user_login)), $url)))
99
  if (($url = preg_replace ("/%%user_id%%/i", ws_plugin__s2member_esc_ds (urlencode ($user_id)), $url)))
100
+ {
101
+ if (is_array ($fields) && !empty ($fields))
102
+ foreach ($fields as $var => $val) /* Custom Registration Fields. */
103
+ if (! ($url = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", ws_plugin__s2member_esc_ds (urlencode (maybe_serialize ($val))), $url)))
104
+ break;
105
+ /**/
106
+ if (($url = trim (preg_replace ("/%%(.+?)%%/i", "", $url))))
107
+ ws_plugin__s2member_remote ($url);
108
+ }
109
  }
110
  /**/
111
  if (is_object ($user = new WP_User ($user_id)) && $user->ID && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["eot_del_notification_recipients"] && is_array ($cv = preg_split ("/\|/", $custom)))
112
  {
113
  $msg = $sbj = "( s2Member / API Notification Email ) - EOT/Deletion";
114
  $msg .= "\n\n"; /* Spacing in the message body. */
115
+ /**/
116
  $msg .= "subscr_id: %%subscr_id%%\n";
117
  $msg .= "user_first_name: %%user_first_name%%\n";
118
  $msg .= "user_last_name: %%user_last_name%%\n";
120
  $msg .= "user_email: %%user_email%%\n";
121
  $msg .= "user_login: %%user_login%%\n";
122
  $msg .= "user_id: %%user_id%%\n";
123
+ /**/
124
+ if (is_array ($fields) && !empty ($fields))
125
+ foreach ($fields as $var => $val)
126
+ $msg .= $var . ": %%" . $var . "%%\n";
127
+ /**/
128
  $msg .= "cv0: %%cv0%%\n";
129
  $msg .= "cv1: %%cv1%%\n";
130
  $msg .= "cv2: %%cv2%%\n";
142
  if (($msg = preg_replace ("/%%user_email%%/i", ws_plugin__s2member_esc_ds ($user->user_email), $msg)))
143
  if (($msg = preg_replace ("/%%user_login%%/i", ws_plugin__s2member_esc_ds ($user->user_login), $msg)))
144
  if (($msg = preg_replace ("/%%user_id%%/i", ws_plugin__s2member_esc_ds ($user_id), $msg)))
145
+ {
146
+ if (is_array ($fields) && !empty ($fields))
147
+ foreach ($fields as $var => $val) /* Custom Registration Fields. */
148
+ if (! ($msg = preg_replace ("/%%" . preg_quote ($var, "/") . "%%/i", ws_plugin__s2member_esc_ds (maybe_serialize ($val)), $msg)))
149
+ break;
150
  /**/
151
+ if (($msg = trim (preg_replace ("/%%(.+?)%%/i", "", $msg))))
152
+ foreach (ws_plugin__s2member_trim_deep (preg_split ("/;+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["eot_del_notification_recipients"])) as $recipient)
153
+ ($recipient) ? wp_mail ($recipient, apply_filters ("ws_plugin__s2member_eot_del_notification_email_sbj", $sbj, get_defined_vars ()), apply_filters ("ws_plugin__s2member_eot_del_notification_email_msg", $msg, get_defined_vars ()), "From: \"" . preg_replace ('/"/', "'", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . "\" <" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"] . ">\r\nContent-Type: text/plain; charset=utf-8") : null;
154
+ }
155
  }
156
  /**/
157
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
includes/functions/users-list.inc.php CHANGED
@@ -25,7 +25,8 @@ if (!function_exists ("ws_plugin__s2member_users_list_cols"))
25
  do_action ("ws_plugin__s2member_before_users_list_cols", get_defined_vars ());
26
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
27
  /**/
28
- $cols["s2member_registration_time"] = "Registered On"; /* Date they signed up. */
 
29
  $cols["s2member_subscr_id"] = "Paid Subscr. ID"; /* Special field that is always applied. */
30
  /**/
31
  if (!is_multisite () || !ws_plugin__s2member_is_multisite_farm () || is_main_site ())
@@ -66,7 +67,20 @@ if (!function_exists ("ws_plugin__s2member_users_list_display_cols"))
66
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
67
  /**/
68
  if ($col === "s2member_registration_time")
69
- $val = ($v = $user->user_registered) ? date ("D M j, Y", strtotime ($v)) . '<br />@exactly ' . date ("g:i a", strtotime ($v)) : "—";
 
 
 
 
 
 
 
 
 
 
 
 
 
70
  /**/
71
  else if ($col === "s2member_subscr_id")
72
  $val = ($v = get_user_option ("s2member_subscr_id", $user_id)) ? esc_html ($v) : "—";
@@ -101,6 +115,42 @@ if (!function_exists ("ws_plugin__s2member_users_list_display_cols"))
101
  }
102
  }
103
  /*
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
  Function adds Custom Fields to the admin profile editing page.
105
 
106
  Attach to: add_action("edit_user_profile");
@@ -125,10 +175,10 @@ if (!function_exists ("ws_plugin__s2member_users_list_edit_cols"))
125
  /**/
126
  if ($user && $user->ID && $current_user && $current_user->ID) /* Validate both of these User objects beforehand. */
127
  {
 
 
128
  if (current_user_can ("edit_users") && (!is_multisite () || is_super_admin () || is_user_member_of_blog ($user->ID)))
129
  {
130
- $level = ws_plugin__s2member_user_access_level ($user); /* This User's Access Level for s2Member. */
131
- /**/
132
  echo '<div style="margin:25px 0 25px 0; height:1px; line-height:1px; background:#CCCCCC;"></div>' . "\n";
133
  /**/
134
  echo '<h3 style="position:relative;"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/large-icon.png" title="s2Member ( a Membership management system for WordPress® )" alt="" style="position:absolute; top:-15px; right:0; border:0;" />s2Member Configuration &amp; Profile Fields' . ( (is_multisite ()) ? ' ( for this Blog )' : '') . '</h3>' . "\n";
@@ -318,7 +368,7 @@ if (!function_exists ("ws_plugin__s2member_users_list_edit_cols"))
318
  else if ($current_user->ID === $user->ID) /* Otherwise, a User can always edit their own Profile. */
319
  {
320
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"]) /* Only if configured. */
321
- if ($fields_applicable = ws_plugin__s2member_custom_fields_configured_at_level ("auto-detection"))
322
  {
323
  echo '<div style="margin:25px 0 25px 0; height:1px; line-height:1px; background:#CCCCCC;"></div>' . "\n";
324
  /**/
@@ -414,6 +464,8 @@ if (!function_exists ("ws_plugin__s2member_users_list_update_cols"))
414
  /**/
415
  if ($user && $user->ID && $current_user && $current_user->ID) /* Validate both of these User objects before we even begin. */
416
  {
 
 
417
  if (current_user_can ("edit_users") && (!is_multisite () || is_super_admin () || is_user_member_of_blog ($user->ID)))
418
  {
419
  if (is_array ($_POST = ws_plugin__s2member_trim_deep (stripslashes_deep ($_POST))) && !empty ($_POST))
@@ -434,9 +486,6 @@ if (!function_exists ("ws_plugin__s2member_users_list_update_cols"))
434
  if (isset ($_POST["ws_plugin__s2member_profile_s2member_auto_eot_time"])) /* Then check if set. */
435
  update_user_option ($user_id, "s2member_auto_eot_time", $auto_eot_time);
436
  /**/
437
- if ($_POST["ws_plugin__s2member_profile_opt_in"]) /* Process list servers for this User? */
438
- ws_plugin__s2member_process_list_servers (ws_plugin__s2member_user_access_level ($user), $user->user_email, $user->first_name, $user->last_name, "", true);
439
- /**/
440
  if (isset ($_POST["ws_plugin__s2member_profile_s2member_ccaps"]))
441
  {
442
  foreach ($user->allcaps as $cap => $cap_enabled)
@@ -461,6 +510,17 @@ if (!function_exists ("ws_plugin__s2member_users_list_update_cols"))
461
  /**/
462
  update_user_option ($user_id, "s2member_custom_fields", $fields);
463
  /**/
 
 
 
 
 
 
 
 
 
 
 
464
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
465
  do_action ("ws_plugin__s2member_during_users_list_update_cols", get_defined_vars ());
466
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
@@ -472,7 +532,7 @@ if (!function_exists ("ws_plugin__s2member_users_list_update_cols"))
472
  if (is_array ($_POST = ws_plugin__s2member_trim_deep (stripslashes_deep ($_POST))) && !empty ($_POST))
473
  {
474
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"])
475
- if ($fields_applicable = ws_plugin__s2member_custom_fields_configured_at_level ("auto-detection"))
476
  {
477
  $_existing_fields = get_user_option ("s2member_custom_fields", $user_id);
478
  /**/
@@ -505,6 +565,25 @@ if (!function_exists ("ws_plugin__s2member_users_list_update_cols"))
505
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
506
  do_action ("ws_plugin__s2member_after_users_list_update_cols", get_defined_vars ());
507
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
 
 
508
  }
509
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
510
  ?>
25
  do_action ("ws_plugin__s2member_before_users_list_cols", get_defined_vars ());
26
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
27
  /**/
28
+ $cols["s2member_registration_time"] = "Registration Date"; /* Date they signed up. */
29
+ $cols["s2member_paid_registration_times"] = "Paid Registr. Date"; /* Payment Times. */
30
  $cols["s2member_subscr_id"] = "Paid Subscr. ID"; /* Special field that is always applied. */
31
  /**/
32
  if (!is_multisite () || !ws_plugin__s2member_is_multisite_farm () || is_main_site ())
67
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
68
  /**/
69
  if ($col === "s2member_registration_time")
70
+ $val = ($v = $user->user_registered) ? date ("D M jS, Y", strtotime ($v)) . '<br /><small>@ precisely ' . date ("g:i a", strtotime ($v)) . '</small>' : "—";
71
+ /**/
72
+ else if ($col === "s2member_paid_registration_times")
73
+ {
74
+ $val = ""; /* Initialize $val before we begin. */
75
+ if (is_array ($v = get_user_option ("s2member_paid_registration_times", $user_id)))
76
+ foreach ($v as $level => $time) /* Go through each Paid Registration Time. */
77
+ {
78
+ if ($level === "level") /* First Payment Time, regardless of Level. */
79
+ $val .= (($val) ? "<br />" : "") . '<span title="' . esc_attr (date ("D M jS, Y", $time)) . ' @ precisely ' . esc_attr (date ("g:i a", $time)) . '">' . date ("D M jS, Y", $time) . '</span>';
80
+ else if (preg_match ("/^level([0-9]+)$/i", $level) && ($level = preg_replace ("/^level/", "", $level)))
81
+ $val .= (($val) ? "<br />" : "") . '<small><em>@Level ' . $level . ': <span title="' . esc_attr (date ("D M jS, Y", $time)) . ' @ precisely ' . esc_attr (date ("g:i a", $time)) . '">' . date ("D M jS, Y", $time) . '</span></em></small>';
82
+ }
83
+ }
84
  /**/
85
  else if ($col === "s2member_subscr_id")
86
  $val = ($v = get_user_option ("s2member_subscr_id", $user_id)) ? esc_html ($v) : "—";
115
  }
116
  }
117
  /*
118
+ Function that modifies the search query.
119
+ Affects searches performed in the list of Users.
120
+ Attach to: add_action("pre_user_search");
121
+ */
122
+ function ws_plugin__s2member_users_list_search (&$search = FALSE)
123
+ {
124
+ global $wpdb; /* Need this global object reference. */
125
+ /**/
126
+ eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
127
+ do_action ("ws_plugin__s2member_before_users_list_search", get_defined_vars ());
128
+ unset ($__refs, $__v); /* Unset defined __refs, __v. */
129
+ /**/
130
+ if ($search->search_term && ($s = "%" . esc_sql (like_escape ($search->search_term)) . "%")) /* Only when executing an actual search query. */
131
+ {
132
+ $search->query_from = " FROM `" . $wpdb->users . "` INNER JOIN `" . $wpdb->usermeta . "` ON `" . $wpdb->users . "`.`ID` = `" . $wpdb->usermeta . "`.`user_id`";
133
+ /**/
134
+ $search->query_where = " WHERE '1' = '1' AND (" . apply_filters ("ws_plugin__s2member_before_users_list_search_where_or_before", "", get_defined_vars ());
135
+ $search->query_where .= " (`" . $wpdb->usermeta . "`.`meta_key` = '" . $wpdb->prefix . "s2member_subscr_id' AND `" . $wpdb->usermeta . "`.`meta_value` LIKE '" . $s . "')";
136
+ $search->query_where .= " OR (`" . $wpdb->usermeta . "`.`meta_key` = '" . $wpdb->prefix . "s2member_custom' AND `" . $wpdb->usermeta . "`.`meta_value` LIKE '" . $s . "')";
137
+ $search->query_where .= " OR (`" . $wpdb->usermeta . "`.`meta_key` = '" . $wpdb->prefix . "s2member_custom_fields' AND `" . $wpdb->usermeta . "`.`meta_value` LIKE '" . $s . "')";
138
+ $search->query_where .= " OR `user_login` LIKE '" . $s . "' OR `user_nicename` LIKE '" . $s . "' OR `user_email` LIKE '" . $s . "' OR `user_url` LIKE '" . $s . "' OR `display_name` LIKE '" . $s . "'";
139
+ $search->query_where .= apply_filters ("ws_plugin__s2member_before_users_list_search_where_or_after", "", get_defined_vars ()) . ")"; /* Leaving room for additional searches here. */
140
+ $search->query_where .= " AND `" . $wpdb->users . "`.`ID` IN(SELECT DISTINCT(`user_id`) FROM `" . $wpdb->usermeta . "` WHERE `meta_key` = '" . $wpdb->prefix . "capabilities'" ./**/
141
+ (($search->role) ? " AND `meta_value` LIKE '%" . esc_sql (like_escape ($search->role)) . "%'" : "") . ")";
142
+ /**/
143
+ $search->query_from = apply_filters ("ws_plugin__s2member_before_users_list_search_from", $search->query_from, get_defined_vars ());
144
+ $search->query_where = apply_filters ("ws_plugin__s2member_before_users_list_search_where", $search->query_where, get_defined_vars ());
145
+ }
146
+ /**/
147
+ eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
148
+ do_action ("ws_plugin__s2member_after_users_list_search", get_defined_vars ());
149
+ unset ($__refs, $__v); /* Unset defined __refs, __v. */
150
+ /**/
151
+ return;
152
+ }
153
+ /*
154
  Function adds Custom Fields to the admin profile editing page.
155
 
156
  Attach to: add_action("edit_user_profile");
175
  /**/
176
  if ($user && $user->ID && $current_user && $current_user->ID) /* Validate both of these User objects beforehand. */
177
  {
178
+ $level = ws_plugin__s2member_user_access_level ($user); /* This User's Access Level for s2Member; needed below. */
179
+ /**/
180
  if (current_user_can ("edit_users") && (!is_multisite () || is_super_admin () || is_user_member_of_blog ($user->ID)))
181
  {
 
 
182
  echo '<div style="margin:25px 0 25px 0; height:1px; line-height:1px; background:#CCCCCC;"></div>' . "\n";
183
  /**/
184
  echo '<h3 style="position:relative;"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/large-icon.png" title="s2Member ( a Membership management system for WordPress® )" alt="" style="position:absolute; top:-15px; right:0; border:0;" />s2Member Configuration &amp; Profile Fields' . ( (is_multisite ()) ? ' ( for this Blog )' : '') . '</h3>' . "\n";
368
  else if ($current_user->ID === $user->ID) /* Otherwise, a User can always edit their own Profile. */
369
  {
370
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"]) /* Only if configured. */
371
+ if ($fields_applicable = ws_plugin__s2member_custom_fields_configured_at_level ($level))
372
  {
373
  echo '<div style="margin:25px 0 25px 0; height:1px; line-height:1px; background:#CCCCCC;"></div>' . "\n";
374
  /**/
464
  /**/
465
  if ($user && $user->ID && $current_user && $current_user->ID) /* Validate both of these User objects before we even begin. */
466
  {
467
+ $level = ws_plugin__s2member_user_access_level ($user); /* This User's Access Level for s2Member; needed below. */
468
+ /**/
469
  if (current_user_can ("edit_users") && (!is_multisite () || is_super_admin () || is_user_member_of_blog ($user->ID)))
470
  {
471
  if (is_array ($_POST = ws_plugin__s2member_trim_deep (stripslashes_deep ($_POST))) && !empty ($_POST))
486
  if (isset ($_POST["ws_plugin__s2member_profile_s2member_auto_eot_time"])) /* Then check if set. */
487
  update_user_option ($user_id, "s2member_auto_eot_time", $auto_eot_time);
488
  /**/
 
 
 
489
  if (isset ($_POST["ws_plugin__s2member_profile_s2member_ccaps"]))
490
  {
491
  foreach ($user->allcaps as $cap => $cap_enabled)
510
  /**/
511
  update_user_option ($user_id, "s2member_custom_fields", $fields);
512
  /**/
513
+ if ($level > 0) /* We ONLY process this if they are higher than Level#0. */
514
+ {
515
+ $pr_times = get_user_option ("s2member_paid_registration_times", $user_id);
516
+ $pr_times["level"] = (!$pr_times["level"]) ? time () : $pr_times["level"]; /* Preserve. */
517
+ $pr_times["level" . $level] = (!$pr_times["level" . $level]) ? time () : $pr_times["level" . $level];
518
+ update_user_option ($user_id, "s2member_paid_registration_times", $pr_times); /* Update now. */
519
+ }
520
+ /**/
521
+ if ($_POST["ws_plugin__s2member_profile_opt_in"]) /* Process list servers for this User? Only if current_user_can ("edit_users"). */
522
+ ws_plugin__s2member_process_list_servers (ws_plugin__s2member_user_access_role ($user), ws_plugin__s2member_user_access_level ($user), $user->user_email, $user->first_name, $user->last_name, "", true, $user_id);
523
+ /**/
524
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
525
  do_action ("ws_plugin__s2member_during_users_list_update_cols", get_defined_vars ());
526
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
532
  if (is_array ($_POST = ws_plugin__s2member_trim_deep (stripslashes_deep ($_POST))) && !empty ($_POST))
533
  {
534
  if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"])
535
+ if ($fields_applicable = ws_plugin__s2member_custom_fields_configured_at_level ($level))
536
  {
537
  $_existing_fields = get_user_option ("s2member_custom_fields", $user_id);
538
  /**/
565
  eval ('foreach(array_keys(get_defined_vars())as$__v)$__refs[$__v]=&$$__v;');
566
  do_action ("ws_plugin__s2member_after_users_list_update_cols", get_defined_vars ());
567
  unset ($__refs, $__v); /* Unset defined __refs, __v. */
568
+ /**/
569
+ return;
570
  }
571
  }
572
+ /*
573
+ Function that synchronizes Paid Registration Times with Role assignments.
574
+ Attach to: add_action("set_user_role");
575
+ */
576
+ function ws_plugin__s2member_synchronize_paid_reg_times ($user_id = FALSE, $role = FALSE)
577
+ {
578
+ if ($user_id && is_object ($user = new WP_User ($user_id)) && $user->ID)
579
+ if (($level = ws_plugin__s2member_user_access_level ($user)) > 0)
580
+ {
581
+ $pr_times = get_user_option ("s2member_paid_registration_times", $user_id);
582
+ $pr_times["level"] = (!$pr_times["level"]) ? time () : $pr_times["level"]; /* Preserve. */
583
+ $pr_times["level" . $level] = (!$pr_times["level" . $level]) ? time () : $pr_times["level" . $level];
584
+ update_user_option ($user_id, "s2member_paid_registration_times", $pr_times); /* Update now. */
585
+ }
586
+ /**/
587
+ return;
588
+ }
589
  ?>
includes/functions/utilities.inc.php CHANGED
@@ -645,7 +645,7 @@ if (!function_exists ("ws_plugin__s2member_form_whips_2_url"))
645
  {
646
  $name = trim ($input_name_m[7]);
647
  $value = trim (wp_specialchars_decode ($input_value_m[7], ENT_QUOTES));
648
- $value = (preg_match ("/^http(s)?\:\/\//i", $value)) ? rawurlencode ($value) : $value;
649
  $url = add_query_arg ($name, $value, $url);
650
  }
651
  }
645
  {
646
  $name = trim ($input_name_m[7]);
647
  $value = trim (wp_specialchars_decode ($input_value_m[7], ENT_QUOTES));
648
+ $value = (preg_match ("/^http(s)?\:\/\//i", $value)) ? rawurlencode ($value) : urlencode ($value);
649
  $url = add_query_arg ($name, $value, $url);
650
  }
651
  }
includes/hooks.inc.php CHANGED
@@ -35,10 +35,10 @@ add_action ("init", "ws_plugin__s2member_delete_signup_tracking_cookie");
35
  add_action ("init", "ws_plugin__s2member_delete_sp_tracking_cookie");
36
  add_action ("init", "ws_plugin__s2member_auto_eot_system_via_cron");
37
  /**/
38
- add_action ("template_redirect", "ws_plugin__s2member_profile");
39
- add_action ("template_redirect", "ws_plugin__s2member_membership_options_page");
40
- add_action ("template_redirect", "ws_plugin__s2member_check_force_ssl");
41
  add_action ("template_redirect", "ws_plugin__s2member_security_gate", 1);
 
 
42
  /**/
43
  add_filter ("widget_text", "do_shortcode"); /* Shortcodes in widgets. */
44
  /**/
@@ -66,6 +66,7 @@ add_action ("register_form", "ws_plugin__s2member_custom_registration_fields");
66
  add_action ("bp_before_registration_submit_buttons", "ws_plugin__s2member_opt_in_4bp");
67
  /**/
68
  add_filter ("add_signup_meta", "ws_plugin__s2member_ms_process_signup_meta");
 
69
  add_action ("signup_hidden_fields", "ws_plugin__s2member_ms_process_signup_hidden_fields");
70
  add_filter ("wpmu_signup_user_notification_email", "ws_plugin__s2member_ms_nice_email_roles", 11);
71
  add_action ("wpmu_activate_user", "ws_plugin__s2member_configure_user_on_ms_user_activation", 10, 3);
@@ -93,12 +94,14 @@ add_action ("admin_menu", "ws_plugin__s2member_add_admin_options");
93
  add_action ("admin_print_scripts", "ws_plugin__s2member_add_admin_scripts");
94
  add_action ("admin_print_styles", "ws_plugin__s2member_add_admin_styles");
95
  /**/
 
96
  add_filter ("manage_users_columns", "ws_plugin__s2member_users_list_cols");
97
  add_filter ("manage_users_custom_column", "ws_plugin__s2member_users_list_display_cols", 10, 3);
98
  add_action ("edit_user_profile", "ws_plugin__s2member_users_list_edit_cols");
99
  add_action ("show_user_profile", "ws_plugin__s2member_users_list_edit_cols");
100
  add_action ("edit_user_profile_update", "ws_plugin__s2member_users_list_update_cols");
101
  add_action ("personal_options_update", "ws_plugin__s2member_users_list_update_cols");
 
102
  add_filter ("show_password_fields", "ws_plugin__s2member_demo_hide_password_fields", 10, 2);
103
  /**/
104
  add_filter ("cron_schedules", "ws_plugin__s2member_extend_cron_schedules");
35
  add_action ("init", "ws_plugin__s2member_delete_sp_tracking_cookie");
36
  add_action ("init", "ws_plugin__s2member_auto_eot_system_via_cron");
37
  /**/
38
+ add_action ("template_redirect", "ws_plugin__s2member_check_force_ssl", 1);
 
 
39
  add_action ("template_redirect", "ws_plugin__s2member_security_gate", 1);
40
+ add_action ("template_redirect", "ws_plugin__s2member_membership_options_page");
41
+ add_action ("template_redirect", "ws_plugin__s2member_profile");
42
  /**/
43
  add_filter ("widget_text", "do_shortcode"); /* Shortcodes in widgets. */
44
  /**/
66
  add_action ("bp_before_registration_submit_buttons", "ws_plugin__s2member_opt_in_4bp");
67
  /**/
68
  add_filter ("add_signup_meta", "ws_plugin__s2member_ms_process_signup_meta");
69
+ add_filter ("bp_signup_usermeta", "ws_plugin__s2member_ms_process_signup_meta");
70
  add_action ("signup_hidden_fields", "ws_plugin__s2member_ms_process_signup_hidden_fields");
71
  add_filter ("wpmu_signup_user_notification_email", "ws_plugin__s2member_ms_nice_email_roles", 11);
72
  add_action ("wpmu_activate_user", "ws_plugin__s2member_configure_user_on_ms_user_activation", 10, 3);
94
  add_action ("admin_print_scripts", "ws_plugin__s2member_add_admin_scripts");
95
  add_action ("admin_print_styles", "ws_plugin__s2member_add_admin_styles");
96
  /**/
97
+ add_action ("pre_user_search", "ws_plugin__s2member_users_list_search");
98
  add_filter ("manage_users_columns", "ws_plugin__s2member_users_list_cols");
99
  add_filter ("manage_users_custom_column", "ws_plugin__s2member_users_list_display_cols", 10, 3);
100
  add_action ("edit_user_profile", "ws_plugin__s2member_users_list_edit_cols");
101
  add_action ("show_user_profile", "ws_plugin__s2member_users_list_edit_cols");
102
  add_action ("edit_user_profile_update", "ws_plugin__s2member_users_list_update_cols");
103
  add_action ("personal_options_update", "ws_plugin__s2member_users_list_update_cols");
104
+ add_action ("set_user_role", "ws_plugin__s2member_synchronize_paid_reg_times", 10, 2);
105
  add_filter ("show_password_fields", "ws_plugin__s2member_demo_hide_password_fields", 10, 2);
106
  /**/
107
  add_filter ("cron_schedules", "ws_plugin__s2member_extend_cron_schedules");
includes/menu-pages/api-ops.inc.php CHANGED
@@ -42,7 +42,7 @@ if (apply_filters ("ws_plugin__s2member_during_api_ops_page_during_left_sections
42
  /**/
43
  echo '<div class="ws-menu-page-section ws-plugin--s2member-signup-notifications-section">' . "\n";
44
  echo '<h3>Signup Notification URLs ( optional )</h3>' . "\n";
45
- echo '<p>If you use affiliate software, or have back-office routines that need to be notified whenever a new Subscription is created, you\'ll want to read this section. This is marked `Signup`, because the URLs that you list below, will be notified each time a Member signs up. Depending on your fee structure, this may include a first initial payment that establishes their Subscription. This Notification will only be triggered once for each Member. Signup Notifications are sent right after a Member signs up successfully through PayPal®, regardless of whether any money has actually been received. In other words, this Notification is triggered anytime a Member signs up, even if you provided them with a free trial. Please note, this feature is not to be confused with the PayPal® IPN service. PayPal® IPN integration is already built into s2Member, and it remains active at all times. These Signup Notifications are an added layer of functionality, and they are completely optional.</p>' . "\n";
46
  do_action ("ws_plugin__s2member_during_api_ops_page_during_left_sections_during_signup_notifications", get_defined_vars ());
47
  /**/
48
  echo '<table class="form-table">' . "\n";
@@ -61,21 +61,21 @@ if (apply_filters ("ws_plugin__s2member_during_api_ops_page_during_left_sections
61
  echo '<td>' . "\n";
62
  echo 'You can input multiple Notification URLs by inserting one per line.<br />' . "\n";
63
  echo '<textarea name="ws_plugin__s2member_signup_notification_urls" id="ws-plugin--s2member-signup-notification-urls" rows="3" wrap="off">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["signup_notification_urls"]) . '</textarea><br />' . "\n";
64
- echo 'Signup Notifications take place silently behind-the-scene, using an HTTP connection. Each URL will be notified every time a new user signs up successfully through PayPal.<br /><br />' . "\n";
65
  echo '<strong>You can also use these special Replacement Codes if you need them:</strong>' . "\n";
66
  echo '<ul>' . "\n";
67
- echo '<li><code>%%subscr_id%%</code> = The PayPal® Subscription ID, which remains constant throughout any &amp; all future payments. [ <a href="#" onclick="alert(\'There is one exception. If you are selling Lifetime or Fixed-Term ( non-recurring ) access, using Buy Now functionality; the %%subscr_id%% is actually set to the Transaction ID for the purchase.\\n\\nPayPal® does not provide a specific Subscription ID for Buy Now purchases. Since Lifetime &amp; Fixed-Term Subscriptions are NOT recurring ( i.e. there is only ONE payment ), using the Transaction ID as the Subscription ID is a graceful way to deal with this minor conflict.\'); return false;">?</a> ]</li>' . "\n";
68
- echo '<li><code>%%initial%%</code> = The Initial Fee charged during signup. If you offered a free trial, this will be <code>0</code>. [ <a href="#" onclick="alert(\'This will always represent the amount of money the Customer spent, whenever they initially signed up, no matter what. Even if that amount is 0.\\n\\nIf a Customer signs up, under the terms of a free trial period, this will be 0. So be careful using %%initial%% when you offer a free trial period, because a $0.00 sale amount could cause havoc with affiliate programs.\\n\\nIf you\\\'re offering a free trial period, and you need to track sales through affiliate programs, you can either hard-code an amount; or use `Payment Notifications` instead.\'); return false;">?</a> ]</li>' . "\n";
69
- echo '<li><code>%%regular%%</code> = The Regular Amount of the Subscription. This value is <code>always > 0</code>, no matter what. [ <a href="#" onclick="alert(\'This is how much the Subscription costs after an initial period expires. The %%regular%% rate is always > 0. If you did not offer an initial period, %%initial%% and %%regular%% will be equal to the same thing.\'); return false;">?</a> ]</li>' . "\n";
70
- echo '<li><code>%%recurring%%</code> = This is the amount that will be charged on a Recurring basis, or <code>0</code> if non-Recurring. [ <a href="#" onclick="alert(\'If recurring payments have not been required, this will be equal to 0. That being said, %%regular%% &amp; %%recurring%% are usually the same value. This variable can be used in two different ways. You can use it to determine what the regular recurring rate is, or to determine whether the Subscription will recur or not. If it is going to recur, %%recurring%% will be > 0.\'); return false;">?</a> ]</li>' . "\n";
71
  echo '<li><code>%%first_name%%</code> = The First Name of the Customer who purchased the Membership Subscription.</li>' . "\n";
72
  echo '<li><code>%%last_name%%</code> = The Last Name of the Customer who purchased the Membership Subscription.</li>' . "\n";
73
  echo '<li><code>%%full_name%%</code> = The Full Name ( First &amp; Last ) of the Customer who purchased the Membership Subscription.</li>' . "\n";
74
  echo '<li><code>%%payer_email%%</code> = The Email Address of the Customer who purchased the Membership Subscription.</li>' . "\n";
75
  echo '<li><code>%%item_number%%</code> = The Item Number ( colon separated <code><em>level:custom_capabilities:fixed term</em></code> ) for the Membership Subscription.</li>' . "\n";
76
  echo '<li><code>%%item_name%%</code> = The Item Name ( as provided by the <code>desc=""</code> attribute in your Shortcode, which briefly describes the Item Number ).</li>' . "\n";
77
- echo '<li><code>%%initial_term%%</code> = This is the term length of the initial period. This will be a numeric value, followed by a space, then a single letter. [ <a href="#" onclick="alert(\'Here are some examples:\\n\\n%%initial_term%% = 1 D ( this means 1 Day )\\n%%initial_term%% = 1 W ( this means 1 Week )\\n%%initial_term%% = 1 M ( this means 1 Month )\\n%%initial_term%% = 1 Y ( this means 1 Year )\\n\\nThe initial period never recurs, so this only lasts for the term length specified, then it is over. If no initial period was even offered, the value of %%initial_term%% will just be: 0 D, meaning zero days.\'); return false;">?</a> ]</li>' . "\n";
78
- echo '<li><code>%%regular_term%%</code> = This is the term length of the regular period. This will be a numeric value, followed by a space, then a single letter. [ <a href="#" onclick="alert(\'Here are some examples:\\n\\n%%regular_term%% = 1 D ( this means 1 Day )\\n%%regular_term%% = 1 W ( this means 1 Week )\\n%%regular_term%% = 1 M ( this means 1 Month )\\n%%regular_term%% = 1 Y ( this means 1 Year )\\n%%regular_term%% = 1 L ( this means 1 Lifetime )\\n\\nThe regular term is usually recurring. So the regular term value represents the period ( or duration ) of each recurring period. If %%recurring%% = 0, then the regular term only applies once, because it is not recurring. So if it is not recurring, the value of %%regular_term%% simply represents how long their Membership privileges are going to last after the %%initial_term%% has expired, if there was an initial term. The value of this variable ( %%regular_term%% ) will never be empty, it will always be at least: 1 D, meaning 1 day. No exceptions.\'); return false;">?</a> ]</li>' . "\n";
79
  echo '</ul>' . "\n";
80
  /**/
81
  if (!is_multisite () || !ws_plugin__s2member_is_multisite_farm () || is_main_site ())
@@ -133,7 +133,7 @@ if (apply_filters ("ws_plugin__s2member_during_api_ops_page_during_left_sections
133
  /**/
134
  echo '<div class="ws-menu-page-section ws-plugin--s2member-registration-notifications-section">' . "\n";
135
  echo '<h3>Registration Notification URLs ( optional )</h3>' . "\n";
136
- echo '<p>If you use affiliate software, or have back-office routines that need to be notified whenever a new Member is created, you\'ll want to read this section. This is marked `Registration`, because the URLs that you list below, will be notified each time a Member registers a Username. This is usually triggered right after a `Signup` Notification; at the point in which a new Member successfully completes the Registration form, and they are assigned a Username. However, this is ALSO triggered whenever you create a new User inside your WordPress® Dashboard. Please note, this feature is not to be confused with the PayPal® IPN service. PayPal® IPN integration is already built into s2Member, and it remains active at all times. These Registration Notifications are an added layer of functionality, and they are completely optional.</p>' . "\n";
137
  do_action ("ws_plugin__s2member_during_api_ops_page_during_left_sections_during_registration_notifications", get_defined_vars ());
138
  /**/
139
  echo '<table class="form-table">' . "\n";
@@ -152,7 +152,7 @@ if (apply_filters ("ws_plugin__s2member_during_api_ops_page_during_left_sections
152
  echo '<td>' . "\n";
153
  echo 'You can input multiple Notification URLs by inserting one per line.<br />' . "\n";
154
  echo '<textarea name="ws_plugin__s2member_registration_notification_urls" id="ws-plugin--s2member-registration-notification-urls" rows="3" wrap="off">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["registration_notification_urls"]) . '</textarea><br />' . "\n";
155
- echo 'Registration Notifications take place silently behind-the-scene, using an HTTP connection. Each URL will be notified every time a new user registers a Username.<br /><br />' . "\n";
156
  echo '<strong>You can also use these special Replacement Codes if you need them:</strong>' . "\n";
157
  echo '<ul>' . "\n";
158
  echo '<li><code>%%role%%</code> = The Role ID <code>( subscriber, s2member_level[1-4], administrator, editor, author, contributor )</code>.</li>' . "\n";
@@ -166,6 +166,14 @@ if (apply_filters ("ws_plugin__s2member_during_api_ops_page_during_left_sections
166
  echo '<li><code>%%user_id%%</code> = A unique WordPress® User ID generated during registration.</li>' . "\n";
167
  echo '</ul>' . "\n";
168
  /**/
 
 
 
 
 
 
 
 
169
  if (!is_multisite () || !ws_plugin__s2member_is_multisite_farm () || is_main_site ())
170
  {
171
  echo '<strong>Custom Replacement Codes can also be inserted using these instructions:</strong>' . "\n";
@@ -223,7 +231,7 @@ if (apply_filters ("ws_plugin__s2member_during_api_ops_page_during_left_sections
223
  /**/
224
  echo '<div class="ws-menu-page-section ws-plugin--s2member-payment-notifications-section">' . "\n";
225
  echo '<h3>Payment Notification URLs ( optional )</h3>' . "\n";
226
- echo '<p>If you use affiliate software, or have back-office routines that need to be notified whenever payment transactions take place, and/or for recurring payments, you\'ll want to read this section. This is marked `Payment`, because the URLs that you list below, will be notified each time an actual payment occurs. Depending on your fee structure, this may include a first initial payment that establishes a Subscription. But more importantly, this will be triggered on all future payments that are received for the lifetime of the Subscription. So unlike the `Signup` Notification, `Payment` Notifications take place whenever actual payments are received, instead of just once after signup is completed. If a payment is required during signup ( e.g. no free trial is being offered ), a Signup Notification will be triggered, and a Payment Notification will ALSO be triggered. In other words, a Payment Notification occurs anytime funds are received, no matter what. Please note, this feature is not to be confused with the PayPal® IPN service. PayPal® IPN integration is already built into s2Member, and it remains active at all times. These Payment Notifications are an added layer of functionality, and they are completely optional.</p>' . "\n";
227
  do_action ("ws_plugin__s2member_during_api_ops_page_during_left_sections_during_payment_notifications", get_defined_vars ());
228
  /**/
229
  echo '<table class="form-table">' . "\n";
@@ -242,11 +250,11 @@ if (apply_filters ("ws_plugin__s2member_during_api_ops_page_during_left_sections
242
  echo '<td>' . "\n";
243
  echo 'You can input multiple Notification URLs by inserting one per line.<br />' . "\n";
244
  echo '<textarea name="ws_plugin__s2member_payment_notification_urls" id="ws-plugin--s2member-payment-notification-urls" rows="3" wrap="off">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["payment_notification_urls"]) . '</textarea><br />' . "\n";
245
- echo 'Payment Notifications take place silently behind-the-scene, using an HTTP connection. Each URL will be notified every time an initial and/or recurring payment occurs.<br /><br />' . "\n";
246
  echo '<strong>You can also use these special Replacement Codes if you need them:</strong>' . "\n";
247
  echo '<ul>' . "\n";
248
- echo '<li><code>%%subscr_id%%</code> = The PayPal® Subscription ID, which remains constant throughout any &amp; all future payments. [ <a href="#" onclick="alert(\'There is one exception. If you are selling Lifetime or Fixed-Term ( non-recurring ) access, using Buy Now functionality; the %%subscr_id%% is actually set to the Transaction ID for the payment.\\n\\nPayPal® does not provide a specific Subscription ID for Buy Now purchases. Since Lifetime &amp; Fixed-Term Subscriptions are NOT recurring ( i.e. there is only ONE payment ), using the Transaction ID as the Subscription ID is a graceful way to deal with this minor conflict.\'); return false;">?</a> ]</li>' . "\n";
249
- echo '<li><code>%%txn_id%%</code> = The PayPal® unique Transaction ID, which is always unique for each payment received.</li>' . "\n";
250
  echo '<li><code>%%amount%%</code> = The Amount of the payment. Most affiliate programs calculate commissions from this.</li>' . "\n";
251
  echo '<li><code>%%first_name%%</code> = The First Name of the Customer who purchased the Membership Subscription.</li>' . "\n";
252
  echo '<li><code>%%last_name%%</code> = The Last Name of the Customer who purchased the Membership Subscription.</li>' . "\n";
@@ -254,8 +262,20 @@ if (apply_filters ("ws_plugin__s2member_during_api_ops_page_during_left_sections
254
  echo '<li><code>%%payer_email%%</code> = The Email Address of the Customer who purchased the Membership Subscription.</li>' . "\n";
255
  echo '<li><code>%%item_number%%</code> = The Item Number ( colon separated <code><em>level:custom_capabilities:fixed term</em></code> ) that the payment is for.</li>' . "\n";
256
  echo '<li><code>%%item_name%%</code> = The Item Name ( as provided by the <code>desc=""</code> attribute in your Shortcode, which briefly describes the Item Number ).</li>' . "\n";
257
- echo '<li><code>%%subscr_payment%%</code> = This will be ( <code>1</code> or <code>0</code> ). The value <code>1</code> = payment IS associated with a "Subscription", <code>0</code> = Buy Now.</li>' . "\n";
258
- echo '<li><code>%%subscr_payment_user_id%%</code> = A unique ID that references this account in the WordPress® database. This is ONLY available if <code>%%subscr_payment%%</code> = 1.</li>' . "\n";
 
 
 
 
 
 
 
 
 
 
 
 
259
  echo '</ul>' . "\n";
260
  /**/
261
  if (!is_multisite () || !ws_plugin__s2member_is_multisite_farm () || is_main_site ())
@@ -315,9 +335,9 @@ if (apply_filters ("ws_plugin__s2member_during_api_ops_page_during_left_sections
315
  /**/
316
  echo '<div class="ws-menu-page-section ws-plugin--s2member-cancellation-notifications-section">' . "\n";
317
  echo '<h3>Cancellation Notification URLs ( optional )</h3>' . "\n";
318
- echo '<p>If you use affiliate software, or have back-office routines that need to be notified whenever Subscriptions are cancelled through PayPal®, you\'ll want to read this section. This is marked `Cancellation`, because the URLs that you list below, will be notified each time a Subscription is cancelled. A Cancellation is triggered when you cancel a Customer\'s Subscription through PayPal®, or when a Customer cancels their own Subscription through PayPal®. Please note, this feature is not to be confused with the PayPal® IPN service. PayPal® IPN integration is already built into s2Member, and it remains active at all times. These Cancellation Notifications are an added layer of functionality, and they are completely optional.</p>' . "\n";
319
- echo '<p><em><strong>*Understanding Cancellations*</strong> It\'s important to realize that a Cancellation is not an EOT ( End Of Term ). All that happens during a Cancellation event, is that billing is stopped, and it\'s understood that the Customer is going to lose access, at some point in the future. This does NOT mean, that access will be revoked immediately. A separate EOT event will automatically handle a (demotion|deletion) later, at the appropriate time; which could be several days, or even a year after the Cancellation took place.</em></p>' . "\n";
320
- echo '<p><em><strong>*Some Hairy Details*</strong> There might be times whenever you notice that a Members\'s Subscription has been cancelled through PayPal®... but, s2Member continues allowing the User access to your site as a paid Member. Please don\'t be confused by this... in 99.9% of these cases, the reason for this is legitimate. s2Member will only remove the User\'s Membership privileges when PayPal® sends a <code>subscr_eot</code> notification via the IPN service, a refund occurs, a chargeback occurs, or when a cancellation occurs - which would later result in a delayed Auto-EOT by s2Member. s2Member will not process an EOT ( End Of Term ) until the User has completely used up the time they paid for. In other words, if a User signs up for a monthly Subscription on Jan 1st, and then cancels their Subscription on Jan 15th; technically, they should still be allowed to access the site for another 15 days, and then on Feb 1st, the time they paid for has completely elapsed. At that time, s2Member will remove their Membership privileges; by either demoting them to a Free Subscriber, or deleting their account from the system ( based on your configuration ). s2Member also calculates one extra day ( 24 hours ) into its equation, just to make sure access is not removed sooner than a Customer might expect.</em></p>' . "\n";
321
  do_action ("ws_plugin__s2member_during_api_ops_page_during_left_sections_during_cancellation_notifications", get_defined_vars ());
322
  /**/
323
  echo '<table class="form-table">' . "\n";
@@ -336,20 +356,28 @@ if (apply_filters ("ws_plugin__s2member_during_api_ops_page_during_left_sections
336
  echo '<td>' . "\n";
337
  echo 'You can input multiple Notification URLs by inserting one per line.<br />' . "\n";
338
  echo '<textarea name="ws_plugin__s2member_cancellation_notification_urls" id="ws-plugin--s2member-cancellation-notification-urls" rows="3" wrap="off">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["cancellation_notification_urls"]) . '</textarea><br />' . "\n";
339
- echo 'Cancellation Notifications take place silently behind-the-scene, using an HTTP connection. Each URL will be notified every time a Subscription is cancelled.<br /><br />' . "\n";
340
  echo '<strong>You can also use these special Replacement Codes if you need them:</strong>' . "\n";
341
  echo '<ul>' . "\n";
342
- echo '<li><code>%%subscr_id%%</code> = The PayPal® Subscription ID, which remained constant throughout the lifetime of the Membership. [ <a href="#" onclick="alert(\'There is one exception. If you are selling Lifetime or Fixed-Term ( non-recurring ) access, using Buy Now functionality; the %%subscr_id%% is actually set to the original Transaction ID for the purchase.\\n\\nPayPal® does not provide a specific Subscription ID for Buy Now purchases. Since Lifetime &amp; Fixed-Term Subscriptions are NOT recurring ( i.e. there was only ONE payment ), using the Transaction ID as the Subscription ID is a graceful way to deal with this minor conflict.\'); return false;">?</a> ]</li>' . "\n";
343
  echo '<li><code>%%item_number%%</code> = The Item Number ( colon separated <em>level:custom_capabilities:fixed term</em> ) that the Subscription was for.</li>' . "\n";
344
  echo '<li><code>%%item_name%%</code> = The Item Name ( as provided by the <code>desc=""</code> attribute in your Shortcode, which briefly describes the Item Number ).</li>' . "\n";
345
- echo '<li><code>%%user_first_name%%</code> = The First Name listed on their User account. This might be different than what is on file at PayPal®.</li>' . "\n";
346
- echo '<li><code>%%user_last_name%%</code> = The Last Name listed on their User account. This might be different than what is on file at PayPal®.</li>' . "\n";
347
- echo '<li><code>%%user_full_name%%</code> = The Full Name listed on their User account. This might be different than what is on file at PayPal®.</li>' . "\n";
348
- echo '<li><code>%%user_email%%</code> = The Email Address associated with their User account. This might be different than what is on file at PayPal®.</li>' . "\n";
349
  echo '<li><code>%%user_login%%</code> = The Username associated with their account. The Customer created this during registration.</li>' . "\n";
350
  echo '<li><code>%%user_id%%</code> = A unique WordPress® User ID that references this account in the WordPress® database.</li>' . "\n";
351
  echo '</ul>' . "\n";
352
  /**/
 
 
 
 
 
 
 
 
353
  if (!is_multisite () || !ws_plugin__s2member_is_multisite_farm () || is_main_site ())
354
  {
355
  echo '<strong>Custom Replacement Codes can also be inserted using these instructions:</strong>' . "\n";
@@ -407,9 +435,9 @@ if (apply_filters ("ws_plugin__s2member_during_api_ops_page_during_left_sections
407
  /**/
408
  echo '<div class="ws-menu-page-section ws-plugin--s2member-eot-deletion-notifications-section">' . "\n";
409
  echo '<h3>EOT/Deletion Notification URLs ( optional )</h3>' . "\n";
410
- echo '<p>If you use affiliate software, or have back-office routines that need to be notified whenever Subscriptions have ended ( and a Member is demoted to a Free Subscriber ), or when an account is deleted from the system, you\'ll want to read this section. This is marked `EOT/Deletion`, because the URLs that you list below, will be notified in both cases. EOT = End Of Term. An EOT is triggered <em>immediately</em> when you refund a Customer, when a Customer forces a chargeback to occur, or when a PayPal® Subscription ends naturally ( i.e. expires ), and the PayPal® IPN service sends s2Member a <code>subscr_eot</code> response. Delayed EOTs occur after a Cancellation, either as a result of you cancelling a Customer\'s Subscription, or a Customer cancelling their own Subscription through PayPal®. A Cancellation usually results in a delayed EOT, because a Cancellation does NOT always warrant an immediate action; there could still be time left on their Subscription.</p>' . "\n";
411
- echo '<p>Manual Deletions will trigger an immediate Notification. If you delete an account manually from within your WordPress® Dashboard, your URLs can be notified automatically through this system. So the two events are an EOT and/or a Manual Deletion. Please note, this feature is not to be confused with the PayPal® IPN service. PayPal® IPN integration is already built into s2Member, and it remains active at all times. These EOT/Deletion Notifications are an added layer of functionality, and they are completely optional.</p>' . "\n";
412
- echo '<p><em><strong>*Some Hairy Details*</strong> There might be times whenever you notice that a Members\'s Subscription has been cancelled through PayPal®... but, s2Member continues allowing the User access to your site as a paid Member. Please don\'t be confused by this... in 99.9% of these cases, the reason for this is legitimate. s2Member will only remove the User\'s Membership privileges when PayPal® sends a <code>subscr_eot</code> notification via the IPN service, a refund occurs, a chargeback occurs, or when a cancellation occurs - which would later result in a delayed Auto-EOT by s2Member. s2Member will not process an EOT until the User has completely used up the time they paid for. In other words, if a User signs up for a monthly Subscription on Jan 1st, and then cancels their Subscription on Jan 15th; technically, they should still be allowed to access the site for another 15 days, and then on Feb 1st, the time they paid for has completely elapsed. At that time, s2Member will remove their Membership privileges; by either demoting them to a Free Subscriber, or deleting their account from the system ( based on your configuration ). s2Member also calculates one extra day ( 24 hours ) into its equation, just to make sure access is not removed sooner than a Customer might expect.</em></p>' . "\n";
413
  do_action ("ws_plugin__s2member_during_api_ops_page_during_left_sections_during_eot_deletion_notifications", get_defined_vars ());
414
  /**/
415
  echo '<table class="form-table">' . "\n";
@@ -428,18 +456,26 @@ if (apply_filters ("ws_plugin__s2member_during_api_ops_page_during_left_sections
428
  echo '<td>' . "\n";
429
  echo 'You can input multiple Notification URLs by inserting one per line.<br />' . "\n";
430
  echo '<textarea name="ws_plugin__s2member_eot_del_notification_urls" id="ws-plugin--s2member-eot-del-notification-urls" rows="3" wrap="off">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["eot_del_notification_urls"]) . '</textarea><br />' . "\n";
431
- echo 'EOT/Deletion Notifications take place silently behind-the-scene, using an HTTP connection. Each URL will be notified every time a Subscription hits an EOT, or is deleted.<br /><br />' . "\n";
432
  echo '<strong>You can also use these special Replacement Codes if you need them:</strong>' . "\n";
433
  echo '<ul>' . "\n";
434
- echo '<li><code>%%subscr_id%%</code> = The PayPal® Subscription ID, which remained constant throughout the lifetime of the Membership. [ <a href="#" onclick="alert(\'There is one exception. If you are selling Lifetime or Fixed-Term ( non-recurring ) access, using Buy Now functionality; the %%subscr_id%% is actually set to the original Transaction ID for the purchase.\\n\\nPayPal® does not provide a specific Subscription ID for Buy Now purchases. Since Lifetime &amp; Fixed-Term Subscriptions are NOT recurring ( i.e. there was only ONE payment ), using the Transaction ID as the Subscription ID is a graceful way to deal with this minor conflict.\'); return false;">?</a> ]</li>' . "\n";
435
- echo '<li><code>%%user_first_name%%</code> = The First Name listed on their User account. This might be different than what is on file at PayPal®.</li>' . "\n";
436
- echo '<li><code>%%user_last_name%%</code> = The Last Name listed on their User account. This might be different than what is on file at PayPal®.</li>' . "\n";
437
- echo '<li><code>%%user_full_name%%</code> = The Full Name listed on their User account. This might be different than what is on file at PayPal®.</li>' . "\n";
438
- echo '<li><code>%%user_email%%</code> = The Email Address associated with their User account. This might be different than what is on file at PayPal®.</li>' . "\n";
439
  echo '<li><code>%%user_login%%</code> = The Username associated with their account. The Customer created this during registration.</li>' . "\n";
440
  echo '<li><code>%%user_id%%</code> = A unique WordPress® User ID that references this account in the WordPress® database.</li>' . "\n";
441
  echo '</ul>' . "\n";
442
  /**/
 
 
 
 
 
 
 
 
443
  if (!is_multisite () || !ws_plugin__s2member_is_multisite_farm () || is_main_site ())
444
  {
445
  echo '<strong>Custom Replacement Codes can also be inserted using these instructions:</strong>' . "\n";
@@ -498,7 +534,7 @@ if (apply_filters ("ws_plugin__s2member_during_api_ops_page_during_left_sections
498
  echo '<div class="ws-menu-page-section ws-plugin--s2member-refund-reversal-notifications-section">' . "\n";
499
  echo '<h3>Refund/Reversal Notification URLs ( optional )</h3>' . "\n";
500
  echo '<p>If you use affiliate software, or have back-office routines that need to be notified whenever Subscriptions have been refunded or reversed ( i.e. charged back to you ), you\'ll want to read this section. This is marked `Refund/Reversal`, because the URLs that you list below, will ONLY be notified in those specific cases, as opposed to the EOT Notifications, which are all-inclusive. This is very similar to the EOT/Deletion described above. But, there is an important distinction. EOT includes cancellations, expirations, failed payments, refunds, chargebacks, etc, etc. In other words, ANY time a deletion or End Of Term action takes place.</p>' . "\n";
501
- echo '<p>So the distinction is that Refund/Reversal Notifications are ONLY sent under these specific circumstances: 1. You log into your PayPal® account and refund a payment that is associated with a Subscription. 2. The Customer complains to PayPal® and a chargeback occurs, forcing a Reversal. In both of these cases, an EOT/Deletion Notification will be sent ( as described above ), but since EOT is a more broad Notification, the Refund/Reversal Notification is here so you can nail down specific back-office operations in these two specific scenarios. Please note, this feature is not to be confused with the PayPal® IPN service. PayPal® IPN integration is already built into s2Member, and it remains active at all times. These Refund/Reversal Notifications are an added layer of functionality, and they are completely optional.</p>' . "\n";
502
  do_action ("ws_plugin__s2member_during_api_ops_page_during_left_sections_during_refund_reversal_notifications", get_defined_vars ());
503
  /**/
504
  echo '<table class="form-table">' . "\n";
@@ -517,13 +553,13 @@ if (apply_filters ("ws_plugin__s2member_during_api_ops_page_during_left_sections
517
  echo '<td>' . "\n";
518
  echo 'You can input multiple Notification URLs by inserting one per line.<br />' . "\n";
519
  echo '<textarea name="ws_plugin__s2member_ref_rev_notification_urls" id="ws-plugin--s2member-ref-rev-notification-urls" rows="3" wrap="off">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["ref_rev_notification_urls"]) . '</textarea><br />' . "\n";
520
- echo 'Refund/Reversal Notifications take place silently behind-the-scene, using an HTTP connection. Each URL will be notified every time a payment is refunded through PayPal® or a chargeback occurs.<br /><br />' . "\n";
521
  echo '<strong>You can also use these special Replacement Codes if you need them:</strong>' . "\n";
522
  echo '<ul>' . "\n";
523
- echo '<li><code>%%subscr_id%%</code> = The PayPal® Subscription ID, which remained constant throughout the lifetime of the Membership. [ <a href="#" onclick="alert(\'There is one exception. If you are selling Lifetime or Fixed-Term ( non-recurring ) access, using Buy Now functionality; the %%subscr_id%% is actually set to the original Transaction ID for the purchase.\\n\\nPayPal® does not provide a specific Subscription ID for Buy Now purchases. Since Lifetime &amp; Fixed-Term Subscriptions are NOT recurring ( i.e. there was only ONE payment ), using the Transaction ID as the Subscription ID is a graceful way to deal with this minor conflict.\'); return false;">?</a> ]</li>' . "\n";
524
- echo '<li><code>%%parent_txn_id%%</code> = The PayPal® Transaction ID, associated with the original payment that is being refunded/reversed.</li>' . "\n";
525
  echo '<li><code>%%-amount%%</code> = The Negative Amount of the payment, that was refunded or reversed back to the Customer.</li>' . "\n";
526
- echo '<li><code>%%-fee%%</code> = The Negative PayPal® fee, that was refunded back to you as the Merchant/Seller.</li>' . "\n";
527
  echo '<li><code>%%first_name%%</code> = The First Name of the Customer who purchased the Membership Subscription.</li>' . "\n";
528
  echo '<li><code>%%last_name%%</code> = The Last Name of the Customer who purchased the Membership Subscription.</li>' . "\n";
529
  echo '<li><code>%%full_name%%</code> = The Full Name ( First &amp; Last ) of the Customer who purchased the Membership Subscription.</li>' . "\n";
@@ -533,6 +569,14 @@ if (apply_filters ("ws_plugin__s2member_during_api_ops_page_during_left_sections
533
  echo '<li><code>%%user_id%%</code> = A unique WordPress® User ID that references this account in the WordPress® database.</li>' . "\n";
534
  echo '</ul>' . "\n";
535
  /**/
 
 
 
 
 
 
 
 
536
  if (!is_multisite () || !ws_plugin__s2member_is_multisite_farm () || is_main_site ())
537
  {
538
  echo '<strong>Custom Replacement Codes can also be inserted using these instructions:</strong>' . "\n";
@@ -590,7 +634,7 @@ if (apply_filters ("ws_plugin__s2member_during_api_ops_page_during_left_sections
590
  /**/
591
  echo '<div class="ws-menu-page-section ws-plugin--s2member-sp-sale-notifications-section">' . "\n";
592
  echo '<h3>Specific Post/Page ~ Sale Notification URLs ( optional )</h3>' . "\n";
593
- echo '<p>If you use affiliate software, or have back-office routines that need to be notified whenever Specific Post/Page sales take place, you\'ll want to read this section. This is marked `Specific Post/Page`, because the URLs that you list below, will be notified each time a payment occurs, on a sale providing access to a Specific Post/Page. This is one of only TWO Notifications that are sent for Specific Post/Page Access ( i.e. this one, and another below - for Refunds/Reversals ). All of the other API Notifications are designed for Membership Level Access. Please note, this feature is not to be confused with the PayPal® IPN service. PayPal® IPN integration is already built into s2Member, and it remains active at all times. These Sale Notifications are an added layer of functionality, and they are completely optional.</p>' . "\n";
594
  do_action ("ws_plugin__s2member_during_api_ops_page_during_left_sections_during_sp_sale_notifications", get_defined_vars ());
595
  /**/
596
  echo '<table class="form-table">' . "\n";
@@ -609,12 +653,12 @@ if (apply_filters ("ws_plugin__s2member_during_api_ops_page_during_left_sections
609
  echo '<td>' . "\n";
610
  echo 'You can input multiple Notification URLs by inserting one per line.<br />' . "\n";
611
  echo '<textarea name="ws_plugin__s2member_sp_sale_notification_urls" id="ws-plugin--s2member-sp-sale-notification-urls" rows="3" wrap="off">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sp_sale_notification_urls"]) . '</textarea><br />' . "\n";
612
- echo 'Specific Post/Page ~ Sale Notifications take place silently behind-the-scene, using an HTTP connection. Each URL will be notified every time a sale occurs.<br /><br />' . "\n";
613
  echo '<strong>You can also use these special Replacement Codes if you need them:</strong>' . "\n";
614
  echo '<ul>' . "\n";
615
  echo '<li><code>%%sp_access_url%%</code> = The full URL ( generated by s2Member ) where the Customer can gain access.</li>' . "\n";
616
  echo '<li><code>%%sp_access_exp%%</code> = Human readable expiration for <code>%%sp_access_url%%</code>. Ex: <em>( link expires in <code>%%sp_access_exp%%</code> )</em>.</li>' . "\n";
617
- echo '<li><code>%%txn_id%%</code> = The PayPal® Transaction ID. PayPal® assigns a unique identifier for every purchase.</li>' . "\n";
618
  echo '<li><code>%%amount%%</code> = The full Amount of the sale. Most affiliate programs calculate commissions from this.</li>' . "\n";
619
  echo '<li><code>%%first_name%%</code> = The First Name of the Customer who purchased Specific Post/Page Access.</li>' . "\n";
620
  echo '<li><code>%%last_name%%</code> = The Last Name of the Customer who purchased Specific Post/Page Access.</li>' . "\n";
@@ -681,7 +725,7 @@ if (apply_filters ("ws_plugin__s2member_during_api_ops_page_during_left_sections
681
  /**/
682
  echo '<div class="ws-menu-page-section ws-plugin--s2member-sp-refund-reversal-notifications-section">' . "\n";
683
  echo '<h3>Specific Post/Page ~ Refund/Reversal Notification URLs ( optional )</h3>' . "\n";
684
- echo '<p>If you use affiliate software, or have back-office routines that need to be notified whenever sales have been refunded or reversed ( i.e. charged back to you ), you\'ll want to read this section. This is marked `Specific Post/Page`, because the URLs that you list below, will be notified each time a Refund or Reversal occurs, on a sale that provided access to a Specific Post/Page. This is one of ONLY two Notifications that are sent for Specific Post/Page Access ( i.e. this one, and another above - for Sales ). All of the other API Notifications are designed for Membership Level Access. Please note, this feature is not to be confused with the PayPal® IPN service. PayPal® IPN integration is already built into s2Member, and it remains active at all times. These Refund/Reversal Notifications are an added layer of functionality, and they are completely optional.</p>' . "\n";
685
  do_action ("ws_plugin__s2member_during_api_ops_page_during_left_sections_during_sp_refund_reversal_notifications", get_defined_vars ());
686
  /**/
687
  echo '<table class="form-table">' . "\n";
@@ -700,12 +744,12 @@ if (apply_filters ("ws_plugin__s2member_during_api_ops_page_during_left_sections
700
  echo '<td>' . "\n";
701
  echo 'You can input multiple Notification URLs by inserting one per line.<br />' . "\n";
702
  echo '<textarea name="ws_plugin__s2member_sp_ref_rev_notification_urls" id="ws-plugin--s2member-sp-ref-rev-notification-urls" rows="3" wrap="off">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sp_ref_rev_notification_urls"]) . '</textarea><br />' . "\n";
703
- echo 'Specific Post/Page ~ Refund/Reversal Notifications take place silently behind-the-scene, using an HTTP connection. Each URL will be notified every time a payment is refunded through PayPal® or a chargeback occurs.<br /><br />' . "\n";
704
  echo '<strong>You can also use these special Replacement Codes if you need them:</strong>' . "\n";
705
  echo '<ul>' . "\n";
706
- echo '<li><code>%%parent_txn_id%%</code> = The PayPal® Transaction ID, associated with the original payment that is being refunded/reversed.</li>' . "\n";
707
  echo '<li><code>%%-amount%%</code> = The Negative Amount of the payment, that was refunded or reversed back to the Customer.</li>' . "\n";
708
- echo '<li><code>%%-fee%%</code> = The Negative PayPal® fee, that was refunded back to you as the Merchant/Seller.</li>' . "\n";
709
  echo '<li><code>%%first_name%%</code> = The First Name of the Customer who purchased access to a Specific Post/Page.</li>' . "\n";
710
  echo '<li><code>%%last_name%%</code> = The Last Name of the Customer who purchased access to a Specific Post/Page.</li>' . "\n";
711
  echo '<li><code>%%full_name%%</code> = The Full Name ( First &amp; Last ) of the Customer who purchased access to a Specific Post/Page.</li>' . "\n";
42
  /**/
43
  echo '<div class="ws-menu-page-section ws-plugin--s2member-signup-notifications-section">' . "\n";
44
  echo '<h3>Signup Notification URLs ( optional )</h3>' . "\n";
45
+ echo '<p>If you use affiliate software, or have back-office routines that need to be notified whenever a new Subscription is created, you\'ll want to read this section. This is marked `Signup`, because the URLs that you list below, will be notified each time a "paying" Member signs up. Depending on your fee structure, this may include a first Initial Payment that establishes their Subscription. This Notification will only be triggered once for each Member. Signup Notifications are sent right after a Member signs up successfully through your Payment Gateway, regardless of whether any money has actually been transacted initially. In other words, this Notification is triggered anytime a "paying" Member signs up, even if you provided them with a 100% Free Trial Period. However, this Notification will NOT be processed for Free Subscribers that register without going through your Payment Gateway at all. Please note, this feature is not to be confused with the PayPal® IPN service. PayPal® IPN ( and other service integrations ) are already built into s2Member. They remain active at all times. These Signup Notifications are an added layer of functionality, and they are completely optional.</p>' . "\n";
46
  do_action ("ws_plugin__s2member_during_api_ops_page_during_left_sections_during_signup_notifications", get_defined_vars ());
47
  /**/
48
  echo '<table class="form-table">' . "\n";
61
  echo '<td>' . "\n";
62
  echo 'You can input multiple Notification URLs by inserting one per line.<br />' . "\n";
63
  echo '<textarea name="ws_plugin__s2member_signup_notification_urls" id="ws-plugin--s2member-signup-notification-urls" rows="3" wrap="off">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["signup_notification_urls"]) . '</textarea><br />' . "\n";
64
+ echo 'Signup Notifications take place silently behind-the-scene, using an HTTP connection.<br /><br />' . "\n";
65
  echo '<strong>You can also use these special Replacement Codes if you need them:</strong>' . "\n";
66
  echo '<ul>' . "\n";
67
+ echo '<li><code>%%subscr_id%%</code> = The Paid Subscription ID, which remains constant throughout any &amp; all future payments. [ <a href="#" onclick="alert(\'There is one exception. If you are selling Lifetime or Fixed-Term ( non-recurring ) access, using Buy Now functionality; the %%subscr_id%% is actually set to the Transaction ID for the purchase.\\n\\nPayment Gateways do not provide a specific Subscription ID for Buy Now purchases. Since Lifetime &amp; Fixed-Term Subscriptions are NOT recurring ( i.e. there is only ONE payment ), using the Transaction ID as the Subscription ID is a graceful way to deal with this minor conflict.\'); return false;">?</a> ]</li>' . "\n";
68
+ echo '<li><code>%%initial%%</code> = The Initial Fee charged during signup. If you offered a 100% Free Trial, this will be <code>0</code>. [ <a href="#" onclick="alert(\'This will always represent the amount of money the Customer spent, whenever they initially signed up, no matter what. Even if that amount is 0.\\n\\nIf a Customer signs up, under the terms of a 100% Free Trial Period, this will be 0. So be careful using %%initial%% when you offer a 100% Free Trial Period, because a $0.00 sale amount could cause havoc with affiliate programs.\\n\\nIf you\\\'re offering a 100% Free Trial Period, and you need to track sales through affiliate programs, you can either hard-code an amount; or use `Payment Notifications` instead.\'); return false;">?</a> ]</li>' . "\n";
69
+ echo '<li><code>%%regular%%</code> = The Regular Amount of the Subscription. This value is <code>always > 0</code>, no matter what. [ <a href="#" onclick="alert(\'This is how much the Subscription costs after an Initial Period expires. The %%regular%% rate is always > 0. If you did NOT offer an Initial Period at a different price, %%initial%% and %%regular%% will be equal to the same thing.\'); return false;">?</a> ]</li>' . "\n";
70
+ echo '<li><code>%%recurring%%</code> = This is the amount that will be charged on a recurring basis, or <code>0</code> if non-recurring. [ <a href="#" onclick="alert(\'If Recurring Payments have not been required, this will be equal to 0. That being said, %%regular%% &amp; %%recurring%% are usually the same value. This variable can be used in two different ways. You can use it to determine what the Regular Recurring Rate is, or to determine whether the Subscription will recur or not. If it is going to recur, %%recurring%% will be > 0.\'); return false;">?</a> ]</li>' . "\n";
71
  echo '<li><code>%%first_name%%</code> = The First Name of the Customer who purchased the Membership Subscription.</li>' . "\n";
72
  echo '<li><code>%%last_name%%</code> = The Last Name of the Customer who purchased the Membership Subscription.</li>' . "\n";
73
  echo '<li><code>%%full_name%%</code> = The Full Name ( First &amp; Last ) of the Customer who purchased the Membership Subscription.</li>' . "\n";
74
  echo '<li><code>%%payer_email%%</code> = The Email Address of the Customer who purchased the Membership Subscription.</li>' . "\n";
75
  echo '<li><code>%%item_number%%</code> = The Item Number ( colon separated <code><em>level:custom_capabilities:fixed term</em></code> ) for the Membership Subscription.</li>' . "\n";
76
  echo '<li><code>%%item_name%%</code> = The Item Name ( as provided by the <code>desc=""</code> attribute in your Shortcode, which briefly describes the Item Number ).</li>' . "\n";
77
+ echo '<li><code>%%initial_term%%</code> = This is the term length of the Initial Period. This will be a numeric value, followed by a space, then a single letter. [ <a href="#" onclick="alert(\'Here are some examples:\\n\\n%%initial_term%% = 1 D ( this means 1 Day )\\n%%initial_term%% = 1 W ( this means 1 Week )\\n%%initial_term%% = 1 M ( this means 1 Month )\\n%%initial_term%% = 1 Y ( this means 1 Year )\\n\\nThe Initial Period never recurs, so this only lasts for the term length specified, then it is over.\'); return false;">?</a> ]</li>' . "\n";
78
+ echo '<li><code>%%regular_term%%</code> = This is the term length of the Regular Period. This will be a numeric value, followed by a space, then a single letter. [ <a href="#" onclick="alert(\'Here are some examples:\\n\\n%%regular_term%% = 1 D ( this means 1 Day )\\n%%regular_term%% = 1 W ( this means 1 Week )\\n%%regular_term%% = 1 M ( this means 1 Month )\\n%%regular_term%% = 1 Y ( this means 1 Year )\\n%%regular_term%% = 1 L ( this means 1 Lifetime )\\n\\nThe Regular Term is usually recurring. So the Regular Term value represents the period ( or duration ) of each recurring period. If %%recurring%% = 0, then the Regular Term only applies once, because it is not recurring. So if it is not recurring, the value of %%regular_term%% simply represents how long their Membership privileges are going to last after the %%initial_term%% has expired, if there was an Initial Term. The value of this variable ( %%regular_term%% ) will never be empty, it will always be at least: 1 D, meaning 1 day. No exceptions.\'); return false;">?</a> ]</li>' . "\n";
79
  echo '</ul>' . "\n";
80
  /**/
81
  if (!is_multisite () || !ws_plugin__s2member_is_multisite_farm () || is_main_site ())
133
  /**/
134
  echo '<div class="ws-menu-page-section ws-plugin--s2member-registration-notifications-section">' . "\n";
135
  echo '<h3>Registration Notification URLs ( optional )</h3>' . "\n";
136
+ echo '<p>If you use affiliate software, or have back-office routines that need to be notified whenever a new Member is created, you\'ll want to read this section. This is marked `Registration`, because the URLs that you list below, will be notified each time a Member registers a Username. This is usually triggered right after a `Signup` Notification; at the point in which a new Member successfully completes the Registration form, and they are assigned a Username. However, this is ALSO triggered whenever you create a new User inside your WordPress® Dashboard. Please note, this feature is not to be confused with the PayPal® IPN service. PayPal® IPN ( and other service integrations ) are already built into s2Member. They remain active at all times. These Registration Notifications are an added layer of functionality, and they are completely optional.</p>' . "\n";
137
  do_action ("ws_plugin__s2member_during_api_ops_page_during_left_sections_during_registration_notifications", get_defined_vars ());
138
  /**/
139
  echo '<table class="form-table">' . "\n";
152
  echo '<td>' . "\n";
153
  echo 'You can input multiple Notification URLs by inserting one per line.<br />' . "\n";
154
  echo '<textarea name="ws_plugin__s2member_registration_notification_urls" id="ws-plugin--s2member-registration-notification-urls" rows="3" wrap="off">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["registration_notification_urls"]) . '</textarea><br />' . "\n";
155
+ echo 'Registration Notifications take place silently behind-the-scene, using an HTTP connection.<br /><br />' . "\n";
156
  echo '<strong>You can also use these special Replacement Codes if you need them:</strong>' . "\n";
157
  echo '<ul>' . "\n";
158
  echo '<li><code>%%role%%</code> = The Role ID <code>( subscriber, s2member_level[1-4], administrator, editor, author, contributor )</code>.</li>' . "\n";
166
  echo '<li><code>%%user_id%%</code> = A unique WordPress® User ID generated during registration.</li>' . "\n";
167
  echo '</ul>' . "\n";
168
  /**/
169
+ echo '<strong>Custom Registration Fields are also supported in this notification:</strong>' . "\n";
170
+ echo '<ul>' . "\n";
171
+ echo '<li><code>%%date_of_birth%%</code> would be valid; if you have a Custom Registration Field with the ID <code>date_of_birth</code>.</li>' . "\n";
172
+ echo '<li><code>%%street_address%%</code> would be valid; if you have a Custom Registration Field with the ID <code>street_address</code>.</li>' . "\n";
173
+ echo '<li><code>%%country%%</code> would be valid; if you have a Custom Registration Field with the ID <code>country</code>.</li>' . "\n";
174
+ echo '<li><em><code>%%etc, etc...%%</code> <strong>see:</strong> s2Member -> General Options -> Custom Registration Fields</em>.</li>' . "\n";
175
+ echo '</ul>' . "\n";
176
+ /**/
177
  if (!is_multisite () || !ws_plugin__s2member_is_multisite_farm () || is_main_site ())
178
  {
179
  echo '<strong>Custom Replacement Codes can also be inserted using these instructions:</strong>' . "\n";
231
  /**/
232
  echo '<div class="ws-menu-page-section ws-plugin--s2member-payment-notifications-section">' . "\n";
233
  echo '<h3>Payment Notification URLs ( optional )</h3>' . "\n";
234
+ echo '<p>If you use affiliate software, or have back-office routines that need to be notified whenever payment transactions take place, and/or for Recurring Payments, you\'ll want to read this section. This is marked `Payment`, because the URLs that you list below, will be notified each time an actual payment occurs. Depending on your fee structure, this may include a first Initial Payment that establishes a Subscription. But more importantly, this will be triggered on all future payments that are received for the lifetime of the Subscription. So unlike the `Signup` Notification, `Payment` Notifications take place whenever actual payments are received, instead of just once after signup is completed. If a payment is required during signup ( e.g. no Free Trial is being offered ), a Signup Notification will be triggered, and a Payment Notification will ALSO be triggered. In other words, a Payment Notification occurs anytime funds are received, no matter what. Please note, this feature is not to be confused with the PayPal® IPN service. PayPal® IPN ( and other service integrations ) are already built into s2Member. They remain active at all times. These Payment Notifications are an added layer of functionality, and they are completely optional.</p>' . "\n";
235
  do_action ("ws_plugin__s2member_during_api_ops_page_during_left_sections_during_payment_notifications", get_defined_vars ());
236
  /**/
237
  echo '<table class="form-table">' . "\n";
250
  echo '<td>' . "\n";
251
  echo 'You can input multiple Notification URLs by inserting one per line.<br />' . "\n";
252
  echo '<textarea name="ws_plugin__s2member_payment_notification_urls" id="ws-plugin--s2member-payment-notification-urls" rows="3" wrap="off">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["payment_notification_urls"]) . '</textarea><br />' . "\n";
253
+ echo 'Payment Notifications take place silently behind-the-scene, using an HTTP connection.<br /><br />' . "\n";
254
  echo '<strong>You can also use these special Replacement Codes if you need them:</strong>' . "\n";
255
  echo '<ul>' . "\n";
256
+ echo '<li><code>%%subscr_id%%</code> = The Paid Subscription ID, which remains constant throughout any &amp; all future payments. [ <a href="#" onclick="alert(\'There is one exception. If you are selling Lifetime or Fixed-Term ( non-recurring ) access, using Buy Now functionality; the %%subscr_id%% is actually set to the Transaction ID for the payment.\\n\\nPayment Gateways do not provide a specific Subscription ID for Buy Now purchases. Since Lifetime &amp; Fixed-Term Subscriptions are NOT recurring ( i.e. there is only ONE payment ), using the Transaction ID as the Subscription ID is a graceful way to deal with this minor conflict.\'); return false;">?</a> ]</li>' . "\n";
257
+ echo '<li><code>%%txn_id%%</code> = The Payment Transaction ID, which is always unique for each payment received.</li>' . "\n";
258
  echo '<li><code>%%amount%%</code> = The Amount of the payment. Most affiliate programs calculate commissions from this.</li>' . "\n";
259
  echo '<li><code>%%first_name%%</code> = The First Name of the Customer who purchased the Membership Subscription.</li>' . "\n";
260
  echo '<li><code>%%last_name%%</code> = The Last Name of the Customer who purchased the Membership Subscription.</li>' . "\n";
262
  echo '<li><code>%%payer_email%%</code> = The Email Address of the Customer who purchased the Membership Subscription.</li>' . "\n";
263
  echo '<li><code>%%item_number%%</code> = The Item Number ( colon separated <code><em>level:custom_capabilities:fixed term</em></code> ) that the payment is for.</li>' . "\n";
264
  echo '<li><code>%%item_name%%</code> = The Item Name ( as provided by the <code>desc=""</code> attribute in your Shortcode, which briefly describes the Item Number ).</li>' . "\n";
265
+ echo '<li><code>%%user_first_name%%</code> = The First Name listed on their User account. This might be different than what is on file with your Payment Gateway.</li>' . "\n";
266
+ echo '<li><code>%%user_last_name%%</code> = The Last Name listed on their User account. This might be different than what is on file with your Payment Gateway.</li>' . "\n";
267
+ echo '<li><code>%%user_full_name%%</code> = The Full Name listed on their User account. This might be different than what is on file with your Payment Gateway.</li>' . "\n";
268
+ echo '<li><code>%%user_email%%</code> = The Email Address associated with their User account. This might be different than what is on file with your Payment Gateway.</li>' . "\n";
269
+ echo '<li><code>%%user_login%%</code> = The Username associated with their account. The Customer created this during registration.</li>' . "\n";
270
+ echo '<li><code>%%user_id%%</code> = A unique WordPress® User ID that references this account in the WordPress® database.</li>' . "\n";
271
+ echo '</ul>' . "\n";
272
+ /**/
273
+ echo '<strong>Custom Registration Fields are also supported in this notification:</strong>' . "\n";
274
+ echo '<ul>' . "\n";
275
+ echo '<li><code>%%date_of_birth%%</code> would be valid; if you have a Custom Registration Field with the ID <code>date_of_birth</code>.</li>' . "\n";
276
+ echo '<li><code>%%street_address%%</code> would be valid; if you have a Custom Registration Field with the ID <code>street_address</code>.</li>' . "\n";
277
+ echo '<li><code>%%country%%</code> would be valid; if you have a Custom Registration Field with the ID <code>country</code>.</li>' . "\n";
278
+ echo '<li><em><code>%%etc, etc...%%</code> <strong>see:</strong> s2Member -> General Options -> Custom Registration Fields</em>.</li>' . "\n";
279
  echo '</ul>' . "\n";
280
  /**/
281
  if (!is_multisite () || !ws_plugin__s2member_is_multisite_farm () || is_main_site ())
335
  /**/
336
  echo '<div class="ws-menu-page-section ws-plugin--s2member-cancellation-notifications-section">' . "\n";
337
  echo '<h3>Cancellation Notification URLs ( optional )</h3>' . "\n";
338
+ echo '<p>If you use affiliate software, or have back-office routines that need to be notified whenever Subscriptions are cancelled through your Payment Gateway, you\'ll want to read this section. This is marked `Cancellation`, because the URLs that you list below, will be notified each time a Subscription is cancelled. A Cancellation is triggered when you cancel a Customer\'s Subscription through your Payment Gateway, or when a Customer cancels their own Subscription. Please note, this feature is not to be confused with the PayPal® IPN service. PayPal® IPN ( and other service integrations ) are already built into s2Member. They remain active at all times. These Cancellation Notifications are an added layer of functionality, and they are completely optional.</p>' . "\n";
339
+ echo '<p><em><strong>*Understanding Cancellations*</strong> It\'s important to realize that a Cancellation is not an EOT ( End Of Term ). All that happens during a Cancellation event, is that billing is stopped, and it\'s understood that the Customer is going to lose access, at some point in the future. This does NOT mean, that access will be revoked immediately. A separate EOT event will automatically handle a (demotion or deletion) later, at the appropriate time; which could be several days, or even a year after the Cancellation took place.</em></p>' . "\n";
340
+ echo '<p><em><strong>*Some Hairy Details*</strong> There might be times whenever you notice that a Members\'s Subscription has been cancelled through your Payment Gateway... but, s2Member continues allowing the User access to your site as a paid Member. Please don\'t be confused by this... in 99.9% of these cases, the reason for this is legitimate. s2Member will only remove the User\'s Membership privileges when an EOT ( End Of Term ) is processed, a refund occurs, a chargeback occurs, or when a cancellation occurs - which would later result in a delayed Auto-EOT by s2Member. s2Member will not process an EOT ( End Of Term ) until the User has completely used up the time they paid for. In other words, if a User signs up for a monthly Subscription on Jan 1st, and then cancels their Subscription on Jan 15th; technically, they should still be allowed to access the site for another 15 days, and then on Feb 1st, the time they paid for has completely elapsed. At that time, s2Member will remove their Membership privileges; by either demoting them to a Free Subscriber, or deleting their account from the system ( based on your configuration ). s2Member also calculates one extra day ( 24 hours ) into its equation, just to make sure access is not removed sooner than a Customer might expect.</em></p>' . "\n";
341
  do_action ("ws_plugin__s2member_during_api_ops_page_during_left_sections_during_cancellation_notifications", get_defined_vars ());
342
  /**/
343
  echo '<table class="form-table">' . "\n";
356
  echo '<td>' . "\n";
357
  echo 'You can input multiple Notification URLs by inserting one per line.<br />' . "\n";
358
  echo '<textarea name="ws_plugin__s2member_cancellation_notification_urls" id="ws-plugin--s2member-cancellation-notification-urls" rows="3" wrap="off">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["cancellation_notification_urls"]) . '</textarea><br />' . "\n";
359
+ echo 'Cancellation Notifications take place silently behind-the-scene, using an HTTP connection.<br /><br />' . "\n";
360
  echo '<strong>You can also use these special Replacement Codes if you need them:</strong>' . "\n";
361
  echo '<ul>' . "\n";
362
+ echo '<li><code>%%subscr_id%%</code> = The Paid Subscription ID, which remained constant throughout the lifetime of the Membership. [ <a href="#" onclick="alert(\'There is one exception. If you are selling Lifetime or Fixed-Term ( non-recurring ) access, using Buy Now functionality; the %%subscr_id%% is actually set to the original Transaction ID for the purchase.\\n\\nPayment Gateways do not provide a specific Subscription ID for Buy Now purchases. Since Lifetime &amp; Fixed-Term Subscriptions are NOT recurring ( i.e. there was only ONE payment ), using the Transaction ID as the Subscription ID is a graceful way to deal with this minor conflict.\'); return false;">?</a> ]</li>' . "\n";
363
  echo '<li><code>%%item_number%%</code> = The Item Number ( colon separated <em>level:custom_capabilities:fixed term</em> ) that the Subscription was for.</li>' . "\n";
364
  echo '<li><code>%%item_name%%</code> = The Item Name ( as provided by the <code>desc=""</code> attribute in your Shortcode, which briefly describes the Item Number ).</li>' . "\n";
365
+ echo '<li><code>%%user_first_name%%</code> = The First Name listed on their User account. This might be different than what is on file with your Payment Gateway.</li>' . "\n";
366
+ echo '<li><code>%%user_last_name%%</code> = The Last Name listed on their User account. This might be different than what is on file with your Payment Gateway.</li>' . "\n";
367
+ echo '<li><code>%%user_full_name%%</code> = The Full Name listed on their User account. This might be different than what is on file with your Payment Gateway.</li>' . "\n";
368
+ echo '<li><code>%%user_email%%</code> = The Email Address associated with their User account. This might be different than what is on file with your Payment Gateway.</li>' . "\n";
369
  echo '<li><code>%%user_login%%</code> = The Username associated with their account. The Customer created this during registration.</li>' . "\n";
370
  echo '<li><code>%%user_id%%</code> = A unique WordPress® User ID that references this account in the WordPress® database.</li>' . "\n";
371
  echo '</ul>' . "\n";
372
  /**/
373
+ echo '<strong>Custom Registration Fields are also supported in this notification:</strong>' . "\n";
374
+ echo '<ul>' . "\n";
375
+ echo '<li><code>%%date_of_birth%%</code> would be valid; if you have a Custom Registration Field with the ID <code>date_of_birth</code>.</li>' . "\n";
376
+ echo '<li><code>%%street_address%%</code> would be valid; if you have a Custom Registration Field with the ID <code>street_address</code>.</li>' . "\n";
377
+ echo '<li><code>%%country%%</code> would be valid; if you have a Custom Registration Field with the ID <code>country</code>.</li>' . "\n";
378
+ echo '<li><em><code>%%etc, etc...%%</code> <strong>see:</strong> s2Member -> General Options -> Custom Registration Fields</em>.</li>' . "\n";
379
+ echo '</ul>' . "\n";
380
+ /**/
381
  if (!is_multisite () || !ws_plugin__s2member_is_multisite_farm () || is_main_site ())
382
  {
383
  echo '<strong>Custom Replacement Codes can also be inserted using these instructions:</strong>' . "\n";
435
  /**/
436
  echo '<div class="ws-menu-page-section ws-plugin--s2member-eot-deletion-notifications-section">' . "\n";
437
  echo '<h3>EOT/Deletion Notification URLs ( optional )</h3>' . "\n";
438
+ echo '<p>If you use affiliate software, or have back-office routines that need to be notified whenever Subscriptions have ended ( and a Member is demoted to a Free Subscriber ), or when an account is deleted from the system, you\'ll want to read this section. This is marked `EOT/Deletion`, because the URLs that you list below, will be notified in both cases. EOT = End Of Term. An EOT is triggered <em>immediately</em> when you refund a Customer, when a Customer forces a chargeback to occur, or when a paid Subscription ends naturally ( i.e. expires ), and your Payment Gateway sends s2Member an EOT ( End Of Term ) response. Delayed EOTs occur after a Cancellation, either as a result of you cancelling a Customer\'s Subscription, or a Customer cancelling their own Subscription. A Cancellation usually results in a delayed EOT, because a Cancellation does NOT always warrant an immediate action; there could still be time left on their Subscription.</p>' . "\n";
439
+ echo '<p>Manual Deletions will trigger an immediate Notification. If you delete an account manually from within your WordPress® Dashboard, your URLs can be notified automatically through this system. So the two events are an EOT and/or a Manual Deletion. Please note, this feature is not to be confused with the PayPal® IPN service. PayPal® IPN ( and other service integrations ) are already built into s2Member. They remain active at all times. These EOT/Deletion Notifications are an added layer of functionality, and they are completely optional.</p>' . "\n";
440
+ echo '<p><em><strong>*Some Hairy Details*</strong> There might be times whenever you notice that a Members\'s Subscription has been cancelled through your Payment Gateway... but, s2Member continues allowing the User access to your site as a paid Member. Please don\'t be confused by this... in 99.9% of these cases, the reason for this is legitimate. s2Member will only remove the User\'s Membership privileges when an EOT ( End Of Term ) is processed, a refund occurs, a chargeback occurs, or when a cancellation occurs - which would later result in a delayed Auto-EOT by s2Member. s2Member will not process an EOT ( End Of Term ) until the User has completely used up the time they paid for. In other words, if a User signs up for a monthly Subscription on Jan 1st, and then cancels their Subscription on Jan 15th; technically, they should still be allowed to access the site for another 15 days, and then on Feb 1st, the time they paid for has completely elapsed. At that time, s2Member will remove their Membership privileges; by either demoting them to a Free Subscriber, or deleting their account from the system ( based on your configuration ). s2Member also calculates one extra day ( 24 hours ) into its equation, just to make sure access is not removed sooner than a Customer might expect.</em></p>' . "\n";
441
  do_action ("ws_plugin__s2member_during_api_ops_page_during_left_sections_during_eot_deletion_notifications", get_defined_vars ());
442
  /**/
443
  echo '<table class="form-table">' . "\n";
456
  echo '<td>' . "\n";
457
  echo 'You can input multiple Notification URLs by inserting one per line.<br />' . "\n";
458
  echo '<textarea name="ws_plugin__s2member_eot_del_notification_urls" id="ws-plugin--s2member-eot-del-notification-urls" rows="3" wrap="off">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["eot_del_notification_urls"]) . '</textarea><br />' . "\n";
459
+ echo 'EOT/Deletion Notifications take place silently behind-the-scene, using an HTTP connection.<br /><br />' . "\n";
460
  echo '<strong>You can also use these special Replacement Codes if you need them:</strong>' . "\n";
461
  echo '<ul>' . "\n";
462
+ echo '<li><code>%%subscr_id%%</code> = The Paid Subscription ID, which remained constant throughout the lifetime of the Membership. [ <a href="#" onclick="alert(\'There is one exception. If you are selling Lifetime or Fixed-Term ( non-recurring ) access, using Buy Now functionality; the %%subscr_id%% is actually set to the original Transaction ID for the purchase.\\n\\nPayment Gateways do not provide a specific Subscription ID for Buy Now purchases. Since Lifetime &amp; Fixed-Term Subscriptions are NOT recurring ( i.e. there was only ONE payment ), using the Transaction ID as the Subscription ID is a graceful way to deal with this minor conflict.\'); return false;">?</a> ]</li>' . "\n";
463
+ echo '<li><code>%%user_first_name%%</code> = The First Name listed on their User account. This might be different than what is on file with your Payment Gateway.</li>' . "\n";
464
+ echo '<li><code>%%user_last_name%%</code> = The Last Name listed on their User account. This might be different than what is on file with your Payment Gateway.</li>' . "\n";
465
+ echo '<li><code>%%user_full_name%%</code> = The Full Name listed on their User account. This might be different than what is on file with your Payment Gateway.</li>' . "\n";
466
+ echo '<li><code>%%user_email%%</code> = The Email Address associated with their User account. This might be different than what is on file with your Payment Gateway.</li>' . "\n";
467
  echo '<li><code>%%user_login%%</code> = The Username associated with their account. The Customer created this during registration.</li>' . "\n";
468
  echo '<li><code>%%user_id%%</code> = A unique WordPress® User ID that references this account in the WordPress® database.</li>' . "\n";
469
  echo '</ul>' . "\n";
470
  /**/
471
+ echo '<strong>Custom Registration Fields are also supported in this notification:</strong>' . "\n";
472
+ echo '<ul>' . "\n";
473
+ echo '<li><code>%%date_of_birth%%</code> would be valid; if you have a Custom Registration Field with the ID <code>date_of_birth</code>.</li>' . "\n";
474
+ echo '<li><code>%%street_address%%</code> would be valid; if you have a Custom Registration Field with the ID <code>street_address</code>.</li>' . "\n";
475
+ echo '<li><code>%%country%%</code> would be valid; if you have a Custom Registration Field with the ID <code>country</code>.</li>' . "\n";
476
+ echo '<li><em><code>%%etc, etc...%%</code> <strong>see:</strong> s2Member -> General Options -> Custom Registration Fields</em>.</li>' . "\n";
477
+ echo '</ul>' . "\n";
478
+ /**/
479
  if (!is_multisite () || !ws_plugin__s2member_is_multisite_farm () || is_main_site ())
480
  {
481
  echo '<strong>Custom Replacement Codes can also be inserted using these instructions:</strong>' . "\n";
534
  echo '<div class="ws-menu-page-section ws-plugin--s2member-refund-reversal-notifications-section">' . "\n";
535
  echo '<h3>Refund/Reversal Notification URLs ( optional )</h3>' . "\n";
536
  echo '<p>If you use affiliate software, or have back-office routines that need to be notified whenever Subscriptions have been refunded or reversed ( i.e. charged back to you ), you\'ll want to read this section. This is marked `Refund/Reversal`, because the URLs that you list below, will ONLY be notified in those specific cases, as opposed to the EOT Notifications, which are all-inclusive. This is very similar to the EOT/Deletion described above. But, there is an important distinction. EOT includes cancellations, expirations, failed payments, refunds, chargebacks, etc, etc. In other words, ANY time a deletion or End Of Term action takes place.</p>' . "\n";
537
+ echo '<p>So the distinction is that Refund/Reversal Notifications are ONLY sent under these specific circumstances: 1. You log into your Payment Gateway and refund a payment that is associated with a Subscription. 2. The Customer complains to your Payment Gateway and a chargeback occurs, forcing a Reversal. In both of these cases, an EOT/Deletion Notification will be sent ( as described above ), but since EOT is a more broad Notification, the Refund/Reversal Notification is here so you can nail down specific back-office operations in these two specific scenarios. Please note, this feature is not to be confused with the PayPal® IPN service. PayPal® IPN ( and other service integrations ) are already built into s2Member. They remain active at all times. These Refund/Reversal Notifications are an added layer of functionality, and they are completely optional.</p>' . "\n";
538
  do_action ("ws_plugin__s2member_during_api_ops_page_during_left_sections_during_refund_reversal_notifications", get_defined_vars ());
539
  /**/
540
  echo '<table class="form-table">' . "\n";
553
  echo '<td>' . "\n";
554
  echo 'You can input multiple Notification URLs by inserting one per line.<br />' . "\n";
555
  echo '<textarea name="ws_plugin__s2member_ref_rev_notification_urls" id="ws-plugin--s2member-ref-rev-notification-urls" rows="3" wrap="off">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["ref_rev_notification_urls"]) . '</textarea><br />' . "\n";
556
+ echo 'Refund/Reversal Notifications take place silently behind-the-scene, using an HTTP connection.<br /><br />' . "\n";
557
  echo '<strong>You can also use these special Replacement Codes if you need them:</strong>' . "\n";
558
  echo '<ul>' . "\n";
559
+ echo '<li><code>%%subscr_id%%</code> = The Paid Subscription ID, which remained constant throughout the lifetime of the Membership. [ <a href="#" onclick="alert(\'There is one exception. If you are selling Lifetime or Fixed-Term ( non-recurring ) access, using Buy Now functionality; the %%subscr_id%% is actually set to the original Transaction ID for the purchase.\\n\\nPayment Gateways do not provide a specific Subscription ID for Buy Now purchases. Since Lifetime &amp; Fixed-Term Subscriptions are NOT recurring ( i.e. there was only ONE payment ), using the Transaction ID as the Subscription ID is a graceful way to deal with this minor conflict.\'); return false;">?</a> ]</li>' . "\n";
560
+ echo '<li><code>%%parent_txn_id%%</code> = The Parent Transaction ID, associated with the original payment being refunded/reversed.</li>' . "\n";
561
  echo '<li><code>%%-amount%%</code> = The Negative Amount of the payment, that was refunded or reversed back to the Customer.</li>' . "\n";
562
+ echo '<li><code>%%-fee%%</code> = The Negative Payment Gateway fee, that was refunded back to you as the Merchant/Seller.</li>' . "\n";
563
  echo '<li><code>%%first_name%%</code> = The First Name of the Customer who purchased the Membership Subscription.</li>' . "\n";
564
  echo '<li><code>%%last_name%%</code> = The Last Name of the Customer who purchased the Membership Subscription.</li>' . "\n";
565
  echo '<li><code>%%full_name%%</code> = The Full Name ( First &amp; Last ) of the Customer who purchased the Membership Subscription.</li>' . "\n";
569
  echo '<li><code>%%user_id%%</code> = A unique WordPress® User ID that references this account in the WordPress® database.</li>' . "\n";
570
  echo '</ul>' . "\n";
571
  /**/
572
+ echo '<strong>Custom Registration Fields are also supported in this notification:</strong>' . "\n";
573
+ echo '<ul>' . "\n";
574
+ echo '<li><code>%%date_of_birth%%</code> would be valid; if you have a Custom Registration Field with the ID <code>date_of_birth</code>.</li>' . "\n";
575
+ echo '<li><code>%%street_address%%</code> would be valid; if you have a Custom Registration Field with the ID <code>street_address</code>.</li>' . "\n";
576
+ echo '<li><code>%%country%%</code> would be valid; if you have a Custom Registration Field with the ID <code>country</code>.</li>' . "\n";
577
+ echo '<li><em><code>%%etc, etc...%%</code> <strong>see:</strong> s2Member -> General Options -> Custom Registration Fields</em>.</li>' . "\n";
578
+ echo '</ul>' . "\n";
579
+ /**/
580
  if (!is_multisite () || !ws_plugin__s2member_is_multisite_farm () || is_main_site ())
581
  {
582
  echo '<strong>Custom Replacement Codes can also be inserted using these instructions:</strong>' . "\n";
634
  /**/
635
  echo '<div class="ws-menu-page-section ws-plugin--s2member-sp-sale-notifications-section">' . "\n";
636
  echo '<h3>Specific Post/Page ~ Sale Notification URLs ( optional )</h3>' . "\n";
637
+ echo '<p>If you use affiliate software, or have back-office routines that need to be notified whenever Specific Post/Page sales take place, you\'ll want to read this section. This is marked `Specific Post/Page`, because the URLs that you list below, will be notified each time a payment occurs, on a sale providing access to a Specific Post/Page. This is one of only TWO Notifications that are sent for Specific Post/Page Access ( i.e. this one, and another below - for Refunds/Reversals ). All of the other API Notifications are designed for Membership Level Access. Please note, this feature is not to be confused with the PayPal® IPN service. PayPal® IPN ( and other service integrations ) are already built into s2Member. They remain active at all times. These Sale Notifications are an added layer of functionality, and they are completely optional.</p>' . "\n";
638
  do_action ("ws_plugin__s2member_during_api_ops_page_during_left_sections_during_sp_sale_notifications", get_defined_vars ());
639
  /**/
640
  echo '<table class="form-table">' . "\n";
653
  echo '<td>' . "\n";
654
  echo 'You can input multiple Notification URLs by inserting one per line.<br />' . "\n";
655
  echo '<textarea name="ws_plugin__s2member_sp_sale_notification_urls" id="ws-plugin--s2member-sp-sale-notification-urls" rows="3" wrap="off">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sp_sale_notification_urls"]) . '</textarea><br />' . "\n";
656
+ echo 'Specific Post/Page ~ Sale Notifications take place silently behind-the-scene, using an HTTP connection.<br /><br />' . "\n";
657
  echo '<strong>You can also use these special Replacement Codes if you need them:</strong>' . "\n";
658
  echo '<ul>' . "\n";
659
  echo '<li><code>%%sp_access_url%%</code> = The full URL ( generated by s2Member ) where the Customer can gain access.</li>' . "\n";
660
  echo '<li><code>%%sp_access_exp%%</code> = Human readable expiration for <code>%%sp_access_url%%</code>. Ex: <em>( link expires in <code>%%sp_access_exp%%</code> )</em>.</li>' . "\n";
661
+ echo '<li><code>%%txn_id%%</code> = The Paid Transaction ID. Payment Gateways assign a unique identifier for every purchase.</li>' . "\n";
662
  echo '<li><code>%%amount%%</code> = The full Amount of the sale. Most affiliate programs calculate commissions from this.</li>' . "\n";
663
  echo '<li><code>%%first_name%%</code> = The First Name of the Customer who purchased Specific Post/Page Access.</li>' . "\n";
664
  echo '<li><code>%%last_name%%</code> = The Last Name of the Customer who purchased Specific Post/Page Access.</li>' . "\n";
725
  /**/
726
  echo '<div class="ws-menu-page-section ws-plugin--s2member-sp-refund-reversal-notifications-section">' . "\n";
727
  echo '<h3>Specific Post/Page ~ Refund/Reversal Notification URLs ( optional )</h3>' . "\n";
728
+ echo '<p>If you use affiliate software, or have back-office routines that need to be notified whenever sales have been refunded or reversed ( i.e. charged back to you ), you\'ll want to read this section. This is marked `Specific Post/Page`, because the URLs that you list below, will be notified each time a Refund or Reversal occurs, on a sale that provided access to a Specific Post/Page. This is one of ONLY two Notifications that are sent for Specific Post/Page Access ( i.e. this one, and another above - for Sales ). All of the other API Notifications are designed for Membership Level Access. Please note, this feature is not to be confused with the PayPal® IPN service. PayPal® IPN ( and other service integrations ) are already built into s2Member. They remain active at all times. These Refund/Reversal Notifications are an added layer of functionality, and they are completely optional.</p>' . "\n";
729
  do_action ("ws_plugin__s2member_during_api_ops_page_during_left_sections_during_sp_refund_reversal_notifications", get_defined_vars ());
730
  /**/
731
  echo '<table class="form-table">' . "\n";
744
  echo '<td>' . "\n";
745
  echo 'You can input multiple Notification URLs by inserting one per line.<br />' . "\n";
746
  echo '<textarea name="ws_plugin__s2member_sp_ref_rev_notification_urls" id="ws-plugin--s2member-sp-ref-rev-notification-urls" rows="3" wrap="off">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sp_ref_rev_notification_urls"]) . '</textarea><br />' . "\n";
747
+ echo 'Specific Post/Page ~ Refund/Reversal Notifications take place silently behind-the-scene, using an HTTP connection.<br /><br />' . "\n";
748
  echo '<strong>You can also use these special Replacement Codes if you need them:</strong>' . "\n";
749
  echo '<ul>' . "\n";
750
+ echo '<li><code>%%parent_txn_id%%</code> = The Parent Transaction ID, associated with the original payment being refunded/reversed.</li>' . "\n";
751
  echo '<li><code>%%-amount%%</code> = The Negative Amount of the payment, that was refunded or reversed back to the Customer.</li>' . "\n";
752
+ echo '<li><code>%%-fee%%</code> = The Negative Payment Gateway fee, that was refunded back to you as the Merchant/Seller.</li>' . "\n";
753
  echo '<li><code>%%first_name%%</code> = The First Name of the Customer who purchased access to a Specific Post/Page.</li>' . "\n";
754
  echo '<li><code>%%last_name%%</code> = The Last Name of the Customer who purchased access to a Specific Post/Page.</li>' . "\n";
755
  echo '<li><code>%%full_name%%</code> = The Full Name ( First &amp; Last ) of the Customer who purchased access to a Specific Post/Page.</li>' . "\n";
includes/menu-pages/bridges.inc.php CHANGED
@@ -12,7 +12,7 @@ If not, see: <http://www.gnu.org/licenses/>.
12
  Direct access denial.
13
  */
14
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
15
- exit("Do not access this file directly.");
16
  /*
17
  API Scripting page.
18
  */
@@ -39,7 +39,7 @@ if (apply_filters ("ws_plugin__s2member_during_bridges_page_during_left_sections
39
  echo '<div class="ws-menu-page-section ws-plugin--s2member-bbpress-section">' . "\n";
40
  echo '<h3>bbPress® Bridge Integration ( install/uninstall )</h3>' . "\n";
41
  echo '<p>If you\'re running <a href="http://bbpress.org/" target="_blank" rel="external">bbPress® forums</a>, you can protect them with the s2Member plugin. BUT, you will need to install this Bridge/plugin first. This bbPress® Bridge/plugin will block all non-Member access to your forums. Only the bbPress® login-page will be available. Forum registration will be redirected to your Membership Options Page for s2Member ( on your main WordPress® installation ). This way, a visitor can signup on your site, and gain Membership Access to your forums.</p>' . "\n";
42
- echo '<p><em>* This Bridge/plugin will NOT work, until you\'ve successfully integrated WordPress® into bbPress®. For more information, log into your bbPress® Dashboard, and go to: <code>bbPress® -> Settings -> WordPress® Integration</code>. Once you have WordPress® integrated, come back here, and install the s2Member Bridge/plugin. * This Bridge Integration can also be installed manually. You\'ll find the bbPress® Bridge/plugin inside <code>/s2member/includes/dropins/bridges/_s2member-bbpress-bridge.php</code>. Pop that file into the `my-plugins/` directory for bbPress®.</em></p>' . "\n";
43
  do_action ("ws_plugin__s2member_during_bridges_page_during_left_sections_during_api_easy_way", get_defined_vars ());
44
  /**/
45
  echo '<table class="form-table">' . "\n";
@@ -64,12 +64,12 @@ if (apply_filters ("ws_plugin__s2member_during_bridges_page_during_left_sections
64
  /**/
65
  echo 'Minimum Level required for access to your bbPress® forums.<br />' . "\n";
66
  echo '<select name="ws_plugin__s2member_bridge_bbpress_min_level" id="ws-plugin--s2member-bbpress-min-level" style="width:99%;">' . "\n";
67
- echo '<option value=""' . ((!strlen ($_POST["ws_plugin__s2member_bridge_bbpress_min_level"])) ? ' selected="selected"' : '') . '></option>' . "\n";
68
- echo '<option value="0"' . (($_POST["ws_plugin__s2member_bridge_bbpress_min_level"] === "0") ? ' selected="selected"' : '') . '>s2Member Level 0</option>' . "\n";
69
- echo '<option value="1"' . (($_POST["ws_plugin__s2member_bridge_bbpress_min_level"] === "1") ? ' selected="selected"' : '') . '>s2Member Level 1</option>' . "\n";
70
- echo '<option value="2"' . (($_POST["ws_plugin__s2member_bridge_bbpress_min_level"] === "2") ? ' selected="selected"' : '') . '>s2Member Level 2</option>' . "\n";
71
- echo '<option value="3"' . (($_POST["ws_plugin__s2member_bridge_bbpress_min_level"] === "3") ? ' selected="selected"' : '') . '>s2Member Level 3</option>' . "\n";
72
- echo '<option value="4"' . (($_POST["ws_plugin__s2member_bridge_bbpress_min_level"] === "4") ? ' selected="selected"' : '') . '>s2Member Level 4</option>' . "\n";
73
  echo '</select><br /><br />' . "\n";
74
  /**/
75
  echo '<p class="submit"><input type="submit" name="ws_plugin__s2member_bridge_bbpress_action" class="button-primary" value="Install / Re-Install" /> &nbsp;&nbsp; <input type="submit" name="ws_plugin__s2member_bridge_bbpress_action" class="button-primary" value="Un-Install" /></p>' . "\n";
12
  Direct access denial.
13
  */
14
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
15
+ exit ("Do not access this file directly.");
16
  /*
17
  API Scripting page.
18
  */
39
  echo '<div class="ws-menu-page-section ws-plugin--s2member-bbpress-section">' . "\n";
40
  echo '<h3>bbPress® Bridge Integration ( install/uninstall )</h3>' . "\n";
41
  echo '<p>If you\'re running <a href="http://bbpress.org/" target="_blank" rel="external">bbPress® forums</a>, you can protect them with the s2Member plugin. BUT, you will need to install this Bridge/plugin first. This bbPress® Bridge/plugin will block all non-Member access to your forums. Only the bbPress® login-page will be available. Forum registration will be redirected to your Membership Options Page for s2Member ( on your main WordPress® installation ). This way, a visitor can signup on your site, and gain Membership Access to your forums.</p>' . "\n";
42
+ echo '<p><em>* This Bridge/plugin will NOT work, until you\'ve successfully integrated WordPress® into bbPress®. For more information, log into your bbPress® Dashboard, and go to: <code>bbPress® -> Settings -> WordPress® Integration</code>. Once you have WordPress® integrated ( <a href="http://wordpress.org/extend/plugins/bbpress-integration/" target="_blank" rel="external">install this plugin</a> ) and follow the instructions regarding your <code>/wp-config.php</code> file. Then, come back here, and install the s2Member Bridge/plugin. * This Bridge Integration could also be installed manually. You\'ll find the bbPress® Bridge/plugin inside <code>/s2member/includes/dropins/bridges/_s2member-bbpress-bridge.php</code>. Pop that file into the `my-plugins/` directory for bbPress®, or just click the Install button below; s2Member will do this part for you automatically.</em></p>' . "\n";
43
  do_action ("ws_plugin__s2member_during_bridges_page_during_left_sections_during_api_easy_way", get_defined_vars ());
44
  /**/
45
  echo '<table class="form-table">' . "\n";
64
  /**/
65
  echo 'Minimum Level required for access to your bbPress® forums.<br />' . "\n";
66
  echo '<select name="ws_plugin__s2member_bridge_bbpress_min_level" id="ws-plugin--s2member-bbpress-min-level" style="width:99%;">' . "\n";
67
+ echo '<option value=""' . ( (!strlen ($_POST["ws_plugin__s2member_bridge_bbpress_min_level"])) ? ' selected="selected"' : '') . '></option>' . "\n";
68
+ echo '<option value="0"' . ( ($_POST["ws_plugin__s2member_bridge_bbpress_min_level"] === "0") ? ' selected="selected"' : '') . '>s2Member Level 0</option>' . "\n";
69
+ echo '<option value="1"' . ( ($_POST["ws_plugin__s2member_bridge_bbpress_min_level"] === "1") ? ' selected="selected"' : '') . '>s2Member Level 1</option>' . "\n";
70
+ echo '<option value="2"' . ( ($_POST["ws_plugin__s2member_bridge_bbpress_min_level"] === "2") ? ' selected="selected"' : '') . '>s2Member Level 2</option>' . "\n";
71
+ echo '<option value="3"' . ( ($_POST["ws_plugin__s2member_bridge_bbpress_min_level"] === "3") ? ' selected="selected"' : '') . '>s2Member Level 3</option>' . "\n";
72
+ echo '<option value="4"' . ( ($_POST["ws_plugin__s2member_bridge_bbpress_min_level"] === "4") ? ' selected="selected"' : '') . '>s2Member Level 4</option>' . "\n";
73
  echo '</select><br /><br />' . "\n";
74
  /**/
75
  echo '<p class="submit"><input type="submit" name="ws_plugin__s2member_bridge_bbpress_action" class="button-primary" value="Install / Re-Install" /> &nbsp;&nbsp; <input type="submit" name="ws_plugin__s2member_bridge_bbpress_action" class="button-primary" value="Un-Install" /></p>' . "\n";
includes/menu-pages/code-samples/current-user-custom.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php echo S2MEMBER_CURRENT_USER_CUSTOM; ?>
2
  This may output something like: www.yourdomain.com|cv1|cv2|cv3
3
- ( this is the PayPal input field value for the `custom` variable )
4
 
5
  ---- s2member Shortcode Equivalent ----
6
 
1
  <?php echo S2MEMBER_CURRENT_USER_CUSTOM; ?>
2
  This may output something like: www.yourdomain.com|cv1|cv2|cv3
3
+ ( this is the input field value for the custom="" attribute in your Shortcode )
4
 
5
  ---- s2member Shortcode Equivalent ----
6
 
includes/menu-pages/code-samples/current-user-paid-registration-days-dripping.php ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if(S2MEMBER_CURRENT_USER_IS_LOGGED_IN_AS_MEMBER){ ?>
2
+
3
+ This is some content that will be displayed to all paying Members.
4
+
5
+ <?php if(S2MEMBER_CURRENT_USER_PAID_REGISTRATION_DAYS >= 30){ ?>
6
+ Drip content to Members that started paying you at least 30 days ago.
7
+ <?php } ?>
8
+
9
+ <?php if(S2MEMBER_CURRENT_USER_PAID_REGISTRATION_DAYS >= 60){ ?>
10
+ Drip content to Members that started paying you at least 60 days ago.
11
+ <?php } ?>
12
+
13
+ <?php if(S2MEMBER_CURRENT_USER_PAID_REGISTRATION_DAYS >= 90){ ?>
14
+ Drip content to Members that started paying you at least 90 days ago.
15
+ <?php } ?>
16
+
17
+ <?php } ?>
18
+
19
+ ---- s2member Shortcode Equivalent ----
20
+
21
+ [s2Get constant="S2MEMBER_CURRENT_USER_PAID_REGISTRATION_DAYS" /]
22
+
23
+ There is NO Shortcode equivalent for this logic yet. Coming soon.
includes/menu-pages/code-samples/current-user-paid-registration-days.php ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php echo S2MEMBER_CURRENT_USER_PAID_REGISTRATION_DAYS; ?>
2
+ This may output something like: 120 ( 120 days is approx 4 months )
3
+
4
+ In this example, the longer they've been a "paying" Member, the more they get.
5
+
6
+ <?php if(S2MEMBER_CURRENT_USER_IS_LOGGED_IN_AS_MEMBER){ ?>
7
+
8
+ This is some content that will be displayed to all paying Members.
9
+
10
+ <?php if(S2MEMBER_CURRENT_USER_PAID_REGISTRATION_DAYS >= 30){ ?>
11
+ Drip content to Members that started paying you at least 30 days ago.
12
+ <?php } ?>
13
+
14
+ <?php if(S2MEMBER_CURRENT_USER_PAID_REGISTRATION_DAYS >= 60){ ?>
15
+ Drip content to Members that started paying you at least 60 days ago.
16
+ <?php } ?>
17
+
18
+ <?php if(S2MEMBER_CURRENT_USER_PAID_REGISTRATION_DAYS >= 90){ ?>
19
+ Drip content to Members that started paying you at least 90 days ago.
20
+ <?php } ?>
21
+
22
+ <?php } ?>
23
+
24
+ ---- s2member Shortcode Equivalent ----
25
+
26
+ [s2Get constant="S2MEMBER_CURRENT_USER_PAID_REGISTRATION_DAYS" /]
27
+
28
+ There is NO Shortcode equivalent for this logic yet. Coming soon.
includes/menu-pages/code-samples/current-user-paid-registration-time.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php echo S2MEMBER_CURRENT_USER_PAID_REGISTRATION_TIME; ?>
2
+ This may output something like: 1270537981
3
+ ( this is a Unix timestamp, which is based on seconds )
4
+
5
+ ---- s2member Shortcode Equivalent ----
6
+
7
+ [s2Get constant="S2MEMBER_CURRENT_USER_PAID_REGISTRATION_TIME" /]
includes/menu-pages/code-samples/current-user-registration-days-dripping.php DELETED
@@ -1,23 +0,0 @@
1
- <?php if(S2MEMBER_CURRENT_USER_IS_LOGGED_IN_AS_MEMBER){ ?>
2
-
3
- This is some content that will be displayed to all Members.
4
-
5
- <?php if(S2MEMBER_CURRENT_USER_REGISTRATION_DAYS >= 30){ ?>
6
- Drip content to Members who are more than 30 days old.
7
- <?php } ?>
8
-
9
- <?php if(S2MEMBER_CURRENT_USER_REGISTRATION_DAYS >= 60){ ?>
10
- Drip content to Members who are more than 60 days old.
11
- <?php } ?>
12
-
13
- <?php if(S2MEMBER_CURRENT_USER_REGISTRATION_DAYS >= 90){ ?>
14
- Drip content to Members who are more than 90 days old.
15
- <?php } ?>
16
-
17
- <?php } ?>
18
-
19
- ---- s2member Shortcode Equivalent ----
20
-
21
- [s2Get constant="S2MEMBER_CURRENT_USER_REGISTRATION_DAYS" /]
22
-
23
- There is NO Shortcode equivalent for this logic yet. Coming soon.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/menu-pages/code-samples/current-user-registration-days.php CHANGED
@@ -1,22 +1,22 @@
1
  <?php echo S2MEMBER_CURRENT_USER_REGISTRATION_DAYS; ?>
2
  This may output something like: 120 ( 120 days is approx 4 months )
3
 
4
- Here's how you Drip Content. The longer they've been a Member, the more they get.
5
 
6
- <?php if(S2MEMBER_CURRENT_USER_IS_LOGGED_IN_AS_MEMBER){ ?>
7
 
8
- This is some content that will be displayed to all Members.
9
 
10
  <?php if(S2MEMBER_CURRENT_USER_REGISTRATION_DAYS >= 30){ ?>
11
- Drip content to Members who are more than 30 days old.
12
  <?php } ?>
13
 
14
  <?php if(S2MEMBER_CURRENT_USER_REGISTRATION_DAYS >= 60){ ?>
15
- Drip content to Members who are more than 60 days old.
16
  <?php } ?>
17
 
18
  <?php if(S2MEMBER_CURRENT_USER_REGISTRATION_DAYS >= 90){ ?>
19
- Drip content to Members who are more than 90 days old.
20
  <?php } ?>
21
 
22
  <?php } ?>
1
  <?php echo S2MEMBER_CURRENT_USER_REGISTRATION_DAYS; ?>
2
  This may output something like: 120 ( 120 days is approx 4 months )
3
 
4
+ In this example, the longer they've been registered ( for free or otherwise ), the more they get.
5
 
6
+ <?php if(S2MEMBER_CURRENT_USER_IS_LOGGED_IN){ ?>
7
 
8
+ This is some content that will be displayed to all Users ( free or otherwise ).
9
 
10
  <?php if(S2MEMBER_CURRENT_USER_REGISTRATION_DAYS >= 30){ ?>
11
+ Drip content to Users who've been registered for at least 30 days.
12
  <?php } ?>
13
 
14
  <?php if(S2MEMBER_CURRENT_USER_REGISTRATION_DAYS >= 60){ ?>
15
+ Drip content to Users who've been registered for at least 60 days.
16
  <?php } ?>
17
 
18
  <?php if(S2MEMBER_CURRENT_USER_REGISTRATION_DAYS >= 90){ ?>
19
+ Drip content to Users who've been registered for at least 90 days.
20
  <?php } ?>
21
 
22
  <?php } ?>
includes/menu-pages/code-samples/current-user-subscr-id.php CHANGED
@@ -1,8 +1,8 @@
1
  <?php echo S2MEMBER_CURRENT_USER_SUBSCR_ID; ?>
2
  This may output something like: S-82234JD0923423
3
- ( this is the PayPal Subscription ID associated with their account )
4
  ( if the User is a Free Subscriber, this is their Free Subscriber ID )
5
- ( for Lifetime subscriptions sold through Buy It Now buttons, this will hold the PayPal Transaction ID associated with their purchase )
6
 
7
  ---- s2member Shortcode Equivalent ----
8
 
1
  <?php echo S2MEMBER_CURRENT_USER_SUBSCR_ID; ?>
2
  This may output something like: S-82234JD0923423
3
+ ( this is the Paid Subscription ID associated with their account )
4
  ( if the User is a Free Subscriber, this is their Free Subscriber ID )
5
+ ( for Lifetime subscriptions sold through Buy Now buttons, this will hold the Paid Transaction ID associated with their purchase )
6
 
7
  ---- s2member Shortcode Equivalent ----
8
 
includes/menu-pages/code-samples/paypal-pdt-identity-token.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php echo S2MEMBER_PAYPAL_PDT_IDENTITY_TOKEN; ?>
2
+ This may output something like: jjweu7234jKDdsjSLKSEDFoe38345j3232llii3450823kk2o0jgg
3
+ ( or whatever you have configured as your PayPal® Identity Token )
4
+
5
+ ---- s2member Shortcode Equivalent ----
6
+
7
+ [s2Get constant="S2MEMBER_PAYPAL_PDT_IDENTITY_TOKEN" /]
includes/menu-pages/code-samples/s2member-paid-registration-time-examples.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ------- Example #1 ------------------------------------------------------
2
+
3
+ <?php if(s2member_paid_registration_time() > 0){ ?>
4
+
5
+ This is some content that will be displayed to all Members that have paid you at some point.
6
+
7
+ <?php if(s2member_paid_registration_time("level2") > 0){ ?>
8
+ This will be displayed to all Members that have paid for Level#2 at some point.
9
+ <?php } ?>
10
+
11
+ <?php if(s2member_paid_registration_time("level3") > 0){ ?>
12
+ This will be displayed to all Members that have paid for Level#3 at some point.
13
+ <?php } ?>
14
+
15
+ <?php } ?>
16
+
17
+ ------- Example #2 ------------------------------------------------------
18
+
19
+ <?php if(s2member_paid_registration_time() > 0){ ?>
20
+
21
+ This is some content that will be displayed to all Members that have paid you at some point.
22
+
23
+ <?php if(s2member_paid_registration_time("level1") >= ($_30_days_ago = strtotime("-30 days"))){ ?>
24
+ Drip content to Members that started paying you at Level#1, at least 30 days ago.
25
+ <?php } ?>
26
+
27
+ <?php if(s2member_paid_registration_time("level1") >= ($_60_days_ago = strtotime("-60 days"))){ ?>
28
+ Drip more content to Members that started paying you at Level#1, at least 60 days ago.
29
+ <?php } ?>
30
+
31
+ <?php } ?>
includes/menu-pages/code-samples/s2member-paid-registration-time.php ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ * Function: s2member_paid_registration_time ($level, $user_id); // returns a Unix timestamp.
2
+
3
+ The $level argument is optional. It defaults to the first/initial Paid Registration Time, regardless of Level#.
4
+ Or you could do this: s2member_paid_registration_time("level1"); which will give you the Registration Time at Level #1.
5
+ If a User/Member has never paid for Level #1 ( i.e. they signed up at Level#2 ), the function will return 0.
6
+
7
+ The argument $user_id defaults to the current user that is logged in.
8
+
9
+ Here are some examples:
10
+
11
+ <?php
12
+ $time = s2member_registration_time (); // ... first registration time ( free or otherwise ).
13
+ $time = s2member_paid_registration_time (); // ... first "paid" registration and/or upgrade time.
14
+ $time = s2member_paid_registration_time ("level1"); // ... first "paid" registration or upgrade time at Level#1.
15
+ $time = s2member_paid_registration_time ("level2"); // ... first "paid" registration or upgrade time at Level#2.
16
+ $time = s2member_paid_registration_time ("level3"); // ... first "paid" registration or upgrade time at Level#3.
17
+ $time = s2member_paid_registration_time ("level4"); // ... first "paid" registration or upgrade time at Level#4.
18
+ ?>
includes/menu-pages/down-ops.inc.php CHANGED
@@ -53,8 +53,8 @@ if (apply_filters ("ws_plugin__s2member_during_down_ops_page_during_left_section
53
  echo '<div class="ws-menu-page-hr"></div>' . "\n";
54
  /**/
55
  echo '<p>s2Member will allow access to these protected files, based on the configuration you specify below. Repeated downloads of the same exact file are NOT tabulated against the totals below. Once a file has been downloaded, future downloads of the same exact file, by the same exact Member will not be counted against them. In other words, if a Member downloads the same file three times, the system only counts that as one unique download.</p>' . "\n";
56
- echo '<p>s2Member will automatically detect links, anywhere in your content, and/or anywhere in your theme files, that contain <code>?s2member_file_download</code>. Whenever a logged-in Member clicks a link that contains <code>?s2member_file_download</code>, the system will politely ask the user to confirm the download using a very intuitive JavaScript confirmation prompt that contains specific details about download limitations. This way your Members will be aware of how many files they\'ve downloaded in the current period; and they\'ll be able to make a conscious decision about whether to proceed with a specific download or not.</p>' . "\n";
57
- echo '<p><em>* The above only applies to Users who are logged in as Members. For all other visitors in the general public, the <code>?s2member_file_download</code> links will redirect them your Membership Options Page, so that new visitors can signup, in order to gain access, by becoming a Member.</em></p>' . "\n";
58
  /**/
59
  echo '<div class="ws-menu-page-hr"></div>' . "\n";
60
  /**/
@@ -182,7 +182,7 @@ if (apply_filters ("ws_plugin__s2member_during_down_ops_page_during_left_section
182
  echo '<select name="ws_plugin__s2member_file_download_limit_exceeded_page" id="ws-plugin--s2member-file-download-limit-exceeded-page">' . "\n";
183
  echo '<option value="">&mdash; Select &mdash;</option>' . "\n";
184
  foreach (($ws_plugin__s2member_temp_a = array_merge ((array)get_pages ())) as $ws_plugin__s2member_temp_o)
185
- echo '<option value="' . esc_attr ($ws_plugin__s2member_temp_o->ID) . '"' . (($ws_plugin__s2member_temp_o->ID == $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_limit_exceeded_page"]) ? ' selected="selected"' : '') . '>' . esc_html ($ws_plugin__s2member_temp_o->post_title) . '</option>' . "\n";
186
  echo '</select><br />' . "\n";
187
  echo 'Please choose a Page that Members will see if they reach their file download limit. This Page should provide an informative message to the Member, describing your file access restrictions. Just tell them a little bit about your policy on file downloads. We recommend the following title: <code>Download Limit Exceeded</code>.' . "\n";
188
  echo '</td>' . "\n";
@@ -235,7 +235,7 @@ if (apply_filters ("ws_plugin__s2member_during_down_ops_page_during_left_section
235
  echo '<div class="ws-menu-page-section ws-plugin--s2member-inline-extensions-section">' . "\n";
236
  echo '<h3>Inline File Extensions ( optional, for content-disposition )</h3>' . "\n";
237
  echo '<p>There are two ways to serve files. Inline, or as an Attachment. By default, s2Member will serve all of your protected Files, as downloadable attachments. Meaning, visitors will be given a File Download Prompt. Otherwise known as <code>Content-Disposition: attachment</code>. In some cases though, you may wish to serve files Inline. For example, PDF files and images should usually be served Inline. When you serve a file Inline, it is displayed in your browser immediately, rather than your browser prompting you to download the file as an attachment.</p>' . "\n";
238
- echo '<p>Using the field below, you can list all of the extensions that you want s2Member to serve Inline ( ex: <code>htm,html,pdf,jpg,jpeg,jpe,gif,png</code> ). Please understand, some files just cannot be displayed inline. For instance, there is no way to display an <code>exe</code> file inline. So only specify extensions that can, and should be displayed inline by a web browser.</p>' . "\n";
239
  do_action ("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_inline_extensions", get_defined_vars ());
240
  /**/
241
  echo '<table class="form-table">' . "\n";
@@ -244,7 +244,7 @@ if (apply_filters ("ws_plugin__s2member_during_down_ops_page_during_left_section
244
  /**/
245
  echo '<th>' . "\n";
246
  echo '<label for="ws-plugin--s2member-file-download-inline-extensions">' . "\n";
247
- echo 'Inline File Extensions ( comma delimited ):' . "\n";
248
  echo '</label>' . "\n";
249
  echo '</th>' . "\n";
250
  /**/
53
  echo '<div class="ws-menu-page-hr"></div>' . "\n";
54
  /**/
55
  echo '<p>s2Member will allow access to these protected files, based on the configuration you specify below. Repeated downloads of the same exact file are NOT tabulated against the totals below. Once a file has been downloaded, future downloads of the same exact file, by the same exact Member will not be counted against them. In other words, if a Member downloads the same file three times, the system only counts that as one unique download.</p>' . "\n";
56
+ echo '<p>s2Member will automatically detect links, anywhere in your content, and/or anywhere in your theme files, that contain <code>?s2member_file_download</code>. Whenever a logged-in Member clicks a link that contains <code>?s2member_file_download</code>, the system will politely ask the user to confirm the download using a very intuitive JavaScript confirmation prompt that contains specific details about download limitations. This way your Members will be aware of how many files they\'ve downloaded in the current period; and they\'ll be able to make a conscious decision about whether to proceed with a specific download or not. If you want to suppress this JavaScript confirmation prompt, you add this to the end of your links: <code>&amp;s2member_skip_confirmation</code>.</p>' . "\n";
57
+ echo '<p><em>* The above only applies to Users who are logged in as Members. For all other visitors in the general public, the <code>?s2member_file_download</code> links will redirect them your Membership Options Page, so that new visitors can signup, in order to gain access, by becoming a Member. You may also want to have a look down below at s2Member\'s "Advanced Download Restrictions", which provides a greater degree of flexibility.</em></p>' . "\n";
58
  /**/
59
  echo '<div class="ws-menu-page-hr"></div>' . "\n";
60
  /**/
182
  echo '<select name="ws_plugin__s2member_file_download_limit_exceeded_page" id="ws-plugin--s2member-file-download-limit-exceeded-page">' . "\n";
183
  echo '<option value="">&mdash; Select &mdash;</option>' . "\n";
184
  foreach (($ws_plugin__s2member_temp_a = array_merge ((array)get_pages ())) as $ws_plugin__s2member_temp_o)
185
+ echo '<option value="' . esc_attr ($ws_plugin__s2member_temp_o->ID) . '"' . ( ($ws_plugin__s2member_temp_o->ID == $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_limit_exceeded_page"]) ? ' selected="selected"' : '') . '>' . esc_html ($ws_plugin__s2member_temp_o->post_title) . '</option>' . "\n";
186
  echo '</select><br />' . "\n";
187
  echo 'Please choose a Page that Members will see if they reach their file download limit. This Page should provide an informative message to the Member, describing your file access restrictions. Just tell them a little bit about your policy on file downloads. We recommend the following title: <code>Download Limit Exceeded</code>.' . "\n";
188
  echo '</td>' . "\n";
235
  echo '<div class="ws-menu-page-section ws-plugin--s2member-inline-extensions-section">' . "\n";
236
  echo '<h3>Inline File Extensions ( optional, for content-disposition )</h3>' . "\n";
237
  echo '<p>There are two ways to serve files. Inline, or as an Attachment. By default, s2Member will serve all of your protected Files, as downloadable attachments. Meaning, visitors will be given a File Download Prompt. Otherwise known as <code>Content-Disposition: attachment</code>. In some cases though, you may wish to serve files Inline. For example, PDF files and images should usually be served Inline. When you serve a file Inline, it is displayed in your browser immediately, rather than your browser prompting you to download the file as an attachment.</p>' . "\n";
238
+ echo '<p>Using the field below, you can list all of the extensions that you want s2Member to serve Inline ( ex: <code>htm,html,pdf,jpg,jpeg,jpe,gif,png</code> ). Please understand, some files just cannot be displayed inline. For instance, there is no way to display an <code>exe</code> file inline. So only specify extensions that can, and should be displayed inline by a web browser. Alternatively, if you would rather handle this on a case-by-case basis, you can simply add the following to the end of your download links: <code>&amp;s2member_file_inline=yes</code>.</p>' . "\n";
239
  do_action ("ws_plugin__s2member_during_down_ops_page_during_left_sections_during_inline_extensions", get_defined_vars ());
240
  /**/
241
  echo '<table class="form-table">' . "\n";
244
  /**/
245
  echo '<th>' . "\n";
246
  echo '<label for="ws-plugin--s2member-file-download-inline-extensions">' . "\n";
247
+ echo 'Default Inline File Extensions ( comma delimited ):' . "\n";
248
  echo '</label>' . "\n";
249
  echo '</th>' . "\n";
250
  /**/
includes/menu-pages/els-ops.inc.php CHANGED
@@ -12,9 +12,9 @@ If not, see: <http://www.gnu.org/licenses/>.
12
  Direct access denial.
13
  */
14
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
15
- exit("Do not access this file directly.");
16
  /*
17
- PayPal® Options page.
18
  */
19
  echo '<div class="wrap ws-menu-page">' . "\n";
20
  /**/
@@ -171,7 +171,7 @@ if (apply_filters ("ws_plugin__s2member_during_els_ops_page_during_left_sections
171
  echo '<a href="http://aweber.com/?348037" target="_blank"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/aweber-logo.png" class="ws-menu-page-right" style="width:125px; height:125px; border:0;" alt="." /></a>' . "\n";
172
  echo '<h3>AWeber® List Server Integration ( optional )</h3>' . "\n";
173
  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";
174
- echo '<p>You can have your Members automatically subscribed to your AWeber® marketing lists ( e.g. newsletters / auto-responders ). You\'ll need an <a href="http://aweber.com/?348037" 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 Custom Email Parser inside your AWeber® account. Log into AWeber®, and go to <em>My Lists -> Email Parser</em>. Choose the PayPal® Parser. You can safely ignore the additional instructions they provide. s2Member just needs the PayPal® box checked, and that\'s all. At some point, we\'ll get in contact with AWeber® about integrating a Custom Parser that is specifically designed for s2Member. Until then, you can just use the PayPal® Parser that is already available in your AWeber® account.</p>' . "\n";
175
  do_action ("ws_plugin__s2member_during_els_ops_page_during_left_sections_during_aweber", get_defined_vars ());
176
  /**/
177
  echo '<table class="form-table">' . "\n";
@@ -280,12 +280,12 @@ if (apply_filters ("ws_plugin__s2member_during_els_ops_page_during_left_sections
280
  /**/
281
  echo '<div class="ws-menu-page-section ws-plugin--s2member-opt-in-section">' . "\n";
282
  echo '<h3>Double Opt-In Checkbox Field ( optional )</h3>' . "\n";
283
- echo '<p>A Double Opt-In Checkbox will ONLY be displayed, if you\'ve integrated one <em>or more</em> List Servers ( in the sections above ).' . ((defined ("BP_VERSION")) ? ' With BuddyPress installed, the Checkbox will only be displayed if your BuddyPress theme supports <code>do_action("bp_before_registration_submit_buttons")</code>. Almost all BuddyPress themes support this. If yours does not, you can add it in.' : '') . '</p>' . "\n";
284
  do_action ("ws_plugin__s2member_during_els_ops_page_during_left_sections_during_opt_in", get_defined_vars ());
285
  /**/
286
  echo '<table class="form-table">' . "\n";
287
  echo '<tbody>' . "\n";
288
- echo '<tr class="ws-plugin--s2member-custom-reg-opt-in-label-row"' . ((!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in"]) ? ' style="display:none;"' : '') . '>' . "\n";
289
  /**/
290
  echo '<th>' . "\n";
291
  echo '<label for="ws-plugin--s2member-custom-reg-opt-in-label">' . "\n";
@@ -294,11 +294,11 @@ if (apply_filters ("ws_plugin__s2member_during_els_ops_page_during_left_sections
294
  echo '</th>' . "\n";
295
  /**/
296
  echo '</tr>' . "\n";
297
- echo '<tr class="ws-plugin--s2member-custom-reg-opt-in-label-row"' . ((!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in"]) ? ' style="display:none;"' : '') . '>' . "\n";
298
  /**/
299
  echo '<td>' . "\n";
300
  echo '<input type="text" name="ws_plugin__s2member_custom_reg_opt_in_label" id="ws-plugin--s2member-custom-reg-opt-in-label" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in_label"]) . '" /><br />' . "\n";
301
- echo 'Example: <code><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in"] == 1) ? 'checked' : 'unchecked') . '.png" class="ws-plugin--s2member-custom-reg-opt-in-label-prev-img ws-menu-page-img-16" style="vertical-align:middle;" alt="" /> Your Label will appear next to a Checkbox.</code>' . "\n";
302
  echo '</td>' . "\n";
303
  /**/
304
  echo '</tr>' . "\n";
@@ -315,9 +315,9 @@ if (apply_filters ("ws_plugin__s2member_during_els_ops_page_during_left_sections
315
  /**/
316
  echo '<td>' . "\n";
317
  echo '<select name="ws_plugin__s2member_custom_reg_opt_in" id="ws-plugin--s2member-custom-reg-opt-in">' . "\n";
318
- echo '<option value="1"' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in"] == 1) ? ' selected="selected"' : '') . '>Yes ( the Box MUST be checked — checked by default )</option>' . "\n";
319
- echo '<option value="2"' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in"] == 2) ? ' selected="selected"' : '') . '>Yes ( the Box MUST be checked — unchecked by default )</option>' . "\n";
320
- echo '<option value="0"' . ((!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in"]) ? ' selected="selected"' : '') . '>No ( disable — do NOT display or require the Checkbox )</option>' . "\n";
321
  echo '</select><br />' . "\n";
322
  echo 'An email confirmation will NOT be sent to the User, unless the Box is checked, or you\'ve disabled the Box; by choosing <code>No</code>.' . "\n";
323
  echo '</td>' . "\n";
12
  Direct access denial.
13
  */
14
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
15
+ exit ("Do not access this file directly.");
16
  /*
17
+ List Server Options page.
18
  */
19
  echo '<div class="wrap ws-menu-page">' . "\n";
20
  /**/
171
  echo '<a href="http://aweber.com/?348037" target="_blank"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/aweber-logo.png" class="ws-menu-page-right" style="width:125px; height:125px; border:0;" alt="." /></a>' . "\n";
172
  echo '<h3>AWeber® List Server Integration ( optional )</h3>' . "\n";
173
  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";
174
+ echo '<p>You can have your Members automatically subscribed to your AWeber® marketing lists ( e.g. newsletters / auto-responders ). You\'ll need an <a href="http://aweber.com/?348037" 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 Custom Email Parser inside your AWeber® account. Log into AWeber®, and go to <em>My Lists -> Email Parser</em>. Choose the PayPal® Parser ( even if you\'re not using PayPal® as your Payment Gateway ). You can safely ignore the additional instructions they provide. s2Member just needs the PayPal® box checked, and that\'s all. At some point, we\'ll get in contact with AWeber® about integrating a Custom Parser that is specifically designed for s2Member. Until then, you can just use the PayPal® Parser that is already available in your AWeber® account.</p>' . "\n";
175
  do_action ("ws_plugin__s2member_during_els_ops_page_during_left_sections_during_aweber", get_defined_vars ());
176
  /**/
177
  echo '<table class="form-table">' . "\n";
280
  /**/
281
  echo '<div class="ws-menu-page-section ws-plugin--s2member-opt-in-section">' . "\n";
282
  echo '<h3>Double Opt-In Checkbox Field ( optional )</h3>' . "\n";
283
+ echo '<p>A Double Opt-In Checkbox will ONLY be displayed, if you\'ve integrated one <em>or more</em> List Servers ( in the sections above ).' . ( (defined ("BP_VERSION")) ? ' With BuddyPress installed, the Checkbox will only be displayed if your BuddyPress theme supports <code>do_action("bp_before_registration_submit_buttons")</code>. Almost all BuddyPress themes support this. If yours does not, you can add it in.' : '') . '</p>' . "\n";
284
  do_action ("ws_plugin__s2member_during_els_ops_page_during_left_sections_during_opt_in", get_defined_vars ());
285
  /**/
286
  echo '<table class="form-table">' . "\n";
287
  echo '<tbody>' . "\n";
288
+ echo '<tr class="ws-plugin--s2member-custom-reg-opt-in-label-row"' . ( (!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in"]) ? ' style="display:none;"' : '') . '>' . "\n";
289
  /**/
290
  echo '<th>' . "\n";
291
  echo '<label for="ws-plugin--s2member-custom-reg-opt-in-label">' . "\n";
294
  echo '</th>' . "\n";
295
  /**/
296
  echo '</tr>' . "\n";
297
+ echo '<tr class="ws-plugin--s2member-custom-reg-opt-in-label-row"' . ( (!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in"]) ? ' style="display:none;"' : '') . '>' . "\n";
298
  /**/
299
  echo '<td>' . "\n";
300
  echo '<input type="text" name="ws_plugin__s2member_custom_reg_opt_in_label" id="ws-plugin--s2member-custom-reg-opt-in-label" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in_label"]) . '" /><br />' . "\n";
301
+ echo 'Example: <code><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/' . ( ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in"] == 1) ? 'checked' : 'unchecked') . '.png" class="ws-plugin--s2member-custom-reg-opt-in-label-prev-img ws-menu-page-img-16" style="vertical-align:middle;" alt="" /> Your Label will appear next to a Checkbox.</code>' . "\n";
302
  echo '</td>' . "\n";
303
  /**/
304
  echo '</tr>' . "\n";
315
  /**/
316
  echo '<td>' . "\n";
317
  echo '<select name="ws_plugin__s2member_custom_reg_opt_in" id="ws-plugin--s2member-custom-reg-opt-in">' . "\n";
318
+ echo '<option value="1"' . ( ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in"] == 1) ? ' selected="selected"' : '') . '>Yes ( the Box MUST be checked — checked by default )</option>' . "\n";
319
+ echo '<option value="2"' . ( ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in"] == 2) ? ' selected="selected"' : '') . '>Yes ( the Box MUST be checked — unchecked by default )</option>' . "\n";
320
+ echo '<option value="0"' . ( (!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_opt_in"]) ? ' selected="selected"' : '') . '>No ( disable — do NOT display or require the Checkbox )</option>' . "\n";
321
  echo '</select><br />' . "\n";
322
  echo 'An email confirmation will NOT be sent to the User, unless the Box is checked, or you\'ve disabled the Box; by choosing <code>No</code>.' . "\n";
323
  echo '</td>' . "\n";
includes/menu-pages/menu-pages-s-min.js CHANGED
@@ -1 +1 @@
1
- jQuery(document).ready(function(b){var a=esc_html=function(c){return String(c).replace(/"/g,"&quot;").replace(/\</g,"&lt;").replace(/\>/g,"&gt;")};if(location.href.match(/page\=ws-plugin--s2member-mms-options/)){b("select#ws-plugin--s2member-mms-registration-file").change(function(){if(b(this).val()==="wp-signup"){b("div#ws-plugin--s2member-mms-registration-support-package-details-wrapper").show(),b("div.ws-plugin--s2member-mms-registration-wp-login, table.ws-plugin--s2member-mms-registration-wp-login").hide(),b("div.ws-plugin--s2member-mms-registration-wp-signup, table.ws-plugin--s2member-mms-registration-wp-signup").show()}else{if(b(this).val()==="wp-login"){b("div#ws-plugin--s2member-mms-registration-support-package-details-wrapper").hide(),b("div.ws-plugin--s2member-mms-registration-wp-login, table.ws-plugin--s2member-mms-registration-wp-login").show(),b("div.ws-plugin--s2member-mms-registration-wp-signup, table.ws-plugin--s2member-mms-registration-wp-signup").hide()}}b("div.ws-plugin--s2member-mms-registration-wp-signup-blogs-level0, table.ws-plugin--s2member-mms-registration-wp-signup-blogs-level0")[((b("select#ws-plugin--s2member-mms-registration-grants").val()==="all")?"show":"hide")](),b("input#ws-plugin--s2member-mms-registration-blogs-level0").val(((b("select#ws-plugin--s2member-mms-registration-grants").val()==="all")?"1":"0"))}).trigger("change");b("select#ws-plugin--s2member-mms-registration-grants").change(function(){b("select#ws-plugin--s2member-mms-registration-file").trigger("change")})}else{if(location.href.match(/page\=ws-plugin--s2member-options/)){ws_plugin__s2member_generateSecurityKey=function(){var f=function(h,g){h=(arguments.length<1)?0:h;g=(arguments.length<2)?2147483647:g;return Math.floor(Math.random()*(g-h+1))+h};var e="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()";for(var d=0,c="";d<56;d++){c+=e.substr(f(0,e.length-1),1)}b("input#ws-plugin--s2member-sec-encryption-key").val(c);return false};ws_plugin__s2member_enableSecurityKey=function(){if(confirm("Edit Key? Are you sure?\nThis could break your installation!\n\n*Note* If you've been testing s2Member, feel free to change this Key before you go live. Just don't go live, and then change it. You'll have some very unhappy Customers. Data corruption WILL occur!\n\nFor your safety, s2Member keeps a history of the last 10 Keys that you've used. If you get yourself into a real situation, s2Member will let you revert back to a previous Key.")){b("input#ws-plugin--s2member-sec-encryption-key").attr("disabled",false)}return false};ws_plugin__s2member_securityKeyHistory=function(){b("div#ws-plugin--s2member-sec-encryption-key-history").toggle();return false};if(b("input#ws-plugin--s2member-custom-reg-fields").length&&b("div#ws-plugin--s2member-custom-reg-field-configuration").length){(function(){var c=b("input#ws-plugin--s2member-custom-reg-fields");var f=b("div#ws-plugin--s2member-custom-reg-field-configuration");var l=(c.val())?b.JSON.parse(c.val()):[];l=(l instanceof Array)?l:[];var k='<div id="ws-plugin--s2member-custom-reg-field-configuration-tools"></div>';var r='<table id="ws-plugin--s2member-custom-reg-field-configuration-table"></table>';f.html(k+r);var i=b("div#ws-plugin--s2member-custom-reg-field-configuration-tools");var o=b("table#ws-plugin--s2member-custom-reg-field-configuration-table");ws_plugin__s2member_customRegFieldTypeChange=function(t){var s,v,u=b(t).val();s="tr.ws-plugin--s2member-custom-reg-field-configuration-tools-form-options";v="tr.ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected";if(u.match(/^(text|textarea|checkbox|pre_checkbox)$/)){b(s).css("display","none"),b(s).prev("tr").css("display","none")}else{b(s).css("display",""),b(s).prev("tr").css("display","")}if(u.match(/^(select|selects|checkboxes|radios)$/)){b(v).css("display","none"),b(v).prev("tr").css("display","none")}else{b(v).css("display",""),b(v).prev("tr").css("display","")}};ws_plugin__s2member_customRegFieldDelete=function(t){var s=new Array();for(var u=0;u<l.length;u++){if(u!==t){s.push(l[u])}}l=s,q(),p()};ws_plugin__s2member_customRegFieldMoveUp=function(u){if(typeof l[u]==="object"&&typeof l[u-1]==="object"){var t=l[u-1],s=l[u];l[u-1]=s,l[u]=t;q(),p()}};ws_plugin__s2member_customRegFieldMoveDown=function(u){if(typeof l[u]==="object"&&typeof l[u+1]==="object"){var s=l[u+1],t=l[u];l[u+1]=t,l[u]=s;q(),p()}};ws_plugin__s2member_customRegFieldCreate=function(){var s=b("table#ws-plugin--s2member-custom-reg-field-configuration-tools-form"),t={};b(':input[property!=""]',s).each(function(){var v=b(this),u=v.attr("property"),w=b.trim(v.val());t[u]=w});if((t=d(t))){l.push(t),q(),j(),p(),n();setTimeout(function(){var u="tr.ws-plugin--s2member-custom-reg-field-configuration-table-row-"+(l.length-1);alert('Field created successfully.\n* Remember to "Save Changes".');b(u).effect("highlight",1000)},500)}};ws_plugin__s2member_customRegFieldUpdate=function(t){var s=b("table#ws-plugin--s2member-custom-reg-field-configuration-tools-form"),u={};b(':input[property!=""]',s).each(function(){var x=b(this),w=x.attr("property"),y=b.trim(x.val());u[w]=y});if((u=d(u,t))){l[t]=u,q(),j(),p(),n();var v="tr.ws-plugin--s2member-custom-reg-field-configuration-table-row-"+t;b(v).effect("highlight",1000)}};ws_plugin__s2member_customRegFieldAdd=function(){j(true)};ws_plugin__s2member_customRegFieldEdit=function(s){j(false,s),n()};ws_plugin__s2member_customRegFieldCancel=function(){j(),n()};var d=function(w,u){var s=(typeof u==="number"&&typeof l[u]==="object")?true:false,x=[],t,v;if(typeof w!=="object"){x.push("Invalid field object. Please try again.")}else{if(!w.id){x.push("Unique Field ID:\nThis is required. Please try again.")}else{if(h(w.id)&&(!s||w.id!==l[u].id)){x.push("Unique Field ID:\nThat Field ID already exists. Please try again.")}}if(!w.label){x.push("Field Label/Description:\nThis is required. Please try again.")}if(w.type.match(/^(select|selects|checkboxes|radios)$/)){w.expected="";if(!w.options){x.push("Option Configuration File:\nThis is required. Please try again.")}else{t=w.options.split(/[\r\n]+/);for(v=0;v<t.length;v++){t[v]=b.trim(t[v]);if(!t[v].match(/^([^\|]*)(\|)([^\|]*)(\|default)?$/)){x.push("Option Configuration File:\nInvalid configuration at line #"+(v+1)+".");break}}w.options=b.trim(t.join("\n"))}}else{w.options=""}if(!(w.levels=w.levels.replace(/ /g,""))){x.push("Applicable Levels:\nThis is required. Please try again.")}else{if(!w.levels.match(/^(all|[0-9,]+)$/)){x.push("Applicable Levels:\nShould be comma delimited Levels, or just type: all.\n( examples: 0,1,2,3,4 or type the word: all )")}}if(w.classes&&w.classes.match(/[^a-z 0-9 _ \-]/i)){x.push("CSS Classes:\nContains invalid characters. Please try again.\n( only: alphanumerics, underscores, hyphens, spaces )")}if(w.styles&&w.styles.match(/["\=\>\<]/)){x.push('CSS Styles:\nContains invalid characters. Please try again.\n( do NOT use these characters: = " < > )')}if(w.attrs&&w.attrs.match(/[\>\<]/)){x.push("Other Attributes:\nContains invalid characters. Please try again.\n( do NOT use these characters: < > )")}}if(x.length>0){alert(x.join("\n\n"));return false}else{return w}};var q=function(){c.val(((l.length>0)?b.JSON.stringify(l):""))};var m=function(s){return(typeof s==="string")?b.trim(s).toLowerCase().replace(/[^a-z0-9]/g,"_"):""};var g=function(t){var s={text:"Text ( single line )",textarea:"Textarea ( multi-line )",select:"Select Menu ( drop-down )",selects:"Select Menu ( multi-option )",checkbox:"Checkbox ( single )",pre_checkbox:"Checkbox ( pre-checked )",checkboxes:"Checkboxes ( multi-option )",radios:"Radio Buttons ( multi-option )"};if(typeof s[t]==="string"){return s[t]}return""};var h=function(s){for(var t=0;t<l.length;t++){if(l[t].id===s){return true}}};var n=function(){scrollTo(0,b("div.ws-plugin--s2member-custom-reg-fields-section").offset()["top"]-100)};var j=function(s,A){var x=0,z="",t="",D=0,y=0,v={id:"",label:"",type:"text",options:"",expected:"",required:"yes",levels:"all",editable:"yes",classes:"",styles:"",attrs:""};var u=(typeof A==="number"&&typeof l[A]==="object")?true:false,C=(s||u)?true:false,B=(u)?l[A]:v;z+='<a href="#" onclick="ws_plugin__s2member_customRegFieldAdd(); return false;">Add New Field</a>';tb_remove(),b("div#ws-plugin--s2member-custom-reg-field-configuration-thickbox-tools-form").remove();if(C){t+='<div id="ws-plugin--s2member-custom-reg-field-configuration-thickbox-tools-form">';t+='<table id="ws-plugin--s2member-custom-reg-field-configuration-tools-form">';t+="<tbody>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-type">';t+='<td colspan="2">';t+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-type">Form Field Type: *</label>';t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-type">';t+='<td colspan="2">';t+='<select property="type" onchange="ws_plugin__s2member_customRegFieldTypeChange(this);" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-type">';t+='<option value="text"'+((B.type==="text")?' selected="selected"':"")+'">'+esc_html(g("text"))+"</option>";t+='<option value="textarea"'+((B.type==="textarea")?' selected="selected"':"")+'">'+esc_html(g("textarea"))+"</option>";t+='<option value="select"'+((B.type==="select")?' selected="selected"':"")+'">'+esc_html(g("select"))+"</option>";t+='<option value="selects"'+((B.type==="selects")?' selected="selected"':"")+'">'+esc_html(g("selects"))+"</option>";t+='<option value="checkbox"'+((B.type==="checkbox")?' selected="selected"':"")+'">'+esc_html(g("checkbox"))+"</option>";t+='<option value="pre_checkbox"'+((B.type==="pre_checkbox")?' selected="selected"':"")+'">'+esc_html(g("pre_checkbox"))+"</option>";t+='<option value="checkboxes"'+((B.type==="checkboxes")?' selected="selected"':"")+'">'+esc_html(g("checkboxes"))+"</option>";t+='<option value="radios"'+((B.type==="radios")?' selected="selected"':"")+'">'+esc_html(g("radios"))+"</option>";t+="</select>";t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer"><td colspan="2">&nbsp;</td></tr>';t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-label">';t+='<td colspan="2">';t+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-label">Field Label/Desc: *</label>';t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-label">';t+='<td colspan="2">';t+='<input type="text" property="label" value="'+a(B.label)+'" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-label" /><br />';t+="<small>Examples: <code>Choose Country</code>, <code>Street Address</code></small>";t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer"><td colspan="2">&nbsp;</td></tr>';t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-id">';t+='<td colspan="2">';t+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-id">Unique Field ID: *</label></label>';t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-id">';t+='<td colspan="2">';t+='<input type="text" property="id" value="'+a(B.id)+'" maxlength="25" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-id" /><br />';t+="<small>Examples: <code>country_code</code>, <code>street_address</code></small><br />";t+='<small>e.g. <code>&lt;?php echo get_user_field("country_code"); ?&gt;</code></small>';t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer"><td colspan="2">&nbsp;</td></tr>';t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-required">';t+='<td colspan="2">';t+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-required">Field Required: *</label>';t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-required">';t+='<td colspan="2">';t+='<select property="required" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-required">';t+='<option value="yes"'+((B.required==="yes")?' selected="selected"':"")+'">Yes ( required )</option>';t+='<option value="no"'+((B.required==="no")?' selected="selected"':"")+'">No ( optional )</option>';t+="</select><br />";t+='<small>If <code>yes</code>, only Users/Members will be "required" to enter this field.</small><br />';t+="<small>* Administrators are exempt from this requirement.</small>";t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer"'+((B.type.match(/^(text|textarea|checkbox|pre_checkbox)$/))?' style="display:none;"':"")+'><td colspan="2">&nbsp;</td></tr>';t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-options"'+((B.type.match(/^(text|textarea|checkbox|pre_checkbox)$/))?' style="display:none;"':"")+">";t+='<td colspan="2">';t+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-options">Option Configuration File: * ( one option per line )</label><br />';t+="<small>Use a pipe <code>|</code> delimited format: <code>option value|option label</code></small>";t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-options"'+((B.type.match(/^(text|textarea|checkbox|pre_checkbox)$/))?' style="display:none;"':"")+">";t+='<td colspan="2">';t+='<textarea property="options" rows="3" wrap="off" spellcheck="false" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-options">'+esc_html(B.options)+"</textarea><br />";t+="Here is a quick example:<br />";t+="<small>You can also specify a <em>default</em> option:</small><br />";t+="<code>US|United States|default</code><br />";t+="<code>CA|Canada</code><br />";t+="<code>VI|Virgin Islands (U.S.)</code>";t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer"'+((B.type.match(/^(select|selects|checkboxes|radios)$/))?' style="display:none;"':"")+'><td colspan="2">&nbsp;</td></tr>';t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected"'+((B.type.match(/^(select|selects|checkboxes|radios)$/))?' style="display:none;"':"")+">";t+='<td colspan="2">';t+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected">Expected Format: *</label>';t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected"'+((B.type.match(/^(select|selects|checkboxes|radios)$/))?' style="display:none;"':"")+">";t+='<td colspan="2">';t+='<select property="expected" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected">';t+='<option value=""'+((B.expected==="")?' selected="selected"':"")+'">Anything Goes</option>';t+='<option disabled="disabled"></option>';t+='<optgroup label="Specific Input Types">';t+='<option value="numeric-wp-commas"'+((B.expected==="numeric-wp-commas")?' selected="selected"':"")+'">Numeric ( with or without decimals, commas allowed )</option>';t+='<option value="numeric"'+((B.expected==="numeric")?' selected="selected"':"")+'">Numeric ( with or without decimals, no commas )</option>';t+='<option value="integer"'+((B.expected==="integer")?' selected="selected"':"")+'">Integer ( whole number, without any decimals )</option>';t+='<option value="integer-gt-0"'+((B.expected==="integer-gt-0")?' selected="selected"':"")+'">Integer > 0 ( whole number, no decimals, greater than 0 )</option>';t+='<option value="float"'+((B.expected==="float")?' selected="selected"':"")+'">Float ( floating point number, decimals required )</option>';t+='<option value="float-gt-0"'+((B.expected==="float-gt-0")?' selected="selected"':"")+'">Float > 0 ( floating point number, decimals required, greater than 0 )</option>';t+='<option value="date"'+((B.expected==="date")?' selected="selected"':"")+'">Date ( required date format: dd/mm/yyyy )</option>';t+='<option value="email"'+((B.expected==="email")?' selected="selected"':"")+'">Email ( require valid email )</option>';t+='<option value="url"'+((B.expected==="url")?' selected="selected"':"")+'">Full URL ( starting with http or https )</option>';t+='<option value="domain"'+((B.expected==="domain")?' selected="selected"':"")+'">Domain Name ( domain name only, without http )</option>';t+='<option value="phone"'+((B.expected==="phone")?' selected="selected"':"")+'">Phone # ( 10 digits w/possible hyphens,spaces,brackets )</option>';t+='<option value="uszip"'+((B.expected==="uszip")?' selected="selected"':"")+'">US Zipcode ( 5-9 digits w/possible hyphen )</option>';t+='<option value="cazip"'+((B.expected==="cazip")?' selected="selected"':"")+'">Canadian Zipcode ( 6 alpha-numerics w/possible space )</option>';t+='<option value="uczip"'+((B.expected==="uczip")?' selected="selected"':"")+'">US/Canadian Zipcode ( either a US or Canadian zipcode )</option>';t+="</optgroup>";t+='<option disabled="disabled"></option>';t+='<optgroup label="Any Character Combination">';for(x=1;x<=25;x++){t+='<option value="any-'+x+'"'+((B.expected==="any-"+x)?' selected="selected"':"")+'">Any Character Combination ( '+x+" character minimum )</option>";t+='<option value="any-'+x+'-e"'+((B.expected==="any-"+x+"-e")?' selected="selected"':"")+'">Any Character Combination ( exactly '+x+" character"+((x>1)?"s":"")+" )</option>"}t+="</optgroup>";t+='<option disabled="disabled"></option>';t+='<optgroup label="Alphanumerics, Spaces &amp; Punctuation Only">';for(x=1;x<=25;x++){t+='<option value="alphanumerics-spaces-punctuation-'+x+'"'+((B.expected==="alphanumerics-spaces-punctuation-"+x)?' selected="selected"':"")+'">Alphanumerics, Spaces &amp; Punctuation ( '+x+" character minimum )</option>";t+='<option value="alphanumerics-spaces-punctuation-'+x+'-e"'+((B.expected==="alphanumerics-spaces-punctuation-"+x+"-e")?' selected="selected"':"")+'">Alphanumerics, Spaces &amp; Punctuation ( exactly '+x+" character"+((x>1)?"s":"")+" )</option>"}t+="</optgroup>";t+='<option disabled="disabled"></option>';t+='<optgroup label="Alphanumerics &amp; Spaces Only">';for(x=1;x<=25;x++){t+='<option value="alphanumerics-spaces-'+x+'"'+((B.expected==="alphanumerics-spaces-"+x)?' selected="selected"':"")+'">Alphanumerics &amp; Spaces ( '+x+" character minimum )</option>";t+='<option value="alphanumerics-spaces-'+x+'-e"'+((B.expected==="alphanumerics-spaces-"+x+"-e")?' selected="selected"':"")+'">Alphanumerics &amp; Spaces ( exactly '+x+" character"+((x>1)?"s":"")+" )</option>"}t+="</optgroup>";t+='<option disabled="disabled"></option>';t+='<optgroup label="Alphanumerics &amp; Punctuation Only">';for(x=1;x<=25;x++){t+='<option value="alphanumerics-punctuation-'+x+'"'+((B.expected==="alphanumerics-punctuation-"+x)?' selected="selected"':"")+'">Alphanumerics &amp; Punctuation ( '+x+" character minimum )</option>";t+='<option value="alphanumerics-punctuation-'+x+'-e"'+((B.expected==="alphanumerics-punctuation-"+x+"-e")?' selected="selected"':"")+'">Alphanumerics &amp; Punctuation ( exactly '+x+" character"+((x>1)?"s":"")+" )</option>"}t+="</optgroup>";t+='<option disabled="disabled"></option>';t+='<optgroup label="Alphanumerics Only">';for(x=1;x<=25;x++){t+='<option value="alphanumerics-'+x+'"'+((B.expected==="alphanumerics-"+x)?' selected="selected"':"")+'">Alphanumerics ( '+x+" character minimum )</option>";t+='<option value="alphanumerics-'+x+'-e"'+((B.expected==="alphanumerics-"+x+"-e")?' selected="selected"':"")+'">Alphanumerics ( exactly '+x+" character"+((x>1)?"s":"")+" )</option>"}t+="</optgroup>";t+='<option disabled="disabled"></option>';t+='<optgroup label="Alphabetics Only">';for(x=1;x<=25;x++){t+='<option value="alphabetics-'+x+'"'+((B.expected==="alphabetics-"+x)?' selected="selected"':"")+'">Alphabetics ( '+x+" character minimum )</option>";t+='<option value="alphabetics-'+x+'-e"'+((B.expected==="alphabetics-"+x+"-e")?' selected="selected"':"")+'">Alphabetics ( exactly '+x+" character"+((x>1)?"s":"")+" )</option>"}t+="</optgroup>";t+='<option disabled="disabled"></option>';t+='<optgroup label="Numeric Digits Only">';for(x=1;x<=25;x++){t+='<option value="numerics-'+x+'"'+((B.expected==="numerics-"+x)?' selected="selected"':"")+'">Numeric Digits ( '+x+" digit minimum )</option>";t+='<option value="numerics-'+x+'-e"'+((B.expected==="numerics-"+x+"-e")?' selected="selected"':"")+'">Numeric Digits ( exactly '+x+" digit"+((x>1)?"s":"")+" )</option>"}t+="</optgroup>";t+="</select><br />";t+="<small>Only Users/Members will be required to meet this criteria.</small><br />";t+="<small>* Administrators are exempt from this.</small>";t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer"><td colspan="2">&nbsp;</td></tr>';t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-levels">';t+='<td colspan="2">';t+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-levels">Applicable Membership Levels: *</label>';t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-levels">';t+='<td colspan="2">';t+='<input type="text" property="levels" value="'+a(B.levels)+'" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-levels" /><br />';t+="<small>Please use comma-delimited Level #'s: <code>0,1,2,3,4</code> or type: <code>all</code>.</small><br />";t+="<small>This allows you to enable this field - only at specific Membership Levels.</small>";t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer"><td colspan="2">&nbsp;</td></tr>';t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-editable">';t+='<td colspan="2">';t+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-editable">Allow Profile Edits: *</label>';t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-editable">';t+='<td colspan="2">';t+='<select property="editable" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-editable">';t+='<option value="yes"'+((B.editable==="yes")?' selected="selected"':"")+'">Yes ( editable )</option>';t+='<option value="no"'+((B.editable==="no")?' selected="selected"':"")+'">No ( uneditable after registration )</option>';t+='<option value="no-invisible"'+((B.editable==="no-invisible")?' selected="selected"':"")+'">No ( uneditable &amp; totally invisible )</option>';t+="</select><br />";t+="<small>If <code>No</code>, this field will be un-editable after registration.</small><br />";t+="<small>* Administrators are exempt from this.</small>";t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer"><td colspan="2">&nbsp;</td></tr>';t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-classes">';t+='<td colspan="2">';t+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-classes">CSS Classes: ( optional )</label>';t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-classes">';t+='<td colspan="2">';t+='<input type="text" property="classes" value="'+a(B.classes)+'" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-classes" /><br />';t+="<small>Example: <code>my-style-1 my-style-2</code></small>";t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer"><td colspan="2">&nbsp;</td></tr>';t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-styles">';t+='<td colspan="2">';t+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-styles">CSS Styles: ( optional )</label>';t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-styles">';t+='<td colspan="2">';t+='<input type="text" property="styles" value="'+a(B.styles)+'" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-styles" /><br />';t+="<small>Example: <code>color:#000000; background:#FFFFFF;</code></small>";t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer"><td colspan="2">&nbsp;</td></tr>';t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-attrs">';t+='<td colspan="2">';t+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-attrs">Other Attributes: ( optional )</label>';t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-attrs">';t+='<td colspan="2">';t+='<input type="text" property="attrs" value="'+a(B.attrs)+'" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-attrs" /><br />';t+='<small>Example: <code>onkeyup="" onblur=""</code></small>';t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer"><td colspan="2">&nbsp;</td></tr>';t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-buttons">';t+='<td align="left">';t+='<input type="button" value="Cancel" onclick="ws_plugin__s2member_customRegFieldCancel();" />';t+="</td>";t+='<td align="right">';t+='<input type="button" value="'+((u)?"Update This Field":"Create Registration Field")+'" onclick="'+((u)?"ws_plugin__s2member_customRegFieldUpdate("+A+");":"ws_plugin__s2member_customRegFieldCreate();")+'" />';t+="</td>";t+="</tr>";t+="</tbody>";t+="</table>";t+="<div>";b("body").append(t);tb_show(((u)?"Editing Registration Field":"New Custom Registration Field"),"#TB_inline?inlineId=ws-plugin--s2member-custom-reg-field-configuration-thickbox-tools-form");b(window).trigger("resize"),b("table#ws-plugin--s2member-custom-reg-field-configuration-tools-form").show()}i.html(z)};var e=function(){b(window).resize(function(){var s,t;s=b(window).width(),t=b(window).height(),s=(s>720)?720:s;b("#TB_ajaxContent").css({width:s-50,height:t-75,margin:0,padding:0})})};var p=function(){var s=l.length,v=0,w,u="",t="o";u+="<tbody>";u+="<tr>";u+="<th>Order</th>";u+="<th>Field Type</th>";u+="<th>Unique ID</th>";u+="<th>Required</th>";u+="<th>Levels</th>";u+="<th>- Tools -</th>";u+="</tr>";if(l.length>0){for(v=0;v<l.length;v++){t=(t==="o")?"e":"o";w=l[v];u+='<tr class="'+a(t)+" ws-plugin--s2member-custom-reg-field-configuration-table-row-"+v+'">';u+='<td nowrap="nowrap"><a class="ws-plugin--s2member-custom-reg-field-configuration-move-up" href="#" onclick="ws_plugin__s2member_customRegFieldMoveUp('+v+'); return false;"></a><a class="ws-plugin--s2member-custom-reg-field-configuration-move-down" href="#" onclick="ws_plugin__s2member_customRegFieldMoveDown('+v+'); return false;"></a></td>';u+='<td nowrap="nowrap">'+esc_html(g(w.type))+"</td>";u+='<td nowrap="nowrap">'+esc_html(w.id)+"</td>";u+='<td nowrap="nowrap">'+esc_html(w.required)+"</td>";u+='<td nowrap="nowrap">'+esc_html(w.levels)+"</td>";u+='<td nowrap="nowrap"><a class="ws-plugin--s2member-custom-reg-field-configuration-edit" href="#" onclick="ws_plugin__s2member_customRegFieldEdit('+v+'); return false;"></a><a class="ws-plugin--s2member-custom-reg-field-configuration-delete" href="#" onclick="ws_plugin__s2member_customRegFieldDelete('+v+'); return false;"></a></td>';u+="</tr>"}}else{u+="<tr>";u+='<td colspan="6">No Custom Fields are configured.</td>';u+="</tr>"}u+="</tbody>";o.html(u)};j(),e(),p()})()}b("input#ws-plugin--s2member-ip-restrictions-reset-button").click(function(){var c=b(this);c.val("one moment please ...");b.post(ajaxurl,{action:"ws_plugin__s2member_delete_reset_all_ip_restrictions_via_ajax",ws_plugin__s2member_delete_reset_all_ip_restrictions_via_ajax:'<?php echo ws_plugin__s2member_esc_sq (wp_create_nonce ("ws-plugin--s2member-delete-reset-all-ip-restrictions-via-ajax")); ?>'},function(d){alert("s2Member's IP Restriction Logs have all been reset."),c.val("Reset IP Restriction Logs")});return false})}else{if(location.href.match(/page\=ws-plugin--s2member-paypal-ops/)){b("select#ws-plugin--s2member-auto-eot-system-enabled").change(function(){var d=b(this),e=d.val();var c=b("p#ws-plugin--s2member-auto-eot-system-enabled-via-cron");if(e==2){c.show()}else{c.hide()}})}else{if(location.href.match(/page\=ws-plugin--s2member-els-ops/)){b("select#ws-plugin--s2member-custom-reg-opt-in").change(function(){var e=b(this),f=e.val();var d=b("tr.ws-plugin--s2member-custom-reg-opt-in-label-row");var c=b("img.ws-plugin--s2member-custom-reg-opt-in-label-prev-img");if(f<=0){d.css("display","none"),c.attr("src",c.attr("src").replace(/\/checked\.png$/,"/unchecked.png"))}else{if(f==1){d.css("display",""),c.attr("src",c.attr("src").replace(/\/unchecked\.png$/,"/checked.png"))}else{if(f==2){d.css("display",""),c.attr("src",c.attr("src").replace(/\/checked\.png$/,"/unchecked.png"))}}}})}else{if(location.href.match(/page\=ws-plugin--s2member-paypal-buttons/)){b("select#ws-plugin--s2member-level1-term, select#ws-plugin--s2member-level2-term, select#ws-plugin--s2member-level3-term, select#ws-plugin--s2member-level4-term, select#ws-plugin--s2member-modification-term").change(function(){var d=this.id.replace(/^ws-plugin--s2member-(.+?)-term$/g,"$1");var c=(b(this).val().split("-")[2].replace(/[^0-1BN]/g,"")==="BN")?1:0;b("p#ws-plugin--s2member-"+d+"-trial-line").css("display",(c?"none":""));b("span#ws-plugin--s2member-"+d+"-trial-then").css("display",(c?"none":""));b("span#ws-plugin--s2member-"+d+"-20p-rule").css("display",(c?"none":""));(c)?b("input#ws-plugin--s2member-"+form+"-trial-period").val(0):null});b("input#ws-plugin--s2member-level1-ccaps, input#ws-plugin--s2member-level2-ccaps, input#ws-plugin--s2member-level3-ccaps, input#ws-plugin--s2member-level4-ccaps, input#ws-plugin--s2member-modification-ccaps").keyup(function(){if(this.value.match(/[^a-z_0-9,]/)){this.value=b.trim(b.trim(this.value).replace(/[ \-]/g,"_").replace(/[^A-Z_0-9,]/gi,"").toLowerCase())}});ws_plugin__s2member_paypalButtonGenerate=function(f){var c='[s2Member-PayPal-Button %%attrs%% image="default" /]',r="",u={};u.level0='<?php echo ws_plugin__s2member_esc_sq ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level0_label"]); ?>';u.level1='<?php echo ws_plugin__s2member_esc_sq ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_label"]); ?>';u.level2='<?php echo ws_plugin__s2member_esc_sq ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_label"]); ?>';u.level3='<?php echo ws_plugin__s2member_esc_sq ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_label"]); ?>';u.level4='<?php echo ws_plugin__s2member_esc_sq ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_label"]); ?>';var o=b("input#ws-plugin--s2member-"+f+"-shortcode");var g=b("textarea#ws-plugin--s2member-"+f+"-button");var k=b("select#ws-plugin--s2member-modification-level");var h=(f==="modification")?k.val().split(":",2)[1]:f.replace(/^level/,"");var l=u["level"+h].replace(/"/g,"");var p=b("input#ws-plugin--s2member-"+f+"-trial-amount").val().replace(/[^0-9\.]/g,"");var d=b("input#ws-plugin--s2member-"+f+"-trial-period").val().replace(/[^0-9]/g,"");var j=b("select#ws-plugin--s2member-"+f+"-trial-term").val().replace(/[^A-Z]/g,"");var m=b("input#ws-plugin--s2member-"+f+"-amount").val().replace(/[^0-9\.]/g,"");var t=b("select#ws-plugin--s2member-"+f+"-term").val().split("-")[0].replace(/[^0-9]/g,"");var v=b("select#ws-plugin--s2member-"+f+"-term").val().split("-")[1].replace(/[^A-Z]/g,"");var s=b("select#ws-plugin--s2member-"+f+"-term").val().split("-")[2].replace(/[^0-1BN]/g,"");var e=b.trim(b("input#ws-plugin--s2member-"+f+"-page-style").val().replace(/"/g,""));var i=b("select#ws-plugin--s2member-"+f+"-currency").val().replace(/[^A-Z]/g,"");var n=b.trim(b.trim(b("input#ws-plugin--s2member-"+f+"-ccaps").val()).replace(/[ \-]/g,"_").replace(/[^A-Z_0-9,]/gi,"").toLowerCase());d=(s==="BN")?"0":d;p=(!p||isNaN(p)||p<0.01||d<=0)?"0":p;var q=(s==="BN"&&v!=="L")?h+":"+n+":"+t+" "+v:h+":"+n;q=q.replace(/\:+$/g,"");if(p&&(isNaN(p)||p<0)){alert("Oops, a slight problem:\n\nWhen provided, Trial Amount must be >= 0.00");return false}else{if(p&&p>10000){alert("Oops, a slight problem:\n\nMaximum Trial Amount is: 10000.00");return false}else{if(j==="D"&&d>7){alert("Oops, a slight problem:\n\nMaximum Free Days is: 7.\nIf you want to offer more than 7 days free, please choose Weeks or Months from the drop-down.");return false}else{if(j==="W"&&d>52){alert("Oops, a slight problem:\n\nMaximum Free Weeks is: 52.\nIf you want to offer more than 52 weeks free, please choose Months from the drop-down.");return false}else{if(j==="M"&&d>12){alert("Oops, a slight problem:\n\nMaximum Free Months is: 12.\nIf you want to offer more than 12 months free, please choose Years from the drop-down.");return false}else{if(j==="Y"&&d>1){alert("Oops, a slight problem:\n\nMax Trial Period Years is: 1. *This is a PayPal® limitation.");return false}else{if(!m||isNaN(m)||m<0.01){alert("Oops, a slight problem:\n\nAmount must be >= 0.01");return false}else{if(m>10000){alert("Oops, a slight problem:\n\nMaximum amount is: 10000.00");return false}}}}}}}}g.val(g.val().replace(/ \<\!--(\<input type\="hidden" name\="(amount|src|sra|a1|p1|t1|a3|p3|t3)" value\="(.*?)" \/\>)--\>/g," $1"));(parseInt(d)<=0)?g.val(g.val().replace(/ (\<input type\="hidden" name\="(a1|p1|t1)" value\="(.*?)" \/\>)/g," <!--$1-->")):null;(s==="BN")?g.val(g.val().replace(/ (\<input type\="hidden" name\="cmd" value\=")(.*?)(" \/\>)/g," $1_xclick$3")):null;(s==="BN")?g.val(g.val().replace(/ (\<input type\="hidden" name\="(src|sra|a1|p1|t1|a3|p3|t3)" value\="(.*?)" \/\>)/g," <!--$1-->")):null;(s!=="BN")?g.val(g.val().replace(/ (\<input type\="hidden" name\="cmd" value\=")(.*?)(" \/\>)/g," $1_xclick-subscriptions$3")):null;(s!=="BN")?g.val(g.val().replace(/ (\<input type\="hidden" name\="amount" value\="(.*?)" \/\>)/g," <!--$1-->")):null;r+='level="'+a(h)+'" ccaps="'+a(n)+'" desc="'+a(l)+'" ps="'+a(e)+'" cc="'+a(i)+'" ns="1" custom="<?php echo esc_attr ($_SERVER["HTTP_HOST"]); ?>"';r+=' ta="'+a(p)+'" tp="'+a(d)+'" tt="'+a(j)+'" ra="'+a(m)+'" rp="'+a(t)+'" rt="'+a(v)+'" rr="'+a(s)+'"';r+=(f==="modification")?' modify="1"':"";o.val(c.replace(/%%attrs%%/,r));g.val(g.val().replace(/ name\="item_name" value\="(.*?)"/,' name="item_name" value="'+a(l)+'"'));g.val(g.val().replace(/ name\="item_number" value\="(.*?)"/,' name="item_number" value="'+a(q)+'"'));g.val(g.val().replace(/ name\="page_style" value\="(.*?)"/,' name="page_style" value="'+a(e)+'"'));g.val(g.val().replace(/ name\="currency_code" value\="(.*?)"/,' name="currency_code" value="'+a(i)+'"'));g.val(g.val().replace(/ name\="custom" value\="(.*?)"/,' name="custom" value="<?php echo esc_attr ($_SERVER["HTTP_HOST"]); ?>"'));g.val(g.val().replace(/ name\="modify" value\="(.*?)"/,' name="modify" value="'+((f==="modification")?"1":"0")+'"'));g.val(g.val().replace(/ name\="amount" value\="(.*?)"/,' name="amount" value="'+a(m)+'"'));g.val(g.val().replace(/ name\="src" value\="(.*?)"/,' name="src" value="'+a(s)+'"'));g.val(g.val().replace(/ name\="a1" value\="(.*?)"/,' name="a1" value="'+a(p)+'"'));g.val(g.val().replace(/ name\="p1" value\="(.*?)"/,' name="p1" value="'+a(d)+'"'));g.val(g.val().replace(/ name\="t1" value\="(.*?)"/,' name="t1" value="'+a(j)+'"'));g.val(g.val().replace(/ name\="a3" value\="(.*?)"/,' name="a3" value="'+a(m)+'"'));g.val(g.val().replace(/ name\="p3" value\="(.*?)"/,' name="p3" value="'+a(t)+'"'));g.val(g.val().replace(/ name\="t3" value\="(.*?)"/,' name="t3" value="'+a(v)+'"'));b("div#ws-plugin--s2member-"+f+"-button-prev").html(g.val().replace(/\<form/,'<form target="_blank"').replace(/\<\?php echo S2MEMBER_CURRENT_USER_VALUE_FOR_PP_(ON0|OS0); \?\>/g,""));(f==="modification")?alert("Your Modification Button has been generated.\nPlease copy/paste the Shortcode Format into your Login Welcome Page, or wherever you feel it would be most appropriate."):alert("Your Button has been generated.\nPlease copy/paste the Shortcode Format into your Membership Options Page.");o.each(function(){this.focus(),this.select()});return false};ws_plugin__s2member_paypalSpButtonGenerate=function(){var q='[s2Member-PayPal-Button %%attrs%% image="default" /]',p="";var n=b("input#ws-plugin--s2member-sp-shortcode");var e=b("textarea#ws-plugin--s2member-sp-button");var f=b("select#ws-plugin--s2member-sp-leading-id").val().replace(/[^0-9]/g,"");var h=b("select#ws-plugin--s2member-sp-additional-ids").val()||[];var o=b("select#ws-plugin--s2member-sp-hours").val().replace(/[^0-9]/g,"");var k=b("input#ws-plugin--s2member-sp-amount").val().replace(/[^0-9\.]/g,"");var j=b.trim(b("input#ws-plugin--s2member-sp-desc").val().replace(/"/g,""));var m=b.trim(b("input#ws-plugin--s2member-sp-page-style").val().replace(/"/g,""));var d=b("select#ws-plugin--s2member-sp-currency").val().replace(/[^A-Z]/g,"");if(!f){alert("Oops, a slight problem:\n\nPlease select a Leading Post/Page.\n\n*Tip* If there are no Posts/Pages in the menu, it's because you've not configured s2Member for Specific Post/Page Access yet. See: s2Member -> General Options -> Specific Post/Page Access Restrictions.");return false}else{if(!k||isNaN(k)||k<0.01){alert("Oops, a slight problem:\n\nAmount must be >= 0.01");return false}else{if(k>10000){alert("Oops, a slight problem:\n\nMaximum amount is: 10000.00");return false}else{if(!j){alert("Oops, a slight problem:\n\nPlease type a Description for this Button.");return false}}}}for(var g=0,c=f;g<h.length;g++){if(h[g]&&h[g]!==f){c+=","+h[g]}}var l="sp:"+c+":"+o;p+='ids="'+a(c)+'" exp="'+a(o)+'" desc="'+a(j)+'" ps="'+a(m)+'" cc="'+a(d)+'" ns="1"';p+=' custom="<?php echo esc_attr ($_SERVER["HTTP_HOST"]); ?>" ra="'+a(k)+'" sp="1"';n.val(q.replace(/%%attrs%%/,p));e.val(e.val().replace(/ name\="item_name" value\="(.*?)"/,' name="item_name" value="'+a(j)+'"'));e.val(e.val().replace(/ name\="item_number" value\="(.*?)"/,' name="item_number" value="'+a(l)+'"'));e.val(e.val().replace(/ name\="page_style" value\="(.*?)"/,' name="page_style" value="'+a(m)+'"'));e.val(e.val().replace(/ name\="currency_code" value\="(.*?)"/,' name="currency_code" value="'+a(d)+'"'));e.val(e.val().replace(/ name\="custom" value\="(.*?)"/,' name="custom" value="<?php echo esc_attr ($_SERVER["HTTP_HOST"]); ?>"'));e.val(e.val().replace(/ name\="amount" value\="(.*?)"/,' name="amount" value="'+a(k)+'"'));b("div#ws-plugin--s2member-sp-button-prev").html(e.val().replace(/\<form/,'<form target="_blank"'));alert("Your Button has been generated.\nPlease copy/paste the Shortcode Format into your Membership Options Page.");n.each(function(){this.focus(),this.select()});return false};ws_plugin__s2member_paypalSpLinkGenerate=function(){var j=b("select#ws-plugin--s2member-sp-link-leading-id").val().replace(/[^0-9]/g,"");var h=b("select#ws-plugin--s2member-sp-link-additional-ids").val()||[];var c=b("select#ws-plugin--s2member-sp-link-hours").val().replace(/[^0-9]/g,"");var d=b("p#ws-plugin--s2member-sp-link"),g=b("img#ws-plugin--s2member-sp-link-loading");if(!j){alert("Oops, a slight problem:\n\nPlease select a Leading Post/Page.\n\n*Tip* If there are no Posts/Pages in the menu, it's because you've not configured s2Member for Specific Post/Page Access yet. See: s2Member -> General Options -> Specific Post/Page Access Restrictions.");return false}for(var e=0,f=j;e<h.length;e++){if(h[e]&&h[e]!==j){f+=","+h[e]}}d.hide(),g.show(),b.post(ajaxurl,{action:"ws_plugin__s2member_sp_access_link_via_ajax",ws_plugin__s2member_sp_access_link_via_ajax:'<?php echo ws_plugin__s2member_esc_sq (wp_create_nonce ("ws-plugin--s2member-sp-access-link-via-ajax")); ?>',s2member_sp_access_link_ids:f,s2member_sp_access_link_hours:c},function(i){d.show().html('<a href="'+a(i)+'" target="_blank" rel="external">'+esc_html(i)+"</a>"),g.hide()});return false}}}}}}});
1
+ jQuery(document).ready(function(b){var a=esc_html=function(c){return String(c).replace(/"/g,"&quot;").replace(/\</g,"&lt;").replace(/\>/g,"&gt;")};if(location.href.match(/page\=ws-plugin--s2member-mms-options/)){b("select#ws-plugin--s2member-mms-registration-file").change(function(){if(b(this).val()==="wp-signup"){b("div#ws-plugin--s2member-mms-registration-support-package-details-wrapper").show(),b("div.ws-plugin--s2member-mms-registration-wp-login, table.ws-plugin--s2member-mms-registration-wp-login").hide(),b("div.ws-plugin--s2member-mms-registration-wp-signup, table.ws-plugin--s2member-mms-registration-wp-signup").show()}else{if(b(this).val()==="wp-login"){b("div#ws-plugin--s2member-mms-registration-support-package-details-wrapper").hide(),b("div.ws-plugin--s2member-mms-registration-wp-login, table.ws-plugin--s2member-mms-registration-wp-login").show(),b("div.ws-plugin--s2member-mms-registration-wp-signup, table.ws-plugin--s2member-mms-registration-wp-signup").hide()}}b("div.ws-plugin--s2member-mms-registration-wp-signup-blogs-level0, table.ws-plugin--s2member-mms-registration-wp-signup-blogs-level0")[((b("select#ws-plugin--s2member-mms-registration-grants").val()==="all")?"show":"hide")](),b("input#ws-plugin--s2member-mms-registration-blogs-level0").val(((b("select#ws-plugin--s2member-mms-registration-grants").val()==="all")?"1":"0"))}).trigger("change");b("select#ws-plugin--s2member-mms-registration-grants").change(function(){b("select#ws-plugin--s2member-mms-registration-file").trigger("change")})}else{if(location.href.match(/page\=ws-plugin--s2member-options/)){ws_plugin__s2member_generateSecurityKey=function(){var f=function(h,g){h=(arguments.length<1)?0:h;g=(arguments.length<2)?2147483647:g;return Math.floor(Math.random()*(g-h+1))+h};var e="ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()";for(var d=0,c="";d<56;d++){c+=e.substr(f(0,e.length-1),1)}b("input#ws-plugin--s2member-sec-encryption-key").val(c);return false};ws_plugin__s2member_enableSecurityKey=function(){if(confirm("Edit Key? Are you sure?\nThis could break your installation!\n\n*Note* If you've been testing s2Member, feel free to change this Key before you go live. Just don't go live, and then change it. You'll have some very unhappy Customers. Data corruption WILL occur!\n\nFor your safety, s2Member keeps a history of the last 10 Keys that you've used. If you get yourself into a real situation, s2Member will let you revert back to a previous Key.")){b("input#ws-plugin--s2member-sec-encryption-key").attr("disabled",false)}return false};ws_plugin__s2member_securityKeyHistory=function(){b("div#ws-plugin--s2member-sec-encryption-key-history").toggle();return false};if(b("input#ws-plugin--s2member-custom-reg-fields").length&&b("div#ws-plugin--s2member-custom-reg-field-configuration").length){(function(){var c=b("input#ws-plugin--s2member-custom-reg-fields");var f=b("div#ws-plugin--s2member-custom-reg-field-configuration");var l=(c.val())?b.JSON.parse(c.val()):[];l=(l instanceof Array)?l:[];var k='<div id="ws-plugin--s2member-custom-reg-field-configuration-tools"></div>';var r='<table id="ws-plugin--s2member-custom-reg-field-configuration-table"></table>';f.html(k+r);var i=b("div#ws-plugin--s2member-custom-reg-field-configuration-tools");var o=b("table#ws-plugin--s2member-custom-reg-field-configuration-table");ws_plugin__s2member_customRegFieldTypeChange=function(t){var s,v,u=b(t).val();s="tr.ws-plugin--s2member-custom-reg-field-configuration-tools-form-options";v="tr.ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected";if(u.match(/^(text|textarea|checkbox|pre_checkbox)$/)){b(s).css("display","none"),b(s).prev("tr").css("display","none")}else{b(s).css("display",""),b(s).prev("tr").css("display","")}if(u.match(/^(select|selects|checkboxes|radios)$/)){b(v).css("display","none"),b(v).prev("tr").css("display","none")}else{b(v).css("display",""),b(v).prev("tr").css("display","")}};ws_plugin__s2member_customRegFieldDelete=function(t){var s=new Array();for(var u=0;u<l.length;u++){if(u!==t){s.push(l[u])}}l=s,q(),p()};ws_plugin__s2member_customRegFieldMoveUp=function(u){if(typeof l[u]==="object"&&typeof l[u-1]==="object"){var t=l[u-1],s=l[u];l[u-1]=s,l[u]=t;q(),p()}};ws_plugin__s2member_customRegFieldMoveDown=function(u){if(typeof l[u]==="object"&&typeof l[u+1]==="object"){var s=l[u+1],t=l[u];l[u+1]=t,l[u]=s;q(),p()}};ws_plugin__s2member_customRegFieldCreate=function(){var s=b("table#ws-plugin--s2member-custom-reg-field-configuration-tools-form"),t={};b(':input[property!=""]',s).each(function(){var v=b(this),u=v.attr("property"),w=b.trim(v.val());t[u]=w});if((t=d(t))){l.push(t),q(),j(),p(),n();setTimeout(function(){var u="tr.ws-plugin--s2member-custom-reg-field-configuration-table-row-"+(l.length-1);alert('Field created successfully.\n* Remember to "Save Changes".');b(u).effect("highlight",1000)},500)}};ws_plugin__s2member_customRegFieldUpdate=function(t){var s=b("table#ws-plugin--s2member-custom-reg-field-configuration-tools-form"),u={};b(':input[property!=""]',s).each(function(){var x=b(this),w=x.attr("property"),y=b.trim(x.val());u[w]=y});if((u=d(u,t))){l[t]=u,q(),j(),p(),n();var v="tr.ws-plugin--s2member-custom-reg-field-configuration-table-row-"+t;b(v).effect("highlight",1000)}};ws_plugin__s2member_customRegFieldAdd=function(){j(true)};ws_plugin__s2member_customRegFieldEdit=function(s){j(false,s),n()};ws_plugin__s2member_customRegFieldCancel=function(){j(),n()};var d=function(w,u){var s=(typeof u==="number"&&typeof l[u]==="object")?true:false,x=[],t,v;if(typeof w!=="object"){x.push("Invalid field object. Please try again.")}else{if(!w.id){x.push("Unique Field ID:\nThis is required. Please try again.")}else{if(h(w.id)&&(!s||w.id!==l[u].id)){x.push("Unique Field ID:\nThat Field ID already exists. Please try again.")}}if(!w.label){x.push("Field Label/Description:\nThis is required. Please try again.")}if(w.type.match(/^(select|selects|checkboxes|radios)$/)){w.expected="";if(!w.options){x.push("Option Configuration File:\nThis is required. Please try again.")}else{t=w.options.split(/[\r\n]+/);for(v=0;v<t.length;v++){t[v]=b.trim(t[v]);if(!t[v].match(/^([^\|]*)(\|)([^\|]*)(\|default)?$/)){x.push("Option Configuration File:\nInvalid configuration at line #"+(v+1)+".");break}}w.options=b.trim(t.join("\n"))}}else{w.options=""}if(!(w.levels=w.levels.replace(/ /g,""))){x.push("Applicable Levels:\nThis is required. Please try again.")}else{if(!w.levels.match(/^(all|[0-9,]+)$/)){x.push("Applicable Levels:\nShould be comma delimited Levels, or just type: all.\n( examples: 0,1,2,3,4 or type the word: all )")}}if(w.classes&&w.classes.match(/[^a-z 0-9 _ \-]/i)){x.push("CSS Classes:\nContains invalid characters. Please try again.\n( only: alphanumerics, underscores, hyphens, spaces )")}if(w.styles&&w.styles.match(/["\=\>\<]/)){x.push('CSS Styles:\nContains invalid characters. Please try again.\n( do NOT use these characters: = " < > )')}if(w.attrs&&w.attrs.match(/[\>\<]/)){x.push("Other Attributes:\nContains invalid characters. Please try again.\n( do NOT use these characters: < > )")}}if(x.length>0){alert(x.join("\n\n"));return false}else{return w}};var q=function(){c.val(((l.length>0)?b.JSON.stringify(l):""))};var m=function(s){return(typeof s==="string")?b.trim(s).toLowerCase().replace(/[^a-z0-9]/g,"_"):""};var g=function(t){var s={text:"Text ( single line )",textarea:"Textarea ( multi-line )",select:"Select Menu ( drop-down )",selects:"Select Menu ( multi-option )",checkbox:"Checkbox ( single )",pre_checkbox:"Checkbox ( pre-checked )",checkboxes:"Checkboxes ( multi-option )",radios:"Radio Buttons ( multi-option )"};if(typeof s[t]==="string"){return s[t]}return""};var h=function(s){for(var t=0;t<l.length;t++){if(l[t].id===s){return true}}};var n=function(){scrollTo(0,b("div.ws-plugin--s2member-custom-reg-fields-section").offset()["top"]-100)};var j=function(s,A){var x=0,z="",t="",D=0,y=0,v={id:"",label:"",type:"text",options:"",expected:"",required:"yes",levels:"all",editable:"yes",classes:"",styles:"",attrs:""};var u=(typeof A==="number"&&typeof l[A]==="object")?true:false,C=(s||u)?true:false,B=(u)?l[A]:v;z+='<a href="#" onclick="ws_plugin__s2member_customRegFieldAdd(); return false;">Add New Field</a>';tb_remove(),b("div#ws-plugin--s2member-custom-reg-field-configuration-thickbox-tools-form").remove();if(C){t+='<div id="ws-plugin--s2member-custom-reg-field-configuration-thickbox-tools-form">';t+='<table id="ws-plugin--s2member-custom-reg-field-configuration-tools-form">';t+="<tbody>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-type">';t+='<td colspan="2">';t+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-type">Form Field Type: *</label>';t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-type">';t+='<td colspan="2">';t+='<select property="type" onchange="ws_plugin__s2member_customRegFieldTypeChange(this);" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-type">';t+='<option value="text"'+((B.type==="text")?' selected="selected"':"")+'">'+esc_html(g("text"))+"</option>";t+='<option value="textarea"'+((B.type==="textarea")?' selected="selected"':"")+'">'+esc_html(g("textarea"))+"</option>";t+='<option value="select"'+((B.type==="select")?' selected="selected"':"")+'">'+esc_html(g("select"))+"</option>";t+='<option value="selects"'+((B.type==="selects")?' selected="selected"':"")+'">'+esc_html(g("selects"))+"</option>";t+='<option value="checkbox"'+((B.type==="checkbox")?' selected="selected"':"")+'">'+esc_html(g("checkbox"))+"</option>";t+='<option value="pre_checkbox"'+((B.type==="pre_checkbox")?' selected="selected"':"")+'">'+esc_html(g("pre_checkbox"))+"</option>";t+='<option value="checkboxes"'+((B.type==="checkboxes")?' selected="selected"':"")+'">'+esc_html(g("checkboxes"))+"</option>";t+='<option value="radios"'+((B.type==="radios")?' selected="selected"':"")+'">'+esc_html(g("radios"))+"</option>";t+="</select>";t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer"><td colspan="2">&nbsp;</td></tr>';t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-label">';t+='<td colspan="2">';t+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-label">Field Label/Desc: *</label>';t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-label">';t+='<td colspan="2">';t+='<input type="text" property="label" value="'+a(B.label)+'" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-label" /><br />';t+="<small>Examples: <code>Choose Country</code>, <code>Street Address</code></small>";t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer"><td colspan="2">&nbsp;</td></tr>';t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-id">';t+='<td colspan="2">';t+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-id">Unique Field ID: *</label></label>';t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-id">';t+='<td colspan="2">';t+='<input type="text" property="id" value="'+a(B.id)+'" maxlength="25" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-id" /><br />';t+="<small>Examples: <code>country_code</code>, <code>street_address</code></small><br />";t+='<small>e.g. <code>&lt;?php echo get_user_field("country_code"); ?&gt;</code></small>';t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer"><td colspan="2">&nbsp;</td></tr>';t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-required">';t+='<td colspan="2">';t+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-required">Field Required: *</label>';t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-required">';t+='<td colspan="2">';t+='<select property="required" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-required">';t+='<option value="yes"'+((B.required==="yes")?' selected="selected"':"")+'">Yes ( required )</option>';t+='<option value="no"'+((B.required==="no")?' selected="selected"':"")+'">No ( optional )</option>';t+="</select><br />";t+='<small>If <code>yes</code>, only Users/Members will be "required" to enter this field.</small><br />';t+="<small>* Administrators are exempt from this requirement.</small>";t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer"'+((B.type.match(/^(text|textarea|checkbox|pre_checkbox)$/))?' style="display:none;"':"")+'><td colspan="2">&nbsp;</td></tr>';t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-options"'+((B.type.match(/^(text|textarea|checkbox|pre_checkbox)$/))?' style="display:none;"':"")+">";t+='<td colspan="2">';t+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-options">Option Configuration File: * ( one option per line )</label><br />';t+="<small>Use a pipe <code>|</code> delimited format: <code>option value|option label</code></small>";t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-options"'+((B.type.match(/^(text|textarea|checkbox|pre_checkbox)$/))?' style="display:none;"':"")+">";t+='<td colspan="2">';t+='<textarea property="options" rows="3" wrap="off" spellcheck="false" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-options">'+esc_html(B.options)+"</textarea><br />";t+="Here is a quick example:<br />";t+="<small>You can also specify a <em>default</em> option:</small><br />";t+="<code>US|United States|default</code><br />";t+="<code>CA|Canada</code><br />";t+="<code>VI|Virgin Islands (U.S.)</code>";t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer"'+((B.type.match(/^(select|selects|checkboxes|radios)$/))?' style="display:none;"':"")+'><td colspan="2">&nbsp;</td></tr>';t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected"'+((B.type.match(/^(select|selects|checkboxes|radios)$/))?' style="display:none;"':"")+">";t+='<td colspan="2">';t+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected">Expected Format: *</label>';t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected"'+((B.type.match(/^(select|selects|checkboxes|radios)$/))?' style="display:none;"':"")+">";t+='<td colspan="2">';t+='<select property="expected" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected">';t+='<option value=""'+((B.expected==="")?' selected="selected"':"")+'">Anything Goes</option>';t+='<option disabled="disabled"></option>';t+='<optgroup label="Specific Input Types">';t+='<option value="numeric-wp-commas"'+((B.expected==="numeric-wp-commas")?' selected="selected"':"")+'">Numeric ( with or without decimals, commas allowed )</option>';t+='<option value="numeric"'+((B.expected==="numeric")?' selected="selected"':"")+'">Numeric ( with or without decimals, no commas )</option>';t+='<option value="integer"'+((B.expected==="integer")?' selected="selected"':"")+'">Integer ( whole number, without any decimals )</option>';t+='<option value="integer-gt-0"'+((B.expected==="integer-gt-0")?' selected="selected"':"")+'">Integer > 0 ( whole number, no decimals, greater than 0 )</option>';t+='<option value="float"'+((B.expected==="float")?' selected="selected"':"")+'">Float ( floating point number, decimals required )</option>';t+='<option value="float-gt-0"'+((B.expected==="float-gt-0")?' selected="selected"':"")+'">Float > 0 ( floating point number, decimals required, greater than 0 )</option>';t+='<option value="date"'+((B.expected==="date")?' selected="selected"':"")+'">Date ( required date format: dd/mm/yyyy )</option>';t+='<option value="email"'+((B.expected==="email")?' selected="selected"':"")+'">Email ( require valid email )</option>';t+='<option value="url"'+((B.expected==="url")?' selected="selected"':"")+'">Full URL ( starting with http or https )</option>';t+='<option value="domain"'+((B.expected==="domain")?' selected="selected"':"")+'">Domain Name ( domain name only, without http )</option>';t+='<option value="phone"'+((B.expected==="phone")?' selected="selected"':"")+'">Phone # ( 10 digits w/possible hyphens,spaces,brackets )</option>';t+='<option value="uszip"'+((B.expected==="uszip")?' selected="selected"':"")+'">US Zipcode ( 5-9 digits w/possible hyphen )</option>';t+='<option value="cazip"'+((B.expected==="cazip")?' selected="selected"':"")+'">Canadian Zipcode ( 6 alpha-numerics w/possible space )</option>';t+='<option value="uczip"'+((B.expected==="uczip")?' selected="selected"':"")+'">US/Canadian Zipcode ( either a US or Canadian zipcode )</option>';t+="</optgroup>";t+='<option disabled="disabled"></option>';t+='<optgroup label="Any Character Combination">';for(x=1;x<=25;x++){t+='<option value="any-'+x+'"'+((B.expected==="any-"+x)?' selected="selected"':"")+'">Any Character Combination ( '+x+" character minimum )</option>";t+='<option value="any-'+x+'-e"'+((B.expected==="any-"+x+"-e")?' selected="selected"':"")+'">Any Character Combination ( exactly '+x+" character"+((x>1)?"s":"")+" )</option>"}t+="</optgroup>";t+='<option disabled="disabled"></option>';t+='<optgroup label="Alphanumerics, Spaces &amp; Punctuation Only">';for(x=1;x<=25;x++){t+='<option value="alphanumerics-spaces-punctuation-'+x+'"'+((B.expected==="alphanumerics-spaces-punctuation-"+x)?' selected="selected"':"")+'">Alphanumerics, Spaces &amp; Punctuation ( '+x+" character minimum )</option>";t+='<option value="alphanumerics-spaces-punctuation-'+x+'-e"'+((B.expected==="alphanumerics-spaces-punctuation-"+x+"-e")?' selected="selected"':"")+'">Alphanumerics, Spaces &amp; Punctuation ( exactly '+x+" character"+((x>1)?"s":"")+" )</option>"}t+="</optgroup>";t+='<option disabled="disabled"></option>';t+='<optgroup label="Alphanumerics &amp; Spaces Only">';for(x=1;x<=25;x++){t+='<option value="alphanumerics-spaces-'+x+'"'+((B.expected==="alphanumerics-spaces-"+x)?' selected="selected"':"")+'">Alphanumerics &amp; Spaces ( '+x+" character minimum )</option>";t+='<option value="alphanumerics-spaces-'+x+'-e"'+((B.expected==="alphanumerics-spaces-"+x+"-e")?' selected="selected"':"")+'">Alphanumerics &amp; Spaces ( exactly '+x+" character"+((x>1)?"s":"")+" )</option>"}t+="</optgroup>";t+='<option disabled="disabled"></option>';t+='<optgroup label="Alphanumerics &amp; Punctuation Only">';for(x=1;x<=25;x++){t+='<option value="alphanumerics-punctuation-'+x+'"'+((B.expected==="alphanumerics-punctuation-"+x)?' selected="selected"':"")+'">Alphanumerics &amp; Punctuation ( '+x+" character minimum )</option>";t+='<option value="alphanumerics-punctuation-'+x+'-e"'+((B.expected==="alphanumerics-punctuation-"+x+"-e")?' selected="selected"':"")+'">Alphanumerics &amp; Punctuation ( exactly '+x+" character"+((x>1)?"s":"")+" )</option>"}t+="</optgroup>";t+='<option disabled="disabled"></option>';t+='<optgroup label="Alphanumerics Only">';for(x=1;x<=25;x++){t+='<option value="alphanumerics-'+x+'"'+((B.expected==="alphanumerics-"+x)?' selected="selected"':"")+'">Alphanumerics ( '+x+" character minimum )</option>";t+='<option value="alphanumerics-'+x+'-e"'+((B.expected==="alphanumerics-"+x+"-e")?' selected="selected"':"")+'">Alphanumerics ( exactly '+x+" character"+((x>1)?"s":"")+" )</option>"}t+="</optgroup>";t+='<option disabled="disabled"></option>';t+='<optgroup label="Alphabetics Only">';for(x=1;x<=25;x++){t+='<option value="alphabetics-'+x+'"'+((B.expected==="alphabetics-"+x)?' selected="selected"':"")+'">Alphabetics ( '+x+" character minimum )</option>";t+='<option value="alphabetics-'+x+'-e"'+((B.expected==="alphabetics-"+x+"-e")?' selected="selected"':"")+'">Alphabetics ( exactly '+x+" character"+((x>1)?"s":"")+" )</option>"}t+="</optgroup>";t+='<option disabled="disabled"></option>';t+='<optgroup label="Numeric Digits Only">';for(x=1;x<=25;x++){t+='<option value="numerics-'+x+'"'+((B.expected==="numerics-"+x)?' selected="selected"':"")+'">Numeric Digits ( '+x+" digit minimum )</option>";t+='<option value="numerics-'+x+'-e"'+((B.expected==="numerics-"+x+"-e")?' selected="selected"':"")+'">Numeric Digits ( exactly '+x+" digit"+((x>1)?"s":"")+" )</option>"}t+="</optgroup>";t+="</select><br />";t+="<small>Only Users/Members will be required to meet this criteria.</small><br />";t+="<small>* Administrators are exempt from this.</small>";t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer"><td colspan="2">&nbsp;</td></tr>';t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-levels">';t+='<td colspan="2">';t+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-levels">Applicable Membership Levels: *</label>';t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-levels">';t+='<td colspan="2">';t+='<input type="text" property="levels" value="'+a(B.levels)+'" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-levels" /><br />';t+="<small>Please use comma-delimited Level #'s: <code>0,1,2,3,4</code> or type: <code>all</code>.</small><br />";t+="<small>This allows you to enable this field - only at specific Membership Levels.</small>";t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer"><td colspan="2">&nbsp;</td></tr>';t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-editable">';t+='<td colspan="2">';t+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-editable">Allow Profile Edits: *</label>';t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-editable">';t+='<td colspan="2">';t+='<select property="editable" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-editable">';t+='<option value="yes"'+((B.editable==="yes")?' selected="selected"':"")+'">Yes ( editable )</option>';t+='<option value="no"'+((B.editable==="no")?' selected="selected"':"")+'">No ( uneditable after registration )</option>';t+='<option value="no-invisible"'+((B.editable==="no-invisible")?' selected="selected"':"")+'">No ( uneditable &amp; totally invisible )</option>';t+="</select><br />";t+="<small>If <code>No</code>, this field will be un-editable after registration.</small><br />";t+="<small>* Administrators are exempt from this.</small>";t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer"><td colspan="2">&nbsp;</td></tr>';t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-classes">';t+='<td colspan="2">';t+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-classes">CSS Classes: ( optional )</label>';t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-classes">';t+='<td colspan="2">';t+='<input type="text" property="classes" value="'+a(B.classes)+'" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-classes" /><br />';t+="<small>Example: <code>my-style-1 my-style-2</code></small>";t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer"><td colspan="2">&nbsp;</td></tr>';t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-styles">';t+='<td colspan="2">';t+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-styles">CSS Styles: ( optional )</label>';t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-styles">';t+='<td colspan="2">';t+='<input type="text" property="styles" value="'+a(B.styles)+'" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-styles" /><br />';t+="<small>Example: <code>color:#000000; background:#FFFFFF;</code></small>";t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer"><td colspan="2">&nbsp;</td></tr>';t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-attrs">';t+='<td colspan="2">';t+='<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-attrs">Other Attributes: ( optional )</label>';t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-attrs">';t+='<td colspan="2">';t+='<input type="text" property="attrs" value="'+a(B.attrs)+'" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-attrs" /><br />';t+='<small>Example: <code>onkeyup="" onblur=""</code></small>';t+="</td>";t+="</tr>";t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer"><td colspan="2">&nbsp;</td></tr>';t+='<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-buttons">';t+='<td align="left">';t+='<input type="button" value="Cancel" onclick="ws_plugin__s2member_customRegFieldCancel();" />';t+="</td>";t+='<td align="right">';t+='<input type="button" value="'+((u)?"Update This Field":"Create Registration Field")+'" onclick="'+((u)?"ws_plugin__s2member_customRegFieldUpdate("+A+");":"ws_plugin__s2member_customRegFieldCreate();")+'" />';t+="</td>";t+="</tr>";t+="</tbody>";t+="</table>";t+="<div>";b("body").append(t);tb_show(((u)?"Editing Registration Field":"New Custom Registration Field"),"#TB_inline?inlineId=ws-plugin--s2member-custom-reg-field-configuration-thickbox-tools-form");b(window).trigger("resize"),b("table#ws-plugin--s2member-custom-reg-field-configuration-tools-form").show()}i.html(z)};var e=function(){b(window).resize(function(){var s,t;s=b(window).width(),t=b(window).height(),s=(s>720)?720:s;b("#TB_ajaxContent").css({width:s-50,height:t-75,margin:0,padding:0})})};var p=function(){var s=l.length,v=0,w,u="",t="o";u+="<tbody>";u+="<tr>";u+="<th>Order</th>";u+="<th>Field Type</th>";u+="<th>Unique ID</th>";u+="<th>Required</th>";u+="<th>Levels</th>";u+="<th>- Tools -</th>";u+="</tr>";if(l.length>0){for(v=0;v<l.length;v++){t=(t==="o")?"e":"o";w=l[v];u+='<tr class="'+a(t)+" ws-plugin--s2member-custom-reg-field-configuration-table-row-"+v+'">';u+='<td nowrap="nowrap"><a class="ws-plugin--s2member-custom-reg-field-configuration-move-up" href="#" onclick="ws_plugin__s2member_customRegFieldMoveUp('+v+'); return false;"></a><a class="ws-plugin--s2member-custom-reg-field-configuration-move-down" href="#" onclick="ws_plugin__s2member_customRegFieldMoveDown('+v+'); return false;"></a></td>';u+='<td nowrap="nowrap">'+esc_html(g(w.type))+"</td>";u+='<td nowrap="nowrap">'+esc_html(w.id)+"</td>";u+='<td nowrap="nowrap">'+esc_html(w.required)+"</td>";u+='<td nowrap="nowrap">'+esc_html(w.levels)+"</td>";u+='<td nowrap="nowrap"><a class="ws-plugin--s2member-custom-reg-field-configuration-edit" href="#" onclick="ws_plugin__s2member_customRegFieldEdit('+v+'); return false;"></a><a class="ws-plugin--s2member-custom-reg-field-configuration-delete" href="#" onclick="ws_plugin__s2member_customRegFieldDelete('+v+'); return false;"></a></td>';u+="</tr>"}}else{u+="<tr>";u+='<td colspan="6">No Custom Fields are configured.</td>';u+="</tr>"}u+="</tbody>";o.html(u)};j(),e(),p()})()}b("input#ws-plugin--s2member-ip-restrictions-reset-button").click(function(){var c=b(this);c.val("one moment please ...");b.post(ajaxurl,{action:"ws_plugin__s2member_delete_reset_all_ip_restrictions_via_ajax",ws_plugin__s2member_delete_reset_all_ip_restrictions_via_ajax:'<?php echo ws_plugin__s2member_esc_sq (wp_create_nonce ("ws-plugin--s2member-delete-reset-all-ip-restrictions-via-ajax")); ?>'},function(d){alert("s2Member's IP Restriction Logs have all been reset."),c.val("Reset IP Restriction Logs")});return false})}else{if(location.href.match(/page\=ws-plugin--s2member-paypal-ops/)){b("select#ws-plugin--s2member-auto-eot-system-enabled").change(function(){var d=b(this),e=d.val();var c=b("p#ws-plugin--s2member-auto-eot-system-enabled-via-cron");if(e==2){c.show()}else{c.hide()}})}else{if(location.href.match(/page\=ws-plugin--s2member-els-ops/)){b("select#ws-plugin--s2member-custom-reg-opt-in").change(function(){var e=b(this),f=e.val();var d=b("tr.ws-plugin--s2member-custom-reg-opt-in-label-row");var c=b("img.ws-plugin--s2member-custom-reg-opt-in-label-prev-img");if(f<=0){d.css("display","none"),c.attr("src",c.attr("src").replace(/\/checked\.png$/,"/unchecked.png"))}else{if(f==1){d.css("display",""),c.attr("src",c.attr("src").replace(/\/unchecked\.png$/,"/checked.png"))}else{if(f==2){d.css("display",""),c.attr("src",c.attr("src").replace(/\/checked\.png$/,"/unchecked.png"))}}}})}else{if(location.href.match(/page\=ws-plugin--s2member-paypal-buttons/)){b("select#ws-plugin--s2member-level1-term, select#ws-plugin--s2member-level2-term, select#ws-plugin--s2member-level3-term, select#ws-plugin--s2member-level4-term, select#ws-plugin--s2member-modification-term").change(function(){var d=this.id.replace(/^ws-plugin--s2member-(.+?)-term$/g,"$1");var c=(b(this).val().split("-")[2].replace(/[^0-1BN]/g,"")==="BN")?1:0;b("p#ws-plugin--s2member-"+d+"-trial-line").css("display",(c?"none":""));b("span#ws-plugin--s2member-"+d+"-trial-then").css("display",(c?"none":""));b("span#ws-plugin--s2member-"+d+"-20p-rule").css("display",(c?"none":""));(c)?b("input#ws-plugin--s2member-"+form+"-trial-period").val(0):null;(c)?b("input#ws-plugin--s2member-"+form+"-trial-amount").val("0.00"):null});b("input#ws-plugin--s2member-level1-ccaps, input#ws-plugin--s2member-level2-ccaps, input#ws-plugin--s2member-level3-ccaps, input#ws-plugin--s2member-level4-ccaps, input#ws-plugin--s2member-modification-ccaps").keyup(function(){if(this.value.match(/[^a-z_0-9,]/)){this.value=b.trim(b.trim(this.value).replace(/[ \-]/g,"_").replace(/[^A-Z_0-9,]/gi,"").toLowerCase())}});ws_plugin__s2member_paypalButtonGenerate=function(f){var c='[s2Member-PayPal-Button %%attrs%% image="default" output="button" /]',r="",v={};v.level0='<?php echo ws_plugin__s2member_esc_sq ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level0_label"]); ?>';v.level1='<?php echo ws_plugin__s2member_esc_sq ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_label"]); ?>';v.level2='<?php echo ws_plugin__s2member_esc_sq ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_label"]); ?>';v.level3='<?php echo ws_plugin__s2member_esc_sq ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_label"]); ?>';v.level4='<?php echo ws_plugin__s2member_esc_sq ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_label"]); ?>';var o=b("input#ws-plugin--s2member-"+f+"-shortcode");var g=b("textarea#ws-plugin--s2member-"+f+"-button");var k=b("select#ws-plugin--s2member-modification-level");var h=(f==="modification")?k.val().split(":",2)[1]:f.replace(/^level/,"");var l=v["level"+h].replace(/"/g,"");var s=b.trim(b("input#ws-plugin--s2member-"+f+"-desc").val().replace(/"/g,""));var p=b("input#ws-plugin--s2member-"+f+"-trial-amount").val().replace(/[^0-9\.]/g,"");var e=b("input#ws-plugin--s2member-"+f+"-trial-period").val().replace(/[^0-9]/g,"");var j=b("select#ws-plugin--s2member-"+f+"-trial-term").val().replace(/[^A-Z]/g,"");var m=b("input#ws-plugin--s2member-"+f+"-amount").val().replace(/[^0-9\.]/g,"");var u=b("select#ws-plugin--s2member-"+f+"-term").val().split("-")[0].replace(/[^0-9]/g,"");var w=b("select#ws-plugin--s2member-"+f+"-term").val().split("-")[1].replace(/[^A-Z]/g,"");var t=b("select#ws-plugin--s2member-"+f+"-term").val().split("-")[2].replace(/[^0-1BN]/g,"");var d=b.trim(b("input#ws-plugin--s2member-"+f+"-page-style").val().replace(/"/g,""));var i=b("select#ws-plugin--s2member-"+f+"-currency").val().replace(/[^A-Z]/g,"");var n=b.trim(b.trim(b("input#ws-plugin--s2member-"+f+"-ccaps").val()).replace(/[ \-]/g,"_").replace(/[^A-Z_0-9,]/gi,"").toLowerCase());e=(t==="BN")?"0":e;p=(!p||isNaN(p)||p<0.01||e<=0)?"0":p;var q=(t==="BN"&&w!=="L")?h+":"+n+":"+u+" "+w:h+":"+n;q=q.replace(/\:+$/g,"");if(p&&(isNaN(p)||p<0)){alert("Oops, a slight problem:\n\nWhen provided, Trial Amount must be >= 0.00");return false}else{if(p&&p>10000){alert("Oops, a slight problem:\n\nMaximum Trial Amount is: 10000.00");return false}else{if(j==="D"&&e>7){alert("Oops, a slight problem:\n\nMaximum Free Days is: 7.\nIf you want to offer more than 7 days free, please choose Weeks or Months from the drop-down.");return false}else{if(j==="W"&&e>52){alert("Oops, a slight problem:\n\nMaximum Free Weeks is: 52.\nIf you want to offer more than 52 weeks free, please choose Months from the drop-down.");return false}else{if(j==="M"&&e>12){alert("Oops, a slight problem:\n\nMaximum Free Months is: 12.\nIf you want to offer more than 12 months free, please choose Years from the drop-down.");return false}else{if(j==="Y"&&e>1){alert("Oops, a slight problem:\n\nMax Trial Period Years is: 1.");return false}else{if(!m||isNaN(m)||m<0.01){alert("Oops, a slight problem:\n\nAmount must be >= 0.01");return false}else{if(m>10000){alert("Oops, a slight problem:\n\nMaximum amount is: 10000.00");return false}else{if(!s){alert("Oops, a slight problem:\n\nPlease type a Description for this Button.");return false}}}}}}}}}g.html(g.val().replace(/ \<\!--(\<input type\="hidden" name\="(amount|src|sra|a1|p1|t1|a3|p3|t3)" value\="(.*?)" \/\>)--\>/g," $1"));(parseInt(e)<=0)?g.html(g.val().replace(/ (\<input type\="hidden" name\="(a1|p1|t1)" value\="(.*?)" \/\>)/g," <!--$1-->")):null;(t==="BN")?g.html(g.val().replace(/ (\<input type\="hidden" name\="cmd" value\=")(.*?)(" \/\>)/g," $1_xclick$3")):null;(t==="BN")?g.html(g.val().replace(/ (\<input type\="hidden" name\="(src|sra|a1|p1|t1|a3|p3|t3)" value\="(.*?)" \/\>)/g," <!--$1-->")):null;(t!=="BN")?g.html(g.val().replace(/ (\<input type\="hidden" name\="cmd" value\=")(.*?)(" \/\>)/g," $1_xclick-subscriptions$3")):null;(t!=="BN")?g.html(g.val().replace(/ (\<input type\="hidden" name\="amount" value\="(.*?)" \/\>)/g," <!--$1-->")):null;r+='level="'+a(h)+'" ccaps="'+a(n)+'" desc="'+a(s)+'" ps="'+a(d)+'" cc="'+a(i)+'" ns="1" custom="<?php echo ws_plugin__s2member_esc_sq (esc_attr ($_SERVER["HTTP_HOST"])); ?>"';r+=' ta="'+a(p)+'" tp="'+a(e)+'" tt="'+a(j)+'" ra="'+a(m)+'" rp="'+a(u)+'" rt="'+a(w)+'" rr="'+a(t)+'"';r+=(f==="modification")?' modify="1"':"";o.val(c.replace(/%%attrs%%/,r));g.html(g.val().replace(/ name\="item_name" value\="(.*?)"/,' name="item_name" value="'+a(s)+'"'));g.html(g.val().replace(/ name\="item_number" value\="(.*?)"/,' name="item_number" value="'+a(q)+'"'));g.html(g.val().replace(/ name\="page_style" value\="(.*?)"/,' name="page_style" value="'+a(d)+'"'));g.html(g.val().replace(/ name\="currency_code" value\="(.*?)"/,' name="currency_code" value="'+a(i)+'"'));g.html(g.val().replace(/ name\="custom" value\="(.*?)"/,' name="custom" value="<?php echo ws_plugin__s2member_esc_sq (esc_attr ($_SERVER["HTTP_HOST"])); ?>"'));g.html(g.val().replace(/ name\="modify" value\="(.*?)"/,' name="modify" value="'+((f==="modification")?"1":"0")+'"'));g.html(g.val().replace(/ name\="amount" value\="(.*?)"/,' name="amount" value="'+a(m)+'"'));g.html(g.val().replace(/ name\="src" value\="(.*?)"/,' name="src" value="'+a(t)+'"'));g.html(g.val().replace(/ name\="a1" value\="(.*?)"/,' name="a1" value="'+a(p)+'"'));g.html(g.val().replace(/ name\="p1" value\="(.*?)"/,' name="p1" value="'+a(e)+'"'));g.html(g.val().replace(/ name\="t1" value\="(.*?)"/,' name="t1" value="'+a(j)+'"'));g.html(g.val().replace(/ name\="a3" value\="(.*?)"/,' name="a3" value="'+a(m)+'"'));g.html(g.val().replace(/ name\="p3" value\="(.*?)"/,' name="p3" value="'+a(u)+'"'));g.html(g.val().replace(/ name\="t3" value\="(.*?)"/,' name="t3" value="'+a(w)+'"'));b("div#ws-plugin--s2member-"+f+"-button-prev").html(g.val().replace(/\<form/,'<form target="_blank"').replace(/\<\?php echo S2MEMBER_CURRENT_USER_VALUE_FOR_PP_(ON0|OS0); \?\>/g,""));(f==="modification")?alert("Your Modification Button has been generated.\nPlease copy/paste the Shortcode Format into your Login Welcome Page, or wherever you feel it would be most appropriate."):alert("Your Button has been generated.\nPlease copy/paste the Shortcode Format into your Membership Options Page.");o.each(function(){this.focus(),this.select()});return false};ws_plugin__s2member_paypalSpButtonGenerate=function(){var q='[s2Member-PayPal-Button %%attrs%% image="default" output="button" /]',p="";var n=b("input#ws-plugin--s2member-sp-shortcode");var e=b("textarea#ws-plugin--s2member-sp-button");var f=b("select#ws-plugin--s2member-sp-leading-id").val().replace(/[^0-9]/g,"");var h=b("select#ws-plugin--s2member-sp-additional-ids").val()||[];var o=b("select#ws-plugin--s2member-sp-hours").val().replace(/[^0-9]/g,"");var k=b("input#ws-plugin--s2member-sp-amount").val().replace(/[^0-9\.]/g,"");var j=b.trim(b("input#ws-plugin--s2member-sp-desc").val().replace(/"/g,""));var m=b.trim(b("input#ws-plugin--s2member-sp-page-style").val().replace(/"/g,""));var d=b("select#ws-plugin--s2member-sp-currency").val().replace(/[^A-Z]/g,"");if(!f){alert("Oops, a slight problem:\n\nPlease select a Leading Post/Page.\n\n*Tip* If there are no Posts/Pages in the menu, it's because you've not configured s2Member for Specific Post/Page Access yet. See: s2Member -> General Options -> Specific Post/Page Access Restrictions.");return false}else{if(!k||isNaN(k)||k<0.01){alert("Oops, a slight problem:\n\nAmount must be >= 0.01");return false}else{if(k>10000){alert("Oops, a slight problem:\n\nMaximum amount is: 10000.00");return false}else{if(!j){alert("Oops, a slight problem:\n\nPlease type a Description for this Button.");return false}}}}for(var g=0,c=f;g<h.length;g++){if(h[g]&&h[g]!==f){c+=","+h[g]}}var l="sp:"+c+":"+o;p+='ids="'+a(c)+'" exp="'+a(o)+'" desc="'+a(j)+'" ps="'+a(m)+'" cc="'+a(d)+'" ns="1"';p+=' custom="<?php echo ws_plugin__s2member_esc_sq (esc_attr ($_SERVER["HTTP_HOST"])); ?>" ra="'+a(k)+'" sp="1"';n.val(q.replace(/%%attrs%%/,p));e.html(e.val().replace(/ name\="item_name" value\="(.*?)"/,' name="item_name" value="'+a(j)+'"'));e.html(e.val().replace(/ name\="item_number" value\="(.*?)"/,' name="item_number" value="'+a(l)+'"'));e.html(e.val().replace(/ name\="page_style" value\="(.*?)"/,' name="page_style" value="'+a(m)+'"'));e.html(e.val().replace(/ name\="currency_code" value\="(.*?)"/,' name="currency_code" value="'+a(d)+'"'));e.html(e.val().replace(/ name\="custom" value\="(.*?)"/,' name="custom" value="<?php echo ws_plugin__s2member_esc_sq (esc_attr ($_SERVER["HTTP_HOST"])); ?>"'));e.html(e.val().replace(/ name\="amount" value\="(.*?)"/,' name="amount" value="'+a(k)+'"'));b("div#ws-plugin--s2member-sp-button-prev").html(e.val().replace(/\<form/,'<form target="_blank"'));alert("Your Button has been generated.\nPlease copy/paste the Shortcode Format into your Membership Options Page.");n.each(function(){this.focus(),this.select()});return false};ws_plugin__s2member_paypalSpLinkGenerate=function(){var j=b("select#ws-plugin--s2member-sp-link-leading-id").val().replace(/[^0-9]/g,"");var h=b("select#ws-plugin--s2member-sp-link-additional-ids").val()||[];var c=b("select#ws-plugin--s2member-sp-link-hours").val().replace(/[^0-9]/g,"");var d=b("p#ws-plugin--s2member-sp-link"),g=b("img#ws-plugin--s2member-sp-link-loading");if(!j){alert("Oops, a slight problem:\n\nPlease select a Leading Post/Page.\n\n*Tip* If there are no Posts/Pages in the menu, it's because you've not configured s2Member for Specific Post/Page Access yet. See: s2Member -> General Options -> Specific Post/Page Access Restrictions.");return false}for(var e=0,f=j;e<h.length;e++){if(h[e]&&h[e]!==j){f+=","+h[e]}}d.hide(),g.show(),b.post(ajaxurl,{action:"ws_plugin__s2member_sp_access_link_via_ajax",ws_plugin__s2member_sp_access_link_via_ajax:'<?php echo ws_plugin__s2member_esc_sq (wp_create_nonce ("ws-plugin--s2member-sp-access-link-via-ajax")); ?>',s2member_sp_access_link_ids:f,s2member_sp_access_link_hours:c},function(i){d.show().html('<a href="'+a(i)+'" target="_blank" rel="external">'+esc_html(i)+"</a>"),g.hide()});return false}}}}}}});
includes/menu-pages/menu-pages-s.js CHANGED
@@ -10,7 +10,7 @@ If not, see: <http://www.gnu.org/licenses/>.
10
  /*
11
  These routines are all specific to this software.
12
  */
13
- jQuery (document).ready (function($)
14
  {
15
  var esc_attr = esc_html = function(str) /* Convert special characters. */
16
  {
@@ -19,24 +19,24 @@ jQuery (document).ready (function($)
19
  /**/
20
  if (location.href.match (/page\=ws-plugin--s2member-mms-options/))
21
  {
22
- $ ('select#ws-plugin--s2member-mms-registration-file').change (function()
23
  {
24
  if ($ (this).val () === 'wp-signup') /* Expand/collapse relevant options; based on file selection. */
25
  {
26
- $ ('div#ws-plugin--s2member-mms-registration-support-package-details-wrapper').show (), $ ('div.ws-plugin--s2member-mms-registration-wp-login, table.ws-plugin--s2member-mms-registration-wp-login').hide (), $ ('div.ws-plugin--s2member-mms-registration-wp-signup, table.ws-plugin--s2member-mms-registration-wp-signup').show ();
27
  }
28
  else if ($ (this).val () === 'wp-login') /* Expand/collapse relevant options. */
29
  {
30
- $ ('div#ws-plugin--s2member-mms-registration-support-package-details-wrapper').hide (), $ ('div.ws-plugin--s2member-mms-registration-wp-login, table.ws-plugin--s2member-mms-registration-wp-login').show (), $ ('div.ws-plugin--s2member-mms-registration-wp-signup, table.ws-plugin--s2member-mms-registration-wp-signup').hide ();
31
  }
32
  /**/
33
- $ ('div.ws-plugin--s2member-mms-registration-wp-signup-blogs-level0, table.ws-plugin--s2member-mms-registration-wp-signup-blogs-level0')[ ( ($ ('select#ws-plugin--s2member-mms-registration-grants').val () === 'all') ? 'show' : 'hide')] (), $ ('input#ws-plugin--s2member-mms-registration-blogs-level0').val ( ( ($ ('select#ws-plugin--s2member-mms-registration-grants').val () === 'all') ? '1' : '0'));
34
  /**/
35
  }).trigger ('change'); /* Fire on ready too. */
36
  /**/
37
- $ ('select#ws-plugin--s2member-mms-registration-grants').change (function()
38
  {
39
- $ ('select#ws-plugin--s2member-mms-registration-file').trigger ('change');
40
  });
41
  }
42
  /**/
@@ -55,7 +55,7 @@ jQuery (document).ready (function($)
55
  var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()';
56
  for (var i = 0, key = ''; i < 56; i++) key += chars.substr (mt_rand (0, chars.length - 1), 1);
57
  /**/
58
- $ ('input#ws-plugin--s2member-sec-encryption-key').val (key);
59
  /**/
60
  return false;
61
  };
@@ -63,14 +63,14 @@ jQuery (document).ready (function($)
63
  ws_plugin__s2member_enableSecurityKey = function() /* Allow Security Key editing?? */
64
  {
65
  if (confirm ('Edit Key? Are you sure?\nThis could break your installation!\n\n*Note* If you\'ve been testing s2Member, feel free to change this Key before you go live. Just don\'t go live, and then change it. You\'ll have some very unhappy Customers. Data corruption WILL occur!\n\nFor your safety, s2Member keeps a history of the last 10 Keys that you\'ve used. If you get yourself into a real situation, s2Member will let you revert back to a previous Key.'))
66
- $ ('input#ws-plugin--s2member-sec-encryption-key').attr ('disabled', false);
67
  /**/
68
  return false;
69
  };
70
  /**/
71
  ws_plugin__s2member_securityKeyHistory = function() /* Displays history of Keys. */
72
  {
73
- $ ('div#ws-plugin--s2member-sec-encryption-key-history').toggle ();
74
  /**/
75
  return false;
76
  };
@@ -100,15 +100,15 @@ jQuery (document).ready (function($)
100
  tr2 = 'tr.ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected';
101
  /**/
102
  if (type.match (/^(text|textarea|checkbox|pre_checkbox)$/))
103
- $ (tr1).css ('display', 'none'), $ (tr1).prev ('tr').css ('display', 'none');
104
  else /* Otherwise we display the table row by removing the display property. */
105
- $ (tr1).css ('display', ''), $ (tr1).prev ('tr').css ('display', '');
106
  /**/
107
  /**/
108
  if (type.match (/^(select|selects|checkboxes|radios)$/))
109
- $ (tr2).css ('display', 'none'), $ (tr2).prev ('tr').css ('display', 'none');
110
  else /* Otherwise we display the table row by removing the display property. */
111
- $ (tr2).css ('display', ''), $ (tr2).prev ('tr').css ('display', '');
112
  };
113
  /**/
114
  ws_plugin__s2member_customRegFieldDelete = function(index)
@@ -164,8 +164,8 @@ jQuery (document).ready (function($)
164
  setTimeout (function() /* A momentary delay here for usability. */
165
  {
166
  var row = 'tr.ws-plugin--s2member-custom-reg-field-configuration-table-row-' + (fields.length - 1);
167
- alert ('Field created successfully.\n* Remember to "Save Changes".');
168
- $ (row).effect ('highlight', 1000);
169
  }, 500);
170
  }
171
  };
@@ -186,13 +186,13 @@ jQuery (document).ready (function($)
186
  fields[index] = field, updateFields (), buildTools (), buildTable (), scrollReset ();
187
  /**/
188
  var row = 'tr.ws-plugin--s2member-custom-reg-field-configuration-table-row-' + index;
189
- $ (row).effect ('highlight', 1000);
190
  }
191
  };
192
  /**/
193
  ws_plugin__s2member_customRegFieldAdd = function() /* Add new field links. */
194
  {
195
- buildTools (true); /* No need to reset scroll position. */
196
  };
197
  /**/
198
  ws_plugin__s2member_customRegFieldEdit = function(index) /* Edit links. */
@@ -260,7 +260,7 @@ jQuery (document).ready (function($)
260
  field.options = ''; /* Force empty options. */
261
  }
262
  /**/
263
- if (! (field.levels = field.levels.replace (/ /g, '')))
264
  {
265
  errors.push ('Applicable Levels:\nThis is required. Please try again.');
266
  }
@@ -287,7 +287,7 @@ jQuery (document).ready (function($)
287
  /**/
288
  if (errors.length > 0) /* Errors? */
289
  {
290
- alert (errors.join ('\n\n'));
291
  return false;
292
  }
293
  else /* Return. */
@@ -296,7 +296,7 @@ jQuery (document).ready (function($)
296
  /**/
297
  var updateFields = function() /* Update hidden input value. */
298
  {
299
- $fields.val ( ( (fields.length > 0) ? $.JSON.stringify (fields) : ''));
300
  };
301
  /**/
302
  var fieldId2Var = function(fieldId) /* Convert ids to variables. */
@@ -352,14 +352,14 @@ jQuery (document).ready (function($)
352
  form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-type">';
353
  form += '<td colspan="2">';
354
  form += '<select property="type" onchange="ws_plugin__s2member_customRegFieldTypeChange(this);" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-type">';
355
- form += '<option value="text"' + ( (field.type === 'text') ? ' selected="selected"' : '') + '">' + esc_html (fieldTypeDesc ('text')) + '</option>';
356
- form += '<option value="textarea"' + ( (field.type === 'textarea') ? ' selected="selected"' : '') + '">' + esc_html (fieldTypeDesc ('textarea')) + '</option>';
357
- form += '<option value="select"' + ( (field.type === 'select') ? ' selected="selected"' : '') + '">' + esc_html (fieldTypeDesc ('select')) + '</option>';
358
- form += '<option value="selects"' + ( (field.type === 'selects') ? ' selected="selected"' : '') + '">' + esc_html (fieldTypeDesc ('selects')) + '</option>';
359
- form += '<option value="checkbox"' + ( (field.type === 'checkbox') ? ' selected="selected"' : '') + '">' + esc_html (fieldTypeDesc ('checkbox')) + '</option>';
360
- form += '<option value="pre_checkbox"' + ( (field.type === 'pre_checkbox') ? ' selected="selected"' : '') + '">' + esc_html (fieldTypeDesc ('pre_checkbox')) + '</option>';
361
- form += '<option value="checkboxes"' + ( (field.type === 'checkboxes') ? ' selected="selected"' : '') + '">' + esc_html (fieldTypeDesc ('checkboxes')) + '</option>';
362
- form += '<option value="radios"' + ( (field.type === 'radios') ? ' selected="selected"' : '') + '">' + esc_html (fieldTypeDesc ('radios')) + '</option>';
363
  form += '</select>';
364
  form += '</td>';
365
  form += '</tr>';
@@ -406,24 +406,24 @@ jQuery (document).ready (function($)
406
  form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-required">';
407
  form += '<td colspan="2">';
408
  form += '<select property="required" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-required">';
409
- form += '<option value="yes"' + ( (field.required === 'yes') ? ' selected="selected"' : '') + '">Yes ( required )</option>';
410
- form += '<option value="no"' + ( (field.required === 'no') ? ' selected="selected"' : '') + '">No ( optional )</option>';
411
  form += '</select><br />';
412
  form += '<small>If <code>yes</code>, only Users/Members will be "required" to enter this field.</small><br />';
413
  form += '<small>* Administrators are exempt from this requirement.</small>';
414
  form += '</td>';
415
  form += '</tr>';
416
  /**/
417
- form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer"' + ( (field.type.match (/^(text|textarea|checkbox|pre_checkbox)$/)) ? ' style="display:none;"' : '') + '><td colspan="2">&nbsp;</td></tr>';
418
  /**/
419
- form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-options"' + ( (field.type.match (/^(text|textarea|checkbox|pre_checkbox)$/)) ? ' style="display:none;"' : '') + '>';
420
  form += '<td colspan="2">';
421
  form += '<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-options">Option Configuration File: * ( one option per line )</label><br />';
422
  form += '<small>Use a pipe <code>|</code> delimited format: <code>option value|option label</code></small>';
423
  form += '</td>';
424
  form += '</tr>';
425
  /**/
426
- form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-options"' + ( (field.type.match (/^(text|textarea|checkbox|pre_checkbox)$/)) ? ' style="display:none;"' : '') + '>';
427
  form += '<td colspan="2">';
428
  form += '<textarea property="options" rows="3" wrap="off" spellcheck="false" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-options">' + esc_html (field.options) + '</textarea><br />';
429
  form += 'Here is a quick example:<br />';
@@ -434,36 +434,36 @@ jQuery (document).ready (function($)
434
  form += '</td>';
435
  form += '</tr>';
436
  /**/
437
- form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer"' + ( (field.type.match (/^(select|selects|checkboxes|radios)$/)) ? ' style="display:none;"' : '') + '><td colspan="2">&nbsp;</td></tr>';
438
  /**/
439
- form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected"' + ( (field.type.match (/^(select|selects|checkboxes|radios)$/)) ? ' style="display:none;"' : '') + '>';
440
  form += '<td colspan="2">';
441
  form += '<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected">Expected Format: *</label>';
442
  form += '</td>';
443
  form += '</tr>';
444
  /**/
445
- form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected"' + ( (field.type.match (/^(select|selects|checkboxes|radios)$/)) ? ' style="display:none;"' : '') + '>';
446
  form += '<td colspan="2">';
447
  form += '<select property="expected" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected">';
448
  /**/
449
- form += '<option value=""' + ( (field.expected === '') ? ' selected="selected"' : '') + '">Anything Goes</option>';
450
  form += '<option disabled="disabled"></option>';
451
  /**/
452
  form += '<optgroup label="Specific Input Types">';
453
- form += '<option value="numeric-wp-commas"' + ( (field.expected === 'numeric-wp-commas') ? ' selected="selected"' : '') + '">Numeric ( with or without decimals, commas allowed )</option>';
454
- form += '<option value="numeric"' + ( (field.expected === 'numeric') ? ' selected="selected"' : '') + '">Numeric ( with or without decimals, no commas )</option>';
455
- form += '<option value="integer"' + ( (field.expected === 'integer') ? ' selected="selected"' : '') + '">Integer ( whole number, without any decimals )</option>';
456
- form += '<option value="integer-gt-0"' + ( (field.expected === 'integer-gt-0') ? ' selected="selected"' : '') + '">Integer > 0 ( whole number, no decimals, greater than 0 )</option>';
457
- form += '<option value="float"' + ( (field.expected === 'float') ? ' selected="selected"' : '') + '">Float ( floating point number, decimals required )</option>';
458
- form += '<option value="float-gt-0"' + ( (field.expected === 'float-gt-0') ? ' selected="selected"' : '') + '">Float > 0 ( floating point number, decimals required, greater than 0 )</option>';
459
- form += '<option value="date"' + ( (field.expected === 'date') ? ' selected="selected"' : '') + '">Date ( required date format: dd/mm/yyyy )</option>';
460
- form += '<option value="email"' + ( (field.expected === 'email') ? ' selected="selected"' : '') + '">Email ( require valid email )</option>';
461
- form += '<option value="url"' + ( (field.expected === 'url') ? ' selected="selected"' : '') + '">Full URL ( starting with http or https )</option>';
462
- form += '<option value="domain"' + ( (field.expected === 'domain') ? ' selected="selected"' : '') + '">Domain Name ( domain name only, without http )</option>';
463
- form += '<option value="phone"' + ( (field.expected === 'phone') ? ' selected="selected"' : '') + '">Phone # ( 10 digits w/possible hyphens,spaces,brackets )</option>';
464
- form += '<option value="uszip"' + ( (field.expected === 'uszip') ? ' selected="selected"' : '') + '">US Zipcode ( 5-9 digits w/possible hyphen )</option>';
465
- form += '<option value="cazip"' + ( (field.expected === 'cazip') ? ' selected="selected"' : '') + '">Canadian Zipcode ( 6 alpha-numerics w/possible space )</option>';
466
- form += '<option value="uczip"' + ( (field.expected === 'uczip') ? ' selected="selected"' : '') + '">US/Canadian Zipcode ( either a US or Canadian zipcode )</option>';
467
  form += '</optgroup>';
468
  /**/
469
  form += '<option disabled="disabled"></option>';
@@ -471,8 +471,8 @@ jQuery (document).ready (function($)
471
  form += '<optgroup label="Any Character Combination">';
472
  for (i = 1; i <= 25; i++)
473
  {
474
- form += '<option value="any-' + i + '"' + ( (field.expected === 'any-' + i) ? ' selected="selected"' : '') + '">Any Character Combination ( ' + i + ' character minimum )</option>';
475
- form += '<option value="any-' + i + '-e"' + ( (field.expected === 'any-' + i + '-e') ? ' selected="selected"' : '') + '">Any Character Combination ( exactly ' + i + ' character' + ( (i > 1) ? 's' : '') + ' )</option>';
476
  }
477
  form += '</optgroup>';
478
  /**/
@@ -481,8 +481,8 @@ jQuery (document).ready (function($)
481
  form += '<optgroup label="Alphanumerics, Spaces &amp; Punctuation Only">';
482
  for (i = 1; i <= 25; i++)
483
  {
484
- form += '<option value="alphanumerics-spaces-punctuation-' + i + '"' + ( (field.expected === 'alphanumerics-spaces-punctuation-' + i) ? ' selected="selected"' : '') + '">Alphanumerics, Spaces &amp; Punctuation ( ' + i + ' character minimum )</option>';
485
- form += '<option value="alphanumerics-spaces-punctuation-' + i + '-e"' + ( (field.expected === 'alphanumerics-spaces-punctuation-' + i + '-e') ? ' selected="selected"' : '') + '">Alphanumerics, Spaces &amp; Punctuation ( exactly ' + i + ' character' + ( (i > 1) ? 's' : '') + ' )</option>';
486
  }
487
  form += '</optgroup>';
488
  /**/
@@ -491,8 +491,8 @@ jQuery (document).ready (function($)
491
  form += '<optgroup label="Alphanumerics &amp; Spaces Only">';
492
  for (i = 1; i <= 25; i++)
493
  {
494
- form += '<option value="alphanumerics-spaces-' + i + '"' + ( (field.expected === 'alphanumerics-spaces-' + i) ? ' selected="selected"' : '') + '">Alphanumerics &amp; Spaces ( ' + i + ' character minimum )</option>';
495
- form += '<option value="alphanumerics-spaces-' + i + '-e"' + ( (field.expected === 'alphanumerics-spaces-' + i + '-e') ? ' selected="selected"' : '') + '">Alphanumerics &amp; Spaces ( exactly ' + i + ' character' + ( (i > 1) ? 's' : '') + ' )</option>';
496
  }
497
  form += '</optgroup>';
498
  /**/
@@ -501,8 +501,8 @@ jQuery (document).ready (function($)
501
  form += '<optgroup label="Alphanumerics &amp; Punctuation Only">';
502
  for (i = 1; i <= 25; i++)
503
  {
504
- form += '<option value="alphanumerics-punctuation-' + i + '"' + ( (field.expected === 'alphanumerics-punctuation-' + i) ? ' selected="selected"' : '') + '">Alphanumerics &amp; Punctuation ( ' + i + ' character minimum )</option>';
505
- form += '<option value="alphanumerics-punctuation-' + i + '-e"' + ( (field.expected === 'alphanumerics-punctuation-' + i + '-e') ? ' selected="selected"' : '') + '">Alphanumerics &amp; Punctuation ( exactly ' + i + ' character' + ( (i > 1) ? 's' : '') + ' )</option>';
506
  }
507
  form += '</optgroup>';
508
  /**/
@@ -511,8 +511,8 @@ jQuery (document).ready (function($)
511
  form += '<optgroup label="Alphanumerics Only">';
512
  for (i = 1; i <= 25; i++)
513
  {
514
- form += '<option value="alphanumerics-' + i + '"' + ( (field.expected === 'alphanumerics-' + i) ? ' selected="selected"' : '') + '">Alphanumerics ( ' + i + ' character minimum )</option>';
515
- form += '<option value="alphanumerics-' + i + '-e"' + ( (field.expected === 'alphanumerics-' + i + '-e') ? ' selected="selected"' : '') + '">Alphanumerics ( exactly ' + i + ' character' + ( (i > 1) ? 's' : '') + ' )</option>';
516
  }
517
  form += '</optgroup>';
518
  /**/
@@ -521,8 +521,8 @@ jQuery (document).ready (function($)
521
  form += '<optgroup label="Alphabetics Only">';
522
  for (i = 1; i <= 25; i++)
523
  {
524
- form += '<option value="alphabetics-' + i + '"' + ( (field.expected === 'alphabetics-' + i) ? ' selected="selected"' : '') + '">Alphabetics ( ' + i + ' character minimum )</option>';
525
- form += '<option value="alphabetics-' + i + '-e"' + ( (field.expected === 'alphabetics-' + i + '-e') ? ' selected="selected"' : '') + '">Alphabetics ( exactly ' + i + ' character' + ( (i > 1) ? 's' : '') + ' )</option>';
526
  }
527
  form += '</optgroup>';
528
  /**/
@@ -531,8 +531,8 @@ jQuery (document).ready (function($)
531
  form += '<optgroup label="Numeric Digits Only">';
532
  for (i = 1; i <= 25; i++)
533
  {
534
- form += '<option value="numerics-' + i + '"' + ( (field.expected === 'numerics-' + i) ? ' selected="selected"' : '') + '">Numeric Digits ( ' + i + ' digit minimum )</option>';
535
- form += '<option value="numerics-' + i + '-e"' + ( (field.expected === 'numerics-' + i + '-e') ? ' selected="selected"' : '') + '">Numeric Digits ( exactly ' + i + ' digit' + ( (i > 1) ? 's' : '') + ' )</option>';
536
  }
537
  form += '</optgroup>';
538
  /**/
@@ -569,9 +569,9 @@ jQuery (document).ready (function($)
569
  form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-editable">';
570
  form += '<td colspan="2">';
571
  form += '<select property="editable" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-editable">';
572
- form += '<option value="yes"' + ( (field.editable === 'yes') ? ' selected="selected"' : '') + '">Yes ( editable )</option>';
573
- form += '<option value="no"' + ( (field.editable === 'no') ? ' selected="selected"' : '') + '">No ( uneditable after registration )</option>';
574
- form += '<option value="no-invisible"' + ( (field.editable === 'no-invisible') ? ' selected="selected"' : '') + '">No ( uneditable &amp; totally invisible )</option>';
575
  form += '</select><br />';
576
  form += '<small>If <code>No</code>, this field will be un-editable after registration.</small><br />';
577
  form += '<small>* Administrators are exempt from this.</small>';
@@ -630,7 +630,7 @@ jQuery (document).ready (function($)
630
  form += '<input type="button" value="Cancel" onclick="ws_plugin__s2member_customRegFieldCancel();" />';
631
  form += '</td>';
632
  form += '<td align="right">';
633
- form += '<input type="button" value="' + ( (editing) ? 'Update This Field' : 'Create Registration Field') + '" onclick="' + ( (editing) ? 'ws_plugin__s2member_customRegFieldUpdate(' + index + ');' : 'ws_plugin__s2member_customRegFieldCreate();') + '" />';
634
  form += '</td>';
635
  form += '</tr>';
636
  /**/
@@ -639,9 +639,9 @@ jQuery (document).ready (function($)
639
  /**/
640
  form += '<div>';
641
  /**/
642
- $ ('body').append (form);
643
- tb_show ( ( (editing) ? 'Editing Registration Field' : 'New Custom Registration Field'), '#TB_inline?inlineId=ws-plugin--s2member-custom-reg-field-configuration-thickbox-tools-form');
644
- $ (window).trigger ('resize'), $ ('table#ws-plugin--s2member-custom-reg-field-configuration-tools-form').show ();
645
  }
646
  /**/
647
  $tools.html (html);
@@ -649,11 +649,11 @@ jQuery (document).ready (function($)
649
  /**/
650
  var attachTBResizer = function() /* Resize inline #TB_ajaxContent. */
651
  {
652
- $ (window).resize (function()
653
  {
654
  var w, h; /* Initialize width/height vars. */
655
  w = $ (window).width (), h = $ (window).height (), w = (w > 720) ? 720 : w;
656
- $ ('#TB_ajaxContent').css ({'width': w - 50, 'height': h - 75, 'margin': 0, 'padding': 0});
657
  });
658
  };
659
  /**/
@@ -706,14 +706,14 @@ jQuery (document).ready (function($)
706
  }) ();
707
  }
708
  /**/
709
- $ ('input#ws-plugin--s2member-ip-restrictions-reset-button').click (function()
710
  {
711
  var $this = $ (this); /* Save $(this) into $this. */
712
  $this.val ('one moment please ...'); /* Indicate loading status ( please wait ). */
713
  /**/
714
  $.post (ajaxurl, {action: 'ws_plugin__s2member_delete_reset_all_ip_restrictions_via_ajax', ws_plugin__s2member_delete_reset_all_ip_restrictions_via_ajax: '<?php echo ws_plugin__s2member_esc_sq (wp_create_nonce ("ws-plugin--s2member-delete-reset-all-ip-restrictions-via-ajax")); ?>'}, function(response)
715
  {
716
- alert ('s2Member\'s IP Restriction Logs have all been reset.'), $this.val ('Reset IP Restriction Logs');
717
  });
718
  /**/
719
  return false;
@@ -722,7 +722,7 @@ jQuery (document).ready (function($)
722
  /**/
723
  else if (location.href.match (/page\=ws-plugin--s2member-paypal-ops/))
724
  {
725
- $ ('select#ws-plugin--s2member-auto-eot-system-enabled').change (function()
726
  {
727
  var $this = $ (this), val = $this.val ();
728
  var $viaCron = $ ('p#ws-plugin--s2member-auto-eot-system-enabled-via-cron');
@@ -736,7 +736,7 @@ jQuery (document).ready (function($)
736
  /**/
737
  else if (location.href.match (/page\=ws-plugin--s2member-els-ops/))
738
  {
739
- $ ('select#ws-plugin--s2member-custom-reg-opt-in').change (function()
740
  {
741
  var $this = $ (this), val = $this.val ();
742
  var $rows = $ ('tr.ws-plugin--s2member-custom-reg-opt-in-label-row');
@@ -755,17 +755,21 @@ jQuery (document).ready (function($)
755
  /**/
756
  else if (location.href.match (/page\=ws-plugin--s2member-paypal-buttons/))
757
  {
758
- $ ('select#ws-plugin--s2member-level1-term, select#ws-plugin--s2member-level2-term, select#ws-plugin--s2member-level3-term, select#ws-plugin--s2member-level4-term, select#ws-plugin--s2member-modification-term').change (function()
759
  {
760
  var button = this.id.replace (/^ws-plugin--s2member-(.+?)-term$/g, '$1');
 
761
  var trialDisabled = ($ (this).val ().split ('-')[2].replace (/[^0-1BN]/g, '') === 'BN') ? 1 : 0;
762
- $ ('p#ws-plugin--s2member-' + button + '-trial-line').css ('display', (trialDisabled ? 'none' : ''));
763
- $ ('span#ws-plugin--s2member-' + button + '-trial-then').css ('display', (trialDisabled ? 'none' : ''));
764
- $ ('span#ws-plugin--s2member-' + button + '-20p-rule').css ('display', (trialDisabled ? 'none' : ''));
 
 
765
  (trialDisabled) ? $ ('input#ws-plugin--s2member-' + form + '-trial-period').val (0) : null;
 
766
  });
767
  /**/
768
- $ ('input#ws-plugin--s2member-level1-ccaps, input#ws-plugin--s2member-level2-ccaps, input#ws-plugin--s2member-level3-ccaps, input#ws-plugin--s2member-level4-ccaps, input#ws-plugin--s2member-modification-ccaps').keyup (function()
769
  {
770
  if (this.value.match (/[^a-z_0-9,]/)) /* Only if there is a problem; because this causes interruption. */
771
  this.value = $.trim ($.trim (this.value).replace (/[ \-]/g, '_').replace (/[^A-Z_0-9,]/gi, '').toLowerCase ());
@@ -773,7 +777,7 @@ jQuery (document).ready (function($)
773
  /**/
774
  ws_plugin__s2member_paypalButtonGenerate = function(button) /* Handles PayPal® Button Generation. */
775
  {
776
- var shortCodeTemplate = '[s2Member-PayPal-Button %%attrs%% image="default" /]', shortCodeTemplateAttrs = '', labels = {};
777
  /**/
778
  labels['level0'] = '<?php echo ws_plugin__s2member_esc_sq ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level0_label"]); ?>';
779
  labels['level1'] = '<?php echo ws_plugin__s2member_esc_sq ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_label"]); ?>';
@@ -787,6 +791,7 @@ jQuery (document).ready (function($)
787
  /**/
788
  var level = (button === 'modification') ? modLevel.val ().split (':', 2)[1] : button.replace (/^level/, '');
789
  var label = labels['level' + level].replace (/"/g, ""); /* Labels may NOT contain any double-quotes. */
 
790
  /**/
791
  var trialAmount = $ ('input#ws-plugin--s2member-' + button + '-trial-amount').val ().replace (/[^0-9\.]/g, '');
792
  var trialPeriod = $ ('input#ws-plugin--s2member-' + button + '-trial-period').val ().replace (/[^0-9]/g, '');
@@ -801,81 +806,86 @@ jQuery (document).ready (function($)
801
  var currencyCode = $ ('select#ws-plugin--s2member-' + button + '-currency').val ().replace (/[^A-Z]/g, '');
802
  var cCaps = $.trim ($.trim ($ ('input#ws-plugin--s2member-' + button + '-ccaps').val ()).replace (/[ \-]/g, '_').replace (/[^A-Z_0-9,]/gi, '').toLowerCase ());
803
  /**/
804
- trialPeriod = (regRecur === 'BN') ? '0' : trialPeriod; /* Lifetime ( 1-L-BN ) and Buy Now ( BN ) access is absolutely NOT compatible w/ free trials. */
805
- trialAmount = (!trialAmount || isNaN (trialAmount) || trialAmount < 0.01 || trialPeriod <= 0) ? '0' : trialAmount; /* Validate trial amount. */
806
  /**/
807
  var levelCcapsPer = (regRecur === 'BN' && regTerm !== 'L') ? level + ':' + cCaps + ':' + regPeriod + ' ' + regTerm : level + ':' + cCaps;
808
  levelCcapsPer = levelCcapsPer.replace (/\:+$/g, ''); /* Clean any trailing separators from this string. */
809
  /**/
810
  if (trialAmount && (isNaN (trialAmount) || trialAmount < 0.00))
811
  {
812
- alert ('Oops, a slight problem:\n\nWhen provided, Trial Amount must be >= 0.00');
813
  return false;
814
  }
815
  else if (trialAmount && trialAmount > 10000.00) /* $10,000.00 maximum. */
816
  {
817
- alert ('Oops, a slight problem:\n\nMaximum Trial Amount is: 10000.00');
818
  return false;
819
  }
820
  else if (trialTerm === 'D' && trialPeriod > 7) /* Some validation on the Trial Period. Max days: 7. */
821
  {
822
- alert ('Oops, a slight problem:\n\nMaximum Free Days is: 7.\nIf you want to offer more than 7 days free, please choose Weeks or Months from the drop-down.');
823
  return false;
824
  }
825
  else if (trialTerm === 'W' && trialPeriod > 52) /* Some validation on the Trial Period. 52 max. */
826
  {
827
- alert ('Oops, a slight problem:\n\nMaximum Free Weeks is: 52.\nIf you want to offer more than 52 weeks free, please choose Months from the drop-down.');
828
  return false;
829
  }
830
  else if (trialTerm === 'M' && trialPeriod > 12) /* Some validation on the Trial Period. 12 max. */
831
  {
832
- alert ('Oops, a slight problem:\n\nMaximum Free Months is: 12.\nIf you want to offer more than 12 months free, please choose Years from the drop-down.');
833
  return false;
834
  }
835
- else if (trialTerm === 'Y' && trialPeriod > 1) /* 1 year max for PayPal®. */
836
  {
837
- alert ('Oops, a slight problem:\n\nMax Trial Period Years is: 1. *This is a PayPal® limitation.');
838
  return false;
839
  }
840
  else if (!regAmount || isNaN (regAmount) || regAmount < 0.01)
841
  {
842
- alert ('Oops, a slight problem:\n\nAmount must be >= 0.01');
843
  return false;
844
  }
845
  else if (regAmount > 10000.00) /* $10,000.00 maximum. */
846
  {
847
- alert ('Oops, a slight problem:\n\nMaximum amount is: 10000.00');
 
 
 
 
 
848
  return false;
849
  }
850
  /**/
851
- code.val (code.val ().replace (/ \<\!--(\<input type\="hidden" name\="(amount|src|sra|a1|p1|t1|a3|p3|t3)" value\="(.*?)" \/\>)--\>/g, " $1"));
852
- (parseInt (trialPeriod) <= 0) ? code.val (code.val ().replace (/ (\<input type\="hidden" name\="(a1|p1|t1)" value\="(.*?)" \/\>)/g, " <!--$1-->")) : null;
853
- (regRecur === 'BN') ? code.val (code.val ().replace (/ (\<input type\="hidden" name\="cmd" value\=")(.*?)(" \/\>)/g, " $1_xclick$3")) : null;
854
- (regRecur === 'BN') ? code.val (code.val ().replace (/ (\<input type\="hidden" name\="(src|sra|a1|p1|t1|a3|p3|t3)" value\="(.*?)" \/\>)/g, " <!--$1-->")) : null;
855
- (regRecur !== 'BN') ? code.val (code.val ().replace (/ (\<input type\="hidden" name\="cmd" value\=")(.*?)(" \/\>)/g, " $1_xclick-subscriptions$3")) : null;
856
- (regRecur !== 'BN') ? code.val (code.val ().replace (/ (\<input type\="hidden" name\="amount" value\="(.*?)" \/\>)/g, " <!--$1-->")) : null;
857
  /**/
858
- shortCodeTemplateAttrs += 'level="' + esc_attr (level) + '" ccaps="' + esc_attr (cCaps) + '" desc="' + esc_attr (label) + '" ps="' + esc_attr (pageStyle) + '" cc="' + esc_attr (currencyCode) + '" ns="1" custom="<?php echo esc_attr ($_SERVER["HTTP_HOST"]); ?>"';
859
  shortCodeTemplateAttrs += ' ta="' + esc_attr (trialAmount) + '" tp="' + esc_attr (trialPeriod) + '" tt="' + esc_attr (trialTerm) + '" ra="' + esc_attr (regAmount) + '" rp="' + esc_attr (regPeriod) + '" rt="' + esc_attr (regTerm) + '" rr="' + esc_attr (regRecur) + '"';
860
  shortCodeTemplateAttrs += (button === 'modification') ? ' modify="1"' : ''; /* For Modification Buttons. */
861
  shortCode.val (shortCodeTemplate.replace (/%%attrs%%/, shortCodeTemplateAttrs));
862
  /**/
863
- code.val (code.val ().replace (/ name\="item_name" value\="(.*?)"/, ' name="item_name" value="' + esc_attr (label) + '"'));
864
- code.val (code.val ().replace (/ name\="item_number" value\="(.*?)"/, ' name="item_number" value="' + esc_attr (levelCcapsPer) + '"'));
865
- code.val (code.val ().replace (/ name\="page_style" value\="(.*?)"/, ' name="page_style" value="' + esc_attr (pageStyle) + '"'));
866
- code.val (code.val ().replace (/ name\="currency_code" value\="(.*?)"/, ' name="currency_code" value="' + esc_attr (currencyCode) + '"'));
867
- code.val (code.val ().replace (/ name\="custom" value\="(.*?)"/, ' name="custom" value="<?php echo esc_attr ($_SERVER["HTTP_HOST"]); ?>"'));
868
- code.val (code.val ().replace (/ name\="modify" value\="(.*?)"/, ' name="modify" value="' + ( (button === 'modification') ? '1' : '0') + '"'));
869
- code.val (code.val ().replace (/ name\="amount" value\="(.*?)"/, ' name="amount" value="' + esc_attr (regAmount) + '"'));
870
- code.val (code.val ().replace (/ name\="src" value\="(.*?)"/, ' name="src" value="' + esc_attr (regRecur) + '"'));
871
- code.val (code.val ().replace (/ name\="a1" value\="(.*?)"/, ' name="a1" value="' + esc_attr (trialAmount) + '"'));
872
- code.val (code.val ().replace (/ name\="p1" value\="(.*?)"/, ' name="p1" value="' + esc_attr (trialPeriod) + '"'));
873
- code.val (code.val ().replace (/ name\="t1" value\="(.*?)"/, ' name="t1" value="' + esc_attr (trialTerm) + '"'));
874
- code.val (code.val ().replace (/ name\="a3" value\="(.*?)"/, ' name="a3" value="' + esc_attr (regAmount) + '"'));
875
- code.val (code.val ().replace (/ name\="p3" value\="(.*?)"/, ' name="p3" value="' + esc_attr (regPeriod) + '"'));
876
- code.val (code.val ().replace (/ name\="t3" value\="(.*?)"/, ' name="t3" value="' + esc_attr (regTerm) + '"'));
877
- /**/
878
- $ ('div#ws-plugin--s2member-' + button + '-button-prev').html (code.val ().replace (/\<form/, '<form target="_blank"').replace (/\<\?php echo S2MEMBER_CURRENT_USER_VALUE_FOR_PP_(ON0|OS0); \?\>/g, ''));
879
  /**/
880
  (button === 'modification') ? alert ('Your Modification Button has been generated.\nPlease copy/paste the Shortcode Format into your Login Welcome Page, or wherever you feel it would be most appropriate.') : alert ('Your Button has been generated.\nPlease copy/paste the Shortcode Format into your Membership Options Page.');
881
  /**/
@@ -889,7 +899,7 @@ jQuery (document).ready (function($)
889
  /**/
890
  ws_plugin__s2member_paypalSpButtonGenerate = function() /* Handles PayPal® Button Generation for Specific Post/Page Access. */
891
  {
892
- var shortCodeTemplate = '[s2Member-PayPal-Button %%attrs%% image="default" /]', shortCodeTemplateAttrs = '';
893
  /**/
894
  var shortCode = $ ('input#ws-plugin--s2member-sp-shortcode');
895
  var code = $ ('textarea#ws-plugin--s2member-sp-button');
@@ -904,22 +914,22 @@ jQuery (document).ready (function($)
904
  /**/
905
  if (!leading) /* Must have a Leading Post/Page ID to work with. Otherwise, Link generation will fail. */
906
  {
907
- alert ('Oops, a slight problem:\n\nPlease select a Leading Post/Page.\n\n*Tip* If there are no Posts/Pages in the menu, it\'s because you\'ve not configured s2Member for Specific Post/Page Access yet. See: s2Member -> General Options -> Specific Post/Page Access Restrictions.');
908
  return false;
909
  }
910
  else if (!regAmount || isNaN (regAmount) || regAmount < 0.01)
911
  {
912
- alert ('Oops, a slight problem:\n\nAmount must be >= 0.01');
913
  return false;
914
  }
915
  else if (regAmount > 10000.00) /* $10,000.00 maximum. */
916
  {
917
- alert ('Oops, a slight problem:\n\nMaximum amount is: 10000.00');
918
  return false;
919
  }
920
  else if (!desc) /* Each Button should have a Description. */
921
  {
922
- alert ('Oops, a slight problem:\n\nPlease type a Description for this Button.');
923
  return false;
924
  }
925
  /**/
@@ -930,19 +940,19 @@ jQuery (document).ready (function($)
930
  var spIdsHours = 'sp:' + ids + ':' + hours; /* Combined sp:ids:expiration hours. */
931
  /**/
932
  shortCodeTemplateAttrs += 'ids="' + esc_attr (ids) + '" exp="' + esc_attr (hours) + '" desc="' + esc_attr (desc) + '" ps="' + esc_attr (pageStyle) + '" cc="' + esc_attr (currencyCode) + '" ns="1"';
933
- shortCodeTemplateAttrs += ' custom="<?php echo esc_attr ($_SERVER["HTTP_HOST"]); ?>" ra="' + esc_attr (regAmount) + '" sp="1"';
934
  shortCode.val (shortCodeTemplate.replace (/%%attrs%%/, shortCodeTemplateAttrs));
935
  /**/
936
- code.val (code.val ().replace (/ name\="item_name" value\="(.*?)"/, ' name="item_name" value="' + esc_attr (desc) + '"'));
937
- code.val (code.val ().replace (/ name\="item_number" value\="(.*?)"/, ' name="item_number" value="' + esc_attr (spIdsHours) + '"'));
938
- code.val (code.val ().replace (/ name\="page_style" value\="(.*?)"/, ' name="page_style" value="' + esc_attr (pageStyle) + '"'));
939
- code.val (code.val ().replace (/ name\="currency_code" value\="(.*?)"/, ' name="currency_code" value="' + esc_attr (currencyCode) + '"'));
940
- code.val (code.val ().replace (/ name\="custom" value\="(.*?)"/, ' name="custom" value="<?php echo esc_attr ($_SERVER["HTTP_HOST"]); ?>"'));
941
- code.val (code.val ().replace (/ name\="amount" value\="(.*?)"/, ' name="amount" value="' + esc_attr (regAmount) + '"'));
942
  /**/
943
- $ ('div#ws-plugin--s2member-sp-button-prev').html (code.val ().replace (/\<form/, '<form target="_blank"'));
944
  /**/
945
- alert ('Your Button has been generated.\nPlease copy/paste the Shortcode Format into your Membership Options Page.');
946
  /**/
947
  shortCode.each (function() /* Focus and select the recommended Shortcode. */
948
  {
@@ -961,7 +971,7 @@ jQuery (document).ready (function($)
961
  /**/
962
  if (!leading) /* Must have a Leading Post/Page ID to work with. Otherwise, Link generation will fail. */
963
  {
964
- alert ('Oops, a slight problem:\n\nPlease select a Leading Post/Page.\n\n*Tip* If there are no Posts/Pages in the menu, it\'s because you\'ve not configured s2Member for Specific Post/Page Access yet. See: s2Member -> General Options -> Specific Post/Page Access Restrictions.');
965
  return false;
966
  }
967
  /**/
10
  /*
11
  These routines are all specific to this software.
12
  */
13
+ jQuery(document).ready (function($)
14
  {
15
  var esc_attr = esc_html = function(str) /* Convert special characters. */
16
  {
19
  /**/
20
  if (location.href.match (/page\=ws-plugin--s2member-mms-options/))
21
  {
22
+ $('select#ws-plugin--s2member-mms-registration-file').change (function()
23
  {
24
  if ($ (this).val () === 'wp-signup') /* Expand/collapse relevant options; based on file selection. */
25
  {
26
+ $('div#ws-plugin--s2member-mms-registration-support-package-details-wrapper').show (), $ ('div.ws-plugin--s2member-mms-registration-wp-login, table.ws-plugin--s2member-mms-registration-wp-login').hide (), $ ('div.ws-plugin--s2member-mms-registration-wp-signup, table.ws-plugin--s2member-mms-registration-wp-signup').show ();
27
  }
28
  else if ($ (this).val () === 'wp-login') /* Expand/collapse relevant options. */
29
  {
30
+ $('div#ws-plugin--s2member-mms-registration-support-package-details-wrapper').hide (), $ ('div.ws-plugin--s2member-mms-registration-wp-login, table.ws-plugin--s2member-mms-registration-wp-login').show (), $ ('div.ws-plugin--s2member-mms-registration-wp-signup, table.ws-plugin--s2member-mms-registration-wp-signup').hide ();
31
  }
32
  /**/
33
+ $('div.ws-plugin--s2member-mms-registration-wp-signup-blogs-level0, table.ws-plugin--s2member-mms-registration-wp-signup-blogs-level0')[(($ ('select#ws-plugin--s2member-mms-registration-grants').val () === 'all') ? 'show' : 'hide')] (), $ ('input#ws-plugin--s2member-mms-registration-blogs-level0').val ((($ ('select#ws-plugin--s2member-mms-registration-grants').val () === 'all') ? '1' : '0'));
34
  /**/
35
  }).trigger ('change'); /* Fire on ready too. */
36
  /**/
37
+ $('select#ws-plugin--s2member-mms-registration-grants').change (function()
38
  {
39
+ $('select#ws-plugin--s2member-mms-registration-file').trigger ('change');
40
  });
41
  }
42
  /**/
55
  var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()';
56
  for (var i = 0, key = ''; i < 56; i++) key += chars.substr (mt_rand (0, chars.length - 1), 1);
57
  /**/
58
+ $('input#ws-plugin--s2member-sec-encryption-key').val (key);
59
  /**/
60
  return false;
61
  };
63
  ws_plugin__s2member_enableSecurityKey = function() /* Allow Security Key editing?? */
64
  {
65
  if (confirm ('Edit Key? Are you sure?\nThis could break your installation!\n\n*Note* If you\'ve been testing s2Member, feel free to change this Key before you go live. Just don\'t go live, and then change it. You\'ll have some very unhappy Customers. Data corruption WILL occur!\n\nFor your safety, s2Member keeps a history of the last 10 Keys that you\'ve used. If you get yourself into a real situation, s2Member will let you revert back to a previous Key.'))
66
+ $('input#ws-plugin--s2member-sec-encryption-key').attr ('disabled', false);
67
  /**/
68
  return false;
69
  };
70
  /**/
71
  ws_plugin__s2member_securityKeyHistory = function() /* Displays history of Keys. */
72
  {
73
+ $('div#ws-plugin--s2member-sec-encryption-key-history').toggle ();
74
  /**/
75
  return false;
76
  };
100
  tr2 = 'tr.ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected';
101
  /**/
102
  if (type.match (/^(text|textarea|checkbox|pre_checkbox)$/))
103
+ $(tr1).css ('display', 'none'), $ (tr1).prev ('tr').css ('display', 'none');
104
  else /* Otherwise we display the table row by removing the display property. */
105
+ $(tr1).css ('display', ''), $ (tr1).prev ('tr').css ('display', '');
106
  /**/
107
  /**/
108
  if (type.match (/^(select|selects|checkboxes|radios)$/))
109
+ $(tr2).css ('display', 'none'), $ (tr2).prev ('tr').css ('display', 'none');
110
  else /* Otherwise we display the table row by removing the display property. */
111
+ $(tr2).css ('display', ''), $ (tr2).prev ('tr').css ('display', '');
112
  };
113
  /**/
114
  ws_plugin__s2member_customRegFieldDelete = function(index)
164
  setTimeout (function() /* A momentary delay here for usability. */
165
  {
166
  var row = 'tr.ws-plugin--s2member-custom-reg-field-configuration-table-row-' + (fields.length - 1);
167
+ alert('Field created successfully.\n* Remember to "Save Changes".');
168
+ $(row).effect ('highlight', 1000);
169
  }, 500);
170
  }
171
  };
186
  fields[index] = field, updateFields (), buildTools (), buildTable (), scrollReset ();
187
  /**/
188
  var row = 'tr.ws-plugin--s2member-custom-reg-field-configuration-table-row-' + index;
189
+ $(row).effect ('highlight', 1000);
190
  }
191
  };
192
  /**/
193
  ws_plugin__s2member_customRegFieldAdd = function() /* Add new field links. */
194
  {
195
+ buildTools(true); /* No need to reset scroll position. */
196
  };
197
  /**/
198
  ws_plugin__s2member_customRegFieldEdit = function(index) /* Edit links. */
260
  field.options = ''; /* Force empty options. */
261
  }
262
  /**/
263
+ if (!(field.levels = field.levels.replace (/ /g, '')))
264
  {
265
  errors.push ('Applicable Levels:\nThis is required. Please try again.');
266
  }
287
  /**/
288
  if (errors.length > 0) /* Errors? */
289
  {
290
+ alert(errors.join ('\n\n'));
291
  return false;
292
  }
293
  else /* Return. */
296
  /**/
297
  var updateFields = function() /* Update hidden input value. */
298
  {
299
+ $fields.val (((fields.length > 0) ? $.JSON.stringify (fields) : ''));
300
  };
301
  /**/
302
  var fieldId2Var = function(fieldId) /* Convert ids to variables. */
352
  form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-type">';
353
  form += '<td colspan="2">';
354
  form += '<select property="type" onchange="ws_plugin__s2member_customRegFieldTypeChange(this);" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-type">';
355
+ form += '<option value="text"' + ((field.type === 'text') ? ' selected="selected"' : '') + '">' + esc_html (fieldTypeDesc ('text')) + '</option>';
356
+ form += '<option value="textarea"' + ((field.type === 'textarea') ? ' selected="selected"' : '') + '">' + esc_html (fieldTypeDesc ('textarea')) + '</option>';
357
+ form += '<option value="select"' + ((field.type === 'select') ? ' selected="selected"' : '') + '">' + esc_html (fieldTypeDesc ('select')) + '</option>';
358
+ form += '<option value="selects"' + ((field.type === 'selects') ? ' selected="selected"' : '') + '">' + esc_html (fieldTypeDesc ('selects')) + '</option>';
359
+ form += '<option value="checkbox"' + ((field.type === 'checkbox') ? ' selected="selected"' : '') + '">' + esc_html (fieldTypeDesc ('checkbox')) + '</option>';
360
+ form += '<option value="pre_checkbox"' + ((field.type === 'pre_checkbox') ? ' selected="selected"' : '') + '">' + esc_html (fieldTypeDesc ('pre_checkbox')) + '</option>';
361
+ form += '<option value="checkboxes"' + ((field.type === 'checkboxes') ? ' selected="selected"' : '') + '">' + esc_html (fieldTypeDesc ('checkboxes')) + '</option>';
362
+ form += '<option value="radios"' + ((field.type === 'radios') ? ' selected="selected"' : '') + '">' + esc_html (fieldTypeDesc ('radios')) + '</option>';
363
  form += '</select>';
364
  form += '</td>';
365
  form += '</tr>';
406
  form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-required">';
407
  form += '<td colspan="2">';
408
  form += '<select property="required" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-required">';
409
+ form += '<option value="yes"' + ((field.required === 'yes') ? ' selected="selected"' : '') + '">Yes ( required )</option>';
410
+ form += '<option value="no"' + ((field.required === 'no') ? ' selected="selected"' : '') + '">No ( optional )</option>';
411
  form += '</select><br />';
412
  form += '<small>If <code>yes</code>, only Users/Members will be "required" to enter this field.</small><br />';
413
  form += '<small>* Administrators are exempt from this requirement.</small>';
414
  form += '</td>';
415
  form += '</tr>';
416
  /**/
417
+ form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer"' + ((field.type.match (/^(text|textarea|checkbox|pre_checkbox)$/)) ? ' style="display:none;"' : '') + '><td colspan="2">&nbsp;</td></tr>';
418
  /**/
419
+ form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-options"' + ((field.type.match (/^(text|textarea|checkbox|pre_checkbox)$/)) ? ' style="display:none;"' : '') + '>';
420
  form += '<td colspan="2">';
421
  form += '<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-options">Option Configuration File: * ( one option per line )</label><br />';
422
  form += '<small>Use a pipe <code>|</code> delimited format: <code>option value|option label</code></small>';
423
  form += '</td>';
424
  form += '</tr>';
425
  /**/
426
+ form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-options"' + ((field.type.match (/^(text|textarea|checkbox|pre_checkbox)$/)) ? ' style="display:none;"' : '') + '>';
427
  form += '<td colspan="2">';
428
  form += '<textarea property="options" rows="3" wrap="off" spellcheck="false" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-options">' + esc_html (field.options) + '</textarea><br />';
429
  form += 'Here is a quick example:<br />';
434
  form += '</td>';
435
  form += '</tr>';
436
  /**/
437
+ form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-spacer"' + ((field.type.match (/^(select|selects|checkboxes|radios)$/)) ? ' style="display:none;"' : '') + '><td colspan="2">&nbsp;</td></tr>';
438
  /**/
439
+ form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected"' + ((field.type.match (/^(select|selects|checkboxes|radios)$/)) ? ' style="display:none;"' : '') + '>';
440
  form += '<td colspan="2">';
441
  form += '<label for="ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected">Expected Format: *</label>';
442
  form += '</td>';
443
  form += '</tr>';
444
  /**/
445
+ form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected"' + ((field.type.match (/^(select|selects|checkboxes|radios)$/)) ? ' style="display:none;"' : '') + '>';
446
  form += '<td colspan="2">';
447
  form += '<select property="expected" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-expected">';
448
  /**/
449
+ form += '<option value=""' + ((field.expected === '') ? ' selected="selected"' : '') + '">Anything Goes</option>';
450
  form += '<option disabled="disabled"></option>';
451
  /**/
452
  form += '<optgroup label="Specific Input Types">';
453
+ form += '<option value="numeric-wp-commas"' + ((field.expected === 'numeric-wp-commas') ? ' selected="selected"' : '') + '">Numeric ( with or without decimals, commas allowed )</option>';
454
+ form += '<option value="numeric"' + ((field.expected === 'numeric') ? ' selected="selected"' : '') + '">Numeric ( with or without decimals, no commas )</option>';
455
+ form += '<option value="integer"' + ((field.expected === 'integer') ? ' selected="selected"' : '') + '">Integer ( whole number, without any decimals )</option>';
456
+ form += '<option value="integer-gt-0"' + ((field.expected === 'integer-gt-0') ? ' selected="selected"' : '') + '">Integer > 0 ( whole number, no decimals, greater than 0 )</option>';
457
+ form += '<option value="float"' + ((field.expected === 'float') ? ' selected="selected"' : '') + '">Float ( floating point number, decimals required )</option>';
458
+ form += '<option value="float-gt-0"' + ((field.expected === 'float-gt-0') ? ' selected="selected"' : '') + '">Float > 0 ( floating point number, decimals required, greater than 0 )</option>';
459
+ form += '<option value="date"' + ((field.expected === 'date') ? ' selected="selected"' : '') + '">Date ( required date format: dd/mm/yyyy )</option>';
460
+ form += '<option value="email"' + ((field.expected === 'email') ? ' selected="selected"' : '') + '">Email ( require valid email )</option>';
461
+ form += '<option value="url"' + ((field.expected === 'url') ? ' selected="selected"' : '') + '">Full URL ( starting with http or https )</option>';
462
+ form += '<option value="domain"' + ((field.expected === 'domain') ? ' selected="selected"' : '') + '">Domain Name ( domain name only, without http )</option>';
463
+ form += '<option value="phone"' + ((field.expected === 'phone') ? ' selected="selected"' : '') + '">Phone # ( 10 digits w/possible hyphens,spaces,brackets )</option>';
464
+ form += '<option value="uszip"' + ((field.expected === 'uszip') ? ' selected="selected"' : '') + '">US Zipcode ( 5-9 digits w/possible hyphen )</option>';
465
+ form += '<option value="cazip"' + ((field.expected === 'cazip') ? ' selected="selected"' : '') + '">Canadian Zipcode ( 6 alpha-numerics w/possible space )</option>';
466
+ form += '<option value="uczip"' + ((field.expected === 'uczip') ? ' selected="selected"' : '') + '">US/Canadian Zipcode ( either a US or Canadian zipcode )</option>';
467
  form += '</optgroup>';
468
  /**/
469
  form += '<option disabled="disabled"></option>';
471
  form += '<optgroup label="Any Character Combination">';
472
  for (i = 1; i <= 25; i++)
473
  {
474
+ form += '<option value="any-' + i + '"' + ((field.expected === 'any-' + i) ? ' selected="selected"' : '') + '">Any Character Combination ( ' + i + ' character minimum )</option>';
475
+ form += '<option value="any-' + i + '-e"' + ((field.expected === 'any-' + i + '-e') ? ' selected="selected"' : '') + '">Any Character Combination ( exactly ' + i + ' character' + ((i > 1) ? 's' : '') + ' )</option>';
476
  }
477
  form += '</optgroup>';
478
  /**/
481
  form += '<optgroup label="Alphanumerics, Spaces &amp; Punctuation Only">';
482
  for (i = 1; i <= 25; i++)
483
  {
484
+ form += '<option value="alphanumerics-spaces-punctuation-' + i + '"' + ((field.expected === 'alphanumerics-spaces-punctuation-' + i) ? ' selected="selected"' : '') + '">Alphanumerics, Spaces &amp; Punctuation ( ' + i + ' character minimum )</option>';
485
+ form += '<option value="alphanumerics-spaces-punctuation-' + i + '-e"' + ((field.expected === 'alphanumerics-spaces-punctuation-' + i + '-e') ? ' selected="selected"' : '') + '">Alphanumerics, Spaces &amp; Punctuation ( exactly ' + i + ' character' + ((i > 1) ? 's' : '') + ' )</option>';
486
  }
487
  form += '</optgroup>';
488
  /**/
491
  form += '<optgroup label="Alphanumerics &amp; Spaces Only">';
492
  for (i = 1; i <= 25; i++)
493
  {
494
+ form += '<option value="alphanumerics-spaces-' + i + '"' + ((field.expected === 'alphanumerics-spaces-' + i) ? ' selected="selected"' : '') + '">Alphanumerics &amp; Spaces ( ' + i + ' character minimum )</option>';
495
+ form += '<option value="alphanumerics-spaces-' + i + '-e"' + ((field.expected === 'alphanumerics-spaces-' + i + '-e') ? ' selected="selected"' : '') + '">Alphanumerics &amp; Spaces ( exactly ' + i + ' character' + ((i > 1) ? 's' : '') + ' )</option>';
496
  }
497
  form += '</optgroup>';
498
  /**/
501
  form += '<optgroup label="Alphanumerics &amp; Punctuation Only">';
502
  for (i = 1; i <= 25; i++)
503
  {
504
+ form += '<option value="alphanumerics-punctuation-' + i + '"' + ((field.expected === 'alphanumerics-punctuation-' + i) ? ' selected="selected"' : '') + '">Alphanumerics &amp; Punctuation ( ' + i + ' character minimum )</option>';
505
+ form += '<option value="alphanumerics-punctuation-' + i + '-e"' + ((field.expected === 'alphanumerics-punctuation-' + i + '-e') ? ' selected="selected"' : '') + '">Alphanumerics &amp; Punctuation ( exactly ' + i + ' character' + ((i > 1) ? 's' : '') + ' )</option>';
506
  }
507
  form += '</optgroup>';
508
  /**/
511
  form += '<optgroup label="Alphanumerics Only">';
512
  for (i = 1; i <= 25; i++)
513
  {
514
+ form += '<option value="alphanumerics-' + i + '"' + ((field.expected === 'alphanumerics-' + i) ? ' selected="selected"' : '') + '">Alphanumerics ( ' + i + ' character minimum )</option>';
515
+ form += '<option value="alphanumerics-' + i + '-e"' + ((field.expected === 'alphanumerics-' + i + '-e') ? ' selected="selected"' : '') + '">Alphanumerics ( exactly ' + i + ' character' + ((i > 1) ? 's' : '') + ' )</option>';
516
  }
517
  form += '</optgroup>';
518
  /**/
521
  form += '<optgroup label="Alphabetics Only">';
522
  for (i = 1; i <= 25; i++)
523
  {
524
+ form += '<option value="alphabetics-' + i + '"' + ((field.expected === 'alphabetics-' + i) ? ' selected="selected"' : '') + '">Alphabetics ( ' + i + ' character minimum )</option>';
525
+ form += '<option value="alphabetics-' + i + '-e"' + ((field.expected === 'alphabetics-' + i + '-e') ? ' selected="selected"' : '') + '">Alphabetics ( exactly ' + i + ' character' + ((i > 1) ? 's' : '') + ' )</option>';
526
  }
527
  form += '</optgroup>';
528
  /**/
531
  form += '<optgroup label="Numeric Digits Only">';
532
  for (i = 1; i <= 25; i++)
533
  {
534
+ form += '<option value="numerics-' + i + '"' + ((field.expected === 'numerics-' + i) ? ' selected="selected"' : '') + '">Numeric Digits ( ' + i + ' digit minimum )</option>';
535
+ form += '<option value="numerics-' + i + '-e"' + ((field.expected === 'numerics-' + i + '-e') ? ' selected="selected"' : '') + '">Numeric Digits ( exactly ' + i + ' digit' + ((i > 1) ? 's' : '') + ' )</option>';
536
  }
537
  form += '</optgroup>';
538
  /**/
569
  form += '<tr class="ws-plugin--s2member-custom-reg-field-configuration-tools-form-editable">';
570
  form += '<td colspan="2">';
571
  form += '<select property="editable" id="ws-plugin--s2member-custom-reg-field-configuration-tools-form-editable">';
572
+ form += '<option value="yes"' + ((field.editable === 'yes') ? ' selected="selected"' : '') + '">Yes ( editable )</option>';
573
+ form += '<option value="no"' + ((field.editable === 'no') ? ' selected="selected"' : '') + '">No ( uneditable after registration )</option>';
574
+ form += '<option value="no-invisible"' + ((field.editable === 'no-invisible') ? ' selected="selected"' : '') + '">No ( uneditable &amp; totally invisible )</option>';
575
  form += '</select><br />';
576
  form += '<small>If <code>No</code>, this field will be un-editable after registration.</small><br />';
577
  form += '<small>* Administrators are exempt from this.</small>';
630
  form += '<input type="button" value="Cancel" onclick="ws_plugin__s2member_customRegFieldCancel();" />';
631
  form += '</td>';
632
  form += '<td align="right">';
633
+ form += '<input type="button" value="' + ((editing) ? 'Update This Field' : 'Create Registration Field') + '" onclick="' + ((editing) ? 'ws_plugin__s2member_customRegFieldUpdate(' + index + ');' : 'ws_plugin__s2member_customRegFieldCreate();') + '" />';
634
  form += '</td>';
635
  form += '</tr>';
636
  /**/
639
  /**/
640
  form += '<div>';
641
  /**/
642
+ $('body').append (form);
643
+ tb_show (((editing) ? 'Editing Registration Field' : 'New Custom Registration Field'), '#TB_inline?inlineId=ws-plugin--s2member-custom-reg-field-configuration-thickbox-tools-form');
644
+ $(window).trigger ('resize'), $ ('table#ws-plugin--s2member-custom-reg-field-configuration-tools-form').show ();
645
  }
646
  /**/
647
  $tools.html (html);
649
  /**/
650
  var attachTBResizer = function() /* Resize inline #TB_ajaxContent. */
651
  {
652
+ $(window).resize (function()
653
  {
654
  var w, h; /* Initialize width/height vars. */
655
  w = $ (window).width (), h = $ (window).height (), w = (w > 720) ? 720 : w;
656
+ $('#TB_ajaxContent').css ({'width': w - 50, 'height': h - 75, 'margin': 0, 'padding': 0});
657
  });
658
  };
659
  /**/
706
  }) ();
707
  }
708
  /**/
709
+ $('input#ws-plugin--s2member-ip-restrictions-reset-button').click (function()
710
  {
711
  var $this = $ (this); /* Save $(this) into $this. */
712
  $this.val ('one moment please ...'); /* Indicate loading status ( please wait ). */
713
  /**/
714
  $.post (ajaxurl, {action: 'ws_plugin__s2member_delete_reset_all_ip_restrictions_via_ajax', ws_plugin__s2member_delete_reset_all_ip_restrictions_via_ajax: '<?php echo ws_plugin__s2member_esc_sq (wp_create_nonce ("ws-plugin--s2member-delete-reset-all-ip-restrictions-via-ajax")); ?>'}, function(response)
715
  {
716
+ alert('s2Member\'s IP Restriction Logs have all been reset.'), $this.val ('Reset IP Restriction Logs');
717
  });
718
  /**/
719
  return false;
722
  /**/
723
  else if (location.href.match (/page\=ws-plugin--s2member-paypal-ops/))
724
  {
725
+ $('select#ws-plugin--s2member-auto-eot-system-enabled').change (function()
726
  {
727
  var $this = $ (this), val = $this.val ();
728
  var $viaCron = $ ('p#ws-plugin--s2member-auto-eot-system-enabled-via-cron');
736
  /**/
737
  else if (location.href.match (/page\=ws-plugin--s2member-els-ops/))
738
  {
739
+ $('select#ws-plugin--s2member-custom-reg-opt-in').change (function()
740
  {
741
  var $this = $ (this), val = $this.val ();
742
  var $rows = $ ('tr.ws-plugin--s2member-custom-reg-opt-in-label-row');
755
  /**/
756
  else if (location.href.match (/page\=ws-plugin--s2member-paypal-buttons/))
757
  {
758
+ $('select#ws-plugin--s2member-level1-term, select#ws-plugin--s2member-level2-term, select#ws-plugin--s2member-level3-term, select#ws-plugin--s2member-level4-term, select#ws-plugin--s2member-modification-term').change (function()
759
  {
760
  var button = this.id.replace (/^ws-plugin--s2member-(.+?)-term$/g, '$1');
761
+ /**/
762
  var trialDisabled = ($ (this).val ().split ('-')[2].replace (/[^0-1BN]/g, '') === 'BN') ? 1 : 0;
763
+ /**/
764
+ $('p#ws-plugin--s2member-' + button + '-trial-line').css ('display', (trialDisabled ? 'none' : ''));
765
+ $('span#ws-plugin--s2member-' + button + '-trial-then').css ('display', (trialDisabled ? 'none' : ''));
766
+ $('span#ws-plugin--s2member-' + button + '-20p-rule').css ('display', (trialDisabled ? 'none' : ''));
767
+ /**/
768
  (trialDisabled) ? $ ('input#ws-plugin--s2member-' + form + '-trial-period').val (0) : null;
769
+ (trialDisabled) ? $ ('input#ws-plugin--s2member-' + form + '-trial-amount').val ('0.00') : null;
770
  });
771
  /**/
772
+ $('input#ws-plugin--s2member-level1-ccaps, input#ws-plugin--s2member-level2-ccaps, input#ws-plugin--s2member-level3-ccaps, input#ws-plugin--s2member-level4-ccaps, input#ws-plugin--s2member-modification-ccaps').keyup (function()
773
  {
774
  if (this.value.match (/[^a-z_0-9,]/)) /* Only if there is a problem; because this causes interruption. */
775
  this.value = $.trim ($.trim (this.value).replace (/[ \-]/g, '_').replace (/[^A-Z_0-9,]/gi, '').toLowerCase ());
777
  /**/
778
  ws_plugin__s2member_paypalButtonGenerate = function(button) /* Handles PayPal® Button Generation. */
779
  {
780
+ var shortCodeTemplate = '[s2Member-PayPal-Button %%attrs%% image="default" output="button" /]', shortCodeTemplateAttrs = '', labels = {};
781
  /**/
782
  labels['level0'] = '<?php echo ws_plugin__s2member_esc_sq ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level0_label"]); ?>';
783
  labels['level1'] = '<?php echo ws_plugin__s2member_esc_sq ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_label"]); ?>';
791
  /**/
792
  var level = (button === 'modification') ? modLevel.val ().split (':', 2)[1] : button.replace (/^level/, '');
793
  var label = labels['level' + level].replace (/"/g, ""); /* Labels may NOT contain any double-quotes. */
794
+ var desc = $.trim ($ ('input#ws-plugin--s2member-' + button + '-desc').val ().replace (/"/g, ""));
795
  /**/
796
  var trialAmount = $ ('input#ws-plugin--s2member-' + button + '-trial-amount').val ().replace (/[^0-9\.]/g, '');
797
  var trialPeriod = $ ('input#ws-plugin--s2member-' + button + '-trial-period').val ().replace (/[^0-9]/g, '');
806
  var currencyCode = $ ('select#ws-plugin--s2member-' + button + '-currency').val ().replace (/[^A-Z]/g, '');
807
  var cCaps = $.trim ($.trim ($ ('input#ws-plugin--s2member-' + button + '-ccaps').val ()).replace (/[ \-]/g, '_').replace (/[^A-Z_0-9,]/gi, '').toLowerCase ());
808
  /**/
809
+ trialPeriod = (regRecur === 'BN') ? '0' : trialPeriod; /* Lifetime ( 1-L-BN ) and Buy Now ( BN ) access is absolutely NOT compatible w/ Free Trials. */
810
+ trialAmount = (!trialAmount || isNaN (trialAmount) || trialAmount < 0.01 || trialPeriod <= 0) ? '0' : trialAmount; /* Validate Trial Amount. */
811
  /**/
812
  var levelCcapsPer = (regRecur === 'BN' && regTerm !== 'L') ? level + ':' + cCaps + ':' + regPeriod + ' ' + regTerm : level + ':' + cCaps;
813
  levelCcapsPer = levelCcapsPer.replace (/\:+$/g, ''); /* Clean any trailing separators from this string. */
814
  /**/
815
  if (trialAmount && (isNaN (trialAmount) || trialAmount < 0.00))
816
  {
817
+ alert('Oops, a slight problem:\n\nWhen provided, Trial Amount must be >= 0.00');
818
  return false;
819
  }
820
  else if (trialAmount && trialAmount > 10000.00) /* $10,000.00 maximum. */
821
  {
822
+ alert('Oops, a slight problem:\n\nMaximum Trial Amount is: 10000.00');
823
  return false;
824
  }
825
  else if (trialTerm === 'D' && trialPeriod > 7) /* Some validation on the Trial Period. Max days: 7. */
826
  {
827
+ alert('Oops, a slight problem:\n\nMaximum Free Days is: 7.\nIf you want to offer more than 7 days free, please choose Weeks or Months from the drop-down.');
828
  return false;
829
  }
830
  else if (trialTerm === 'W' && trialPeriod > 52) /* Some validation on the Trial Period. 52 max. */
831
  {
832
+ alert('Oops, a slight problem:\n\nMaximum Free Weeks is: 52.\nIf you want to offer more than 52 weeks free, please choose Months from the drop-down.');
833
  return false;
834
  }
835
  else if (trialTerm === 'M' && trialPeriod > 12) /* Some validation on the Trial Period. 12 max. */
836
  {
837
+ alert('Oops, a slight problem:\n\nMaximum Free Months is: 12.\nIf you want to offer more than 12 months free, please choose Years from the drop-down.');
838
  return false;
839
  }
840
+ else if (trialTerm === 'Y' && trialPeriod > 1) /* 1 year max. */
841
  {
842
+ alert('Oops, a slight problem:\n\nMax Trial Period Years is: 1.');
843
  return false;
844
  }
845
  else if (!regAmount || isNaN (regAmount) || regAmount < 0.01)
846
  {
847
+ alert('Oops, a slight problem:\n\nAmount must be >= 0.01');
848
  return false;
849
  }
850
  else if (regAmount > 10000.00) /* $10,000.00 maximum. */
851
  {
852
+ alert('Oops, a slight problem:\n\nMaximum amount is: 10000.00');
853
+ return false;
854
+ }
855
+ else if (!desc) /* Each Button should have a Description. */
856
+ {
857
+ alert('Oops, a slight problem:\n\nPlease type a Description for this Button.');
858
  return false;
859
  }
860
  /**/
861
+ code.html (code.val ().replace (/ \<\!--(\<input type\="hidden" name\="(amount|src|sra|a1|p1|t1|a3|p3|t3)" value\="(.*?)" \/\>)--\>/g, " $1"));
862
+ (parseInt (trialPeriod) <= 0) ? code.html (code.val ().replace (/ (\<input type\="hidden" name\="(a1|p1|t1)" value\="(.*?)" \/\>)/g, " <!--$1-->")) : null;
863
+ (regRecur === 'BN') ? code.html (code.val ().replace (/ (\<input type\="hidden" name\="cmd" value\=")(.*?)(" \/\>)/g, " $1_xclick$3")) : null;
864
+ (regRecur === 'BN') ? code.html (code.val ().replace (/ (\<input type\="hidden" name\="(src|sra|a1|p1|t1|a3|p3|t3)" value\="(.*?)" \/\>)/g, " <!--$1-->")) : null;
865
+ (regRecur !== 'BN') ? code.html (code.val ().replace (/ (\<input type\="hidden" name\="cmd" value\=")(.*?)(" \/\>)/g, " $1_xclick-subscriptions$3")) : null;
866
+ (regRecur !== 'BN') ? code.html (code.val ().replace (/ (\<input type\="hidden" name\="amount" value\="(.*?)" \/\>)/g, " <!--$1-->")) : null;
867
  /**/
868
+ shortCodeTemplateAttrs += 'level="' + esc_attr (level) + '" ccaps="' + esc_attr (cCaps) + '" desc="' + esc_attr (desc) + '" ps="' + esc_attr (pageStyle) + '" cc="' + esc_attr (currencyCode) + '" ns="1" custom="<?php echo ws_plugin__s2member_esc_sq (esc_attr ($_SERVER["HTTP_HOST"])); ?>"';
869
  shortCodeTemplateAttrs += ' ta="' + esc_attr (trialAmount) + '" tp="' + esc_attr (trialPeriod) + '" tt="' + esc_attr (trialTerm) + '" ra="' + esc_attr (regAmount) + '" rp="' + esc_attr (regPeriod) + '" rt="' + esc_attr (regTerm) + '" rr="' + esc_attr (regRecur) + '"';
870
  shortCodeTemplateAttrs += (button === 'modification') ? ' modify="1"' : ''; /* For Modification Buttons. */
871
  shortCode.val (shortCodeTemplate.replace (/%%attrs%%/, shortCodeTemplateAttrs));
872
  /**/
873
+ code.html (code.val ().replace (/ name\="item_name" value\="(.*?)"/, ' name="item_name" value="' + esc_attr (desc) + '"'));
874
+ code.html (code.val ().replace (/ name\="item_number" value\="(.*?)"/, ' name="item_number" value="' + esc_attr (levelCcapsPer) + '"'));
875
+ code.html (code.val ().replace (/ name\="page_style" value\="(.*?)"/, ' name="page_style" value="' + esc_attr (pageStyle) + '"'));
876
+ code.html (code.val ().replace (/ name\="currency_code" value\="(.*?)"/, ' name="currency_code" value="' + esc_attr (currencyCode) + '"'));
877
+ code.html (code.val ().replace (/ name\="custom" value\="(.*?)"/, ' name="custom" value="<?php echo ws_plugin__s2member_esc_sq (esc_attr ($_SERVER["HTTP_HOST"])); ?>"'));
878
+ code.html (code.val ().replace (/ name\="modify" value\="(.*?)"/, ' name="modify" value="' + ((button === 'modification') ? '1' : '0') + '"'));
879
+ code.html (code.val ().replace (/ name\="amount" value\="(.*?)"/, ' name="amount" value="' + esc_attr (regAmount) + '"'));
880
+ code.html (code.val ().replace (/ name\="src" value\="(.*?)"/, ' name="src" value="' + esc_attr (regRecur) + '"'));
881
+ code.html (code.val ().replace (/ name\="a1" value\="(.*?)"/, ' name="a1" value="' + esc_attr (trialAmount) + '"'));
882
+ code.html (code.val ().replace (/ name\="p1" value\="(.*?)"/, ' name="p1" value="' + esc_attr (trialPeriod) + '"'));
883
+ code.html (code.val ().replace (/ name\="t1" value\="(.*?)"/, ' name="t1" value="' + esc_attr (trialTerm) + '"'));
884
+ code.html (code.val ().replace (/ name\="a3" value\="(.*?)"/, ' name="a3" value="' + esc_attr (regAmount) + '"'));
885
+ code.html (code.val ().replace (/ name\="p3" value\="(.*?)"/, ' name="p3" value="' + esc_attr (regPeriod) + '"'));
886
+ code.html (code.val ().replace (/ name\="t3" value\="(.*?)"/, ' name="t3" value="' + esc_attr (regTerm) + '"'));
887
+ /**/
888
+ $('div#ws-plugin--s2member-' + button + '-button-prev').html (code.val ().replace (/\<form/, '<form target="_blank"').replace (/\<\?php echo S2MEMBER_CURRENT_USER_VALUE_FOR_PP_(ON0|OS0); \?\>/g, ''));
889
  /**/
890
  (button === 'modification') ? alert ('Your Modification Button has been generated.\nPlease copy/paste the Shortcode Format into your Login Welcome Page, or wherever you feel it would be most appropriate.') : alert ('Your Button has been generated.\nPlease copy/paste the Shortcode Format into your Membership Options Page.');
891
  /**/
899
  /**/
900
  ws_plugin__s2member_paypalSpButtonGenerate = function() /* Handles PayPal® Button Generation for Specific Post/Page Access. */
901
  {
902
+ var shortCodeTemplate = '[s2Member-PayPal-Button %%attrs%% image="default" output="button" /]', shortCodeTemplateAttrs = '';
903
  /**/
904
  var shortCode = $ ('input#ws-plugin--s2member-sp-shortcode');
905
  var code = $ ('textarea#ws-plugin--s2member-sp-button');
914
  /**/
915
  if (!leading) /* Must have a Leading Post/Page ID to work with. Otherwise, Link generation will fail. */
916
  {
917
+ alert('Oops, a slight problem:\n\nPlease select a Leading Post/Page.\n\n*Tip* If there are no Posts/Pages in the menu, it\'s because you\'ve not configured s2Member for Specific Post/Page Access yet. See: s2Member -> General Options -> Specific Post/Page Access Restrictions.');
918
  return false;
919
  }
920
  else if (!regAmount || isNaN (regAmount) || regAmount < 0.01)
921
  {
922
+ alert('Oops, a slight problem:\n\nAmount must be >= 0.01');
923
  return false;
924
  }
925
  else if (regAmount > 10000.00) /* $10,000.00 maximum. */
926
  {
927
+ alert('Oops, a slight problem:\n\nMaximum amount is: 10000.00');
928
  return false;
929
  }
930
  else if (!desc) /* Each Button should have a Description. */
931
  {
932
+ alert('Oops, a slight problem:\n\nPlease type a Description for this Button.');
933
  return false;
934
  }
935
  /**/
940
  var spIdsHours = 'sp:' + ids + ':' + hours; /* Combined sp:ids:expiration hours. */
941
  /**/
942
  shortCodeTemplateAttrs += 'ids="' + esc_attr (ids) + '" exp="' + esc_attr (hours) + '" desc="' + esc_attr (desc) + '" ps="' + esc_attr (pageStyle) + '" cc="' + esc_attr (currencyCode) + '" ns="1"';
943
+ shortCodeTemplateAttrs += ' custom="<?php echo ws_plugin__s2member_esc_sq (esc_attr ($_SERVER["HTTP_HOST"])); ?>" ra="' + esc_attr (regAmount) + '" sp="1"';
944
  shortCode.val (shortCodeTemplate.replace (/%%attrs%%/, shortCodeTemplateAttrs));
945
  /**/
946
+ code.html (code.val ().replace (/ name\="item_name" value\="(.*?)"/, ' name="item_name" value="' + esc_attr (desc) + '"'));
947
+ code.html (code.val ().replace (/ name\="item_number" value\="(.*?)"/, ' name="item_number" value="' + esc_attr (spIdsHours) + '"'));
948
+ code.html (code.val ().replace (/ name\="page_style" value\="(.*?)"/, ' name="page_style" value="' + esc_attr (pageStyle) + '"'));
949
+ code.html (code.val ().replace (/ name\="currency_code" value\="(.*?)"/, ' name="currency_code" value="' + esc_attr (currencyCode) + '"'));
950
+ code.html (code.val ().replace (/ name\="custom" value\="(.*?)"/, ' name="custom" value="<?php echo ws_plugin__s2member_esc_sq (esc_attr ($_SERVER["HTTP_HOST"])); ?>"'));
951
+ code.html (code.val ().replace (/ name\="amount" value\="(.*?)"/, ' name="amount" value="' + esc_attr (regAmount) + '"'));
952
  /**/
953
+ $('div#ws-plugin--s2member-sp-button-prev').html (code.val ().replace (/\<form/, '<form target="_blank"'));
954
  /**/
955
+ alert('Your Button has been generated.\nPlease copy/paste the Shortcode Format into your Membership Options Page.');
956
  /**/
957
  shortCode.each (function() /* Focus and select the recommended Shortcode. */
958
  {
971
  /**/
972
  if (!leading) /* Must have a Leading Post/Page ID to work with. Otherwise, Link generation will fail. */
973
  {
974
+ alert('Oops, a slight problem:\n\nPlease select a Leading Post/Page.\n\n*Tip* If there are no Posts/Pages in the menu, it\'s because you\'ve not configured s2Member for Specific Post/Page Access yet. See: s2Member -> General Options -> Specific Post/Page Access Restrictions.');
975
  return false;
976
  }
977
  /**/
includes/menu-pages/mms-options.inc.php CHANGED
@@ -98,7 +98,7 @@ if (is_multisite () && is_main_site ()) /* These panels will ONLY be available o
98
  echo '<img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/large-icon.png" title="s2Member ( a Membership management system for WordPress® )" alt="" style="float:right; margin:0 0 0 25px; border:0;" />' . "\n";
99
  echo '<h3>Multisite Registration ( Main Site Configuration )</h3>' . "\n";
100
  echo '<p>s2Member supports Free Subscribers ( at Level #0 ), along with four Primary Levels [1-4] of paid Membership. If you want your visitors to be capable of registering absolutely free, you will want to "allow" Open Registration. Whenever a visitor registers without paying, they\'ll automatically become a Free Subscriber, at Level #0. &nbsp;&nbsp;<strong>With Multisite Networking enabled</strong>, your ( Main Site ) could ALSO offer a Customer access to create a Blog of their own, where a Customer becomes a "Member" of your ( Main Site ), and also a Blog Owner/Administrator. With s2Member installed ( network wide ), each of your Blog Owners could offer Membership too, using a single copy of the s2Member plugin ( which is a great selling point<em>!</em> ). We refer to this as a Multisite Blog Farm.</p>' . "\n";
101
- echo '<p>Multisite Networking also makes a new Registration Form available ( driven by your theme ); which we refer to as ( <code>wp-signup.php</code> ). If you\'re planning to offer Blogs, you MUST use <a href="' . apply_filters ("wp_signup_location", get_bloginfo ("wpurl") . "/wp-signup.php") . '" target="_blank" rel="external">wp-signup.php</a>, instead of using the Standard Login/Registration Form. In a Multisite installation, we refer to the Standard Login/Registration Form, as ( <code>wp-login.php?action=register</code> ). If you\'re planning to offer Membership Access only, and NOT Blogs, you can just use the <a href="' . add_query_arg ("action", "register", wp_login_url ()) . '" target="_blank" rel="external">Standard Login/Registration Form</a>, which is easily customized through <code>s2Member -> General Options -> Login/Registration Design</code>.</p>' . "\n";
102
  do_action ("ws_plugin__s2member_during_mms_options_page_during_left_sections_during_mms_registration", get_defined_vars ());
103
  echo '<div id="ws-plugin--s2member-mms-registration-support-package-details-wrapper">' . "\n";
104
  echo '<h3>Running a Multisite Blog Farm? ( <a href="#" onclick="jQuery(\'div#ws-plugin--s2member-mms-registration-support-package-details\').toggle(); return false;" class="ws-dotted-link">please read</a> )</h3>' . "\n";
@@ -132,8 +132,8 @@ if (is_multisite () && is_main_site ()) /* These panels will ONLY be available o
132
  else
133
  {
134
  echo '<select name="ws_plugin__s2member_mms_registration_file" id="ws-plugin--s2member-mms-registration-file">' . "\n";
135
- echo '<option value="wp-login"' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_registration_file"] === "wp-login") ? ' selected="selected"' : '') . '>Membership Only ( I\'m NOT offering Blogs )</option>' . "\n";
136
- echo '<option value="wp-signup"' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_registration_file"] === "wp-signup") ? ' selected="selected"' : '') . '>Blog Farm ( I plan to offer both Membership &amp; Blog creation )</option>' . "\n";
137
  echo '</select><br />' . "\n";
138
  echo 'Depending on your selection, the options below may change.' . "\n";
139
  }
@@ -161,10 +161,10 @@ if (is_multisite () && is_main_site ()) /* These panels will ONLY be available o
161
  /**/
162
  echo '<td>' . "\n";
163
  echo '<select name="ws_plugin__s2member_allow_subscribers_in" id="ws-plugin--s2member-allow-subscribers-in">' . "\n";
164
- echo '<option value="0"' . ((!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["allow_subscribers_in"]) ? ' selected="selected"' : '') . '>No ( do NOT allow Open Registration )</option>' . "\n";
165
- echo '<option value="1"' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["allow_subscribers_in"]) ? ' selected="selected"' : '') . '>Yes ( allow Open Registration; Free Subscribers at Level #0 )</option>' . "\n";
166
  echo '</select><br />' . "\n";
167
- echo 'If you set this to <code>Yes</code>, you\'re unlocking <a href="' . add_query_arg ("action", "register", wp_login_url ()) . '" target="_blank" rel="external">wp-login.php?action=register</a> ( on your Main Site ). When a visitor registers without paying, they\'ll automatically become a Free Subscriber, at Level #0. The s2Member software reserves Level #0; to be used ONLY for Free Subscribers. All other Membership Levels [1-4] require payment.' . "\n";
168
  echo '</td>' . "\n";
169
  /**/
170
  echo '</tr>' . "\n";
@@ -186,9 +186,9 @@ if (is_multisite () && is_main_site ()) /* These panels will ONLY be available o
186
  /**/
187
  echo '<td style="padding-bottom:0;">' . "\n";
188
  echo '<select name="ws_plugin__s2member_mms_registration_grants" id="ws-plugin--s2member-mms-registration-grants">' . "\n";
189
- echo '<option value="none"' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_registration_grants"] === "none") ? ' selected="selected"' : '') . '>No ( do NOT allow Open Registration )</option>' . "\n";
190
- echo '<option value="user"' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_registration_grants"] === "user") ? ' selected="selected"' : '') . '>Yes ( allow Open Registration; Free Subscribers at Level #0 )</option>' . "\n";
191
- echo '<option value="all"' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_registration_grants"] === "all") ? ' selected="selected"' : '') . '>Yes ( allow Open Registration; Free Subscribers, with a free Blog too )</option>' . "\n";
192
  echo '</select><br />' . "\n";
193
  echo 'If you set this to <code>Yes</code>, you\'re unlocking <a href="' . apply_filters ("wp_signup_location", get_bloginfo ("wpurl") . "/wp-signup.php") . '" target="_blank" rel="external">wp-signup.php</a> ( on your Main Site ).' . "\n";
194
  echo '</td>' . "\n";
98
  echo '<img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/large-icon.png" title="s2Member ( a Membership management system for WordPress® )" alt="" style="float:right; margin:0 0 0 25px; border:0;" />' . "\n";
99
  echo '<h3>Multisite Registration ( Main Site Configuration )</h3>' . "\n";
100
  echo '<p>s2Member supports Free Subscribers ( at Level #0 ), along with four Primary Levels [1-4] of paid Membership. If you want your visitors to be capable of registering absolutely free, you will want to "allow" Open Registration. Whenever a visitor registers without paying, they\'ll automatically become a Free Subscriber, at Level #0. &nbsp;&nbsp;<strong>With Multisite Networking enabled</strong>, your ( Main Site ) could ALSO offer a Customer access to create a Blog of their own, where a Customer becomes a "Member" of your ( Main Site ), and also a Blog Owner/Administrator. With s2Member installed ( network wide ), each of your Blog Owners could offer Membership too, using a single copy of the s2Member plugin ( which is a great selling point<em>!</em> ). We refer to this as a Multisite Blog Farm.</p>' . "\n";
101
+ echo '<p>Multisite Networking also makes a new Registration Form available ( driven by your theme ); which we refer to as ( <code>wp-signup.php</code> ). If you\'re planning to offer Blogs, you MUST use <a href="' . apply_filters ("wp_signup_location", get_bloginfo ("wpurl") . "/wp-signup.php") . '" target="_blank" rel="external">wp-signup.php</a>, instead of using the Standard Login/Registration Form. In a Multisite installation, we refer to the Standard Login/Registration Form, as ( <code>wp-login.php?action=register</code> ). If you\'re planning to offer Membership Access only, and NOT Blogs, you can just use the <a href="' . add_query_arg ("action", urlencode ("register"), wp_login_url ()) . '" target="_blank" rel="external">Standard Login/Registration Form</a>, which is easily customized through <code>s2Member -> General Options -> Login/Registration Design</code>.</p>' . "\n";
102
  do_action ("ws_plugin__s2member_during_mms_options_page_during_left_sections_during_mms_registration", get_defined_vars ());
103
  echo '<div id="ws-plugin--s2member-mms-registration-support-package-details-wrapper">' . "\n";
104
  echo '<h3>Running a Multisite Blog Farm? ( <a href="#" onclick="jQuery(\'div#ws-plugin--s2member-mms-registration-support-package-details\').toggle(); return false;" class="ws-dotted-link">please read</a> )</h3>' . "\n";
132
  else
133
  {
134
  echo '<select name="ws_plugin__s2member_mms_registration_file" id="ws-plugin--s2member-mms-registration-file">' . "\n";
135
+ echo '<option value="wp-login"' . ( ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_registration_file"] === "wp-login") ? ' selected="selected"' : '') . '>Membership Only ( I\'m NOT offering Blogs )</option>' . "\n";
136
+ echo '<option value="wp-signup"' . ( ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_registration_file"] === "wp-signup") ? ' selected="selected"' : '') . '>Blog Farm ( I plan to offer both Membership &amp; Blog creation )</option>' . "\n";
137
  echo '</select><br />' . "\n";
138
  echo 'Depending on your selection, the options below may change.' . "\n";
139
  }
161
  /**/
162
  echo '<td>' . "\n";
163
  echo '<select name="ws_plugin__s2member_allow_subscribers_in" id="ws-plugin--s2member-allow-subscribers-in">' . "\n";
164
+ echo '<option value="0"' . ( (!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["allow_subscribers_in"]) ? ' selected="selected"' : '') . '>No ( do NOT allow Open Registration )</option>' . "\n";
165
+ echo '<option value="1"' . ( ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["allow_subscribers_in"]) ? ' selected="selected"' : '') . '>Yes ( allow Open Registration; Free Subscribers at Level #0 )</option>' . "\n";
166
  echo '</select><br />' . "\n";
167
+ echo 'If you set this to <code>Yes</code>, you\'re unlocking <a href="' . add_query_arg ("action", urlencode ("register"), wp_login_url ()) . '" target="_blank" rel="external">wp-login.php?action=register</a> ( on your Main Site ). When a visitor registers without paying, they\'ll automatically become a Free Subscriber, at Level #0. The s2Member software reserves Level #0; to be used ONLY for Free Subscribers. All other Membership Levels [1-4] require payment.' . "\n";
168
  echo '</td>' . "\n";
169
  /**/
170
  echo '</tr>' . "\n";
186
  /**/
187
  echo '<td style="padding-bottom:0;">' . "\n";
188
  echo '<select name="ws_plugin__s2member_mms_registration_grants" id="ws-plugin--s2member-mms-registration-grants">' . "\n";
189
+ echo '<option value="none"' . ( ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_registration_grants"] === "none") ? ' selected="selected"' : '') . '>No ( do NOT allow Open Registration )</option>' . "\n";
190
+ echo '<option value="user"' . ( ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_registration_grants"] === "user") ? ' selected="selected"' : '') . '>Yes ( allow Open Registration; Free Subscribers at Level #0 )</option>' . "\n";
191
+ echo '<option value="all"' . ( ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["mms_registration_grants"] === "all") ? ' selected="selected"' : '') . '>Yes ( allow Open Registration; Free Subscribers, with a free Blog too )</option>' . "\n";
192
  echo '</select><br />' . "\n";
193
  echo 'If you set this to <code>Yes</code>, you\'re unlocking <a href="' . apply_filters ("wp_signup_location", get_bloginfo ("wpurl") . "/wp-signup.php") . '" target="_blank" rel="external">wp-signup.php</a> ( on your Main Site ).' . "\n";
194
  echo '</td>' . "\n";
includes/menu-pages/options.inc.php CHANGED
@@ -161,7 +161,7 @@ if (apply_filters ("ws_plugin__s2member_during_options_page_during_left_sections
161
  echo '<option value="0"' . ( (!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["allow_subscribers_in"]) ? ' selected="selected"' : '') . '>No ( do NOT allow Open Registration )</option>' . "\n";
162
  echo '<option value="1"' . ( ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["allow_subscribers_in"]) ? ' selected="selected"' : '') . '>Yes ( allow Open Registration; Free Subscribers at Level #0 )</option>' . "\n";
163
  echo '</select><br />' . "\n";
164
- echo 'If you set this to <code>Yes</code>, you\'re unlocking <a href="' . add_query_arg ("action", "register", wp_login_url ()) . '" target="_blank" rel="external">wp-login.php?action=register</a>. When a visitor registers without paying, they\'ll automatically become a Free Subscriber, at Level #0. The s2Member software reserves Level #0; to be used ONLY for Free Subscribers. All other Membership Levels [1-4] require payment.' . "\n";
165
  echo '</td>' . "\n";
166
  /**/
167
  echo '</tr>' . "\n";
@@ -290,7 +290,7 @@ if (apply_filters ("ws_plugin__s2member_during_options_page_during_left_sections
290
  /**/
291
  echo '<div class="ws-menu-page-section ws-plugin--s2member-login-registration-section">' . "\n";
292
  echo '<h3>Login/Registration Page Customization ( required )</h3>' . "\n";
293
- echo '<p>These settings allow you to customize the user interface for your Login / Registration Pages:<br />( <a href="' . add_query_arg ("action", "register", wp_login_url ()) . '" target="_blank" rel="external">' . esc_html (add_query_arg ("action", "register", wp_login_url ())) . '</a> )</p>' . "\n";
294
  echo (is_multisite () && ws_plugin__s2member_is_multisite_farm () && is_main_site ()) ? '<p><em>A Multisite Blog Farm uses this Form instead, powered by your theme.<br />( <a href="' . apply_filters ("wp_signup_location", get_bloginfo ("wpurl") . "/wp-signup.php") . '" target="_blank" rel="external">' . esc_html (apply_filters ("wp_signup_location", get_bloginfo ("wpurl") . "/wp-signup.php")) . '</a> )</em></p>' . "\n" : '';
295
  do_action ("ws_plugin__s2member_during_options_page_during_left_sections_during_login_registration", get_defined_vars ());
296
  /**/
@@ -586,7 +586,7 @@ if (apply_filters ("ws_plugin__s2member_during_options_page_during_left_sections
586
  echo '<h3>Custom Registration Fields ( optional, for further customization )</h3>' . "\n";
587
  echo '<p>Some fields are already built-in by default. The defaults are: <code>*Username*, *Email*, *First Name*, *Last Name*</code>.</p>' . "\n";
588
  /**/
589
- echo '<p>Custom Fields will appear in your Standard Registration Form:<br />( <a href="' . add_query_arg ("action", "register", wp_login_url ()) . '" target="_blank" rel="external">' . esc_html (add_query_arg ("action", "register", wp_login_url ())) . '</a> )</p>' . "\n";
590
  echo (is_multisite () && ws_plugin__s2member_is_multisite_farm () && is_main_site ()) ? '<p><em>A Multisite Blog Farm uses this Form instead. It supports Custom Fields too.<br />( <a href="' . apply_filters ("wp_signup_location", get_bloginfo ("wpurl") . "/wp-signup.php") . '" target="_blank" rel="external">' . esc_html (apply_filters ("wp_signup_location", get_bloginfo ("wpurl") . "/wp-signup.php")) . '</a> )</em></p>' . "\n" : '';
591
  /**/
592
  if (defined ("BP_VERSION"))
@@ -680,7 +680,7 @@ if (apply_filters ("ws_plugin__s2member_during_options_page_during_left_sections
680
  echo '<option value="' . esc_attr ($ws_plugin__s2member_temp_o->ID) . '"' . ( (!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_redirection_override"] && $ws_plugin__s2member_temp_o->ID == $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"]) ? ' selected="selected"' : '') . '>' . esc_html ($ws_plugin__s2member_temp_o->post_title) . '</option>' . "\n";
681
  echo '</select><br />' . "\n";
682
  echo 'Please choose a Page to be used as the first page Members will see after logging in. This Page can contain anything you like. We recommend the following title: <code>Welcome To Our Members Area</code>.<br /><br />' . "\n";
683
- echo '&darr; 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 login ( their Username, lowercase ).\\n%%current_user_id%% = The current User\\\'s ID.\\n%%current_user_level%% = The current User\\\'s s2Member Level.\\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: ' . get_bloginfo ("wpurl") . '/members/%%current_user_login%%/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";
684
  echo '<input type="text" 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";
685
  echo '</td>' . "\n";
686
  /**/
@@ -1180,7 +1180,7 @@ if (apply_filters ("ws_plugin__s2member_during_options_page_during_left_sections
1180
  echo '<div class="ws-menu-page-section ws-plugin--s2member-uri-level-access-section">' . "\n";
1181
  echo '<h3>URI Level Access Restrictions ( optional )</h3>' . "\n";
1182
  echo '<p>Here you can specify URIs ( or word fragments found in URIs ) that are restricted to certain Membership Access Levels. Control over URIs is a little more complex. This section is intended for advanced webmasters only. That being said, here are the basics... A REQUEST_URI, is the portion of the URL that comes after the domain. This is a URL <code>http://www.example.com/path/to/file.php</code>, and this is the URI: <code>/path/to/file.php</code>.</p>' . "\n";
1183
- echo '<p>In the fields below, you can provide a list ( one per line ) of URIs on your site that should be off-limits based on Membership Level. You can also use word fragments instead of a full URI. If a word fragment is found anywhere in the URI, it will be protected. Wildcards and other regex patterns are not supported here, and therefore you don\'t need to escape special characters or anything. Please note, these ARE caSe sensitive. You must be specific with respect to case sensitivity. The word fragment <code>some-path/</code> would NOT match a URI that contains <code>some-Path/</code>. <em>A few <a href="#" onclick="alert(\'URI Replacement Codes:\\n\\n%%current_user_login%% = The current User\\\'s login ( their Username, lowercase ).\\n%%current_user_id%% = The current User\\\'s ID.\\n%%current_user_level%% = The current User\\\'s s2Member Level.\\n\\nFor example, if you\\\'re using BuddyPress, and want to protect BuddyPress Groups, you could add URI protection, like this: /members/%%current_user_login%%/groups/\'); return false;">Replacement Codes</a> are also supported here.</em></p>' . "\n";
1184
  do_action ("ws_plugin__s2member_during_options_page_during_left_sections_during_uri_level_access", get_defined_vars ());
1185
  /**/
1186
  echo '<table class="form-table">' . "\n";
@@ -1379,7 +1379,6 @@ if (apply_filters ("ws_plugin__s2member_during_options_page_during_left_sections
1379
  echo '<h3>Unique IP Access Restrictions ( prevents username/link sharing )</h3>' . "\n";
1380
  echo '<input type="button" id="ws-plugin--s2member-ip-restrictions-reset-button" value="Reset IP Restriction Logs" class="ws-menu-page-right" style="min-width:175px;" />' . "\n";
1381
  echo '<p>As with any Membership system, it is possible for one Member to signup, and then share their Username with someone else; or even post it online for the whole world to see. This is known as Link Sharing ( aka: Username Sharing ). It is NOT likely that you\'ll be attacked in this way, but it\'s still a good idea to protect your system; just in case somebody tries this. s2Member\'s IP Restrictions work for Membership Level Access ( account logins ), Specific Post/Page Access, Registration Links, and other secure Entry Points. In all cases, the rules are simple. A single Username, Access Link, and/or Entry Point ... is only valid for a certain number of unique IP addresses. Once that limit is reached, s2Member assumes there has been a security breach. At that time, s2Member will place a temporary ban ( preventing access ) to a Specific Post/Page, or to an account associated with a particular Username. This temporary ban, will ONLY affect the offending Link and/or Username associated with the security breach. You can fine-tune this behavior, using the options below.</p>' . "\n";
1382
- echo '<p>This form of IP monitoring, is known as an (Adaptive Concurrency Restriction). We refer to this as "Adaptive", because the concurrency timeouts are increased automatically, based on the number of attempts that MAY take place over time. The default period of 30 days works on 99.9% of all installations. This period is renewed automatically, every time a new attempt is made. This allows s2Member to become more secure; with each attempt from a new location ( commonly associated with link sharing ). In other words, s2Member adapts itself to bad behavior, so it can ALSO crack-down on hacking attempts that may occur over a longer period of time. And without being SO paranoid that a legitimate Customer would have a problem.</p>' . "\n";
1383
  echo '<p><em>*Note* an empty IP address ( associated with someone browsing anonymously ), is also considered a unique IP address, so it cannot circumvent s2Member\'s security.</em></p>' . "\n";
1384
  do_action ("ws_plugin__s2member_during_options_page_during_left_sections_during_ip_restrictions", get_defined_vars ());
1385
  /**/
161
  echo '<option value="0"' . ( (!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["allow_subscribers_in"]) ? ' selected="selected"' : '') . '>No ( do NOT allow Open Registration )</option>' . "\n";
162
  echo '<option value="1"' . ( ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["allow_subscribers_in"]) ? ' selected="selected"' : '') . '>Yes ( allow Open Registration; Free Subscribers at Level #0 )</option>' . "\n";
163
  echo '</select><br />' . "\n";
164
+ echo 'If you set this to <code>Yes</code>, you\'re unlocking <a href="' . add_query_arg ("action", urlencode ("register"), wp_login_url ()) . '" target="_blank" rel="external">wp-login.php?action=register</a>. When a visitor registers without paying, they\'ll automatically become a Free Subscriber, at Level #0. The s2Member software reserves Level #0; to be used ONLY for Free Subscribers. All other Membership Levels [1-4] require payment.' . "\n";
165
  echo '</td>' . "\n";
166
  /**/
167
  echo '</tr>' . "\n";
290
  /**/
291
  echo '<div class="ws-menu-page-section ws-plugin--s2member-login-registration-section">' . "\n";
292
  echo '<h3>Login/Registration Page Customization ( required )</h3>' . "\n";
293
+ echo '<p>These settings allow you to customize the user interface for your Login / Registration Pages:<br />( <a href="' . add_query_arg ("action", urlencode ("register"), wp_login_url ()) . '" target="_blank" rel="external">' . esc_html (add_query_arg ("action", urlencode ("register"), wp_login_url ())) . '</a> )</p>' . "\n";
294
  echo (is_multisite () && ws_plugin__s2member_is_multisite_farm () && is_main_site ()) ? '<p><em>A Multisite Blog Farm uses this Form instead, powered by your theme.<br />( <a href="' . apply_filters ("wp_signup_location", get_bloginfo ("wpurl") . "/wp-signup.php") . '" target="_blank" rel="external">' . esc_html (apply_filters ("wp_signup_location", get_bloginfo ("wpurl") . "/wp-signup.php")) . '</a> )</em></p>' . "\n" : '';
295
  do_action ("ws_plugin__s2member_during_options_page_during_left_sections_during_login_registration", get_defined_vars ());
296
  /**/
586
  echo '<h3>Custom Registration Fields ( optional, for further customization )</h3>' . "\n";
587
  echo '<p>Some fields are already built-in by default. The defaults are: <code>*Username*, *Email*, *First Name*, *Last Name*</code>.</p>' . "\n";
588
  /**/
589
+ echo '<p>Custom Fields will appear in your Standard Registration Form:<br />( <a href="' . add_query_arg ("action", urlencode ("register"), wp_login_url ()) . '" target="_blank" rel="external">' . esc_html (add_query_arg ("action", urlencode ("register"), wp_login_url ())) . '</a> )</p>' . "\n";
590
  echo (is_multisite () && ws_plugin__s2member_is_multisite_farm () && is_main_site ()) ? '<p><em>A Multisite Blog Farm uses this Form instead. It supports Custom Fields too.<br />( <a href="' . apply_filters ("wp_signup_location", get_bloginfo ("wpurl") . "/wp-signup.php") . '" target="_blank" rel="external">' . esc_html (apply_filters ("wp_signup_location", get_bloginfo ("wpurl") . "/wp-signup.php")) . '</a> )</em></p>' . "\n" : '';
591
  /**/
592
  if (defined ("BP_VERSION"))
680
  echo '<option value="' . esc_attr ($ws_plugin__s2member_temp_o->ID) . '"' . ( (!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_redirection_override"] && $ws_plugin__s2member_temp_o->ID == $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"]) ? ' selected="selected"' : '') . '>' . esc_html ($ws_plugin__s2member_temp_o->post_title) . '</option>' . "\n";
681
  echo '</select><br />' . "\n";
682
  echo 'Please choose a Page to be used as the first page Members will see after logging in. This Page can contain anything you like. We recommend the following title: <code>Welcome To Our Members Area</code>.<br /><br />' . "\n";
683
+ echo '&darr; 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 login ( their Username, lowercase ).\\n%%current_user_id%% = The current User\\\'s ID.\\n%%current_user_level%% = The current User\\\'s s2Member Level.\\n%%current_user_role%% = The current User\\\'s WordPress® Role.\\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: ' . get_bloginfo ("wpurl") . '/members/%%current_user_login%%/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";
684
  echo '<input type="text" 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";
685
  echo '</td>' . "\n";
686
  /**/
1180
  echo '<div class="ws-menu-page-section ws-plugin--s2member-uri-level-access-section">' . "\n";
1181
  echo '<h3>URI Level Access Restrictions ( optional )</h3>' . "\n";
1182
  echo '<p>Here you can specify URIs ( or word fragments found in URIs ) that are restricted to certain Membership Access Levels. Control over URIs is a little more complex. This section is intended for advanced webmasters only. That being said, here are the basics... A REQUEST_URI, is the portion of the URL that comes after the domain. This is a URL <code>http://www.example.com/path/to/file.php</code>, and this is the URI: <code>/path/to/file.php</code>.</p>' . "\n";
1183
+ echo '<p>In the fields below, you can provide a list ( one per line ) of URIs on your site that should be off-limits based on Membership Level. You can also use word fragments instead of a full URI. If a word fragment is found anywhere in the URI, it will be protected. Wildcards and other regex patterns are not supported here, and therefore you don\'t need to escape special characters or anything. Please note, these ARE caSe sensitive. You must be specific with respect to case sensitivity. The word fragment <code>some-path/</code> would NOT match a URI that contains <code>some-Path/</code>. <em>A few <a href="#" onclick="alert(\'URI Replacement Codes:\\n\\n%%current_user_login%% = The current User\\\'s login ( their Username, lowercase ).\\n%%current_user_id%% = The current User\\\'s ID.\\n%%current_user_level%% = The current User\\\'s s2Member Level.\\n%%current_user_role%% = The current User\\\'s WordPress® Role.\\n\\nFor example, if you\\\'re using BuddyPress, and want to protect BuddyPress Groups, you could add URI protection, like this: /members/%%current_user_login%%/groups/\'); return false;">Replacement Codes</a> are also supported here.</em></p>' . "\n";
1184
  do_action ("ws_plugin__s2member_during_options_page_during_left_sections_during_uri_level_access", get_defined_vars ());
1185
  /**/
1186
  echo '<table class="form-table">' . "\n";
1379
  echo '<h3>Unique IP Access Restrictions ( prevents username/link sharing )</h3>' . "\n";
1380
  echo '<input type="button" id="ws-plugin--s2member-ip-restrictions-reset-button" value="Reset IP Restriction Logs" class="ws-menu-page-right" style="min-width:175px;" />' . "\n";
1381
  echo '<p>As with any Membership system, it is possible for one Member to signup, and then share their Username with someone else; or even post it online for the whole world to see. This is known as Link Sharing ( aka: Username Sharing ). It is NOT likely that you\'ll be attacked in this way, but it\'s still a good idea to protect your system; just in case somebody tries this. s2Member\'s IP Restrictions work for Membership Level Access ( account logins ), Specific Post/Page Access, Registration Links, and other secure Entry Points. In all cases, the rules are simple. A single Username, Access Link, and/or Entry Point ... is only valid for a certain number of unique IP addresses. Once that limit is reached, s2Member assumes there has been a security breach. At that time, s2Member will place a temporary ban ( preventing access ) to a Specific Post/Page, or to an account associated with a particular Username. This temporary ban, will ONLY affect the offending Link and/or Username associated with the security breach. You can fine-tune this behavior, using the options below.</p>' . "\n";
 
1382
  echo '<p><em>*Note* an empty IP address ( associated with someone browsing anonymously ), is also considered a unique IP address, so it cannot circumvent s2Member\'s security.</em></p>' . "\n";
1383
  do_action ("ws_plugin__s2member_during_options_page_during_left_sections_during_ip_restrictions", get_defined_vars ());
1384
  /**/
includes/menu-pages/paypal-buttons.inc.php CHANGED
@@ -55,9 +55,10 @@ if (apply_filters ("ws_plugin__s2member_during_paypal_buttons_page_during_left_s
55
  /**/
56
  echo '<td>' . "\n";
57
  echo '<form onsubmit="return false;">' . "\n";
58
- echo '<p id="ws-plugin--s2member-level1-trial-line">I\'ll offer the first <input type="text" id="ws-plugin--s2member-level1-trial-period" value="0" size="6" /> <select id="ws-plugin--s2member-level1-trial-term">' . file_get_contents (dirname (dirname (__FILE__)) . "/templates/options/paypal-membership-trial-terms.html") . '</select> <input type="hidden" id="ws-plugin--s2member-level1-trial-amount" value="0" />free.</p>' . "\n";
59
  echo '<p><span id="ws-plugin--s2member-level1-trial-then">Then, </span>I want to charge: $<input type="text" id="ws-plugin--s2member-level1-amount" value="0.01" size="4" /> / <select id="ws-plugin--s2member-level1-term">' . file_get_contents (dirname (dirname (__FILE__)) . "/templates/options/paypal-membership-regular-terms.html") . '</select></p>' . "\n";
60
  echo '<p>Checkout Page Style <a href="#" onclick="alert(\'Optional. This can be configured inside your PayPal® account. PayPal® allows you to create Custom Page Styles, and assign a unique name to them. You can add your own header image and color selection to the checkout form. Once you\\\'ve created a Custom Page Style at PayPal®, you can enter that Page Style here.\\n\\nIn addition. The Shortcode below, provided by s2Member; supports an image attribute: image=\\\'\\\'default\\\'\\\'. This can be changed to a full URL, pointing to a custom image of your own; instead of the default PayPal® Button image.\'); return false;" tabindex="-1">[?]</a>: <input type="text" id="ws-plugin--s2member-level1-page-style" value="paypal" size="18" /> <select id="ws-plugin--s2member-level1-currency">' . file_get_contents (dirname (dirname (__FILE__)) . "/templates/options/paypal-currencies.html") . '</select> <input type="button" value="Generate Button Code" onclick="ws_plugin__s2member_paypalButtonGenerate(\'level1\');" class="button-primary" /></p>' . "\n";
 
61
  echo '<p' . ( (is_multisite () && ws_plugin__s2member_is_multisite_farm () && !is_main_site ()) ? ' style="display:none;"' : '') . '>Custom Capabilities ( comma delimited ) <a href="#" onclick="alert(\'Optional. This is VERY advanced. For full details, see:\\ns2Member -> API Scripting -> Custom Capabilities.\'); return false;" tabindex="-1">[?]</a> <input type="text" id="ws-plugin--s2member-level1-ccaps" size="40" maxlength="125" /></p>' . "\n";
62
  echo '</form>' . "\n";
63
  echo '</td>' . "\n";
@@ -70,9 +71,9 @@ if (apply_filters ("ws_plugin__s2member_during_paypal_buttons_page_during_left_s
70
  do_action ("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_during_level1_buttons_before_shortcode", get_defined_vars ());
71
  echo '<strong>WordPress® Shortcode:</strong> ( recommended for both the WordPress® Visual &amp; HTML Editors )<br />' . "\n";
72
  $ws_plugin__s2member_temp_s = trim (file_get_contents (dirname (dirname (__FILE__)) . "/templates/shortcodes/paypal-checkout-button-shortcode.html"));
73
- $ws_plugin__s2member_temp_s = preg_replace ("/%%domain%%/", ws_plugin__s2member_esc_ds (esc_attr ($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_temp_s);
74
  $ws_plugin__s2member_temp_s = preg_replace ("/%%level%%/", ws_plugin__s2member_esc_ds (esc_attr ("1")), $ws_plugin__s2member_temp_s);
75
  $ws_plugin__s2member_temp_s = preg_replace ("/%%level_label%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_label"])), $ws_plugin__s2member_temp_s);
 
76
  echo '<input id="ws-plugin--s2member-level1-shortcode" type="text" value="' . format_to_edit ($ws_plugin__s2member_temp_s) . '" onclick="this.select ();" style="font-family:Consolas, monospace; width:99%;" />' . "\n";
77
  /**/
78
  echo '<div' . ( (is_multisite () && ws_plugin__s2member_is_multisite_farm () && !is_main_site ()) ? ' style="display:none;"' : '') . '><br />' . "\n";
@@ -81,15 +82,18 @@ if (apply_filters ("ws_plugin__s2member_during_paypal_buttons_page_during_left_s
81
  $ws_plugin__s2member_temp_s = trim (file_get_contents (dirname (dirname (__FILE__)) . "/templates/buttons/paypal-checkout-button.html"));
82
  $ws_plugin__s2member_temp_s = preg_replace ("/%%endpoint%%/", ws_plugin__s2member_esc_ds (esc_attr (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com")), $ws_plugin__s2member_temp_s);
83
  $ws_plugin__s2member_temp_s = preg_replace ("/%%paypal_business%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $ws_plugin__s2member_temp_s);
 
84
  $ws_plugin__s2member_temp_s = preg_replace ("/%%level_label%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_label"])), $ws_plugin__s2member_temp_s);
85
  $ws_plugin__s2member_temp_s = preg_replace ("/%%cancel_return%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("url"))), $ws_plugin__s2member_temp_s);
86
  $ws_plugin__s2member_temp_s = preg_replace ("/%%notify_url%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl") . "/?s2member_paypal_notify=1")), $ws_plugin__s2member_temp_s);
87
  $ws_plugin__s2member_temp_s = preg_replace ("/%%return%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl") . "/?s2member_paypal_return=1")), $ws_plugin__s2member_temp_s);
88
- $ws_plugin__s2member_temp_s = preg_replace ("/%%domain%%/", ws_plugin__s2member_esc_ds (esc_attr ($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_temp_s);
89
- $ws_plugin__s2member_temp_s = preg_replace ("/%%level%%/", ws_plugin__s2member_esc_ds (esc_attr ("1")), $ws_plugin__s2member_temp_s);
 
90
  echo format_to_edit ($ws_plugin__s2member_temp_s);
91
  echo '</textarea><br />' . "\n";
92
- echo '&uarr; Use this more advanced Code if you\'re building a theme or plugin that integrates with s2Member.' . "\n";
 
93
  echo '</div>' . "\n";
94
  /**/
95
  echo '</form>' . "\n";
@@ -130,9 +134,10 @@ if (apply_filters ("ws_plugin__s2member_during_paypal_buttons_page_during_left_s
130
  /**/
131
  echo '<td>' . "\n";
132
  echo '<form onsubmit="return false;">' . "\n";
133
- echo '<p id="ws-plugin--s2member-level2-trial-line">I\'ll offer the first <input type="text" id="ws-plugin--s2member-level2-trial-period" value="0" size="6" /> <select id="ws-plugin--s2member-level2-trial-term">' . file_get_contents (dirname (dirname (__FILE__)) . "/templates/options/paypal-membership-trial-terms.html") . '</select> <input type="hidden" id="ws-plugin--s2member-level2-trial-amount" value="0" />free.</p>' . "\n";
134
  echo '<p><span id="ws-plugin--s2member-level2-trial-then">Then, </span>I want to charge: $<input type="text" id="ws-plugin--s2member-level2-amount" value="0.01" size="4" /> / <select id="ws-plugin--s2member-level2-term">' . file_get_contents (dirname (dirname (__FILE__)) . "/templates/options/paypal-membership-regular-terms.html") . '</select></p>' . "\n";
135
  echo '<p>Checkout Page Style <a href="#" onclick="alert(\'Optional. This can be configured inside your PayPal® account. PayPal® allows you to create Custom Page Styles, and assign a unique name to them. You can add your own header image and color selection to the checkout form. Once you\\\'ve created a Custom Page Style at PayPal®, you can enter that Page Style here.\\n\\nIn addition. The Shortcode below, provided by s2Member; supports an image attribute: image=\\\'\\\'default\\\'\\\'. This can be changed to a full URL, pointing to a custom image of your own; instead of the default PayPal® Button image.\'); return false;" tabindex="-1">[?]</a>: <input type="text" id="ws-plugin--s2member-level2-page-style" value="paypal" size="18" /> <select id="ws-plugin--s2member-level2-currency">' . file_get_contents (dirname (dirname (__FILE__)) . "/templates/options/paypal-currencies.html") . '</select> <input type="button" value="Generate Button Code" onclick="ws_plugin__s2member_paypalButtonGenerate(\'level2\');" class="button-primary" /></p>' . "\n";
 
136
  echo '<p' . ( (is_multisite () && ws_plugin__s2member_is_multisite_farm () && !is_main_site ()) ? ' style="display:none;"' : '') . '>Custom Capabilities ( comma delimited ) <a href="#" onclick="alert(\'Optional. This is VERY advanced. For full details, see:\\ns2Member -> API Scripting -> Custom Capabilities.\'); return false;" tabindex="-1">[?]</a> <input type="text" id="ws-plugin--s2member-level2-ccaps" size="40" maxlength="125" /></p>' . "\n";
137
  echo '</form>' . "\n";
138
  echo '</td>' . "\n";
@@ -145,9 +150,9 @@ if (apply_filters ("ws_plugin__s2member_during_paypal_buttons_page_during_left_s
145
  do_action ("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_during_level2_buttons_before_shortcode", get_defined_vars ());
146
  echo '<strong>WordPress® Shortcode:</strong> ( recommended for both the WordPress® Visual &amp; HTML Editors )<br />' . "\n";
147
  $ws_plugin__s2member_temp_s = trim (file_get_contents (dirname (dirname (__FILE__)) . "/templates/shortcodes/paypal-checkout-button-shortcode.html"));
148
- $ws_plugin__s2member_temp_s = preg_replace ("/%%domain%%/", ws_plugin__s2member_esc_ds (esc_attr ($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_temp_s);
149
  $ws_plugin__s2member_temp_s = preg_replace ("/%%level%%/", ws_plugin__s2member_esc_ds (esc_attr ("2")), $ws_plugin__s2member_temp_s);
150
  $ws_plugin__s2member_temp_s = preg_replace ("/%%level_label%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_label"])), $ws_plugin__s2member_temp_s);
 
151
  echo '<input id="ws-plugin--s2member-level2-shortcode" type="text" value="' . format_to_edit ($ws_plugin__s2member_temp_s) . '" onclick="this.select ();" style="font-family:Consolas, monospace; width:99%;" />' . "\n";
152
  /**/
153
  echo '<div' . ( (is_multisite () && ws_plugin__s2member_is_multisite_farm () && !is_main_site ()) ? ' style="display:none;"' : '') . '><br />' . "\n";
@@ -156,15 +161,18 @@ if (apply_filters ("ws_plugin__s2member_during_paypal_buttons_page_during_left_s
156
  $ws_plugin__s2member_temp_s = trim (file_get_contents (dirname (dirname (__FILE__)) . "/templates/buttons/paypal-checkout-button.html"));
157
  $ws_plugin__s2member_temp_s = preg_replace ("/%%endpoint%%/", ws_plugin__s2member_esc_ds (esc_attr (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com")), $ws_plugin__s2member_temp_s);
158
  $ws_plugin__s2member_temp_s = preg_replace ("/%%paypal_business%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $ws_plugin__s2member_temp_s);
 
159
  $ws_plugin__s2member_temp_s = preg_replace ("/%%level_label%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_label"])), $ws_plugin__s2member_temp_s);
160
  $ws_plugin__s2member_temp_s = preg_replace ("/%%cancel_return%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("url"))), $ws_plugin__s2member_temp_s);
161
  $ws_plugin__s2member_temp_s = preg_replace ("/%%notify_url%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl") . "/?s2member_paypal_notify=1")), $ws_plugin__s2member_temp_s);
162
  $ws_plugin__s2member_temp_s = preg_replace ("/%%return%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl") . "/?s2member_paypal_return=1")), $ws_plugin__s2member_temp_s);
163
- $ws_plugin__s2member_temp_s = preg_replace ("/%%domain%%/", ws_plugin__s2member_esc_ds (esc_attr ($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_temp_s);
164
- $ws_plugin__s2member_temp_s = preg_replace ("/%%level%%/", ws_plugin__s2member_esc_ds (esc_attr ("2")), $ws_plugin__s2member_temp_s);
 
165
  echo format_to_edit ($ws_plugin__s2member_temp_s);
166
  echo '</textarea><br />' . "\n";
167
- echo '&uarr; Use this more advanced Code if you\'re building a theme or plugin that integrates with s2Member.' . "\n";
 
168
  echo '</div>' . "\n";
169
  /**/
170
  echo '</form>' . "\n";
@@ -205,9 +213,10 @@ if (apply_filters ("ws_plugin__s2member_during_paypal_buttons_page_during_left_s
205
  /**/
206
  echo '<td>' . "\n";
207
  echo '<form onsubmit="return false;">' . "\n";
208
- echo '<p id="ws-plugin--s2member-level3-trial-line">I\'ll offer the first <input type="text" id="ws-plugin--s2member-level3-trial-period" value="0" size="6" /> <select id="ws-plugin--s2member-level3-trial-term">' . file_get_contents (dirname (dirname (__FILE__)) . "/templates/options/paypal-membership-trial-terms.html") . '</select> <input type="hidden" id="ws-plugin--s2member-level3-trial-amount" value="0" />free.</p>' . "\n";
209
  echo '<p><span id="ws-plugin--s2member-level3-trial-then">Then, </span>I want to charge: $<input type="text" id="ws-plugin--s2member-level3-amount" value="0.01" size="4" /> / <select id="ws-plugin--s2member-level3-term">' . file_get_contents (dirname (dirname (__FILE__)) . "/templates/options/paypal-membership-regular-terms.html") . '</select></p>' . "\n";
210
  echo '<p>Checkout Page Style <a href="#" onclick="alert(\'Optional. This can be configured inside your PayPal® account. PayPal® allows you to create Custom Page Styles, and assign a unique name to them. You can add your own header image and color selection to the checkout form. Once you\\\'ve created a Custom Page Style at PayPal®, you can enter that Page Style here.\\n\\nIn addition. The Shortcode below, provided by s2Member; supports an image attribute: image=\\\'\\\'default\\\'\\\'. This can be changed to a full URL, pointing to a custom image of your own; instead of the default PayPal® Button image.\'); return false;" tabindex="-1">[?]</a>: <input type="text" id="ws-plugin--s2member-level3-page-style" value="paypal" size="18" /> <select id="ws-plugin--s2member-level3-currency">' . file_get_contents (dirname (dirname (__FILE__)) . "/templates/options/paypal-currencies.html") . '</select> <input type="button" value="Generate Button Code" onclick="ws_plugin__s2member_paypalButtonGenerate(\'level3\');" class="button-primary" /></p>' . "\n";
 
211
  echo '<p' . ( (is_multisite () && ws_plugin__s2member_is_multisite_farm () && !is_main_site ()) ? ' style="display:none;"' : '') . '>Custom Capabilities ( comma delimited ) <a href="#" onclick="alert(\'Optional. This is VERY advanced. For full details, see:\\ns2Member -> API Scripting -> Custom Capabilities.\'); return false;" tabindex="-1">[?]</a> <input type="text" id="ws-plugin--s2member-level3-ccaps" size="40" maxlength="125" /></p>' . "\n";
212
  echo '</form>' . "\n";
213
  echo '</td>' . "\n";
@@ -220,9 +229,9 @@ if (apply_filters ("ws_plugin__s2member_during_paypal_buttons_page_during_left_s
220
  do_action ("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_during_level3_buttons_before_shortcode", get_defined_vars ());
221
  echo '<strong>WordPress® Shortcode:</strong> ( recommended for both the WordPress® Visual &amp; HTML Editors )<br />' . "\n";
222
  $ws_plugin__s2member_temp_s = trim (file_get_contents (dirname (dirname (__FILE__)) . "/templates/shortcodes/paypal-checkout-button-shortcode.html"));
223
- $ws_plugin__s2member_temp_s = preg_replace ("/%%domain%%/", ws_plugin__s2member_esc_ds (esc_attr ($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_temp_s);
224
  $ws_plugin__s2member_temp_s = preg_replace ("/%%level%%/", ws_plugin__s2member_esc_ds (esc_attr ("3")), $ws_plugin__s2member_temp_s);
225
  $ws_plugin__s2member_temp_s = preg_replace ("/%%level_label%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_label"])), $ws_plugin__s2member_temp_s);
 
226
  echo '<input id="ws-plugin--s2member-level3-shortcode" type="text" value="' . format_to_edit ($ws_plugin__s2member_temp_s) . '" onclick="this.select ();" style="font-family:Consolas, monospace; width:99%;" />' . "\n";
227
  /**/
228
  echo '<div' . ( (is_multisite () && ws_plugin__s2member_is_multisite_farm () && !is_main_site ()) ? ' style="display:none;"' : '') . '><br />' . "\n";
@@ -231,15 +240,18 @@ if (apply_filters ("ws_plugin__s2member_during_paypal_buttons_page_during_left_s
231
  $ws_plugin__s2member_temp_s = trim (file_get_contents (dirname (dirname (__FILE__)) . "/templates/buttons/paypal-checkout-button.html"));
232
  $ws_plugin__s2member_temp_s = preg_replace ("/%%endpoint%%/", ws_plugin__s2member_esc_ds (esc_attr (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com")), $ws_plugin__s2member_temp_s);
233
  $ws_plugin__s2member_temp_s = preg_replace ("/%%paypal_business%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $ws_plugin__s2member_temp_s);
 
234
  $ws_plugin__s2member_temp_s = preg_replace ("/%%level_label%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_label"])), $ws_plugin__s2member_temp_s);
235
  $ws_plugin__s2member_temp_s = preg_replace ("/%%cancel_return%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("url"))), $ws_plugin__s2member_temp_s);
236
  $ws_plugin__s2member_temp_s = preg_replace ("/%%notify_url%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl") . "/?s2member_paypal_notify=1")), $ws_plugin__s2member_temp_s);
237
  $ws_plugin__s2member_temp_s = preg_replace ("/%%return%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl") . "/?s2member_paypal_return=1")), $ws_plugin__s2member_temp_s);
238
- $ws_plugin__s2member_temp_s = preg_replace ("/%%domain%%/", ws_plugin__s2member_esc_ds (esc_attr ($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_temp_s);
239
- $ws_plugin__s2member_temp_s = preg_replace ("/%%level%%/", ws_plugin__s2member_esc_ds (esc_attr ("3")), $ws_plugin__s2member_temp_s);
 
240
  echo format_to_edit ($ws_plugin__s2member_temp_s);
241
  echo '</textarea><br />' . "\n";
242
- echo '&uarr; Use this more advanced Code if you\'re building a theme or plugin that integrates with s2Member.' . "\n";
 
243
  echo '</div>' . "\n";
244
  /**/
245
  echo '</form>' . "\n";
@@ -280,9 +292,10 @@ if (apply_filters ("ws_plugin__s2member_during_paypal_buttons_page_during_left_s
280
  /**/
281
  echo '<td>' . "\n";
282
  echo '<form onsubmit="return false;">' . "\n";
283
- echo '<p id="ws-plugin--s2member-level4-trial-line">I\'ll offer the first <input type="text" id="ws-plugin--s2member-level4-trial-period" value="0" size="6" /> <select id="ws-plugin--s2member-level4-trial-term">' . file_get_contents (dirname (dirname (__FILE__)) . "/templates/options/paypal-membership-trial-terms.html") . '</select> <input type="hidden" id="ws-plugin--s2member-level4-trial-amount" value="0" />free.</p>' . "\n";
284
  echo '<p><span id="ws-plugin--s2member-level4-trial-then">Then, </span>I want to charge: $<input type="text" id="ws-plugin--s2member-level4-amount" value="0.01" size="4" /> / <select id="ws-plugin--s2member-level4-term">' . file_get_contents (dirname (dirname (__FILE__)) . "/templates/options/paypal-membership-regular-terms.html") . '</select></p>' . "\n";
285
  echo '<p>Checkout Page Style <a href="#" onclick="alert(\'Optional. This can be configured inside your PayPal® account. PayPal® allows you to create Custom Page Styles, and assign a unique name to them. You can add your own header image and color selection to the checkout form. Once you\\\'ve created a Custom Page Style at PayPal®, you can enter that Page Style here.\\n\\nIn addition. The Shortcode below, provided by s2Member; supports an image attribute: image=\\\'\\\'default\\\'\\\'. This can be changed to a full URL, pointing to a custom image of your own; instead of the default PayPal® Button image.\'); return false;" tabindex="-1">[?]</a>: <input type="text" id="ws-plugin--s2member-level4-page-style" value="paypal" size="18" /> <select id="ws-plugin--s2member-level4-currency">' . file_get_contents (dirname (dirname (__FILE__)) . "/templates/options/paypal-currencies.html") . '</select> <input type="button" value="Generate Button Code" onclick="ws_plugin__s2member_paypalButtonGenerate(\'level4\');" class="button-primary" /></p>' . "\n";
 
286
  echo '<p' . ( (is_multisite () && ws_plugin__s2member_is_multisite_farm () && !is_main_site ()) ? ' style="display:none;"' : '') . '>Custom Capabilities ( comma delimited ) <a href="#" onclick="alert(\'Optional. This is VERY advanced. For full details, see:\\ns2Member -> API Scripting -> Custom Capabilities.\'); return false;" tabindex="-1">[?]</a> <input type="text" id="ws-plugin--s2member-level4-ccaps" size="40" maxlength="125" /></p>' . "\n";
287
  echo '</form>' . "\n";
288
  echo '</td>' . "\n";
@@ -295,9 +308,9 @@ if (apply_filters ("ws_plugin__s2member_during_paypal_buttons_page_during_left_s
295
  do_action ("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_during_level4_buttons_before_shortcode", get_defined_vars ());
296
  echo '<strong>WordPress® Shortcode:</strong> ( recommended for both the WordPress® Visual &amp; HTML Editors )<br />' . "\n";
297
  $ws_plugin__s2member_temp_s = trim (file_get_contents (dirname (dirname (__FILE__)) . "/templates/shortcodes/paypal-checkout-button-shortcode.html"));
298
- $ws_plugin__s2member_temp_s = preg_replace ("/%%domain%%/", ws_plugin__s2member_esc_ds (esc_attr ($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_temp_s);
299
  $ws_plugin__s2member_temp_s = preg_replace ("/%%level%%/", ws_plugin__s2member_esc_ds (esc_attr ("4")), $ws_plugin__s2member_temp_s);
300
  $ws_plugin__s2member_temp_s = preg_replace ("/%%level_label%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_label"])), $ws_plugin__s2member_temp_s);
 
301
  echo '<input id="ws-plugin--s2member-level4-shortcode" type="text" value="' . format_to_edit ($ws_plugin__s2member_temp_s) . '" onclick="this.select ();" style="font-family:Consolas, monospace; width:99%;" />' . "\n";
302
  /**/
303
  echo '<div' . ( (is_multisite () && ws_plugin__s2member_is_multisite_farm () && !is_main_site ()) ? ' style="display:none;"' : '') . '><br />' . "\n";
@@ -306,15 +319,18 @@ if (apply_filters ("ws_plugin__s2member_during_paypal_buttons_page_during_left_s
306
  $ws_plugin__s2member_temp_s = trim (file_get_contents (dirname (dirname (__FILE__)) . "/templates/buttons/paypal-checkout-button.html"));
307
  $ws_plugin__s2member_temp_s = preg_replace ("/%%endpoint%%/", ws_plugin__s2member_esc_ds (esc_attr (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com")), $ws_plugin__s2member_temp_s);
308
  $ws_plugin__s2member_temp_s = preg_replace ("/%%paypal_business%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $ws_plugin__s2member_temp_s);
 
309
  $ws_plugin__s2member_temp_s = preg_replace ("/%%level_label%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_label"])), $ws_plugin__s2member_temp_s);
310
  $ws_plugin__s2member_temp_s = preg_replace ("/%%cancel_return%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("url"))), $ws_plugin__s2member_temp_s);
311
  $ws_plugin__s2member_temp_s = preg_replace ("/%%notify_url%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl") . "/?s2member_paypal_notify=1")), $ws_plugin__s2member_temp_s);
312
  $ws_plugin__s2member_temp_s = preg_replace ("/%%return%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl") . "/?s2member_paypal_return=1")), $ws_plugin__s2member_temp_s);
313
- $ws_plugin__s2member_temp_s = preg_replace ("/%%domain%%/", ws_plugin__s2member_esc_ds (esc_attr ($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_temp_s);
314
- $ws_plugin__s2member_temp_s = preg_replace ("/%%level%%/", ws_plugin__s2member_esc_ds (esc_attr ("4")), $ws_plugin__s2member_temp_s);
 
315
  echo format_to_edit ($ws_plugin__s2member_temp_s);
316
  echo '</textarea><br />' . "\n";
317
- echo '&uarr; Use this more advanced Code if you\'re building a theme or plugin that integrates with s2Member.' . "\n";
 
318
  echo '</div>' . "\n";
319
  /**/
320
  echo '</form>' . "\n";
@@ -359,9 +375,10 @@ if (apply_filters ("ws_plugin__s2member_during_paypal_buttons_page_during_left_s
359
  echo '<td>' . "\n";
360
  echo '<form onsubmit="return false;">' . "\n";
361
  echo '<p>Modification: <select id="ws-plugin--s2member-modification-level">' . file_get_contents (dirname (dirname (__FILE__)) . "/templates/options/paypal-membership-modification-levels.html") . '</select></p>' . "\n";
362
- echo '<p id="ws-plugin--s2member-modification-trial-line">I\'ll offer the first <input type="text" id="ws-plugin--s2member-modification-trial-period" value="0" size="6" /> <select id="ws-plugin--s2member-modification-trial-term">' . file_get_contents (dirname (dirname (__FILE__)) . "/templates/options/paypal-membership-trial-terms.html") . '</select> <input type="hidden" id="ws-plugin--s2member-modification-trial-amount" value="0" />free.</p>' . "\n";
363
  echo '<p><span id="ws-plugin--s2member-modification-trial-then">Then, </span>I want to charge: $<input type="text" id="ws-plugin--s2member-modification-amount" value="0.01" size="4" /> / <select id="ws-plugin--s2member-modification-term">' . file_get_contents (dirname (dirname (__FILE__)) . "/templates/options/paypal-membership-regular-terms.html") . '</select><span id="ws-plugin--s2member-modification-20p-rule"><br /><small>** Watch out for <a href="https://www.x.com/thread/41748" target="_blank" rel="external">the 20% rule</a>. Additional details on the 20% rule are <a href="https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_api_WPRecurringPayments#id086530108PM__id08653060UE6" target="_blank" rel="external">documented here</a>.</small></span></p>' . "\n";
364
  echo '<p>Checkout Page Style <a href="#" onclick="alert(\'Optional. This can be configured inside your PayPal® account. PayPal® allows you to create Custom Page Styles, and assign a unique name to them. You can add your own header image and color selection to the checkout form. Once you\\\'ve created a Custom Page Style at PayPal®, you can enter that Page Style here.\\n\\nIn addition. The Shortcode below, provided by s2Member; supports an image attribute: image=\\\'\\\'default\\\'\\\'. This can be changed to a full URL, pointing to a custom image of your own; instead of the default PayPal® Button image.\'); return false;" tabindex="-1">[?]</a>: <input type="text" id="ws-plugin--s2member-modification-page-style" value="paypal" size="18" /> <select id="ws-plugin--s2member-modification-currency">' . file_get_contents (dirname (dirname (__FILE__)) . "/templates/options/paypal-currencies.html") . '</select> <input type="button" value="Generate Button Code" onclick="ws_plugin__s2member_paypalButtonGenerate(\'modification\');" class="button-primary" /></p>' . "\n";
 
365
  echo '<p' . ( (is_multisite () && ws_plugin__s2member_is_multisite_farm () && !is_main_site ()) ? ' style="display:none;"' : '') . '>Custom Capabilities ( comma delimited ) <a href="#" onclick="alert(\'Optional. This is VERY advanced. For full details, see:\\ns2Member -> API Scripting -> Custom Capabilities.\'); return false;" tabindex="-1">[?]</a> <input type="text" id="ws-plugin--s2member-modification-ccaps" size="40" maxlength="125" /></p>' . "\n";
366
  echo '</form>' . "\n";
367
  echo '</td>' . "\n";
@@ -374,10 +391,10 @@ if (apply_filters ("ws_plugin__s2member_during_paypal_buttons_page_during_left_s
374
  do_action ("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_during_modification_buttons_before_shortcode", get_defined_vars ());
375
  echo '<strong>WordPress® Shortcode:</strong> ( recommended for both the WordPress® Visual &amp; HTML Editors )<br />' . "\n";
376
  $ws_plugin__s2member_temp_s = trim (file_get_contents (dirname (dirname (__FILE__)) . "/templates/shortcodes/paypal-checkout-button-shortcode.html"));
377
- $ws_plugin__s2member_temp_s = preg_replace ("/\/]$/", 'modify="1" /]', $ws_plugin__s2member_temp_s);
378
- $ws_plugin__s2member_temp_s = preg_replace ("/%%domain%%/", ws_plugin__s2member_esc_ds (esc_attr ($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_temp_s);
379
  $ws_plugin__s2member_temp_s = preg_replace ("/%%level%%/", ws_plugin__s2member_esc_ds (esc_attr ("2")), $ws_plugin__s2member_temp_s);
380
- $ws_plugin__s2member_temp_s = preg_replace ("/%%level_label%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_label"])), $ws_plugin__s2member_temp_s);
 
 
381
  echo '<input id="ws-plugin--s2member-modification-shortcode" type="text" value="' . format_to_edit ($ws_plugin__s2member_temp_s) . '" onclick="this.select ();" style="font-family:Consolas, monospace; width:99%;" />' . "\n";
382
  /**/
383
  echo '<div' . ( (is_multisite () && ws_plugin__s2member_is_multisite_farm () && !is_main_site ()) ? ' style="display:none;"' : '') . '><br />' . "\n";
@@ -387,15 +404,18 @@ if (apply_filters ("ws_plugin__s2member_during_paypal_buttons_page_during_left_s
387
  $ws_plugin__s2member_temp_s = preg_replace ('/name\="modify" value\="(.*?)"/', 'name="modify" value="1"', $ws_plugin__s2member_temp_s);
388
  $ws_plugin__s2member_temp_s = preg_replace ("/%%endpoint%%/", ws_plugin__s2member_esc_ds (esc_attr (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com")), $ws_plugin__s2member_temp_s);
389
  $ws_plugin__s2member_temp_s = preg_replace ("/%%paypal_business%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $ws_plugin__s2member_temp_s);
390
- $ws_plugin__s2member_temp_s = preg_replace ("/%%level_label%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_label"])), $ws_plugin__s2member_temp_s);
 
391
  $ws_plugin__s2member_temp_s = preg_replace ("/%%cancel_return%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("url"))), $ws_plugin__s2member_temp_s);
392
  $ws_plugin__s2member_temp_s = preg_replace ("/%%notify_url%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl") . "/?s2member_paypal_notify=1")), $ws_plugin__s2member_temp_s);
393
  $ws_plugin__s2member_temp_s = preg_replace ("/%%return%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl") . "/?s2member_paypal_return=1")), $ws_plugin__s2member_temp_s);
394
- $ws_plugin__s2member_temp_s = preg_replace ("/%%domain%%/", ws_plugin__s2member_esc_ds (esc_attr ($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_temp_s);
395
- $ws_plugin__s2member_temp_s = preg_replace ("/%%level%%/", ws_plugin__s2member_esc_ds (esc_attr ("2")), $ws_plugin__s2member_temp_s);
 
396
  echo format_to_edit ($ws_plugin__s2member_temp_s);
397
  echo '</textarea><br />' . "\n";
398
- echo '&uarr; Use this more advanced Code if you\'re building a theme or plugin that integrates with s2Member.' . "\n";
 
399
  echo '</div>' . "\n";
400
  /**/
401
  echo '</form>' . "\n";
@@ -419,8 +439,10 @@ if (apply_filters ("ws_plugin__s2member_during_paypal_buttons_page_during_left_s
419
  /**/
420
  echo '<div class="ws-menu-page-section ws-plugin--s2member-cancellation-buttons-section">' . "\n";
421
  echo '<h3>One Button Does It All For Cancellations ( copy/paste )</h3>' . "\n";
422
- echo '<p>Since every paid Membership is associated with a PayPal® Subscription; and every PayPal® Subscription is associated with a PayPal® Account; your Members will always have a PayPal® Account of their own, which is tied to their Membership with you. So... a Member can simply log into their own PayPal® account and cancel their Subscription(s) with you at anytime, all on their own. However, some Customers do not realize this. So, if you would like to make it clearer ( easier ) for Members to cancel their own Subscription(s), you can provide this Cancellation Button for them on your Login Welcome Page, or somewhere in the support section of your website. Note... you don\'t have to use this Cancellation Button at all, if you don\'t want to. It\'s completely optional.</p>' . "\n";
423
  echo '<p><em><strong>*Cancellation Process*</strong> Very simple. A Member clicks the Cancellation Button. PayPal® asks them to log into their PayPal® account. Once they\'re logged in, PayPal® will display a list of all active Subscriptions they have with you. They choose which ones they want to cancel, and s2Member is notified silently behind-the-scene, through the PayPal® IPN service.</em></p>' . "\n";
 
 
424
  do_action ("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_during_cancellation_buttons", get_defined_vars ());
425
  /**/
426
  echo '<table class="form-table">' . "\n";
@@ -434,6 +456,8 @@ if (apply_filters ("ws_plugin__s2member_during_paypal_buttons_page_during_left_s
434
  $ws_plugin__s2member_temp_s = trim (file_get_contents (dirname (dirname (__FILE__)) . "/templates/buttons/paypal-cancellation-button.html"));
435
  $ws_plugin__s2member_temp_s = preg_replace ("/%%endpoint%%/", ws_plugin__s2member_esc_ds (esc_attr (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com")), $ws_plugin__s2member_temp_s);
436
  $ws_plugin__s2member_temp_s = preg_replace ("/%%paypal_business%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $ws_plugin__s2member_temp_s);
 
 
437
  echo preg_replace ("/\<a/", '<a target="_blank"', $ws_plugin__s2member_temp_s);
438
  echo '</div>' . "\n";
439
  echo '</label>' . "\n";
@@ -461,9 +485,12 @@ if (apply_filters ("ws_plugin__s2member_during_paypal_buttons_page_during_left_s
461
  $ws_plugin__s2member_temp_s = trim (file_get_contents (dirname (dirname (__FILE__)) . "/templates/buttons/paypal-cancellation-button.html"));
462
  $ws_plugin__s2member_temp_s = preg_replace ("/%%endpoint%%/", ws_plugin__s2member_esc_ds (esc_attr (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com")), $ws_plugin__s2member_temp_s);
463
  $ws_plugin__s2member_temp_s = preg_replace ("/%%paypal_business%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $ws_plugin__s2member_temp_s);
 
 
464
  echo format_to_edit ($ws_plugin__s2member_temp_s);
465
  echo '</textarea><br />' . "\n";
466
- echo '&uarr; Use this more advanced Code if you\'re building a theme or plugin that integrates with s2Member.' . "\n";
 
467
  echo '</div>' . "\n";
468
  /**/
469
  echo '</form>' . "\n";
@@ -552,7 +579,7 @@ if (apply_filters ("ws_plugin__s2member_during_paypal_buttons_page_during_left_s
552
  do_action ("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_during_sp_buttons_before_shortcode", get_defined_vars ());
553
  echo '<strong>WordPress® Shortcode:</strong> ( recommended for both the WordPress® Visual &amp; HTML Editors )<br />' . "\n";
554
  $ws_plugin__s2member_temp_s = trim (file_get_contents (dirname (dirname (__FILE__)) . "/templates/shortcodes/paypal-sp-checkout-button-shortcode.html"));
555
- $ws_plugin__s2member_temp_s = preg_replace ("/%%domain%%/", ws_plugin__s2member_esc_ds (esc_attr ($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_temp_s);
556
  echo '<input id="ws-plugin--s2member-sp-shortcode" type="text" value="' . format_to_edit ($ws_plugin__s2member_temp_s) . '" onclick="this.select ();" style="font-family:Consolas, monospace; width:99%;" />' . "\n";
557
  /**/
558
  echo '<div' . ( (is_multisite () && ws_plugin__s2member_is_multisite_farm () && !is_main_site ()) ? ' style="display:none;"' : '') . '><br />' . "\n";
@@ -564,10 +591,13 @@ if (apply_filters ("ws_plugin__s2member_during_paypal_buttons_page_during_left_s
564
  $ws_plugin__s2member_temp_s = preg_replace ("/%%cancel_return%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("url"))), $ws_plugin__s2member_temp_s);
565
  $ws_plugin__s2member_temp_s = preg_replace ("/%%notify_url%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl") . "/?s2member_paypal_notify=1")), $ws_plugin__s2member_temp_s);
566
  $ws_plugin__s2member_temp_s = preg_replace ("/%%return%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl") . "/?s2member_paypal_return=1")), $ws_plugin__s2member_temp_s);
567
- $ws_plugin__s2member_temp_s = preg_replace ("/%%domain%%/", ws_plugin__s2member_esc_ds (esc_attr ($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_temp_s);
 
 
568
  echo format_to_edit ($ws_plugin__s2member_temp_s);
569
  echo '</textarea><br />' . "\n";
570
- echo '&uarr; Use this more advanced Code if you\'re building a theme or plugin that integrates with s2Member.' . "\n";
 
571
  echo '</div>' . "\n";
572
  /**/
573
  echo '</form>' . "\n";
@@ -650,6 +680,57 @@ if (apply_filters ("ws_plugin__s2member_during_paypal_buttons_page_during_left_s
650
  do_action ("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_after_sp_links", get_defined_vars ());
651
  }
652
  /**/
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
653
  do_action ("ws_plugin__s2member_during_paypal_buttons_page_after_left_sections", get_defined_vars ());
654
  /**/
655
  echo '</td>' . "\n";
55
  /**/
56
  echo '<td>' . "\n";
57
  echo '<form onsubmit="return false;">' . "\n";
58
+ echo '<p id="ws-plugin--s2member-level1-trial-line">I\'ll offer the first <input type="text" id="ws-plugin--s2member-level1-trial-period" value="0" size="6" /> <select id="ws-plugin--s2member-level1-trial-term">' . file_get_contents (dirname (dirname (__FILE__)) . "/templates/options/paypal-membership-trial-terms.html") . '</select> @ $<input type="text" id="ws-plugin--s2member-level1-trial-amount" value="0.00" size="4" /></p>' . "\n";
59
  echo '<p><span id="ws-plugin--s2member-level1-trial-then">Then, </span>I want to charge: $<input type="text" id="ws-plugin--s2member-level1-amount" value="0.01" size="4" /> / <select id="ws-plugin--s2member-level1-term">' . file_get_contents (dirname (dirname (__FILE__)) . "/templates/options/paypal-membership-regular-terms.html") . '</select></p>' . "\n";
60
  echo '<p>Checkout Page Style <a href="#" onclick="alert(\'Optional. This can be configured inside your PayPal® account. PayPal® allows you to create Custom Page Styles, and assign a unique name to them. You can add your own header image and color selection to the checkout form. Once you\\\'ve created a Custom Page Style at PayPal®, you can enter that Page Style here.\\n\\nIn addition. The Shortcode below, provided by s2Member; supports an image attribute: image=\\\'\\\'default\\\'\\\'. This can be changed to a full URL, pointing to a custom image of your own; instead of the default PayPal® Button image.\'); return false;" tabindex="-1">[?]</a>: <input type="text" id="ws-plugin--s2member-level1-page-style" value="paypal" size="18" /> <select id="ws-plugin--s2member-level1-currency">' . file_get_contents (dirname (dirname (__FILE__)) . "/templates/options/paypal-currencies.html") . '</select> <input type="button" value="Generate Button Code" onclick="ws_plugin__s2member_paypalButtonGenerate(\'level1\');" class="button-primary" /></p>' . "\n";
61
+ echo '<p>Description: <input type="text" id="ws-plugin--s2member-level1-desc" value="' . esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_label"]) . ' description and pricing details here." size="73" /></p>' . "\n";
62
  echo '<p' . ( (is_multisite () && ws_plugin__s2member_is_multisite_farm () && !is_main_site ()) ? ' style="display:none;"' : '') . '>Custom Capabilities ( comma delimited ) <a href="#" onclick="alert(\'Optional. This is VERY advanced. For full details, see:\\ns2Member -> API Scripting -> Custom Capabilities.\'); return false;" tabindex="-1">[?]</a> <input type="text" id="ws-plugin--s2member-level1-ccaps" size="40" maxlength="125" /></p>' . "\n";
63
  echo '</form>' . "\n";
64
  echo '</td>' . "\n";
71
  do_action ("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_during_level1_buttons_before_shortcode", get_defined_vars ());
72
  echo '<strong>WordPress® Shortcode:</strong> ( recommended for both the WordPress® Visual &amp; HTML Editors )<br />' . "\n";
73
  $ws_plugin__s2member_temp_s = trim (file_get_contents (dirname (dirname (__FILE__)) . "/templates/shortcodes/paypal-checkout-button-shortcode.html"));
 
74
  $ws_plugin__s2member_temp_s = preg_replace ("/%%level%%/", ws_plugin__s2member_esc_ds (esc_attr ("1")), $ws_plugin__s2member_temp_s);
75
  $ws_plugin__s2member_temp_s = preg_replace ("/%%level_label%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_label"])), $ws_plugin__s2member_temp_s);
76
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%custom%%/", ws_plugin__s2member_esc_ds (esc_attr ($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_temp_s);
77
  echo '<input id="ws-plugin--s2member-level1-shortcode" type="text" value="' . format_to_edit ($ws_plugin__s2member_temp_s) . '" onclick="this.select ();" style="font-family:Consolas, monospace; width:99%;" />' . "\n";
78
  /**/
79
  echo '<div' . ( (is_multisite () && ws_plugin__s2member_is_multisite_farm () && !is_main_site ()) ? ' style="display:none;"' : '') . '><br />' . "\n";
82
  $ws_plugin__s2member_temp_s = trim (file_get_contents (dirname (dirname (__FILE__)) . "/templates/buttons/paypal-checkout-button.html"));
83
  $ws_plugin__s2member_temp_s = preg_replace ("/%%endpoint%%/", ws_plugin__s2member_esc_ds (esc_attr (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com")), $ws_plugin__s2member_temp_s);
84
  $ws_plugin__s2member_temp_s = preg_replace ("/%%paypal_business%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $ws_plugin__s2member_temp_s);
85
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%level%%/", ws_plugin__s2member_esc_ds (esc_attr ("1")), $ws_plugin__s2member_temp_s);
86
  $ws_plugin__s2member_temp_s = preg_replace ("/%%level_label%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_label"])), $ws_plugin__s2member_temp_s);
87
  $ws_plugin__s2member_temp_s = preg_replace ("/%%cancel_return%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("url"))), $ws_plugin__s2member_temp_s);
88
  $ws_plugin__s2member_temp_s = preg_replace ("/%%notify_url%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl") . "/?s2member_paypal_notify=1")), $ws_plugin__s2member_temp_s);
89
  $ws_plugin__s2member_temp_s = preg_replace ("/%%return%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl") . "/?s2member_paypal_return=1")), $ws_plugin__s2member_temp_s);
90
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%custom%%/", ws_plugin__s2member_esc_ds (esc_attr ($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_temp_s);
91
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%images%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images")), $ws_plugin__s2member_temp_s);
92
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%wpurl%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl"))), $ws_plugin__s2member_temp_s);
93
  echo format_to_edit ($ws_plugin__s2member_temp_s);
94
  echo '</textarea><br />' . "\n";
95
+ echo '&uarr; Use this more advanced Code if you\'re building a theme or plugin that integrates with s2Member.<br />' . "\n";
96
+ echo '&uarr; <em>This <span class="ws-menu-page-hilite">may contain PHP code too</span>; so be careful if you use this.</em>' . "\n";
97
  echo '</div>' . "\n";
98
  /**/
99
  echo '</form>' . "\n";
134
  /**/
135
  echo '<td>' . "\n";
136
  echo '<form onsubmit="return false;">' . "\n";
137
+ echo '<p id="ws-plugin--s2member-level2-trial-line">I\'ll offer the first <input type="text" id="ws-plugin--s2member-level2-trial-period" value="0" size="6" /> <select id="ws-plugin--s2member-level2-trial-term">' . file_get_contents (dirname (dirname (__FILE__)) . "/templates/options/paypal-membership-trial-terms.html") . '</select> @ $<input type="text" id="ws-plugin--s2member-level2-trial-amount" value="0.00" size="4" /></p>' . "\n";
138
  echo '<p><span id="ws-plugin--s2member-level2-trial-then">Then, </span>I want to charge: $<input type="text" id="ws-plugin--s2member-level2-amount" value="0.01" size="4" /> / <select id="ws-plugin--s2member-level2-term">' . file_get_contents (dirname (dirname (__FILE__)) . "/templates/options/paypal-membership-regular-terms.html") . '</select></p>' . "\n";
139
  echo '<p>Checkout Page Style <a href="#" onclick="alert(\'Optional. This can be configured inside your PayPal® account. PayPal® allows you to create Custom Page Styles, and assign a unique name to them. You can add your own header image and color selection to the checkout form. Once you\\\'ve created a Custom Page Style at PayPal®, you can enter that Page Style here.\\n\\nIn addition. The Shortcode below, provided by s2Member; supports an image attribute: image=\\\'\\\'default\\\'\\\'. This can be changed to a full URL, pointing to a custom image of your own; instead of the default PayPal® Button image.\'); return false;" tabindex="-1">[?]</a>: <input type="text" id="ws-plugin--s2member-level2-page-style" value="paypal" size="18" /> <select id="ws-plugin--s2member-level2-currency">' . file_get_contents (dirname (dirname (__FILE__)) . "/templates/options/paypal-currencies.html") . '</select> <input type="button" value="Generate Button Code" onclick="ws_plugin__s2member_paypalButtonGenerate(\'level2\');" class="button-primary" /></p>' . "\n";
140
+ echo '<p>Description: <input type="text" id="ws-plugin--s2member-level2-desc" value="' . esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_label"]) . ' description and pricing details here." size="73" /></p>' . "\n";
141
  echo '<p' . ( (is_multisite () && ws_plugin__s2member_is_multisite_farm () && !is_main_site ()) ? ' style="display:none;"' : '') . '>Custom Capabilities ( comma delimited ) <a href="#" onclick="alert(\'Optional. This is VERY advanced. For full details, see:\\ns2Member -> API Scripting -> Custom Capabilities.\'); return false;" tabindex="-1">[?]</a> <input type="text" id="ws-plugin--s2member-level2-ccaps" size="40" maxlength="125" /></p>' . "\n";
142
  echo '</form>' . "\n";
143
  echo '</td>' . "\n";
150
  do_action ("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_during_level2_buttons_before_shortcode", get_defined_vars ());
151
  echo '<strong>WordPress® Shortcode:</strong> ( recommended for both the WordPress® Visual &amp; HTML Editors )<br />' . "\n";
152
  $ws_plugin__s2member_temp_s = trim (file_get_contents (dirname (dirname (__FILE__)) . "/templates/shortcodes/paypal-checkout-button-shortcode.html"));
 
153
  $ws_plugin__s2member_temp_s = preg_replace ("/%%level%%/", ws_plugin__s2member_esc_ds (esc_attr ("2")), $ws_plugin__s2member_temp_s);
154
  $ws_plugin__s2member_temp_s = preg_replace ("/%%level_label%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_label"])), $ws_plugin__s2member_temp_s);
155
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%custom%%/", ws_plugin__s2member_esc_ds (esc_attr ($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_temp_s);
156
  echo '<input id="ws-plugin--s2member-level2-shortcode" type="text" value="' . format_to_edit ($ws_plugin__s2member_temp_s) . '" onclick="this.select ();" style="font-family:Consolas, monospace; width:99%;" />' . "\n";
157
  /**/
158
  echo '<div' . ( (is_multisite () && ws_plugin__s2member_is_multisite_farm () && !is_main_site ()) ? ' style="display:none;"' : '') . '><br />' . "\n";
161
  $ws_plugin__s2member_temp_s = trim (file_get_contents (dirname (dirname (__FILE__)) . "/templates/buttons/paypal-checkout-button.html"));
162
  $ws_plugin__s2member_temp_s = preg_replace ("/%%endpoint%%/", ws_plugin__s2member_esc_ds (esc_attr (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com")), $ws_plugin__s2member_temp_s);
163
  $ws_plugin__s2member_temp_s = preg_replace ("/%%paypal_business%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $ws_plugin__s2member_temp_s);
164
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%level%%/", ws_plugin__s2member_esc_ds (esc_attr ("2")), $ws_plugin__s2member_temp_s);
165
  $ws_plugin__s2member_temp_s = preg_replace ("/%%level_label%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_label"])), $ws_plugin__s2member_temp_s);
166
  $ws_plugin__s2member_temp_s = preg_replace ("/%%cancel_return%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("url"))), $ws_plugin__s2member_temp_s);
167
  $ws_plugin__s2member_temp_s = preg_replace ("/%%notify_url%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl") . "/?s2member_paypal_notify=1")), $ws_plugin__s2member_temp_s);
168
  $ws_plugin__s2member_temp_s = preg_replace ("/%%return%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl") . "/?s2member_paypal_return=1")), $ws_plugin__s2member_temp_s);
169
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%custom%%/", ws_plugin__s2member_esc_ds (esc_attr ($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_temp_s);
170
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%images%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images")), $ws_plugin__s2member_temp_s);
171
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%wpurl%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl"))), $ws_plugin__s2member_temp_s);
172
  echo format_to_edit ($ws_plugin__s2member_temp_s);
173
  echo '</textarea><br />' . "\n";
174
+ echo '&uarr; Use this more advanced Code if you\'re building a theme or plugin that integrates with s2Member.<br />' . "\n";
175
+ echo '&uarr; <em>This <span class="ws-menu-page-hilite">may contain PHP code too</span>; so be careful if you use this.</em>' . "\n";
176
  echo '</div>' . "\n";
177
  /**/
178
  echo '</form>' . "\n";
213
  /**/
214
  echo '<td>' . "\n";
215
  echo '<form onsubmit="return false;">' . "\n";
216
+ echo '<p id="ws-plugin--s2member-level3-trial-line">I\'ll offer the first <input type="text" id="ws-plugin--s2member-level3-trial-period" value="0" size="6" /> <select id="ws-plugin--s2member-level3-trial-term">' . file_get_contents (dirname (dirname (__FILE__)) . "/templates/options/paypal-membership-trial-terms.html") . '</select> @ $<input type="text" id="ws-plugin--s2member-level3-trial-amount" value="0.00" size="4" /></p>' . "\n";
217
  echo '<p><span id="ws-plugin--s2member-level3-trial-then">Then, </span>I want to charge: $<input type="text" id="ws-plugin--s2member-level3-amount" value="0.01" size="4" /> / <select id="ws-plugin--s2member-level3-term">' . file_get_contents (dirname (dirname (__FILE__)) . "/templates/options/paypal-membership-regular-terms.html") . '</select></p>' . "\n";
218
  echo '<p>Checkout Page Style <a href="#" onclick="alert(\'Optional. This can be configured inside your PayPal® account. PayPal® allows you to create Custom Page Styles, and assign a unique name to them. You can add your own header image and color selection to the checkout form. Once you\\\'ve created a Custom Page Style at PayPal®, you can enter that Page Style here.\\n\\nIn addition. The Shortcode below, provided by s2Member; supports an image attribute: image=\\\'\\\'default\\\'\\\'. This can be changed to a full URL, pointing to a custom image of your own; instead of the default PayPal® Button image.\'); return false;" tabindex="-1">[?]</a>: <input type="text" id="ws-plugin--s2member-level3-page-style" value="paypal" size="18" /> <select id="ws-plugin--s2member-level3-currency">' . file_get_contents (dirname (dirname (__FILE__)) . "/templates/options/paypal-currencies.html") . '</select> <input type="button" value="Generate Button Code" onclick="ws_plugin__s2member_paypalButtonGenerate(\'level3\');" class="button-primary" /></p>' . "\n";
219
+ echo '<p>Description: <input type="text" id="ws-plugin--s2member-level3-desc" value="' . esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_label"]) . ' description and pricing details here." size="73" /></p>' . "\n";
220
  echo '<p' . ( (is_multisite () && ws_plugin__s2member_is_multisite_farm () && !is_main_site ()) ? ' style="display:none;"' : '') . '>Custom Capabilities ( comma delimited ) <a href="#" onclick="alert(\'Optional. This is VERY advanced. For full details, see:\\ns2Member -> API Scripting -> Custom Capabilities.\'); return false;" tabindex="-1">[?]</a> <input type="text" id="ws-plugin--s2member-level3-ccaps" size="40" maxlength="125" /></p>' . "\n";
221
  echo '</form>' . "\n";
222
  echo '</td>' . "\n";
229
  do_action ("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_during_level3_buttons_before_shortcode", get_defined_vars ());
230
  echo '<strong>WordPress® Shortcode:</strong> ( recommended for both the WordPress® Visual &amp; HTML Editors )<br />' . "\n";
231
  $ws_plugin__s2member_temp_s = trim (file_get_contents (dirname (dirname (__FILE__)) . "/templates/shortcodes/paypal-checkout-button-shortcode.html"));
 
232
  $ws_plugin__s2member_temp_s = preg_replace ("/%%level%%/", ws_plugin__s2member_esc_ds (esc_attr ("3")), $ws_plugin__s2member_temp_s);
233
  $ws_plugin__s2member_temp_s = preg_replace ("/%%level_label%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_label"])), $ws_plugin__s2member_temp_s);
234
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%custom%%/", ws_plugin__s2member_esc_ds (esc_attr ($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_temp_s);
235
  echo '<input id="ws-plugin--s2member-level3-shortcode" type="text" value="' . format_to_edit ($ws_plugin__s2member_temp_s) . '" onclick="this.select ();" style="font-family:Consolas, monospace; width:99%;" />' . "\n";
236
  /**/
237
  echo '<div' . ( (is_multisite () && ws_plugin__s2member_is_multisite_farm () && !is_main_site ()) ? ' style="display:none;"' : '') . '><br />' . "\n";
240
  $ws_plugin__s2member_temp_s = trim (file_get_contents (dirname (dirname (__FILE__)) . "/templates/buttons/paypal-checkout-button.html"));
241
  $ws_plugin__s2member_temp_s = preg_replace ("/%%endpoint%%/", ws_plugin__s2member_esc_ds (esc_attr (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com")), $ws_plugin__s2member_temp_s);
242
  $ws_plugin__s2member_temp_s = preg_replace ("/%%paypal_business%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $ws_plugin__s2member_temp_s);
243
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%level%%/", ws_plugin__s2member_esc_ds (esc_attr ("3")), $ws_plugin__s2member_temp_s);
244
  $ws_plugin__s2member_temp_s = preg_replace ("/%%level_label%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_label"])), $ws_plugin__s2member_temp_s);
245
  $ws_plugin__s2member_temp_s = preg_replace ("/%%cancel_return%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("url"))), $ws_plugin__s2member_temp_s);
246
  $ws_plugin__s2member_temp_s = preg_replace ("/%%notify_url%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl") . "/?s2member_paypal_notify=1")), $ws_plugin__s2member_temp_s);
247
  $ws_plugin__s2member_temp_s = preg_replace ("/%%return%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl") . "/?s2member_paypal_return=1")), $ws_plugin__s2member_temp_s);
248
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%custom%%/", ws_plugin__s2member_esc_ds (esc_attr ($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_temp_s);
249
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%images%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images")), $ws_plugin__s2member_temp_s);
250
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%wpurl%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl"))), $ws_plugin__s2member_temp_s);
251
  echo format_to_edit ($ws_plugin__s2member_temp_s);
252
  echo '</textarea><br />' . "\n";
253
+ echo '&uarr; Use this more advanced Code if you\'re building a theme or plugin that integrates with s2Member.<br />' . "\n";
254
+ echo '&uarr; <em>This <span class="ws-menu-page-hilite">may contain PHP code too</span>; so be careful if you use this.</em>' . "\n";
255
  echo '</div>' . "\n";
256
  /**/
257
  echo '</form>' . "\n";
292
  /**/
293
  echo '<td>' . "\n";
294
  echo '<form onsubmit="return false;">' . "\n";
295
+ echo '<p id="ws-plugin--s2member-level4-trial-line">I\'ll offer the first <input type="text" id="ws-plugin--s2member-level4-trial-period" value="0" size="6" /> <select id="ws-plugin--s2member-level4-trial-term">' . file_get_contents (dirname (dirname (__FILE__)) . "/templates/options/paypal-membership-trial-terms.html") . '</select> @ $<input type="text" id="ws-plugin--s2member-level4-trial-amount" value="0.00" size="4" /></p>' . "\n";
296
  echo '<p><span id="ws-plugin--s2member-level4-trial-then">Then, </span>I want to charge: $<input type="text" id="ws-plugin--s2member-level4-amount" value="0.01" size="4" /> / <select id="ws-plugin--s2member-level4-term">' . file_get_contents (dirname (dirname (__FILE__)) . "/templates/options/paypal-membership-regular-terms.html") . '</select></p>' . "\n";
297
  echo '<p>Checkout Page Style <a href="#" onclick="alert(\'Optional. This can be configured inside your PayPal® account. PayPal® allows you to create Custom Page Styles, and assign a unique name to them. You can add your own header image and color selection to the checkout form. Once you\\\'ve created a Custom Page Style at PayPal®, you can enter that Page Style here.\\n\\nIn addition. The Shortcode below, provided by s2Member; supports an image attribute: image=\\\'\\\'default\\\'\\\'. This can be changed to a full URL, pointing to a custom image of your own; instead of the default PayPal® Button image.\'); return false;" tabindex="-1">[?]</a>: <input type="text" id="ws-plugin--s2member-level4-page-style" value="paypal" size="18" /> <select id="ws-plugin--s2member-level4-currency">' . file_get_contents (dirname (dirname (__FILE__)) . "/templates/options/paypal-currencies.html") . '</select> <input type="button" value="Generate Button Code" onclick="ws_plugin__s2member_paypalButtonGenerate(\'level4\');" class="button-primary" /></p>' . "\n";
298
+ echo '<p>Description: <input type="text" id="ws-plugin--s2member-level4-desc" value="' . esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_label"]) . ' description and pricing details here." size="73" /></p>' . "\n";
299
  echo '<p' . ( (is_multisite () && ws_plugin__s2member_is_multisite_farm () && !is_main_site ()) ? ' style="display:none;"' : '') . '>Custom Capabilities ( comma delimited ) <a href="#" onclick="alert(\'Optional. This is VERY advanced. For full details, see:\\ns2Member -> API Scripting -> Custom Capabilities.\'); return false;" tabindex="-1">[?]</a> <input type="text" id="ws-plugin--s2member-level4-ccaps" size="40" maxlength="125" /></p>' . "\n";
300
  echo '</form>' . "\n";
301
  echo '</td>' . "\n";
308
  do_action ("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_during_level4_buttons_before_shortcode", get_defined_vars ());
309
  echo '<strong>WordPress® Shortcode:</strong> ( recommended for both the WordPress® Visual &amp; HTML Editors )<br />' . "\n";
310
  $ws_plugin__s2member_temp_s = trim (file_get_contents (dirname (dirname (__FILE__)) . "/templates/shortcodes/paypal-checkout-button-shortcode.html"));
 
311
  $ws_plugin__s2member_temp_s = preg_replace ("/%%level%%/", ws_plugin__s2member_esc_ds (esc_attr ("4")), $ws_plugin__s2member_temp_s);
312
  $ws_plugin__s2member_temp_s = preg_replace ("/%%level_label%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_label"])), $ws_plugin__s2member_temp_s);
313
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%custom%%/", ws_plugin__s2member_esc_ds (esc_attr ($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_temp_s);
314
  echo '<input id="ws-plugin--s2member-level4-shortcode" type="text" value="' . format_to_edit ($ws_plugin__s2member_temp_s) . '" onclick="this.select ();" style="font-family:Consolas, monospace; width:99%;" />' . "\n";
315
  /**/
316
  echo '<div' . ( (is_multisite () && ws_plugin__s2member_is_multisite_farm () && !is_main_site ()) ? ' style="display:none;"' : '') . '><br />' . "\n";
319
  $ws_plugin__s2member_temp_s = trim (file_get_contents (dirname (dirname (__FILE__)) . "/templates/buttons/paypal-checkout-button.html"));
320
  $ws_plugin__s2member_temp_s = preg_replace ("/%%endpoint%%/", ws_plugin__s2member_esc_ds (esc_attr (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com")), $ws_plugin__s2member_temp_s);
321
  $ws_plugin__s2member_temp_s = preg_replace ("/%%paypal_business%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $ws_plugin__s2member_temp_s);
322
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%level%%/", ws_plugin__s2member_esc_ds (esc_attr ("4")), $ws_plugin__s2member_temp_s);
323
  $ws_plugin__s2member_temp_s = preg_replace ("/%%level_label%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_label"])), $ws_plugin__s2member_temp_s);
324
  $ws_plugin__s2member_temp_s = preg_replace ("/%%cancel_return%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("url"))), $ws_plugin__s2member_temp_s);
325
  $ws_plugin__s2member_temp_s = preg_replace ("/%%notify_url%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl") . "/?s2member_paypal_notify=1")), $ws_plugin__s2member_temp_s);
326
  $ws_plugin__s2member_temp_s = preg_replace ("/%%return%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl") . "/?s2member_paypal_return=1")), $ws_plugin__s2member_temp_s);
327
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%custom%%/", ws_plugin__s2member_esc_ds (esc_attr ($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_temp_s);
328
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%images%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images")), $ws_plugin__s2member_temp_s);
329
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%wpurl%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl"))), $ws_plugin__s2member_temp_s);
330
  echo format_to_edit ($ws_plugin__s2member_temp_s);
331
  echo '</textarea><br />' . "\n";
332
+ echo '&uarr; Use this more advanced Code if you\'re building a theme or plugin that integrates with s2Member.<br />' . "\n";
333
+ echo '&uarr; <em>This <span class="ws-menu-page-hilite">may contain PHP code too</span>; so be careful if you use this.</em>' . "\n";
334
  echo '</div>' . "\n";
335
  /**/
336
  echo '</form>' . "\n";
375
  echo '<td>' . "\n";
376
  echo '<form onsubmit="return false;">' . "\n";
377
  echo '<p>Modification: <select id="ws-plugin--s2member-modification-level">' . file_get_contents (dirname (dirname (__FILE__)) . "/templates/options/paypal-membership-modification-levels.html") . '</select></p>' . "\n";
378
+ echo '<p id="ws-plugin--s2member-modification-trial-line">I\'ll offer the first <input type="text" id="ws-plugin--s2member-modification-trial-period" value="0" size="6" /> <select id="ws-plugin--s2member-modification-trial-term">' . file_get_contents (dirname (dirname (__FILE__)) . "/templates/options/paypal-membership-trial-terms.html") . '</select> @ $<input type="text" id="ws-plugin--s2member-modification-trial-amount" value="0.00" size="4" /></p>' . "\n";
379
  echo '<p><span id="ws-plugin--s2member-modification-trial-then">Then, </span>I want to charge: $<input type="text" id="ws-plugin--s2member-modification-amount" value="0.01" size="4" /> / <select id="ws-plugin--s2member-modification-term">' . file_get_contents (dirname (dirname (__FILE__)) . "/templates/options/paypal-membership-regular-terms.html") . '</select><span id="ws-plugin--s2member-modification-20p-rule"><br /><small>** Watch out for <a href="https://www.x.com/thread/41748" target="_blank" rel="external">the 20% rule</a>. Additional details on the 20% rule are <a href="https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_api_WPRecurringPayments#id086530108PM__id08653060UE6" target="_blank" rel="external">documented here</a>.</small></span></p>' . "\n";
380
  echo '<p>Checkout Page Style <a href="#" onclick="alert(\'Optional. This can be configured inside your PayPal® account. PayPal® allows you to create Custom Page Styles, and assign a unique name to them. You can add your own header image and color selection to the checkout form. Once you\\\'ve created a Custom Page Style at PayPal®, you can enter that Page Style here.\\n\\nIn addition. The Shortcode below, provided by s2Member; supports an image attribute: image=\\\'\\\'default\\\'\\\'. This can be changed to a full URL, pointing to a custom image of your own; instead of the default PayPal® Button image.\'); return false;" tabindex="-1">[?]</a>: <input type="text" id="ws-plugin--s2member-modification-page-style" value="paypal" size="18" /> <select id="ws-plugin--s2member-modification-currency">' . file_get_contents (dirname (dirname (__FILE__)) . "/templates/options/paypal-currencies.html") . '</select> <input type="button" value="Generate Button Code" onclick="ws_plugin__s2member_paypalButtonGenerate(\'modification\');" class="button-primary" /></p>' . "\n";
381
+ echo '<p>Description: <input type="text" id="ws-plugin--s2member-modification-desc" value="Description and pricing details here." size="73" /></p>' . "\n";
382
  echo '<p' . ( (is_multisite () && ws_plugin__s2member_is_multisite_farm () && !is_main_site ()) ? ' style="display:none;"' : '') . '>Custom Capabilities ( comma delimited ) <a href="#" onclick="alert(\'Optional. This is VERY advanced. For full details, see:\\ns2Member -> API Scripting -> Custom Capabilities.\'); return false;" tabindex="-1">[?]</a> <input type="text" id="ws-plugin--s2member-modification-ccaps" size="40" maxlength="125" /></p>' . "\n";
383
  echo '</form>' . "\n";
384
  echo '</td>' . "\n";
391
  do_action ("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_during_modification_buttons_before_shortcode", get_defined_vars ());
392
  echo '<strong>WordPress® Shortcode:</strong> ( recommended for both the WordPress® Visual &amp; HTML Editors )<br />' . "\n";
393
  $ws_plugin__s2member_temp_s = trim (file_get_contents (dirname (dirname (__FILE__)) . "/templates/shortcodes/paypal-checkout-button-shortcode.html"));
 
 
394
  $ws_plugin__s2member_temp_s = preg_replace ("/%%level%%/", ws_plugin__s2member_esc_ds (esc_attr ("2")), $ws_plugin__s2member_temp_s);
395
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%level_label%% /", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_label"])), $ws_plugin__s2member_temp_s);
396
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%custom%%/", ws_plugin__s2member_esc_ds (esc_attr ($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_temp_s);
397
+ $ws_plugin__s2member_temp_s = preg_replace ("/\/]$/", 'modify="1" /]', $ws_plugin__s2member_temp_s); /* Adds modify="1" to the end of the Shortcode. */
398
  echo '<input id="ws-plugin--s2member-modification-shortcode" type="text" value="' . format_to_edit ($ws_plugin__s2member_temp_s) . '" onclick="this.select ();" style="font-family:Consolas, monospace; width:99%;" />' . "\n";
399
  /**/
400
  echo '<div' . ( (is_multisite () && ws_plugin__s2member_is_multisite_farm () && !is_main_site ()) ? ' style="display:none;"' : '') . '><br />' . "\n";
404
  $ws_plugin__s2member_temp_s = preg_replace ('/name\="modify" value\="(.*?)"/', 'name="modify" value="1"', $ws_plugin__s2member_temp_s);
405
  $ws_plugin__s2member_temp_s = preg_replace ("/%%endpoint%%/", ws_plugin__s2member_esc_ds (esc_attr (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com")), $ws_plugin__s2member_temp_s);
406
  $ws_plugin__s2member_temp_s = preg_replace ("/%%paypal_business%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $ws_plugin__s2member_temp_s);
407
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%level%%/", ws_plugin__s2member_esc_ds (esc_attr ("2")), $ws_plugin__s2member_temp_s);
408
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%level_label%% /", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_label"])), $ws_plugin__s2member_temp_s);
409
  $ws_plugin__s2member_temp_s = preg_replace ("/%%cancel_return%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("url"))), $ws_plugin__s2member_temp_s);
410
  $ws_plugin__s2member_temp_s = preg_replace ("/%%notify_url%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl") . "/?s2member_paypal_notify=1")), $ws_plugin__s2member_temp_s);
411
  $ws_plugin__s2member_temp_s = preg_replace ("/%%return%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl") . "/?s2member_paypal_return=1")), $ws_plugin__s2member_temp_s);
412
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%custom%%/", ws_plugin__s2member_esc_ds (esc_attr ($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_temp_s);
413
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%images%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images")), $ws_plugin__s2member_temp_s);
414
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%wpurl%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl"))), $ws_plugin__s2member_temp_s);
415
  echo format_to_edit ($ws_plugin__s2member_temp_s);
416
  echo '</textarea><br />' . "\n";
417
+ echo '&uarr; Use this more advanced Code if you\'re building a theme or plugin that integrates with s2Member.<br />' . "\n";
418
+ echo '&uarr; <em>This <span class="ws-menu-page-hilite">may contain PHP code too</span>; so be careful if you use this.</em>' . "\n";
419
  echo '</div>' . "\n";
420
  /**/
421
  echo '</form>' . "\n";
439
  /**/
440
  echo '<div class="ws-menu-page-section ws-plugin--s2member-cancellation-buttons-section">' . "\n";
441
  echo '<h3>One Button Does It All For Cancellations ( copy/paste )</h3>' . "\n";
442
+ echo '<p>Since all recurring charges are associated with a PayPal® Subscription; and every PayPal® Subscription is associated with a PayPal® Account; your Members will always have a PayPal® Account of their own, which is tied to their Membership with you. So... a Member can simply log into their own PayPal® account and cancel their Subscription(s) with you at anytime, all on their own. However, some Customers do not realize this. So, if you would like to make it clearer ( easier ) for Members to cancel their own Subscription(s), you can provide this Cancellation Button for them on your Login Welcome Page, or somewhere in the support section of your website. Note... you don\'t have to use this Cancellation Button at all, if you don\'t want to. It\'s completely optional.</p>' . "\n";
443
  echo '<p><em><strong>*Cancellation Process*</strong> Very simple. A Member clicks the Cancellation Button. PayPal® asks them to log into their PayPal® account. Once they\'re logged in, PayPal® will display a list of all active Subscriptions they have with you. They choose which ones they want to cancel, and s2Member is notified silently behind-the-scene, through the PayPal® IPN service.</em></p>' . "\n";
444
+ echo '<p><em><strong>*Understanding Cancellations*</strong> It\'s important to realize that a Cancellation is not an EOT ( End Of Term ). All that happens during a Cancellation event, is that billing is stopped, and it\'s understood that the Customer is going to lose access, at some point in the future. This does NOT mean, that access will be revoked immediately. A separate EOT event will automatically handle a (demotion or deletion) later, at the appropriate time; which could be several days, or even a year after the Cancellation took place.</em></p>' . "\n";
445
+ echo '<p><em><strong>*Some Hairy Details*</strong> There might be times whenever you notice that a Members\'s Subscription has been cancelled through PayPal®... but, s2Member continues allowing the User access to your site as a paid Member. Please don\'t be confused by this... in 99.9% of these cases, the reason for this is legitimate. s2Member will only remove the User\'s Membership privileges when an EOT ( End Of Term ) is processed, a refund occurs, a chargeback occurs, or when a cancellation occurs - which would later result in a delayed Auto-EOT by s2Member. s2Member will not process an EOT ( End Of Term ) until the User has completely used up the time they paid for. In other words, if a User signs up for a monthly Subscription on Jan 1st, and then cancels their Subscription on Jan 15th; technically, they should still be allowed to access the site for another 15 days, and then on Feb 1st, the time they paid for has completely elapsed. At that time, s2Member will remove their Membership privileges; by either demoting them to a Free Subscriber, or deleting their account from the system ( based on your configuration ). s2Member also calculates one extra day ( 24 hours ) into its equation, just to make sure access is not removed sooner than a Customer might expect.</em></p>' . "\n";
446
  do_action ("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_during_cancellation_buttons", get_defined_vars ());
447
  /**/
448
  echo '<table class="form-table">' . "\n";
456
  $ws_plugin__s2member_temp_s = trim (file_get_contents (dirname (dirname (__FILE__)) . "/templates/buttons/paypal-cancellation-button.html"));
457
  $ws_plugin__s2member_temp_s = preg_replace ("/%%endpoint%%/", ws_plugin__s2member_esc_ds (esc_attr (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com")), $ws_plugin__s2member_temp_s);
458
  $ws_plugin__s2member_temp_s = preg_replace ("/%%paypal_business%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $ws_plugin__s2member_temp_s);
459
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%images%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images")), $ws_plugin__s2member_temp_s);
460
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%wpurl%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl"))), $ws_plugin__s2member_temp_s);
461
  echo preg_replace ("/\<a/", '<a target="_blank"', $ws_plugin__s2member_temp_s);
462
  echo '</div>' . "\n";
463
  echo '</label>' . "\n";
485
  $ws_plugin__s2member_temp_s = trim (file_get_contents (dirname (dirname (__FILE__)) . "/templates/buttons/paypal-cancellation-button.html"));
486
  $ws_plugin__s2member_temp_s = preg_replace ("/%%endpoint%%/", ws_plugin__s2member_esc_ds (esc_attr (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com")), $ws_plugin__s2member_temp_s);
487
  $ws_plugin__s2member_temp_s = preg_replace ("/%%paypal_business%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])), $ws_plugin__s2member_temp_s);
488
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%images%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images")), $ws_plugin__s2member_temp_s);
489
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%wpurl%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl"))), $ws_plugin__s2member_temp_s);
490
  echo format_to_edit ($ws_plugin__s2member_temp_s);
491
  echo '</textarea><br />' . "\n";
492
+ echo '&uarr; Use this more advanced Code if you\'re building a theme or plugin that integrates with s2Member.<br />' . "\n";
493
+ echo '&uarr; <em>This <span class="ws-menu-page-hilite">may contain PHP code too</span>; so be careful if you use this.</em>' . "\n";
494
  echo '</div>' . "\n";
495
  /**/
496
  echo '</form>' . "\n";
579
  do_action ("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_during_sp_buttons_before_shortcode", get_defined_vars ());
580
  echo '<strong>WordPress® Shortcode:</strong> ( recommended for both the WordPress® Visual &amp; HTML Editors )<br />' . "\n";
581
  $ws_plugin__s2member_temp_s = trim (file_get_contents (dirname (dirname (__FILE__)) . "/templates/shortcodes/paypal-sp-checkout-button-shortcode.html"));
582
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%custom%%/", ws_plugin__s2member_esc_ds (esc_attr ($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_temp_s);
583
  echo '<input id="ws-plugin--s2member-sp-shortcode" type="text" value="' . format_to_edit ($ws_plugin__s2member_temp_s) . '" onclick="this.select ();" style="font-family:Consolas, monospace; width:99%;" />' . "\n";
584
  /**/
585
  echo '<div' . ( (is_multisite () && ws_plugin__s2member_is_multisite_farm () && !is_main_site ()) ? ' style="display:none;"' : '') . '><br />' . "\n";
591
  $ws_plugin__s2member_temp_s = preg_replace ("/%%cancel_return%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("url"))), $ws_plugin__s2member_temp_s);
592
  $ws_plugin__s2member_temp_s = preg_replace ("/%%notify_url%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl") . "/?s2member_paypal_notify=1")), $ws_plugin__s2member_temp_s);
593
  $ws_plugin__s2member_temp_s = preg_replace ("/%%return%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl") . "/?s2member_paypal_return=1")), $ws_plugin__s2member_temp_s);
594
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%custom%%/", ws_plugin__s2member_esc_ds (esc_attr ($_SERVER["HTTP_HOST"])), $ws_plugin__s2member_temp_s);
595
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%images%%/", ws_plugin__s2member_esc_ds (esc_attr ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images")), $ws_plugin__s2member_temp_s);
596
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%wpurl%%/", ws_plugin__s2member_esc_ds (esc_attr (get_bloginfo ("wpurl"))), $ws_plugin__s2member_temp_s);
597
  echo format_to_edit ($ws_plugin__s2member_temp_s);
598
  echo '</textarea><br />' . "\n";
599
+ echo '&uarr; Use this more advanced Code if you\'re building a theme or plugin that integrates with s2Member.<br />' . "\n";
600
+ echo '&uarr; <em>This <span class="ws-menu-page-hilite">may contain PHP code too</span>; so be careful if you use this.</em>' . "\n";
601
  echo '</div>' . "\n";
602
  /**/
603
  echo '</form>' . "\n";
680
  do_action ("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_after_sp_links", get_defined_vars ());
681
  }
682
  /**/
683
+ if (apply_filters ("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_display_shortcode_attrs", true, get_defined_vars ()))
684
+ {
685
+ do_action ("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_before_shortcode_attrs", get_defined_vars ());
686
+ /**/
687
+ echo '<div class="ws-menu-page-group" title="Shortcode Attributes ( Explained )">' . "\n";
688
+ /**/
689
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-shortcode-attrs-section">' . "\n";
690
+ echo '<h3>Shortcode Attributes ( Explained In Full Detail )</h3>' . "\n";
691
+ echo '<p>When you generate a Button Code, s2Member will make a <a href="http://codex.wordpress.org/Shortcode_API#Overview" target="_blank" rel="external">Shortcode</a> available to you. Like most Shortcodes for WordPress®, s2Member reads Attributes in your Shortcode. These Attributes will be pre-configured by one of s2Member\'s Button Generators automatically; so there really is nothing more you need to do. However, many site owners like to know exactly how these Shortcode Attributes work. Below, is a brief overview of each possible Shortcode Attribute.</p>' . "\n";
692
+ do_action ("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_during_shortcode_attrs", get_defined_vars ());
693
+ /**/
694
+ echo '<table class="form-table" style="margin-top:0;">' . "\n";
695
+ echo '<tbody>' . "\n";
696
+ echo '<tr style="padding-top:0;">' . "\n";
697
+ /**/
698
+ echo '<td style="padding-top:0;">' . "\n";
699
+ echo '<ul>' . "\n";
700
+ echo '<li><code>image="default"</code> Button Image Location. Possible values: <code>default</code> = use the default PayPal® Button, <code>http://...</code> = location of your custom Image.</li>' . "\n";
701
+ echo '<li><code>output="button"</code> Output Type. Possible values: <code>button</code> = PayPal® Button w/hidden inputs, <code>anchor</code> = PayPal® Button ( &lt;a&gt; anchor tag ) URL w/ ?query string, <code>url</code> = raw URL w/ ?query string.</li>' . "\n";
702
+ echo '<li><code>level="1"</code> Membership Level [1-4]. Only valid for Buttons providing Membership Level [1-4] Access.</li>' . "\n";
703
+ echo '<li><code>ccaps="music,videos"</code> A comma-delimited list of Custom Capabilities. Only valid w/ Membership Level Access.</li>' . "\n";
704
+ echo '<li><code>desc="Gold Membership"</code> A brief purchase Description. Not valid when <code>cancel="1"</code>.</li>' . "\n";
705
+ echo '<li><code>ps="paypal"</code> PayPal® checkout Page Style. Not valid when <code>cancel="1"</code>.</li>' . "\n";
706
+ echo '<li><code>cc="USD"</code> 3 character Currency Code. Not valid when <code>cancel="1"</code>.</li>' . "\n";
707
+ echo '<li><code>ns="1"</code> The <em>no_shipping</em> directive. Possible values: <code>0</code> = prompt for an address, but do not require one, <code>1</code> = do not prompt for a shipping address, <code>2</code> = prompt for an address, and require one. Not valid when <code>cancel="1"</code>.</li>' . "\n";
708
+ echo '<li><code>custom="' . $_SERVER["HTTP_HOST"] . '"</code> must start with your domain. Additional values can be piped in ( ex: <code>custom="' . $_SERVER["HTTP_HOST"] . '|cv1|cv2|cv3|etc"</code> ). Not valid when <code>cancel="1"</code>.</li>' . "\n";
709
+ echo '<li><code>ta="0.00"</code> Trial Amount. Only valid w/ Membership Level Access. Must be <code>0</code> when <code>rt="L"</code> or when <code>rr="BN"</code>.</li>' . "\n";
710
+ echo '<li><code>tp="0"</code> Trial Period. Only valid w/ Membership Level Access. Must be <code>0</code> when <code>rt="L"</code> or when <code>rr="BN"</code>.</li>' . "\n";
711
+ echo '<li><code>tt="D"</code> Trial Term. Only valid w/ Membership Level Access. Possible values: <code>D</code> = Days, <code>W</code> = Weeks, <code>M</code> = Months, <code>Y</code> = Years.</li>' . "\n";
712
+ echo '<li><code>ra="0.01"</code> Regular, Buy Now, and/or Recurring Amount. Must be >= <code>0.01</code>. Not valid when <code>cancel="1"</code>.</li>' . "\n";
713
+ echo '<li><code>rp="1"</code> Regular Period. Only valid w/ Membership Level Access. Must be >= <code>1</code> ( ex: <code>1</code> Week, <code>2</code> Months, <code>1</code> Month, <code>3</code> Days ).</li>' . "\n";
714
+ echo '<li><code>rt="M"</code> Regular Term. Only valid w/ Membership Level Access. Possible values: <code>D</code> = Days, <code>W</code> = Weeks, <code>M</code> = Months, <code>Y</code> = Years, <code>L</code> = Lifetime.</li>' . "\n";
715
+ echo '<li><code>rr="1"</code> Recurring directive. Only valid w/ Membership Level Access. Possible values: <code>0</code> = non-recurring "Subscription" with possible Trial Period for free, or at a different Trial Amount; <code>1</code> = recurring "Subscription" with possible Trial Period for free, or at a different Trial Amount; <code>BN</code> = non-recurring "Buy Now" functionality, no Trial Period possible.</li>' . "\n";
716
+ echo '<li><code>modify="0"</code> Modification directive. Only valid w/ Membership Level Access. Possible values: <code>0</code> = allows Customers to only create a new Subscription, <code>1</code> = allows Customers to modify their current Subscription or sign up for a new one, <code>2</code> = allows Customers to only modify their current Subscription.</li>' . "\n";
717
+ echo '<li><code>cancel="0"</code> Cancellation Button. Only valid w/ Membership Level Access. Possible values: <code>0</code> = this is NOT a Cancellation Button, <code>1</code> = this IS a Cancellation Button.</li>' . "\n";
718
+ echo '<li><code>sp="0"</code> Specific Post/Page Button. Possible values: <code>0</code> = this is NOT a Specific Post/Page Access Button, <code>1</code> = this IS a Specific Post/Page Access Button.</li>' . "\n";
719
+ echo '<li><code>ids="14"</code> A Post/Page ID#, or a comma-delimited list of IDs. Only valid when <code>sp="1"</code> for Specific Post/Page Access.</li>' . "\n";
720
+ echo '<li><code>exp="72"</code> Access Expires ( in hours ). Only valid when <code>sp="1"</code> for Specific Post/Page Access.</li>' . "\n";
721
+ echo '</ul>' . "\n";
722
+ echo '</td>' . "\n";
723
+ /**/
724
+ echo '</tr>' . "\n";
725
+ echo '</tbody>' . "\n";
726
+ echo '</table>' . "\n";
727
+ echo '</div>' . "\n";
728
+ /**/
729
+ echo '</div>' . "\n";
730
+ /**/
731
+ do_action ("ws_plugin__s2member_during_paypal_buttons_page_during_left_sections_after_shortcode_attrs", get_defined_vars ());
732
+ }
733
+ /**/
734
  do_action ("ws_plugin__s2member_during_paypal_buttons_page_after_left_sections", get_defined_vars ());
735
  /**/
736
  echo '</td>' . "\n";
includes/menu-pages/paypal-ops.inc.php CHANGED
@@ -12,7 +12,7 @@ If not, see: <http://www.gnu.org/licenses/>.
12
  Direct access denial.
13
  */
14
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
15
- exit("Do not access this file directly.");
16
  /*
17
  PayPal® Options page.
18
  */
@@ -40,9 +40,9 @@ if (apply_filters ("ws_plugin__s2member_during_paypal_ops_page_during_left_secti
40
  /**/
41
  echo '<div class="ws-menu-page-group" title="PayPal® Account Details">' . "\n";
42
  /**/
43
- echo '<div class="ws-menu-page-section ws-plugin--s2member-paypal-email-section">' . "\n";
44
  echo '<a href="https://www.paypal.com/us/mrb/pal=KMEJ5UCMUQVAW" target="_blank"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/paypal-logo.png" class="ws-menu-page-right" style="width:125px; height:125px; border:0;" alt="." /></a>' . "\n";
45
- echo '<h3>PayPal® Account Details ( required, please customize these )</h3>' . "\n";
46
  echo '<p>This plugin works in conjunction with <a href="https://www.paypal.com/us/mrb/pal=KMEJ5UCMUQVAW" target="_blank" rel="external">PayPal® Website Payments Standard</a>, for businesses. You do NOT need a PayPal® Pro account. You just need to upgrade your Personal PayPal® account to a Business status, which is free. A PayPal® account can be <a href="http://pages.ebay.com/help/buy/questions/upgrade-paypal-account.html" target="_blank" rel="external">upgraded</a> from a Personal account to a Business account, simply by going to the `Profile` button under the `My Account` tab, selecting the `Personal Business Information` button, and then clicking the `Upgrade Your Account` button.</p>' . "\n";
47
  do_action ("ws_plugin__s2member_during_paypal_ops_page_during_left_sections_during_paypal_account_details", get_defined_vars ());
48
  /**/
@@ -88,7 +88,7 @@ if (apply_filters ("ws_plugin__s2member_during_paypal_ops_page_during_left_secti
88
  echo '<tr>' . "\n";
89
  /**/
90
  echo '<td>' . "\n";
91
- echo '<input type="radio" name="ws_plugin__s2member_paypal_sandbox" id="ws-plugin--s2member-paypal-sandbox-0" value="0"' . ((!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? ' checked="checked"' : '') . ' /> <label for="ws-plugin--s2member-paypal-sandbox-0">No</label> &nbsp;&nbsp;&nbsp; <input type="radio" name="ws_plugin__s2member_paypal_sandbox" id="ws-plugin--s2member-paypal-sandbox-1" value="1"' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? ' checked="checked"' : '') . ' /> <label for="ws-plugin--s2member-paypal-sandbox-1">Yes, enable support for Sandbox testing.</label><br />' . "\n";
92
  echo '<em>Only enable this if you\'ve provided a Sandbox email address above.<br />This puts the API, IPN, PDT and Form/Button Generators all into Sandbox mode.<br />See: <a href="https://developer.paypal.com/" target="_blank" rel="external">https://developer.paypal.com</a></em>' . "\n";
93
  echo '</td>' . "\n";
94
  /**/
@@ -99,7 +99,7 @@ if (apply_filters ("ws_plugin__s2member_during_paypal_ops_page_during_left_secti
99
  echo '<tr>' . "\n";
100
  /**/
101
  echo '<th>' . "\n";
102
- echo '<label for="ws-plugin--s2member-paypal-debug">' . "\n";
103
  echo 'Enable Logging Routines?' . "\n";
104
  echo '</label>' . "\n";
105
  echo '</th>' . "\n";
@@ -108,7 +108,7 @@ if (apply_filters ("ws_plugin__s2member_during_paypal_ops_page_during_left_secti
108
  echo '<tr>' . "\n";
109
  /**/
110
  echo '<td>' . "\n";
111
- echo '<input type="radio" name="ws_plugin__s2member_paypal_debug" id="ws-plugin--s2member-paypal-debug-0" value="0"' . ((!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_debug"]) ? ' checked="checked"' : '') . ' /> <label for="ws-plugin--s2member-paypal-debug-0">No</label> &nbsp;&nbsp;&nbsp; <input type="radio" name="ws_plugin__s2member_paypal_debug" id="ws-plugin--s2member-paypal-debug-1" value="1"' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_debug"]) ? ' checked="checked"' : '') . ' /> <label for="ws-plugin--s2member-paypal-debug-1">Yes, enable debugging, with API, IPN &amp; Return Page logging.</label><br />' . "\n";
112
  echo '<em>This enables API, IPN and Return Page logging. The log files are stored here:<br /><code>' . preg_replace ("/^" . preg_quote ($_SERVER["DOCUMENT_ROOT"], "/") . "/", "", $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"]) . '</code></em>' . "\n";
113
  echo '</td>' . "\n";
114
  /**/
@@ -281,19 +281,19 @@ if (apply_filters ("ws_plugin__s2member_during_paypal_ops_page_during_left_secti
281
  echo '<ul>' . "\n";
282
  echo '<li><code>%%registration_url%%</code> = The full URL ( generated by s2Member ) where the Customer can get registered.</li>' . "\n";
283
  echo '<li><code>%%subscr_id%%</code> = The PayPal® Subscription ID, which remains constant throughout any &amp; all future payments. [ <a href="#" onclick="alert(\'There is one exception. If you are selling Lifetime or Fixed-Term ( non-recurring ) access, using Buy Now functionality; the %%subscr_id%% is actually set to the Transaction ID for the purchase.\\n\\nPayPal® does not provide a specific Subscription ID for Buy Now purchases. Since Lifetime &amp; Fixed-Term Subscriptions are NOT recurring ( i.e. there is only ONE payment ), using the Transaction ID as the Subscription ID is a graceful way to deal with this minor conflict.\'); return false;">?</a> ]</li>' . "\n";
284
- echo '<li><code>%%initial%%</code> = The Initial Fee charged during signup. If you offered a free trial, this will be <code>0</code>. [ <a href="#" onclick="alert(\'This will always represent the amount of money the Customer spent, whenever they initially signed up, no matter what. If a Customer signs up, under the terms of a free trial period, this will be 0.\'); return false;">?</a> ]</li>' . "\n";
285
- echo '<li><code>%%regular%%</code> = The Regular Amount of the Subscription. This value is <code>always > 0</code>, no matter what. [ <a href="#" onclick="alert(\'This is how much the Subscription costs after an initial period expires. The %%regular%% rate is always > 0. If you did not offer an initial period, %%initial%% and %%regular%% will be equal to the same thing.\'); return false;">?</a> ]</li>' . "\n";
286
- echo '<li><code>%%recurring%%</code> = This is the amount that will be charged on a Recurring basis, or <code>0</code> if non-Recurring. [ <a href="#" onclick="alert(\'If recurring payments have not been required, this will be equal to 0. That being said, %%regular%% &amp; %%recurring%% are usually the same value. This variable can be used in two different ways. You can use it to determine what the regular recurring rate is, or to determine whether the Subscription will recur or not. If it is going to recur, %%recurring%% will be > 0.\'); return false;">?</a> ]</li>' . "\n";
287
  echo '<li><code>%%first_name%%</code> = The First Name of the Customer who purchased the Membership Subscription.</li>' . "\n";
288
  echo '<li><code>%%last_name%%</code> = The Last Name of the Customer who purchased the Membership Subscription.</li>' . "\n";
289
  echo '<li><code>%%full_name%%</code> = The Full Name ( First &amp; Last ) of the Customer who purchased the Membership Subscription.</li>' . "\n";
290
  echo '<li><code>%%payer_email%%</code> = The Email Address of the Customer who purchased the Membership Subscription.</li>' . "\n";
291
  echo '<li><code>%%item_number%%</code> = The Item Number ( colon separated <code><em>level:custom_capabilities:fixed term</em></code> ) that the Subscription is for.</li>' . "\n";
292
  echo '<li><code>%%item_name%%</code> = The Item Name ( as provided by the <code>desc=""</code> attribute in your Shortcode, which briefly describes the Item Number ).</li>' . "\n";
293
- echo '<li><code>%%initial_term%%</code> = This is the term length of the initial period. This will be a numeric value, followed by a space, then a single letter. [ <a href="#" onclick="alert(\'Here are some examples:\\n\\n%%initial_term%% = 1 D ( this means 1 Day )\\n%%initial_term%% = 1 W ( this means 1 Week )\\n%%initial_term%% = 1 M ( this means 1 Month )\\n%%initial_term%% = 1 Y ( this means 1 Year )\\n\\nThe initial period never recurs, so this only lasts for the term length specified, then it is over. If no initial period was even offered, the value of %%initial_term%% will just be: 0 D, meaning zero days.\'); return false;">?</a> ]</li>' . "\n";
294
- echo '<li><code>%%initial_cycle%%</code> = This is the <code>%%initial_term%%</code> from above, converted ( and reduced ) to just a cycle representation, of: <code><em>Daily, Weekly, Monthly, or Yearly</em></code>.</li>' . "\n";
295
- echo '<li><code>%%regular_term%%</code> = This is the term length of the regular period. This will be a numeric value, followed by a space, then a single letter. [ <a href="#" onclick="alert(\'Here are some examples:\\n\\n%%regular_term%% = 1 D ( this means 1 Day )\\n%%regular_term%% = 1 W ( this means 1 Week )\\n%%regular_term%% = 1 M ( this means 1 Month )\\n%%regular_term%% = 1 Y ( this means 1 Year )\\n%%regular_term%% = 1 L ( this means 1 Lifetime )\\n\\nThe regular term is usually recurring. So the regular term value represents the period ( or duration ) of each recurring period. If %%recurring%% = 0, then the regular term only applies once, because it is not recurring. So if it is not recurring, the value of %%regular_term%% simply represents how long their membership privileges are going to last after the %%initial_term%% has expired, if there was an initial term. The value of this variable ( %%regular_term%% ) will never be empty, it will always be at least: 1 D, meaning 1 day. No exceptions.\'); return false;">?</a> ]</li>' . "\n";
296
- echo '<li><code>%%regular_cycle%%</code> = This is the <code>%%regular_term%%</code> from above, converted ( and reduced ) to just a cycle representation, of: <code><em>Daily, Weekly, Monthly, Yearly, or Lifetime</em></code>.</li>' . "\n";
297
  echo '<li><code>%%recurring/regular_cycle%%</code> = Example ( <code>14.95 / Monthly</code> ), or ... ( <code>0 / non-recurring</code> ); depending on the value of <code>%%recurring%%</code>.</li>' . "\n";
298
  echo '</ul>' . "\n";
299
  /**/
@@ -431,10 +431,10 @@ if (apply_filters ("ws_plugin__s2member_during_paypal_ops_page_during_left_secti
431
  echo '<h3>PayPal® EOT Behavior ( required, please choose )</h3>' . "\n";
432
  echo '<p>EOT = End Of Term. By default, s2Member will demote a paid Member to a Free Subscriber whenever their Subscription term has ended ( i.e. expired ), been cancelled, refunded, charged back to you, etc. s2Member demotes them to a Free Subscriber, so they will no longer have Member Level Access to your site. However, in some cases, you may prefer to have Customer accounts deleted completely, instead of just being demoted. This is where you choose which method works best for your site. If you don\'t want s2Member to take ANY action at all, you can disable s2Member\'s EOT System temporarily, or even completely.</p>' . "\n";
433
  echo '<p>The PayPal® IPN service will notify s2Member whenever a Member\'s payments have been failing, and/or whenever a Member\'s Subscription has expired for any reason. Even refunds &amp; chargeback reversals are supported through the IPN service. If you issue a refund to an unhappy Customer through PayPal®, s2Member will be notified, and the account for that Customer will either be demoted to a Free Subscriber, or deleted automatically ( based on your configuration ). The communication from PayPal® -> s2Member is seamless.</p>' . "\n";
434
- echo '<p><em><strong>*Some Hairy Details*</strong> There might be times whenever you notice that a Members\'s Subscription has been cancelled through PayPal®... but, s2Member continues allowing the User access to your site as a paid Member. Please don\'t be confused by this... in 99.9% of these cases, the reason for this is legitimate. s2Member will only remove the User\'s membership privileges when PayPal® sends a <code>subscr_eot</code> notification via the IPN service, a refund occurs, a chargeback occurs, or when a cancellation occurs - which would later result in a delayed Auto-EOT by s2Member. s2Member will not process an EOT until the User has completely used up the time they paid for. In other words, if a User signs up for a monthly Subscription on Jan 1st, and then cancels their Subscription on Jan 15th; technically, they should still be allowed to access the site for another 15 days, and then on Feb 1st, the time they paid for has completely elapsed. At that time, s2Member will remove their membership privileges; by either demoting them to a Free Subscriber, or deleting their account from the system ( based on your configuration ). s2Member also calculates one extra day ( 24 hours ) into its equation, just to make sure access is not removed sooner than a Customer might expect.</em></p>' . "\n";
435
  do_action ("ws_plugin__s2member_during_paypal_ops_page_during_left_sections_during_eot_behavior", get_defined_vars ());
436
  /**/
437
- echo '<p id="ws-plugin--s2member-auto-eot-system-enabled-via-cron"' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["auto_eot_system_enabled"] == 2 && (!function_exists ("wp_cron") || !wp_get_schedule ("ws_plugin__s2member_auto_eot_system__schedule"))) ? '' : ' style="display:none;"') . '>If you\'d like to run s2Member\'s Auto-EOT System through a more traditional Cron Job; instead of through <code>WP-Cron</code>, you will need to configure a Cron Job through your server control panel; provided by your hosting company. Set the Cron Job to run <code>once about every 10 minutes to an hour</code>. You\'ll want to configure an HTTP Cron Job that loads this URL:<br /><code>' . esc_html (add_query_arg ("s2member_auto_eot_system_via_cron", "1", get_bloginfo ("wpurl") . "/")) . '</code></p>' . "\n";
438
  /**/
439
  echo '<table class="form-table">' . "\n";
440
  echo '<tbody>' . "\n";
@@ -452,10 +452,10 @@ if (apply_filters ("ws_plugin__s2member_during_paypal_ops_page_during_left_secti
452
  echo '<td>' . "\n";
453
  echo '<select name="ws_plugin__s2member_auto_eot_system_enabled" id="ws-plugin--s2member-auto-eot-system-enabled">' . "\n";
454
  /* Very advanced conditionals here. If the Auto-EOT System is NOT running, or NOT fully configured, this will indicate that no option is set - as sort of a built-in acknowledgment/warning in the UI panel. */
455
- echo (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["auto_eot_system_enabled"] == 1 && (!function_exists ("wp_cron") || !wp_get_schedule ("ws_plugin__s2member_auto_eot_system__schedule"))) || ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["auto_eot_system_enabled"] == 2 && (function_exists ("wp_cron") && wp_get_schedule ("ws_plugin__s2member_auto_eot_system__schedule"))) || (!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["auto_eot_system_enabled"] && (function_exists ("wp_cron") && wp_get_schedule ("ws_plugin__s2member_auto_eot_system__schedule")))) ? '<option value=""></option>' . "\n" : '';
456
- echo '<option value="1"' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["auto_eot_system_enabled"] == 1 && function_exists ("wp_cron") && wp_get_schedule ("ws_plugin__s2member_auto_eot_system__schedule")) ? ' selected="selected"' : '') . '>Yes ( enable the Auto-EOT System through WP-Cron )</option>' . "\n";
457
- echo (!is_multisite () || !ws_plugin__s2member_is_multisite_farm () || is_main_site ()) ? '<option value="2"' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["auto_eot_system_enabled"] == 2 && (!function_exists ("wp_cron") || !wp_get_schedule ("ws_plugin__s2member_auto_eot_system__schedule"))) ? ' selected="selected"' : '') . '>Yes ( but, I\'ll run it with my own Cron Job )</option>' . "\n" : '';
458
- echo '<option value="0"' . ((!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["auto_eot_system_enabled"] && (!function_exists ("wp_cron") || !wp_get_schedule ("ws_plugin__s2member_auto_eot_system__schedule"))) ? ' selected="selected"' : '') . '>No ( disable the Auto-EOT System )</option>' . "\n";
459
  echo '</select><br />' . "\n";
460
  echo 'Recommended setting: ( <code>Yes / enable via WP-Cron</code> )' . "\n";
461
  echo '</td>' . "\n";
@@ -474,8 +474,8 @@ if (apply_filters ("ws_plugin__s2member_during_paypal_ops_page_during_left_secti
474
  /**/
475
  echo '<td>' . "\n";
476
  echo '<select name="ws_plugin__s2member_membership_eot_behavior" id="ws-plugin--s2member-membership-eot-behavior">' . "\n";
477
- echo '<option value="demote"' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_eot_behavior"] === "demote") ? ' selected="selected"' : '') . '>Demote ( convert them to a Free Subscriber )</option>' . "\n";
478
- echo '<option value="delete"' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_eot_behavior"] === "delete") ? ' selected="selected"' : '') . '>Delete ( erase their account completely )</option>' . "\n";
479
  echo '</select>' . "\n";
480
  echo '</td>' . "\n";
481
  /**/
@@ -493,10 +493,10 @@ if (apply_filters ("ws_plugin__s2member_during_paypal_ops_page_during_left_secti
493
  /**/
494
  echo '<td>' . "\n";
495
  echo '<select name="ws_plugin__s2member_triggers_immediate_eot" id="ws-plugin--s2member-triggers-immediate-eot">' . "\n";
496
- echo '<option value="none"' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["triggers_immediate_eot"] === "none") ? ' selected="selected"' : '') . '>Neither ( I\'ll review these two events manually )</option>' . "\n";
497
- echo '<option value="refunds"' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["triggers_immediate_eot"] === "refunds") ? ' selected="selected"' : '') . '>Refunds ( refunds ALWAYS trigger an immediate EOT action )</option>' . "\n";
498
- echo '<option value="reversals"' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["triggers_immediate_eot"] === "reversals") ? ' selected="selected"' : '') . '>Reversals ( chargebacks ALWAYS trigger an immediate EOT action )</option>' . "\n";
499
- echo '<option value="refunds,reversals"' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["triggers_immediate_eot"] === "refunds,reversals") ? ' selected="selected"' : '') . '>Refunds/Reversals ( ALWAYS trigger an immediate EOT action )</option>' . "\n";
500
  echo '</select><br />' . "\n";
501
  echo 'This setting will <a href="#" onclick="alert(\'A Refund/Reversal Notification will ALWAYS be processed internally by s2Member, even if no action is taken by s2Member. This way you\\\'ll have the full ability to listen for these two events on your own; if you prefer ( optional ). For more information, check your Dashboard under: `s2Member -> API Notifications -> Refunds/Reversals`.\'); return false;">NOT affect</a> s2Member\'s internal API Notifications for Refund/Reversal events.' . "\n";
502
  echo '</td>' . "\n";
12
  Direct access denial.
13
  */
14
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
15
+ exit ("Do not access this file directly.");
16
  /*
17
  PayPal® Options page.
18
  */
40
  /**/
41
  echo '<div class="ws-menu-page-group" title="PayPal® Account Details">' . "\n";
42
  /**/
43
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-paypal-account-details-section">' . "\n";
44
  echo '<a href="https://www.paypal.com/us/mrb/pal=KMEJ5UCMUQVAW" target="_blank"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/paypal-logo.png" class="ws-menu-page-right" style="width:125px; height:125px; border:0;" alt="." /></a>' . "\n";
45
+ echo '<h3>PayPal® Account Details ( required, if using PayPal® )</h3>' . "\n";
46
  echo '<p>This plugin works in conjunction with <a href="https://www.paypal.com/us/mrb/pal=KMEJ5UCMUQVAW" target="_blank" rel="external">PayPal® Website Payments Standard</a>, for businesses. You do NOT need a PayPal® Pro account. You just need to upgrade your Personal PayPal® account to a Business status, which is free. A PayPal® account can be <a href="http://pages.ebay.com/help/buy/questions/upgrade-paypal-account.html" target="_blank" rel="external">upgraded</a> from a Personal account to a Business account, simply by going to the `Profile` button under the `My Account` tab, selecting the `Personal Business Information` button, and then clicking the `Upgrade Your Account` button.</p>' . "\n";
47
  do_action ("ws_plugin__s2member_during_paypal_ops_page_during_left_sections_during_paypal_account_details", get_defined_vars ());
48
  /**/
88
  echo '<tr>' . "\n";
89
  /**/
90
  echo '<td>' . "\n";
91
+ echo '<input type="radio" name="ws_plugin__s2member_paypal_sandbox" id="ws-plugin--s2member-paypal-sandbox-0" value="0"' . ( (!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? ' checked="checked"' : '') . ' /> <label for="ws-plugin--s2member-paypal-sandbox-0">No</label> &nbsp;&nbsp;&nbsp; <input type="radio" name="ws_plugin__s2member_paypal_sandbox" id="ws-plugin--s2member-paypal-sandbox-1" value="1"' . ( ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? ' checked="checked"' : '') . ' /> <label for="ws-plugin--s2member-paypal-sandbox-1">Yes, enable support for Sandbox testing.</label><br />' . "\n";
92
  echo '<em>Only enable this if you\'ve provided a Sandbox email address above.<br />This puts the API, IPN, PDT and Form/Button Generators all into Sandbox mode.<br />See: <a href="https://developer.paypal.com/" target="_blank" rel="external">https://developer.paypal.com</a></em>' . "\n";
93
  echo '</td>' . "\n";
94
  /**/
99
  echo '<tr>' . "\n";
100
  /**/
101
  echo '<th>' . "\n";
102
+ echo '<label for="ws-plugin--s2member-gateway-debug-logs">' . "\n";
103
  echo 'Enable Logging Routines?' . "\n";
104
  echo '</label>' . "\n";
105
  echo '</th>' . "\n";
108
  echo '<tr>' . "\n";
109
  /**/
110
  echo '<td>' . "\n";
111
+ 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, with API, IPN &amp; Return Page logging.</label><br />' . "\n";
112
  echo '<em>This enables API, IPN and Return Page logging. The log files are stored here:<br /><code>' . preg_replace ("/^" . preg_quote ($_SERVER["DOCUMENT_ROOT"], "/") . "/", "", $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"]) . '</code></em>' . "\n";
113
  echo '</td>' . "\n";
114
  /**/
281
  echo '<ul>' . "\n";
282
  echo '<li><code>%%registration_url%%</code> = The full URL ( generated by s2Member ) where the Customer can get registered.</li>' . "\n";
283
  echo '<li><code>%%subscr_id%%</code> = The PayPal® Subscription ID, which remains constant throughout any &amp; all future payments. [ <a href="#" onclick="alert(\'There is one exception. If you are selling Lifetime or Fixed-Term ( non-recurring ) access, using Buy Now functionality; the %%subscr_id%% is actually set to the Transaction ID for the purchase.\\n\\nPayPal® does not provide a specific Subscription ID for Buy Now purchases. Since Lifetime &amp; Fixed-Term Subscriptions are NOT recurring ( i.e. there is only ONE payment ), using the Transaction ID as the Subscription ID is a graceful way to deal with this minor conflict.\'); return false;">?</a> ]</li>' . "\n";
284
+ echo '<li><code>%%initial%%</code> = The Initial Fee charged during signup. If you offered a 100% Free Trial, this will be <code>0</code>. [ <a href="#" onclick="alert(\'This will always represent the amount of money the Customer spent, whenever they initially signed up, no matter what. If a Customer signs up, under the terms of a 100% Free Trial Period, this will be 0.\'); return false;">?</a> ]</li>' . "\n";
285
+ echo '<li><code>%%regular%%</code> = The Regular Amount of the Subscription. This value is <code>always > 0</code>, no matter what. [ <a href="#" onclick="alert(\'This is how much the Subscription costs after an Initial Period expires. The %%regular%% rate is always > 0. If you did NOT offer an Initial Period at a different price, %%initial%% and %%regular%% will be equal to the same thing.\'); return false;">?</a> ]</li>' . "\n";
286
+ echo '<li><code>%%recurring%%</code> = This is the amount that will be charged on a recurring basis, or <code>0</code> if non-recurring. [ <a href="#" onclick="alert(\'If Recurring Payments have not been required, this will be equal to 0. That being said, %%regular%% &amp; %%recurring%% are usually the same value. This variable can be used in two different ways. You can use it to determine what the Regular Recurring Rate is, or to determine whether the Subscription will recur or not. If it is going to recur, %%recurring%% will be > 0.\'); return false;">?</a> ]</li>' . "\n";
287
  echo '<li><code>%%first_name%%</code> = The First Name of the Customer who purchased the Membership Subscription.</li>' . "\n";
288
  echo '<li><code>%%last_name%%</code> = The Last Name of the Customer who purchased the Membership Subscription.</li>' . "\n";
289
  echo '<li><code>%%full_name%%</code> = The Full Name ( First &amp; Last ) of the Customer who purchased the Membership Subscription.</li>' . "\n";
290
  echo '<li><code>%%payer_email%%</code> = The Email Address of the Customer who purchased the Membership Subscription.</li>' . "\n";
291
  echo '<li><code>%%item_number%%</code> = The Item Number ( colon separated <code><em>level:custom_capabilities:fixed term</em></code> ) that the Subscription is for.</li>' . "\n";
292
  echo '<li><code>%%item_name%%</code> = The Item Name ( as provided by the <code>desc=""</code> attribute in your Shortcode, which briefly describes the Item Number ).</li>' . "\n";
293
+ echo '<li><code>%%initial_term%%</code> = This is the term length of the Initial Period. This will be a numeric value, followed by a space, then a single letter. [ <a href="#" onclick="alert(\'Here are some examples:\\n\\n%%initial_term%% = 1 D ( this means 1 Day )\\n%%initial_term%% = 1 W ( this means 1 Week )\\n%%initial_term%% = 1 M ( this means 1 Month )\\n%%initial_term%% = 1 Y ( this means 1 Year )\\n\\nThe Initial Period never recurs, so this only lasts for the term length specified, then it is over.\'); return false;">?</a> ]</li>' . "\n";
294
+ echo '<li><code>%%initial_cycle%%</code> = This is the <code>%%initial_term%%</code> from above, converted to a cycle representation of: <code><em>X days/weeks/months/years</em></code>.</li>' . "\n";
295
+ echo '<li><code>%%regular_term%%</code> = This is the term length of the Regular Period. This will be a numeric value, followed by a space, then a single letter. [ <a href="#" onclick="alert(\'Here are some examples:\\n\\n%%regular_term%% = 1 D ( this means 1 Day )\\n%%regular_term%% = 1 W ( this means 1 Week )\\n%%regular_term%% = 1 M ( this means 1 Month )\\n%%regular_term%% = 1 Y ( this means 1 Year )\\n%%regular_term%% = 1 L ( this means 1 Lifetime )\\n\\nThe Regular Term is usually recurring. So the Regular Term value represents the period ( or duration ) of each recurring period. If %%recurring%% = 0, then the Regular Term only applies once, because it is not recurring. So if it is not recurring, the value of %%regular_term%% simply represents how long their membership privileges are going to last after the %%initial_term%% has expired, if there was an Initial Term. The value of this variable ( %%regular_term%% ) will never be empty, it will always be at least: 1 D, meaning 1 day. No exceptions.\'); return false;">?</a> ]</li>' . "\n";
296
+ echo '<li><code>%%regular_cycle%%</code> = This is the <code>%%regular_term%%</code> from above, converted to a cycle representation of: <code><em>[every] X days/weeks/months/years — OR daily, weekly, bi-weekly, monthly, bi-monthly, quarterly, yearly, or lifetime</em></code>. This is a very useful Replacment Code. Its value is dynamic; depending on term length, recurring status, and period/term lengths configured.</li>' . "\n";
297
  echo '<li><code>%%recurring/regular_cycle%%</code> = Example ( <code>14.95 / Monthly</code> ), or ... ( <code>0 / non-recurring</code> ); depending on the value of <code>%%recurring%%</code>.</li>' . "\n";
298
  echo '</ul>' . "\n";
299
  /**/
431
  echo '<h3>PayPal® EOT Behavior ( required, please choose )</h3>' . "\n";
432
  echo '<p>EOT = End Of Term. By default, s2Member will demote a paid Member to a Free Subscriber whenever their Subscription term has ended ( i.e. expired ), been cancelled, refunded, charged back to you, etc. s2Member demotes them to a Free Subscriber, so they will no longer have Member Level Access to your site. However, in some cases, you may prefer to have Customer accounts deleted completely, instead of just being demoted. This is where you choose which method works best for your site. If you don\'t want s2Member to take ANY action at all, you can disable s2Member\'s EOT System temporarily, or even completely.</p>' . "\n";
433
  echo '<p>The PayPal® IPN service will notify s2Member whenever a Member\'s payments have been failing, and/or whenever a Member\'s Subscription has expired for any reason. Even refunds &amp; chargeback reversals are supported through the IPN service. If you issue a refund to an unhappy Customer through PayPal®, s2Member will be notified, and the account for that Customer will either be demoted to a Free Subscriber, or deleted automatically ( based on your configuration ). The communication from PayPal® -> s2Member is seamless.</p>' . "\n";
434
+ echo '<p><em><strong>*Some Hairy Details*</strong> There might be times whenever you notice that a Members\'s Subscription has been cancelled through PayPal®... but, s2Member continues allowing the User access to your site as a paid Member. Please don\'t be confused by this... in 99.9% of these cases, the reason for this is legitimate. s2Member will only remove the User\'s membership privileges when an EOT ( End Of Term ) is processed, a refund occurs, a chargeback occurs, or when a cancellation occurs - which would later result in a delayed Auto-EOT by s2Member. s2Member will not process an EOT until the User has completely used up the time they paid for. In other words, if a User signs up for a monthly Subscription on Jan 1st, and then cancels their Subscription on Jan 15th; technically, they should still be allowed to access the site for another 15 days, and then on Feb 1st, the time they paid for has completely elapsed. At that time, s2Member will remove their membership privileges; by either demoting them to a Free Subscriber, or deleting their account from the system ( based on your configuration ). s2Member also calculates one extra day ( 24 hours ) into its equation, just to make sure access is not removed sooner than a Customer might expect.</em></p>' . "\n";
435
  do_action ("ws_plugin__s2member_during_paypal_ops_page_during_left_sections_during_eot_behavior", get_defined_vars ());
436
  /**/
437
+ echo '<p id="ws-plugin--s2member-auto-eot-system-enabled-via-cron"' . ( ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["auto_eot_system_enabled"] == 2 && (!function_exists ("wp_cron") || !wp_get_schedule ("ws_plugin__s2member_auto_eot_system__schedule"))) ? '' : ' style="display:none;"') . '>If you\'d like to run s2Member\'s Auto-EOT System through a more traditional Cron Job; instead of through <code>WP-Cron</code>, you will need to configure a Cron Job through your server control panel; provided by your hosting company. Set the Cron Job to run <code>once about every 10 minutes to an hour</code>. You\'ll want to configure an HTTP Cron Job that loads this URL:<br /><code>' . esc_html (add_query_arg ("s2member_auto_eot_system_via_cron", urlencode ("1"), get_bloginfo ("wpurl") . "/")) . '</code></p>' . "\n";
438
  /**/
439
  echo '<table class="form-table">' . "\n";
440
  echo '<tbody>' . "\n";
452
  echo '<td>' . "\n";
453
  echo '<select name="ws_plugin__s2member_auto_eot_system_enabled" id="ws-plugin--s2member-auto-eot-system-enabled">' . "\n";
454
  /* Very advanced conditionals here. If the Auto-EOT System is NOT running, or NOT fully configured, this will indicate that no option is set - as sort of a built-in acknowledgment/warning in the UI panel. */
455
+ echo ( ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["auto_eot_system_enabled"] == 1 && (!function_exists ("wp_cron") || !wp_get_schedule ("ws_plugin__s2member_auto_eot_system__schedule"))) || ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["auto_eot_system_enabled"] == 2 && (function_exists ("wp_cron") && wp_get_schedule ("ws_plugin__s2member_auto_eot_system__schedule"))) || (!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["auto_eot_system_enabled"] && (function_exists ("wp_cron") && wp_get_schedule ("ws_plugin__s2member_auto_eot_system__schedule")))) ? '<option value=""></option>' . "\n" : '';
456
+ echo '<option value="1"' . ( ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["auto_eot_system_enabled"] == 1 && function_exists ("wp_cron") && wp_get_schedule ("ws_plugin__s2member_auto_eot_system__schedule")) ? ' selected="selected"' : '') . '>Yes ( enable the Auto-EOT System through WP-Cron )</option>' . "\n";
457
+ echo (!is_multisite () || !ws_plugin__s2member_is_multisite_farm () || is_main_site ()) ? '<option value="2"' . ( ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["auto_eot_system_enabled"] == 2 && (!function_exists ("wp_cron") || !wp_get_schedule ("ws_plugin__s2member_auto_eot_system__schedule"))) ? ' selected="selected"' : '') . '>Yes ( but, I\'ll run it with my own Cron Job )</option>' . "\n" : '';
458
+ echo '<option value="0"' . ( (!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["auto_eot_system_enabled"] && (!function_exists ("wp_cron") || !wp_get_schedule ("ws_plugin__s2member_auto_eot_system__schedule"))) ? ' selected="selected"' : '') . '>No ( disable the Auto-EOT System )</option>' . "\n";
459
  echo '</select><br />' . "\n";
460
  echo 'Recommended setting: ( <code>Yes / enable via WP-Cron</code> )' . "\n";
461
  echo '</td>' . "\n";
474
  /**/
475
  echo '<td>' . "\n";
476
  echo '<select name="ws_plugin__s2member_membership_eot_behavior" id="ws-plugin--s2member-membership-eot-behavior">' . "\n";
477
+ echo '<option value="demote"' . ( ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_eot_behavior"] === "demote") ? ' selected="selected"' : '') . '>Demote ( convert them to a Free Subscriber )</option>' . "\n";
478
+ echo '<option value="delete"' . ( ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_eot_behavior"] === "delete") ? ' selected="selected"' : '') . '>Delete ( erase their account completely )</option>' . "\n";
479
  echo '</select>' . "\n";
480
  echo '</td>' . "\n";
481
  /**/
493
  /**/
494
  echo '<td>' . "\n";
495
  echo '<select name="ws_plugin__s2member_triggers_immediate_eot" id="ws-plugin--s2member-triggers-immediate-eot">' . "\n";
496
+ echo '<option value="none"' . ( ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["triggers_immediate_eot"] === "none") ? ' selected="selected"' : '') . '>Neither ( I\'ll review these two events manually )</option>' . "\n";
497
+ echo '<option value="refunds"' . ( ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["triggers_immediate_eot"] === "refunds") ? ' selected="selected"' : '') . '>Refunds ( refunds ALWAYS trigger an immediate EOT action )</option>' . "\n";
498
+ echo '<option value="reversals"' . ( ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["triggers_immediate_eot"] === "reversals") ? ' selected="selected"' : '') . '>Reversals ( chargebacks ALWAYS trigger an immediate EOT action )</option>' . "\n";
499
+ echo '<option value="refunds,reversals"' . ( ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["triggers_immediate_eot"] === "refunds,reversals") ? ' selected="selected"' : '') . '>Refunds/Reversals ( ALWAYS trigger an immediate EOT action )</option>' . "\n";
500
  echo '</select><br />' . "\n";
501
  echo 'This setting will <a href="#" onclick="alert(\'A Refund/Reversal Notification will ALWAYS be processed internally by s2Member, even if no action is taken by s2Member. This way you\\\'ll have the full ability to listen for these two events on your own; if you prefer ( optional ). For more information, check your Dashboard under: `s2Member -> API Notifications -> Refunds/Reversals`.\'); return false;">NOT affect</a> s2Member\'s internal API Notifications for Refund/Reversal events.' . "\n";
502
  echo '</td>' . "\n";
includes/menu-pages/scripting.inc.php CHANGED
@@ -238,11 +238,11 @@ if (apply_filters ("ws_plugin__s2member_during_scripting_page_during_left_sectio
238
  /**/
239
  echo '<div class="ws-menu-page-section ws-plugin--s2member-custom-capabilities-section">' . "\n";
240
  echo '<h3>Packaging Together Custom Capabilities w/ Membership</h3>' . "\n";
241
- echo '<p>Using the PayPal® Button Generator for s2Member, you can add Custom Capabilities in comma delimited format. s2Member builds upon existing functionality offered by WordPress® Roles/Capabilities. s2Member supports Free Subscribers ( at Level #0 ), and up to four Primary Roles ( i.e. s2Member Levels 1-4 ). Each s2Member Level provides <code>current_user_can("access_s2member_level0"), 1, 2, 3, 4</code>. These are the default Capabilities that come with each Membership Level. Now... If you\'d like to package together some variations of each Membership Level that you\'re selling, you can! All you do is add some Custom Capabilities whenever you create your PayPal® Button Code ( <em>there is a field in the Button Generator where you can enter Custom Capabilities</em> ). You can sell membership packages that come with Custom Capabilities, and even with custom prices.</p>' . "\n";
242
  echo '<p>Custom Capabilities are an extension to a feature that already exists in WordPress®. The <code>current_user_can()</code> function, can be used to test for these additional Capabilities that you allow. Whenever a Member completes the checkout process, after having purchased a Membership from you ( one that included Custom Capabilities ), s2Member will add those Custom Capabilities to the account for that specific Member.</p>' . "\n";
243
  echo '<p>Custom Capabilities are always prepended with <code>access_s2member_ccap_</code>. You fill in the last part, with ONLY lowercase alpha-numerics and/or underscores. For example, let\'s say you want to sell Membership Level #1, as is. But, you also want to sell a slight variation of Membership Level #1, that includes the ability to access the Music &amp; Video sections of your site. So, instead of selling this additional access under a whole new Membership Level, you could just sell a modified version of Membership Level #1. Add the the Custom Capabilities: <code>music,videos</code>. Once a Member has these Capabilities, you can test for these Capabilities using <code>current_user_can("access_s2member_ccap_music")</code> and <code>current_user_can("access_s2member_ccap_videos")</code>.</p>' . "\n";
244
  echo '<p>The important thing to realize, is that Custom Capabilities, are just that. They\'re custom. s2Member only deals with the default Capabilities that it uses. If you start using Custom Capabilities, you MUST use Simple or Advanced Conditionals ( <em>i.e. <code>current_user_can</code> logic</em> ) to test for them. Either in your theme files with PHP, or in Posts/Pages using Simple Conditionals ( powered by Shortcodes ).</p>' . "\n";
245
- echo '<p><em class="ws-menu-page-hilite"><strong>*Tip*</strong> Starting with s2Member v3.2+, you can now tell s2Member to require Custom Capabilities on a per Post/Page basis. So now, s2Member ( if you prefer ) can handle Custom Capabilities for you! Whenever you edit a Post/Page, you can tell s2Member to require certain Custom Capabilities that you type in, using comma delimited format. In other words, you will need to type in some of the trigger words that you used whenever you created your PayPal® Pro Forms and/or PayPal® Buttons. This way your Members will have the proper Capabilities to view different kinds of content that you offer.</em></p>' . "\n";
246
  do_action ("ws_plugin__s2member_during_scripting_page_during_left_sections_during_custom_capabilities", get_defined_vars ());
247
  /**/
248
  echo '<div class="ws-menu-page-hr"></div>' . "\n";
@@ -303,10 +303,24 @@ if (apply_filters ("ws_plugin__s2member_during_scripting_page_during_left_sectio
303
  /**/
304
  echo '<div class="ws-menu-page-section ws-plugin--s2member-api-advanced-dripping-section">' . "\n";
305
  echo '<h3>Dripping Content ( some PHP scripting required )</h3>' . "\n";
306
- echo '<p>Content Dripping is the gradual, pre-scheduled release of premium website content to paying Members. This has become increasingly popular, because it allows older Members; those who have paid you more, due to recurring charges; to acquire access to more content progressively; based on their original registration date. It also gives you ( as the site owner ), the ability to launch multiple membership site portals, operating on autopilot, without any direct day-to-day involvement in a content release process. This requires some PHP scripting. In order to use PHP scripting inside your Posts/Pages, you\'ll need to install this handy plugin ( <a href="http://wordpress.org/extend/plugins/exec-php/" target="_blank" rel="external">Exec-PHP</a> ).</p>' . "\n";
307
  do_action ("ws_plugin__s2member_during_scripting_page_during_left_sections_during_api_advanced_dripping", get_defined_vars ());
308
- echo '<p><strong>To drip content, use <code>S2MEMBER_CURRENT_USER_REGISTRATION_DAYS</code>:</strong></p>' . "\n";
309
- echo '<p>' . ws_plugin__s2member_highlight_php (file_get_contents (dirname (__FILE__) . "/code-samples/current-user-registration-days-dripping.php")) . '</p>' . "\n";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
310
  echo '</div>' . "\n";
311
  /**/
312
  echo '</div>' . "\n";
@@ -407,16 +421,26 @@ if (apply_filters ("ws_plugin__s2member_during_scripting_page_during_left_sectio
407
  /**/
408
  echo '<div class="ws-menu-page-hr"></div>' . "\n";
409
  /**/
410
- echo '<p><strong>S2MEMBER_CURRENT_USER_REGISTRATION_TIME</strong><br />This will always be an (int); in the form of a Unix timestamp. 0 if not logged in. This holds the recorded time at which the Member originally registered their Username for access to your site. This is useful if you want to drip content over an extended period of time, based on how long someone has been a Member.</p>' . "\n";
411
  echo '<p>' . ws_plugin__s2member_highlight_php (file_get_contents (dirname (__FILE__) . "/code-samples/current-user-registration-time.php")) . '</p>' . "\n";
412
  /**/
413
  echo '<div class="ws-menu-page-hr"></div>' . "\n";
414
  /**/
415
- echo '<p><strong>S2MEMBER_CURRENT_USER_REGISTRATION_DAYS</strong><br />This will always be an (int). 0 if not logged in. This is the number of days that have passed since the Member originally registered their Username for access to your site. This is useful if you want to drip content over an extended period of time, based on how long someone has been a Member.</p>' . "\n";
416
  echo '<p>' . ws_plugin__s2member_highlight_php (file_get_contents (dirname (__FILE__) . "/code-samples/current-user-registration-days.php")) . '</p>' . "\n";
417
  /**/
418
  echo '<div class="ws-menu-page-hr"></div>' . "\n";
419
  /**/
 
 
 
 
 
 
 
 
 
 
420
  echo '<p><strong>S2MEMBER_CURRENT_USER_DISPLAY_NAME</strong><br />This will always be a (string). Empty if not logged in.</p>' . "\n";
421
  echo '<p>' . ws_plugin__s2member_highlight_php (file_get_contents (dirname (__FILE__) . "/code-samples/current-user-display-name.php")) . '</p>' . "\n";
422
  /**/
@@ -625,6 +649,14 @@ if (apply_filters ("ws_plugin__s2member_during_scripting_page_during_left_sectio
625
  /**/
626
  echo '<div class="ws-menu-page-hr"></div>' . "\n";
627
  /**/
 
 
 
 
 
 
 
 
628
  echo '<p><strong>S2MEMBER_CURRENT_USER_VALUE_FOR_PP_ON0</strong><br />This auto-fills the <code>on0</code> value in PayPal® Button Codes.<br />If a Button Code is presented to a logged-in Member, this will auto-fill the value for the <code>on0</code> input variable, with the string: <code>"Updating Subscr. ID"</code>. Otherwise, it will be an empty string.</p>' . "\n";
629
  echo '<p><strong>S2MEMBER_CURRENT_USER_VALUE_FOR_PP_OS0</strong><br />This auto-fills the <code>os0</code> value in PayPal® Button Codes.<br />If a Button Code is presented to a logged-in Member, this will auto-fill the value for the <code>os0</code> input variable, with the value of <code>S2MEMBER_CURRENT_USER_SUBSCR_ID</code>. Otherwise, it will be an empty string.</p>' . "\n";
630
  echo '<p>These two Constants are special. They are used by the PayPal® Button Generator for s2Member. This is how s2Member identifies an existing Member ( and/or a Free Subscriber ), who is already logged in when they click a PayPal® Modification Button that was generated for you by s2Member. Instead of forcing a Member ( and/or a Free Subscriber ) to re-register for a new account, s2Member can identify their existing account, and update it, according to the modified terms in your Button Code. These three Button Code parameters: <code>on0, os0, modify</code>, work together in harmony. If you\'re using the Shortcode Format for PayPal® Buttons ( recommended ), you won\'t even see these, because they\'re added internally by the Shortcode processor. Anyway, they\'re just documented here for clarity; you probably won\'t use these directly; the Button Code Generator pops them in.</p>' . "\n";
@@ -636,8 +668,6 @@ if (apply_filters ("ws_plugin__s2member_during_scripting_page_during_left_sectio
636
  echo '<p><em><strong>*Conditional Upgrades*</strong> You could also use the API Constant <code>S2MEMBER_CURRENT_USER_ACCESS_LEVEL</code> to build Conditionals that display a specific Modification Button, based on the Membership Level of the currently logged-in Member. This can help you maximize your marketing efforts. In other words, instead of just throwing a single Modification Button out there to everyone, get specific if you need to!</em></p>' . "\n";
637
  echo '<p>' . ws_plugin__s2member_highlight_php (file_get_contents (dirname (__FILE__) . "/code-samples/current-user-access-level-conditional-upgrades.php")) . '</p>' . "\n";
638
  /**/
639
- do_action ("ws_plugin__s2member_during_scripting_page_during_left_sections_during_list_of_api_constants", get_defined_vars ());
640
- /**/
641
  echo '</div>' . "\n";
642
  /**/
643
  echo '</div>' . "\n";
@@ -653,7 +683,7 @@ if (apply_filters ("ws_plugin__s2member_during_scripting_page_during_left_sectio
653
  /**/
654
  echo '<div class="ws-menu-page-section ws-plugin--s2member-api-js-globals-section">' . "\n";
655
  echo '<h3>You Also Have Access To JS Globals ( some JavaScript knowledge required )</h3>' . "\n";
656
- echo '<p>All of the PHP Constants, are also available through JavaScript, as Global Variables ( with the exact same names/types as their PHP counterparts ). s2Member automatically loads it\'s compressed JavaScript API ( only 2kbs ) into your theme for WordPress®. s2Member is very intelligent about the way it loads ( and maintains ) it\'s JavaScript API. You can rely on the JavaScript Globals, the same way you rely on PHP Constants.</p>' . "\n";
657
  do_action ("ws_plugin__s2member_during_scripting_page_during_left_sections_during_api_js_globals", get_defined_vars ());
658
  echo '</div>' . "\n";
659
  /**/
@@ -670,7 +700,7 @@ if (apply_filters ("ws_plugin__s2member_during_scripting_page_during_left_sectio
670
  /**/
671
  echo '<div class="ws-menu-page-section ws-plugin--s2member-api-hooks-section">' . "\n";
672
  echo '<h3>WP® Hooks For Theme/Plugin Developers ( scripting required )</h3>' . "\n";
673
- echo '<p>In addition to its API Constants, s2Member also makes several Hooks/Filters available throughout its framework. This makes it possible to build onto ( or even modify ) s2Member in lots of different ways. If you need to add custom processing routines, modify the behavior of existing processing routines, or tinker with things otherwise; you should use API Hooks/Filters. API Hooks &amp; Filters, give you the ability to "hook into", and/or "filter" processing routines, with files/functions of your own; instead of editing the s2Member plugin files directly. If you don\'t use a Hook/Filter, and instead, you edit the plugin files for s2Member, you\'ll have to merge all of your changes every time a new version of s2Member is released.</p>' . "\n";
674
  echo '<p>Un-documented. There are simply too many Hooks/Filters spread throughout s2Member\'s framework. Rather than documenting each Hook/Filter, it is easier to browse through the files inside: <code>/s2member/includes/functions/</code>. Inspecting Hooks/Filters in this way, also leads you to a better understanding of how they work. One way to save time, is to run a search for <code>do_action</code> and/or <code>apply_filters</code>.</p>' . "\n";
675
  do_action ("ws_plugin__s2member_during_scripting_page_during_left_sections_during_api_hooks", get_defined_vars ());
676
  echo '</div>' . "\n";
238
  /**/
239
  echo '<div class="ws-menu-page-section ws-plugin--s2member-custom-capabilities-section">' . "\n";
240
  echo '<h3>Packaging Together Custom Capabilities w/ Membership</h3>' . "\n";
241
+ echo '<p>Using one of s2Member\'s Payment Button and/or Form Generators, you can add Custom Capabilities in comma delimited format. s2Member builds upon existing functionality offered by WordPress® Roles/Capabilities. s2Member supports Free Subscribers ( at Level #0 ), and up to four Primary Roles ( i.e. s2Member Levels 1-4 ). Each s2Member Level provides <code>current_user_can("access_s2member_level0"), 1, 2, 3, 4</code>. These are the default Capabilities that come with each Membership Level. Now... If you\'d like to package together some variations of each Membership Level that you\'re selling, you can! All you do is add some Custom Capabilities whenever you create your Payment Button and/or Form Shortcode ( <em>there is a field in the Button &amp; Form Generators where you can enter Custom Capabilities</em> ). You can sell membership packages that come with Custom Capabilities, and even with custom prices.</p>' . "\n";
242
  echo '<p>Custom Capabilities are an extension to a feature that already exists in WordPress®. The <code>current_user_can()</code> function, can be used to test for these additional Capabilities that you allow. Whenever a Member completes the checkout process, after having purchased a Membership from you ( one that included Custom Capabilities ), s2Member will add those Custom Capabilities to the account for that specific Member.</p>' . "\n";
243
  echo '<p>Custom Capabilities are always prepended with <code>access_s2member_ccap_</code>. You fill in the last part, with ONLY lowercase alpha-numerics and/or underscores. For example, let\'s say you want to sell Membership Level #1, as is. But, you also want to sell a slight variation of Membership Level #1, that includes the ability to access the Music &amp; Video sections of your site. So, instead of selling this additional access under a whole new Membership Level, you could just sell a modified version of Membership Level #1. Add the the Custom Capabilities: <code>music,videos</code>. Once a Member has these Capabilities, you can test for these Capabilities using <code>current_user_can("access_s2member_ccap_music")</code> and <code>current_user_can("access_s2member_ccap_videos")</code>.</p>' . "\n";
244
  echo '<p>The important thing to realize, is that Custom Capabilities, are just that. They\'re custom. s2Member only deals with the default Capabilities that it uses. If you start using Custom Capabilities, you MUST use Simple or Advanced Conditionals ( <em>i.e. <code>current_user_can</code> logic</em> ) to test for them. Either in your theme files with PHP, or in Posts/Pages using Simple Conditionals ( powered by Shortcodes ).</p>' . "\n";
245
+ echo '<p><em class="ws-menu-page-hilite"><strong>*Tip*</strong> Starting with s2Member v3.2+, you can now tell s2Member to require certain Custom Capabilities on a per Post/Page basis. So now, s2Member ( if you prefer ) CAN handle Custom Capabilities for you automatically! Whenever you edit a Post/Page, you can tell s2Member ( i.e. there is a Meta Box for s2Member in your Post/Page editing station )... you can tell s2Member to require certain Custom Capabilities that you type in, using comma-delimited format. In other words, you will need to type in some of the trigger words that you used whenever you created your Payment Buttons/Forms. This way paying Members will have the Custom Capabilities to view different kinds of content that you offer.</em></p>' . "\n";
246
  do_action ("ws_plugin__s2member_during_scripting_page_during_left_sections_during_custom_capabilities", get_defined_vars ());
247
  /**/
248
  echo '<div class="ws-menu-page-hr"></div>' . "\n";
303
  /**/
304
  echo '<div class="ws-menu-page-section ws-plugin--s2member-api-advanced-dripping-section">' . "\n";
305
  echo '<h3>Dripping Content ( some PHP scripting required )</h3>' . "\n";
306
+ echo '<p>Content Dripping is the gradual, pre-scheduled release of premium website content to paying Members. This has become increasingly popular, because it allows older Members; those who have paid you more, due to recurring charges; to acquire access to more content progressively; based on their original paid registration time. It also gives you ( as the site owner ), the ability to launch multiple membership site portals, operating on autopilot, without any direct day-to-day involvement in a content release process. This requires some PHP scripting. In order to use PHP scripting inside your Posts/Pages, you\'ll need to install this handy plugin ( <a href="http://wordpress.org/extend/plugins/exec-php/" target="_blank" rel="external">Exec-PHP</a> ).</p>' . "\n";
307
  do_action ("ws_plugin__s2member_during_scripting_page_during_left_sections_during_api_advanced_dripping", get_defined_vars ());
308
+ /**/
309
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
310
+ /**/
311
+ echo '<p><strong>To drip content using <code>S2MEMBER_CURRENT_USER_PAID_REGISTRATION_DAYS</code>:</strong></p>' . "\n";
312
+ echo '<p>' . ws_plugin__s2member_highlight_php (file_get_contents (dirname (__FILE__) . "/code-samples/current-user-paid-registration-days-dripping.php")) . '</p>' . "\n";
313
+ /**/
314
+ echo '<p><em>There are more examples on this page, under the sub-section "s2Member PHP/API Constants". You\'ll see that s2Member provides you with access to several PHP/API Constants, which will assist you in dripping content. Some of the most relevant API Constants include: <code>S2MEMBER_CURRENT_USER_PAID_REGISTRATION_TIME</code>, <code>S2MEMBER_CURRENT_USER_PAID_REGISTRATION_DAYS</code>, <code>S2MEMBER_CURRENT_USER_REGISTRATION_TIME</code>, <code>S2MEMBER_CURRENT_USER_REGISTRATION_DAYS</code>; and there are many others.</em></p>' . "\n";
315
+ /**/
316
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
317
+ /**/
318
+ echo '<h3>Very Advanced Content Dripping ( some PHP required )</h3>' . "\n";
319
+ echo '<p>If you plan on dripping content in VERY advanced ways, you can tap into s2Member\'s recorded history of all Paid Registration Times. ( i.e. <code>' . esc_html ('<?php $time = s2member_paid_registration_time("level1"); ?>') . '</code> ) will give you a timestamp at which a Member first paid for Level#1 access. If they\'ve never paid for Level#1 access, the function will return 0. s2Member keeps a recorded history of timestamps associated with each Level that a Member gains access to, throughout the lifetime of their account. * NOTE: This requires s2Member v3.3+. Previous versions of s2Member did NOT record this information. If you implement this functionality on an upgraded installation of s2Member, please remember that s2Member will have NO Paid Registration Time for any Member you acquired prior to installing s2Member v3.3+. <em>Check the forums for work-arounds.</em></p>' . "\n";
320
+ echo '<p><strong>Here is the function documentation for PHP/WordPress® developers:</strong></p>' . "\n";
321
+ echo '<p>' . ws_plugin__s2member_highlight_php (file_get_contents (dirname (__FILE__) . "/code-samples/s2member-paid-registration-time.php")) . '</p>' . "\n";
322
+ echo '<p><strong>Here are some actual examples that should give you some ideas:</strong></p>' . "\n";
323
+ echo '<p>' . ws_plugin__s2member_highlight_php (file_get_contents (dirname (__FILE__) . "/code-samples/s2member-paid-registration-time-examples.php")) . '</p>' . "\n";
324
  echo '</div>' . "\n";
325
  /**/
326
  echo '</div>' . "\n";
421
  /**/
422
  echo '<div class="ws-menu-page-hr"></div>' . "\n";
423
  /**/
424
+ echo '<p><strong>S2MEMBER_CURRENT_USER_REGISTRATION_TIME</strong><br />This will always be an (int); in the form of a Unix timestamp. 0 if not logged in. This holds the recorded time at which the User originally registered their Username for access to your site; for free or otherwise. This is useful if you want to drip content over an extended period of time, based on how long someone has been registered (period); regardless of whether they are/were paying you. <strong>* Note:</strong> this is NOT the same as <code>S2MEMBER_CURRENT_USER_PAID_REGISTRATION_TIME</code>, which could be used as an alternative, depending on your intended usage.</p>' . "\n";
425
  echo '<p>' . ws_plugin__s2member_highlight_php (file_get_contents (dirname (__FILE__) . "/code-samples/current-user-registration-time.php")) . '</p>' . "\n";
426
  /**/
427
  echo '<div class="ws-menu-page-hr"></div>' . "\n";
428
  /**/
429
+ echo '<p><strong>S2MEMBER_CURRENT_USER_REGISTRATION_DAYS</strong><br />This will always be an (int). 0 if not logged in. This is the number of days that have passed since the User originally registered their Username for access to your site; for free or otherwise. This is useful if you want to drip content over an extended period of time, based on how long someone has been registered (period); regardless of whether they are/were paying you. <strong>* Note:</strong> this is NOT the same as <code>S2MEMBER_CURRENT_USER_PAID_REGISTRATION_DAYS</code>, which could be used as an alternative, depending on your intended usage.</p>' . "\n";
430
  echo '<p>' . ws_plugin__s2member_highlight_php (file_get_contents (dirname (__FILE__) . "/code-samples/current-user-registration-days.php")) . '</p>' . "\n";
431
  /**/
432
  echo '<div class="ws-menu-page-hr"></div>' . "\n";
433
  /**/
434
+ echo '<p><strong>S2MEMBER_CURRENT_USER_PAID_REGISTRATION_TIME</strong><br />This will always be an (int); in the form of a Unix timestamp. However, this will be 0 if they\'re not logged in; or if they\'ve never paid you at all <em>( e.g. if they\'re still a Free Subscriber )</em>. This holds the recorded time at which the Member originally registered their Username (or upgraded for) any type of "paid" access to your site. This value is preserved for the lifetime of their account, even if they upgrade, and even if they\'re demoted at some point. Once this value is recorded, it never changes under any circumstance. This is useful if you want to drip content over an extended period of time, based on how long someone has been a "paying" Member (period); regardless of their original or existing Membership Level. <strong>* Note:</strong> this is NOT the same as <code>S2MEMBER_CURRENT_USER_REGISTRATION_TIME</code>, which could be used as an alternative, depending on your intended usage.</p>' . "\n";
435
+ echo '<p>' . ws_plugin__s2member_highlight_php (file_get_contents (dirname (__FILE__) . "/code-samples/current-user-paid-registration-time.php")) . '</p>' . "\n";
436
+ /**/
437
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
438
+ /**/
439
+ echo '<p><strong>S2MEMBER_CURRENT_USER_PAID_REGISTRATION_DAYS</strong><br />This will always be an (int); in the form of a Unix timestamp. However, this will be 0 if they\'re not logged in; or if they\'ve never paid you at all <em>( e.g. if they\'re still a Free Subscriber )</em>. This is the number of days that have passed since the Member originally registered their Username (or upgraded for) any type of "paid" access to your site. The underlying timestamp behind this value is preserved for the lifetime of their account, even if they upgrade, and even if they\'re demoted at some point. Once the underlying timestamp behind this value is recorded, it never changes under any circumstance. This is useful if you want to drip content over an extended period of time, based on how long someone has been a "paying" Member (period); regardless of their original or existing Membership Level. <strong>* Note:</strong> this is NOT the same as <code>S2MEMBER_CURRENT_USER_REGISTRATION_DAYS</code>, which could be used as an alternative, depending on your intended usage.</p>' . "\n";
440
+ echo '<p>' . ws_plugin__s2member_highlight_php (file_get_contents (dirname (__FILE__) . "/code-samples/current-user-paid-registration-days.php")) . '</p>' . "\n";
441
+ /**/
442
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
443
+ /**/
444
  echo '<p><strong>S2MEMBER_CURRENT_USER_DISPLAY_NAME</strong><br />This will always be a (string). Empty if not logged in.</p>' . "\n";
445
  echo '<p>' . ws_plugin__s2member_highlight_php (file_get_contents (dirname (__FILE__) . "/code-samples/current-user-display-name.php")) . '</p>' . "\n";
446
  /**/
649
  /**/
650
  echo '<div class="ws-menu-page-hr"></div>' . "\n";
651
  /**/
652
+ echo '<p><strong>S2MEMBER_PAYPAL_PDT_IDENTITY_TOKEN</strong><br />This is the PDT Identity Token associated with your PayPal® Business.</p>' . "\n";
653
+ echo '<p>' . ws_plugin__s2member_highlight_php (file_get_contents (dirname (__FILE__) . "/code-samples/paypal-pdt-identity-token.php")) . '</p>' . "\n";
654
+ echo '<p><em>* For security purposes, this is NOT included in the JS/API (JavaSript API).</em></p>' . "\n";
655
+ /**/
656
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
657
+ /**/
658
+ do_action ("ws_plugin__s2member_during_scripting_page_during_left_sections_during_list_of_api_constants", get_defined_vars ());
659
+ /**/
660
  echo '<p><strong>S2MEMBER_CURRENT_USER_VALUE_FOR_PP_ON0</strong><br />This auto-fills the <code>on0</code> value in PayPal® Button Codes.<br />If a Button Code is presented to a logged-in Member, this will auto-fill the value for the <code>on0</code> input variable, with the string: <code>"Updating Subscr. ID"</code>. Otherwise, it will be an empty string.</p>' . "\n";
661
  echo '<p><strong>S2MEMBER_CURRENT_USER_VALUE_FOR_PP_OS0</strong><br />This auto-fills the <code>os0</code> value in PayPal® Button Codes.<br />If a Button Code is presented to a logged-in Member, this will auto-fill the value for the <code>os0</code> input variable, with the value of <code>S2MEMBER_CURRENT_USER_SUBSCR_ID</code>. Otherwise, it will be an empty string.</p>' . "\n";
662
  echo '<p>These two Constants are special. They are used by the PayPal® Button Generator for s2Member. This is how s2Member identifies an existing Member ( and/or a Free Subscriber ), who is already logged in when they click a PayPal® Modification Button that was generated for you by s2Member. Instead of forcing a Member ( and/or a Free Subscriber ) to re-register for a new account, s2Member can identify their existing account, and update it, according to the modified terms in your Button Code. These three Button Code parameters: <code>on0, os0, modify</code>, work together in harmony. If you\'re using the Shortcode Format for PayPal® Buttons ( recommended ), you won\'t even see these, because they\'re added internally by the Shortcode processor. Anyway, they\'re just documented here for clarity; you probably won\'t use these directly; the Button Code Generator pops them in.</p>' . "\n";
668
  echo '<p><em><strong>*Conditional Upgrades*</strong> You could also use the API Constant <code>S2MEMBER_CURRENT_USER_ACCESS_LEVEL</code> to build Conditionals that display a specific Modification Button, based on the Membership Level of the currently logged-in Member. This can help you maximize your marketing efforts. In other words, instead of just throwing a single Modification Button out there to everyone, get specific if you need to!</em></p>' . "\n";
669
  echo '<p>' . ws_plugin__s2member_highlight_php (file_get_contents (dirname (__FILE__) . "/code-samples/current-user-access-level-conditional-upgrades.php")) . '</p>' . "\n";
670
  /**/
 
 
671
  echo '</div>' . "\n";
672
  /**/
673
  echo '</div>' . "\n";
683
  /**/
684
  echo '<div class="ws-menu-page-section ws-plugin--s2member-api-js-globals-section">' . "\n";
685
  echo '<h3>You Also Have Access To JS Globals ( some JavaScript knowledge required )</h3>' . "\n";
686
+ echo '<p>Unless noted otherwise, all of the PHP Constants, are also available through JavaScript, as Global Variables ( with the exact same names/types as their PHP counterparts ). s2Member automatically loads it\'s compressed JavaScript API ( only 2kbs ) into your theme for WordPress®. s2Member is very intelligent about the way it loads ( and maintains ) it\'s JavaScript API. You can rely on the JavaScript Globals, the same way you rely on PHP Constants. The only exceptions are related to security. Variables that include private server-side details, like Identity Tokens and other API service credentials, will be excluded automatically.</p>' . "\n";
687
  do_action ("ws_plugin__s2member_during_scripting_page_during_left_sections_during_api_js_globals", get_defined_vars ());
688
  echo '</div>' . "\n";
689
  /**/
700
  /**/
701
  echo '<div class="ws-menu-page-section ws-plugin--s2member-api-hooks-section">' . "\n";
702
  echo '<h3>WP® Hooks For Theme/Plugin Developers ( scripting required )</h3>' . "\n";
703
+ echo '<p>In addition to its API Constants, s2Member also makes several Hooks/Filters available throughout its framework. This makes it possible to build onto ( or even modify ) s2Member in lots of different ways. If you need to add custom processing routines, modify the behavior of existing processing routines, or tinker with things otherwise; you should use API Hooks/Filters. API Hooks &amp; Filters, give you the ability to "hook into", and/or "filter" processing routines, with files/functions of your own; instead of editing the s2Member plugin files directly. If you don\'t use a Hook/Filter, and instead, you edit the plugin files for s2Member, you\'ll have to merge all of your changes every time a new version of s2Member is released. If you create custom processing routines, you could place those routines into a PHP file here: <code>/wp-content/mu-plugins/my-s2member-hacks.php</code>. If you don\'t have an /mu-plugins/ directory, please create one. These are (mu) MUST USE plugins, which are loaded into WordPress® automatically; that\'s what you want!</p>' . "\n";
704
  echo '<p>Un-documented. There are simply too many Hooks/Filters spread throughout s2Member\'s framework. Rather than documenting each Hook/Filter, it is easier to browse through the files inside: <code>/s2member/includes/functions/</code>. Inspecting Hooks/Filters in this way, also leads you to a better understanding of how they work. One way to save time, is to run a search for <code>do_action</code> and/or <code>apply_filters</code>.</p>' . "\n";
705
  do_action ("ws_plugin__s2member_during_scripting_page_during_left_sections_during_api_hooks", get_defined_vars ());
706
  echo '</div>' . "\n";
includes/menu-pages/start.inc.php CHANGED
@@ -12,7 +12,7 @@ If not, see: <http://www.gnu.org/licenses/>.
12
  Direct access denial.
13
  */
14
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
15
- exit("Do not access this file directly.");
16
  /*
17
  Flow Of Events page.
18
  */
@@ -113,7 +113,7 @@ if (apply_filters ("ws_plugin__s2member_during_start_page_during_left_sections_d
113
  echo '<div class="ws-menu-page-section ws-plugin--s2member-general-options-section">' . "\n";
114
  echo '<h3>Your s2Member -> General Options ( basic configuration )</h3>' . "\n";
115
  echo '<p>Once you have a Login Welcome Page, and a Membership Options Page. Go to: <code>s2Member -> General Options</code>.</p>' . "\n";
116
- echo '<p>From your s2Member General Options Panel, you may restrict access to certain Posts, Pages, Tags, Categories, and/or URIs based on a Member\'s Level. The s2Member Options Panel makes it easy for you. All you do is type in the basics of what you want to restrict access to, and those sections of your site will be off limits to non-Members.' . ((!is_multisite () || !ws_plugin__s2member_is_multisite_farm () || is_main_site ()) ? ' That being said, there are times when you might need to have greater control over which portions of your site can be viewed by non-Members, or Members at different Levels. This is where API Scripting with Conditionals comes in. <em>For more information, see: <code>s2Member -> API Scripting</code></em>.' : '') . '</p>' . "\n";
117
  do_action ("ws_plugin__s2member_during_start_page_during_left_sections_during_general_options", get_defined_vars ());
118
  echo '</div>' . "\n";
119
  /**/
@@ -132,7 +132,7 @@ if (apply_filters ("ws_plugin__s2member_during_start_page_during_left_sections_d
132
  echo '<h3>Subscription Cancellations / Expirations / Terminations</h3>' . "\n";
133
  echo '<p>You\'ll be happy to know that s2Member handles cancellations, expirations, failed payments, terminations ( e.g. refunds &amp; chargebacks ) for you automatically. If you log into your PayPal® account and cancel a Member\'s Subscription, or, if the Member logs into their PayPal® account and cancels their own Subscription, s2Member will be notified of these important changes and react accordingly through the PayPal® IPN service that runs silently behind-the-scene.</p>' . "\n";
134
  echo '<p>The PayPal® IPN service will notify s2Member whenever a Member\'s payments have been failing, and/or whenever a Member\'s Subscription has expired for any reason. Even refunds &amp; chargeback reversals are supported through the IPN service. If you issue a refund to an unhappy Customer through PayPal®, s2Member will be notified, and the account for that Customer will either be demoted to a Free Subscriber, or deleted automatically ( based on your configuration ). The communication from PayPal® -> s2Member is seamless.</p>' . "\n";
135
- echo '<p><em><strong>*Some Hairy Details*</strong> There might be times whenever you notice that a Members\'s Subscription has been cancelled through PayPal®... but, s2Member continues allowing the User access to your site as a paid Member. Please don\'t be confused by this... in 99.9% of these cases, the reason for this is legitimate. s2Member will only remove the User\'s membership privileges when PayPal® sends a <code>subscr_eot</code> notification via the IPN service, a refund occurs, a chargeback occurs, or when a cancellation occurs - which would later result in a delayed Auto-EOT by s2Member. s2Member will not process an EOT until the User has completely used up the time they paid for. In other words, if a User signs up for a monthly Subscription on Jan 1st, and then cancels their Subscription on Jan 15th; technically, they should still be allowed to access the site for another 15 days, and then on Feb 1st, the time they paid for has completely elapsed. At that time, s2Member will remove their membership privileges; by either demoting them to a Free Subscriber, or deleting their account from the system ( based on your configuration ). s2Member also calculates one extra day ( 24 hours ) into its equation, just to make sure access is not removed sooner than a Customer might expect.</em></p>' . "\n";
136
  do_action ("ws_plugin__s2member_during_start_page_during_left_sections_during_automation_process", get_defined_vars ());
137
  echo '</div>' . "\n";
138
  /**/
12
  Direct access denial.
13
  */
14
  if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
15
+ exit ("Do not access this file directly.");
16
  /*
17
  Flow Of Events page.
18
  */
113
  echo '<div class="ws-menu-page-section ws-plugin--s2member-general-options-section">' . "\n";
114
  echo '<h3>Your s2Member -> General Options ( basic configuration )</h3>' . "\n";
115
  echo '<p>Once you have a Login Welcome Page, and a Membership Options Page. Go to: <code>s2Member -> General Options</code>.</p>' . "\n";
116
+ echo '<p>From your s2Member General Options Panel, you may restrict access to certain Posts, Pages, Tags, Categories, and/or URIs based on a Member\'s Level. The s2Member Options Panel makes it easy for you. All you do is type in the basics of what you want to restrict access to, and those sections of your site will be off limits to non-Members.' . ( (!is_multisite () || !ws_plugin__s2member_is_multisite_farm () || is_main_site ()) ? ' That being said, there are times when you might need to have greater control over which portions of your site can be viewed by non-Members, or Members at different Levels. This is where API Scripting with Conditionals comes in. <em>For more information, see: <code>s2Member -> API Scripting</code></em>.' : '') . '</p>' . "\n";
117
  do_action ("ws_plugin__s2member_during_start_page_during_left_sections_during_general_options", get_defined_vars ());
118
  echo '</div>' . "\n";
119
  /**/
132
  echo '<h3>Subscription Cancellations / Expirations / Terminations</h3>' . "\n";
133
  echo '<p>You\'ll be happy to know that s2Member handles cancellations, expirations, failed payments, terminations ( e.g. refunds &amp; chargebacks ) for you automatically. If you log into your PayPal® account and cancel a Member\'s Subscription, or, if the Member logs into their PayPal® account and cancels their own Subscription, s2Member will be notified of these important changes and react accordingly through the PayPal® IPN service that runs silently behind-the-scene.</p>' . "\n";
134
  echo '<p>The PayPal® IPN service will notify s2Member whenever a Member\'s payments have been failing, and/or whenever a Member\'s Subscription has expired for any reason. Even refunds &amp; chargeback reversals are supported through the IPN service. If you issue a refund to an unhappy Customer through PayPal®, s2Member will be notified, and the account for that Customer will either be demoted to a Free Subscriber, or deleted automatically ( based on your configuration ). The communication from PayPal® -> s2Member is seamless.</p>' . "\n";
135
+ echo '<p><em><strong>*Some Hairy Details*</strong> There might be times whenever you notice that a Members\'s Subscription has been cancelled through PayPal®... but, s2Member continues allowing the User access to your site as a paid Member. Please don\'t be confused by this... in 99.9% of these cases, the reason for this is legitimate. s2Member will only remove the User\'s membership privileges when an EOT ( End Of Term ) is processed, a refund occurs, a chargeback occurs, or when a cancellation occurs - which would later result in a delayed Auto-EOT by s2Member. s2Member will not process an EOT until the User has completely used up the time they paid for. In other words, if a User signs up for a monthly Subscription on Jan 1st, and then cancels their Subscription on Jan 15th; technically, they should still be allowed to access the site for another 15 days, and then on Feb 1st, the time they paid for has completely elapsed. At that time, s2Member will remove their membership privileges; by either demoting them to a Free Subscriber, or deleting their account from the system ( based on your configuration ). s2Member also calculates one extra day ( 24 hours ) into its equation, just to make sure access is not removed sooner than a Customer might expect.</em></p>' . "\n";
136
  do_action ("ws_plugin__s2member_during_start_page_during_left_sections_during_automation_process", get_defined_vars ());
137
  echo '</div>' . "\n";
138
  /**/
includes/menu-pages/trk-ops.inc.php CHANGED
@@ -42,8 +42,8 @@ if (apply_filters ("ws_plugin__s2member_during_trk_ops_page_during_left_sections
42
  /**/
43
  echo '<div class="ws-menu-page-section ws-plugin--s2member-signup-tracking-section">' . "\n";
44
  echo '<h3>Membership Signup Tracking Codes ( optional )</h3>' . "\n";
45
- echo '<p>If you use affiliate software, a list server, tracking codes from advertising networks, or the like; you\'ll want to read this section. The HTML' . ((is_multisite () && ws_plugin__s2member_is_multisite_farm () && !is_main_site ()) ? '' : ' and/or PHP') . ' code that you enter below, will be loaded up in a web browser, after a Customer returns from a successful Signup through PayPal®. Tracking Codes are only displayed/processed one time for each Customer. s2Member will display your Tracking Codes in one of three possible locations... <strong>1.</strong> If possible, on the Registration Form, after returning from PayPal®. <strong>2.</strong> Otherwise, if possible, on the Login Form after Registration is completed. <strong>3.</strong> Otherwise, in the footer of your WordPress® theme, after the Customer\'s very first Login.</p>' . "\n";
46
- echo '<p>Signup Tracking Codes are displayed for all types of Membership Level Access. Including: Recurring Subscriptions ( with or without a free trial period ), Non-Recurring Subscriptions ( with or without a free trial period ), Lifetime Subscriptions, and even Fixed-Term Subscriptions. All of these are supported by s2Member\'s Button/Form Generators, and all of these are supported here.</p>' . "\n";
47
  do_action ("ws_plugin__s2member_during_trk_ops_page_during_left_sections_during_signup_tracking", get_defined_vars ());
48
  /**/
49
  echo '<table class="form-table">' . "\n";
@@ -61,21 +61,21 @@ if (apply_filters ("ws_plugin__s2member_during_trk_ops_page_during_left_sections
61
  /**/
62
  echo '<td>' . "\n";
63
  echo '<textarea name="ws_plugin__s2member_signup_tracking_codes" id="ws-plugin--s2member-signup-tracking-codes" rows="8" wrap="off" spellcheck="false" style="font-family:Consolas, monospace;">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["signup_tracking_codes"]) . '</textarea><br />' . "\n";
64
- echo 'Any valid XHTML / JavaScript' . ((is_multisite () && ws_plugin__s2member_is_multisite_farm () && !is_main_site ()) ? '' : ' ( or even PHP )') . ' code will work just fine here. Just try not to put anything here that would actually be visible to the Customer. Things like 1x1 pixel images that load up silently and/or JavaScript tracking routines will be fine. Google® Analytics code works just fine, AdSense® performance tracking, as well as Yahoo® tracking and other affiliate network codes are all OK here.<br /><br />' . "\n";
65
  echo '<strong>You can also use these special Replacement Codes if you need them:</strong>' . "\n";
66
  echo '<ul>' . "\n";
67
- echo '<li><code>%%subscr_id%%</code> = The PayPal® Subscription ID, which remains constant throughout any &amp; all future payments. [ <a href="#" onclick="alert(\'There is one exception. If you are selling Lifetime or Fixed-Term ( non-recurring ) access, using Buy Now functionality; the %%subscr_id%% is actually set to the Transaction ID for the purchase.\\n\\nPayPal® does not provide a specific Subscription ID for Buy Now purchases. Since Lifetime &amp; Fixed-Term Subscriptions are NOT recurring ( i.e. there is only ONE payment ), using the Transaction ID as the Subscription ID is a graceful way to deal with this minor conflict.\'); return false;">?</a> ]</li>' . "\n";
68
- echo '<li><code>%%initial%%</code> = The Initial Fee charged during signup. If you offered a free trial, this will be <code>0</code>. [ <a href="#" onclick="alert(\'This will always represent the amount of money the Customer spent, whenever they initially signed up, no matter what. If a Customer signs up, under the terms of a free trial period, this will be 0.\'); return false;">?</a> ]</li>' . "\n";
69
- echo '<li><code>%%regular%%</code> = The Regular Amount of the Subscription. This value is <code>always > 0</code>, no matter what. [ <a href="#" onclick="alert(\'This is how much the Subscription costs after an initial period expires. The %%regular%% rate is always > 0. If you did not offer an initial period, %%initial%% and %%regular%% will be equal to the same thing.\'); return false;">?</a> ]</li>' . "\n";
70
- echo '<li><code>%%recurring%%</code> = This is the amount that will be charged on a Recurring basis, or <code>0</code> if non-Recurring. [ <a href="#" onclick="alert(\'If recurring payments have not been required, this will be equal to 0. That being said, %%regular%% &amp; %%recurring%% are usually the same value. This variable can be used in two different ways. You can use it to determine what the regular recurring rate is, or to determine whether the Subscription will recur or not. If it is going to recur, %%recurring%% will be > 0.\'); return false;">?</a> ]</li>' . "\n";
71
  echo '<li><code>%%first_name%%</code> = The First Name of the Customer who purchased the Membership Subscription.</li>' . "\n";
72
  echo '<li><code>%%last_name%%</code> = The Last Name of the Customer who purchased the Membership Subscription.</li>' . "\n";
73
  echo '<li><code>%%full_name%%</code> = The Full Name ( First &amp; Last ) of the Customer who purchased the Membership Subscription.</li>' . "\n";
74
  echo '<li><code>%%payer_email%%</code> = The Email Address of the Customer who purchased the Membership Subscription.</li>' . "\n";
75
  echo '<li><code>%%item_number%%</code> = The Item Number ( colon separated <code><em>level:custom_capabilities:fixed term</em></code> ) that the Subscription is for.</li>' . "\n";
76
  echo '<li><code>%%item_name%%</code> = The Item Name ( as provided by the <code>desc=""</code> attribute in your Shortcode, which briefly describes the Item Number ).</li>' . "\n";
77
- echo '<li><code>%%initial_term%%</code> = This is the term length of the initial period. This will be a numeric value, followed by a space, then a single letter. [ <a href="#" onclick="alert(\'Here are some examples:\\n\\n%%initial_term%% = 1 D ( this means 1 Day )\\n%%initial_term%% = 1 W ( this means 1 Week )\\n%%initial_term%% = 1 M ( this means 1 Month )\\n%%initial_term%% = 1 Y ( this means 1 Year )\\n\\nThe initial period never recurs, so this only lasts for the term length specified, then it is over. If no initial period was even offered, the value of %%initial_term%% will just be: 0 D, meaning zero days.\'); return false;">?</a> ]</li>' . "\n";
78
- echo '<li><code>%%regular_term%%</code> = This is the term length of the regular period. This will be a numeric value, followed by a space, then a single letter. [ <a href="#" onclick="alert(\'Here are some examples:\\n\\n%%regular_term%% = 1 D ( this means 1 Day )\\n%%regular_term%% = 1 W ( this means 1 Week )\\n%%regular_term%% = 1 M ( this means 1 Month )\\n%%regular_term%% = 1 Y ( this means 1 Year )\\n%%regular_term%% = 1 L ( this means 1 Lifetime )\\n\\nThe regular term is usually recurring. So the regular term value represents the period ( or duration ) of each recurring period. If %%recurring%% = 0, then the regular term only applies once, because it is not recurring. So if it is not recurring, the value of %%regular_term%% simply represents how long their membership privileges are going to last after the %%initial_term%% has expired, if there was an initial term. The value of this variable ( %%regular_term%% ) will never be empty, it will always be at least: 1 D, meaning 1 day. No exceptions.\'); return false;">?</a> ]</li>' . "\n";
79
  echo '</ul>' . "\n";
80
  /**/
81
  if (!is_multisite () || !ws_plugin__s2member_is_multisite_farm () || is_main_site ())
@@ -110,7 +110,7 @@ if (apply_filters ("ws_plugin__s2member_during_trk_ops_page_during_left_sections
110
  /**/
111
  echo '<div class="ws-menu-page-section ws-plugin--s2member-sp-tracking-section">' . "\n";
112
  echo '<h3>Tracking Codes For Specific Post/Page Access ( optional )</h3>' . "\n";
113
- echo '<p>If you use affiliate software, a list server, tracking codes from advertising networks, or the like; you\'ll want to read this section. The HTML' . ((is_multisite () && ws_plugin__s2member_is_multisite_farm () && !is_main_site ()) ? '' : ' and/or PHP') . ' code that you enter below, will be loaded up in a web browser, after a Customer returns from a successful transaction at PayPal®; specifically for Post/Page Access. These Codes are NOT injected for any type of Member Level Access. These are only for Specific Post/Page transactions. The Tracking Codes that you enter below, will be displayed in the footer section of your WordPress® theme, after a Customer returns from PayPal®.</p>' . "\n";
114
  do_action ("ws_plugin__s2member_during_trk_ops_page_during_left_sections_during_sp_tracking", get_defined_vars ());
115
  /**/
116
  echo '<table class="form-table">' . "\n";
@@ -128,10 +128,10 @@ if (apply_filters ("ws_plugin__s2member_during_trk_ops_page_during_left_sections
128
  /**/
129
  echo '<td>' . "\n";
130
  echo '<textarea name="ws_plugin__s2member_sp_tracking_codes" id="ws-plugin--s2member-sp-tracking-codes" rows="8" wrap="off" spellcheck="false" style="font-family:Consolas, monospace;">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sp_tracking_codes"]) . '</textarea><br />' . "\n";
131
- echo 'Any valid XHTML / JavaScript' . ((is_multisite () && ws_plugin__s2member_is_multisite_farm () && !is_main_site ()) ? '' : ' ( or even PHP )') . ' code will work just fine here. Just try not to put anything here that would actually be visible to the Customer. Things like 1x1 pixel images that load up silently and/or JavaScript tracking routines will be fine. Google® Analytics code works just fine, AdSense® performance tracking, as well as Yahoo® tracking and other affiliate network codes are all OK here.<br /><br />' . "\n";
132
  echo '<strong>You can also use these special Replacement Codes if you need them:</strong>' . "\n";
133
  echo '<ul>' . "\n";
134
- echo '<li><code>%%txn_id%%</code> = The PayPal® Transaction ID. PayPal® assigns a unique identifier for every purchase.</li>' . "\n";
135
  echo '<li><code>%%amount%%</code> = The full Amount that you charged for Specific Post/Page Access. This value will <code>always be > 0</code>.</li>' . "\n";
136
  echo '<li><code>%%first_name%%</code> = The First Name of the Customer who purchased Specific Post/Page Access.</li>' . "\n";
137
  echo '<li><code>%%last_name%%</code> = The Last Name of the Customer who purchased Specific Post/Page Access.</li>' . "\n";
@@ -225,7 +225,7 @@ if (apply_filters ("ws_plugin__s2member_during_trk_ops_page_during_left_sections
225
  /**/
226
  echo '<div class="ws-menu-page-section ws-plugin--s2member-other-methods-section">' . "\n";
227
  echo '<h3>Other Tracking Methods Are Available ( there\'s always a way )</h3>' . "\n";
228
- echo '<p>Check the s2Member API Notifications panel. You\'ll find additional layers of automation available through the use of the `Signup`, `Registration`, `Payment`, `EOT/Deletion`, `Refund/Reversal`, and `Specific Post/Page` Notifications that are available to you through the s2Member API. The s2Member API Notifications make it possible to integrate with 3rd party applications; like list servers, affiliate programs, and other back-office routines; in more advanced ways. Since the s2Member API Notifications operate silently on the back-end, in conjunction with the PayPal® IPN system, they tend to be more reliable and also more versatile. That being said, nothing replaces the simplicity of Tracking Codes. The more advanced API Notifications are NOT always the best tool for the job. For instance, API Notifications will NOT work with Google® Analytics, or 1 pixel &lt;img&gt; tags. They operate silently behind-the-scene, using HTTP connections, as opposed to being loaded in a browser.</p>' . "\n";
229
  do_action ("ws_plugin__s2member_during_trk_ops_page_during_left_sections_during_other_methods", get_defined_vars ());
230
  echo '</div>' . "\n";
231
  /**/
42
  /**/
43
  echo '<div class="ws-menu-page-section ws-plugin--s2member-signup-tracking-section">' . "\n";
44
  echo '<h3>Membership Signup Tracking Codes ( optional )</h3>' . "\n";
45
+ echo '<p>If you use affiliate software, a list server, tracking codes from advertising networks, or the like; you\'ll want to read this section. The HTML' . ( (is_multisite () && ws_plugin__s2member_is_multisite_farm () && !is_main_site ()) ? '' : ' and/or PHP') . ' code that you enter below, will be loaded up in a web browser, after a Customer completes Signup through your Payment Gateway. Tracking Codes are only displayed/processed one time for each Customer. s2Member will display your Tracking Codes in one of three possible locations... <strong>1.</strong> If possible, on the Registration Form, after returning from your Payment Gateway. <strong>2.</strong> Otherwise, if possible, on the Login Form after Registration is completed. <strong>3.</strong> Otherwise, in the footer of your WordPress® theme, as soon as possible; or after the Customer\'s very first login.</p>' . "\n";
46
+ echo '<p>Signup Tracking Codes are displayed for all types of Membership Level Access. Including: Recurring Subscriptions ( with or without a Free Trial Period ), Non-Recurring Subscriptions ( with or without a Free Trial Period ), Lifetime Subscriptions, and even Fixed-Term Subscriptions. All of these are supported by s2Member\'s Button/Form Generators, and all of these are supported here.</p>' . "\n";
47
  do_action ("ws_plugin__s2member_during_trk_ops_page_during_left_sections_during_signup_tracking", get_defined_vars ());
48
  /**/
49
  echo '<table class="form-table">' . "\n";
61
  /**/
62
  echo '<td>' . "\n";
63
  echo '<textarea name="ws_plugin__s2member_signup_tracking_codes" id="ws-plugin--s2member-signup-tracking-codes" rows="8" wrap="off" spellcheck="false" style="font-family:Consolas, monospace;">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["signup_tracking_codes"]) . '</textarea><br />' . "\n";
64
+ echo 'Any valid XHTML / JavaScript' . ( (is_multisite () && ws_plugin__s2member_is_multisite_farm () && !is_main_site ()) ? '' : ' ( or even PHP )') . ' code will work just fine here. Just try not to put anything here that would actually be visible to the Customer. Things like 1x1 pixel images that load up silently and/or JavaScript tracking routines will be fine. Google® Analytics code works just fine, AdSense® performance tracking, as well as Yahoo® tracking and other affiliate network codes are all OK here.<br /><br />' . "\n";
65
  echo '<strong>You can also use these special Replacement Codes if you need them:</strong>' . "\n";
66
  echo '<ul>' . "\n";
67
+ echo '<li><code>%%subscr_id%%</code> = The Paid Subscription ID, which remains constant throughout any &amp; all future payments. [ <a href="#" onclick="alert(\'There is one exception. If you are selling Lifetime or Fixed-Term ( non-recurring ) access, using Buy Now functionality; the %%subscr_id%% is actually set to the Transaction ID for the purchase.\\n\\nPayment Gateways do not provide a specific Subscription ID for Buy Now purchases. Since Lifetime &amp; Fixed-Term Subscriptions are NOT recurring ( i.e. there is only ONE payment ), using the Transaction ID as the Subscription ID is a graceful way to deal with this minor conflict.\'); return false;">?</a> ]</li>' . "\n";
68
+ echo '<li><code>%%initial%%</code> = The Initial Fee charged during signup. If you offered a 100% Free Trial Period, this will be <code>0</code>. [ <a href="#" onclick="alert(\'This will always represent the amount of money the Customer spent, whenever they initially signed up, no matter what. If a Customer signs up, under the terms of a 100% Free Trial Period, this will be 0.\'); return false;">?</a> ]</li>' . "\n";
69
+ echo '<li><code>%%regular%%</code> = The Regular Amount of the Subscription. This value is <code>always > 0</code>, no matter what. [ <a href="#" onclick="alert(\'This is how much the Subscription costs after an Initial Period expires. The %%regular%% rate is always > 0. If you did NOT offer an Initial Period at a different price, %%initial%% and %%regular%% will be equal to the same thing.\'); return false;">?</a> ]</li>' . "\n";
70
+ echo '<li><code>%%recurring%%</code> = This is the amount that will be charged on a recurring basis, or <code>0</code> if non-recurring. [ <a href="#" onclick="alert(\'If Recurring Payments have not been required, this will be equal to 0. That being said, %%regular%% &amp; %%recurring%% are usually the same value. This variable can be used in two different ways. You can use it to determine what the Regular Recurring Rate is, or to determine whether the Subscription will recur or not. If it is going to recur, %%recurring%% will be > 0.\'); return false;">?</a> ]</li>' . "\n";
71
  echo '<li><code>%%first_name%%</code> = The First Name of the Customer who purchased the Membership Subscription.</li>' . "\n";
72
  echo '<li><code>%%last_name%%</code> = The Last Name of the Customer who purchased the Membership Subscription.</li>' . "\n";
73
  echo '<li><code>%%full_name%%</code> = The Full Name ( First &amp; Last ) of the Customer who purchased the Membership Subscription.</li>' . "\n";
74
  echo '<li><code>%%payer_email%%</code> = The Email Address of the Customer who purchased the Membership Subscription.</li>' . "\n";
75
  echo '<li><code>%%item_number%%</code> = The Item Number ( colon separated <code><em>level:custom_capabilities:fixed term</em></code> ) that the Subscription is for.</li>' . "\n";
76
  echo '<li><code>%%item_name%%</code> = The Item Name ( as provided by the <code>desc=""</code> attribute in your Shortcode, which briefly describes the Item Number ).</li>' . "\n";
77
+ echo '<li><code>%%initial_term%%</code> = This is the term length of the Initial Period. This will be a numeric value, followed by a space, then a single letter. [ <a href="#" onclick="alert(\'Here are some examples:\\n\\n%%initial_term%% = 1 D ( this means 1 Day )\\n%%initial_term%% = 1 W ( this means 1 Week )\\n%%initial_term%% = 1 M ( this means 1 Month )\\n%%initial_term%% = 1 Y ( this means 1 Year )\\n\\nThe Initial Period never recurs, so this only lasts for the term length specified, then it is over.\'); return false;">?</a> ]</li>' . "\n";
78
+ echo '<li><code>%%regular_term%%</code> = This is the term length of the Regular Period. This will be a numeric value, followed by a space, then a single letter. [ <a href="#" onclick="alert(\'Here are some examples:\\n\\n%%regular_term%% = 1 D ( this means 1 Day )\\n%%regular_term%% = 1 W ( this means 1 Week )\\n%%regular_term%% = 1 M ( this means 1 Month )\\n%%regular_term%% = 1 Y ( this means 1 Year )\\n%%regular_term%% = 1 L ( this means 1 Lifetime )\\n\\nThe Regular Term is usually recurring. So the Regular Term value represents the period ( or duration ) of each recurring period. If %%recurring%% = 0, then the Regular Term only applies once, because it is not recurring. So if it is not recurring, the value of %%regular_term%% simply represents how long their membership privileges are going to last after the %%initial_term%% has expired, if there was an Initial Term. The value of this variable ( %%regular_term%% ) will never be empty, it will always be at least: 1 D, meaning 1 day. No exceptions.\'); return false;">?</a> ]</li>' . "\n";
79
  echo '</ul>' . "\n";
80
  /**/
81
  if (!is_multisite () || !ws_plugin__s2member_is_multisite_farm () || is_main_site ())
110
  /**/
111
  echo '<div class="ws-menu-page-section ws-plugin--s2member-sp-tracking-section">' . "\n";
112
  echo '<h3>Tracking Codes For Specific Post/Page Access ( optional )</h3>' . "\n";
113
+ echo '<p>If you use affiliate software, a list server, tracking codes from advertising networks, or the like; you\'ll want to read this section. The HTML' . ( (is_multisite () && ws_plugin__s2member_is_multisite_farm () && !is_main_site ()) ? '' : ' and/or PHP') . ' code that you enter below, will be loaded up in a web browser, after a Customer completes a successful transaction through your Payment Gateway; specifically for Post/Page Access. These Codes are NOT injected for any type of Member Level Access. These are only for Specific Post/Page transactions. The Tracking Codes that you enter below, will be displayed in the footer section of your WordPress® theme, after a Customer completes checkout.</p>' . "\n";
114
  do_action ("ws_plugin__s2member_during_trk_ops_page_during_left_sections_during_sp_tracking", get_defined_vars ());
115
  /**/
116
  echo '<table class="form-table">' . "\n";
128
  /**/
129
  echo '<td>' . "\n";
130
  echo '<textarea name="ws_plugin__s2member_sp_tracking_codes" id="ws-plugin--s2member-sp-tracking-codes" rows="8" wrap="off" spellcheck="false" style="font-family:Consolas, monospace;">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sp_tracking_codes"]) . '</textarea><br />' . "\n";
131
+ echo 'Any valid XHTML / JavaScript' . ( (is_multisite () && ws_plugin__s2member_is_multisite_farm () && !is_main_site ()) ? '' : ' ( or even PHP )') . ' code will work just fine here. Just try not to put anything here that would actually be visible to the Customer. Things like 1x1 pixel images that load up silently and/or JavaScript tracking routines will be fine. Google® Analytics code works just fine, AdSense® performance tracking, as well as Yahoo® tracking and other affiliate network codes are all OK here.<br /><br />' . "\n";
132
  echo '<strong>You can also use these special Replacement Codes if you need them:</strong>' . "\n";
133
  echo '<ul>' . "\n";
134
+ echo '<li><code>%%txn_id%%</code> = The Paid Transaction ID. Payment Gateways assign a unique identifier for every purchase.</li>' . "\n";
135
  echo '<li><code>%%amount%%</code> = The full Amount that you charged for Specific Post/Page Access. This value will <code>always be > 0</code>.</li>' . "\n";
136
  echo '<li><code>%%first_name%%</code> = The First Name of the Customer who purchased Specific Post/Page Access.</li>' . "\n";
137
  echo '<li><code>%%last_name%%</code> = The Last Name of the Customer who purchased Specific Post/Page Access.</li>' . "\n";
225
  /**/
226
  echo '<div class="ws-menu-page-section ws-plugin--s2member-other-methods-section">' . "\n";
227
  echo '<h3>Other Tracking Methods Are Available ( there\'s always a way )</h3>' . "\n";
228
+ echo '<p>Check the s2Member API Notifications panel. You\'ll find additional layers of automation available through the use of the `Signup`, `Registration`, `Payment`, `EOT/Deletion`, `Refund/Reversal`, and `Specific Post/Page` Notifications that are available to you through the s2Member API. The s2Member API Notifications make it possible to integrate with 3rd party applications; like list servers, affiliate programs, and other back-office routines; in more advanced ways. Since s2Member API Notifications operate silently on the back-end, they tend to be more reliable and also more versatile. That being said, nothing replaces the simplicity of Tracking Codes. The more advanced API Notifications are NOT always the best tool for the job. For instance, API Notifications will NOT work with Google® Analytics, or 1 pixel &lt;img&gt; tags. They operate silently behind-the-scene, using HTTP connections, as opposed to being loaded in a browser.</p>' . "\n";
229
  do_action ("ws_plugin__s2member_during_trk_ops_page_during_left_sections_during_other_methods", get_defined_vars ());
230
  echo '</div>' . "\n";
231
  /**/
includes/s2member-min.js CHANGED
@@ -1 +1 @@
1
- jQuery(document).ready(function(a){ws_plugin__s2member_uniqueFilesDownloaded=[];if(S2MEMBER_CURRENT_USER_IS_LOGGED_IN&&S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY<S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED){a("a[href*=s2member_file_download]").click(function(){if(!this.href.match(/file_download_key\=(.+)/)){var b="** Please Confirm This File Download **\n\n";b+="You've downloaded "+S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY+" protected file"+((S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY<1||S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY>1)?"s":"")+" in the last "+S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS+" days.\n\n";b+="You're entitled to "+((S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_IS_UNLIMITED)?"UNLIMITED downloads though ( so, no worries ).":S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED+" unique downloads every "+S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS+" day period.");if(confirm(b)){if(a.inArray(this.href,ws_plugin__s2member_uniqueFilesDownloaded)===-1){ws_plugin__s2member_uniqueFilesDownloaded.push(this.href),S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY++}return true}else{return false}}})}if(location.href.match(/\/wp-signup\.php/)){a("div#content > div.mu_register > form#setupform").submit(function(){var d=this,c="",b="",e="";a("input#user_name, input#user_email, input#blogname, input#blog_title",d).each(function(){if((c=a.trim(a(this).prev("label").text().replace(/[\r\n\t]+/g," ")))){if(b=ws_plugin__s2member_validationErrors(c,this,d,true)){e+=b+"\n\n"}}else{if((c=a.trim(a(this).prev("span.prefix_address").prev("label").text().replace(/[\r\n\t]+/g," ")))){if(b=ws_plugin__s2member_validationErrors(c,this,d,true)){e+=b+"\n\n"}}}});a(":input",d).each(function(){if((c=a.trim(a(this).prev("label").text().replace(/[\r\n\t]+/g," ")))){if(b=ws_plugin__s2member_validationErrors(c,this,d)){e+=b+"\n\n"}}});if(e=a.trim(e)){alert("Oops, you missed something:\n\n"+e);return false}return true})}else{if(location.href.match(/\/wp-login\.php/)){a("div#login > form#registerform").submit(function(){var d=this,c="",b="",e="";a("input#user_login, input#user_email",d).each(function(){if((c=a.trim(a(this).parent("label").text().replace(/[\r\n\t]+/g," ")))){if(b=ws_plugin__s2member_validationErrors(c,this,d,true)){e+=b+"\n\n"}}});a(":input",d).each(function(){if((c=a.trim(a(this).parent("label").children("span").slice(0,1).text().replace(/[\r\n\t]+/g," ")))){if(b=ws_plugin__s2member_validationErrors(c,this,d)){e+=b+"\n\n"}}});if(e=a.trim(e)){alert("Oops, you missed something:\n\n"+e);return false}return true})}else{if(location.href.match(/\/\?s2member_profile\=1/)){a("form#ws-plugin--s2member-profile").submit(function(){var e=this,d="",c="",g="";var b=a("input#ws-plugin--s2member-profile-password");var f=a("input#ws-plugin--s2member-profile-password-confirmation");a(":input",e).each(function(){if((d=a.trim(a(this).parent("label").children("strong").slice(0,1).text().replace(/[\r\n\t]+/g," ")))){if(c=ws_plugin__s2member_validationErrors(d,this,e)){g+=c+"\n\n"}}});if(g=a.trim(g)){alert("Oops, you missed something:\n\n"+g);return false}else{if(a.trim(b.val())&&a.trim(b.val())!==a.trim(f.val())){alert("Oops, you missed something:\n\nPasswords do not match up. Please try again.");return false}}return true})}else{if(location.href.match(/\/wp-admin\/profile\.php/)){a("form#your-profile").submit(function(){var d=this,c="",b="",e="";a(':input[id^="ws-plugin--s2member-profile-"]',d).each(function(){if((c=a.trim(a(this).parent("td").prev("th").children("label").slice(0,1).text().replace(/[\r\n\t]+/g," ")))){if(b=ws_plugin__s2member_validationErrors(c,this,d)){e+=b+"\n\n"}}});if(e=a.trim(e)){alert("Oops, you missed something:\n\n"+e);return false}return true})}}}}ws_plugin__s2member_validationErrors=function(l,k,c,g,f){if(typeof l==="string"&&l&&typeof k==="object"&&typeof c==="object"){if(typeof k.tagName==="string"&&k.tagName.match(/^(input|textarea|select)$/i)){var n=k.tagName.toLowerCase(),j=a(k),i=String(j.attr("type")).toLowerCase(),b=String(j.attr("name")),m=j.val();var g=(typeof g==="boolean")?g:(j.attr("aria-required")==="true"),f=(typeof f==="string")?f:j.attr("data-expected");if(n==="input"&&i==="checkbox"&&b.match(/\[\]$/)){if(typeof k.id==="string"&&k.id.match(/-0$/)){if(g&&!a('input[name="'+b.replace(/([\[\]])/g,"$1")+'"]:checked',c).length){return l+"\nPlease check at least one of the boxes."}}}else{if(n==="input"&&i==="checkbox"){if(g&&!k.checked){return l+"\nRequired. This box must be checked."}}else{if(n==="input"&&i==="radio"){if(typeof k.id==="string"&&k.id.match(/-0$/)){if(g&&!a('input[name="'+b.replace(/([\[\]])/g,"$1")+'"]:checked',c).length){return l+"\nPlease select one of the options."}}}else{if(n==="select"&&j.attr("multiple")){if(g&&(!(m instanceof Array)||!m.length)){return l+"\nPlease select at least one of the options."}}else{if(typeof m!=="string"||(g&&!(m=a.trim(m)).length)){return l+"\nThis is a required field, please try again."}else{if(((n==="input"&&i.match(/^(text|password)$/i))||n==="textarea")&&typeof f==="string"&&f.length){if(f==="numeric-wp-commas"&&(!m.match(/^[0-9\.,]+$/)||isNaN(m.replace(/,/g,"")))){return l+"\nMust be numeric ( with or without decimals, commas allowed )."}else{if(f==="numeric"&&(!m.match(/^[0-9\.]+$/)||isNaN(m))){return l+"\nMust be numeric ( with or without decimals, no commas )."}else{if(f==="integer"&&(!m.match(/^[0-9]+$/)||isNaN(m))){return l+"\nMust be an integer ( a whole number, without any decimals )."}else{if(f==="integer-gt-0"&&(!m.match(/^[0-9]+$/)||isNaN(m)||m<=0)){return l+"\nMust be an integer > 0 ( whole number, no decimals, greater than 0 )."}else{if(f==="float"&&(!m.match(/^[0-9\.]+$/)||!m.match(/[0-9]/)||!m.match(/\./)||isNaN(m))){return l+"\nMust be a float ( floating point number, decimals required )."}else{if(f==="float-gt-0"&&(!m.match(/^[0-9\.]+$/)||!m.match(/[0-9]/)||!m.match(/\./)||isNaN(m)||m<=0)){return l+"\nMust be a float > 0 ( floating point number, decimals required, greater than 0 )."}else{if(f==="date"&&!m.match(/^[0-9]{2}\/[0-9]{2}\/[0-9]{4}$/)){return l+"\nMust be a date ( required date format: dd/mm/yyyy )."}else{if(f==="email"&&!m.match(/^([a-z_~0-9\+\-]+)(((\.?)([a-z_~0-9\+\-]+))*)(@)([a-z0-9]+)(((-*)([a-z0-9]+))*)(((\.)([a-z0-9]+)(((-*)([a-z0-9]+))*))*)(\.)([a-z]{2,6})$/i)){return l+"\nMust be a valid email address."}else{if(f==="url"&&!m.match(/^http(s?)\:\/\/(.{5,})$/i)){return l+"\nMust be a full URL ( starting with http or https )."}else{if(f==="domain"&&!m.match(/^([a-z0-9]+)(((-*)([a-z0-9]+))*)(((\.)([a-z0-9]+)(((-*)([a-z0-9]+))*))*)(\.)([a-z]{2,6})$/i)){return l+"\nMust be a domain name ( domain name only, without http )."}else{if(f==="phone"&&(!m.match(/^[0-9 \(\)\-]+$/)||m.replace(/[^0-9]/g,"").length!==10)){return l+"\nMust be a phone # ( 10 digits w/possible hyphens,spaces,brackets )."}else{if(f==="uszip"&&!m.match(/^[0-9]{5}(-[0-9]{4})?$/)){return l+"\nMust be a US zipcode ( 5-9 digits w/possible hyphen )."}else{if(f==="cazip"&&!m.match(/^[0-9A-Z]{3}( ?)[0-9A-Z]{3}$/i)){return l+"\nMust be a Canadian zipcode ( 6 alpha-numerics w/possible space )."}else{if(f==="uczip"&&!m.match(/^[0-9]{5}(-[0-9]{4})?$/)&&!m.match(/^[0-9A-Z]{3}( ?)[0-9A-Z]{3}$/i)){return l+"\nMust be a zipcode ( either a US or Canadian zipcode )."}else{if(f.match(/^alphanumerics-spaces-punctuation-([0-9]+)(-e)?$/)&&!m.match(/^[a-z 0-9,\.\/\?\:;"'\{\}\[\]\|\\\+\=_\-\(\)\*&\^%\$#@\!`~]+$/i)){return l+"\nPlease use alphanumerics, spaces & punctuation only."}else{if(f.match(/^alphanumerics-spaces-([0-9]+)(-e)?$/)&&!m.match(/^[a-z 0-9]+$/i)){return l+"\nPlease use alphanumerics & spaces only."}else{if(f.match(/^alphanumerics-punctuation-([0-9]+)(-e)?$/)&&!m.match(/^[a-z0-9,\.\/\?\:;"'\{\}\[\]\|\\\+\=_\-\(\)\*&\^%\$#@\!`~]+$/i)){return l+"\nPlease use alphanumerics & punctuation only ( no spaces )."}else{if(f.match(/^alphanumerics-([0-9]+)(-e)?$/)&&!m.match(/^[a-z0-9]+$/i)){return l+"\nPlease use alphanumerics only ( no spaces/punctuation )."}else{if(f.match(/^alphabetics-([0-9]+)(-e)?$/)&&!m.match(/^[a-z]+$/i)){return l+"\nPlease use alphabetics only ( no digits/spaces/punctuation )."}else{if(f.match(/^numerics-([0-9]+)(-e)?$/)&&!m.match(/^[0-9]+$/i)){return l+"\nPlease use numeric digits only."}else{if(f.match(/^(any|alphanumerics-spaces-punctuation|alphanumerics-spaces|alphanumerics-punctuation|alphanumerics|alphabetics|numerics)-([0-9]+)(-e)?$/)){var h=f.split("-"),d=Number(h[1]),e=(h.length>2)?Number(h[2]):"";if(e&&m.length!==d){return l+"\nMust be exactly "+d+" "+((h[0]==="numerics")?"digit":"character")+((d>1)?"s":"")+"."}else{if(m.length<d){return l+"\nMust be at least "+d+" "+((h[0]==="numerics")?"digit":"character")+((d>1)?"s":"")+"."}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}return""}});
1
+ jQuery(document).ready(function(a){ws_plugin__s2member_uniqueFilesDownloaded=[];if(S2MEMBER_CURRENT_USER_IS_LOGGED_IN&&S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY<S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED){a("a[href*=s2member_file_download]").click(function(){if(!this.href.match(/s2member_file_download_key\=(.+)/i)){var b="** Please Confirm This File Download **\n\n";b+="You've downloaded "+S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY+" protected file"+((S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY<1||S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY>1)?"s":"")+" in the last "+S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS+" days.\n\n";b+="You're entitled to "+((S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_IS_UNLIMITED)?"UNLIMITED downloads though ( so, no worries ).":S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED+" unique downloads every "+S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS+" day period.");if(this.href.match(/s2member_skip_confirmation/i)||confirm(b)){if(a.inArray(this.href,ws_plugin__s2member_uniqueFilesDownloaded)===-1){ws_plugin__s2member_uniqueFilesDownloaded.push(this.href),S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY++}return true}else{return false}}else{return true}})}if(location.href.match(/\/wp-signup\.php/)){a("div#content > div.mu_register > form#setupform").submit(function(){var d=this,c="",b="",e="";a("input#user_name, input#user_email, input#blogname, input#blog_title",d).each(function(){if((c=a.trim(a(this).prev("label").text().replace(/[\r\n\t]+/g," ")))){if(b=ws_plugin__s2member_validationErrors(c,this,d,true)){e+=b+"\n\n"}}else{if((c=a.trim(a(this).prev("span.prefix_address").prev("label").text().replace(/[\r\n\t]+/g," ")))){if(b=ws_plugin__s2member_validationErrors(c,this,d,true)){e+=b+"\n\n"}}}});a(":input",d).each(function(){if((c=a.trim(a(this).prev("label").text().replace(/[\r\n\t]+/g," ")))){if(b=ws_plugin__s2member_validationErrors(c,this,d)){e+=b+"\n\n"}}});if(e=a.trim(e)){alert("Oops, you missed something:\n\n"+e);return false}return true})}else{if(location.href.match(/\/wp-login\.php/)){a("div#login > form#registerform").submit(function(){var d=this,c="",b="",e="";a("input#user_login, input#user_email",d).each(function(){if((c=a.trim(a(this).parent("label").text().replace(/[\r\n\t]+/g," ")))){if(b=ws_plugin__s2member_validationErrors(c,this,d,true)){e+=b+"\n\n"}}});a(":input",d).each(function(){if((c=a.trim(a(this).parent("label").children("span").slice(0,1).text().replace(/[\r\n\t]+/g," ")))){if(b=ws_plugin__s2member_validationErrors(c,this,d)){e+=b+"\n\n"}}});if(e=a.trim(e)){alert("Oops, you missed something:\n\n"+e);return false}return true})}else{if(location.href.match(/\/\?s2member_profile\=1/)){a("form#ws-plugin--s2member-profile").submit(function(){var e=this,d="",c="",g="";var b=a("input#ws-plugin--s2member-profile-password");var f=a("input#ws-plugin--s2member-profile-password-confirmation");a(":input",e).each(function(){if((d=a.trim(a(this).parent("label").children("strong").slice(0,1).text().replace(/[\r\n\t]+/g," ")))){if(c=ws_plugin__s2member_validationErrors(d,this,e)){g+=c+"\n\n"}}});if(g=a.trim(g)){alert("Oops, you missed something:\n\n"+g);return false}else{if(a.trim(b.val())&&a.trim(b.val())!==a.trim(f.val())){alert("Oops, you missed something:\n\nPasswords do not match up. Please try again.");return false}}return true})}else{if(location.href.match(/\/wp-admin\/profile\.php/)){a("form#your-profile").submit(function(){var d=this,c="",b="",e="";a(':input[id^="ws-plugin--s2member-profile-"]',d).each(function(){if((c=a.trim(a(this).parent("td").prev("th").children("label").slice(0,1).text().replace(/[\r\n\t]+/g," ")))){if(b=ws_plugin__s2member_validationErrors(c,this,d)){e+=b+"\n\n"}}});if(e=a.trim(e)){alert("Oops, you missed something:\n\n"+e);return false}return true})}}}}ws_plugin__s2member_validationErrors=function(l,k,c,g,f){if(typeof l==="string"&&l&&typeof k==="object"&&typeof c==="object"){if(typeof k.tagName==="string"&&k.tagName.match(/^(input|textarea|select)$/i)){var n=k.tagName.toLowerCase(),j=a(k),i=String(j.attr("type")).toLowerCase(),b=String(j.attr("name")),m=j.val();var g=(typeof g==="boolean")?g:(j.attr("aria-required")==="true"),f=(typeof f==="string")?f:j.attr("data-expected");if(n==="input"&&i==="checkbox"&&b.match(/\[\]$/)){if(typeof k.id==="string"&&k.id.match(/-0$/)){if(g&&!a('input[name="'+b.replace(/([\[\]])/g,"$1")+'"]:checked',c).length){return l+"\nPlease check at least one of the boxes."}}}else{if(n==="input"&&i==="checkbox"){if(g&&!k.checked){return l+"\nRequired. This box must be checked."}}else{if(n==="input"&&i==="radio"){if(typeof k.id==="string"&&k.id.match(/-0$/)){if(g&&!a('input[name="'+b.replace(/([\[\]])/g,"$1")+'"]:checked',c).length){return l+"\nPlease select one of the options."}}}else{if(n==="select"&&j.attr("multiple")){if(g&&(!(m instanceof Array)||!m.length)){return l+"\nPlease select at least one of the options."}}else{if(typeof m!=="string"||(g&&!(m=a.trim(m)).length)){return l+"\nThis is a required field, please try again."}else{if((m=a.trim(m)).length&&((n==="input"&&i.match(/^(text|password)$/i))||n==="textarea")&&typeof f==="string"&&f.length){if(f==="numeric-wp-commas"&&(!m.match(/^[0-9\.,]+$/)||isNaN(m.replace(/,/g,"")))){return l+"\nMust be numeric ( with or without decimals, commas allowed )."}else{if(f==="numeric"&&(!m.match(/^[0-9\.]+$/)||isNaN(m))){return l+"\nMust be numeric ( with or without decimals, no commas )."}else{if(f==="integer"&&(!m.match(/^[0-9]+$/)||isNaN(m))){return l+"\nMust be an integer ( a whole number, without any decimals )."}else{if(f==="integer-gt-0"&&(!m.match(/^[0-9]+$/)||isNaN(m)||m<=0)){return l+"\nMust be an integer > 0 ( whole number, no decimals, greater than 0 )."}else{if(f==="float"&&(!m.match(/^[0-9\.]+$/)||!m.match(/[0-9]/)||!m.match(/\./)||isNaN(m))){return l+"\nMust be a float ( floating point number, decimals required )."}else{if(f==="float-gt-0"&&(!m.match(/^[0-9\.]+$/)||!m.match(/[0-9]/)||!m.match(/\./)||isNaN(m)||m<=0)){return l+"\nMust be a float > 0 ( floating point number, decimals required, greater than 0 )."}else{if(f==="date"&&!m.match(/^[0-9]{2}\/[0-9]{2}\/[0-9]{4}$/)){return l+"\nMust be a date ( required date format: dd/mm/yyyy )."}else{if(f==="email"&&!m.match(/^([a-z_~0-9\+\-]+)(((\.?)([a-z_~0-9\+\-]+))*)(@)([a-z0-9]+)(((-*)([a-z0-9]+))*)(((\.)([a-z0-9]+)(((-*)([a-z0-9]+))*))*)(\.)([a-z]{2,6})$/i)){return l+"\nMust be a valid email address."}else{if(f==="url"&&!m.match(/^http(s?)\:\/\/(.{5,})$/i)){return l+"\nMust be a full URL ( starting with http or https )."}else{if(f==="domain"&&!m.match(/^([a-z0-9]+)(((-*)([a-z0-9]+))*)(((\.)([a-z0-9]+)(((-*)([a-z0-9]+))*))*)(\.)([a-z]{2,6})$/i)){return l+"\nMust be a domain name ( domain name only, without http )."}else{if(f==="phone"&&(!m.match(/^[0-9 \(\)\-]+$/)||m.replace(/[^0-9]/g,"").length!==10)){return l+"\nMust be a phone # ( 10 digits w/possible hyphens,spaces,brackets )."}else{if(f==="uszip"&&!m.match(/^[0-9]{5}(-[0-9]{4})?$/)){return l+"\nMust be a US zipcode ( 5-9 digits w/possible hyphen )."}else{if(f==="cazip"&&!m.match(/^[0-9A-Z]{3}( ?)[0-9A-Z]{3}$/i)){return l+"\nMust be a Canadian zipcode ( 6 alpha-numerics w/possible space )."}else{if(f==="uczip"&&!m.match(/^[0-9]{5}(-[0-9]{4})?$/)&&!m.match(/^[0-9A-Z]{3}( ?)[0-9A-Z]{3}$/i)){return l+"\nMust be a zipcode ( either a US or Canadian zipcode )."}else{if(f.match(/^alphanumerics-spaces-punctuation-([0-9]+)(-e)?$/)&&!m.match(/^[a-z 0-9,\.\/\?\:;"'\{\}\[\]\|\\\+\=_\-\(\)\*&\^%\$#@\!`~]+$/i)){return l+"\nPlease use alphanumerics, spaces & punctuation only."}else{if(f.match(/^alphanumerics-spaces-([0-9]+)(-e)?$/)&&!m.match(/^[a-z 0-9]+$/i)){return l+"\nPlease use alphanumerics & spaces only."}else{if(f.match(/^alphanumerics-punctuation-([0-9]+)(-e)?$/)&&!m.match(/^[a-z0-9,\.\/\?\:;"'\{\}\[\]\|\\\+\=_\-\(\)\*&\^%\$#@\!`~]+$/i)){return l+"\nPlease use alphanumerics & punctuation only ( no spaces )."}else{if(f.match(/^alphanumerics-([0-9]+)(-e)?$/)&&!m.match(/^[a-z0-9]+$/i)){return l+"\nPlease use alphanumerics only ( no spaces/punctuation )."}else{if(f.match(/^alphabetics-([0-9]+)(-e)?$/)&&!m.match(/^[a-z]+$/i)){return l+"\nPlease use alphabetics only ( no digits/spaces/punctuation )."}else{if(f.match(/^numerics-([0-9]+)(-e)?$/)&&!m.match(/^[0-9]+$/i)){return l+"\nPlease use numeric digits only."}else{if(f.match(/^(any|alphanumerics-spaces-punctuation|alphanumerics-spaces|alphanumerics-punctuation|alphanumerics|alphabetics|numerics)-([0-9]+)(-e)?$/)){var h=f.split("-"),d=Number(h[1]),e=(h.length>2)?Number(h[2]):"";if(e&&m.length!==d){return l+"\nMust be exactly "+d+" "+((h[0]==="numerics")?"digit":"character")+((d>1)?"s":"")+"."}else{if(m.length<d){return l+"\nMust be at least "+d+" "+((h[0]==="numerics")?"digit":"character")+((d>1)?"s":"")+"."}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}return""}});
includes/s2member.js CHANGED
@@ -19,21 +19,23 @@ jQuery (document).ready (function($)
19
  {
20
  $ ('a[href*=s2member_file_download]').click (function()
21
  {
22
- if (!this.href.match (/file_download_key\=(.+)/)) /* ~Only for links with NO key. */
23
  {
24
  var c = '** Please Confirm This File Download **\n\n';
25
  c += 'You\'ve downloaded ' + S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY + ' protected file' + ( (S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY < 1 || S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY > 1) ? 's' : '') + ' in the last ' + S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS + ' days.\n\n';
26
  c += 'You\'re entitled to ' + ( (S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_IS_UNLIMITED) ? 'UNLIMITED downloads though ( so, no worries ).' : S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED + ' unique downloads every ' + S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS + ' day period.');
27
  /**/
28
- if (confirm (c)) /* Force the user to confirm before we allow processing. */
29
  {
30
  if ($.inArray (this.href, ws_plugin__s2member_uniqueFilesDownloaded) === -1) /* Real-time counting. */
31
  ws_plugin__s2member_uniqueFilesDownloaded.push (this.href), S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY++;
32
- return true; /* Allow processing. */
33
  }
34
- else /* Do not process. */
35
  return false;
36
  }
 
 
37
  });
38
  }
39
  /*
@@ -201,7 +203,7 @@ jQuery (document).ready (function($)
201
  {
202
  return label + '\nThis is a required field, please try again.'; /* Missing data. */
203
  }
204
- else if (( (tag === 'input' && type.match (/^(text|password)$/i)) || tag === 'textarea') && typeof expected === 'string' && expected.length)
205
  {
206
  if (expected === 'numeric-wp-commas' && (!value.match (/^[0-9\.,]+$/) || isNaN (value.replace (/,/g, ''))))
207
  {
19
  {
20
  $ ('a[href*=s2member_file_download]').click (function()
21
  {
22
+ if (!this.href.match (/s2member_file_download_key\=(.+)/i))
23
  {
24
  var c = '** Please Confirm This File Download **\n\n';
25
  c += 'You\'ve downloaded ' + S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY + ' protected file' + ( (S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY < 1 || S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY > 1) ? 's' : '') + ' in the last ' + S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS + ' days.\n\n';
26
  c += 'You\'re entitled to ' + ( (S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_IS_UNLIMITED) ? 'UNLIMITED downloads though ( so, no worries ).' : S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED + ' unique downloads every ' + S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS + ' day period.');
27
  /**/
28
+ if (this.href.match (/s2member_skip_confirmation/i) || confirm (c))
29
  {
30
  if ($.inArray (this.href, ws_plugin__s2member_uniqueFilesDownloaded) === -1) /* Real-time counting. */
31
  ws_plugin__s2member_uniqueFilesDownloaded.push (this.href), S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY++;
32
+ return true; /* Allow. */
33
  }
34
+ else /* Disallow. */
35
  return false;
36
  }
37
+ else /* Allow. */
38
+ return true;
39
  });
40
  }
41
  /*
203
  {
204
  return label + '\nThis is a required field, please try again.'; /* Missing data. */
205
  }
206
+ else if ((value = $.trim (value)).length && ( (tag === 'input' && type.match (/^(text|password)$/i)) || tag === 'textarea') && typeof expected === 'string' && expected.length)
207
  {
208
  if (expected === 'numeric-wp-commas' && (!value.match (/^[0-9\.,]+$/) || isNaN (value.replace (/,/g, ''))))
209
  {
includes/syscon.inc.php CHANGED
@@ -61,6 +61,8 @@ if (!function_exists ("ws_plugin__s2member_configure_options_and_their_defaults"
61
  /**/
62
  "options_version" => "1.0", /* Used internally to keep runtime files up-to-date. */
63
  /**/
 
 
64
  "sec_encryption_key" => "", /* For security. This keeps each installation unique. */
65
  "sec_encryption_key_history" => array (), /* This keeps a history of the last 10 keys. */
66
  /**/
@@ -110,7 +112,6 @@ if (!function_exists ("ws_plugin__s2member_configure_options_and_their_defaults"
110
  "reg_email_from_name" => get_bloginfo ("name"), /* Defaults to the site name. */
111
  "reg_email_from_email" => get_bloginfo ("admin_email"), /* Defaults to the admin. */
112
  /**/
113
- "paypal_debug" => "0", /* Use the PayPal debug/logs for development testing? */
114
  "paypal_sandbox" => "0", /* Use the PayPal sandbox for development testing? */
115
  "paypal_business" => "", /* Paypal business email address for their account. */
116
  "paypal_identity_token" => "", /* Paypal payment data transfer identity token. */
@@ -222,19 +223,14 @@ if (!function_exists ("ws_plugin__s2member_configure_options_and_their_defaults"
222
  */
223
  $GLOBALS["WS_PLUGIN__"]["s2member"]["o"] = array_merge ($default_options, ( ($options !== false) ? (array)$options : (array)get_option ("ws_plugin__s2member_options")));
224
  /*
225
- Backward compatibility for "sp_notification_urls", which was renamed in v3.2.3 to "sp_sale_notification_urls".
226
- */
227
- if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sp_notification_urls"] && !$options["sp_sale_notification_urls"])
228
- $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sp_sale_notification_urls"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sp_notification_urls"];
229
- /*
230
- Backward compatibility for "sp_notification_recipients", which was renamed in v3.2.3 to "sp_sale_notification_recipients".
231
  */
232
- if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sp_notification_recipients"] && !$options["sp_sale_notification_recipients"])
233
- $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sp_sale_notification_recipients"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["sp_notification_recipients"];
234
  /*
235
  Backward compatibility for "custom_reg_fields", which was re-formatted in v3.2.7 to a JSON encoded array of fields.
236
  */
237
- if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"] && !$options["custom_reg_fields"] && !is_array (json_decode ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"])))
238
  {
239
  $fields = array (); /* Initialize the new array of field objects. */
240
  /**/
@@ -265,6 +261,9 @@ if (!function_exists ("ws_plugin__s2member_configure_options_and_their_defaults"
265
  else if ($key === "options_version" && (!is_string ($value) || !is_numeric ($value)))
266
  $value = $default_options[$key];
267
  /**/
 
 
 
268
  else if ($key === "sec_encryption_key" && (!is_string ($value) || !strlen ($value)))
269
  $value = $default_options[$key];
270
  /**/
@@ -334,9 +333,6 @@ if (!function_exists ("ws_plugin__s2member_configure_options_and_their_defaults"
334
  else if ($key === "reg_email_from_email" && (!is_string ($value) || !strlen ($value)))
335
  $value = $default_options[$key];
336
  /**/
337
- else if ($key === "paypal_debug" && (!is_string ($value) || !is_numeric ($value)))
338
- $value = $default_options[$key];
339
- /**/
340
  else if ($key === "paypal_sandbox" && (!is_string ($value) || !is_numeric ($value)))
341
  $value = $default_options[$key];
342
  /**/
61
  /**/
62
  "options_version" => "1.0", /* Used internally to keep runtime files up-to-date. */
63
  /**/
64
+ "gateway_debug_logs" => "0", /* Enable debugging / logging for development testing? */
65
+ /**/
66
  "sec_encryption_key" => "", /* For security. This keeps each installation unique. */
67
  "sec_encryption_key_history" => array (), /* This keeps a history of the last 10 keys. */
68
  /**/
112
  "reg_email_from_name" => get_bloginfo ("name"), /* Defaults to the site name. */
113
  "reg_email_from_email" => get_bloginfo ("admin_email"), /* Defaults to the admin. */
114
  /**/
 
115
  "paypal_sandbox" => "0", /* Use the PayPal sandbox for development testing? */
116
  "paypal_business" => "", /* Paypal business email address for their account. */
117
  "paypal_identity_token" => "", /* Paypal payment data transfer identity token. */
223
  */
224
  $GLOBALS["WS_PLUGIN__"]["s2member"]["o"] = array_merge ($default_options, ( ($options !== false) ? (array)$options : (array)get_option ("ws_plugin__s2member_options")));
225
  /*
226
+ Backward compatibility for "paypal_debug", which was renamed in v3.3, to "gateway_debug_logs".
 
 
 
 
 
227
  */
228
+ if (isset ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_debug"]) && !isset ($options["gateway_debug_logs"]))
229
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["gateway_debug_logs"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_debug"];
230
  /*
231
  Backward compatibility for "custom_reg_fields", which was re-formatted in v3.2.7 to a JSON encoded array of fields.
232
  */
233
+ if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"] && !is_array (json_decode ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"])))
234
  {
235
  $fields = array (); /* Initialize the new array of field objects. */
236
  /**/
261
  else if ($key === "options_version" && (!is_string ($value) || !is_numeric ($value)))
262
  $value = $default_options[$key];
263
  /**/
264
+ else if ($key === "gateway_debug_logs" && (!is_string ($value) || !is_numeric ($value)))
265
+ $value = $default_options[$key];
266
+ /**/
267
  else if ($key === "sec_encryption_key" && (!is_string ($value) || !strlen ($value)))
268
  $value = $default_options[$key];
269
  /**/
333
  else if ($key === "reg_email_from_email" && (!is_string ($value) || !strlen ($value)))
334
  $value = $default_options[$key];
335
  /**/
 
 
 
336
  else if ($key === "paypal_sandbox" && (!is_string ($value) || !is_numeric ($value)))
337
  $value = $default_options[$key];
338
  /**/
includes/templates/buttons/paypal-cancellation-button.html CHANGED
@@ -1,3 +1,3 @@
1
  <a href="https://%%endpoint%%/cgi-bin/webscr?cmd=_subscr-find&amp;alias=%%paypal_business%%" style="outline:none;">
2
- <img alt="PayPal®" style="border:0;" src="https://www.paypal.com/en_US/i/btn/btn_unsubscribe_LG.gif" />
3
  </a>
1
  <a href="https://%%endpoint%%/cgi-bin/webscr?cmd=_subscr-find&amp;alias=%%paypal_business%%" style="outline:none;">
2
+ <img src="https://www.paypal.com/en_US/i/btn/btn_unsubscribe_LG.gif" style="width:auto; height:auto; border:0;" alt="PayPal®" />
3
  </a>
includes/templates/buttons/paypal-checkout-button.html CHANGED
@@ -9,7 +9,7 @@
9
  <!-- Configures All Of The Checkout Fields -->
10
  <input type="hidden" name="no_shipping" value="1" />
11
  <input type="hidden" name="no_note" value="1" />
12
- <input type="hidden" name="custom" value="%%domain%%" />
13
  <input type="hidden" name="currency_code" value="USD" />
14
  <input type="hidden" name="page_style" value="paypal" />
15
  <input type="hidden" name="item_name" value="%%level_label%% description and pricing details here." />
@@ -29,5 +29,5 @@
29
  <input type="hidden" name="p3" value="1" />
30
  <input type="hidden" name="t3" value="M" />
31
  <!-- Displays The PayPal® Image Button -->
32
- <input type="image" alt="PayPal®" style="border:0;" src="https://www.paypal.com/en_US/i/btn/btn_xpressCheckout.gif" />
33
  </form>
9
  <!-- Configures All Of The Checkout Fields -->
10
  <input type="hidden" name="no_shipping" value="1" />
11
  <input type="hidden" name="no_note" value="1" />
12
+ <input type="hidden" name="custom" value="%%custom%%" />
13
  <input type="hidden" name="currency_code" value="USD" />
14
  <input type="hidden" name="page_style" value="paypal" />
15
  <input type="hidden" name="item_name" value="%%level_label%% description and pricing details here." />
29
  <input type="hidden" name="p3" value="1" />
30
  <input type="hidden" name="t3" value="M" />
31
  <!-- Displays The PayPal® Image Button -->
32
+ <input type="image" src="https://www.paypal.com/en_US/i/btn/btn_xpressCheckout.gif" style="width:auto; height:auto; border:0;" alt="PayPal®" />
33
  </form>
includes/templates/buttons/paypal-sp-checkout-button.html CHANGED
@@ -9,12 +9,12 @@
9
  <!-- Configures All Of The Checkout Fields -->
10
  <input type="hidden" name="no_shipping" value="1" />
11
  <input type="hidden" name="no_note" value="1" />
12
- <input type="hidden" name="custom" value="%%domain%%" />
13
  <input type="hidden" name="currency_code" value="USD" />
14
  <input type="hidden" name="page_style" value="paypal" />
15
  <input type="hidden" name="item_name" value="Description and pricing details here." />
16
  <input type="hidden" name="item_number" value="sp:0:72" />
17
  <input type="hidden" name="amount" value="0.01" />
18
  <!-- Displays The PayPal® Image Button -->
19
- <input type="image" alt="PayPal®" style="border:0;" src="https://www.paypal.com/en_US/i/btn/btn_xpressCheckout.gif" />
20
  </form>
9
  <!-- Configures All Of The Checkout Fields -->
10
  <input type="hidden" name="no_shipping" value="1" />
11
  <input type="hidden" name="no_note" value="1" />
12
+ <input type="hidden" name="custom" value="%%custom%%" />
13
  <input type="hidden" name="currency_code" value="USD" />
14
  <input type="hidden" name="page_style" value="paypal" />
15
  <input type="hidden" name="item_name" value="Description and pricing details here." />
16
  <input type="hidden" name="item_number" value="sp:0:72" />
17
  <input type="hidden" name="amount" value="0.01" />
18
  <!-- Displays The PayPal® Image Button -->
19
+ <input type="image" src="https://www.paypal.com/en_US/i/btn/btn_xpressCheckout.gif" style="width:auto; height:auto; border:0;" alt="PayPal®" />
20
  </form>
includes/templates/options/paypal-currencies.html CHANGED
@@ -1,26 +1,189 @@
1
  <optgroup label="Currency">
2
- <option value="USD" title="$ / U.S. Dollar">USD</option>
3
- <option value="AUD" title="$ / Australian Dollar">AUD</option>
4
- <option value="BRL" title="R$ / Brazilian Real">BRL</option>
5
- <option value="CAD" title="$ / Canadian Dollar">CAD</option>
6
- <option value="CZK" title="Kč / Czech Koruna">CZK</option>
7
- <option value="DKK" title="kr / Danish Krone">DKK</option>
8
- <option value="EUR" title="€ / Euro">EUR</option>
9
- <option value="HKD" title="$ / Hong Kong Dollar">HKD</option>
10
- <option value="HUF" title="Ft / Hungarian Forint">HUF</option>
11
- <option value="ILS" title="₪ / Israeli New Sheqel">ILS</option>
12
- <option value="JPY" title="¥ / Japanese Yen">JPY</option>
13
- <option value="MYR" title="RM / Malaysian Ringgit">MYR</option>
14
- <option value="MXN" title="$ / Mexican Peso">MXN</option>
15
- <option value="NOK" title="kr / Norwegian Krone">NOK</option>
16
- <option value="NZD" title="$ / New Zealand Dollar">NZD</option>
17
- <option value="PHP" title="Php / Philippine Peso">PHP</option>
18
- <option value="PLN" title="zł / Polish Zloty">PLN</option>
19
- <option value="GBP" title="£ / Pound Sterling">GBP</option>
20
- <option value="SGD" title="$ / Singapore Dollar">SGD</option>
21
- <option value="SEK" title="kr / Swedish Krona">SEK</option>
22
- <option value="CHF" title="CHF / Swiss Franc">CHF</option>
23
- <option value="TWD" title="NT$ / Taiwan New Dollar">TWD</option>
24
- <option value="THB" title="฿ / Thai Baht">THB</option>
25
- <option value="USD" title="$ / U.S. Dollar">USD</option>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  </optgroup>
1
  <optgroup label="Currency">
2
+ <option value="ADF">ADF</option>
3
+ <option value="ADP">ADP</option>
4
+ <option value="AED">AED</option>
5
+ <option value="AFA">AFA</option>
6
+ <option value="AFN">AFN</option>
7
+ <option value="ALL">ALL</option>
8
+ <option value="AMD">AMD</option>
9
+ <option value="ANG">ANG</option>
10
+ <option value="AOA">AOA</option>
11
+ <option value="AON">AON</option>
12
+ <option value="ARS">ARS</option>
13
+ <option value="ATS">ATS</option>
14
+ <option value="AUD">AUD</option>
15
+ <option value="AWG">AWG</option>
16
+ <option value="AZN">AZN</option>
17
+ <option value="BAM">BAM</option>
18
+ <option value="BBD">BBD</option>
19
+ <option value="BDT">BDT</option>
20
+ <option value="BEF">BEF</option>
21
+ <option value="BGN">BGN</option>
22
+ <option value="BHD">BHD</option>
23
+ <option value="BIF">BIF</option>
24
+ <option value="BMD">BMD</option>
25
+ <option value="BND">BND</option>
26
+ <option value="BOB">BOB</option>
27
+ <option value="BRL">BRL</option>
28
+ <option value="BSD">BSD</option>
29
+ <option value="BTN">BTN</option>
30
+ <option value="BWP">BWP</option>
31
+ <option value="BYR">BYR</option>
32
+ <option value="BZD">BZD</option>
33
+ <option value="CAD">CAD</option>
34
+ <option value="CDF">CDF</option>
35
+ <option value="CFP">CFP</option>
36
+ <option value="CHF">CHF</option>
37
+ <option value="CLP">CLP</option>
38
+ <option value="CNY">CNY</option>
39
+ <option value="COP">COP</option>
40
+ <option value="CRC">CRC</option>
41
+ <option value="CSK">CSK</option>
42
+ <option value="CUC">CUC</option>
43
+ <option value="CUP">CUP</option>
44
+ <option value="CVE">CVE</option>
45
+ <option value="CYP">CYP</option>
46
+ <option value="CZK">CZK</option>
47
+ <option value="DEM">DEM</option>
48
+ <option value="DJF">DJF</option>
49
+ <option value="DKK">DKK</option>
50
+ <option value="DOP">DOP</option>
51
+ <option value="DZD">DZD</option>
52
+ <option value="ECS">ECS</option>
53
+ <option value="EEK">EEK</option>
54
+ <option value="EGP">EGP</option>
55
+ <option value="ESP">ESP</option>
56
+ <option value="ETB">ETB</option>
57
+ <option value="EUR">EUR</option>
58
+ <option value="FIM">FIM</option>
59
+ <option value="FJD">FJD</option>
60
+ <option value="FKP">FKP</option>
61
+ <option value="FRF">FRF</option>
62
+ <option value="GBP">GBP</option>
63
+ <option value="GEL">GEL</option>
64
+ <option value="GHC">GHC</option>
65
+ <option value="GHS">GHS</option>
66
+ <option value="GIP">GIP</option>
67
+ <option value="GMD">GMD</option>
68
+ <option value="GNF">GNF</option>
69
+ <option value="GRD">GRD</option>
70
+ <option value="GTQ">GTQ</option>
71
+ <option value="GYD">GYD</option>
72
+ <option value="HKD">HKD</option>
73
+ <option value="HNL">HNL</option>
74
+ <option value="HRK">HRK</option>
75
+ <option value="HTG">HTG</option>
76
+ <option value="HUF">HUF</option>
77
+ <option value="IDR">IDR</option>
78
+ <option value="IEP">IEP</option>
79
+ <option value="ILS">ILS</option>
80
+ <option value="INR">INR</option>
81
+ <option value="IQD">IQD</option>
82
+ <option value="IRR">IRR</option>
83
+ <option value="ISK">ISK</option>
84
+ <option value="ITL">ITL</option>
85
+ <option value="JMD">JMD</option>
86
+ <option value="JOD">JOD</option>
87
+ <option value="JPY">JPY</option>
88
+ <option value="KES">KES</option>
89
+ <option value="KGS">KGS</option>
90
+ <option value="KHR">KHR</option>
91
+ <option value="KMF">KMF</option>
92
+ <option value="KPW">KPW</option>
93
+ <option value="KRW">KRW</option>
94
+ <option value="KWD">KWD</option>
95
+ <option value="KYD">KYD</option>
96
+ <option value="KZT">KZT</option>
97
+ <option value="LAK">LAK</option>
98
+ <option value="LBP">LBP</option>
99
+ <option value="LKR">LKR</option>
100
+ <option value="LRD">LRD</option>
101
+ <option value="LSL">LSL</option>
102
+ <option value="LTL">LTL</option>
103
+ <option value="LUF">LUF</option>
104
+ <option value="LVL">LVL</option>
105
+ <option value="LYD">LYD</option>
106
+ <option value="MAD">MAD</option>
107
+ <option value="MDL">MDL</option>
108
+ <option value="MGF">MGF</option>
109
+ <option value="MKD">MKD</option>
110
+ <option value="MMK">MMK</option>
111
+ <option value="MNT">MNT</option>
112
+ <option value="MOP">MOP</option>
113
+ <option value="MRO">MRO</option>
114
+ <option value="MTL">MTL</option>
115
+ <option value="MUR">MUR</option>
116
+ <option value="MVR">MVR</option>
117
+ <option value="MWK">MWK</option>
118
+ <option value="MXN">MXN</option>
119
+ <option value="MYR">MYR</option>
120
+ <option value="MZM">MZM</option>
121
+ <option value="MZN">MZN</option>
122
+ <option value="NAD">NAD</option>
123
+ <option value="NGN">NGN</option>
124
+ <option value="NIO">NIO</option>
125
+ <option value="NLG">NLG</option>
126
+ <option value="NOK">NOK</option>
127
+ <option value="NPR">NPR</option>
128
+ <option value="NZD">NZD</option>
129
+ <option value="OMR">OMR</option>
130
+ <option value="PAB">PAB</option>
131
+ <option value="PEN">PEN</option>
132
+ <option value="PGK">PGK</option>
133
+ <option value="PHP">PHP</option>
134
+ <option value="PKR">PKR</option>
135
+ <option value="PLN">PLN</option>
136
+ <option value="PTE">PTE</option>
137
+ <option value="PYG">PYG</option>
138
+ <option value="QAR">QAR</option>
139
+ <option value="ROL">ROL</option>
140
+ <option value="RON">RON</option>
141
+ <option value="RSD">RSD</option>
142
+ <option value="RUB">RUB</option>
143
+ <option value="SAR">SAR</option>
144
+ <option value="SBD">SBD</option>
145
+ <option value="SCR">SCR</option>
146
+ <option value="SDD">SDD</option>
147
+ <option value="SDG">SDG</option>
148
+ <option value="SDP">SDP</option>
149
+ <option value="SEK">SEK</option>
150
+ <option value="SGD">SGD</option>
151
+ <option value="SHP">SHP</option>
152
+ <option value="SIT">SIT</option>
153
+ <option value="SKK">SKK</option>
154
+ <option value="SLL">SLL</option>
155
+ <option value="SOS">SOS</option>
156
+ <option value="SRD">SRD</option>
157
+ <option value="SRG">SRG</option>
158
+ <option value="STD">STD</option>
159
+ <option value="SVC">SVC</option>
160
+ <option value="SYP">SYP</option>
161
+ <option value="SZL">SZL</option>
162
+ <option value="THB">THB</option>
163
+ <option value="TMM">TMM</option>
164
+ <option value="TND">TND</option>
165
+ <option value="TOP">TOP</option>
166
+ <option value="TRL">TRL</option>
167
+ <option value="TRY">TRY</option>
168
+ <option value="TTD">TTD</option>
169
+ <option value="TWD">TWD</option>
170
+ <option value="TZS">TZS</option>
171
+ <option value="UAH">UAH</option>
172
+ <option value="UGS">UGS</option>
173
+ <option value="USD" selected="selected">USD</option>
174
+ <option value="UYU">UYU</option>
175
+ <option value="UZS">UZS</option>
176
+ <option value="VEF">VEF</option>
177
+ <option value="VND">VND</option>
178
+ <option value="VUV">VUV</option>
179
+ <option value="WST">WST</option>
180
+ <option value="XAF">XAF</option>
181
+ <option value="XCD">XCD</option>
182
+ <option value="XOF">XOF</option>
183
+ <option value="XPF">XPF</option>
184
+ <option value="YER">YER</option>
185
+ <option value="YUN">YUN</option>
186
+ <option value="ZAR">ZAR</option>
187
+ <option value="ZMK">ZMK</option>
188
+ <option value="ZWD">ZWD</option>
189
  </optgroup>
includes/templates/options/paypal-membership-regular-terms.html CHANGED
@@ -1,7 +1,9 @@
1
  <optgroup label="PayPal® ( Subscriptions )">
2
  <option value="1-D-1">Daily ( recurring charge, for ongoing access )</option>
3
  <option value="1-W-1">Weekly ( recurring charge, for ongoing access )</option>
 
4
  <option value="1-M-1" selected="selected">Monthly ( recurring charge, for ongoing access )</option>
 
5
  <option value="3-M-1">Quarterly ( recurring charge, for ongoing access )</option>
6
  <option value="1-Y-1">Yearly ( recurring charge, for ongoing access )</option>
7
  </optgroup>
1
  <optgroup label="PayPal® ( Subscriptions )">
2
  <option value="1-D-1">Daily ( recurring charge, for ongoing access )</option>
3
  <option value="1-W-1">Weekly ( recurring charge, for ongoing access )</option>
4
+ <option value="2-W-1">Bi-Weekly ( recurring charge, for ongoing access )</option>
5
  <option value="1-M-1" selected="selected">Monthly ( recurring charge, for ongoing access )</option>
6
+ <option value="2-M-1">Bi-Monthly ( recurring charge, for ongoing access )</option>
7
  <option value="3-M-1">Quarterly ( recurring charge, for ongoing access )</option>
8
  <option value="1-Y-1">Yearly ( recurring charge, for ongoing access )</option>
9
  </optgroup>
includes/templates/shortcodes/paypal-cancellation-button-shortcode.html CHANGED
@@ -1 +1 @@
1
- [s2Member-PayPal-Button cancel="1" image="default" /]
1
+ [s2Member-PayPal-Button cancel="1" image="default" output="anchor" /]
includes/templates/shortcodes/paypal-checkout-button-shortcode.html CHANGED
@@ -1 +1 @@
1
- [s2Member-PayPal-Button level="%%level%%" ccaps="" desc="%%level_label%% description and pricing details here." ps="paypal" cc="USD" ns="1" custom="%%domain%%" ta="0" tp="0" tt="D" ra="0.01" rp="1" rt="M" rr="1" image="default" /]
1
+ [s2Member-PayPal-Button level="%%level%%" ccaps="" desc="%%level_label%% description and pricing details here." ps="paypal" cc="USD" ns="1" custom="%%custom%%" ta="0" tp="0" tt="D" ra="0.01" rp="1" rt="M" rr="1" image="default" output="button" /]
includes/templates/shortcodes/paypal-sp-checkout-button-shortcode.html CHANGED
@@ -1 +1 @@
1
- [s2Member-PayPal-Button ids="0" exp="72" desc="Description and pricing details here." ps="paypal" cc="USD" ns="1" custom="%%domain%%" ra="0.01" sp="1" image="default" /]
1
+ [s2Member-PayPal-Button ids="0" exp="72" desc="Description and pricing details here." ps="paypal" cc="USD" ns="1" custom="%%custom%%" ra="0.01" sp="1" image="default" output="button" /]
readme.txt CHANGED
@@ -1,7 +1,7 @@
1
  === s2Member ( Membership w/ PayPal® Integration ) ~ now Multisite compatible! ===
2
 
3
- Version: 3.2.9
4
- Stable tag: 3.2.9
5
  Framework: WS-P-3.1
6
 
7
  SSL Compatible: yes
@@ -11,6 +11,12 @@ BuddyPress Compatible: yes
11
  WP Multisite Compatible: yes
12
  Multisite Blog Farm Compatible: yes
13
 
 
 
 
 
 
 
14
  Tested up to: 3.0.1
15
  Requires at least: 3.0
16
  Requires: WordPress® 3.0+, PHP 5.2+
@@ -31,7 +37,7 @@ Plugin URI: http://www.primothemes.com/post/product/s2member-membership-plugin-w
31
  Description: Empowers WordPress® with membership capabilities. Integrates seamlessly with PayPal®. Also compatible with Multisite Networking, and even with BuddyPress if you like.
32
  Tags: membership, members, member, register, signup, paypal, pay pal, s2member, subscriber, members only, buddypress, buddy press, buddy press compatible, shopping cart, checkout, api, options panel included, websharks framework, w3c validated code, includes extensive documentation, highly extensible
33
 
34
- s2Member is an extremely powerful ( and free ) membership management system for WordPress®. It empowers WordPress® with membership capabilities, integrating seamlessly with PayPal®. Also compatible with Multisite Networking, and even with BuddyPress if you like.
35
 
36
  == Installation ==
37
 
@@ -68,7 +74,7 @@ This depends on your hosting provider and/or server configuration. Some web host
68
 
69
  == Description ==
70
 
71
- s2Member is an extremely powerful ( and free ) membership management system for WordPress®. The s2Member Framework ( free ) integrates seamlessly with PayPal® ( very easy ), and fully supports recurring billing, with the ability to track affiliate commissions on a recurring basis. s2Member supports custom Pages for registration ( including Custom Registration Fields ), account access, and a whole lot more. Now compatible with Multisite Networking too, and even with BuddyPress if you like!
72
 
73
  s2Member supports Free Subscribers ( at Level #0 ), and up to four Primary Membership Levels, [1-4]; plus unlimited Custom Capability Packages. Custom Capabilities allow you to create an unlimited number of Membership Packages, all with different Capabilities and prices. You can label your Membership Levels anything you like. The defaults are Free, Bronze, Silver, Gold, and Platinum.
74
 
@@ -76,9 +82,9 @@ s2Member allows you to protect Pages, Posts, Tags, Categories, URIs, URI word fr
76
 
77
  Each Membership Level can have different restrictions, and you could even integrate Conditionals within your content based on Member Level, or on Custom Capabilities. Both Simple ( Shortcode ) and Advanced ( PHP ) code samples are provided under `s2Member -> API Scripting`. s2Member has been fully integrated with Roles &amp; Capabilities that are already built into WordPress®. No new tables :-) It is designed to be completely seamless, without code bloat. We've carefully structured the entire framework, in order to maximize s2Member's ability to operate with other plugins installed.
78
 
79
- You can also sell Specific Post/Page Access ( membership not required ), using "Buy Now" buttons. You can even package multiple Posts/Pages together into one "Buy Now" transaction. Further details are provided under `s2Member -> PayPal® Buttons -> Special Posts/Pages`.
80
 
81
- New! - [s2Member Pro](http://www.s2member.com/) is an add-on module for the free version of s2Member. [s2Member Pro](http://www.s2member.com/) adds [PayPal® Pro integration](http://www.primothemes.com/forums/viewtopic.php?f=4&t=304), a PayPal® Pro Form Generator, advanced User Import/Export tools, support for Coupon Codes, and more. Your purchase of s2Member Pro includes free lifetime upgrades; along with full access to our [video tutorial library](http://www.s2member.com/videos/).
82
 
83
  == Screenshots ==
84
 
@@ -104,7 +110,7 @@ Yes. The [Support Forum](http://www.primothemes.com/forums/viewforum.php?f=4) fo
104
  = Does s2Member install any new database tables? =
105
  No, s2Member has been fully integrated with the Roles &amp; Capabilities that are already built into WordPress®. It is designed to be completely seamless, without code bloat. We've carefully structured the entire framework, in order to maximize s2Member's ability to operate with other plugins installed. For instance, s2Member is also compatible with BuddyPress.
106
 
107
- = Does the PayPal integration work right-out-of-the-box? =
108
  Yes, it can even generate your PayPal® Subscription Buttons for you. Everything is fully integrated. You even get to create your own Pages within WordPress® to handle Membership Options, the Login Welcome Page, etc. For advanced webmasters, there are scripting techniques that are documented as well. These will help you further develop your site and tailor it to meet your specific needs. s2Member API Scripting is NOT required however.
109
 
110
  = How many Membership Levels are supported? =
@@ -116,6 +122,9 @@ Yes, s2Member supports automation of account activation, welcome emails, confirm
116
  = Does s2Member support PayPal® PDT/Auto-Return? =
117
  Yes, s2Member will work with PayPal® Auto-Return/PDT (Payment Data Transfer) `On`, and also with Auto-Return/PDT `Off`. If you enable Auto-Return, you MUST also enable PDT and supply s2Member with your Identity Token. If one is enabled, the other must also be enabled; and vice-versa. There is a place to enter your PayPal® Identity Token for PDT under `s2Member -> PayPal® Options`.
118
 
 
 
 
119
  = How does s2Member protect content from public access? =
120
  s2Member allows you to protect Pages, Posts, Tags, Categories, URIs, URI word fragments, URI Replacement Codes for BuddyPress, Specific Post/Page Access ( Buy Now! ), and even portions of content within Posts/Pages/themes/plugins using Simple ( Shortcode ) or Advanced ( PHP ) Conditionals. Everything is configurable through the s2Member Options Panel. This makes s2Member VERY easy to integrate into any WordPress®-powered site. With s2Member, you can also protect downloadable files, using special restrictions on how many downloads can occur within a certain amount of time. Each Membership Level can have different restrictions ( even Custom Capability Packages ). You can also integrate Conditionals within your content based on Capabilities. Both Simple and Advanced code samples are provided under `s2Member -> API Scripting`.
121
 
@@ -137,7 +146,7 @@ You can get started now, by turning on [Multisite Networking](http://codex.wordp
137
  Yes it is. In fact, we must say... the s2Member/BuddyPress combination is just awesome. These two plugins running together make all sorts of things possible.
138
 
139
  = How does s2Member know when to demote a paid Member to a Free Subscriber? =
140
- s2Member uses its built-in Auto-EOT System ( new ). EOT = End Of Term. Whenever you generate a PayPal® Button with s2Member, you'll configure a length for the Subscription. Depending on the type of Subscription you choose ( recurring, non-recurring, lifetime, or fixed-term ); s2Member will either use PayPal's IPN/`subscr_cancel,subscr_eot` notices, or it will set an Automatic EOT Time, which is processed automatically by s2Member via WP_Cron. For each Member, you can also override the EOT Time, by forcing a specific expiration date. To manually adjust the EOT Time for a specific Member, go to: `WordPress® -> Users`, and click the Edit link next the Member you want to work on.
141
 
142
  = Do I need the s2Clean Theme? =
143
  No. Both s2Member ( the [free version](http://www.primothemes.com/post/product/s2member-membership-plugin-with-paypal/) ), as well as the [s2Member Pro Module](http://www.s2member.com/prices/) will work in just about ANY WordPress® theme. That being said, if you're starting a brand new site, we DO suggest the [s2Clean Theme](http://www.primothemes.com/post/product/s2clean-theme-for-wordpress/), because it has already been setup specifically for s2Member, which will cut down on your development time. For example, the s2Clean Theme comes with a login box built into the site, and it also comes with pre-built Page Templates for s2Member's Login Welcome Page. You could create both of these inside WordPress® using any theme, even without Templates; but the s2Clean Theme makes it all much easier to work with.
@@ -160,16 +169,33 @@ Yes, without a doubt. The free version of s2Member ( aka: the s2Member Framework
160
  = s2Member does this, but I want it to do that. Is that possible? =
161
  We get this type of question a lot. The answer is most definitely **yes**. The entire s2Member Framework is extremely versatile. For instance, the s2Member Pro Module is built on top of the free s2Member Framework; on top of the worlds' most powerful publishing platform ( WordPress® ). That being said, you WILL need be familiar with PHP, and/or WordPress® Hooks/Filters in order to accomplish advanced customizations. We suggest hiring a freelance developer at Elance.com, or hiring Jason Caldwell ( our own Lead Developer ) @ PriMoThemes.com / WebSharks, Inc. [Jason Caldwell](http://www.primothemes.com/post/author/websharksinc-jason/) is the Lead Developer behind the s2Member plugin, and also the s2Member Pro Module.
162
 
163
- = Can s2Member be used with ClickBank® or Google® Checkout? =
164
- Not yet. This is coming soon though. It will be included in a future release of the s2Member Pro Module, which already works with PayPal® Pro; using direct ( on-site ) credit card processing for Visa®, MasterCard®, American Express®, Discover®, Maestro®, Solo®, and PayPal® Express Checkout. [s2Member Pro](http://www.s2member.com/) is an add-on module for the [free version](http://www.primothemes.com/post/product/s2member-membership-plugin-with-paypal/) of s2Member. s2Member Pro adds full PayPal® Pro integration, a PayPal® Pro Form Generator, User Import/Export tools; along with full access to our [video tutorial library](http://www.s2member.com/videos/).
165
-
166
  == Upgrade Notice ==
167
 
168
- = 3.2+ =
169
- * Upgrade highly recommended. New features, Multisite Networking, and several bug fixes.
170
 
171
  == Changelog ==
172
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
  = 3.2.9 =
174
  * Compatibility. s2Member's Custom Field interface was being negatively impacted by the Prototype library for JavaScript; which is utilized by some other popular plugins, such as WP-O-Matic. As a result, on some installations of s2Member ( depending on your plugin combination ), a few site owners were seeing a jumbled mix of fields in their General Options panel for s2Member. This conflict with the Prototype library has been resolved in s2Member v3.2.9+.
175
 
@@ -183,7 +209,7 @@ Not yet. This is coming soon though. It will be included in a future release of
183
  * Attn Developers ( before upgrading ). Hooks/Filters ( e.g. those related to Custom Fields ) have been modified in ways that may break custom scripts you've created to work with previous versions of s2Member. We suggest dropping all of your Hooks/Filters related to Custom Fields. Instead, use the NEW improved tools w/s2Member v3.2.7+. Please see: `s2Member -> General Options -> Custom Fields`.
184
  * BuddyPress/Multisite. A plugin conflict was resolved between BuddyPress/s2Member when both of these plugins were installed on a Multisite Network together. BuddyPress bypasses the default Filter ( `pre_site_option_registration` ) and instead, it uses: `bp_core_get_site_options()`. This has been resolved in s2Member v3.2.6+.
185
  * Bug fix. A bug was found in s2Member's handling of Custom Fields columns. This minor bug was conflicting with other plugins that attempt to create User-based columns. This was been resolved in s2Member v3.2.7+.
186
- * New Shortcode attribute. s2Member's PayPal Button Shortcode now accepts a new attribute ( `ta="0.00"`, Trial Amount ). In the past, if you intended to offer a "paid" initial period at a different price, you had to use the Full Button Code. Now you can just change the `ta="0.00"` attribute ( which is easier ).
187
  * More informative. s2Member now generates warnings for newbies that create conflicts between their Membership Options Page and Login Welcome Page. s2Member is now capable of detecting the most common conflicts, in order to produce informative messages that assist site owners.
188
  * Login/Registration Design. s2Member v3.2.7+ includes additional customization tools that allow font sizes and font families to be configured for the Login/Registration system. In your Dashboard, go to: `s2Member -> General Options -> Login/Registration Design`.
189
  * Bug fix. The Default Profile Editing Panel ( e.g. `/wp-admin/profile.php` ) was NOT validating Custom Fields. s2Member v3.2.7 resolves this for Users/Members. Administrators are exempt ( the intended functionality ).
1
  === s2Member ( Membership w/ PayPal® Integration ) ~ now Multisite compatible! ===
2
 
3
+ Version: 3.3
4
+ Stable tag: 3.3
5
  Framework: WS-P-3.1
6
 
7
  SSL Compatible: yes
11
  WP Multisite Compatible: yes
12
  Multisite Blog Farm Compatible: yes
13
 
14
+ PayPal® Standard Compatible: yes
15
+ PayPal® Pro Compatible: w/ s2Member Pro
16
+ Google® Checkout Compatible: w/ s2Member Pro
17
+ ClickBank® Compatible: w/ s2Member Pro
18
+ AliPay® Compatible: w/ s2Member Pro
19
+
20
  Tested up to: 3.0.1
21
  Requires at least: 3.0
22
  Requires: WordPress® 3.0+, PHP 5.2+
37
  Description: Empowers WordPress® with membership capabilities. Integrates seamlessly with PayPal®. Also compatible with Multisite Networking, and even with BuddyPress if you like.
38
  Tags: membership, members, member, register, signup, paypal, pay pal, s2member, subscriber, members only, buddypress, buddy press, buddy press compatible, shopping cart, checkout, api, options panel included, websharks framework, w3c validated code, includes extensive documentation, highly extensible
39
 
40
+ s2Member is an extremely powerful ( and free ) membership management system for WordPress®. The s2Member Framework ( free ) integrates seamlessly with PayPal® ( very easy ), and fully supports recurring billing, with the ability to track affiliate commissions on a recurring basis. s2Member supports custom Pages for registration ( including Custom Registration Fields ), account access, and a whole lot more. s2Member is now compatible with Multisite Networking too, and even with BuddyPress if you like. In addition, with the s2Member Pro Module ( an optional paid upgrade ), you can add support for PayPal® Pro, Google® Checkout, ClickBank®, and reach over 1 billion people in China with s2Member's AliPay® integration.
41
 
42
  == Installation ==
43
 
74
 
75
  == Description ==
76
 
77
+ s2Member is an extremely powerful ( and free ) membership management system for WordPress®. The s2Member Framework ( free ) integrates seamlessly with PayPal® ( very easy ), and fully supports recurring billing, with the ability to track affiliate commissions on a recurring basis. s2Member supports custom Pages for registration ( including Custom Registration Fields ), account access, and a whole lot more. s2Member is now compatible with Multisite Networking too, and even with BuddyPress if you like. In addition, with the s2Member Pro Module ( an optional paid upgrade ), you can add support for PayPal® Pro, Google® Checkout, ClickBank®, and reach over 1 billion people in China with s2Member's AliPay® integration.
78
 
79
  s2Member supports Free Subscribers ( at Level #0 ), and up to four Primary Membership Levels, [1-4]; plus unlimited Custom Capability Packages. Custom Capabilities allow you to create an unlimited number of Membership Packages, all with different Capabilities and prices. You can label your Membership Levels anything you like. The defaults are Free, Bronze, Silver, Gold, and Platinum.
80
 
82
 
83
  Each Membership Level can have different restrictions, and you could even integrate Conditionals within your content based on Member Level, or on Custom Capabilities. Both Simple ( Shortcode ) and Advanced ( PHP ) code samples are provided under `s2Member -> API Scripting`. s2Member has been fully integrated with Roles &amp; Capabilities that are already built into WordPress®. No new tables :-) It is designed to be completely seamless, without code bloat. We've carefully structured the entire framework, in order to maximize s2Member's ability to operate with other plugins installed.
84
 
85
+ You can also sell Specific Post/Page Access ( membership not required ), using "Buy Now" buttons. You can even package multiple Posts/Pages together into one "Buy Now" transaction. Further details are provided under `s2Member -> PayPal® Buttons -> Specific Posts/Pages`.
86
 
87
+ New! - [s2Member Pro](http://www.s2member.com/) is an add-on module for the free version of s2Member. [s2Member Pro](http://www.s2member.com/) adds [PayPal® Pro integration](http://www.primothemes.com/forums/viewtopic.php?f=4&t=304), a PayPal® Pro Form Generator, Google® Checkout integration, ClickBank® integration, AliPay® integration, advanced User Import/Export tools, support for Coupon Codes, and more. Your purchase of s2Member Pro includes free lifetime upgrades; along with full access to our [video tutorial library](http://www.s2member.com/videos/).
88
 
89
  == Screenshots ==
90
 
110
  = Does s2Member install any new database tables? =
111
  No, s2Member has been fully integrated with the Roles &amp; Capabilities that are already built into WordPress®. It is designed to be completely seamless, without code bloat. We've carefully structured the entire framework, in order to maximize s2Member's ability to operate with other plugins installed. For instance, s2Member is also compatible with BuddyPress.
112
 
113
+ = Does PayPal integration work right-out-of-the-box? =
114
  Yes, it can even generate your PayPal® Subscription Buttons for you. Everything is fully integrated. You even get to create your own Pages within WordPress® to handle Membership Options, the Login Welcome Page, etc. For advanced webmasters, there are scripting techniques that are documented as well. These will help you further develop your site and tailor it to meet your specific needs. s2Member API Scripting is NOT required however.
115
 
116
  = How many Membership Levels are supported? =
122
  = Does s2Member support PayPal® PDT/Auto-Return? =
123
  Yes, s2Member will work with PayPal® Auto-Return/PDT (Payment Data Transfer) `On`, and also with Auto-Return/PDT `Off`. If you enable Auto-Return, you MUST also enable PDT and supply s2Member with your Identity Token. If one is enabled, the other must also be enabled; and vice-versa. There is a place to enter your PayPal® Identity Token for PDT under `s2Member -> PayPal® Options`.
124
 
125
+ = Can s2Member be used with AliPay®, ClickBank®, Google® Checkout? =
126
+ Yes. [s2Member Pro](http://www.s2member.com/) is an add-on module for the free version of s2Member. [s2Member Pro](http://www.s2member.com/) adds [PayPal® Pro integration](http://www.primothemes.com/forums/viewtopic.php?f=4&t=304) ( highly recommended ), a PayPal® Pro Form Generator, Google® Checkout integration, ClickBank® integration, AliPay® integration, advanced User Import/Export tools, support for Coupon Codes, and more. Your purchase of s2Member Pro includes free lifetime upgrades; along with full access to our [video tutorial library](http://www.s2member.com/videos/).
127
+
128
  = How does s2Member protect content from public access? =
129
  s2Member allows you to protect Pages, Posts, Tags, Categories, URIs, URI word fragments, URI Replacement Codes for BuddyPress, Specific Post/Page Access ( Buy Now! ), and even portions of content within Posts/Pages/themes/plugins using Simple ( Shortcode ) or Advanced ( PHP ) Conditionals. Everything is configurable through the s2Member Options Panel. This makes s2Member VERY easy to integrate into any WordPress®-powered site. With s2Member, you can also protect downloadable files, using special restrictions on how many downloads can occur within a certain amount of time. Each Membership Level can have different restrictions ( even Custom Capability Packages ). You can also integrate Conditionals within your content based on Capabilities. Both Simple and Advanced code samples are provided under `s2Member -> API Scripting`.
130
 
146
  Yes it is. In fact, we must say... the s2Member/BuddyPress combination is just awesome. These two plugins running together make all sorts of things possible.
147
 
148
  = How does s2Member know when to demote a paid Member to a Free Subscriber? =
149
+ s2Member uses its built-in Auto-EOT System ( new ). EOT = End Of Term. Whenever you generate a PayPal® Button with s2Member, you'll configure a length for the Subscription. Depending on the type of Subscription you choose ( recurring, non-recurring, lifetime, or fixed-term ); s2Member will either use PayPal's IPN/`subscr_payment,subscr_cancel,subscr_eot` notices, or it will set an Automatic EOT Time, which is processed automatically by s2Member via WP_Cron. For each Member, you can also override the EOT Time, by forcing a specific expiration date. To manually adjust the EOT Time for a specific Member, go to: `WordPress® -> Users`, and click the Edit link next the Member you want to work on.
150
 
151
  = Do I need the s2Clean Theme? =
152
  No. Both s2Member ( the [free version](http://www.primothemes.com/post/product/s2member-membership-plugin-with-paypal/) ), as well as the [s2Member Pro Module](http://www.s2member.com/prices/) will work in just about ANY WordPress® theme. That being said, if you're starting a brand new site, we DO suggest the [s2Clean Theme](http://www.primothemes.com/post/product/s2clean-theme-for-wordpress/), because it has already been setup specifically for s2Member, which will cut down on your development time. For example, the s2Clean Theme comes with a login box built into the site, and it also comes with pre-built Page Templates for s2Member's Login Welcome Page. You could create both of these inside WordPress® using any theme, even without Templates; but the s2Clean Theme makes it all much easier to work with.
169
  = s2Member does this, but I want it to do that. Is that possible? =
170
  We get this type of question a lot. The answer is most definitely **yes**. The entire s2Member Framework is extremely versatile. For instance, the s2Member Pro Module is built on top of the free s2Member Framework; on top of the worlds' most powerful publishing platform ( WordPress® ). That being said, you WILL need be familiar with PHP, and/or WordPress® Hooks/Filters in order to accomplish advanced customizations. We suggest hiring a freelance developer at Elance.com, or hiring Jason Caldwell ( our own Lead Developer ) @ PriMoThemes.com / WebSharks, Inc. [Jason Caldwell](http://www.primothemes.com/post/author/websharksinc-jason/) is the Lead Developer behind the s2Member plugin, and also the s2Member Pro Module.
171
 
 
 
 
172
  == Upgrade Notice ==
173
 
174
+ = 3.3+ =
175
+ * Upgrade highly recommended. New features, ClickBank®, AliPay®, Multisite Networking, and several bug fixes.
176
 
177
  == Changelog ==
178
 
179
+ = 3.3 =
180
+ * (s2Member) Bug fix / File Downloads. Use of PHP's `fread()` function has been updated to `stream_get_contents()` with a 2MB chunk size in order to satisfy the needs of site owners delivering VERY large files ( 500MB+ ) though simulated HTTP streams "inline". For instance, an MP4 video file into a FlowPlayer/JWPlayer or another Flash-based application. In addition, s2Member is now capable of output buffering its chunked file delivery, making it possible for s2Member to deliver VERY large files through most shared hosting platforms without needing to upgrade to a private server.
181
+ * (s2Member) Bug fix / BuddyPress. Bug fix. New filter added in support of BuddyPress on a Multisite installation. `add_filter ("bp_signup_usermeta", "ws_plugin__s2member_ms_process_signup_meta");`
182
+ * (s2Member) Bug fix / BuddyPress. Improved detection of BuddyPress activation/registration slugs using `BP_ACTIVATION_SLUG`, `BP_REGISTER_SLUG` in conjunction with improved routing of `$usermeta` data inside `/s2member/includes/functions/config-user-registration.inc.php`. This resolves an issue where s2Member was not properly applying Membership Levels ( e.g. an s2 Role ) with BuddyPress installed on a Multisite Network.
183
+ * (s2Member) Custom Registration Fields. s2Member's API Notifications now support custom Replacement Codes for any Custom Registration Fields that you've configured with s2Member. This makes it easier for developers to integrate 3rd party services, because s2Member's API Notifications can now be configured to send additional information that may include data entered by your Customer into a Custom Registration Field. Also, s2Member still supports the `custom="domain|cv1|cv2|cv3|etc..."` Attribute in your Shortcode too. For full details, check your Dashboard under: `s2Member -> API Notifications`.
184
+ * (s2Member) Improved documentation on various Replacement Codes available for s2Member. There are also some new Replacement Codes made available in various sections/integrations.
185
+ * (s2Member) In WordPress®, when you list all `Users`, you will find a search box in the upper right-hand corner of the screen. This search box now has the ability to find Members by `Username, Display Name, Nickname, s2Member / Paid Subscr. ID, Custom String, and ANY Custom Registration Field value`.
186
+ * (s2Member) Advanced Content Dripping. A new PHP/API Constant has been made available for Content Dripping `S2MEMBER_CURRENT_USER_PAID_REGISTRATION_DAYS` ( note the addition of "PAID" ). Also, s2Member v3.3 includes an entirely new/alternative method for Dripping Content, using a new API Function called `s2member_registration_time ([level])`. You will find all of the information/documentation on this topic inside your Dashboard under: `s2Member -> API Scripting -> Content Dripping`. s2Member now has the ability to provide you with information about when a Member pays you at each specific Membership Level. That being said, there IS an issue with this... The new function `s2member_registration_time ()` will NOT return data correctly for existing Members that paid you prior to you upgrading to s2Member v3.3+. This is because s2Member did NOT record all of this information in previous versions. So it can't give you what it doesn't have on any of your existing Members. Please check the forums for workarounds.
187
+ * (s2Member) API Constants. s2Member v3.3 includes some new API Constants related to PayPal® and PayPal® Pro integration. Such as the configured PayPal® API Username, Password, Signature, etc. These will make it easier for other extensions to be built on top of s2Member should the need arise.
188
+ * (s2Member/s2Member Pro) Documentation updated throughout. Some minor wording changes were required here-and-there in order to prevent confusion with all of s2Member Pro's new Gateway integrations.
189
+ * (s2Member/s2Member Pro) All of s2Member's Button Generators now give you the ability to set a Trial Period and a separate Trial Billing Amount. So instead of just offering a 100% free Trial Period, you can now offer an Initial Period at one price, but have the Subscription billed later at a different Regular Recurring rate.
190
+ * (s2Member Pro) New configuration panel added to s2Member Pro. The new `Other Gateways` panel allows you to enable/disable other Payment Gateways that have been integrated with s2Member Pro.
191
+ * (s2Member Pro) Google® Checkout. s2Member Pro has been integrated with Google® for Direct Payments and also for Recurring Billing. In order to take advantage of this new integration method, you will need to have a copy of s2Member Pro, and a Google® Checkout Account. A Google® Checkout account is free.
192
+ * (s2Member Pro) ClickBank®. s2Member Pro has now been integrated with ClickBank® for Direct Payments and also for Recurring Billing. In order to take advantage of this new integration method, you will need to have a copy of s2Member Pro, and a ClickBank® Merchant Account. Otherwise, you can just use the PayPal® Standard integration that comes with the free version of s2Member.
193
+ * (s2Member Pro) AliPay®. s2Member Pro has been integrated with AliPay® for Direct Payments. In order to take advantage of this new integration method, you will need to have an AliPay® Merchant Account with Direct Pay enabled ( aka: 前台自助--即时到账收款 ). This can sometimes take a couple of days to acquire. Once you've been approved at AliPay®, you'll be given a Partner ID, and a Security Code; which you'll need to configure inside your `s2Member -> AliPay® Options`.
194
+ * (s2Member Pro) PayPal® Pro integration with s2Member Pro, now supports Coupon Codes that can be configured to ONLY apply to (ta) Trial Amounts, or (ra) Regular Amounts. For further details and examples, please check your Dashboard under: `s2Member -> Coupon Codes`.
195
+ * (s2Member Pro) PayPal® Pro Forms with s2Member Pro, can now be configured to recur at these new intervals: Bi-Weekly, Bi-Monthly, and Quarterly recurring cycles.
196
+ * (s2Member Pro) Documentation. New documentation on ALL of s2Member's Shortcode Attributes for Pro Forms, Standard Shortcodes, and other Payment Gateways; is now included inside your Dashboard. For each Payment Gateway that you enable, there will be a Button Generator available in the s2Member Menu panel. At the bottom of each Button Generating station, you'll find a detailed examination of s2Member's Shortcode Attributes. This should make s2Member even easier for developers to integrate.
197
+ * (s2Member Pro) AliPay® chinese documentation added to the `/s2member-pro/extras/` folder in case developers would like to review the technical aspects. This is NOT required though.
198
+
199
  = 3.2.9 =
200
  * Compatibility. s2Member's Custom Field interface was being negatively impacted by the Prototype library for JavaScript; which is utilized by some other popular plugins, such as WP-O-Matic. As a result, on some installations of s2Member ( depending on your plugin combination ), a few site owners were seeing a jumbled mix of fields in their General Options panel for s2Member. This conflict with the Prototype library has been resolved in s2Member v3.2.9+.
201
 
209
  * Attn Developers ( before upgrading ). Hooks/Filters ( e.g. those related to Custom Fields ) have been modified in ways that may break custom scripts you've created to work with previous versions of s2Member. We suggest dropping all of your Hooks/Filters related to Custom Fields. Instead, use the NEW improved tools w/s2Member v3.2.7+. Please see: `s2Member -> General Options -> Custom Fields`.
210
  * BuddyPress/Multisite. A plugin conflict was resolved between BuddyPress/s2Member when both of these plugins were installed on a Multisite Network together. BuddyPress bypasses the default Filter ( `pre_site_option_registration` ) and instead, it uses: `bp_core_get_site_options()`. This has been resolved in s2Member v3.2.6+.
211
  * Bug fix. A bug was found in s2Member's handling of Custom Fields columns. This minor bug was conflicting with other plugins that attempt to create User-based columns. This was been resolved in s2Member v3.2.7+.
212
+ * New Shortcode attribute. s2Member's PayPal Button Shortcode now accepts a new attribute ( `ta="0.00"`, Trial Amount ). In the past, if you intended to offer a "paid" Initial Period at a different price, you had to use the Full Button Code. Now you can just change the `ta="0.00"` attribute ( which is easier ).
213
  * More informative. s2Member now generates warnings for newbies that create conflicts between their Membership Options Page and Login Welcome Page. s2Member is now capable of detecting the most common conflicts, in order to produce informative messages that assist site owners.
214
  * Login/Registration Design. s2Member v3.2.7+ includes additional customization tools that allow font sizes and font families to be configured for the Login/Registration system. In your Dashboard, go to: `s2Member -> General Options -> Login/Registration Design`.
215
  * Bug fix. The Default Profile Editing Panel ( e.g. `/wp-admin/profile.php` ) was NOT validating Custom Fields. s2Member v3.2.7 resolves this for Users/Members. Administrators are exempt ( the intended functionality ).
s2member.php CHANGED
@@ -9,8 +9,8 @@ along with this software. In the main directory, see: /licensing/
9
  If not, see: <http://www.gnu.org/licenses/>.
10
  */
11
  /*
12
- Version: 3.2.9
13
- Stable tag: 3.2.9
14
  Framework: WS-P-3.1
15
 
16
  SSL Compatible: yes
@@ -20,6 +20,12 @@ BuddyPress Compatible: yes
20
  WP Multisite Compatible: yes
21
  Multisite Blog Farm Compatible: yes
22
 
 
 
 
 
 
 
23
  Tested up to: 3.0.1
24
  Requires at least: 3.0
25
  Requires: WordPress® 3.0+, PHP 5.2+
@@ -48,10 +54,10 @@ if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
48
  /*
49
  Define versions.
50
  */
51
- define ("WS_PLUGIN__S2MEMBER_VERSION", "3.2.9");
52
  define ("WS_PLUGIN__S2MEMBER_MIN_PHP_VERSION", "5.2");
53
  define ("WS_PLUGIN__S2MEMBER_MIN_WP_VERSION", "3.0");
54
- define ("WS_PLUGIN__S2MEMBER_MIN_PRO_VERSION", "1.2.7");
55
  /*
56
  Compatibility checks.
57
  */
9
  If not, see: <http://www.gnu.org/licenses/>.
10
  */
11
  /*
12
+ Version: 3.3
13
+ Stable tag: 3.3
14
  Framework: WS-P-3.1
15
 
16
  SSL Compatible: yes
20
  WP Multisite Compatible: yes
21
  Multisite Blog Farm Compatible: yes
22
 
23
+ PayPal® Standard Compatible: yes
24
+ PayPal® Pro Compatible: w/ s2Member Pro
25
+ Google® Checkout Compatible: w/ s2Member Pro
26
+ ClickBank® Compatible: w/ s2Member Pro
27
+ AliPay® Compatible: w/ s2Member Pro
28
+
29
  Tested up to: 3.0.1
30
  Requires at least: 3.0
31
  Requires: WordPress® 3.0+, PHP 5.2+
54
  /*
55
  Define versions.
56
  */
57
+ define ("WS_PLUGIN__S2MEMBER_VERSION", "3.3");
58
  define ("WS_PLUGIN__S2MEMBER_MIN_PHP_VERSION", "5.2");
59
  define ("WS_PLUGIN__S2MEMBER_MIN_WP_VERSION", "3.0");
60
+ define ("WS_PLUGIN__S2MEMBER_MIN_PRO_VERSION", "1.3");
61
  /*
62
  Compatibility checks.
63
  */