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

Version Description

  • A new option was added under s2Member -> General Options -> De-Activation Safeguards. This new option allows you to disable the de-activation routines for the s2Member plugin, so that s2Member Roles, Capabilities, and your Configuration Options will be preserved in case s2Member is de-activated inadvertently. We recommend that you Safeguard all s2Member data on your system; so please have a look at this new option.
  • A bug was found in the Shortcode processor, related specifically to Buy Now buttons for Lifetime access. This bug has been corrected in s2Member v2.8.4.
  • Stable tag updated in support of tagged releases within the repository at WordPress.org.
Download this release

Release Info

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

Version 2.8.4

Files changed (160) hide show
  1. images/bg.fla +0 -0
  2. images/bg.png +0 -0
  3. images/brand-bg.fla +0 -0
  4. images/brand-bg.png +0 -0
  5. images/brand-dark.fla +0 -0
  6. images/brand-dark.png +0 -0
  7. images/brand-donations.fla +0 -0
  8. images/brand-donations.jpg +0 -0
  9. images/brand-favicon.fla +0 -0
  10. images/brand-favicon.png +0 -0
  11. images/brand-gradient-bg.fla +0 -0
  12. images/brand-gradient-bg.png +0 -0
  13. images/brand-icon.fla +0 -0
  14. images/brand-icon.png +0 -0
  15. images/brand-light.fla +0 -0
  16. images/brand-light.png +0 -0
  17. images/brand-tips.fla +0 -0
  18. images/brand-tips.png +0 -0
  19. images/brand-tools.fla +0 -0
  20. images/brand-tools.png +0 -0
  21. images/brand-updates.fla +0 -0
  22. images/brand-updates.png +0 -0
  23. images/brand-xlink.fla +0 -0
  24. images/brand-xlink.png +0 -0
  25. images/index.php +0 -0
  26. images/logo.fla +0 -0
  27. images/logo.png +0 -0
  28. images/promos/150x150.jpg +0 -0
  29. images/promos/300x225.jpg +0 -0
  30. images/promos/590x300.jpg +0 -0
  31. images/promos/80x80.jpg +0 -0
  32. images/promos/900x285.jpg +0 -0
  33. images/promos/900x385.jpg +0 -0
  34. images/promos/index.php +0 -0
  35. images/wordpress-dark.fla +0 -0
  36. images/wordpress-dark.png +0 -0
  37. images/wordpress-light.fla +0 -0
  38. images/wordpress-light.png +0 -0
  39. includes/funcs.inc.php +24 -0
  40. includes/functions/activate-deactivate.inc.php +185 -0
  41. includes/functions/admin-lockout.inc.php +30 -0
  42. includes/functions/admin-notices.inc.php +78 -0
  43. includes/functions/catg-level-access.inc.php +103 -0
  44. includes/functions/constants.inc.php +189 -0
  45. includes/functions/email-configs.inc.php +36 -0
  46. includes/functions/file-download-access.inc.php +124 -0
  47. includes/functions/hide-some-systematics.inc.php +31 -0
  48. includes/functions/index.php +0 -0
  49. includes/functions/is-systematic.inc.php +64 -0
  50. includes/functions/js-globals.inc.php +125 -0
  51. includes/functions/login-customizations.inc.php +70 -0
  52. includes/functions/login-redirection.inc.php +40 -0
  53. includes/functions/max-download-period.inc.php +44 -0
  54. includes/functions/menu-pages.inc.php +297 -0
  55. includes/functions/min-level-4-downloads.inc.php +41 -0
  56. includes/functions/nocache.inc.php +80 -0
  57. includes/functions/page-level-access.inc.php +61 -0
  58. includes/functions/paypal-notify.inc.php +301 -0
  59. includes/functions/paypal-postvars.inc.php +71 -0
  60. includes/functions/paypal-register.inc.php +40 -0
  61. includes/functions/paypal-return.inc.php +274 -0
  62. includes/functions/post-level-access.inc.php +58 -0
  63. includes/functions/profile-modifications.inc.php +73 -0
  64. includes/functions/ptag-level-access.inc.php +87 -0
  65. includes/functions/readme-parsing.inc.php +92 -0
  66. includes/functions/register-access.inc.php +198 -0
  67. includes/functions/ruri-level-access.inc.php +45 -0
  68. includes/functions/shortcodes.inc.php +59 -0
  69. includes/functions/translations.inc.php +64 -0
  70. includes/functions/user-access-level.inc.php +47 -0
  71. includes/functions/user-deletions.inc.php +39 -0
  72. includes/functions/user-downloads.inc.php +58 -0
  73. includes/functions/users-list.inc.php +129 -0
  74. includes/functions/utilities.inc.php +200 -0
  75. includes/hooks.inc.php +71 -0
  76. includes/index.php +0 -0
  77. includes/markdown/index.php +0 -0
  78. includes/markdown/nc-markdown.inc.php +1469 -0
  79. includes/menu-pages/api-ops.inc.php +268 -0
  80. includes/menu-pages/button.html +32 -0
  81. includes/menu-pages/buttons.inc.php +281 -0
  82. includes/menu-pages/con-samps/current_user_access_label.php +3 -0
  83. includes/menu-pages/con-samps/current_user_access_level.php +13 -0
  84. includes/menu-pages/con-samps/current_user_custom.php +3 -0
  85. includes/menu-pages/con-samps/current_user_display_name.php +3 -0
  86. includes/menu-pages/con-samps/current_user_downloads_allowed.php +3 -0
  87. includes/menu-pages/con-samps/current_user_downloads_allowed_days.php +3 -0
  88. includes/menu-pages/con-samps/current_user_downloads_allowed_is_unlimited.php +2 -0
  89. includes/menu-pages/con-samps/current_user_downloads_currently.php +3 -0
  90. includes/menu-pages/con-samps/current_user_email.php +3 -0
  91. includes/menu-pages/con-samps/current_user_fields.php +7 -0
  92. includes/menu-pages/con-samps/current_user_first_name.php +3 -0
  93. includes/menu-pages/con-samps/current_user_id.php +3 -0
  94. includes/menu-pages/con-samps/current_user_ip.php +3 -0
  95. includes/menu-pages/con-samps/current_user_is_logged_in.php +3 -0
  96. includes/menu-pages/con-samps/current_user_last_name.php +3 -0
  97. includes/menu-pages/con-samps/current_user_login.php +3 -0
  98. includes/menu-pages/con-samps/current_user_profile_modification_page_url.php +8 -0
  99. includes/menu-pages/con-samps/current_user_registration_days.php +15 -0
  100. includes/menu-pages/con-samps/current_user_registration_time.php +3 -0
  101. includes/menu-pages/con-samps/current_user_subscr_id.php +5 -0
  102. includes/menu-pages/con-samps/file_download_limit_exceeded_page_url.php +3 -0
  103. includes/menu-pages/con-samps/level1_file_downloads_allowed.php +3 -0
  104. includes/menu-pages/con-samps/level1_file_downloads_allowed_days.php +3 -0
  105. includes/menu-pages/con-samps/level1_label.php +3 -0
  106. includes/menu-pages/con-samps/level2_file_downloads_allowed.php +3 -0
  107. includes/menu-pages/con-samps/level2_file_downloads_allowed_days.php +3 -0
  108. includes/menu-pages/con-samps/level2_label.php +3 -0
  109. includes/menu-pages/con-samps/level3_file_downloads_allowed.php +3 -0
  110. includes/menu-pages/con-samps/level3_file_downloads_allowed_days.php +3 -0
  111. includes/menu-pages/con-samps/level3_label.php +3 -0
  112. includes/menu-pages/con-samps/level4_file_downloads_allowed.php +3 -0
  113. includes/menu-pages/con-samps/level4_file_downloads_allowed_days.php +3 -0
  114. includes/menu-pages/con-samps/level4_label.php +3 -0
  115. includes/menu-pages/con-samps/login_page_url.php +4 -0
  116. includes/menu-pages/con-samps/login_welcome_page_url.php +4 -0
  117. includes/menu-pages/con-samps/logout_page_url.php +4 -0
  118. includes/menu-pages/con-samps/membership_options_page_url.php +4 -0
  119. includes/menu-pages/con-samps/paypal_business.php +3 -0
  120. includes/menu-pages/con-samps/paypal_endpoint.php +3 -0
  121. includes/menu-pages/con-samps/paypal_notify_url.php +3 -0
  122. includes/menu-pages/con-samps/paypal_return_url.php +3 -0
  123. includes/menu-pages/con-samps/reg_email_from_email.php +3 -0
  124. includes/menu-pages/con-samps/reg_email_from_name.php +3 -0
  125. includes/menu-pages/cur-samps.php +33 -0
  126. includes/menu-pages/down-ops.inc.php +189 -0
  127. includes/menu-pages/drip-samps.php +9 -0
  128. includes/menu-pages/events.inc.php +118 -0
  129. includes/menu-pages/index.php +0 -0
  130. includes/menu-pages/info.inc.php +56 -0
  131. includes/menu-pages/menu-pages.css +458 -0
  132. includes/menu-pages/menu-pages.js +217 -0
  133. includes/menu-pages/mod-samps.php +33 -0
  134. includes/menu-pages/options.inc.php +964 -0
  135. includes/menu-pages/paypal-ops.inc.php +241 -0
  136. includes/menu-pages/s2m-samps.php +33 -0
  137. includes/menu-pages/scripting.inc.php +318 -0
  138. includes/menu-pages/shortcode.html +1 -0
  139. includes/menu-pages/trk-ops.inc.php +118 -0
  140. includes/mime-types.ini +313 -0
  141. includes/profile.inc.php +124 -0
  142. includes/s2member-min.js +1 -0
  143. includes/s2member.js +105 -0
  144. includes/syscon.inc.php +295 -0
  145. index.php +0 -0
  146. licensing/gpl.txt +339 -0
  147. licensing/index.php +0 -0
  148. licensing/license.txt +33 -0
  149. readme.txt +249 -0
  150. s2member.php +85 -0
  151. screenshot-1.png +0 -0
  152. screenshot-10.png +0 -0
  153. screenshot-2.png +0 -0
  154. screenshot-3.png +0 -0
  155. screenshot-4.png +0 -0
  156. screenshot-5.png +0 -0
  157. screenshot-6.png +0 -0
  158. screenshot-7.png +0 -0
  159. screenshot-8.png +0 -0
  160. screenshot-9.png +0 -0
images/bg.fla ADDED
Binary file
images/bg.png ADDED
Binary file
images/brand-bg.fla ADDED
Binary file
images/brand-bg.png ADDED
Binary file
images/brand-dark.fla ADDED
Binary file
images/brand-dark.png ADDED
Binary file
images/brand-donations.fla ADDED
Binary file
images/brand-donations.jpg ADDED
Binary file
images/brand-favicon.fla ADDED
Binary file
images/brand-favicon.png ADDED
Binary file
images/brand-gradient-bg.fla ADDED
Binary file
images/brand-gradient-bg.png ADDED
Binary file
images/brand-icon.fla ADDED
Binary file
images/brand-icon.png ADDED
Binary file
images/brand-light.fla ADDED
Binary file
images/brand-light.png ADDED
Binary file
images/brand-tips.fla ADDED
Binary file
images/brand-tips.png ADDED
Binary file
images/brand-tools.fla ADDED
Binary file
images/brand-tools.png ADDED
Binary file
images/brand-updates.fla ADDED
Binary file
images/brand-updates.png ADDED
Binary file
images/brand-xlink.fla ADDED
Binary file
images/brand-xlink.png ADDED
Binary file
images/index.php ADDED
File without changes
images/logo.fla ADDED
Binary file
images/logo.png ADDED
Binary file
images/promos/150x150.jpg ADDED
Binary file
images/promos/300x225.jpg ADDED
Binary file
images/promos/590x300.jpg ADDED
Binary file
images/promos/80x80.jpg ADDED
Binary file
images/promos/900x285.jpg ADDED
Binary file
images/promos/900x385.jpg ADDED
Binary file
images/promos/index.php ADDED
File without changes
images/wordpress-dark.fla ADDED
Binary file
images/wordpress-dark.png ADDED
Binary file
images/wordpress-light.fla ADDED
Binary file
images/wordpress-light.png ADDED
Binary file
includes/funcs.inc.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Include all of the functions that came with this plugin.
18
+ */
19
+ if (is_dir(dirname(__FILE__) . "/functions"))
20
+ if ($ws_plugin__s2member_temp_r = opendir(dirname(__FILE__) . "/functions"))
21
+ while (($ws_plugin__s2member_temp_s = readdir($ws_plugin__s2member_temp_r)) !== false)
22
+ if (preg_match("/\.php$/", $ws_plugin__s2member_temp_s) && !preg_match("/^index\.php$/i", $ws_plugin__s2member_temp_s))
23
+ include_once dirname(__FILE__) . "/functions/" . $ws_plugin__s2member_temp_s;
24
+ ?>
includes/functions/activate-deactivate.inc.php ADDED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Function for handling activation routines.
18
+ This function should match the array key for this plugin:
19
+ ws_plugin__$plugin_key_activate() is called by our themes.
20
+
21
+ We also initialize some option values here.
22
+ Initializing these options will force them to be
23
+ autoloaded into WordPress® instead of generating
24
+ extra queries before they are set.
25
+ */
26
+ function ws_plugin__s2member_activate ()
27
+ {
28
+ add_role ("s2member_level1", "s2Member Level 1");
29
+ add_role ("s2member_level2", "s2Member Level 2");
30
+ add_role ("s2member_level3", "s2Member Level 3");
31
+ add_role ("s2member_level4", "s2Member Level 4");
32
+ /**/
33
+ $role = &get_role ("s2member_level1");
34
+ $role->add_cap ("read");
35
+ $role->add_cap ("level_0");
36
+ $role->add_cap ("access_s2member_level1");
37
+ /**/
38
+ $role = &get_role ("s2member_level2");
39
+ $role->add_cap ("read");
40
+ $role->add_cap ("level_0");
41
+ $role->add_cap ("access_s2member_level2");
42
+ $role->add_cap ("access_s2member_level1");
43
+ /**/
44
+ $role = &get_role ("s2member_level3");
45
+ $role->add_cap ("read");
46
+ $role->add_cap ("level_0");
47
+ $role->add_cap ("access_s2member_level3");
48
+ $role->add_cap ("access_s2member_level2");
49
+ $role->add_cap ("access_s2member_level1");
50
+ /**/
51
+ $role = &get_role ("s2member_level4");
52
+ $role->add_cap ("read");
53
+ $role->add_cap ("level_0");
54
+ $role->add_cap ("access_s2member_level4");
55
+ $role->add_cap ("access_s2member_level3");
56
+ $role->add_cap ("access_s2member_level2");
57
+ $role->add_cap ("access_s2member_level1");
58
+ /**/
59
+ $role = &get_role ("administrator");
60
+ $role->add_cap ("access_s2member_level1");
61
+ $role->add_cap ("access_s2member_level2");
62
+ $role->add_cap ("access_s2member_level3");
63
+ $role->add_cap ("access_s2member_level4");
64
+ /**/
65
+ $role = &get_role ("editor");
66
+ $role->add_cap ("access_s2member_level1");
67
+ $role->add_cap ("access_s2member_level2");
68
+ $role->add_cap ("access_s2member_level3");
69
+ $role->add_cap ("access_s2member_level4");
70
+ /**/
71
+ $role = &get_role ("author");
72
+ $role->add_cap ("access_s2member_level1");
73
+ $role->add_cap ("access_s2member_level2");
74
+ $role->add_cap ("access_s2member_level3");
75
+ $role->add_cap ("access_s2member_level4");
76
+ /**/
77
+ $role = &get_role ("contributor");
78
+ $role->add_cap ("access_s2member_level1");
79
+ $role->add_cap ("access_s2member_level2");
80
+ $role->add_cap ("access_s2member_level3");
81
+ $role->add_cap ("access_s2member_level4");
82
+ /**/
83
+ if (!is_dir ($files_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"]))
84
+ if (is_writable (dirname ($files_dir)))
85
+ mkdir ($files_dir, 0777);
86
+ /**/
87
+ if (is_dir ($files_dir) && is_writable ($files_dir))
88
+ if (!file_exists ($htaccess = $files_dir . "/.htaccess"))
89
+ file_put_contents ($htaccess, "deny from all");
90
+ /**/
91
+ if (!is_dir ($logs_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"]))
92
+ if (is_writable (dirname ($logs_dir)))
93
+ mkdir ($logs_dir, 0777);
94
+ /**/
95
+ if (is_dir ($logs_dir) && is_writable ($logs_dir))
96
+ if (!file_exists ($htaccess = $logs_dir . "/.htaccess"))
97
+ file_put_contents ($htaccess, "deny from all");
98
+ /**/
99
+ if (!is_numeric (get_option ("ws_plugin__s2member_configured")))
100
+ update_option ("ws_plugin__s2member_configured", "0");
101
+ /**/
102
+ if (!is_array (get_option ("ws_plugin__s2member_cache")))
103
+ update_option ("ws_plugin__s2member_cache", array ());
104
+ /**/
105
+ if (!is_array (get_option ("ws_plugin__s2member_notices")))
106
+ update_option ("ws_plugin__s2member_notices", array ());
107
+ /**/
108
+ if (!is_array (get_option ("ws_plugin__s2member_options")))
109
+ update_option ("ws_plugin__s2member_options", array ());
110
+ /**/
111
+ return;
112
+ }
113
+ /*
114
+ Function for handling de-activation cleanup routines.
115
+ This function should match the array key for this plugin:
116
+ ws_plugin__$plugin_key_deactivate() is called by our themes.
117
+ */
118
+ function ws_plugin__s2member_deactivate ()
119
+ {
120
+ if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["run_deactivation_routines"])
121
+ {
122
+ remove_role ("s2member_level1");
123
+ remove_role ("s2member_level2");
124
+ remove_role ("s2member_level3");
125
+ remove_role ("s2member_level4");
126
+ /**/
127
+ $role = &get_role ("administrator");
128
+ $role->remove_cap ("access_s2member_level1");
129
+ $role->remove_cap ("access_s2member_level2");
130
+ $role->remove_cap ("access_s2member_level3");
131
+ $role->remove_cap ("access_s2member_level4");
132
+ /**/
133
+ $role = &get_role ("editor");
134
+ $role->remove_cap ("access_s2member_level1");
135
+ $role->remove_cap ("access_s2member_level2");
136
+ $role->remove_cap ("access_s2member_level3");
137
+ $role->remove_cap ("access_s2member_level4");
138
+ /**/
139
+ $role = &get_role ("author");
140
+ $role->remove_cap ("access_s2member_level1");
141
+ $role->remove_cap ("access_s2member_level2");
142
+ $role->remove_cap ("access_s2member_level3");
143
+ $role->remove_cap ("access_s2member_level4");
144
+ /**/
145
+ $role = &get_role ("contributor");
146
+ $role->remove_cap ("access_s2member_level1");
147
+ $role->remove_cap ("access_s2member_level2");
148
+ $role->remove_cap ("access_s2member_level3");
149
+ $role->remove_cap ("access_s2member_level4");
150
+ /**/
151
+ if (is_dir ($files_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"]))
152
+ {
153
+ if (file_exists ($htaccess = $files_dir . "/.htaccess"))
154
+ if (is_writable ($htaccess))
155
+ unlink ($htaccess);
156
+ /**/
157
+ @rmdir ($files_dir);
158
+ }
159
+ /**/
160
+ if (is_dir ($logs_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"]))
161
+ {
162
+ if (file_exists ($htaccess = $logs_dir . "/.htaccess"))
163
+ if (is_writable ($htaccess))
164
+ unlink ($htaccess);
165
+ /**/
166
+ if (file_exists ($log = $logs_dir . "/paypal-ipn.log"))
167
+ if (is_writable ($log))
168
+ unlink ($log);
169
+ /**/
170
+ if (file_exists ($log = $logs_dir . "/paypal-rtn.log"))
171
+ if (is_writable ($log))
172
+ unlink ($log);
173
+ /**/
174
+ @rmdir ($logs_dir);
175
+ }
176
+ /**/
177
+ delete_option ("ws_plugin__s2member_configured");
178
+ delete_option ("ws_plugin__s2member_cache");
179
+ delete_option ("ws_plugin__s2member_notices");
180
+ delete_option ("ws_plugin__s2member_options");
181
+ }
182
+ /**/
183
+ return;
184
+ }
185
+ ?>
includes/functions/admin-lockout.inc.php ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Function for handling admin lockouts.
18
+ Attach to: add_action("admin_init");
19
+ */
20
+ function ws_plugin__s2member_admin_lockout ()
21
+ {
22
+ /* This prevents users ( who cannot edit ) from gaining any access to the admin area. */
23
+ /* WordPress® handles most of this on its own, but this prevents profile access also. */
24
+ if (!current_user_can ("edit_posts") /* In other words, if they are a subscriber or a member. */
25
+ && wp_redirect (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"])) !== "nill")
26
+ exit;
27
+ /**/
28
+ return;
29
+ }
30
+ ?>
includes/functions/admin-notices.inc.php ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Function displays an admin notice immediately.
18
+ */
19
+ function ws_plugin__s2member_display_admin_notice ($notice = FALSE, $error = FALSE)
20
+ {
21
+ if ($notice && $error) /* Special format for errors. */
22
+ {
23
+ echo '<div class="error fade"><p>' . $notice . '</p></div>';
24
+ }
25
+ else if ($notice) /* Otherwise, we just send it as an update notice. */
26
+ {
27
+ echo '<div class="updated fade"><p>' . $notice . '</p></div>';
28
+ }
29
+ /**/
30
+ return;
31
+ }
32
+ /*
33
+ Function that enqueues admin notices.
34
+ */
35
+ function ws_plugin__s2member_enqueue_admin_notice ($notice = FALSE, $on_pages = FALSE, $error = FALSE, $time = FALSE)
36
+ {
37
+ if ($notice && is_string ($notice)) /* If we have a valid string. */
38
+ {
39
+ $notices = (array)get_option ("ws_plugin__s2member_notices");
40
+ /**/
41
+ array_push ($notices, array ("notice" => $notice, "on_pages" => $on_pages, "error" => $error, "time" => $time));
42
+ /**/
43
+ update_option ("ws_plugin__s2member_notices", ws_plugin__s2member_array_unique ($notices));
44
+ }
45
+ /**/
46
+ return;
47
+ }
48
+ /*
49
+ Function that displays admin notices.
50
+ Attach to: add_action("admin_notices");
51
+ */
52
+ function ws_plugin__s2member_admin_notices ()
53
+ {
54
+ global $pagenow; /* This holds the current page filename. */
55
+ /**/
56
+ if (is_array ($notices = get_option ("ws_plugin__s2member_notices")) && !empty ($notices))
57
+ {
58
+ foreach ($notices as $key => $notice) /* Check time on each notice. */
59
+ {
60
+ if (empty ($notice["on_pages"]) || $pagenow === $notice["on_pages"] || in_array ($pagenow, (array)$notice["on_pages"]) || $_GET["page"] === $notice["on_pages"] || in_array ($_GET["page"], (array)$notice["on_pages"]))
61
+ {
62
+ if (strtotime ("now") >= $notice["time"]) /* Time to show it? */
63
+ {
64
+ unset ($notices[$key]); /* Clear this notice & display it. */
65
+ /**/
66
+ ws_plugin__s2member_display_admin_notice ($notice["notice"], $notice["error"]);
67
+ }
68
+ }
69
+ }
70
+ /**/
71
+ $notices = array_merge ($notices); /* Re-index array keys. */
72
+ /**/
73
+ update_option ("ws_plugin__s2member_notices", $notices);
74
+ }
75
+ /**/
76
+ return;
77
+ }
78
+ ?>
includes/functions/catg-level-access.inc.php ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Function for handling category level access permissions.
18
+ Attach to: add_action("template_redirect");
19
+ */
20
+ function ws_plugin__s2member_check_catg_level_access ()
21
+ {
22
+ global $post; /* get_the_ID() not yet available here. */
23
+ /**/
24
+ if ((is_category () && ($cat_ID = get_query_var ("cat"))) || (is_single () && !is_page () && is_object ($post) && ($post_ID = $post->ID)))
25
+ {
26
+ if (!ws_plugin__s2member_is_systematic_use_page ()) /* Never restrict systematic use pages. */
27
+ {
28
+ $current_user = (is_user_logged_in ()) ? wp_get_current_user () : false;
29
+ /**/
30
+ if (is_category () && $cat_ID) /* We also check if this is a child category of a restricted category. */
31
+ {
32
+ if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_catgs"] === "all" && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level1")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=1")) !== "nill")
33
+ exit;
34
+ /**/
35
+ else if (in_array ($cat_ID, ($level1_catgs = preg_split ("/,/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_catgs"]))) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level1")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=1")) !== "nill")
36
+ exit;
37
+ /**/
38
+ else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_catgs"] === "all" && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level2")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=2")) !== "nill")
39
+ exit;
40
+ /**/
41
+ else if (in_array ($cat_ID, ($level2_catgs = preg_split ("/,/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_catgs"]))) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level2")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=2")) !== "nill")
42
+ exit;
43
+ /**/
44
+ else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_catgs"] === "all" && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level3")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=3")) !== "nill")
45
+ exit;
46
+ /**/
47
+ else if (in_array ($cat_ID, ($level3_catgs = preg_split ("/,/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_catgs"]))) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level3")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=3")) !== "nill")
48
+ exit;
49
+ /**/
50
+ else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_catgs"] === "all" && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level4")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=4")) !== "nill")
51
+ exit;
52
+ /**/
53
+ else if (in_array ($cat_ID, ($level4_catgs = preg_split ("/,/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_catgs"]))) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level4")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=4")) !== "nill")
54
+ exit;
55
+ /**/
56
+ foreach ($level1_catgs as $catg)
57
+ if (cat_is_ancestor_of ($catg, $cat_ID) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level1")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=1")) !== "nill")
58
+ exit;
59
+ /**/
60
+ foreach ($level2_catgs as $catg)
61
+ if (cat_is_ancestor_of ($catg, $cat_ID) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level2")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=2")) !== "nill")
62
+ exit;
63
+ /**/
64
+ foreach ($level3_catgs as $catg)
65
+ if (cat_is_ancestor_of ($catg, $cat_ID) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level3")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=3")) !== "nill")
66
+ exit;
67
+ /**/
68
+ foreach ($level4_catgs as $catg)
69
+ if (cat_is_ancestor_of ($catg, $cat_ID) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level4")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=4")) !== "nill")
70
+ exit;
71
+ }
72
+ else if (is_single () && !is_page () && $post_ID)
73
+ {
74
+ if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_catgs"] === "all" && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level1")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=1")) !== "nill")
75
+ exit;
76
+ /**/
77
+ else if (($level1_catgs = preg_split ("/,/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_catgs"])) && (in_category ($level1_catgs, $post_ID) || ws_plugin__s2member_in_descendant_category ($level1_catgs, $post_ID)) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level1")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=1")) !== "nill")
78
+ exit;
79
+ /**/
80
+ else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_catgs"] === "all" && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level2")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=2")) !== "nill")
81
+ exit;
82
+ /**/
83
+ else if (($level2_catgs = preg_split ("/,/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_catgs"])) && (in_category ($level2_catgs, $post_ID) || ws_plugin__s2member_in_descendant_category ($level2_catgs, $post_ID)) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level2")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=2")) !== "nill")
84
+ exit;
85
+ /**/
86
+ else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_catgs"] === "all" && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level3")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=3")) !== "nill")
87
+ exit;
88
+ /**/
89
+ else if (($level3_catgs = preg_split ("/,/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_catgs"])) && (in_category ($level3_catgs, $post_ID) || ws_plugin__s2member_in_descendant_category ($level3_catgs, $post_ID)) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level3")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=3")) !== "nill")
90
+ exit;
91
+ /**/
92
+ else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_catgs"] === "all" && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level4")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=4")) !== "nill")
93
+ exit;
94
+ /**/
95
+ else if (($level4_catgs = preg_split ("/,/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_catgs"])) && (in_category ($level4_catgs, $post_ID) || ws_plugin__s2member_in_descendant_category ($level4_catgs, $post_ID)) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level4")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=4")) !== "nill")
96
+ exit;
97
+ }
98
+ }
99
+ }
100
+ /**/
101
+ return;
102
+ }
103
+ ?>
includes/functions/constants.inc.php ADDED
@@ -0,0 +1,189 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Define several API Constants for s2Member.
18
+ Note that these are duplicated into the JavaScript API as well.
19
+ Attach to: add_action("init");
20
+ */
21
+ function ws_plugin__s2member_constants ()
22
+ {
23
+ $links = ws_plugin__s2member_constant_links ();
24
+ $metas = ws_plugin__s2member_constant_metas ();
25
+ $level = ws_plugin__s2member_user_access_level ();
26
+ $current_user = (is_user_logged_in ()) ? wp_get_current_user () : false;
27
+ $file_downloads = ws_plugin__s2member_user_downloads ("", $metas["s2member_file_download_access_log"]);
28
+ $login_redirection_override = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_redirection_override"];
29
+ /**/
30
+ define ("S2MEMBER_CURRENT_USER_IS_LOGGED_IN", (($level >= 1) ? true : false)); /* This will always be (bool) true or false. False if they are not currently logged in. */
31
+ define ("S2MEMBER_CURRENT_USER_ACCESS_LEVEL", (int)$level); /* This will always be (int) negative 1 thru positive 4. -1 if user is not logged in. 0 if logged in w/o access. */
32
+ define ("S2MEMBER_CURRENT_USER_ACCESS_LABEL", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $level . "_label"]); /* This will always be a (string). Empty if not logged in. */
33
+ define ("S2MEMBER_CURRENT_USER_SUBSCR_ID", (($current_user) ? (($metas["s2member_subscr_id"]) ? $metas["s2member_subscr_id"] : $current_user->ID) : "")); /* Empty if not logged in. */
34
+ define ("S2MEMBER_CURRENT_USER_CUSTOM", (($current_user) ? $metas["s2member_custom"] : "")); /* This will always a (string). However, it will be empty if not logged in. */
35
+ define ("S2MEMBER_CURRENT_USER_REGISTRATION_TIME", (($current_user) ? strtotime ($current_user->user_registered) : 0)); /* Always an (int). Or 0 if they're not logged in. */
36
+ define ("S2MEMBER_CURRENT_USER_REGISTRATION_DAYS", (($current_user) ? floor ((strtotime ("now") - strtotime ($current_user->user_registered)) / 86400) : 0)); /* (int). */
37
+ define ("S2MEMBER_CURRENT_USER_DISPLAY_NAME", (($current_user) ? $current_user->display_name : "")); /* This will always be a (string). Empty if not logged in. */
38
+ define ("S2MEMBER_CURRENT_USER_FIRST_NAME", (($current_user) ? $current_user->user_firstname : "")); /* This will always be a (string). Empty if not logged in. */
39
+ define ("S2MEMBER_CURRENT_USER_LAST_NAME", (($current_user) ? $current_user->user_lastname : "")); /* This will always be a (string). Empty if not logged in. */
40
+ define ("S2MEMBER_CURRENT_USER_LOGIN", (($current_user) ? $current_user->user_login : "")); /* This will always be a (string). Empty if not logged in. */
41
+ define ("S2MEMBER_CURRENT_USER_EMAIL", (($current_user) ? $current_user->user_email : "")); /* This will always be a (string). Empty if not logged in. */
42
+ define ("S2MEMBER_CURRENT_USER_IP", $_SERVER["REMOTE_ADDR"]); /* This will always be a (string). It may be empty if the user is browsing anonymously. */
43
+ define ("S2MEMBER_CURRENT_USER_ID", (($current_user) ? (int)$current_user->ID : 0)); /* This will always be an (int). Zero if not logged in. */
44
+ define ("S2MEMBER_CURRENT_USER_FIELDS", (($current_user) ? serialize (array_merge /* Always a serialized (array). This includes custom fields. */
45
+ (array ("id" => S2MEMBER_CURRENT_USER_ID, "ip" => S2MEMBER_CURRENT_USER_IP, "email" => S2MEMBER_CURRENT_USER_EMAIL, "login" => S2MEMBER_CURRENT_USER_LOGIN,/**/
46
+ "first_name" => S2MEMBER_CURRENT_USER_FIRST_NAME, "last_name" => S2MEMBER_CURRENT_USER_LAST_NAME, "display_name" => S2MEMBER_CURRENT_USER_DISPLAY_NAME,/**/
47
+ "subscr_id" => S2MEMBER_CURRENT_USER_SUBSCR_ID, "custom" => S2MEMBER_CURRENT_USER_CUSTOM), $metas["s2member_custom_fields"])) : serialize (array ())));
48
+ /**/
49
+ define ("S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED", (int)$file_downloads["allowed"]); /* This will always be an integer value (int) >= 0 where 0 means no access. */
50
+ define ("S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_IS_UNLIMITED", (($file_downloads["allowed"] >= 999999999) ? true : false)); /* This will always be (bool). */
51
+ define ("S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY", (int)$file_downloads["currently"]); /* This will always be an integer value (int) >= 0 where 0 means none currently. */
52
+ define ("S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS", (int)$file_downloads["allowed_days"]); /* This will always be an integer value (int) >= 0 where 0 means no access. */
53
+ /**/
54
+ define ("S2MEMBER_FILE_DOWNLOAD_LIMIT_EXCEEDED_PAGE_ID", (int)$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_limit_exceeded_page"]); /* The exceeded page id (int). */
55
+ define ("S2MEMBER_MEMBERSHIP_OPTIONS_PAGE_ID", (int)$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]); /* Options page id, always an (int). */
56
+ define ("S2MEMBER_LOGIN_WELCOME_PAGE_ID", (int)$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"]); /* The welcome page id, always an (int). */
57
+ /**/
58
+ define ("S2MEMBER_CURRENT_USER_PROFILE_MODIFICATION_PAGE_URL", get_bloginfo ("url") . "/?s2member_profile=1"); /* Where a user modifies their profile. */
59
+ define ("S2MEMBER_FILE_DOWNLOAD_LIMIT_EXCEEDED_PAGE_URL", $links["file_download_limit_exceeded_page"]); /* Always a string. URL to limit exceeded page. */
60
+ define ("S2MEMBER_MEMBERSHIP_OPTIONS_PAGE_URL", $links["membership_options_page"]); /* Always a string. This is the URL to the membership options page. */
61
+ define ("S2MEMBER_LOGIN_WELCOME_PAGE_URL", (($login_redirection_override) ? $login_redirection_override : $links["login_welcome_page"])); /* Always a string. */
62
+ define ("S2MEMBER_LOGOUT_PAGE_URL", wp_logout_url ()); /* This is always the same, it is the default wordpress action=logout url generated by wp_logout_url(). */
63
+ define ("S2MEMBER_LOGIN_PAGE_URL", wp_login_url ()); /* This is always the same, it is the default wordpress login url that is generated by wp_login_url(). */
64
+ /**/
65
+ define ("S2MEMBER_LEVEL1_LABEL", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_label"]); /* This is the (string) label that you created for membership level number 1. */
66
+ define ("S2MEMBER_LEVEL2_LABEL", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_label"]); /* This is the (string) label that you created for membership level number 2. */
67
+ define ("S2MEMBER_LEVEL3_LABEL", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_label"]); /* This is the (string) label that you created for membership level number 3. */
68
+ define ("S2MEMBER_LEVEL4_LABEL", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_label"]); /* This is the (string) label that you created for membership level number 4. */
69
+ /**/
70
+ define ("S2MEMBER_LEVEL1_FILE_DOWNLOADS_ALLOWED", (int)$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_file_downloads_allowed"]); /* This is the (int) allowed downloads. */
71
+ define ("S2MEMBER_LEVEL2_FILE_DOWNLOADS_ALLOWED", (int)$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_file_downloads_allowed"]); /* This is the (int) allowed downloads. */
72
+ define ("S2MEMBER_LEVEL3_FILE_DOWNLOADS_ALLOWED", (int)$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_file_downloads_allowed"]); /* This is the (int) allowed downloads. */
73
+ define ("S2MEMBER_LEVEL4_FILE_DOWNLOADS_ALLOWED", (int)$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_file_downloads_allowed"]); /* This is the (int) allowed downloads. */
74
+ /**/
75
+ define ("S2MEMBER_LEVEL1_FILE_DOWNLOADS_ALLOWED_DAYS", (int)$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_file_downloads_allowed_days"]); /* This is (int) allowed days. */
76
+ define ("S2MEMBER_LEVEL2_FILE_DOWNLOADS_ALLOWED_DAYS", (int)$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_file_downloads_allowed_days"]); /* This is (int) allowed days. */
77
+ define ("S2MEMBER_LEVEL3_FILE_DOWNLOADS_ALLOWED_DAYS", (int)$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_file_downloads_allowed_days"]); /* This is (int) allowed days. */
78
+ define ("S2MEMBER_LEVEL4_FILE_DOWNLOADS_ALLOWED_DAYS", (int)$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_file_downloads_allowed_days"]); /* This is (int) allowed days. */
79
+ /**/
80
+ define ("S2MEMBER_REG_EMAIL_FROM_NAME", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]); /* This is the name that outgoing email messages are sent by. */
81
+ define ("S2MEMBER_REG_EMAIL_FROM_EMAIL", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"]); /* This is the email that outgoing messages are sent by. */
82
+ /**/
83
+ define ("S2MEMBER_PAYPAL_NOTIFY_URL", get_bloginfo ("url") . "/?s2member_paypal_notify=1"); /* This will always be a (string), and it will never be an empty value. */
84
+ define ("S2MEMBER_PAYPAL_RETURN_URL", get_bloginfo ("url") . "/?s2member_paypal_return=1"); /* This will always be a (string), and it will never be an empty value. */
85
+ define ("S2MEMBER_PAYPAL_ENDPOINT", (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com")); /* Using sandbox? */
86
+ define ("S2MEMBER_PAYPAL_BUSINESS", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"]); /* This is the email address that identifies your paypal business. */
87
+ /**/
88
+ return;
89
+ }
90
+ /*
91
+ This function pulls all of the page links needed for Constants.
92
+ Page links are cached into the s2member options on 15 min intervals.
93
+ This allows the API Constants to provide quick access to them without being
94
+ forced to execute get_page_link() all the time, which piles up DB queries.
95
+ */
96
+ function ws_plugin__s2member_constant_links ()
97
+ {
98
+ $cache_minutes = 15; /* Could be higher? */
99
+ /**/
100
+ $l["login_welcome_page"] = (string)"";
101
+ $l["membership_options_page"] = (string)"";
102
+ $l["file_download_limit_exceeded_page"] = (string)"";
103
+ /**/
104
+ $login_welcome_page = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"];
105
+ $membership_options_page = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"];
106
+ $file_download_limit_exceeded_page = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_limit_exceeded_page"];
107
+ /**/
108
+ $login_welcome_page_cache = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["cache"]["login_welcome_page"];
109
+ $membership_options_page_cache = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["cache"]["membership_options_page"];
110
+ $file_download_limit_exceeded_page_cache = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["cache"]["file_download_limit_exceeded_page"];
111
+ /**/
112
+ if ($login_welcome_page && $login_welcome_page_cache["page"] === $login_welcome_page && $login_welcome_page_cache["link"] && $login_welcome_page_cache["time"] >= strtotime ("-" . $cache_minutes . " minutes"))
113
+ {
114
+ $l["login_welcome_page"] = $login_welcome_page_cache["link"];
115
+ }
116
+ else /* Otherwise, we need to query the database using get_page_link() and update the cache. */
117
+ {
118
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["cache"]["login_welcome_page"]["time"] = strtotime ("now");
119
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["cache"]["login_welcome_page"]["page"] = $login_welcome_page;
120
+ $l["login_welcome_page"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["cache"]["login_welcome_page"]["link"] = get_page_link ($login_welcome_page);
121
+ /**/
122
+ $cache_needs_updating = true;
123
+ }
124
+ /**/
125
+ if ($membership_options_page && $membership_options_page_cache["page"] === $membership_options_page && $membership_options_page_cache["link"] && $membership_options_page_cache["time"] >= strtotime ("-" . $cache_minutes . " minutes"))
126
+ {
127
+ $l["membership_options_page"] = $membership_options_page_cache["link"];
128
+ }
129
+ else /* Otherwise, we need to query the database using get_page_link() and update the cache. */
130
+ {
131
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["cache"]["membership_options_page"]["time"] = strtotime ("now");
132
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["cache"]["membership_options_page"]["page"] = $membership_options_page;
133
+ $l["membership_options_page"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["cache"]["membership_options_page"]["link"] = get_page_link ($membership_options_page);
134
+ /**/
135
+ $cache_needs_updating = true;
136
+ }
137
+ /**/
138
+ if ($file_download_limit_exceeded_page && $file_download_limit_exceeded_page_cache["page"] === $file_download_limit_exceeded_page && $file_download_limit_exceeded_page_cache["link"] && $file_download_limit_exceeded_page_cache["time"] >= strtotime ("-" . $cache_minutes . " minutes"))
139
+ {
140
+ $l["file_download_limit_exceeded_page"] = $file_download_limit_exceeded_page_cache["link"];
141
+ }
142
+ else /* Otherwise, we need to query the database using get_page_link() and update the cache. */
143
+ {
144
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["cache"]["file_download_limit_exceeded_page"]["time"] = strtotime ("now");
145
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["cache"]["file_download_limit_exceeded_page"]["page"] = $file_download_limit_exceeded_page;
146
+ $l["file_download_limit_exceeded_page"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["cache"]["file_download_limit_exceeded_page"]["link"] = get_page_link ($file_download_limit_exceeded_page);
147
+ /**/
148
+ $cache_needs_updating = true;
149
+ }
150
+ /**/
151
+ if ($cache_needs_updating) /* The cache is also reset when options are updated from a menu page. */
152
+ {
153
+ update_option ("ws_plugin__s2member_cache", $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["cache"]);
154
+ }
155
+ /**/
156
+ return $l; /* Links. */
157
+ }
158
+ /*
159
+ This function pulls all of the usermeta details needed for Constants.
160
+ Pulling them all at once helps to prevent repeated database queries.
161
+ */
162
+ function ws_plugin__s2member_constant_metas ()
163
+ {
164
+ global $wpdb; /* The global database object. */
165
+ /**/
166
+ $m["s2member_file_download_access_log"] = array ();
167
+ $m["s2member_custom_fields"] = array ();
168
+ $m["s2member_subscr_id"] = (string)"";
169
+ $m["s2member_custom"] = (string)"";
170
+ /**/
171
+ if (($current_user = (is_user_logged_in ()) ? wp_get_current_user () : false))
172
+ {
173
+ if (is_array ($results = $wpdb->get_results ("SELECT `meta_key`, `meta_value` FROM `" . $wpdb->usermeta . "` WHERE `user_id` = '" . $current_user->ID . "' AND (meta_key = 's2member_file_download_access_log' OR meta_key = 's2member_subscr_id' OR meta_key = 's2member_custom') LIMIT 3")))
174
+ {
175
+ foreach ($results as $r) /* Fill in the array we need. */
176
+ if ($r->meta_key === "s2member_file_download_access_log")
177
+ $m["s2member_file_download_access_log"] = (array)maybe_unserialize ($r->meta_value);
178
+ else if ($result->meta_key === "s2member_custom_fields")
179
+ $m["s2member_custom_fields"] = (array)maybe_unserialize ($r->meta_value);
180
+ else if ($r->meta_key === "s2member_subscr_id")
181
+ $m["s2member_subscr_id"] = (string)$r->meta_value;
182
+ else if ($result->meta_key === "s2member_custom")
183
+ $m["s2member_custom"] = (string)$r->meta_value;
184
+ }
185
+ }
186
+ /**/
187
+ return $m; /* Metas. */
188
+ }
189
+ ?>
includes/functions/email-configs.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;
16
+ /*
17
+ Functions that modify the email From: name/address.
18
+ */
19
+ function ws_plugin__s2member_email_config ()
20
+ {
21
+ add_filter ("wp_mail_from", "_ws_plugin__s2member_email_config_email");
22
+ add_filter ("wp_mail_from_name", "_ws_plugin__s2member_email_config_name");
23
+ /**/
24
+ return;
25
+ }
26
+ /**/
27
+ function _ws_plugin__s2member_email_config_email ($email = FALSE)
28
+ {
29
+ return $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"];
30
+ }
31
+ /**/
32
+ function _ws_plugin__s2member_email_config_name ($name = FALSE)
33
+ {
34
+ return $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"];
35
+ }
36
+ ?>
includes/functions/file-download-access.inc.php ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Function for handling download access permissions.
18
+ Attach to: add_action("init");
19
+ */
20
+ function ws_plugin__s2member_check_file_download_access ()
21
+ {
22
+ if ($_GET["s2member_file_download"])
23
+ {
24
+ if (!$_GET["s2member_free_file_download_key"] || ws_plugin__s2member_xdecrypt ($_GET["s2member_free_file_download_key"]) !== $_GET["s2member_file_download"])
25
+ {
26
+ $_GET["s2member_file_download"] = trim ($_GET["s2member_file_download"], "/");
27
+ /**/
28
+ $file_download_access_is_allowed = $minimum_level_required_to_download_files = ws_plugin__s2member_min_level_4_downloads ();
29
+ /**/
30
+ if (!($current_user = (is_user_logged_in ()) ? wp_get_current_user () : false) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=" . urlencode ($minimum_level_required_to_download_files))) !== "nill")
31
+ exit;
32
+ /**/
33
+ else if (!$file_download_access_is_allowed) /* Have file downloads even been enabled? */
34
+ {
35
+ header ("HTTP/1.0 503 Service Temporarily Unavailable");
36
+ echo '503 File Downloads Are Not Enabled.';
37
+ exit;
38
+ }
39
+ /**/
40
+ else if (!file_exists ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"] . "/" . $_GET["s2member_file_download"]))
41
+ {
42
+ header ("HTTP/1.0 404 Not Found"); /* The file does not even exist. */
43
+ echo '404 File Download Not Found.';
44
+ exit;
45
+ }
46
+ /**/
47
+ else if ((!is_array ($file_downloads = ws_plugin__s2member_user_downloads ()) || !$file_downloads["allowed"] || !$file_downloads["allowed_days"])/**/
48
+ && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_limit_exceeded_page"]), "s2member_file_download=" . urlencode ($_GET["s2member_file_download"]))) !== "nill")
49
+ exit;
50
+ /**/
51
+ $previous_file_downloads = 0; /* Here we're going to count how many downloads they've performed. */
52
+ $maximum_days_logged = ws_plugin__s2member_maximum_download_period (); /* The longest period in days. */
53
+ $file_download_access_log = (array)get_usermeta ($current_user->ID, "s2member_file_download_access_log");
54
+ $file_download_access_arc = (array)get_usermeta ($current_user->ID, "s2member_file_download_access_arc");
55
+ /**/
56
+ foreach ($file_download_access_log as $file_download_access_log_entry_key => $file_download_access_log_entry)
57
+ {
58
+ if (strtotime ($file_download_access_log_entry["date"]) < strtotime ("-" . $maximum_days_logged . " days"))
59
+ {
60
+ unset ($file_download_access_log[$file_download_access_log_entry_key]);
61
+ $file_download_access_arc[] = $file_download_access_log_entry;
62
+ }
63
+ else if (strtotime ($file_download_access_log_entry["date"]) >= strtotime ("-" . $file_downloads["allowed_days"] . " days"))
64
+ {
65
+ $previous_file_downloads++;
66
+ /* Here we check if this file has already been downloaded. */
67
+ if ($file_download_access_log_entry["file"] === $_GET["s2member_file_download"])
68
+ $already_downloaded = true;
69
+ }
70
+ }
71
+ /**/
72
+ if (!$already_downloaded && $previous_file_downloads >= $file_downloads["allowed"] /* They have NOT already downloaded this file, and they're over their limit. */
73
+ && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_limit_exceeded_page"]), "s2member_file_download=" . urlencode ($_GET["s2member_file_download"]))) !== "nill")
74
+ exit;
75
+ /**/
76
+ if (!$already_downloaded) /* Only add this file to the log if they have not already downloaded it. */
77
+ $file_download_access_log[] = array ("date" => date ("Y-m-d"), "file" => $_GET["s2member_file_download"]);
78
+ update_usermeta ($current_user->ID, "s2member_file_download_access_arc", ws_plugin__s2member_array_unique ($file_download_access_arc));
79
+ update_usermeta ($current_user->ID, "s2member_file_download_access_log", ws_plugin__s2member_array_unique ($file_download_access_log));
80
+ }
81
+ else /* This is a free download that we just need to check on the existence of. */
82
+ {
83
+ $_GET["s2member_file_download"] = trim ($_GET["s2member_file_download"], "/");
84
+ /**/
85
+ if (!file_exists ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"] . "/" . $_GET["s2member_file_download"]))
86
+ {
87
+ header ("HTTP/1.0 404 Not Found"); /* The file does not exist. */
88
+ echo '404 File Download Not Found.';
89
+ exit;
90
+ }
91
+ }
92
+ /*
93
+ Here we are going to put together all of the file download information.
94
+ */
95
+ $mimetypes = parse_ini_file (dirname (dirname (dirname (__FILE__))) . "/includes/mime-types.ini");
96
+ /**/
97
+ $pathinfo = pathinfo ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"] . "/" . $_GET["s2member_file_download"]);
98
+ /**/
99
+ $extension = strtolower ($pathinfo["extension"]); /* Convert file extension to lowercase format for MIME type lookup. */
100
+ /**/
101
+ $mimetype = ($mimetypes[$extension]) ? $mimetypes[$extension] : "application/octet-stream"; /* Lookup MIME type. */
102
+ /**/
103
+ $length = filesize ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"] . "/" . $_GET["s2member_file_download"]);
104
+ /*
105
+ Now send the file to the browser. Be sure to turn off output compression.
106
+ */
107
+ ini_set ("zlib.output_compression", 0);
108
+ /**/
109
+ header ("Content-Encoding: none");
110
+ header ("Content-Type: " . $mimetype);
111
+ header ("Content-Length: " . $length);
112
+ header ('Content-Disposition: attachment; filename="' . $pathinfo["basename"] . '"');
113
+ header ("Expires: " . gmdate ("D, d M Y H:i:s", strtotime ("-1 week")) . " GMT");
114
+ header ("Last-Modified: " . gmdate ("D, d M Y H:i:s") . " GMT");
115
+ header ("Cache-Control: no-cache, must-revalidate, max-age=0");
116
+ header ("Cache-Control: post-check=0, pre-check=0", false);
117
+ header ("Pragma: no-cache");
118
+ /**/
119
+ readfile ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"] . "/" . $_GET["s2member_file_download"]);
120
+ /**/
121
+ exit;
122
+ }
123
+ }
124
+ ?>
includes/functions/hide-some-systematics.inc.php ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Function that hides some of the systematic use pages.
18
+ Attach to: add_filter("posts_where");
19
+ */
20
+ function ws_plugin__s2member_hide_some_systematics ($where = FALSE)
21
+ {
22
+ global $wpdb; /* Need this to get the table name. */
23
+ /**/
24
+ if (is_search()) /* Here we exclude a few systematic use pages from the search query. */
25
+ {
26
+ $where .= " AND " . $wpdb->posts . ".ID NOT IN ('" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"] . "', '" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"] . "', '" . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_limit_exceeded_page"] . "')";
27
+ }
28
+ /**/
29
+ return $where;
30
+ }
31
+ ?>
includes/functions/index.php ADDED
File without changes
includes/functions/is-systematic.inc.php ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Function that determines whether we are on a systematic use page.
18
+ */
19
+ function ws_plugin__s2member_is_systematic_use_page ()
20
+ {
21
+ static $is_systematic; /* For optimization. */
22
+ /**/
23
+ if (isset ($is_systematic)) /* Already cached? */
24
+ {
25
+ return $is_systematic; /* Saves time. */
26
+ }
27
+ else if (is_admin ()) /* In the admin area? */
28
+ {
29
+ return ($is_systematic = true);
30
+ }
31
+ else if (preg_match ("/^cli$/i", PHP_SAPI))
32
+ {
33
+ return ($is_systematic = true);
34
+ }
35
+ else if ($_SERVER["REMOTE_ADDR"] === $_SERVER["SERVER_ADDR"])
36
+ {
37
+ return ($is_systematic = true);
38
+ }
39
+ else if (preg_match ("/\/wp-login\.php/", $_SERVER["REQUEST_URI"]))
40
+ {
41
+ return ($is_systematic = true);
42
+ }
43
+ else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"] && is_page ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]))
44
+ {
45
+ return ($is_systematic = true);
46
+ }
47
+ else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"] && is_page ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"]))
48
+ {
49
+ return ($is_systematic = true);
50
+ }
51
+ else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_limit_exceeded_page"] && is_page ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_limit_exceeded_page"]))
52
+ {
53
+ return ($is_systematic = true);
54
+ }
55
+ else if (preg_match ("/^s2member/", $_SERVER["QUERY_STRING"]) && ($_SERVER["REQUEST_URI"] === "/" || strtolower (rtrim (get_bloginfo ("url"), "/")) === rtrim (strtolower ("http://" . $_SERVER["HTTP_HOST"]) . $_SERVER["REQUEST_URI"], "/")))
56
+ {
57
+ return ($is_systematic = true); /* Only true when the request starts with /?s2member from the root URL of the domain, or from the root URL of the WordPress® installation. */
58
+ }
59
+ else /* Otherwise, we return false. */
60
+ {
61
+ return ($is_systematic = false);
62
+ }
63
+ }
64
+ ?>
includes/functions/js-globals.inc.php ADDED
@@ -0,0 +1,125 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Function for adding script to the header.
18
+ This function is fired in the admin area also.
19
+ Do NOT enqueue the script in the admin area.
20
+ Attach to: add_action("wp_print_scripts");
21
+ */
22
+ function ws_plugin__s2member_add_js_w_globals ()
23
+ {
24
+ if (!is_admin ()) /* Not in the admin. */
25
+ {
26
+ if (is_user_logged_in ())
27
+ {
28
+ $a = get_defined_constants (true);
29
+ $c = (array)$a["user"];
30
+ unset ($a);
31
+ /**/
32
+ foreach ($c as $k => $v)
33
+ if (preg_match ("/^S2MEMBER_/i", $k))
34
+ $s2member[$k] = $v;
35
+ /**/
36
+ $md5 = md5 (serialize ($s2member)); /* This is a hash based on the global key => values. */
37
+ /* The md5 hash allows the script to be cached in the browser until the globals happen to change. */
38
+ /* For instance, the global variables may change when a user who is logged-in changes their profile. */
39
+ wp_enqueue_script ("ws-plugin--s2member", get_bloginfo ("url") . "/?ws_plugin__s2member_js_w_globals=1&s2ABC=1&qcABC=1&" . $md5, array ("jquery"), $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["options_version"] . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["filemtime"]);
40
+ }
41
+ else /* Else if they are not logged in, we distinguish the script by not including the md5 hash. */
42
+ { /* This essentially creates 2 versions of the script. One while logged in & another when not. */
43
+ wp_enqueue_script ("ws-plugin--s2member", get_bloginfo ("url") . "/?ws_plugin__s2member_js_w_globals=1&s2ABC=1&qcABC=1", array ("jquery"), $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["options_version"] . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["filemtime"]);
44
+ }
45
+ }
46
+ /**/
47
+ return;
48
+ }
49
+ /*
50
+ Function for adding s2member.js with globals.
51
+ Attach to: add_action("init");
52
+ */
53
+ function ws_plugin__s2member_js_w_globals ()
54
+ {
55
+ if ($_GET["ws_plugin__s2member_js_w_globals"])
56
+ {
57
+ header ("Content-Type: text/javascript; charset=utf-8");
58
+ header ("Expires: " . gmdate ("D, d M Y H:i:s", strtotime ("+1 week")) . " GMT");
59
+ header ("Last-Modified: " . gmdate ("D, d M Y H:i:s") . " GMT");
60
+ header ("Cache-Control: max-age=604800");
61
+ header ("Pragma: public");
62
+ /**/
63
+ $g = "var S2MEMBER_CURRENT_USER_IS_LOGGED_IN = " . ((S2MEMBER_CURRENT_USER_IS_LOGGED_IN) ? "true" : "false") . ",";
64
+ $g .= "S2MEMBER_CURRENT_USER_ACCESS_LEVEL = " . S2MEMBER_CURRENT_USER_ACCESS_LEVEL . ",";
65
+ $g .= "S2MEMBER_CURRENT_USER_ACCESS_LABEL = '" . preg_replace ("/'/", "\'", S2MEMBER_CURRENT_USER_ACCESS_LABEL) . "',";
66
+ $g .= "S2MEMBER_CURRENT_USER_SUBSCR_ID = '" . preg_replace ("/'/", "\'", S2MEMBER_CURRENT_USER_SUBSCR_ID) . "',";
67
+ $g .= "S2MEMBER_CURRENT_USER_CUSTOM = '" . preg_replace ("/'/", "\'", S2MEMBER_CURRENT_USER_CUSTOM) . "',";
68
+ $g .= "S2MEMBER_CURRENT_USER_REGISTRATION_TIME = " . S2MEMBER_CURRENT_USER_REGISTRATION_TIME . ",";
69
+ $g .= "S2MEMBER_CURRENT_USER_REGISTRATION_DAYS = " . S2MEMBER_CURRENT_USER_REGISTRATION_DAYS . ",";
70
+ $g .= "S2MEMBER_CURRENT_USER_DISPLAY_NAME = '" . preg_replace ("/'/", "\'", S2MEMBER_CURRENT_USER_DISPLAY_NAME) . "',";
71
+ $g .= "S2MEMBER_CURRENT_USER_FIRST_NAME = '" . preg_replace ("/'/", "\'", S2MEMBER_CURRENT_USER_FIRST_NAME) . "',";
72
+ $g .= "S2MEMBER_CURRENT_USER_LAST_NAME = '" . preg_replace ("/'/", "\'", S2MEMBER_CURRENT_USER_LAST_NAME) . "',";
73
+ $g .= "S2MEMBER_CURRENT_USER_LOGIN = '" . preg_replace ("/'/", "\'", S2MEMBER_CURRENT_USER_LOGIN) . "',";
74
+ $g .= "S2MEMBER_CURRENT_USER_EMAIL = '" . preg_replace ("/'/", "\'", S2MEMBER_CURRENT_USER_EMAIL) . "',";
75
+ $g .= "S2MEMBER_CURRENT_USER_IP = '" . preg_replace ("/'/", "\'", S2MEMBER_CURRENT_USER_IP) . "',";
76
+ $g .= "S2MEMBER_CURRENT_USER_ID = " . S2MEMBER_CURRENT_USER_ID . ",";
77
+ /**/
78
+ $g .= "S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED = " . S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED . ",";
79
+ $g .= "S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_IS_UNLIMITED = " . ((S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_IS_UNLIMITED) ? "true" : "false") . ",";
80
+ $g .= "S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY = " . S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY . ",";
81
+ $g .= "S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS = " . S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS . ",";
82
+ /**/
83
+ $g .= "S2MEMBER_FILE_DOWNLOAD_LIMIT_EXCEEDED_PAGE_ID = " . S2MEMBER_FILE_DOWNLOAD_LIMIT_EXCEEDED_PAGE_ID . ",";
84
+ $g .= "S2MEMBER_MEMBERSHIP_OPTIONS_PAGE_ID = " . S2MEMBER_MEMBERSHIP_OPTIONS_PAGE_ID . ",";
85
+ $g .= "S2MEMBER_LOGIN_WELCOME_PAGE_ID = " . S2MEMBER_LOGIN_WELCOME_PAGE_ID . ",";
86
+ /**/
87
+ $g .= "S2MEMBER_CURRENT_USER_PROFILE_MODIFICATION_PAGE_URL = '" . preg_replace ("/'/", "\'", S2MEMBER_CURRENT_USER_PROFILE_MODIFICATION_PAGE_URL) . "',";
88
+ $g .= "S2MEMBER_FILE_DOWNLOAD_LIMIT_EXCEEDED_PAGE_URL = '" . preg_replace ("/'/", "\'", S2MEMBER_FILE_DOWNLOAD_LIMIT_EXCEEDED_PAGE_URL) . "',";
89
+ $g .= "S2MEMBER_MEMBERSHIP_OPTIONS_PAGE_URL = '" . preg_replace ("/'/", "\'", S2MEMBER_MEMBERSHIP_OPTIONS_PAGE_URL) . "',";
90
+ $g .= "S2MEMBER_LOGOUT_PAGE_URL = '" . preg_replace ("/'/", "\'", S2MEMBER_LOGOUT_PAGE_URL) . "',";
91
+ $g .= "S2MEMBER_LOGIN_PAGE_URL = '" . preg_replace ("/'/", "\'", S2MEMBER_LOGIN_PAGE_URL) . "',";
92
+ /**/
93
+ $g .= "S2MEMBER_LEVEL1_LABEL = '" . preg_replace ("/'/", "\'", S2MEMBER_LEVEL1_LABEL) . "',";
94
+ $g .= "S2MEMBER_LEVEL2_LABEL = '" . preg_replace ("/'/", "\'", S2MEMBER_LEVEL2_LABEL) . "',";
95
+ $g .= "S2MEMBER_LEVEL3_LABEL = '" . preg_replace ("/'/", "\'", S2MEMBER_LEVEL3_LABEL) . "',";
96
+ $g .= "S2MEMBER_LEVEL4_LABEL = '" . preg_replace ("/'/", "\'", S2MEMBER_LEVEL4_LABEL) . "',";
97
+ /**/
98
+ $g .= "S2MEMBER_LEVEL1_FILE_DOWNLOADS_ALLOWED = " . S2MEMBER_LEVEL1_FILE_DOWNLOADS_ALLOWED . ",";
99
+ $g .= "S2MEMBER_LEVEL2_FILE_DOWNLOADS_ALLOWED = " . S2MEMBER_LEVEL2_FILE_DOWNLOADS_ALLOWED . ",";
100
+ $g .= "S2MEMBER_LEVEL3_FILE_DOWNLOADS_ALLOWED = " . S2MEMBER_LEVEL3_FILE_DOWNLOADS_ALLOWED . ",";
101
+ $g .= "S2MEMBER_LEVEL4_FILE_DOWNLOADS_ALLOWED = " . S2MEMBER_LEVEL4_FILE_DOWNLOADS_ALLOWED . ",";
102
+ /**/
103
+ $g .= "S2MEMBER_LEVEL1_FILE_DOWNLOADS_ALLOWED_DAYS = " . S2MEMBER_LEVEL1_FILE_DOWNLOADS_ALLOWED_DAYS . ",";
104
+ $g .= "S2MEMBER_LEVEL2_FILE_DOWNLOADS_ALLOWED_DAYS = " . S2MEMBER_LEVEL2_FILE_DOWNLOADS_ALLOWED_DAYS . ",";
105
+ $g .= "S2MEMBER_LEVEL3_FILE_DOWNLOADS_ALLOWED_DAYS = " . S2MEMBER_LEVEL3_FILE_DOWNLOADS_ALLOWED_DAYS . ",";
106
+ $g .= "S2MEMBER_LEVEL4_FILE_DOWNLOADS_ALLOWED_DAYS = " . S2MEMBER_LEVEL4_FILE_DOWNLOADS_ALLOWED_DAYS . ",";
107
+ /**/
108
+ $g .= "S2MEMBER_REG_EMAIL_FROM_NAME = '" . preg_replace ("/'/", "\'", S2MEMBER_REG_EMAIL_FROM_NAME) . "',";
109
+ $g .= "S2MEMBER_REG_EMAIL_FROM_EMAIL = '" . preg_replace ("/'/", "\'", S2MEMBER_REG_EMAIL_FROM_EMAIL) . "',";
110
+ /**/
111
+ $g .= "S2MEMBER_PAYPAL_NOTIFY_URL = '" . preg_replace ("/'/", "\'", S2MEMBER_PAYPAL_NOTIFY_URL) . "',";
112
+ $g .= "S2MEMBER_PAYPAL_RETURN_URL = '" . preg_replace ("/'/", "\'", S2MEMBER_PAYPAL_RETURN_URL) . "',";
113
+ $g .= "S2MEMBER_PAYPAL_ENDPOINT = '" . preg_replace ("/'/", "\'", S2MEMBER_PAYPAL_ENDPOINT) . "',";
114
+ $g .= "S2MEMBER_PAYPAL_BUSINESS = '" . preg_replace ("/'/", "\'", S2MEMBER_PAYPAL_BUSINESS) . "',";
115
+ /**/
116
+ $g = trim ($g, " ,") . ";"; /* Trim & add semicolon. */
117
+ $j = file_get_contents (dirname (dirname (__FILE__)) . "/s2member-min.js");
118
+ $j = preg_replace ("/('|\")%%globals%%('|\");/", $g, $j);
119
+ /**/
120
+ echo $j;
121
+ /**/
122
+ exit;
123
+ }
124
+ }
125
+ ?>
includes/functions/login-customizations.inc.php ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Function for filtering the login logo url.
18
+ Attach to: add_filter("login_headerurl");
19
+ */
20
+ function ws_plugin__s2member_login_header_url ($url = FALSE)
21
+ {
22
+ $url = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_url"];
23
+ /**/
24
+ return $url;
25
+ }
26
+ /*
27
+ Function for filtering the login logo title.
28
+ Attach to: add_filter("login_headertitle");
29
+ */
30
+ function ws_plugin__s2member_login_header_title ($title = FALSE)
31
+ {
32
+ $title = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_title"];
33
+ /**/
34
+ return $title;
35
+ }
36
+ /*
37
+ Function for creating the styles for the login panel.
38
+ Attach to: add_action("login_head");
39
+ */
40
+ function ws_plugin__s2member_login_header_styles ()
41
+ {
42
+ echo "\n" . '<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>' . "\n";
43
+ echo '<script type="text/javascript" src="' . get_bloginfo ("url") . '/?ws_plugin__s2member_js_w_globals=1&amp;no-cache=' . urlencode (md5 (mt_rand ())) . '"></script>' . "\n";
44
+ /**/
45
+ echo "\n" . '<style type="text/css">' . "\n";
46
+ /**/
47
+ echo 'html, body { border: 0 !important; background: none !important; }' . "\n"; /* Clear borders & existing background. */
48
+ echo 'html { background-color: #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_color"] . ' !important; }' . "\n";
49
+ echo 'html { background-image: url(' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_image"] . ') !important; }' . "\n";
50
+ /**/
51
+ echo 'p#backtoblog a, p#backtoblog a:hover, p#backtoblog a:active, p#backtoblog a:focus { color: #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_text_color"] . ' !important; text-shadow: 1px 1px 3px #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_text_shadow_color"] . ' !important; top: 15px !important; left: 15px !important; padding: 10px !important; border:1px solid #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_box_shadow_color"] . ' !important; background-color: #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_color"] . ' !important; -moz-border-radius:3px !important; -webkit-border-radius:3px !important; border-radius:3px !important; }' . "\n";
52
+ /**/
53
+ echo 'div#login { width: ' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_src_width"] . 'px !important; }' . "\n";
54
+ echo 'div#login h1 a { background: url(' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_src"] . ') no-repeat top center !important; }' . "\n";
55
+ echo 'div#login h1 a { display: block !important; width: 100% !important; height: ' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_src_height"] . 'px !important; }' . "\n";
56
+ echo 'div#login p#nav, div#login p#nav a, div#login p#nav a:hover, div#login p#nav a:active, div#login p#nav a:focus { color: #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_text_color"] . ' !important; text-shadow: 1px 1px 3px #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_text_shadow_color"] . ' !important; }' . "\n";
57
+ echo 'div#login form { -moz-box-shadow: 1px 1px 5px #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_box_shadow_color"] . ', -1px -1px 5px #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_box_shadow_color"] . ' !important; -webkit-box-shadow: 1px 1px 5px #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_box_shadow_color"] . ', -1px -1px 5px #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_box_shadow_color"] . ' !important; -khtml-box-shadow: 1px 1px 5px #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_box_shadow_color"] . ', -1px -1px 5px #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_box_shadow_color"] . ' !important; box-shadow: 1px 1px 5px #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_box_shadow_color"] . ', -1px -1px 5px #' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_box_shadow_color"] . ' !important; }' . "\n";
58
+ echo 'div#login form input[type="submit"], div#login form input[type="submit"]:hover, div#login form input[type="submit"]:active, div#login form input[type="submit"]:focus { color: #333333 !important; border: 1px solid #666666 !important; background: #CCCCCC !important; padding: 5px !important; -moz-border-radius: 3px !important; -webkit-border-radius: 3px !important; -khtml-border-radius: 3px !important; border-radius: 3px !important; }' . "\n";
59
+ echo 'div#login form input[type="submit"]:hover, div#login form input[type="submit"]:active, div#login form input[type="submit"]:focus { color: #000000 !important; border: 1px solid #000000 !important; }' . "\n";
60
+ /**/
61
+ echo 'div#login form input.ws-plugin--s2member-custom-reg-field { background:none repeat scroll 0 0 #FBFBFB; border:1px solid #E5E5E5; font-size:24px; margin-bottom:16px; margin-right:6px; margin-top:2px; padding:3px; width:97%; }' . "\n";
62
+ /**/
63
+ if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_password"])
64
+ echo 'p#reg_passmail { display: none; }' . "\n";
65
+ /**/
66
+ echo '</style>' . "\n\n";
67
+ /**/
68
+ return;
69
+ }
70
+ ?>
includes/functions/login-redirection.inc.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Function for handling login redirections.
18
+ Attach to: add_action("wp_login");
19
+ */
20
+ function ws_plugin__s2member_login_redirect ()
21
+ {
22
+ /* Note that current_user_can() will not work here because the cookie was just set. */
23
+ global $user; /* Available during the login routine just before wp_login is hooked in. */
24
+ /**/
25
+ $uzer = new WP_User ($user->ID); /* Now lets get a user object to check capabilities. */
26
+ /**/
27
+ if (!$uzer->has_cap ("edit_posts")) /* In other words, all subscribers & members. */
28
+ {
29
+ if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_redirection_override"])
30
+ wp_redirect ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_redirection_override"]);
31
+ /**/
32
+ else /* Otherwise, use the Login Welcome Page. */
33
+ wp_redirect (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"]));
34
+ /**/
35
+ exit;
36
+ }
37
+ /**/
38
+ return;
39
+ }
40
+ ?>
includes/functions/max-download-period.inc.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Function determines the maximum period in days for download access.
18
+ Returns number of days, where 0 means no access to files has been allowed.
19
+ */
20
+ function ws_plugin__s2member_maximum_download_period ()
21
+ {
22
+ if ($days = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_file_downloads_allowed_days"])
23
+ {
24
+ $maximum = ($maximum < $days) ? $days : $maximum;
25
+ }
26
+ /**/
27
+ if ($days = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_file_downloads_allowed_days"])
28
+ {
29
+ $maximum = ($maximum < $days) ? $days : $maximum;
30
+ }
31
+ /**/
32
+ if ($days = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_file_downloads_allowed_days"])
33
+ {
34
+ $maximum = ($maximum < $days) ? $days : $maximum;
35
+ }
36
+ /**/
37
+ if ($days = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_file_downloads_allowed_days"])
38
+ {
39
+ $maximum = ($maximum < $days) ? $days : $maximum;
40
+ }
41
+ /**/
42
+ return ($maximum > 365) ? 365 : (int)$maximum;
43
+ }
44
+ ?>
includes/functions/menu-pages.inc.php ADDED
@@ -0,0 +1,297 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Function for saving all options from any page.
18
+ */
19
+ function ws_plugin__s2member_update_all_options ()
20
+ {
21
+ if (($nonce = $_POST["ws_plugin__s2member_options_save"]) && wp_verify_nonce ($nonce, "ws-plugin--s2member-options-save"))
22
+ {
23
+ $options = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]; /* Get current options. */
24
+ /**/
25
+ foreach ($_POST as $key => $value) /* Go through each post variable and look for s2member. */
26
+ {
27
+ if (preg_match ("/^" . preg_quote ("ws_plugin__s2member", "/") . "/", $key)) /* Look for keys. */
28
+ {
29
+ if ($key === "ws_plugin__s2member_configured") /* This is a special configuration option. */
30
+ {
31
+ update_option ("ws_plugin__s2member_configured", trim (stripslashes ($value))); /* Update this option separately. */
32
+ /**/
33
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["configured"] = trim (stripslashes ($value)); /* Update configuration on-the-fly. */
34
+ }
35
+ else /* We need to place this option into the array. Here we remove the ws_plugin__s2member_ portion on the beginning. */
36
+ {
37
+ (is_array ($value)) ? array_shift ($value) : null; /* Arrays should be padded, 1st key is removed. */
38
+ $options[preg_replace ("/^" . preg_quote ("ws_plugin__s2member_", "/") . "/", "", $key)] = $value;
39
+ }
40
+ }
41
+ }
42
+ /**/
43
+ $options["options_version"] = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["options_version"] + 0.001; /* Increment options version. */
44
+ /**/
45
+ $options = ws_plugin__s2member_configure_options_and_their_defaults ($options); /* Also updates the global options array. */
46
+ /**/
47
+ update_option ("ws_plugin__s2member_options", $options) . update_option ("ws_plugin__s2member_cache", array ());
48
+ /**/
49
+ ws_plugin__s2member_display_admin_notice ('<strong>Options saved.</strong>'); /* Display admin notice. */
50
+ }
51
+ /**/
52
+ return;
53
+ }
54
+ /*
55
+ Add the options menus & sub-menus.
56
+ Attach to: add_action("admin_menu");
57
+ */
58
+ function ws_plugin__s2member_add_admin_options ()
59
+ {
60
+ add_filter ("plugin_action_links", "_ws_plugin__s2member_add_settings_link", 10, 2);
61
+ /**/
62
+ add_menu_page ("s2Member Options", "s2Member", "edit_plugins", "ws-plugin--s2member-options", "ws_plugin__s2member_options_page");
63
+ add_submenu_page ("ws-plugin--s2member-options", "s2Member General Options", "General Options", "edit_plugins", "ws-plugin--s2member-options", "ws_plugin__s2member_options_page");
64
+ add_submenu_page ("ws-plugin--s2member-options", "s2Member PayPal Options", "PayPal® Options", "edit_plugins", "ws-plugin--s2member-paypal-ops", "ws_plugin__s2member_paypal_ops_page");
65
+ add_submenu_page ("ws-plugin--s2member-options", "s2Member PayPal® Buttons", "PayPal® Buttons", "edit_plugins", "ws-plugin--s2member-buttons", "ws_plugin__s2member_buttons_page");
66
+ add_submenu_page ("ws-plugin--s2member-options", "s2Member File Download Options", "Download Options", "edit_plugins", "ws-plugin--s2member-down-ops", "ws_plugin__s2member_down_ops_page");
67
+ add_submenu_page ("ws-plugin--s2member-options", "s2Member API / Tracking", "API / Tracking", "edit_plugins", "ws-plugin--s2member-trk-ops", "ws_plugin__s2member_trk_ops_page");
68
+ add_submenu_page ("ws-plugin--s2member-options", "s2Member API / Notifications", "API / Notifications", "edit_plugins", "ws-plugin--s2member-api-ops", "ws_plugin__s2member_api_ops_page");
69
+ add_submenu_page ("ws-plugin--s2member-options", "s2Member API / Scripting", "API / Scripting", "edit_plugins", "ws-plugin--s2member-scripting", "ws_plugin__s2member_scripting_page");
70
+ add_submenu_page ("ws-plugin--s2member-options", "s2Member Flow Of Events", "Flow Of Events", "edit_plugins", "ws-plugin--s2member-events", "ws_plugin__s2member_events_page");
71
+ add_submenu_page ("ws-plugin--s2member-options", "s2Member Information", "s2Member Info", "edit_plugins", "ws-plugin--s2member-info", "ws_plugin__s2member_info_page");
72
+ /**/
73
+ return;
74
+ }
75
+ /*
76
+ A sort of callback function to add the settings link.
77
+ */
78
+ function _ws_plugin__s2member_add_settings_link ($links = array (), $file = "")
79
+ {
80
+ if (preg_match ("/" . preg_quote ($file, "/") . "$/", $GLOBALS["WS_PLUGIN__"]["s2member"]["l"]) && is_array ($links))
81
+ {
82
+ $settings = '<a href="admin.php?page=ws-plugin--s2member-options">Settings</a>';
83
+ array_unshift ($links, $settings);
84
+ }
85
+ /**/
86
+ return $links;
87
+ }
88
+ /*
89
+ Add scripts to admin panels.
90
+ Attach to: add_action("admin_print_scripts");
91
+ */
92
+ function ws_plugin__s2member_add_admin_scripts ()
93
+ {
94
+ if ($_GET["page"] && preg_match ("/ws-plugin--s2member-/", $_GET["page"]))
95
+ {
96
+ wp_enqueue_script ("jquery");
97
+ wp_enqueue_script ("thickbox");
98
+ wp_enqueue_script ("media-upload");
99
+ wp_enqueue_script ("ws-plugin--s2member-menu-pages", get_bloginfo ("url") . "/?ws_plugin__s2member_menu_pages_js=1", array ("jquery", "thickbox", "media-upload"), $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["options_version"] . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["filemtime"]);
100
+ }
101
+ /**/
102
+ return;
103
+ }
104
+ /*
105
+ Add styles to admin panels.
106
+ Attach to: add_action("admin_print_styles");
107
+ */
108
+ function ws_plugin__s2member_add_admin_styles ()
109
+ {
110
+ if ($_GET["page"] && preg_match ("/ws-plugin--s2member-/", $_GET["page"]))
111
+ {
112
+ wp_enqueue_style ("thickbox");
113
+ wp_enqueue_style ("ws-plugin--s2member-menu-pages", get_bloginfo ("url") . "/?ws_plugin__s2member_menu_pages_css=1", array ("thickbox"), $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["options_version"] . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["filemtime"], "all");
114
+ }
115
+ /**/
116
+ return;
117
+ }
118
+ /*
119
+ Function that outputs the JS for menu pages.
120
+ Attach to: add_action("init");
121
+ */
122
+ function ws_plugin__s2member_menu_pages_js ()
123
+ {
124
+ if ($_GET["ws_plugin__s2member_menu_pages_js"] && is_user_logged_in () && current_user_can ("edit_plugins"))
125
+ {
126
+ header ("Content-Type: text/javascript; charset=utf-8");
127
+ header ("Expires: " . gmdate ("D, d M Y H:i:s", strtotime ("-1 week")) . " GMT");
128
+ header ("Last-Modified: " . gmdate ("D, d M Y H:i:s") . " GMT");
129
+ header ("Cache-Control: no-cache, must-revalidate, max-age=0");
130
+ header ("Pragma: no-cache");
131
+ /**/
132
+ $u = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"];
133
+ $i = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images";
134
+ /**/
135
+ include_once dirname (dirname (__FILE__)) . "/menu-pages/menu-pages.js";
136
+ /**/
137
+ exit;
138
+ }
139
+ }
140
+ /*
141
+ Function that outputs the CSS for menu pages.
142
+ Attach to: add_action("init");
143
+ */
144
+ function ws_plugin__s2member_menu_pages_css ()
145
+ {
146
+ if ($_GET["ws_plugin__s2member_menu_pages_css"] && is_user_logged_in () && current_user_can ("edit_plugins"))
147
+ {
148
+ header ("Content-Type: text/css; charset=utf-8");
149
+ header ("Expires: " . gmdate ("D, d M Y H:i:s", strtotime ("-1 week")) . " GMT");
150
+ header ("Last-Modified: " . gmdate ("D, d M Y H:i:s") . " GMT");
151
+ header ("Cache-Control: no-cache, must-revalidate, max-age=0");
152
+ header ("Pragma: no-cache");
153
+ /**/
154
+ $u = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"];
155
+ $i = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images";
156
+ /**/
157
+ include_once dirname (dirname (__FILE__)) . "/menu-pages/menu-pages.css";
158
+ /**/
159
+ exit;
160
+ }
161
+ }
162
+ /*
163
+ Function for building and handling the General Options page.
164
+ */
165
+ function ws_plugin__s2member_options_page ()
166
+ {
167
+ ws_plugin__s2member_update_all_options ();
168
+ /**/
169
+ include_once dirname (dirname (__FILE__)) . "/menu-pages/options.inc.php";
170
+ /**/
171
+ return;
172
+ }
173
+ /*
174
+ Function for building and handling the Paypal Options page.
175
+ */
176
+ function ws_plugin__s2member_paypal_ops_page ()
177
+ {
178
+ ws_plugin__s2member_update_all_options ();
179
+ /**/
180
+ $logs_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"];
181
+ /**/
182
+ if (!is_dir ($logs_dir) && is_writable (dirname ($logs_dir)))
183
+ mkdir ($logs_dir, 0777);
184
+ /**/
185
+ $htaccess = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"] . "/.htaccess";
186
+ /**/
187
+ if (is_dir ($logs_dir) && is_writable ($logs_dir) && !file_exists ($htaccess))
188
+ file_put_contents ($htaccess, "deny from all");
189
+ /**/
190
+ if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_debug"]) /* If logging is enabled. */
191
+ {
192
+ if (!is_dir ($logs_dir)) /* If the security-enabled logs directory does not exist yet. */
193
+ 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);
194
+ /**/
195
+ else if (!is_writable ($logs_dir)) /* If the logs directory is not writable yet. */
196
+ ws_plugin__s2member_display_admin_notice ("Permissions error. The security-enabled logs directory ( <code>" . preg_replace ("/^" . preg_quote ($_SERVER["DOCUMENT_ROOT"], "/") . "/", "", $logs_dir) . "</code> ) is not writable. Please make this directory writable ( chmod 777 ).", true);
197
+ /**/
198
+ if (!file_exists ($htaccess)) /* If the .htaccess file has not been created yet. */
199
+ ws_plugin__s2member_display_admin_notice ("The .htaccess protection file ( <code>" . preg_replace ("/^" . preg_quote ($_SERVER["DOCUMENT_ROOT"], "/") . "/", "", $htaccess) . "</code> ) does not exist. Please create this file manually. Inside your .htaccess file, add this one line: <code>deny from all</code>.", true);
200
+ /**/
201
+ else if (!preg_match ("/deny from all/i", file_get_contents ($htaccess))) /* Else if the .htaccess file does not offer the required protection. */
202
+ ws_plugin__s2member_display_admin_notice ("Unprotected. The .htaccess protection file ( <code>" . preg_replace ("/^" . preg_quote ($_SERVER["DOCUMENT_ROOT"], "/") . "/", "", $htaccess) . "</code> ) does not contain <code>deny from all</code>. Inside your .htaccess file, add this one line: <code>deny from all</code>.", true);
203
+ }
204
+ /**/
205
+ include_once dirname (dirname (__FILE__)) . "/menu-pages/paypal-ops.inc.php";
206
+ /**/
207
+ return;
208
+ }
209
+ /*
210
+ Function for building and handling the Download Options page.
211
+ */
212
+ function ws_plugin__s2member_down_ops_page ()
213
+ {
214
+ ws_plugin__s2member_update_all_options ();
215
+ /**/
216
+ $files_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"];
217
+ /**/
218
+ if (!is_dir ($files_dir) && is_writable (dirname ($files_dir)))
219
+ mkdir ($files_dir, 0777);
220
+ /**/
221
+ $htaccess = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"] . "/.htaccess";
222
+ /**/
223
+ if (is_dir ($files_dir) && is_writable ($files_dir) && !file_exists ($htaccess))
224
+ file_put_contents ($htaccess, "deny from all");
225
+ /**/
226
+ if (!is_dir ($files_dir)) /* If the security-enabled files directory does not exist yet. */
227
+ ws_plugin__s2member_display_admin_notice ("The security-enabled files directory ( <code>" . preg_replace ("/^" . preg_quote ($_SERVER["DOCUMENT_ROOT"], "/") . "/", "", $files_dir) . "</code> ) does not exist. Please create this directory manually.", true);
228
+ /**/
229
+ if (!file_exists ($htaccess)) /* If the .htaccess file has not been created yet. */
230
+ ws_plugin__s2member_display_admin_notice ("The .htaccess protection file ( <code>" . preg_replace ("/^" . preg_quote ($_SERVER["DOCUMENT_ROOT"], "/") . "/", "", $htaccess) . "</code> ) does not exist. Please create this file manually. Inside your .htaccess file, add this one line: <code>deny from all</code>.", true);
231
+ /**/
232
+ else if (!preg_match ("/deny from all/i", file_get_contents ($htaccess))) /* Else if the .htaccess file does not offer the required protection. */
233
+ ws_plugin__s2member_display_admin_notice ("Unprotected. The .htaccess protection file ( <code>" . preg_replace ("/^" . preg_quote ($_SERVER["DOCUMENT_ROOT"], "/") . "/", "", $htaccess) . "</code> ) does not contain <code>deny from all</code>. Inside your .htaccess file, add this one line: <code>deny from all</code>.", true);
234
+ /**/
235
+ include_once dirname (dirname (__FILE__)) . "/menu-pages/down-ops.inc.php";
236
+ /**/
237
+ return;
238
+ }
239
+ /*
240
+ Function for building and handling the API Tracking options page.
241
+ */
242
+ function ws_plugin__s2member_trk_ops_page ()
243
+ {
244
+ ws_plugin__s2member_update_all_options ();
245
+ /**/
246
+ include_once dirname (dirname (__FILE__)) . "/menu-pages/trk-ops.inc.php";
247
+ /**/
248
+ return;
249
+ }
250
+ /*
251
+ Function for building and handling the API Notifications page.
252
+ */
253
+ function ws_plugin__s2member_api_ops_page ()
254
+ {
255
+ ws_plugin__s2member_update_all_options ();
256
+ /**/
257
+ include_once dirname (dirname (__FILE__)) . "/menu-pages/api-ops.inc.php";
258
+ /**/
259
+ return;
260
+ }
261
+ /*
262
+ Function for building the PayPal Button Generator page.
263
+ */
264
+ function ws_plugin__s2member_buttons_page ()
265
+ {
266
+ include_once dirname (dirname (__FILE__)) . "/menu-pages/buttons.inc.php";
267
+ /**/
268
+ return;
269
+ }
270
+ /*
271
+ Function for building the API Scripting page.
272
+ */
273
+ function ws_plugin__s2member_scripting_page ()
274
+ {
275
+ include_once dirname (dirname (__FILE__)) . "/menu-pages/scripting.inc.php";
276
+ /**/
277
+ return;
278
+ }
279
+ /*
280
+ Function for building the Flow Of Events page.
281
+ */
282
+ function ws_plugin__s2member_events_page ()
283
+ {
284
+ include_once dirname (dirname (__FILE__)) . "/menu-pages/events.inc.php";
285
+ /**/
286
+ return;
287
+ }
288
+ /*
289
+ Function for building the s2Member Info page.
290
+ */
291
+ function ws_plugin__s2member_info_page ()
292
+ {
293
+ include_once dirname (dirname (__FILE__)) . "/menu-pages/info.inc.php";
294
+ /**/
295
+ return;
296
+ }
297
+ ?>
includes/functions/min-level-4-downloads.inc.php ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Function determines the minimum level required for file download access.
18
+ Returns 0-4, where 0 means no access to file downloads has been allowed.
19
+ */
20
+ function ws_plugin__s2member_min_level_4_downloads ()
21
+ {
22
+ if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_file_downloads_allowed"] && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_file_downloads_allowed_days"])
23
+ {
24
+ $file_download_access_is_allowed = $minimum_level_required_to_download_files = 1;
25
+ }
26
+ else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_file_downloads_allowed"] && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_file_downloads_allowed_days"])
27
+ {
28
+ $file_download_access_is_allowed = $minimum_level_required_to_download_files = 2;
29
+ }
30
+ else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_file_downloads_allowed"] && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_file_downloads_allowed_days"])
31
+ {
32
+ $file_download_access_is_allowed = $minimum_level_required_to_download_files = 3;
33
+ }
34
+ else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_file_downloads_allowed"] && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_file_downloads_allowed_days"])
35
+ {
36
+ $file_download_access_is_allowed = $minimum_level_required_to_download_files = 4;
37
+ }
38
+ /**/
39
+ return (int)$minimum_level_required_to_download_files;
40
+ }
41
+ ?>
includes/functions/nocache.inc.php ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Handles no-cache headers and compatible constants for s2Member.
18
+ This is compatible with Quick Cache and also with WP Super Cache.
19
+ Attach to: add_action("init");
20
+ */
21
+ function ws_plugin__s2member_nocache ()
22
+ {
23
+ ws_plugin__s2member_nocache_constants () . ws_plugin__s2member_nocache_headers ();
24
+ /**/
25
+ return;
26
+ }
27
+ /*
28
+ Define compatible nocache constants for s2Member.
29
+ This is compatible with Quick Cache and also with WP Super Cache.
30
+ Quick Cache uses: QUICK_CACHE_ALLOWED, and Super Cache uses: DONOTCACHEPAGE.
31
+ Actually, Quick Cache is compatible with either of these defined constants.
32
+
33
+ Always disallow caching for logged in users and GET requests with /?s2member systematic use.
34
+ For clarity on the systematic use with s2member in the request, see: is-systematic.inc.php.
35
+ - Also disallow caching if the $nocache param is passed in as true by other routines.
36
+ * BUT, always obey s2AC and qcAC params that specifically allow caching.
37
+
38
+ This function is also called upon by other routines that protect members-only content areas.
39
+ Members-only content areas should never be cached. In other words, there are some important supplemental
40
+ routines that occur outside the scope of this single function. This function is called upon by those other
41
+ targeted routines, to handle the nocache constants when they are required.
42
+
43
+ These additional supplemental routines, include:
44
+ - ws_plugin__s2member_check_ruri_level_access()
45
+ - ws_plugin__s2member_check_catg_level_access()
46
+ - ws_plugin__s2member_check_ptag_level_access()
47
+ - ws_plugin__s2member_check_post_level_access()
48
+ - ws_plugin__s2member_check_page_level_access()
49
+ */
50
+ function ws_plugin__s2member_nocache_constants ($nocache = FALSE) /* Always obey the s2AC & qcAC params. */
51
+ {
52
+ if (!$_GET["s2AC"] && !$_GET["qcAC"] && ($nocache || is_user_logged_in () || (preg_match ("/^s2member/", $_SERVER["QUERY_STRING"]) && ($_SERVER["REQUEST_URI"] === "/" || strtolower (rtrim (get_bloginfo ("url"), "/")) === rtrim (strtolower ("http://" . $_SERVER["HTTP_HOST"]) . $_SERVER["REQUEST_URI"], "/")))))
53
+ {
54
+ define ("QUICK_CACHE_ALLOWED", false) . define ("DONOTCACHEPAGE", true);
55
+ }
56
+ /**/
57
+ return;
58
+ }
59
+ /*
60
+ Sends Cache-Control ( no-cache ) headers.
61
+ This uses the nocache_headers() function provided by WordPress®.
62
+ This is compatible with the Quick Cache parameter ?qcABC=1 as well.
63
+ * Always obey s2ABC & qcABC params that specifically allow browser caching.
64
+ */
65
+ function ws_plugin__s2member_nocache_headers () /* Cache-Control header. */
66
+ {
67
+ if (!$_GET["s2ABC"] && !$_GET["qcABC"]) /* Always obey. */
68
+ {
69
+ if (is_array ($headers = headers_list ()))
70
+ foreach ($headers as $k => $header)
71
+ if (preg_match ("/no-cache/i", $header))
72
+ $no_cache_already_sent = true;
73
+ /**/
74
+ if (!$no_cache_already_sent)
75
+ nocache_headers ();
76
+ }
77
+ /**/
78
+ return;
79
+ }
80
+ ?>
includes/functions/page-level-access.inc.php ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Function for handling page level access permissions.
18
+ Attach to: add_action("template_redirect");
19
+ */
20
+ function ws_plugin__s2member_check_page_level_access ()
21
+ {
22
+ global $post; /* get_the_ID() not yet available here. */
23
+ /**/
24
+ if (is_page () && is_object ($post) && ($page_ID = $post->ID))
25
+ {
26
+ $current_user = (is_user_logged_in ()) ? wp_get_current_user () : false;
27
+ /**/
28
+ if ($page_ID == $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"] && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || (!current_user_can ("access_s2member_level1") && !$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["allow_subscribers_in"])) && $page_ID != $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"] && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=1")) !== "nill")
29
+ exit;
30
+ /**/
31
+ else if ($page_ID == $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["file_download_limit_exceeded_page"] && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level1")) && $page_ID != $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"] && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=1")) !== "nill")
32
+ exit;
33
+ /**/
34
+ else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_pages"] === "all" && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level1")) && !ws_plugin__s2member_is_systematic_use_page () && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=1")) !== "nill")
35
+ exit;
36
+ /**/
37
+ else if (in_array ($page_ID, preg_split ("/,/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_pages"])) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level1")) && !ws_plugin__s2member_is_systematic_use_page () && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=1")) !== "nill")
38
+ exit;
39
+ /**/
40
+ else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_pages"] === "all" && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level2")) && !ws_plugin__s2member_is_systematic_use_page () && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=2")) !== "nill")
41
+ exit;
42
+ /**/
43
+ else if (in_array ($page_ID, preg_split ("/,/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_pages"])) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level2")) && !ws_plugin__s2member_is_systematic_use_page () && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=2")) !== "nill")
44
+ exit;
45
+ /**/
46
+ else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_pages"] === "all" && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level3")) && !ws_plugin__s2member_is_systematic_use_page () && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=3")) !== "nill")
47
+ exit;
48
+ /**/
49
+ else if (in_array ($page_ID, preg_split ("/,/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_pages"])) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level3")) && !ws_plugin__s2member_is_systematic_use_page () && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=3")) !== "nill")
50
+ exit;
51
+ /**/
52
+ else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_pages"] === "all" && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level4")) && !ws_plugin__s2member_is_systematic_use_page () && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=4")) !== "nill")
53
+ exit;
54
+ /**/
55
+ else if (in_array ($page_ID, preg_split ("/,/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_pages"])) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level4")) && !ws_plugin__s2member_is_systematic_use_page () && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=4")) !== "nill")
56
+ exit;
57
+ }
58
+ /**/
59
+ return;
60
+ }
61
+ ?>
includes/functions/paypal-notify.inc.php ADDED
@@ -0,0 +1,301 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Handles paypal ipn url processing.
18
+ Attach to: add_action("init");
19
+ */
20
+ function ws_plugin__s2member_paypal_notify ()
21
+ {
22
+ if ($_GET["s2member_paypal_notify"] && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])
23
+ {
24
+ global $wpdb; /* Need this global variable as a reference to the database object. */
25
+ /**/
26
+ if (is_object ($wpdb) && is_array ($paypal = ws_plugin__s2member_paypal_postvars ()))
27
+ {
28
+ $paypal["s2member_log"][] = "s2Member POST vars verified through a POST back to PayPal®.";
29
+ /**/
30
+ if (preg_match ("/^" . preg_quote ($_SERVER["HTTP_HOST"], "/") . "/i", $paypal["custom"])) /* Matches originating host? */
31
+ { /* The business address validation was removed from this routine, because PayPal® always fills that with the primary
32
+ email address. In cases where an alternate PayPal® address is being paid, validation is not possible. */
33
+ $paypal["s2member_log"][] = "s2Member originating domain ( _SERVER[HTTP_HOST] ) validated.";
34
+ /**/
35
+ if (preg_match ("/^(web_accept|subscr_signup)$/i", $paypal["txn_type"]) && $paypal["payer_email"] && ($paypal["subscr_id"] || ($paypal["subscr_id"] = $paypal["txn_id"])) && preg_match ("/^[1-4]$/", $paypal["item_number"]))
36
+ {
37
+ $paypal["s2member_log"][] = "s2Member txn_type identified as (web_accept|subscr_signup).";
38
+ /**/
39
+ if (preg_match ("/(updat|upgrad)/i", $paypal["option_name1"]) && $paypal["option_selection1"]) /* This is an advanced way to handle subscription update modifications. */
40
+ /* 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
41
+ modify=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 their existing account. */
42
+ {
43
+ $paypal["s2member_log"][] = "s2Member txn_type identified as (web_accept|subscr_signup) w/ update vars.";
44
+ /**/
45
+ /* Here we need to check for both the old & new s2member_subscr_id's, just in case the Return routine has already changed it. */
46
+ if (($q = $wpdb->get_row ("SELECT `user_id` FROM `" . $wpdb->usermeta . "` WHERE `meta_key` = 's2member_subscr_id' AND (`meta_value` = '" . $wpdb->escape ($paypal["option_selection1"]) . "' OR `meta_value` = '" . $wpdb->escape ($paypal["subscr_id"]) . "') LIMIT 1"))/**/
47
+ || ($q = $wpdb->get_row ("SELECT `ID` AS `user_id` FROM `" . $wpdb->users . "` WHERE `ID` = '" . $wpdb->escape ($paypal["option_selection1"]) . "' LIMIT 1")))
48
+ {
49
+ if ($user_id = $q->user_id) /* Got it! */
50
+ {
51
+ $user = new WP_User ($user_id);
52
+ $user->set_role ("s2member_level" . $paypal["item_number"]);
53
+ update_usermeta ($user_id, "s2member_subscr_id", $paypal["subscr_id"]);
54
+ update_usermeta ($user_id, "s2member_custom", $paypal["custom"]);
55
+ delete_usermeta ($user_id, "s2member_file_download_access_arc");
56
+ delete_usermeta ($user_id, "s2member_file_download_access_log");
57
+ /**/
58
+ $paypal["s2member_log"][] = "s2Member level updated w/ advanced update routines.";
59
+ }
60
+ else
61
+ {
62
+ $paypal["s2member_log"][] = "Unable to get user_id from the DB.";
63
+ }
64
+ }
65
+ else
66
+ {
67
+ $paypal["s2member_log"][] = "Unable to find subscription/subscriber in the DB.";
68
+ }
69
+ }
70
+ else /* Else this is a normal subscription signup, we are not updating anything for a past subscription. */
71
+ {
72
+ $paypal["s2member_log"][] = "s2Member txn_type identified as (web_accept|subscr_signup) w/o update vars.";
73
+ /**/
74
+ if ($subscr_id_custom_item_number_xencrypted = ws_plugin__s2member_xencrypt ("subscr_id_custom_item_number:.:|:.:" . $paypal["subscr_id"] . ":.:|:.:" . $paypal["custom"] . ":.:|:.:" . $paypal["item_number"]))
75
+ {
76
+ if ($tinyurl = @file_get_contents ("http://tinyurl.com/api-create.php?url=" . rawurlencode (get_bloginfo ("url") . "/?s2member_paypal_register=" . urlencode ($subscr_id_custom_item_number_xencrypted))))
77
+ {
78
+ if (is_array ($cv = preg_split ("/\|/", $paypal["custom"]))) /* Values passed through the "custom" field to PayPal. */
79
+ {
80
+ $sbj = preg_replace ("/%%registration_url%%/i", $tinyurl, $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["signup_email_subject"]);
81
+ $msg = preg_replace ("/%%registration_url%%/i", $tinyurl, $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["signup_email_message"]);
82
+ /**/
83
+ if (preg_match ("/^web_accept$/i", $paypal["txn_type"]))
84
+ {
85
+ $paypal["period3"] = "1 L"; /* 1 Lifetime. */
86
+ $paypal["amount3"] = $paypal["payment_gross"];
87
+ }
88
+ /**/
89
+ $initial_term = $paypal["period1"] ? $paypal["period1"] : "0 D"; /* Do not allow the initial period to be empty. */
90
+ $initial = (isset ($paypal["amount1"]) && preg_match ("/^[1-9]/", $paypal["period1"])) ? $paypal["amount1"] : $paypal["amount3"];
91
+ $regular = $paypal["amount3"]; /* This is the regular payment amount that is charged to the customer. Always required by PayPal. */
92
+ $recurring = ($paypal["recurring"]) ? $paypal["amount3"] : "0"; /* If non-recurring, this should be zero, otherwise regular. */
93
+ /* The initial amount will only be $0 if a trial was offered. If no trial was offered, they were charged a regular rate. */
94
+ if (($sbj = preg_replace ("/%%cv([0-9]+)%%/ei", 'urlencode(trim($cv[$1]))', $sbj)) && ($sbj = preg_replace ("/%%subscr_id%%/i", urlencode ($paypal["subscr_id"]), $sbj)))
95
+ if (($sbj = preg_replace ("/%%initial%%/i", urlencode ($initial), $sbj)) && ($sbj = preg_replace ("/%%recurring%%/i", urlencode ($recurring), $sbj))) /* Adv calculations. */
96
+ if (($sbj = preg_replace ("/%%regular%%/i", urlencode ($regular), $sbj))) /* This is provided mostly for rare cases where a trial is offered, and there is NO recurrence. */
97
+ /* In cases where there is a free trial offered, and no recurring charges either ( could happen ), both initial & recurring are 0. So regular should be reported then. */
98
+ if (($sbj = preg_replace ("/%%initial_term%%/i", urlencode ($initial_term), $sbj)) && ($sbj = preg_replace ("/%%regular_term%%/i", urlencode ($paypal["period3"]), $sbj)))
99
+ if (($sbj = preg_replace ("/%%item_number%%/i", urlencode ($paypal["item_number"]), $sbj)) && ($sbj = preg_replace ("/%%item_name%%/i", urlencode ($paypal["item_name"]), $sbj)))
100
+ if (($sbj = preg_replace ("/%%first_name%%/i", urlencode ($paypal["first_name"]), $sbj)) && ($sbj = preg_replace ("/%%last_name%%/i", urlencode ($paypal["last_name"]), $sbj)))
101
+ if (($sbj = preg_replace ("/%%full_name%%/i", urlencode (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $sbj)))
102
+ if (($sbj = preg_replace ("/%%payer_email%%/i", urlencode ($paypal["payer_email"]), $sbj)) && ($sbj = trim ($sbj)))
103
+ if (($msg = preg_replace ("/%%cv([0-9]+)%%/ei", 'urlencode(trim($cv[$1]))', $msg)) && ($msg = preg_replace ("/%%subscr_id%%/i", urlencode ($paypal["subscr_id"]), $msg)))
104
+ if (($msg = preg_replace ("/%%initial%%/i", urlencode ($initial), $msg)) && ($msg = preg_replace ("/%%recurring%%/i", urlencode ($recurring), $msg))) /* Adv calculations. */
105
+ if (($msg = preg_replace ("/%%regular%%/i", urlencode ($regular), $msg))) /* This is provided mostly for rare cases where a trial is offered, and there is NO recurrence. */
106
+ /* In cases where there is a free trial offered, and no recurring charges either ( could happen ), both initial & recurring are 0. So regular should be reported then. */
107
+ if (($msg = preg_replace ("/%%initial_term%%/i", urlencode ($initial_term), $msg)) && ($msg = preg_replace ("/%%regular_term%%/i", urlencode ($paypal["period3"]), $msg)))
108
+ if (($msg = preg_replace ("/%%item_number%%/i", urlencode ($paypal["item_number"]), $msg)) && ($msg = preg_replace ("/%%item_name%%/i", urlencode ($paypal["item_name"]), $msg)))
109
+ if (($msg = preg_replace ("/%%first_name%%/i", urlencode ($paypal["first_name"]), $msg)) && ($msg = preg_replace ("/%%last_name%%/i", urlencode ($paypal["last_name"]), $msg)))
110
+ if (($msg = preg_replace ("/%%full_name%%/i", urlencode (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $msg)))
111
+ if (($msg = preg_replace ("/%%payer_email%%/i", urlencode ($paypal["payer_email"]), $msg)) && ($msg = trim ($msg)))
112
+ @mail ($paypal["payer_email"], $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", "-f " . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"]);
113
+ /**/
114
+ $paypal["s2member_log"][] = "Email sent after signup, ( w/tiny URL ) to assist customer w/ registration.";
115
+ }
116
+ }
117
+ else if ($longurl = get_bloginfo ("url") . "/?s2member_paypal_register=" . urlencode ($subscr_id_custom_item_number_xencrypted))
118
+ {
119
+ if (is_array ($cv = preg_split ("/\|/", $paypal["custom"]))) /* Values passed through the "custom" field to PayPal. */
120
+ {
121
+ $sbj = preg_replace ("/%%registration_url%%/i", $longurl, $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["signup_email_subject"]);
122
+ $msg = preg_replace ("/%%registration_url%%/i", $longurl, $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["signup_email_message"]);
123
+ /**/
124
+ if (preg_match ("/^web_accept$/i", $paypal["txn_type"]))
125
+ {
126
+ $paypal["period3"] = "1 L"; /* 1 Lifetime. */
127
+ $paypal["amount3"] = $paypal["payment_gross"];
128
+ }
129
+ /**/
130
+ $initial_term = $paypal["period1"] ? $paypal["period1"] : "0 D"; /* Do not allow the initial period to be empty. */
131
+ $initial = (isset ($paypal["amount1"]) && preg_match ("/^[1-9]/", $paypal["period1"])) ? $paypal["amount1"] : $paypal["amount3"];
132
+ $regular = $paypal["amount3"]; /* This is the regular payment amount that is charged to the customer. Always required by PayPal. */
133
+ $recurring = ($paypal["recurring"]) ? $paypal["amount3"] : "0"; /* If non-recurring, this should be zero, otherwise regular. */
134
+ /* The initial amount will only be $0 if a trial was offered. If no trial was offered, they were charged a regular rate. */
135
+ if (($sbj = preg_replace ("/%%cv([0-9]+)%%/ei", 'urlencode(trim($cv[$1]))', $sbj)) && ($sbj = preg_replace ("/%%subscr_id%%/i", urlencode ($paypal["subscr_id"]), $sbj)))
136
+ if (($sbj = preg_replace ("/%%initial%%/i", urlencode ($initial), $sbj)) && ($sbj = preg_replace ("/%%recurring%%/i", urlencode ($recurring), $sbj))) /* Adv calculations. */
137
+ if (($sbj = preg_replace ("/%%regular%%/i", urlencode ($regular), $sbj))) /* This is provided mostly for rare cases where a trial is offered, and there is NO recurrence. */
138
+ /* In cases where there is a free trial offered, and no recurring charges either ( could happen ), both initial & recurring are 0. So regular should be reported then. */
139
+ if (($sbj = preg_replace ("/%%initial_term%%/i", urlencode ($initial_term), $sbj)) && ($sbj = preg_replace ("/%%regular_term%%/i", urlencode ($paypal["period3"]), $sbj)))
140
+ if (($sbj = preg_replace ("/%%item_number%%/i", urlencode ($paypal["item_number"]), $sbj)) && ($sbj = preg_replace ("/%%item_name%%/i", urlencode ($paypal["item_name"]), $sbj)))
141
+ if (($sbj = preg_replace ("/%%first_name%%/i", urlencode ($paypal["first_name"]), $sbj)) && ($sbj = preg_replace ("/%%last_name%%/i", urlencode ($paypal["last_name"]), $sbj)))
142
+ if (($sbj = preg_replace ("/%%full_name%%/i", urlencode (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $sbj)))
143
+ if (($sbj = preg_replace ("/%%payer_email%%/i", urlencode ($paypal["payer_email"]), $sbj)) && ($sbj = trim ($sbj)))
144
+ if (($msg = preg_replace ("/%%cv([0-9]+)%%/ei", 'urlencode(trim($cv[$1]))', $msg)) && ($msg = preg_replace ("/%%subscr_id%%/i", urlencode ($paypal["subscr_id"]), $msg)))
145
+ if (($msg = preg_replace ("/%%initial%%/i", urlencode ($initial), $msg)) && ($msg = preg_replace ("/%%recurring%%/i", urlencode ($recurring), $msg))) /* Adv calculations. */
146
+ if (($msg = preg_replace ("/%%regular%%/i", urlencode ($regular), $msg))) /* This is provided mostly for rare cases where a trial is offered, and there is NO recurrence. */
147
+ /* In cases where there is a free trial offered, and no recurring charges either ( could happen ), both initial & recurring are 0. So regular should be reported then. */
148
+ if (($msg = preg_replace ("/%%initial_term%%/i", urlencode ($initial_term), $msg)) && ($msg = preg_replace ("/%%regular_term%%/i", urlencode ($paypal["period3"]), $msg)))
149
+ if (($msg = preg_replace ("/%%item_number%%/i", urlencode ($paypal["item_number"]), $msg)) && ($msg = preg_replace ("/%%item_name%%/i", urlencode ($paypal["item_name"]), $msg)))
150
+ if (($msg = preg_replace ("/%%first_name%%/i", urlencode ($paypal["first_name"]), $msg)) && ($msg = preg_replace ("/%%last_name%%/i", urlencode ($paypal["last_name"]), $msg)))
151
+ if (($msg = preg_replace ("/%%full_name%%/i", urlencode (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $msg)))
152
+ if (($msg = preg_replace ("/%%payer_email%%/i", urlencode ($paypal["payer_email"]), $msg)) && ($msg = trim ($msg)))
153
+ @mail ($paypal["payer_email"], $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", "-f " . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"]);
154
+ /**/
155
+ $paypal["s2member_log"][] = "Email sent after signup, ( w/long URL ) to assist customer w/ registration.";
156
+ }
157
+ }
158
+ }
159
+ }
160
+ /**/
161
+ if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["signup_notification_urls"] && is_array ($cv = preg_split ("/\|/", $paypal["custom"])))
162
+ {
163
+ if (preg_match ("/^web_accept$/i", $paypal["txn_type"]))
164
+ {
165
+ $paypal["period3"] = "1 L"; /* 1 Lifetime. */
166
+ $paypal["amount3"] = $paypal["payment_gross"];
167
+ }
168
+ /**/
169
+ $initial_term = $paypal["period1"] ? $paypal["period1"] : "0 D"; /* Do not allow the initial period to be empty. */
170
+ $initial = (isset ($paypal["amount1"]) && preg_match ("/^[1-9]/", $paypal["period1"])) ? $paypal["amount1"] : $paypal["amount3"];
171
+ $regular = $paypal["amount3"]; /* This is the regular payment amount that is charged to the customer. Always required by PayPal. */
172
+ $recurring = ($paypal["recurring"]) ? $paypal["amount3"] : "0"; /* If non-recurring, this should be zero, otherwise regular. */
173
+ /* The initial amount will only be $0 if a trial was offered. If no trial was offered, they were charged a regular rate. */
174
+ foreach (preg_split ("/[\r\n\t]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["signup_notification_urls"]) as $url)
175
+ if (($url = preg_replace ("/%%cv([0-9]+)%%/ei", 'urlencode(trim($cv[$1]))', $url)) && ($url = preg_replace ("/%%subscr_id%%/i", urlencode ($paypal["subscr_id"]), $url)))
176
+ if (($url = preg_replace ("/%%initial%%/i", urlencode ($initial), $url)) && ($url = preg_replace ("/%%recurring%%/i", urlencode ($recurring), $url))) /* Adv calculations. */
177
+ if (($url = preg_replace ("/%%regular%%/i", urlencode ($regular), $url))) /* This is provided mostly for rare cases where a trial is offered, and there is NO recurrence. */
178
+ /* In cases where there is a free trial offered, and no recurring charges either ( could happen ), both initial & recurring are 0. So regular should be reported then. */
179
+ if (($url = preg_replace ("/%%initial_term%%/i", urlencode ($initial_term), $url)) && ($url = preg_replace ("/%%regular_term%%/i", urlencode ($paypal["period3"]), $url)))
180
+ if (($url = preg_replace ("/%%item_number%%/i", urlencode ($paypal["item_number"]), $url)) && ($url = preg_replace ("/%%item_name%%/i", urlencode ($paypal["item_name"]), $url)))
181
+ if (($url = preg_replace ("/%%first_name%%/i", urlencode ($paypal["first_name"]), $url)) && ($url = preg_replace ("/%%last_name%%/i", urlencode ($paypal["last_name"]), $url)))
182
+ if (($url = preg_replace ("/%%full_name%%/i", urlencode (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $url)))
183
+ if (($url = preg_replace ("/%%payer_email%%/i", urlencode ($paypal["payer_email"]), $url)))
184
+ if (($url = trim ($url))) /* Make sure it is not empty now. */
185
+ ws_plugin__s2member_curlpsr ($url, "s2member=1");
186
+ /**/
187
+ $paypal["s2member_log"][] = "Signup notification URLs have been processed.";
188
+ }
189
+ }
190
+ else if (preg_match ("/^subscr_modify$/i", $paypal["txn_type"]) && $paypal["subscr_id"] && preg_match ("/^[1-4]$/", $paypal["item_number"]))
191
+ {
192
+ $paypal["s2member_log"][] = "s2Member txn_type identified as subscr_modify.";
193
+ /**/
194
+ if ($q = $wpdb->get_row ("SELECT `user_id` FROM `" . $wpdb->usermeta . "` WHERE `meta_key` = 's2member_subscr_id' AND `meta_value` = '" . $wpdb->escape ($paypal["subscr_id"]) . "' LIMIT 1"))
195
+ {
196
+ if ($user_id = $q->user_id) /* Got it! */
197
+ {
198
+ $user = new WP_User ($user_id);
199
+ $user->set_role ("s2member_level" . $paypal["item_number"]);
200
+ update_usermeta ($user_id, "s2member_custom", $paypal["custom"]);
201
+ /**/
202
+ $paypal["s2member_log"][] = "s2Member level updated on subscription modification.";
203
+ }
204
+ else
205
+ {
206
+ $paypal["s2member_log"][] = "Unable to get user_id from the DB.";
207
+ }
208
+ }
209
+ else
210
+ {
211
+ $paypal["s2member_log"][] = "Unable to find subscription in the DB.";
212
+ }
213
+ }
214
+ else if (preg_match ("/^subscr_payment$/i", $paypal["txn_type"]) && $paypal["payer_email"] && $paypal["subscr_id"] && preg_match ("/^[1-4]$/", $paypal["item_number"]) && $paypal["txn_id"] && $paypal["payment_gross"])
215
+ {
216
+ $paypal["s2member_log"][] = "s2Member txn_type identified as subscr_payment.";
217
+ /**/
218
+ if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["payment_notification_urls"] && is_array ($cv = preg_split ("/\|/", $paypal["custom"])))
219
+ {
220
+ foreach (preg_split ("/[\r\n\t]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["payment_notification_urls"]) as $url)
221
+ if (($url = preg_replace ("/%%cv([0-9]+)%%/ei", 'urlencode(trim($cv[$1]))', $url)) && ($url = preg_replace ("/%%subscr_id%%/i", urlencode ($paypal["subscr_id"]), $url)))
222
+ if (($url = preg_replace ("/%%amount%%/i", urlencode ($paypal["payment_gross"]), $url)) && ($url = preg_replace ("/%%txn_id%%/i", urlencode ($paypal["txn_id"]), $url)))
223
+ if (($url = preg_replace ("/%%item_number%%/i", urlencode ($paypal["item_number"]), $url)) && ($url = preg_replace ("/%%item_name%%/i", urlencode ($paypal["item_name"]), $url)))
224
+ if (($url = preg_replace ("/%%first_name%%/i", urlencode ($paypal["first_name"]), $url)) && ($url = preg_replace ("/%%last_name%%/i", urlencode ($paypal["last_name"]), $url)))
225
+ if (($url = preg_replace ("/%%full_name%%/i", urlencode (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $url)))
226
+ if (($url = preg_replace ("/%%payer_email%%/i", urlencode ($paypal["payer_email"]), $url)))
227
+ if (($url = trim ($url))) /* Make sure it is not empty now. */
228
+ ws_plugin__s2member_curlpsr ($url, "s2member=1");
229
+ /**/
230
+ $paypal["s2member_log"][] = "Payment notification URLs have been processed.";
231
+ }
232
+ }
233
+ else if ((preg_match ("/^subscr_eot$/i", $paypal["txn_type"]) || preg_match ("/^(refunded|reversed)$/i", $paypal["payment_status"])) && ($paypal["subscr_id"] || ($paypal["subscr_id"] = $paypal["parent_txn_id"])) && preg_match ("/^[1-4]$/", $paypal["item_number"]))
234
+ {
235
+ $paypal["s2member_log"][] = "s2Member txn_type identified as subscr_eot - or - payment_status (refunded|reversed).";
236
+ /**/
237
+ if ($q = $wpdb->get_row ("SELECT `user_id` FROM `" . $wpdb->usermeta . "` WHERE `meta_key` = 's2member_subscr_id' AND `meta_value` = '" . $wpdb->escape ($paypal["subscr_id"]) . "' LIMIT 1"))
238
+ {
239
+ if ($user_id = $q->user_id) /* Delete the user. Note that `ws_plugin__s2member_handle_user_deletions()` is fired too; it handles the `eot_del_notification_urls`. */
240
+ {
241
+ wp_delete_user ($user_id); /* This triggers `ws_plugin__s2member_handle_user_deletions()` */
242
+ /**/
243
+ $paypal["s2member_log"][] = "User account automatically deleted from the system.";
244
+ /**/
245
+ $paypal["s2member_log"][] = "EOT/Deletion notification URLs have been processed.";
246
+ }
247
+ else
248
+ {
249
+ $paypal["s2member_log"][] = "Unable to get user_id from the DB.";
250
+ }
251
+ /**/
252
+ if (!preg_match ("/^subscr_eot$/i", $paypal["txn_type"]) && preg_match ("/^(refunded|reversed)$/i", $paypal["payment_status"]) && $paypal["parent_txn_id"])
253
+ {
254
+ if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["ref_rev_notification_urls"] && is_array ($cv = preg_split ("/\|/", $paypal["custom"])))
255
+ {
256
+ foreach (preg_split ("/[\r\n\t]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["ref_rev_notification_urls"]) as $url)
257
+ if (($url = preg_replace ("/%%cv([0-9]+)%%/ei", 'urlencode(trim($cv[$1]))', $url)) && ($url = preg_replace ("/%%subscr_id%%/i", urlencode ($paypal["subscr_id"]), $url)))
258
+ if (($url = preg_replace ("/%%-amount%%/i", urlencode ($paypal["payment_gross"]), $url)) && ($url = preg_replace ("/%%parent_txn_id%%/i", urlencode ($paypal["parent_txn_id"]), $url)))
259
+ if (($url = preg_replace ("/%%item_number%%/i", urlencode ($paypal["item_number"]), $url)) && ($url = preg_replace ("/%%item_name%%/i", urlencode ($paypal["item_name"]), $url)))
260
+ if (($url = preg_replace ("/%%first_name%%/i", urlencode ($paypal["first_name"]), $url)) && ($url = preg_replace ("/%%last_name%%/i", urlencode ($paypal["last_name"]), $url)))
261
+ if (($url = preg_replace ("/%%full_name%%/i", urlencode (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $url)))
262
+ if (($url = preg_replace ("/%%payer_email%%/i", urlencode ($paypal["payer_email"]), $url)))
263
+ if (($url = trim ($url))) /* Make sure it is not empty now. */
264
+ ws_plugin__s2member_curlpsr ($url, "s2member=1");
265
+ /**/
266
+ $paypal["s2member_log"][] = "Refund/Reversal notification URLs have been processed.";
267
+ }
268
+ }
269
+ }
270
+ else
271
+ {
272
+ $paypal["s2member_log"][] = "Unable to find subscription in the DB.";
273
+ }
274
+ }
275
+ else
276
+ {
277
+ $paypal["s2member_log"][] = "The txn_type does not require any action on the part of s2Member.";
278
+ }
279
+ }
280
+ else
281
+ {
282
+ $paypal["s2member_log"][] = "Unable to verify _SERVER[HTTP_HOST].";
283
+ }
284
+ }
285
+ else
286
+ {
287
+ $paypal["s2member_log"][] = "Unable to verify POST vars.";
288
+ }
289
+ /**/
290
+ if ($_GET["s2member_paypal_proxy"]) /* For proxy identification. */
291
+ $paypal["s2member_paypal_proxy"] = $_GET["s2member_paypal_proxy"];
292
+ /**/
293
+ if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_debug"])
294
+ if (is_dir ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"]))
295
+ if (is_writable ($logs_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"]))
296
+ file_put_contents ($logs_dir . "/paypal-ipn.log", var_export ($paypal, true) . "\n\n", FILE_APPEND);
297
+ /**/
298
+ exit;
299
+ }
300
+ }
301
+ ?>
includes/functions/paypal-postvars.inc.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Get post vars from paypal, verify and return array.
18
+ */
19
+ function ws_plugin__s2member_paypal_postvars ()
20
+ {
21
+ if ($_GET["tx"]) /* PDT with Auto-Return. */
22
+ {
23
+ if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_identity_token"])
24
+ {
25
+ $postback = "cmd=_notify-synch";
26
+ /**/
27
+ $postback .= "&tx=" . urlencode ($_GET["tx"]);
28
+ $postback .= "&at=" . urlencode ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_identity_token"]);
29
+ /**/
30
+ $endpoint = ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com";
31
+ /**/
32
+ if (preg_match ("/^SUCCESS/i", ($response = trim (ws_plugin__s2member_curlpsr ("https://" . $endpoint . "/cgi-bin/webscr", $postback)))))
33
+ {
34
+ foreach (preg_split ("/[\r\n]+/", preg_replace ("/^SUCCESS/i", "", $response)) as $varline)
35
+ {
36
+ list ($key, $value) = preg_split ("/\=/", $varline, 2);
37
+ if (strlen ($key = trim ($key)) && strlen ($value = trim ($value)))
38
+ $postvars[$key] = trim (stripslashes (urldecode ($value)));
39
+ }
40
+ /**/
41
+ return $postvars;
42
+ }
43
+ }
44
+ /**/
45
+ return false;
46
+ }
47
+ else if (is_array ($postvars = stripslashes_deep ($_POST)))
48
+ {
49
+ $postback = "cmd=_notify-validate";
50
+ /**/
51
+ foreach ($postvars as $key => $value)
52
+ $postback .= "&" . $key . "=" . urlencode ($value);
53
+ /**/
54
+ foreach ($postvars as $key => $value)
55
+ $postvars[$key] = trim ($value);
56
+ /**/
57
+ $endpoint = ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com";
58
+ /**/
59
+ if (strtolower (trim (ws_plugin__s2member_curlpsr ("https://" . $endpoint . "/cgi-bin/webscr", $postback))) === "verified")
60
+ {
61
+ return $postvars;
62
+ }
63
+ /**/
64
+ return false;
65
+ }
66
+ else /* Unable to obtain. */
67
+ {
68
+ return false;
69
+ }
70
+ }
71
+ ?>
includes/functions/paypal-register.inc.php ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Handles paypal registration links.
18
+ Attach to: add_action("init");
19
+ */
20
+ function ws_plugin__s2member_paypal_register ()
21
+ {
22
+ if ($_GET["s2member_paypal_register"])
23
+ {
24
+ if (is_array ($registered = preg_split ("/\:\.\:\|\:\.\:/", ws_plugin__s2member_xdecrypt ($_GET["s2member_paypal_register"]))))
25
+ {
26
+ if (count ($registered) === 4 && $registered[0] === "subscr_id_custom_item_number" && $registered[1] && $registered[2] && $registered[3])
27
+ {
28
+ setcookie ("s2member_subscr_id", $registered[1], time () + 31556926, "/");
29
+ setcookie ("s2member_custom", $registered[2], time () + 31556926, "/");
30
+ setcookie ("s2member_level", $registered[3], time () + 31556926, "/");
31
+ /**/
32
+ echo '<script type="text/javascript">' . "\n";
33
+ echo "window.location = '" . esc_js (add_query_arg ("action", "register", wp_login_url ())) . "';";
34
+ echo '</script>' . "\n";
35
+ }
36
+ }
37
+ exit;
38
+ }
39
+ }
40
+ ?>
includes/functions/paypal-return.inc.php ADDED
@@ -0,0 +1,274 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Handles paypal return url processing.
18
+ Attach to: add_action("init");
19
+ */
20
+ function ws_plugin__s2member_paypal_return ()
21
+ {
22
+ /* Note: Auto-Return with PDT does not send anything when subscriptions are modified.
23
+ Therefore, we need to be sure that we always send a thank you message here by default,
24
+ and then we'll just leave the rest of the modification up to the IPN handler instead. */
25
+ if ($_GET["s2member_paypal_return"] && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])
26
+ {
27
+ global $wpdb; /* Need this global variable as a reference to the database object. */
28
+ /**/
29
+ if (is_object ($wpdb) && is_array ($paypal = ws_plugin__s2member_paypal_postvars ()))
30
+ {
31
+ $paypal["s2member_log"][] = "s2Member POST vars verified through a POST back to PayPal®.";
32
+ /**/
33
+ if (preg_match ("/^" . preg_quote ($_SERVER["HTTP_HOST"], "/") . "/i", $paypal["custom"])) /* Matches originating host? */
34
+ { /* The business address validation was removed from this routine, because PayPal® always fills that with the primary
35
+ email address. In cases where an alternate PayPal® address is being paid, validation is not possible. */
36
+ $paypal["s2member_log"][] = "s2Member originating domain ( _SERVER[HTTP_HOST] ) validated.";
37
+ /**/
38
+ if (preg_match ("/^(web_accept|subscr_signup|subscr_payment)$/i", $paypal["txn_type"]) && ($paypal["subscr_id"] || ($paypal["subscr_id"] = $paypal["txn_id"])) && preg_match ("/^[1-4]$/", $paypal["item_number"]))
39
+ { /* With Auto-Return/PDT, PayPal will send subscr_payment instead of subscr_signup to the return URL.
40
+ So we need to look for (web_accept|subscr_signup|subscr_payment), and treat them as the same. */
41
+ $paypal["s2member_log"][] = "s2Member txn_type identified as (web_accept|subscr_signup|subscr_payment).";
42
+ /**/
43
+ if (preg_match ("/(updat|upgrad)/i", $paypal["option_name1"]) && $paypal["option_selection1"]) /* Advanced subscription update modifications. */
44
+ /* 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
45
+ modify=2 parameter to be used in those scenarios, because technically there is nothing to update. The only thing to be updated is the existing account. */
46
+ {
47
+ $paypal["s2member_log"][] = "s2Member txn_type identified as (web_accept|subscr_signup|subscr_payment) w/ update vars.";
48
+ /**/
49
+ /* Here we need to check for both the old & new s2member_subscr_id's, just in case the IPN routine has already changed it. */
50
+ if (($q = $wpdb->get_row ("SELECT `user_id` FROM `" . $wpdb->usermeta . "` WHERE `meta_key` = 's2member_subscr_id' AND (`meta_value` = '" . $wpdb->escape ($paypal["option_selection1"]) . "' OR `meta_value` = '" . $wpdb->escape ($paypal["subscr_id"]) . "') LIMIT 1"))/**/
51
+ || ($q = $wpdb->get_row ("SELECT `ID` AS `user_id` FROM `" . $wpdb->users . "` WHERE `ID` = '" . $wpdb->escape ($paypal["option_selection1"]) . "' LIMIT 1")))
52
+ {
53
+ if ($user_id = $q->user_id) /* Got it! */
54
+ {
55
+ $user = new WP_User ($user_id);
56
+ $user->set_role ("s2member_level" . $paypal["item_number"]);
57
+ update_usermeta ($user_id, "s2member_subscr_id", $paypal["subscr_id"]);
58
+ update_usermeta ($user_id, "s2member_custom", $paypal["custom"]);
59
+ delete_usermeta ($user_id, "s2member_file_download_access_arc");
60
+ delete_usermeta ($user_id, "s2member_file_download_access_log");
61
+ /**/
62
+ $paypal["s2member_log"][] = "s2Member level updated w/ advanced update routines.";
63
+ /**/
64
+ echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' . "\n";
65
+ echo '<html xmlns="http://www.w3.org/1999/xhtml" ', language_attributes (), '>' . "\n";
66
+ echo '<head profile="http://gmpg.org/xfn/11">' . "\n";
67
+ echo '<meta http-equiv="Content-Type" content="' . get_bloginfo ("html_type") . '; charset=' . get_bloginfo ("charset") . '" />' . "\n";
68
+ echo '<script type="text/javascript">' . "\n"; /* Onload allows any pixel codes to finish loading. */
69
+ echo "window.onload = function(){ " . "\n"; /* After everything has finished loading, we alert and then redirect. */
70
+ 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";
71
+ echo "window.location = '" . wp_login_url () . "'; };" . "\n";
72
+ echo '</script>' . "\n";
73
+ echo '</head>' . "\n";
74
+ /**/
75
+ echo '<body style="background:#' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_color"] . ' url(' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_image"] . ');">' . "\n";
76
+ /**/
77
+ echo '<!-- Pixel Tracking codes from the s2Member plugin for WordPress. -->' . "\n";
78
+ /**/
79
+ if (($code = trim ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["signup_pixel_tracking_codes"])) && is_array ($cv = preg_split ("/\|/", $paypal["custom"])))
80
+ {
81
+ if (preg_match ("/^subscr_signup$/i", $paypal["txn_type"]))
82
+ $initial = (isset ($paypal["amount1"]) && preg_match ("/^[1-9]/", $paypal["period1"])) ? $paypal["amount1"] : $paypal["amount3"];
83
+ /* The initial amount will only be $0 if a trial was offered. If no trial was offered, they were charged a regular rate. */
84
+ else if (preg_match ("/^(web_accept|subscr_payment)$/i", $paypal["txn_type"])) /* PDT w/Auto-Return sends subscr_payment. */
85
+ $initial = $paypal["payment_gross"]; /* Here, the initial payment is provided clearly as the payment gross. */
86
+ /**/
87
+ if (($code = preg_replace ("/%%cv([0-9]+)%%/ei", 'urlencode(trim($cv[$1]))', $code)) && ($code = preg_replace ("/%%subscr_id%%/i", urlencode ($paypal["subscr_id"]), $code)))
88
+ if (($code = preg_replace ("/%%initial%%/i", urlencode ($initial), $code))) /* Adv calculations here. We have to support both sets of variables, subscr_signup & subscr_payment. */
89
+ if (($code = preg_replace ("/%%item_number%%/i", urlencode ($paypal["item_number"]), $code)) && ($code = preg_replace ("/%%item_name%%/i", urlencode ($paypal["item_name"]), $code)))
90
+ if (($code = preg_replace ("/%%first_name%%/i", urlencode ($paypal["first_name"]), $code)) && ($code = preg_replace ("/%%last_name%%/i", urlencode ($paypal["last_name"]), $code)))
91
+ if (($code = preg_replace ("/%%full_name%%/i", urlencode (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $code)))
92
+ if (($code = preg_replace ("/%%payer_email%%/i", urlencode ($paypal["payer_email"]), $code)))
93
+ if (($code = trim ($code))) /* Make sure it is not empty now. */
94
+ echo $code . "\n"; /* Everything here must finish loading. */
95
+ /**/
96
+ $paypal["s2member_log"][] = "Signup Pixel Tracking codes have been processed.";
97
+ }
98
+ echo '<!-- Pixel Tracking codes from the s2Member plugin for WordPress. -->' . "\n";
99
+ /**/
100
+ $paypal["s2member_log"][] = "Redirecting user to login page.";
101
+ /**/
102
+ echo '</body>' . "\n";
103
+ echo '</html>';
104
+ }
105
+ else
106
+ {
107
+ $paypal["s2member_log"][] = "Unable to get user_id from the DB.";
108
+ /**/
109
+ echo '<script type="text/javascript">' . "\n";
110
+ echo "alert('Thank you very much... please click OK!');" . "\n";
111
+ echo "window.location = '" . esc_js (wp_login_url ()) . "';";
112
+ echo '</script>' . "\n";
113
+ /**/
114
+ $paypal["s2member_log"][] = "Redirecting user to login page.";
115
+ }
116
+ }
117
+ else
118
+ {
119
+ $paypal["s2member_log"][] = "Unable to find subscription/subscriber in the DB.";
120
+ /**/
121
+ echo '<script type="text/javascript">' . "\n";
122
+ echo "alert('Thank you very much... please click OK!');" . "\n";
123
+ echo "window.location = '" . esc_js (wp_login_url ()) . "';";
124
+ echo '</script>' . "\n";
125
+ /**/
126
+ $paypal["s2member_log"][] = "Redirecting user to login page.";
127
+ }
128
+ }
129
+ else /* Else this is a normal subscription signup, we are not updating anything for a past subscription. */
130
+ {
131
+ $paypal["s2member_log"][] = "s2Member txn_type identified as (web_accept|subscr_signup|subscr_payment) w/o update vars.";
132
+ /**/
133
+ setcookie ("s2member_subscr_id", $paypal["subscr_id"], time () + 31556926, "/");
134
+ setcookie ("s2member_custom", $paypal["custom"], time () + 31556926, "/");
135
+ setcookie ("s2member_level", $paypal["item_number"], time () + 31556926, "/");
136
+ /**/
137
+ $paypal["s2member_log"][] = "s2Member cookies set on (web_accept|subscr_signup|subscr_payment) w/o update vars.";
138
+ /**/
139
+ echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' . "\n";
140
+ echo '<html xmlns="http://www.w3.org/1999/xhtml" ', language_attributes (), '>' . "\n";
141
+ echo '<head profile="http://gmpg.org/xfn/11">' . "\n";
142
+ echo '<meta http-equiv="Content-Type" content="' . get_bloginfo ("html_type") . '; charset=' . get_bloginfo ("charset") . '" />' . "\n";
143
+ echo '<script type="text/javascript">' . "\n"; /* Onload allows any pixel codes to finish loading. */
144
+ echo "window.onload = function(){ " . "\n"; /* After everything has finished loading, we alert and then redirect. */
145
+ echo "alert('Thank You! Your membership has been approved.\\nThe next step is to Register a Username.\\n\\nPlease click OK to Register now.');" . "\n";/**/
146
+ echo "window.location = '" . esc_js (add_query_arg ("action", "register", wp_login_url ())) . "'; };" . "\n";
147
+ echo '</script>' . "\n";
148
+ echo '</head>' . "\n";
149
+ /**/
150
+ echo '<body style="background:#' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_color"] . ' url(' . $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_image"] . ');">' . "\n";
151
+ /**/
152
+ echo '<!-- Pixel Tracking codes from the s2Member plugin for WordPress. -->' . "\n";
153
+ /**/
154
+ if (($code = trim ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["signup_pixel_tracking_codes"])) && is_array ($cv = preg_split ("/\|/", $paypal["custom"])))
155
+ {
156
+ if (preg_match ("/^subscr_signup$/i", $paypal["txn_type"]))
157
+ $initial = (isset ($paypal["amount1"]) && preg_match ("/^[1-9]/", $paypal["period1"])) ? $paypal["amount1"] : $paypal["amount3"];
158
+ /* The initial amount will only be $0 if a trial was offered. If no trial was offered, they were charged a regular rate. */
159
+ else if (preg_match ("/^(web_accept|subscr_payment)$/i", $paypal["txn_type"])) /* PDT w/Auto-Return sends subscr_payment. */
160
+ $initial = $paypal["payment_gross"]; /* Here, the initial payment is provided clearly as the payment gross. */
161
+ /**/
162
+ if (($code = preg_replace ("/%%cv([0-9]+)%%/ei", 'urlencode(trim($cv[$1]))', $code)) && ($code = preg_replace ("/%%subscr_id%%/i", urlencode ($paypal["subscr_id"]), $code)))
163
+ if (($code = preg_replace ("/%%initial%%/i", urlencode ($initial), $code))) /* Adv calculations here. We have to support both sets of variables, subscr_signup & subscr_payment. */
164
+ if (($code = preg_replace ("/%%item_number%%/i", urlencode ($paypal["item_number"]), $code)) && ($code = preg_replace ("/%%item_name%%/i", urlencode ($paypal["item_name"]), $code)))
165
+ if (($code = preg_replace ("/%%first_name%%/i", urlencode ($paypal["first_name"]), $code)) && ($code = preg_replace ("/%%last_name%%/i", urlencode ($paypal["last_name"]), $code)))
166
+ if (($code = preg_replace ("/%%full_name%%/i", urlencode (trim ($paypal["first_name"] . " " . $paypal["last_name"])), $code)))
167
+ if (($code = preg_replace ("/%%payer_email%%/i", urlencode ($paypal["payer_email"]), $code)))
168
+ if (($code = trim ($code))) /* Make sure it is not empty now. */
169
+ echo $code . "\n"; /* Everything here must finish loading. */
170
+ /**/
171
+ $paypal["s2member_log"][] = "Signup Pixel Tracking codes have been processed.";
172
+ }
173
+ echo '<!-- Pixel Tracking codes from the s2Member plugin for WordPress. -->' . "\n";
174
+ /**/
175
+ $paypal["s2member_log"][] = "Redirecting user to registration page.";
176
+ /**/
177
+ echo '</body>' . "\n";
178
+ echo '</html>';
179
+ }
180
+ }
181
+ /**/
182
+ else if (preg_match ("/^subscr_modify$/i", $paypal["txn_type"]) && $paypal["subscr_id"] && preg_match ("/^[1-4]$/", $paypal["item_number"]))
183
+ {
184
+ $paypal["s2member_log"][] = "s2Member txn_type identified as subscr_modify.";
185
+ /**/
186
+ if ($q = $wpdb->get_row ("SELECT `user_id` FROM `" . $wpdb->usermeta . "` WHERE `meta_key` = 's2member_subscr_id' AND `meta_value` = '" . $wpdb->escape ($paypal["subscr_id"]) . "' LIMIT 1"))
187
+ {
188
+ if ($user_id = $q->user_id) /* Got it! */
189
+ {
190
+ $user = new WP_User ($user_id);
191
+ $user->set_role ("s2member_level" . $paypal["item_number"]);
192
+ update_usermeta ($user_id, "s2member_custom", $paypal["custom"]);
193
+ /**/
194
+ $paypal["s2member_log"][] = "s2Member level updated on subscription modification.";
195
+ /**/
196
+ echo '<script type="text/javascript">' . "\n";
197
+ 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";
198
+ echo "window.location = '" . esc_js (wp_login_url ()) . "';";
199
+ echo '</script>' . "\n";
200
+ /**/
201
+ $paypal["s2member_log"][] = "Redirecting user to login page.";
202
+ }
203
+ else
204
+ {
205
+ $paypal["s2member_log"][] = "Unable to get user_id from the DB.";
206
+ /**/
207
+ echo '<script type="text/javascript">' . "\n";
208
+ echo "alert('Thank you very much... please click OK!');" . "\n";
209
+ echo "window.location = '" . esc_js (wp_login_url ()) . "';";
210
+ echo '</script>' . "\n";
211
+ /**/
212
+ $paypal["s2member_log"][] = "Redirecting user to login page.";
213
+ }
214
+ }
215
+ else
216
+ {
217
+ $paypal["s2member_log"][] = "Unable to find subscription in the DB.";
218
+ /**/
219
+ echo '<script type="text/javascript">' . "\n";
220
+ echo "alert('Thank you very much... please click OK!');" . "\n";
221
+ echo "window.location = '" . esc_js (wp_login_url ()) . "';";
222
+ echo '</script>' . "\n";
223
+ /**/
224
+ $paypal["s2member_log"][] = "Redirecting user to login page.";
225
+ }
226
+ }
227
+ else
228
+ {
229
+ $paypal["s2member_log"][] = "The txn_type does not require any action on the part of s2Member.";
230
+ /**/
231
+ echo '<script type="text/javascript">' . "\n";
232
+ echo "alert('Thank you very much... please click OK!');" . "\n";
233
+ echo "window.location = '" . esc_js (wp_login_url ()) . "';";
234
+ echo '</script>' . "\n";
235
+ /**/
236
+ $paypal["s2member_log"][] = "Redirecting user to login page.";
237
+ }
238
+ }
239
+ else
240
+ {
241
+ $paypal["s2member_log"][] = "Unable to verify _SERVER[HTTP_HOST].";
242
+ /**/
243
+ echo '<script type="text/javascript">' . "\n";
244
+ echo "alert('Thank you very much... please click OK!');" . "\n";
245
+ echo "window.location = '" . esc_js (wp_login_url ()) . "';";
246
+ echo '</script>' . "\n";
247
+ /**/
248
+ $paypal["s2member_log"][] = "Redirecting user to login page.";
249
+ }
250
+ }
251
+ else
252
+ {
253
+ $paypal["s2member_log"][] = "Unable to verify POST vars.";
254
+ /**/
255
+ echo '<script type="text/javascript">' . "\n";
256
+ echo "alert('Thank you very much... please click OK!');" . "\n";
257
+ echo "window.location = '" . esc_js (wp_login_url ()) . "';";
258
+ echo '</script>' . "\n";
259
+ /**/
260
+ $paypal["s2member_log"][] = "Redirecting user to login page.";
261
+ }
262
+ /**/
263
+ if ($_GET["s2member_paypal_proxy"]) /* For proxy identification. */
264
+ $paypal["s2member_paypal_proxy"] = $_GET["s2member_paypal_proxy"];
265
+ /**/
266
+ if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_debug"])
267
+ if (is_dir ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"]))
268
+ if (is_writable ($logs_dir = $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"]))
269
+ file_put_contents ($logs_dir . "/paypal-rtn.log", var_export ($paypal, true) . "\n\n", FILE_APPEND);
270
+ /**/
271
+ exit;
272
+ }
273
+ }
274
+ ?>
includes/functions/post-level-access.inc.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Function for handling post level access permissions.
18
+ Attach to: add_action("template_redirect");
19
+ */
20
+ function ws_plugin__s2member_check_post_level_access ()
21
+ {
22
+ global $post; /* get_the_ID() not yet available here. */
23
+ /**/
24
+ if (is_single () && !is_page () && is_object ($post) && ($post_ID = $post->ID))
25
+ {
26
+ if (!ws_plugin__s2member_is_systematic_use_page ()) /* Never restrict systematic use pages. */
27
+ {
28
+ $current_user = (is_user_logged_in ()) ? wp_get_current_user () : false;
29
+ /**/
30
+ if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_posts"] === "all" && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level1")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=1")) !== "nill")
31
+ exit;
32
+ /**/
33
+ else if (in_array ($post_ID, preg_split ("/,/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_posts"])) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level1")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=1")) !== "nill")
34
+ exit;
35
+ /**/
36
+ else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_posts"] === "all" && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level2")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=2")) !== "nill")
37
+ exit;
38
+ /**/
39
+ else if (in_array ($post_ID, preg_split ("/,/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_posts"])) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level2")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=2")) !== "nill")
40
+ exit;
41
+ /**/
42
+ else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_posts"] === "all" && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level3")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=3")) !== "nill")
43
+ exit;
44
+ /**/
45
+ else if (in_array ($post_ID, preg_split ("/,/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_posts"])) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level3")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=3")) !== "nill")
46
+ exit;
47
+ /**/
48
+ else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_posts"] === "all" && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level4")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=4")) !== "nill")
49
+ exit;
50
+ /**/
51
+ else if (in_array ($post_ID, preg_split ("/,/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_posts"])) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level4")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=4")) !== "nill")
52
+ exit;
53
+ }
54
+ }
55
+ /**/
56
+ return;
57
+ }
58
+ ?>
includes/functions/profile-modifications.inc.php ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Function for handling profile modifications.
18
+ Attach to: add_action("init");
19
+ */
20
+ function ws_plugin__s2member_handle_profile_modifications ()
21
+ {
22
+ if ($_GET["s2member_profile"] && ($current_user = (is_user_logged_in ()) ? wp_get_current_user () : false))
23
+ {
24
+ if (($nonce = $_POST["ws_plugin__s2member_profile_save"]) && wp_verify_nonce ($nonce, "ws-plugin--s2member-profile-save"))
25
+ {
26
+ $_POST = stripslashes_deep ($_POST); /* Clean POST vars. */
27
+ /**/
28
+ $userdata["ID"] = $user_id = $current_user->ID;
29
+ /**/
30
+ include_once (ABSPATH . WPINC . "/registration.php");
31
+ /**/
32
+ if (trim ($_POST["ws_plugin__s2member_profile_email"]))
33
+ if (is_email (trim ($_POST["ws_plugin__s2member_profile_email"])))
34
+ if (!email_exists (trim ($_POST["ws_plugin__s2member_profile_email"])))
35
+ $userdata["user_email"] = trim ($_POST["ws_plugin__s2member_profile_email"]);
36
+ /**/
37
+ if (trim ($_POST["ws_plugin__s2member_profile_password"]))
38
+ $userdata["user_pass"] = trim ($_POST["ws_plugin__s2member_profile_password"]);
39
+ /**/
40
+ $userdata["first_name"] = $userdata["display_name"] = trim ($_POST["ws_plugin__s2member_profile_first_name"]);
41
+ /**/
42
+ $userdata["last_name"] = trim ($_POST["ws_plugin__s2member_profile_last_name"]);
43
+ /**/
44
+ wp_update_user ($userdata); /* Send this array for an update. */
45
+ /**/
46
+ foreach (preg_split ("/[\r\n\t,;]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"]) as $field)
47
+ {
48
+ if ($field = trim ($field, "* \t\n\r\0\x0B")) /* Don't process empty fields. */
49
+ {
50
+ $field = preg_replace ("/[^a-z0-9]/i", "_", strtolower ($field));
51
+ $fields[$field] = trim ($_POST["ws_plugin__s2member_profile_" . $field]);
52
+ }
53
+ }
54
+ /**/
55
+ update_usermeta ($user_id, "s2member_custom_fields", $fields);
56
+ /**/
57
+ echo '<script type="text/javascript">' . "\n";
58
+ echo "if(window.parent && window.parent != window) { try{ window.parent.Shadowbox.close(); } catch(e){} try{ window.parent.tb_remove(); } catch(e){} window.parent.alert('Profile updated successfully!'); window.parent.location = '" . esc_js (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"])) . "'; }";
59
+ echo "else if(window.opener) { window.close(); window.opener.alert('Profile updated successfully!'); window.opener.location = '" . esc_js (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"])) . "'; }";
60
+ echo "else { alert('Profile updated successfully!'); window.location = '" . esc_js (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_welcome_page"])) . "'; }";
61
+ echo '</script>' . "\n";
62
+ /**/
63
+ exit;
64
+ }
65
+ /**/
66
+ include_once dirname (dirname (__FILE__)) . "/profile.inc.php";
67
+ /**/
68
+ exit;
69
+ }
70
+ /**/
71
+ return;
72
+ }
73
+ ?>
includes/functions/ptag-level-access.inc.php ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Function for handling ptag level access permissions.
18
+ Attach to: add_action("template_redirect");
19
+ */
20
+ function ws_plugin__s2member_check_ptag_level_access ()
21
+ {
22
+ global $post; /* get_the_ID() not yet available here. */
23
+ /**/
24
+ if ((is_tag () && ($tag_ID = get_query_var ("tag"))) || (is_single () && has_tag () && is_object ($post) && ($post_ID = $post->ID)))
25
+ {
26
+ if (!ws_plugin__s2member_is_systematic_use_page ()) /* Never restrict systematic use pages. */
27
+ {
28
+ $current_user = (is_user_logged_in ()) ? wp_get_current_user () : false;
29
+ /**/
30
+ if (is_tag () && $tag_ID) /* We also check if this is a post or page with tags, having a restricted tag. */
31
+ {
32
+ if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_ptags"] === "all" && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level1")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=1")) !== "nill")
33
+ exit;
34
+ /**/
35
+ else if (($level1_ptags = preg_split ("/,/", preg_replace ("/( +)/", "-", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_ptags"]))) && is_tag ($level1_ptags) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level1")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=1")) !== "nill")
36
+ exit;
37
+ /**/
38
+ else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_ptags"] === "all" && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level2")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=2")) !== "nill")
39
+ exit;
40
+ /**/
41
+ else if (($level2_ptags = preg_split ("/,/", preg_replace ("/( +)/", "-", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_ptags"]))) && is_tag ($level2_ptags) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level2")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=2")) !== "nill")
42
+ exit;
43
+ /**/
44
+ else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_ptags"] === "all" && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level3")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=3")) !== "nill")
45
+ exit;
46
+ /**/
47
+ else if (($level3_ptags = preg_split ("/,/", preg_replace ("/( +)/", "-", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_ptags"]))) && is_tag ($level3_ptags) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level3")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=3")) !== "nill")
48
+ exit;
49
+ /**/
50
+ else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_catgs"] === "all" && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level4")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=4")) !== "nill")
51
+ exit;
52
+ /**/
53
+ else if (($level4_ptags = preg_split ("/,/", preg_replace ("/( +)/", "-", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_ptags"]))) && is_tag ($level4_ptags) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level4")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=4")) !== "nill")
54
+ exit;
55
+ }
56
+ else if (is_single () && has_tag () && $post_ID)
57
+ {
58
+ if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_ptags"] === "all" && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level1")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=1")) !== "nill")
59
+ exit;
60
+ /**/
61
+ else if (($level1_ptags = preg_split ("/,/", preg_replace ("/( +)/", "-", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_ptags"]))) && has_tag ($level1_ptags) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level1")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=1")) !== "nill")
62
+ exit;
63
+ /**/
64
+ else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_ptags"] === "all" && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level2")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=2")) !== "nill")
65
+ exit;
66
+ /**/
67
+ else if (($level2_ptags = preg_split ("/,/", preg_replace ("/( +)/", "-", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_ptags"]))) && has_tag ($level2_ptags) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level2")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=2")) !== "nill")
68
+ exit;
69
+ /**/
70
+ else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_ptags"] === "all" && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level3")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=3")) !== "nill")
71
+ exit;
72
+ /**/
73
+ else if (($level3_ptags = preg_split ("/,/", preg_replace ("/( +)/", "-", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_ptags"]))) && has_tag ($level3_ptags) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level3")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=3")) !== "nill")
74
+ exit;
75
+ /**/
76
+ else if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_ptags"] === "all" && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level4")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=4")) !== "nill")
77
+ exit;
78
+ /**/
79
+ else if (($level4_ptags = preg_split ("/,/", preg_replace ("/( +)/", "-", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_ptags"]))) && has_tag ($level4_ptags) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level4")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=4")) !== "nill")
80
+ exit;
81
+ }
82
+ }
83
+ }
84
+ /**/
85
+ return;
86
+ }
87
+ ?>
includes/functions/readme-parsing.inc.php ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Function that handles readme.txt parsing.
18
+ */
19
+ function ws_plugin__s2member_parse_readme ()
20
+ {
21
+ if (file_exists (dirname (dirname (dirname (__FILE__))) . "/readme.txt"))
22
+ {
23
+ if (!function_exists ("NC_Markdown"))
24
+ include_once dirname (dirname (__FILE__)) . "/markdown/nc-markdown.inc.php";
25
+ /**/
26
+ $rm = file_get_contents (dirname (dirname (dirname (__FILE__))) . "/readme.txt"); /* Get readme.txt file contents. */
27
+ $mb = function_exists ("mb_convert_encoding") ? @mb_convert_encoding ($rm, "UTF-8",@mb_detect_encoding ($rm, "WINDOWS-1252, UTF-8")) : $rm;
28
+ $rm = ($mb) ? $mb : $rm; /* Double check this, just in case conversion fails on an unpredicted charset. */
29
+ /**/
30
+ $rm = preg_replace ("/(\=\=\=)( )(.+?)( )(\=\=\=)/", "<h2>Specifications</h2>", $rm);
31
+ $rm = preg_replace ("/(\=\=)( )(.+?)( )(\=\=)/", "<h2>$3</h2>", $rm);
32
+ $rm = preg_replace ("/(\=)( )(.+?)( )(\=)/", "<h3>$3</h3>", $rm);
33
+ $rm = NC_Markdown ($rm); /* Parse out the Markdown syntax now. */
34
+ /**/
35
+ $r1 = "/(\<h2\>)(.+?)(\<\/h2\>)(.+?)(\<h2\>|$)/si";
36
+ $r2 = "/(\<\/div\>)(\<h2\>)(.+?)(\<\/h2\>)(.+?)(\<div class\=\"section\"\>\<h2\>|$)/si";
37
+ $r3 = "/(\<div class\=\"section\"\>)(\<h2\>)(Specifications)(\<\/h2\>)(\<div class\=\"content\"\>)(.+?)(\<\/div\>\<\/div\>)/sei";
38
+ $r4 = "/(\<div class\=\"section\"\>)(\<h2\>)(Screenshots)(\<\/h2\>)(\<div class\=\"content\"\>)(.+?)(\<\/div\>\<\/div\>)/si";
39
+ /**/
40
+ $rm = preg_replace ($r1, '<div class="section">' . "$1$2$3" . '<div class="content">' . "$4" . '</div></div>' . "$5", $rm);
41
+ $rm = preg_replace ($r2, "$1" . '<div class="section">' . "$2$3$4" . '<div class="content">' . "$5" . '</div></div>' . "$6", $rm);
42
+ $rm = stripslashes (preg_replace ($r3, "'\\1\\2\\3\\4\\5'._ws_plugin__s2member_parse_readme_specs('\\6').'\\7'", $rm, 1));
43
+ $rm = stripslashes (preg_replace ($r4, "", $rm, 1)); /* Here we just remove the screenshots completely. */
44
+ /**/
45
+ $readme = '<div class="readme">' . "\n";
46
+ $readme .= $rm . "\n"; /* Content. */
47
+ $readme .= '</div>' . "\n";
48
+ /**/
49
+ return $readme;
50
+ }
51
+ else /* In case readme.txt is deleted. */
52
+ {
53
+ return "Unable to parse /readme.txt.";
54
+ }
55
+ }
56
+ /*
57
+ Callback function that helps readme file parsing with specs.
58
+ */
59
+ function _ws_plugin__s2member_parse_readme_specs ($str = FALSE)
60
+ {
61
+ $str = preg_replace ("/(\<p\>|^)(.+?)(\:)( )(.+?)($|\<\/p\>)/mi", "$1" . '<li><strong>' . "$2" . '</strong>' . "$3" . '&nbsp;&nbsp;&nbsp;&nbsp;<code>' . "$5" . '</code></li>' . "$6", $str);
62
+ $str = preg_replace ("/\<p\>\<li\>/i", '<ul><li>', $str); /* Open the list items. */
63
+ $str = preg_replace ("/\<\/li\>\<\/p\>/i", '</li></ul><br />', $str);
64
+ /**/
65
+ return $str;
66
+ }
67
+ /*
68
+ Function for parsing readme.txt files and returning a key value.
69
+ */
70
+ function ws_plugin__s2member_parse_readme_value ($key = FALSE)
71
+ {
72
+ static $readme; /* For repeated lookups. */
73
+ /**/
74
+ $path = dirname (dirname (dirname (__FILE__))) . "/readme.txt";
75
+ /**/
76
+ if (isset ($readme) || file_exists ($path))
77
+ {
78
+ if (!isset ($readme)) /* If not already opened, we need open it up now. */
79
+ {
80
+ $readme = file_get_contents ($path); /* Get readme.txt file contents. */
81
+ $mb = function_exists ("mb_convert_encoding") ? @mb_convert_encoding ($readme, "UTF-8",@mb_detect_encoding ($readme, "WINDOWS-1252, UTF-8")) : $readme;
82
+ $readme = ($mb) ? $mb : $readme; /* Double check this, just in case conversion fails on an unpredicted charset. */
83
+ }
84
+ /**/
85
+ preg_match ("/(^)(" . preg_quote ($key, "/") . ")(\:)( )(.+?)($)/m", $readme, $m);
86
+ /**/
87
+ return strlen ($m[5] = trim ($m[5])) ? $m[5] : false;
88
+ }
89
+ else /* Nope. */
90
+ return false;
91
+ }
92
+ ?>
includes/functions/register-access.inc.php ADDED
@@ -0,0 +1,198 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Function that forces a default Subscriber Role.
18
+ Attach to: add_filter("pre_option_default_role");
19
+ */
20
+ function ws_plugin__s2member_force_default_role ($default_role = FALSE)
21
+ {
22
+ return ($default_role = "subscriber");
23
+ }
24
+ /*
25
+ Function for allowing access to the register form.
26
+ Attach to: add_filter("pre_option_users_can_register");
27
+ */
28
+ function ws_plugin__s2member_check_register_access ($users_can_register = FALSE)
29
+ {
30
+ global $pagenow; /* Check if we are on the General Options page. */
31
+ /**/
32
+ if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["allow_subscribers_in"])
33
+ {
34
+ return ($users_can_register = "1");
35
+ }
36
+ else if ($pagenow !== "options-general.php" && $_COOKIE["s2member_subscr_id"] && $_COOKIE["s2member_custom"] && preg_match ("/^[1-4]$/", $_COOKIE["s2member_level"]))
37
+ {
38
+ global $wpdb; /* Global database object reference. */
39
+ /**/
40
+ if (!$usermeta = $wpdb->get_row ("SELECT `user_id` FROM `" . $wpdb->usermeta . "` WHERE `meta_key` = 's2member_subscr_id' AND `meta_value` = '" . $wpdb->escape ($_COOKIE["s2member_subscr_id"]) . "' LIMIT 1"))
41
+ {
42
+ return ($users_can_register = "1");
43
+ }
44
+ }
45
+ /**/
46
+ return ($users_can_register = "0");
47
+ }
48
+ /*
49
+ Function that describes the General Option overrides for clarity.
50
+ Attach to: add_action("admin_init");
51
+ */
52
+ function ws_plugin__s2member_general_ops_notice ()
53
+ {
54
+ global $pagenow; /* Need this. */
55
+ /**/
56
+ if ($pagenow === "options-general.php" && !isset ($_GET["page"]))
57
+ {
58
+ $notice = "<em>* Note: The s2Member plugin has control over two options on this page. <code>Anyone Can Register = " . esc_html (get_option ("users_can_register")) . "</code>, and <code>Default Role = " . esc_html (get_option ("default_role")) . "</code>.";
59
+ /**/
60
+ ws_plugin__s2member_enqueue_admin_notice ($notice, $pagenow);
61
+ }
62
+ }
63
+ /*
64
+ This adds custom fields to the registration form.
65
+ Attach to: add_action("register_form");
66
+ */
67
+ function ws_plugin__s2member_custom_registration_fields ()
68
+ {
69
+ if (!defined ("BP_VERSION")) /* Not compatible with BuddyPress. */
70
+ {
71
+ echo '<input type="hidden" name="ws_plugin__s2member_registration" value="' . esc_attr (wp_create_nonce ("ws-plugin--s2member-registration")) . '" />' . "\n";
72
+ /**/
73
+ $tabindex = 20; /* Incremented tabindex starting with 20. */
74
+ /**/
75
+ if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_password"] && function_exists ("ws_plugin__s2member_generate_password"))
76
+ {
77
+ echo '<p>' . "\n";
78
+ echo '<label>' . "\n";
79
+ echo 'Password *' . "\n";
80
+ echo '<input aria-required="true" type="password" maxlength="100" name="ws_plugin__s2member_custom_reg_field_user_pass" id="ws-plugin--s2member-custom-reg-field-user-pass" class="ws-plugin--s2member-custom-reg-field input" size="25" tabindex="' . esc_attr (($tabindex = $tabindex + 1)) . '" value="' . format_to_edit (trim (stripslashes ($_REQUEST["ws_plugin__s2member_custom_reg_field_user_pass"]))) . '" />' . "\n";
81
+ echo '</label>' . "\n";
82
+ echo '</p>';
83
+ }
84
+ /**/
85
+ echo '<p>' . "\n";
86
+ echo '<label>' . "\n";
87
+ echo 'First Name *' . "\n";
88
+ echo '<input aria-required="true" type="text" maxlength="100" name="ws_plugin__s2member_custom_reg_field_first_name" id="ws-plugin--s2member-custom-reg-field-first-name" class="ws-plugin--s2member-custom-reg-field input" size="25" tabindex="' . esc_attr (($tabindex = $tabindex + 1)) . '" value="' . format_to_edit (trim (stripslashes ($_REQUEST["ws_plugin__s2member_custom_reg_field_first_name"]))) . '" />' . "\n";
89
+ echo '</label>' . "\n";
90
+ echo '</p>';
91
+ /**/
92
+ echo '<p>' . "\n";
93
+ echo '<label>' . "\n";
94
+ echo 'Last Name *' . "\n";
95
+ echo '<input aria-required="true" type="text" maxlength="100" name="ws_plugin__s2member_custom_reg_field_last_name" id="ws-plugin--s2member-custom-reg-field-last-name" class="ws-plugin--s2member-custom-reg-field input" size="25" tabindex="' . esc_attr (($tabindex = $tabindex + 1)) . '" value="' . format_to_edit (trim (stripslashes ($_REQUEST["ws_plugin__s2member_custom_reg_field_last_name"]))) . '" />' . "\n";
96
+ echo '</label>' . "\n";
97
+ echo '</p>';
98
+ /**/
99
+ foreach (preg_split ("/[\r\n\t,;]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"]) as $field)
100
+ {
101
+ $req = preg_match ("/\*/", $field); /* Required fields should be wrapped inside asterisks. */
102
+ $req = ($req) ? ' aria-required="true"' : ''; /* Has JavaScript validation applied. */
103
+ /**/
104
+ if ($field = trim ($field, "* \t\n\r\0\x0B")) /* Don't process empty fields. */
105
+ {
106
+ echo '<p>' . "\n";
107
+ echo '<label>' . "\n";
108
+ echo esc_html ($field) . (($req) ? " *" : "") . "\n";
109
+ $field = preg_replace ("/[^a-z0-9]/i", "_", strtolower ($field));
110
+ echo '<input' . $req . ' type="text" maxlength="100" name="ws_plugin__s2member_custom_reg_field_' . esc_attr ($field) . '" id="ws-plugin--s2member-custom-reg-field-' . esc_attr (preg_replace ("/_/", "-", $field)) . '" class="ws-plugin--s2member-custom-reg-field input" size="25" tabindex="' . esc_attr (($tabindex = $tabindex + 1)) . '" value="' . format_to_edit (trim (stripslashes ($_REQUEST["ws_plugin__s2member_custom_reg_field_" . $field]))) . '" />' . "\n";
111
+ echo '</label>' . "\n";
112
+ echo '</p>';
113
+ }
114
+ }
115
+ }
116
+ /**/
117
+ return;
118
+ }
119
+ /*
120
+ Function for configuring new users.
121
+ Attach to: add_action("user_register");
122
+ Attach to: add_action("bp_core_signup_user");
123
+ */
124
+ function ws_plugin__s2member_configure_user_registration ($user_id = FALSE)
125
+ {
126
+ static $processed; /* Prevents duplicate processing when attached to multiple hooks in support of plugins like BuddyPress. */
127
+ /**/
128
+ if (!$processed && $user_id && is_array ($_POST = stripslashes_deep ($_POST)) && is_object ($user = new WP_User ($user_id)) && ($processed = true))
129
+ {
130
+ ws_plugin__s2member_email_config (); /* Configures From: header that will be used in new user notifications. */
131
+ /**/
132
+ if ($_COOKIE["s2member_subscr_id"] && $_COOKIE["s2member_custom"] && preg_match ("/^[1-4]$/", $_COOKIE["s2member_level"]))
133
+ {
134
+ global $wpdb; /* Global database object required for this routine. We need to check the uniqueness of their s2member_subscr_id. */
135
+ /**/
136
+ if (!$usermeta = $wpdb->get_row ("SELECT `user_id` FROM `" . $wpdb->usermeta . "` WHERE `meta_key` = 's2member_subscr_id' AND `meta_value` = '" . $wpdb->escape ($_COOKIE["s2member_subscr_id"]) . "' LIMIT 1"))
137
+ {
138
+ $user->set_role ("s2member_level" . $_COOKIE["s2member_level"]);
139
+ /**/
140
+ update_usermeta ($user_id, "s2member_subscr_id", $_COOKIE["s2member_subscr_id"]);
141
+ update_usermeta ($user_id, "s2member_custom", $_COOKIE["s2member_custom"]);
142
+ }
143
+ /**/
144
+ setcookie ("s2member_subscr_id", "", time () + 31556926, "/");
145
+ setcookie ("s2member_custom", "", time () + 31556926, "/");
146
+ setcookie ("s2member_level", "", time () + 31556926, "/");
147
+ }
148
+ /**/
149
+ if (!defined ("BP_VERSION")) /* Custom fields are not compatible when running together with BuddyPress. */
150
+ {
151
+ update_usermeta ($user_id, "first_name", ($first_name = trim ($_POST["ws_plugin__s2member_custom_reg_field_first_name"])));
152
+ update_usermeta ($user_id, "last_name", ($last_name = trim ($_POST["ws_plugin__s2member_custom_reg_field_last_name"])));
153
+ /**/
154
+ wp_update_user (array ("ID" => $user_id, "display_name" => $first_name));
155
+ /**/
156
+ foreach (preg_split ("/[\r\n\t,;]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"]) as $field)
157
+ {
158
+ if ($field = trim ($field, "* \t\n\r\0\x0B")) /* Don't process empty fields. */
159
+ {
160
+ $field = preg_replace ("/[^a-z0-9]/i", "_", strtolower ($field));
161
+ $fields[$field] = trim ($_POST["ws_plugin__s2member_custom_reg_field_" . $field]);
162
+ }
163
+ }
164
+ /**/
165
+ update_usermeta ($user_id, "s2member_custom_fields", $fields);
166
+ }
167
+ }
168
+ /**/
169
+ return;
170
+ }
171
+ /*
172
+ Pluggable function that handles password generation.
173
+ Taken from: /wp-includes/pluggable.php
174
+ */
175
+ if (!function_exists ("wp_generate_password"))
176
+ {
177
+ function wp_generate_password ($length = 12, $special_chars = TRUE)
178
+ {
179
+ return ws_plugin__s2member_generate_password ($length, $special_chars);
180
+ }
181
+ /**/
182
+ function ws_plugin__s2member_generate_password ($length = 12, $special_chars = TRUE)
183
+ {
184
+ $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
185
+ $chars .= ($special_chars) ? "!@#$%^&*()" : "";
186
+ /**/
187
+ for ($i = 0, $password = ""; $i < $length; $i++)
188
+ $password .= substr ($chars, wp_rand (0, strlen ($chars) - 1), 1);
189
+ /**/
190
+ if (!defined ("BP_VERSION") && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_password"])
191
+ if (wp_verify_nonce (trim (stripslashes ($_POST["ws_plugin__s2member_registration"])), "ws-plugin--s2member-registration"))
192
+ if ($custom = trim (stripslashes ($_POST["ws_plugin__s2member_custom_reg_field_user_pass"])))
193
+ $password = $custom;
194
+ /**/
195
+ return $password;
196
+ }
197
+ }
198
+ ?>
includes/functions/ruri-level-access.inc.php ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Function for handling request uri level access permissions.
18
+ Attach to: add_action("template_redirect");
19
+ */
20
+ function ws_plugin__s2member_check_ruri_level_access ()
21
+ {
22
+ if (!ws_plugin__s2member_is_systematic_use_page ()) /* Never restrict systematic use pages. */
23
+ {
24
+ $current_user = (is_user_logged_in ()) ? wp_get_current_user () : false;
25
+ /**/
26
+ foreach (preg_split ("/[\r\n\t]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_ruris"]) as $str)
27
+ if ($str && preg_match ("/" . preg_quote ($str, "/") . "/", $_SERVER["REQUEST_URI"]) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level1")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=1")) !== "nill")
28
+ exit;
29
+ /**/
30
+ foreach (preg_split ("/[\r\n\t]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_ruris"]) as $str)
31
+ if ($str && preg_match ("/" . preg_quote ($str, "/") . "/", $_SERVER["REQUEST_URI"]) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level2")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=2")) !== "nill")
32
+ exit;
33
+ /**/
34
+ foreach (preg_split ("/[\r\n\t]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_ruris"]) as $str)
35
+ if ($str && preg_match ("/" . preg_quote ($str, "/") . "/", $_SERVER["REQUEST_URI"]) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level3")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=3")) !== "nill")
36
+ exit;
37
+ /**/
38
+ foreach (preg_split ("/[\r\n\t]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_ruris"]) as $str)
39
+ if ($str && preg_match ("/" . preg_quote ($str, "/") . "/", $_SERVER["REQUEST_URI"]) && ws_plugin__s2member_nocache_constants () !== "nill" && (!$current_user || !current_user_can ("access_s2member_level4")) && wp_redirect (ws_plugin__s2member_append_query_var (get_page_link ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]), "s2member_level_req=4")) !== "nill")
40
+ exit;
41
+ }
42
+ /**/
43
+ return;
44
+ }
45
+ ?>
includes/functions/shortcodes.inc.php ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Function that handles the Shortcode for [s2Member-PayPal-Button /].
18
+ [s2Member-PayPal-Button level="1" ps="paypal" cc="USD" on0="" os0="" modify="0" custom="www.domain.com" tp="0" tt="D" ra="0.01" rp="1" rt="M" rr="1" /]
19
+ Attach to: add_shortcode("s2Member-PayPal-Button");
20
+ */
21
+ function ws_plugin__s2member_paypal_button ($attr = FALSE, $content = FALSE, $shortcode = FALSE)
22
+ {
23
+ $sc = shortcode_atts (array ("level" => "1", "ps" => "paypal", "cc" => "USD", "on0" => "", "os0" => "", "modify" => "0", "custom" => $_SERVER["HTTP_HOST"], "tp" => "0", "tt" => "D", "ra" => "0.01", "rp" => "1", "rt" => "M", "rr" => "1"), $attr);
24
+ /**/
25
+ $code = trim (file_get_contents (dirname (dirname (__FILE__)) . "/menu-pages/button.html"));
26
+ $code = preg_replace ("/%%endpoint%%/", (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com"), $code);
27
+ $code = preg_replace ("/%%paypal_business%%/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"], $code);
28
+ $code = preg_replace ("/%%level_label%%/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level" . $sc["level"] . "_label"], $code);
29
+ $code = preg_replace ("/%%cancel_return%%/", get_bloginfo ("url"), $code);
30
+ $code = preg_replace ("/%%notify_url%%/", get_bloginfo ("url") . "/?s2member_paypal_notify=1", $code);
31
+ $code = preg_replace ("/%%return%%/", get_bloginfo ("url") . "/?s2member_paypal_return=1", $code);
32
+ $code = preg_replace ("/%%domain%%/", strtolower ($_SERVER["HTTP_HOST"]), $code);
33
+ $code = preg_replace ("/%%level%%/", $sc["level"], $code);
34
+ /**/
35
+ $code = preg_replace ('/ \<\!--(\<input type\="hidden" name\="(amount|modify|src|sra|a1|p1|t1|a3|p3|t3)" value\="(.*?)" \/\>)--\>/', " $1", $code);
36
+ $code = ($sc["on0"] || $sc["os0"]) ? preg_replace ('/ \<\!--(\<input type\="hidden" name\="(on0|os0)" value\="(.*?)" \/\>)--\>/', " $1", $code) : $code;
37
+ $code = ($sc["tp"] <= 0) ? preg_replace ('/ (\<input type\="hidden" name\="(a1|p1|t1)" value\="(.*?)" \/\>)/', " <!--$1-->", $code) : $code;
38
+ $code = ($sc["rt"] === "L") ? preg_replace ('/ (\<input type\="hidden" name\="cmd" value\=")(.*?)(" \/\>)/', " $1_xclick$3", $code) : $code;
39
+ $code = ($sc["rt"] === "L") ? preg_replace ('/ (\<input type\="hidden" name\="(modify|src|sra|a1|p1|t1|a3|p3|t3)" value\="(.*?)" \/\>)/', " <!--$1-->", $code) : $code;
40
+ $code = ($sc["rt"] !== "L") ? preg_replace ('/ (\<input type\="hidden" name\="cmd" value\=")(.*?)(" \/\>)/', " $1_xclick-subscriptions$3", $code) : $code;
41
+ $code = ($sc["rt"] !== "L") ? preg_replace ('/ (\<input type\="hidden" name\="amount" value\="(.*?)" \/\>)/', " <!--$1-->", $code) : $code;
42
+ /**/
43
+ $code = preg_replace ('/ name\="page_style" value\="(.*?)"/', ' name="page_style" value="' . $sc["ps"] . '"', $code);
44
+ $code = preg_replace ('/ name\="currency_code" value\="(.*?)"/', ' name="currency_code" value="' . $sc["cc"] . '"', $code);
45
+ $code = preg_replace ('/ name\="on0" value\="(.*?)"/', ' name="on0" value="' . $sc["on0"] . '"', $code);
46
+ $code = preg_replace ('/ name\="os0" value\="(.*?)"/', ' name="os0" value="' . $sc["os0"] . '"', $code);
47
+ $code = preg_replace ('/ name\="modify" value\="(.*?)"/', ' name="modify" value="' . $sc["modify"] . '"', $code);
48
+ $code = preg_replace ('/ name\="custom" value\="(.*?)"/', ' name="custom" value="' . $sc["custom"] . '"', $code);
49
+ $code = preg_replace ('/ name\="amount" value\="(.*?)"/', ' name="amount" value="' . $sc["ra"] . '"', $code);
50
+ $code = preg_replace ('/ name\="src" value\="(.*?)"/', ' name="src" value="' . $sc["rr"] . '"', $code);
51
+ $code = preg_replace ('/ name\="p1" value\="(.*?)"/', ' name="p1" value="' . $sc["tp"] . '"', $code);
52
+ $code = preg_replace ('/ name\="t1" value\="(.*?)"/', ' name="t1" value="' . $sc["tt"] . '"', $code);
53
+ $code = preg_replace ('/ name\="a3" value\="(.*?)"/', ' name="a3" value="' . $sc["ra"] . '"', $code);
54
+ $code = preg_replace ('/ name\="p3" value\="(.*?)"/', ' name="p3" value="' . $sc["rp"] . '"', $code);
55
+ $code = preg_replace ('/ name\="t3" value\="(.*?)"/', ' name="t3" value="' . $sc["rt"] . '"', $code);
56
+ /**/
57
+ return $code; /* The finished PayPal® Button. */
58
+ }
59
+ ?>
includes/functions/translations.inc.php ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Mangles internal translations.
18
+ Attach to: add_filter("gettext");
19
+ */
20
+ function ws_plugin__s2member_translation_mangler ($translated = FALSE, $original = FALSE, $domain = FALSE)
21
+ {
22
+ static $is_admin_media_upload, $is_wp_login; /* Optimizes this routine. */
23
+ /**/
24
+ if (!isset ($is_admin_media_upload) || $is_admin_media_upload)
25
+ {
26
+ if ($is_admin_media_upload || (is_admin () && preg_match ("/\/(async-upload|media-upload)\.php/", $_SERVER["REQUEST_URI"])))
27
+ {
28
+ $is_admin_media_upload = true;
29
+ /**/
30
+ if ($translated === "Insert into Post")
31
+ {
32
+ $translated = "Insert";
33
+ }
34
+ }
35
+ else
36
+ {
37
+ $is_admin_media_upload = false;
38
+ }
39
+ }
40
+ /**/
41
+ else if (!isset ($is_wp_login) || $is_wp_login)
42
+ {
43
+ if ($is_wp_login || preg_match ("/\/wp-login\.php/", $_SERVER["REQUEST_URI"]))
44
+ {
45
+ $is_wp_login = true;
46
+ /**/
47
+ if ($translated === "Username")
48
+ {
49
+ $translated = "Username *";
50
+ }
51
+ else if ($translated === "E-mail")
52
+ {
53
+ $translated = "Email Address *";
54
+ }
55
+ }
56
+ else
57
+ {
58
+ $is_wp_login = false;
59
+ }
60
+ }
61
+ /**/
62
+ return $translated;
63
+ }
64
+ ?>
includes/functions/user-access-level.inc.php ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Function for determing the access level of a user.
18
+ Returns 0-4 according to the current user's access level.
19
+ */
20
+ function ws_plugin__s2member_user_access_level ()
21
+ {
22
+ if (!($current_user = (is_user_logged_in ()) ? wp_get_current_user () : false))
23
+ {
24
+ return -1; /* Return of -1, means not logged in. */
25
+ }
26
+ else if (current_user_can ("access_s2member_level4"))
27
+ {
28
+ return 4; /* User logged in with level 4 access. */
29
+ }
30
+ else if (current_user_can ("access_s2member_level3"))
31
+ {
32
+ return 3; /* User logged in with level 3 access. */
33
+ }
34
+ else if (current_user_can ("access_s2member_level2"))
35
+ {
36
+ return 2; /* User logged in with level 2 access. */
37
+ }
38
+ else if (current_user_can ("access_s2member_level1"))
39
+ {
40
+ return 1; /* User logged in with level 1 access. */
41
+ }
42
+ else /* If a user is logged in but has no access. */
43
+ {
44
+ return 0; /* User is logged in without access. */
45
+ }
46
+ }
47
+ ?>
includes/functions/user-deletions.inc.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Function for handling user deletions.
18
+ Attach to: add_action("delete_user");
19
+ */
20
+ function ws_plugin__s2member_handle_user_deletions ($user_id = FALSE)
21
+ {
22
+ $userdata = get_userdata ($user_id);
23
+ $paypal["custom"] = get_usermeta ($user_id, "s2member_custom");
24
+ $paypal["subscr_id"] = get_usermeta ($user_id, "s2member_subscr_id");
25
+ /**/
26
+ if ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["eot_del_notification_urls"] && is_object ($userdata) && $paypal["subscr_id"] && $paypal["custom"] && is_array ($cv = preg_split ("/\|/", $paypal["custom"])))
27
+ {
28
+ foreach (preg_split ("/[\r\n\t]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["eot_del_notification_urls"]) as $url) /* Handle eot notifications on user deletion. */
29
+ if (($url = preg_replace ("/%%cv([0-9]+)%%/ei", 'urlencode(trim($cv[$1]))', $url)) && ($url = preg_replace ("/%%subscr_id%%/i", urlencode ($paypal["subscr_id"]), $url)))
30
+ if (($url = preg_replace ("/%%user_first_name%%/i", urlencode ($userdata->first_name), $url)) && ($url = preg_replace ("/%%user_last_name%%/i", urlencode ($userdata->last_name), $url)))
31
+ if (($url = preg_replace ("/%%user_full_name%%/i", urlencode (trim ($userdata->first_name . " " . $userdata->last_name)), $url)))
32
+ if (($url = preg_replace ("/%%user_email%%/i", urlencode ($userdata->user_email), $url)))
33
+ if (($url = trim ($url))) /* Make sure it is not empty now. */
34
+ ws_plugin__s2member_curlpsr ($url, "s2member=1");
35
+ }
36
+ /**/
37
+ return;
38
+ }
39
+ ?>
includes/functions/user-downloads.inc.php ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Function determines how many downloads allowed - etc, etc.
18
+ Returns an array with 3 elements: allowed, allowed_days, currently.
19
+ The 2nd parameter can be used to prevent another database connection.
20
+ */
21
+ function ws_plugin__s2member_user_downloads ($not_counting_this_particular_file = false, $log = null)
22
+ {
23
+ if (($current_user = (is_user_logged_in ()) ? wp_get_current_user () : false))
24
+ {
25
+ if (current_user_can ("access_s2member_level1") && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_file_downloads_allowed"])
26
+ {
27
+ $allowed = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_file_downloads_allowed"];
28
+ $allowed_days = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_file_downloads_allowed_days"];
29
+ }
30
+ /**/
31
+ if (current_user_can ("access_s2member_level2") && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_file_downloads_allowed"])
32
+ {
33
+ $allowed = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_file_downloads_allowed"];
34
+ $allowed_days = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_file_downloads_allowed_days"];
35
+ }
36
+ /**/
37
+ if (current_user_can ("access_s2member_level3") && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_file_downloads_allowed"])
38
+ {
39
+ $allowed = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_file_downloads_allowed"];
40
+ $allowed_days = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_file_downloads_allowed_days"];
41
+ }
42
+ /**/
43
+ if (current_user_can ("access_s2member_level4") && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_file_downloads_allowed"])
44
+ {
45
+ $allowed = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_file_downloads_allowed"];
46
+ $allowed_days = $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_file_downloads_allowed_days"];
47
+ }
48
+ /**/
49
+ $file_download_access_log = (isset ($log)) ? (array)$log : (array)get_usermeta ($current_user->ID, "s2member_file_download_access_log");
50
+ foreach ($file_download_access_log as $file_download_access_log_entry_key => $file_download_access_log_entry)
51
+ if (strtotime ($file_download_access_log_entry["date"]) >= strtotime ("-" . (int)$allowed_days . " days"))
52
+ if ($file_download_access_log_entry["file"] !== $not_counting_this_particular_file)
53
+ $currently = ($currently) ? $currently + 1 : 1;
54
+ }
55
+ /**/
56
+ return array ("allowed" => (int)$allowed, "allowed_days" => (int)$allowed_days, "currently" => (int)$currently);
57
+ }
58
+ ?>
includes/functions/users-list.inc.php ADDED
@@ -0,0 +1,129 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Function that adds columns to the list of Users.
18
+ Attach to: add_filter ("manage_users_columns");
19
+ */
20
+ function ws_plugin__s2member_users_list_cols ($cols = FALSE)
21
+ {
22
+ $cols["s2member_registration_time"] = "Registered On"; /* Date they signed up. */
23
+ $cols["s2member_subscr_id"] = "PayPal® Subscr. ID"; /* Special field that is always applied. */
24
+ /**/
25
+ if (!defined ("BP_VERSION")) /* Custom fields are not compatible when running together with BuddyPress. */
26
+ {
27
+ foreach (preg_split ("/[\r\n\t,;]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"]) as $field)
28
+ {
29
+ if ($field = trim ($field, "* \t\n\r\0\x0B")) /* Don't process empty fields. */
30
+ {
31
+ $cols[preg_replace ("/[^a-z0-9]/i", "_", strtolower ($field))] = $field;
32
+ }
33
+ }
34
+ }
35
+ /**/
36
+ return $cols;
37
+ }
38
+ /*
39
+ Function that displays column data in the row of details.
40
+ Attach to: add_filter ("manage_users_custom_column");
41
+ */
42
+ function ws_plugin__s2member_users_list_display_cols ($_ = FALSE, $col = FALSE, $user_id = FALSE)
43
+ {
44
+ global $user_object; /* The user_row() function already has this. */
45
+ static $fields, $fields_4_user_id; /* Used to conserve resources. */
46
+ /**/
47
+ if ((!isset ($fields) || $fields_4_user_id !== $user_id) && ($fields_4_user_id = $user_id))
48
+ $fields = get_usermeta ($user_id, "s2member_custom_fields");
49
+ /**/
50
+ if ($col === "s2member_registration_time")
51
+ return ($r = $user_object->user_registered) ? /* Displays date & time ( 2 lines ). */
52
+ date ("D M j, Y", strtotime ($r)) . '<br />@exactly ' . date ("g:i a", strtotime ($r)) : "—";
53
+ /**/
54
+ else if ($col === "s2member_subscr_id")
55
+ return ($r = get_usermeta ($user_id, "s2member_subscr_id")) ? esc_html ($r) : "—";
56
+ /**/
57
+ if ($fields[$col] && preg_match ("/^http(s?)\:/i", $fields[$col]))
58
+ return '<a href="' . esc_attr ($fields[$col]) . '" target="_blank">' . esc_html (substr ($fields[$col], strpos ($fields[$col], ":") + 3, 25) . "...") . '</a>';
59
+ /**/
60
+ return ($fields[$col]) ? esc_html ($fields[$col]) : "—";
61
+ }
62
+ /*
63
+ Function that adds custom fields to the admin profile editing page.
64
+ Attach to: add_action("edit_user_profile");
65
+ Attach to: add_action("show_user_profile");
66
+ */
67
+ function ws_plugin__s2member_users_list_edit_cols ($user = FALSE)
68
+ {
69
+ if (current_user_can ("edit_users")) /* Security check. */
70
+ {
71
+ echo '<h3>s2Member Profile Fields</h3>' . "\n";
72
+ /**/
73
+ echo '<table class="form-table">' . "\n";
74
+ /**/
75
+ echo '<tr>' . "\n";
76
+ echo '<th><label>PayPal® Subscr. ID </label></th>' . "\n";
77
+ echo '<td><input type="text" name="ws_plugin__s2member_profile_s2member_subscr_id" value="' . esc_attr (get_usermeta ($user->ID, "s2member_subscr_id")) . '" class="regular-text" /></td>' . "\n";
78
+ echo '</tr>' . "\n";
79
+ /**/
80
+ if (!defined ("BP_VERSION")) /* Custom fields are not compatible when running together with BuddyPress. */
81
+ {
82
+ $fields = get_usermeta ($user->ID, "s2member_custom_fields");
83
+ /**/
84
+ foreach (preg_split ("/[\r\n\t,;]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"]) as $field)
85
+ {
86
+ if ($field = trim ($field, "* \t\n\r\0\x0B")) /* Don't process empty fields. */
87
+ {
88
+ echo '<tr>' . "\n";
89
+ echo '<th><label>' . esc_html ($field) . ' </label></th>' . "\n";
90
+ $field = preg_replace ("/[^a-z0-9]/i", "_", strtolower ($field));
91
+ echo '<td><input type="text" name="ws_plugin__s2member_profile_' . esc_attr ($field) . '" value="' . esc_attr ($fields[$field]) . '" class="regular-text" /></td>' . "\n";
92
+ echo '</tr>' . "\n";
93
+ }
94
+ }
95
+ }
96
+ /**/
97
+ echo '</table>' . "\n";
98
+ }
99
+ }
100
+ /*
101
+ Function that saves custom fields after an admin updates profile.
102
+ Attach to: add_action("edit_user_profile");
103
+ Attach to: add_action("personal_options_update");
104
+ */
105
+ function ws_plugin__s2member_users_list_update_cols ($user_id = FALSE)
106
+ {
107
+ if (current_user_can ("edit_users")) /* Quick security check here. */
108
+ {
109
+ if (is_array ($_POST = stripslashes_deep ($_POST)) && !empty ($_POST))
110
+ {
111
+ update_usermeta ($user_id, "s2member_subscr_id", $_POST["ws_plugin__s2member_profile_s2member_subscr_id"]);
112
+ /**/
113
+ if (!defined ("BP_VERSION")) /* Custom fields are not compatible when running together with BuddyPress. */
114
+ {
115
+ foreach (preg_split ("/[\r\n\t,;]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"]) as $field)
116
+ {
117
+ if ($field = trim ($field, "* \t\n\r\0\x0B")) /* Don't process empty fields. */
118
+ {
119
+ $field = preg_replace ("/[^a-z0-9]/i", "_", strtolower ($field));
120
+ $fields[$field] = trim ($_POST["ws_plugin__s2member_profile_" . $field]);
121
+ }
122
+ }
123
+ /**/
124
+ update_usermeta ($user_id, "s2member_custom_fields", $fields);
125
+ }
126
+ }
127
+ }
128
+ }
129
+ ?>
includes/functions/utilities.inc.php ADDED
@@ -0,0 +1,200 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Function that extends array_unique to
18
+ support multi-dimensional arrays.
19
+ */
20
+ function ws_plugin__s2member_array_unique ($array = FALSE)
21
+ {
22
+ if (!is_array ($array))
23
+ {
24
+ return array ($array);
25
+ }
26
+ else /* Serialized array_unique. */
27
+ {
28
+ foreach ($array as &$value)
29
+ {
30
+ $value = serialize ($value);
31
+ }
32
+ /**/
33
+ $array = array_unique ($array);
34
+ /**/
35
+ foreach ($array as &$value)
36
+ {
37
+ $value = unserialize ($value);
38
+ }
39
+ /**/
40
+ return $array;
41
+ }
42
+ }
43
+ /*
44
+ Function that buffers ( gets ) function output.
45
+ */
46
+ function ws_plugin__s2member_get ($function = FALSE)
47
+ {
48
+ $args = func_get_args ();
49
+ $function = array_shift ($args);
50
+ /**/
51
+ if (is_string ($function) && $function)
52
+ {
53
+ ob_start ();
54
+ /**/
55
+ if (is_array ($args) && !empty ($args))
56
+ {
57
+ $return = call_user_func_array ($function, $args);
58
+ }
59
+ else /* There are no additional arguments to pass. */
60
+ {
61
+ $return = call_user_func ($function);
62
+ }
63
+ /**/
64
+ $echo = ob_get_contents ();
65
+ /**/
66
+ ob_end_clean ();
67
+ /**/
68
+ return (!strlen ($echo) && strlen ($return)) ? $return : $echo;
69
+ }
70
+ else /* Else return null. */
71
+ return;
72
+ }
73
+ /*
74
+ Function for appending query string vars onto the end.
75
+ */
76
+ function ws_plugin__s2member_append_query_var ($url = FALSE, $var = FALSE)
77
+ {
78
+ if (is_string ($url) && $url && is_string ($var) && $var)
79
+ return preg_match ("/\?/", $url) ? $url . "&" . $var : $url . "?" . $var;
80
+ /**/
81
+ return $url;
82
+ }
83
+ /*
84
+ Function checks if a post is in a child category.
85
+ */
86
+ function ws_plugin__s2member_in_descendant_category ($cats = FALSE, $post_ID = FALSE)
87
+ {
88
+ foreach ((array)$cats as $cat)
89
+ {
90
+ $descendants = get_term_children ((int)$cat, "category");
91
+ if ($descendants && in_category ($descendants, $post_ID))
92
+ return true;
93
+ }
94
+ /**/
95
+ return false;
96
+ }
97
+ /*
98
+ Curl operation for posting data and reading response.
99
+ */
100
+ function ws_plugin__s2member_curlpsr ($url = FALSE, $vars = FALSE)
101
+ {
102
+ if ($url && ($connection = curl_init ()))
103
+ {
104
+ curl_setopt ($connection, CURLOPT_URL, $url);
105
+ curl_setopt ($connection, CURLOPT_POST, true);
106
+ curl_setopt ($connection, CURLOPT_TIMEOUT, 20);
107
+ curl_setopt ($connection, CURLOPT_CONNECTTIMEOUT, 20);
108
+ curl_setopt ($connection, CURLOPT_FOLLOWLOCATION, false);
109
+ curl_setopt ($connection, CURLOPT_MAXREDIRS, 0);
110
+ curl_setopt ($connection, CURLOPT_HEADER, false);
111
+ curl_setopt ($connection, CURLOPT_VERBOSE, true);
112
+ curl_setopt ($connection, CURLOPT_ENCODING, "");
113
+ curl_setopt ($connection, CURLOPT_SSL_VERIFYPEER, false);
114
+ curl_setopt ($connection, CURLOPT_RETURNTRANSFER, true);
115
+ curl_setopt ($connection, CURLOPT_FORBID_REUSE, true);
116
+ curl_setopt ($connection, CURLOPT_FAILONERROR, true);
117
+ curl_setopt ($connection, CURLOPT_POSTFIELDS, $vars);
118
+ /**/
119
+ $output = trim (curl_exec ($connection));
120
+ /**/
121
+ curl_close ($connection);
122
+ }
123
+ /**/
124
+ return (strlen ($output)) ? $output : false;
125
+ }
126
+ /*
127
+ Base32 encode ( base32 is case insensitive ).
128
+ */
129
+ function ws_plugin__s2member_base32_encode ($string = FALSE)
130
+ {
131
+ for ($i = 0; $i < strlen ((string)$string); $i++)
132
+ {
133
+ $hexdec = dechex (ord (substr ($string, $i, 1)));
134
+ $base32 .= base_convert ($hexdec, 16, 32);
135
+ }
136
+ /**/
137
+ return (string)$base32;
138
+ }
139
+ /*
140
+ Base32 decode ( base32 is case insensitive ).
141
+ */
142
+ function ws_plugin__s2member_base32_decode ($base32 = FALSE)
143
+ {
144
+ for ($i = 0; $i < strlen ((string)$base32); $i += 2)
145
+ {
146
+ $hexdec = base_convert (substr ($base32, $i, 2), 32, 16);
147
+ $string .= chr (hexdec ($hexdec));
148
+ }
149
+ /**/
150
+ return (string)$string;
151
+ }
152
+ /*
153
+ Xencrypt and xdecrypt ( very useful functions ).
154
+ */
155
+ function ws_plugin__s2member_xencrypt ($string = FALSE, $key = FALSE)
156
+ {
157
+ $key = (!is_string ($key) || !strlen ($key)) ? "POE993432" : $key;
158
+ /**/
159
+ for ($i = 1; $i <= strlen ((string)$string); $i++)
160
+ {
161
+ $char = substr ($string, $i - 1, 1);
162
+ $keychar = substr ($key, ($i % strlen ($key)) - 1, 1);
163
+ $encrypted .= chr (ord ($char) + ord ($keychar));
164
+ }
165
+ /**/
166
+ return ws_plugin__s2member_base32_encode ((string)$encrypted);
167
+ }
168
+ /*
169
+ Alias function for API Scripting usage.
170
+ */
171
+ function s2member_xencrypt ($string = FALSE, $key = FALSE)
172
+ {
173
+ return ws_plugin__s2member_xencrypt ($string, $key);
174
+ }
175
+ /*
176
+ Xencrypt and xdecrypt ( very useful functions ).
177
+ */
178
+ function ws_plugin__s2member_xdecrypt ($string = FALSE, $key = FALSE)
179
+ {
180
+ $key = (!is_string ($key) || !strlen ($key)) ? "POE993432" : $key;
181
+ /**/
182
+ $string = ws_plugin__s2member_base32_decode ((string)$string);
183
+ /**/
184
+ for ($i = 1; $i <= strlen ((string)$string); $i++)
185
+ {
186
+ $char = substr ($string, $i - 1, 1);
187
+ $keychar = substr ($key, ($i % strlen ($key)) - 1, 1);
188
+ $decrypted .= chr (ord ($char) - ord ($keychar));
189
+ }
190
+ /**/
191
+ return (string)$decrypted;
192
+ }
193
+ /*
194
+ Alias function for API Scripting usage.
195
+ */
196
+ function s2member_xdecrypt ($string = FALSE, $key = FALSE)
197
+ {
198
+ return ws_plugin__s2member_xdecrypt ($string, $key);
199
+ }
200
+ ?>
includes/hooks.inc.php ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Add the plugin actions/filters here.
18
+ */
19
+ add_action ("init", "ws_plugin__s2member_nocache");
20
+ add_action ("init", "ws_plugin__s2member_constants");
21
+ add_action ("init", "ws_plugin__s2member_js_w_globals");
22
+ add_action ("init", "ws_plugin__s2member_menu_pages_js");
23
+ add_action ("init", "ws_plugin__s2member_menu_pages_css");
24
+ add_action ("init", "ws_plugin__s2member_paypal_return");
25
+ add_action ("init", "ws_plugin__s2member_paypal_notify");
26
+ add_action ("init", "ws_plugin__s2member_paypal_register");
27
+ add_action ("init", "ws_plugin__s2member_check_file_download_access");
28
+ add_action ("init", "ws_plugin__s2member_handle_profile_modifications");
29
+ /**/
30
+ add_action ("template_redirect", "ws_plugin__s2member_check_ruri_level_access", 1);
31
+ add_action ("template_redirect", "ws_plugin__s2member_check_catg_level_access", 1);
32
+ add_action ("template_redirect", "ws_plugin__s2member_check_ptag_level_access", 1);
33
+ add_action ("template_redirect", "ws_plugin__s2member_check_post_level_access", 1);
34
+ add_action ("template_redirect", "ws_plugin__s2member_check_page_level_access", 1);
35
+ /**/
36
+ add_action ("wp_print_scripts", "ws_plugin__s2member_add_js_w_globals");
37
+ add_filter ("gettext", "ws_plugin__s2member_translation_mangler", 10, 3);
38
+ add_filter ("posts_where", "ws_plugin__s2member_hide_some_systematics");
39
+ /**/
40
+ add_action ("delete_user", "ws_plugin__s2member_handle_user_deletions");
41
+ add_filter ("pre_option_default_role", "ws_plugin__s2member_force_default_role");
42
+ add_filter ("pre_option_users_can_register", "ws_plugin__s2member_check_register_access");
43
+ add_action ("user_register", "ws_plugin__s2member_configure_user_registration");
44
+ add_action ("register_form", "ws_plugin__s2member_custom_registration_fields");
45
+ /**/
46
+ add_action ("wp_login", "ws_plugin__s2member_login_redirect");
47
+ add_action ("login_head", "ws_plugin__s2member_login_header_styles");
48
+ add_filter ("login_headerurl", "ws_plugin__s2member_login_header_url");
49
+ add_filter ("login_headertitle", "ws_plugin__s2member_login_header_title");
50
+ /**/
51
+ add_action ("admin_init", "ws_plugin__s2member_admin_lockout");
52
+ add_action ("admin_init", "ws_plugin__s2member_general_ops_notice");
53
+ add_action ("admin_notices", "ws_plugin__s2member_admin_notices");
54
+ add_action ("admin_menu", "ws_plugin__s2member_add_admin_options");
55
+ add_action ("admin_print_scripts", "ws_plugin__s2member_add_admin_scripts");
56
+ add_action ("admin_print_styles", "ws_plugin__s2member_add_admin_styles");
57
+ /**/
58
+ add_filter ("manage_users_columns", "ws_plugin__s2member_users_list_cols");
59
+ add_filter ("manage_users_custom_column", "ws_plugin__s2member_users_list_display_cols", 10, 3);
60
+ add_action ("edit_user_profile", "ws_plugin__s2member_users_list_edit_cols");
61
+ add_action ("show_user_profile", "ws_plugin__s2member_users_list_edit_cols");
62
+ add_action ("edit_user_profile_update", "ws_plugin__s2member_users_list_update_cols");
63
+ add_action ("personal_options_update", "ws_plugin__s2member_users_list_update_cols");
64
+ /**/
65
+ add_shortcode ("s2Member-PayPal-Button", "ws_plugin__s2member_paypal_button");
66
+ /*
67
+ Register the activation | de-activation routines.
68
+ */
69
+ register_activation_hook ($GLOBALS["WS_PLUGIN__"]["s2member"]["l"], "ws_plugin__s2member_activate");
70
+ register_deactivation_hook ($GLOBALS["WS_PLUGIN__"]["s2member"]["l"], "ws_plugin__s2member_deactivate");
71
+ ?>
includes/index.php ADDED
File without changes
includes/markdown/index.php ADDED
File without changes
includes/markdown/nc-markdown.inc.php ADDED
@@ -0,0 +1,1469 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ #
3
+ # PHP NC_Markdown ( no conflict version ) Modified by WebSharks, Inc. / 2009
4
+ # Uses custom a class name and interface. Excludes WP and the other interfaces.
5
+ #
6
+ # Original PHP Markdown ( class intact )
7
+ # Copyright (c) 2004-2008 Michel Fortin
8
+ # <http://www.michelf.com/projects/php-markdown/>
9
+ #
10
+ # Original Markdown
11
+ # Copyright (c) 2004-2006 John Gruber
12
+ # <http://daringfireball.net/projects/markdown/>
13
+ #
14
+
15
+ function NC_Markdown($text) {
16
+ #
17
+ # Initialize the parser and return the result of its transform method.
18
+ #
19
+ # Setup static parser variable.
20
+ static $parser;
21
+ if (!isset($parser)) {
22
+ $parser_class = NC_Markdown_Parser;
23
+ $parser = new $parser_class;
24
+ }
25
+
26
+ # Transform text using parser.
27
+ return $parser->transform($text);
28
+ }
29
+
30
+
31
+ #
32
+ # NC_Markdown Parser Class
33
+ #
34
+
35
+ class NC_Markdown_Parser {
36
+
37
+ # Regex to match balanced [brackets].
38
+ # Needed to insert a maximum bracked depth while converting to PHP.
39
+ var $nested_brackets_depth = 6;
40
+ var $nested_brackets_re;
41
+
42
+ var $nested_url_parenthesis_depth = 4;
43
+ var $nested_url_parenthesis_re;
44
+
45
+ # Table of hash values for escaped characters:
46
+ var $escape_chars = '\`*_{}[]()>#+-.!';
47
+ var $escape_chars_re;
48
+
49
+ # Change to ">" for HTML output.
50
+ var $empty_element_suffix = " />";
51
+ var $tab_width = 4;
52
+
53
+ # Change to `true` to disallow markup or entities.
54
+ var $no_markup = false;
55
+ var $no_entities = false;
56
+
57
+ # Predefined urls and titles for reference links and images.
58
+ var $predef_urls = array();
59
+ var $predef_titles = array();
60
+
61
+
62
+ function NC_Markdown_Parser() {
63
+ #
64
+ # Constructor function. Initialize appropriate member variables.
65
+ #
66
+ $this->_initDetab();
67
+ $this->prepareItalicsAndBold();
68
+
69
+ $this->nested_brackets_re =
70
+ str_repeat('(?>[^\[\]]+|\[', $this->nested_brackets_depth).
71
+ str_repeat('\])*', $this->nested_brackets_depth);
72
+
73
+ $this->nested_url_parenthesis_re =
74
+ str_repeat('(?>[^()\s]+|\(', $this->nested_url_parenthesis_depth).
75
+ str_repeat('(?>\)))*', $this->nested_url_parenthesis_depth);
76
+
77
+ $this->escape_chars_re = '['.preg_quote($this->escape_chars).']';
78
+
79
+ # Sort document, block, and span gamut in ascendent priority order.
80
+ asort($this->document_gamut);
81
+ asort($this->block_gamut);
82
+ asort($this->span_gamut);
83
+ }
84
+
85
+
86
+ # Internal hashes used during transformation.
87
+ var $urls = array();
88
+ var $titles = array();
89
+ var $html_hashes = array();
90
+
91
+ # Status flag to avoid invalid nesting.
92
+ var $in_anchor = false;
93
+
94
+
95
+ function setup() {
96
+ #
97
+ # Called before the transformation process starts to setup parser
98
+ # states.
99
+ #
100
+ # Clear global hashes.
101
+ $this->urls = $this->predef_urls;
102
+ $this->titles = $this->predef_titles;
103
+ $this->html_hashes = array();
104
+
105
+ $in_anchor = false;
106
+ }
107
+
108
+ function teardown() {
109
+ #
110
+ # Called after the transformation process to clear any variable
111
+ # which may be taking up memory unnecessarly.
112
+ #
113
+ $this->urls = array();
114
+ $this->titles = array();
115
+ $this->html_hashes = array();
116
+ }
117
+
118
+
119
+ function transform($text) {
120
+ #
121
+ # Main function. Performs some preprocessing on the input text
122
+ # and pass it through the document gamut.
123
+ #
124
+ $this->setup();
125
+
126
+ # Remove UTF-8 BOM and marker character in input, if present.
127
+ $text = preg_replace('{^\xEF\xBB\xBF|\x1A}', '', $text);
128
+
129
+ # Standardize line endings:
130
+ # DOS to Unix and Mac to Unix
131
+ $text = preg_replace('{\r\n?}', "\n", $text);
132
+
133
+ # Make sure $text ends with a couple of newlines:
134
+ $text .= "\n\n";
135
+
136
+ # Convert all tabs to spaces.
137
+ $text = $this->detab($text);
138
+
139
+ # Turn block-level HTML blocks into hash entries
140
+ $text = $this->hashHTMLBlocks($text);
141
+
142
+ # Strip any lines consisting only of spaces and tabs.
143
+ # This makes subsequent regexen easier to write, because we can
144
+ # match consecutive blank lines with /\n+/ instead of something
145
+ # contorted like /[ ]*\n+/ .
146
+ $text = preg_replace('/^[ ]+$/m', '', $text);
147
+
148
+ # Run document gamut methods.
149
+ foreach ($this->document_gamut as $method => $priority) {
150
+ $text = $this->$method($text);
151
+ }
152
+
153
+ $this->teardown();
154
+
155
+ return $text . "\n";
156
+ }
157
+
158
+ var $document_gamut = array(
159
+ # Strip link definitions, store in hashes.
160
+ "stripLinkDefinitions" => 20,
161
+
162
+ "runBasicBlockGamut" => 30,
163
+ );
164
+
165
+
166
+ function stripLinkDefinitions($text) {
167
+ #
168
+ # Strips link definitions from text, stores the URLs and titles in
169
+ # hash references.
170
+ #
171
+ $less_than_tab = $this->tab_width - 1;
172
+
173
+ # Link defs are in the form: ^[id]: url "optional title"
174
+ $text = preg_replace_callback('{
175
+ ^[ ]{0,'.$less_than_tab.'}\[(.+)\][ ]?: # id = $1
176
+ [ ]*
177
+ \n? # maybe *one* newline
178
+ [ ]*
179
+ <?(\S+?)>? # url = $2
180
+ [ ]*
181
+ \n? # maybe one newline
182
+ [ ]*
183
+ (?:
184
+ (?<=\s) # lookbehind for whitespace
185
+ ["(]
186
+ (.*?) # title = $3
187
+ [")]
188
+ [ ]*
189
+ )? # title is optional
190
+ (?:\n+|\Z)
191
+ }xm',
192
+ array(&$this, '_stripLinkDefinitions_callback'),
193
+ $text);
194
+ return $text;
195
+ }
196
+ function _stripLinkDefinitions_callback($matches) {
197
+ $link_id = strtolower($matches[1]);
198
+ $this->urls[$link_id] = $matches[2];
199
+ $this->titles[$link_id] =& $matches[3];
200
+ return ''; # String that will replace the block
201
+ }
202
+
203
+
204
+ function hashHTMLBlocks($text) {
205
+ if ($this->no_markup) return $text;
206
+
207
+ $less_than_tab = $this->tab_width - 1;
208
+
209
+ # Hashify HTML blocks:
210
+ # We only want to do this for block-level HTML tags, such as headers,
211
+ # lists, and tables. That's because we still want to wrap <p>s around
212
+ # "paragraphs" that are wrapped in non-block-level tags, such as anchors,
213
+ # phrase emphasis, and spans. The list of tags we're looking for is
214
+ # hard-coded:
215
+ #
216
+ # * List "a" is made of tags which can be both inline or block-level.
217
+ # These will be treated block-level when the start tag is alone on
218
+ # its line, otherwise they're not matched here and will be taken as
219
+ # inline later.
220
+ # * List "b" is made of tags which are always block-level;
221
+ #
222
+ $block_tags_a_re = 'ins|del';
223
+ $block_tags_b_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|'.
224
+ 'script|noscript|form|fieldset|iframe|math';
225
+
226
+ # Regular expression for the content of a block tag.
227
+ $nested_tags_level = 4;
228
+ $attr = '
229
+ (?> # optional tag attributes
230
+ \s # starts with whitespace
231
+ (?>
232
+ [^>"/]+ # text outside quotes
233
+ |
234
+ /+(?!>) # slash not followed by ">"
235
+ |
236
+ "[^"]*" # text inside double quotes (tolerate ">")
237
+ |
238
+ \'[^\']*\' # text inside single quotes (tolerate ">")
239
+ )*
240
+ )?
241
+ ';
242
+ $content =
243
+ str_repeat('
244
+ (?>
245
+ [^<]+ # content without tag
246
+ |
247
+ <\2 # nested opening tag
248
+ '.$attr.' # attributes
249
+ (?>
250
+ />
251
+ |
252
+ >', $nested_tags_level). # end of opening tag
253
+ '.*?'. # last level nested tag content
254
+ str_repeat('
255
+ </\2\s*> # closing nested tag
256
+ )
257
+ |
258
+ <(?!/\2\s*> # other tags with a different name
259
+ )
260
+ )*',
261
+ $nested_tags_level);
262
+ $content2 = str_replace('\2', '\3', $content);
263
+
264
+ # First, look for nested blocks, e.g.:
265
+ # <div>
266
+ # <div>
267
+ # tags for inner block must be indented.
268
+ # </div>
269
+ # </div>
270
+ #
271
+ # The outermost tags must start at the left margin for this to match, and
272
+ # the inner nested divs must be indented.
273
+ # We need to do this before the next, more liberal match, because the next
274
+ # match will start at the first `<div>` and stop at the first `</div>`.
275
+ $text = preg_replace_callback('{(?>
276
+ (?>
277
+ (?<=\n\n) # Starting after a blank line
278
+ | # or
279
+ \A\n? # the beginning of the doc
280
+ )
281
+ ( # save in $1
282
+
283
+ # Match from `\n<tag>` to `</tag>\n`, handling nested tags
284
+ # in between.
285
+
286
+ [ ]{0,'.$less_than_tab.'}
287
+ <('.$block_tags_b_re.')# start tag = $2
288
+ '.$attr.'> # attributes followed by > and \n
289
+ '.$content.' # content, support nesting
290
+ </\2> # the matching end tag
291
+ [ ]* # trailing spaces/tabs
292
+ (?=\n+|\Z) # followed by a newline or end of document
293
+
294
+ | # Special version for tags of group a.
295
+
296
+ [ ]{0,'.$less_than_tab.'}
297
+ <('.$block_tags_a_re.')# start tag = $3
298
+ '.$attr.'>[ ]*\n # attributes followed by >
299
+ '.$content2.' # content, support nesting
300
+ </\3> # the matching end tag
301
+ [ ]* # trailing spaces/tabs
302
+ (?=\n+|\Z) # followed by a newline or end of document
303
+
304
+ | # Special case just for <hr />. It was easier to make a special
305
+ # case than to make the other regex more complicated.
306
+
307
+ [ ]{0,'.$less_than_tab.'}
308
+ <(hr) # start tag = $2
309
+ '.$attr.' # attributes
310
+ /?> # the matching end tag
311
+ [ ]*
312
+ (?=\n{2,}|\Z) # followed by a blank line or end of document
313
+
314
+ | # Special case for standalone HTML comments:
315
+
316
+ [ ]{0,'.$less_than_tab.'}
317
+ (?s:
318
+ <!-- .*? -->
319
+ )
320
+ [ ]*
321
+ (?=\n{2,}|\Z) # followed by a blank line or end of document
322
+
323
+ | # PHP and ASP-style processor instructions (<? and <%)
324
+
325
+ [ ]{0,'.$less_than_tab.'}
326
+ (?s:
327
+ <([?%]) # $2
328
+ .*?
329
+ \2>
330
+ )
331
+ [ ]*
332
+ (?=\n{2,}|\Z) # followed by a blank line or end of document
333
+
334
+ )
335
+ )}Sxmi',
336
+ array(&$this, '_hashHTMLBlocks_callback'),
337
+ $text);
338
+
339
+ return $text;
340
+ }
341
+ function _hashHTMLBlocks_callback($matches) {
342
+ $text = $matches[1];
343
+ $key = $this->hashBlock($text);
344
+ return "\n\n$key\n\n";
345
+ }
346
+
347
+
348
+ function hashPart($text, $boundary = 'X') {
349
+ #
350
+ # Called whenever a tag must be hashed when a function insert an atomic
351
+ # element in the text stream. Passing $text to through this function gives
352
+ # a unique text-token which will be reverted back when calling unhash.
353
+ #
354
+ # The $boundary argument specify what character should be used to surround
355
+ # the token. By convension, "B" is used for block elements that needs not
356
+ # to be wrapped into paragraph tags at the end, ":" is used for elements
357
+ # that are word separators and "X" is used in the general case.
358
+ #
359
+ # Swap back any tag hash found in $text so we do not have to `unhash`
360
+ # multiple times at the end.
361
+ $text = $this->unhash($text);
362
+
363
+ # Then hash the block.
364
+ static $i = 0;
365
+ $key = "$boundary\x1A" . ++$i . $boundary;
366
+ $this->html_hashes[$key] = $text;
367
+ return $key; # String that will replace the tag.
368
+ }
369
+
370
+
371
+ function hashBlock($text) {
372
+ #
373
+ # Shortcut function for hashPart with block-level boundaries.
374
+ #
375
+ return $this->hashPart($text, 'B');
376
+ }
377
+
378
+
379
+ var $block_gamut = array(
380
+ #
381
+ # These are all the transformations that form block-level
382
+ # tags like paragraphs, headers, and list items.
383
+ #
384
+ "doHeaders" => 10,
385
+ "doHorizontalRules" => 20,
386
+
387
+ "doLists" => 40,
388
+ "doCodeBlocks" => 50,
389
+ "doBlockQuotes" => 60,
390
+ );
391
+
392
+ function runBlockGamut($text) {
393
+ #
394
+ # Run block gamut tranformations.
395
+ #
396
+ # We need to escape raw HTML in Markdown source before doing anything
397
+ # else. This need to be done for each block, and not only at the
398
+ # begining in the Markdown function since hashed blocks can be part of
399
+ # list items and could have been indented. Indented blocks would have
400
+ # been seen as a code block in a previous pass of hashHTMLBlocks.
401
+ $text = $this->hashHTMLBlocks($text);
402
+
403
+ return $this->runBasicBlockGamut($text);
404
+ }
405
+
406
+ function runBasicBlockGamut($text) {
407
+ #
408
+ # Run block gamut tranformations, without hashing HTML blocks. This is
409
+ # useful when HTML blocks are known to be already hashed, like in the first
410
+ # whole-document pass.
411
+ #
412
+ foreach ($this->block_gamut as $method => $priority) {
413
+ $text = $this->$method($text);
414
+ }
415
+
416
+ # Finally form paragraph and restore hashed blocks.
417
+ $text = $this->formParagraphs($text);
418
+
419
+ return $text;
420
+ }
421
+
422
+
423
+ function doHorizontalRules($text) {
424
+ # Do Horizontal Rules:
425
+ return preg_replace(
426
+ '{
427
+ ^[ ]{0,3} # Leading space
428
+ ([-*_]) # $1: First marker
429
+ (?> # Repeated marker group
430
+ [ ]{0,2} # Zero, one, or two spaces.
431
+ \1 # Marker character
432
+ ){2,} # Group repeated at least twice
433
+ [ ]* # Tailing spaces
434
+ $ # End of line.
435
+ }mx',
436
+ "\n".$this->hashBlock("<hr$this->empty_element_suffix")."\n",
437
+ $text);
438
+ }
439
+
440
+
441
+ var $span_gamut = array(
442
+ #
443
+ # These are all the transformations that occur *within* block-level
444
+ # tags like paragraphs, headers, and list items.
445
+ #
446
+ # Process character escapes, code spans, and inline HTML
447
+ # in one shot.
448
+ "parseSpan" => -30,
449
+
450
+ # Process anchor and image tags. Images must come first,
451
+ # because ![foo][f] looks like an anchor.
452
+ "doImages" => 10,
453
+ "doAnchors" => 20,
454
+
455
+ # Make links out of things like `<http://example.com/>`
456
+ # Must come after doAnchors, because you can use < and >
457
+ # delimiters in inline links like [this](<url>).
458
+ "doAutoLinks" => 30,
459
+ "encodeAmpsAndAngles" => 40,
460
+
461
+ "doItalicsAndBold" => 50,
462
+ "doHardBreaks" => 60,
463
+ );
464
+
465
+ function runSpanGamut($text) {
466
+ #
467
+ # Run span gamut tranformations.
468
+ #
469
+ foreach ($this->span_gamut as $method => $priority) {
470
+ $text = $this->$method($text);
471
+ }
472
+
473
+ return $text;
474
+ }
475
+
476
+
477
+ function doHardBreaks($text) {
478
+ # Do hard breaks:
479
+ return preg_replace_callback('/ {2,}\n/',
480
+ array(&$this, '_doHardBreaks_callback'), $text);
481
+ }
482
+ function _doHardBreaks_callback($matches) {
483
+ return $this->hashPart("<br$this->empty_element_suffix\n");
484
+ }
485
+
486
+
487
+ function doAnchors($text) {
488
+ #
489
+ # Turn Markdown link shortcuts into XHTML <a> tags.
490
+ #
491
+ if ($this->in_anchor) return $text;
492
+ $this->in_anchor = true;
493
+
494
+ #
495
+ # First, handle reference-style links: [link text] [id]
496
+ #
497
+ $text = preg_replace_callback('{
498
+ ( # wrap whole match in $1
499
+ \[
500
+ ('.$this->nested_brackets_re.') # link text = $2
501
+ \]
502
+
503
+ [ ]? # one optional space
504
+ (?:\n[ ]*)? # one optional newline followed by spaces
505
+
506
+ \[
507
+ (.*?) # id = $3
508
+ \]
509
+ )
510
+ }xs',
511
+ array(&$this, '_doAnchors_reference_callback'), $text);
512
+
513
+ #
514
+ # Next, inline-style links: [link text](url "optional title")
515
+ #
516
+ $text = preg_replace_callback('{
517
+ ( # wrap whole match in $1
518
+ \[
519
+ ('.$this->nested_brackets_re.') # link text = $2
520
+ \]
521
+ \( # literal paren
522
+ [ ]*
523
+ (?:
524
+ <(\S*)> # href = $3
525
+ |
526
+ ('.$this->nested_url_parenthesis_re.') # href = $4
527
+ )
528
+ [ ]*
529
+ ( # $5
530
+ ([\'"]) # quote char = $6
531
+ (.*?) # Title = $7
532
+ \6 # matching quote
533
+ [ ]* # ignore any spaces/tabs between closing quote and )
534
+ )? # title is optional
535
+ \)
536
+ )
537
+ }xs',
538
+ array(&$this, '_DoAnchors_inline_callback'), $text);
539
+
540
+ #
541
+ # Last, handle reference-style shortcuts: [link text]
542
+ # These must come last in case you've also got [link test][1]
543
+ # or [link test](/foo)
544
+ #
545
+ // $text = preg_replace_callback('{
546
+ // ( # wrap whole match in $1
547
+ // \[
548
+ // ([^\[\]]+) # link text = $2; can\'t contain [ or ]
549
+ // \]
550
+ // )
551
+ // }xs',
552
+ // array(&$this, '_doAnchors_reference_callback'), $text);
553
+
554
+ $this->in_anchor = false;
555
+ return $text;
556
+ }
557
+ function _doAnchors_reference_callback($matches) {
558
+ $whole_match = $matches[1];
559
+ $link_text = $matches[2];
560
+ $link_id =& $matches[3];
561
+
562
+ if ($link_id == "") {
563
+ # for shortcut links like [this][] or [this].
564
+ $link_id = $link_text;
565
+ }
566
+
567
+ # lower-case and turn embedded newlines into spaces
568
+ $link_id = strtolower($link_id);
569
+ $link_id = preg_replace('{[ ]?\n}', ' ', $link_id);
570
+
571
+ if (isset($this->urls[$link_id])) {
572
+ $url = $this->urls[$link_id];
573
+ $url = $this->encodeAttribute($url);
574
+
575
+ $result = "<a href=\"$url\"";
576
+ if ( isset( $this->titles[$link_id] ) ) {
577
+ $title = $this->titles[$link_id];
578
+ $title = $this->encodeAttribute($title);
579
+ $result .= " title=\"$title\"";
580
+ }
581
+
582
+ $link_text = $this->runSpanGamut($link_text);
583
+ $result .= ">$link_text</a>";
584
+ $result = $this->hashPart($result);
585
+ }
586
+ else {
587
+ $result = $whole_match;
588
+ }
589
+ return $result;
590
+ }
591
+ function _doAnchors_inline_callback($matches) {
592
+ $whole_match = $matches[1];
593
+ $link_text = $this->runSpanGamut($matches[2]);
594
+ $url = $matches[3] == '' ? $matches[4] : $matches[3];
595
+ $title =& $matches[7];
596
+
597
+ $url = $this->encodeAttribute($url);
598
+
599
+ $result = "<a href=\"$url\"";
600
+ if (isset($title)) {
601
+ $title = $this->encodeAttribute($title);
602
+ $result .= " title=\"$title\"";
603
+ }
604
+
605
+ $link_text = $this->runSpanGamut($link_text);
606
+ $result .= ">$link_text</a>";
607
+
608
+ return $this->hashPart($result);
609
+ }
610
+
611
+
612
+ function doImages($text) {
613
+ #
614
+ # Turn Markdown image shortcuts into <img> tags.
615
+ #
616
+ #
617
+ # First, handle reference-style labeled images: ![alt text][id]
618
+ #
619
+ $text = preg_replace_callback('{
620
+ ( # wrap whole match in $1
621
+ !\[
622
+ ('.$this->nested_brackets_re.') # alt text = $2
623
+ \]
624
+
625
+ [ ]? # one optional space
626
+ (?:\n[ ]*)? # one optional newline followed by spaces
627
+
628
+ \[
629
+ (.*?) # id = $3
630
+ \]
631
+
632
+ )
633
+ }xs',
634
+ array(&$this, '_doImages_reference_callback'), $text);
635
+
636
+ #
637
+ # Next, handle inline images: ![alt text](url "optional title")
638
+ # Don't forget: encode * and _
639
+ #
640
+ $text = preg_replace_callback('{
641
+ ( # wrap whole match in $1
642
+ !\[
643
+ ('.$this->nested_brackets_re.') # alt text = $2
644
+ \]
645
+ \s? # One optional whitespace character
646
+ \( # literal paren
647
+ [ ]*
648
+ (?:
649
+ <(\S*)> # src url = $3
650
+ |
651
+ ('.$this->nested_url_parenthesis_re.') # src url = $4
652
+ )
653
+ [ ]*
654
+ ( # $5
655
+ ([\'"]) # quote char = $6
656
+ (.*?) # title = $7
657
+ \6 # matching quote
658
+ [ ]*
659
+ )? # title is optional
660
+ \)
661
+ )
662
+ }xs',
663
+ array(&$this, '_doImages_inline_callback'), $text);
664
+
665
+ return $text;
666
+ }
667
+ function _doImages_reference_callback($matches) {
668
+ $whole_match = $matches[1];
669
+ $alt_text = $matches[2];
670
+ $link_id = strtolower($matches[3]);
671
+
672
+ if ($link_id == "") {
673
+ $link_id = strtolower($alt_text); # for shortcut links like ![this][].
674
+ }
675
+
676
+ $alt_text = $this->encodeAttribute($alt_text);
677
+ if (isset($this->urls[$link_id])) {
678
+ $url = $this->encodeAttribute($this->urls[$link_id]);
679
+ $result = "<img src=\"$url\" alt=\"$alt_text\"";
680
+ if (isset($this->titles[$link_id])) {
681
+ $title = $this->titles[$link_id];
682
+ $title = $this->encodeAttribute($title);
683
+ $result .= " title=\"$title\"";
684
+ }
685
+ $result .= $this->empty_element_suffix;
686
+ $result = $this->hashPart($result);
687
+ }
688
+ else {
689
+ # If there's no such link ID, leave intact:
690
+ $result = $whole_match;
691
+ }
692
+
693
+ return $result;
694
+ }
695
+ function _doImages_inline_callback($matches) {
696
+ $whole_match = $matches[1];
697
+ $alt_text = $matches[2];
698
+ $url = $matches[3] == '' ? $matches[4] : $matches[3];
699
+ $title =& $matches[7];
700
+
701
+ $alt_text = $this->encodeAttribute($alt_text);
702
+ $url = $this->encodeAttribute($url);
703
+ $result = "<img src=\"$url\" alt=\"$alt_text\"";
704
+ if (isset($title)) {
705
+ $title = $this->encodeAttribute($title);
706
+ $result .= " title=\"$title\""; # $title already quoted
707
+ }
708
+ $result .= $this->empty_element_suffix;
709
+
710
+ return $this->hashPart($result);
711
+ }
712
+
713
+
714
+ function doHeaders($text) {
715
+ # Setext-style headers:
716
+ # Header 1
717
+ # ========
718
+ #
719
+ # Header 2
720
+ # --------
721
+ #
722
+ $text = preg_replace_callback('{ ^(.+?)[ ]*\n(=+|-+)[ ]*\n+ }mx',
723
+ array(&$this, '_doHeaders_callback_setext'), $text);
724
+
725
+ # atx-style headers:
726
+ # # Header 1
727
+ # ## Header 2
728
+ # ## Header 2 with closing hashes ##
729
+ # ...
730
+ # ###### Header 6
731
+ #
732
+ $text = preg_replace_callback('{
733
+ ^(\#{1,6}) # $1 = string of #\'s
734
+ [ ]*
735
+ (.+?) # $2 = Header text
736
+ [ ]*
737
+ \#* # optional closing #\'s (not counted)
738
+ \n+
739
+ }xm',
740
+ array(&$this, '_doHeaders_callback_atx'), $text);
741
+
742
+ return $text;
743
+ }
744
+ function _doHeaders_callback_setext($matches) {
745
+ # Terrible hack to check we haven't found an empty list item.
746
+ if ($matches[2] == '-' && preg_match('{^-(?: |$)}', $matches[1]))
747
+ return $matches[0];
748
+
749
+ $level = $matches[2]{0} == '=' ? 1 : 2;
750
+ $block = "<h$level>".$this->runSpanGamut($matches[1])."</h$level>";
751
+ return "\n" . $this->hashBlock($block) . "\n\n";
752
+ }
753
+ function _doHeaders_callback_atx($matches) {
754
+ $level = strlen($matches[1]);
755
+ $block = "<h$level>".$this->runSpanGamut($matches[2])."</h$level>";
756
+ return "\n" . $this->hashBlock($block) . "\n\n";
757
+ }
758
+
759
+
760
+ function doLists($text) {
761
+ #
762
+ # Form HTML ordered (numbered) and unordered (bulleted) lists.
763
+ #
764
+ $less_than_tab = $this->tab_width - 1;
765
+
766
+ # Re-usable patterns to match list item bullets and number markers:
767
+ $marker_ul_re = '[*+-]';
768
+ $marker_ol_re = '\d+[.]';
769
+ $marker_any_re = "(?:$marker_ul_re|$marker_ol_re)";
770
+
771
+ $markers_relist = array($marker_ul_re, $marker_ol_re);
772
+
773
+ foreach ($markers_relist as $marker_re) {
774
+ # Re-usable pattern to match any entirel ul or ol list:
775
+ $whole_list_re = '
776
+ ( # $1 = whole list
777
+ ( # $2
778
+ [ ]{0,'.$less_than_tab.'}
779
+ ('.$marker_re.') # $3 = first list item marker
780
+ [ ]+
781
+ )
782
+ (?s:.+?)
783
+ ( # $4
784
+ \z
785
+ |
786
+ \n{2,}
787
+ (?=\S)
788
+ (?! # Negative lookahead for another list item marker
789
+ [ ]*
790
+ '.$marker_re.'[ ]+
791
+ )
792
+ )
793
+ )
794
+ '; // mx
795
+
796
+ # We use a different prefix before nested lists than top-level lists.
797
+ # See extended comment in _ProcessListItems().
798
+
799
+ if ($this->list_level) {
800
+ $text = preg_replace_callback('{
801
+ ^
802
+ '.$whole_list_re.'
803
+ }mx',
804
+ array(&$this, '_doLists_callback'), $text);
805
+ }
806
+ else {
807
+ $text = preg_replace_callback('{
808
+ (?:(?<=\n)\n|\A\n?) # Must eat the newline
809
+ '.$whole_list_re.'
810
+ }mx',
811
+ array(&$this, '_doLists_callback'), $text);
812
+ }
813
+ }
814
+
815
+ return $text;
816
+ }
817
+ function _doLists_callback($matches) {
818
+ # Re-usable patterns to match list item bullets and number markers:
819
+ $marker_ul_re = '[*+-]';
820
+ $marker_ol_re = '\d+[.]';
821
+ $marker_any_re = "(?:$marker_ul_re|$marker_ol_re)";
822
+
823
+ $list = $matches[1];
824
+ $list_type = preg_match("/$marker_ul_re/", $matches[3]) ? "ul" : "ol";
825
+
826
+ $marker_any_re = ( $list_type == "ul" ? $marker_ul_re : $marker_ol_re );
827
+
828
+ $list .= "\n";
829
+ $result = $this->processListItems($list, $marker_any_re);
830
+
831
+ $result = $this->hashBlock("<$list_type>\n" . $result . "</$list_type>");
832
+ return "\n". $result ."\n\n";
833
+ }
834
+
835
+ var $list_level = 0;
836
+
837
+ function processListItems($list_str, $marker_any_re) {
838
+ #
839
+ # Process the contents of a single ordered or unordered list, splitting it
840
+ # into individual list items.
841
+ #
842
+ # The $this->list_level global keeps track of when we're inside a list.
843
+ # Each time we enter a list, we increment it; when we leave a list,
844
+ # we decrement. If it's zero, we're not in a list anymore.
845
+ #
846
+ # We do this because when we're not inside a list, we want to treat
847
+ # something like this:
848
+ #
849
+ # I recommend upgrading to version
850
+ # 8. Oops, now this line is treated
851
+ # as a sub-list.
852
+ #
853
+ # As a single paragraph, despite the fact that the second line starts
854
+ # with a digit-period-space sequence.
855
+ #
856
+ # Whereas when we're inside a list (or sub-list), that line will be
857
+ # treated as the start of a sub-list. What a kludge, huh? This is
858
+ # an aspect of Markdown's syntax that's hard to parse perfectly
859
+ # without resorting to mind-reading. Perhaps the solution is to
860
+ # change the syntax rules such that sub-lists must start with a
861
+ # starting cardinal number; e.g. "1." or "a.".
862
+
863
+ $this->list_level++;
864
+
865
+ # trim trailing blank lines:
866
+ $list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str);
867
+
868
+ $list_str = preg_replace_callback('{
869
+ (\n)? # leading line = $1
870
+ (^[ ]*) # leading whitespace = $2
871
+ ('.$marker_any_re.' # list marker and space = $3
872
+ (?:[ ]+|(?=\n)) # space only required if item is not empty
873
+ )
874
+ ((?s:.*?)) # list item text = $4
875
+ (?:(\n+(?=\n))|\n) # tailing blank line = $5
876
+ (?= \n* (\z | \2 ('.$marker_any_re.') (?:[ ]+|(?=\n))))
877
+ }xm',
878
+ array(&$this, '_processListItems_callback'), $list_str);
879
+
880
+ $this->list_level--;
881
+ return $list_str;
882
+ }
883
+ function _processListItems_callback($matches) {
884
+ $item = $matches[4];
885
+ $leading_line =& $matches[1];
886
+ $leading_space =& $matches[2];
887
+ $marker_space = $matches[3];
888
+ $tailing_blank_line =& $matches[5];
889
+
890
+ if ($leading_line || $tailing_blank_line ||
891
+ preg_match('/\n{2,}/', $item))
892
+ {
893
+ # Replace marker with the appropriate whitespace indentation
894
+ $item = $leading_space . str_repeat(' ', strlen($marker_space)) . $item;
895
+ $item = $this->runBlockGamut($this->outdent($item)."\n");
896
+ }
897
+ else {
898
+ # Recursion for sub-lists:
899
+ $item = $this->doLists($this->outdent($item));
900
+ $item = preg_replace('/\n+$/', '', $item);
901
+ $item = $this->runSpanGamut($item);
902
+ }
903
+
904
+ return "<li>" . $item . "</li>\n";
905
+ }
906
+
907
+
908
+ function doCodeBlocks($text) {
909
+ #
910
+ # Process Markdown `<pre><code>` blocks.
911
+ #
912
+ $text = preg_replace_callback('{
913
+ (?:\n\n|\A\n?)
914
+ ( # $1 = the code block -- one or more lines, starting with a space/tab
915
+ (?>
916
+ [ ]{'.$this->tab_width.'} # Lines must start with a tab or a tab-width of spaces
917
+ .*\n+
918
+ )+
919
+ )
920
+ ((?=^[ ]{0,'.$this->tab_width.'}\S)|\Z) # Lookahead for non-space at line-start, or end of doc
921
+ }xm',
922
+ array(&$this, '_doCodeBlocks_callback'), $text);
923
+
924
+ return $text;
925
+ }
926
+ function _doCodeBlocks_callback($matches) {
927
+ $codeblock = $matches[1];
928
+
929
+ $codeblock = $this->outdent($codeblock);
930
+ $codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
931
+
932
+ # trim leading newlines and trailing newlines
933
+ $codeblock = preg_replace('/\A\n+|\n+\z/', '', $codeblock);
934
+
935
+ $codeblock = "<pre><code>$codeblock\n</code></pre>";
936
+ return "\n\n".$this->hashBlock($codeblock)."\n\n";
937
+ }
938
+
939
+
940
+ function makeCodeSpan($code) {
941
+ #
942
+ # Create a code span markup for $code. Called from handleSpanToken.
943
+ #
944
+ $code = htmlspecialchars(trim($code), ENT_NOQUOTES);
945
+ return $this->hashPart("<code>$code</code>");
946
+ }
947
+
948
+
949
+ var $em_relist = array(
950
+ '' => '(?:(?<!\*)\*(?!\*)|(?<!_)_(?!_))(?=\S)(?![.,:;]\s)',
951
+ '*' => '(?<=\S)(?<!\*)\*(?!\*)',
952
+ '_' => '(?<=\S)(?<!_)_(?!_)',
953
+ );
954
+ var $strong_relist = array(
955
+ '' => '(?:(?<!\*)\*\*(?!\*)|(?<!_)__(?!_))(?=\S)(?![.,:;]\s)',
956
+ '**' => '(?<=\S)(?<!\*)\*\*(?!\*)',
957
+ '__' => '(?<=\S)(?<!_)__(?!_)',
958
+ );
959
+ var $em_strong_relist = array(
960
+ '' => '(?:(?<!\*)\*\*\*(?!\*)|(?<!_)___(?!_))(?=\S)(?![.,:;]\s)',
961
+ '***' => '(?<=\S)(?<!\*)\*\*\*(?!\*)',
962
+ '___' => '(?<=\S)(?<!_)___(?!_)',
963
+ );
964
+ var $em_strong_prepared_relist;
965
+
966
+ function prepareItalicsAndBold() {
967
+ #
968
+ # Prepare regular expressions for seraching emphasis tokens in any
969
+ # context.
970
+ #
971
+ foreach ($this->em_relist as $em => $em_re) {
972
+ foreach ($this->strong_relist as $strong => $strong_re) {
973
+ # Construct list of allowed token expressions.
974
+ $token_relist = array();
975
+ if (isset($this->em_strong_relist["$em$strong"])) {
976
+ $token_relist[] = $this->em_strong_relist["$em$strong"];
977
+ }
978
+ $token_relist[] = $em_re;
979
+ $token_relist[] = $strong_re;
980
+
981
+ # Construct master expression from list.
982
+ $token_re = '{('. implode('|', $token_relist) .')}';
983
+ $this->em_strong_prepared_relist["$em$strong"] = $token_re;
984
+ }
985
+ }
986
+ }
987
+
988
+ function doItalicsAndBold($text) {
989
+ $token_stack = array('');
990
+ $text_stack = array('');
991
+ $em = '';
992
+ $strong = '';
993
+ $tree_char_em = false;
994
+
995
+ while (1) {
996
+ #
997
+ # Get prepared regular expression for seraching emphasis tokens
998
+ # in current context.
999
+ #
1000
+ $token_re = $this->em_strong_prepared_relist["$em$strong"];
1001
+
1002
+ #
1003
+ # Each loop iteration seach for the next emphasis token.
1004
+ # Each token is then passed to handleSpanToken.
1005
+ #
1006
+ $parts = preg_split($token_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE);
1007
+ $text_stack[0] .= $parts[0];
1008
+ $token =& $parts[1];
1009
+ $text =& $parts[2];
1010
+
1011
+ if (empty($token)) {
1012
+ # Reached end of text span: empty stack without emitting.
1013
+ # any more emphasis.
1014
+ while ($token_stack[0]) {
1015
+ $text_stack[1] .= array_shift($token_stack);
1016
+ $text_stack[0] .= array_shift($text_stack);
1017
+ }
1018
+ break;
1019
+ }
1020
+
1021
+ $token_len = strlen($token);
1022
+ if ($tree_char_em) {
1023
+ # Reached closing marker while inside a three-char emphasis.
1024
+ if ($token_len == 3) {
1025
+ # Three-char closing marker, close em and strong.
1026
+ array_shift($token_stack);
1027
+ $span = array_shift($text_stack);
1028
+ $span = $this->runSpanGamut($span);
1029
+ $span = "<strong><em>$span</em></strong>";
1030
+ $text_stack[0] .= $this->hashPart($span);
1031
+ $em = '';
1032
+ $strong = '';
1033
+ } else {
1034
+ # Other closing marker: close one em or strong and
1035
+ # change current token state to match the other
1036
+ $token_stack[0] = str_repeat($token{0}, 3-$token_len);
1037
+ $tag = $token_len == 2 ? "strong" : "em";
1038
+ $span = $text_stack[0];
1039
+ $span = $this->runSpanGamut($span);
1040
+ $span = "<$tag>$span</$tag>";
1041
+ $text_stack[0] = $this->hashPart($span);
1042
+ $$tag = ''; # $$tag stands for $em or $strong
1043
+ }
1044
+ $tree_char_em = false;
1045
+ } else if ($token_len == 3) {
1046
+ if ($em) {
1047
+ # Reached closing marker for both em and strong.
1048
+ # Closing strong marker:
1049
+ for ($i = 0; $i < 2; ++$i) {
1050
+ $shifted_token = array_shift($token_stack);
1051
+ $tag = strlen($shifted_token) == 2 ? "strong" : "em";
1052
+ $span = array_shift($text_stack);
1053
+ $span = $this->runSpanGamut($span);
1054
+ $span = "<$tag>$span</$tag>";
1055
+ $text_stack[0] .= $this->hashPart($span);
1056
+ $$tag = ''; # $$tag stands for $em or $strong
1057
+ }
1058
+ } else {
1059
+ # Reached opening three-char emphasis marker. Push on token
1060
+ # stack; will be handled by the special condition above.
1061
+ $em = $token{0};
1062
+ $strong = "$em$em";
1063
+ array_unshift($token_stack, $token);
1064
+ array_unshift($text_stack, '');
1065
+ $tree_char_em = true;
1066
+ }
1067
+ } else if ($token_len == 2) {
1068
+ if ($strong) {
1069
+ # Unwind any dangling emphasis marker:
1070
+ if (strlen($token_stack[0]) == 1) {
1071
+ $text_stack[1] .= array_shift($token_stack);
1072
+ $text_stack[0] .= array_shift($text_stack);
1073
+ }
1074
+ # Closing strong marker:
1075
+ array_shift($token_stack);
1076
+ $span = array_shift($text_stack);
1077
+ $span = $this->runSpanGamut($span);
1078
+ $span = "<strong>$span</strong>";
1079
+ $text_stack[0] .= $this->hashPart($span);
1080
+ $strong = '';
1081
+ } else {
1082
+ array_unshift($token_stack, $token);
1083
+ array_unshift($text_stack, '');
1084
+ $strong = $token;
1085
+ }
1086
+ } else {
1087
+ # Here $token_len == 1
1088
+ if ($em) {
1089
+ if (strlen($token_stack[0]) == 1) {
1090
+ # Closing emphasis marker:
1091
+ array_shift($token_stack);
1092
+ $span = array_shift($text_stack);
1093
+ $span = $this->runSpanGamut($span);
1094
+ $span = "<em>$span</em>";
1095
+ $text_stack[0] .= $this->hashPart($span);
1096
+ $em = '';
1097
+ } else {
1098
+ $text_stack[0] .= $token;
1099
+ }
1100
+ } else {
1101
+ array_unshift($token_stack, $token);
1102
+ array_unshift($text_stack, '');
1103
+ $em = $token;
1104
+ }
1105
+ }
1106
+ }
1107
+ return $text_stack[0];
1108
+ }
1109
+
1110
+
1111
+ function doBlockQuotes($text) {
1112
+ $text = preg_replace_callback('/
1113
+ ( # Wrap whole match in $1
1114
+ (?>
1115
+ ^[ ]*>[ ]? # ">" at the start of a line
1116
+ .+\n # rest of the first line
1117
+ (.+\n)* # subsequent consecutive lines
1118
+ \n* # blanks
1119
+ )+
1120
+ )
1121
+ /xm',
1122
+ array(&$this, '_doBlockQuotes_callback'), $text);
1123
+
1124
+ return $text;
1125
+ }
1126
+ function _doBlockQuotes_callback($matches) {
1127
+ $bq = $matches[1];
1128
+ # trim one level of quoting - trim whitespace-only lines
1129
+ $bq = preg_replace('/^[ ]*>[ ]?|^[ ]+$/m', '', $bq);
1130
+ $bq = $this->runBlockGamut($bq); # recurse
1131
+
1132
+ $bq = preg_replace('/^/m', " ", $bq);
1133
+ # These leading spaces cause problem with <pre> content,
1134
+ # so we need to fix that:
1135
+ $bq = preg_replace_callback('{(\s*<pre>.+?</pre>)}sx',
1136
+ array(&$this, '_DoBlockQuotes_callback2'), $bq);
1137
+
1138
+ return "\n". $this->hashBlock("<blockquote>\n$bq\n</blockquote>")."\n\n";
1139
+ }
1140
+ function _doBlockQuotes_callback2($matches) {
1141
+ $pre = $matches[1];
1142
+ $pre = preg_replace('/^ /m', '', $pre);
1143
+ return $pre;
1144
+ }
1145
+
1146
+
1147
+ function formParagraphs($text) {
1148
+ #
1149
+ # Params:
1150
+ # $text - string to process with html <p> tags
1151
+ #
1152
+ # Strip leading and trailing lines:
1153
+ $text = preg_replace('/\A\n+|\n+\z/', '', $text);
1154
+
1155
+ $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY);
1156
+
1157
+ #
1158
+ # Wrap <p> tags and unhashify HTML blocks
1159
+ #
1160
+ foreach ($grafs as $key => $value) {
1161
+ if (!preg_match('/^B\x1A[0-9]+B$/', $value)) {
1162
+ # Is a paragraph.
1163
+ $value = $this->runSpanGamut($value);
1164
+ $value = preg_replace('/^([ ]*)/', "<p>", $value);
1165
+ $value .= "</p>";
1166
+ $grafs[$key] = $this->unhash($value);
1167
+ }
1168
+ else {
1169
+ # Is a block.
1170
+ # Modify elements of @grafs in-place...
1171
+ $graf = $value;
1172
+ $block = $this->html_hashes[$graf];
1173
+ $graf = $block;
1174
+ // if (preg_match('{
1175
+ // \A
1176
+ // ( # $1 = <div> tag
1177
+ // <div \s+
1178
+ // [^>]*
1179
+ // \b
1180
+ // markdown\s*=\s* ([\'"]) # $2 = attr quote char
1181
+ // 1
1182
+ // \2
1183
+ // [^>]*
1184
+ // >
1185
+ // )
1186
+ // ( # $3 = contents
1187
+ // .*
1188
+ // )
1189
+ // (</div>) # $4 = closing tag
1190
+ // \z
1191
+ // }xs', $block, $matches))
1192
+ // {
1193
+ // list(, $div_open, , $div_content, $div_close) = $matches;
1194
+ //
1195
+ // # We can't call Markdown(), because that resets the hash;
1196
+ // # that initialization code should be pulled into its own sub, though.
1197
+ // $div_content = $this->hashHTMLBlocks($div_content);
1198
+ //
1199
+ // # Run document gamut methods on the content.
1200
+ // foreach ($this->document_gamut as $method => $priority) {
1201
+ // $div_content = $this->$method($div_content);
1202
+ // }
1203
+ //
1204
+ // $div_open = preg_replace(
1205
+ // '{\smarkdown\s*=\s*([\'"]).+?\1}', '', $div_open);
1206
+ //
1207
+ // $graf = $div_open . "\n" . $div_content . "\n" . $div_close;
1208
+ // }
1209
+ $grafs[$key] = $graf;
1210
+ }
1211
+ }
1212
+
1213
+ return implode("\n\n", $grafs);
1214
+ }
1215
+
1216
+
1217
+ function encodeAttribute($text) {
1218
+ #
1219
+ # Encode text for a double-quoted HTML attribute. This function
1220
+ # is *not* suitable for attributes enclosed in single quotes.
1221
+ #
1222
+ $text = $this->encodeAmpsAndAngles($text);
1223
+ $text = str_replace('"', '&quot;', $text);
1224
+ return $text;
1225
+ }
1226
+
1227
+
1228
+ function encodeAmpsAndAngles($text) {
1229
+ #
1230
+ # Smart processing for ampersands and angle brackets that need to
1231
+ # be encoded. Valid character entities are left alone unless the
1232
+ # no-entities mode is set.
1233
+ #
1234
+ if ($this->no_entities) {
1235
+ $text = str_replace('&', '&amp;', $text);
1236
+ } else {
1237
+ # Ampersand-encoding based entirely on Nat Irons's Amputator
1238
+ # MT plugin: <http://bumppo.net/projects/amputator/>
1239
+ $text = preg_replace('/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/',
1240
+ '&amp;', $text);;
1241
+ }
1242
+ # Encode remaining <'s
1243
+ $text = str_replace('<', '&lt;', $text);
1244
+
1245
+ return $text;
1246
+ }
1247
+
1248
+
1249
+ function doAutoLinks($text) {
1250
+ $text = preg_replace_callback('{<((https?|ftp|dict):[^\'">\s]+)>}i',
1251
+ array(&$this, '_doAutoLinks_url_callback'), $text);
1252
+
1253
+ # Email addresses: <address@domain.foo>
1254
+ $text = preg_replace_callback('{
1255
+ <
1256
+ (?:mailto:)?
1257
+ (
1258
+ [-.\w\x80-\xFF]+
1259
+ \@
1260
+ [-a-z0-9\x80-\xFF]+(\.[-a-z0-9\x80-\xFF]+)*\.[a-z]+
1261
+ )
1262
+ >
1263
+ }xi',
1264
+ array(&$this, '_doAutoLinks_email_callback'), $text);
1265
+
1266
+ return $text;
1267
+ }
1268
+ function _doAutoLinks_url_callback($matches) {
1269
+ $url = $this->encodeAttribute($matches[1]);
1270
+ $link = "<a href=\"$url\">$url</a>";
1271
+ return $this->hashPart($link);
1272
+ }
1273
+ function _doAutoLinks_email_callback($matches) {
1274
+ $address = $matches[1];
1275
+ $link = $this->encodeEmailAddress($address);
1276
+ return $this->hashPart($link);
1277
+ }
1278
+
1279
+
1280
+ function encodeEmailAddress($addr) {
1281
+ #
1282
+ # Input: an email address, e.g. "foo@example.com"
1283
+ #
1284
+ # Output: the email address as a mailto link, with each character
1285
+ # of the address encoded as either a decimal or hex entity, in
1286
+ # the hopes of foiling most address harvesting spam bots. E.g.:
1287
+ #
1288
+ # <p><a href="&#109;&#x61;&#105;&#x6c;&#116;&#x6f;&#58;&#x66;o&#111;
1289
+ # &#x40;&#101;&#x78;&#97;&#x6d;&#112;&#x6c;&#101;&#46;&#x63;&#111;
1290
+ # &#x6d;">&#x66;o&#111;&#x40;&#101;&#x78;&#97;&#x6d;&#112;&#x6c;
1291
+ # &#101;&#46;&#x63;&#111;&#x6d;</a></p>
1292
+ #
1293
+ # Based by a filter by Matthew Wickline, posted to BBEdit-Talk.
1294
+ # With some optimizations by Milian Wolff.
1295
+ #
1296
+ $addr = "mailto:" . $addr;
1297
+ $chars = preg_split('/(?<!^)(?!$)/', $addr);
1298
+ $seed = (int)abs(crc32($addr) / strlen($addr)); # Deterministic seed.
1299
+
1300
+ foreach ($chars as $key => $char) {
1301
+ $ord = ord($char);
1302
+ # Ignore non-ascii chars.
1303
+ if ($ord < 128) {
1304
+ $r = ($seed * (1 + $key)) % 100; # Pseudo-random function.
1305
+ # roughly 10% raw, 45% hex, 45% dec
1306
+ # '@' *must* be encoded. I insist.
1307
+ if ($r > 90 && $char != '@') /* do nothing */;
1308
+ else if ($r < 45) $chars[$key] = '&#x'.dechex($ord).';';
1309
+ else $chars[$key] = '&#'.$ord.';';
1310
+ }
1311
+ }
1312
+
1313
+ $addr = implode('', $chars);
1314
+ $text = implode('', array_slice($chars, 7)); # text without `mailto:`
1315
+ $addr = "<a href=\"$addr\">$text</a>";
1316
+
1317
+ return $addr;
1318
+ }
1319
+
1320
+
1321
+ function parseSpan($str) {
1322
+ #
1323
+ # Take the string $str and parse it into tokens, hashing embeded HTML,
1324
+ # escaped characters and handling code spans.
1325
+ #
1326
+ $output = '';
1327
+
1328
+ $span_re = '{
1329
+ (
1330
+ \\\\'.$this->escape_chars_re.'
1331
+ |
1332
+ (?<![`\\\\])
1333
+ `+ # code span marker
1334
+ '.( $this->no_markup ? '' : '
1335
+ |
1336
+ <!-- .*? --> # comment
1337
+ |
1338
+ <\?.*?\?> | <%.*?%> # processing instruction
1339
+ |
1340
+ <[/!$]?[-a-zA-Z0-9:]+ # regular tags
1341
+ (?>
1342
+ \s
1343
+ (?>[^"\'>]+|"[^"]*"|\'[^\']*\')*
1344
+ )?
1345
+ >
1346
+ ').'
1347
+ )
1348
+ }xs';
1349
+
1350
+ while (1) {
1351
+ #
1352
+ # Each loop iteration seach for either the next tag, the next
1353
+ # openning code span marker, or the next escaped character.
1354
+ # Each token is then passed to handleSpanToken.
1355
+ #
1356
+ $parts = preg_split($span_re, $str, 2, PREG_SPLIT_DELIM_CAPTURE);
1357
+
1358
+ # Create token from text preceding tag.
1359
+ if ($parts[0] != "") {
1360
+ $output .= $parts[0];
1361
+ }
1362
+
1363
+ # Check if we reach the end.
1364
+ if (isset($parts[1])) {
1365
+ $output .= $this->handleSpanToken($parts[1], $parts[2]);
1366
+ $str = $parts[2];
1367
+ }
1368
+ else {
1369
+ break;
1370
+ }
1371
+ }
1372
+
1373
+ return $output;
1374
+ }
1375
+
1376
+
1377
+ function handleSpanToken($token, &$str) {
1378
+ #
1379
+ # Handle $token provided by parseSpan by determining its nature and
1380
+ # returning the corresponding value that should replace it.
1381
+ #
1382
+ switch ($token{0}) {
1383
+ case "\\":
1384
+ return $this->hashPart("&#". ord($token{1}). ";");
1385
+ case "`":
1386
+ # Search for end marker in remaining text.
1387
+ if (preg_match('/^(.*?[^`])'.preg_quote($token).'(?!`)(.*)$/sm',
1388
+ $str, $matches))
1389
+ {
1390
+ $str = $matches[2];
1391
+ $codespan = $this->makeCodeSpan($matches[1]);
1392
+ return $this->hashPart($codespan);
1393
+ }
1394
+ return $token; // return as text since no ending marker found.
1395
+ default:
1396
+ return $this->hashPart($token);
1397
+ }
1398
+ }
1399
+
1400
+
1401
+ function outdent($text) {
1402
+ #
1403
+ # Remove one level of line-leading tabs or spaces
1404
+ #
1405
+ return preg_replace('/^(\t|[ ]{1,'.$this->tab_width.'})/m', '', $text);
1406
+ }
1407
+
1408
+
1409
+ # String length function for detab. `_initDetab` will create a function to
1410
+ # hanlde UTF-8 if the default function does not exist.
1411
+ var $utf8_strlen = 'mb_strlen';
1412
+
1413
+ function detab($text) {
1414
+ #
1415
+ # Replace tabs with the appropriate amount of space.
1416
+ #
1417
+ # For each line we separate the line in blocks delemited by
1418
+ # tab characters. Then we reconstruct every line by adding the
1419
+ # appropriate number of space between each blocks.
1420
+
1421
+ $text = preg_replace_callback('/^.*\t.*$/m',
1422
+ array(&$this, '_detab_callback'), $text);
1423
+
1424
+ return $text;
1425
+ }
1426
+ function _detab_callback($matches) {
1427
+ $line = $matches[0];
1428
+ $strlen = $this->utf8_strlen; # strlen function for UTF-8.
1429
+
1430
+ # Split in blocks.
1431
+ $blocks = explode("\t", $line);
1432
+ # Add each blocks to the line.
1433
+ $line = $blocks[0];
1434
+ unset($blocks[0]); # Do not add first block twice.
1435
+ foreach ($blocks as $block) {
1436
+ # Calculate amount of space, insert spaces, insert block.
1437
+ $amount = $this->tab_width -
1438
+ $strlen($line, 'UTF-8') % $this->tab_width;
1439
+ $line .= str_repeat(" ", $amount) . $block;
1440
+ }
1441
+ return $line;
1442
+ }
1443
+ function _initDetab() {
1444
+ #
1445
+ # Check for the availability of the function in the `utf8_strlen` property
1446
+ # (initially `mb_strlen`). If the function is not available, create a
1447
+ # function that will loosely count the number of UTF-8 characters with a
1448
+ # regular expression.
1449
+ #
1450
+ if (function_exists($this->utf8_strlen)) return;
1451
+ $this->utf8_strlen = create_function('$text', 'return preg_match_all(
1452
+ "/[\\\\x00-\\\\xBF]|[\\\\xC0-\\\\xFF][\\\\x80-\\\\xBF]*/",
1453
+ $text, $m);');
1454
+ }
1455
+
1456
+
1457
+ function unhash($text) {
1458
+ #
1459
+ # Swap back in all the tags hashed by _HashHTMLBlocks.
1460
+ #
1461
+ return preg_replace_callback('/(.)\x1A[0-9]+\1/',
1462
+ array(&$this, '_unhash_callback'), $text);
1463
+ }
1464
+ function _unhash_callback($matches) {
1465
+ return $this->html_hashes[$matches[0]];
1466
+ }
1467
+
1468
+ }
1469
+ ?>
includes/menu-pages/api-ops.inc.php ADDED
@@ -0,0 +1,268 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ API Notifications page.
18
+ */
19
+ echo '<div class="wrap ws-menu-page">' . "\n";
20
+ /**/
21
+ echo '<div id="icon-plugins" class="icon32"><br /></div>' . "\n";
22
+ echo '<h2><div>Developed by <a href="' . ws_plugin__s2member_parse_readme_value ("Plugin URI") . '"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-light.png" alt="." /></a></div>s2Member API / Notifications</h2>' . "\n";
23
+ /**/
24
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
25
+ /**/
26
+ echo '<table class="ws-menu-page-table">' . "\n";
27
+ echo '<tbody class="ws-menu-page-table-tbody">' . "\n";
28
+ echo '<tr class="ws-menu-page-table-tr">' . "\n";
29
+ echo '<td class="ws-menu-page-table-l">' . "\n";
30
+ /**/
31
+ echo '<form method="post" name="ws_plugin__s2member_options_form" id="ws-plugin--s2member-options-form">' . "\n";
32
+ echo '<input type="hidden" name="ws_plugin__s2member_options_save" id="ws-plugin--s2member-options-save" value="' . esc_attr (wp_create_nonce ("ws-plugin--s2member-options-save")) . '" />' . "\n";
33
+ echo '<input type="hidden" name="ws_plugin__s2member_configured" id="ws-plugin--s2member-configured" value="1" />' . "\n";
34
+ /**/
35
+ echo '<div class="ws-menu-page-group" title="Signup Notifications">' . "\n";
36
+ /**/
37
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-signup-notifications-section">' . "\n";
38
+ echo '<h3>Signup Notification URLs ( optional )</h3>' . "\n";
39
+ 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 user 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 user. Signup notifications are sent just after a user signs up successfully through PayPal®, regardless of whether any money has actually been received. In other words, this notification is triggered anytime a user 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 remains active at all times. These Signup Notifications are an added layer of functionality, and they are completely optional; used primarily in affiliate program integration &amp; other back-office routines.</p>' . "\n";
40
+ /**/
41
+ echo '<table class="form-table">' . "\n";
42
+ echo '<tbody>' . "\n";
43
+ echo '<tr>' . "\n";
44
+ /**/
45
+ echo '<th>' . "\n";
46
+ echo '<label for="ws-plugin--s2member-signup-notification-urls">' . "\n";
47
+ echo 'Signup Notification URLs:' . "\n";
48
+ echo '</label>' . "\n";
49
+ echo '</th>' . "\n";
50
+ /**/
51
+ echo '</tr>' . "\n";
52
+ echo '<tr>' . "\n";
53
+ /**/
54
+ echo '<td>' . "\n";
55
+ echo 'You can input multiple notification URLs by inserting one per line.<br />' . "\n";
56
+ 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";
57
+ echo 'Signup notifications take place silently behind-the-scenes, using a cURL connection. Each URL will be notified every time a new user signs up successfully through PayPal.<br /><br />' . "\n";
58
+ echo '<strong>You can also use these special replacement codes if you need them:</strong>' . "\n";
59
+ echo '<ul>' . "\n";
60
+ echo '<li><code>%%subscr_id%% = The PayPal® Subscription ID, which remains constant throughout any &amp; all future payments.</code> [ <a href="#" onclick="alert(\'There is one exception. If you are selling Lifetime ( non-recurring ) access, using a Buy It Now button; the %%subscr_id%% is actually set to the Transaction ID for the purchase.\\n\\nPayPal® does not provide a specific Subscription ID for Buy It Now purchases. Since Lifetime 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";
61
+ echo '<li><code>%%initial%% = The initial fee charged during signup, in USD. If you offered a free trial, this will be 0.</code> [ <a href="#" onclick="alert(\'If no initial period was offered or required, this initial amount will be equal to the %%regular%% rate. In other words, this will always represent the amount of money the customer spent whenever they signed up, no matter what.\\n\\nIf a user signs up under the terms of a free trial period, this will be 0. So be careful using this value with 3rd party affiliate integrations because a $0 sale amount could cause havoc. If you have a lot of trouble, try using the %%regular%% amount, or use the `Payment` notifications instead of the `Signup` notifications.\'); return false;">?</a> ]</li>' . "\n";
62
+ echo '<li><code>%%regular%% = The regular amount of the subscription in USD. This dollar value is always > 0, no matter what.</code> [ <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";
63
+ echo '<li><code>%%recurring%% = This is the amount in USD that will be charged on a recurring basis, or 0 if non-recurring.</code> [ <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.\\n\\nThe only time this is NOT equal to the %%regular%% rate, is when recurring payments are not required; and only a one-time regular rate applies. If you have trouble, try using the %%regular%% amount, or use the `Payment` notifications instead of the `Signup` notifications.\'); return false;">?</a> ]</li>' . "\n";
64
+ echo '<li><code>%%first_name%% = The first name of the customer who purchased the membership subscription through PayPal®.</code></li>' . "\n";
65
+ echo '<li><code>%%last_name%% = The last name of the customer who purchased the membership subscription through PayPal®.</code></li>' . "\n";
66
+ echo '<li><code>%%full_name%% = The full name ( first & last ) of the customer who purchased the membership subscription.</code></li>' . "\n";
67
+ echo '<li><code>%%payer_email%% = The email address of the customer who purchased the membership subscription through PayPal®.</code></li>' . "\n";
68
+ echo '<li><code>%%item_number%% = The item number ( in other words, the membership level: 1, 2, 3 or 4 ) that the subscription is for.</code></li>' . "\n";
69
+ echo '<li><code>%%item_name%% = The item name ( in other words, the associated membership level label that briefly describes the item number ).</code></li>' . "\n";
70
+ echo '<li><code>%%initial_term%% = This is the term length of the initial period. This will be a numeric value, followed by a space, then a single letter.</code> [ <a href="#" onclick="alert(\'Here are some examples:\\n\\n%%initial_term%% = 1 D ( this means 1 Day )\\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";
71
+ echo '<li><code>%%regular_term%% = This is the term length of the regular period. This will be a numeric value, followed by a space, then a single letter.</code> [ <a href="#" onclick="alert(\'Here are some examples:\\n\\n%%regular_term%% = 1 D ( this means 1 Day )\\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 priviledges 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";
72
+ echo '</ul>' . "\n";
73
+ echo '<strong>Custom replacement codes can also be inserted using these instructions:</strong>' . "\n";
74
+ echo '<ul>' . "\n";
75
+ echo '<li><code>%%cv0%% = The domain of your site, which is passed through to PayPal® using the `custom` field in your PayPal® button code.</code></li>' . "\n";
76
+ echo '<li><code>%%cv1%% = If you need to track additional custom variables, you can pipe delimit them into the `custom` field of your button code like this: &lt;input type="hidden" name="custom" value="' . $_SERVER["HTTP_HOST"] . '|cv1|cv2|cv3" /&gt;. You can have an unlimited number of custom variables that track IP addresses, affiliate IDs, etc. In some cases you may need to use PHP code to insert a value into the custom field dynamically. Obviously this is for advanced webmasters, but the functionality has been made available for those who need it.</li>' . "\n";
77
+ echo '</ul>' . "\n";
78
+ echo '<strong>This example uses cv1 to track a user\'s IP address:</strong><br />' . "\n";
79
+ echo '<em>( The IP address can be referenced in your notification URL using %%cv1%% )</em><br />' . "\n";
80
+ echo '<code>&lt;input type="hidden" name="custom" value="' . $_SERVER["HTTP_HOST"] . '|&lt;?php echo $_SERVER["REMOTE_ADDR"]; ?&gt;" /&gt;</code>' . "\n";
81
+ echo '</td>' . "\n";
82
+ /**/
83
+ echo '</tr>' . "\n";
84
+ echo '</tbody>' . "\n";
85
+ echo '</table>' . "\n";
86
+ echo '</div>' . "\n";
87
+ /**/
88
+ echo '</div>' . "\n";
89
+ /**/
90
+ echo '<div class="ws-menu-page-group" title="Payment Notifications">' . "\n";
91
+ /**/
92
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-payment-notifications-section">' . "\n";
93
+ echo '<h3>Payment Notification URLs ( optional )</h3>' . "\n";
94
+ 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 remains active at all times. These Payment Notifications are an added layer of functionality, and they are completely optional; used primarily in affiliate program integration &amp; other back-office routines.</p>' . "\n";
95
+ /**/
96
+ echo '<table class="form-table">' . "\n";
97
+ echo '<tbody>' . "\n";
98
+ echo '<tr>' . "\n";
99
+ /**/
100
+ echo '<th>' . "\n";
101
+ echo '<label for="ws-plugin--s2member-payment-notification-urls">' . "\n";
102
+ echo 'Payment Notification URLs:' . "\n";
103
+ echo '</label>' . "\n";
104
+ echo '</th>' . "\n";
105
+ /**/
106
+ echo '</tr>' . "\n";
107
+ echo '<tr>' . "\n";
108
+ /**/
109
+ echo '<td>' . "\n";
110
+ echo 'You can input multiple notification URLs by inserting one per line.<br />' . "\n";
111
+ 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";
112
+ echo 'Payment notifications take place silently behind-the-scenes, using a cURL connection. Each URL will be notified every time an initial and/or recurring payment occurs.<br /><br />' . "\n";
113
+ echo '<strong>You can also use these special replacement codes if you need them:</strong>' . "\n";
114
+ echo '<ul>' . "\n";
115
+ echo '<li><code>%%subscr_id%% = The PayPal® Subscription ID, which remains constant throughout any &amp; all future payments.</code> [ <a href="#" onclick="alert(\'There is one exception. If you are selling Lifetime ( non-recurring ) access, using a Buy It Now button; the %%subscr_id%% is actually set to the Transaction ID for the payment.\\n\\nPayPal® does not provide a specific Subscription ID for Buy It Now purchases. Since Lifetime 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";
116
+ echo '<li><code>%%txn_id%% = The PayPal® unique Transaction ID, which is always unique for each payment received.</code></li>' . "\n";
117
+ echo '<li><code>%%amount%% = The amount of the payment in USD. Most affiliate programs calculate commissions from this.</code></li>' . "\n";
118
+ echo '<li><code>%%first_name%% = The first name of the customer who purchased the membership subscription through PayPal®.</code></li>' . "\n";
119
+ echo '<li><code>%%last_name%% = The last name of the customer who purchased the membership subscription through PayPal®.</code></li>' . "\n";
120
+ echo '<li><code>%%full_name%% = The full name ( first & last ) of the customer who purchased the membership subscription.</code></li>' . "\n";
121
+ echo '<li><code>%%payer_email%% = The email address of the customer who purchased the membership subscription through PayPal®.</code></li>' . "\n";
122
+ echo '<li><code>%%item_number%% = The item number ( in other words, the membership level: 1, 2, 3 or 4 ) that the payment is for.</code></li>' . "\n";
123
+ echo '<li><code>%%item_name%% = The item name ( in other words, the associated membership level label that briefly describes the item number ).</code></li>' . "\n";
124
+ echo '</ul>' . "\n";
125
+ echo '<strong>Custom replacement codes can also be inserted using these instructions:</strong>' . "\n";
126
+ echo '<ul>' . "\n";
127
+ echo '<li><code>%%cv0%% = The domain of your site, which is passed through to PayPal® using the `custom` field in your PayPal® button code.</code></li>' . "\n";
128
+ echo '<li><code>%%cv1%% = If you need to track additional custom variables, you can pipe delimit them into the `custom` field of your button code like this: &lt;input type="hidden" name="custom" value="' . $_SERVER["HTTP_HOST"] . '|cv1|cv2|cv3" /&gt;. You can have an unlimited number of custom variables that track IP addresses, affiliate IDs, etc. In some cases you may need to use PHP code to insert a value into the custom field dynamically. Obviously this is for advanced webmasters, but the functionality has been made available for those who need it.</li>' . "\n";
129
+ echo '</ul>' . "\n";
130
+ echo '<strong>This example uses cv1 to track a user\'s IP address:</strong><br />' . "\n";
131
+ echo '<em>( The IP address can be referenced in your notification URL using %%cv1%% )</em><br />' . "\n";
132
+ echo '<code>&lt;input type="hidden" name="custom" value="' . $_SERVER["HTTP_HOST"] . '|&lt;?php echo $_SERVER["REMOTE_ADDR"]; ?&gt;" /&gt;</code>' . "\n";
133
+ echo '</td>' . "\n";
134
+ /**/
135
+ echo '</tr>' . "\n";
136
+ echo '</tbody>' . "\n";
137
+ echo '</table>' . "\n";
138
+ echo '</div>' . "\n";
139
+ /**/
140
+ echo '</div>' . "\n";
141
+ /**/
142
+ echo '<div class="ws-menu-page-group" title="EOT/Deletion Notifications">' . "\n";
143
+ /**/
144
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-eot-deletion-notifications-section">' . "\n";
145
+ echo '<h3>EOT/Deletion Notification URLs ( optional )</h3>' . "\n";
146
+ echo '<p>If you use affiliate software, or have back-office routines that need to be notified whenever subscriptions have ended, or when an account is deleted from the system otherwise, 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 anytime you cancel or refund a subscription via PayPal®, or if a user cancels their own subscription through PayPal®, fails to make payments, etc. In other words, anytime a subscription reaches the end of its term because you issue a refund, a chargeback occurs, a cancellation occurs or failed payments force PayPal® to end their subscription, this is triggered.</p>' . "\n";
147
+ echo '<p>EOTs are not necessarily triggered immediately after a cancellation takes place though. For example, 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 your site for another 15 days, and then on Feb 1st, the time they paid for has completely elapsed and that is when their account is automatically deleted from the system and an EOT notification is triggered. That being said, there are cases when an EOT is triggered immediately. For instance, if too many of their subscription payments fail at PayPal® ( more than 2 in a row ), an EOT will be issued immediately, also resulting in the automatic deletion of their account. If you log into your PayPal® account and issue a refund to an unhappy customer, their account will be automatically deleted, and an EOT is triggered immediately.</p>' . "\n";
148
+ echo '<p>Manual Deletions are the other case in which these notifications will be triggered. If you delete an account manually from within your WordPress® Dashboard, your affiliate software will be notified automatically through this notification. So the two events are EOT and/or 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 remains active at all times. These EOT/Deletion Notifications are an added layer of functionality, and they are completely optional; used primarily in affiliate program integration &amp; other back-office routines.</p>' . "\n";
149
+ /**/
150
+ echo '<table class="form-table">' . "\n";
151
+ echo '<tbody>' . "\n";
152
+ echo '<tr>' . "\n";
153
+ /**/
154
+ echo '<th>' . "\n";
155
+ echo '<label for="ws-plugin--s2member-eot-del-notification-urls">' . "\n";
156
+ echo 'EOT/Deletion Notification URLs:' . "\n";
157
+ echo '</label>' . "\n";
158
+ echo '</th>' . "\n";
159
+ /**/
160
+ echo '</tr>' . "\n";
161
+ echo '<tr>' . "\n";
162
+ /**/
163
+ echo '<td>' . "\n";
164
+ echo 'You can input multiple notification URLs by inserting one per line.<br />' . "\n";
165
+ 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";
166
+ echo 'EOT/Deletion notifications take place silently behind-the-scenes, using a cURL connection. Each URL will be notified every time a subscription reaches the end of its term or is deleted otherwise.<br /><br />' . "\n";
167
+ echo '<strong>You can also use these special replacement codes if you need them:</strong>' . "\n";
168
+ echo '<ul>' . "\n";
169
+ echo '<li><code>%%subscr_id%% = The PayPal® Subscription ID, which remained constant throughout the lifetime of the membership.</code> [ <a href="#" onclick="alert(\'There is one exception. If you are selling Lifetime ( non-recurring ) access, using a Buy It Now button; 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 It Now purchases. Since Lifetime 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";
170
+ echo '<li><code>%%user_first_name%% = The first name listed on their user account. This might be different than what is on file at PayPal®.</code></li>' . "\n";
171
+ echo '<li><code>%%user_last_name%% = The last name listed on their user account. This might be different than what is on file at PayPal®.</code></li>' . "\n";
172
+ echo '<li><code>%%user_full_name%% = The full name listed on their user account. This might be different than what is on file at PayPal®.</code></li>' . "\n";
173
+ echo '<li><code>%%user_email%% = The email address associated with their user account. This might be different than what is on file at PayPal®.</code></li>' . "\n";
174
+ echo '</ul>' . "\n";
175
+ echo '<strong>Custom replacement codes can also be inserted using these instructions:</strong>' . "\n";
176
+ echo '<ul>' . "\n";
177
+ echo '<li><code>%%cv0%% = The domain of your site, which is passed through to PayPal® using the `custom` field in your PayPal® button code.</code></li>' . "\n";
178
+ echo '<li><code>%%cv1%% = If you need to track additional custom variables, you can pipe delimit them into the `custom` field of your button code like this: &lt;input type="hidden" name="custom" value="' . $_SERVER["HTTP_HOST"] . '|cv1|cv2|cv3" /&gt;. You can have an unlimited number of custom variables that track IP addresses, affiliate IDs, etc. In some cases you may need to use PHP code to insert a value into the custom field dynamically. Obviously this is for advanced webmasters, but the functionality has been made available for those who need it.</li>' . "\n";
179
+ echo '</ul>' . "\n";
180
+ echo '<strong>This example uses cv1 to track a user\'s IP address:</strong><br />' . "\n";
181
+ echo '<em>( The IP address can be referenced in your notification URL using %%cv1%% )</em><br />' . "\n";
182
+ echo '<code>&lt;input type="hidden" name="custom" value="' . $_SERVER["HTTP_HOST"] . '|&lt;?php echo $_SERVER["REMOTE_ADDR"]; ?&gt;" /&gt;</code>' . "\n";
183
+ echo '</td>' . "\n";
184
+ /**/
185
+ echo '</tr>' . "\n";
186
+ echo '</tbody>' . "\n";
187
+ echo '</table>' . "\n";
188
+ echo '</div>' . "\n";
189
+ /**/
190
+ echo '</div>' . "\n";
191
+ /**/
192
+ echo '<div class="ws-menu-page-group" title="Refund/Reversal Notifications">' . "\n";
193
+ /**/
194
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-refund-reversal-notifications-section">' . "\n";
195
+ echo '<h3>Refund/Reversal Notification URLs ( optional )</h3>' . "\n";
196
+ echo '<p>If you use affiliate software, or have back-office routines that need to be notified whenever subscriptions have been refunded or reversed ( e.g. 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 decribed 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";
197
+ 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 remains active at all times. These Refund/Reversal Notifications are an added layer of functionality, and they are completely optional; used primarily in affiliate program integration &amp; other back-office routines.</p>' . "\n";
198
+ /**/
199
+ echo '<table class="form-table">' . "\n";
200
+ echo '<tbody>' . "\n";
201
+ echo '<tr>' . "\n";
202
+ /**/
203
+ echo '<th>' . "\n";
204
+ echo '<label for="ws-plugin--s2member-ref-rev-notification-urls">' . "\n";
205
+ echo 'Refund/Reversal Notification URLs:' . "\n";
206
+ echo '</label>' . "\n";
207
+ echo '</th>' . "\n";
208
+ /**/
209
+ echo '</tr>' . "\n";
210
+ echo '<tr>' . "\n";
211
+ /**/
212
+ echo '<td>' . "\n";
213
+ echo 'You can input multiple notification URLs by inserting one per line.<br />' . "\n";
214
+ 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";
215
+ echo 'Refund/Reversal notifications take place silently behind-the-scenes, using a cURL connection. Each URL will be notified every time a payment is refunded through PayPal® or a chargeback occurs.<br /><br />' . "\n";
216
+ echo '<strong>You can also use these special replacement codes if you need them:</strong>' . "\n";
217
+ echo '<ul>' . "\n";
218
+ echo '<li><code>%%subscr_id%% = The PayPal® Subscription ID, which remained constant throughout the lifetime of the membership.</code> [ <a href="#" onclick="alert(\'There is one exception. If you are selling Lifetime ( non-recurring ) access, using a Buy It Now button; 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 It Now purchases. Since Lifetime 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";
219
+ echo '<li><code>%%parent_txn_id%% = The PayPal® Transaction ID, associated with the original payment that is being refunded/reversed.</code></li>' . "\n";
220
+ echo '<li><code>%%-amount%% = The negative amount of the payment in USD, that was refunded or reversed back to the customer.</code></li>' . "\n";
221
+ echo '<li><code>%%first_name%% = The first name of the customer who purchased the membership subscription through PayPal®.</code></li>' . "\n";
222
+ echo '<li><code>%%last_name%% = The last name of the customer who purchased the membership subscription through PayPal®.</code></li>' . "\n";
223
+ echo '<li><code>%%full_name%% = The full name ( first & last ) of the customer who purchased the membership subscription.</code></li>' . "\n";
224
+ echo '<li><code>%%payer_email%% = The email address of the customer who purchased the membership subscription through PayPal®.</code></li>' . "\n";
225
+ echo '<li><code>%%item_number%% = The item number ( in other words, the membership level: 1, 2, 3 or 4 ) that the payment was for.</code></li>' . "\n";
226
+ echo '<li><code>%%item_name%% = The item name ( in other words, the associated membership level label that briefly describes the item number ).</code></li>' . "\n";
227
+ echo '</ul>' . "\n";
228
+ echo '<strong>Custom replacement codes can also be inserted using these instructions:</strong>' . "\n";
229
+ echo '<ul>' . "\n";
230
+ echo '<li><code>%%cv0%% = The domain of your site, which is passed through to PayPal® using the `custom` field in your PayPal® button code.</code></li>' . "\n";
231
+ echo '<li><code>%%cv1%% = If you need to track additional custom variables, you can pipe delimit them into the `custom` field of your button code like this: &lt;input type="hidden" name="custom" value="' . $_SERVER["HTTP_HOST"] . '|cv1|cv2|cv3" /&gt;. You can have an unlimited number of custom variables that track IP addresses, affiliate IDs, etc. In some cases you may need to use PHP code to insert a value into the custom field dynamically. Obviously this is for advanced webmasters, but the functionality has been made available for those who need it.</li>' . "\n";
232
+ echo '</ul>' . "\n";
233
+ echo '<strong>This example uses cv1 to track a user\'s IP address:</strong><br />' . "\n";
234
+ echo '<em>( The IP address can be referenced in your notification URL using %%cv1%% )</em><br />' . "\n";
235
+ echo '<code>&lt;input type="hidden" name="custom" value="' . $_SERVER["HTTP_HOST"] . '|&lt;?php echo $_SERVER["REMOTE_ADDR"]; ?&gt;" /&gt;</code>' . "\n";
236
+ echo '</td>' . "\n";
237
+ /**/
238
+ echo '</tr>' . "\n";
239
+ echo '</tbody>' . "\n";
240
+ echo '</table>' . "\n";
241
+ echo '</div>' . "\n";
242
+ /**/
243
+ echo '</div>' . "\n";
244
+ /**/
245
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
246
+ /**/
247
+ echo '<p class="submit"><input type="submit" class="button-primary" value="Save Changes" /></p>' . "\n";
248
+ /**/
249
+ echo '</form>' . "\n";
250
+ /**/
251
+ echo '</td>' . "\n";
252
+ /**/
253
+ echo '<td class="ws-menu-page-table-r">' . "\n";
254
+ /**/
255
+ echo ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["menu-r"]["tools"]) ? '<div class="ws-menu-page-tools"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-tools.png" alt="." /></div>' . "\n" : '';
256
+ /**/
257
+ echo ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["menu-r"]["tips"]) ? '<div class="ws-menu-page-tips"><a href="' . ws_plugin__s2member_parse_readme_value ("Customization URI") . '"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-tips.png" alt="." /></a></div>' . "\n" : '';
258
+ /**/
259
+ echo ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["menu-r"]["donations"]) ? '<div class="ws-menu-page-donations"><a href="' . ws_plugin__s2member_parse_readme_value ("Donate link") . '"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-donations.jpg" alt="." /></a></div>' . "\n" : '';
260
+ /**/
261
+ echo '</td>' . "\n";
262
+ /**/
263
+ echo '</tr>' . "\n";
264
+ echo '</tbody>' . "\n";
265
+ echo '</table>' . "\n";
266
+ /**/
267
+ echo '</div>' . "\n";
268
+ ?>
includes/menu-pages/button.html ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <form action="https://%%endpoint%%/cgi-bin/webscr" method="post">
2
+ <input type="hidden" name="business" value="%%paypal_business%%" />
3
+ <input type="hidden" name="cmd" value="_xclick-subscriptions" />
4
+ <!-- Instant Payment Notification / Return Details -->
5
+ <input type="hidden" name="notify_url" value="%%notify_url%%" />
6
+ <input type="hidden" name="cancel_return" value="%%cancel_return%%" />
7
+ <input type="hidden" name="return" value="%%return%%" />
8
+ <input type="hidden" name="rm" value="2" />
9
+ <!-- Identify / Customize 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%%" />
16
+ <input type="hidden" name="item_number" value="%%level%%" />
17
+ <!-- Set The Terms Of The Subscription. -->
18
+ <!--<input type="hidden" name="on0" value="" />-->
19
+ <!--<input type="hidden" name="os0" value="" />-->
20
+ <!--<input type="hidden" name="amount" value="0.01" />-->
21
+ <input type="hidden" name="modify" value="0" />
22
+ <input type="hidden" name="src" value="1" />
23
+ <input type="hidden" name="sra" value="1" />
24
+ <input type="hidden" name="a1" value="0.00" />
25
+ <input type="hidden" name="p1" value="0" />
26
+ <input type="hidden" name="t1" value="D" />
27
+ <input type="hidden" name="a3" value="0.01" />
28
+ <input type="hidden" name="p3" value="1" />
29
+ <input type="hidden" name="t3" value="M" />
30
+ <!-- Display The Subscription Button. -->
31
+ <input type="image" alt="PayPal®" style="border:0;" src="https://www.paypal.com/en_GB/i/btn/btn_xpressCheckout.gif" />
32
+ </form>
includes/menu-pages/buttons.inc.php ADDED
@@ -0,0 +1,281 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ PayPal® Button Generating page.
18
+ */
19
+ echo '<div class="wrap ws-menu-page">' . "\n";
20
+ /**/
21
+ echo '<div id="icon-plugins" class="icon32"><br /></div>' . "\n";
22
+ echo '<h2><div>Developed by <a href="' . ws_plugin__s2member_parse_readme_value ("Plugin URI") . '"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-light.png" alt="." /></a></div>s2Member PayPal® Subscription Buttons</h2>' . "\n";
23
+ /**/
24
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
25
+ /**/
26
+ echo '<table class="ws-menu-page-table">' . "\n";
27
+ echo '<tbody class="ws-menu-page-table-tbody">' . "\n";
28
+ echo '<tr class="ws-menu-page-table-tr">' . "\n";
29
+ echo '<td class="ws-menu-page-table-l">' . "\n";
30
+ /**/
31
+ if (get_option ("ws_plugin__s2member_configured") && $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"])
32
+ {
33
+ echo '<form method="post" name="ws_plugin__s2member_buttons_form" id="ws-plugin--s2member-buttons-form">' . "\n";
34
+ /**/
35
+ echo '<div class="ws-menu-page-group" title="PayPal® Button For Level #1 Subscriptions">' . "\n";
36
+ /**/
37
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-button-code-1-section">' . "\n";
38
+ echo '<h3>Button Code Generator For Level #1 Subscriptions</h3>' . "\n";
39
+ echo '<p>Very simple. All you do is customize the form fields provided, for each Membership Level that you plan to offer. Then press (Generate Button Code). These special subscription buttons are customized to work with s2Member seamlessly. User accounts will be activated instantly, in an automated fashion. When you, or a User, cancels their membership, or fails to make payments on time, s2Member will automatically terminate their membership privileges using automated routines. s2Member makes extensive use of the PayPal® IPN service, which receives updates directly from PayPal® behind the scenes.</p>' . "\n";
40
+ echo '<p><em>* Buttons are NOT saved here. This is only a Button Generator. Once you\'ve generated your Button, copy/paste it into your Membership Options Page. If you lose your Button Code, you\'ll need to come back &amp; regenerate a new one. If you\'re currently in Sandbox testing mode, please remember to come back and regenerate new Buttons once you go live.</em></p>' . "\n";
41
+ /**/
42
+ echo '<table class="form-table">' . "\n";
43
+ echo '<tbody>' . "\n";
44
+ echo '<tr>' . "\n";
45
+ /**/
46
+ echo '<th class="ws-menu-page-th-side">' . "\n";
47
+ echo '<label for="ws-plugin--s2member-level1-button">' . "\n";
48
+ echo 'Button Code<br />For Level #1:<br /><br />' . "\n";
49
+ echo '<div id="ws-plugin--s2member-level1-button-prev"></div>' . "\n";
50
+ echo '</label>' . "\n";
51
+ echo '</th>' . "\n";
52
+ /**/
53
+ echo '<td>' . "\n";
54
+ 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="2" /> <select id="ws-plugin--s2member-level1-trial-term"><option value="D" selected="selected">Days</option><option value="W">Weeks</option><option value="M">Months</option><option value="Y">Years</option></select> free.</p>' . "\n";
55
+ 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"><optgroup label="Recurring Subscriptions"><option value="1-D-1">Daily ( recurring charge, for ongoing access )</option><option value="1-W-1">Weekly ( recurring charge, for ongoing access )</option><option value="1-M-1" selected="selected">Monthly ( recurring charge, for ongoing access )</option><option value="3-M-1">Quarterly ( recurring charge, for ongoing access )</option><option value="1-Y-1">Yearly ( recurring charge, for ongoing access )</option></optgroup><optgroup label="Days / Non-Recurring"><option value="1-D-0">One Time ( for 1 day access, non-recurring )</option><option value="2-D-0">One Time ( for 2 day access, non-recurring )</option><option value="3-D-0">One Time ( for 3 day access, non-recurring )</option><option value="4-D-0">One Time ( for 4 day access, non-recurring )</option><option value="5-D-0">One Time ( for 5 day access, non-recurring )</option><option value="6-D-0">One Time ( for 6 day access, non-recurring )</option></optgroup><optgroup label="Weeks / Non-Recurring"><option value="1-W-0">One Time ( for 1 week access, non-recurring )</option><option value="2-W-0">One Time ( for 2 week access, non-recurring )</option><option value="3-W-0">One Time ( for 3 week access, non-recurring )</option></optgroup><optgroup label="Months / Non-Recurring"><option value="1-M-0">One Time ( for 1 month access, non-recurring )</option><option value="2-M-0">One Time ( for 2 month access, non-recurring )</option><option value="3-M-0">One Time ( for 3 month access, non-recurring )</option><option value="4-M-0">One Time ( for 4 month access, non-recurring )</option><option value="5-M-0">One Time ( for 5 month access, non-recurring )</option><option value="6-M-0">One Time ( for 6 month access, non-recurring )</option></optgroup><optgroup label="Years / Non-Recurring"><option value="1-Y-0">One Time ( for 1 year access, non-recurring )</option><option value="2-Y-0">One Time ( for 2 year access, non-recurring )</option><option value="3-Y-0">One Time ( for 3 year access, non-recurring )</option><option value="4-Y-0">One Time ( for 4 year access, non-recurring )</option><option value="5-Y-0">One Time ( for 5 year access, non-recurring )</option></optgroup><optgroup label="Lifetime / Buy Now / Non-Recurring / No Trial"><option value="1-L-0">Buy Now ( for lifetime access, no-trial, non-recurring )</option></optgroup></select></p>' . "\n";
56
+ 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. Once you\\\'ve created a Custom Page Style at PayPal®, you can enter that Page Style here.\'); return false;">?</a>]: <input type="text" id="ws-plugin--s2member-level1-page-style" value="paypal" size="10" /> <select id="ws-plugin--s2member-level1-currency"><optgroup label="Currency"><option value="USD" title="U.S. Dollar">USD</option><option value="AUD" title="Australian Dollar">AUD</option><option value="BRL" title="Brazilian Real">BRL</option><option value="CAD" title="Canadian Dollar">CAD</option><option value="CZK" title="Czech Koruna">CZK</option><option value="DKK" title="Danish Krone">DKK</option><option value="EUR" title="Euro">EUR</option><option value="HKD" title="Hong Kong Dollar">HKD</option><option value="HUF" title="Hungarian Forint">HUF</option><option value="ILS" title="Israeli New Sheqel">ILS</option><option value="JPY" title="Japanese Yen">JPY</option><option value="MYR" title="Malaysian Ringgit">MYR</option><option value="MXN" title="Mexican Peso">MXN</option><option value="NOK" title="Norwegian Krone">NOK</option><option value="NZD" title="New Zealand Dollar">NZD</option><option value="PHP" title="Philippine Peso">PHP</option><option value="PLN" title="Polish Zloty">PLN</option><option value="GBP" title="Pound Sterling">GBP</option><option value="SGD" title="Singapore Dollar">SGD</option><option value="SEK" title="Swedish Krona">SEK</option><option value="CHF" title="Swiss Franc">CHF</option><option value="TWD" title="Taiwan New Dollar">TWD</option><option value="THB" title="Thai Baht">THB</option><option value="USD" title="U.S. Dollar">USD</option></optgroup></select> <input type="button" value="Generate Button Code" onclick="ws_plugin__s2member_paypalButtonGenerate(1);" class="button-primary" /></p>' . "\n";
57
+ echo '</td>' . "\n";
58
+ /**/
59
+ echo '</tr>' . "\n";
60
+ echo '<tr>' . "\n";
61
+ /**/
62
+ echo '<td colspan="2">' . "\n";
63
+ echo '<strong>WordPress® Shortcode:</strong> ( recommended for both the WordPress® Visual &amp; HTML Editors )<br />' . "\n";
64
+ $ws_plugin__s2member_temp_s = trim (file_get_contents (dirname (__FILE__) . "/shortcode.html"));
65
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%domain%%/", strtolower ($_SERVER["HTTP_HOST"]), $ws_plugin__s2member_temp_s);
66
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%level%%/", "1", $ws_plugin__s2member_temp_s);
67
+ echo '<input id="ws-plugin--s2member-level1-shortcode" type="text" value="' . format_to_edit ($ws_plugin__s2member_temp_s) . '" onclick="this.select ();" /><br /><br />' . "\n";
68
+ echo '<strong>Resulting PayPal® Button Code:</strong> ( ultimately, your Shortcode will produce this snippet )<br />' . "\n";
69
+ echo '<textarea id="ws-plugin--s2member-level1-button" rows="8" wrap="off" onclick="this.select ();">';
70
+ $ws_plugin__s2member_temp_s = trim (file_get_contents (dirname (__FILE__) . "/button.html"));
71
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%endpoint%%/", (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com"), $ws_plugin__s2member_temp_s);
72
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%paypal_business%%/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"], $ws_plugin__s2member_temp_s);
73
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%level_label%%/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_label"], $ws_plugin__s2member_temp_s);
74
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%cancel_return%%/", get_bloginfo ("url"), $ws_plugin__s2member_temp_s);
75
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%notify_url%%/", get_bloginfo ("url") . "/?s2member_paypal_notify=1", $ws_plugin__s2member_temp_s);
76
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%return%%/", get_bloginfo ("url") . "/?s2member_paypal_return=1", $ws_plugin__s2member_temp_s);
77
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%domain%%/", strtolower ($_SERVER["HTTP_HOST"]), $ws_plugin__s2member_temp_s);
78
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%level%%/", "1", $ws_plugin__s2member_temp_s);
79
+ echo format_to_edit ($ws_plugin__s2member_temp_s);
80
+ echo '</textarea><br />' . "\n";
81
+ echo '&uarr; Use this more advanced Code if you\'re building a theme or plugin that integrates with s2Member.' . "\n";
82
+ echo '</td>' . "\n";
83
+ /**/
84
+ echo '</tr>' . "\n";
85
+ echo '</tbody>' . "\n";
86
+ echo '</table>' . "\n";
87
+ echo '</div>' . "\n";
88
+ /**/
89
+ echo '</div>' . "\n";
90
+ /**/
91
+ echo '<div class="ws-menu-page-group" title="PayPal® Button For Level #2 Subscriptions">' . "\n";
92
+ /**/
93
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-button-code-2-section">' . "\n";
94
+ echo '<h3>Button Code Generator For Level #2 Subscriptions</h3>' . "\n";
95
+ echo '<p>Very simple. All you do is customize the form fields provided, for each Membership Level that you plan to offer. Then press (Generate Button Code). These special subscription buttons are customized to work with s2Member seamlessly. User accounts will be activated instantly, in an automated fashion. When you, or a User, cancels their membership, or fails to make payments on time, s2Member will automatically terminate their membership privileges using automated routines. s2Member makes extensive use of the PayPal® IPN service, which receives updates directly from PayPal® behind the scenes.</p>' . "\n";
96
+ echo '<p><em>* Buttons are NOT saved here. This is only a Button Generator. Once you\'ve generated your Button, copy/paste it into your Membership Options Page. If you lose your Button Code, you\'ll need to come back &amp; regenerate a new one. If you\'re currently in Sandbox testing mode, please remember to come back and regenerate new Buttons once you go live.</em></p>' . "\n";
97
+ /**/
98
+ echo '<table class="form-table">' . "\n";
99
+ echo '<tbody>' . "\n";
100
+ echo '<tr>' . "\n";
101
+ /**/
102
+ echo '<th class="ws-menu-page-th-side">' . "\n";
103
+ echo '<label for="ws-plugin--s2member-level2-button">' . "\n";
104
+ echo 'Button Code<br />For Level #2:<br /><br />' . "\n";
105
+ echo '<div id="ws-plugin--s2member-level2-button-prev"></div>' . "\n";
106
+ echo '</label>' . "\n";
107
+ echo '</th>' . "\n";
108
+ /**/
109
+ echo '<td>' . "\n";
110
+ 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="2" /> <select id="ws-plugin--s2member-level2-trial-term"><option value="D" selected="selected">Days</option><option value="W">Weeks</option><option value="M">Months</option><option value="Y">Years</option></select> free.</p>' . "\n";
111
+ 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"><optgroup label="Recurring Subscriptions"><option value="1-D-1">Daily ( recurring charge, for ongoing access )</option><option value="1-W-1">Weekly ( recurring charge, for ongoing access )</option><option value="1-M-1" selected="selected">Monthly ( recurring charge, for ongoing access )</option><option value="3-M-1">Quarterly ( recurring charge, for ongoing access )</option><option value="1-Y-1">Yearly ( recurring charge, for ongoing access )</option></optgroup><optgroup label="Days / Non-Recurring"><option value="1-D-0">One Time ( for 1 day access, non-recurring )</option><option value="2-D-0">One Time ( for 2 day access, non-recurring )</option><option value="3-D-0">One Time ( for 3 day access, non-recurring )</option><option value="4-D-0">One Time ( for 4 day access, non-recurring )</option><option value="5-D-0">One Time ( for 5 day access, non-recurring )</option><option value="6-D-0">One Time ( for 6 day access, non-recurring )</option></optgroup><optgroup label="Weeks / Non-Recurring"><option value="1-W-0">One Time ( for 1 week access, non-recurring )</option><option value="2-W-0">One Time ( for 2 week access, non-recurring )</option><option value="3-W-0">One Time ( for 3 week access, non-recurring )</option></optgroup><optgroup label="Months / Non-Recurring"><option value="1-M-0">One Time ( for 1 month access, non-recurring )</option><option value="2-M-0">One Time ( for 2 month access, non-recurring )</option><option value="3-M-0">One Time ( for 3 month access, non-recurring )</option><option value="4-M-0">One Time ( for 4 month access, non-recurring )</option><option value="5-M-0">One Time ( for 5 month access, non-recurring )</option><option value="6-M-0">One Time ( for 6 month access, non-recurring )</option></optgroup><optgroup label="Years / Non-Recurring"><option value="1-Y-0">One Time ( for 1 year access, non-recurring )</option><option value="2-Y-0">One Time ( for 2 year access, non-recurring )</option><option value="3-Y-0">One Time ( for 3 year access, non-recurring )</option><option value="4-Y-0">One Time ( for 4 year access, non-recurring )</option><option value="5-Y-0">One Time ( for 5 year access, non-recurring )</option></optgroup><optgroup label="Lifetime / Buy Now / Non-Recurring / No Trial"><option value="1-L-0">Buy Now ( for lifetime access, no-trial, non-recurring )</option></optgroup></select></p>' . "\n";
112
+ 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. Once you\\\'ve created a Custom Page Style at PayPal®, you can enter that Page Style here.\'); return false;">?</a>]: <input type="text" id="ws-plugin--s2member-level2-page-style" value="paypal" size="10" /> <select id="ws-plugin--s2member-level2-currency"><optgroup label="Currency"><option value="USD" title="U.S. Dollar">USD</option><option value="AUD" title="Australian Dollar">AUD</option><option value="BRL" title="Brazilian Real">BRL</option><option value="CAD" title="Canadian Dollar">CAD</option><option value="CZK" title="Czech Koruna">CZK</option><option value="DKK" title="Danish Krone">DKK</option><option value="EUR" title="Euro">EUR</option><option value="HKD" title="Hong Kong Dollar">HKD</option><option value="HUF" title="Hungarian Forint">HUF</option><option value="ILS" title="Israeli New Sheqel">ILS</option><option value="JPY" title="Japanese Yen">JPY</option><option value="MYR" title="Malaysian Ringgit">MYR</option><option value="MXN" title="Mexican Peso">MXN</option><option value="NOK" title="Norwegian Krone">NOK</option><option value="NZD" title="New Zealand Dollar">NZD</option><option value="PHP" title="Philippine Peso">PHP</option><option value="PLN" title="Polish Zloty">PLN</option><option value="GBP" title="Pound Sterling">GBP</option><option value="SGD" title="Singapore Dollar">SGD</option><option value="SEK" title="Swedish Krona">SEK</option><option value="CHF" title="Swiss Franc">CHF</option><option value="TWD" title="Taiwan New Dollar">TWD</option><option value="THB" title="Thai Baht">THB</option><option value="USD" title="U.S. Dollar">USD</option></optgroup></select> <input type="button" value="Generate Button Code" onclick="ws_plugin__s2member_paypalButtonGenerate(2);" class="button-primary" /></p>' . "\n";
113
+ echo '</td>' . "\n";
114
+ /**/
115
+ echo '</tr>' . "\n";
116
+ echo '<tr>' . "\n";
117
+ /**/
118
+ echo '<td colspan="2">' . "\n";
119
+ echo '<strong>WordPress® Shortcode:</strong> ( recommended for both the WordPress® Visual &amp; HTML Editors )<br />' . "\n";
120
+ $ws_plugin__s2member_temp_s = trim (file_get_contents (dirname (__FILE__) . "/shortcode.html"));
121
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%domain%%/", strtolower ($_SERVER["HTTP_HOST"]), $ws_plugin__s2member_temp_s);
122
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%level%%/", "2", $ws_plugin__s2member_temp_s);
123
+ echo '<input id="ws-plugin--s2member-level2-shortcode" type="text" value="' . format_to_edit ($ws_plugin__s2member_temp_s) . '" onclick="this.select ();" /><br /><br />' . "\n";
124
+ echo '<strong>Resulting PayPal® Button Code:</strong> ( ultimately, your Shortcode will produce this snippet )<br />' . "\n";
125
+ echo '<textarea id="ws-plugin--s2member-level2-button" rows="8" wrap="off" onclick="this.select ();">';
126
+ $ws_plugin__s2member_temp_s = trim (file_get_contents (dirname (__FILE__) . "/button.html"));
127
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%endpoint%%/", (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com"), $ws_plugin__s2member_temp_s);
128
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%paypal_business%%/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"], $ws_plugin__s2member_temp_s);
129
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%level_label%%/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_label"], $ws_plugin__s2member_temp_s);
130
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%cancel_return%%/", get_bloginfo ("url"), $ws_plugin__s2member_temp_s);
131
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%notify_url%%/", get_bloginfo ("url") . "/?s2member_paypal_notify=1", $ws_plugin__s2member_temp_s);
132
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%return%%/", get_bloginfo ("url") . "/?s2member_paypal_return=1", $ws_plugin__s2member_temp_s);
133
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%domain%%/", strtolower ($_SERVER["HTTP_HOST"]), $ws_plugin__s2member_temp_s);
134
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%level%%/", "2", $ws_plugin__s2member_temp_s);
135
+ echo format_to_edit ($ws_plugin__s2member_temp_s);
136
+ echo '</textarea><br />' . "\n";
137
+ echo '&uarr; Use this more advanced Code if you\'re building a theme or plugin that integrates with s2Member.' . "\n";
138
+ echo '</td>' . "\n";
139
+ /**/
140
+ echo '</tr>' . "\n";
141
+ echo '</tbody>' . "\n";
142
+ echo '</table>' . "\n";
143
+ echo '</div>' . "\n";
144
+ /**/
145
+ echo '</div>' . "\n";
146
+ /**/
147
+ echo '<div class="ws-menu-page-group" title="PayPal® Button For Level #3 Subscriptions">' . "\n";
148
+ /**/
149
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-button-code-3-section">' . "\n";
150
+ echo '<h3>Button Code Generator For Level #3 Subscriptions</h3>' . "\n";
151
+ echo '<p>Very simple. All you do is customize the form fields provided, for each Membership Level that you plan to offer. Then press (Generate Button Code). These special subscription buttons are customized to work with s2Member seamlessly. User accounts will be activated instantly, in an automated fashion. When you, or a User, cancels their membership, or fails to make payments on time, s2Member will automatically terminate their membership privileges using automated routines. s2Member makes extensive use of the PayPal® IPN service, which receives updates directly from PayPal® behind the scenes.</p>' . "\n";
152
+ echo '<p><em>* Buttons are NOT saved here. This is only a Button Generator. Once you\'ve generated your Button, copy/paste it into your Membership Options Page. If you lose your Button Code, you\'ll need to come back &amp; regenerate a new one. If you\'re currently in Sandbox testing mode, please remember to come back and regenerate new Buttons once you go live.</em></p>' . "\n";
153
+ /**/
154
+ echo '<table class="form-table">' . "\n";
155
+ echo '<tbody>' . "\n";
156
+ echo '<tr>' . "\n";
157
+ /**/
158
+ echo '<th class="ws-menu-page-th-side">' . "\n";
159
+ echo '<label for="ws-plugin--s2member-level3-button">' . "\n";
160
+ echo 'Button Code<br />For Level #3:<br /><br />' . "\n";
161
+ echo '<div id="ws-plugin--s2member-level3-button-prev"></div>' . "\n";
162
+ echo '</label>' . "\n";
163
+ echo '</th>' . "\n";
164
+ /**/
165
+ echo '<td>' . "\n";
166
+ 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="2" /> <select id="ws-plugin--s2member-level3-trial-term"><option value="D" selected="selected">Days</option><option value="W">Weeks</option><option value="M">Months</option><option value="Y">Years</option></select> free.</p>' . "\n";
167
+ 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"><optgroup label="Recurring Subscriptions"><option value="1-D-1">Daily ( recurring charge, for ongoing access )</option><option value="1-W-1">Weekly ( recurring charge, for ongoing access )</option><option value="1-M-1" selected="selected">Monthly ( recurring charge, for ongoing access )</option><option value="3-M-1">Quarterly ( recurring charge, for ongoing access )</option><option value="1-Y-1">Yearly ( recurring charge, for ongoing access )</option></optgroup><optgroup label="Days / Non-Recurring"><option value="1-D-0">One Time ( for 1 day access, non-recurring )</option><option value="2-D-0">One Time ( for 2 day access, non-recurring )</option><option value="3-D-0">One Time ( for 3 day access, non-recurring )</option><option value="4-D-0">One Time ( for 4 day access, non-recurring )</option><option value="5-D-0">One Time ( for 5 day access, non-recurring )</option><option value="6-D-0">One Time ( for 6 day access, non-recurring )</option></optgroup><optgroup label="Weeks / Non-Recurring"><option value="1-W-0">One Time ( for 1 week access, non-recurring )</option><option value="2-W-0">One Time ( for 2 week access, non-recurring )</option><option value="3-W-0">One Time ( for 3 week access, non-recurring )</option></optgroup><optgroup label="Months / Non-Recurring"><option value="1-M-0">One Time ( for 1 month access, non-recurring )</option><option value="2-M-0">One Time ( for 2 month access, non-recurring )</option><option value="3-M-0">One Time ( for 3 month access, non-recurring )</option><option value="4-M-0">One Time ( for 4 month access, non-recurring )</option><option value="5-M-0">One Time ( for 5 month access, non-recurring )</option><option value="6-M-0">One Time ( for 6 month access, non-recurring )</option></optgroup><optgroup label="Years / Non-Recurring"><option value="1-Y-0">One Time ( for 1 year access, non-recurring )</option><option value="2-Y-0">One Time ( for 2 year access, non-recurring )</option><option value="3-Y-0">One Time ( for 3 year access, non-recurring )</option><option value="4-Y-0">One Time ( for 4 year access, non-recurring )</option><option value="5-Y-0">One Time ( for 5 year access, non-recurring )</option></optgroup><optgroup label="Lifetime / Buy Now / Non-Recurring / No Trial"><option value="1-L-0">Buy Now ( for lifetime access, no-trial, non-recurring )</option></optgroup></select></p>' . "\n";
168
+ 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. Once you\\\'ve created a Custom Page Style at PayPal®, you can enter that Page Style here.\'); return false;">?</a>]: <input type="text" id="ws-plugin--s2member-level3-page-style" value="paypal" size="10" /> <select id="ws-plugin--s2member-level3-currency"><optgroup label="Currency"><option value="USD" title="U.S. Dollar">USD</option><option value="AUD" title="Australian Dollar">AUD</option><option value="BRL" title="Brazilian Real">BRL</option><option value="CAD" title="Canadian Dollar">CAD</option><option value="CZK" title="Czech Koruna">CZK</option><option value="DKK" title="Danish Krone">DKK</option><option value="EUR" title="Euro">EUR</option><option value="HKD" title="Hong Kong Dollar">HKD</option><option value="HUF" title="Hungarian Forint">HUF</option><option value="ILS" title="Israeli New Sheqel">ILS</option><option value="JPY" title="Japanese Yen">JPY</option><option value="MYR" title="Malaysian Ringgit">MYR</option><option value="MXN" title="Mexican Peso">MXN</option><option value="NOK" title="Norwegian Krone">NOK</option><option value="NZD" title="New Zealand Dollar">NZD</option><option value="PHP" title="Philippine Peso">PHP</option><option value="PLN" title="Polish Zloty">PLN</option><option value="GBP" title="Pound Sterling">GBP</option><option value="SGD" title="Singapore Dollar">SGD</option><option value="SEK" title="Swedish Krona">SEK</option><option value="CHF" title="Swiss Franc">CHF</option><option value="TWD" title="Taiwan New Dollar">TWD</option><option value="THB" title="Thai Baht">THB</option><option value="USD" title="U.S. Dollar">USD</option></optgroup></select> <input type="button" value="Generate Button Code" onclick="ws_plugin__s2member_paypalButtonGenerate(3);" class="button-primary" /></p>' . "\n";
169
+ echo '</td>' . "\n";
170
+ /**/
171
+ echo '</tr>' . "\n";
172
+ echo '<tr>' . "\n";
173
+ /**/
174
+ echo '<td colspan="2">' . "\n";
175
+ echo '<strong>WordPress® Shortcode:</strong> ( recommended for both the WordPress® Visual &amp; HTML Editors )<br />' . "\n";
176
+ $ws_plugin__s2member_temp_s = trim (file_get_contents (dirname (__FILE__) . "/shortcode.html"));
177
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%domain%%/", strtolower ($_SERVER["HTTP_HOST"]), $ws_plugin__s2member_temp_s);
178
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%level%%/", "3", $ws_plugin__s2member_temp_s);
179
+ echo '<input id="ws-plugin--s2member-level3-shortcode" type="text" value="' . format_to_edit ($ws_plugin__s2member_temp_s) . '" onclick="this.select ();" /><br /><br />' . "\n";
180
+ echo '<strong>Resulting PayPal® Button Code:</strong> ( ultimately, your Shortcode will produce this snippet )<br />' . "\n";
181
+ echo '<textarea id="ws-plugin--s2member-level3-button" rows="8" wrap="off" onclick="this.select ();">';
182
+ $ws_plugin__s2member_temp_s = trim (file_get_contents (dirname (__FILE__) . "/button.html"));
183
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%endpoint%%/", (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com"), $ws_plugin__s2member_temp_s);
184
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%paypal_business%%/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"], $ws_plugin__s2member_temp_s);
185
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%level_label%%/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_label"], $ws_plugin__s2member_temp_s);
186
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%cancel_return%%/", get_bloginfo ("url"), $ws_plugin__s2member_temp_s);
187
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%notify_url%%/", get_bloginfo ("url") . "/?s2member_paypal_notify=1", $ws_plugin__s2member_temp_s);
188
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%return%%/", get_bloginfo ("url") . "/?s2member_paypal_return=1", $ws_plugin__s2member_temp_s);
189
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%domain%%/", strtolower ($_SERVER["HTTP_HOST"]), $ws_plugin__s2member_temp_s);
190
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%level%%/", "3", $ws_plugin__s2member_temp_s);
191
+ echo format_to_edit ($ws_plugin__s2member_temp_s);
192
+ echo '</textarea><br />' . "\n";
193
+ echo '&uarr; Use this more advanced Code if you\'re building a theme or plugin that integrates with s2Member.' . "\n";
194
+ echo '</td>' . "\n";
195
+ /**/
196
+ echo '</tr>' . "\n";
197
+ echo '</tbody>' . "\n";
198
+ echo '</table>' . "\n";
199
+ echo '</div>' . "\n";
200
+ /**/
201
+ echo '</div>' . "\n";
202
+ /**/
203
+ echo '<div class="ws-menu-page-group" title="PayPal® Button For Level #4 Subscriptions">' . "\n";
204
+ /**/
205
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-button-code-4-section">' . "\n";
206
+ echo '<h3>Button Code Generator For Level #4 Subscriptions</h3>' . "\n";
207
+ echo '<p>Very simple. All you do is customize the form fields provided, for each Membership Level that you plan to offer. Then press (Generate Button Code). These special subscription buttons are customized to work with s2Member seamlessly. User accounts will be activated instantly, in an automated fashion. When you, or a User, cancels their membership, or fails to make payments on time, s2Member will automatically terminate their membership privileges using automated routines. s2Member makes extensive use of the PayPal® IPN service, which receives updates directly from PayPal® behind the scenes.</p>' . "\n";
208
+ echo '<p><em>* Buttons are NOT saved here. This is only a Button Generator. Once you\'ve generated your Button, copy/paste it into your Membership Options Page. If you lose your Button Code, you\'ll need to come back &amp; regenerate a new one. If you\'re currently in Sandbox testing mode, please remember to come back and regenerate new Buttons once you go live.</em></p>' . "\n";
209
+ /**/
210
+ echo '<table class="form-table">' . "\n";
211
+ echo '<tbody>' . "\n";
212
+ echo '<tr>' . "\n";
213
+ /**/
214
+ echo '<th class="ws-menu-page-th-side">' . "\n";
215
+ echo '<label for="ws-plugin--s2member-level4-button">' . "\n";
216
+ echo 'Button Code<br />For Level #4:<br /><br />' . "\n";
217
+ echo '<div id="ws-plugin--s2member-level4-button-prev"></div>' . "\n";
218
+ echo '</label>' . "\n";
219
+ echo '</th>' . "\n";
220
+ /**/
221
+ echo '<td>' . "\n";
222
+ 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="2" /> <select id="ws-plugin--s2member-level4-trial-term"><option value="D" selected="selected">Days</option><option value="W">Weeks</option><option value="M">Months</option><option value="Y">Years</option></select> free.</p>' . "\n";
223
+ 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"><optgroup label="Recurring Subscriptions"><option value="1-D-1">Daily ( recurring charge, for ongoing access )</option><option value="1-W-1">Weekly ( recurring charge, for ongoing access )</option><option value="1-M-1" selected="selected">Monthly ( recurring charge, for ongoing access )</option><option value="3-M-1">Quarterly ( recurring charge, for ongoing access )</option><option value="1-Y-1">Yearly ( recurring charge, for ongoing access )</option></optgroup><optgroup label="Days / Non-Recurring"><option value="1-D-0">One Time ( for 1 day access, non-recurring )</option><option value="2-D-0">One Time ( for 2 day access, non-recurring )</option><option value="3-D-0">One Time ( for 3 day access, non-recurring )</option><option value="4-D-0">One Time ( for 4 day access, non-recurring )</option><option value="5-D-0">One Time ( for 5 day access, non-recurring )</option><option value="6-D-0">One Time ( for 6 day access, non-recurring )</option></optgroup><optgroup label="Weeks / Non-Recurring"><option value="1-W-0">One Time ( for 1 week access, non-recurring )</option><option value="2-W-0">One Time ( for 2 week access, non-recurring )</option><option value="3-W-0">One Time ( for 3 week access, non-recurring )</option></optgroup><optgroup label="Months / Non-Recurring"><option value="1-M-0">One Time ( for 1 month access, non-recurring )</option><option value="2-M-0">One Time ( for 2 month access, non-recurring )</option><option value="3-M-0">One Time ( for 3 month access, non-recurring )</option><option value="4-M-0">One Time ( for 4 month access, non-recurring )</option><option value="5-M-0">One Time ( for 5 month access, non-recurring )</option><option value="6-M-0">One Time ( for 6 month access, non-recurring )</option></optgroup><optgroup label="Years / Non-Recurring"><option value="1-Y-0">One Time ( for 1 year access, non-recurring )</option><option value="2-Y-0">One Time ( for 2 year access, non-recurring )</option><option value="3-Y-0">One Time ( for 3 year access, non-recurring )</option><option value="4-Y-0">One Time ( for 4 year access, non-recurring )</option><option value="5-Y-0">One Time ( for 5 year access, non-recurring )</option></optgroup><optgroup label="Lifetime / Buy Now / Non-Recurring / No Trial"><option value="1-L-0">Buy Now ( for lifetime access, no-trial, non-recurring )</option></optgroup></select></p>' . "\n";
224
+ 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. Once you\\\'ve created a Custom Page Style at PayPal®, you can enter that Page Style here.\'); return false;">?</a>]: <input type="text" id="ws-plugin--s2member-level4-page-style" value="paypal" size="10" /> <select id="ws-plugin--s2member-level4-currency"><optgroup label="Currency"><option value="USD" title="U.S. Dollar">USD</option><option value="AUD" title="Australian Dollar">AUD</option><option value="BRL" title="Brazilian Real">BRL</option><option value="CAD" title="Canadian Dollar">CAD</option><option value="CZK" title="Czech Koruna">CZK</option><option value="DKK" title="Danish Krone">DKK</option><option value="EUR" title="Euro">EUR</option><option value="HKD" title="Hong Kong Dollar">HKD</option><option value="HUF" title="Hungarian Forint">HUF</option><option value="ILS" title="Israeli New Sheqel">ILS</option><option value="JPY" title="Japanese Yen">JPY</option><option value="MYR" title="Malaysian Ringgit">MYR</option><option value="MXN" title="Mexican Peso">MXN</option><option value="NOK" title="Norwegian Krone">NOK</option><option value="NZD" title="New Zealand Dollar">NZD</option><option value="PHP" title="Philippine Peso">PHP</option><option value="PLN" title="Polish Zloty">PLN</option><option value="GBP" title="Pound Sterling">GBP</option><option value="SGD" title="Singapore Dollar">SGD</option><option value="SEK" title="Swedish Krona">SEK</option><option value="CHF" title="Swiss Franc">CHF</option><option value="TWD" title="Taiwan New Dollar">TWD</option><option value="THB" title="Thai Baht">THB</option><option value="USD" title="U.S. Dollar">USD</option></optgroup></select> <input type="button" value="Generate Button Code" onclick="ws_plugin__s2member_paypalButtonGenerate(4);" class="button-primary" /></p>' . "\n";
225
+ echo '</td>' . "\n";
226
+ /**/
227
+ echo '</tr>' . "\n";
228
+ echo '<tr>' . "\n";
229
+ /**/
230
+ echo '<td colspan="2">' . "\n";
231
+ echo '<strong>WordPress® Shortcode:</strong> ( recommended for both the WordPress® Visual &amp; HTML Editors )<br />' . "\n";
232
+ $ws_plugin__s2member_temp_s = trim (file_get_contents (dirname (__FILE__) . "/shortcode.html"));
233
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%domain%%/", strtolower ($_SERVER["HTTP_HOST"]), $ws_plugin__s2member_temp_s);
234
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%level%%/", "4", $ws_plugin__s2member_temp_s);
235
+ echo '<input id="ws-plugin--s2member-level4-shortcode" type="text" value="' . format_to_edit ($ws_plugin__s2member_temp_s) . '" onclick="this.select ();" /><br /><br />' . "\n";
236
+ echo '<strong>Resulting PayPal® Button Code:</strong> ( ultimately, your Shortcode will produce this snippet )<br />' . "\n";
237
+ echo '<textarea id="ws-plugin--s2member-level4-button" rows="8" wrap="off" onclick="this.select ();">';
238
+ $ws_plugin__s2member_temp_s = trim (file_get_contents (dirname (__FILE__) . "/button.html"));
239
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%endpoint%%/", (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_sandbox"]) ? "www.sandbox.paypal.com" : "www.paypal.com"), $ws_plugin__s2member_temp_s);
240
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%paypal_business%%/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"], $ws_plugin__s2member_temp_s);
241
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%level_label%%/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_label"], $ws_plugin__s2member_temp_s);
242
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%cancel_return%%/", get_bloginfo ("url"), $ws_plugin__s2member_temp_s);
243
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%notify_url%%/", get_bloginfo ("url") . "/?s2member_paypal_notify=1", $ws_plugin__s2member_temp_s);
244
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%return%%/", get_bloginfo ("url") . "/?s2member_paypal_return=1", $ws_plugin__s2member_temp_s);
245
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%domain%%/", strtolower ($_SERVER["HTTP_HOST"]), $ws_plugin__s2member_temp_s);
246
+ $ws_plugin__s2member_temp_s = preg_replace ("/%%level%%/", "4", $ws_plugin__s2member_temp_s);
247
+ echo format_to_edit ($ws_plugin__s2member_temp_s);
248
+ echo '</textarea><br />' . "\n";
249
+ echo '&uarr; Use this more advanced Code if you\'re building a theme or plugin that integrates with s2Member.' . "\n";
250
+ echo '</td>' . "\n";
251
+ /**/
252
+ echo '</tr>' . "\n";
253
+ echo '</tbody>' . "\n";
254
+ echo '</table>' . "\n";
255
+ echo '</div>' . "\n";
256
+ /**/
257
+ echo '</div>' . "\n";
258
+ /**/
259
+ echo '</form>' . "\n";
260
+ }
261
+ else /* They need to first configure the options. */
262
+ echo '<p>Please configure the s2Member PayPal® Options first. Once your PayPal® Options have been properly configured, return to this page &amp; generate your PayPal® subscription button(s).</p>' . "\n";
263
+ /**/
264
+ echo '</td>' . "\n";
265
+ /**/
266
+ echo '<td class="ws-menu-page-table-r">' . "\n";
267
+ /**/
268
+ echo ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["menu-r"]["tools"]) ? '<div class="ws-menu-page-tools"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-tools.png" alt="." /></div>' . "\n" : '';
269
+ /**/
270
+ echo ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["menu-r"]["tips"]) ? '<div class="ws-menu-page-tips"><a href="' . ws_plugin__s2member_parse_readme_value ("Customization URI") . '"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-tips.png" alt="." /></a></div>' . "\n" : '';
271
+ /**/
272
+ echo ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["menu-r"]["donations"]) ? '<div class="ws-menu-page-donations"><a href="' . ws_plugin__s2member_parse_readme_value ("Donate link") . '"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-donations.jpg" alt="." /></a></div>' . "\n" : '';
273
+ /**/
274
+ echo '</td>' . "\n";
275
+ /**/
276
+ echo '</tr>' . "\n";
277
+ echo '</tbody>' . "\n";
278
+ echo '</table>' . "\n";
279
+ /**/
280
+ echo '</div>' . "\n";
281
+ ?>
includes/menu-pages/con-samps/current_user_access_label.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php echo S2MEMBER_CURRENT_USER_ACCESS_LABEL; ?>
2
+ This may output something like: Gold Membership
3
+ ( or whatever label you've configured for their membership level )
includes/menu-pages/con-samps/current_user_access_level.php ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php if (S2MEMBER_CURRENT_USER_ACCESS_LEVEL === 4){ ?>
2
+ Member has an access level of 4.
3
+ <?php } else if (S2MEMBER_CURRENT_USER_ACCESS_LEVEL === 3){ ?>
4
+ Member has an access level of 3.
5
+ <?php } else if (S2MEMBER_CURRENT_USER_ACCESS_LEVEL === 2){ ?>
6
+ Member has an access level of 2.
7
+ <?php } else if (S2MEMBER_CURRENT_USER_ACCESS_LEVEL === 1){ ?>
8
+ Member has an access level of 1.
9
+ <?php } else if(S2MEMBER_CURRENT_USER_ACCESS_LEVEL === 0){ ?>
10
+ User is logged in but is not a member.
11
+ <?php } else if(S2MEMBER_CURRENT_USER_ACCESS_LEVEL === -1){ ?>
12
+ User is not logged in.
13
+ <?php } ?>
includes/menu-pages/con-samps/current_user_custom.php ADDED
@@ -0,0 +1,3 @@
 
 
 
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 )
includes/menu-pages/con-samps/current_user_display_name.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php echo S2MEMBER_CURRENT_USER_DISPLAY_NAME; ?>
2
+ This may output something like: Johnny
3
+ ( this is the User's display name )
includes/menu-pages/con-samps/current_user_downloads_allowed.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php echo S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED; ?>
2
+ This will output the number of files they're allowed to download.
3
+ ( the number of files allowed is based on their membership level )
includes/menu-pages/con-samps/current_user_downloads_allowed_days.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php echo S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS; ?>
2
+ This will output the number of days ( the period ) in which stats are being kept.
3
+ ( users are allowed to download X number of files every X number of days )
includes/menu-pages/con-samps/current_user_downloads_allowed_is_unlimited.php ADDED
@@ -0,0 +1,2 @@
 
 
1
+ You are allowed to download <?php echo (S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_IS_UNLIMITED) ? 'Unlimited' : S2MEMBER_LEVEL2_FILE_DOWNLOADS_ALLOWED; ?> files
2
+ every <?php S2MEMBER_LEVEL2_FILE_DOWNLOADS_ALLOWED_DAYS; ?> days.
includes/menu-pages/con-samps/current_user_downloads_currently.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php echo S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY; ?>
2
+ This will output the number of files they've downloaded recently.
3
+ ( that is, the number of files within the last X days, according to your configuration )
includes/menu-pages/con-samps/current_user_email.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php echo S2MEMBER_CURRENT_USER_EMAIL; ?>
2
+ This may output something like: johnsmith@example.com
3
+ ( or whatever their email address is )
includes/menu-pages/con-samps/current_user_fields.php ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
1
+ <?php $fields = unserialize(S2MEMBER_CURRENT_USER_FIELDS); ?>
2
+ <?php echo $fields["first_name"]; ?> <?php echo $fields["last_name"]; ?>
3
+ This would output the first and last name for the current user.
4
+
5
+ Custom Fields are also included in the unserialized array.
6
+ <?php print_r(unserialize(S2MEMBER_CURRENT_USER_FIELDS)); ?>
7
+ ( Displays a full list of all array elements. )
includes/menu-pages/con-samps/current_user_first_name.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php echo S2MEMBER_CURRENT_USER_FIRST_NAME; ?>
2
+ This may output something like: John
3
+ ( or whatever their first name is )
includes/menu-pages/con-samps/current_user_id.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php echo S2MEMBER_CURRENT_USER_ID; ?>
2
+ This may output something like: 5547
3
+ ( or whatever their user ID# is )
includes/menu-pages/con-samps/current_user_ip.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php echo S2MEMBER_CURRENT_USER_IP; ?>
2
+ This may output something like: 123.456.789.111
3
+ ( or whatever the current user's IP address happens to be )
includes/menu-pages/con-samps/current_user_is_logged_in.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php if (S2MEMBER_CURRENT_USER_IS_LOGGED_IN){ ?>
2
+ The user is logged in.
3
+ <?php } ?>
includes/menu-pages/con-samps/current_user_last_name.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php echo S2MEMBER_CURRENT_USER_LAST_NAME; ?>
2
+ This may output something like: Smith
3
+ ( or whatever their last name is )
includes/menu-pages/con-samps/current_user_login.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php echo S2MEMBER_CURRENT_USER_LOGIN; ?>
2
+ This may output something like: johnsmith22
3
+ ( or whatever their login/username is )
includes/menu-pages/con-samps/current_user_profile_modification_page_url.php ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
1
+ <a href="#" onclick="if(!window.open('<?php echo S2MEMBER_CURRENT_USER_PROFILE_MODIFICATION_PAGE_URL; ?>',
2
+ '_popup', 'height=350,width=400,left=100,screenX=100,top=100,screenY=100,
3
+ location=0,menubar=0,toolbar=0,status=0,scrollbars=1,resizable=1'))
4
+ alert('Please disable popup blockers and try again!');
5
+ return false;">Modify Profile</a>
6
+
7
+ This could also be embedded into a Post/Page using an IFRAME tag. So if you don't like using pop-ups, try this:
8
+ <iframe src="<?php echo S2MEMBER_CURRENT_USER_PROFILE_MODIFICATION_PAGE_URL; ?>" scrolling="auto" style="width:100%; height:325px; border:1px solid #666666;"></iframe>
includes/menu-pages/con-samps/current_user_registration_days.php ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php echo S2MEMBER_CURRENT_USER_REGISTRATION_DAYS; ?>
2
+ This may output something like: 120
3
+ ( 120 days means they've been a Member for approx 4 months )
4
+
5
+ Here is a more practical example:
6
+
7
+ <?php if(S2MEMBER_CURRENT_USER_REGISTRATION_DAYS >= 90){ ?>
8
+ Drip content to Members who are more than 90 days old.
9
+ <?php } else if(S2MEMBER_CURRENT_USER_REGISTRATION_DAYS >= 60){ ?>
10
+ Drip content to Members who are more than 60 days old.
11
+ <?php } else if(S2MEMBER_CURRENT_USER_REGISTRATION_DAYS >= 30){ ?>
12
+ Drip content to Members who are more than 30 days old.
13
+ <?php } else { ?>
14
+ Initial content for newer Members.
15
+ <?php } ?>
includes/menu-pages/con-samps/current_user_registration_time.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php echo S2MEMBER_CURRENT_USER_REGISTRATION_TIME; ?>
2
+ This may output something like: 1270537981
3
+ ( this is a Unix timestamp, which is based on seconds )
includes/menu-pages/con-samps/current_user_subscr_id.php ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
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 )
includes/menu-pages/con-samps/file_download_limit_exceeded_page_url.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php if (S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY > S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED){ ?>
2
+ Limit Exceeded, <a href="<?php echo S2MEMBER_FILE_DOWNLOAD_LIMIT_EXCEEDED_PAGE_URL; ?>">click here for details</a>.
3
+ <?php } ?>
includes/menu-pages/con-samps/level1_file_downloads_allowed.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ Level #1 users are allowed to download
2
+ <?php echo S2MEMBER_LEVEL1_FILE_DOWNLOADS_ALLOWED; ?> files
3
+ every <?php S2MEMBER_LEVEL1_FILE_DOWNLOADS_ALLOWED_DAYS; ?> days.
includes/menu-pages/con-samps/level1_file_downloads_allowed_days.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ Level #1 users are allowed to download
2
+ <?php echo S2MEMBER_LEVEL1_FILE_DOWNLOADS_ALLOWED; ?> files
3
+ every <?php S2MEMBER_LEVEL1_FILE_DOWNLOADS_ALLOWED_DAYS; ?> days.
includes/menu-pages/con-samps/level1_label.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php echo S2MEMBER_LEVEL1_LABEL; ?>
2
+ This may output something like: Bronze Membership
3
+ ( or whatever label you've configured for level #1 )
includes/menu-pages/con-samps/level2_file_downloads_allowed.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ Level #2 users are allowed to download
2
+ <?php echo S2MEMBER_LEVEL2_FILE_DOWNLOADS_ALLOWED; ?> files
3
+ every <?php S2MEMBER_LEVEL2_FILE_DOWNLOADS_ALLOWED_DAYS; ?> days.
includes/menu-pages/con-samps/level2_file_downloads_allowed_days.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ Level #2 users are allowed to download
2
+ <?php echo S2MEMBER_LEVEL2_FILE_DOWNLOADS_ALLOWED; ?> files
3
+ every <?php S2MEMBER_LEVEL2_FILE_DOWNLOADS_ALLOWED_DAYS; ?> days.
includes/menu-pages/con-samps/level2_label.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php echo S2MEMBER_LEVEL2_LABEL; ?>
2
+ This may output something like: Silver Membership
3
+ ( or whatever label you've configured for level #2 )
includes/menu-pages/con-samps/level3_file_downloads_allowed.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ Level #3 users are allowed to download
2
+ <?php echo S2MEMBER_LEVEL3_FILE_DOWNLOADS_ALLOWED; ?> files
3
+ every <?php S2MEMBER_LEVEL3_FILE_DOWNLOADS_ALLOWED_DAYS; ?> days.
includes/menu-pages/con-samps/level3_file_downloads_allowed_days.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ Level #3 users are allowed to download
2
+ <?php echo S2MEMBER_LEVEL3_FILE_DOWNLOADS_ALLOWED; ?> files
3
+ every <?php S2MEMBER_LEVEL3_FILE_DOWNLOADS_ALLOWED_DAYS; ?> days.
includes/menu-pages/con-samps/level3_label.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php echo S2MEMBER_LEVEL3_LABEL; ?>
2
+ This may output something like: Gold Membership
3
+ ( or whatever label you've configured for level #3 )
includes/menu-pages/con-samps/level4_file_downloads_allowed.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ Level #4 users are allowed to download
2
+ <?php echo S2MEMBER_LEVEL4_FILE_DOWNLOADS_ALLOWED; ?> files
3
+ every <?php S2MEMBER_LEVEL4_FILE_DOWNLOADS_ALLOWED_DAYS; ?> days.
includes/menu-pages/con-samps/level4_file_downloads_allowed_days.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ Level #4 users are allowed to download
2
+ <?php echo S2MEMBER_LEVEL4_FILE_DOWNLOADS_ALLOWED; ?> files
3
+ every <?php S2MEMBER_LEVEL4_FILE_DOWNLOADS_ALLOWED_DAYS; ?> days.
includes/menu-pages/con-samps/level4_label.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php echo S2MEMBER_LEVEL4_LABEL; ?>
2
+ This may output something like: Platinum Membership
3
+ ( or whatever label you've configured for level #4 )
includes/menu-pages/con-samps/login_page_url.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php if (!S2MEMBER_CURRENT_USER_IS_LOGGED_IN){ ?>
2
+ <a href="<?php echo S2MEMBER_MEMBERSHIP_OPTIONS_PAGE_URL; ?>">Please Signup</a>
3
+ | <a href="<?php echo S2MEMBER_LOGIN_PAGE_URL; ?>">Or Login</a>
4
+ <?php } ?>
includes/menu-pages/con-samps/login_welcome_page_url.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php if (S2MEMBER_CURRENT_USER_IS_LOGGED_IN){ ?>
2
+ <a href="<?php echo S2MEMBER_LOGIN_WELCOME_PAGE_URL; ?>">My Account</a>
3
+ | <a href="<?php echo S2MEMBER_LOGOUT_PAGE_URL; ?>">Logout</a>
4
+ <?php } ?>
includes/menu-pages/con-samps/logout_page_url.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php if (S2MEMBER_CURRENT_USER_IS_LOGGED_IN){ ?>
2
+ <a href="<?php echo S2MEMBER_LOGIN_WELCOME_PAGE_URL; ?>">My Account</a>
3
+ | <a href="<?php echo S2MEMBER_LOGOUT_PAGE_URL; ?>">Logout</a>
4
+ <?php } ?>
includes/menu-pages/con-samps/membership_options_page_url.php ADDED
@@ -0,0 +1,4 @@
 
 
 
 
1
+ <?php if (!S2MEMBER_CURRENT_USER_IS_LOGGED_IN){ ?>
2
+ <a href="<?php echo S2MEMBER_MEMBERSHIP_OPTIONS_PAGE_URL; ?>">Please Signup</a>
3
+ | <a href="<?php echo S2MEMBER_LOGIN_PAGE_URL; ?>">Or Login</a>
4
+ <?php } ?>
includes/menu-pages/con-samps/paypal_business.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php echo S2MEMBER_PAYPAL_BUSINESS; ?>
2
+ This may output something like: paypal@example.com
3
+ ( or whatever you have configured as your paypal email address )
includes/menu-pages/con-samps/paypal_endpoint.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php echo S2MEMBER_PAYPAL_ENDPOINT; ?>
2
+ This will output the paypal endpoint domain: www.paypal.com
3
+ ( if sandbox testing is enabled, it will output www.sandbox.paypal.com )
includes/menu-pages/con-samps/paypal_notify_url.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php echo S2MEMBER_PAYPAL_NOTIFY_URL; ?>
2
+ This will output something like: http://www.example.com/?s2member_paypal_notify=1
3
+ ( this is used silently behind the scenes to communicate back and forth with PayPal )
includes/menu-pages/con-samps/paypal_return_url.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php echo S2MEMBER_PAYPAL_RETURN_URL; ?>
2
+ This will output something like: http://www.example.com/?s2member_paypal_return=1
3
+ ( this is used as the Signup Confirmation Page, and also handles PDT w/ Auto-Return )
includes/menu-pages/con-samps/reg_email_from_email.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php echo S2MEMBER_REG_EMAIL_FROM_EMAIL; ?>
2
+ This may output something like: support@example.com
3
+ ( or whatever you have configured as your From: email )
includes/menu-pages/con-samps/reg_email_from_name.php ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ <?php echo S2MEMBER_REG_EMAIL_FROM_NAME; ?>
2
+ This may output something like: Member Support
3
+ ( or whatever you have configured as your From: name )
includes/menu-pages/cur-samps.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Example #1, Allow all levels greater than or equal to 1 full access.
2
+
3
+ <?php if (current_user_can("access_s2member_level1")){ ?>
4
+ Show premium members-only content to all members.
5
+ <?php } else { ?>
6
+ Show non-member public content.
7
+ <?php } ?>
8
+
9
+ Example #2, Specific content for each member level.
10
+
11
+ <?php if (current_user_can("access_s2member_level4")){ ?>
12
+ Show level 4 member content.
13
+ <?php } else if (current_user_can("access_s2member_level3")){ ?>
14
+ Show level 3 member content.
15
+ <?php } else if (current_user_can("access_s2member_level2")){ ?>
16
+ Show level 2 member content.
17
+ <?php } else if (current_user_can("access_s2member_level1")){ ?>
18
+ Show level 1 member content.
19
+ <?php } else { ?>
20
+ Show non-member content.
21
+ <?php } ?>
22
+
23
+ * Tip ( levels allow incremental access to areas of your site ).
24
+ - A user with level 4 access will also be able to access levels 1, 2 & 3.
25
+ - A user with level 3 access will also be able to access levels 1 & 2.
26
+ - A user with level 2 access will also be able to access level 1.
27
+ - A user with level 1 access will only be able to access level 1.
28
+
29
+ * WordPress® Administrators, Editors, Authors, and Contributors have level 4 access.
30
+
31
+ * WordPress® Subscribers are not allowed membership access. They must be promoted to a member.
32
+ However, if you set `Allow Free Subscribers` to `Yes`, then Free Subscribers WILL be able to access
33
+ your Login Welcome Page, but that is all. See `s2Member->General Options->Login Welcome Page`.
includes/menu-pages/down-ops.inc.php ADDED
@@ -0,0 +1,189 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Download Options page.
18
+ */
19
+ echo '<div class="wrap ws-menu-page">' . "\n";
20
+ /**/
21
+ echo '<div id="icon-plugins" class="icon32"><br /></div>' . "\n";
22
+ echo '<h2><div>Developed by <a href="' . ws_plugin__s2member_parse_readme_value ("Plugin URI") . '"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-light.png" alt="." /></a></div>s2Member File Download Options</h2>' . "\n";
23
+ /**/
24
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
25
+ /**/
26
+ echo '<table class="ws-menu-page-table">' . "\n";
27
+ echo '<tbody class="ws-menu-page-table-tbody">' . "\n";
28
+ echo '<tr class="ws-menu-page-table-tr">' . "\n";
29
+ echo '<td class="ws-menu-page-table-l">' . "\n";
30
+ /**/
31
+ echo '<form method="post" name="ws_plugin__s2member_options_form" id="ws-plugin--s2member-options-form">' . "\n";
32
+ echo '<input type="hidden" name="ws_plugin__s2member_options_save" id="ws-plugin--s2member-options-save" value="' . esc_attr (wp_create_nonce ("ws-plugin--s2member-options-save")) . '" />' . "\n";
33
+ echo '<input type="hidden" name="ws_plugin__s2member_configured" id="ws-plugin--s2member-configured" value="1" />' . "\n";
34
+ /**/
35
+ echo '<div class="ws-menu-page-group" title="Protected File Downloads">' . "\n";
36
+ /**/
37
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-download-restrictions-section">' . "\n";
38
+ echo '<h3>File Download Restrictions ( required, if providing access to protected files )</h3>' . "\n";
39
+ echo '<p>If your membership offering allows access to restricted files, you\'ll need to configure these options.</p>' . "\n";
40
+ /**/
41
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
42
+ /**/
43
+ echo '<h3>Upload restricted files to this security-enabled directory:<br /> <code>' . preg_replace ("/^" . preg_quote ($_SERVER["DOCUMENT_ROOT"], "/") . "/", "", $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"]) . '</code></h3>' . "\n";
44
+ echo '<p>- Then, you can link to these restricted files using this special format:<br />&nbsp;&nbsp;<code>' . get_bloginfo ("url") . '/?<strong>s2member_file_download</strong>=example-file.zip</code><br />&nbsp;&nbsp;<small><em><strong>s2member_file_download</strong> = location of the file, relative to the /' . esc_html (basename ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/ directory. In other words, just the file name.</em></small></p>' . "\n";
45
+ echo '<p>- If needed, you can make certain files available free, using an extra variable:<br />&nbsp;&nbsp;<code>' . get_bloginfo ("url") . '/?<strong>s2member_file_download</strong>=example-file.zip&<strong>s2member_free_file_download_key</strong>=&lt;?php echo s2member_xencrypt("example-file.zip"); ?&gt;</code><br />&nbsp;&nbsp;<small><em><strong>s2member_free_file_download_key</strong> = &lt;?php echo s2member_xencrypt("location of the file, relative to the /' . esc_html (basename ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"])) . '/ directory"); ?&gt;</em></small></p>' . "\n";
46
+ /**/
47
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
48
+ /**/
49
+ echo '<p>s2Member will allow access to these protected files, based on the configuration you specify below. <em>* Note: 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.</em></p>' . "\n";
50
+ 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 consious decision about whether to proceed with a specific download or not.</p>' . "\n";
51
+ echo '<p><em>* The above only applies to users who are logged in as members. For all other users in the general public, the <code>?s2member_file_download</code> links will redirect them your Membership Options Page, so that new users can signup, in order to gain access.</em></p>' . "\n";
52
+ /**/
53
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
54
+ /**/
55
+ echo '<table class="form-table">' . "\n";
56
+ echo '<tbody>' . "\n";
57
+ echo '<tr>' . "\n";
58
+ /**/
59
+ echo '<th>' . "\n";
60
+ echo '<label for="ws-plugin--s2member-level1-file-downloads-allowed">' . "\n";
61
+ echo 'File Downloads ( Level #1 Or Higher ):' . "\n";
62
+ echo '</label>' . "\n";
63
+ echo '</th>' . "\n";
64
+ /**/
65
+ echo '</tr>' . "\n";
66
+ echo '<tr>' . "\n";
67
+ /**/
68
+ echo '<td>' . "\n";
69
+ echo '<input type="text" name="ws_plugin__s2member_level1_file_downloads_allowed" id="ws-plugin--s2member-level1-file-downloads-allowed" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_file_downloads_allowed"]) . '" style="width:200px;" maxlength="9" /> every <input type="text" name="ws_plugin__s2member_level1_file_downloads_allowed_days" id="ws-plugin--s2member-level1-file-downloads-allowed-days" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_file_downloads_allowed_days"]) . '" style="width:200px;" maxlength="3" onkeyup="if(this.value > 365){ alert(\'( 365 days is the maximum ).\\nThis keeps the logs optimized.\'); this.value = 365; }" /> days.<br />' . "\n";
70
+ echo 'Only this many unique downloads ( <code><em>999999999 = unlimited</em></code> ) will be permitted every X days.' . "\n";
71
+ echo '</td>' . "\n";
72
+ /**/
73
+ echo '</tr>' . "\n";
74
+ echo '<tr>' . "\n";
75
+ /**/
76
+ echo '<th>' . "\n";
77
+ echo '<label for="ws-plugin--s2member-level2-file-downloads-allowed">' . "\n";
78
+ echo 'File Downloads ( Level #2 Or Higher ):' . "\n";
79
+ echo '</label>' . "\n";
80
+ echo '</th>' . "\n";
81
+ /**/
82
+ echo '</tr>' . "\n";
83
+ echo '<tr>' . "\n";
84
+ /**/
85
+ echo '<td>' . "\n";
86
+ echo '<input type="text" name="ws_plugin__s2member_level2_file_downloads_allowed" id="ws-plugin--s2member-level2-file-downloads-allowed" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_file_downloads_allowed"]) . '" style="width:200px;" maxlength="9" /> every <input type="text" name="ws_plugin__s2member_level2_file_downloads_allowed_days" id="ws-plugin--s2member-level2-file-downloads-allowed-days" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_file_downloads_allowed_days"]) . '" style="width:200px;" maxlength="3" onkeyup="if(this.value > 365){ alert(\'( 365 days is the maximum ).\\nThis keeps the logs optimized.\'); this.value = 365; }" /> days.<br />' . "\n";
87
+ echo 'Only this many unique downloads ( <code><em>999999999 = unlimited</em></code> ) will be permitted every X days.' . "\n";
88
+ echo '</td>' . "\n";
89
+ /**/
90
+ echo '</tr>' . "\n";
91
+ echo '<tr>' . "\n";
92
+ /**/
93
+ echo '<th>' . "\n";
94
+ echo '<label for="ws-plugin--s2member-level3-file-downloads-allowed">' . "\n";
95
+ echo 'File Downloads ( Level #3 Or Higher ):' . "\n";
96
+ echo '</label>' . "\n";
97
+ echo '</th>' . "\n";
98
+ /**/
99
+ echo '</tr>' . "\n";
100
+ echo '<tr>' . "\n";
101
+ /**/
102
+ echo '<td>' . "\n";
103
+ echo '<input type="text" name="ws_plugin__s2member_level3_file_downloads_allowed" id="ws-plugin--s2member-level3-file-downloads-allowed" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_file_downloads_allowed"]) . '" style="width:200px;" maxlength="9" /> every <input type="text" name="ws_plugin__s2member_level3_file_downloads_allowed_days" id="ws-plugin--s2member-level3-file-downloads-allowed-days" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_file_downloads_allowed_days"]) . '" style="width:200px;" maxlength="3" onkeyup="if(this.value > 365){ alert(\'( 365 days is the maximum ).\\nThis keeps the logs optimized.\'); this.value = 365; }" /> days.<br />' . "\n";
104
+ echo 'Only this many unique downloads ( <code><em>999999999 = unlimited</em></code> ) will be permitted every X days.' . "\n";
105
+ echo '</td>' . "\n";
106
+ /**/
107
+ echo '</tr>' . "\n";
108
+ echo '<tr>' . "\n";
109
+ /**/
110
+ echo '<th>' . "\n";
111
+ echo '<label for="ws-plugin--s2member-level4-file-downloads-allowed">' . "\n";
112
+ echo 'File Downloads ( Highest Level #4 ):' . "\n";
113
+ echo '</label>' . "\n";
114
+ echo '</th>' . "\n";
115
+ /**/
116
+ echo '</tr>' . "\n";
117
+ echo '<tr>' . "\n";
118
+ /**/
119
+ echo '<td>' . "\n";
120
+ echo '<input type="text" name="ws_plugin__s2member_level4_file_downloads_allowed" id="ws-plugin--s2member-level4-file-downloads-allowed" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_file_downloads_allowed"]) . '" style="width:200px;" maxlength="9" /> every <input type="text" name="ws_plugin__s2member_level4_file_downloads_allowed_days" id="ws-plugin--s2member-level4-file-downloads-allowed-days" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_file_downloads_allowed_days"]) . '" style="width:200px;" maxlength="3" onkeyup="if(this.value > 365){ alert(\'( 365 days is the maximum ).\\nThis keeps the logs optimized.\'); this.value = 365; }" /> days.<br />' . "\n";
121
+ echo 'Only this many unique downloads ( <code><em>999999999 = unlimited</em></code> ) will be permitted every X days.' . "\n";
122
+ echo '</td>' . "\n";
123
+ /**/
124
+ echo '</tr>' . "\n";
125
+ echo '</tbody>' . "\n";
126
+ echo '</table>' . "\n";
127
+ echo '</div>' . "\n";
128
+ /**/
129
+ echo '</div>' . "\n";
130
+ /**/
131
+ echo '<div class="ws-menu-page-group" title="Download Limit Exceeded">' . "\n";
132
+ /**/
133
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-limit-exceeded-section">' . "\n";
134
+ echo '<h3>Download Limit Exceeded Page ( required, if providing access to protected files )</h3>' . "\n";
135
+ echo '<p>This Page will be shown if a user reaches their download limit, based on the configuration you\'ve specified in the fields above. This Page should be created by you, in WordPress®. This Page should provide an informative message to the User, describing your file access restrictions. Just tell them a little bit about your policy on file downloads, and why they might have reached this Page.</p>' . "\n";
136
+ /**/
137
+ echo '<table class="form-table">' . "\n";
138
+ echo '<tbody>' . "\n";
139
+ echo '<tr>' . "\n";
140
+ /**/
141
+ echo '<th>' . "\n";
142
+ echo '<label for="ws-plugin--s2member-file-download-limit-exceeded-page">' . "\n";
143
+ echo 'Download Limit Exceeded Page:' . "\n";
144
+ echo '</label>' . "\n";
145
+ echo '</th>' . "\n";
146
+ /**/
147
+ echo '</tr>' . "\n";
148
+ echo '<tr>' . "\n";
149
+ /**/
150
+ echo '<td>' . "\n";
151
+ echo '<option value="">&mdash; Select &mdash;</option>' . "\n";
152
+ echo '<select name="ws_plugin__s2member_file_download_limit_exceeded_page" id="ws-plugin--s2member-file-download-limit-exceeded-page">' . "\n";
153
+ foreach (($ws_plugin__s2member_temp_a = array_merge ((array)get_pages ())) as $ws_plugin__s2member_temp_o)
154
+ 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";
155
+ echo '</select><br />' . "\n";
156
+ echo 'Please choose a Page that Users will see if they reach their file download limit. This Page should provide an informative message to the User, 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";
157
+ echo '</td>' . "\n";
158
+ /**/
159
+ echo '</tr>' . "\n";
160
+ echo '</tbody>' . "\n";
161
+ echo '</table>' . "\n";
162
+ echo '</div>' . "\n";
163
+ /**/
164
+ echo '</div>' . "\n";
165
+ /**/
166
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
167
+ /**/
168
+ echo '<p class="submit"><input type="submit" class="button-primary" value="Save Changes" /></p>' . "\n";
169
+ /**/
170
+ echo '</form>' . "\n";
171
+ /**/
172
+ echo '</td>' . "\n";
173
+ /**/
174
+ echo '<td class="ws-menu-page-table-r">' . "\n";
175
+ /**/
176
+ echo ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["menu-r"]["tools"]) ? '<div class="ws-menu-page-tools"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-tools.png" alt="." /></div>' . "\n" : '';
177
+ /**/
178
+ echo ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["menu-r"]["tips"]) ? '<div class="ws-menu-page-tips"><a href="' . ws_plugin__s2member_parse_readme_value ("Customization URI") . '"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-tips.png" alt="." /></a></div>' . "\n" : '';
179
+ /**/
180
+ echo ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["menu-r"]["donations"]) ? '<div class="ws-menu-page-donations"><a href="' . ws_plugin__s2member_parse_readme_value ("Donate link") . '"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-donations.jpg" alt="." /></a></div>' . "\n" : '';
181
+ /**/
182
+ echo '</td>' . "\n";
183
+ /**/
184
+ echo '</tr>' . "\n";
185
+ echo '</tbody>' . "\n";
186
+ echo '</table>' . "\n";
187
+ /**/
188
+ echo '</div>' . "\n";
189
+ ?>
includes/menu-pages/drip-samps.php ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ <?php if(S2MEMBER_CURRENT_USER_REGISTRATION_DAYS >= 90){ ?>
2
+ Drip content to Members who are more than 90 days old.
3
+ <?php } else if(S2MEMBER_CURRENT_USER_REGISTRATION_DAYS >= 60){ ?>
4
+ Drip content to Members who are more than 60 days old.
5
+ <?php } else if(S2MEMBER_CURRENT_USER_REGISTRATION_DAYS >= 30){ ?>
6
+ Drip content to Members who are more than 30 days old.
7
+ <?php } else { ?>
8
+ Initial content for newer Members.
9
+ <?php } ?>
includes/menu-pages/events.inc.php ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Flow Of Events page.
18
+ */
19
+ echo '<div class="wrap ws-menu-page">' . "\n";
20
+ /**/
21
+ echo '<div id="icon-plugins" class="icon32"><br /></div>' . "\n";
22
+ echo '<h2><div>Developed by <a href="' . ws_plugin__s2member_parse_readme_value ("Plugin URI") . '"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-light.png" alt="." /></a></div>s2Member Flow Of Events</h2>' . "\n";
23
+ /**/
24
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
25
+ /**/
26
+ echo '<table class="ws-menu-page-table">' . "\n";
27
+ echo '<tbody class="ws-menu-page-table-tbody">' . "\n";
28
+ echo '<tr class="ws-menu-page-table-tr">' . "\n";
29
+ echo '<td class="ws-menu-page-table-l">' . "\n";
30
+ /**/
31
+ echo '<div class="ws-menu-page-group" title="The Registration Process">' . "\n";
32
+ /**/
33
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-registration-process-section">' . "\n";
34
+ echo '<h3>The Subscription Registration Process</h3>' . "\n";
35
+ echo '<p>1. Internet Users will go to your Membership Options Page ( which you\'ll need to configure on the s2Member General Options panel ). On this Membership Options Page, that YOU will create in WordPress®, you\'ll insert the PayPal® Subscription Buttons that were generated for you by s2Member.</p>' . "\n";
36
+ echo '<p>2. An Internet User will click on a PayPal® Subscription Button from your Membership Options Page. They will be transferred over to PayPal® in order to agree to your membership terms and pricing. You can customize the Checkout Page Style, Pricing, Payment Periods, and more whenever you generate your PayPal® Buttons through s2Member.</p>' . "\n";
37
+ echo '<p>3. Once a User has completed the Subscription Signup Process at PayPal®, they\'ll be returned to your site, where they\'ll be activated by s2Member instantly, and given the opportunity to register a Username &amp; Password for their membership on the next page ( note: they\'ll be allowed to register a Username &amp; Password, even if you\'ve set \'Anyone Can Register\' to `Off` in your General WordPress® options, because s2Member identifies the user as having paid for membership access through PayPal® ). s2Member will also send the User an email with instructions on how to register their Username &amp; Password, just in case they missed the instructions after checkout. That email will be sent to their PayPal® email address. And it will be sent even if they never returned to your site after checkout for some reason. Much of this is handled through the PayPal® IPN service behind the scenes, where PayPal® and s2Member communicate with each other.</p>' . "\n";
38
+ echo '<p>4. Once a User has completed checkout and registered a Username &amp; Password, they\'ll be able to login. The first page they\'ll see after logging in, will be your Login Welcome Page ( which you\'ll need to configure on the s2Member General Options panel ). Your Login Welcome Page can contain whatever you like. Feel free to be creative whenever you create this Page in WordPress®.</p>' . "\n";
39
+ echo '</div>' . "\n";
40
+ /**/
41
+ echo '</div>' . "\n";
42
+ /**/
43
+ echo '<div class="ws-menu-page-group" title="Subscription Cancellations">' . "\n";
44
+ /**/
45
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-automation-process-section">' . "\n";
46
+ echo '<h3>Subscription Cancellations / Expirations / Terminations</h3>' . "\n";
47
+ echo '<p>You\'ll be happy to know that s2Member handles cancellations, expirations, failed payments ( more than 2 in a row ), terminations ( e.g. refunds &amp; chargebacks ) for you automatically. If you log into your PayPal® account and cancel a User\'s subscription, or, if the User 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 scenes. The PayPal® IPN service will notify s2Member whenever a User\'s payments have been failing ( more than 2 times in a row ), and/or whenever a User\'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 be deleted automagically. The communication from PayPal® -> s2Member is seamless. You may also want to check the s2Member API Notifications panel. You\'ll find additional layers of automation available through the use of the `Signup`, `Payment`, `EOT/Deletion` and `Refund/Reversal` notifications that are available to you through the s2Member API. These make it easy to integrate with 3rd party applications like affiliate programs and other back-office routines.</p>' . "\n";
48
+ echo '</div>' . "\n";
49
+ /**/
50
+ echo '<div class="ws-menu-page-hr ws-plugin--s2member-automation-hairy-details-section-hr"></div>' . "\n";
51
+ /**/
52
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-automation-hairy-details-section">' . "\n";
53
+ echo '<h3>Subscription Cancellations / Some Hairy Details With Dates</h3>' . "\n";
54
+ echo '<p>There might be times whenever you notice that a User\'s subscription has been cancelled through PayPal®... but, s2Member continues to allow the User to access 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 the SUBSCR_EOT notification via the IPN service. PayPal® will sometimes wait to send this SUBSCR_EOT notification 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 and PayPal® will send the SUBSCR_EOT notification to s2Member. At that time, s2Member will remove their membership privileges by deleting their account from the system automatically.</p>' . "\n";
55
+ echo '</div>' . "\n";
56
+ /**/
57
+ echo '</div>' . "\n";
58
+ /**/
59
+ echo '<div class="ws-menu-page-group" title="Upgrading/Downgrading Accounts">' . "\n";
60
+ /**/
61
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-upgrading-downgrading-section">' . "\n";
62
+ echo '<h3>Upgrading And/Or Downgrading User Accounts</h3>' . "\n";
63
+ echo '<p>s2Member builds upon existing functionality offered through WordPress® Roles and Capabilities. From your WordPress® Dashboard, go to: <code>Users -> Authors &amp; Users</code>. You can use the bulk actions to modify User access levels all at once, or click on an individual User account to modify only their specific access level. If you want to temporarily demote a user so they cannot access membership priveledges, set their Role to Subscriber. When you\'re ready to give them their membership priviledges back, change their Role back to one of the s2Member levels.</p>' . "\n";
64
+ echo '<p>All financial details, such as pricing, trial periods, subscription lengths, refunds, and other customer service issues; should be handled by YOU, through your PayPal® account, and NOT through WordPress®. Feel free to modify your Users\' Subscriptions via PayPal® as often as you like. s2Member will be notified through the PayPal® IPN service behind the scenes automatically. For example... If you log into PayPal® and cancel a User\'s paid Subscription, s2Member will be notified by PayPal® behind the scenes, and s2Member will remove their membership priviledges at the correct point in time.</p>' . "\n";
65
+ echo '<p>That being said, if you log into your WordPress® Dashboard and delete a User account, you will still need to log into PayPal® and cancel the billing for the account you deleted. In other words, s2Member can be notified automatically about actions you take inside PayPal\'s interface, but PayPal® CANNOT be notified of actions you take inside your WordPress® Dashboard. At least, not in an automated fashion, as that would create a security issue for PayPal® users. So... automation works seamlessly from PayPal® -> to s2Member, but NOT the other way around.</p>' . "\n";
66
+ echo '</div>' . "\n";
67
+ /**/
68
+ echo '<div class="ws-menu-page-hr ws-plugin--s2member-subscription-modification-section-hr"></div>' . "\n";
69
+ /**/
70
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-subscription-modification-section">' . "\n";
71
+ echo '<h3>Giving Members The Ability To Modify Their Own Subscription</h3>' . "\n";
72
+ echo '<p>Using the PayPal® Subscription Buttons that were generated for you by s2Member, look for this input variable ( <code>modify=0</code> ) and change that to ( <code>modify=2</code> ). Now you can simply provide your Subscription Modification Buttons to existing Members wherever you feel they would be appropriate on your site. We suggest placing these on the Login Welcome Page that you create in WordPress®, that way they\'re not available to the general public, only to Members who are logged in. When an existing Member clicks one of these Subscription Modification Buttons, they\'ll be taken to PayPal® just like they would if they were setting up a new account. But, once they actually get logged in over at PayPal®, the flow of events that occur next, will be slightly different than they would be normally. The Subscription Modification Buttons cause the PayPal® system to react differently.</p>' . "\n";
73
+ echo '<p>When you send a Member to PayPal® using a Subscription Modification Button, instead of being able to signup for a new membership, PayPal® will provide them with the ability to upgrade and/or downgrade their existing membership with you, by allowing them to switch to the one that was specified in the Subscription Modification Button. PayPal® handles this nicely, and you\'ll be happy to know that s2Member has been pre-configured to deal with this scenario as well, so that everything remains automated. Their Membership Access Level will either be promoted or demoted based on the actions they took at PayPal® during the modification process. Once a user completes their Subscription Modification at PayPal®, they\'ll be brought back to their Login Welcome Page, instead of to the registration screen.</p>' . "\n";
74
+ echo '</div>' . "\n";
75
+ /**/
76
+ echo '<div class="ws-menu-page-hr ws-plugin--s2member-subscription-modification-section-hr"></div>' . "\n";
77
+ /**/
78
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-subscription-modification-section">' . "\n";
79
+ echo '<h3>Unfortunately, The <code>modify=2</code> Approach, Does NOT Always Work Well</h3>' . "\n";
80
+ echo '<p>There are a few circumstances when this will NOT work using the ( <code>modify=2</code> ) solution described above. For example, if you offer your visitors a subscription option that does NOT recur, then PayPal® will not allow them to modify to a different plan that you offer, because there is no recurring payment associated with the existing subscription they have with you. Another example is when you have a Member who WAS setup to recur, but their subscription has expired or been cancelled; so it is no longer recurring. In other words, PayPal® will ONLY play nice on the ( <code>modify=2</code> ) approach, if the existing subscription ( the one that needs to be modified ) is still active and setup to recur. Luckily, this is usually not a problem, because in most cases a modification is being requested to adjust a monthly or yearly fee, not to stop or start anything.</p>' . "\n";
81
+ echo '<p>In those rare cases when you need to send an existing Customer over to PayPal® and have them signup for a new subscription, without forcing them to re-register for a new account afterward, you can add the following two variables to your Button Code. Add ( <code>on0 = "Update Subscription ID"</code> ), and set ( <code>os0 = "[Their existing Subscription ID]"</code> ). Adding these two additional input variables will allow s2Member to work seamlessly with PayPal® after they signup. Instead of asking them to re-register for a new account, s2Member will update their existing account and provide responses similar to what you would see using the ( <code>modify=2</code> ) approach. You can use the s2Member Constants in PHP to access the current Members\'s Subscription ID. We\'ve provided an example below.</p>' . "\n";
82
+ echo '<p><strong>S2MEMBER_CURRENT_USER_SUBSCR_ID</strong> = their existing Subscription ID</p>' . "\n";
83
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/current_user_subscr_id.php"), true) . '</p>' . "\n";
84
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
85
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/mod-samps.php"), true) . '</p>' . "\n";
86
+ echo '</div>' . "\n";
87
+ /**/
88
+ echo '<div class="ws-menu-page-hr ws-plugin--s2member-subscription-modification-section-hr"></div>' . "\n";
89
+ /**/
90
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-subscription-modification-section">' . "\n";
91
+ echo '<h3>Upgrading Free Subscribers To Paid Members ( same technique )</h3>' . "\n";
92
+ echo '<p>If you\'ve allowed Users to signup for free <em><code>( see: s2Member->General Options->Login Welcome Page->Free Subscribers )</code></em>, and now you want to send an existing Free Subscriber over to PayPal® and have them signup for a paid Membership; without forcing them to re-register for a new account afterward; you can add the following two variables to your Button Code. Add ( <code>on0 = "Update Subscriber ID"</code> ), and set ( <code>os0 = "[Their existing Subscriber ID]"</code> ). Adding these two additional input variables will allow s2Member to work seamlessly with PayPal® after they signup. Instead of asking them to re-register for a new account, s2Member will update their existing account and provide responses similar to what you would see using the ( <code>modify=2</code> ) approach. You can use the s2Member Constants in PHP to access the current User\'s Subscriber ID. We\'ve provided an example below.</p>' . "\n";
93
+ echo '<p><strong>S2MEMBER_CURRENT_USER_SUBSCR_ID</strong> = their existing Subscriber ID</p>' . "\n";
94
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/current_user_subscr_id.php"), true) . '</p>' . "\n";
95
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
96
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/s2m-samps.php"), true) . '</p>' . "\n";
97
+ echo '</div>' . "\n";
98
+ /**/
99
+ echo '</div>' . "\n";
100
+ /**/
101
+ echo '</td>' . "\n";
102
+ /**/
103
+ echo '<td class="ws-menu-page-table-r">' . "\n";
104
+ /**/
105
+ echo ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["menu-r"]["tools"]) ? '<div class="ws-menu-page-tools"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-tools.png" alt="." /></div>' . "\n" : '';
106
+ /**/
107
+ echo ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["menu-r"]["tips"]) ? '<div class="ws-menu-page-tips"><a href="' . ws_plugin__s2member_parse_readme_value ("Customization URI") . '"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-tips.png" alt="." /></a></div>' . "\n" : '';
108
+ /**/
109
+ echo ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["menu-r"]["donations"]) ? '<div class="ws-menu-page-donations"><a href="' . ws_plugin__s2member_parse_readme_value ("Donate link") . '"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-donations.jpg" alt="." /></a></div>' . "\n" : '';
110
+ /**/
111
+ echo '</td>' . "\n";
112
+ /**/
113
+ echo '</tr>' . "\n";
114
+ echo '</tbody>' . "\n";
115
+ echo '</table>' . "\n";
116
+ /**/
117
+ echo '</div>' . "\n";
118
+ ?>
includes/menu-pages/index.php ADDED
File without changes
includes/menu-pages/info.inc.php ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ s2Member Info page.
18
+ */
19
+ echo '<div class="wrap ws-menu-page">' . "\n";
20
+ /**/
21
+ echo '<div id="icon-plugins" class="icon32"><br /></div>' . "\n";
22
+ echo '<h2><div>Developed by <a href="' . ws_plugin__s2member_parse_readme_value("Plugin URI") . '"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-light.png" alt="." /></a></div>s2Member Information</h2>' . "\n";
23
+ /**/
24
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
25
+ /**/
26
+ echo '<table class="ws-menu-page-table">' . "\n";
27
+ echo '<tbody class="ws-menu-page-table-tbody">' . "\n";
28
+ echo '<tr class="ws-menu-page-table-tr">' . "\n";
29
+ echo '<td class="ws-menu-page-table-l">' . "\n";
30
+ /**/
31
+ echo '<img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-icon.png" class="ws-menu-page-brand-icon" alt="." />' . "\n";
32
+ /**/
33
+ echo '<a href="' . ws_plugin__s2member_parse_readme_value("Plugin URI") . '?check_ver=' . urlencode(ws_plugin__s2member_parse_readme_value("Version")) . '"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-updates.png" class="ws-menu-page-brand-updates" alt="." /></a>' . "\n";
34
+ /**/
35
+ echo '<div class="ws-menu-page-readme">' . "\n";
36
+ echo ws_plugin__s2member_parse_readme() . "\n";
37
+ echo '</div>' . "\n";
38
+ /**/
39
+ echo '</td>' . "\n";
40
+ /**/
41
+ echo '<td class="ws-menu-page-table-r">' . "\n";
42
+ /**/
43
+ echo ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["menu-r"]["tools"]) ? '<div class="ws-menu-page-tools"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-tools.png" alt="." /></div>' . "\n" : '';
44
+ /**/
45
+ echo ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["menu-r"]["tips"]) ? '<div class="ws-menu-page-tips"><a href="' . ws_plugin__s2member_parse_readme_value("Customization URI") . '"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-tips.png" alt="." /></a></div>' . "\n" : '';
46
+ /**/
47
+ echo ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["menu-r"]["donations"]) ? '<div class="ws-menu-page-donations"><a href="' . ws_plugin__s2member_parse_readme_value("Donate link") . '"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-donations.jpg" alt="." /></a></div>' . "\n" : '';
48
+ /**/
49
+ echo '</td>' . "\n";
50
+ /**/
51
+ echo '</tr>' . "\n";
52
+ echo '</tbody>' . "\n";
53
+ echo '</table>' . "\n";
54
+ /**/
55
+ echo '</div>' . "\n";
56
+ ?>
includes/menu-pages/menu-pages.css ADDED
@@ -0,0 +1,458 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ Copyright: © 2009 WebSharks, Inc. ( coded in the USA )
3
+ <mailto:support@websharks-inc.com> <http://www.websharks-inc.com/>
4
+
5
+ Released under the terms of the GNU General Public License.
6
+ You should have received a copy of the GNU General Public License,
7
+ along with this software. In the main directory, see: /licensing/
8
+ If not, see: <http://www.gnu.org/licenses/>.
9
+ */
10
+ /*
11
+ These CSS selectors address common layout styles.
12
+ */
13
+ div.ws-menu-page
14
+ {
15
+ clear: both;
16
+ min-width: 800px;
17
+ margin-bottom: 20px;
18
+ background: url('<?php echo $i; ?>/brand-bg.png') no-repeat top right;
19
+ }
20
+ div.ws-menu-page > h2
21
+ {
22
+ padding-right: 0;
23
+ }
24
+ div.ws-menu-page > h2 > div
25
+ {
26
+ float: right;
27
+ font-size: 80%;
28
+ margin: 0 0 0 25px;
29
+ }
30
+ div.ws-menu-page > h2 > div > a > img
31
+ {
32
+ border: 0px;
33
+ width: 132px;
34
+ height: 35px;
35
+ margin: 0 0 0 10px;
36
+ vertical-align: middle;
37
+ }
38
+ div.ws-menu-page .ws-menu-page-right
39
+ {
40
+ float: right;
41
+ margin-left: 25px;
42
+ }
43
+ div.ws-menu-page .ws-menu-page-left
44
+ {
45
+ float: left;
46
+ margin-right: 25px;
47
+ }
48
+ div.ws-menu-page .ws-menu-page-center
49
+ {
50
+ display: block;
51
+ margin-left: auto;
52
+ margin-right: auto;
53
+ }
54
+ div.ws-menu-page div.ws-menu-page-hr
55
+ {
56
+ height: 1px;
57
+ line-height: 1px;
58
+ background: #DDDDDD;
59
+ margin: 20px 0 20px 0;
60
+ }
61
+ div.ws-menu-page .ws-menu-page-hilite
62
+ {
63
+ font-size: 102%;
64
+ background: #FFFEEB;
65
+ }
66
+ div.ws-menu-page .ws-menu-page-error
67
+ {
68
+ color: #CC0000;
69
+ }
70
+ div.ws-menu-page .ws-menu-page-error-hilite
71
+ {
72
+ color: #FFFFFF;
73
+ background: #FF0000;
74
+ }
75
+ div.ws-menu-page img.ws-menu-page-img-16
76
+ {
77
+ border: 0;
78
+ width: 16px;
79
+ height: 16px;
80
+ }
81
+ div.ws-menu-page img.ws-menu-page-img-24
82
+ {
83
+ border: 0;
84
+ width: 24px;
85
+ height: 24px;
86
+ }
87
+ div.ws-menu-page img.ws-menu-page-img-32
88
+ {
89
+ border: 0;
90
+ width: 32px;
91
+ height: 32px;
92
+ }
93
+ div.ws-menu-page img.ws-menu-page-img-48
94
+ {
95
+ border: 0;
96
+ width: 48px;
97
+ height: 48px;
98
+ }
99
+ div.ws-menu-page img.ws-menu-page-img-64
100
+ {
101
+ border: 0;
102
+ width: 64px;
103
+ height: 64px;
104
+ }
105
+ div.ws-menu-page img.ws-menu-page-img-128
106
+ {
107
+ border: 0;
108
+ width: 128px;
109
+ height: 128px;
110
+ }
111
+ div.ws-menu-page img.ws-menu-page-img-200
112
+ {
113
+ border: 0;
114
+ width: 200px;
115
+ height: 200px;
116
+ }
117
+ div.ws-menu-page img.ws-menu-page-img-256
118
+ {
119
+ border: 0;
120
+ width: 256px;
121
+ height: 256px;
122
+ }
123
+ div.ws-menu-page img.ws-menu-page-img-200-auto
124
+ {
125
+ border: 0;
126
+ width: 200px;
127
+ height: auto;
128
+ }
129
+ div.ws-menu-page img.ws-menu-page-img-256-auto
130
+ {
131
+ border: 0;
132
+ width: 256px;
133
+ height: auto;
134
+ }
135
+ /*
136
+ Specifically for the main layout table.
137
+ These CSS selectors address common layout styles.
138
+ */
139
+ div.ws-menu-page > table.ws-menu-page-table
140
+ {
141
+ border: 0;
142
+ width: 100%;
143
+ }
144
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr
145
+ {
146
+ vertical-align: top;
147
+ }
148
+ /*
149
+ Specifically for the main content area on the left side.
150
+ These CSS selectors address common layout styles.
151
+ */
152
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l
153
+ {
154
+ padding: 0;
155
+ width: 100%;
156
+ }
157
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l img.ws-menu-page-brand-icon
158
+ {
159
+ border: 0px;
160
+ float: right;
161
+ width: 128px;
162
+ height: 128px;
163
+ margin: 0 0 0 25px;
164
+ vertical-align: middle;
165
+ }
166
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l img.ws-menu-page-brand-updates
167
+ {
168
+ border: 0px;
169
+ float: right;
170
+ width: 155px;
171
+ height: 40px;
172
+ margin: 0 -153px 0 25px;
173
+ vertical-align: middle;
174
+ }
175
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l p.submit
176
+ {
177
+ margin: 0;
178
+ padding: 0;
179
+ }
180
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l a[rel = "xlink"]
181
+ {
182
+ padding-right: 18px;
183
+ background: url('<?php echo $i; ?>/brand-xlink.png') no-repeat center right;
184
+ }
185
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l div.ws-menu-page-groups-show,
186
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l div.ws-menu-page-groups-hide
187
+ {
188
+ float: right;
189
+ color: #333333;
190
+ padding: 10px;
191
+ font-size: 220%;
192
+ cursor: pointer;
193
+ font-weight: bold;
194
+ background: #FFFFFF;
195
+ margin: 0 0 0 30px;
196
+ font-family: monospace;
197
+ border: 1px solid #666666;
198
+ -moz-border-radius: 5px;
199
+ -webkit-border-radius: 5px;
200
+ border-radius: 5px;
201
+ -moz-user-select: none;
202
+ -webkit-user-select: none;
203
+ user-select: none;
204
+ }
205
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l div.ws-menu-page-groups-hide
206
+ {
207
+ color: #999999;
208
+ border-color: #999999;
209
+ }
210
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l div.ws-menu-page-group-header
211
+ {
212
+ color: #666666;
213
+ padding: 10px;
214
+ font-size: 145%;
215
+ cursor: pointer;
216
+ position: relative;
217
+ background: #FFFFFF;
218
+ margin: 30px 0 30px 0;
219
+ border: 1px solid #CCCCCC;
220
+ -moz-border-radius: 5px;
221
+ -webkit-border-radius: 5px;
222
+ border-radius: 5px;
223
+ font-family: 'Georgia', serif;
224
+ vertical-align: middle;
225
+ -moz-user-select: none;
226
+ -webkit-user-select: none;
227
+ user-select: none;
228
+ }
229
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l div.ws-menu-page-group-header > ins
230
+ {
231
+ width: 22px;
232
+ height: 22px;
233
+ color: #CCCCCC;
234
+ font-size: 17px;
235
+ line-height: 22px;
236
+ font-weight: bold;
237
+ text-align: center;
238
+ margin: -2px 10px 0 0;
239
+ background: #666666;
240
+ text-decoration: none;
241
+ font-family: monospace;
242
+ vertical-align: middle;
243
+ border: 1px solid transparent;
244
+ -moz-border-radius: 5px;
245
+ -webkit-border-radius: 5px;
246
+ border-radius: 5px;
247
+ display: inline-block;
248
+ zoom: 1
249
+ !ie<8;
250
+ display: inline
251
+ !ie<8;
252
+ margin-top: 0
253
+ !ie<8;
254
+ }
255
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l div.ws-menu-page-group-header:hover,
256
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l div.ws-menu-page-group-header.open
257
+ {
258
+ color: #164A61;
259
+ border-color: #666666;
260
+ }
261
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l div.ws-menu-page-group-header:hover > ins,
262
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l div.ws-menu-page-group-header.open > ins
263
+ {
264
+ color: #FFFFFF;
265
+ background: #164A61;
266
+ }
267
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l div.ws-menu-page-group
268
+ {
269
+ display: none;
270
+ margin: -35px 5px 0 5px;
271
+ padding: 20px 10px 10px 10px;
272
+ border: 1px solid #CCCCCC;
273
+ -moz-border-radius: 5px;
274
+ -webkit-border-radius: 5px;
275
+ border-radius: 5px;
276
+ background: #FFFFFF url('<?php echo $i; ?>/brand-gradient-bg.png') repeat-x;
277
+ }
278
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l div.ws-menu-page-group > div.ws-menu-page-hr
279
+ {
280
+ background: #666666;
281
+ margin: 15px 0 15px 0;
282
+ }
283
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l div.ws-menu-page-section > table.form-table > tbody > tr
284
+ {
285
+ vertical-align: top;
286
+ }
287
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l div.ws-menu-page-section > table.form-table > tbody > tr > th
288
+ {
289
+ width: auto;
290
+ color: #164A61;
291
+ padding-bottom: 0;
292
+ }
293
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l div.ws-menu-page-group > div.ws-menu-page-section > table.form-table > tbody > tr > th
294
+ {
295
+ padding-left: 0;
296
+ }
297
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l div.ws-menu-page-section > table.form-table > tbody > tr > th.ws-menu-page-th-side
298
+ {
299
+ width: 200px;
300
+ }
301
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l div.ws-menu-page-section > table.form-table > tbody > tr > td
302
+ {
303
+ width: auto;
304
+ }
305
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l div.ws-menu-page-group > div.ws-menu-page-section > table.form-table > tbody > tr > td
306
+ {
307
+ padding-left: 0;
308
+ }
309
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l div.ws-menu-page-section > table.form-table > tbody > tr > td > input[type = "text"]
310
+ {
311
+ width: 99%;
312
+ }
313
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l div.ws-menu-page-section > table.form-table > tbody > tr > td > textarea
314
+ {
315
+ width: 99%;
316
+ font-family: 'Courier New', monospace;
317
+ }
318
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l div.ws-menu-page-section > table.form-table > tbody > tr > td > select
319
+ {
320
+ width: 99%;
321
+ }
322
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l div.ws-menu-page-section > table.form-table > tbody > tr > td > ol
323
+ {
324
+ margin: 10px 0 10px 20px;
325
+ list-style: decimal outside;
326
+ }
327
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l div.ws-menu-page-section > table.form-table > tbody > tr > td > ul
328
+ {
329
+ margin: 10px 0 10px 20px;
330
+ list-style: disc outside;
331
+ }
332
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l div.ws-menu-page-section > table.form-table > tbody > tr > td > input.ws-menu-page-media-btn
333
+ {
334
+ float: left;
335
+ margin: 5px 25px 0 0;
336
+ }
337
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l div.ws-menu-page-section > table.form-table > tbody > tr > td > div.ws-menu-page-scrollbox
338
+ {
339
+ margin: 1px;
340
+ padding: 5px;
341
+ height: 150px;
342
+ overflow-y: scroll;
343
+ overflow-x: visible;
344
+ background: #FFFFFF;
345
+ border: 1px solid #CCCCCC;
346
+ -moz-border-radius: 4px;
347
+ -webkit-border-radius: 4px;
348
+ border-radius: 4px;
349
+ }
350
+ /*
351
+ Specifically for the main content area on the left side.
352
+ Specifically for info pages with readme files.
353
+ These CSS selectors address common layout styles.
354
+ */
355
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l > div.ws-menu-page-readme > div.readme > div.section
356
+ {
357
+ margin: 0 0 20px 0;
358
+ padding: 0 0 20px 0;
359
+ border: 0 solid #DDDDDD;
360
+ border-width: 0 0 1px 0;
361
+ }
362
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l > div.ws-menu-page-readme > div.readme > div.section > h2
363
+ {
364
+ margin-top: 0;
365
+ padding-top: 0;
366
+ font-size: 150%;
367
+ }
368
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l > div.ws-menu-page-readme > div.readme > div.section > div.content ul
369
+ {
370
+ padding: 0;
371
+ margin: 10px 0 0 25px;
372
+ list-style: disc outside;
373
+ }
374
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l > div.ws-menu-page-readme > div.readme > div.section > div.content ol
375
+ {
376
+ padding: 0;
377
+ margin: 10px 0 0 25px;
378
+ list-style: decimal outside;
379
+ }
380
+ /*
381
+ Specifically for the main content area on the left side.
382
+ Specifically for pages with a FeedBurner block.
383
+ These CSS selectors address common layout styles.
384
+ */
385
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l > div.feedburnerFeedBlock
386
+ {
387
+ margin: 0 0 20px 0;
388
+ }
389
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l > div.feedburnerFeedBlock > ul > li
390
+ {
391
+ margin: 25px 0 0 0;
392
+ padding: 0 0 20px 0;
393
+ border: 0 solid #DDDDDD;
394
+ border-width: 0 0 1px 0;
395
+ }
396
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l > div.feedburnerFeedBlock > ul > li:first-child
397
+ {
398
+ margin-top: 0;
399
+ }
400
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l > div.feedburnerFeedBlock > ul > li > span.headline
401
+ {
402
+ font-size: 150%;
403
+ font-family: 'Georgia', serif;
404
+ }
405
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l > div.feedburnerFeedBlock > ul > li > p.date
406
+ {
407
+ font-size: 130%;
408
+ font-family: 'Georgia', serif;
409
+ }
410
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l > div.feedburnerFeedBlock > ul > li > div > div.feedflare
411
+ {
412
+ margin: 10px 0 0 0;
413
+ }
414
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-l > div.feedburnerFeedBlock > p.fbsubscribelink
415
+ {
416
+ margin: 25px 0 0 0;
417
+ }
418
+ /*
419
+ Specifically for the right sidebar panel.
420
+ These CSS selectors address common layout styles.
421
+ */
422
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-r
423
+ {
424
+ padding: 0;
425
+ text-align: right;
426
+ }
427
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-r > div.ws-menu-page-tools
428
+ {
429
+ margin: 0 0 25px 25px;
430
+ }
431
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-r > div.ws-menu-page-tools > img
432
+ {
433
+ width: 200px;
434
+ height: 200px;
435
+ }
436
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-r > div.ws-menu-page-tips
437
+ {
438
+ margin: 0 0 10px 25px;
439
+ }
440
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-r > div.ws-menu-page-tips > a > img
441
+ {
442
+ width: 200px;
443
+ height: 150px;
444
+ }
445
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-r > div.ws-menu-page-donations
446
+ {
447
+ margin: 0 0 10px 25px;
448
+ }
449
+ div.ws-menu-page > table.ws-menu-page-table > tbody > tr > td.ws-menu-page-table-r > div.ws-menu-page-donations > a > img
450
+ {
451
+ width: 200px;
452
+ height: 400px;
453
+ border: 1px solid #333333;
454
+ }
455
+ /*
456
+ These CSS selectors are specific to this software.
457
+ */
458
+ /* None currently. */
includes/menu-pages/menu-pages.js ADDED
@@ -0,0 +1,217 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ Copyright: © 2009 WebSharks, Inc. ( coded in the USA )
3
+ <mailto:support@websharks-inc.com> <http://www.websharks-inc.com/>
4
+
5
+ Released under the terms of the GNU General Public License.
6
+ You should have received a copy of the GNU General Public License,
7
+ along with this software. In the main directory, see: /licensing/
8
+ If not, see: <http://www.gnu.org/licenses/>.
9
+ */
10
+ jQuery(document).ready (function($)
11
+ {
12
+ /*
13
+ These routines address common layout styles for menu pages.
14
+ */
15
+ $('div.ws-menu-page-group').each (function(index)
16
+ {
17
+ var ins = '<ins>+</ins>', group = $(this), title = group.attr ('title');
18
+ /**/
19
+ var header = $('<div class="ws-menu-page-group-header">' + ins + title + '</div>');
20
+ /**/
21
+ header.css ({'z-index': 100 - index}); /* Stack them sequentially, top to bottom. */
22
+ /**/
23
+ header.insertBefore (group), group.hide (), header.click (function()
24
+ {
25
+ var ins = $('ins', this), group = $(this).next ();
26
+ /**/
27
+ if (group.css ('display') === 'none')
28
+ {
29
+ $(this).addClass ('open'), ins.html ('-'), group.show ();
30
+ }
31
+ else
32
+ {
33
+ $(this).removeClass ('open'), ins.html ('+'), group.hide ();
34
+ }
35
+ /**/
36
+ return false;
37
+ });
38
+ if (index === 0) /* These are the buttons for showing/hiding all groups. */
39
+ {
40
+ $('<div class="ws-menu-page-groups-show">+</div>').insertBefore (header).click (function()
41
+ {
42
+ $('div.ws-menu-page-group-header').each (function()
43
+ {
44
+ var ins = $('ins', this), group = $(this).next ();
45
+ /**/
46
+ $(this).addClass ('open'), ins.html ('-'), group.show ();
47
+ /**/
48
+ return;
49
+ });
50
+ /**/
51
+ return false;
52
+ });
53
+ $('<div class="ws-menu-page-groups-hide">-</div>').insertBefore (header).click (function()
54
+ {
55
+ $('div.ws-menu-page-group-header').each (function()
56
+ {
57
+ var ins = $('ins', this), group = $(this).next ();
58
+ /**/
59
+ $(this).removeClass ('open'), ins.html ('+'), group.hide ();
60
+ /**/
61
+ return;
62
+ });
63
+ /**/
64
+ return false;
65
+ });
66
+ }
67
+ /**/
68
+ if (group.attr ('default-state') === 'open')
69
+ header.trigger ('click');
70
+ /**/
71
+ return;
72
+ });
73
+ /**/
74
+ $('div.ws-menu-page-hr:first').css ({'margin-top': '10px', 'margin-bottom': '20px'});
75
+ /**/
76
+ $('div.ws-menu-page-section:first > h3').css ({'margin-top': '0'});
77
+ /**/
78
+ $('div.ws-menu-page-group > div.ws-menu-page-section:first-child > h3').css ({'margin-top': '0'});
79
+ $('div.ws-menu-page-group-header:first').css ({'margin-top': '0', 'margin-right': '140px'});
80
+ $('div.ws-menu-page-group:first').css ({'margin-right': '145px'});
81
+ /**/
82
+ $('div.ws-menu-page-readme > div.readme > div.section:last-child').css ({'border-bottom-width': '0'});
83
+ /**/
84
+ $('input.ws-menu-page-media-btn').filter (function() /* Only those that have a rel attribute. */
85
+ {
86
+ return ($(this).attr ('rel')) ? true : false; /* Must have rel targeting an input id. */
87
+ })/**/
88
+ .click (function() /* Attach click events to media buttons with send_to_editor(). */
89
+ {
90
+ $this = $(this), window.send_to_editor = function(html)
91
+ {
92
+ var $inp, $txt; /* Looking for input|textarea. */
93
+ /**/
94
+ if (($inp = $('input#' + $this.attr ('rel'))).length > 0)
95
+ {
96
+ var oBg = $inp.css ('background-color'), src = $.trim ($(html).attr ('src'));
97
+ src = (!src) ? $.trim ($('img', html).attr ('src')) : src;
98
+ /**/
99
+ $inp.val (src), $inp.css ({'background-color': '#FFFFCC'}), setTimeout(function()
100
+ {
101
+ $inp.css ({'background-color': oBg});
102
+ }, 2000);
103
+ /**/
104
+ tb_remove ();
105
+ /**/
106
+ return;
107
+ }
108
+ else if (($txt = $('textarea#' + $this.attr ('rel'))).length > 0)
109
+ {
110
+ var oBg = $txt.css ('background-color'), src = $.trim ($(html).attr ('src'));
111
+ src = (!src) ? $.trim ($('img', html).attr ('src')) : src;
112
+ /**/
113
+ $txt.val ($.trim ($txt.val ()) + '\n' + src), $txt.css ({'background-color': '#FFFFCC'}), setTimeout(function()
114
+ {
115
+ $txt.css ({'background-color': oBg});
116
+ }, 2000);
117
+ /**/
118
+ tb_remove ();
119
+ /**/
120
+ return;
121
+ }
122
+ };
123
+ /**/
124
+ tb_show('', './media-upload.php?type=image&TB_iframe=true');
125
+ /**/
126
+ return false;
127
+ });
128
+ /*
129
+ These routines are all specific to this software.
130
+ */
131
+ $('form#ws-plugin--s2member-buttons-form select#ws-plugin--s2member-level1-term').change (function()
132
+ {
133
+ var trialDisabled = ($(this).val ().split ('-')[1].replace (/[^A-Z]/g, '') === 'L') ? 'disabled' : '';
134
+ $('p#ws-plugin--s2member-level1-trial-line').css ('display', (trialDisabled ? 'none' : ''));
135
+ $('span#ws-plugin--s2member-level1-trial-then').css ('display', (trialDisabled ? 'none' : ''));
136
+ });
137
+ /**/
138
+ $('form#ws-plugin--s2member-buttons-form select#ws-plugin--s2member-level2-term').change (function()
139
+ {
140
+ var trialDisabled = ($(this).val ().split ('-')[1].replace (/[^A-Z]/g, '') === 'L') ? 'disabled' : '';
141
+ $('p#ws-plugin--s2member-level2-trial-line').css ('display', (trialDisabled ? 'none' : ''));
142
+ $('span#ws-plugin--s2member-level2-trial-then').css ('display', (trialDisabled ? 'none' : ''));
143
+ });
144
+ /**/
145
+ $('form#ws-plugin--s2member-buttons-form select#ws-plugin--s2member-level3-term').change (function()
146
+ {
147
+ var trialDisabled = ($(this).val ().split ('-')[1].replace (/[^A-Z]/g, '') === 'L') ? 'disabled' : '';
148
+ $('p#ws-plugin--s2member-level3-trial-line').css ('display', (trialDisabled ? 'none' : ''));
149
+ $('span#ws-plugin--s2member-level3-trial-then').css ('display', (trialDisabled ? 'none' : ''));
150
+ });
151
+ /**/
152
+ $('form#ws-plugin--s2member-buttons-form select#ws-plugin--s2member-level4-term').change (function()
153
+ {
154
+ var trialDisabled = ($(this).val ().split ('-')[1].replace (/[^A-Z]/g, '') === 'L') ? 'disabled' : '';
155
+ $('p#ws-plugin--s2member-level4-trial-line').css ('display', (trialDisabled ? 'none' : ''));
156
+ $('span#ws-plugin--s2member-level4-trial-then').css ('display', (trialDisabled ? 'none' : ''));
157
+ });
158
+ /**/
159
+ ws_plugin__s2member_paypalButtonGenerate = function(level) /* Handles PayPal® Button Generation. */
160
+ {
161
+ var shortCodeTemplate = '[s2Member-PayPal-Button %%attrs%% /]', shortCodeTemplateAttrs = '';
162
+ /**/
163
+ var shortCode = $('#ws-plugin--s2member-level' + level + '-shortcode');
164
+ var code = $('#ws-plugin--s2member-level' + level + '-button');
165
+ /**/
166
+ var trialPeriod = $('#ws-plugin--s2member-level' + level + '-trial-period').val ().replace (/[^0-9]/g, '');
167
+ var trialTerm = $('#ws-plugin--s2member-level' + level + '-trial-term').val ().replace (/[^A-Z]/g, '');
168
+ var regAmount = $('#ws-plugin--s2member-level' + level + '-amount').val ().replace (/[^0-9\.]/g, '');
169
+ var regPeriod = $('#ws-plugin--s2member-level' + level + '-term').val ().split ('-')[0].replace (/[^0-9]/g, '');
170
+ var regTerm = $('#ws-plugin--s2member-level' + level + '-term').val ().split ('-')[1].replace (/[^A-Z]/g, '');
171
+ var regRecur = $('#ws-plugin--s2member-level' + level + '-term').val ().split ('-')[2].replace (/[^0-1]/g, '');
172
+ var pageStyle = $.trim ($('#ws-plugin--s2member-level' + level + '-page-style').val ().replace (/["']/g, ''));
173
+ var currencyCode = $('#ws-plugin--s2member-level' + level + '-currency').val ().replace (/[^A-Z]/g, '');
174
+ trialPeriod = (regTerm === 'L') ? '0' : trialPeriod; /* Lifetime access is NOT compatible w/trials. */
175
+ /**/
176
+ if (trialTerm === 'D' && trialPeriod > 90) /* Some validation on the trial period. Max days: 90. */
177
+ alert('* WARNING: Maximum Free Days is: 90.\nIf you want to offer more than 90 days free, please choose Weeks or Months from the drop-down.'), trialPeriod = 90;
178
+ else if (trialTerm === 'W' && trialPeriod > 52) /* Some validation on the trial period. 52 max. */
179
+ alert('* WARNING: Maximum Free Weeks is: 52.\nIf you want to offer more than 52 weeks free, please choose Months from the drop-down.'), trialPeriod = 52;
180
+ else if (trialTerm === 'M' && trialPeriod > 24) /* Some validation on the trial period. 24 max. */
181
+ alert('* WARNING: Maximum Free Months is: 24.\nIf you want to offer more than 24 months free, please choose Years from the drop-down.'), trialPeriod = 24;
182
+ else if (trialTerm === 'Y' && trialPeriod > 5) /* 5 years max. */
183
+ alert('* WARNING: Maximum Free Years is: 5.'), trialPeriod = 5;
184
+ /**/
185
+ code.val (code.val ().replace (/ \<\!--(\<input type\="hidden" name\="(amount|modify|src|sra|a1|p1|t1|a3|p3|t3)" value\="(.*?)" \/\>)--\>/g, " $1"));
186
+ (parseInt(trialPeriod) <= 0) ? code.val (code.val ().replace (/ (\<input type\="hidden" name\="(a1|p1|t1)" value\="(.*?)" \/\>)/g, " <!--$1-->")) : null;
187
+ (regTerm === 'L') ? code.val (code.val ().replace (/ (\<input type\="hidden" name\="cmd" value\=")(.*?)(" \/\>)/g, " $1_xclick$3")) : null;
188
+ (regTerm === 'L') ? code.val (code.val ().replace (/ (\<input type\="hidden" name\="(modify|src|sra|a1|p1|t1|a3|p3|t3)" value\="(.*?)" \/\>)/g, " <!--$1-->")) : null;
189
+ (regTerm !== 'L') ? code.val (code.val ().replace (/ (\<input type\="hidden" name\="cmd" value\=")(.*?)(" \/\>)/g, " $1_xclick-subscriptions$3")) : null;
190
+ (regTerm !== 'L') ? code.val (code.val ().replace (/ (\<input type\="hidden" name\="amount" value\="(.*?)" \/\>)/g, " <!--$1-->")) : null;
191
+ /**/
192
+ shortCodeTemplateAttrs += 'level="' + level + '" ps="' + pageStyle + '" cc="' + currencyCode + '" on0="" os0="" modify="0" custom="<?php echo $_SERVER["HTTP_HOST"]; ?>"';
193
+ shortCodeTemplateAttrs += ' tp="' + trialPeriod + '" tt="' + trialTerm + '" ra="' + regAmount + '" rp="' + regPeriod + '" rt="' + regTerm + '" rr="' + regRecur + '"';
194
+ shortCode.val (shortCodeTemplate.replace (/%%attrs%%/, shortCodeTemplateAttrs));
195
+ /**/
196
+ code.val (code.val ().replace (/ name\="currency_code" value\="(.*?)"/, ' name="currency_code" value="' + currencyCode + '"'));
197
+ code.val (code.val ().replace (/ name\="amount" value\="(.*?)"/, ' name="amount" value="' + regAmount + '"'));
198
+ code.val (code.val ().replace (/ name\="src" value\="(.*?)"/, ' name="src" value="' + regRecur + '"'));
199
+ code.val (code.val ().replace (/ name\="p1" value\="(.*?)"/, ' name="p1" value="' + trialPeriod + '"'));
200
+ code.val (code.val ().replace (/ name\="t1" value\="(.*?)"/, ' name="t1" value="' + trialTerm + '"'));
201
+ code.val (code.val ().replace (/ name\="a3" value\="(.*?)"/, ' name="a3" value="' + regAmount + '"'));
202
+ code.val (code.val ().replace (/ name\="p3" value\="(.*?)"/, ' name="p3" value="' + regPeriod + '"'));
203
+ code.val (code.val ().replace (/ name\="t3" value\="(.*?)"/, ' name="t3" value="' + regTerm + '"'));
204
+ code.val (code.val ().replace (/ name\="page_style" value\="(.*?)"/, ' name="page_style" value="' + pageStyle + '"'));
205
+ /**/
206
+ $('#ws-plugin--s2member-level' + level + '-button-prev').html (code.val ().replace (/\<form/, '<form target="_blank"'));
207
+ /**/
208
+ alert('Your Codes for Membership Level #' + level + ' have been generated. Please copy/paste the Shortcode Format into your Membership Options Page.');
209
+ /**/
210
+ shortCode.each (function() /* Focus and select the recommended Shortcode. */
211
+ {
212
+ this.focus (), this.select ();
213
+ });
214
+ /**/
215
+ return false;
216
+ };
217
+ });
includes/menu-pages/mod-samps.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
2
+ <input type="hidden" name="business" value="paypal@example.com">
3
+ <input type="hidden" name="cmd" value="_xclick-subscriptions">
4
+ <!-- Instant Payment Notification / Return Details -->
5
+ <input type="hidden" name="notify_url" value="http://www.example.com/?s2member_paypal_notify=1">
6
+ <input type="hidden" name="cancel_return" value="http://www.example.com">
7
+ <input type="hidden" name="return" value="http://www.example.com/?s2member_paypal_return=1">
8
+ <input type="hidden" name="rm" value="2">
9
+ <!-- Identify / Customize 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="www.example.com">
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 2 Upgrade ( $25/mo )">
16
+ <input type="hidden" name="item_number" value="2">
17
+ <!-- Identify / Update An Existing Member After Checkout. -->
18
+ <input type="hidden" name="on0" value="Update Subscription ID">
19
+ <input type="hidden" name="os0" value="<?php echo S2MEMBER_CURRENT_USER_SUBSCR_ID; ?>">
20
+ <!-- Set The Terms Of The New Subscription. -->
21
+ <input type="hidden" name="modify" value="0">
22
+ <input type="hidden" name="src" value="1">
23
+ <input type="hidden" name="sra" value="1">
24
+ <input type="hidden" name="a3" value="25">
25
+ <input type="hidden" name="p3" value="1">
26
+ <input type="hidden" name="t3" value="M">
27
+ <!-- Display The Subscription Button. -->
28
+ <input type="image" alt="PayPal®" style="border:0;" src="https://www.paypal.com/en_GB/i/btn/btn_xpressCheckout.gif">
29
+ </form>
30
+ -------------------------------------------------------------------------------------------------
31
+ SO THE RELEVANT SECTION IN THE EXAMPLE GIVEN ABOVE IS:
32
+ <input type="hidden" name="on0" value="Update Subscription ID">
33
+ <input type="hidden" name="os0" value="<?php echo S2MEMBER_CURRENT_USER_SUBSCR_ID; ?>">
includes/menu-pages/options.inc.php ADDED
@@ -0,0 +1,964 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ General Options page.
18
+ */
19
+ echo '<div class="wrap ws-menu-page">' . "\n";
20
+ /**/
21
+ echo '<div id="icon-plugins" class="icon32"><br /></div>' . "\n";
22
+ echo '<h2><div>Developed by <a href="' . ws_plugin__s2member_parse_readme_value ("Plugin URI") . '"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-light.png" alt="." /></a></div>s2Member General Options</h2>' . "\n";
23
+ /**/
24
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
25
+ /**/
26
+ echo '<table class="ws-menu-page-table">' . "\n";
27
+ echo '<tbody class="ws-menu-page-table-tbody">' . "\n";
28
+ echo '<tr class="ws-menu-page-table-tr">' . "\n";
29
+ echo '<td class="ws-menu-page-table-l">' . "\n";
30
+ /**/
31
+ echo '<form method="post" name="ws_plugin__s2member_options_form" id="ws-plugin--s2member-options-form">' . "\n";
32
+ echo '<input type="hidden" name="ws_plugin__s2member_options_save" id="ws-plugin--s2member-options-save" value="' . esc_attr (wp_create_nonce ("ws-plugin--s2member-options-save")) . '" />' . "\n";
33
+ echo '<input type="hidden" name="ws_plugin__s2member_configured" id="ws-plugin--s2member-configured" value="1" />' . "\n";
34
+ /**/
35
+ echo '<div class="ws-menu-page-group" title="Email Configuration">' . "\n";
36
+ /**/
37
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-email-section">' . "\n";
38
+ echo '<h3>EMail From: ' . esc_html ('"Name" <address>') . '</h3>' . "\n";
39
+ echo '<p>This is the name/address that will appear in outgoing email notifications sent by the s2Member plugin.</p>' . "\n";
40
+ /**/
41
+ echo '<table class="form-table">' . "\n";
42
+ echo '<tbody>' . "\n";
43
+ echo '<tr>' . "\n";
44
+ /**/
45
+ echo '<th>' . "\n";
46
+ echo '<label for="ws-plugin--s2member-reg-email-from-name">' . "\n";
47
+ echo 'EMail From Name:' . "\n";
48
+ echo '</label>' . "\n";
49
+ echo '</th>' . "\n";
50
+ /**/
51
+ echo '</tr>' . "\n";
52
+ echo '<tr>' . "\n";
53
+ /**/
54
+ echo '<td>' . "\n";
55
+ echo '<input type="text" name="ws_plugin__s2member_reg_email_from_name" id="ws-plugin--s2member-reg-email-from-name" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_name"]) . '" /><br />' . "\n";
56
+ echo 'We recommend that you use the name of your site here.' . "\n";
57
+ echo '</td>' . "\n";
58
+ /**/
59
+ echo '</tr>' . "\n";
60
+ echo '<tr>' . "\n";
61
+ /**/
62
+ echo '<th>' . "\n";
63
+ echo '<label for="ws-plugin--s2member-reg-email-from-email">' . "\n";
64
+ echo 'EMail From Address:' . "\n";
65
+ echo '</label>' . "\n";
66
+ echo '</th>' . "\n";
67
+ /**/
68
+ echo '</tr>' . "\n";
69
+ echo '<tr>' . "\n";
70
+ /**/
71
+ echo '<td>' . "\n";
72
+ echo '<input type="text" name="ws_plugin__s2member_reg_email_from_email" id="ws-plugin--s2member-reg-email-from-email" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["reg_email_from_email"]) . '" /><br />' . "\n";
73
+ echo 'We recommend something like: support@your-domain.com.' . "\n";
74
+ echo '</td>' . "\n";
75
+ /**/
76
+ echo '</tr>' . "\n";
77
+ echo '</tbody>' . "\n";
78
+ echo '</table>' . "\n";
79
+ echo '</div>' . "\n";
80
+ /**/
81
+ echo '</div>' . "\n";
82
+ /**/
83
+ echo '<div class="ws-menu-page-group" title="Custom Registration Fields">' . "\n";
84
+ /**/
85
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-custom-reg-fields-section">' . "\n";
86
+ echo '<h3>Custom Registration Fields ( optional, for further custmization )</h3>' . "\n";
87
+ echo '<p>This is a comma delimited list of additional form fields to collect during registration. By default, all of your Custom Fields will remain optional to the User. That is, the User will NOT be required to enter any of these values. If you want specific fields to be *required*, wrap those Custom Fields inside *asterisks*. Some fields are already built-in by default. The defaults are: <code>*Username*, *Email*, *First Name*, *Last Name*</code>. If you need to add other Custom Fields, in addition to these defaults, you can do that here.</p>' . "\n";
88
+ if (defined ("BP_VERSION")) /* Notify the site owner about the conflict with Custom Fields and BuddyPress. */
89
+ echo '<p><em class="ws-menu-page-error">* Custom Registration Fields are NOT applicable with BuddyPress. Instead, use <code>BuddyPress -> Profile Field Setup</code>.</em></p>' . "\n";
90
+ if (!function_exists ("ws_plugin__s2member_generate_password"))
91
+ echo '<p><em class="ws-menu-page-error">* Custom Passwords CANNOT be used with your installation of s2Member. This is due to a minor conflict with another plugin that is using <code>wp_generate_password()</code>. If you really want to allow Custom Passwords during registration, please disable some of your other plugins until this warning goes away.</em></p>' . "\n";
92
+ echo '<table class="form-table">' . "\n";
93
+ echo '<tbody>' . "\n";
94
+ echo '<tr>' . "\n";
95
+ /**/
96
+ echo '<th>' . "\n";
97
+ echo '<label for="ws-plugin--s2member-custom-reg-fields">' . "\n";
98
+ echo 'Custom Registration Fields:' . "\n";
99
+ echo '</label>' . "\n";
100
+ echo '</th>' . "\n";
101
+ /**/
102
+ echo '</tr>' . "\n";
103
+ echo '<tr>' . "\n";
104
+ /**/
105
+ echo '<td>' . "\n";
106
+ echo '<input type="text" name="ws_plugin__s2member_custom_reg_fields" id="ws-plugin--s2member-custom-reg-fields" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"]) . '" /><br />' . "\n";
107
+ echo 'Comma delimited please. <em>Ex: <code>*Company*, *Website URL*, Street Address, City, State, Zip Code, Phone</code></em>' . "\n";
108
+ echo '</td>' . "\n";
109
+ /**/
110
+ echo '</tr>' . "\n";
111
+ echo '<tr>' . "\n";
112
+ /**/
113
+ echo '<th>' . "\n";
114
+ echo '<label for="ws-plugin--s2member-custom-reg-password">' . "\n";
115
+ echo 'Allow Custom Passwords during Registration?' . "\n";
116
+ echo '</label>' . "\n";
117
+ echo '</th>' . "\n";
118
+ /**/
119
+ echo '</tr>' . "\n";
120
+ echo '<tr>' . "\n";
121
+ /**/
122
+ echo '<td>' . "\n";
123
+ echo '<select name="ws_plugin__s2member_custom_reg_password" id="ws-plugin--s2member-custom-reg-password">' . "\n";
124
+ echo '<option value="0"' . ((!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_password"]) ? ' selected="selected"' : '') . '>No ( send auto-generated passwords via email; after registration )</option>' . "\n";
125
+ echo '<option value="1"' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_password"]) ? ' selected="selected"' : '') . '>Yes ( allow members to create their own password during registration )</option>' . "\n";
126
+ echo '</select><br />' . "\n";
127
+ echo 'Auto-generated Passwords are recommended for best security; because, this also serves as a form of email confirmation.' . "\n";
128
+ echo '</td>' . "\n";
129
+ /**/
130
+ echo '</tr>' . "\n";
131
+ echo '</tbody>' . "\n";
132
+ echo '</table>' . "\n";
133
+ echo '</div>' . "\n";
134
+ /**/
135
+ echo '</div>' . "\n";
136
+ /**/
137
+ echo '<div class="ws-menu-page-group" title="Login/Registration Design">' . "\n";
138
+ /**/
139
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-login-registration-section">' . "\n";
140
+ echo '<h3>Login/Registration Page Customization ( required )</h3>' . "\n";
141
+ echo '<p>These settings allow you to customize the user interface for the login / registration pages.</p>' . "\n";
142
+ /**/
143
+ echo '<table class="form-table">' . "\n";
144
+ echo '<tbody>' . "\n";
145
+ echo '<tr>' . "\n";
146
+ /**/
147
+ echo '<th>' . "\n";
148
+ echo '<label for="ws-plugin--s2member-login-reg-background-color">' . "\n";
149
+ echo 'Login / Registration Background Color:' . "\n";
150
+ echo '</label>' . "\n";
151
+ echo '</th>' . "\n";
152
+ /**/
153
+ echo '</tr>' . "\n";
154
+ echo '<tr>' . "\n";
155
+ /**/
156
+ echo '<td>' . "\n";
157
+ echo '<input type="text" name="ws_plugin__s2member_login_reg_background_color" id="ws-plugin--s2member-login-reg-background-color" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_color"]) . '" /><br />' . "\n";
158
+ echo 'Set this to a 6-digit hex color code.' . "\n";
159
+ echo '</td>' . "\n";
160
+ /**/
161
+ echo '</tr>' . "\n";
162
+ echo '<tr>' . "\n";
163
+ /**/
164
+ echo '<th>' . "\n";
165
+ echo '<label for="ws-plugin--s2member-login-reg-background-image">' . "\n";
166
+ echo 'Login / Registration Background Image:' . "\n";
167
+ echo '</label>' . "\n";
168
+ echo '</th>' . "\n";
169
+ /**/
170
+ echo '</tr>' . "\n";
171
+ echo '<tr>' . "\n";
172
+ /**/
173
+ echo '<td>' . "\n";
174
+ echo '<input type="text" name="ws_plugin__s2member_login_reg_background_image" id="ws-plugin--s2member-login-reg-background-image" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_image"]) . '" /><br />' . "\n";
175
+ echo '<input type="button" id="ws-plugin--s2member-login-reg-background-image-media-btn" value="Open Media Library" class="ws-menu-page-media-btn" rel="ws-plugin--s2member-login-reg-background-image" />' . "\n";
176
+ echo 'Set this to the URL of your background image.' . "\n";
177
+ echo '</td>' . "\n";
178
+ /**/
179
+ echo '</tr>' . "\n";
180
+ echo '<tr>' . "\n";
181
+ /**/
182
+ echo '<th>' . "\n";
183
+ echo '<label for="ws-plugin--s2member-login-reg-background-text-color">' . "\n";
184
+ echo 'Login / Registration Background Text Color:' . "\n";
185
+ echo '</label>' . "\n";
186
+ echo '</th>' . "\n";
187
+ /**/
188
+ echo '</tr>' . "\n";
189
+ echo '<tr>' . "\n";
190
+ /**/
191
+ echo '<td>' . "\n";
192
+ echo '<input type="text" name="ws_plugin__s2member_login_reg_background_text_color" id="ws-plugin--s2member-login-reg-background-text-color" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_text_color"]) . '" /><br />' . "\n";
193
+ echo 'Set this to a 6-digit hex color code.' . "\n";
194
+ echo '</td>' . "\n";
195
+ /**/
196
+ echo '</tr>' . "\n";
197
+ echo '<tr>' . "\n";
198
+ /**/
199
+ echo '<th>' . "\n";
200
+ echo '<label for="ws-plugin--s2member-login-reg-background-text-shadow-color">' . "\n";
201
+ echo 'Login / Registration Bg Text Shadow Color:' . "\n";
202
+ echo '</label>' . "\n";
203
+ echo '</th>' . "\n";
204
+ /**/
205
+ echo '</tr>' . "\n";
206
+ echo '<tr>' . "\n";
207
+ /**/
208
+ echo '<td>' . "\n";
209
+ echo '<input type="text" name="ws_plugin__s2member_login_reg_background_text_shadow_color" id="ws-plugin--s2member-login-reg-background-text-shadow-color" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_text_shadow_color"]) . '" /><br />' . "\n";
210
+ echo 'Set this to a 6-digit hex color code.' . "\n";
211
+ echo '</td>' . "\n";
212
+ /**/
213
+ echo '</tr>' . "\n";
214
+ echo '<tr>' . "\n";
215
+ /**/
216
+ echo '<th>' . "\n";
217
+ echo '<label for="ws-plugin--s2member-login-reg-background-box-shadow-color">' . "\n";
218
+ echo 'Login / Registration Bg Box Shadow Color:' . "\n";
219
+ echo '</label>' . "\n";
220
+ echo '</th>' . "\n";
221
+ /**/
222
+ echo '</tr>' . "\n";
223
+ echo '<tr>' . "\n";
224
+ /**/
225
+ echo '<td>' . "\n";
226
+ echo '<input type="text" name="ws_plugin__s2member_login_reg_background_box_shadow_color" id="ws-plugin--s2member-login-reg-background-box-shadow-color" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_background_box_shadow_color"]) . '" /><br />' . "\n";
227
+ echo 'Set this to a 6-digit hex color code.' . "\n";
228
+ echo '</td>' . "\n";
229
+ /**/
230
+ echo '</tr>' . "\n";
231
+ echo '<tr>' . "\n";
232
+ /**/
233
+ echo '<th>' . "\n";
234
+ echo '<label for="ws-plugin--s2member-login-reg-logo-src">' . "\n";
235
+ echo 'Login / Registration Logo Image:' . "\n";
236
+ echo '</label>' . "\n";
237
+ echo '</th>' . "\n";
238
+ /**/
239
+ echo '</tr>' . "\n";
240
+ echo '<tr>' . "\n";
241
+ /**/
242
+ echo '<td>' . "\n";
243
+ echo '<input type="text" name="ws_plugin__s2member_login_reg_logo_src" id="ws-plugin--s2member-login-reg-logo-src" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_src"]) . '" /><br />' . "\n";
244
+ echo '<input type="button" id="ws-plugin--s2member-login-reg-logo-src-media-btn" value="Open Media Library" class="ws-menu-page-media-btn" rel="ws-plugin--s2member-login-reg-logo-src" />' . "\n";
245
+ echo 'Set this to the URL of your logo image.' . "\n";
246
+ echo '</td>' . "\n";
247
+ /**/
248
+ echo '</tr>' . "\n";
249
+ echo '<tr>' . "\n";
250
+ /**/
251
+ echo '<th>' . "\n";
252
+ echo '<label for="ws-plugin--s2member-login-reg-logo-src-width">' . "\n";
253
+ echo 'Login / Registration Logo Image Width:' . "\n";
254
+ echo '</label>' . "\n";
255
+ echo '</th>' . "\n";
256
+ /**/
257
+ echo '</tr>' . "\n";
258
+ echo '<tr>' . "\n";
259
+ /**/
260
+ echo '<td>' . "\n";
261
+ echo '<input type="text" name="ws_plugin__s2member_login_reg_logo_src_width" id="ws-plugin--s2member-login-reg-logo-src-width" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_src_width"]) . '" /><br />' . "\n";
262
+ echo 'Set this to pixel width of your logo image. <em>* This also affects the overall width of your login/registration forms. If you want wider form fields, use a wider logo.</em>' . "\n";
263
+ echo '</td>' . "\n";
264
+ /**/
265
+ echo '</tr>' . "\n";
266
+ echo '<tr>' . "\n";
267
+ /**/
268
+ echo '<th>' . "\n";
269
+ echo '<label for="ws-plugin--s2member-login-reg-logo-src-height">' . "\n";
270
+ echo 'Login / Registration Logo Image Height:' . "\n";
271
+ echo '</label>' . "\n";
272
+ echo '</th>' . "\n";
273
+ /**/
274
+ echo '</tr>' . "\n";
275
+ echo '<tr>' . "\n";
276
+ /**/
277
+ echo '<td>' . "\n";
278
+ echo '<input type="text" name="ws_plugin__s2member_login_reg_logo_src_height" id="ws-plugin--s2member-login-reg-logo-src-height" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_src_height"]) . '" /><br />' . "\n";
279
+ echo 'Set this to pixel height of your logo image.' . "\n";
280
+ echo '</td>' . "\n";
281
+ /**/
282
+ echo '</tr>' . "\n";
283
+ echo '<tr>' . "\n";
284
+ /**/
285
+ echo '<th>' . "\n";
286
+ echo '<label for="ws-plugin--s2member-login-reg-logo-url">' . "\n";
287
+ echo 'Login / Registration Logo Image Click URL:' . "\n";
288
+ echo '</label>' . "\n";
289
+ echo '</th>' . "\n";
290
+ /**/
291
+ echo '</tr>' . "\n";
292
+ echo '<tr>' . "\n";
293
+ /**/
294
+ echo '<td>' . "\n";
295
+ echo '<input type="text" name="ws_plugin__s2member_login_reg_logo_url" id="ws-plugin--s2member-login-reg-logo-url" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_url"]) . '" /><br />' . "\n";
296
+ echo 'Set this to click URL for your logo image.' . "\n";
297
+ echo '</td>' . "\n";
298
+ /**/
299
+ echo '</tr>' . "\n";
300
+ echo '<tr>' . "\n";
301
+ /**/
302
+ echo '<th>' . "\n";
303
+ echo '<label for="ws-plugin--s2member-login-reg-logo-title">' . "\n";
304
+ echo 'Login / Registration Logo Image Title:' . "\n";
305
+ echo '</label>' . "\n";
306
+ echo '</th>' . "\n";
307
+ /**/
308
+ echo '</tr>' . "\n";
309
+ echo '<tr>' . "\n";
310
+ /**/
311
+ echo '<td>' . "\n";
312
+ echo '<input type="text" name="ws_plugin__s2member_login_reg_logo_title" id="ws-plugin--s2member-login-reg-logo-title" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["login_reg_logo_title"]) . '" /><br />' . "\n";
313
+ echo 'Used as the title attribute for your logo image.' . "\n";
314
+ echo '</td>' . "\n";
315
+ /**/
316
+ echo '</tr>' . "\n";
317
+ echo '</tbody>' . "\n";
318
+ echo '</table>' . "\n";
319
+ echo '</div>' . "\n";
320
+ /**/
321
+ echo '</div>' . "\n";
322
+ /**/
323
+ echo '<div class="ws-menu-page-group" title="Login Welcome Page">' . "\n";
324
+ /**/
325
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-login-welcome-page-section">' . "\n";
326
+ echo '<h3>Login Welcome Page ( required, please customize this )</h3>' . "\n";
327
+ echo '<p>Please create and/or choose an existing Page to use as the first page Users will see after logging in.</p>' . "\n";
328
+ /**/
329
+ echo '<table class="form-table">' . "\n";
330
+ echo '<tbody>' . "\n";
331
+ echo '<tr>' . "\n";
332
+ /**/
333
+ echo '<th>' . "\n";
334
+ echo '<label for="ws-plugin--s2member-login-welcome-page">' . "\n";
335
+ echo 'Login Welcome Page:' . "\n";
336
+ echo '</label>' . "\n";
337
+ echo '</th>' . "\n";
338
+ /**/
339
+ echo '</tr>' . "\n";
340
+ echo '<tr>' . "\n";
341
+ /**/
342
+ echo '<td>' . "\n";
343
+ echo '<select name="ws_plugin__s2member_login_welcome_page" id="ws-plugin--s2member-login-welcome-page">' . "\n";
344
+ echo '<option value="">&mdash; Select &mdash;</option>' . "\n";
345
+ foreach (($ws_plugin__s2member_temp_a = array_merge ((array)get_pages ())) as $ws_plugin__s2member_temp_o)
346
+ 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";
347
+ echo '</select><br />' . "\n";
348
+ echo 'Please choose a Page to be used as the first page Users 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";
349
+ 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>' . "\n";
350
+ 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";
351
+ echo '</td>' . "\n";
352
+ /**/
353
+ echo '</tr>' . "\n";
354
+ echo '<tr>' . "\n";
355
+ /**/
356
+ echo '<th>' . "\n";
357
+ echo '<label for="ws-plugin--s2member-allow-subscribers-in">' . "\n";
358
+ echo 'Allow Free Subscribers Access To This Page?' . "\n";
359
+ echo '</label>' . "\n";
360
+ echo '</th>' . "\n";
361
+ /**/
362
+ echo '</tr>' . "\n";
363
+ echo '<tr>' . "\n";
364
+ /**/
365
+ echo '<td>' . "\n";
366
+ echo '<select name="ws_plugin__s2member_allow_subscribers_in" id="ws-plugin--s2member-allow-subscribers-in">' . "\n";
367
+ echo '<option value="0"' . ((!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["allow_subscribers_in"]) ? ' selected="selected"' : '') . '>No ( only Members can access their Login Welcome Page )</option>' . "\n";
368
+ echo '<option value="1"' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["allow_subscribers_in"]) ? ' selected="selected"' : '') . '>Yes ( if a free Subscriber is logged in, they can also access this Page )</option>' . "\n";
369
+ echo '</select><br />' . "\n";
370
+ echo 'If you set this to <code>Yes</code>, it means that you\'re giving Free Subscribers the ability to access this special Page that is normally intended only for Members. If you set this to <code>Yes</code>, you\'re also turning on the `Anyone Can Register` option that is built into WordPress®. So what this means, is that you\'re allowing people to signup for free, as a Free Subscriber, who will then have access to the Login Welcome Page, even though they\'re NOT a paid Member. This is only useful if you plan to let Users signup for free ( <a href="' . add_query_arg ("action", "register", wp_login_url ()) . '" target="_blank" rel="xlink">' . esc_html (add_query_arg ("action", "register", wp_login_url ())) . '</a> ). See <code>s2Member->API Scripting->Advanced Conditionals</code>, for details on how to customize your Login Welcome Page with Conditionals; based on Membership Level.' . "\n";
371
+ echo '</td>' . "\n";
372
+ /**/
373
+ echo '</tr>' . "\n";
374
+ echo '</tbody>' . "\n";
375
+ echo '</table>' . "\n";
376
+ echo '</div>' . "\n";
377
+ /**/
378
+ echo '</div>' . "\n";
379
+ /**/
380
+ echo '<div class="ws-menu-page-group" title="Membership Options Page">' . "\n";
381
+ /**/
382
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-membership-options-page-section">' . "\n";
383
+ echo '<h3>Membership Options Page ( required, please customize this )</h3>' . "\n";
384
+ echo '<p>Please create and/or choose an existing Page that showcases your membership subscription options. This special Page is where you will insert the PayPal® Subscription Buttons generated for you by s2Member. This Page serves as your signup page. It should detail all of the features that come with membership to your site, and provide a PayPal® Subscription Button for each level of access you plan to offer. This is also the page that Users will be redirected to, should they attempt to access an area of your site that requires membership.</p>' . "\n";
385
+ /**/
386
+ echo '<table class="form-table">' . "\n";
387
+ echo '<tbody>' . "\n";
388
+ echo '<tr>' . "\n";
389
+ /**/
390
+ echo '<th>' . "\n";
391
+ echo '<label for="ws-plugin--s2member-membership-options-page">' . "\n";
392
+ echo 'Membership Options Page:' . "\n";
393
+ echo '</label>' . "\n";
394
+ echo '</th>' . "\n";
395
+ /**/
396
+ echo '</tr>' . "\n";
397
+ echo '<tr>' . "\n";
398
+ /**/
399
+ echo '<td>' . "\n";
400
+ echo '<select name="ws_plugin__s2member_membership_options_page" id="ws-plugin--s2member-membership-options-page">' . "\n";
401
+ echo '<option value="">&mdash; Select &mdash;</option>' . "\n";
402
+ foreach (($ws_plugin__s2member_temp_a = array_merge ((array)get_pages ())) as $ws_plugin__s2member_temp_o)
403
+ echo '<option value="' . esc_attr ($ws_plugin__s2member_temp_o->ID) . '"' . (($ws_plugin__s2member_temp_o->ID == $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["membership_options_page"]) ? ' selected="selected"' : '') . '>' . esc_html ($ws_plugin__s2member_temp_o->post_title) . '</option>' . "\n";
404
+ echo '</select><br />' . "\n";
405
+ echo 'Please choose a Page that provides Users a way to signup for membership. This Page should also contain your PayPal&reg subscription button(s). We recommend the following title: <code>Membership Signup</code>.' . "\n";
406
+ echo '</td>' . "\n";
407
+ /**/
408
+ echo '</tr>' . "\n";
409
+ echo '</tbody>' . "\n";
410
+ echo '</table>' . "\n";
411
+ echo '</div>' . "\n";
412
+ /**/
413
+ echo '</div>' . "\n";
414
+ /**/
415
+ echo '<div class="ws-menu-page-group" title="Membership Levels/Labels">' . "\n";
416
+ /**/
417
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-membership-levels-section">' . "\n";
418
+ echo '<h3>Membership Levels ( required, please customize these )</h3>' . "\n";
419
+ echo '<p>The default membership levels are labeled generically; feel free to modify them as needed.</p>' . "\n";
420
+ echo '<p>s2Member supports up to 4 different levels of membership. However, you don\'t have to use all of the membership levels if you don\'t want to. To use only 1 or 2 of these levels, just create and/or modify your Membership Options Page, so that it only includes PayPal® Subscription Buttons for the levels you wish to use.</p>' . "\n";
421
+ /**/
422
+ echo '<table class="form-table">' . "\n";
423
+ echo '<tbody>' . "\n";
424
+ echo '<tr>' . "\n";
425
+ /**/
426
+ echo '<th>' . "\n";
427
+ echo '<label for="ws-plugin--s2member-level1-label">' . "\n";
428
+ echo 'Membership Level #1 Label:' . "\n";
429
+ echo '</label>' . "\n";
430
+ echo '</th>' . "\n";
431
+ /**/
432
+ echo '</tr>' . "\n";
433
+ echo '<tr>' . "\n";
434
+ /**/
435
+ echo '<td>' . "\n";
436
+ echo '<input type="text" name="ws_plugin__s2member_level1_label" id="ws-plugin--s2member-level1-label" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_label"]) . '" /><br />' . "\n";
437
+ echo 'This is the label for membership level 1.<br />' . "\n";
438
+ echo '</td>' . "\n";
439
+ /**/
440
+ echo '</tr>' . "\n";
441
+ echo '<tr>' . "\n";
442
+ /**/
443
+ echo '<th>' . "\n";
444
+ echo '<label for="ws-plugin--s2member-level2-label">' . "\n";
445
+ echo 'Membership Level #2 Label:' . "\n";
446
+ echo '</label>' . "\n";
447
+ echo '</th>' . "\n";
448
+ /**/
449
+ echo '</tr>' . "\n";
450
+ echo '<tr>' . "\n";
451
+ /**/
452
+ echo '<td>' . "\n";
453
+ echo '<input type="text" name="ws_plugin__s2member_level2_label" id="ws-plugin--s2member-level2-label" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_label"]) . '" /><br />' . "\n";
454
+ echo 'This is the label for membership level 2.<br />' . "\n";
455
+ echo '</td>' . "\n";
456
+ /**/
457
+ echo '</tr>' . "\n";
458
+ echo '<tr>' . "\n";
459
+ /**/
460
+ echo '<th>' . "\n";
461
+ echo '<label for="ws-plugin--s2member-level3-label">' . "\n";
462
+ echo 'Membership Level #3 Label:' . "\n";
463
+ echo '</label>' . "\n";
464
+ echo '</th>' . "\n";
465
+ /**/
466
+ echo '</tr>' . "\n";
467
+ echo '<tr>' . "\n";
468
+ /**/
469
+ echo '<td>' . "\n";
470
+ echo '<input type="text" name="ws_plugin__s2member_level3_label" id="ws-plugin--s2member-level3-label" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_label"]) . '" /><br />' . "\n";
471
+ echo 'This is the label for membership level 3.<br />' . "\n";
472
+ echo '</td>' . "\n";
473
+ /**/
474
+ echo '</tr>' . "\n";
475
+ echo '<tr>' . "\n";
476
+ /**/
477
+ echo '<th>' . "\n";
478
+ echo '<label for="ws-plugin--s2member-level4-label">' . "\n";
479
+ echo 'Membership Level #4 Label:' . "\n";
480
+ echo '</label>' . "\n";
481
+ echo '</th>' . "\n";
482
+ /**/
483
+ echo '</tr>' . "\n";
484
+ echo '<tr>' . "\n";
485
+ /**/
486
+ echo '<td>' . "\n";
487
+ echo '<input type="text" name="ws_plugin__s2member_level4_label" id="ws-plugin--s2member-level4-label" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_label"]) . '" /><br />' . "\n";
488
+ echo 'This is the label for membership level 4.<br />' . "\n";
489
+ echo '</td>' . "\n";
490
+ /**/
491
+ echo '</tr>' . "\n";
492
+ echo '</tbody>' . "\n";
493
+ echo '</table>' . "\n";
494
+ echo '</div>' . "\n";
495
+ /**/
496
+ echo '</div>' . "\n";
497
+ /**/
498
+ echo '<div class="ws-menu-page-group" title="Post Access Restrictions">' . "\n";
499
+ /**/
500
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-post-level-access-section">' . "\n";
501
+ echo '<h3>Post Level Access Restrictions ( optional )</h3>' . "\n";
502
+ echo '<p>Here you can specify posts that are restricted to certain membership access levels.</p>' . "\n";
503
+ /**/
504
+ echo '<table class="form-table">' . "\n";
505
+ echo '<tbody>' . "\n";
506
+ echo '<tr>' . "\n";
507
+ /**/
508
+ echo '<th>' . "\n";
509
+ echo '<label for="ws-plugin--s2member-level1-posts">' . "\n";
510
+ echo 'Posts That Require Level #1 Or Higher:' . "\n";
511
+ echo '</label>' . "\n";
512
+ echo '</th>' . "\n";
513
+ /**/
514
+ echo '</tr>' . "\n";
515
+ echo '<tr>' . "\n";
516
+ /**/
517
+ echo '<td>' . "\n";
518
+ echo '<input type="text" name="ws_plugin__s2member_level1_posts" id="ws-plugin--s2member-level1-posts" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_posts"]) . '" /><br />' . "\n";
519
+ echo 'Post IDs in comma delimited format. Example: <code>1,2,3,34,8,21</code> — or you can type: <code>all</code>.' . "\n";
520
+ echo '</td>' . "\n";
521
+ /**/
522
+ echo '</tr>' . "\n";
523
+ echo '<tr>' . "\n";
524
+ /**/
525
+ echo '<th>' . "\n";
526
+ echo '<label for="ws-plugin--s2member-level2-posts">' . "\n";
527
+ echo 'Posts That Require Level #2 Or Higher:' . "\n";
528
+ echo '</label>' . "\n";
529
+ echo '</th>' . "\n";
530
+ /**/
531
+ echo '</tr>' . "\n";
532
+ echo '<tr>' . "\n";
533
+ /**/
534
+ echo '<td>' . "\n";
535
+ echo '<input type="text" name="ws_plugin__s2member_level2_posts" id="ws-plugin--s2member-level2-posts" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_posts"]) . '" /><br />' . "\n";
536
+ echo 'Post IDs in comma delimited format. Example: <code>1,2,3,34,8,21</code> — or you can type: <code>all</code>.' . "\n";
537
+ echo '</td>' . "\n";
538
+ /**/
539
+ echo '</tr>' . "\n";
540
+ echo '<tr>' . "\n";
541
+ /**/
542
+ echo '<th>' . "\n";
543
+ echo '<label for="ws-plugin--s2member-level3-posts">' . "\n";
544
+ echo 'Posts That Require Level #3 Or Higher:' . "\n";
545
+ echo '</label>' . "\n";
546
+ echo '</th>' . "\n";
547
+ /**/
548
+ echo '</tr>' . "\n";
549
+ echo '<tr>' . "\n";
550
+ /**/
551
+ echo '<td>' . "\n";
552
+ echo '<input type="text" name="ws_plugin__s2member_level3_posts" id="ws-plugin--s2member-level3-posts" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_posts"]) . '" /><br />' . "\n";
553
+ echo 'Post IDs in comma delimited format. Example: <code>1,2,3,34,8,21</code> — or you can type: <code>all</code>.' . "\n";
554
+ echo '</td>' . "\n";
555
+ /**/
556
+ echo '</tr>' . "\n";
557
+ echo '<tr>' . "\n";
558
+ /**/
559
+ echo '<th>' . "\n";
560
+ echo '<label for="ws-plugin--s2member-level4-posts">' . "\n";
561
+ echo 'Posts That Require Highest Level #4:' . "\n";
562
+ echo '</label>' . "\n";
563
+ echo '</th>' . "\n";
564
+ /**/
565
+ echo '</tr>' . "\n";
566
+ echo '<tr>' . "\n";
567
+ /**/
568
+ echo '<td>' . "\n";
569
+ echo '<input type="text" name="ws_plugin__s2member_level4_posts" id="ws-plugin--s2member-level4-posts" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_posts"]) . '" /><br />' . "\n";
570
+ echo 'Post IDs in comma delimited format. Example: <code>1,2,3,34,8,21</code> — or you can type: <code>all</code>.' . "\n";
571
+ echo '</td>' . "\n";
572
+ /**/
573
+ echo '</tr>' . "\n";
574
+ echo '</tbody>' . "\n";
575
+ echo '</table>' . "\n";
576
+ echo '</div>' . "\n";
577
+ /**/
578
+ echo '</div>' . "\n";
579
+ /**/
580
+ echo '<div class="ws-menu-page-group" title="Page Access Restrictions">' . "\n";
581
+ /**/
582
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-page-level-access-section">' . "\n";
583
+ echo '<h3>Page Level Access Restrictions ( optional )</h3>' . "\n";
584
+ echo '<p>Here you can specify Pages that are restricted to certain membership access levels.</p>' . "\n";
585
+ /**/
586
+ echo '<table class="form-table">' . "\n";
587
+ echo '<tbody>' . "\n";
588
+ echo '<tr>' . "\n";
589
+ /**/
590
+ echo '<th>' . "\n";
591
+ echo '<label for="ws-plugin--s2member-level1-pages">' . "\n";
592
+ echo 'Pages That Require Level #1 Or Higher:' . "\n";
593
+ echo '</label>' . "\n";
594
+ echo '</th>' . "\n";
595
+ /**/
596
+ echo '</tr>' . "\n";
597
+ echo '<tr>' . "\n";
598
+ /**/
599
+ echo '<td>' . "\n";
600
+ echo '<input type="text" name="ws_plugin__s2member_level1_pages" id="ws-plugin--s2member-level1-pages" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_pages"]) . '" /><br />' . "\n";
601
+ echo 'Page IDs in comma delimited format. Example: <code>1,2,3,34,8,21</code> — or you can type: <code>all</code>.' . "\n";
602
+ echo '</td>' . "\n";
603
+ /**/
604
+ echo '</tr>' . "\n";
605
+ echo '<tr>' . "\n";
606
+ /**/
607
+ echo '<th>' . "\n";
608
+ echo '<label for="ws-plugin--s2member-level2-pages">' . "\n";
609
+ echo 'Pages That Require Level #2 Or Higher:' . "\n";
610
+ echo '</label>' . "\n";
611
+ echo '</th>' . "\n";
612
+ /**/
613
+ echo '</tr>' . "\n";
614
+ echo '<tr>' . "\n";
615
+ /**/
616
+ echo '<td>' . "\n";
617
+ echo '<input type="text" name="ws_plugin__s2member_level2_pages" id="ws-plugin--s2member-level2-pages" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_pages"]) . '" /><br />' . "\n";
618
+ echo 'Page IDs in comma delimited format. Example: <code>1,2,3,34,8,21</code> — or you can type: <code>all</code>.' . "\n";
619
+ echo '</td>' . "\n";
620
+ /**/
621
+ echo '</tr>' . "\n";
622
+ echo '<tr>' . "\n";
623
+ /**/
624
+ echo '<th>' . "\n";
625
+ echo '<label for="ws-plugin--s2member-level3-pages">' . "\n";
626
+ echo 'Pages That Require Level #3 Or Higher:' . "\n";
627
+ echo '</label>' . "\n";
628
+ echo '</th>' . "\n";
629
+ /**/
630
+ echo '</tr>' . "\n";
631
+ echo '<tr>' . "\n";
632
+ /**/
633
+ echo '<td>' . "\n";
634
+ echo '<input type="text" name="ws_plugin__s2member_level3_pages" id="ws-plugin--s2member-level3-pages" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_pages"]) . '" /><br />' . "\n";
635
+ echo 'Page IDs in comma delimited format. Example: <code>1,2,3,34,8,21</code> — or you can type: <code>all</code>.' . "\n";
636
+ echo '</td>' . "\n";
637
+ /**/
638
+ echo '</tr>' . "\n";
639
+ echo '<tr>' . "\n";
640
+ /**/
641
+ echo '<th>' . "\n";
642
+ echo '<label for="ws-plugin--s2member-level4-pages">' . "\n";
643
+ echo 'Pages That Require Highest Level #4:' . "\n";
644
+ echo '</label>' . "\n";
645
+ echo '</th>' . "\n";
646
+ /**/
647
+ echo '</tr>' . "\n";
648
+ echo '<tr>' . "\n";
649
+ /**/
650
+ echo '<td>' . "\n";
651
+ echo '<input type="text" name="ws_plugin__s2member_level4_pages" id="ws-plugin--s2member-level4-pages" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_pages"]) . '" /><br />' . "\n";
652
+ echo 'Page IDs in comma delimited format. Example: <code>1,2,3,34,8,21</code> — or you can type: <code>all</code>.' . "\n";
653
+ echo '</td>' . "\n";
654
+ /**/
655
+ echo '</tr>' . "\n";
656
+ echo '</tbody>' . "\n";
657
+ echo '</table>' . "\n";
658
+ echo '</div>' . "\n";
659
+ /**/
660
+ echo '</div>' . "\n";
661
+ /**/
662
+ echo '<div class="ws-menu-page-group" title="Tag Access Restrictions">' . "\n";
663
+ /**/
664
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-tag-level-access-section">' . "\n";
665
+ echo '<h3>Tag Level Access Restrictions ( optional )</h3>' . "\n";
666
+ echo '<p>Here you can specify tags that are restricted to certain membership access levels. Tag restrictions are a bit more complex. When you restrict access to a tag, it also restricts access to any posts that may have the tag. In other words, restricting a tag protects that tag archive, and it also protects any posts that have the tag; even if they have other tags.</p>' . "\n";
667
+ /**/
668
+ echo '<table class="form-table">' . "\n";
669
+ echo '<tbody>' . "\n";
670
+ echo '<tr>' . "\n";
671
+ /**/
672
+ echo '<th>' . "\n";
673
+ echo '<label for="ws-plugin--s2member-level1-ptags">' . "\n";
674
+ echo 'Tags That Require Level #1 Or Higher:' . "\n";
675
+ echo '</label>' . "\n";
676
+ echo '</th>' . "\n";
677
+ /**/
678
+ echo '</tr>' . "\n";
679
+ echo '<tr>' . "\n";
680
+ /**/
681
+ echo '<td>' . "\n";
682
+ echo '<input type="text" name="ws_plugin__s2member_level1_ptags" id="ws-plugin--s2member-level1-ptags" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_ptags"]) . '" /><br />' . "\n";
683
+ echo 'Tags in comma delimited format. Example: <code>premium,restricted</code> — or you can type: <code>all</code>.' . "\n";
684
+ echo '</td>' . "\n";
685
+ /**/
686
+ echo '</tr>' . "\n";
687
+ echo '<tr>' . "\n";
688
+ /**/
689
+ echo '<th>' . "\n";
690
+ echo '<label for="ws-plugin--s2member-level2-ptags">' . "\n";
691
+ echo 'Tags That Require Level #2 Or Higher:' . "\n";
692
+ echo '</label>' . "\n";
693
+ echo '</th>' . "\n";
694
+ /**/
695
+ echo '</tr>' . "\n";
696
+ echo '<tr>' . "\n";
697
+ /**/
698
+ echo '<td>' . "\n";
699
+ echo '<input type="text" name="ws_plugin__s2member_level2_ptags" id="ws-plugin--s2member-level2-ptags" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_ptags"]) . '" /><br />' . "\n";
700
+ echo 'Tags in comma delimited format. Example: <code>premium,restricted</code> — or you can type: <code>all</code>.' . "\n";
701
+ echo '</td>' . "\n";
702
+ /**/
703
+ echo '</tr>' . "\n";
704
+ echo '<tr>' . "\n";
705
+ /**/
706
+ echo '<th>' . "\n";
707
+ echo '<label for="ws-plugin--s2member-level3-ptags">' . "\n";
708
+ echo 'Tags That Require Level #3 Or Higher:' . "\n";
709
+ echo '</label>' . "\n";
710
+ echo '</th>' . "\n";
711
+ /**/
712
+ echo '</tr>' . "\n";
713
+ echo '<tr>' . "\n";
714
+ /**/
715
+ echo '<td>' . "\n";
716
+ echo '<input type="text" name="ws_plugin__s2member_level3_ptags" id="ws-plugin--s2member-level3-ptags" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_ptags"]) . '" /><br />' . "\n";
717
+ echo 'Tags in comma delimited format. Example: <code>premium,restricted</code> — or you can type: <code>all</code>.' . "\n";
718
+ echo '</td>' . "\n";
719
+ /**/
720
+ echo '</tr>' . "\n";
721
+ echo '<tr>' . "\n";
722
+ /**/
723
+ echo '<th>' . "\n";
724
+ echo '<label for="ws-plugin--s2member-level4-ptags">' . "\n";
725
+ echo 'Tags That Require Highest Level #4:' . "\n";
726
+ echo '</label>' . "\n";
727
+ echo '</th>' . "\n";
728
+ /**/
729
+ echo '</tr>' . "\n";
730
+ echo '<tr>' . "\n";
731
+ /**/
732
+ echo '<td>' . "\n";
733
+ echo '<input type="text" name="ws_plugin__s2member_level4_ptags" id="ws-plugin--s2member-level4-ptags" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_ptags"]) . '" /><br />' . "\n";
734
+ echo 'Tags in comma delimited format. Example: <code>premium,restricted</code> — or you can type: <code>all</code>.' . "\n";
735
+ echo '</td>' . "\n";
736
+ /**/
737
+ echo '</tr>' . "\n";
738
+ echo '</tbody>' . "\n";
739
+ echo '</table>' . "\n";
740
+ echo '</div>' . "\n";
741
+ /**/
742
+ echo '</div>' . "\n";
743
+ /**/
744
+ echo '<div class="ws-menu-page-group" title="Category Access Restrictions">' . "\n";
745
+ /**/
746
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-category-level-access-section">' . "\n";
747
+ echo '<h3>Category Level Access Restrictions ( optional )</h3>' . "\n";
748
+ echo '<p>Here you can specify categories that are restricted to certain membership access levels. Category restrictions are a bit more complex. When you restrict access to a category, it also restricts access to any child categories it may have ( aka: sub-categories ). In other words, restricting a category protects that category archive, all of its child category archives, and any posts contained within the category or its child categories.</p>' . "\n";
749
+ /**/
750
+ echo '<table class="form-table">' . "\n";
751
+ echo '<tbody>' . "\n";
752
+ echo '<tr>' . "\n";
753
+ /**/
754
+ echo '<th>' . "\n";
755
+ echo '<label for="ws-plugin--s2member-level1-catgs">' . "\n";
756
+ echo 'Categories That Require Level #1 Or Higher:' . "\n";
757
+ echo '</label>' . "\n";
758
+ echo '</th>' . "\n";
759
+ /**/
760
+ echo '</tr>' . "\n";
761
+ echo '<tr>' . "\n";
762
+ /**/
763
+ echo '<td>' . "\n";
764
+ echo '<input type="text" name="ws_plugin__s2member_level1_catgs" id="ws-plugin--s2member-level1-catgs" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_catgs"]) . '" /><br />' . "\n";
765
+ echo 'Category IDs in comma delimited format. Example: <code>1,2,3,34,8,21</code> — or you can type: <code>all</code>.' . "\n";
766
+ echo '</td>' . "\n";
767
+ /**/
768
+ echo '</tr>' . "\n";
769
+ echo '<tr>' . "\n";
770
+ /**/
771
+ echo '<th>' . "\n";
772
+ echo '<label for="ws-plugin--s2member-level2-catgs">' . "\n";
773
+ echo 'Categories That Require Level #2 Or Higher:' . "\n";
774
+ echo '</label>' . "\n";
775
+ echo '</th>' . "\n";
776
+ /**/
777
+ echo '</tr>' . "\n";
778
+ echo '<tr>' . "\n";
779
+ /**/
780
+ echo '<td>' . "\n";
781
+ echo '<input type="text" name="ws_plugin__s2member_level2_catgs" id="ws-plugin--s2member-level2-catgs" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_catgs"]) . '" /><br />' . "\n";
782
+ echo 'Category IDs in comma delimited format. Example: <code>1,2,3,34,8,21</code> — or you can type: <code>all</code>.' . "\n";
783
+ echo '</td>' . "\n";
784
+ /**/
785
+ echo '</tr>' . "\n";
786
+ echo '<tr>' . "\n";
787
+ /**/
788
+ echo '<th>' . "\n";
789
+ echo '<label for="ws-plugin--s2member-level3-catgs">' . "\n";
790
+ echo 'Categories That Require Level #3 Or Higher:' . "\n";
791
+ echo '</label>' . "\n";
792
+ echo '</th>' . "\n";
793
+ /**/
794
+ echo '</tr>' . "\n";
795
+ echo '<tr>' . "\n";
796
+ /**/
797
+ echo '<td>' . "\n";
798
+ echo '<input type="text" name="ws_plugin__s2member_level3_catgs" id="ws-plugin--s2member-level3-catgs" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_catgs"]) . '" /><br />' . "\n";
799
+ echo 'Category IDs in comma delimited format. Example: <code>1,2,3,34,8,21</code> — or you can type: <code>all</code>.' . "\n";
800
+ echo '</td>' . "\n";
801
+ /**/
802
+ echo '</tr>' . "\n";
803
+ echo '<tr>' . "\n";
804
+ /**/
805
+ echo '<th>' . "\n";
806
+ echo '<label for="ws-plugin--s2member-level4-catgs">' . "\n";
807
+ echo 'Categories That Require Highest Level #4:' . "\n";
808
+ echo '</label>' . "\n";
809
+ echo '</th>' . "\n";
810
+ /**/
811
+ echo '</tr>' . "\n";
812
+ echo '<tr>' . "\n";
813
+ /**/
814
+ echo '<td>' . "\n";
815
+ echo '<input type="text" name="ws_plugin__s2member_level4_catgs" id="ws-plugin--s2member-level4-catgs" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_catgs"]) . '" /><br />' . "\n";
816
+ echo 'Category IDs in comma delimited format. Example: <code>1,2,3,34,8,21</code> — or you can type: <code>all</code>.' . "\n";
817
+ echo '</td>' . "\n";
818
+ /**/
819
+ echo '</tr>' . "\n";
820
+ echo '</tbody>' . "\n";
821
+ echo '</table>' . "\n";
822
+ echo '</div>' . "\n";
823
+ /**/
824
+ echo '</div>' . "\n";
825
+ /**/
826
+ echo '<div class="ws-menu-page-group" title="URI Access Restrictions">' . "\n";
827
+ /**/
828
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-uri-level-access-section">' . "\n";
829
+ echo '<h3>URI Level Access Restrictions ( optional )</h3>' . "\n";
830
+ echo '<p>Here you can specify URIs ( or word fragments found in URIs ) that are restricted to certain membership access levels. The control over URIs is 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>. 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>.</p>' . "\n";
831
+ /**/
832
+ echo '<table class="form-table">' . "\n";
833
+ echo '<tbody>' . "\n";
834
+ echo '<tr>' . "\n";
835
+ /**/
836
+ echo '<th>' . "\n";
837
+ echo '<label for="ws-plugin--s2member-level1-ruris">' . "\n";
838
+ echo 'URIs That Require Level #1 Or Higher:' . "\n";
839
+ echo '</label>' . "\n";
840
+ echo '</th>' . "\n";
841
+ /**/
842
+ echo '</tr>' . "\n";
843
+ echo '<tr>' . "\n";
844
+ /**/
845
+ echo '<td>' . "\n";
846
+ echo '<textarea name="ws_plugin__s2member_level1_ruris" id="ws-plugin--s2member-level1-ruris" rows="3" wrap="off">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level1_ruris"]) . '</textarea><br />' . "\n";
847
+ echo 'URIs and/or word fragments found in URIs. One per line please.' . "\n";
848
+ echo '</td>' . "\n";
849
+ /**/
850
+ echo '</tr>' . "\n";
851
+ echo '<tr>' . "\n";
852
+ /**/
853
+ echo '<th>' . "\n";
854
+ echo '<label for="ws-plugin--s2member-level2-ruris">' . "\n";
855
+ echo 'URIs That Require Level #2 Or Higher:' . "\n";
856
+ echo '</label>' . "\n";
857
+ echo '</th>' . "\n";
858
+ /**/
859
+ echo '</tr>' . "\n";
860
+ echo '<tr>' . "\n";
861
+ /**/
862
+ echo '<td>' . "\n";
863
+ echo '<textarea name="ws_plugin__s2member_level2_ruris" id="ws-plugin--s2member-level2-ruris" rows="3" wrap="off">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level2_ruris"]) . '</textarea><br />' . "\n";
864
+ echo 'URIs and/or word fragments found in URIs. One per line please.' . "\n";
865
+ echo '</td>' . "\n";
866
+ /**/
867
+ echo '</tr>' . "\n";
868
+ echo '<tr>' . "\n";
869
+ /**/
870
+ echo '<th>' . "\n";
871
+ echo '<label for="ws-plugin--s2member-level3-ruris">' . "\n";
872
+ echo 'URIs That Require Level #3 Or Higher:' . "\n";
873
+ echo '</label>' . "\n";
874
+ echo '</th>' . "\n";
875
+ /**/
876
+ echo '</tr>' . "\n";
877
+ echo '<tr>' . "\n";
878
+ /**/
879
+ echo '<td>' . "\n";
880
+ echo '<textarea name="ws_plugin__s2member_level3_ruris" id="ws-plugin--s2member-level3-ruris" rows="3" wrap="off">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level3_ruris"]) . '</textarea><br />' . "\n";
881
+ echo 'URIs and/or word fragments found in URIs. One per line please.' . "\n";
882
+ echo '</td>' . "\n";
883
+ /**/
884
+ echo '</tr>' . "\n";
885
+ echo '<tr>' . "\n";
886
+ /**/
887
+ echo '<th>' . "\n";
888
+ echo '<label for="ws-plugin--s2member-level4-ruris">' . "\n";
889
+ echo 'URIs That Require Highest Level #4:' . "\n";
890
+ echo '</label>' . "\n";
891
+ echo '</th>' . "\n";
892
+ /**/
893
+ echo '</tr>' . "\n";
894
+ echo '<tr>' . "\n";
895
+ /**/
896
+ echo '<td>' . "\n";
897
+ echo '<textarea name="ws_plugin__s2member_level4_ruris" id="ws-plugin--s2member-level4-ruris" rows="3" wrap="off">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["level4_ruris"]) . '</textarea><br />' . "\n";
898
+ echo 'URIs and/or word fragments found in URIs. One per line please.' . "\n";
899
+ echo '</td>' . "\n";
900
+ /**/
901
+ echo '</tr>' . "\n";
902
+ echo '</tbody>' . "\n";
903
+ echo '</table>' . "\n";
904
+ echo '</div>' . "\n";
905
+ /**/
906
+ echo '</div>' . "\n";
907
+ /**/
908
+ echo '<div class="ws-menu-page-group" title="De-Activation Safeguards">' . "\n";
909
+ /**/
910
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-deactivation-section">' . "\n";
911
+ echo '<h3>De-Activation Safeguards ( optional, for safeguarding s2Member data )</h3>' . "\n";
912
+ echo '<p>By default, s2Member will cleanup ( erase ) all of it\'s Roles, Capabilities, and your Configuration Options when/if you de-activate it from the Plugins Menu in WordPress®. If you would like to Safeguard all of this information, in case s2Member is de-activated inadvertently, you can disable the De-Activation Routines for s2Member.</p>' . "\n";
913
+ echo '<table class="form-table">' . "\n";
914
+ echo '<tbody>' . "\n";
915
+ echo '<tr>' . "\n";
916
+ /**/
917
+ echo '<th>' . "\n";
918
+ echo '<label for="ws-plugin--s2member-run-deactivation-routines">' . "\n";
919
+ echo 'Run De-Activation Routines for s2Member?' . "\n";
920
+ echo '</label>' . "\n";
921
+ echo '</th>' . "\n";
922
+ /**/
923
+ echo '</tr>' . "\n";
924
+ echo '<tr>' . "\n";
925
+ /**/
926
+ echo '<td>' . "\n";
927
+ echo '<select name="ws_plugin__s2member_run_deactivation_routines" id="ws-plugin--s2member-run-deactivation-routines">' . "\n";
928
+ echo '<option value="1"' . (($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["run_deactivation_routines"]) ? ' selected="selected"' : '') . '>Yes ( erase all s2Member data/options on de-activation )</option>' . "\n";
929
+ echo '<option value="0"' . ((!$GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["run_deactivation_routines"]) ? ' selected="selected"' : '') . '>No ( safeguard all s2Member data/options )</option>' . "\n";
930
+ echo '</select><br />' . "\n";
931
+ echo 'It is recommended that you Safeguard all s2Member data/options on your system.' . "\n";
932
+ echo '</td>' . "\n";
933
+ /**/
934
+ echo '</tr>' . "\n";
935
+ echo '</tbody>' . "\n";
936
+ echo '</table>' . "\n";
937
+ echo '</div>' . "\n";
938
+ /**/
939
+ echo '</div>' . "\n";
940
+ /**/
941
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
942
+ /**/
943
+ echo '<p class="submit"><input type="submit" class="button-primary" value="Save Changes" /></p>' . "\n";
944
+ /**/
945
+ echo '</form>' . "\n";
946
+ /**/
947
+ echo '</td>' . "\n";
948
+ /**/
949
+ echo '<td class="ws-menu-page-table-r">' . "\n";
950
+ /**/
951
+ echo ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["menu-r"]["tools"]) ? '<div class="ws-menu-page-tools"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-tools.png" alt="." /></div>' . "\n" : '';
952
+ /**/
953
+ echo ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["menu-r"]["tips"]) ? '<div class="ws-menu-page-tips"><a href="' . ws_plugin__s2member_parse_readme_value ("Customization URI") . '"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-tips.png" alt="." /></a></div>' . "\n" : '';
954
+ /**/
955
+ echo ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["menu-r"]["donations"]) ? '<div class="ws-menu-page-donations"><a href="' . ws_plugin__s2member_parse_readme_value ("Donate link") . '"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-donations.jpg" alt="." /></a></div>' . "\n" : '';
956
+ /**/
957
+ echo '</td>' . "\n";
958
+ /**/
959
+ echo '</tr>' . "\n";
960
+ echo '</tbody>' . "\n";
961
+ echo '</table>' . "\n";
962
+ /**/
963
+ echo '</div>' . "\n";
964
+ ?>
includes/menu-pages/paypal-ops.inc.php ADDED
@@ -0,0 +1,241 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ PayPal® Options page.
18
+ */
19
+ echo '<div class="wrap ws-menu-page">' . "\n";
20
+ /**/
21
+ echo '<div id="icon-plugins" class="icon32"><br /></div>' . "\n";
22
+ echo '<h2><div>Developed by <a href="' . ws_plugin__s2member_parse_readme_value ("Plugin URI") . '"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-light.png" alt="." /></a></div>s2Member PayPal® Options</h2>' . "\n";
23
+ /**/
24
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
25
+ /**/
26
+ echo '<table class="ws-menu-page-table">' . "\n";
27
+ echo '<tbody class="ws-menu-page-table-tbody">' . "\n";
28
+ echo '<tr class="ws-menu-page-table-tr">' . "\n";
29
+ echo '<td class="ws-menu-page-table-l">' . "\n";
30
+ /**/
31
+ echo '<form method="post" name="ws_plugin__s2member_options_form" id="ws-plugin--s2member-options-form">' . "\n";
32
+ echo '<input type="hidden" name="ws_plugin__s2member_options_save" id="ws-plugin--s2member-options-save" value="' . esc_attr (wp_create_nonce ("ws-plugin--s2member-options-save")) . '" />' . "\n";
33
+ echo '<input type="hidden" name="ws_plugin__s2member_configured" id="ws-plugin--s2member-configured" value="1" />' . "\n";
34
+ /**/
35
+ echo '<div class="ws-menu-page-group" title="PayPal® Account Details">' . "\n";
36
+ /**/
37
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-paypal-email-section">' . "\n";
38
+ echo '<h3>PayPal® EMail Address ( required, please customize this )</h3>' . "\n";
39
+ echo '<p>This plugin works in conjunction with PayPal® Website Payments Standard, 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="xlink">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";
40
+ /**/
41
+ echo '<table class="form-table">' . "\n";
42
+ echo '<tbody>' . "\n";
43
+ echo '<tr>' . "\n";
44
+ /**/
45
+ echo '<th>' . "\n";
46
+ echo '<label for="ws-plugin--s2member-paypal-business">' . "\n";
47
+ echo 'Your PayPal® EMail Address:' . "\n";
48
+ echo '</label>' . "\n";
49
+ echo '</th>' . "\n";
50
+ /**/
51
+ echo '</tr>' . "\n";
52
+ echo '<tr>' . "\n";
53
+ /**/
54
+ echo '<td>' . "\n";
55
+ echo '<input type="text" name="ws_plugin__s2member_paypal_business" id="ws-plugin--s2member-paypal-business" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_business"]) . '" /><br />' . "\n";
56
+ echo 'Enter the email address you\'ve associated with your PayPal® account.' . "\n";
57
+ echo '</td>' . "\n";
58
+ /**/
59
+ echo '</tr>' . "\n";
60
+ echo '<tr>' . "\n";
61
+ /**/
62
+ echo '<th>' . "\n";
63
+ echo '<label for="ws-plugin--s2member-paypal-sandbox">' . "\n";
64
+ echo 'Sandbox Testing?' . "\n";
65
+ echo '</label>' . "\n";
66
+ echo '</th>' . "\n";
67
+ /**/
68
+ echo '</tr>' . "\n";
69
+ echo '<tr>' . "\n";
70
+ /**/
71
+ echo '<td>' . "\n";
72
+ 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";
73
+ echo '<em>Only enable this if you\'ve provided a Sandbox email address above. This puts the IPN, PDT and Button Generator into Sandbox mode. See: <a href="https://developer.paypal.com/" target="_blank" rel="xlink">https://developer.paypal.com/</a></em>' . "\n";
74
+ echo '</td>' . "\n";
75
+ /**/
76
+ echo '</tr>' . "\n";
77
+ echo '<tr>' . "\n";
78
+ /**/
79
+ echo '<th>' . "\n";
80
+ echo '<label for="ws-plugin--s2member-paypal-debug">' . "\n";
81
+ echo 'Enable Logging Routines?' . "\n";
82
+ echo '</label>' . "\n";
83
+ echo '</th>' . "\n";
84
+ /**/
85
+ echo '</tr>' . "\n";
86
+ echo '<tr>' . "\n";
87
+ /**/
88
+ echo '<td>' . "\n";
89
+ 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 IPN &amp; Return Page logging.</label><br />' . "\n";
90
+ echo '<em>Only enable if you\'re debugging. This enables IPN and Return Page logging. The log files are stored here: <code>' . preg_replace ("/^" . preg_quote ($_SERVER["DOCUMENT_ROOT"], "/") . "/", "", $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"]) . '</code></em>' . "\n";
91
+ echo '</td>' . "\n";
92
+ /**/
93
+ echo '</tr>' . "\n";
94
+ echo '</tbody>' . "\n";
95
+ echo '</table>' . "\n";
96
+ echo '</div>' . "\n";
97
+ /**/
98
+ echo '</div>' . "\n";
99
+ /**/
100
+ echo '<div class="ws-menu-page-group" title="PayPal® IPN Integration">' . "\n";
101
+ /**/
102
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-paypal-ipn-section">' . "\n";
103
+ echo '<h3>PayPal® IPN / Instant Payment Notifications ( required, please enable )</h3>' . "\n";
104
+ echo '<p>Log into your PayPal® account and navigate to this section:<br /><code>Account Profile -> Instant Payment Notification Preferences</code></p>' . "\n";
105
+ echo '<p>Edit your IPN settings &amp; turn IPN Notifications: <strong><code>On</code></strong></p>' . "\n";
106
+ echo '<p>You\'ll need your IPN URL, which is:<br /><code>' . get_bloginfo ("url") . '/?s2member_paypal_notify=1</code></p>' . "\n";
107
+ echo '<p><strong>Quick tip:</strong> In addition to the default IPN Settings inside your PayPal® account, the IPN URL is also set on a per-transaction basis by the special PayPal® button code that s2Member provides you with. In other words, if you have multiple sites operating on one PayPal® account, that\'s OK. s2Member dynamically sets the IPN URL for each transaction. The result is that the IPN URL configured from within your PayPal® account, becomes the default, which is then overwritten on a per transaction basis. In fact, PayPal® recently updated their system to support IPN URL preservation, which makes it easier to use one PayPal® account to handle multiple sites, all using different IPN URLs.' . "\n";
108
+ echo '<p><strong>More information:</strong> You\'ll be happy to know that s2Member handles cancellations, expirations, failed payments ( more than 2 in a row ), terminations ( e.g. refunds &amp; chargebacks ) for you automatically. If you log into your PayPal® account and cancel a User\'s subscription, or, if the User 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 scenes. The PayPal® IPN service will notify s2Member whenever a User\'s payments have been failing ( more than 2 times in a row ), and/or whenever a User\'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 be deleted automagically. The communication from PayPal® -> s2Member is seamless.</p>' . "\n";
109
+ echo '</div>' . "\n";
110
+ /**/
111
+ echo '</div>' . "\n";
112
+ /**/
113
+ echo '<div class="ws-menu-page-group" title="PayPal® PDT/Auto-Return">' . "\n";
114
+ /**/
115
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-paypal-pdt-section">' . "\n";
116
+ echo '<h3>PayPal® PDT Identity Token ( required, if using PayPal® Auto-Return )</h3>' . "\n";
117
+ echo '<p>Only fill this in if you\'re using PayPal\'s Auto-Return feature with PDT ( Payment Data Transfer ). Please note that Auto-Return w/PDT does <strong>NOT</strong> have to be enabled in your PayPal® account for s2Member to function. It is merely a way to bring visitors back to your site faster after completing checkout at PayPal®. That being said, <strong>if you enable Auto-Return, you MUST also enable PDT &amp; supply your Identity Token here</strong>. Auto-Return &amp; PDT ( Payment Data Transfer ) can both be enabled from within your PayPal® account. You\'ll need your Auto-Return URL, which is:<br /><code>' . get_bloginfo ("url") . '/?s2member_paypal_return=1</code></p>' . "\n";
118
+ echo '<p>It is also worth noting that in addition to your default PayPal® account configuration, the Auto-Return URL is also set on a per-transaction basis from within the special PayPal® button code that s2Member provides you with. In other words, if you have multiple sites operating on one PayPal® account, that\'s OK. s2Member dynamically sets the Auto-Return URL for each transaction. The result is that the Auto-Return URL configured from within your PayPal® account, becomes the default, which is then overwritten on a per transaction basis.' . "\n";
119
+ echo '<p>Once you\'ve enabled Auto-Return and PDT, PayPal® will issue your Identity Token.' . "\n";
120
+ /**/
121
+ echo '<table class="form-table">' . "\n";
122
+ echo '<tbody>' . "\n";
123
+ echo '<tr>' . "\n";
124
+ /**/
125
+ echo '<th>' . "\n";
126
+ echo '<label for="ws-plugin--s2member-paypal-identity-token">' . "\n";
127
+ echo 'PayPal® PDT Identity Token:' . "\n";
128
+ echo '</label>' . "\n";
129
+ echo '</th>' . "\n";
130
+ /**/
131
+ echo '</tr>' . "\n";
132
+ echo '<tr>' . "\n";
133
+ /**/
134
+ echo '<td>' . "\n";
135
+ echo '<input type="text" name="ws_plugin__s2member_paypal_identity_token" id="ws-plugin--s2member-paypal-identity-token" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["paypal_identity_token"]) . '" /><br />' . "\n";
136
+ echo 'You MUST fill this in if you\'ve enabled Auto-Return. Auto-Return &amp; PDT can both be enabled from within your PayPal® account.' . "\n";
137
+ echo '</td>' . "\n";
138
+ /**/
139
+ echo '</tr>' . "\n";
140
+ echo '</tbody>' . "\n";
141
+ echo '</table>' . "\n";
142
+ echo '</div>' . "\n";
143
+ /**/
144
+ echo '</div>' . "\n";
145
+ /**/
146
+ echo '<div class="ws-menu-page-group" title="PayPal® Confirmation Email">' . "\n";
147
+ /**/
148
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-signup-confirmation-email-section">' . "\n";
149
+ echo '<h3>Signup Confirmation Email ( required, but the default works fine )</h3>' . "\n";
150
+ echo '<p>This email is sent to new Customers after they return from a successful signup at PayPal®. The <strong>primary</strong> purpose of this email is to provide the Customer with instructions, along with a link to register a Username for their membership. You may also customize this further by providing details that are specifically geared to your site.</p>' . "\n";
151
+ /**/
152
+ echo '<table class="form-table">' . "\n";
153
+ echo '<tbody>' . "\n";
154
+ echo '<tr>' . "\n";
155
+ /**/
156
+ echo '<th>' . "\n";
157
+ echo '<label for="ws-plugin--s2member-signup-email-subject">' . "\n";
158
+ echo 'Signup Confirmation Email Subject:' . "\n";
159
+ echo '</label>' . "\n";
160
+ echo '</th>' . "\n";
161
+ /**/
162
+ echo '</tr>' . "\n";
163
+ echo '<tr>' . "\n";
164
+ /**/
165
+ echo '<td>' . "\n";
166
+ echo '<input type="text" name="ws_plugin__s2member_signup_email_subject" id="ws-plugin--s2member-signup-email-subject" value="' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["signup_email_subject"]) . '" /><br />' . "\n";
167
+ echo 'Subject Line used in the email sent to a Customer after a successful signup has occurred through PayPal®.' . "\n";
168
+ echo '</td>' . "\n";
169
+ /**/
170
+ echo '</tr>' . "\n";
171
+ echo '<tr>' . "\n";
172
+ /**/
173
+ echo '<th>' . "\n";
174
+ echo '<label for="ws-plugin--s2member-signup-email-message">' . "\n";
175
+ echo 'Signup Confirmation Email Message:' . "\n";
176
+ echo '</label>' . "\n";
177
+ echo '</th>' . "\n";
178
+ /**/
179
+ echo '</tr>' . "\n";
180
+ echo '<tr>' . "\n";
181
+ /**/
182
+ echo '<td>' . "\n";
183
+ echo '<textarea name="ws_plugin__s2member_signup_email_message" id="ws-plugin--s2member-signup-email-message" rows="10">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["signup_email_message"]) . '</textarea><br />' . "\n";
184
+ echo 'Message Body used in the email sent to a Customer after a successful signup has occurred through PayPal®.<br /><br />' . "\n";
185
+ echo '<strong>You can also use these special replacement codes if you need them:</strong>' . "\n";
186
+ echo '<ul>' . "\n";
187
+ echo '<li><code>%%registration_url%% = The full URL ( generated by s2Member ) where the Customer can get registered.</code></li>' . "\n";
188
+ echo '<li><code>%%subscr_id%% = The PayPal® Subscription ID, which remains constant throughout any &amp; all future payments.</code> [ <a href="#" onclick="alert(\'There is one exception. If you are selling Lifetime ( non-recurring ) access, using a Buy It Now button; the %%subscr_id%% is actually set to the Transaction ID for the purchase.\\n\\nPayPal® does not provide a specific Subscription ID for Buy It Now purchases. Since Lifetime 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";
189
+ echo '<li><code>%%initial%% = The initial fee charged during signup, in USD. If you offered a free trial, this will be 0.</code> [ <a href="#" onclick="alert(\'If no initial period was offered or required, this initial amount will be equal to the %%regular%% rate. In other words, this will always represent the amount of money the customer spent whenever they signed up, no matter what.\\n\\nIf a user signs up under the terms of a free trial period, this will be 0.\'); return false;">?</a> ]</li>' . "\n";
190
+ echo '<li><code>%%regular%% = The regular amount of the subscription in USD. This dollar value is always > 0, no matter what.</code> [ <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";
191
+ echo '<li><code>%%recurring%% = This is the amount in USD that will be charged on a recurring basis, or 0 if non-recurring.</code> [ <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.\\n\\nThe only time this is NOT equal to the %%regular%% rate, is when recurring payments are not required; and only a one-time regular rate applies.\'); return false;">?</a> ]</li>' . "\n";
192
+ echo '<li><code>%%first_name%% = The first name of the customer who purchased the membership subscription through PayPal®.</code></li>' . "\n";
193
+ echo '<li><code>%%last_name%% = The last name of the customer who purchased the membership subscription through PayPal®.</code></li>' . "\n";
194
+ echo '<li><code>%%full_name%% = The full name ( first & last ) of the customer who purchased the membership subscription.</code></li>' . "\n";
195
+ echo '<li><code>%%payer_email%% = The email address of the customer who purchased the membership subscription through PayPal®.</code></li>' . "\n";
196
+ echo '<li><code>%%item_number%% = The item number ( in other words, the membership level: 1, 2, 3 or 4 ) that the subscription is for.</code></li>' . "\n";
197
+ echo '<li><code>%%item_name%% = The item name ( in other words, the associated membership level label that briefly describes the item number ).</code></li>' . "\n";
198
+ echo '<li><code>%%initial_term%% = This is the term length of the initial period. This will be a numeric value, followed by a space, then a single letter.</code> [ <a href="#" onclick="alert(\'Here are some examples:\\n\\n%%initial_term%% = 1 D ( this means 1 Day )\\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";
199
+ echo '<li><code>%%regular_term%% = This is the term length of the regular period. This will be a numeric value, followed by a space, then a single letter.</code> [ <a href="#" onclick="alert(\'Here are some examples:\\n\\n%%regular_term%% = 1 D ( this means 1 Day )\\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 priviledges 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";
200
+ echo '</ul>' . "\n";
201
+ echo '<strong>Custom replacement codes can also be inserted using these instructions:</strong>' . "\n";
202
+ echo '<ul>' . "\n";
203
+ echo '<li><code>%%cv0%% = The domain of your site, which is passed through to PayPal® using the `custom` field in your PayPal® button code.</code></li>' . "\n";
204
+ echo '<li><code>%%cv1%% = If you need to track additional custom variables, you can pipe delimit them into the `custom` field of your button code like this: &lt;input type="hidden" name="custom" value="' . $_SERVER["HTTP_HOST"] . '|cv1|cv2|cv3" /&gt;. You can have an unlimited number of custom variables that track IP addresses, affiliate IDs, etc. In some cases you may need to use PHP code to insert a value into the custom field dynamically. Obviously this is for advanced webmasters, but the functionality has been made available for those who need it.</li>' . "\n";
205
+ echo '</ul>' . "\n";
206
+ echo '<strong>This example uses cv1 to track a user\'s IP address:</strong><br />' . "\n";
207
+ echo '<em>( The IP address can be referenced in your Signup Confirmation Email using %%cv1%% )</em><br />' . "\n";
208
+ echo '<code>&lt;input type="hidden" name="custom" value="' . $_SERVER["HTTP_HOST"] . '|&lt;?php echo $_SERVER["REMOTE_ADDR"]; ?&gt;" /&gt;</code>' . "\n";
209
+ echo '</td>' . "\n";
210
+ /**/
211
+ echo '</tr>' . "\n";
212
+ echo '</tbody>' . "\n";
213
+ echo '</table>' . "\n";
214
+ echo '</div>' . "\n";
215
+ /**/
216
+ echo '</div>' . "\n";
217
+ /**/
218
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
219
+ /**/
220
+ echo '<p class="submit"><input type="submit" class="button-primary" value="Save Changes" /></p>' . "\n";
221
+ /**/
222
+ echo '</form>' . "\n";
223
+ /**/
224
+ echo '</td>' . "\n";
225
+ /**/
226
+ echo '<td class="ws-menu-page-table-r">' . "\n";
227
+ /**/
228
+ echo ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["menu-r"]["tools"]) ? '<div class="ws-menu-page-tools"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-tools.png" alt="." /></div>' . "\n" : '';
229
+ /**/
230
+ echo ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["menu-r"]["tips"]) ? '<div class="ws-menu-page-tips"><a href="' . ws_plugin__s2member_parse_readme_value ("Customization URI") . '"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-tips.png" alt="." /></a></div>' . "\n" : '';
231
+ /**/
232
+ echo ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["menu-r"]["donations"]) ? '<div class="ws-menu-page-donations"><a href="' . ws_plugin__s2member_parse_readme_value ("Donate link") . '"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-donations.jpg" alt="." /></a></div>' . "\n" : '';
233
+ /**/
234
+ echo '</td>' . "\n";
235
+ /**/
236
+ echo '</tr>' . "\n";
237
+ echo '</tbody>' . "\n";
238
+ echo '</table>' . "\n";
239
+ /**/
240
+ echo '</div>' . "\n";
241
+ ?>
includes/menu-pages/s2m-samps.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
2
+ <input type="hidden" name="business" value="paypal@example.com">
3
+ <input type="hidden" name="cmd" value="_xclick-subscriptions">
4
+ <!-- Instant Payment Notification / Return Details -->
5
+ <input type="hidden" name="notify_url" value="http://www.example.com/?s2member_paypal_notify=1">
6
+ <input type="hidden" name="cancel_return" value="http://www.example.com">
7
+ <input type="hidden" name="return" value="http://www.example.com/?s2member_paypal_return=1">
8
+ <input type="hidden" name="rm" value="2">
9
+ <!-- Identify / Customize 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="www.example.com">
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="Paid Membership ( $25/mo )">
16
+ <input type="hidden" name="item_number" value="1">
17
+ <!-- Identify / Update An Existing Free Subscriber After Checkout. -->
18
+ <input type="hidden" name="on0" value="Update Subscriber ID">
19
+ <input type="hidden" name="os0" value="<?php echo S2MEMBER_CURRENT_USER_SUBSCR_ID; ?>">
20
+ <!-- Set The Terms Of The New Subscription. -->
21
+ <input type="hidden" name="modify" value="0">
22
+ <input type="hidden" name="src" value="1">
23
+ <input type="hidden" name="sra" value="1">
24
+ <input type="hidden" name="a3" value="25">
25
+ <input type="hidden" name="p3" value="1">
26
+ <input type="hidden" name="t3" value="M">
27
+ <!-- Display The Subscription Button. -->
28
+ <input type="image" alt="PayPal®" style="border:0;" src="https://www.paypal.com/en_GB/i/btn/btn_xpressCheckout.gif">
29
+ </form>
30
+ -------------------------------------------------------------------------------------------------
31
+ SO THE RELEVANT SECTION IN THE EXAMPLE GIVEN ABOVE IS:
32
+ <input type="hidden" name="on0" value="Update Subscriber ID">
33
+ <input type="hidden" name="os0" value="<?php echo S2MEMBER_CURRENT_USER_SUBSCR_ID; ?>">
includes/menu-pages/scripting.inc.php ADDED
@@ -0,0 +1,318 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ API Scripting page.
18
+ */
19
+ echo '<div class="wrap ws-menu-page">' . "\n";
20
+ /**/
21
+ echo '<div id="icon-plugins" class="icon32"><br /></div>' . "\n";
22
+ echo '<h2><div>Developed by <a href="' . ws_plugin__s2member_parse_readme_value ("Plugin URI") . '"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-light.png" alt="." /></a></div>s2Member API / Scripting</h2>' . "\n";
23
+ /**/
24
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
25
+ /**/
26
+ echo '<table class="ws-menu-page-table">' . "\n";
27
+ echo '<tbody class="ws-menu-page-table-tbody">' . "\n";
28
+ echo '<tr class="ws-menu-page-table-tr">' . "\n";
29
+ echo '<td class="ws-menu-page-table-l">' . "\n";
30
+ /**/
31
+ echo '<div class="ws-menu-page-group" title="The Extremely Easy Way">' . "\n";
32
+ /**/
33
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-api-easy-way-section">' . "\n";
34
+ echo '<h3>The Extremely Easy Way ( no scripting required )</h3>' . "\n";
35
+ 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. 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 Advanced Conditionals comes in.</p>' . "\n";
36
+ echo '</div>' . "\n";
37
+ /**/
38
+ echo '</div>' . "\n";
39
+ /**/
40
+ echo '<div class="ws-menu-page-group" title="Using Advanced Conditionals">' . "\n";
41
+ /**/
42
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-api-advanced-way-section">' . "\n";
43
+ echo '<h3>The Advanced Way ( some PHP scripting required )</h3>' . "\n";
44
+ echo '<p>In an effort to give you even more control over access restrictions, s2Member makes a special PHP function available to you from within WordPress®. The function is named <strong>current_user_can()</strong>. To make use of this function, please follow our PHP code samples below. Using PHP, you can control access to certain portions of your content, and even build Advanced Conditionals within your content based on a Members\'s level. If you\'re unable to use PHP scripting inside your Posts or Pages, you might want to install this handy plugin ( <a href="http://wordpress.org/extend/plugins/exec-php/" target="_blank" rel="xlink">Exec-PHP</a> ).</p>' . "\n";
45
+ echo '<p><strong>Here are some examples of how you could use the `current_user_can` function in PHP scripting:</strong></p>' . "\n";
46
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/cur-samps.php"), true) . '</p>' . "\n";
47
+ echo '</div>' . "\n";
48
+ /**/
49
+ echo '</div>' . "\n";
50
+ /**/
51
+ echo '<div class="ws-menu-page-group" title="s2Member Content Dripping">' . "\n";
52
+ /**/
53
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-api-advanced-dripping-section">' . "\n";
54
+ echo '<h3>Dripping Content ( some PHP scripting required )</h3>' . "\n";
55
+ 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. If you\'re unable to use PHP scripting inside your Posts or Pages, you might want to install this handy plugin ( <a href="http://wordpress.org/extend/plugins/exec-php/" target="_blank" rel="xlink">Exec-PHP</a> ).</p>' . "\n";
56
+ echo '<p><strong>To drip content, use <code>S2MEMBER_CURRENT_USER_REGISTRATION_DAYS</code> in your PHP scripting:</strong></p>' . "\n";
57
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/drip-samps.php"), true) . '</p>' . "\n";
58
+ echo '</div>' . "\n";
59
+ /**/
60
+ echo '</div>' . "\n";
61
+ /**/
62
+ echo '<div class="ws-menu-page-group" title="s2Member PHP/API Constants">' . "\n";
63
+ /**/
64
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-api-constants-section">' . "\n";
65
+ echo '<h3>You Have Access To PHP Constants ( some PHP scripting required )</h3>' . "\n";
66
+ echo '<p>A constant is an identifier ( name ) for a simple value in PHP scripting. Below is a comprehensive list that includes all PHP defined constants that are available to you. All of these Constants are also available through JavaScript as global variables. Example code has been provided in the documenation below. If you\'re a web developer, we suggest using some of these Constants in the creation of the Login Welcome Page described in the s2Member General Options panel. It is not required mind you, but you can get pretty creative with the Login Welcome Page if you know a little PHP. For example, you might use `S2MEMBER_CURRENT_USER_ACCESS_LABEL` to display the type of membership the User currently has. Or you could use `S2MEMBER_CURRENT_USER_PROFILE_MODIFICATION_PAGE_URL` to provide the user with a really easy way to update their Membership Profile. If you get stuck on this, you might want to check out Elance.com. You can hire a freelancer to do this for you. It\'s about a $100 job. There are many other possibilities available as well; <em>limitless actually!</em></p>' . "\n";
67
+ /**/
68
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
69
+ /**/
70
+ echo '<p><strong>S2MEMBER_CURRENT_USER_IS_LOGGED_IN</strong> = This will always be (bool) true or false. True if a user is currently logged in with a level of 1 or higher.</p>' . "\n";
71
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/current_user_is_logged_in.php"), true) . '</p>' . "\n";
72
+ /**/
73
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
74
+ /**/
75
+ echo '<p><strong>S2MEMBER_CURRENT_USER_ACCESS_LEVEL</strong> = This will always be (int) -1 thru 4. -1 if not logged in. 0 if logged in without access.</p>' . "\n";
76
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/current_user_access_level.php"), true) . '</p>' . "\n";
77
+ /**/
78
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
79
+ /**/
80
+ echo '<p><strong>S2MEMBER_CURRENT_USER_ACCESS_LABEL</strong> = This will always be a (string). Empty if not logged in.</p>' . "\n";
81
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/current_user_access_label.php"), true) . '</p>' . "\n";
82
+ /**/
83
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
84
+ /**/
85
+ echo '<p><strong>S2MEMBER_CURRENT_USER_SUBSCR_ID</strong> = This will always be a (string). Empty if not logged in.</p>' . "\n";
86
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/current_user_subscr_id.php"), true) . '</p>' . "\n";
87
+ /**/
88
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
89
+ /**/
90
+ echo '<p><strong>S2MEMBER_CURRENT_USER_CUSTOM</strong> = This will always be a (string). Empty if not logged in.</p>' . "\n";
91
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/current_user_custom.php"), true) . '</p>' . "\n";
92
+ /**/
93
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
94
+ /**/
95
+ echo '<p><strong>S2MEMBER_CURRENT_USER_REGISTRATION_TIME</strong> = 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";
96
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/current_user_registration_time.php"), true) . '</p>' . "\n";
97
+ /**/
98
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
99
+ /**/
100
+ echo '<p><strong>S2MEMBER_CURRENT_USER_REGISTRATION_DAYS</strong> = 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";
101
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/current_user_registration_days.php"), true) . '</p>' . "\n";
102
+ /**/
103
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
104
+ /**/
105
+ echo '<p><strong>S2MEMBER_CURRENT_USER_DISPLAY_NAME</strong> = This will always be a (string). Empty if not logged in.</p>' . "\n";
106
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/current_user_display_name.php"), true) . '</p>' . "\n";
107
+ /**/
108
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
109
+ /**/
110
+ echo '<p><strong>S2MEMBER_CURRENT_USER_FIRST_NAME</strong> = This will always be a (string). Empty if not logged in.</p>' . "\n";
111
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/current_user_first_name.php"), true) . '</p>' . "\n";
112
+ /**/
113
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
114
+ /**/
115
+ echo '<p><strong>S2MEMBER_CURRENT_USER_LAST_NAME</strong> = This will always be a (string). Empty if not logged in.</p>' . "\n";
116
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/current_user_last_name.php"), true) . '</p>' . "\n";
117
+ /**/
118
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
119
+ /**/
120
+ echo '<p><strong>S2MEMBER_CURRENT_USER_LOGIN</strong> = This will always be a (string). Empty if not logged in.</p>' . "\n";
121
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/current_user_login.php"), true) . '</p>' . "\n";
122
+ /**/
123
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
124
+ /**/
125
+ echo '<p><strong>S2MEMBER_CURRENT_USER_EMAIL</strong> = This will always be a (string). Empty if not logged in.</p>' . "\n";
126
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/current_user_email.php"), true) . '</p>' . "\n";
127
+ /**/
128
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
129
+ /**/
130
+ echo '<p><strong>S2MEMBER_CURRENT_USER_IP</strong> = This will always be a (string). Empty if browsing anonymously.</p>' . "\n";
131
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/current_user_ip.php"), true) . '</p>' . "\n";
132
+ /**/
133
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
134
+ /**/
135
+ echo '<p><strong>S2MEMBER_CURRENT_USER_ID</strong> = This will always be an (int). However, it will be 0 if not logged in.</p>' . "\n";
136
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/current_user_id.php"), true) . '</p>' . "\n";
137
+ /**/
138
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
139
+ /**/
140
+ echo '<p><strong>S2MEMBER_CURRENT_USER_FIELDS</strong> = This will always be a serialized array (string). An empty serialized array (string) if not logged in. This serialized array will contain the following fields: <code>id, ip, email, login, first_name, last_name, display_name, subscr_id, custom</code>. If you\'ve configured additional Custom Fields, those Custom Fields will also be added to this array. For example, if you configured the Custom Field: <code>Street Address</code>, it would be included in this array as: <code>street_address</code>. Custom Field references are converted to lowercase format, and spaces are replaced by underscores. You can do <code>print_r(unserialize(S2MEMBER_CURRENT_USER_FIELDS));</code> to get a full list for testing.</p>' . "\n";
141
+ if (defined ("BP_VERSION"))
142
+ echo '<p><em class="ws-menu-page-error">* Custom Fields are N/A when running together with BuddyPress. Instead, use <code>BuddyPress -> Profile Field Setup</code>.</em></p>' . "\n";
143
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/current_user_fields.php"), true) . '</p>' . "\n";
144
+ /**/
145
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
146
+ /**/
147
+ echo '<p><strong>S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED</strong> = This will always be an (int) value >= 0 where 0 means no access.</p>' . "\n";
148
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/current_user_downloads_allowed.php"), true) . '</p>' . "\n";
149
+ /**/
150
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
151
+ /**/
152
+ echo '<p><strong>S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_IS_UNLIMITED</strong> = This will always be (bool) true or false. A value of true means their allowed downloads are >= 999999999, and false means it is not. This is useful if you are allowing unlimited ( 999999999 ) downloads on some membership levels. You can display `Unlimited` instead of a number.</p>' . "\n";
153
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/current_user_downloads_allowed_is_unlimited.php"), true) . '</p>' . "\n";
154
+ /**/
155
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
156
+ /**/
157
+ echo '<p><strong>S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY</strong> = This will always be an (int) value >= 0 where 0 means none.</p>' . "\n";
158
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/current_user_downloads_currently.php"), true) . '</p>' . "\n";
159
+ /**/
160
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
161
+ /**/
162
+ echo '<p><strong>S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS</strong> = This will always be an (int) value >= 0 where 0 means no access.</p>' . "\n";
163
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/current_user_downloads_allowed_days.php"), true) . '</p>' . "\n";
164
+ /**/
165
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
166
+ /**/
167
+ echo '<p><strong>S2MEMBER_CURRENT_USER_PROFILE_MODIFICATION_PAGE_URL</strong> = This is where a user can modify their profile. ( window.open is suggested ).</p>' . "\n";
168
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/current_user_profile_modification_page_url.php"), true) . '</p>' . "\n";
169
+ /**/
170
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
171
+ /**/
172
+ echo '<p><strong>S2MEMBER_FILE_DOWNLOAD_LIMIT_EXCEEDED_PAGE_URL</strong> = This is the full URL to the Limit Exceeded Page ( informational ).<br />' . "\n";
173
+ echo '<strong>S2MEMBER_FILE_DOWNLOAD_LIMIT_EXCEEDED_PAGE_ID</strong> = This is the Page ID that was used to generate the full URL.</p>' . "\n";
174
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/file_download_limit_exceeded_page_url.php"), true) . '</p>' . "\n";
175
+ /**/
176
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
177
+ /**/
178
+ echo '<p><strong>S2MEMBER_MEMBERSHIP_OPTIONS_PAGE_URL</strong> = This is the full URL to the Membership Options Page ( the signup page ).<br />' . "\n";
179
+ echo '<strong>S2MEMBER_MEMBERSHIP_OPTIONS_PAGE_ID</strong> = This is the Page ID that was used to generate the full URL.</p>' . "\n";
180
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/membership_options_page_url.php"), true) . '</p>' . "\n";
181
+ /**/
182
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
183
+ /**/
184
+ echo '<p><strong>S2MEMBER_LOGIN_WELCOME_PAGE_URL</strong> = This is the full URL to the Login Welcome Page ( the user\'s account page ). * This could also be the full URL to a Special Redirection URL ( if you configured one ). See <code>s2Member -> General Options -> Login Welcome Page</code>.<br />' . "\n";
185
+ echo '<strong>S2MEMBER_LOGIN_WELCOME_PAGE_ID</strong> = This is the Page ID that was used to generate the full URL. * In the case of a Special Redirection URL, this ID is not really applicable.</p>' . "\n";
186
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/login_welcome_page_url.php"), true) . '</p>' . "\n";
187
+ /**/
188
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
189
+ /**/
190
+ echo '<p><strong>S2MEMBER_LOGIN_PAGE_URL</strong> = This is the full URL to the Membership Login Page ( the wordpress login page ).</p>' . "\n";
191
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/login_page_url.php"), true) . '</p>' . "\n";
192
+ /**/
193
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
194
+ /**/
195
+ echo '<p><strong>S2MEMBER_LOGOUT_PAGE_URL</strong> = This is the full URL to the Membership Logout Page ( the wordpress logout page ).</p>' . "\n";
196
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/logout_page_url.php"), true) . '</p>' . "\n";
197
+ /**/
198
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
199
+ /**/
200
+ echo '<p><strong>S2MEMBER_LEVEL1_LABEL</strong> = This is the (string) label that you created for membership level number 1.</p>' . "\n";
201
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/level1_label.php"), true) . '</p>' . "\n";
202
+ /**/
203
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
204
+ /**/
205
+ echo '<p><strong>S2MEMBER_LEVEL2_LABEL</strong> = This is the (string) label that you created for membership level number 2.</p>' . "\n";
206
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/level2_label.php"), true) . '</p>' . "\n";
207
+ /**/
208
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
209
+ /**/
210
+ echo '<p><strong>S2MEMBER_LEVEL3_LABEL</strong> = This is the (string) label that you created for membership level number 3.</p>' . "\n";
211
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/level3_label.php"), true) . '</p>' . "\n";
212
+ /**/
213
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
214
+ /**/
215
+ echo '<p><strong>S2MEMBER_LEVEL4_LABEL</strong> = This is the (string) label that you created for membership level number 4.</p>' . "\n";
216
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/level4_label.php"), true) . '</p>' . "\n";
217
+ /**/
218
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
219
+ /**/
220
+ echo '<p><strong>S2MEMBER_LEVEL1_FILE_DOWNLOADS_ALLOWED</strong> = This is the (int) allowed downloads for level number 1.</p>' . "\n";
221
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/level1_file_downloads_allowed.php"), true) . '</p>' . "\n";
222
+ /**/
223
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
224
+ /**/
225
+ echo '<p><strong>S2MEMBER_LEVEL2_FILE_DOWNLOADS_ALLOWED</strong> = This is the (int) allowed downloads for level number 2.</p>' . "\n";
226
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/level2_file_downloads_allowed.php"), true) . '</p>' . "\n";
227
+ /**/
228
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
229
+ /**/
230
+ echo '<p><strong>S2MEMBER_LEVEL3_FILE_DOWNLOADS_ALLOWED</strong> = This is the (int) allowed downloads for level number 3.</p>' . "\n";
231
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/level3_file_downloads_allowed.php"), true) . '</p>' . "\n";
232
+ /**/
233
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
234
+ /**/
235
+ echo '<p><strong>S2MEMBER_LEVEL4_FILE_DOWNLOADS_ALLOWED</strong> = This is the (int) allowed downloads for level number 4.</p>' . "\n";
236
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/level4_file_downloads_allowed.php"), true) . '</p>' . "\n";
237
+ /**/
238
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
239
+ /**/
240
+ echo '<p><strong>S2MEMBER_LEVEL1_FILE_DOWNLOADS_ALLOWED_DAYS</strong> = This is the (int) allowed download days for level number 1.</p>' . "\n";
241
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/level1_file_downloads_allowed_days.php"), true) . '</p>' . "\n";
242
+ /**/
243
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
244
+ /**/
245
+ echo '<p><strong>S2MEMBER_LEVEL2_FILE_DOWNLOADS_ALLOWED_DAYS</strong> = This is the (int) allowed download days for level number 2.</p>' . "\n";
246
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/level2_file_downloads_allowed_days.php"), true) . '</p>' . "\n";
247
+ /**/
248
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
249
+ /**/
250
+ echo '<p><strong>S2MEMBER_LEVEL3_FILE_DOWNLOADS_ALLOWED_DAYS</strong> = This is the (int) allowed download days for level number 3.</p>' . "\n";
251
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/level3_file_downloads_allowed_days.php"), true) . '</p>' . "\n";
252
+ /**/
253
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
254
+ /**/
255
+ echo '<p><strong>S2MEMBER_LEVEL4_FILE_DOWNLOADS_ALLOWED_DAYS</strong> = This is the (int) allowed download days for level number 4.</p>' . "\n";
256
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/level4_file_downloads_allowed_days.php"), true) . '</p>' . "\n";
257
+ /**/
258
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
259
+ /**/
260
+ echo '<p><strong>S2MEMBER_REG_EMAIL_FROM_NAME</strong> = This is the name that outgoing email messages are sent by.</p>' . "\n";
261
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/reg_email_from_name.php"), true) . '</p>' . "\n";
262
+ /**/
263
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
264
+ /**/
265
+ echo '<p><strong>S2MEMBER_REG_EMAIL_FROM_EMAIL</strong> = This is the email address that outgoing messages are sent by.</p>' . "\n";
266
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/reg_email_from_email.php"), true) . '</p>' . "\n";
267
+ /**/
268
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
269
+ /**/
270
+ echo '<p><strong>S2MEMBER_PAYPAL_NOTIFY_URL</strong> = This is the URL on your system that receives PayPal IPN responses.</p>' . "\n";
271
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/paypal_notify_url.php"), true) . '</p>' . "\n";
272
+ /**/
273
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
274
+ /**/
275
+ echo '<p><strong>S2MEMBER_PAYPAL_RETURN_URL</strong> = This is the URL on your system that receives PayPal return variables.</p>' . "\n";
276
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/paypal_return_url.php"), true) . '</p>' . "\n";
277
+ /**/
278
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
279
+ /**/
280
+ echo '<p><strong>S2MEMBER_PAYPAL_ENDPOINT</strong> = This is the endpoint domain to the paypal server.</p>' . "\n";
281
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/paypal_endpoint.php"), true) . '</p>' . "\n";
282
+ /**/
283
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
284
+ /**/
285
+ echo '<p><strong>S2MEMBER_PAYPAL_BUSINESS</strong> = This is the email address that identifies your paypal business.</p>' . "\n";
286
+ echo '<p>' . highlight_string (file_get_contents (dirname (__FILE__) . "/con-samps/paypal_business.php"), true) . '</p>' . "\n";
287
+ /**/
288
+ echo '</div>' . "\n";
289
+ /**/
290
+ echo '</div>' . "\n";
291
+ /**/
292
+ echo '<div class="ws-menu-page-group" title="s2Member JS/API Globals">' . "\n";
293
+ /**/
294
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-api-js-globals-section">' . "\n";
295
+ echo '<h3>You Also Have Access To JS Globals ( some scripting required )</h3>' . "\n";
296
+ echo '<p>All of the PHP Constants are also available through JavaScript as global variables.</p>' . "\n";
297
+ echo '</div>' . "\n";
298
+ /**/
299
+ echo '</div>' . "\n";
300
+ /**/
301
+ echo '</td>' . "\n";
302
+ /**/
303
+ echo '<td class="ws-menu-page-table-r">' . "\n";
304
+ /**/
305
+ echo ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["menu-r"]["tools"]) ? '<div class="ws-menu-page-tools"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-tools.png" alt="." /></div>' . "\n" : '';
306
+ /**/
307
+ echo ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["menu-r"]["tips"]) ? '<div class="ws-menu-page-tips"><a href="' . ws_plugin__s2member_parse_readme_value ("Customization URI") . '"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-tips.png" alt="." /></a></div>' . "\n" : '';
308
+ /**/
309
+ echo ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["menu-r"]["donations"]) ? '<div class="ws-menu-page-donations"><a href="' . ws_plugin__s2member_parse_readme_value ("Donate link") . '"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-donations.jpg" alt="." /></a></div>' . "\n" : '';
310
+ /**/
311
+ echo '</td>' . "\n";
312
+ /**/
313
+ echo '</tr>' . "\n";
314
+ echo '</tbody>' . "\n";
315
+ echo '</table>' . "\n";
316
+ /**/
317
+ echo '</div>' . "\n";
318
+ ?>
includes/menu-pages/shortcode.html ADDED
@@ -0,0 +1 @@
 
1
+ [s2Member-PayPal-Button level="%%level%%" ps="paypal" cc="USD" on0="" os0="" modify="0" custom="%%domain%%" tp="0" tt="D" ra="0.01" rp="1" rt="M" rr="1" /]
includes/menu-pages/trk-ops.inc.php ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ API Tracking page.
18
+ */
19
+ echo '<div class="wrap ws-menu-page">' . "\n";
20
+ /**/
21
+ echo '<div id="icon-plugins" class="icon32"><br /></div>' . "\n";
22
+ echo '<h2><div>Developed by <a href="' . ws_plugin__s2member_parse_readme_value ("Plugin URI") . '"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-light.png" alt="." /></a></div>s2Member API / Tracking</h2>' . "\n";
23
+ /**/
24
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
25
+ /**/
26
+ echo '<table class="ws-menu-page-table">' . "\n";
27
+ echo '<tbody class="ws-menu-page-table-tbody">' . "\n";
28
+ echo '<tr class="ws-menu-page-table-tr">' . "\n";
29
+ echo '<td class="ws-menu-page-table-l">' . "\n";
30
+ /**/
31
+ echo '<form method="post" name="ws_plugin__s2member_options_form" id="ws-plugin--s2member-options-form">' . "\n";
32
+ echo '<input type="hidden" name="ws_plugin__s2member_options_save" id="ws-plugin--s2member-options-save" value="' . esc_attr (wp_create_nonce ("ws-plugin--s2member-options-save")) . '" />' . "\n";
33
+ echo '<input type="hidden" name="ws_plugin__s2member_configured" id="ws-plugin--s2member-configured" value="1" />' . "\n";
34
+ /**/
35
+ echo '<div class="ws-menu-page-group" title="Pixel Tracking Code Snippets">' . "\n";
36
+ /**/
37
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-pixel-tracking-section">' . "\n";
38
+ echo '<h3>Pixel Tracking Codes ( optional, these will be injected into the Signup Confirmation Page )</h3>' . "\n";
39
+ echo '<p>If you use affiliate software, have tracking codes from advertising networks, or the like, you\'ll want to read this section. The HTML code that you enter below, will be loaded up in a web browser, whenever a Customer lands on the Signup Confirmation Page after checkout. The s2Member (built-in) Signup Confirmation Page ( also known as a Thank-You Page ), is really just a blank page that alerts the Customer via JavaScript. It says: `Thank You! Your membership has been approved.`. Then it says: `The next step is to Register a Username. Please click OK to be redirected.`. After they\'ve clicked OK on this alert, and after everything ( if there is anything ) on the blank page has finished loading, they\'ll be redirected to the Registration system, where they will be able to setup their Username and login for the first time. This process has been fully automated, very simple.</p>' . "\n";
40
+ echo '<p>Now, if you want to track the performance of your marketing efforts using Google® Analytics, affiliate software or advertising networks, you can place the code for those in the field below. All of the code in the field below, will be injected into the Signup Confirmation Page, between the <code>&lt;body&gt;&lt;/body&gt;</code> tags. After everything in your code has finished loading, the new Member will be redirected to the Registration system, so they can setup their Username and login. In other words, the Signup Confirmation Page ensures that all 1x1 pixel images and/or other data from your Pixel Tracking Code ( in the field below ) has finished loading, before it redirects the Member away from the page. This way you can be sure that all of your tracking statistics, and other marketing efforts, remain accurate. This is handled through the magic of the <code>window.onload</code> event, compatible in all major browsers.</p>' . "\n";
41
+ /**/
42
+ echo '<table class="form-table">' . "\n";
43
+ echo '<tbody>' . "\n";
44
+ echo '<tr>' . "\n";
45
+ /**/
46
+ echo '<th>' . "\n";
47
+ echo '<label for="ws-plugin--s2member-signup-pixel-tracking-codes">' . "\n";
48
+ echo 'Pixel Tracking Codes:' . "\n";
49
+ echo '</label>' . "\n";
50
+ echo '</th>' . "\n";
51
+ /**/
52
+ echo '</tr>' . "\n";
53
+ echo '<tr>' . "\n";
54
+ /**/
55
+ echo '<td>' . "\n";
56
+ echo '<textarea name="ws_plugin__s2member_signup_pixel_tracking_codes" id="ws-plugin--s2member-signup-pixel-tracking-codes" rows="8">' . format_to_edit ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["signup_pixel_tracking_codes"]) . '</textarea><br />' . "\n";
57
+ echo 'Any valid XHTML or JavaScript code will work just fine here. Just try not to put anything here that would actually be visible to the user. They won\'t see it anyway, because they\'re going to be redirected as soon as it loads up. Things like 1x1 pixel images that load up silently and/or JavaScript tracking routines will be fine though. 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";
58
+ echo '<strong>You can also use these special replacement codes if you need them:</strong>' . "\n";
59
+ echo '<ul>' . "\n";
60
+ echo '<li><code>%%subscr_id%% = The PayPal® Subscription ID, which remains constant throughout any &amp; all future payments.</code> [ <a href="#" onclick="alert(\'There is one exception. If you are selling Lifetime ( non-recurring ) access, using a Buy It Now button; the %%subscr_id%% is actually set to the Transaction ID for the purchase.\\n\\nPayPal® does not provide a specific Subscription ID for Buy It Now purchases. Since Lifetime 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";
61
+ echo '<li><code>%%initial%% = The initial fee charged during signup, in USD. If you offered a free trial, this will be 0.</code> [ <a href="#" onclick="alert(\'If no initial period was offered or required, this initial amount will be equal to the regular subscription rate. In other words, this will always represent the amount of money the customer spent whenever they signed up, no matter what.\\n\\nIf a user signs up under the terms of a free trial period, this will be 0. So be careful using this value with 3rd party affiliate integrations because a $0 sale amount could cause havoc. If you have a lot of trouble, try using the more advanced `Payment` notifications available in the API Notifications panel for s2Member.\'); return false;">?</a> ]</li>' . "\n";
62
+ echo '<li><code>%%first_name%% = The first name of the customer who purchased the membership subscription through PayPal®.</code></li>' . "\n";
63
+ echo '<li><code>%%last_name%% = The last name of the customer who purchased the membership subscription through PayPal®.</code></li>' . "\n";
64
+ echo '<li><code>%%full_name%% = The full name ( first & last ) of the customer who purchased the membership subscription.</code></li>' . "\n";
65
+ echo '<li><code>%%payer_email%% = The email address of the customer who purchased the membership subscription through PayPal®.</code></li>' . "\n";
66
+ echo '<li><code>%%item_number%% = The item number ( in other words, the membership level: 1, 2, 3 or 4 ) that the subscription is for.</code></li>' . "\n";
67
+ echo '<li><code>%%item_name%% = The item name ( in other words, the associated membership level label that briefly describes the item number ).</code></li>' . "\n";
68
+ echo '</ul>' . "\n";
69
+ echo '<strong>Custom replacement codes can also be inserted using these instructions:</strong>' . "\n";
70
+ echo '<ul>' . "\n";
71
+ echo '<li><code>%%cv0%% = The domain of your site, which is passed through to PayPal® using the `custom` field in your PayPal® button code.</code></li>' . "\n";
72
+ echo '<li><code>%%cv1%% = If you need to track additional custom variables, you can pipe delimit them into the `custom` field of your button code like this: &lt;input type="hidden" name="custom" value="' . $_SERVER["HTTP_HOST"] . '|cv1|cv2|cv3" /&gt;. You can have an unlimited number of custom variables that track IP addresses, affiliate IDs, etc. In some cases you may need to use PHP code to insert a value into the custom field dynamically. Obviously this is for advanced webmasters, but the functionality has been made available for those who need it.</code></li>' . "\n";
73
+ echo '</ul>' . "\n";
74
+ echo '<strong>This example uses cv1 to track a user\'s IP address:</strong><br />' . "\n";
75
+ echo '<em>( The IP address can be referenced in your Pixel Code using %%cv1%% )</em><br />' . "\n";
76
+ echo '<code>&lt;input type="hidden" name="custom" value="' . $_SERVER["HTTP_HOST"] . '|&lt;?php echo $_SERVER["REMOTE_ADDR"]; ?&gt;" /&gt;</code>' . "\n";
77
+ echo '</td>' . "\n";
78
+ /**/
79
+ echo '</tr>' . "\n";
80
+ echo '</tbody>' . "\n";
81
+ echo '</table>' . "\n";
82
+ echo '</div>' . "\n";
83
+ /**/
84
+ echo '</div>' . "\n";
85
+ /**/
86
+ echo '<div class="ws-menu-page-group" title="Other Methods Available">' . "\n";
87
+ /**/
88
+ echo '<div class="ws-menu-page-section ws-plugin--s2member-other-methods-section">' . "\n";
89
+ echo '<h3>Other Methods Are Available As Well</h3>' . "\n";
90
+ echo '<p>You may also want to check the s2Member API Notifications panel. You\'ll find additional layers of automation available through the use of the `Signup`, `Payment`, `EOT/Deletion` and `Refund/Reversal` notifications that are available to you through the s2Member API. These make it easy to integrate with 3rd party applications like affiliate programs and other back-office routines. 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 really replaces the simplicity of using Pixel Tracking, and the s2Member API Notifications are not necessarily the best tool for the job in all cases. For instance, API Notifications will NOT work with Google® Analytics, or 1 pixel &lt;img&gt; tags. They operate silently behind-the-scenes, using cURL connections, as opposed to being loaded in a browser.</p>' . "\n";
91
+ echo '</div>' . "\n";
92
+ /**/
93
+ echo '</div>' . "\n";
94
+ /**/
95
+ echo '<div class="ws-menu-page-hr"></div>' . "\n";
96
+ /**/
97
+ echo '<p class="submit"><input type="submit" class="button-primary" value="Save Changes" /></p>' . "\n";
98
+ /**/
99
+ echo '</form>' . "\n";
100
+ /**/
101
+ echo '</td>' . "\n";
102
+ /**/
103
+ echo '<td class="ws-menu-page-table-r">' . "\n";
104
+ /**/
105
+ echo ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["menu-r"]["tools"]) ? '<div class="ws-menu-page-tools"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-tools.png" alt="." /></div>' . "\n" : '';
106
+ /**/
107
+ echo ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["menu-r"]["tips"]) ? '<div class="ws-menu-page-tips"><a href="' . ws_plugin__s2member_parse_readme_value ("Customization URI") . '"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-tips.png" alt="." /></a></div>' . "\n" : '';
108
+ /**/
109
+ echo ($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["menu-r"]["donations"]) ? '<div class="ws-menu-page-donations"><a href="' . ws_plugin__s2member_parse_readme_value ("Donate link") . '"><img src="' . $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . '/images/brand-donations.jpg" alt="." /></a></div>' . "\n" : '';
110
+ /**/
111
+ echo '</td>' . "\n";
112
+ /**/
113
+ echo '</tr>' . "\n";
114
+ echo '</tbody>' . "\n";
115
+ echo '</table>' . "\n";
116
+ /**/
117
+ echo '</div>' . "\n";
118
+ ?>
includes/mime-types.ini ADDED
@@ -0,0 +1,313 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [application]
2
+ afm = application/x-adobe-font-metric
3
+ ai = application/postscript
4
+ acx = application/internet-property-stream
5
+ axs = application/olescript
6
+ bcpio = application/x-bcpio
7
+ bdf = application/x-bdf-font
8
+ bin = application/octet-stream
9
+ cat = application/vnd.ms-pkiseccat
10
+ ccad = application/clariscad
11
+ cdf = application/x-cdf
12
+ cer = application/x-x509-ca-cert
13
+ cgi = application/x-perl
14
+ class = application/octet-stream
15
+ clp = application/x-msclip
16
+ cpio = application/x-cpio
17
+ cpt = application/mac-compactpro
18
+ crd = application/x-mscardfile
19
+ crl = application/pkix-crl
20
+ crt = application/x-x509-ca-cert
21
+ csh = application/x-csh
22
+ dcr = application/x-director
23
+ der = application/x-x509-ca-cert
24
+ dir = application/x-director
25
+ dms = application/octet-stream
26
+ dll = application/x-msdownload
27
+ doc = application/msword
28
+ dot = application/msword
29
+ drw = application/drafting
30
+ dvi = application/x-dvi
31
+ dwg = application/acad
32
+ dxf = application/dxf
33
+ dxr = application/x-director
34
+ eps = application/postscript
35
+ evy = application/envoy
36
+ exe = application/octet-stream
37
+ ez = application/andrew-inset
38
+ f3b = application/x-openwin-font
39
+ fif = application/fractals
40
+ fla = application/x-shockwave-flash
41
+ gsf = application/x-postscript-font
42
+ gtar = application/x-gtar
43
+ gz = application/x-gzip
44
+ hdf = application/x-hdf
45
+ hlp = application/winhlp
46
+ hta = application/hta
47
+ hqx = application/mac-binhex40
48
+ iii = application/x-iphone
49
+ ins = application/x-internet-signup
50
+ ips = application/x-ipscript
51
+ ipx = application/x-ipix
52
+ iso = application/iso-10161-ill-1
53
+ isp = application/x-internet-signup
54
+ js = application/x-javascript
55
+ latex = application/x-latex
56
+ lha = application/octet-stream
57
+ lsp = application/x-lisp
58
+ lzh = application/octet-stream
59
+ m13 = application/x-msmediaview
60
+ m14 = application/x-msmediaview
61
+ man = application/x-troff-man
62
+ mdb = application/x-msaccess
63
+ me = application/x-troff-me
64
+ mif = application/vnd.mif
65
+ mny = application/x-msmoney
66
+ mpp = application/vnd.ms-project
67
+ ms = application/x-troff-ms
68
+ mvb = application/x-msmediaview
69
+ nc = application/x-netcdf
70
+ oda = application/oda
71
+ odt = application/vnd.oasis.opendocument.text
72
+ ott = application/vnd.oasis.opendocument.text-template
73
+ odg = application/vnd.oasis.opendocument.graphics
74
+ otg = application/vnd.oasis.opendocument.graphics-template
75
+ odp = application/vnd.oasis.opendocument.presentation
76
+ otp = application/vnd.oasis.opendocument.presentation-template
77
+ ods = application/vnd.oasis.opendocument.spreadsheet
78
+ ots = application/vnd.oasis.opendocument.spreadsheet-template
79
+ odc = application/vnd.oasis.opendocument.chart
80
+ otc = application/vnd.oasis.opendocument.chart-template
81
+ odi = application/vnd.oasis.opendocument.image
82
+ oti = application/vnd.oasis.opendocument.image-template
83
+ odf = application/vnd.oasis.opendocument.formula
84
+ otf = application/vnd.oasis.opendocument.formula-template
85
+ odm = application/vnd.oasis.opendocument.text-master
86
+ oth = application/vnd.oasis.opendocument.text-web
87
+ p10 = application/pkcs10
88
+ p12 = application/x-pkcs12
89
+ p7b = application/x-pkcs7-certificates
90
+ p7c = application/x-pkcs7-mime
91
+ p7m = application/x-pkcs7-mime
92
+ p7r = application/x-pkcs7-certreqresp
93
+ p7s = application/x-pkcs7-signature
94
+ pcf = application/x-pcf-font
95
+ pdf = application/pdf
96
+ pfa = application/x-postscript-font
97
+ pfb = application/x-postscript-font
98
+ pfr = application/font-tdpfr
99
+ pfx = application/x-pkcs12
100
+ pgn = application/x-chess-pgn
101
+ php = application/x-php
102
+ pko = application/ynd.ms-pkipko
103
+ pl = application/x-perl
104
+ pma = application/x-perfmon
105
+ pmc = application/x-perfmon
106
+ pml = application/x-perfmon
107
+ pmr = application/x-perfmon
108
+ pmw = application/x-perfmon
109
+ pot = application/mspowerpoint
110
+ pps = application/mspowerpoint
111
+ ppt = application/mspowerpoint
112
+ ppz = application/mspowerpoint
113
+ pre = application/x-freelance
114
+ prf = application/pics-rules
115
+ prt = application/pro_eng
116
+ ps = application/postscript
117
+ pub = application/x-mspublisher
118
+ rar = application/x-rar
119
+ roff = application/x-troff
120
+ rtf = application/rtf
121
+ ruby = application/x-ruby
122
+ scd = application/x-msschedule
123
+ scm = application/x-lotusscreencam
124
+ set = application/set
125
+ setpay = application/set-payment-initiation
126
+ setreg = application/set-registration-initiation
127
+ sh = application/x-sh
128
+ shar = application/x-shar
129
+ sit = application/x-stuffit
130
+ skd = application/x-koan
131
+ skm = application/x-koan
132
+ skp = application/x-koan
133
+ skt = application/x-koan
134
+ smi = application/smil
135
+ smil = application/smil
136
+ sol = application/solids
137
+ spc = application/x-pkcs7-certificates
138
+ spl = application/x-futuresplash
139
+ src = application/x-wais-source
140
+ sst = application/vnd.ms-pkicertstore
141
+ step = application/STEP
142
+ stl = application/vnd.ms-pkistl
143
+ stp = application/STEP
144
+ sv4cpio = application/x-sv4cpio
145
+ sv4crc = application/x-sv4crc
146
+ swf = application/x-shockwave-flash
147
+ t = application/x-troff
148
+ tar = application/x-tar
149
+ tcl = application/x-tcl
150
+ tex = application/x-tex
151
+ texi = application/x-texinfo
152
+ texinfo = application/x-texinfo
153
+ ttf = application/x-truetype-font
154
+ tgz = application/x-compressed
155
+ tr = application/x-troff
156
+ trm = application/x-msterminal
157
+ tsp = application/dsptype
158
+ unv = application/i-deas
159
+ ustar = application/x-ustar
160
+ vcd = application/x-cdlink
161
+ vda = application/vda
162
+ wcm = application/vnd.ms-works
163
+ wdb = application/vnd.ms-works
164
+ wks = application/vnd.ms-works
165
+ wmf = application/x-msmetafile
166
+ wps = application/vnd.ms-works
167
+ wri = application/x-mswrite
168
+ xla = application/vnd.ms-excel
169
+ xlc = application/vnd.ms-excel
170
+ xlm = application/vnd.ms-excel
171
+ xls = application/vnd.ms-excel
172
+ xlt = application/vnd.ms-excel
173
+ xlw = application/vnd.ms-excel
174
+ z = application/x-compress
175
+ zip = application/zip
176
+
177
+ [audio]
178
+ aif = audio/x-aiff
179
+ aifc = audio/x-aiff
180
+ aiff = audio/x-aiff
181
+ au = audio/basic
182
+ kar = audio/midi
183
+ m3u = audio/x-mpegurl
184
+ mid = audio/midi
185
+ midi = audio/midi
186
+ mp2 = audio/mpeg
187
+ mp3 = audio/mpeg
188
+ mp4 = audio/mp4
189
+ mpga = audio/mpeg
190
+ ra = audio/x-pn-realaudio
191
+ ram = audio/x-pn-realaudio
192
+ rm = audio/x-pn-realaudio
193
+ rmi = audio/mid
194
+ rpm = audio/x-pn-realaudio-plugin
195
+ snd = audio/basic
196
+ tsi = audio/TSP-audio
197
+ wav = audio/x-wav
198
+ wma = audio/x-ms-wma
199
+ wmv = audio/x-ms-wmv
200
+
201
+ [text]
202
+ 323 = text/h323
203
+ asc = text/plain
204
+ c = text/plain
205
+ cc = text/plain
206
+ css = text/css
207
+ csv = text/comma-separated-values
208
+ bas = text/plain
209
+ etx = text/x-setext
210
+ f = text/plain
211
+ f90 = text/plain
212
+ h = text/plain
213
+ hh = text/plain
214
+ htc = text/x-component
215
+ htm = text/html
216
+ html = text/html
217
+ htt = text/webviewhtml
218
+ m = text/plain
219
+ rtx = text/richtext
220
+ sct = text/scriptlet
221
+ sgm = text/sgml
222
+ sgml = text/sgml
223
+ stm = text/html
224
+ tsv = text/tab-separated-values
225
+ tpl = text/template
226
+ txt = text/plain
227
+ uls = text/iuls
228
+ vcf = text/x-vcard
229
+ xml = text/xml
230
+
231
+ [video]
232
+ asf = video/x-ms-asf
233
+ asr = video/x-ms-asf
234
+ asx = video/x-ms-asf
235
+ avi = video/x-msvideo
236
+ fli = video/x-fli
237
+ flv = video/x-flv
238
+ f4a = video/mp4
239
+ f4b = video/mp4
240
+ f4v = video/mp4
241
+ f4p = video/mp4
242
+ lsf = video/x-la-asf
243
+ lsx = video/x-la-asf
244
+ mov = video/quicktime
245
+ movie = video/x-sgi-movie
246
+ mp2 = video/mpeg
247
+ mpa = video/mpeg
248
+ mpe = video/mpeg
249
+ mpeg = video/mpeg
250
+ mpg = video/mpeg
251
+ mpv2 = video/mpeg
252
+ qt = video/quicktime
253
+ viv = video/vnd.vivo
254
+ vivo = video/vnd.vivo
255
+ mp4 = video/mp4
256
+
257
+ [image]
258
+ bmp = image/bmp
259
+ cmx = image/x-cmx
260
+ cod = image/cis-cod
261
+ gif = image/gif
262
+ ico = image/x-icon
263
+ ief = image/ief
264
+ jfif = image/pipeg
265
+ jpe = image/jpeg
266
+ jpeg = image/jpeg
267
+ jpg = image/jpeg
268
+ pbm = image/x-portable-bitmap
269
+ pgm = image/x-portable-graymap
270
+ png = image/png
271
+ pnm = image/x-portable-anymap
272
+ ppm = image/x-portable-pixmap
273
+ ras = image/x-cmu-raster
274
+ rgb = image/x-rgb
275
+ svg = image/svg+xml
276
+ tif = image/tiff
277
+ tiff = image/tiff
278
+ xbm = image/x-xbitmap
279
+ xpm = image/x-xpixmap
280
+ xwd = image/x-xwindowdump
281
+
282
+ [x-conference]
283
+ ice = x-conference/x-cooltalk
284
+
285
+ [model]
286
+ iges = model/iges
287
+ igs = model/iges
288
+ mesh = model/mesh
289
+ msh = model/mesh
290
+ silo = model/mesh
291
+ vrml = model/vrml
292
+ wrl = model/vrml
293
+
294
+ [message]
295
+ mht = message/rfc822
296
+ mhtml = message/rfc822
297
+ nws = message/rfc822
298
+
299
+ [www]
300
+ mime = www/mime
301
+
302
+ [chemical]
303
+ pdb = chemical/x-pdb
304
+ xyz = chemical/x-pdb
305
+
306
+ [world]
307
+ flr = x-world/x-vrml
308
+ vrml = x-world/x-vrml
309
+ wrl = x-world/x-vrml
310
+ wrz = x-world/x-vrml
311
+ xaf = x-world/x-vrml
312
+ xbm = image/x-xbitmap
313
+ xof = x-world/x-vrml
includes/profile.inc.php ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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;
16
+ /*
17
+ Referenced by: /?s2member_profile=1
18
+ See: s2Member -> API Scripting -> PHP Constants
19
+ S2MEMBER_CURRENT_USER_PROFILE_MODIFICATION_PAGE_URL
20
+ */
21
+ $current_user = wp_get_current_user (); /* Current user. */
22
+ /**/
23
+ echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' . "\n";
24
+ /**/
25
+ echo '<html xmlns="http://www.w3.org/1999/xhtml">' . "\n";
26
+ echo '<head>' . "\n";
27
+ echo '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />' . "\n";
28
+ echo '<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>' . "\n";
29
+ echo '<script type="text/javascript" src="' . get_bloginfo ("url") . '/?ws_plugin__s2member_js_w_globals=1&amp;no-cache=' . urlencode (md5 (mt_rand ())) . '"></script>' . "\n";
30
+ /**/
31
+ echo '<title>My Profile</title>' . "\n";
32
+ echo '</head>' . "\n";
33
+ /**/
34
+ echo '<body style="background:#EEEEEE; color:#333333; font-family:verdana; font-size:13px;">' . "\n";
35
+ /**/
36
+ echo '<form method="post" name="ws_plugin__s2member_profile" id="ws-plugin--s2member-profile">' . "\n";
37
+ /**/
38
+ echo '<input type="hidden" name="ws_plugin__s2member_profile_save" id="ws-plugin--s2member-profile-save" value="' . esc_attr (wp_create_nonce ("ws-plugin--s2member-profile-save")) . '" />' . "\n";
39
+ /**/
40
+ echo '<table cellpadding="5" cellspacing="5" style="width:100%; border:0;">' . "\n";
41
+ echo '<tbody>' . "\n";
42
+ /**/
43
+ echo '<tr>' . "\n";
44
+ echo '<td>' . "\n";
45
+ echo '<label>' . "\n";
46
+ echo '<strong>Username *</strong> ( cannot be changed )<br />' . "\n";
47
+ echo '<input aria-required="true" type="text" maxlength="60" name="ws_plugin__s2member_profile_login" id="ws-plugin--s2member-profile-login" style="width:99%;" value="' . format_to_edit ($current_user->user_login) . '" disabled="disabled" />' . "\n";
48
+ echo '</label>' . "\n";
49
+ echo '</td>' . "\n";
50
+ echo '</tr>' . "\n";
51
+ /**/
52
+ echo '<tr>' . "\n";
53
+ echo '<td>' . "\n";
54
+ echo '<label>' . "\n";
55
+ echo '<strong>Email Address *</strong><br />' . "\n";
56
+ echo '<input aria-required="true" type="text" maxlength="100" name="ws_plugin__s2member_profile_email" id="ws-plugin--s2member-profile-email" style="width:99%;" value="' . format_to_edit ($current_user->user_email) . '" />' . "\n";
57
+ echo '</label>' . "\n";
58
+ echo '</td>' . "\n";
59
+ echo '</tr>' . "\n";
60
+ /**/
61
+ echo '<tr>' . "\n";
62
+ echo '<td>' . "\n";
63
+ echo '<label>' . "\n";
64
+ echo '<strong>First Name *</strong><br />' . "\n";
65
+ echo '<input aria-required="true" type="text" maxlength="100" name="ws_plugin__s2member_profile_first_name" id="ws-plugin--s2member-profile-first-name" style="width:99%;" value="' . format_to_edit ($current_user->user_firstname) . '" />' . "\n";
66
+ echo '</label>' . "\n";
67
+ echo '</td>' . "\n";
68
+ echo '</tr>' . "\n";
69
+ /**/
70
+ echo '<tr>' . "\n";
71
+ echo '<td>' . "\n";
72
+ echo '<label>' . "\n";
73
+ echo '<strong>Last Name *</strong><br />' . "\n";
74
+ echo '<input aria-required="true" type="text" maxlength="100" name="ws_plugin__s2member_profile_last_name" id="ws-plugin--s2member-profile-last-name" style="width:99%;" value="' . format_to_edit ($current_user->user_lastname) . '" />' . "\n";
75
+ echo '</label>' . "\n";
76
+ echo '</td>' . "\n";
77
+ echo '</tr>' . "\n";
78
+ /**/
79
+ $fields = get_usermeta ($current_user->ID, "s2member_custom_fields");
80
+ /**/
81
+ foreach (preg_split ("/[\r\n\t,;]+/", $GLOBALS["WS_PLUGIN__"]["s2member"]["o"]["custom_reg_fields"]) as $field)
82
+ {
83
+ $req = preg_match ("/\*/", $field); /* Required fields should be wrapped inside asterisks. */
84
+ $req = ($req) ? ' aria-required="true"' : ''; /* Has JavaScript validation applied. */
85
+ /**/
86
+ if ($field = trim ($field, "* \t\n\r\0\x0B")) /* Don't process empty fields. */
87
+ {
88
+ echo '<tr>' . "\n";
89
+ echo '<td>' . "\n";
90
+ echo '<label>' . "\n";
91
+ echo '<strong>' . esc_html ($field) . (($req) ? " *" : "") . '</strong><br />' . "\n";
92
+ $field = preg_replace ("/[^a-z0-9]/i", "_", strtolower ($field));
93
+ echo '<input' . $req . ' type="text" maxlength="100" name="ws_plugin__s2member_profile_' . esc_attr ($field) . '" id="ws-plugin--s2member-profile-' . esc_attr (preg_replace ("/_/", "-", $field)) . '" style="width:99%;" value="' . format_to_edit ($fields[$field]) . '" />' . "\n";
94
+ echo '</label>' . "\n";
95
+ echo '</td>' . "\n";
96
+ echo '</tr>' . "\n";
97
+ }
98
+ }
99
+ /**/
100
+ echo '<tr>' . "\n";
101
+ echo '<td>' . "\n";
102
+ echo '<label>' . "\n";
103
+ echo '<strong>New Password</strong> ( only if you want to change it )<br />' . "\n";
104
+ echo '<input type="password" maxlength="100" autocomplete="off" name="ws_plugin__s2member_profile_password" id="ws-plugin--s2member-profile-password" style="width:99%;" value="" />' . "\n";
105
+ echo '</label>' . "\n";
106
+ echo '</td>' . "\n";
107
+ echo '</tr>' . "\n";
108
+ /**/
109
+ echo '<tr>' . "\n";
110
+ echo '<td>' . "\n";
111
+ echo '<input type="submit" value="Save Changes" />' . "\n";
112
+ echo '</td>' . "\n";
113
+ echo '</tr>' . "\n";
114
+ /**/
115
+ echo '</tbody>' . "\n";
116
+ echo '</table>' . "\n";
117
+ /**/
118
+ echo '</form>' . "\n";
119
+ /**/
120
+ echo '</form>' . "\n";
121
+ /**/
122
+ echo '</body>' . "\n";
123
+ echo '</html>';
124
+ ?>
includes/s2member-min.js ADDED
@@ -0,0 +1 @@
 
1
+ "%%globals%%";jQuery(document).ready(function(a){s2member_unique_files_downloaded=[];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_free_file_download_key\=(.+)/)){var b="** Please Confirm This File Download **\n\n";b+="You've downloaded "+S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY+" 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":S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED+" unique")+" downloads every "+S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS+" day period.\n\n";if(confirm(b)){if(a.inArray(this.href,s2member_unique_files_downloaded)===-1){s2member_unique_files_downloaded.push(this.href),S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY++}return true}else{return false}}else{var b="This is a FREE download for members.\n";b+="It does not count against your membership entitlement.\n\n";b+="~Enjoy~";if(confirm(b)){return true}else{return false}}})}if(location.href.match(/\/wp-login\.php/)){a("div#login > form#registerform").submit(function(){var b="",c="";a("input[aria-required=true]",this).each(function(){if(!a.trim(this.value)&&(c=a.trim(a(this).parent("label").text().replace(/\*/,"")))){b+="• ( "+c+" ) is a required field.\n"}});if(b=a.trim(b)){alert("Oops, you missed something:\n\n"+b);return false}return true})}if(location.href.match(/\/\?s2member_profile\=1/)){a("form#ws-plugin--s2member-profile").submit(function(){var b="",c="";a("input[aria-required=true]",this).each(function(){if(!a.trim(this.value)&&(c=a.trim(a("strong",a(this).parent("label")).text().replace(/\*/,"")))){b+="• ( "+c+" ) is a required field.\n"}});if(b=a.trim(b)){alert("Oops, you missed something:\n\n"+b);return false}return true})}});
includes/s2member.js ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ Copyright: © 2009 WebSharks, Inc. ( coded in the USA )
3
+ <mailto:support@websharks-inc.com> <http://www.websharks-inc.com/>
4
+
5
+ Released under the terms of the GNU General Public License.
6
+ You should have received a copy of the GNU General Public License,
7
+ along with this software. In the main directory, see: /licensing/
8
+ If not, see: <http://www.gnu.org/licenses/>.
9
+ */
10
+ /*
11
+ Global variables, duplicated from PHP Contants.
12
+ These are inserted dynamically.
13
+ */
14
+ '%%globals%%';
15
+ /*
16
+ Other scripting routines handled on document ready state.
17
+ */
18
+ jQuery(document).ready (function($)
19
+ {
20
+ /*
21
+ Attach onclick handlers to download links.
22
+ Members will need to confirm download processing.
23
+ */
24
+ s2member_unique_files_downloaded = []; /* Maintains real-time counts. */
25
+ /* This is used in case a user downloads multiple files from a single page. */
26
+ /**/
27
+ if (S2MEMBER_CURRENT_USER_IS_LOGGED_IN && S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY < S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED)
28
+ {
29
+ $('a[href*=s2member_file_download]').click (function()
30
+ {
31
+ if (!this.href.match (/s2member_free_file_download_key\=(.+)/))
32
+ {
33
+ var c = '** Please Confirm This File Download **\n\n';
34
+ c += 'You\'ve downloaded ' + S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY + ' 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';
35
+ c += 'You\'re entitled to ' + ((S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_IS_UNLIMITED) ? 'unlimited' : S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED + ' unique') + ' downloads every ' + S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_DAYS + ' day period.\n\n';
36
+ /**/
37
+ if (confirm(c)) /* Force the user to confirm before we allow processing. */
38
+ {
39
+ if ($.inArray (this.href, s2member_unique_files_downloaded) === -1) /* Real-time counting. */
40
+ s2member_unique_files_downloaded.push (this.href), S2MEMBER_CURRENT_USER_DOWNLOADS_CURRENTLY++;
41
+ return true; /* Allow processing. */
42
+ }
43
+ else /* Do not process. */
44
+ return false;
45
+ }
46
+ else /* Else relax the user, this is free. */
47
+ {
48
+ var c = 'This is a FREE download for members.\n';
49
+ c += 'It does not count against your membership entitlement.\n\n';
50
+ c += '~Enjoy~';
51
+ /**/
52
+ if (confirm(c))
53
+ return true;
54
+ else /* ? */
55
+ return false;
56
+ }
57
+ });
58
+ }
59
+ /*
60
+ Attach form submission handler for registration validation.
61
+ */
62
+ if (location.href.match (/\/wp-login\.php/))
63
+ /**/
64
+ $('div#login > form#registerform').submit (function()
65
+ {
66
+ var fieldErrors = '', fieldLabel = '';
67
+ /**/
68
+ $('input[aria-required=true]', this).each (function()
69
+ {
70
+ if (!$.trim (this.value) && (fieldLabel = $.trim ($(this).parent ('label').text ().replace (/\*/, ''))))
71
+ fieldErrors += '• ( ' + fieldLabel + ' ) is a required field.\n';
72
+ });
73
+ /**/
74
+ if (fieldErrors = $.trim (fieldErrors))
75
+ {
76
+ alert('Oops, you missed something:\n\n' + fieldErrors);
77
+ return false;
78
+ }
79
+ /**/
80
+ return true;
81
+ });
82
+ /*
83
+ Attach form submission handler for profile modification validation.
84
+ */
85
+ if (location.href.match (/\/\?s2member_profile\=1/))
86
+ /**/
87
+ $('form#ws-plugin--s2member-profile').submit (function()
88
+ {
89
+ var fieldErrors = '', fieldLabel = '';
90
+ /**/
91
+ $('input[aria-required=true]', this).each (function()
92
+ {
93
+ if (!$.trim (this.value) && (fieldLabel = $.trim ($('strong', $(this).parent ('label')).text ().replace (/\*/, ''))))
94
+ fieldErrors += '• ( ' + fieldLabel + ' ) is a required field.\n';
95
+ });
96
+ /**/
97
+ if (fieldErrors = $.trim (fieldErrors))
98
+ {
99
+ alert('Oops, you missed something:\n\n' + fieldErrors);
100
+ return false;
101
+ }
102
+ /**/
103
+ return true;
104
+ });
105
+ });
includes/syscon.inc.php ADDED
@@ -0,0 +1,295 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ WARNING: This is a system configuration file, please DO NOT EDIT this file directly!
13
+ ... Instead, use the plugin options panel in WordPress® to override these settings.
14
+ */
15
+ /*
16
+ Direct access denial.
17
+ */
18
+ if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
19
+ exit;
20
+ /*
21
+ Detect if we are inside an MU installation.
22
+ */
23
+ if (($GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["is_wpmu"] = function_exists ("wpmu_current_site"))/**/
24
+ && (file_exists (dirname (dirname (__FILE__)) . "/wpmu.farm") || file_exists (TEMPLATEPATH . "/wpmu.farm")))
25
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["is_wpmu_farm"] = true; /* Requires /wpmu.farm file. */
26
+ /*
27
+ Determine the full url to the directory this plugin resides in.
28
+ */
29
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] = WP_CONTENT_URL . /* URL to the plugin directory. */
30
+ preg_replace ("/^(.*?)(\/" . preg_quote (basename (WP_CONTENT_DIR), "/") . ")/", "", dirname (dirname (__FILE__)));
31
+ /*
32
+ Check if the plugin has been configured *should be set after the first config via options panel*.
33
+ */
34
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["configured"] = get_option ("ws_plugin__s2member_configured");
35
+ /*
36
+ This is a special option cache that holds some additional information autoloaded into WordPress®.
37
+ */
38
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["cache"] = get_option ("ws_plugin__s2member_cache");
39
+ /*
40
+ Configure the right menu options panel for this software.
41
+ */
42
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["menu-r"] = array ("tools" => true, "tips" => true, "donations" => true);
43
+ /*
44
+ Configure the file modification time for the syscon.inc.php file.
45
+ */
46
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["filemtime"] = filemtime (__FILE__);
47
+ /*
48
+ Configure the directory for files protected by this plugin.
49
+ */
50
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["files_dir"] = dirname (dirname (__FILE__)) . "-files";
51
+ /*
52
+ Configure the directory for logs protected by this plugin.
53
+ */
54
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["logs_dir"] = dirname (dirname (__FILE__)) . "-logs";
55
+ /*
56
+ Configure & validate all of the plugin options; and set their defaults.
57
+ */
58
+ function ws_plugin__s2member_configure_options_and_their_defaults ($options = FALSE) /* Can also be used to merge options with defaults. */
59
+ {
60
+ /* Here we build the default options array, which will be merged with the user options.
61
+ It is important to note that sometimes default options may not or should not be pre-filled on an options form.
62
+ These defaults are for the system to use in various ways, we may choose not to pre-fill certain fields.
63
+ In other words, some defaults may be used internally, but to the user, the option will be empty. */
64
+ $default_options = array ( /* Please comment each line for clarity, it is easy to forget things. */
65
+ /**/
66
+ "options_version" => "1.0", /* Used internally to keep runtime files up-to-date. */
67
+ /**/
68
+ "run_deactivation_routines" => "1", /* Should deactivation routines be processed? */
69
+ /**/
70
+ "custom_reg_fields" => "", /* A comma delimited list of custom fields to collect/use. */
71
+ "custom_reg_password" => "0", /* Allow users to register their own custom password? */
72
+ /**/
73
+ "allow_subscribers_in" => "0", /* Allow subscribers to access the login_welcome_page ? */
74
+ /**/
75
+ "login_welcome_page" => "", /* Preceded by bloginfo("url"). Defaults to the home page. */
76
+ "login_redirection_override" => "", /* Alternate redirection location; instead of the welcome page. */
77
+ "membership_options_page" => "", /* Preceded by bloginfo("url"). Defaults to the home page. */
78
+ "file_download_limit_exceeded_page" => "", /* Preceded by bloginfo("url"). Defaults to the home page. */
79
+ /**/
80
+ "login_reg_background_color" => "FFFFFF", /* Defaults to white, and the bg.png is also white. */
81
+ "login_reg_background_image" => $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images/bg.png",/**/
82
+ "login_reg_background_text_color" => "000000", /* Defaults to black, which is high contrast on white. */
83
+ "login_reg_background_text_shadow_color" => "CCCCCC", /* Defaults to gray, which is slightly visible. */
84
+ "login_reg_background_box_shadow_color" => "CCCCCC", /* Defaults to gray, which is slightly visible. */
85
+ /**/
86
+ "login_reg_logo_src" => $GLOBALS["WS_PLUGIN__"]["s2member"]["c"]["dir_url"] . "/images/logo.png",/**/
87
+ "login_reg_logo_src_width" => "350", /* Defaults to the logo_src image width. */
88
+ "login_reg_logo_src_height" => "100", /* Defaults to the logo_src image height. */
89
+ "login_reg_logo_url" => get_bloginfo ("url"), /* Defaults to the site url. */
90
+ "login_reg_logo_title" => get_bloginfo ("name"), /* Defaults to the site name. */
91
+ /**/
92
+ "reg_email_from_name" => get_bloginfo ("name"), /* Defaults to the site name. */
93
+ "reg_email_from_email" => get_bloginfo ("admin_email"), /* Defaults to the admin. */
94
+ /**/
95
+ "paypal_debug" => "0", /* Use the PayPal debug/logs for development testing? */
96
+ "paypal_sandbox" => "0", /* Use the PayPal sandbox for development testing? */
97
+ "paypal_business" => "", /* Paypal business email address for their account. */
98
+ "paypal_identity_token" => "", /* Paypal payment data transfer identity token. */
99
+ /**/
100
+ "signup_pixel_tracking_codes" => "", /* s2Member pixel tracking codes. */
101
+ /**/
102
+ "signup_email_subject" => "Congratulations! Your membership has been approved.",/**/
103
+ "signup_email_message" => "Thanks %%first_name%%! Your membership has been approved.\n\nIf you haven't already done so, the next step is to Register a Username.\n\nComplete your registration here:\n%%registration_url%%\n\nIf you have any trouble, please feel free to contact us.\n\nBest Regards,\n" . get_bloginfo ("name"),/**/
104
+ /**/
105
+ "signup_notification_urls" => "", /* s2Member signup notification urls. */
106
+ "payment_notification_urls" => "", /* s2Member payment notification urls. */
107
+ "eot_del_notification_urls" => "", /* s2Member eot/del notification urls. */
108
+ "ref_rev_notification_urls" => "", /* s2Member ref/rev notification urls. */
109
+ /**/
110
+ "level1_label" => "Bronze", /* This is just an initial generic level label. */
111
+ "level2_label" => "Silver", /* This is just an initial generic level label. */
112
+ "level3_label" => "Gold", /* This is just an initial generic level label. */
113
+ "level4_label" => "Platinum", /* This is just an initial generic level label. */
114
+ /**/
115
+ "level1_file_downloads_allowed" => "", /* This should always be numeric or empty. */
116
+ "level2_file_downloads_allowed" => "", /* This should always be numeric or empty. */
117
+ "level3_file_downloads_allowed" => "", /* This should always be numeric or empty. */
118
+ "level4_file_downloads_allowed" => "", /* This should always be numeric or empty. */
119
+ /**/
120
+ "level1_file_downloads_allowed_days" => "", /* This should be numeric or empty. */
121
+ "level2_file_downloads_allowed_days" => "", /* This should be numeric or empty. */
122
+ "level3_file_downloads_allowed_days" => "", /* This should be numeric or empty. */
123
+ "level4_file_downloads_allowed_days" => "", /* This should be numeric or empty. */
124
+ /**/
125
+ "level1_ruris" => "", /* It is ok for these to just be empty strings. */
126
+ "level2_ruris" => "", /* It is ok for these to just be empty strings. */
127
+ "level3_ruris" => "", /* It is ok for these to just be empty strings. */
128
+ "level4_ruris" => "", /* It is ok for these to just be empty strings. */
129
+ /**/
130
+ "level1_catgs" => "", /* It is ok for these to just be empty strings. */
131
+ "level2_catgs" => "", /* It is ok for these to just be empty strings. */
132
+ "level3_catgs" => "", /* It is ok for these to just be empty strings. */
133
+ "level4_catgs" => "", /* It is ok for these to just be empty strings. */
134
+ /**/
135
+ "level1_ptags" => "", /* It is ok for these to just be empty strings. */
136
+ "level2_ptags" => "", /* It is ok for these to just be empty strings. */
137
+ "level3_ptags" => "", /* It is ok for these to just be empty strings. */
138
+ "level4_ptags" => "", /* It is ok for these to just be empty strings. */
139
+ /**/
140
+ "level1_posts" => "", /* It is ok for these to just be empty strings. */
141
+ "level2_posts" => "", /* It is ok for these to just be empty strings. */
142
+ "level3_posts" => "", /* It is ok for these to just be empty strings. */
143
+ "level4_posts" => "", /* It is ok for these to just be empty strings. */
144
+ /**/
145
+ "level1_pages" => "", /* It is ok for these to just be empty strings. */
146
+ "level2_pages" => "", /* It is ok for these to just be empty strings. */
147
+ "level3_pages" => "", /* It is ok for these to just be empty strings. */
148
+ "level4_pages" => ""); /* It is ok for these to just be empty strings. */
149
+ /*
150
+ Here they are merged. user options will overwrite some or all default values.
151
+ */
152
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["o"] = array_merge ($default_options, (($options !== false) ? (array)$options : (array)get_option ("ws_plugin__s2member_options")));
153
+ /*
154
+ Validate each option, possibly reverting back to the default value if invalid.
155
+ Also check if options were passed in on some of these, in case empty values are to be allowed.
156
+ */
157
+ foreach ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"] as $key => &$value)
158
+ {
159
+ if (!is_array ($value))
160
+ $value = trim (stripslashes ($value));
161
+ else /* A string, or an array of strings. */
162
+ foreach ($value as $k => $v)
163
+ $value[$k] = trim (stripslashes ($v));
164
+ /**/
165
+ if (!isset ($default_options[$key]))
166
+ unset ($GLOBALS["WS_PLUGIN__"]["s2member"]["o"][$key]);
167
+ /**/
168
+ else if ($key === "options_version" && (!is_string ($value) || !is_numeric ($value)))
169
+ $value = $default_options[$key];
170
+ /**/
171
+ else if ($key === "run_deactivation_routines" && (!is_string ($value) || !is_numeric ($value)))
172
+ $value = $default_options[$key];
173
+ /**/
174
+ else if ($key === "custom_reg_fields" && (!is_string ($value) || !strlen ($value)))
175
+ $value = $default_options[$key];
176
+ /**/
177
+ else if ($key === "custom_reg_password" && (!is_string ($value) || !is_numeric ($value)))
178
+ $value = $default_options[$key];
179
+ /**/
180
+ else if ($key === "allow_subscribers_in" && (!is_string ($value) || !is_numeric ($value)))
181
+ $value = $default_options[$key];
182
+ /**/
183
+ else if ($key === "login_welcome_page" && (!is_string ($value) || !is_numeric ($value)))
184
+ $value = $default_options[$key];
185
+ /**/
186
+ else if ($key === "login_redirection_override" && (!is_string ($value) || !strlen ($value)))
187
+ $value = $default_options[$key];
188
+ /**/
189
+ else if ($key === "membership_options_page" && (!is_string ($value) || !is_numeric ($value)))
190
+ $value = $default_options[$key];
191
+ /**/
192
+ else if ($key === "file_download_limit_exceeded_page" && (!is_string ($value) || !is_numeric ($value)))
193
+ $value = $default_options[$key];
194
+ /**/
195
+ else if ($key === "login_reg_background_color" && (!is_string ($value) || !strlen ($value)))
196
+ $value = $default_options[$key];
197
+ /**/
198
+ else if ($key === "login_reg_background_image" && (!is_string ($value) || !strlen ($value)))
199
+ $value = $default_options[$key];
200
+ /**/
201
+ else if ($key === "login_reg_logo_src" && (!is_string ($value) || !strlen ($value)))
202
+ $value = $default_options[$key];
203
+ /**/
204
+ else if ($key === "login_reg_logo_src_width" && (!is_string ($value) || !is_numeric ($value)))
205
+ $value = $default_options[$key];
206
+ /**/
207
+ else if ($key === "login_reg_logo_src_height" && (!is_string ($value) || !is_numeric ($value)))
208
+ $value = $default_options[$key];
209
+ /**/
210
+ else if ($key === "login_reg_logo_url" && (!is_string ($value) || !strlen ($value)))
211
+ $value = $default_options[$key];
212
+ /**/
213
+ else if ($key === "login_reg_logo_title" && (!is_string ($value) || !strlen ($value)))
214
+ $value = $default_options[$key];
215
+ /**/
216
+ else if ($key === "reg_email_from_name" && (!is_string ($value) || !strlen ($value)))
217
+ $value = $default_options[$key];
218
+ /**/
219
+ else if ($key === "reg_email_from_email" && (!is_string ($value) || !strlen ($value)))
220
+ $value = $default_options[$key];
221
+ /**/
222
+ else if ($key === "paypal_debug" && (!is_string ($value) || !is_numeric ($value)))
223
+ $value = $default_options[$key];
224
+ /**/
225
+ else if ($key === "paypal_sandbox" && (!is_string ($value) || !is_numeric ($value)))
226
+ $value = $default_options[$key];
227
+ /**/
228
+ else if ($key === "paypal_business" && (!is_string ($value) || !strlen ($value)))
229
+ $value = $default_options[$key];
230
+ /**/
231
+ else if ($key === "paypal_identity_token" && (!is_string ($value) || !strlen ($value)))
232
+ $value = $default_options[$key];
233
+ /**/
234
+ else if ($key === "signup_pixel_tracking_codes" && (!is_string ($value) || !strlen ($value)))
235
+ $value = $default_options[$key];
236
+ /**/
237
+ else if ($key === "signup_email_subject" && (!is_string ($value) || !strlen ($value)))
238
+ $value = $default_options[$key];
239
+ /**/
240
+ else if ($key === "signup_email_message" && (!is_string ($value) || !strlen ($value)))
241
+ $value = $default_options[$key];
242
+ /**/
243
+ else if ($key === "signup_notification_urls" && (!is_string ($value) || !strlen ($value)))
244
+ $value = $default_options[$key];
245
+ /**/
246
+ else if ($key === "payment_notification_urls" && (!is_string ($value) || !strlen ($value)))
247
+ $value = $default_options[$key];
248
+ /**/
249
+ else if ($key === "eot_del_notification_urls" && (!is_string ($value) || !strlen ($value)))
250
+ $value = $default_options[$key];
251
+ /**/
252
+ else if ($key === "ref_rev_notification_urls" && (!is_string ($value) || !strlen ($value)))
253
+ $value = $default_options[$key];
254
+ /**/
255
+ else if ($key === "level1_label" && (!is_string ($value) || !strlen ($value)))
256
+ $value = $default_options[$key];
257
+ /**/
258
+ else if ($key === "level2_label" && (!is_string ($value) || !strlen ($value)))
259
+ $value = $default_options[$key];
260
+ /**/
261
+ else if ($key === "level3_label" && (!is_string ($value) || !strlen ($value)))
262
+ $value = $default_options[$key];
263
+ /**/
264
+ else if ($key === "level4_label" && (!is_string ($value) || !strlen ($value)))
265
+ $value = $default_options[$key];
266
+ /**/
267
+ else if (preg_match ("/level[1-4]_file_downloads_allowed$/", $key) && (!is_string ($value) || !is_numeric ($value) || $value < 0))
268
+ $value = $default_options[$key];
269
+ /**/
270
+ else if (preg_match ("/level[1-4]_file_downloads_allowed_days$/", $key) && (!is_string ($value) || !is_numeric ($value) || $value < 0))
271
+ $value = $default_options[$key];
272
+ /**/
273
+ else if (preg_match ("/level[1-4]_ruris$/", $key) && (!is_string ($value) || !strlen ($value)))
274
+ $value = $default_options[$key];
275
+ /**/
276
+ else if (preg_match ("/level[1-4]_catgs$/", $key) && (!is_string ($value) || !($value = (($value === "all") ? $value : preg_replace ("/[^0-9,]/", "", $value)))))
277
+ $value = $default_options[$key];
278
+ /**/
279
+ else if (preg_match ("/level[1-4]_ptags$/", $key) && (!is_string ($value) || !($value = (($value === "all") ? $value : strtolower (preg_replace ("/( +)/", " ", trim (preg_replace ("/( *),( *)/", ",", $value))))))))
280
+ $value = $default_options[$key];
281
+ /**/
282
+ else if (preg_match ("/level[1-4]_posts$/", $key) && (!is_string ($value) || !($value = (($value === "all") ? $value : preg_replace ("/[^0-9,]/", "", $value)))))
283
+ $value = $default_options[$key];
284
+ /**/
285
+ else if (preg_match ("/level[1-4]_pages$/", $key) && (!is_string ($value) || !($value = (($value === "all") ? $value : preg_replace ("/[^0-9,]/", "", $value)))))
286
+ $value = $default_options[$key];
287
+ }
288
+ /**/
289
+ return $GLOBALS["WS_PLUGIN__"]["s2member"]["o"];
290
+ }
291
+ /*
292
+ Now lets call the function.
293
+ */
294
+ call_user_func ("ws_plugin__s2member_configure_options_and_their_defaults");
295
+ ?>
index.php ADDED
File without changes
licensing/gpl.txt ADDED
@@ -0,0 +1,339 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ GNU GENERAL PUBLIC LICENSE
2
+ Version 2, June 1991
3
+
4
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6
+ Everyone is permitted to copy and distribute verbatim copies
7
+ of this license document, but changing it is not allowed.
8
+
9
+ Preamble
10
+
11
+ The licenses for most software are designed to take away your
12
+ freedom to share and change it. By contrast, the GNU General Public
13
+ License is intended to guarantee your freedom to share and change free
14
+ software--to make sure the software is free for all its users. This
15
+ General Public License applies to most of the Free Software
16
+ Foundation's software and to any other program whose authors commit to
17
+ using it. (Some other Free Software Foundation software is covered by
18
+ the GNU Lesser General Public License instead.) You can apply it to
19
+ your programs, too.
20
+
21
+ When we speak of free software, we are referring to freedom, not
22
+ price. Our General Public Licenses are designed to make sure that you
23
+ have the freedom to distribute copies of free software (and charge for
24
+ this service if you wish), that you receive source code or can get it
25
+ if you want it, that you can change the software or use pieces of it
26
+ in new free programs; and that you know you can do these things.
27
+
28
+ To protect your rights, we need to make restrictions that forbid
29
+ anyone to deny you these rights or to ask you to surrender the rights.
30
+ These restrictions translate to certain responsibilities for you if you
31
+ distribute copies of the software, or if you modify it.
32
+
33
+ For example, if you distribute copies of such a program, whether
34
+ gratis or for a fee, you must give the recipients all the rights that
35
+ you have. You must make sure that they, too, receive or can get the
36
+ source code. And you must show them these terms so they know their
37
+ rights.
38
+
39
+ We protect your rights with two steps: (1) copyright the software, and
40
+ (2) offer you this license which gives you legal permission to copy,
41
+ distribute and/or modify the software.
42
+
43
+ Also, for each author's protection and ours, we want to make certain
44
+ that everyone understands that there is no warranty for this free
45
+ software. If the software is modified by someone else and passed on, we
46
+ want its recipients to know that what they have is not the original, so
47
+ that any problems introduced by others will not reflect on the original
48
+ authors' reputations.
49
+
50
+ Finally, any free program is threatened constantly by software
51
+ patents. We wish to avoid the danger that redistributors of a free
52
+ program will individually obtain patent licenses, in effect making the
53
+ program proprietary. To prevent this, we have made it clear that any
54
+ patent must be licensed for everyone's free use or not licensed at all.
55
+
56
+ The precise terms and conditions for copying, distribution and
57
+ modification follow.
58
+
59
+ GNU GENERAL PUBLIC LICENSE
60
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61
+
62
+ 0. This License applies to any program or other work which contains
63
+ a notice placed by the copyright holder saying it may be distributed
64
+ under the terms of this General Public License. The "Program", below,
65
+ refers to any such program or work, and a "work based on the Program"
66
+ means either the Program or any derivative work under copyright law:
67
+ that is to say, a work containing the Program or a portion of it,
68
+ either verbatim or with modifications and/or translated into another
69
+ language. (Hereinafter, translation is included without limitation in
70
+ the term "modification".) Each licensee is addressed as "you".
71
+
72
+ Activities other than copying, distribution and modification are not
73
+ covered by this License; they are outside its scope. The act of
74
+ running the Program is not restricted, and the output from the Program
75
+ is covered only if its contents constitute a work based on the
76
+ Program (independent of having been made by running the Program).
77
+ Whether that is true depends on what the Program does.
78
+
79
+ 1. You may copy and distribute verbatim copies of the Program's
80
+ source code as you receive it, in any medium, provided that you
81
+ conspicuously and appropriately publish on each copy an appropriate
82
+ copyright notice and disclaimer of warranty; keep intact all the
83
+ notices that refer to this License and to the absence of any warranty;
84
+ and give any other recipients of the Program a copy of this License
85
+ along with the Program.
86
+
87
+ You may charge a fee for the physical act of transferring a copy, and
88
+ you may at your option offer warranty protection in exchange for a fee.
89
+
90
+ 2. You may modify your copy or copies of the Program or any portion
91
+ of it, thus forming a work based on the Program, and copy and
92
+ distribute such modifications or work under the terms of Section 1
93
+ above, provided that you also meet all of these conditions:
94
+
95
+ a) You must cause the modified files to carry prominent notices
96
+ stating that you changed the files and the date of any change.
97
+
98
+ b) You must cause any work that you distribute or publish, that in
99
+ whole or in part contains or is derived from the Program or any
100
+ part thereof, to be licensed as a whole at no charge to all third
101
+ parties under the terms of this License.
102
+
103
+ c) If the modified program normally reads commands interactively
104
+ when run, you must cause it, when started running for such
105
+ interactive use in the most ordinary way, to print or display an
106
+ announcement including an appropriate copyright notice and a
107
+ notice that there is no warranty (or else, saying that you provide
108
+ a warranty) and that users may redistribute the program under
109
+ these conditions, and telling the user how to view a copy of this
110
+ License. (Exception: if the Program itself is interactive but
111
+ does not normally print such an announcement, your work based on
112
+ the Program is not required to print an announcement.)
113
+
114
+ These requirements apply to the modified work as a whole. If
115
+ identifiable sections of that work are not derived from the Program,
116
+ and can be reasonably considered independent and separate works in
117
+ themselves, then this License, and its terms, do not apply to those
118
+ sections when you distribute them as separate works. But when you
119
+ distribute the same sections as part of a whole which is a work based
120
+ on the Program, the distribution of the whole must be on the terms of
121
+ this License, whose permissions for other licensees extend to the
122
+ entire whole, and thus to each and every part regardless of who wrote it.
123
+
124
+ Thus, it is not the intent of this section to claim rights or contest
125
+ your rights to work written entirely by you; rather, the intent is to
126
+ exercise the right to control the distribution of derivative or
127
+ collective works based on the Program.
128
+
129
+ In addition, mere aggregation of another work not based on the Program
130
+ with the Program (or with a work based on the Program) on a volume of
131
+ a storage or distribution medium does not bring the other work under
132
+ the scope of this License.
133
+
134
+ 3. You may copy and distribute the Program (or a work based on it,
135
+ under Section 2) in object code or executable form under the terms of
136
+ Sections 1 and 2 above provided that you also do one of the following:
137
+
138
+ a) Accompany it with the complete corresponding machine-readable
139
+ source code, which must be distributed under the terms of Sections
140
+ 1 and 2 above on a medium customarily used for software interchange; or,
141
+
142
+ b) Accompany it with a written offer, valid for at least three
143
+ years, to give any third party, for a charge no more than your
144
+ cost of physically performing source distribution, a complete
145
+ machine-readable copy of the corresponding source code, to be
146
+ distributed under the terms of Sections 1 and 2 above on a medium
147
+ customarily used for software interchange; or,
148
+
149
+ c) Accompany it with the information you received as to the offer
150
+ to distribute corresponding source code. (This alternative is
151
+ allowed only for noncommercial distribution and only if you
152
+ received the program in object code or executable form with such
153
+ an offer, in accord with Subsection b above.)
154
+
155
+ The source code for a work means the preferred form of the work for
156
+ making modifications to it. For an executable work, complete source
157
+ code means all the source code for all modules it contains, plus any
158
+ associated interface definition files, plus the scripts used to
159
+ control compilation and installation of the executable. However, as a
160
+ special exception, the source code distributed need not include
161
+ anything that is normally distributed (in either source or binary
162
+ form) with the major components (compiler, kernel, and so on) of the
163
+ operating system on which the executable runs, unless that component
164
+ itself accompanies the executable.
165
+
166
+ If distribution of executable or object code is made by offering
167
+ access to copy from a designated place, then offering equivalent
168
+ access to copy the source code from the same place counts as
169
+ distribution of the source code, even though third parties are not
170
+ compelled to copy the source along with the object code.
171
+
172
+ 4. You may not copy, modify, sublicense, or distribute the Program
173
+ except as expressly provided under this License. Any attempt
174
+ otherwise to copy, modify, sublicense or distribute the Program is
175
+ void, and will automatically terminate your rights under this License.
176
+ However, parties who have received copies, or rights, from you under
177
+ this License will not have their licenses terminated so long as such
178
+ parties remain in full compliance.
179
+
180
+ 5. You are not required to accept this License, since you have not
181
+ signed it. However, nothing else grants you permission to modify or
182
+ distribute the Program or its derivative works. These actions are
183
+ prohibited by law if you do not accept this License. Therefore, by
184
+ modifying or distributing the Program (or any work based on the
185
+ Program), you indicate your acceptance of this License to do so, and
186
+ all its terms and conditions for copying, distributing or modifying
187
+ the Program or works based on it.
188
+
189
+ 6. Each time you redistribute the Program (or any work based on the
190
+ Program), the recipient automatically receives a license from the
191
+ original licensor to copy, distribute or modify the Program subject to
192
+ these terms and conditions. You may not impose any further
193
+ restrictions on the recipients' exercise of the rights granted herein.
194
+ You are not responsible for enforcing compliance by third parties to
195
+ this License.
196
+
197
+ 7. If, as a consequence of a court judgment or allegation of patent
198
+ infringement or for any other reason (not limited to patent issues),
199
+ conditions are imposed on you (whether by court order, agreement or
200
+ otherwise) that contradict the conditions of this License, they do not
201
+ excuse you from the conditions of this License. If you cannot
202
+ distribute so as to satisfy simultaneously your obligations under this
203
+ License and any other pertinent obligations, then as a consequence you
204
+ may not distribute the Program at all. For example, if a patent
205
+ license would not permit royalty-free redistribution of the Program by
206
+ all those who receive copies directly or indirectly through you, then
207
+ the only way you could satisfy both it and this License would be to
208
+ refrain entirely from distribution of the Program.
209
+
210
+ If any portion of this section is held invalid or unenforceable under
211
+ any particular circumstance, the balance of the section is intended to
212
+ apply and the section as a whole is intended to apply in other
213
+ circumstances.
214
+
215
+ It is not the purpose of this section to induce you to infringe any
216
+ patents or other property right claims or to contest validity of any
217
+ such claims; this section has the sole purpose of protecting the
218
+ integrity of the free software distribution system, which is
219
+ implemented by public license practices. Many people have made
220
+ generous contributions to the wide range of software distributed
221
+ through that system in reliance on consistent application of that
222
+ system; it is up to the author/donor to decide if he or she is willing
223
+ to distribute software through any other system and a licensee cannot
224
+ impose that choice.
225
+
226
+ This section is intended to make thoroughly clear what is believed to
227
+ be a consequence of the rest of this License.
228
+
229
+ 8. If the distribution and/or use of the Program is restricted in
230
+ certain countries either by patents or by copyrighted interfaces, the
231
+ original copyright holder who places the Program under this License
232
+ may add an explicit geographical distribution limitation excluding
233
+ those countries, so that distribution is permitted only in or among
234
+ countries not thus excluded. In such case, this License incorporates
235
+ the limitation as if written in the body of this License.
236
+
237
+ 9. The Free Software Foundation may publish revised and/or new versions
238
+ of the General Public License from time to time. Such new versions will
239
+ be similar in spirit to the present version, but may differ in detail to
240
+ address new problems or concerns.
241
+
242
+ Each version is given a distinguishing version number. If the Program
243
+ specifies a version number of this License which applies to it and "any
244
+ later version", you have the option of following the terms and conditions
245
+ either of that version or of any later version published by the Free
246
+ Software Foundation. If the Program does not specify a version number of
247
+ this License, you may choose any version ever published by the Free Software
248
+ Foundation.
249
+
250
+ 10. If you wish to incorporate parts of the Program into other free
251
+ programs whose distribution conditions are different, write to the author
252
+ to ask for permission. For software which is copyrighted by the Free
253
+ Software Foundation, write to the Free Software Foundation; we sometimes
254
+ make exceptions for this. Our decision will be guided by the two goals
255
+ of preserving the free status of all derivatives of our free software and
256
+ of promoting the sharing and reuse of software generally.
257
+
258
+ NO WARRANTY
259
+
260
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261
+ FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262
+ OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263
+ PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264
+ OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266
+ TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267
+ PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268
+ REPAIR OR CORRECTION.
269
+
270
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272
+ REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273
+ INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274
+ OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275
+ TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276
+ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277
+ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278
+ POSSIBILITY OF SUCH DAMAGES.
279
+
280
+ END OF TERMS AND CONDITIONS
281
+
282
+ How to Apply These Terms to Your New Programs
283
+
284
+ If you develop a new program, and you want it to be of the greatest
285
+ possible use to the public, the best way to achieve this is to make it
286
+ free software which everyone can redistribute and change under these terms.
287
+
288
+ To do so, attach the following notices to the program. It is safest
289
+ to attach them to the start of each source file to most effectively
290
+ convey the exclusion of warranty; and each file should have at least
291
+ the "copyright" line and a pointer to where the full notice is found.
292
+
293
+ <one line to give the program's name and a brief idea of what it does.>
294
+ Copyright (C) <year> <name of author>
295
+
296
+ This program is free software; you can redistribute it and/or modify
297
+ it under the terms of the GNU General Public License as published by
298
+ the Free Software Foundation; either version 2 of the License, or
299
+ (at your option) any later version.
300
+
301
+ This program is distributed in the hope that it will be useful,
302
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
303
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304
+ GNU General Public License for more details.
305
+
306
+ You should have received a copy of the GNU General Public License along
307
+ with this program; if not, write to the Free Software Foundation, Inc.,
308
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309
+
310
+ Also add information on how to contact you by electronic and paper mail.
311
+
312
+ If the program is interactive, make it output a short notice like this
313
+ when it starts in an interactive mode:
314
+
315
+ Gnomovision version 69, Copyright (C) year name of author
316
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317
+ This is free software, and you are welcome to redistribute it
318
+ under certain conditions; type `show c' for details.
319
+
320
+ The hypothetical commands `show w' and `show c' should show the appropriate
321
+ parts of the General Public License. Of course, the commands you use may
322
+ be called something other than `show w' and `show c'; they could even be
323
+ mouse-clicks or menu items--whatever suits your program.
324
+
325
+ You should also get your employer (if you work as a programmer) or your
326
+ school, if any, to sign a "copyright disclaimer" for the program, if
327
+ necessary. Here is a sample; alter the names:
328
+
329
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
331
+
332
+ <signature of Ty Coon>, 1 April 1989
333
+ Ty Coon, President of Vice
334
+
335
+ This General Public License does not permit incorporating your program into
336
+ proprietary programs. If your program is a subroutine library, you may
337
+ consider it more useful to permit linking proprietary applications with the
338
+ library. If this is what you want to do, use the GNU Lesser General
339
+ Public License instead of this License.
licensing/index.php ADDED
File without changes
licensing/license.txt ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright: © 2009 WebSharks, Inc. ( coded in the USA )
2
+ <mailto:support@websharks-inc.com> <http://www.websharks-inc.com/>
3
+
4
+ Released under the terms of the GNU General Public License.
5
+ <http://www.gnu.org/licenses/> - attached as [gpl.txt].
6
+
7
+ Credits / Additional Acknowledgments:
8
+
9
+ * Software designed for WordPress®.
10
+ - GPL License <http://codex.wordpress.org/GPL>
11
+ - WordPress® <http://wordpress.org>
12
+
13
+ * JavaScript extensions require jQuery.
14
+ - GPL License <http://jquery.org/license>
15
+ - jQuery <http://jquery.com/>
16
+
17
+ * Readme parsing routines, powered (in part) by PHP Markdown.
18
+ - BSD / GPL Compatible License <http://michelf.com/projects/php-markdown/license/>
19
+ - PHP Markdown <http://michelf.com/projects/php-markdown/>
20
+
21
+ * Administration panel (tools icon) was provided by Everaldo.com.
22
+ - LGPL License <http://www.everaldo.com/crystal/?action=license>
23
+ - Everaldo <http://www.everaldo.com/crystal/?action=downloads>
24
+
25
+ * PayPal® and its associated buttons & services have been integrated into this software via external hyperlinks.
26
+ The files/services provided by PayPal® are not distributed with this software. They have their own terms & conditions.
27
+ - PayPal®, a 3rd party service, is powered by eBay, Inc. <http://www.paypal.com/>
28
+ - PayPal® is a trademark of eBay, Inc. <http://www.ebay.com/>
29
+
30
+ * The W3C® and its associated validator & services have been integrated into this software via external hyperlinks.
31
+ The files/services provided by the W3C® are not distributed with this software. They have their own terms & conditions.
32
+ - The W3C®, a 3rd party service, is powered by the World Wide Web Consortium <http://validator.w3.org/>
33
+ - W3C® is a trademark of the World Wide Web Consortium. <http://www.w3.org/>
readme.txt ADDED
@@ -0,0 +1,249 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ === s2Member ( Membership w/ PayPal Integration ) also works w/ BuddyPress ===
2
+
3
+ Version: 2.8.4
4
+ Framework: P-2.1
5
+ Stable tag: 2.8.4
6
+
7
+ WordPress Compatible: yes
8
+ BuddyPress Compatible: yes
9
+ WordPress MU Compatible: yes
10
+ MU Blog Farm Compatible: soon
11
+
12
+ Tested up to: 2.9
13
+ Requires at least: 2.8.4
14
+ Requires: WordPress® 2.8.4+, PHP 5.2+
15
+
16
+ Copyright: © 2009 WebSharks, Inc.
17
+ License: GNU General Public License
18
+ Contributors: WebSharks, PriMoThemes
19
+ Author URI: http://www.primothemes.com/
20
+ Author: PriMoThemes.com / WebSharks, Inc.
21
+ Donate link: http://www.primothemes.com/donate/
22
+
23
+ ZipId: s2member
24
+ FolderId: s2member
25
+ Plugin Name: s2Member
26
+ Plugin URI: http://www.primothemes.com/post/s2member-membership-plugin-with-paypal/
27
+ Customization URI: http://www.primothemes.com/post/s2member-membership-plugin-with-paypal/#comments
28
+ Description: Empowers WordPress® with membership capabilities. Integrates seamlessly with PayPal®. Also compatible with the BuddyPress plugin for WP.
29
+ 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, multi widget support, includes extensive documentation, highly extensible
30
+
31
+ s2Member is a full-featured membership management system for WordPress®. It empowers WordPress® with membership capabilities, integrating seamlessly with PayPal®. s2Member is also compatible with BuddyPress.
32
+
33
+ == Installation ==
34
+
35
+ 1. Upload the `/s2member` folder to your `/wp-content/plugins/` directory.
36
+ 2. Activate the plugin through the `Plugins` menu in WordPress®.
37
+ 3. Navigate to the `s2Member Options` panel for configuration details.
38
+
39
+ ***Special instructions for WordPress® MU:** If you're installing this plugin on WordPress® MU, and you run a Blog Farm ( e.g. you give away free blogs to the public ), you should create a file in this plugin's directory, and name it: `wpmu.farm`. When this plugin is running under WordPress® MU, and that file ( `wpmu.farm` ) is present, the plugin will disable PHP code evaluation on data provided by the user, and it will tell the plugin to mutate itself ( including its menus ) for compatiblity with public Blog Farms. You don't need to do this unless you run a public Blog Farm. If you're running the standard version of WordPress®, or you run WordPress® MU to host your own sites, you can safely skip this step.*
40
+
41
+ ***Security On WordPress® MU Blog Farms:** This plugin is currently released as NOT having compatiblity with MU Blog Farms. This is because s2Member provides a configuration panel for protected file downloads, and also a programming API that makes PHP Constants and other routines available to advanced users. For these reasons, it is not a good idea to make s2Member available for use within a public Blog Farm. That being said, if you want to use the `wpmu.farm` file & tweak the code a little, you might be able to tune things in. -- If you're running the standard version of WordPress®, or you run WordPress® MU to host your own sites, you can safely ignore this warning.*
42
+
43
+ == Description ==
44
+
45
+ s2Member is a full-featured membership management system for WordPress®. It provides a very tight integration with PayPal® Subscriptions, and fully supports recurring billing with the ability to track affiliate commissions on a recurring basis. s2Member supports up to 4 different levels of membership with custom labels. It supports custom Pages for signup, account access, and many others. It also supports the ability to protect certain Pages, certain Posts, certain Categories/Tags, certain parts of content, and even includes advanced documentation on how to utilize the PHP runtime constants provided by the s2Member API. s2Member also supports protected file downloads with limitations on the how many files each user ( or each level ) can download in a given period of time.
46
+
47
+ - s2Member is also compatible with the BuddyPress plugin for WordPress®.
48
+
49
+ == Screenshots ==
50
+
51
+ 1. s2Member / Screenshot #1
52
+ 2. s2Member / Screenshot #2
53
+ 3. s2Member / Screenshot #3
54
+ 4. s2Member / Screenshot #4
55
+ 5. s2Member / Screenshot #5
56
+ 6. s2Member / Screenshot #6
57
+ 7. s2Member / Screenshot #7
58
+ 8. s2Member / Screenshot #8
59
+ 9. s2Member / Screenshot #9
60
+ 10. s2Member / Screenshot #10
61
+
62
+ == Frequently Asked Questions ==
63
+
64
+ = Does the PayPal integration work right-out-of-the-box? =
65
+ 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. Advanced scripting is not required however.
66
+
67
+ = How many membership levels are supported? =
68
+ s2Member supports up to 4 membership levels, and you can label those levels anything you like. The defaults are Bronze, Silver, Gold, Platinum.
69
+
70
+ = Does s2Member utilize the PayPal IPN system? =
71
+ Yes, s2Member supports automation of account activation, welcome emails, renewals, de-activation, refunds, etc.
72
+
73
+ = Does s2Member support PayPal Auto-Return w/Payment Data Transfer? =
74
+ 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 enter your Identity Token. If one is enabled, the other must also be enabled. There is a place to enter your PayPal® Identity Token for PDT under `s2Member -> PayPal® Options`. You'll also find some additional instructions there.
75
+
76
+ = Does s2Member install any new database tables? =
77
+ No, s2Member has been fully integrated with the Roles & Capabilities that are already built into WordPress®. It is designed to be completely seamless without code bloat.
78
+
79
+ = How does s2Member protect content from public access? =
80
+ s2Member allows you to protect Pages, Posts, and/or portions of content within Pages & Posts. It also allows you to protect downloadable files with special periodic restrictions on how many downloads can occur within a certain amount of time; on a per-user basis. All of this is configurable through the s2Member options panel. Each membership level can have different restrictions, and you could even integrate conditionals within your content based on the membership of the user. Examples are provided.
81
+
82
+ = Does s2Member provide an API that I can connect to? =
83
+ Yes, s2Member provides many *Advanced Scripting* techniques that are fully documented within its configuration and info pages. Example code is provided for everything. There are several functions that you can use, along with PHP Constants. This allows you to access many parts of its functionality, as well as specific user information. Theme designers are welcome to integrate their themes with s2Member using the code samples we provide.
84
+
85
+ = Is s2Member compatible with Quick Cache or WP Super Cache? =
86
+ Yes, there were some bugs in the beginning, but they have been fixed now. Both Quick Cache and WP Super Cache will remain compatible with s2Member. We have integrated two internal constants that prevent these plugins from caching important members only areas of your site, no matter what your cache configuration might be. The two Constants are: `DONOTCACHEPAGE` and `QUICK_CACHE_ALLOWED = false`. We recommend Quick Cache over WP Super Cache simply because we actually developed Quick Cache and we have done more extensive testing with the s2Member/Quick-Cache combination.
87
+
88
+ = Is s2Member compatible with the BuddyPress plugin for WordPress? =
89
+ 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.
90
+
91
+ = Do you take feature requests for future versions of s2Member? =
92
+ We welcome any and all [contributions](http://www.primothemes.com/donate/) so that s2Member may remain publicly available. If you contribute more than $200, your feature requests will be given high priority, and you will also receive 5 WordPress® themes ( of your choosing ) from PriMoThemes.com, along with a PriMoThemes.com T-shirt, and special credits in the next release of s2Member.
93
+
94
+ = Do you offer professional installation for s2Member? =
95
+ Yes, please contact [PriMoThemes.com](http://www.primothemes.com/contact/) for professional assistance.
96
+
97
+ = Is there a discussion forum for s2Member? =
98
+ Yes. In the form of comments on [this page](http://www.primothemes.com/post/s2member-membership-plugin-with-paypal/).
99
+
100
+ == Changelog ==
101
+
102
+ = 2.8.4 =
103
+ * A new option was added under `s2Member -> General Options -> De-Activation Safeguards`. This new option allows you to disable the de-activation routines for the s2Member plugin, so that s2Member Roles, Capabilities, and your Configuration Options will be preserved in case s2Member is de-activated inadvertently. We recommend that you Safeguard all s2Member data on your system; so please have a look at this new option.
104
+ * A bug was found in the Shortcode processor, related specifically to Buy Now buttons for Lifetime access. This bug has been corrected in s2Member v2.8.4.
105
+ * Stable tag updated in support of tagged releases within the repository at WordPress.org.
106
+
107
+ = 2.8.3 =
108
+ * A bug was found in the PayPal Button Generator, including the Shortcode processor. This has been resolved in v2.8.3. It was related to regex parsing. More specifically, it was related to Unix-style newlines vs. Windows-style newlines. For some site owners ( depending on how certain files were uploaded to their server ), this was resulting in an error at checkout that read "A1, P1, T1"; Invalid Trial. This bug has been corrected by modifying the regex parsing routines so that they're no longer dependent on multiline mode /m. The file `/button.html` has also been converted to Unix format to match the rest of the s2Member files.
109
+ * The action priority has been raised to (1) for `template_redirect` hooks inside `hooks.inc.php`. These hooks are reponsible for access control routines that protect Pages, Posts, Tags, Categories, and URIs. This increase in the action priority gives s2Member greater compatibility with BuddyPress and other plugins that attempt to use `template_redirect` as a hook into their application. A plugin such as s2Member should always be given top priority in this chain of events, because it is protecting content from public access.
110
+
111
+ = 2.8.2 =
112
+ * Bug fix. A bug was found &amp; resolved in the activation/de-activation routines for s2Member. This bug was first introduced in the initial release of s2Member v2.8.0, and has been resolved in this release ( v2.8.2 ). This bug was preventing the s2Member Roles from being created properly on some WordPress® installations.
113
+ * Dependency on the pluggable function `wp_new_user_notification()` has been dropped, making s2Member compatible with MailPress and other plugins that need `wp_new_user_notification()`. Some site owners were encountering conflicts specifically with MailPress. This issue has been resolved in s2Member v2.8.2. s2Member now uses a work-around that bypasses the need for `wp_new_user_notification()`.
114
+ * A new configuration option has been added to `s2Member -> General Options -> Login Welcome Page`. This new configuration option, makes it possible for you to redirect Members to a Special URL after logging in ( and not just to a WordPress® Page ). For example, you could now have Members redirected to their BuddyPress profile after logging in, or to ANY other URL for that matter.
115
+ * Default values for the Login Welcome Page &amp; Membership Options Page are now empty when s2Member is first installed. Site owners just getting started with s2Member will appreciate this, because this tends to be less confusing if you're configuring s2Member for the first time.
116
+
117
+ = 2.8.1 =
118
+ * The PayPal® Button Generator now provides built-in JavaScript validation; preventing invalid Trial subscription configurations that could potentially cause `A1, P1, T1 errors` at checkout.
119
+ * The new Shortcode Format for PayPal Buttons is now the default format. The more advanced version ( the full Button Code ) is still made available; but only for theme designers and plugin developers.
120
+ * The resulting PayPal Button Code is now W3C compliant under XHTML Strict mode.
121
+
122
+ = 2.8 =
123
+ * s2Member now supports Custom Fields, and ALSO *required* Custom Fields. If you would like to make specific fields *required* during registration, you can! See: `s2Member->General Options->Custom Registration Fields`.
124
+ * Your Custom Fields are now visible inside `WordPress® -> under Users`. With s2Member installed, you'll now have the ability to view &amp; manipulate Custom Fields from your WordPress® Dashboard. In previous versions of s2Member, this information could only be obtained through the s2Member API. Version 2.8 makes everything available inside the WordPress® UI now. We also have plans to build onto this functionality in the next release. A CSV export would be nice, and also a history of file downloads. These are coming soon. Waiting for additional contributors.
125
+ * The `S2MEMBER_CURRENT_USER_PROFILE_MODIFICATION_PAGE_URL` ( which is a PHP Constant included with the s2Member API ), has been updated to support *required* Custom Fields. It has also been updated to support IFRAME implementations. Documentation and code samples for IFRAME implementation are available under `s2Member->API Scripting->Constants`.
126
+ * Support for Content Dripping has been added in s2Member v2.8. Please see: `s2Member->API Scripting->Content Dripping`. Two new API Constants make this possible. These are `S2MEMBER_CURRENT_USER_REGISTRATION_DAYS` and `S2MEMBER_CURRENT_USER_REGISTRATION_TIME`. If you're dripping content, you should use `S2MEMBER_CURRENT_USER_REGISTRATION_DAYS`, it's easier.
127
+ * s2Member v2.8 includes support for Free Subscribers ( without going through PayPal® ). See: `s2Member->General Options->Login Welcome Page->Allow Free Subscribers`. You can now allow Users to register for FREE, and then upgrade them later using the instructions provided under `s2Member->Flow Of Events->Upgrading`.
128
+ * The PayPal® Button Generator has been improved significantly. It now supports MANY new options for Subscription Lengths. All the way up to 5 years &amp; also Lifetime Access.
129
+ * The PayPal® Button Generator now supports LIFETIME Subscriptions using `Buy It Now` buttons. Just choose `Lifetime` from the drop-down menu. This allows you to charge a Customer ONCE, and they'll never expire. It also makes the checkout experience more user-friendly, whenever your intention is to provide them lifetime access; as opposed to a specific number of days/weeks/months/years with recurring charges. s2Member now supports all of these methods.
130
+ * The PayPal® Button Generator now supports over 20 different international currencies.
131
+ * The PayPal® Button Generator now provides an alternative `Shortcode` method of insertion into Posts/Pages. If you were having problems associated with the Visual Editor for WordPress® ( i.e. raw code getting corrupted ), please use the new alternative format. This new format is made available after you click `Generate`. The Shortcode syntax is a more elegant solution than the Raw HTML plugin many of you were forced to use in previous versions of s2Member. The Alternative Shortcode syntax is every bit as powerful, without the headaches. The Shortcode syntax is also compatible with WordPress® MU filters.
132
+ * Under `s2Member->General Options->Login Customizations`, you can now use a wider Logo Image, which automatically forces the Login/Registration forms to become wider overall. This adds a nice touch whenever you're using lots of Custom Fields. Otherwise you'll end up with a tall/narrow stack of form fields that really does not look nice :-). Try using a Logo Image about 550px wide.
133
+ * Documentation updated throughout. Many files modified. Some minor changes in the menu structure and naming conventions. Stay tuned! Have fun, and make some money!
134
+ * Please thank [Jennifer Stuart](http://scriptygoddess.com/) for a generous donation that helped make s2Member v2.8 possible.
135
+ * Also thank Stree Overlord with LARGE Inc. for his generous contribution that helped make s2Member v2.8 possible.
136
+ * Also thank Martin B. for his donation too. You'll find him the Comment threads. Say thanks!
137
+ * For more info, feature requests, etc; Visit: http://www.primothemes.com/post/s2member-membership-plugin-with-paypal/
138
+
139
+ = 2.7.2 =
140
+ * WebSharks Framework for Plugins has been updated to P-2.1.
141
+ * The s2Member file download headers (`file-download-access.inc.php`) has been updated to support CGI/FastCGI implementations. s2Member has been tested with HostGator, BlueHost, (mt)MediaTemple (gs) and (dv), The Rackspace Cloud, and several dedicated servers running with Apache; including support for both `mod_php` and also `CGI/FastCGI` implementations. s2Member should work fine with any Apache/PHP combination. Please report all bugs to <primothemes@websharks-inc.com>.
142
+
143
+ = 2.7.1 =
144
+ * A bug in Custom Registration Fields has been corrected. This bug was introduced in v2.7, and has been corrected in v2.7.1. This bug was causing a mysterious [Empty Registration Field](http://www.primothemes.com/post/s2member-membership-plugin-with-paypal/comment-page-3/#comment-312) to appear on the form; when a new Customer registers their Username. Please thank [Jeffrey Nichols](http://jeffreyanichols.com/) for reporting this important issue.
145
+
146
+ = 2.7 =
147
+ * s2Member is now compatible with BuddyPress :-) And I must say... the s2Member/BuddyPress combination is just awesome. These two plugins running together make all sorts of things possible.
148
+ * A decision has been made to release this version, and future versions of s2Member as open source. We originally had plans to release this version privately as s2Member Pro. Instead, we've decided to keep future versions of s2Member licensed as GPL, and allow s2Member to be used freely by the entire WP community. We welcome any and all [contributions](http://www.primothemes.com/donate/) so that s2Member may remain publicly available. If you contribute more than `200.00`, your feature requests will be given high priority, and you will also receive 5 WordPress® themes ( of your choosing ) from PriMoThemes.com, along with a PriMoThemes.com T-shirt, and special credits in the next release of s2Member.
149
+ * All Option Panels have been given a makeover. The General Options Panel now includes a new section that provides you with the ability to collect and reference Custom Fields during user registration. The s2Member registration form now includes fields for First Name &amp; Last Name by default. These are the default, built-in Custom Fields.
150
+ * The Profile Modification Page ( `S2MEMBER_CURRENT_USER_PROFILE_MODIFICATION_PAGE_URL` ), has been updated to support the new Custom Fields added to the General Options.
151
+ * A new PHP Constant has been added to the s2Member API ( `S2MEMBER_CURRENT_USER_FIELDS` ). Documentation for this PHP Constant is available under `s2Member -> Advanced Scripting`. This provides programmatic access to all fields, including Custom Fields.
152
+ * The PayPal® Button Generator that is built into s2Member, now supports both recurring and NON-recurring charges with various membership subscription terms. s2Member has always supported ANY type of PayPal subscription, whether it be recurring or non-recurring. However, this update makes it possible for you to configure additional options using the Button Generator, instead of having to tweak the code it generates manually.
153
+ * There is a new section under `s2Member -> PayPal® Options` that provides you with several tools to help you customize the Signup Confirmation email Subject Line and Message Body templates.
154
+ * Support for Custom Payment Pages has been improved, along with further documentation built into the PayPal® Button Generator. Click the [?] icons for additional details about how to brand Custom Payment Pages for checkout.
155
+ * Under `s2Member -> General Options -> Login/Registration Design` we've added some easy-to-use buttons that open your Media Library ( then press Insert to save time ); this allows you to pull images out of your Media Library easily.
156
+ * Multiple files updated. The most significant changes were in: `/includes/hooks.inc.php, /includes/profile.inc.php, /functions/register-access.inc.php, /functions/profile-modifications.inc.php, /functions/constants.inc.php, /menu-pages/buttons.inc.php, /menu-pages/menu-pages.js`.
157
+ * Coming soon... in v2.8 we will be including some pre-built templates that will further assist you in creating your Membership Options Page and Login Welcome Page for s2Member. If you don't know any PHP at all, and you are totally confused by the s2Member API instructions, these pre-built templates will help kick start your experience with s2Member. Stay tuned for the latest. We also have plans to release WP themes that are pre-integrated with s2Member in creative ways.
158
+ * Please thank [Greg Eland](http://gregeland.com/) for a generous contribution that made s2Member v2.7 possible.
159
+
160
+ = 2.6 =
161
+ * The security-enabled directory that protects downloadable files, has been moved outside the main plugin folder, and into a new directory `wp-content/plugins/s2member-files`. If you're using a previous version of s2Member to protect files inside the old directory `wp-content/plugins/s2member/files/`, you will need to move them into the new directory.
162
+
163
+ s2Member will attempt to create this new directory for you automatically. However, if your `wp-content/plugins` directory is not writable, s2Member will fail silently, and you'll need to create that directory yourself. A warning will be displayed inside your WordPress® Dashboard, on the `Download Options` page if the security-enabled directory ( `s2member-files` ) is non-existent or unprotected. Instructions will be provided at that time about how to create this directory manually.
164
+
165
+ It should also be noted... any of your existing links that use the `?s2member_file_download` variable will remain unaffected by this change. You can leave those links the way they are, just move your files into the new directory and you're good.
166
+ * The `File Download Options` page has been cleaned up a bit, and some additional instruction has been added to this configuration page.
167
+ * Enhanced logging routines for PayPal® IPN connections and sub-routines. Added PayPal® Return logging routines. Both of these logs can be turned on/off under `PayPal® Options`.
168
+ * Added some additional instructions to the `PayPal® Options` page, detailing step-by-step how to enable PayPal® IPN reporting, and optional Auto-Return w/ Payment Data Transfer.
169
+
170
+ = 2.5 =
171
+ * Bug fixed in PayPal® IPN routine. This bug was related to alias email addresses being paid through PayPal®, but then the primary (business) email address being returned in the IPN response. This bug was affecting some users who have multiple email addresses associated with a single PayPal® account. If they decided to use a non-Primary address with s2Member, it was causing a conflict. The validation routines have been corrected so that this is no longer an issue. One of the symptoms of this bug, was a simple Thank-you message after checkout, and a redirect to the login screen instead of to the registration page. Bug resolved.
172
+ * Another minor bug was found in the IPN routine. The IPN routine was not utilizing the `Email From Name` set in the `s2Member General Options`. A cleaning routine was completely losing the name field on one particular sub-routine associated with subscription signups. This bug has also been corrected.
173
+ * Files modified: `/functions/paypal-return.inc.php`, `/functions/paypal-notify.inc.php`, `/functions/email-hacks.inc.php` renamed to `email-configs.inc.php`.
174
+
175
+ = 2.4 =
176
+ * Fixed a bug in the PayPal® IPN and Auto-Return routines where it was possible for a conflict to arise whenever a subscription modification from one of these two routines jumped ahead of the other. This bug would have only affected site owners that were using the advanced `on0` and `os0` variables to allow members to upgrade from one membership level to another. This advanced technique is described in greater detail on the `Flow Of Events` page under `s2Member Options`.
177
+ * Applied the use of `add_query_arg()` ( a native WordPress® function ) to redirection after a successful signup. Some site owners reported problems with the `?action=register` parameter not being passed through correctly. The `add_query_arg()` function handles the `?` vs. `&` appendages more reliably.
178
+ * Added a fallback to the PayPal® IPN sub-routine for email receipts. By default, s2Member uses tinyURL.com to compress the longer URL into an email-friendly format. This new fallback will revert to using the longer version when/if tinyURL.com becomes temporarily unavailable for some reason.
179
+
180
+ = 2.3 =
181
+ * Fixed a bug related to compatiblity with `WP Super Cache` and the more modern `Quick Cache` plugin. We recommend `Quick Cache` because there has been more extensive testing performed with `Quick Cache`. That being said, s2Member should work fine with either of them installed. s2Member is compatible with both of these plugins. s2Member will prevent protected areas of your site from being cached by these plugins. To maximize compatiblity, please make sure that you're using friendly Permalinks; which is recommended anyway if you're using a caching plugin of any kind.
182
+ * Renamed `api-constants.inc.php` to just `constants.inc.php`.
183
+ * Renamed `nocache-headers.inc.php` to just `nocache.inc.php`.
184
+ * Modified `hooks.inc.php` to reflect these changes.
185
+
186
+ = 2.2 =
187
+ * Further optimized API routines that provide access to PHP Constants. Reduced queries from five down to just one.
188
+ * Fixed Tag Level Access issue; related to tag/slug conversion in the `General Options Panel`. This was not really a bug, but it was confusing to people, because tags were being converted to slugs automatically. This still happens internally, but they are no longer auto-converted within the `General Options Panel` because it was too confusing to site owners. If you are/were protecting certain tags, those tags will continue to be protected. This change will have NO impact on existing installations of s2Member.
189
+
190
+ = 2.1 =
191
+ * Re-organized core framework. Updated to: P-2.0.
192
+ * Updated to support WP 2.9+.
193
+
194
+ = 2.0 =
195
+ * Two new options were added for login screen customization. s2Member now supports the ability to modify the shadow and text colors too.
196
+ * A new internal filter was added to suppress systematic use pages; such as the Login Welcome Page and Download Limit Exceeded Page from search results. These pages are always protected anyway, but s2Member now filters them from on-site search listings as well, just to prevent them from popping up and causing confusion.
197
+ * Added some additional inline documentation for the option panels.
198
+ * Replaced deprecated `split()` function with `preg_split()`.
199
+
200
+ = 1.9 =
201
+ * Minor bug fixed in JavaScript API. Some constants were empty ( non-zero ) when downloads were disabled.
202
+ * Added some additional API Constants for Page IDs. These are intended to supplement the existing Page URLs.
203
+
204
+ = 1.8 =
205
+ * I broke the options panel down into smaller sub-sections because things were getting too crowded all on one page.
206
+ * A new API has been added that provides extended notifications for affiliate program integration and other back-office routines.
207
+ * Support for refunds and reversals ( e.g. charge backs ) has been added to the IPN integration making it 100% seamless now!
208
+ * Pixel Tracking has been added to support AdSense / Yahoo / Google Analytics and other tracking codes & marketing campaigns.
209
+ * Additional documentation has been added along side or beneath each option; which helps to further clarify any confusion.
210
+
211
+ = 1.7 =
212
+ * JavaScript prompts for (Protected File Download Confirmation) are now issued by s2Member in an intuitive way. Check your options panel under File Download Restrictions for notes on this topic.
213
+ * Added a new PHP Constant: `S2MEMBER_CURRENT_USER_DOWNLOADS_ALLOWED_IS_UNLIMITED`. Check the Advanced Scripting page in your Dashboard for further details.
214
+ * In the options panel, support was added for category level restrictions, tag level restrictions, and URI level restrictions.
215
+ * All of the PHP runtime Constants for advanced scripting have been made available through a new JavaScript API as well.
216
+ * Bug fix: `s2member_file_download` counters were counting the same file more than once. This has been corrected.
217
+
218
+ = 1.6 =
219
+ * Upgraded to fully support WP 2.8.4. Slight tweaks. Nothing major.
220
+ * Added a `Flow Of Events` page that provides additional documentation & explanations.
221
+ * Added optional support for PayPal Auto-Return with PDT ( Payment Data Transfer ).
222
+
223
+ = 1.5 =
224
+ * You can now customize the Login / Registration Pages with your bg & logo.
225
+ * Added support for affiliate program tracking with optional custom fields.
226
+ * Added support for recurring commission processing for affiliates.
227
+
228
+ = 1.4 =
229
+ * Added file download limitations, restrictions and .htaccess protection.
230
+ * Corrected a bug with 404 errors on files that were not available.
231
+ * Added support / compatibility for WP Super Cache & Quick Cache.
232
+
233
+ = 1.3 =
234
+ * Added full support for PayPal IPN scripting automation.
235
+ * Added additional documentation & code samples for advanced scripting.
236
+ * Added `s2member_xencrypt()` & `s2member_xdecrypt()` functions to the API.
237
+
238
+ = 1.2 =
239
+ * Added more code samples w/ PHP Constants for advanced scripting.
240
+ * Added support for custom labels on different membership levels.
241
+ * You can now customize the From: `"Name" <address>` used in emails.
242
+
243
+ = 1.1 =
244
+ * Updated to a more seamless integration with WP Roles & Capabilities.
245
+ * Added ways to easily protect Pages, Posts and conditional content.
246
+ * Advanced scripting now makes `current_user_can()` available.
247
+
248
+ = 1.0 =
249
+ * Initial release.
s2member.php ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ Version: 2.8.4
13
+ Framework: P-2.1
14
+ Stable tag: 2.8.4
15
+
16
+ WordPress Compatible: yes
17
+ BuddyPress Compatible: yes
18
+ WordPress MU Compatible: yes
19
+ MU Blog Farm Compatible: soon
20
+
21
+ Tested up to: 2.9
22
+ Requires at least: 2.8.4
23
+ Requires: WordPress® 2.8.4+, PHP 5.2+
24
+
25
+ Copyright: © 2009 WebSharks, Inc.
26
+ License: GNU General Public License
27
+ Contributors: WebSharks, PriMoThemes
28
+ Author URI: http://www.primothemes.com/
29
+ Author: PriMoThemes.com / WebSharks, Inc.
30
+ Donate link: http://www.primothemes.com/donate/
31
+
32
+ ZipId: s2member
33
+ FolderId: s2member
34
+ Plugin Name: s2Member
35
+ Plugin URI: http://www.primothemes.com/post/s2member-membership-plugin-with-paypal/
36
+ Customization URI: http://www.primothemes.com/post/s2member-membership-plugin-with-paypal/#comments
37
+ Description: Empowers WordPress® with membership capabilities. Integrates seamlessly with PayPal®. Also compatible with the BuddyPress plugin for WP.
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, multi widget support, includes extensive documentation, highly extensible
39
+ */
40
+ /*
41
+ Direct access denial.
42
+ */
43
+ if (realpath (__FILE__) === realpath ($_SERVER["SCRIPT_FILENAME"]))
44
+ exit;
45
+ /*
46
+ Compatibility checks.
47
+ */
48
+ if (version_compare (PHP_VERSION, "5.2", ">=") && version_compare (get_bloginfo ("version"), "2.8.4", ">=") && !isset ($GLOBALS["WS_PLUGIN__"]["s2member"]) && function_exists ("curl_init"))
49
+ {
50
+ /*
51
+ Record the location of this file.
52
+ */
53
+ $GLOBALS["WS_PLUGIN__"]["s2member"]["l"] = __FILE__;
54
+ /*
55
+ Function includes.
56
+ */
57
+ include_once dirname (__FILE__) . "/includes/funcs.inc.php";
58
+ /*
59
+ Syscon includes.
60
+ */
61
+ include_once dirname (__FILE__) . "/includes/syscon.inc.php";
62
+ /*
63
+ Hook includes.
64
+ */
65
+ include_once dirname (__FILE__) . "/includes/hooks.inc.php";
66
+ }
67
+ /*
68
+ Else handle incompatibilities.
69
+ */
70
+ else if (is_admin () || ($_GET["preview"] && $_GET["template"]))
71
+ {
72
+ if (!version_compare (PHP_VERSION, "5.2", ">="))
73
+ {
74
+ register_shutdown_function (create_function ('', 'echo \'<script type="text/javascript">alert(\\\'You need PHP version 5.2 or higher to use the s2Member plugin.\\\');</script>\';'));
75
+ }
76
+ else if (!version_compare (get_bloginfo ("version"), "2.8.4", ">="))
77
+ {
78
+ register_shutdown_function (create_function ('', 'echo \'<script type="text/javascript">alert(\\\'You need WordPress® 2.8.4 or higher to use the s2Member plugin.\\\');</script>\';'));
79
+ }
80
+ else if (!function_exists ("curl_init"))
81
+ {
82
+ register_shutdown_function (create_function ('', 'echo \'<script type="text/javascript">alert(\\\'You need the CURL extension for PHP to use the s2Member plugin.\\\');</script>\';'));
83
+ }
84
+ }
85
+ ?>
screenshot-1.png ADDED
Binary file
screenshot-10.png ADDED
Binary file
screenshot-2.png ADDED
Binary file
screenshot-3.png ADDED
Binary file
screenshot-4.png ADDED
Binary file
screenshot-5.png ADDED
Binary file
screenshot-6.png ADDED
Binary file
screenshot-7.png ADDED
Binary file
screenshot-8.png ADDED
Binary file
screenshot-9.png ADDED
Binary file